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;
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;
231 recheckCodecVersions();
233 sendmsg = Msg_create(CodecVersion);
234 sendmsg->payload.codecVersion->alpha = iCodecAlpha;
235 sendmsg->payload.codecVersion->beta = iCodecBeta;
236 sendmsg->payload.codecVersion->prefer_alpha = bPreferAlpha;
237 Client_send_message(client, sendmsg);
239 /* Iterate channels and send channel info */
241 while (Chan_iterate(&ch_itr) != NULL) {
242 sendmsg = Msg_create(ChannelState);
243 sendmsg->payload.channelState->has_channel_id = true;
244 sendmsg->payload.channelState->channel_id = ch_itr->id;
245 if (ch_itr->id != 0) {
246 sendmsg->payload.channelState->has_parent = true;
247 sendmsg->payload.channelState->parent = ch_itr->parent->id;
249 sendmsg->payload.channelState->name = strdup(ch_itr->name);
251 sendmsg->payload.channelState->description = strdup(ch_itr->desc);
252 Log_debug("Send channel info: %s", sendmsg->payload.channelState->name);
253 Client_send_message(client, sendmsg);
256 /* Iterate channels and send channel links info */
258 while (Chan_iterate(&ch_itr) != NULL) {
259 if (ch_itr->linkcount > 0) { /* Has links */
264 sendmsg = Msg_create(ChannelState);
265 sendmsg->payload.channelState->has_channel_id = true;
266 sendmsg->payload.channelState->channel_id = ch_itr->id;
267 sendmsg->payload.channelState->n_links = ch_itr->linkcount;
269 links = (uint32_t *)malloc(ch_itr->linkcount * sizeof(uint32_t));
270 list_iterate(itr, &ch_itr->channel_links) { /* Iterate links */
272 ch = list_get_entry(itr, channel_t, link_node);
275 sendmsg->payload.channelState->links = links;
276 Client_send_message(client, sendmsg);
280 /* Send user state for connecting user to other users */
281 sendmsg = Msg_create(UserState);
282 sendmsg->payload.userState->has_session = true;
283 sendmsg->payload.userState->session = client->sessionId;
284 sendmsg->payload.userState->name = strdup(client->username);
285 sendmsg->payload.userState->has_channel_id = true;
286 sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
288 Client_send_message_except(client, sendmsg);
291 while (Client_iterate(&client_itr) != NULL) {
292 if (!IS_AUTH(client_itr))
294 sendmsg = Msg_create(UserState);
295 sendmsg->payload.userState->has_session = true;
296 sendmsg->payload.userState->session = client_itr->sessionId;
297 sendmsg->payload.userState->name = strdup(client_itr->username);
298 sendmsg->payload.userState->has_channel_id = true;
299 sendmsg->payload.userState->channel_id = ((channel_t *)client_itr->channel)->id;
301 /* Only self_mute/deaf supported */
302 if (client_itr->deaf) {
303 sendmsg->payload.userState->has_self_deaf = true;
304 sendmsg->payload.userState->self_deaf = true;
306 if (client_itr->mute) {
307 sendmsg->payload.userState->has_self_mute = true;
308 sendmsg->payload.userState->self_mute = true;
310 if (client_itr->recording) {
311 sendmsg->payload.userState->has_recording = true;
312 sendmsg->payload.userState->recording = true;
314 Client_send_message(client, sendmsg);
318 sendmsg = Msg_create(ServerSync);
319 sendmsg->payload.serverSync->has_session = true;
320 sendmsg->payload.serverSync->session = client->sessionId;
321 sendmsg->payload.serverSync->welcome_text = strdup(getStrConf(WELCOMETEXT));
322 sendmsg->payload.serverSync->has_max_bandwidth = true;
323 sendmsg->payload.serverSync->max_bandwidth = getIntConf(MAX_BANDWIDTH);
324 Client_send_message(client, sendmsg);
326 /* Server config message */
327 sendmsg = Msg_create(ServerConfig);
328 sendmsg->payload.serverConfig->has_allow_html = true;
329 sendmsg->payload.serverConfig->allow_html = true; /* Support this? */
330 sendmsg->payload.serverConfig->has_message_length = true;
331 sendmsg->payload.serverConfig->message_length = MAX_TEXT; /* Hardcoded */
332 sendmsg->payload.serverConfig->has_image_message_length = true;
333 sendmsg->payload.serverConfig->image_message_length = 0; /* XXX */
334 Client_send_message(client, sendmsg);
336 Log_info_client(client, "User %s authenticated", client->username);
340 if (msg->payload.ping->has_good)
341 client->cryptState.uiRemoteGood = msg->payload.ping->good;
342 if (msg->payload.ping->has_late)
343 client->cryptState.uiRemoteLate = msg->payload.ping->late;
344 if (msg->payload.ping->has_lost)
345 client->cryptState.uiRemoteLost = msg->payload.ping->lost;
346 if (msg->payload.ping->has_resync)
347 client->cryptState.uiRemoteResync = msg->payload.ping->resync;
349 Log_debug("Ping <-: %d %d %d %d",
350 client->cryptState.uiRemoteGood, client->cryptState.uiRemoteLate,
351 client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync
354 client->UDPPingAvg = msg->payload.ping->udp_ping_avg;
355 client->UDPPingVar = msg->payload.ping->udp_ping_var;
356 client->TCPPingAvg = msg->payload.ping->tcp_ping_avg;
357 client->TCPPingVar = msg->payload.ping->tcp_ping_var;
358 client->UDPPackets = msg->payload.ping->udp_packets;
359 client->TCPPackets = msg->payload.ping->tcp_packets;
361 sendmsg = Msg_create(Ping);
363 sendmsg->payload.ping->timestamp = msg->payload.ping->timestamp;
364 sendmsg->payload.ping->has_timestamp = true;
365 sendmsg->payload.ping->good = client->cryptState.uiGood;
366 sendmsg->payload.ping->has_good = true;
367 sendmsg->payload.ping->late = client->cryptState.uiLate;
368 sendmsg->payload.ping->has_late = true;
369 sendmsg->payload.ping->lost = client->cryptState.uiLost;
370 sendmsg->payload.ping->has_lost = true;
371 sendmsg->payload.ping->resync = client->cryptState.uiResync;
372 sendmsg->payload.ping->has_resync = true;
374 Client_send_message(client, sendmsg);
375 Log_debug("Ping ->: %d %d %d %d",
376 client->cryptState.uiGood, client->cryptState.uiLate,
377 client->cryptState.uiLost, client->cryptState.uiResync);
381 Log_debug("Voice channel crypt resync requested");
382 if (!msg->payload.cryptSetup->has_client_nonce) {
383 sendmsg = Msg_create(CryptSetup);
384 sendmsg->payload.cryptSetup->has_server_nonce = true;
385 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.decrypt_iv;
386 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
387 Client_send_message(client, sendmsg);
389 memcpy(client->cryptState.decrypt_iv, msg->payload.cryptSetup->client_nonce.data, AES_BLOCK_SIZE);
390 client->cryptState.uiResync++;
395 /* Only allow state changes for for the self user unless an admin is issuing */
396 if (msg->payload.userState->has_session &&
397 msg->payload.userState->session != client->sessionId && !client->isAdmin) {
398 sendPermissionDenied(client, "Permission denied");
401 if (msg->payload.userState->has_session && msg->payload.userState->session != client->sessionId) {
402 while (Client_iterate(&target) != NULL) {
403 if (target->sessionId == msg->payload.userState->session)
406 if (target == NULL) {
407 Log_warn("Client with sessionID %d not found", msg->payload.userState->session);
412 if (msg->payload.userState->has_user_id || msg->payload.userState->has_suppress ||
413 msg->payload.userState->has_priority_speaker || msg->payload.userState->has_texture) {
414 sendPermissionDenied(client, "Not supported by uMurmur");
421 msg->payload.userState->has_session = true;
422 msg->payload.userState->session = target->sessionId;
423 msg->payload.userState->has_actor = true;
424 msg->payload.userState->actor = client->sessionId;
426 if (msg->payload.userState->has_deaf) {
427 target->deaf = msg->payload.userState->deaf;
429 msg->payload.userState->has_mute = true;
430 msg->payload.userState->mute = true;
433 if (msg->payload.userState->has_mute) {
434 target->mute = msg->payload.userState->mute;
436 msg->payload.userState->has_deaf = true;
437 msg->payload.userState->deaf = false;
438 client->deaf = false;
441 if (msg->payload.userState->has_self_deaf) {
442 client->deaf = msg->payload.userState->self_deaf;
444 if (msg->payload.userState->has_self_mute) {
445 client->mute = msg->payload.userState->self_mute;
447 msg->payload.userState->has_self_deaf = true;
448 msg->payload.userState->self_deaf = false;
449 client->deaf = false;
452 if (msg->payload.userState->has_recording &&
453 msg->payload.userState->recording != client->recording) {
454 client->recording = msg->payload.userState->recording;
458 message = malloc(strlen(client->username) + 32);
460 Log_fatal("Out of memory");
461 tree_id = malloc(sizeof(uint32_t));
463 Log_fatal("Out of memory");
465 sendmsg = Msg_create(TextMessage);
466 sendmsg->payload.textMessage->message = message;
467 sendmsg->payload.textMessage->n_tree_id = 1;
468 sendmsg->payload.textMessage->tree_id = tree_id;
469 if (client->recording)
470 sprintf(message, "User %s started recording", client->username);
472 sprintf(message, "User %s stopped recording", client->username);
473 Client_send_message_except_ver(NULL, sendmsg, ~0x010203);
476 if (msg->payload.userState->has_channel_id) {
478 channelJoinResult_t chjoin_rc = Chan_userJoin_id_test(msg->payload.userState->channel_id, client);
480 if (chjoin_rc != CHJOIN_OK) {
481 if (chjoin_rc == CHJOIN_WRONGPW) {
482 sendPermissionDenied(client, "Wrong channel password");
487 leave_id = Chan_userJoin_id(msg->payload.userState->channel_id, client);
489 Log_debug("Removing channel ID %d", leave_id);
490 sendmsg = Msg_create(ChannelRemove);
491 sendmsg->payload.channelRemove->channel_id = leave_id;
494 if (msg->payload.userState->has_plugin_context) {
496 free(client->context);
497 client->context = malloc(msg->payload.userState->plugin_context.len);
498 if (client->context == NULL)
499 Log_fatal("Out of memory");
500 memcpy(client->context, msg->payload.userState->plugin_context.data,
501 msg->payload.userState->plugin_context.len);
503 break; /* Don't inform other users about this state */
508 Client_send_message_except(NULL, msg);
510 /* Need to send remove channel message _after_ UserState message */
512 Client_send_message_except(NULL, sendmsg);
516 if (!getBoolConf(ALLOW_TEXTMESSAGE))
518 msg->payload.textMessage->has_actor = true;
519 msg->payload.textMessage->actor = client->sessionId;
521 /* XXX - HTML is allowed and can't be turned off */
522 if (msg->payload.textMessage->n_tree_id > 0) {
523 sendPermissionDenied(client, "Tree message not supported");
527 if (msg->payload.textMessage->n_channel_id > 0) { /* To channel */
530 for (i = 0; i < msg->payload.textMessage->n_channel_id; i++) {
533 Chan_iterate(&ch_itr);
534 } while (ch_itr != NULL && ch_itr->id != msg->payload.textMessage->channel_id[i]);
535 if (ch_itr != NULL) {
537 list_iterate(itr, &ch_itr->clients) {
539 c = list_get_entry(itr, client_t, chan_node);
540 if (c != client && !c->deaf) {
542 Client_send_message(c, msg);
543 Log_debug("Text message to session ID %d", c->sessionId);
549 if (msg->payload.textMessage->n_session > 0) { /* To user */
552 for (i = 0; i < msg->payload.textMessage->n_session; i++) {
554 while (Client_iterate(&itr) != NULL) {
557 if (itr->sessionId == msg->payload.textMessage->session[i]) {
560 Client_send_message(itr, msg);
561 Log_debug("Text message to session ID %d", itr->sessionId);
567 Log_warn("TextMessage: Session ID %d not found", msg->payload.textMessage->session[i]);
574 int i, j, count, targetId = msg->payload.voiceTarget->id;
575 struct _MumbleProto__VoiceTarget__Target *target;
577 if (!targetId || targetId >= 0x1f)
579 Voicetarget_add_id(client, targetId);
580 count = msg->payload.voiceTarget->n_targets;
583 for (i = 0; i < count; i++) {
584 target = msg->payload.voiceTarget->targets[i];
585 for (j = 0; j < target->n_session; j++)
586 Voicetarget_add_session(client, targetId, target->session[j]);
587 if (target->has_channel_id) {
588 bool_t linked = false, children = false;
589 if (target->has_links)
590 linked = target->links;
591 if (target->has_children)
592 children = target->children;
593 Voicetarget_add_channel(client, targetId, target->channel_id, linked, children);
599 Log_debug("Version message received");
600 if (msg->payload.version->has_version) {
601 client->version = msg->payload.version->version;
602 Log_debug("Client version 0x%x", client->version);
604 if (msg->payload.version->release) {
605 if (client->release) free(client->release);
606 client->release = strdup(msg->payload.version->release);
607 Log_debug("Client release %s", client->release);
609 if (msg->payload.version->os) {
610 if (client->os) free(client->os);
611 client->os = strdup(msg->payload.version->os);
612 Log_debug("Client OS %s", client->os);
614 if (msg->payload.version->os_version) {
615 if (client->os_version) free(client->os_version);
616 client->os_version = strdup(msg->payload.version->os_version);
617 Log_debug("Client OS version %s", client->os_version);
620 case PermissionQuery:
621 Msg_inc_ref(msg); /* Re-use message */
622 msg->payload.permissionQuery->has_permissions = true;
625 msg->payload.permissionQuery->permissions = PERM_ADMIN;
627 msg->payload.permissionQuery->permissions = PERM_DEFAULT;
629 if (!getBoolConf(ALLOW_TEXTMESSAGE))
630 msg->payload.permissionQuery->permissions &= ~PERM_TEXTMESSAGE;
631 if (!getBoolConf(ENABLE_BAN))
632 msg->payload.permissionQuery->permissions &= ~PERM_BAN;
634 Client_send_message(client, msg);
637 client->bUDP = false;
638 Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
642 channel_t *ch_itr, *parent, *newchan;
644 /* Don't allow any changes to existing channels */
645 if (msg->payload.channelState->has_channel_id) {
646 sendPermissionDenied(client, "Not supported by uMurmur");
649 /* Must have parent */
650 if (!msg->payload.channelState->has_parent) {
651 sendPermissionDenied(client, "Not supported by uMurmur");
655 if (msg->payload.channelState->name == NULL) {
656 sendPermissionDenied(client, "Not supported by uMurmur");
659 /* Must be temporary channel */
660 if (msg->payload.channelState->temporary != true) {
661 sendPermissionDenied(client, "Only temporary channels are supported by uMurmur");
664 /* Check channel name is OK */
665 if (strlen(msg->payload.channelState->name) > MAX_TEXT) {
666 sendPermissionDenied(client, "Channel name too long");
670 parent = Chan_fromId(msg->payload.channelState->parent);
674 while (Chan_iterate_siblings(parent, &ch_itr) != NULL) {
675 if (strcmp(ch_itr->name, msg->payload.channelState->name) == 0) {
676 sendPermissionDenied(client, "Channel already exists");
683 /* Disallow temporary channels as siblings to temporary channels */
684 if (parent->temporary) {
685 sendPermissionDenied(client, "Parent channel is temporary channel");
689 /* XXX - Murmur looks for "\\w" and sends perm denied if not found.
690 * I don't know why so I don't do that here...
693 /* Create the channel */
694 newchan = Chan_createChannel(msg->payload.channelState->name,
695 msg->payload.channelState->description);
696 newchan->temporary = true;
697 Chan_addChannel(parent, newchan);
698 msg->payload.channelState->has_channel_id = true;
699 msg->payload.channelState->channel_id = newchan->id;
701 Client_send_message_except(NULL, msg);
703 /* Join the creating user */
704 sendmsg = Msg_create(UserState);
705 sendmsg->payload.userState->has_session = true;
706 sendmsg->payload.userState->session = client->sessionId;
707 sendmsg->payload.userState->has_channel_id = true;
708 sendmsg->payload.userState->channel_id = newchan->id;
709 Client_send_message_except(NULL, sendmsg);
711 leave_id = Chan_userJoin(newchan, client);
713 Log_debug("Removing channel ID %d", leave_id);
714 sendmsg = Msg_create(ChannelRemove);
715 sendmsg->payload.channelRemove->channel_id = leave_id;
716 Client_send_message_except(NULL, sendmsg);
723 client_t *target = NULL;
724 codec_t *codec_itr = NULL;
726 bool_t details = true;
728 if (msg->payload.userStats->has_stats_only)
729 details = !msg->payload.userStats->stats_only;
731 if (!msg->payload.userStats->has_session)
732 sendPermissionDenied(client, "Not supported by uMurmur");
733 while (Client_iterate(&target) != NULL) {
734 if (!IS_AUTH(target))
736 if (target->sessionId == msg->payload.userStats->session)
739 if (!target) /* Not found */
743 * Differences from Murmur:
744 * o Ignoring certificates intentionally
745 * o Ignoring channel local determining
748 sendmsg = Msg_create(UserStats);
749 sendmsg->payload.userStats->session = msg->payload.userStats->session;
750 sendmsg->payload.userStats->from_client->has_good = true;
751 sendmsg->payload.userStats->from_client->good = target->cryptState.uiGood;
752 sendmsg->payload.userStats->from_client->has_late = true;
753 sendmsg->payload.userStats->from_client->late = target->cryptState.uiLate;
754 sendmsg->payload.userStats->from_client->has_lost = true;
755 sendmsg->payload.userStats->from_client->lost = target->cryptState.uiLost;
756 sendmsg->payload.userStats->from_client->has_resync = true;
757 sendmsg->payload.userStats->from_client->resync = target->cryptState.uiResync;
759 sendmsg->payload.userStats->from_server->has_good = true;
760 sendmsg->payload.userStats->from_server->good = target->cryptState.uiRemoteGood;
761 sendmsg->payload.userStats->from_server->has_late = true;
762 sendmsg->payload.userStats->from_server->late = target->cryptState.uiRemoteLate;
763 sendmsg->payload.userStats->from_server->has_lost = true;
764 sendmsg->payload.userStats->from_server->lost = target->cryptState.uiRemoteLost;
765 sendmsg->payload.userStats->from_server->has_resync = true;
766 sendmsg->payload.userStats->from_server->resync = target->cryptState.uiRemoteResync;
768 sendmsg->payload.userStats->has_udp_packets = true;
769 sendmsg->payload.userStats->udp_packets = target->UDPPackets;
770 sendmsg->payload.userStats->has_udp_ping_avg = true;
771 sendmsg->payload.userStats->udp_ping_avg = target->UDPPingAvg;
772 sendmsg->payload.userStats->has_udp_ping_var = true;
773 sendmsg->payload.userStats->udp_ping_var = target->UDPPingVar;
775 sendmsg->payload.userStats->has_tcp_ping_avg = true;
776 sendmsg->payload.userStats->tcp_ping_avg = target->TCPPingAvg;
777 sendmsg->payload.userStats->has_tcp_ping_var = true;
778 sendmsg->payload.userStats->tcp_ping_var = target->TCPPingVar;
779 sendmsg->payload.userStats->has_tcp_packets = true;
780 sendmsg->payload.userStats->tcp_packets = target->TCPPackets;
784 sendmsg->payload.userStats->version->has_version = true;
785 sendmsg->payload.userStats->version->version = target->version;
786 sendmsg->payload.userStats->version->release = strdup(target->release);
787 sendmsg->payload.userStats->version->os = strdup(target->os);
788 sendmsg->payload.userStats->version->os_version = strdup(target->os_version);
790 sendmsg->payload.userStats->n_celt_versions = target->codec_count;
791 sendmsg->payload.userStats->celt_versions = malloc(sizeof(int32_t) * target->codec_count);
792 if (!sendmsg->payload.userStats->celt_versions)
793 Log_fatal("Out of memory");
795 while (Client_codec_iterate(target, &codec_itr) != NULL)
796 sendmsg->payload.userStats->celt_versions[i++] = codec_itr->codec;
799 sendmsg->payload.userStats->has_address = true;
800 sendmsg->payload.userStats->address.data = malloc(sizeof(uint8_t) * 16);
801 if (!sendmsg->payload.userStats->address.data)
802 Log_fatal("Out of memory");
803 memset(sendmsg->payload.userStats->address.data, 0, 16);
804 /* ipv4 representation as ipv6 address. Supposedly correct. */
805 memcpy(&sendmsg->payload.userStats->address.data[12], &target->remote_tcp.sin_addr, 4);
806 memset(&sendmsg->payload.userStats->address.data[10], 0xff, 2); /* IPv4 */
807 sendmsg->payload.userStats->address.len = 16;
810 sendmsg->payload.userStats->has_bandwidth = true;
811 sendmsg->payload.userStats->bandwidth = target->availableBandwidth;
814 sendmsg->payload.userStats->has_onlinesecs = true;
815 sendmsg->payload.userStats->onlinesecs = Timer_elapsed(&target->connectTime) / 1000000LL;
817 sendmsg->payload.userStats->has_idlesecs = true;
818 sendmsg->payload.userStats->idlesecs = Timer_elapsed(&target->idleTime) / 1000000LL;
819 Client_send_message(client, sendmsg);
824 /* Only admin can issue this */
825 if (!client->isAdmin) {
826 sendPermissionDenied(client, "Permission denied");
829 while (Client_iterate(&target) != NULL) {
830 if (target->sessionId == msg->payload.userRemove->session)
833 if (target == NULL) {
834 Log_warn("Client with sessionId %d not found", msg->payload.userRemove->session);
837 msg->payload.userRemove->session = target->sessionId;
838 msg->payload.userRemove->has_actor = true;
839 msg->payload.userRemove->actor = client->sessionId;
841 if (msg->payload.userRemove->has_ban && msg->payload.userRemove->ban) {
842 if (!getBoolConf(ENABLE_BAN))
843 sendPermissionDenied(client, "Permission denied");
845 Ban_UserBan(target, msg->payload.userRemove->reason);
847 Log_info_client(target, "User kicked. Reason: '%s'",
848 strlen(msg->payload.userRemove->reason) == 0 ? "N/A" : msg->payload.userRemove->reason);
853 Client_send_message_except(NULL, msg);
854 Client_close(target);
857 /* Only admin can issue this */
858 if (!client->isAdmin) {
859 sendPermissionDenied(client, "Permission denied");
862 if (!getBoolConf(ENABLE_BAN)) {
863 sendPermissionDenied(client, "Permission denied");
866 if (msg->payload.banList->has_query && msg->payload.banList->query) {
867 /* Create banlist message and add banentrys */
868 sendmsg = Ban_getBanList();
869 Client_send_message(client, sendmsg);
871 /* Clear banlist and set the new one */
873 Ban_putBanList(msg, msg->payload.banList->n_bans);
877 /* Permission denied for all these messages. Not implemented. */
880 case ContextActionAdd:
884 sendPermissionDenied(client, "Not supported by uMurmur");
888 Log_warn("Message %d not handled", msg->messageType);
897 Client_close(client);