updates by buttocks by fixing uneven bytes recv
This commit is contained in:
parent
a29a884671
commit
2eb343d6e0
105
extension.cpp
105
extension.cpp
@ -46,9 +46,16 @@
|
||||
#include "CDetour/detours.h"
|
||||
#include "extension.h"
|
||||
|
||||
// voice packets are sent over unreliable netchannel
|
||||
//#define NET_MAX_DATAGRAM_PAYLOAD 4000 // = maximum unreliable payload size
|
||||
// voice packetsize = 64 | netchannel overflows at >4000 bytes
|
||||
// with 22050 samplerate and 512 frames per packet -> 23.22ms per packet
|
||||
// SVC_VoiceData overhead = 5 bytes
|
||||
// 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))
|
||||
|
||||
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_SmVoiceLogging("sm_voice_logging", "0", FCVAR_PROTECTED, "Log voice packets.");
|
||||
|
||||
/**
|
||||
* @file extension.cpp
|
||||
@ -67,29 +74,6 @@ IServer *iserver = NULL;
|
||||
double g_fLastVoiceData[SM_MAXPLAYERS + 1];
|
||||
int g_aFrameVoiceBytes[SM_MAXPLAYERS + 1];
|
||||
|
||||
#define NET_MAX_VOICE_BYTES_FRAME 512
|
||||
#define NET_MAX_VOICE_BYTES_FRAME_LOG 1024
|
||||
|
||||
/*
|
||||
// This is just the client_t->netchan.datagram buffer size (shouldn't ever need to be huge)
|
||||
#define NET_MAX_VOICE_BYTES_FRAME 4000 // = maximum unreliable payload size
|
||||
maybe try 1024 for starters
|
||||
instead of 4096
|
||||
voice data should never be that big
|
||||
actually I can give you a fool-proof number
|
||||
since I did tests for torchlight
|
||||
the packetsize is hardcoded 64 bytes
|
||||
torchlight sends max 5 frames at once to clients
|
||||
there are 512 frames per packet
|
||||
sample rate 22050
|
||||
so one packet is 23.2ms
|
||||
anyways, since torchlight only sends 5 packets at once, which is 5*64 = 320 bytes
|
||||
make the limit > 384 (6 * 64)
|
||||
I'm thinking the guy probably just sends a huge packet with max size 4000 or whatever to the server
|
||||
and it puts it in the netchan, which seems to be 4000 max big
|
||||
and then any other data in there overflows it
|
||||
*/
|
||||
|
||||
DETOUR_DECL_STATIC4(SV_BroadcastVoiceData, void, IClient *, pClient, int, nBytes, char *, data, int64, xuid)
|
||||
{
|
||||
if(g_Interface.OnBroadcastVoiceData(pClient, nBytes, data))
|
||||
@ -328,6 +312,12 @@ const sp_nativeinfo_t MyNatives[] =
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static void ListenSocketAction(void *pData)
|
||||
{
|
||||
CVoice *pThis = (CVoice *)pData;
|
||||
pThis->ListenSocket();
|
||||
}
|
||||
|
||||
void CVoice::SDK_OnAllLoaded()
|
||||
{
|
||||
sharesys->AddNatives(myself, MyNatives);
|
||||
@ -366,9 +356,19 @@ void CVoice::SDK_OnAllLoaded()
|
||||
return;
|
||||
}
|
||||
|
||||
// This doesn't seem to work right away ...
|
||||
engine->ServerCommand("exec sourcemod/extension.Voice.cfg\n");
|
||||
engine->ServerExecute();
|
||||
|
||||
// ... delay starting listen server to next frame
|
||||
smutils->AddFrameAction(ListenSocketAction, this);
|
||||
}
|
||||
|
||||
void CVoice::ListenSocket()
|
||||
{
|
||||
if(m_PollFds > 0)
|
||||
return;
|
||||
|
||||
sockaddr_in bindAddr;
|
||||
memset(&bindAddr, 0, sizeof(bindAddr));
|
||||
bindAddr.sin_family = AF_INET;
|
||||
@ -439,37 +439,25 @@ void CVoice::OnGameFrame(bool simulating)
|
||||
memset(g_aFrameVoiceBytes, 0, sizeof(g_aFrameVoiceBytes));
|
||||
}
|
||||
|
||||
|
||||
bool CVoice::OnBroadcastVoiceData(IClient *pClient, int nBytes, char *data)
|
||||
{
|
||||
int client = pClient->GetPlayerSlot() + 1;
|
||||
IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client);
|
||||
|
||||
// Reject empty packets
|
||||
if(nBytes < 1)
|
||||
{
|
||||
smutils->LogMessage(myself, "%s (%s): Empty voice packet", pPlayer->GetName(), pPlayer->GetSteam2Id(true), data);
|
||||
return false;
|
||||
}
|
||||
|
||||
// this is to log all voice packet
|
||||
if (g_SmVoiceLogging.GetInt())
|
||||
smutils->LogMessage(myself, "%s (%s): %s", pPlayer->GetName(), pPlayer->GetSteam2Id(true), data);
|
||||
int client = pClient->GetPlayerSlot() + 1;
|
||||
|
||||
// Reject voice packet if we'd send more than NET_MAX_VOICE_BYTES_FRAME voice bytes from this client in the current frame.
|
||||
// 5 = SVC_VoiceData header/overhead
|
||||
g_aFrameVoiceBytes[client] += 5 + nBytes;
|
||||
|
||||
if(g_aFrameVoiceBytes[client] > NET_MAX_VOICE_BYTES_FRAME)
|
||||
return false;
|
||||
|
||||
g_fLastVoiceData[client] = gpGlobals->curtime;
|
||||
|
||||
// Reject voice packet if we'd send more than NET_MAX_VOICE_BYTES_FRAME voice bytes from this client in the current frame.
|
||||
g_aFrameVoiceBytes[client] += nBytes;
|
||||
|
||||
if(g_aFrameVoiceBytes[client] > NET_MAX_VOICE_BYTES_FRAME)
|
||||
{
|
||||
if(g_aFrameVoiceBytes[client] > NET_MAX_VOICE_BYTES_FRAME_LOG)
|
||||
{
|
||||
smutils->LogMessage(myself, "%s (%s) voice overflow! %d > %d\n", pPlayer->GetName(), pPlayer->GetSteam2Id(true), g_aFrameVoiceBytes[client], NET_MAX_VOICE_BYTES_FRAME);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void CVoice::HandleNetwork()
|
||||
{
|
||||
@ -503,6 +491,7 @@ void CVoice::HandleNetwork()
|
||||
m_aClients[Client].m_LastLength = 0;
|
||||
m_aClients[Client].m_LastValidData = 0.0;
|
||||
m_aClients[Client].m_New = true;
|
||||
m_aClients[Client].m_UnEven = false;
|
||||
|
||||
m_aPollFds[m_PollFds].fd = Socket;
|
||||
m_aPollFds[m_PollFds].events = POLLIN | POLLHUP;
|
||||
@ -560,7 +549,16 @@ void CVoice::HandleNetwork()
|
||||
if(min(BytesAvailable, sizeof(aBuf)) > m_Buffer.CurrentFree() * sizeof(int16_t))
|
||||
continue;
|
||||
|
||||
ssize_t Bytes = recv(pClient->m_Socket, aBuf, sizeof(aBuf), 0);
|
||||
// Edge case: previously received data is uneven and last recv'd byte has to be prepended
|
||||
int Shift = 0;
|
||||
if(pClient->m_UnEven)
|
||||
{
|
||||
Shift = 1;
|
||||
aBuf[0] = pClient->m_Remainder;
|
||||
pClient->m_UnEven = false;
|
||||
}
|
||||
|
||||
ssize_t Bytes = recv(pClient->m_Socket, &aBuf[Shift], sizeof(aBuf) - Shift, 0);
|
||||
|
||||
if(Bytes <= 0)
|
||||
{
|
||||
@ -568,10 +566,21 @@ void CVoice::HandleNetwork()
|
||||
pClient->m_Socket = -1;
|
||||
m_aPollFds[PollFds].fd = -1;
|
||||
CompressPollFds = true;
|
||||
smutils->LogMessage(myself, "Client %d disconnected!(1)\n", Client);
|
||||
//smutils->LogMessage(myself, "Client %d disconnected!(1)\n", Client);
|
||||
continue;
|
||||
}
|
||||
|
||||
Bytes += Shift;
|
||||
|
||||
// Edge case: data received is uneven (can't be divided by two)
|
||||
// store last byte, drop it here and prepend it right before the next recv
|
||||
if(Bytes & 1)
|
||||
{
|
||||
pClient->m_UnEven = true;
|
||||
pClient->m_Remainder = aBuf[Bytes - 1];
|
||||
Bytes -= 1;
|
||||
}
|
||||
|
||||
// Got data!
|
||||
OnDataReceived(pClient, (int16_t *)aBuf, Bytes / sizeof(int16_t));
|
||||
|
||||
|
@ -139,6 +139,8 @@ public:
|
||||
void OnGameFrame(bool simulating);
|
||||
bool OnBroadcastVoiceData(IClient *pClient, int nBytes, char *data);
|
||||
|
||||
void ListenSocket();
|
||||
|
||||
private:
|
||||
int m_ListenSocket;
|
||||
|
||||
@ -149,6 +151,8 @@ private:
|
||||
size_t m_LastLength;
|
||||
double m_LastValidData;
|
||||
bool m_New;
|
||||
bool m_UnEven;
|
||||
unsigned char m_Remainder;
|
||||
} m_aClients[MAX_CLIENTS];
|
||||
|
||||
struct pollfd m_aPollFds[1 + MAX_CLIENTS];
|
||||
|
Loading…
Reference in New Issue
Block a user