// ============================================================================= // RelayServer entrypoint. // // Boot sequence: // 1. Connect to SurrealDB (port 8000) via SurrealService. // 2. Wire static singletons onto ChatSocketBehavior (it's a WebSocketSharp // WebSocketBehavior, so DI is impossible — fields are static). // 3. Run ServerBootstrapService.InitializeAsync — seeds users, server, members, // channels (welcome, general, files, voice-general), roles, role assignments, // channel permission overrides, and encryption keys. Idempotent across reboots. // 4. Start two listeners in parallel: // - HTTP API on 127.0.0.1:5000 (RtcEndpoints — REST for RTC call orchestration) // - WebSocket server on 127.0.0.1:5001 (ChatSocketBehavior — the chat/RTC-signal pipe) // 5. Block on ConsoleCommandService.ShutdownTokenSource for graceful shutdown. // // Why two listeners? The HTTP API is used for one-shot RPC-style calls (e.g. "fetch // the participant list for this voice channel"). The WebSocket is the persistent // duplex pipe used for chat, typing, presence, encrypted RTC signalling. // ============================================================================= using RelayServer.Endpoints; using RelayServer.Services.Chat; using RelayServer.Services.Core; using RelayServer.Services.Data; using RelayServer.Services.Rtc; using RelayShared.Rtc; using RelayShared.Services; using WebSocketSharp.Server; var surrealService = new SurrealService(); var coreClient = new CoreClientService(); var cryptoService = new ChannelCryptoService(); await using var db = await surrealService.ConnectAsync(); ChatSocketBehavior.ClientKeyService = new ClientKeyService(db); ChatSocketBehavior.PermissionService = new PermissionService(db); ChatSocketBehavior.Db = db; ChatSocketBehavior.ChannelCryptoService = cryptoService; var bootstrapService = new ServerBootstrapService(db, coreClient, cryptoService); await bootstrapService.InitializeAsync(); var builder = WebApplication.CreateBuilder(args); builder.WebHost.UseUrls("http://127.0.0.1:5000/"); // builder.WebHost.UseUrls("http://192.168.1.92:5000/"); builder.Services.AddSingleton(db); builder.Services.AddScoped(); var app = builder.Build(); app.MapGet("/", () => "Server Running!"); app.MapRtcEndpoints(); var wssv = new WebSocketServer("ws://127.0.0.1:5001"); // var wssv = new WebSocketServer("ws://192.168.1.92:5001"); wssv.AddWebSocketService("/"); RtcNotificationService.Server = wssv; wssv.Start(); Console.WriteLine("WebSocket server started"); await app.StartAsync(); Console.WriteLine("HTTP API started"); ConsoleCommandService.Start(); await Task.Delay(Timeout.Infinite, ConsoleCommandService.ShutdownTokenSource.Token); wssv.Stop(); await app.StopAsync(); return;