Skip to content

Latest commit

Β 

History

256 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

βœ… BitTorrent

This project implements a distributed BitTorrent system with P2P discovery using Docker, Go, and overlay networks.


πŸ“¦ 1. Clone the project

git clone https://github.com/JabelResendiz/BitTorrent.git
cd BitTorrent/src

πŸ—οΈ 2. Build the Docker images

Run from the src directory:

docker build -t client_img -f client/Dockerfile .
docker build -t tracker_img -f tracker/Dockerfile .

πŸš€ 3. Create the .torrent file and prepare the files

  1. Place the original file to share in:
archives/seeder/
  1. Generate the .torrent using mktorrent
sudo apt install mktorrent
mktorrent -a http://tracker:8080/announce \
  -o archives/torrents/video.torrent \
  archives/seeder/video.mp4

Where:

  • -a β†’ tracker URL (if using the overlay network, this does not matter)
  • -o β†’ path where the .torrent will be saved
  • last argument β†’ original file

Make sure this exists:

archives/torrents/video.torrent

🧰 4. Run EVERYTHING automatically (recommended)

Using the run_containers.sh script:

chmod +x script/run_containers.sh
./script/run_containers.sh

This script:

  • Creates the bittorrent network if it does not exist
  • Verifies that the .torrent exists
  • Cleans up previous containers
  • Starts the seeder
  • Starts multiple leechers
  • Each client starts with its corresponding port, hostname, and bootstrap

To run it without rebuilding the image, execute:

./script/run_containers.sh --no-build

πŸ› οΈ 5. Manual execution (without the script)

πŸ›°οΈ Run the Tracker

In one terminal:

go run tracker/cmd/main.go

This runs the tracker at:

localhost:8080

Expected output:

tracker listening on :8080 interval=1800s data=tracker_data.json

πŸ’» Run the Client

In another terminal:

go run client/cmd/main.go \
  --torrent="./archives/torrents/video.torrent" \
  --archives="./archives/seeder"

Typical output:

Tracker request:  http://localhost:8080/announce?info_hash=...
Tracker response: map[complete:0 incomplete:1 interval:1800 peers:]

Registered peers will appear in:

tracker_data.json

🧡 6. Run clients inside Docker (manual)

Example seeder client:

docker network create bittorrent

docker run -d --name seeder --network bittorrent \
  -v "$(pwd)/archives/seeder":/data \
  -v "$(pwd)/archives/torrents":/torrents:ro \
  -p 6000:6000 \
  client_img \
  --torrent=/torrents/video.torrent \
  --archives=/data \
  --hostname=seeder \
  --discovery-mode=overlay \
  --overlay-port=6000

Example leecher client with bootstrap:

docker run -d --name leecher1 --network bittorrent \
  -v "$(pwd)/archives/leecher1":/data \
  -v "$(pwd)/archives/torrents":/torrents:ro \
  -p 6001:6001 \
  client_img \
  --torrent=/torrents/video.torrent \
  --archives=/data \
  --hostname=leecher1 \
  --discovery-mode=overlay \
  --overlay-port=6001 \
  --bootstrap=seeder:6000

🐳 7. Run multiple clients on several PCs using Docker Swarm

To allow several clients (leecher/seeder) to run on different machines in a distributed network, we use Docker Swarm and a shared overlay network.


πŸ–₯️ Step 1 β€” Build the images (only once)

From the src/ directory:

docker build -t client -f client/Dockerfile .
docker build -t tracker -f tracker/Dockerfile .

You must copy these images to each PC, or upload them to a private registry if desired.


πŸ–₯️ PC 1 β€” Swarm Manager Node

Initialize the cluster:

docker swarm init

Get the token to add more nodes:

docker swarm join-token manager

(Copy the resulting command to the other PCs.)

Then create the distributed overlay network:

docker network create --driver overlay bittorrent-net

πŸ–₯️ PC 2 (and any others) β€” Worker Nodes

On this PC, paste the command generated by join-token, for example:

docker swarm join --token <TOKEN>

Then verify that the overlay network is available:

docker network ls

You will see something like:

bittorrent-net   overlay   swarm

πŸš€ Manual Service Deployment (Tracker and Clients)

1. Tracker (on any cluster node)

