INET Framework for OMNeT++/OMNEST
inet::cSocketRTScheduler Class Reference

#include <cSocketRTScheduler.h>

Inheritance diagram for inet::cSocketRTScheduler:

Public Member Functions

 cSocketRTScheduler ()
 Constructor. More...
 
virtual ~cSocketRTScheduler ()
 Destructor. More...
 
virtual void startRun () override
 Called at the beginning of a simulation run. More...
 
virtual void endRun () override
 Called at the end of a simulation run. More...
 
virtual void executionResumed () override
 Recalculates "base time" from current wall clock time. More...
 
void setInterfaceModule (cModule *mod, const char *dev, const char *filter)
 To be called from the module which wishes to receive data from the socket. More...
 
virtual cEvent * guessNextEvent () override
 Returns the first event in the Future Event Set. More...
 
virtual cEvent * takeNextEvent () override
 Scheduler function – it comes from the cScheduler interface. More...
 
virtual void putBackEvent (cEvent *event) override
 Scheduler function – it comes from the cScheduler interface. More...
 
void sendBytes (unsigned char *buf, size_t numBytes, struct sockaddr *from, socklen_t addrlen)
 Send on the currently open connection. More...
 

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 (long usec)
 
virtual int receiveUntil (const timeval &targetTime)
 

Protected Attributes

int fd
 

Constructor & Destructor Documentation

inet::cSocketRTScheduler::cSocketRTScheduler ( )

Constructor.

64  : cScheduler()
65 {
66  fd = INVALID_SOCKET;
67 }
int fd
Definition: cSocketRTScheduler.h:44
inet::cSocketRTScheduler::~cSocketRTScheduler ( )
virtual

Destructor.

70 {
71 }

Member Function Documentation

void inet::cSocketRTScheduler::endRun ( )
overridevirtual

Called at the end of a simulation run.

87 {
88  close(fd);
89  fd = INVALID_SOCKET;
90 
91  for (uint16 i = 0; i < pds.size(); i++) {
92  pcap_stat ps;
93  if (pcap_stats(pds.at(i), &ps) < 0)
94  throw cRuntimeError("cSocketRTScheduler::endRun(): Cannot query pcap statistics: %s", pcap_geterr(pds.at(i)));
95  else
96  EV << modules.at(i)->getFullPath() << ": Received Packets: " << ps.ps_recv << " Dropped Packets: " << ps.ps_drop << ".\n";
97  pcap_close(pds.at(i));
98  }
99 
100  pds.clear();
101  modules.clear();
102  pds.clear();
103  datalinks.clear();
104  headerLengths.clear();
105 }
int fd
Definition: cSocketRTScheduler.h:44
static std::vector< cModule * > modules
Definition: cSocketRTScheduler.h:59
static std::vector< int > headerLengths
Definition: cSocketRTScheduler.h:62
static std::vector< int > datalinks
Definition: cSocketRTScheduler.h:61
bool close(double one, double two)
Tests whether two doubles are close enough to be declared equal.
Definition: INETMath.h:135
static std::vector< pcap_t * > pds
Definition: cSocketRTScheduler.h:60
uint16_t uint16
Definition: Compat.h:32
void inet::cSocketRTScheduler::executionResumed ( )
overridevirtual

Recalculates "base time" from current wall clock time.

108 {
109  gettimeofday(&baseTime, nullptr);
110  baseTime = timeval_substract(baseTime, sim->getSimTime().dbl());
111 }
static timeval baseTime
Definition: cSocketRTScheduler.h:63
cEvent * inet::cSocketRTScheduler::guessNextEvent ( )
overridevirtual

Returns the first event in the Future Event Set.

291 {
292  return FES(sim)->peekFirst();
293 }
#define FES(sim)
Definition: cSocketRTScheduler.cc:44
void inet::cSocketRTScheduler::putBackEvent ( cEvent *  event)
overridevirtual

Scheduler function – it comes from the cScheduler interface.

335 {
336  FES(sim)->putBackFirst(event);
337 }
#define FES(sim)
Definition: cSocketRTScheduler.cc:44
int inet::cSocketRTScheduler::receiveUntil ( const timeval &  targetTime)
protectedvirtual

Referenced by takeNextEvent().

267 {
268  // if there's more than 2*UI_REFRESH_TIME to wait, wait in UI_REFRESH_TIME chunks
269  // in order to keep UI responsiveness by invoking getEnvir()->idle()
270  timeval curTime;
271  gettimeofday(&curTime, nullptr);
272  while (targetTime.tv_sec-curTime.tv_sec >=2 ||
273  timeval_diff_usec(targetTime, curTime) >= 2*UI_REFRESH_TIME)
274  {
276  return 1;
277  if (getEnvir()->idle())
278  return -1;
279  gettimeofday(&curTime, nullptr);
280  }
281 
282  // difference is now at most UI_REFRESH_TIME, do it at once
283  long usec = timeval_diff_usec(targetTime, curTime);
284  if (usec>0)
285  if (receiveWithTimeout(usec))
286  return 1;
287  return 0;
288 }
virtual bool receiveWithTimeout(long usec)
Definition: cSocketRTScheduler.cc:223
#define UI_REFRESH_TIME
Definition: cSocketRTScheduler.cc:38
bool inet::cSocketRTScheduler::receiveWithTimeout ( long  usec)
protectedvirtual

