Send channel links info at client connect
[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 "messagehandler.h"
39 #include "crypt.h"
40 #include "channel.h"
41 #include "conf.h"
42 #include "voicetarget.h"
43
44 #define MAX_TEXT 512
45
46 extern channel_t *defaultChan;
47 extern int iCodecAlpha, iCodecBeta;
48 extern bool_t bPreferAlpha;
49
50 static void sendServerReject(client_t *client, const char *reason, MumbleProto__Reject__RejectType type)
51 {
52         message_t *msg = Msg_create(Reject);
53         msg->payload.reject->reason = strdup(reason);
54         msg->payload.reject->type = type;
55         msg->payload.reject->has_type = true;
56         Client_send_message(client, msg);
57         
58         Log_info_client(client, "Server reject reason: %s", reason);
59 }
60
61 static void sendPermissionDenied(client_t *client, const char *reason)
62 {
63         message_t *msg = Msg_create(PermissionDenied);
64         msg->payload.permissionDenied->has_type = true;
65         msg->payload.permissionDenied->type = MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__Text;
66         msg->payload.permissionDenied->reason = strdup(reason);
67         Client_send_message(client, msg);
68 }
69
70 void Mh_handle_message(client_t *client, message_t *msg)
71 {
72         message_t *sendmsg = NULL;
73         channel_t *ch_itr = NULL;
74         client_t *client_itr;
75
76         if (!client->authenticated && !(msg->messageType == Authenticate ||
77                                                                         msg->messageType == Version)) {
78                 goto out;
79         }       
80         switch (msg->messageType) {
81         case Authenticate:
82                                 
83                 Log_debug("Authenticate message received");
84                 Log_debug("Username: %s", msg->payload.authenticate->username);
85                 
86                 client->authenticated = true;
87                 
88                 client_itr = NULL;
89                 while (Client_iterate(&client_itr) != NULL) {
90                         if (!IS_AUTH(client_itr))
91                                 continue;
92                         if (client_itr->username && strncmp(client_itr->username, msg->payload.authenticate->username, MAX_TEXT) == 0) {
93                                 char buf[64];
94                                 sprintf(buf, "Username already in use");
95                                 Log_debug("Username already in use");
96                                 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__UsernameInUse);
97                                 goto disconnect;
98                         }                               
99                 }
100                 if (strlen(getStrConf(PASSPHRASE)) > 0) {
101                         if (!msg->payload.authenticate->password || strncmp(getStrConf(PASSPHRASE), msg->payload.authenticate->password, MAX_TEXT) != 0) {
102                                 char buf[64];
103                                 sprintf(buf, "Wrong server password");
104                                 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__WrongServerPW);
105                                 Log_debug("Wrong server password: %s", msg->payload.authenticate->password);
106                                 goto disconnect;
107                         }
108                 }                               
109                 if (strlen(msg->payload.authenticate->username) == 0 ||
110                         strlen(msg->payload.authenticate->username) >= MAX_TEXT) { /* XXX - other invalid names? */
111                         char buf[64];
112                         sprintf(buf, "Invalid username");
113                         Log_debug("Invalid username");
114                         sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__InvalidUsername);
115                         goto disconnect;
116                 }                               
117
118                 if (Client_count() >= getIntConf(MAX_CLIENTS)) {
119                         char buf[64];
120                         sprintf(buf, "Server is full (max %d users)", getIntConf(MAX_CLIENTS));
121                         sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__ServerFull);
122                         goto disconnect;
123                 }
124                 
125                 /* Name & password */
126                 client->username = strdup(msg->payload.authenticate->username);                         
127                 
128                 /* Setup UDP encryption */
129                 CryptState_init(&client->cryptState);
130                 CryptState_genKey(&client->cryptState);
131                 sendmsg = Msg_create(CryptSetup);
132                 sendmsg->payload.cryptSetup->has_key = true;
133                 sendmsg->payload.cryptSetup->key.data = client->cryptState.raw_key;
134                 sendmsg->payload.cryptSetup->key.len = AES_BLOCK_SIZE;
135                 sendmsg->payload.cryptSetup->has_server_nonce = true;
136                 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.encrypt_iv;
137                 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
138                 sendmsg->payload.cryptSetup->has_client_nonce = true;
139                 sendmsg->payload.cryptSetup->client_nonce.data = client->cryptState.decrypt_iv;
140                 sendmsg->payload.cryptSetup->client_nonce.len = AES_BLOCK_SIZE;
141                 Client_send_message(client, sendmsg);
142
143                 /* Channel stuff */
144                 Chan_userJoin(defaultChan, client); /* Join default channel */
145
146                 /* Codec version */             
147                 Log_debug("Client %d has %d CELT codecs", client->sessionId,
148                                   msg->payload.authenticate->n_celt_versions);
149                 if (msg->payload.authenticate->n_celt_versions > 0) {
150                         int i;
151                         codec_t *codec_itr;
152                         client->codec_count = msg->payload.authenticate->n_celt_versions;
153                         
154                         for (i = 0; i < client->codec_count; i++)
155                         Client_codec_add(client, msg->payload.authenticate->celt_versions[i]);
156                         codec_itr = NULL;
157                         while (Client_codec_iterate(client, &codec_itr) != NULL)
158                                 Log_debug("Client %d CELT codec ver 0x%x", client->sessionId, codec_itr->codec);
159                                 
160                 } else {
161                         Client_codec_add(client, (int32_t)0x8000000a);
162                         client->codec_count = 1;
163                 }
164                 
165                 recheckCodecVersions();
166                 
167                 sendmsg = Msg_create(CodecVersion);
168                 sendmsg->payload.codecVersion->alpha = iCodecAlpha;
169                 sendmsg->payload.codecVersion->beta = iCodecBeta;
170                 sendmsg->payload.codecVersion->prefer_alpha = bPreferAlpha;
171                 Client_send_message(client, sendmsg);
172                 
173                 /* Iterate channels and send channel info */
174                 ch_itr = NULL;
175                 while (Chan_iterate(&ch_itr) != NULL) {
176                         sendmsg = Msg_create(ChannelState);
177                         sendmsg->payload.channelState->has_channel_id = true;
178                         sendmsg->payload.channelState->channel_id = ch_itr->id;
179                         if (ch_itr->id != 0) {
180                                 sendmsg->payload.channelState->has_parent = true;
181                                 sendmsg->payload.channelState->parent = ch_itr->parent->id;
182                         }
183                         sendmsg->payload.channelState->name = strdup(ch_itr->name);
184                         if (ch_itr->desc)
185                                 sendmsg->payload.channelState->description = strdup(ch_itr->desc);
186                         Log_debug("Send channel info: %s", sendmsg->payload.channelState->name);
187                         Client_send_message(client, sendmsg);                   
188                 }
189
190                 /* Iterate channels and send channel links info */
191                 ch_itr = NULL;
192                 while (Chan_iterate(&ch_itr) != NULL) {
193                         if (ch_itr->linkcount > 0) { /* Has links */
194                                 uint32_t *links;
195                                 int i = 0;
196                                 struct dlist *itr;
197                                 
198                                 sendmsg = Msg_create(ChannelState);
199                                 sendmsg->payload.channelState->has_channel_id = true;
200                                 sendmsg->payload.channelState->channel_id = ch_itr->id;
201                                 sendmsg->payload.channelState->n_links = ch_itr->linkcount;
202                                 
203                                 links = (uint32_t *)malloc(ch_itr->linkcount * sizeof(uint32_t));
204                                 list_iterate(itr, &ch_itr->channel_links) { /* Iterate links */
205                                         channel_t *ch;
206                                         ch = list_get_entry(itr, channel_t, link_node);
207                                         links[i++] = ch->id;
208                                 }
209                                 sendmsg->payload.channelState->links = links;
210                                 Client_send_message(client, sendmsg);
211                         }
212                 }
213                 
214                 /* Send user state for connecting user to other users */
215                 sendmsg = Msg_create(UserState);
216                 sendmsg->payload.userState->has_session = true;
217                 sendmsg->payload.userState->session = client->sessionId;
218                 sendmsg->payload.userState->has_user_id = true;
219                 sendmsg->payload.userState->user_id = client->sessionId;
220                 sendmsg->payload.userState->name = strdup(client->username);
221                 sendmsg->payload.userState->has_channel_id = true;
222                 sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
223                 
224                 Client_send_message_except(client, sendmsg);
225
226                 client_itr = NULL;
227                 while (Client_iterate(&client_itr) != NULL) {
228                         if (!IS_AUTH(client_itr))
229                                 continue;
230                         sendmsg = Msg_create(UserState);
231                         sendmsg->payload.userState->has_session = true;
232                         sendmsg->payload.userState->session = client_itr->sessionId;
233                         sendmsg->payload.userState->name = strdup(client_itr->username);
234                         sendmsg->payload.userState->has_channel_id = true;
235                         sendmsg->payload.userState->channel_id = ((channel_t *)client_itr->channel)->id;
236
237                         /* Only self_mute/deaf supported */
238                         if (client_itr->deaf) {
239                                 sendmsg->payload.userState->has_self_deaf = true;
240                                 sendmsg->payload.userState->self_deaf = true;
241                         }
242                         if (client_itr->mute) {
243                                 sendmsg->payload.userState->has_self_mute = true;
244                                 sendmsg->payload.userState->self_mute = true;
245                         }
246                         Client_send_message(client, sendmsg);
247                 }
248
249                 /* Sync message */
250                 sendmsg = Msg_create(ServerSync);
251                 sendmsg->payload.serverSync->has_session = true;
252                 sendmsg->payload.serverSync->session = client->sessionId;
253                 sendmsg->payload.serverSync->welcome_text = strdup(getStrConf(WELCOMETEXT));
254                 sendmsg->payload.serverSync->has_max_bandwidth = true;
255                 sendmsg->payload.serverSync->max_bandwidth = getIntConf(MAX_BANDWIDTH);
256                 sendmsg->payload.serverSync->has_allow_html = true;
257                 sendmsg->payload.serverSync->allow_html = true; /* Support this? */
258                 Client_send_message(client, sendmsg);
259                 
260                 Log_info_client(client, "User %s authenticated", client->username);
261                 break;
262                 
263         case Ping:
264                 if (msg->payload.ping->has_good)
265                         client->cryptState.uiRemoteGood = msg->payload.ping->good;
266                 if (msg->payload.ping->has_late)
267                         client->cryptState.uiRemoteLate = msg->payload.ping->late;
268                 if (msg->payload.ping->has_lost)
269                         client->cryptState.uiRemoteLost = msg->payload.ping->lost;
270                 if (msg->payload.ping->has_resync)
271                         client->cryptState.uiRemoteResync = msg->payload.ping->resync;
272
273                 Log_debug("Ping <-: %d %d %d %d",
274                                   client->cryptState.uiRemoteGood, client->cryptState.uiRemoteLate,
275                                   client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync
276                         );
277                 
278                 /* Ignoring the double values since they don't seem to be used */
279                 
280                 sendmsg = Msg_create(Ping);
281
282                 sendmsg->payload.ping->timestamp = msg->payload.ping->timestamp;
283                 sendmsg->payload.ping->has_timestamp = true;
284                 sendmsg->payload.ping->good = client->cryptState.uiGood;
285                 sendmsg->payload.ping->has_good = true;
286                 sendmsg->payload.ping->late = client->cryptState.uiLate;
287                 sendmsg->payload.ping->has_late = true;
288                 sendmsg->payload.ping->lost = client->cryptState.uiLost;
289                 sendmsg->payload.ping->has_lost = true;
290                 sendmsg->payload.ping->resync = client->cryptState.uiResync;
291                 sendmsg->payload.ping->has_resync = true;
292
293                 Client_send_message(client, sendmsg);
294                 Log_debug("Ping ->: %d %d %d %d",
295                                   client->cryptState.uiGood, client->cryptState.uiLate,
296                                   client->cryptState.uiLost, client->cryptState.uiResync);
297
298                 break;
299         case CryptSetup:
300                 Log_debug("Voice channel crypt resync requested");
301                 if (!msg->payload.cryptSetup->has_client_nonce) {
302                         sendmsg = Msg_create(CryptSetup);
303                         sendmsg->payload.cryptSetup->has_server_nonce = true;
304                         sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.decrypt_iv;
305                         sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
306                         Client_send_message(client, sendmsg);
307                 } else {
308                         memcpy(client->cryptState.decrypt_iv, msg->payload.cryptSetup->client_nonce.data, AES_BLOCK_SIZE);
309                         client->cryptState.uiResync++;
310                 }
311                 break;
312         case UserState:
313                 /* Only allow state changes for for the self user */
314                 if (msg->payload.userState->has_session &&
315                         msg->payload.userState->session != client->sessionId) {
316                         sendPermissionDenied(client, "Permission denied");
317                         break;
318                 }
319                 if (msg->payload.userState->has_user_id || msg->payload.userState->has_mute ||
320                         msg->payload.userState->has_deaf || msg->payload.userState->has_suppress ||
321                         msg->payload.userState->has_texture) {
322                         
323                         sendPermissionDenied(client, "Not supported by uMurmur");
324                         break;
325                 }
326                 if (msg->payload.userState->has_self_deaf) {
327                         client->deaf = msg->payload.userState->self_deaf;
328                 }
329                 if (msg->payload.userState->has_self_mute) {
330                         client->mute = msg->payload.userState->self_mute;                       
331                 }
332                 if (msg->payload.userState->has_channel_id) {
333                         int leave_id;
334                         if (!Chan_userJoin_id_test(msg->payload.userState->channel_id))
335                                 break;
336                         leave_id = Chan_userJoin_id(msg->payload.userState->channel_id, client);
337                         if (leave_id > 0) {
338                                 Log_debug("Removing channel ID %d", leave_id);
339                                 sendmsg = Msg_create(ChannelRemove);
340                                 sendmsg->payload.channelRemove->channel_id = leave_id;
341                         }
342                 }
343                 if (msg->payload.userState->plugin_context != NULL) {
344                         if (client->context)
345                                 free(client->context);
346                         client->context = strdup(msg->payload.userState->plugin_context);
347                         if (client->context == NULL)
348                                 Log_fatal("Out of memory");
349                         
350                         break; /* Don't inform other users about this state */
351                 }
352                 
353                 /* Re-use message */
354                 Msg_inc_ref(msg);
355                 msg->payload.userState->has_actor = true;
356                 msg->payload.userState->actor = client->sessionId;
357                 Client_send_message_except(NULL, msg);
358
359                 /* Need to send remove channel message _after_ UserState message */
360                 if (sendmsg != NULL)
361                         Client_send_message_except(NULL, sendmsg);
362                 break;
363                 
364         case TextMessage:
365                 msg->payload.textMessage->has_actor = true;
366                 msg->payload.textMessage->actor = client->sessionId;
367
368                 /* XXX - HTML is allowed and can't be turned off */
369                 if (msg->payload.textMessage->n_tree_id > 0) {
370                         sendPermissionDenied(client, "Tree message not supported");
371                         break;
372                 }
373                         
374                 if (msg->payload.textMessage->n_channel_id > 0) { /* To channel */
375                         int i;
376                         channel_t *ch_itr;
377                         for (i = 0; i < msg->payload.textMessage->n_channel_id; i++) {
378                                 ch_itr = NULL;
379                                 do {
380                                         Chan_iterate(&ch_itr);
381                                 } while (ch_itr != NULL && ch_itr->id != msg->payload.textMessage->channel_id[i]);
382                                 if (ch_itr != NULL) {
383                                         struct dlist *itr;
384                                         list_iterate(itr, &ch_itr->clients) {
385                                                 client_t *c;
386                                                 c = list_get_entry(itr, client_t, chan_node);
387                                                 if (c != client && !c->deaf) {
388                                                         Msg_inc_ref(msg);
389                                                         Client_send_message(c, msg);
390                                                         Log_debug("Text message to session ID %d", c->sessionId);
391                                                 }
392                                         }
393                                 }
394                         } /* for */
395                 }
396                 if (msg->payload.textMessage->n_session > 0) { /* To user */
397                         int i;
398                         client_t *itr;
399                         for (i = 0; i < msg->payload.textMessage->n_session; i++) {
400                                 itr = NULL;
401                                 while (Client_iterate(&itr) != NULL) {
402                                         if (!IS_AUTH(itr))
403                                                 continue;
404                                         if (itr->sessionId == msg->payload.textMessage->session[i]) {
405                                                 if (!itr->deaf) {
406                                                         Msg_inc_ref(msg);
407                                                         Client_send_message(itr, msg);
408                                                         Log_debug("Text message to session ID %d", itr->sessionId);
409                                                 }
410                                                 break;
411                                         }
412                                 }
413                                 if (itr == NULL)
414                                         Log_warn("TextMessage: Session ID %d not found", msg->payload.textMessage->session[i]);
415                         } /* for */
416                 }
417                 break;
418
419         case VoiceTarget:
420         {
421                 int i, j, count, targetId = msg->payload.voiceTarget->id;
422                 struct _MumbleProto__VoiceTarget__Target *target;
423
424                 if (!targetId || targetId >= 0x1f)
425                         break;
426                 Voicetarget_add_id(client, targetId);
427                 count = msg->payload.voiceTarget->n_targets;
428                 if (!count)
429                         break;
430                 for (i = 0; i < count; i++) {
431                         target = msg->payload.voiceTarget->targets[i];
432                         for (j = 0; j < target->n_session; j++)
433                                 Voicetarget_add_session(client, targetId, target->session[j]);
434                         if (target->has_channel_id) {
435                                 bool_t linked = false, children = false;
436                                 if (target->has_links)
437                                         linked = target->links;
438                                 if (target->has_children)
439                                         children = target->children;
440                                 Voicetarget_add_channel(client, targetId, target->channel_id, linked, children);
441                         }
442                 }
443                 break;
444         }
445         case Version:
446                 Log_debug("Version message received");
447                 if (msg->payload.version->has_version) {
448                         client->version = msg->payload.version->version;
449                         Log_debug("Client version 0x%x", client->version);
450                 }
451                 if (msg->payload.version->release) {
452                         if (client->release) free(client->release);
453                         client->release = strdup(msg->payload.version->release);
454                         Log_debug("Client release %s", client->release);
455                 }
456                 if (msg->payload.version->os) {
457                         if (client->os) free(client->os);                       
458                         client->os = strdup(msg->payload.version->os);
459                         Log_debug("Client OS %s", client->os);
460                 }
461                 break;
462         case PermissionQuery:
463                 Msg_inc_ref(msg); /* Re-use message */
464                 msg->payload.permissionQuery->has_permissions = true;
465                 msg->payload.permissionQuery->permissions = PERM_DEFAULT;
466                 
467                 Client_send_message(client, msg);
468                 break;
469         case UDPTunnel:
470                 client->bUDP = false;
471                 Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
472             break;
473         case ChannelState:
474         {
475                 channel_t *ch_itr, *parent, *newchan;
476                 int leave_id;           
477                 /* Don't allow any changes to existing channels */
478                 if (msg->payload.channelState->has_channel_id) {
479                         sendPermissionDenied(client, "Not supported by uMurmur");
480                         break;
481                 }
482                 /* Must have parent */
483                 if (!msg->payload.channelState->has_parent) {
484                         sendPermissionDenied(client, "Not supported by uMurmur");
485                         break;
486                 }
487                 /* Must have name */
488                 if (msg->payload.channelState->name == NULL) {
489                         sendPermissionDenied(client, "Not supported by uMurmur");
490                         break;
491                 }
492                 /* Must be temporary channel */
493                 if (msg->payload.channelState->temporary != true) {
494                         sendPermissionDenied(client, "Only temporary channels are supported by uMurmur");
495                         break;
496                 }
497                 /* Check channel name is OK */
498                 if (strlen(msg->payload.channelState->name) > MAX_TEXT) {
499                         sendPermissionDenied(client, "Channel name too long");
500                         break;
501                 }
502                         
503                 parent = Chan_fromId(msg->payload.channelState->parent);
504                 if (parent == NULL)
505                         break;
506                 ch_itr = NULL;
507                 while (Chan_iterate_siblings(parent, &ch_itr) != NULL) {
508                         if (strcmp(ch_itr->name, msg->payload.channelState->name) == 0) {
509                                 sendPermissionDenied(client, "Channel already exists");
510                                 break;
511                         }
512                 }
513                 if (ch_itr != NULL)
514                         break;
515                 
516                 /* Disallow temporary channels as siblings to temporary channels */
517                 if (parent->temporary) {
518                         sendPermissionDenied(client, "Parent channel is temporary channel");
519                         break;
520                 }
521                         
522                 /* XXX - Murmur looks for "\\w" and sends perm denied if not found.
523                  * I don't know why so I don't do that here...
524                  */
525
526                 /* Create the channel */
527                 newchan = Chan_createChannel(msg->payload.channelState->name,
528                                                                          msg->payload.channelState->description);
529                 newchan->temporary = true;
530                 Chan_addChannel(parent, newchan);
531                 msg->payload.channelState->has_channel_id = true;
532                 msg->payload.channelState->channel_id = newchan->id;
533                 Msg_inc_ref(msg);
534                 Client_send_message_except(NULL, msg);
535
536                 /* Join the creating user */
537                 sendmsg = Msg_create(UserState);
538                 sendmsg->payload.userState->has_session = true;
539                 sendmsg->payload.userState->session = client->sessionId;
540                 sendmsg->payload.userState->has_channel_id = true;
541                 sendmsg->payload.userState->channel_id = newchan->id;
542                 Client_send_message_except(NULL, sendmsg);
543                 
544                 leave_id = Chan_userJoin(newchan, client);
545                 if (leave_id > 0) {
546                         Log_debug("Removing channel ID %d", leave_id);
547                         sendmsg = Msg_create(ChannelRemove);
548                         sendmsg->payload.channelRemove->channel_id = leave_id;
549                         Client_send_message_except(NULL, sendmsg);
550                 }
551         }               
552         break;
553
554                 /* Permission denied for all these messages. Not implemented. */
555         case ChannelRemove:
556         case ContextAction:
557         case ContextActionAdd:
558         case ACL:
559         case BanList:
560         case UserList:
561         case QueryUsers:
562                 sendPermissionDenied(client, "Not supported by uMurmur");
563                 break;
564                                 
565         default:
566                 Log_warn("Message %d not handled", msg->messageType);
567                 break;
568         }
569 out:
570         Msg_free(msg);
571         return;
572         
573 disconnect:
574         Msg_free(msg);
575         Client_close(client);
576 }
577