/** * @file Simulation.cpp * * Created on: 16.01.2017 * @author Piotr Dergun */ #include "Simulation.h" #include "Node.h" #include "NATRouter.h" #include "Peer.h" #include "P2PServer.h" Simulation::Simulation() { srand(time(NULL)); this->rows = 0; this->cols = 0; #ifndef DEBUG // inicjalizacja ncurses initscr(); curs_set(0); getmaxyx(stdscr, this->rows, this->cols); if (has_colors()) { start_color(); init_pair(0, COLOR_BLACK, COLOR_WHITE); init_pair(1, COLOR_RED, COLOR_BLACK); init_pair(2, COLOR_GREEN, COLOR_BLACK); init_pair(3, COLOR_YELLOW, COLOR_BLACK); init_pair(4, COLOR_BLUE, COLOR_BLACK); init_pair(5, COLOR_MAGENTA, COLOR_BLACK); init_pair(6, COLOR_CYAN, COLOR_BLACK); init_pair(7, COLOR_WHITE, COLOR_BLACK); } #endif this->name = "Simulation"; this->setLineNumber(rows -1); this->setDelimiter("\t"); this->setObjectName(&this->name); this->setColor(WHITE); this->startTime = time(NULL); #ifndef DEBUG this->createThread("resizeWnd", SIM_RESIZE, this); #endif } Simulation::~Simulation() { //niestety nie dziala... endwin(); } void Simulation::createThread(string name, THREAD_TYPE type, void* context) { struct threadParams params; params.type = type; params.context = context; this->threads.insert(pair(name, params)); map::iterator it = threads.find(name); if (pthread_create(&it->second.thread_id, NULL, Simulation::threadWrapper, &it->second) == -1) { cerr << "pthread_create() failed" << endl; exit(1); } this->threads.insert(pair(name, params)); usleep(3000); // 3ms } /* * przy niszczeniu watku niszczy sie ncurses :( * TODO poszukac rozwiazania w miare mozliwosci */ void Simulation::destroyThread(string name) { void * state; map::iterator it = threads.find(name); if (it == threads.end()) { cerr << "Thread: " << name << " does not exist!" << endl; exit(1); } if (pthread_cancel(it->second.thread_id) != 0) { cerr << "pthread_cancel() failed" << endl; exit(1); } if (pthread_join(it->second.thread_id, &state) == -1) { cerr << "pthread_cancel() failed" << endl; exit(1); } if (pthread_detach(it->second.thread_id) == -1) { cerr << "pthread_detach() failed" << endl; exit(1); } threads.erase(it); } /* * wrapper, w ktory trzeba opakowac metody do zastosowania w watku */ void * Simulation::threadWrapper(void * context) { struct threadParams *params = (struct threadParams*)context; switch(params->type) { case NODE_RECV: ((Node *)params->context)->onRecv(); break; case SIM_TIMER: ((Simulation *)params->context)->timer(); break; case SIM_RESIZE: ((Simulation *)params->context)->resizeWnd(); break; case NAT_FP: ((NATRouter *)params->context)->freePorts(); break; } return 0; } void Simulation::resizeWnd() { while(true) { #ifndef DEBUG getmaxyx(stdscr, this->rows, this->cols); if (this->getLineNumber() != this->rows-1) this->setLineNumber(rows -1); //refresh(); #endif } } void Simulation::timer() { #ifndef DEBUG char str[10]; int h,m, s; unsigned long timeElapsed; pthread_mutex_t *mutex; #endif while(true) { #ifndef DEBUG refresh(); timeElapsed = time(NULL) - this->startTime; h = timeElapsed / 3600; m = (timeElapsed % 3600) / 60; s = (timeElapsed % 3600) % 60; mutex = Log::getMutex(); pthread_mutex_lock(mutex); sprintf(str, "%02d:%02d:%02d", h, m, s); move(0, this->cols-strlen(str)); printw(str); pthread_mutex_unlock(mutex); #endif usleep(100000); // 100 ms //sleep(1); } } void Simulation::p2pSimulation() { this->print("Creating P2P peers"); Peer seed("Seed", "192.168.1.2", "255.255.255.0", "192.168.1.1"); seed.setSender(true); seed.setSim(this); seed.setLogParams(0, GREEN, "\t\t"); Peer peer("Peer", "10.0.0.2", "255.255.255.0", "10.0.0.1"); peer.setSim(this); peer.setLogParams(4, CYAN, "\t\t"); seed.print("IP 192.168.1.2/24, Gateway: 192.168.1.1"); peer.print("IP 10.0.0.2/24, Gateway: 10.0.0.1"); sleep(1); this->print("Creating NAT devices"); NATRouter r1("Router 1", "192.168.1.1", "255.255.255.0"); NATRouter r2("Router 2", "10.0.0.1", "255.255.255.0"); r1.setLogParams(1, RED, "\t"); r2.setLogParams(3, MAGENTA, "\t"); r1.print("IP 192.168.1.1/24"); r2.print("IP 10.0.0.1/24"); sleep(1); this->print("Setting WAN configuration"); r1.setWanIp("41.42.43.44"); r1.setWanMask("255.255.255.255"); r2.setWanIp("45.46.47.48"); r2.setWanMask("255.255.255.255"); r1.print("WAN IP 41.42.43.44/32"); r2.print("WAN IP 45.46.47.48/32"); sleep(1); this->print("Creating P2P server"); P2PServer server("Server", "80.80.90.91", "255.255.255.255"); server.setSim(this); server.setLogParams(2, YELLOW, "\t\t"); server.print("IP 80.80.90.91/32"); sleep(1); this->print("Plugging Seed <---> Router 1"); r1.connectNode(&seed); usleep(600000); this->print("Plugging Peer <---> Router 2"); r2.connectNode(&peer); usleep(600000); this->print("Plugging Router 1 <---> Router 2"); r1.connectNode(&r2, true); usleep(600000); this->print("Plugging Server <---> Router 1"); server.connectNode(&r1); usleep(600000); this->print("Plugging Server <---> Router 2"); server.connectNode(&r2); usleep(600000); this->print("Starting simulation..."); sleep(1); this->createThread("r1", NODE_RECV, &r1); this->createThread("r2", NODE_RECV, &r2); this->createThread("s1", NODE_RECV, &server); this->print("Connecting peers to P2P server"); seed.connectToServer("80.80.90.91", 6565); peer.connectToServer("80.80.90.91", 6565); sleep(3); this->createThread("p1", NODE_RECV, &seed); this->createThread("p2", NODE_RECV, &peer); while(true); } void Simulation::natOverflowSimulation(int nNodes) { int i = 0, srcPort; stringstream ss; string hostname; this->print("Creating server"); Node server("Server", "93.92.91.90", "255.255.255.255"); server.setLogParams(0, BLUE, "\t\t"); server.print("IP 93.92.91.90/32"); sleep(1); this->print("Creating NAT device"); NATRouter router("Router", "10.13.12.254", "255.255.255.0"); router.setLogParams(1, YELLOW, "\t\t"); router.setDelay(0); router.print("IP 10.13.12.254/24", true); sleep(1); this->print("Setting WAN configuration"); router.setWanIp("80.55.33.12"); router.setWanMask("255.255.255.255"); router.print("WAN IP 80.55.33.12/32", true); sleep(1); this->print("Creating and setting clients"); Node *client = new Node[nNodes]; for (i = 0; i < nNodes; ++i) { client[i].setLogParams(2, CYAN, "\t"); ss.str(""); ss << "Client " << (i + 1); client[i].setHostname(ss.str()); ss.str(""); ss << "10.13.12." << (i + 1); client[i].setIp(ss.str()); client[i].setMask("255.255.255.0"); client[i].setGatewayIp("10.13.12.254"); ss.str(""); ss << "IP 10.13.12." << (i + 1) << "/24, Gateway: 10.13.12.254"; client[i].print(ss.str()); usleep(12500); } for (i = 0; i < nNodes; ++i) { ss.str(""); ss << "Plugging Client " << (i + 1) << " <---> Router"; this->print(ss.str()); router.connectNode(&client[i]); usleep(12500); } this->print("Plugging Server <---> Router"); server.connectNode(&router); usleep(600000); this->print("Starting simulation..."); sleep(2); this->createThread("router", NODE_RECV, &router); this->createThread("server", NODE_RECV, &server); this->createThread("nat", NAT_FP, &router); Packet p("test packet"); p.setDstIp("93.92.91.90"); p.setDstPort(80); i=0; Log clientLog; clientLog.setLogParams(5, MAGENTA, "\t"); clientLog.setFirstLine(6); clientLog.setObjectName(&hostname); while(true) { i = (nNodes>1) ? rand()%nNodes : 0; ss.str(""); //p.setSrcPort(0); srcPort = client[i].send(p); hostname = client[i].getHostname(); ss << "Sent " << client[i].getIp() << ":" << srcPort << " to 93.92.91.90:80"; clientLog.printLine(ss.str()); this->delay(150); //usleep(1); } }