diff --git a/client/_c2c_decoders.go b/client/_c2c_decoders.go index 72a72b44..e6d2e7e3 100644 --- a/client/_c2c_decoders.go +++ b/client/_c2c_decoders.go @@ -1,8 +1,11 @@ package client -import "github.com/Mrs4s/MiraiGo/client/pb/msg" +import ( + "github.com/Mrs4s/MiraiGo/client/internal/network" + "github.com/Mrs4s/MiraiGo/client/pb/msg" +) -var privateMsgDecoders = map[int32]func(*QQClient, *msg.Message, *incomingPacketInfo){ +var privateMsgDecoders = map[int32]func(*QQClient, *msg.Message, *network.IncomingPacketInfo){ 9: privateMessageDecoder, 10: privateMessageDecoder, 31: privateMessageDecoder, 79: privateMessageDecoder, 97: privateMessageDecoder, 120: privateMessageDecoder, 132: privateMessageDecoder, 133: privateMessageDecoder, 166: privateMessageDecoder, @@ -10,21 +13,21 @@ var privateMsgDecoders = map[int32]func(*QQClient, *msg.Message, *incomingPacket 208: privatePttDecoder, } -var nonSvcNotifyTroopSystemMsgDecoders = map[int32]func(*QQClient, *msg.Message, *incomingPacketInfo){ +var nonSvcNotifyTroopSystemMsgDecoders = map[int32]func(*QQClient, *msg.Message, *network.IncomingPacketInfo){ 36: troopSystemMessageDecoder, 85: troopSystemMessageDecoder, } -var troopSystemMsgDecoders = map[int32]func(*QQClient, *msg.Message, *incomingPacketInfo){ +var troopSystemMsgDecoders = map[int32]func(*QQClient, *msg.Message, *network.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){ +var sysMsgDecoders = map[int32]func(*QQClient, *msg.Message, *network.IncomingPacketInfo){ 187: systemMessageDecoder, 188: systemMessageDecoder, 189: systemMessageDecoder, 190: systemMessageDecoder, 191: systemMessageDecoder, } // IsSvcNotify -var otherDecoders = map[int32]func(*QQClient, *msg.Message, *incomingPacketInfo){ +var otherDecoders = map[int32]func(*QQClient, *msg.Message, *network.IncomingPacketInfo){ 33: troopAddMemberBroadcastDecoder, 529: msgType0x211Decoder, } diff --git a/client/builders.go b/client/builders.go index 4ca6d771..ebb530e7 100644 --- a/client/builders.go +++ b/client/builders.go @@ -1070,7 +1070,7 @@ func (c *QQClient) buildAppInfoRequestPacket(id string) (uint16, []byte) { body := &qweb.QWebReq{ Seq: proto.Int64(1), Qua: proto.String("V1_AND_SQ_8.4.8_1492_YYB_D"), - Device: proto.String(c.getWebDeviceInfo()), + device: proto.String(c.getWebDeviceInfo()), BusiBuff: b, TraceId: proto.String(fmt.Sprintf("%v_%v_%v", c.Uin, time.Now().Format("0102150405"), rand.Int63())), } diff --git a/client/c2c_processor.go b/client/c2c_processor.go index 652b7df6..beec05ca 100644 --- a/client/c2c_processor.go +++ b/client/c2c_processor.go @@ -9,6 +9,7 @@ import ( "github.com/pkg/errors" "github.com/Mrs4s/MiraiGo/binary" + "github.com/Mrs4s/MiraiGo/client/internal/network" "github.com/Mrs4s/MiraiGo/client/pb" "github.com/Mrs4s/MiraiGo/client/pb/msg" "github.com/Mrs4s/MiraiGo/internal/proto" @@ -27,18 +28,18 @@ type ( ) const ( - GroupSource TempSessionSource = 0 // 来自群聊 - ConsultingSource TempSessionSource = 1 // 来自QQ咨询 - SearchSource TempSessionSource = 2 // 来自查找 - MovieSource TempSessionSource = 3 // 来自QQ电影 - HotChatSource TempSessionSource = 4 // 来自热聊 - SystemMessageSource TempSessionSource = 6 // 来自验证消息 - MultiChatSource TempSessionSource = 7 // 来自多人聊天 - DateSource TempSessionSource = 8 // 来自约会 - AddressBookSource TempSessionSource = 9 // 来自通讯录 + GroupSource TempSessionSource = iota // 来自群聊 + ConsultingSource // 来自QQ咨询 + SearchSource // 来自查找 + MovieSource // 来自QQ电影 + HotChatSource // 来自热聊 + SystemMessageSource // 来自验证消息 + MultiChatSource // 来自多人聊天 + DateSource // 来自约会 + AddressBookSource // 来自通讯录 ) -func (c *QQClient) c2cMessageSyncProcessor(rsp *msg.GetMessageResponse, info *incomingPacketInfo) { +func (c *QQClient) c2cMessageSyncProcessor(rsp *msg.GetMessageResponse, info *network.IncomingPacketInfo) { c.syncCookie = rsp.SyncCookie c.pubAccountCookie = rsp.PubAccountCookie // c.msgCtrlBuf = rsp.MsgCtrlBuf @@ -76,7 +77,7 @@ func (c *QQClient) c2cMessageSyncProcessor(rsp *msg.GetMessageResponse, info *in } } -func (c *QQClient) commMsgProcessor(pMsg *msg.Message, info *incomingPacketInfo) { +func (c *QQClient) commMsgProcessor(pMsg *msg.Message, info *network.IncomingPacketInfo) { strKey := fmt.Sprintf("%d%d%d%d", pMsg.Head.GetFromUin(), pMsg.Head.GetToUin(), pMsg.Head.GetMsgSeq(), pMsg.Head.GetMsgUid()) if _, ok := c.msgSvcCache.GetAndUpdate(strKey, time.Hour); ok { c.Debug("c2c msg %v already exists in cache. skip.", pMsg.Head.GetMsgUid()) @@ -88,7 +89,7 @@ func (c *QQClient) commMsgProcessor(pMsg *msg.Message, info *incomingPacketInfo) return } c.lastC2CMsgTime = int64(pMsg.Head.GetMsgTime()) - if info.Params.bool("init") { + if info.Params.Bool("init") { return } if decoder, _ := peekC2CDecoder(pMsg.Head.GetMsgType()); decoder != nil { @@ -98,7 +99,7 @@ func (c *QQClient) commMsgProcessor(pMsg *msg.Message, info *incomingPacketInfo) } } -func privateMessageDecoder(c *QQClient, pMsg *msg.Message, _ *incomingPacketInfo) { +func privateMessageDecoder(c *QQClient, pMsg *msg.Message, _ *network.IncomingPacketInfo) { switch pMsg.Head.GetC2CCmd() { case 11, 175: // friend msg if pMsg.Head.GetFromUin() == c.Uin { @@ -126,7 +127,7 @@ func privateMessageDecoder(c *QQClient, pMsg *msg.Message, _ *incomingPacketInfo } } -func privatePttDecoder(c *QQClient, pMsg *msg.Message, _ *incomingPacketInfo) { +func privatePttDecoder(c *QQClient, pMsg *msg.Message, _ *network.IncomingPacketInfo) { if pMsg.Body == nil || pMsg.Body.RichText == nil || pMsg.Body.RichText.Ptt == nil { return } @@ -137,7 +138,7 @@ func privatePttDecoder(c *QQClient, pMsg *msg.Message, _ *incomingPacketInfo) { c.dispatchPrivateMessage(c.parsePrivateMessage(pMsg)) } -func tempSessionDecoder(c *QQClient, pMsg *msg.Message, _ *incomingPacketInfo) { +func tempSessionDecoder(c *QQClient, pMsg *msg.Message, _ *network.IncomingPacketInfo) { if pMsg.Head.C2CTmpMsgHead == nil || pMsg.Body == nil { return } @@ -198,7 +199,7 @@ func tempSessionDecoder(c *QQClient, pMsg *msg.Message, _ *incomingPacketInfo) { } } -func troopAddMemberBroadcastDecoder(c *QQClient, pMsg *msg.Message, _ *incomingPacketInfo) { +func troopAddMemberBroadcastDecoder(c *QQClient, pMsg *msg.Message, _ *network.IncomingPacketInfo) { groupJoinLock.Lock() defer groupJoinLock.Unlock() group := c.FindGroupByUin(pMsg.Head.GetFromUin()) @@ -225,13 +226,13 @@ func troopAddMemberBroadcastDecoder(c *QQClient, pMsg *msg.Message, _ *incomingP } } -func systemMessageDecoder(c *QQClient, _ *msg.Message, _ *incomingPacketInfo) { +func systemMessageDecoder(c *QQClient, _ *msg.Message, _ *network.IncomingPacketInfo) { _, pkt := c.buildSystemMsgNewFriendPacket() _ = c.sendPacket(pkt) } -func troopSystemMessageDecoder(c *QQClient, pMsg *msg.Message, info *incomingPacketInfo) { - if !info.Params.bool("used_reg_proxy") && pMsg.Head.GetMsgType() != 85 && pMsg.Head.GetMsgType() != 36 { +func troopSystemMessageDecoder(c *QQClient, pMsg *msg.Message, info *network.IncomingPacketInfo) { + if !info.Params.Bool("used_reg_proxy") && pMsg.Head.GetMsgType() != 85 && pMsg.Head.GetMsgType() != 36 { c.exceptAndDispatchGroupSysMsg() } if len(pMsg.Body.GetMsgContent()) == 0 { @@ -245,7 +246,7 @@ func troopSystemMessageDecoder(c *QQClient, pMsg *msg.Message, info *incomingPac } } -func msgType0x211Decoder(c *QQClient, pMsg *msg.Message, info *incomingPacketInfo) { +func msgType0x211Decoder(c *QQClient, pMsg *msg.Message, info *network.IncomingPacketInfo) { if pMsg.Head.GetC2CCmd() == 6 || pMsg.Head.C2CTmpMsgHead != nil { tempSessionDecoder(c, pMsg, info) } diff --git a/client/c2c_switch.go b/client/c2c_switch.go index de8f735f..160e4005 100644 --- a/client/c2c_switch.go +++ b/client/c2c_switch.go @@ -3,6 +3,7 @@ package client import ( + "github.com/Mrs4s/MiraiGo/client/internal/network" "github.com/Mrs4s/MiraiGo/client/pb/msg" ) @@ -15,7 +16,7 @@ const ( troopSystemMsgDecoders ) -func peekC2CDecoder(msgType int32) (decoder func(*QQClient, *msg.Message, *incomingPacketInfo), decoderType uint8) { +func peekC2CDecoder(msgType int32) (decoder func(*QQClient, *msg.Message, *network.IncomingPacketInfo), decoderType uint8) { switch msgType { case 9: return privateMessageDecoder, privateMsgDecoders diff --git a/client/client.go b/client/client.go index c4786c7f..652054c9 100644 --- a/client/client.go +++ b/client/client.go @@ -17,6 +17,7 @@ import ( "github.com/Mrs4s/MiraiGo/binary/jce" "github.com/Mrs4s/MiraiGo/client/internal/auth" "github.com/Mrs4s/MiraiGo/client/internal/highway" + "github.com/Mrs4s/MiraiGo/client/internal/network" "github.com/Mrs4s/MiraiGo/client/pb/msg" "github.com/Mrs4s/MiraiGo/internal/crypto" "github.com/Mrs4s/MiraiGo/internal/packets" @@ -50,7 +51,7 @@ type QQClient struct { SequenceId atomic.Int32 OutGoingPacketSessionId []byte RandomKey []byte - TCP *utils.TCPListener + TCP *network.TCPListener // todo: combine other protocol state into one struct ConnectTime time.Time // internal state @@ -123,17 +124,17 @@ type QiDianAccountInfo struct { type handlerInfo struct { fun func(i interface{}, err error) dynamic bool - params requestParams + params network.RequestParams } -func (h *handlerInfo) getParams() requestParams { +func (h *handlerInfo) getParams() network.RequestParams { if h == nil { return nil } return h.params } -var decoders = map[string]func(*QQClient, *incomingPacketInfo, []byte) (interface{}, error){ +var decoders = map[string]func(*QQClient, *network.IncomingPacketInfo, []byte) (interface{}, error){ "wtlogin.login": decodeLoginResponse, "wtlogin.exchange_emp": decodeExchangeEmpResponse, "wtlogin.trans_emp": decodeTransEmpResponse, @@ -180,7 +181,7 @@ func NewClientMd5(uin int64, passwordMd5 [16]byte) *QQClient { AllowSlider: true, RandomKey: make([]byte, 16), OutGoingPacketSessionId: []byte{0x02, 0xB0, 0x5B, 0x8B}, - TCP: &utils.TCPListener{}, + TCP: &network.TCPListener{}, sigInfo: &auth.SigInfo{}, eventHandlers: &eventHandlers{}, msgSvcCache: utils.NewCache(time.Second * 15), @@ -440,7 +441,7 @@ func (c *QQClient) init(tokenLogin bool) error { _, _ = c.sendAndWait(c.buildConnKeyRequestPacket()) // big data key 如果等待 config push 的话时间来不及 } seq, pkt := c.buildGetMessageRequestPacket(msg.SyncFlag_START, time.Now().Unix()) - _, _ = c.sendAndWait(seq, pkt, requestParams{"used_reg_proxy": true, "init": true}) + _, _ = c.sendAndWait(seq, pkt, network.RequestParams{"used_reg_proxy": true, "init": true}) c.syncChannelFirstView() return nil } @@ -802,7 +803,7 @@ func (c *QQClient) doHeartbeat() { sso := packets.BuildSsoPacket(seq, c.version.AppId, c.version.SubAppId, "Heartbeat.Alive", c.deviceInfo.IMEI, EmptyBytes, c.OutGoingPacketSessionId, EmptyBytes, c.ksid) packet := packets.BuildLoginPacket(c.Uin, 0, EmptyBytes, sso, EmptyBytes) _, err := c.sendAndWait(seq, packet) - if errors.Is(err, utils.ErrConnectionClosed) { + if errors.Is(err, network.ErrConnectionClosed) { continue } times++ diff --git a/client/decoders.go b/client/decoders.go index 1daaa082..ee6ea8d6 100644 --- a/client/decoders.go +++ b/client/decoders.go @@ -14,6 +14,7 @@ import ( "github.com/Mrs4s/MiraiGo/binary" "github.com/Mrs4s/MiraiGo/binary/jce" + "github.com/Mrs4s/MiraiGo/client/internal/network" "github.com/Mrs4s/MiraiGo/client/pb" "github.com/Mrs4s/MiraiGo/client/pb/cmd0x352" "github.com/Mrs4s/MiraiGo/client/pb/cmd0x6ff" @@ -31,7 +32,7 @@ var ( ) // wtlogin.login -func decodeLoginResponse(c *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeLoginResponse(c *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { reader := binary.NewReader(payload) reader.ReadUInt16() // sub command t := reader.ReadByte() @@ -179,7 +180,7 @@ func decodeLoginResponse(c *QQClient, _ *incomingPacketInfo, payload []byte) (in } // StatSvc.register -func decodeClientRegisterResponse(c *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeClientRegisterResponse(c *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { request := &jce.RequestPacket{} request.ReadFrom(jce.NewJceReader(payload)) data := &jce.RequestDataVersion2{} @@ -196,7 +197,7 @@ func decodeClientRegisterResponse(c *QQClient, _ *incomingPacketInfo, payload [] } // wtlogin.exchange_emp -func decodeExchangeEmpResponse(c *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeExchangeEmpResponse(c *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { reader := binary.NewReader(payload) cmd := reader.ReadUInt16() t := reader.ReadByte() @@ -216,7 +217,7 @@ func decodeExchangeEmpResponse(c *QQClient, _ *incomingPacketInfo, payload []byt } // wtlogin.trans_emp -func decodeTransEmpResponse(c *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeTransEmpResponse(c *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { if len(payload) < 48 { return nil, errors.New("missing payload length") } @@ -299,7 +300,7 @@ func decodeTransEmpResponse(c *QQClient, _ *incomingPacketInfo, payload []byte) } // ConfigPushSvc.PushReq -func decodePushReqPacket(c *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodePushReqPacket(c *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { request := &jce.RequestPacket{} request.ReadFrom(jce.NewJceReader(payload)) data := &jce.RequestDataVersion2{} @@ -369,7 +370,7 @@ func decodePushReqPacket(c *QQClient, _ *incomingPacketInfo, payload []byte) (in } // MessageSvc.PbGetMsg -func decodeMessageSvcPacket(c *QQClient, info *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeMessageSvcPacket(c *QQClient, info *network.IncomingPacketInfo, payload []byte) (interface{}, error) { rsp := msg.GetMessageResponse{} err := proto.Unmarshal(payload, &rsp) if err != nil { @@ -380,7 +381,7 @@ func decodeMessageSvcPacket(c *QQClient, info *incomingPacketInfo, payload []byt } // MessageSvc.PushNotify -func decodeSvcNotify(c *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeSvcNotify(c *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { request := &jce.RequestPacket{} request.ReadFrom(jce.NewJceReader(payload[4:])) data := &jce.RequestDataVersion2{} @@ -407,7 +408,7 @@ func decodeSvcNotify(c *QQClient, _ *incomingPacketInfo, payload []byte) (interf } // SummaryCard.ReqSummaryCard -func decodeSummaryCardResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeSummaryCardResponse(_ *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { request := &jce.RequestPacket{} request.ReadFrom(jce.NewJceReader(payload)) data := &jce.RequestDataVersion2{} @@ -455,7 +456,7 @@ func decodeSummaryCardResponse(_ *QQClient, _ *incomingPacketInfo, payload []byt } // friendlist.getFriendGroupList -func decodeFriendGroupListResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeFriendGroupListResponse(_ *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { request := &jce.RequestPacket{} request.ReadFrom(jce.NewJceReader(payload)) data := &jce.RequestDataVersion3{} @@ -480,7 +481,7 @@ func decodeFriendGroupListResponse(_ *QQClient, _ *incomingPacketInfo, payload [ } // friendlist.delFriend -func decodeFriendDeleteResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeFriendDeleteResponse(_ *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { request := &jce.RequestPacket{} request.ReadFrom(jce.NewJceReader(payload)) data := &jce.RequestDataVersion3{} @@ -493,7 +494,7 @@ func decodeFriendDeleteResponse(_ *QQClient, _ *incomingPacketInfo, payload []by } // friendlist.GetTroopListReqV2 -func decodeGroupListResponse(c *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeGroupListResponse(c *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { request := &jce.RequestPacket{} request.ReadFrom(jce.NewJceReader(payload)) data := &jce.RequestDataVersion3{} @@ -525,7 +526,7 @@ func decodeGroupListResponse(c *QQClient, _ *incomingPacketInfo, payload []byte) } // friendlist.GetTroopMemberListReq -func decodeGroupMemberListResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeGroupMemberListResponse(_ *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { request := &jce.RequestPacket{} request.ReadFrom(jce.NewJceReader(payload)) data := &jce.RequestDataVersion3{} @@ -561,7 +562,7 @@ func decodeGroupMemberListResponse(_ *QQClient, _ *incomingPacketInfo, payload [ } // group_member_card.get_group_member_card_info -func decodeGroupMemberInfoResponse(c *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeGroupMemberInfoResponse(c *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { rsp := pb.GroupMemberRspBody{} if err := proto.Unmarshal(payload, &rsp); err != nil { return nil, errors.Wrap(err, "failed to unmarshal protobuf message") @@ -594,7 +595,7 @@ func decodeGroupMemberInfoResponse(c *QQClient, _ *incomingPacketInfo, payload [ } // LongConn.OffPicUp -func decodeOffPicUpResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeOffPicUpResponse(_ *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { rsp := cmd0x352.RspBody{} if err := proto.Unmarshal(payload, &rsp); err != nil { return nil, errors.Wrap(err, "failed to unmarshal protobuf message") @@ -632,7 +633,7 @@ func decodeOffPicUpResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) } // OnlinePush.PbPushTransMsg -func decodeOnlinePushTransPacket(c *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeOnlinePushTransPacket(c *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { info := msg.TransMsgInfo{} err := proto.Unmarshal(payload, &info) if err != nil { @@ -735,7 +736,7 @@ func decodeOnlinePushTransPacket(c *QQClient, _ *incomingPacketInfo, payload []b } // ProfileService.Pb.ReqSystemMsgNew.Friend -func decodeSystemMsgFriendPacket(c *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeSystemMsgFriendPacket(c *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { rsp := structmsg.RspSystemMsgNew{} if err := proto.Unmarshal(payload, &rsp); err != nil { return nil, errors.Wrap(err, "failed to unmarshal protobuf message") @@ -757,7 +758,7 @@ func decodeSystemMsgFriendPacket(c *QQClient, _ *incomingPacketInfo, payload []b } // MessageSvc.PushForceOffline -func decodeForceOfflinePacket(c *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeForceOfflinePacket(c *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { request := &jce.RequestPacket{} request.ReadFrom(jce.NewJceReader(payload)) data := &jce.RequestDataVersion2{} @@ -770,7 +771,7 @@ func decodeForceOfflinePacket(c *QQClient, _ *incomingPacketInfo, payload []byte } // StatSvc.ReqMSFOffline -func decodeMSFOfflinePacket(c *QQClient, _ *incomingPacketInfo, _ []byte) (interface{}, error) { +func decodeMSFOfflinePacket(c *QQClient, _ *network.IncomingPacketInfo, _ []byte) (interface{}, error) { // c.lastLostMsg = "服务器端强制下线." c.Disconnect() // 这个decoder不能消耗太多时间, event另起线程处理 @@ -779,7 +780,7 @@ func decodeMSFOfflinePacket(c *QQClient, _ *incomingPacketInfo, _ []byte) (inter } // OidbSvc.0xd79 -func decodeWordSegmentation(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeWordSegmentation(_ *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { pkg := oidb.OIDBSSOPkg{} rsp := &oidb.D79RspBody{} if err := proto.Unmarshal(payload, &pkg); err != nil { @@ -794,7 +795,7 @@ func decodeWordSegmentation(_ *QQClient, _ *incomingPacketInfo, payload []byte) return nil, errors.New("no word received") } -func decodeSidExpiredPacket(c *QQClient, i *incomingPacketInfo, _ []byte) (interface{}, error) { +func decodeSidExpiredPacket(c *QQClient, i *network.IncomingPacketInfo, _ []byte) (interface{}, error) { _, err := c.sendAndWait(c.buildRequestChangeSigPacket(3554528)) if err != nil { return nil, errors.Wrap(err, "resign client error") @@ -824,6 +825,6 @@ func decodeAppInfoResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) ( } */ -func ignoreDecoder(_ *QQClient, _ *incomingPacketInfo, _ []byte) (interface{}, error) { +func ignoreDecoder(_ *QQClient, _ *network.IncomingPacketInfo, _ []byte) (interface{}, error) { return nil, nil } diff --git a/client/face.go b/client/face.go index 674ec9e6..dca3a22f 100644 --- a/client/face.go +++ b/client/face.go @@ -5,6 +5,7 @@ import ( "github.com/pkg/errors" + "github.com/Mrs4s/MiraiGo/client/internal/network" "github.com/Mrs4s/MiraiGo/client/pb/faceroam" "github.com/Mrs4s/MiraiGo/internal/proto" ) @@ -40,7 +41,7 @@ func (c *QQClient) buildFaceroamRequestPacket() (uint16, []byte) { return c.uniPacket("Faceroam.OpReq", payload) } -func decodeFaceroamResponse(c *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeFaceroamResponse(c *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { rsp := faceroam.FaceroamRspBody{} if err := proto.Unmarshal(payload, &rsp); err != nil { return nil, errors.Wrap(err, "failed to unmarshal protobuf message") diff --git a/client/global.go b/client/global.go index 391dfe99..13ddcc13 100644 --- a/client/global.go +++ b/client/global.go @@ -30,14 +30,6 @@ type ( groupMessageBuilder struct { MessageSlices []*msg.Message } - - incomingPacketInfo struct { - CommandName string - SequenceId uint16 - Params requestParams - } - - requestParams map[string]interface{} ) var SystemDeviceInfo = &DeviceInfo{ @@ -308,28 +300,6 @@ func genLongTemplate(resID, brief string, ts int64) *message.ServiceElement { } } -func (p requestParams) bool(k string) bool { - if p == nil { - return false - } - i, ok := p[k] - if !ok { - return false - } - return i.(bool) -} - -func (p requestParams) int32(k string) int32 { - if p == nil { - return 0 - } - i, ok := p[k] - if !ok { - return 0 - } - return i.(int32) -} - func (c *QQClient) getWebDeviceInfo() (i string) { qimei := strings.ToLower(utils.RandomString(36)) i += fmt.Sprintf("i=%v&imsi=&mac=%v&m=%v&o=%v&", c.deviceInfo.IMEI, utils.B2S(c.deviceInfo.MacAddress), utils.B2S(c.deviceInfo.Device), utils.B2S(c.deviceInfo.Version.Release)) diff --git a/client/group_file.go b/client/group_file.go index d72d955a..c2799a15 100644 --- a/client/group_file.go +++ b/client/group_file.go @@ -12,6 +12,7 @@ import ( "github.com/pkg/errors" "github.com/Mrs4s/MiraiGo/client/internal/highway" + "github.com/Mrs4s/MiraiGo/client/internal/network" "github.com/Mrs4s/MiraiGo/client/pb/exciting" "github.com/Mrs4s/MiraiGo/client/pb/oidb" "github.com/Mrs4s/MiraiGo/internal/proto" @@ -439,7 +440,7 @@ func (c *QQClient) buildGroupFileDeleteReqPacket(groupCode int64, parentFolderId return c.uniPacket("OidbSvc.0x6d6_3", payload) } -func decodeOIDB6d81Response(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeOIDB6d81Response(_ *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { pkg := oidb.OIDBSSOPkg{} rsp := oidb.D6D8RspBody{} if err := proto.Unmarshal(payload, &pkg); err != nil { @@ -452,7 +453,7 @@ func decodeOIDB6d81Response(_ *QQClient, _ *incomingPacketInfo, payload []byte) } // OidbSvc.0x6d6_2 -func decodeOIDB6d62Response(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeOIDB6d62Response(_ *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { pkg := oidb.OIDBSSOPkg{} rsp := oidb.D6D6RspBody{} if err := proto.Unmarshal(payload, &pkg); err != nil { @@ -469,7 +470,7 @@ func decodeOIDB6d62Response(_ *QQClient, _ *incomingPacketInfo, payload []byte) return fmt.Sprintf("http://%s/ftn_handler/%s/", ip, url), nil } -func decodeOIDB6d63Response(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeOIDB6d63Response(_ *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { pkg := oidb.OIDBSSOPkg{} rsp := oidb.D6D6RspBody{} if err := proto.Unmarshal(payload, &pkg); err != nil { @@ -484,7 +485,7 @@ func decodeOIDB6d63Response(_ *QQClient, _ *incomingPacketInfo, payload []byte) return rsp.DeleteFileRsp.GetClientWording(), nil } -func decodeOIDB6d60Response(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeOIDB6d60Response(_ *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { pkg := oidb.OIDBSSOPkg{} rsp := oidb.D6D6RspBody{} if err := proto.Unmarshal(payload, &pkg); err != nil { @@ -496,7 +497,7 @@ func decodeOIDB6d60Response(_ *QQClient, _ *incomingPacketInfo, payload []byte) return rsp.UploadFileRsp, nil } -func decodeOIDB6d7Response(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeOIDB6d7Response(_ *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { pkg := oidb.OIDBSSOPkg{} rsp := oidb.D6D7RspBody{} if err := proto.Unmarshal(payload, &pkg); err != nil { diff --git a/client/group_info.go b/client/group_info.go index da71e9fd..e42ee7c3 100644 --- a/client/group_info.go +++ b/client/group_info.go @@ -15,6 +15,7 @@ import ( "github.com/Mrs4s/MiraiGo/binary" "github.com/Mrs4s/MiraiGo/binary/jce" + "github.com/Mrs4s/MiraiGo/client/internal/network" "github.com/Mrs4s/MiraiGo/client/pb/oidb" "github.com/Mrs4s/MiraiGo/client/pb/profilecard" "github.com/Mrs4s/MiraiGo/internal/proto" @@ -187,7 +188,7 @@ func (c *QQClient) buildGroupSearchPacket(keyword string) (uint16, []byte) { } // SummaryCard.ReqSearch -func decodeGroupSearchResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeGroupSearchResponse(_ *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { request := &jce.RequestPacket{} request.ReadFrom(jce.NewJceReader(payload)) data := &jce.RequestDataVersion2{} @@ -225,7 +226,7 @@ func decodeGroupSearchResponse(_ *QQClient, _ *incomingPacketInfo, payload []byt } // OidbSvc.0x88d_0 -func decodeGroupInfoResponse(c *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeGroupInfoResponse(c *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { pkg := oidb.OIDBSSOPkg{} rsp := oidb.D88DRspBody{} if err := proto.Unmarshal(payload, &pkg); err != nil { diff --git a/client/group_msg.go b/client/group_msg.go index f00b6dbd..3a35f250 100644 --- a/client/group_msg.go +++ b/client/group_msg.go @@ -14,6 +14,7 @@ import ( "github.com/pkg/errors" "github.com/Mrs4s/MiraiGo/client/internal/highway" + "github.com/Mrs4s/MiraiGo/client/internal/network" "github.com/Mrs4s/MiraiGo/client/pb/longmsg" "github.com/Mrs4s/MiraiGo/client/pb/msg" "github.com/Mrs4s/MiraiGo/client/pb/multimsg" @@ -80,7 +81,7 @@ func (c *QQClient) SendGroupForwardMessage(groupCode int64, m *message.ForwardEl // GetGroupMessages 从服务器获取历史信息 func (c *QQClient) GetGroupMessages(groupCode, beginSeq, endSeq int64) ([]*message.GroupMessage, error) { seq, pkt := c.buildGetGroupMsgRequest(groupCode, beginSeq, endSeq) - i, err := c.sendAndWait(seq, pkt, requestParams{"raw": false}) + i, err := c.sendAndWait(seq, pkt, network.RequestParams{"raw": false}) if err != nil { return nil, err } @@ -296,7 +297,7 @@ func (c *QQClient) buildAtAllRemainRequestPacket(groupCode int64) (uint16, []byt } // OnlinePush.PbPushGroupMsg -func decodeGroupMessagePacket(c *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeGroupMessagePacket(c *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { pkt := msg.PushMessagePacket{} err := proto.Unmarshal(payload, &pkt) if err != nil { @@ -337,7 +338,7 @@ func decodeGroupMessagePacket(c *QQClient, _ *incomingPacketInfo, payload []byte return nil, nil } -func decodeMsgSendResponse(c *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeMsgSendResponse(c *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { rsp := msg.SendMessageResponse{} if err := proto.Unmarshal(payload, &rsp); err != nil { return nil, errors.Wrap(err, "failed to unmarshal protobuf message") @@ -352,7 +353,7 @@ func decodeMsgSendResponse(c *QQClient, _ *incomingPacketInfo, payload []byte) ( return nil, nil } -func decodeGetGroupMsgResponse(c *QQClient, info *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeGetGroupMsgResponse(c *QQClient, info *network.IncomingPacketInfo, payload []byte) (interface{}, error) { rsp := msg.GetGroupMsgResp{} if err := proto.Unmarshal(payload, &rsp); err != nil { return nil, errors.Wrap(err, "failed to unmarshal protobuf message") @@ -366,7 +367,7 @@ func decodeGetGroupMsgResponse(c *QQClient, info *incomingPacketInfo, payload [] if m.Head.FromUin == nil { continue } - if m.Content != nil && m.Content.GetPkgNum() > 1 && !info.Params.bool("raw") { + if m.Content != nil && m.Content.GetPkgNum() > 1 && !info.Params.Bool("raw") { if m.Content.GetPkgIndex() == 0 { c.Debug("build fragmented message from history") i := m.Head.GetMsgSeq() - m.Content.GetPkgNum() @@ -374,7 +375,7 @@ func decodeGetGroupMsgResponse(c *QQClient, info *incomingPacketInfo, payload [] for { end := int32(math.Min(float64(i+19), float64(m.Head.GetMsgSeq()+m.Content.GetPkgNum()))) seq, pkt := c.buildGetGroupMsgRequest(m.Head.GroupInfo.GetGroupCode(), int64(i), int64(end)) - data, err := c.sendAndWait(seq, pkt, requestParams{"raw": true}) + data, err := c.sendAndWait(seq, pkt, network.RequestParams{"raw": true}) if err != nil { return nil, errors.Wrap(err, "build fragmented message error") } @@ -401,7 +402,7 @@ func decodeGetGroupMsgResponse(c *QQClient, info *incomingPacketInfo, payload [] return ret, nil } -func decodeAtAllRemainResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeAtAllRemainResponse(_ *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { pkg := oidb.OIDBSSOPkg{} rsp := oidb.D8A7RspBody{} if err := proto.Unmarshal(payload, &pkg); err != nil { @@ -597,7 +598,7 @@ func (c *QQClient) buildEssenceMsgOperatePacket(groupCode int64, msgSeq, msgRand } // OidbSvc.0xeac_1/2 -func decodeEssenceMsgResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeEssenceMsgResponse(_ *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { pkg := oidb.OIDBSSOPkg{} rsp := &oidb.EACRspBody{} if err := proto.Unmarshal(payload, &pkg); err != nil { diff --git a/client/guild.go b/client/guild.go index 7cb76426..a1852ae4 100644 --- a/client/guild.go +++ b/client/guild.go @@ -7,6 +7,7 @@ import ( "strconv" "time" + "github.com/Mrs4s/MiraiGo/client/internal/network" "github.com/Mrs4s/MiraiGo/topic" "github.com/Mrs4s/MiraiGo/client/pb/qweb" @@ -737,7 +738,7 @@ func (c *QQClient) buildSyncChannelFirstViewPacket() (uint16, []byte) { return c.uniPacket("trpc.group_pro.synclogic.SyncLogic.SyncFirstView", payload) } -func decodeGuildPushFirstView(c *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeGuildPushFirstView(c *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { firstViewMsg := new(channel.FirstViewMsg) if err := proto.Unmarshal(payload, firstViewMsg); err != nil { return nil, errors.Wrap(err, "failed to unmarshal protobuf message") diff --git a/client/guild_eventflow.go b/client/guild_eventflow.go index 4a7d36b0..b04efe22 100644 --- a/client/guild_eventflow.go +++ b/client/guild_eventflow.go @@ -8,6 +8,7 @@ import ( "github.com/pkg/errors" + "github.com/Mrs4s/MiraiGo/client/internal/network" "github.com/Mrs4s/MiraiGo/client/pb/channel" "github.com/Mrs4s/MiraiGo/client/pb/msg" "github.com/Mrs4s/MiraiGo/internal/proto" @@ -26,7 +27,7 @@ type tipsPushInfo struct { ChannelId uint64 } -func decodeGuildEventFlowPacket(c *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeGuildEventFlowPacket(c *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { push := new(channel.MsgOnlinePush) if err := proto.Unmarshal(payload, push); err != nil { return nil, errors.Wrap(err, "failed to unmarshal protobuf message") diff --git a/client/guild_msg.go b/client/guild_msg.go index 61ab8120..c1bb4d4a 100644 --- a/client/guild_msg.go +++ b/client/guild_msg.go @@ -12,6 +12,7 @@ import ( "github.com/Mrs4s/MiraiGo/binary" "github.com/Mrs4s/MiraiGo/client/internal/highway" + "github.com/Mrs4s/MiraiGo/client/internal/network" "github.com/Mrs4s/MiraiGo/client/pb/channel" "github.com/Mrs4s/MiraiGo/client/pb/cmd0x388" "github.com/Mrs4s/MiraiGo/client/pb/msg" @@ -290,7 +291,7 @@ func decodeGuildMessageEmojiReactions(content *channel.ChannelMsgContent) (r []* return } -func decodeGuildImageStoreResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeGuildImageStoreResponse(_ *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { body := new(cmd0x388.D388RspBody) if err := proto.Unmarshal(payload, body); err != nil { return nil, errors.Wrap(err, "failed to unmarshal protobuf message") diff --git a/client/image.go b/client/image.go index e473a147..e3736b9f 100644 --- a/client/image.go +++ b/client/image.go @@ -14,6 +14,7 @@ import ( "github.com/Mrs4s/MiraiGo/binary" "github.com/Mrs4s/MiraiGo/client/internal/highway" + "github.com/Mrs4s/MiraiGo/client/internal/network" "github.com/Mrs4s/MiraiGo/client/pb/cmd0x388" highway2 "github.com/Mrs4s/MiraiGo/client/pb/highway" "github.com/Mrs4s/MiraiGo/client/pb/oidb" @@ -337,7 +338,7 @@ func (c *QQClient) buildImageOcrRequestPacket(url, md5 string, size, weight, hei } // ImgStore.GroupPicUp -func decodeGroupImageStoreResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeGroupImageStoreResponse(_ *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { pkt := cmd0x388.D388RspBody{} err := proto.Unmarshal(payload, &pkt) if err != nil { @@ -364,7 +365,7 @@ func decodeGroupImageStoreResponse(_ *QQClient, _ *incomingPacketInfo, payload [ }, nil } -func decodeGroupImageDownloadResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeGroupImageDownloadResponse(_ *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { pkt := cmd0x388.D388RspBody{} if err := proto.Unmarshal(payload, &pkt); err != nil { return nil, errors.Wrap(err, "unmarshal protobuf message error") @@ -379,7 +380,7 @@ func decodeGroupImageDownloadResponse(_ *QQClient, _ *incomingPacketInfo, payloa } // OidbSvc.0xe07_0 -func decodeImageOcrResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeImageOcrResponse(_ *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { pkg := oidb.OIDBSSOPkg{} rsp := oidb.DE07RspBody{} if err := proto.Unmarshal(payload, &pkg); err != nil { diff --git a/client/internal/auth/auth.go b/client/internal/auth/auth.go index 9ac6cfbb..65d45a6d 100644 --- a/client/internal/auth/auth.go +++ b/client/internal/auth/auth.go @@ -27,8 +27,8 @@ type AppVersion struct { Protocol Protocol } -func (p Protocol) Version() *AppVersion { - switch p { +func (i Protocol) Version() *AppVersion { + switch i { case AndroidPhone: // Dumped by mirai from qq android v8.8.38 return &AppVersion{ ApkId: "com.tencent.mobileqq", @@ -42,7 +42,7 @@ func (p Protocol) Version() *AppVersion { MiscBitmap: 184024956, SubSigmap: 0x10400, MainSigMap: 34869472, - Protocol: p, + Protocol: i, } case AndroidWatch: return &AppVersion{ @@ -57,7 +57,7 @@ func (p Protocol) Version() *AppVersion { MiscBitmap: 16252796, SubSigmap: 0x10400, MainSigMap: 34869472, - Protocol: p, + Protocol: i, } case IPad: return &AppVersion{ @@ -72,7 +72,7 @@ func (p Protocol) Version() *AppVersion { MiscBitmap: 150470524, SubSigmap: 66560, MainSigMap: 1970400, - Protocol: p, + Protocol: i, } case MacOS: return &AppVersion{ @@ -87,7 +87,7 @@ func (p Protocol) Version() *AppVersion { MiscBitmap: 150470524, SubSigmap: 66560, MainSigMap: 1970400, - Protocol: p, + Protocol: i, } case QiDian: return &AppVersion{ @@ -102,7 +102,7 @@ func (p Protocol) Version() *AppVersion { MiscBitmap: 49807228, SubSigmap: 66560, MainSigMap: 34869472, - Protocol: p, + Protocol: i, } } return nil diff --git a/utils/connection.go b/client/internal/network/conn.go similarity index 99% rename from utils/connection.go rename to client/internal/network/conn.go index 77f66da8..a43614c1 100644 --- a/utils/connection.go +++ b/client/internal/network/conn.go @@ -1,4 +1,4 @@ -package utils +package network import ( "encoding/binary" diff --git a/client/internal/network/packet.go b/client/internal/network/packet.go new file mode 100644 index 00000000..bccfe152 --- /dev/null +++ b/client/internal/network/packet.go @@ -0,0 +1,31 @@ +package network + +type IncomingPacketInfo struct { + CommandName string + SequenceId uint16 + Params RequestParams +} + +type RequestParams map[string]interface{} + +func (p RequestParams) Bool(k string) bool { + if p == nil { + return false + } + i, ok := p[k] + if !ok { + return false + } + return i.(bool) +} + +func (p RequestParams) Int32(k string) int32 { + if p == nil { + return 0 + } + i, ok := p[k] + if !ok { + return 0 + } + return i.(int32) +} diff --git a/client/internal/network/request.go b/client/internal/network/request.go new file mode 100644 index 00000000..88ff01f0 --- /dev/null +++ b/client/internal/network/request.go @@ -0,0 +1,27 @@ +package network + +type RequestType uint32 + +const ( + RequestTypeLogin = 0x0A + RequestTypeSimple = 0x0B +) + +var emptyKey = make([]byte, 16) + +type EncryptType uint32 + +const ( + EncryptTypeNoEncrypt EncryptType = iota // 0x00 + EncryptTypeD2Key // 0x01 + EncryptTypeEmptyKey // 0x02 +) + +type Request struct { + Type RequestType + EncryptType EncryptType + SequenceID int32 + Uin int64 + Method string + Body []byte +} diff --git a/client/internal/network/transport.go b/client/internal/network/transport.go new file mode 100644 index 00000000..4bc4de87 --- /dev/null +++ b/client/internal/network/transport.go @@ -0,0 +1,127 @@ +package network + +import ( + "strconv" + "sync" + + "github.com/Mrs4s/MiraiGo/binary" + "github.com/Mrs4s/MiraiGo/client/internal/auth" +) + +// Transport is a network transport. +type Transport struct { + sessionMu sync.Mutex + // todo: combine session fields to a struct + tgt []byte + d2key []byte + sessionID []byte + ksid []byte + + version *auth.AppVersion + device *auth.Device + + // connection + conn *TCPListener +} + +func (t *Transport) packBody(req *Request, w *binary.Writer) { + w.WriteIntLvPacket(4, func(writer *binary.Writer) { + if req.Type == RequestTypeLogin { + writer.WriteUInt32(uint32(req.SequenceID)) + writer.WriteUInt32(t.version.AppId) + writer.WriteUInt32(t.version.SubAppId) + writer.Write([]byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}) + if len(t.tgt) == 0 || len(t.tgt) == 4 { + writer.WriteUInt32(0x04) + } else { + writer.WriteUInt32(uint32(len(t.tgt) + 4)) + writer.Write(t.tgt) + } + } + + writer.WriteString(req.Method) + writer.WriteUInt32(uint32(len(t.sessionID) + 4)) + w.Write(t.sessionID) + if req.Type == RequestTypeLogin { + writer.WriteString(t.device.IMEI) + writer.WriteUInt32(0x04) + { + writer.WriteUInt16(uint16(len(t.ksid)) + 2) + writer.Write(t.ksid) + } + } + writer.WriteUInt32(0x04) + }) + + w.WriteUInt32(uint32(len(req.Body) + 4)) + w.Write(req.Body) +} + +func (t *Transport) Send(req *Request) error { + // todo: return response + head := binary.NewWriterF(func(w *binary.Writer) { + w.WriteUInt32(uint32(req.Type)) + w.WriteUInt32(uint32(req.EncryptType)) + switch req.Type { + case RequestTypeLogin: + switch req.EncryptType { + case EncryptTypeD2Key: + w.WriteUInt32(uint32(len(t.d2key) + 4)) + w.Write(t.d2key) + default: + w.WriteUInt32(4) + } + case RequestTypeSimple: + w.WriteUInt32(uint32(req.SequenceID)) + } + w.WriteString(strconv.FormatInt(req.Uin, 10)) + }) + + w := binary.SelectWriter() + defer binary.PutWriter(w) + t.packBody(req, w) + body := w.Bytes() + + // encrypt body + switch req.EncryptType { + case EncryptTypeD2Key: + body = binary.NewTeaCipher(t.d2key).Encrypt(body) + case EncryptTypeEmptyKey: + body = binary.NewTeaCipher(emptyKey).Encrypt(body) + } + + w2 := binary.SelectWriter() + defer binary.PutWriter(w2) + w2.WriteUInt32(uint32(len(head) + len(body) + 4)) + w2.Write(head) + w2.Write(body) + err := t.conn.Write(w2.Bytes()) + if err != nil { + return err + } + return nil +} + +func (t *Transport) parse(head []byte) *Request { + req := new(Request) + r := binary.NewReader(head) + req.Type = RequestType(r.ReadInt32()) + encryptType := EncryptType(r.ReadInt32()) + switch req.Type { + case RequestTypeLogin: + // req.Key = r.ReadBytes(int(encryptType)) + case RequestTypeSimple: + req.SequenceID = r.ReadInt32() + } + _ = r.ReadString() // req.Uin + body := r.ReadAvailable() + switch encryptType { + case EncryptTypeNoEncrypt: + req.Body = body + case EncryptTypeD2Key: + req.Body = binary.NewTeaCipher(t.d2key).Decrypt(body) + case EncryptTypeEmptyKey: + req.Body = binary.NewTeaCipher(emptyKey).Decrypt(body) + } + return req +} diff --git a/client/multimsg.go b/client/multimsg.go index beace7d4..4798a6de 100644 --- a/client/multimsg.go +++ b/client/multimsg.go @@ -8,6 +8,7 @@ import ( "github.com/pkg/errors" "github.com/Mrs4s/MiraiGo/binary" + "github.com/Mrs4s/MiraiGo/client/internal/network" "github.com/Mrs4s/MiraiGo/client/pb/longmsg" "github.com/Mrs4s/MiraiGo/client/pb/msg" "github.com/Mrs4s/MiraiGo/client/pb/multimsg" @@ -44,7 +45,7 @@ func (c *QQClient) buildMultiApplyUpPacket(data, hash []byte, buType int32, grou } // MultiMsg.ApplyUp -func decodeMultiApplyUpResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeMultiApplyUpResponse(_ *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { body := multimsg.MultiRspBody{} if err := proto.Unmarshal(payload, &body); err != nil { return nil, errors.Wrap(err, "failed to unmarshal protobuf message") @@ -84,7 +85,7 @@ func (c *QQClient) buildMultiApplyDownPacket(resID string) (uint16, []byte) { } // MultiMsg.ApplyDown -func decodeMultiApplyDownResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeMultiApplyDownResponse(_ *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { body := multimsg.MultiRspBody{} if err := proto.Unmarshal(payload, &body); err != nil { return nil, errors.Wrap(err, "failed to unmarshal protobuf message") diff --git a/client/network.go b/client/network.go index 4cea8a50..fc5eab50 100644 --- a/client/network.go +++ b/client/network.go @@ -8,6 +8,7 @@ import ( "github.com/pkg/errors" + "github.com/Mrs4s/MiraiGo/client/internal/network" "github.com/Mrs4s/MiraiGo/internal/packets" "github.com/Mrs4s/MiraiGo/message" "github.com/Mrs4s/MiraiGo/utils" @@ -146,13 +147,13 @@ func (c *QQClient) Disconnect() { } // sendAndWait 向服务器发送一个数据包, 并等待返回 -func (c *QQClient) sendAndWait(seq uint16, pkt []byte, params ...requestParams) (interface{}, error) { +func (c *QQClient) sendAndWait(seq uint16, pkt []byte, params ...network.RequestParams) (interface{}, error) { type T struct { Response interface{} Error error } ch := make(chan T, 1) - var p requestParams + var p network.RequestParams if len(params) != 0 { p = params[0] @@ -248,14 +249,14 @@ func (c *QQClient) sendAndWaitDynamic(seq uint16, pkt []byte) ([]byte, error) { } // plannedDisconnect 计划中断线事件 -func (c *QQClient) plannedDisconnect(_ *utils.TCPListener) { +func (c *QQClient) plannedDisconnect(_ *network.TCPListener) { c.Debug("planned disconnect.") c.stat.DisconnectTimes.Add(1) c.Online.Store(false) } // unexpectedDisconnect 非预期断线事件 -func (c *QQClient) unexpectedDisconnect(_ *utils.TCPListener, e error) { +func (c *QQClient) unexpectedDisconnect(_ *network.TCPListener, e error) { c.Error("unexpected disconnect: %v", e) c.stat.DisconnectTimes.Add(1) c.Online.Store(false) @@ -331,7 +332,7 @@ func (c *QQClient) netLoop() { var decoded interface{} decoded = pkt.Payload if info == nil || !info.dynamic { - decoded, err = decoder(c, &incomingPacketInfo{ + decoded, err = decoder(c, &network.IncomingPacketInfo{ SequenceId: pkt.SequenceId, CommandName: pkt.CommandName, Params: info.getParams(), diff --git a/client/offline_file.go b/client/offline_file.go index ca4986c2..0fd8099e 100644 --- a/client/offline_file.go +++ b/client/offline_file.go @@ -3,6 +3,7 @@ package client import ( "github.com/pkg/errors" + "github.com/Mrs4s/MiraiGo/client/internal/network" "github.com/Mrs4s/MiraiGo/client/pb/cmd0x346" "github.com/Mrs4s/MiraiGo/internal/proto" ) @@ -32,7 +33,7 @@ func (c *QQClient) buildOfflineFileDownloadRequestPacket(uuid []byte) (uint16, [ return seq, packet } -func decodeOfflineFileDownloadResponse(c *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeOfflineFileDownloadResponse(c *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { rsp := cmd0x346.C346RspBody{} if err := proto.Unmarshal(payload, &rsp); err != nil { c.Error("unmarshal cmd0x346 rsp body error: %v", err) diff --git a/client/online_push.go b/client/online_push.go index c94b0cf0..ab4de977 100644 --- a/client/online_push.go +++ b/client/online_push.go @@ -9,6 +9,7 @@ import ( "github.com/Mrs4s/MiraiGo/binary" "github.com/Mrs4s/MiraiGo/binary/jce" + "github.com/Mrs4s/MiraiGo/client/internal/network" "github.com/Mrs4s/MiraiGo/client/pb" "github.com/Mrs4s/MiraiGo/client/pb/msgtype0x210" "github.com/Mrs4s/MiraiGo/client/pb/notify" @@ -22,7 +23,7 @@ var msg0x210Decoders = map[int64]func(*QQClient, []byte) error{ } // OnlinePush.ReqPush -func decodeOnlinePushReqPacket(c *QQClient, info *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeOnlinePushReqPacket(c *QQClient, info *network.IncomingPacketInfo, payload []byte) (interface{}, error) { request := &jce.RequestPacket{} request.ReadFrom(jce.NewJceReader(payload)) data := &jce.RequestDataVersion2{} diff --git a/client/ptt.go b/client/ptt.go index a36e1f80..beb864e3 100644 --- a/client/ptt.go +++ b/client/ptt.go @@ -10,6 +10,7 @@ import ( "github.com/Mrs4s/MiraiGo/binary" "github.com/Mrs4s/MiraiGo/client/internal/highway" + "github.com/Mrs4s/MiraiGo/client/internal/network" "github.com/Mrs4s/MiraiGo/client/pb/cmd0x346" "github.com/Mrs4s/MiraiGo/client/pb/cmd0x388" "github.com/Mrs4s/MiraiGo/client/pb/msg" @@ -336,7 +337,7 @@ func (c *QQClient) buildC2CPttStoreBDHExt(target int64, md5 []byte, size, voiceL } // PttCenterSvr.ShortVideoDownReq -func decodePttShortVideoDownResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodePttShortVideoDownResponse(_ *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { rsp := pttcenter.ShortVideoRspBody{} if err := proto.Unmarshal(payload, &rsp); err != nil { return nil, errors.Wrap(err, "failed to unmarshal protobuf message") @@ -348,7 +349,7 @@ func decodePttShortVideoDownResponse(_ *QQClient, _ *incomingPacketInfo, payload } // PttCenterSvr.GroupShortVideoUpReq -func decodeGroupShortVideoUploadResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeGroupShortVideoUploadResponse(_ *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { rsp := pttcenter.ShortVideoRspBody{} if err := proto.Unmarshal(payload, &rsp); err != nil { return nil, errors.Wrap(err, "failed to unmarshal protobuf message") diff --git a/client/qidian.go b/client/qidian.go index 70f8f4fe..1054ac5d 100644 --- a/client/qidian.go +++ b/client/qidian.go @@ -11,6 +11,7 @@ import ( "github.com/pkg/errors" "github.com/Mrs4s/MiraiGo/binary" + "github.com/Mrs4s/MiraiGo/client/internal/network" "github.com/Mrs4s/MiraiGo/client/pb/cmd0x3f6" "github.com/Mrs4s/MiraiGo/client/pb/cmd0x6ff" "github.com/Mrs4s/MiraiGo/client/pb/msg" @@ -151,7 +152,7 @@ func (c *QQClient) bigDataRequest(subCmd uint32, req proto.Message) ([]byte, err return tea.Decrypt(payload), nil } -func decodeLoginExtraResponse(c *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeLoginExtraResponse(c *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { rsp := cmd0x3f6.C3F6RspBody{} if err := proto.Unmarshal(payload, &rsp); err != nil { return nil, errors.Wrap(err, "failed to unmarshal protobuf message") @@ -167,7 +168,7 @@ func decodeLoginExtraResponse(c *QQClient, _ *incomingPacketInfo, payload []byte return nil, nil } -func decodeConnKeyResponse(c *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeConnKeyResponse(c *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { rsp := cmd0x6ff.C501RspBody{} if err := proto.Unmarshal(payload, &rsp); err != nil { return nil, errors.Wrap(err, "failed to unmarshal protobuf message") diff --git a/client/recall.go b/client/recall.go index 2567be6e..a65104e9 100644 --- a/client/recall.go +++ b/client/recall.go @@ -3,6 +3,7 @@ package client import ( "github.com/pkg/errors" + "github.com/Mrs4s/MiraiGo/client/internal/network" "github.com/Mrs4s/MiraiGo/client/pb/msg" "github.com/Mrs4s/MiraiGo/internal/proto" "github.com/Mrs4s/MiraiGo/message" @@ -91,7 +92,7 @@ func (c *QQClient) buildPrivateRecallPacket(uin, ts int64, msgSeq, random int32) return c.uniPacket("PbMessageSvc.PbMsgWithDraw", payload) } -func decodeMsgWithDrawResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeMsgWithDrawResponse(_ *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { rsp := msg.MsgWithDrawResp{} if err := proto.Unmarshal(payload, &rsp); err != nil { return nil, errors.Wrap(err, "failed to unmarshal protobuf message") diff --git a/client/security.go b/client/security.go index bb3c6ca9..777a4031 100644 --- a/client/security.go +++ b/client/security.go @@ -3,6 +3,7 @@ package client import ( "github.com/pkg/errors" + "github.com/Mrs4s/MiraiGo/client/internal/network" "github.com/Mrs4s/MiraiGo/client/pb/oidb" "github.com/Mrs4s/MiraiGo/internal/proto" ) @@ -14,9 +15,9 @@ func init() { type UrlSecurityLevel int const ( - Safe UrlSecurityLevel = 1 - Unknown UrlSecurityLevel = 2 - Danger UrlSecurityLevel = 3 + Safe UrlSecurityLevel = iota + 1 + Unknown + Danger ) // CheckUrlSafely 通过TX服务器检查URL安全性 @@ -47,7 +48,7 @@ func (c *QQClient) buildUrlCheckRequest(url string) (uint16, []byte) { return c.uniPacket("OidbSvc.0xbcb_0", payload) } -func decodeUrlCheckResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeUrlCheckResponse(_ *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { pkg := &oidb.OIDBSSOPkg{} rsp := &oidb.DBCBRspBody{} if err := proto.Unmarshal(payload, pkg); err != nil { diff --git a/client/sync.go b/client/sync.go index 4703de77..470b09e8 100644 --- a/client/sync.go +++ b/client/sync.go @@ -8,6 +8,7 @@ import ( "github.com/pkg/errors" "github.com/Mrs4s/MiraiGo/binary/jce" + "github.com/Mrs4s/MiraiGo/client/internal/network" "github.com/Mrs4s/MiraiGo/client/pb/msf" "github.com/Mrs4s/MiraiGo/client/pb/msg" "github.com/Mrs4s/MiraiGo/client/pb/oidb" @@ -284,7 +285,7 @@ func (c *QQClient) buildPrivateMsgReadedPacket(uin, time int64) (uint16, []byte) } // StatSvc.GetDevLoginInfo -func decodeDevListResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeDevListResponse(_ *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { request := &jce.RequestPacket{} request.ReadFrom(jce.NewJceReader(payload)) data := &jce.RequestDataVersion2{} @@ -306,7 +307,7 @@ func decodeDevListResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) ( } // RegPrxySvc.PushParam -func decodePushParamPacket(c *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodePushParamPacket(c *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { request := &jce.RequestPacket{} request.ReadFrom(jce.NewJceReader(payload)) data := &jce.RequestDataVersion2{} @@ -351,7 +352,7 @@ func decodePushParamPacket(c *QQClient, _ *incomingPacketInfo, payload []byte) ( } // RegPrxySvc.PbSyncMsg -func decodeMsgSyncResponse(c *QQClient, info *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeMsgSyncResponse(c *QQClient, info *network.IncomingPacketInfo, payload []byte) (interface{}, error) { rsp := &msf.SvcRegisterProxyMsgResp{} if err := proto.Unmarshal(payload, rsp); err != nil { return nil, err @@ -395,7 +396,7 @@ func decodeMsgSyncResponse(c *QQClient, info *incomingPacketInfo, payload []byte } // OnlinePush.PbC2CMsgSync -func decodeC2CSyncPacket(c *QQClient, info *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeC2CSyncPacket(c *QQClient, info *network.IncomingPacketInfo, payload []byte) (interface{}, error) { m := msg.PbPushMsg{} if err := proto.Unmarshal(payload, &m); err != nil { return nil, err @@ -405,7 +406,7 @@ func decodeC2CSyncPacket(c *QQClient, info *incomingPacketInfo, payload []byte) return nil, nil } -func decodeMsgReadedResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeMsgReadedResponse(_ *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { rsp := msg.PbMsgReadedReportResp{} if err := proto.Unmarshal(payload, &rsp); err != nil { return nil, errors.Wrap(err, "failed to unmarshal protobuf message") @@ -419,7 +420,7 @@ func decodeMsgReadedResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) var loginNotifyLock sync.Mutex // StatSvc.SvcReqMSFLoginNotify -func decodeLoginNotifyPacket(c *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeLoginNotifyPacket(c *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { request := &jce.RequestPacket{} request.ReadFrom(jce.NewJceReader(payload)) data := &jce.RequestDataVersion2{} diff --git a/client/system_msg.go b/client/system_msg.go index 5f782dc6..e6dbfdd6 100644 --- a/client/system_msg.go +++ b/client/system_msg.go @@ -1,6 +1,7 @@ package client import ( + "github.com/Mrs4s/MiraiGo/client/internal/network" "github.com/Mrs4s/MiraiGo/client/pb/structmsg" "github.com/Mrs4s/MiraiGo/internal/proto" ) @@ -189,7 +190,7 @@ func (c *QQClient) buildSystemMsgFriendActionPacket(reqID, requester int64, acce } // ProfileService.Pb.ReqSystemMsgNew.Group -func decodeSystemMsgGroupPacket(c *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeSystemMsgGroupPacket(c *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { rsp := structmsg.RspSystemMsgNew{} if err := proto.Unmarshal(payload, &rsp); err != nil { return nil, err diff --git a/client/tlv_decoders.go b/client/tlv_decoders.go index d32f9221..7df0828c 100644 --- a/client/tlv_decoders.go +++ b/client/tlv_decoders.go @@ -90,7 +90,9 @@ func (c *QQClient) decodeT119(data, ek []byte) { // readT138(t138) // chg time } - c.sigInfo = &auth.SigInfo{ + // we don't use `c.sigInfo = &auth.SigInfo{...}` here, + // because we need spread `SigInfo` to other places + *c.sigInfo = auth.SigInfo{ LoginBitmap: 0, SrmToken: utils.Select(m[0x16a], c.sigInfo.SrmToken), T133: utils.Select(m[0x133], c.sigInfo.T133), diff --git a/client/translate.go b/client/translate.go index a27f9032..946cec49 100644 --- a/client/translate.go +++ b/client/translate.go @@ -3,6 +3,7 @@ package client import ( "github.com/pkg/errors" + "github.com/Mrs4s/MiraiGo/client/internal/network" "github.com/Mrs4s/MiraiGo/client/pb/oidb" "github.com/Mrs4s/MiraiGo/internal/proto" ) @@ -40,7 +41,7 @@ func (c *QQClient) Translate(src, dst, text string) (string, error) { } // OidbSvc.0x990 -func decodeTranslateResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeTranslateResponse(_ *QQClient, _ *network.IncomingPacketInfo, payload []byte) (interface{}, error) { pkg := oidb.OIDBSSOPkg{} rsp := oidb.TranslateRspBody{} if err := proto.Unmarshal(payload, &pkg); err != nil { diff --git a/internal/generator/c2c_switcher/c2c_switcher.go b/internal/generator/c2c_switcher/c2c_switcher.go index 649b2ea4..99085cb7 100644 --- a/internal/generator/c2c_switcher/c2c_switcher.go +++ b/internal/generator/c2c_switcher/c2c_switcher.go @@ -27,7 +27,7 @@ const ( {{end}} ) -func peekC2CDecoder(msgType int32) (decoder func(*QQClient, *msg.Message, *incomingPacketInfo), decoderType uint8) { +func peekC2CDecoder(msgType int32) (decoder func(*QQClient, *msg.Message, *network.IncomingPacketInfo), decoderType uint8) { switch msgType { {{range .Decoders}} case {{.Id}}: return {{.Func}}, {{.DecoderType}}