00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00024 #include "realtimescheduler.h"
00025
00026 Register_PerRunConfigOption(CFGID_EXTERNALAPP_CONNECTION_LIMIT, "externalapp-connection-limit", CFG_INT, NULL, "TODO some documentation");
00027 Register_PerRunConfigOption(CFGID_EXTERNALAPP_APP_PORT, "externalapp-app-port", CFG_INT, NULL, "TODO some documentation");
00028
00029 inline std::ostream& operator<<(std::ostream& os, const timeval& tv)
00030 {
00031 return os << (unsigned long)tv.tv_sec << "s" << tv.tv_usec << "us";
00032 }
00033
00034 RealtimeScheduler::RealtimeScheduler() : cScheduler()
00035 {
00036 FD_ZERO(&all_fds);
00037 maxfd = 0;
00038 netw_fd = INVALID_SOCKET;
00039 additional_fd = INVALID_SOCKET;
00040 apptun_fd = INVALID_SOCKET;
00041 }
00042
00043 RealtimeScheduler::~RealtimeScheduler()
00044 { }
00045
00046 void RealtimeScheduler::startRun()
00047 {
00048 if (initsocketlibonce()!=0)
00049 throw cRuntimeError("RealtimeScheduler: Cannot initialize socket library");
00050
00051 gettimeofday(&baseTime, NULL);
00052
00053 appModule = NULL;
00054 appNotificationMsg = NULL;
00055 module = NULL;
00056 notificationMsg = NULL;
00057
00058 appConnectionLimit = ev.getConfig()->getAsInt(CFGID_EXTERNALAPP_CONNECTION_LIMIT, 0);
00059
00060 if (initializeNetwork()) {
00061 opp_error("realtimeScheduler error: initializeNetwork failed\n");
00062 }
00063 }
00064
00065 void RealtimeScheduler::endRun()
00066 {}
00067
00068 void RealtimeScheduler::executionResumed()
00069 {
00070 gettimeofday(&baseTime, NULL);
00071 baseTime = timeval_substract(baseTime, SIMTIME_DBL(simTime()));
00072 }
00073
00074 void RealtimeScheduler::setInterfaceModule(cModule *mod, cMessage *notifMsg,
00075 PacketBuffer* buffer, int mtu,
00076 bool isApp)
00077 {
00078 if (!mod || !notifMsg || !buffer) {
00079 throw cRuntimeError("RealtimeScheduler: setInterfaceModule(): "
00080 "arguments must be non-NULL");
00081 }
00082
00083 if (!isApp) {
00084 if (module) {
00085 throw cRuntimeError("RealtimeScheduler: setInterfaceModule() "
00086 "already called");
00087 }
00088 module = mod;
00089 notificationMsg = notifMsg;
00090 packetBuffer = buffer;
00091 buffersize = mtu;
00092 } else {
00093 if (appModule) {
00094 throw cRuntimeError("RealtimeScheduler: setInterfaceModule() "
00095 "already called");
00096 }
00097 appModule = mod;
00098 appNotificationMsg = notifMsg;
00099 appPacketBuffer = buffer;
00100 appBuffersize = mtu;
00101 }
00102 }
00103
00104 bool RealtimeScheduler::receiveWithTimeout(long usec)
00105 {
00106 bool newEvent = false;
00107
00108 fd_set readFD;
00109 readFD = all_fds;
00110
00111 timeval timeout;
00112 timeout.tv_sec = 0;
00113 timeout.tv_usec = usec;
00114
00115 if (select(FD_SETSIZE, &readFD, NULL, NULL, &timeout) > 0) {
00116
00117 for (SOCKET fd = 0; fd <= maxfd; fd++) {
00118 if (FD_ISSET(fd, &readFD)) {
00119
00120 if (fd == netw_fd) {
00121 char* buf = new char[buffersize];
00122 int nBytes;
00123
00124
00125
00126 sockaddr* from = (sockaddr*) new sockaddr_in;
00127 socklen_t addrlen = sizeof(sockaddr_in);
00128
00129
00130 getsockname(netw_fd, from, &addrlen);
00131 if ( from->sa_family != SOCK_DGRAM ) {
00132 delete from;
00133 from = 0;
00134 addrlen = 0;
00135
00136 nBytes = read(netw_fd, buf, buffersize);
00137 } else {
00138 addrlen = sizeof(sockaddr_in);
00139 nBytes = recvfrom(netw_fd, buf, buffersize, 0, from, &addrlen);
00140 }
00141
00142 if (nBytes < 0) {
00143 ev << "[RealtimeScheduler::receiveWithTimeout()]\n"
00144 << " Error reading from network: " << strerror(sock_errno())
00145 << endl;
00146 delete[] buf;
00147 buf = NULL;
00148 opp_error("Read from network device returned an error");
00149 } else if (nBytes == 0) {
00150 ev << "[RealtimeScheduler::receiveWithTimeout()]\n"
00151 << " Received 0 byte long UDP packet!" << endl;
00152 delete[] buf;
00153 buf = NULL;
00154 } else {
00155
00156 ev << "[RealtimeScheduler::receiveWithTimeout()]\n"
00157 << " Received " << nBytes << " bytes"
00158 << endl;
00159 packetBuffer->push_back(PacketBufferEntry(buf, nBytes, from, addrlen));
00160
00161 sendNotificationMsg(notificationMsg, module);
00162 newEvent = true;
00163 }
00164 } else if ( fd == apptun_fd ) {
00165
00166 char* buf = new char[appBuffersize];
00167
00168 int nBytes = read(fd, buf, appBuffersize);
00169
00170 if (nBytes < 0) {
00171 ev << "[RealtimeScheduler::receiveWithTimeout()]\n"
00172 << " Error reading from application TUN socket: "
00173 << strerror(sock_errno())
00174 << endl;
00175 delete[] buf;
00176 buf = NULL;
00177 opp_error("Read from application TUN socket returned "
00178 "an error");
00179 } else if (nBytes == 0) {
00180 ev << "[RealtimeScheduler::receiveWithTimeout()]\n"
00181 << " Received 0 byte long UDP packet!" << endl;
00182 delete[] buf;
00183 buf = NULL;
00184 } else {
00185
00186 ev << "[RealtimeScheduler::receiveWithTimeout()]\n"
00187 << " Received " << nBytes << " bytes"
00188 << endl;
00189
00190 appPacketBuffer->push_back(PacketBufferEntry(buf,
00191 nBytes, PacketBufferEntry::PACKET_APPTUN_DATA, fd));
00192
00193
00194 sendNotificationMsg(appNotificationMsg, appModule);
00195 newEvent = true;
00196 }
00197 } else if ( fd == additional_fd ) {
00198
00199 additionalFD();
00200 newEvent = true;
00201 } else {
00202
00203 char* buf = new char[appBuffersize];
00204 int nBytes = recv(fd, buf, appBuffersize, 0);
00205 if (nBytes < 0) {
00206 delete[] buf;
00207 buf = NULL;
00208 ev << "[RealtimeScheduler::receiveWithTimeout()]\n"
00209 << " Read error from application socket: "
00210 << strerror(sock_errno()) << endl;
00211 opp_error("Read from network device returned an error (App)");
00212 } else if (nBytes == 0) {
00213
00214 ev << "[RealtimeScheduler::receiveWithTimeout()]\n"
00215 << " Application closed socket"
00216 << endl;
00217 delete[] buf;
00218 buf = NULL;
00219 closeAppSocket(fd);
00220 newEvent = true;
00221 } else {
00222
00223 ev << "[RealtimeScheduler::receiveWithTimeout()]\n"
00224 << " Received " << nBytes << " bytes"
00225 << endl;
00226 appPacketBuffer->push_back(PacketBufferEntry(buf, nBytes, PacketBufferEntry::PACKET_DATA, fd));
00227
00228 sendNotificationMsg(appNotificationMsg, appModule);
00229 newEvent = true;
00230 }
00231 }
00232 }
00233 }
00234 }
00235 return newEvent;
00236 }
00237
00238 int RealtimeScheduler::receiveUntil(const timeval& targetTime)
00239 {
00240
00241
00242 timeval curTime;
00243 gettimeofday(&curTime, NULL);
00244 while (targetTime.tv_sec-curTime.tv_sec >=2 ||
00245 timeval_diff_usec(targetTime, curTime) >= 200000) {
00246 if (receiveWithTimeout(100000)) {
00247 if (ev.idle()) return -1;
00248 return 1;
00249 }
00250 if (ev.idle()) return -1;
00251 gettimeofday(&curTime, NULL);
00252 }
00253
00254
00255 long usec = timeval_diff_usec(targetTime, curTime);
00256 if (usec>0)
00257 if (receiveWithTimeout(usec)) {
00258 if (ev.idle()) return -1;
00259 return 1;
00260 }
00261 if (ev.idle()) return -1;
00262 return 0;
00263 }
00264
00265 cMessage *RealtimeScheduler::getNextEvent()
00266 {
00267
00268 if (!module)
00269 throw cRuntimeError("RealtimeScheduler: setInterfaceModule() not called: it must be called from a module's initialize() function");
00270
00271
00272
00273
00274
00275 timeval targetTime;
00276 cMessage *msg = sim->msgQueue.peekFirst();
00277 if (!msg) {
00278
00279
00280 targetTime.tv_sec = LONG_MAX;
00281 targetTime.tv_usec = 0;
00282 } else {
00283
00284 simtime_t eventSimtime = msg->getArrivalTime();
00285 targetTime = timeval_add(baseTime, SIMTIME_DBL(eventSimtime));
00286 }
00287
00288
00289 timeval curTime;
00290 gettimeofday(&curTime, NULL);
00291 if (timeval_greater(targetTime, curTime)) {
00292 int status = receiveUntil(targetTime);
00293 if (status == -1) {
00294 printf("WARNING: receiveUntil returned -1 (user interrupt)\n");
00295 return NULL;
00296 } else if (status == 1) {
00297 msg = sim->msgQueue.peekFirst();
00298 }
00299 } else {
00300
00301
00302
00303 }
00304
00305 return msg;
00306 }
00307
00308 void RealtimeScheduler::closeAppSocket(SOCKET fd)
00309 {
00310 #ifdef _WIN32
00311 closesocket(fd);
00312 #else
00313 close(fd);
00314 #endif
00315 FD_CLR(fd, &all_fds);
00316
00317 appPacketBuffer->push_back(PacketBufferEntry(0, 0, PacketBufferEntry::PACKET_FD_CLOSE, fd));
00318 sendNotificationMsg(appNotificationMsg, appModule);
00319 }
00320
00321 void RealtimeScheduler::sendNotificationMsg(cMessage* msg, cModule* mod)
00322 {
00323 if (msg->isScheduled()) return;
00324 timeval curTime;
00325 gettimeofday(&curTime, NULL);
00326 curTime = timeval_substract(curTime, baseTime);
00327 simtime_t t = curTime.tv_sec + curTime.tv_usec*1e-6;
00328
00329
00330
00331 if (t < simTime()) t = simTime();
00332
00333 msg->setSentFrom(mod, -1, simTime());
00334 msg->setArrival(mod,-1,t);
00335 simulation.msgQueue.insert(msg);
00336 }
00337
00338 ssize_t RealtimeScheduler::sendBytes(const char *buf,
00339 size_t numBytes,
00340 sockaddr* addr,
00341 socklen_t addrlen,
00342 bool isApp,
00343 SOCKET fd)
00344 {
00345 if (!buf) {
00346 ev << "[RealtimeScheduler::sendBytes()]\n"
00347 << " Error sending packet: buf = NULL"
00348 << endl;
00349 return -1;
00350 }
00351 if (!isApp) {
00352 if( numBytes > buffersize ) {
00353 ev << "[RealtimeScheduler::sendBytes()]\n"
00354 << " Trying to send oversized packet: size " << numBytes << " mtu " << buffersize
00355 << endl;
00356 opp_error("Can't send packet: too large");
00357 }
00358
00359 if ( netw_fd == INVALID_SOCKET ) {
00360 ev << "[RealtimeScheduler::sendBytes()]\n"
00361 << " Can't send packet to network: no tun/udp socket"
00362 << endl;
00363 return 0;
00364 }
00365 int nBytes;
00366 if (addr) {
00367 nBytes = sendto(netw_fd, buf, numBytes, 0, addr, addrlen);
00368 } else {
00369
00370 nBytes = write(netw_fd, buf, numBytes);
00371 }
00372 if (nBytes < 0) {
00373 ev << "[RealtimeScheduler::sendBytes()]\n"
00374 << " Error sending data to network: " << strerror(sock_errno()) << "\n"
00375 << " FD = " << netw_fd << ", numBytes = " << numBytes << ", addrlen = " << addrlen
00376 << endl;
00377 }
00378 return nBytes;
00379
00380 } else {
00381 if (numBytes > appBuffersize) {
00382 ev << "[RealtimeScheduler::sendBytes()]\n"
00383 << " Trying to send oversized packet: size " << numBytes << "\n"
00384 << " mtu " << appBuffersize
00385 << endl;
00386 opp_error("Can't send packet: too large");
00387 }
00388
00389 if (fd == INVALID_SOCKET) {
00390 for (fd = 0; fd <= maxfd; fd++) {
00391 if (fd == netw_fd) continue;
00392 if (fd == additional_fd) continue;
00393 if (FD_ISSET(fd, &all_fds)) break;
00394 }
00395 if (fd > maxfd) {
00396 throw cRuntimeError("Can't send packet to Application: no socket");
00397 }
00398 }
00399 if (fd == apptun_fd) {
00400
00401 return write(fd, buf, numBytes);
00402 } else {
00403 return send(fd, buf, numBytes, 0);
00404 }
00405 }
00406
00407 }
00408