Initial patch for in-game VoIP support!

This commit is contained in:
Ryan C. Gordon 2008-06-01 07:51:23 +00:00
parent 0ee3960225
commit 12326a9eac
19 changed files with 1185 additions and 127 deletions

View file

@ -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) );
}