torrust_tracker/servers/udp/
mod.rs

1//! UDP Tracker.
2//!
3//! This module contains the UDP tracker implementation.
4//!
5//! The UDP tracker is a simple UDP server that responds to these requests:
6//!
7//! - `Connect`: used to get a connection ID which must be provided on each
8//!   request in order to avoid spoofing the source address of the UDP packets.
9//! - `Announce`: used to announce the presence of a peer to the tracker.
10//! - `Scrape`: used to get information about a torrent.
11//!
12//! It was introduced in [BEP 15. UDP Tracker Protocol for `BitTorrent`](https://www.bittorrent.org/beps/bep_0015.html)
13//! as an alternative to the [HTTP tracker](https://www.bittorrent.org/beps/bep_0003.html).
14//! The UDP tracker is more efficient than the HTTP tracker because it uses UDP
15//! instead of TCP.
16//!
17//! Refer to the [`bit_torrent`](crate::shared::bit_torrent) module for more
18//! information about the `BitTorrent` protocol.
19//!
20//! Refer to [BEP 15. UDP Tracker Protocol for `BitTorrent`](https://www.bittorrent.org/beps/bep_0015.html)
21//! and to [BEP 41. UDP Tracker Protocol Extensions](https://www.bittorrent.org/beps/bep_0041.html)
22//! for more information about the UDP tracker protocol.
23//!
24//! > **NOTICE**: [BEP-41](https://www.bittorrent.org/beps/bep_0041.html) is not
25//! > implemented yet.
26//!
27//! > **NOTICE**: we are using the [`aquatic_udp_protocol`](https://crates.io/crates/aquatic_udp_protocol)
28//! > crate so requests and responses are handled by it.
29//!
30//! > **NOTICE**: all values are send in network byte order ([big endian](https://en.wikipedia.org/wiki/Endianness)).
31//!
32//! ## Table of Contents
33//!
34//! - [Actions](#actions)
35//!     - [Connect](#connect)
36//!         - [Connect Request](#connect-request)
37//!         - [Connect Response](#connect-response)
38//!     - [Announce](#announce)
39//!         - [Announce Request](#announce-request)
40//!         - [Announce Response](#announce-response)
41//!     - [Scrape](#scrape)
42//!         - [Scrape Request](#scrape-request)
43//!         - [Scrape Response](#scrape-response)
44//! - [Errors](#errors)
45//! - [Extensions](#extensions)
46//! - [Links](#links)
47//! - [Credits](#credits)
48//!
49//! ## Actions
50//!
51//! Requests are sent to the tracker using UDP packets. The UDP tracker protocol
52//! is designed to be as simple as possible. It uses a single UDP port and
53//! supports only three types of requests: `Connect`, `Announce` and `Scrape`.
54//!
55//! Request are parsed from UDP packets using the [`aquatic_udp_protocol`](https://crates.io/crates/aquatic_udp_protocol)
56//! crate and then handled by the [`Tracker`](crate::core::Tracker) struct.
57//! And then the response is also build using the [`aquatic_udp_protocol`](https://crates.io/crates/aquatic_udp_protocol)
58//! and converted to a UDP packet.
59//!
60//! ```text
61//! UDP packet -> Aquatic Struct Request -> [Torrust Struct Request] ->  Tracker -> Aquatic Struct Response -> UDP packet
62//! ```
63//!
64//! ### Connect
65//!
66//! `Connect` requests are used to get a connection ID which must be provided on
67//! each request in order to avoid spoofing the source address of the UDP.
68//!
69//! The connection ID is a random 64-bit integer that is used to identify the
70//! client. It is used to prevent spoofing of the source address of the UDP
71//! packets. Before announcing or scraping, you have to obtain a connection ID.
72//!
73//! The connection ID is generated by the tracker and sent back to the client's
74//! IP address. Only the client using that IP can receive the response, so the
75//! tracker can be sure that the client is the one who sent the request. If the
76//! client's IP was spoofed the tracker will send the response to the wrong
77//! client and the client will not receive it.
78//!
79//! The reason why the UDP tracker protocol needs a connection ID to avoid IP
80//! spoofing can be explained as follows:
81//!
82//! 1. No connection state: Unlike TCP, UDP is a connectionless protocol,
83//!    meaning that it does not establish a connection between two endpoints before
84//!    exchanging data. As a result, it is more susceptible to IP spoofing, where
85//!    an attacker sends packets with a forged source IP address, tricking the
86//!    receiver into believing that they are coming from a legitimate source.
87//!
88//! 2. Mitigating IP spoofing: To mitigate IP spoofing in the UDP tracker
89//!    protocol, a connection ID is used. When a client wants to interact with a
90//!    tracker, it sends a "connect" request to the tracker, which, in turn,
91//!    responds with a unique connection ID. This connection ID must be included in
92//!    all subsequent requests from the client to the tracker.
93//!
94//! 3. Validating requests: By requiring the connection ID, the tracker can
95//!    verify that the requests are coming from the same client that initially sent
96//!    the "connect" request. If an attacker attempts to spoof the client's IP
97//!    address, they would also need to know the valid connection ID to be accepted
98//!    by the tracker. This makes it significantly more challenging for an attacker
99//!    to spoof IP addresses and disrupt the P2P network.
100//!
101//! There are different ways to generate a connection ID. The most common way is
102//! to generate a time bound secret. The secret is generated using a time based
103//! algorithm and it is valid for a certain amount of time.
104//!
105//! ```text
106//! connection ID = hash(client IP + current time slot + secret seed)
107//! ```
108//!
109//! The BEP-15 recommends a two-minute time slot. Refer to [`connection_cookie`]
110//! for more information about the connection ID generation with this method.
111//!
112//! #### Connect Request
113//!
114//! **Connect request (UDP packet)**
115//!
116//! Offset | Type/Size         | Name             | Description                                     | Hex                         | Decimal
117//! -------|-------------------|------------------|-------------------------------------------------|-----------------------------|-----------------
118//! 0      | [`i64`](std::i64) | `protocol_id`    | Magic constant that will identify the protocol. | `0x00_00_04_17_27_10_19_80` | `4497486125440`
119//! 8      | [`i32`](std::i32) | `action`         | Action identifying the connect request.         | `0x00_00_00_00`             | `0`
120//! 12     | [`i32`](std::i32) | `transaction_id` | Randomly generated by the client.               | `0x34_FA_A1_F9`             | `-888840697`
121//!
122//! **Sample connect request (UDP packet)**
123//!
124//! UDP packet bytes:
125//!
126//! ```text
127//! Offset:  [   0,    1,    2,    3,    4,    5,    6,    7,    8,    9,   10,   11,   12,   13,   14,   15]
128//! Decimal: [   0,    0,    4,   23,   39,   16,   25,  128,    0,    0,    0,    0,  203,    5,   94,    7]
129//! Hex:     [0x00, 0x00, 0x04, 0x17, 0x27, 0x10, 0x19, 0x80, 0x00, 0x00, 0x00, 0x00, 0xCB, 0x05, 0x5E, 0x07]
130//! Param:   [<------------- protocol_id ------------------>,<------- action ------>,<--- transaction_id -->]
131//! ```
132//!
133//! UDP packet fields:
134//!
135//! Offset | Type/Size         | Name             | Bytes Dec (Big Endian)         | Hex                         | Decimal
136//! -------|-------------------|------------------|--------------------------------|-----------------------------|----------------
137//! 0      | [`i64`](std::i64) | `protocol_id`    | [0, 0, 4, 23, 39, 16, 25, 128] | `0x00_00_04_17_27_10_19_80` | `4497486125440`
138//! 4      | [`i32`](std::i32) | `action`         | [0, 0, 0, 0]                   | `0x00_00_00_00`             | `0`
139//! 8      | [`i32`](std::i32) | `transaction_id` | [35, 63, 226, 1]               | `0xCB_05_5E_07`             | `-888840697`
140//!
141//! **Connect request (parsed struct)**
142//!
143//! After parsing the UDP packet, the [`ConnectRequest`](aquatic_udp_protocol::request::ConnectRequest)
144//! request struct will look like this:
145//!
146//! Field            | Type                                                           | Example
147//! -----------------|----------------------------------------------------------------|-------------
148//! `transaction_id` | [`TransactionId`](aquatic_udp_protocol::common::TransactionId) | `1950635409`
149//!
150//! #### Connect Response
151//!
152//! **Connect response (UDP packet)**
153//!
154//! Offset | Type/Size         | Name             | Description                                           | Hex                         | Decimal
155//! -------|-------------------|------------------|-------------------------------------------------------|-----------------------------|-----------------------
156//! 0      | [`i64`](std::i32) | `action`         | Action identifying the connect request                | `0x00_00_00_00`             | `0`
157//! 4      | [`i32`](std::i32) | `transaction_id` | Must match the `transaction_id` sent from the client. | `0xCB_05_5E_07`             | `-888840697`
158//! 8      | [`i32`](std::i64) | `connection_id`  | Generated by the tracker to authenticate the client.  | `0xC5_58_7C_09_08_48_D8_37` | `-4226491872051668937`
159//!
160//! > **NOTICE**: the `connection_id` is used when further information is
161//! > exchanged with the tracker, to identify the client. This `connection_id` can
162//! > be reused for multiple requests, but if it's cached for too long, it will
163//! > not be valid anymore.
164//!
165//! > **NOTICE**: `Hex` column is a signed 2's complement.
166//!
167//! **Sample connect response (UDP packet)**
168//!
169//! UDP packet bytes:
170//!
171//! ```text
172//! Offset:  [   0,    1,    2,    3,    4,    5,    6,    7,    8,    9,   10,   11,   12,   13,   14,    15]
173//! Decimal: [   0,    0,    0,    0,  203,    5,   94,    7,  197,   88,  124,    9,    8,   72,  216,   55]
174//! Hex:     [0x00, 0x00, 0x00, 0x00, 0xCB, 0x05, 0x5E, 0x07, 0xC5, 0x58, 0x7C, 0x09, 0x08, 0x48, 0xD8, 0x37]
175//! Param:   [<------ action ------>,<-- transaction_id --->,<--------------- connection_id --------------->]
176//! ```
177//!
178//! UDP packet fields:
179//!
180//! Offset | Type/Size         | Name             | Bytes (Big Endian)                | Hex                          | Decimal
181//! -------|-------------------|------------------|-----------------------------------|------------------------------|-----------------------
182//! 0      | [`i64`](std::i32) | `action`         | [0, 0, 0, 0]                      | `0x00_00_00_00`              | `0`
183//! 4      | [`i64`](std::i32) | `transaction_id` | [203, 5, 94, 7]                   | `0xCB_05_5E_07`              | `-888840697`
184//! 8      | [`i64`](std::i64) | `connection_id`  | [197, 88, 124, 9, 8, 72, 216, 55] | `0xC5_58_7C_09_08_48_D8_37`  | `-4226491872051668937`
185//!
186//! > **NOTICE**: `Hex` column is a signed 2's complement.
187//!
188//! **Connect response (struct)**
189//!
190//! Before building the UDP packet, the [`ConnectResponse`](aquatic_udp_protocol::response::ConnectResponse)
191//! struct will look like this:
192//!
193//! Field            | Type                                                           | Example
194//! -----------------|----------------------------------------------------------------|-------------------------
195//! `connection_id`  | [`ConnectionId`](aquatic_udp_protocol::common::ConnectionId)   | `-4226491872051668937`
196//! `transaction_id` | [`TransactionId`](aquatic_udp_protocol::common::TransactionId) | `-888840697`
197//!
198//! **Connect specification**
199//!
200//! Original specification in [BEP 15. UDP Tracker Protocol for `BitTorrent`](https://www.bittorrent.org/beps/bep_0015.html).
201//!
202//! ### Announce
203//!
204//! `Announce` requests are used to announce the presence of a peer to the
205//! tracker. The tracker responds with a list of peers that are also downloading
206//! the same torrent. A "swarm" is a group of peers that are downloading the
207//! same torrent.
208//!
209//! #### Announce Request
210//!
211//! **Announce request (UDP packet)**
212//!
213//! Offset | Type/Size         | Name             | Description                                                  | Hex                                                             | Decimal                                                  
214//! -------|-------------------|------------------|--------------------------------------------------------------|-----------------------------------------------------------------|----------------------------------------------------------
215//! 0      | [`i64`](std::i64) | `connection_id`  | The connection id acquired from establishing the connection. | `0xC5_58_7C_09_08_48_D8_37`                                     | `-4226491872051668937`
216//! 8      | [`i32`](std::i32) | `action`         | Action for announce request.                                 | `0x00_00_00_01`                                                 | `1`
217//! 12     | [`i32`](std::i32) | `transaction_id` | Randomly generated by the client.                            | `0xA2_F9_54_48`                                                 | `-1560718264`
218//! 16     | 20-byte           | `info_hash`      | The infohash of the torrent being announced.                 | `0x03_84_05_48_64_3A_F2_A7_B6_3A_9F_5C_BC_A3_48_BC_71_50_CA_3A` | `20071130873666512363095721859061691407221705274`
219//! 36     | 20-byte           | `peer_id`        | The ID of the peer announcing the torrent.                   | `0x2D_71_42_34_34_31_30_2D_29_53_64_7E_64_65_34_78_4D_70_36_44` | `259430336069436570531165609119312093997849130564`
220//! 56     | [`i64`](std::i64) | `downloaded`     | The number of bytes the peer has downloaded so far.          | `0x00_00_00_00_00_00_00_00`                                     | `0`
221//! 64     | [`i64`](std::i64) | `left`           | The number of bytes left to download by the peer.            | `0x00_00_00_00_00_00_00_00`                                     | `0`
222//! 72     | [`i64`](std::i64) | `uploaded`       | The number of bytes the peer has uploaded so far.            | `0x00_00_00_00_00_00_00_00`                                     | `0`
223//! 80     | [`i32`](std::i32) | `event`          | The event the peer is reporting to the tracker.              | `0x0`, `0x1`, `0x2`, `0x3`                                      | `0`: none; `1`: completed; `2`: started; `3`: stopped
224//! 84     | [`i32`](std::i32) | `IP address`     | The peer IP. Ignored by the tracker. It uses the Sender's IP.| `0x00_00_00_00`                                                 | `0`
225//! 88     | [`i32`](std::i32) | `key`            | A unique key that is randomized by the client.               | `0xEF_34_95_D6`                                                 | `-281766442`
226//! 92     | [`i32`](std::i32) | `num_want`       | The maximum number of peers the peer wants in the response.  | `0x00_00_00_C8`                                                 | `200`
227//! 96     | [`i16`](std::i16) | `port`           | The port the peer is listening on.                           | `0x44_8C`                                                       | `17548`
228//!
229//! **Peer IP address**
230//!
231//! The peer IP address is always ignored by the tracker. It uses the sender's
232//! IP address.
233//!
234//! _"Do note that most trackers will only honor the IP address field under
235//! limited circumstances."_ ([BEP 15](https://www.bittorrent.org/beps/bep_0015.html)).
236//!
237//! Although not supported by this tracker a UDP tracker can use the IP address
238//! provided by the peer in the announce request under specific circumstances
239//! when it cannot rely on the source IP address of the incoming request. These
240//! circumstances might include:
241//!
242//! 1. Network Address Translation (NAT): In cases where a peer is behind a NAT,
243//!    the private IP address of the peer is not directly routable over the
244//!    internet. The NAT device translates the private IP address to a public one
245//!    when sending packets to the tracker. The public IP address is what the
246//!    tracker sees as the source IP of the incoming request. However, if the peer
247//!    provides its private IP address in the announce request, the tracker can use
248//!    this information to facilitate communication between peers in the same
249//!    private network.
250//!
251//! 2. Proxy or VPN usage: If a peer uses a proxy or VPN service to connect to
252//!    the tracker, the source IP address seen by the tracker will be the one
253//!    assigned by the proxy or VPN server. In this case, if the peer provides its
254//!    actual IP address in the announce request, the tracker can use it to
255//!    establish a direct connection with other peers, bypassing the proxy or VPN
256//!    server. This might improve performance or help in cases where some peers
257//!    cannot connect to the proxy or VPN server.
258//!
259//! 3. Tracker is behind a NAT, firewall, proxy, VPN, or load balancer: In cases
260//!    where the tracker is behind a NAT, firewall, proxy, VPN, or load balancer,
261//!    the source IP address of the incoming request will be the public IP address
262//!    of the NAT, firewall, proxy, VPN, or load balancer. If the peer provides its
263//!    private IP address in the announce request, the tracker can use this
264//!    information to establish a direct connection with the peer.
265//!
266//! It's important to note that using the provided IP address can pose security
267//! risks, as malicious peers might spoof their IP addresses in the announce
268//! request to perform various types of attacks.
269//!
270//! > **NOTICE**: The current tracker behavior is to ignore the IP address
271//! > provided by the peer, and use the source IP address of the incoming request,
272//! > when the tracker is not running behind a proxy, and to use the right-most IP
273//! > address in the `X-Forwarded-For` header when the tracker is running behind a
274//! > proxy.
275//!
276//! > **NOTICE**: The tracker also changes the peer IP address to the tracker
277//! > external IP when the peer is using a loopback IP address.
278//!
279//! **Sample announce request (UDP packet)**
280//!
281//! Some values used in the sample request:
282//!
283//! - Infohash: `0x03840548643AF2A7B63A9F5CBCA348BC7150CA3A`
284//! - Peer ID: `0x2D7142343431302D2953647E646534784D703644`
285//!
286//! UDP packet bytes:
287//!
288//! ```text
289//! Offset:  [    0,    1,    2,    3,    4,    5,    6,    7,    8,    9,   10,   11,   12,   13,   14,   15,   16,   17,   18,   19,   20,   21,   22,   23,   24,   25,   26,   27,   28,   29,   30,   31,   32,   33,   34,   35,   36,   37,   38,   39,   40,   41,   42,   43,   44,   45,   46,   47,   48,   49,   50,   51,   52,   53,   54,   55,   56,   57,   58,   59,   60,   61,   62,   63,   64,   65,   66,   67,   68,   69,   70,   71,   72,   73,   74,   75,   76,   77,   78,   79,   80,   81,   82,   83,   84,   85,   86,   87,   88,   89,   90,   91,   92,   93,   94,   95,   96,   97,   98,   99,  100]
290//! Decimal: [  197,   88,  124,    9,    8,   72,  216,   55,    0,    0,    0,    1,  162,  249,   84,   72,    3,  132,    5,   72,  100,   58,  242,  167,  182,   58,  159,   92,  188,  163,   72,  188,  113,   80,  202,   58,   45,  113,   66,   52,   52,   49,   48,   45,   41,   83,  100,  126,  100,  101,   52,  120,   77,  112,   54,   68,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    2,    0,    0,    0,    0,  239,   52,  149,  214,    0,    0,    0,  200,   68,  140,    2,    1,   47]
291//! Hex:     [ 0xC5, 0x58, 0x7C, 0x09, 0x08, 0x48, 0xD8, 0x37, 0x00, 0x00, 0x00, 0x01, 0xA2, 0xF9, 0x54, 0x48, 0x03, 0x84, 0x05, 0x48, 0x64, 0x3A, 0xF2, 0xA7, 0xB6, 0x3A, 0x9F, 0x5C, 0xBC, 0xA3, 0x48, 0xBC, 0x71, 0x50, 0xCA, 0x3A, 0x2D, 0x71, 0x42, 0x34, 0x34, 0x31, 0x30, 0x2D, 0x29, 0x53, 0x64, 0x7E, 0x64, 0x65, 0x34, 0x78, 0x4D, 0x70, 0x36, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0xEF, 0x34, 0x95, 0xD6, 0x00, 0x00, 0x00, 0xC8, 0x44, 0x8C, 0x02, 0x01, 0x2F]
292//! Param:   [<--------------- connection_id --------------->,<--------- action ---->,<-- transaction_id --->,<--------------------------------------------------------- info_hash ------------------------------------------------->,<---------------------------------------------- peer_id -------------------------------------------------------------->,<------------------- downloaded -------------->,<-------------------- left ------------------->,<---------------- uploaded ------------------->,<-------- event ------>,<----- IP address ---->,<--------- key ------->,<------ num_want ----->,<-- port --><---- BEP 41 --->]
293//! ```
294//!
295//! UDP packet fields:
296//!
297//! Offset | Type/Size         | Name              | Bytes Dec (Big Endian)                                                   | Hex                                                             | Decimal
298//! -------|-------------------|-------------------|--------------------------------------------------------------------------|-----------------------------------------------------------------|----------------------------------------------------
299//! 0      | [`i64`](std::i64) | `connection_id`   | `[197,88,124,9,8,72,216,55]`                                             | `0xC5_58_7C_09_08_48_D8_37`                                     | `-4226491872051668937`
300//! 8      | [`i32`](std::i32) | `action`          | `[0,0,0,1]`                                                              | `0x00_00_00_01`                                                 | `1`
301//! 12     | [`i32`](std::i32) | `transaction_id`  | `[162,249,84,72]`                                                        | `0xA2_F9_54_48`                                                 | `-1560718264`
302//! 16     | 20 bytes          | `info_hash`       | `[3,132,5,72,100,58,242,167,182,58,159,92,188,163,72,188,113,80,202,58]` | `0x03_84_05_48_64_3A_F2_A7_B6_3A_9F_5C_BC_A3_48_BC_71_50_CA_3A` | `20071130873666512363095721859061691407221705274`
303//! 36     | 20 bytes          | `peer_id`         | `[45,113,66,52,52,49,48,45,41,83,100,126,100,101,52,120,77,112,54,68]`   | `0x2D_71_42_34_34_31_30_2D_29_53_64_7E_64_65_34_78_4D_70_36_44` | `259430336069436570531165609119312093997849130564`
304//! 56     | [`i64`](std::i64) | `downloaded`      | `[0,0,0,0,0,0,0,0]`                                                      | `0x00_00_00_00_00_00_00_00`                                     | `0`
305//! 64     | [`i64`](std::i64) | `left`            | `[0,0,0,0,0,0,0,0]`                                                      | `0x00_00_00_00_00_00_00_00`                                     | `0`
306//! 72     | [`i64`](std::i64) | `uploaded`        | `[0,0,0,0,0,0,0,0]`                                                      | `0x00_00_00_00_00_00_00_00`                                     | `0`
307//! 80     | [`i32`](std::i32) | `event`           | `[0,0,0,2]`                                                              | `0x00_00_00_02`                                                 | `2` (`Started`)
308//! 84     | [`i32`](std::i32) | `IP address`      | `[0,0,0,0]`                                                              | `0x00_00_00_00`                                                 | `0`
309//! 88     | [`i32`](std::i32) | `key`             | `[239,52,149,214]`                                                       | `0xEF_34_95_D6`                                                 | `-281766442`
310//! 92     | [`i32`](std::i32) | `num_want`        | `[0,0,0,200]`                                                            | `0x00_00_00_C8`                                                 | `200`
311//! 96     | [`i16`](std::i16) | `port`            | `[8,140]`                                                                | `0x44_8C`                                                       | `17548`
312//! 98     | 1 byte            | `Option-Type`     | `[2]`                                                                    | `0x02`                                                          | `2`
313//! 99     | 2 byte            | `Length Byte`     | `[1,47]`                                                                 | `0x01_2F`                                                       | `303`
314//! 101    | N bytes           |                   |                                                                          |                                                                 |
315//!
316//! > **NOTICE**: bytes after offset 98 are part of the [BEP-41. UDP Tracker Protocol Extensions](https://www.bittorrent.org/beps/bep_0041.html).
317//! > There are three options defined for byte 98: `0x0` (`EndOfOptions`), `0x1` (`NOP`) and `0x2` (`URLData`).
318//!
319//! > **NOTICE**: `num_want` is being ignored by the tracker. Refer to
320//! > [issue 262](https://github.com/torrust/torrust-tracker/issues/262) for more
321//! > information.
322//!
323//! **Announce request (parsed struct)**
324//!
325//! After parsing the UDP packet, the [`AnnounceRequest`](aquatic_udp_protocol::request::AnnounceRequest)
326//! struct will contain the following fields:
327//!
328//! Field              | Type                                                            | Example
329//! -------------------|---------------------------------------------------------------- |--------------
330//! `connection_id`    | [`ConnectionId`](aquatic_udp_protocol::common::ConnectionId)    | `-4226491872051668937`
331//! `transaction_id`   | [`TransactionId`](aquatic_udp_protocol::common::TransactionId)  | `-1560718264`
332//! `info_hash`        | [`InfoHash`](aquatic_udp_protocol::common::InfoHash)            | `[3,132,5,72,100,58,242,167,182,58,159,92,188,163,72,188,113,80,202,58]`
333//! `peer_id`          | [`PeerId`](aquatic_udp_protocol::common::PeerId)                | `[45,113,66,52,52,49,48,45,41,83,100,126,100,101,52,120,77,112,54,68]`
334//! `bytes_downloaded` | [`NumberOfBytes`](aquatic_udp_protocol::common::NumberOfBytes)  | `0`
335//! `bytes_uploaded`   | [`TransactionId`](aquatic_udp_protocol::common::NumberOfBytes)  | `0`
336//! `event`            | [`AnnounceEvent`](aquatic_udp_protocol::request::AnnounceEvent) | `Started`
337//! `ip_address`       | [`Ipv4Addr`](aquatic_udp_protocol::common::ConnectionId)        | `None`
338//! `peers_wanted`     | [`NumberOfPeers`](aquatic_udp_protocol::common::NumberOfPeers)  | `200`
339//! `port`             | [`Port`](aquatic_udp_protocol::common::Port)                    | `17548`
340//!
341//! > **NOTICE**: the `peers_wanted` field is the `num_want` field in the UDP
342//! > packet.
343//!
344//! We are using a wrapper struct for the aquatic [`AnnounceRequest`](aquatic_udp_protocol::request::AnnounceRequest)
345//! struct, because we have our internal [`InfoHash`](torrust_tracker_primitives::info_hash::InfoHash)
346//! struct.
347//!
348//! ```text
349//! pub struct AnnounceWrapper {
350//!     pub announce_request: AnnounceRequest, // aquatic
351//!     pub info_hash: InfoHash, // our own
352//! }
353//! ```
354//!
355//! #### Announce Response
356//!
357//! **Announce response (UDP packet)**
358//!
359//! Offset     | Type/Size         | Name             | Description                                                                     | Hex             | Decimal
360//! -----------|-------------------|------------------|---------------------------------------------------------------------------------|-----------------|----------------------------
361//! 0          | [`i32`](std::i32) | `action`         | The action this is a reply to.                                                  | `0x00_00_00_01` | `1`: announce; `3`: error
362//! 4          | [`i32`](std::i32) | `transaction_id` | Must match the `transaction_id` sent in the announce request.                   | `0x00_00_00_00` | `0`
363//! 8          | [`i32`](std::i32) | `interval`       | The number of seconds the peer should wait until re-announcing itself.          | `0x00_00_00_00` | `0`
364//! 12         | [`i32`](std::i32) | `leechers`       | The number of peers in the swarm that has not finished downloading.             | `0x00_00_00_00` | `0`
365//! 16         | [`i32`](std::i32) | `seeders`        | The number of peers in the swarm that has finished downloading and are seeding. | `0x00_00_00_00` | `0`
366//!            |                   |                  |                                                                                 |                 |
367//! 20 + 6 * n | [`i32`](std::i32) | `IP address`     | The IP of a peer in the swarm.                                                  | `0x69_69_69_69` | `1768515945`
368//! 24 + 6 * n | [`i16`](std::i16) | `TCP port`       | The peer's listen port.                                                         | `0x44_8C`       | `17548`
369//! 20 + 6 * N |                   |                  |                                                                                 |                 |
370//!
371//! > **NOTICE**: `Hex` column is a signed 2's complement.
372//!
373//! > **NOTICE**: `IP address` should always be set to 0 when the peer is using
374//! > `IPv6`.
375//!
376//! **Sample announce response (UDP packet)**
377//!
378//! UDP packet bytes (fixed part):
379//!
380//! ```text
381//! Offset:  [    0,    1,    2,    3,    4,    5,    6,    7,    8,    9,   10,   11,   12,   13,   14,   15,   16,   17,   18,   19]
382//! Decimal: [    0,    0,    0,    1,  162,  249,   84,   72,    0,    0,    0,  120,    0,    0,    0,    0,    0,    0,    0,    1]
383//! Hex:     [ 0x00, 0x00, 0x00, 0x01, 0xA2, 0xF9, 0x54, 0x48, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]
384//! Param:   [<------- action ------>,<-- transaction_id --->,<----- interval ------>,<----- leechers ------>,<------ seeders ------>]
385//! ```
386//!
387//! UDP packet fields (fixed part):
388//!
389//! Offset     | Type/Size         | Name             | Bytes (Big Endian)  | Hex             | Decimal
390//! -----------|-------------------|------------------|---------------------|-----------------|----------------------------
391//! 0          | [`i32`](std::i32) | `action`         | `[0, 0, 0, 0]`      | `0x00_00_00_01` | `1`: announce; `3`: error
392//! 4          | [`i32`](std::i32) | `transaction_id` | `[162,249,84,72]`   | `0xA2_F9_54_48` | `-1560718264`
393//! 8          | [`i32`](std::i32) | `interval`       | `[0,0,0,120]`       | `0x00_00_00_78` | `120`
394//! 12         | [`i32`](std::i32) | `leechers`       | `[0, 0, 0, 0]`      | `0x00_00_00_00` | `0`
395//! 16         | [`i32`](std::i32) | `seeders`        | `[0, 0, 0, 1]`      | `0x00_00_00_01` | `1`
396//!
397//! This is the fixed part of the packet. After the fixed part there is
398//! dynamically generated data with the list of peers in the swarm. The list may
399//! include `IPv4` or `IPv6` peers, depending on the address family of the
400//! underlying UDP packet. I.e. packets from a v4 address use the v4 format,
401//! those from a v6 address use the v6 format.
402//!
403//! UDP packet bytes (`IPv4` peer list):
404//!
405//! ```text
406//! Offset:  [   20,   21,   22,   23,   24,   25]
407//! Decimal: [  105,  105,  105,  105,   08,  140]
408//! Hex:     [ 0x69, 0x69, 0x69, 0x69, 0x44, 0x8C]
409//! Param:   [<----- IP address ---->,<-TCP port>]
410//! ```
411//!
412//! > **NOTICE**: there are 6 bytes per peer (4 bytes for the `IPv4` address and
413//! > 2 bytes for the TCP port).
414//!
415//! UDP packet fields (`IPv4` peer list):
416//!
417//! Offset   | Type/Size         | Name         | Bytes (Big Endian)  | Hex             | Decimal
418//! ---------|-------------------|--------------|---------------------|-----------------|----------------------------
419//! 20 + 6*n | [`i32`](std::i32) | `IP address` | `[105,105,105,105]` | `0x69_69_69_69` | `1768515945`
420//! 24 + 6*n | [`i16`](std::i16) | `TCP port`   | `[8,140]`           | `0x44_8C`       | `17548`
421//! 20 + 6*N |                   |              |                     |                 |
422//!
423//! UDP packet bytes (`IPv6` peer list):
424//!
425//! ```text
426//! Offset:  [   20,   21,   22,   23,   24,   25,   26,   27,   28,   29,   30,   31,   32,   33,   34,   35,   36,   37]
427//! Decimal: [  105,  105,  105,  105,  105,  105,  105,  105,  105,  105,  105,  105,  105,  105,  105,  105,   08,  140]
428//! Hex:     [ 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x44, 0x8C]
429//! Param:   [<-------------------------------------------- IP address ------------------------------------->,<-TCP port>]
430//! ```
431//!
432//! > **NOTICE**: there are 18 bytes per peer (16 bytes for the `IPv6` address and
433//! > 2 bytes for the TCP port).
434//!
435//! UDP packet fields (`IPv6` peer list):
436//!
437//! Offset    | Type/Size           | Name         | Bytes (Big Endian)                                                  | Hex                                                 | Decimal
438//! ----------|---------------------|--------------|---------------------------------------------------------------------|-----------------------------------------------------|-------------------------------------------
439//! 20 + 18*n | [`i128`](std::i128) | `IP address` | `[105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105]` | `0x69_69_69_69_69_69_69_69_69_69_69_69_69_69_69_69` | `140116268732151132014330720707198675305`
440//! 24 + 18*n | [`i16`](std::i16)   | `TCP port`   | `[8,140]`                                                           | `0x44_8C`                                           | `17548`
441//! 20 + 18*N |                     |              |                                                                     |                                                     |
442//!
443//! > **NOTICE**: `Hex` column is a signed 2's complement.
444//!
445//! > **NOTICE**: the peer list does not include the peer that sent the announce
446//! > request.
447//!
448//! **Announce response (struct)**
449//!
450//! The [`AnnounceResponse`](aquatic_udp_protocol::response::AnnounceResponse)
451//! struct will have the following fields:
452//!
453//! Field               | Type                                                                   | Example
454//! --------------------|------------------------------------------------------------------------|--------------
455//! `transaction_id`    | [`TransactionId`](aquatic_udp_protocol::common::TransactionId)         | `-1560718264`
456//! `announce_interval` | [`AnnounceInterval`](aquatic_udp_protocol::common::AnnounceInterval)   | `120`
457//! `leechers`          | [`NumberOfPeers`](aquatic_udp_protocol::common::NumberOfPeers)         | `0`
458//! `seeders`           | [`NumberOfPeers`](aquatic_udp_protocol::common::NumberOfPeers)         | `1`
459//! `peers`             | Vector of [`ResponsePeer`](aquatic_udp_protocol::common::ResponsePeer) | `[]`
460//!
461//! **Announce specification**
462//!
463//! Original specification in [BEP 15. UDP Tracker Protocol for `BitTorrent`](https://www.bittorrent.org/beps/bep_0015.html).
464//!
465//! ### Scrape
466//!
467//! The `scrape` request allows a peer to get [swarm metadata](torrust_tracker_primitives::swarm_metadata::SwarmMetadata)
468//! for multiple torrents at the same time.
469//!
470//! The response contains the [swarm metadata](torrust_tracker_primitives::swarm_metadata::SwarmMetadata)
471//! for that torrent:
472//!
473//! - [complete](torrust_tracker_primitives::swarm_metadata::SwarmMetadata::complete)
474//! - [downloaded](torrust_tracker_primitives::swarm_metadata::SwarmMetadata::downloaded)
475//! - [incomplete](torrust_tracker_primitives::swarm_metadata::SwarmMetadata::incomplete)
476//!
477//! > **NOTICE**: up to about 74 torrents can be scraped at once. A full scrape
478//! > can't be done with this protocol. This is a limitation of the UDP protocol.
479//! > Defined with a hardcoded const [`MAX_SCRAPE_TORRENTS`](crate::shared::bit_torrent::common::MAX_SCRAPE_TORRENTS).
480//! > Refer to [issue 262](https://github.com/torrust/torrust-tracker/issues/262)
481//! > for more information about this limitation.
482//!
483//! #### Scrape Request
484//!
485//! **Scrape request (UDP packet)**
486//!
487//! Offset    | Type/Size         | Name             | Description                                                            | Hex                                                             | Decimal
488//! ----------|-------------------|------------------|------------------------------------------------------------------------|-----------------------------------------------------------------|--------------------------------------------------
489//! 0         | [`i64`](std::i64) | `connection_id`  | The `connection_id` retrieved from the establishing of the connection. | `0xC5_58_7C_09_08_48_D8_37`                                     | `-4226491872051668937`
490//! 8         | [`i32`](std::i32) | `action`         | Action identifying the scrape request                                  | `0x00_00_00_02`                                                 | `2` (`Scrape`)
491//! 12        | [`i32`](std::i32) | `transaction_id` | Randomly generated by the client.                                      | `0xA2_F9_54_48`                                                 | `-1560718264`
492//! 16 + 20*n | 20 bytes          | `info_hash`      | The infohash of the torrent being scraped.                             | `0x03_84_05_48_64_3A_F2_A7_B6_3A_9F_5C_BC_A3_48_BC_71_50_CA_3A` | `20071130873666512363095721859061691407221705274`
493//! 16 + 20*N |                   |                  |                                                                        |
494//!
495//! The last field (`info_hash`) is repeated for each torrent being scraped.
496//!
497//! Dynamic part of the UDP packet:
498//!
499//! Offset    | Type/Size         | Name        | Description                                | Hex                                                             | Decimal
500//! ----------|-------------------|-------------|--------------------------------------------|-----------------------------------------------------------------|---------------------------------------------------
501//! 16 + 20*n | 20 bytes          | `info_hash` | The infohash of the torrent being scraped. | `0x03_84_05_48_64_3A_F2_A7_B6_3A_9F_5C_BC_A3_48_BC_71_50_CA_3A` | `20071130873666512363095721859061691407221705274`
502//!
503//! **Sample scrape request (UDP packet)**
504//!
505//! UDP packet bytes (fixed part):
506//!
507//! ```text
508//! Offset:  [    0,    1,    2,    3,    4,    5,    6,    7,    8,    9,   10,   11,   12,   13,   14,   15,   16,   17,   18,   19,   20,   21,   22,   23,   24,   25,   26,   27,   28,   29,   30,   31,   32,   33,   34,   35]
509//! Decimal: [  197,   88,  124,    9,    8,   72,  216,   55,    0,    0,    0,    2,  162,  249,   84,   72,    3,  132,    5,   72,  100,   58,  242,  167,  182,   58,  159,   92,  188,  163,   72,  188,  113,   80,  202,   58]
510//! Hex:     [ 0xC5, 0x58, 0x7C, 0x09, 0x08, 0x48, 0xD8, 0x37, 0x00, 0x00, 0x00, 0x02, 0xA2, 0xF9, 0x54, 0x48, 0x03, 0x84, 0x05, 0x48, 0x64, 0x3A, 0xF2, 0xA7, 0xB6, 0x3A, 0x9F, 0x5C, 0xBC, 0xA3, 0x48, 0xBC, 0x71, 0x50, 0xCA, 0x3A]
511//! Param:   [<--------------- connection_id --------------->,<--------- action ---->,<-- transaction_id --->,<--------------------------------------------------------- info_hash ------------------------------------------------->]
512//! ```
513//!
514//! UDP packet bytes (infohash list):
515//!
516//! ```text
517//! Offset:  [   16,   17,   18,   19,   20,   21,   22,   23,   24,   25,   26,   27,   28,   29,   30,   31,   32,   33,   34,   35]
518//! Decimal: [    3,  132,    5,   72,  100,   58,  242,  167,  182,   58,  159,   92,  188,  163,   72,  188,  113,   80,  202,   58]
519//! Hex:     [ 0x03, 0x84, 0x05, 0x48, 0x64, 0x3A, 0xF2, 0xA7, 0xB6, 0x3A, 0x9F, 0x5C, 0xBC, 0xA3, 0x48, 0xBC, 0x71, 0x50, 0xCA, 0x3A]
520//! Param:   [<--------------------------------------------------------- info_hash ------------------------------------------------->]
521//! ```
522//!
523//! UDP packet fields:
524//!
525//! Offset | Type/Size         | Name             | Bytes Dec (Big Endian)                                                   | Hex                                                             | Decimal
526//! -------|-------------------|------------------|--------------------------------------------------------------------------|-----------------------------------------------------------------|--------------------------------------------------
527//! 0      | [`i64`](std::i64) | `connection_id`  | `[197,88,124,9,8,72,216,55]`                                             | `0xC5_58_7C_09_08_48_D8_37`                                     | `-4226491872051668937`
528//! 4      | [`i32`](std::i32) | `action`         | `[0, 0, 0, 2]`                                                           | `0x00_00_00_02`                                                 | `2` (`Scrape`)
529//! 8      | [`i32`](std::i32) | `transaction_id` | `[162,249,84,72]`                                                        | `0xA2_F9_54_48`                                                 | `-1560718264`
530//! 8      | 20 bytes          | `info_hash`      | `[3,132,5,72,100,58,242,167,182,58,159,92,188,163,72,188,113,80,202,58]` | `0x03_84_05_48_64_3A_F2_A7_B6_3A_9F_5C_BC_A3_48_BC_71_50_CA_3A` | `20071130873666512363095721859061691407221705274`
531//!
532//! **Scrape request (parsed struct)**
533//!
534//! After parsing the UDP packet, the [`ScrapeRequest`](aquatic_udp_protocol::request::ScrapeRequest)
535//! struct will look like this:
536//!
537//! Field            | Type                                                           | Example
538//! -----------------|----------------------------------------------------------------|----------------------------------------------------------------------------
539//! `connection_id`  | [`ConnectionId`](aquatic_udp_protocol::common::ConnectionId)   | `-4226491872051668937`
540//! `transaction_id` | [`TransactionId`](aquatic_udp_protocol::common::TransactionId) | `-1560718264`
541//! `info_hashes`    | Vector of [`InfoHash`](aquatic_udp_protocol::common::InfoHash) | `[[3,132,5,72,100,58,242,167,182,58,159,92,188,163,72,188,113,80,202,58]]`
542//!
543//! #### Scrape Response
544//!
545//! **Scrape response (UDP packet)**
546//!
547//! Offset    | Type/Size         | Name (BEP15 or libtorrent)  | Description                                           | Hex             | Decimal
548//! ----------|-------------------|-----------------------------|-------------------------------------------------------|-----------------|-----------------
549//! 0         | [`i32`](std::i32) | `action`                    | Action identifying the connect request                | `0x00_00_00_00` | `2` (`Scrape`)
550//! 4         | [`i32`](std::i32) | `transaction_id`            | Must match the `transaction_id` sent from the client. | `0xA2_F9_54_48` | `-1560718264`
551//! 8 + 12*n  | [`i32`](std::i32) | `seeders` or `complete`     | The current number of connected seeds.                | `0x00_00_00_00` | `0`
552//! 12 + 12*n | [`i32`](std::i32) | `completed` or `downloaded` | The number of times this torrent has been downloaded. | `0x00_00_00_00` | `0`
553//! 16 + 12*n | [`i32`](std::i32) | `leechers` or `incomplete`  | The current number of connected leechers.             | `0x00_00_00_00` | `0`
554//! 8 + 12*N  |                   |                             |                                                       |                 |
555//!
556//! > **NOTICE**: `Hex` column is a signed 2's complement.
557//!
558//! Dynamic part of the UDP packet:
559//!
560//! Offset    | Type/Size         | Name (BEP15 or libtorrent)  | Description                                           | Hex             | Decimal
561//! ----------|-------------------|-----------------------------|-------------------------------------------------------|-----------------|-----------------
562//! 8 + 12*n  | [`i32`](std::i32) | `seeders` or `complete`     | The current number of connected seeds.                | `0x00_00_00_00` | `0`
563//! 12 + 12*n | [`i32`](std::i32) | `completed` or `downloaded` | The number of times this torrent has been downloaded. | `0x00_00_00_00` | `0`
564//! 16 + 12*n | [`i32`](std::i32) | `leechers` or `incomplete`  | The current number of connected leechers.             | `0x00_00_00_00` | `0`
565//! 8 + 12*N  |                   |                             |                                                       |                 |
566//!
567//! For each info hash in the request there will be 3 32-bit integers (12 bytes)
568//! in the response with the number of seeders, leechers and downloads.
569//!
570//! **Sample scrape response (UDP packet)**
571//!
572//! UDP packet bytes:
573//!
574//! ```text
575//! Offset:  [   0,    1,    2,    3,    4,    5,    6,    7,    8,    9,   10,   11,   12,   13,   14,   15,   16,   17,   18,   19]
576//! Decimal: [   0,    0,    0,    0,  203,    5,   94,    7,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0]
577//! Hex:     [0x00, 0x00, 0x00, 0x00, 0xCB, 0x05, 0x5E, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
578//! Param:   [<------ action ------>,<-- transaction_id --->,<------ seeders ------>,<----- completed ----->,<------ leechers ----->]
579//! ```
580//!
581//! UDP packet fields:
582//!
583//! Offset | Type/Size         | Name             | Bytes (Big Endian) | Hex              | Decimal
584//! -------|-------------------|------------------|--------------------|------------------|----------------
585//! 0      | [`i32`](std::i32) | `action`         | [0, 0, 0, 2]       | `0x00_00_00_02`  | `2` (`Scrape`)
586//! 4      | [`i32`](std::i32) | `transaction_id` | [203, 5, 94, 7]    | `0xA2_F9_54_48`  | `-1560718264`
587//! 8      | [`i32`](std::i32) | `seeders`        | [0, 0, 0, 0]       | `0x00_00_00_00`  | `0`
588//! 12     | [`i32`](std::i32) | `completed`      | [0, 0, 0, 0]       | `0x00_00_00_00`  | `0`
589//! 16     | [`i32`](std::i32) | `leechers`       | [0, 0, 0, 0]       | `0x00_00_00_00`  | `0`
590//!
591//! > **NOTICE**: `Hex` column is a signed 2's complement.
592//!
593//! **Scrape response (struct)**
594//!
595//! Before building the UDP packet, the [`ScrapeResponse`](aquatic_udp_protocol::response::ScrapeResponse)
596//! struct will look like this:
597//!
598//! Field            | Type                                                                                            | Example
599//! -----------------|-------------------------------------------------------------------------------------------------|---------------
600//! `transaction_id` | [`TransactionId`](aquatic_udp_protocol::common::TransactionId)                                  | `-1560718264`
601//! `torrent_stats`  | Vector of [`TorrentScrapeStatistics`](aquatic_udp_protocol::response::TorrentScrapeStatistics)  | `[]`
602//!
603//! **Scrape specification**
604//!
605//! Original specification in [BEP 15. UDP Tracker Protocol for `BitTorrent`](https://www.bittorrent.org/beps/bep_0015.html).
606//!
607//! ## Errors
608//!
609//! ### Error Response
610//!
611//! **Error response (UDP packet)**
612//!
613//! Offset | Type/Size         | Name             | Description                                           | Hex                         | Decimal
614//! -------|-------------------|------------------|-------------------------------------------------------|-----------------------------|-----------------------
615//! 0      | [`i32`](std::i32) | `action`         | Action identifying the error response.                | `0x00_00_00_03`             | `3`
616//! 4      | [`i32`](std::i32) | `transaction_id` | Must match the `transaction_id` sent from the client. | `0xCB_05_5E_07`             | `-888840697`
617//! 8      | N Bytes           | `error_string`   | Error description.                                    |                             |
618//!
619//! ## Extensions
620//!
621//! Extensions described in [BEP 41. UDP Tracker Protocol Extensions](https://www.bittorrent.org/beps/bep_0041.html)
622//! are not supported yet.
623//!
624//! ## Links
625//!
626//! - [BEP 15. UDP Tracker Protocol for `BitTorrent`](https://www.bittorrent.org/beps/bep_0015.html).
627//! - [BEP 41. UDP Tracker Protocol Extensions](https://www.bittorrent.org/beps/bep_0041.html).
628//! - [libtorrent - Bittorrent UDP-tracker protocol extension](https://www.rasterbar.com/products/libtorrent/udp_tracker_protocol.html).
629//! - [XBTT Tracker. UDP tracker protocol](https://xbtt.sourceforge.net/udp_tracker_protocol.html).
630//! - [Wikipedia: UDP tracker](https://en.wikipedia.org/wiki/UDP_tracker).
631//!
632//! ## Credits
633//!
634//! [Bittorrent UDP-tracker protocol extension](https://www.rasterbar.com/products/libtorrent/udp_tracker_protocol.html)
635//! documentation by [Arvid Norberg](https://github.com/arvidn) was very
636//! supportive in the development of this documentation. Some descriptions were
637//! taken from the [libtorrent](https://www.rasterbar.com/products/libtorrent/udp_tracker_protocol.html).
638
639use std::net::SocketAddr;
640
641pub mod connection_cookie;
642pub mod error;
643pub mod handlers;
644pub mod logging;
645pub mod peer_builder;
646pub mod server;
647
648pub const UDP_TRACKER_LOG_TARGET: &str = "UDP TRACKER";
649
650/// Number of bytes.
651pub type Bytes = u64;
652/// The port the peer is listening on.
653pub type Port = u16;
654/// The transaction id. A random number generated byt the peer that is used to
655/// match requests and responses.
656pub type TransactionId = i64;
657
658#[derive(Clone, Debug)]
659pub struct RawRequest {
660    payload: Vec<u8>,
661    from: SocketAddr,
662}