INET Framework for OMNeT++/OMNEST
|
#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 |
cSocketRTScheduler::cSocketRTScheduler | ( | ) |
Constructor.
: cScheduler() { fd = INVALID_SOCKET; }
cSocketRTScheduler::~cSocketRTScheduler | ( | ) | [virtual] |
Destructor.
{ }
void cSocketRTScheduler::endRun | ( | ) | [virtual] |
Called at the end of a simulation run.
{ #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] |
cMessage * cSocketRTScheduler::getNextEvent | ( | ) | [virtual] |
Scheduler function -- it comes from cScheduler interface.
{ 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] |
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] |
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().
{ if (fd == INVALID_SOCKET) throw cRuntimeError("cSocketRTScheduler::sendBytes(): no raw socket."); int sent = sendto(fd, (char *)buf, numBytes, 0, to, addrlen); //note: no ssize_t on MSVC if (sent == numBytes) EV << "Sent an IP packet with length of " << sent << " bytes.\n"; else EV << "Sending of an IP packet FAILED! (sendto returned " << sent << " (" << strerror(errno) << ") instead of " << numBytes << ").\n"; }
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().
{ #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.
{ #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] |
Referenced by executionResumed(), getNextEvent(), and startRun().
int cSocketRTScheduler::fd [protected] |
Referenced by cSocketRTScheduler(), endRun(), receiveWithTimeout(), sendBytes(), and startRun().