#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 }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|