Skip to content

feat: RdpBridge – standalone FreeRDP SDK with C ABI, CMake build, and CI/CD - #1

Merged
Soar360 merged 7 commits into
mainfrom
copilot/refactor-rdpsdk-from-cxrdpbridge
Jun 29, 2026
Merged

feat: RdpBridge – standalone FreeRDP SDK with C ABI, CMake build, and CI/CD#1
Soar360 merged 7 commits into
mainfrom
copilot/refactor-rdpsdk-from-cxrdpbridge

Conversation

Copilot AI commented Jun 29, 2026

Copy link
Copy Markdown

Extracts and refactors the FreeRDP-based RDP bridge from CxShell/CxRdpBridge into a standalone, production-grade SDK with a stable C ABI suitable for P/Invoke from C#/Avalonia and other languages.

Public API (include/rdp_bridge.h)

  • Renamed from cxrdp_*RdpBridge_* prefix for clean namespace
  • Typed callbacks: RdpBridge_FrameCallback (BGRA32), RdpBridge_StatusCallback, RdpBridge_DisconnectCallback
  • Full Doxygen documentation on every exported symbol
void* session = RdpBridge_create();
RdpBridge_set_callbacks(session, on_frame, on_status, on_disconnect, ctx);
RdpBridge_connect(session, "192.168.1.1", 3389, "Administrator", "pass", 1920, 1080);
// ... event loop ...
RdpBridge_disconnect(session);
RdpBridge_destroy(session);

Core implementation (src/RdpBridge/rdp_bridge.cpp)

  • All CxShell / UI / application-layer dependencies removed
  • Worker thread model: connection runs on a dedicated thread; atomic_bool session state; mutex-protected callbacks
  • Security profile fallback chain: NLA → TLS → RDP-legacy → negotiate (auto-retry on failure)
  • BGRA32 framebuffer via BeginPaint/EndPaint — zero-copy pointer delivery to caller
  • OpenSSL provider init (default + legacy) with Windows ossl-modules path discovery
  • Named constant BGRA32_BYTES_PER_PIXEL instead of magic 4

Build (CMakeLists.txt)

  • find_package for FreeRDP 3, WinPR, OpenSSL; no vendored deps
  • Output: RdpBridge.dll (Windows, no lib prefix) / libRdpBridge.so (Linux)
  • $ORIGIN / @loader_path RPATH for portable deployment
  • Full install + exported CMake targets for downstream consumption

CI/CD (.github/workflows/build.yml)

Trigger Action
Push / PR → main Build Linux SO (ubuntu-24.04 / GCC / Ninja) + Windows DLL (windows-2022 / MSVC / vcpkg)
Tag v* Package include/ + binaries → tar.gz / .zip → GitHub Release via softprops/action-gh-release

All build jobs carry explicit permissions: contents: read; the release job additionally has contents: write. Ubuntu 24.04 is required — libfreerdp3-dev is not packaged for 22.04.

Example (examples/minimal/main.c)

Minimal C program exercising the full session lifecycle, with correct platform includes (<windows.h> / <time.h>).

Original prompt

You are a senior C++/CMake and DevOps engineer.

I want you to extract and refactor an existing FreeRDP-based native RDP bridge from this repository:

https://github.com/xiaochengzjc/CxShell/tree/master/native/CxRdpBridge


🎯 Goal

Create a new standalone GitHub repository named:

RdpBridge

This repository will become a production-grade native RDP SDK built on FreeRDP.

It must expose a clean C ABI for use in:

  • C#
  • P/Invoke
  • other languages

🧠 Core Objective

Refactor the existing CxRdpBridge implementation into a clean, reusable SDK:

✔ remove all dependencies on CxShell
✔ remove UI / shell / application logic
✔ keep only RDP runtime core
✔ ensure stable ABI suitable for long-term SDK usage


📦 Functional Requirements

The SDK must support:

1. Session lifecycle

  • create session
  • destroy session
  • connect
  • disconnect

2. RDP rendering

  • framebuffer output via callback
  • BGRA raw pixel buffer
  • width / height / stride provided

3. Input handling

  • mouse input (move / click / wheel)
  • keyboard input (scancode)
  • unicode keyboard input

4. Status & events

  • status callback (log / state updates)
  • disconnect callback
  • error reporting

🔌 Required C ABI (IMPORTANT)

Expose a stable API:

RdpBridge_create()
RdpBridge_destroy()

RdpBridge_connect(host, port, username, password, width, height)
RdpBridge_disconnect()

RdpBridge_set_callbacks(frame, status, disconnect, user_data)

RdpBridge_send_pointer(flags, x, y)
RdpBridge_send_key(key, down)
RdpBridge_send_unicode_key(code, down)


🧱 Internal Implementation Requirements

Reuse and refactor logic from original CxRdpBridge:

MUST KEEP:

  • FreeRDP initialization logic
  • connection thread model
  • security fallback profiles:
    • NLA
    • TLS
    • RDP
    • negotiate mode
  • framebuffer callback logic (BeginPaint / EndPaint)
  • authentication callback handling
  • OpenSSL provider initialization logic

🧵 Threading Model

  • connection must run in a dedicated worker thread
  • framebuffer callback must be thread-safe
  • input APIs must be safe while connected
  • session state must be atomic-safe

🧪 Rendering Model

Framebuffer output rules:

  • format: BGRA32
  • zero-copy preferred (avoid unnecessary allocations)
  • provide raw pointer to pixel buffer
  • include width, height, stride

