149 lines
3.6 KiB
C++
149 lines
3.6 KiB
C++
/***************************************************************************
|
|
* By Théophile Bastian, 2017
|
|
* M1 Network course project at ENS Cachan, Juliusz Chroboczek.
|
|
* License: WTFPL v2 <http://www.wtfpl.net/>
|
|
**************************************************************************/
|
|
|
|
#include "neighbours.h"
|
|
#include "nw_constants.h"
|
|
|
|
#include <cstdlib>
|
|
|
|
using namespace std;
|
|
|
|
Neighbours::Neighbours(Protocol* proto) :
|
|
proto(proto), lastPeerPeek(0)
|
|
{}
|
|
|
|
void Neighbours::fullCheck() {
|
|
for(auto nei : neiType) {
|
|
switch(nei.second) {
|
|
case NEI_SYM:
|
|
if(time(NULL) - lastRecv[nei.first] > csts::TIMEOUT_SYM_RECV
|
|
|| (time(NULL) - lastIHU[nei.first]
|
|
> csts::TIMEOUT_SYM_IHU))
|
|
{
|
|
changeNeiType(nei.first, NEI_POTENTIAL);
|
|
}
|
|
break;
|
|
case NEI_UNIDIR:
|
|
if(time(NULL) - lastRecv[nei.first] > csts::TIMEOUT_UNIDIR)
|
|
changeNeiType(nei.first, NEI_POTENTIAL);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Neighbours::fullUpdate() {
|
|
fullCheck();
|
|
|
|
for(auto nei : unidirNei)
|
|
updateSendPackets(nei);
|
|
for(auto nei : symNei)
|
|
updateSendPackets(nei);
|
|
|
|
if(potentialNei.size() > 0
|
|
&& symNei.size() < csts::SYM_COUNT_BEFORE_PEEK
|
|
&& time(NULL) - lastPeerPeek >= csts::TIME_PEER_PEEK) {
|
|
int nPeerId = rand() % potentialNei.size();
|
|
auto it = potentialNei.begin();
|
|
for(int at=0; at < nPeerId; ++at, ++it);
|
|
proto->sendEmpty(it->id);
|
|
lastPckSent[it->id] = time(NULL);
|
|
lastPeerPeek = time(NULL);
|
|
}
|
|
}
|
|
|
|
void Neighbours::addPotentialNei(const Neighbour& nei) {
|
|
potentialNei.push_back(nei);
|
|
lastRecv.insert({nei.id, 0});
|
|
lastIHU.insert({nei.id, 0});
|
|
neiType.insert({nei.id, NEI_POTENTIAL});
|
|
proto->addIdAddr(nei.addr, nei.id);
|
|
}
|
|
|
|
void Neighbours::receivedFrom(u64 id) {
|
|
NeiType typ = neiType[id];
|
|
lastRecv[id] = time(NULL);
|
|
|
|
if(typ == NEI_POTENTIAL)
|
|
changeNeiType(id, NEI_UNIDIR);
|
|
}
|
|
|
|
void Neighbours::hadIHU(u64 id) {
|
|
NeiType typ = neiType[id];
|
|
lastRecv[id] = time(NULL);
|
|
lastIHU[id] = time(NULL);
|
|
if(typ == NEI_POTENTIAL || typ == NEI_UNIDIR)
|
|
changeNeiType(id, NEI_SYM);
|
|
}
|
|
|
|
list<Neighbour>* Neighbours::listOfType(NeiType typ) {
|
|
switch(typ) {
|
|
case NEI_POTENTIAL:
|
|
return &potentialNei;
|
|
case NEI_UNIDIR:
|
|
return &unidirNei;
|
|
case NEI_SYM:
|
|
return &symNei;
|
|
default:
|
|
break;
|
|
}
|
|
throw WrongNeiType();
|
|
}
|
|
|
|
void Neighbours::changeNeiType(u64 id, NeiType nType) {
|
|
printf("TYPE %lX %d\n", id, neiType[id]);
|
|
NeiType cType = neiType[id];
|
|
if(cType == nType)
|
|
return;
|
|
list<Neighbour> *fromList = listOfType(cType),
|
|
*toList = listOfType(nType);
|
|
neiType[id] = nType;
|
|
|
|
bool wasSpliced=false;
|
|
for(auto it=fromList->begin(); it != fromList->end(); ++it) {
|
|
if(it->id == id) {
|
|
printf("%ld %ld\n", fromList->size(), toList->size());
|
|
toList->push_back(*it); // splice() doesn't work?!
|
|
fromList->erase(it);
|
|
printf("%ld %ld %d\n", fromList->size(), toList->size(),
|
|
toList == &unidirNei);
|
|
wasSpliced=true;
|
|
break;
|
|
}
|
|
}
|
|
if(!wasSpliced) {
|
|
fprintf(stderr, "[ERROR] Node %lX wasn't found (type change)\n", id);
|
|
}
|
|
printf("TYPE %lX %d\n", id, neiType[id]);
|
|
}
|
|
|
|
void Neighbours::updateSendPackets(const Neighbour& nei) {
|
|
if(!sendIHU(nei.id))
|
|
sendEmpty(nei.id);
|
|
}
|
|
|
|
bool Neighbours::sendEmpty(u64 id) {
|
|
if(time(NULL) - lastPckSent[id] >= csts::TIME_RESEND_EMPTY) {
|
|
printf("[DBG] sending empty packet to %lX.\n", id);
|
|
lastPckSent[id] = time(NULL);
|
|
proto->sendEmpty(id);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Neighbours::sendIHU(u64 id) {
|
|
if(time(NULL) - lastIHUSent[id] >= csts::TIME_RESEND_IHU) {
|
|
printf("[DBG] sending IHU packet to %lX.\n", id);
|
|
lastIHUSent[id] = time(NULL);
|
|
lastPckSent[id] = time(NULL);
|
|
proto->sendIHU(id);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|