diff --git a/GServer.NCSServer/GServer.NCSServer.csproj b/GServer.NCSServer/GServer.NCSServer.csproj deleted file mode 100644 index ebc74e5..0000000 --- a/GServer.NCSServer/GServer.NCSServer.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - net8.0 - enable - enable - - - - - - - diff --git a/GServer.NCSServer/GameSession.cs b/GServer.NCSServer/GameSession.cs deleted file mode 100644 index ca24f5a..0000000 --- a/GServer.NCSServer/GameSession.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System.Net.Sockets; -using NetCoreServer; - -namespace GServer.NCSServer; - -public class GameSession : TcpSession -{ - public GameSession(TcpServer server) : base(server) - { - } - - protected override void OnConnected() - { - Console.WriteLine($"Chat TCP session with Id {Id} connected!"); - } - - protected override void OnConnecting() - { - base.OnConnecting(); - } - - protected override void OnDisconnecting() - { - base.OnDisconnecting(); - } - - protected override void OnDisconnected() - { - Console.WriteLine($"Chat TCP session with Id {Id} disconnected!"); - } - - protected override void OnReceived(byte[] buffer, long offset, long size) - { - base.OnReceived(buffer, offset, size); - } - - protected override void OnSent(long sent, long pending) - { - base.OnSent(sent, pending); - } - - protected override void OnEmpty() - { - base.OnEmpty(); - } - - protected override void OnError(SocketError error) - { - base.OnError(error); - } -} \ No newline at end of file diff --git a/GServer.NCSServer/Program.cs b/GServer.NCSServer/Program.cs deleted file mode 100644 index d5d844b..0000000 --- a/GServer.NCSServer/Program.cs +++ /dev/null @@ -1,4 +0,0 @@ -WebApplicationBuilder builder = WebApplication.CreateBuilder(args); -WebApplication app = builder.Build(); - -app.Run(); diff --git a/GServer.NCSServer/Properties/launchSettings.json b/GServer.NCSServer/Properties/launchSettings.json deleted file mode 100644 index e5a5080..0000000 --- a/GServer.NCSServer/Properties/launchSettings.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "$schema": "http://json.schemastore.org/launchsettings.json", - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:58673", - "sslPort": 44396 - } - }, - "profiles": { - "http": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "applicationUrl": "http://localhost:5051", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "https": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "applicationUrl": "https://localhost:7192;http://localhost:5051", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } -} diff --git a/GServer.NCSServer/appsettings.Development.json b/GServer.NCSServer/appsettings.Development.json deleted file mode 100644 index ff66ba6..0000000 --- a/GServer.NCSServer/appsettings.Development.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - } -} diff --git a/GServer.NCSServer/appsettings.json b/GServer.NCSServer/appsettings.json deleted file mode 100644 index 4d56694..0000000 --- a/GServer.NCSServer/appsettings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - }, - "AllowedHosts": "*" -} diff --git a/GServer.Server/Business/Services/AuthService.cs b/GServer.Server/Business/Services/AuthService.cs new file mode 100644 index 0000000..89237a9 --- /dev/null +++ b/GServer.Server/Business/Services/AuthService.cs @@ -0,0 +1,21 @@ +namespace GServer.Server.Business.Services; + +public interface IAuthService +{ + /// + /// Checks whether a given email and password combination match. + /// + /// + /// + /// + bool IsPasswordCorrect(string email, string password); +} + +public class AuthService : IAuthService +{ + public bool IsPasswordCorrect(string username, string password) + { + // TODO: Check DB + return username == "aaronyarbz" && password == "password123"; + } +} \ No newline at end of file diff --git a/GServer.Server/GServer.Server.csproj b/GServer.Server/GServer.Server.csproj index 29b7a00..d4d61b9 100644 --- a/GServer.Server/GServer.Server.csproj +++ b/GServer.Server/GServer.Server.csproj @@ -4,6 +4,11 @@ + + + + + Exe net8.0 diff --git a/GServer.Server/Program.cs b/GServer.Server/Program.cs index 3155efa..4ee2726 100644 --- a/GServer.Server/Program.cs +++ b/GServer.Server/Program.cs @@ -1,4 +1,7 @@ using System.Net; +using GServer.Server.Business.Services; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; namespace GServer.Server; @@ -7,17 +10,44 @@ internal sealed class Program { private const int ListenPort = 11000; - private static void Main(string[] args) + private static async Task Main(string[] args) { - - CancellationTokenSource cancellationTokenSource = new(); + HostApplicationBuilder builder = Host.CreateApplicationBuilder(args); - Thread serverWorker = new(delegate() + // Register services + _ = builder.Services.AddScoped(); + _ = builder.Services.AddScoped(); + _ = builder.Services.AddTransient((services) => { - TcpGameServer server = new(new IPEndPoint(IPAddress.Any, ListenPort), new GameServerOptions()); + return new TcpGameServer( + new IPEndPoint(IPAddress.Any, ListenPort), + services.GetRequiredService() + ); + }); + + // Start service + using IHost host = builder.Build(); + ApplicationLifetime(host.Services); + await host.RunAsync(); + } + + private static void ApplicationLifetime(IServiceProvider hostProvider) + { + using IServiceScope serviceScope = hostProvider.CreateScope(); + + Thread serverWorker = new(() => + { + ITcpGameServer server = serviceScope.ServiceProvider.GetRequiredService(); server.Start(); + + while (true) + { + // Sleep to not consume too much CPU while waiting + Thread.Sleep(1000); + } }); serverWorker.Start(); + serverWorker.Join(); // Wait for the thread to complete before disposing the scope } } \ No newline at end of file diff --git a/GServer.Server/TcpGameServer.cs b/GServer.Server/TcpGameServer.cs index 326f4b7..67e2fa3 100644 --- a/GServer.Server/TcpGameServer.cs +++ b/GServer.Server/TcpGameServer.cs @@ -1,15 +1,21 @@ using System.Net; using System.Net.Sockets; using GServer.Common.Networking.Core; -using GServer.Common.Networking.Messages; namespace GServer.Server; -public class TcpGameServer(IPEndPoint endPoint, GameServerOptions options) : IDisposable +public interface ITcpGameServer +{ + void Dispose(); + void Start(); +} + +public class TcpGameServer( + IPEndPoint endPoint, + ITcpMessageHandler messageHandler +) : IDisposable, ITcpGameServer { - private readonly GameServerOptions _options = options; private readonly TcpListener _tcpListener = new(endPoint); - private readonly IMessageHandler _messageHandler = new TcpMessageHandler(); /// /// Bind the server to the given endpoint. @@ -26,41 +32,46 @@ public class TcpGameServer(IPEndPoint endPoint, GameServerOptions options) : IDi { Console.WriteLine("Waiting for a connection..."); - _tcpListener.AcceptTcpClient(); + TcpClient client = _tcpListener.AcceptTcpClient(); Console.WriteLine("Client accepted!"); - Thread worker = new Thread(new ParameterizedThreadStart(HandleClient!)); - worker.Start(); + Thread worker = new(new ParameterizedThreadStart(HandleClient!)); // TODO: use thread pools instead + worker.Start(client); } - finally + catch (Exception ex) { - _tcpListener.Stop(); + Console.WriteLine($"An error occured while processing a tcp connection: {ex.Message}"); } } } - private void HandleClient(object clientObj) + private async void HandleClient(object clientObj) { - TcpClient tcpClient = (TcpClient)clientObj; + if (clientObj is not TcpClient tcpClient) + { + return; + } try { - using NetworkStream stream = tcpClient.GetStream(); - - byte[] data = new byte[tcpClient.ReceiveBufferSize]; - while (stream.Read(data, 0, data.Length) != 0) + using (tcpClient) + using (NetworkStream stream = tcpClient.GetStream()) { - // Use the in-memory buffer to process the message - _messageHandler.HandleMessageAsync(stream.Socket, new MessageMemoryStream(data)).Wait(); + byte[] data = new byte[tcpClient.ReceiveBufferSize]; + while (stream.Read(data, 0, data.Length) != 0) + { + // Use the in-memory buffer to process the message + await messageHandler.HandleMessageAsync(stream.Socket, new MessageMemoryStream(data)); + } } } catch (Exception ex) { - Console.WriteLine(ex); + Console.WriteLine($"Error handling client: {ex.Message}"); } } - private async void Stop() + private void Stop() { Console.WriteLine($"Stopping ${nameof(TcpGameServer)} listener..."); _tcpListener.Stop(); diff --git a/GServer.Server/TcpMessageHandler.cs b/GServer.Server/TcpMessageHandler.cs index 6555972..306db1d 100644 --- a/GServer.Server/TcpMessageHandler.cs +++ b/GServer.Server/TcpMessageHandler.cs @@ -4,10 +4,18 @@ using GServer.Common.Networking.Enums; using GServer.Common.Networking.Messages; using GServer.Common.Networking.Messages.Client; using GServer.Common.Networking.Messages.Server; +using GServer.Server.Business.Services; namespace GServer.Server; -public class TcpMessageHandler : IMessageHandler +public interface ITcpMessageHandler +{ + Task HandleMessageAsync(Socket clientSocket, MessageMemoryStream messageStream); +} + +public class TcpMessageHandler( + IAuthService authService +) : IMessageHandler, ITcpMessageHandler { public async Task HandleMessageAsync(Socket clientSocket, MessageMemoryStream messageStream) { @@ -20,7 +28,8 @@ public class TcpMessageHandler : IMessageHandler case ServerPacketIn.Auth: AuthMessage msg = new(messageStream); - AuthResponseMessage resp = msg is { Username: "aaronyarbz", Password: "password123" } + bool isPasswordCorrect = authService.IsPasswordCorrect(msg.Username, msg.Password); + AuthResponseMessage resp = isPasswordCorrect ? new(true, Guid.NewGuid().ToString(), failureReason: null) : new(false, null, AuthResponseFailure.IncorrectLoginOrPassword);