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 (SimpleNodeEntry *entry)
 set or change the nodeEntry of this module
 SimpleUDP ()
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
void finish ()

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
int numLost
 number of lost packets to due queue full/bit errors
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
double jitter
 amount of jitter in % of total delay
BootstrapOraclebootstrapOracle
 pointer to BootstrapOracle
GlobalStatisticsglobalStatistics
 pointer to GlobalStatistics
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

list of sockets ordered by localPort


Constructor & Destructor Documentation

SimpleUDP::SimpleUDP (  ) 

00087 {
00088     globalStatistics = NULL;
00089 }

SimpleUDP::~SimpleUDP (  )  [virtual]

destructor

00092 {
00093     for (SocketsByIdMap::iterator i=socketsByIdMap.begin();
00094          i!=socketsByIdMap.end(); ++i)
00095         delete i->second;
00096 }


Member Function Documentation

void SimpleUDP::setNodeEntry ( SimpleNodeEntry entry  ) 

set or change the nodeEntry of this module

Parameters:
entry the new nodeEntry

Referenced by SimpleNetConfigurator::createNode(), and SimpleNetConfigurator::migrateNode().

00703 {
00704     nodeEntry = entry;
00705 }

void SimpleUDP::updateDisplayString (  )  [protected]

utility: show current statistics above the icon

Referenced by handleMessage().

00264 {
00265     char buf[80];
00266     sprintf(buf, "passed up: %d pks\nsent: %d pks", numPassedUp, numSent);
00267     if (numDroppedWrongPort>0) {
00268         sprintf(buf+strlen(buf), "\ndropped (no app): %d pks", numDroppedWrongPort);
00269         displayString().setTagArg("i",1,"red");
00270     }
00271     if (numLost>0) {
00272         sprintf(buf+strlen(buf), "\nlost (bit error/queue): %d pks", numLost);
00273         displayString().setTagArg("i",1,"red");
00274     }
00275     displayString().setTagArg("t",0,buf);
00276 }

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

bind socket

Parameters:
gateIndex application gate connected to the socket
ctrl control information for communication

Referenced by processCommandFromApp().

00135 {
00136     // XXX checks could be added, of when the bind should be allowed to proceed
00137 
00138     if (ctrl->srcPort() <= 0 || ctrl->srcPort() > 65535)
00139         opp_error("bind: invalid src port number %d", ctrl->srcPort());
00140 
00141     // create and fill in SockDesc
00142     SockDesc *sd = new SockDesc();
00143     sd->sockId = ctrl->sockId();
00144     sd->userId = ctrl->userId();
00145     sd->appGateIndex = gateIndex;
00146     sd->localAddr = ctrl->srcAddr();
00147     sd->remoteAddr = ctrl->destAddr();
00148     sd->localPort = ctrl->srcPort();
00149     sd->remotePort = ctrl->destPort();
00150     sd->interfaceId = ctrl->interfaceId();
00151 
00152     if (sd->sockId==-1)
00153         error("sockId in BIND message not filled in");
00154     if (sd->localPort==0)
00155         sd->localPort = getEphemeralPort();
00156 
00157     sd->onlyLocalPortIsSet = sd->localAddr.isUnspecified() &&
00158                              sd->remoteAddr.isUnspecified() &&
00159                              sd->remotePort==0 &&
00160                              sd->interfaceId==-1;
00161 
00162     cModule *node = parentModule();
00163     IPvXAddress ip = IPAddressResolver().addressOf(node);
00164     EV << "[SimpleUDP::bind() @ " << ip << "]\n"
00165        << "    Binding socket: " << *sd
00166        << endl;
00167 
00168     // add to socketsByIdMap
00169     ASSERT(socketsByIdMap.find(sd->sockId)==socketsByIdMap.end());
00170     socketsByIdMap[sd->sockId] = sd;
00171 
00172     // add to socketsByPortMap
00173     // create if doesn't exist
00174     SockDescList& list = socketsByPortMap[sd->localPort];
00175     list.push_back(sd);
00176 }

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

