Manual Técnico Oficial de Arquitectura — Connecting

Documentación técnica exhaustiva del funcionamiento interno de Connecting Remote Desktop: flujo de captura gráfica GDI, compresión JPEG adaptativa, inyección de eventos Win32, protocolo binario sobre sockets TCP y estructura modular C#.

Diseño Open Source & Aislamiento de Privacidad: El código alojado en el repositorio público build/windows/ está estructurado de forma genérica para permitir la compilación limpia y el despliegue privado en cualquier servidor o red corporativa sin dependencia de infraestructura de terceros.

1. Estructura Modular del Código Fuente C#

La aplicación está estructurada en módulos desacoplados dentro del directorio src/ para facilitar el mantenimiento y la compilación nativa en cualquier entorno Windows sin requerir dependencias pesadas ni instaladores externos:

Archivo Fuente Namespace / Clase Responsabilidad Principal
src/Common/PeerResolver.cs Conecting.Common.PeerResolver Generación de ID permanente de 9 dígitos, gestión de clave PSK, persistencia de idioma, registro HKLM del Servicio de Windows y configuración del dominio/IP del Servidor Relay.
src/Common/PacketProtocol.cs Conecting.Common.PacketProtocol Protocolo binario de enmarcado TCP: serialización y deserialización de payloads con cabecera de 1 byte de comando y 4 bytes de longitud.
src/Common/AppI18n.cs Conecting.Common.AppI18n Motor de internacionalización dinámico bidireccional (Español / Inglés).
src/Core/DesktopCapturer.cs Conecting.Core.DesktopCapturer Captura de pantalla de alta velocidad mediante Win32 GDI, conmutación dinámica de escritorio de entrada (Desktop switch) y compresión JPEG adaptativa en memoria.
src/Core/NativeInputInjector.cs Conecting.Core.NativeInputInjector Inyección directa de eventos de ratón y teclado en el sistema operativo remoto utilizando la API nativa `SendInput` de Win32.
src/Core/ConnectionHistory.cs Conecting.Core.ConnectionHistory Persistencia del historial de conexiones recientes, nombres de equipos y alias de usuario en formato JSON/DAT.
src/UI/MainForm.cs Conecting.UI.MainForm Ventana principal de la aplicación, panel de control, configuración global, gestión del servidor Relay y bucle de registro de host.
src/UI/RemoteSessionView.cs Conecting.UI.RemoteSessionView Visor de la sesión remota en vivo: renderizado de vídeo a 60 FPS, escalado gráfico, captura de eventos de entrada y control de calidad adaptativa (90L, 75L, 60L).
src/UI/SessionTabControl.cs Conecting.UI.SessionTabControl Sistema de navegación multi-sesión por pestañas dinámicas estilo AnyDesk.
Interfaz Principal de Connecting
Figura 1: Interfaz gráfica principal de Connecting renderizando el ID de acceso de 9 dígitos y la clave PSK.

2. Procesamiento de Imagen GDI & Compresión JPEG Adaptativa

El motor de transmisión de vídeo en tiempo real se implementa en src/Core/DesktopCapturer.cs mediante la captura directa de la memoria de pantalla (Device Context) de Windows:

Algoritmo de Captura & Encodificación:

  1. Obtención del Contexto de Pantalla (GDI DC): Mediante Graphics.FromHdc o CopyFromScreen, se extrae el marco actual del monitor primario utilizando las dimensiones del área de trabajo.
  2. Recreación de Bitmaps en Memoria: Para minimizar el uso de Garbage Collection (GC) de .NET, el objeto Bitmap en memoria se reutiliza de forma continua. Si las dimensiones de la pantalla cambian, el contexto gráfico se libera y se vuelve a instanciar automáticamente.
  3. Compresión JPEG con Calidad Adaptativa: La imagen capturada se comprime en memoria usando el códec nativo de Windows (System.Drawing.Imaging.Encoder.Quality) y se convierte en un arreglo de bytes JPEG.
// Fragmento de configuración de calidad JPEG en DesktopCapturer.cs EncoderParameters encoderParams = new EncoderParameters(1); encoderParams.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qualityLevel); // 90L, 75L, o 60L ImageCodecInfo jpegCodec = GetEncoder(ImageFormat.Jpeg); MemoryStream ms = new MemoryStream(); _captureBitmap.Save(ms, jpegCodec, encoderParams); return ms.ToArray();

Niveles de Calidad de Transmisión:

Transmisión HD a Pantalla Completa
Figura 2: Sesión remota activa a pantalla completa con ajuste adaptativo de resolución y 60 FPS.

3. Inyección Nativa de Entrada Win32 (`SendInput`)

La inyección de eventos de ratón y teclado se realiza en src/Core/NativeInputInjector.cs interactuando directamente con el subsistema user32.dll del sistema operativo remoto:

