Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

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, cMessage *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->byteLength() << " 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 socketId () const
void setUserId (int userId)
int userId () const
int state ()
Getter functions
IPvXAddress localAddress ()
int localPort ()
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 setMulticastInterface (int interfaceId)
int multicastInterface () 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

enum UDPSocket::State
 

Enumeration values:
NOT_BOUND 
BOUND 
00118 {NOT_BOUND, BOUND};  // FIXME needed?


Constructor & Destructor Documentation

UDPSocket::UDPSocket  ) 
 

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

00023 {
00024     // don't allow user-specified sockIds because they may conflict with
00025     // automatically assigned ones.
00026     sockId = generateSocketId();
00027     usrId = -1;
00028     sockstate = NOT_BOUND;
00029 
00030     localPrt = remotePrt = 0;
00031     mcastIfaceId = -1;
00032     cb = NULL;
00033     yourPtr = NULL;
00034 
00035     gateToUdp = NULL;
00036 }

UDPSocket::~UDPSocket  )  [inline]
 

Destructor

00149 {}


Member Function Documentation

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 controlInfo().)

00175 {
00176     return dynamic_cast<UDPControlInfo *>(msg->controlInfo());
00177 }

bool UDPSocket::belongsToSocket cMessage *  msg  ) 
 

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

00169 {
00170     return dynamic_cast<UDPControlInfo *>(msg->controlInfo()) &&
00171            ((UDPControlInfo *)(msg->controlInfo()))->sockId()==sockId;
00172 }

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.

00092 {
00093     if (sockstate!=NOT_BOUND)
00094         opp_error("UDPSocket::bind(): socket already bound");
00095     if (lPort<=0 || lPort>65535)
00096         opp_error("UDPSocket::bind(): invalid port number %d", lPort);
00097 
00098     localAddr = lAddr;
00099     localPrt = lPort;
00100 
00101     UDPControlInfo *ctrl = new UDPControlInfo();
00102     ctrl->setSockId(sockId);
00103     ctrl->setUserId(usrId);
00104     ctrl->setSrcAddr(localAddr);
00105     ctrl->setSrcPort(localPrt);
00106     cMessage *msg = new cMessage("BIND", UDP_C_BIND);
00107     msg->setControlInfo(ctrl);
00108     sendToUDP(msg);
00109 
00110     sockstate = BOUND;
00111 }

void UDPSocket::bind int  localPort  ) 
 

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

00072 {
00073     if (sockstate!=NOT_BOUND)
00074         opp_error("UDPSocket::bind(): socket already bound");
00075     if (lPort<=0 || lPort>65535)
00076         opp_error("UDPSocket::bind(): invalid port number %d", lPort);
00077 
00078     localPrt = lPort;
00079 
00080     UDPControlInfo *ctrl = new UDPControlInfo();
00081     ctrl->setSockId(sockId);
00082     ctrl->setUserId(usrId);
00083     ctrl->setSrcPort(localPrt);
00084     cMessage *msg = new cMessage("BIND", UDP_C_BIND);
00085     msg->setControlInfo(ctrl);
00086     sendToUDP(msg);
00087 
00088     sockstate = BOUND;
00089 }

void UDPSocket::close  ) 
 

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

00156 {
00157     if (sockstate!=BOUND)
00158         return;
00159 
00160     cMessage *msg = new cMessage("UNBIND", UDP_C_UNBIND);
00161     UDPControlInfo *ctrl = new UDPControlInfo();
00162     ctrl->setSockId(sockId);
00163     msg->setControlInfo(ctrl);
00164     sendToUDP(msg);
00165     sockstate = NOT_BOUND;
00166 }

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.

00114 {
00115     if (sockstate!=BOUND)
00116         opp_error( "UDPSocket::connect(): socket must be bound before connect() can be called");
00117     if (addr.isUnspecified())
00118         opp_error("UDPSocket::connect(): unspecified remote address");
00119     if (port<=0 || port>65535)
00120         opp_error("UDPSocket::connect(): invalid remote port number %d", port);
00121 
00122     remoteAddr = addr;
00123     remotePrt = port;
00124 
00125     UDPControlInfo *ctrl = new UDPControlInfo();
00126     ctrl->setSockId(sockId);
00127     ctrl->setDestAddr(remoteAddr);
00128     ctrl->setDestPort(remotePrt);
00129     cMessage *msg = new cMessage("CONNECT", UDP_C_CONNECT);
00130     msg->setControlInfo(ctrl);
00131     sendToUDP(msg);
00132 }

