summaryrefslogtreecommitdiffstats
path: root/src/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp154
1 files changed, 105 insertions, 49 deletions
diff --git a/src/main.cpp b/src/main.cpp
index da8eb75d4..5cd057278 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -2,6 +2,7 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "Root.h"
+#include "tclap/CmdLine.h"
#include <exception>
#include <csignal>
@@ -12,12 +13,11 @@
#endif // _MSC_VER
#include "OSSupport/NetworkSingleton.h"
+#include "BuildInfo.h"
+#include "MemorySettingsRepository.h"
-/** Make the Root instance global, so it can be terminated from the worker threads */
-cRoot Root;
-
/** If something has told the server to stop; checked periodically in cRoot */
bool cRoot::m_TerminateEventRaised = false;
@@ -35,14 +35,20 @@ bool g_ShouldLogCommOut;
bool cRoot::m_RunAsService = false;
+
+
+
#if defined(_WIN32)
-SERVICE_STATUS_HANDLE g_StatusHandle = NULL;
-HANDLE g_ServiceThread = INVALID_HANDLE_VALUE;
-#define SERVICE_NAME "MCServerService"
+ SERVICE_STATUS_HANDLE g_StatusHandle = NULL;
+ HANDLE g_ServiceThread = INVALID_HANDLE_VALUE;
+ #define SERVICE_NAME "MCServerService"
#endif
-/// If defined, a thorough leak finder will be used (debug MSVC only); leaks will be output to the Output window
+
+
+
+/** If defined, a thorough leak finder will be used (debug MSVC only); leaks will be output to the Output window */
// _X 2014_02_20: Disabled for canon repo, it makes the debug version too slow in MSVC2013
// and we haven't had a memory leak for over a year anyway.
// #define ENABLE_LEAK_FINDER
@@ -74,6 +80,10 @@ void NonCtrlHandler(int a_Signal)
std::signal(SIGSEGV, SIG_DFL);
LOGERROR(" D: | MCServer has encountered an error and needs to close");
LOGERROR("Details | SIGSEGV: Segmentation fault");
+ #ifdef BUILD_ID
+ LOGERROR("MCServer " BUILD_SERIES_NAME " build id: " BUILD_ID);
+ LOGERROR("from commit id: " BUILD_COMMIT_ID " built at: " BUILD_DATETIME);
+ #endif
PrintStackTrace();
abort();
}
@@ -85,6 +95,10 @@ void NonCtrlHandler(int a_Signal)
std::signal(a_Signal, SIG_DFL);
LOGERROR(" D: | MCServer has encountered an error and needs to close");
LOGERROR("Details | SIGABRT: Server self-terminated due to an internal fault");
+ #ifdef BUILD_ID
+ LOGERROR("MCServer " BUILD_SERIES_NAME " build id: " BUILD_ID);
+ LOGERROR("from commit id: " BUILD_COMMIT_ID " built at: " BUILD_DATETIME);
+ #endif
PrintStackTrace();
abort();
}
@@ -169,6 +183,7 @@ LONG WINAPI LastChanceExceptionFilter(__in struct _EXCEPTION_POINTERS * a_Except
+
#ifdef _WIN32
// Handle CTRL events in windows, including console window close
BOOL CtrlHandler(DWORD fdwCtrlType)
@@ -188,10 +203,11 @@ BOOL CtrlHandler(DWORD fdwCtrlType)
+
////////////////////////////////////////////////////////////////////////////////
// universalMain - Main startup logic for both standard running and as a service
-void universalMain()
+void universalMain(std::unique_ptr<cSettingsRepositoryInterface> overridesRepo)
{
#ifdef _WIN32
if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE))
@@ -210,7 +226,8 @@ void universalMain()
try
#endif
{
- Root.Start();
+ cRoot Root;
+ Root.Start(std::move(overridesRepo));
}
#if !defined(ANDROID_NDK)
catch (std::exception & e)
@@ -241,7 +258,7 @@ DWORD WINAPI serviceWorkerThread(LPVOID lpParam)
UNREFERENCED_PARAMETER(lpParam);
// Do the normal startup
- universalMain();
+ universalMain(cpp14::make_unique<cMemorySettingsRepository>());
return ERROR_SUCCESS;
}
@@ -282,7 +299,7 @@ void WINAPI serviceCtrlHandler(DWORD CtrlCode)
{
case SERVICE_CONTROL_STOP:
{
- Root.SetStopping(true);
+ cRoot::m_ShouldStop = true;
serviceSetState(0, SERVICE_STOP_PENDING, 0);
break;
}
@@ -309,10 +326,10 @@ void WINAPI serviceMain(DWORD argc, TCHAR *argv[])
char applicationFilename[MAX_PATH];
char applicationDirectory[MAX_PATH];
- GetModuleFileName(NULL, applicationFilename, MAX_PATH); // This binaries fill path.
+ GetModuleFileName(NULL, applicationFilename, sizeof(applicationFilename)); // This binary's file path.
- // GetModuleFileName() returns the path and filename. Strip off the filename.
- strncpy(applicationDirectory, applicationFilename, (strrchr(applicationFilename, '\\') - applicationFilename));
+ // Strip off the filename, keep only the path:
+ strncpy_s(applicationDirectory, sizeof(applicationDirectory), applicationFilename, (strrchr(applicationFilename, '\\') - applicationFilename));
applicationDirectory[strlen(applicationDirectory)] = '\0'; // Make sure new path is null terminated
// Services are run by the SCM, and inherit its working directory - usually System32.
@@ -323,7 +340,7 @@ void WINAPI serviceMain(DWORD argc, TCHAR *argv[])
if (g_StatusHandle == NULL)
{
- OutputDebugString("RegisterServiceCtrlHandler() failed\n");
+ OutputDebugStringA("RegisterServiceCtrlHandler() failed\n");
serviceSetState(0, SERVICE_STOPPED, GetLastError());
return;
}
@@ -333,7 +350,7 @@ void WINAPI serviceMain(DWORD argc, TCHAR *argv[])
g_ServiceThread = CreateThread(NULL, 0, serviceWorkerThread, NULL, 0, NULL);
if (g_ServiceThread == NULL)
{
- OutputDebugString("CreateThread() failed\n");
+ OutputDebugStringA("CreateThread() failed\n");
serviceSetState(0, SERVICE_STOPPED, GetLastError());
return;
}
@@ -347,14 +364,79 @@ void WINAPI serviceMain(DWORD argc, TCHAR *argv[])
+std::unique_ptr<cMemorySettingsRepository> parseArguments(int argc, char **argv)
+{
+ try
+ {
+ TCLAP::CmdLine cmd("MCServer");
+
+ TCLAP::ValueArg<int> slotsArg("s", "max-players", "Maximum number of slots for the server to use, overrides setting in setting.ini", false, -1, "number", cmd);
+
+ TCLAP::MultiArg<int> portsArg("p", "port", "The port number the server should listen to", false, "port", cmd);
+
+ TCLAP::SwitchArg commLogArg("", "log-comm", "Log server client communications to file", cmd);
+
+ TCLAP::SwitchArg commLogInArg("", "log-comm-in", "Log inbound server client communications to file", cmd);
+
+ TCLAP::SwitchArg commLogOutArg("", "log-comm-out", "Log outbound server client communications to file", cmd);
+
+ TCLAP::SwitchArg noBufArg("", "no-output-buffering", "Disable output buffering", cmd);
+
+ cmd.parse(argc, argv);
+
+ auto repo = cpp14::make_unique<cMemorySettingsRepository>();
+
+ if (slotsArg.isSet())
+ {
+
+ int slots = slotsArg.getValue();
+
+ repo->AddValue("Server", "MaxPlayers", static_cast<Int64>(slots));
+
+ }
+
+ if (portsArg.isSet())
+ {
+ std::vector<int> ports = portsArg.getValue();
+ for (auto port : ports)
+ {
+ repo->AddValue("Server", "Port", static_cast<Int64>(port));
+ }
+ }
+
+ if (commLogArg.getValue())
+ {
+ g_ShouldLogCommIn = true;
+ g_ShouldLogCommOut = true;
+ }
+ else
+ {
+ g_ShouldLogCommIn = commLogInArg.getValue();
+ g_ShouldLogCommOut = commLogOutArg.getValue();
+ }
+
+ if (noBufArg.getValue())
+ {
+ setvbuf(stdout, nullptr, _IONBF, 0);
+ }
+
+ repo->SetReadOnly();
+
+ return repo;
+ }
+ catch (TCLAP::ArgException &e)
+ {
+ printf("error reading command line %s for arg %s", e.error().c_str(), e.argId().c_str());
+ return cpp14::make_unique<cMemorySettingsRepository>();
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
// main:
-int main( int argc, char **argv)
+int main(int argc, char **argv)
{
- UNUSED(argc);
- UNUSED(argv);
#if defined(_MSC_VER) && defined(_DEBUG) && defined(ENABLE_LEAK_FINDER)
InitLeakFinder();
@@ -409,39 +491,13 @@ int main( int argc, char **argv)
// DEBUG: test the dumpfile creation:
// *((int *)0) = 0;
+ auto argsRepo = parseArguments(argc, argv);
+
// Check if comm logging is to be enabled:
for (int i = 0; i < argc; i++)
{
AString Arg(argv[i]);
- if (
- (NoCaseCompare(Arg, "/commlog") == 0) ||
- (NoCaseCompare(Arg, "/logcomm") == 0)
- )
- {
- g_ShouldLogCommIn = true;
- g_ShouldLogCommOut = true;
- }
- else if (
- (NoCaseCompare(Arg, "/commlogin") == 0) ||
- (NoCaseCompare(Arg, "/comminlog") == 0) ||
- (NoCaseCompare(Arg, "/logcommin") == 0)
- )
- {
- g_ShouldLogCommIn = true;
- }
- else if (
- (NoCaseCompare(Arg, "/commlogout") == 0) ||
- (NoCaseCompare(Arg, "/commoutlog") == 0) ||
- (NoCaseCompare(Arg, "/logcommout") == 0)
- )
- {
- g_ShouldLogCommOut = true;
- }
- else if (NoCaseCompare(Arg, "nooutbuf") == 0)
- {
- setvbuf(stdout, nullptr, _IONBF, 0);
- }
- else if (NoCaseCompare(Arg, "/service") == 0)
+ if (NoCaseCompare(Arg, "/service") == 0)
{
cRoot::m_RunAsService = true;
}
@@ -467,7 +523,7 @@ int main( int argc, char **argv)
#endif
{
// Not running as a service, do normal startup
- universalMain();
+ universalMain(std::move(argsRepo));
}
#if defined(_MSC_VER) && defined(_DEBUG) && defined(ENABLE_LEAK_FINDER)