Skip to main content
The server peer API represents a single connected RDP client from the server’s perspective. Each accepted connection produces a freerdp_peer instance that drives the RDP protocol state machine for that client. Header: <freerdp/peer.h>

Lifecycle

freerdp_peer_new

Allocates a new peer object bound to an already-accepted TCP socket file descriptor. Returns NULL on allocation failure. The returned pointer must eventually be released with freerdp_peer_free().

freerdp_peer_free

Frees all resources associated with the peer, including its context. Call after the peer’s worker thread has exited.

freerdp_peer_context_new / freerdp_peer_context_new_ex

Allocates the rdpContext for the peer and invokes the ContextNew callback. freerdp_peer_context_new_ex allows supplying a pre-built settings object. Must be called before peer->Initialize().

freerdp_peer_context_free

Releases the peer context and calls ContextFree. Called automatically by freerdp_peer_free().

Struct: rdp_freerdp_peer

The core peer struct (typedefd as freerdp_peer). Key fields:
rdpContext*
The RDP context. Access settings via context->settings, update interface via context->update, autodetect via context->autodetect.
int
The underlying TCP socket file descriptor.
char[50]
String representation of the client’s address, populated by freerdp_peer_set_local_and_hostname().
BOOL
TRUE when the connection is from a Unix-domain socket (local).
BOOL
Set to TRUE once the low-level connection is established.
BOOL
Set to TRUE after the Activate callback returns successfully.
BOOL
Set to TRUE after NLA or another authentication mechanism completes.
size_t
Set this to sizeof(YourContext) before calling freerdp_peer_context_new() to extend the context with private data.
void*
Optional extra data pointer passed unchanged through context lifecycle callbacks.

Initialization Callbacks

psPeerContextNew
Called by freerdp_peer_context_new() after allocating the context. Use this to initialize any fields in your custom context struct. Return FALSE to abort.
psPeerContextFree
Called when the context is being freed. Clean up context-private resources here.
psPeerInitialize
Starts the RDP handshake state machine. Must be called once after freerdp_peer_context_new(). Returns FALSE on failure.

Event Loop

psPeerGetEventHandle
Returns a waitable HANDLE (event) that becomes signalled when the peer has data to process. Use with WaitForSingleObject or WaitForMultipleObjects.
psPeerGetEventHandles
Fills events[] with all handles (transport, virtual channels, etc.) that the peer event loop depends on. Returns the number of handles written.
psPeerGetReceiveEventHandle
Returns the specific receive-side event handle.
psPeerCheckFileDescriptor
Processes any pending incoming data. Must be called whenever GetEventHandle becomes signalled. Returns FALSE when the connection should be closed.
psPeerHasMoreToRead
Returns TRUE if the peer input buffer has unprocessed data. Call CheckFileDescriptor again when this returns TRUE without waiting on the handle.
psPeerIsWriteBlocked
Returns TRUE if the send buffer is full. In this case drain it with DrainOutputBuffer before sending more data.
psPeerDrainOutputBuffer
Flushes any buffered outgoing data. Returns > 0 if data remains, 0 when fully drained, < 0 on error.

Connection Callbacks

psPeerCapabilities
Called after the client’s capabilities have been received and merged. Inspect peer->context->settings here to check what the client supports. Return FALSE to reject.
psPeerPostConnect
Called after capabilities negotiation but before Activate. Use this to open virtual channels and configure the update pipeline. Return FALSE to abort.
psPeerActivate
Called when the client has sent its initial Input Synchronize PDU, signalling it is ready to receive screen updates. This is the earliest point to begin sending graphics. Return FALSE to abort.
psPeerLogon
Called after initial authentication succeeds. automatic is TRUE when the connection was already authenticated (e.g. Kerberos SSO), FALSE for RDP/TLS tunnels where credentials arrive here. Return FALSE to deny the connection.
psPeerClientCapabilities
Called when client-capability PDU is processed (alternate hook, complementary to Capabilities).
psPeerLicenseCallback
Custom license handling hook. Return LICENSE_CB_COMPLETED to proceed, LICENSE_CB_ABORT to disconnect.

Disconnection

psPeerClose
Gracefully closes the RDP session by sending a disconnect PDU. Returns FALSE on error.
psPeerDisconnect
Immediately terminates the underlying transport without a graceful disconnect PDU.

Channel I/O

psPeerSendChannelData
Sends a complete static virtual channel PDU in one call.
psPeerSendChannelPacket
Sends a channel PDU chunk with explicit fragmentation flags (CHANNEL_FLAG_FIRST, CHANNEL_FLAG_LAST, etc.).
psPeerReceiveChannelData
Callback invoked by the framework when channel data arrives from the client. Register this to intercept raw channel traffic.
psPeerVirtualChannelOpen
Opens a dynamic virtual channel by name. flags is WTS_CHANNEL_OPTION_DYNAMIC or similar.

Sending Graphics Updates

After Activate returns, push screen updates through peer->context->update:
For RFX / RemoteFX encoded updates, use update->SurfaceCommand and compose the RFX payload with rfx_compose_message() (see Codecs).

Minimal Peer Setup Example

The peer CheckFileDescriptor callback returns FALSE when the client disconnects or a protocol error occurs. Always check the return value and exit the event loop accordingly.
Do not call freerdp_peer_free() from the same thread context that the peer listener accepted the connection on — spin up a dedicated worker thread per peer.