🏗 Repository Structure

Create a clean SDK layout:

/src
/RdpBridge (core implementation)
/include (public headers)
/cmake
/examples (minimal usage example)
/.github/workflows


⚙ Build System

Use CMake.

Support:

  • Windows (MSVC)
  • Linux (GCC/Clang)

Output:

  • Windows: RdpBridge.dll
  • Linux: libRdpBridge.so

🚀 GitHub Actions CI/CD (CRITICAL)

Create workflow:

.github/workflows/build.yml

Requirements:

On push to main:

  • build Windows Release DLL
  • build Linux Release SO

On tag release (v*):

  • build artifacts
  • package SDK:
    • include headers
    • include binaries

Upload to GitHub Release:

  • Windows zip package
  • Linux tar.gz package

Use:

  • actions/checkout
  • cmake configure + build
  • upload-artifact
  • softprops/action-gh-release

🧹 Cleanup Requirements

Remove completely:

  • CxShell dependencies
  • UI code
  • application shell logic
  • any business-specific logic

Keep only:
✔ RDP engine
✔ transport layer
✔ framebuffer + input bridge


🎯 Final Goal

The final repository must behave like a production-grade SDK:

  • stable ABI
  • predictable callbacks
  • cross-language usable
  • buildable via CI
  • ready for C# Avalonia integration via P/Invoke

🧠 Important Quality Requirements

  • No memory leaks in callback usage
  • Proper thread cleanup on disconnect
  • Safe session lifecycle handling
  • Clean separation between FreeRDP internals and public API

Copilot AI changed the title [WIP] Refactor existing CxRdpBridge into standalone RDP SDK feat: RdpBridge – standalone FreeRDP SDK with C ABI, CMake build, and CI/CD Jun 29, 2026
Copilot AI requested a review from Soar360 June 29, 2026 15:17
@Soar360
Soar360 marked this pull request as ready for review June 29, 2026 16:23
Copilot AI review requested due to automatic review settings June 29, 2026 16:23
@Soar360
Soar360 merged commit 38780f3 into main Jun 29, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR turns the project into a standalone FreeRDP-based native SDK (“RdpBridge”) with a stable C ABI, a CMake build suitable for downstream consumption, and CI workflows to build/package binaries on Linux and Windows.

Changes:

  • Adds the core SDK implementation (RdpBridge_* C ABI) with a worker-thread connection model, callbacks, input injection, and OpenSSL provider setup.
  • Introduces a public header (include/rdp_bridge.h) plus a minimal C example.
  • Adds a top-level CMake build and a GitHub Actions workflow to build/package artifacts and publish releases on tags.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
src/RdpBridge/rdp_bridge.cpp Implements the FreeRDP-backed session object, worker thread, callbacks, and C ABI entrypoints.
include/rdp_bridge.h Defines the public C ABI types and functions with Doxygen comments.
CMakeLists.txt Adds the shared library target, dependency discovery, install rules, and example option.
examples/minimal/main.c Minimal lifecycle example program using the C ABI.
examples/minimal/CMakeLists.txt Builds the minimal example, including a standalone find_package(RdpBridge CONFIG) path.
README.md Documents features, build instructions, API usage, and layout.
.github/workflows/build.yml CI builds Linux/Windows artifacts and publishes GitHub Releases on tags.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +184 to +192
void notify_status(RdpSession* session, const char* message)
{
if (!session)
return;

std::lock_guard<std::mutex> lock(session->callback_mutex);
if (session->status_callback)
session->status_callback(session->user_data, message);
}
Comment on lines +500 to +502
std::lock_guard<std::mutex> lock(session->callback_mutex);
if (session->frame_callback)
session->frame_callback(session->user_data, width, height, stride, pixels);
Comment on lines +550 to +554
const bool wasConnected = session->connected.exchange(false);
notify_status(session, "RDP disconnected.");
std::lock_guard<std::mutex> lock(session->callback_mutex);
if (wasConnected && session->disconnect_callback)
session->disconnect_callback(session->user_data);
Comment on lines +178 to +182
void set_error(RdpSession* session, const std::string& message)
{
if (session)
session->last_error = message;
}
Comment on lines +863 to +869
RDP_BRIDGE_API const char* RdpBridge_get_last_error(void* handle)
{
auto* session = static_cast<RdpSession*>(handle);
if (!session)
return "";
return session->last_error.c_str();
}
Comment thread CMakeLists.txt
Comment on lines +81 to +85
install(EXPORT RdpBridgeTargets
FILE RdpBridgeTargets.cmake
NAMESPACE RdpBridge::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/RdpBridge
)
Comment thread include/rdp_bridge.h
Comment on lines +88 to +93
* @param handle Session handle.
* @param host Server hostname or IP address (UTF-8, must not be NULL).
* @param port TCP port (use 3389 for the default).
* @param username Login username (UTF-8, must not be NULL).
* @param password Login password (UTF-8, must not be NULL).
* @param width Initial desktop width in pixels.
Comment thread include/rdp_bridge.h
Comment on lines +95 to +97
* @return 0 – connection thread started successfully.
* -1 – invalid handle.
* -2 – Winsock initialisation failed (Windows only).
Comment on lines +618 to +619
freerdp_settings_set_bool(settings, FreeRDP_IgnoreCertificate, TRUE);
freerdp_settings_set_bool(settings, FreeRDP_AutoAcceptCertificate, TRUE);
<< " flags=0x" << std::hex << flags;
notify_status(session, message.str().c_str());
}
return 2;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants