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, SockDescListSocketsByPortMap
 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

00082 {
00083     for (SocketsByIdMap::iterator i=socketsByIdMap.begin();
00084          i!=socketsByIdMap.end(); ++i)
00085         delete i->second;
00086 
00087     if(nodeEntry)
00088         delete nodeEntry;
00089 }


Member Function Documentation

void SimpleUDP::setNodeEntry ( const SimpleNodeEntry entry  ) 

set or change the nodeEntry of this module

Parameters:
entry the new nodeEntry
00587 {
00588     if(nodeEntry != NULL)
00589         delete nodeEntry;
00590     nodeEntry = new SimpleNodeEntry(entry);
00591 }

void SimpleUDP::updateDisplayString (  )  [protected]

utility: show current statistics above the icon

00238 {
00239     char buf[80];
00240     sprintf(buf, "passed up: %d pks\nsent: %d pks", numPassedUp, numSent);
00241     if (numDroppedWrongPort>0) {
00242         sprintf(buf+strlen(buf), "\ndropped (no app): %d pks", numDroppedWrongPort);
00243         displayString().setTagArg("i",1,"red");
00244     }
00245     displayString().setTagArg("t",0,buf);
00246 }

void SimpleUDP::bind ( int  gateIndex,
UDPControlInfo *  ctrl 
) [protected]

bind socket

Parameters:
gateIndex application gate connected to the socket
ctrl control information for communication
00120 {
00121     // XXX checks could be added, of when the bind should be allowed to proceed
00122 
00123     // create and fill in SockDesc
00124     SockDesc *sd = new SockDesc();
00125     sd->sockId = ctrl->sockId();
00126     sd->userId = ctrl->userId();
00127     sd->appGateIndex = gateIndex;
00128     sd->localAddr = ctrl->srcAddr();
00129     sd->remoteAddr = ctrl->destAddr();
00130     sd->localPort = ctrl->srcPort();
00131     sd->remotePort = ctrl->destPort();
00132     sd->interfaceId = ctrl->interfaceId();
00133 
00134     if (sd->sockId==-1)
00135         error("sockId in BIND message not filled in");
00136     if (sd->localPort==0)
00137         sd->localPort = getEphemeralPort();
00138 
00139     sd->onlyLocalPortIsSet = sd->localAddr.isUnspecified() &&
00140                              sd->remoteAddr.isUnspecified() &&
00141                              sd->remotePort==0 &&
00142                              sd->interfaceId==-1;
00143 
00144     EV << "Binding socket: " << *sd << "\n";
00145 
00146     // add to socketsByIdMap
00147     ASSERT(socketsByIdMap.find(sd->sockId)==socketsByIdMap.end());
00148     socketsByIdMap[sd->sockId] = sd;
00149 
00150     // add to socketsByPortMap
00151     // create if doesn't exist
00152     SockDescList& list = socketsByPortMap[sd->localPort];
00153     list.push_back(sd);
00154 }

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
00157 {
00158     SocketsByIdMap::iterator it = socketsByIdMap.find(sockId);
00159     if (it==socketsByIdMap.end())
00160         error("socket id=%d doesn't exist (already closed?)", sockId);
00161     if (addr.isUnspecified())
00162         opp_error("connect: unspecified remote address");
00163     if (port<=0 || port>65535)
00164         opp_error("connect: invalid remote port number %d", port);
00165 
00166     SockDesc *sd = it->second;
00167     sd->remoteAddr = addr;
00168     sd->remotePort = port;
00169 
00170     sd->onlyLocalPortIsSet = false;
00171 
00172     EV << "Connecting socket: " << *sd << "\n";
00173 }

void SimpleUDP::unbind ( int  sockId  )  [protected]

unbind socket

Parameters:
sockId id of the socket to unbind
00176 {
00177     // remove from socketsByIdMap
00178     SocketsByIdMap::iterator it = socketsByIdMap.find(sockId);
00179     if (it==socketsByIdMap.end())
00180         error("socket id=%d doesn't exist (already closed?)", sockId);
00181     SockDesc *sd = it->second;
00182     socketsByIdMap.erase(it);
00183 
00184     EV << "Unbinding socket: " << *sd << "\n";
00185 
00186     // remove from socketsByPortMap
00187     SockDescList& list = socketsByPortMap[sd->localPort];
00188     for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it)
00189         if (*it == sd) {
00190             list.erase(it);
00191             break;
00192         }
00193     if (list.empty())
00194         socketsByPortMap.erase(sd->localPort);
00195     delete sd;
00196 }

short SimpleUDP::getEphemeralPort (  )  [protected]

ephemeral port.