int UDPSocket::generateSocketId  )  [static]
 

Generates a new socket id.

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

IPvXAddress UDPSocket::localAddress  )  [inline]
 

00186 {return localAddr;}

int UDPSocket::localPort  )  [inline]
 

00187 {return localPrt;}

int UDPSocket::multicastInterface  )  const [inline]
 

Returns the output interface for sending multicast packets.

00227 {return mcastIfaceId;}

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!

00186 {
00187     UDPControlInfo *ctrl = check_and_cast<UDPControlInfo *>(msg->removeControlInfo());
00188     ASSERT(ctrl->sockId()==sockId);
00189 
00190     switch (msg->kind())
00191     {
00192         case UDP_I_DATA:
00193              if (cb)
00194                  cb->socketDatagramArrived(sockId, yourPtr, msg, ctrl);
00195              else {
00196                  delete msg;
00197                  delete ctrl;
00198              }
00199              break;
00200         case UDP_I_ERROR:
00201              sockstate = NOT_BOUND;
00202              delete msg;
00203              if (cb)
00204                  cb->socketPeerClosed(sockId, yourPtr);
00205              break;
00206         default:
00207              opp_error("UDPSocket: invalid msg kind %d, one of the UDP_I_xxx constants expected", msg->kind());
00208     }
00209 }

void UDPSocket::send cMessage *  msg  ) 
 

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

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

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

Sends a data packet to the given address and port.

00135 {
00136     msg->setKind(UDP_C_DATA);
00137     UDPControlInfo *ctrl = new UDPControlInfo();
00138     ctrl->setSockId(sockId);
00139     ctrl->setSrcAddr(localAddr);
00140     ctrl->setSrcPort(localPrt);
00141     ctrl->setDestAddr(destAddr);
00142     ctrl->setDestPort(destPort);
00143     ctrl->setInterfaceId(mcastIfaceId);
00144     msg->setControlInfo(ctrl);
00145     sendToUDP(msg);
00146 }

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

00057 {
00058     if (!gateToUdp)
00059         opp_error("UDPSocket: setOutputGate() must be invoked before socket can be used");
00060 
00061     check_and_cast<cSimpleModule *>(gateToUdp->ownerModule())->send(msg, gateToUdp);
00062 }

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.

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

void UDPSocket::setMulticastInterface 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.

00222 {mcastIfaceId = interfaceId;}

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"));

00197 {gateToUdp = toUdp;}

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.)

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

int UDPSocket::socketId  )  const [inline]
 

Returns the internal socket Id.

00154 {return sockId;}

int UDPSocket::state  )  [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.

00172 {return sockstate;}

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

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

00039 {
00040 #define CASE(x) case x: s=#x; break
00041     const char *s = "unknown";
00042     switch (state)
00043     {
00044         CASE(NOT_BOUND);
00045         CASE(BOUND);
00046     }
00047     return s;
00048 #undef CASE
00049 }

int UDPSocket::userId  )  const [inline]
 

Returns the userId.

00165 {return usrId;}


Member Data Documentation

CallbackInterface* UDPSocket::cb [protected]
 

cGate* UDPSocket::gateToUdp [protected]
 

IPvXAddress UDPSocket::localAddr [protected]
 

int UDPSocket::localPrt [protected]
 

int UDPSocket::mcastIfaceId [protected]
 

IPvXAddress UDPSocket::remoteAddr [protected]
 

int UDPSocket::remotePrt [protected]
 

int UDPSocket::sockId [protected]
 

int UDPSocket::sockstate [protected]
 

int UDPSocket::usrId [protected]
 

void* UDPSocket::yourPtr [protected]
 


The documentation for this class was generated from the following files:
Generated on Thu Oct 19 18:22:32 2006 for INET Framework for OMNeT++/OMNEST by  doxygen 1.4.0