#include <UDP.h>
More info in the NED file.
Public Types | |
| typedef std::list< SockDesc * > | SockDescList |
| typedef std::map< int, SockDesc * > | SocketsByIdMap |
| typedef std::map< int, SockDescList > | SocketsByPortMap |
Public Member Functions | |
| UDP () | |
| virtual | ~UDP () |
Protected Member Functions | |
| void | updateDisplayString () |
| void | bind (int gateIndex, UDPControlInfo *ctrl) |
| void | connect (int sockId, IPvXAddress addr, int port) |
| void | unbind (int sockId) |
| short | getEphemeralPort () |
| bool | matchesSocket (SockDesc *sd, UDPPacket *udp, IPControlInfo *ctrl) |
| bool | matchesSocket (SockDesc *sd, UDPPacket *udp, IPv6ControlInfo *ctrl) |
| bool | matchesSocket (SockDesc *sd, const IPvXAddress &localAddr, const IPvXAddress &remoteAddr, short remotePort) |
| void | sendUp (cMessage *payload, UDPPacket *udpHeader, IPControlInfo *ctrl, SockDesc *sd) |
| void | sendUp (cMessage *payload, UDPPacket *udpHeader, IPv6ControlInfo *ctrl, SockDesc *sd) |
| void | processUndeliverablePacket (UDPPacket *udpPacket, cPolymorphic *ctrl) |
| void | sendUpErrorNotification (SockDesc *sd, int msgkind, const IPvXAddress &localAddr, const IPvXAddress &remoteAddr, short remotePort) |
| virtual void | processICMPError (cMessage *icmpErrorMsg) |
| virtual void | processUDPPacket (UDPPacket *udpPacket) |
| virtual void | processMsgFromApp (cMessage *appData) |
| virtual void | processCommandFromApp (cMessage *msg) |
| virtual void | initialize () |
| virtual void | handleMessage (cMessage *msg) |
Protected Attributes | |
| SocketsByIdMap | socketsByIdMap |
| SocketsByPortMap | socketsByPortMap |
| short | lastEphemeralPort |
| ICMP * | icmp |
| ICMPv6 * | icmpv6 |
| int | numSent |
| int | numPassedUp |
| int | numDroppedWrongPort |
| int | numDroppedBadChecksum |
Classes | |
| struct | SockDesc |
|
|
|
|
|
|
|
|
|
|
|
00120 {}
|
|
|
00077 {
00078 for (SocketsByIdMap::iterator i=socketsByIdMap.begin(); i!=socketsByIdMap.end(); ++i)
00079 delete i->second;
00080 }
|
|
||||||||||||
|
00102 {
00103 // XXX checks could be added, of when the bind should be allowed to proceed
00104
00105 // create and fill in SockDesc
00106 SockDesc *sd = new SockDesc();
00107 sd->sockId = ctrl->sockId();
00108 sd->userId = ctrl->userId();
00109 sd->appGateIndex = gateIndex;
00110 sd->localAddr = ctrl->srcAddr();
00111 sd->remoteAddr = ctrl->destAddr();
00112 sd->localPort = ctrl->srcPort();
00113 sd->remotePort = ctrl->destPort();
00114 sd->interfaceId = ctrl->interfaceId();
00115
00116 if (sd->sockId==-1)
00117 error("sockId in BIND message not filled in");
00118 if (sd->localPort==0)
00119 sd->localPort = getEphemeralPort();
00120
00121 sd->onlyLocalPortIsSet = sd->localAddr.isUnspecified() &&
00122 sd->remoteAddr.isUnspecified() &&
00123 sd->remotePort==0 &&
00124 sd->interfaceId==-1;
00125
00126 EV << "Binding socket: " << *sd << "\n";
00127
00128 // add to socketsByIdMap
00129 ASSERT(socketsByIdMap.find(sd->sockId)==socketsByIdMap.end());
00130 socketsByIdMap[sd->sockId] = sd;
00131
00132 // add to socketsByPortMap
00133 SockDescList& list = socketsByPortMap[sd->localPort]; // create if doesn't exist
00134 list.push_back(sd);
00135 }
|
|
||||||||||||||||
|
00138 {
00139 SocketsByIdMap::iterator it = socketsByIdMap.find(sockId);
00140 if (it==socketsByIdMap.end())
00141 error("socket id=%d doesn't exist (already closed?)", sockId);
00142 if (addr.isUnspecified())
00143 opp_error("connect: unspecified remote address");
00144 if (port<=0 || port>65535)
00145 opp_error("connect: invalid remote port number %d", port);
00146
00147 SockDesc *sd = it->second;
00148 sd->remoteAddr = addr;
00149 sd->remotePort = port;
00150
00151 sd->onlyLocalPortIsSet = false;
00152
00153 EV << "Connecting socket: " << *sd << "\n";
00154 }
|
|
|
00178 {
00179 // start at the last allocated port number + 1, and search for an unused one
00180 short searchUntil = lastEphemeralPort++;
00181 if (lastEphemeralPort == EPHEMERAL_PORTRANGE_END) // wrap
00182 lastEphemeralPort = EPHEMERAL_PORTRANGE_START;
00183
00184 while (socketsByPortMap.find(lastEphemeralPort)!=socketsByPortMap.end())
00185 {
00186 if (lastEphemeralPort == searchUntil) // got back to starting point?
00187 error("Ephemeral port range %d..%d exhausted, all ports occupied", EPHEMERAL_PORTRANGE_START, EPHEMERAL_PORTRANGE_END);
00188 lastEphemeralPort++;
00189 if (lastEphemeralPort == EPHEMERAL_PORTRANGE_END) // wrap
00190 lastEphemeralPort = EPHEMERAL_PORTRANGE_START;
00191 }
00192
00193 // found a free one, return it
00194 return lastEphemeralPort;
00195 }
|
|
|
00198 {
00199 // received from IP layer
00200 if (msg->arrivedOn("from_ip") || msg->arrivedOn("from_ipv6"))
00201 {
00202 if (dynamic_cast<ICMPMessage *>(msg) || dynamic_cast<ICMPv6Message *>(msg))
00203 processICMPError(msg);
00204 else
00205 processUDPPacket(check_and_cast<UDPPacket *>(msg));
00206 }
00207 else // received from application layer
00208 {
00209 if (msg->kind()==UDP_C_DATA)
00210 processMsgFromApp(msg);
00211 else
00212 processCommandFromApp(msg);
00213 }
00214
00215 if (ev.isGUI())
00216 updateDisplayString();
00217 }
|
|
|
00083 {
00084 WATCH_PTRMAP(socketsByIdMap);
00085 WATCH_MAP(socketsByPortMap);
00086
00087 lastEphemeralPort = EPHEMERAL_PORTRANGE_START;
00088 icmp = NULL;
00089 icmpv6 = NULL;
00090
00091 numSent = 0;
00092 numPassedUp = 0;
00093 numDroppedWrongPort = 0;
00094 numDroppedBadChecksum = 0;
00095 WATCH(numSent);
00096 WATCH(numPassedUp);
00097 WATCH(numDroppedWrongPort);
00098 WATCH(numDroppedBadChecksum);
00099 }
|
|
||||||||||||||||||||
|
00260 {
00261 return (sd->remotePort==0 || sd->remotePort!=remotePort) &&
00262 (sd->localAddr.isUnspecified() || sd->localAddr==localAddr) &&
00263 (sd->remoteAddr.isUnspecified() || sd->remoteAddr==remoteAddr);
00264 }
|
|
||||||||||||||||
|
00246 {
00247 // IPv6 version
00248 if (sd->remotePort!=0 && sd->remotePort!=udp->sourcePort())
00249 return false;
00250 if (!sd->localAddr.isUnspecified() && sd->localAddr.get6()!=ipCtrl->destAddr())
00251 return false;
00252 if (!sd->remoteAddr.isUnspecified() && sd->remoteAddr.get6()!=ipCtrl->srcAddr())
00253 return false;
00254 if (sd->interfaceId!=-1 && sd->interfaceId!=ipCtrl->interfaceId())
00255 return false;
00256 return true;
00257 }
|
|
||||||||||||||||
|
00232 {
00233 // IPv4 version
00234 if (sd->remotePort!=0 && sd->remotePort!=udp->sourcePort())
00235 return false;
00236 if (!sd->localAddr.isUnspecified() && sd->localAddr.get4()!=ipCtrl->destAddr())
00237 return false;
00238 if (!sd->remoteAddr.isUnspecified() && sd->remoteAddr.get4()!=ipCtrl->srcAddr())
00239 return false;
00240 if (sd->interfaceId!=-1 && sd->interfaceId!=ipCtrl->interfaceId())
00241 return false;
00242 return true;
00243 }
|
|
|
00531 {
00532 UDPControlInfo *udpCtrl = check_and_cast<UDPControlInfo *>(msg->removeControlInfo());
00533 switch (msg->kind())
00534 {
00535 case UDP_C_BIND:
00536 bind(msg->arrivalGate()->index(), udpCtrl);
00537 break;
00538 case UDP_C_CONNECT:
00539 connect(udpCtrl->sockId(), udpCtrl->destAddr(), udpCtrl->destPort());
00540 break;
00541 case UDP_C_UNBIND:
00542 unbind(udpCtrl->sockId());
00543 break;
00544 default:
00545 error("unknown command code (message kind) %d received from app", msg->kind());
00546 }
00547
00548 delete udpCtrl;
00549 delete msg;
00550 }
|
|
|
00328 {
00329 // extract details from the error message, then try to notify socket that sent bogus packet
00330 int type, code;
00331 IPvXAddress localAddr, remoteAddr;
00332 int localPort, remotePort;
00333
00334 if (dynamic_cast<ICMPMessage *>(msg))
00335 {
00336 ICMPMessage *icmpMsg = (ICMPMessage *)msg;
00337 type = icmpMsg->getType();
00338 code = icmpMsg->getCode();
00339 icmpMsg->setLength(icmpMsg->encapsulatedMsg()->length()); // trick because payload in ICMP is conceptually truncated
00340 IPDatagram *datagram = check_and_cast<IPDatagram *>(icmpMsg->decapsulate());
00341 localAddr = datagram->srcAddress();
00342 remoteAddr = datagram->destAddress();
00343 UDPPacket *packet = check_and_cast<UDPPacket *>(datagram->decapsulate());
00344 localPort = packet->sourcePort();
00345 remotePort = packet->destinationPort();
00346 delete icmpMsg;
00347 delete datagram;
00348 delete packet;
00349 }
00350 else if (dynamic_cast<ICMPv6Message *>(msg))
00351 {
00352 ICMPv6Message *icmpMsg = (ICMPv6Message *)msg;
00353 type = icmpMsg->type();
00354 code = -1; // FIXME this is dependent on type()...
00355 IPv6Datagram *datagram = check_and_cast<IPv6Datagram *>(icmpMsg->decapsulate());
00356 localAddr = datagram->srcAddress();
00357 remoteAddr = datagram->destAddress();
00358 UDPPacket *packet = check_and_cast<UDPPacket *>(datagram->decapsulate());
00359 localPort = packet->sourcePort();
00360 remotePort = packet->destinationPort();
00361 delete icmpMsg;
00362 delete datagram;
00363 delete packet;
00364 }
00365 EV << "ICMP error received: type=" << type << " code=" << code
00366 << " about packet " << localAddr << ":" << localPort << " > "
00367 << remoteAddr << ":" << remotePort << "\n";
00368
00369 // identify socket and report error to it
00370 SocketsByPortMap::iterator it = socketsByPortMap.find(localPort);
00371 if (it==socketsByPortMap.end())
00372 {
00373 EV << "No socket on that local port, ignoring ICMP error\n";
00374 return;
00375 }
00376 SockDescList& list = it->second;
00377 SockDesc *srcSocket = NULL;
00378 for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it)
00379 {
00380 SockDesc *sd = *it;
00381 if (sd->onlyLocalPortIsSet || matchesSocket(sd, localAddr, remoteAddr, remotePort))
00382 {
00383 srcSocket = sd; // FIXME what to do if there's more than one matching socket ???
00384 }
00385 }
00386 if (!srcSocket)
00387 {
00388 EV << "No matching socket, ignoring ICMP error\n";
00389 return;
00390 }
00391
00392 // send UDP_I_ERROR to socket
00393 EV << "Source socket is sockId=" << srcSocket->sockId << ", notifying.\n";
00394 sendUpErrorNotification(srcSocket, UDP_I_ERROR, localAddr, remoteAddr, remotePort);
00395 }
|
|
|
00488 {
00489 UDPControlInfo *udpCtrl = check_and_cast<UDPControlInfo *>(appData->removeControlInfo());
00490
00491 UDPPacket *udpPacket = new UDPPacket(appData->name());
00492 udpPacket->setByteLength(UDP_HEADER_BYTES);
00493 udpPacket->encapsulate(appData);
00494
00495 // set source and destination port
00496 udpPacket->setSourcePort(udpCtrl->srcPort());
00497 udpPacket->setDestinationPort(udpCtrl->destPort());
00498
00499 if (!udpCtrl->destAddr().isIPv6())
00500 {
00501 // send to IPv4
00502 EV << "Sending app packet " << appData->name() << " over IPv4.\n";
00503 IPControlInfo *ipControlInfo = new IPControlInfo();
00504 ipControlInfo->setProtocol(IP_PROT_UDP);
00505 ipControlInfo->setSrcAddr(udpCtrl->srcAddr().get4());
00506 ipControlInfo->setDestAddr(udpCtrl->destAddr().get4());
00507 ipControlInfo->setInterfaceId(udpCtrl->interfaceId());
00508 udpPacket->setControlInfo(ipControlInfo);
00509 delete udpCtrl;
00510
00511 send(udpPacket,"to_ip");
00512 }
00513 else
00514 {
00515 // send to IPv6
00516 EV << "Sending app packet " << appData->name() << " over IPv6.\n";
00517 IPv6ControlInfo *ipControlInfo = new IPv6ControlInfo();
00518 ipControlInfo->setProtocol(IP_PROT_UDP);
00519 ipControlInfo->setSrcAddr(udpCtrl->srcAddr().get6());
00520 ipControlInfo->setDestAddr(udpCtrl->destAddr().get6());
00521 // ipControlInfo->setInterfaceId(udpCtrl->InterfaceId()); FIXME extend IPv6 with this!!!
00522 udpPacket->setControlInfo(ipControlInfo);
00523 delete udpCtrl;
00524
00525 send(udpPacket,"to_ipv6");
00526 }
00527 numSent++;
00528 }
|
|
|
00413 {
00414 // simulate checksum: discard packet if it has bit error
00415 EV << "Packet " << udpPacket->name() << " received from network, dest port " << udpPacket->destinationPort() << "\n";
00416 if (udpPacket->hasBitError())
00417 {
00418 EV << "Packet has bit error, discarding\n";
00419 delete udpPacket;
00420 numDroppedBadChecksum++;
00421 return;
00422 }
00423
00424 int destPort = udpPacket->destinationPort();
00425 cPolymorphic *ctrl = udpPacket->removeControlInfo();
00426
00427 // send back ICMP error if no socket is bound to that port
00428 SocketsByPortMap::iterator it = socketsByPortMap.find(destPort);
00429 if (it==socketsByPortMap.end())
00430 {
00431 EV << "No socket registered on port " << destPort << "\n";
00432 processUndeliverablePacket(udpPacket, ctrl);
00433 return;
00434 }
00435 SockDescList& list = it->second;
00436
00437 int matches = 0;
00438
00439 // deliver a copy of the packet to each matching socket
00440 cMessage *payload = udpPacket->encapsulatedMsg();
00441 if (dynamic_cast<IPControlInfo *>(ctrl)!=NULL)
00442 {
00443 IPControlInfo *ctrl4 = (IPControlInfo *)ctrl;
00444 for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it)
00445 {
00446 SockDesc *sd = *it;
00447 if (sd->onlyLocalPortIsSet || matchesSocket(sd, udpPacket, ctrl4))
00448 {
00449 EV << "Socket sockId=" << sd->sockId << " matches, sending up a copy.\n";
00450 sendUp((cMessage*)payload->dup(), udpPacket, ctrl4, sd);
00451 matches++;
00452 }
00453 }
00454 }
00455 else if (dynamic_cast<IPv6ControlInfo *>(udpPacket->controlInfo())!=NULL)
00456 {
00457 IPv6ControlInfo *ctrl6 = (IPv6ControlInfo *)ctrl;
00458 for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it)
00459 {
00460 SockDesc *sd = *it;
00461 if (sd->onlyLocalPortIsSet || matchesSocket(sd, udpPacket, ctrl6))
00462 {
00463 EV << "Socket sockId=" << sd->sockId << " matches, sending up a copy.\n";
00464 sendUp((cMessage*)payload->dup(), udpPacket, ctrl6, sd);
00465 matches++;
00466 }
00467 }
00468 }
00469 else
00470 {
00471 error("(%s)%s arrived from lower layer without control info", udpPacket->className(), udpPacket->name());
00472 }
00473
00474 // send back ICMP error if there is no matching socket
00475 if (matches==0)
00476 {
00477 EV << "None of the sockets on port " << destPort << " matches the packet\n";
00478 processUndeliverablePacket(udpPacket, ctrl);
00479 return;
00480 }
00481
00482 delete udpPacket;
00483 delete ctrl;
00484 }
|
|
||||||||||||
|
00301 {
00302 numDroppedWrongPort++;
00303
00304 // send back ICMP PORT_UNREACHABLE
00305 if (dynamic_cast<IPControlInfo *>(ctrl)!=NULL)
00306 {
00307 if (!icmp)
00308 icmp = ICMPAccess().get();
00309 IPControlInfo *ctrl4 = (IPControlInfo *)ctrl;
00310 if (!ctrl4->destAddr().isMulticast())
00311 icmp->sendErrorMessage(udpPacket, ctrl4, ICMP_DESTINATION_UNREACHABLE, ICMP_DU_PORT_UNREACHABLE);
00312 }
00313 else if (dynamic_cast<IPv6ControlInfo *>(udpPacket->controlInfo())!=NULL)
00314 {
00315 if (!icmpv6)
00316 icmpv6 = ICMPv6Access().get();
00317 IPv6ControlInfo *ctrl6 = (IPv6ControlInfo *)ctrl;
00318 if (!ctrl6->destAddr().isMulticast())
00319 icmpv6->sendErrorMessage(udpPacket, ctrl6, ICMPv6_DESTINATION_UNREACHABLE, PORT_UNREACHABLE);
00320 }
00321 else
00322 {
00323 error("(%s)%s arrived from lower layer without control info", udpPacket->className(), udpPacket->name());
00324 }
00325 }
|
|
||||||||||||||||||||
|
00284 {
00285 // send payload with UDPControlInfo up to the application -- IPv6 version
00286 UDPControlInfo *udpCtrl = new UDPControlInfo();
00287 udpCtrl->setSockId(sd->sockId);
00288 udpCtrl->setUserId(sd->userId);
00289 udpCtrl->setSrcAddr(ipCtrl->srcAddr());
00290 udpCtrl->setDestAddr(ipCtrl->destAddr());
00291 udpCtrl->setSrcPort(udpHeader->sourcePort());
00292 udpCtrl->setDestPort(udpHeader->destinationPort());
00293 udpCtrl->setInterfaceId(ipCtrl->interfaceId());
00294 payload->setControlInfo(udpCtrl);
00295
00296 send(payload, "to_app", sd->appGateIndex);
00297 numPassedUp++;
00298 }
|
|
||||||||||||||||||||
|
00267 {
00268 // send payload with UDPControlInfo up to the application -- IPv4 version
00269 UDPControlInfo *udpCtrl = new UDPControlInfo();
00270 udpCtrl->setSockId(sd->sockId);
00271 udpCtrl->setUserId(sd->userId);
00272 udpCtrl->setSrcAddr(ipCtrl->srcAddr());
00273 udpCtrl->setDestAddr(ipCtrl->destAddr());
00274 udpCtrl->setSrcPort(udpHeader->sourcePort());
00275 udpCtrl->setDestPort(udpHeader->destinationPort());
00276 udpCtrl->setInterfaceId(ipCtrl->interfaceId());
00277 payload->setControlInfo(udpCtrl);
00278
00279 send(payload, "to_app", sd->appGateIndex);
00280 numPassedUp++;
00281 }
|
|
||||||||||||||||||||||||
|
00398 {
00399 cMessage *notifyMsg = new cMessage("ERROR", msgkind);
00400 UDPControlInfo *udpCtrl = new UDPControlInfo();
00401 udpCtrl->setSockId(sd->sockId);
00402 udpCtrl->setUserId(sd->userId);
00403 udpCtrl->setSrcAddr(localAddr);
00404 udpCtrl->setDestAddr(remoteAddr);
00405 udpCtrl->setSrcPort(sd->localPort);
00406 udpCtrl->setDestPort(remotePort);
00407 notifyMsg->setControlInfo(udpCtrl);
00408
00409 send(notifyMsg, "to_app", sd->appGateIndex);
00410 }
|
|
|
00157 {
00158 // remove from socketsByIdMap
00159 SocketsByIdMap::iterator it = socketsByIdMap.find(sockId);
00160 if (it==socketsByIdMap.end())
00161 error("socket id=%d doesn't exist (already closed?)", sockId);
00162 SockDesc *sd = it->second;
00163 socketsByIdMap.erase(it);
00164
00165 EV << "Unbinding socket: " << *sd << "\n";
00166
00167 // remove from socketsByPortMap
00168 SockDescList& list = socketsByPortMap[sd->localPort];
00169 for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it)
00170 if (*it == sd)
00171 {list.erase(it); break;}
00172 if (list.empty())
00173 socketsByPortMap.erase(sd->localPort);
00174 delete sd;
00175 }
|
|
|
00220 {
00221 char buf[80];
00222 sprintf(buf, "passed up: %d pks\nsent: %d pks", numPassedUp, numSent);
00223 if (numDroppedWrongPort>0)
00224 {
00225 sprintf(buf+strlen(buf), "\ndropped (no app): %d pks", numDroppedWrongPort);
00226 displayString().setTagArg("i",1,"red");
00227 }
00228 displayString().setTagArg("t",0,buf);
00229 }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1.4.1