diff --git a/client/client.go b/client/client.go index 8b747945..bdd0fad2 100644 --- a/client/client.go +++ b/client/client.go @@ -5,6 +5,7 @@ import ( "fmt" "math/rand" "net" + "net/netip" "sort" "strconv" "sync" @@ -59,7 +60,7 @@ type QQClient struct { // internal state handlers syncx.Map[uint16, *handlerInfo] waiters syncx.Map[string, func(any, error)] - servers []*net.TCPAddr + servers []netip.AddrPort currServerIndex int retryTimes int version *auth.AppVersion @@ -196,7 +197,6 @@ func NewClientMd5(uin int64, passwordMd5 [16]byte) *QQClient { msgSvcCache: utils.NewCache[unit](time.Second * 15), transCache: utils.NewCache[unit](time.Second * 15), onlinePushCache: utils.NewCache[unit](time.Second * 15), - servers: []*net.TCPAddr{}, alive: true, highwaySession: new(highway.Session), @@ -226,28 +226,29 @@ func NewClientMd5(uin int64, passwordMd5 [16]byte) *QQClient { } adds, err := net.LookupIP("msfwifi.3g.qq.com") // host servers if err == nil && len(adds) > 0 { - var hostAddrs []*net.TCPAddr + var hostAddrs []netip.AddrPort for _, addr := range adds { - hostAddrs = append(hostAddrs, &net.TCPAddr{ - IP: addr, - Port: 8080, - }) + ip, ok := netip.AddrFromSlice(addr.To4()) + if ok { + hostAddrs = append(hostAddrs, netip.AddrPortFrom(ip, 8080)) + } } cli.servers = append(hostAddrs, cli.servers...) } if len(cli.servers) == 0 { - cli.servers = []*net.TCPAddr{ // default servers - {IP: net.IP{42, 81, 172, 81}, Port: 80}, - {IP: net.IP{114, 221, 148, 59}, Port: 14000}, - {IP: net.IP{42, 81, 172, 147}, Port: 443}, - {IP: net.IP{125, 94, 60, 146}, Port: 80}, - {IP: net.IP{114, 221, 144, 215}, Port: 80}, - {IP: net.IP{42, 81, 172, 22}, Port: 80}, + cli.servers = []netip.AddrPort{ // default servers + netip.AddrPortFrom(netip.AddrFrom4([4]byte{42, 81, 172, 81}), 80), + netip.AddrPortFrom(netip.AddrFrom4([4]byte{114, 221, 148, 59}), 14000), + netip.AddrPortFrom(netip.AddrFrom4([4]byte{42, 81, 172, 147}), 443), + netip.AddrPortFrom(netip.AddrFrom4([4]byte{125, 94, 60, 146}), 80), + netip.AddrPortFrom(netip.AddrFrom4([4]byte{114, 221, 144, 215}), 80), + netip.AddrPortFrom(netip.AddrFrom4([4]byte{42, 81, 172, 22}), 80), } } pings := make([]int64, len(cli.servers)) wg := sync.WaitGroup{} wg.Add(len(cli.servers)) + println(len(cli.servers)) for i := range cli.servers { go func(index int) { defer wg.Done() @@ -783,7 +784,7 @@ func (c *QQClient) UpdateProfile(profile ProfileDetailUpdate) { _, _ = c.sendAndWait(c.buildUpdateProfileDetailPacket(profile)) } -func (c *QQClient) SetCustomServer(servers []*net.TCPAddr) { +func (c *QQClient) SetCustomServer(servers []netip.AddrPort) { c.servers = append(servers, c.servers...) } diff --git a/client/decoders.go b/client/decoders.go index f8452d4b..d5e5427d 100644 --- a/client/decoders.go +++ b/client/decoders.go @@ -2,7 +2,7 @@ package client import ( "crypto/md5" - "net" + "net/netip" "strconv" "strings" "sync" @@ -312,16 +312,16 @@ func decodePushReqPacket(c *QQClient, _ *network.IncomingPacketInfo, payload []b ssoPkt := jce.NewJceReader(jceBuf) servers := ssoPkt.ReadSsoServerInfos(1) if len(servers) > 0 { - var adds []*net.TCPAddr + var adds []netip.AddrPort for _, s := range servers { if strings.Contains(s.Server, "com") { continue } c.debug("got new server addr: %v location: %v", s.Server, s.Location) - adds = append(adds, &net.TCPAddr{ - IP: net.ParseIP(s.Server), - Port: int(s.Port), - }) + addr, err := netip.ParseAddr(s.Server) + if err == nil { + adds = append(adds, netip.AddrPortFrom(addr, uint16(s.Port))) + } } f := true for _, e := range c.eventHandlers.serverUpdatedHandlers { diff --git a/client/global.go b/client/global.go index 5b4cc48e..ca623397 100644 --- a/client/global.go +++ b/client/global.go @@ -6,6 +6,7 @@ import ( "fmt" "math/rand" "net" + "net/netip" "sort" "strconv" "strings" @@ -114,7 +115,7 @@ func GenIMEI() string { return final.String() } -func getSSOAddress() ([]*net.TCPAddr, error) { +func getSSOAddress() ([]netip.AddrPort, error) { protocol := SystemDeviceInfo.Protocol.Version() key, _ := hex.DecodeString("F0441F5FF42DA58FDCF7949ABA62D411") payload := jce.NewJceWriter(). // see ServerConfig.d @@ -150,15 +151,15 @@ func getSSOAddress() ([]*net.TCPAddr, error) { data.ReadFrom(jce.NewJceReader(rspPkt.SBuffer)) reader := jce.NewJceReader(data.Map["HttpServerListRes"][1:]) servers := reader.ReadSsoServerInfos(2) - adds := make([]*net.TCPAddr, 0, len(servers)) + adds := make([]netip.AddrPort, 0, len(servers)) for _, s := range servers { if strings.Contains(s.Server, "com") { continue } - adds = append(adds, &net.TCPAddr{ - IP: net.ParseIP(s.Server), - Port: int(s.Port), - }) + ip, ok := netip.AddrFromSlice(net.ParseIP(s.Server)) + if ok { + adds = append(adds, netip.AddrPortFrom(ip, uint16(s.Port))) + } } return adds, nil } diff --git a/client/internal/network/conn.go b/client/internal/network/conn.go index a43614c1..682b3034 100644 --- a/client/internal/network/conn.go +++ b/client/internal/network/conn.go @@ -34,9 +34,9 @@ func (t *TCPListener) UnexpectedDisconnect(f func(*TCPListener, error)) { t.unexpectedDisconnect = f } -func (t *TCPListener) Connect(addr *net.TCPAddr) error { +func (t *TCPListener) Connect(addr string) error { t.Close() - conn, err := net.DialTCP("tcp", nil, addr) + conn, err := net.Dial("tcp", addr) if err != nil { return errors.Wrap(err, "dial tcp error") } diff --git a/client/network.go b/client/network.go index 4a546155..868ebd03 100644 --- a/client/network.go +++ b/client/network.go @@ -40,11 +40,13 @@ func (c *QQClient) ConnectionQualityTest() *ConnectionQualityInfo { r := &ConnectionQualityInfo{} wg := sync.WaitGroup{} wg.Add(2) + + currentServerAddr := c.servers[c.currServerIndex].String() go func() { defer wg.Done() var err error - if r.ChatServerLatency, err = qualityTest(c.servers[c.currServerIndex].String()); err != nil { + if r.ChatServerLatency, err = qualityTest(currentServerAddr); err != nil { c.error("test chat server latency error: %v", err) r.ChatServerLatency = 9999 } @@ -67,7 +69,7 @@ func (c *QQClient) ConnectionQualityTest() *ConnectionQualityInfo { }() go func() { defer wg.Done() - res := utils.RunTCPPingLoop(c.servers[c.currServerIndex].String(), 10) + res := utils.RunTCPPingLoop(currentServerAddr, 10) r.ChatServerPacketLoss = res.PacketsLoss if c.highwaySession.AddrLength() > 0 { res = utils.RunTCPPingLoop(c.highwaySession.SsoAddr[0].String(), 10) @@ -87,8 +89,9 @@ func (c *QQClient) ConnectionQualityTest() *ConnectionQualityInfo { // connect 连接到 QQClient.servers 中的服务器 func (c *QQClient) connect() error { - c.info("connect to server: %v", c.servers[c.currServerIndex].String()) - err := c.TCP.Connect(c.servers[c.currServerIndex]) + addr := c.servers[c.currServerIndex].String() + c.info("connect to server: %v", addr) + err := c.TCP.Connect(addr) c.currServerIndex++ if c.currServerIndex == len(c.servers) { c.currServerIndex = 0 diff --git a/topic/feed.go b/topic/feed.go index 5472131e..8cb65363 100644 --- a/topic/feed.go +++ b/topic/feed.go @@ -58,7 +58,7 @@ type ( content map[string]any ) -var globalBlockId int64 = 0 +var globalBlockId int64 func genBlockId() string { id := atomic.AddInt64(&globalBlockId, 1) diff --git a/utils/sys.go b/utils/sys.go index 7ef22b45..b9d78312 100644 --- a/utils/sys.go +++ b/utils/sys.go @@ -44,59 +44,6 @@ func MultiReadSeeker(r ...io.ReadSeeker) io.ReadSeeker { } } -type multiReadAt struct { - first io.ReadSeeker - second io.ReadSeeker - firstSize int64 - secondSize int64 -} - -func (m *multiReadAt) ReadAt(p []byte, off int64) (n int, err error) { - if m.second == nil { // quick path - _, _ = m.first.Seek(off, io.SeekStart) - return m.first.Read(p) - } - if off < m.firstSize && off+int64(len(p)) < m.firstSize { - _, err = m.first.Seek(off, io.SeekStart) - if err != nil { - return - } - return m.first.Read(p) - } else if off < m.firstSize && off+int64(len(p)) >= m.firstSize { - _, _ = m.first.Seek(off, io.SeekStart) - _, _ = m.second.Seek(0, io.SeekStart) - n, err = m.first.Read(p[:m.firstSize-off]) - if err != nil { - return - } - n2, err := m.second.Read(p[m.firstSize-off:]) - return n + n2, err - } - _, err = m.second.Seek(off-m.firstSize, io.SeekStart) - if err != nil { - return - } - return m.second.Read(p) -} - -func ReaderAtFrom2ReadSeeker(first, second io.ReadSeeker) io.ReaderAt { - firstSize, _ := first.Seek(0, io.SeekEnd) - if second == nil { - return &multiReadAt{ - first: first, - firstSize: firstSize, - secondSize: 0, - } - } - secondSize, _ := second.Seek(0, io.SeekEnd) - return &multiReadAt{ - first: first, - second: second, - firstSize: firstSize, - secondSize: secondSize, - } -} - // Select 如果A为nil 将会返回 B 否则返回A // 对应 ?? 语法 func Select(a, b []byte) []byte {