SimpleUDP Class Reference

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

#include <SimpleUDP.h>

List of all members.

Classes

struct  SockDesc
 defines a socket More...

Public Types

enum  delayFaultTypeNum { delayFaultUndefined, delayFaultLiveAll, delayFaultLivePlanetlab, delayFaultSimulation }
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

Static Public Attributes

static std::string delayFaultTypeString
static std::map< std::string,
delayFaultTypeNum
delayFaultTypeMap

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 (cPacket *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 numQueueLost
 number of lost packets due to queue full
int numPartitionLost
 number of lost packets due to network partitions
int numDestUnavailableLost
 number of lost packets due to unavailable destination
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
bool faultyDelay
GlobalNodeListglobalNodeList
 violate the triangle inequality?
GlobalStatisticsglobalStatistics
 pointer to GlobalStatistics
SimpleNodeEntrynodeEntry
 nodeEntry of the overlay node this module belongs to

Detailed Description

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

More info in the NED file.

Definition at line 63 of file SimpleUDP.h.


Member Typedef Documentation

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

list of socket pointers

Definition at line 84 of file SimpleUDP.h.

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

list of socket ordered by sockId

Definition at line 85 of file SimpleUDP.h.

list of sockets ordered by localPort

Definition at line 86 of file SimpleUDP.h.


Member Enumeration Documentation

Enumerator:
delayFaultUndefined 
delayFaultLiveAll 
delayFaultLivePlanetlab 
delayFaultSimulation 

Definition at line 90 of file SimpleUDP.h.


Constructor & Destructor Documentation

SimpleUDP::SimpleUDP (  ) 

Definition at line 92 of file SimpleUDP.cc.

00093 {
00094     globalStatistics = NULL;
00095 }

SimpleUDP::~SimpleUDP (  )  [virtual]

destructor

Definition at line 97 of file SimpleUDP.cc.

00098 {
00099     for (SocketsByIdMap::iterator i=socketsByIdMap.begin();
00100     i!=socketsByIdMap.end(); ++i)
00101         delete i->second;
00102 }


Member Function Documentation

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

bind socket

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

Definition at line 169 of file SimpleUDP.cc.

Referenced by processCommandFromApp().

00170 {
00171     // XXX checks could be added, of when the bind should be allowed to proceed
00172 
00173     if (ctrl->getSrcPort() <= 0 || ctrl->getSrcPort() > 65535)
00174         opp_error("bind: invalid src port number %d", ctrl->getSrcPort());
00175 
00176     // create and fill in SockDesc
00177     SockDesc *sd = new SockDesc();
00178     sd->sockId = ctrl->getSockId();
00179     sd->userId = ctrl->getUserId();
00180     sd->appGateIndex = gateIndex;
00181     sd->localAddr = ctrl->getSrcAddr();
00182     sd->remoteAddr = ctrl->getDestAddr();
00183     sd->localPort = ctrl->getSrcPort();
00184     sd->remotePort = ctrl->getDestPort();
00185     sd->interfaceId = ctrl->getInterfaceId();
00186 
00187     if (sd->sockId==-1)
00188         error("sockId in BIND message not filled in");
00189     if (sd->localPort==0)
00190         sd->localPort = getEphemeralPort();
00191 
00192     sd->onlyLocalPortIsSet = sd->localAddr.isUnspecified() &&
00193                              sd->remoteAddr.isUnspecified() &&
00194                              sd->remotePort==0 &&
00195                              sd->interfaceId==-1;
00196 
00197     cModule *node = getParentModule();
00198     IPvXAddress ip = IPAddressResolver().addressOf(node);
00199     EV << "[SimpleUDP::bind() @ " << ip << "]\n"
00200        << "    Binding socket: " << *sd
00201        << endl;
00202 
00203     // add to socketsByIdMap
00204     ASSERT(socketsByIdMap.find(sd->sockId)==socketsByIdMap.end());
00205     socketsByIdMap[sd->sockId] = sd;
00206 
00207     // add to socketsByPortMap
00208     // create if doesn't exist
00209     SockDescList& list = socketsByPortMap[sd->localPort];
00210     list.push_back(sd);
00211 }

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

Definition at line 213 of file SimpleUDP.cc.

Referenced by processCommandFromApp().

00214 {
00215     SocketsByIdMap::iterator it = socketsByIdMap.find(sockId);
00216     if (it==socketsByIdMap.end())
00217         error("socket id=%d doesn't exist (already closed?)", sockId);
00218     if (addr.isUnspecified())
00219         opp_error("connect: unspecified remote address");
00220     if (port<=0 || port>65535)
00221         opp_error("connect: invalid remote port number %d", port);
00222 
00223     SockDesc *sd = it->second;
00224     sd->remoteAddr = addr;
00225     sd->remotePort = port;
00226 
00227     sd->onlyLocalPortIsSet = false;
00228 
00229     EV << "[SimpleUDP::connect() @ " << sd->localAddr << "]\n"
00230        << "    Connecting socket: " << *sd
00231        << endl;
00232 }

void SimpleUDP::finish (  )  [protected]

Definition at line 155 of file SimpleUDP.cc.

00156 {
00157     globalStatistics->addStdDev("SimpleUDP: Packets sent",
00158                                 numSent);
00159     globalStatistics->addStdDev("SimpleUDP: Packets dropped with bad checksum",
00160                                 numDroppedBadChecksum);
00161     globalStatistics->addStdDev("SimpleUDP: Packets dropped due to queue overflows",
00162                                 numQueueLost);
00163     globalStatistics->addStdDev("SimpleUDP: Packets dropped due to network partitions",
00164                                 numPartitionLost);
00165     globalStatistics->addStdDev("SimpleUDP: Packets dropped due to unavailable destination",
00166                                 numDestUnavailableLost);
00167 }

short SimpleUDP::getEphemeralPort (  )  [protected]

ephemeral port.

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

Definition at line 259 of file SimpleUDP.cc.

Referenced by bind().

00260 {
00261     // start at the last allocated port number + 1, and search for an unused one
00262     short searchUntil = lastEphemeralPort++;
00263     if (lastEphemeralPort == EPHEMERAL_PORTRANGE_END) // wrap
00264         lastEphemeralPort = EPHEMERAL_PORTRANGE_START;
00265 
00266     while (socketsByPortMap.find(lastEphemeralPort)!=socketsByPortMap.end()) {
00267         if (lastEphemeralPort == searchUntil) // got back to starting point?
00268             error("Ephemeral port range %d..%d exhausted, all ports occupied", EPHEMERAL_PORTRANGE_START, EPHEMERAL_PORTRANGE_END);
00269         lastEphemeralPort++;
00270         if (lastEphemeralPort == EPHEMERAL_PORTRANGE_END) // wrap
00271             lastEphemeralPort = EPHEMERAL_PORTRANGE_START;
00272     }
00273 
00274     // found a free one, return it
00275     return lastEphemeralPort;
00276 }

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

process received messages

Parameters:
msg the received message

Definition at line 278 of file SimpleUDP.cc.

00279 {
00280     // received from the network layer
00281     if (msg->arrivedOn("network_in")) {
00282         if (dynamic_cast<ICMPMessage *>(msg) || dynamic_cast<ICMPv6Message *>(msg))
00283             processICMPError(msg);
00284         else
00285             processUDPPacket(check_and_cast<SimpleUDPPacket *>(msg));
00286     } else // received from application layer
00287     {
00288         if (msg->getKind()==UDP_C_DATA)
00289             processMsgFromApp(check_and_cast<cPacket*>(msg));
00290         else
00291             processCommandFromApp(msg);
00292     }
00293 
00294     if (ev.isGUI())
00295         updateDisplayString();
00296 }

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

initialise the SimpleUDP module

Parameters:
stage stage of initialisation phase

Definition at line 104 of file SimpleUDP.cc.

00105 {
00106     if(stage == MIN_STAGE_UNDERLAY) {
00107         WATCH_PTRMAP(socketsByIdMap);
00108         WATCH_MAP(socketsByPortMap);
00109 
00110         lastEphemeralPort = EPHEMERAL_PORTRANGE_START;
00111         icmp = NULL;
00112         icmpv6 = NULL;
00113 
00114         numSent = 0;
00115         numPassedUp = 0;
00116         numDroppedWrongPort = 0;
00117         numDroppedBadChecksum = 0;
00118         numQueueLost = 0;
00119         numPartitionLost = 0;
00120         numDestUnavailableLost = 0;
00121         WATCH(numSent);
00122         WATCH(numPassedUp);
00123         WATCH(numDroppedWrongPort);
00124         WATCH(numDroppedBadChecksum);
00125         WATCH(numQueueLost);
00126         WATCH(numPartitionLost);
00127         WATCH(numDestUnavailableLost);
00128 
00129         globalNodeList = GlobalNodeListAccess().get();
00130         globalStatistics = GlobalStatisticsAccess().get();
00131         constantDelay = par("constantDelay");
00132         useCoordinateBasedDelay = par("useCoordinateBasedDelay");
00133 
00134         delayFaultTypeString = par("delayFaultType").stdstringValue();
00135         delayFaultTypeMap["live_all"] = delayFaultLiveAll;
00136         delayFaultTypeMap["live_planetlab"] = delayFaultLivePlanetlab;
00137         delayFaultTypeMap["simulation"] = delayFaultSimulation;
00138 
00139         switch (delayFaultTypeMap[delayFaultTypeString]) {
00140         case SimpleUDP::delayFaultLiveAll:
00141         case SimpleUDP::delayFaultLivePlanetlab:
00142         case SimpleUDP::delayFaultSimulation:
00143             faultyDelay = true;
00144             break;
00145         default:
00146             faultyDelay = false;
00147         }
00148 
00149         jitter = par("jitter");
00150         nodeEntry = NULL;
00151         WATCH_PTR(nodeEntry);
00152     }
00153 }

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

Definition at line 341 of file SimpleUDP.cc.

00342 {
00343     return (sd->remotePort==0 || sd->remotePort!=remotePort) &&
00344            (sd->localAddr.isUnspecified() || sd->localAddr==localAddr) &&
00345            (sd->remoteAddr.isUnspecified() || sd->remoteAddr==remoteAddr);
00346 }

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

Definition at line 327 of file SimpleUDP.cc.

00328 {
00329     // IPv6 version
00330     if (sd->remotePort!=0 && sd->remotePort!=udp->getSourcePort())
00331         return false;
00332     if (!sd->localAddr.isUnspecified() && sd->localAddr.get6()!=ipCtrl->getDestAddr())
00333         return false;
00334     if (!sd->remoteAddr.isUnspecified() && sd->remoteAddr.get6()!=ipCtrl->getSrcAddr())
00335         return false;
00336     if (sd->interfaceId!=-1 && sd->interfaceId!=ipCtrl->getInterfaceId())
00337         return false;
00338     return true;
00339 }

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

Definition at line 313 of file SimpleUDP.cc.

Referenced by processICMPError(), and processUDPPacket().

00314 {
00315     // IPv4 version
00316     if (sd->remotePort!=0 && sd->remotePort!=udp->getSourcePort())
00317         return false;
00318     if (!sd->localAddr.isUnspecified() && sd->localAddr.get4()!=ipCtrl->getDestAddr())
00319         return false;
00320     if (!sd->remoteAddr.isUnspecified() && sd->remoteAddr.get4()!=ipCtrl->getSrcAddr())
00321         return false;
00322     if (sd->interfaceId!=-1 && sd->interfaceId!=ipCtrl->getInterfaceId())
00323         return false;
00324     return true;
00325 }

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

returns the number of init stages

Returns:
the number of init stages

Definition at line 288 of file SimpleUDP.h.

00289     {
00290         return MAX_STAGE_UNDERLAY + 1;
00291     }

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

process commands from application

Parameters:
msg the command message

Definition at line 739 of file SimpleUDP.cc.

Referenced by handleMessage().

00740 {
00741     UDPControlInfo *udpCtrl = check_and_cast<UDPControlInfo *>(msg->removeControlInfo());
00742     switch (msg->getKind()) {
00743     case UDP_C_BIND:
00744         bind(msg->getArrivalGate()->getIndex(), udpCtrl);
00745         break;
00746     case UDP_C_CONNECT:
00747         connect(udpCtrl->getSockId(), udpCtrl->getDestAddr(), udpCtrl->getDestPort());
00748         break;
00749     case UDP_C_UNBIND:
00750         unbind(udpCtrl->getSockId());
00751         break;
00752     default:
00753         error("unknown command code (message kind) %d received from app", msg->getKind());
00754     }
00755 
00756     delete udpCtrl;
00757     delete msg;
00758 }

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

process an ICMP error packet

Parameters:
icmpErrorMsg the received icmp Message

Definition at line 413 of file SimpleUDP.cc.

Referenced by handleMessage().

00414 {
00415     // extract details from the error message, then try to notify socket that sent bogus packet
00416     int type = 0;
00417     int code = 0;
00418     IPvXAddress localAddr, remoteAddr;
00419     int localPort = 0;
00420     int remotePort = 0;
00421 
00422     if (dynamic_cast<ICMPMessage *>(msg)) {
00423         ICMPMessage *icmpMsg = (ICMPMessage *)msg;
00424         type = icmpMsg->getType();
00425         code = icmpMsg->getCode();
00426         icmpMsg->setBitLength(icmpMsg->getEncapsulatedPacket()->getBitLength()); // trick because payload in ICMP is conceptually truncated
00427         IPDatagram *datagram = check_and_cast<IPDatagram *>(icmpMsg->decapsulate());
00428         localAddr = datagram->getSrcAddress();
00429         remoteAddr = datagram->getDestAddress();
00430         SimpleUDPPacket *packet = check_and_cast<SimpleUDPPacket *>(datagram->decapsulate());
00431         localPort = packet->getSourcePort();
00432         remotePort = packet->getDestinationPort();
00433         delete icmpMsg;
00434         delete datagram;
00435         delete packet;
00436     } else if (dynamic_cast<ICMPv6Message *>(msg)) {
00437         ICMPv6Message *icmpMsg = (ICMPv6Message *)msg;
00438         type = icmpMsg->getType();
00439         code = -1; // FIXME this is dependent on getType()...
00440         IPv6Datagram *datagram = check_and_cast<IPv6Datagram *>(icmpMsg->decapsulate());
00441         localAddr = datagram->getSrcAddress();
00442         remoteAddr = datagram->getDestAddress();
00443         SimpleUDPPacket *packet = check_and_cast<SimpleUDPPacket *>(datagram->decapsulate());
00444         localPort = packet->getSourcePort();
00445         remotePort = packet->getDestinationPort();
00446         delete icmpMsg;
00447         delete datagram;
00448         delete packet;
00449     }
00450     EV << "[SimpleUDP::processICMPError() @ " << localAddr << "]\n"
00451        << "    ICMP error received: type=" << type << " code=" << code
00452        << "\n    about packet " << localAddr << ":" << localPort << " --> "
00453        << "    " << remoteAddr << ":" << remotePort
00454        << endl;
00455 
00456     // identify socket and report error to it
00457     SocketsByPortMap::iterator it = socketsByPortMap.find(localPort);
00458     if (it==socketsByPortMap.end()) {
00459         EV << "[SimpleUDP::processICMPError() @ " << localAddr << "]\n"
00460            << "    No socket on that local port, ignoring ICMP error"
00461            << endl;
00462         return;
00463     }
00464     SockDescList& list = it->second;
00465     SockDesc *srcSocket = NULL;
00466     for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it) {
00467         SockDesc *sd = *it;
00468         if (sd->onlyLocalPortIsSet || matchesSocket(sd, localAddr, remoteAddr, remotePort)) {
00469             srcSocket = sd; // FIXME what to do if there's more than one matching socket ???
00470         }
00471     }
00472     if (!srcSocket) {
00473         EV << "[SimpleUDP::processICMPError() @ " << localAddr << "]\n"
00474            << "    No matching socket, ignoring ICMP error"
00475            << endl;
00476         return;
00477     }
00478 
00479     // send UDP_I_ERROR to socket
00480     EV << "[SimpleUDP::processICMPError() @ " << localAddr << "]\n"
00481        << "    Source socket is sockId=" << srcSocket->sockId << ", notifying"
00482        << endl;
00483     sendUpErrorNotification(srcSocket, UDP_I_ERROR, localAddr, remoteAddr, remotePort);
00484 }

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

