Added voice target (whisper) functionality.
authorfatbob313 <martin@fatbob.nu>
Wed, 6 Jan 2010 14:57:42 +0000 (14:57 +0000)
committerfatbob313 <martin@fatbob.nu>
Wed, 6 Jan 2010 14:57:42 +0000 (14:57 +0000)
src/client.c
src/client.h
src/messagehandler.c
src/voicetarget.c [new file with mode: 0644]
src/voicetarget.h [new file with mode: 0644]

index 2b8934594f68240068e80591df19931a26ff3548..7cc4d0c475d0cbf72f8fba959713c9b3724b6544 100644 (file)
@@ -40,6 +40,7 @@
 #include "conf.h"
 #include "channel.h"
 #include "version.h"
+#include "voicetarget.h"
 
 static int Client_read(client_t *client);
 static int Client_write(client_t *client);
@@ -105,7 +106,7 @@ void Client_janitor()
 void recheckCodecVersions()
 {
        int codec_map[MAX_CODECS][2];
-       client_t *itr;
+       client_t *itr = NULL;
        int i, codecindex, max = 0, version, current_version;
        message_t *sendmsg;
        
@@ -113,15 +114,16 @@ void recheckCodecVersions()
        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)
+                               if (codec_map[codecindex][0] == 0) {
                                        codec_map[codecindex][0] = itr->codecs[i];
+                                       codec_map[codecindex][1] = 1;
+                                       break;
+                               }
                                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;
@@ -183,6 +185,7 @@ int Client_add(int fd, struct sockaddr_in *remote)
        init_list_entry(&newclient->txMsgQueue);
        init_list_entry(&newclient->chan_node);
        init_list_entry(&newclient->node);
+       init_list_entry(&newclient->voicetargets);
        
        list_add_tail(&newclient->node, &clients);
        clientcount++;
@@ -218,7 +221,8 @@ void Client_free(client_t *client)
                list_del(&list_get_entry(itr, message_t, node)->node);
                Msg_free(list_get_entry(itr, message_t, node));
        }
-               
+       Voicetarget_free_all(client);
+       
        list_del(&client->node);
        list_del(&client->chan_node);
        if (client->ssl)
@@ -255,7 +259,7 @@ int Client_read_fd(int fd)
        client_t *client = NULL;
        
        list_iterate(itr, &clients) {
-               if(fd == list_get_entry(itr, client_t, node)->tcpfd) {
+               if (fd == list_get_entry(itr, client_t, node)->tcpfd) {
                        client = list_get_entry(itr, client_t, node);
                        break;
                }
@@ -583,6 +587,7 @@ int Client_read_udp()
                Client_voiceMsg(itr, buffer, len);
                break;
        case UDPPing:
+               Log_debug("UDP Ping reply len %d", len);
                Client_send_udp(itr, buffer, len);
                break;
        default:
@@ -603,7 +608,8 @@ int Client_voiceMsg(client_t *client, uint8_t *data, int len)
        unsigned int target = data[0] & 0x1f;
        unsigned int poslen, counter;
        int offset, packetsize;
-
+       voicetarget_t *vt;
+       
        channel_t *ch = (channel_t *)client->channel;
        struct dlist *itr;
        
@@ -626,7 +632,7 @@ int Client_voiceMsg(client_t *client, uint8_t *data, int len)
        Pds_add_numval(pds, client->sessionId);
        Pds_append_data_nosize(pds, data + 1, len - 1);
        
-       if (target & 0x1f) { /* Loopback */
+       if (target == 0x1f) { /* Loopback */
                buffer[0] = (uint8_t) type;
                Client_send_udp(client, buffer, pds->offset + 1);
        }
@@ -643,8 +649,35 @@ int Client_voiceMsg(client_t *client, uint8_t *data, int len)
                                Client_send_udp(c, buffer, pds->offset + 1);
                        }
                }
+       } 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++) {
+                       Log_debug("Whisper channel %d", vt->channels[i]);
+                       ch = Chan_fromId(vt->channels[i]);
+                       if (ch == NULL)
+                               continue;
+                       list_iterate(itr, &ch->clients) {
+                               client_t *c;
+                               c = list_get_entry(itr, client_t, chan_node);
+                               if (c != client && !c->deaf && IS_AUTH(c)) {
+                                       Client_send_udp(c, buffer, pds->offset + 1);
+                               }
+                       }
+               }                       
+               /* Sessions */
+               for (i = 0; i < TARGET_MAX_SESSIONS && vt->sessions[i] != -1; i++) {
+                       client_t *c;
+                       Log_debug("Whisper session %d", vt->sessions[i]);
+                       while (Client_iterate(&c) != NULL) {
+                               if (c->sessionId == vt->sessions[i] && c != client && !c->deaf && IS_AUTH(c)) {
+                                       Client_send_udp(c, buffer, pds->offset + 1);
+                                       break;
+                               }
+                       }
+               }
        }
