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.
 
 

284 lines
5.8 KiB

/*
* 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;
}