Initial patch for in-game VoIP support!
This commit is contained in:
parent
0ee3960225
commit
12326a9eac
19 changed files with 1185 additions and 127 deletions
|
@ -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) );
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue