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