124 lines
5.0 KiB
Plaintext
124 lines
5.0 KiB
Plaintext
using Cysharp.Threading.Tasks;
|
|
using ShrinkNetwork;
|
|
|
|
namespace ShrinkNetwork.ServerHost.Framework;
|
|
|
|
public sealed class ShrinkDedicatedServerApp
|
|
{
|
|
private readonly List<IShrinkServerModule> _modules;
|
|
private readonly ServerModuleContext _context;
|
|
|
|
public ShrinkDedicatedServerApp(ServerHostOptions options, params IShrinkServerModule[] modules)
|
|
{
|
|
_modules = modules.ToList();
|
|
_context = new ServerModuleContext(options, new ServerAuthStore());
|
|
}
|
|
|
|
public ServerModuleContext Context => _context;
|
|
|
|
public async UniTask StartAsync(CancellationToken cancellationToken = default)
|
|
{
|
|
if (_context.Options.EnableUnityCodeScan)
|
|
{
|
|
var manifest = UnityNetworkCodeScanner.Scan(_context.Options.UnityAssetsPath);
|
|
UnityNetworkCodeScanner.WriteOutputs(manifest, _context.Options.ScanOutputDirectory);
|
|
_context.ScanManifest = manifest;
|
|
}
|
|
|
|
var tcpService = CreateService("TCP");
|
|
var kcpService = CreateService("KCP");
|
|
|
|
_context.RegisterService("TCP", tcpService);
|
|
_context.RegisterService("KCP", kcpService);
|
|
|
|
foreach (var module in _modules)
|
|
{
|
|
module.ConfigureService(_context, tcpService, "TCP");
|
|
module.ConfigureService(_context, kcpService, "KCP");
|
|
}
|
|
|
|
tcpService.BindTransport(new TcpServerTransport(System.Net.IPAddress.Any, _context.Options.Port,
|
|
tlsOptions: BuildTcpTlsOptions()));
|
|
kcpService.BindTransport(new KcpServerTransport(System.Net.IPAddress.Any, _context.Options.Port, new ShrinkKcpTransportOptions
|
|
{
|
|
Interval = 10,
|
|
UpdateIntervalMs = 10,
|
|
IdleTimeoutMs = 15000,
|
|
HandshakeRetryMs = 250,
|
|
ConnectTimeoutMs = 4000
|
|
}));
|
|
|
|
foreach (var module in _modules)
|
|
module.StartAsync(_context, cancellationToken).Forget();
|
|
|
|
await UniTask.CompletedTask;
|
|
}
|
|
|
|
private ShrinkNetworkService CreateService(string transportName)
|
|
{
|
|
var service = new ShrinkNetworkService(new ShrinkJsonNetworkSerializer(),
|
|
new ShrinkNetworkMessageRegistry(),
|
|
new ShrinkNetworkRouter());
|
|
service.MinProtocolVersion = _context.Options.MinProtocolVersion;
|
|
service.MaxProtocolVersion = _context.Options.MaxProtocolVersion;
|
|
service.MinSchemaVersion = _context.Options.MinSchemaVersion;
|
|
service.MaxSchemaVersion = _context.Options.MaxSchemaVersion;
|
|
service.DisconnectOnProtocolViolation = _context.Options.DisconnectOnProtocolViolation;
|
|
service.IncomingPacketValidator = (session, packet) => ValidateIncomingPacket(service, session, packet);
|
|
|
|
service.OnSessionConnected += session =>
|
|
{
|
|
session.SetPeerKind(ShrinkNetworkPeerKind.Client);
|
|
ShrinkNetworkLogger.Info($"[{transportName}] Client connected: {session.SessionId} {session.RemoteAddress}");
|
|
};
|
|
service.OnSessionDisconnected += session =>
|
|
{
|
|
_context.AuthStore.Remove(service, session.SessionId);
|
|
ShrinkNetworkLogger.Info($"[{transportName}] Client disconnected: {session.SessionId}");
|
|
};
|
|
|
|
return service;
|
|
}
|
|
|
|
private ShrinkIncomingPacketValidationResult ValidateIncomingPacket(
|
|
ShrinkNetworkService service,
|
|
ShrinkNetworkSession session,
|
|
ShrinkNetworkPacket packet)
|
|
{
|
|
if (!_context.Options.EnableSessionTokens)
|
|
return ShrinkIncomingPacketValidationResult.Allow;
|
|
if (packet.Kind == ShrinkNetworkPacketKind.Response)
|
|
return ShrinkIncomingPacketValidationResult.Allow;
|
|
if (string.Equals(packet.Route, AuthServerModule.LoginRoute, StringComparison.Ordinal) ||
|
|
string.Equals(packet.Route, AuthServerModule.RefreshRoute, StringComparison.Ordinal))
|
|
return ShrinkIncomingPacketValidationResult.Allow;
|
|
if (!_context.AuthStore.TryGetState(service, session.SessionId, out _))
|
|
return ShrinkIncomingPacketValidationResult.Allow;
|
|
|
|
if (_context.AuthStore.TryValidateSessionToken(service, session.SessionId, packet.SessionToken, out var authState,
|
|
out var failureReason))
|
|
{
|
|
session.SetSessionToken(authState.SessionToken, authState.SessionTokenExpiresAtUtc);
|
|
return ShrinkIncomingPacketValidationResult.Allow;
|
|
}
|
|
|
|
return ShrinkIncomingPacketValidationResult.Reject(failureReason,
|
|
_context.Options.DisconnectOnInvalidSessionToken);
|
|
}
|
|
|
|
private ShrinkTcpTlsOptions? BuildTcpTlsOptions()
|
|
{
|
|
if (!_context.Options.EnableTcpTls)
|
|
return null;
|
|
|
|
return new ShrinkTcpTlsOptions
|
|
{
|
|
Enabled = true,
|
|
TargetHost = _context.Options.TcpTlsTargetHost,
|
|
ServerCertificatePath = _context.Options.TcpTlsCertificatePath,
|
|
ServerCertificatePassword = _context.Options.TcpTlsCertificatePassword,
|
|
CheckCertificateRevocation = _context.Options.TcpTlsCheckCertificateRevocation
|
|
};
|
|
}
|
|
}
|