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++; } }
static void SV_UserVoip(client_t *cl, msg_t *msg) { int sender, generation, sequence, frames, packetsize; uint8_t recips[(MAX_CLIENTS + 7) / 8]; int flags; byte encoded[sizeof(cl->voipPacket[0]->data)]; client_t *client = NULL; voipServerPacket_t *packet = NULL; int i; sender = cl - svs.clients; generation = MSG_ReadByte(msg); sequence = MSG_ReadLong(msg); frames = MSG_ReadByte(msg); MSG_ReadData(msg, recips, sizeof(recips)); flags = MSG_ReadByte(msg); packetsize = MSG_ReadShort(msg); if (msg->readcount > msg->cursize) 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? // 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 unsupported protocol 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. if(Com_IsVoipTarget(recips, sizeof(recips), i)) flags |= VOIP_DIRECT; else flags &= ~VOIP_DIRECT; if (!(flags & (VOIP_SPATIAL | VOIP_DIRECT))) continue; // not addressed to this player. // Transmit this packet to the client. if (client->queuedVoipPackets >= ARRAY_LEN(client->voipPacket)) { Com_Printf("Too many VoIP packets queued for client #%d\n", i); continue; // no room for another packet right now. } packet = Z_Malloc(sizeof(*packet)); packet->sender = sender; packet->frames = frames; packet->len = packetsize; packet->generation = generation; packet->sequence = sequence; packet->flags = flags; memcpy(packet->data, encoded, packetsize); client->voipPacket[(client->queuedVoipIndex + client->queuedVoipPackets) % ARRAY_LEN(client->voipPacket)] = packet; client->queuedVoipPackets++; } }