00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "TCP_old.h"
00020 #include "TCPConnection_old.h"
00021 #include "TCPSegment.h"
00022 #include "TCPCommand_m.h"
00023 #include "IPControlInfo.h"
00024 #include "IPv6ControlInfo.h"
00025 #include "ICMPMessage_m.h"
00026 #include "ICMPv6Message_m.h"
00027
00028 using namespace tcp_old;
00029
00030 Define_Module(TCP);
00031
00032 bool TCP::testing;
00033 bool TCP::logverbose;
00034
00035 #define EPHEMERAL_PORTRANGE_START 1024
00036 #define EPHEMERAL_PORTRANGE_END 5000
00037
00038 static std::ostream& operator<<(std::ostream& os, const TCP::SockPair& sp)
00039 {
00040 os << "loc=" << IPvXAddress(sp.localAddr) << ":" << sp.localPort << " "
00041 << "rem=" << IPvXAddress(sp.remoteAddr) << ":" << sp.remotePort;
00042 return os;
00043 }
00044
00045 static std::ostream& operator<<(std::ostream& os, const TCP::AppConnKey& app)
00046 {
00047 os << "connId=" << app.connId << " appGateIndex=" << app.appGateIndex;
00048 return os;
00049 }
00050
00051 static std::ostream& operator<<(std::ostream& os, const TCPConnection& conn)
00052 {
00053 os << "connId=" << conn.connId << " " << TCPConnection::stateName(conn.getFsmState())
00054 << " state={" << const_cast<TCPConnection&>(conn).getState()->info() << "}";
00055 return os;
00056 }
00057
00058
00059 void TCP::initialize()
00060 {
00061 lastEphemeralPort = EPHEMERAL_PORTRANGE_START;
00062 WATCH(lastEphemeralPort);
00063
00064 WATCH_PTRMAP(tcpConnMap);
00065 WATCH_PTRMAP(tcpAppConnMap);
00066
00067 recordStatistics = par("recordStats");
00068
00069 cModule *netw = simulation.getSystemModule();
00070 testing = netw->hasPar("testing") && netw->par("testing").boolValue();
00071 logverbose = !testing && netw->hasPar("logverbose") && netw->par("logverbose").boolValue();
00072 }
00073
00074 TCP::~TCP()
00075 {
00076 while (!tcpAppConnMap.empty())
00077 {
00078 TcpAppConnMap::iterator i = tcpAppConnMap.begin();
00079 delete (*i).second;
00080 tcpAppConnMap.erase(i);
00081 }
00082 }
00083
00084 void TCP::handleMessage(cMessage *msg)
00085 {
00086 if (msg->isSelfMessage())
00087 {
00088 TCPConnection *conn = (TCPConnection *) msg->getContextPointer();
00089 bool ret = conn->processTimer(msg);
00090 if (!ret)
00091 removeConnection(conn);
00092 }
00093 else if (msg->arrivedOn("ipIn") || msg->arrivedOn("ipv6In"))
00094 {
00095 if (dynamic_cast<ICMPMessage *>(msg) || dynamic_cast<ICMPv6Message *>(msg))
00096 {
00097 tcpEV << "ICMP error received -- discarding\n";
00098 delete msg;
00099 }
00100 else
00101 {
00102
00103 TCPSegment *tcpseg = check_and_cast<TCPSegment *>(msg);
00104
00105
00106 IPvXAddress srcAddr, destAddr;
00107 if (dynamic_cast<IPControlInfo *>(tcpseg->getControlInfo())!=NULL)
00108 {
00109 IPControlInfo *controlInfo = (IPControlInfo *)tcpseg->removeControlInfo();
00110 srcAddr = controlInfo->getSrcAddr();
00111 destAddr = controlInfo->getDestAddr();
00112 delete controlInfo;
00113 }
00114 else if (dynamic_cast<IPv6ControlInfo *>(tcpseg->getControlInfo())!=NULL)
00115 {
00116 IPv6ControlInfo *controlInfo = (IPv6ControlInfo *)tcpseg->removeControlInfo();
00117 srcAddr = controlInfo->getSrcAddr();
00118 destAddr = controlInfo->getDestAddr();
00119 delete controlInfo;
00120 }
00121 else
00122 {
00123 error("(%s)%s arrived without control info", tcpseg->getClassName(), tcpseg->getName());
00124 }
00125
00126
00127 TCPConnection *conn = findConnForSegment(tcpseg, srcAddr, destAddr);
00128 if (conn)
00129 {
00130 bool ret = conn->processTCPSegment(tcpseg, srcAddr, destAddr);
00131 if (!ret)
00132 removeConnection(conn);
00133 }
00134 else
00135 {
00136 segmentArrivalWhileClosed(tcpseg, srcAddr, destAddr);
00137 }
00138 }
00139 }
00140 else
00141 {
00142 TCPCommand *controlInfo = check_and_cast<TCPCommand *>(msg->getControlInfo());
00143 int appGateIndex = msg->getArrivalGate()->getIndex();
00144 int connId = controlInfo->getConnId();
00145
00146 TCPConnection *conn = findConnForApp(appGateIndex, connId);
00147
00148 if (!conn)
00149 {
00150 conn = createConnection(appGateIndex, connId);
00151
00152
00153
00154 AppConnKey key;
00155 key.appGateIndex = appGateIndex;
00156 key.connId = connId;
00157 tcpAppConnMap[key] = conn;
00158
00159 tcpEV << "TCP connection created for " << msg << "\n";
00160 }
00161 bool ret = conn->processAppCommand(msg);
00162 if (!ret)
00163 removeConnection(conn);
00164 }
00165
00166 if (ev.isGUI())
00167 updateDisplayString();
00168 }
00169
00170 TCPConnection *TCP::createConnection(int appGateIndex, int connId)
00171 {
00172 return new TCPConnection(this, appGateIndex, connId);
00173 }
00174
00175 void TCP::segmentArrivalWhileClosed(TCPSegment *tcpseg, IPvXAddress srcAddr, IPvXAddress destAddr)
00176 {
00177 TCPConnection *tmp = new TCPConnection();
00178 tmp->segmentArrivalWhileClosed(tcpseg, srcAddr, destAddr);
00179 delete tmp;
00180 delete tcpseg;
00181 }
00182
00183 void TCP::updateDisplayString()
00184 {
00185 if (ev.isDisabled())
00186 {
00187
00188
00189 getDisplayString().setTagArg("t",0,"");
00190 return;
00191 }
00192
00193
00194
00195
00196
00197 int numINIT=0, numCLOSED=0, numLISTEN=0, numSYN_SENT=0, numSYN_RCVD=0,
00198 numESTABLISHED=0, numCLOSE_WAIT=0, numLAST_ACK=0, numFIN_WAIT_1=0,
00199 numFIN_WAIT_2=0, numCLOSING=0, numTIME_WAIT=0;
00200
00201 for (TcpAppConnMap::iterator i=tcpAppConnMap.begin(); i!=tcpAppConnMap.end(); ++i)
00202 {
00203 int state = (*i).second->getFsmState();
00204 switch(state)
00205 {
00206 case TCP_S_INIT: numINIT++; break;
00207 case TCP_S_CLOSED: numCLOSED++; break;
00208 case TCP_S_LISTEN: numLISTEN++; break;
00209 case TCP_S_SYN_SENT: numSYN_SENT++; break;
00210 case TCP_S_SYN_RCVD: numSYN_RCVD++; break;
00211 case TCP_S_ESTABLISHED: numESTABLISHED++; break;
00212 case TCP_S_CLOSE_WAIT: numCLOSE_WAIT++; break;
00213 case TCP_S_LAST_ACK: numLAST_ACK++; break;
00214 case TCP_S_FIN_WAIT_1: numFIN_WAIT_1++; break;
00215 case TCP_S_FIN_WAIT_2: numFIN_WAIT_2++; break;
00216 case TCP_S_CLOSING: numCLOSING++; break;
00217 case TCP_S_TIME_WAIT: numTIME_WAIT++; break;
00218 }
00219 }
00220 char buf2[200];
00221 buf2[0] = '\0';
00222 if (numINIT>0) sprintf(buf2+strlen(buf2), "init:%d ", numINIT);
00223 if (numCLOSED>0) sprintf(buf2+strlen(buf2), "closed:%d ", numCLOSED);
00224 if (numLISTEN>0) sprintf(buf2+strlen(buf2), "listen:%d ", numLISTEN);
00225 if (numSYN_SENT>0) sprintf(buf2+strlen(buf2), "syn_sent:%d ", numSYN_SENT);
00226 if (numSYN_RCVD>0) sprintf(buf2+strlen(buf2), "syn_rcvd:%d ", numSYN_RCVD);
00227 if (numESTABLISHED>0) sprintf(buf2+strlen(buf2),"estab:%d ", numESTABLISHED);
00228 if (numCLOSE_WAIT>0) sprintf(buf2+strlen(buf2), "close_wait:%d ", numCLOSE_WAIT);
00229 if (numLAST_ACK>0) sprintf(buf2+strlen(buf2), "last_ack:%d ", numLAST_ACK);
00230 if (numFIN_WAIT_1>0) sprintf(buf2+strlen(buf2), "fin_wait_1:%d ", numFIN_WAIT_1);
00231 if (numFIN_WAIT_2>0) sprintf(buf2+strlen(buf2), "fin_wait_2:%d ", numFIN_WAIT_2);
00232 if (numCLOSING>0) sprintf(buf2+strlen(buf2), "closing:%d ", numCLOSING);
00233 if (numTIME_WAIT>0) sprintf(buf2+strlen(buf2), "time_wait:%d ", numTIME_WAIT);
00234 getDisplayString().setTagArg("t",0,buf2);
00235 }
00236
00237 TCPConnection *TCP::findConnForSegment(TCPSegment *tcpseg, IPvXAddress srcAddr, IPvXAddress destAddr)
00238 {
00239 SockPair key;
00240 key.localAddr = destAddr;
00241 key.remoteAddr = srcAddr;
00242 key.localPort = tcpseg->getDestPort();
00243 key.remotePort = tcpseg->getSrcPort();
00244 SockPair save = key;
00245
00246
00247 TcpConnMap::iterator i;
00248 i = tcpConnMap.find(key);
00249 if (i!=tcpConnMap.end())
00250 return i->second;
00251
00252
00253 key.localAddr = IPvXAddress();
00254 i = tcpConnMap.find(key);
00255 if (i!=tcpConnMap.end())
00256 return i->second;
00257
00258
00259 key = save;
00260 key.remoteAddr = IPvXAddress();
00261 key.remotePort = -1;
00262 i = tcpConnMap.find(key);
00263 if (i!=tcpConnMap.end())
00264 return i->second;
00265
00266
00267 key.localAddr = IPvXAddress();
00268 i = tcpConnMap.find(key);
00269 if (i!=tcpConnMap.end())
00270 return i->second;
00271
00272
00273 return NULL;
00274 }
00275
00276 TCPConnection *TCP::findConnForApp(int appGateIndex, int connId)
00277 {
00278 AppConnKey key;
00279 key.appGateIndex = appGateIndex;
00280 key.connId = connId;
00281
00282 TcpAppConnMap::iterator i = tcpAppConnMap.find(key);
00283 return i==tcpAppConnMap.end() ? NULL : i->second;
00284 }
00285
00286 ushort TCP::getEphemeralPort()
00287 {
00288
00289 ushort searchUntil = lastEphemeralPort++;
00290 if (lastEphemeralPort == EPHEMERAL_PORTRANGE_END)
00291 lastEphemeralPort = EPHEMERAL_PORTRANGE_START;
00292
00293 while (usedEphemeralPorts.find(lastEphemeralPort)!=usedEphemeralPorts.end())
00294 {
00295 if (lastEphemeralPort == searchUntil)
00296 error("Ephemeral port range %d..%d exhausted, all ports occupied", EPHEMERAL_PORTRANGE_START, EPHEMERAL_PORTRANGE_END);
00297 lastEphemeralPort++;
00298 if (lastEphemeralPort == EPHEMERAL_PORTRANGE_END)
00299 lastEphemeralPort = EPHEMERAL_PORTRANGE_START;
00300 }
00301
00302
00303 return lastEphemeralPort;
00304 }
00305
00306 void TCP::addSockPair(TCPConnection *conn, IPvXAddress localAddr, IPvXAddress remoteAddr, int localPort, int remotePort)
00307 {
00308
00309 SockPair key;
00310 key.localAddr = conn->localAddr = localAddr;
00311 key.remoteAddr = conn->remoteAddr = remoteAddr;
00312 key.localPort = conn->localPort = localPort;
00313 key.remotePort = conn->remotePort = remotePort;
00314
00315
00316 TcpConnMap::iterator it = tcpConnMap.find(key);
00317 if (it!=tcpConnMap.end())
00318 {
00319
00320 if (remoteAddr.isUnspecified() && remotePort==-1)
00321 error("Address already in use: there is already a connection listening on %s:%d",
00322 localAddr.str().c_str(), localPort);
00323 else
00324 error("Address already in use: there is already a connection %s:%d to %s:%d",
00325 localAddr.str().c_str(), localPort, remoteAddr.str().c_str(), remotePort);
00326 }
00327
00328
00329 tcpConnMap[key] = conn;
00330
00331
00332 if (localPort>=EPHEMERAL_PORTRANGE_START && localPort<EPHEMERAL_PORTRANGE_END)
00333 usedEphemeralPorts.insert(localPort);
00334 }
00335
00336 void TCP::updateSockPair(TCPConnection *conn, IPvXAddress localAddr, IPvXAddress remoteAddr, int localPort, int remotePort)
00337 {
00338
00339 SockPair key;
00340 key.localAddr = conn->localAddr;
00341 key.remoteAddr = conn->remoteAddr;
00342 key.localPort = conn->localPort;
00343 key.remotePort = conn->remotePort;
00344 TcpConnMap::iterator it = tcpConnMap.find(key);
00345 ASSERT(it!=tcpConnMap.end() && it->second==conn);
00346
00347
00348 tcpConnMap.erase(it);
00349
00350
00351 key.localAddr = conn->localAddr = localAddr;
00352 key.remoteAddr = conn->remoteAddr = remoteAddr;
00353 ASSERT(conn->localPort == localPort);
00354 key.remotePort = conn->remotePort = remotePort;
00355 tcpConnMap[key] = conn;
00356
00357
00358 }
00359
00360 void TCP::addForkedConnection(TCPConnection *conn, TCPConnection *newConn, IPvXAddress localAddr, IPvXAddress remoteAddr, int localPort, int remotePort)
00361 {
00362
00363 updateSockPair(conn, localAddr, remoteAddr, localPort, remotePort);
00364 addSockPair(newConn, newConn->localAddr, newConn->remoteAddr, newConn->localPort, newConn->remotePort);
00365
00366
00367 AppConnKey key;
00368 key.appGateIndex = conn->appGateIndex;
00369 key.connId = conn->connId;
00370 tcpAppConnMap.erase(key);
00371 key.connId = conn->connId = ev.getUniqueNumber();
00372 tcpAppConnMap[key] = conn;
00373
00374
00375 key.appGateIndex = newConn->appGateIndex;
00376 key.connId = newConn->connId;
00377 tcpAppConnMap[key] = newConn;
00378 }
00379
00380 void TCP::removeConnection(TCPConnection *conn)
00381 {
00382 tcpEV << "Deleting TCP connection\n";
00383
00384 AppConnKey key;
00385 key.appGateIndex = conn->appGateIndex;
00386 key.connId = conn->connId;
00387 tcpAppConnMap.erase(key);
00388
00389 SockPair key2;
00390 key2.localAddr = conn->localAddr;
00391 key2.remoteAddr = conn->remoteAddr;
00392 key2.localPort = conn->localPort;
00393 key2.remotePort = conn->remotePort;
00394 tcpConnMap.erase(key2);
00395
00396
00397
00398 std::multiset<ushort>::iterator it = usedEphemeralPorts.find(conn->localPort);
00399 if (it!=usedEphemeralPorts.end())
00400 usedEphemeralPorts.erase(it);
00401
00402 delete conn;
00403 }
00404
00405 void TCP::finish()
00406 {
00407 tcpEV << getFullPath() << ": finishing with " << tcpConnMap.size() << " connections open.\n";
00408 }