Skip to content

Commit 6b993c1

Browse files
committed
gameserver: apply networking limit increases
1 parent 49bd205 commit 6b993c1

File tree

7 files changed

+124
-12
lines changed

7 files changed

+124
-12
lines changed

source/lua.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ namespace Lua
3535

3636
// Each new metatable has this entry.
3737
struct LuaMetaEntry {
38-
unsigned char iType = -1;
38+
unsigned char iType = UCHAR_MAX;
3939
};
4040

4141
/*

source/modules/gameserver.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1333,6 +1333,23 @@ LUA_FUNCTION_STATIC(CNetChan_SetTimeout)
13331333
return 0;
13341334
}
13351335

1336+
LUA_FUNCTION_STATIC(CNetChan_GetRate)
1337+
{
1338+
CNetChan* pNetChannel = Get_CNetChan(LUA, 1, true);
1339+
1340+
LUA->PushNumber(pNetChannel->GetDataRate());
1341+
return 1;
1342+
}
1343+
1344+
LUA_FUNCTION_STATIC(CNetChan_SetRate)
1345+
{
1346+
CNetChan* pNetChannel = Get_CNetChan(LUA, 1, true);
1347+
float rate = (float)LUA->CheckNumber(2);
1348+
1349+
pNetChannel->SetDataRate(rate);
1350+
return 0;
1351+
}
1352+
13361353
LUA_FUNCTION_STATIC(CNetChan_Transmit)
13371354
{
13381355
CNetChan* pNetChannel = Get_CNetChan(LUA, 1, true);
@@ -1390,6 +1407,15 @@ LUA_FUNCTION_STATIC(CNetChan_Shutdown)
13901407
return 0;
13911408
}
13921409

1410+
LUA_FUNCTION_STATIC(CNetChan_CanPacket)
1411+
{
1412+
CNetChan* pNetChannel = Get_CNetChan(LUA, 1, true);
1413+
1414+
net_time = Util::engineserver->Time();
1415+
LUA->PushBool(pNetChannel->CanPacket());
1416+
return 1;
1417+
}
1418+
13931419
static Detouring::Hook detour_CNetChan_D2;
13941420
void hook_CNetChan_D2(CNetChan* pNetChan)
13951421
{
@@ -1654,6 +1680,16 @@ LUA_FUNCTION_STATIC(CNetChan_SendMessage)
16541680
return 1;
16551681
}
16561682

1683+
LUA_FUNCTION_STATIC(CNetChan_SendFile)
1684+
{
1685+
CNetChan* pNetChannel = Get_CNetChan(LUA, 1, true);
1686+
const char* pFileName = LUA->CheckString(2);
1687+
int transferID = LUA->CheckNumber(3);
1688+
1689+
LUA->PushBool(pNetChannel->SendFile(pFileName, transferID));
1690+
return 1;
1691+
}
1692+
16571693
LUA_FUNCTION_STATIC(CNetChan_SetMessageCallback)
16581694
{
16591695
CNetChan* pNetChannel = Get_CNetChan(LUA, 1, true);
@@ -2269,12 +2305,16 @@ void CGameServerModule::LuaInit(GarrysMod::Lua::ILuaInterface* pLua, bool bServe
22692305
Util::AddFunc(pLua, CNetChan_GetClearTime, "GetClearTime");
22702306
Util::AddFunc(pLua, CNetChan_GetTimeout, "GetTimeout");
22712307
Util::AddFunc(pLua, CNetChan_SetTimeout, "SetTimeout");
2308+
Util::AddFunc(pLua, CNetChan_GetRate, "GetRate");
2309+
Util::AddFunc(pLua, CNetChan_SetRate, "SetRate");
22722310
Util::AddFunc(pLua, CNetChan_Transmit, "Transmit");
22732311
Util::AddFunc(pLua, CNetChan_ProcessStream, "ProcessStream");
22742312
Util::AddFunc(pLua, CNetChan_SetMaxBufferSize, "SetMaxBufferSize");
22752313
Util::AddFunc(pLua, CNetChan_GetMaxRoutablePayloadSize, "GetMaxRoutablePayloadSize");
22762314
Util::AddFunc(pLua, CNetChan_SendMessage, "SendMessage");
2315+
Util::AddFunc(pLua, CNetChan_SendFile, "SendFile");
22772316
Util::AddFunc(pLua, CNetChan_Shutdown, "Shutdown");
2317+
Util::AddFunc(pLua, CNetChan_CanPacket, "CanPacket");
22782318

22792319
// Callbacks
22802320
Util::AddFunc(pLua, CNetChan_SetMessageCallback, "SetMessageCallback");
@@ -2874,6 +2914,32 @@ int NET_ReceiveStream(int nSock, char* buf, int len, int flags)
28742914
return func_NET_ReceiveStream(nSock, buf, len, flags);
28752915
}
28762916

2917+
static ConVar* host_timescale = nullptr;
2918+
static Detouring::Hook detour_NET_SetTime;
2919+
static void hook_NET_SetTime(double flRealtime) // We need this hook to keep net_time up to date
2920+
{
2921+
detour_NET_SetTime.GetTrampoline<Symbols::NET_SetTime>()(flRealtime);
2922+
2923+
static double s_last_realtime = 0;
2924+
2925+
double frametime = flRealtime - s_last_realtime;
2926+
s_last_realtime = flRealtime;
2927+
2928+
if (frametime > 1.0f)
2929+
{
2930+
// if we have very long frame times because of loading stuff
2931+
// don't apply that to net time to avoid unwanted timeouts
2932+
frametime = 1.0f;
2933+
}
2934+
else if (frametime < 0.0f)
2935+
{
2936+
frametime = 0.0f;
2937+
}
2938+
2939+
// adjust network time so fakelag works with host_timescale
2940+
net_time += frametime * (host_timescale ? host_timescale->GetFloat() : 1.0f);
2941+
}
2942+
28772943
void CGameServerModule::InitDetour(bool bPreServer)
28782944
{
28792945
if (bPreServer)
@@ -2916,6 +2982,12 @@ void CGameServerModule::InitDetour(bool bPreServer)
29162982
(void*)hook_CGameClient_SpawnPlayer, m_pID
29172983
);
29182984

2985+
Detour::Create(
2986+
&detour_NET_SetTime, "NET_SetTime",
2987+
engine_loader.GetModule(), Symbols::NET_SetTimeSym,
2988+
(void*)hook_NET_SetTime, m_pID
2989+
);
2990+
29192991
SourceSDK::FactoryLoader server_loader("server");
29202992
if (!g_pModuleManager.IsMarkedAsBinaryModule()) // Loaded by require? Then we skip this.
29212993
{
@@ -2989,4 +3061,6 @@ void CGameServerModule::InitDetour(bool bPreServer)
29893061
Detour::CheckFunction((void*)func_NET_ReceiveStream, "NET_ReceiveStream");
29903062

29913063
s_NetChannels = Detour::ResolveSymbol<CUtlVectorMT<CUtlVector<CNetChan*>>>(engine_loader, Symbols::s_NetChannelsSym);
3064+
3065+
host_timescale = g_pCVar->FindVar("host_timescale");
29923066
}

source/sourcesdk/cnetchan.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "filesystem_init.h"
1717
#include "custom_net_chan.h"
1818
#include <lz4/lz4_compression.h>
19+
#include <memory>
1920

2021
// memdbgon must be the last include file in a .cpp file!!!
2122
#include "tier0/memdbgon.h"
@@ -36,7 +37,7 @@ static ConVar net_blockmsg( "holylib_net_blockmsg", "none", FCVAR_CHEAT, "Discar
3637
static ConVar net_showdrop( "holylib_net_showdrop", "0", 0, "Show dropped packets in console" );
3738
static ConVar net_drawslider( "holylib_net_drawslider", "0", 0, "Draw completion slider during signon" );
3839
static ConVar net_chokeloopback( "holylib_net_chokeloop", "0", 0, "Apply bandwidth choke to loopback packets" );
39-
static ConVar net_maxfilesize( "holylib_net_maxfilesize", "256", 0, "Maximum allowed file size for uploading in MiB", true, 0, true, 512 );
40+
static ConVar net_maxfilesize( "holylib_net_maxfilesize", "4096", 0, "Maximum allowed file size for uploading in MiB", true, 0, true, 4096 );
4041
static ConVar net_compresspackets( "holylib_net_compresspackets", "1", 0, "Use compression on game packets." );
4142
static ConVar net_compresspackets_minsize( "holylib_net_compresspackets_minsize", "1024", 0, "Don't bother compressing packets below this size." );
4243
static ConVar net_maxcleartime( "holylib_net_maxcleartime", "4.0", 0, "Max # of seconds we can wait for next packets to be sent based on rate setting (0 == no limit)." );
@@ -1145,10 +1146,10 @@ bool CNetChan::CreateFragmentsFromFile( const char *filename, int stream, unsign
11451146
}
11461147

11471148
int totalBytes = (int)g_pFullFileSystem->Size( filename, pPathID );
1148-
1149-
if ( totalBytes >= (net_maxfilesize.GetInt()*1024*1024) )
1149+
1150+
if ( totalBytes >= (((uint64_t)net_maxfilesize.GetInt()) *1024*1024) ) // We need it as a uint64_t since else we'll overflow the int!
11501151
{
1151-
ConMsg( "CreateFragmentsFromFile: '%s' size exceeds net_maxfilesize limit (%i MiB).\n", filename, net_maxfilesize.GetInt() );
1152+
ConMsg( "CreateFragmentsFromFile: '%s' size exceeds net_maxfilesize limit (%i MiB, %i).\n", filename, net_maxfilesize.GetInt(), totalBytes);
11521153
return false;
11531154
}
11541155

@@ -1620,7 +1621,9 @@ A 0 length will still generate a packet and deal with the reliable messages.
16201621
*/
16211622
int CNetChan::SendDatagram(bf_write *datagram)
16221623
{
1623-
ALIGN4 byte send_buf[ NET_MAX_MESSAGE ] ALIGN4_POST;
1624+
// We cannot stackallocate this amount as else we can easily crash!
1625+
// We also use static so that each thread only allocates this once instead of on every call & we use a std::unique_ptr so that our memory is freed when the thread dies.
1626+
static thread_local std::unique_ptr<byte[]> send_buf(new byte[NET_MAX_MESSAGE]);
16241627

16251628
#ifndef NO_VCR
16261629
if ( vcr_verbose.GetInt() && datagram && datagram->GetNumBytesWritten() > 0 )
@@ -1664,7 +1667,7 @@ int CNetChan::SendDatagram(bf_write *datagram)
16641667
m_StreamReliable.Reset();
16651668
}
16661669

