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 "TCPSocket.h"
00019
00020
00021 TCPSocket::TCPSocket()
00022 {
00023
00024
00025 connId = ev.getUniqueNumber();
00026 sockstate = NOT_BOUND;
00027
00028 localPrt = remotePrt = -1;
00029 cb = NULL;
00030 yourPtr = NULL;
00031
00032 gateToTcp = NULL;
00033 }
00034
00035 TCPSocket::TCPSocket(cMessage *msg)
00036 {
00037 TCPCommand *ind = dynamic_cast<TCPCommand *>(msg->getControlInfo());
00038 if (!ind)
00039 opp_error("TCPSocket::TCPSocket(cMessage *): no TCPCommand control info in message (not from TCP?)");
00040
00041 connId = ind->getConnId();
00042 sockstate = CONNECTED;
00043
00044 localPrt = remotePrt = -1;
00045 cb = NULL;
00046 yourPtr = NULL;
00047
00048 gateToTcp = NULL;
00049
00050 if (msg->getKind()==TCP_I_ESTABLISHED)
00051 {
00052
00053
00054
00055
00056
00057 TCPConnectInfo *connectInfo = dynamic_cast<TCPConnectInfo *>(msg->getControlInfo());
00058 localAddr = connectInfo->getLocalAddr();
00059 remoteAddr = connectInfo->getRemoteAddr();
00060 localPrt = connectInfo->getLocalPort();
00061 remotePrt = connectInfo->getRemotePort();
00062 }
00063 }
00064
00065 const char *TCPSocket::stateName(int state)
00066 {
00067 #define CASE(x) case x: s=#x; break
00068 const char *s = "unknown";
00069 switch (state)
00070 {
00071 CASE(NOT_BOUND);
00072 CASE(BOUND);
00073 CASE(LISTENING);
00074 CASE(CONNECTING);
00075 CASE(CONNECTED);
00076 CASE(PEER_CLOSED);
00077 CASE(LOCALLY_CLOSED);
00078 CASE(CLOSED);
00079 CASE(SOCKERROR);
00080 }
00081 return s;
00082 #undef CASE
00083 }
00084
00085 void TCPSocket::sendToTCP(cMessage *msg)
00086 {
00087 if (!gateToTcp)
00088 opp_error("TCPSocket: setOutputGate() must be invoked before socket can be used");
00089
00090 check_and_cast<cSimpleModule *>(gateToTcp->getOwnerModule())->send(msg, gateToTcp);
00091 }
00092
00093 void TCPSocket::bind(int lPort)
00094 {
00095 if (sockstate!=NOT_BOUND)
00096 opp_error("TCPSocket::bind(): socket already bound");
00097 if (lPort<0 || lPort>65535)
00098 opp_error("TCPSocket::bind(): invalid port number %d", lPort);
00099
00100 localPrt = lPort;
00101 sockstate = BOUND;
00102 }
00103
00104 void TCPSocket::bind(IPvXAddress lAddr, int lPort)
00105 {
00106 if (sockstate!=NOT_BOUND)
00107 opp_error("TCPSocket::bind(): socket already bound");
00108
00109 if ((lPort<0 || lPort>65535) && lPort!=-1)
00110 opp_error("TCPSocket::bind(): invalid port number %d", lPort);
00111
00112 localAddr = lAddr;
00113 localPrt = lPort;
00114 sockstate = BOUND;
00115 }
00116
00117 void TCPSocket::listen(bool fork)
00118 {
00119 if (sockstate!=BOUND)
00120 opp_error(sockstate==NOT_BOUND ? "TCPSocket: must call bind() before listen()"
00121 : "TCPSocket::listen(): connect() or listen() already called");
00122
00123 cMessage *msg = new cMessage("PassiveOPEN", TCP_C_OPEN_PASSIVE);
00124
00125 TCPOpenCommand *openCmd = new TCPOpenCommand();
00126 openCmd->setLocalAddr(localAddr);
00127 openCmd->setLocalPort(localPrt);
00128 openCmd->setConnId(connId);
00129 openCmd->setFork(fork);
00130 openCmd->setSendQueueClass(sendQueueClass.c_str());
00131 openCmd->setReceiveQueueClass(receiveQueueClass.c_str());
00132 openCmd->setTcpAlgorithmClass(tcpAlgorithmClass.c_str());
00133
00134 msg->setControlInfo(openCmd);
00135 sendToTCP(msg);
00136 sockstate = LISTENING;
00137 }
00138
00139 void TCPSocket::connect(IPvXAddress remoteAddress, int remotePort)
00140 {
00141 if (sockstate!=NOT_BOUND && sockstate!=BOUND)
00142 opp_error( "TCPSocket::connect(): connect() or listen() already called (need renewSocket()?)");
00143 if (remotePort<0 || remotePort>65535)
00144 opp_error("TCPSocket::connect(): invalid remote port number %d", remotePort);
00145
00146 cMessage *msg = new cMessage("ActiveOPEN", TCP_C_OPEN_ACTIVE);
00147
00148 remoteAddr = remoteAddress;
00149 remotePrt = remotePort;
00150
00151 TCPOpenCommand *openCmd = new TCPOpenCommand();
00152 openCmd->setConnId(connId);
00153 openCmd->setLocalAddr(localAddr);
00154 openCmd->setLocalPort(localPrt);
00155 openCmd->setRemoteAddr(remoteAddr);
00156 openCmd->setRemotePort(remotePrt);
00157 openCmd->setSendQueueClass(sendQueueClass.c_str());
00158 openCmd->setReceiveQueueClass(receiveQueueClass.c_str());
00159 openCmd->setTcpAlgorithmClass(tcpAlgorithmClass.c_str());
00160
00161 msg->setControlInfo(openCmd);
00162 sendToTCP(msg);
00163 sockstate = CONNECTING;
00164 }
00165
00166 void TCPSocket::send(cMessage *msg)
00167 {
00168 if (sockstate!=CONNECTED && sockstate!=CONNECTING && sockstate!=PEER_CLOSED)
00169 opp_error("TCPSocket::send(): not connected or connecting");
00170
00171 msg->setKind(TCP_C_SEND);
00172 TCPSendCommand *cmd = new TCPSendCommand();
00173 cmd->setConnId(connId);
00174 msg->setControlInfo(cmd);
00175 sendToTCP(msg);
00176 }
00177
00178 void TCPSocket::close()
00179 {
00180 if (sockstate!=CONNECTED && sockstate!=PEER_CLOSED && sockstate!=CONNECTING && sockstate!=LISTENING)
00181 opp_error("TCPSocket::close(): not connected or close() already called");
00182
00183 cMessage *msg = new cMessage("CLOSE", TCP_C_CLOSE);
00184 TCPCommand *cmd = new TCPCommand();
00185 cmd->setConnId(connId);
00186 msg->setControlInfo(cmd);
00187 sendToTCP(msg);
00188 sockstate = sockstate==CONNECTED ? LOCALLY_CLOSED : CLOSED;
00189 }
00190
00191 void TCPSocket::abort()
00192 {
00193 if (sockstate!=NOT_BOUND && sockstate!=BOUND && sockstate!=CLOSED && sockstate!=SOCKERROR)
00194 {
00195 cMessage *msg = new cMessage("ABORT", TCP_C_ABORT);
00196 TCPCommand *cmd = new TCPCommand();
00197 cmd->setConnId(connId);
00198 msg->setControlInfo(cmd);
00199 sendToTCP(msg);
00200 }
00201 sockstate = CLOSED;
00202 }
00203
00204 void TCPSocket::requestStatus()
00205 {
00206 cMessage *msg = new cMessage("STATUS", TCP_C_STATUS);
00207 TCPCommand *cmd = new TCPCommand();
00208 cmd->setConnId(connId);
00209 msg->setControlInfo(cmd);
00210 sendToTCP(msg);
00211 }
00212
00213 void TCPSocket::renewSocket()
00214 {
00215 connId = ev.getUniqueNumber();
00216 remoteAddr = localAddr = IPvXAddress();
00217 remotePrt = localPrt = -1;
00218
00219 sockstate = NOT_BOUND;
00220 }
00221
00222 bool TCPSocket::belongsToSocket(cMessage *msg)
00223 {
00224 return dynamic_cast<TCPCommand *>(msg->getControlInfo()) &&
00225 ((TCPCommand *)(msg->getControlInfo()))->getConnId()==connId;
00226 }
00227
00228 bool TCPSocket::belongsToAnyTCPSocket(cMessage *msg)
00229 {
00230 return dynamic_cast<TCPCommand *>(msg->getControlInfo());
00231 }
00232
00233 void TCPSocket::setCallbackObject(CallbackInterface *callback, void *yourPointer)
00234 {
00235 cb = callback;
00236 yourPtr = yourPointer;
00237 }
00238
00239 void TCPSocket::processMessage(cMessage *msg)
00240 {
00241 ASSERT(belongsToSocket(msg));
00242
00243 TCPStatusInfo *status;
00244 TCPConnectInfo *connectInfo;
00245 switch (msg->getKind())
00246 {
00247 case TCP_I_DATA:
00248 if (cb)
00249 cb->socketDataArrived(connId, yourPtr, PK(msg), false);
00250 else
00251 delete msg;
00252 break;
00253 case TCP_I_URGENT_DATA:
00254 if (cb)
00255 cb->socketDataArrived(connId, yourPtr, PK(msg), true);
00256 else
00257 delete msg;
00258 break;
00259 case TCP_I_ESTABLISHED:
00260
00261
00262
00263
00264
00265 sockstate = CONNECTED;
00266 connectInfo = dynamic_cast<TCPConnectInfo *>(msg->getControlInfo());
00267 localAddr = connectInfo->getLocalAddr();
00268 remoteAddr = connectInfo->getRemoteAddr();
00269 localPrt = connectInfo->getLocalPort();
00270 remotePrt = connectInfo->getRemotePort();
00271 delete msg;
00272 if (cb)
00273 cb->socketEstablished(connId, yourPtr);
00274 break;
00275 case TCP_I_PEER_CLOSED:
00276 sockstate = sockstate==CONNECTED ? PEER_CLOSED : CLOSED;
00277 delete msg;
00278 if (cb)
00279 cb->socketPeerClosed(connId, yourPtr);
00280 break;
00281 case TCP_I_CLOSED:
00282 sockstate = CLOSED;
00283 delete msg;
00284 if (cb)
00285 cb->socketClosed(connId, yourPtr);
00286 break;
00287 case TCP_I_CONNECTION_REFUSED:
00288 case TCP_I_CONNECTION_RESET:
00289 case TCP_I_TIMED_OUT:
00290 sockstate = SOCKERROR;
00291 if (cb)
00292 cb->socketFailure(connId, yourPtr, msg->getKind());
00293 delete msg;
00294 break;
00295 case TCP_I_STATUS:
00296 status = check_and_cast<TCPStatusInfo *>(msg->removeControlInfo());
00297 delete msg;
00298 if (cb)
00299 cb->socketStatusArrived(connId, yourPtr, status);
00300 break;
00301 default:
00302 opp_error("TCPSocket: invalid msg kind %d, one of the TCP_I_xxx constants expected", msg->getKind());
00303 }
00304 }
00305