#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);
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;
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;
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++;
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)
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;
}
Client_voiceMsg(itr, buffer, len);
break;
case UDPPing:
+ Log_debug("UDP Ping reply len %d", len);
Client_send_udp(itr, buffer, len);
break;
default:
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;
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);
}
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);
/* Channel */
void *channel; /*Ugly... */
struct dlist chan_node;
+ struct dlist voicetargets;
} client_t;
#include "crypt.h"
#include "channel.h"
#include "conf.h"
+#include "voicetarget.h"
extern channel_t *defaultChan;
extern int iCodecAlpha, iCodecBeta;
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) {
case ContextActionAdd:
case ACL:
case BanList:
+ case UserList:
+ case QueryUsers:
sendPermissionDenied(client, "Not supported by uMurmur");
break;
--- /dev/null
+/* 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));
+ }
+}
--- /dev/null
+/* 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