SimpleUDP Class Reference

#include <SimpleUDP.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
 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
BootstrapOraclebootstrapOracle
 pointer to BootstrapOracle
SimpleNodeEntrynodeEntry
 nodeEntry of the overlay node this module belongs to

Classes

struct  SockDesc
 defines a socket More...


Member Typedef Documentation

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


Constructor & Destructor Documentation

SimpleUDP::SimpleUDP (  )  [inline]

constructor

00247     {}

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 }


Member Function Documentation

void SimpleUDP::setNodeEntry ( const SimpleNodeEntry entry  ) 

set or change the nodeEntry of this module

Parameters:
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

Parameters:
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

Parameters:
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

Parameters:
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.

Returns:
a free ephemeral port, if there is no free port, error is called
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

Parameters:
sd the socket
udp the received SimpleUDPPacket
ctrl the IPControlInfo of udp
Returns:
true if destination of the SimpleUDPPacket is the specified socket
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

Parameters:
sd the socket
udp the received SimpleUDPPacket
ctrl the IPControlInfo of udp
Returns:
true if destination of the SimpleUDPPacket is the specified socket
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

Parameters:
sd the socket
localAddr the specified localAddr
remoteAddr the specified remoteAddr
remotePort the specified remotePort
Returns:
true if specified parameters match the sockets parameters
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

Parameters:
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

Parameters:
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

Parameters:
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

Parameters:
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

Parameters:
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

Parameters:
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

Parameters:
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

Parameters:
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

Parameters:
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

Returns:
the number of init stages
00266     {
00267         return MAX_STAGE_UNDERLAY + 1;
00268     }

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

process received messages

Parameters:
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 }


Member Data Documentation

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


The documentation for this class was generated from the following files:
Generated on Thu Apr 17 13:19:30 2008 for ITM OverSim by  doxygen 1.5.3