From c6732a03cbf0efa815e8a857af8118878c053af0 Mon Sep 17 00:00:00 2001 From: Dirk Engling Date: Thu, 5 Nov 2026 18:18:45 +0100 Subject: Answer blacklisted torrent announces with an empty packet, that carries a re-announce timeout --- tests/integration/test_accesslist.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'tests/integration/test_accesslist.py') diff --git a/tests/integration/test_accesslist.py b/tests/integration/test_accesslist.py index 1c84ccf..7d01264 100644 --- a/tests/integration/test_accesslist.py +++ b/tests/integration/test_accesslist.py @@ -38,10 +38,11 @@ class Blacklist(TrackerTestCase): self.assertNotIn(b"failure reason", answer) self.assertEqual(answer[b"complete"], 1) - def test_the_block_is_an_error_packet_over_udp(self): - """BEP 15 has an error action, which is what a refusal should use. - It used to answer the announce header with no body behind it, a - packet too short for any client to read.""" + def test_the_block_is_an_empty_announce_over_udp(self): + """An empty swarm with a long interval, not an error. BEP 15 binds a + client to the interval and says nothing about what to do with an + error, so an error puts the client on its own retry schedule, which + starts in the tens of seconds.""" sock, connection_id = self.tracker.udp_connect() sock.close() request = struct.pack( @@ -49,10 +50,13 @@ class Blacklist(TrackerTestCase): ) answer = self.tracker.udp_raw(request) self.assertIsNotNone(answer) - action, transaction = struct.unpack(">II", answer[:8]) - self.assertEqual(action, 3, "action 3 is the error packet") + self.assertEqual(len(answer), 20, "header and counts, no peers behind them") + action, transaction, interval, leechers, seeders = struct.unpack(">IIIII", answer) + self.assertEqual(action, 1, "action 1 is the announce packet") self.assertEqual(transaction, 7) - self.assertIn(b"not authorized", answer[8:]) + self.assertEqual((leechers, seeders), (0, 0)) + self.assertGreaterEqual(interval, 60 * 60, "far enough out to be worth the trouble") + self.assertLessEqual(interval, 60 * 60 * 6, "not so far out that a client clamps it") def test_a_blocked_hash_is_not_stored_when_it_arrives_over_udp(self): sock, connection_id = self.tracker.udp_connect() -- cgit v1.3