Fix for:
authorfatbob313 <martin@fatbob.nu>
Sun, 7 Feb 2010 14:48:55 +0000 (14:48 +0000)
committerfatbob313 <martin@fatbob.nu>
Sun, 7 Feb 2010 14:48:55 +0000 (14:48 +0000)
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
src/channel.h
src/client.c
src/client.h
src/messagehandler.c
src/messages.c
src/messages.h
src/voicetarget.c
src/voicetarget.h

index c3ddda8377ed939b211778e153b3094498643a70..4de6490329e73b578c8fa54772fe6053cee9487f 100644 (file)
@@ -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));
+       }
+}
index c092c56b46c9b809ec87c8a3917075a02952af0c..e20bfad6ec9919c0e266010eddcef6d707208904 100644 (file)
@@ -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
index 9f09c2a83c16c870636550cbd13427a22491bb74..b72e46f06443952139d1588bb3763486b67f8c78 100644 (file)
@@ -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;
index a7d43f0bbb42d108de343ad1d9535aebc572f7e1..f7b88c492993a65144357151ead09a8f22990ada 100644 (file)
@@ -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;
index b1a55fbcf96a04f60e44ee7271b830f0fa143e26..98a9953b2996256e351a6619b534c38cff8b1d84 100644 (file)
@@ -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:
index 09ec927378c603f6ae3ca29a115afa985b186242..109f5eb22af6c8844262678e5519e676ef78f73f 100644 (file)
 
 #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:
index 9aebc4b6574f8066b8bd957f708b1d5f2a3d6f95..9fde9f9ab2cf739551147723866a4f6611e502ae 100644 (file)
@@ -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
index 935139fd2fb8c7080e9773771bb5be5a3e46af8f..85c26076384a45469db99ca3ad1ad1275eec2339 100644 (file)
@@ -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;
index 0d2f05106d0c5da0acb58813cbf5efa0daeca5c2..1bd2d17961e53cb310912f2557ecff2be4837f7b 100644 (file)
 #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);