Add functions for sending messages to clients with different Mumble versions.
authorfatbob313 <martin@fatbob.nu>
Mon, 6 Dec 2010 20:03:03 +0000 (20:03 +0000)
committerfatbob313 <martin@fatbob.nu>
Mon, 6 Dec 2010 20:03:03 +0000 (20:03 +0000)
Add recording support.

src/client.c
src/client.h
src/messagehandler.c
src/messages.c

index 963ec4dd5fb8b1b62a4acb1d99fa59500cd00c33..35ab266c331697e20ed0189e46d0a85fa03ed323 100644 (file)
@@ -505,6 +505,15 @@ int Client_write(client_t *client)
        return 0;
 }
 
+int Client_send_message_ver(client_t *client, message_t *msg, uint32_t version)
+{
+       if ((version == 0) || (client->version >= version) ||
+               ((version & 0x80000000) && (client->version < (~version))))
+               return Client_send_message(client, msg);
+       else
+               Msg_free(msg);
+}
+
 int Client_send_message(client_t *client, message_t *msg)
 {
        if (!client->authenticated && msg->messageType != Version) {
@@ -577,6 +586,29 @@ int Client_send_message_except(client_t *client, message_t *msg)
        return 0;
 }
 
+int Client_send_message_except_ver(client_t *client, message_t *msg, uint32_t version)
+{
+       client_t *itr = NULL;
+       int count = 0;
+       
+       Msg_inc_ref(msg); /* Make sure a reference is held during the whole iteration. */
+       while (Client_iterate(&itr) != NULL) {
+               if (itr != client) {
+                       if (count++ > 0)
+                               Msg_inc_ref(msg); /* One extra reference for each new copy */
+                       Log_debug("Msg %d to %s refcount %d",  msg->messageType, itr->username, msg->refcount);
+                       Client_send_message_ver(itr, msg, version);
+               }
+       }
+       Msg_free(msg); /* Free our reference to the message */
+       
+       if (count == 0)
+               Msg_free(msg); /* If only 1 client is connected then no message is passed
+                                               * to Client_send_message(). Free it here. */
+               
+       return 0;
+}
+
 static bool_t checkDecrypt(client_t *client, const uint8_t *encrypted, uint8_t *plain, unsigned int len)
 {
        if (CryptState_isValid(&client->cryptState) &&
index d2f935c2511c52dac9d0eca17b20dc34f80e400c..a74a2068580d74b7ad04f39591c3e9e53fec860a 100644 (file)
@@ -70,7 +70,7 @@ typedef struct {
        int sessionId;
        uint64_t key;
        char *username;
-       bool_t bUDP, authenticated, deaf, mute;
+       bool_t bUDP, authenticated, deaf, mute, recording;
        char *os, *release, *os_version;
        uint32_t version;
        int codec_count;
@@ -100,6 +100,8 @@ int Client_add(int fd, struct sockaddr_in *remote);
 int Client_read_fd(int fd);
 int Client_write_fd(int fd);
 int Client_send_message(client_t *client, message_t *msg);
+int Client_send_message_ver(client_t *client, message_t *msg, uint32_t version);
+int Client_send_message_except_ver(client_t *client, message_t *msg, uint32_t version);
 int Client_count(void);
 void Client_close(client_t *client);
 client_t *Client_iterate(client_t **client);
index 640a736c9572389c939e3baa778d4fd909851571..c2aa522dae820baed897b61d967f7775bc937619 100644 (file)
@@ -42,6 +42,7 @@
 #include "voicetarget.h"
 
 #define MAX_TEXT 512
+#define MAX_USERNAME 128
 
 extern channel_t *defaultChan;
 extern int iCodecAlpha, iCodecBeta;
@@ -108,7 +109,7 @@ void Mh_handle_message(client_t *client, message_t *msg)
                while (Client_iterate(&client_itr) != NULL) {
                        if (!IS_AUTH(client_itr))
                                continue;
-                       if (client_itr->username && strncmp(client_itr->username, msg->payload.authenticate->username, MAX_TEXT) == 0) {
+                       if (client_itr->username && strncmp(client_itr->username, msg->payload.authenticate->username, MAX_USERNAME) == 0) {
                                char buf[64];
                                sprintf(buf, "Username already in use");
                                Log_debug("Username already in use");
@@ -129,7 +130,7 @@ void Mh_handle_message(client_t *client, message_t *msg)
                        }
                }                               
                if (strlen(msg->payload.authenticate->username) == 0 ||
-                       strlen(msg->payload.authenticate->username) >= MAX_TEXT) { /* XXX - other invalid names? */
+                       strlen(msg->payload.authenticate->username) >= MAX_USERNAME) { /* XXX - other invalid names? */
                        char buf[64];
                        sprintf(buf, "Invalid username");
                        Log_debug("Invalid username");
@@ -240,7 +241,7 @@ void Mh_handle_message(client_t *client, message_t *msg)
                sendmsg->payload.userState->name = strdup(client->username);
                sendmsg->payload.userState->has_channel_id = true;
                sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
-               
+
                Client_send_message_except(client, sendmsg);
 
                client_itr = NULL;
@@ -263,6 +264,10 @@ void Mh_handle_message(client_t *client, message_t *msg)
                                sendmsg->payload.userState->has_self_mute = true;
                                sendmsg->payload.userState->self_mute = true;
                        }
+                       if (client_itr->recording) {
+                               sendmsg->payload.userState->has_recording = true;
+                               sendmsg->payload.userState->recording = true;
+                       }
                        Client_send_message(client, sendmsg);
                }
 
@@ -373,6 +378,30 @@ void Mh_handle_message(client_t *client, message_t *msg)
                                client->deaf = false;
                        }
                }
+               if (msg->payload.userState->has_recording &&
+                       msg->payload.userState->recording != client->recording) {
+                       client->recording = msg->payload.userState->recording;
+                       char *message;
+                       uint32_t *tree_id;
+                       
+                       message = malloc(strlen(client->username) + 32);
+                       if (!message)
+                               Log_fatal("Out of memory");
+                       tree_id = malloc(sizeof(uint32_t));
+                       if (!tree_id)
+                               Log_fatal("Out of memory");
+                       *tree_id = 0;
+                       sendmsg = Msg_create(TextMessage);
+                       sendmsg->payload.textMessage->message = message;
+                       sendmsg->payload.textMessage->n_tree_id = 1;
+                       sendmsg->payload.textMessage->tree_id = tree_id;
+                       if (client->recording)
+                               sprintf(message, "User %s started recording", client->username);
+                       else
+                               sprintf(message, "User %s stopped recording", client->username);
+                       Client_send_message_except_ver(NULL, sendmsg, ~0x010203);
+                       sendmsg = NULL;
+               }
                if (msg->payload.userState->has_channel_id) {
                        int leave_id;
                        if (!Chan_userJoin_id_test(msg->payload.userState->channel_id))
@@ -395,7 +424,6 @@ void Mh_handle_message(client_t *client, message_t *msg)
                        
                        break; /* Don't inform other users about this state */
                }
-               
                /* Re-use message */
                Msg_inc_ref(msg);
                                
index 5a610826a917650f8925c5c53d07389b68bf7880..38d4ea91c832500facc4ace3047d0f7836ab6eed 100644 (file)
@@ -436,6 +436,14 @@ void Msg_free(message_t *msg)
                if (msg->unpacked)
                        mumble_proto__text_message__free_unpacked(msg->payload.textMessage, NULL);
                else {
+                       if (msg->payload.textMessage->message)
+                               free(msg->payload.textMessage->message);
+                       if (msg->payload.textMessage->session)
+                               free(msg->payload.textMessage->session);
+                       if (msg->payload.textMessage->channel_id)
+                               free(msg->payload.textMessage->channel_id);
+                       if (msg->payload.textMessage->tree_id)
+                               free(msg->payload.textMessage->tree_id);
                        free(msg->payload.textMessage);
                }
                break;