process packets from application

Parameters:
appData the data that has to be sent

Definition at line 590 of file SimpleUDP.cc.

Referenced by handleMessage().

00591 {
00592     cModule *node = getParentModule();
00593 //    IPvXAddress ip = IPAddressResolver().addressOf(node);
00594 //    Speedhack SK
00595 
00596     IPvXAddress srcAddr, destAddr;
00597     //cGate* destGate;
00598 
00599     UDPControlInfo *udpCtrl = check_and_cast<UDPControlInfo *>(appData->removeControlInfo());
00600 
00601     SimpleUDPPacket *udpPacket = new SimpleUDPPacket(appData->getName());
00602 
00603     //
00604     udpPacket->setByteLength(UDP_HEADER_BYTES + IP_HEADER_BYTES);
00605     udpPacket->encapsulate(appData);
00606 
00607     // set source and destination port
00608     udpPacket->setSourcePort(udpCtrl->getSrcPort());
00609     udpPacket->setDestinationPort(udpCtrl->getDestPort());
00610 
00611     srcAddr = udpCtrl->getSrcAddr();
00612     destAddr = udpCtrl->getDestAddr();
00613     if (!udpCtrl->getDestAddr().isIPv6()) {
00614         // send to IPv4
00615         //EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n"
00616         //<< "    Sending app packet " << appData->getName() << " over IPv4"
00617         //<< endl;
00618         IPControlInfo *ipControlInfo = new IPControlInfo();
00619         ipControlInfo->setProtocol(IP_PROT_UDP);
00620         ipControlInfo->setSrcAddr(srcAddr.get4());
00621         ipControlInfo->setDestAddr(destAddr.get4());
00622         ipControlInfo->setInterfaceId(udpCtrl->getInterfaceId());
00623         udpPacket->setControlInfo(ipControlInfo);
00624         delete udpCtrl;
00625     } else {
00626         // send to IPv6
00627         //EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n"
00628         //<< "    Sending app packet " << appData->getName() << " over IPv6"
00629         //<< endl;
00630         IPv6ControlInfo *ipControlInfo = new IPv6ControlInfo();
00631         ipControlInfo->setProtocol(IP_PROT_UDP);
00632         ipControlInfo->setSrcAddr(srcAddr.get6());
00633         ipControlInfo->setDestAddr(destAddr.get6());
00634         // ipControlInfo->setInterfaceId(udpCtrl->InterfaceId()); FIXME extend IPv6 with this!!!
00635         udpPacket->setControlInfo(ipControlInfo);
00636         delete udpCtrl;
00637     }
00638 
00639     SimpleInfo* info = dynamic_cast<SimpleInfo*>(globalNodeList->getPeerInfo(destAddr));
00640     numSent++;
00641 
00642     if (info == NULL) {
00643         EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n"
00644            << "    No route to host " << destAddr
00645            << endl;
00646 
00647         delete udpPacket;
00648         numDestUnavailableLost++;
00649         return;
00650     }
00651 
00652     SimpleNodeEntry* destEntry = info->getEntry();
00653 
00654     // calculate delay
00655     simtime_t totalDelay = 0;
00656     if (srcAddr != destAddr) {
00657         SimpleNodeEntry::SimpleDelay temp;
00658         if (faultyDelay) {
00659             SimpleInfo* thisInfo = static_cast<SimpleInfo*>(globalNodeList->getPeerInfo(srcAddr));
00660             temp = nodeEntry->calcDelay(udpPacket, *destEntry,
00661                                         !(thisInfo->getNpsLayer() == 0 ||
00662                                           info->getNpsLayer() == 0)); //TODO
00663         } else {
00664             temp = nodeEntry->calcDelay(udpPacket, *destEntry);
00665         }
00666         if (useCoordinateBasedDelay == false) {
00667             totalDelay = constantDelay;
00668         } else if (temp.second == false) {
00669             EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n"
00670                << "    Send queue full: packet " << udpPacket << " dropped"
00671                << endl;
00672             delete udpPacket;
00673             numQueueLost++;
00674             return;
00675         } else {
00676             totalDelay = temp.first;
00677         }
00678     }
00679 
00680     SimpleInfo* thisInfo = dynamic_cast<SimpleInfo*>(globalNodeList->getPeerInfo(srcAddr));
00681 
00682     if (!globalNodeList->areNodeTypesConnected(thisInfo->getTypeID(), info->getTypeID())) {
00683         EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n"
00684                    << "    Partition " << thisInfo->getTypeID() << "->" << info->getTypeID()
00685                    << " is not connected"
00686                    << endl;
00687         delete udpPacket;
00688         numPartitionLost++;
00689         return;
00690     }
00691 
00692     if (jitter) {
00693         // jitter
00694         //totalDelay += truncnormal(0, SIMTIME_DBL(totalDelay) * jitter);
00695 
00696         //workaround (bug in truncnormal(): sometimes returns inf)
00697         double temp = truncnormal(0, SIMTIME_DBL(totalDelay) * jitter);
00698         while (temp == INFINITY || temp != temp) { // reroll if temp is INF or NaN
00699             std::cerr << "\n******* SimpleUDP: truncnormal() -> inf !!\n"
00700                       << std::endl;
00701             temp = truncnormal(0, SIMTIME_DBL(totalDelay) * jitter);
00702         }
00703 
00704         totalDelay += temp;
00705     }
00706 
00707     if (udpPacket != NULL) {
00708         BaseOverlayMessage* temp = NULL;
00709 
00710         if (ev.isGUI() && udpPacket->getEncapsulatedPacket()) {
00711             if ((temp = dynamic_cast<BaseOverlayMessage*>(udpPacket
00712                     ->getEncapsulatedPacket()))) {
00713                 switch (temp->getStatType()) {
00714                 case APP_DATA_STAT:
00715                     udpPacket->setKind(1);
00716                     break;
00717                 case APP_LOOKUP_STAT:
00718                     udpPacket->setKind(2);
00719                     break;
00720                 case MAINTENANCE_STAT:
00721                 default:
00722                     udpPacket->setKind(3);
00723                 }
00724             } else {
00725                 udpPacket->setKind(1);
00726             }
00727         }
00728 
00729         EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n"
00730            << "    Packet " << udpPacket << " sent with delay = " << totalDelay
00731            << endl;
00732 
00733         //RECORD_STATS(globalStatistics->addStdDev("SimpleUDP: delay", totalDelay));
00734 
00735         sendDirect(udpPacket, totalDelay, 0, destEntry->getGate());
00736     }
00737 }

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

