You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: file-transfer-protocol.md
+115-3Lines changed: 115 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -8,7 +8,28 @@ All application-level messages are dictionaries, which are JSON-encoded and
8
8
and UTF-8 encoded before being handed to `wormhole.send` (which then encrypts
9
9
them before sending through the rendezvous server to the peer).
10
10
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
12
33
13
34
`wormhole send` has two main modes: file/directory (which requires a
14
35
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:
44
65
~~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
45
66
wormhole connection may be closed after the ack).
46
67
47
-
## Recipient
68
+
###Recipient
48
69
49
70
`wormhole receive` is used for both file/directory-mode and text-mode: it
50
71
learns which is being used from the `offer` message.
@@ -61,7 +82,7 @@ received message:
61
82
number of bytes, then write them to the target filename
62
83
*`directory`: as with `file`, but unzip the bytes into the target directory
63
84
64
-
## Transit
85
+
###Transit
65
86
66
87
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):
67
88
@@ -109,6 +130,97 @@ the Transit connection. The final ack of the received data is sent through
109
130
the Transit object, as a UTF-8-encoded JSON-encoded dictionary with `ack: ok`
110
131
and `sha256: HEXHEX` containing the hash of the received data.
111
132
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
+
112
224
## Future Extensions
113
225
114
226
Transit will be extended to provide other connection techniques:
0 commit comments