DHTRoutingTableSerializerTest.cc 8.2 KB

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