package protocol import ( "bytes" "compress/zlib" "encoding/binary" "io" "math" ) func ZlibCompress(data []byte) []byte { var b bytes.Buffer w := zlib.NewWriter(&b) w.Write(data) w.Close() return b.Bytes() } // Codec Functions (migrated from main.go) func ReadVarint(r io.ByteReader) (uint64, error) { return binary.ReadUvarint(r) } func ReadVarintInt64(r io.ByteReader) (int64, error) { v, err := binary.ReadUvarint(r) return int64(v), err } func EncodeVarint(v uint64) []byte { buf := make([]byte, binary.MaxVarintLen64) n := binary.PutUvarint(buf, v) return buf[:n] } func EncodeDouble(v float64) []byte { buf := make([]byte, 8) binary.LittleEndian.PutUint64(buf, math.Float64bits(v)) return buf } func SkipField(reader *bytes.Reader, wireType uint64) { switch wireType { case 0: // Varint ReadVarint(reader) case 1: // Fixed64 reader.Seek(8, io.SeekCurrent) case 2: // Length-delimited length, _ := ReadVarint(reader) reader.Seek(int64(length), io.SeekCurrent) case 5: // Fixed32 reader.Seek(4, io.SeekCurrent) } } // Helper to read a packet length (4 bytes, Big Endian) as per official protocol func ReadPacketLength(conn io.Reader) (uint32, error) { var length uint32 err := binary.Read(conn, binary.BigEndian, &length) return length, err } // WrapPacket encapsulates a payload in the Message and Packet structure // 1. Message wrapper (Field 1: requestNumber, Field [requestNumber]: payload field) // 2. Packet wrapper (Field 1: packetID, Field 3: Message bytes) // 3. 4-byte Big Endian length prefix func WrapPacket(requestNumber int, payload []byte, packetID uint32) []byte { // 1. Wrap in Message msg := make([]byte, 0) // Field 1: request_number (Varint) msg = append(msg, 0x08) msg = append(msg, EncodeVarint(uint64(requestNumber))...) // Field [requestNumber]: The actual response payload msg = append(msg, EncodeVarint(uint64(uint32(requestNumber)<<3|2))...) msg = append(msg, EncodeVarint(uint64(len(payload)))...) msg = append(msg, payload...) // 2. Wrap in Packet packet := make([]byte, 0) // Field 1: Id (Varint) packet = append(packet, 0x08) packet = append(packet, EncodeVarint(uint64(packetID))...) // Field 3: Payload (Message) packet = append(packet, 0x1a) packet = append(packet, EncodeVarint(uint64(len(msg)))...) packet = append(packet, msg...) // 3. Add 4-byte length prefix final := make([]byte, 4) binary.BigEndian.PutUint32(final, uint32(len(packet))) final = append(final, packet...) return final }