Mapeo y Normalización de Coordenadas:

Los clics y movimientos de ratón recibidos en el cliente se transmiten como valores flotantes normalizados entre 0.0 y 1.0. En el host, NativeInputInjector convierte estas coordenadas al espacio absoluto de Win32 (de 0 a 65535):

// Conversión de coordenadas de ratón normalizadas a absolutas Win32 int absoluteX = (int)(normalizedX * 65535.0f); int absoluteY = (int)(normalizedY * 65535.0f); INPUT input = new INPUT(); input.type = INPUT_MOUSE; input.union.mi.dx = absoluteX; input.union.mi.dy = absoluteY; input.union.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_VIRTUALDESK | MOUSEEVENTF_MOVE; SendInput(1, ref input, Marshal.SizeOf(typeof(INPUT)));

4. Protocolo Binario de Enmarcado TCP (Framing)

La comunicación entre cliente, host y servidor de relevo se gestiona en src/Common/PacketProtocol.cs a través de un protocolo binario ligero estructurado de la siguiente forma:

+--------------------+--------------------------------+--------------------------------+ | Tipo (1 Byte) | Longitud Payload (4 Bytes) | Payload de Datos (N Bytes) | +--------------------+--------------------------------+--------------------------------+

Catálogo de Paquetes de Control:

Código Hex Nombre del Paquete Descripción del Payload
0x00 FRAME_JPEG Arreglo de bytes conteniendo la imagen comprimida en JPEG de la pantalla actual.
0x01 MOUSE_EVENT Coordenadas flotantes normalizadas (X, Y) y código de acción (Move, Down, Up, RightClick).
0x02 KEYBOARD_EVENT Código de tecla virtual Win32 (Virtual Key code) y estado de pulsación (KeyDown / KeyUp).
0x03 CHAT_MESSAGE Cadena de texto en formato UTF-8 conteniendo mensajes del chat de soporte técnico.
0x04 CLIPBOARD_SYNC Contenido de texto del portapapeles para sincronización bidireccional en tiempo real.
0x05 QUALITY_CHANGE Instrucción de cambio de calidad JPEG (envía 90, 75 o 60 para actualizar el encoder del host).

5. Configuración del Servidor Relay & Seguridad TLS/SSL

El servidor Relay (build/server/server.js) soporta cifrado TLS/SSL nativo usando certificados Let's Encrypt o cualquier certificado X.509 válido. Toda la comunicación entre clientes, hosts y el servidor viaja cifrada de extremo a extremo mediante TLS 1.2+.

Arquitectura de Seguridad TLS:
El servidor opera en modo dual: si detecta certificados SSL válidos en el sistema, inicia como servidor tls.createServer() con cifrado nativo. Si no encuentra certificados, inicia en modo TCP plano como fallback de desarrollo. Los clientes negocian SslStream con SslProtocols.Tls12 para máxima compatibilidad y seguridad.

Configuración del Dominio y Certificados SSL:

El servidor soporta configuración mediante variables de entorno para máxima flexibilidad de despliegue:

# Variables de entorno soportadas por server.js: RELAY_DOMAIN="your-relay-server.com" # Dominio del certificado SSL CERT_PATH="/etc/letsencrypt/live/your-domain/fullchain.pem" # Ruta al certificado KEY_PATH="/etc/letsencrypt/live/your-domain/privkey.pem" # Ruta a la clave privada PORT=8443 # Puerto de escucha (default: 8443)

Flujo de Conexión TLS:

┌─────────────────┐ TLS 1.2 ┌─────────────────┐ TLS 1.2 ┌─────────────────┐ │ Host (C#) │ ◄──────────────── │ Relay Server │ ──────────────── │ Client (C#) │ │ SslStream │ Puerto 8443 │ tls.createServer│ Puerto 8443 │ SslStream │ │ TLS 1.2 │ │ Node.js │ │ TLS 1.2 │ └─────────────────┘ └─────────────────┘ └─────────────────┘

A) Modificación Directa en el Código Fuente C#:

Abre el archivo src/Common/PeerResolver.cs y modifica las siguientes variables estáticas:

// src/Common/PeerResolver.cs (Líneas 23 - 24) public static string RelayServerDomain = "tu-servidor-relay.com"; // Modifica por la IP o dominio de tu servidor Relay public static int RelayServerPort = 8443;

B) Configuración Dinámica desde la Interfaz Visual (GUI):

Dentro de la aplicación, navega a la pestaña de Configuración & Seguridad en la parte inferior. En la sección Servidor Relay Personalizado (Dominio o IP), ingresa la dirección de tu servidor y presiona el botón Guardar Servidor. La aplicación persistirá este cambio en %APPDATA%\ConnectingNodes\relayhost.dat y reiniciará el registro de puesto automáticamente.

