UDPTrackerClientTest.cc 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  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. int32_t transactionId)
  30. {
  31. std::shared_ptr<UDPTrackerRequest> req(new UDPTrackerRequest());
  32. req->connectionId = INT64_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, int32_t transactionId,
  53. 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, int32_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. int32_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,
  106. (int32_t)bittorrent::getIntParam(data, 12));
  107. }
  108. void UDPTrackerClientTest::testCreateUDPTrackerAnnounce()
  109. {
  110. unsigned char data[100];
  111. std::string remoteAddr;
  112. uint16_t remotePort = 0;
  113. std::shared_ptr<UDPTrackerRequest> req(
  114. createAnnounce("192.168.0.1", 6991, 1000000009));
  115. ssize_t rv =
  116. createUDPTrackerAnnounce(data, sizeof(data), remoteAddr, remotePort, req);
  117. CPPUNIT_ASSERT_EQUAL((ssize_t)100, rv);
  118. CPPUNIT_ASSERT_EQUAL(req->connectionId,
  119. (int64_t)bittorrent::getLLIntParam(data, 0));
  120. CPPUNIT_ASSERT_EQUAL((int)req->action, (int)bittorrent::getIntParam(data, 8));
  121. CPPUNIT_ASSERT_EQUAL(req->transactionId,
  122. (int32_t)bittorrent::getIntParam(data, 12));
  123. CPPUNIT_ASSERT_EQUAL(req->infohash, std::string(&data[16], &data[36]));
  124. CPPUNIT_ASSERT_EQUAL(req->peerId, std::string(&data[36], &data[56]));
  125. CPPUNIT_ASSERT_EQUAL(req->downloaded,
  126. (int64_t)bittorrent::getLLIntParam(data, 56));
  127. CPPUNIT_ASSERT_EQUAL(req->left, (int64_t)bittorrent::getLLIntParam(data, 64));
  128. CPPUNIT_ASSERT_EQUAL(req->uploaded,
  129. (int64_t)bittorrent::getLLIntParam(data, 72));
  130. CPPUNIT_ASSERT_EQUAL(req->event, (int32_t)bittorrent::getIntParam(data, 80));
  131. CPPUNIT_ASSERT_EQUAL(req->ip, bittorrent::getIntParam(data, 84));
  132. CPPUNIT_ASSERT_EQUAL(req->key, bittorrent::getIntParam(data, 88));
  133. CPPUNIT_ASSERT_EQUAL(req->numWant,
  134. (int32_t)bittorrent::getIntParam(data, 92));
  135. CPPUNIT_ASSERT_EQUAL(req->port, bittorrent::getShortIntParam(data, 96));
  136. CPPUNIT_ASSERT_EQUAL(req->extensions, bittorrent::getShortIntParam(data, 98));
  137. }
  138. void UDPTrackerClientTest::testConnectFollowedByAnnounce()
  139. {
  140. ssize_t rv;
  141. UDPTrackerClient tr;
  142. unsigned char data[100];
  143. std::string remoteAddr;
  144. uint16_t remotePort;
  145. Timer now;
  146. std::shared_ptr<UDPTrackerRequest> req1(
  147. createAnnounce("192.168.0.1", 6991, 0));
  148. std::shared_ptr<UDPTrackerRequest> req2(
  149. createAnnounce("192.168.0.1", 6991, 0));
  150. req2->infohash = "bittorrent-infohash2";
  151. tr.addRequest(req1);
  152. tr.addRequest(req2);
  153. CPPUNIT_ASSERT_EQUAL((size_t)2, tr.getPendingRequests().size());
  154. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  155. // CONNECT request was inserted
  156. CPPUNIT_ASSERT_EQUAL((size_t)3, tr.getPendingRequests().size());
  157. CPPUNIT_ASSERT_EQUAL((ssize_t)16, rv);
  158. CPPUNIT_ASSERT_EQUAL(req1->remoteAddr, remoteAddr);
  159. CPPUNIT_ASSERT_EQUAL(req1->remotePort, remotePort);
  160. CPPUNIT_ASSERT_EQUAL((int64_t)UDPT_INITIAL_CONNECTION_ID,
  161. (int64_t)bittorrent::getLLIntParam(data, 0));
  162. int32_t transactionId = bittorrent::getIntParam(data, 12);
  163. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  164. // Duplicate CONNECT request was not inserted
  165. CPPUNIT_ASSERT_EQUAL((size_t)3, tr.getPendingRequests().size());
  166. CPPUNIT_ASSERT_EQUAL((ssize_t)16, rv);
  167. tr.requestSent(now);
  168. // CONNECT request was moved to inflight
  169. CPPUNIT_ASSERT_EQUAL((size_t)2, tr.getPendingRequests().size());
  170. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  171. // Now all pending requests were moved to connect
  172. CPPUNIT_ASSERT_EQUAL((ssize_t)-1, rv);
  173. CPPUNIT_ASSERT(tr.getPendingRequests().empty());
  174. int64_t connectionId = 12345;
  175. rv = createConnectReply(data, sizeof(data), connectionId, transactionId);
  176. rv = tr.receiveReply(data, rv, req1->remoteAddr, req1->remotePort, now);
  177. CPPUNIT_ASSERT_EQUAL(0, (int)rv);
  178. // Now 2 requests get back to pending
  179. CPPUNIT_ASSERT_EQUAL((size_t)2, tr.getPendingRequests().size());
  180. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  181. // Creates announce for req1
  182. CPPUNIT_ASSERT_EQUAL((ssize_t)100, rv);
  183. CPPUNIT_ASSERT_EQUAL((size_t)2, tr.getPendingRequests().size());
  184. CPPUNIT_ASSERT_EQUAL(connectionId,
  185. (int64_t)bittorrent::getLLIntParam(data, 0));
  186. CPPUNIT_ASSERT_EQUAL((int)UDPT_ACT_ANNOUNCE,
  187. (int)bittorrent::getIntParam(data, 8));
  188. CPPUNIT_ASSERT_EQUAL(req1->infohash, std::string(&data[16], &data[36]));
  189. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  190. // Don't duplicate same request data
  191. CPPUNIT_ASSERT_EQUAL((ssize_t)100, rv);
  192. CPPUNIT_ASSERT_EQUAL((size_t)2, tr.getPendingRequests().size());
  193. int32_t transactionId1 = bittorrent::getIntParam(data, 12);
  194. tr.requestSent(now);
  195. CPPUNIT_ASSERT_EQUAL((size_t)1, tr.getPendingRequests().size());
  196. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  197. int32_t transactionId2 = bittorrent::getIntParam(data, 12);
  198. // Creates announce for req2
  199. CPPUNIT_ASSERT_EQUAL((ssize_t)100, rv);
  200. CPPUNIT_ASSERT_EQUAL((size_t)1, tr.getPendingRequests().size());
  201. CPPUNIT_ASSERT_EQUAL(connectionId,
  202. (int64_t)bittorrent::getLLIntParam(data, 0));
  203. CPPUNIT_ASSERT_EQUAL((int)UDPT_ACT_ANNOUNCE,
  204. (int)bittorrent::getIntParam(data, 8));
  205. CPPUNIT_ASSERT_EQUAL(req2->infohash, std::string(&data[16], &data[36]));
  206. tr.requestSent(now);
  207. // Now all requests are inflight
  208. CPPUNIT_ASSERT_EQUAL((size_t)0, tr.getPendingRequests().size());
  209. // Reply for req2
  210. rv = createAnnounceReply(data, sizeof(data), transactionId2);
  211. rv = tr.receiveReply(data, rv, req2->remoteAddr, req2->remotePort, now);
  212. CPPUNIT_ASSERT_EQUAL(0, (int)rv);
  213. CPPUNIT_ASSERT_EQUAL((int)UDPT_STA_COMPLETE, req2->state);
  214. CPPUNIT_ASSERT_EQUAL((int)UDPT_ERR_SUCCESS, req2->error);
  215. // Reply for req1
  216. rv = createAnnounceReply(data, sizeof(data), transactionId1, 2);
  217. rv = tr.receiveReply(data, rv, req1->remoteAddr, req1->remotePort, now);
  218. CPPUNIT_ASSERT_EQUAL(0, (int)rv);
  219. CPPUNIT_ASSERT_EQUAL((int)UDPT_STA_COMPLETE, req1->state);
  220. CPPUNIT_ASSERT_EQUAL((int)UDPT_ERR_SUCCESS, req1->error);
  221. CPPUNIT_ASSERT_EQUAL((size_t)2, req1->reply->peers.size());
  222. for (int i = 0; i < 2; ++i) {
  223. CPPUNIT_ASSERT_EQUAL("192.168.0." + util::uitos(i + 1),
  224. req1->reply->peers[i].first);
  225. CPPUNIT_ASSERT_EQUAL((uint16_t)(6990 + i), req1->reply->peers[i].second);
  226. }
  227. // Since we have connection ID, next announce request can be sent
  228. // immediately
  229. std::shared_ptr<UDPTrackerRequest> req3(
  230. createAnnounce("192.168.0.1", 6991, 0));
  231. req3->infohash = "bittorrent-infohash3";
  232. tr.addRequest(req3);
  233. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  234. CPPUNIT_ASSERT_EQUAL((ssize_t)100, rv);
  235. CPPUNIT_ASSERT_EQUAL(req3->infohash, std::string(&data[16], &data[36]));
  236. tr.requestSent(now);
  237. std::shared_ptr<UDPTrackerRequest> req4(
  238. createAnnounce("192.168.0.1", 6991, 0));
  239. req4->infohash = "bittorrent-infohash4";
  240. tr.addRequest(req4);
  241. Timer future = now;
  242. future.advance(1_h);
  243. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, future);
  244. // connection ID is stale because of the timeout
  245. CPPUNIT_ASSERT_EQUAL((ssize_t)16, rv);
  246. CPPUNIT_ASSERT_EQUAL((int64_t)UDPT_INITIAL_CONNECTION_ID,
  247. (int64_t)bittorrent::getLLIntParam(data, 0));
  248. }
  249. void UDPTrackerClientTest::testRequestFailure()
  250. {
  251. ssize_t rv;
  252. UDPTrackerClient tr;
  253. unsigned char data[100];
  254. std::string remoteAddr;
  255. uint16_t remotePort;
  256. Timer now;
  257. {
  258. std::shared_ptr<UDPTrackerRequest> req1(
  259. createAnnounce("192.168.0.1", 6991, 0));
  260. std::shared_ptr<UDPTrackerRequest> req2(
  261. createAnnounce("192.168.0.1", 6991, 0));
  262. tr.addRequest(req1);
  263. tr.addRequest(req2);
  264. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  265. CPPUNIT_ASSERT_EQUAL((int)UDPT_ACT_CONNECT,
  266. (int)bittorrent::getIntParam(data, 8));
  267. tr.requestFail(UDPT_ERR_NETWORK);
  268. CPPUNIT_ASSERT_EQUAL((int)UDPT_STA_COMPLETE, req1->state);
  269. CPPUNIT_ASSERT_EQUAL((int)UDPT_ERR_NETWORK, req1->error);
  270. CPPUNIT_ASSERT_EQUAL((int)UDPT_STA_COMPLETE, req2->state);
  271. CPPUNIT_ASSERT_EQUAL((int)UDPT_ERR_NETWORK, req2->error);
  272. CPPUNIT_ASSERT(tr.getConnectRequests().empty());
  273. CPPUNIT_ASSERT(tr.getPendingRequests().empty());
  274. CPPUNIT_ASSERT(tr.getInflightRequests().empty());
  275. }
  276. {
  277. std::shared_ptr<UDPTrackerRequest> req1(
  278. createAnnounce("192.168.0.1", 6991, 0));
  279. std::shared_ptr<UDPTrackerRequest> req2(
  280. createAnnounce("192.168.0.1", 6991, 0));
  281. tr.addRequest(req1);
  282. tr.addRequest(req2);
  283. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  284. CPPUNIT_ASSERT_EQUAL((int)UDPT_ACT_CONNECT,
  285. (int)bittorrent::getIntParam(data, 8));
  286. int32_t transactionId = bittorrent::getIntParam(data, 12);
  287. tr.requestSent(now);
  288. rv = createErrorReply(data, sizeof(data), transactionId, "error");
  289. rv = tr.receiveReply(data, rv, req1->remoteAddr, req1->remotePort, now);
  290. CPPUNIT_ASSERT_EQUAL((int)UDPT_STA_COMPLETE, req1->state);
  291. CPPUNIT_ASSERT_EQUAL((int)UDPT_ERR_TRACKER, req1->error);
  292. CPPUNIT_ASSERT_EQUAL((int)UDPT_STA_COMPLETE, req2->state);
  293. CPPUNIT_ASSERT_EQUAL((int)UDPT_ERR_TRACKER, req2->error);
  294. CPPUNIT_ASSERT(tr.getConnectRequests().empty());
  295. CPPUNIT_ASSERT(tr.getPendingRequests().empty());
  296. CPPUNIT_ASSERT(tr.getInflightRequests().empty());
  297. }
  298. {
  299. std::shared_ptr<UDPTrackerRequest> req1(
  300. createAnnounce("192.168.0.1", 6991, 0));
  301. tr.addRequest(req1);
  302. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  303. CPPUNIT_ASSERT_EQUAL((ssize_t)16, rv);
  304. CPPUNIT_ASSERT_EQUAL((int)UDPT_ACT_CONNECT,
  305. (int)bittorrent::getIntParam(data, 8));
  306. int32_t transactionId = bittorrent::getIntParam(data, 12);
  307. tr.requestSent(now);
  308. int64_t connectionId = 12345;
  309. rv = createConnectReply(data, sizeof(data), connectionId, transactionId);
  310. rv = tr.receiveReply(data, rv, req1->remoteAddr, req1->remotePort, now);
  311. CPPUNIT_ASSERT_EQUAL(0, (int)rv);
  312. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  313. CPPUNIT_ASSERT_EQUAL((int)UDPT_ACT_ANNOUNCE,
  314. (int)bittorrent::getIntParam(data, 8));
  315. transactionId = bittorrent::getIntParam(data, 12);
  316. tr.requestSent(now);
  317. rv = createErrorReply(data, sizeof(data), transactionId, "announce error");
  318. rv = tr.receiveReply(data, rv, req1->remoteAddr, req1->remotePort, now);
  319. CPPUNIT_ASSERT_EQUAL((int)UDPT_STA_COMPLETE, req1->state);
  320. CPPUNIT_ASSERT_EQUAL((int)UDPT_ERR_TRACKER, req1->error);
  321. CPPUNIT_ASSERT(tr.getConnectRequests().empty());
  322. CPPUNIT_ASSERT(tr.getPendingRequests().empty());
  323. CPPUNIT_ASSERT(tr.getInflightRequests().empty());
  324. }
  325. }
  326. void UDPTrackerClientTest::testTimeout()
  327. {
  328. ssize_t rv;
  329. unsigned char data[100];
  330. std::string remoteAddr;
  331. uint16_t remotePort;
  332. Timer now;
  333. UDPTrackerClient tr;
  334. {
  335. std::shared_ptr<UDPTrackerRequest> req1(
  336. createAnnounce("192.168.0.1", 6991, 0));
  337. std::shared_ptr<UDPTrackerRequest> req2(
  338. createAnnounce("192.168.0.1", 6991, 0));
  339. tr.addRequest(req1);
  340. tr.addRequest(req2);
  341. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  342. CPPUNIT_ASSERT_EQUAL((int)UDPT_ACT_CONNECT,
  343. (int)bittorrent::getIntParam(data, 8));
  344. tr.requestSent(now);
  345. now.advance(20_s);
  346. // 15 seconds 1st stage timeout passed
  347. tr.handleTimeout(now);
  348. CPPUNIT_ASSERT(tr.getConnectRequests().empty());
  349. CPPUNIT_ASSERT_EQUAL((size_t)3, tr.getPendingRequests().size());
  350. CPPUNIT_ASSERT(tr.getInflightRequests().empty());
  351. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  352. // CONNECT request was inserted
  353. CPPUNIT_ASSERT_EQUAL((int)UDPT_ACT_CONNECT,
  354. (int)bittorrent::getIntParam(data, 8));
  355. tr.requestSent(now);
  356. now.advance(65_s);
  357. // 60 seconds 2nd stage timeout passed
  358. tr.handleTimeout(now);
  359. CPPUNIT_ASSERT(tr.getConnectRequests().empty());
  360. CPPUNIT_ASSERT(tr.getPendingRequests().empty());
  361. CPPUNIT_ASSERT(tr.getInflightRequests().empty());
  362. CPPUNIT_ASSERT_EQUAL((int)UDPT_STA_COMPLETE, req1->state);
  363. CPPUNIT_ASSERT_EQUAL((int)UDPT_ERR_TIMEOUT, req1->error);
  364. CPPUNIT_ASSERT_EQUAL((int)UDPT_STA_COMPLETE, req2->state);
  365. CPPUNIT_ASSERT_EQUAL((int)UDPT_ERR_TIMEOUT, req2->error);
  366. }
  367. {
  368. std::shared_ptr<UDPTrackerRequest> req1(
  369. createAnnounce("192.168.0.1", 6991, 0));
  370. tr.addRequest(req1);
  371. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  372. CPPUNIT_ASSERT_EQUAL((ssize_t)16, rv);
  373. CPPUNIT_ASSERT_EQUAL((int)UDPT_ACT_CONNECT,
  374. (int)bittorrent::getIntParam(data, 8));
  375. int32_t transactionId = bittorrent::getIntParam(data, 12);
  376. tr.requestSent(now);
  377. int64_t connectionId = 12345;
  378. rv = createConnectReply(data, sizeof(data), connectionId, transactionId);
  379. rv = tr.receiveReply(data, rv, req1->remoteAddr, req1->remotePort, now);
  380. CPPUNIT_ASSERT_EQUAL(0, (int)rv);
  381. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  382. CPPUNIT_ASSERT_EQUAL((int)UDPT_ACT_ANNOUNCE,
  383. (int)bittorrent::getIntParam(data, 8));
  384. tr.requestSent(now);
  385. now.advance(20_s);
  386. // 15 seconds 1st stage timeout passed
  387. tr.handleTimeout(now);
  388. CPPUNIT_ASSERT(tr.getConnectRequests().empty());
  389. CPPUNIT_ASSERT_EQUAL((size_t)1, tr.getPendingRequests().size());
  390. CPPUNIT_ASSERT(tr.getInflightRequests().empty());
  391. rv = tr.createRequest(data, sizeof(data), remoteAddr, remotePort, now);
  392. CPPUNIT_ASSERT_EQUAL((int)UDPT_ACT_ANNOUNCE,
  393. (int)bittorrent::getIntParam(data, 8));
  394. tr.requestSent(now);
  395. now.advance(65_s);
  396. // 60 seconds 2nd stage timeout passed
  397. tr.handleTimeout(now);
  398. CPPUNIT_ASSERT(tr.getConnectRequests().empty());
  399. CPPUNIT_ASSERT(tr.getPendingRequests().empty());
  400. CPPUNIT_ASSERT(tr.getInflightRequests().empty());
  401. CPPUNIT_ASSERT_EQUAL((int)UDPT_STA_COMPLETE, req1->state);
  402. CPPUNIT_ASSERT_EQUAL((int)UDPT_ERR_TIMEOUT, req1->error);
  403. }
  404. }
  405. } // namespace aria2