Symulacja NAT na przedmiot Symulacje Komputerowe
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

340 lines
7.8 KiB

  1. /**
  2. * @file Simulation.cpp
  3. *
  4. * Created on: 16.01.2017
  5. * @author Piotr Dergun
  6. */
  7. #include "Simulation.h"
  8. #include "Node.h"
  9. #include "NATRouter.h"
  10. #include "Peer.h"
  11. #include "P2PServer.h"
  12. Simulation::Simulation()
  13. {
  14. srand(time(NULL));
  15. this->rows = 0;
  16. this->cols = 0;
  17. #ifndef DEBUG
  18. // inicjalizacja ncurses
  19. initscr();
  20. curs_set(0);
  21. getmaxyx(stdscr, this->rows, this->cols);
  22. if (has_colors())
  23. {
  24. start_color();
  25. init_pair(0, COLOR_BLACK, COLOR_WHITE);
  26. init_pair(1, COLOR_RED, COLOR_BLACK);
  27. init_pair(2, COLOR_GREEN, COLOR_BLACK);
  28. init_pair(3, COLOR_YELLOW, COLOR_BLACK);
  29. init_pair(4, COLOR_BLUE, COLOR_BLACK);
  30. init_pair(5, COLOR_MAGENTA, COLOR_BLACK);
  31. init_pair(6, COLOR_CYAN, COLOR_BLACK);
  32. init_pair(7, COLOR_WHITE, COLOR_BLACK);
  33. }
  34. #endif
  35. this->name = "Simulation";
  36. this->setLineNumber(rows -1);
  37. this->setDelimiter("\t");
  38. this->setObjectName(&this->name);
  39. this->setColor(WHITE);
  40. this->startTime = time(NULL);
  41. #ifndef DEBUG
  42. this->createThread("resizeWnd", SIM_RESIZE, this);
  43. #endif
  44. }
  45. Simulation::~Simulation()
  46. {
  47. //niestety nie dziala...
  48. endwin();
  49. }
  50. void Simulation::createThread(string name, THREAD_TYPE type, void* context)
  51. {
  52. struct threadParams params;
  53. params.type = type;
  54. params.context = context;
  55. this->threads.insert(pair<string, struct threadParams>(name, params));
  56. map<string, struct threadParams>::iterator it = threads.find(name);
  57. if (pthread_create(&it->second.thread_id, NULL, Simulation::threadWrapper, &it->second) == -1)
  58. {
  59. cerr << "pthread_create() failed" << endl;
  60. exit(1);
  61. }
  62. this->threads.insert(pair<string, struct threadParams>(name, params));
  63. usleep(3000); // 3ms
  64. }
  65. /*
  66. * przy niszczeniu watku niszczy sie ncurses :(
  67. * TODO poszukac rozwiazania w miare mozliwosci
  68. */
  69. void Simulation::destroyThread(string name)
  70. {
  71. void * state;
  72. map<string, struct threadParams>::iterator it = threads.find(name);
  73. if (it == threads.end())
  74. {
  75. cerr << "Thread: " << name << " does not exist!" << endl;
  76. exit(1);
  77. }
  78. if (pthread_cancel(it->second.thread_id) != 0)
  79. {
  80. cerr << "pthread_cancel() failed" << endl;
  81. exit(1);
  82. }
  83. if (pthread_join(it->second.thread_id, &state) == -1)
  84. {
  85. cerr << "pthread_cancel() failed" << endl;
  86. exit(1);
  87. }
  88. if (pthread_detach(it->second.thread_id) == -1)
  89. {
  90. cerr << "pthread_detach() failed" << endl;
  91. exit(1);
  92. }
  93. threads.erase(it);
  94. }
  95. /*
  96. * wrapper, w ktory trzeba opakowac metody do zastosowania w watku
  97. */
  98. void * Simulation::threadWrapper(void * context)
  99. {
  100. struct threadParams *params = (struct threadParams*)context;
  101. switch(params->type)
  102. {
  103. case NODE_RECV:
  104. ((Node *)params->context)->onRecv();
  105. break;
  106. case SIM_TIMER:
  107. ((Simulation *)params->context)->timer();
  108. break;
  109. case SIM_RESIZE:
  110. ((Simulation *)params->context)->resizeWnd();
  111. break;
  112. case NAT_FP:
  113. ((NATRouter *)params->context)->freePorts();
  114. break;
  115. }
  116. return 0;
  117. }
  118. void Simulation::resizeWnd()
  119. {
  120. while(true)
  121. {
  122. #ifndef DEBUG
  123. getmaxyx(stdscr, this->rows, this->cols);
  124. if (this->getLineNumber() != this->rows-1)
  125. this->setLineNumber(rows -1);
  126. //refresh();
  127. #endif
  128. }
  129. }
  130. void Simulation::timer()
  131. {
  132. #ifndef DEBUG
  133. char str[10];
  134. int h,m, s;
  135. unsigned long timeElapsed;
  136. pthread_mutex_t *mutex;
  137. #endif
  138. while(true)
  139. {
  140. #ifndef DEBUG
  141. refresh();
  142. timeElapsed = time(NULL) - this->startTime;
  143. h = timeElapsed / 3600;
  144. m = (timeElapsed % 3600) / 60;
  145. s = (timeElapsed % 3600) % 60;
  146. mutex = Log::getMutex();
  147. pthread_mutex_lock(mutex);
  148. sprintf(str, "%02d:%02d:%02d", h, m, s);
  149. move(0, this->cols-strlen(str));
  150. printw(str);
  151. pthread_mutex_unlock(mutex);
  152. #endif
  153. usleep(100000); // 100 ms
  154. //sleep(1);
  155. }
  156. }
  157. void Simulation::p2pSimulation()
  158. {
  159. this->print("Creating P2P peers");
  160. Peer seed("Seed", "192.168.1.2", "255.255.255.0", "192.168.1.1");
  161. seed.setSender(true);
  162. seed.setSim(this);
  163. seed.setLogParams(0, GREEN, "\t\t");
  164. Peer peer("Peer", "10.0.0.2", "255.255.255.0", "10.0.0.1");
  165. peer.setSim(this);
  166. peer.setLogParams(4, CYAN, "\t\t");
  167. seed.print("IP 192.168.1.2/24, Gateway: 192.168.1.1");
  168. peer.print("IP 10.0.0.2/24, Gateway: 10.0.0.1");
  169. sleep(1);
  170. this->print("Creating NAT devices");
  171. NATRouter r1("Router 1", "192.168.1.1", "255.255.255.0");
  172. NATRouter r2("Router 2", "10.0.0.1", "255.255.255.0");
  173. r1.setLogParams(1, RED, "\t");
  174. r2.setLogParams(3, MAGENTA, "\t");
  175. r1.print("IP 192.168.1.1/24");
  176. r2.print("IP 10.0.0.1/24");
  177. sleep(1);
  178. this->print("Setting WAN configuration");
  179. r1.setWanIp("41.42.43.44");
  180. r1.setWanMask("255.255.255.255");
  181. r2.setWanIp("45.46.47.48");
  182. r2.setWanMask("255.255.255.255");
  183. r1.print("WAN IP 41.42.43.44/32");
  184. r2.print("WAN IP 45.46.47.48/32");
  185. sleep(1);
  186. this->print("Creating P2P server");
  187. P2PServer server("Server", "80.80.90.91", "255.255.255.255");
  188. server.setSim(this);
  189. server.setLogParams(2, YELLOW, "\t\t");
  190. server.print("IP 80.80.90.91/32");
  191. sleep(1);
  192. this->print("Plugging Seed <---> Router 1");
  193. r1.connectNode(&seed);
  194. usleep(600000);
  195. this->print("Plugging Peer <---> Router 2");
  196. r2.connectNode(&peer);
  197. usleep(600000);
  198. this->print("Plugging Router 1 <---> Router 2");
  199. r1.connectNode(&r2, true);
  200. usleep(600000);
  201. this->print("Plugging Server <---> Router 1");
  202. server.connectNode(&r1);
  203. usleep(600000);
  204. this->print("Plugging Server <---> Router 2");
  205. server.connectNode(&r2);
  206. usleep(600000);
  207. this->print("Starting simulation...");
  208. sleep(1);
  209. this->createThread("r1", NODE_RECV, &r1);
  210. this->createThread("r2", NODE_RECV, &r2);
  211. this->createThread("s1", NODE_RECV, &server);
  212. this->print("Connecting peers to P2P server");
  213. seed.connectToServer("80.80.90.91", 6565);
  214. peer.connectToServer("80.80.90.91", 6565);
  215. sleep(3);
  216. this->createThread("p1", NODE_RECV, &seed);
  217. this->createThread("p2", NODE_RECV, &peer);
  218. while(true);
  219. }
  220. void Simulation::natOverflowSimulation(int nNodes)
  221. {
  222. int i = 0, srcPort;
  223. stringstream ss;
  224. string hostname;
  225. this->print("Creating server");
  226. Node server("Server", "93.92.91.90", "255.255.255.255");
  227. server.setLogParams(0, BLUE, "\t\t");
  228. server.print("IP 93.92.91.90/32");
  229. sleep(1);
  230. this->print("Creating NAT device");
  231. NATRouter router("Router", "10.13.12.254", "255.255.255.0");
  232. router.setLogParams(1, YELLOW, "\t\t");
  233. router.setDelay(0);
  234. router.print("IP 10.13.12.254/24", true);
  235. sleep(1);
  236. this->print("Setting WAN configuration");
  237. router.setWanIp("80.55.33.12");
  238. router.setWanMask("255.255.255.255");
  239. router.print("WAN IP 80.55.33.12/32", true);
  240. sleep(1);
  241. this->print("Creating and setting clients");
  242. Node *client = new Node[nNodes];
  243. for (i = 0; i < nNodes; ++i)
  244. {
  245. client[i].setLogParams(2, CYAN, "\t");
  246. ss.str("");
  247. ss << "Client " << (i + 1);
  248. client[i].setHostname(ss.str());
  249. ss.str("");
  250. ss << "10.13.12." << (i + 1);
  251. client[i].setIp(ss.str());
  252. client[i].setMask("255.255.255.0");
  253. client[i].setGatewayIp("10.13.12.254");
  254. ss.str("");
  255. ss << "IP 10.13.12." << (i + 1) << "/24, Gateway: 10.13.12.254";
  256. client[i].print(ss.str());
  257. usleep(12500);
  258. }
  259. for (i = 0; i < nNodes; ++i)
  260. {
  261. ss.str("");
  262. ss << "Plugging Client " << (i + 1) << " <---> Router";
  263. this->print(ss.str());
  264. router.connectNode(&client[i]);
  265. usleep(12500);
  266. }
  267. this->print("Plugging Server <---> Router");
  268. server.connectNode(&router);
  269. usleep(600000);
  270. this->print("Starting simulation...");
  271. sleep(2);
  272. this->createThread("router", NODE_RECV, &router);
  273. this->createThread("server", NODE_RECV, &server);
  274. this->createThread("nat", NAT_FP, &router);
  275. Packet p("test packet");
  276. p.setDstIp("93.92.91.90");
  277. p.setDstPort(80);
  278. i=0;
  279. Log clientLog;
  280. clientLog.setLogParams(5, MAGENTA, "\t");
  281. clientLog.setFirstLine(6);
  282. clientLog.setObjectName(&hostname);
  283. while(true)
  284. {
  285. i = (nNodes>1) ? rand()%nNodes : 0;
  286. ss.str("");
  287. //p.setSrcPort(0);
  288. srcPort = client[i].send(p);
  289. hostname = client[i].getHostname();
  290. ss << "Sent " << client[i].getIp() << ":" << srcPort << " to 93.92.91.90:80";
  291. clientLog.printLine(ss.str());
  292. this->delay(150);
  293. //usleep(1);
  294. }
  295. }