package protocol import ( "bytes" "encoding/binary" "errors" ) // PacketType represents the type of a TeamSpeak 3 packet. type PacketType uint8 const ( PacketTypeVoice PacketType = 0x00 PacketTypeVoiceWhisper PacketType = 0x01 PacketTypeCommand PacketType = 0x02 PacketTypeCommandLow PacketType = 0x03 PacketTypePing PacketType = 0x04 PacketTypePong PacketType = 0x05 PacketTypeAck PacketType = 0x06 PacketTypeAckLow PacketType = 0x07 PacketTypeInit1 PacketType = 0x08 ) // Packet Flags const ( PacketFlagUnencrypted = 0x80 PacketFlagCompressed = 0x40 PacketFlagNewProtocol = 0x20 PacketFlagFragmented = 0x10 ) const ( HeaderSizeClientToServer = 13 // 8 MAC + 2 PID + 2 CID + 1 PT HeaderSizeServerToClient = 11 // 8 MAC + 2 PID + 1 PT MACSize = 8 ) // PacketHeader represents the common header fields. type PacketHeader struct { MAC [8]byte PacketID uint16 ClientID uint16 // Only present in Client -> Server Type uint8 // Contains PacketType and Flags } // Packet represents a parsed TeamSpeak 3 packet. type Packet struct { Header PacketHeader Data []byte } func (h *PacketHeader) FlagUnencrypted() bool { return h.Type&PacketFlagUnencrypted != 0 } func (h *PacketHeader) FlagCompressed() bool { return h.Type&PacketFlagCompressed != 0 } func (h *PacketHeader) FlagNewProtocol() bool { return h.Type&PacketFlagNewProtocol != 0 } func (h *PacketHeader) FlagFragmented() bool { return h.Type&PacketFlagFragmented != 0 } func (h *PacketHeader) PacketType() PacketType { return PacketType(h.Type & 0x0F) } // SetType sets the packet type and preserves flags func (h *PacketHeader) SetType(pt PacketType) { flags := h.Type & 0xF0 h.Type = flags | uint8(pt&0x0F) } // Encode writes the packet to a byte slice. func (p *Packet) Encode(isClientToServer bool) ([]byte, error) { buf := new(bytes.Buffer) // MAC buf.Write(p.Header.MAC[:]) // Packet ID if err := binary.Write(buf, binary.BigEndian, p.Header.PacketID); err != nil { return nil, err } // Client ID (only C->S) if isClientToServer { if err := binary.Write(buf, binary.BigEndian, p.Header.ClientID); err != nil { return nil, err } } // Packet Type if err := binary.Write(buf, binary.BigEndian, p.Header.Type); err != nil { return nil, err } // Data buf.Write(p.Data) return buf.Bytes(), nil } // Decode parses a packet from a byte slice. func Decode(data []byte, isClientToServer bool) (*Packet, error) { reader := bytes.NewReader(data) p := &Packet{} // Check minimum size minSize := HeaderSizeServerToClient if isClientToServer { minSize = HeaderSizeClientToServer } if len(data) < minSize { return nil, errors.New("packet too short") } // MAC if _, err := reader.Read(p.Header.MAC[:]); err != nil { return nil, err } // Packet ID if err := binary.Read(reader, binary.BigEndian, &p.Header.PacketID); err != nil { return nil, err } // Client ID (only C->S) if isClientToServer { if err := binary.Read(reader, binary.BigEndian, &p.Header.ClientID); err != nil { return nil, err } } // Packet Type if err := binary.Read(reader, binary.BigEndian, &p.Header.Type); err != nil { return nil, err } // Data p.Data = make([]byte, reader.Len()) if _, err := reader.Read(p.Data); err != nil { return nil, err } return p, nil } func NewPacket(pt PacketType, data []byte) *Packet { return &Packet{ Header: PacketHeader{ Type: uint8(pt), MAC: [8]byte{}, // Default empty MAC }, Data: data, } }