|  |  |  | @ -19,6 +19,7 @@ const ( | 
		
	
		
			
				|  |  |  |  |   AUDIO_GET_SAMPLE_RATE | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   CHANNEL_COMMAND_BUFFER_SIZE int = 2048 | 
		
	
		
			
				|  |  |  |  |   CHANNEL_CLOSE_BUFFER_SIZE int = 100 | 
		
	
		
			
				|  |  |  |  | ) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | type ModeID uint8 | 
		
	
	
		
			
				
					|  |  |  | @ -27,49 +28,76 @@ type Permission string | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | type Channel struct { | 
		
	
		
			
				|  |  |  |  |   Commands chan SessionChannelCommand | 
		
	
		
			
				|  |  |  |  |   ClosedSessions chan *ServerSession | 
		
	
		
			
				|  |  |  |  |   Modes  map[ModeID]*atomic.Value | 
		
	
		
			
				|  |  |  |  |   Members atomic.Value | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func(channel *Channel) update_state() { | 
		
	
		
			
				|  |  |  |  |   for true { | 
		
	
		
			
				|  |  |  |  |     incoming := <-channel.Commands | 
		
	
		
			
				|  |  |  |  |     if incoming.Packet == nil { | 
		
	
		
			
				|  |  |  |  |       break | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     select { | 
		
	
		
			
				|  |  |  |  |     case session := <-channel.ClosedSessions: | 
		
	
		
			
				|  |  |  |  |       members := channel.Members.Load().([]*ServerSession) | 
		
	
		
			
				|  |  |  |  |       idx := slices.Index(members, session) | 
		
	
		
			
				|  |  |  |  |       if idx != -1 { | 
		
	
		
			
				|  |  |  |  |         new_members := make([]*ServerSession, len(members) - 1) | 
		
	
		
			
				|  |  |  |  |         copy(new_members, members[:idx]) | 
		
	
		
			
				|  |  |  |  |         copy(new_members[idx:], members[idx+1:]) | 
		
	
		
			
				|  |  |  |  |         channel.Members.Store(new_members) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         for _, mode_val := range(channel.Modes) { | 
		
	
		
			
				|  |  |  |  |           mode := mode_val.Load().(Mode) | 
		
	
		
			
				|  |  |  |  |           mode_val.Store(mode.Leave(session)) | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |       } | 
		
	
		
			
				|  |  |  |  |     case incoming := <-channel.Commands: | 
		
	
		
			
				|  |  |  |  |       if incoming.Packet == nil { | 
		
	
		
			
				|  |  |  |  |         break | 
		
	
		
			
				|  |  |  |  |       } else if incoming.Session.active.Load() == false { | 
		
	
		
			
				|  |  |  |  |         continue | 
		
	
		
			
				|  |  |  |  |       } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     command := incoming.Packet | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     if command.Mode == MODE_CHANNEL { | 
		
	
		
			
				|  |  |  |  |       switch command.Command { | 
		
	
		
			
				|  |  |  |  |       case CHANNEL_COMMAND_JOIN: | 
		
	
		
			
				|  |  |  |  |         members := channel.Members.Load().([]*ServerSession) | 
		
	
		
			
				|  |  |  |  |         if slices.Contains(members, incoming.Session) == false { | 
		
	
		
			
				|  |  |  |  |           new_members := make([]*ServerSession, len(members) + 1) | 
		
	
		
			
				|  |  |  |  |           copy(new_members, members) | 
		
	
		
			
				|  |  |  |  |           new_members[len(members)] = incoming.Session | 
		
	
		
			
				|  |  |  |  |           channel.Members.Store(new_members) | 
		
	
		
			
				|  |  |  |  |           fmt.Printf("New Members: %+v\n", channel.Members.Load()) | 
		
	
		
			
				|  |  |  |  |       command := incoming.Packet | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |       if command.Mode == MODE_CHANNEL { | 
		
	
		
			
				|  |  |  |  |         switch command.Command { | 
		
	
		
			
				|  |  |  |  |         case CHANNEL_COMMAND_JOIN: | 
		
	
		
			
				|  |  |  |  |           members := channel.Members.Load().([]*ServerSession) | 
		
	
		
			
				|  |  |  |  |           if slices.Contains(members, incoming.Session) == false { | 
		
	
		
			
				|  |  |  |  |             new_members := make([]*ServerSession, len(members) + 1) | 
		
	
		
			
				|  |  |  |  |             copy(new_members, members) | 
		
	
		
			
				|  |  |  |  |             new_members[len(members)] = incoming.Session | 
		
	
		
			
				|  |  |  |  |             channel.Members.Store(new_members) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |             for _, mode_val := range(channel.Modes) { | 
		
	
		
			
				|  |  |  |  |               mode := mode_val.Load().(Mode) | 
		
	
		
			
				|  |  |  |  |               mode_val.Store(mode.Join(incoming.Session)) | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |           } | 
		
	
		
			
				|  |  |  |  |         case CHANNEL_COMMAND_LEAVE: | 
		
	
		
			
				|  |  |  |  |           members := channel.Members.Load().([]*ServerSession) | 
		
	
		
			
				|  |  |  |  |           idx := slices.Index(members, incoming.Session) | 
		
	
		
			
				|  |  |  |  |           if idx != -1 { | 
		
	
		
			
				|  |  |  |  |             new_members := make([]*ServerSession, len(members) - 1) | 
		
	
		
			
				|  |  |  |  |             copy(new_members, members[:idx]) | 
		
	
		
			
				|  |  |  |  |             copy(new_members[idx:], members[idx+1:]) | 
		
	
		
			
				|  |  |  |  |             channel.Members.Store(new_members) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |             for _, mode_val := range(channel.Modes) { | 
		
	
		
			
				|  |  |  |  |               mode := mode_val.Load().(Mode) | 
		
	
		
			
				|  |  |  |  |               mode_val.Store(mode.Leave(incoming.Session)) | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |           } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |       case CHANNEL_COMMAND_LEAVE: | 
		
	
		
			
				|  |  |  |  |         members := channel.Members.Load().([]*ServerSession) | 
		
	
		
			
				|  |  |  |  |         idx := slices.Index(members, incoming.Session) | 
		
	
		
			
				|  |  |  |  |         if idx != -1 { | 
		
	
		
			
				|  |  |  |  |           new_members := make([]*ServerSession, len(members) - 1) | 
		
	
		
			
				|  |  |  |  |           copy(new_members, members[:idx]) | 
		
	
		
			
				|  |  |  |  |           copy(new_members[idx:], members[idx+1:]) | 
		
	
		
			
				|  |  |  |  |           channel.Members.Store(new_members) | 
		
	
		
			
				|  |  |  |  |           fmt.Printf("New Members: %+v\n", channel.Members.Load()) | 
		
	
		
			
				|  |  |  |  |       } else { | 
		
	
		
			
				|  |  |  |  |         mode, has_mode := channel.Modes[command.Mode] | 
		
	
		
			
				|  |  |  |  |         if has_mode { | 
		
	
		
			
				|  |  |  |  |           members := channel.Members.Load().([]*ServerSession) | 
		
	
		
			
				|  |  |  |  |           mode_val := mode.Load().(Mode) | 
		
	
		
			
				|  |  |  |  |           new_mode := mode_val.Command(incoming.Session, command.Command, command.ReqID, command.Channel, members, command.Data) | 
		
	
		
			
				|  |  |  |  |           mode.Store(new_mode) | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |       } | 
		
	
		
			
				|  |  |  |  |     } else { | 
		
	
		
			
				|  |  |  |  |       mode, has_mode := channel.Modes[command.Mode] | 
		
	
		
			
				|  |  |  |  |       if has_mode { | 
		
	
		
			
				|  |  |  |  |         members := channel.Members.Load().([]*ServerSession) | 
		
	
		
			
				|  |  |  |  |         mode_val := mode.Load().(Mode) | 
		
	
		
			
				|  |  |  |  |         new_mode := mode_val.Command(incoming.Session, command.Command, command.ReqID, command.Channel, members, command.Data) | 
		
	
		
			
				|  |  |  |  |         mode.CompareAndSwap(mode_val, new_mode) | 
		
	
		
			
				|  |  |  |  |       } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
	
		
			
				
					|  |  |  | @ -86,6 +114,7 @@ func NewChannel(modes map[ModeID]Mode) (*Channel, error) { | 
		
	
		
			
				|  |  |  |  |    | 
		
	
		
			
				|  |  |  |  |   channel := &Channel{ | 
		
	
		
			
				|  |  |  |  |     Commands: make(chan SessionChannelCommand, CHANNEL_COMMAND_BUFFER_SIZE), | 
		
	
		
			
				|  |  |  |  |     ClosedSessions: make(chan *ServerSession, CHANNEL_CLOSE_BUFFER_SIZE), | 
		
	
		
			
				|  |  |  |  |     Modes: initial_modes, | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  |   channel.Members.Store([]*ServerSession{}) | 
		
	
	
		
			
				
					|  |  |  | @ -96,6 +125,8 @@ func NewChannel(modes map[ModeID]Mode) (*Channel, error) { | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | type Mode interface { | 
		
	
		
			
				|  |  |  |  |   Join(session *ServerSession) Mode | 
		
	
		
			
				|  |  |  |  |   Leave(session *ServerSession) Mode | 
		
	
		
			
				|  |  |  |  |   Command(session *ServerSession, command byte, request_id uuid.UUID, channel_id ChannelID, members []*ServerSession, data []byte) Mode | 
		
	
		
			
				|  |  |  |  |   Data(session *ServerSession, channel_id ChannelID, members []*ServerSession, data []byte) | 
		
	
		
			
				|  |  |  |  | } | 
		
	
	
		
			
				
					|  |  |  | @ -119,6 +150,14 @@ func multiplex(packet *Packet, sessions []*ServerSession) { | 
		
	
		
			
				|  |  |  |  | type RawMode struct { | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func(mode RawMode) Join(session *ServerSession) Mode { | 
		
	
		
			
				|  |  |  |  |   return mode | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func(mode RawMode) Leave(session *ServerSession) Mode { | 
		
	
		
			
				|  |  |  |  |   return mode | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func(mode RawMode) Command(session *ServerSession, command byte, request_id uuid.UUID, channel_id ChannelID, members []*ServerSession, data []byte) Mode { | 
		
	
		
			
				|  |  |  |  |   return mode | 
		
	
		
			
				|  |  |  |  | } | 
		
	
	
		
			
				
					|  |  |  | @ -139,6 +178,14 @@ type AudioMode struct { | 
		
	
		
			
				|  |  |  |  |   SampleRate SampleRate | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func(mode AudioMode) Join(session *ServerSession) Mode { | 
		
	
		
			
				|  |  |  |  |   return mode | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func(mode AudioMode) Leave(session *ServerSession) Mode { | 
		
	
		
			
				|  |  |  |  |   return mode | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func(mode AudioMode) Command(session *ServerSession, command byte, request_id uuid.UUID, channel_id ChannelID, members []*ServerSession, data []byte) Mode { | 
		
	
		
			
				|  |  |  |  |   switch command { | 
		
	
		
			
				|  |  |  |  |   case AUDIO_SET_SAMPLE_RATE: | 
		
	
	
		
			
				
					|  |  |  | 
 |