Status: ✅ Approved & Implemented
Owner: Cesar Romero & Engineering Team
Created: 2026-06-28
Dependencies: S39 (Native Server Engine)
Enables: High-performance IoT gateways, raw TCP/UDP messaging, native MQTT client/server without third-party dependencies (CrossSocket, Indy, etc.).
Currently, the Dext Framework implements native, high-performance, kernel-level I/O engines (IOCP on Windows and epoll on Linux) inside the Dext.Server layer. However, this infrastructure is tightly coupled to standard HTTP/1.1 parsing and WebSocket handshakes. All socket descriptors, connection loops, and raw buffers are processed internally and cannot be used for generic TCP/UDP workloads or IoT protocols.
In industrial automation, telematics, and Internet of Things (IoT) systems, developers must support raw socket streams (TCP/UDP) and lightweight broker-based protocols like MQTT (Message Queuing Telemetry Transport).
This specification defines how Dext will:
- Refactor and Decouple the core IOCP/Epoll engines to support arbitrary protocol handlers.
- Expose generic TCP servers and clients.
- Expose generic UDP servers and clients.
- Implement a native MQTT client and server (broker) directly on top of the newly decoupled high-performance TCP engine.
In modern .NET, Kestrel (the web server) is built on top of Microsoft.AspNetCore.Connections.Abstractions.
- A connection is represented by a
ConnectionContext. - It exposes a
PipeReaderandPipeWriterfor asynchronous stream processing. - This allows developers to build custom TCP/UDP servers (such as Bedrock.Framework or custom MQTT brokers) directly on Kestrel's I/O transport layer without writing low-level Socket select loops.
Netty separates transport (IOCP, epoll, kqueue) from logic using a ChannelPipeline and ChannelHandler.
- Data flows through a series of handlers (e.g.,
ByteToMessageDecoder,MessageToByteEncoder). - For MQTT, Netty provides
MqttDecoderandMqttEncoder, which convert raw byte buffers into typed MQTT packet objects.
Currently, TDextIocpWorker.Execute and TDextEpollEngine read from the socket and immediately call TDextIocpHttpParser.TryParseRequest.
We will refactor this structure into a decoupled pipeline:
┌────────────────────────────────────────────────────────┐
│ Dext.Server.Engine (IOCP/Epoll) │
└──────────────────────────┬─────────────────────────────┘
│ (Connection & Buffer Events)
▼
[IDextTransportConnection]
- Send(const ABuffer: TBytes)
- Close()
│
┌─────────────────┼──────────────────┐
▼ ▼ ▼
┌─────────────────┐ ┌───────────────┐ ┌───────────────┐
│ HTTP/WebSocket │ │ Raw TCP │ │ MQTT Broker/ │
│ ProtocolHandler │ │ Server/Client│ │ Client │
└─────────────────┘ └───────────────┘ └───────────────┘
- Introduce
IDextTransportConnectionto represent a generic, thread-safe network channel. - Expose a generic
IConnectionHandlerinterface:type IConnectionHandler = interface ['{A672F8B0-4A0B-4712-A3DF-8BFCE48FA472}'] procedure OnConnect(const AConnection: IDextTransportConnection); procedure OnDisconnect(const AConnection: IDextTransportConnection); procedure OnData(const AConnection: IDextTransportConnection; const ABuffer: TBytes; ALength: Integer); procedure OnError(const AConnection: IDextTransportConnection; AException: Exception); end;
- Update
TDextIocpEngineandTDextEpollEngineto accept anIConnectionHandlerrather than internally tying the socket read loops to HTTP parsers. The HTTP stack will become an implementation ofIConnectionHandler.
We will introduce Dext.Net.Tcp containing the high-performance wrappers:
type
ITcpConnection = interface(IDextTransportConnection)
['{E3C2B6A1-9F0D-47C1-B6C2-EA15C3847BE2}']
function GetConnectionId: UInt64;
function GetRemoteAddress: string;
function GetRemotePort: Word;
procedure Send(const ABuffer: TBytes); overload;
procedure Send(const AStream: TStream); overload;
procedure Close;
property ConnectionId: UInt64 read GetConnectionId;
property RemoteAddress: string read GetRemoteAddress;
property RemotePort: Word read GetRemotePort;
end;
TTcpConnectionEvent = reference to procedure(const AConnection: ITcpConnection);
TTcpDataEvent = reference to procedure(const AConnection: ITcpConnection; const AData: TBytes);
TDextTcpServer = class
private
FEngine: IDextServerEngine;
FOnConnect: TTcpConnectionEvent;
FOnDisconnect: TTcpConnectionEvent;
FOnData: TTcpDataEvent;
public
constructor Create(const AOptions: TServerEngineOptions);
destructor Destroy; override;
procedure Bind(const AAddress: string; APort: Word);
procedure Start;
procedure Stop;
property OnConnect: TTcpConnectionEvent read FOnConnect write FOnConnect;
property OnDisconnect: TTcpConnectionEvent read FOnDisconnect write FOnDisconnect;
property OnData: TTcpDataEvent read FOnData write FOnData;
end;
TDextTcpClient = class
private
FSocket: TSocket;
// Client-side IOCP/Epoll handler integration for non-blocking read
public
constructor Create;
destructor Destroy; override;
procedure Connect(const AAddress: string; APort: Word);
procedure Disconnect;
procedure Send(const ABuffer: TBytes);
function Receive(var ABuffer: TBytes; ATimeoutMs: Integer = 5000): Integer;
end;UDP runs without connection states. The I/O engine must bind to SOCK_DGRAM and handle packet dispatching:
type
TUdpPacket = record
RemoteAddress: string;
RemotePort: Word;
Data: TBytes;
end;
TUdpPacketEvent = reference to procedure(const APacket: TUdpPacket);
TDextUdpServer = class
public
constructor Create(const AOptions: TServerEngineOptions);
procedure Bind(const AAddress: string; APort: Word);
procedure Start;
procedure Stop;
procedure SendTo(const AAddress: string; APort: Word; const AData: TBytes);
property OnPacketReceived: TUdpPacketEvent read FOnPacketReceived write FOnPacketReceived;
end;
TDextUdpClient = class
public
procedure Send(const AAddress: string; APort: Word; const AData: TBytes);
function Receive(out APacket: TUdpPacket; ATimeoutMs: Integer = 5000): Boolean;
end;MQTT v3.1.1 and v5.0 are binary-framed packet protocols. Dext will provide a native parser inside Dext.Net.Mqtt.Parser.pas that encodes and decodes packets without heap allocations where possible.
- CONNECT / CONNACK: Handshake and session initiation.
- PUBLISH / PUBACK / PUBREC / PUBREL / PUBCOMP: Message publishing with QoS 0 (At most once), QoS 1 (At least once), and QoS 2 (Exactly once).
- SUBSCRIBE / SUBACK: Subscription to topic filters.
- UNSUBSCRIBE / UNSUBACK: Removal of subscriptions.
- PINGREQ / PINGRESP: Keep-alive ping mechanism.
- DISCONNECT: Clean disconnection.
The Broker (TDextMqttServer) must support:
- Single-level wildcard
+(e.g.sensors/+/temperaturematchessensors/kitchen/temperature). - Multi-level wildcard
#(e.g.sensors/#matchessensors/kitchen/temperatureandsensors/garden/humidity). - These filters will be resolved using an optimized trie-based prefix tree structure (
TDextMqttTopicTrie).
type
TMqttMessage = record
Topic: string;
Payload: TBytes;
QoS: Byte;
Retain: Boolean;
end;
TMqttMessageEvent = reference to procedure(const AMessage: TMqttMessage);
TDextMqttClient = class
public
constructor Create;
destructor Destroy; override;
procedure Connect(const AHost: string; APort: Word; const AClientId: string = '');
procedure Disconnect;
procedure Publish(const ATopic: string; const APayload: TBytes; AQoS: Byte = 0; ARetain: Boolean = False);
procedure Subscribe(const ATopicFilter: string; AQoS: Byte = 0);
procedure Unsubscribe(const ATopicFilter: string);
property OnMessageReceived: TMqttMessageEvent read FOnMessageReceived write FOnMessageReceived;
end;
TDextMqttServer = class
private
FTcpServer: TDextTcpServer;
// Session state dictionary and topic trie tree
public
constructor Create(const AOptions: TServerEngineOptions);
destructor Destroy; override;
procedure Start;
procedure Stop;
// Broker event hooks (auth callbacks, client connected, etc.)
end;- Refactoring I/O Engine: Medium-High. The risk of regression in the existing HTTP/1.1 and WebSocket engines is present. Complete code separation with abstract handlers is required.
- TCP/UDP Wrappers: Medium. Simple binding of system sockets to the IOCP/epoll selectors.
- MQTT Parser: Medium. Binary parsing of the MQTT protocol is straightforward but requires meticulous unit tests.
- MQTT Broker: High. Managing concurrent sessions, connection timeouts (keep-alive), client message queues, and QoS 1/2 state validation requires significant threading stability and validation.
- Opens up Dext for IoT gateways, edge routers, SCADA systems, and embedded long-lived TCP connection services.
- Replaces complex third-party stacks, allowing 100% native Pascal compile-once deploy-anywhere setups on Linux/Windows.
The implementation of S47 will affect the following existing files and introduce new components:
- Dext.Server.Engine.Interfaces.pas - Modify to introduce generic
IDextTransportConnectionandIConnectionHandlerinterfaces, separating them from the HTTP-specific request handlers. - Dext.Server.Iocp.pas - Decouple the Windows IOCP worker loops from HTTP parsing, forwarding events to the configured
IConnectionHandler. - Dext.Server.Epoll.pas - Decouple the Linux Epoll worker loops from HTTP parsing, forwarding events to the configured
IConnectionHandler.
[NEW]Dext.Net.Tcp.pas - Implementation of raw TCP server (TDextTcpServer), client (TDextTcpClient), and connection wraps.[NEW]Dext.Net.Udp.pas - Implementation of raw UDP server (TDextUdpServer) and client (TDextUdpClient).[NEW]Dext.Net.Mqtt.Parser.pas - High-performance MQTT control packet binary encoder/decoder.[NEW]Dext.Net.Mqtt.pas - Implementation ofTDextMqttClient,TDextMqttServer(Broker), and subscription trie pattern.
[NEW]Dext.Net.TcpTests.pas - Unit and integration tests for the new TCP/UDP and MQTT layers.
- TCP Roundtrip Loop: Spin up
TDextTcpServeron dynamic port (Port 0), connect withTDextTcpClient, exchange 100MB of random payloads, verify integrity, and check for memory leaks. - UDP Echo: Test packet sending and receiving using
TDextUdpServerandTDextUdpClient. - MQTT Parser Suite: Validate parser against standard MQTT binary payloads (handshake packets, QoS-framed publishes) to verify correct field extraction.
- Trie Pattern Matcher: Unit tests validating wildcard topic match results (
+,#, system topics).
- Connect
TDextMqttClientto a local Mosquitto Broker. Publish and subscribe to topics. - Connect a Python/JS MQTT client (e.g.
paho-mqtt) toTDextMqttServer(Broker), run stress testing tool (mqtt-benchmark) to measure throughput and memory overhead on Windows and Linux under 10k connections.
Created by Cesar Romero & Antigravity AI — June 2026