1 /* Copyright (C) 2009-2013, Martin Johansson <martin@fatbob.nu>
2 Copyright (C) 2005-2013, Thorvald Natvig <thorvald@natvig.com>
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
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.
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.
38 #include "messagehandler.h"
42 #include "voicetarget.h"
46 #define MAX_USERNAME 128
48 #define NO_CELT_MESSAGE "<strong>WARNING:</strong> Your client doesn't support the CELT codec, you won't be able to talk to or hear most clients. Please make sure your client was built with CELT support."
51 extern channel_t *defaultChan;
52 extern int iCodecAlpha, iCodecBeta;
53 extern bool_t bPreferAlpha, bOpus;
55 static bool_t fake_celt_support;
57 static void sendServerReject(client_t *client, const char *reason, MumbleProto__Reject__RejectType type)
59 message_t *msg = Msg_create(Reject);
60 msg->payload.reject->reason = strdup(reason);
61 msg->payload.reject->type = type;
62 msg->payload.reject->has_type = true;
63 Client_send_message(client, msg);
65 Log_info_client(client, "Server reject reason: %s", reason);
68 static void sendPermissionDenied(client_t *client, const char *reason)
70 message_t *msg = Msg_create(PermissionDenied);
71 msg->payload.permissionDenied->has_type = true;
72 msg->payload.permissionDenied->type = MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__Text;
73 msg->payload.permissionDenied->reason = strdup(reason);
74 Client_send_message(client, msg);
77 static void addTokens(client_t *client, message_t *msg)
80 if (client->tokencount + msg->payload.authenticate->n_tokens < MAX_TOKENS) {
81 /* Check lengths first */
82 for (i = 0; i < msg->payload.authenticate->n_tokens; i++) {
83 if (strlen(msg->payload.authenticate->tokens[i]) > MAX_TOKENSIZE - 1) {
84 sendPermissionDenied(client, "Too long token");
89 for (i = 0; i < msg->payload.authenticate->n_tokens; i++) {
90 Log_debug("Adding token '%s' to client '%s'", msg->payload.authenticate->tokens[i], client->username);
91 Client_token_add(client, msg->payload.authenticate->tokens[i]);
95 sendPermissionDenied(client, "Too many tokens");
98 void Mh_handle_message(client_t *client, message_t *msg)
100 message_t *sendmsg = NULL;
101 channel_t *ch_itr = NULL;
102 client_t *client_itr, *target;
104 if (!client->authenticated && !(msg->messageType == Authenticate ||
105 msg->messageType == Version)) {
109 switch (msg->messageType) {
115 case PermissionQuery:
118 Timer_restart(&client->idleTime);
121 switch (msg->messageType) {
123 Log_debug("Authenticate message received");
125 if (IS_AUTH(client) || !msg->payload.authenticate->username) {
126 /* Authenticate message might be sent when a tokens are changed by the user.*/
127 Client_token_free(client); /* Clear the token list */
128 if (msg->payload.authenticate->n_tokens > 0) {
129 Log_debug("Tokens in auth message from '%s'. n_tokens = %d", client->username,
130 msg->payload.authenticate->n_tokens);
131 addTokens(client, msg);
136 if (SSLi_getSHA1Hash(client->ssl, client->hash) && Ban_isBanned(client)) {
138 SSLi_hash2hex(client->hash, hexhash);
139 Log_info("Client with hash '%s' is banned. Disconnecting", hexhash);
143 client->authenticated = true;
146 while (Client_iterate(&client_itr) != NULL) {
147 if (!IS_AUTH(client_itr))
149 if (client_itr->username && strncmp(client_itr->username, msg->payload.authenticate->username, MAX_USERNAME) == 0) {
151 sprintf(buf, "Username already in use");
152 Log_debug("Username already in use");
153 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__UsernameInUse);
157 if (strlen(getStrConf(PASSPHRASE)) > 0) {
158 if (!msg->payload.authenticate->password ||
159 (msg->payload.authenticate->password &&
160 strncmp(getStrConf(PASSPHRASE), msg->payload.authenticate->password, MAX_TEXT) != 0)) {
162 sprintf(buf, "Wrong server password");
163 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__WrongServerPW);
164 Log_debug("Wrong server password: '%s'", msg->payload.authenticate->password != NULL ?
165 msg->payload.authenticate->password : "(null)");
169 if (strlen(msg->payload.authenticate->username) == 0 ||
170 strlen(msg->payload.authenticate->username) >= MAX_USERNAME) { /* XXX - other invalid names? */
172 sprintf(buf, "Invalid username");
173 Log_debug("Invalid username");
174 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__InvalidUsername);
178 if (Client_count() >= getIntConf(MAX_CLIENTS)) {
180 snprintf(buf, 64, "Server is full (max %d users)", getIntConf(MAX_CLIENTS));
181 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__ServerFull);
186 client->username = strdup(msg->payload.authenticate->username);
189 if (msg->payload.authenticate->n_tokens > 0)
190 addTokens(client, msg);
192 /* Check if admin PW among tokens */
193 if (strlen(getStrConf(ADMIN_PASSPHRASE)) > 0 &&
194 Client_token_match(client, getStrConf(ADMIN_PASSPHRASE))) {
195 client->isAdmin = true;
196 Log_info_client(client, "User provided admin password");
199 /* Setup UDP encryption */
200 CryptState_init(&client->cryptState);
201 CryptState_genKey(&client->cryptState);
202 sendmsg = Msg_create(CryptSetup);
203 sendmsg->payload.cryptSetup->has_key = true;
204 sendmsg->payload.cryptSetup->key.data = client->cryptState.raw_key;
205 sendmsg->payload.cryptSetup->key.len = AES_BLOCK_SIZE;
206 sendmsg->payload.cryptSetup->has_server_nonce = true;
207 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.encrypt_iv;
208 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
209 sendmsg->payload.cryptSetup->has_client_nonce = true;
210 sendmsg->payload.cryptSetup->client_nonce.data = client->cryptState.decrypt_iv;
211 sendmsg->payload.cryptSetup->client_nonce.len = AES_BLOCK_SIZE;
212 Client_send_message(client, sendmsg);
215 Chan_userJoin(defaultChan, client); /* Join default channel */
218 Log_debug("Client %d has %d CELT codecs", client->sessionId,
219 msg->payload.authenticate->n_celt_versions);
220 if (msg->payload.authenticate->n_celt_versions > 0) {
223 client->codec_count = msg->payload.authenticate->n_celt_versions;
225 for (i = 0; i < client->codec_count; i++)
226 Client_codec_add(client, msg->payload.authenticate->celt_versions[i]);
228 while (Client_codec_iterate(client, &codec_itr) != NULL)
229 Log_debug("Client %d CELT codec ver 0x%x", client->sessionId, codec_itr->codec);
232 Client_codec_add(client, (int32_t)0x8000000b);
233 client->codec_count = 1;
234 fake_celt_support = true;
236 if (msg->payload.authenticate->opus)
237 client->bOpus = true;
239 recheckCodecVersions(client);
241 sendmsg = Msg_create(CodecVersion);
242 sendmsg->payload.codecVersion->alpha = iCodecAlpha;
243 sendmsg->payload.codecVersion->beta = iCodecBeta;
244 sendmsg->payload.codecVersion->prefer_alpha = bPreferAlpha;
245 sendmsg->payload.codecVersion->has_opus = true;
246 sendmsg->payload.codecVersion->opus = bOpus;
247 Client_send_message(client, sendmsg);
249 if (!bOpus && client->bOpus && fake_celt_support) {
250 Client_textmessage(client, NO_CELT_MESSAGE);
253 /* Iterate channels and send channel info */
255 while (Chan_iterate(&ch_itr) != NULL) {
256 sendmsg = Msg_create(ChannelState);
257 sendmsg->payload.channelState->has_channel_id = true;
258 sendmsg->payload.channelState->channel_id = ch_itr->id;
259 if (ch_itr->id != 0) {
260 sendmsg->payload.channelState->has_parent = true;
261 sendmsg->payload.channelState->parent = ch_itr->parent->id;
263 sendmsg->payload.channelState->name = strdup(ch_itr->name);
265 sendmsg->payload.channelState->description = strdup(ch_itr->desc);
266 if (ch_itr->position != 0) {
267 sendmsg->payload.channelState->has_position = true;
268 sendmsg->payload.channelState->position = ch_itr->position;
270 Log_debug("Send channel info: %s", sendmsg->payload.channelState->name);
271 Client_send_message(client, sendmsg);
274 /* Iterate channels and send channel links info */
276 while (Chan_iterate(&ch_itr) != NULL) {
277 if (ch_itr->linkcount > 0) { /* Has links */
282 sendmsg = Msg_create(ChannelState);
283 sendmsg->payload.channelState->has_channel_id = true;
284 sendmsg->payload.channelState->channel_id = ch_itr->id;
285 sendmsg->payload.channelState->n_links = ch_itr->linkcount;
287 links = (uint32_t *)malloc(ch_itr->linkcount * sizeof(uint32_t));
288 list_iterate(itr, &ch_itr->channel_links) { /* Iterate links */
290 ch = list_get_entry(itr, channel_t, link_node);
293 sendmsg->payload.channelState->links = links;
294 Client_send_message(client, sendmsg);
298 /* Send user state for connecting user to other users */
299 sendmsg = Msg_create(UserState);
300 sendmsg->payload.userState->has_session = true;
301 sendmsg->payload.userState->session = client->sessionId;
302 sendmsg->payload.userState->name = strdup(client->username);
303 sendmsg->payload.userState->has_channel_id = true;
304 sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
306 Client_send_message_except(client, sendmsg);
309 while (Client_iterate(&client_itr) != NULL) {
310 if (!IS_AUTH(client_itr))
312 sendmsg = Msg_create(UserState);
313 sendmsg->payload.userState->has_session = true;
314 sendmsg->payload.userState->session = client_itr->sessionId;
315 sendmsg->payload.userState->name = strdup(client_itr->username);
316 sendmsg->payload.userState->has_channel_id = true;
317 sendmsg->payload.userState->channel_id = ((channel_t *)client_itr->channel)->id;
319 if (client_itr->self_deaf) {
320 sendmsg->payload.userState->has_self_deaf = true;
321 sendmsg->payload.userState->self_deaf = true;
323 if (client_itr->self_mute) {
324 sendmsg->payload.userState->has_self_mute = true;
325 sendmsg->payload.userState->self_mute = true;
327 if (client_itr->deaf) {
328 sendmsg->payload.userState->has_deaf = true;
329 sendmsg->payload.userState->deaf = true;
331 if (client_itr->mute) {
332 sendmsg->payload.userState->has_mute = true;
333 sendmsg->payload.userState->mute = true;
335 if (client_itr->recording) {
336 sendmsg->payload.userState->has_recording = true;
337 sendmsg->payload.userState->recording = true;
339 Client_send_message(client, sendmsg);
343 sendmsg = Msg_create(ServerSync);
344 sendmsg->payload.serverSync->has_session = true;
345 sendmsg->payload.serverSync->session = client->sessionId;
346 sendmsg->payload.serverSync->welcome_text = strdup(getStrConf(WELCOMETEXT));
347 sendmsg->payload.serverSync->has_max_bandwidth = true;
348 sendmsg->payload.serverSync->max_bandwidth = getIntConf(MAX_BANDWIDTH);
349 Client_send_message(client, sendmsg);
351 /* Server config message */
352 sendmsg = Msg_create(ServerConfig);
353 sendmsg->payload.serverConfig->has_allow_html = true;
354 sendmsg->payload.serverConfig->allow_html = true; /* Support this? */
355 sendmsg->payload.serverConfig->has_message_length = true;
356 sendmsg->payload.serverConfig->message_length = MAX_TEXT; /* Hardcoded */
357 sendmsg->payload.serverConfig->has_image_message_length = true;
358 sendmsg->payload.serverConfig->image_message_length = 0; /* XXX */
359 Client_send_message(client, sendmsg);
361 Log_info_client(client, "User %s authenticated", client->username);
365 if (msg->payload.ping->has_good)
366 client->cryptState.uiRemoteGood = msg->payload.ping->good;
367 if (msg->payload.ping->has_late)
368 client->cryptState.uiRemoteLate = msg->payload.ping->late;
369 if (msg->payload.ping->has_lost)
370 client->cryptState.uiRemoteLost = msg->payload.ping->lost;
371 if (msg->payload.ping->has_resync)
372 client->cryptState.uiRemoteResync = msg->payload.ping->resync;
374 Log_debug("Ping <-: %d %d %d %d",
375 client->cryptState.uiRemoteGood, client->cryptState.uiRemoteLate,
376 client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync
379 client->UDPPingAvg = msg->payload.ping->udp_ping_avg;
380 client->UDPPingVar = msg->payload.ping->udp_ping_var;
381 client->TCPPingAvg = msg->payload.ping->tcp_ping_avg;
382 client->TCPPingVar = msg->payload.ping->tcp_ping_var;
383 client->UDPPackets = msg->payload.ping->udp_packets;
384 client->TCPPackets = msg->payload.ping->tcp_packets;
386 sendmsg = Msg_create(Ping);
388 sendmsg->payload.ping->timestamp = msg->payload.ping->timestamp;
389 sendmsg->payload.ping->has_timestamp = true;
390 sendmsg->payload.ping->good = client->cryptState.uiGood;
391 sendmsg->payload.ping->has_good = true;
392 sendmsg->payload.ping->late = client->cryptState.uiLate;
393 sendmsg->payload.ping->has_late = true;
394 sendmsg->payload.ping->lost = client->cryptState.uiLost;
395 sendmsg->payload.ping->has_lost = true;
396 sendmsg->payload.ping->resync = client->cryptState.uiResync;
397 sendmsg->payload.ping->has_resync = true;
399 Client_send_message(client, sendmsg);
400 Log_debug("Ping ->: %d %d %d %d",
401 client->cryptState.uiGood, client->cryptState.uiLate,
402 client->cryptState.uiLost, client->cryptState.uiResync);
406 Log_debug("Voice channel crypt resync requested");
407 if (!msg->payload.cryptSetup->has_client_nonce) {
408 sendmsg = Msg_create(CryptSetup);
409 sendmsg->payload.cryptSetup->has_server_nonce = true;
410 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.decrypt_iv;
411 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
412 Client_send_message(client, sendmsg);
414 memcpy(client->cryptState.decrypt_iv, msg->payload.cryptSetup->client_nonce.data, AES_BLOCK_SIZE);
415 client->cryptState.uiResync++;
420 /* Only allow state changes for for the self user unless an admin is issuing */
421 if (msg->payload.userState->has_session &&
422 msg->payload.userState->session != client->sessionId && !client->isAdmin) {
423 sendPermissionDenied(client, "Permission denied");
426 if (msg->payload.userState->has_session && msg->payload.userState->session != client->sessionId) {
427 while (Client_iterate(&target) != NULL) {
428 if (target->sessionId == msg->payload.userState->session)
431 if (target == NULL) {
432 Log_warn("Client with sessionID %d not found", msg->payload.userState->session);
437 if (msg->payload.userState->has_user_id || msg->payload.userState->has_suppress ||
438 msg->payload.userState->has_priority_speaker || msg->payload.userState->has_texture) {
439 sendPermissionDenied(client, "Not supported by uMurmur");
446 msg->payload.userState->has_session = true;
447 msg->payload.userState->session = target->sessionId;
448 msg->payload.userState->has_actor = true;
449 msg->payload.userState->actor = client->sessionId;
451 if (msg->payload.userState->has_deaf) {
452 target->deaf = msg->payload.userState->deaf;
454 msg->payload.userState->has_mute = true;
455 msg->payload.userState->mute = true;
458 if (msg->payload.userState->has_mute) {
459 target->mute = msg->payload.userState->mute;
461 msg->payload.userState->has_deaf = true;
462 msg->payload.userState->deaf = false;
463 target->deaf = false;
466 if (msg->payload.userState->has_self_deaf) {
467 client->self_deaf = msg->payload.userState->self_deaf;
468 if (client->self_deaf) {
469 msg->payload.userState->has_self_mute = true;
470 msg->payload.userState->self_mute = true;
473 if (msg->payload.userState->has_self_mute) {
474 client->self_mute = msg->payload.userState->self_mute;
475 if (!client->self_mute) {
476 msg->payload.userState->has_self_deaf = true;
477 msg->payload.userState->self_deaf = false;
478 client->self_deaf = false;
481 if (msg->payload.userState->has_recording &&
482 msg->payload.userState->recording != client->recording) {
483 client->recording = msg->payload.userState->recording;
487 message = malloc(strlen(client->username) + 32);
489 Log_fatal("Out of memory");
490 tree_id = malloc(sizeof(uint32_t));
492 Log_fatal("Out of memory");
494 sendmsg = Msg_create(TextMessage);
495 sendmsg->payload.textMessage->message = message;
496 sendmsg->payload.textMessage->n_tree_id = 1;
497 sendmsg->payload.textMessage->tree_id = tree_id;
498 if (client->recording)
499 sprintf(message, "User %s started recording", client->username);
501 sprintf(message, "User %s stopped recording", client->username);
502 Client_send_message_except_ver(NULL, sendmsg, ~0x010203);
505 if (msg->payload.userState->has_channel_id) {
507 channelJoinResult_t chjoin_rc = Chan_userJoin_id_test(msg->payload.userState->channel_id, target);
509 if (chjoin_rc != CHJOIN_OK) {
510 if (chjoin_rc == CHJOIN_WRONGPW) {
511 if (target == client && !client->isAdmin) {
512 sendPermissionDenied(client, "Wrong channel password");
515 /* Tricky one: if user hasn't the password, but is moved to the channel by admin then let
516 * the user in. Also let admin user in regardless of channel password.
517 * Take no action on other errors.
519 else if (!client->isAdmin)
525 leave_id = Chan_userJoin_id(msg->payload.userState->channel_id, target);
527 Log_debug("Removing channel ID %d", leave_id);
528 sendmsg = Msg_create(ChannelRemove);
529 sendmsg->payload.channelRemove->channel_id = leave_id;
532 if (msg->payload.userState->has_plugin_context) {
534 free(client->context);
535 client->context = malloc(msg->payload.userState->plugin_context.len);
536 if (client->context == NULL)
537 Log_fatal("Out of memory");
538 memcpy(client->context, msg->payload.userState->plugin_context.data,
539 msg->payload.userState->plugin_context.len);
541 break; /* Don't inform other users about this state */
546 Client_send_message_except(NULL, msg);
548 /* Need to send remove channel message _after_ UserState message */
550 Client_send_message_except(NULL, sendmsg);
554 if (!getBoolConf(ALLOW_TEXTMESSAGE))
556 msg->payload.textMessage->has_actor = true;
557 msg->payload.textMessage->actor = client->sessionId;
559 /* XXX - HTML is allowed and can't be turned off */
560 if (msg->payload.textMessage->n_tree_id > 0) {
561 sendPermissionDenied(client, "Tree message not supported");
565 if (msg->payload.textMessage->n_channel_id > 0) { /* To channel */
568 for (i = 0; i < msg->payload.textMessage->n_channel_id; i++) {
571 Chan_iterate(&ch_itr);
572 } while (ch_itr != NULL && ch_itr->id != msg->payload.textMessage->channel_id[i]);
573 if (ch_itr != NULL) {
575 list_iterate(itr, &ch_itr->clients) {
577 c = list_get_entry(itr, client_t, chan_node);
578 if (c != client && !c->deaf && !c->self_deaf) {
580 Client_send_message(c, msg);
581 Log_debug("Text message to session ID %d", c->sessionId);
587 if (msg->payload.textMessage->n_session > 0) { /* To user */
590 for (i = 0; i < msg->payload.textMessage->n_session; i++) {
592 while (Client_iterate(&itr) != NULL) {
595 if (itr->sessionId == msg->payload.textMessage->session[i]) {
596 if (!itr->deaf && !itr->self_deaf) {
598 Client_send_message(itr, msg);
599 Log_debug("Text message to session ID %d", itr->sessionId);
605 Log_warn("TextMessage: Session ID %d not found", msg->payload.textMessage->session[i]);
612 int i, j, count, targetId = msg->payload.voiceTarget->id;
613 struct _MumbleProto__VoiceTarget__Target *target;
615 if (!targetId || targetId >= 0x1f)
617 Voicetarget_add_id(client, targetId);
618 count = msg->payload.voiceTarget->n_targets;
621 for (i = 0; i < count; i++) {
622 target = msg->payload.voiceTarget->targets[i];
623 for (j = 0; j < target->n_session; j++)
624 Voicetarget_add_session(client, targetId, target->session[j]);
625 if (target->has_channel_id) {
626 bool_t linked = false, children = false;
627 if (target->has_links)
628 linked = target->links;
629 if (target->has_children)
630 children = target->children;
631 Voicetarget_add_channel(client, targetId, target->channel_id, linked, children);
637 Log_debug("Version message received");
638 if (msg->payload.version->has_version) {
639 client->version = msg->payload.version->version;
640 Log_debug("Client version 0x%x", client->version);
642 if (msg->payload.version->release) {
643 if (client->release) free(client->release);
644 client->release = strdup(msg->payload.version->release);
645 Log_debug("Client release %s", client->release);
647 if (msg->payload.version->os) {
648 if (client->os) free(client->os);
649 client->os = strdup(msg->payload.version->os);
650 Log_debug("Client OS %s", client->os);
652 if (msg->payload.version->os_version) {
653 if (client->os_version) free(client->os_version);
654 client->os_version = strdup(msg->payload.version->os_version);
655 Log_debug("Client OS version %s", client->os_version);
658 case PermissionQuery:
659 Msg_inc_ref(msg); /* Re-use message */
660 msg->payload.permissionQuery->has_permissions = true;
663 msg->payload.permissionQuery->permissions = PERM_ADMIN;
665 msg->payload.permissionQuery->permissions = PERM_DEFAULT;
667 if (!getBoolConf(ALLOW_TEXTMESSAGE))
668 msg->payload.permissionQuery->permissions &= ~PERM_TEXTMESSAGE;
669 if (!getBoolConf(ENABLE_BAN))
670 msg->payload.permissionQuery->permissions &= ~PERM_BAN;
672 Client_send_message(client, msg);
675 client->bUDP = false;
676 Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
680 channel_t *ch_itr, *parent, *newchan;
682 /* Don't allow any changes to existing channels */
683 if (msg->payload.channelState->has_channel_id) {
684 sendPermissionDenied(client, "Not supported by uMurmur");
687 /* Must have parent */
688 if (!msg->payload.channelState->has_parent) {
689 sendPermissionDenied(client, "Not supported by uMurmur");
693 if (msg->payload.channelState->name == NULL) {
694 sendPermissionDenied(client, "Not supported by uMurmur");
697 /* Must be temporary channel */
698 if (msg->payload.channelState->temporary != true) {
699 sendPermissionDenied(client, "Only temporary channels are supported by uMurmur");
702 /* Check channel name is OK */
703 if (strlen(msg->payload.channelState->name) > MAX_TEXT) {
704 sendPermissionDenied(client, "Channel name too long");
708 parent = Chan_fromId(msg->payload.channelState->parent);
712 while (Chan_iterate_siblings(parent, &ch_itr) != NULL) {
713 if (strcmp(ch_itr->name, msg->payload.channelState->name) == 0) {
714 sendPermissionDenied(client, "Channel already exists");
721 /* Disallow temporary channels as siblings to temporary channels */
722 if (parent->temporary) {
723 sendPermissionDenied(client, "Parent channel is temporary channel");
727 /* XXX - Murmur looks for "\\w" and sends perm denied if not found.
728 * I don't know why so I don't do that here...
731 /* Create the channel */
732 newchan = Chan_createChannel(msg->payload.channelState->name,
733 msg->payload.channelState->description);
734 newchan->temporary = true;
735 if (msg->payload.channelState->has_position)
736 newchan->position = msg->payload.channelState->position;
737 Chan_addChannel(parent, newchan);
738 msg->payload.channelState->has_channel_id = true;
739 msg->payload.channelState->channel_id = newchan->id;
741 Client_send_message_except(NULL, msg);
743 /* Join the creating user */
744 sendmsg = Msg_create(UserState);
745 sendmsg->payload.userState->has_session = true;
746 sendmsg->payload.userState->session = client->sessionId;
747 sendmsg->payload.userState->has_channel_id = true;
748 sendmsg->payload.userState->channel_id = newchan->id;
749 Client_send_message_except(NULL, sendmsg);
751 leave_id = Chan_userJoin(newchan, client);
753 Log_debug("Removing channel ID %d", leave_id);
754 sendmsg = Msg_create(ChannelRemove);
755 sendmsg->payload.channelRemove->channel_id = leave_id;
756 Client_send_message_except(NULL, sendmsg);
763 client_t *target = NULL;
764 codec_t *codec_itr = NULL;
766 bool_t details = true;
768 if (msg->payload.userStats->has_stats_only)
769 details = !msg->payload.userStats->stats_only;
771 if (!msg->payload.userStats->has_session)
772 sendPermissionDenied(client, "Not supported by uMurmur");
773 while (Client_iterate(&target) != NULL) {
774 if (!IS_AUTH(target))
776 if (target->sessionId == msg->payload.userStats->session)
779 if (!target) /* Not found */
783 * Differences from Murmur:
784 * o Ignoring certificates intentionally
785 * o Ignoring channel local determining
788 sendmsg = Msg_create(UserStats);
789 sendmsg->payload.userStats->session = msg->payload.userStats->session;
790 sendmsg->payload.userStats->from_client->has_good = true;
791 sendmsg->payload.userStats->from_client->good = target->cryptState.uiGood;
792 sendmsg->payload.userStats->from_client->has_late = true;
793 sendmsg->payload.userStats->from_client->late = target->cryptState.uiLate;
794 sendmsg->payload.userStats->from_client->has_lost = true;
795 sendmsg->payload.userStats->from_client->lost = target->cryptState.uiLost;
796 sendmsg->payload.userStats->from_client->has_resync = true;
797 sendmsg->payload.userStats->from_client->resync = target->cryptState.uiResync;
799 sendmsg->payload.userStats->from_server->has_good = true;
800 sendmsg->payload.userStats->from_server->good = target->cryptState.uiRemoteGood;
801 sendmsg->payload.userStats->from_server->has_late = true;
802 sendmsg->payload.userStats->from_server->late = target->cryptState.uiRemoteLate;
803 sendmsg->payload.userStats->from_server->has_lost = true;
804 sendmsg->payload.userStats->from_server->lost = target->cryptState.uiRemoteLost;
805 sendmsg->payload.userStats->from_server->has_resync = true;
806 sendmsg->payload.userStats->from_server->resync = target->cryptState.uiRemoteResync;
808 sendmsg->payload.userStats->has_udp_packets = true;
809 sendmsg->payload.userStats->udp_packets = target->UDPPackets;
810 sendmsg->payload.userStats->has_udp_ping_avg = true;
811 sendmsg->payload.userStats->udp_ping_avg = target->UDPPingAvg;
812 sendmsg->payload.userStats->has_udp_ping_var = true;
813 sendmsg->payload.userStats->udp_ping_var = target->UDPPingVar;
815 sendmsg->payload.userStats->has_tcp_ping_avg = true;
816 sendmsg->payload.userStats->tcp_ping_avg = target->TCPPingAvg;
817 sendmsg->payload.userStats->has_tcp_ping_var = true;
818 sendmsg->payload.userStats->tcp_ping_var = target->TCPPingVar;
819 sendmsg->payload.userStats->has_tcp_packets = true;
820 sendmsg->payload.userStats->tcp_packets = target->TCPPackets;
824 sendmsg->payload.userStats->version->has_version = true;
825 sendmsg->payload.userStats->version->version = target->version;
827 sendmsg->payload.userStats->version->release = strdup(target->release);
829 sendmsg->payload.userStats->version->os = strdup(target->os);
830 if (target->os_version)
831 sendmsg->payload.userStats->version->os_version = strdup(target->os_version);
833 sendmsg->payload.userStats->n_celt_versions = target->codec_count;
834 sendmsg->payload.userStats->celt_versions = malloc(sizeof(int32_t) * target->codec_count);
835 if (!sendmsg->payload.userStats->celt_versions)
836 Log_fatal("Out of memory");
838 while (Client_codec_iterate(target, &codec_itr) != NULL)
839 sendmsg->payload.userStats->celt_versions[i++] = codec_itr->codec;
841 sendmsg->payload.userStats->has_opus = true;
842 sendmsg->payload.userStats->opus = target->bOpus;
845 sendmsg->payload.userStats->has_address = true;
846 sendmsg->payload.userStats->address.data = malloc(sizeof(uint8_t) * 16);
847 if (!sendmsg->payload.userStats->address.data)
848 Log_fatal("Out of memory");
849 memset(sendmsg->payload.userStats->address.data, 0, 16);
850 /* ipv4 representation as ipv6 address. Supposedly correct. */
851 memcpy(&sendmsg->payload.userStats->address.data[12], &target->remote_tcp.sin_addr, 4);
852 memset(&sendmsg->payload.userStats->address.data[10], 0xff, 2); /* IPv4 */
853 sendmsg->payload.userStats->address.len = 16;
856 sendmsg->payload.userStats->has_bandwidth = true;
857 sendmsg->payload.userStats->bandwidth = target->availableBandwidth;
860 sendmsg->payload.userStats->has_onlinesecs = true;
861 sendmsg->payload.userStats->onlinesecs = Timer_elapsed(&target->connectTime) / 1000000LL;
863 sendmsg->payload.userStats->has_idlesecs = true;
864 sendmsg->payload.userStats->idlesecs = Timer_elapsed(&target->idleTime) / 1000000LL;
865 Client_send_message(client, sendmsg);
870 /* Only admin can issue this */
871 if (!client->isAdmin) {
872 sendPermissionDenied(client, "Permission denied");
875 while (Client_iterate(&target) != NULL) {
876 if (target->sessionId == msg->payload.userRemove->session)
879 if (target == NULL) {
880 Log_warn("Client with sessionId %d not found", msg->payload.userRemove->session);
883 msg->payload.userRemove->session = target->sessionId;
884 msg->payload.userRemove->has_actor = true;
885 msg->payload.userRemove->actor = client->sessionId;
887 if (msg->payload.userRemove->has_ban && msg->payload.userRemove->ban) {
888 if (!getBoolConf(ENABLE_BAN))
889 sendPermissionDenied(client, "Permission denied");
891 Ban_UserBan(target, msg->payload.userRemove->reason);
893 Log_info_client(target, "User kicked. Reason: '%s'",
894 strlen(msg->payload.userRemove->reason) == 0 ? "N/A" : msg->payload.userRemove->reason);
899 Client_send_message_except(NULL, msg);
900 Client_close(target);
903 /* Only admin can issue this */
904 if (!client->isAdmin) {
905 sendPermissionDenied(client, "Permission denied");
908 if (!getBoolConf(ENABLE_BAN)) {
909 sendPermissionDenied(client, "Permission denied");
912 if (msg->payload.banList->has_query && msg->payload.banList->query) {
913 /* Create banlist message and add banentrys */
914 sendmsg = Ban_getBanList();
915 Client_send_message(client, sendmsg);
917 /* Clear banlist and set the new one */
919 Ban_putBanList(msg, msg->payload.banList->n_bans);
923 /* Permission denied for all these messages. Not implemented. */
926 case ContextActionAdd:
930 sendPermissionDenied(client, "Not supported by uMurmur");
934 Log_warn("Message %d not handled", msg->messageType);
943 Client_close(client);