/*************************************************************************** * By Théophile Bastian, 2017 * M1 Network course project at ENS Cachan, Juliusz Chroboczek. * License: WTFPL v2 **************************************************************************/ #include "dataStore.h" #include #include #include using namespace std; DataStore::DataStore(Protocol* proto) : proto(proto), myData(0), hasOwnData(false) {} DataStore::~DataStore() { } void DataStore::update() { while(!expireEvents.empty()) { TimeEvent evt = expireEvents.front(); if(evt.time > time(NULL)) // We're done for now. break; expireEvents.pop(); handleExpire(evt.id, evt.seqno); } if(hasOwnData) { if(time(NULL) - recvTime[myData] > csts::TIME_REPUBLISH_DATA) handleRepublish(myData); } } void DataStore::addData(Bytes pck, u32 seqno, u64 id, bool mine) { if(curSeqno.find(id) != curSeqno.end() && curSeqno[id] >= seqno) return; data[id] = Data(pck, mine); curSeqno[id] = seqno; if(mine) { hasOwnData = true; myData = id; } else { expireEvents.push(TimeEvent( time(NULL) + csts::TIMEOUT_DATA, seqno, id)); // If it is not renewed, it will expire. } recvTime[id] = time(NULL); fprintf(stderr, "[INFO] Storing data %lX (%u)\n", id, seqno); handleFlood(id); } ssize_t DataStore::dataSize(u64 id) { if(data.find(id) == data.end()) return -1; return data[id].data.size(); } ssize_t DataStore::readData(u64 id, char* buffer, size_t size) { if(data.find(id) == data.end()) return -1; ssize_t len = min((ssize_t)size, dataSize(id)); data[id].data.writeToBuffer(buffer, size); return len; } void DataStore::ids(std::vector& out) { for(auto& dat : data) out.push_back(dat.first); } void DataStore::setFlooded(u64 id) { toFlood_.erase(id); } void DataStore::dump() { for(auto it=data.begin(); it != data.end(); ++it) { Bytes dat = it->second.data; while(dat.size() >= 2) { printf(">> DATA %lX (%u, %ld sec) ", it->first, curSeqno[it->first], time(NULL)-recvTime[it->first]); if(dat.size() < 2) { printf("INVALID\n"); continue; } u8 type, len; dat >> type >> len; if(dat.size() < len) { printf("INVALID\n"); continue; } if(type == csts::TLV_DATA_TEXT) { string val; for(int i=0; i < len; i++) { u8 c; dat >> c; val += c; } printf("'%s'\n", val.c_str()); } else printf("type=%d\n", type); } } } void DataStore::handleExpire(u64 id, u32 seqno) { if(seqno < curSeqno[id]) return; // Was updated in time cleanData(id); } void DataStore::handleRepublish(u64 datId) { if(data.find(datId) == data.end() || !data[datId].isMine) { return; } curSeqno[datId] = time(NULL); recvTime[datId] = time(NULL); handleFlood(datId); } void DataStore::handleFlood(u64 id) { toFlood_.insert(id); } void DataStore::cleanData(u64 id) { curSeqno.erase(id); recvTime.erase(id); data.erase(id); // Deletes the Bytes as well }