More work towards 1.2.0
authorfatbob313 <martin@fatbob.nu>
Wed, 23 Dec 2009 22:33:43 +0000 (22:33 +0000)
committerfatbob313 <martin@fatbob.nu>
Wed, 23 Dec 2009 22:33:43 +0000 (22:33 +0000)
src/client.c
src/client.h
src/messagehandler.c
src/messages.c

index 42907117694b60dbe87a1028148af862b3ec3e4f..706e3f5bfa98f277e2c63b51218791e158824521 100644 (file)
@@ -53,6 +53,9 @@ static int clientcount; /* = 0 */
 static int session = 1;
 static int maxBandwidth;
 
+static int iCodecAlpha, iCodecBeta;
+static bool_t bPreferAlpha;
+
 extern int udpsock;
 
 void Client_init()
@@ -101,10 +104,64 @@ void Client_janitor()
        }
 }
 
+void recheckCodecVersions()
+{
+       int codec_map[MAX_CODECS][2];
+       client_t *itr;
+       int i, codecindex, max = 0, version, current_version;
+       message_t *sendmsg;
+       
+       memset(codec_map, 0, MAX_CODECS * 2 * sizeof(int));
+       while (Client_iterate(&itr) != NULL) {
+               for (i = 0; i < itr->codec_count; i++) {
+                       for (codecindex = 0; codecindex < MAX_CODECS; codecindex++) {
+                               if (codec_map[codecindex][0] == 0)
+                                       codec_map[codecindex][0] = itr->codecs[i];
+                               if (itr->codecs[i] == codec_map[codecindex][0])
+                                       codec_map[codecindex][1]++;
+                       }
+               }
+       }
+       if (codec_map[codecindex][0] == 0)
+               return;
+       for (codecindex = 0; codecindex < MAX_CODECS; codecindex++) {
+               if (codec_map[codecindex][0] == 0)
+                       break;
+               if (codec_map[codecindex][1] > max) {
+                       max = codec_map[codecindex][1];
+                       version = codec_map[codecindex][0];
+               }
+       }
+       current_version = bPreferAlpha ? iCodecAlpha : iCodecBeta;
+       if (current_version == version)
+               return;
+       // If we don't already use the compat bitstream version set
+       // it as alpha and announce it. If another codec now got the
+       // majority set it as the opposite of the currently valid bPreferAlpha
+       // and announce it.
+       if (version == (uint32_t)0x8000000a)
+               bPreferAlpha = true;
+       else
+               bPreferAlpha = ! bPreferAlpha;
+
+       if (bPreferAlpha)
+               iCodecAlpha = version;
+       else
+               iCodecBeta = version;
+       
+       sendmsg = Msg_create(CodecVersion);
+       sendmsg->payload.codecVersion->alpha = version;
+       sendmsg->payload.codecVersion->beta = version;
+       sendmsg->payload.codecVersion->beta = bPreferAlpha;
+       Client_send_message_except(NULL, sendmsg);
+
+}
+
 int Client_add(int fd, struct sockaddr_in *remote)
 {
        client_t *newclient;
-
+       message_t *sendmsg;
+       
        newclient = malloc(sizeof(client_t));
        if (newclient == NULL)
                Log_fatal("Out of memory");
@@ -128,6 +185,16 @@ int Client_add(int fd, struct sockaddr_in *remote)
        
        list_add_tail(&newclient->node, &clients);
        clientcount++;
+       
+       /* Send version message to client */
+       sendmsg = Msg_create(Version);
+       sendmsg->payload.version->has_version = true;
+       sendmsg->payload.version->version = (1 << 16) | (2 << 8) | 0; /* XXX fix */
+       sendmsg->payload.version->release = strdup("1.2.0");
+       sendmsg->payload.version->os = strdup("Linux/OpenWRT");
+               
+       Client_send_message(newclient, sendmsg);
+
        return 0;
 }
 
