diff --git a/message.go b/message.go index 5ebb410..3e25fae 100644 --- a/message.go +++ b/message.go @@ -158,10 +158,29 @@ func (server *Server) handlePingMessage(client *Client, msg *Message) { }) } -func (server *Server) handleChannelAddMessage(client *Client, msg *Message) { -} - func (server *Server) handleChannelRemoveMessage(client *Client, msg *Message) { + chanremove := &mumbleproto.ChannelRemove{} + err := proto.Unmarshal(msg.buf, chanremove) + if err != nil { + client.Panic(err.String()) + return + } + + if chanremove.ChannelId == nil { + return + } + + channel, exists := server.Channels[int(*chanremove.ChannelId)] + if !exists { + return + } + + if !server.HasPermission(client, channel, WritePermission) { + client.sendPermissionDenied(client, channel, WritePermission) + return + } + + server.RemoveChannel(channel) } // Handle channel state change. diff --git a/server.go b/server.go index a975ab6..34397b3 100644 --- a/server.go +++ b/server.go @@ -830,7 +830,7 @@ func (server *Server) handleIncomingMessage(client *Client, msg *Message) { case MessagePing: server.handlePingMessage(msg.client, msg) case MessageChannelRemove: - server.handlePingMessage(msg.client, msg) + server.handleChannelRemoveMessage(msg.client, msg) case MessageChannelState: server.handleChannelStateMessage(msg.client, msg) case MessageUserState: @@ -1109,6 +1109,50 @@ func (s *Server) removeRegisteredUserFromChannel(uid uint32, channel *Channel) { } } +// Remove a channel +func (server *Server) RemoveChannel(channel *Channel) { + // Can't remove root + if channel.parent == nil { + return + } + + // Remove all links + for _, linkedChannel := range channel.Links { + linkedChannel.Links[channel.Id] = nil, false + } + + // Remove all subchannels + for _, subChannel := range channel.children { + server.RemoveChannel(subChannel) + } + + // Remove all clients + for _, client := range channel.clients { + target := channel.parent + for target.parent != nil && !server.HasPermission(client, target, EnterPermission) { + target = target.parent + } + + userstate := &mumbleproto.UserState{} + userstate.Session = proto.Uint32(client.Session) + userstate.ChannelId = proto.Uint32(uint32(target.Id)) + server.userEnterChannel(client, target, userstate) + if err := server.broadcastProtoMessage(MessageUserState, userstate); err != nil { + server.Panicf("%v", err) + } + } + + // Remove the channel itself + parent := channel.parent + parent.children[channel.Id] = nil, false + chanremove := &mumbleproto.ChannelRemove{ + ChannelId: proto.Uint32(uint32(channel.Id)), + } + if err := server.broadcastProtoMessage(MessageChannelRemove, chanremove); err != nil { + server.Panicf("%v", err) + } +} + // Is the incoming connection conn banned? func (server *Server) IsBanned(conn net.Conn) bool { server.banlock.RLock()