Public Member Functions | Static Public Attributes | Protected Member Functions | Protected Attributes

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 timeval baseTime

Protected Member Functions

virtual bool receiveWithTimeout ()
virtual int receiveUntil (const timeval &targetTime)

Protected Attributes

int fd

Detailed Description

Definition at line 40 of file cSocketRTScheduler.h.


Constructor & Destructor Documentation

cSocketRTScheduler::cSocketRTScheduler (  ) 

Constructor.

Definition at line 55 of file cSocketRTScheduler.cc.

                                       : cScheduler()
{
    fd = INVALID_SOCKET;
}

cSocketRTScheduler::~cSocketRTScheduler (  )  [virtual]

Destructor.

Definition at line 60 of file cSocketRTScheduler.cc.

{
}


Member Function Documentation

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.

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

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
}


Member Data Documentation

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


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