1 /* Copyright (C) 2009-2011, Martin Johansson <martin@fatbob.nu>
2 Copyright (C) 2005-2011, 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"
45 #define MAX_USERNAME 128
47 extern channel_t *defaultChan;
48 extern int iCodecAlpha, iCodecBeta;
49 extern bool_t bPreferAlpha;
51 static void sendServerReject(client_t *client, const char *reason, MumbleProto__Reject__RejectType type)
53 message_t *msg = Msg_create(Reject);
54 msg->payload.reject->reason = strdup(reason);
55 msg->payload.reject->type = type;
56 msg->payload.reject->has_type = true;
57 Client_send_message(client, msg);
59 Log_info_client(client, "Server reject reason: %s", reason);
62 static void sendPermissionDenied(client_t *client, const char *reason)
64 message_t *msg = Msg_create(PermissionDenied);
65 msg->payload.permissionDenied->has_type = true;
66 msg->payload.permissionDenied->type = MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__Text;
67 msg->payload.permissionDenied->reason = strdup(reason);
68 Client_send_message(client, msg);
71 static void addTokens(client_t *client, message_t *msg)
74 if (client->tokencount + msg->payload.authenticate->n_tokens < MAX_TOKENS) {
75 /* Check lengths first */
76 for (i = 0; i < msg->payload.authenticate->n_tokens; i++) {
77 if (strlen(msg->payload.authenticate->tokens[i]) > MAX_TOKENSIZE - 1) {
78 sendPermissionDenied(client, "Too long token");
83 for (i = 0; i < msg->payload.authenticate->n_tokens; i++) {
84 Log_debug("Adding token '%s' to client '%s'", msg->payload.authenticate->tokens[i], client->username);
85 Client_token_add(client, msg->payload.authenticate->tokens[i]);
89 sendPermissionDenied(client, "Too many tokens");
92 void Mh_handle_message(client_t *client, message_t *msg)
94 message_t *sendmsg = NULL;
95 channel_t *ch_itr = NULL;
96 client_t *client_itr, *target;
98 if (!client->authenticated && !(msg->messageType == Authenticate ||
99 msg->messageType == Version)) {
103 switch (msg->messageType) {
109 case PermissionQuery:
112 Timer_restart(&client->idleTime);
115 switch (msg->messageType) {
117 Log_debug("Authenticate message received");
119 if (IS_AUTH(client) || !msg->payload.authenticate->username) {
120 /* Authenticate message might be sent when a tokens are changed by the user.*/
121 Client_token_free(client); /* Clear the token list */
122 if (msg->payload.authenticate->n_tokens > 0) {
123 Log_debug("Tokens in auth message from '%s'. n_tokens = %d", client->username,
124 msg->payload.authenticate->n_tokens);
125 addTokens(client, msg);
130 SSLi_getSHA1Hash(client->ssl, client->hash);
131 if (Ban_isBanned(client))
134 client->authenticated = true;
137 while (Client_iterate(&client_itr) != NULL) {
138 if (!IS_AUTH(client_itr))
140 if (client_itr->username && strncmp(client_itr->username, msg->payload.authenticate->username, MAX_USERNAME) == 0) {
142 sprintf(buf, "Username already in use");
143 Log_debug("Username already in use");
144 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__UsernameInUse);
148 if (strlen(getStrConf(PASSPHRASE)) > 0) {
149 if (!msg->payload.authenticate->password ||
150 (msg->payload.authenticate->password &&
151 strncmp(getStrConf(PASSPHRASE), msg->payload.authenticate->password, MAX_TEXT) != 0)) {
153 sprintf(buf, "Wrong server password");
154 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__WrongServerPW);
155 Log_debug("Wrong server password: '%s'", msg->payload.authenticate->password != NULL ?
156 msg->payload.authenticate->password : "(null)");
160 if (strlen(msg->payload.authenticate->username) == 0 ||
161 strlen(msg->payload.authenticate->username) >= MAX_USERNAME) { /* XXX - other invalid names? */
163 sprintf(buf, "Invalid username");
164 Log_debug("Invalid username");
165 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__InvalidUsername);
169 if (Client_count() >= getIntConf(MAX_CLIENTS)) {
171 snprintf(buf, 64, "Server is full (max %d users)", getIntConf(MAX_CLIENTS));
172 sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__ServerFull);
177 client->username = strdup(msg->payload.authenticate->username);
180 if (msg->payload.authenticate->n_tokens > 0)
181 addTokens(client, msg);
183 /* Check if admin PW among tokens */
184 if (strlen(getStrConf(ADMIN_PASSPHRASE)) > 0 &&
185 Client_token_match(client, getStrConf(ADMIN_PASSPHRASE))) {
186 client->isAdmin = true;
187 Log_info("User is admin");
190 /* Setup UDP encryption */
191 CryptState_init(&client->cryptState);
192 CryptState_genKey(&client->cryptState);
193 sendmsg = Msg_create(CryptSetup);
194 sendmsg->payload.cryptSetup->has_key = true;
195 sendmsg->payload.cryptSetup->key.data = client->cryptState.raw_key;
196 sendmsg->payload.cryptSetup->key.len = AES_BLOCK_SIZE;
197 sendmsg->payload.cryptSetup->has_server_nonce = true;
198 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.encrypt_iv;
199 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
200 sendmsg->payload.cryptSetup->has_client_nonce = true;
201 sendmsg->payload.cryptSetup->client_nonce.data = client->cryptState.decrypt_iv;
202 sendmsg->payload.cryptSetup->client_nonce.len = AES_BLOCK_SIZE;
203 Client_send_message(client, sendmsg);
206 Chan_userJoin(defaultChan, client); /* Join default channel */
209 Log_debug("Client %d has %d CELT codecs", client->sessionId,
210 msg->payload.authenticate->n_celt_versions);
211 if (msg->payload.authenticate->n_celt_versions > 0) {
214 client->codec_count = msg->payload.authenticate->n_celt_versions;
216 for (i = 0; i < client->codec_count; i++)
217 Client_codec_add(client, msg->payload.authenticate->celt_versions[i]);
219 while (Client_codec_iterate(client, &codec_itr) != NULL)
220 Log_debug("Client %d CELT codec ver 0x%x", client->sessionId, codec_itr->codec);
223 Client_codec_add(client, (int32_t)0x8000000a);
224 client->codec_count = 1;
227 recheckCodecVersions();
229 sendmsg = Msg_create(CodecVersion);
230 sendmsg->payload.codecVersion->alpha = iCodecAlpha;
231 sendmsg->payload.codecVersion->beta = iCodecBeta;
232 sendmsg->payload.codecVersion->prefer_alpha = bPreferAlpha;
233 Client_send_message(client, sendmsg);
235 /* Iterate channels and send channel info */
237 while (Chan_iterate(&ch_itr) != NULL) {
238 sendmsg = Msg_create(ChannelState);
239 sendmsg->payload.channelState->has_channel_id = true;
240 sendmsg->payload.channelState->channel_id = ch_itr->id;
241 if (ch_itr->id != 0) {
242 sendmsg->payload.channelState->has_parent = true;
243 sendmsg->payload.channelState->parent = ch_itr->parent->id;
245 sendmsg->payload.channelState->name = strdup(ch_itr->name);
247 sendmsg->payload.channelState->description = strdup(ch_itr->desc);
248 Log_debug("Send channel info: %s", sendmsg->payload.channelState->name);
249 Client_send_message(client, sendmsg);
252 /* Iterate channels and send channel links info */
254 while (Chan_iterate(&ch_itr) != NULL) {
255 if (ch_itr->linkcount > 0) { /* Has links */
260 sendmsg = Msg_create(ChannelState);
261 sendmsg->payload.channelState->has_channel_id = true;
262 sendmsg->payload.channelState->channel_id = ch_itr->id;
263 sendmsg->payload.channelState->n_links = ch_itr->linkcount;
265 links = (uint32_t *)malloc(ch_itr->linkcount * sizeof(uint32_t));
266 list_iterate(itr, &ch_itr->channel_links) { /* Iterate links */
268 ch = list_get_entry(itr, channel_t, link_node);
271 sendmsg->payload.channelState->links = links;
272 Client_send_message(client, sendmsg);
276 /* Send user state for connecting user to other users */
277 sendmsg = Msg_create(UserState);
278 sendmsg->payload.userState->has_session = true;
279 sendmsg->payload.userState->session = client->sessionId;
280 sendmsg->payload.userState->name = strdup(client->username);
281 sendmsg->payload.userState->has_channel_id = true;
282 sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
284 Client_send_message_except(client, sendmsg);
287 while (Client_iterate(&client_itr) != NULL) {
288 if (!IS_AUTH(client_itr))
290 sendmsg = Msg_create(UserState);
291 sendmsg->payload.userState->has_session = true;
292 sendmsg->payload.userState->session = client_itr->sessionId;
293 sendmsg->payload.userState->name = strdup(client_itr->username);
294 sendmsg->payload.userState->has_channel_id = true;
295 sendmsg->payload.userState->channel_id = ((channel_t *)client_itr->channel)->id;
297 /* Only self_mute/deaf supported */
298 if (client_itr->deaf) {
299 sendmsg->payload.userState->has_self_deaf = true;
300 sendmsg->payload.userState->self_deaf = true;
302 if (client_itr->mute) {
303 sendmsg->payload.userState->has_self_mute = true;
304 sendmsg->payload.userState->self_mute = true;
306 if (client_itr->recording) {
307 sendmsg->payload.userState->has_recording = true;
308 sendmsg->payload.userState->recording = true;
310 Client_send_message(client, sendmsg);
314 sendmsg = Msg_create(ServerSync);
315 sendmsg->payload.serverSync->has_session = true;
316 sendmsg->payload.serverSync->session = client->sessionId;
317 sendmsg->payload.serverSync->welcome_text = strdup(getStrConf(WELCOMETEXT));
318 sendmsg->payload.serverSync->has_max_bandwidth = true;
319 sendmsg->payload.serverSync->max_bandwidth = getIntConf(MAX_BANDWIDTH);
320 Client_send_message(client, sendmsg);
322 /* Server config message */
323 sendmsg = Msg_create(ServerConfig);
324 sendmsg->payload.serverConfig->has_allow_html = true;
325 sendmsg->payload.serverConfig->allow_html = true; /* Support this? */
326 sendmsg->payload.serverConfig->has_message_length = true;
327 sendmsg->payload.serverConfig->message_length = MAX_TEXT; /* Hardcoded */
328 sendmsg->payload.serverConfig->has_image_message_length = true;
329 sendmsg->payload.serverConfig->image_message_length = 0; /* XXX */
330 Client_send_message(client, sendmsg);
332 Log_info_client(client, "User %s authenticated", client->username);
336 if (msg->payload.ping->has_good)
337 client->cryptState.uiRemoteGood = msg->payload.ping->good;
338 if (msg->payload.ping->has_late)
339 client->cryptState.uiRemoteLate = msg->payload.ping->late;
340 if (msg->payload.ping->has_lost)
341 client->cryptState.uiRemoteLost = msg->payload.ping->lost;
342 if (msg->payload.ping->has_resync)
343 client->cryptState.uiRemoteResync = msg->payload.ping->resync;
345 Log_debug("Ping <-: %d %d %d %d",
346 client->cryptState.uiRemoteGood, client->cryptState.uiRemoteLate,
347 client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync
350 client->UDPPingAvg = msg->payload.ping->udp_ping_avg;
351 client->UDPPingVar = msg->payload.ping->udp_ping_var;
352 client->TCPPingAvg = msg->payload.ping->tcp_ping_avg;
353 client->TCPPingVar = msg->payload.ping->tcp_ping_var;
354 client->UDPPackets = msg->payload.ping->udp_packets;
355 client->TCPPackets = msg->payload.ping->tcp_packets;
357 sendmsg = Msg_create(Ping);
359 sendmsg->payload.ping->timestamp = msg->payload.ping->timestamp;
360 sendmsg->payload.ping->has_timestamp = true;
361 sendmsg->payload.ping->good = client->cryptState.uiGood;
362 sendmsg->payload.ping->has_good = true;
363 sendmsg->payload.ping->late = client->cryptState.uiLate;
364 sendmsg->payload.ping->has_late = true;
365 sendmsg->payload.ping->lost = client->cryptState.uiLost;
366 sendmsg->payload.ping->has_lost = true;
367 sendmsg->payload.ping->resync = client->cryptState.uiResync;
368 sendmsg->payload.ping->has_resync = true;
370 Client_send_message(client, sendmsg);
371 Log_debug("Ping ->: %d %d %d %d",
372 client->cryptState.uiGood, client->cryptState.uiLate,
373 client->cryptState.uiLost, client->cryptState.uiResync);
377 Log_debug("Voice channel crypt resync requested");
378 if (!msg->payload.cryptSetup->has_client_nonce) {
379 sendmsg = Msg_create(CryptSetup);
380 sendmsg->payload.cryptSetup->has_server_nonce = true;
381 sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.decrypt_iv;
382 sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
383 Client_send_message(client, sendmsg);
385 memcpy(client->cryptState.decrypt_iv, msg->payload.cryptSetup->client_nonce.data, AES_BLOCK_SIZE);
386 client->cryptState.uiResync++;
391 /* Only allow state changes for for the self user unless an admin is issuing */
392 if (msg->payload.userState->has_session &&
393 msg->payload.userState->session != client->sessionId && !client->isAdmin) {
394 sendPermissionDenied(client, "Permission denied");
397 if (msg->payload.userState->has_session && msg->payload.userState->session != client->sessionId) {
398 while (Client_iterate(&target) != NULL) {
399 if (target->sessionId == msg->payload.userState->session)
402 if (target == NULL) {
403 Log_warn("Client with sessionID %d not found", msg->payload.userState->session);
408 if (msg->payload.userState->has_user_id || msg->payload.userState->has_suppress ||
409 msg->payload.userState->has_texture) {
410 sendPermissionDenied(client, "Not supported by uMurmur");
417 msg->payload.userState->has_session = true;
418 msg->payload.userState->session = target->sessionId;
419 msg->payload.userState->has_actor = true;
420 msg->payload.userState->actor = client->sessionId;
422 if (msg->payload.userState->has_deaf) {
423 target->deaf = msg->payload.userState->deaf;
425 if (msg->payload.userState->has_mute) {
426 target->mute = msg->payload.userState->mute;
428 msg->payload.userState->has_deaf = true;
429 msg->payload.userState->deaf = false;
430 client->deaf = false;
433 if (msg->payload.userState->has_self_deaf) {
434 client->deaf = msg->payload.userState->self_deaf;
436 if (msg->payload.userState->has_self_mute) {
437 client->mute = msg->payload.userState->self_mute;
439 msg->payload.userState->has_self_deaf = true;
440 msg->payload.userState->self_deaf = false;
441 client->deaf = false;
444 if (msg->payload.userState->has_recording &&
445 msg->payload.userState->recording != client->recording) {
446 client->recording = msg->payload.userState->recording;
450 message = malloc(strlen(client->username) + 32);
452 Log_fatal("Out of memory");
453 tree_id = malloc(sizeof(uint32_t));
455 Log_fatal("Out of memory");
457 sendmsg = Msg_create(TextMessage);
458 sendmsg->payload.textMessage->message = message;
459 sendmsg->payload.textMessage->n_tree_id = 1;
460 sendmsg->payload.textMessage->tree_id = tree_id;
461 if (client->recording)
462 sprintf(message, "User %s started recording", client->username);
464 sprintf(message, "User %s stopped recording", client->username);
465 Client_send_message_except_ver(NULL, sendmsg, ~0x010203);
468 if (msg->payload.userState->has_channel_id) {
470 channelJoinResult_t chjoin_rc = Chan_userJoin_id_test(msg->payload.userState->channel_id, client);
472 if (chjoin_rc != CHJOIN_OK) {
473 if (chjoin_rc == CHJOIN_WRONGPW) {
474 sendPermissionDenied(client, "Wrong channel password");
479 leave_id = Chan_userJoin_id(msg->payload.userState->channel_id, client);
481 Log_debug("Removing channel ID %d", leave_id);
482 sendmsg = Msg_create(ChannelRemove);
483 sendmsg->payload.channelRemove->channel_id = leave_id;
486 if (msg->payload.userState->has_plugin_context) {
488 free(client->context);
489 client->context = malloc(msg->payload.userState->plugin_context.len);
490 if (client->context == NULL)
491 Log_fatal("Out of memory");
492 memcpy(client->context, msg->payload.userState->plugin_context.data,
493 msg->payload.userState->plugin_context.len);
495 break; /* Don't inform other users about this state */
500 Client_send_message_except(NULL, msg);
502 /* Need to send remove channel message _after_ UserState message */
504 Client_send_message_except(NULL, sendmsg);
508 msg->payload.textMessage->has_actor = true;
509 msg->payload.textMessage->actor = client->sessionId;
511 /* XXX - HTML is allowed and can't be turned off */
512 if (msg->payload.textMessage->n_tree_id > 0) {
513 sendPermissionDenied(client, "Tree message not supported");
517 if (msg->payload.textMessage->n_channel_id > 0) { /* To channel */
520 for (i = 0; i < msg->payload.textMessage->n_channel_id; i++) {
523 Chan_iterate(&ch_itr);
524 } while (ch_itr != NULL && ch_itr->id != msg->payload.textMessage->channel_id[i]);
525 if (ch_itr != NULL) {
527 list_iterate(itr, &ch_itr->clients) {
529 c = list_get_entry(itr, client_t, chan_node);
530 if (c != client && !c->deaf) {
532 Client_send_message(c, msg);
533 Log_debug("Text message to session ID %d", c->sessionId);
539 if (msg->payload.textMessage->n_session > 0) { /* To user */
542 for (i = 0; i < msg->payload.textMessage->n_session; i++) {
544 while (Client_iterate(&itr) != NULL) {
547 if (itr->sessionId == msg->payload.textMessage->session[i]) {
550 Client_send_message(itr, msg);
551 Log_debug("Text message to session ID %d", itr->sessionId);
557 Log_warn("TextMessage: Session ID %d not found", msg->payload.textMessage->session[i]);
564 int i, j, count, targetId = msg->payload.voiceTarget->id;
565 struct _MumbleProto__VoiceTarget__Target *target;
567 if (!targetId || targetId >= 0x1f)
569 Voicetarget_add_id(client, targetId);
570 count = msg->payload.voiceTarget->n_targets;
573 for (i = 0; i < count; i++) {
574 target = msg->payload.voiceTarget->targets[i];
575 for (j = 0; j < target->n_session; j++)
576 Voicetarget_add_session(client, targetId, target->session[j]);
577 if (target->has_channel_id) {
578 bool_t linked = false, children = false;
579 if (target->has_links)
580 linked = target->links;
581 if (target->has_children)
582 children = target->children;
583 Voicetarget_add_channel(client, targetId, target->channel_id, linked, children);
589 Log_debug("Version message received");
590 if (msg->payload.version->has_version) {
591 client->version = msg->payload.version->version;
592 Log_debug("Client version 0x%x", client->version);
594 if (msg->payload.version->release) {
595 if (client->release) free(client->release);
596 client->release = strdup(msg->payload.version->release);
597 Log_debug("Client release %s", client->release);
599 if (msg->payload.version->os) {
600 if (client->os) free(client->os);
601 client->os = strdup(msg->payload.version->os);
602 Log_debug("Client OS %s", client->os);
604 if (msg->payload.version->os_version) {
605 if (client->os_version) free(client->os_version);
606 client->os_version = strdup(msg->payload.version->os_version);
607 Log_debug("Client OS version %s", client->os_version);
610 case PermissionQuery:
611 Msg_inc_ref(msg); /* Re-use message */
612 msg->payload.permissionQuery->has_permissions = true;
614 msg->payload.permissionQuery->permissions = PERM_ADMIN;
616 msg->payload.permissionQuery->permissions = PERM_DEFAULT;
618 Client_send_message(client, msg);
621 client->bUDP = false;
622 Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
626 channel_t *ch_itr, *parent, *newchan;
628 /* Don't allow any changes to existing channels */
629 if (msg->payload.channelState->has_channel_id) {
630 sendPermissionDenied(client, "Not supported by uMurmur");
633 /* Must have parent */
634 if (!msg->payload.channelState->has_parent) {
635 sendPermissionDenied(client, "Not supported by uMurmur");
639 if (msg->payload.channelState->name == NULL) {
640 sendPermissionDenied(client, "Not supported by uMurmur");
643 /* Must be temporary channel */
644 if (msg->payload.channelState->temporary != true) {
645 sendPermissionDenied(client, "Only temporary channels are supported by uMurmur");
648 /* Check channel name is OK */
649 if (strlen(msg->payload.channelState->name) > MAX_TEXT) {
650 sendPermissionDenied(client, "Channel name too long");
654 parent = Chan_fromId(msg->payload.channelState->parent);
658 while (Chan_iterate_siblings(parent, &ch_itr) != NULL) {
659 if (strcmp(ch_itr->name, msg->payload.channelState->name) == 0) {
660 sendPermissionDenied(client, "Channel already exists");
667 /* Disallow temporary channels as siblings to temporary channels */
668 if (parent->temporary) {
669 sendPermissionDenied(client, "Parent channel is temporary channel");
673 /* XXX - Murmur looks for "\\w" and sends perm denied if not found.
674 * I don't know why so I don't do that here...
677 /* Create the channel */
678 newchan = Chan_createChannel(msg->payload.channelState->name,
679 msg->payload.channelState->description);
680 newchan->temporary = true;
681 Chan_addChannel(parent, newchan);
682 msg->payload.channelState->has_channel_id = true;
683 msg->payload.channelState->channel_id = newchan->id;
685 Client_send_message_except(NULL, msg);
687 /* Join the creating user */
688 sendmsg = Msg_create(UserState);
689 sendmsg->payload.userState->has_session = true;
690 sendmsg->payload.userState->session = client->sessionId;
691 sendmsg->payload.userState->has_channel_id = true;
692 sendmsg->payload.userState->channel_id = newchan->id;
693 Client_send_message_except(NULL, sendmsg);
695 leave_id = Chan_userJoin(newchan, client);
697 Log_debug("Removing channel ID %d", leave_id);
698 sendmsg = Msg_create(ChannelRemove);
699 sendmsg->payload.channelRemove->channel_id = leave_id;
700 Client_send_message_except(NULL, sendmsg);
707 client_t *target = NULL;
708 codec_t *codec_itr = NULL;
710 bool_t details = true;
712 if (msg->payload.userStats->has_stats_only)
713 details = !msg->payload.userStats->stats_only;
715 if (!msg->payload.userStats->has_session)
716 sendPermissionDenied(client, "Not supported by uMurmur");
717 while (Client_iterate(&target) != NULL) {
718 if (!IS_AUTH(target))
720 if (target->sessionId == msg->payload.userStats->session)
723 if (!target) /* Not found */
727 * Differences from Murmur:
728 * o Ignoring certificates intentionally
729 * o Ignoring channel local determining
732 sendmsg = Msg_create(UserStats);
733 sendmsg->payload.userStats->session = msg->payload.userStats->session;
734 sendmsg->payload.userStats->from_client->has_good = true;
735 sendmsg->payload.userStats->from_client->good = target->cryptState.uiGood;
736 sendmsg->payload.userStats->from_client->has_late = true;
737 sendmsg->payload.userStats->from_client->late = target->cryptState.uiLate;
738 sendmsg->payload.userStats->from_client->has_lost = true;
739 sendmsg->payload.userStats->from_client->lost = target->cryptState.uiLost;
740 sendmsg->payload.userStats->from_client->has_resync = true;
741 sendmsg->payload.userStats->from_client->resync = target->cryptState.uiResync;
743 sendmsg->payload.userStats->from_server->has_good = true;
744 sendmsg->payload.userStats->from_server->good = target->cryptState.uiRemoteGood;
745 sendmsg->payload.userStats->from_server->has_late = true;
746 sendmsg->payload.userStats->from_server->late = target->cryptState.uiRemoteLate;
747 sendmsg->payload.userStats->from_server->has_lost = true;
748 sendmsg->payload.userStats->from_server->lost = target->cryptState.uiRemoteLost;
749 sendmsg->payload.userStats->from_server->has_resync = true;
750 sendmsg->payload.userStats->from_server->resync = target->cryptState.uiRemoteResync;
752 sendmsg->payload.userStats->has_udp_packets = true;
753 sendmsg->payload.userStats->udp_packets = target->UDPPackets;
754 sendmsg->payload.userStats->has_udp_ping_avg = true;
755 sendmsg->payload.userStats->udp_ping_avg = target->UDPPingAvg;
756 sendmsg->payload.userStats->has_udp_ping_var = true;
757 sendmsg->payload.userStats->udp_ping_var = target->UDPPingVar;
759 sendmsg->payload.userStats->has_tcp_ping_avg = true;
760 sendmsg->payload.userStats->tcp_ping_avg = target->TCPPingAvg;
761 sendmsg->payload.userStats->has_tcp_ping_var = true;
762 sendmsg->payload.userStats->tcp_ping_var = target->TCPPingVar;
763 sendmsg->payload.userStats->has_tcp_packets = true;
764 sendmsg->payload.userStats->tcp_packets = target->TCPPackets;
768 sendmsg->payload.userStats->version->has_version = true;
769 sendmsg->payload.userStats->version->version = target->version;
770 sendmsg->payload.userStats->version->release = strdup(target->release);
771 sendmsg->payload.userStats->version->os = strdup(target->os);
772 sendmsg->payload.userStats->version->os_version = strdup(target->os_version);
774 sendmsg->payload.userStats->n_celt_versions = target->codec_count;
775 sendmsg->payload.userStats->celt_versions = malloc(sizeof(int32_t) * target->codec_count);
776 if (!sendmsg->payload.userStats->celt_versions)
777 Log_fatal("Out of memory");
779 while (Client_codec_iterate(target, &codec_itr) != NULL)
780 sendmsg->payload.userStats->celt_versions[i++] = codec_itr->codec;
783 sendmsg->payload.userStats->has_address = true;
784 sendmsg->payload.userStats->address.data = malloc(sizeof(uint8_t) * 16);
785 if (!sendmsg->payload.userStats->address.data)
786 Log_fatal("Out of memory");
787 memset(sendmsg->payload.userStats->address.data, 0, 16);
788 /* ipv4 representation as ipv6 address. Supposedly correct. */
789 memcpy(&sendmsg->payload.userStats->address.data[12], &target->remote_tcp.sin_addr, 4);
790 sendmsg->payload.userStats->address.len = 16;
793 sendmsg->payload.userStats->has_bandwidth = true;
794 sendmsg->payload.userStats->bandwidth = target->availableBandwidth;
797 sendmsg->payload.userStats->has_onlinesecs = true;
798 sendmsg->payload.userStats->onlinesecs = Timer_elapsed(&target->connectTime) / 1000000LL;
800 sendmsg->payload.userStats->has_idlesecs = true;
801 sendmsg->payload.userStats->idlesecs = Timer_elapsed(&target->idleTime) / 1000000LL;
802 Client_send_message(client, sendmsg);
807 /* Only admin can issue this */
808 if (!client->isAdmin) {
809 sendPermissionDenied(client, "Permission denied");
812 while (Client_iterate(&target) != NULL) {
813 if (target->sessionId == msg->payload.userRemove->session)
816 if (target == NULL) {
817 Log_warn("Client with sessionId %d not found", msg->payload.userRemove->session);
820 msg->payload.userRemove->session = target->sessionId;
821 msg->payload.userRemove->has_actor = true;
822 msg->payload.userRemove->actor = client->sessionId;
824 if (msg->payload.userRemove->has_ban && msg->payload.userRemove->ban) {
825 Ban_UserBan(target, msg->payload.userRemove->reason);
827 Log_info("User kicked");
832 Client_send_message_except(NULL, msg);
833 Client_close(target);
836 /* Permission denied for all these messages. Not implemented. */
839 case ContextActionAdd:
844 sendPermissionDenied(client, "Not supported by uMurmur");
848 Log_warn("Message %d not handled", msg->messageType);
857 Client_close(client);