Protocol changes to support more packet types
parent
13b7a99860
commit
17990e35d9
@ -1,37 +1,221 @@
|
||||
package pnyx
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"encoding"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type PacketType uint8
|
||||
const (
|
||||
PACKET_CHANNEL_COMMAND PacketType = iota
|
||||
PACKET_CHANNEL_DATA
|
||||
PACKET_CHANNEL_PEER
|
||||
|
||||
CHANNEL_HEADER_LEN int = 5
|
||||
CHANNEL_COMMAND_LEN = CHANNEL_HEADER_LEN + COMMAND_LENGTH + ID_LENGTH
|
||||
CHANNEL_PEER_LEN = CHANNEL_HEADER_LEN + ID_LENGTH
|
||||
)
|
||||
|
||||
type Payload interface {
|
||||
encoding.BinaryMarshaler
|
||||
}
|
||||
|
||||
type Packet struct {
|
||||
Type PacketType
|
||||
Payload Payload
|
||||
}
|
||||
|
||||
func(packet Packet) MarshalBinary() ([]byte, error) {
|
||||
payload, err := packet.Payload.MarshalBinary()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return append([]byte{byte(packet.Type)}, payload...), nil
|
||||
}
|
||||
|
||||
func ParsePacket(data []byte) (Payload, error) {
|
||||
if len(data) < 1 {
|
||||
return nil, fmt.Errorf("Packet too short to parse - %d/1", len(data))
|
||||
}
|
||||
|
||||
switch PacketType(data[0]) {
|
||||
case PACKET_CHANNEL_DATA:
|
||||
return ParseChannelDataPacket(data[1:])
|
||||
case PACKET_CHANNEL_COMMAND:
|
||||
return ParseChannelCommandPacket(data[1:])
|
||||
case PACKET_CHANNEL_PEER:
|
||||
return ParseChannelPeerPacket(data[1:])
|
||||
default:
|
||||
return nil, fmt.Errorf("Don't know how to parse packet type 0x%02x", data[0])
|
||||
}
|
||||
}
|
||||
|
||||
type ChannelHeader struct {
|
||||
Channel ChannelID
|
||||
Mode ModeID
|
||||
}
|
||||
|
||||
func(packet ChannelHeader) MarshalBinary() ([]byte, error) {
|
||||
p := binary.BigEndian.AppendUint32(nil, uint32(packet.Channel))
|
||||
return append(p, byte(packet.Mode)), nil
|
||||
}
|
||||
|
||||
func ParseChannelHeader(data []byte) (ChannelHeader, error) {
|
||||
if len(data) < 5 {
|
||||
return ChannelHeader{}, fmt.Errorf("Not enough bytes to parse ChannelPacket(%d/%d)", len(data), 6)
|
||||
}
|
||||
|
||||
return ChannelHeader{
|
||||
Channel: ChannelID(binary.BigEndian.Uint32(data)),
|
||||
Mode: ModeID(data[4]),
|
||||
}, nil
|
||||
}
|
||||
|
||||
type ChannelCommandPacket struct {
|
||||
ChannelHeader
|
||||
Command byte
|
||||
ReqID uuid.UUID
|
||||
Data []byte
|
||||
}
|
||||
|
||||
func(packet Packet) String() string {
|
||||
return fmt.Sprintf("{Channel: %x, Mode: %x, Data: %x}", packet.Channel, packet.Mode, packet.Data)
|
||||
func NewChannelCommandPacket(channel ChannelID, mode ModeID, command byte, data []byte) (*Packet, uuid.UUID) {
|
||||
request_id := uuid.New()
|
||||
return &Packet{
|
||||
Type: PACKET_CHANNEL_COMMAND,
|
||||
Payload: ChannelCommandPacket{
|
||||
ChannelHeader: ChannelHeader{
|
||||
Channel: channel,
|
||||
Mode: mode,
|
||||
},
|
||||
Command: command,
|
||||
ReqID: request_id,
|
||||
Data: data,
|
||||
},
|
||||
}, request_id
|
||||
}
|
||||
|
||||
func(packet Packet) MarshalBinary() ([]byte, error) {
|
||||
p := binary.BigEndian.AppendUint32(nil, uint32(packet.Channel))
|
||||
p = append(p, byte(packet.Mode))
|
||||
p = append(p, byte(packet.Command))
|
||||
return append(p, packet.Data...), nil
|
||||
func(packet ChannelCommandPacket) MarshalBinary() ([]byte, error) {
|
||||
header, err := packet.ChannelHeader.MarshalBinary()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data := append(header, packet.Command)
|
||||
data = append(data, packet.ReqID[:]...)
|
||||
return append(data, packet.Data...), nil
|
||||
}
|
||||
|
||||
func ParsePacket(data []byte) (*Packet, error) {
|
||||
if len(data) < 6 {
|
||||
return nil, fmt.Errorf("Not enough bytes to parse Packet(%d/%d)", len(data), 6)
|
||||
func ParseChannelCommandPacket(data []byte) (ChannelCommandPacket, error) {
|
||||
if len(data) < CHANNEL_COMMAND_LEN {
|
||||
return ChannelCommandPacket{}, fmt.Errorf("Not enough data to decode channel command packet %d/%d", len(data), CHANNEL_COMMAND_LEN)
|
||||
}
|
||||
|
||||
header, err := ParseChannelHeader(data[:CHANNEL_HEADER_LEN])
|
||||
if err != nil {
|
||||
return ChannelCommandPacket{}, err
|
||||
}
|
||||
|
||||
command := data[CHANNEL_HEADER_LEN]
|
||||
request_id := uuid.UUID(data[CHANNEL_HEADER_LEN+COMMAND_LENGTH:])
|
||||
return ChannelCommandPacket{
|
||||
ChannelHeader: header,
|
||||
Command: command,
|
||||
ReqID: request_id,
|
||||
Data: data[CHANNEL_COMMAND_LEN:],
|
||||
}, nil
|
||||
}
|
||||
|
||||
type ChannelPeerPacket struct {
|
||||
ChannelHeader
|
||||
Peer PeerID
|
||||
Data []byte
|
||||
}
|
||||
|
||||
func NewChannelPeerPacket(peer PeerID, channel ChannelID, mode ModeID, data []byte) *Packet {
|
||||
return &Packet{
|
||||
Channel: ChannelID(binary.BigEndian.Uint32(data)),
|
||||
Mode: ModeID(data[4]),
|
||||
Command: data[5],
|
||||
Data: data[6:],
|
||||
Type: PACKET_CHANNEL_PEER,
|
||||
Payload: ChannelPeerPacket{
|
||||
ChannelHeader: ChannelHeader{
|
||||
Channel: channel,
|
||||
Mode: mode,
|
||||
},
|
||||
Peer: peer,
|
||||
Data: data,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func(packet ChannelPeerPacket) MarshalBinary() ([]byte, error) {
|
||||
header, err := packet.ChannelHeader.MarshalBinary()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data := append(header, packet.Peer[:]...)
|
||||
return append(data, packet.Data...), nil
|
||||
}
|
||||
|
||||
func ParseChannelPeerPacket(data []byte) (ChannelPeerPacket, error) {
|
||||
if len(data) < CHANNEL_PEER_LEN {
|
||||
return ChannelPeerPacket{}, fmt.Errorf("Not enough bytes to parse ServerChannelPacket: %d/%d", len(data), ID_LENGTH)
|
||||
}
|
||||
|
||||
header, err := ParseChannelHeader(data)
|
||||
if err != nil {
|
||||
return ChannelPeerPacket{}, err
|
||||
}
|
||||
|
||||
return ChannelPeerPacket{
|
||||
ChannelHeader: header,
|
||||
Peer: PeerID(data[CHANNEL_HEADER_LEN:]),
|
||||
Data: data[CHANNEL_PEER_LEN:],
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
type ChannelDataPacket struct {
|
||||
ChannelHeader
|
||||
Data []byte
|
||||
}
|
||||
|
||||
func NewChannelDataPacket(channel ChannelID, mode ModeID, data []byte) *Packet {
|
||||
return &Packet{
|
||||
Type: PACKET_CHANNEL_DATA,
|
||||
Payload: ChannelDataPacket{
|
||||
ChannelHeader: ChannelHeader{
|
||||
Channel: channel,
|
||||
Mode: mode,
|
||||
},
|
||||
Data: data,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func(packet ChannelDataPacket) MarshalBinary() ([]byte, error) {
|
||||
header, err := packet.ChannelHeader.MarshalBinary()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return append(header, packet.Data...), nil
|
||||
}
|
||||
|
||||
func ParseChannelDataPacket(data []byte) (ChannelDataPacket, error) {
|
||||
if len(data) < CHANNEL_HEADER_LEN {
|
||||
return ChannelDataPacket{}, fmt.Errorf("Not enough data to parse ChannelDataPacket")
|
||||
}
|
||||
|
||||
header, err := ParseChannelHeader(data)
|
||||
if err != nil {
|
||||
return ChannelDataPacket{}, nil
|
||||
}
|
||||
|
||||
return ChannelDataPacket{
|
||||
ChannelHeader: header,
|
||||
Data: data[CHANNEL_HEADER_LEN:],
|
||||
}, nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue