diff --git a/binary/jce/structs.go b/binary/jce/structs.go index b7877ad1..280dc9f5 100644 --- a/binary/jce/structs.go +++ b/binary/jce/structs.go @@ -27,6 +27,12 @@ type ( Map map[string]map[string][]byte `jceId:"0"` } + SsoServerInfo struct { + Server string `jceId:"1"` + Port int32 `jceId:"2"` + Location string `jceId:"8"` + } + SvcReqRegister struct { IJceStruct Uin int64 `jceId:"0"` @@ -358,6 +364,12 @@ func (pkt *RequestDataVersion2) ReadFrom(r *JceReader) { }) } +func (pkt *SsoServerInfo) ReadFrom(r *JceReader) { + pkt.Server = r.ReadString(1) + pkt.Port = r.ReadInt32(2) + pkt.Location = r.ReadString(8) +} + func (pkt *SvcReqRegister) ToBytes() []byte { w := NewJceWriter() w.WriteJceStructRaw(pkt) diff --git a/client/client.go b/client/client.go index fb806935..0b21315d 100644 --- a/client/client.go +++ b/client/client.go @@ -936,6 +936,7 @@ func (c *QQClient) sendAndWait(seq uint16, pkt []byte) (interface{}, error) { case <-time.After(time.Second * 30): retry++ if retry < 2 { + c.Error("packet %v timed out. retry.", seq) _ = c.send(pkt) continue } @@ -954,6 +955,7 @@ func (c *QQClient) netLoop() { for c.Online { l, err := reader.ReadInt32() if err == io.EOF || err == io.ErrClosedPipe { + c.Error("connection dropped by server: %v", err) err = c.connect() if err != nil { break diff --git a/client/decoders.go b/client/decoders.go index b1a0103a..ba2e204a 100644 --- a/client/decoders.go +++ b/client/decoders.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/Mrs4s/MiraiGo/client/pb/pttcenter" "log" + "net" "strconv" "sync" "sync/atomic" @@ -130,6 +131,24 @@ func decodePushReqPacket(c *QQClient, _ uint16, payload []byte) (interface{}, er jceBuf := []byte{} t := r.ReadInt32(1) r.ReadSlice(&jceBuf, 2) + if t == 1 && len(jceBuf) > 0 { + ssoPkt := jce.NewJceReader(jceBuf) + servers := []jce.SsoServerInfo{} + ssoPkt.ReadSlice(&servers, 1) + if len(servers) > 0 { + c.server = &net.TCPAddr{ + IP: net.ParseIP(servers[0].Server), + Port: int(servers[0].Port), + } + c.Debug("got new server addr: %v location: %v", c.server.String(), servers[0].Location) + for _, e := range c.eventHandlers.serverUpdatedHandlers { + cover(func() { + e(c, &ServerUpdatedEvent{Servers: servers}) + }) + } + return nil, nil + } + } seq := r.ReadInt64(3) _, pkt := c.buildConfPushRespPacket(t, seq, jceBuf) return nil, c.send(pkt) diff --git a/client/entities.go b/client/entities.go index 4e690552..f743dc5f 100644 --- a/client/entities.go +++ b/client/entities.go @@ -2,6 +2,7 @@ package client import ( "errors" + "github.com/Mrs4s/MiraiGo/binary/jce" "strings" "sync" ) @@ -154,6 +155,10 @@ type ( Message string } + ServerUpdatedEvent struct { + Servers []jce.SsoServerInfo + } + NewFriendEvent struct { Friend *FriendInfo } diff --git a/client/events.go b/client/events.go index f4e3d97c..5ea6b885 100644 --- a/client/events.go +++ b/client/events.go @@ -24,6 +24,7 @@ type eventHandlers struct { newFriendHandlers []func(*QQClient, *NewFriendEvent) disconnectHandlers []func(*QQClient, *ClientDisconnectedEvent) logHandlers []func(*QQClient, *LogEvent) + serverUpdatedHandlers []func(*QQClient, *ServerUpdatedEvent) groupMessageReceiptHandlers sync.Map } @@ -99,6 +100,10 @@ func (c *QQClient) OnDisconnected(f func(*QQClient, *ClientDisconnectedEvent)) { c.eventHandlers.disconnectHandlers = append(c.eventHandlers.disconnectHandlers, f) } +func (c *QQClient) OnServerUpdated(f func(*QQClient, *ServerUpdatedEvent)) { + c.eventHandlers.serverUpdatedHandlers = append(c.eventHandlers.serverUpdatedHandlers, f) +} + func (c *QQClient) OnLog(f func(*QQClient, *LogEvent)) { c.eventHandlers.logHandlers = append(c.eventHandlers.logHandlers, f) }