DHTRoutingTableSerializerTest.cc 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. #include "DHTRoutingTableSerializer.h"
  2. #include <cstring>
  3. #include <fstream>
  4. #include <iostream>
  5. #include <cppunit/extensions/HelperMacros.h>
  6. #include "Exception.h"
  7. #include "util.h"
  8. #include "DHTNode.h"
  9. #include "array_fun.h"
  10. #include "DHTConstants.h"
  11. #include "bittorrent_helper.h"
  12. #include "a2netcompat.h"
  13. namespace aria2 {
  14. class DHTRoutingTableSerializerTest : public CppUnit::TestFixture {
  15. CPPUNIT_TEST_SUITE(DHTRoutingTableSerializerTest);
  16. CPPUNIT_TEST(testSerialize);
  17. CPPUNIT_TEST(testSerialize6);
  18. CPPUNIT_TEST_SUITE_END();
  19. private:
  20. char zero[256];
  21. char buf[20];
  22. void checkToLocalnode(std::istream& ss,
  23. const std::shared_ptr<DHTNode>& localNode);
  24. void checkNumNodes(std::istream& ss, size_t expected);
  25. public:
  26. void setUp() { memset(zero, 0, sizeof(zero)); }
  27. void tearDown() {}
  28. void testSerialize();
  29. void testSerialize6();
  30. };
  31. CPPUNIT_TEST_SUITE_REGISTRATION(DHTRoutingTableSerializerTest);
  32. void DHTRoutingTableSerializerTest::checkToLocalnode(
  33. std::istream& ss, const std::shared_ptr<DHTNode>& localNode)
  34. {
  35. // header
  36. ss.read(buf, 8);
  37. // magic
  38. CPPUNIT_ASSERT((char)0xa1 == buf[0]);
  39. CPPUNIT_ASSERT((char)0xa2 == buf[1]);
  40. // format ID
  41. CPPUNIT_ASSERT((char)0x02 == buf[2]);
  42. // reserved
  43. CPPUNIT_ASSERT((char)0x00 == buf[3]);
  44. CPPUNIT_ASSERT((char)0x00 == buf[4]);
  45. CPPUNIT_ASSERT((char)0x00 == buf[5]);
  46. // version
  47. CPPUNIT_ASSERT((char)0x00 == buf[6]);
  48. CPPUNIT_ASSERT((char)0x03 == buf[7]);
  49. // time
  50. ss.read(buf, 8);
  51. time_t time;
  52. uint64_t timebuf;
  53. memcpy(&timebuf, buf, sizeof(timebuf));
  54. time = ntoh64(timebuf);
  55. std::cerr << time << std::endl;
  56. // localnode
  57. // 8bytes reserved
  58. ss.read(buf, 8);
  59. CPPUNIT_ASSERT(memcmp(zero, buf, 8) == 0);
  60. // localnode ID
  61. ss.read(buf, DHT_ID_LENGTH);
  62. CPPUNIT_ASSERT(memcmp(localNode->getID(), buf, DHT_ID_LENGTH) == 0);
  63. // 4bytes reserved
  64. ss.read(buf, 4);
  65. CPPUNIT_ASSERT(memcmp(zero, buf, 4) == 0);
  66. }
  67. void DHTRoutingTableSerializerTest::checkNumNodes(std::istream& ss,
  68. size_t expected)
  69. {
  70. // number of nodes saved
  71. ss.read(buf, 4);
  72. uint32_t numNodes;
  73. memcpy(&numNodes, buf, sizeof(numNodes));
  74. numNodes = ntohl(numNodes);
  75. CPPUNIT_ASSERT_EQUAL((uint32_t)expected, numNodes);
  76. }
  77. void DHTRoutingTableSerializerTest::testSerialize()
  78. {
  79. std::shared_ptr<DHTNode> localNode(new DHTNode());
  80. std::vector<std::shared_ptr<DHTNode>> nodes(3);
  81. for (size_t i = 0; i < nodes.size(); ++i) {
  82. nodes[i].reset(new DHTNode());
  83. nodes[i]->setIPAddress("192.168.0." + util::uitos(i + 1));
  84. nodes[i]->setPort(6881 + i);
  85. }
  86. nodes[1]->setIPAddress("non-numerical-name");
  87. DHTRoutingTableSerializer s(AF_INET);
  88. s.setLocalNode(localNode);
  89. s.setNodes(nodes);
  90. std::string filename =
  91. A2_TEST_OUT_DIR "/aria2_DHTRoutingTableSerializerTest_testSerialize";
  92. s.serialize(filename);
  93. std::ifstream ss(filename.c_str(), std::ios::binary);
  94. checkToLocalnode(ss, localNode);
  95. size_t numNodes = 3;
  96. checkNumNodes(ss, numNodes);
  97. // 4bytes reserved
  98. ss.read(buf, 4);
  99. CPPUNIT_ASSERT(memcmp(zero, buf, 4) == 0);
  100. // node[0]
  101. // 1byte compatc peer format length
  102. {
  103. uint8_t len;
  104. ss >> len;
  105. CPPUNIT_ASSERT_EQUAL((uint8_t)6, len);
  106. }
  107. // 7bytes reserved
  108. ss.read(buf, 7);
  109. CPPUNIT_ASSERT(memcmp(zero, buf, 7) == 0);
  110. // 6bytes compact peer info
  111. ss.read(buf, 6);
  112. {
  113. std::pair<std::string, uint16_t> peer = bittorrent::unpackcompact(
  114. reinterpret_cast<const unsigned char*>(buf), AF_INET);
  115. CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.1"), peer.first);
  116. CPPUNIT_ASSERT_EQUAL((uint16_t)6881, peer.second);
  117. }
  118. // 2bytes reserved
  119. ss.read(buf, 2);
  120. CPPUNIT_ASSERT(memcmp(zero, buf, 2) == 0);
  121. // 16bytes reserved
  122. ss.read(buf, 16);
  123. CPPUNIT_ASSERT(memcmp(zero, buf, 16) == 0);
  124. // localnode ID
  125. ss.read(buf, DHT_ID_LENGTH);
  126. CPPUNIT_ASSERT(memcmp(nodes[0]->getID(), buf, DHT_ID_LENGTH) == 0);
  127. // 4bytes reserved
  128. ss.read(buf, 4);
  129. CPPUNIT_ASSERT(memcmp(zero, buf, 4) == 0);
  130. // node[1]
  131. // 1byte compatc peer format length
  132. {
  133. uint8_t len;
  134. ss >> len;
  135. CPPUNIT_ASSERT_EQUAL((uint8_t)6, len);
  136. }
  137. // 7bytes reserved
  138. ss.read(buf, 7);
  139. CPPUNIT_ASSERT(memcmp(zero, buf, 7) == 0);
  140. // 6bytes compact peer info
  141. ss.read(buf, 6);
  142. // zero filled because node[1]'s hostname is not numerical form
  143. // deserializer should skip this entry
  144. CPPUNIT_ASSERT(memcmp(zero, buf, 6) == 0);
  145. // 2bytes reserved
  146. ss.read(buf, 2);
  147. CPPUNIT_ASSERT(memcmp(zero, buf, 2) == 0);
  148. // 16bytes reserved
  149. ss.read(buf, 16);
  150. CPPUNIT_ASSERT(memcmp(zero, buf, 16) == 0);
  151. // localnode ID
  152. ss.read(buf, DHT_ID_LENGTH);
  153. CPPUNIT_ASSERT(memcmp(nodes[1]->getID(), buf, DHT_ID_LENGTH) == 0);
  154. // 4bytes reserved
  155. ss.read(buf, 4);
  156. CPPUNIT_ASSERT(memcmp(zero, buf, 4) == 0);
  157. // node[2]
  158. // 1byte compatc peer format length
  159. {
  160. uint8_t len;
  161. ss >> len;
  162. CPPUNIT_ASSERT_EQUAL((uint8_t)6, len);
  163. }
  164. // 7bytes reserved
  165. ss.read(buf, 7);
  166. CPPUNIT_ASSERT(memcmp(zero, buf, 7) == 0);
  167. // 6bytes compact peer info
  168. ss.read(buf, 6);
  169. {
  170. std::pair<std::string, uint16_t> peer = bittorrent::unpackcompact(
  171. reinterpret_cast<const unsigned char*>(buf), AF_INET);
  172. CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.3"), peer.first);
  173. CPPUNIT_ASSERT_EQUAL((uint16_t)6883, peer.second);
  174. }
  175. // 2bytes reserved
  176. ss.read(buf, 2);
  177. CPPUNIT_ASSERT(memcmp(zero, buf, 2) == 0);
  178. // 16bytes reserved
  179. ss.read(buf, 16);
  180. CPPUNIT_ASSERT(memcmp(zero, buf, 16) == 0);
  181. // localnode ID
  182. ss.read(buf, DHT_ID_LENGTH);
  183. CPPUNIT_ASSERT(memcmp(nodes[2]->getID(), buf, DHT_ID_LENGTH) == 0);
  184. // 4bytes reserved
  185. ss.read(buf, 4);
  186. CPPUNIT_ASSERT(memcmp(zero, buf, 4) == 0);
  187. // check to see stream ends
  188. ss.read(buf, 1);
  189. CPPUNIT_ASSERT_EQUAL((std::streamsize)0, ss.gcount());
  190. CPPUNIT_ASSERT(ss.eof());
  191. }
  192. void DHTRoutingTableSerializerTest::testSerialize6()
  193. {
  194. std::shared_ptr<DHTNode> localNode(new DHTNode());
  195. std::vector<std::shared_ptr<DHTNode>> nodes(2);
  196. for (size_t i = 0; i < nodes.size(); ++i) {
  197. nodes[i].reset(new DHTNode());
  198. nodes[i]->setIPAddress("2001::100" + util::uitos(i + 1));
  199. nodes[i]->setPort(6881 + i);
  200. }
  201. nodes[1]->setIPAddress("non-numerical-name");
  202. DHTRoutingTableSerializer s(AF_INET6);
  203. s.setLocalNode(localNode);
  204. s.setNodes(nodes);
  205. std::string filename =
  206. A2_TEST_OUT_DIR "/aria2_DHTRoutingTableSerializerTest_testSerialize6";
  207. s.serialize(filename);
  208. std::ifstream ss(filename.c_str(), std::ios::binary);
  209. checkToLocalnode(ss, localNode);
  210. size_t numNodes = 2;
  211. checkNumNodes(ss, numNodes);
  212. // 4bytes reserved
  213. ss.read(buf, 4);
  214. CPPUNIT_ASSERT(memcmp(zero, buf, 4) == 0);
  215. // node[0]
  216. // 1byte compatc peer format length
  217. {
  218. uint8_t len;
  219. ss >> len;
  220. CPPUNIT_ASSERT_EQUAL((uint8_t)18, len);
  221. }
  222. // 7bytes reserved
  223. ss.read(buf, 7);
  224. CPPUNIT_ASSERT(memcmp(zero, buf, 7) == 0);
  225. // 18 bytes compact peer info
  226. ss.read(buf, 18);
  227. {
  228. std::pair<std::string, uint16_t> peer = bittorrent::unpackcompact(
  229. reinterpret_cast<const unsigned char*>(buf), AF_INET6);
  230. CPPUNIT_ASSERT_EQUAL(std::string("2001::1001"), peer.first);
  231. CPPUNIT_ASSERT_EQUAL((uint16_t)6881, peer.second);
  232. }
  233. // 6bytes reserved
  234. ss.read(buf, 6);
  235. CPPUNIT_ASSERT(memcmp(zero, buf, 6) == 0);
  236. // localnode ID
  237. ss.read(buf, DHT_ID_LENGTH);
  238. CPPUNIT_ASSERT(memcmp(nodes[0]->getID(), buf, DHT_ID_LENGTH) == 0);
  239. // 4bytes reserved
  240. ss.read(buf, 4);
  241. CPPUNIT_ASSERT(memcmp(zero, buf, 4) == 0);
  242. // node[1]
  243. // 1byte compatc peer format length
  244. {
  245. uint8_t len;
  246. ss >> len;
  247. CPPUNIT_ASSERT_EQUAL((uint8_t)18, len);
  248. }
  249. // 7bytes reserved
  250. ss.read(buf, 7);
  251. CPPUNIT_ASSERT(memcmp(zero, buf, 7) == 0);
  252. // 18bytes compact peer info
  253. ss.read(buf, 18);
  254. // zero filled because node[1]'s hostname is not numerical form
  255. // deserializer should skip this entry
  256. CPPUNIT_ASSERT(memcmp(zero, buf, 18) == 0);
  257. // 6bytes reserved
  258. ss.read(buf, 6);
  259. CPPUNIT_ASSERT(memcmp(zero, buf, 6) == 0);
  260. // localnode ID
  261. ss.read(buf, DHT_ID_LENGTH);
  262. CPPUNIT_ASSERT(memcmp(nodes[1]->getID(), buf, DHT_ID_LENGTH) == 0);
  263. // 4bytes reserved
  264. ss.read(buf, 4);
  265. CPPUNIT_ASSERT(memcmp(zero, buf, 4) == 0);
  266. // check to see stream ends
  267. ss.read(buf, 1);
  268. CPPUNIT_ASSERT_EQUAL((std::streamsize)0, ss.gcount());
  269. CPPUNIT_ASSERT(ss.eof());
  270. }
  271. } // namespace aria2