Specification of client uploads in (Tight)VNC/RFB?

735 Views Asked by At

I'm looking to understand how file transfers working in VNC/TightVNC/RFB.

In https://github.com/rfbproto/rfbproto/blob/master/rfbproto.rst#serverinit I see there is mention of certain client messages that look relevant if using the Tight Security Type, e.g.

132 "TGHT"  "FTC_UPRQ"  File Upload Request
133 "TGHT"  "FTC_UPDT"  File Upload Data

But I don't see detail on how these messages are used in the protocol

At https://www.tightvnc.com/ there is lots of information on usage, but so far not found anything about the protocol itself.

How do the file transfers work? As in, what are the low-level details of the messages sent in both directions to initiate and complete an upload from the client to the server?

(Ultimately I am looking to implement this, say in NoVNC, but I'm quite a few steps away from any coding at this point)

3

There are 3 best solutions below

0
On

This a very partial answer from looking at the code of

I think that an upload from the client is initiated by the client:

And then I think that uploads are done in max 64k chunks (num of bytes are limited to 16 bits). So each chunk is:

  • client -> server, 1 byte = 133: message type of file upload data request

  • client -> server, 1 byte: compression level, where 0 is not compressed, and I don't think libvnc supports anything other than 0(?)

  • client -> server, 2 bytes big endian: the uncompressed(?) size of the upload data

  • client -> server, 2 bytes big endian: the compressed size of the upload data. I think for libvnc since compression isn't supported, this has to equal the uncompressed size

  • client -> server, "compressed size" bytes: the data of the current chunk the file itself

  • not sure how the server acknowledges that this is all fine

Then once all the data has been uploaded, there is a final empty chunk followed by the modification/access time of the file:

  • client -> server, 1 byte = 133: message type of file upload data request

  • client -> server, 1 byte: compression level, where 0 is not compressed, and I don't think libvnc supports anything other than 0(?)

  • client -> server, 2 bytes = 0: the uncompressed(?) size of the upload data

  • client -> server, 2 bytes = 0: the compressed size of the upload data

  • client -> server, 4 bytes: the modification and access time of the file. libvnc sets both to be the same, and interestingly there doesn't seem to be a conversion from the endianness of the messages to the endianness of the system.

  • and as per the other parts of upload, not sure how the server acknowledges that this has been successful

If the client wants to cancel the upload:

  • client -> server, 1 byte = 135: message type of file upload failed

  • client -> server, 1 byte: unused(?)

  • client -> server, 1 byte: length of reason

  • client -> server, "length of reason" bytes: human readable reason of why the upload was cancelled

If the server wants to fail the upload:

  • server -> client, 1 byte = 132: message type of file upload cancel

  • server -> client, 1 byte: unused(?)

  • server -> client, 1 byte: length of reason

  • server -> client, "length of reason" bytes: human readable reason of why the upload failed

It does seem odd that there doesn't seem a way for the server to acknowledge any sort of success, so the client can't really give the user a "yes, it's worked!" sign. At least, not one with high confidence that everything has indeed worked.

It also does look like at most 1 upload at a time is possible: there is no ID or anything like that to distinguish multiple files being uploaded at the same time. Although given this would all be over the same TCP connection (typically) there would probably not be any speed benefit of this.

0
On

Looking in the source for UltraVNC there is another protocol, based on message type of 7 to initiate a file transfer. This is part of the RFB specification, although details are not given beyond including that messages of type 7 related to "FileTransfer"

0
On

Looking in the source for TightVNC, it looks like (confusingly) TightVNC itself doesn't seem to support the 132 "TGHT" / 133 "TGHT" messages.

Instead, it has a sub-protocol based on messages of type 252 (0xFC). In this sub-protocol, the message types are 4 byte integers: 252 in the first byte, and then 3 more, as per the comment in FTMessage.h

read first byte (UINT8) as message id, but if first byte is equal to 0xFC then it's TightVNC extension message and must read next 3 bytes and create UINT32 message id for processing.

At first glance on a high level it looks similar to the one in libvnc, but it does appear to include more server acknowledgements. For example, in response to a request to start an upload, the server will reply with a message to type 0xFC000107 to say "yes, that's fine" (I think)