package pnyx import ( "fmt" "github.com/google/uuid" ) type ChannelID byte const ( MODE_RAW ModeID = iota MODE_AUDIO AUDIO_SET_SAMPLE_RATE = iota AUDIO_GET_SAMPLE_RATE ) type ModeID uint8 type CommandID uint8 type Permission string type Channel struct { id ChannelID name string modes map[ModeID]Mode members []*ServerSession } func(channel *Channel) Data(session *ServerSession, mode ModeID, data []byte) { m, has_mode := channel.modes[mode] if has_mode { m.Data(session, channel.id, channel.members, data) } } func(channel *Channel) Command(session *ServerSession, command byte, request_id uuid.UUID, mode_id ModeID, data []byte) error { mode, has_mode := channel.modes[mode_id] if has_mode == false { return fmt.Errorf("Channel has no mode 0x%02x", mode) } else { return mode.Command(session, command, request_id, channel.id, channel.members, data) } } func(channel *Channel) Join(client PeerID, session SessionID) { } func(channel *Channel) Leave(client PeerID, session SessionID) { } type Mode interface { Command(session *ServerSession, command byte, request_id uuid.UUID, channel_id ChannelID, members []*ServerSession, data []byte) error Data(session *ServerSession, channel_id ChannelID, members []*ServerSession, data []byte) Join(client PeerID, session SessionID) Leave(client PeerID, session SessionID) } func multiplex_without_sender(origin SessionID, packet *Packet, sessions []*ServerSession) { for _, session := range(sessions) { if session.ID == origin { continue } session.OutgoingPackets <- packet } } func multiplex(packet *Packet, sessions []*ServerSession) { for _, session := range(sessions) { session.OutgoingPackets <- packet } } type RawMode struct { } func(mode *RawMode) Command(session *ServerSession, command byte, request_id uuid.UUID, channel_id ChannelID, members []*ServerSession, data []byte) error { return fmt.Errorf("unknown raw mode command 0x%02x", command) } func(mode *RawMode) Data(session *ServerSession, channel_id ChannelID, members []*ServerSession, data []byte) { new_packet := NewChannelPeerPacket(session.Peer, channel_id, MODE_RAW, data) multiplex_without_sender(session.ID, new_packet, members) } func(mode *RawMode) Join(client PeerID, session SessionID) { } func(mode *RawMode) Leave(client PeerID, session SessionID) { } type SampleRate byte const ( SAMPLE_RATE_UNSET SampleRate = 0xFF SAMPLE_RATE_24KHZ = 0x01 SAMPLE_RATE_48KHZ = 0x02 ) type AudioMode struct { SampleRate SampleRate } func(mode *AudioMode) Command(session *ServerSession, command byte, request_id uuid.UUID, channel_id ChannelID, members []*ServerSession, data []byte) error { switch command { case AUDIO_SET_SAMPLE_RATE: if len(data) == 1 { switch SampleRate(data[0]) { case SAMPLE_RATE_24KHZ: fallthrough case SAMPLE_RATE_48KHZ: mode.SampleRate = SampleRate(data[0]) update_packet := NewChannelCommandPacket(request_id, channel_id, MODE_AUDIO, AUDIO_SET_SAMPLE_RATE, data) multiplex(update_packet, members) return nil default: return fmt.Errorf("Invalid sample rate: %x", data[0]) } } else { return fmt.Errorf("Invalid AUDIO_SET_SAMPLE_RATE payload: %x", data) } case AUDIO_GET_SAMPLE_RATE: session.OutgoingPackets <- NewChannelCommandPacket(request_id, channel_id, MODE_AUDIO, AUDIO_SET_SAMPLE_RATE, []byte{byte(mode.SampleRate)}) return nil default: return fmt.Errorf("unknown audio mode command 0x%02x", command) } } func(mode *AudioMode) Data(session *ServerSession, channel_id ChannelID, members []*ServerSession, data []byte) { new_packet := NewChannelPeerPacket(session.Peer, channel_id, MODE_AUDIO, data) multiplex_without_sender(session.ID, new_packet, members) } func(mode *AudioMode) Join(client PeerID, session SessionID) { } func(mode *AudioMode) Leave(client PeerID, session SessionID) { }