#include <SimpleUDP.h>
More info in the NED file.
Public Types | |
typedef std::list< SockDesc * > | SockDescList |
list of socket pointers | |
typedef std::map< int, SockDesc * > | SocketsByIdMap |
list of socket ordered by sockId | |
typedef std::map< int, SockDescList > | SocketsByPortMap |
list of sockets ordered by localPort | |
Public Member Functions | |
void | setNodeEntry (const SimpleNodeEntry &entry) |
set or change the nodeEntry of this module | |
SimpleUDP () | |
constructor | |
virtual | ~SimpleUDP () |
destructor | |
Protected Member Functions | |
void | updateDisplayString () |
utility: show current statistics above the icon | |
void | bind (int gateIndex, UDPControlInfo *ctrl) |
bind socket | |
void | connect (int sockId, IPvXAddress addr, int port) |
connect socket | |
void | unbind (int sockId) |
unbind socket | |
short | getEphemeralPort () |
ephemeral port. | |
bool | matchesSocket (SockDesc *sd, SimpleUDPPacket *udp, IPControlInfo *ctrl) |
decides if a received packet (IPv4) belongs to the specified socket | |
bool | matchesSocket (SockDesc *sd, SimpleUDPPacket *udp, IPv6ControlInfo *ctrl) |
decides if a received packet (IPv6) belongs to the specified socket | |
bool | matchesSocket (SockDesc *sd, const IPvXAddress &localAddr, const IPvXAddress &remoteAddr, short remotePort) |
decides if a socket matches the specified parameters | |
void | sendUp (cMessage *payload, SimpleUDPPacket *udpHeader, IPControlInfo *ctrl, SockDesc *sd) |
sends payload up to the application | |
void | sendUp (cMessage *payload, SimpleUDPPacket *udpHeader, IPv6ControlInfo *ctrl, SockDesc *sd) |
sends payload up to the application | |
void | processUndeliverablePacket (SimpleUDPPacket *udpPacket, cPolymorphic *ctrl) |
handles received packet which destination port is not bound to any socket | |
void | sendUpErrorNotification (SockDesc *sd, int msgkind, const IPvXAddress &localAddr, const IPvXAddress &remoteAddr, short remotePort) |
sends an error up to the application | |
virtual void | processICMPError (cMessage *icmpErrorMsg) |
process an ICMP error packet | |
virtual void | processUDPPacket (SimpleUDPPacket *udpPacket) |
process UDP packets coming from IP | |
virtual void | processMsgFromApp (cMessage *appData) |
process packets from application | |
virtual void | processCommandFromApp (cMessage *msg) |
process commands from application | |
virtual void | initialize (int stage) |
initialise the SimpleUDP module | |
virtual int | numInitStages () const |
returns the number of init stages | |
virtual void | handleMessage (cMessage *msg) |
process received messages | |
Protected Attributes | |
SocketsByIdMap | socketsByIdMap |
list of socket ordered by sockId | |
SocketsByPortMap | socketsByPortMap |
list of sockets ordered by localPort | |
short | lastEphemeralPort |
last used port (all ports above should be free) | |
ICMP * | icmp |
pointer to a received icmp (IPv4) message | |
ICMPv6 * | icmpv6 |
pointer to a received icmp (IPv6) message | |
int | numSent |
number of packets sent to the network | |
int | numPassedUp |
number of packet passed up to applications | |
int | numDroppedWrongPort |
number of dropped packets due to wrong destination port | |
int | numDroppedBadChecksum |
number of dropped packets due to bad checksum | |
simtime_t | delay |
simulated delay between sending and receiving udp module | |
simtime_t | constantDelay |
constant delay between two peers | |
bool | useCoordinateBasedDelay |
delay should be calculated from euklidean distance between two peers | |
BootstrapOracle * | bootstrapOracle |
pointer to BootstrapOracle | |
SimpleNodeEntry * | nodeEntry |
nodeEntry of the overlay node this module belongs to | |
Classes | |
struct | SockDesc |
defines a socket More... |
typedef std::list<SockDesc *> SimpleUDP::SockDescList |
list of socket pointers
typedef std::map<int,SockDesc *> SimpleUDP::SocketsByIdMap |
list of socket ordered by sockId
typedef std::map<int,SockDescList> SimpleUDP::SocketsByPortMap |
list of sockets ordered by localPort
SimpleUDP::~SimpleUDP | ( | ) | [virtual] |
destructor
00083 { 00084 for (SocketsByIdMap::iterator i=socketsByIdMap.begin(); 00085 i!=socketsByIdMap.end(); ++i) 00086 delete i->second; 00087 00088 if(nodeEntry) 00089 delete nodeEntry; 00090 }
void SimpleUDP::setNodeEntry | ( | const SimpleNodeEntry & | entry | ) |
set or change the nodeEntry of this module
entry | the new nodeEntry |
00634 { 00635 if(nodeEntry != NULL) 00636 delete nodeEntry; 00637 nodeEntry = new SimpleNodeEntry(entry); 00638 }
void SimpleUDP::updateDisplayString | ( | ) | [protected] |
utility: show current statistics above the icon
00247 { 00248 char buf[80]; 00249 sprintf(buf, "passed up: %d pks\nsent: %d pks", numPassedUp, numSent); 00250 if (numDroppedWrongPort>0) { 00251 sprintf(buf+strlen(buf), "\ndropped (no app): %d pks", numDroppedWrongPort); 00252 displayString().setTagArg("i",1,"red"); 00253 } 00254 displayString().setTagArg("t",0,buf); 00255 }
void SimpleUDP::bind | ( | int | gateIndex, | |
UDPControlInfo * | ctrl | |||
) | [protected] |
bind socket
gateIndex | application gate connected to the socket | |
ctrl | control information for communication |
00121 { 00122 // XXX checks could be added, of when the bind should be allowed to proceed 00123 00124 // create and fill in SockDesc 00125 SockDesc *sd = new SockDesc(); 00126 sd->sockId = ctrl->sockId(); 00127 sd->userId = ctrl->userId(); 00128 sd->appGateIndex = gateIndex; 00129 sd->localAddr = ctrl->srcAddr(); 00130 sd->remoteAddr = ctrl->destAddr(); 00131 sd->localPort = ctrl->srcPort(); 00132 sd->remotePort = ctrl->destPort(); 00133 sd->interfaceId = ctrl->interfaceId(); 00134 00135 if (sd->sockId==-1) 00136 error("sockId in BIND message not filled in"); 00137 if (sd->localPort==0) 00138 sd->localPort = getEphemeralPort(); 00139 00140 sd->onlyLocalPortIsSet = sd->localAddr.isUnspecified() && 00141 sd->remoteAddr.isUnspecified() && 00142 sd->remotePort==0 && 00143 sd->interfaceId==-1; 00144 00145 cModule *node = parentModule(); 00146 IPvXAddress ip = IPAddressResolver().addressOf(node); 00147 EV << "[SimpleUDP::bind() @ " << ip << "]\n" 00148 << " Binding socket: " << *sd 00149 << endl; 00150 00151 // add to socketsByIdMap 00152 ASSERT(socketsByIdMap.find(sd->sockId)==socketsByIdMap.end()); 00153 socketsByIdMap[sd->sockId] = sd; 00154 00155 // add to socketsByPortMap 00156 // create if doesn't exist 00157 SockDescList& list = socketsByPortMap[sd->localPort]; 00158 list.push_back(sd); 00159 }
void SimpleUDP::connect | ( | int | sockId, | |
IPvXAddress | addr, | |||
int | port | |||
) | [protected] |
connect socket
sockId | id of the socket to connect | |
addr | IPvXAddress of the remote socket | |
port | port of the remote socket |
00162 { 00163 SocketsByIdMap::iterator it = socketsByIdMap.find(sockId); 00164 if (it==socketsByIdMap.end()) 00165 error("socket id=%d doesn't exist (already closed?)", sockId); 00166 if (addr.isUnspecified()) 00167 opp_error("connect: unspecified remote address"); 00168 if (port<=0 || port>65535) 00169 opp_error("connect: invalid remote port number %d", port); 00170 00171 SockDesc *sd = it->second; 00172 sd->remoteAddr = addr; 00173 sd->remotePort = port; 00174 00175 sd->onlyLocalPortIsSet = false; 00176 00177 EV << "[SimpleUDP::connect() @ " << sd->localAddr << "]\n" 00178 << " Connecting socket: " << *sd 00179 << endl; 00180 }
void SimpleUDP::unbind | ( | int | sockId | ) | [protected] |
unbind socket
sockId | id of the socket to unbind |
00183 { 00184 // remove from socketsByIdMap 00185 SocketsByIdMap::iterator it = socketsByIdMap.find(sockId); 00186 if (it==socketsByIdMap.end()) 00187 error("socket id=%d doesn't exist (already closed?)", sockId); 00188 SockDesc *sd = it->second; 00189 socketsByIdMap.erase(it); 00190 00191 EV << "[SimpleUDP::unbind() @ " << sd->localAddr << "]\n" 00192 << " Unbinding socket: " << *sd 00193 << endl; 00194 00195 // remove from socketsByPortMap 00196 SockDescList& list = socketsByPortMap[sd->localPort]; 00197 for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it) 00198 if (*it == sd) { 00199 list.erase(it); 00200 break; 00201 } 00202 if (list.empty()) 00203 socketsByPortMap.erase(sd->localPort); 00204 delete sd; 00205 }
short SimpleUDP::getEphemeralPort | ( | ) | [protected] |
ephemeral port.
00208 { 00209 // start at the last allocated port number + 1, and search for an unused one 00210 short searchUntil = lastEphemeralPort++; 00211 if (lastEphemeralPort == EPHEMERAL_PORTRANGE_END) // wrap 00212 lastEphemeralPort = EPHEMERAL_PORTRANGE_START; 00213 00214 while (socketsByPortMap.find(lastEphemeralPort)!=socketsByPortMap.end()) { 00215 if (lastEphemeralPort == searchUntil) // got back to starting point? 00216 error("Ephemeral port range %d..%d exhausted, all ports occupied", EPHEMERAL_PORTRANGE_START, EPHEMERAL_PORTRANGE_END); 00217 lastEphemeralPort++; 00218 if (lastEphemeralPort == EPHEMERAL_PORTRANGE_END) // wrap 00219 lastEphemeralPort = EPHEMERAL_PORTRANGE_START; 00220 } 00221 00222 // found a free one, return it 00223 return lastEphemeralPort; 00224 }
bool SimpleUDP::matchesSocket | ( | SockDesc * | sd, | |
SimpleUDPPacket * | udp, | |||
IPControlInfo * | ctrl | |||
) | [protected] |
decides if a received packet (IPv4) belongs to the specified socket
sd | the socket | |
udp | the received SimpleUDPPacket | |
ctrl | the IPControlInfo of udp |
00258 { 00259 // IPv4 version 00260 if (sd->remotePort!=0 && sd->remotePort!=udp->sourcePort()) 00261 return false; 00262 if (!sd->localAddr.isUnspecified() && sd->localAddr.get4()!=ipCtrl->destAddr()) 00263 return false; 00264 if (!sd->remoteAddr.isUnspecified() && sd->remoteAddr.get4()!=ipCtrl->srcAddr()) 00265 return false; 00266 if (sd->interfaceId!=-1 && sd->interfaceId!=ipCtrl->interfaceId()) 00267 return false; 00268 return true; 00269 }
bool SimpleUDP::matchesSocket | ( | SockDesc * | sd, | |
SimpleUDPPacket * | udp, | |||
IPv6ControlInfo * | ctrl | |||
) | [protected] |
decides if a received packet (IPv6) belongs to the specified socket
sd | the socket | |
udp | the received SimpleUDPPacket | |
ctrl | the IPControlInfo of udp |
00272 { 00273 // IPv6 version 00274 if (sd->remotePort!=0 && sd->remotePort!=udp->sourcePort()) 00275 return false; 00276 if (!sd->localAddr.isUnspecified() && sd->localAddr.get6()!=ipCtrl->destAddr()) 00277 return false; 00278 if (!sd->remoteAddr.isUnspecified() && sd->remoteAddr.get6()!=ipCtrl->srcAddr()) 00279 return false; 00280 if (sd->interfaceId!=-1 && sd->interfaceId!=ipCtrl->interfaceId()) 00281 return false; 00282 return true; 00283 }
bool SimpleUDP::matchesSocket | ( | SockDesc * | sd, | |
const IPvXAddress & | localAddr, | |||
const IPvXAddress & | remoteAddr, | |||
short | remotePort | |||
) | [protected] |
decides if a socket matches the specified parameters
sd | the socket | |
localAddr | the specified localAddr | |
remoteAddr | the specified remoteAddr | |
remotePort | the specified remotePort |
00286 { 00287 return (sd->remotePort==0 || sd->remotePort!=remotePort) && 00288 (sd->localAddr.isUnspecified() || sd->localAddr==localAddr) && 00289 (sd->remoteAddr.isUnspecified() || sd->remoteAddr==remoteAddr); 00290 }
void SimpleUDP::sendUp | ( | cMessage * | payload, | |
SimpleUDPPacket * | udpHeader, | |||
IPControlInfo * | ctrl, | |||
SockDesc * | sd | |||
) | [protected] |
sends payload up to the application
payload | the payload | |
udpHeader | the udpHeader of the IPv4 message | |
ctrl | the IPControlInfo of the IPv4 message | |
sd | the socket at which the IPv4 message arrived |
00293 { 00294 // send payload with UDPControlInfo up to the application -- IPv4 version 00295 UDPControlInfo *udpCtrl = new UDPControlInfo(); 00296 udpCtrl->setSockId(sd->sockId); 00297 udpCtrl->setUserId(sd->userId); 00298 udpCtrl->setSrcAddr(ipCtrl->srcAddr()); 00299 udpCtrl->setDestAddr(ipCtrl->destAddr()); 00300 udpCtrl->setSrcPort(udpHeader->sourcePort()); 00301 udpCtrl->setDestPort(udpHeader->destinationPort()); 00302 udpCtrl->setInterfaceId(ipCtrl->interfaceId()); 00303 payload->setControlInfo(udpCtrl); 00304 00305 send(payload, "to_app", sd->appGateIndex); 00306 numPassedUp++; 00307 }
void SimpleUDP::sendUp | ( | cMessage * | payload, | |
SimpleUDPPacket * | udpHeader, | |||
IPv6ControlInfo * | ctrl, | |||
SockDesc * | sd | |||
) | [protected] |
sends payload up to the application
payload | the payload | |
udpHeader | the udpHeader of the IPv6 message | |
ctrl | the IPControlInfo of the IPv6 message | |
sd | the socket at which the IPv6 message arrived |
00310 { 00311 // send payload with UDPControlInfo up to the application -- IPv6 version 00312 UDPControlInfo *udpCtrl = new UDPControlInfo(); 00313 udpCtrl->setSockId(sd->sockId); 00314 udpCtrl->setUserId(sd->userId); 00315 udpCtrl->setSrcAddr(ipCtrl->srcAddr()); 00316 udpCtrl->setDestAddr(ipCtrl->destAddr()); 00317 udpCtrl->setSrcPort(udpHeader->sourcePort()); 00318 udpCtrl->setDestPort(udpHeader->destinationPort()); 00319 udpCtrl->setInterfaceId(ipCtrl->interfaceId()); 00320 payload->setControlInfo(udpCtrl); 00321 00322 send(payload, "to_app", sd->appGateIndex); 00323 numPassedUp++; 00324 }
void SimpleUDP::processUndeliverablePacket | ( | SimpleUDPPacket * | udpPacket, | |
cPolymorphic * | ctrl | |||
) | [protected] |
handles received packet which destination port is not bound to any socket
udpPacket | the SimpleUDPPacket with the wrong port number | |
ctrl | the IPControlInfo of udpPacket |
00327 { 00328 numDroppedWrongPort++; 00329 00330 // send back ICMP PORT_UNREACHABLE 00331 if (dynamic_cast<IPControlInfo *>(ctrl)!=NULL) { 00332 if (!icmp) 00333 icmp = ICMPAccess().get(); 00334 IPControlInfo *ctrl4 = (IPControlInfo *)ctrl; 00335 if (!ctrl4->destAddr().isMulticast()) 00336 icmp->sendErrorMessage(udpPacket, ctrl4, ICMP_DESTINATION_UNREACHABLE, ICMP_DU_PORT_UNREACHABLE); 00337 } else if (dynamic_cast<IPv6ControlInfo *>(udpPacket->controlInfo()) 00338 !=NULL) { 00339 if (!icmpv6) 00340 icmpv6 = ICMPv6Access().get(); 00341 IPv6ControlInfo *ctrl6 = (IPv6ControlInfo *)ctrl; 00342 if (!ctrl6->destAddr().isMulticast()) 00343 icmpv6->sendErrorMessage(udpPacket, ctrl6, ICMPv6_DESTINATION_UNREACHABLE, PORT_UNREACHABLE); 00344 } else { 00345 error("(%s)%s arrived from lower layer without control info", udpPacket->className(), udpPacket->name()); 00346 } 00347 }
void SimpleUDP::sendUpErrorNotification | ( | SockDesc * | sd, | |
int | msgkind, | |||
const IPvXAddress & | localAddr, | |||
const IPvXAddress & | remoteAddr, | |||
short | remotePort | |||
) | [protected] |
sends an error up to the application
sd | the socket that received the error | |
msgkind | the type of the error notification | |
localAddr | the address from which the faulty message was sent | |
remoteAddr | the address to which the faulty message was sent | |
remotePort | the port to which the faulty message was sent |
00423 { 00424 cMessage *notifyMsg = new cMessage("ERROR", msgkind); 00425 UDPControlInfo *udpCtrl = new UDPControlInfo(); 00426 udpCtrl->setSockId(sd->sockId); 00427 udpCtrl->setUserId(sd->userId); 00428 udpCtrl->setSrcAddr(localAddr); 00429 udpCtrl->setDestAddr(remoteAddr); 00430 udpCtrl->setSrcPort(sd->localPort); 00431 udpCtrl->setDestPort(remotePort); 00432 notifyMsg->setControlInfo(udpCtrl); 00433 00434 send(notifyMsg, "to_app", sd->appGateIndex); 00435 }
void SimpleUDP::processICMPError | ( | cMessage * | icmpErrorMsg | ) | [protected, virtual] |
process an ICMP error packet
icmpErrorMsg | the received icmp Message |
00350 { 00351 // extract details from the error message, then try to notify socket that sent bogus packet 00352 int type = 0; 00353 int code = 0; 00354 IPvXAddress localAddr, remoteAddr; 00355 int localPort = 0; 00356 int remotePort = 0; 00357 00358 if (dynamic_cast<ICMPMessage *>(msg)) { 00359 ICMPMessage *icmpMsg = (ICMPMessage *)msg; 00360 type = icmpMsg->getType(); 00361 code = icmpMsg->getCode(); 00362 icmpMsg->setLength(icmpMsg->encapsulatedMsg()->length()); // trick because payload in ICMP is conceptually truncated 00363 IPDatagram *datagram = check_and_cast<IPDatagram *>(icmpMsg->decapsulate()); 00364 localAddr = datagram->srcAddress(); 00365 remoteAddr = datagram->destAddress(); 00366 SimpleUDPPacket *packet = check_and_cast<SimpleUDPPacket *>(datagram->decapsulate()); 00367 localPort = packet->sourcePort(); 00368 remotePort = packet->destinationPort(); 00369 delete icmpMsg; 00370 delete datagram; 00371 delete packet; 00372 } else if (dynamic_cast<ICMPv6Message *>(msg)) { 00373 ICMPv6Message *icmpMsg = (ICMPv6Message *)msg; 00374 type = icmpMsg->type(); 00375 code = -1; // FIXME this is dependent on type()... 00376 IPv6Datagram *datagram = check_and_cast<IPv6Datagram *>(icmpMsg->decapsulate()); 00377 localAddr = datagram->srcAddress(); 00378 remoteAddr = datagram->destAddress(); 00379 SimpleUDPPacket *packet = check_and_cast<SimpleUDPPacket *>(datagram->decapsulate()); 00380 localPort = packet->sourcePort(); 00381 remotePort = packet->destinationPort(); 00382 delete icmpMsg; 00383 delete datagram; 00384 delete packet; 00385 } 00386 EV << "[SimpleUDP::processICMPError() @ " << localAddr << "]\n" 00387 << " ICMP error received: type=" << type << " code=" << code 00388 << "\n about packet " << localAddr << ":" << localPort << " --> " 00389 << " " << remoteAddr << ":" << remotePort 00390 << endl; 00391 00392 // identify socket and report error to it 00393 SocketsByPortMap::iterator it = socketsByPortMap.find(localPort); 00394 if (it==socketsByPortMap.end()) { 00395 EV << "[SimpleUDP::processICMPError() @ " << localAddr << "]\n" 00396 << " No socket on that local port, ignoring ICMP error" 00397 << endl; 00398 return; 00399 } 00400 SockDescList& list = it->second; 00401 SockDesc *srcSocket = NULL; 00402 for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it) { 00403 SockDesc *sd = *it; 00404 if (sd->onlyLocalPortIsSet || matchesSocket(sd, localAddr, remoteAddr, remotePort)) { 00405 srcSocket = sd; // FIXME what to do if there's more than one matching socket ??? 00406 } 00407 } 00408 if (!srcSocket) { 00409 EV << "[SimpleUDP::processICMPError() @ " << localAddr << "]\n" 00410 << " No matching socket, ignoring ICMP error" 00411 << endl; 00412 return; 00413 } 00414 00415 // send UDP_I_ERROR to socket 00416 EV << "[SimpleUDP::processICMPError() @ " << localAddr << "]\n" 00417 << " Source socket is sockId=" << srcSocket->sockId << ", notifying" 00418 << endl; 00419 sendUpErrorNotification(srcSocket, UDP_I_ERROR, localAddr, remoteAddr, remotePort); 00420 }
void SimpleUDP::processUDPPacket | ( | SimpleUDPPacket * | udpPacket | ) | [protected, virtual] |
process UDP packets coming from IP
udpPacket | the received packet |
00438 { 00439 cModule *node = parentModule(); 00440 IPvXAddress ip = IPAddressResolver().addressOf(node); 00441 00442 // simulate checksum: discard packet if it has bit error 00443 EV << "[SimpleUDP::processUDPPacket() @ " << ip << "]\n" 00444 << " Packet " << udpPacket->name() << " received from network, dest port " << udpPacket->destinationPort() 00445 << endl; 00446 00447 if (udpPacket->hasBitError()) { 00448 EV << "[SimpleUDP::processUDPPacket() @ " << ip << "]\n" 00449 << " Packet has bit error, discarding" 00450 << endl; 00451 delete udpPacket; 00452 numDroppedBadChecksum++; 00453 return; 00454 } 00455 00456 int destPort = udpPacket->destinationPort(); 00457 cPolymorphic *ctrl = udpPacket->removeControlInfo(); 00458 00459 // send back ICMP error if no socket is bound to that port 00460 SocketsByPortMap::iterator it = socketsByPortMap.find(destPort); 00461 if (it==socketsByPortMap.end()) { 00462 EV << "[SimpleUDP::processUDPPacket() @ " << ip << "]\n" 00463 << " No socket registered on port " << destPort 00464 << endl; 00465 processUndeliverablePacket(udpPacket, ctrl); 00466 return; 00467 } 00468 SockDescList& list = it->second; 00469 00470 int matches = 0; 00471 00472 // deliver a copy of the packet to each matching socket 00473 // cMessage *payload = udpPacket->encapsulatedMsg(); 00474 cMessage *payload = udpPacket->decapsulate(); 00475 if (dynamic_cast<IPControlInfo *>(ctrl)!=NULL) { 00476 IPControlInfo *ctrl4 = (IPControlInfo *)ctrl; 00477 for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it) { 00478 SockDesc *sd = *it; 00479 if (sd->onlyLocalPortIsSet || matchesSocket(sd, udpPacket, ctrl4)) { 00480 // EV << "[SimpleUDP::processUDPPacket() @ " << ip << "]\n" 00481 // << " Socket sockId=" << sd->sockId << " matches, sending up a copy" 00482 // << endl; 00483 // sendUp((cMessage*)payload->dup(), udpPacket, ctrl4, sd); 00484 // ib: speed hack 00485 00486 if (matches == 0) { 00487 sendUp(payload, udpPacket, ctrl4, sd); 00488 } else 00489 opp_error("Edit SimpleUDP.cc to support multibinding."); 00490 matches++; 00491 } 00492 } 00493 } else if (dynamic_cast<IPv6ControlInfo *>(udpPacket->controlInfo()) 00494 !=NULL) { 00495 IPv6ControlInfo *ctrl6 = (IPv6ControlInfo *)ctrl; 00496 for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it) { 00497 SockDesc *sd = *it; 00498 if (sd->onlyLocalPortIsSet || matchesSocket(sd, udpPacket, ctrl6)) { 00499 EV << "[SimpleUDP::processUDPPacket() @ " << ip << "]\n" 00500 << " Socket sockId=" << sd->sockId << " matches, sending up a copy" 00501 << endl; 00502 sendUp((cMessage*)payload->dup(), udpPacket, ctrl6, sd); 00503 matches++; 00504 } 00505 } 00506 } else { 00507 error("(%s)%s arrived from lower layer without control info", udpPacket->className(), udpPacket->name()); 00508 } 00509 00510 // send back ICMP error if there is no matching socket 00511 if (matches==0) { 00512 EV << "[SimpleUDP::processUDPPacket() @ " << ip << "]\n" 00513 << " None of the sockets on port " << destPort << " matches the packet" 00514 << endl; 00515 processUndeliverablePacket(udpPacket, ctrl) 00516 ; 00517 return; 00518 } 00519 00520 delete udpPacket; 00521 delete ctrl; 00522 }
void SimpleUDP::processMsgFromApp | ( | cMessage * | appData | ) | [protected, virtual] |
process packets from application
appData | the data that has to be sent |
00526 { 00527 cModule *node = parentModule(); 00528 IPvXAddress ip = IPAddressResolver().addressOf(node); 00529 00530 IPvXAddress srcAddr, destAddr; 00531 //cGate* destGate; 00532 00533 UDPControlInfo *udpCtrl = check_and_cast<UDPControlInfo *>(appData->removeControlInfo()); 00534 00535 SimpleUDPPacket *udpPacket = new SimpleUDPPacket(appData->name()); 00536 00537 // 00538 udpPacket->setByteLength(UDP_HEADER_BYTES + IP_HEADER_BYTES); 00539 udpPacket->encapsulate(appData); 00540 00541 // set source and destination port 00542 udpPacket->setSourcePort(udpCtrl->srcPort()); 00543 udpPacket->setDestinationPort(udpCtrl->destPort()); 00544 00545 srcAddr = udpCtrl->srcAddr(); 00546 destAddr = udpCtrl->destAddr(); 00547 if (!udpCtrl->destAddr().isIPv6()) { 00548 // send to IPv4 00549 //EV << "[SimpleUDP::processMsgFromApp() @ " << ip << "]\n" 00550 //<< " Sending app packet " << appData->name() << " over IPv4" 00551 //<< endl; 00552 IPControlInfo *ipControlInfo = new IPControlInfo(); 00553 ipControlInfo->setProtocol(IP_PROT_UDP); 00554 ipControlInfo->setSrcAddr(srcAddr.get4()); 00555 ipControlInfo->setDestAddr(destAddr.get4()); 00556 ipControlInfo->setInterfaceId(udpCtrl->interfaceId()); 00557 udpPacket->setControlInfo(ipControlInfo); 00558 delete udpCtrl; 00559 } else { 00560 // send to IPv6 00561 //EV << "[SimpleUDP::processMsgFromApp() @ " << ip << "]\n" 00562 //<< " Sending app packet " << appData->name() << " over IPv6" 00563 //<< endl; 00564 IPv6ControlInfo *ipControlInfo = new IPv6ControlInfo(); 00565 ipControlInfo->setProtocol(IP_PROT_UDP); 00566 ipControlInfo->setSrcAddr(srcAddr.get6()); 00567 ipControlInfo->setDestAddr(destAddr.get6()); 00568 // ipControlInfo->setInterfaceId(udpCtrl->InterfaceId()); FIXME extend IPv6 with this!!! 00569 udpPacket->setControlInfo(ipControlInfo); 00570 delete udpCtrl; 00571 } 00572 00573 SimpleInfo* info = dynamic_cast<SimpleInfo*>(bootstrapOracle->getPeerInfo(destAddr)); 00574 numSent++; 00575 if(info == NULL) { 00576 EV << "[SimpleUDP::processMsgFromApp() @ " << ip << "]\n" 00577 << " No route to host " << destAddr 00578 << endl; 00579 delete udpPacket->removeControlInfo(); 00580 delete udpPacket; 00581 return; 00582 } 00583 00584 SimpleNodeEntry* destEntry = info->getEntry(); 00585 00586 // calculate delay 00587 float totalDelay = 0; 00588 if(srcAddr != destAddr) { 00589 if (useCoordinateBasedDelay == true) { 00590 SimpleNodeEntry::SimpleDelay temp = nodeEntry->calcDelay(*udpPacket, *destEntry); 00591 if (temp.second == false) { 00592 EV << "[SimpleUDP::processMsgFromApp() @ " << ip << "]\n" 00593 << " Send queue full/send error: packet " << udpPacket << " dropped" 00594 << endl; 00595 delete udpPacket; 00596 udpPacket = NULL; 00597 } else 00598 totalDelay = temp.first; 00599 } else 00600 totalDelay = constantDelay; 00601 } 00602 00603 if(udpPacket != NULL) { 00604 EV << "[SimpleUDP::processMsgFromApp() @ " << ip << "]\n" 00605 << " Packet " << udpPacket << " sent with delay = " << totalDelay 00606 << endl; 00607 sendDirect(udpPacket, totalDelay, destEntry->getGate()); 00608 } 00609 }
void SimpleUDP::processCommandFromApp | ( | cMessage * | msg | ) | [protected, virtual] |
process commands from application
msg | the command message |
00612 { 00613 UDPControlInfo *udpCtrl = check_and_cast<UDPControlInfo *>(msg->removeControlInfo()); 00614 switch (msg->kind()) { 00615 case UDP_C_BIND: 00616 bind(msg->arrivalGate()->index(), udpCtrl); 00617 break; 00618 case UDP_C_CONNECT: 00619 connect(udpCtrl->sockId(), udpCtrl->destAddr(), udpCtrl->destPort()); 00620 break; 00621 case UDP_C_UNBIND: 00622 unbind(udpCtrl->sockId()); 00623 break; 00624 default: 00625 error("unknown command code (message kind) %d received from app", msg->kind()); 00626 } 00627 00628 delete udpCtrl; 00629 delete msg; 00630 }
void SimpleUDP::initialize | ( | int | stage | ) | [protected, virtual] |
initialise the SimpleUDP module
stage | stage of initialisation phase |
00093 { 00094 if(stage == MIN_STAGE_UNDERLAY) { 00095 WATCH_PTRMAP(socketsByIdMap); 00096 WATCH_MAP(socketsByPortMap); 00097 00098 lastEphemeralPort = EPHEMERAL_PORTRANGE_START; 00099 icmp = NULL; 00100 icmpv6 = NULL; 00101 00102 numSent = 0; 00103 numPassedUp = 0; 00104 numDroppedWrongPort = 0; 00105 numDroppedBadChecksum = 0; 00106 WATCH(numSent); 00107 WATCH(numPassedUp); 00108 WATCH(numDroppedWrongPort); 00109 WATCH(numDroppedBadChecksum); 00110 00111 //} else if (stage == MAX_STAGE_UNDERLAY) { 00112 bootstrapOracle = BootstrapOracleAccess().get(); 00113 constantDelay = par("constantDelay"); 00114 useCoordinateBasedDelay = par("useCoordinateBasedDelay"); 00115 nodeEntry = NULL; 00116 WATCH_PTR(nodeEntry); 00117 } 00118 }
virtual int SimpleUDP::numInitStages | ( | void | ) | const [inline, protected, virtual] |
returns the number of init stages
00266 { 00267 return MAX_STAGE_UNDERLAY + 1; 00268 }
void SimpleUDP::handleMessage | ( | cMessage * | msg | ) | [protected, virtual] |
process received messages
msg | the received message |
00227 { 00228 // received from the network layer 00229 if (msg->arrivedOn("network_in")) { 00230 if (dynamic_cast<ICMPMessage *>(msg) || dynamic_cast<ICMPv6Message *>(msg)) 00231 processICMPError(msg); 00232 else 00233 processUDPPacket(check_and_cast<SimpleUDPPacket *>(msg)); 00234 } else // received from application layer 00235 { 00236 if (msg->kind()==UDP_C_DATA) 00237 processMsgFromApp(msg); 00238 else 00239 processCommandFromApp(msg); 00240 } 00241 00242 if (ev.isGUI()) 00243 updateDisplayString(); 00244 }
SocketsByIdMap SimpleUDP::socketsByIdMap [protected] |
list of socket ordered by sockId
SocketsByPortMap SimpleUDP::socketsByPortMap [protected] |
list of sockets ordered by localPort
short SimpleUDP::lastEphemeralPort [protected] |
last used port (all ports above should be free)
ICMP* SimpleUDP::icmp [protected] |
pointer to a received icmp (IPv4) message
ICMPv6* SimpleUDP::icmpv6 [protected] |
pointer to a received icmp (IPv6) message
int SimpleUDP::numSent [protected] |
number of packets sent to the network
int SimpleUDP::numPassedUp [protected] |
number of packet passed up to applications
int SimpleUDP::numDroppedWrongPort [protected] |
number of dropped packets due to wrong destination port
int SimpleUDP::numDroppedBadChecksum [protected] |
number of dropped packets due to bad checksum
simtime_t SimpleUDP::delay [protected] |
simulated delay between sending and receiving udp module
simtime_t SimpleUDP::constantDelay [protected] |
constant delay between two peers
bool SimpleUDP::useCoordinateBasedDelay [protected] |
delay should be calculated from euklidean distance between two peers
BootstrapOracle* SimpleUDP::bootstrapOracle [protected] |
pointer to BootstrapOracle
SimpleNodeEntry* SimpleUDP::nodeEntry [protected] |
nodeEntry of the overlay node this module belongs to