#include "FEPSim.h" /** * Constructor. Sets data values for RPC Client and socket server. * * @param ATMSHost The IP of ATMS Server * @param FEP RPC program number * @param FEP RPC program revision number * @param Socket Server listen port */ FEPSim::FEPSim(char * ATMShost, int FEP_PROG, int FEP_REV, int SOCK_PORT) { this->ATMSHost = ATMShost; this->FEP_PROG = FEP_PROG; this->FEP_REV = FEP_REV; this->SOCK_PORT = SOCK_PORT; this->FEPLogFileName = "FEPSimLog.txt"; // clear log file FEPLogFile.open(FEPLogFileName, ios::trunc); FEPLogFile.close(); } /** * Destructor: closes the log file if open */ FEPSim::~FEPSim() { FEPLogFile.close(); } /** * Handler for the ATMS RPC Response (to the client RPC Call) * @param response pointer to fep_reply struct */ void FEPSim::handleCallResponse(void *response) { // Failed RPC Call if (response == NULL) { clnt_perror(clnt, "RPC call failed"); } // Successful RPC Call else { FEPLogFile << "Successful RPC call to ATMS..." << endl; } } /** * Sends an fep_reply for each station on the FEPLine. * Gets highway status from recieved socket msg. * * @param buffer The recieved highway status msg. */ void FEPSim::sendReplys(char * buffer) { HighwaysParser highwaysParser = HighwaysParser(buffer); vector lines = highwaysParser.lines; vector ldsMap = highwaysParser.stations; cout << "Starting sendReplys for " << lines.size() << " lines." << endl; // Send one reply for every FEPLine for (int i = 0; i < lines.size(); i++) { fep_reply fepReply; FEP_LINE * currLine = lines.at(i); // populate reply fepReply.reply = SHORTPOLL; fepReply.schedule = currLine->schedule; fepReply.lineinfo = currLine->lineInfo; fepReply.kind = (enum polltype) 0; fepReply.flag = (enum replykind) 0; fepReply.schedule_sequence = currLine->schedleSeq; fepReply.global_sequence = currLine->globalSeq; // using current unix time, may need to look at later fepReply.schedule_time = time(NULL); fepReply.user_info1 = currLine->lineNum; fepReply.user_info2 = currLine->lineNum; fepReply.system_key = currLine->systemKey; fepReply.answers.size = 1; fepReply.answers.fep_answer_list_u.shortp.count = 1; // construct a shortanswer for each station in line for (int j = 0; j < currLine->lds.size(); j++) { fep_shortanswer fsa; STATION * currStation = ldsMap.at(currLine->ldsIndex.at(j)); // msg: oa, od, currStation.dataPack, od, ff fsa.msg.message_len = currStation->length + 2; fsa.msg.message[0] = 0x0d; fsa.msg.message[1] = 0x0a; for (int k = 0; k < currStation->length; k++) { //printf("Adding: %d %02X\n", k, currStation->dataPack[k]); fsa.msg.message[2 + k] = currStation->dataPack[k]; } int aa = currStation->length; fsa.msg.message[2 + aa] = 0x0d; fsa.msg.message[3 + aa] = 0xff; /*for(int l = 0; l < fsa.msg.message_len + 2; l++) { printf("%02X", (unsigned char) fsa.msg.message[l]); } printf("\n");*/ // info fsa.info.poll_error_count = 0; fsa.info.poll_time = time(NULL); fsa.info.poll_user_info1 = currStation->drop; // drop number fsa.info.poll_user_info2 = 1; //always 1 fsa.info.retries = 0; fsa.info.status = (enum replystatus) 1; fepReply.answers.fep_answer_list_u.shortp.answers[0] = fsa; // send out data FEPLogFile << "Sending fepReply for line #" << currLine->lineNum << " station number #" << ldsMap.at(currLine->ldsIndex.at(j)) << endl; // Transfer the station data to ATMS and listen for response handleCallResponse(fep_reply_xfer_32(&fepReply, clnt)); } // pause to let ATMS server catch up //unsigned int sleepseconds = 220000; //usleep(sleepseconds); } cout << "Finished." << endl; } /** * Creates an RPC Client, and on successful creation, sends fep_replys to ATMS. * @param The recieved highway status msg. */ void FEPSim::manageClientConnection(char * buffer) { // Attempt to create RPC client if (createClient()) { // Prepare and send the highway status as FEP replies sendReplys(buffer); FEPLogFile << "Destroying client..." << endl; clnt_destroy(clnt); int startTime = time(NULL); FEPLogFile << "time is: " << startTime << endl; } } /** * Creates an RPC Client to the ATMS Server. If unsuccessful, returns false * @return bool success */ bool FEPSim::createClient() { /* Create RPC Client to communicate with ATMS */ bool success = true; clnt = clnt_create(this->ATMSHost, FEP_PROG, FEP_REV, "tcp"); /* Check if client creation failed */ if (clnt == (CLIENT *) NULL) { cerr << "Can't create client to " << this->ATMSHost << endl; cerr << "Verify you are connected to ATL network." << endl; success = false; } else { FEPLogFile << "Client created" << endl; } return success; } /** * Creates a socket server and awaits the highway status message from the * ATMS Driver. Upon receipt of the highway status message, creates an RPC * client and sends the fep_replys to the ATMS. */ void FEPSim::runSockServer() { int sockfd, newsockfd, portno, clilen; char buffer[BUFF_SIZE]; struct sockaddr_in serv_addr, cli_addr; int n; portno = this->SOCK_PORT; /* First call to socket() function */ sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { perror("ERROR opening socket"); exit(1); } /* Initialize socket structure */ bzero((char *) &serv_addr, sizeof (serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(portno); /* Now bind the host address using bind() call.*/ if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0) { perror("ERROR on binding"); exit(1); } /* Now start listening for the clients, here process will * go in sleep mode and will wait for the incoming connection */ listen(sockfd, 5); clilen = sizeof (cli_addr); /* Accept actual connections from the client */ while (1) { newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t *) & clilen); if (newsockfd < 0) { perror("ERROR on accept"); exit(1); } /* If connection is established then start communicating */ // zero out buffer bzero(buffer, BUFF_SIZE); // read XML from socket int totBytes = 0; while ((n = recv(newsockfd, &buffer[totBytes], sizeof (buffer), 0)) > 0) { totBytes += n; } if (n < 0) { perror("ERROR reading from socket"); exit(1); } // open log file FEPLogFile.open(FEPLogFileName, ios::app); // send data to atms manageClientConnection(buffer); // close log file FEPLogFile.close(); close(newsockfd); } }