Code Documentation

api Module

Helpers to allow vncdotool to be intergrated into other applications.

Warning

EXPERIMENTAL. This feature is under development, your help testing and debugging is appreciated.

vncdotool.api.connect(server: str) ThreadedVNCClientProxy[source]
vncdotool.api.connect(server: str, password: str | None) ThreadedVNCClientProxy
vncdotool.api.connect(server: str, password: str | None, factory_class: type[VNCDoToolFactory]) ThreadedVNCClientProxy
vncdotool.api.connect(server: str, password: str | None, factory_class: type[VNCDoToolFactory], proxy: type[TProxy]) TProxy
vncdotool.api.connect(server: str, password: str | None, factory_class: type[VNCDoToolFactory], proxy: type[TProxy], timeout: float | None) TProxy
vncdotool.api.connect(server: str, password: str | None, factory_class: type[VNCDoToolFactory], proxy: type[TProxy], timeout: float | None, username: str | None) TProxy

Connect to a VNCServer and return a Client instance that is usable in the main thread of non-Twisted Python Applications,

>>> from vncdotool import api
>>> with api.connect('host') as client
>>>     client.keyPress('c')

You may then call any regular VNCDoToolClient method on client from your application code.

If you are using a GUI toolkit or other major async library please read Choosing a Reactor and GUI Toolkit Integration for a better method of intergrating vncdotool.

vncdotool.api.shutdown() None[source]

Shutdown background thread running Twisted reactor.

client Module

Twisted based VNC client protocol and factory.

exception vncdotool.client.AuthenticationError[source]

Bases: VNCDoException

VNC Server requires Authentication

exception vncdotool.client.ProtocolError[source]

Bases: VNCDoException

VNC Server sent something we cannot handle

class vncdotool.client.VMWareClient[source]

Bases: VNCDoToolClient

SINGLE_PIXLE_UPDATE = b'\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00'
dataReceived(data: bytes) None[source]

Called whenever data is received.

Use this method to translate to a higher-level message. Usually, some callback will be made upon the receipt of each complete protocol message.

@param data: a string of indeterminate length. Please keep in mind

that you will probably need to buffer some data, as partial (or multiple) protocol messages may be received! I recommend that unit tests for protocols call through to this method with differing chunk sizes, down to one byte at a time.

class vncdotool.client.VMWareFactory[source]

Bases: VNCDoToolFactory

protocol

alias of VMWareClient

exception vncdotool.client.VNCDoException[source]

Bases: Exception

class vncdotool.client.VNCDoToolClient[source]

Bases: RFBClient

MAX_DESKTOP_SIZE = 65536
SPECIAL_KEYS_US = '~!@#$%^&*()_+{}|:"<>?'
bell()[source]
buttons = 0
captureRegion(fp: str | Path | IO[bytes], x: int, y: int, w: int, h: int, incremental: bool = False) Deferred[source]

Save a region of the current display to filename

captureScreen(fp: str | Path | IO[bytes], incremental: bool = False, format: str | None = None) Deferred[source]

Capture and save the current VNC screen display to a file.

Parameters:
fp (TFile): The destination where the screenshot will be saved.

It can be a string path, a pathlib.Path object, or a file-like object opened in binary mode.

incremental (bool, optional):
  • False (default): Captures the entire screen.

  • True: Captures only the regions of the screen that have changed since the last capture.

format (str | None, optional):
cmask: Image | None = None
commitUpdate(rectangles: list[Tuple[int, int, int, int]] | None = None) None[source]

called after a series of updateRectangle(), copyRectangle() or fillRectangle() are finished.

Typicaly, here is the place to request the next screen update with framebufferUpdateRequest() with incremental=True.

Parameters:

rectangles – a list of tuples (x,y,w,h) with the updated rectangles.

connectionLost(reason: Failure) None[source]

Called when the connection is shut down.

Clear any circular references here, and any external references to this Protocol. The connection has been closed.

@type reason: L{twisted.python.failure.Failure}

connectionMade() None[source]

Called when a connection is made.

This may be considered the initializer of the protocol, because it is called when the connection is completed. For clients, this is called once the connection to the server has been established; for servers, this is called after an accept() call stops blocking and a socket has been received. If you need to send any greeting or initial message, do it here.

copy_text(text: str) None[source]

The server has new ISO 8859-1 (Latin-1) text in its cut buffer. (aka clipboard)

cursor: Image | None = None
deferred: Deferred | None = None
drawCursor() None[source]
encoding = 0
expectRegion(filename: str, x: int, y: int, maxrms: float = 0) Deferred[source]

