UDPSocket Class Reference

#include <UDPSocket.h>

List of all members.


Detailed Description

UDPSocket is a convenience class, to make it easier to manage TCP connections from your application models. You'd have one (or more) UDPSocket object(s) in your application simple module class, and call its member functions (bind(), listen(), connect(), etc.) to open, close or abort a TCP connection.

UDPSocket chooses and remembers the sockId for you, assembles and sends command packets (such as OPEN_ACTIVE, OPEN_PASSIVE, CLOSE, ABORT, etc.) to TCP, and can also help you deal with packets and notification messages arriving from TCP.

A session which opens a connection from local port 1000 to 10.0.0.2:2000, sends 16K of data and closes the connection may be as simple as this (the code can be placed in your handleMessage() or activity()):

   UDPSocket socket;
   socket.connect(IPvXAddress("10.0.0.2"), 2000);

   msg = new cMessage("data1");
   msg->setByteLength(16*1024);  // 16K
   socket.send(msg);

   socket.close();
 

Dealing with packets and notification messages coming from TCP is somewhat more cumbersome. Basically you have two choices: you either process those messages yourself, or let UDPSocket do part of the job. For the latter, you give UDPSocket a callback object on which it'll invoke the appropriate member functions: socketEstablished(), socketDataArrived(), socketFailure(), socketPeerClosed(), etc (these are methods of UDPSocket::CallbackInterface)., The callback object can be your simple module class too.

This code skeleton example shows how to set up a UDPSocket to use the module itself as callback object:

 class MyModule : public cSimpleModule, public UDPSocket::CallbackInterface
 {
    UDPSocket socket;
    virtual void socketDataArrived(int sockId, void *yourPtr, cPacket *msg, bool urgent);
    virtual void socketFailure(int sockId, void *yourPtr, int code);
    ...
 };

 void MyModule::initialize() {
    socket.setCallbackObject(this,NULL);
 }

 void MyModule::handleMessage(cMessage *msg) {
    if (socket.belongsToSocket(msg))
       socket.processMessage(msg);
    else
       ...
 }

 void MyModule::socketDatagramArrived(int, void *, cMessage *msg, UDPControlInfo *ctrl) {
     ev << "Received UDP packet, " << msg->getByteLength() << " bytes\\n";
     delete msg;
 }

 void MyModule::socketPeerClosed(int, void *, int code) {
     ev << "Socket peer closed!\\n";
 }
 

If you need to manage a large number of sockets, the UDPSocketMap class may be useful.

See also:
UDPSocketMap

Handling of messages arriving from UDP



bool belongsToSocket (cMessage *msg)
void setCallbackObject (CallbackInterface *cb, void *yourPtr=NULL)
void processMessage (cMessage *msg)
static bool belongsToAnyUDPSocket (cMessage *msg)

Public Types

enum  State { NOT_BOUND, BOUND }

Public Member Functions

 UDPSocket ()
 ~UDPSocket ()
int getSocketId () const
void setUserId (int userId)
int getUserId () const
int getState ()
Getter functions


IPvXAddress getLocalAddress ()
int getLocalPort ()
Opening and closing connections, sending data


void setOutputGate (cGate *toUdp)
void bind (int localPort)
void bind (IPvXAddress localAddr, int localPort)
void connect (IPvXAddress remoteAddr, int remotePort)
void setMulticastInterfaceId (int interfaceId)
int getMulticastInterfaceId () const
void sendTo (cMessage *msg, IPvXAddress destAddr, int destPort)
void send (cMessage *msg)
void close ()

Static Public Member Functions

static const char * stateName (int state)
static int generateSocketId ()

Protected Member Functions

void sendToUDP (cMessage *msg)

Protected Attributes

int sockId
int usrId
int sockstate
IPvXAddress localAddr
int localPrt
IPvXAddress remoteAddr
int remotePrt
int mcastIfaceId
CallbackInterfacecb
void * yourPtr
cGate * gateToUdp

Classes

class  CallbackInterface

Member Enumeration Documentation

Enumerator:
NOT_BOUND 
BOUND 
00117 {NOT_BOUND, BOUND};  // FIXME needed?


Constructor & Destructor Documentation

UDPSocket::UDPSocket (  ) 

Constructor. The getSocketId() method returns a valid Id right after constructor call.

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 }

UDPSocket::~UDPSocket (  )  [inline]

Destructor

00148 {}


Member Function Documentation

void UDPSocket::sendToUDP ( cMessage *  msg  )  [protected]

Referenced by bind(), close(), connect(), and sendTo().

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 }

int UDPSocket::getSocketId (  )  const [inline]

Returns the internal socket Id.

00153 {return sockId;}

void UDPSocket::setUserId ( int  userId  ) 

Sets userId to an arbitrary value. (This value will be sent back to us by UDP in UDPControlInfo if we receive a packet on this socket.)

00064 {
00065     if (sockstate!=NOT_BOUND)
00066         opp_error("UDPSocket::setUserId(): cannot change userId after socket is bound");
00067     usrId = userId;
00068 }

int UDPSocket::getUserId (  )  const [inline]

Returns the userId.

00164 {return usrId;}

int UDPSocket::getState (  )  [inline]

Returns the socket state, one of NOT_BOUND, BOUND, etc. Messages received from UDP must be routed through processMessage() in order to keep socket state up-to-date.

00171 {return sockstate;}

const char * UDPSocket::stateName ( int  state  )  [static]

Returns name of socket state code returned by getState().

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 }

int UDPSocket::generateSocketId (  )  [static]

