Skip to main content
The listener API provides a lightweight TCP server that binds to a port, accepts incoming RDP connections, and vends freerdp_peer objects via the PeerAccepted callback. Header: <freerdp/listener.h>

Lifecycle

freerdp_listener_new

Allocates a new listener instance. Returns NULL on failure. Pair with freerdp_listener_free() when done.

freerdp_listener_free

Closes any open sockets and releases all resources.

Struct: rdp_freerdp_listener

typedefd as freerdp_listener. All functional members are function pointers set by the implementation.
psPeerAccepted
Callback invoked for each newly accepted connection. The implementation receives a ready-to-use freerdp_peer*. Typically used to spawn a worker thread for the peer. Return FALSE to immediately reject and free the peer.
psListenerOpen
Binds and listens on a TCP address/port. bind_address may be NULL to listen on all interfaces. Returns FALSE on error.
psListenerOpenLocal
Binds and listens on a Unix-domain socket at path. Useful for local IPC connections.
psListenerOpenFromSocket
Takes ownership of an already-bound, already-listening socket file descriptor. Useful for socket-activation (e.g. systemd).
psListenerGetEventHandles
Fills events[] with all waitable handles the listener uses (one per open socket). Returns the number of handles written. Use these with WaitForMultipleObjects in the accept loop.
psListenerCheckFileDescriptor
Processes any pending accepts. For each ready connection a freerdp_peer is created and PeerAccepted is called. Returns FALSE on a fatal listener error.
psListenerCheckFileDescriptor
Optional hook. When set, called before PeerAccepted to allow early connection filtering (e.g. rate limiting, IP allow-lists).
psListenerClose
Closes all listening sockets. New connections will no longer be accepted. In-flight peers are unaffected.

Accept Loop Example

PeerAccepted is called on the listener thread. Offload long-running work (the entire peer RDP handshake) to a dedicated thread to avoid blocking incoming accepts.
For Unix socket support (e.g. xrdp integration), use listener->OpenLocal(listener, "/tmp/my_rdp.sock") instead of Open.