96 lines
2.4 KiB
Go
96 lines
2.4 KiB
Go
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
|
|
}
|