bvterm 2.xx Protocol Specification
==============================================================================
This document is Copyright (C) 2010 by Bitvise Limited.
Last updated: 2010-10-19
This document and the information contained herein are provided on an
"AS IS" basis. BITVISE LIMITED DISCLAIMS ALL WARRANTIES, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF
THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
==============================================================================
The purpose of the bvterm terminal protocol is to provide a quality Windows
terminal experience that cannot be achieved with other well established
terminal protocols such as xterm.
On Windows, character based applications receive keyboard input and render
their output in a Windows Console. bvterm 2.xx is based on the Windows
Console API; it may even loosely be viewed as a Windows Console API remote
procedure call specification.
The current protocol version is 2.0. As of the time of this writing,
bvterm 2.xx is supported by Bitvise WinSSHD 5.xx, and Tunnelier 4.25 or newer.
Older versions of WinSSHD and Tunnelier supported bvterm versions 1.xx.
Bitvise considers these versions obsolete for new implementations, and
recommends implementation of bvterm 2.0 as described herein.
bvterm is intended for integration with SSH. Most of the bvterm protocol
requires only a reliable communication channel supporting an 8-bit binary
stream in both directions. However, an external mechanism such as SSH channel
requests is needed for initial negotiation.
Packet format:
byte[3] packet-size (little-endian, not counting the size field itself)
byte packet-type
Types used in packet definitions:
bool =
byte boolean-value (zero = false, non-zero = true)
word16 =
byte[2] value (little-endian)
word32 =
byte[4] value (little-endian)
charinfo =
word16 unicode-char
word16 attribute (Windows Console attribute)
Implementations must ignore packets of unrecognized types.
When packets contain superfluous data beyond recognized fields, such
superfluous data must also be ignored.
Server-to-client packets
========================
The client must be able to accept packets with a size of up to 409600 bytes.
byte BVT_BEEP = 6
word32 frequency
word32 duration
Sent by the server to have the client generate a tone on the PC speaker.
For more information, please lookup Beep() in MSDN.
The BVT_BEEP packet has been adopted from bvterm 1.2.
byte BVT_MESSAGE_BEEP = 7
word32 type
Sent by the server to have the client play a waveform sound.
For more information, please lookup MessageBeep() in MSDN.
The BVT_MESSAGE_BEEP packet has been adopted from bvterm 1.2.
byte BVT_VERSION = 8
byte version
Sent by the server to enable the bvterm version chosen by the server. The
server can choose one of the bvterm versions that the client has requested
in the "bvterm-req" channel request. Please see the "Integrating bvterm
with SSH2" section for more information.
The most significant 4 bits of the version byte represent the major version,
while the less significant 4 bits represent the minor bvterm version.
For example, 2.0 is encoded as 0x20.
This packet can only be sent as the first - initial packet. The client
must ignore any BVT_VERSION packets received at a different point. Clients
implementing older bvterm versions must assume bvterm version 1.1 if the
first packet sent by the server is not BVT_VERSION. Clients implementing
only bvterm 2.xx must report an error and close the channel if the first
packet received is not BVT_VERSION, or if the version byte is less than 0x20.
The BVT_VERSION packet has been adopted from bvterm 1.2.
byte BVT_SET_TEXT_ATTRIBUTE = 9
word16 attribute
Sent by the server to set a current text attribute on the client. The
current text attribute value affects the BVT_SET_BUFFER_SIZE packet only.
The server should set it before sending any BVT_SET_BUFFER_SIZE packets.
For more information, please lookup SetConsoleTextAttribute() in MSDN.
byte BVT_SET_BUFFER_SIZE = 10
word16 columns
word16 rows
Sent by the server to set a new screen buffer size on the client. If the
screen buffer is enlarged in any way, then the client must fill the new cells
with space characters (' ') and the current text attribute. The server should
have previously set the current text attribute with BVT_SET_TEXT_ATTRIBUTE.
If the server has failed to set a current text attribute, the client should
assume the default text attribute of a newly opened Windows Command prompt -
gray text, without intensity, on a black background.
For more information, please lookup SetConsoleScreenBufferSize() in MSDN.
byte BVT_SCROLL_BUFFER = 11
word16 scroll-left
word16 scroll-top
word16 scroll-right
word16 scroll-bottom
word16 clip-left
word16 clip-top
word16 clip-right
word16 clip-bottom
word16 dest-column
word16 dest-row
charinfo fill-character
bool fill-double-width
Sent by the server to scroll screen buffer on the client.
Fill-double-width is true if fill-character on the server occupies two
columns in width.
According to the MSDN's IsDBCSLeadByteEx() documentation, only the following
Windows Console code pages are capable of displaying double-width characters:
932 (Japanese Shift-JIS)
936 (Simplified Chinese GBK)
949 (Korean Unified Hangul Code)
950 (Traditional Chinese Big5)
1361 (Korean Johab)
The Tunnelier bvterm client outputs to a Windows console, and will replace
fill-character with '?' if fill-double-width is true and the client's console
code page is not one of the above.
For more information about other fields, please lookup
ScrollConsoleScreenBuffer() in MSDN.
byte BVT_SET_CURSOR_POS = 12
word16 column
word16 row
Sent by the server to set a cursor position on the client.
For more information, please lookup SetConsoleCursorPos() in MSDN.
byte BVT_SET_CURSOR_INFO = 13
word32 size
bool visible
Sent by the server to set cursor settings on the client.
For more information, please lookup SetConsoleCursorInfo() in MSDN.
byte BVT_SET_WINDOW_INFO = 14
word32 window-info-magic
bool absolute
word16 left
word16 top
word16 right
word16 bottom
Sent by the server to set a window size and position on the client.
For information about window-info-magic, please see BVT_WINDOW_SIZE_NOTIFY.
For more information about other fields, please lookup
SetConsoleWindowInfo() in MSDN.
byte BVT_WRITE_OUTPUT_CHARACTER = 15
word32 character-count
word16 unicode-character[character-count]
word32 double-width-count
byte double-width[double-width-count]
word16 column
word16 row
Sent by the server to print characters to the client's screen buffer.
Double-width array is a bit vector for the unicode-character array. If a
particular unicode-character on the server occupies two columns in width,
then its associated double-width bit will be set. Double-width array may
hold less bits than there are unicode-characters, in which case the missing
double-width bytes are assumed to be 0x00. Accordingly, the server may
completely omit the double-width array (double-width-count set to 0) if
there are no double width characters present in the packet. In a two byte
0x06 0x01 double-width array, the 2nd, 3rd, and 9th character are double
width.
For more information, please lookup WriteConsoleOutputCharacter() in MSDN.
byte BVT_WRITE_OUTPUT_ATTRIBUTE = 16
word32 attribute-count
word16 attribute[attribute-count]
word16 column
word16 row
Sent by the server to apply attributes to the client's screen buffer.
For more information, please lookup WriteConsoleOutputAttribute() in MSDN.
byte BVT_FILL_OUTPUT_CHARACTER = 17
word16 unicode-character
bool double-width
word32 length
word16 column
word16 row
Sent by the server to fill the client's screen buffer with the requested
character.
Double-width is true if unicode-character on the server occupies two
columns in width.
For more information about other fields, please lookup
FillConsoleOutputCharacter() in MSDN.
byte BVT_FILL_OUTPUT_ATTRIBUTE = 18
word16 attribute
word32 length
word16 column
word16 row
Sent by the server to fill the client's screen buffer with the requested
attribute.
For more information, please lookup WriteConsoleOutputAttribute() in MSDN.
byte BVT_WRITE_OUTPUT = 19
word32 character-count
charinfo character[output-count]
word16 left
word16 top
word16 right
word16 bottom
Sent by the server to both print characters and apply attributes to the
client's screen buffer.
For more information, please lookup WriteConsoleOutput() in MSDN.
Note that the character array may hold single width characters only.
byte BVT_FILL_OUTPUT = 20
charinfo character
word16 left
word16 top
word16 right
word16 bottom
Sent by the server to fill the client's screen buffer with the requested
character and attribute.
For more information, please lookup FillConsoleOutput() in MSDN.
Note that the character array may hold single width characters only.
Client-to-server packets
========================
The server must accept packets with a size of up to 4096 bytes.
byte BVT_KEY = 128
bool key-down
byte repeat-count
word16 virtual-key-code
word16 unicode-character
word32 control-key-state
Sent by the client to describe a keyboard event that has taken place.
For more information, please lookup KEY_EVENT_RECORD in MSDN. Note that
the virtual-key-scan field is omitted because it is device-dependent.
The BVT_KEY packet has been adopted from bvterm 1.0.
byte BVT_BUFFER_SIZE_REQEST = 129
word16 columns
word16 rows
Sent by the client to request a resize of the buffer. The client must not
resize the buffer on its own, but must wait for server to respond with a
BVT_SET_BUFFER_SIZE packet.
The BVT_BUFFER_SIZE_NOTIFY packet has been adopted from bvterm 1.0.
byte BVT_WINDOW_SIZE_NOTIFY = 130
word32 last-window-info-magic
word16 columns-minus-1
word16 rows-minus-1
Sent by the client to notify a resize of the viewing area. No response is
to be sent back by the server.
Last-window-info-magic must be set to the last window-info-magic received
with BVT_SET_WINDOW_INFO. If such a packet has not yet been received, then
last-window-info-magic must be set to 0. The server should ignore
BVT_WINDOW_SIZE_NOTIFY packets where last-window-info-magic does not match
the last windows-info-magic sent in BVT_SET_WINDOW_INFO.
Due to behavior of early bvterm implementations, the columns and rows sent
in this packet are subtracted by 1. The client sends:
columns = actual-columns - 1
And the server interprets:
actual-columns = columns + 1
The BVT_WINDOW_SIZE_NOTIFY packet has been adopted from bvterm 1.0.
byte BVT_SIGNAL = 131
byte ctrl-event
Sent by the client to describe a console CTRL event that has taken place.
Ctrl-event can be either CTRL_C_EVENT (= 0) or CTRL_BREAK_EVENT (= 1).
The BVT_SIGNAL packet has been adopted from bvterm 1.1.
Integrating bvterm with SSH2
============================
Integration of bvterm 2.xx with SSH2 has been adopted from bvterm 1.xx.
At any point after establishing an SSH session, the client begins a bvterm
session by opening a "session" channel, setting up the terminal, and sending
a "shell" channel request.
Instead of preceding the "shell" channel request with "pty-req", the client
must precede it with a "bvterm-req" channel request:
byte SSH_MSG_CHANNEL_REQUEST
uint32 recipient_channel
string "bvterm-req"
boolean want_reply
uint32 initial-buffer-width (e.g. 80)
uint32 initial-buffer-height (e.g. 100)
uint32 initial-window-width (e.g. 80)
uint32 initial-window-height (e.g. 25)
string versions-requested (e.g. "\x20")
If the client wants to find out whether the server supports bvterm, the
client should send "bvterm-req" with want_reply == TRUE. If the server
responds with SSH_MSG_CHANNEL_SUCCESS, then the server supports bvterm and
the client can now safely submit a "shell" channel request. If the server
responds with SSH_MSG_CHANNEL_FAILURE, then the server doesn't support
bvterm and the client should either abort, or revert to another type of
terminal by sending a "pty-req" channel request before "shell".
The versions-requested field is optional for older bvterm implementations,
and was added in bvterm 1.2. A client implementing bvterm 2.xx, but not
older bvterm versions, must not omit this field. A client supporting bvterm
1.2 or newer should use this field to list the bvterm versions that it
supports, in order from most to least desirable. The server, implementing
bvterm 1.2 or newer, must then pick the first bvterm version from the list
that it supports. If this field is missing, "\x11\x10" is assumed.
Each byte in the versions requested string represents a bvterm version.
The more significant 4 bits of that byte represents the major version,
while the less significant 4 bits represents the minor bvterm version.
For example, 2.0 followed by 1.2 and 1.1 is encoded as "\x20\x12\x11".
If the client submits "bvterm-req" as well as "pty-req", or if the client
submits multiple "bvterm-req" packets, the server must act according to
the last of these packets received before the "shell" request.
On compatibility of channel request name with SSH specification
===============================================================
We understand that the SSH specification calls for naming private extensions
using a name@domain syntax.
On this topic, bvterm authors are in disagreement with the SSH specification.
We believe that:
- Names without appendages are easy to choose in a way that is sufficiently
unique, and "bvterm-req" is sufficiently unique.
- The @domain syntax hinders changing status of a name from private to
registered. If an extension becomes standardized and receives an
un-appendaged name, all implementations must be modified to recognize
the new name, even if behavior is identical.
The channel request name "bvterm-req" has been used by our implementations
without issue for nearly a decade. At this point, we believe that defining
an alternative appendaged alias would not serve any goal except a principle,
and would add confusion. We request that new implementations continue to use
the channel request name "bvterm-req" exclusively.
Version history
===============
2010-10-15: First published.
2010-10-19: Added discussion of channel request name, and Version History.