From 8f46c2a3cb1e906c68cd658469974d1ab3761d4d Mon Sep 17 00:00:00 2001 From: fatbob313 Date: Wed, 23 Dec 2009 22:33:43 +0000 Subject: [PATCH] More work towards 1.2.0 --- src/client.c | 82 ++++++++++++++++++++++++++++++++++++++++---- src/client.h | 6 ++++ src/messagehandler.c | 50 ++++++++++++++++++++------- src/messages.c | 9 ++++- 4 files changed, 126 insertions(+), 21 deletions(-) diff --git a/src/client.c b/src/client.c index 4290711..706e3f5 100644 --- a/src/client.c +++ b/src/client.c @@ -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); diff --git a/src/client.h b/src/client.h index b6528eb..358993e 100644 --- a/src/client.h +++ b/src/client.h @@ -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 diff --git a/src/messagehandler.c b/src/messagehandler.c index a962cac..dff80fe 100644 --- a/src/messagehandler.c +++ b/src/messagehandler.c @@ -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); } + diff --git a/src/messages.c b/src/messages.c index 3014f88..8b4c497 100644 --- a/src/messages.c +++ b/src/messages.c @@ -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; -- 2.30.2