Динамически обрабатывать разные версии протокола - PullRequest
0 голосов
/ 29 января 2020

Мне приходится обрабатывать несколько версий протокола связи. У меня есть пакеты со всеми пакетами и их идентификаторами, которые выглядят как

package v1_8

//Clientbound packet IDs
const (
    KeepAliveClientbound byte = iota
    JoinGame
    ChatMessageClientbound
    TimeUpdate
    EntityEquipment
    SpawnPosition
    UpdateHealth
    Respawn
    PlayerPositionAndLookClientbound
    HeldItemChangeClientbound
    UseBed
    AnimationClientbound
    SpawnPlayer
    CollectItem
...

и

package v1_14_3

//Clientbound packet IDs
const (
    SpawnObject byte = iota //0x00
    SpawnExperienceOrb
    SpawnGlobalEntity
    SpawnMob
    SpawnPainting
    SpawnPlayer
    AnimationClientbound
    Statistics
    BlockBreakAnimation
    UpdateBlockEntity
    BlockAction
    BlockChange
    BossBar
    ServerDifficulty
    ChatMessageClientbound
    MultiBlockChange
...

Существуют небольшие различия между версиями (разные идентификаторы для тех же пакетов или измененный тип данных) как мне go справиться с ними? Пока я просто использую оператор switch, чтобы проверить, какой пакет обрабатывается, но это работает только для одной версии. У меня есть информация о версии протокола клиента, поэтому мне просто нужно изменить пакет, который используется в операторе switch.

for {
    pkt, err := src.ReadPacket()
    if err != nil {
        ...handle error
    }

    switch pkt.ID {
    case v1_14_3.<Packet Const>:
        ...handle packet - there might be different data type assigned for different versions of protocol
    }

    err = dst.WritePacket(pkt)
    if err != nil {
        ...handle error
    }
}

@ Edit: предоставление дополнительной информации

Структура пакета, возвращаемая ReadPacket()

type Packet struct {
    ID   byte
    Data []byte
}

И некоторые реальные данные

{0 [234 3 9 108 111 99 97 108 104 111 115 116 99 156 1]}

Это один из пакетов, определенных здесь как Рукопожатие

Затем я использую Scan метод Packet struct наподобие

switch pkt.ID {
case v1_14_3.Handshake:
    var (
        protocolVersion packet.VarInt
        serverAddress   packet.String
        serverPort      packet.UnsignedShort
        nextState       packet.VarInt
    )
    err = pkt.Scan(&protocolVersion, &serverAddress, &serverPort, &nextState)
    if err != nil {
        ...handle error
    }
    ...process packet
}

Как я уже говорил, типы, переданные в метод Scan, могут немного отличаться для разных версий, а также для идентификаторов пакетов. Таким образом, пакет Handshake между версиями может иметь различную pkt.ID или различную полезную нагрузку (поэтому свойства, передаваемые для сканирования, будут другими). Scan - это просто переменная c функция, которая передает переданные переменные с pkt.Data

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...