#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 timeval | baseTime |
Protected Member Functions | |
virtual bool | receiveWithTimeout () |
virtual int | receiveUntil (const timeval &targetTime) |
Protected Attributes | |
int | fd |
Definition at line 40 of file cSocketRTScheduler.h.
cSocketRTScheduler::cSocketRTScheduler | ( | ) |
Constructor.
Definition at line 55 of file cSocketRTScheduler.cc.
: cScheduler() { fd = INVALID_SOCKET; }
cSocketRTScheduler::~cSocketRTScheduler | ( | ) | [virtual] |
void cSocketRTScheduler::endRun | ( | ) | [virtual] |
Called at the end of a simulation run.
Definition at line 82 of file cSocketRTScheduler.cc.
{ #ifdef HAVE_PCAP pcap_stat ps; #endif close(fd); fd = INVALID_SOCKET; #ifdef HAVE_PCAP for (uint16 i=0; i<pds.size(); i++) { if (pcap_stats(pds.at(i), &ps) < 0) throw cRuntimeError("cSocketRTScheduler::endRun(): Can not get pcap statistics: %s", pcap_geterr(pds.at(i))); else EV << modules.at(i)->getFullPath() << ": Received Packets: " << ps.ps_recv << " Dropped Packets: " << ps.ps_drop << ".\n"; pcap_close(pds.at(i)); } pds.clear(); modules.clear(); pds.clear(); datalinks.clear(); headerLengths.clear(); #endif }
void cSocketRTScheduler::executionResumed | ( | ) | [virtual] |
Recalculates "base time" from current wall clock time.
Definition at line 109 of file cSocketRTScheduler.cc.
cMessage * cSocketRTScheduler::getNextEvent | ( | ) | [virtual] |
Scheduler function -- it comes from cScheduler interface.
Definition at line 287 of file cSocketRTScheduler.cc.
{ timeval targetTime, curTime, diffTime; // calculate target time cMessage *msg = sim->msgQueue.peekFirst(); if (!msg) { targetTime.tv_sec = LONG_MAX; targetTime.tv_usec = 0; } else { simtime_t eventSimtime = msg->getArrivalTime(); targetTime = timeval_add(baseTime, eventSimtime.dbl()); } gettimeofday(&curTime, NULL); if (timeval_greater(targetTime, curTime)) { int32 status = receiveUntil(targetTime); if (status == -1) return NULL; // interrupted by user if (status == 1) msg = sim->msgQueue.peekFirst(); // received something } else { // we're behind -- customized versions of this class may // alert if we're too much behind, whatever that means diffTime = timeval_substract(curTime, targetTime); EV << "We are behind: " << diffTime.tv_sec + diffTime.tv_usec * 1e-6 << " seconds\n"; } return msg; }
int32 cSocketRTScheduler::receiveUntil | ( | const timeval & | targetTime | ) | [protected, virtual] |
Definition at line 270 of file cSocketRTScheduler.cc.
Referenced by getNextEvent().
{ // wait until targetTime or a bit longer, wait in PCAP_TIMEOUT chunks // in order to keep UI responsiveness by invoking ev.idle() timeval curTime; gettimeofday(&curTime, NULL); while (timeval_greater(targetTime, curTime)) { if (receiveWithTimeout()) return 1; if (ev.idle()) return -1; gettimeofday(&curTime, NULL); } return 0; }
bool cSocketRTScheduler::receiveWithTimeout | ( | ) | [protected, virtual] |
Definition at line 218 of file cSocketRTScheduler.cc.
Referenced by receiveUntil().
{ bool found; struct timeval timeout; #ifdef HAVE_PCAP int32 n; #ifdef LINUX int32 fd[FD_SETSIZE], maxfd; fd_set rdfds; #endif #endif found = false; timeout.tv_sec = 0; timeout.tv_usec = PCAP_TIMEOUT * 1000; #ifdef HAVE_PCAP #ifdef LINUX FD_ZERO(&rdfds); maxfd = -1; for (uint16 i = 0; i < pds.size(); i++) { fd[i] = pcap_get_selectable_fd(pds.at(i)); if (fd[i] > maxfd) maxfd = fd[i]; FD_SET(fd[i], &rdfds); } if (select(maxfd + 1, &rdfds, NULL, NULL, &timeout) < 0) { return found; } #endif for (uint16 i = 0; i < pds.size(); i++) { #ifdef LINUX if (!(FD_ISSET(fd[i], &rdfds))) continue; #endif if ((n = pcap_dispatch(pds.at(i), 1, packet_handler, (uint8 *)&i)) < 0) throw cRuntimeError("cSocketRTScheduler::pcap_dispatch(): An error occired: %s", pcap_geterr(pds.at(i))); if (n > 0) found = true; } #ifndef LINUX if (!found) select(0, NULL, NULL, NULL, &timeout); #endif #else select(0, NULL, NULL, NULL, &timeout); #endif return found; }
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().
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.
Definition at line 115 of file cSocketRTScheduler.cc.
Referenced by ExtInterface::initialize().
{ #ifdef HAVE_PCAP char errbuf[PCAP_ERRBUF_SIZE]; struct bpf_program fcode; pcap_t * pd; int32 datalink; int32 headerLength; if (!mod || !dev || !filter) throw cRuntimeError("cSocketRTScheduler::setInterfaceModule(): arguments must be non-NULL"); /* get pcap handle */ memset(&errbuf, 0, sizeof(errbuf)); if ((pd = pcap_open_live(dev, PCAP_SNAPLEN, 0, PCAP_TIMEOUT, errbuf)) == NULL) throw cRuntimeError("cSocketRTScheduler::setInterfaceModule(): Can not open pcap device, error = %s", errbuf); else if(strlen(errbuf) > 0) EV << "cSocketRTScheduler::setInterfaceModule: pcap_open_live returned waring: " << errbuf << "\n"; /* compile this command into a filter program */ if (pcap_compile(pd, &fcode, (char *)filter, 0, 0) < 0) throw cRuntimeError("cSocketRTScheduler::setInterfaceModule(): Can not compile filter: %s", pcap_geterr(pd)); /* apply the compiled filter to the packet capture device */ if (pcap_setfilter(pd, &fcode) < 0) throw cRuntimeError("cSocketRTScheduler::setInterfaceModule(): Can not apply compiled filter: %s", pcap_geterr(pd)); if ((datalink = pcap_datalink(pd)) < 0) throw cRuntimeError("cSocketRTScheduler::setInterfaceModule(): Can not get datalink: %s", pcap_geterr(pd)); #ifndef LINUX if (pcap_setnonblock(pd, 1, errbuf) < 0) throw cRuntimeError("cSocketRTScheduler::pcap_setnonblock(): Can not put pcap device into non-blocking mode, error = %s", errbuf); #endif switch (datalink) { case DLT_NULL: headerLength = 4; break; case DLT_EN10MB: headerLength = 14; break; case DLT_SLIP: headerLength = 24; break; case DLT_PPP: headerLength = 24; break; default: throw cRuntimeError("cSocketRTScheduler::setInterfaceModule(): Unsupported datalink: %d", datalink); } modules.push_back(mod); pds.push_back(pd); datalinks.push_back(datalink); headerLengths.push_back(headerLength); EV << "Opened pcap device " << dev << " with filter " << filter << " and datalink " << datalink << ".\n"; #else throw cRuntimeError("cSocketRTScheduler::setInterfaceModule(): pcap devices not supported"); #endif }
void cSocketRTScheduler::startRun | ( | ) | [virtual] |
Called at the beginning of a simulation run.
Definition at line 64 of file cSocketRTScheduler.cc.
{ #ifdef HAVE_PCAP const int32 on = 1; #endif gettimeofday(&baseTime, NULL); #ifdef HAVE_PCAP // Enabling sending makes no sense when we can't receive... fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if (fd == INVALID_SOCKET) throw cRuntimeError("cSocketRTScheduler: Root priviledges needed"); if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on)) < 0) throw cRuntimeError("cSocketRTScheduler: couldn't set sockopt for raw socket"); #endif }
timeval cSocketRTScheduler::baseTime [static] |
Definition at line 63 of file cSocketRTScheduler.h.
Referenced by executionResumed(), getNextEvent(), and startRun().
int cSocketRTScheduler::fd [protected] |
Definition at line 43 of file cSocketRTScheduler.h.
Referenced by cSocketRTScheduler(), endRun(), receiveWithTimeout(), and startRun().