87 lines
4.5 KiB
C#
87 lines
4.5 KiB
C#
using System;
|
||
using System.IO;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using XWorld.Server.Gateway;
|
||
|
||
namespace XWorld.Server.Gateway.Runner
|
||
{
|
||
public static class Program
|
||
{
|
||
public static async Task Main(string[] args)
|
||
{
|
||
string gamesRoot = GetArg(args, "--gamesRoot") ??
|
||
Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..", "..", "..", "..", "Server.Host.Tests", "TestGames"));
|
||
int port = int.TryParse(GetArg(args, "--port"), out int p) ? p : 5005;
|
||
int tickMs = int.TryParse(GetArg(args, "--tickMs"), out int t) ? t : 100;
|
||
long matchTimeoutTicks = long.TryParse(GetArg(args, "--matchTimeoutTicks"), out long mt) ? mt : 150;
|
||
string devToken = GetArg(args, "--devToken");
|
||
string advertiseWs = GetArg(args, "--advertiseWs");
|
||
string advertiseCdn = GetArg(args, "--advertiseCdn");
|
||
bool lan = Array.Exists(args, a => string.Equals(a, "--lan", StringComparison.OrdinalIgnoreCase));
|
||
int cdnPort = int.TryParse(GetArg(args, "--cdnPort"), out int cp) ? cp : 15081;
|
||
// --lan 下若未显式给 CDN 地址,用本机 LAN IP + 约定端口兜底广而告之 CDN 根
|
||
// (客户端从根派生两套:minigame/<id>/<ver>/ 与 XWorld/<platform>/;advertiseWs 缺省由 GameServerHost 内部用 LanIp 兜底)
|
||
if (lan && string.IsNullOrEmpty(advertiseCdn))
|
||
advertiseCdn = $"http://{XWorld.Server.Gateway.LanIp.Resolve()}:{cdnPort}/";
|
||
|
||
// 鉴权 opt-in:给了 --authDbPath 才启用账号鉴权(/register、/login、/ws 验 token)。
|
||
// 密钥优先级:--authSecret(base64) > DB 同目录 auth.key 文件(不存在则生成并持久化)。
|
||
string authDbPath = GetArg(args, "--authDbPath");
|
||
string authSecretB64 = GetArg(args, "--authSecret");
|
||
byte[] authSecret = null;
|
||
if (!string.IsNullOrEmpty(authDbPath))
|
||
{
|
||
if (!string.IsNullOrEmpty(authSecretB64))
|
||
authSecret = Convert.FromBase64String(authSecretB64);
|
||
else
|
||
{
|
||
string keyPath = Path.Combine(
|
||
Path.GetDirectoryName(Path.GetFullPath(authDbPath)) ?? ".", "auth.key");
|
||
if (File.Exists(keyPath))
|
||
authSecret = Convert.FromBase64String(File.ReadAllText(keyPath).Trim());
|
||
else
|
||
{
|
||
authSecret = System.Security.Cryptography.RandomNumberGenerator.GetBytes(32);
|
||
File.WriteAllText(keyPath, Convert.ToBase64String(authSecret));
|
||
}
|
||
}
|
||
}
|
||
|
||
var host = new GameServerHost();
|
||
await host.StartAsync(gamesRoot, tickMs, matchTimeoutTicks: matchTimeoutTicks, listenPort: port,
|
||
bindAllInterfaces: lan,
|
||
devDiscoveryToken: devToken, advertiseGatewayUrl: advertiseWs, advertiseResourceBaseUrl: advertiseCdn,
|
||
authSecret: authSecret, authDbPath: authDbPath);
|
||
Console.WriteLine("XWorld Gateway smoke server started.");
|
||
Console.WriteLine(" gamesRoot: " + gamesRoot);
|
||
Console.WriteLine(" tickMs: " + tickMs + ", matchTimeoutTicks: " + matchTimeoutTicks);
|
||
Console.WriteLine(" ws: " + host.WsBaseUrl + "/ws?pid=1");
|
||
if (!string.IsNullOrEmpty(devToken))
|
||
Console.WriteLine(" dev-discovery: ON (UDP " + host.DevDiscoveryPort + "), advertise ws=" +
|
||
(string.IsNullOrEmpty(advertiseWs) ? host.WsBaseUrl + "/ws" : advertiseWs) + " cdn=" + advertiseCdn);
|
||
Console.WriteLine(" auth: " + (authSecret != null ? ("ON (db=" + authDbPath + ", /register /login /ws?token=)") : "OFF (dev ?pid=)"));
|
||
Console.WriteLine("Press Ctrl+C to stop.");
|
||
|
||
using var stop = new CancellationTokenSource();
|
||
Console.CancelKeyPress += (s, e) =>
|
||
{
|
||
e.Cancel = true;
|
||
stop.Cancel();
|
||
};
|
||
|
||
try { await Task.Delay(Timeout.InfiniteTimeSpan, stop.Token); }
|
||
catch (OperationCanceledException) { }
|
||
await host.StopAsync();
|
||
}
|
||
|
||
private static string GetArg(string[] args, string name)
|
||
{
|
||
for (int i = 0; i < args.Length - 1; i++)
|
||
if (string.Equals(args[i], name, StringComparison.OrdinalIgnoreCase))
|
||
return args[i + 1];
|
||
return null;
|
||
}
|
||
}
|
||
}
|