| 14 | | To discover other peers in a swarm a client announces it's existance to a tracker. |
| 15 | | The HTTP protocol is used and a typical request contains the following parameters: |
| 16 | | info_hash, key, peer_id, port, downloaded, left, uploaded and compact. |
| 17 | | A response contains a list of peers (host and port) and some other information. |
| 18 | | The request and response are both quite short. |
| 19 | | Since TCP is used, a connection has to be opened and closed, introducing additional overhead. |
| | 14 | To discover other peers in a swarm a client announces it's existance |
| | 15 | to a tracker. The HTTP protocol is used and a typical request |
| | 16 | contains the following parameters: info_hash, key, peer_id, port, |
| | 17 | downloaded, left, uploaded and compact. A response contains a list of |
| | 18 | peers (host and port) and some other information. The request and |
| | 19 | response are both quite short. Since TCP is used, a connection has to |
| | 20 | be opened and closed, introducing additional overhead. |
| 24 | | Using HTTP introduces significant overhead. There's overhead at the ethernet layer (14 bytes per packet), at the IP layer (20 bytes per packet), at the TCP layer (20 bytes per packet) and at the HTTP layer. |
| 25 | | About 10 packets are used for a request plus response containing 50 peers and the total number of bytes used is about 1206 [1]. |
| 26 | | This overhead can be reduced significantly by using a UDP based protocol. The protocol proposed here uses 4 packets and about 618 bytes, reducing traffic by 50%. |
| 27 | | For a client, saving 1 kbyte every hour isn't significant, but for a tracker serving a million peers, reducing traffic by 50% matters a lot. |
| 28 | | An additional advantage is that a UDP based binary protocol doesn't require a complex parser and no connection handling, reducing the complexity of tracker code and increasing it's performance. |
| | 25 | Using HTTP introduces significant overhead. There's overhead at the |
| | 26 | ethernet layer (14 bytes per packet), at the IP layer (20 bytes per |
| | 27 | packet), at the TCP layer (20 bytes per packet) and at the HTTP layer. |
| | 28 | About 10 packets are used for a request plus response containing 50 |
| | 29 | peers and the total number of bytes used is about 1206 [1]. This |
| | 30 | overhead can be reduced significantly by using a UDP based |
| | 31 | protocol. The protocol proposed here uses 4 packets and about 618 |
| | 32 | bytes, reducing traffic by 50%. For a client, saving 1 kbyte every |
| | 33 | hour isn't significant, but for a tracker serving a million peers, |
| | 34 | reducing traffic by 50% matters a lot. An additional advantage is |
| | 35 | that a UDP based binary protocol doesn't require a complex parser and |
| | 36 | no connection handling, reducing the complexity of tracker code and |
| | 37 | increasing it's performance. |
| 33 | | In the ideal case, only 2 packets would be necessary. However, it is possible to spoof the source address of a UDP packet. |
| 34 | | The tracker has to ensure this doesn't occur, so it calculates a value (connection_id) and sends it to the client. |
| 35 | | If the client spoofed it's source address, it won't receive this value (unless it's sniffing the network). |
| 36 | | The connection_id will then be send to the tracker again in packet 3. The tracker verifies the connection_id and ignores the request if it doesn't match. |
| 37 | | Connection IDs should not be guessable by the client. This is comparable to a TCP handshake and a syn cookie like approach can be used to storing the connection IDs on the tracker side. |
| 38 | | A connection ID can be used for multiple requests. A client can use a connection ID until one minute after it has received it. Trackers should accept the connection ID until two minutes after it has been send. |
| | 42 | In the ideal case, only 2 packets would be necessary. However, it is |
| | 43 | possible to spoof the source address of a UDP packet. The tracker has |
| | 44 | to ensure this doesn't occur, so it calculates a value (connection_id) |
| | 45 | and sends it to the client. If the client spoofed it's source |
| | 46 | address, it won't receive this value (unless it's sniffing the |
| | 47 | network). The connection_id will then be send to the tracker again in |
| | 48 | packet 3. The tracker verifies the connection_id and ignores the |
| | 49 | request if it doesn't match. Connection IDs should not be guessable |
| | 50 | by the client. This is comparable to a TCP handshake and a syn cookie |
| | 51 | like approach can be used to storing the connection IDs on the tracker |
| | 52 | side. A connection ID can be used for multiple requests. A client can |
| | 53 | use a connection ID until one minute after it has received |
| | 54 | it. Trackers should accept the connection ID until two minutes after |
| | 55 | it has been send. |
| 43 | | UDP is an 'unreliable' protocol. This means it doesn't retransmit lost packets itself. The application is responsible for this. |
| 44 | | If a response is not received after 15 * 2 ^ n seconds, the client should retransmit the request, where n starts at 0 and is increased up to 8 (3840 seconds) after every retransmission. |
| 45 | | Note that it is necessary to rerequest a connection ID when it has expired. |
| | 60 | UDP is an 'unreliable' protocol. This means it doesn't retransmit lost |
| | 61 | packets itself. The application is responsible for this. If a |
| | 62 | response is not received after 15 * 2 ^ n seconds, the client should |
| | 63 | retransmit the request, where n starts at 0 and is increased up to 8 |
| | 64 | (3840 seconds) after every retransmission. Note that it is necessary |
| | 65 | to rerequest a connection ID when it has expired. |
| 129 | | announce request |
| 130 | | Offset Size Name Value |
| 131 | | 0 64-bit integer connection_id |
| 132 | | 8 32-bit integer action 1 // announce |
| 133 | | 12 32-bit integer transaction_id |
| 134 | | 16 20-byte string info_hash |
| 135 | | 36 20-byte string peer_id |
| 136 | | 56 64-bit integer downloaded |
| 137 | | 64 64-bit integer left |
| 138 | | 72 64-bit integer uploaded |
| 139 | | 80 32-bit integer event 0 // 0: none; 1: completed; 2: started; 3: stopped |
| 140 | | 84 32-bit integer IP address 0 // default |
| 141 | | 88 32-bit integer key |
| 142 | | 92 32-bit integer num_want -1 // default |
| 143 | | 96 16-bit integer port |
| 144 | | 98 |
| | 157 | announce request:: |
| | 158 | |
| | 159 | Offset Size Name Value |
| | 160 | 0 64-bit integer connection_id |
| | 161 | 8 32-bit integer action 1 // announce |
| | 162 | 12 32-bit integer transaction_id |
| | 163 | 16 20-byte string info_hash |
| | 164 | 36 20-byte string peer_id |
| | 165 | 56 64-bit integer downloaded |
| | 166 | 64 64-bit integer left |
| | 167 | 72 64-bit integer uploaded |
| | 168 | 80 32-bit integer event 0 // 0: none; 1: completed; 2: started; 3: stopped |
| | 169 | 84 32-bit integer IP address 0 // default |
| | 170 | 88 32-bit integer key |
| | 171 | 92 32-bit integer num_want -1 // default |
| | 172 | 96 16-bit integer port |
| | 173 | 98 |
| 152 | | announce response |
| 153 | | Offset Size Name Value |
| 154 | | 0 32-bit integer action 1 // announce |
| 155 | | 4 32-bit integer transaction_id |
| 156 | | 8 32-bit integer interval |
| 157 | | 12 32-bit integer leechers |
| 158 | | 16 32-bit integer seeders |
| 159 | | 20 + 6 * n 32-bit integer IP address |
| 160 | | 24 + 6 * n 16-bit integer TCP port |
| 161 | | 20 + 6 * N |
| | 181 | announce response:: |
| | 182 | |
| | 183 | Offset Size Name Value |
| | 184 | 0 32-bit integer action 1 // announce |
| | 185 | 4 32-bit integer transaction_id |
| | 186 | 8 32-bit integer interval |
| | 187 | 12 32-bit integer leechers |
| | 188 | 16 32-bit integer seeders |
| | 189 | 20 + 6 * n 32-bit integer IP address |
| | 190 | 24 + 6 * n 16-bit integer TCP port |
| | 191 | 20 + 6 * N |
| 182 | | scrape response |
| 183 | | Offset Size Name Value |
| 184 | | 0 32-bit integer action 2 // scrape |
| 185 | | 4 32-bit integer transaction_id |
| 186 | | 8 + 12 * n 32-bit integer seeders |
| 187 | | 12 + 12 * n 32-bit integer completed |
| 188 | | 16 + 12 * n 32-bit integer leechers |
| 189 | | 8 + 12 * N |
| | 213 | scrape response:: |
| | 214 | |
| | 215 | Offset Size Name Value |
| | 216 | 0 32-bit integer action 2 // scrape |
| | 217 | 4 32-bit integer transaction_id |
| | 218 | 8 + 12 * n 32-bit integer seeders |
| | 219 | 12 + 12 * n 32-bit integer completed |
| | 220 | 16 + 12 * n 32-bit integer leechers |
| | 221 | 8 + 12 * N |