From 80e2d83dab3583667f9709d245cb00266fcf4a9c Mon Sep 17 00:00:00 2001 From: wdvxdr Date: Thu, 21 Oct 2021 18:01:33 +0800 Subject: [PATCH 1/5] fix: only read protobuf on known sub-type Fixes Mrs4s/go-cqhttp#1120 --- binary/jce/reader.go | 3 +++ client/online_push.go | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/binary/jce/reader.go b/binary/jce/reader.go index 3c6d5614..7d2f0a7e 100644 --- a/binary/jce/reader.go +++ b/binary/jce/reader.go @@ -90,6 +90,9 @@ func (r *JceReader) SkipField(c int) { } func (r *JceReader) readBytes(len int) []byte { + if len == 0 { + return nil + } b := make([]byte, len) _, err := r.buf.Read(b) if err != nil { diff --git a/client/online_push.go b/client/online_push.go index b85848a5..1eec697f 100644 --- a/client/online_push.go +++ b/client/online_push.go @@ -113,8 +113,8 @@ func decodeOnlinePushReqPacket(c *QQClient, info *incomingPacketInfo, payload [] if m.MsgType == 528 { vr := jce.NewJceReader(m.VMsg) subType := vr.ReadInt64(0) - protobuf := vr.ReadBytes(10) if decoder, ok := msg0x210Decoders[subType]; ok { + protobuf := vr.ReadBytes(10) if err := decoder(c, protobuf); err != nil { return nil, errors.Wrap(err, "decode online push 0x210 error") } From 7a6c0df081af781546ca10e4b5098fdc20cf2ca9 Mon Sep 17 00:00:00 2001 From: Lin <767763591@qq.com> Date: Wed, 27 Oct 2021 09:35:23 +0800 Subject: [PATCH 2/5] =?UTF-8?q?tidy:=20=E5=B0=86c2cDecoders=20switch?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/c2c_decoders.go | 33 +++++++++++++++++++++++++++++++++ client/c2c_processor.go | 41 +++-------------------------------------- client/decoders.go | 17 ++++++++++------- 3 files changed, 46 insertions(+), 45 deletions(-) create mode 100644 client/c2c_decoders.go diff --git a/client/c2c_decoders.go b/client/c2c_decoders.go new file mode 100644 index 00000000..0d0272da --- /dev/null +++ b/client/c2c_decoders.go @@ -0,0 +1,33 @@ +//go:build ignore +// +build ignore + +package client + +import "github.com/Mrs4s/MiraiGo/client/pb/msg" + +var privateMsgDecoders = map[int32]func(*QQClient, *msg.Message, *incomingPacketInfo){ + 9: privateMessageDecoder, 10: privateMessageDecoder, 31: privateMessageDecoder, + 79: privateMessageDecoder, 97: privateMessageDecoder, 120: privateMessageDecoder, + 132: privateMessageDecoder, 133: privateMessageDecoder, 166: privateMessageDecoder, + 167: privateMessageDecoder, 140: tempSessionDecoder, 141: tempSessionDecoder, + 208: privatePttDecoder, +} + +var nonSvcNotifyTroopSystemMsgDecoders = map[int32]func(*QQClient, *msg.Message, *incomingPacketInfo){ + 36: troopSystemMessageDecoder, 85: troopSystemMessageDecoder, +} + +var troopSystemMsgDecoders = map[int32]func(*QQClient, *msg.Message, *incomingPacketInfo){ + 35: troopSystemMessageDecoder, 37: troopSystemMessageDecoder, + 45: troopSystemMessageDecoder, 46: troopSystemMessageDecoder, 84: troopSystemMessageDecoder, + 86: troopSystemMessageDecoder, 87: troopSystemMessageDecoder, +} // IsSvcNotify + +var sysMsgDecoders = map[int32]func(*QQClient, *msg.Message, *incomingPacketInfo){ + 187: systemMessageDecoder, 188: systemMessageDecoder, 189: systemMessageDecoder, + 190: systemMessageDecoder, 191: systemMessageDecoder, +} // IsSvcNotify + +var otherDecoders = map[int32]func(*QQClient, *msg.Message, *incomingPacketInfo){ + 33: troopAddMemberBroadcastDecoder, 529: msgType0x211Decoder, +} diff --git a/client/c2c_processor.go b/client/c2c_processor.go index bcc447c2..a6278b25 100644 --- a/client/c2c_processor.go +++ b/client/c2c_processor.go @@ -1,5 +1,7 @@ package client +//go:generate go run c2c_switcher.go + import ( "fmt" "sync/atomic" @@ -13,31 +15,6 @@ import ( "google.golang.org/protobuf/proto" ) -var privateMsgDecoders = map[int32]func(*QQClient, *msg.Message, *incomingPacketInfo){ - 9: privateMessageDecoder, 10: privateMessageDecoder, 31: privateMessageDecoder, - 79: privateMessageDecoder, 97: privateMessageDecoder, 120: privateMessageDecoder, - 132: privateMessageDecoder, 133: privateMessageDecoder, 166: privateMessageDecoder, - 167: privateMessageDecoder, 140: tempSessionDecoder, 141: tempSessionDecoder, - 208: privatePttDecoder, -} - -var troopSystemMsgDecoders = map[int32]func(*QQClient, *msg.Message, *incomingPacketInfo){ - 35: troopSystemMessageDecoder, 36: troopSystemMessageDecoder, 37: troopSystemMessageDecoder, - 45: troopSystemMessageDecoder, 46: troopSystemMessageDecoder, 84: troopSystemMessageDecoder, - 85: troopSystemMessageDecoder, 86: troopSystemMessageDecoder, 87: troopSystemMessageDecoder, -} - -var sysMsgDecoders = map[int32]func(*QQClient, *msg.Message, *incomingPacketInfo){ - 187: systemMessageDecoder, 188: systemMessageDecoder, 189: systemMessageDecoder, - 190: systemMessageDecoder, 191: systemMessageDecoder, -} - -var otherDecoders = map[int32]func(*QQClient, *msg.Message, *incomingPacketInfo){ - 33: troopAddMemberBroadcastDecoder, 529: msgType0x211Decoder, -} - -var c2cDecoders = map[int32]func(*QQClient, *msg.Message, *incomingPacketInfo){} - type ( TempSessionInfo struct { Source TempSessionSource @@ -62,18 +39,6 @@ const ( AddressBookSource TempSessionSource = 9 // 来自通讯录 ) -func init() { - merge := func(m map[int32]func(*QQClient, *msg.Message, *incomingPacketInfo)) { - for k, v := range m { - c2cDecoders[k] = v - } - } - merge(privateMsgDecoders) - merge(troopSystemMsgDecoders) - merge(sysMsgDecoders) - merge(otherDecoders) -} - func (c *QQClient) c2cMessageSyncProcessor(rsp *msg.GetMessageResponse, info *incomingPacketInfo) { c.syncCookie = rsp.SyncCookie c.pubAccountCookie = rsp.PubAccountCookie @@ -127,7 +92,7 @@ func (c *QQClient) commMsgProcessor(pMsg *msg.Message, info *incomingPacketInfo) if info.Params.bool("init") { return } - if decoder, ok := c2cDecoders[pMsg.Head.GetMsgType()]; ok { + if decoder, _ := peekC2CDecoder(pMsg.Head.GetMsgType()); decoder != nil { decoder(c, pMsg, info) } else { c.Debug("unknown msg type on c2c processor: %v - %v", pMsg.Head.GetMsgType(), pMsg.Head.GetC2CCmd()) diff --git a/client/decoders.go b/client/decoders.go index 6c5e4123..32a4d113 100644 --- a/client/decoders.go +++ b/client/decoders.go @@ -395,13 +395,16 @@ func decodeSvcNotify(c *QQClient, _ *incomingPacketInfo, payload []byte) (interf } notify := &jce.RequestPushNotify{} notify.ReadFrom(jce.NewJceReader(data.Map["req_PushNotify"]["PushNotifyPack.RequestPushNotify"][1:])) - if _, ok := troopSystemMsgDecoders[notify.MsgType]; ok && notify.MsgType != 85 && notify.MsgType != 36 { - c.exceptAndDispatchGroupSysMsg() - return nil, nil - } - if _, ok := sysMsgDecoders[notify.MsgType]; ok { - _, pkt := c.buildSystemMsgNewFriendPacket() - return nil, c.sendPacket(pkt) + if decoder, typ := peekC2CDecoder(notify.MsgType); decoder != nil { + // notify.MsgType != 85 && notify.MsgType != 36 moves to c2c_decoders.go [nonSvcNotifyTroopSystemMsgDecoders] + if typ == troopSystemMsgDecoders { + c.exceptAndDispatchGroupSysMsg() + return nil, nil + } + if typ == sysMsgDecoders { + _, pkt := c.buildSystemMsgNewFriendPacket() + return nil, c.sendPacket(pkt) + } } _, err := c.sendAndWait(c.buildGetMessageRequestPacket(msg.SyncFlag_START, time.Now().Unix())) return nil, err From 4767245285719c5f14645145aa17147c21b9118f Mon Sep 17 00:00:00 2001 From: Lin <767763591@qq.com> Date: Wed, 27 Oct 2021 09:38:30 +0800 Subject: [PATCH 3/5] =?UTF-8?q?tidy:=20=E5=B0=86c2cDecoders=20switch?= =?UTF-8?q?=E5=8C=96=20#2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/c2c_switch.go | 81 +++++++++++++++++++++++++++ client/c2c_switcher.go | 122 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 203 insertions(+) create mode 100644 client/c2c_switch.go create mode 100644 client/c2c_switcher.go diff --git a/client/c2c_switch.go b/client/c2c_switch.go new file mode 100644 index 00000000..e0fb94f4 --- /dev/null +++ b/client/c2c_switch.go @@ -0,0 +1,81 @@ +// Code generated by client/c2c_switcher.go DO NOT EDIT. + +package client + +import ( + "github.com/Mrs4s/MiraiGo/client/pb/msg" +) + +const ( + UnknownDecoder = iota + sysMsgDecoders + otherDecoders + privateMsgDecoders + nonSvcNotifyTroopSystemMsgDecoders + troopSystemMsgDecoders +) + +func peekC2CDecoder(msgType int32) (decoder func(*QQClient, *msg.Message, *incomingPacketInfo), decoderType uint8) { + switch msgType { + case 9: + return privateMessageDecoder, privateMsgDecoders + case 10: + return privateMessageDecoder, privateMsgDecoders + case 31: + return privateMessageDecoder, privateMsgDecoders + case 33: + return troopAddMemberBroadcastDecoder, otherDecoders + case 35: + return troopSystemMessageDecoder, troopSystemMsgDecoders + case 36: + return troopSystemMessageDecoder, nonSvcNotifyTroopSystemMsgDecoders + case 37: + return troopSystemMessageDecoder, troopSystemMsgDecoders + case 45: + return troopSystemMessageDecoder, troopSystemMsgDecoders + case 46: + return troopSystemMessageDecoder, troopSystemMsgDecoders + case 79: + return privateMessageDecoder, privateMsgDecoders + case 84: + return troopSystemMessageDecoder, troopSystemMsgDecoders + case 85: + return troopSystemMessageDecoder, nonSvcNotifyTroopSystemMsgDecoders + case 86: + return troopSystemMessageDecoder, troopSystemMsgDecoders + case 87: + return troopSystemMessageDecoder, troopSystemMsgDecoders + case 97: + return privateMessageDecoder, privateMsgDecoders + case 120: + return privateMessageDecoder, privateMsgDecoders + case 132: + return privateMessageDecoder, privateMsgDecoders + case 133: + return privateMessageDecoder, privateMsgDecoders + case 140: + return tempSessionDecoder, privateMsgDecoders + case 141: + return tempSessionDecoder, privateMsgDecoders + case 166: + return privateMessageDecoder, privateMsgDecoders + case 167: + return privateMessageDecoder, privateMsgDecoders + case 187: + return systemMessageDecoder, sysMsgDecoders + case 188: + return systemMessageDecoder, sysMsgDecoders + case 189: + return systemMessageDecoder, sysMsgDecoders + case 190: + return systemMessageDecoder, sysMsgDecoders + case 191: + return systemMessageDecoder, sysMsgDecoders + case 208: + return privatePttDecoder, privateMsgDecoders + case 529: + return msgType0x211Decoder, otherDecoders + default: + return nil, UnknownDecoder + } +} diff --git a/client/c2c_switcher.go b/client/c2c_switcher.go new file mode 100644 index 00000000..01088f55 --- /dev/null +++ b/client/c2c_switcher.go @@ -0,0 +1,122 @@ +//go:build ignore +// +build ignore + +package main + +import ( + "bytes" + "go/ast" + "go/format" + "go/parser" + "go/token" + "os" + "sort" + "strconv" + "text/template" +) + +const codeTemplate = `// Code generated by client/c2c_switcher.go DO NOT EDIT. + +package client + +import ( +{{range .Imports}} {{.}} +{{end}} +) + +const ( + UnknownDecoder = iota +{{range .Consts}} {{.}} +{{end}} +) + +func peekC2CDecoder(msgType int32) (decoder func(*QQClient, *msg.Message, *incomingPacketInfo), decoderType uint8) { + switch msgType { +{{range .Decoders}} case {{.Id}}: + return {{.Func}}, {{.DecoderType}} +{{end}} default: + return nil, UnknownDecoder + } +}` + +type decoder struct { + Id int64 + Func string + DecoderType string +} +type DecoderSort []decoder + +func (d DecoderSort) Len() int { return len(d) } +func (d DecoderSort) Swap(i, j int) { d[i], d[j] = d[j], d[i] } +func (d DecoderSort) Less(i, j int) bool { return d[i].Id < d[j].Id } + +func main() { + type switchFile struct { + Imports []string + Consts []string + Decoders DecoderSort + } + var sf switchFile + + fset := token.NewFileSet() + astF, err := parser.ParseFile(fset, "c2c_decoders.go", nil, parser.AllErrors|parser.ParseComments) + if err != nil { + panic(err) + } + + sf.Imports = make([]string, 0, len(astF.Imports)) + for _, imp := range astF.Imports { + sf.Imports = append(sf.Imports, imp.Path.Value) + } + + sf.Consts = make([]string, 0, len(astF.Scope.Objects)) + for _, obj := range astF.Scope.Objects { + if obj.Kind != ast.Var { + panic(`unknown non-variable in "c2c_decoders.go"`) + } + value := obj.Decl.(*ast.ValueSpec) + sf.Consts = append(sf.Consts, obj.Name) + for _, value := range value.Values { + if value, ok := value.(*ast.CompositeLit); ok { + for _, kv := range value.Elts { + if kv, ok := kv.(*ast.KeyValueExpr); ok { + k := kv.Key.(*ast.BasicLit) + v := kv.Value.(*ast.Ident) + sf.Decoders = append(sf.Decoders, decoder{ + Id: mustParseInt(k.Value), + Func: v.Name, + DecoderType: obj.Name, + }) + } else { + panic(`unknown key value in ` + obj.Name + ` in "c2c_decoders.go"`) + } + } + } else { + panic(`unknown non-map value in "c2c_decoders.go"`) + } + } + } + sort.Sort(sf.Decoders) + + f, _ := os.OpenFile("c2c_switch.go", os.O_WRONLY|os.O_CREATE|os.O_SYNC|os.O_TRUNC, 0o755) + tmpl, err := template.New("template").Parse(codeTemplate) + if err != nil { + panic(err) + } + buffer := &bytes.Buffer{} + err = tmpl.Execute(buffer, &sf) + if err != nil { + panic(err) + } + source, _ := format.Source(buffer.Bytes()) + f.Write(source) + f.Close() +} + +func mustParseInt(s string) int64 { + i, err := strconv.ParseInt(s, 10, 32) + if err != nil { + panic(err) + } + return i +} From 0f68dadc9a1741b8377b80500bdd61f50493617b Mon Sep 17 00:00:00 2001 From: Lin <767763591@qq.com> Date: Wed, 27 Oct 2021 10:03:19 +0800 Subject: [PATCH 4/5] =?UTF-8?q?chron:=20=E6=B7=BB=E5=8A=A0=E4=B8=8B?= =?UTF-8?q?=E5=88=92=E7=BA=BF=EF=BC=8C=E4=BF=AE=E6=94=B9=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/{c2c_decoders.go => _c2c_decoders.go} | 3 --- client/c2c_switch.go | 4 ++-- client/c2c_switcher.go | 10 +++++----- client/decoders.go | 2 +- 4 files changed, 8 insertions(+), 11 deletions(-) rename client/{c2c_decoders.go => _c2c_decoders.go} (97%) diff --git a/client/c2c_decoders.go b/client/_c2c_decoders.go similarity index 97% rename from client/c2c_decoders.go rename to client/_c2c_decoders.go index 0d0272da..72a72b44 100644 --- a/client/c2c_decoders.go +++ b/client/_c2c_decoders.go @@ -1,6 +1,3 @@ -//go:build ignore -// +build ignore - package client import "github.com/Mrs4s/MiraiGo/client/pb/msg" diff --git a/client/c2c_switch.go b/client/c2c_switch.go index e0fb94f4..fb9199ec 100644 --- a/client/c2c_switch.go +++ b/client/c2c_switch.go @@ -8,11 +8,11 @@ import ( const ( UnknownDecoder = iota - sysMsgDecoders - otherDecoders privateMsgDecoders nonSvcNotifyTroopSystemMsgDecoders troopSystemMsgDecoders + sysMsgDecoders + otherDecoders ) func peekC2CDecoder(msgType int32) (decoder func(*QQClient, *msg.Message, *incomingPacketInfo), decoderType uint8) { diff --git a/client/c2c_switcher.go b/client/c2c_switcher.go index 01088f55..058a6f03 100644 --- a/client/c2c_switcher.go +++ b/client/c2c_switcher.go @@ -59,7 +59,7 @@ func main() { var sf switchFile fset := token.NewFileSet() - astF, err := parser.ParseFile(fset, "c2c_decoders.go", nil, parser.AllErrors|parser.ParseComments) + astF, err := parser.ParseFile(fset, "_c2c_decoders.go", nil, parser.AllErrors|parser.ParseComments) if err != nil { panic(err) } @@ -72,7 +72,7 @@ func main() { sf.Consts = make([]string, 0, len(astF.Scope.Objects)) for _, obj := range astF.Scope.Objects { if obj.Kind != ast.Var { - panic(`unknown non-variable in "c2c_decoders.go"`) + panic(`unknown non-variable in "_c2c_decoders.go"`) } value := obj.Decl.(*ast.ValueSpec) sf.Consts = append(sf.Consts, obj.Name) @@ -88,17 +88,17 @@ func main() { DecoderType: obj.Name, }) } else { - panic(`unknown key value in ` + obj.Name + ` in "c2c_decoders.go"`) + panic(`unknown key value in ` + obj.Name + ` in "_c2c_decoders.go"`) } } } else { - panic(`unknown non-map value in "c2c_decoders.go"`) + panic(`unknown non-map value in "_c2c_decoders.go"`) } } } sort.Sort(sf.Decoders) - f, _ := os.OpenFile("c2c_switch.go", os.O_WRONLY|os.O_CREATE|os.O_SYNC|os.O_TRUNC, 0o755) + f, _ := os.OpenFile("c2c_switch.go", os.O_WRONLY|os.O_CREATE|os.O_SYNC|os.O_TRUNC, 0o644) tmpl, err := template.New("template").Parse(codeTemplate) if err != nil { panic(err) diff --git a/client/decoders.go b/client/decoders.go index 32a4d113..22602626 100644 --- a/client/decoders.go +++ b/client/decoders.go @@ -396,7 +396,7 @@ func decodeSvcNotify(c *QQClient, _ *incomingPacketInfo, payload []byte) (interf notify := &jce.RequestPushNotify{} notify.ReadFrom(jce.NewJceReader(data.Map["req_PushNotify"]["PushNotifyPack.RequestPushNotify"][1:])) if decoder, typ := peekC2CDecoder(notify.MsgType); decoder != nil { - // notify.MsgType != 85 && notify.MsgType != 36 moves to c2c_decoders.go [nonSvcNotifyTroopSystemMsgDecoders] + // notify.MsgType != 85 && notify.MsgType != 36 moves to _c2c_decoders.go [nonSvcNotifyTroopSystemMsgDecoders] if typ == troopSystemMsgDecoders { c.exceptAndDispatchGroupSysMsg() return nil, nil From d68da1f65f2fcc0daedd19d2a68066d1c575900c Mon Sep 17 00:00:00 2001 From: Lin <767763591@qq.com> Date: Wed, 27 Oct 2021 10:09:21 +0800 Subject: [PATCH 5/5] =?UTF-8?q?chron:=20=E7=A7=BB=E5=8A=A8=E5=88=B0cmd?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/c2c_processor.go | 2 +- client/{ => cmd}/c2c_switcher.go | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) rename client/{ => cmd}/c2c_switcher.go (97%) diff --git a/client/c2c_processor.go b/client/c2c_processor.go index a6278b25..5888a767 100644 --- a/client/c2c_processor.go +++ b/client/c2c_processor.go @@ -1,6 +1,6 @@ package client -//go:generate go run c2c_switcher.go +//go:generate go run cmd/c2c_switcher.go import ( "fmt" diff --git a/client/c2c_switcher.go b/client/cmd/c2c_switcher.go similarity index 97% rename from client/c2c_switcher.go rename to client/cmd/c2c_switcher.go index 058a6f03..10f49712 100644 --- a/client/c2c_switcher.go +++ b/client/cmd/c2c_switcher.go @@ -1,6 +1,3 @@ -//go:build ignore -// +build ignore - package main import ( @@ -109,8 +106,8 @@ func main() { panic(err) } source, _ := format.Source(buffer.Bytes()) - f.Write(source) - f.Close() + _, _ = f.Write(source) + _ = f.Close() } func mustParseInt(s string) int64 {