From 477a4a1b836a9693338dd2ef76782013f3fb0a16 Mon Sep 17 00:00:00 2001 From: fatbob313 Date: Sun, 7 Feb 2010 14:48:55 +0000 Subject: [PATCH] Fix for: o TCP mode with with associated positional data size calculation errors o Enable whisper to channel with children o Linked channels shall only be used when whispering o Set flag correctly for channel and session whisper --- src/channel.c | 25 ++++++++++++++++ src/channel.h | 7 +++++ src/client.c | 69 +++++++++++++++++++++++++++----------------- src/client.h | 2 +- src/messagehandler.c | 10 +++++-- src/messages.c | 36 ++++++++++++++--------- src/messages.h | 1 + src/voicetarget.c | 11 ++++--- src/voicetarget.h | 11 +++++-- 9 files changed, 122 insertions(+), 50 deletions(-) diff --git a/src/channel.c b/src/channel.c index c3ddda8..4de6490 100644 --- a/src/channel.c +++ b/src/channel.c @@ -342,3 +342,28 @@ void Chan_removeChannel(channel_t *ch) { list_del(&ch->node); } + +void Chan_buildTreeList(channel_t *ch, struct dlist *head) +{ + channellist_t *chl; + struct dlist *itr; + channel_t *sub; + + chl = malloc(sizeof(channellist_t)); + chl->chan = ch; + init_list_entry(&chl->node); + list_add_tail(&chl->node, head); + + list_iterate(itr, &ch->subs) { + sub = list_get_entry(itr, channel_t, node); + Chan_buildTreeList(sub, head); + } +} + +void Chan_freeTreeList(struct dlist *head) +{ + struct dlist *itr, *save; + list_iterate_safe(itr, save, head) { + free(list_get_entry(itr, channellist_t, node)); + } +} diff --git a/src/channel.h b/src/channel.h index c092c56..e20bfad 100644 --- a/src/channel.h +++ b/src/channel.h @@ -49,6 +49,11 @@ typedef struct channel { struct dlist link_node; } channel_t; +typedef struct { + channel_t *chan; + struct dlist node; +} channellist_t; + void Chan_init(); void Chan_free(); void Chan_addChannel(channel_t *parent, channel_t *sub); @@ -64,5 +69,7 @@ channel_t *Chan_iterate_siblings(channel_t *parent, channel_t **channelpptr); channel_t *Chan_createChannel(const char *name, const char *desc); channel_t *Chan_fromId(int channelid); void Chan_freeChannel(channel_t *ch); +void Chan_buildTreeList(channel_t *ch, struct dlist *head); +void Chan_freeTreeList(struct dlist *head); #endif diff --git a/src/client.c b/src/client.c index 9f09c2a..b72e46f 100644 --- a/src/client.c +++ b/src/client.c @@ -658,16 +658,17 @@ int Client_read_udp() } } /* while */ } - if (itr == NULL) { + if (itr == NULL) { /* Couldn't find this peer among connected clients */ goto out; } + len -= 4; /* Adjust for crypt header */ msgType = (UDPMessageType_t)((buffer[0] >> 5) & 0x7); switch (msgType) { case UDPVoiceSpeex: case UDPVoiceCELTAlpha: case UDPVoiceCELTBeta: - // u->bUdp = true; + itr->bUDP = true; Client_voiceMsg(itr, buffer, len); break; case UDPPing: @@ -678,6 +679,7 @@ int Client_read_udp() Log_debug("Unknown UDP message type from %s port %d", inet_ntoa(from.sin_addr), ntohs(from.sin_port)); break; } + out: return 0; } @@ -689,7 +691,7 @@ static inline void Client_send_voice(client_t *src, client_t *dst, uint8_t *data src->context != NULL && dst->context != NULL && /* ...both source and destination has context */ strcmp(src->context, dst->context) == 0) /* ...and the contexts match */ Client_send_udp(dst, data, len); - else + else Client_send_udp(dst, data, len - poslen); } } @@ -743,27 +745,14 @@ int Client_voiceMsg(client_t *client, uint8_t *data, int len) c = list_get_entry(itr, client_t, chan_node); Client_send_voice(client, c, buffer, pds->offset + 1, poslen); } - /* Channel links */ - if (!list_empty(&ch->channel_links)) { - struct dlist *ch_itr; - list_iterate(ch_itr, &ch->channel_links) { - channel_t *ch_link; - ch_link = list_get_entry(ch_itr, channel_t, link_node); - list_iterate(itr, &ch_link->clients) { - client_t *c; - c = list_get_entry(itr, client_t, chan_node); - Log_debug("Linked voice from %s -> %s", ch->name, ch_link->name); - Client_send_voice(client, c, buffer, pds->offset + 1, poslen); - } - } - } } else if ((vt = Voicetarget_get_id(client, target)) != NULL) { /* Targeted whisper */ int i; channel_t *ch; /* Channels */ - for (i = 0; i < TARGET_MAX_CHANNELS && vt->channels[i] != -1; i++) { + for (i = 0; i < TARGET_MAX_CHANNELS && vt->channels[i].channel != -1; i++) { + buffer[0] = (uint8_t) (type | 1); Log_debug("Whisper channel %d", vt->channels[i]); - ch = Chan_fromId(vt->channels[i]); + ch = Chan_fromId(vt->channels[i].channel); if (ch == NULL) continue; list_iterate(itr, &ch->clients) { @@ -771,10 +760,42 @@ int Client_voiceMsg(client_t *client, uint8_t *data, int len) c = list_get_entry(itr, client_t, chan_node); Client_send_voice(client, c, buffer, pds->offset + 1, poslen); } + /* Channel links */ + if (vt->channels[i].linked && !list_empty(&ch->channel_links)) { + struct dlist *ch_itr; + list_iterate(ch_itr, &ch->channel_links) { + channel_t *ch_link; + ch_link = list_get_entry(ch_itr, channel_t, link_node); + list_iterate(itr, &ch_link->clients) { + client_t *c; + c = list_get_entry(itr, client_t, chan_node); + Log_debug("Linked voice from %s -> %s", ch->name, ch_link->name); + Client_send_voice(client, c, buffer, pds->offset + 1, poslen); + } + } + } + /* children */ + if (vt->channels[i].children) { + struct dlist chanlist, *ch_itr; + init_list_entry(&chanlist); + Chan_buildTreeList(ch, &chanlist); + list_iterate(ch_itr, &chanlist) { + channel_t *sub; + sub = list_get_entry(ch_itr, channellist_t, node)->chan; + list_iterate(itr, &sub->clients) { + client_t *c; + c = list_get_entry(itr, client_t, chan_node); + Log_debug("Child voice from %s -> %s", ch->name, sub->name); + Client_send_voice(client, c, buffer, pds->offset + 1, poslen); + } + } + Chan_freeTreeList(&chanlist); + } } /* Sessions */ for (i = 0; i < TARGET_MAX_SESSIONS && vt->sessions[i] != -1; i++) { client_t *c; + buffer[0] = (uint8_t) (type | 2); Log_debug("Whisper session %d", vt->sessions[i]); while (Client_iterate(&c) != NULL) { if (c->sessionId == vt->sessions[i]) { @@ -796,7 +817,8 @@ static int Client_send_udp(client_t *client, uint8_t *data, int len) { uint8_t *buf, *mbuf; - if (client->remote_udp.sin_port != 0 && CryptState_isValid(&client->cryptState)) { + if (client->remote_udp.sin_port != 0 && CryptState_isValid(&client->cryptState) && + client->bUDP) { #if defined(__LP64__) buf = mbuf = malloc(len + 4 + 16); buf += 4; @@ -813,12 +835,7 @@ static int Client_send_udp(client_t *client, uint8_t *data, int len) free(mbuf); } else { message_t *msg; - buf = malloc(len); - memcpy(buf, data, len); - msg = Msg_create(UDPTunnel); - - msg->payload.UDPTunnel->packet.data = buf; - msg->payload.UDPTunnel->packet.len = len; + msg = Msg_CreateVoiceMsg(data, len); Client_send_message(client, msg); } return 0; diff --git a/src/client.h b/src/client.h index a7d43f0..f7b88c4 100644 --- a/src/client.h +++ b/src/client.h @@ -70,7 +70,7 @@ typedef struct { int sessionId; uint64_t key; char *username; - bool_t authenticated, deaf, mute; + bool_t bUDP, authenticated, deaf, mute; char *os, *release; uint32_t version; int codec_count; diff --git a/src/messagehandler.c b/src/messagehandler.c index b1a55fb..98a9953 100644 --- a/src/messagehandler.c +++ b/src/messagehandler.c @@ -413,9 +413,12 @@ void Mh_handle_message(client_t *client, message_t *msg) for (j = 0; j < target->n_session; j++) Voicetarget_add_session(client, targetId, target->session[j]); if (target->has_channel_id) { - if (target->has_links || target->has_children) - Log_warn("Whisper to children or linked channels not implemented. Ignoring."); - Voicetarget_add_channel(client, targetId, target->channel_id); + bool_t linked = false, children = false; + if (target->has_links) + linked = target->links; + if (target->has_children) + children = target->children; + Voicetarget_add_channel(client, targetId, target->channel_id, linked, children); } } break; @@ -445,6 +448,7 @@ void Mh_handle_message(client_t *client, message_t *msg) Client_send_message(client, msg); break; case UDPTunnel: + client->bUDP = false; Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len); break; case ChannelState: diff --git a/src/messages.c b/src/messages.c index 09ec927..109f5eb 100644 --- a/src/messages.c +++ b/src/messages.c @@ -41,10 +41,10 @@ #define PREAMBLE_SIZE 6 -void dumpmsg(uint8_t *data, int size); +static void dumpmsg(uint8_t *data, int size); static message_t *Msg_create_nopayload(messageType_t messageType); -void Msg_addPreamble(uint8_t *buffer, uint16_t type, uint32_t len) +static void Msg_addPreamble(uint8_t *buffer, uint16_t type, uint32_t len) { type = htons(type); len = htonl(len); @@ -232,13 +232,13 @@ int Msg_messageToNetwork(message_t *msg, uint8_t *buffer) break; default: - Log_warn("Msg_networkToMessage: Unsupported message %d", msg->messageType); + Log_warn("Msg_MessageToNetwork: Unsupported message %d", msg->messageType); return 0; } return len + PREAMBLE_SIZE; } -message_t *Msg_create_nopayload(messageType_t messageType) +static message_t *Msg_create_nopayload(messageType_t messageType) { message_t *msg = malloc(sizeof(message_t)); @@ -501,6 +501,23 @@ void dumpmsg(uint8_t *data, int size) } } +message_t *Msg_CreateVoiceMsg(uint8_t *data, int size) +{ + message_t *msg = NULL; + + msg = Msg_create_nopayload(UDPTunnel); + msg->unpacked = false; + msg->payload.UDPTunnel = malloc(sizeof(struct _MumbleProto__UDPTunnel)); + if (msg->payload.UDPTunnel == NULL) + Log_fatal("Out of memory"); + msg->payload.UDPTunnel->packet.data = malloc(size); + if (msg->payload.UDPTunnel->packet.data == NULL) + Log_fatal("Out of memory"); + memcpy(msg->payload.UDPTunnel->packet.data, data, size); + msg->payload.UDPTunnel->packet.len = size; + return msg; +} + message_t *Msg_networkToMessage(uint8_t *data, int size) { message_t *msg = NULL; @@ -524,16 +541,7 @@ message_t *Msg_networkToMessage(uint8_t *data, int size) } case UDPTunnel: /* Non-standard handling of tunneled voice data */ { - msg = Msg_create_nopayload(UDPTunnel); - msg->unpacked = false; - msg->payload.UDPTunnel = malloc(sizeof(struct _MumbleProto__UDPTunnel)); - if (msg->payload.UDPTunnel == NULL) - Log_fatal("Out of memory"); - msg->payload.UDPTunnel->packet.data = malloc(msgLen); - if (msg->payload.UDPTunnel->packet.data == NULL) - Log_fatal("Out of memory"); - memcpy(msg->payload.UDPTunnel->packet.data, msgData, msgLen); - msg->payload.UDPTunnel->packet.len = msgLen; + msg = Msg_CreateVoiceMsg(msgData, msgLen); break; } case Authenticate: diff --git a/src/messages.h b/src/messages.h index 9aebc4b..9fde9f9 100644 --- a/src/messages.h +++ b/src/messages.h @@ -139,6 +139,7 @@ message_t *Msg_networkToMessage(uint8_t *data, int size); void Msg_free(message_t *msg); void Msg_inc_ref(message_t *msg); +message_t *Msg_CreateVoiceMsg(uint8_t *data, int size); message_t *Msg_create(messageType_t messageType); #endif diff --git a/src/voicetarget.c b/src/voicetarget.c index 935139f..85c2607 100644 --- a/src/voicetarget.c +++ b/src/voicetarget.c @@ -52,7 +52,8 @@ void Voicetarget_add_session(client_t *client, int targetId, int sessionId) } } -void Voicetarget_add_channel(client_t *client, int targetId, int channelId) +void Voicetarget_add_channel(client_t *client, int targetId, int channelId, + bool_t linked, bool_t children) { struct dlist *itr; voicetarget_t *vt; @@ -62,8 +63,10 @@ void Voicetarget_add_channel(client_t *client, int targetId, int channelId) int i; vt = list_get_entry(itr, voicetarget_t, node); for (i = 0; i < TARGET_MAX_CHANNELS; i++) { - if (vt->channels[i] == -1) { - vt->channels[i] = channelId; + if (vt->channels[i].channel == -1) { + vt->channels[i].channel = channelId; + vt->channels[i].linked = linked; + vt->channels[i].children = children; Log_debug("Adding channel ID %d to voicetarget ID %d", channelId, targetId); return; } @@ -83,7 +86,7 @@ void Voicetarget_add_id(client_t *client, int targetId) Log_fatal("Out of memory"); memset(newtarget, 0, sizeof(voicetarget_t)); for (i = 0; i < TARGET_MAX_CHANNELS; i++) - newtarget->channels[i] = -1; + newtarget->channels[i].channel = -1; for (i = 0; i < TARGET_MAX_SESSIONS; i++) newtarget->sessions[i] = -1; newtarget->id = targetId; diff --git a/src/voicetarget.h b/src/voicetarget.h index 0d2f051..1bd2d17 100644 --- a/src/voicetarget.h +++ b/src/voicetarget.h @@ -37,9 +37,15 @@ #define TARGET_MAX_CHANNELS 16 #define TARGET_MAX_SESSIONS 32 +typedef struct { + int channel; + bool_t linked; + bool_t children; +} channeltarget_t; + typedef struct { int id; - int channels[TARGET_MAX_CHANNELS]; + channeltarget_t channels[TARGET_MAX_CHANNELS]; int sessions[TARGET_MAX_SESSIONS]; struct dlist node; } voicetarget_t; @@ -48,7 +54,8 @@ void Voicetarget_add_id(client_t *client, int targetId); void Voicetarget_del_id(client_t *client, int targetId); void Voicetarget_add_session(client_t *client, int targetId, int sessionId); -void Voicetarget_add_channel(client_t *client, int targetId, int channelId); +void Voicetarget_add_channel(client_t *client, int targetId, int channelId, + bool_t linked, bool_t children); voicetarget_t *Voicetarget_get_id(client_t *client, int targetId); void Voicetarget_free_all(client_t *client); -- 2.30.2