// Copyright Epic Games, Inc. All Rights Reserved. #include "config.h" #include "diag/logging.h" #include #include #include #include #include ZEN_THIRD_PARTY_INCLUDES_START #include #include #include #include ZEN_THIRD_PARTY_INCLUDES_END #if ZEN_PLATFORM_WINDOWS # include #else # include #endif #if ZEN_PLATFORM_WINDOWS // Used for getting My Documents for default data directory # include # pragma comment(lib, "shell32.lib") std::filesystem::path PickDefaultStateDirectory() { // Pick sensible default PWSTR programDataDir = nullptr; HRESULT hRes = SHGetKnownFolderPath(FOLDERID_ProgramData, 0, NULL, &programDataDir); if (SUCCEEDED(hRes)) { std::filesystem::path finalPath(programDataDir); finalPath /= L"Epic\\Zen\\Data"; ::CoTaskMemFree(programDataDir); return finalPath; } return L""; } #else std::filesystem::path PickDefaultStateDirectory() { int UserId = getuid(); const passwd* Passwd = getpwuid(UserId); return std::filesystem::path(Passwd->pw_dir) / ".zen"; } #endif void ValidateOptions(ZenServerOptions& ServerOptions) { if (ServerOptions.EncryptionKey.empty() == false) { const auto Key = zen::AesKey256Bit::FromString(ServerOptions.EncryptionKey); if (Key.IsValid() == false) { throw cxxopts::OptionParseException("Invalid AES encryption key"); } } if (ServerOptions.EncryptionIV.empty() == false) { const auto IV = zen::AesIV128Bit::FromString(ServerOptions.EncryptionIV); if (IV.IsValid() == false) { throw cxxopts::OptionParseException("Invalid AES initialization vector"); } } } UpstreamCachePolicy ParseUpstreamCachePolicy(std::string_view Options) { if (Options == "readonly") { return UpstreamCachePolicy::Read; } else if (Options == "writeonly") { return UpstreamCachePolicy::Write; } else if (Options == "disabled") { return UpstreamCachePolicy::Disabled; } else { return UpstreamCachePolicy::ReadWrite; } } void ParseConfigFile(const std::filesystem::path& Path, ZenServerOptions& ServerOptions); void ParseCliOptions(int argc, char* argv[], ZenServerOptions& ServerOptions) { #if ZEN_WITH_HTTPSYS const char* DefaultHttp = "httpsys"; #else const char* DefaultHttp = "asio"; #endif // Note to those adding future options; std::filesystem::path-type options // must be read into a std::string first. As of cxxopts-3.0.0 it uses a >> // stream operator to convert argv value into the options type. std::fs::path // expects paths in streams to be quoted but argv paths are unquoted. By // going into a std::string first, paths with whitespace parse correctly. std::string DataDir; std::string ContentDir; std::string AbsLogFile; std::string ConfigFile; cxxopts::Options options("zenserver", "Zen Server"); options.add_options()("dedicated", "Enable dedicated server mode", cxxopts::value(ServerOptions.IsDedicated)->default_value("false")); options.add_options()("d, debug", "Enable debugging", cxxopts::value(ServerOptions.IsDebug)->default_value("false")); options.add_options()("help", "Show command line help"); options.add_options()("t, test", "Enable test mode", cxxopts::value(ServerOptions.IsTest)->default_value("false")); options.add_options()("log-id", "Specify id for adding context to log output", cxxopts::value(ServerOptions.LogId)); options.add_options()("data-dir", "Specify persistence root", cxxopts::value(DataDir)); options.add_options()("content-dir", "Frontend content directory", cxxopts::value(ContentDir)); options.add_options()("abslog", "Path to log file", cxxopts::value(AbsLogFile)); options.add_options()("config", "Path to Lua config file", cxxopts::value(ConfigFile)); options.add_options()("no-sentry", "Disable Sentry crash handler", cxxopts::value(ServerOptions.NoSentry)->default_value("false")); options.add_option("security", "", "encryption-aes-key", "256 bit AES encryption key", cxxopts::value(ServerOptions.EncryptionKey), ""); options.add_option("security", "", "encryption-aes-iv", "128 bit AES encryption initialization vector", cxxopts::value(ServerOptions.EncryptionIV), ""); options .add_option("lifetime", "", "owner-pid", "Specify owning process id", cxxopts::value(ServerOptions.OwnerPid), ""); options.add_option("lifetime", "", "child-id", "Specify id which can be used to signal parent", cxxopts::value(ServerOptions.ChildId), ""); #if ZEN_PLATFORM_WINDOWS options.add_option("lifetime", "", "install", "Install zenserver as a Windows service", cxxopts::value(ServerOptions.InstallService), ""); options.add_option("lifetime", "", "uninstall", "Uninstall zenserver as a Windows service", cxxopts::value(ServerOptions.UninstallService), ""); #endif options.add_option("network", "", "http", "Select HTTP server implementation (asio|httpsys|null)", cxxopts::value(ServerOptions.HttpServerClass)->default_value(DefaultHttp), ""); options.add_option("network", "p", "port", "Select HTTP port", cxxopts::value(ServerOptions.BasePort)->default_value("1337"), ""); options.add_option("network", "", "websocket-port", "Websocket server port", cxxopts::value(ServerOptions.WebSocketPort)->default_value("0"), ""); options.add_option("network", "", "websocket-threads", "Number of websocket I/O thread(s) (0 == hardware concurrency)", cxxopts::value(ServerOptions.WebSocketThreads)->default_value("0"), ""); #if ZEN_ENABLE_MESH options.add_option("network", "m", "mesh", "Enable mesh network", cxxopts::value(ServerOptions.MeshEnabled)->default_value("false"), ""); #endif #if ZEN_WITH_TRACE options.add_option("ue-trace", "", "tracehost", "Hostname to send the trace to", cxxopts::value(ServerOptions.TraceHost)->default_value(""), ""); options.add_option("ue-trace", "", "tracefile", "Path to write a trace to", cxxopts::value(ServerOptions.TraceFile)->default_value(""), ""); #endif // ZEN_WITH_TRACE options.add_option("diagnostics", "", "crash", "Simulate a crash", cxxopts::value(ServerOptions.ShouldCrash)->default_value("false"), ""); std::string UpstreamCachePolicyOptions; options.add_option("cache", "", "upstream-cache-policy", "", cxxopts::value(UpstreamCachePolicyOptions)->default_value(""), "Upstream cache policy (readwrite|readonly|writeonly|disabled)"); options.add_option("cache", "", "upstream-jupiter-url", "URL to a Jupiter instance", cxxopts::value(ServerOptions.UpstreamCacheConfig.JupiterConfig.Url)->default_value(""), ""); options.add_option("cache", "", "upstream-jupiter-oauth-url", "URL to the OAuth provier", cxxopts::value(ServerOptions.UpstreamCacheConfig.JupiterConfig.OAuthUrl)->default_value(""), ""); options.add_option("cache", "", "upstream-jupiter-oauth-clientid", "The OAuth client ID", cxxopts::value(ServerOptions.UpstreamCacheConfig.JupiterConfig.OAuthClientId)->default_value(""), ""); options.add_option("cache", "", "upstream-jupiter-oauth-clientsecret", "The OAuth client secret", cxxopts::value(ServerOptions.UpstreamCacheConfig.JupiterConfig.OAuthClientSecret)->default_value(""), ""); options.add_option("cache", "", "upstream-jupiter-openid-provider", "Name of a registered Open ID provider", cxxopts::value(ServerOptions.UpstreamCacheConfig.JupiterConfig.OpenIdProvider)->default_value(""), ""); options.add_option("cache", "", "upstream-jupiter-token", "A static authentication token", cxxopts::value(ServerOptions.UpstreamCacheConfig.JupiterConfig.AccessToken)->default_value(""), ""); options.add_option("cache", "", "upstream-jupiter-namespace", "The Common Blob Store API namespace", cxxopts::value(ServerOptions.UpstreamCacheConfig.JupiterConfig.Namespace)->default_value(""), ""); options.add_option("cache", "", "upstream-jupiter-namespace-ddc", "The lecacy DDC namespace", cxxopts::value(ServerOptions.UpstreamCacheConfig.JupiterConfig.DdcNamespace)->default_value(""), ""); options.add_option("cache", "", "upstream-jupiter-use-legacy-ddc", "Whether to store derived data using the legacy endpoint", cxxopts::value(ServerOptions.UpstreamCacheConfig.JupiterConfig.UseLegacyDdc)->default_value("false"), ""); options.add_option("cache", "", "upstream-zen-url", "URL to remote Zen server. Use a comma separated list to choose the one with the best latency.", cxxopts::value>(ServerOptions.UpstreamCacheConfig.ZenConfig.Urls), ""); options.add_option("cache", "", "upstream-zen-dns", "DNS that resolves to one or more Zen server instance(s)", cxxopts::value>(ServerOptions.UpstreamCacheConfig.ZenConfig.Dns), ""); options.add_option("cache", "", "upstream-thread-count", "Number of threads used for upstream procsssing", cxxopts::value(ServerOptions.UpstreamCacheConfig.UpstreamThreadCount)->default_value("4"), ""); options.add_option("cache", "", "upstream-connect-timeout-ms", "Connect timeout in millisecond(s). Default 5000 ms.", cxxopts::value(ServerOptions.UpstreamCacheConfig.ConnectTimeoutMilliseconds)->default_value("5000"), ""); options.add_option("cache", "", "upstream-timeout-ms", "Timeout in millisecond(s). Default 0 ms", cxxopts::value(ServerOptions.UpstreamCacheConfig.TimeoutMilliseconds)->default_value("0"), ""); options.add_option("compute", "", "upstream-horde-url", "URL to a Horde instance.", cxxopts::value(ServerOptions.UpstreamCacheConfig.HordeConfig.Url)->default_value(""), ""); options.add_option("compute", "", "upstream-horde-oauth-url", "URL to the OAuth provier", cxxopts::value(ServerOptions.UpstreamCacheConfig.HordeConfig.OAuthUrl)->default_value(""), ""); options.add_option("compute", "", "upstream-horde-oauth-clientid", "The OAuth client ID", cxxopts::value(ServerOptions.UpstreamCacheConfig.HordeConfig.OAuthClientId)->default_value(""), ""); options.add_option("compute", "", "upstream-horde-oauth-clientsecret", "The OAuth client secret", cxxopts::value(ServerOptions.UpstreamCacheConfig.HordeConfig.OAuthClientSecret)->default_value(""), ""); options.add_option("compute", "", "upstream-horde-openid-provider", "Name of a registered Open ID provider", cxxopts::value(ServerOptions.UpstreamCacheConfig.HordeConfig.OpenIdProvider)->default_value(""), ""); options.add_option("compute", "", "upstream-horde-token", "A static authentication token", cxxopts::value(ServerOptions.UpstreamCacheConfig.HordeConfig.AccessToken)->default_value(""), ""); options.add_option("compute", "", "upstream-horde-storage-url", "URL to a Horde Storage instance.", cxxopts::value(ServerOptions.UpstreamCacheConfig.HordeConfig.StorageUrl)->default_value(""), ""); options.add_option("compute", "", "upstream-horde-storage-oauth-url", "URL to the OAuth provier", cxxopts::value(ServerOptions.UpstreamCacheConfig.HordeConfig.StorageOAuthUrl)->default_value(""), ""); options.add_option("compute", "", "upstream-horde-storage-oauth-clientid", "The OAuth client ID", cxxopts::value(ServerOptions.UpstreamCacheConfig.HordeConfig.StorageOAuthClientId)->default_value(""), ""); options.add_option( "compute", "", "upstream-horde-storage-oauth-clientsecret", "The OAuth client secret", cxxopts::value(ServerOptions.UpstreamCacheConfig.HordeConfig.StorageOAuthClientSecret)->default_value(""), ""); options.add_option("compute", "", "upstream-horde-storage-openid-provider", "Name of a registered Open ID provider", cxxopts::value(ServerOptions.UpstreamCacheConfig.HordeConfig.StorageOpenIdProvider)->default_value(""), ""); options.add_option("compute", "", "upstream-horde-storage-token", "A static authentication token", cxxopts::value(ServerOptions.UpstreamCacheConfig.HordeConfig.StorageAccessToken)->default_value(""), ""); options.add_option("compute", "", "upstream-horde-cluster", "The Horde compute cluster id", cxxopts::value(ServerOptions.UpstreamCacheConfig.HordeConfig.Cluster)->default_value(""), ""); options.add_option("compute", "", "upstream-horde-namespace", "The Jupiter namespace to use with Horde compute", cxxopts::value(ServerOptions.UpstreamCacheConfig.HordeConfig.Namespace)->default_value(""), ""); options.add_option("gc", "", "gc-enabled", "Whether garbage collection is enabled or not.", cxxopts::value(ServerOptions.GcConfig.Enabled)->default_value("true"), ""); options.add_option("gc", "", "gc-small-objects", "Whether garbage collection is enabled or not.", cxxopts::value(ServerOptions.GcConfig.CollectSmallObjects)->default_value("true"), ""); options.add_option("gc", "", "gc-interval-seconds", "Garbage collection interval in seconds. Default set to 0 (Off).", cxxopts::value(ServerOptions.GcConfig.IntervalSeconds)->default_value("0"), ""); options.add_option("gc", "", "gc-cache-duration-seconds", "Max duration in seconds before Z$ entries get evicted.", cxxopts::value(ServerOptions.GcConfig.Cache.MaxDurationSeconds)->default_value("86400"), ""); options.add_option("gc", "", "disk-reserve-size", "Size of gc disk reserve in bytes.", cxxopts::value(ServerOptions.GcConfig.DiskReserveSize)->default_value("268435456"), ""); options.add_option("gc", "", "gc-monitor-interval-seconds", "Garbage collection monitoring interval in seconds.", cxxopts::value(ServerOptions.GcConfig.MonitorIntervalSeconds)->default_value("30"), ""); try { auto result = options.parse(argc, argv); ServerOptions.DataDir = DataDir; if (result.count("help")) { zen::logging::ConsoleLog().info("{}", options.help()); #if ZEN_PLATFORM_WINDOWS zen::logging::ConsoleLog().info("Press any key to exit!"); _getch(); #else // Assume the user's in a terminal on all other platforms and that // they'll use less/more/etc. if need be. #endif exit(0); } ServerOptions.DataDir = DataDir; ServerOptions.ContentDir = ContentDir; ServerOptions.AbsLogFile = AbsLogFile; ServerOptions.ConfigFile = ConfigFile; ServerOptions.UpstreamCacheConfig.CachePolicy = ParseUpstreamCachePolicy(UpstreamCachePolicyOptions); if (!ServerOptions.ConfigFile.empty()) { ParseConfigFile(ServerOptions.ConfigFile, ServerOptions); } else { ParseConfigFile(ServerOptions.DataDir / "zen_cfg.lua", ServerOptions); } ValidateOptions(ServerOptions); } catch (cxxopts::OptionParseException& e) { zen::logging::ConsoleLog().error("Error parsing zenserver arguments: {}\n\n{}", e.what(), options.help()); throw; } if (ServerOptions.DataDir.empty()) { ServerOptions.DataDir = PickDefaultStateDirectory(); } } void ParseConfigFile(const std::filesystem::path& Path, ZenServerOptions& ServerOptions) { zen::IoBuffer LuaScript = zen::IoBufferBuilder::MakeFromFile(Path); if (LuaScript) { sol::state lua; lua.open_libraries(sol::lib::base); lua.set_function("getenv", [&](const std::string env) -> sol::object { #if ZEN_PLATFORM_WINDOWS std::wstring EnvVarValue; size_t RequiredSize = 0; std::wstring EnvWide = zen::Utf8ToWide(env); _wgetenv_s(&RequiredSize, nullptr, 0, EnvWide.c_str()); if (RequiredSize == 0) return sol::make_object(lua, sol::lua_nil); EnvVarValue.resize(RequiredSize); _wgetenv_s(&RequiredSize, EnvVarValue.data(), RequiredSize, EnvWide.c_str()); return sol::make_object(lua, zen::WideToUtf8(EnvVarValue.c_str())); #else ZEN_UNUSED(env); return sol::make_object(lua, sol::lua_nil); #endif }); try { sol::load_result config = lua.load(std::string_view((const char*)LuaScript.Data(), LuaScript.Size()), "zen_cfg"); if (!config.valid()) { sol::error err = config; std::string ErrorString = sol::to_string(config.status()); throw std::runtime_error(fmt::format("{} error: {}", ErrorString, err.what())); } config(); } catch (std::exception& e) { throw std::runtime_error(fmt::format("failed to load config script ('{}'): {}", Path, e.what()).c_str()); } if (sol::optional ServerConfig = lua["server"]) { if (ServerOptions.DataDir.empty()) { if (sol::optional Opt = ServerConfig.value()["datadir"]) { ServerOptions.DataDir = Opt.value(); } } if (ServerOptions.ContentDir.empty()) { if (sol::optional Opt = ServerConfig.value()["contentdir"]) { ServerOptions.ContentDir = Opt.value(); } } if (ServerOptions.AbsLogFile.empty()) { if (sol::optional Opt = ServerConfig.value()["abslog"]) { ServerOptions.AbsLogFile = Opt.value(); } } ServerOptions.IsDebug = ServerConfig->get_or("debug", ServerOptions.IsDebug); } if (sol::optional NetworkConfig = lua["network"]) { if (sol::optional Opt = NetworkConfig.value()["httpserverclass"]) { ServerOptions.HttpServerClass = Opt.value(); } ServerOptions.BasePort = NetworkConfig->get_or("port", ServerOptions.BasePort); #if ZEN_ENABLE_MESH ServerOptions.MeshEnabled = NetworkConfig->get_or("meshenabled", ServerOptions.MeshEnabled); #endif } auto UpdateStringValueFromConfig = [](const sol::table& Table, std::string_view Key, std::string& OutValue) { // Update the specified config value unless it has been set, i.e. from command line if (auto MaybeValue = Table.get>(Key); MaybeValue.has_value() && OutValue.empty()) { OutValue = MaybeValue.value(); } }; if (sol::optional StructuredCacheConfig = lua["cache"]) { ServerOptions.StructuredCacheEnabled = StructuredCacheConfig->get_or("enable", ServerOptions.StructuredCacheEnabled); if (auto UpstreamConfig = StructuredCacheConfig->get>("upstream")) { std::string Policy = UpstreamConfig->get_or("policy", std::string()); ServerOptions.UpstreamCacheConfig.CachePolicy = ParseUpstreamCachePolicy(Policy); ServerOptions.UpstreamCacheConfig.UpstreamThreadCount = UpstreamConfig->get_or("upstreamthreadcount", ServerOptions.UpstreamCacheConfig.UpstreamThreadCount); if (auto JupiterConfig = UpstreamConfig->get>("jupiter")) { UpdateStringValueFromConfig(JupiterConfig.value(), std::string_view("name"), ServerOptions.UpstreamCacheConfig.JupiterConfig.Name); UpdateStringValueFromConfig(JupiterConfig.value(), std::string_view("url"), ServerOptions.UpstreamCacheConfig.JupiterConfig.Url); UpdateStringValueFromConfig(JupiterConfig.value(), std::string_view("oauthprovider"), ServerOptions.UpstreamCacheConfig.JupiterConfig.OAuthUrl); UpdateStringValueFromConfig(JupiterConfig.value(), std::string_view("oauthclientid"), ServerOptions.UpstreamCacheConfig.JupiterConfig.OAuthClientId); UpdateStringValueFromConfig(JupiterConfig.value(), std::string_view("oauthclientsecret"), ServerOptions.UpstreamCacheConfig.JupiterConfig.OAuthClientSecret); UpdateStringValueFromConfig(JupiterConfig.value(), std::string_view("openidprovider"), ServerOptions.UpstreamCacheConfig.JupiterConfig.OpenIdProvider); UpdateStringValueFromConfig(JupiterConfig.value(), std::string_view("token"), ServerOptions.UpstreamCacheConfig.JupiterConfig.AccessToken); UpdateStringValueFromConfig(JupiterConfig.value(), std::string_view("namespace"), ServerOptions.UpstreamCacheConfig.JupiterConfig.Namespace); UpdateStringValueFromConfig(JupiterConfig.value(), std::string_view("ddcnamespace"), ServerOptions.UpstreamCacheConfig.JupiterConfig.DdcNamespace); ServerOptions.UpstreamCacheConfig.JupiterConfig.UseLegacyDdc = JupiterConfig->get_or("uselegacyddc", ServerOptions.UpstreamCacheConfig.JupiterConfig.UseLegacyDdc); }; if (auto ZenConfig = UpstreamConfig->get>("zen")) { ServerOptions.UpstreamCacheConfig.ZenConfig.Name = ZenConfig.value().get_or("name", std::string("Zen")); if (auto Url = ZenConfig.value().get>("url")) { ServerOptions.UpstreamCacheConfig.ZenConfig.Urls.push_back(Url.value()); } else if (auto Urls = ZenConfig.value().get>("url")) { for (const auto& Kv : Urls.value()) { ServerOptions.UpstreamCacheConfig.ZenConfig.Urls.push_back(Kv.second.as()); } } if (auto Dns = ZenConfig.value().get>("dns")) { ServerOptions.UpstreamCacheConfig.ZenConfig.Dns.push_back(Dns.value()); } else if (auto DnsArray = ZenConfig.value().get>("dns")) { for (const auto& Kv : DnsArray.value()) { ServerOptions.UpstreamCacheConfig.ZenConfig.Dns.push_back(Kv.second.as()); } } } } } if (sol::optional ExecConfig = lua["exec"]) { ServerOptions.ExecServiceEnabled = ExecConfig->get_or("enable", ServerOptions.ExecServiceEnabled); } if (sol::optional ComputeConfig = lua["compute"]) { ServerOptions.ComputeServiceEnabled = ComputeConfig->get_or("enable", ServerOptions.ComputeServiceEnabled); if (auto UpstreamConfig = ComputeConfig->get>("upstream")) { if (auto HordeConfig = UpstreamConfig->get>("horde")) { UpdateStringValueFromConfig(HordeConfig.value(), std::string_view("name"), ServerOptions.UpstreamCacheConfig.HordeConfig.Name); UpdateStringValueFromConfig(HordeConfig.value(), std::string_view("url"), ServerOptions.UpstreamCacheConfig.HordeConfig.Url); UpdateStringValueFromConfig(HordeConfig.value(), std::string_view("oauthprovider"), ServerOptions.UpstreamCacheConfig.HordeConfig.OAuthUrl); UpdateStringValueFromConfig(HordeConfig.value(), std::string_view("oauthclientid"), ServerOptions.UpstreamCacheConfig.HordeConfig.OAuthClientId); UpdateStringValueFromConfig(HordeConfig.value(), std::string_view("oauthclientsecret"), ServerOptions.UpstreamCacheConfig.HordeConfig.OAuthClientSecret); UpdateStringValueFromConfig(HordeConfig.value(), std::string_view("openidprovider"), ServerOptions.UpstreamCacheConfig.HordeConfig.OpenIdProvider); UpdateStringValueFromConfig(HordeConfig.value(), std::string_view("token"), ServerOptions.UpstreamCacheConfig.HordeConfig.AccessToken); UpdateStringValueFromConfig(HordeConfig.value(), std::string_view("cluster"), ServerOptions.UpstreamCacheConfig.HordeConfig.Cluster); UpdateStringValueFromConfig(HordeConfig.value(), std::string_view("namespace"), ServerOptions.UpstreamCacheConfig.HordeConfig.Namespace); }; if (auto StorageConfig = UpstreamConfig->get>("storage")) { UpdateStringValueFromConfig(StorageConfig.value(), std::string_view("url"), ServerOptions.UpstreamCacheConfig.HordeConfig.StorageUrl); UpdateStringValueFromConfig(StorageConfig.value(), std::string_view("oauthprovider"), ServerOptions.UpstreamCacheConfig.HordeConfig.StorageOAuthUrl); UpdateStringValueFromConfig(StorageConfig.value(), std::string_view("oauthclientid"), ServerOptions.UpstreamCacheConfig.HordeConfig.StorageOAuthClientId); UpdateStringValueFromConfig(StorageConfig.value(), std::string_view("oauthclientsecret"), ServerOptions.UpstreamCacheConfig.HordeConfig.StorageOAuthClientSecret); UpdateStringValueFromConfig(StorageConfig.value(), std::string_view("openidprovider"), ServerOptions.UpstreamCacheConfig.HordeConfig.StorageOpenIdProvider); UpdateStringValueFromConfig(StorageConfig.value(), std::string_view("token"), ServerOptions.UpstreamCacheConfig.HordeConfig.StorageAccessToken); }; } } if (sol::optional GcConfig = lua["gc"]) { ServerOptions.GcConfig.MonitorIntervalSeconds = GcConfig.value().get_or("monitorintervalseconds", 30); ServerOptions.GcConfig.IntervalSeconds = GcConfig.value().get_or("intervalseconds", 0); ServerOptions.GcConfig.DiskReserveSize = GcConfig.value().get_or("diskreservesize", uint64_t(1u << 28)); if (sol::optional CacheGcConfig = GcConfig.value()["cache"]) { ServerOptions.GcConfig.Cache.MaxDurationSeconds = CacheGcConfig.value().get_or("maxdurationseconds", int32_t(0)); ServerOptions.GcConfig.Cache.DiskSizeLimit = CacheGcConfig.value().get_or("disksizelimit", ~uint64_t(0)); ServerOptions.GcConfig.Cache.MemorySizeLimit = CacheGcConfig.value().get_or("memorysizelimit", ~uint64_t(0)); } if (sol::optional CasGcConfig = GcConfig.value()["cas"]) { ServerOptions.GcConfig.Cas.LargeStrategySizeLimit = CasGcConfig.value().get_or("largestrategysizelimit", ~uint64_t(0)); ServerOptions.GcConfig.Cas.SmallStrategySizeLimit = CasGcConfig.value().get_or("smallstrategysizelimit", ~uint64_t(0)); ServerOptions.GcConfig.Cas.TinyStrategySizeLimit = CasGcConfig.value().get_or("tinystrategysizelimit", ~uint64_t(0)); } } if (sol::optional SecurityConfig = lua["security"]) { ServerOptions.EncryptionKey = SecurityConfig.value().get_or("encryptionaeskey", std::string()); ServerOptions.EncryptionIV = SecurityConfig.value().get_or("encryptionaesiv", std::string()); } } }