1667-
bf_write send( "CNetChan_TransmitBits->send", send_buf, sizeof(send_buf) );
1670+
bf_write send( "CNetChan_TransmitBits->send", send_buf.get(), NET_MAX_MESSAGE);
16681671

16691672
// Prepare the packet header
16701673
// build packet flags
@@ -3173,6 +3176,7 @@ int CNetChan::IncrementSplitPacketSequence()
31733176
return ++m_nSplitPacketSequence;
31743177
}
31753178

3179+
// ToDo: iirc gmod changed this from a blacklist to whitelist for files.
31763180
bool CNetChan::IsValidFileForTransfer( const char *pszFilename )
31773181
{
31783182
if ( !pszFilename || !pszFilename[ 0 ] )

source/sourcesdk/custom_net_chan.h

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,38 @@
2121
#include "const.h"
2222
#include "inetchannel.h"
2323

24+
// Flow control bytes per second limits
25+
#undef MAX_RATE
26+
#undef MIN_RATE
27+
#undef DEFAULT_RATE
28+
#define MAX_RATE (1024*1024*16)
29+
#define MIN_RATE 4000
30+
#define DEFAULT_RATE 240000
31+
32+
#undef FRAGMENT_BITS
33+
#undef FRAGMENT_SIZE
34+
#undef MAX_FILE_SIZE_BITS
35+
#undef MAX_FILE_SIZE
36+
#define FRAGMENT_BITS 13
37+
constexpr int FRAGMENT_SIZE = 1 << FRAGMENT_BITS;
38+
#define MAX_FILE_SIZE_BITS 29
39+
constexpr int MAX_FILE_SIZE = (1 << MAX_FILE_SIZE_BITS) - 1; // maximum transferable size is 4GB
40+
41+
#undef NET_MAX_PAYLOAD
42+
#undef NET_MAX_DATAGRAM_PAYLOAD
43+
// This is the packet payload without any header bytes (which are attached for actual sending)
44+
#define NET_MAX_PAYLOAD 576000 // largest message we can send in bytes
45+
#define NET_MAX_DATAGRAM_PAYLOAD 8000 // = maximum unreliable payload size
46+
2447
#define MAX_FRAGMENTS_BITS 5 // How many fragments we can send at once
25-
#define MAX_FRAGMENTS (1 << MAX_FRAGMENTS_BITS) - 1 // Maximum number of fragments we can safely transmit. -1 as else we would go over MAX_FRAGMENTS_BITS
48+
constexpr int MAX_FRAGMENTS = (1 << MAX_FRAGMENTS_BITS) - 1; // Maximum number of fragments we can safely transmit. -1 as else we would go over MAX_FRAGMENTS_BITS
2649

2750
#undef MAX_ROUTABLE_PAYLOAD
28-
#define MAX_ROUTABLE_PAYLOAD (FRAGMENT_SIZE * FRAGMENT_SIZE) // Matches x360 size(1260). Update: Won't match anymore
51+
constexpr int MAX_ROUTABLE_PAYLOAD = FRAGMENT_SIZE * FRAGMENT_SIZE; // Matches x360 size(1260). Update: Won't match anymore
52+
53+
54+
#undef NET_MAX_MESSAGE
55+
constexpr int NET_MAX_MESSAGE = PAD_NUMBER((NET_MAX_PAYLOAD + HEADER_BYTES), 16);
2956

3057
// How fast to converge flow estimates
3158
#define FLOW_AVG ( 3.0F / 4.0F )
@@ -34,10 +61,10 @@
3461

3562

3663
#define NET_FRAMES_BACKUP 64 // must be power of 2
37-
#define NET_FRAMES_MASK (NET_FRAMES_BACKUP-1)
64+
constexpr int NET_FRAMES_MASK = (NET_FRAMES_BACKUP - 1);
3865

3966
#define SUBCHANNEL_BITS 4 // raising it above 5 would require changes to m_nOutReliableState & m_nInReliableState as they couldn't hold the states anymore.
40-
#define MAX_SUBCHANNELS (1 << SUBCHANNEL_BITS) // we have 16 alternative send&wait bits
67+
constexpr int MAX_SUBCHANNELS = (1 << SUBCHANNEL_BITS); // we have 16 alternative send&wait bits
4168

4269
#define SUBCHANNEL_FREE 0 // subchannel is free to use
4370
#define SUBCHANNEL_TOSEND 1 // subchannel has data, but not send yet

source/symbols.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -890,4 +890,8 @@ namespace Symbols
890890
const std::vector<Symbol> s_NetChannelsSym = {
891891
Symbol::FromName("_ZL13s_NetChannels"),
892892
};
893+
894+
const std::vector<Symbol> NET_SetTimeSym = {
895+
Symbol::FromName("_Z11NET_SetTimed"),
896+
};
893897
}

source/symbols.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,9 @@ namespace Symbols
628628
typedef int (*NET_ReceiveStream)(int nSock, char * buf, int len, int flags);
629629
extern const std::vector<Symbol> NET_ReceiveStreamSym;
630630

631+
typedef void (*NET_SetTime)(double flRealtime);
632+
extern const std::vector<Symbol> NET_SetTimeSym;
633+
631634
extern const std::vector<Symbol> s_NetChannelsSym;
632635

633636
//---------------------------------------------------------------------------------

source/util.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ struct LuaUserData;
456456
extern std::unordered_set<LuaUserData*> g_pLuaUserData; // A set containing all LuaUserData that actually hold a reference.
457457
#endif
458458
struct LuaUserData { // No constructor/deconstructor since its managed by Lua!
459-
inline void Init(GarrysMod::Lua::ILuaInterface* LUA, int type, void* pData)
459+
inline void Init(GarrysMod::Lua::ILuaInterface* LUA, unsigned char type, void* pData)
460460
{
461461
// Since Lua creates our userdata, we need to set all the fields ourself!
462462
#if HOLYLIB_UTIL_BASEUSERDATA

0 commit comments

Comments
 (0)