1
0
mirror of https://github.com/Mrs4s/MiraiGo.git synced 2025-05-04 11:07:40 +08:00

Merge remote-tracking branch 'origin/master' into network

This commit is contained in:
wdvxdr 2022-01-28 22:17:44 +08:00
commit c1cbb69110
No known key found for this signature in database
GPG Key ID: 703F8C071DE7A1B6
10 changed files with 97 additions and 88 deletions

View File

@ -3,13 +3,13 @@ package client
import ( import (
"bytes" "bytes"
"encoding/hex" "encoding/hex"
"image"
"io" "io"
"math/rand" "math/rand"
"os" "os"
"strings" "strings"
"time" "time"
"github.com/fumiama/imgsz"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/Mrs4s/MiraiGo/binary" "github.com/Mrs4s/MiraiGo/binary"
@ -76,12 +76,9 @@ func (c *QQClient) UploadGroupImage(groupCode int64, img io.ReadSeeker) (*messag
return nil, errors.Wrap(err, "upload failed") return nil, errors.Wrap(err, "upload failed")
ok: ok:
_, _ = img.Seek(0, io.SeekStart) _, _ = img.Seek(0, io.SeekStart)
i, _, _ := image.DecodeConfig(img) i, t, _ := imgsz.DecodeSize(img)
var imageType int32 = 1000 var imageType int32 = 1000
_, _ = img.Seek(0, io.SeekStart) if t == "gif" {
tmp := make([]byte, 4)
_, _ = img.Read(tmp)
if bytes.Equal(tmp, []byte{0x47, 0x49, 0x46, 0x38}) {
imageType = 2000 imageType = 2000
} }
return message.NewGroupImage(binary.CalculateImageResourceId(fh), fh, rsp.FileId, int32(length), int32(i.Width), int32(i.Height), imageType), nil return message.NewGroupImage(binary.CalculateImageResourceId(fh), fh, rsp.FileId, int32(length), int32(i.Width), int32(i.Height), imageType), nil
@ -129,12 +126,9 @@ func (c *QQClient) UploadGroupImageByFile(groupCode int64, path string) (*messag
return nil, errors.Wrap(err, "upload failed") return nil, errors.Wrap(err, "upload failed")
ok: ok:
_, _ = img.Seek(0, io.SeekStart) _, _ = img.Seek(0, io.SeekStart)
i, _, _ := image.DecodeConfig(img) i, t, _ := imgsz.DecodeSize(img)
var imageType int32 = 1000 var imageType int32 = 1000
_, _ = img.Seek(0, io.SeekStart) if t == "gif" {
tmp := make([]byte, 4)
_, _ = img.Read(tmp)
if bytes.Equal(tmp, []byte{0x47, 0x49, 0x46, 0x38}) {
imageType = 2000 imageType = 2000
} }
return message.NewGroupImage(binary.CalculateImageResourceId(fh), fh, rsp.FileId, int32(length), int32(i.Width), int32(i.Height), imageType), nil return message.NewGroupImage(binary.CalculateImageResourceId(fh), fh, rsp.FileId, int32(length), int32(i.Width), int32(i.Height), imageType), nil

View File

@ -8,6 +8,7 @@ import (
"net" "net"
"net/http" "net/http"
"sync/atomic" "sync/atomic"
"time"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -27,6 +28,8 @@ type Session struct {
seq int32 seq int32
} }
const highwayMaxResponseSize int32 = 1024 * 100 // 100k
func (s *Session) AddrLength() int { func (s *Session) AddrLength() int {
return len(s.SsoAddr) return len(s.SsoAddr)
} }
@ -48,7 +51,7 @@ type Input struct {
func (s *Session) Upload(addr Addr, input Input) error { func (s *Session) Upload(addr Addr, input Input) error {
fh, length := utils.ComputeMd5AndLength(input.Body) fh, length := utils.ComputeMd5AndLength(input.Body)
_, _ = input.Body.Seek(0, io.SeekStart) _, _ = input.Body.Seek(0, io.SeekStart)
conn, err := net.DialTCP("tcp", nil, addr.asTcpAddr()) conn, err := net.DialTimeout("tcp", addr.String(), time.Second*3)
if err != nil { if err != nil {
return errors.Wrap(err, "connect error") return errors.Wrap(err, "connect error")
} }
@ -246,6 +249,9 @@ func readResponse(r *binary.NetworkReader) (*pb.RspDataHighwayHead, []byte, erro
} }
hl, _ := r.ReadInt32() hl, _ := r.ReadInt32()
a2, _ := r.ReadInt32() a2, _ := r.ReadInt32()
if hl > highwayMaxResponseSize || a2 > highwayMaxResponseSize {
return nil, nil, errors.Errorf("highway response invild. head size: %v body size: %v", hl, a2)
}
head, _ := r.ReadBytes(int(hl)) head, _ := r.ReadBytes(int(hl))
payload, _ := r.ReadBytes(int(a2)) payload, _ := r.ReadBytes(int(a2))
_, _ = r.ReadByte() _, _ = r.ReadByte()

View File

@ -67,10 +67,10 @@ func (c *QQClient) ConnectionQualityTest() *ConnectionQualityInfo {
}() }()
go func() { go func() {
defer wg.Done() defer wg.Done()
res := utils.RunICMPPingLoop(&net.IPAddr{IP: c.servers[c.currServerIndex].IP}, 10) res := utils.RunTCPPingLoop(c.servers[c.currServerIndex].String(), 10)
r.ChatServerPacketLoss = res.PacketsLoss r.ChatServerPacketLoss = res.PacketsLoss
if c.highwaySession.AddrLength() > 0 { if c.highwaySession.AddrLength() > 0 {
res = utils.RunICMPPingLoop(&net.IPAddr{IP: c.highwaySession.SsoAddr[0].AsNetIP()}, 10) res = utils.RunTCPPingLoop(c.highwaySession.SsoAddr[0].String(), 10)
r.SrvServerPacketLoss = res.PacketsLoss r.SrvServerPacketLoss = res.PacketsLoss
} }
}() }()

1
go.mod
View File

@ -4,6 +4,7 @@ go 1.17
require ( require (
github.com/RomiChan/protobuf v0.0.0-20211223055824-048df49a8956 github.com/RomiChan/protobuf v0.0.0-20211223055824-048df49a8956
github.com/fumiama/imgsz v0.0.2
github.com/klauspost/compress v1.13.6 github.com/klauspost/compress v1.13.6
github.com/pierrec/lz4/v4 v4.1.11 github.com/pierrec/lz4/v4 v4.1.11
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1

2
go.sum
View File

@ -3,6 +3,8 @@ github.com/RomiChan/protobuf v0.0.0-20211223055824-048df49a8956/go.mod h1:CKKOWC
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fumiama/imgsz v0.0.2 h1:fAkC0FnIscdKOXwAxlyw3EUba5NzxZdSxGaq3Uyfxak=
github.com/fumiama/imgsz v0.0.2/go.mod h1:dR71mI3I2O5u6+PCpd47M9TZptzP+39tRBcbdIkoqM4=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=

View File

@ -4,7 +4,7 @@ import "github.com/Mrs4s/MiraiGo/binary"
func T545(imei []byte) []byte { func T545(imei []byte) []byte {
return binary.NewWriterF(func(w *binary.Writer) { return binary.NewWriterF(func(w *binary.Writer) {
w.WriteUInt16(0x108) w.WriteUInt16(0x545)
w.WriteBytesShort(imei) w.WriteBytesShort(imei)
}) })
} }

View File

@ -90,6 +90,14 @@ func (e *GuildImageElement) Type() ElementType {
} }
func (e *GroupImageElement) Pack() (r []*msg.Elem) { func (e *GroupImageElement) Pack() (r []*msg.Elem) {
// width and height are required, set 720*480 if not set
if e.Width == 0 {
e.Width = 720
}
if e.Height == 0 {
e.Height = 480
}
cface := &msg.CustomFace{ cface := &msg.CustomFace{
FileType: proto.Int32(66), FileType: proto.Int32(66),
Useful: proto.Int32(1), Useful: proto.Int32(1),

View File

@ -1,73 +0,0 @@
package utils
import (
"math/rand"
"net"
"time"
"github.com/pkg/errors"
"golang.org/x/net/icmp"
"golang.org/x/net/ipv4"
)
type ICMPPingResult struct {
PacketsSent int
PacketsRecv int
PacketsLoss int
Rtts []int64
}
func RunICMPPingLoop(addr *net.IPAddr, count int) *ICMPPingResult {
if count <= 0 {
return nil
}
r := &ICMPPingResult{
PacketsSent: count,
Rtts: make([]int64, count),
}
for i := 1; i <= count; i++ {
rtt, err := SendICMPRequest(addr, i)
if err != nil {
r.PacketsLoss++
r.Rtts[i-1] = 9999
continue
}
r.PacketsRecv++
r.Rtts[i-1] = rtt
time.Sleep(time.Millisecond * 100)
}
return r
}
func SendICMPRequest(addr *net.IPAddr, seq int) (int64, error) {
data := make([]byte, 32)
rand.Read(data)
body := &icmp.Echo{
ID: 0,
Seq: seq,
Data: data,
}
msg := &icmp.Message{
Type: ipv4.ICMPTypeEcho,
Code: 0,
Body: body,
}
msgBytes, _ := msg.Marshal(nil)
conn, err := net.DialIP("ip4:icmp", nil, addr)
if err != nil {
return 0, errors.Wrap(err, "dial icmp conn error")
}
defer func() { _ = conn.Close() }()
if _, err = conn.Write(msgBytes); err != nil {
return 0, errors.Wrap(err, "write icmp packet error")
}
start := time.Now()
_ = conn.SetReadDeadline(time.Now().Add(time.Second * 2))
buff := make([]byte, 1024)
_, err = conn.Read(buff)
if err != nil {
return 0, errors.Wrap(err, "read icmp conn error")
}
duration := time.Since(start).Milliseconds()
return duration, nil
}

59
utils/tcping.go Normal file
View File

@ -0,0 +1,59 @@
package utils
import (
"net"
"strings"
"time"
)
type ICMPPingResult struct {
PacketsSent int
PacketsLoss int
AvgTimeMill int64
}
// RunTCPPingLoop 使用 tcp 进行 ping
func RunTCPPingLoop(ipport string, count int) (r ICMPPingResult) {
r = ICMPPingResult{
PacketsSent: count,
PacketsLoss: count,
AvgTimeMill: 9999,
}
if count <= 0 {
return
}
durs := make([]int64, 0, count)
for i := 0; i < count; i++ {
d, err := tcping(ipport)
if err == nil {
r.PacketsLoss--
durs = append(durs, d)
}
time.Sleep(time.Millisecond * 100)
}
if len(durs) > 0 {
r.AvgTimeMill = 0
for _, d := range durs {
r.AvgTimeMill += d
}
if len(durs) > 1 {
r.AvgTimeMill /= int64(len(durs))
}
}
return
}
func tcping(ipport string) (int64, error) {
t := time.Now().UnixMilli()
conn, err := net.DialTimeout("tcp", ipport, time.Second*2)
if err != nil {
if strings.Contains(err.Error(), "timeout") {
return 9999, err
}
} else {
_ = conn.Close()
}
return time.Now().UnixMilli() - t, nil
}

12
utils/tcping_test.go Normal file
View File

@ -0,0 +1,12 @@
package utils
import (
"testing"
)
func TestPing(t *testing.T) {
r := RunTCPPingLoop("127.0.0.1:23333", 4)
if r.PacketsLoss == r.PacketsSent {
t.Fatal(r)
}
}