process UDP packets coming from IP

Parameters:
udpPacket the received packet

Definition at line 501 of file SimpleUDP.cc.

Referenced by handleMessage().

00502 {
00503     cModule *node = getParentModule();
00504 //    IPvXAddress ip = IPAddressResolver().addressOf(node);
00505 //    Speedhack SK
00506 
00507     // simulate checksum: discard packet if it has bit error
00508     EV << "[SimpleUDP::processUDPPacket() @ " << IPAddressResolver().addressOf(node) << "]\n"
00509        << "    Packet " << udpPacket->getName() << " received from network, dest port " << udpPacket->getDestinationPort()
00510        << endl;
00511 
00512     if (udpPacket->hasBitError()) {
00513         EV << "[SimpleUDP::processUDPPacket() @ " << IPAddressResolver().addressOf(node) << "]\n"
00514            << "    Packet has bit error, discarding"
00515            << endl;
00516         delete udpPacket;
00517         numDroppedBadChecksum++;
00518         return;
00519     }
00520 
00521     int destPort = udpPacket->getDestinationPort();
00522     cPolymorphic *ctrl = udpPacket->removeControlInfo();
00523 
00524     // send back ICMP error if no socket is bound to that port
00525     SocketsByPortMap::iterator it = socketsByPortMap.find(destPort);
00526     if (it==socketsByPortMap.end()) {
00527         EV << "[SimpleUDP::processUDPPacket() @ " << IPAddressResolver().addressOf(node) << "]\n"
00528            << "    No socket registered on port " << destPort
00529            << endl;
00530         processUndeliverablePacket(udpPacket, ctrl);
00531         return;
00532     }
00533     SockDescList& list = it->second;
00534 
00535     int matches = 0;
00536 
00537     // deliver a copy of the packet to each matching socket
00538     //    cMessage *payload = udpPacket->getEncapsulatedPacket();
00539     cMessage *payload = udpPacket->decapsulate();
00540     if (dynamic_cast<IPControlInfo *>(ctrl)!=NULL) {
00541         IPControlInfo *ctrl4 = (IPControlInfo *)ctrl;
00542         for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it) {
00543             SockDesc *sd = *it;
00544             if (sd->onlyLocalPortIsSet || matchesSocket(sd, udpPacket, ctrl4)) {
00545 //              EV << "[SimpleUDP::processUDPPacket() @ " << IPAddressResolver().addressOf(node) << "]\n"
00546 //                 << "    Socket sockId=" << sd->sockId << " matches, sending up a copy"
00547 //                 << endl;
00548 //              sendUp((cMessage*)payload->dup(), udpPacket, ctrl4, sd);
00549 //              ib: speed hack
00550 
00551                 if (matches == 0) {
00552                     sendUp(payload, udpPacket, ctrl4, sd);
00553                 } else
00554                     opp_error("Edit SimpleUDP.cc to support multibinding.");
00555                 matches++;
00556             }
00557         }
00558     } else if (dynamic_cast<IPv6ControlInfo *>(udpPacket->getControlInfo())
00559                !=NULL) {
00560         IPv6ControlInfo *ctrl6 = (IPv6ControlInfo *)ctrl;
00561         for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it) {
00562             SockDesc *sd = *it;
00563             if (sd->onlyLocalPortIsSet || matchesSocket(sd, udpPacket, ctrl6)) {
00564                 EV << "[SimpleUDP::processUDPPacket() @ " << IPAddressResolver().addressOf(node) << "]\n"
00565                    << "    Socket sockId=" << sd->sockId << " matches, sending up a copy"
00566                    << endl;
00567                 sendUp((cMessage*)payload->dup(), udpPacket, ctrl6, sd);
00568                 matches++;
00569             }
00570         }
00571     } else {
00572         error("(%s)%s arrived from lower layer without control info", udpPacket->getClassName(), udpPacket->getName());
00573     }
00574 
00575     // send back ICMP error if there is no matching socket
00576     if (matches==0) {
00577         EV << "[SimpleUDP::processUDPPacket() @ " << IPAddressResolver().addressOf(node) << "]\n"
00578            << "    None of the sockets on port " << destPort << " matches the packet"
00579            << endl;
00580         processUndeliverablePacket(udpPacket, ctrl)
00581         ;
00582         return;
00583     }
00584 
00585     delete udpPacket;
00586     delete ctrl;
00587 }

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

