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

#include <ExtLowerUdp.h>

Inheritance diagram for inet::ExtLowerUdp:
inet::ILifecycle inet::RealTimeScheduler::ICallback

Classes

class  Socket
 

Public Member Functions

virtual ~ExtLowerUdp ()
 
- Public Member Functions inherited from inet::ILifecycle
virtual ~ILifecycle ()
 
- Public Member Functions inherited from inet::RealTimeScheduler::ICallback
virtual ~ICallback ()
 

Protected Member Functions

virtual int numInitStages () const override
 
virtual void initialize (int stage) override
 
virtual void handleMessage (cMessage *message) override
 
virtual bool handleOperationStage (LifecycleOperation *operation, IDoneCallback *doneCallback) override
 Perform one stage of a lifecycle operation. More...
 
virtual bool notify (int fd) override
 
virtual Socketopen (int socketId)
 
virtual void bind (int socketId, const L3Address &localAddress, int localPort)
 
virtual void connect (int socketId, const L3Address &remoteAddress, int remotePort)
 
virtual void close (int socketId)
 
virtual void processPacketFromUpper (Packet *packet)
 
virtual void processPacketFromLower (int fd)
 

Protected Attributes

const char * packetNameFormat = nullptr
 
PacketPrinter packetPrinter
 
RealTimeSchedulerrtScheduler = nullptr
 
std::map< int, Socket * > socketIdToSocketMap
 
std::map< int, Socket * > fdToSocketMap
 

Constructor & Destructor Documentation

◆ ~ExtLowerUdp()

inet::ExtLowerUdp::~ExtLowerUdp ( )
virtual
28 {
29  for (auto& it : socketIdToSocketMap) {
30  close(it.second->socketId);
31  }
32 }

Member Function Documentation

◆ bind()

