Add option 'noenter' to channel configuration and implement support.
[umurmur.git] / src / messagehandler.c
1 /* Copyright (C) 2009-2010, Martin Johansson <martin@fatbob.nu>
2    Copyright (C) 2005-2010, Thorvald Natvig <thorvald@natvig.com>
3
4    All rights reserved.
5
6    Redistribution and use in source and binary forms, with or without
7    modification, are permitted provided that the following conditions
8    are met:
9
10    - Redistributions of source code must retain the above copyright notice,
11      this list of conditions and the following disclaimer.
12    - Redistributions in binary form must reproduce the above copyright notice,
13      this list of conditions and the following disclaimer in the documentation
14      and/or other materials provided with the distribution.
15    - Neither the name of the Developers nor the names of its contributors may
16      be used to endorse or promote products derived from this software without
17      specific prior written permission.
18
19    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
23    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31 #include <string.h>
32 #include <openssl/aes.h>
33
34 #include "log.h"
35 #include "list.h"
36 #include "client.h"
37 #include "messages.h"
38 #include "crypt.h"
39 #include "channel.h"
40 #include "conf.h"
41 #include "voicetarget.h"
42
43 extern channel_t *defaultChan;
44 extern int iCodecAlpha, iCodecBeta;
45 extern bool_t bPreferAlpha;
46
47 static void sendServerReject(client_t *client, const char *reason, MumbleProto__Reject__RejectType type)
48 {
49         message_t *msg = Msg_create(Reject);
50         msg->payload.reject->reason = strdup(reason);
51         msg->payload.reject->type = type;
52         msg->payload.reject->has_type = true;
53         Client_send_message(client, msg);
54         
55         Log_info("Server reject reason: %s. Disconnecting session %d - %s@%s:%d",
56                          reason,
57                          client->sessionId,
58                          client->playerName,
59                          inet_ntoa(client->remote_tcp.sin_addr),
60                          ntohs(client->remote_tcp.sin_port));
61         
62 }
63
64 static void sendPermissionDenied(client_t *client, const char *reason)
65 {
66         message_t *msg = Msg_create(PermissionDenied);
67         msg->payload.permissionDenied->has_type = true;
68         msg->payload.permissionDenied->type = MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__Text;
69         msg->payload.permissionDenied->reason = strdup(reason);
70         Client_send_message(client, msg);
71 }
72
73 void Mh_handle_message(client_t *client, message_t *msg)
74 {
75         message_t *sendmsg = NULL;
76         channel_t *ch_itr = NULL;
77         client_t *client_itr;
78
79         if (!client->authenticated && !(msg->messageType == Authenticate ||
80                                                                         msg->messageType == Version)) {
81                 goto out;
82         }       
83         switch (msg->messageType) {
84         case Authenticate:
85                 /*
86                  * 1. Check stuff, Serverreject if not ok
87                  * 2. Setup UDP encryption -> MessageCryptSetup
88                  * 3. (Enter channel)
89                  * 4. MessageChannelAdd + MessageChannelDescUpdate for all channels
90                  * 5. (MessageChannelLink)
91                  * 6. MessageServerJoin
92                  * 7. MessagePlayerMove
93                  * 8. MessageServerJoin for all connected users
94                  * 9. PlayerDeaf/PlayerMute/PlayerSelfMuteDeaf for all users it applies to
95                  * 10. MessageServerSync
96                  */
97                                 
98                 Log_debug("Authenticate message received");
99                 Log_debug("Username: %s", msg->payload.authenticate->username);
100                 
101                 client->authenticated = true;
102                 
103                 client_itr = NULL;
104                 while (Client_iterate(&client_itr) != NULL) {
105                         if (!IS_AUTH(client_itr))
106                                 continue;
107                         if (client_itr->playerName && strncmp(client_itr->playerName, msg->payload.authenticate->username, MAX_TEXT) == 0) {
108                                 char buf[64];
109                                 sprintf(buf, "Username already in use");
110                                 Log_debug("Username already in use");
111                                 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__UsernameInUse);
112                                 goto disconnect;
113                         }                               
114                 }
115                 if (msg->payload.authenticate->password && strncmp(getStrConf(PASSPHRASE), msg->payload.authenticate->password, MAX_TEXT) != 0) {
116                         char buf[64];
117                         sprintf(buf, "Wrong server password");
118                         Log_debug("Wrong server password: %s", msg->payload.authenticate->password);
119                         sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__WrongServerPW);
120                         goto disconnect;
121                 }                               
122                 if (strlen(msg->payload.authenticate->username) == 0 ||
123                         strlen(msg->payload.authenticate->username) >= MAX_TEXT) { /* XXX - other invalid names? */
124                         char buf[64];
125                         sprintf(buf, "Invalid username");
126                         Log_debug("Invalid username");
127                         sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__InvalidUsername);
128                         goto disconnect;
129                 }                               
130
131                 if (Client_count() >= getIntConf(MAX_CLIENTS)) {
132                         char buf[64];
133                         sprintf(buf, "Server is full (max %d users)", getIntConf(MAX_CLIENTS));
134                         sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__ServerFull);
135                         goto disconnect;
136                 }
137                 
138                 /* Name & password */
139                 client->playerName = strdup(msg->payload.authenticate->username);                               
140                 
141                 /* Setup UDP encryption */
142                 CryptState_init(&client->cryptState);
143                 CryptState_genKey(&client->cryptState);
144                 sendmsg = Msg_create(CryptSetup);
145                 sendmsg->payload.cryptSetup->has_key = true;
146                 sendmsg->payload.cryptSetup->key.data = client->cryptState.raw_key;
147                 sendmsg->payload.cryptSetup->key.len = AES_BLOCK_SIZE;
148                 sendmsg->payload.cryptSetup->has_server_nonce = true;
149                 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.encrypt_iv;
150                 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
151                 sendmsg->payload.cryptSetup->has_client_nonce = true;
152                 sendmsg->payload.cryptSetup->client_nonce.data = client->cryptState.decrypt_iv;
153                 sendmsg->payload.cryptSetup->client_nonce.len = AES_BLOCK_SIZE;
154                 Client_send_message(client, sendmsg);
155
156                 /* Channel stuff */
157                 Chan_playerJoin(defaultChan, client); /* Join default channel */
158
159                 /* Codec version */
160                 if (msg->payload.authenticate->n_celt_versions > MAX_CODECS)
161                         Log_warn("Client has more than %d CELT codecs. Ignoring %d codecs",
162                                          MAX_CODECS, msg->payload.authenticate->n_celt_versions - MAX_CODECS);
163                 
164                 Log_debug("Client %d has %d CELT codecs", client->sessionId, msg->payload.authenticate->n_celt_versions);
165                 if (msg->payload.authenticate->n_celt_versions > 0) {
166                         int i;
167                         client->codec_count = msg->payload.authenticate->n_celt_versions > MAX_CODECS ?
168                                 MAX_CODECS : msg->payload.authenticate->n_celt_versions;
169                         for (i = 0; i < client->codec_count; i++) {
170                                 client->codecs[i] = msg->payload.authenticate->celt_versions[i];
171                                 Log_debug("Client %d CELT codec ver 0x%x", client->sessionId, client->codecs[i]);
172                         }
173                 } else {
174                         client->codecs[0] = (int32_t)0x8000000a;
175                         client->codec_count = 1;
176                 }
177                 
178                 recheckCodecVersions();
179                 
180                 sendmsg = Msg_create(CodecVersion);
181                 sendmsg->payload.codecVersion->alpha = iCodecAlpha;
182                 sendmsg->payload.codecVersion->beta = iCodecBeta;
183                 sendmsg->payload.codecVersion->prefer_alpha = bPreferAlpha;
184                 Client_send_message(client, sendmsg);
185                 
186                 /* Iterate channels and send channel info */
187                 ch_itr = NULL;
188                 Chan_iterate(&ch_itr);
189                 do {
190                         sendmsg = Msg_create(ChannelState);
191                         sendmsg->payload.channelState->has_channel_id = true;
192                         sendmsg->payload.channelState->channel_id = ch_itr->id;
193                         if (ch_itr->id != 0) {
194                                 sendmsg->payload.channelState->has_parent = true;
195                                 sendmsg->payload.channelState->parent = ch_itr->parent->id;
196                         }
197                         sendmsg->payload.channelState->name = strdup(ch_itr->name);
198                         if (strlen(ch_itr->desc) > 0) {
199                                 sendmsg->payload.channelState->description = strdup(ch_itr->desc);
200                         }
201                         Log_debug("Send channel info: %s", sendmsg->payload.channelState->name);
202                         Client_send_message(client, sendmsg);
203                         
204                         Chan_iterate(&ch_itr);
205                 } while (ch_itr != NULL);
206
207                 /* Not supporting channel links yet */
208                 
209                 /* Send user state for connecting user to other users */
210                 sendmsg = Msg_create(UserState);
211                 sendmsg->payload.userState->has_session = true;
212                 sendmsg->payload.userState->session = client->sessionId;
213                 sendmsg->payload.userState->has_user_id = true;
214                 sendmsg->payload.userState->user_id = client->sessionId;
215                 sendmsg->payload.userState->name = strdup(client->playerName);
216                 sendmsg->payload.userState->has_channel_id = true;
217                 sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
218                 
219                 Client_send_message_except(client, sendmsg);
220
221                 client_itr = NULL;
222                 while (Client_iterate(&client_itr) != NULL) {
223                         if (!IS_AUTH(client_itr))
224                                 continue;
225                         sendmsg = Msg_create(UserState);
226                         sendmsg->payload.userState->has_session = true;
227                         sendmsg->payload.userState->session = client_itr->sessionId;
228                         sendmsg->payload.userState->name = strdup(client_itr->playerName);
229                         sendmsg->payload.userState->has_channel_id = true;
230                         sendmsg->payload.userState->channel_id = ((channel_t *)client_itr->channel)->id;
231
232                         /* Only self_mute/deaf supported */
233                         if (client_itr->deaf) {
234                                 sendmsg->payload.userState->has_self_deaf = true;
235                                 sendmsg->payload.userState->self_deaf = true;
236                         }
237                         if (client_itr->mute) {
238                                 sendmsg->payload.userState->has_self_mute = true;
239                                 sendmsg->payload.userState->self_mute = true;
240                         }
241                         Client_send_message(client, sendmsg);
242                 }
243
244                 /* Sync message */
245                 sendmsg = Msg_create(ServerSync);
246                 sendmsg->payload.serverSync->has_session = true;
247                 sendmsg->payload.serverSync->session = client->sessionId;
248                 sendmsg->payload.serverSync->welcome_text = strdup(getStrConf(WELCOMETEXT));
249                 sendmsg->payload.serverSync->has_max_bandwidth = true;
250                 sendmsg->payload.serverSync->max_bandwidth = getIntConf(MAX_BANDWIDTH);
251                 sendmsg->payload.serverSync->has_allow_html = true;
252                 sendmsg->payload.serverSync->allow_html = true; /* Support this? */
253                 Client_send_message(client, sendmsg);
254                 
255                 Log_info("User %s authenticated", client->playerName);
256                 break;
257                 
258         case Ping:
259                 if (msg->payload.ping->has_good)
260                         client->cryptState.uiRemoteGood = msg->payload.ping->good;
261                 if (msg->payload.ping->has_late)
262                         client->cryptState.uiRemoteLate = msg->payload.ping->late;
263                 if (msg->payload.ping->has_lost)
264                         client->cryptState.uiRemoteLost = msg->payload.ping->lost;
265                 if (msg->payload.ping->has_resync)
266                         client->cryptState.uiRemoteResync = msg->payload.ping->resync;
267
268                 Log_debug("Ping <-: %d %d %d %d",
269                                   client->cryptState.uiRemoteGood, client->cryptState.uiRemoteLate,
270                                   client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync
271                         );
272                 
273                 /* Ignoring the double values since they don't seem to be used */
274                 
275                 sendmsg = Msg_create(Ping);
276
277                 sendmsg->payload.ping->timestamp = msg->payload.ping->timestamp;
278                 sendmsg->payload.ping->has_timestamp = true;
279                 sendmsg->payload.ping->good = client->cryptState.uiGood;
280                 sendmsg->payload.ping->has_good = true;
281                 sendmsg->payload.ping->late = client->cryptState.uiLate;
282                 sendmsg->payload.ping->has_late = true;
283                 sendmsg->payload.ping->lost = client->cryptState.uiLost;
284                 sendmsg->payload.ping->has_lost = true;
285                 sendmsg->payload.ping->resync = client->cryptState.uiResync;
286                 sendmsg->payload.ping->has_resync = true;
287
288                 Client_send_message(client, sendmsg);
289                 Log_debug("Ping ->: %d %d %d %d",
290                                   client->cryptState.uiGood, client->cryptState.uiLate,
291                                   client->cryptState.uiLost, client->cryptState.uiResync);
292
293                 break;
294         case CryptSetup:
295                 Log_debug("Voice channel crypt resync requested");
296                 if (!msg->payload.cryptSetup->has_client_nonce) {
297                         sendmsg = Msg_create(CryptSetup);
298                         sendmsg->payload.cryptSetup->has_server_nonce = true;
299                         sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.decrypt_iv;
300                         sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
301                         Client_send_message(client, sendmsg);
302                 } else {
303                         memcpy(client->cryptState.decrypt_iv, msg->payload.cryptSetup->client_nonce.data, AES_BLOCK_SIZE);
304                         client->cryptState.uiResync++;
305                 }
306                 break;
307         case UserState:
308                 /* Only allow state changes for for the self user */
309                 if (msg->payload.userState->has_session &&
310                         msg->payload.userState->session != client->sessionId) {
311                         sendPermissionDenied(client, "Permission denied");
312                         break;
313                 }
314                 if (msg->payload.userState->has_user_id || msg->payload.userState->has_mute ||
315                         msg->payload.userState->has_deaf || msg->payload.userState->has_suppress ||
316                         msg->payload.userState->has_texture) {
317                         
318                         sendPermissionDenied(client, "Not supported by uMurmur");
319                         break;
320                 }
321                 if (msg->payload.userState->has_self_deaf) {
322                         client->deaf = msg->payload.userState->self_deaf;
323                 }
324                 if (msg->payload.userState->has_self_mute) {
325                         client->mute = msg->payload.userState->self_mute;                       
326                 }
327                 if (msg->payload.userState->has_channel_id) {
328                         int leave_id;
329                         if (!Chan_playerJoin_id_test(msg->payload.userState->channel_id))
330                                 break;
331                         leave_id = Chan_playerJoin_id(msg->payload.userState->channel_id, client);
332                         if (leave_id > 0) {
333                                 Log_debug("Removing channel ID %d", leave_id);
334                                 sendmsg = Msg_create(ChannelRemove);
335                                 sendmsg->payload.channelRemove->channel_id = leave_id;
336                         }
337                 }
338                 if (msg->payload.userState->plugin_context != NULL) {
339                         if (client->context)
340                                 free(client->context);
341                         client->context = strdup(msg->payload.userState->plugin_context);
342                         if (client->context == NULL)
343                                 Log_fatal("Out of memory");
344                         
345                         break; /* Don't inform other users about this state */
346                 }
347                 
348                 /* Re-use message */
349                 Msg_inc_ref(msg);
350                 msg->payload.userState->has_actor = true;
351                 msg->payload.userState->actor = client->sessionId;
352                 Client_send_message_except(NULL, msg);
353
354                 /* Need to send remove channel message _after_ UserState message */
355                 if (sendmsg != NULL)
356                         Client_send_message_except(NULL, sendmsg);
357                 break;
358                 
359         case TextMessage:
360                 msg->payload.textMessage->has_actor = true;
361                 msg->payload.textMessage->actor = client->sessionId;
362
363                 /* XXX - HTML is allowed and can't be turned off */
364                 if (msg->payload.textMessage->n_tree_id > 0) {
365                         sendPermissionDenied(client, "Tree message not supported");
366                         break;
367                 }
368                         
369                 if (msg->payload.textMessage->n_channel_id > 0) { /* To channel */
370                         int i;
371                         channel_t *ch_itr;
372                         for (i = 0; i < msg->payload.textMessage->n_channel_id; i++) {
373                                 ch_itr = NULL;
374                                 do {
375                                         Chan_iterate(&ch_itr);
376                                 } while (ch_itr != NULL && ch_itr->id != msg->payload.textMessage->channel_id[i]);
377                                 if (ch_itr == NULL)
378                                         Log_warn("Channel id %d not found - ignoring.", msg->payload.textMessage->channel_id[i]);
379                                 else {
380                                         struct dlist *itr;
381                                         list_iterate(itr, &ch_itr->clients) {
382                                                 client_t *c;
383                                                 c = list_get_entry(itr, client_t, chan_node);
384                                                 if (c != client && !c->deaf) {
385                                                         Msg_inc_ref(msg);
386                                                         Client_send_message(c, msg);
387                                                         Log_debug("Text message to session ID %d", c->sessionId);
388                                                 }
389                                         }
390                                 }
391                         } /* for */
392                 }
393                 if (msg->payload.textMessage->n_session > 0) { /* To user */
394                         int i;
395                         client_t *itr;
396                         for (i = 0; i < msg->payload.textMessage->n_session; i++) {
397                                 itr = NULL;
398                                 while (Client_iterate(&itr) != NULL) {
399                                         if (!IS_AUTH(itr))
400                                                 continue;
401                                         if (itr->sessionId == msg->payload.textMessage->session[i]) {
402                                                 if (!itr->deaf) {
403                                                         Msg_inc_ref(msg);
404                                                         Client_send_message(itr, msg);
405                                                         Log_debug("Text message to session ID %d", itr->sessionId);
406                                                 }
407                                                 break;
408                                         }
409                                 }
410                                 if (itr == NULL)
411                                         Log_warn("TextMessage: Session ID %d not found", msg->payload.textMessage->session[i]);
412                         } /* for */
413                 }
414                 break;
415
416         case VoiceTarget:
417         {
418                 int i, j, count, targetId = msg->payload.voiceTarget->id;
419                 struct _MumbleProto__VoiceTarget__Target *target;
420
421                 if (!targetId || targetId >= 0x1f)
422                         break;
423                 Voicetarget_add_id(client, targetId);
424                 count = msg->payload.voiceTarget->n_targets;
425                 if (!count)
426                         break;
427                 for (i = 0; i < count; i++) {
428                         target = msg->payload.voiceTarget->targets[i];
429                         for (j = 0; j < target->n_session; j++)
430                                 Voicetarget_add_session(client, targetId, target->session[j]);
431                         if (target->has_channel_id) {
432                                 if (target->has_links || target->has_children)
433                                         Log_warn("Whisper to children or linked channels not implemented. Ignoring.");
434                                 Voicetarget_add_channel(client, targetId, target->channel_id);
435                         }
436                 }
437                 break;
438         }
439         case Version:
440                 Log_debug("Version message received");
441                 if (msg->payload.version->has_version) {
442                         client->version = msg->payload.version->version;
443                         Log_debug("Client version 0x%x", client->version);
444                 }
445                 if (msg->payload.version->release) {
446                         if (client->release) free(client->release);
447                         client->release = strdup(msg->payload.version->release);
448                         Log_debug("Client release %s", client->release);
449                 }
450                 if (msg->payload.version->os) {
451                         if (client->os) free(client->os);                       
452                         client->os = strdup(msg->payload.version->os);
453                         Log_debug("Client OS %s", client->os);
454                 }
455                 break;
456         case PermissionQuery:
457                 Msg_inc_ref(msg); /* Re-use message */
458                 msg->payload.permissionQuery->has_permissions = true;
459                 msg->payload.permissionQuery->permissions = PERM_DEFAULT;
460                 
461                 Client_send_message(client, msg);
462                 break;
463         case UDPTunnel:
464                 Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
465             break;
466         case ChannelState:
467         {
468                 channel_t *ch_itr, *parent, *newchan;
469                 int leave_id;           
470                 /* Don't allow any changes to existing channels */
471                 if (msg->payload.channelState->has_channel_id) {
472                         sendPermissionDenied(client, "Not supported by uMurmur");
473                         break;
474                 }
475                 /* Must have parent */
476                 if (!msg->payload.channelState->has_parent) {
477                         sendPermissionDenied(client, "Not supported by uMurmur");
478                         break;
479                 }
480                 /* Must have name */
481                 if (msg->payload.channelState->name == NULL) {
482                         sendPermissionDenied(client, "Not supported by uMurmur");
483                         break;
484                 }
485                 /* Must be temporary channel */
486                 if (msg->payload.channelState->temporary != true) {
487                         sendPermissionDenied(client, "Only temporary channels are supported by uMurmur");
488                         break;
489                 }
490                 /* Check channel name is OK */
491                 if (strlen(msg->payload.channelState->name) > MAX_TEXT) {
492                         sendPermissionDenied(client, "Channel name too long");
493                         break;
494                 }
495                         
496                 parent = Chan_fromId(msg->payload.channelState->parent);
497                 if (parent == NULL)
498                         break;
499                 ch_itr = NULL;
500                 while (Chan_iterate_siblings(parent, &ch_itr) != NULL) {
501                         if (strcmp(ch_itr->name, msg->payload.channelState->name) == 0) {
502                                 sendPermissionDenied(client, "Channel already exists");
503                                 break;
504                         }
505                 }
506                 if (ch_itr != NULL)
507                         break;
508                 
509                 /* Disallow temporary channels as siblings to temporary channels */
510                 if (parent->temporary) {
511                         sendPermissionDenied(client, "Parent channel is temporary channel");
512                         break;
513                 }
514                         
515                 /* XXX - Murmur looks for "\\w" and sends perm denied if not found.
516                  * I don't know why so I don't do that here...
517                  */
518
519                 /* Create the channel */
520                 newchan = Chan_createChannel(msg->payload.channelState->name,
521                                                                          msg->payload.channelState->description);
522                 newchan->temporary = true;
523                 Chan_addChannel(parent, newchan);
524                 msg->payload.channelState->has_channel_id = true;
525                 msg->payload.channelState->channel_id = newchan->id;
526                 Msg_inc_ref(msg);
527                 Client_send_message_except(NULL, msg);
528
529                 /* Join the creating user */
530                 sendmsg = Msg_create(UserState);
531                 sendmsg->payload.userState->has_session = true;
532                 sendmsg->payload.userState->session = client->sessionId;
533                 sendmsg->payload.userState->has_channel_id = true;
534                 sendmsg->payload.userState->channel_id = newchan->id;
535                 Client_send_message_except(NULL, sendmsg);
536                 
537                 leave_id = Chan_playerJoin(newchan, client);
538                 if (leave_id > 0) {
539                         Log_debug("Removing channel ID %d", leave_id);
540                         sendmsg = Msg_create(ChannelRemove);
541                         sendmsg->payload.channelRemove->channel_id = leave_id;
542                         Client_send_message_except(NULL, sendmsg);
543                 }
544         }               
545         break;
546
547                 /* Permission denied for all these messages. Not implemented. */
548         case ChannelRemove:
549         case ContextAction:
550         case ContextActionAdd:
551         case ACL:
552         case BanList:
553         case UserList:
554         case QueryUsers:
555                 sendPermissionDenied(client, "Not supported by uMurmur");
556                 break;
557                                 
558         default:
559                 Log_warn("Message %d not handled", msg->messageType);
560                 break;
561         }
562 out:
563         Msg_free(msg);
564         return;
565         
566 disconnect:
567         Msg_free(msg);
568         Client_close(client);
569 }
570