UDPTrackerClientTest.cc 18 KB

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