Referenced by processCommandFromApp().

00179 {
00180     SocketsByIdMap::iterator it = socketsByIdMap.find(sockId);
00181     if (it==socketsByIdMap.end())
00182         error("socket id=%d doesn't exist (already closed?)", sockId);
00183     if (addr.isUnspecified())
00184         opp_error("connect: unspecified remote address");
00185     if (port<=0 || port>65535)
00186         opp_error("connect: invalid remote port number %d", port);
00187 
00188     SockDesc *sd = it->second;
00189     sd->remoteAddr = addr;
00190     sd->remotePort = port;
00191 
00192     sd->onlyLocalPortIsSet = false;
00193 
00194     EV << "[SimpleUDP::connect() @ " << sd->localAddr << "]\n"
00195        << "    Connecting socket: " << *sd
00196        << endl;
00197 }

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

unbind socket

Parameters:
sockId id of the socket to unbind

Referenced by processCommandFromApp().

00200 {
00201     // remove from socketsByIdMap
00202     SocketsByIdMap::iterator it = socketsByIdMap.find(sockId);
00203     if (it==socketsByIdMap.end())
00204         error("socket id=%d doesn't exist (already closed?)", sockId);
00205     SockDesc *sd = it->second;
00206     socketsByIdMap.erase(it);
00207 
00208     EV << "[SimpleUDP::unbind() @ " << sd->localAddr << "]\n"
00209        << "    Unbinding socket: " << *sd
00210        << endl;
00211 
00212     // remove from socketsByPortMap
00213     SockDescList& list = socketsByPortMap[sd->localPort];
00214     for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it)
00215         if (*it == sd) {
00216             list.erase(it);
00217             break;
00218         }
00219     if (list.empty())
00220         socketsByPortMap.erase(sd->localPort);
00221     delete sd;
00222 }

short SimpleUDP::getEphemeralPort (  )  [protected]

ephemeral port.

Returns:
a free ephemeral port, if there is no free port, error is called

Referenced by bind().

00225 {
00226     // start at the last allocated port number + 1, and search for an unused one
00227     short searchUntil = lastEphemeralPort++;
00228     if (lastEphemeralPort == EPHEMERAL_PORTRANGE_END) // wrap
00229         lastEphemeralPort = EPHEMERAL_PORTRANGE_START;
00230 
00231     while (socketsByPortMap.find(lastEphemeralPort)!=socketsByPortMap.end()) {
00232         if (lastEphemeralPort == searchUntil) // got back to starting point?
00233             error("Ephemeral port range %d..%d exhausted, all ports occupied", EPHEMERAL_PORTRANGE_START, EPHEMERAL_PORTRANGE_END);
00234         lastEphemeralPort++;
00235         if (lastEphemeralPort == EPHEMERAL_PORTRANGE_END) // wrap
00236             lastEphemeralPort = EPHEMERAL_PORTRANGE_START;
00237     }
00238 
00239     // found a free one, return it
00240     return lastEphemeralPort;
00241 }

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

Referenced by processICMPError(), and processUDPPacket().

00279 {
00280     // IPv4 version
00281     if (sd->remotePort!=0 && sd->remotePort!=udp->sourcePort())
00282         return false;
00283     if (!sd->localAddr.isUnspecified() && sd->localAddr.get4()!=ipCtrl->destAddr())
00284         return false;
00285     if (!sd->remoteAddr.isUnspecified() && sd->remoteAddr.get4()!=ipCtrl->srcAddr())
00286         return false;
00287     if (sd->interfaceId!=-1 && sd->interfaceId!=ipCtrl->interfaceId())
00288         return false;
00289     return true;
00290 }

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
00293 {
00294     // IPv6 version
00295     if (sd->remotePort!=0 && sd->remotePort!=udp->sourcePort())
00296         return false;
00297     if (!sd->localAddr.isUnspecified() && sd->localAddr.get6()!=ipCtrl->destAddr())
00298         return false;
00299     if (!sd->remoteAddr.isUnspecified() && sd->remoteAddr.get6()!=ipCtrl->srcAddr())
00300         return false;
00301     if (sd->interfaceId!=-1 && sd->interfaceId!=ipCtrl->interfaceId())
00302         return false;
00303     return true;
00304 }

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
00307 {
00308     return (sd->remotePort==0 || sd->remotePort!=remotePort) &&
00309            (sd->localAddr.isUnspecified() || sd->localAddr==localAddr) &&
00310            (sd->remoteAddr.isUnspecified() || sd->remoteAddr==remoteAddr);
00311 }

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

