| 1 | #include "FEPSim.h" |
|---|
| 2 | |
|---|
| 3 | /** |
|---|
| 4 | * Constructor. Sets data values for RPC Client and socket server. |
|---|
| 5 | * |
|---|
| 6 | * @param ATMSHost The IP of ATMS Server |
|---|
| 7 | * @param FEP RPC program number |
|---|
| 8 | * @param FEP RPC program revision number |
|---|
| 9 | * @param Socket Server listen port |
|---|
| 10 | */ |
|---|
| 11 | FEPSim::FEPSim(char * ATMShost, int FEP_PROG, int FEP_REV, int SOCK_PORT) { |
|---|
| 12 | this->ATMSHost = ATMShost; |
|---|
| 13 | this->FEP_PROG = FEP_PROG; |
|---|
| 14 | this->FEP_REV = FEP_REV; |
|---|
| 15 | this->SOCK_PORT = SOCK_PORT; |
|---|
| 16 | this->FEPLogFileName = "FEPSimLog.txt"; |
|---|
| 17 | // clear log file |
|---|
| 18 | FEPLogFile.open(FEPLogFileName, ios::trunc); |
|---|
| 19 | FEPLogFile.close(); |
|---|
| 20 | } |
|---|
| 21 | |
|---|
| 22 | /** |
|---|
| 23 | * Destructor: closes the log file if open |
|---|
| 24 | */ |
|---|
| 25 | FEPSim::~FEPSim() { |
|---|
| 26 | FEPLogFile.close(); |
|---|
| 27 | } |
|---|
| 28 | |
|---|
| 29 | /** |
|---|
| 30 | * Handler for the ATMS RPC Response (to the client RPC Call) |
|---|
| 31 | * @param response pointer to fep_reply struct |
|---|
| 32 | */ |
|---|
| 33 | void FEPSim::handleCallResponse(void *response) { |
|---|
| 34 | // Failed RPC Call |
|---|
| 35 | if (response == NULL) { |
|---|
| 36 | clnt_perror(clnt, "RPC call failed"); |
|---|
| 37 | } |
|---|
| 38 | // Successful RPC Call |
|---|
| 39 | else { |
|---|
| 40 | FEPLogFile << "Successful RPC call to ATMS..." << endl; |
|---|
| 41 | } |
|---|
| 42 | } |
|---|
| 43 | |
|---|
| 44 | /** |
|---|
| 45 | * Sends an fep_reply for each station on the FEPLine. |
|---|
| 46 | * Gets highway status from recieved socket msg. |
|---|
| 47 | * |
|---|
| 48 | * @param buffer The recieved highway status msg. |
|---|
| 49 | */ |
|---|
| 50 | void FEPSim::sendReplys(char * buffer) { |
|---|
| 51 | HighwaysParser highwaysParser = HighwaysParser(buffer); |
|---|
| 52 | vector<FEP_LINE*> lines = highwaysParser.lines; |
|---|
| 53 | vector<STATION*> ldsMap = highwaysParser.stations; |
|---|
| 54 | |
|---|
| 55 | cout << "Starting sendReplys for " << lines.size() << " lines." << endl; |
|---|
| 56 | // Send one reply for every FEPLine |
|---|
| 57 | for (int i = 0; i < lines.size(); i++) { |
|---|
| 58 | fep_reply fepReply; |
|---|
| 59 | FEP_LINE * currLine = lines.at(i); |
|---|
| 60 | // populate reply |
|---|
| 61 | fepReply.reply = SHORTPOLL; |
|---|
| 62 | fepReply.schedule = currLine->schedule; |
|---|
| 63 | fepReply.lineinfo = currLine->lineInfo; |
|---|
| 64 | fepReply.kind = (enum polltype) 0; |
|---|
| 65 | fepReply.flag = (enum replykind) 0; |
|---|
| 66 | |
|---|
| 67 | fepReply.schedule_sequence = currLine->schedleSeq; |
|---|
| 68 | fepReply.global_sequence = currLine->globalSeq; |
|---|
| 69 | |
|---|
| 70 | // using current unix time, may need to look at later |
|---|
| 71 | fepReply.schedule_time = time(NULL); |
|---|
| 72 | |
|---|
| 73 | fepReply.user_info1 = currLine->lineNum; |
|---|
| 74 | fepReply.user_info2 = currLine->lineNum; |
|---|
| 75 | fepReply.system_key = currLine->systemKey; |
|---|
| 76 | |
|---|
| 77 | fepReply.answers.size = 1; |
|---|
| 78 | fepReply.answers.fep_answer_list_u.shortp.count = 1; |
|---|
| 79 | |
|---|
| 80 | // construct a shortanswer for each station in line |
|---|
| 81 | for (int j = 0; j < currLine->lds.size(); j++) { |
|---|
| 82 | fep_shortanswer fsa; |
|---|
| 83 | STATION * currStation = ldsMap.at(currLine->ldsIndex.at(j)); |
|---|
| 84 | |
|---|
| 85 | // msg: oa, od, currStation.dataPack, od, ff |
|---|
| 86 | fsa.msg.message_len = currStation->length + 2; |
|---|
| 87 | fsa.msg.message[0] = 0x0d; |
|---|
| 88 | fsa.msg.message[1] = 0x0a; |
|---|
| 89 | for (int k = 0; k < currStation->length; k++) { |
|---|
| 90 | //printf("Adding: %d %02X\n", k, currStation->dataPack[k]); |
|---|
| 91 | fsa.msg.message[2 + k] = currStation->dataPack[k]; |
|---|
| 92 | } |
|---|
| 93 | int aa = currStation->length; |
|---|
| 94 | fsa.msg.message[2 + aa] = 0x0d; |
|---|
| 95 | fsa.msg.message[3 + aa] = 0xff; |
|---|
| 96 | |
|---|
| 97 | /*for(int l = 0; l < fsa.msg.message_len + 2; l++) |
|---|
| 98 | { |
|---|
| 99 | printf("%02X", (unsigned char) fsa.msg.message[l]); |
|---|
| 100 | } |
|---|
| 101 | printf("\n");*/ |
|---|
| 102 | |
|---|
| 103 | // info |
|---|
| 104 | fsa.info.poll_error_count = 0; |
|---|
| 105 | fsa.info.poll_time = time(NULL); |
|---|
| 106 | fsa.info.poll_user_info1 = currStation->drop; // drop number |
|---|
| 107 | fsa.info.poll_user_info2 = 1; //always 1 |
|---|
| 108 | fsa.info.retries = 0; |
|---|
| 109 | fsa.info.status = (enum replystatus) 1; |
|---|
| 110 | |
|---|
| 111 | fepReply.answers.fep_answer_list_u.shortp.answers[0] = fsa; |
|---|
| 112 | // send out data |
|---|
| 113 | |
|---|
| 114 | FEPLogFile << "Sending fepReply for line #" << currLine->lineNum |
|---|
| 115 | << " station number #" |
|---|
| 116 | << ldsMap.at(currLine->ldsIndex.at(j)) << endl; |
|---|
| 117 | |
|---|
| 118 | // Transfer the station data to ATMS and listen for response |
|---|
| 119 | handleCallResponse(fep_reply_xfer_32(&fepReply, clnt)); |
|---|
| 120 | } |
|---|
| 121 | // pause to let ATMS server catch up |
|---|
| 122 | //unsigned int sleepseconds = 220000; |
|---|
| 123 | //usleep(sleepseconds); |
|---|
| 124 | } |
|---|
| 125 | cout << "Finished." << endl; |
|---|
| 126 | } |
|---|
| 127 | |
|---|
| 128 | /** |
|---|
| 129 | * Creates an RPC Client, and on successful creation, sends fep_replys to ATMS. |
|---|
| 130 | * @param The recieved highway status msg. |
|---|
| 131 | */ |
|---|
| 132 | void FEPSim::manageClientConnection(char * buffer) |
|---|
| 133 | { |
|---|
| 134 | // Attempt to create RPC client |
|---|
| 135 | if (createClient()) |
|---|
| 136 | { |
|---|
| 137 | // Prepare and send the highway status as FEP replies |
|---|
| 138 | sendReplys(buffer); |
|---|
| 139 | FEPLogFile << "Destroying client..." << endl; |
|---|
| 140 | clnt_destroy(clnt); |
|---|
| 141 | int startTime = time(NULL); |
|---|
| 142 | FEPLogFile << "time is: " << startTime << endl; |
|---|
| 143 | } |
|---|
| 144 | } |
|---|
| 145 | |
|---|
| 146 | /** |
|---|
| 147 | * Creates an RPC Client to the ATMS Server. If unsuccessful, returns false |
|---|
| 148 | * @return bool success |
|---|
| 149 | */ |
|---|
| 150 | bool FEPSim::createClient() { |
|---|
| 151 | /* Create RPC Client to communicate with ATMS */ |
|---|
| 152 | bool success = true; |
|---|
| 153 | |
|---|
| 154 | clnt = clnt_create(this->ATMSHost, FEP_PROG, FEP_REV, "tcp"); |
|---|
| 155 | /* Check if client creation failed */ |
|---|
| 156 | if (clnt == (CLIENT *) NULL) { |
|---|
| 157 | cerr << "Can't create client to " << this->ATMSHost << endl; |
|---|
| 158 | cerr << "Verify you are connected to ATL network." << endl; |
|---|
| 159 | success = false; |
|---|
| 160 | } else { |
|---|
| 161 | FEPLogFile << "Client created" << endl; |
|---|
| 162 | } |
|---|
| 163 | return success; |
|---|
| 164 | } |
|---|
| 165 | |
|---|
| 166 | /** |
|---|
| 167 | * Creates a socket server and awaits the highway status message from the |
|---|
| 168 | * ATMS Driver. Upon receipt of the highway status message, creates an RPC |
|---|
| 169 | * client and sends the fep_replys to the ATMS. |
|---|
| 170 | */ |
|---|
| 171 | void FEPSim::runSockServer() { |
|---|
| 172 | int sockfd, newsockfd, portno, clilen; |
|---|
| 173 | char buffer[BUFF_SIZE]; |
|---|
| 174 | struct sockaddr_in serv_addr, cli_addr; |
|---|
| 175 | int n; |
|---|
| 176 | portno = this->SOCK_PORT; |
|---|
| 177 | |
|---|
| 178 | /* First call to socket() function */ |
|---|
| 179 | sockfd = socket(AF_INET, SOCK_STREAM, 0); |
|---|
| 180 | |
|---|
| 181 | if (sockfd < 0) { |
|---|
| 182 | perror("ERROR opening socket"); |
|---|
| 183 | exit(1); |
|---|
| 184 | } |
|---|
| 185 | |
|---|
| 186 | /* Initialize socket structure */ |
|---|
| 187 | bzero((char *) &serv_addr, sizeof (serv_addr)); |
|---|
| 188 | |
|---|
| 189 | serv_addr.sin_family = AF_INET; |
|---|
| 190 | serv_addr.sin_addr.s_addr = INADDR_ANY; |
|---|
| 191 | serv_addr.sin_port = htons(portno); |
|---|
| 192 | |
|---|
| 193 | /* Now bind the host address using bind() call.*/ |
|---|
| 194 | if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0) { |
|---|
| 195 | perror("ERROR on binding"); |
|---|
| 196 | exit(1); |
|---|
| 197 | } |
|---|
| 198 | |
|---|
| 199 | /* Now start listening for the clients, here process will |
|---|
| 200 | * go in sleep mode and will wait for the incoming connection |
|---|
| 201 | */ |
|---|
| 202 | |
|---|
| 203 | listen(sockfd, 5); |
|---|
| 204 | clilen = sizeof (cli_addr); |
|---|
| 205 | |
|---|
| 206 | /* Accept actual connections from the client */ |
|---|
| 207 | while (1) { |
|---|
| 208 | newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t *) & clilen); |
|---|
| 209 | |
|---|
| 210 | if (newsockfd < 0) { |
|---|
| 211 | perror("ERROR on accept"); |
|---|
| 212 | exit(1); |
|---|
| 213 | } |
|---|
| 214 | |
|---|
| 215 | /* If connection is established then start communicating */ |
|---|
| 216 | // zero out buffer |
|---|
| 217 | bzero(buffer, BUFF_SIZE); |
|---|
| 218 | |
|---|
| 219 | // read XML from socket |
|---|
| 220 | int totBytes = 0; |
|---|
| 221 | while ((n = recv(newsockfd, &buffer[totBytes], sizeof (buffer), 0)) > 0) { |
|---|
| 222 | totBytes += n; |
|---|
| 223 | } |
|---|
| 224 | |
|---|
| 225 | if (n < 0) { |
|---|
| 226 | perror("ERROR reading from socket"); |
|---|
| 227 | exit(1); |
|---|
| 228 | } |
|---|
| 229 | // open log file |
|---|
| 230 | FEPLogFile.open(FEPLogFileName, ios::app); |
|---|
| 231 | // send data to atms |
|---|
| 232 | manageClientConnection(buffer); |
|---|
| 233 | // close log file |
|---|
| 234 | FEPLogFile.close(); |
|---|
| 235 | close(newsockfd); |
|---|
| 236 | } |
|---|
| 237 | } |
|---|