void inet::ExtLowerUdp::bind ( int  socketId,
const L3Address localAddress,
int  localPort 
)
protectedvirtual
196 {
197  Socket *socket = nullptr;
198  auto it = socketIdToSocketMap.find(socketId);
199  if (it == socketIdToSocketMap.end())
200  socket = open(socketId);
201  else
202  socket = it->second;
203  struct sockaddr_in sockaddr;
204  sockaddr.sin_family = PF_INET;
205  sockaddr.sin_port = htons(localPort);
206  sockaddr.sin_addr.s_addr = htonl(localAddress.toIpv4().getInt());
207 #if !defined(linux) && !defined(__linux) && !defined(_WIN32)
208  sockaddr.sin_len = sizeof(struct sockaddr_in);
209 #endif
210  int n = ::bind(socket->fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
211  if (n < 0)
212  throw cRuntimeError("Cannot bind socket: %d", n);
213 }

Referenced by handleMessage().

◆ close()

void inet::ExtLowerUdp::close ( int  socketId)
protectedvirtual
236 {
237  auto it = socketIdToSocketMap.find(socketId);
238  if (it == socketIdToSocketMap.end())
239  throw cRuntimeError("Unknown socket");
240  else {
241  auto socket = it->second;
242  socketIdToSocketMap.erase(it);
243  fdToSocketMap.erase(socket->fd);
244  rtScheduler->removeCallback(socket->fd, this);
245  delete socket;
246  }
247 }

Referenced by handleMessage(), and ~ExtLowerUdp().

◆ connect()

void inet::ExtLowerUdp::connect ( int  socketId,
const L3Address remoteAddress,
int  remotePort 
)
protectedvirtual
216 {
217  Socket *socket = nullptr;
218  auto it = socketIdToSocketMap.find(socketId);
219  if (it == socketIdToSocketMap.end())
220  socket = open(socketId);
221  else
222  socket = it->second;
223  struct sockaddr_in sockaddr;
224  sockaddr.sin_family = PF_INET;
225  sockaddr.sin_port = htons(remotePort);
226  sockaddr.sin_addr.s_addr = htonl(remoteAddress.toIpv4().getInt());
227 #if !defined(linux) && !defined(__linux) && !defined(_WIN32)
228  sockaddr.sin_len = sizeof(struct sockaddr_in);
229 #endif
230  int n = ::connect(socket->fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
231  if (n < 0)
232  throw cRuntimeError("Cannot connect socket: %d", n);
233 }

Referenced by handleMessage().

◆ handleMessage()

void inet::ExtLowerUdp::handleMessage ( cMessage *  message)
overrideprotectedvirtual
49 {
50  switch (message->getKind()) {
51  case UDP_C_BIND: {
52  int socketId = check_and_cast<Request *>(message)->getTag<SocketReq>()->getSocketId();
53  UdpBindCommand *ctrl = check_and_cast<UdpBindCommand *>(message->getControlInfo());
54  bind(socketId, ctrl->getLocalAddr(), ctrl->getLocalPort());
55  break;
56  }
57 
58  case UDP_C_CONNECT: {
59  int socketId = check_and_cast<Request *>(message)->getTag<SocketReq>()->getSocketId();
60  UdpConnectCommand *ctrl = check_and_cast<UdpConnectCommand *>(message->getControlInfo());
61  connect(socketId, ctrl->getRemoteAddr(), ctrl->getRemotePort());
62  break;
63  }
64 
65  case UDP_C_CLOSE: {
66  int socketId = check_and_cast<Request *>(message)->getTag<SocketReq>()->getSocketId();
67  close(socketId);
68  break;
69  }
70 
71  case UDP_C_DATA: {
72  processPacketFromUpper(check_and_cast<Packet *>(message));
73  break;
74  }
75 
76  case UDP_C_SETOPTION: {
77  throw cRuntimeError("Not implemented");
78 // int socketId = check_and_cast<Request *>(message)->getTag<SocketReq>()->getSocketId();
79 // UdpSetOptionCommand *ctrl = check_and_cast<UdpSetOptionCommand *>(message->getControlInfo());
80 // SockDesc *sd = getOrCreateSocket(socketId);
81 //
82 // if (auto cmd = dynamic_cast<UdpSetTimeToLiveCommand *>(ctrl))
83 // setTimeToLive(sd, cmd->getTtl());
84 // else if (auto cmd = dynamic_cast<UdpSetTypeOfServiceCommand *>(ctrl))
85 // setTypeOfService(sd, cmd->getTos());
86 // else if (auto cmd = dynamic_cast<UdpSetBroadcastCommand *>(ctrl))
87 // setBroadcast(sd, cmd->getBroadcast());
88 // else if (auto cmd = dynamic_cast<UdpSetMulticastInterfaceCommand *>(ctrl))
89 // setMulticastOutputInterface(sd, cmd->getInterfaceId());
90 // else if (auto cmd = dynamic_cast<UdpSetMulticastLoopCommand *>(ctrl))
91 // setMulticastLoop(sd, cmd->getLoop());
92 // else if (auto cmd = dynamic_cast<UdpSetReuseAddressCommand *>(ctrl))
93 // setReuseAddress(sd, cmd->getReuseAddress());
94 // else if (auto cmd = dynamic_cast<UdpJoinMulticastGroupsCommand *>(ctrl)) {
95 // std::vector<L3Address> addresses;
96 // std::vector<int> interfaceIds;
97 // for (size_t i = 0; i < cmd->getMulticastAddrArraySize(); i++)
98 // addresses.push_back(cmd->getMulticastAddr(i));
99 // for (size_t i = 0; i < cmd->getInterfaceIdArraySize(); i++)
100 // interfaceIds.push_back(cmd->getInterfaceId(i));
101 // joinMulticastGroups(sd, addresses, interfaceIds);
102 // }
103 // else if (auto cmd = dynamic_cast<UdpLeaveMulticastGroupsCommand *>(ctrl)) {
104 // std::vector<L3Address> addresses;
105 // for (size_t i = 0; i < cmd->getMulticastAddrArraySize(); i++)
106 // addresses.push_back(cmd->getMulticastAddr(i));
107 // leaveMulticastGroups(sd, addresses);
108 // }
109 // else if (auto cmd = dynamic_cast<UdpBlockMulticastSourcesCommand *>(ctrl)) {
110 // NetworkInterface *ie = ift->getInterfaceById(cmd->getInterfaceId());
111 // std::vector<L3Address> sourceList;
112 // for (size_t i = 0; i < cmd->getSourceListArraySize(); i++)
113 // sourceList.push_back(cmd->getSourceList(i));
114 // blockMulticastSources(sd, ie, cmd->getMulticastAddr(), sourceList);
115 // }
116 // else if (auto cmd = dynamic_cast<UdpUnblockMulticastSourcesCommand *>(ctrl)) {
117 // NetworkInterface *ie = ift->getInterfaceById(cmd->getInterfaceId());
118 // std::vector<L3Address> sourceList;
119 // for (size_t i = 0; i < cmd->getSourceListArraySize(); i++)
120 // sourceList.push_back(cmd->getSourceList(i));
121 // leaveMulticastSources(sd, ie, cmd->getMulticastAddr(), sourceList);
122 // }
123 // else if (auto cmd = dynamic_cast<UdpJoinMulticastSourcesCommand *>(ctrl)) {
124 // NetworkInterface *ie = ift->getInterfaceById(cmd->getInterfaceId());
125 // std::vector<L3Address> sourceList;
126 // for (size_t i = 0; i < cmd->getSourceListArraySize(); i++)
127 // sourceList.push_back(cmd->getSourceList(i));
128 // joinMulticastSources(sd, ie, cmd->getMulticastAddr(), sourceList);
129 // }
130 // else if (auto cmd = dynamic_cast<UdpLeaveMulticastSourcesCommand *>(ctrl)) {
131 // NetworkInterface *ie = ift->getInterfaceById(cmd->getInterfaceId());
132 // std::vector<L3Address> sourceList;
133 // for (size_t i = 0; i < cmd->getSourceListArraySize(); i++)
134 // sourceList.push_back(cmd->getSourceList(i));
135 // leaveMulticastSources(sd, ie, cmd->getMulticastAddr(), sourceList);
136 // }
137 // else if (auto cmd = dynamic_cast<UdpSetMulticastSourceFilterCommand *>(ctrl)) {
138 // NetworkInterface *ie = ift->getInterfaceById(cmd->getInterfaceId());
139 // std::vector<L3Address> sourceList;
140 // for (unsigned int i = 0; i < cmd->getSourceListArraySize(); i++)
141 // sourceList.push_back(cmd->getSourceList(i));
142 // setMulticastSourceFilter(sd, ie, cmd->getMulticastAddr(), cmd->getFilterMode(), sourceList);
143 // }
144 // else
145 // throw cRuntimeError("Unknown subclass of UdpSetOptionCommand received from app: %s", ctrl->getClassName());
146 // break;
147  }
148 
149  default:
150  throw cRuntimeError("Unknown command code (message kind) %d received from app", message->getKind());
151  }
152  delete message;
153 }

◆ handleOperationStage()

bool inet::ExtLowerUdp::handleOperationStage ( LifecycleOperation operation,
IDoneCallback doneCallback 
)
overrideprotectedvirtual

Perform one stage of a lifecycle operation.

Processing may be done entirely within this method, or may be a longer process that involves nonzero simulation time or several events, and is triggered by this method call.

Return value: true = "done"; false = "not yet done, will invoke doneCallback when done"

Implements inet::ILifecycle.

156 {
157  Enter_Method("handleOperationStage");
158  // TODO
159  return true;
160 }

◆ initialize()

void inet::ExtLowerUdp::initialize ( int  stage)
overrideprotectedvirtual
35 {
36  cSimpleModule::initialize(stage);
37  if (stage == INITSTAGE_LOCAL) {
38  packetNameFormat = par("packetNameFormat");
39  if (auto scheduler = dynamic_cast<RealTimeScheduler *>(getSimulation()->getScheduler())) {
40  rtScheduler = scheduler;
41  }
42  }
43  else if (stage == INITSTAGE_TRANSPORT_LAYER) {
44  registerService(Protocol::udp, gate("appIn"), gate("appOut"));
45  }
46 }

◆ notify()

bool inet::ExtLowerUdp::notify ( int  fd)
overrideprotectedvirtual

Implements inet::RealTimeScheduler::ICallback.

163 {
164  auto it = fdToSocketMap.find(fd);
165  if (it == fdToSocketMap.end())
166  return false;
167  else {
168  auto socket = it->second;
169  processPacketFromLower(socket->fd);
170  return true;
171  }
172 }

◆ numInitStages()

virtual int inet::ExtLowerUdp::numInitStages ( ) const
inlineoverrideprotectedvirtual
37 { return NUM_INIT_STAGES; }

◆ open()

ExtLowerUdp::Socket * inet::ExtLowerUdp::open ( int  socketId)
protectedvirtual
175 {
176  NetworkNamespaceContext context(par("namespace"));
177  auto socket = new Socket(socketId);
178  int fd = ::socket(AF_INET, SOCK_DGRAM, 0);
179  if (fd < 0)
180  throw cRuntimeError("Cannot create socket: %d", fd);
181 
182  // Setting this option makes it possible to kill the simulations
183  // and restart them right away using the same port numbers.
184  int enable = 1;
185  if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&enable, sizeof(int)) < 0)
186  throw cRuntimeError("ExtLowerUdp: cannot set socket option");
187 
188  socket->fd = fd;
189  socketIdToSocketMap[socketId] = socket;
190  fdToSocketMap[fd] = socket;
191  rtScheduler->addCallback(fd, this);
192  return socket;
193 }

