|
| 1 | +File transfer over the TTY |
| 2 | +=============================== |
| 3 | + |
| 4 | +There are sometimes situations where the TTY is the only convenient pipe |
| 5 | +between two connected systems, for example, nested SSH sessions, a serial |
| 6 | +line, etc. In such scenarios, it is useful to be able to transfer files |
| 7 | +over the TTY. |
| 8 | + |
| 9 | +This protocol provides the ability to transfer regular files, directories and |
| 10 | +links (both symbolic and hard) preserving most of their metadata. It can |
| 11 | +optionally use compression and transmit only binary diffs to speed up |
| 12 | +transfers. However, since all data is base64 encoded for transmission over the |
| 13 | +TTY, this protocol will never be competitive with more direct file transfer |
| 14 | +mechanisms. |
| 15 | + |
| 16 | +Overall design |
| 17 | +---------------- |
| 18 | + |
| 19 | +The basic design of this protocol is around transfer "sessions". Since |
| 20 | +untrusted software should not be able to read/write to another machines |
| 21 | +filesystem, a session must be approved by the user in the terminal emulator |
| 22 | +before any actual data is transmitted. |
| 23 | + |
| 24 | +There can be either send or receive sessions. In send sessions files are sent |
| 25 | +from from remote client to the terminal emulator and vice versa for receive |
| 26 | +sessions. Every session basically consists of sending metadata for the files |
| 27 | +first and then sending the actual data. The session is a series of commands, |
| 28 | +every command carrying the session id (which should be a random unique-ish |
| 29 | +identifier, to avoid conflicts). The session is bi-directional with commands |
| 30 | +going both to and from the terminal emulator. Every command in a session |
| 31 | +also carries an ``action`` field that specifies what the command does. The |
| 32 | +remaining fields in the command are dependent on the nature of the command. |
| 33 | + |
| 34 | +Let's look at some simple examples of sessions to get a feel for the protocol. |
| 35 | + |
| 36 | + |
| 37 | +Sending files to the terminal emulator |
| 38 | +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 39 | + |
| 40 | +The client starts by sending a start command command:: |
| 41 | + |
| 42 | + → action=send id=someid |
| 43 | + |
| 44 | +It then waits for a status message from the terminal either |
| 45 | +allowing the transfer or refusing it. Until this message is received |
| 46 | +the client is not allowed to send any more commands for the session. |
| 47 | +The terminal emulator should drop a session if it receives any commands |
| 48 | +before sending an ``OK`` response. If the user accepts the transfer, |
| 49 | +the terminal will send:: |
| 50 | + |
| 51 | + ← action=status id=someid status=OK |
| 52 | + |
| 53 | +Or if the transfer is refused:: |
| 54 | + |
| 55 | + ← action=status id=someid status=EPERM:User refused the transfer |
| 56 | + |
| 57 | +The client then sends one or more ``file`` commands with the metadata of the file it wants |
| 58 | +to transfer:: |
| 59 | + |
| 60 | + → action=file id=someid file_id=f1 name=/path/to/destination |
| 61 | + → action=file id=someid file_id=f2 name=/path/to/destination2 ftype=directory |
| 62 | + |
| 63 | +The terminal responds with either ``OK`` for directories or ``STARTED`` for |
| 64 | +files:: |
| 65 | + |
| 66 | + ← action=status id=someid file_id=f1 status=STARTED |
| 67 | + ← action=status id=someid file_id=f2 status=OK |
| 68 | + |
| 69 | +If there was an error with the file, for example, if the terminal does not have |
| 70 | +permission to write to the specified location, it will instead respond with an |
| 71 | +error, such as:: |
| 72 | + |
| 73 | + ← action=status id=someid file_id=f1 status=EPERM:No permission |
| 74 | + |
| 75 | +The client sends data for files using ``data`` commands. It does not need to |
| 76 | +wait for the ``STARTED`` from the terminal for this, the terminal must discard data |
| 77 | +for files that are not ``STARTED``. Data for a file is sent in individual |
| 78 | +chunks of no larger than ``4096`` bytes. For example:: |
| 79 | + |
| 80 | + |
| 81 | + → action=data id=someid file_id=f1 data=chunk of bytes |
| 82 | + → action=data id=someid file_id=f1 data=chunk of bytes |
| 83 | + ... |
| 84 | + → action=end_data id=someid file_id=f1 data=chunk of bytes |
| 85 | + |
| 86 | +The sequence of data transmission for a file is ended with an ``end_data`` |
| 87 | +command. After each data packet is received the terminal replies with |
| 88 | +an acknowledgement of the form:: |
| 89 | + |
| 90 | + ← action=status id=someid file_id=f1 status=PROGRESS size=bytes written |
| 91 | + |
| 92 | +After ``end_data`` the terminal replies with:: |
| 93 | + |
| 94 | + ← action=status id=someid file_id=f1 status=OK size=bytes written |
| 95 | + |
| 96 | +If an error occurs while writing the data, the terminal replies with an error |
| 97 | +code and ignores further commands about that file, for example:: |
| 98 | + |
| 99 | + ← action=status id=someid file_id=f1 status=EIO:Failed to write to file |
| 100 | + |
| 101 | +Once the client has finished sending as many files as it wants to, it ends |
| 102 | +the session with:: |
| 103 | + |
| 104 | + → action=finish id=someid |
| 105 | + |
| 106 | +At this point the terminal commits the session, applying file metadata, |
| 107 | +creating links, etc. If any errors occur it responds with an error message, |
| 108 | +such as:: |
| 109 | + |
| 110 | + ← action=status id=someid status=Some error occurred |
0 commit comments