Update copyright year
[umurmur.git] / src / messagehandler.c
index 504c66b0e40b0e258ce8ff4b079f533c403ac2eb..849c55990526d270954149d815dd44d1c32d9279 100644 (file)
@@ -1,5 +1,5 @@
-/* Copyright (C) 2009-2012, Martin Johansson <martin@fatbob.nu>
-   Copyright (C) 2005-2012, Thorvald Natvig <thorvald@natvig.com>
+/* Copyright (C) 2009-2014, Martin Johansson <martin@fatbob.nu>
+   Copyright (C) 2005-2014, Thorvald Natvig <thorvald@natvig.com>
 
    All rights reserved.
 
 #define MAX_TEXT 512
 #define MAX_USERNAME 128
 
+#define NO_CELT_MESSAGE "<strong>WARNING:</strong> Your client doesn't support the CELT codec, you won't be able to talk to or hear most clients. Please make sure your client was built with CELT support."
+
+
 extern channel_t *defaultChan;
 extern int iCodecAlpha, iCodecBeta;
 extern bool_t bPreferAlpha, bOpus;
 
+static bool_t fake_celt_support;
+
 static void sendServerReject(client_t *client, const char *reason, MumbleProto__Reject__RejectType type)
 {
        message_t *msg = Msg_create(Reject);
@@ -224,8 +229,9 @@ void Mh_handle_message(client_t *client, message_t *msg)
                                Log_debug("Client %d CELT codec ver 0x%x", client->sessionId, codec_itr->codec);
                                
                } else {
-                       Client_codec_add(client, (int32_t)0x8000000a);
+                       Client_codec_add(client, (int32_t)0x8000000b);
                        client->codec_count = 1;
+                       fake_celt_support = true;
                }
                if (msg->payload.authenticate->opus)
                        client->bOpus = true;
@@ -236,8 +242,14 @@ void Mh_handle_message(client_t *client, message_t *msg)
                sendmsg->payload.codecVersion->alpha = iCodecAlpha;
                sendmsg->payload.codecVersion->beta = iCodecBeta;
                sendmsg->payload.codecVersion->prefer_alpha = bPreferAlpha;
+               sendmsg->payload.codecVersion->has_opus = true;
+               sendmsg->payload.codecVersion->opus = bOpus;
                Client_send_message(client, sendmsg);
-               
+
+               if (!bOpus && client->bOpus && fake_celt_support) {
+                       Client_textmessage(client, NO_CELT_MESSAGE);
+               }
+
                /* Iterate channels and send channel info */
                ch_itr = NULL;
                while (Chan_iterate(&ch_itr) != NULL) {
@@ -251,6 +263,10 @@ void Mh_handle_message(client_t *client, message_t *msg)
                        sendmsg->payload.channelState->name = strdup(ch_itr->name);
                        if (ch_itr->desc)
                                sendmsg->payload.channelState->description = strdup(ch_itr->desc);
+                       if (ch_itr->position != 0) {
+                               sendmsg->payload.channelState->has_position = true;
+                               sendmsg->payload.channelState->position = ch_itr->position;
+                       }
                        Log_debug("Send channel info: %s", sendmsg->payload.channelState->name);
                        Client_send_message(client, sendmsg);                   
                }
@@ -287,6 +303,11 @@ void Mh_handle_message(client_t *client, message_t *msg)
                sendmsg->payload.userState->has_channel_id = true;
                sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
 
+               if (defaultChan->silent) {
+                       sendmsg->payload.userState->has_suppress = true;
+                       sendmsg->payload.userState->suppress = true;
+               }
+
                Client_send_message_except(client, sendmsg);
 
                client_itr = NULL;
@@ -299,6 +320,10 @@ void Mh_handle_message(client_t *client, message_t *msg)
                        sendmsg->payload.userState->name = strdup(client_itr->username);
                        sendmsg->payload.userState->has_channel_id = true;
                        sendmsg->payload.userState->channel_id = ((channel_t *)client_itr->channel)->id;
