Write entire compressed packet at once (#236)
This commit is contained in:
@ -63,104 +63,54 @@ func (p *Packet) packWithoutCompression(w io.Writer) error {
|
||||
VarInt(p.ID).WriteTo(buffer)
|
||||
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
|
||||
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:])
|
||||
_, err := w.Write(buffer.Bytes()[varIntOffset:])
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *Packet) packWithCompression(w io.Writer, threshold int) error {
|
||||
buff := bufPool.Get().(*bytes.Buffer)
|
||||
defer bufPool.Put(buff)
|
||||
// Allocate room for the 'packet length' and 'data length' fields. Each can take up to 3 bytes
|
||||
buff.Reset()
|
||||
buff.Write([]byte{0, 0, 0, 0, 0, 0})
|
||||
|
||||
var writeStart int
|
||||
|
||||
if len(p.Data) < threshold {
|
||||
_, err := VarInt(0).WriteTo(buff)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = VarInt(p.ID).WriteTo(buff)
|
||||
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
|
||||
}
|
||||
VarInt(p.ID).WriteTo(buff)
|
||||
buff.Write(p.Data)
|
||||
// Packet is below compression threshold so 'data length' is 0
|
||||
// Front of the packet is already initialized to 0, so just decrement the offset
|
||||
writeStart = 5
|
||||
} else {
|
||||
zw := zlib.NewWriter(buff)
|
||||
n1, err := VarInt(p.ID).WriteTo(zw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
n2, err := zw.Write(p.Data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = zw.Close()
|
||||
varIntLen, _ := VarInt(p.ID).WriteTo(zw)
|
||||
zw.Write(p.Data)
|
||||
|
||||
err := zw.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dataLength := bufPool.Get().(*bytes.Buffer)
|
||||
defer bufPool.Put(dataLength)
|
||||
dataLength.Reset()
|
||||
n3, err := VarInt(int(n1) + n2).WriteTo(dataLength)
|
||||
if err != nil {
|
||||
return err
|
||||
// Write 'data length' before ID + payload
|
||||
uncompressedLen := VarInt(varIntLen + int64(len(p.Data)))
|
||||
writeStart = 6 - uncompressedLen.Len()
|
||||
uncompressedLen.WriteToBytes(buff.Bytes()[writeStart:])
|
||||
}
|
||||
|
||||
// Packet Length
|
||||
_, err = VarInt(int(n3) + buff.Len()).WriteTo(w)
|
||||
if err != 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
|
||||
}
|
||||
// Data Length
|
||||
_, err = dataLength.WriteTo(w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// PacketID + Data
|
||||
_, err = buff.WriteTo(w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnPack in-place decompression a packet
|
||||
func (p *Packet) UnPack(r io.Reader, threshold int) error {
|
||||
|
@ -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) {
|
||||
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)
|
||||
i := 0
|
||||
for {
|
||||
b := num & 0x7F
|
||||
num >>= 7
|
||||
if num != 0 {
|
||||
b |= 0x80
|
||||
}
|
||||
vi = append(vi, byte(b))
|
||||
buf[i] = byte(b)
|
||||
i++
|
||||
if num == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
nn, err := w.Write(vi)
|
||||
return int64(nn), err
|
||||
return i
|
||||
}
|
||||
|
||||
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) {
|
||||
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)
|
||||
i := 0
|
||||
for {
|
||||
b := num & 0x7F
|
||||
num >>= 7
|
||||
if num != 0 {
|
||||
b |= 0x80
|
||||
}
|
||||
vi = append(vi, byte(b))
|
||||
buf[i] = byte(b)
|
||||
i++
|
||||
if num == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
nn, err := w.Write(vi)
|
||||
return int64(nn), err
|
||||
return i
|
||||
}
|
||||
|
||||
func (v *VarLong) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
|
Reference in New Issue
Block a user