Wait until a portion of the screen matches the target image

The region compared is defined by the box (x, y), (x + image.width, y + image.height)

expectScreen(filename: str, maxrms: float = 0) Deferred[source]

Wait until the display matches a target image

Parameters:
  • filename – an image file to read and compare against.

  • maxrms – the maximum root mean square between histograms of the screen and target image.

property image_mode: str
keyDown(key: str) TClient[source]
keyPress(key: str) TClient[source]

Send a key press to the server

Parameters:

key – either [a-z] or a from KEYMAP.

keyUp(key: str) TClient[source]
mouseDown(button: int) TClient[source]

Send a mouse button down at the last set position

Parameters:

button – [1-n]

mouseDrag(x: int, y: int, step: int = 1) Iterator[Deferred][source]

Move the mouse point to position (x, y) in increments of step

mouseMove(x: int, y: int) TClient[source]

Move the mouse pointer to position (x, y)

mousePress(button: int) TClient[source]

Send a mouse click at the last set position

Parameters:

button – [1-n]

mouseUp(button: int) TClient[source]

Send mouse button released at the last set position

Parameters:

button – [1-n]

paste(message: str) TClient[source]
pause(duration: float) Deferred[source]
refreshScreen(incremental: bool = False) Deferred[source]
screen: Image | None = None
setImageMode() None[source]

Check support for PixelFormats announced by server or select client supported alternative.

updateCursor(x: int, y: int, width: int, height: int, image: bytes, mask: bytes) None[source]

New cursor, focuses at (x, y)

updateDesktopSize(width: int, height: int) None[source]

New desktop size of width*height.

updateRectangle(x: int, y: int, width: int, height: int, data: bytes) None[source]

new bitmap data.

Parameters:

data – bytes in the pixel format set up earlier.

vncAuthFailed(reason: bytes | str) None[source]

called when the authentication failed. the connection is closed.

vncConnectionMade() None[source]

connection is initialized and ready. typicaly, the pixel format is set here.

vncProtocolError(reason: str) None[source]

called when the server sends something we cannot handle. the connection is closed.

vncRequestPassword() None[source]

a password is needed to log on, use sendPassword() to send one.

x = 0
y = 0
class vncdotool.client.VNCDoToolFactory[source]

Bases: RFBFactory

clientConnectionFailed(connector: <InterfaceClass twisted.internet.interfaces.IConnector>, reason: Failure) None[source]

Called when a connection has failed to connect.

It may be useful to call connector.connect() - this will reconnect.

clientConnectionLost(connector: <InterfaceClass twisted.internet.interfaces.IConnector>, reason: Failure) None[source]

Called when an established connection is lost.

It may be useful to call connector.connect() - this will reconnect.

clientConnectionMade(protocol: VNCDoToolClient) None[source]
force_caps = False
last_rect = True
nocursor = False
password: str | None = None
protocol

alias of VNCDoToolClient

pseudocursor = False
pseudodesktop = True
qemu_extended_key = True
shared = True
username: str | None = None
vncdotool.client.factory_connect(factory: VNCDoToolFactory, host: str, port: int, family: AddressFamily) None[source]

rfb Module

RFB protocol implementattion, client side.

Override RFBClient and RFBFactory in your application. See vncviewer.py for an example.

Reference: https://www.rfc-editor.org/rfc/rfc6143 https://github.com/rfbproto/rfbproto/blob/master/rfbproto.rst

class vncdotool.rfb.PixelFormat(bpp: int = 32, depth: int = 24, bigendian: bool = False, truecolor: bool = True, redmax: int = 255, greenmax: int = 255, bluemax: int = 255, redshift: int = 0, greenshift: int = 8, blueshift: int = 16)[source]

Bases: object

RFC 6143 §7.4. Pixel Format Data Structure.

STRUCT: ClassVar = <_struct.Struct object>
VALIDATE: ClassVar = False
bigendian: bool = False
bluemax: int = 255
blueshift: int = 16
bpp: int = 32
property bypp: int
depth: int = 24
classmethod from_bytes(block: bytes) PixelFormat[source]
greenmax: int = 255
greenshift: int = 8
redmax: int = 255
redshift: int = 0
to_bytes() bytes[source]
truecolor: bool = True
class vncdotool.rfb.RFBClient[source]

Bases: Protocol

