1
0
mirror of https://github.com/Mrs4s/MiraiGo.git synced 2025-05-04 11:07:40 +08:00

change writer without buffer

使用了sync.Pool,从池中取出来的自带一定容量,所以无需使用Buffer
This commit is contained in:
wdvxdr 2021-03-23 22:37:36 +08:00
parent 207df5fc00
commit d233c90d50
No known key found for this signature in database
GPG Key ID: 55FF1414A69CEBA6
4 changed files with 81 additions and 186 deletions

View File

@ -1,53 +1,44 @@
package binary
import (
"bytes"
"encoding/binary"
"encoding/hex"
"sync"
)
type Writer bytes.Buffer
type Writer struct {
b []byte
}
var bufferPool = sync.Pool{
New: func() interface{} {
return new(bytes.Buffer)
return new(Writer)
},
}
func NewBuffer() *bytes.Buffer {
return bufferPool.Get().(*bytes.Buffer)
func NewWriter() *Writer {
return bufferPool.Get().(*Writer)
}
func PutBuffer(buf *bytes.Buffer) {
func PutBuffer(w *Writer) {
// See https://golang.org/issue/23199
const maxSize = 1 << 16
if buf.Cap() < maxSize { // 对于大Buffer直接丢弃
buf.Reset()
bufferPool.Put(buf)
if cap(w.b) < maxSize { // 对于大Buffer直接丢弃
w.b = w.b[:0]
bufferPool.Put(w)
}
}
func NewWriter() *Writer {
return new(Writer)
}
/*
func PutWriter(w *Writer) {
PutBuffer((*bytes.Buffer)(w))
}
*/
func NewWriterF(f func(writer *Writer)) []byte {
w := NewBuffer()
f((*Writer)(w))
w := NewWriter()
f(w)
b := append([]byte(nil), w.Bytes()...)
PutBuffer(w)
return b
}
func (w *Writer) Write(b []byte) {
(*bytes.Buffer)(w).Write(b)
w.b = append(w.b, b...)
}
func (w *Writer) WriteHex(h string) {
@ -56,7 +47,7 @@ func (w *Writer) WriteHex(h string) {
}
func (w *Writer) WriteByte(b byte) {
(*bytes.Buffer)(w).WriteByte(b)
w.b = append(w.b, b)
}
func (w *Writer) WriteUInt16(v uint16) {
@ -138,5 +129,5 @@ func (w *Writer) WriteTlvLimitedSize(data []byte, limit int) {
}
func (w *Writer) Bytes() []byte {
return (*bytes.Buffer)(w).Bytes()
return w.b
}

View File

@ -1,71 +1,10 @@
package binary
import (
"bytes"
"encoding/hex"
"fmt"
"math/rand"
"sync"
"testing"
)
func NewWriterFOld(f func(writer *Writer)) []byte {
w := new(bytes.Buffer)
f((*Writer)(w))
return w.Bytes()
}
func TestNewWriterF(t *testing.T) {
wg := sync.WaitGroup{}
for i := 0; i < 10000; i++ {
wg.Add(1)
go func() {
defer wg.Done()
test := make([]byte, 1024)
rand.Read(test)
b1 := NewWriterFOld(func(writer *Writer) {
writer.Write(test)
writer.Write(NewWriterFOld(func(writer *Writer) {
writer.Write(test)
writer.Write(NewWriterFOld(func(writer *Writer) {
writer.Write(test)
}))
}))
})
b2 := NewWriterF(func(writer *Writer) {
writer.Write(test)
writer.Write(NewWriterF(func(writer *Writer) {
writer.Write(test)
writer.Write(NewWriterF(func(writer *Writer) {
writer.Write(test)
}))
}))
})
if !bytes.Equal(b1, b2) {
fmt.Println(hex.EncodeToString(b1))
fmt.Println(hex.EncodeToString(b2))
t.Error("Not equal!!!")
}
}()
}
wg.Wait()
}
func BenchmarkNewWriterFOld128(b *testing.B) {
test := make([]byte, 128)
rand.Read(test)
b.StartTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
NewWriterFOld(func(w *Writer) {
w.Write(test)
})
}
})
}
func BenchmarkNewWriterF128(b *testing.B) {
test := make([]byte, 128)
rand.Read(test)
@ -79,21 +18,6 @@ func BenchmarkNewWriterF128(b *testing.B) {
})
}
func BenchmarkNewWriterFOld128_3(b *testing.B) {
test := make([]byte, 128)
rand.Read(test)
b.StartTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
NewWriterFOld(func(w *Writer) {
w.Write(test)
w.Write(test)
w.Write(test)
})
}
})
}
func BenchmarkNewWriterF128_3(b *testing.B) {
test := make([]byte, 128)
rand.Read(test)
@ -109,23 +33,6 @@ func BenchmarkNewWriterF128_3(b *testing.B) {
})
}
func BenchmarkNewWriterFOld128_5(b *testing.B) {
test := make([]byte, 128)
rand.Read(test)
b.StartTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
NewWriterFOld(func(w *Writer) {
w.Write(test)
w.Write(test)
w.Write(test)
w.Write(test)
w.Write(test)
})
}
})
}
func BenchmarkNewWriterF128_5(b *testing.B) {
test := make([]byte, 128)
rand.Read(test)

View File

@ -7,35 +7,35 @@ import (
)
func BuildLoginPacket(uin int64, bodyType byte, key, body, extraData []byte) []byte {
w := binary.NewWriter()
w.WriteIntLvPacket(4, func(w *binary.Writer) {
w.WriteUInt32(0x00_00_00_0A)
w.WriteByte(bodyType)
return binary.NewWriterF(func(w *binary.Writer) {
w.WriteIntLvPacket(4, func(w *binary.Writer) {
w.Write(extraData)
w.WriteUInt32(0x00_00_00_0A)
w.WriteByte(bodyType)
w.WriteIntLvPacket(4, func(w *binary.Writer) {
w.Write(extraData)
})
w.WriteByte(0x00)
w.WriteString(strconv.FormatInt(uin, 10))
if len(key) == 0 {
w.Write(body)
} else {
w.EncryptAndWrite(key, body)
}
})
w.WriteByte(0x00)
w.WriteString(strconv.FormatInt(uin, 10))
if len(key) == 0 {
w.Write(body)
} else {
w.EncryptAndWrite(key, body)
}
})
return w.Bytes()
}
func BuildUniPacket(uin int64, seq uint16, commandName string, encryptType byte, sessionID, extraData, key, body []byte) []byte {
w := binary.NewWriter()
w.WriteIntLvPacket(4, func(w *binary.Writer) {
w.WriteUInt32(0x0B)
w.WriteByte(encryptType)
w.WriteUInt32(uint32(seq))
w.WriteByte(0)
w.WriteString(strconv.FormatInt(uin, 10))
w.EncryptAndWrite(key, binary.NewWriterF(func(w *binary.Writer) {
w.WriteUniPacket(commandName, sessionID, extraData, body)
}))
return binary.NewWriterF(func(w *binary.Writer) {
w.WriteIntLvPacket(4, func(w *binary.Writer) {
w.WriteUInt32(0x0B)
w.WriteByte(encryptType)
w.WriteUInt32(uint32(seq))
w.WriteByte(0)
w.WriteString(strconv.FormatInt(uin, 10))
w.EncryptAndWrite(key, binary.NewWriterF(func(w *binary.Writer) {
w.WriteUniPacket(commandName, sessionID, extraData, body)
}))
})
})
return w.Bytes()
}

View File

@ -33,26 +33,23 @@ type IEncryptMethod interface {
}
func BuildOicqRequestPacket(uin int64, commandId uint16, encrypt IEncryptMethod, key []byte, bodyFunc func(writer *binary.Writer)) []byte {
b := binary.NewWriter()
bodyFunc(b)
body := encrypt.DoEncrypt(b.Bytes(), key)
p := binary.NewWriter()
p.WriteByte(0x02)
p.WriteUInt16(27 + 2 + uint16(len(body)))
p.WriteUInt16(8001)
p.WriteUInt16(commandId)
p.WriteUInt16(1)
p.WriteUInt32(uint32(uin))
p.WriteByte(3)
p.WriteByte(encrypt.Id())
p.WriteByte(0)
p.WriteUInt32(2)
p.WriteUInt32(0)
p.WriteUInt32(0)
p.Write(body)
p.WriteByte(0x03)
return p.Bytes()
body := encrypt.DoEncrypt(binary.NewWriterF(bodyFunc), key)
return binary.NewWriterF(func(p *binary.Writer) {
p.WriteByte(0x02)
p.WriteUInt16(27 + 2 + uint16(len(body)))
p.WriteUInt16(8001)
p.WriteUInt16(commandId)
p.WriteUInt16(1)
p.WriteUInt32(uint32(uin))
p.WriteByte(3)
p.WriteByte(encrypt.Id())
p.WriteByte(0)
p.WriteUInt32(2)
p.WriteUInt32(0)
p.WriteUInt32(0)
p.Write(body)
p.WriteByte(0x03)
})
}
func BuildCode2DRequestPacket(seq uint32, j uint64, cmd uint16, bodyFunc func(writer *binary.Writer)) []byte {
@ -73,35 +70,35 @@ func BuildCode2DRequestPacket(seq uint32, j uint64, cmd uint16, bodyFunc func(wr
}
func BuildSsoPacket(seq uint16, appID uint32, commandName, imei string, extData, outPacketSessionId, body, ksid []byte) []byte {
p := binary.NewWriter()
p.WriteIntLvPacket(4, func(writer *binary.Writer) {
writer.WriteUInt32(uint32(seq))
writer.WriteUInt32(appID)
writer.WriteUInt32(appID)
writer.Write([]byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00})
if len(extData) == 0 || len(extData) == 4 {
return binary.NewWriterF(func(p *binary.Writer) {
p.WriteIntLvPacket(4, func(writer *binary.Writer) {
writer.WriteUInt32(uint32(seq))
writer.WriteUInt32(appID)
writer.WriteUInt32(appID)
writer.Write([]byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00})
if len(extData) == 0 || len(extData) == 4 {
writer.WriteUInt32(0x04)
} else {
writer.WriteUInt32(uint32(len(extData) + 4))
writer.Write(extData)
}
writer.WriteString(commandName)
writer.WriteIntLvPacket(4, func(w *binary.Writer) {
w.Write(outPacketSessionId)
})
writer.WriteString(imei)
writer.WriteUInt32(0x04)
{
writer.WriteUInt16(uint16(len(ksid)) + 2)
writer.Write(ksid)
}
writer.WriteUInt32(0x04)
} else {
writer.WriteUInt32(uint32(len(extData) + 4))
writer.Write(extData)
}
writer.WriteString(commandName)
writer.WriteIntLvPacket(4, func(w *binary.Writer) {
w.Write(outPacketSessionId)
})
writer.WriteString(imei)
writer.WriteUInt32(0x04)
{
writer.WriteUInt16(uint16(len(ksid)) + 2)
writer.Write(ksid)
}
writer.WriteUInt32(0x04)
})
p.WriteIntLvPacket(4, func(writer *binary.Writer) {
writer.Write(body)
p.WriteIntLvPacket(4, func(writer *binary.Writer) {
writer.Write(body)
})
})
return p.Bytes()
}
func ParseIncomingPacket(payload, d2key []byte) (*IncomingPacket, error) {