docker service create \
  --name tracker \
  --network bittorrent-net \
  --publish 8080:8080 \
  tracker

2. Seeder and Leechers

Example: run one seeder and two leechers distributed automatically by Swarm:

docker run -it --name seeder --network bittorrent-net \
  -v "$(cd "$(dirname "$0")/.." && pwd)/archives/seeder":/data \
  -v "$(cd "$(dirname "$0")/.." && pwd)/archives/torrents":/torrents:ro \
  -p 6000:6000 \
  client_img \
  --torrent=/torrents/pelicula.torrent \
  --archives=/data \
  --hostname=seeder \
  --discovery-mode=overlay \
  --overlay-port=6000

docker run -it --name leecher1 --network bittorrent-net \
  -v "$(cd "$(dirname "$0")/.." && pwd)/archives/leecher1":/data \
  -v "$(cd "$(dirname "$0")/.." && pwd)/archives/torrents":/torrents:ro \
  -p 6001:6001 \
  client_img \
  --torrent=/torrents/pelicula.torrent \
  --archives=/data \
  --hostname=leecher1 \
  --discovery-mode=overlay \
  --overlay-port=6001 \
  --bootstrap=seeder:6000

The replicas are distributed automatically across the Swarm PCs.


πŸ§ͺ Verify that the cluster works

On any PC in the cluster:

docker node ls
docker service ls
docker service ps tracker
docker service ps seeder
docker service ps leecher

πŸŽ‰ Result

  • The clients and tracker (if needed) are running on several distributed machines
  • They communicate through an overlay network
  • Docker Swarm automatically balances and manages the nodes

πŸ“„ 8. .torrent File Specification (Metainfo)

.torrent files are bencoded.
A .torrent is a dictionary with these main keys (all strings are UTF-8):

  • info: dictionary describing the torrent files
    • single-file: one file
    • multi-file: multiple files
  • announce: tracker URL (string)
  • announce-list: (optional) list of alternative trackers
  • creation date: (optional) UNIX epoch date (integer, seconds since Jan 1, 1970)
  • comment: (optional) free-form text from the author
  • created by: (optional) client that generated the torrent
  • encoding: (optional) string encoding in info

info Dictionary

Common fields

  • piece length: bytes per piece (integer)
  • pieces: concatenation of 20-byte SHA-1 hashes
  • private: (optional)
    • 1: use listed trackers only
    • 0 or absent: DHT, PEX, etc. may be used

Single-File Mode

A torrent that downloads a single file. The info dictionary directly contains the file size and name. All pieces correspond only to this file.

  • name: file name (string)
  • length: size in bytes (integer)
  • piece length: piece size
  • pieces: concatenated SHA-1 hashes
  • md5sum: (optional) MD5 hash
"info": {
  "name": "file.txt",
  "length": 123456,
  "piece length": 16384,
  "pieces": "<concatenated SHA1 hashes>"
}

Multi-File Mode

A torrent containing several files inside a root directory. In this case, info contains a files list instead of a single length value.

"info": {
  "name": "My_Folder",
  "piece length": 32768,
  "pieces": "<SHA1 concatenados>",
  "files": [
    {
      "length": 1024,
      "path": ["subdir1", "file1.txt"]
    },
    {
      "length": 2048,
      "path": ["subdir2", "file2.mp4"]
    }
  ]
}

Notes on pieces

  • Size is usually a power of 2
  • Historically: torrent ≀ 75 KB
  • Recommended: pieces ≀ 512 KB for 8–10 GB torrents
  • Common sizes: 256 KB, 512 KB, 1 MB
  • All pieces have the same size except the last one
  • In multi-file torrents, files are concatenated β†’ pieces may cross file boundaries
  • Each piece is represented by a SHA-1 hash (20 bytes) in pieces

Example .torrent file (bencoded)

"single-file" version

  • announce: tracker URL.
  • announce list: (list of URL lists)
  • creation date: date
  • comment: comments
  • created by: author
  • info: dictionary with file details:
    • length: file size in bytes.
    • name: file name.
    • piece length: size in bytes of each piece.
    • pieces: concatenation of 20-byte SHA-1 hashes.
    • private

JSON version

