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);
127 /* Check if admin PW among tokens */
128 if (strlen(getStrConf(ADMIN_PASSPHRASE)) > 0 &&
129 Client_token_match(client, getStrConf(ADMIN_PASSPHRASE))) {
130 client->isAdmin = true;
131 Log_info("User is admin");
137 client->authenticated = true;
138 SSLi_getSHA1Hash(client->ssl, client->hash);
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("User is admin");
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_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 if (msg->payload.userState->has_mute) {
430 target->mute = msg->payload.userState->mute;
432 msg->payload.userState->has_deaf = true;
433 msg->payload.userState->deaf = false;
434 client->deaf = false;
437 if (msg->payload.userState->has_self_deaf) {
438 client->deaf = msg->payload.userState->self_deaf;
440 if (msg->payload.userState->has_self_mute) {
441 client->mute = msg->payload.userState->self_mute;
443 msg->payload.userState->has_self_deaf = true;
444 msg->payload.userState->self_deaf = false;
445 client->deaf = false;
448 if (msg->payload.userState->has_recording &&
449 msg->payload.userState->recording != client->recording) {
450 client->recording = msg->payload.userState->recording;
454 message = malloc(strlen(client->username) + 32);
456 Log_fatal("Out of memory");
457 tree_id = malloc(sizeof(uint32_t));
459 Log_fatal("Out of memory");
461 sendmsg = Msg_create(TextMessage);
462 sendmsg->payload.textMessage->message = message;
463 sendmsg->payload.textMessage->n_tree_id = 1;
464 sendmsg->payload.textMessage->tree_id = tree_id;
465 if (client->recording)
466 sprintf(message, "User %s started recording", client->username);
468 sprintf(message, "User %s stopped recording", client->username);
469 Client_send_message_except_ver(NULL, sendmsg, ~0x010203);
472 if (msg->payload.userState->has_channel_id) {
474 channelJoinResult_t chjoin_rc = Chan_userJoin_id_test(msg->payload.userState->channel_id, client);
476 if (chjoin_rc != CHJOIN_OK) {
477 if (chjoin_rc == CHJOIN_WRONGPW) {
478 sendPermissionDenied(client, "Wrong channel password");
483 leave_id = Chan_userJoin_id(msg->payload.userState->channel_id, client);
485 Log_debug("Removing channel ID %d", leave_id);
486 sendmsg = Msg_create(ChannelRemove);
487 sendmsg->payload.channelRemove->channel_id = leave_id;
490 if (msg->payload.userState->has_plugin_context) {
492 free(client->context);
493 client->context = malloc(msg->payload.userState->plugin_context.len);
494 if (client->context == NULL)
495 Log_fatal("Out of memory");
496 memcpy(client->context, msg->payload.userState->plugin_context.data,
497 msg->payload.userState->plugin_context.len);
499 break; /* Don't inform other users about this state */
504 Client_send_message_except(NULL, msg);
506 /* Need to send remove channel message _after_ UserState message */
508 Client_send_message_except(NULL, sendmsg);
512 msg->payload.textMessage->has_actor = true;
513 msg->payload.textMessage->actor = client->sessionId;
515 /* XXX - HTML is allowed and can't be turned off */
516 if (msg->payload.textMessage->n_tree_id > 0) {
517 sendPermissionDenied(client, "Tree message not supported");
521 if (msg->payload.textMessage->n_channel_id > 0) { /* To channel */
524 for (i = 0; i < msg->payload.textMessage->n_channel_id; i++) {
527 Chan_iterate(&ch_itr);
528 } while (ch_itr != NULL && ch_itr->id != msg->payload.textMessage->channel_id[i]);
529 if (ch_itr != NULL) {
531 list_iterate(itr, &ch_itr->clients) {
533 c = list_get_entry(itr, client_t, chan_node);
534 if (c != client && !c->deaf) {
536 Client_send_message(c, msg);
537 Log_debug("Text message to session ID %d", c->sessionId);
543 if (msg->payload.textMessage->n_session > 0) { /* To user */
546 for (i = 0; i < msg->payload.textMessage->n_session; i++) {
548 while (Client_iterate(&itr) != NULL) {
551 if (itr->sessionId == msg->payload.textMessage->session[i]) {
554 Client_send_message(itr, msg);
555 Log_debug("Text message to session ID %d", itr->sessionId);
561 Log_warn("TextMessage: Session ID %d not found", msg->payload.textMessage->session[i]);
568 int i, j, count, targetId = msg->payload.voiceTarget->id;
569 struct _MumbleProto__VoiceTarget__Target *target;
571 if (!targetId || targetId >= 0x1f)
573 Voicetarget_add_id(client, targetId);
574 count = msg->payload.voiceTarget->n_targets;
577 for (i = 0; i < count; i++) {
578 target = msg->payload.voiceTarget->targets[i];
579 for (j = 0; j < target->n_session; j++)
580 Voicetarget_add_session(client, targetId, target->session[j]);
581 if (target->has_channel_id) {
582 bool_t linked = false, children = false;
583 if (target->has_links)
584 linked = target->links;
585 if (target->has_children)
586 children = target->children;
587 Voicetarget_add_channel(client, targetId, target->channel_id, linked, children);
593 Log_debug("Version message received");
594 if (msg->payload.version->has_version) {
595 client->version = msg->payload.version->version;
596 Log_debug("Client version 0x%x", client->version);
598 if (msg->payload.version->release) {
599 if (client->release) free(client->release);
600 client->release = strdup(msg->payload.version->release);
601 Log_debug("Client release %s", client->release);
603 if (msg->payload.version->os) {
604 if (client->os) free(client->os);
605 client->os = strdup(msg->payload.version->os);
606 Log_debug("Client OS %s", client->os);
608 if (msg->payload.version->os_version) {
609 if (client->os_version) free(client->os_version);
610 client->os_version = strdup(msg->payload.version->os_version);
611 Log_debug("Client OS version %s", client->os_version);
614 case PermissionQuery:
615 Msg_inc_ref(msg); /* Re-use message */
616 msg->payload.permissionQuery->has_permissions = true;
618 msg->payload.permissionQuery->permissions = PERM_ADMIN;
620 msg->payload.permissionQuery->permissions = PERM_DEFAULT;
622 Client_send_message(client, msg);
625 client->bUDP = false;
626 Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
630 channel_t *ch_itr, *parent, *newchan;
632 /* Don't allow any changes to existing channels */
633 if (msg->payload.channelState->has_channel_id) {
634 sendPermissionDenied(client, "Not supported by uMurmur");
637 /* Must have parent */
638 if (!msg->payload.channelState->has_parent) {
639 sendPermissionDenied(client, "Not supported by uMurmur");
643 if (msg->payload.channelState->name == NULL) {
644 sendPermissionDenied(client, "Not supported by uMurmur");
647 /* Must be temporary channel */
648 if (msg->payload.channelState->temporary != true) {
649 sendPermissionDenied(client, "Only temporary channels are supported by uMurmur");
652 /* Check channel name is OK */
653 if (strlen(msg->payload.channelState->name) > MAX_TEXT) {
654 sendPermissionDenied(client, "Channel name too long");
658 parent = Chan_fromId(msg->payload.channelState->parent);
662 while (Chan_iterate_siblings(parent, &ch_itr) != NULL) {
663 if (strcmp(ch_itr->name, msg->payload.channelState->name) == 0) {
664 sendPermissionDenied(client, "Channel already exists");
671 /* Disallow temporary channels as siblings to temporary channels */
672 if (parent->temporary) {
673 sendPermissionDenied(client, "Parent channel is temporary channel");
677 /* XXX - Murmur looks for "\\w" and sends perm denied if not found.
678 * I don't know why so I don't do that here...
681 /* Create the channel */
682 newchan = Chan_createChannel(msg->payload.channelState->name,
683 msg->payload.channelState->description);
684 newchan->temporary = true;
685 Chan_addChannel(parent, newchan);
686 msg->payload.channelState->has_channel_id = true;
687 msg->payload.channelState->channel_id = newchan->id;
689 Client_send_message_except(NULL, msg);
691 /* Join the creating user */
692 sendmsg = Msg_create(UserState);
693 sendmsg->payload.userState->has_session = true;
694 sendmsg->payload.userState->session = client->sessionId;
695 sendmsg->payload.userState->has_channel_id = true;
696 sendmsg->payload.userState->channel_id = newchan->id;
697 Client_send_message_except(NULL, sendmsg);
699 leave_id = Chan_userJoin(newchan, client);
701 Log_debug("Removing channel ID %d", leave_id);
702 sendmsg = Msg_create(ChannelRemove);
703 sendmsg->payload.channelRemove->channel_id = leave_id;
704 Client_send_message_except(NULL, sendmsg);
711 client_t *target = NULL;
712 codec_t *codec_itr = NULL;
714 bool_t details = true;
716 if (msg->payload.userStats->has_stats_only)
717 details = !msg->payload.userStats->stats_only;
719 if (!msg->payload.userStats->has_session)
720 sendPermissionDenied(client, "Not supported by uMurmur");
721 while (Client_iterate(&target) != NULL) {
722 if (!IS_AUTH(target))
724 if (target->sessionId == msg->payload.userStats->session)
727 if (!target) /* Not found */
731 * Differences from Murmur:
732 * o Ignoring certificates intentionally
733 * o Ignoring channel local determining
736 sendmsg = Msg_create(UserStats);
737 sendmsg->payload.userStats->session = msg->payload.userStats->session;
738 sendmsg->payload.userStats->from_client->has_good = true;
739 sendmsg->payload.userStats->from_client->good = target->cryptState.uiGood;
740 sendmsg->payload.userStats->from_client->has_late = true;
741 sendmsg->payload.userStats->from_client->late = target->cryptState.uiLate;
742 sendmsg->payload.userStats->from_client->has_lost = true;
743 sendmsg->payload.userStats->from_client->lost = target->cryptState.uiLost;
744 sendmsg->payload.userStats->from_client->has_resync = true;
745 sendmsg->payload.userStats->from_client->resync = target->cryptState.uiResync;
747 sendmsg->payload.userStats->from_server->has_good = true;
748 sendmsg->payload.userStats->from_server->good = target->cryptState.uiRemoteGood;
749 sendmsg->payload.userStats->from_server->has_late = true;
750 sendmsg->payload.userStats->from_server->late = target->cryptState.uiRemoteLate;
751 sendmsg->payload.userStats->from_server->has_lost = true;
752 sendmsg->payload.userStats->from_server->lost = target->cryptState.uiRemoteLost;
753 sendmsg->payload.userStats->from_server->has_resync = true;
754 sendmsg->payload.userStats->from_server->resync = target->cryptState.uiRemoteResync;
756 sendmsg->payload.userStats->has_udp_packets = true;
757 sendmsg->payload.userStats->udp_packets = target->UDPPackets;
758 sendmsg->payload.userStats->has_udp_ping_avg = true;
759 sendmsg->payload.userStats->udp_ping_avg = target->UDPPingAvg;
760 sendmsg->payload.userStats->has_udp_ping_var = true;
761 sendmsg->payload.userStats->udp_ping_var = target->UDPPingVar;
763 sendmsg->payload.userStats->has_tcp_ping_avg = true;
764 sendmsg->payload.userStats->tcp_ping_avg = target->TCPPingAvg;
765 sendmsg->payload.userStats->has_tcp_ping_var = true;
766 sendmsg->payload.userStats->tcp_ping_var = target->TCPPingVar;
767 sendmsg->payload.userStats->has_tcp_packets = true;
768 sendmsg->payload.userStats->tcp_packets = target->TCPPackets;
772 sendmsg->payload.userStats->version->has_version = true;
773 sendmsg->payload.userStats->version->version = target->version;
774 sendmsg->payload.userStats->version->release = strdup(target->release);
775 sendmsg->payload.userStats->version->os = strdup(target->os);
776 sendmsg->payload.userStats->version->os_version = strdup(target->os_version);
778 sendmsg->payload.userStats->n_celt_versions = target->codec_count;
779 sendmsg->payload.userStats->celt_versions = malloc(sizeof(int32_t) * target->codec_count);
780 if (!sendmsg->payload.userStats->celt_versions)
781 Log_fatal("Out of memory");
783 while (Client_codec_iterate(target, &codec_itr) != NULL)
784 sendmsg->payload.userStats->celt_versions[i++] = codec_itr->codec;
787 sendmsg->payload.userStats->has_address = true;
788 sendmsg->payload.userStats->address.data = malloc(sizeof(uint8_t) * 16);
789 if (!sendmsg->payload.userStats->address.data)
790 Log_fatal("Out of memory");
791 memset(sendmsg->payload.userStats->address.data, 0, 16);
792 /* ipv4 representation as ipv6 address. Supposedly correct. */
793 memcpy(&sendmsg->payload.userStats->address.data[12], &target->remote_tcp.sin_addr, 4);
794 sendmsg->payload.userStats->address.len = 16;
797 sendmsg->payload.userStats->has_bandwidth = true;
798 sendmsg->payload.userStats->bandwidth = target->availableBandwidth;
801 sendmsg->payload.userStats->has_onlinesecs = true;
802 sendmsg->payload.userStats->onlinesecs = Timer_elapsed(&target->connectTime) / 1000000LL;
804 sendmsg->payload.userStats->has_idlesecs = true;
805 sendmsg->payload.userStats->idlesecs = Timer_elapsed(&target->idleTime) / 1000000LL;
806 Client_send_message(client, sendmsg);
811 /* Only admin can issue this */
812 if (!client->isAdmin) {
813 sendPermissionDenied(client, "Permission denied");
816 while (Client_iterate(&target) != NULL) {
817 if (target->sessionId == msg->payload.userRemove->session)
820 if (target == NULL) {
821 Log_warn("Client with sessionId %d not found", msg->payload.userRemove->session);
824 msg->payload.userRemove->session = target->sessionId;
825 msg->payload.userRemove->has_actor = true;
826 msg->payload.userRemove->actor = client->sessionId;
828 if (msg->payload.userRemove->has_ban && msg->payload.userRemove->ban) {
829 Log_info("User banned for %d seconds", getIntConf(BAN_LENGTH));
830 /* Put reason, IP, hash, name etc in a list ---> msg->payload.userRemove->reason */
832 Log_info("User kicked");
837 Client_send_message_except(NULL, msg);
838 Client_close(target);
841 /* Permission denied for all these messages. Not implemented. */
844 case ContextActionAdd:
849 sendPermissionDenied(client, "Not supported by uMurmur");
853 Log_warn("Message %d not handled", msg->messageType);
862 Client_close(client);