Master 1 network course project
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.

129 lines
2.8 KiB

/***************************************************************************
* By Théophile Bastian, 2017
* M1 Network course project at ENS Cachan, Juliusz Chroboczek.
* License: WTFPL v2 <http://www.wtfpl.net/>
**************************************************************************/
#include "packetParser.h"
#include <cstring>
PacketParser::PacketParser(Neighbours* nei, Protocol* proto,
DataStore* dataStore) :
neighbours(nei), protocol(proto), dataStore(dataStore)
{}
void PacketParser::parse(Bytes pck, const SockAddr& addr) {
u64 peerId;
if(pck.size() < 8) {
fprintf(stderr, "[WARNING] Bad packet size.\n");
return;
}
pck >> peerId;
neighbours->receivedFrom(peerId, addr);
while(pck.size() > 0) {
readTLV(pck, peerId, addr);
}
}
void PacketParser::readTLV(Bytes& pck, u64 nei, const SockAddr& addr) {
u8 type, len;
if(pck.size() < 2) {
fprintf(stderr, "[WARNING] Bad packet size from %lX.\n", nei);
return;
}
pck >> type >> len;
fprintf(stderr, "[INFO] Parsing %d from %lX.\n", type, nei);
if(pck.size() < len) {
fprintf(stderr, "[WARNING] Advertised TLV does not fit in the packet"
".\n");
pck.extract(pck.size());
return;
}
Bytes subpacket = pck.extract(len);
switch(type) {
case csts::TLV_PAD1:
case csts::TLV_PADN:
break;
case csts::TLV_IHU: {
u64 ihuId;
subpacket >> ihuId;
if(ihuId != protocol->getSelfId())
break;
neighbours->hadIHU(nei, addr);
break;
}
case csts::TLV_NR:
handleNR(nei);
break;
case csts::TLV_NEIGH:
receiveNeigh(subpacket);
break;
case csts::TLV_DATA:
receiveData(subpacket, nei);
break;
case csts::TLV_IHAVE:
receiveIHave(subpacket, nei);
break;
}
}
void PacketParser::receiveNeigh(Bytes& pck) {
while(pck.size() >= 8+16+2) { /* enough to read one peer */
u64 id;
u16 port;
SockAddr addr;
memset(&addr, 0, sizeof(addr));
addr.sin6_family = AF_INET6;
pck >> id;
for(int byte=0; byte < 16; byte++)
pck >> addr.sin6_addr.s6_addr[byte];
pck >> port;
addr.sin6_port = htons(port);
if(id == protocol->getSelfId())
continue;
Neighbour nei(id, addr);
neighbours->addPotentialNei(nei);
}
}
void PacketParser::receiveData(Bytes& pck, u64 from) {
u32 seqNo;
u64 datId;
pck >> seqNo >> datId;
neighbours->gotIHave(from, datId, seqNo);
protocol->sendIHave(from, datId, seqNo);
dataStore->addData(pck, seqNo, datId, false);
}
void PacketParser::receiveIHave(Bytes& pck, u64 from) {
u32 seqno;
u64 datId;
if(pck.size() < 8+4) {
fprintf(stderr, "[WARNING] IHave too short from %lX\n", from);
return;
}
pck >> seqno >> datId;
neighbours->gotIHave(from, datId, seqno);
}
void PacketParser::handleNR(u64 from) {
std::vector<Neighbour> neigh;
neighbours->getNeighbours(neigh, from, csts::NB_NEIGH_PER_NR);
protocol->sendNeighbours(from, neigh);
}