# The RVC Protocol (draft 6!)

Tim Waugh

          twaugh@redhat.com

## Introduction

Throughout this document, a virtual console refers to the active console of a machine; I acknowledge that for some configurations that doesn't mean anything. On Linux machines with virtual consoles configured, there are effectively several consoles, all multiplexed through the same display adapter. The operator can switch between them at will, and some may be graphical while others are textual.

RVC (remote virtual console) is a protocol for remote access to a computer's active virtual text console, and is based on RFB. It allows a client to watch and control changes to the text console of a machine on which an RVC server is running.

Like RFB, RVC makes the client stateless, meaning that a client can disconnect and reconnect without affecting the actual console on the server machine.

## Viewing

The viewing side of the protocol is split into three types of update, based on common tasks for virtual consoles: writing text at the cursor position, scrolling, and other arbitrary updates to characters at certain positions on the screen (as well as cursor position changes).

In addition, the server can report when the machine has switched to a virtual console that is in a graphical mode, in order for the client to be able to use RFB to get updates for that console.

Since different virtual consoles may have different sizes, the server can report a console size change; the client may however request that the server just sends the bottom left rectangle of a console that is too large to display in its entirety.

Unlike RFB, RVC is not demand-driven by the client; the server will send incremental updates as and when they happen. However, the client can request a full screen update explicitly. Since text consoles are not nearly as big as graphical ones, bandwidth considerations don't warrant quite the same concern as with RFB. However, the client can specify (at the beginning of the connection) a maximum rate at which incremental updates are sent.

## Controlling

There is provision in the RVC protocol for the client to control the console at the server (but the server may or may not allow it).

This allows the console input to come from the RVC client instead of (or as well as) an operator situated at the console. The model is of raw terminal input: characters are read from the console at the client end in raw mode, and written in raw mode at the server end.

This results in some differences between using an RVC client and standing in front of the console, but it probably a lot easier to implement on a lot of platforms.

## Representation of text display

The console representation is heavily biased towards the format of Linux's `/dev/vcsa`n``. The console is just a rectangular array of characters (one byte each), each of which has an associated attribute byte. In addition there is a cursor which may be placed over any of the characters.

## RVC Protocol

The RVC protocol, like the RFB protocol, can operate over any reliable transport. RVC also has an initial handshaking phase.

The initial handshaking for RVC consists of `ProtocolVersion`, `Authentication`, `ServerInitialisation` and `ClientInitialisation` messages. Both sides of the protocol send `ProtocolVersion`; the feature set to use is negotiated in the initialisation messages.

The messages begin with a `message-type` byte followed by message-specific data. However, the message formats and their message types differ significantly from those in the RFB protocol.

The messages are in network byte order.

### Handshake messages

`ProtocolVersion`

The server first sends the client a `ProtocolVersion` message, to which the client responds with a similar message detailing the protocol to actually use.

Minor increments in the version number should be feature additions (new messages/features) that the server may optionally provide.

Versions of the protocol that differ in major number are probably not compatible with one another.

The `ProtocolVersion` message is the same as in RFB: 12 ASCII bytes. For RVC, they are as follows.

#### ProtocolVersion

No. of bytes | Value
12 | "RVC 001.000\n" (hex 52 56 43 20 30 30 31 30 30 0a)

#### `Authentication`

The `Authentication` message is just the same as in RFB.

#### `Authentication`

No. of bytes | Type | Value | Description
4 | uint32_t |  | authentication-scheme:
|  | 0 | connection failed
|  | 1 | no authentication
|  | 2 | VNC authentication

This is followed by data specific to the authentication-scheme:

- connection failed---for some reason the connection failed. This is followed by an ASCII string describing why.

  #### connection failed

  No. of bytes | Type | Value | Description
  4 | uint32_t |  | reason-length
  reason-length | uint8_t[] |  | reason-string

  For connection-based transports, the server closes the connection after sending this message.

- no authentication---no authentication is needed and the protocol continues to `ServerInitialisation`.

- VNC authentication---VNC authentication is to be used. This is adequately described in the RFB protocol description and is not covered here.

#### `ServerInitialisation`

The RVC server advertises to the client which features it can provide using the `ServerInitialisation` message.

#### `ServerInitialisation`

No. of bytes | Type | Value | Description
1 | uint8_t | 0 | message-type
1 | uint8_t |  | num-features
num-features | uint8_t[] |  | feature-list

Features that can appear in the feature-list are:

#### Features

Feature | Description
0 | `Key` message
1 | `Pointer` message
2 | Incremental rectangle updates
3 | Incremental scroll updates
4 | Clear screen updates
5 | Console cropping
6 | Console switch reporting
7 | Console display locking
8 | Console input locking
9 | Shareable session
10 | VNC server integration
11 | Console switching
12 | Console pushing

