|
@@ -56,136 +56,161 @@ DHTRoutingTableDeserializer::DHTRoutingTableDeserializer() {}
|
|
|
|
|
|
DHTRoutingTableDeserializer::~DHTRoutingTableDeserializer() {}
|
|
|
|
|
|
-static std::istream& readBytes(unsigned char* buf, size_t buflen,
|
|
|
- std::istream& in, size_t readlen)
|
|
|
+static void readBytes(unsigned char* buf, size_t buflen,
|
|
|
+ std::istream& in, size_t readlen)
|
|
|
{
|
|
|
assert(readlen <= buflen);
|
|
|
- return in.read(reinterpret_cast<char*>(buf), readlen);
|
|
|
+ in.read(reinterpret_cast<char*>(buf), readlen);
|
|
|
}
|
|
|
|
|
|
+#define CHECK_STREAM(in, length) \
|
|
|
+ if(in.gcount() != length) { \
|
|
|
+ throw DL_ABORT_EX \
|
|
|
+ (StringFormat("Failed to load DHT routing table. cause:%s", \
|
|
|
+ "Unexpected EOF").str()); \
|
|
|
+ } \
|
|
|
+ if(!in) { \
|
|
|
+ throw DL_ABORT_EX \
|
|
|
+ (StringFormat("Failed to load DHT routing table. cause:%s", \
|
|
|
+ strerror(errno)).str()); \
|
|
|
+ }
|
|
|
+
|
|
|
void DHTRoutingTableDeserializer::deserialize(std::istream& in)
|
|
|
{
|
|
|
- try {
|
|
|
- char header[8];
|
|
|
- memset(header, 0, sizeof(header));
|
|
|
- // magic
|
|
|
- header[0] = 0xa1;
|
|
|
- header[1] = 0xa2;
|
|
|
- // format ID
|
|
|
- header[2] = 0x02;
|
|
|
- // version
|
|
|
- header[6] = 0;
|
|
|
- header[7] = 0x03;
|
|
|
-
|
|
|
- char headerCompat[8];
|
|
|
- memset(headerCompat, 0, sizeof(headerCompat));
|
|
|
- // magic
|
|
|
- headerCompat[0] = 0xa1;
|
|
|
- headerCompat[1] = 0xa2;
|
|
|
- // format ID
|
|
|
- headerCompat[2] = 0x02;
|
|
|
- // version
|
|
|
- headerCompat[6] = 0;
|
|
|
- headerCompat[7] = 0x02;
|
|
|
-
|
|
|
- char zero[8];
|
|
|
- memset(zero, 0, sizeof(zero));
|
|
|
-
|
|
|
- int version;
|
|
|
-
|
|
|
- // If you change the code to read more than the size of buf, then
|
|
|
- // expand the buf size here.
|
|
|
- array_wrapper<unsigned char, 255> buf;
|
|
|
-
|
|
|
- // header
|
|
|
- readBytes(buf, buf.size(), in, 8);
|
|
|
- if(memcmp(header, buf, 8) == 0) {
|
|
|
- version = 3;
|
|
|
- } else if(memcmp(headerCompat, buf, 8) == 0) {
|
|
|
- version = 2;
|
|
|
- } else {
|
|
|
- throw DL_ABORT_EX
|
|
|
- (StringFormat("Failed to load DHT routing table. cause:%s",
|
|
|
- "bad header").str());
|
|
|
- }
|
|
|
+ char header[8];
|
|
|
+ memset(header, 0, sizeof(header));
|
|
|
+ // magic
|
|
|
+ header[0] = 0xa1;
|
|
|
+ header[1] = 0xa2;
|
|
|
+ // format ID
|
|
|
+ header[2] = 0x02;
|
|
|
+ // version
|
|
|
+ header[6] = 0;
|
|
|
+ header[7] = 0x03;
|
|
|
+
|
|
|
+ char headerCompat[8];
|
|
|
+ memset(headerCompat, 0, sizeof(headerCompat));
|
|
|
+ // magic
|
|
|
+ headerCompat[0] = 0xa1;
|
|
|
+ headerCompat[1] = 0xa2;
|
|
|
+ // format ID
|
|
|
+ headerCompat[2] = 0x02;
|
|
|
+ // version
|
|
|
+ headerCompat[6] = 0;
|
|
|
+ headerCompat[7] = 0x02;
|
|
|
+
|
|
|
+ char zero[8];
|
|
|
+ memset(zero, 0, sizeof(zero));
|
|
|
+
|
|
|
+ int version;
|
|
|
+
|
|
|
+ // If you change the code to read more than the size of buf, then
|
|
|
+ // expand the buf size here.
|
|
|
+ array_wrapper<unsigned char, 255> buf;
|
|
|
+
|
|
|
+ // header
|
|
|
+ readBytes(buf, buf.size(), in, 8);
|
|
|
+ CHECK_STREAM(in, 8);
|
|
|
+ if(memcmp(header, buf, 8) == 0) {
|
|
|
+ version = 3;
|
|
|
+ } else if(memcmp(headerCompat, buf, 8) == 0) {
|
|
|
+ version = 2;
|
|
|
+ } else {
|
|
|
+ throw DL_ABORT_EX
|
|
|
+ (StringFormat("Failed to load DHT routing table. cause:%s",
|
|
|
+ "bad header").str());
|
|
|
+ }
|
|
|
|
|
|
- uint32_t temp32;
|
|
|
- uint64_t temp64;
|
|
|
- // time
|
|
|
- if(version == 2) {
|
|
|
- in.read(reinterpret_cast<char*>(&temp32), sizeof(temp32));
|
|
|
- _serializedTime.setTimeInSec(ntohl(temp32));
|
|
|
- // 4bytes reserved
|
|
|
- readBytes(buf, buf.size(), in, 4);
|
|
|
- } else {
|
|
|
- in.read(reinterpret_cast<char*>(&temp64), sizeof(temp64));
|
|
|
- _serializedTime.setTimeInSec(ntoh64(temp64));
|
|
|
- }
|
|
|
+ uint32_t temp32;
|
|
|
+ uint64_t temp64;
|
|
|
+ // time
|
|
|
+ if(version == 2) {
|
|
|
+ in.read(reinterpret_cast<char*>(&temp32), sizeof(temp32));
|
|
|
+ CHECK_STREAM(in, sizeof(temp32));
|
|
|
+ _serializedTime.setTimeInSec(ntohl(temp32));
|
|
|
+ // 4bytes reserved
|
|
|
+ readBytes(buf, buf.size(), in, 4);
|
|
|
+ CHECK_STREAM(in, 4);
|
|
|
+ } else {
|
|
|
+ in.read(reinterpret_cast<char*>(&temp64), sizeof(temp64));
|
|
|
+ CHECK_STREAM(in, sizeof(temp64));
|
|
|
+ _serializedTime.setTimeInSec(ntoh64(temp64));
|
|
|
+ }
|
|
|
|
|
|
- // localnode
|
|
|
- // 8bytes reserved
|
|
|
- readBytes(buf, buf.size(), in, 8);
|
|
|
+ // localnode
|
|
|
+ // 8bytes reserved
|
|
|
+ readBytes(buf, buf.size(), in, 8);
|
|
|
+ CHECK_STREAM(in, 8);
|
|
|
+ // localnode ID
|
|
|
+ readBytes(buf, buf.size(), in, DHT_ID_LENGTH);
|
|
|
+ CHECK_STREAM(in, DHT_ID_LENGTH);
|
|
|
+ SharedHandle<DHTNode> localNode(new DHTNode(buf));
|
|
|
+ // 4bytes reserved
|
|
|
+ readBytes(buf, buf.size(), in, 4);
|
|
|
+ CHECK_STREAM(in, 4);
|
|
|
+
|
|
|
+ // number of nodes
|
|
|
+ in.read(reinterpret_cast<char*>(&temp32), sizeof(temp32));
|
|
|
+ CHECK_STREAM(in, sizeof(temp32));
|
|
|
+ uint32_t numNodes = ntohl(temp32);
|
|
|
+ // 4bytes reserved
|
|
|
+ readBytes(buf, buf.size(), in, 4);
|
|
|
+ CHECK_STREAM(in, 4);
|
|
|
+
|
|
|
+ std::deque<SharedHandle<DHTNode> > nodes;
|
|
|
+ // nodes
|
|
|
+ for(size_t i = 0; i < numNodes; ++i) {
|
|
|
+ // Currently, only IPv4 addresses are supported.
|
|
|
+ // 1byte compact peer info length
|
|
|
+ uint8_t peerInfoLen;
|
|
|
+ in >> peerInfoLen;
|
|
|
+ if(peerInfoLen != 6) {
|
|
|
+ // skip this entry
|
|
|
+ readBytes(buf, buf.size(), in, 42+7+6);
|
|
|
+ CHECK_STREAM(in, 42+7+6);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // 7bytes reserved
|
|
|
+ readBytes(buf, buf.size(), in, 7);
|
|
|
+ CHECK_STREAM(in, 7);
|
|
|
+ // 6bytes compact peer info
|
|
|
+ readBytes(buf, buf.size(), in, 6);
|
|
|
+ CHECK_STREAM(in, 6);
|
|
|
+ if(memcmp(zero, buf, 6) == 0) {
|
|
|
+ // skip this entry
|
|
|
+ readBytes(buf, buf.size(), in, 42);
|
|
|
+ CHECK_STREAM(in, 42);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ std::pair<std::string, uint16_t> peer =
|
|
|
+ PeerMessageUtil::unpackcompact(buf);
|
|
|
+ if(peer.first.empty()) {
|
|
|
+ // skip this entry
|
|
|
+ readBytes(buf, buf.size(), in, 42);
|
|
|
+ CHECK_STREAM(in, 42);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // 2bytes reserved
|
|
|
+ readBytes(buf, buf.size(), in, 2);
|
|
|
+ CHECK_STREAM(in, 2);
|
|
|
+ // 16byte reserved
|
|
|
+ readBytes(buf, buf.size(), in, 16);
|
|
|
+ CHECK_STREAM(in, 16);
|
|
|
// localnode ID
|
|
|
readBytes(buf, buf.size(), in, DHT_ID_LENGTH);
|
|
|
- SharedHandle<DHTNode> localNode(new DHTNode(buf));
|
|
|
- // 4bytes reserved
|
|
|
- readBytes(buf, buf.size(), in, 4);
|
|
|
+ CHECK_STREAM(in, DHT_ID_LENGTH);
|
|
|
|
|
|
- // number of nodes
|
|
|
- in.read(reinterpret_cast<char*>(&temp32), sizeof(temp32));
|
|
|
- uint32_t numNodes = ntohl(temp32);
|
|
|
+ SharedHandle<DHTNode> node(new DHTNode(buf));
|
|
|
+ node->setIPAddress(peer.first);
|
|
|
+ node->setPort(peer.second);
|
|
|
// 4bytes reserved
|
|
|
readBytes(buf, buf.size(), in, 4);
|
|
|
+ CHECK_STREAM(in, 4);
|
|
|
|
|
|
- // nodes
|
|
|
- for(size_t i = 0; i < numNodes; ++i) {
|
|
|
- // Currently, only IPv4 addresses are supported.
|
|
|
- // 1byte compact peer info length
|
|
|
- uint8_t peerInfoLen;
|
|
|
- in >> peerInfoLen;
|
|
|
- if(peerInfoLen != 6) {
|
|
|
- // skip this entry
|
|
|
- readBytes(buf, buf.size(), in, 42+7+6);
|
|
|
- continue;
|
|
|
- }
|
|
|
- // 7bytes reserved
|
|
|
- readBytes(buf, buf.size(), in, 7);
|
|
|
- // 6bytes compact peer info
|
|
|
- readBytes(buf, buf.size(), in, 6);
|
|
|
- if(memcmp(zero, buf, 6) == 0) {
|
|
|
- // skip this entry
|
|
|
- readBytes(buf, buf.size(), in, 42);
|
|
|
- continue;
|
|
|
- }
|
|
|
- std::pair<std::string, uint16_t> peer =
|
|
|
- PeerMessageUtil::unpackcompact(buf);
|
|
|
- if(peer.first.empty()) {
|
|
|
- // skip this entry
|
|
|
- readBytes(buf, buf.size(), in, 42);
|
|
|
- continue;
|
|
|
- }
|
|
|
- // 2bytes reserved
|
|
|
- readBytes(buf, buf.size(), in, 2);
|
|
|
- // 16byte reserved
|
|
|
- readBytes(buf, buf.size(), in, 16);
|
|
|
- // localnode ID
|
|
|
- readBytes(buf, buf.size(), in, DHT_ID_LENGTH);
|
|
|
-
|
|
|
- SharedHandle<DHTNode> node(new DHTNode(buf));
|
|
|
- node->setIPAddress(peer.first);
|
|
|
- node->setPort(peer.second);
|
|
|
- // 4bytes reserved
|
|
|
- readBytes(buf, buf.size(), in, 4);
|
|
|
-
|
|
|
- _nodes.push_back(node);
|
|
|
- }
|
|
|
- _localNode = localNode;
|
|
|
- } catch(std::ios::failure const& exception) {
|
|
|
- _nodes.clear();
|
|
|
- throw DL_ABORT_EX
|
|
|
- (StringFormat("Failed to load DHT routing table. cause:%s",
|
|
|
- strerror(errno)).str());
|
|
|
+ nodes.push_back(node);
|
|
|
}
|
|
|
+ _localNode = localNode;
|
|
|
+ _nodes = nodes;
|
|
|
}
|
|
|
|
|
|
} // namespace aria2
|