00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <netdb.h>
00012 #include "cUDPSocketRTScheduler.h"
00013
00014 Register_Class(cUDPSocketRTScheduler);
00015 Register_GlobalConfigOption(CFGID_UDPSOCKETRTSCHEDULER_PORT, "udpsocketrtscheduler-port", CFG_INT, "2424", "When cUDPSocketRTScheduler is selected as scheduler class: the port number cUDPSocketRTScheduler listens on.");
00016
00020 cUDPSocketRTScheduler::cUDPSocketRTScheduler() : cScheduler()
00021 {
00022 listenerSocket = INVALID_SOCKET;
00023 connSocket = INVALID_SOCKET;
00024 }
00025
00029 cUDPSocketRTScheduler::~cUDPSocketRTScheduler()
00030 {
00031 }
00032
00036 void
00037 cUDPSocketRTScheduler::startRun()
00038 {
00039 if (initsocketlibonce()!=0)
00040 throw new cRuntimeError("cUDPSocketRTScheduler: Cannot initialize socket library");
00041
00042 gettimeofday(&baseTime, NULL);
00043
00044 module = NULL;
00045 notificationMsg = NULL;
00046 recvBuffer = NULL;
00047 recvBufferSize = 0;
00048 numBytesPtr = NULL;
00049
00050 port = ev.getConfig()->getAsInt(CFGID_UDPSOCKETRTSCHEDULER_PORT);
00051 setupListener();
00052 }
00053
00057 void
00058 cUDPSocketRTScheduler::endRun()
00059 {
00060 }
00061
00065 void
00066 cUDPSocketRTScheduler::setupListener()
00067 {
00068 struct addrinfo request;
00069 struct addrinfo *result;
00070
00071 memset(&request, 0, sizeof(struct addrinfo));
00072 request.ai_family = AF_UNSPEC;
00073 request.ai_socktype = SOCK_DGRAM;
00074 request.ai_flags = AI_PASSIVE;
00075 request.ai_protocol = 0;
00076 request.ai_canonname = NULL;
00077 request.ai_addr = NULL;
00078 request.ai_next = NULL;
00079
00080 char cport[5];
00081 sprintf(cport, "%i", port);
00082
00083 if (getaddrinfo(NULL, cport, &request, &result) < 0)
00084 throw new cRuntimeError("cUDPSocketRTScheduler: getaddrinfo");
00085
00086 listenerSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
00087 if (listenerSocket == INVALID_SOCKET)
00088 throw new cRuntimeError("cUDPSocketRTScheduler: cannot create socket");
00089
00090 if (bind(listenerSocket, result->ai_addr, result->ai_addrlen) == SOCKET_ERROR)
00091 throw new cRuntimeError("cUDPSocketRTScheduler: socket bind() failed");
00092 }
00093
00098 void
00099 cUDPSocketRTScheduler::executionResumed()
00100 {
00101 gettimeofday(&baseTime, NULL);
00102 baseTime = timeval_substract(baseTime, sim->getSimTime().dbl());
00103 }
00104
00105 void
00106 cUDPSocketRTScheduler::setInterfaceModule(cModule *mod, cMessage *notifMsg, \
00107 char *buf, int bufSize, int *nBytesPtr)
00108 {
00109 if (module)
00110 throw new cRuntimeError("cUDPSocketRTScheduler: setInterfaceModule() already called");
00111 if (!mod || !notifMsg || !buf || !bufSize || !nBytesPtr)
00112 throw new cRuntimeError("cUDPSocketRTScheduler: setInterfaceModule(): arguments must be non-NULL");
00113
00114 module = mod;
00115 notificationMsg = notifMsg;
00116 recvBuffer = buf;
00117 recvBufferSize = bufSize;
00118 numBytesPtr = nBytesPtr;
00119 *numBytesPtr = 0;
00120 }
00121
00125 bool cUDPSocketRTScheduler::receiveWithTimeout(long usec)
00126 {
00127
00128 fd_set readFDs, writeFDs, exceptFDs;
00129 FD_ZERO(&readFDs);
00130 FD_ZERO(&writeFDs);
00131 FD_ZERO(&exceptFDs);
00132
00133 FD_SET(listenerSocket, &readFDs);
00134
00135 timeval timeout;
00136 timeout.tv_sec = 0;
00137 timeout.tv_usec = usec;
00138
00139 if (select(FD_SETSIZE, &readFDs, &writeFDs, &exceptFDs, &timeout) > 0)
00140 {
00141 if (listenerSocket != INVALID_SOCKET && FD_ISSET(listenerSocket, &readFDs))
00142 {
00143
00144 sockaddr_in sinRemote;
00145 int addrSize = sizeof(sinRemote);
00146 char *bufPtr = recvBuffer + (*numBytesPtr);
00147 int bufLeft = recvBufferSize - (*numBytesPtr);
00148 if (bufLeft <= 0)
00149 throw new cRuntimeError("cUDPSocketRTScheduler: interface module's recvBuffer is full");
00150 int nBytes = recvfrom(listenerSocket, bufPtr, bufLeft, 0, \
00151 (sockaddr*) &sinRemote, (socklen_t*) &addrSize);
00152 if (nBytes == SOCKET_ERROR)
00153 {
00154 ev << "cUDPSocketRTScheduler: error receiving socket" << sock_errno() << "\n";
00155 connSocket = INVALID_SOCKET;
00156 } else {
00157
00158 ev << "cUDPSocketRTScheduler: " << nBytes << " bytes received\n";
00159 (*numBytesPtr) += nBytes;
00160
00161 notificationMsg->setName("rtmsg");
00162
00163 timeval curTime;
00164 gettimeofday(&curTime, NULL);
00165 curTime = timeval_substract(curTime, baseTime);
00166 simtime_t t = curTime.tv_sec + curTime.tv_usec * 1e-6;
00167
00168 notificationMsg->setArrival(module,-1,t);
00169 notificationMsg->setTimestamp(t);
00170
00171 simulation.msgQueue.insert(notificationMsg);
00172 return true;
00173 }
00174 }
00175 }
00176 return false;
00177 }
00178
00179 int
00180 cUDPSocketRTScheduler::receiveUntil(const timeval& targetTime)
00181 {
00182
00183
00184 timeval curTime;
00185 gettimeofday(&curTime, NULL);
00186 while (targetTime.tv_sec-curTime.tv_sec >=2 ||
00187 timeval_diff_usec(targetTime, curTime) >= 200000)
00188 {
00189 if (receiveWithTimeout(100000))
00190 return 1;
00191 if (ev.idle())
00192 return -1;
00193 gettimeofday(&curTime, NULL);
00194 }
00195
00196
00197 long usec = timeval_diff_usec(targetTime, curTime);
00198 if (usec>0)
00199 if (receiveWithTimeout(usec))
00200 return 1;
00201 return 0;
00202 }
00203
00210 cMessage *cUDPSocketRTScheduler::getNextEvent()
00211 {
00212 ev << "Processing next event\n";
00213
00214
00215 if (!module)
00216 throw new cRuntimeError("cUDPSocketRTScheduler: setInterfaceModule() \
00217 not called: it must be called from a module's initialize() function");
00218
00219
00220 timeval targetTime;
00221 cMessage *msg = sim->msgQueue.peekFirst();
00222 if (!msg)
00223 {
00224
00225
00226 targetTime.tv_sec = LONG_MAX;
00227 targetTime.tv_usec = 0;
00228 }
00229 else
00230 {
00231
00232 simtime_t eventSimtime = msg->getArrivalTime();
00233 targetTime = timeval_add(baseTime, eventSimtime.dbl());
00234 }
00235
00236
00237 timeval curTime;
00238 gettimeofday(&curTime, NULL);
00239 if (timeval_greater(targetTime, curTime))
00240 {
00241 int status = receiveUntil(targetTime);
00242 if (status == -1)
00243 return NULL;
00244 if (status == 1)
00245 msg = sim->msgQueue.peekFirst();
00246 }
00247 else
00248 {
00249
00250
00251 }
00252
00253
00254 return msg;
00255 }
00256
00257 int
00258 cUDPSocketRTScheduler::sendMessage(const char *msg,
00259 const size_t numBytes,
00260 const struct sockaddr *nodeAddr,
00261 const socklen_t addrSize)
00262 {
00263 int bytesSent = sendto(listenerSocket, msg, numBytes, 0, nodeAddr, addrSize);
00264 ev << "cUDPSocketRTScheduler: " << bytesSent << " bytes sent to ";
00265
00266 if (bytesSent <= 0)
00267 {
00268 ev << "(" << strerror(errno) << ")\n";
00269 return SOCKET_ERROR;
00270 } else {
00271 ev << "\n";
00272 return 0;
00273 }
00274 }