{
  "announce": "http://tracker.example.com/announce",
  "announce-list": [
    ["http://tracker.example.com/announce"],
    ["http://backuptracker.example.net/announce"]
  ],
  "creation date": 1695600000,
  "comment": "Educational torrent example",
  "created by": "ChatGPT TorrentMaker v1.0",
  "info": {
    "name": "file.txt",
    "length": 123456,
    "piece length": 16384,
    "pieces": "<binary concatenation of 20-byte SHA1 hashes>",
    "private": 0
  }
}

Same version in bencode

d
8:announce23:http://tracker.example.com/announce
13:announce-list
  ll
    23:http://tracker.example.com/announce
  e
  l
    33:http://backuptracker.example.net/announce
  e
e
13:creation datei1695600000e
7:comment27:Educational torrent example
10:created by27:ChatGPT TorrentMaker v1.0
4:infod
  4:name8:file.txt
  6:lengthi123456e
  12:piece lengthi16384e
  6:pieces40:<SHA1 piece 1><SHA1 piece 2>...
  7:privatei0e
e
e

πŸ“˜ 9. Tracker Module

The tracker does not store β€œwho has each piece of the file”; it stores who is participating in that torrent in general.

πŸ“Œ Specifically:

The torrent file is identified by its info_hash (SHA-1 of the info dictionary).

When a client announces to the tracker, it says:

β€œI am in the swarm for the torrent with info_hash = X”

It passes its peer_id, IP, port, and state (started, stopped, completed).

The tracker records: β€œPeer Y is in torrent X”.

Optionally, it counts how many peers have completed the file (seeders) and how many have not (leechers).

However, it does not know whether you have piece #5 or #200. Each peer knows that, and later reports it through a bitfield or have messages.

  • The tracker is an HTTP/HTTPS service that responds to HTTP GET requests. Requests include client metrics that help the tracker maintain general statistics about the torrent.

  • The response includes a list of peers that helps the client participate in the torrent.

Client request parameters to the tracker

The parameters used in the client's GET request to the tracker are:

  • info_hash: 20-byte SHA-1 hash (URL-encoded) of the info key's value in the metainfo file. This value is a bencoded dictionary, as defined by the info key.

  • peer_id: 20-byte string (URL-encoded) used as the client's unique ID, generated at startup. It may have any value; there are no generation rules. It must be unique on the local machine (include process ID + timestamp).

  • port: the port number on which the client listens. Ports 6881–6889 are reserved for BitTorrent. If it cannot use one of them, some clients simply give up.

  • uploaded: total bytes uploaded by the client when sending the started event to the tracker (in base-10 ASCII).

  • downloaded: total bytes downloaded since the started event (in base-10 ASCII).

  • left: number of bytes the client still needs to download (in base-10 ASCII), that is, the amount remaining to have 100% of the torrent.

  • compact: if set to 1, the client accepts a compact response. In that case, the peer list is replaced by a 6-byte binary string per peer:

    • 4 bytes -> IP in network byte order
    • 2 bytes -> port in network byte order
    • Some trackers accept only compact = 1 and reject other requests
  • no_peer_id: indicates that the tracker may omit the peer_id field from the peer list. Ignored if compact = 1.

  • event: if specified, it must be one of:

    • started: the first request to the tracker must include it
    • stopped: when the client shuts down cleanly
    • completed: when the torrent reaches 100% (but not if it was already complete at startup)
    • empty: equivalent to omitting it (regular requests)
  • ip (optional): the client's real IP address. It may be in IPv4 or IPv6 format.

  • numwant (optional): number of peers the client wants to receive. It may be 0. If omitted, the usual default is 50 peers.

  • key (optional): extra identifier not shared with other peers. It allows a client to prove its identity if its IP changes.

  • trackerid (optional): if the tracker returned a tracker_id in a previous announce, it must be sent again here.

GET /announce?info_hash=%12%34%56%78%9A%BC%DE%F1%23%45%67%89%AB%CD%EF%12%34%56%78%9A
&peer_id=-AZ2060-6wfG2wk6wWLc
&port=6881
&uploaded=0
&downloaded=0
&left=123456789
&compact=1
&event=started HTTP/1.1
Host: tracker.example.com:6969
User-Agent: MyBitTorrentClient/1.0
Connection: close

Tracker response parameters

