Skip to content

Commit

Permalink
feat: UploadSrcByStreamAsync()
Browse files Browse the repository at this point in the history
  • Loading branch information
Szzrain committed Apr 20, 2024
1 parent 66338e1 commit 3132355
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 0 deletions.
95 changes: 95 additions & 0 deletions client/highway.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ package client

import (
"bytes"
binary2 "encoding/binary"
"fmt"
highway2 "github.com/LagrangeDev/LagrangeGo/packets/highway"
"github.com/LagrangeDev/LagrangeGo/packets/pb/service/highway"
"github.com/LagrangeDev/LagrangeGo/utils"
"github.com/LagrangeDev/LagrangeGo/utils/binary"
Expand All @@ -10,8 +13,12 @@ import (
"net/http"
"net/url"
"strconv"
"sync/atomic"
)

var highwayUri map[uint32][]string
var sequence atomic.Uint32

type UpBlock struct {
CommandId int
Uin uint
Expand All @@ -25,6 +32,94 @@ type UpBlock struct {
Timestamp uint64
}

func (c *QQClient) GetServiceServer() map[uint32][]string {
if highwayUri == nil {
highwayUri = make(map[uint32][]string)
packet, err := highway2.BuildHighWayUrlReq(c.sig.Tgt)
if err != nil {
return nil
}
payload, err := c.SendUniPacketAndAwait("HttpConn.0x6ff_501", packet.Data())
if err != nil {
networkLogger.Errorf("Failed to get highway server: %v", err)
return nil
}
resp, err := highway2.ParseHighWayUrlReq(payload.Data)
if err != nil {
networkLogger.Errorf("Failed to parse highway server: %v", err)
return nil
}
for _, info := range resp.HttpConn.ServerInfos {
servicetype := info.ServiceType
for _, addr := range info.ServerAddrs {
ip := make([]byte, 4)
binary2.LittleEndian.PutUint32(ip, addr.IP)
service := highwayUri[servicetype]
service = append(service, fmt.Sprintf("http://%x.%x.%x.%x:%d/cgi-bin/httpconn?htcmd=0x6FF0087&uin=%d", ip[0], ip[1], ip[2], ip[3], addr.Port, c.sig.Uin))
highwayUri[servicetype] = service
}
}
}
return highwayUri
}

func (c *QQClient) UploadSrcByStreamAsync(commonId int, stream io.ReadSeeker, ticket []byte, md5 []byte, extendInfo []byte) bool {
// Get server URL
server := c.GetServiceServer()
if server == nil {
return false
}
success := true
var upBlocks []UpBlock
data, err := io.ReadAll(stream)
if err != nil {
return false
}

fileSize := uint64(len(data))
offset := uint64(0)
_, err = stream.Seek(0, io.SeekStart)
if err != nil {
return false
}

for offset < fileSize {
var buffersize uint64
if uint64(1024*1024) > fileSize-offset {
buffersize = fileSize - offset
} else {
buffersize = uint64(1024 * 1024)
}
buffer := make([]byte, buffersize)
payload, err := io.ReadFull(stream, buffer)
if err != nil {
return false
}
reqBody := UpBlock{
CommandId: commonId,
Uin: uint(c.sig.Uin),
Sequence: uint(sequence.Load()),
FileSize: fileSize,
Offset: offset,
Ticket: ticket,
FileMd5: md5,
Block: buffer,
ExtendInfo: extendInfo,
}
sequence.Add(1)
upBlocks = append(upBlocks, reqBody)
offset += uint64(payload)
// 4 is HighwayConcurrent
if len(upBlocks) >= 4 || offset == fileSize {
for _, block := range upBlocks {
success = success && c.SendUpBlockAsync(block, server[1][0])
}
upBlocks = nil
}
}
return success
}

func (c *QQClient) SendUpBlockAsync(block UpBlock, server string) bool {
head := &highway.DataHighwayHead{
Version: 1,
Expand Down
43 changes: 43 additions & 0 deletions packets/highway/HighWayUrl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package highway

import (
"encoding/hex"
"github.com/LagrangeDev/LagrangeGo/packets/pb/action"
"github.com/LagrangeDev/LagrangeGo/utils/binary"
"github.com/RomiChan/protobuf/proto"
)

func BuildHighWayUrlReq(tgt []byte) (*binary.Builder, error) {
tgtHex := hex.EncodeToString(tgt)
body := &action.HttpConn0X6Ff_501{
HttpConn: &action.HttpConn{
Field1: 0,
Field2: 0,
Field3: 16,
Field4: 1,
Tgt: tgtHex,
Field6: 3,
ServiceTypes: []int32{1, 5, 10, 21},
Field9: 2,
Field10: 9,
Field11: 8,
Ver: "1.0.1",
},
}
packet := binary.NewBuilder(nil)
marshal, err := proto.Marshal(body)
if err != nil {
return nil, err
}
packet.WriteBytes(marshal, false)
return packet, nil
}

func ParseHighWayUrlReq(data []byte) (*action.HttpConn0X6Ff_501Response, error) {
var req action.HttpConn0X6Ff_501Response
err := proto.Unmarshal(data, &req)
if err != nil {
return nil, err
}
return &req, nil
}

0 comments on commit 3132355

Please sign in to comment.