Referenced by receiveUntil().

224 {
225  bool found;
226  struct timeval timeout;
227  int32 n;
228 #ifdef __linux__
229  int32 fd[FD_SETSIZE], maxfd;
230  fd_set rdfds;
231 #endif
232 
233  found = false;
234  timeout.tv_sec = 0;
235  timeout.tv_usec = usec;
236 #ifdef __linux__
237  FD_ZERO(&rdfds);
238  maxfd = -1;
239  for (uint16 i = 0; i < pds.size(); i++) {
240  fd[i] = pcap_get_selectable_fd(pds.at(i));
241  if (fd[i] > maxfd)
242  maxfd = fd[i];
243  FD_SET(fd[i], &rdfds);
244  }
245  if (select(maxfd + 1, &rdfds, nullptr, nullptr, &timeout) < 0) {
246  return found;
247  }
248 #endif
249  for (uint16 i = 0; i < pds.size(); i++) {
250 #ifdef __linux__
251  if (!(FD_ISSET(fd[i], &rdfds)))
252  continue;
253 #endif // ifdef __linux__
254  if ((n = pcap_dispatch(pds.at(i), 1, packet_handler, (uint8 *)&i)) < 0)
255  throw cRuntimeError("cSocketRTScheduler::pcap_dispatch(): An error occured: %s", pcap_geterr(pds.at(i)));
256  if (n > 0)
257  found = true;
258  }
259 #ifndef __linux__
260  if (!found)
261  select(0, nullptr, nullptr, nullptr, &timeout);
262 #endif
263  return found;
264 }
uint8_t uint8
Definition: Compat.h:34
int fd
Definition: cSocketRTScheduler.h:44
int32_t int32
Definition: Compat.h:31
static std::vector< pcap_t * > pds
Definition: cSocketRTScheduler.h:60
uint16_t uint16
Definition: Compat.h:32
void inet::cSocketRTScheduler::sendBytes ( unsigned char *  buf,
size_t  numBytes,
struct sockaddr *  from,
socklen_t  addrlen 
)

Send on the currently open connection.

Referenced by inet::ExtInterface::handleMessage().

340 {
341  if (fd == INVALID_SOCKET)
342  throw cRuntimeError("cSocketRTScheduler::sendBytes(): no raw socket.");
343 
344  int sent = sendto(fd, (char *)buf, numBytes, 0, to, addrlen); //note: no ssize_t on MSVC
345 
346  if ((size_t)sent == numBytes)
347  EV << "Sent an IP packet with length of " << sent << " bytes.\n";
348  else
349  EV << "Sending of an IP packet FAILED! (sendto returned " << sent << " (" << strerror(errno) << ") instead of " << numBytes << ").\n";
350 }
int fd
Definition: cSocketRTScheduler.h:44
void inet::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 inet::ExtInterface::initialize().

