1 /* Copyright (C) 2009-2012, Martin Johansson <martin@fatbob.nu>
2 Copyright (C) 2005-2012, 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 Log_debug("Send channel info: %s", sendmsg->payload.channelState->name);
267 Client_send_message(client, sendmsg);
270 /* Iterate channels and send channel links info */
272 while (Chan_iterate(&ch_itr) != NULL) {
273 if (ch_itr->linkcount > 0) { /* Has links */
278 sendmsg = Msg_create(ChannelState);
279 sendmsg->payload.channelState->has_channel_id = true;
280 sendmsg->payload.channelState->channel_id = ch_itr->id;
281 sendmsg->payload.channelState->n_links = ch_itr->linkcount;
283 links = (uint32_t *)malloc(ch_itr->linkcount * sizeof(uint32_t));
284 list_iterate(itr, &ch_itr->channel_links) { /* Iterate links */
286 ch = list_get_entry(itr, channel_t, link_node);
289 sendmsg->payload.channelState->links = links;
290 Client_send_message(client, sendmsg);
294 /* Send user state for connecting user to other users */
295 sendmsg = Msg_create(UserState);
296 sendmsg->payload.userState->has_session = true;
297 sendmsg->payload.userState->session = client->sessionId;
298 sendmsg->payload.userState->name = strdup(client->username);
299 sendmsg->payload.userState->has_channel_id = true;
300 sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
302 Client_send_message_except(client, sendmsg);
305 while (Client_iterate(&client_itr) != NULL) {
306 if (!IS_AUTH(client_itr))
308 sendmsg = Msg_create(UserState);
309 sendmsg->payload.userState->has_session = true;
310 sendmsg->payload.userState->session = client_itr->sessionId;
311 sendmsg->payload.userState->name = strdup(client_itr->username);
312 sendmsg->payload.userState->has_channel_id = true;
313 sendmsg->payload.userState->channel_id = ((channel_t *)client_itr->channel)->id;
315 if (client_itr->self_deaf) {
316 sendmsg->payload.userState->has_self_deaf = true;
317 sendmsg->payload.userState->self_deaf = true;
319 if (client_itr->self_mute) {
320 sendmsg->payload.userState->has_self_mute = true;
321 sendmsg->payload.userState->self_mute = true;
323 if (client_itr->deaf) {
324 sendmsg->payload.userState->has_deaf = true;
325 sendmsg->payload.userState->deaf = true;
327 if (client_itr->mute) {
328 sendmsg->payload.userState->has_mute = true;
329 sendmsg->payload.userState->mute = true;
331 if (client_itr->recording) {
332 sendmsg->payload.userState->has_recording = true;
333 sendmsg->payload.userState->recording = true;
335 Client_send_message(client, sendmsg);
339 sendmsg = Msg_create(ServerSync);
340 sendmsg->payload.serverSync->has_session = true;
341 sendmsg->payload.serverSync->session = client->sessionId;
342 sendmsg->payload.serverSync->welcome_text = strdup(getStrConf(WELCOMETEXT));
343 sendmsg->payload.serverSync->has_max_bandwidth = true;
344 sendmsg->payload.serverSync->max_bandwidth = getIntConf(MAX_BANDWIDTH);
345 Client_send_message(client, sendmsg);
347 /* Server config message */
348 sendmsg = Msg_create(ServerConfig);
349 sendmsg->payload.serverConfig->has_allow_html = true;
350 sendmsg->payload.serverConfig->allow_html = true; /* Support this? */
351 sendmsg->payload.serverConfig->has_message_length = true;
352 sendmsg->payload.serverConfig->message_length = MAX_TEXT; /* Hardcoded */
353 sendmsg->payload.serverConfig->has_image_message_length = true;
354 sendmsg->payload.serverConfig->image_message_length = 0; /* XXX */
355 Client_send_message(client, sendmsg);
357 Log_info_client(client, "User %s authenticated", client->username);
361 if (msg->payload.ping->has_good)
362 client->cryptState.uiRemoteGood = msg->payload.ping->good;
363 if (msg->payload.ping->has_late)
364 client->cryptState.uiRemoteLate = msg->payload.ping->late;
365 if (msg->payload.ping->has_lost)
366 client->cryptState.uiRemoteLost = msg->payload.ping->lost;
367 if (msg->payload.ping->has_resync)
368 client->cryptState.uiRemoteResync = msg->payload.ping->resync;
370 Log_debug("Ping <-: %d %d %d %d",
371 client->cryptState.uiRemoteGood, client->cryptState.uiRemoteLate,
372 client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync
375 client->UDPPingAvg = msg->payload.ping->udp_ping_avg;
376 client->UDPPingVar = msg->payload.ping->udp_ping_var;
377 client->TCPPingAvg = msg->payload.ping->tcp_ping_avg;
378 client->TCPPingVar = msg->payload.ping->tcp_ping_var;
379 client->UDPPackets = msg->payload.ping->udp_packets;
380 client->TCPPackets = msg->payload.ping->tcp_packets;
382 sendmsg = Msg_create(Ping);
384 sendmsg->payload.ping->timestamp = msg->payload.ping->timestamp;
385 sendmsg->payload.ping->has_timestamp = true;
386 sendmsg->payload.ping->good = client->cryptState.uiGood;
387 sendmsg->payload.ping->has_good = true;
388 sendmsg->payload.ping->late = client->cryptState.uiLate;
389 sendmsg->payload.ping->has_late = true;
390 sendmsg->payload.ping->lost = client->cryptState.uiLost;
391 sendmsg->payload.ping->has_lost = true;
392 sendmsg->payload.ping->resync = client->cryptState.uiResync;
393 sendmsg->payload.ping->has_resync = true;
395 Client_send_message(client, sendmsg);
396 Log_debug("Ping ->: %d %d %d %d",
397 client->cryptState.uiGood, client->cryptState.uiLate,
398 client->cryptState.uiLost, client->cryptState.uiResync);
402 Log_debug("Voice channel crypt resync requested");
403 if (!msg->payload.cryptSetup->has_client_nonce) {
404 sendmsg = Msg_create(CryptSetup);
405 sendmsg->payload.cryptSetup->has_server_nonce = true;
406 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.decrypt_iv;
407 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
408 Client_send_message(client, sendmsg);
410 memcpy(client->cryptState.decrypt_iv, msg->payload.cryptSetup->client_nonce.data, AES_BLOCK_SIZE);
411 client->cryptState.uiResync++;
416 /* Only allow state changes for for the self user unless an admin is issuing */
417 if (msg->payload.userState->has_session &&
418 msg->payload.userState->session != client->sessionId && !client->isAdmin) {
419 sendPermissionDenied(client, "Permission denied");
422 if (msg->payload.userState->has_session && msg->payload.userState->session != client->sessionId) {
423 while (Client_iterate(&target) != NULL) {
424 if (target->sessionId == msg->payload.userState->session)
427 if (target == NULL) {
428 Log_warn("Client with sessionID %d not found", msg->payload.userState->session);
433 if (msg->payload.userState->has_user_id || msg->payload.userState->has_suppress ||
434 msg->payload.userState->has_priority_speaker || msg->payload.userState->has_texture) {
435 sendPermissionDenied(client, "Not supported by uMurmur");
442 msg->payload.userState->has_session = true;
443 msg->payload.userState->session = target->sessionId;
444 msg->payload.userState->has_actor = true;
445 msg->payload.userState->actor = client->sessionId;
447 if (msg->payload.userState->has_deaf) {
448 target->deaf = msg->payload.userState->deaf;
450 msg->payload.userState->has_mute = true;
451 msg->payload.userState->mute = true;
454 if (msg->payload.userState->has_mute) {
455 target->mute = msg->payload.userState->mute;
457 msg->payload.userState->has_deaf = true;
458 msg->payload.userState->deaf = false;
459 target->deaf = false;
462 if (msg->payload.userState->has_self_deaf) {
463 client->self_deaf = msg->payload.userState->self_deaf;
464 if (client->self_deaf) {
465 msg->payload.userState->has_self_mute = true;
466 msg->payload.userState->self_mute = true;
469 if (msg->payload.userState->has_self_mute) {
470 client->self_mute = msg->payload.userState->self_mute;
471 if (!client->self_mute) {
472 msg->payload.userState->has_self_deaf = true;
473 msg->payload.userState->self_deaf = false;
474 client->self_deaf = false;
477 if (msg->payload.userState->has_recording &&
478 msg->payload.userState->recording != client->recording) {
479 client->recording = msg->payload.userState->recording;
483 message = malloc(strlen(client->username) + 32);
485 Log_fatal("Out of memory");
486 tree_id = malloc(sizeof(uint32_t));
488 Log_fatal("Out of memory");
490 sendmsg = Msg_create(TextMessage);
491 sendmsg->payload.textMessage->message = message;
492 sendmsg->payload.textMessage->n_tree_id = 1;
493 sendmsg->payload.textMessage->tree_id = tree_id;
494 if (client->recording)
495 sprintf(message, "User %s started recording", client->username);
497 sprintf(message, "User %s stopped recording", client->username);
498 Client_send_message_except_ver(NULL, sendmsg, ~0x010203);
501 if (msg->payload.userState->has_channel_id) {
503 channelJoinResult_t chjoin_rc = Chan_userJoin_id_test(msg->payload.userState->channel_id, target);
505 if (chjoin_rc != CHJOIN_OK) {
506 if (chjoin_rc == CHJOIN_WRONGPW) {
507 if (target == client && !client->isAdmin) {
508 sendPermissionDenied(client, "Wrong channel password");
511 /* Tricky one: if user hasn't the password, but is moved to the channel by admin then let
512 * the user in. Also let admin user in regardless of channel password.
513 * Take no action on other errors.
515 else if (!client->isAdmin)
521 leave_id = Chan_userJoin_id(msg->payload.userState->channel_id, target);
523 Log_debug("Removing channel ID %d", leave_id);
524 sendmsg = Msg_create(ChannelRemove);
525 sendmsg->payload.channelRemove->channel_id = leave_id;
528 if (msg->payload.userState->has_plugin_context) {
530 free(client->context);
531 client->context = malloc(msg->payload.userState->plugin_context.len);
532 if (client->context == NULL)
533 Log_fatal("Out of memory");
534 memcpy(client->context, msg->payload.userState->plugin_context.data,
535 msg->payload.userState->plugin_context.len);
537 break; /* Don't inform other users about this state */
542 Client_send_message_except(NULL, msg);
544 /* Need to send remove channel message _after_ UserState message */
546 Client_send_message_except(NULL, sendmsg);
550 if (!getBoolConf(ALLOW_TEXTMESSAGE))
552 msg->payload.textMessage->has_actor = true;
553 msg->payload.textMessage->actor = client->sessionId;
555 /* XXX - HTML is allowed and can't be turned off */
556 if (msg->payload.textMessage->n_tree_id > 0) {
557 sendPermissionDenied(client, "Tree message not supported");
561 if (msg->payload.textMessage->n_channel_id > 0) { /* To channel */
564 for (i = 0; i < msg->payload.textMessage->n_channel_id; i++) {
567 Chan_iterate(&ch_itr);
568 } while (ch_itr != NULL && ch_itr->id != msg->payload.textMessage->channel_id[i]);
569 if (ch_itr != NULL) {
571 list_iterate(itr, &ch_itr->clients) {
573 c = list_get_entry(itr, client_t, chan_node);
574 if (c != client && !c->deaf && !c->self_deaf) {
576 Client_send_message(c, msg);
577 Log_debug("Text message to session ID %d", c->sessionId);
583 if (msg->payload.textMessage->n_session > 0) { /* To user */
586 for (i = 0; i < msg->payload.textMessage->n_session; i++) {
588 while (Client_iterate(&itr) != NULL) {
591 if (itr->sessionId == msg->payload.textMessage->session[i]) {
592 if (!itr->deaf && !itr->self_deaf) {
594 Client_send_message(itr, msg);
595 Log_debug("Text message to session ID %d", itr->sessionId);
601 Log_warn("TextMessage: Session ID %d not found", msg->payload.textMessage->session[i]);
608 int i, j, count, targetId = msg->payload.voiceTarget->id;
609 struct _MumbleProto__VoiceTarget__Target *target;
611 if (!targetId || targetId >= 0x1f)
613 Voicetarget_add_id(client, targetId);
614 count = msg->payload.voiceTarget->n_targets;
617 for (i = 0; i < count; i++) {
618 target = msg->payload.voiceTarget->targets[i];
619 for (j = 0; j < target->n_session; j++)
620 Voicetarget_add_session(client, targetId, target->session[j]);
621 if (target->has_channel_id) {
622 bool_t linked = false, children = false;
623 if (target->has_links)
624 linked = target->links;
625 if (target->has_children)
626 children = target->children;
627 Voicetarget_add_channel(client, targetId, target->channel_id, linked, children);
633 Log_debug("Version message received");
634 if (msg->payload.version->has_version) {
635 client->version = msg->payload.version->version;
636 Log_debug("Client version 0x%x", client->version);
638 if (msg->payload.version->release) {
639 if (client->release) free(client->release);
640 client->release = strdup(msg->payload.version->release);
641 Log_debug("Client release %s", client->release);
643 if (msg->payload.version->os) {
644 if (client->os) free(client->os);
645 client->os = strdup(msg->payload.version->os);
646 Log_debug("Client OS %s", client->os);
648 if (msg->payload.version->os_version) {
649 if (client->os_version) free(client->os_version);
650 client->os_version = strdup(msg->payload.version->os_version);
651 Log_debug("Client OS version %s", client->os_version);
654 case PermissionQuery:
655 Msg_inc_ref(msg); /* Re-use message */
656 msg->payload.permissionQuery->has_permissions = true;
659 msg->payload.permissionQuery->permissions = PERM_ADMIN;
661 msg->payload.permissionQuery->permissions = PERM_DEFAULT;
663 if (!getBoolConf(ALLOW_TEXTMESSAGE))
664 msg->payload.permissionQuery->permissions &= ~PERM_TEXTMESSAGE;
665 if (!getBoolConf(ENABLE_BAN))
666 msg->payload.permissionQuery->permissions &= ~PERM_BAN;
668 Client_send_message(client, msg);
671 client->bUDP = false;
672 Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
676 channel_t *ch_itr, *parent, *newchan;
678 /* Don't allow any changes to existing channels */
679 if (msg->payload.channelState->has_channel_id) {
680 sendPermissionDenied(client, "Not supported by uMurmur");
683 /* Must have parent */
684 if (!msg->payload.channelState->has_parent) {
685 sendPermissionDenied(client, "Not supported by uMurmur");
689 if (msg->payload.channelState->name == NULL) {
690 sendPermissionDenied(client, "Not supported by uMurmur");
693 /* Must be temporary channel */
694 if (msg->payload.channelState->temporary != true) {
695 sendPermissionDenied(client, "Only temporary channels are supported by uMurmur");
698 /* Check channel name is OK */
699 if (strlen(msg->payload.channelState->name) > MAX_TEXT) {
700 sendPermissionDenied(client, "Channel name too long");
704 parent = Chan_fromId(msg->payload.channelState->parent);
708 while (Chan_iterate_siblings(parent, &ch_itr) != NULL) {
709 if (strcmp(ch_itr->name, msg->payload.channelState->name) == 0) {
710 sendPermissionDenied(client, "Channel already exists");
717 /* Disallow temporary channels as siblings to temporary channels */
718 if (parent->temporary) {
719 sendPermissionDenied(client, "Parent channel is temporary channel");
723 /* XXX - Murmur looks for "\\w" and sends perm denied if not found.
724 * I don't know why so I don't do that here...
727 /* Create the channel */
728 newchan = Chan_createChannel(msg->payload.channelState->name,
729 msg->payload.channelState->description);
730 newchan->temporary = true;
731 Chan_addChannel(parent, newchan);
732 msg->payload.channelState->has_channel_id = true;
733 msg->payload.channelState->channel_id = newchan->id;
735 Client_send_message_except(NULL, msg);
737 /* Join the creating user */
738 sendmsg = Msg_create(UserState);
739 sendmsg->payload.userState->has_session = true;
740 sendmsg->payload.userState->session = client->sessionId;
741 sendmsg->payload.userState->has_channel_id = true;
742 sendmsg->payload.userState->channel_id = newchan->id;
743 Client_send_message_except(NULL, sendmsg);
745 leave_id = Chan_userJoin(newchan, client);
747 Log_debug("Removing channel ID %d", leave_id);
748 sendmsg = Msg_create(ChannelRemove);
749 sendmsg->payload.channelRemove->channel_id = leave_id;
750 Client_send_message_except(NULL, sendmsg);
757 client_t *target = NULL;
758 codec_t *codec_itr = NULL;
760 bool_t details = true;
762 if (msg->payload.userStats->has_stats_only)
763 details = !msg->payload.userStats->stats_only;
765 if (!msg->payload.userStats->has_session)
766 sendPermissionDenied(client, "Not supported by uMurmur");
767 while (Client_iterate(&target) != NULL) {
768 if (!IS_AUTH(target))
770 if (target->sessionId == msg->payload.userStats->session)
773 if (!target) /* Not found */
777 * Differences from Murmur:
778 * o Ignoring certificates intentionally
779 * o Ignoring channel local determining
782 sendmsg = Msg_create(UserStats);
783 sendmsg->payload.userStats->session = msg->payload.userStats->session;
784 sendmsg->payload.userStats->from_client->has_good = true;
785 sendmsg->payload.userStats->from_client->good = target->cryptState.uiGood;
786 sendmsg->payload.userStats->from_client->has_late = true;
787 sendmsg->payload.userStats->from_client->late = target->cryptState.uiLate;
788 sendmsg->payload.userStats->from_client->has_lost = true;
789 sendmsg->payload.userStats->from_client->lost = target->cryptState.uiLost;
790 sendmsg->payload.userStats->from_client->has_resync = true;
791 sendmsg->payload.userStats->from_client->resync = target->cryptState.uiResync;
793 sendmsg->payload.userStats->from_server->has_good = true;
794 sendmsg->payload.userStats->from_server->good = target->cryptState.uiRemoteGood;
795 sendmsg->payload.userStats->from_server->has_late = true;
796 sendmsg->payload.userStats->from_server->late = target->cryptState.uiRemoteLate;
797 sendmsg->payload.userStats->from_server->has_lost = true;
798 sendmsg->payload.userStats->from_server->lost = target->cryptState.uiRemoteLost;
799 sendmsg->payload.userStats->from_server->has_resync = true;
800 sendmsg->payload.userStats->from_server->resync = target->cryptState.uiRemoteResync;
802 sendmsg->payload.userStats->has_udp_packets = true;
803 sendmsg->payload.userStats->udp_packets = target->UDPPackets;
804 sendmsg->payload.userStats->has_udp_ping_avg = true;
805 sendmsg->payload.userStats->udp_ping_avg = target->UDPPingAvg;
806 sendmsg->payload.userStats->has_udp_ping_var = true;
807 sendmsg->payload.userStats->udp_ping_var = target->UDPPingVar;
809 sendmsg->payload.userStats->has_tcp_ping_avg = true;
810 sendmsg->payload.userStats->tcp_ping_avg = target->TCPPingAvg;
811 sendmsg->payload.userStats->has_tcp_ping_var = true;
812 sendmsg->payload.userStats->tcp_ping_var = target->TCPPingVar;
813 sendmsg->payload.userStats->has_tcp_packets = true;
814 sendmsg->payload.userStats->tcp_packets = target->TCPPackets;
818 sendmsg->payload.userStats->version->has_version = true;
819 sendmsg->payload.userStats->version->version = target->version;
820 sendmsg->payload.userStats->version->release = strdup(target->release);
821 sendmsg->payload.userStats->version->os = strdup(target->os);
822 sendmsg->payload.userStats->version->os_version = strdup(target->os_version);
824 sendmsg->payload.userStats->n_celt_versions = target->codec_count;
825 sendmsg->payload.userStats->celt_versions = malloc(sizeof(int32_t) * target->codec_count);
826 if (!sendmsg->payload.userStats->celt_versions)
827 Log_fatal("Out of memory");
829 while (Client_codec_iterate(target, &codec_itr) != NULL)
830 sendmsg->payload.userStats->celt_versions[i++] = codec_itr->codec;
832 sendmsg->payload.userStats->opus = target->bOpus;
835 sendmsg->payload.userStats->has_address = true;
836 sendmsg->payload.userStats->address.data = malloc(sizeof(uint8_t) * 16);
837 if (!sendmsg->payload.userStats->address.data)
838 Log_fatal("Out of memory");
839 memset(sendmsg->payload.userStats->address.data, 0, 16);
840 /* ipv4 representation as ipv6 address. Supposedly correct. */
841 memcpy(&sendmsg->payload.userStats->address.data[12], &target->remote_tcp.sin_addr, 4);
842 memset(&sendmsg->payload.userStats->address.data[10], 0xff, 2); /* IPv4 */
843 sendmsg->payload.userStats->address.len = 16;
846 sendmsg->payload.userStats->has_bandwidth = true;
847 sendmsg->payload.userStats->bandwidth = target->availableBandwidth;
850 sendmsg->payload.userStats->has_onlinesecs = true;
851 sendmsg->payload.userStats->onlinesecs = Timer_elapsed(&target->connectTime) / 1000000LL;
853 sendmsg->payload.userStats->has_idlesecs = true;
854 sendmsg->payload.userStats->idlesecs = Timer_elapsed(&target->idleTime) / 1000000LL;
855 Client_send_message(client, sendmsg);
860 /* Only admin can issue this */
861 if (!client->isAdmin) {
862 sendPermissionDenied(client, "Permission denied");
865 while (Client_iterate(&target) != NULL) {
866 if (target->sessionId == msg->payload.userRemove->session)
869 if (target == NULL) {
870 Log_warn("Client with sessionId %d not found", msg->payload.userRemove->session);
873 msg->payload.userRemove->session = target->sessionId;
874 msg->payload.userRemove->has_actor = true;
875 msg->payload.userRemove->actor = client->sessionId;
877 if (msg->payload.userRemove->has_ban && msg->payload.userRemove->ban) {
878 if (!getBoolConf(ENABLE_BAN))
879 sendPermissionDenied(client, "Permission denied");
881 Ban_UserBan(target, msg->payload.userRemove->reason);
883 Log_info_client(target, "User kicked. Reason: '%s'",
884 strlen(msg->payload.userRemove->reason) == 0 ? "N/A" : msg->payload.userRemove->reason);
889 Client_send_message_except(NULL, msg);
890 Client_close(target);
893 /* Only admin can issue this */
894 if (!client->isAdmin) {
895 sendPermissionDenied(client, "Permission denied");
898 if (!getBoolConf(ENABLE_BAN)) {
899 sendPermissionDenied(client, "Permission denied");
902 if (msg->payload.banList->has_query && msg->payload.banList->query) {
903 /* Create banlist message and add banentrys */
904 sendmsg = Ban_getBanList();
905 Client_send_message(client, sendmsg);
907 /* Clear banlist and set the new one */
909 Ban_putBanList(msg, msg->payload.banList->n_bans);
913 /* Permission denied for all these messages. Not implemented. */
916 case ContextActionAdd:
920 sendPermissionDenied(client, "Not supported by uMurmur");
924 Log_warn("Message %d not handled", msg->messageType);
933 Client_close(client);