MAX_CLIENT_VERSION = (3, 8)
SUPPORTED_AUTHS = {AuthTypes.NONE, AuthTypes.VNC_AUTHENTICATION, AuthTypes.DIFFIE_HELLMAN}
SUPPORTED_ENCODINGS = {Encoding.PSEUDO_QEMU_EXTENDED_KEY_EVENT, Encoding.PSEUDO_CURSOR, Encoding.PSEUDO_LAST_RECT, Encoding.PSEUDO_DESKTOP_SIZE, Encoding.RAW, Encoding.COPY_RECTANGLE, Encoding.RRE, Encoding.CORRE, Encoding.HEXTILE, Encoding.ZRLE}
SUPPORTED_SERVER_VERSIONS = {(3, 3), (3, 7), (3, 8), (3, 889), (4, 0), (4, 1), (5, 0)}
ardRequestCredentials() None[source]
beginUpdate() None[source]

called before a series of updateRectangle(), copyRectangle() or fillRectangle().

bell()[source]
property bypp: int
clientCutText(message: str) None[source]

The client has new ISO 8859-1 (Latin-1) text in its cut buffer. (aka clipboard)

commitUpdate(rectangles: list[Tuple[int, int, int, int]] | None = None) None[source]

called after a series of updateRectangle(), copyRectangle() or fillRectangle() are finished.

Typicaly, here is the place to request the next screen update with framebufferUpdateRequest() with incremental=True.

Parameters:

rectangles – a list of tuples (x,y,w,h) with the updated rectangles.

copyRectangle(srcx: int, srcy: int, x: int, y: int, width: int, height: int) None[source]

used for copyrect encoding. copy the given rectangle (src, srxy, width, height) to the target coords (x,y)

copy_text(text: str) None[source]

The server has new ISO 8859-1 (Latin-1) text in its cut buffer. (aka clipboard)

dataReceived(data: bytes) None[source]

Called whenever data is received.

Use this method to translate to a higher-level message. Usually, some callback will be made upon the receipt of each complete protocol message.

@param data: a string of indeterminate length. Please keep in mind

that you will probably need to buffer some data, as partial (or multiple) protocol messages may be received! I recommend that unit tests for protocols call through to this method with differing chunk sizes, down to one byte at a time.

expect(handler: Callable[[...], None], size: int, *args: Any, **kwargs: Any) None[source]
fillRectangle(x: int, y: int, width: int, height: int, color: bytes) None[source]

fill the area with the color.

Parameters:

color – bytes in the pixel format set up earlier.

framebufferUpdateRequest(x: int = 0, y: int = 0, width: int | None = None, height: int | None = None, incremental: bool = False) None[source]
keyEvent(key: Key | int, down: bool = True) None[source]

For most ordinary keys, the “keysym” is the same as the corresponding ASCII value. Other common keys are shown in the Key constants.

pointerEvent(x: int, y: int, buttonmask: int = 0) None[source]

Indicates either pointer movement or a pointer button press or release. The pointer is now at (x-position, y-position), and 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 (pressed).

sendPassword(password: str) None[source]

send password

setEncodings(list_of_encodings: Collection[Encoding]) None[source]
setPixelFormat(pixel_format: PixelFormat) None[source]
set_color_map(first: int, colors: list[tuple[int, int, int]]) None[source]

The server is using a new color map.

updateCursor(x: int, y: int, width: int, height: int, image: bytes, mask: bytes) None[source]

New cursor, focuses at (x, y)

updateDesktopSize(width: int, height: int) None[source]

New desktop size of width*height.

updateRectangle(x: int, y: int, width: int, height: int, data: bytes) None[source]

new bitmap data.

Parameters:

data – bytes in the pixel format set up earlier.

vncAuthFailed(reason: Failure) None[source]

called when the authentication failed. the connection is closed.

vncConnectionMade() None[source]

connection is initialized and ready. typicaly, the pixel format is set here.

vncProtocolError(reason: str) None[source]

called when the server sends something we cannot handle. the connection is closed.

vncRequestPassword() None[source]

a password is needed to log on, use sendPassword() to send one.

class vncdotool.rfb.RFBFactory(password: str | None = None, shared: bool = False)[source]

Bases: ClientFactory

A factory for remote frame buffer connections.

protocol

alias of RFBClient

vncdotool.rfb.des_encrypt(key: bytes, data: bytes) bytes[source]

Encrypt with single DES, as the VNC family’s password handling uses.

Single DES in ECB is weak, and is what RFB specifies: both the authentication challenge response (RFC 6143 section 7.2.2) and the password file format are defined in terms of it, so a stronger algorithm here would simply fail to talk to any VNC server.

vncdotool.rfb.reverse_bits(data: bytes) bytes[source]

The bit-reversal the VNC family applies to a DES key before using it, both for the authentication challenge response here and for the password obfuscation in ~/.vnc/passwd files.