Referenced by processUDPPacket().

00314 {
00315     // send payload with UDPControlInfo up to the application -- IPv4 version
00316     UDPControlInfo *udpCtrl = new UDPControlInfo();
00317     udpCtrl->setSockId(sd->sockId);
00318     udpCtrl->setUserId(sd->userId);
00319     udpCtrl->setSrcAddr(ipCtrl->srcAddr());
00320     udpCtrl->setDestAddr(ipCtrl->destAddr());
00321     udpCtrl->setSrcPort(udpHeader->sourcePort());
00322     udpCtrl->setDestPort(udpHeader->destinationPort());
00323     udpCtrl->setInterfaceId(ipCtrl->interfaceId());
00324     payload->setControlInfo(udpCtrl);
00325 
00326     send(payload, "to_app", sd->appGateIndex);
00327     numPassedUp++;
00328 }

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
00331 {
00332     // send payload with UDPControlInfo up to the application -- IPv6 version
00333     UDPControlInfo *udpCtrl = new UDPControlInfo();
00334     udpCtrl->setSockId(sd->sockId);
00335     udpCtrl->setUserId(sd->userId);
00336     udpCtrl->setSrcAddr(ipCtrl->srcAddr());
00337     udpCtrl->setDestAddr(ipCtrl->destAddr());
00338     udpCtrl->setSrcPort(udpHeader->sourcePort());
00339     udpCtrl->setDestPort(udpHeader->destinationPort());
00340     udpCtrl->setInterfaceId(ipCtrl->interfaceId());
00341     payload->setControlInfo(udpCtrl);
00342 
00343     send(payload, "to_app", sd->appGateIndex);
00344     numPassedUp++;
00345 }

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

Referenced by processUDPPacket().

00348 {
00349     numDroppedWrongPort++;
00350 
00351     // send back ICMP PORT_UNREACHABLE
00352     if (dynamic_cast<IPControlInfo *>(ctrl)!=NULL) {
00353 /*        if (!icmp)
00354             icmp = ICMPAccess().get();
00355         IPControlInfo *ctrl4 = (IPControlInfo *)ctrl;
00356         if (!ctrl4->destAddr().isMulticast())
00357             icmp->sendErrorMessage(udpPacket, ctrl4, ICMP_DESTINATION_UNREACHABLE, ICMP_DU_PORT_UNREACHABLE);*/
00358         /* TODO: implement icmp module */
00359         EV << "[SimpleUDP::processUndeliverablePacket()]\n"
00360                 << "    Dropped packet bound to unreserved port, ignoring ICMP error"
00361                 << endl;
00362     } else if (dynamic_cast<IPv6ControlInfo *>(udpPacket->controlInfo())
00363                !=NULL) {
00364 /*        if (!icmpv6)
00365             icmpv6 = ICMPv6Access().get();
00366         IPv6ControlInfo *ctrl6 = (IPv6ControlInfo *)ctrl;
00367         if (!ctrl6->destAddr().isMulticast())
00368             icmpv6->sendErrorMessage(udpPacket, ctrl6, ICMPv6_DESTINATION_UNREACHABLE, PORT_UNREACHABLE);*/
00369         /* TODO: implement icmp module */
00370         EV << "[SimpleUDP::processUndeliverablePacket()]\n"
00371            << "    Dropped packet bound to unreserved port, ignoring ICMP error"
00372            << endl;
00373     } else {
00374         error("(%s)%s arrived from lower layer without control info", udpPacket->className(), udpPacket->name());
00375     }
00376 }

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