Definition at line 382 of file SimpleUDP.cc.

Referenced by processUDPPacket().

00383 {
00384     numDroppedWrongPort++;
00385 
00386     // send back ICMP PORT_UNREACHABLE
00387     if (dynamic_cast<IPControlInfo *>(ctrl)!=NULL) {
00388 /*        if (!icmp)
00389             icmp = ICMPAccess().get();
00390         IPControlInfo *ctrl4 = (IPControlInfo *)ctrl;
00391         if (!ctrl4->getDestAddr().isMulticast())
00392             icmp->sendErrorMessage(udpPacket, ctrl4, ICMP_DESTINATION_UNREACHABLE, ICMP_DU_PORT_UNREACHABLE);*/
00393         /* TODO: implement icmp module */
00394         EV << "[SimpleUDP::processUndeliverablePacket()]\n"
00395                 << "    Dropped packet bound to unreserved port, ignoring ICMP error"
00396                 << endl;
00397     } else if (dynamic_cast<IPv6ControlInfo *>(udpPacket->getControlInfo())
00398                !=NULL) {
00399 /*        if (!icmpv6)
00400             icmpv6 = ICMPv6Access().get();
00401         IPv6ControlInfo *ctrl6 = (IPv6ControlInfo *)ctrl;
00402         if (!ctrl6->getDestAddr().isMulticast())
00403             icmpv6->sendErrorMessage(udpPacket, ctrl6, ICMPv6_DESTINATION_UNREACHABLE, PORT_UNREACHABLE);*/
00404         /* TODO: implement icmp module */
00405         EV << "[SimpleUDP::processUndeliverablePacket()]\n"
00406            << "    Dropped packet bound to unreserved port, ignoring ICMP error"
00407            << endl;
00408     } else {
00409         error("(%s)%s arrived from lower layer without control info", udpPacket->getClassName(), udpPacket->getName());
00410     }
00411 }

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

