Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "UDPSocket.h"
00019
00020
00021 UDPSocket::UDPSocket()
00022 {
00023
00024
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