Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

UDP Class Reference

#include <UDP.h>

List of all members.


Detailed Description

Implements the UDP protocol: encapsulates/decapsulates user data into/from UDP.

More info in the NED file.


Public Types

typedef std::list< SockDesc * > SockDescList
typedef std::map< int, SockDesc * > SocketsByIdMap
typedef std::map< int, SockDescListSocketsByPortMap

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
ICMPicmp
ICMPv6icmpv6
int numSent
int numPassedUp
int numDroppedWrongPort
int numDroppedBadChecksum

Classes

struct  SockDesc


Member Typedef Documentation

typedef std::list<SockDesc *> UDP::SockDescList
 

typedef std::map<int,SockDesc *> UDP::SocketsByIdMap
 

typedef std::map<int,SockDescList> UDP::SocketsByPortMap
 


Constructor & Destructor Documentation

UDP::UDP  )  [inline]
 

00120 {}

UDP::~UDP  )  [virtual]
 

00077 {
00078     for (SocketsByIdMap::iterator i=socketsByIdMap.begin(); i!=socketsByIdMap.end(); ++i)
00079         delete i->second;
00080 }


Member Function Documentation

void UDP::bind int  gateIndex,
UDPControlInfo ctrl
[protected]
 

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 }

void UDP::connect int  sockId,
IPvXAddress  addr,
int  port
[protected]
 

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 }

short UDP::getEphemeralPort  )  [protected]
 

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 }

void UDP::handleMessage cMessage *  msg  )  [protected, virtual]
 

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 }

void UDP::initialize  )  [protected, virtual]
 

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 }

bool UDP::matchesSocket SockDesc sd,
const IPvXAddress localAddr,
const IPvXAddress remoteAddr,
short  remotePort
[protected]
 

00260 {
00261     return (sd->remotePort==0 || sd->remotePort!=remotePort) &&
00262            (sd->localAddr.isUnspecified() || sd->localAddr==localAddr) &&
00263            (sd->remoteAddr.isUnspecified() || sd->remoteAddr==remoteAddr);
00264 }

bool UDP::matchesSocket SockDesc sd,
UDPPacket udp,
IPv6ControlInfo ctrl
[protected]
 

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 }

bool UDP::matchesSocket SockDesc sd,
UDPPacket udp,
IPControlInfo ctrl
[protected]
 

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 }

void UDP::processCommandFromApp cMessage *  msg  )  [protected, virtual]
 

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 }

void UDP::processICMPError cMessage *  icmpErrorMsg  )  [protected, virtual]
 

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 }

void UDP::processMsgFromApp cMessage *  appData  )  [protected, virtual]
 

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 }

void UDP::processUDPPacket UDPPacket udpPacket  )  [protected, virtual]
 

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 }

void UDP::processUndeliverablePacket UDPPacket udpPacket,
cPolymorphic *  ctrl
[protected]
 

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 }

void UDP::sendUp cMessage *  payload,
UDPPacket udpHeader,
IPv6ControlInfo ctrl,
SockDesc sd
[protected]
 

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 }

void UDP::sendUp cMessage *  payload,
UDPPacket udpHeader,
IPControlInfo ctrl,
SockDesc sd
[protected]
 

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 }

void UDP::sendUpErrorNotification SockDesc sd,
int  msgkind,
const IPvXAddress localAddr,
const IPvXAddress remoteAddr,
short  remotePort
[protected]
 

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 }

void UDP::unbind int  sockId  )  [protected]
 

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 }

void UDP::updateDisplayString  )  [protected]
 

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 }


Member Data Documentation

ICMP* UDP::icmp [protected]
 

ICMPv6* UDP::icmpv6 [protected]
 

short UDP::lastEphemeralPort [protected]
 

int UDP::numDroppedBadChecksum [protected]
 

int UDP::numDroppedWrongPort [protected]
 

int UDP::numPassedUp [protected]
 

int UDP::numSent [protected]
 

SocketsByIdMap UDP::socketsByIdMap [protected]
 

SocketsByPortMap UDP::socketsByPortMap [protected]
 


The documentation for this class was generated from the following files:
Generated on Thu Oct 19 18:22:32 2006 for INET Framework for OMNeT++/OMNEST by  doxygen 1.4.0