Definition at line 365 of file SimpleUDP.cc.

00366 {
00367     // send payload with UDPControlInfo up to the application -- IPv6 version
00368     UDPControlInfo *udpCtrl = new UDPControlInfo();
00369     udpCtrl->setSockId(sd->sockId);
00370     udpCtrl->setUserId(sd->userId);
00371     udpCtrl->setSrcAddr(ipCtrl->getSrcAddr());
00372     udpCtrl->setDestAddr(ipCtrl->getDestAddr());
00373     udpCtrl->setSrcPort(udpHeader->getSourcePort());
00374     udpCtrl->setDestPort(udpHeader->getDestinationPort());
00375     udpCtrl->setInterfaceId(ipCtrl->getInterfaceId());
00376     payload->setControlInfo(udpCtrl);
00377 
00378     send(payload, "appOut", sd->appGateIndex);
00379     numPassedUp++;
00380 }

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

Definition at line 348 of file SimpleUDP.cc.

Referenced by processUDPPacket().

00349 {
00350     // send payload with UDPControlInfo up to the application -- IPv4 version
00351     UDPControlInfo *udpCtrl = new UDPControlInfo();
00352     udpCtrl->setSockId(sd->sockId);
00353     udpCtrl->setUserId(sd->userId);
00354     udpCtrl->setSrcAddr(ipCtrl->getSrcAddr());
00355     udpCtrl->setDestAddr(ipCtrl->getDestAddr());
00356     udpCtrl->setSrcPort(udpHeader->getSourcePort());
00357     udpCtrl->setDestPort(udpHeader->getDestinationPort());
00358     udpCtrl->setInterfaceId(ipCtrl->getInterfaceId());
00359     payload->setControlInfo(udpCtrl);
00360 
00361     send(payload, "appOut", sd->appGateIndex);
00362     numPassedUp++;
00363 }

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

