UDPTrackerClientTest.cc 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. #include "UDPTrackerClient.h"
  2. #include <cstring>
  3. #include <cppunit/extensions/HelperMacros.h>
  4. #include "TestUtil.h"
  5. #include "UDPTrackerRequest.h"
  6. #include "bittorrent_helper.h"
  7. #include "wallclock.h"
  8. namespace aria2 {
  9. class UDPTrackerClientTest : public CppUnit::TestFixture {
  10. CPPUNIT_TEST_SUITE(UDPTrackerClientTest);
  11. CPPUNIT_TEST(testCreateUDPTrackerConnect);
  12. CPPUNIT_TEST(testCreateUDPTrackerAnnounce);
  13. CPPUNIT_TEST(testConnectFollowedByAnnounce);
  14. CPPUNIT_TEST(testRequestFailure);
  15. CPPUNIT_TEST(testTimeout);
  16. CPPUNIT_TEST_SUITE_END();
  17. public:
  18. void setUp() {}
  19. void testCreateUDPTrackerConnect();
  20. void testCreateUDPTrackerAnnounce();
  21. void testConnectFollowedByAnnounce();
  22. void testRequestFailure();
  23. void testTimeout();
  24. };
  25. CPPUNIT_TEST_SUITE_REGISTRATION(UDPTrackerClientTest);
  26. namespace {
  27. std::shared_ptr<UDPTrackerRequest> createAnnounce(const std::string& remoteAddr,
  28. uint16_t remotePort,
  29. uint32_t transactionId)
  30. {
  31. std::shared_ptr<UDPTrackerRequest> req(new UDPTrackerRequest());
  32. req->connectionId = std::numeric_limits<uint64_t>::max();
  33. req->action = UDPT_ACT_ANNOUNCE;
  34. req->remoteAddr = remoteAddr;
  35. req->remotePort = remotePort;
  36. req->transactionId = transactionId;
  37. req->infohash = "bittorrent-infohash-";
  38. req->peerId = "bittorrent-peer-id--";
  39. req->downloaded = INT64_MAX - 1;
  40. req->left = INT64_MAX - 2;
  41. req->uploaded = INT64_MAX - 3;
  42. req->event = UDPT_EVT_STARTED;
  43. req->ip = 0;
  44. req->key = 1000000007;
  45. req->numWant = 50;
  46. req->port = 6889;
  47. req->extensions = 0;
  48. return req;
  49. }
  50. } // namespace
  51. namespace {
  52. ssize_t createErrorReply(unsigned char* data, size_t len,
  53. uint32_t transactionId, const std::string& errorString)
  54. {
  55. bittorrent::setIntParam(data, UDPT_ACT_ERROR);
  56. bittorrent::setIntParam(data + 4, transactionId);
  57. memcpy(data + 8, errorString.c_str(), errorString.size());
  58. return 8 + errorString.size();
  59. }
  60. } // namespace
  61. namespace {
  62. ssize_t createConnectReply(unsigned char* data, size_t len,
  63. uint64_t connectionId, uint32_t transactionId)
  64. {
  65. bittorrent::setIntParam(data, UDPT_ACT_CONNECT);
  66. bittorrent::setIntParam(data + 4, transactionId);
  67. bittorrent::setLLIntParam(data + 8, connectionId);
  68. return 16;
  69. }
  70. } // namespace
  71. namespace {
  72. ssize_t createAnnounceReply(unsigned char* data, size_t len,
  73. uint32_t transactionId, int numPeers = 0)
  74. {
  75. bittorrent::setIntParam(data, UDPT_ACT_ANNOUNCE);
  76. bittorrent::setIntParam(data + 4, transactionId);
  77. bittorrent::setIntParam(data + 8, 1800);
  78. bittorrent::setIntParam(data + 12, 100);
  79. bittorrent::setIntParam(data + 16, 256);
  80. for (int i = 0; i < numPeers; ++i) {
  81. bittorrent::packcompact(data + 20 + 6 * i,
  82. "192.168.0." + util::uitos(i + 1), 6990 + i);
  83. }
  84. return 20 + 6 * numPeers;
  85. }
  86. } // namespace
  87. void UDPTrackerClientTest::testCreateUDPTrackerConnect()
  88. {
  89. unsigned char data[16];
  90. std::string remoteAddr;
  91. uint16_t remotePort = 0;
  92. std::shared_ptr<UDPTrackerRequest> req(new UDPTrackerRequest());
  93. req->action = UDPT_ACT_CONNECT;
  94. req->remoteAddr = "192.168.0.1";
  95. req->remotePort = 6991;
  96. req->transactionId = 1000000009;
  97. ssize_t rv =
  98. createUDPTrackerConnect(data, sizeof(data), remoteAddr, remotePort, req);
  99. CPPUNIT_ASSERT_EQUAL((ssize_t)16, rv);
  100. CPPUNIT_ASSERT_EQUAL(req->remoteAddr, remoteAddr);
  101. CPPUNIT_ASSERT_EQUAL(req->remotePort, remotePort);
  102. CPPUNIT_ASSERT_EQUAL((int64_t)UDPT_INITIAL_CONNECTION_ID,
  103. (int64_t)bittorrent::getLLIntParam(data, 0));
  104. CPPUNIT_ASSERT_EQUAL((int)req->action, (int)bittorrent::getIntParam(data, 8));
  105. CPPUNIT_ASSERT_EQUAL(req->transactionId, bittorrent::getIntParam(data, 12));
  106. }
  107. void UDPTrackerClientTest::testCreateUDPTrackerAnnounce()
  108. {
  109. unsigned char data[100];
  110. std::string remoteAddr;
  111. uint16_t remotePort = 0;
  112. std::shared_ptr<UDPTrackerRequest> req(
  113. createAnnounce("192.168.0.1", 6991, 1000000009));
  114. ssize_t rv =
  115. createUDPTrackerAnnounce(data, sizeof(data), remoteAddr, remotePort, req);
  116. CPPUNIT_ASSERT_EQUAL((ssize_t)100, rv);
  117. CPPUNIT_ASSERT_EQUAL(req->connectionId, bittorrent::getLLIntParam(data, 0));
  118. CPPUNIT_ASSERT_EQUAL((int)req->action, (int)bittorrent::getIntParam(data, 8));
  119. CPPUNIT_ASSERT_EQUAL(req->transactionId, bittorrent::getIntParam(data, 12));
  120. CPPUNIT_ASSERT_EQUAL(req->infohash, std::string(&data[16], &data[36]));
  121. CPPUNIT_ASSERT_EQUAL(req->peerId, std::string(&data[36], &data[56]));
  122. CPPUNIT_ASSERT_EQUAL(req->downloaded,
  123. (int64_t)bittorrent::getLLIntParam(data, 56));
  124. CPPUNIT_ASSERT_EQUAL(req->left, (int64_t)bittorrent::getLLIntParam(data, 64));
  125. CPPUNIT_ASSERT_EQUAL(req->uploaded,
  126. (int64_t)bittorrent::getLLIntParam(data, 72));
  127. CPPUNIT_ASSERT_EQUAL(req->event, (int32_t)bittorrent::getIntParam(data, 80));
  128. CPPUNIT_ASSERT_EQUAL(req->ip, bittorrent::getIntParam(data, 84));
  129. CPPUNIT_ASSERT_EQUAL(req->key, bittorrent::getIntParam(data, 88));
  130. CPPUNIT_ASSERT_EQUAL(req->numWant,
  131. (int32_t)bittorrent::getIntParam(data, 92));
  132. CPPUNIT_ASSERT_EQUAL(req->port, bittorrent::getShortIntParam(data, 96));
  133. CPPUNIT_ASSERT_EQUAL(req->extensions, bittorrent::getShortIntParam(data, 98));
  134. }
  135. void UDPTrackerClientTest::testConnectFollowedByAnnounce()
  136. {
  137. ssize_t rv;
  138. UDPTrackerClient tr;
  139. unsigned char data[100];
  140. std::string remoteAddr;
  141. uint16_t remotePort;
  142. Timer now;
  143. std::shared_ptr<UDPTrackerRequest> req1(
  144. createAnnounce("192.168.0.1", 6991, 0));
  145. std::shared_ptr<UDPTrackerRequest> req2(
  146. createAnnounce("192.168.0.1", 6991, 0));
  147. req2->infohash = "bittorrent-infohash2";
  148. tr.addRequest(req1);
  149. tr.addRequest(req2);
  150. CPPUNIT_ASSERT_EQUAL((size_t)2, tr.getPendingRequests().size());
  151. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  152. // CONNECT request was inserted
  153. CPPUNIT_ASSERT_EQUAL((size_t)3, tr.getPendingRequests().size());
  154. CPPUNIT_ASSERT_EQUAL((ssize_t)16, rv);
  155. CPPUNIT_ASSERT_EQUAL(req1->remoteAddr, remoteAddr);
  156. CPPUNIT_ASSERT_EQUAL(req1->remotePort, remotePort);
  157. CPPUNIT_ASSERT_EQUAL((int64_t)UDPT_INITIAL_CONNECTION_ID,
  158. (int64_t)bittorrent::getLLIntParam(data, 0));
  159. uint32_t transactionId = bittorrent::getIntParam(data, 12);
  160. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  161. // Duplicate CONNECT request was not inserted
  162. CPPUNIT_ASSERT_EQUAL((size_t)3, tr.getPendingRequests().size());
  163. CPPUNIT_ASSERT_EQUAL((ssize_t)16, rv);
  164. tr.requestSent(now);
  165. // CONNECT request was moved to inflight
  166. CPPUNIT_ASSERT_EQUAL((size_t)2, tr.getPendingRequests().size());
  167. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  168. // Now all pending requests were moved to connect
  169. CPPUNIT_ASSERT_EQUAL((ssize_t)-1, rv);
  170. CPPUNIT_ASSERT(tr.getPendingRequests().empty());
  171. uint64_t connectionId = 12345;
  172. rv = createConnectReply(data, sizeof(data), connectionId, transactionId);
  173. rv = tr.receiveReply(data, rv, req1->remoteAddr, req1->remotePort, now);
  174. CPPUNIT_ASSERT_EQUAL(0, (int)rv);
  175. // Now 2 requests get back to pending
  176. CPPUNIT_ASSERT_EQUAL((size_t)2, tr.getPendingRequests().size());
  177. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  178. // Creates announce for req1
  179. CPPUNIT_ASSERT_EQUAL((ssize_t)100, rv);
  180. CPPUNIT_ASSERT_EQUAL((size_t)2, tr.getPendingRequests().size());
  181. CPPUNIT_ASSERT_EQUAL(connectionId, bittorrent::getLLIntParam(data, 0));
  182. CPPUNIT_ASSERT_EQUAL((int)UDPT_ACT_ANNOUNCE,
  183. (int)bittorrent::getIntParam(data, 8));
  184. CPPUNIT_ASSERT_EQUAL(req1->infohash, std::string(&data[16], &data[36]));
  185. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  186. // Don't duplicate same request data
  187. CPPUNIT_ASSERT_EQUAL((ssize_t)100, rv);
  188. CPPUNIT_ASSERT_EQUAL((size_t)2, tr.getPendingRequests().size());
  189. uint32_t transactionId1 = bittorrent::getIntParam(data, 12);
  190. tr.requestSent(now);
  191. CPPUNIT_ASSERT_EQUAL((size_t)1, tr.getPendingRequests().size());
  192. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  193. uint32_t transactionId2 = bittorrent::getIntParam(data, 12);
  194. // Creates announce for req2
  195. CPPUNIT_ASSERT_EQUAL((ssize_t)100, rv);
  196. CPPUNIT_ASSERT_EQUAL((size_t)1, tr.getPendingRequests().size());
  197. CPPUNIT_ASSERT_EQUAL(connectionId, bittorrent::getLLIntParam(data, 0));
  198. CPPUNIT_ASSERT_EQUAL((int)UDPT_ACT_ANNOUNCE,
  199. (int)bittorrent::getIntParam(data, 8));
  200. CPPUNIT_ASSERT_EQUAL(req2->infohash, std::string(&data[16], &data[36]));
  201. tr.requestSent(now);
  202. // Now all requests are inflight
  203. CPPUNIT_ASSERT_EQUAL((size_t)0, tr.getPendingRequests().size());
  204. // Reply for req2
  205. rv = createAnnounceReply(data, sizeof(data), transactionId2);
  206. rv = tr.receiveReply(data, rv, req2->remoteAddr, req2->remotePort, now);
  207. CPPUNIT_ASSERT_EQUAL(0, (int)rv);
  208. CPPUNIT_ASSERT_EQUAL((int)UDPT_STA_COMPLETE, req2->state);
  209. CPPUNIT_ASSERT_EQUAL((int)UDPT_ERR_SUCCESS, req2->error);
  210. // Reply for req1
  211. rv = createAnnounceReply(data, sizeof(data), transactionId1, 2);
  212. rv = tr.receiveReply(data, rv, req1->remoteAddr, req1->remotePort, now);
  213. CPPUNIT_ASSERT_EQUAL(0, (int)rv);
  214. CPPUNIT_ASSERT_EQUAL((int)UDPT_STA_COMPLETE, req1->state);
  215. CPPUNIT_ASSERT_EQUAL((int)UDPT_ERR_SUCCESS, req1->error);
  216. CPPUNIT_ASSERT_EQUAL((size_t)2, req1->reply->peers.size());
  217. for (int i = 0; i < 2; ++i) {
  218. CPPUNIT_ASSERT_EQUAL("192.168.0." + util::uitos(i + 1),
  219. req1->reply->peers[i].first);
  220. CPPUNIT_ASSERT_EQUAL((uint16_t)(6990 + i), req1->reply->peers[i].second);
  221. }
  222. // Since we have connection ID, next announce request can be sent
  223. // immediately
  224. std::shared_ptr<UDPTrackerRequest> req3(
  225. createAnnounce("192.168.0.1", 6991, 0));
  226. req3->infohash = "bittorrent-infohash3";
  227. tr.addRequest(req3);
  228. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  229. CPPUNIT_ASSERT_EQUAL((ssize_t)100, rv);
  230. CPPUNIT_ASSERT_EQUAL(req3->infohash, std::string(&data[16], &data[36]));
  231. tr.requestSent(now);
  232. std::shared_ptr<UDPTrackerRequest> req4(
  233. createAnnounce("192.168.0.1", 6991, 0));
  234. req4->infohash = "bittorrent-infohash4";
  235. tr.addRequest(req4);
  236. Timer future = now;
  237. future.advance(1_h);
  238. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, future);
  239. // connection ID is stale because of the timeout
  240. CPPUNIT_ASSERT_EQUAL((ssize_t)16, rv);
  241. CPPUNIT_ASSERT_EQUAL((int64_t)UDPT_INITIAL_CONNECTION_ID,
  242. (int64_t)bittorrent::getLLIntParam(data, 0));
  243. }
  244. void UDPTrackerClientTest::testRequestFailure()
  245. {
  246. ssize_t rv;
  247. UDPTrackerClient tr;
  248. unsigned char data[100];
  249. std::string remoteAddr;
  250. uint16_t remotePort;
  251. Timer now;
  252. {
  253. std::shared_ptr<UDPTrackerRequest> req1(
  254. createAnnounce("192.168.0.1", 6991, 0));
  255. std::shared_ptr<UDPTrackerRequest> req2(
  256. createAnnounce("192.168.0.1", 6991, 0));
  257. tr.addRequest(req1);
  258. tr.addRequest(req2);
  259. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  260. CPPUNIT_ASSERT_EQUAL((int)UDPT_ACT_CONNECT,
  261. (int)bittorrent::getIntParam(data, 8));
  262. tr.requestFail(UDPT_ERR_NETWORK);
  263. CPPUNIT_ASSERT_EQUAL((int)UDPT_STA_COMPLETE, req1->state);
  264. CPPUNIT_ASSERT_EQUAL((int)UDPT_ERR_NETWORK, req1->error);
  265. CPPUNIT_ASSERT_EQUAL((int)UDPT_STA_COMPLETE, req2->state);
  266. CPPUNIT_ASSERT_EQUAL((int)UDPT_ERR_NETWORK, req2->error);
  267. CPPUNIT_ASSERT(tr.getConnectRequests().empty());
  268. CPPUNIT_ASSERT(tr.getPendingRequests().empty());
  269. CPPUNIT_ASSERT(tr.getInflightRequests().empty());
  270. }
  271. {
  272. std::shared_ptr<UDPTrackerRequest> req1(
  273. createAnnounce("192.168.0.1", 6991, 0));
  274. std::shared_ptr<UDPTrackerRequest> req2(
  275. createAnnounce("192.168.0.1", 6991, 0));
  276. tr.addRequest(req1);
  277. tr.addRequest(req2);
  278. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  279. CPPUNIT_ASSERT_EQUAL((int)UDPT_ACT_CONNECT,
  280. (int)bittorrent::getIntParam(data, 8));
  281. uint32_t transactionId = bittorrent::getIntParam(data, 12);
  282. tr.requestSent(now);
  283. rv = createErrorReply(data, sizeof(data), transactionId, "error");
  284. rv = tr.receiveReply(data, rv, req1->remoteAddr, req1->remotePort, now);
  285. CPPUNIT_ASSERT_EQUAL((int)UDPT_STA_COMPLETE, req1->state);
  286. CPPUNIT_ASSERT_EQUAL((int)UDPT_ERR_TRACKER, req1->error);
  287. CPPUNIT_ASSERT_EQUAL((int)UDPT_STA_COMPLETE, req2->state);
  288. CPPUNIT_ASSERT_EQUAL((int)UDPT_ERR_TRACKER, req2->error);
  289. CPPUNIT_ASSERT(tr.getConnectRequests().empty());
  290. CPPUNIT_ASSERT(tr.getPendingRequests().empty());
  291. CPPUNIT_ASSERT(tr.getInflightRequests().empty());
  292. }
  293. {
  294. std::shared_ptr<UDPTrackerRequest> req1(
  295. createAnnounce("192.168.0.1", 6991, 0));
  296. tr.addRequest(req1);
  297. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  298. CPPUNIT_ASSERT_EQUAL((ssize_t)16, rv);
  299. CPPUNIT_ASSERT_EQUAL((int)UDPT_ACT_CONNECT,
  300. (int)bittorrent::getIntParam(data, 8));
  301. uint32_t transactionId = bittorrent::getIntParam(data, 12);
  302. tr.requestSent(now);
  303. uint64_t connectionId = 12345;
  304. rv = createConnectReply(data, sizeof(data), connectionId, transactionId);
  305. rv = tr.receiveReply(data, rv, req1->remoteAddr, req1->remotePort, now);
  306. CPPUNIT_ASSERT_EQUAL(0, (int)rv);
  307. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  308. CPPUNIT_ASSERT_EQUAL((int)UDPT_ACT_ANNOUNCE,
  309. (int)bittorrent::getIntParam(data, 8));
  310. transactionId = bittorrent::getIntParam(data, 12);
  311. tr.requestSent(now);
  312. rv = createErrorReply(data, sizeof(data), transactionId, "announce error");
  313. rv = tr.receiveReply(data, rv, req1->remoteAddr, req1->remotePort, now);
  314. CPPUNIT_ASSERT_EQUAL((int)UDPT_STA_COMPLETE, req1->state);
  315. CPPUNIT_ASSERT_EQUAL((int)UDPT_ERR_TRACKER, req1->error);
  316. CPPUNIT_ASSERT(tr.getConnectRequests().empty());
  317. CPPUNIT_ASSERT(tr.getPendingRequests().empty());
  318. CPPUNIT_ASSERT(tr.getInflightRequests().empty());
  319. }
  320. }
  321. void UDPTrackerClientTest::testTimeout()
  322. {
  323. ssize_t rv;
  324. unsigned char data[100];
  325. std::string remoteAddr;
  326. uint16_t remotePort;
  327. Timer now;
  328. UDPTrackerClient tr;
  329. {
  330. std::shared_ptr<UDPTrackerRequest> req1(
  331. createAnnounce("192.168.0.1", 6991, 0));
  332. std::shared_ptr<UDPTrackerRequest> req2(
  333. createAnnounce("192.168.0.1", 6991, 0));
  334. tr.addRequest(req1);
  335. tr.addRequest(req2);
  336. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  337. CPPUNIT_ASSERT_EQUAL((int)UDPT_ACT_CONNECT,
  338. (int)bittorrent::getIntParam(data, 8));
  339. tr.requestSent(now);
  340. now.advance(20_s);
  341. // 15 seconds 1st stage timeout passed
  342. tr.handleTimeout(now);
  343. CPPUNIT_ASSERT(tr.getConnectRequests().empty());
  344. CPPUNIT_ASSERT_EQUAL((size_t)3, tr.getPendingRequests().size());
  345. CPPUNIT_ASSERT(tr.getInflightRequests().empty());
  346. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  347. // CONNECT request was inserted
  348. CPPUNIT_ASSERT_EQUAL((int)UDPT_ACT_CONNECT,
  349. (int)bittorrent::getIntParam(data, 8));
  350. tr.requestSent(now);
  351. now.advance(65_s);
  352. // 60 seconds 2nd stage timeout passed
  353. tr.handleTimeout(now);
  354. CPPUNIT_ASSERT(tr.getConnectRequests().empty());
  355. CPPUNIT_ASSERT(tr.getPendingRequests().empty());
  356. CPPUNIT_ASSERT(tr.getInflightRequests().empty());
  357. CPPUNIT_ASSERT_EQUAL((int)UDPT_STA_COMPLETE, req1->state);
  358. CPPUNIT_ASSERT_EQUAL((int)UDPT_ERR_TIMEOUT, req1->error);
  359. CPPUNIT_ASSERT_EQUAL((int)UDPT_STA_COMPLETE, req2->state);
  360. CPPUNIT_ASSERT_EQUAL((int)UDPT_ERR_TIMEOUT, req2->error);
  361. }
  362. {
  363. std::shared_ptr<UDPTrackerRequest> req1(
  364. createAnnounce("192.168.0.1", 6991, 0));
  365. tr.addRequest(req1);
  366. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  367. CPPUNIT_ASSERT_EQUAL((ssize_t)16, rv);
  368. CPPUNIT_ASSERT_EQUAL((int)UDPT_ACT_CONNECT,
  369. (int)bittorrent::getIntParam(data, 8));
  370. uint32_t transactionId = bittorrent::getIntParam(data, 12);
  371. tr.requestSent(now);
  372. uint64_t connectionId = 12345;
  373. rv = createConnectReply(data, sizeof(data), connectionId, transactionId);
  374. rv = tr.receiveReply(data, rv, req1->remoteAddr, req1->remotePort, now);
  375. CPPUNIT_ASSERT_EQUAL(0, (int)rv);
  376. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  377. CPPUNIT_ASSERT_EQUAL((int)UDPT_ACT_ANNOUNCE,
  378. (int)bittorrent::getIntParam(data, 8));
  379. tr.requestSent(now);
  380. now.advance(20_s);
  381. // 15 seconds 1st stage timeout passed
  382. tr.handleTimeout(now);
  383. CPPUNIT_ASSERT(tr.getConnectRequests().empty());
  384. CPPUNIT_ASSERT_EQUAL((size_t)1, tr.getPendingRequests().size());
  385. CPPUNIT_ASSERT(tr.getInflightRequests().empty());
  386. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  387. CPPUNIT_ASSERT_EQUAL((int)UDPT_ACT_ANNOUNCE,
  388. (int)bittorrent::getIntParam(data, 8));
  389. tr.requestSent(now);
  390. now.advance(65_s);
  391. // 60 seconds 2nd stage timeout passed
  392. tr.handleTimeout(now);
  393. CPPUNIT_ASSERT(tr.getConnectRequests().empty());
  394. CPPUNIT_ASSERT(tr.getPendingRequests().empty());
  395. CPPUNIT_ASSERT(tr.getInflightRequests().empty());
  396. CPPUNIT_ASSERT_EQUAL((int)UDPT_STA_COMPLETE, req1->state);
  397. CPPUNIT_ASSERT_EQUAL((int)UDPT_ERR_TIMEOUT, req1->error);
  398. }
  399. }
  400. } // namespace aria2