Nota sobre la Especificación del Puerto del Servidor Relay:
El campo Servidor Relay Personalizado (Dominio o IP) soporta tanto el nombre de dominio/IP sin puerto (ejemplo: midominio.com o 192.168.1.50, el cual utilizará el puerto TCP 8443 por defecto), como también el formato con puerto explícito (ejemplo: midominio.com:8443 o 192.168.1.50:8443). El motor de resolución (PeerResolver.cs) analiza y extrae automáticamente el host y el puerto ingresado.

¿Por qué la conexión remota funciona aunque no se configure una clave personalizada?

Connecting genera automáticamente una clave PSK de 6 dígitos aleatorios almacenada en node_psk.dat (mostrada en pantalla como Clave PSK Segura). Si el campo de contraseña personalizada (txtCustomPsk / unattended_psk.dat) se deja vacío, la aplicación utiliza la clave PSK dinámica generada, garantizando acceso desatendido seguro de inmediato.

6. Elevación UAC & Servicio de Windows (`ConnectingService`)

Modo Portátil e Inicios sin Elevación (`asInvoker`):

Al ejecutarse de forma portátil, Connecting inicia en 1 segundo con privilegios normales de usuario (asInvoker), evitando la necesidad de contraseñas de administrador o confirmaciones UAC al abrir la aplicación.

Reinicio con Elevación UAC Voluntaria:

Si el técnico necesita interactuar con ventanas administrativas (tales como el Administrador de Tareas, consolas de comandos o ejecutables de instalación), se utiliza el botón Reiniciar como Admin ubicado en la interfaz. Este botón reinicia la aplicación invocando la API de Windows con el verbo de elevación:

ProcessStartInfo psi = new ProcessStartInfo { FileName = Application.ExecutablePath, Verb = "runas", // Solicita elevación UAC a Windows UseShellExecute = true }; Process.Start(psi); Application.Exit();
Botón Reiniciar como Admin
Figura 3: Ubicación del botón "Reiniciar como Admin" para elevación UAC en tiempo de ejecución.

Instalación del Servicio de Asistencia de Windows (`ConnectingService`):

Para soporte desatendido continuo en equipos corporativos, la aplicación permite la instalación como Servicio de Windows (ejecutado bajo la cuenta NT AUTHORITY\SYSTEM en Sesión 0). La gestión se realiza directamente desde el panel de Configuración de la app o mediante la consola de comandos:

# Instalación manual del Servicio de Windows mediante consola de comandos (cmd as admin) sc stop "ConnectingService" 2>nul sc delete "ConnectingService" 2>nul sc create "ConnectingService" binPath= "C:\Ruta\Connecting.exe --service" start= auto sc start "ConnectingService"
Instalación del Servicio de Windows
Figura 4: Panel de Configuración mostrando la opción de instalación/desinstalación del Servicio de Windows.

7. Solicitud de Certificación SignPath Foundation (En Trámite)

Para cumplir con los estándares de la Free Software Foundation (FSF) y garantizar la distribución de ejecutables confiables sin alertas de Windows SmartScreen, el proyecto se encuentra en proceso de solicitud de patrocinio con SignPath Foundation (actualmente en trámite y pendiente de aprobación final) para obtener firma digital EV Authenticode de código abierto.

La firma Authenticode pública permitirá declarar la bandera uiAccess="true" en el manifiesto de la aplicación, habilitando la captura nativa de la pantalla de seguridad de UAC (Winlogon / SecureDesktop) sin requerir que la aplicación sea instalada previamente en Program Files.

8. Instrucciones de Compilación y Funcionamiento de los Scripts de Build

El proyecto includes scripts automatizados en PowerShell para compilar el código fuente sin necesidad de instalar Visual Studio completo. A continuación se detalla exactamente qué realiza cada script dentro del flujo de compilación:

A) Script de Combinación de Código Fuente (combine.ps1):

Este script se encarga de transformar la arquitectura modular de desarrollo (ubicada en src/) en un único archivo C# monolítico listo para compilación limpia (ConnectingApp.cs):

B) Script de Compilación y Firma Digital (build.ps1):

Este script ejecuta el proceso de compilación nativa del sistema, empaquetado de recursos y firma de seguridad Authenticode:

Comandos para Ejecutar la Compilación:

# 1. Navega al directorio del proyecto (build/windows o local-nogit/windows) cd build/windows # 2. Genera el archivo monolítico ConnectingApp.cs a partir de src/*.cs powershell -ExecutionPolicy Bypass -File .\combine.ps1 # 3. Compila Connecting.exe, incrusta el manifiesto/icono y firma el binario powershell -ExecutionPolicy Bypass -File .\build.ps1