/*************************************************************************** * By Théophile Bastian, 2017 * M1 Network course project at ENS Cachan, Juliusz Chroboczek. * License: WTFPL v2 **************************************************************************/ #include "neighbours.h" #include "nw_constants.h" #include 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, proto); for(auto nei : symNei) updateSendPackets(nei, proto); 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); 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.insert({id, time(NULL)}); if(typ == NEI_POTENTIAL) changeNeiType(id, NEI_UNIDIR); } void Neighbours::hadIHU(u64 id) { NeiType typ = neiType[id]; lastRecv.insert({id, time(NULL)}); lastIHU.insert({id, time(NULL)}); if(typ == NEI_POTENTIAL || typ == NEI_UNIDIR) changeNeiType(id, NEI_SYM); } list& 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) { NeiType cType = neiType[id]; if(cType == nType) return; list& fromList = listOfType(cType), toList = listOfType(nType); neiType.insert({id, nType}); bool wasSpliced=false; for(auto it=fromList.begin(); it != fromList.end(); ++it) { if(it->id == id) { fromList.splice(it, toList); wasSpliced=true; break; } } if(!wasSpliced) { //TODO log error. } } void Neighbours::updateSendPackets(const Neighbour& nei, Protocol* proto) { if(time(NULL) - lastIHUSent[nei.id] >= csts::TIME_RESEND_IHU) { lastIHUSent[nei.id] = time(NULL); lastPckSent[nei.id] = time(NULL); proto->sendIHU(nei.id); } else if(time(NULL) - lastPckSent[nei.id] >= csts::TIME_RESEND_EMPTY) { lastPckSent[nei.id] = time(NULL); proto->sendEmpty(nei.id); } }