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