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 extern channel_t *defaultChan;
49 extern int iCodecAlpha, iCodecBeta;
50 extern bool_t bPreferAlpha, bOpus;
52 static void sendServerReject(client_t *client, const char *reason, MumbleProto__Reject__RejectType type)
54 message_t *msg = Msg_create(Reject);
55 msg->payload.reject->reason = strdup(reason);
56 msg->payload.reject->type = type;
57 msg->payload.reject->has_type = true;
58 Client_send_message(client, msg);
60 Log_info_client(client, "Server reject reason: %s", reason);
63 static void sendPermissionDenied(client_t *client, const char *reason)
65 message_t *msg = Msg_create(PermissionDenied);
66 msg->payload.permissionDenied->has_type = true;
67 msg->payload.permissionDenied->type = MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__Text;
68 msg->payload.permissionDenied->reason = strdup(reason);
69 Client_send_message(client, msg);
72 static void addTokens(client_t *client, message_t *msg)
75 if (client->tokencount + msg->payload.authenticate->n_tokens < MAX_TOKENS) {
76 /* Check lengths first */
77 for (i = 0; i < msg->payload.authenticate->n_tokens; i++) {
78 if (strlen(msg->payload.authenticate->tokens[i]) > MAX_TOKENSIZE - 1) {
79 sendPermissionDenied(client, "Too long token");
84 for (i = 0; i < msg->payload.authenticate->n_tokens; i++) {
85 Log_debug("Adding token '%s' to client '%s'", msg->payload.authenticate->tokens[i], client->username);
86 Client_token_add(client, msg->payload.authenticate->tokens[i]);
90 sendPermissionDenied(client, "Too many tokens");
93 void Mh_handle_message(client_t *client, message_t *msg)
95 message_t *sendmsg = NULL;
96 channel_t *ch_itr = NULL;
97 client_t *client_itr, *target;
99 if (!client->authenticated && !(msg->messageType == Authenticate ||
100 msg->messageType == Version)) {
104 switch (msg->messageType) {
110 case PermissionQuery:
113 Timer_restart(&client->idleTime);
116 switch (msg->messageType) {
118 Log_debug("Authenticate message received");
120 if (IS_AUTH(client) || !msg->payload.authenticate->username) {
121 /* Authenticate message might be sent when a tokens are changed by the user.*/
122 Client_token_free(client); /* Clear the token list */
123 if (msg->payload.authenticate->n_tokens > 0) {
124 Log_debug("Tokens in auth message from '%s'. n_tokens = %d", client->username,
125 msg->payload.authenticate->n_tokens);
126 addTokens(client, msg);
131 if (SSLi_getSHA1Hash(client->ssl, client->hash) && Ban_isBanned(client)) {
133 SSLi_hash2hex(client->hash, hexhash);
134 Log_info("Client with hash '%s' is banned. Disconnecting", hexhash);
138 client->authenticated = true;
141 while (Client_iterate(&client_itr) != NULL) {
142 if (!IS_AUTH(client_itr))
144 if (client_itr->username && strncmp(client_itr->username, msg->payload.authenticate->username, MAX_USERNAME) == 0) {
146 sprintf(buf, "Username already in use");
147 Log_debug("Username already in use");
148 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__UsernameInUse);
152 if (strlen(getStrConf(PASSPHRASE)) > 0) {
153 if (!msg->payload.authenticate->password ||
154 (msg->payload.authenticate->password &&
155 strncmp(getStrConf(PASSPHRASE), msg->payload.authenticate->password, MAX_TEXT) != 0)) {
157 sprintf(buf, "Wrong server password");
158 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__WrongServerPW);
159 Log_debug("Wrong server password: '%s'", msg->payload.authenticate->password != NULL ?
160 msg->payload.authenticate->password : "(null)");
164 if (strlen(msg->payload.authenticate->username) == 0 ||
165 strlen(msg->payload.authenticate->username) >= MAX_USERNAME) { /* XXX - other invalid names? */
167 sprintf(buf, "Invalid username");
168 Log_debug("Invalid username");
169 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__InvalidUsername);
173 if (Client_count() >= getIntConf(MAX_CLIENTS)) {
175 snprintf(buf, 64, "Server is full (max %d users)", getIntConf(MAX_CLIENTS));
176 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__ServerFull);
181 client->username = strdup(msg->payload.authenticate->username);
184 if (msg->payload.authenticate->n_tokens > 0)
185 addTokens(client, msg);
187 /* Check if admin PW among tokens */
188 if (strlen(getStrConf(ADMIN_PASSPHRASE)) > 0 &&
189 Client_token_match(client, getStrConf(ADMIN_PASSPHRASE))) {
190 client->isAdmin = true;
191 Log_info_client(client, "User provided admin password");
194 /* Setup UDP encryption */
195 CryptState_init(&client->cryptState);
196 CryptState_genKey(&client->cryptState);
197 sendmsg = Msg_create(CryptSetup);
198 sendmsg->payload.cryptSetup->has_key = true;
199 sendmsg->payload.cryptSetup->key.data = client->cryptState.raw_key;
200 sendmsg->payload.cryptSetup->key.len = AES_BLOCK_SIZE;
201 sendmsg->payload.cryptSetup->has_server_nonce = true;
202 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.encrypt_iv;
203 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
204 sendmsg->payload.cryptSetup->has_client_nonce = true;
205 sendmsg->payload.cryptSetup->client_nonce.data = client->cryptState.decrypt_iv;
206 sendmsg->payload.cryptSetup->client_nonce.len = AES_BLOCK_SIZE;
207 Client_send_message(client, sendmsg);
210 Chan_userJoin(defaultChan, client); /* Join default channel */
213 Log_debug("Client %d has %d CELT codecs", client->sessionId,
214 msg->payload.authenticate->n_celt_versions);
215 if (msg->payload.authenticate->n_celt_versions > 0) {
218 client->codec_count = msg->payload.authenticate->n_celt_versions;
220 for (i = 0; i < client->codec_count; i++)
221 Client_codec_add(client, msg->payload.authenticate->celt_versions[i]);
223 while (Client_codec_iterate(client, &codec_itr) != NULL)
224 Log_debug("Client %d CELT codec ver 0x%x", client->sessionId, codec_itr->codec);
227 Client_codec_add(client, (int32_t)0x8000000a);
228 client->codec_count = 1;
230 if (msg->payload.authenticate->opus)
231 client->bOpus = true;
233 recheckCodecVersions(client);
235 sendmsg = Msg_create(CodecVersion);
236 sendmsg->payload.codecVersion->alpha = iCodecAlpha;
237 sendmsg->payload.codecVersion->beta = iCodecBeta;
238 sendmsg->payload.codecVersion->prefer_alpha = bPreferAlpha;
239 Client_send_message(client, sendmsg);
241 /* Iterate channels and send channel info */
243 while (Chan_iterate(&ch_itr) != NULL) {
244 sendmsg = Msg_create(ChannelState);
245 sendmsg->payload.channelState->has_channel_id = true;
246 sendmsg->payload.channelState->channel_id = ch_itr->id;
247 if (ch_itr->id != 0) {
248 sendmsg->payload.channelState->has_parent = true;
249 sendmsg->payload.channelState->parent = ch_itr->parent->id;
251 sendmsg->payload.channelState->name = strdup(ch_itr->name);
253 sendmsg->payload.channelState->description = strdup(ch_itr->desc);
254 Log_debug("Send channel info: %s", sendmsg->payload.channelState->name);
255 Client_send_message(client, sendmsg);
258 /* Iterate channels and send channel links info */
260 while (Chan_iterate(&ch_itr) != NULL) {
261 if (ch_itr->linkcount > 0) { /* Has links */
266 sendmsg = Msg_create(ChannelState);
267 sendmsg->payload.channelState->has_channel_id = true;
268 sendmsg->payload.channelState->channel_id = ch_itr->id;
269 sendmsg->payload.channelState->n_links = ch_itr->linkcount;
271 links = (uint32_t *)malloc(ch_itr->linkcount * sizeof(uint32_t));
272 list_iterate(itr, &ch_itr->channel_links) { /* Iterate links */
274 ch = list_get_entry(itr, channel_t, link_node);
277 sendmsg->payload.channelState->links = links;
278 Client_send_message(client, sendmsg);
282 /* Send user state for connecting user to other users */
283 sendmsg = Msg_create(UserState);
284 sendmsg->payload.userState->has_session = true;
285 sendmsg->payload.userState->session = client->sessionId;
286 sendmsg->payload.userState->name = strdup(client->username);
287 sendmsg->payload.userState->has_channel_id = true;
288 sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
290 Client_send_message_except(client, sendmsg);
293 while (Client_iterate(&client_itr) != NULL) {
294 if (!IS_AUTH(client_itr))
296 sendmsg = Msg_create(UserState);
297 sendmsg->payload.userState->has_session = true;
298 sendmsg->payload.userState->session = client_itr->sessionId;
299 sendmsg->payload.userState->name = strdup(client_itr->username);
300 sendmsg->payload.userState->has_channel_id = true;
301 sendmsg->payload.userState->channel_id = ((channel_t *)client_itr->channel)->id;
303 if (client_itr->self_deaf) {
304 sendmsg->payload.userState->has_self_deaf = true;
305 sendmsg->payload.userState->self_deaf = true;
307 if (client_itr->self_mute) {
308 sendmsg->payload.userState->has_self_mute = true;
309 sendmsg->payload.userState->self_mute = true;
311 if (client_itr->deaf) {
312 sendmsg->payload.userState->has_deaf = true;
313 sendmsg->payload.userState->deaf = true;
315 if (client_itr->mute) {
316 sendmsg->payload.userState->has_mute = true;
317 sendmsg->payload.userState->mute = true;
319 if (client_itr->recording) {
320 sendmsg->payload.userState->has_recording = true;
321 sendmsg->payload.userState->recording = true;
323 Client_send_message(client, sendmsg);
327 sendmsg = Msg_create(ServerSync);
328 sendmsg->payload.serverSync->has_session = true;
329 sendmsg->payload.serverSync->session = client->sessionId;
330 sendmsg->payload.serverSync->welcome_text = strdup(getStrConf(WELCOMETEXT));
331 sendmsg->payload.serverSync->has_max_bandwidth = true;
332 sendmsg->payload.serverSync->max_bandwidth = getIntConf(MAX_BANDWIDTH);
333 Client_send_message(client, sendmsg);
335 /* Server config message */
336 sendmsg = Msg_create(ServerConfig);
337 sendmsg->payload.serverConfig->has_allow_html = true;
338 sendmsg->payload.serverConfig->allow_html = true; /* Support this? */
339 sendmsg->payload.serverConfig->has_message_length = true;
340 sendmsg->payload.serverConfig->message_length = MAX_TEXT; /* Hardcoded */
341 sendmsg->payload.serverConfig->has_image_message_length = true;
342 sendmsg->payload.serverConfig->image_message_length = 0; /* XXX */
343 Client_send_message(client, sendmsg);
345 Log_info_client(client, "User %s authenticated", client->username);
349 if (msg->payload.ping->has_good)
350 client->cryptState.uiRemoteGood = msg->payload.ping->good;
351 if (msg->payload.ping->has_late)
352 client->cryptState.uiRemoteLate = msg->payload.ping->late;
353 if (msg->payload.ping->has_lost)
354 client->cryptState.uiRemoteLost = msg->payload.ping->lost;
355 if (msg->payload.ping->has_resync)
356 client->cryptState.uiRemoteResync = msg->payload.ping->resync;
358 Log_debug("Ping <-: %d %d %d %d",
359 client->cryptState.uiRemoteGood, client->cryptState.uiRemoteLate,
360 client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync
363 client->UDPPingAvg = msg->payload.ping->udp_ping_avg;
364 client->UDPPingVar = msg->payload.ping->udp_ping_var;
365 client->TCPPingAvg = msg->payload.ping->tcp_ping_avg;
366 client->TCPPingVar = msg->payload.ping->tcp_ping_var;
367 client->UDPPackets = msg->payload.ping->udp_packets;
368 client->TCPPackets = msg->payload.ping->tcp_packets;
370 sendmsg = Msg_create(Ping);
372 sendmsg->payload.ping->timestamp = msg->payload.ping->timestamp;
373 sendmsg->payload.ping->has_timestamp = true;
374 sendmsg->payload.ping->good = client->cryptState.uiGood;
375 sendmsg->payload.ping->has_good = true;
376 sendmsg->payload.ping->late = client->cryptState.uiLate;
377 sendmsg->payload.ping->has_late = true;
378 sendmsg->payload.ping->lost = client->cryptState.uiLost;
379 sendmsg->payload.ping->has_lost = true;
380 sendmsg->payload.ping->resync = client->cryptState.uiResync;
381 sendmsg->payload.ping->has_resync = true;
383 Client_send_message(client, sendmsg);
384 Log_debug("Ping ->: %d %d %d %d",
385 client->cryptState.uiGood, client->cryptState.uiLate,
386 client->cryptState.uiLost, client->cryptState.uiResync);
390 Log_debug("Voice channel crypt resync requested");
391 if (!msg->payload.cryptSetup->has_client_nonce) {
392 sendmsg = Msg_create(CryptSetup);
393 sendmsg->payload.cryptSetup->has_server_nonce = true;
394 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.decrypt_iv;
395 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
396 Client_send_message(client, sendmsg);
398 memcpy(client->cryptState.decrypt_iv, msg->payload.cryptSetup->client_nonce.data, AES_BLOCK_SIZE);
399 client->cryptState.uiResync++;
404 /* Only allow state changes for for the self user unless an admin is issuing */
405 if (msg->payload.userState->has_session &&
406 msg->payload.userState->session != client->sessionId && !client->isAdmin) {
407 sendPermissionDenied(client, "Permission denied");
410 if (msg->payload.userState->has_session && msg->payload.userState->session != client->sessionId) {
411 while (Client_iterate(&target) != NULL) {
412 if (target->sessionId == msg->payload.userState->session)
415 if (target == NULL) {
416 Log_warn("Client with sessionID %d not found", msg->payload.userState->session);
421 if (msg->payload.userState->has_user_id || msg->payload.userState->has_suppress ||
422 msg->payload.userState->has_priority_speaker || msg->payload.userState->has_texture) {
423 sendPermissionDenied(client, "Not supported by uMurmur");
430 msg->payload.userState->has_session = true;
431 msg->payload.userState->session = target->sessionId;
432 msg->payload.userState->has_actor = true;
433 msg->payload.userState->actor = client->sessionId;
435 if (msg->payload.userState->has_deaf) {
436 target->deaf = msg->payload.userState->deaf;
438 msg->payload.userState->has_mute = true;
439 msg->payload.userState->mute = true;
442 if (msg->payload.userState->has_mute) {
443 target->mute = msg->payload.userState->mute;
445 msg->payload.userState->has_deaf = true;
446 msg->payload.userState->deaf = false;
447 target->deaf = false;
450 if (msg->payload.userState->has_self_deaf) {
451 client->self_deaf = msg->payload.userState->self_deaf;
452 if (client->self_deaf) {
453 msg->payload.userState->has_self_mute = true;
454 msg->payload.userState->self_mute = true;
457 if (msg->payload.userState->has_self_mute) {
458 client->self_mute = msg->payload.userState->self_mute;
459 if (!client->self_mute) {
460 msg->payload.userState->has_self_deaf = true;
461 msg->payload.userState->self_deaf = false;
462 client->self_deaf = false;
465 if (msg->payload.userState->has_recording &&
466 msg->payload.userState->recording != client->recording) {
467 client->recording = msg->payload.userState->recording;
471 message = malloc(strlen(client->username) + 32);
473 Log_fatal("Out of memory");
474 tree_id = malloc(sizeof(uint32_t));
476 Log_fatal("Out of memory");
478 sendmsg = Msg_create(TextMessage);
479 sendmsg->payload.textMessage->message = message;
480 sendmsg->payload.textMessage->n_tree_id = 1;
481 sendmsg->payload.textMessage->tree_id = tree_id;
482 if (client->recording)
483 sprintf(message, "User %s started recording", client->username);
485 sprintf(message, "User %s stopped recording", client->username);
486 Client_send_message_except_ver(NULL, sendmsg, ~0x010203);
489 if (msg->payload.userState->has_channel_id) {
491 channelJoinResult_t chjoin_rc = Chan_userJoin_id_test(msg->payload.userState->channel_id, target);
493 if (chjoin_rc != CHJOIN_OK) {
494 if (chjoin_rc == CHJOIN_WRONGPW) {
495 if (target == client && !client->isAdmin) {
496 sendPermissionDenied(client, "Wrong channel password");
499 /* Tricky one: if user hasn't the password, but is moved to the channel by admin then let
500 * the user in. Also let admin user in regardless of channel password.
501 * Take no action on other errors.
503 else if (!client->isAdmin)
509 leave_id = Chan_userJoin_id(msg->payload.userState->channel_id, target);
511 Log_debug("Removing channel ID %d", leave_id);
512 sendmsg = Msg_create(ChannelRemove);
513 sendmsg->payload.channelRemove->channel_id = leave_id;
516 if (msg->payload.userState->has_plugin_context) {
518 free(client->context);
519 client->context = malloc(msg->payload.userState->plugin_context.len);
520 if (client->context == NULL)
521 Log_fatal("Out of memory");
522 memcpy(client->context, msg->payload.userState->plugin_context.data,
523 msg->payload.userState->plugin_context.len);
525 break; /* Don't inform other users about this state */
530 Client_send_message_except(NULL, msg);
532 /* Need to send remove channel message _after_ UserState message */
534 Client_send_message_except(NULL, sendmsg);
538 if (!getBoolConf(ALLOW_TEXTMESSAGE))
540 msg->payload.textMessage->has_actor = true;
541 msg->payload.textMessage->actor = client->sessionId;
543 /* XXX - HTML is allowed and can't be turned off */
544 if (msg->payload.textMessage->n_tree_id > 0) {
545 sendPermissionDenied(client, "Tree message not supported");
549 if (msg->payload.textMessage->n_channel_id > 0) { /* To channel */
552 for (i = 0; i < msg->payload.textMessage->n_channel_id; i++) {
555 Chan_iterate(&ch_itr);
556 } while (ch_itr != NULL && ch_itr->id != msg->payload.textMessage->channel_id[i]);
557 if (ch_itr != NULL) {
559 list_iterate(itr, &ch_itr->clients) {
561 c = list_get_entry(itr, client_t, chan_node);
562 if (c != client && !c->deaf && !c->self_deaf) {
564 Client_send_message(c, msg);
565 Log_debug("Text message to session ID %d", c->sessionId);
571 if (msg->payload.textMessage->n_session > 0) { /* To user */
574 for (i = 0; i < msg->payload.textMessage->n_session; i++) {
576 while (Client_iterate(&itr) != NULL) {
579 if (itr->sessionId == msg->payload.textMessage->session[i]) {
580 if (!itr->deaf && !itr->self_deaf) {
582 Client_send_message(itr, msg);
583 Log_debug("Text message to session ID %d", itr->sessionId);
589 Log_warn("TextMessage: Session ID %d not found", msg->payload.textMessage->session[i]);
596 int i, j, count, targetId = msg->payload.voiceTarget->id;
597 struct _MumbleProto__VoiceTarget__Target *target;
599 if (!targetId || targetId >= 0x1f)
601 Voicetarget_add_id(client, targetId);
602 count = msg->payload.voiceTarget->n_targets;
605 for (i = 0; i < count; i++) {
606 target = msg->payload.voiceTarget->targets[i];
607 for (j = 0; j < target->n_session; j++)
608 Voicetarget_add_session(client, targetId, target->session[j]);
609 if (target->has_channel_id) {
610 bool_t linked = false, children = false;
611 if (target->has_links)
612 linked = target->links;
613 if (target->has_children)
614 children = target->children;
615 Voicetarget_add_channel(client, targetId, target->channel_id, linked, children);
621 Log_debug("Version message received");
622 if (msg->payload.version->has_version) {
623 client->version = msg->payload.version->version;
624 Log_debug("Client version 0x%x", client->version);
626 if (msg->payload.version->release) {
627 if (client->release) free(client->release);
628 client->release = strdup(msg->payload.version->release);
629 Log_debug("Client release %s", client->release);
631 if (msg->payload.version->os) {
632 if (client->os) free(client->os);
633 client->os = strdup(msg->payload.version->os);
634 Log_debug("Client OS %s", client->os);
636 if (msg->payload.version->os_version) {
637 if (client->os_version) free(client->os_version);
638 client->os_version = strdup(msg->payload.version->os_version);
639 Log_debug("Client OS version %s", client->os_version);
642 case PermissionQuery:
643 Msg_inc_ref(msg); /* Re-use message */
644 msg->payload.permissionQuery->has_permissions = true;
647 msg->payload.permissionQuery->permissions = PERM_ADMIN;
649 msg->payload.permissionQuery->permissions = PERM_DEFAULT;
651 if (!getBoolConf(ALLOW_TEXTMESSAGE))
652 msg->payload.permissionQuery->permissions &= ~PERM_TEXTMESSAGE;
653 if (!getBoolConf(ENABLE_BAN))
654 msg->payload.permissionQuery->permissions &= ~PERM_BAN;
656 Client_send_message(client, msg);
659 client->bUDP = false;
660 Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
664 channel_t *ch_itr, *parent, *newchan;
666 /* Don't allow any changes to existing channels */
667 if (msg->payload.channelState->has_channel_id) {
668 sendPermissionDenied(client, "Not supported by uMurmur");
671 /* Must have parent */
672 if (!msg->payload.channelState->has_parent) {
673 sendPermissionDenied(client, "Not supported by uMurmur");
677 if (msg->payload.channelState->name == NULL) {
678 sendPermissionDenied(client, "Not supported by uMurmur");
681 /* Must be temporary channel */
682 if (msg->payload.channelState->temporary != true) {
683 sendPermissionDenied(client, "Only temporary channels are supported by uMurmur");
686 /* Check channel name is OK */
687 if (strlen(msg->payload.channelState->name) > MAX_TEXT) {
688 sendPermissionDenied(client, "Channel name too long");
692 parent = Chan_fromId(msg->payload.channelState->parent);
696 while (Chan_iterate_siblings(parent, &ch_itr) != NULL) {
697 if (strcmp(ch_itr->name, msg->payload.channelState->name) == 0) {
698 sendPermissionDenied(client, "Channel already exists");
705 /* Disallow temporary channels as siblings to temporary channels */
706 if (parent->temporary) {
707 sendPermissionDenied(client, "Parent channel is temporary channel");
711 /* XXX - Murmur looks for "\\w" and sends perm denied if not found.
712 * I don't know why so I don't do that here...
715 /* Create the channel */
716 newchan = Chan_createChannel(msg->payload.channelState->name,
717 msg->payload.channelState->description);
718 newchan->temporary = true;
719 Chan_addChannel(parent, newchan);
720 msg->payload.channelState->has_channel_id = true;
721 msg->payload.channelState->channel_id = newchan->id;
723 Client_send_message_except(NULL, msg);
725 /* Join the creating user */
726 sendmsg = Msg_create(UserState);
727 sendmsg->payload.userState->has_session = true;
728 sendmsg->payload.userState->session = client->sessionId;
729 sendmsg->payload.userState->has_channel_id = true;
730 sendmsg->payload.userState->channel_id = newchan->id;
731 Client_send_message_except(NULL, sendmsg);
733 leave_id = Chan_userJoin(newchan, client);
735 Log_debug("Removing channel ID %d", leave_id);
736 sendmsg = Msg_create(ChannelRemove);
737 sendmsg->payload.channelRemove->channel_id = leave_id;
738 Client_send_message_except(NULL, sendmsg);
745 client_t *target = NULL;
746 codec_t *codec_itr = NULL;
748 bool_t details = true;
750 if (msg->payload.userStats->has_stats_only)
751 details = !msg->payload.userStats->stats_only;
753 if (!msg->payload.userStats->has_session)
754 sendPermissionDenied(client, "Not supported by uMurmur");
755 while (Client_iterate(&target) != NULL) {
756 if (!IS_AUTH(target))
758 if (target->sessionId == msg->payload.userStats->session)
761 if (!target) /* Not found */
765 * Differences from Murmur:
766 * o Ignoring certificates intentionally
767 * o Ignoring channel local determining
770 sendmsg = Msg_create(UserStats);
771 sendmsg->payload.userStats->session = msg->payload.userStats->session;
772 sendmsg->payload.userStats->from_client->has_good = true;
773 sendmsg->payload.userStats->from_client->good = target->cryptState.uiGood;
774 sendmsg->payload.userStats->from_client->has_late = true;
775 sendmsg->payload.userStats->from_client->late = target->cryptState.uiLate;
776 sendmsg->payload.userStats->from_client->has_lost = true;
777 sendmsg->payload.userStats->from_client->lost = target->cryptState.uiLost;
778 sendmsg->payload.userStats->from_client->has_resync = true;
779 sendmsg->payload.userStats->from_client->resync = target->cryptState.uiResync;
781 sendmsg->payload.userStats->from_server->has_good = true;
782 sendmsg->payload.userStats->from_server->good = target->cryptState.uiRemoteGood;
783 sendmsg->payload.userStats->from_server->has_late = true;
784 sendmsg->payload.userStats->from_server->late = target->cryptState.uiRemoteLate;
785 sendmsg->payload.userStats->from_server->has_lost = true;
786 sendmsg->payload.userStats->from_server->lost = target->cryptState.uiRemoteLost;
787 sendmsg->payload.userStats->from_server->has_resync = true;
788 sendmsg->payload.userStats->from_server->resync = target->cryptState.uiRemoteResync;
790 sendmsg->payload.userStats->has_udp_packets = true;
791 sendmsg->payload.userStats->udp_packets = target->UDPPackets;
792 sendmsg->payload.userStats->has_udp_ping_avg = true;
793 sendmsg->payload.userStats->udp_ping_avg = target->UDPPingAvg;
794 sendmsg->payload.userStats->has_udp_ping_var = true;
795 sendmsg->payload.userStats->udp_ping_var = target->UDPPingVar;
797 sendmsg->payload.userStats->has_tcp_ping_avg = true;
798 sendmsg->payload.userStats->tcp_ping_avg = target->TCPPingAvg;
799 sendmsg->payload.userStats->has_tcp_ping_var = true;
800 sendmsg->payload.userStats->tcp_ping_var = target->TCPPingVar;
801 sendmsg->payload.userStats->has_tcp_packets = true;
802 sendmsg->payload.userStats->tcp_packets = target->TCPPackets;
806 sendmsg->payload.userStats->version->has_version = true;
807 sendmsg->payload.userStats->version->version = target->version;
808 sendmsg->payload.userStats->version->release = strdup(target->release);
809 sendmsg->payload.userStats->version->os = strdup(target->os);
810 sendmsg->payload.userStats->version->os_version = strdup(target->os_version);
812 sendmsg->payload.userStats->n_celt_versions = target->codec_count;
813 sendmsg->payload.userStats->celt_versions = malloc(sizeof(int32_t) * target->codec_count);
814 if (!sendmsg->payload.userStats->celt_versions)
815 Log_fatal("Out of memory");
817 while (Client_codec_iterate(target, &codec_itr) != NULL)
818 sendmsg->payload.userStats->celt_versions[i++] = codec_itr->codec;
820 sendmsg->payload.userStats->opus = target->bOpus;
823 sendmsg->payload.userStats->has_address = true;
824 sendmsg->payload.userStats->address.data = malloc(sizeof(uint8_t) * 16);
825 if (!sendmsg->payload.userStats->address.data)
826 Log_fatal("Out of memory");
827 memset(sendmsg->payload.userStats->address.data, 0, 16);
828 /* ipv4 representation as ipv6 address. Supposedly correct. */
829 memcpy(&sendmsg->payload.userStats->address.data[12], &target->remote_tcp.sin_addr, 4);
830 memset(&sendmsg->payload.userStats->address.data[10], 0xff, 2); /* IPv4 */
831 sendmsg->payload.userStats->address.len = 16;
834 sendmsg->payload.userStats->has_bandwidth = true;
835 sendmsg->payload.userStats->bandwidth = target->availableBandwidth;
838 sendmsg->payload.userStats->has_onlinesecs = true;
839 sendmsg->payload.userStats->onlinesecs = Timer_elapsed(&target->connectTime) / 1000000LL;
841 sendmsg->payload.userStats->has_idlesecs = true;
842 sendmsg->payload.userStats->idlesecs = Timer_elapsed(&target->idleTime) / 1000000LL;
843 Client_send_message(client, sendmsg);
848 /* Only admin can issue this */
849 if (!client->isAdmin) {
850 sendPermissionDenied(client, "Permission denied");
853 while (Client_iterate(&target) != NULL) {
854 if (target->sessionId == msg->payload.userRemove->session)
857 if (target == NULL) {
858 Log_warn("Client with sessionId %d not found", msg->payload.userRemove->session);
861 msg->payload.userRemove->session = target->sessionId;
862 msg->payload.userRemove->has_actor = true;
863 msg->payload.userRemove->actor = client->sessionId;
865 if (msg->payload.userRemove->has_ban && msg->payload.userRemove->ban) {
866 if (!getBoolConf(ENABLE_BAN))
867 sendPermissionDenied(client, "Permission denied");
869 Ban_UserBan(target, msg->payload.userRemove->reason);
871 Log_info_client(target, "User kicked. Reason: '%s'",
872 strlen(msg->payload.userRemove->reason) == 0 ? "N/A" : msg->payload.userRemove->reason);
877 Client_send_message_except(NULL, msg);
878 Client_close(target);
881 /* Only admin can issue this */
882 if (!client->isAdmin) {
883 sendPermissionDenied(client, "Permission denied");
886 if (!getBoolConf(ENABLE_BAN)) {
887 sendPermissionDenied(client, "Permission denied");
890 if (msg->payload.banList->has_query && msg->payload.banList->query) {
891 /* Create banlist message and add banentrys */
892 sendmsg = Ban_getBanList();
893 Client_send_message(client, sendmsg);
895 /* Clear banlist and set the new one */
897 Ban_putBanList(msg, msg->payload.banList->n_bans);
901 /* Permission denied for all these messages. Not implemented. */
904 case ContextActionAdd:
908 sendPermissionDenied(client, "Not supported by uMurmur");
912 Log_warn("Message %d not handled", msg->messageType);
921 Client_close(client);