command Module

Command line interface to interact with a VNC Server.

exception vncdotool.command.CommandParseError[source]

Bases: RuntimeError

class vncdotool.command.ExitStatus(value)[source]

Bases: IntEnum

Exit codes returned by vncdo, grouped by cause.

AUTHENTICATION_FAILED = 3
COMMAND_FAILED = 30
CONNECTION_FAILED = 10
CONNECTION_LOST = 11
ERROR = 1
PROTOCOL_ERROR = 20
SUCCESS = 0
TIMEOUT = 40
USAGE = 2
class vncdotool.command.ExitingProcess[source]

Bases: ProcessProtocol

errReceived(data: bytes) None[source]

Some data was received from stderr.

processExited(reason: Failure) None[source]

This will be called when the subprocess exits.

@type reason: L{twisted.python.failure.Failure}

exception vncdotool.command.TimeoutError[source]

Bases: RuntimeError

class vncdotool.command.VNCDoCLIClient[source]

Bases: VNCDoToolClient

vncRequestPassword() None[source]

a password is needed to log on, use sendPassword() to send one.

class vncdotool.command.VNCDoCLIFactory[source]

Bases: VNCDoToolFactory

clientConnectionFailed(connector: <InterfaceClass twisted.internet.interfaces.IConnector>, reason: Failure) None[source]

Called when a connection has failed to connect.

It may be useful to call connector.connect() - this will reconnect.

clientConnectionLost(connector: <InterfaceClass twisted.internet.interfaces.IConnector>, reason: Failure) None[source]

Called when an established connection is lost.

It may be useful to call connector.connect() - this will reconnect.

done(exit_code: ExitStatus) None[source]
error(reason: Failure, default: ExitStatus = ExitStatus.COMMAND_FAILED) None[source]
protocol

alias of VNCDoCLIClient

static status_for(reason: Failure, default: ExitStatus) ExitStatus[source]
class vncdotool.command.VNCDoToolOptionParser(usage=None, option_list=None, option_class=<class 'optparse.Option'>, version=None, conflict_handler='error', description=None, formatter=None, add_help_option=True, prog=None, epilog=None)[source]

Bases: OptionParser

format_help(formatter: HelpFormatter | None = None) str[source]
vncdotool.command.add_standard_options(parser: OptionParser) OptionParser[source]
vncdotool.command.build_command_list(factory: VNCDoCLIFactory, args: list[str], delay: float | None = None, warp: float = 1.0, incremental_refreshes: bool = False) None[source]
vncdotool.command.build_proxy(options: Values) VNCLoggingServerFactory[source]
vncdotool.command.build_tool(options: Values, args: list[str]) VNCDoCLIFactory[source]
vncdotool.command.log_connected(pcol: TClient) TClient[source]
vncdotool.command.log_exceptions(type_: type[BaseException], value: BaseException, tb: TracebackType | None) None[source]
vncdotool.command.parse_server(server: str) tuple[AddressFamily, str, int][source]
vncdotool.command.setup_logging(options: Values) None[source]
vncdotool.command.vncdo(argv: list[str] | None = None) None[source]
vncdotool.command.vncdo_replay() None[source]

Replay a vnclog –capture-raw archive: serve it, or drive it.

Two processes: –server serves the recorded bytes, and any client (this command without –server, a GUI viewer, or a hand-written vncdo line) can drive the session against it. See docs/capture.rst.

vncdotool.command.vnclog() None[source]

loggingproxy Module

class vncdotool.loggingproxy.NullTransport[source]

Bases: object

addressFamily = 0
loseConnection() None[source]
setTcpNoDelay(enabled: bool) None[source]
write(data: bytes) None[source]
writeSequence(data: bytes) None[source]
exception vncdotool.loggingproxy.ProtocolError[source]

Bases: Exception

VNC Protocol error

class vncdotool.loggingproxy.RFBServer[source]

Bases: Protocol

connectionMade() None[source]

Called when a connection is made.

This may be considered the initializer of the protocol, because it is called when the connection is completed. For clients, this is called once the connection to the server has been established; for servers, this is called after an accept() call stops blocking and a socket has been received. If you need to send any greeting or initial message, do it here.

dataReceived(data: bytes) None[source]

Called whenever data is received.

Use this method to translate to a higher-level message. Usually, some callback will be made upon the receipt of each complete protocol message.

@param data: a string of indeterminate length. Please keep in mind

that you will probably need to buffer some data, as partial (or multiple) protocol messages may be received! I recommend that unit tests for protocols call through to this method with differing chunk sizes, down to one byte at a time.

