|
|
|
@ -1,25 +1,19 @@
|
|
|
|
|
package pnyx
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"slices"
|
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
|
|
"github.com/google/uuid"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type ChannelID byte
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
MODE_CHANNEL ModeID = iota
|
|
|
|
|
MODE_RAW
|
|
|
|
|
MODE_RAW ModeID = iota
|
|
|
|
|
MODE_AUDIO
|
|
|
|
|
|
|
|
|
|
CHANNEL_JOIN byte = iota
|
|
|
|
|
CHANNEL_LEAVE
|
|
|
|
|
CHANNEL_MEMBERS
|
|
|
|
|
|
|
|
|
|
AUDIO_SET_SAMPLE_RATE = iota
|
|
|
|
|
AUDIO_GET_SAMPLE_RATE
|
|
|
|
|
|
|
|
|
|
RAW_DATA = iota
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type ModeID uint8
|
|
|
|
@ -30,103 +24,70 @@ type Channel struct {
|
|
|
|
|
id ChannelID
|
|
|
|
|
name string
|
|
|
|
|
modes map[ModeID]Mode
|
|
|
|
|
sessions []SessionID
|
|
|
|
|
members []*ServerSession
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func(channel *Channel) Data(session *Session, mode ModeID, data []byte) []SendPacket {
|
|
|
|
|
func(channel *Channel) Data(session *ServerSession, mode ModeID, data []byte) {
|
|
|
|
|
m, has_mode := channel.modes[mode]
|
|
|
|
|
if has_mode == false {
|
|
|
|
|
return nil
|
|
|
|
|
} else {
|
|
|
|
|
return m.Data(session, channel, data)
|
|
|
|
|
if has_mode {
|
|
|
|
|
m.Data(session, channel.id, channel.members, data)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func(channel *Channel) Command(session *Session, packet ChannelCommandPacket) ([]SendPacket, error) {
|
|
|
|
|
if packet.Mode == MODE_CHANNEL {
|
|
|
|
|
switch packet.Command {
|
|
|
|
|
case CHANNEL_JOIN:
|
|
|
|
|
if slices.Contains(channel.sessions, session.ID) {
|
|
|
|
|
return nil, fmt.Errorf("Session %s already in channel %d, can't join", session.ID, channel.id)
|
|
|
|
|
} else {
|
|
|
|
|
channel.sessions = append(channel.sessions, session.ID)
|
|
|
|
|
return nil, nil
|
|
|
|
|
}
|
|
|
|
|
case CHANNEL_LEAVE:
|
|
|
|
|
idx := slices.Index(channel.sessions, session.ID)
|
|
|
|
|
if idx == -1 {
|
|
|
|
|
return nil, fmt.Errorf("Session %s not in channel %d, can't leave", session.ID, channel.id)
|
|
|
|
|
} else {
|
|
|
|
|
channel.sessions = slices.Delete(channel.sessions, idx, idx+1)
|
|
|
|
|
return nil, nil
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
return nil, fmt.Errorf("Unknown MODE_CHANNEL command: 0x%02x", packet.Command)
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
mode, has_mode := channel.modes[packet.Mode]
|
|
|
|
|
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 nil, fmt.Errorf("Channel has no mode 0x%02x", mode)
|
|
|
|
|
return fmt.Errorf("Channel has no mode 0x%02x", mode)
|
|
|
|
|
} else {
|
|
|
|
|
return mode.Command(session, channel, packet)
|
|
|
|
|
}
|
|
|
|
|
return mode.Command(session, command, request_id, channel.id, channel.members, data)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type SendPacket struct {
|
|
|
|
|
Packet *Packet
|
|
|
|
|
Session SessionID
|
|
|
|
|
func(channel *Channel) Join(client PeerID, session SessionID) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func(channel *Channel) Leave(client PeerID, session SessionID) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Mode interface {
|
|
|
|
|
// Process takes incoming packets from a session and returns a list of packets to send
|
|
|
|
|
Command(session *Session, channel *Channel, packet ChannelCommandPacket) ([]SendPacket, error)
|
|
|
|
|
Data(session *Session, channel *Channel, data []byte) []SendPacket
|
|
|
|
|
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 []SessionID) []SendPacket {
|
|
|
|
|
send_packets := make([]SendPacket, len(sessions) - 1)
|
|
|
|
|
i := 0
|
|
|
|
|
for _, session_id := range(sessions) {
|
|
|
|
|
if session_id == origin {
|
|
|
|
|
func multiplex_without_sender(origin SessionID, packet *Packet, sessions []*ServerSession) {
|
|
|
|
|
for _, session := range(sessions) {
|
|
|
|
|
if session.ID == origin {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
send_packets[i] = SendPacket{
|
|
|
|
|
Packet: packet,
|
|
|
|
|
Session: session_id,
|
|
|
|
|
session.OutgoingPackets <- packet
|
|
|
|
|
}
|
|
|
|
|
i += 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return send_packets
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func multiplex(packet *Packet, sessions []SessionID) []SendPacket {
|
|
|
|
|
send_packets := make([]SendPacket, len(sessions))
|
|
|
|
|
for i, session_id := range(sessions) {
|
|
|
|
|
send_packets[i] = SendPacket{
|
|
|
|
|
Packet: packet,
|
|
|
|
|
Session: session_id,
|
|
|
|
|
func multiplex(packet *Packet, sessions []*ServerSession) {
|
|
|
|
|
for _, session := range(sessions) {
|
|
|
|
|
session.OutgoingPackets <- packet
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return send_packets
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type RawMode struct {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func(mode *RawMode) Command(session *Session, channel *Channel, packet ChannelCommandPacket) ([]SendPacket, error) {
|
|
|
|
|
return nil, fmt.Errorf("unknown raw mode command 0x%02x", packet.Command)
|
|
|
|
|
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 *Session, channel *Channel, data []byte) []SendPacket {
|
|
|
|
|
if slices.Contains(channel.sessions, session.ID) {
|
|
|
|
|
new_packet := NewChannelPeerPacket(session.Peer, channel.id, MODE_RAW, data)
|
|
|
|
|
return multiplex_without_sender(session.ID, new_packet, channel.sessions)
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
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
|
|
|
|
@ -140,37 +101,38 @@ type AudioMode struct {
|
|
|
|
|
SampleRate SampleRate
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func(mode *AudioMode) Command(session *Session, channel *Channel, packet ChannelCommandPacket) ([]SendPacket, error) {
|
|
|
|
|
switch packet.Command {
|
|
|
|
|
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(packet.Data) == 1 {
|
|
|
|
|
switch SampleRate(packet.Data[0]) {
|
|
|
|
|
if len(data) == 1 {
|
|
|
|
|
switch SampleRate(data[0]) {
|
|
|
|
|
case SAMPLE_RATE_24KHZ:
|
|
|
|
|
fallthrough
|
|
|
|
|
case SAMPLE_RATE_48KHZ:
|
|
|
|
|
mode.SampleRate = SampleRate(packet.Data[0])
|
|
|
|
|
update_packet := NewChannelCommandPacket(packet.ReqID, channel.id, MODE_AUDIO, AUDIO_SET_SAMPLE_RATE, packet.Data)
|
|
|
|
|
return multiplex(update_packet, channel.sessions), nil
|
|
|
|
|
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 nil, fmt.Errorf("Invalid sample rate: %x", packet.Data[0])
|
|
|
|
|
return fmt.Errorf("Invalid sample rate: %x", data[0])
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return nil, fmt.Errorf("Invalid AUDIO_SET_SAMPLE_RATE payload: %x", packet.Data)
|
|
|
|
|
return fmt.Errorf("Invalid AUDIO_SET_SAMPLE_RATE payload: %x", data)
|
|
|
|
|
}
|
|
|
|
|
case AUDIO_GET_SAMPLE_RATE:
|
|
|
|
|
return []SendPacket{{
|
|
|
|
|
Packet: NewChannelCommandPacket(packet.ReqID, channel.id, MODE_AUDIO, AUDIO_SET_SAMPLE_RATE, []byte{byte(mode.SampleRate)}),
|
|
|
|
|
Session: session.ID,
|
|
|
|
|
}}, nil
|
|
|
|
|
session.OutgoingPackets <- NewChannelCommandPacket(request_id, channel_id, MODE_AUDIO, AUDIO_SET_SAMPLE_RATE, []byte{byte(mode.SampleRate)})
|
|
|
|
|
return nil
|
|
|
|
|
default:
|
|
|
|
|
return nil, fmt.Errorf("unknown audio mode command 0x%02x", packet.Command)
|
|
|
|
|
return fmt.Errorf("unknown audio mode command 0x%02x", command)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func(mode *AudioMode) Data(session *Session, channel *Channel, data []byte) []SendPacket {
|
|
|
|
|
if slices.Contains(channel.sessions, session.ID) {
|
|
|
|
|
new_packet := NewChannelPeerPacket(session.Peer, channel.id, MODE_AUDIO, data)
|
|
|
|
|
return multiplex_without_sender(session.ID, new_packet, channel.sessions)
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
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) {
|
|
|
|
|
}
|
|
|
|
|