2
0
mirror of https://github.com/rehlds/revoice.git synced 2025-01-15 08:08:01 +03:00

Added voice rate limiter

This commit is contained in:
asmodai 2015-12-15 00:50:47 +03:00
parent 639e79e766
commit fec9126f34
6 changed files with 86 additions and 30 deletions

View File

@ -32,7 +32,7 @@ int CSteamP2PCodec::StreamDecode(const char *pCompressed, int compressedBytes, c
readPos += 2; readPos += 2;
break; break;
case 0x04: //Voice payoad case 0x04: //Voice payload
{ {
if (readPos + 2 > maxReadPos) { if (readPos + 2 > maxReadPos) {
return 0; return 0;

View File

@ -5,7 +5,7 @@ cvar_t* pcv_sv_voiceenable = NULL;
void Rehlds_ClientConnected_Hook(IRehldsHook_ClientConnected* chain, IGameClient* cl) { void Rehlds_ClientConnected_Hook(IRehldsHook_ClientConnected* chain, IGameClient* cl) {
int protocol = g_ReunionApi->GetClientProtocol(cl->GetId()); int protocol = g_ReunionApi->GetClientProtocol(cl->GetId());
if (protocol >= 47 && protocol <= 48) { if (protocol == 47 || protocol == 48) {
CRevoicePlayer* plr = GetPlayerByClientPtr(cl); CRevoicePlayer* plr = GetPlayerByClientPtr(cl);
plr->OnConnected(protocol); plr->OnConnected(protocol);
@ -21,7 +21,7 @@ void Rehlds_ClientConnected_Hook(IRehldsHook_ClientConnected* chain, IGameClient
void SV_DropClient_hook(IRehldsHook_SV_DropClient* chain, IGameClient* cl, bool crash, const char* msg) { void SV_DropClient_hook(IRehldsHook_SV_DropClient* chain, IGameClient* cl, bool crash, const char* msg) {
CRevoicePlayer* plr = GetPlayerByClientPtr(cl); CRevoicePlayer* plr = GetPlayerByClientPtr(cl);
plr->OnDisconected(); plr->OnDisconnected();
chain->callNext(cl, crash, msg); chain->callNext(cl, crash, msg);
} }
@ -54,7 +54,6 @@ int TranscodeVoice(const char* srcBuf, int srcBufLen, IVoiceCodec* srcCodec, IVo
return 0; return 0;
} }
int compressedSize = dstCodec->Compress(decodedBuf, numDecodedSamples, dstBuf, dstBufSize, false); int compressedSize = dstCodec->Compress(decodedBuf, numDecodedSamples, dstBuf, dstBufSize, false);
if (compressedSize <= 0) { if (compressedSize <= 0) {
return 0; return 0;
@ -77,25 +76,23 @@ int TranscodeVoice(const char* srcBuf, int srcBufLen, IVoiceCodec* srcCodec, IVo
} }
void SV_ParseVoiceData_emu(IGameClient* cl) { void SV_ParseVoiceData_emu(IGameClient* cl) {
if (pcv_sv_voiceenable->value == 0.0f) if (pcv_sv_voiceenable->value == 0.0f) {
return; return;
}
char chReceived[4096]; char chReceived[4096];
unsigned int nDataLength = g_RehldsFuncs->MSG_ReadShort(); unsigned int nDataLength = g_RehldsFuncs->MSG_ReadShort();
if (nDataLength > sizeof(chReceived)) if (nDataLength > sizeof(chReceived)) {
{
g_RehldsFuncs->DropClient(cl, FALSE, "Invalid voice data\n"); g_RehldsFuncs->DropClient(cl, FALSE, "Invalid voice data\n");
return; return;
} }
g_RehldsFuncs->MSG_ReadBuf(nDataLength, chReceived); g_RehldsFuncs->MSG_ReadBuf(nDataLength, chReceived);
//cl->m_lastvoicetime = g_RehldsSv->GetTime();
CRevoicePlayer* srcPlayer = GetPlayerByClientPtr(cl); CRevoicePlayer* srcPlayer = GetPlayerByClientPtr(cl);
if (srcPlayer->GetCodecType() == vct_none) { srcPlayer->SetLastVoiceTime(g_RehldsSv->GetTime());
return; srcPlayer->IncreaseVoiceRate(nDataLength);
}
char transcodedBuf[4096]; char transcodedBuf[4096];
char* speexData; int speexDataLen; char* speexData; int speexDataLen;
@ -104,6 +101,9 @@ void SV_ParseVoiceData_emu(IGameClient* cl) {
switch (srcPlayer->GetCodecType()) { switch (srcPlayer->GetCodecType()) {
case vct_silk: case vct_silk:
{ {
//if (nDataLength > MAX_SILK_DATA_LEN || srcPlayer->GetVoiceRate() > MAX_SILK_VOICE_RATE)
//return;
silkData = chReceived; silkDataLen = nDataLength; silkData = chReceived; silkDataLen = nDataLength;
speexData = transcodedBuf; speexData = transcodedBuf;
speexDataLen = TranscodeVoice(silkData, silkDataLen, srcPlayer->GetSilkCodec(), srcPlayer->GetSpeexCodec(), transcodedBuf, sizeof(transcodedBuf)); speexDataLen = TranscodeVoice(silkData, silkDataLen, srcPlayer->GetSilkCodec(), srcPlayer->GetSpeexCodec(), transcodedBuf, sizeof(transcodedBuf));
@ -111,6 +111,9 @@ void SV_ParseVoiceData_emu(IGameClient* cl) {
} }
case vct_speex: case vct_speex:
//if (nDataLength > MAX_SPEEX_DATA_LEN || srcPlayer->GetVoiceRate() > MAX_SPEEX_VOICE_RATE)
//return;
speexData = chReceived; speexDataLen = nDataLength; speexData = chReceived; speexDataLen = nDataLength;
silkData = transcodedBuf; silkData = transcodedBuf;
silkDataLen = TranscodeVoice(speexData, speexDataLen, srcPlayer->GetSpeexCodec(), srcPlayer->GetSilkCodec(), transcodedBuf, sizeof(transcodedBuf)); silkDataLen = TranscodeVoice(speexData, speexDataLen, srcPlayer->GetSpeexCodec(), srcPlayer->GetSilkCodec(), transcodedBuf, sizeof(transcodedBuf));
@ -120,14 +123,16 @@ void SV_ParseVoiceData_emu(IGameClient* cl) {
return; return;
} }
for (int i = 0; i < g_RehldsSvs->GetMaxClients(); i++) { int maxclients = g_RehldsSvs->GetMaxClients();
for (int i = 0; i < maxclients; i++) {
CRevoicePlayer* dstPlayer = &g_Players[i]; CRevoicePlayer* dstPlayer = &g_Players[i];
IGameClient* dstClient = dstPlayer->GetClient(); IGameClient* dstClient = dstPlayer->GetClient();
if (!((1 << (i & 0x1F)) & cl->GetVoiceStream(i >> 5)) && i != cl->GetId()) if (!((1 << i) & cl->GetVoiceStream(0)) && dstPlayer != srcPlayer)
continue; continue;
if (!dstClient->IsActive() && !dstClient->IsConnected() && i != cl->GetId()) if (!dstClient->IsActive() && !dstClient->IsConnected() && dstPlayer != srcPlayer)
continue; continue;
char* sendBuf; int nSendLen; char* sendBuf; int nSendLen;
@ -146,17 +151,15 @@ void SV_ParseVoiceData_emu(IGameClient* cl) {
break; break;
} }
if (sendBuf == NULL || nSendLen == 0) { if (sendBuf == NULL || nSendLen == 0)
continue; continue;
}
if (i == cl->GetId() && !dstClient->GetLoopback()) if (dstPlayer == srcPlayer && !dstClient->GetLoopback())
nSendLen = 0; nSendLen = 0;
sizebuf_t* dstDatagram = dstClient->GetDatagram(); sizebuf_t* dstDatagram = dstClient->GetDatagram();
if (dstDatagram->cursize + nSendLen + 6 < dstDatagram->maxsize) if (dstDatagram->cursize + nSendLen + 6 < dstDatagram->maxsize) {
{ g_RehldsFuncs->MSG_WriteByte(dstDatagram, svc_voicedata); //svc_voicedata
g_RehldsFuncs->MSG_WriteByte(dstDatagram, 53); //svc_voicedata
g_RehldsFuncs->MSG_WriteByte(dstDatagram, cl->GetId()); g_RehldsFuncs->MSG_WriteByte(dstDatagram, cl->GetId());
g_RehldsFuncs->MSG_WriteShort(dstDatagram, nSendLen); g_RehldsFuncs->MSG_WriteShort(dstDatagram, nSendLen);
g_RehldsFuncs->MSG_WriteBuf(dstDatagram, nSendLen, sendBuf); g_RehldsFuncs->MSG_WriteBuf(dstDatagram, nSendLen, sendBuf);
@ -187,13 +190,13 @@ void SV_WriteVoiceCodec_hooked(IRehldsHook_SV_WriteVoiceCodec* chain, sizebuf_t*
switch (plr->GetCodecType()) { switch (plr->GetCodecType()) {
case vct_silk: case vct_silk:
g_RehldsFuncs->MSG_WriteByte(sb, 52); //svc_voiceinit g_RehldsFuncs->MSG_WriteByte(sb, svc_voiceinit); //svc_voiceinit
g_RehldsFuncs->MSG_WriteString(sb, ""); //codec id g_RehldsFuncs->MSG_WriteString(sb, ""); //codec id
g_RehldsFuncs->MSG_WriteByte(sb, 0); //quality g_RehldsFuncs->MSG_WriteByte(sb, 0); //quality
break; break;
case vct_speex: case vct_speex:
g_RehldsFuncs->MSG_WriteByte(sb, 52); //svc_voiceinit g_RehldsFuncs->MSG_WriteByte(sb, svc_voiceinit); //svc_voiceinit
g_RehldsFuncs->MSG_WriteString(sb, "voice_speex"); //codec id g_RehldsFuncs->MSG_WriteString(sb, "voice_speex"); //codec id
g_RehldsFuncs->MSG_WriteByte(sb, 5); //quality g_RehldsFuncs->MSG_WriteByte(sb, 5); //quality
break; break;

View File

@ -8,8 +8,8 @@ CRevoicePlayer::CRevoicePlayer() {
m_SpeexCodec = new VoiceCodec_Frame(new VoiceEncoder_Speex()); m_SpeexCodec = new VoiceCodec_Frame(new VoiceEncoder_Speex());
m_SilkCodec = new CSteamP2PCodec(new VoiceEncoder_Silk()); m_SilkCodec = new CSteamP2PCodec(new VoiceEncoder_Silk());
m_SpeexCodec->Init(5); m_SpeexCodec->Init(SPEEX_VOICE_QUALITY);
m_SilkCodec->Init(5); m_SilkCodec->Init(SILK_VOICE_QUALITY);
m_RehldsClient = NULL; m_RehldsClient = NULL;
m_Protocol = 0; m_Protocol = 0;
@ -28,11 +28,13 @@ void CRevoicePlayer::InitVoice(revoice_codec_type codecType) {
void CRevoicePlayer::OnConnected(int protocol) { void CRevoicePlayer::OnConnected(int protocol) {
m_Protocol = protocol; m_Protocol = protocol;
m_CodecType = vct_none; m_CodecType = vct_none;
m_VoiceRate = 0;
} }
void CRevoicePlayer::OnDisconected() { void CRevoicePlayer::OnDisconnected() {
m_Protocol = 0; m_Protocol = 0;
m_CodecType = vct_none; m_CodecType = vct_none;
m_VoiceRate = 0;
} }
void Revoice_Init_Players() { void Revoice_Init_Players() {
@ -55,3 +57,42 @@ CRevoicePlayer* GetPlayerByEdict(const edict_t* ed) {
return &g_Players[clientId]; return &g_Players[clientId];
} }
void CRevoicePlayer::SetLastVoiceTime(double time)
{
UpdateVoiceRate(time - m_RehldsClient->GetLastVoiceTime());
m_RehldsClient->SetLastVoiceTime(time);
}
void CRevoicePlayer::UpdateVoiceRate(double delta)
{
if (m_VoiceRate)
{
switch (m_CodecType)
{
case vct_silk:
m_VoiceRate -= int(delta * MAX_SILK_VOICE_RATE) + MAX_SILK_DATA_LEN;
break;
case vct_speex:
m_VoiceRate -= int(delta * MAX_SPEEX_VOICE_RATE) + MAX_SPEEX_DATA_LEN;
break;
default:
;
}
if (m_VoiceRate < 0)
m_VoiceRate = 0;
}
}
void CRevoicePlayer::IncreaseVoiceRate(int dataLength)
{
m_VoiceRate += dataLength;
}
int CRevoicePlayer::GetVoiceRate()
{
return m_VoiceRate;
}

View File

@ -14,13 +14,18 @@ private:
CSteamP2PCodec* m_SilkCodec; CSteamP2PCodec* m_SilkCodec;
VoiceCodec_Frame* m_SpeexCodec; VoiceCodec_Frame* m_SpeexCodec;
int m_Protocol; int m_Protocol;
int m_VoiceRate;
public: public:
CRevoicePlayer(); CRevoicePlayer();
void Initialize(IGameClient* cl); void Initialize(IGameClient* cl);
void OnConnected(int protocol); void OnConnected(int protocol);
void OnDisconected(); void OnDisconnected();
void InitVoice(revoice_codec_type codecType); void InitVoice(revoice_codec_type codecType);
void SetLastVoiceTime(double time);
void UpdateVoiceRate(double delta);
void IncreaseVoiceRate(int dataLength);
int GetVoiceRate();
int GetProtocol() const { return m_Protocol; } int GetProtocol() const { return m_Protocol; }
revoice_codec_type GetCodecType() const { return m_CodecType; } revoice_codec_type GetCodecType() const { return m_CodecType; }

View File

@ -3,13 +3,16 @@
#include "rehlds_api.h" #include "rehlds_api.h"
#define MAX_PLAYERS 32 #define MAX_PLAYERS 32
#define MAX_STEAMIDSALTLEN 64
#define LOG_PREFIX "[REVOICE]: " #define LOG_PREFIX "[REVOICE]: "
#define HLDS_APPID 10 #define MAX_SILK_DATA_LEN 650
#define HLDS_APPVERSION "1.1.2.7/Stdio" #define MAX_SPEEX_DATA_LEN 228
#define MAX_SILK_VOICE_RATE 3800
#define MAX_SPEEX_VOICE_RATE 2014
#define SILK_VOICE_QUALITY 5
#define SPEEX_VOICE_QUALITY 5
enum revoice_log_mode { enum revoice_log_mode {
rl_none = 0, rl_none = 0,
@ -23,6 +26,11 @@ enum revoice_codec_type {
vct_speex, vct_speex,
}; };
enum svc_messages {
svc_voiceinit = 52,
svc_voicedata = 53
};
template <typename T> template <typename T>
T _min(T a, T b) { T _min(T a, T b) {
return (a < b) ? a : b; return (a < b) ? a : b;

View File

@ -69,7 +69,6 @@ uint32 crc32(const void* buf, unsigned int bufLen) {
return hCrc; return hCrc;
} }
void util_syserror(const char* fmt, ...) void util_syserror(const char* fmt, ...)
{ {
va_list argptr; va_list argptr;