+                       sendmsg->payload.userState->has_suppress = ((channel_t *)client_itr->channel)->silent;
+                       sendmsg->payload.userState->suppress = ((channel_t *)client_itr->channel)->silent;
+
+                       client_itr->isSuppressed = ((channel_t *)client_itr->channel)->silent;
 
                        if (client_itr->self_deaf) {
                                sendmsg->payload.userState->has_self_deaf = true;
@@ -488,30 +513,44 @@ void Mh_handle_message(client_t *client, message_t *msg)
                }
                if (msg->payload.userState->has_channel_id) {
                        int leave_id;
-                       channelJoinResult_t chjoin_rc = Chan_userJoin_id_test(msg->payload.userState->channel_id, target);
-                       
-                       if (chjoin_rc != CHJOIN_OK) {
-                               if (chjoin_rc == CHJOIN_WRONGPW) {
-                                       if (target == client && !client->isAdmin) {
-                                               sendPermissionDenied(client, "Wrong channel password");
-                                               break;
-                                       }
-                                       /* Tricky one: if user hasn't the password, but is moved to the channel by admin then let
-                                        * the user in. Also let admin user in regardless of channel password.
-                                        * Take no action on other errors.
-                                        */
-                                       else if (!client->isAdmin)
-                                               break;
+
+                       channelJoinResult_t result = Chan_userJoin_id_test(msg->payload.userState->channel_id, target);
+
+                       if (result.CHJOIN_NOENTER || result.CHJOIN_NOTFOUND)
+                               break;
+
+                       if (result.CHJOIN_WRONGPW) {
+                               if (target == client && !client->isAdmin) {
+                                       sendPermissionDenied(client, "Wrong channel password");
+                                       break;
                                }
-                               else break;
+                               /* Tricky one: if user hasn't the password, but is moved to the channel by admin then let
+                                * the user in. Also let admin user in regardless of channel password.
+                                * Take no action on other errors.
+                                */
+                               else if (!client->isAdmin)
+                                       break;
                        }
-                       
+
                        leave_id = Chan_userJoin_id(msg->payload.userState->channel_id, target);
                        if (leave_id > 0) {
                                Log_debug("Removing channel ID %d", leave_id);
                                sendmsg = Msg_create(ChannelRemove);
                                sendmsg->payload.channelRemove->channel_id = leave_id;
                        }
+
+                       if (result.CHJOIN_SILENT) {
+                               if (!target->isSuppressed) {
+                               msg->payload.userState->has_suppress = true;
+                               msg->payload.userState->suppress = true;
+                               target->isSuppressed = true;
+                               }
+                       }
+                       else if (target->isSuppressed) {
+                               msg->payload.userState->has_suppress = true;
+                               msg->payload.userState->suppress = false;
+                               target->isSuppressed = false;
+                       }
                }
                if (msg->payload.userState->has_plugin_context) {
                        if (client->context)
@@ -716,6 +755,8 @@ void Mh_handle_message(client_t *client, message_t *msg)
                newchan = Chan_createChannel(msg->payload.channelState->name,
                                                                         msg->payload.channelState->description);
                newchan->temporary = true;
+               if (msg->payload.channelState->has_position)
+                       newchan->position = msg->payload.channelState->position;
                Chan_addChannel(parent, newchan);
                msg->payload.channelState->has_channel_id = true;
                msg->payload.channelState->channel_id = newchan->id;
@@ -728,8 +769,15 @@ void Mh_handle_message(client_t *client, message_t *msg)
                sendmsg->payload.userState->session = client->sessionId;
                sendmsg->payload.userState->has_channel_id = true;
                sendmsg->payload.userState->channel_id = newchan->id;
+
+               if (client->isSuppressed) {
+                       sendmsg->payload.userState->has_suppress = true;
+                       sendmsg->payload.userState->suppress = false;
+                       client->isSuppressed = false;
+               }
+
                Client_send_message_except(NULL, sendmsg);
-               
+
                leave_id = Chan_userJoin(newchan, client);
                if (leave_id > 0) {
                        Log_debug("Removing channel ID %d", leave_id);
@@ -805,9 +853,12 @@ void Mh_handle_message(client_t *client, message_t *msg)
 
                        sendmsg->payload.userStats->version->has_version = true;
                        sendmsg->payload.userStats->version->version = target->version;
-                       sendmsg->payload.userStats->version->release = strdup(target->release);
-                       sendmsg->payload.userStats->version->os = strdup(target->os);
-                       sendmsg->payload.userStats->version->os_version = strdup(target->os_version);
+                       if (target->release)
+                               sendmsg->payload.userStats->version->release = strdup(target->release);
+                       if (target->os)
+                               sendmsg->payload.userStats->version->os = strdup(target->os);
+                       if (target->os_version)
+                               sendmsg->payload.userStats->version->os_version = strdup(target->os_version);
                        
                        sendmsg->payload.userStats->n_celt_versions = target->codec_count;
                        sendmsg->payload.userStats->celt_versions = malloc(sizeof(int32_t) * target->codec_count);
@@ -817,6 +868,7 @@ void Mh_handle_message(client_t *client, message_t *msg)
                        while (Client_codec_iterate(target, &codec_itr) != NULL)
                                sendmsg->payload.userStats->celt_versions[i++] = codec_itr->codec;
 
+                       sendmsg->payload.userStats->has_opus = true;
                        sendmsg->payload.userStats->opus = target->bOpus;
 
                        /* Address */