@@ -339,11 +406,11 @@ int Client_write(client_t *client)
 
 int Client_send_message(client_t *client, message_t *msg)
 {
-       if (!client->authenticated || !client->SSLready) {
+       if (!client->authenticated && msg->messageType != Version) {
                Msg_free(msg);
                return 0;
        }
-       if (client->txsize != 0) {
+       if (client->txsize != 0 || !client->SSLready) {
                /* Queue message */
                if ((client->txQueueCount > 5 &&  msg->messageType == UDPTunnel) ||
                        client->txQueueCount > 30) {
@@ -533,14 +600,14 @@ int Client_voiceMsg(client_t *client, uint8_t *data, int len)
        struct dlist *itr;
        
        if (!client->authenticated || client->mute)
-               return 0;
+               goto out;
        
        packetsize = 20 + 8 + 4 + len;
        if (client->availableBandwidth - packetsize < 0)
-               return 0; /* Discard */
+               goto out; /* Discard */
        client->availableBandwidth -= packetsize;
        
-       counter = Pds_get_numval(pdi); /* Seems like this... */
+       counter = Pds_get_numval(pdi); /* step past session id */
        do {
                counter = Pds_next8(pdi);
                offset = Pds_skip(pdi, counter & 0x7f);
@@ -559,7 +626,7 @@ int Client_voiceMsg(client_t *client, uint8_t *data, int len)
                buffer[0] = (uint8_t) type;
                
                if (ch == NULL)
-                       return 0;
+                       goto out;
                
                list_iterate(itr, &ch->clients) {
                        client_t *c;
@@ -570,6 +637,7 @@ int Client_voiceMsg(client_t *client, uint8_t *data, int len)
                }
        }
        /* XXX - Add targeted whisper here */
+out:
        Pds_free(pds);
        Pds_free(pdi);
        
index b6528ebff8289708eb99e66b361a8c2dba279539..358993e0e77d6850cc60add09284bdb6be1fcbeb 100644 (file)
@@ -51,6 +51,7 @@
 #define BUFSIZE 2048
 #define UDP_BUFSIZE 512
 #define INACTICITY_TIMEOUT 15 /* Seconds */
+#define MAX_CODECS 10
 
 #define IS_AUTH(_a_) ((_a_)->authenticated)
 
@@ -71,6 +72,10 @@ typedef struct {
        char playerName[MAX_TEXT];
        int playerId;
        bool_t authenticated, deaf, mute;
+       char *os, *release;
+       uint32_t version;
+       int codec_count;
+       int32_t codecs[MAX_CODECS];
        int availableBandwidth;
        etimer_t lastActivity;
        struct dlist node;
@@ -96,5 +101,6 @@ int Client_send_message_except(client_t *client, message_t *msg);
 int Client_read_udp(void);
 void Client_disconnect_all();
 int Client_voiceMsg(client_t *client, uint8_t *data, int len);
+void recheckCodecVersions();
 
 #endif
index a962cac477fb7484facd041d0433df6c72f153ed..dff80fedb19e377860e542fa264a56d35cacd97e 100644 (file)
@@ -145,6 +145,22 @@ void Mh_handle_message(client_t *client, message_t *msg)
                /* Channel stuff */
                Chan_playerJoin(defaultChan, client); /* Join default channel */
 
+               /* Codec version */
+               if (msg->payload.authenticate->n_celt_versions > MAX_CODECS)
+                       Log_warn("Client has more than %d CELT codecs. Ignoring %d codecs",
+                                        MAX_CODECS, msg->payload.authenticate->n_celt_versions - MAX_CODECS);
+               if (msg->payload.authenticate->n_celt_versions > 0) {
+                       int i;
+                       client->codec_count = msg->payload.authenticate->n_celt_versions > MAX_CODECS ?
+                               MAX_CODECS : msg->payload.authenticate->n_celt_versions;
+                       for (i = 0; i < client->codec_count; i++)
+                               client->codecs[i] = msg->payload.authenticate->celt_versions[i];
+               } else {
+                       client->codecs[0] = (int32_t)0x8000000a;
+                       client->codec_count = 1;
+               }
+               recheckCodecVersions();
+                       
                /* Iterate channels and send channel info */
                ch_itr = NULL;
                Chan_iterate(&ch_itr);
@@ -186,17 +202,17 @@ void Mh_handle_message(client_t *client, message_t *msg)
                                continue;
                        sendmsg = Msg_create(UserState);
                        sendmsg->payload.userState->has_session = true;
-                       sendmsg->payload.userState->session = client->sessionId;
-                       sendmsg->payload.userState->name = strdup(client->playerName);
+                       sendmsg->payload.userState->session = client_itr->sessionId;
+                       sendmsg->payload.userState->name = strdup(client_itr->playerName);
                        sendmsg->payload.userState->has_channel_id = true;
-                       sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
+                       sendmsg->payload.userState->channel_id = ((channel_t *)client_itr->channel)->id;
 
                        /* XXX - check if self_* is correct */
-                       if (client->deaf) {
+                       if (client_itr->deaf) {
                                sendmsg->payload.userState->has_self_deaf = true;
                                sendmsg->payload.userState->self_deaf = true;
                        }
-                       if (client->mute) {
+                       if (client_itr->mute) {
                                sendmsg->payload.userState->has_self_mute = true;
                                sendmsg->payload.userState->self_mute = true;
                        }
@@ -262,7 +278,7 @@ void Mh_handle_message(client_t *client, message_t *msg)
                if (!msg->payload.cryptSetup->has_client_nonce) {
                        sendmsg = Msg_create(CryptSetup);
                        sendmsg->payload.cryptSetup->has_server_nonce = true;
-                       memcpy(sendmsg->payload.cryptSetup->server_nonce.data, client->cryptState.decrypt_iv, AES_BLOCK_SIZE);
+                       sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.decrypt_iv;
                        sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
                        Client_send_message(client, sendmsg);
                } else {
@@ -347,14 +363,21 @@ void Mh_handle_message(client_t *client, message_t *msg)
                break;
 
        case Version:
-               sendmsg = Msg_create(Version); /* Re-use message */
                Log_debug("Version message received");
-               sendmsg->payload.version->has_version = true;
-               sendmsg->payload.version->version = (1 << 16) | (2 << 8) | 0; /* XXX fix */
-               sendmsg->payload.version->release = "Phony donkey";
-               sendmsg->payload.version->os = "OpenWRT";
-               
-               Client_send_message(client, sendmsg);
+               if (msg->payload.version->has_version) {
+                       client->version = msg->payload.version->version;
+                       Log_debug("Client version 0x%x", client->version);
+               }
+               if (msg->payload.version->release) {
+                       if (client->release) free(client->release);
+                       client->release = strdup(msg->payload.version->release);
+                       Log_debug("Client release %s", client->release);
+               }
+               if (msg->payload.version->os) {
+                       if (client->os) free(client->os);                       
+                       client->os = strdup(msg->payload.version->os);
+                       Log_debug("Client OS %s", client->os);
+               }
                break;
        case CodecVersion:
                Msg_inc_ref(msg); /* Re-use message */
@@ -386,3 +409,4 @@ disconnect:
        Msg_free(msg);
        Client_close(client);
 }
+
index 3014f88ca34f19b882f1776b080cf891ec95803e..8b4c497e8679c638277e47ec8452f32d601b5161 100644 (file)
@@ -75,6 +75,8 @@ int Msg_messageToNetwork(message_t *msg, uint8_t *buffer)
                        break;
                }
                Msg_addPreamble(buffer, msg->messageType, len);
+               Log_debug("To net: Version->release: %s Version->os: %s",
+                                 msg->payload.version->release, msg->payload.version->os);
                mumble_proto__version__pack(msg->payload.version, bufptr);
                break;
        case UDPTunnel:
@@ -294,12 +296,17 @@ void Msg_free(message_t *msg)
        if (msg->refcount > 0)
                return;
 
-       /* XXX - add free for locally generated messages too */
        switch (msg->messageType) {
        case Version:
                if (msg->unpacked)
                        mumble_proto__version__free_unpacked(msg->payload.version, NULL);
                else {
+                       if (msg->payload.version->release)
+                               free(msg->payload.version->release);
+                       if (msg->payload.version->os)
+                               free(msg->payload.version->os);
+                       if (msg->payload.version->os_version)
+                               free(msg->payload.version->os_version);
                        free(msg->payload.version);
                }
                break;