Add support for channel passwords.
[umurmur.git] / src / messagehandler.c
1 /* Copyright (C) 2009-2011, Martin Johansson <martin@fatbob.nu>
2    Copyright (C) 2005-2011, 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 #define MAX_USERNAME 128
46
47 extern channel_t *defaultChan;
48 extern int iCodecAlpha, iCodecBeta;
49 extern bool_t bPreferAlpha;
50
51 static void sendServerReject(client_t *client, const char *reason, MumbleProto__Reject__RejectType type)
52 {
53         message_t *msg = Msg_create(Reject);
54         msg->payload.reject->reason = strdup(reason);
55         msg->payload.reject->type = type;
56         msg->payload.reject->has_type = true;
57         Client_send_message(client, msg);
58         
59         Log_info_client(client, "Server reject reason: %s", reason);
60 }
61
62 static void sendPermissionDenied(client_t *client, const char *reason)
63 {
64         message_t *msg = Msg_create(PermissionDenied);
65         msg->payload.permissionDenied->has_type = true;
66         msg->payload.permissionDenied->type = MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__Text;
67         msg->payload.permissionDenied->reason = strdup(reason);
68         Client_send_message(client, msg);
69 }
70
71 static void addTokens(client_t *client, message_t *msg)
72 {
73         int i;
74         if (client->tokencount + msg->payload.authenticate->n_tokens < MAX_TOKENS) {
75                 /* Check lengths first */
76                 for (i = 0; i < msg->payload.authenticate->n_tokens; i++) {
77                         if (strlen(msg->payload.authenticate->tokens[i]) > MAX_TOKENSIZE - 1) {
78                                 sendPermissionDenied(client, "Too long token");
79                                 return;
80                         }
81                 }
82                 
83                 for (i = 0; i < msg->payload.authenticate->n_tokens; i++) {
84                         Log_debug("Adding token '%s' to client '%s'", msg->payload.authenticate->tokens[i], client->username);
85                         Client_token_add(client, msg->payload.authenticate->tokens[i]);
86                 }
87         }
88         else
89                 sendPermissionDenied(client, "Too many tokens");
90 }
91
92 void Mh_handle_message(client_t *client, message_t *msg)
93 {
94         message_t *sendmsg = NULL;
95         channel_t *ch_itr = NULL;
96         client_t *client_itr;
97
98         if (!client->authenticated && !(msg->messageType == Authenticate ||
99                                                                         msg->messageType == Version)) {
100                 goto out;
101         }
102         
103         switch (msg->messageType) {
104         case UDPTunnel:
105         case Ping:
106         case CryptSetup:
107         case VoiceTarget:
108         case UserStats:
109         case PermissionQuery:
110                 break;
111         default:
112                 Timer_restart(&client->idleTime);
113         }
114         
115         switch (msg->messageType) {
116         case Authenticate:
117                 Log_debug("Authenticate message received");
118                 
119                 if (IS_AUTH(client) || !msg->payload.authenticate->username) {
120                         /* Authenticate message might be sent when a tokens are changed by the user.*/
121                         Client_token_free(client); /* Clear the token list */
122                         if (msg->payload.authenticate->n_tokens > 0) {
123                                 Log_debug("Tokens in auth message from '%s'. n_tokens = %d", client->username,
124                                           msg->payload.authenticate->n_tokens);
125                                 addTokens(client, msg);
126                         }
127                         break;
128                 }
129                 
130                 client->authenticated = true;
131                 
132                 client_itr = NULL;
133                 while (Client_iterate(&client_itr) != NULL) {
134                         if (!IS_AUTH(client_itr))
135                                 continue;
136                         if (client_itr->username && strncmp(client_itr->username, msg->payload.authenticate->username, MAX_USERNAME) == 0) {
137                                 char buf[64];
138                                 sprintf(buf, "Username already in use");
139                                 Log_debug("Username already in use");
140                                 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__UsernameInUse);
141                                 goto disconnect;
142                         }                               
143                 }
144                 if (strlen(getStrConf(PASSPHRASE)) > 0) {
145                         if (!msg->payload.authenticate->password ||
146                                 (msg->payload.authenticate->password &&
147                                  strncmp(getStrConf(PASSPHRASE), msg->payload.authenticate->password, MAX_TEXT) != 0)) {
148                                 char buf[64];
149                                 sprintf(buf, "Wrong server password");
150                                 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__WrongServerPW);
151                                 Log_debug("Wrong server password: '%s'", msg->payload.authenticate->password != NULL ?
152                                                   msg->payload.authenticate->password : "(null)");
153                                 goto disconnect;
154                         }
155                 }                               
156                 if (strlen(msg->payload.authenticate->username) == 0 ||
157                         strlen(msg->payload.authenticate->username) >= MAX_USERNAME) { /* XXX - other invalid names? */
158                         char buf[64];
159                         sprintf(buf, "Invalid username");
160                         Log_debug("Invalid username");
161                         sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__InvalidUsername);
162                         goto disconnect;
163                 }                               
164
165                 if (Client_count() >= getIntConf(MAX_CLIENTS)) {
166                         char buf[64];
167                         snprintf(buf, 64, "Server is full (max %d users)", getIntConf(MAX_CLIENTS));
168                         sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__ServerFull);
169                         goto disconnect;
170                 }
171                 
172                 /* Name */
173                 client->username = strdup(msg->payload.authenticate->username);                         
174
175                 /* Tokens */
176                 if (msg->payload.authenticate->n_tokens > 0)
177                         addTokens(client, msg);
178
179                 
180                 /* Setup UDP encryption */
181                 CryptState_init(&client->cryptState);
182                 CryptState_genKey(&client->cryptState);
183                 sendmsg = Msg_create(CryptSetup);
184                 sendmsg->payload.cryptSetup->has_key = true;
185                 sendmsg->payload.cryptSetup->key.data = client->cryptState.raw_key;
186                 sendmsg->payload.cryptSetup->key.len = AES_BLOCK_SIZE;
187                 sendmsg->payload.cryptSetup->has_server_nonce = true;
188                 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.encrypt_iv;
189                 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
190                 sendmsg->payload.cryptSetup->has_client_nonce = true;
191                 sendmsg->payload.cryptSetup->client_nonce.data = client->cryptState.decrypt_iv;
192                 sendmsg->payload.cryptSetup->client_nonce.len = AES_BLOCK_SIZE;
193                 Client_send_message(client, sendmsg);
194
195                 /* Channel stuff */
196                 Chan_userJoin(defaultChan, client); /* Join default channel */
197
198                 /* Codec version */             
199                 Log_debug("Client %d has %d CELT codecs", client->sessionId,
200                                   msg->payload.authenticate->n_celt_versions);
201                 if (msg->payload.authenticate->n_celt_versions > 0) {
202                         int i;
203                         codec_t *codec_itr;
204                         client->codec_count = msg->payload.authenticate->n_celt_versions;
205                         
206                         for (i = 0; i < client->codec_count; i++)
207                         Client_codec_add(client, msg->payload.authenticate->celt_versions[i]);
208                         codec_itr = NULL;
209                         while (Client_codec_iterate(client, &codec_itr) != NULL)
210                                 Log_debug("Client %d CELT codec ver 0x%x", client->sessionId, codec_itr->codec);
211                                 
212                 } else {
213                         Client_codec_add(client, (int32_t)0x8000000a);
214                         client->codec_count = 1;
215                 }
216                 
217                 recheckCodecVersions();
218                 
219                 sendmsg = Msg_create(CodecVersion);
220                 sendmsg->payload.codecVersion->alpha = iCodecAlpha;
221                 sendmsg->payload.codecVersion->beta = iCodecBeta;
222                 sendmsg->payload.codecVersion->prefer_alpha = bPreferAlpha;
223                 Client_send_message(client, sendmsg);
224                 
225                 /* Iterate channels and send channel info */
226                 ch_itr = NULL;
227                 while (Chan_iterate(&ch_itr) != NULL) {
228                         sendmsg = Msg_create(ChannelState);
229                         sendmsg->payload.channelState->has_channel_id = true;
230                         sendmsg->payload.channelState->channel_id = ch_itr->id;
231                         if (ch_itr->id != 0) {
232                                 sendmsg->payload.channelState->has_parent = true;
233                                 sendmsg->payload.channelState->parent = ch_itr->parent->id;
234                         }
235                         sendmsg->payload.channelState->name = strdup(ch_itr->name);
236                         if (ch_itr->desc)
237                                 sendmsg->payload.channelState->description = strdup(ch_itr->desc);
238                         Log_debug("Send channel info: %s", sendmsg->payload.channelState->name);
239                         Client_send_message(client, sendmsg);                   
240                 }
241
242                 /* Iterate channels and send channel links info */
243                 ch_itr = NULL;
244                 while (Chan_iterate(&ch_itr) != NULL) {
245                         if (ch_itr->linkcount > 0) { /* Has links */
246                                 uint32_t *links;
247                                 int i = 0;
248                                 struct dlist *itr;
249                                 
250                                 sendmsg = Msg_create(ChannelState);
251                                 sendmsg->payload.channelState->has_channel_id = true;
252                                 sendmsg->payload.channelState->channel_id = ch_itr->id;
253                                 sendmsg->payload.channelState->n_links = ch_itr->linkcount;
254                                 
255                                 links = (uint32_t *)malloc(ch_itr->linkcount * sizeof(uint32_t));
256                                 list_iterate(itr, &ch_itr->channel_links) { /* Iterate links */
257                                         channel_t *ch;
258                                         ch = list_get_entry(itr, channel_t, link_node);
259                                         links[i++] = ch->id;
260                                 }
261                                 sendmsg->payload.channelState->links = links;
262                                 Client_send_message(client, sendmsg);
263                         }
264                 }
265                 
266                 /* Send user state for connecting user to other users */
267                 sendmsg = Msg_create(UserState);
268                 sendmsg->payload.userState->has_session = true;
269                 sendmsg->payload.userState->session = client->sessionId;
270                 sendmsg->payload.userState->name = strdup(client->username);
271                 sendmsg->payload.userState->has_channel_id = true;
272                 sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
273
274                 Client_send_message_except(client, sendmsg);
275
276                 client_itr = NULL;
277                 while (Client_iterate(&client_itr) != NULL) {
278                         if (!IS_AUTH(client_itr))
279                                 continue;
280                         sendmsg = Msg_create(UserState);
281                         sendmsg->payload.userState->has_session = true;
282                         sendmsg->payload.userState->session = client_itr->sessionId;
283                         sendmsg->payload.userState->name = strdup(client_itr->username);
284                         sendmsg->payload.userState->has_channel_id = true;
285                         sendmsg->payload.userState->channel_id = ((channel_t *)client_itr->channel)->id;
286
287                         /* Only self_mute/deaf supported */
288                         if (client_itr->deaf) {
289                                 sendmsg->payload.userState->has_self_deaf = true;
290                                 sendmsg->payload.userState->self_deaf = true;
291                         }
292                         if (client_itr->mute) {
293                                 sendmsg->payload.userState->has_self_mute = true;
294                                 sendmsg->payload.userState->self_mute = true;
295                         }
296                         if (client_itr->recording) {
297                                 sendmsg->payload.userState->has_recording = true;
298                                 sendmsg->payload.userState->recording = true;
299                         }
300                         Client_send_message(client, sendmsg);
301                 }
302
303                 /* Sync message */
304                 sendmsg = Msg_create(ServerSync);
305                 sendmsg->payload.serverSync->has_session = true;
306                 sendmsg->payload.serverSync->session = client->sessionId;
307                 sendmsg->payload.serverSync->welcome_text = strdup(getStrConf(WELCOMETEXT));
308                 sendmsg->payload.serverSync->has_max_bandwidth = true;
309                 sendmsg->payload.serverSync->max_bandwidth = getIntConf(MAX_BANDWIDTH);
310                 Client_send_message(client, sendmsg);
311
312                 /* Server config message */
313                 sendmsg = Msg_create(ServerConfig);             
314                 sendmsg->payload.serverConfig->has_allow_html = true;
315                 sendmsg->payload.serverConfig->allow_html = true; /* Support this? */
316                 sendmsg->payload.serverConfig->has_message_length = true;
317                 sendmsg->payload.serverConfig->message_length = MAX_TEXT; /* Hardcoded */
318                 sendmsg->payload.serverConfig->has_image_message_length = true;
319                 sendmsg->payload.serverConfig->image_message_length = 0; /* XXX */
320                 Client_send_message(client, sendmsg);
321
322                 Log_info_client(client, "User %s authenticated", client->username);
323                 break;
324                 
325         case Ping:
326                 if (msg->payload.ping->has_good)
327                         client->cryptState.uiRemoteGood = msg->payload.ping->good;
328                 if (msg->payload.ping->has_late)
329                         client->cryptState.uiRemoteLate = msg->payload.ping->late;
330                 if (msg->payload.ping->has_lost)
331                         client->cryptState.uiRemoteLost = msg->payload.ping->lost;
332                 if (msg->payload.ping->has_resync)
333                         client->cryptState.uiRemoteResync = msg->payload.ping->resync;
334
335                 Log_debug("Ping <-: %d %d %d %d",
336                                   client->cryptState.uiRemoteGood, client->cryptState.uiRemoteLate,
337                                   client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync
338                         );
339                 
340                 client->UDPPingAvg = msg->payload.ping->udp_ping_avg;
341                 client->UDPPingVar = msg->payload.ping->udp_ping_var;
342                 client->TCPPingAvg = msg->payload.ping->tcp_ping_avg;
343                 client->TCPPingVar = msg->payload.ping->tcp_ping_var;
344                 client->UDPPackets = msg->payload.ping->udp_packets;
345                 client->TCPPackets = msg->payload.ping->tcp_packets;
346                 
347                 sendmsg = Msg_create(Ping);
348
349                 sendmsg->payload.ping->timestamp = msg->payload.ping->timestamp;
350                 sendmsg->payload.ping->has_timestamp = true;
351                 sendmsg->payload.ping->good = client->cryptState.uiGood;
352                 sendmsg->payload.ping->has_good = true;
353                 sendmsg->payload.ping->late = client->cryptState.uiLate;
354                 sendmsg->payload.ping->has_late = true;
355                 sendmsg->payload.ping->lost = client->cryptState.uiLost;
356                 sendmsg->payload.ping->has_lost = true;
357                 sendmsg->payload.ping->resync = client->cryptState.uiResync;
358                 sendmsg->payload.ping->has_resync = true;
359
360                 Client_send_message(client, sendmsg);
361                 Log_debug("Ping ->: %d %d %d %d",
362                                   client->cryptState.uiGood, client->cryptState.uiLate,
363                                   client->cryptState.uiLost, client->cryptState.uiResync);
364
365                 break;
366         case CryptSetup:
367                 Log_debug("Voice channel crypt resync requested");
368                 if (!msg->payload.cryptSetup->has_client_nonce) {
369                         sendmsg = Msg_create(CryptSetup);
370                         sendmsg->payload.cryptSetup->has_server_nonce = true;
371                         sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.decrypt_iv;
372                         sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
373                         Client_send_message(client, sendmsg);
374                 } else {
375                         memcpy(client->cryptState.decrypt_iv, msg->payload.cryptSetup->client_nonce.data, AES_BLOCK_SIZE);
376                         client->cryptState.uiResync++;
377                 }
378                 break;
379         case UserState:
380                 /* Only allow state changes for for the self user */
381                 if (msg->payload.userState->has_session &&
382                         msg->payload.userState->session != client->sessionId) {
383                         sendPermissionDenied(client, "Permission denied");
384                         break;
385                 }
386                 if (msg->payload.userState->has_user_id || msg->payload.userState->has_mute ||
387                         msg->payload.userState->has_deaf || msg->payload.userState->has_suppress ||
388                         msg->payload.userState->has_texture) {
389                         
390                         sendPermissionDenied(client, "Not supported by uMurmur");
391                         break;
392                 }
393                 
394                 msg->payload.userState->has_session = true;
395                 msg->payload.userState->session = client->sessionId;
396                 msg->payload.userState->has_actor = true;
397                 msg->payload.userState->actor = client->sessionId;
398
399                 if (msg->payload.userState->has_self_deaf) {
400                         client->deaf = msg->payload.userState->self_deaf;
401                 }
402                 if (msg->payload.userState->has_self_mute) {
403                         client->mute = msg->payload.userState->self_mute;
404                         if (!client->mute) {
405                                 msg->payload.userState->has_self_deaf = true;
406                                 msg->payload.userState->self_deaf = false;
407                                 client->deaf = false;
408                         }
409                 }
410                 if (msg->payload.userState->has_recording &&
411                         msg->payload.userState->recording != client->recording) {
412                         client->recording = msg->payload.userState->recording;
413                         char *message;
414                         uint32_t *tree_id;
415                         
416                         message = malloc(strlen(client->username) + 32);
417                         if (!message)
418                                 Log_fatal("Out of memory");
419                         tree_id = malloc(sizeof(uint32_t));
420                         if (!tree_id)
421                                 Log_fatal("Out of memory");
422                         *tree_id = 0;
423                         sendmsg = Msg_create(TextMessage);
424                         sendmsg->payload.textMessage->message = message;
425                         sendmsg->payload.textMessage->n_tree_id = 1;
426                         sendmsg->payload.textMessage->tree_id = tree_id;
427                         if (client->recording)
428                                 sprintf(message, "User %s started recording", client->username);
429                         else
430                                 sprintf(message, "User %s stopped recording", client->username);
431                         Client_send_message_except_ver(NULL, sendmsg, ~0x010203);
432                         sendmsg = NULL;
433                 }
434                 if (msg->payload.userState->has_channel_id) {
435                         int leave_id;
436                         channelJoinResult_t chjoin_rc = Chan_userJoin_id_test(msg->payload.userState->channel_id, client);
437                         
438                         if (chjoin_rc != CHJOIN_OK) {
439                                 if (chjoin_rc == CHJOIN_WRONGPW) {
440                                         sendPermissionDenied(client, "Wrong channel password");
441                                 }
442                                 break;
443                         }
444                         
445                         leave_id = Chan_userJoin_id(msg->payload.userState->channel_id, client);
446                         if (leave_id > 0) {
447                                 Log_debug("Removing channel ID %d", leave_id);
448                                 sendmsg = Msg_create(ChannelRemove);
449                                 sendmsg->payload.channelRemove->channel_id = leave_id;
450                         }
451                 }
452                 if (msg->payload.userState->has_plugin_context) {
453                         if (client->context)
454                                 free(client->context);
455                         client->context = malloc(msg->payload.userState->plugin_context.len);
456                         if (client->context == NULL)
457                                 Log_fatal("Out of memory");
458                         memcpy(client->context, msg->payload.userState->plugin_context.data,
459                                    msg->payload.userState->plugin_context.len);
460                         
461                         break; /* Don't inform other users about this state */
462                 }
463                 /* Re-use message */
464                 Msg_inc_ref(msg);
465                                 
466                 Client_send_message_except(NULL, msg);
467
468                 /* Need to send remove channel message _after_ UserState message */
469                 if (sendmsg != NULL)
470                         Client_send_message_except(NULL, sendmsg);
471                 break;
472                 
473         case TextMessage:
474                 msg->payload.textMessage->has_actor = true;
475                 msg->payload.textMessage->actor = client->sessionId;
476
477                 /* XXX - HTML is allowed and can't be turned off */
478                 if (msg->payload.textMessage->n_tree_id > 0) {
479                         sendPermissionDenied(client, "Tree message not supported");
480                         break;
481                 }
482                         
483                 if (msg->payload.textMessage->n_channel_id > 0) { /* To channel */
484                         int i;
485                         channel_t *ch_itr;
486                         for (i = 0; i < msg->payload.textMessage->n_channel_id; i++) {
487                                 ch_itr = NULL;
488                                 do {
489                                         Chan_iterate(&ch_itr);
490                                 } while (ch_itr != NULL && ch_itr->id != msg->payload.textMessage->channel_id[i]);
491                                 if (ch_itr != NULL) {
492                                         struct dlist *itr;
493                                         list_iterate(itr, &ch_itr->clients) {
494                                                 client_t *c;
495                                                 c = list_get_entry(itr, client_t, chan_node);
496                                                 if (c != client && !c->deaf) {
497                                                         Msg_inc_ref(msg);
498                                                         Client_send_message(c, msg);
499                                                         Log_debug("Text message to session ID %d", c->sessionId);
500                                                 }
501                                         }
502                                 }
503                         } /* for */
504                 }
505                 if (msg->payload.textMessage->n_session > 0) { /* To user */
506                         int i;
507                         client_t *itr;
508                         for (i = 0; i < msg->payload.textMessage->n_session; i++) {
509                                 itr = NULL;
510                                 while (Client_iterate(&itr) != NULL) {
511                                         if (!IS_AUTH(itr))
512                                                 continue;
513                                         if (itr->sessionId == msg->payload.textMessage->session[i]) {
514                                                 if (!itr->deaf) {
515                                                         Msg_inc_ref(msg);
516                                                         Client_send_message(itr, msg);
517                                                         Log_debug("Text message to session ID %d", itr->sessionId);
518                                                 }
519                                                 break;
520                                         }
521                                 }
522                                 if (itr == NULL)
523                                         Log_warn("TextMessage: Session ID %d not found", msg->payload.textMessage->session[i]);
524                         } /* for */
525                 }
526                 break;
527
528         case VoiceTarget:
529         {
530                 int i, j, count, targetId = msg->payload.voiceTarget->id;
531                 struct _MumbleProto__VoiceTarget__Target *target;
532
533                 if (!targetId || targetId >= 0x1f)
534                         break;
535                 Voicetarget_add_id(client, targetId);
536                 count = msg->payload.voiceTarget->n_targets;
537                 if (!count)
538                         break;
539                 for (i = 0; i < count; i++) {
540                         target = msg->payload.voiceTarget->targets[i];
541                         for (j = 0; j < target->n_session; j++)
542                                 Voicetarget_add_session(client, targetId, target->session[j]);
543                         if (target->has_channel_id) {
544                                 bool_t linked = false, children = false;
545                                 if (target->has_links)
546                                         linked = target->links;
547                                 if (target->has_children)
548                                         children = target->children;
549                                 Voicetarget_add_channel(client, targetId, target->channel_id, linked, children);
550                         }
551                 }
552                 break;
553         }
554         case Version:
555                 Log_debug("Version message received");
556                 if (msg->payload.version->has_version) {
557                         client->version = msg->payload.version->version;
558                         Log_debug("Client version 0x%x", client->version);
559                 }
560                 if (msg->payload.version->release) {
561                         if (client->release) free(client->release);
562                         client->release = strdup(msg->payload.version->release);
563                         Log_debug("Client release %s", client->release);
564                 }
565                 if (msg->payload.version->os) {
566                         if (client->os) free(client->os);                       
567                         client->os = strdup(msg->payload.version->os);
568                         Log_debug("Client OS %s", client->os);
569                 }
570                 if (msg->payload.version->os_version) {
571                         if (client->os_version) free(client->os_version);                       
572                         client->os_version = strdup(msg->payload.version->os_version);
573                         Log_debug("Client OS version %s", client->os_version);
574                 }
575                 break;
576         case PermissionQuery:
577                 Msg_inc_ref(msg); /* Re-use message */
578                 msg->payload.permissionQuery->has_permissions = true;
579                 msg->payload.permissionQuery->permissions = PERM_DEFAULT;
580                 
581                 Client_send_message(client, msg);
582                 break;
583         case UDPTunnel:
584                 client->bUDP = false;
585                 Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
586             break;
587         case ChannelState:
588         {
589                 channel_t *ch_itr, *parent, *newchan;
590                 int leave_id;           
591                 /* Don't allow any changes to existing channels */
592                 if (msg->payload.channelState->has_channel_id) {
593                         sendPermissionDenied(client, "Not supported by uMurmur");
594                         break;
595                 }
596                 /* Must have parent */
597                 if (!msg->payload.channelState->has_parent) {
598                         sendPermissionDenied(client, "Not supported by uMurmur");
599                         break;
600                 }
601                 /* Must have name */
602                 if (msg->payload.channelState->name == NULL) {
603                         sendPermissionDenied(client, "Not supported by uMurmur");
604                         break;
605                 }
606                 /* Must be temporary channel */
607                 if (msg->payload.channelState->temporary != true) {
608                         sendPermissionDenied(client, "Only temporary channels are supported by uMurmur");
609                         break;
610                 }
611                 /* Check channel name is OK */
612                 if (strlen(msg->payload.channelState->name) > MAX_TEXT) {
613                         sendPermissionDenied(client, "Channel name too long");
614                         break;
615                 }
616                         
617                 parent = Chan_fromId(msg->payload.channelState->parent);
618                 if (parent == NULL)
619                         break;
620                 ch_itr = NULL;
621                 while (Chan_iterate_siblings(parent, &ch_itr) != NULL) {
622                         if (strcmp(ch_itr->name, msg->payload.channelState->name) == 0) {
623                                 sendPermissionDenied(client, "Channel already exists");
624                                 break;
625                         }
626                 }
627                 if (ch_itr != NULL)
628                         break;
629                 
630                 /* Disallow temporary channels as siblings to temporary channels */
631                 if (parent->temporary) {
632                         sendPermissionDenied(client, "Parent channel is temporary channel");
633                         break;
634                 }
635                         
636                 /* XXX - Murmur looks for "\\w" and sends perm denied if not found.
637                  * I don't know why so I don't do that here...
638                  */
639
640                 /* Create the channel */
641                 newchan = Chan_createChannel(msg->payload.channelState->name,
642                                                                          msg->payload.channelState->description);
643                 newchan->temporary = true;
644                 Chan_addChannel(parent, newchan);
645                 msg->payload.channelState->has_channel_id = true;
646                 msg->payload.channelState->channel_id = newchan->id;
647                 Msg_inc_ref(msg);
648                 Client_send_message_except(NULL, msg);
649
650                 /* Join the creating user */
651                 sendmsg = Msg_create(UserState);
652                 sendmsg->payload.userState->has_session = true;
653                 sendmsg->payload.userState->session = client->sessionId;
654                 sendmsg->payload.userState->has_channel_id = true;
655                 sendmsg->payload.userState->channel_id = newchan->id;
656                 Client_send_message_except(NULL, sendmsg);
657                 
658                 leave_id = Chan_userJoin(newchan, client);
659                 if (leave_id > 0) {
660                         Log_debug("Removing channel ID %d", leave_id);
661                         sendmsg = Msg_create(ChannelRemove);
662                         sendmsg->payload.channelRemove->channel_id = leave_id;
663                         Client_send_message_except(NULL, sendmsg);
664                 }
665         }               
666         break;
667
668         case UserStats:
669         {
670                 client_t *target = NULL;
671                 codec_t *codec_itr = NULL;
672                 int i;
673                 bool_t details = true;
674                 
675                 if (msg->payload.userStats->has_stats_only)
676                         details = !msg->payload.userStats->stats_only;
677                 
678                 if (!msg->payload.userStats->has_session)
679                         sendPermissionDenied(client, "Not supported by uMurmur");
680                 while (Client_iterate(&target) != NULL) {
681                         if (!IS_AUTH(target))
682                                 continue;
683                         if (target->sessionId == msg->payload.userStats->session)
684                                 break;
685                 }
686                 if (!target) /* Not found */
687                         break;
688                 
689                 /*
690                  * Differences from Murmur:
691                  * o Ignoring certificates intentionally
692                  * o Ignoring channel local determining
693                  */
694                 
695                 sendmsg = Msg_create(UserStats);
696                 sendmsg->payload.userStats->session = msg->payload.userStats->session;
697                 sendmsg->payload.userStats->from_client->has_good = true;
698                 sendmsg->payload.userStats->from_client->good = target->cryptState.uiGood;
699                 sendmsg->payload.userStats->from_client->has_late = true;
700                 sendmsg->payload.userStats->from_client->late = target->cryptState.uiLate;
701                 sendmsg->payload.userStats->from_client->has_lost = true;
702                 sendmsg->payload.userStats->from_client->lost = target->cryptState.uiLost;
703                 sendmsg->payload.userStats->from_client->has_resync = true;
704                 sendmsg->payload.userStats->from_client->resync = target->cryptState.uiResync;
705                 
706                 sendmsg->payload.userStats->from_server->has_good = true;
707                 sendmsg->payload.userStats->from_server->good = target->cryptState.uiRemoteGood;
708                 sendmsg->payload.userStats->from_server->has_late = true;
709                 sendmsg->payload.userStats->from_server->late = target->cryptState.uiRemoteLate;
710                 sendmsg->payload.userStats->from_server->has_lost = true;
711                 sendmsg->payload.userStats->from_server->lost = target->cryptState.uiRemoteLost;
712                 sendmsg->payload.userStats->from_server->has_resync = true;
713                 sendmsg->payload.userStats->from_server->resync = target->cryptState.uiRemoteResync;
714
715                 sendmsg->payload.userStats->has_udp_packets = true;
716                 sendmsg->payload.userStats->udp_packets = target->UDPPackets;
717                 sendmsg->payload.userStats->has_udp_ping_avg = true;
718                 sendmsg->payload.userStats->udp_ping_avg = target->UDPPingAvg;
719                 sendmsg->payload.userStats->has_udp_ping_var = true;
720                 sendmsg->payload.userStats->udp_ping_var = target->UDPPingVar;
721                 
722                 sendmsg->payload.userStats->has_tcp_ping_avg = true;
723                 sendmsg->payload.userStats->tcp_ping_avg = target->TCPPingAvg;
724                 sendmsg->payload.userStats->has_tcp_ping_var = true;
725                 sendmsg->payload.userStats->tcp_ping_var = target->TCPPingVar;
726                 sendmsg->payload.userStats->has_tcp_packets = true;
727                 sendmsg->payload.userStats->tcp_packets = target->TCPPackets;
728                 
729                 if (details) {
730
731                         sendmsg->payload.userStats->version->has_version = true;
732                         sendmsg->payload.userStats->version->version = target->version;
733                         sendmsg->payload.userStats->version->release = strdup(target->release);
734                         sendmsg->payload.userStats->version->os = strdup(target->os);
735                         sendmsg->payload.userStats->version->os_version = strdup(target->os_version);
736                         
737                         sendmsg->payload.userStats->n_celt_versions = target->codec_count;
738                         sendmsg->payload.userStats->celt_versions = malloc(sizeof(int32_t) * target->codec_count);
739                         if (!sendmsg->payload.userStats->celt_versions)
740                                 Log_fatal("Out of memory");
741                         i = 0;
742                         while (Client_codec_iterate(target, &codec_itr) != NULL)
743                                 sendmsg->payload.userStats->celt_versions[i++] = codec_itr->codec;
744
745                         /* Address */
746                         sendmsg->payload.userStats->has_address = true;
747                         sendmsg->payload.userStats->address.data = malloc(sizeof(uint8_t) * 16);
748                         if (!sendmsg->payload.userStats->address.data)
749                                 Log_fatal("Out of memory");
750                         memset(sendmsg->payload.userStats->address.data, 0, 16);
751                         /* ipv4 representation as ipv6 address. Supposedly correct. */
752                         memcpy(&sendmsg->payload.userStats->address.data[12], &target->remote_tcp.sin_addr, 4);
753                         sendmsg->payload.userStats->address.len = 16;
754                 }
755                 /* BW */
756                 sendmsg->payload.userStats->has_bandwidth = true;
757                 sendmsg->payload.userStats->bandwidth = target->availableBandwidth;
758                 
759                 /* Onlinesecs */
760                 sendmsg->payload.userStats->has_onlinesecs = true;
761                 sendmsg->payload.userStats->onlinesecs = Timer_elapsed(&target->connectTime) / 1000000LL;               
762                 /* Idlesecs */
763                 sendmsg->payload.userStats->has_idlesecs = true;
764                 sendmsg->payload.userStats->idlesecs = Timer_elapsed(&target->idleTime) / 1000000LL;            
765                 Client_send_message(client, sendmsg);
766         }
767         break;
768                 /* Permission denied for all these messages. Not implemented. */
769         case ChannelRemove:
770         case ContextAction:
771         case ContextActionAdd:
772         case ACL:
773         case BanList:
774         case UserList:
775         case QueryUsers:
776                 sendPermissionDenied(client, "Not supported by uMurmur");
777                 break;
778                                 
779         default:
780                 Log_warn("Message %d not handled", msg->messageType);
781                 break;
782         }
783 out:
784         Msg_free(msg);
785         return;
786         
787 disconnect:
788         Msg_free(msg);
789         Client_close(client);
790 }
791