xfreerdp and sdl-freerdp sit on top of libfreerdp (the protocol core), which in turn relies on libwinpr for OS-abstraction primitives. Virtual channel plugins extend the protocol with optional capabilities.
Major Components
libfreerdp — the protocol core
libfreerdp — the protocol core
libfreerdp implements the full RDP protocol stack: negotiation, capability exchange, input/output, graphics pipeline, licensing, and channel multiplexing. Every public API lives behind the FREERDP_API visibility macro and is declared in include/freerdp/.Key internal modules (libfreerdp/core/):| Module | Responsibility |
|---|---|
connection.c | Connection state machine |
nego.c | Protocol/security negotiation |
nla.c | Network Level Authentication (CredSSP) |
mcs.c | MCS channel multiplexing |
fastpath.c | Fast-path input/output |
channels.c | Virtual channel dispatch |
codecs.c | Codec context lifecycle |
transport.c | TCP / TLS transport |
libwinpr — WinAPI portability layer
libwinpr — WinAPI portability layer
libwinpr provides Windows API compatibility on Linux, macOS, and BSD: threading primitives (HANDLE, wThread), SSPI for NTLM/Kerberos, stream utilities (wStream), logging (wLog), and more. FreeRDP code uses WinPR types exclusively so that the same source compiles on every platform.Virtual channel plugins
Virtual channel plugins
Each virtual channel is a loadable plugin that follows either the static virtual channel (SVC) or dynamic virtual channel (DVC) plugin ABI. Plugins live under
channels/ and are built as separate shared libraries (e.g. libfreerdp-client-cliprdr.so). See Channels for a full list.Client frontends
Client frontends
Frontends are thin wrappers that create a
freerdp instance, populate settings, register callbacks, and run an event loop:- xfreerdp — X11 frontend (
client/X11/) - sdl-freerdp — SDL2/SDL3 cross-platform frontend (
client/SDL/) - wfreerdp — Windows native frontend (
client/Windows/) - libfreerdp-client — Shared client helper library used by all frontends
Server / peer side
Server / peer side
libfreerdp also contains a server-side peer API. A freerdp_peer struct (include/freerdp/peer.h) exposes callbacks such as Capabilities, PostConnect, Activate, and Logon that a server application implements. The shadow server (server/shadow/) is a full reference implementation.Connection Lifecycle
The diagram below shows the sequence a client goes through fromfreerdp_new() to an active session.
TCP connect
freerdp_connect() resolves the hostname from FreeRDP_ServerHostname and opens a TCP connection to FreeRDP_ServerPort (default 3389).Protocol negotiation
nego.c sends a Connection Request with the requested security protocol (PROTOCOL_TLS, PROTOCOL_HYBRID for NLA, etc.) and waits for the server’s Connection Confirm.TLS handshake
The raw TCP socket is upgraded to TLS. Certificate verification fires the
VerifyCertificateEx or VerifyX509Certificate callback.NLA / CredSSP
When NLA is negotiated,
nla.c performs a CredSSP handshake carrying SPNEGO tokens (NTLM or Kerberos). The AuthenticateEx callback supplies credentials.Capability exchange
MCS and GCC data blocks carry client/server capability sets. FreeRDP creates three
rdpSettings instances: initial config, remote peer settings, and merged settings.The rdpContext Structure
rdpContext (include/freerdp/freerdp.h) is the central hub that ties every subsystem together. It is allocated by freerdp_context_new() and lives for the duration of the connection.
rdpContext by setting instance->ContextSize to sizeof(MyClientContext), where MyClientContext embeds rdpContext as its first field:
The rdp_freerdp Instance
The freerdp typedef (struct rdp_freerdp) is the top-level handle passed to every public API. It carries:
| Field | Description |
|---|---|
context | Pointer to rdpContext |
ContextSize | Size used by freerdp_context_new() for the context allocation |
ContextNew / ContextFree | Lifecycle callbacks for context allocation |
PreConnect / PostConnect | Connection phase callbacks |
Authenticate / AuthenticateEx | Credential supply callbacks |
VerifyCertificateEx | Certificate acceptance callback |
VerifyX509Certificate | Full PEM certificate verification callback |
LoadChannels | Called to configure channel plugins (possibly multiple times on redirect) |
SendChannelData / ReceiveChannelData | Low-level channel I/O |
Client Frontend Pattern
All bundled frontends follow the same pattern.The
RDP_CLIENT_ENTRY_POINTS struct (include/freerdp/client.h) provides an alternative entry-point mechanism used by the client helper library (libfreerdp-client). Frontends that use RdpClientEntry get GlobalInit, ClientNew, ClientStart, and ClientStop callbacks managed automatically.