maeqtt/mqtt/packets/packets.go
2021-10-17 21:09:44 +02:00

101 lines
2.5 KiB
Go

package packets
import (
"bufio"
"fmt"
"io"
"badat.dev/maeqtt/v2/mqtt/types"
)
type PacketVisitor interface {
VisitConnect(ConnectPacket)
VisitPublish(PublishPacket)
VisitDisconnect(DisconnectPacket)
VisitSubscribe(SubscribePacket)
VisitUnsubscribe(UnsubscribePacket)
VisitPing(PingreqPacket)
VisitPubackPacket(PubackPacket)
VisitPubrecPacket(PubrecPacket)
VisitPubrelPacket(PubrelPacket)
VisitPubcompPacket(PubcompPacket)
}
type ClientPacket interface {
Visit(PacketVisitor)
}
type ServerPacket interface {
Write(w io.Writer) error
}
type PacketType byte
const (
PacketTypeReserved PacketType = 0 // Forbidden
PacketTypeConnect PacketType = 1
PacketTypeConnack PacketType = 2
PacketTypePublish PacketType = 3
PacketTypePuback PacketType = 4
PacketTypePubrec PacketType = 5
PacketTypePubrel PacketType = 6
PacketTypePubcomp PacketType = 7
PacketTypeSubscribe PacketType = 8
PacketTypeSuback PacketType = 9
PacketTypeUnsubscribe PacketType = 10
PacketTypeUnsuback PacketType = 11
PacketTypePingreq PacketType = 12
PacketTypePingresp PacketType = 13
PacketTypeDisconnect PacketType = 14
PacketTypeAuth PacketType = 15
)
func ReadPacket(r *bufio.Reader) (*ClientPacket, error) {
fixedHeader, err := r.ReadByte()
if err != nil {
return nil, err
}
highestFourBits := uint((fixedHeader >> 4) & 0b1111)
lowerFourBits := uint(fixedHeader & 0b1111)
dataLength, err := types.DecodeVariableByteInt(r)
if err != nil {
return nil, err
}
reader := io.LimitReader(r, int64(dataLength))
control := controlPacket{
packetType: PacketType(highestFourBits),
flags: lowerFourBits,
reader: reader,
}
var packet ClientPacket
switch control.packetType {
case PacketTypeConnect:
packet, err = parseConnectPacket(control)
case PacketTypePublish:
packet, err = parsePublishPacket(control)
case PacketTypeDisconnect:
packet, err = parseDisconnectPacket(control)
case PacketTypeSubscribe:
packet, err = parseSubscribePacket(control)
case PacketTypeUnsubscribe:
packet, err = parseUnsubscribePacket(control)
case PacketTypePingreq:
packet, err = parsePingreq(control)
case PacketTypePuback:
panic("Puback packet parsing unimplemented")
case PacketTypePubrec:
panic("Pubrec packet parsing unimplemented")
case PacketTypePubrel:
panic("Pubrel packet parsing unimplemented")
case PacketTypePubcomp:
panic("Pubcomp packet parsing unimplemented")
default:
return nil, fmt.Errorf("Unknown packet type %v", control.packetType)
}
return &packet, err
}