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