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