114 {
115  char errbuf[PCAP_ERRBUF_SIZE];
116  struct bpf_program fcode;
117  pcap_t *pd;
118  int32 datalink;
119  int32 headerLength;
120 
121  if (!mod || !dev || !filter)
122  throw cRuntimeError("cSocketRTScheduler::setInterfaceModule(): arguments must be non-nullptr");
123 
124  /* get pcap handle */
125  memset(&errbuf, 0, sizeof(errbuf));
126  if ((pd = pcap_create(dev, errbuf)) == nullptr)
127  throw cRuntimeError("cSocketRTScheduler::setInterfaceModule(): Cannot create pcap device, error = %s", errbuf);
128  else if (strlen(errbuf) > 0)
129  EV << "cSocketRTScheduler::setInterfaceModule(): pcap_open_live returned warning: " << errbuf << "\n";
130 
131  /* apply the immediate mode to pcap */
132  if (pcap_set_immediate_mode(pd, 1) != 0)
133  throw cRuntimeError("cSocketRTScheduler::setInterfaceModule(): Cannot set immediate mode to pcap device");
134 
135  if (pcap_activate(pd) != 0)
136  throw cRuntimeError("cSocketRTScheduler::setInterfaceModule(): Cannot activate pcap device");
137 
138  /* compile this command into a filter program */
139  if (pcap_compile(pd, &fcode, (char *)filter, 0, 0) < 0)
140  throw cRuntimeError("cSocketRTScheduler::setInterfaceModule(): Cannot compile pcap filter: %s", pcap_geterr(pd));
141 
142  /* apply the compiled filter to the packet capture device */
143  if (pcap_setfilter(pd, &fcode) < 0)
144  throw cRuntimeError("cSocketRTScheduler::setInterfaceModule(): Cannot apply compiled pcap filter: %s", pcap_geterr(pd));
145 
146  if ((datalink = pcap_datalink(pd)) < 0)
147  throw cRuntimeError("cSocketRTScheduler::setInterfaceModule(): Cannot query pcap link-layer header type: %s", pcap_geterr(pd));
148 
149 #ifndef __linux__
150  if (pcap_setnonblock(pd, 1, errbuf) < 0)
151  throw cRuntimeError("cSocketRTScheduler::setInterfaceModule(): Cannot put pcap device into non-blocking mode, error: %s", errbuf);
152 #endif
153 
154  switch (datalink) {
155  case DLT_NULL:
156  headerLength = 4;
157  break;
158 
159  case DLT_EN10MB:
160  headerLength = 14;
161  break;
162 
163  case DLT_SLIP:
164  headerLength = 24;
165  break;
166 
167  case DLT_PPP:
168  headerLength = 24;
169  break;
170 
171  default:
172  throw cRuntimeError("cSocketRTScheduler::setInterfaceModule(): Unsupported datalink: %d", datalink);
173  }
174  modules.push_back(mod);
175  pds.push_back(pd);
176  datalinks.push_back(datalink);
177  headerLengths.push_back(headerLength);
178 
179  EV << "Opened pcap device " << dev << " with filter " << filter << " and datalink " << datalink << ".\n";
180 }
double mod(double dividend, double divisor)
Returns the rest of a whole-numbered division.
Definition: INETMath.h:108
static std::vector< cModule * > modules
Definition: cSocketRTScheduler.h:59
static std::vector< int > headerLengths
Definition: cSocketRTScheduler.h:62
int32_t int32
Definition: Compat.h:31
static std::vector< int > datalinks
Definition: cSocketRTScheduler.h:61
static std::vector< pcap_t * > pds
Definition: cSocketRTScheduler.h:60
void inet::cSocketRTScheduler::startRun ( )
overridevirtual

Called at the beginning of a simulation run.

74 {
75  gettimeofday(&baseTime, nullptr);
76 
77  // Enabling sending makes no sense when we can't receive...
78  fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
79  if (fd == INVALID_SOCKET)
80  throw cRuntimeError("cSocketRTScheduler: Root privileges needed");
81  const int32 on = 1;
82  if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on)) < 0)
83  throw cRuntimeError("cSocketRTScheduler: couldn't set sockopt for raw socket");
84 }
#define IP_HDRINCL
Definition: lwip_ip.h:69
static timeval baseTime
Definition: cSocketRTScheduler.h:63
int fd
Definition: cSocketRTScheduler.h:44
int32_t int32
Definition: Compat.h:31
cEvent * inet::cSocketRTScheduler::takeNextEvent ( )
overridevirtual

Scheduler function – it comes from the cScheduler interface.

296 {
297  timeval targetTime;
298 
299  // calculate target time
300  cEvent *event = FES(sim)->peekFirst();
301  if (!event) {
302  targetTime.tv_sec = LONG_MAX;
303  targetTime.tv_usec = 0;
304  }
305  else {
306  // use time of next event
307  simtime_t eventSimtime = event->getArrivalTime();
308  targetTime = timeval_add(baseTime, eventSimtime.dbl());
309  }
310 
311  // if needed, wait until that time arrives
312  timeval curTime;
313  gettimeofday(&curTime, nullptr);
314  if (timeval_greater(targetTime, curTime))
315  {
316  int status = receiveUntil(targetTime);
317  if (status == -1)
318  return nullptr; // interrupted by user
319  if (status == 1)
320  event = FES(sim)->peekFirst(); // received something
321  }
322  else {
323  // we're behind -- customized versions of this class may
324  // alert if we're too much behind, whatever that means
325  timeval diffTime = timeval_substract(curTime, targetTime);
326  EV << "We are behind: " << diffTime.tv_sec + diffTime.tv_usec * 1e-6 << " seconds\n";
327  }
328  cEvent *tmp = FES(sim)->removeFirst();
329  ASSERT(tmp == event);
330  return event;
331 }
static timeval baseTime
Definition: cSocketRTScheduler.h:63
const value< double, units::C > e(1.602176487e-19)
#define FES(sim)
Definition: cSocketRTScheduler.cc:44
virtual int receiveUntil(const timeval &targetTime)
Definition: cSocketRTScheduler.cc:266

Member Data Documentation

timeval inet::cSocketRTScheduler::baseTime
static
std::vector< int32 > inet::cSocketRTScheduler::datalinks
static

Referenced by endRun(), and setInterfaceModule().

int inet::cSocketRTScheduler::fd
protected
std::vector< int32 > inet::cSocketRTScheduler::headerLengths
static

Referenced by endRun(), and setInterfaceModule().

std::vector< cModule * > inet::cSocketRTScheduler::modules
static

Referenced by endRun(), and setInterfaceModule().

std::vector< pcap_t * > inet::cSocketRTScheduler::pds
static

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