From f3e46b7920549b3e4dd4cc1d852d3b26af3c490c Mon Sep 17 00:00:00 2001 From: PioDer Date: Tue, 17 Jan 2017 02:11:06 +0100 Subject: [PATCH] klasa Log do wyswietlania komunikatow, watki, klasa symulacyjna z modelem symulacji (podstawa) --- Log.cpp | 82 +++++++++++++++++++ Log.h | 46 +++++++++++ Main.cpp | 28 ++++--- Makefile | 4 +- NATRouter.cpp | 40 ++++++---- Node.cpp | 11 ++- Node.h | 4 +- Simulation.cpp | 212 +++++++++++++++++++++++++++++++++++++++++++++++++ Simulation.h | 48 +++++++++++ common.h | 3 + 10 files changed, 442 insertions(+), 36 deletions(-) create mode 100644 Log.cpp create mode 100644 Log.h create mode 100644 Simulation.cpp create mode 100644 Simulation.h diff --git a/Log.cpp b/Log.cpp new file mode 100644 index 0000000..ed241f9 --- /dev/null +++ b/Log.cpp @@ -0,0 +1,82 @@ +/* + * Log.cpp + * + * Created on: 16.01.2017 + * Author: piotrek + */ + +#include "Log.h" + +Log::Log() +{ + this->color = WHITE; + this->delimiter = ""; + this->lineNumber = 0; + this->objectName = NULL; +} + +LOG_COLOR Log::getColor() const +{ + return color; +} + +void Log::setColor(LOG_COLOR color) +{ + this->color = color; +} + +const string& Log::getDelimiter() const +{ + return delimiter; +} + +void Log::setDelimiter(const string& delimiter) +{ + this->delimiter = delimiter; +} + +int Log::getLineNumber() const +{ + return lineNumber; +} + +void Log::setLineNumber(int lineNumber) +{ + this->lineNumber = lineNumber; +} + +string* Log::getObjectName() const +{ + return objectName; +} + +void Log::setObjectName(string* objectName) +{ + this->objectName = objectName; +} + +void Log::print(string msg) +{ + if (this->getObjectName() == NULL) + return; + + move(this->getLineNumber(), 0); + clrtoeol(); + + if(has_colors()) + attron(COLOR_PAIR(this->getColor())); + + printw("%s:%s%s", this->getObjectName()->c_str(), this->getDelimiter().c_str(), msg.c_str()); + + if(has_colors()) + attroff(COLOR_PAIR(this->getColor())); + + move(0, 0); +} + +void Log::setLogParams(int lineNumber, LOG_COLOR color, string delimiter) +{ + this->setLineNumber(lineNumber); + this->setColor(color); + this->setDelimiter(delimiter); +} diff --git a/Log.h b/Log.h new file mode 100644 index 0000000..0cfc8e8 --- /dev/null +++ b/Log.h @@ -0,0 +1,46 @@ +/* + * Log.h + * + * Created on: 16.01.2017 + * Author: piotrek + */ + +#ifndef LOG_H_ +#define LOG_H_ + +#include "common.h" + +enum LOG_COLOR { + BLACK, + RED, + GREEN, + YELLOW, + BLUE, + MAGENTA, + CYAN, + WHITE +}; + +class Log +{ + int lineNumber; + LOG_COLOR color; + string delimiter; + string *objectName; +protected: + string* getObjectName() const; + void setObjectName(string* objectName); +public: + Log(); + void print(string msg); + + LOG_COLOR getColor() const; + void setColor(LOG_COLOR color); + const string& getDelimiter() const; + void setDelimiter(const string& delimiter); + int getLineNumber() const; + void setLineNumber(int lineNumber); + void setLogParams(int lineNumber, LOG_COLOR color, string delimiter); +}; + +#endif /* LOG_H_ */ diff --git a/Main.cpp b/Main.cpp index 961ad16..55bb83a 100644 --- a/Main.cpp +++ b/Main.cpp @@ -8,6 +8,7 @@ #include "common.h" #include "Node.h" #include "NATRouter.h" +#include "Simulation.h" int main(int argc, char *argv[]) { @@ -36,6 +37,21 @@ int main(int argc, char *argv[]) exit(0); */ + Simulation sim; + Node pc1("PC1", "10.0.0.2", "255.0.0.0", "10.0.0.1"); + pc1.setDelimiter("\t"); + pc1.setColor(CYAN); + sim.print("initalizing thread"); + //sim.createThread("timer", &Simulation::timerHelper, &sim); + //sim.createThread("nowa", &Simulation::threadWrapper, &sim.timer); + //sim.createThread("test", dupa); + sim.createThread("timer", SIM_TIMER, &sim); + //sleep(5); + sim.p2pSimulation(); + while(1); + exit(0); + + /* cout << "Obiekt PC1" << endl; Node pc1("PC1", "10.0.0.2", "255.0.0.0", "10.0.0.1"); @@ -55,16 +71,6 @@ int main(int argc, char *argv[]) Node s("Serwer", "8.8.8.8", "255.255.255.255"); s.connectNode(&r1, true); - /* - * zastapilem to polaczenie bezposrednie - * polaczeniem przez router (a'la switch) - - cout << "Lacze PC1 z PC2" << endl; - cout << pc1.connectNode(&pc2) << endl; - - cout << "Lacze PC1 z PC2 (ponownie)" << endl; - cout << pc1.connectNode(&pc2) << endl; - */ cout << "Tworze pakiet i adresuje go do PC2" << endl; Packet p("piekna wiadomosc"); @@ -107,6 +113,6 @@ int main(int argc, char *argv[]) cout << "Wywoluje onRecv() na PC1" << endl; pc1.onRecv(); - +*/ return 0; } diff --git a/Makefile b/Makefile index 8b4687a..d2f9c08 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ CXX = g++ CXXFLAGS = -Wall -std=c++11 -LDFLAGS = -pthread -OBJ = Packet.o Node.o NATItem.o NATRouter.o +LDFLAGS = -pthread -lncurses +OBJ = Log.o Packet.o Node.o NATItem.o NATRouter.o Simulation.o all: +@make simulation diff --git a/NATRouter.cpp b/NATRouter.cpp index dfa1367..661636a 100644 --- a/NATRouter.cpp +++ b/NATRouter.cpp @@ -57,26 +57,34 @@ NATRouter::~NATRouter() void NATRouter::onRecv() { - Packet p = this->recv(); - - if (p.getSrcPort() != 0) + while (true) { - // jezeli pakiet idzie z jednego wezla do drugiego w danej possieci to odeslij mu "jak switch" - if (this->calculateNetwork(p.getDstIp(), this->getMask()) == this->getNetwork() && p.getDstIp() != this->getIp()) - { - this->send(p, true); - } - else if (p.getDstIp() != this->getIp() && p.getDstIp() != this->getWanIp()) - { - this->sNAT(&p); - } - else if (p.getDstIp() == this->getWanIp() && !this->natTable[p.getDstPort()].isFree()) + Packet p = this->recv(); + + if (p.getSrcPort() != 0) { - this->dNAT(&p); + // jezeli pakiet idzie z jednego wezla do drugiego w danej possieci to odeslij mu "jak switch" + if (this->calculateNetwork(p.getDstIp(), this->getMask()) == this->getNetwork() && p.getDstIp() != this->getIp()) + { + this->send(p, true); + } + else if (p.getDstIp() != this->getIp() && p.getDstIp() != this->getWanIp()) + { + this->sNAT(&p); + } + else if (p.getDstIp() == this->getWanIp() && !this->natTable[p.getDstPort()].isFree()) + { + this->dNAT(&p); + } + else + { + // TUTAJ ew. implementacja obslugi pakietu adresowanego do routera + } } else { - // TUTAJ ew. implementacja obslugi pakietu adresowanego do routera + this->print("onRecv() sleeping..."); + sleep(1); } } } @@ -127,7 +135,7 @@ void NATRouter::sNAT(Packet *packet) while ((port = this->getFreePort()) == -1) { //TESTOWO - cout << "Brak wolnych portow, czekam 1s" << endl; + //cout << "Brak wolnych portow, czekam 1s" << endl; sleep(1); } diff --git a/Node.cpp b/Node.cpp index 8728be6..e0a3f8a 100644 --- a/Node.cpp +++ b/Node.cpp @@ -92,6 +92,8 @@ Node::Node() this->setIp("0.0.0.0"); this->setMask("0.0.0.0"); this->setGatewayIp("0.0.0.0"); + + this->setObjectName(&this->hostname); } Node::~Node() @@ -242,13 +244,10 @@ void Node::onRecv() Packet p = this->recv(); if (p.getSrcPort() != 0) { - cout << endl << "<<<<<< " << this->getHostname() << " >>>>>>" << endl; - cout << "Odebrano wiadomosc!" << endl; - cout << "Src: " << p.getSrcIp() << ":" << p.getSrcPort() << endl; - cout << "Dst: " << p.getDstIp() << ":" << p.getDstPort() << endl; - cout << "---" << endl << p.getMsg() << endl << endl; + stringstream s; + s << "onRecv() received \"" << p.getMsg() << "\" from " << p.getSrcIp() << ":" << p.getSrcPort(); + this->print(s.str()); } - } void Node::setNetwork() diff --git a/Node.h b/Node.h index d0aa010..c24709d 100644 --- a/Node.h +++ b/Node.h @@ -10,6 +10,8 @@ #include "common.h" #include "Packet.h" +#include "Log.h" + typedef struct { string ip; string mask; @@ -17,7 +19,7 @@ typedef struct { string gatewayIp; } NetConf; -class Node +class Node : public Log { private: queuercvBuffer; // kolejka z pakietami do przetworzenia diff --git a/Simulation.cpp b/Simulation.cpp new file mode 100644 index 0000000..a72ba62 --- /dev/null +++ b/Simulation.cpp @@ -0,0 +1,212 @@ +/* + * Simulation.cpp + * + * Created on: 16.01.2017 + * Author: piotrek + */ + +#include "Simulation.h" +#include "Node.h" +#include "NATRouter.h" + +Simulation::Simulation() +{ + // inicjalizacja ncurses + initscr(); + 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); + } + + this->name = "Simulation"; + this->setLineNumber(rows -1); + this->setDelimiter("\t"); + this->setObjectName(&this->name); + this->setColor(WHITE); + this->startTime = time(NULL); + + //this->createThread("resizeWnd", &Simulation::resizeWndHelper, this); + this->createThread("resizeWnd", SIM_RESIZE, this); +} + +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(2000); +} + +/* + * 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; + } + return 0; +} + +void Simulation::resizeWnd() +{ + while(true) + { + getmaxyx(stdscr, this->rows, this->cols); + //refresh(); + } +} + +void Simulation::timer() +{ + char str[10]; + int h,m, s; + unsigned long timeElapsed; + while(true) + { + refresh(); + timeElapsed = time(NULL) - this->startTime; + h = timeElapsed / 3600; + m = (timeElapsed % 3600) / 60; + s = (timeElapsed % 3600) % 60; + //refresh(); + sprintf(str, "%02d:%02d:%02d", h, m, s); + move(0, this->cols-strlen(str)); + printw(str); + usleep(100000); // 100 ms + //sleep(1); + } +} + +void Simulation::p2pSimulation() +{ + this->print("Creating P2P peers"); + Node peer1("Peer 1", "192.168.1.2", "255.255.255.0", "192.168.1.1"); + peer1.setLogParams(0, GREEN, "\t\t"); + Node peer2("Peer 1", "10.0.0.2", "255.255.255.0", "10.0.0.1"); + peer2.setLogParams(1, CYAN, "\t\t"); + peer1.print("IP 192.168.1.2/24, Gateway: 192.168.1.1"); + peer2.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(2, RED, "\t"); + r2.setLogParams(4, 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"); + Node server("Server", "80.80.90.91", "255.255.255.255"); + server.setLogParams(3, YELLOW, "\t\t"); + server.print("IP 80.80.90.91/32"); + sleep(1); + + this->print("Plugging Peer1 <---> Router 1"); + peer1.connectNode(&r1); + sleep(1); + this->print("Plugging Peer2 <---> Router 2"); + peer2.connectNode(&r2); + sleep(1); + this->print("Plugging Router 1 <---> Router 2"); + r1.connectNode(&r2, true); + sleep(1); + this->print("Plugging Server <---> Router 1"); + server.connectNode(&r1); + sleep(1); + this->print("Plugging Server <---> Router 2"); + server.connectNode(&r2); + sleep(1); + + sleep(3); + this->print("Starting simulation..."); + this->createThread("r1", NODE_RECV, &r1); + this->createThread("r2", NODE_RECV, &r2); +} diff --git a/Simulation.h b/Simulation.h new file mode 100644 index 0000000..50dffc0 --- /dev/null +++ b/Simulation.h @@ -0,0 +1,48 @@ +/* + * Simulation.h + * + * Created on: 16.01.2017 + * Author: piotrek + */ + +#ifndef SIMULATION_H_ +#define SIMULATION_H_ + +#include "common.h" +#include "Log.h" + +enum THREAD_TYPE +{ + NODE_RECV, + SIM_TIMER, + SIM_RESIZE +}; + +struct threadParams +{ + THREAD_TYPE type; + void *context; + pthread_t thread_id; +}; + +class Simulation : public Log +{ + map threads; + int cols, rows; + string name; + unsigned long startTime; +public: + Simulation(); + ~Simulation(); + + void createThread(string name, THREAD_TYPE type, void * context); + void destroyThread(string name); + static void * threadWrapper(void * context); + + void resizeWnd(); + void timer(); + + void p2pSimulation(); +}; + +#endif /* SIMULATION_H_ */ diff --git a/common.h b/common.h index 035fe28..f1f3335 100644 --- a/common.h +++ b/common.h @@ -17,6 +17,9 @@ #include #include #include +#include +#include +#include using namespace std;