The tracker responds with a text/plain document consisting of a bencoded dictionary with the following keys:

  • failure reason: if present, no other keys may be included. The value is a human-readable error message explaining why the request failed (string).

  • warning message (new, optional): Similar to failure reason, but the response is still processed normally. The warning message is displayed like an error.

  • interval: interval in seconds that the client must wait between regular requests to the tracker.

  • min interval (optional): minimum announce interval. If present, clients must not send announces more frequently than this.

  • tracker id: a string that the client must send in subsequent announces. If absent and a previous announce included a tracker id, the old value must not be discarded; it must continue to be used.

  • complete: number of peers with the complete file, that is, seeders (integer).

  • incomplete: number of non-seeder peers (leechers).

  • peers (dictionary model): the value is a list of dictionaries, each with the following keys:

    • peer id: peer's self-selected ID, as described in the tracker request (string)
    • ip: peer's IP address, either IPv6, IPv4, or a DNS name (string)
    • port: peer's port number (integer)
  • peers (binary model): instead of using the dictionary model described above, peers may be a string consisting of multiples of 6 bytes. The first 4 bytes are the IP address and the last 2 bytes are the port number. Everything uses network byte order (big endian).

Response in "dictionary" mode (non-compact)

HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 210

d
  8:intervali1800e
  8:completei12e
  10:incompletei34e
  5:peersl
    d2:ip13:192.168.1.210:porti6881e7:peer id20:-ABCD1234567890ABCDEe
    d2:ip13:192.168.1.211:porti6882e7:peer id20:-XYZ9876543210XYZabcde
  ee
e

Response in "compact" mode (more commonly used in practice)

HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 68

d8:intervali1800e8:completei12e10:incompletei34e5:peers12:\xC0\xA8\x01\xD2\x1A\xE1\xC0\xA8\x01\xD3\x1A\xE2e

Tracker Scrape Convention

Trackers (optionally) support another type of request that queries the status of a particular torrent (or all torrents) managed by the tracker. This is known as the "scrape page" because it automates the otherwise tedious process of viewing the tracker's statistics page.

  • It is useful when building a graphical interface or a console with detailed information.
  • Internal decision optimizations (for more advanced clients): before joining a torrent, the client asks the tracker whether it is worth joining, avoiding a torrent with 0 seeders.

The scrape URL also uses the HTTP GET method, similar to the one described above. However, the base URL is different. To obtain it:

  1. Start with the announce URL.
  2. Locate the last '/' in it.
  3. If the text immediately after that '/' is not 'announce', the tracker is considered not to support the scrape convention.
  4. If it is, replace 'announce' with 'scrape' to obtain the scrape URL.

The scrape URL may include the optional info_hash parameter, a 20-byte value. This restricts the tracker's report to that particular torrent (otherwise, it returns statistics for all torrents managed by the tracker, which is not recommended because it uses more load and bandwidth).

The response to this HTTP GET method is a text/plain document consisting of a bencoded dictionary with the following keys:

  • files: a dictionary containing one key/value pair for each torrent with available statistics
    • Each key is a 20-byte binary info_hash.
    • The associated value is another dictionary with:
      • complete: number of peers with the complete file (seeds or seeders) (integer).
      • downloaded: total number of times the tracker recorded a completion (event=completed, meaning a client finished downloading the torrent).
      • incomplete: number of peers without the complete file (leechers) (integer).
      • name (optional): internal torrent name, specified by the name field in the .torrent file's info section.

Tracker response to scrape

HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 68

d5:filesd20:....................(info_hash)d8:completei5e10:downloadedi50e10:incompletei10eeee

Scrape request

GET /scrape?info_hash=%12%34%56%78... HTTP/1.1
Host: tracker.example.com:6969

🌐 10. Peer Wire Protocol (TCP)

  • a client must maintain state information for each connection it has with a remote peer.
    • choked: indicates whether the remote peer has "choked" this client. When this happens, it tells the client that it will not respond to requests until it is unchoked. The client must not send block requests and must consider all pending requests discarded by the remote peer.
    • interested: indicates whether the remote peer is interested in something this client offers. It notifies the client that the remote peer will start requesting blocks when the client stops choking it.
    • am_choking: this client is choking the peer (initial = 1)
    • am_interested: this client is interested in the peer (initial = 0)
    • peer_choking: the peer is choking the client (initial = 1)
    • peer_interested: the peer is interested in this client (peer_interested = 0)
    • a block is downloaded when (am_interested = 1) and (peer_choking = 0)
    • a block is uploaded when (peer_interested = 1) and (am_choking = 0)

