1
0
mirror of https://github.com/Mrs4s/MiraiGo.git synced 2025-05-04 19:17:38 +08:00

client: use net/netip

netip包中的数据结构更省内存,而且不需要堆分配
This commit is contained in:
wdvxdr 2022-03-22 22:44:37 +08:00
parent 4314fdcb39
commit 665c6acf02
No known key found for this signature in database
GPG Key ID: 703F8C071DE7A1B6
7 changed files with 39 additions and 87 deletions

View File

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"math/rand" "math/rand"
"net" "net"
"net/netip"
"sort" "sort"
"strconv" "strconv"
"sync" "sync"
@ -59,7 +60,7 @@ type QQClient struct {
// internal state // internal state
handlers syncx.Map[uint16, *handlerInfo] handlers syncx.Map[uint16, *handlerInfo]
waiters syncx.Map[string, func(any, error)] waiters syncx.Map[string, func(any, error)]
servers []*net.TCPAddr servers []netip.AddrPort
currServerIndex int currServerIndex int
retryTimes int retryTimes int
version *auth.AppVersion version *auth.AppVersion
@ -196,7 +197,6 @@ func NewClientMd5(uin int64, passwordMd5 [16]byte) *QQClient {
msgSvcCache: utils.NewCache[unit](time.Second * 15), msgSvcCache: utils.NewCache[unit](time.Second * 15),
transCache: utils.NewCache[unit](time.Second * 15), transCache: utils.NewCache[unit](time.Second * 15),
onlinePushCache: utils.NewCache[unit](time.Second * 15), onlinePushCache: utils.NewCache[unit](time.Second * 15),
servers: []*net.TCPAddr{},
alive: true, alive: true,
highwaySession: new(highway.Session), 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 adds, err := net.LookupIP("msfwifi.3g.qq.com") // host servers
if err == nil && len(adds) > 0 { if err == nil && len(adds) > 0 {
var hostAddrs []*net.TCPAddr var hostAddrs []netip.AddrPort
for _, addr := range adds { for _, addr := range adds {
hostAddrs = append(hostAddrs, &net.TCPAddr{ ip, ok := netip.AddrFromSlice(addr.To4())
IP: addr, if ok {
Port: 8080, hostAddrs = append(hostAddrs, netip.AddrPortFrom(ip, 8080))
}) }
} }
cli.servers = append(hostAddrs, cli.servers...) cli.servers = append(hostAddrs, cli.servers...)
} }
if len(cli.servers) == 0 { if len(cli.servers) == 0 {
cli.servers = []*net.TCPAddr{ // default servers cli.servers = []netip.AddrPort{ // default servers
{IP: net.IP{42, 81, 172, 81}, Port: 80}, netip.AddrPortFrom(netip.AddrFrom4([4]byte{42, 81, 172, 81}), 80),
{IP: net.IP{114, 221, 148, 59}, Port: 14000}, netip.AddrPortFrom(netip.AddrFrom4([4]byte{114, 221, 148, 59}), 14000),
{IP: net.IP{42, 81, 172, 147}, Port: 443}, netip.AddrPortFrom(netip.AddrFrom4([4]byte{42, 81, 172, 147}), 443),
{IP: net.IP{125, 94, 60, 146}, Port: 80}, netip.AddrPortFrom(netip.AddrFrom4([4]byte{125, 94, 60, 146}), 80),
{IP: net.IP{114, 221, 144, 215}, Port: 80}, netip.AddrPortFrom(netip.AddrFrom4([4]byte{114, 221, 144, 215}), 80),
{IP: net.IP{42, 81, 172, 22}, Port: 80}, netip.AddrPortFrom(netip.AddrFrom4([4]byte{42, 81, 172, 22}), 80),
} }
} }
pings := make([]int64, len(cli.servers)) pings := make([]int64, len(cli.servers))
wg := sync.WaitGroup{} wg := sync.WaitGroup{}
wg.Add(len(cli.servers)) wg.Add(len(cli.servers))
println(len(cli.servers))
for i := range cli.servers { for i := range cli.servers {
go func(index int) { go func(index int) {
defer wg.Done() defer wg.Done()
@ -783,7 +784,7 @@ func (c *QQClient) UpdateProfile(profile ProfileDetailUpdate) {
_, _ = c.sendAndWait(c.buildUpdateProfileDetailPacket(profile)) _, _ = 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...) c.servers = append(servers, c.servers...)
} }

View File

@ -2,7 +2,7 @@ package client
import ( import (
"crypto/md5" "crypto/md5"
"net" "net/netip"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
@ -312,16 +312,16 @@ func decodePushReqPacket(c *QQClient, _ *network.IncomingPacketInfo, payload []b
ssoPkt := jce.NewJceReader(jceBuf) ssoPkt := jce.NewJceReader(jceBuf)
servers := ssoPkt.ReadSsoServerInfos(1) servers := ssoPkt.ReadSsoServerInfos(1)
if len(servers) > 0 { if len(servers) > 0 {
var adds []*net.TCPAddr var adds []netip.AddrPort
for _, s := range servers { for _, s := range servers {
if strings.Contains(s.Server, "com") { if strings.Contains(s.Server, "com") {
continue continue
} }
c.debug("got new server addr: %v location: %v", s.Server, s.Location) c.debug("got new server addr: %v location: %v", s.Server, s.Location)
adds = append(adds, &net.TCPAddr{ addr, err := netip.ParseAddr(s.Server)
IP: net.ParseIP(s.Server), if err == nil {
Port: int(s.Port), adds = append(adds, netip.AddrPortFrom(addr, uint16(s.Port)))
}) }
} }
f := true f := true
for _, e := range c.eventHandlers.serverUpdatedHandlers { for _, e := range c.eventHandlers.serverUpdatedHandlers {

View File

@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"math/rand" "math/rand"
"net" "net"
"net/netip"
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
@ -114,7 +115,7 @@ func GenIMEI() string {
return final.String() return final.String()
} }
func getSSOAddress() ([]*net.TCPAddr, error) { func getSSOAddress() ([]netip.AddrPort, error) {
protocol := SystemDeviceInfo.Protocol.Version() protocol := SystemDeviceInfo.Protocol.Version()
key, _ := hex.DecodeString("F0441F5FF42DA58FDCF7949ABA62D411") key, _ := hex.DecodeString("F0441F5FF42DA58FDCF7949ABA62D411")
payload := jce.NewJceWriter(). // see ServerConfig.d payload := jce.NewJceWriter(). // see ServerConfig.d
@ -150,15 +151,15 @@ func getSSOAddress() ([]*net.TCPAddr, error) {
data.ReadFrom(jce.NewJceReader(rspPkt.SBuffer)) data.ReadFrom(jce.NewJceReader(rspPkt.SBuffer))
reader := jce.NewJceReader(data.Map["HttpServerListRes"][1:]) reader := jce.NewJceReader(data.Map["HttpServerListRes"][1:])
servers := reader.ReadSsoServerInfos(2) servers := reader.ReadSsoServerInfos(2)
adds := make([]*net.TCPAddr, 0, len(servers)) adds := make([]netip.AddrPort, 0, len(servers))
for _, s := range servers { for _, s := range servers {
if strings.Contains(s.Server, "com") { if strings.Contains(s.Server, "com") {
continue continue
} }
adds = append(adds, &net.TCPAddr{ ip, ok := netip.AddrFromSlice(net.ParseIP(s.Server))
IP: net.ParseIP(s.Server), if ok {
Port: int(s.Port), adds = append(adds, netip.AddrPortFrom(ip, uint16(s.Port)))
}) }
} }
return adds, nil return adds, nil
} }

View File

@ -34,9 +34,9 @@ func (t *TCPListener) UnexpectedDisconnect(f func(*TCPListener, error)) {
t.unexpectedDisconnect = f t.unexpectedDisconnect = f
} }
func (t *TCPListener) Connect(addr *net.TCPAddr) error { func (t *TCPListener) Connect(addr string) error {
t.Close() t.Close()
conn, err := net.DialTCP("tcp", nil, addr) conn, err := net.Dial("tcp", addr)
if err != nil { if err != nil {
return errors.Wrap(err, "dial tcp error") return errors.Wrap(err, "dial tcp error")
} }

View File

@ -40,11 +40,13 @@ func (c *QQClient) ConnectionQualityTest() *ConnectionQualityInfo {
r := &ConnectionQualityInfo{} r := &ConnectionQualityInfo{}
wg := sync.WaitGroup{} wg := sync.WaitGroup{}
wg.Add(2) wg.Add(2)
currentServerAddr := c.servers[c.currServerIndex].String()
go func() { go func() {
defer wg.Done() defer wg.Done()
var err error 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) c.error("test chat server latency error: %v", err)
r.ChatServerLatency = 9999 r.ChatServerLatency = 9999
} }
@ -67,7 +69,7 @@ func (c *QQClient) ConnectionQualityTest() *ConnectionQualityInfo {
}() }()
go func() { go func() {
defer wg.Done() defer wg.Done()
res := utils.RunTCPPingLoop(c.servers[c.currServerIndex].String(), 10) res := utils.RunTCPPingLoop(currentServerAddr, 10)
r.ChatServerPacketLoss = res.PacketsLoss r.ChatServerPacketLoss = res.PacketsLoss
if c.highwaySession.AddrLength() > 0 { if c.highwaySession.AddrLength() > 0 {
res = utils.RunTCPPingLoop(c.highwaySession.SsoAddr[0].String(), 10) res = utils.RunTCPPingLoop(c.highwaySession.SsoAddr[0].String(), 10)
@ -87,8 +89,9 @@ func (c *QQClient) ConnectionQualityTest() *ConnectionQualityInfo {
// connect 连接到 QQClient.servers 中的服务器 // connect 连接到 QQClient.servers 中的服务器
func (c *QQClient) connect() error { func (c *QQClient) connect() error {
c.info("connect to server: %v", c.servers[c.currServerIndex].String()) addr := c.servers[c.currServerIndex].String()
err := c.TCP.Connect(c.servers[c.currServerIndex]) c.info("connect to server: %v", addr)
err := c.TCP.Connect(addr)
c.currServerIndex++ c.currServerIndex++
if c.currServerIndex == len(c.servers) { if c.currServerIndex == len(c.servers) {
c.currServerIndex = 0 c.currServerIndex = 0

View File

@ -58,7 +58,7 @@ type (
content map[string]any content map[string]any
) )
var globalBlockId int64 = 0 var globalBlockId int64
func genBlockId() string { func genBlockId() string {
id := atomic.AddInt64(&globalBlockId, 1) id := atomic.AddInt64(&globalBlockId, 1)

View File

@ -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 // Select 如果A为nil 将会返回 B 否则返回A
// 对应 ?? 语法 // 对应 ?? 语法
func Select(a, b []byte) []byte { func Select(a, b []byte) []byte {