Referenced by processICMPError().

00452 {
00453     cMessage *notifyMsg = new cMessage("ERROR", msgkind);
00454     UDPControlInfo *udpCtrl = new UDPControlInfo();
00455     udpCtrl->setSockId(sd->sockId);
00456     udpCtrl->setUserId(sd->userId);
00457     udpCtrl->setSrcAddr(localAddr);
00458     udpCtrl->setDestAddr(remoteAddr);
00459     udpCtrl->setSrcPort(sd->localPort);
00460     udpCtrl->setDestPort(remotePort);
00461     notifyMsg->setControlInfo(udpCtrl);
00462 
00463     send(notifyMsg, "to_app", sd->appGateIndex);
00464 }

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

process an ICMP error packet

Parameters:
icmpErrorMsg the received icmp Message

Referenced by handleMessage().

00379 {
00380     // extract details from the error message, then try to notify socket that sent bogus packet
00381     int type = 0;
00382     int code = 0;
00383     IPvXAddress localAddr, remoteAddr;
00384     int localPort = 0;
00385     int remotePort = 0;
00386 
00387     if (dynamic_cast<ICMPMessage *>(msg)) {
00388         ICMPMessage *icmpMsg = (ICMPMessage *)msg;
00389         type = icmpMsg->getType();
00390         code = icmpMsg->getCode();
00391         icmpMsg->setLength(icmpMsg->encapsulatedMsg()->length()); // trick because payload in ICMP is conceptually truncated
00392         IPDatagram *datagram = check_and_cast<IPDatagram *>(icmpMsg->decapsulate());
00393         localAddr = datagram->srcAddress();
00394         remoteAddr = datagram->destAddress();
00395         SimpleUDPPacket *packet = check_and_cast<SimpleUDPPacket *>(datagram->decapsulate());
00396         localPort = packet->sourcePort();
00397         remotePort = packet->destinationPort();
00398         delete icmpMsg;
00399         delete datagram;
00400         delete packet;
00401     } else if (dynamic_cast<ICMPv6Message *>(msg)) {
00402         ICMPv6Message *icmpMsg = (ICMPv6Message *)msg;
00403         type = icmpMsg->type();
00404         code = -1; // FIXME this is dependent on type()...
00405         IPv6Datagram *datagram = check_and_cast<IPv6Datagram *>(icmpMsg->decapsulate());
00406         localAddr = datagram->srcAddress();
00407         remoteAddr = datagram->destAddress();
00408         SimpleUDPPacket *packet = check_and_cast<SimpleUDPPacket *>(datagram->decapsulate());
00409         localPort = packet->sourcePort();
00410         remotePort = packet->destinationPort();
00411         delete icmpMsg;
00412         delete datagram;
00413         delete packet;
00414     }
00415     EV << "[SimpleUDP::processICMPError() @ " << localAddr << "]\n"
00416        << "    ICMP error received: type=" << type << " code=" << code
00417        << "\n    about packet " << localAddr << ":" << localPort << " --> "
00418        << "    " << remoteAddr << ":" << remotePort
00419        << endl;
00420 
00421     // identify socket and report error to it
00422     SocketsByPortMap::iterator it = socketsByPortMap.find(localPort);
00423     if (it==socketsByPortMap.end()) {
00424         EV << "[SimpleUDP::processICMPError() @ " << localAddr << "]\n"
00425            << "    No socket on that local port, ignoring ICMP error"
00426            << endl;
00427         return;
00428     }
00429     SockDescList& list = it->second;
00430     SockDesc *srcSocket = NULL;
00431     for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it) {
00432         SockDesc *sd = *it;
00433         if (sd->onlyLocalPortIsSet || matchesSocket(sd, localAddr, remoteAddr, remotePort)) {
00434             srcSocket = sd; // FIXME what to do if there's more than one matching socket ???
00435         }
00436     }
00437     if (!srcSocket) {
00438         EV << "[SimpleUDP::processICMPError() @ " << localAddr << "]\n"
00439            << "    No matching socket, ignoring ICMP error"
00440            << endl;
00441         return;
00442     }
00443 
00444     // send UDP_I_ERROR to socket
00445     EV << "[SimpleUDP::processICMPError() @ " << localAddr << "]\n"
00446        << "    Source socket is sockId=" << srcSocket->sockId << ", notifying"
00447        << endl;
00448     sendUpErrorNotification(srcSocket, UDP_I_ERROR, localAddr, remoteAddr, remotePort);
00449 }

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