Referenced by bind(), and connect().

◆ processPacketFromLower()

void inet::ExtLowerUdp::processPacketFromLower ( int  fd)
protectedvirtual
286 {
287  Enter_Method("processPacketFromLower");
288  auto it = fdToSocketMap.find(fd);
289  if (it == fdToSocketMap.end())
290  throw cRuntimeError("Unknown socket");
291  else {
292  auto socket = it->second;
293  uint8_t buffer[1 << 16];
294  struct sockaddr_in sockaddr;
295  socklen_t socklen = sizeof(sockaddr);
296  // type of buffer in recvfrom(): win: char *, linux: void *
297  int n = ::recvfrom(fd, (char *)buffer, sizeof(buffer), 0, (struct sockaddr *)&sockaddr, &socklen);
298  if (n < 0)
299  throw cRuntimeError("Calling recv failed: %d", n);
300  auto data = makeShared<BytesChunk>(static_cast<const uint8_t *>(buffer), n);
301  auto packet = new Packet(nullptr, data);
302  packet->addTag<SocketInd>()->setSocketId(socket->socketId);
303  packet->addTag<L3AddressInd>()->setSrcAddress(Ipv4Address(ntohl(sockaddr.sin_addr.s_addr)));
304  packet->addTag<L4PortInd>()->setSrcPort(ntohs(sockaddr.sin_port));
305  packet->setName(packetPrinter.printPacketToString(packet, packetNameFormat).c_str());
306  emit(packetReceivedSignal, packet);
307  send(packet, "appOut");
308  emit(packetSentToUpperSignal, packet);
309  }
310 }