#### `ClientInitialisation`

The `ClientInitialisation` is a response to the `ServerInitialisation` message.

#### `ClientInitialisation`

No. of bytes | Type | Value | Description
1 | uint8_t | 255 | message-type
3 | uint8_t[] | Padding
4 | uint32_t |  | Minimum incremental update period (ms)
1 | uint8_t |  | Rows
1 | uint8_t |  | Columns
1 | uint8_t | 0 | Special flags
1 | uint8_t |  | num-features
num-features | uint8_t[] |  | features-requested

The client specifies the minimum amount of time between unsolicited incremental updates in milliseconds.

It also specifies the number of rows and columns that it has. This information is only needed if the console cropping feature is used.

The features-requested array refers to the features advertised in the `ServerInitialisation` message; if num-features exceeds the number of features advertised, the excess are ignored.

A zero value for a feature request means that the feature must not be used; a value of 1 means that it may be used.

If the console pushing feature is in use, the server and client swap roles, and the original client must send the original server a `ServerInitialisation` message, which may not advertise the console pushing feature.

### Client-originated messages

#### `FullUpdateRequest`

In order to request a full console update, the client uses this message. Incremental updates not covering the entire console area will not be sent by the server until it receives and responds to this message.

#### `FullUpdateRequest`

No. of bytes | Type | Value | Description
1 | uint8_t | 254 | message-type

#### `Key`

If the `Key` feature is in use, the client can send a key to the RVC server.

#### `Key`

No. of bytes | Type | Value | Description
1 | uint8_t | 253 | message-type
1 | uint8_t |  | key

#### `Pointer`

If the `Pointer` feature is in use, the client can send a pointer event to the RVC server.

#### `Pointer`

No. of bytes | Type | Value | Description
1 | uint8_t | 252 | message-type
1 | uint8_t |  | x position
1 | uint8_t |  | y position
1 | uint8_t |  | button-mask

The x and y positions are zero-based, from the top left hand corner. The current state of buttons 1 to 8 are represented by bits 0 to 7 of button-mask respectively, 0 meaning up, 1 meaning down.

#### `SwitchRequest`

A `SwitchRequest` can be used to try to change the active console. If successful, a `Switch` message will be generated (if allowed). Note that if the active console is under programmatic control, the switch request may silently fail.

#### `SwitchRequest`

No. of bytes | Type | Value | Description
1 | uint8_t | 251 | message-type
1 | uint8_t |  | virtual console number

#### `Terminate`

A `Terminate` message causes the server to go back to its initial state (awaiting `ProtocolVersion`), if the connection is still valid.

#### `Terminate`

No. of bytes | Type | Value | Description
1 | uint8_t | 128 | message-type

### Server-originated messages

#### `IncrementalUpdate`

If the incremental update feature is not in use, any `IncrementalUpdate` messages must cover the entire console area.

#### `IncrementalUpdate`

No. of bytes | Type | Value | Description
1 | uint8_t | 1 | message-type
1 | uint8_t |  | update-type:
|  | 0 | rectangle
|  | 1 | scroll
|  | 2 | clear
2 | uint16_t | n | content-length
n | uint8_t[] |  | contents

A client must support rectangle type updates. Other types of update will only be sent if the corresponding feature is in use.

The header is followed by type-specific data.

- For `rectangle` updates the header is followed by:

  #### `rectangle`

  No. of bytes | Type | Value | Description
  1 | uint8_t |  | x offset
  1 | uint8_t |  | y offset
  1 | uint8_t |  | rows
  1 | uint8_t |  | columns
  1 | uint8_t |  | x position
  1 | uint8_t |  | y position
  2*rows*columns | uint8_t[] |  | contents

  The contents are sent in rows, with the first byte of a (row,column) entry being the character at that position, and the second being the attributes. The attribute byte takes the form of VGA text mode character attributes.

- For `scroll` updates the header is followed by:

  #### `scroll`

  No. of bytes | Type | Value | Description
  1 | uint8_t |  | lines to scroll

- For `clear` updates nothing else follows the header.

  The intent of a `clear` update is to tell the client to clear its terminal.

#### `Switch`

If the console switch reporting feature is in use, this message may be sent.

#### `Switch`

No. of bytes | Type | Value | Description
1 | uint8_t | 2 | message-type
1 | uint8_t |  | virtual console number
2 | uint16_t |  | port number
1 | uint8_t |  | mode (0 for text)

The port number is one on which an RFB server is accepting connections for that display, or zero if there is no such server.

### `Terminate`

A `Terminate` message causes the client to go back to its initial state (send `ProtocolVersion`), if the connection is still valid.

### `Terminate`

No. of bytes | Type | Value | Description
1 | uint8_t | 128 | message-type