TCPTester.cc 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. //
  2. // Copyright (C) 2004 Andras Varga
  3. //
  4. // This program is free software; you can redistribute it and/or
  5. // modify it under the terms of the GNU General Public License
  6. // as published by the Free Software Foundation; either version 2
  7. // of the License, or (at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with this program; if not, write to the Free Software
  16. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. //
  18. #include "TCPTester.h"
  19. #include "inet/networklayer/contract/NetworkProtocolCommand_m.h"
  20. #include "inet/networklayer/common/IPSocket.h"
  21. #include "inet/networklayer/contract/ipv4/IPv4ControlInfo.h"
  22. namespace inet {
  23. namespace tcp {
  24. TCPTesterBase::TCPTesterBase() : cSimpleModule()
  25. {
  26. }
  27. void TCPTesterBase::initialize()
  28. {
  29. fromASeq = 0;
  30. fromBSeq = 0;
  31. tcpdump.setOutStream(EVSTREAM);
  32. }
  33. void TCPTesterBase::dump(TCPSegment *seg, bool fromA, const char *comment)
  34. {
  35. #if OMNETPP_VERSION < 0x0500
  36. if (getEnvir()->isDisabled())
  37. return;
  38. #else
  39. if (getEnvir()->isExpressMode())
  40. return;
  41. #endif
  42. char lbl[32];
  43. sprintf(lbl," %c%03d", fromA ? 'A' : 'B', fromA ? fromASeq : fromBSeq);
  44. std::ostringstream out;
  45. tcpdump.setOutStream(out);
  46. tcpdump.tcpDump(fromA, lbl, seg, std::string(fromA?"A":"B"),std::string(fromA?"B":"A"), comment);
  47. EV_DEBUG_C("testing") << out.str();
  48. tcpdump.setOutStream(EVSTREAM);
  49. }
  50. void TCPTesterBase::finish()
  51. {
  52. char buf[128];
  53. sprintf(buf,"tcpdump finished, A:%d B:%d segments",fromASeq,fromBSeq);
  54. std::ostringstream out;
  55. tcpdump.setOutStream(out);
  56. tcpdump.dump("", buf);
  57. EV_DEBUG_C("testing") << out.str();
  58. tcpdump.setOutStream(EVSTREAM);
  59. }
  60. //---
  61. Define_Module(TCPScriptableTester);
  62. void TCPScriptableTester::initialize()
  63. {
  64. TCPTesterBase::initialize();
  65. const char *script = par("script");
  66. parseScript(script);
  67. }
  68. void TCPScriptableTester::parseScript(const char *script)
  69. {
  70. const char *s = script;
  71. while (*s)
  72. {
  73. Command cmd;
  74. // direction
  75. while (isspace(*s)) s++;
  76. if (*s=='a' || *s=='A')
  77. cmd.fromA = true;
  78. else if (*s=='b' || *s=='B')
  79. cmd.fromA = false;
  80. else
  81. throw cRuntimeError("syntax error in script: wrong segment spec");
  82. s++;
  83. // seg number
  84. if (!isdigit(*s))
  85. throw cRuntimeError("syntax error in script: wrong segment spec");
  86. cmd.segno = atoi(s);
  87. while (isdigit(*s)) s++;
  88. // command
  89. while (isspace(*s)) s++;
  90. if (!strncmp(s,"delete",6)) {
  91. cmd.command = CMD_DELETE; s+=6;
  92. } else if (!strncmp(s,"delay",5)) {
  93. cmd.command = CMD_COPY; s+=5;
  94. } else if (!strncmp(s,"copy",4)) {
  95. cmd.command = CMD_COPY; s+=4;
  96. } else
  97. throw cRuntimeError("syntax error in script: wrong command");
  98. // args
  99. if (cmd.command==CMD_COPY)
  100. {
  101. for (;;)
  102. {
  103. while (isspace(*s)) s++;
  104. if (!*s || *s==';') break;
  105. double d = strtod(s,&const_cast<char *&>(s));
  106. cmd.delays.push_back(d);
  107. while (isspace(*s)) s++;
  108. if (!*s || *s==';') break;
  109. if (*s!=',')
  110. throw cRuntimeError("syntax error in script: error in arg list");
  111. s++;
  112. }
  113. }
  114. // add command
  115. commands.push_back(cmd);
  116. // skip delimiter
  117. while (isspace(*s)) s++;
  118. if (!*s) break;
  119. if (*s!=';')
  120. throw cRuntimeError("syntax error in script: command separator ';' missing");
  121. s++;
  122. while (isspace(*s)) s++;
  123. }
  124. }
  125. void TCPScriptableTester::handleMessage(cMessage *msg)
  126. {
  127. if (dynamic_cast<RegisterTransportProtocolCommand*>(msg))
  128. {
  129. delete msg;
  130. return;
  131. }
  132. if (msg->isSelfMessage())
  133. {
  134. TCPSegment *seg = check_and_cast<TCPSegment *>(msg);
  135. dispatchSegment(seg);
  136. }
  137. else if (msg->isPacket())
  138. {
  139. TCPSegment *seg = check_and_cast<TCPSegment *>(msg);
  140. bool fromA = msg->arrivedOn("in1");
  141. processIncomingSegment(seg, fromA);
  142. }
  143. else if (dynamic_cast<IPRegisterProtocolCommand *>(msg)) {
  144. delete msg;
  145. }
  146. else
  147. {
  148. throw cRuntimeError("Unknown message");
  149. }
  150. }
  151. void TCPScriptableTester::dispatchSegment(TCPSegment *seg)
  152. {
  153. Command *cmd = (Command *)seg->getContextPointer();
  154. bool fromA = cmd->fromA;
  155. bubble("introducing copy");
  156. dump(seg, fromA, "introducing copy");
  157. send(seg, fromA ? "out2" : "out1");
  158. }
  159. void TCPScriptableTester::processIncomingSegment(TCPSegment *seg, bool fromA)
  160. {
  161. int segno = fromA ? ++fromASeq : ++fromBSeq;
  162. // find entry in script
  163. Command *cmd = NULL;
  164. for (CommandVector::iterator i=commands.begin(); i!=commands.end(); ++i)
  165. if (i->fromA==fromA && i->segno==segno)
  166. cmd = &(*i);
  167. if (!cmd)
  168. {
  169. // dump & forward
  170. dump(seg, fromA);
  171. send(seg, fromA ? "out2" : "out1");
  172. }
  173. else if (cmd->command==CMD_DELETE)
  174. {
  175. bubble("deleting");
  176. dump(seg, fromA, "deleting");
  177. delete seg;
  178. }
  179. else if (cmd->command==CMD_COPY)
  180. {
  181. bubble("removing original");
  182. dump(seg, fromA, "removing original");
  183. for (unsigned int i=0; i<cmd->delays.size(); i++)
  184. {
  185. simtime_t d = cmd->delays[i];
  186. TCPSegment *segcopy = (TCPSegment *)seg->dup();
  187. segcopy->setControlInfo(new IPv4ControlInfo(*check_and_cast<IPv4ControlInfo *>(seg->getControlInfo())));
  188. if (d==0)
  189. {
  190. bubble("forwarding after 0 delay");
  191. dump(segcopy, fromA, "introducing copy");
  192. send(segcopy, fromA ? "out2" : "out1");
  193. }
  194. else
  195. {
  196. segcopy->setContextPointer(cmd);
  197. scheduleAt(simTime()+d, segcopy);
  198. }
  199. }
  200. delete seg;
  201. }
  202. else
  203. {
  204. throw cRuntimeError("wrong command code");
  205. }
  206. }
  207. //------
  208. Define_Module(TCPRandomTester);
  209. void TCPRandomTester::initialize()
  210. {
  211. TCPTesterBase::initialize();
  212. pdelete = par("pdelete");
  213. pdelay = par("pdelay");
  214. pcopy = par("pcopy");
  215. numCopies = &par("numCopies");
  216. delay = &par("delayValue");
  217. }
  218. void TCPRandomTester::handleMessage(cMessage *msg)
  219. {
  220. if (dynamic_cast<RegisterTransportProtocolCommand*>(msg))
  221. {
  222. delete msg;
  223. return;
  224. }
  225. if (msg->isSelfMessage())
  226. {
  227. TCPSegment *seg = check_and_cast<TCPSegment *>(msg);
  228. dispatchSegment(seg);
  229. }
  230. else if (msg->isPacket())
  231. {
  232. TCPSegment *seg = check_and_cast<TCPSegment *>(msg);
  233. bool fromA = msg->arrivedOn("in1");
  234. processIncomingSegment(seg, fromA);
  235. }
  236. else if (dynamic_cast<IPRegisterProtocolCommand *>(msg)) {
  237. delete msg;
  238. }
  239. else
  240. {
  241. throw cRuntimeError("Unknown message");
  242. }
  243. }
  244. void TCPRandomTester::dispatchSegment(TCPSegment *seg)
  245. {
  246. bool fromA = (bool)seg->getContextPointer();
  247. bubble("introducing copy");
  248. dump(seg, fromA, "introducing copy");
  249. send(seg, fromA ? "out2" : "out1");
  250. }
  251. void TCPRandomTester::processIncomingSegment(TCPSegment *seg, bool fromA)
  252. {
  253. if (fromA) ++fromASeq; else ++fromBSeq;
  254. // decide what to do
  255. double x = dblrand();
  256. if (x<=pdelete)
  257. {
  258. bubble("deleting");
  259. dump(seg, fromA, "deleting");
  260. delete seg;
  261. }
  262. else if (x-=pdelete, x<=pdelay)
  263. {
  264. bubble("delay: removing original");
  265. dump(seg, fromA, "delay: removing original");
  266. double d = delay->doubleValue();
  267. seg->setContextPointer((void*)fromA);
  268. scheduleAt(simTime()+d, seg);
  269. }
  270. else if (x-=pdelay, x<=pcopy)
  271. {
  272. bubble("copy: removing original");
  273. dump(seg, fromA, "copy: removing original");
  274. int n = numCopies->longValue();
  275. for (int i=0; i<n; i++)
  276. {
  277. double d = delay->doubleValue();
  278. TCPSegment *segcopy = (TCPSegment *)seg->dup();
  279. segcopy->setControlInfo(new IPv4ControlInfo(*check_and_cast<IPv4ControlInfo *>(seg->getControlInfo())));
  280. segcopy->setContextPointer((void *)fromA);
  281. scheduleAt(simTime()+d, segcopy);
  282. }
  283. delete seg;
  284. }
  285. else
  286. {
  287. // dump & forward
  288. dump(seg, fromA);
  289. send(seg, fromA ? "out2" : "out1");
  290. }
  291. }
  292. } // namespace tcp
  293. } // namespace inet