Files
huya-go/internal/huya/wss_message.go
T

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)
}