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