handle_clientCutText(block: bytes) None[source]
handle_framebufferUpdate(x: int, y: int, w: int, h: int, incremental: bool) None[source]
handle_keyEvent(key: int, down: bool) None[source]
handle_keyEventExtended(keysym: int, down: bool, keycode: int) None[source]
handle_pointerEvent(x: int, y: int, buttonmask: int) None[source]
handle_setEncodings(encodings: Sequence[int]) None[source]
handle_setPixelFormat(pixel_format: PixelFormat) None[source]
class vncdotool.loggingproxy.VNCLoggingClient[source]

Bases: VNCDoToolClient

Specialization of a VNCDoToolClient that will save screen captures.

capture: CaptureWriter | None = None
capture_file: str | None = None
commitUpdate(rectangles: list[Tuple[int, int, int, int]] | None = None) None[source]

called after a series of updateRectangle(), copyRectangle() or fillRectangle() are finished.

Typicaly, here is the place to request the next screen update with framebufferUpdateRequest() with incremental=True.

Parameters:

rectangles – a list of tuples (x,y,w,h) with the updated rectangles.

class vncdotool.loggingproxy.VNCLoggingClientFactory[source]

Bases: ProxyClientFactory

protocol

alias of VNCLoggingClientProxy

class vncdotool.loggingproxy.VNCLoggingClientProxy[source]

Bases: ProxyClient

Accept data from a server and forward to logger and downstream client.

VNC server -> VNCLoggingClientProxy -> VNC client
                                    -> VNCLoggingClient
dataReceived(data: bytes) None[source]

Called whenever data is received.

Use this method to translate to a higher-level message. Usually, some callback will be made upon the receipt of each complete protocol message.

@param data: a string of indeterminate length. Please keep in mind

that you will probably need to buffer some data, as partial (or multiple) protocol messages may be received! I recommend that unit tests for protocols call through to this method with differing chunk sizes, down to one byte at a time.

ncaptures = 0
startLogging(peer: VNCLoggingServerProxy) None[source]
vnclog: VNCLoggingClient | None = None
class vncdotool.loggingproxy.VNCLoggingServerFactory(host: str, port: int)[source]

Bases: ProxyFactory

capture_failed: bool = False
capture_path: str | None = None
capture_preserve_auth: bool = False
clientConnectionLost(client: VNCLoggingServerProxy) None[source]
clientConnectionMade(client: VNCLoggingServerProxy) None[source]
force_caps = False
getRecordedSession() bytes[source]
getRecorder() Callable[[str], int][source]
last_rect = True
nocursor = False
one_shot: bool = False
output: IO[str] | str = <_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'>
password: str | None = None
password_required = False
protocol

alias of VNCLoggingServerProxy

pseudocursor = False
pseudodesktop = True
qemu_extended_key = True
server_address: str = ''
sessionFinished() None[source]

End the process after a –one-shot session, once it has closed.

session_taken: bool = False
shared = True
class vncdotool.loggingproxy.VNCLoggingServerProxy[source]

Bases: ProxyServer, RFBServer

Proxy in the middle, decodes and logs RFB messages before sending them upstream.

VNC client -> VNCLoggingServerProxy -> VNC server
                                    -> RFBServer
buttons = 0
capture: CaptureWriter | None = None
clientProtocolFactory

alias of VNCLoggingClientFactory

connectionLost(reason: Failure) None[source]

Called when the connection is shut down.

Clear any circular references here, and any external references to this Protocol. The connection has been closed.

@type reason: L{twisted.python.failure.Failure}

connectionMade() None[source]

Called when a connection is made.

This may be considered the initializer of the protocol, because it is called when the connection is completed. For clients, this is called once the connection to the server has been established; for servers, this is called after an accept() call stops blocking and a socket has been received. If you need to send any greeting or initial message, do it here.

dataReceived(data: bytes) None[source]

Called whenever data is received.

Use this method to translate to a higher-level message. Usually, some callback will be made upon the receipt of each complete protocol message.

@param data: a string of indeterminate length. Please keep in mind

that you will probably need to buffer some data, as partial (or multiple) protocol messages may be received! I recommend that unit tests for protocols call through to this method with differing chunk sizes, down to one byte at a time.

handle_keyEvent(key: int, down: bool) None[source]
handle_pointerEvent(x: int, y: int, buttonmask: int) None[source]
recorder: Callable[[str], int] | None = None
refused: bool = False
saw_bytes: bool = False
server: str | None = None
took_session: bool = False
property vnclog_client: VNCLoggingClient | None