Generates a new socket id.

Referenced by UDPAppBase::bindToPort(), RTP::createSocket(), RTCP::createSocket(), and UDPSocket().

00051 {
00052     return ev.getUniqueNumber();
00053 }

IPvXAddress UDPSocket::getLocalAddress (  )  [inline]

00185 {return localAddr;}

int UDPSocket::getLocalPort (  )  [inline]

00186 {return localPrt;}

void UDPSocket::setOutputGate ( cGate *  toUdp  )  [inline]

Sets the gate on which to send to UDP. Must be invoked before socket can be used. Example: socket.setOutputGate(gate("udpOut"));

Referenced by LDP::initialize().

00196 {gateToUdp = toUdp;}

void UDPSocket::bind ( int  localPort  ) 

Bind the socket to a local port number. Use port=0 for ephemeral port.

Referenced by LDP::initialize().

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 }

void UDPSocket::bind ( IPvXAddress  localAddr,
int  localPort 
)

Bind the socket to a local port number and IP address (useful with multi-homing or multicast addresses). Use port=0 for an ephemeral port.

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 }

void UDPSocket::connect ( IPvXAddress  remoteAddr,
int  remotePort 
)

Connects to a remote UDP socket. This has two effects: (1) this socket will only receive packets from specified address/port, and (2) you can use send() (as opposed to sendTo()) to send packets.

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 }

void UDPSocket::setMulticastInterfaceId ( int  interfaceId  )  [inline]

Set the output interface for sending multicast packets (like the Unix IP_MULTICAST_IF socket option). The argument is the interface's Id in InterfaceTable.

00221 {mcastIfaceId = interfaceId;}

int UDPSocket::getMulticastInterfaceId (  )  const [inline]

Returns the output interface for sending multicast packets.

00226 {return mcastIfaceId;}

void UDPSocket::sendTo ( cMessage *  msg,
IPvXAddress  destAddr,
int  destPort 
)

Sends a data packet to the given address and port.

Referenced by send(), and LDP::sendHelloTo().

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 }

void UDPSocket::send ( cMessage *  msg  ) 

Sends a data packet to the address and port specified previously in a connect() call.

Referenced by sendToUDP().

00148 {
00149     if (remoteAddr.isUnspecified() || remotePrt==0)
00150         opp_error("UDPSocket::send(): must call connect() before using send()");
00151     sendTo(msg, remoteAddr, remotePrt);
00152 }

void UDPSocket::close (  ) 

Unbinds the socket. There is no need for renewSocket() as with TCPSocket.

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 }

bool UDPSocket::belongsToSocket ( cMessage *  msg  ) 

Returns true if the message belongs to this socket instance (message has a UDPControlInfo as getControlInfo(), and the sockId in it matches that of the socket.)

00168 {
00169     return dynamic_cast<UDPControlInfo *>(msg->getControlInfo()) &&
00170            ((UDPControlInfo *)(msg->getControlInfo()))->getSockId()==sockId;
00171 }

bool UDPSocket::belongsToAnyUDPSocket ( cMessage *  msg  )  [static]

Returns true if the message belongs to any UDPSocket instance. (This basically checks if the message has an UDPControlInfo attached to it as getControlInfo().)

00174 {
00175     return dynamic_cast<UDPControlInfo *>(msg->getControlInfo());
00176 }

void UDPSocket::setCallbackObject ( CallbackInterface cb,
void *  yourPtr = NULL 
)

Sets a callback object, to be used with processMessage(). This callback object may be your simple module itself (if it multiply inherits from CallbackInterface too, that is you declared it as

 class MyAppModule : public cSimpleModule, public UDPSocket::CallbackInterface
 
and redefined the necessary virtual functions; or you may use dedicated class (and objects) for this purpose.

UDPSocket doesn't delete the callback object in the destructor or on any other occasion.

YourPtr is an optional pointer. It may contain any value you wish -- UDPSocket will not look at it or do anything with it except passing it back to you in the CallbackInterface calls. You may find it useful if you maintain additional per-connection information: in that case you don't have to look it up by sockId in the callbacks, you can have it passed to you as yourPtr.

00179 {
00180     cb = callback;
00181     yourPtr = yourPointer;
00182 }

void UDPSocket::processMessage ( cMessage *  msg  ) 

Examines the message (which should have arrived from UDP), and if there is a callback object installed (see setCallbackObject(), class CallbackInterface), dispatches to the appropriate method of it with the same yourPtr that you gave in the setCallbackObject() call.

IMPORTANT: for performance reasons, this method doesn't check that the message belongs to this socket, i.e. belongsToSocket(msg) would return true!

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 }


Member Data Documentation

int UDPSocket::sockId [protected]

int UDPSocket::usrId [protected]

Referenced by bind(), setUserId(), and UDPSocket().

int UDPSocket::sockstate [protected]

Referenced by bind(), and sendTo().

int UDPSocket::localPrt [protected]

Referenced by bind(), sendTo(), and UDPSocket().

Referenced by connect(), and send().

int UDPSocket::remotePrt [protected]

Referenced by connect(), send(), and UDPSocket().

int UDPSocket::mcastIfaceId [protected]

Referenced by sendTo(), and UDPSocket().

void* UDPSocket::yourPtr [protected]

cGate* UDPSocket::gateToUdp [protected]

Referenced by sendToUDP(), and UDPSocket().


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

Generated on Fri Mar 20 18:51:23 2009 for INET Framework for OMNeT++/OMNEST by  doxygen 1.5.5