#include <UDP.h>
Classes | |
struct | SockDesc |
Public Types | |
typedef std::list< SockDesc * > | SockDescList |
typedef std::map< int, SockDesc * > | SocketsByIdMap |
typedef std::map< int, SockDescList > | SocketsByPortMap |
Public Member Functions | |
UDP () | |
virtual | ~UDP () |
Protected Member Functions | |
virtual void | updateDisplayString () |
virtual void | bind (int gateIndex, UDPControlInfo *ctrl) |
virtual void | connect (int sockId, IPvXAddress addr, int port) |
virtual void | unbind (int sockId) |
virtual ushort | getEphemeralPort () |
virtual bool | matchesSocket (SockDesc *sd, UDPPacket *udp, IPControlInfo *ctrl) |
virtual bool | matchesSocket (SockDesc *sd, UDPPacket *udp, IPv6ControlInfo *ctrl) |
virtual bool | matchesSocket (SockDesc *sd, const IPvXAddress &localAddr, const IPvXAddress &remoteAddr, ushort remotePort) |
virtual void | sendUp (cPacket *payload, UDPPacket *udpHeader, IPControlInfo *ctrl, SockDesc *sd) |
virtual void | sendUp (cPacket *payload, UDPPacket *udpHeader, IPv6ControlInfo *ctrl, SockDesc *sd) |
virtual void | processUndeliverablePacket (UDPPacket *udpPacket, cPolymorphic *ctrl) |
virtual void | sendUpErrorNotification (SockDesc *sd, int msgkind, const IPvXAddress &localAddr, const IPvXAddress &remoteAddr, ushort remotePort) |
virtual void | processICMPError (cPacket *icmpErrorMsg) |
virtual void | processUDPPacket (UDPPacket *udpPacket) |
virtual void | processMsgFromApp (cPacket *appData) |
virtual void | processCommandFromApp (cMessage *msg) |
virtual UDPPacket * | createUDPPacket (const char *name) |
virtual void | initialize () |
virtual void | handleMessage (cMessage *msg) |
Protected Attributes | |
SocketsByIdMap | socketsByIdMap |
SocketsByPortMap | socketsByPortMap |
ushort | lastEphemeralPort |
ICMP * | icmp |
ICMPv6 * | icmpv6 |
int | numSent |
int | numPassedUp |
int | numDroppedWrongPort |
int | numDroppedBadChecksum |
Implements the UDP protocol: encapsulates/decapsulates user data into/from UDP.
More info in the NED file.
Definition at line 46 of file UDP.h.
typedef std::list<SockDesc *> UDP::SockDescList |
typedef std::map<int,SockDesc *> UDP::SocketsByIdMap |
typedef std::map<int,SockDescList> UDP::SocketsByPortMap |
UDP::~UDP | ( | ) | [virtual] |
Definition at line 75 of file UDP.cc.
{ for (SocketsByIdMap::iterator i=socketsByIdMap.begin(); i!=socketsByIdMap.end(); ++i) delete i->second; }
void UDP::bind | ( | int | gateIndex, | |
UDPControlInfo * | ctrl | |||
) | [protected, virtual] |
Definition at line 100 of file UDP.cc.
Referenced by processCommandFromApp().
{ // XXX checks could be added, of when the bind should be allowed to proceed // create and fill in SockDesc SockDesc *sd = new SockDesc(); sd->sockId = ctrl->getSockId(); sd->userId = ctrl->getUserId(); sd->appGateIndex = gateIndex; sd->localAddr = ctrl->getSrcAddr(); sd->remoteAddr = ctrl->getDestAddr(); sd->localPort = ctrl->getSrcPort(); sd->remotePort = ctrl->getDestPort(); sd->interfaceId = ctrl->getInterfaceId(); if (sd->sockId==-1) error("sockId in BIND message not filled in"); if (sd->localPort==0) sd->localPort = getEphemeralPort(); sd->onlyLocalPortIsSet = sd->localAddr.isUnspecified() && sd->remoteAddr.isUnspecified() && sd->remotePort==0 && sd->interfaceId==-1; EV << "Binding socket: " << *sd << "\n"; // add to socketsByIdMap ASSERT(socketsByIdMap.find(sd->sockId)==socketsByIdMap.end()); socketsByIdMap[sd->sockId] = sd; // add to socketsByPortMap SockDescList& list = socketsByPortMap[sd->localPort]; // create if doesn't exist list.push_back(sd); }
void UDP::connect | ( | int | sockId, | |
IPvXAddress | addr, | |||
int | port | |||
) | [protected, virtual] |
Definition at line 136 of file UDP.cc.
Referenced by processCommandFromApp().
{ SocketsByIdMap::iterator it = socketsByIdMap.find(sockId); if (it==socketsByIdMap.end()) error("socket id=%d doesn't exist (already closed?)", sockId); if (addr.isUnspecified()) opp_error("connect: unspecified remote address"); if (port<=0 || port>65535) opp_error("connect: invalid remote port number %d", port); SockDesc *sd = it->second; sd->remoteAddr = addr; sd->remotePort = port; sd->onlyLocalPortIsSet = false; EV << "Connecting socket: " << *sd << "\n"; }
UDPPacket * UDP::createUDPPacket | ( | const char * | name | ) | [protected, virtual] |
Definition at line 526 of file UDP.cc.
Referenced by processMsgFromApp().
{ return new UDPPacket(name); }
ushort UDP::getEphemeralPort | ( | ) | [protected, virtual] |
Definition at line 176 of file UDP.cc.
Referenced by bind().
{ // start at the last allocated port number + 1, and search for an unused one ushort searchUntil = lastEphemeralPort++; if (lastEphemeralPort == EPHEMERAL_PORTRANGE_END) // wrap lastEphemeralPort = EPHEMERAL_PORTRANGE_START; while (socketsByPortMap.find(lastEphemeralPort)!=socketsByPortMap.end()) { if (lastEphemeralPort == searchUntil) // got back to starting point? error("Ephemeral port range %d..%d exhausted, all ports occupied", EPHEMERAL_PORTRANGE_START, EPHEMERAL_PORTRANGE_END); lastEphemeralPort++; if (lastEphemeralPort == EPHEMERAL_PORTRANGE_END) // wrap lastEphemeralPort = EPHEMERAL_PORTRANGE_START; } // found a free one, return it return lastEphemeralPort; }
void UDP::handleMessage | ( | cMessage * | msg | ) | [protected, virtual] |
Definition at line 196 of file UDP.cc.
{ // received from IP layer if (msg->arrivedOn("ipIn") || msg->arrivedOn("ipv6In")) { if (dynamic_cast<ICMPMessage *>(msg) || dynamic_cast<ICMPv6Message *>(msg)) processICMPError(PK(msg)); else processUDPPacket(check_and_cast<UDPPacket *>(msg)); } else // received from application layer { if (msg->getKind()==UDP_C_DATA) processMsgFromApp(PK(msg)); else processCommandFromApp(msg); } if (ev.isGUI()) updateDisplayString(); }
void UDP::initialize | ( | ) | [protected, virtual] |
Definition at line 81 of file UDP.cc.
{ WATCH_PTRMAP(socketsByIdMap); WATCH_MAP(socketsByPortMap); lastEphemeralPort = EPHEMERAL_PORTRANGE_START; icmp = NULL; icmpv6 = NULL; numSent = 0; numPassedUp = 0; numDroppedWrongPort = 0; numDroppedBadChecksum = 0; WATCH(numSent); WATCH(numPassedUp); WATCH(numDroppedWrongPort); WATCH(numDroppedBadChecksum); }
bool UDP::matchesSocket | ( | SockDesc * | sd, | |
const IPvXAddress & | localAddr, | |||
const IPvXAddress & | remoteAddr, | |||
ushort | remotePort | |||
) | [protected, virtual] |
bool UDP::matchesSocket | ( | SockDesc * | sd, | |
UDPPacket * | udp, | |||
IPControlInfo * | ctrl | |||
) | [protected, virtual] |
Definition at line 230 of file UDP.cc.
Referenced by processICMPError(), and processUDPPacket().
{ // IPv4 version if (sd->remotePort!=0 && sd->remotePort!=udp->getSourcePort()) return false; if (!sd->localAddr.isUnspecified() && sd->localAddr.get4()!=ipCtrl->getDestAddr()) return false; if (!sd->remoteAddr.isUnspecified() && sd->remoteAddr.get4()!=ipCtrl->getSrcAddr()) return false; if (sd->interfaceId!=-1 && sd->interfaceId!=ipCtrl->getInterfaceId()) return false; return true; }
bool UDP::matchesSocket | ( | SockDesc * | sd, | |
UDPPacket * | udp, | |||
IPv6ControlInfo * | ctrl | |||
) | [protected, virtual] |
Definition at line 244 of file UDP.cc.
{ // IPv6 version if (sd->remotePort!=0 && sd->remotePort!=udp->getSourcePort()) return false; if (!sd->localAddr.isUnspecified() && sd->localAddr.get6()!=ipCtrl->getDestAddr()) return false; if (!sd->remoteAddr.isUnspecified() && sd->remoteAddr.get6()!=ipCtrl->getSrcAddr()) return false; if (sd->interfaceId!=-1 && sd->interfaceId!=ipCtrl->getInterfaceId()) return false; return true; }
void UDP::processCommandFromApp | ( | cMessage * | msg | ) | [protected, virtual] |
Definition at line 531 of file UDP.cc.
Referenced by handleMessage().
{ UDPControlInfo *udpCtrl = check_and_cast<UDPControlInfo *>(msg->removeControlInfo()); switch (msg->getKind()) { case UDP_C_BIND: bind(msg->getArrivalGate()->getIndex(), udpCtrl); break; case UDP_C_CONNECT: connect(udpCtrl->getSockId(), udpCtrl->getDestAddr(), udpCtrl->getDestPort()); break; case UDP_C_UNBIND: unbind(udpCtrl->getSockId()); break; default: error("unknown command code (message kind) %d received from app", msg->getKind()); } delete udpCtrl; delete msg; }
void UDP::processICMPError | ( | cPacket * | icmpErrorMsg | ) | [protected, virtual] |
Definition at line 326 of file UDP.cc.
Referenced by handleMessage().
{ // extract details from the error message, then try to notify socket that sent bogus packet int type, code; IPvXAddress localAddr, remoteAddr; ushort localPort, remotePort; if (dynamic_cast<ICMPMessage *>(msg)) { ICMPMessage *icmpMsg = (ICMPMessage *)msg; type = icmpMsg->getType(); code = icmpMsg->getCode(); // Note: we must NOT use decapsulate() because payload in ICMP is conceptually truncated IPDatagram *datagram = check_and_cast<IPDatagram *>(icmpMsg->getEncapsulatedMsg()); UDPPacket *packet = check_and_cast<UDPPacket *>(datagram->getEncapsulatedMsg()); localAddr = datagram->getSrcAddress(); remoteAddr = datagram->getDestAddress(); localPort = packet->getSourcePort(); remotePort = packet->getDestinationPort(); delete icmpMsg; } else if (dynamic_cast<ICMPv6Message *>(msg)) { ICMPv6Message *icmpMsg = (ICMPv6Message *)msg; type = icmpMsg->getType(); code = -1; // FIXME this is dependent on getType()... // Note: we must NOT use decapsulate() because payload in ICMP is conceptually truncated IPv6Datagram *datagram = check_and_cast<IPv6Datagram *>(icmpMsg->getEncapsulatedMsg()); UDPPacket *packet = check_and_cast<UDPPacket *>(datagram->getEncapsulatedMsg()); localAddr = datagram->getSrcAddress(); remoteAddr = datagram->getDestAddress(); localPort = packet->getSourcePort(); remotePort = packet->getDestinationPort(); delete icmpMsg; } EV << "ICMP error received: type=" << type << " code=" << code << " about packet " << localAddr << ":" << localPort << " > " << remoteAddr << ":" << remotePort << "\n"; // identify socket and report error to it SocketsByPortMap::iterator it = socketsByPortMap.find(localPort); if (it==socketsByPortMap.end()) { EV << "No socket on that local port, ignoring ICMP error\n"; return; } SockDescList& list = it->second; SockDesc *srcSocket = NULL; for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it) { SockDesc *sd = *it; if (sd->onlyLocalPortIsSet || matchesSocket(sd, localAddr, remoteAddr, remotePort)) { srcSocket = sd; // FIXME what to do if there's more than one matching socket ??? } } if (!srcSocket) { EV << "No matching socket, ignoring ICMP error\n"; return; } // send UDP_I_ERROR to socket EV << "Source socket is sockId=" << srcSocket->sockId << ", notifying.\n"; sendUpErrorNotification(srcSocket, UDP_I_ERROR, localAddr, remoteAddr, remotePort); }
void UDP::processMsgFromApp | ( | cPacket * | appData | ) | [protected, virtual] |
Definition at line 483 of file UDP.cc.
Referenced by handleMessage().
{ UDPControlInfo *udpCtrl = check_and_cast<UDPControlInfo *>(appData->removeControlInfo()); UDPPacket *udpPacket = createUDPPacket(appData->getName()); udpPacket->setByteLength(UDP_HEADER_BYTES); udpPacket->encapsulate(appData); // set source and destination port udpPacket->setSourcePort(udpCtrl->getSrcPort()); udpPacket->setDestinationPort(udpCtrl->getDestPort()); if (!udpCtrl->getDestAddr().isIPv6()) { // send to IPv4 EV << "Sending app packet " << appData->getName() << " over IPv4.\n"; IPControlInfo *ipControlInfo = new IPControlInfo(); ipControlInfo->setProtocol(IP_PROT_UDP); ipControlInfo->setSrcAddr(udpCtrl->getSrcAddr().get4()); ipControlInfo->setDestAddr(udpCtrl->getDestAddr().get4()); ipControlInfo->setInterfaceId(udpCtrl->getInterfaceId()); udpPacket->setControlInfo(ipControlInfo); delete udpCtrl; send(udpPacket,"ipOut"); } else { // send to IPv6 EV << "Sending app packet " << appData->getName() << " over IPv6.\n"; IPv6ControlInfo *ipControlInfo = new IPv6ControlInfo(); ipControlInfo->setProtocol(IP_PROT_UDP); ipControlInfo->setSrcAddr(udpCtrl->getSrcAddr().get6()); ipControlInfo->setDestAddr(udpCtrl->getDestAddr().get6()); // ipControlInfo->setInterfaceId(udpCtrl->InterfaceId()); FIXME extend IPv6 with this!!! udpPacket->setControlInfo(ipControlInfo); delete udpCtrl; send(udpPacket,"ipv6Out"); } numSent++; }
void UDP::processUDPPacket | ( | UDPPacket * | udpPacket | ) | [protected, virtual] |
Definition at line 408 of file UDP.cc.
Referenced by handleMessage().
{ // simulate checksum: discard packet if it has bit error EV << "Packet " << udpPacket->getName() << " received from network, dest port " << udpPacket->getDestinationPort() << "\n"; if (udpPacket->hasBitError()) { EV << "Packet has bit error, discarding\n"; delete udpPacket; numDroppedBadChecksum++; return; } int destPort = udpPacket->getDestinationPort(); cPolymorphic *ctrl = udpPacket->removeControlInfo(); // send back ICMP error if no socket is bound to that port SocketsByPortMap::iterator it = socketsByPortMap.find(destPort); if (it==socketsByPortMap.end()) { EV << "No socket registered on port " << destPort << "\n"; processUndeliverablePacket(udpPacket, ctrl); return; } SockDescList& list = it->second; int matches = 0; // deliver a copy of the packet to each matching socket cPacket *payload = udpPacket->getEncapsulatedMsg(); if (dynamic_cast<IPControlInfo *>(ctrl)!=NULL) { IPControlInfo *ctrl4 = (IPControlInfo *)ctrl; for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it) { SockDesc *sd = *it; if (sd->onlyLocalPortIsSet || matchesSocket(sd, udpPacket, ctrl4)) { EV << "Socket sockId=" << sd->sockId << " matches, sending up a copy.\n"; sendUp((cPacket*)payload->dup(), udpPacket, ctrl4, sd); matches++; } } } else if (dynamic_cast<IPv6ControlInfo *>(ctrl)!=NULL) { IPv6ControlInfo *ctrl6 = (IPv6ControlInfo *)ctrl; for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it) { SockDesc *sd = *it; if (sd->onlyLocalPortIsSet || matchesSocket(sd, udpPacket, ctrl6)) { EV << "Socket sockId=" << sd->sockId << " matches, sending up a copy.\n"; sendUp((cPacket*)payload->dup(), udpPacket, ctrl6, sd); matches++; } } } else { error("(%s)%s arrived from lower layer without control info", udpPacket->getClassName(), udpPacket->getName()); } // send back ICMP error if there is no matching socket if (matches==0) { EV << "None of the sockets on port " << destPort << " matches the packet\n"; processUndeliverablePacket(udpPacket, ctrl); return; } delete udpPacket; delete ctrl; }
void UDP::processUndeliverablePacket | ( | UDPPacket * | udpPacket, | |
cPolymorphic * | ctrl | |||
) | [protected, virtual] |
Definition at line 299 of file UDP.cc.
Referenced by processUDPPacket().
{ numDroppedWrongPort++; // send back ICMP PORT_UNREACHABLE if (dynamic_cast<IPControlInfo *>(ctrl)!=NULL) { if (!icmp) icmp = ICMPAccess().get(); IPControlInfo *ctrl4 = (IPControlInfo *)ctrl; if (!ctrl4->getDestAddr().isMulticast()) icmp->sendErrorMessage(udpPacket, ctrl4, ICMP_DESTINATION_UNREACHABLE, ICMP_DU_PORT_UNREACHABLE); } else if (dynamic_cast<IPv6ControlInfo *>(udpPacket->getControlInfo())!=NULL) { if (!icmpv6) icmpv6 = ICMPv6Access().get(); IPv6ControlInfo *ctrl6 = (IPv6ControlInfo *)ctrl; if (!ctrl6->getDestAddr().isMulticast()) icmpv6->sendErrorMessage(udpPacket, ctrl6, ICMPv6_DESTINATION_UNREACHABLE, PORT_UNREACHABLE); } else { error("(%s)%s arrived from lower layer without control info", udpPacket->getClassName(), udpPacket->getName()); } }
void UDP::sendUp | ( | cPacket * | payload, | |
UDPPacket * | udpHeader, | |||
IPv6ControlInfo * | ctrl, | |||
SockDesc * | sd | |||
) | [protected, virtual] |
Definition at line 282 of file UDP.cc.
{ // send payload with UDPControlInfo up to the application -- IPv6 version UDPControlInfo *udpCtrl = new UDPControlInfo(); udpCtrl->setSockId(sd->sockId); udpCtrl->setUserId(sd->userId); udpCtrl->setSrcAddr(ipCtrl->getSrcAddr()); udpCtrl->setDestAddr(ipCtrl->getDestAddr()); udpCtrl->setSrcPort(udpHeader->getSourcePort()); udpCtrl->setDestPort(udpHeader->getDestinationPort()); udpCtrl->setInterfaceId(ipCtrl->getInterfaceId()); payload->setControlInfo(udpCtrl); send(payload, "appOut", sd->appGateIndex); numPassedUp++; }
void UDP::sendUp | ( | cPacket * | payload, | |
UDPPacket * | udpHeader, | |||
IPControlInfo * | ctrl, | |||
SockDesc * | sd | |||
) | [protected, virtual] |
Definition at line 265 of file UDP.cc.
Referenced by processUDPPacket().
{ // send payload with UDPControlInfo up to the application -- IPv4 version UDPControlInfo *udpCtrl = new UDPControlInfo(); udpCtrl->setSockId(sd->sockId); udpCtrl->setUserId(sd->userId); udpCtrl->setSrcAddr(ipCtrl->getSrcAddr()); udpCtrl->setDestAddr(ipCtrl->getDestAddr()); udpCtrl->setSrcPort(udpHeader->getSourcePort()); udpCtrl->setDestPort(udpHeader->getDestinationPort()); udpCtrl->setInterfaceId(ipCtrl->getInterfaceId()); payload->setControlInfo(udpCtrl); send(payload, "appOut", sd->appGateIndex); numPassedUp++; }
void UDP::sendUpErrorNotification | ( | SockDesc * | sd, | |
int | msgkind, | |||
const IPvXAddress & | localAddr, | |||
const IPvXAddress & | remoteAddr, | |||
ushort | remotePort | |||
) | [protected, virtual] |
Definition at line 393 of file UDP.cc.
Referenced by processICMPError().
{ cPacket *notifyMsg = new cPacket("ERROR", msgkind); UDPControlInfo *udpCtrl = new UDPControlInfo(); udpCtrl->setSockId(sd->sockId); udpCtrl->setUserId(sd->userId); udpCtrl->setSrcAddr(localAddr); udpCtrl->setDestAddr(remoteAddr); udpCtrl->setSrcPort(sd->localPort); udpCtrl->setDestPort(remotePort); notifyMsg->setControlInfo(udpCtrl); send(notifyMsg, "appOut", sd->appGateIndex); }
void UDP::unbind | ( | int | sockId | ) | [protected, virtual] |
Definition at line 155 of file UDP.cc.
Referenced by processCommandFromApp().
{ // remove from socketsByIdMap SocketsByIdMap::iterator it = socketsByIdMap.find(sockId); if (it==socketsByIdMap.end()) error("socket id=%d doesn't exist (already closed?)", sockId); SockDesc *sd = it->second; socketsByIdMap.erase(it); EV << "Unbinding socket: " << *sd << "\n"; // remove from socketsByPortMap SockDescList& list = socketsByPortMap[sd->localPort]; for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it) if (*it == sd) {list.erase(it); break;} if (list.empty()) socketsByPortMap.erase(sd->localPort); delete sd; }
void UDP::updateDisplayString | ( | ) | [protected, virtual] |
Definition at line 218 of file UDP.cc.
Referenced by handleMessage().
{ char buf[80]; sprintf(buf, "passed up: %d pks\nsent: %d pks", numPassedUp, numSent); if (numDroppedWrongPort>0) { sprintf(buf+strlen(buf), "\ndropped (no app): %d pks", numDroppedWrongPort); getDisplayString().setTagArg("i",1,"red"); } getDisplayString().setTagArg("t",0,buf); }
ICMPv6* UDP::icmpv6 [protected] |
Definition at line 74 of file UDP.h.
Referenced by initialize(), and processUndeliverablePacket().
ushort UDP::lastEphemeralPort [protected] |
Definition at line 72 of file UDP.h.
Referenced by getEphemeralPort(), and initialize().
int UDP::numDroppedBadChecksum [protected] |
Definition at line 80 of file UDP.h.
Referenced by initialize(), and processUDPPacket().
int UDP::numDroppedWrongPort [protected] |
Definition at line 79 of file UDP.h.
Referenced by initialize(), processUndeliverablePacket(), and updateDisplayString().
int UDP::numPassedUp [protected] |
Definition at line 78 of file UDP.h.
Referenced by initialize(), sendUp(), and updateDisplayString().
int UDP::numSent [protected] |
Definition at line 77 of file UDP.h.
Referenced by initialize(), processMsgFromApp(), and updateDisplayString().
SocketsByIdMap UDP::socketsByIdMap [protected] |
SocketsByPortMap UDP::socketsByPortMap [protected] |
Definition at line 69 of file UDP.h.
Referenced by bind(), getEphemeralPort(), initialize(), processICMPError(), processUDPPacket(), and unbind().