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 }