#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 |
00665 { 00666 if(nodeEntry != NULL) 00667 delete nodeEntry; 00668 nodeEntry = new SimpleNodeEntry(entry); 00669 }
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 /* TODO: implement icmp module */ 00338 EV << "[SimpleUDP::processUndeliverablePacket()]\n" 00339 << " Dropped packet bound to unreserved port, ignoring ICMP error" 00340 << endl; 00341 } else if (dynamic_cast<IPv6ControlInfo *>(udpPacket->controlInfo()) 00342 !=NULL) { 00343 /* if (!icmpv6) 00344 icmpv6 = ICMPv6Access().get(); 00345 IPv6ControlInfo *ctrl6 = (IPv6ControlInfo *)ctrl; 00346 if (!ctrl6->destAddr().isMulticast()) 00347 icmpv6->sendErrorMessage(udpPacket, ctrl6, ICMPv6_DESTINATION_UNREACHABLE, PORT_UNREACHABLE);*/ 00348 /* TODO: implement icmp module */ 00349 EV << "[SimpleUDP::processUndeliverablePacket()]\n" 00350 << " Dropped packet bound to unreserved port, ignoring ICMP error" 00351 << endl; 00352 } else { 00353 error("(%s)%s arrived from lower layer without control info", udpPacket->className(), udpPacket->name()); 00354 } 00355 }
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 |
00431 { 00432 cMessage *notifyMsg = new cMessage("ERROR", msgkind); 00433 UDPControlInfo *udpCtrl = new UDPControlInfo(); 00434 udpCtrl->setSockId(sd->sockId); 00435 udpCtrl->setUserId(sd->userId); 00436 udpCtrl->setSrcAddr(localAddr); 00437 udpCtrl->setDestAddr(remoteAddr); 00438 udpCtrl->setSrcPort(sd->localPort); 00439 udpCtrl->setDestPort(remotePort); 00440 notifyMsg->setControlInfo(udpCtrl); 00441 00442 send(notifyMsg, "to_app", sd->appGateIndex); 00443 }
void SimpleUDP::processICMPError | ( | cMessage * | icmpErrorMsg | ) | [protected, virtual] |
process an ICMP error packet
icmpErrorMsg | the received icmp Message |
00358 { 00359 // extract details from the error message, then try to notify socket that sent bogus packet 00360 int type = 0; 00361 int code = 0; 00362 IPvXAddress localAddr, remoteAddr; 00363 int localPort = 0; 00364 int remotePort = 0; 00365 00366 if (dynamic_cast<ICMPMessage *>(msg)) { 00367 ICMPMessage *icmpMsg = (ICMPMessage *)msg; 00368 type = icmpMsg->getType(); 00369 code = icmpMsg->getCode(); 00370 icmpMsg->setLength(icmpMsg->encapsulatedMsg()->length()); // trick because payload in ICMP is conceptually truncated 00371 IPDatagram *datagram = check_and_cast<IPDatagram *>(icmpMsg->decapsulate()); 00372 localAddr = datagram->srcAddress(); 00373 remoteAddr = datagram->destAddress(); 00374 SimpleUDPPacket *packet = check_and_cast<SimpleUDPPacket *>(datagram->decapsulate()); 00375 localPort = packet->sourcePort(); 00376 remotePort = packet->destinationPort(); 00377 delete icmpMsg; 00378 delete datagram; 00379 delete packet; 00380 } else if (dynamic_cast<ICMPv6Message *>(msg)) { 00381 ICMPv6Message *icmpMsg = (ICMPv6Message *)msg; 00382 type = icmpMsg->type(); 00383 code = -1; // FIXME this is dependent on type()... 00384 IPv6Datagram *datagram = check_and_cast<IPv6Datagram *>(icmpMsg->decapsulate()); 00385 localAddr = datagram->srcAddress(); 00386 remoteAddr = datagram->destAddress(); 00387 SimpleUDPPacket *packet = check_and_cast<SimpleUDPPacket *>(datagram->decapsulate()); 00388 localPort = packet->sourcePort(); 00389 remotePort = packet->destinationPort(); 00390 delete icmpMsg; 00391 delete datagram; 00392 delete packet; 00393 } 00394 EV << "[SimpleUDP::processICMPError() @ " << localAddr << "]\n" 00395 << " ICMP error received: type=" << type << " code=" << code 00396 << "\n about packet " << localAddr << ":" << localPort << " --> " 00397 << " " << remoteAddr << ":" << remotePort 00398 << endl; 00399 00400 // identify socket and report error to it 00401 SocketsByPortMap::iterator it = socketsByPortMap.find(localPort); 00402 if (it==socketsByPortMap.end()) { 00403 EV << "[SimpleUDP::processICMPError() @ " << localAddr << "]\n" 00404 << " No socket on that local port, ignoring ICMP error" 00405 << endl; 00406 return; 00407 } 00408 SockDescList& list = it->second; 00409 SockDesc *srcSocket = NULL; 00410 for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it) { 00411 SockDesc *sd = *it; 00412 if (sd->onlyLocalPortIsSet || matchesSocket(sd, localAddr, remoteAddr, remotePort)) { 00413 srcSocket = sd; // FIXME what to do if there's more than one matching socket ??? 00414 } 00415 } 00416 if (!srcSocket) { 00417 EV << "[SimpleUDP::processICMPError() @ " << localAddr << "]\n" 00418 << " No matching socket, ignoring ICMP error" 00419 << endl; 00420 return; 00421 } 00422 00423 // send UDP_I_ERROR to socket 00424 EV << "[SimpleUDP::processICMPError() @ " << localAddr << "]\n" 00425 << " Source socket is sockId=" << srcSocket->sockId << ", notifying" 00426 << endl; 00427 sendUpErrorNotification(srcSocket, UDP_I_ERROR, localAddr, remoteAddr, remotePort); 00428 }
void SimpleUDP::processUDPPacket | ( | SimpleUDPPacket * | udpPacket | ) | [protected, virtual] |
process UDP packets coming from IP
udpPacket | the received packet |
00446 { 00447 cModule *node = parentModule(); 00448 // IPvXAddress ip = IPAddressResolver().addressOf(node); 00449 // Speedhack SK 00450 00451 // simulate checksum: discard packet if it has bit error 00452 EV << "[SimpleUDP::processUDPPacket() @ " << IPAddressResolver().addressOf(node) << "]\n" 00453 << " Packet " << udpPacket->name() << " received from network, dest port " << udpPacket->destinationPort() 00454 << endl; 00455 00456 if (udpPacket->hasBitError()) { 00457 EV << "[SimpleUDP::processUDPPacket() @ " << IPAddressResolver().addressOf(node) << "]\n" 00458 << " Packet has bit error, discarding" 00459 << endl; 00460 delete udpPacket; 00461 numDroppedBadChecksum++; 00462 return; 00463 } 00464 00465 int destPort = udpPacket->destinationPort(); 00466 cPolymorphic *ctrl = udpPacket->removeControlInfo(); 00467 00468 // send back ICMP error if no socket is bound to that port 00469 SocketsByPortMap::iterator it = socketsByPortMap.find(destPort); 00470 if (it==socketsByPortMap.end()) { 00471 EV << "[SimpleUDP::processUDPPacket() @ " << IPAddressResolver().addressOf(node) << "]\n" 00472 << " No socket registered on port " << destPort 00473 << endl; 00474 processUndeliverablePacket(udpPacket, ctrl); 00475 return; 00476 } 00477 SockDescList& list = it->second; 00478 00479 int matches = 0; 00480 00481 // deliver a copy of the packet to each matching socket 00482 // cMessage *payload = udpPacket->encapsulatedMsg(); 00483 cMessage *payload = udpPacket->decapsulate(); 00484 if (dynamic_cast<IPControlInfo *>(ctrl)!=NULL) { 00485 IPControlInfo *ctrl4 = (IPControlInfo *)ctrl; 00486 for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it) { 00487 SockDesc *sd = *it; 00488 if (sd->onlyLocalPortIsSet || matchesSocket(sd, udpPacket, ctrl4)) { 00489 // EV << "[SimpleUDP::processUDPPacket() @ " << IPAddressResolver().addressOf(node) << "]\n" 00490 // << " Socket sockId=" << sd->sockId << " matches, sending up a copy" 00491 // << endl; 00492 // sendUp((cMessage*)payload->dup(), udpPacket, ctrl4, sd); 00493 // ib: speed hack 00494 00495 if (matches == 0) { 00496 sendUp(payload, udpPacket, ctrl4, sd); 00497 } else 00498 opp_error("Edit SimpleUDP.cc to support multibinding."); 00499 matches++; 00500 } 00501 } 00502 } else if (dynamic_cast<IPv6ControlInfo *>(udpPacket->controlInfo()) 00503 !=NULL) { 00504 IPv6ControlInfo *ctrl6 = (IPv6ControlInfo *)ctrl; 00505 for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it) { 00506 SockDesc *sd = *it; 00507 if (sd->onlyLocalPortIsSet || matchesSocket(sd, udpPacket, ctrl6)) { 00508 EV << "[SimpleUDP::processUDPPacket() @ " << IPAddressResolver().addressOf(node) << "]\n" 00509 << " Socket sockId=" << sd->sockId << " matches, sending up a copy" 00510 << endl; 00511 sendUp((cMessage*)payload->dup(), udpPacket, ctrl6, sd); 00512 matches++; 00513 } 00514 } 00515 } else { 00516 error("(%s)%s arrived from lower layer without control info", udpPacket->className(), udpPacket->name()); 00517 } 00518 00519 // send back ICMP error if there is no matching socket 00520 if (matches==0) { 00521 EV << "[SimpleUDP::processUDPPacket() @ " << IPAddressResolver().addressOf(node) << "]\n" 00522 << " None of the sockets on port " << destPort << " matches the packet" 00523 << endl; 00524 processUndeliverablePacket(udpPacket, ctrl) 00525 ; 00526 return; 00527 } 00528 00529 delete udpPacket; 00530 delete ctrl; 00531 }
void SimpleUDP::processMsgFromApp | ( | cMessage * | appData | ) | [protected, virtual] |
process packets from application
appData | the data that has to be sent |
00535 { 00536 cModule *node = parentModule(); 00537 // IPvXAddress ip = IPAddressResolver().addressOf(node); 00538 // Speedhack SK 00539 00540 IPvXAddress srcAddr, destAddr; 00541 //cGate* destGate; 00542 00543 UDPControlInfo *udpCtrl = check_and_cast<UDPControlInfo *>(appData->removeControlInfo()); 00544 00545 SimpleUDPPacket *udpPacket = new SimpleUDPPacket(appData->name()); 00546 00547 // 00548 udpPacket->setByteLength(UDP_HEADER_BYTES + IP_HEADER_BYTES); 00549 udpPacket->encapsulate(appData); 00550 00551 // set source and destination port 00552 udpPacket->setSourcePort(udpCtrl->srcPort()); 00553 udpPacket->setDestinationPort(udpCtrl->destPort()); 00554 00555 srcAddr = udpCtrl->srcAddr(); 00556 destAddr = udpCtrl->destAddr(); 00557 if (!udpCtrl->destAddr().isIPv6()) { 00558 // send to IPv4 00559 //EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n" 00560 //<< " Sending app packet " << appData->name() << " over IPv4" 00561 //<< endl; 00562 IPControlInfo *ipControlInfo = new IPControlInfo(); 00563 ipControlInfo->setProtocol(IP_PROT_UDP); 00564 ipControlInfo->setSrcAddr(srcAddr.get4()); 00565 ipControlInfo->setDestAddr(destAddr.get4()); 00566 ipControlInfo->setInterfaceId(udpCtrl->interfaceId()); 00567 udpPacket->setControlInfo(ipControlInfo); 00568 delete udpCtrl; 00569 } else { 00570 // send to IPv6 00571 //EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n" 00572 //<< " Sending app packet " << appData->name() << " over IPv6" 00573 //<< endl; 00574 IPv6ControlInfo *ipControlInfo = new IPv6ControlInfo(); 00575 ipControlInfo->setProtocol(IP_PROT_UDP); 00576 ipControlInfo->setSrcAddr(srcAddr.get6()); 00577 ipControlInfo->setDestAddr(destAddr.get6()); 00578 // ipControlInfo->setInterfaceId(udpCtrl->InterfaceId()); FIXME extend IPv6 with this!!! 00579 udpPacket->setControlInfo(ipControlInfo); 00580 delete udpCtrl; 00581 } 00582 00583 SimpleInfo* info = dynamic_cast<SimpleInfo*>(bootstrapOracle->getPeerInfo(destAddr)); 00584 numSent++; 00585 00586 if(info == NULL) { 00587 EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n" 00588 << " No route to host " << destAddr 00589 << endl; 00590 delete udpPacket->removeControlInfo(); 00591 delete udpPacket; 00592 return; 00593 } 00594 00595 SimpleInfo* thisInfo = dynamic_cast<SimpleInfo*>(bootstrapOracle->getPeerInfo(srcAddr)); 00596 00597 if (!bootstrapOracle->areNodeTypesConnected(thisInfo->getTypeID(), info->getTypeID())) { 00598 EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n" 00599 << " Partition " << thisInfo->getTypeID() << "->" << info->getTypeID() 00600 << " is not connected" 00601 << endl; 00602 delete udpPacket->removeControlInfo(); 00603 delete udpPacket; 00604 return; 00605 } 00606 00607 SimpleNodeEntry* destEntry = info->getEntry(); 00608 00609 // calculate delay 00610 float totalDelay = 0; 00611 if (srcAddr != destAddr) { 00612 if (useCoordinateBasedDelay == true) { 00613 SimpleNodeEntry::SimpleDelay temp = nodeEntry->calcDelay(*udpPacket, *destEntry); 00614 if (temp.second == false) { 00615 EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n" 00616 << " Send queue full/send error: packet " << udpPacket << " dropped" 00617 << endl; 00618 delete udpPacket; 00619 udpPacket = NULL; 00620 } else 00621 totalDelay = temp.first; 00622 } else 00623 totalDelay = constantDelay; 00624 } 00625 00626 if (udpPacket != NULL) { 00627 BaseOverlayMessage* temp = NULL; 00628 00629 if (ev.isGUI() && udpPacket->encapsulatedMsg() && 00630 (temp = dynamic_cast<BaseOverlayMessage*>(udpPacket->encapsulatedMsg())) && 00631 temp->getSignaling()) { 00632 udpPacket->setKind(1); 00633 } 00634 00635 EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n" 00636 << " Packet " << udpPacket << " sent with delay = " << totalDelay 00637 << endl; 00638 sendDirect(udpPacket, totalDelay, destEntry->getGate()); 00639 } 00640 }
void SimpleUDP::processCommandFromApp | ( | cMessage * | msg | ) | [protected, virtual] |
process commands from application
msg | the command message |
00643 { 00644 UDPControlInfo *udpCtrl = check_and_cast<UDPControlInfo *>(msg->removeControlInfo()); 00645 switch (msg->kind()) { 00646 case UDP_C_BIND: 00647 bind(msg->arrivalGate()->index(), udpCtrl); 00648 break; 00649 case UDP_C_CONNECT: 00650 connect(udpCtrl->sockId(), udpCtrl->destAddr(), udpCtrl->destPort()); 00651 break; 00652 case UDP_C_UNBIND: 00653 unbind(udpCtrl->sockId()); 00654 break; 00655 default: 00656 error("unknown command code (message kind) %d received from app", msg->kind()); 00657 } 00658 00659 delete udpCtrl; 00660 delete msg; 00661 }
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