Files
hk4e/gate/kcp/enet.go
2023-02-14 22:57:35 +08:00

135 lines
3.9 KiB
Go

package kcp
import (
"bytes"
"encoding/binary"
"encoding/hex"
"errors"
)
// 原神Enet连接控制协议
// MM MM MM MM | LL LL LL LL | HH HH HH HH | EE EE EE EE | MM MM MM MM
// MM为表示连接状态的幻数 在开头的4字节和结尾的4字节
// LL和HH分别为convId的低4字节和高4字节
// EE为Enet事件类型 4字节
// Enet协议上报结构体
type Enet struct {
Addr string
ConvId uint64
ConnType uint8
EnetType uint32
}
// Enet连接状态类型
const (
ConnEnetSyn = 1
ConnEnetEst = 2
ConnEnetFin = 3
ConnEnetAddrChange = 4
)
// Enet连接状态类型幻数
var MagicEnetSynHead, _ = hex.DecodeString("000000ff")
var MagicEnetSynTail, _ = hex.DecodeString("ffffffff")
var MagicEnetEstHead, _ = hex.DecodeString("00000145")
var MagicEnetEstTail, _ = hex.DecodeString("14514545")
var MagicEnetFinHead, _ = hex.DecodeString("00000194")
var MagicEnetFinTail, _ = hex.DecodeString("19419494")
// Enet事件类型
const (
EnetTimeout = 0
EnetClientClose = 1
EnetClientRebindFail = 2
EnetClientShutdown = 3
EnetServerRelogin = 4
EnetServerKick = 5
EnetServerShutdown = 6
EnetNotFoundSession = 7
EnetLoginUnfinished = 8
EnetPacketFreqTooHigh = 9
EnetPingTimeout = 10
EnetTranferFailed = 11
EnetServerKillClient = 12
EnetCheckMoveSpeed = 13
EnetAccountPasswordChange = 14
EnetClientEditorConnectKey = 987654321
EnetClientConnectKey = 1234567890
)
func BuildEnet(connType uint8, enetType uint32, conv uint64) []byte {
data := make([]byte, 20)
if connType == ConnEnetSyn {
copy(data[0:4], MagicEnetSynHead)
copy(data[16:20], MagicEnetSynTail)
} else if connType == ConnEnetEst {
copy(data[0:4], MagicEnetEstHead)
copy(data[16:20], MagicEnetEstTail)
} else if connType == ConnEnetFin {
copy(data[0:4], MagicEnetFinHead)
copy(data[16:20], MagicEnetFinTail)
} else {
return nil
}
// conv的高四个字节和低四个字节分开
// 例如 00 00 01 45 | LL LL LL LL | HH HH HH HH | 49 96 02 d2 | 14 51 45 45
data[4] = uint8(conv >> 24)
data[5] = uint8(conv >> 16)
data[6] = uint8(conv >> 8)
data[7] = uint8(conv >> 0)
data[8] = uint8(conv >> 56)
data[9] = uint8(conv >> 48)
data[10] = uint8(conv >> 40)
data[11] = uint8(conv >> 32)
// Enet
data[12] = uint8(enetType >> 24)
data[13] = uint8(enetType >> 16)
data[14] = uint8(enetType >> 8)
data[15] = uint8(enetType >> 0)
return data
}
func ParseEnet(data []byte) (connType uint8, enetType uint32, conv uint64, err error) {
// 提取convId
conv = uint64(0)
conv += uint64(data[4]) << 24
conv += uint64(data[5]) << 16
conv += uint64(data[6]) << 8
conv += uint64(data[7]) << 0
conv += uint64(data[8]) << 56
conv += uint64(data[9]) << 48
conv += uint64(data[10]) << 40
conv += uint64(data[11]) << 32
// 提取Enet协议头部和尾部幻数
udpPayloadEnetHead := data[:4]
udpPayloadEnetTail := data[len(data)-4:]
// 提取Enet协议类型
enetTypeData := data[12:16]
enetTypeDataBuffer := bytes.NewBuffer(enetTypeData)
enetType = uint32(0)
_ = binary.Read(enetTypeDataBuffer, binary.BigEndian, &enetType)
equalHead := bytes.Equal(udpPayloadEnetHead, MagicEnetSynHead)
equalTail := bytes.Equal(udpPayloadEnetTail, MagicEnetSynTail)
if equalHead && equalTail {
// 客户端前置握手获取conv
connType = ConnEnetSyn
return connType, enetType, conv, nil
}
equalHead = bytes.Equal(udpPayloadEnetHead, MagicEnetEstHead)
equalTail = bytes.Equal(udpPayloadEnetTail, MagicEnetEstTail)
if equalHead && equalTail {
// 连接建立
connType = ConnEnetEst
return connType, enetType, conv, nil
}
equalHead = bytes.Equal(udpPayloadEnetHead, MagicEnetFinHead)
equalTail = bytes.Equal(udpPayloadEnetTail, MagicEnetFinTail)
if equalHead && equalTail {
// 连接断开
connType = ConnEnetFin
return connType, enetType, conv, nil
}
return 0, 0, 0, errors.New("unknown conn type")
}