the torchlight packets are now also checked before being send. hopefully it prevents buffer overflow. the packet size for players was also slightly increased

This commit is contained in:
jenz 2026-01-29 11:27:14 +00:00
parent b987a8207d
commit 59fbf67c4a
2 changed files with 26 additions and 15 deletions

View File

@ -53,7 +53,9 @@
// with 22050 samplerate and 512 frames per packet -> 23.22ms per packet // with 22050 samplerate and 512 frames per packet -> 23.22ms per packet
// SVC_VoiceData overhead = 5 bytes // SVC_VoiceData overhead = 5 bytes
// sensible limit of 8 packets per frame = 552 bytes -> 185.76ms of voice data per frame // sensible limit of 8 packets per frame = 552 bytes -> 185.76ms of voice data per frame
#define NET_MAX_VOICE_BYTES_FRAME (8 * (5 + 64)) //#define NET_MAX_VOICE_BYTES_FRAME (8 * (5 + 64))
#define NET_MAX_VOICE_BYTES_FRAME (10 * (5 + 64))
#define NET_MAX_VOICE_BYTES_FRAME_TORCHLIGHT (22 * (5 + 64))
ConVar g_SmVoiceAddr("sm_voice_addr", "127.0.0.1", FCVAR_PROTECTED, "Voice server listen ip address."); ConVar g_SmVoiceAddr("sm_voice_addr", "127.0.0.1", FCVAR_PROTECTED, "Voice server listen ip address.");
ConVar g_SmVoicePort("sm_voice_port", "27020", FCVAR_PROTECTED, "Voice server listen port.", true, 1025.0, true, 65535.0); ConVar g_SmVoicePort("sm_voice_port", "27020", FCVAR_PROTECTED, "Voice server listen port.", true, 1025.0, true, 65535.0);
@ -138,7 +140,7 @@ int g_aFrameVoiceBytes[SM_MAXPLAYERS + 1];
DETOUR_DECL_STATIC4(SV_BroadcastVoiceData, void, IClient *, pClient, int, nBytes, char *, data, int64, xuid) DETOUR_DECL_STATIC4(SV_BroadcastVoiceData, void, IClient *, pClient, int, nBytes, char *, data, int64, xuid)
{ {
if(g_Interface.OnBroadcastVoiceData(pClient, nBytes, data)) if(g_Interface.OnBroadcastVoiceData(pClient, nBytes, data, false))
DETOUR_STATIC_CALL(SV_BroadcastVoiceData)(pClient, nBytes, data, xuid); DETOUR_STATIC_CALL(SV_BroadcastVoiceData)(pClient, nBytes, data, xuid);
} }
@ -151,7 +153,7 @@ DETOUR_DECL_STATIC2(SV_BroadcastVoiceData_LTCG, void, char *, data, int64, xuid)
__asm mov pClient, ecx; __asm mov pClient, ecx;
__asm mov nBytes, edx; __asm mov nBytes, edx;
bool ret = g_Interface.OnBroadcastVoiceData(pClient, nBytes, data); bool ret = g_Interface.OnBroadcastVoiceData(pClient, nBytes, data, false);
__asm mov ecx, pClient; __asm mov ecx, pClient;
__asm mov edx, nBytes; __asm mov edx, nBytes;
@ -488,7 +490,7 @@ void CVoice::OnGameFrame(bool simulating)
memset(g_aFrameVoiceBytes, 0, sizeof(g_aFrameVoiceBytes)); memset(g_aFrameVoiceBytes, 0, sizeof(g_aFrameVoiceBytes));
} }
bool CVoice::OnBroadcastVoiceData(IClient *pClient, int nBytes, char *data) bool CVoice::OnBroadcastVoiceData(IClient *pClient, int nBytes, char *data, bool isSourceTV)
{ {
// Reject empty packets // Reject empty packets
if(nBytes < 1) if(nBytes < 1)
@ -500,10 +502,18 @@ bool CVoice::OnBroadcastVoiceData(IClient *pClient, int nBytes, char *data)
// 5 = SVC_VoiceData header/overhead // 5 = SVC_VoiceData header/overhead
g_aFrameVoiceBytes[client] += 5 + nBytes; g_aFrameVoiceBytes[client] += 5 + nBytes;
if(g_aFrameVoiceBytes[client] > NET_MAX_VOICE_BYTES_FRAME) if (!isSourceTV && g_aFrameVoiceBytes[client] > NET_MAX_VOICE_BYTES_FRAME)
{ {
return false; return false;
} }
if (isSourceTV)
{
if (g_aFrameVoiceBytes[client] > NET_MAX_VOICE_BYTES_FRAME_TORCHLIGHT)
{
smutils->LogMessage(myself, "inside interface BroadcastVoiceData with torchlight. g_aFrameVoiceBytes[client]: %d. NET_MAX_VOICE_BYTES_FRAME_TORCHLIGHT: %d", g_aFrameVoiceBytes[client], NET_MAX_VOICE_BYTES_FRAME_TORCHLIGHT);
return false;
}
}
g_fLastVoiceData[client] = gpGlobals->curtime; g_fLastVoiceData[client] = gpGlobals->curtime;
@ -701,6 +711,7 @@ void CVoice::HandleVoiceData()
if(!FramesAvailable) if(!FramesAvailable)
return; return;
//int FramesMax = 5; //used to be 5
int FramesMax = 2; //used to be 5 int FramesMax = 2; //used to be 5
bool reset_state = false; bool reset_state = false;
if (FramesAvailable <= FramesMax) if (FramesAvailable <= FramesMax)
@ -714,13 +725,11 @@ void CVoice::HandleVoiceData()
return; return;
float TimeAvailable = (float)m_Buffer.TotalLength() / sampleRate; float TimeAvailable = (float)m_Buffer.TotalLength() / sampleRate;
if(m_AvailableTime < getTime() && TimeAvailable < 0.2) if (m_AvailableTime < getTime() && TimeAvailable < 0.2)
//if(m_AvailableTime < getTime() && TimeAvailable < 0.1)
return; return;
double maxBuffer = (m_AvailableTime < getTime()) ? 0.2 : 0.04; double maxBuffer = (m_AvailableTime < getTime()) ? 0.2 : 0.04;
//double maxBuffer = (m_AvailableTime < getTime()) ? 0.1 : 0.02; if (m_AvailableTime > getTime() + maxBuffer)
if(m_AvailableTime > getTime() + maxBuffer)
return; return;
@ -744,12 +753,11 @@ void CVoice::HandleVoiceData()
// 3. Payload Type 11 (1 byte) // 3. Payload Type 11 (1 byte)
aFinal[FinalSize++] = 0x0B; aFinal[FinalSize++] = 0x0B;
// 4. Sample Rate (2 bytes little-endian) // 4. Sample Rate (2 bytes little-endian)
memcpy(&aFinal[FinalSize], &sampleRate, sizeof(uint16_t)); memcpy(&aFinal[FinalSize], &sampleRate, sizeof(uint16_t));
FinalSize += sizeof(uint16_t); FinalSize += sizeof(uint16_t);
// 5. Payload Type 6 for Opus (1 byte) // 5. Payload Type 5 for Opus. 6 for opus plc (1 byte)
aFinal[FinalSize++] = 0x05; aFinal[FinalSize++] = 0x05;
// 6. Reserve space for total data length (2 bytes little-endian) // 6. Reserve space for total data length (2 bytes little-endian)
@ -777,6 +785,7 @@ void CVoice::HandleVoiceData()
*pFrameSize = sizeof(aFinal) - sizeof(uint32_t) - FinalSize; *pFrameSize = sizeof(aFinal) - sizeof(uint32_t) - FinalSize;
// Encode with Opus // Encode with Opus
//pcm <tt>opus_int16*</tt>: Input signal (interleaved if 2 channels). length is frame_size*channels*sizeof(opus_int16)
int nbBytes = opus_encode(m_OpusEncoder, (const opus_int16*)aBuffer, SamplesPerChannel, int nbBytes = opus_encode(m_OpusEncoder, (const opus_int16*)aBuffer, SamplesPerChannel,
&aFinal[FinalSize], *pFrameSize); &aFinal[FinalSize], *pFrameSize);
if (nbBytes <= 1) if (nbBytes <= 1)
@ -814,7 +823,6 @@ void CVoice::HandleVoiceData()
FinalSize += sizeof(uint32_t); FinalSize += sizeof(uint32_t);
BroadcastVoiceData(pClient, FinalSize, aFinal); BroadcastVoiceData(pClient, FinalSize, aFinal);
//smutils->LogMessage(myself, "FinalSize: %d", FinalSize);
if (m_AvailableTime < getTime()) if (m_AvailableTime < getTime())
m_AvailableTime = getTime(); m_AvailableTime = getTime();
@ -834,6 +842,9 @@ void CVoice::BroadcastVoiceData(IClient *pClient, int nBytes, unsigned char *pDa
DETOUR_STATIC_CALL(SV_BroadcastVoiceData_LTCG)((char *)pData, 0); DETOUR_STATIC_CALL(SV_BroadcastVoiceData_LTCG)((char *)pData, 0);
#else #else
if (g_Interface.OnBroadcastVoiceData(pClient, nBytes, (char *)pData, true))
{
DETOUR_STATIC_CALL(SV_BroadcastVoiceData)(pClient, nBytes, (char *)pData, 0); DETOUR_STATIC_CALL(SV_BroadcastVoiceData)(pClient, nBytes, (char *)pData, 0);
}
#endif #endif
} }

View File

@ -136,7 +136,7 @@ public: // IConCommandBaseAccessor
public: public:
CVoice(); CVoice();
void OnGameFrame(bool simulating); void OnGameFrame(bool simulating);
bool OnBroadcastVoiceData(IClient *pClient, int nBytes, char *data); bool OnBroadcastVoiceData(IClient *pClient, int nBytes, char *data, bool isSourceTV);
void ListenSocket(); void ListenSocket();