Author: | Ian Reinhart Geiser <geiseri@yahoo.com> |
---|---|
Version: | 0.1 (Draft) |
Table of Contents
This is the specification extends the core RFB specification to allow a RFB server to read and write blocks from a clients local file system. File access is done in server defined data blocks. This block based approach enables the server to access only the parts of the file that it requires and to interleave block messages with other RFB messages.
The client can have multiple numbers of shared local directories. It will advertise these to the server where the user can decide the share they wish to access. The server will provide some sort of user space application or device driver to present the remote files to the user. The server will then communicate with the VNC server to forward the request to the client over the RFB connection. The client in turn will use the local file system APIs to perform the file system operation. Once the operation is complete the client will send a response back to the server over the RFB connection. The server will then interpret this response and will forward this response to the user space application.
It is recommended that the server exposes shares via a local device driver so that it will closely mirror a normal physical file system. It is the server's responsibility though to provide some sort of security to limit access the the share to the currently attached client. This behavior is up to the server implementations to further define. This protocol accounts for multiple shared to be provided to the server, but it is the server's prerogative whether to allow this feature. To accommodate the lowest common denominator of file system's volume names are limited to 11 characters not including a trailing null character. It is the servers responsibility to enforce this either by truncating the name or not accepting the share.
Server implementations may use some sort of cache system provided it follow the semantics of a write through cache. This cache will always be considered valid for reads, but any writes performed must be transfered to the client immediately. To accommodate this behavior it is recommended that if possible file system modifications from outside of the RFB client be prohibited. If a file is modified outside of client the server and the client may become out of sync. This could result in a corrupt file on the client file system.
This protocol is intended to be completely asynchronous. To facilitate this each message that requires a response contains a transaction identifier (transaction-id). These identifiers allow messages to pair themselves back together in an asynchronous manner. These must be unique for all messages currently being sent and received.
When the client attaches initially and sends the supported encoding it will add the RFB_BLOCK_XFR (???) to the list of supported encodings. If the server supports this encoding the following sequence will take place:
To traverse the local file system the Request directory info message will provide the contents of a specific path relative to the root of the share. This closely mirrors the behavior of running stat on each directory entry item of a specific path. The information returned is only a subset of the client file system because it must suit the lowest common denominator of file system features.
Directories may be created, removed or moved on the local file system. This operation may or may not succeed when the file system is in use.1
It is the responsibility of the client to manage the actual creation, tear down and freeing of local resources. It is the servers responsibility to manage the lifetime of the access to the file. When the file system driver requests access to a specific file the following sequence will take place:
Files can be removed or moved by an absolute path based off of the root of the shared folder. The underlying client file system may or may not succeed if the file is currently in use.1
Symbolic links are not supported so if the server requests that a symbolic link be created it will result in an error. On the client symbolic links are not to be presented to the server in directory listings or in file open requests.
There are two ways that the share can be removed from the server. The first is that the server can request the share be removed using the Request share close message. This is usually called when the server's file system driver unmounts the share. This can also happen during shutdown of the server to ensure the client can cleanly tear things down. The second way is that the client can send a Client disable share message to the server. The server will then respond back with a Request share close message after notifying the file system driver and performing any cleanup tasks that must happen on the server to cleanly remove the share. The client must keep the share active until the Request share close message is received from the server.
In the event that the connection is severed during the session it is the server and the client's responsibility to clean up resources and notify the user of the error.
This is a generic response message for operations that just need to report back a status of the last operation. This message contains the following structure:
No. of bytes | Type | Value | Description |
---|---|---|---|
1 | U8 | 249 | message-type |
4 | U32 | 20 | message-sub-type |
4 | U32 | transaction-id | |
1 | U8 | status |
This message requests file system information for a specific path. This path is defined as being based off of the root of the share. So for example if the share is providing the local path of /home/user/Documents and the host would like to see the entries for that share it would ask for the path /. It is important to note that the paths supplied to the client use the Unix style of path separators. This message contains the following structure:
No. of bytes | Type | Value | Description |
---|---|---|---|
1 | U8 | 249 | message-type |
4 | U32 | 13 | message-sub-type |
4 | U32 | transaction-id | |
4 | U32 | path-length | |
path-length | U8 array | path |
This message contains high level file system information for each child entry in a path. It is the client's responsibility to ensure the underlying read of the directory has returned before it returns the result.2 If there is a non-zero status the errors are as follows:
Status | Description |
---|---|
1 | Permission denied. |
2 | Path not found. |
3 | Undefined error |
This message contains the following structure:
No. of bytes | Type | Value | Description |
---|---|---|---|
1 | U8 | 249 | message-type |
4 | U32 | 13 | message-sub-type |
4 | U32 | transaction-id | |
1 | U8 | status | |
4 | U32 | entry-count |
followed by entry-count repetitions of the following:
No. of bytes | Type | Value | Description |
---|---|---|---|
1 | U8 | is-dir | |
1 | U8 | file-name-length | |
file-name-length | U8 array | file-name | |
1 | U8 | attributes | |
4 | U32 | create-time | |
4 | U32 | last-access-time | |
4 | U32 | last-modify-time | |
4 | U32 | size |
A bit mask of the attributes that this file contains. This protocol only supports exporting very limited sets of attributes. Currently they are as follows:
Value | Description |
---|---|
1 | The file is readable |
2 | The file is writable |
4 | The file is hidden |
8 | The file is executable |
This message is sent by the server to query the current attributes for the directory entry. This message contains the following structure:
No. of bytes | Type | Value | Description |
---|---|---|---|
1 | U8 | 249 | message-type |
4 | U32 | 23 | message-sub-type |
4 | U32 | transaction-id | |
4 | U32 | path-length | |
path-length | U8 array | path |
This message contains high level file system information for a specific path. It is the client's responsibility to ensure the underlying read of the directory has returned before it returns the result.2 If there is a non-zero status the errors are as follows:
Status | Description |
---|---|
1 | Permission denied. |
2 | Path not found. |
3 | Undefined error |
This message shares many of the same fields as the Directory info response message but with only information for a specific directory entry. This message contains the following structure:
No. of bytes | Type | Value | Description |
---|---|---|---|
1 | U8 | 249 | message-type |
4 | U32 | 23 | message-sub-type |
4 | U32 | transaction-id | |
1 | U8 | status | |
1 | U8 | is-dir | |
1 | U8 | attributes | |
4 | U32 | create-time | |
4 | U32 | last-access-time | |
4 | U32 | last-modify-time | |
4 | U32 | size |
This message is sent by the server to set the attributes for a specific directory entry. This message contains the following structure:
No. of bytes | Type | Value | Description |
---|---|---|---|
1 | U8 | 249 | message-type |
4 | U32 | 24 | message-sub-type |
4 | U32 | transaction-id | |
4 | U32 | path-length | |
path-length | U8 array | path | |
1 | U8 | attributes |
This message returns a Generic status response message. If there is a non-zero status the errors are as follows:
Status | Description |
---|---|
1 | Permission denied. |
2 | Path not found. |
3 | Undefined error |
This request notifies the host would like to access a file on the local client. The path is given as an absolute path.
No. of bytes | Type | Value | Description |
---|---|---|---|
1 | U8 | 249 | message-type |
4 | U32 | 14 | message-sub-type |
4 | U32 | transaction-id | |
4 | U32 | path-length | |
path-length | U8 array | path | |
1 | U8 | mode |
A bit field defining the access mode that the file should be opened as. These are defined below:
Value | Description |
---|---|
1 | Open for reading. |
2 | Open for writing. |
If a file is successfully opened then it will return a valid file-id. This is a unique value that will allow the host to manage the lifetime of its access to the file. It is the client's responsibility to ensure the open operation has returned before it returns the result.2 If there is a non-zero status the errors are as follows:
Status | Description |
---|---|
1 | Permission denied. |
2 | File not found. |
3 | Undefined error |
This message contains the following structure:
No. of bytes | Type | Value | Description |
---|---|---|---|
1 | U8 | 249 | message-type |
4 | U32 | 14 | message-sub-type |
4 | U32 | transaction-id | |
1 | U8 | status | |
2 | U16 | file-id |
The host uses this message to inform the client that it is done accessing a specific file and the client can discard any information associated with it. The file-id must match the result returned by the Open file response message. This message is nonblocking and will not get a response. This message contains the following structure:
No. of bytes | Type | Value | Description |
---|---|---|---|
1 | U8 | 249 | message-type |
4 | U32 | 15 | message-sub-type |
2 | U16 | file-id |
This is a helper message that will notify the client to truncate a specific file based off of a path. It is the client's responsibility to ensure the truncation of the path returns before it returns the result.2 If there is a non-zero status the errors are as follows:
Status | Description |
---|---|
1 | Permission denied. |
2 | File not found. |
3 | Not regular file. |
This message contains the following structure:
No. of bytes | Type | Value | Description |
---|---|---|---|
1 | U8 | 249 | message-type |
4 | U32 | 16 | message-sub-type |
4 | U32 | transaction-id | |
4 | U32 | path-length | |
path-length | U8 array | path | |
4 | U32 | new-file-size |
This message requests a specific block of a currently open file. The server decides the size of the block to read so it is responsible for breaking up any large reads into smaller chunks.3
No. of bytes | Type | Value | Description |
---|---|---|---|
1 | U8 | 249 | message-type |
4 | U32 | 17 | message-sub-type |
4 | U32 | transaction-id | |
2 | U16 | file-id | |
4 | U32 | file-offset | |
4 | U32 | read-size |
The client will read a specific block from an open file and return the status along with the actual data. The data is not encoded in any way, and should be transfered verbatim. On a successful read status will be set to 0, and the read-data-size will be set to the size of the data.2 If there is a non-zero status the errors are as follows:
Status | Description |
---|---|
1 | File not open. |
2 | Read out of bounds. |
3 | General IO error. |
This message contains the following structure:
No. of bytes | Type | Value | Description |
---|---|---|---|
1 | U8 | 249 | message-type |
4 | U32 | 17 | message-sub-type |
4 | U32 | transaction-id | |
1 | U8 | status | |
4 | U32 | read-data-size | |
read-data-size | U8 array | read-data |
This message is passed from the server to the client when a block of data is to be written to an open file at an offset. The server is responsible for the size of the block to be written.3 The client will then respond with a Generic status response message providing the server with the status of the operation. It is the client's responsibility to ensure the entire block of data is written before it returns the result.2 If there is a non-zero status the errors are as follows:
Status | Description |
---|---|
1 | File not open. |
2 | Write out of bounds. |
3 | General IO error. |
This message contains the following structure:
No. of bytes | Type | Value | Description |
---|---|---|---|
1 | U8 | 249 | message-type |
4 | U32 | 18 | message-sub-type |
4 | U32 | transaction-id | |
2 | U16 | file-id | |
4 | U32 | file-offset | |
4 | U32 | write-data-size | |
write-data-size | U8 array | write-data |
To remove a file or directory from the share the server will send this message. The client will then respond with a Generic status response message providing the server with the status of the operation.1 It is the client's responsibility to ensure the path is removed before it returns the result.2 If there is a non-zero status the errors are as follows:
Status | Description |
---|---|
1 | Permission denied. |
2 | Entry not found. |
3 | Entry busy. |
4 | General IO error. |
This message contains the following structure:
No. of bytes | Type | Value | Description |
---|---|---|---|
1 | U8 | 249 | message-type |
4 | U32 | 19 | message-sub-type |
4 | U32 | transaction-id | |
4 | U32 | path-length | |
path-length | U8 array | path |
To move a file or directory from the share the server will send this message. The client will then respond with a Generic status response message providing the server with the status of the operation.1 It is the client's responsibility to ensure the requested path is moved before it returns the result.2 If there is a non-zero status the errors are as follows:
Status | Description |
---|---|
1 | Permission denied. |
2 | Entry not found. |
3 | Entry busy. |
4 | General IO error. |
This message contains the following structure:
No. of bytes | Type | Value | Description |
---|---|---|---|
1 | U8 | 249 | message-type |
4 | U32 | 20 | message-sub-type |
4 | U32 | transaction-id | |
4 | U32 | path-length | |
path-length | U8 array | path | |
4 | U32 | new-path-length | |
new-path-length | U8 array | new-path |
To create directory from the share the server will send this message. The client will then respond with a Generic status response message providing the server with the status of the operation. It is the client's responsibility to ensure the requested path is created before it returns the result.2 If there is a non-zero status the errors are as follows:
Status | Description |
---|---|
1 | Permission denied. |
2 | Directory exists. |
3 | Parent path not found. |
4 | General IO error. |
This message contains the following structure:
No. of bytes | Type | Value | Description |
---|---|---|---|
1 | U8 | 249 | message-type |
4 | U32 | 21 | message-sub-type |
4 | U32 | transaction-id | |
4 | U32 | path-length | |
path-length | U8 array | path |
[1] | (1, 2, 3, 4) The client's underlying file system will limit if a file or directory may be moved or removed if it is currently in use. The client will have to report this error up to the server so that it can give the appropriate message to the host operating system. |
[2] | (1, 2, 3, 4, 5, 6, 7, 8, 9) The client should have a provision for timing out on a file system operation and returning an error to the server. This means the server must wait for a response from the client before continuing. The only exception to this is if the client disconnects during the specified operation the server can continue and return an error to the host operating system. |
[3] | (1, 2) It is in the best interest of performance to manage block size keeping in mind that larger block sizes will give faster file transfer while smaller block sizes will allow servers to interleave framebuffer updates in between blocks. |