Returns:
a free ephemeral port, if there is no free port, error is called
00199 {
00200     // start at the last allocated port number + 1, and search for an unused one
00201     short searchUntil = lastEphemeralPort++;
00202     if (lastEphemeralPort == EPHEMERAL_PORTRANGE_END) // wrap
00203         lastEphemeralPort = EPHEMERAL_PORTRANGE_START;
00204 
00205     while (socketsByPortMap.find(lastEphemeralPort)!=socketsByPortMap.end()) {
00206         if (lastEphemeralPort == searchUntil) // got back to starting point?
00207             error("Ephemeral port range %d..%d exhausted, all ports occupied", EPHEMERAL_PORTRANGE_START, EPHEMERAL_PORTRANGE_END);
00208         lastEphemeralPort++;
00209         if (lastEphemeralPort == EPHEMERAL_PORTRANGE_END) // wrap
00210             lastEphemeralPort = EPHEMERAL_PORTRANGE_START;
00211     }
00212 
00213     // found a free one, return it
00214     return lastEphemeralPort;
00215 }

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
00249 {
00250     // IPv4 version
00251     if (sd->remotePort!=0 && sd->remotePort!=udp->sourcePort())
00252         return false;
00253     if (!sd->localAddr.isUnspecified() && sd->localAddr.get4()!=ipCtrl->destAddr())
00254         return false;
00255     if (!sd->remoteAddr.isUnspecified() && sd->remoteAddr.get4()!=ipCtrl->srcAddr())
00256         return false;
00257     if (sd->interfaceId!=-1 && sd->interfaceId!=ipCtrl->interfaceId())
00258         return false;
00259     return true;
00260 }

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
00263 {
00264     // IPv6 version
00265     if (sd->remotePort!=0 && sd->remotePort!=udp->sourcePort())
00266         return false;
00267     if (!sd->localAddr.isUnspecified() && sd->localAddr.get6()!=ipCtrl->destAddr())
00268         return false;
00269     if (!sd->remoteAddr.isUnspecified() && sd->remoteAddr.get6()!=ipCtrl->srcAddr())
00270         return false;
00271     if (sd->interfaceId!=-1 && sd->interfaceId!=ipCtrl->interfaceId())
00272         return false;
00273     return true;
00274 }

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
00277 {
00278     return (sd->remotePort==0 || sd->remotePort!=remotePort) &&
00279            (sd->localAddr.isUnspecified() || sd->localAddr==localAddr) &&
00280            (sd->remoteAddr.isUnspecified() || sd->remoteAddr==remoteAddr);
00281 }

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
00284 {
00285     // send payload with UDPControlInfo up to the application -- IPv4 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 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
00301 {
00302     // send payload with UDPControlInfo up to the application -- IPv6 version
00303     UDPControlInfo *udpCtrl = new UDPControlInfo();
00304     udpCtrl->setSockId(sd->sockId);
00305     udpCtrl->setUserId(sd->userId);
00306     udpCtrl->setSrcAddr(ipCtrl->srcAddr());
00307     udpCtrl->setDestAddr(ipCtrl->destAddr());
00308     udpCtrl->setSrcPort(udpHeader->sourcePort());
00309     udpCtrl->setDestPort(udpHeader->destinationPort());
00310     udpCtrl->setInterfaceId(ipCtrl->interfaceId());
00311     payload->setControlInfo(udpCtrl);
00312 
00313     send(payload, "to_app", sd->appGateIndex);
00314     numPassedUp++;
00315 }

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
00318 {
00319     numDroppedWrongPort++;
00320 
00321     // send back ICMP PORT_UNREACHABLE
00322     if (dynamic_cast<IPControlInfo *>(ctrl)!=NULL) {
00323         if (!icmp)
00324             icmp = ICMPAccess().get();
00325         IPControlInfo *ctrl4 = (IPControlInfo *)ctrl;
00326         if (!ctrl4->destAddr().isMulticast())
00327             icmp->sendErrorMessage(udpPacket, ctrl4, ICMP_DESTINATION_UNREACHABLE, ICMP_DU_PORT_UNREACHABLE);
00328     } else if (dynamic_cast<IPv6ControlInfo *>(udpPacket->controlInfo())
00329                !=NULL) {
00330         if (!icmpv6)
00331             icmpv6 = ICMPv6Access().get();
00332         IPv6ControlInfo *ctrl6 = (IPv6ControlInfo *)ctrl;
00333         if (!ctrl6->destAddr().isMulticast())
00334             icmpv6->sendErrorMessage(udpPacket, ctrl6, ICMPv6_DESTINATION_UNREACHABLE, PORT_UNREACHABLE);
00335     } else {
00336         error("(%s)%s arrived from lower layer without control info", udpPacket->className(), udpPacket->name());
00337     }
00338 }

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
00406 {
00407     cMessage *notifyMsg = new cMessage("ERROR", msgkind);
00408     UDPControlInfo *udpCtrl = new UDPControlInfo();
00409     udpCtrl->setSockId(sd->sockId);
00410     udpCtrl->setUserId(sd->userId);
00411     udpCtrl->setSrcAddr(localAddr);
00412     udpCtrl->setDestAddr(remoteAddr);
00413     udpCtrl->setSrcPort(sd->localPort);
00414     udpCtrl->setDestPort(remotePort);
00415     notifyMsg->setControlInfo(udpCtrl);
00416 
00417     send(notifyMsg, "to_app", sd->appGateIndex);
00418 }

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

process an ICMP error packet

Parameters:
icmpErrorMsg the received icmp Message
00341 {
00342     // extract details from the error message, then try to notify socket that sent bogus packet
00343     int type = 0;
00344     int code = 0;
00345     IPvXAddress localAddr, remoteAddr;
00346     int localPort = 0;
00347     int remotePort = 0;
00348 
00349     if (dynamic_cast<ICMPMessage *>(msg)) {
00350         ICMPMessage *icmpMsg = (ICMPMessage *)msg;
00351         type = icmpMsg->getType();
00352         code = icmpMsg->getCode();
00353         icmpMsg->setLength(icmpMsg->encapsulatedMsg()->length()); // trick because payload in ICMP is conceptually truncated
00354         IPDatagram *datagram = check_and_cast<IPDatagram *>(icmpMsg->decapsulate());
00355         localAddr = datagram->srcAddress();
00356         remoteAddr = datagram->destAddress();
00357         SimpleUDPPacket *packet = check_and_cast<SimpleUDPPacket *>(datagram->decapsulate());
00358         localPort = packet->sourcePort();
00359         remotePort = packet->destinationPort();
00360         delete icmpMsg;
00361         delete datagram;
00362         delete packet;
00363     } else if (dynamic_cast<ICMPv6Message *>(msg)) {
00364         ICMPv6Message *icmpMsg = (ICMPv6Message *)msg;
00365         type = icmpMsg->type();
00366         code = -1; // FIXME this is dependent on type()...
00367         IPv6Datagram *datagram = check_and_cast<IPv6Datagram *>(icmpMsg->decapsulate());
00368         localAddr = datagram->srcAddress();
00369         remoteAddr = datagram->destAddress();
00370         SimpleUDPPacket *packet = check_and_cast<SimpleUDPPacket *>(datagram->decapsulate());
00371         localPort = packet->sourcePort();
00372         remotePort = packet->destinationPort();
00373         delete icmpMsg;
00374         delete datagram;
00375         delete packet;
00376     }
00377     EV << "ICMP error received: type=" << type << " code=" << code
00378     << " about packet " << localAddr << ":" << localPort << " > "
00379     << remoteAddr << ":" << remotePort << "\n";
00380 
00381     // identify socket and report error to it
00382     SocketsByPortMap::iterator it = socketsByPortMap.find(localPort);
00383     if (it==socketsByPortMap.end()) {
00384         EV << "No socket on that local port, ignoring ICMP error\n";
00385         return;
00386     }
00387     SockDescList& list = it->second;
00388     SockDesc *srcSocket = NULL;
00389     for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it) {
00390         SockDesc *sd = *it;
00391         if (sd->onlyLocalPortIsSet || matchesSocket(sd, localAddr, remoteAddr, remotePort)) {
00392             srcSocket = sd; // FIXME what to do if there's more than one matching socket ???
00393         }
00394     }
00395     if (!srcSocket) {
00396         EV << "No matching socket, ignoring ICMP error\n";
00397         return;
00398     }
00399 
00400     // send UDP_I_ERROR to socket
00401     EV << "Source socket is sockId=" << srcSocket->sockId << ", notifying.\n";
00402     sendUpErrorNotification(srcSocket, UDP_I_ERROR, localAddr, remoteAddr, remotePort);
00403 }

