mirror of
https://github.com/FlourishingWorld/hk4e.git
synced 2026-02-04 15:52:27 +08:00
135 lines
3.9 KiB
Go
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")
|
|
}
|