Write entire compressed packet at once (#236)
This commit is contained in:
@ -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
|
// Write 'packet length' before all other fields
|
||||||
_, err = VarInt(int(n3) + buff.Len()).WriteTo(w)
|
packetLen := VarInt(buff.Len() - writeStart)
|
||||||
if err != nil {
|
start := writeStart - packetLen.Len()
|
||||||
|
VarInt(packetLen).WriteToBytes(buff.Bytes()[start:])
|
||||||
|
|
||||||
|
_, err := w.Write(buff.Bytes()[start:])
|
||||||
return err
|
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
|
// UnPack in-place decompression a packet
|
||||||
|
@ -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) {
|
||||||
|
Reference in New Issue
Block a user