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