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 = 1 PacketTypeConnack = 2 PacketTypePublish = 3 PacketTypePuback = 4 PacketTypePubrec = 5 PacketTypePubrel = 6 PacketTypePubcomp = 7 PacketTypeSubscribe = 8 PacketTypeSuback = 9 PacketTypeUnsubscribe = 10 PacketTypeUnsuback = 11 PacketTypePingreq = 12 PacketTypePingresp = 13 PacketTypeDisconnect = 14 PacketTypeAuth = 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 }