mirror of
https://github.com/Mrs4s/MiraiGo.git
synced 2025-05-04 11:07:40 +08:00
client: use TCP method to upload group file
This commit is contained in:
parent
f630205782
commit
1ec3bbf188
@ -27,12 +27,13 @@ type Transaction struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (bdh *Transaction) encrypt(key []byte) error {
|
func (bdh *Transaction) encrypt(key []byte) error {
|
||||||
if bdh.Encrypt {
|
if !bdh.Encrypt {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
if len(key) == 0 {
|
if len(key) == 0 {
|
||||||
return errors.New("session key not found. maybe miss some packet?")
|
return errors.New("session key not found. maybe miss some packet?")
|
||||||
}
|
}
|
||||||
bdh.Ext = binary.NewTeaCipher(key).Encrypt(bdh.Ext)
|
bdh.Ext = binary.NewTeaCipher(key).Encrypt(bdh.Ext)
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +89,16 @@ func uploadBDH(s *Session, addr Addr, trans *Transaction) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
ch := md5.Sum(chunk)
|
ch := md5.Sum(chunk)
|
||||||
head, _ := proto.Marshal(&pb.ReqDataHighwayHead{
|
head, _ := proto.Marshal(&pb.ReqDataHighwayHead{
|
||||||
MsgBasehead: s.dataHighwayHead(_REQ_CMD_DATA, 4096, trans.CommandID, 2052),
|
MsgBasehead: &pb.DataHighwayHead{
|
||||||
|
Version: 1,
|
||||||
|
Uin: s.Uin,
|
||||||
|
Command: _REQ_CMD_DATA,
|
||||||
|
Seq: s.nextSeq(),
|
||||||
|
Appid: s.AppID,
|
||||||
|
Dataflag: 4096,
|
||||||
|
CommandId: trans.CommandID,
|
||||||
|
LocaleId: 2052,
|
||||||
|
},
|
||||||
MsgSeghead: &pb.SegHead{
|
MsgSeghead: &pb.SegHead{
|
||||||
Filesize: trans.Size,
|
Filesize: trans.Size,
|
||||||
Dataoffset: int64(offset),
|
Dataoffset: int64(offset),
|
||||||
@ -100,8 +110,8 @@ func uploadBDH(s *Session, addr Addr, trans *Transaction) ([]byte, error) {
|
|||||||
ReqExtendinfo: trans.Ext,
|
ReqExtendinfo: trans.Ext,
|
||||||
})
|
})
|
||||||
offset += rl
|
offset += rl
|
||||||
frame := newFrame(head, chunk)
|
buffers := frame(head, chunk)
|
||||||
_, err = frame.WriteTo(conn)
|
_, err = buffers.WriteTo(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "write conn error")
|
return nil, errors.Wrap(err, "write conn error")
|
||||||
}
|
}
|
||||||
@ -190,7 +200,16 @@ func uploadBDHMultiThread(s *Session, addr Addr, trans *Transaction) ([]byte, er
|
|||||||
}
|
}
|
||||||
ch := md5.Sum(chunk)
|
ch := md5.Sum(chunk)
|
||||||
head, _ := proto.Marshal(&pb.ReqDataHighwayHead{
|
head, _ := proto.Marshal(&pb.ReqDataHighwayHead{
|
||||||
MsgBasehead: s.dataHighwayHead(_REQ_CMD_DATA, 4096, trans.CommandID, 2052),
|
MsgBasehead: &pb.DataHighwayHead{
|
||||||
|
Version: 1,
|
||||||
|
Uin: s.Uin,
|
||||||
|
Command: _REQ_CMD_DATA,
|
||||||
|
Seq: s.nextSeq(),
|
||||||
|
Appid: s.AppID,
|
||||||
|
Dataflag: 4096,
|
||||||
|
CommandId: trans.CommandID,
|
||||||
|
LocaleId: 2052,
|
||||||
|
},
|
||||||
MsgSeghead: &pb.SegHead{
|
MsgSeghead: &pb.SegHead{
|
||||||
Filesize: trans.Size,
|
Filesize: trans.Size,
|
||||||
Dataoffset: off,
|
Dataoffset: off,
|
||||||
@ -201,8 +220,8 @@ func uploadBDHMultiThread(s *Session, addr Addr, trans *Transaction) ([]byte, er
|
|||||||
},
|
},
|
||||||
ReqExtendinfo: trans.Ext,
|
ReqExtendinfo: trans.Ext,
|
||||||
})
|
})
|
||||||
frame := newFrame(head, chunk)
|
buffers := frame(head, chunk)
|
||||||
_, err = frame.WriteTo(conn)
|
_, err = buffers.WriteTo(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "write conn error")
|
return errors.Wrap(err, "write conn error")
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
|
|
||||||
var etx = []byte{0x29}
|
var etx = []byte{0x29}
|
||||||
|
|
||||||
// newFrame 包格式
|
// frame 包格式
|
||||||
//
|
//
|
||||||
// - STX: 0x28(40)
|
// - STX: 0x28(40)
|
||||||
// - head length
|
// - head length
|
||||||
@ -17,7 +17,7 @@ var etx = []byte{0x29}
|
|||||||
// - ETX: 0x29(41)
|
// - ETX: 0x29(41)
|
||||||
//
|
//
|
||||||
// 节省内存, 可被go runtime优化为writev操作
|
// 节省内存, 可被go runtime优化为writev操作
|
||||||
func newFrame(head []byte, body []byte) net.Buffers {
|
func frame(head []byte, body []byte) net.Buffers {
|
||||||
buffers := make(net.Buffers, 4)
|
buffers := make(net.Buffers, 4)
|
||||||
// buffer0 format:
|
// buffer0 format:
|
||||||
// - STX
|
// - STX
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
package highway
|
package highway
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/md5"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -42,6 +39,11 @@ type Session struct {
|
|||||||
SsoAddr []Addr
|
SsoAddr []Addr
|
||||||
|
|
||||||
seq int32
|
seq int32
|
||||||
|
/*
|
||||||
|
idleMu sync.Mutex
|
||||||
|
idleCount int
|
||||||
|
idle *idle
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
const highwayMaxResponseSize int32 = 1024 * 100 // 100k
|
const highwayMaxResponseSize int32 = 1024 * 100 // 100k
|
||||||
@ -58,94 +60,25 @@ func (s *Session) AppendAddr(ip, port uint32) {
|
|||||||
s.SsoAddr = append(s.SsoAddr, addr)
|
s.SsoAddr = append(s.SsoAddr, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Session) UploadExciting(trans Transaction) ([]byte, error) {
|
|
||||||
return s.retry(uploadExciting, &trans)
|
|
||||||
}
|
|
||||||
|
|
||||||
func uploadExciting(s *Session, addr Addr, trans *Transaction) ([]byte, error) {
|
|
||||||
url := fmt.Sprintf("http://%v/cgi-bin/httpconn?htcmd=0x6FF0087&Uin=%v", addr.String(), s.Uin)
|
|
||||||
var rspExt []byte
|
|
||||||
var offset int64
|
|
||||||
const chunkSize = 524288
|
|
||||||
chunk := make([]byte, chunkSize)
|
|
||||||
for {
|
|
||||||
chunk = chunk[:chunkSize]
|
|
||||||
rl, err := io.ReadFull(trans.Body, chunk)
|
|
||||||
if rl == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if err == io.ErrUnexpectedEOF {
|
|
||||||
chunk = chunk[:rl]
|
|
||||||
}
|
|
||||||
ch := md5.Sum(chunk)
|
|
||||||
head, _ := proto.Marshal(&pb.ReqDataHighwayHead{
|
|
||||||
MsgBasehead: s.dataHighwayHead(_REQ_CMD_DATA, 0, trans.CommandID, 0),
|
|
||||||
MsgSeghead: &pb.SegHead{
|
|
||||||
Filesize: trans.Size,
|
|
||||||
Dataoffset: offset,
|
|
||||||
Datalength: int32(rl),
|
|
||||||
Serviceticket: trans.Ticket,
|
|
||||||
Md5: ch[:],
|
|
||||||
FileMd5: trans.Sum,
|
|
||||||
},
|
|
||||||
ReqExtendinfo: trans.Ext,
|
|
||||||
})
|
|
||||||
offset += int64(rl)
|
|
||||||
frame := newFrame(head, chunk)
|
|
||||||
req, _ := http.NewRequest(http.MethodPost, url, &frame)
|
|
||||||
req.Header.Set("Accept", "*/*")
|
|
||||||
req.Header.Set("Connection", "Keep-Alive")
|
|
||||||
req.Header.Set("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)")
|
|
||||||
req.Header.Set("Pragma", "no-cache")
|
|
||||||
req.ContentLength = int64(len(head) + len(chunk) + 10)
|
|
||||||
rsp, err := http.DefaultClient.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "request error")
|
|
||||||
}
|
|
||||||
body, _ := io.ReadAll(rsp.Body)
|
|
||||||
_ = rsp.Body.Close()
|
|
||||||
r := binary.NewReader(body)
|
|
||||||
r.ReadByte()
|
|
||||||
hl := r.ReadInt32()
|
|
||||||
_ = r.ReadInt32()
|
|
||||||
h := r.ReadBytes(int(hl))
|
|
||||||
rspHead := new(pb.RspDataHighwayHead)
|
|
||||||
if err = proto.Unmarshal(h, rspHead); err != nil {
|
|
||||||
return nil, errors.Wrap(err, "failed to unmarshal protobuf message")
|
|
||||||
}
|
|
||||||
if rspHead.ErrorCode != 0 {
|
|
||||||
return nil, errors.Errorf("upload failed: %d", rspHead.ErrorCode)
|
|
||||||
}
|
|
||||||
if rspHead.RspExtendinfo != nil {
|
|
||||||
rspExt = rspHead.RspExtendinfo
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rspExt, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Session) nextSeq() int32 {
|
func (s *Session) nextSeq() int32 {
|
||||||
return atomic.AddInt32(&s.seq, 2)
|
return atomic.AddInt32(&s.seq, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Session) dataHighwayHead(cmd string, flag, cmdID, locale int32) *pb.DataHighwayHead {
|
|
||||||
return &pb.DataHighwayHead{
|
|
||||||
Version: 1,
|
|
||||||
Uin: s.Uin,
|
|
||||||
Command: cmd,
|
|
||||||
Seq: s.nextSeq(),
|
|
||||||
Appid: s.AppID,
|
|
||||||
Dataflag: flag,
|
|
||||||
CommandId: cmdID,
|
|
||||||
LocaleId: locale,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Session) sendHeartbreak(conn net.Conn) error {
|
func (s *Session) sendHeartbreak(conn net.Conn) error {
|
||||||
head, _ := proto.Marshal(&pb.ReqDataHighwayHead{
|
head, _ := proto.Marshal(&pb.ReqDataHighwayHead{
|
||||||
MsgBasehead: s.dataHighwayHead(_REQ_CMD_HEART_BREAK, 4096, 0, 2052),
|
MsgBasehead: &pb.DataHighwayHead{
|
||||||
|
Version: 1,
|
||||||
|
Uin: s.Uin,
|
||||||
|
Command: _REQ_CMD_HEART_BREAK,
|
||||||
|
Seq: s.nextSeq(),
|
||||||
|
Appid: s.AppID,
|
||||||
|
Dataflag: 4096,
|
||||||
|
CommandId: 0,
|
||||||
|
LocaleId: 2052,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
frame := newFrame(head, nil)
|
buffers := frame(head, nil)
|
||||||
_, err := frame.WriteTo(conn)
|
_, err := buffers.WriteTo(conn)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,3 +112,23 @@ func readResponse(r *binary.NetworkReader) (*pb.RspDataHighwayHead, error) {
|
|||||||
}
|
}
|
||||||
return rsp, nil
|
return rsp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
const maxIdleConn = 5
|
||||||
|
|
||||||
|
type idle struct {
|
||||||
|
conn net.Conn
|
||||||
|
delay int64
|
||||||
|
next *idle
|
||||||
|
}
|
||||||
|
|
||||||
|
// getConn ...
|
||||||
|
func (s *Session) getConn() net.Conn {
|
||||||
|
s.idleMu.Lock()
|
||||||
|
defer s.idleMu.Unlock()
|
||||||
|
|
||||||
|
conn := s.idle.conn
|
||||||
|
s.idle = s.idle.next
|
||||||
|
return conn
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
@ -147,7 +147,7 @@ func (c *QQClient) UploadFile(target message.Source, file *LocalFile) error {
|
|||||||
if target.SourceType == message.SourcePrivate {
|
if target.SourceType == message.SourcePrivate {
|
||||||
input.CommandID = 69
|
input.CommandID = 69
|
||||||
}
|
}
|
||||||
if _, err := c.highwaySession.UploadExciting(input); err != nil {
|
if _, err := c.highwaySession.UploadBDH(input); err != nil {
|
||||||
return errors.Wrap(err, "upload failed")
|
return errors.Wrap(err, "upload failed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user