Handshake

It is a mandatory message and must be the first message transmitted by the client. It has a length of (49 + len(pstr)) bytes.

handshake: <pstrlen><pstr><reserved><info_hash><peer_id>
  • pstrlen: length of the pstr string, as a single raw byte

  • pstr: protocol string identifier

  • reserved: 8 reserved bytes. All current implementations use 0. Each bit in these bytes may be used to change protocol behavior.

  • info_hash: the same info_hash transmitted in tracker requests (20 bytes)

  • peer_id: 20-byte string used as the client's unique ID (the same one transmitted in tracker requests)

  • in version 1.0 of the BitTorrent protocol, pstrlen=19 and pstr="BitTorrent protocol"

  • the connection initiator must transmit its handshake immediately. The receiver may wait for the initiator's handshake if it can serve multiple torrents simultaneously. However, the receiver must respond as soon as it sees the info_hash portion of the handshake (the peer ID will presumably be sent after the receiver sends its handshake). The tracker's NAT-checking function does not send the peer_id field of the handshake.

  • If a client receives a handshake with an info_hash it is not currently serving, it must close the connection.

  • If the connection initiator receives a handshake whose peer_id does not match the expected peer ID, it must close the connection. In other words, the peer_id received by the tracker is expected to match the one in the handshake.

Data Types

All integers in the peer wire protocol are encoded as four-byte values in big-endian. This includes the length prefix in all messages that follow the handshake.

Message Flow

The protocol consists of an initial handshake. Afterwards, peers communicate by exchanging messages prefixed with their length. The length prefix is an integer.

Messages