process UDP packets coming from IP

Parameters:
udpPacket the received packet

Referenced by handleMessage().

00467 {
00468     cModule *node = parentModule();
00469 //    IPvXAddress ip = IPAddressResolver().addressOf(node);
00470 //    Speedhack SK
00471 
00472     // simulate checksum: discard packet if it has bit error
00473     EV << "[SimpleUDP::processUDPPacket() @ " << IPAddressResolver().addressOf(node) << "]\n"
00474        << "    Packet " << udpPacket->name() << " received from network, dest port " << udpPacket->destinationPort()
00475        << endl;
00476 
00477     if (udpPacket->hasBitError()) {
00478         EV << "[SimpleUDP::processUDPPacket() @ " << IPAddressResolver().addressOf(node) << "]\n"
00479            << "    Packet has bit error, discarding"
00480            << endl;
00481         delete udpPacket;
00482         numDroppedBadChecksum++;
00483         return;
00484     }
00485 
00486     int destPort = udpPacket->destinationPort();
00487     cPolymorphic *ctrl = udpPacket->removeControlInfo();
00488 
00489     // send back ICMP error if no socket is bound to that port
00490     SocketsByPortMap::iterator it = socketsByPortMap.find(destPort);
00491     if (it==socketsByPortMap.end()) {
00492         EV << "[SimpleUDP::processUDPPacket() @ " << IPAddressResolver().addressOf(node) << "]\n"
00493            << "    No socket registered on port " << destPort
00494            << endl;
00495         processUndeliverablePacket(udpPacket, ctrl);
00496         return;
00497     }
00498     SockDescList& list = it->second;
00499 
00500     int matches = 0;
00501 
00502     // deliver a copy of the packet to each matching socket
00503     //    cMessage *payload = udpPacket->encapsulatedMsg();
00504     cMessage *payload = udpPacket->decapsulate();
00505     if (dynamic_cast<IPControlInfo *>(ctrl)!=NULL) {
00506         IPControlInfo *ctrl4 = (IPControlInfo *)ctrl;
00507         for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it) {
00508             SockDesc *sd = *it;
00509             if (sd->onlyLocalPortIsSet || matchesSocket(sd, udpPacket, ctrl4)) {
00510 //              EV << "[SimpleUDP::processUDPPacket() @ " << IPAddressResolver().addressOf(node) << "]\n"
00511 //                 << "    Socket sockId=" << sd->sockId << " matches, sending up a copy"
00512 //                 << endl;
00513 //              sendUp((cMessage*)payload->dup(), udpPacket, ctrl4, sd);
00514 //              ib: speed hack
00515 
00516                 if (matches == 0) {
00517                     sendUp(payload, udpPacket, ctrl4, sd);
00518                 } else
00519                     opp_error("Edit SimpleUDP.cc to support multibinding.");
00520                 matches++;
00521             }
00522         }
00523     } else if (dynamic_cast<IPv6ControlInfo *>(udpPacket->controlInfo())
00524                !=NULL) {
00525         IPv6ControlInfo *ctrl6 = (IPv6ControlInfo *)ctrl;
00526         for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it) {
00527             SockDesc *sd = *it;
00528             if (sd->onlyLocalPortIsSet || matchesSocket(sd, udpPacket, ctrl6)) {
00529                 EV << "[SimpleUDP::processUDPPacket() @ " << IPAddressResolver().addressOf(node) << "]\n"
00530                    << "    Socket sockId=" << sd->sockId << " matches, sending up a copy"
00531                    << endl;
00532                 sendUp((cMessage*)payload->dup(), udpPacket, ctrl6, sd);
00533                 matches++;
00534             }
00535         }
00536     } else {
00537         error("(%s)%s arrived from lower layer without control info", udpPacket->className(), udpPacket->name());
00538     }
00539 
00540     // send back ICMP error if there is no matching socket
00541     if (matches==0) {
00542         EV << "[SimpleUDP::processUDPPacket() @ " << IPAddressResolver().addressOf(node) << "]\n"
00543            << "    None of the sockets on port " << destPort << " matches the packet"
00544            << endl;
00545         processUndeliverablePacket(udpPacket, ctrl)
00546         ;
00547         return;
00548     }
00549 
00550     delete udpPacket;
00551     delete ctrl;
00552 }

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

