123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- //
- // This library is free software, you can redistribute it
- // and/or modify
- // it under the terms of the GNU Lesser General Public License
- // as published by the Free Software Foundation;
- // either version 2 of the License, or any later version.
- // The library is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- // See the GNU Lesser General Public License for more details.
- //
- // Copyright 2004 Andras Varga
- //
- #include <vector>
- #include <string>
- #include "inet/common/INETDefs.h"
- #include "inet/transportlayer/contract/tcp/TCPSocket.h"
- namespace inet {
- /**
- * TCP client application for testing the TCP model.
- */
- class INET_API TcpTestClient : public cSimpleModule
- {
- protected:
- struct Command
- {
- simtime_t tSend;
- int numBytes;
- };
- typedef std::list<Command> Commands;
- Commands commands;
- enum { TEST_OPEN, TEST_SEND, TEST_CLOSE };
- int ctr;
- TCPSocket socket;
- // statistics
- int64_t rcvdBytes;
- int rcvdPackets;
- protected:
- void parseScript(const char *script);
- std::string makeMsgName();
- void handleSelfMessage(cMessage *msg);
- void scheduleNextSend();
- protected:
- virtual void initialize();
- virtual void handleMessage(cMessage *msg);
- virtual void finish();
- };
- Define_Module(TcpTestClient);
- void TcpTestClient::parseScript(const char *script)
- {
- const char *s = script;
- while (*s)
- {
- Command cmd;
- // parse time
- while (isspace(*s)) s++;
- if (!*s || *s==';') break;
- const char *s0 = s;
- cmd.tSend = strtod(s,&const_cast<char *&>(s));
- if (s==s0)
- throw cRuntimeError("syntax error in script: simulation time expected");
- // parse number of bytes
- while (isspace(*s)) s++;
- if (!isdigit(*s))
- throw cRuntimeError("syntax error in script: number of bytes expected");
- cmd.numBytes = atoi(s);
- while (isdigit(*s)) s++;
- // add command
- commands.push_back(cmd);
- // skip delimiter
- while (isspace(*s)) s++;
- if (!*s) break;
- if (*s!=';')
- throw cRuntimeError("syntax error in script: separator ';' missing");
- s++;
- while (isspace(*s)) s++;
- }
- }
- std::string TcpTestClient::makeMsgName()
- {
- char buf[40];
- sprintf(buf,"data-%d", ++ctr);
- return std::string(buf);
- }
- void TcpTestClient::initialize()
- {
- rcvdBytes = 0;
- rcvdPackets = 0;
- // parameters
- simtime_t tOpen = par("tOpen");
- Command cmd;
- cmd.tSend = par("tSend");
- cmd.numBytes = par("sendBytes");
- simtime_t tClose = par("tClose");
- const char *script = par("sendScript");
- if (cmd.numBytes > 0)
- commands.push_back(cmd);
- parseScript(script);
- if (cmd.numBytes > 0 && commands.size() > 1)
- throw cRuntimeError("cannot use both sendScript and tSend+sendBytes");
- socket.readDataTransferModePar(*this);
- socket.setOutputGate(gate("tcpOut"));
- ctr = 0;
- scheduleAt(tOpen, new cMessage("Open", TEST_OPEN));
- if (tClose > 0)
- scheduleAt(tClose, new cMessage("Close", TEST_CLOSE));
- }
- void TcpTestClient::handleMessage(cMessage *msg)
- {
- if (msg->isSelfMessage())
- {
- handleSelfMessage(msg);
- return;
- }
- //EV << fullPath() << ": received " << msg->name() << ", " << msg->byteLength() << " bytes\n";
- if (msg->getKind()==TCP_I_DATA || msg->getKind()==TCP_I_URGENT_DATA)
- {
- rcvdPackets++;
- rcvdBytes += PK(msg)->getByteLength();
- }
- socket.processMessage(msg);
- }
- void TcpTestClient::handleSelfMessage(cMessage *msg)
- {
- switch (msg->getKind())
- {
- case TEST_OPEN:
- {
- const char *localAddress = par("localAddress");
- int localPort = par("localPort");
- const char *connectAddress = par("connectAddress");
- int connectPort = par("connectPort");
- socket.bind(*localAddress ? L3Address(localAddress) : L3Address(), localPort);
- if (par("active").boolValue())
- socket.connect(L3Address(connectAddress), connectPort);
- else
- socket.listenOnce();
- scheduleNextSend();
- delete msg;
- break;
- }
- case TEST_SEND:
- socket.send(msg);
- scheduleNextSend();
- break;
- case TEST_CLOSE:
- socket.close();
- delete msg;
- break;
- default:
- throw cRuntimeError("Unknown self message!");
- break;
- }
- }
- void TcpTestClient::scheduleNextSend()
- {
- if (commands.empty())
- return;
- Command cmd = commands.front();
- commands.pop_front();
- cPacket *msg = new cPacket(makeMsgName().c_str(),TEST_SEND);
- msg->setByteLength(cmd.numBytes);
- scheduleAt(cmd.tSend, msg);
- }
- void TcpTestClient::finish()
- {
- EV << getFullPath() << ": received " << rcvdBytes << " bytes in " << rcvdPackets << " packets\n";
- }
- } // namespace inet
|