-       /* XXX - Add targeted whisper here */
 out:
        Pds_free(pds);
        Pds_free(pdi);
index ba2082f9b52b71ca91229133c824da441bc44b58..081c99e3a0020837617e0fbd128c2ba02c179da5 100644 (file)
@@ -83,6 +83,7 @@ typedef struct {
        /* Channel */
        void *channel; /*Ugly... */
        struct dlist chan_node;
+       struct dlist voicetargets;
 } client_t;
 
 
index d0c24e98d3a91cd5ed904a762e6523636cb4bbed..189588ec0f5a4163d624bf8b4fbe8cccf4e772bc 100644 (file)
@@ -38,6 +38,7 @@
 #include "crypt.h"
 #include "channel.h"
 #include "conf.h"
+#include "voicetarget.h"
 
 extern channel_t *defaultChan;
 extern int iCodecAlpha, iCodecBeta;
@@ -380,9 +381,28 @@ void Mh_handle_message(client_t *client, message_t *msg)
                break;
 
        case VoiceTarget:
-               /* XXX -TODO */
-               break;
+       {
+               int i, j, count, targetId = msg->payload.voiceTarget->id;
+               struct _MumbleProto__VoiceTarget__Target *target;
 
+               if (!targetId || targetId >= 0x1f)
+                       break;
+               Voicetarget_add_id(client, targetId);
+               count = msg->payload.voiceTarget->n_targets;
+               if (!count)
+                       break;
+               for (i = 0; i < count; i++) {
+                       target = msg->payload.voiceTarget->targets[i];
+                       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);
+                       }
+               }
+               break;
+       }
        case Version:
                Log_debug("Version message received");
                if (msg->payload.version->has_version) {
@@ -417,6 +437,8 @@ void Mh_handle_message(client_t *client, message_t *msg)
        case ContextActionAdd:
        case ACL:
        case BanList:
+       case UserList:
+       case QueryUsers:
                sendPermissionDenied(client, "Not supported by uMurmur");
                break;
                                
diff --git a/src/voicetarget.c b/src/voicetarget.c
new file mode 100644 (file)
index 0000000..3a8e0fd
--- /dev/null
@@ -0,0 +1,125 @@
+/* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
+   Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
+
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright notice,
+     this list of conditions and the following disclaimer.
+   - Redistributions in binary form must reproduce the above copyright notice,
+     this list of conditions and the following disclaimer in the documentation
+     and/or other materials provided with the distribution.
+   - Neither the name of the Developers nor the names of its contributors may
+     be used to endorse or promote products derived from this software without
+     specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "voicetarget.h"
+#include "log.h"
+
+void Voicetarget_add_session(client_t *client, int targetId, int sessionId)
+{
+       struct dlist *itr;
+       voicetarget_t *vt;
+       
+       list_iterate(itr, &client->voicetargets) {
+               if (targetId == list_get_entry(itr, voicetarget_t, node)->id) {
+                       int i;
+                       vt = list_get_entry(itr, voicetarget_t, node);
+                       for (i = 0; i < TARGET_MAX_SESSIONS; i++) {
+                               if (vt->sessions[i] == -1) {
+                                       vt->sessions[i] = sessionId;
+                                       Log_debug("Adding session ID %d to voicetarget ID %d", sessionId, targetId);
+                                       return;
+                               }
+                       }
+               }
+       }
+}
+
+void Voicetarget_add_channel(client_t *client, int targetId, int channelId)
+{
+       struct dlist *itr;
+       voicetarget_t *vt;
+       
+       list_iterate(itr, &client->voicetargets) {
+               if (targetId == list_get_entry(itr, voicetarget_t, node)->id) {
+                       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;
+                                       Log_debug("Adding channel ID %d to voicetarget ID %d", channelId, targetId);
+                                       return;
+                               }
+                       }
+               }
+       }       
+}
+
+void Voicetarget_add_id(client_t *client, int targetId)
+{
+       voicetarget_t *newtarget;
+       int i;
+       
+       Voicetarget_del_id(client, targetId);
+       newtarget = malloc(sizeof(voicetarget_t));
+       if (!newtarget)
+               Log_fatal("Out of memory");
+       memset(newtarget, 0, sizeof(voicetarget_t));
+       for (i = 0; i < TARGET_MAX_CHANNELS; i++)
+               newtarget->channels[i] = -1;
+       for (i = 0; i < TARGET_MAX_SESSIONS; i++)
+               newtarget->sessions[i] = -1;
+       newtarget->id = targetId;
+       list_add_tail(&newtarget->node, &client->voicetargets);
+}
+
+void Voicetarget_del_id(client_t *client, int targetId)
+{
+       struct dlist *itr;
+       list_iterate(itr, &client->voicetargets) {
+               if (targetId == list_get_entry(itr, voicetarget_t, node)->id) {
+                       list_del(&list_get_entry(itr, voicetarget_t, node)->node);
+                       free(list_get_entry(itr, voicetarget_t, node));
+                       Log_debug("Removing voicetarget ID %d", targetId);
+               }
+       }
+}
+
+voicetarget_t *Voicetarget_get_id(client_t *client, int targetId)
+{
+       struct dlist *itr;
+       list_iterate(itr, &client->voicetargets) {
+               if (targetId == list_get_entry(itr, voicetarget_t, node)->id) {
+                       return list_get_entry(itr, voicetarget_t, node);
+               }
+       }
+       return NULL;
+}
+
+
+void Voicetarget_free_all(client_t *client)
+{
+       struct dlist *itr, *save;
+
+       list_iterate_safe(itr, save, &client->voicetargets) {
+               list_del(&list_get_entry(itr, voicetarget_t, node)->node);
+               free(list_get_entry(itr, voicetarget_t, node));
+       }
+}
diff --git a/src/voicetarget.h b/src/voicetarget.h
new file mode 100644 (file)
index 0000000..fa8af04
--- /dev/null
@@ -0,0 +1,57 @@
+/* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
+   Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
+
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright notice,
+     this list of conditions and the following disclaimer.
+   - Redistributions in binary form must reproduce the above copyright notice,
+     this list of conditions and the following disclaimer in the documentation
+     and/or other materials provided with the distribution.
+   - Neither the name of the Developers nor the names of its contributors may
+     be used to endorse or promote products derived from this software without
+     specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef VOICETARGET_H_98762439875
+#define VOICETARGET_H_98762439875
+
+#include "client.h"
+#include "list.h"
+
+#define TARGET_MAX_CHANNELS 16
+#define TARGET_MAX_SESSIONS 32
+
+typedef struct {
+       int id;
+       int channels[TARGET_MAX_CHANNELS];
+       int sessions[TARGET_MAX_SESSIONS];
+       struct dlist node;
+} voicetarget_t;
+
+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);
+voicetarget_t *Voicetarget_get_id(client_t *client, int targetId);
+
+void Voicetarget_free_all(client_t *client);
+
+
+#endif