process packets from application

Parameters:
appData the data that has to be sent

Referenced by handleMessage().

00556 {
00557     cModule *node = parentModule();
00558 //    IPvXAddress ip = IPAddressResolver().addressOf(node);
00559 //    Speedhack SK
00560 
00561     IPvXAddress srcAddr, destAddr;
00562     //cGate* destGate;
00563 
00564     UDPControlInfo *udpCtrl = check_and_cast<UDPControlInfo *>(appData->removeControlInfo());
00565 
00566     SimpleUDPPacket *udpPacket = new SimpleUDPPacket(appData->name());
00567 
00568     //
00569     udpPacket->setByteLength(UDP_HEADER_BYTES + IP_HEADER_BYTES);
00570     udpPacket->encapsulate(appData);
00571 
00572     // set source and destination port
00573     udpPacket->setSourcePort(udpCtrl->srcPort());
00574     udpPacket->setDestinationPort(udpCtrl->destPort());
00575 
00576     srcAddr = udpCtrl->srcAddr();
00577     destAddr = udpCtrl->destAddr();
00578     if (!udpCtrl->destAddr().isIPv6()) {
00579         // send to IPv4
00580         //EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n"
00581         //<< "    Sending app packet " << appData->name() << " over IPv4"
00582         //<< endl;
00583         IPControlInfo *ipControlInfo = new IPControlInfo();
00584         ipControlInfo->setProtocol(IP_PROT_UDP);
00585         ipControlInfo->setSrcAddr(srcAddr.get4());
00586         ipControlInfo->setDestAddr(destAddr.get4());
00587         ipControlInfo->setInterfaceId(udpCtrl->interfaceId());
00588         udpPacket->setControlInfo(ipControlInfo);
00589         delete udpCtrl;
00590     } else {
00591         // send to IPv6
00592         //EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n"
00593         //<< "    Sending app packet " << appData->name() << " over IPv6"
00594         //<< endl;
00595         IPv6ControlInfo *ipControlInfo = new IPv6ControlInfo();
00596         ipControlInfo->setProtocol(IP_PROT_UDP);
00597         ipControlInfo->setSrcAddr(srcAddr.get6());
00598         ipControlInfo->setDestAddr(destAddr.get6());
00599         // ipControlInfo->setInterfaceId(udpCtrl->InterfaceId()); FIXME extend IPv6 with this!!!
00600         udpPacket->setControlInfo(ipControlInfo);
00601         delete udpCtrl;
00602     }
00603 
00604     SimpleInfo* info = dynamic_cast<SimpleInfo*>(bootstrapOracle->getPeerInfo(destAddr));
00605     numSent++;
00606 
00607     if (info == NULL) {
00608         EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n"
00609            << "    No route to host " << destAddr
00610            << endl;
00611         delete udpPacket->removeControlInfo();
00612         delete udpPacket;
00613         return;
00614     }
00615 
00616     SimpleInfo* thisInfo = dynamic_cast<SimpleInfo*>(bootstrapOracle->getPeerInfo(srcAddr));
00617 
00618     if (!bootstrapOracle->areNodeTypesConnected(thisInfo->getTypeID(), info->getTypeID())) {
00619         EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n"
00620                    << "    Partition " << thisInfo->getTypeID() << "->" << info->getTypeID()
00621                    << " is not connected"
00622                    << endl;
00623                 delete udpPacket->removeControlInfo();
00624                 delete udpPacket;
00625                 return;
00626     }
00627 
00628     SimpleNodeEntry* destEntry = info->getEntry();
00629 
00630     // calculate delay
00631     float totalDelay = 0;
00632     if (srcAddr != destAddr) {
00633         if (useCoordinateBasedDelay == true) {
00634             SimpleNodeEntry::SimpleDelay temp = nodeEntry->calcDelay(*udpPacket, *destEntry);
00635             if (temp.second == false) {
00636                 EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n"
00637                    << "    Send queue full/send error: packet " << udpPacket << " dropped"
00638                    << endl;
00639                 delete udpPacket;
00640                 udpPacket = NULL;
00641                 numLost++;
00642             } else
00643                 totalDelay = temp.first;
00644         } else
00645             totalDelay = constantDelay;
00646     }
00647 
00648     // jitter
00649     totalDelay += truncnormal(0, totalDelay * jitter);
00650 
00651     if (udpPacket != NULL) {
00652         BaseOverlayMessage* temp = NULL;
00653 
00654         if (ev.isGUI() && udpPacket->encapsulatedMsg()) {
00655             if ((temp = dynamic_cast<BaseOverlayMessage*>(udpPacket
00656                     ->encapsulatedMsg()))) {
00657                 switch (temp->getStatType()) {
00658                 case APP_DATA_STAT:
00659                     udpPacket->setKind(1);
00660                     break;
00661                 case APP_LOOKUP_STAT:
00662                     udpPacket->setKind(2);
00663                     break;
00664                 case MAINTENANCE_STAT:
00665                 default:
00666                     udpPacket->setKind(3);
00667                 }
00668             } else {
00669                 udpPacket->setKind(1);
00670             }
00671         }
00672 
00673         EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n"
00674            << "    Packet " << udpPacket << " sent with delay = " << totalDelay
00675            << endl;
00676         sendDirect(udpPacket, totalDelay, destEntry->getGate());
00677     }
00678 }

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