void SimpleUDP::processUDPPacket ( SimpleUDPPacket *  udpPacket  )  [protected, virtual]

process UDP packets coming from IP

Parameters:
udpPacket the received packet
00421 {
00422     // simulate checksum: discard packet if it has bit error
00423     EV << "Packet " << udpPacket->name() << " received from network, dest port " << udpPacket->destinationPort() << "\n";
00424     if (udpPacket->hasBitError()) {
00425         EV << "Packet has bit error, discarding\n";
00426         delete udpPacket;
00427         numDroppedBadChecksum++;
00428         return;
00429     }
00430 
00431     int destPort = udpPacket->destinationPort();
00432     cPolymorphic *ctrl = udpPacket->removeControlInfo();
00433 
00434     // send back ICMP error if no socket is bound to that port
00435     SocketsByPortMap::iterator it = socketsByPortMap.find(destPort);
00436     if (it==socketsByPortMap.end()) {
00437         EV << "No socket registered on port " << destPort << "\n";
00438         processUndeliverablePacket(udpPacket, ctrl);
00439         return;
00440     }
00441     SockDescList& list = it->second;
00442 
00443     int matches = 0;
00444 
00445     // deliver a copy of the packet to each matching socket
00446     //    cMessage *payload = udpPacket->encapsulatedMsg();
00447     cMessage *payload = udpPacket->decapsulate();
00448     if (dynamic_cast<IPControlInfo *>(ctrl)!=NULL) {
00449         IPControlInfo *ctrl4 = (IPControlInfo *)ctrl;
00450         for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it) {
00451             SockDesc *sd = *it;
00452             if (sd->onlyLocalPortIsSet || matchesSocket(sd, udpPacket, ctrl4)) {
00453                 //                EV << "Socket sockId=" << sd->sockId << " matches, sending up a copy.\n";
00454                 //                sendUp((cMessage*)payload->dup(), udpPacket, ctrl4, sd);
00455                 // ib: speed hack
00456                 if (matches == 0) {
00457                     sendUp(payload, udpPacket, ctrl4, sd);
00458                 } else
00459                     opp_error("Edit SimpleUDP.cc to support multibinding.");
00460                 matches++;
00461             }
00462         }
00463     } else if (dynamic_cast<IPv6ControlInfo *>(udpPacket->controlInfo())
00464                !=NULL) {
00465         IPv6ControlInfo *ctrl6 = (IPv6ControlInfo *)ctrl;
00466         for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it) {
00467             SockDesc *sd = *it;
00468             if (sd->onlyLocalPortIsSet || matchesSocket(sd, udpPacket, ctrl6)) {
00469                 //                EV << "Socket sockId=" << sd->sockId << " matches, sending up a copy.\n";
00470                 sendUp((cMessage*)payload->dup(), udpPacket, ctrl6, sd);
00471                 matches++;
00472             }
00473         }
00474     } else {
00475         error("(%s)%s arrived from lower layer without control info", udpPacket->className(), udpPacket->name());
00476     }
00477 
00478     // send back ICMP error if there is no matching socket
00479     if (matches==0) {
00480         EV << "None of the sockets on port " << destPort << " matches the packet\n";
00481         processUndeliverablePacket(udpPacket, ctrl)
00482         ;
00483         return;
00484     }
00485 
00486     delete udpPacket;
00487     delete ctrl;
00488 }

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

