Fjord Protocol is a TCP based protocol that allows a more flexible and adaptable sharing of pieces between a server that acts as a buffer and a client which will receive all informations about the server state as well as the downloaded pieces as soon as they are available.
Protocol version: 1.0.0
note: big-endian is the norm here
The most basic TCP server should
- allow the connection of new clients through a
handshake
message and verify the handshake token with its own secret. - allow authenticated wires to upload a torrent file and directly start downloading it to a local directory
- allow authenticated wires to selectively listen to torrent-specific events, using bitmasks
- receive status update including eta, speeds
- receive piece availabilities
- receive pieces
- allow authenticated to start, resume and destroy torrents
A client is a host that is defined by a host ID (randomly generated by the server and specified in the handshake), and remote server address. A wire is a connection between the client and the server, defined by:
- its client ID. Basically the host ID.
- the target server address
- the client port listening for connection
So there might be only one client per client/server relation (as expected) but several wires for a client.
Every message is structured like this:
01 A4 <Message Length: UInt32 (4)> <Message Type: UInt8 (1)> <Data>
The first bytes are a constant value to identify protocol used (c. f. http://www.bittorrent.org/beps/bep_0003.html#peer-protocol)
The message length represents the total message length in bytes, from 0 to 4,294,967,295. This includes the message prefix (0x14A), the message length and type as well as the total amount of data.
The client-to-server message types are defined as follows:
0x01
: Handshake message0x03
: Subscribe to server-specific events0x04
: Start a torrent0x05
: Subscribe to torrent specific events0x07
: Torrent-specific commands0x08
: Request one or more pieces
The server may respond with these messages:
0x02
: Handshake Response message0x06
: Server-specific events notifications0x0a
: Torrent specific events0x10
: Piece data
The handshake is the first message that should be sent by the client to the server. The only data it contains is an UTF-8 encoded authentication JWT token that allows only selected peers to connect to the server. This token, signed and delivered by the server should contains two values :
hi
the client ID, a randomly generated numberhn
the client name a familiar name for the user
The said token should expire at most 3 months after its creation.
This message is used by clients to listen for server-specific events. Those are:
The message sent by the client to the server in order to subscribe to events is defined like this:
<…> <Event Bitmask: UInt8 (1)>
The event bitmask is a simple integer which specifies which events to listen to for this wire. Possible values are available in section 2.3.1
The start torrent message is a simple message which data only contains the torrent file buffer to start.
This event has payload defined like this:
<…> <Hash: UInt (20)> <Event mask: UInt8 (1)>
The hash is the infoHash this wires wants to listen to event. The event bitmask selects which event to subscribe to, by masking bits using &
. Possible events are available in 2.3.2. Torrent events
Note: all the events are distributed across clients, so one client with multiple wires having same event bitmasks will only receive every notification once.
Issues torrent specific commands. Payload is:
<…> <Command ID: UInt8 (1)> [Command payload]
For possible commands see 2.3.3. Torrent commands
This commands request pieces for this wire as soon as they are available and the wire is not already transmitting data.
<…> <Torrent hash: string (20)> <Pieces Indexes: UInt32 (4)>...
Once a Handshake message has been sent to the server, the latter will respond with a Handshake response message that specifies whether the authentication request has been accepted - essentially if the JWT token is valid. If it fails, it may also contain an error message and the connection will eventually be dropped by the server.
The response data is as follows:
… <Status byte: UInt8 (1)> [Error Message: string (…)]
The Status byte is either 0 (failure) or 1 (success). If it failed to authenticate, then the error message is an UTF-8 encoded string for the remaining data.
The payload is:
<…> <Event: UInt8 (1)> <Event payload>
See section 2.3.1 for possible events and their corresponding payloads.
The payload is
<…> <Event: UInt8 (1)> <Info Hash: UInt (20)> <Event payload>
See Torrent events for a list of events and payloads
The payload is:
<…> <Torrent hash: string (20)> <Piece Index: UInt32 (4)> <Piece data...>
See section 2.3.1 for possible events and their corresponding payloads.
0x01
: torrent started. Data is the torrent infoHash encoded as an UTF-8 string.0x02
: torrent finished. Data is the torrent infoHash.0x04
: peer connected. Data is<…> <Host ID: string (8)> <Host name: string (…)>
0x01
: Torrent started0x02
: Torrent status update. Payload for the callback is:
<…>
<Torrent status: UInt8 (2)>
<Peers connected: UInt8 (2)>
<Downloaded: UInt32 (4)>
<Uploaded: UInt32 (4)>
<Download speed: UInt32 (4)>
<Upload speed: UInt32 (4)>
0x04
: Torrent piece available. Payload is a UInt32Array describing grouped indexes of new pieces received
0x01
: Pause torrent0x02
: Resume torrent0x03
: Destroy torrent