torrust_tracker/servers/http/
mod.rs

1//! HTTP Tracker.
2//!
3//! This module contains the HTTP tracker implementation.
4//!
5//! The HTTP tracker is a simple HTTP server that responds to two `GET` requests:
6//!
7//! - `Announce`: used to announce the presence of a peer to the tracker.
8//! - `Scrape`: used to get information about a torrent.
9//!
10//! Refer to the [`bit_torrent`](crate::shared::bit_torrent) module for more
11//! information about the `BitTorrent` protocol.
12//!
13//! ## Table of Contents
14//!
15//! - [Requests](#requests)
16//!     - [Announce](#announce)
17//!     - [Scrape](#scrape)
18//! - [Versioning](#versioning)
19//! - [Links](#links)
20//!
21//! ## Requests
22//!
23//! ### Announce
24//!
25//! `Announce` requests are used to announce the presence of a peer to the
26//! tracker. The tracker responds with a list of peers that are also downloading
27//! the same torrent. A "swarm" is a group of peers that are downloading the
28//! same torrent.
29//!
30//! `Announce` responses are encoded in [bencoded](https://en.wikipedia.org/wiki/Bencode)
31//! format.
32//!
33//! There are two types of `Announce` responses: `compact` and `non-compact`. In
34//! a compact response, the peers are encoded in a single string. In a
35//! non-compact response, the peers are encoded in a list of dictionaries. The
36//! compact response is more efficient than the non-compact response and it does
37//! not contain the peer's IDs.
38//!
39//! **Query parameters**
40//!
41//! > **NOTICE**: you can click on the parameter name to see a full description
42//! > after extracting and parsing the parameter from the URL query component.
43//!
44//! Parameter | Type | Description | Required |  Default | Example
45//! ---|---|---|---|---|---
46//! [`info_hash`](crate::servers::http::v1::requests::announce::Announce::info_hash) | percent encoded of 20-byte array | The `Info Hash` of the torrent. | Yes | No | `%81%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00`
47//! `peer_addr` | string |The IP address of the peer. | No | No | `2.137.87.41`
48//! [`downloaded`](crate::servers::http::v1::requests::announce::Announce::downloaded) | positive integer |The number of bytes downloaded by the peer. | No | `0` | `0`
49//! [`uploaded`](crate::servers::http::v1::requests::announce::Announce::uploaded) | positive integer | The number of bytes uploaded by the peer. | No | `0` | `0`
50//! [`peer_id`](crate::servers::http::v1::requests::announce::Announce::peer_id) | percent encoded of 20-byte array  | The ID of the peer. | Yes | No | `-qB00000000000000001`
51//! [`port`](crate::servers::http::v1::requests::announce::Announce::port) | positive integer | The port used by the peer. | Yes | No | `17548`
52//! [`left`](crate::servers::http::v1::requests::announce::Announce::left) | positive integer | The number of bytes pending to download. | No | `0` | `0`
53//! [`event`](crate::servers::http::v1::requests::announce::Announce::event) | positive integer | The event that triggered the `Announce` request: `started`, `completed`, `stopped` | No | `None` | `completed`
54//! [`compact`](crate::servers::http::v1::requests::announce::Announce::compact) | `0` or `1` | Whether the tracker should return a compact peer list. | No | `None` | `0`
55//! `numwant` | positive integer | **Not implemented**. The maximum number of peers you want in the reply. | No | `50` | `50`
56//!
57//! Refer to the [`Announce`](crate::servers::http::v1::requests::announce::Announce)
58//! request for more information about the parameters.
59//!
60//! > **NOTICE**: the [BEP 03](https://www.bittorrent.org/beps/bep_0003.html)
61//! > defines only the `ip` and `event` parameters as optional. However, the
62//! > tracker assigns default values to the optional parameters if they are not
63//! > provided.
64//!
65//! > **NOTICE**: the `peer_addr` parameter is not part of the original
66//! > specification. But the peer IP was added in the
67//! > [UDP Tracker protocol](https://www.bittorrent.org/beps/bep_0015.html). It is
68//! > used to provide the peer's IP address to the tracker, but it is ignored by
69//! > the tracker. The tracker uses the IP address of the peer that sent the
70//! > request or the right-most-ip in the `X-Forwarded-For` header if the tracker
71//! > is behind a reverse proxy.
72//!
73//! > **NOTICE**: the maximum number of peers that the tracker can return is
74//! > `74`. Defined with a hardcoded const [`TORRENT_PEERS_LIMIT`](torrust_tracker_configuration::TORRENT_PEERS_LIMIT).
75//! > Refer to [issue 262](https://github.com/torrust/torrust-tracker/issues/262)
76//! > for more information about this limitation.
77//!
78//! > **NOTICE**: the `info_hash` parameter is NOT a `URL` encoded string param.
79//! > It is percent encode of the raw `info_hash` bytes (40 bytes). URL `GET` params
80//! > can contain any bytes, not only well-formed UTF-8. The `info_hash` is a
81//! > 20-byte SHA1. Check the [`percent_encoding`]
82//! > module to know more about the encoding.
83//!
84//! > **NOTICE**: the `peer_id` parameter is NOT a `URL` encoded string param.
85//! > It is percent encode of the raw peer ID bytes (20 bytes). URL `GET` params
86//! > can contain any bytes, not only well-formed UTF-8. The `info_hash` is a
87//! > 20-byte SHA1. Check the [`percent_encoding`]
88//! > module to know more about the encoding.
89//!
90//! > **NOTICE**: by default, the tracker returns the non-compact peer list when
91//! > no `compact` parameter is provided or is empty. The
92//! > [BEP 23](https://www.bittorrent.org/beps/bep_0023.html) suggests to do the
93//! > opposite. The tracker should return the compact peer list by default and
94//! > return the non-compact peer list if the `compact` parameter is `0`.
95//!
96//! **Sample announce URL**
97//!
98//! A sample `GET` `announce` request:
99//!
100//! <http://0.0.0.0:7070/announce?info_hash=%81%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00&peer_addr=2.137.87.41&downloaded=0&uploaded=0&peer_id=-qB00000000000000001&port=17548&left=0&event=completed&compact=0>
101//!
102//! **Sample non-compact response**
103//!
104//! In [bencoded](https://en.wikipedia.org/wiki/Bencode) format:
105//!
106//! ```text
107//! d8:completei333e10:incompletei444e8:intervali111e12:min intervali222e5:peersld2:ip15:105.105.105.1057:peer id20:-qB000000000000000014:porti28784eed2:ip39:6969:6969:6969:6969:6969:6969:6969:69697:peer id20:-qB000000000000000024:porti28784eeee
108//! ```
109//!
110//! And represented as a json:
111//!
112//! ```json
113//! {
114//!     "complete": 333,
115//!     "incomplete": 444,
116//!     "interval": 111,
117//!     "min interval": 222,
118//!     "peers": [
119//!        {
120//!           "ip": "105.105.105.105",
121//!           "peer id": "-qB00000000000000001",
122//!           "port": 28784
123//!        },
124//!        {
125//!           "ip": "6969:6969:6969:6969:6969:6969:6969:6969",
126//!           "peer id": "-qB00000000000000002",
127//!           "port": 28784
128//!        }
129//!     ]
130//! }
131//! ```
132//!
133//! If you save the response as a file and you open it with a program that can
134//! handle binary data you would see:
135//!
136//! ```text
137//! 00000000: 6438 3a63 6f6d 706c 6574 6569 3333 3365  d8:completei333e
138//! 00000010: 3130 3a69 6e63 6f6d 706c 6574 6569 3434  10:incompletei44
139//! 00000020: 3465 383a 696e 7465 7276 616c 6931 3131  4e8:intervali111
140//! 00000030: 6531 323a 6d69 6e20 696e 7465 7276 616c  e12:min interval
141//! 00000040: 6932 3232 6535 3a70 6565 7273 6c64 323a  i222e5:peersld2:
142//! 00000050: 6970 3135 3a31 3035 2e31 3035 2e31 3035  ip15:105.105.105
143//! 00000060: 2e31 3035 373a 7065 6572 2069 6432 303a  .1057:peer id20:
144//! 00000070: 2d71 4230 3030 3030 3030 3030 3030 3030  -qB0000000000000
145//! 00000080: 3030 3031 343a 706f 7274 6932 3837 3834  00014:porti28784
146//! 00000090: 6565 6432 3a69 7033 393a 3639 3639 3a36  eed2:ip39:6969:6
147//! 000000a0: 3936 393a 3639 3639 3a36 3936 393a 3639  969:6969:6969:69
148//! 000000b0: 3639 3a36 3936 393a 3639 3639 3a36 3936  69:6969:6969:696
149//! 000000c0: 3937 3a70 6565 7220 6964 3230 3a2d 7142  97:peer id20:-qB
150//! 000000d0: 3030 3030 3030 3030 3030 3030 3030 3030  0000000000000000
151//! 000000e0: 3234 3a70 6f72 7469 3238 3738 3465 6565  24:porti28784eee
152//! 000000f0: 65                                       e
153//! ```
154//!
155//! Refer to the [`Normal`](crate::servers::http::v1::responses::announce::Normal), i.e. `Non-Compact`
156//! response for more information about the response.
157//!
158//! **Sample compact response**
159//!
160//! In [bencoded](https://en.wikipedia.org/wiki/Bencode) format:
161//!
162//! ```text
163//! d8:completei333e10:incompletei444e8:intervali111e12:min intervali222e5:peers6:iiiipp6:peers618:iiiiiiiiiiiiiiiippe
164//! ```
165//!
166//! And represented as a json:
167//!
168//! ```json
169//! {
170//!     "complete": 333,
171//!     "incomplete": 444,
172//!     "interval": 111,
173//!     "min interval": 222,
174//!     "peers": "iiiipp",
175//!     "peers6": "iiiiiiiiiiiiiiiipp"
176//! }
177//! ```
178//!
179//! If you save the response as a file and you open it with a program that can
180//! handle binary data you would see:
181//!
182//! ```text
183//! 0000000: 6438 3a63 6f6d 706c 6574 6569 3333 3365  d8:completei333e
184//! 0000010: 3130 3a69 6e63 6f6d 706c 6574 6569 3434  10:incompletei44
185//! 0000020: 3465 383a 696e 7465 7276 616c 6931 3131  4e8:intervali111
186//! 0000030: 6531 323a 6d69 6e20 696e 7465 7276 616c  e12:min interval
187//! 0000040: 6932 3232 6535 3a70 6565 7273 363a 6969  i222e5:peers6:ii
188//! 0000050: 6969 7070 363a 7065 6572 7336 3138 3a69  iipp6:peers618:i
189//! 0000060: 6969 6969 6969 6969 6969 6969 6969 6970  iiiiiiiiiiiiiiip
190//! 0000070: 7065                                     pe
191//! ```
192//!
193//! Refer to the [`Compact`](crate::servers::http::v1::responses::announce::Compact)
194//! response for more information about the response.
195//!
196//! **Protocol**
197//!
198//! Original specification in [BEP 03. The `BitTorrent` Protocol Specification](https://www.bittorrent.org/beps/bep_0003.html).
199//!
200//! If you want to know more about the `announce` request:
201//!
202//! - [BEP 03. The `BitTorrent` Protocol Specification](https://www.bittorrent.org/beps/bep_0003.html)
203//! - [BEP 23. Tracker Returns Compact Peer Lists](https://www.bittorrent.org/beps/bep_0023.html)
204//! - [Vuze announce docs](https://wiki.vuze.com/w/Announce)
205//! - [wiki.theory.org - Announce](https://wiki.theory.org/BitTorrent_Tracker_Protocol#Basic_Tracker_Announce_Request)
206//!
207//! ### Scrape
208//!
209//! The `scrape` request allows a peer to get [swarm metadata](torrust_tracker_primitives::swarm_metadata::SwarmMetadata)
210//! for multiple torrents at the same time.
211//!
212//! The response contains the [swarm metadata](torrust_tracker_primitives::swarm_metadata::SwarmMetadata)
213//! for that torrent:
214//!
215//! - [complete](torrust_tracker_primitives::swarm_metadata::SwarmMetadata::complete)
216//! - [downloaded](torrust_tracker_primitives::swarm_metadata::SwarmMetadata::downloaded)
217//! - [incomplete](torrust_tracker_primitives::swarm_metadata::SwarmMetadata::incomplete)
218//!
219//! **Query parameters**
220//!
221//! Parameter | Type | Description | Required |  Default | Example
222//! ---|---|---|---|---|---
223//! [`info_hash`](crate::servers::http::v1::requests::scrape::Scrape::info_hashes) | percent encoded of 20-byte array | The `Info Hash` of the torrent. | Yes | No | `%81%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00`
224//!
225//! > **NOTICE**: you can scrape multiple torrents at the same time by passing
226//! > multiple `info_hash` parameters.
227//!
228//! Refer to the [`Scrape`](crate::servers::http::v1::requests::scrape::Scrape)
229//! request for more information about the parameters.
230//!
231//! **Sample scrape URL**
232//!
233//! A sample `scrape` request for only one torrent:
234//!
235//! <http://0.0.0.0:7070/scrape?info_hash=%81%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00>
236//!
237//! In order to scrape multiple torrents at the same time you can pass multiple
238//! `info_hash` parameters: `info_hash=%81%00%0...00%00%00&info_hash=%82%00%0...00%00%00`
239//!
240//! > **NOTICE**: the maximum number of torrents you can scrape at the same time
241//! > is `74`. Defined with a hardcoded const [`MAX_SCRAPE_TORRENTS`](crate::shared::bit_torrent::common::MAX_SCRAPE_TORRENTS).
242//!
243//! **Sample response**
244//!
245//! The `scrape` response is a [bencoded](https://en.wikipedia.org/wiki/Bencode)
246//! byte array like the following:
247//!
248//! ```text
249//! d5:filesd20:iiiiiiiiiiiiiiiiiiiid8:completei1e10:downloadedi2e10:incompletei3eeee
250//! ```
251//!
252//! And represented as a json:
253//!
254//! ```json
255//! {
256//!     "files": {
257//!        "iiiiiiiiiiiiiiiiiiii": {
258//!           "complete": 1,
259//!           "downloaded": 2,
260//!           "incomplete": 3
261//!        }
262//!     }
263//! }
264//! ```
265//!
266//! Where the `files` key contains a dictionary of dictionaries. The first
267//! dictionary key is the `info_hash` of the torrent (`iiiiiiiiiiiiiiiiiiii` in
268//! the example). The second level dictionary contains the
269//! [swarm metadata](torrust_tracker_primitives::swarm_metadata::SwarmMetadata) for that torrent.
270//!
271//! If you save the response as a file and you open it with a program that
272//! can handle binary data you would see:
273//!
274//! ```text
275//! 00000000: 6435 3a66 696c 6573 6432 303a 6969 6969  d5:filesd20:iiii
276//! 00000010: 6969 6969 6969 6969 6969 6969 6969 6969  iiiiiiiiiiiiiiii
277//! 00000020: 6438 3a63 6f6d 706c 6574 6569 3165 3130  d8:completei1e10
278//! 00000030: 3a64 6f77 6e6c 6f61 6465 6469 3265 3130  :downloadedi2e10
279//! 00000040: 3a69 6e63 6f6d 706c 6574 6569 3365 6565  :incompletei3eee
280//! 00000050: 65                                       e
281//! ```
282//!
283//! **Protocol**
284//!
285//! If you want to know more about the `scrape` request:
286//!
287//! - [BEP 48. Tracker Protocol Extension: Scrape](https://www.bittorrent.org/beps/bep_0048.html)
288//! - [Vuze scrape docs](https://wiki.vuze.com/w/Scrape)
289//!
290//! ## Versioning
291//!
292//! Right not there is only version `v1`. The HTTP tracker implements BEPS:
293//!
294//! - [BEP 03. The `BitTorrent` Protocol Specification](https://www.bittorrent.org/beps/bep_0003.html)
295//! - [BEP 07. IPv6 Tracker Extension](https://www.bittorrent.org/beps/bep_0007.html)
296//! - [BEP 23. Tracker Returns Compact Peer Lists](https://www.bittorrent.org/beps/bep_0023.html)
297//! - [BEP 48. Tracker Protocol Extension: Scrape](https://www.bittorrent.org/beps/bep_0048.html)
298//!
299//! In the future there could be a `v2` that implements new BEPS with breaking
300//! changes.
301//!
302//! ## Links
303//!
304//! - [Bencode](https://en.wikipedia.org/wiki/Bencode).
305//! - [Bencode to Json Online converter](https://chocobo1.github.io/bencode_online).
306use serde::{Deserialize, Serialize};
307
308pub mod percent_encoding;
309pub mod server;
310pub mod v1;
311
312pub const HTTP_TRACKER_LOG_TARGET: &str = "HTTP TRACKER";
313
314/// The version of the HTTP tracker.
315#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Debug)]
316pub enum Version {
317    /// The `v1` version of the HTTP tracker.
318    V1,
319}