#include <UDPSocket.h>
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.
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 |
CallbackInterface * | cb |
void * | yourPtr |
cGate * | gateToUdp |
Classes | |
class | CallbackInterface |
enum UDPSocket::State |
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 }
void UDPSocket::sendToUDP | ( | cMessage * | msg | ) | [protected] |
int UDPSocket::getSocketId | ( | ) | const [inline] |
void UDPSocket::setUserId | ( | int | userId | ) |
int UDPSocket::getUserId | ( | ) | const [inline] |
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().
IPvXAddress UDPSocket::getLocalAddress | ( | ) | [inline] |
int UDPSocket::getLocalPort | ( | ) | [inline] |
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] |
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().)
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::CallbackInterfaceand 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.
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 }
int UDPSocket::sockId [protected] |
Referenced by belongsToSocket(), bind(), close(), connect(), processMessage(), sendTo(), and UDPSocket().
int UDPSocket::usrId [protected] |
Referenced by bind(), setUserId(), and UDPSocket().
int UDPSocket::sockstate [protected] |
Referenced by bind(), close(), connect(), processMessage(), setUserId(), and UDPSocket().
IPvXAddress UDPSocket::localAddr [protected] |
int UDPSocket::localPrt [protected] |
Referenced by bind(), sendTo(), and UDPSocket().
IPvXAddress UDPSocket::remoteAddr [protected] |
int UDPSocket::remotePrt [protected] |
Referenced by connect(), send(), and UDPSocket().
int UDPSocket::mcastIfaceId [protected] |
Referenced by sendTo(), and UDPSocket().
CallbackInterface* UDPSocket::cb [protected] |
Referenced by processMessage(), setCallbackObject(), and UDPSocket().
void* UDPSocket::yourPtr [protected] |
Referenced by processMessage(), setCallbackObject(), and UDPSocket().
cGate* UDPSocket::gateToUdp [protected] |
Referenced by sendToUDP(), and UDPSocket().