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

129 lines
3.3 KiB
Go

package network
import (
"strconv"
"sync"
"github.com/Mrs4s/MiraiGo/binary"
"github.com/Mrs4s/MiraiGo/client/internal/auth"
)
// Transport is a network transport.
type Transport struct {
sessionMu sync.Mutex
Sig *auth.SigInfo
Version *auth.AppVersion
Device *auth.Device
// connection
// conn *TCPListener
}
func (t *Transport) packBody(req *Request) []byte {
w := binary.SelectWriter()
defer binary.PutWriter(w)
w.WriteIntLvPacket(4, func(writer *binary.Writer) {
if req.Type == RequestTypeLogin {
writer.WriteUInt32(uint32(req.SequenceID))
writer.WriteUInt32(t.Version.AppId)
writer.WriteUInt32(t.Version.SubAppId)
writer.Write([]byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00})
tgt := t.Sig.TGT
if len(tgt) == 0 || len(tgt) == 4 {
writer.WriteUInt32(0x04)
} else {
writer.WriteUInt32(uint32(len(tgt) + 4))
writer.Write(tgt)
}
}
writer.WriteString(req.CommandName)
writer.WriteIntLvPacket(4, func(w *binary.Writer) {
w.Write(t.Sig.OutPacketSessionID)
})
// writer.WriteUInt32(uint32(len(t.Sig.OutPacketSessionID) + 4))
// w.Write(t.Sig.OutPacketSessionID)
if req.Type == RequestTypeLogin {
writer.WriteString(t.Device.IMEI)
writer.WriteUInt32(0x04)
{
writer.WriteUInt16(uint16(len(t.Sig.Ksid)) + 2)
writer.Write(t.Sig.Ksid)
}
}
writer.WriteUInt32(0x04)
})
w.WriteIntLvPacket(4, func(w *binary.Writer) {
w.Write(req.Body)
})
// w.WriteUInt32(uint32(len(req.Body) + 4))
// w.Write(req.Body)
return append([]byte(nil), w.Bytes()...)
}
// PackPacket packs a packet.
func (t *Transport) PackPacket(req *Request) []byte {
// todo(wdvxdr): combine pack packet, send packet and return the response
if len(t.Sig.D2) == 0 {
req.EncryptType = EncryptTypeEmptyKey
}
body := t.packBody(req)
// encrypt body
switch req.EncryptType {
case EncryptTypeD2Key:
body = binary.NewTeaCipher(t.Sig.D2Key).Encrypt(body)
case EncryptTypeEmptyKey:
body = binary.NewTeaCipher(emptyKey).Encrypt(body)
}
head := binary.NewWriterF(func(w *binary.Writer) {
w.WriteUInt32(uint32(req.Type))
w.WriteByte(byte(req.EncryptType))
switch req.Type {
case RequestTypeLogin:
switch req.EncryptType {
case EncryptTypeD2Key:
w.WriteUInt32(uint32(len(t.Sig.D2) + 4))
w.Write(t.Sig.D2)
default:
w.WriteUInt32(4)
}
case RequestTypeSimple:
w.WriteUInt32(uint32(req.SequenceID))
}
w.WriteByte(0x00)
w.WriteString(strconv.FormatInt(req.Uin, 10))
})
w := binary.SelectWriter()
defer binary.PutWriter(w)
w.WriteUInt32(uint32(len(head)+len(body)) + 4)
w.Write(head)
w.Write(body)
return append([]byte(nil), w.Bytes()...) // copy
}
func (t *Transport) parse(head []byte) *Request {
req := new(Request)
r := binary.NewReader(head)
req.Type = RequestType(r.ReadInt32())
encryptType := EncryptType(r.ReadInt32())
switch req.Type {
case RequestTypeLogin:
// req.Key = r.ReadBytes(int(encryptType))
case RequestTypeSimple:
req.SequenceID = r.ReadInt32()
}
_ = r.ReadString() // req.Uin
body := r.ReadAvailable()
switch encryptType {
case EncryptTypeNoEncrypt:
req.Body = body
case EncryptTypeD2Key:
req.Body = binary.NewTeaCipher(t.Sig.D2Key).Decrypt(body)
case EncryptTypeEmptyKey:
req.Body = binary.NewTeaCipher(emptyKey).Decrypt(body)
}
return req
}