process commands from application

Parameters:
msg the command message

Referenced by handleMessage().

00681 {
00682     UDPControlInfo *udpCtrl = check_and_cast<UDPControlInfo *>(msg->removeControlInfo());
00683     switch (msg->kind()) {
00684     case UDP_C_BIND:
00685         bind(msg->arrivalGate()->index(), udpCtrl);
00686         break;
00687     case UDP_C_CONNECT:
00688         connect(udpCtrl->sockId(), udpCtrl->destAddr(), udpCtrl->destPort());
00689         break;
00690     case UDP_C_UNBIND:
00691         unbind(udpCtrl->sockId());
00692         break;
00693     default:
00694         error("unknown command code (message kind) %d received from app", msg->kind());
00695     }
00696 
00697     delete udpCtrl;
00698     delete msg;
00699 }

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

initialise the SimpleUDP module

Parameters:
stage stage of initialisation phase
00099 {
00100     if(stage == MIN_STAGE_UNDERLAY) {
00101         WATCH_PTRMAP(socketsByIdMap);
00102         WATCH_MAP(socketsByPortMap);
00103 
00104         lastEphemeralPort = EPHEMERAL_PORTRANGE_START;
00105         icmp = NULL;
00106         icmpv6 = NULL;
00107 
00108         numSent = 0;
00109         numPassedUp = 0;
00110         numDroppedWrongPort = 0;
00111         numDroppedBadChecksum = 0;
00112         numLost = 0;
00113         WATCH(numSent);
00114         WATCH(numPassedUp);
00115         WATCH(numDroppedWrongPort);
00116         WATCH(numDroppedBadChecksum);
00117         WATCH(numLost);
00118 
00119         bootstrapOracle = BootstrapOracleAccess().get();
00120         globalStatistics = GlobalStatisticsAccess().get();
00121         constantDelay = par("constantDelay");
00122         useCoordinateBasedDelay = par("useCoordinateBasedDelay");
00123         jitter = par("jitter");
00124         nodeEntry = NULL;
00125         WATCH_PTR(nodeEntry);
00126     }
00127 }

