119 lines
2.6 KiB
C++
119 lines
2.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 "configFile.h"
|
|
#include <fstream>
|
|
#include <cstring>
|
|
#include <cstdlib>
|
|
using namespace std;
|
|
|
|
ConfigFile::ConfigFile() : curDataSum(0) {
|
|
selfId = randId();
|
|
}
|
|
|
|
bool ConfigFile::read(const char* path) {
|
|
ifstream handle(path);
|
|
if(!handle.is_open())
|
|
return false;
|
|
|
|
while(handle.good()) {
|
|
string attr;
|
|
handle >> attr;
|
|
|
|
if(attr == "id") {
|
|
handle >> hex >> selfId >> dec;
|
|
}
|
|
else if(attr == "bootstrap") {
|
|
u16 port;
|
|
u64 id;
|
|
SockAddr addr;
|
|
memset(&addr, 0, sizeof(addr));
|
|
addr.sin6_family = AF_INET6;
|
|
string addrStr;
|
|
|
|
handle >> hex >> id >> dec;
|
|
handle >> addrStr;
|
|
handle >> port;
|
|
|
|
addr.sin6_port = htons(port);
|
|
if(inet_pton(AF_INET6, addrStr.c_str(), &(addr.sin6_addr)) != 1) {
|
|
fprintf(stderr, "Could not convert '%s' to IPv6 address\n",
|
|
addrStr.c_str());
|
|
continue;
|
|
}
|
|
|
|
bootstrapNodes.push_back(Neighbour(id, addr));
|
|
}
|
|
else if(attr == "data") {
|
|
string dataStr;
|
|
getline(handle, dataStr);
|
|
|
|
size_t nonWSPos = 0;
|
|
for(; nonWSPos < dataStr.size(); nonWSPos++)
|
|
if(dataStr[nonWSPos] != ' ' && dataStr[nonWSPos] != '\t')
|
|
break;
|
|
if(nonWSPos == dataStr.size())
|
|
continue;
|
|
|
|
std::string realDat = dataStr.substr(nonWSPos);
|
|
if(curDataSum + realDat.size() + 12 + 2 > 0xff) {
|
|
fprintf(stderr, "Too much data, won't fit. Discarding `%s`\n",
|
|
realDat.c_str());
|
|
continue;
|
|
}
|
|
|
|
curDataSum += realDat.size() + 2;
|
|
|
|
data.push_back(realDat);
|
|
}
|
|
else if(attr.empty())
|
|
continue;
|
|
else {
|
|
fprintf(stderr, "Unknown configuration item: '%s'\n",
|
|
attr.c_str());
|
|
continue;
|
|
}
|
|
}
|
|
handle.close();
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ConfigFile::write(const char* path) {
|
|
ofstream handle(path, ofstream::out | ofstream::trunc);
|
|
|
|
if(!handle.is_open())
|
|
return false;
|
|
|
|
handle << "id " << hex << selfId << dec << '\n';
|
|
for(Neighbour nei : bootstrapNodes) {
|
|
char addr[54];
|
|
if(inet_ntop(AF_INET6, &nei.addr.sin6_addr, addr, 54) == NULL) {
|
|
perror("Could not convert IPv6 back to string");
|
|
continue;
|
|
}
|
|
handle << "bootstrap " << hex << nei.id << dec << ' '
|
|
<< addr << ' ' << ntohs(nei.addr.sin6_port) << '\n';
|
|
}
|
|
|
|
for(auto dat : data) {
|
|
handle << "data " << dat << '\n';
|
|
}
|
|
|
|
handle.close();
|
|
|
|
return true;
|
|
}
|
|
|
|
u64 ConfigFile::randId() const {
|
|
u64 out=0;
|
|
for(int i=0; i < 8; i++) {
|
|
out <<= 8;
|
|
out += rand() % 0xFF;
|
|
}
|
|
return out;
|
|
}
|
|
|