/*
|
|
* Node.cpp
|
|
*
|
|
* Created on: 10.01.2017
|
|
* Author: piotrek
|
|
*/
|
|
|
|
#include "Node.h"
|
|
#include "NATRouter.h"
|
|
|
|
Node * Node::findConnection(string ip)
|
|
{
|
|
NATRouter *r;
|
|
Node *ptr = NULL;
|
|
if (ip == "0.0.0.0")
|
|
return NULL;
|
|
|
|
// najpierw szukam tras lokalnych
|
|
map<Node*, bool>::iterator it = this->connectedNodes.begin();
|
|
for (; it != this->connectedNodes.end(); ++it)
|
|
{
|
|
//if ((*it)->getIp() == ip)
|
|
if ((*it).first->getIp() == ip)
|
|
{
|
|
ptr = (*it).first;
|
|
if ((*it).second == false)
|
|
return ptr;
|
|
}
|
|
|
|
/*
|
|
* jezeli wezel ma polaczenie do NAT-routera
|
|
* (i istnieje jego interfejs WAN to sprawdz
|
|
* czy nie ma z nim bezposredniego polaczenia)
|
|
*/
|
|
r = dynamic_cast<NATRouter*>((*it).first);
|
|
|
|
if (r != NULL)
|
|
if (r->getWanIp() == ip)
|
|
return (*it).first;
|
|
}
|
|
/* jezeli takich nie ma, a jest zewnetrzna
|
|
* to musze wskazac do niej
|
|
*/
|
|
if (ptr)
|
|
return ptr;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* funkcja pobiera i usuwa pakiet z bufora "karty sieciowej" */
|
|
Packet Node::recv()
|
|
{
|
|
Packet packet;
|
|
if (!this->rcvBuffer.empty())
|
|
{
|
|
packet = this->rcvBuffer.front();
|
|
this->rcvBuffer.pop();
|
|
}
|
|
|
|
return packet;
|
|
}
|
|
|
|
string Node::ipToString(unsigned int ip)
|
|
{
|
|
ostringstream ss;
|
|
ss << ((ip>>24)&0xFF) << "." << ((ip>>16)&0xFF) << "." << ((ip>>8)&0xFF) << "." << (ip&0xFF);
|
|
|
|
return ss.str();
|
|
}
|
|
|
|
unsigned int Node::stringToIp(string ip)
|
|
{
|
|
istringstream iss(ip);
|
|
int offset = 24;
|
|
unsigned int res=0;
|
|
|
|
std::string token;
|
|
while (getline(iss, token, '.')) {
|
|
if (!token.empty())
|
|
{
|
|
res |= atoi(token.c_str()) << offset;
|
|
offset -= 8;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
Node::Node()
|
|
{
|
|
this->setHostname("");
|
|
this->setIp("0.0.0.0");
|
|
this->setMask("0.0.0.0");
|
|
this->setGatewayIp("0.0.0.0");
|
|
|
|
this->setObjectName(&this->hostname);
|
|
}
|
|
|
|
Node::~Node()
|
|
{
|
|
this->connectedNodes.clear();
|
|
while(!this->rcvBuffer.empty())
|
|
this->rcvBuffer.pop();
|
|
}
|
|
|
|
Node::Node(string hostname) : Node()
|
|
{
|
|
this->setHostname(hostname);
|
|
}
|
|
|
|
Node::Node(string hostname, string ip, string mask) : Node(hostname)
|
|
{
|
|
this->setIp(ip);
|
|
this->setMask(mask);
|
|
}
|
|
|
|
Node::Node(string hostname, string ip, string mask, string gatewayIp) : Node(hostname, ip, mask)
|
|
{
|
|
this->setGatewayIp(gatewayIp);
|
|
}
|
|
|
|
/*
|
|
* funkcja symuluje typową sytuację: mamy kartę sieciową, a funkcja connectNode jest podłączeniem wtyczki
|
|
* z jednej strony
|
|
* @param firstConnected - oznacza, czy pierwsza strona jest podlaczona (jezeli nie to sprawdzamy
|
|
* czy polaczenie juz gdzies zostalo przypadkowo nawiazane, nawiazujemy polaczenie, a nastepnie
|
|
* przekazujemy sterowanie drugiemu wezlowi zeby zrobil to samo)
|
|
*/
|
|
bool Node::connectNode(Node *node, bool isExternal, bool firstConnected)
|
|
{
|
|
if (node->getIp() == "0.0.0.0") // jezeli wezel nie ma skonfigurowanej sieci, nie mozna go przylaczyc
|
|
return false;
|
|
|
|
if (!firstConnected)
|
|
{
|
|
map<Node*, bool>::iterator it = this->connectedNodes.begin();
|
|
for (; it != this->connectedNodes.end(); ++it) // sprawdzamy, czy połączenia już przypadkiem nie ma
|
|
{
|
|
if ((*it).first == node)
|
|
return false;
|
|
}
|
|
}
|
|
this->connectedNodes.insert(pair<Node*, bool>(node, isExternal));//this->connectedNodes.push_back(node); // podłączamy drugi węzeł
|
|
|
|
if (!firstConnected)
|
|
node->connectNode(this, isExternal, true); // to samo w drugą stronę
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* funkcja wysyla, czyli przekazuje kopie pakietu kolejnemu wezlowi - docelowemu lub bramie domyslnej
|
|
* o ile jest skonfigurowana i istnieje do niej sciezka
|
|
*/
|
|
int Node::send(Packet packet, bool isRouter)
|
|
{
|
|
Node *node;
|
|
node = this->findConnection(packet.getDstIp()); // znajdz bezposrednia trase
|
|
|
|
if (!node)
|
|
node = this->findConnection(this->getGatewayIp());
|
|
|
|
if (!node)
|
|
return false; // nie ma zadnej trasy do wezla
|
|
|
|
if (packet.getDstPort() == 0)
|
|
return false; // wypada zdefiniowac nadawce oraz docelowy port...
|
|
// jezeli wezel nie jest routerem to ma ustawic pakietowi swoj srcIp oraz losowy port
|
|
if (!isRouter)
|
|
{
|
|
packet.setSrcIp(this->getIp());
|
|
if (packet.getSrcPort() == 0)
|
|
{
|
|
// ustaw port zrodlowy na port losowy z zakresu [32768,61000] - zob. empheral port (port emferyczny)
|
|
|
|
packet.setSrcPort(rand() % 32768 + 28233);
|
|
}
|
|
}
|
|
node->putPacket(packet);
|
|
|
|
return packet.getSrcPort();
|
|
}
|
|
|
|
/*
|
|
* funkcja jest modelem karty sieciowej - odbiera dane z sieci i umieszcza je
|
|
* w swoim buforze (czy tam systemie)
|
|
*/
|
|
void Node::putPacket(Packet packet)
|
|
{
|
|
this->rcvBuffer.push(packet);
|
|
}
|
|
|
|
void Node::setHostname(string hostname)
|
|
{
|
|
this->hostname = hostname;
|
|
}
|
|
|
|
void Node::setIp(string ip)
|
|
{
|
|
this->netConf.ip = ip;
|
|
this->setNetwork();
|
|
}
|
|
|
|
void Node::setMask(string mask)
|
|
{
|
|
this->netConf.mask = mask;
|
|
this->setNetwork();
|
|
}
|
|
|
|
void Node::setGatewayIp(string gatewayIp)
|
|
{
|
|
// TODO mozna ewentualnie zrobic sprawdzenie czy gateway jest w podsieci
|
|
this->netConf.gatewayIp = gatewayIp;
|
|
}
|
|
|
|
string Node::getHostname()
|
|
{
|
|
return this->hostname;
|
|
}
|
|
|
|
string Node::getIp()
|
|
{
|
|
return this->netConf.ip;
|
|
}
|
|
|
|
string Node::getMask()
|
|
{
|
|
return this->netConf.mask;
|
|
}
|
|
|
|
string Node::getGatewayIp()
|
|
{
|
|
return this->netConf.gatewayIp;
|
|
}
|
|
|
|
string Node::calculateNetwork(string ip, string mask)
|
|
{
|
|
return ipToString(stringToIp(ip) & stringToIp(mask));
|
|
}
|
|
|
|
void Node::onRecv()
|
|
{
|
|
while(true)
|
|
{
|
|
// TESTOWO
|
|
Packet p = this->recv();
|
|
if (p.getSrcPort() != 0)
|
|
{
|
|
stringstream s;
|
|
s << "onRecv() received \"" << p.getMsg() << "\" from " << p.getSrcIp() << ":" << p.getSrcPort();
|
|
|
|
this->print(s.str());
|
|
}
|
|
sleep(1);
|
|
}
|
|
}
|
|
|
|
void Node::setNetwork()
|
|
{
|
|
this->netConf.network = this->calculateNetwork(this->getIp(), this->getMask());
|
|
}
|
|
|
|
string Node::getNetwork()
|
|
{
|
|
return this->netConf.network;
|
|
}
|
|
|
|
void Node::split(const std::string &s, char delim, vector<string> &elems)
|
|
{
|
|
stringstream ss;
|
|
ss.str(s);
|
|
string item;
|
|
while (getline(ss, item, delim))
|
|
{
|
|
elems.push_back(item);
|
|
}
|
|
}
|
|
|
|
vector<string> Node::split(const string &s, char delim)
|
|
{
|
|
vector<std::string> elems;
|
|
split(s, delim, elems);
|
|
return elems;
|
|
}
|