Add initial support for Opus
[umurmur.git] / src / messagehandler.c
index f07e3ca186de5099adfdb2cee5869e43508c22c3..504c66b0e40b0e258ce8ff4b079f533c403ac2eb 100644 (file)
@@ -47,7 +47,7 @@
 
 extern channel_t *defaultChan;
 extern int iCodecAlpha, iCodecBeta;
-extern bool_t bPreferAlpha;
+extern bool_t bPreferAlpha, bOpus;
 
 static void sendServerReject(client_t *client, const char *reason, MumbleProto__Reject__RejectType type)
 {
@@ -227,8 +227,10 @@ void Mh_handle_message(client_t *client, message_t *msg)
                        Client_codec_add(client, (int32_t)0x8000000a);
                        client->codec_count = 1;
                }
+               if (msg->payload.authenticate->opus)
+                       client->bOpus = true;
                
-               recheckCodecVersions();
+               recheckCodecVersions(client);
                
                sendmsg = Msg_create(CodecVersion);
                sendmsg->payload.codecVersion->alpha = iCodecAlpha;
@@ -298,15 +300,22 @@ 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_itr->channel)->id;
 
-                       /* Only self_mute/deaf supported */
-                       if (client_itr->deaf) {
+                       if (client_itr->self_deaf) {
                                sendmsg->payload.userState->has_self_deaf = true;
                                sendmsg->payload.userState->self_deaf = true;
                        }
-                       if (client_itr->mute) {
+                       if (client_itr->self_mute) {
                                sendmsg->payload.userState->has_self_mute = true;
                                sendmsg->payload.userState->self_mute = true;
                        }
+                       if (client_itr->deaf) {
+                               sendmsg->payload.userState->has_deaf = true;
+                               sendmsg->payload.userState->deaf = true;
+                       }
+                       if (client_itr->mute) {
+                               sendmsg->payload.userState->has_mute = true;
+                               sendmsg->payload.userState->mute = true;
+                       }
                        if (client_itr->recording) {
                                sendmsg->payload.userState->has_recording = true;
                                sendmsg->payload.userState->recording = true;
@@ -435,18 +444,22 @@ void Mh_handle_message(client_t *client, message_t *msg)
                        if (!target->mute) {
                                msg->payload.userState->has_deaf = true;
                                msg->payload.userState->deaf = false;
-                               client->deaf = false;
+                               target->deaf = false;
                        }
                }
                if (msg->payload.userState->has_self_deaf) {
-                       client->deaf = msg->payload.userState->self_deaf;
+                       client->self_deaf = msg->payload.userState->self_deaf;
+                       if (client->self_deaf) {
+                               msg->payload.userState->has_self_mute = true;
+                               msg->payload.userState->self_mute = true;
+                       }
                }
                if (msg->payload.userState->has_self_mute) {
-                       client->mute = msg->payload.userState->self_mute;
-                       if (!client->mute) {
+                       client->self_mute = msg->payload.userState->self_mute;
+                       if (!client->self_mute) {
                                msg->payload.userState->has_self_deaf = true;
                                msg->payload.userState->self_deaf = false;
-                               client->deaf = false;
+                               client->self_deaf = false;
                        }
                }
                if (msg->payload.userState->has_recording &&
@@ -475,16 +488,25 @@ 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, client);
+                       channelJoinResult_t chjoin_rc = Chan_userJoin_id_test(msg->payload.userState->channel_id, target);
                        
                        if (chjoin_rc != CHJOIN_OK) {
                                if (chjoin_rc == CHJOIN_WRONGPW) {
-                                       sendPermissionDenied(client, "Wrong channel password");
+                                       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;
                                }
-                               break;
+                               else break;
                        }
                        
-                       leave_id = Chan_userJoin_id(msg->payload.userState->channel_id, client);
+                       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);
@@ -537,7 +559,7 @@ void Mh_handle_message(client_t *client, message_t *msg)
                                        list_iterate(itr, &ch_itr->clients) {
                                                client_t *c;
                                                c = list_get_entry(itr, client_t, chan_node);
-                                               if (c != client && !c->deaf) {
+                                               if (c != client && !c->deaf && !c->self_deaf) {
                                                        Msg_inc_ref(msg);
                                                        Client_send_message(c, msg);
                                                        Log_debug("Text message to session ID %d", c->sessionId);
@@ -555,7 +577,7 @@ void Mh_handle_message(client_t *client, message_t *msg)
                                        if (!IS_AUTH(itr))
                                                continue;
                                        if (itr->sessionId == msg->payload.textMessage->session[i]) {
-                                               if (!itr->deaf) {
+                                               if (!itr->deaf && !itr->self_deaf) {
                                                        Msg_inc_ref(msg);
                                                        Client_send_message(itr, msg);
                                                        Log_debug("Text message to session ID %d", itr->sessionId);
@@ -795,6 +817,8 @@ 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->opus = target->bOpus;
+
                        /* Address */
                        sendmsg->payload.userStats->has_address = true;
                        sendmsg->payload.userStats->address.data = malloc(sizeof(uint8_t) * 16);