process packets from application

Parameters:
appData the data that has to be sent
00492 {
00493     IPvXAddress srcAddr, destAddr;
00494     //cGate* destGate;
00495 
00496     UDPControlInfo *udpCtrl = check_and_cast<UDPControlInfo *>(appData->removeControlInfo());
00497 
00498     SimpleUDPPacket *udpPacket = new SimpleUDPPacket(appData->name());
00499 
00500     //
00501     udpPacket->setByteLength(UDP_HEADER_BYTES + IP_HEADER_BYTES);
00502     udpPacket->encapsulate(appData);
00503 
00504     // set source and destination port
00505     udpPacket->setSourcePort(udpCtrl->srcPort());
00506     udpPacket->setDestinationPort(udpCtrl->destPort());
00507 
00508     srcAddr = udpCtrl->srcAddr();
00509     destAddr = udpCtrl->destAddr();
00510     if (!udpCtrl->destAddr().isIPv6()) {
00511         // send to IPv4
00512         EV << "Sending app packet " << appData->name() << " over IPv4.\n";
00513         IPControlInfo *ipControlInfo = new IPControlInfo();
00514         ipControlInfo->setProtocol(IP_PROT_UDP);
00515         ipControlInfo->setSrcAddr(srcAddr.get4());
00516         ipControlInfo->setDestAddr(destAddr.get4());
00517         ipControlInfo->setInterfaceId(udpCtrl->interfaceId());
00518         udpPacket->setControlInfo(ipControlInfo);
00519         delete udpCtrl;
00520     } else {
00521         // send to IPv6
00522         EV << "Sending app packet " << appData->name() << " over IPv6.\n";
00523         IPv6ControlInfo *ipControlInfo = new IPv6ControlInfo();
00524         ipControlInfo->setProtocol(IP_PROT_UDP);
00525         ipControlInfo->setSrcAddr(srcAddr.get6());
00526         ipControlInfo->setDestAddr(destAddr.get6());
00527         // ipControlInfo->setInterfaceId(udpCtrl->InterfaceId()); FIXME extend IPv6 with this!!!
00528         udpPacket->setControlInfo(ipControlInfo);
00529         delete udpCtrl;
00530     }
00531 
00532     SimpleInfo* info = dynamic_cast<SimpleInfo*>(bootstrapOracle->getPeerInfo(destAddr));
00533     numSent++;
00534     if(info == NULL) {
00535         EV << "No route to host " << destAddr << "!\n";
00536         delete udpPacket->removeControlInfo();
00537         delete udpPacket;
00538         return;
00539     }
00540 
00541     SimpleNodeEntry* destEntry = info->getEntry();
00542 
00543     // calculate delay
00544     float totalDelay = 0;
00545     if(srcAddr != destAddr) {
00546         if (useCoordinateBasedDelay == true) {
00547             SimpleNodeEntry::SimpleDelay temp = nodeEntry->calcDelay(*udpPacket, *destEntry);
00548             if (temp.second == false) {
00549                 EV << "(SimpleUDP) send queue full/send error: packet " << udpPacket << " dropped!" << endl;
00550                 delete udpPacket;
00551                 udpPacket = NULL;
00552             } else
00553                 totalDelay = temp.first;
00554         } else
00555             totalDelay = constantDelay;
00556     }
00557 
00558     if(udpPacket != NULL) {
00559         EV << "(SimpleUDP) packet " << udpPacket << " sent with delay = " << totalDelay << endl;
00560         sendDirect(udpPacket, totalDelay, destEntry->getGate());
00561     }
00562 }

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