virtual int SimpleUDP::numInitStages ( void   )  const [inline, protected, virtual]

returns the number of init stages

Returns:
the number of init stages
00272     {
00273         return MAX_STAGE_UNDERLAY + 1;
00274     }

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

process received messages

Parameters:
msg the received message
00244 {
00245     // received from the network layer
00246     if (msg->arrivedOn("network_in")) {
00247         if (dynamic_cast<ICMPMessage *>(msg) || dynamic_cast<ICMPv6Message *>(msg))
00248             processICMPError(msg);
00249         else
00250             processUDPPacket(check_and_cast<SimpleUDPPacket *>(msg));
00251     } else // received from application layer
00252     {
00253         if (msg->kind()==UDP_C_DATA)
00254             processMsgFromApp(msg);
00255         else
00256             processCommandFromApp(msg);
00257     }
00258 
00259     if (ev.isGUI())
00260         updateDisplayString();
00261 }

void SimpleUDP::finish (  )  [protected]

00130 {
00131     globalStatistics->addStdDev("SimpleUDP: Packet Loss Ratio (Queue full/Bit errors)",
00132                                 (numSent ? ((double)numLost/numSent) : 0));
00133 }


Member Data Documentation

list of socket ordered by sockId

Referenced by bind(), connect(), initialize(), unbind(), and ~SimpleUDP().

list of sockets ordered by localPort

Referenced by bind(), getEphemeralPort(), initialize(), processICMPError(), processUDPPacket(), and unbind().

short SimpleUDP::lastEphemeralPort [protected]

last used port (all ports above should be free)

Referenced by getEphemeralPort(), and initialize().

ICMP* SimpleUDP::icmp [protected]

pointer to a received icmp (IPv4) message

Referenced by initialize().

ICMPv6* SimpleUDP::icmpv6 [protected]

pointer to a received icmp (IPv6) message

Referenced by initialize().

int SimpleUDP::numSent [protected]

number of packets sent to the network

Referenced by finish(), initialize(), processMsgFromApp(), and updateDisplayString().

int SimpleUDP::numPassedUp [protected]

number of packet passed up to applications

Referenced by initialize(), sendUp(), and updateDisplayString().

number of dropped packets due to wrong destination port

Referenced by initialize(), processUndeliverablePacket(), and updateDisplayString().

number of dropped packets due to bad checksum

Referenced by initialize(), and processUDPPacket().

int SimpleUDP::numLost [protected]

number of lost packets to due queue full/bit errors

Referenced by finish(), initialize(), processMsgFromApp(), and updateDisplayString().

simtime_t SimpleUDP::delay [protected]

simulated delay between sending and receiving udp module

simtime_t SimpleUDP::constantDelay [protected]

constant delay between two peers

Referenced by initialize(), and processMsgFromApp().

delay should be calculated from euklidean distance between two peers

Referenced by initialize(), and processMsgFromApp().

double SimpleUDP::jitter [protected]

amount of jitter in % of total delay

Referenced by initialize(), and processMsgFromApp().

pointer to BootstrapOracle

Referenced by initialize(), and processMsgFromApp().

pointer to GlobalStatistics

Referenced by finish(), initialize(), and SimpleUDP().

nodeEntry of the overlay node this module belongs to

Referenced by initialize(), processMsgFromApp(), and setNodeEntry().


The documentation for this class was generated from the following files:

Generated on Fri Sep 19 13:05:08 2008 for ITM OverSim by  doxygen 1.5.5