aboutsummaryrefslogtreecommitdiffstats
path: root/code/server
diff options
context:
space:
mode:
authoricculus <icculus@edf5b092-35ff-0310-97b2-ce42778d08ea>2008-06-01 07:51:23 +0000
committericculus <icculus@edf5b092-35ff-0310-97b2-ce42778d08ea>2008-06-01 07:51:23 +0000
commit10afaeef337e0d19b37cb7dbe3fccee48bf18a43 (patch)
tree365da78a39bf90a8321da9f9bbf554ff5733eae6 /code/server
parent94017ca419caff91bf26841b503b5867d992ca4c (diff)
downloadioquake3-aero-10afaeef337e0d19b37cb7dbe3fccee48bf18a43.tar.gz
ioquake3-aero-10afaeef337e0d19b37cb7dbe3fccee48bf18a43.zip
Initial patch for in-game VoIP support!
git-svn-id: svn://svn.icculus.org/quake3/trunk@1348 edf5b092-35ff-0310-97b2-ce42778d08ea
Diffstat (limited to 'code/server')
-rw-r--r--code/server/server.h30
-rw-r--r--code/server/sv_client.c202
-rw-r--r--code/server/sv_init.c3
-rw-r--r--code/server/sv_main.c8
-rw-r--r--code/server/sv_snapshot.c4
5 files changed, 247 insertions, 0 deletions
diff --git a/code/server/server.h b/code/server/server.h
index 3d03aee..61fd882 100644
--- a/code/server/server.h
+++ b/code/server/server.h
@@ -33,6 +33,18 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define MAX_ENT_CLUSTERS 16
+#if USE_VOIP
+typedef struct voipServerPacket_s
+{
+ int generation;
+ int sequence;
+ int frames;
+ int len;
+ int sender;
+ byte data[1024];
+} voipServerPacket_t;
+#endif
+
typedef struct svEntity_s {
struct worldSector_s *worldSector;
struct svEntity_s *nextEntityInWorldSector;
@@ -167,6 +179,14 @@ typedef struct client_s {
netchan_buffer_t *netchan_start_queue;
netchan_buffer_t **netchan_end_queue;
+#if USE_VOIP
+ qboolean hasVoip;
+ qboolean muteAllVoip;
+ qboolean ignoreVoipFromClient[MAX_CLIENTS];
+ voipServerPacket_t voipPacket[64]; // !!! FIXME: WAY too much memory!
+ int queuedVoipPackets;
+#endif
+
int oldServerTime;
qboolean csUpdated[MAX_CONFIGSTRINGS+1];
} client_t;
@@ -264,6 +284,11 @@ extern cvar_t *sv_strictAuth;
extern serverBan_t serverBans[SERVER_MAXBANS];
extern int serverBansCount;
+#if USE_VOIP
+extern cvar_t *sv_voip;
+#endif
+
+
//===========================================================
//
@@ -320,6 +345,11 @@ void SV_ClientThink (client_t *cl, usercmd_t *cmd);
void SV_WriteDownloadToClient( client_t *cl , msg_t *msg );
+#if USE_VOIP
+void SV_WriteVoipToClient( client_t *cl, msg_t *msg );
+#endif
+
+
//
// sv_ccmds.c
//
diff --git a/code/server/sv_client.c b/code/server/sv_client.c
index c9915b9..6f932d1 100644
--- a/code/server/sv_client.c
+++ b/code/server/sv_client.c
@@ -1083,6 +1083,50 @@ void SV_WriteDownloadToClient( client_t *cl , msg_t *msg )
}
}
+#if USE_VOIP
+/*
+==================
+SV_WriteVoipToClient
+
+Check to see if there is any VoIP queued for a client, and send if there is.
+==================
+*/
+void SV_WriteVoipToClient( client_t *cl, msg_t *msg )
+{
+ voipServerPacket_t *packet = &cl->voipPacket[0];
+ int totalbytes = 0;
+ int i;
+
+ if (*cl->downloadName) {
+ cl->queuedVoipPackets = 0;
+ return; // no VoIP allowed if download is going, to save bandwidth.
+ }
+
+ // Write as many VoIP packets as we reasonably can...
+ for (i = 0; i < cl->queuedVoipPackets; i++, packet++) {
+ totalbytes += packet->len;
+ if (totalbytes > MAX_DOWNLOAD_BLKSIZE)
+ break;
+
+ MSG_WriteByte( msg, svc_voip );
+ MSG_WriteShort( msg, packet->sender );
+ MSG_WriteByte( msg, (byte) packet->generation );
+ MSG_WriteLong( msg, packet->sequence );
+ MSG_WriteByte( msg, packet->frames );
+ MSG_WriteShort( msg, packet->len );
+ MSG_WriteData( msg, packet->data, packet->len );
+ }
+
+ // !!! FIXME: I hate this queue system.
+ cl->queuedVoipPackets -= i;
+ if (cl->queuedVoipPackets > 0) {
+ memmove( &cl->voipPacket[0], &cl->voipPacket[i],
+ sizeof (voipServerPacket_t) * i);
+ }
+}
+#endif
+
+
/*
=================
SV_Disconnect_f
@@ -1326,6 +1370,11 @@ void SV_UserinfoChanged( client_t *cl ) {
cl->snapshotMsec = 50;
}
+#if USE_VOIP
+ val = Info_ValueForKey (cl->userinfo, "voip");
+ cl->hasVoip = (strlen(val) && atoi(val)) ? qtrue : qfalse;
+#endif
+
// TTimo
// maintain the IP information
// the banning code relies on this being consistently present
@@ -1361,6 +1410,39 @@ static void SV_UpdateUserinfo_f( client_t *cl ) {
VM_Call( gvm, GAME_CLIENT_USERINFO_CHANGED, cl - svs.clients );
}
+
+#if USE_VOIP
+static
+void SV_UpdateVoipIgnore(client_t *cl, const char *idstr, qboolean ignore)
+{
+ if ((*idstr >= '0') && (*idstr <= '9')) {
+ const int id = atoi(idstr);
+ if ((id >= 0) && (id < MAX_CLIENTS)) {
+ cl->ignoreVoipFromClient[id] = ignore;
+ }
+ }
+}
+
+/*
+==================
+SV_UpdateUserinfo_f
+==================
+*/
+static void SV_Voip_f( client_t *cl ) {
+ const char *cmd = Cmd_Argv(1);
+ if (strcmp(cmd, "ignore") == 0) {
+ SV_UpdateVoipIgnore(cl, Cmd_Argv(2), qtrue);
+ } else if (strcmp(cmd, "unignore") == 0) {
+ SV_UpdateVoipIgnore(cl, Cmd_Argv(2), qfalse);
+ } else if (strcmp(cmd, "muteall") == 0) {
+ cl->muteAllVoip = qtrue;
+ } else if (strcmp(cmd, "unmuteall") == 0) {
+ cl->muteAllVoip = qfalse;
+ }
+}
+#endif
+
+
typedef struct {
char *name;
void (*func)( client_t *cl );
@@ -1376,6 +1458,10 @@ static ucmd_t ucmds[] = {
{"stopdl", SV_StopDownload_f},
{"donedl", SV_DoneDownload_f},
+#if USE_VOIP
+ {"voip", SV_Voip_f},
+#endif
+
{NULL, NULL}
};
@@ -1596,6 +1682,118 @@ static void SV_UserMove( client_t *cl, msg_t *msg, qboolean delta ) {
}
+#if USE_VOIP
+static
+qboolean SV_ShouldIgnoreVoipSender(const client_t *cl)
+{
+ if (!sv_voip->integer)
+ return qtrue; // VoIP disabled on this server.
+ else if (!cl->hasVoip) // client doesn't have VoIP support?!
+ return qtrue;
+
+ // !!! FIXME: implement player blacklist.
+
+ return qfalse; // don't ignore.
+}
+
+static
+void SV_UserVoip( client_t *cl, msg_t *msg ) {
+ const int sender = (int) (cl - svs.clients);
+ const int generation = MSG_ReadByte(msg);
+ const int sequence = MSG_ReadLong(msg);
+ const int frames = MSG_ReadByte(msg);
+ const int recip1 = MSG_ReadLong(msg);
+ const int recip2 = MSG_ReadLong(msg);
+ const int recip3 = MSG_ReadLong(msg);
+ const int packetsize = MSG_ReadShort(msg);
+ byte encoded[sizeof (cl->voipPacket[0].data)];
+ client_t *client = NULL;
+ voipServerPacket_t *packet = NULL;
+ int i;
+
+ if (generation < 0)
+ return; // short/invalid packet, bail.
+ else if (sequence < 0)
+ return; // short/invalid packet, bail.
+ else if (frames < 0)
+ return; // short/invalid packet, bail.
+ else if (recip1 < 0)
+ return; // short/invalid packet, bail.
+ else if (recip2 < 0)
+ return; // short/invalid packet, bail.
+ else if (recip3 < 0)
+ return; // short/invalid packet, bail.
+ else if (packetsize < 0)
+ return; // short/invalid packet, bail.
+
+ if (packetsize > sizeof (encoded)) { // overlarge packet?
+ int bytesleft = packetsize;
+ while (bytesleft) {
+ int br = bytesleft;
+ if (br > sizeof (encoded))
+ br = sizeof (encoded);
+ MSG_ReadData(msg, encoded, br);
+ bytesleft -= br;
+ }
+ return; // overlarge packet, bail.
+ }
+
+ MSG_ReadData(msg, encoded, packetsize);
+
+ if (SV_ShouldIgnoreVoipSender(cl))
+ return; // Blacklisted, disabled, etc.
+
+ // !!! FIXME: see if we read past end of msg...
+
+ // !!! FIXME: reject if not speex narrowband codec.
+ // !!! FIXME: decide if this is bogus data?
+
+ // (the three recip* values are 31 bits each (ignores sign bit so we can
+ // get a -1 error from MSG_ReadLong() ... ), allowing for 93 clients.)
+ assert( sv_maxclients->integer < 93 );
+
+ // decide who needs this VoIP packet sent to them...
+ for (i = 0, client = svs.clients; i < sv_maxclients->integer ; i++, client++) {
+ if (client->state != CS_ACTIVE)
+ continue; // not in the game yet, don't send to this guy.
+ else if (i == sender)
+ continue; // don't send voice packet back to original author.
+ else if (!client->hasVoip)
+ continue; // no VoIP support, or support disabled.
+ else if (client->muteAllVoip)
+ continue; // client is ignoring everyone.
+ else if (client->ignoreVoipFromClient[sender])
+ continue; // client is ignoring this talker.
+ else if (*cl->downloadName) // !!! FIXME: possible to DoS?
+ continue; // no VoIP allowed if downloading, to save bandwidth.
+ else if ( ((i >= 0) && (i < 31)) && ((recip1 & (1 << (i-0))) == 0) )
+ continue; // not addressed to this player.
+ else if ( ((i >= 31) && (i < 62)) && ((recip2 & (1 << (i-31))) == 0) )
+ continue; // not addressed to this player.
+ else if ( ((i >= 62) && (i < 93)) && ((recip3 & (1 << (i-62))) == 0) )
+ continue; // not addressed to this player.
+
+ // Transmit this packet to the client.
+ // !!! FIXME: I don't like this queueing system.
+ if (client->queuedVoipPackets >= (sizeof (client->voipPacket) / sizeof (client->voipPacket[0]))) {
+ Com_Printf("Too many VoIP packets queued for client #%d\n", i);
+ continue; // no room for another packet right now.
+ }
+
+ packet = &client->voipPacket[client->queuedVoipPackets];
+ packet->sender = sender;
+ packet->frames = frames;
+ packet->len = packetsize;
+ packet->generation = generation;
+ packet->sequence = sequence;
+ memcpy(packet->data, encoded, packetsize);
+ client->queuedVoipPackets++;
+ }
+}
+#endif
+
+
+
/*
===========================================================================
@@ -1699,6 +1897,10 @@ void SV_ExecuteClientMessage( client_t *cl, msg_t *msg ) {
SV_UserMove( cl, msg, qtrue );
} else if ( c == clc_moveNoDelta ) {
SV_UserMove( cl, msg, qfalse );
+#if USE_VOIP
+ } else if ( c == clc_voip ) {
+ SV_UserVoip( cl, msg );
+#endif
} else if ( c != clc_EOF ) {
Com_Printf( "WARNING: bad command byte for client %i\n", (int) (cl - svs.clients) );
}
diff --git a/code/server/sv_init.c b/code/server/sv_init.c
index aca7691..d46f273 100644
--- a/code/server/sv_init.c
+++ b/code/server/sv_init.c
@@ -654,6 +654,9 @@ void SV_Init (void) {
Cvar_Get ("sv_cheats", "1", CVAR_SYSTEMINFO | CVAR_ROM );
sv_serverid = Cvar_Get ("sv_serverid", "0", CVAR_SYSTEMINFO | CVAR_ROM );
sv_pure = Cvar_Get ("sv_pure", "1", CVAR_SYSTEMINFO );
+#if USE_VOIP
+ sv_voip = Cvar_Get ("sv_voip", "1", CVAR_SYSTEMINFO );
+#endif
Cvar_Get ("sv_paks", "", CVAR_SYSTEMINFO | CVAR_ROM );
Cvar_Get ("sv_pakNames", "", CVAR_SYSTEMINFO | CVAR_ROM );
Cvar_Get ("sv_referencedPaks", "", CVAR_SYSTEMINFO | CVAR_ROM );
diff --git a/code/server/sv_main.c b/code/server/sv_main.c
index 552c12b..a12da03 100644
--- a/code/server/sv_main.c
+++ b/code/server/sv_main.c
@@ -22,6 +22,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "server.h"
+#if USE_VOIP
+cvar_t *sv_voip;
+#endif
+
serverStatic_t svs; // persistant server info
server_t sv; // local server
vm_t *gvm = NULL; // game virtual machine
@@ -407,6 +411,10 @@ void SVC_Info( netadr_t from ) {
Info_SetValueForKey( infostring, "gametype", va("%i", sv_gametype->integer ) );
Info_SetValueForKey( infostring, "pure", va("%i", sv_pure->integer ) );
+#if USE_VOIP
+ Info_SetValueForKey( infostring, "voip", va("%i", sv_voip->integer ) );
+#endif
+
if( sv_minPing->integer ) {
Info_SetValueForKey( infostring, "minPing", va("%i", sv_minPing->integer) );
}
diff --git a/code/server/sv_snapshot.c b/code/server/sv_snapshot.c
index 80b6af4..71fdc8b 100644
--- a/code/server/sv_snapshot.c
+++ b/code/server/sv_snapshot.c
@@ -653,6 +653,10 @@ void SV_SendClientSnapshot( client_t *client ) {
// Add any download data if the client is downloading
SV_WriteDownloadToClient( client, &msg );
+#if USE_VOIP
+ SV_WriteVoipToClient( client, &msg );
+#endif
+
// check for overflow
if ( msg.overflowed ) {
Com_Printf ("WARNING: msg overflowed for %s\n", client->name);