Referenced by notify().

◆ processPacketFromUpper()

void inet::ExtLowerUdp::processPacketFromUpper ( Packet packet)
protectedvirtual
250 {
251  emit(packetReceivedFromUpperSignal, packet);
252  auto socketId = packet->getTag<SocketReq>()->getSocketId();
253  auto it = socketIdToSocketMap.find(socketId);
254  if (it == socketIdToSocketMap.end())
255  throw cRuntimeError("Unknown socket");
256  else {
257  auto socket = it->second;
258  auto bytesChunk = packet->peekAllAsBytes();
259  uint8_t buffer[packet->getByteLength()];
260  size_t packetLength = bytesChunk->copyToBuffer(buffer, packet->getByteLength());
261  ASSERT(packetLength == (size_t)packet->getByteLength());
262  if (auto addressReq = packet->findTag<L3AddressReq>()) {
263  struct sockaddr_in sockaddr;
264  sockaddr.sin_family = PF_INET;
265  sockaddr.sin_port = htons(packet->getTag<L4PortReq>()->getDestPort());
266  sockaddr.sin_addr.s_addr = htonl(addressReq->getDestAddress().toIpv4().getInt());
267 #if !defined(linux) && !defined(__linux) && !defined(_WIN32)
268  sockaddr.sin_len = sizeof(struct sockaddr_in);
269 #endif
270  // type of buffer in sendto(): win: char *, linux: void *
271  int n = ::sendto(socket->fd, (char *)buffer, packetLength, 0, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
272  if (n < 0)
273  throw cRuntimeError("Calling sendto failed: %d", n);
274  }
275  else {
276  // type of buffer in send(): win: char *, linux: void *
277  int n = ::send(socket->fd, (char *)buffer, packetLength, 0);
278  if (n < 0)
279  throw cRuntimeError("Calling send failed: %d", n);
280  }
281  emit(packetSentSignal, packet);
282  }
283 }

Referenced by handleMessage().

Member Data Documentation

◆ fdToSocketMap

std::map<int, Socket *> inet::ExtLowerUdp::fdToSocketMap
protected

◆ packetNameFormat

const char* inet::ExtLowerUdp::packetNameFormat = nullptr
protected

◆ packetPrinter

PacketPrinter inet::ExtLowerUdp::packetPrinter
protected

Referenced by processPacketFromLower().

◆ rtScheduler

RealTimeScheduler* inet::ExtLowerUdp::rtScheduler = nullptr
protected

Referenced by close(), initialize(), and open().

◆ socketIdToSocketMap

std::map<int, Socket *> inet::ExtLowerUdp::socketIdToSocketMap
protected

The documentation for this class was generated from the following files:
inet::RealTimeScheduler::removeCallback
void removeCallback(int fd, ICallback *callback)
Definition: RealTimeScheduler.cc:50
inet::ExtLowerUdp::processPacketFromLower
virtual void processPacketFromLower(int fd)
Definition: ExtLowerUdp.cc:285
inet::ExtLowerUdp::packetNameFormat
const char * packetNameFormat
Definition: ExtLowerUdp.h:30
inet::UDP_C_CONNECT
@ UDP_C_CONNECT
Definition: UdpControlInfo_m.h:88
inet::ExtLowerUdp::open
virtual Socket * open(int socketId)
Definition: ExtLowerUdp.cc:174
L4PortReq
removed L4PortReq
Definition: IUdp-gates.txt:11
inet::packetReceivedFromUpperSignal
simsignal_t packetReceivedFromUpperSignal
Definition: Simsignals.cc:88
ntohs
u16_t ntohs(u16_t n)
inet::ExtLowerUdp::rtScheduler
RealTimeScheduler * rtScheduler
Definition: ExtLowerUdp.h:32
inet::ExtLowerUdp::connect
virtual void connect(int socketId, const L3Address &remoteAddress, int remotePort)
Definition: ExtLowerUdp.cc:215
inet::RealTimeScheduler::addCallback
void addCallback(int fd, ICallback *callback)
To be called from the module which wishes to receive data from the fd.
Definition: RealTimeScheduler.cc:41
L3AddressInd
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd L3AddressInd
Definition: IUdp-gates.txt:20
inet::ExtLowerUdp::packetPrinter
PacketPrinter packetPrinter
Definition: ExtLowerUdp.h:31
htonl
u32_t htonl(u32_t n)
inet::packetSentSignal
simsignal_t packetSentSignal
Definition: Simsignals.cc:96
inet::registerService
void registerService(const Protocol &protocol, cGate *gate, ServicePrimitive servicePrimitive)
Registers a service primitive (SDU processing) at the given gate.
Definition: IProtocolRegistrationListener.cc:14
ntohl
u32_t ntohl(u32_t n)
htons
u16_t htons(u16_t n)
inet::ExtLowerUdp::socketIdToSocketMap
std::map< int, Socket * > socketIdToSocketMap
Definition: ExtLowerUdp.h:33
inet::ExtLowerUdp::fdToSocketMap
std::map< int, Socket * > fdToSocketMap
Definition: ExtLowerUdp.h:34
ctrl
removed ctrl
Definition: IUdp-gates.txt:7
inet::packetReceivedSignal
simsignal_t packetReceivedSignal
Definition: Simsignals.cc:97
inet::Protocol::udp
static const Protocol udp
Definition: Protocol.h:117
inet::INITSTAGE_TRANSPORT_LAYER
INET_API InitStage INITSTAGE_TRANSPORT_LAYER
Initialization of transport-layer protocols.
inet::PacketPrinter::printPacketToString
virtual std::string printPacketToString(Packet *packet, const char *format=nullptr) const
Definition: PacketPrinter.cc:223
inet::ExtLowerUdp::close
virtual void close(int socketId)
Definition: ExtLowerUdp.cc:235
inet::INITSTAGE_LOCAL
INET_API InitStage INITSTAGE_LOCAL
Initialization of local state that don't use or affect other modules includes:
NUM_INIT_STAGES
#define NUM_INIT_STAGES
Definition: InitStageRegistry.h:73
inet::UDP_C_BIND
@ UDP_C_BIND
Definition: UdpControlInfo_m.h:87
inet::ExtLowerUdp::processPacketFromUpper
virtual void processPacketFromUpper(Packet *packet)
Definition: ExtLowerUdp.cc:249
L4PortInd
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd L4PortInd
Definition: IUdp-gates.txt:20
Enter_Method
#define Enter_Method(...)
Definition: SelfDoc.h:71
inet::UDP_C_DATA
@ UDP_C_DATA
Definition: UdpControlInfo_m.h:86
inet::UDP_C_SETOPTION
@ UDP_C_SETOPTION
Definition: UdpControlInfo_m.h:89
inet::packetSentToUpperSignal
simsignal_t packetSentToUpperSignal
Definition: Simsignals.cc:87
inet::ExtLowerUdp::bind
virtual void bind(int socketId, const L3Address &localAddress, int localPort)
Definition: ExtLowerUdp.cc:195
inet::UDP_C_CLOSE
@ UDP_C_CLOSE
Definition: UdpControlInfo_m.h:90