Definition at line 486 of file SimpleUDP.cc.

Referenced by processICMPError().

00487 {
00488     cMessage *notifyMsg = new cMessage("ERROR", msgkind);
00489     UDPControlInfo *udpCtrl = new UDPControlInfo();
00490     udpCtrl->setSockId(sd->sockId);
00491     udpCtrl->setUserId(sd->userId);
00492     udpCtrl->setSrcAddr(localAddr);
00493     udpCtrl->setDestAddr(remoteAddr);
00494     udpCtrl->setSrcPort(sd->localPort);
00495     udpCtrl->setDestPort(remotePort);
00496     notifyMsg->setControlInfo(udpCtrl);
00497 
00498     send(notifyMsg, "appOut", sd->appGateIndex);
00499 }

void SimpleUDP::setNodeEntry ( SimpleNodeEntry entry  ) 

set or change the nodeEntry of this module

Parameters:
entry the new nodeEntry

Definition at line 761 of file SimpleUDP.cc.

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

00762 {
00763     nodeEntry = entry;
00764 }

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

unbind socket

Parameters:
sockId id of the socket to unbind

Definition at line 234 of file SimpleUDP.cc.

Referenced by processCommandFromApp().

00235 {
00236     // remove from socketsByIdMap
00237     SocketsByIdMap::iterator it = socketsByIdMap.find(sockId);
00238     if (it==socketsByIdMap.end())
00239         error("socket id=%d doesn't exist (already closed?)", sockId);
00240     SockDesc *sd = it->second;
00241     socketsByIdMap.erase(it);
00242 
00243     EV << "[SimpleUDP::unbind() @ " << sd->localAddr << "]\n"
00244        << "    Unbinding socket: " << *sd
00245        << endl;
00246 
00247     // remove from socketsByPortMap
00248     SockDescList& list = socketsByPortMap[sd->localPort];
00249     for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it)
00250         if (*it == sd) {
00251             list.erase(it);
00252             break;
00253         }
00254     if (list.empty())
00255         socketsByPortMap.erase(sd->localPort);
00256     delete sd;
00257 }

void SimpleUDP::updateDisplayString (  )  [protected]

utility: show current statistics above the icon

Definition at line 298 of file SimpleUDP.cc.

Referenced by handleMessage().

00299 {
00300     char buf[80];
00301     sprintf(buf, "passed up: %d pks\nsent: %d pks", numPassedUp, numSent);
00302     if (numDroppedWrongPort>0) {
00303         sprintf(buf+strlen(buf), "\ndropped (no app): %d pks", numDroppedWrongPort);
00304         getDisplayString().setTagArg("i",1,"red");
00305     }
00306     if (numQueueLost>0) {
00307         sprintf(buf+strlen(buf), "\nlost (queue overflow): %d pks", numQueueLost);
00308         getDisplayString().setTagArg("i",1,"red");
00309     }
00310     getDisplayString().setTagArg("t",0,buf);
00311 }


Member Data Documentation

simtime_t SimpleUDP::constantDelay [protected]

constant delay between two peers

Definition at line 118 of file SimpleUDP.h.

Referenced by initialize(), and processMsgFromApp().

simtime_t SimpleUDP::delay [protected]

simulated delay between sending and receiving udp module

Definition at line 116 of file SimpleUDP.h.

Definition at line 96 of file SimpleUDP.h.

Referenced by SimpleNodeEntry::getFaultyDelay(), and initialize().

