feat(mqtt): implement PUBLISH QoS 0, SUBSCRIBE, and UNSUBSCRIBE handlers

Add ParsePub, ParseSubsOrUnsubs, ProcessPub (QoS 0), ProcessSubs,
ProcessUnsubs, EnqueueSubAck, and EnqueueUnsubAck to MqttPacketHandlers.
Wire PUB/SUB/UNSUB dispatch cases in MqttParser. Add ReadSlice to
MqttReader for raw payload extraction. 18 new unit tests covering
parsing, flags, error cases, QoS downgrade, and full flow. 1 new
integration test verifying SUBSCRIBE handshake over TCP.
This commit is contained in:
Joseph Doherty
2026-03-01 16:04:37 -05:00
parent 95cf20b00b
commit 715367b9ea
7 changed files with 947 additions and 21 deletions

View File

@@ -85,8 +85,10 @@ internal static class MqttParser
switch (pt)
{
case MqttPacket.Pub:
// TODO: Task 4 — MqttParsePub + MqttProcessPub
err = new NotImplementedException("PUBLISH not yet implemented");
var pubFlags = (byte)(b & MqttPacket.FlagMask);
var (pp, pubErr) = MqttPacketHandlers.ParsePub(r, pl, pubFlags, mqtt.RejectQoS2Pub);
if (pubErr != null) { err = pubErr; break; }
err = MqttPacketHandlers.ProcessPub(c, pp!);
break;
case MqttPacket.PubAck:
@@ -110,13 +112,15 @@ internal static class MqttParser
break;
case MqttPacket.Sub:
// TODO: Task 4 — MqttParseSubs + MqttProcessSubs
err = new NotImplementedException("SUBSCRIBE not yet implemented");
var (subPi, subFilters, subErr) = MqttPacketHandlers.ParseSubsOrUnsubs(r, b, pl, isSub: true);
if (subErr != null) { err = subErr; break; }
err = MqttPacketHandlers.ProcessSubs(c, subPi, subFilters!);
break;
case MqttPacket.Unsub:
// TODO: Task 4 — MqttParseUnsubs + MqttProcessUnsubs
err = new NotImplementedException("UNSUBSCRIBE not yet implemented");
var (unsubPi, unsubFilters, unsubErr) = MqttPacketHandlers.ParseSubsOrUnsubs(r, b, pl, isSub: false);
if (unsubErr != null) { err = unsubErr; break; }
err = MqttPacketHandlers.ProcessUnsubs(c, unsubPi, unsubFilters!);
break;
case MqttPacket.Ping: