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