process commands from application

Parameters:
msg the command message
00565 {
00566     UDPControlInfo *udpCtrl = check_and_cast<UDPControlInfo *>(msg->removeControlInfo());
00567     switch (msg->kind()) {
00568     case UDP_C_BIND:
00569         bind(msg->arrivalGate()->index(), udpCtrl);
00570         break;
00571     case UDP_C_CONNECT:
00572         connect(udpCtrl->sockId(), udpCtrl->destAddr(), udpCtrl->destPort());
00573         break;
00574     case UDP_C_UNBIND:
00575         unbind(udpCtrl->sockId());
00576         break;
00577     default:
00578         error("unknown command code (message kind) %d received from app", msg->kind());
00579     }
00580 
00581     delete udpCtrl;
00582     delete msg;
00583 }

void SimpleUDP::initialize ( int  stage  )  [protected, virtual]

initialise the SimpleUDP module

Parameters:
stage stage of initialisation phase
00092 {
00093     if(stage == MIN_STAGE_UNDERLAY) {
00094         WATCH_PTRMAP(socketsByIdMap);
00095         WATCH_MAP(socketsByPortMap);
00096 
00097         lastEphemeralPort = EPHEMERAL_PORTRANGE_START;
00098         icmp = NULL;
00099         icmpv6 = NULL;
00100 
00101         numSent = 0;
00102         numPassedUp = 0;
00103         numDroppedWrongPort = 0;
00104         numDroppedBadChecksum = 0;
00105         WATCH(numSent);
00106         WATCH(numPassedUp);
00107         WATCH(numDroppedWrongPort);
00108         WATCH(numDroppedBadChecksum);
00109 
00110         //} else if (stage == MAX_STAGE_UNDERLAY) {
00111         bootstrapOracle = BootstrapOracleAccess().get();
00112         constantDelay = par("constantDelay");
00113         useCoordinateBasedDelay = par("useCoordinateBasedDelay");
00114         nodeEntry = NULL;
00115         WATCH_PTR(nodeEntry);
00116     }
00117 }

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
00218 {
00219     // received from the network layer
00220     if (msg->arrivedOn("network_in")) {
00221         if (dynamic_cast<ICMPMessage *>(msg) || dynamic_cast<ICMPv6Message *>(msg))
00222             processICMPError(msg);
00223         else
00224             processUDPPacket(check_and_cast<SimpleUDPPacket *>(msg));
00225     } else // received from application layer
00226     {
00227         if (msg->kind()==UDP_C_DATA)
00228             processMsgFromApp(msg);
00229         else
00230             processCommandFromApp(msg);
00231     }
00232 
00233     if (ev.isGUI())
00234         updateDisplayString();
00235 }


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 Tue Jul 24 16:51:19 2007 for ITM OverSim by  doxygen 1.5.1