/
ff_steamworks_thread.cpp
165 lines (140 loc) · 3.99 KB
/
ff_steamworks_thread.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#include "cbase.h"
#include "filesystem.h"
#include "ff_socks.h"
#include "ff_steamworks_thread.h"
#include "vstdlib/icommandline.h"
// supressing macro redefinition warnings
#undef ARRAYSIZE
#undef GetCommandLine
#undef ReadConsoleInput
#undef RegCreateKey
#undef RegCreateKeyEx
#undef RegOpenKey
#undef RegOpenKeyEx
#undef RegQueryValue
#undef RegQueryValueEx
#undef RegSetValue
#undef RegSetValueEx
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define SERVER_EXEC_NAME "bin/sws.exe"
// send a heartbeat every 5 poll (2.5 second), send heartbeat right away
CFFSteamworksThread::CFFSteamworksThread( void ) : m_iPollRate(500), m_hProcess(NULL), m_hThread(NULL),
m_iHeartbeatRate(5), m_iHeartbeatCheckCount(m_iHeartbeatRate)
{
SetName("SteamworksThread");
m_bIsRunning = false;
Start();
}
CFFSteamworksThread::~CFFSteamworksThread( void )
{
ShutdownServer( );
}
bool CFFSteamworksThread::CreateServerProcess( void )
{
if ( !filesystem->FileExists( SERVER_EXEC_NAME, "MOD" ) )
{
Msg( "[Steamworks thread] failed to find SW server '%s' in moddir\n", SERVER_EXEC_NAME );
return false;
}
char szExecPath[MAX_PATH] = { 0 };
filesystem->GetLocalPath( SERVER_EXEC_NAME, szExecPath, MAX_PATH );
PROCESS_INFORMATION procInfo = { 0 };
STARTUPINFO startUpInfo = { 0 };
startUpInfo.cb = sizeof( startUpInfo );
if ( !CreateProcess( NULL, szExecPath, NULL, NULL, false, 0, NULL, NULL, &startUpInfo, &procInfo ) )
{
Msg( "[Steamworks thread] failed to start SW server\n" );
return false;
}
Msg( "[Steamworks thread] sw server started\n" );
m_hProcess = procInfo.hProcess;
m_hThread = procInfo.hThread;
return true;
}
void CFFSteamworksThread::KillServerProcess( void )
{
DevMsg( "[Steamworks thread] KillServerProcess" );
// the server loop will actually end once the socket closes, however make sure and axe it here just incase dragons
if ( !m_hProcess || !m_hThread)
return;
// yikes: results in race condition with os if thread falls through, so just let it..
// CloseHandle( m_hProcess );
// CloseHandle( m_hThread );
}
void CFFSteamworksThread::QueueMessage( const CFFSteamworksMessage &msg )
{
m_QueuedMessages.AddToTail( msg );
}
void CFFSteamworksThread::ShutdownServer( void )
{
DevMsg( "[Steamworks thread] ShutdownServer" );
m_Sock.Close( );
m_bIsShutdown = true;
KillServerProcess( );
// avoid race conditions
if ( m_bIsRunning )
Terminate( );
}
int CFFSteamworksThread::Run()
{
if ( !CreateServerProcess() )
{
DevMsg( "[Steamworks thread] Run - failed to create server process\n" );
return -1;
}
m_bIsRunning = true;
Sleep(50);
// not sure what this is but it triggers winsocks init
m_Sock.Open( 1, 0 );
if ( !m_Sock.Connect("localhost", 7802) )
{
DevMsg( "[Steamworks thread] Run2 - failed to connect to server\n" );
m_bIsRunning = false;
return -2;
}
while ( IsAlive( ) && !m_bIsShutdown )
{
if ( ++m_iHeartbeatCheckCount >= m_iHeartbeatRate )
{
m_iHeartbeatCheckCount = 0;
SendMsg( CFFSteamworksMessage( SWC_HEARTBEAT ) );
}
int queueCount = m_QueuedMessages.Count( );
if (queueCount < 1)
{
Sleep ( m_iPollRate );
continue;
}
for (int i = 0; i < queueCount; ++i)
{
CFFSteamworksMessage &msg = m_QueuedMessages.Element ( i );
SendMsg( msg );
}
m_QueuedMessages.RemoveAll( );
Sleep ( m_iPollRate );
}
DevMsg( "[Steamworks thread] Run3 - fallthrough\n" );
m_Sock.Close( );
m_bIsRunning = false;
return 1;
}
void CFFSteamworksThread::SendMsg( const CFFSteamworksMessage &msg )
{
const int maxSize = 1024;
char buff[maxSize] = { 0 };
Q_snprintf( buff, maxSize,"%d|%s|%s!",(int)msg.GetCommand( ), msg.GetKey( ), msg.GetVal( ) );
DevMsg( "[Steamworks thread] SendMsg - '%s'\n", buff );
if ( !m_Sock.Send( buff ) )
{
// make sure to check this here, it will return false and we want to fall through
m_bIsShutdown = true;
}
}
CFFSteamworksThread& CFFSteamworksThread::GetInstance()
{
static CFFSteamworksThread thread;
return thread;
}