102 lines
2.3 KiB
Go
102 lines
2.3 KiB
Go
package udp
|
|
|
|
import (
|
|
"bytes"
|
|
"compress/zlib"
|
|
"io"
|
|
)
|
|
|
|
// Compression markers used by EQ2EMu protocol
|
|
const (
|
|
CompressedMarker = 0x5A // Marks zlib compressed data
|
|
UncompressedMarker = 0xA5 // Marks uncompressed data
|
|
)
|
|
|
|
// Compress applies zlib compression with EQ2EMu protocol markers
|
|
// Returns compressed data only if compression provides space savings
|
|
func Compress(data []byte) ([]byte, error) {
|
|
// Empty data gets uncompressed marker
|
|
if len(data) == 0 {
|
|
return []byte{UncompressedMarker}, nil
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
buf.WriteByte(CompressedMarker)
|
|
|
|
// Compress data using zlib
|
|
writer := zlib.NewWriter(&buf)
|
|
if _, err := writer.Write(data); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := writer.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Only use compression if it actually saves space
|
|
if buf.Len() >= len(data)+1 {
|
|
result := make([]byte, len(data)+1)
|
|
result[0] = UncompressedMarker
|
|
copy(result[1:], data)
|
|
return result, nil
|
|
}
|
|
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
// Decompress handles both compressed and uncompressed data based on markers
|
|
func Decompress(data []byte) ([]byte, error) {
|
|
if len(data) == 0 {
|
|
return data, nil
|
|
}
|
|
|
|
switch data[0] {
|
|
case UncompressedMarker:
|
|
// Data is uncompressed - return without marker
|
|
return data[1:], nil
|
|
|
|
case CompressedMarker:
|
|
// Data is zlib compressed
|
|
return decompressZlib(data[1:])
|
|
|
|
default:
|
|
// No compression marker - return as-is
|
|
return data, nil
|
|
}
|
|
}
|
|
|
|
// decompressZlib handles zlib decompression
|
|
func decompressZlib(data []byte) ([]byte, error) {
|
|
if len(data) == 0 {
|
|
return nil, io.ErrUnexpectedEOF
|
|
}
|
|
|
|
reader := bytes.NewReader(data)
|
|
zlibReader, err := zlib.NewReader(reader)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer zlibReader.Close()
|
|
|
|
var buf bytes.Buffer
|
|
if _, err := io.Copy(&buf, zlibReader); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
// IsCompressed checks if data has compression marker
|
|
func IsCompressed(data []byte) bool {
|
|
return len(data) > 0 && data[0] == CompressedMarker
|
|
}
|
|
|
|
// IsUncompressed checks if data has uncompressed marker
|
|
func IsUncompressed(data []byte) bool {
|
|
return len(data) > 0 && data[0] == UncompressedMarker
|
|
}
|
|
|
|
// HasCompressionMarker checks if data has any compression marker
|
|
func HasCompressionMarker(data []byte) bool {
|
|
return IsCompressed(data) || IsUncompressed(data)
|
|
}
|