All remaining messages in the protocol take the form <length prefix><message ID><payload>. The length prefix is a 4-byte big-endian value. The message ID is a single decimal byte. The payload depends on the message.

  • keep-alive (len=0000): 0-byte message, specified with a length prefix of 0. It has no message ID or payload. Peers may close a connection if they do not receive messages (keep-alive or otherwise) for a period of time, so a keep-alive must be sent to keep the connection alive if no command has been sent for a while. This is usually 2 minutes.

  • choke (<len=0001><id=0>): the choke message has a fixed length and no payload

  • unchoke (<len=0001><id=1>): has a fixed length and no payload

  • interested (<len=0001><id=2>): same as the previous two

  • not interested (<len=00001><id=3>): same

  • have (<len=00005><id=4>): fixed length. The payload is the zero-based index of a piece that has just been downloaded and hash-verified.

  • bitfield (<len=0001+X><id=5>): the bitfield message may only be sent immediately after completing the handshake, before any other message. It is optional and is not needed if a client has no pieces.

  • request (<len=0013><id=6>): fixed-length message used to request a block. The payload contains: index (piece index), begin (byte offset within the piece), and length (requested length).

  • piece (<len=0009+X><id=7>): variable-length message, where X is the block length. The payload contains: index (piece index), begin (offset within the piece), and block (data, a subset of the specified piece).

  • cancel (<len=0013><id=8>): fixed length and used to cancel block requests. The payload is identical to that of the request message. Typically used during the End Game phase.

  • port (<len=0003><id=9>): the port message is sent by recent versions of Mainline that implement a DHT tracker. listen-port (the port on which the peer's DHT node listens); this peer must be inserted into the local routing table if DHT is supported.


🧠 11. Algorithms

Internal strategies used by BitTorrent clients to improve performance and efficiency. The base protocol defines which messages can be sent (interested, request, piece, ...) but not when or how many to send.

Queuing

  • Problem: imagine that each 16 KB block is downloaded and the client requests the next one only after it finishes. This means waiting for a full round trip (the time between sending a request and receiving the block). On networks with high latency or high bandwidth, this idle time wastes download capacity.

  • Solution: clients maintain a queue of pending requests ("request outstanding"). While downloading one block, several more have already been requested. When one arrives, the next is already on its way. Making 10 requests in parallel is better than making one request, keeping the channel full and using the available bandwidth.

Super Seeding

  • When you are the first seed (the one with the complete file), the goal is to distribute unique pieces as efficiently as possible.
  • The idea is for the seed to pretend it does not have all pieces and only "announce" one piece to peers at a time. This shares different pieces with each peer so that they can later exchange them among themselves. This reduces the total amount of data the seed must upload before another seed is created.
  • Recommended only when seeding a new torrent (when you are the first seed).

Piece Download Strategy

  • Clients may choose to download pieces in random order. A better strategy is to download pieces in increasing order of rarity (rarest first).
  • The client can determine this by maintaining each peer's initial bitfield and updating it with every have message.
  • It can then download the pieces that appear least frequently in those bitfields.
  • Any rarest-first strategy should include some randomization among the least common pieces, because if many clients try to download the same rarest piece, the opposite effect will occur.

End Game

  • When a download is nearly complete, the last blocks tend to arrive slowly.
  • To speed this up, the client sends requests for all missing blocks to all its peers.
  • To prevent this from becoming inefficient, the client also sends a cancel message to all others whenever a block arrives.

protocol overhead

Choking and Optimistic Unchoking

  • The protocol uses choking to control who you upload data to. You cannot upload to everyone at once without overwhelming TCP, so you upload only to some peers.
  • The basic rule is: every 10 seconds, choose the 4 peers uploading to you the fastest (unchoke them). Block requests from the others. This implements tit-for-tat: "you give me speed, I give you speed."
  • The optimized version chooses one peer at random every 30 seconds (even if it is not sending anything) to test whether it could be better than the current 4. If it is fast, it joins the group and another peer leaves.

Anti-Snubbing

  • Sometimes a peer stops sending you pieces (it ignores you).
  • If more than 1 minute passes without receiving data, the client marks it as "snubbed" and stops uploading to it, except in the case of optimistic unchoke.
  • The goal is to avoid wasting time with peers that do not cooperate.

πŸ› οΈ 12. Official Protocol Extensions

Fast Peer Extensions

  • reserved bit: the third least significant bit of the 8th reserved byte reserved[7] |= 0x04
  • this speeds up the startup of a new peer in the swarm (the network of peers sharing a torrent).
  • Normally, if a peer is choked, it cannot request pieces.
  • With this extension, certain peers can download specific pieces while choked, accelerating initial synchronization.

DHT

  • reserved bit reserved[7] |= 0x01 (last bit of the eighth byte).
  • allows peers to be discovered without a centralized tracker. Each peer becomes a node in a DHT network, which stores information about which peers have which torrents.
  • the system continues to work if the tracker goes down
  • peers find one another using a distributed hash table (based on Kademlia)
  • BEP-32 adds IPv6 support

Connection Obfuscation (Message Stream Encryption - MSE)

  • has no specific reserved bit
  • allows BitTorrent connections to be encrypted or disguised so internet providers do not detect or limit torrent traffic.
  • obfuscates the handshake and protocol messages
  • helps evade traffic shaping or throttling
  • improves privacy

Web Seeding

  • does not use a reserved bit
  • allows an HTTP server to act as a seed (data source), in addition to regular peers
  • in short, you can download parts of the torrent from a web server, not only from other users

Extension Protocol

  • reserved bit reserved[5] = 0x10, the 4th most significant bit of the sixth byte
  • defines a generic way to announce and negotiate extensions between clients
  • each additional extension (for example DHT, metadata exchange, peer exchange) is announced and negotiated through this protocol

Extension Negotiation Protocol

  • reserved bits 47 and 48
  • allows peers to decide which extension to use when both support several.
  • avoids conflicts when two clients implement different extension systems.

BitTorrent Location-Aware Protocol

  • reserved bit: 21
  • allows peers to take other peers' geographic location into account. They can then prefer downloading from nearby peers, reducing latency and network load.

SimpleBT Extension Protocol

  • reserved bit in the first byte 0x01
  • adds peer information and connection-statistics exchange.
  • was used in older versions of SimpleBot

BitComet Extension Protocol

  • reserved bit in the first two bytes ex
  • used to exchange additional information (authentication, statistics, chat messages)
  • not officially documented; it is known through reverse engineering

πŸ“š 13. References


About

Implementation of the BitTorrent protocol in Go, developed as part of the Distributed Systems course.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages