SimpleUDP.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2000 Institut fuer Telematik, Universitaet Karlsruhe
00003 // Copyright (C) 2004,2005 Andras Varga
00004 //
00005 // This program is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU General Public License
00007 // as published by the Free Software Foundation; either version 2
00008 // of the License, or (at your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00018 //
00019 
00025 //
00026 // Author: Jochen Reber
00027 // Rewrite: Andras Varga 2004,2005
00028 // Modifications: Stephan Krause
00029 //
00030 
00031 #include <omnetpp.h>
00032 
00033 #include <CommonMessages_m.h>
00034 #include <GlobalNodeListAccess.h>
00035 #include <GlobalStatisticsAccess.h>
00036 
00037 #include <SimpleInfo.h>
00038 #include "SimpleUDPPacket.h"
00039 #include "SimpleUDP.h"
00040 #include "IPControlInfo.h"
00041 #include "IPv6ControlInfo.h"
00042 #include "ICMPAccess.h"
00043 #include "ICMPv6Access.h"
00044 #include "IPAddressResolver.h"
00045 
00046 // the following is only for ICMP error processing
00047 #include "ICMPMessage_m.h"
00048 #include "ICMPv6Message_m.h"
00049 #include "IPDatagram_m.h"
00050 #include "IPv6Datagram_m.h"
00051 
00052 
00053 #define EPHEMERAL_PORTRANGE_START 1024
00054 #define EPHEMERAL_PORTRANGE_END   5000
00055 
00056 
00057 Define_Module( SimpleUDP );
00058 
00059 std::string SimpleUDP::delayFaultTypeString;
00060 std::map<std::string, SimpleUDP::delayFaultTypeNum> SimpleUDP::delayFaultTypeMap;
00061 
00062 static std::ostream & operator<<(std::ostream & os,
00063                                  const SimpleUDP::SockDesc& sd)
00064 {
00065     os << "sockId=" << sd.sockId;
00066     os << " appGateIndex=" << sd.appGateIndex;
00067     os << " userId=" << sd.userId;
00068     os << " localPort=" << sd.localPort;
00069     if (sd.remotePort!=0)
00070         os << " remotePort=" << sd.remotePort;
00071     if (!sd.localAddr.isUnspecified())
00072         os << " localAddr=" << sd.localAddr;
00073     if (!sd.remoteAddr.isUnspecified())
00074         os << " remoteAddr=" << sd.remoteAddr;
00075     if (sd.interfaceId!=-1)
00076         os << " interfaceId=" << sd.interfaceId;
00077 
00078     return os;
00079 }
00080 
00081 static std::ostream & operator<<(std::ostream & os,
00082                                  const SimpleUDP::SockDescList& list)
00083 {
00084     for (SimpleUDP::SockDescList::const_iterator i=list.begin();
00085          i!=list.end(); ++i)
00086         os << "sockId=" << (*i)->sockId << " ";
00087     return os;
00088 }
00089 
00090 //--------
00091 
00092 SimpleUDP::SimpleUDP()
00093 {
00094     globalStatistics = NULL;
00095 }
00096 
00097 SimpleUDP::~SimpleUDP()
00098 {
00099     for (SocketsByIdMap::iterator i=socketsByIdMap.begin();
00100     i!=socketsByIdMap.end(); ++i)
00101         delete i->second;
00102 }
00103 
00104 void SimpleUDP::initialize(int stage)
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 }
00154 
00155 void SimpleUDP::finish()
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 }
00168 
00169 void SimpleUDP::bind(int gateIndex, UDPControlInfo *ctrl)
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 }
00212 
00213 void SimpleUDP::connect(int sockId, IPvXAddress addr, int port)
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 }
00233 
00234 void SimpleUDP::unbind(int sockId)
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 }
00258 
00259 short SimpleUDP::getEphemeralPort()
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 }
00277 
00278 void SimpleUDP::handleMessage(cMessage *msg)
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 }
00297 
00298 void SimpleUDP::updateDisplayString()
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 }
00312 
00313 bool SimpleUDP::matchesSocket(SockDesc *sd, SimpleUDPPacket *udp, IPControlInfo *ipCtrl)
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 }
00326 
00327 bool SimpleUDP::matchesSocket(SockDesc *sd, SimpleUDPPacket *udp, IPv6ControlInfo *ipCtrl)
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 }
00340 
00341 bool SimpleUDP::matchesSocket(SockDesc *sd, const IPvXAddress& localAddr, const IPvXAddress& remoteAddr, short remotePort)
00342 {
00343     return (sd->remotePort==0 || sd->remotePort!=remotePort) &&
00344            (sd->localAddr.isUnspecified() || sd->localAddr==localAddr) &&
00345            (sd->remoteAddr.isUnspecified() || sd->remoteAddr==remoteAddr);
00346 }
00347 
00348 void SimpleUDP::sendUp(cMessage *payload, SimpleUDPPacket *udpHeader, IPControlInfo *ipCtrl, SockDesc *sd)
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 }
00364 
00365 void SimpleUDP::sendUp(cMessage *payload, SimpleUDPPacket *udpHeader, IPv6ControlInfo *ipCtrl, SockDesc *sd)
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 }
00381 
00382 void SimpleUDP::processUndeliverablePacket(SimpleUDPPacket *udpPacket, cPolymorphic *ctrl)
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 }
00412 
00413 void SimpleUDP::processICMPError(cMessage *msg)
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 }
00485 
00486 void SimpleUDP::sendUpErrorNotification(SockDesc *sd, int msgkind, const IPvXAddress& localAddr, const IPvXAddress& remoteAddr, short remotePort)
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 }
00500 
00501 void SimpleUDP::processUDPPacket(SimpleUDPPacket *udpPacket)
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 }
00588 
00589 
00590 void SimpleUDP::processMsgFromApp(cPacket *appData)
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 }
00738 
00739 void SimpleUDP::processCommandFromApp(cMessage *msg)
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 }
00759 
00760 
00761 void SimpleUDP::setNodeEntry(SimpleNodeEntry* entry)
00762 {
00763     nodeEntry = entry;
00764 }
Generated on Wed May 26 16:21:15 2010 for OverSim by  doxygen 1.6.3