Skip to content

Commit 93baff0

Browse files
committed
Transfer-v2: initial proposal
1 parent 69b03a7 commit 93baff0

File tree

1 file changed

+115
-3
lines changed

1 file changed

+115
-3
lines changed

file-transfer-protocol.md

Lines changed: 115 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,28 @@ All application-level messages are dictionaries, which are JSON-encoded and
88
and UTF-8 encoded before being handed to `wormhole.send` (which then encrypts
99
them before sending through the rendezvous server to the peer).
1010

11-
## Sender
11+
## Application version
12+
13+
The main key in the `app_version` object is called `abilities`, which is an array of strings. The known values are: `["transfer-v1", "transfer-v2"]`. Unknown values and keys have to be accepted by every client. An ability may specify additional hints to store in the object as well. If the value is empty (`{}`), `{abilities = ["transfer-v1"];}` must be assumed for backwards compatibility. `transfer-v1` SHOULD always be supported.
14+
15+
The sender gets to pick a protocol version and capabilities based on the version information of the peer. The receiver distinguishes which protocol is used on the first incoming message.
16+
17+
**Example value:**
18+
19+
```json
20+
{
21+
abilities: ["transfer-v1", "transfer-v2"],
22+
transfer-v2-hints: {
23+
supported-formats: ["tar.zst"]
24+
}
25+
}
26+
```
27+
28+
## Transfer v1
29+
30+
The initial version, supports sending files, directories and text messages. Directories are sent by zipping them on the sender side and un-zipping them on the receiver side.
31+
32+
### Sender
1233

1334
`wormhole send` has two main modes: file/directory (which requires a
1435
non-wormhole Transit connection), or text (which does not).
@@ -44,7 +65,7 @@ from the recipient, and processes them. It reacts to the following keys:
4465
~~The sender can handle all of these keys in the same message, or spaced out over multiple ones.~~ **This is strongly discouraged!** *Probably no implementation supports receiving multiple messages in one, and no one sends multiple at once.* ~~It will ignore any keys it doesn't recognize, and will completely ignore messages that don't contain any recognized key.~~ *As all capabilities are explained during version negotiation, every sender knows what keys are supported by the other side. No unsupported values should be transferred.* The only constraint is that the message containing `message_ack` or `file_ack` is the last one: it will stop looking for wormhole messages at that point (the
4566
wormhole connection may be closed after the ack).
4667

47-
## Recipient
68+
### Recipient
4869

4970
`wormhole receive` is used for both file/directory-mode and text-mode: it
5071
learns which is being used from the `offer` message.
@@ -61,7 +82,7 @@ received message:
6182
number of bytes, then write them to the target filename
6283
* `directory`: as with `file`, but unzip the bytes into the target directory
6384

64-
## Transit
85+
### Transit
6586

6687
See [transit](./transit.md) for some general documentation. The transit protocol does not specify how the data for finding each other is transferred. This is the job of the application level protocol (thus, here):
6788

@@ -109,6 +130,97 @@ the Transit connection. The final ack of the received data is sent through
109130
the Transit object, as a UTF-8-encoded JSON-encoded dictionary with `ack: ok`
110131
and `sha256: HEXHEX` containing the hash of the received data.
111132

133+
## Transfer v2 (proposal)
134+
135+
A v2 of the file transfer protocol got invented to add the following features:
136+
137+
- Resumable transfers after a connection interruption
138+
- No need to build a temporary zip file; for both speed and space efficiency reasons. Also zip has a lot of other subtle limitations.
139+
140+
The feature of sending text messages (without a transit connection), on the other hand, got removed.
141+
142+
### Basic protocol
143+
144+
The sender sends an offer, which contains a list of all the files, their size, modification time, and a transfer identifier that can be used to resume connections. The attempt to send the same files twice should use with the same identifier. How it is generated is an implementation detail, the suggested method is to either store it locally or to use the hash of the absolute path of the folder being sent.
145+
146+
The receiver responses either with either a `"transfer rejected"` error of with an acknowledgement. The acknowledgement may contain a list of byte offsets, one for each file, which will tell the sender from where to resume the transfer.
147+
148+
Both do the negotiation to open a transit relay. The process to doing so is slightly different from the one in the first version. The set of supported abilities is already delivered during the file offer/ack. Thus, the `transit` message only contains the hints for methods both sides support. Both side try to connect to every hint of the other side, the sender will then confirm the first one that succeeded.
149+
150+
The sender then sends the requested bytes over the relay using one of the supported formats. Afterwards, it sends a message with checksums. The receiver then closes the connections, optionally with sending an error message on a checksum mismatch.
151+
152+
#### Supported formats
153+
154+
At the moment, the only supported format is `tar.zst`. The files are sent bundled as a tar ball, compressed with zstd. The details are up to the sender; a low compression level is recommended. Only the files requested by the sender must be sent, and only the bytes starting from the requested offset must be contained.
155+
156+
### The structs in detail
157+
158+
#### Send offer
159+
160+
File paths must be normalized and relative to the root of the sent folder. If the sender's file system does not support modification times, `mtime` must be constant (preferably `0`). Sending a file is the same as sending a directory with a single file. `directory-name` is the name of the directory being sent. It must be present unless `files` contains exactly one item. `files` must not be empty.
161+
162+
```json
163+
{
164+
"offer-v2": {
165+
"directory-name": "<string, optional>",
166+
"files": [
167+
{
168+
"path": "<string>",
169+
"size": "<integer>",
170+
"mtime": "<integer>"
171+
}
172+
],
173+
"transit-abilities": "<list, subset of ['direct-tcp-v1', 'relay-v1', 'tor-tcp-v1']>"
174+
};
175+
}
176+
```
177+
178+
#### Receive ack
179+
180+
`files` contains a mapping from file (index) to offset (bytes). If omitted, all files must be sent.
181+
182+
```json
183+
{
184+
"answer-v2": {
185+
"files": {
186+
"<integer>": "<integer>"
187+
},
188+
"transit-abilities": "<list of ability strings>"
189+
}
190+
}
191+
```
192+
193+
#### Transit hints
194+
195+
Note that the hints for abilities added in the future might follow a different schema. The discriminant is `type`.
196+
197+
```json
198+
{
199+
"transit-v2": [
200+
{
201+
"type": "<ability string>",
202+
"hostname": "<string>",
203+
"port": "<tcp port>",
204+
"priority": "<number, usually [0..1], optional, default 0.5>"
205+
},
206+
]
207+
}
208+
```
209+
210+
#### Checksums
211+
212+
`tar-file-sha256` is the lowerhex-encoded sha256sum of all transferred bytes of the tar file.
213+
214+
TODO maybe some per file integrity check?
215+
216+
```json
217+
{
218+
"transfer-ack-v2": {
219+
"tar-file-sha256": "<string>"
220+
}
221+
}
222+
```
223+
112224
## Future Extensions
113225

114226
Transit will be extended to provide other connection techniques:

0 commit comments

Comments
 (0)