|
INET Framework for OMNeT++/OMNEST
|
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