#include <cSocketRTScheduler.h>
Public Member Functions | |
cSocketRTScheduler () | |
virtual | ~cSocketRTScheduler () |
virtual void | startRun () |
virtual void | endRun () |
virtual void | executionResumed () |
void | setInterfaceModule (cModule *mod, const char *dev, const char *filter) |
virtual cMessage * | getNextEvent () |
void | sendBytes (unsigned char *buf, size_t numBytes, struct sockaddr *from, socklen_t addrlen) |
Static Public Attributes | |
static std::vector< cModule * > | modules |
static std::vector< pcap_t * > | pds |
static std::vector< int > | datalinks |
static std::vector< int > | headerLengths |
static timeval | baseTime |
Protected Member Functions | |
virtual bool | receiveWithTimeout () |
virtual int | receiveUntil (const timeval &targetTime) |
Protected Attributes | |
int | fd |
cSocketRTScheduler::cSocketRTScheduler | ( | ) |
bool cSocketRTScheduler::receiveWithTimeout | ( | ) | [protected, virtual] |
Referenced by receiveUntil().
00194 { 00195 bool found; 00196 struct timeval timeout; 00197 int32 n; 00198 #ifdef LINUX 00199 int32 fd[FD_SETSIZE], maxfd; 00200 fd_set rdfds; 00201 #endif 00202 00203 found = false; 00204 timeout.tv_sec = 0; 00205 timeout.tv_usec = PCAP_TIMEOUT * 1000; 00206 #ifdef LINUX 00207 FD_ZERO(&rdfds); 00208 maxfd = -1; 00209 for (uint16 i = 0; i < pds.size(); i++) 00210 { 00211 fd[i] = pcap_get_selectable_fd(pds.at(i)); 00212 if (fd[i] > maxfd) 00213 maxfd = fd[i]; 00214 FD_SET(fd[i], &rdfds); 00215 } 00216 select(maxfd + 1, &rdfds, NULL, NULL, &timeout); 00217 #endif 00218 for (uint16 i = 0; i < pds.size(); i++) 00219 { 00220 #ifdef LINUX 00221 if (!(FD_ISSET(fd[i], &rdfds))) 00222 continue; 00223 #endif 00224 //std::cout << "Looking at pd[" << i << "] = "<< pds.at(i) << ".\n"; 00225 if ((n = pcap_dispatch(pds.at(i), 1, packet_handler, (uint8 *)&i)) < 0) 00226 throw new cRuntimeError("cSocketRTScheduler::pcap_dispatch(): An error occired: %s", pcap_geterr(pds.at(i))); 00227 if (n > 0) 00228 found = true; 00229 } 00230 #ifndef LINUX 00231 if (!found) 00232 select(0, NULL, NULL, NULL, &timeout); 00233 #endif 00234 return found; 00235 }
int32 cSocketRTScheduler::receiveUntil | ( | const timeval & | targetTime | ) | [protected, virtual] |
Referenced by getNextEvent().
00238 { 00239 // wait until targetTime or a bit longer, wait in PCAP_TIMEOUT chunks 00240 // in order to keep UI responsiveness by invoking ev.idle() 00241 timeval curTime; 00242 gettimeofday(&curTime, NULL); 00243 while (timeval_greater(targetTime, curTime)) 00244 { 00245 if (receiveWithTimeout()) 00246 return 1; 00247 if (ev.idle()) 00248 return -1; 00249 gettimeofday(&curTime, NULL); 00250 } 00251 return 0; 00252 }
void cSocketRTScheduler::startRun | ( | ) | [virtual] |
Called at the beginning of a simulation run.
00057 { 00058 const int32 on = 1; 00059 00060 gettimeofday(&baseTime, NULL); 00061 00062 fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); 00063 if(fd == INVALID_SOCKET) 00064 throw new cRuntimeError("cSocketRTScheduler: Root priviledges needed"); 00065 if(setsockopt(fd, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on)) < 0) 00066 throw new cRuntimeError("cSocketRTScheduler: couldn't set sockopt for raw socket"); 00067 }
void cSocketRTScheduler::endRun | ( | ) | [virtual] |
Called at the end of a simulation run.
00071 { 00072 //pcap_stat ps; 00073 00074 close(fd); 00075 fd = INVALID_SOCKET; 00076 /*std::cout<<"pds.size="<<pds.size()<<"\n"; 00077 for (uint16 i=0; i<pds.size(); i++) //I.R. Call of pcap_stats leads to SegFault when calling Rebuild Network 00078 { 00079 if (pcap_stats(pds.at(i), &ps) < 0) 00080 throw new cRuntimeError("cSocketRTScheduler::endRun(): Can not get pcap statistics: %s", pcap_geterr(pds.at(i))); 00081 else 00082 EV << modules.at(i)->name() << ": Received Packets: " << ps.ps_recv << " Dropped Packets: " << ps.ps_drop << ".\n"; 00083 pcap_close(pds.at(i)); 00084 }*/ 00085 }
void cSocketRTScheduler::executionResumed | ( | ) | [virtual] |
void cSocketRTScheduler::setInterfaceModule | ( | cModule * | mod, | |
const char * | dev, | |||
const char * | filter | |||
) |
To be called from the module which wishes to receive data from the socket. The method must be called from the module's initialize() function.
Referenced by ExtInterface::initialize().
00094 { 00095 char errbuf[PCAP_ERRBUF_SIZE]; 00096 struct bpf_program fcode; 00097 pcap_t * pd; 00098 int32 datalink; 00099 int32 headerLength; 00100 00101 /*if (module) 00102 throw new cRuntimeError("cSocketRTScheduler::setInterfaceModule() already called");*/ 00103 if (!mod || !dev || !filter) 00104 throw new cRuntimeError("cSocketRTScheduler::setInterfaceModule(): arguments must be non-NULL"); 00105 00106 /* get pcap handle */ 00107 memset(&errbuf, 0, sizeof(errbuf)); 00108 if ((pd = pcap_open_live(dev, PCAP_SNAPLEN, 0, PCAP_TIMEOUT, errbuf)) == NULL) 00109 throw new cRuntimeError("cSocketRTScheduler::setInterfaceModule(): Can not open pcap device, error = %s", errbuf); 00110 else if(strlen(errbuf) > 0) 00111 EV << "cSocketRTScheduler::setInterfaceModule: pcap_open_live returned waring: " << errbuf << "\n"; 00112 00113 /* compile this command into a filter program */ 00114 if (pcap_compile(pd, &fcode, (char *)filter, 0, 0) < 0) 00115 throw new cRuntimeError("cSocketRTScheduler::setInterfaceModule(): Can not compile filter: %s", pcap_geterr(pd)); 00116 00117 /* apply the compiled filter to the packet capture device */ 00118 if (pcap_setfilter(pd, &fcode) < 0) 00119 throw new cRuntimeError("cSocketRTScheduler::setInterfaceModule(): Can not apply compiled filter: %s", pcap_geterr(pd)); 00120 00121 if ((datalink = pcap_datalink(pd)) < 0) 00122 throw new cRuntimeError("cSocketRTScheduler::setInterfaceModule(): Can not get datalink: %s", pcap_geterr(pd)); 00123 00124 /* FIXME MT: Will we do this also for Linux? */ 00125 if (pcap_setnonblock(pd, 1, errbuf) < 0) 00126 throw new cRuntimeError("cSocketRTScheduler::pcap_setnonblock(): Can not put pcap device into non-blocking mode, error = %s", errbuf); 00127 00128 switch (datalink) { 00129 case DLT_NULL: 00130 headerLength = 4; 00131 break; 00132 case DLT_EN10MB: 00133 headerLength = 14; 00134 break; 00135 case DLT_SLIP: 00136 headerLength = 24; 00137 break; 00138 case DLT_PPP: 00139 headerLength = 24; 00140 break; 00141 default: 00142 throw new cRuntimeError("cSocketRTScheduler::setInterfaceModule(): Unsupported datalink: %d", datalink); 00143 } 00144 modules.push_back(mod); 00145 pds.push_back(pd); 00146 datalinks.push_back(datalink); 00147 headerLengths.push_back(headerLength); 00148 00149 EV << "Opened pcap device " << dev << " with filter " << filter << " and datalink " << datalink << ".\n"; 00150 }
cMessage * cSocketRTScheduler::getNextEvent | ( | ) | [virtual] |
Scheduler function -- it comes from cScheduler interface.
00255 { 00256 timeval targetTime, curTime, diffTime; 00257 00258 /* 00259 if (!module) 00260 throw new cRuntimeError("cSocketRTScheduler::::getNextEvent: setInterfaceModule() not called: it must be called from a module's initialize() function"); 00261 */ 00262 // calculate target time 00263 cMessage *msg = sim->msgQueue.peekFirst(); 00264 if (!msg) 00265 { 00266 targetTime.tv_sec = LONG_MAX; 00267 targetTime.tv_usec = 0; 00268 } 00269 else 00270 { 00271 simtime_t eventSimtime = msg->getArrivalTime(); 00272 targetTime = timeval_add(baseTime, eventSimtime.dbl()); 00273 } 00274 00275 gettimeofday(&curTime, NULL); 00276 if (timeval_greater(targetTime, curTime)) 00277 { 00278 int32 status = receiveUntil(targetTime); 00279 if (status == -1) 00280 return NULL; // interrupted by user 00281 if (status == 1) 00282 msg = sim->msgQueue.peekFirst(); // received something 00283 } 00284 else 00285 { 00286 // we're behind -- customized versions of this class may 00287 // alert if we're too much behind, whatever that means 00288 diffTime = timeval_substract(curTime, targetTime); 00289 EV << "We are behind: " << diffTime.tv_sec + diffTime.tv_usec * 1e-6 << " seconds\n"; 00290 } 00291 return msg; 00292 }
void cSocketRTScheduler::sendBytes | ( | unsigned char * | buf, | |
size_t | numBytes, | |||
struct sockaddr * | from, | |||
socklen_t | addrlen | |||
) |
Send on the currently open connection
Referenced by ExtInterface::handleMessage().
int cSocketRTScheduler::fd [protected] |
Referenced by cSocketRTScheduler(), endRun(), receiveWithTimeout(), and startRun().
std::vector< cModule * > cSocketRTScheduler::modules [static] |
Referenced by setInterfaceModule().
std::vector< pcap_t * > cSocketRTScheduler::pds [static] |
Referenced by receiveWithTimeout(), and setInterfaceModule().
std::vector< int32 > cSocketRTScheduler::datalinks [static] |
Referenced by setInterfaceModule().
std::vector< int32 > cSocketRTScheduler::headerLengths [static] |
Referenced by setInterfaceModule().
timeval cSocketRTScheduler::baseTime [static] |
Referenced by executionResumed(), getNextEvent(), and startRun().