From 325121a3901e190678f120d5b704ced4aff8cf7a Mon Sep 17 00:00:00 2001 From: fatbob313 Date: Wed, 6 Jan 2010 14:57:42 +0000 Subject: [PATCH] Added voice target (whisper) functionality. --- src/client.c | 51 ++++++++++++++---- src/client.h | 1 + src/messagehandler.c | 26 ++++++++- src/voicetarget.c | 125 +++++++++++++++++++++++++++++++++++++++++++ src/voicetarget.h | 57 ++++++++++++++++++++ 5 files changed, 249 insertions(+), 11 deletions(-) create mode 100644 src/voicetarget.c create mode 100644 src/voicetarget.h diff --git a/src/client.c b/src/client.c index 2b89345..7cc4d0c 100644 --- a/src/client.c +++ b/src/client.c @@ -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); diff --git a/src/client.h b/src/client.h index ba2082f..081c99e 100644 --- a/src/client.h +++ b/src/client.h @@ -83,6 +83,7 @@ typedef struct { /* Channel */ void *channel; /*Ugly... */ struct dlist chan_node; + struct dlist voicetargets; } client_t; diff --git a/src/messagehandler.c b/src/messagehandler.c index d0c24e9..189588e 100644 --- a/src/messagehandler.c +++ b/src/messagehandler.c @@ -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 index 0000000..3a8e0fd --- /dev/null +++ b/src/voicetarget.c @@ -0,0 +1,125 @@ +/* Copyright (C) 2009, Martin Johansson + Copyright (C) 2005-2009, Thorvald Natvig + + 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 index 0000000..fa8af04 --- /dev/null +++ b/src/voicetarget.h @@ -0,0 +1,57 @@ +/* Copyright (C) 2009, Martin Johansson + Copyright (C) 2005-2009, Thorvald Natvig + + 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 -- 2.30.2