std::string SimpleUDP::delayFaultTypeString [static]

Definition at line 89 of file SimpleUDP.h.

Referenced by SimpleNodeEntry::getFaultyDelay(), and initialize().

bool SimpleUDP::faultyDelay [protected]

Definition at line 121 of file SimpleUDP.h.

Referenced by initialize(), and processMsgFromApp().

violate the triangle inequality?

pointer to GlobalNodeList

Definition at line 122 of file SimpleUDP.h.

Referenced by initialize(), and processMsgFromApp().

pointer to GlobalStatistics

Definition at line 123 of file SimpleUDP.h.

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

ICMP* SimpleUDP::icmp [protected]

pointer to a received icmp (IPv4) message

Definition at line 105 of file SimpleUDP.h.

Referenced by initialize().

ICMPv6* SimpleUDP::icmpv6 [protected]

pointer to a received icmp (IPv6) message

Definition at line 106 of file SimpleUDP.h.

Referenced by initialize().

double SimpleUDP::jitter [protected]

amount of jitter in % of total delay

Definition at line 120 of file SimpleUDP.h.

Referenced by initialize(), and processMsgFromApp().

short SimpleUDP::lastEphemeralPort [protected]

last used port (all ports above should be free)

Definition at line 104 of file SimpleUDP.h.

Referenced by getEphemeralPort(), and initialize().

nodeEntry of the overlay node this module belongs to

Definition at line 124 of file SimpleUDP.h.

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

number of lost packets due to unavailable destination

Definition at line 115 of file SimpleUDP.h.

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

number of dropped packets due to bad checksum

Definition at line 112 of file SimpleUDP.h.

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

number of dropped packets due to wrong destination port

Definition at line 111 of file SimpleUDP.h.

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

int SimpleUDP::numPartitionLost [protected]

number of lost packets due to network partitions

Definition at line 114 of file SimpleUDP.h.

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

int SimpleUDP::numPassedUp [protected]

number of packet passed up to applications

Definition at line 110 of file SimpleUDP.h.

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

int SimpleUDP::numQueueLost [protected]

number of lost packets due to queue full

Definition at line 113 of file SimpleUDP.h.

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

int SimpleUDP::numSent [protected]

number of packets sent to the network

Definition at line 109 of file SimpleUDP.h.

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

list of socket ordered by sockId

Definition at line 100 of file SimpleUDP.h.

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

list of sockets ordered by localPort

Definition at line 101 of file SimpleUDP.h.

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

delay should be calculated from euklidean distance between two peers

Definition at line 119 of file SimpleUDP.h.

Referenced by initialize(), and processMsgFromApp().


The documentation for this class was generated from the following files:
Generated on Wed May 26 16:21:19 2010 for OverSim by  doxygen 1.6.3