diff --git a/binary/jce/gen/structs_parser.go b/binary/jce/gen/structs_parser.go new file mode 100644 index 00000000..9d941bd6 --- /dev/null +++ b/binary/jce/gen/structs_parser.go @@ -0,0 +1,92 @@ +package main + +import ( + "bufio" + "bytes" + "flag" + "fmt" + "os" + "os/exec" + "strings" + + _ "embed" +) + +//go:embed structs_parser_tmp.go +var tmpmain string + +func main() { + f := flag.String("f", "structs_tobytes.go", "output file.") + i := flag.String("i", "structs.go", "input file.") + flag.Parse() + fmt.Println("gen runs on arg", *f, *i) + fmt.Println("len of tmp main is", len(tmpmain)) + tmp, err := os.Create("tmp.go") + if err != nil { + panic(err) + } + inp, err := os.Open(*i) + if err != nil { + panic(err) + } + var structs []string + var isinhead = true + var isinfill = false + var isnexttemplate = false + s := bufio.NewScanner(bytes.NewReader([]byte(tmpmain))) + for s.Scan() { + line := s.Text() + if isinhead { + if strings.Contains(line, "Main_") { + line = "func main() {" + isnexttemplate = true + isinhead = false + scanner := bufio.NewScanner(inp) + start := false + for scanner.Scan() { + t := scanner.Text() + if t == "type (" { + start = true + } + if start { + tmp.WriteString(t + "\n") + if t == ")" { + break + } + if strings.Contains(t, " struct {") { + structs = append(structs, strings.Trim(t[:len(t)-9], "\t")) + } + } + } + inp.Close() + } + tmp.WriteString(line + "\n") + } else if isinfill { + for _, s := range structs { + fmt.Fprintf(tmp, "\tWriteJceStruct(w, &%s{})\n", s) + } + isinfill = false + tmp.WriteString("// structs_parser: fill area\n") + tmp.WriteString(line + "\n") + } else { + if strings.Contains(line, "// structs_parser: fill area") { + isinfill = true + tmp.WriteString("// structs_parser: fill area\n") + } else { + if isnexttemplate { + fmt.Fprintf(tmp, line+"\n", *f) + isnexttemplate = false + } else { + tmp.WriteString(line + "\n") + } + } + } + } + tmp.Close() + c := exec.Command("go", "run", "tmp.go") + err = c.Run() + if err != nil { + panic(err) + } + os.Remove("tmp.go") +} diff --git a/binary/jce/gen/structs_parser_tmp.go b/binary/jce/gen/structs_parser_tmp.go new file mode 100644 index 00000000..26ccd631 --- /dev/null +++ b/binary/jce/gen/structs_parser_tmp.go @@ -0,0 +1,149 @@ +package main + +import ( + "fmt" + "io" + "os" + "reflect" + "strconv" + "strings" + "sync" +) + +type IJceStruct interface{} + +const head = "// Code generated by structs_parser; DO NOT EDIT.\npackage jce\n" + +func Main_() { + w, err := os.Create("%s") + if err != nil { + panic(err) + } + w.WriteString(head) + // structs_parser: fill area + err = w.Close() + if err != nil { + panic(err) + } +} + +func writeObject(w io.Writer, v reflect.Value, tag byte, name string) { + k := v.Kind() + if k == reflect.Map { + switch v.Interface().(type) { + case map[string]string: + w.Write([]byte(fmt.Sprintf("\tw.writeMapStrStr(pkt.%s, %d)\n", name, tag))) + case map[string][]byte: + w.Write([]byte(fmt.Sprintf("\tw.writeMapStrBytes(pkt.%s, %d)\n", name, tag))) + case map[string]map[string][]byte: + w.Write([]byte(fmt.Sprintf("\tw.writeMapStrMapStrBytes(pkt.%s, %d)\n", name, tag))) + default: + w.Write([]byte(fmt.Sprintf("\tw.writeMap(pkt.%s, %d)\n", name, tag))) + } + return + } + if k == reflect.Slice { + switch v.Interface().(type) { + case []byte: + w.Write([]byte(fmt.Sprintf("\tw.WriteBytes(pkt.%s, %d)\n", name, tag))) + case []int64: + w.Write([]byte(fmt.Sprintf("\tw.WriteInt64Slice(pkt.%s, %d)\n", name, tag))) + case [][]byte: + w.Write([]byte(fmt.Sprintf("\tw.WriteBytesSlice(pkt.%s, %d)\n", name, tag))) + default: + writeJceStructSlice(w, tag, name) + } + return + } + switch k { + case reflect.Uint8, reflect.Int8: + w.Write([]byte(fmt.Sprintf("\tw.WriteByte(pkt.%s, %d)\n", name, tag))) + case reflect.Uint16, reflect.Int16: + w.Write([]byte(fmt.Sprintf("\tw.WriteInt16(pkt.%s, %d)\n", name, tag))) + case reflect.Uint32, reflect.Int32: + w.Write([]byte(fmt.Sprintf("\tw.WriteInt32(pkt.%s, %d)\n", name, tag))) + case reflect.Uint64, reflect.Int64: + w.Write([]byte(fmt.Sprintf("\tw.WriteInt64(pkt.%s, %d)\n", name, tag))) + case reflect.Int, reflect.Uint: + w.Write([]byte(fmt.Sprintf("\tw.WriteInt64(int64(pkt.%s), %d)\n", name, tag))) + case reflect.String: + w.Write([]byte(fmt.Sprintf("\tw.WriteString(pkt.%s, %d)\n", name, tag))) + default: + switch v.Interface().(type) { + case float32: + w.Write([]byte(fmt.Sprintf("\tw.WriteFloat32(pkt.%s, %d)\n", name, tag))) + case float64: + w.Write([]byte(fmt.Sprintf("\tw.WriteFloat64(pkt.%s, %d)\n", name, tag))) + case IJceStruct: + w.Write([]byte(fmt.Sprintf("\tw.writeHead(10, %d)\n", tag))) + w.Write([]byte(fmt.Sprintf("\tw.buf.Write(pkt.%s.ToBytes())\n", name))) + w.Write([]byte("\tw.writeHead(11, 0)\n")) + } + } +} + +type decoder struct { + index int + id int + name string +} + +var decoderCache = sync.Map{} + +// writeJceStructRaw 写入 Jce 结构体 +func writeJceStructRaw(w io.Writer, s interface{}) { + t := reflect.TypeOf(s) + if t.Kind() != reflect.Ptr { + return + } + t = t.Elem() + v := reflect.ValueOf(s).Elem() + var jceDec []decoder + dec, ok := decoderCache.Load(t) + if ok { // 从缓存中加载 + jceDec = dec.([]decoder) + } else { // 初次反射 + jceDec = make([]decoder, 0, t.NumField()) + for i := 0; i < t.NumField(); i++ { + field := t.Field(i) + strId := field.Tag.Get("jceId") + if strId == "" { + continue + } + id, err := strconv.Atoi(strId) + if err != nil { + continue + } + jceDec = append(jceDec, decoder{ + index: i, + id: id, + name: field.Name, + }) + } + decoderCache.Store(t, jceDec) // 存入缓存 + } + for _, dec := range jceDec { + obj := v.Field(dec.index) + writeObject(w, obj, byte(dec.id), dec.name) + } +} + +func writeJceStructSlice(w io.Writer, tag byte, name string) { + w.Write([]byte(fmt.Sprintf("\tw.writeHead(9, %d)\n", tag))) + w.Write([]byte(fmt.Sprintf("\tif len(pkt.%s) == 0 {\n", name))) + w.Write([]byte("\t\tw.writeHead(12, 0) // w.WriteInt32(0, 0)\n")) + w.Write([]byte("\t} else {\n")) + w.Write([]byte(fmt.Sprintf("\t\tw.WriteInt32(int32(len(pkt.%s)), 0)\n", name))) + w.Write([]byte(fmt.Sprintf("\t\tfor _, i := range pkt.%s {\n", name))) + w.Write([]byte("\t\t\tw.buf.Write(i.ToBytes())\n")) + w.Write([]byte("\t\t}\n")) + w.Write([]byte("\t}\n")) +} + +func WriteJceStruct(w io.Writer, s IJceStruct) { + w.Write([]byte(fmt.Sprintf("\nfunc (pkt %s) ToBytes() []byte {\n", strings.ReplaceAll(reflect.TypeOf(s).String(), "main.", "")))) + w.Write([]byte("\tw := NewJceWriter()\n")) + writeJceStructRaw(w, s) + w.Write([]byte("\treturn w.Bytes()\n")) + w.Write([]byte("}\n")) +} diff --git a/binary/jce/reader_test.go b/binary/jce/reader_test.go index 7caec125..883897fd 100644 --- a/binary/jce/reader_test.go +++ b/binary/jce/reader_test.go @@ -2,7 +2,11 @@ package jce import ( "math/rand" + "reflect" + "strconv" + "sync" "testing" + "unsafe" "github.com/stretchr/testify/assert" ) @@ -15,7 +19,7 @@ func TestJceReader_ReadSlice(t *testing.T) { s[i] = b } w := NewJceWriter() - w.WriteObject(s, 1) + w.WriteBytesSlice(s, 1) r := NewJceReader(w.Bytes()) result := r.ReadByteArrArr(1) assert.Equal(t, s, result) @@ -64,7 +68,7 @@ var req = RequestDataVersion2{ func TestRequestDataVersion2_ReadFrom(t *testing.T) { // todo(wdv): fuzz test w := NewJceWriter() - w.WriteObject(req.Map, 0) + w.writeMapStrMapStrBytes(req.Map, 0) src := w.Bytes() result := RequestDataVersion2{} result.ReadFrom(NewJceReader(src)) @@ -73,7 +77,7 @@ func TestRequestDataVersion2_ReadFrom(t *testing.T) { func BenchmarkRequestDataVersion2_ReadFrom(b *testing.B) { w := NewJceWriter() - w.WriteObject(req.Map, 0) + w.writeMapStrMapStrBytes(req.Map, 0) src := w.Bytes() b.SetBytes(int64(len(src))) result := &RequestDataVersion2{} @@ -93,3 +97,210 @@ func TestJceReader_ReadBytes(t *testing.T) { assert.Equal(t, b, rb) } + +func (w *JceWriter) WriteObject(i interface{}, tag byte) { + t := reflect.TypeOf(i) + if t.Kind() == reflect.Map { + w.WriteMap(i, tag) + return + } + if t.Kind() == reflect.Slice { + if b, ok := i.([]byte); ok { + w.WriteBytes(b, tag) + return + } + w.WriteSlice(i, tag) + return + } + switch o := i.(type) { + case byte: + w.WriteByte(o, tag) + case bool: + w.WriteBool(o, tag) + case int16: + w.WriteInt16(o, tag) + case int32: + w.WriteInt32(o, tag) + case int64: + w.WriteInt64(o, tag) + case float32: + w.WriteFloat32(o, tag) + case float64: + w.WriteFloat64(o, tag) + case string: + w.WriteString(o, tag) + case IJceStruct: + w.WriteJceStruct(o, tag) + } +} + +func (w *JceWriter) writeObject(v reflect.Value, tag byte) { + k := v.Kind() + if k == reflect.Map { + switch o := v.Interface().(type) { + case map[string]string: + w.writeMapStrStr(o, tag) + case map[string][]byte: + w.writeMapStrBytes(o, tag) + case map[string]map[string][]byte: + w.writeMapStrMapStrBytes(o, tag) + default: + w.writeMap(v, tag) + } + return + } + if k == reflect.Slice { + switch o := v.Interface().(type) { + case []byte: + w.WriteBytes(o, tag) + case []IJceStruct: + w.WriteJceStructSlice(o, tag) + default: + w.writeSlice(v, tag) + } + return + } + switch k { + case reflect.Uint8, reflect.Int8: + w.WriteByte(*(*byte)(pointerOf(v)), tag) + case reflect.Uint16, reflect.Int16: + w.WriteInt16(*(*int16)(pointerOf(v)), tag) + case reflect.Uint32, reflect.Int32: + w.WriteInt32(*(*int32)(pointerOf(v)), tag) + case reflect.Uint64, reflect.Int64: + w.WriteInt64(*(*int64)(pointerOf(v)), tag) + case reflect.String: + w.WriteString(v.String(), tag) + default: + switch o := v.Interface().(type) { + case IJceStruct: + w.WriteJceStruct(o, tag) + case float32: + w.WriteFloat32(o, tag) + case float64: + w.WriteFloat64(o, tag) + } + } +} + +type decoder struct { + index int + id int +} + +var decoderCache = sync.Map{} + +// WriteJceStructRaw 写入 Jce 结构体 +func (w *JceWriter) WriteJceStructRaw(s interface{}) { + t := reflect.TypeOf(s) + if t.Kind() != reflect.Ptr { + return + } + t = t.Elem() + v := reflect.ValueOf(s).Elem() + var jceDec []decoder + dec, ok := decoderCache.Load(t) + if ok { // 从缓存中加载 + jceDec = dec.([]decoder) + } else { // 初次反射 + jceDec = make([]decoder, 0, t.NumField()) + for i := 0; i < t.NumField(); i++ { + field := t.Field(i) + strId := field.Tag.Get("jceId") + if strId == "" { + continue + } + id, err := strconv.Atoi(strId) + if err != nil { + continue + } + jceDec = append(jceDec, decoder{ + index: i, + id: id, + }) + } + decoderCache.Store(t, jceDec) // 存入缓存 + } + for _, dec := range jceDec { + obj := v.Field(dec.index) + w.writeObject(obj, byte(dec.id)) + } +} + +func (w *JceWriter) WriteJceStruct(s IJceStruct, tag byte) { + w.writeHead(10, tag) + w.WriteJceStructRaw(s) + w.writeHead(11, 0) +} + +func (w *JceWriter) WriteSlice(i interface{}, tag byte) { + va := reflect.ValueOf(i) + if va.Kind() != reflect.Slice { + panic("JceWriter.WriteSlice: not a slice") + } + w.writeSlice(va, tag) +} + +func (w *JceWriter) writeSlice(slice reflect.Value, tag byte) { + if slice.Kind() != reflect.Slice { + return + } + w.writeHead(9, tag) + if slice.Len() == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + return + } + w.WriteInt32(int32(slice.Len()), 0) + for i := 0; i < slice.Len(); i++ { + v := slice.Index(i) + w.writeObject(v, 0) + } +} + +func (w *JceWriter) WriteJceStructSlice(l []IJceStruct, tag byte) { + w.writeHead(9, tag) + if len(l) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + return + } + w.WriteInt32(int32(len(l)), 0) + for _, v := range l { + w.WriteJceStruct(v, 0) + } +} + +func (w *JceWriter) WriteMap(m interface{}, tag byte) { + va := reflect.ValueOf(m) + if va.Kind() != reflect.Map { + panic("JceWriter.WriteMap: not a map") + } + w.writeMap(va, tag) +} + +func (w *JceWriter) writeMap(m reflect.Value, tag byte) { + if m.IsNil() { + w.writeHead(8, tag) + w.writeHead(12, 0) // w.WriteInt32(0, 0) + return + } + if m.Kind() != reflect.Map { + return + } + w.writeHead(8, tag) + w.WriteInt32(int32(m.Len()), 0) + iter := m.MapRange() + for iter.Next() { + w.writeObject(iter.Key(), 0) + w.writeObject(iter.Value(), 1) + } +} + +type value struct { + typ unsafe.Pointer + data unsafe.Pointer + flag uintptr +} + +func pointerOf(v reflect.Value) unsafe.Pointer { + return (*value)(unsafe.Pointer(&v)).data +} diff --git a/binary/jce/reflectx.go b/binary/jce/reflectx.go deleted file mode 100644 index 3adf69f4..00000000 --- a/binary/jce/reflectx.go +++ /dev/null @@ -1,16 +0,0 @@ -package jce - -import ( - "reflect" - "unsafe" -) - -type value struct { - typ unsafe.Pointer - data unsafe.Pointer - flag uintptr -} - -func pointerOf(v reflect.Value) unsafe.Pointer { - return (*value)(unsafe.Pointer(&v)).data -} diff --git a/binary/jce/structs.go b/binary/jce/structs.go index 1cb644e2..f30e9a63 100644 --- a/binary/jce/structs.go +++ b/binary/jce/structs.go @@ -1,10 +1,11 @@ package jce type IJceStruct interface { - // ToBytes() []byte + ToBytes() []byte ReadFrom(*JceReader) } +//go:generate go run gen/structs_parser.go -f structs_tobytes.go -i structs.go type ( RequestPacket struct { IVersion int16 `jceId:"1"` @@ -539,12 +540,6 @@ type ( } ) -func (pkt *RequestPacket) ToBytes() []byte { - w := NewJceWriter() - w.WriteJceStructRaw(pkt) - return w.Bytes() -} - func (pkt *RequestPacket) ReadFrom(r *JceReader) { pkt.IVersion = r.ReadInt16(1) pkt.CPacketType = r.ReadByte(2) @@ -560,22 +555,10 @@ func (pkt *RequestPacket) ReadFrom(r *JceReader) { pkt.Status = r.ReadMapStrStr(10) } -func (pkt *RequestDataVersion3) ToBytes() []byte { - w := NewJceWriter() - w.WriteJceStructRaw(pkt) - return w.Bytes() -} - func (pkt *RequestDataVersion3) ReadFrom(r *JceReader) { pkt.Map = r.ReadMapStrByte(0) } -func (pkt *RequestDataVersion2) ToBytes() []byte { - w := NewJceWriter() - w.WriteJceStructRaw(pkt) - return w.Bytes() -} - func (pkt *RequestDataVersion2) ReadFrom(r *JceReader) { pkt.Map = r.ReadMapStrMapStrByte(0) } @@ -625,12 +608,6 @@ func (pkt *BigDataIPInfo) ReadFrom(r *JceReader) { pkt.Port = r.ReadInt64(2) } -func (pkt *SvcReqRegister) ToBytes() []byte { - w := NewJceWriter() - w.WriteJceStructRaw(pkt) - return w.Bytes() -} - func (pkt *SvcRespRegister) ReadFrom(r *JceReader) { pkt.Uin = r.ReadInt64(0) pkt.Bid = r.ReadInt64(1) @@ -652,24 +629,6 @@ func (pkt *SvcRespRegister) ReadFrom(r *JceReader) { pkt.ExtOnlineStatus = r.ReadInt64(17) } -func (pkt *FriendListRequest) ToBytes() []byte { - w := NewJceWriter() - w.WriteJceStructRaw(pkt) - return w.Bytes() -} - -func (pkt *SummaryCardReq) ToBytes() []byte { - w := NewJceWriter() - w.WriteJceStructRaw(pkt) - return w.Bytes() -} - -func (pkt *SummaryCardReqSearch) ToBytes() []byte { - w := NewJceWriter() - w.WriteJceStructRaw(pkt) - return w.Bytes() -} - func (pkt *FriendInfo) ReadFrom(r *JceReader) { pkt.FriendUin = r.ReadInt64(0) pkt.GroupId = r.ReadByte(1) @@ -683,12 +642,6 @@ func (pkt *FriendInfo) ReadFrom(r *JceReader) { pkt.CardID = r.ReadBytes(41) } -func (pkt *TroopListRequest) ToBytes() []byte { - w := NewJceWriter() - w.WriteJceStructRaw(pkt) - return w.Bytes() -} - func (pkt *TroopNumber) ReadFrom(r *JceReader) { pkt.GroupUin = r.ReadInt64(0) pkt.GroupCode = r.ReadInt64(1) @@ -699,12 +652,6 @@ func (pkt *TroopNumber) ReadFrom(r *JceReader) { pkt.MaxGroupMemberNum = r.ReadInt64(29) } -func (pkt *TroopMemberListRequest) ToBytes() []byte { - w := NewJceWriter() - w.WriteJceStructRaw(pkt) - return w.Bytes() -} - func (pkt *TroopMemberInfo) ReadFrom(r *JceReader) { pkt.MemberUin = r.ReadInt64(0) pkt.FaceId = r.ReadInt16(1) @@ -800,33 +747,3 @@ func (pkt *InstanceInfo) ReadFrom(r *JceReader) { pkt.ProductType = r.ReadInt64(3) pkt.ClientType = r.ReadInt64(4) } - -func (pkt *SvcRespPushMsg) ToBytes() []byte { - w := NewJceWriter() - w.WriteJceStructRaw(pkt) - return w.Bytes() -} - -func (pkt *ModifyGroupCardRequest) ToBytes() []byte { - w := NewJceWriter() - w.WriteJceStructRaw(pkt) - return w.Bytes() -} - -func (pkt *SvcReqGetDevLoginInfo) ToBytes() []byte { - w := NewJceWriter() - w.WriteJceStructRaw(pkt) - return w.Bytes() -} - -func (pkt *SvcReqRegisterNew) ToBytes() []byte { - w := NewJceWriter() - w.WriteJceStructRaw(pkt) - return w.Bytes() -} - -func (pkt *DelFriendReq) ToBytes() []byte { - w := NewJceWriter() - w.WriteJceStructRaw(pkt) - return w.Bytes() -} diff --git a/binary/jce/structs_tobytes.go b/binary/jce/structs_tobytes.go new file mode 100644 index 00000000..1e042498 --- /dev/null +++ b/binary/jce/structs_tobytes.go @@ -0,0 +1,688 @@ +// Code generated by structs_parser; DO NOT EDIT. +package jce + +func (pkt *RequestPacket) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt16(pkt.IVersion, 1) + w.WriteByte(pkt.CPacketType, 2) + w.WriteInt32(pkt.IMessageType, 3) + w.WriteInt32(pkt.IRequestId, 4) + w.WriteString(pkt.SServantName, 5) + w.WriteString(pkt.SFuncName, 6) + w.WriteBytes(pkt.SBuffer, 7) + w.WriteInt32(pkt.ITimeout, 8) + w.writeMapStrStr(pkt.Context, 9) + w.writeMapStrStr(pkt.Status, 10) + return w.Bytes() +} + +func (pkt *RequestDataVersion3) ToBytes() []byte { + w := NewJceWriter() + w.writeMapStrBytes(pkt.Map, 0) + return w.Bytes() +} + +func (pkt *RequestDataVersion2) ToBytes() []byte { + w := NewJceWriter() + w.writeMapStrMapStrBytes(pkt.Map, 0) + return w.Bytes() +} + +func (pkt *SsoServerInfo) ToBytes() []byte { + w := NewJceWriter() + w.WriteString(pkt.Server, 1) + w.WriteInt32(pkt.Port, 2) + w.WriteString(pkt.Location, 8) + return w.Bytes() +} + +func (pkt *FileStoragePushFSSvcList) ToBytes() []byte { + w := NewJceWriter() + w.writeHead(9, 0) + if len(pkt.UploadList) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.UploadList)), 0) + for _, i := range pkt.UploadList { + w.buf.Write(i.ToBytes()) + } + } + w.writeHead(9, 1) + if len(pkt.PicDownloadList) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.PicDownloadList)), 0) + for _, i := range pkt.PicDownloadList { + w.buf.Write(i.ToBytes()) + } + } + w.writeHead(9, 2) + if len(pkt.GPicDownloadList) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.GPicDownloadList)), 0) + for _, i := range pkt.GPicDownloadList { + w.buf.Write(i.ToBytes()) + } + } + w.writeHead(9, 3) + if len(pkt.QZoneProxyServiceList) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.QZoneProxyServiceList)), 0) + for _, i := range pkt.QZoneProxyServiceList { + w.buf.Write(i.ToBytes()) + } + } + w.writeHead(9, 4) + if len(pkt.UrlEncodeServiceList) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.UrlEncodeServiceList)), 0) + for _, i := range pkt.UrlEncodeServiceList { + w.buf.Write(i.ToBytes()) + } + } + w.writeHead(10, 5) + w.buf.Write(pkt.BigDataChannel.ToBytes()) + w.writeHead(11, 0) + w.writeHead(9, 6) + if len(pkt.VipEmotionList) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.VipEmotionList)), 0) + for _, i := range pkt.VipEmotionList { + w.buf.Write(i.ToBytes()) + } + } + w.writeHead(9, 7) + if len(pkt.C2CPicDownList) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.C2CPicDownList)), 0) + for _, i := range pkt.C2CPicDownList { + w.buf.Write(i.ToBytes()) + } + } + w.WriteBytes(pkt.PttList, 10) + return w.Bytes() +} + +func (pkt *FileStorageServerInfo) ToBytes() []byte { + w := NewJceWriter() + w.WriteString(pkt.Server, 1) + w.WriteInt32(pkt.Port, 2) + return w.Bytes() +} + +func (pkt *BigDataChannel) ToBytes() []byte { + w := NewJceWriter() + w.writeHead(9, 0) + if len(pkt.IPLists) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.IPLists)), 0) + for _, i := range pkt.IPLists { + w.buf.Write(i.ToBytes()) + } + } + w.WriteBytes(pkt.SigSession, 1) + w.WriteBytes(pkt.KeySession, 2) + w.WriteInt64(pkt.SigUin, 3) + w.WriteInt32(pkt.ConnectFlag, 4) + w.WriteBytes(pkt.PbBuf, 5) + return w.Bytes() +} + +func (pkt *BigDataIPList) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.ServiceType, 0) + w.writeHead(9, 1) + if len(pkt.IPList) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.IPList)), 0) + for _, i := range pkt.IPList { + w.buf.Write(i.ToBytes()) + } + } + w.WriteInt64(pkt.FragmentSize, 3) + return w.Bytes() +} + +func (pkt *BigDataIPInfo) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.Type, 0) + w.WriteString(pkt.Server, 1) + w.WriteInt64(pkt.Port, 2) + return w.Bytes() +} + +func (pkt *SvcReqRegister) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.Uin, 0) + w.WriteInt64(pkt.Bid, 1) + w.WriteByte(pkt.ConnType, 2) + w.WriteString(pkt.Other, 3) + w.WriteInt32(pkt.Status, 4) + w.WriteByte(pkt.OnlinePush, 5) + w.WriteByte(pkt.IsOnline, 6) + w.WriteByte(pkt.IsShowOnline, 7) + w.WriteByte(pkt.KickPC, 8) + w.WriteByte(pkt.KickWeak, 9) + w.WriteInt64(pkt.Timestamp, 10) + w.WriteInt64(pkt.IOSVersion, 11) + w.WriteByte(pkt.NetType, 12) + w.WriteString(pkt.BuildVer, 13) + w.WriteByte(pkt.RegType, 14) + w.WriteBytes(pkt.DevParam, 15) + w.WriteBytes(pkt.Guid, 16) + w.WriteInt32(pkt.LocaleId, 17) + w.WriteByte(pkt.SilentPush, 18) + w.WriteString(pkt.DevName, 19) + w.WriteString(pkt.DevType, 20) + w.WriteString(pkt.OSVer, 21) + w.WriteByte(pkt.OpenPush, 22) + w.WriteInt64(pkt.LargeSeq, 23) + w.WriteInt64(pkt.LastWatchStartTime, 24) + w.WriteInt64(pkt.OldSSOIp, 26) + w.WriteInt64(pkt.NewSSOIp, 27) + w.WriteString(pkt.ChannelNo, 28) + w.WriteInt64(pkt.CPID, 29) + w.WriteString(pkt.VendorName, 30) + w.WriteString(pkt.VendorOSName, 31) + w.WriteString(pkt.IOSIdfa, 32) + w.WriteBytes(pkt.B769, 33) + w.WriteByte(pkt.IsSetStatus, 34) + w.WriteBytes(pkt.ServerBuf, 35) + w.WriteByte(pkt.SetMute, 36) + w.WriteInt64(pkt.ExtOnlineStatus, 38) + w.WriteInt32(pkt.BatteryStatus, 39) + return w.Bytes() +} + +func (pkt *SvcRespRegister) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.Uin, 0) + w.WriteInt64(pkt.Bid, 1) + w.WriteByte(pkt.ReplyCode, 2) + w.WriteString(pkt.Result, 3) + w.WriteInt64(pkt.ServerTime, 4) + w.WriteByte(pkt.LogQQ, 5) + w.WriteByte(pkt.NeedKik, 6) + w.WriteByte(pkt.UpdateFlag, 7) + w.WriteInt64(pkt.Timestamp, 8) + w.WriteByte(pkt.CrashFlag, 9) + w.WriteString(pkt.ClientIp, 10) + w.WriteInt32(pkt.ClientPort, 11) + w.WriteInt32(pkt.HelloInterval, 12) + w.WriteInt32(pkt.LargeSeq, 13) + w.WriteByte(pkt.LargeSeqUpdate, 14) + w.WriteBytes(pkt.D769RspBody, 15) + w.WriteInt32(pkt.Status, 16) + w.WriteInt64(pkt.ExtOnlineStatus, 17) + w.WriteInt64(pkt.ClientBatteryGetInterval, 18) + w.WriteInt64(pkt.ClientAutoStatusInterval, 19) + return w.Bytes() +} + +func (pkt *SvcReqRegisterNew) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.RequestOptional, 0) + w.WriteByte(pkt.DisGroupMsgFilter, 14) + w.WriteByte(pkt.GroupMask, 15) + w.WriteInt64(pkt.EndSeq, 16) + w.WriteBytes(pkt.O769Body, 20) + return w.Bytes() +} + +func (pkt *SvcReqGetMsgV2) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.Uin, 0) + w.WriteInt32(pkt.DateTime, 1) + w.WriteByte(pkt.RecivePic, 4) + w.WriteInt16(pkt.Ability, 6) + w.WriteByte(pkt.Channel, 9) + w.WriteByte(pkt.Inst, 16) + w.WriteByte(pkt.ChannelEx, 17) + w.WriteBytes(pkt.SyncCookie, 18) + w.WriteInt64(int64(pkt.SyncFlag), 19) + w.WriteByte(pkt.RambleFlag, 20) + w.WriteInt64(pkt.GeneralAbi, 26) + w.WriteBytes(pkt.PubAccountCookie, 27) + return w.Bytes() +} + +func (pkt *SvcReqPullGroupMsgSeq) ToBytes() []byte { + w := NewJceWriter() + w.writeHead(9, 0) + if len(pkt.GroupInfo) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.GroupInfo)), 0) + for _, i := range pkt.GroupInfo { + w.buf.Write(i.ToBytes()) + } + } + w.WriteByte(pkt.VerifyType, 1) + w.WriteInt32(pkt.Filter, 2) + return w.Bytes() +} + +func (pkt *PullGroupSeqParam) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.GroupCode, 0) + w.WriteInt64(pkt.LastSeqId, 1) + return w.Bytes() +} + +func (pkt *SvcRespParam) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt32(pkt.PCStat, 0) + w.WriteInt32(pkt.IsSupportC2CRoamMsg, 1) + w.WriteInt32(pkt.IsSupportDataLine, 2) + w.WriteInt32(pkt.IsSupportPrintable, 3) + w.WriteInt32(pkt.IsSupportViewPCFile, 4) + w.WriteInt32(pkt.PcVersion, 5) + w.WriteInt64(pkt.RoamFlag, 6) + w.writeHead(9, 7) + if len(pkt.OnlineInfos) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.OnlineInfos)), 0) + for _, i := range pkt.OnlineInfos { + w.buf.Write(i.ToBytes()) + } + } + w.WriteInt32(pkt.PCClientType, 8) + return w.Bytes() +} + +func (pkt *RequestPushNotify) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.Uin, 0) + w.WriteByte(pkt.Type, 1) + w.WriteString(pkt.Service, 2) + w.WriteString(pkt.Cmd, 3) + w.WriteBytes(pkt.NotifyCookie, 4) + w.WriteInt32(pkt.MsgType, 5) + w.WriteInt32(pkt.UserActive, 6) + w.WriteInt32(pkt.GeneralFlag, 7) + w.WriteInt64(pkt.BindedUin, 8) + return w.Bytes() +} + +func (pkt *OnlineInfo) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt32(pkt.InstanceId, 0) + w.WriteInt32(pkt.ClientType, 1) + w.WriteInt32(pkt.OnlineStatus, 2) + w.WriteInt32(pkt.PlatformId, 3) + w.WriteString(pkt.SubPlatform, 4) + w.WriteInt64(pkt.UClientType, 5) + return w.Bytes() +} + +func (pkt *SvcReqMSFLoginNotify) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.AppId, 0) + w.WriteByte(pkt.Status, 1) + w.WriteByte(pkt.Tablet, 2) + w.WriteInt64(pkt.Platform, 3) + w.WriteString(pkt.Title, 4) + w.WriteString(pkt.Info, 5) + w.WriteInt64(pkt.ProductType, 6) + w.WriteInt64(pkt.ClientType, 7) + w.writeHead(9, 8) + if len(pkt.InstanceList) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.InstanceList)), 0) + for _, i := range pkt.InstanceList { + w.buf.Write(i.ToBytes()) + } + } + return w.Bytes() +} + +func (pkt *InstanceInfo) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt32(pkt.AppId, 0) + w.WriteByte(pkt.Tablet, 1) + w.WriteInt64(pkt.Platform, 2) + w.WriteInt64(pkt.ProductType, 3) + w.WriteInt64(pkt.ClientType, 4) + return w.Bytes() +} + +func (pkt *PushMessageInfo) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.FromUin, 0) + w.WriteInt64(pkt.MsgTime, 1) + w.WriteInt16(pkt.MsgType, 2) + w.WriteInt16(pkt.MsgSeq, 3) + w.WriteString(pkt.Msg, 4) + w.WriteInt32(pkt.RealMsgTime, 5) + w.WriteBytes(pkt.VMsg, 6) + w.WriteInt64(pkt.AppShareID, 7) + w.WriteBytes(pkt.MsgCookies, 8) + w.WriteBytes(pkt.AppShareCookie, 9) + w.WriteInt64(pkt.MsgUid, 10) + w.WriteInt64(pkt.LastChangeTime, 11) + w.WriteInt64(pkt.FromInstId, 14) + w.WriteBytes(pkt.RemarkOfSender, 15) + w.WriteString(pkt.FromMobile, 16) + w.WriteString(pkt.FromName, 17) + return w.Bytes() +} + +func (pkt *SvcRespPushMsg) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.Uin, 0) + w.writeHead(9, 1) + if len(pkt.DelInfos) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.DelInfos)), 0) + for _, i := range pkt.DelInfos { + w.buf.Write(i.ToBytes()) + } + } + w.WriteInt32(pkt.Svrip, 2) + w.WriteBytes(pkt.PushToken, 3) + w.WriteInt32(pkt.ServiceType, 4) + return w.Bytes() +} + +func (pkt *SvcReqGetDevLoginInfo) ToBytes() []byte { + w := NewJceWriter() + w.WriteBytes(pkt.Guid, 0) + w.WriteString(pkt.AppName, 1) + w.WriteInt64(pkt.LoginType, 2) + w.WriteInt64(pkt.Timestamp, 3) + w.WriteInt64(pkt.NextItemIndex, 4) + w.WriteInt64(pkt.RequireMax, 5) + w.WriteInt64(pkt.GetDevListType, 6) + return w.Bytes() +} + +func (pkt *SvcDevLoginInfo) ToBytes() []byte { + w := NewJceWriter() + return w.Bytes() +} + +func (pkt *DelMsgInfo) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.FromUin, 0) + w.WriteInt64(pkt.MsgTime, 1) + w.WriteInt16(pkt.MsgSeq, 2) + w.WriteBytes(pkt.MsgCookies, 3) + w.WriteInt16(pkt.Cmd, 4) + w.WriteInt64(pkt.MsgType, 5) + w.WriteInt64(pkt.AppId, 6) + w.WriteInt64(pkt.SendTime, 7) + w.WriteInt32(pkt.SsoSeq, 8) + w.WriteInt32(pkt.SsoIp, 9) + w.WriteInt32(pkt.ClientIp, 10) + return w.Bytes() +} + +func (pkt *FriendListRequest) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt32(pkt.Reqtype, 0) + w.WriteByte(pkt.IfReflush, 1) + w.WriteInt64(pkt.Uin, 2) + w.WriteInt16(pkt.StartIndex, 3) + w.WriteInt16(pkt.FriendCount, 4) + w.WriteByte(pkt.GroupId, 5) + w.WriteByte(pkt.IfGetGroupInfo, 6) + w.WriteByte(pkt.GroupStartIndex, 7) + w.WriteByte(pkt.GroupCount, 8) + w.WriteByte(pkt.IfGetMSFGroup, 9) + w.WriteByte(pkt.IfShowTermType, 10) + w.WriteInt64(pkt.Version, 11) + w.WriteInt64Slice(pkt.UinList, 12) + w.WriteInt32(pkt.AppType, 13) + w.WriteByte(pkt.IfGetDOVId, 14) + w.WriteByte(pkt.IfGetBothFlag, 15) + w.WriteBytes(pkt.D50, 16) + w.WriteBytes(pkt.D6B, 17) + w.WriteInt64Slice(pkt.SnsTypeList, 18) + return w.Bytes() +} + +func (pkt *FriendInfo) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.FriendUin, 0) + w.WriteByte(pkt.GroupId, 1) + w.WriteInt16(pkt.FaceId, 2) + w.WriteString(pkt.Remark, 3) + w.WriteByte(pkt.QQType, 4) + w.WriteByte(pkt.Status, 5) + w.WriteByte(pkt.MemberLevel, 6) + w.WriteByte(pkt.IsMqqOnLine, 7) + w.WriteByte(pkt.QQOnlineState, 8) + w.WriteByte(pkt.IsIphoneOnline, 9) + w.WriteByte(pkt.DetailStatusFlag, 10) + w.WriteByte(pkt.QQOnlineStateV2, 11) + w.WriteString(pkt.ShowName, 12) + w.WriteByte(pkt.IsRemark, 13) + w.WriteString(pkt.Nick, 14) + w.WriteByte(pkt.SpecialFlag, 15) + w.WriteBytes(pkt.IMGroupID, 16) + w.WriteBytes(pkt.MSFGroupID, 17) + w.WriteInt32(pkt.TermType, 18) + w.WriteByte(pkt.Network, 20) + w.WriteBytes(pkt.Ring, 21) + w.WriteInt64(pkt.AbiFlag, 22) + w.WriteInt64(pkt.FaceAddonId, 23) + w.WriteInt32(pkt.NetworkType, 24) + w.WriteInt64(pkt.VipFont, 25) + w.WriteInt32(pkt.IconType, 26) + w.WriteString(pkt.TermDesc, 27) + w.WriteInt64(pkt.ColorRing, 28) + w.WriteByte(pkt.ApolloFlag, 29) + w.WriteInt64(pkt.ApolloTimestamp, 30) + w.WriteByte(pkt.Sex, 31) + w.WriteInt64(pkt.FounderFont, 32) + w.WriteString(pkt.EimId, 33) + w.WriteString(pkt.EimMobile, 34) + w.WriteByte(pkt.OlympicTorch, 35) + w.WriteInt64(pkt.ApolloSignTime, 36) + w.WriteInt64(pkt.LaviUin, 37) + w.WriteInt64(pkt.TagUpdateTime, 38) + w.WriteInt64(pkt.GameLastLoginTime, 39) + w.WriteInt64(pkt.GameAppId, 40) + w.WriteBytes(pkt.CardID, 41) + w.WriteInt64(pkt.BitSet, 42) + w.WriteByte(pkt.KingOfGloryFlag, 43) + w.WriteInt64(pkt.KingOfGloryRank, 44) + w.WriteString(pkt.MasterUin, 45) + w.WriteInt64(pkt.LastMedalUpdateTime, 46) + w.WriteInt64(pkt.FaceStoreId, 47) + w.WriteInt64(pkt.FontEffect, 48) + w.WriteString(pkt.DOVId, 49) + w.WriteInt64(pkt.BothFlag, 50) + w.WriteByte(pkt.CentiShow3DFlag, 51) + w.WriteBytes(pkt.IntimateInfo, 52) + w.WriteByte(pkt.ShowNameplate, 53) + w.WriteByte(pkt.NewLoverDiamondFlag, 54) + w.WriteBytes(pkt.ExtSnsFrdData, 55) + w.WriteBytes(pkt.MutualMarkData, 56) + return w.Bytes() +} + +func (pkt *TroopListRequest) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.Uin, 0) + w.WriteByte(pkt.GetMSFMsgFlag, 1) + w.WriteBytes(pkt.Cookies, 2) + w.WriteInt64Slice(pkt.GroupInfo, 3) + w.WriteByte(pkt.GroupFlagExt, 4) + w.WriteInt32(pkt.Version, 5) + w.WriteInt64(pkt.CompanyId, 6) + w.WriteInt64(pkt.VersionNum, 7) + w.WriteByte(pkt.GetLongGroupName, 8) + return w.Bytes() +} + +func (pkt *TroopNumber) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.GroupUin, 0) + w.WriteInt64(pkt.GroupCode, 1) + w.WriteByte(pkt.Flag, 2) + w.WriteInt64(pkt.GroupInfoSeq, 3) + w.WriteString(pkt.GroupName, 4) + w.WriteString(pkt.GroupMemo, 5) + w.WriteInt64(pkt.GroupFlagExt, 6) + w.WriteInt64(pkt.GroupRankSeq, 7) + w.WriteInt64(pkt.CertificationType, 8) + w.WriteInt64(pkt.ShutUpTimestamp, 9) + w.WriteInt64(pkt.MyShutUpTimestamp, 10) + w.WriteInt64(pkt.CmdUinUinFlag, 11) + w.WriteInt64(pkt.AdditionalFlag, 12) + w.WriteInt64(pkt.GroupTypeFlag, 13) + w.WriteInt64(pkt.GroupSecType, 14) + w.WriteInt64(pkt.GroupSecTypeInfo, 15) + w.WriteInt64(pkt.GroupClassExt, 16) + w.WriteInt64(pkt.AppPrivilegeFlag, 17) + w.WriteInt64(pkt.SubscriptionUin, 18) + w.WriteInt64(pkt.MemberNum, 19) + w.WriteInt64(pkt.MemberNumSeq, 20) + w.WriteInt64(pkt.MemberCardSeq, 21) + w.WriteInt64(pkt.GroupFlagExt3, 22) + w.WriteInt64(pkt.GroupOwnerUin, 23) + w.WriteByte(pkt.IsConfGroup, 24) + w.WriteByte(pkt.IsModifyConfGroupFace, 25) + w.WriteByte(pkt.IsModifyConfGroupName, 26) + w.WriteInt64(pkt.CmdUinJoinTime, 27) + w.WriteInt64(pkt.CompanyId, 28) + w.WriteInt64(pkt.MaxGroupMemberNum, 29) + w.WriteInt64(pkt.CmdUinGroupMask, 30) + w.WriteInt64(pkt.GuildAppId, 31) + w.WriteInt64(pkt.GuildSubType, 32) + w.WriteInt64(pkt.CmdUinRingtoneID, 33) + w.WriteInt64(pkt.CmdUinFlagEx2, 34) + return w.Bytes() +} + +func (pkt *TroopMemberListRequest) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.Uin, 0) + w.WriteInt64(pkt.GroupCode, 1) + w.WriteInt64(pkt.NextUin, 2) + w.WriteInt64(pkt.GroupUin, 3) + w.WriteInt64(pkt.Version, 4) + w.WriteInt64(pkt.ReqType, 5) + w.WriteInt64(pkt.GetListAppointTime, 6) + w.WriteByte(pkt.RichCardNameVer, 7) + return w.Bytes() +} + +func (pkt *TroopMemberInfo) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.MemberUin, 0) + w.WriteInt16(pkt.FaceId, 1) + w.WriteByte(pkt.Age, 2) + w.WriteByte(pkt.Gender, 3) + w.WriteString(pkt.Nick, 4) + w.WriteByte(pkt.Status, 5) + w.WriteString(pkt.ShowName, 6) + w.WriteString(pkt.Name, 8) + w.WriteString(pkt.Memo, 12) + w.WriteString(pkt.AutoRemark, 13) + w.WriteInt64(pkt.MemberLevel, 14) + w.WriteInt64(pkt.JoinTime, 15) + w.WriteInt64(pkt.LastSpeakTime, 16) + w.WriteInt64(pkt.CreditLevel, 17) + w.WriteInt64(pkt.Flag, 18) + w.WriteInt64(pkt.FlagExt, 19) + w.WriteInt64(pkt.Point, 20) + w.WriteByte(pkt.Concerned, 21) + w.WriteByte(pkt.Shielded, 22) + w.WriteString(pkt.SpecialTitle, 23) + w.WriteInt64(pkt.SpecialTitleExpireTime, 24) + w.WriteString(pkt.Job, 25) + w.WriteByte(pkt.ApolloFlag, 26) + w.WriteInt64(pkt.ApolloTimestamp, 27) + w.WriteInt64(pkt.GlobalGroupLevel, 28) + w.WriteInt64(pkt.TitleId, 29) + w.WriteInt64(pkt.ShutUpTimestap, 30) + w.WriteInt64(pkt.GlobalGroupPoint, 31) + w.WriteByte(pkt.RichCardNameVer, 33) + w.WriteInt64(pkt.VipType, 34) + w.WriteInt64(pkt.VipLevel, 35) + w.WriteInt64(pkt.BigClubLevel, 36) + w.WriteInt64(pkt.BigClubFlag, 37) + w.WriteInt64(pkt.Nameplate, 38) + w.WriteBytes(pkt.GroupHonor, 39) + return w.Bytes() +} + +func (pkt *ModifyGroupCardRequest) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.Zero, 0) + w.WriteInt64(pkt.GroupCode, 1) + w.WriteInt64(pkt.NewSeq, 2) + w.writeHead(9, 3) + if len(pkt.UinInfo) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.UinInfo)), 0) + for _, i := range pkt.UinInfo { + w.buf.Write(i.ToBytes()) + } + } + return w.Bytes() +} + +func (pkt *UinInfo) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.Uin, 0) + w.WriteInt64(pkt.Flag, 1) + w.WriteString(pkt.Name, 2) + w.WriteByte(pkt.Gender, 3) + w.WriteString(pkt.Phone, 4) + w.WriteString(pkt.Email, 5) + w.WriteString(pkt.Remark, 6) + return w.Bytes() +} + +func (pkt *SummaryCardReq) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.Uin, 0) + w.WriteInt32(pkt.ComeFrom, 1) + w.WriteInt64(pkt.QzoneFeedTimestamp, 2) + w.WriteByte(pkt.IsFriend, 3) + w.WriteInt64(pkt.GroupCode, 4) + w.WriteInt64(pkt.GroupUin, 5) + w.WriteInt64(pkt.GetControl, 8) + w.WriteInt32(pkt.AddFriendSource, 9) + w.WriteBytes(pkt.SecureSig, 10) + w.WriteBytesSlice(pkt.ReqServices, 14) + w.WriteInt64(pkt.TinyId, 15) + w.WriteInt64(pkt.LikeSource, 16) + w.WriteByte(pkt.ReqMedalWallInfo, 18) + w.WriteInt64Slice(pkt.Req0x5ebFieldId, 19) + w.WriteByte(pkt.ReqNearbyGodInfo, 20) + w.WriteByte(pkt.ReqExtendCard, 22) + return w.Bytes() +} + +func (pkt *SummaryCardReqSearch) ToBytes() []byte { + w := NewJceWriter() + w.WriteString(pkt.Keyword, 0) + w.WriteString(pkt.CountryCode, 1) + w.WriteInt32(pkt.Version, 2) + w.WriteBytesSlice(pkt.ReqServices, 3) + return w.Bytes() +} + +func (pkt *DelFriendReq) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.Uin, 0) + w.WriteInt64(pkt.DelUin, 1) + w.WriteByte(pkt.DelType, 2) + w.WriteInt32(pkt.Version, 3) + return w.Bytes() +} diff --git a/binary/jce/writer.go b/binary/jce/writer.go index 6159d1be..d5d803c8 100644 --- a/binary/jce/writer.go +++ b/binary/jce/writer.go @@ -3,9 +3,7 @@ package jce import ( "bytes" goBinary "encoding/binary" - "reflect" - "strconv" - "sync" + "math" ) type JceWriter struct { @@ -16,18 +14,16 @@ func NewJceWriter() *JceWriter { return &JceWriter{buf: new(bytes.Buffer)} } -func (w *JceWriter) writeHead(t byte, tag int) { - if tag < 15 { - b := byte(tag<<4) | t - w.buf.WriteByte(b) - } else if tag < 256 { - b := 0xF0 | t - w.buf.WriteByte(b) - w.buf.WriteByte(byte(tag)) +func (w *JceWriter) writeHead(t, tag byte) { + if tag < 0xF { + w.buf.WriteByte(tag<<4 | t) + } else { + w.buf.WriteByte(0xF0 | t) + w.buf.WriteByte(tag) } } -func (w *JceWriter) WriteByte(b byte, tag int) *JceWriter { +func (w *JceWriter) WriteByte(b, tag byte) *JceWriter { if b == 0 { w.writeHead(12, tag) } else { @@ -37,7 +33,7 @@ func (w *JceWriter) WriteByte(b byte, tag int) *JceWriter { return w } -func (w *JceWriter) WriteBool(b bool, tag int) { +func (w *JceWriter) WriteBool(b bool, tag byte) { var by byte = 0 if b { by = 1 @@ -45,7 +41,7 @@ func (w *JceWriter) WriteBool(b bool, tag int) { w.WriteByte(by, tag) } -func (w *JceWriter) WriteInt16(n int16, tag int) { +func (w *JceWriter) WriteInt16(n int16, tag byte) { switch { case n >= -128 && n <= 127: w.WriteByte(byte(n), tag) @@ -55,14 +51,14 @@ func (w *JceWriter) WriteInt16(n int16, tag int) { } //go:nosplit -func (w *JceWriter) putInt16(n int16, tag int) { +func (w *JceWriter) putInt16(n int16, tag byte) { w.writeHead(1, tag) var buf [2]byte goBinary.BigEndian.PutUint16(buf[:], uint16(n)) w.buf.Write(buf[:]) } -func (w *JceWriter) WriteInt32(n int32, tag int) *JceWriter { +func (w *JceWriter) WriteInt32(n int32, tag byte) *JceWriter { switch { case n >= -128 && n <= 127: w.WriteByte(byte(n), tag) @@ -75,14 +71,14 @@ func (w *JceWriter) WriteInt32(n int32, tag int) *JceWriter { } //go:nosplit -func (w *JceWriter) putInt32(n int32, tag int) { +func (w *JceWriter) putInt32(n int32, tag byte) { w.writeHead(2, tag) var buf [4]byte goBinary.BigEndian.PutUint32(buf[:], uint32(n)) w.buf.Write(buf[:]) } -func (w *JceWriter) WriteInt64(n int64, tag int) *JceWriter { +func (w *JceWriter) WriteInt64(n int64, tag byte) *JceWriter { switch { case n >= -128 && n <= 127: w.WriteByte(byte(n), tag) @@ -97,49 +93,56 @@ func (w *JceWriter) WriteInt64(n int64, tag int) *JceWriter { } //go:nosplit -func (w *JceWriter) putInt64(n int64, tag int) { +func (w *JceWriter) putInt64(n int64, tag byte) { w.writeHead(3, tag) var buf [8]byte goBinary.BigEndian.PutUint64(buf[:], uint64(n)) w.buf.Write(buf[:]) } -func (w *JceWriter) WriteFloat32(n float32, tag int) { +//go:nosplit +func (w *JceWriter) WriteFloat32(n float32, tag byte) { w.writeHead(4, tag) - _ = goBinary.Write(w.buf, goBinary.BigEndian, n) + var buf [4]byte + goBinary.BigEndian.PutUint32(buf[:], math.Float32bits(n)) + w.buf.Write(buf[:]) } -func (w *JceWriter) WriteFloat64(n float64, tag int) { +//go:nosplit +func (w *JceWriter) WriteFloat64(n float64, tag byte) { w.writeHead(5, tag) - _ = goBinary.Write(w.buf, goBinary.BigEndian, n) + var buf [8]byte + goBinary.BigEndian.PutUint64(buf[:], math.Float64bits(n)) + w.buf.Write(buf[:]) } -func (w *JceWriter) WriteString(s string, tag int) *JceWriter { - by := []byte(s) - if len(by) > 255 { +func (w *JceWriter) WriteString(s string, tag byte) *JceWriter { + if len(s) > 255 { w.writeHead(7, tag) - _ = goBinary.Write(w.buf, goBinary.BigEndian, int32(len(by))) - w.buf.Write(by) + var buf [4]byte + goBinary.BigEndian.PutUint32(buf[:], uint32(len(s))) + w.buf.Write(buf[:]) + w.buf.WriteString(s) return w } w.writeHead(6, tag) - w.buf.WriteByte(byte(len(by))) - w.buf.Write(by) + w.buf.WriteByte(byte(len(s))) + w.buf.WriteString(s) return w } -func (w *JceWriter) WriteBytes(l []byte, tag int) *JceWriter { +func (w *JceWriter) WriteBytes(l []byte, tag byte) *JceWriter { w.writeHead(13, tag) - w.writeHead(0, 0) + w.buf.WriteByte(0) // w.writeHead(0, 0) w.WriteInt32(int32(len(l)), 0) w.buf.Write(l) return w } -func (w *JceWriter) WriteInt64Slice(l []int64, tag int) { +func (w *JceWriter) WriteInt64Slice(l []int64, tag byte) { w.writeHead(9, tag) if len(l) == 0 { - w.WriteInt32(0, 0) + w.writeHead(12, 0) // w.WriteInt32(0, 0) return } w.WriteInt32(int32(len(l)), 0) @@ -148,190 +151,58 @@ func (w *JceWriter) WriteInt64Slice(l []int64, tag int) { } } -func (w *JceWriter) WriteSlice(i interface{}, tag int) { - va := reflect.ValueOf(i) - if va.Kind() != reflect.Slice { - panic("JceWriter.WriteSlice: not a slice") - } - w.writeSlice(va, tag) -} - -func (w *JceWriter) writeSlice(slice reflect.Value, tag int) { - if slice.Kind() != reflect.Slice { - return - } - w.writeHead(9, tag) - if slice.Len() == 0 { - w.WriteInt32(0, 0) - return - } - w.WriteInt32(int32(slice.Len()), 0) - for i := 0; i < slice.Len(); i++ { - v := slice.Index(i) - w.writeObject(v, 0) - } -} - -func (w *JceWriter) WriteJceStructSlice(l []IJceStruct, tag int) { +func (w *JceWriter) WriteBytesSlice(l [][]byte, tag byte) { w.writeHead(9, tag) if len(l) == 0 { - w.WriteInt32(0, 0) + w.writeHead(12, 0) // w.WriteInt32(0, 0) return } w.WriteInt32(int32(len(l)), 0) for _, v := range l { - w.WriteJceStruct(v, 0) + w.WriteBytes(v, 0) } } -func (w *JceWriter) WriteMap(m interface{}, tag int) { - va := reflect.ValueOf(m) - if va.Kind() != reflect.Map { - panic("JceWriter.WriteMap: not a map") - } - w.writeMap(va, tag) -} - -func (w *JceWriter) writeMap(m reflect.Value, tag int) { - if m.IsNil() { +func (w *JceWriter) writeMapStrStr(m map[string]string, tag byte) { + if m == nil { w.writeHead(8, tag) - w.WriteInt32(0, 0) - return - } - if m.Kind() != reflect.Map { + w.writeHead(12, 0) // w.WriteInt32(0, 0) return } w.writeHead(8, tag) - w.WriteInt32(int32(m.Len()), 0) - iter := m.MapRange() - for iter.Next() { - w.writeObject(iter.Key(), 0) - w.writeObject(iter.Value(), 1) + w.WriteInt32(int32(len(m)), 0) + for k, v := range m { + w.WriteString(k, 0) + w.WriteString(v, 1) } } -func (w *JceWriter) WriteObject(i interface{}, tag int) { - t := reflect.TypeOf(i) - if t.Kind() == reflect.Map { - w.WriteMap(i, tag) +func (w *JceWriter) writeMapStrBytes(m map[string][]byte, tag byte) { + if m == nil { + w.writeHead(8, tag) + w.writeHead(12, 0) // w.WriteInt32(0, 0) return } - if t.Kind() == reflect.Slice { - if b, ok := i.([]byte); ok { - w.WriteBytes(b, tag) - return - } - w.WriteSlice(i, tag) - return - } - switch o := i.(type) { - case byte: - w.WriteByte(o, tag) - case bool: - w.WriteBool(o, tag) - case int16: - w.WriteInt16(o, tag) - case int32: - w.WriteInt32(o, tag) - case int64: - w.WriteInt64(o, tag) - case float32: - w.WriteFloat32(o, tag) - case float64: - w.WriteFloat64(o, tag) - case string: - w.WriteString(o, tag) - case IJceStruct: - w.WriteJceStruct(o, tag) + w.writeHead(8, tag) + w.WriteInt32(int32(len(m)), 0) + for k, v := range m { + w.WriteString(k, 0) + w.WriteBytes(v, 1) } } -func (w *JceWriter) writeObject(v reflect.Value, tag int) { - k := v.Kind() - if k == reflect.Map { - w.writeMap(v, tag) +func (w *JceWriter) writeMapStrMapStrBytes(m map[string]map[string][]byte, tag byte) { + if m == nil { + w.writeHead(8, tag) + w.writeHead(12, 0) // w.WriteInt32(0, 0) return } - if k == reflect.Slice { - if v.Type().Elem().Kind() == reflect.Uint8 { - w.WriteBytes(v.Bytes(), tag) - return - } - w.writeSlice(v, tag) - return + w.writeHead(8, tag) + w.WriteInt32(int32(len(m)), 0) + for k, v := range m { + w.WriteString(k, 0) + w.writeMapStrBytes(v, 1) } - switch k { - case reflect.Uint8, reflect.Int8: - w.WriteByte(*(*byte)(pointerOf(v)), tag) - case reflect.Uint16, reflect.Int16: - w.WriteInt16(*(*int16)(pointerOf(v)), tag) - case reflect.Uint32, reflect.Int32: - w.WriteInt32(*(*int32)(pointerOf(v)), tag) - case reflect.Uint64, reflect.Int64: - w.WriteInt64(*(*int64)(pointerOf(v)), tag) - case reflect.String: - w.WriteString(v.String(), tag) - default: - switch o := v.Interface().(type) { - case IJceStruct: - w.WriteJceStruct(o, tag) - case float32: - w.WriteFloat32(o, tag) - case float64: - w.WriteFloat64(o, tag) - } - } -} - -type decoder struct { - index int - id int -} - -var decoderCache = sync.Map{} - -// WriteJceStructRaw 写入 Jce 结构体 -func (w *JceWriter) WriteJceStructRaw(s interface{}) { - t := reflect.TypeOf(s) - reflect.ValueOf(s).Interface() - if t.Kind() != reflect.Ptr { - return - } - t = t.Elem() - v := reflect.ValueOf(s).Elem() - var jceDec []decoder - dec, ok := decoderCache.Load(t) - if ok { // 从缓存中加载 - jceDec = dec.([]decoder) - } else { // 初次反射 - jceDec = make([]decoder, 0, t.NumField()) - for i := 0; i < t.NumField(); i++ { - field := t.Field(i) - strId := field.Tag.Get("jceId") - if strId == "" { - continue - } - id, err := strconv.Atoi(strId) - if err != nil { - continue - } - jceDec = append(jceDec, decoder{ - index: i, - id: id, - }) - } - decoderCache.Store(t, jceDec) // 存入缓存 - } - for _, dec := range jceDec { - obj := v.Field(dec.index) - w.writeObject(obj, dec.id) - } -} - -func (w *JceWriter) WriteJceStruct(s IJceStruct, tag int) { - w.writeHead(10, tag) - w.WriteJceStructRaw(s) - w.writeHead(11, 0) } func (w *JceWriter) Bytes() []byte { diff --git a/binary/jce/writer_test.go b/binary/jce/writer_test.go index 1eafdd00..2a2d85bb 100644 --- a/binary/jce/writer_test.go +++ b/binary/jce/writer_test.go @@ -12,7 +12,7 @@ func BenchmarkJceWriter_WriteMap(b *testing.B) { var x = globalBytes for i := 0; i < b.N; i++ { w := NewJceWriter() - w.WriteMap(req.Map, 0) + w.writeMapStrMapStrBytes(req.Map, 0) x = w.Bytes() } globalBytes = x @@ -41,18 +41,14 @@ var reqPacket1 = &RequestPacket{ func BenchmarkJceWriter_WriteJceStructRaw(b *testing.B) { var x = globalBytes for i := 0; i < b.N; i++ { - w := NewJceWriter() - w.WriteJceStructRaw(reqPacket1) - x = w.Bytes() + _ = reqPacket1.ToBytes() } globalBytes = x b.SetBytes(int64(len(globalBytes))) } func TestJceWriter_WriteJceStructRaw(t *testing.T) { - w := NewJceWriter() - w.WriteJceStructRaw(reqPacket1) - r := NewJceReader(w.Bytes()) + r := NewJceReader(reqPacket1.ToBytes()) var reqPacket2 RequestPacket reqPacket2.ReadFrom(r) assert.Equal(t, reqPacket1, &reqPacket2)