feat(mqtt): add MQTT packet parser, dispatch, and ReadLoop integration
Implement Task 2 of MQTT orchestration: - Create MqttParser.cs with loop-based packet parser and dispatch switch - Add MqttReader field to MqttHandler for per-connection parsing state - Wire ReadLoop to call MqttParser for MQTT connections - Implement PINGREQ handler (enqueues PINGRESP) - CONNECT-first enforcement (rejects non-CONNECT as first packet) - Partial packet handling via MqttReader pending buffer - 13 unit tests covering parser, dispatch, partial packets, and edge cases - Stub dispatch entries for CONNECT, PUBLISH, SUB, UNSUB, DISCONNECT (NotImplementedException)
This commit is contained in:
@@ -25,6 +25,7 @@ using Microsoft.Extensions.Logging;
|
||||
using ZB.MOM.NatsNet.Server.Auth;
|
||||
using ZB.MOM.NatsNet.Server.Internal;
|
||||
using ZB.MOM.NatsNet.Server.Internal.DataStructures;
|
||||
using ZB.MOM.NatsNet.Server.Mqtt;
|
||||
using ZB.MOM.NatsNet.Server.Protocol;
|
||||
using ZB.MOM.NatsNet.Server.WebSocket;
|
||||
|
||||
@@ -1405,8 +1406,59 @@ public sealed partial class ClientConnection
|
||||
internal void ReadLoop(byte[]? pre)
|
||||
{
|
||||
LastIn = DateTime.UtcNow;
|
||||
|
||||
// Process any pre-read bytes first.
|
||||
if (pre is { Length: > 0 })
|
||||
{
|
||||
TraceInOp("PRE", pre);
|
||||
if (IsMqtt())
|
||||
{
|
||||
var preErr = MqttParser.Parse(this, pre, pre.Length);
|
||||
if (preErr != null)
|
||||
{
|
||||
CloseConnection(ClosedState.ParseError);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MQTT clients use the MqttParser; NATS clients use ProtocolParser (not yet wired).
|
||||
if (!IsMqtt())
|
||||
return;
|
||||
|
||||
// Main read loop — read from network stream until closed.
|
||||
var buf = new byte[32768]; // 32 KB read buffer
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
int n;
|
||||
try
|
||||
{
|
||||
n = _nc!.Read(buf, 0, buf.Length);
|
||||
}
|
||||
catch
|
||||
{
|
||||
break; // Connection closed or errored.
|
||||
}
|
||||
|
||||
if (n <= 0)
|
||||
break; // Connection closed.
|
||||
|
||||
LastIn = DateTime.UtcNow;
|
||||
|
||||
var err = MqttParser.Parse(this, buf, n);
|
||||
if (err != null)
|
||||
{
|
||||
CloseConnection(ClosedState.ParseError);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
CloseConnection(ClosedState.ClientClosed);
|
||||
}
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
|
||||
Reference in New Issue
Block a user