feat(mqtt): implement CONNECT/CONNACK/DISCONNECT packet handlers

Implement Task 3 of MQTT orchestration:
- Create MqttPacketHandlers.cs with ParseConnect(), ProcessConnect(), EnqueueConnAck(), HandleDisconnect()
- Wire CONNECT and DISCONNECT dispatch in MqttParser.cs
- Parse CONNECT: protocol name/level, flags, keep-alive, client ID, will, auth
- Send CONNACK (4-byte fixed packet with return code)
- DISCONNECT clears will message and closes connection cleanly
- Auto-generate client ID for empty ID + clean session
- Validate reserved bit, will flags, username/password consistency
- Add Reader field to MqttHandler for per-connection parsing
- 11 unit tests for CONNECT parsing and processing
- 1 end-to-end integration test: TCP → CONNECT → CONNACK over the wire
This commit is contained in:
Joseph Doherty
2026-03-01 15:48:22 -05:00
parent 2e2ffee41a
commit 95cf20b00b
6 changed files with 768 additions and 15 deletions

View File

@@ -126,18 +126,32 @@ internal static class MqttParser
case MqttPacket.Connect:
if (connected)
{
// Second CONNECT on same connection is a protocol violation.
err = new InvalidOperationException("second CONNECT packet not allowed");
break;
}
// TODO: Task 3 — MqttParseConnect + MqttProcessConnect
err = new NotImplementedException("CONNECT not yet implemented");
var (rc, cp, parseErr) = MqttPacketHandlers.ParseConnect(r);
if (parseErr != null)
{
// Send CONNACK with error code if we have one, then close.
if (rc != MqttConnAckRc.Accepted)
MqttPacketHandlers.EnqueueConnAck(c, rc, false);
err = parseErr;
break;
}
if (rc != MqttConnAckRc.Accepted)
{
MqttPacketHandlers.EnqueueConnAck(c, rc, false);
err = new InvalidOperationException($"CONNECT rejected with code 0x{rc:X2}");
break;
}
err = MqttPacketHandlers.ProcessConnect(c, cp!);
if (err == null)
connected = true;
break;
case MqttPacket.Disconnect:
// TODO: Task 3 — handle DISCONNECT
err = new NotImplementedException("DISCONNECT not yet implemented");
break;
MqttPacketHandlers.HandleDisconnect(c);
return null; // Connection closed, exit parse loop.
default:
err = new InvalidOperationException($"unknown MQTT packet type: 0x{pt:X2}");