UDPSocket.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2005 Andras Varga
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public License
00006 // as published by the Free Software Foundation; either version 2
00007 // of the License, or (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU Lesser General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU Lesser General Public License
00015 // along with this program; if not, see <http://www.gnu.org/licenses/>.
00016 //
00017 
00018 #include "UDPSocket.h"
00019 
00020 
00021 UDPSocket::UDPSocket()
00022 {
00023     // don't allow user-specified sockIds because they may conflict with
00024     // automatically assigned ones.
00025     sockId = generateSocketId();
00026     usrId = -1;
00027     sockstate = NOT_BOUND;
00028 
00029     localPrt = remotePrt = 0;
00030     mcastIfaceId = -1;
00031     cb = NULL;
00032     yourPtr = NULL;
00033 
00034     gateToUdp = NULL;
00035 }
00036 
00037 const char *UDPSocket::stateName(int state)
00038 {
00039 #define CASE(x) case x: s=#x; break
00040     const char *s = "unknown";
00041     switch (state)
00042     {
00043         CASE(NOT_BOUND);
00044         CASE(BOUND);
00045     }
00046     return s;
00047 #undef CASE
00048 }
00049 
00050 int UDPSocket::generateSocketId()
00051 {
00052     return ev.getUniqueNumber();
00053 }
00054 
00055 void UDPSocket::sendToUDP(cMessage *msg)
00056 {
00057     if (!gateToUdp)
00058         opp_error("UDPSocket: setOutputGate() must be invoked before socket can be used");
00059 
00060     check_and_cast<cSimpleModule *>(gateToUdp->getOwnerModule())->send(msg, gateToUdp);
00061 }
00062 
00063 void UDPSocket::setUserId(int userId)
00064 {
00065     if (sockstate!=NOT_BOUND)
00066         opp_error("UDPSocket::setUserId(): cannot change userId after socket is bound");
00067     usrId = userId;
00068 }
00069 
00070 void UDPSocket::bind(int lPort)
00071 {
00072     if (sockstate!=NOT_BOUND)
00073         opp_error("UDPSocket::bind(): socket already bound");
00074     if (lPort<=0 || lPort>65535)
00075         opp_error("UDPSocket::bind(): invalid port number %d", lPort);
00076 
00077     localPrt = lPort;
00078 
00079     UDPControlInfo *ctrl = new UDPControlInfo();
00080     ctrl->setSockId(sockId);
00081     ctrl->setUserId(usrId);
00082     ctrl->setSrcPort(localPrt);
00083     cMessage *msg = new cMessage("BIND", UDP_C_BIND);
00084     msg->setControlInfo(ctrl);
00085     sendToUDP(msg);
00086 
00087     sockstate = BOUND;
00088 }
00089 
00090 void UDPSocket::bind(IPvXAddress lAddr, int lPort)
00091 {
00092     if (sockstate!=NOT_BOUND)
00093         opp_error("UDPSocket::bind(): socket already bound");
00094     if (lPort<=0 || lPort>65535)
00095         opp_error("UDPSocket::bind(): invalid port number %d", lPort);
00096 
00097     localAddr = lAddr;
00098     localPrt = lPort;
00099 
00100     UDPControlInfo *ctrl = new UDPControlInfo();
00101     ctrl->setSockId(sockId);
00102     ctrl->setUserId(usrId);
00103     ctrl->setSrcAddr(localAddr);
00104     ctrl->setSrcPort(localPrt);
00105     cMessage *msg = new cMessage("BIND", UDP_C_BIND);
00106     msg->setControlInfo(ctrl);
00107     sendToUDP(msg);
00108 
00109     sockstate = BOUND;
00110 }
00111 
00112 void UDPSocket::connect(IPvXAddress addr, int port)
00113 {
00114     if (sockstate!=BOUND)
00115         opp_error( "UDPSocket::connect(): socket must be bound before connect() can be called");
00116     if (addr.isUnspecified())
00117         opp_error("UDPSocket::connect(): unspecified remote address");
00118     if (port<=0 || port>65535)
00119         opp_error("UDPSocket::connect(): invalid remote port number %d", port);
00120 
00121     remoteAddr = addr;
00122     remotePrt = port;
00123 
00124     UDPControlInfo *ctrl = new UDPControlInfo();
00125     ctrl->setSockId(sockId);
00126     ctrl->setDestAddr(remoteAddr);
00127     ctrl->setDestPort(remotePrt);
00128     cMessage *msg = new cMessage("CONNECT", UDP_C_CONNECT);
00129     msg->setControlInfo(ctrl);
00130     sendToUDP(msg);
00131 }
00132 
00133 void UDPSocket::sendTo(cMessage *msg, IPvXAddress destAddr, int destPort)
00134 {
00135     msg->setKind(UDP_C_DATA);
00136     UDPControlInfo *ctrl = new UDPControlInfo();
00137     ctrl->setSockId(sockId);
00138     ctrl->setSrcAddr(localAddr);
00139     ctrl->setSrcPort(localPrt);
00140     ctrl->setDestAddr(destAddr);
00141     ctrl->setDestPort(destPort);
00142     ctrl->setInterfaceId(mcastIfaceId);
00143     msg->setControlInfo(ctrl);
00144     sendToUDP(msg);
00145 }
00146 
00147 void UDPSocket::send(cMessage *msg)
00148 {
00149     if (remoteAddr.isUnspecified() || remotePrt==0)
00150         opp_error("UDPSocket::send(): must call connect() before using send()");
00151     sendTo(msg, remoteAddr, remotePrt);
00152 }
00153 
00154 void UDPSocket::close()
00155 {
00156     if (sockstate!=BOUND)
00157         return;
00158 
00159     cMessage *msg = new cMessage("UNBIND", UDP_C_UNBIND);
00160     UDPControlInfo *ctrl = new UDPControlInfo();
00161     ctrl->setSockId(sockId);
00162     msg->setControlInfo(ctrl);
00163     sendToUDP(msg);
00164     sockstate = NOT_BOUND;
00165 }
00166 
00167 bool UDPSocket::belongsToSocket(cMessage *msg)
00168 {
00169     return dynamic_cast<UDPControlInfo *>(msg->getControlInfo()) &&
00170            ((UDPControlInfo *)(msg->getControlInfo()))->getSockId()==sockId;
00171 }
00172 
00173 bool UDPSocket::belongsToAnyUDPSocket(cMessage *msg)
00174 {
00175     return dynamic_cast<UDPControlInfo *>(msg->getControlInfo());
00176 }
00177 
00178 void UDPSocket::setCallbackObject(CallbackInterface *callback, void *yourPointer)
00179 {
00180     cb = callback;
00181     yourPtr = yourPointer;
00182 }
00183 
00184 void UDPSocket::processMessage(cMessage *msg)
00185 {
00186     UDPControlInfo *ctrl = check_and_cast<UDPControlInfo *>(msg->removeControlInfo());
00187     ASSERT(ctrl->getSockId()==sockId);
00188 
00189     switch (msg->getKind())
00190     {
00191         case UDP_I_DATA:
00192              if (cb)
00193                  cb->socketDatagramArrived(sockId, yourPtr, msg, ctrl);
00194              else {
00195                  delete msg;
00196                  delete ctrl;
00197              }
00198              break;
00199         case UDP_I_ERROR:
00200              sockstate = NOT_BOUND;
00201              delete msg;
00202              if (cb)
00203                  cb->socketPeerClosed(sockId, yourPtr);
00204              break;
00205         default:
00206              opp_error("UDPSocket: invalid msg kind %d, one of the UDP_I_xxx constants expected", msg->getKind());
00207     }
00208 }
00209