//! UDP Tracker.
//!
//! This module contains the UDP tracker implementation.
//!
//! The UDP tracker is a simple UDP server that responds to these requests:
//!
//! - `Connect`: used to get a connection ID which must be provided on each
//! request in order to avoid spoofing the source address of the UDP packets.
//! - `Announce`: used to announce the presence of a peer to the tracker.
//! - `Scrape`: used to get information about a torrent.
//!
//! It was introduced in [BEP 15. UDP Tracker Protocol for `BitTorrent`](https://www.bittorrent.org/beps/bep_0015.html)
//! as an alternative to the [HTTP tracker](https://www.bittorrent.org/beps/bep_0003.html).
//! The UDP tracker is more efficient than the HTTP tracker because it uses UDP
//! instead of TCP.
//!
//! Refer to the [`bit_torrent`](crate::shared::bit_torrent) module for more
//! information about the `BitTorrent` protocol.
//!
//! Refer to [BEP 15. UDP Tracker Protocol for `BitTorrent`](https://www.bittorrent.org/beps/bep_0015.html)
//! and to [BEP 41. UDP Tracker Protocol Extensions](https://www.bittorrent.org/beps/bep_0041.html)
//! for more information about the UDP tracker protocol.
//!
//! > **NOTICE**: [BEP-41](https://www.bittorrent.org/beps/bep_0041.html) is not
//! > implemented yet.
//!
//! > **NOTICE**: we are using the [`aquatic_udp_protocol`](https://crates.io/crates/aquatic_udp_protocol)
//! > crate so requests and responses are handled by it.
//!
//! > **NOTICE**: all values are send in network byte order ([big endian](https://en.wikipedia.org/wiki/Endianness)).
//!
//! ## Table of Contents
//!
//! - [Actions](#actions)
//! - [Connect](#connect)
//! - [Connect Request](#connect-request)
//! - [Connect Response](#connect-response)
//! - [Announce](#announce)
//! - [Announce Request](#announce-request)
//! - [Announce Response](#announce-response)
//! - [Scrape](#scrape)
//! - [Scrape Request](#scrape-request)
//! - [Scrape Response](#scrape-response)
//! - [Errors](#errors)
//! - [Extensions](#extensions)
//! - [Links](#links)
//! - [Credits](#credits)
//!
//! ## Actions
//!
//! Requests are sent to the tracker using UDP packets. The UDP tracker protocol
//! is designed to be as simple as possible. It uses a single UDP port and
//! supports only three types of requests: `Connect`, `Announce` and `Scrape`.
//!
//! Request are parsed from UDP packets using the [`aquatic_udp_protocol`](https://crates.io/crates/aquatic_udp_protocol)
//! crate and then handled by the [`Tracker`](crate::core::Tracker) struct.
//! And then the response is also build using the [`aquatic_udp_protocol`](https://crates.io/crates/aquatic_udp_protocol)
//! and converted to a UDP packet.
//!
//! ```text
//! UDP packet -> Aquatic Struct Request -> [Torrust Struct Request] -> Tracker -> Aquatic Struct Response -> UDP packet
//! ```
//!
//! ### Connect
//!
//! `Connect` requests are used to get a connection ID which must be provided on
//! each request in order to avoid spoofing the source address of the UDP.
//!
//! The connection ID is a random 64-bit integer that is used to identify the
//! client. It is used to prevent spoofing of the source address of the UDP
//! packets. Before announcing or scraping, you have to obtain a connection ID.
//!
//! The connection ID is generated by the tracker and sent back to the client's
//! IP address. Only the client using that IP can receive the response, so the
//! tracker can be sure that the client is the one who sent the request. If the
//! client's IP was spoofed the tracker will send the response to the wrong
//! client and the client will not receive it.
//!
//! The reason why the UDP tracker protocol needs a connection ID to avoid IP
//! spoofing can be explained as follows:
//!
//! 1. No connection state: Unlike TCP, UDP is a connectionless protocol,
//! meaning that it does not establish a connection between two endpoints before
//! exchanging data. As a result, it is more susceptible to IP spoofing, where
//! an attacker sends packets with a forged source IP address, tricking the
//! receiver into believing that they are coming from a legitimate source.
//!
//! 2. Mitigating IP spoofing: To mitigate IP spoofing in the UDP tracker
//! protocol, a connection ID is used. When a client wants to interact with a
//! tracker, it sends a "connect" request to the tracker, which, in turn,
//! responds with a unique connection ID. This connection ID must be included in
//! all subsequent requests from the client to the tracker.
//!
//! 3. Validating requests: By requiring the connection ID, the tracker can
//! verify that the requests are coming from the same client that initially sent
//! the "connect" request. If an attacker attempts to spoof the client's IP
//! address, they would also need to know the valid connection ID to be accepted
//! by the tracker. This makes it significantly more challenging for an attacker
//! to spoof IP addresses and disrupt the P2P network.
//!
//! There are different ways to generate a connection ID. The most common way is
//! to generate a time bound secret. The secret is generated using a time based
//! algorithm and it is valid for a certain amount of time.
//!
//! ```text
//! connection ID = hash(client IP + current time slot + secret seed)
//! ```
//!
//! The BEP-15 recommends a two-minute time slot. Refer to [`connection_cookie`]
//! for more information about the connection ID generation with this method.
//!
//! #### Connect Request
//!
//! **Connect request (UDP packet)**
//!
//! Offset | Type/Size | Name | Description | Hex | Decimal
//! -------|-------------------|------------------|-------------------------------------------------|-----------------------------|-----------------
//! 0 | [`i64`](std::i64) | `protocol_id` | Magic constant that will identify the protocol. | `0x00_00_04_17_27_10_19_80` | `4497486125440`
//! 8 | [`i32`](std::i32) | `action` | Action identifying the connect request. | `0x00_00_00_00` | `0`
//! 12 | [`i32`](std::i32) | `transaction_id` | Randomly generated by the client. | `0x34_FA_A1_F9` | `-888840697`
//!
//! **Sample connect request (UDP packet)**
//!
//! UDP packet bytes:
//!
//! ```text
//! Offset: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
//! Decimal: [ 0, 0, 4, 23, 39, 16, 25, 128, 0, 0, 0, 0, 203, 5, 94, 7]
//! Hex: [0x00, 0x00, 0x04, 0x17, 0x27, 0x10, 0x19, 0x80, 0x00, 0x00, 0x00, 0x00, 0xCB, 0x05, 0x5E, 0x07]
//! Param: [<------------- protocol_id ------------------>,<------- action ------>,<--- transaction_id -->]
//! ```
//!
//! UDP packet fields:
//!
//! Offset | Type/Size | Name | Bytes Dec (Big Endian) | Hex | Decimal
//! -------|-------------------|------------------|--------------------------------|-----------------------------|----------------
//! 0 | [`i64`](std::i64) | `protocol_id` | [0, 0, 4, 23, 39, 16, 25, 128] | `0x00_00_04_17_27_10_19_80` | `4497486125440`
//! 4 | [`i32`](std::i32) | `action` | [0, 0, 0, 0] | `0x00_00_00_00` | `0`
//! 8 | [`i32`](std::i32) | `transaction_id` | [35, 63, 226, 1] | `0xCB_05_5E_07` | `-888840697`
//!
//! **Connect request (parsed struct)**
//!
//! After parsing the UDP packet, the [`ConnectRequest`](aquatic_udp_protocol::request::ConnectRequest)
//! request struct will look like this:
//!
//! Field | Type | Example
//! -----------------|----------------------------------------------------------------|-------------
//! `transaction_id` | [`TransactionId`](aquatic_udp_protocol::common::TransactionId) | `1950635409`
//!
//! #### Connect Response
//!
//! **Connect response (UDP packet)**
//!
//! Offset | Type/Size | Name | Description | Hex | Decimal
//! -------|-------------------|------------------|-------------------------------------------------------|-----------------------------|-----------------------
//! 0 | [`i64`](std::i32) | `action` | Action identifying the connect request | `0x00_00_00_00` | `0`
//! 4 | [`i32`](std::i32) | `transaction_id` | Must match the `transaction_id` sent from the client. | `0xCB_05_5E_07` | `-888840697`
//! 8 | [`i32`](std::i64) | `connection_id` | Generated by the tracker to authenticate the client. | `0xC5_58_7C_09_08_48_D8_37` | `-4226491872051668937`
//!
//! > **NOTICE**: the `connection_id` is used when further information is
//! > exchanged with the tracker, to identify the client. This `connection_id` can
//! > be reused for multiple requests, but if it's cached for too long, it will
//! > not be valid anymore.
//!
//! > **NOTICE**: `Hex` column is a signed 2's complement.
//!
//! **Sample connect response (UDP packet)**
//!
//! UDP packet bytes:
//!
//! ```text
//! Offset: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
//! Decimal: [ 0, 0, 0, 0, 203, 5, 94, 7, 197, 88, 124, 9, 8, 72, 216, 55]
//! Hex: [0x00, 0x00, 0x00, 0x00, 0xCB, 0x05, 0x5E, 0x07, 0xC5, 0x58, 0x7C, 0x09, 0x08, 0x48, 0xD8, 0x37]
//! Param: [<------ action ------>,<-- transaction_id --->,<--------------- connection_id --------------->]
//! ```
//!
//! UDP packet fields:
//!
//! Offset | Type/Size | Name | Bytes (Big Endian) | Hex | Decimal
//! -------|-------------------|------------------|-----------------------------------|------------------------------|-----------------------
//! 0 | [`i64`](std::i32) | `action` | [0, 0, 0, 0] | `0x00_00_00_00` | `0`
//! 4 | [`i64`](std::i32) | `transaction_id` | [203, 5, 94, 7] | `0xCB_05_5E_07` | `-888840697`
//! 8 | [`i64`](std::i64) | `connection_id` | [197, 88, 124, 9, 8, 72, 216, 55] | `0xC5_58_7C_09_08_48_D8_37` | `-4226491872051668937`
//!
//! > **NOTICE**: `Hex` column is a signed 2's complement.
//!
//! **Connect response (struct)**
//!
//! Before building the UDP packet, the [`ConnectResponse`](aquatic_udp_protocol::response::ConnectResponse)
//! struct will look like this:
//!
//! Field | Type | Example
//! -----------------|----------------------------------------------------------------|-------------------------
//! `connection_id` | [`ConnectionId`](aquatic_udp_protocol::common::ConnectionId) | `-4226491872051668937`
//! `transaction_id` | [`TransactionId`](aquatic_udp_protocol::common::TransactionId) | `-888840697`
//!
//! **Connect specification**
//!
//! Original specification in [BEP 15. UDP Tracker Protocol for `BitTorrent`](https://www.bittorrent.org/beps/bep_0015.html).
//!
//! ### Announce
//!
//! `Announce` requests are used to announce the presence of a peer to the
//! tracker. The tracker responds with a list of peers that are also downloading
//! the same torrent. A "swarm" is a group of peers that are downloading the
//! same torrent.
//!
//! #### Announce Request
//!
//! **Announce request (UDP packet)**
//!
//! Offset | Type/Size | Name | Description | Hex | Decimal
//! -------|-------------------|------------------|--------------------------------------------------------------|-----------------------------------------------------------------|----------------------------------------------------------
//! 0 | [`i64`](std::i64) | `connection_id` | The connection id acquired from establishing the connection. | `0xC5_58_7C_09_08_48_D8_37` | `-4226491872051668937`
//! 8 | [`i32`](std::i32) | `action` | Action for announce request. | `0x00_00_00_01` | `1`
//! 12 | [`i32`](std::i32) | `transaction_id` | Randomly generated by the client. | `0xA2_F9_54_48` | `-1560718264`
//! 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`
//! 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`
//! 56 | [`i64`](std::i64) | `downloaded` | The number of bytes the peer has downloaded so far. | `0x00_00_00_00_00_00_00_00` | `0`
//! 64 | [`i64`](std::i64) | `left` | The number of bytes left to download by the peer. | `0x00_00_00_00_00_00_00_00` | `0`
//! 72 | [`i64`](std::i64) | `uploaded` | The number of bytes the peer has uploaded so far. | `0x00_00_00_00_00_00_00_00` | `0`
//! 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
//! 84 | [`i32`](std::i32) | `IP address` | The peer IP. Ignored by the tracker. It uses the Sender's IP.| `0x00_00_00_00` | `0`
//! 88 | [`i32`](std::i32) | `key` | A unique key that is randomized by the client. | `0xEF_34_95_D6` | `-281766442`
//! 92 | [`i32`](std::i32) | `num_want` | The maximum number of peers the peer wants in the response. | `0x00_00_00_C8` | `200`
//! 96 | [`i16`](std::i16) | `port` | The port the peer is listening on. | `0x44_8C` | `17548`
//!
//! **Peer IP address**
//!
//! The peer IP address is always ignored by the tracker. It uses the sender's
//! IP address.
//!
//! _"Do note that most trackers will only honor the IP address field under
//! limited circumstances."_ ([BEP 15](https://www.bittorrent.org/beps/bep_0015.html)).
//!
//! Although not supported by this tracker a UDP tracker can use the IP address
//! provided by the peer in the announce request under specific circumstances
//! when it cannot rely on the source IP address of the incoming request. These
//! circumstances might include:
//!
//! 1. Network Address Translation (NAT): In cases where a peer is behind a NAT,
//! the private IP address of the peer is not directly routable over the
//! internet. The NAT device translates the private IP address to a public one
//! when sending packets to the tracker. The public IP address is what the
//! tracker sees as the source IP of the incoming request. However, if the peer
//! provides its private IP address in the announce request, the tracker can use
//! this information to facilitate communication between peers in the same
//! private network.
//!
//! 2. Proxy or VPN usage: If a peer uses a proxy or VPN service to connect to
//! the tracker, the source IP address seen by the tracker will be the one
//! assigned by the proxy or VPN server. In this case, if the peer provides its
//! actual IP address in the announce request, the tracker can use it to
//! establish a direct connection with other peers, bypassing the proxy or VPN
//! server. This might improve performance or help in cases where some peers
//! cannot connect to the proxy or VPN server.
//!
//! 3. Tracker is behind a NAT, firewall, proxy, VPN, or load balancer: In cases
//! where the tracker is behind a NAT, firewall, proxy, VPN, or load balancer,
//! the source IP address of the incoming request will be the public IP address
//! of the NAT, firewall, proxy, VPN, or load balancer. If the peer provides its
//! private IP address in the announce request, the tracker can use this
//! information to establish a direct connection with the peer.
//!
//! It's important to note that using the provided IP address can pose security
//! risks, as malicious peers might spoof their IP addresses in the announce
//! request to perform various types of attacks.
//!
//! > **NOTICE**: The current tracker behavior is to ignore the IP address
//! > provided by the peer, and use the source IP address of the incoming request,
//! > when the tracker is not running behind a proxy, and to use the right-most IP
//! > address in the `X-Forwarded-For` header when the tracker is running behind a
//! > proxy.
//!
//! > **NOTICE**: The tracker also changes the peer IP address to the tracker
//! > external IP when the peer is using a loopback IP address.
//!
//! **Sample announce request (UDP packet)**
//!
//! Some values used in the sample request:
//!
//! - Infohash: `0x03840548643AF2A7B63A9F5CBCA348BC7150CA3A`
//! - Peer ID: `0x2D7142343431302D2953647E646534784D703644`
//!
//! UDP packet bytes:
//!
//! ```text
//! 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]
//! 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]
//! 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]
//! Param: [<--------------- connection_id --------------->,<--------- action ---->,<-- transaction_id --->,<--------------------------------------------------------- info_hash ------------------------------------------------->,<---------------------------------------------- peer_id -------------------------------------------------------------->,<------------------- downloaded -------------->,<-------------------- left ------------------->,<---------------- uploaded ------------------->,<-------- event ------>,<----- IP address ---->,<--------- key ------->,<------ num_want ----->,<-- port --><---- BEP 41 --->]
//! ```
//!
//! UDP packet fields:
//!
//! Offset | Type/Size | Name | Bytes Dec (Big Endian) | Hex | Decimal
//! -------|-------------------|-------------------|--------------------------------------------------------------------------|-----------------------------------------------------------------|----------------------------------------------------
//! 0 | [`i64`](std::i64) | `connection_id` | `[197,88,124,9,8,72,216,55]` | `0xC5_58_7C_09_08_48_D8_37` | `-4226491872051668937`
//! 8 | [`i32`](std::i32) | `action` | `[0,0,0,1]` | `0x00_00_00_01` | `1`
//! 12 | [`i32`](std::i32) | `transaction_id` | `[162,249,84,72]` | `0xA2_F9_54_48` | `-1560718264`
//! 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`
//! 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`
//! 56 | [`i64`](std::i64) | `downloaded` | `[0,0,0,0,0,0,0,0]` | `0x00_00_00_00_00_00_00_00` | `0`
//! 64 | [`i64`](std::i64) | `left` | `[0,0,0,0,0,0,0,0]` | `0x00_00_00_00_00_00_00_00` | `0`
//! 72 | [`i64`](std::i64) | `uploaded` | `[0,0,0,0,0,0,0,0]` | `0x00_00_00_00_00_00_00_00` | `0`
//! 80 | [`i32`](std::i32) | `event` | `[0,0,0,2]` | `0x00_00_00_02` | `2` (`Started`)
//! 84 | [`i32`](std::i32) | `IP address` | `[0,0,0,0]` | `0x00_00_00_00` | `0`
//! 88 | [`i32`](std::i32) | `key` | `[239,52,149,214]` | `0xEF_34_95_D6` | `-281766442`
//! 92 | [`i32`](std::i32) | `num_want` | `[0,0,0,200]` | `0x00_00_00_C8` | `200`
//! 96 | [`i16`](std::i16) | `port` | `[8,140]` | `0x44_8C` | `17548`
//! 98 | 1 byte | `Option-Type` | `[2]` | `0x02` | `2`
//! 99 | 2 byte | `Length Byte` | `[1,47]` | `0x01_2F` | `303`
//! 101 | N bytes | | | |
//!
//! > **NOTICE**: bytes after offset 98 are part of the [BEP-41. UDP Tracker Protocol Extensions](https://www.bittorrent.org/beps/bep_0041.html).
//! > There are three options defined for byte 98: `0x0` (`EndOfOptions`), `0x1` (`NOP`) and `0x2` (`URLData`).
//!
//! > **NOTICE**: `num_want` is being ignored by the tracker. Refer to
//! > [issue 262](https://github.com/torrust/torrust-tracker/issues/262) for more
//! > information.
//!
//! **Announce request (parsed struct)**
//!
//! After parsing the UDP packet, the [`AnnounceRequest`](aquatic_udp_protocol::request::AnnounceRequest)
//! struct will contain the following fields:
//!
//! Field | Type | Example
//! -------------------|---------------------------------------------------------------- |--------------
//! `connection_id` | [`ConnectionId`](aquatic_udp_protocol::common::ConnectionId) | `-4226491872051668937`
//! `transaction_id` | [`TransactionId`](aquatic_udp_protocol::common::TransactionId) | `-1560718264`
//! `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]`
//! `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]`
//! `bytes_downloaded` | [`NumberOfBytes`](aquatic_udp_protocol::common::NumberOfBytes) | `0`
//! `bytes_uploaded` | [`TransactionId`](aquatic_udp_protocol::common::NumberOfBytes) | `0`
//! `event` | [`AnnounceEvent`](aquatic_udp_protocol::request::AnnounceEvent) | `Started`
//! `ip_address` | [`Ipv4Addr`](aquatic_udp_protocol::common::ConnectionId) | `None`
//! `peers_wanted` | [`NumberOfPeers`](aquatic_udp_protocol::common::NumberOfPeers) | `200`
//! `port` | [`Port`](aquatic_udp_protocol::common::Port) | `17548`
//!
//! > **NOTICE**: the `peers_wanted` field is the `num_want` field in the UDP
//! > packet.
//!
//! We are using a wrapper struct for the aquatic [`AnnounceRequest`](aquatic_udp_protocol::request::AnnounceRequest)
//! struct, because we have our internal [`InfoHash`](torrust_tracker_primitives::info_hash::InfoHash)
//! struct.
//!
//! ```text
//! pub struct AnnounceWrapper {
//! pub announce_request: AnnounceRequest, // aquatic
//! pub info_hash: InfoHash, // our own
//! }
//! ```
//!
//! #### Announce Response
//!
//! **Announce response (UDP packet)**
//!
//! Offset | Type/Size | Name | Description | Hex | Decimal
//! -----------|-------------------|------------------|---------------------------------------------------------------------------------|-----------------|----------------------------
//! 0 | [`i32`](std::i32) | `action` | The action this is a reply to. | `0x00_00_00_01` | `1`: announce; `3`: error
//! 4 | [`i32`](std::i32) | `transaction_id` | Must match the `transaction_id` sent in the announce request. | `0x00_00_00_00` | `0`
//! 8 | [`i32`](std::i32) | `interval` | The number of seconds the peer should wait until re-announcing itself. | `0x00_00_00_00` | `0`
//! 12 | [`i32`](std::i32) | `leechers` | The number of peers in the swarm that has not finished downloading. | `0x00_00_00_00` | `0`
//! 16 | [`i32`](std::i32) | `seeders` | The number of peers in the swarm that has finished downloading and are seeding. | `0x00_00_00_00` | `0`
//! | | | | |
//! 20 + 6 * n | [`i32`](std::i32) | `IP address` | The IP of a peer in the swarm. | `0x69_69_69_69` | `1768515945`
//! 24 + 6 * n | [`i16`](std::i16) | `TCP port` | The peer's listen port. | `0x44_8C` | `17548`
//! 20 + 6 * N | | | | |
//!
//! > **NOTICE**: `Hex` column is a signed 2's complement.
//!
//! > **NOTICE**: `IP address` should always be set to 0 when the peer is using
//! > `IPv6`.
//!
//! **Sample announce response (UDP packet)**
//!
//! UDP packet bytes (fixed part):
//!
//! ```text
//! Offset: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
//! Decimal: [ 0, 0, 0, 1, 162, 249, 84, 72, 0, 0, 0, 120, 0, 0, 0, 0, 0, 0, 0, 1]
//! Hex: [ 0x00, 0x00, 0x00, 0x01, 0xA2, 0xF9, 0x54, 0x48, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]
//! Param: [<------- action ------>,<-- transaction_id --->,<----- interval ------>,<----- leechers ------>,<------ seeders ------>]
//! ```
//!
//! UDP packet fields (fixed part):
//!
//! Offset | Type/Size | Name | Bytes (Big Endian) | Hex | Decimal
//! -----------|-------------------|------------------|---------------------|-----------------|----------------------------
//! 0 | [`i32`](std::i32) | `action` | `[0, 0, 0, 0]` | `0x00_00_00_01` | `1`: announce; `3`: error
//! 4 | [`i32`](std::i32) | `transaction_id` | `[162,249,84,72]` | `0xA2_F9_54_48` | `-1560718264`
//! 8 | [`i32`](std::i32) | `interval` | `[0,0,0,120]` | `0x00_00_00_78` | `120`
//! 12 | [`i32`](std::i32) | `leechers` | `[0, 0, 0, 0]` | `0x00_00_00_00` | `0`
//! 16 | [`i32`](std::i32) | `seeders` | `[0, 0, 0, 1]` | `0x00_00_00_01` | `1`
//!
//! This is the fixed part of the packet. After the fixed part there is
//! dynamically generated data with the list of peers in the swarm. The list may
//! include `IPv4` or `IPv6` peers, depending on the address family of the
//! underlying UDP packet. I.e. packets from a v4 address use the v4 format,
//! those from a v6 address use the v6 format.
//!
//! UDP packet bytes (`IPv4` peer list):
//!
//! ```text
//! Offset: [ 20, 21, 22, 23, 24, 25]
//! Decimal: [ 105, 105, 105, 105, 08, 140]
//! Hex: [ 0x69, 0x69, 0x69, 0x69, 0x44, 0x8C]
//! Param: [<----- IP address ---->,<-TCP port>]
//! ```
//!
//! > **NOTICE**: there are 6 bytes per peer (4 bytes for the `IPv4` address and
//! > 2 bytes for the TCP port).
//!
//! UDP packet fields (`IPv4` peer list):
//!
//! Offset | Type/Size | Name | Bytes (Big Endian) | Hex | Decimal
//! ---------|-------------------|--------------|---------------------|-----------------|----------------------------
//! 20 + 6*n | [`i32`](std::i32) | `IP address` | `[105,105,105,105]` | `0x69_69_69_69` | `1768515945`
//! 24 + 6*n | [`i16`](std::i16) | `TCP port` | `[8,140]` | `0x44_8C` | `17548`
//! 20 + 6*N | | | | |
//!
//! UDP packet bytes (`IPv6` peer list):
//!
//! ```text
//! Offset: [ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37]
//! Decimal: [ 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 08, 140]
//! Hex: [ 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x44, 0x8C]
//! Param: [<-------------------------------------------- IP address ------------------------------------->,<-TCP port>]
//! ```
//!
//! > **NOTICE**: there are 18 bytes per peer (16 bytes for the `IPv6` address and
//! > 2 bytes for the TCP port).
//!
//! UDP packet fields (`IPv6` peer list):
//!
//! Offset | Type/Size | Name | Bytes (Big Endian) | Hex | Decimal
//! ----------|---------------------|--------------|---------------------------------------------------------------------|-----------------------------------------------------|-------------------------------------------
//! 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`
//! 24 + 18*n | [`i16`](std::i16) | `TCP port` | `[8,140]` | `0x44_8C` | `17548`
//! 20 + 18*N | | | | |
//!
//! > **NOTICE**: `Hex` column is a signed 2's complement.
//!
//! > **NOTICE**: the peer list does not include the peer that sent the announce
//! > request.
//!
//! **Announce response (struct)**
//!
//! The [`AnnounceResponse`](aquatic_udp_protocol::response::AnnounceResponse)
//! struct will have the following fields:
//!
//! Field | Type | Example
//! --------------------|------------------------------------------------------------------------|--------------
//! `transaction_id` | [`TransactionId`](aquatic_udp_protocol::common::TransactionId) | `-1560718264`
//! `announce_interval` | [`AnnounceInterval`](aquatic_udp_protocol::common::AnnounceInterval) | `120`
//! `leechers` | [`NumberOfPeers`](aquatic_udp_protocol::common::NumberOfPeers) | `0`
//! `seeders` | [`NumberOfPeers`](aquatic_udp_protocol::common::NumberOfPeers) | `1`
//! `peers` | Vector of [`ResponsePeer`](aquatic_udp_protocol::common::ResponsePeer) | `[]`
//!
//! **Announce specification**
//!
//! Original specification in [BEP 15. UDP Tracker Protocol for `BitTorrent`](https://www.bittorrent.org/beps/bep_0015.html).
//!
//! ### Scrape
//!
//! The `scrape` request allows a peer to get [swarm metadata](torrust_tracker_primitives::swarm_metadata::SwarmMetadata)
//! for multiple torrents at the same time.
//!
//! The response contains the [swarm metadata](torrust_tracker_primitives::swarm_metadata::SwarmMetadata)
//! for that torrent:
//!
//! - [complete](torrust_tracker_primitives::swarm_metadata::SwarmMetadata::complete)
//! - [downloaded](torrust_tracker_primitives::swarm_metadata::SwarmMetadata::downloaded)
//! - [incomplete](torrust_tracker_primitives::swarm_metadata::SwarmMetadata::incomplete)
//!
//! > **NOTICE**: up to about 74 torrents can be scraped at once. A full scrape
//! > can't be done with this protocol. This is a limitation of the UDP protocol.
//! > Defined with a hardcoded const [`MAX_SCRAPE_TORRENTS`](crate::shared::bit_torrent::common::MAX_SCRAPE_TORRENTS).
//! > Refer to [issue 262](https://github.com/torrust/torrust-tracker/issues/262)
//! > for more information about this limitation.
//!
//! #### Scrape Request
//!
//! **Scrape request (UDP packet)**
//!
//! Offset | Type/Size | Name | Description | Hex | Decimal
//! ----------|-------------------|------------------|------------------------------------------------------------------------|-----------------------------------------------------------------|--------------------------------------------------
//! 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`
//! 8 | [`i32`](std::i32) | `action` | Action identifying the scrape request | `0x00_00_00_02` | `2` (`Scrape`)
//! 12 | [`i32`](std::i32) | `transaction_id` | Randomly generated by the client. | `0xA2_F9_54_48` | `-1560718264`
//! 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`
//! 16 + 20*N | | | |
//!
//! The last field (`info_hash`) is repeated for each torrent being scraped.
//!
//! Dynamic part of the UDP packet:
//!
//! Offset | Type/Size | Name | Description | Hex | Decimal
//! ----------|-------------------|-------------|--------------------------------------------|-----------------------------------------------------------------|---------------------------------------------------
//! 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`
//!
//! **Sample scrape request (UDP packet)**
//!
//! UDP packet bytes (fixed part):
//!
//! ```text
//! 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]
//! 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]
//! 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]
//! Param: [<--------------- connection_id --------------->,<--------- action ---->,<-- transaction_id --->,<--------------------------------------------------------- info_hash ------------------------------------------------->]
//! ```
//!
//! UDP packet bytes (infohash list):
//!
//! ```text
//! Offset: [ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35]
//! Decimal: [ 3, 132, 5, 72, 100, 58, 242, 167, 182, 58, 159, 92, 188, 163, 72, 188, 113, 80, 202, 58]
//! Hex: [ 0x03, 0x84, 0x05, 0x48, 0x64, 0x3A, 0xF2, 0xA7, 0xB6, 0x3A, 0x9F, 0x5C, 0xBC, 0xA3, 0x48, 0xBC, 0x71, 0x50, 0xCA, 0x3A]
//! Param: [<--------------------------------------------------------- info_hash ------------------------------------------------->]
//! ```
//!
//! UDP packet fields:
//!
//! Offset | Type/Size | Name | Bytes Dec (Big Endian) | Hex | Decimal
//! -------|-------------------|------------------|--------------------------------------------------------------------------|-----------------------------------------------------------------|--------------------------------------------------
//! 0 | [`i64`](std::i64) | `connection_id` | `[197,88,124,9,8,72,216,55]` | `0xC5_58_7C_09_08_48_D8_37` | `-4226491872051668937`
//! 4 | [`i32`](std::i32) | `action` | `[0, 0, 0, 2]` | `0x00_00_00_02` | `2` (`Scrape`)
//! 8 | [`i32`](std::i32) | `transaction_id` | `[162,249,84,72]` | `0xA2_F9_54_48` | `-1560718264`
//! 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`
//!
//! **Scrape request (parsed struct)**
//!
//! After parsing the UDP packet, the [`ScrapeRequest`](aquatic_udp_protocol::request::ScrapeRequest)
//! struct will look like this:
//!
//! Field | Type | Example
//! -----------------|----------------------------------------------------------------|----------------------------------------------------------------------------
//! `connection_id` | [`ConnectionId`](aquatic_udp_protocol::common::ConnectionId) | `-4226491872051668937`
//! `transaction_id` | [`TransactionId`](aquatic_udp_protocol::common::TransactionId) | `-1560718264`
//! `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]]`
//!
//! #### Scrape Response
//!
//! **Scrape response (UDP packet)**
//!
//! Offset | Type/Size | Name (BEP15 or libtorrent) | Description | Hex | Decimal
//! ----------|-------------------|-----------------------------|-------------------------------------------------------|-----------------|-----------------
//! 0 | [`i32`](std::i32) | `action` | Action identifying the connect request | `0x00_00_00_00` | `2` (`Scrape`)
//! 4 | [`i32`](std::i32) | `transaction_id` | Must match the `transaction_id` sent from the client. | `0xA2_F9_54_48` | `-1560718264`
//! 8 + 12*n | [`i32`](std::i32) | `seeders` or `complete` | The current number of connected seeds. | `0x00_00_00_00` | `0`
//! 12 + 12*n | [`i32`](std::i32) | `completed` or `downloaded` | The number of times this torrent has been downloaded. | `0x00_00_00_00` | `0`
//! 16 + 12*n | [`i32`](std::i32) | `leechers` or `incomplete` | The current number of connected leechers. | `0x00_00_00_00` | `0`
//! 8 + 12*N | | | | |
//!
//! > **NOTICE**: `Hex` column is a signed 2's complement.
//!
//! Dynamic part of the UDP packet:
//!
//! Offset | Type/Size | Name (BEP15 or libtorrent) | Description | Hex | Decimal
//! ----------|-------------------|-----------------------------|-------------------------------------------------------|-----------------|-----------------
//! 8 + 12*n | [`i32`](std::i32) | `seeders` or `complete` | The current number of connected seeds. | `0x00_00_00_00` | `0`
//! 12 + 12*n | [`i32`](std::i32) | `completed` or `downloaded` | The number of times this torrent has been downloaded. | `0x00_00_00_00` | `0`
//! 16 + 12*n | [`i32`](std::i32) | `leechers` or `incomplete` | The current number of connected leechers. | `0x00_00_00_00` | `0`
//! 8 + 12*N | | | | |
//!
//! For each info hash in the request there will be 3 32-bit integers (12 bytes)
//! in the response with the number of seeders, leechers and downloads.
//!
//! **Sample scrape response (UDP packet)**
//!
//! UDP packet bytes:
//!
//! ```text
//! Offset: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
//! Decimal: [ 0, 0, 0, 0, 203, 5, 94, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
//! Hex: [0x00, 0x00, 0x00, 0x00, 0xCB, 0x05, 0x5E, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
//! Param: [<------ action ------>,<-- transaction_id --->,<------ seeders ------>,<----- completed ----->,<------ leechers ----->]
//! ```
//!
//! UDP packet fields:
//!
//! Offset | Type/Size | Name | Bytes (Big Endian) | Hex | Decimal
//! -------|-------------------|------------------|--------------------|------------------|----------------
//! 0 | [`i32`](std::i32) | `action` | [0, 0, 0, 2] | `0x00_00_00_02` | `2` (`Scrape`)
//! 4 | [`i32`](std::i32) | `transaction_id` | [203, 5, 94, 7] | `0xA2_F9_54_48` | `-1560718264`
//! 8 | [`i32`](std::i32) | `seeders` | [0, 0, 0, 0] | `0x00_00_00_00` | `0`
//! 12 | [`i32`](std::i32) | `completed` | [0, 0, 0, 0] | `0x00_00_00_00` | `0`
//! 16 | [`i32`](std::i32) | `leechers` | [0, 0, 0, 0] | `0x00_00_00_00` | `0`
//!
//! > **NOTICE**: `Hex` column is a signed 2's complement.
//!
//! **Scrape response (struct)**
//!
//! Before building the UDP packet, the [`ScrapeResponse`](aquatic_udp_protocol::response::ScrapeResponse)
//! struct will look like this:
//!
//! Field | Type | Example
//! -----------------|-------------------------------------------------------------------------------------------------|---------------
//! `transaction_id` | [`TransactionId`](aquatic_udp_protocol::common::TransactionId) | `-1560718264`
//! `torrent_stats` | Vector of [`TorrentScrapeStatistics`](aquatic_udp_protocol::response::TorrentScrapeStatistics) | `[]`
//!
//! **Scrape specification**
//!
//! Original specification in [BEP 15. UDP Tracker Protocol for `BitTorrent`](https://www.bittorrent.org/beps/bep_0015.html).
//!
//! ## Errors
//!
//! ### Error Response
//!
//! **Error response (UDP packet)**
//!
//! Offset | Type/Size | Name | Description | Hex | Decimal
//! -------|-------------------|------------------|-------------------------------------------------------|-----------------------------|-----------------------
//! 0 | [`i32`](std::i32) | `action` | Action identifying the error response. | `0x00_00_00_03` | `3`
//! 4 | [`i32`](std::i32) | `transaction_id` | Must match the `transaction_id` sent from the client. | `0xCB_05_5E_07` | `-888840697`
//! 8 | N Bytes | `error_string` | Error description. | |
//!
//! ## Extensions
//!
//! Extensions described in [BEP 41. UDP Tracker Protocol Extensions](https://www.bittorrent.org/beps/bep_0041.html)
//! are not supported yet.
//!
//! ## Links
//!
//! - [BEP 15. UDP Tracker Protocol for `BitTorrent`](https://www.bittorrent.org/beps/bep_0015.html).
//! - [BEP 41. UDP Tracker Protocol Extensions](https://www.bittorrent.org/beps/bep_0041.html).
//! - [libtorrent - Bittorrent UDP-tracker protocol extension](https://www.rasterbar.com/products/libtorrent/udp_tracker_protocol.html).
//! - [XBTT Tracker. UDP tracker protocol](https://xbtt.sourceforge.net/udp_tracker_protocol.html).
//! - [Wikipedia: UDP tracker](https://en.wikipedia.org/wiki/UDP_tracker).
//!
//! ## Credits
//!
//! [Bittorrent UDP-tracker protocol extension](https://www.rasterbar.com/products/libtorrent/udp_tracker_protocol.html)
//! documentation by [Arvid Norberg](https://github.com/arvidn) was very
//! supportive in the development of this documentation. Some descriptions were
//! taken from the [libtorrent](https://www.rasterbar.com/products/libtorrent/udp_tracker_protocol.html).
use std::net::SocketAddr;
pub mod connection_cookie;
pub mod error;
pub mod handlers;
pub mod logging;
pub mod peer_builder;
pub mod server;
pub const UDP_TRACKER_LOG_TARGET: &str = "UDP TRACKER";
/// Number of bytes.
pub type Bytes = u64;
/// The port the peer is listening on.
pub type Port = u16;
/// The transaction id. A random number generated byt the peer that is used to
/// match requests and responses.
pub type TransactionId = i64;
#[derive(Clone, Debug)]
pub struct RawRequest {
payload: Vec<u8>,
from: SocketAddr,
}