docs/dev/protocol_reference.md
This document provides a comprehensive reference for the Deskflow network protocol. It is the primary source of information for developers implementing Deskflow clients or extending the protocol.
The Deskflow protocol enables keyboard and mouse sharing between multiple computers over a TCP network connection. The protocol uses two distinct sets of terminology to describe the roles of the computers involved:
Network Role (Client/Server): This describes the connection architecture.
Input Control Role (Primary/Secondary): This describes the flow of keyboard and mouse events.
In a typical setup, the Primary computer (the one whose keyboard and mouse are shared) also acts as the Server. However, the protocol is flexible and allows these roles to be separate. For example, a Primary machine can act as a Client to connect to a Secondary machine that is configured as a Server. This can be useful for navigating restrictive network environments like firewalls.
Throughout the documentation, message direction is often described using the Primary/Secondary roles to clarify the input control flow, while Client/Server roles are used when discussing the underlying network connection.
The protocol is designed to be:
┌─────────────────┐ TCP/IP Network ┌─────────────────┐
│ Primary │◄────────────────────►│ Secondary │
│ (Server) │ Port 24800 │ (Client) │
│ │ │ │
│ • Shares input │ │ • Receives input│
│ • Manages layout│ │ • Reports info │
│ • Coordinates │ │ • Executes cmds │
└─────────────────┘ └─────────────────┘
The protocol operates over a standard TCP connection on port 24800. In protocol versions 1.4 and later, TLS encryption is supported for secure communications.
The client's connection lifecycle is defined by five primary states:
┌──────────────────┐
│ START │
└────────┬─────────┘
│
▼
┌────────┴─────────┐
│ DISCONNECTED │
│ (Initial & │◄───────────────────┐
│ Final State) │ │
└────────┬─────────┘ │
│ │
▼ │
┌──────────────────┐ │
│ CONNECTING │ TCP Failure │
│ (TCP handshake) ├───────────────────►┤
└────────┬─────────┘ │
│ │
TCP Success │ │
│ │
▼ │
┌──────────────────┐ │
│ HANDSHAKE │ Version Mismatch │
│ (Hello/HelloBk) ├───────────────────►┤
└────────┬─────────┘ │
│ │
OK │ │
│ │
▼ │
┌──────────────────┐ │
│ CONNECTED │ CCLOSE (close) │
┌───►│ (Authenticated ├───────────────────►┤
│ │ but inactive) │ │
│ └────────┬─────────┘ │
│ │ │
COUT │ CINN │ │
(Leave) │ (Enter)│ │
│ ▼ │
│ ┌──────────────────┐ │
└────┤ ACTIVE │ CCLOSE (close) │
│ (Receiving all ├───────────────────►┘
┌───►│ input events) │
│ └────────┬─────────┘
│ │
│ ▼
│ ┌──────────────────┐
└────┤ PROCESS EVENT │
└──────────────────┘
Handshake state.Disconnected.Connected, failure sends @ref kMsgEIncompatible error.Active.Connected.Disconnected.The protocol organizes messages into logical categories:
| Category | Prefix | Purpose | Examples |
|---|---|---|---|
| [Handshake](@ref protocol_handshake) | None | Connection setup | @ref kMsgHello, @ref kMsgHelloBack |
| [Commands](@ref protocol_commands) | C | Screen control | @ref kMsgCEnter, @ref kMsgCLeave, @ref kMsgCKeepAlive |
| [Data](@ref protocol_data) | D | Input events | @ref kMsgDKeyDown, @ref kMsgDMouseMove, @ref kMsgCClipboard, @ref kMsgDClipboard |
| [Queries](@ref protocol_queries) | Q | Information requests | @ref kMsgQInfo |
| [Errors](@ref protocol_errors) | E | Error notifications | @ref kMsgEIncompatible, @ref kMsgEBusy |
This table lists all protocol messages in alphabetical order. For a typical sequence of messages, see the Typical Control Flow section.
| Message | Constant | Category | Direction | Purpose | Constraints | Protocol Version |
|---|---|---|---|---|---|---|
| [CALV](@ref kMsgCKeepAlive) | @ref kMsgCKeepAlive | Command | Both | Keep-alive | MsgSize, KeepAlive | 1.3+ |
| [CBYE](@ref kMsgCClose) | @ref kMsgCClose | Command | Server→Client | Close connection | MsgSize | 1.0+ |
| [CCLP](@ref kMsgCClipboard) | @ref kMsgCClipboard | Command | Both | Clipboard ownership notification | MsgSize | 1.0+ |
| [CIAK](@ref kMsgCInfoAck) | @ref kMsgCInfoAck | Command | Server→Client | Acknowledge info message | MsgSize | 1.0+ |
| [CINN](@ref kMsgCEnter) | @ref kMsgCEnter | Command | Server→Client | Enter screen | MsgSize, ScreenEntrySync | 1.0+ |
| [CNOP](@ref kMsgCNoop) | @ref kMsgCNoop | Command | Both | No operation | MsgSize | 1.0+ |
| [COUT](@ref kMsgCLeave) | @ref kMsgCLeave | Command | Server→Client | Leave screen | MsgSize | 1.0+ |
| [CROP](@ref kMsgCResetOptions) | @ref kMsgCResetOptions | Command | Server→Client | Reset options to defaults | MsgSize | 1.0+ |
| [CSEC](@ref kMsgCScreenSaver) | @ref kMsgCScreenSaver | Command | Server→Client | Screen saver control | MsgSize | 1.0+ |
| [DCLP](@ref kMsgDClipboard) | @ref kMsgDClipboard | Data | Both | Clipboard data | MsgSize | 1.0+ |
| [DDRG](@ref kMsgDDragInfo) | @ref kMsgDDragInfo | Data | Server→Client | Drag file info | MsgSize, ListSize | 1.5+ |
| [DFTR](@ref kMsgDFileTransfer) | @ref kMsgDFileTransfer | Data | Both | File transfer data | MsgSize | 1.5+ |
| [DINF](@ref kMsgDInfo) | @ref kMsgDInfo | Data | Client→Server | Screen information | MsgSize | 1.0+ |
| [DKDL](@ref kMsgDKeyDownLang) | @ref kMsgDKeyDownLang | Data | Server→Client | Key down with language | MsgSize, KeyMap | 1.8+ |
| [DKDN](@ref kMsgDKeyDown) | @ref kMsgDKeyDown | Data | Server→Client | Key down | MsgSize, KeyMap | 1.1+ |
| [DKDN](@ref kMsgDKeyDown1_0) | @ref kMsgDKeyDown1_0 | Data | Server→Client | Key down (legacy) | MsgSize, KeyMap | 1.0 |
| [DKRP](@ref kMsgDKeyRepeat) | @ref kMsgDKeyRepeat | Data | Server→Client | Key repeat | MsgSize, KeyMap | 1.1+ |
| [DKRP](@ref kMsgDKeyRepeat1_0) | @ref kMsgDKeyRepeat1_0 | Data | Server→Client | Key repeat (legacy) | MsgSize, KeyMap | 1.0 |
| [DKUP](@ref kMsgDKeyUp) | @ref kMsgDKeyUp | Data | Server→Client | Key up | MsgSize, KeyMap | 1.1+ |
| [DKUP](@ref kMsgDKeyUp1_0) | @ref kMsgDKeyUp1_0 | Data | Server→Client | Key up (legacy) | MsgSize, KeyMap | 1.0 |
| [DMDN](@ref kMsgDMouseDown) | @ref kMsgDMouseDown | Data | Server→Client | Mouse down | MsgSize | 1.0+ |
| [DMMV](@ref kMsgDMouseMove) | @ref kMsgDMouseMove | Data | Server→Client | Mouse move (absolute) | MsgSize | 1.0+ |
| [DMRM](@ref kMsgDMouseRelMove) | @ref kMsgDMouseRelMove | Data | Server→Client | Mouse move (relative) | MsgSize | 1.2+ |
| [DMUP](@ref kMsgDMouseUp) | @ref kMsgDMouseUp | Data | Server→Client | Mouse up | MsgSize | 1.0+ |
| [DMWM](@ref kMsgDMouseWheel) | @ref kMsgDMouseWheel | Data | Server→Client | Mouse wheel | MsgSize | 1.3+ |
| [DMWM](@ref kMsgDMouseWheel1_0) | @ref kMsgDMouseWheel1_0 | Data | Server→Client | Mouse wheel (legacy) | MsgSize | 1.0-1.2 |
| [DSOP](@ref kMsgDSetOptions) | @ref kMsgDSetOptions | Data | Server→Client | Set options | MsgSize, ListSize | 1.0+ |
| [EBAD](@ref kMsgEBad) | @ref kMsgEBad | Error | Server→Client | Protocol violation | MsgSize | 1.0+ |
| [EBSY](@ref kMsgEBusy) | @ref kMsgEBusy | Error | Server→Client | Server busy | MsgSize | 1.0+ |
| [EICV](@ref kMsgEIncompatible) | @ref kMsgEIncompatible | Error | Server→Client | Incompatible version | MsgSize | 1.0+ |
| [EUNK](@ref kMsgEUnknown) | @ref kMsgEUnknown | Error | Server→Client | Unknown client | MsgSize | 1.0+ |
| [Hello](@ref kMsgHello) | @ref kMsgHello | Handshake | Server→Client | Protocol identification | HelloSize, MsgSize | 1.0+ |
| [HelloArgs](@ref kMsgHelloArgs) | @ref kMsgHelloArgs | Handshake | Internal | Hello message construction | HelloSize, MsgSize | 1.0+ |
| [HelloBack](@ref kMsgHelloBack) | @ref kMsgHelloBack | Handshake | Client→Server | Client identification | HelloSize, MsgSize, HandshakeTimeout | 1.0+ |
| [HelloBackArgs](@ref kMsgHelloBackArgs) | @ref kMsgHelloBackArgs | Handshake | Internal | HelloBack message construction | HelloSize, MsgSize, HandshakeTimeout | 1.0+ |
| [LSYN](@ref kMsgDLanguageSynchronisation) | @ref kMsgDLanguageSynchronisation | Data | Server→Client | Language synchronization | MsgSize | 1.8+ |
| [QINF](@ref kMsgQInfo) | @ref kMsgQInfo | Query | Server→Client | Request screen info | MsgSize | 1.0+ |
| [SECN](@ref kMsgDSecureInputNotification) | @ref kMsgDSecureInputNotification | Data | Server→Client | Secure input notification | MsgSize | 1.7+ |
<a id="typical-control-flow"></a>
A typical control flow is as follows:
Hello and HelloBack messages to agree on a protocol version.QINF, and the client responds with DINF.DSOP to configure client options.CALV messages to maintain the connection.CINN to grant control to the client.DMMV, DMDN, DKDN).COUT to revoke control from the client.CCLOSE to terminate the connection.To ensure security, stability, and compatibility, the protocol enforces strict constraints:
<a id="constraint-max-msg"></a>
Maximum Message Size:
<a id="constraint-protocol-max-message-length"></a>4,194,304 bytes (4 MB) — @ref PROTOCOL_MAX_MESSAGE_LENGTH
Maximum total size of any single, length-prefixed data packet
Defined in Protocol Limits
Maximum List Size:
<a id="constraint-max-list"></a>1,048,576 elements — @ref PROTOCOL_MAX_LIST_LENGTH
Maximum number of items in a list/vector within a message
Defined in Protocol Limits
Maximum Hello Size:
<a id="constraint-max-hello"></a>1,024 bytes — @ref kMaxHelloLength
Maximum size of the initial Connection Handshake message
Defined in Protocol Limits
<a id="constraint-tls"></a>
When encryption is enabled, the protocol follows this sequence:
Implementation Details:
Certificate Validation:
A modifier (modifier mask) represents the state of modifier keys (like Shift, Control, Alt, and Command) on a keyboard. It is a binary code (like 0000 0110) where each bit corresponds to a specific modifier key.
Key-Up/Key-Down Strategy:
Modifier Remapping:
<a id="constraint-keep-alive"></a>
Server-Side Behavior:
Client-Side Behavior:
<a id="constraint-screen-entry-sync"></a>
<a id="constraint-handshake-timeout"></a>
| Version | Release Date | Project | Features | Compatibility |
|---|---|---|---|---|
| 1.0 | May 2001 | Synergy | Basic keyboard/mouse sharing (@ref kMsgDKeyDown, @ref kMsgDMouseMove) | All versions |
| 1.1 | Apr 2002 | Synergy | Physical key codes (@ref KeyButton) | 1.1+ |
| 1.2 | Jan 2006 | Synergy | Relative mouse movement | 1.2+ |
| 1.3 | May 2006 | Synergy | Keep-alive (@ref kMsgCKeepAlive), horizontal scroll (@ref kMsgDMouseWheel) | 1.3+ |
| 1.4 | Nov 2012 | Synergy | Encryption support (@ref SecureSocket) | 1.4+ |
| 1.5 | Sep 2013 | Synergy | File transfer | 1.5+ |
| 1.6 | Jan 2014 | Synergy | Clipboard streaming | 1.6+ |
| 1.7 | Nov 2021 | Synergy | Secure input notifications | 1.7+ |
| 1.8 | Jun 2025 | Synergy | Language synchronization | 1.8+ |
When implementing a client that supports multiple protocol versions:
Hello message before using version-specific featuresEIncompatible error gracefully// 1. Connect to server
std::string server_ip = "192.168.1.100";
connect(server_ip, 24800);
// 2. Receive Hello from server
auto hello = receive_message();
std::string server_version, server_name;
parse_hello(hello, &server_version, &server_name);
// 3. Send HelloBack to server
std::string client_version = "1.8";
std::string client_name = "MyClient";
send_hello_back(client_version, client_name);
// 4. Enter main message loop
bool connected = true;
while (connected) {
auto message = receive_message();
handle_message(message);
}
void handle_message(const Message& msg) {
switch (msg.type) {
case "CINN": // Enter screen
handle_enter(msg.x, msg.y, msg.sequence, msg.modifiers);
break;
case "DKDN": // Key down
handle_key_down(msg.key_id, msg.modifiers, msg.key_button);
break;
case "DMMV": // Mouse move
handle_mouse_move(msg.x, msg.y);
break;
// ... handle other message types
}
}
Below is a typical message exchange sequence for a client connecting to a server:
Client Server
| |
| | Server starts listening on port 24800
| |
| TCP SYN |
| ───────────────────────────────────► |
| |
| ◄─────────────────────────────────── |
| TCP SYN+ACK |
| |
| TCP ACK |
| ───────────────────────────────────► |
| | TCP connection established
| |
| ◄─────────────────────────────────── |
| "Deskflow" + version (1.8) | Hello message
| |
| "Deskflow" + version + name |
| ───────────────────────────────────► | HelloBack message
| |
| ◄─────────────────────────────────── |
| "QINF" | Query screen info
| |
| "DINF" + screen dimensions |
| ───────────────────────────────────► | Report screen info
| |
| ◄─────────────────────────────────── |
| "DSOP" + options | Set options
| |
| ◄─────────────────────────────────── |
| "CALV" | Keep-alive
| |
| "CALV" |
| ───────────────────────────────────► | Keep-alive response
| |
| ◄─────────────────────────────────── |
| "CINN" + x + y + seq + mask | Enter screen
| |
| ◄─────────────────────────────────── |
| "DMMV" + x + y | Mouse move
| |
| ◄─────────────────────────────────── |
| "DMDN" + button | Mouse down
| |
| ◄─────────────────────────────────── |
| "DMUP" + button | Mouse up
| |
| ◄─────────────────────────────────── |
| "DKDN" + key + mask + button | Key down
| |
| ◄─────────────────────────────────── |
| "DKUP" + key + mask + button | Key up
| |
| ◄─────────────────────────────────── |
| "COUT" | Leave screen
| |
| ◄─────────────────────────────────── |
| "CCLOSE" | Close connection
| |
| TCP FIN |
| ◄─────────────────────────────────── |
| |
| TCP FIN+ACK |
| ───────────────────────────────────► |
| | Connection closed
Legend:
For platform-specific implementation details, refer to:
Connection Management
Message Processing
Screen Management
Input Synthesis
Clipboard Synchronization
File Transfer (v1.5+)
Security Features
The @ref ServerProxy class provides a reference implementation demonstrating:
When extending the protocol:
This documentation is generated from the source code and is always up-to-date with the latest protocol implementation.