1
0
mirror of https://github.com/Mrs4s/MiraiGo.git synced 2025-05-04 19:17:38 +08:00

Merge pull request #203 from fumiama/master

perf: on jce & tea & pool & writer
This commit is contained in:
Mrs4s 2021-12-03 12:30:19 +08:00 committed by GitHub
commit e043181fc1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 520 additions and 164 deletions

View File

@ -3,7 +3,6 @@ package jce
import (
goBinary "encoding/binary"
"math"
"reflect"
"github.com/Mrs4s/MiraiGo/utils"
)
@ -22,28 +21,36 @@ func NewJceReader(data []byte) *JceReader {
return &JceReader{buf: data}
}
func (r *JceReader) readHead() (hd HeadData, l int32) {
b := r.buf[r.off]
hd.Type = b & 0xF
hd.Tag = (int(b) & 0xF0) >> 4
l = 1
if hd.Tag == 15 {
b = r.buf[r.off+1]
hd.Tag = int(b) & 0xFF
l = 2
}
r.off += int(l)
func (r *JceReader) readHead() (hd HeadData, l int) {
hd, l = r.peakHead()
r.off += l
return
}
func (r *JceReader) peakHead() (h HeadData, l int32) {
h, l = r.readHead()
r.off -= int(l)
func (r *JceReader) peakHead() (hd HeadData, l int) {
b := r.buf[r.off]
hd.Type = b & 0xF
hd.Tag = int(uint(b) >> 4)
l = 1
if hd.Tag == 0xF {
b = r.buf[r.off+1]
hd.Tag = int(uint(b))
l = 2
}
return
}
func (r *JceReader) skipHead() {
l := 1
if int(uint(r.buf[r.off])>>4) == 0xF {
l = 2
}
r.off += l
return
}
func (r *JceReader) skip(l int) {
r.off += l
r.skipBytes(l)
}
func (r *JceReader) skipField(t byte) {
@ -57,10 +64,9 @@ func (r *JceReader) skipField(t byte) {
case 3, 5:
r.skip(8)
case 6:
b := r.readByte()
r.skip(int(b))
r.skip(int(r.readByte()))
case 7:
r.skip(int(r.readInt32()))
r.skip(int(r.readUInt32()))
case 8:
s := r.ReadInt32(0)
for i := 0; i < int(s)*2; i++ {
@ -72,7 +78,7 @@ func (r *JceReader) skipField(t byte) {
r.skipNextField()
}
case 13:
r.readHead()
r.skipHead()
s := r.ReadInt32(0)
r.skip(int(s))
case 10:
@ -96,11 +102,21 @@ func (r *JceReader) readBytes(n int) []byte {
panic("readBytes: EOF")
}
b := make([]byte, n)
n = copy(b, r.buf[r.off:])
r.off += n
r.off += copy(b, r.buf[r.off:])
return b
}
func (r *JceReader) skipBytes(n int) {
if r.off+n > len(r.buf) {
panic("skipBytes: EOF")
}
lremain := len(r.buf[r.off:])
if lremain < n {
n = lremain
}
r.off += n
}
func (r *JceReader) readByte() byte {
if r.off >= len(r.buf) {
panic("readByte: EOF")
@ -111,48 +127,40 @@ func (r *JceReader) readByte() byte {
}
func (r *JceReader) readUInt16() uint16 {
b := r.readBytes(2)
return uint16((int32(b[0]) << 8) + int32(b[1]))
return goBinary.BigEndian.Uint16(r.readBytes(2))
}
func (r *JceReader) readInt32() int32 {
b := r.readBytes(4)
return int32(goBinary.BigEndian.Uint32(b))
func (r *JceReader) readUInt32() uint32 {
return goBinary.BigEndian.Uint32(r.readBytes(4))
}
func (r *JceReader) readInt64() int64 {
b := r.readBytes(8)
return int64(goBinary.BigEndian.Uint64(b))
func (r *JceReader) readUInt64() uint64 {
return goBinary.BigEndian.Uint64(r.readBytes(8))
}
func (r *JceReader) readFloat32() float32 {
b := r.readInt32()
return math.Float32frombits(uint32(b))
return math.Float32frombits(r.readUInt32())
}
func (r *JceReader) readFloat64() float64 {
b := r.readInt64()
return math.Float64frombits(uint64(b))
return math.Float64frombits(r.readUInt64())
}
func (r *JceReader) skipToTag(tag int) bool {
for {
hd, l := r.peakHead()
if tag <= hd.Tag || hd.Type == 11 {
return tag == hd.Tag
}
r.skip(int(l))
hd, l := r.peakHead()
for tag > hd.Tag && hd.Type != 11 {
r.skip(l)
r.skipField(hd.Type)
hd, l = r.peakHead()
}
return tag == hd.Tag
}
func (r *JceReader) skipToStructEnd() {
for {
hd, _ := r.readHead()
hd, _ := r.readHead()
for hd.Type != 11 {
r.skipField(hd.Type)
if hd.Type == 11 {
return
}
hd, _ = r.readHead()
}
}
@ -205,7 +213,7 @@ func (r *JceReader) ReadInt32(tag int) int32 {
case 1:
return int32(r.readUInt16())
case 2:
return r.readInt32()
return int32(r.readUInt32())
default:
return 0
}
@ -224,9 +232,9 @@ func (r *JceReader) ReadInt64(tag int) int64 {
case 1:
return int64(int16(r.readUInt16()))
case 2:
return int64(r.readInt32())
return int64(r.readUInt32())
case 3:
return r.readInt64()
return int64(r.readUInt64())
default:
return 0
}
@ -273,7 +281,7 @@ func (r *JceReader) ReadString(tag int) string {
case 6:
return utils.B2S(r.readBytes(int(r.readByte())))
case 7:
return utils.B2S(r.readBytes(int(r.readInt32())))
return utils.B2S(r.readBytes(int(r.readUInt32())))
default:
return ""
}
@ -293,13 +301,32 @@ func (r *JceReader) ReadBytes(tag int) []byte {
}
return b
case 13:
r.readHead()
r.skipHead()
return r.readBytes(int(r.ReadInt32(0)))
default:
return nil
}
}
func (r *JceReader) ReadByteArrArr(tag int) (baa [][]byte) {
if !r.skipToTag(tag) {
return nil
}
hd, _ := r.readHead()
switch hd.Type {
case 9:
s := r.ReadInt32(0)
baa = make([][]byte, s)
for i := 0; i < int(s); i++ {
baa[i] = r.ReadBytes(0)
}
return baa
default:
return nil
}
}
/*
// ReadAny Read any type via tag, unsupported JceStruct
func (r *JceReader) ReadAny(tag int) interface{} {
if !r.skipToTag(tag) {
@ -312,17 +339,17 @@ func (r *JceReader) ReadAny(tag int) interface{} {
case 1:
return r.readUInt16()
case 2:
return r.readInt32()
return r.readUInt32()
case 3:
return r.readInt64()
return r.readUInt64()
case 4:
return r.readFloat32()
case 5:
return r.readFloat64()
case 6:
return string(r.readBytes(int(r.readByte())))
return utils.B2S(r.readBytes(int(r.readByte())))
case 7:
return string(r.readBytes(int(r.readInt32())))
return utils.B2S(r.readBytes(int(r.readUInt32())))
case 8:
s := r.ReadInt32(0)
m := make(map[interface{}]interface{})
@ -340,12 +367,13 @@ func (r *JceReader) ReadAny(tag int) interface{} {
case 12:
return 0
case 13:
r.readHead()
r.skipHead()
return r.readBytes(int(r.ReadInt32(0)))
default:
return nil
}
}
*/
func (r *JceReader) ReadJceStruct(obj IJceStruct, tag int) {
if !r.skipToTag(tag) {
@ -359,9 +387,63 @@ func (r *JceReader) ReadJceStruct(obj IJceStruct, tag int) {
r.skipToStructEnd()
}
func (r *JceReader) ReadMapStrStr(tag int) map[string]string {
if !r.skipToTag(tag) {
return nil
}
hd, _ := r.readHead()
switch hd.Type {
case 8:
s := r.ReadInt32(0)
m := make(map[string]string, s)
for i := 0; i < int(s); i++ {
m[r.ReadString(0)] = r.ReadString(1)
}
return m
default:
return nil
}
}
func (r *JceReader) ReadMapStrByte(tag int) map[string][]byte {
if !r.skipToTag(tag) {
return nil
}
hd, _ := r.readHead()
switch hd.Type {
case 8:
s := r.ReadInt32(0)
m := make(map[string][]byte, s)
for i := 0; i < int(s); i++ {
m[r.ReadString(0)] = r.ReadBytes(1)
}
return m
default:
return nil
}
}
func (r *JceReader) ReadMapStrMapStrByte(tag int) map[string]map[string][]byte {
if !r.skipToTag(tag) {
return nil
}
hd, _ := r.readHead()
switch hd.Type {
case 8:
s := r.ReadInt32(0)
m := make(map[string]map[string][]byte, s)
for i := 0; i < int(s); i++ {
m[r.ReadString(0)] = r.ReadMapStrByte(1)
}
return m
default:
return nil
}
}
/*
func (r *JceReader) ReadMap(i interface{}, tag int) {
v := reflect.ValueOf(i)
r.readMap(v, tag)
r.readMap(reflect.ValueOf(i), tag)
}
func (r *JceReader) readMap(v reflect.Value, tag int) {
@ -372,7 +454,7 @@ func (r *JceReader) readMap(v reflect.Value, tag int) {
kt := t.Key()
vt := t.Elem()
r.readHead()
r.skipHead()
s := r.ReadInt32(0)
// map with string key or string value is very common.
@ -404,21 +486,240 @@ func (r *JceReader) readMap(v reflect.Value, tag int) {
v.SetMapIndex(kv.Elem(), vv.Elem())
}
}
*/
func (r *JceReader) ReadFileStorageServerInfos(tag int) []FileStorageServerInfo {
if !r.skipToTag(tag) {
return nil
}
hd, _ := r.readHead()
switch hd.Type {
case 9:
s := r.ReadInt32(0)
sl := make([]FileStorageServerInfo, s)
for i := 0; i < int(s); i++ {
r.skipHead()
sl[i].ReadFrom(r)
r.skipToStructEnd()
}
return sl
default:
return nil
}
}
func (r *JceReader) ReadBigDataIPLists(tag int) []BigDataIPList {
if !r.skipToTag(tag) {
return nil
}
hd, _ := r.readHead()
switch hd.Type {
case 9:
s := r.ReadInt32(0)
sl := make([]BigDataIPList, s)
for i := 0; i < int(s); i++ {
r.skipHead()
sl[i].ReadFrom(r)
r.skipToStructEnd()
}
return sl
default:
return nil
}
}
func (r *JceReader) ReadBigDataIPInfos(tag int) []BigDataIPInfo {
if !r.skipToTag(tag) {
return nil
}
hd, _ := r.readHead()
switch hd.Type {
case 9:
s := r.ReadInt32(0)
sl := make([]BigDataIPInfo, s)
for i := 0; i < int(s); i++ {
r.skipHead()
sl[i].ReadFrom(r)
r.skipToStructEnd()
}
return sl
default:
return nil
}
}
func (r *JceReader) ReadOnlineInfos(tag int) []OnlineInfo {
if !r.skipToTag(tag) {
return nil
}
hd, _ := r.readHead()
switch hd.Type {
case 9:
s := r.ReadInt32(0)
sl := make([]OnlineInfo, s)
for i := 0; i < int(s); i++ {
r.skipHead()
sl[i].ReadFrom(r)
r.skipToStructEnd()
}
return sl
default:
return nil
}
}
func (r *JceReader) ReadInstanceInfos(tag int) []InstanceInfo {
if !r.skipToTag(tag) {
return nil
}
hd, _ := r.readHead()
switch hd.Type {
case 9:
s := r.ReadInt32(0)
sl := make([]InstanceInfo, s)
for i := 0; i < int(s); i++ {
r.skipHead()
sl[i].ReadFrom(r)
r.skipToStructEnd()
}
return sl
default:
return nil
}
}
func (r *JceReader) ReadSsoServerInfos(tag int) []SsoServerInfo {
if !r.skipToTag(tag) {
return nil
}
hd, _ := r.readHead()
switch hd.Type {
case 9:
s := r.ReadInt32(0)
sl := make([]SsoServerInfo, s)
for i := 0; i < int(s); i++ {
r.skipHead()
sl[i].ReadFrom(r)
r.skipToStructEnd()
}
return sl
default:
return nil
}
}
func (r *JceReader) ReadFriendInfos(tag int) []FriendInfo {
if !r.skipToTag(tag) {
return nil
}
hd, _ := r.readHead()
switch hd.Type {
case 9:
s := r.ReadInt32(0)
sl := make([]FriendInfo, s)
for i := 0; i < int(s); i++ {
r.skipHead()
sl[i].ReadFrom(r)
r.skipToStructEnd()
}
return sl
default:
return nil
}
}
func (r *JceReader) ReadTroopNumbers(tag int) []TroopNumber {
if !r.skipToTag(tag) {
return nil
}
hd, _ := r.readHead()
switch hd.Type {
case 9:
s := r.ReadInt32(0)
sl := make([]TroopNumber, s)
for i := 0; i < int(s); i++ {
r.skipHead()
sl[i].ReadFrom(r)
r.skipToStructEnd()
}
return sl
default:
return nil
}
}
func (r *JceReader) ReadTroopMemberInfos(tag int) []TroopMemberInfo {
if !r.skipToTag(tag) {
return nil
}
hd, _ := r.readHead()
switch hd.Type {
case 9:
s := r.ReadInt32(0)
sl := make([]TroopMemberInfo, s)
for i := 0; i < int(s); i++ {
r.skipHead()
sl[i].ReadFrom(r)
r.skipToStructEnd()
}
return sl
default:
return nil
}
}
func (r *JceReader) ReadPushMessageInfos(tag int) []PushMessageInfo {
if !r.skipToTag(tag) {
return nil
}
hd, _ := r.readHead()
switch hd.Type {
case 9:
s := r.ReadInt32(0)
sl := make([]PushMessageInfo, s)
for i := 0; i < int(s); i++ {
r.skipHead()
sl[i].ReadFrom(r)
r.skipToStructEnd()
}
return sl
default:
return nil
}
}
func (r *JceReader) ReadSvcDevLoginInfos(tag int) []SvcDevLoginInfo {
if !r.skipToTag(tag) {
return nil
}
hd, _ := r.readHead()
switch hd.Type {
case 9:
s := r.ReadInt32(0)
sl := make([]SvcDevLoginInfo, s)
for i := 0; i < int(s); i++ {
r.skipHead()
sl[i].ReadFrom(r)
r.skipToStructEnd()
}
return sl
default:
return nil
}
}
/*
func (r *JceReader) ReadSlice(i interface{}, tag int) {
r.readSlice(reflect.ValueOf(i), tag)
}
func (r *JceReader) readSlice(v reflect.Value, tag int) {
t := v.Type()
if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Slice {
if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Slice || !r.skipToTag(tag) {
return
}
v = v.Elem()
t = t.Elem()
if !r.skipToTag(tag) {
return
}
hd, _ := r.readHead()
if hd.Type == 9 {
s := r.ReadInt32(0)
@ -432,15 +733,14 @@ func (r *JceReader) readSlice(v reflect.Value, tag int) {
v.Set(sv)
}
if hd.Type == 13 && t.Elem().Kind() == reflect.Uint8 {
r.readHead()
r.skipHead()
arr := r.readBytes(int(r.ReadInt32(0)))
v.SetBytes(arr)
}
}
func (r *JceReader) ReadObject(i interface{}, tag int) {
v := reflect.ValueOf(i)
r.readObject(v, tag)
r.readObject(reflect.ValueOf(i), tag)
}
func (r *JceReader) readObject(v reflect.Value, tag int) {
@ -478,7 +778,7 @@ func (r *JceReader) readObject(v reflect.Value, tag int) {
// other cases
switch o := v.Interface().(type) {
case IJceStruct:
r.readHead()
r.skipHead()
o.ReadFrom(r)
r.skipToStructEnd()
case *float32:
@ -488,3 +788,4 @@ func (r *JceReader) readObject(v reflect.Value, tag int) {
}
}
}
*/

View File

@ -8,15 +8,16 @@ import (
)
func TestJceReader_ReadSlice(t *testing.T) {
s := make([]int64, 50)
s := make([][]byte, 50)
for i := range s {
s[i] = rand.Int63()
b := make([]byte, 64)
_, _ = rand.Read(b)
s[i] = b
}
w := NewJceWriter()
w.WriteObject(s, 1)
r := NewJceReader(w.Bytes())
var result []int64
r.ReadSlice(&result, 1)
result := r.ReadByteArrArr(1)
assert.Equal(t, s, result)
}
@ -35,10 +36,9 @@ func BenchmarkJceReader_ReadSlice(b *testing.B) {
src := w.Bytes()
b.SetBytes(int64(len(src)))
b.StartTimer()
result := make([]BigDataIPInfo, 0)
for i := 0; i < b.N; i++ {
r := NewJceReader(src)
r.ReadSlice(&result, 1)
_ = r.ReadBigDataIPInfos(1)
}
}

View File

@ -555,10 +555,12 @@ func (pkt *RequestPacket) ReadFrom(r *JceReader) {
pkt.IRequestId = r.ReadInt32(4)
pkt.SServantName = r.ReadString(5)
pkt.SFuncName = r.ReadString(6)
r.ReadSlice(&pkt.SBuffer, 7)
pkt.SBuffer = r.ReadBytes(7)
pkt.ITimeout = r.ReadInt32(8)
r.ReadMap(pkt.Context, 9)
r.ReadMap(pkt.Status, 10)
// r.ReadMap(pkt.Context, 9)
pkt.Context = r.ReadMapStrStr(9)
// r.ReadMap(pkt.Status, 10)
pkt.Status = r.ReadMapStrStr(10)
}
func (pkt *RequestDataVersion3) ToBytes() []byte {
@ -568,8 +570,7 @@ func (pkt *RequestDataVersion3) ToBytes() []byte {
}
func (pkt *RequestDataVersion3) ReadFrom(r *JceReader) {
pkt.Map = make(map[string][]byte)
r.ReadMap(pkt.Map, 0)
pkt.Map = r.ReadMapStrByte(0)
}
func (pkt *RequestDataVersion2) ToBytes() []byte {
@ -579,8 +580,7 @@ func (pkt *RequestDataVersion2) ToBytes() []byte {
}
func (pkt *RequestDataVersion2) ReadFrom(r *JceReader) {
pkt.Map = make(map[string]map[string][]byte)
r.ReadMap(pkt.Map, 0)
pkt.Map = r.ReadMapStrMapStrByte(0)
}
func (pkt *SsoServerInfo) ReadFrom(r *JceReader) {
@ -590,22 +590,15 @@ func (pkt *SsoServerInfo) ReadFrom(r *JceReader) {
}
func (pkt *FileStoragePushFSSvcList) ReadFrom(r *JceReader) {
pkt.UploadList = []FileStorageServerInfo{}
pkt.PicDownloadList = []FileStorageServerInfo{}
pkt.GPicDownloadList = []FileStorageServerInfo{}
pkt.QZoneProxyServiceList = []FileStorageServerInfo{}
pkt.UrlEncodeServiceList = []FileStorageServerInfo{}
pkt.UploadList = r.ReadFileStorageServerInfos(0)
pkt.PicDownloadList = r.ReadFileStorageServerInfos(1)
pkt.GPicDownloadList = r.ReadFileStorageServerInfos(2)
pkt.QZoneProxyServiceList = r.ReadFileStorageServerInfos(3)
pkt.UrlEncodeServiceList = r.ReadFileStorageServerInfos(4)
pkt.BigDataChannel = &BigDataChannel{}
pkt.VipEmotionList = []FileStorageServerInfo{}
pkt.C2CPicDownList = []FileStorageServerInfo{}
r.ReadSlice(&pkt.UploadList, 0)
r.ReadSlice(&pkt.PicDownloadList, 1)
r.ReadSlice(&pkt.GPicDownloadList, 2)
r.ReadSlice(&pkt.QZoneProxyServiceList, 3)
r.ReadSlice(&pkt.UrlEncodeServiceList, 4)
pkt.VipEmotionList = r.ReadFileStorageServerInfos(5)
pkt.C2CPicDownList = r.ReadFileStorageServerInfos(7)
r.ReadJceStruct(pkt.BigDataChannel, 5)
r.ReadSlice(&pkt.VipEmotionList, 6)
r.ReadSlice(&pkt.C2CPicDownList, 7)
pkt.PttList = r.ReadBytes(10)
}
@ -615,8 +608,7 @@ func (pkt *FileStorageServerInfo) ReadFrom(r *JceReader) {
}
func (pkt *BigDataChannel) ReadFrom(r *JceReader) {
pkt.IPLists = []BigDataIPList{}
r.ReadSlice(&pkt.IPLists, 0)
pkt.IPLists = r.ReadBigDataIPLists(0)
pkt.SigSession = r.ReadBytes(1)
pkt.KeySession = r.ReadBytes(2)
pkt.SigUin = r.ReadInt64(3)
@ -625,9 +617,8 @@ func (pkt *BigDataChannel) ReadFrom(r *JceReader) {
}
func (pkt *BigDataIPList) ReadFrom(r *JceReader) {
pkt.IPList = []BigDataIPInfo{}
pkt.ServiceType = r.ReadInt64(0)
r.ReadSlice(&pkt.IPList, 1)
pkt.IPList = r.ReadBigDataIPInfos(1)
pkt.FragmentSize = r.ReadInt64(3)
}
@ -692,8 +683,7 @@ func (pkt *FriendInfo) ReadFrom(r *JceReader) {
pkt.Nick = r.ReadString(14)
pkt.Network = r.ReadByte(20)
pkt.NetworkType = r.ReadInt32(24)
pkt.CardID = []byte{}
r.ReadObject(&pkt.CardID, 41)
pkt.CardID = r.ReadBytes(41)
}
func (pkt *TroopListRequest) ToBytes() []byte {
@ -750,8 +740,7 @@ func (pkt *PushMessageInfo) ReadFrom(r *JceReader) {
func (pkt *SvcDevLoginInfo) ReadFrom(r *JceReader) {
pkt.AppId = r.ReadInt64(0)
pkt.Guid = []byte{}
r.ReadSlice(&pkt.Guid, 1)
pkt.Guid = r.ReadBytes(1)
pkt.LoginTime = r.ReadInt64(2)
pkt.LoginPlatform = r.ReadInt64(3)
pkt.LoginLocation = r.ReadString(4)
@ -763,7 +752,6 @@ func (pkt *SvcDevLoginInfo) ReadFrom(r *JceReader) {
}
func (pkt *SvcRespParam) ReadFrom(r *JceReader) {
pkt.OnlineInfos = []OnlineInfo{}
pkt.PCStat = r.ReadInt32(0)
pkt.IsSupportC2CRoamMsg = r.ReadInt32(1)
pkt.IsSupportDataLine = r.ReadInt32(2)
@ -771,7 +759,7 @@ func (pkt *SvcRespParam) ReadFrom(r *JceReader) {
pkt.IsSupportViewPCFile = r.ReadInt32(4)
pkt.PcVersion = r.ReadInt32(5)
pkt.RoamFlag = r.ReadInt64(6)
r.ReadSlice(&pkt.OnlineInfos, 7)
pkt.OnlineInfos = r.ReadOnlineInfos(7)
pkt.PCClientType = r.ReadInt32(8)
}
@ -797,7 +785,6 @@ func (pkt *OnlineInfo) ReadFrom(r *JceReader) {
}
func (pkt *SvcReqMSFLoginNotify) ReadFrom(r *JceReader) {
pkt.InstanceList = []InstanceInfo{}
pkt.AppId = r.ReadInt64(0)
pkt.Status = r.ReadByte(1)
pkt.Tablet = r.ReadByte(2)
@ -806,7 +793,7 @@ func (pkt *SvcReqMSFLoginNotify) ReadFrom(r *JceReader) {
pkt.Info = r.ReadString(5)
pkt.ProductType = r.ReadInt64(6)
pkt.ClientType = r.ReadInt64(7)
r.ReadSlice(&pkt.InstanceList, 8)
pkt.InstanceList = r.ReadInstanceInfos(8)
}
func (pkt *InstanceInfo) ReadFrom(r *JceReader) {

View File

@ -16,11 +16,10 @@ var bufferPool = sync.Pool{
// SelectWriter 从池中取出一个 Writer
func SelectWriter() *Writer {
w := bufferPool.Get().(*Writer)
if w == nil {
return new(Writer)
}
return w
// 因为 bufferPool 定义有 New 函数
// 所以 bufferPool.Get() 永不为 nil
// 不用判空
return bufferPool.Get().(*Writer)
}
// PutWriter 将 Writer 放回池中
@ -103,9 +102,9 @@ var b256kPool = sync.Pool{
// Get256KBytes 获取一个128k大小 []byte
func Get256KBytes() *[]byte {
buf := b256kPool.Get().(*[]byte)
if buf == nil {
return make128kSlicePointer()
}
// 因为 b256kPool 定义有 New 函数
// 所以 b256kPool.Get() 永不为 nil
// 不用判空
if cap(*buf) < size256k {
return make128kSlicePointer()
}

View File

@ -2,11 +2,15 @@ package binary
import (
"encoding/binary"
"math/rand"
_ "unsafe" // required by go:linkname
)
type TEA [4]uint32
// Uint32 returns a lock free uint32 value.
//go:linkname Uint32 runtime.fastrand
func Uint32() uint32
// Encrypt tea 加密
// http://bbs.chinaunix.net/thread-583468-1-1.html
// 感谢xichen大佬对TEA的解释
@ -14,7 +18,9 @@ func (t TEA) Encrypt(src []byte) (dst []byte) {
lens := len(src)
fill := 10 - (lens+1)%8
dst = make([]byte, fill+lens+7)
_, _ = rand.Read(dst[0:fill])
binary.LittleEndian.PutUint32(dst, Uint32())
binary.LittleEndian.PutUint32(dst[4:], Uint32())
binary.LittleEndian.PutUint32(dst[8:], Uint32())
dst[0] = byte(fill-3) | 0xF8 // 存储pad长度
copy(dst[fill:], src)
@ -36,14 +42,13 @@ func (t TEA) Decrypt(data []byte) []byte {
return nil
}
dst := make([]byte, len(data))
var iv1, iv2, holder, tmp uint64
var iv1, iv2, holder uint64
for i := 0; i < len(dst); i += 8 {
block := binary.BigEndian.Uint64(data[i:])
tmp = t.decode(block ^ iv2)
iv2 = tmp
holder = tmp ^ iv1
iv1 = block
binary.BigEndian.PutUint64(dst[i:], holder)
iv1 = binary.BigEndian.Uint64(data[i:])
iv2 ^= iv1
iv2 = t.decode(iv2)
binary.BigEndian.PutUint64(dst[i:], iv2^holder)
holder = iv1
}
return dst[dst[0]&7+3 : len(data)-7]
}

View File

@ -19,6 +19,14 @@ func NewWriterF(f func(writer *Writer)) []byte {
return b
}
// OpenWriterF must call func close
func OpenWriterF(f func(writer *Writer)) (b []byte, close func()) {
w := SelectWriter()
w.WriteByte(0)
f(w)
return w.Bytes(), func() { PutWriter(w) }
}
func (w *Writer) Write(b []byte) {
(*bytes.Buffer)(w).Write(b)
}
@ -69,15 +77,14 @@ func (w *Writer) WriteBool(b bool) {
}
func (w *Writer) EncryptAndWrite(key []byte, data []byte) {
tea := NewTeaCipher(key)
ed := tea.Encrypt(data)
w.Write(ed)
w.Write(NewTeaCipher(key).Encrypt(data))
}
func (w *Writer) WriteIntLvPacket(offset int, f func(writer *Writer)) {
data := NewWriterF(f)
data, close := OpenWriterF(f)
w.WriteUInt32(uint32(len(data) + offset))
w.Write(data)
close()
}
func (w *Writer) WriteUniPacket(commandName string, sessionId, extraData, body []byte) {

View File

@ -49,3 +49,51 @@ func BenchmarkNewWriterF128_5(b *testing.B) {
}
})
}
func BenchmarkOpenWriterF128(b *testing.B) {
test := make([]byte, 128)
rand.Read(test)
b.StartTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, close := OpenWriterF(func(w *Writer) {
w.Write(test)
})
close()
}
})
}
func BenchmarkOpenWriterF128_3(b *testing.B) {
test := make([]byte, 128)
rand.Read(test)
b.StartTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, close := OpenWriterF(func(w *Writer) {
w.Write(test)
w.Write(test)
w.Write(test)
})
close()
}
})
}
func BenchmarkOpenWriterF128_5(b *testing.B) {
test := make([]byte, 128)
rand.Read(test)
b.StartTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, close := OpenWriterF(func(w *Writer) {
w.Write(test)
w.Write(test)
w.Write(test)
w.Write(test)
w.Write(test)
})
close()
}
})
}

View File

@ -169,10 +169,12 @@ func (c *QQClient) buildQRCodeLoginPacket(t106, t16a, t318 []byte) (uint16, []by
w.Write(tlv.T18(16, uint32(c.Uin)))
w.Write(tlv.T1(uint32(c.Uin), c.deviceInfo.IpAddress))
w.Write(binary.NewWriterF(func(w *binary.Writer) {
wb, cl := binary.OpenWriterF(func(w *binary.Writer) {
w.WriteUInt16(0x106)
w.WriteBytesShort(t106)
}))
})
w.Write(wb)
cl()
// w.Write(tlv.T106(uint32(c.Uin), 0, c.version.AppId, c.version.SSOVersion, c.PasswordMd5, true, c.deviceInfo.Guid, c.deviceInfo.TgtgtKey, 0))
w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap))
w.Write(tlv.T100(c.version.SSOVersion, c.version.SubAppId, c.version.MainSigMap))
@ -194,10 +196,12 @@ func (c *QQClient) buildQRCodeLoginPacket(t106, t16a, t318 []byte) (uint16, []by
w.Write(tlv.T145(c.deviceInfo.Guid))
w.Write(tlv.T147(16, []byte(c.version.SortVersionName), c.version.ApkSign))
w.Write(binary.NewWriterF(func(w *binary.Writer) {
wb, cl = binary.OpenWriterF(func(w *binary.Writer) {
w.WriteUInt16(0x16A)
w.WriteBytesShort(t16a)
}))
})
w.Write(wb)
cl()
w.Write(tlv.T154(seq))
w.Write(tlv.T141(c.deviceInfo.SimInfo, c.deviceInfo.APN))
w.Write(tlv.T8(2052))
@ -219,10 +223,12 @@ func (c *QQClient) buildQRCodeLoginPacket(t106, t16a, t318 []byte) (uint16, []by
w.Write(tlv.T516())
w.Write(tlv.T521(8))
// w.Write(tlv.T525(tlv.T536([]byte{0x01, 0x00})))
w.Write(binary.NewWriterF(func(w *binary.Writer) {
wb, cl = binary.OpenWriterF(func(w *binary.Writer) {
w.WriteUInt16(0x318)
w.WriteBytesShort(t318)
}))
})
w.Write(wb)
cl()
})
sso := packets.BuildSsoPacket(seq, c.version.AppId, c.version.SubAppId, "wtlogin.login", c.deviceInfo.IMEI, []byte{}, c.OutGoingPacketSessionId, req, c.ksid)
packet := packets.BuildLoginPacket(c.Uin, 2, make([]byte, 16), sso, []byte{})
@ -306,10 +312,12 @@ func (c *QQClient) buildRequestTgtgtNopicsigPacket() (uint16, []byte) {
w.Write(tlv.T18(16, uint32(c.Uin)))
w.Write(tlv.T1(uint32(c.Uin), c.deviceInfo.IpAddress))
w.Write(binary.NewWriterF(func(w *binary.Writer) {
wb, cl := binary.OpenWriterF(func(w *binary.Writer) {
w.WriteUInt16(0x106)
w.WriteBytesShort(c.sigInfo.encryptedA1)
}))
})
w.Write(wb)
cl()
w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap))
w.Write(tlv.T100(c.version.SSOVersion, 2, c.version.MainSigMap))
w.Write(tlv.T107(0))
@ -989,13 +997,15 @@ func (c *QQClient) buildGroupKickPacket(groupCode, memberUin int64, kickMsg stri
// OidbSvc.0x570_8
func (c *QQClient) buildGroupMutePacket(groupCode, memberUin int64, time uint32) (uint16, []byte) {
seq := c.nextSeq()
payload := c.packOIDBPackage(1392, 8, binary.NewWriterF(func(w *binary.Writer) {
b, cl := binary.OpenWriterF(func(w *binary.Writer) {
w.WriteUInt32(uint32(groupCode))
w.WriteByte(32)
w.WriteUInt16(1)
w.WriteUInt32(uint32(memberUin))
w.WriteUInt32(time)
}))
})
payload := c.packOIDBPackage(1392, 8, b)
cl()
packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0x570_8", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload)
return seq, packet
}
@ -1029,7 +1039,7 @@ func (c *QQClient) buildFriendPokePacket(target int64) (uint16, []byte) {
// OidbSvc.0x55c_1
func (c *QQClient) buildGroupAdminSetPacket(groupCode, member int64, flag bool) (uint16, []byte) {
seq := c.nextSeq()
payload := c.packOIDBPackage(1372, 1, binary.NewWriterF(func(w *binary.Writer) {
b, cl := binary.OpenWriterF(func(w *binary.Writer) {
w.WriteUInt32(uint32(groupCode))
w.WriteUInt32(uint32(member))
w.WriteByte(func() byte {
@ -1038,7 +1048,9 @@ func (c *QQClient) buildGroupAdminSetPacket(groupCode, member int64, flag bool)
}
return 0
}())
}))
})
payload := c.packOIDBPackage(1372, 1, b)
cl()
packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0x55c_1", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload)
return seq, packet
}
@ -1049,10 +1061,12 @@ func (c *QQClient) buildQuitGroupPacket(groupCode int64) (uint16, []byte) {
jw := jce.NewJceWriter()
jw.WriteInt32(2, 0)
jw.WriteInt64(c.Uin, 1)
jw.WriteBytes(binary.NewWriterF(func(w *binary.Writer) {
b, cl := binary.OpenWriterF(func(w *binary.Writer) {
w.WriteUInt32(uint32(c.Uin))
w.WriteUInt32(uint32(groupCode))
}), 2)
})
jw.WriteBytes(b, 2)
cl()
buf := &jce.RequestDataVersion3{Map: map[string][]byte{"GroupMngReq": packUniRequestData(jw.Bytes())}}
pkt := &jce.RequestPacket{
IVersion: 3,

View File

@ -312,8 +312,7 @@ func decodePushReqPacket(c *QQClient, _ *incomingPacketInfo, payload []byte) (in
switch t {
case 1:
ssoPkt := jce.NewJceReader(jceBuf)
servers := []jce.SsoServerInfo{}
ssoPkt.ReadSlice(&servers, 1)
servers := ssoPkt.ReadSsoServerInfos(1)
if len(servers) > 0 {
var adds []*net.TCPAddr
for _, s := range servers {
@ -433,8 +432,7 @@ func decodeSummaryCardResponse(_ *QQClient, _ *incomingPacketInfo, payload []byt
Uin: rsp.ReadInt64(23),
LoginDays: rsp.ReadInt64(36),
}
services := [][]byte{}
rsp.ReadSlice(&services, 46)
services := rsp.ReadByteArrArr(46)
readService := func(buf []byte) (*profilecard.BusiComm, []byte) {
r := binary.NewReader(buf)
r.ReadByte()
@ -467,8 +465,7 @@ func decodeFriendGroupListResponse(_ *QQClient, _ *incomingPacketInfo, payload [
data.ReadFrom(jce.NewJceReader(request.SBuffer))
r := jce.NewJceReader(data.Map["FLRESP"][1:])
totalFriendCount := r.ReadInt16(5)
friends := make([]jce.FriendInfo, 0)
r.ReadSlice(&friends, 7)
friends := r.ReadFriendInfos(7)
l := make([]*FriendInfo, 0, len(friends))
for _, f := range friends {
l = append(l, &FriendInfo{
@ -505,10 +502,8 @@ func decodeGroupListResponse(c *QQClient, _ *incomingPacketInfo, payload []byte)
data := &jce.RequestDataVersion3{}
data.ReadFrom(jce.NewJceReader(request.SBuffer))
r := jce.NewJceReader(data.Map["GetTroopListRespV2"][1:])
vecCookie := []byte{}
groups := []jce.TroopNumber{}
r.ReadSlice(&vecCookie, 4)
r.ReadSlice(&groups, 5)
vecCookie := r.ReadBytes(4)
groups := r.ReadTroopNumbers(5)
l := make([]*GroupInfo, 0, len(groups))
for _, g := range groups {
l = append(l, &GroupInfo{
@ -539,8 +534,7 @@ func decodeGroupMemberListResponse(_ *QQClient, _ *incomingPacketInfo, payload [
data := &jce.RequestDataVersion3{}
data.ReadFrom(jce.NewJceReader(request.SBuffer))
r := jce.NewJceReader(data.Map["GTMLRESP"][1:])
members := make([]jce.TroopMemberInfo, 0)
r.ReadSlice(&members, 3)
members := r.ReadTroopMemberInfos(3)
next := r.ReadInt64(4)
l := make([]*GroupMemberInfo, 0, len(members))
for _, m := range members {

View File

@ -459,12 +459,15 @@ func getSSOAddress() ([]*net.TCPAddr, error) {
SFuncName: "HttpServerListReq",
SBuffer: buf.ToBytes(),
}
tea := binary.NewTeaCipher(key)
rsp, err := utils.HttpPostBytes("https://configsvr.msf.3g.qq.com/configsvr/serverlist.jsp", tea.Encrypt(binary.NewWriterF(func(w *binary.Writer) {
b, cl := binary.OpenWriterF(func(w *binary.Writer) {
w.WriteIntLvPacket(0, func(w *binary.Writer) {
w.Write(pkt.ToBytes())
})
})))
})
tea := binary.NewTeaCipher(key)
encpkt := tea.Encrypt(b)
cl()
rsp, err := utils.HttpPostBytes("https://configsvr.msf.3g.qq.com/configsvr/serverlist.jsp", encpkt)
if err != nil {
return nil, errors.Wrap(err, "unable to fetch server list")
}
@ -473,8 +476,7 @@ func getSSOAddress() ([]*net.TCPAddr, error) {
rspPkt.ReadFrom(jce.NewJceReader(tea.Decrypt(rsp)[4:]))
data.ReadFrom(jce.NewJceReader(rspPkt.SBuffer))
reader := jce.NewJceReader(data.Map["HttpServerListRes"][1:])
servers := []jce.SsoServerInfo{}
reader.ReadSlice(&servers, 2)
servers := reader.ReadSsoServerInfos(2)
adds := make([]*net.TCPAddr, 0, len(servers))
for _, s := range servers {
if strings.Contains(s.Server, "com") {

View File

@ -200,7 +200,8 @@ func decodeGroupSearchResponse(_ *QQClient, _ *incomingPacketInfo, payload []byt
}
rsp := data.Map["RespSearch"]["SummaryCard.RespSearch"][1:]
r := jce.NewJceReader(rsp)
rspService := r.ReadAny(2).([]interface{})[0].([]byte)
// rspService := r.ReadAny(2).([]interface{})[0].([]byte)
rspService := r.ReadByteArrArr(2)[0]
sr := binary.NewReader(rspService)
sr.ReadByte()
ld1 := sr.ReadInt32()

View File

@ -28,9 +28,8 @@ func decodeOnlinePushReqPacket(c *QQClient, info *incomingPacketInfo, payload []
data := &jce.RequestDataVersion2{}
data.ReadFrom(jce.NewJceReader(request.SBuffer))
jr := jce.NewJceReader(data.Map["req"]["OnlinePushPack.SvcReqPushMsg"][1:])
msgInfos := []jce.PushMessageInfo{}
uin := jr.ReadInt64(0)
jr.ReadSlice(&msgInfos, 2)
msgInfos := jr.ReadPushMessageInfos(2)
_ = c.sendPacket(c.buildDeleteOnlinePushPacket(uin, 0, nil, info.SequenceId, msgInfos))
for _, m := range msgInfos {
k := fmt.Sprintf("%v%v%v", m.MsgSeq, m.MsgTime, m.MsgUid)

View File

@ -302,16 +302,15 @@ func decodeDevListResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (
data := &jce.RequestDataVersion2{}
data.ReadFrom(jce.NewJceReader(request.SBuffer))
rsp := jce.NewJceReader(data.Map["SvcRspGetDevLoginInfo"]["QQService.SvcRspGetDevLoginInfo"][1:])
d := []jce.SvcDevLoginInfo{}
rsp.ReadSlice(&d, 4)
d := rsp.ReadSvcDevLoginInfos(4)
if len(d) > 0 {
return d, nil
}
rsp.ReadSlice(&d, 5)
d = rsp.ReadSvcDevLoginInfos(5)
if len(d) > 0 {
return d, nil
}
rsp.ReadSlice(&d, 6)
d = rsp.ReadSvcDevLoginInfos(6)
if len(d) > 0 {
return d, nil
}