cSocketRTScheduler Class Reference

#include <cSocketRTScheduler.h>

List of all members.

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


Constructor & Destructor Documentation

cSocketRTScheduler::cSocketRTScheduler (  ) 

Constructor.

00047                                        : cScheduler()
00048 {
00049         fd = INVALID_SOCKET;
00050 }

cSocketRTScheduler::~cSocketRTScheduler (  )  [virtual]

Destructor.

00053 {
00054 }


Member Function Documentation

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]

Recalculates "base time" from current wall clock time.

00088 {
00089         gettimeofday(&baseTime, NULL);
00090         baseTime = timeval_substract(baseTime, sim->getSimTime().dbl());
00091 }

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().


Member Data Documentation

int cSocketRTScheduler::fd [protected]

std::vector< cModule * > cSocketRTScheduler::modules [static]

Referenced by setInterfaceModule().

std::vector< pcap_t * > cSocketRTScheduler::pds [static]

std::vector< int32 > cSocketRTScheduler::datalinks [static]

Referenced by setInterfaceModule().

std::vector< int32 > cSocketRTScheduler::headerLengths [static]

Referenced by setInterfaceModule().

timeval cSocketRTScheduler::baseTime [static]


The documentation for this class was generated from the following files:

Generated on Fri Mar 20 18:51:18 2009 for INET Framework for OMNeT++/OMNEST by  doxygen 1.5.5