101 lines
2.5 KiB
Go
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
|
|
}
|