Write entire compressed packet at once (#236)

This commit is contained in:
Richard Grover
2023-03-31 19:57:16 -06:00
committed by GitHub
parent 6bbfeec2c7
commit a8f9c4bee5
2 changed files with 52 additions and 88 deletions

View File

@ -63,103 +63,53 @@ func (p *Packet) packWithoutCompression(w io.Writer) error {
VarInt(p.ID).WriteTo(buffer) VarInt(p.ID).WriteTo(buffer)
buffer.Write(p.Data) buffer.Write(p.Data)
payloadLen := uint32(buffer.Len() - 3) // Write length at front
payloadLen := VarInt(buffer.Len() - 3)
varIntOffset := 3 - payloadLen.Len()
payloadLen.WriteToBytes(buffer.Bytes()[varIntOffset:])
// Determine where to start writing the header based on the payload size _, err := w.Write(buffer.Bytes()[varIntOffset:])
var headerStart int
if payloadLen <= 0xFF>>1 {
headerStart = 2
} else if payloadLen <= 0xFFFF>>2 {
headerStart = 1
} else if payloadLen <= 0xFFFFFF>>3 {
headerStart = 0
} else {
panic(fmt.Errorf("packet length %d is too large", payloadLen))
}
// Write the packet length at the beginning of the packet
for i := headerStart; payloadLen != 0; i++ {
b := byte(payloadLen & 0b01111111)
payloadLen >>= 7
if payloadLen != 0 {
b |= 0b10000000
}
buffer.Bytes()[i] = b
}
_, err := w.Write(buffer.Bytes()[headerStart:])
return err return err
} }
func (p *Packet) packWithCompression(w io.Writer, threshold int) error { func (p *Packet) packWithCompression(w io.Writer, threshold int) error {
buff := bufPool.Get().(*bytes.Buffer) buff := bufPool.Get().(*bytes.Buffer)
defer bufPool.Put(buff) defer bufPool.Put(buff)
// Allocate room for the 'packet length' and 'data length' fields. Each can take up to 3 bytes
buff.Reset() buff.Reset()
buff.Write([]byte{0, 0, 0, 0, 0, 0})
var writeStart int
if len(p.Data) < threshold { if len(p.Data) < threshold {
_, err := VarInt(0).WriteTo(buff) VarInt(p.ID).WriteTo(buff)
if err != nil { buff.Write(p.Data)
return err // Packet is below compression threshold so 'data length' is 0
} // Front of the packet is already initialized to 0, so just decrement the offset
_, err = VarInt(p.ID).WriteTo(buff) writeStart = 5
if err != nil {
return err
}
_, err = buff.Write(p.Data)
if err != nil {
return err
}
// Packet Length
_, err = VarInt(buff.Len()).WriteTo(w)
if err != nil {
return err
}
// Data Length + Packet ID + Data
_, err = buff.WriteTo(w)
if err != nil {
return err
}
} else { } else {
zw := zlib.NewWriter(buff) zw := zlib.NewWriter(buff)
n1, err := VarInt(p.ID).WriteTo(zw) varIntLen, _ := VarInt(p.ID).WriteTo(zw)
if err != nil { zw.Write(p.Data)
return err
} err := zw.Close()
n2, err := zw.Write(p.Data)
if err != nil {
return err
}
err = zw.Close()
if err != nil { if err != nil {
return err return err
} }
dataLength := bufPool.Get().(*bytes.Buffer) // Write 'data length' before ID + payload
defer bufPool.Put(dataLength) uncompressedLen := VarInt(varIntLen + int64(len(p.Data)))
dataLength.Reset() writeStart = 6 - uncompressedLen.Len()
n3, err := VarInt(int(n1) + n2).WriteTo(dataLength) uncompressedLen.WriteToBytes(buff.Bytes()[writeStart:])
if err != nil {
return err
}
// Packet Length
_, err = VarInt(int(n3) + buff.Len()).WriteTo(w)
if err != nil {
return err
}
// Data Length
_, err = dataLength.WriteTo(w)
if err != nil {
return err
}
// PacketID + Data
_, err = buff.WriteTo(w)
if err != nil {
return err
}
} }
return nil
// Write 'packet length' before all other fields
packetLen := VarInt(buff.Len() - writeStart)
start := writeStart - packetLen.Len()
VarInt(packetLen).WriteToBytes(buff.Bytes()[start:])
_, err := w.Write(buff.Bytes()[start:])
return err
} }
// UnPack in-place decompression a packet // UnPack in-place decompression a packet

View File

@ -252,21 +252,28 @@ func (l *Long) ReadFrom(r io.Reader) (n int64, err error) {
} }
func (v VarInt) WriteTo(w io.Writer) (n int64, err error) { func (v VarInt) WriteTo(w io.Writer) (n int64, err error) {
vi := make([]byte, 0, MaxVarIntLen) vi := make([]byte, MaxVarIntLen)
nn := v.WriteToBytes(vi)
_, err = w.Write(vi[:nn])
return int64(nn), err
}
func (v VarInt) WriteToBytes(buf []byte) int {
num := uint32(v) num := uint32(v)
i := 0
for { for {
b := num & 0x7F b := num & 0x7F
num >>= 7 num >>= 7
if num != 0 { if num != 0 {
b |= 0x80 b |= 0x80
} }
vi = append(vi, byte(b)) buf[i] = byte(b)
i++
if num == 0 { if num == 0 {
break break
} }
} }
nn, err := w.Write(vi) return i
return int64(nn), err
} }
func (v *VarInt) ReadFrom(r io.Reader) (n int64, err error) { func (v *VarInt) ReadFrom(r io.Reader) (n int64, err error) {
@ -308,21 +315,28 @@ func (v VarInt) Len() int {
} }
func (v VarLong) WriteTo(w io.Writer) (n int64, err error) { func (v VarLong) WriteTo(w io.Writer) (n int64, err error) {
vi := make([]byte, 0, MaxVarLongLen) vi := make([]byte, MaxVarLongLen)
nn := v.WriteToBytes(vi)
_, err = w.Write(vi[:nn])
return int64(nn), err
}
func (v VarLong) WriteToBytes(buf []byte) int {
num := uint64(v) num := uint64(v)
i := 0
for { for {
b := num & 0x7F b := num & 0x7F
num >>= 7 num >>= 7
if num != 0 { if num != 0 {
b |= 0x80 b |= 0x80
} }
vi = append(vi, byte(b)) buf[i] = byte(b)
i++
if num == 0 { if num == 0 {
break break
} }
} }
nn, err := w.Write(vi) return i
return int64(nn), err
} }
func (v *VarLong) ReadFrom(r io.Reader) (n int64, err error) { func (v *VarLong) ReadFrom(r io.Reader) (n int64, err error) {