149 lines
3.9 KiB
Go
149 lines
3.9 KiB
Go
package huya
|
|
|
|
import (
|
|
"fmt"
|
|
"math/rand"
|
|
|
|
"huya-go/internal/taf"
|
|
)
|
|
|
|
const (
|
|
WSSCmdNull int32 = 0
|
|
WSSCmdRegisterReq int32 = 1
|
|
WSSCmdRegisterRsp int32 = 2
|
|
WSSCmdWupReq int32 = 3
|
|
WSSCmdWupRsp int32 = 4
|
|
WSSCmdHeartBeat int32 = 5
|
|
WSSCmdHeartBeatAck int32 = 6
|
|
WSSCmdMsgPushReq int32 = 7
|
|
WSSCmdDeregisterReq int32 = 8
|
|
WSSCmdDeregisterRsp int32 = 9
|
|
WSSCmdVerifyCookieReq int32 = 10
|
|
WSSCmdVerifyCookieRsp int32 = 11
|
|
WSSCmdVerifyHuyaTokenReq int32 = 12
|
|
WSSCmdVerifyHuyaTokenRsp int32 = 13
|
|
WSSCmdUnverifyReq int32 = 14
|
|
WSSCmdUnverifyRsp int32 = 15
|
|
WSSCmdRegisterGroupReq int32 = 16
|
|
WSSCmdRegisterGroupRsp int32 = 17
|
|
WSSCmdUnregisterGroupReq int32 = 18
|
|
WSSCmdUnregisterGroupRsp int32 = 19
|
|
WSSCmdHeartBeatReq int32 = 20
|
|
WSSCmdHeartBeatRsp int32 = 21
|
|
WSSCmdMsgPushReqV2 int32 = 22
|
|
WSSCmdUpdateUserExpsReq int32 = 23
|
|
WSSCmdUpdateUserExpsRsp int32 = 24
|
|
WSSCmdUpdateUserInfoReq int32 = 33
|
|
WSSCmdUpdateUserInfoRsp int32 = 34
|
|
WSSCmdMsgAckReq int32 = 35
|
|
WSSCmdMsgAckRsp int32 = 36
|
|
WSSCmdS2CRpcReq int32 = 40
|
|
WSSCmdC2SRpcRsp int32 = 41
|
|
WSSCmdS2CRpcRspRsp int32 = 42
|
|
WSSCmdSignalUpgradeReq int32 = 105
|
|
WSSCmdSignalUpgradeRsp int32 = 106
|
|
defaultWSSTraceEnableValue = 0
|
|
)
|
|
|
|
// WSSCommand 是浏览器 JS 里的 HUYA.WebSocketCommand。
|
|
//
|
|
// 注意:这不是旧版的 6 字节自定义头。浏览器实际把这个 TAF/JCE
|
|
// 结构直接作为 WebSocket binary payload 发送。
|
|
type WSSCommand struct {
|
|
CmdType int32
|
|
Data []byte
|
|
RequestID int64
|
|
TraceID string
|
|
EncryptType int32
|
|
Time int64
|
|
MD5 string
|
|
}
|
|
|
|
func (c *WSSCommand) WriteTo(w *taf.Writer) error {
|
|
if err := w.WriteInt32(0, int64(c.CmdType)); err != nil {
|
|
return err
|
|
}
|
|
if err := w.WriteBytes(1, c.Data); err != nil {
|
|
return err
|
|
}
|
|
if err := w.WriteInt64(2, c.RequestID); err != nil {
|
|
return err
|
|
}
|
|
if err := w.WriteString(3, c.TraceID); err != nil {
|
|
return err
|
|
}
|
|
if err := w.WriteInt32(4, int64(c.EncryptType)); err != nil {
|
|
return err
|
|
}
|
|
if err := w.WriteInt64(5, c.Time); err != nil {
|
|
return err
|
|
}
|
|
return w.WriteString(6, c.MD5)
|
|
}
|
|
|
|
func (c *WSSCommand) ReadFrom(r *taf.Reader) error {
|
|
var err error
|
|
if c.CmdType, err = r.ReadInt32(0, false, c.CmdType); err != nil {
|
|
return err
|
|
}
|
|
if c.Data, err = r.ReadBytes(1, false, c.Data); err != nil {
|
|
return err
|
|
}
|
|
if c.RequestID, err = r.ReadInt64(2, false, c.RequestID); err != nil {
|
|
return err
|
|
}
|
|
if c.TraceID, err = r.ReadString(3, false, c.TraceID); err != nil {
|
|
return err
|
|
}
|
|
if c.EncryptType, err = r.ReadInt32(4, false, c.EncryptType); err != nil {
|
|
return err
|
|
}
|
|
if c.Time, err = r.ReadInt64(5, false, c.Time); err != nil {
|
|
return err
|
|
}
|
|
c.MD5, err = r.ReadString(6, false, c.MD5)
|
|
return err
|
|
}
|
|
|
|
func (c WSSCommand) Encode() ([]byte, error) {
|
|
w := taf.NewWriter()
|
|
if err := c.WriteTo(w); err != nil {
|
|
return nil, err
|
|
}
|
|
return append([]byte(nil), w.Bytes()...), nil
|
|
}
|
|
|
|
func DecodeWSSCommand(data []byte) (WSSCommand, error) {
|
|
var cmd WSSCommand
|
|
if len(data) == 0 {
|
|
return cmd, fmt.Errorf("wss: 空消息")
|
|
}
|
|
if err := cmd.ReadFrom(taf.NewReader(data)); err != nil {
|
|
return cmd, err
|
|
}
|
|
return cmd, nil
|
|
}
|
|
|
|
func EncodeWSSCommand(cmdType int32, data []byte, traceID string) ([]byte, error) {
|
|
return WSSCommand{
|
|
CmdType: cmdType,
|
|
Data: append([]byte(nil), data...),
|
|
TraceID: traceID,
|
|
}.Encode()
|
|
}
|
|
|
|
func encodeWSSStructCommand(cmdType int32, value taf.Marshaler) ([]byte, error) {
|
|
w := taf.NewWriter()
|
|
if value != nil {
|
|
if err := value.WriteTo(w); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return EncodeWSSCommand(cmdType, w.Bytes(), "")
|
|
}
|
|
|
|
func NewWSSCommandTrace() string {
|
|
trace := lowerHex16(rand.Uint64())
|
|
return fmt.Sprintf("%s:%s:0:%d", trace, trace, defaultWSSTraceEnableValue)
|
|
}
|