diff options
Diffstat (limited to 'src/main.cpp')
-rw-r--r-- | src/main.cpp | 154 |
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) |