From 35755eb7ecfa747f611f39378d6e80f772d85e82 Mon Sep 17 00:00:00 2001 From: Aaron Yarborough Date: Wed, 22 May 2024 17:31:06 +0100 Subject: [PATCH] feat: wip: use TcpClient --- GServer.Client/Program.cs | 2 +- .../Networking/Core/MessageMemoryStream.cs | 4 - .../Messages/Client/AuthResponseMessage.cs | 4 +- .../Client/ListServersResponseMessage.cs | 2 +- .../Networking/Messages/Server/AuthMessage.cs | 2 +- GServer.Server/GameServerOptions.cs | 6 + GServer.Server/TCPGameServer.cs | 116 ++++++++++++++++++ GServer.Server/UDPGameServer.cs | 29 +---- notes | 5 + 9 files changed, 138 insertions(+), 32 deletions(-) create mode 100644 GServer.Server/GameServerOptions.cs create mode 100644 GServer.Server/TCPGameServer.cs create mode 100644 notes diff --git a/GServer.Client/Program.cs b/GServer.Client/Program.cs index 50cbc86..60a6042 100644 --- a/GServer.Client/Program.cs +++ b/GServer.Client/Program.cs @@ -32,7 +32,7 @@ internal class Program { byte[] bytes = udpClient.Receive(ref serverEP); - MessageMemoryStream stream = new(bytes); + MessageNetworkStream stream = new(bytes); ClientPacketIn packetIn = (ClientPacketIn)stream.ReadByte(); switch (packetIn) diff --git a/GServer.Common/Networking/Core/MessageMemoryStream.cs b/GServer.Common/Networking/Core/MessageMemoryStream.cs index b2ea9b8..3e0db44 100644 --- a/GServer.Common/Networking/Core/MessageMemoryStream.cs +++ b/GServer.Common/Networking/Core/MessageMemoryStream.cs @@ -4,10 +4,6 @@ namespace GServer.Common; public class MessageMemoryStream : MemoryStream { - public MessageMemoryStream() - { - } - public MessageMemoryStream(byte[] buffer) : base(buffer) { } diff --git a/GServer.Common/Networking/Messages/Client/AuthResponseMessage.cs b/GServer.Common/Networking/Messages/Client/AuthResponseMessage.cs index ad69d4d..8315f26 100644 --- a/GServer.Common/Networking/Messages/Client/AuthResponseMessage.cs +++ b/GServer.Common/Networking/Messages/Client/AuthResponseMessage.cs @@ -30,7 +30,7 @@ public class AuthResponseMessage : BaseMessage, IMessage FailureReason = failureReason; } - public AuthResponseMessage(MessageMemoryStream stream) : base((byte)ClientPacketIn.AUTH_RESPONSE) + public AuthResponseMessage(MessageNetworkStream stream) : base((byte)ClientPacketIn.AUTH_RESPONSE) { IsSuccessful = stream.ReadBoolean(); @@ -47,7 +47,7 @@ public class AuthResponseMessage : BaseMessage, IMessage public byte[] Serialize() { - using MessageMemoryStream stream = new(); + using MessageNetworkStream stream = new(); stream.WriteByte(PacketId); stream.WriteBoolean(IsSuccessful); diff --git a/GServer.Common/Networking/Messages/Client/ListServersResponseMessage.cs b/GServer.Common/Networking/Messages/Client/ListServersResponseMessage.cs index f658a9f..ce3c34b 100644 --- a/GServer.Common/Networking/Messages/Client/ListServersResponseMessage.cs +++ b/GServer.Common/Networking/Messages/Client/ListServersResponseMessage.cs @@ -12,7 +12,7 @@ public class ListServersResponseMessage : BaseMessage, IMessage Password = password; } - public AuthMessage(MessageMemoryStream stream) : base((byte)ServerPacketIn.AUTH) + public AuthMessage(MessageNetworkStream stream) : base((byte)ServerPacketIn.AUTH) { byte usernameLen = (byte)stream.ReadByte(); string username = stream.ReadUTF8String(usernameLen); diff --git a/GServer.Server/GameServerOptions.cs b/GServer.Server/GameServerOptions.cs new file mode 100644 index 0000000..6dd047f --- /dev/null +++ b/GServer.Server/GameServerOptions.cs @@ -0,0 +1,6 @@ +namespace GServer.Server; + +public class GameServerOptions +{ + public int PacketLength { get; set; } +} diff --git a/GServer.Server/TCPGameServer.cs b/GServer.Server/TCPGameServer.cs new file mode 100644 index 0000000..ffe46db --- /dev/null +++ b/GServer.Server/TCPGameServer.cs @@ -0,0 +1,116 @@ +using System.Net; +using System.Net.Sockets; +using GServer.Common; +using GServer.Common.Networking.Enums; +using GServer.Common.Networking.Messages.Client; +using GServer.Common.Networking.Messages.Server; + +namespace GServer.Server; + +public class TCPGameServer : IDisposable +{ + private readonly TcpListener _tcpListener; + private readonly IPEndPoint _endPoint; + private readonly GameServerOptions _options; + + public TCPGameServer(IPEndPoint endPoint, GameServerOptions options) + { + _endPoint = endPoint; + _options = options; + + _tcpListener = new TcpListener(endPoint); + } + + /// + /// Bind the server to the given endpoint. + /// + public async void Start() + { + Console.WriteLine("Starting TCPGameServer listener..."); + _tcpListener.Start(); + Console.WriteLine($"TCPGameServer listening on {_endPoint}"); + + try + { + while (true) + { + await ProcessAsync(await _tcpListener.AcceptTcpClientAsync()); + } + } + catch + { + throw; + } + finally + { + _tcpListener.Stop(); + } + } + + /// + /// Begin processing messages + /// + /// + public async Task ProcessAsync(TcpClient tcpClient) + { + try + { + using NetworkStream stream = tcpClient.GetStream(); + + byte[] data = new byte[_options.PacketLength]; + int bytesRead = 0; + int chunkSize = 1; + + // Read everything into the data buffer + while (bytesRead < data.Length && chunkSize > 0) + { + bytesRead += + chunkSize = + await stream.ReadAsync(data.AsMemory(bytesRead, data.Length - bytesRead)); + } + + // Use the in-memory buffer to process the message + await HandleMessageAsync(stream.Socket, new MessageMemoryStream(data)); + } + catch (Exception ex) + { + Console.WriteLine(ex); + } + } + + private async Task HandleMessageAsync(Socket clientSocket, MessageMemoryStream messageStream) + { + ServerPacketIn serverPacketIn = (ServerPacketIn)messageStream.ReadByte(); + + Console.WriteLine($"Handling message {serverPacketIn} from {client}..."); + + switch (serverPacketIn) + { + case ServerPacketIn.AUTH: + AuthMessage msg = new(messageStream); + + AuthResponseMessage resp = msg.Username == "aaronyarbz" && msg.Password == "password123" + ? new(true, Guid.NewGuid().ToString(), null) + : new(false, null, AuthResponseFailure.IncorrectLoginOrPassword); + + byte[] buffer = resp.Serialize(); + _ = await TcpClient.Client.SendAsync(buffer, + + break; + + case ServerPacketIn.LIST_SERVERS: + throw new NotImplementedException(); + + default: + Console.WriteLine($"Received unsupported packet."); + break; + } + } + + public void Dispose() + { + TcpClient.Close(); + TcpClient.Dispose(); + GC.SuppressFinalize(this); + } +} \ No newline at end of file diff --git a/GServer.Server/UDPGameServer.cs b/GServer.Server/UDPGameServer.cs index acacbae..b00bcbe 100644 --- a/GServer.Server/UDPGameServer.cs +++ b/GServer.Server/UDPGameServer.cs @@ -2,8 +2,6 @@ using System.Net; using System.Net.Sockets; using GServer.Common; using GServer.Common.Networking.Enums; -using GServer.Common.Networking.Messages.Client; -using GServer.Common.Networking.Messages.Server; namespace GServer.Server; @@ -43,7 +41,7 @@ public class UDPGameServer : IDisposable { UdpReceiveResult res = await UdpClient.ReceiveAsync(); byte[] bytes = res.Buffer; - MessageMemoryStream stream = new(bytes); + MessageNetworkStream stream = new(bytes); await HandleMessageAsync(stream, res.RemoteEndPoint); } catch (Exception ex) @@ -52,32 +50,17 @@ public class UDPGameServer : IDisposable } } - private async Task HandleMessageAsync(MessageMemoryStream stream, IPEndPoint remoteEndPoint) + private async Task HandleMessageAsync(MessageNetworkStream stream, IPEndPoint remoteEndPoint) { - ServerPacketIn serverPacketIn = (ServerPacketIn)stream.ReadByte(); + byte serverPacketInByte = (byte)stream.ReadByte(); + ServerPacketIn serverPacketIn = (ServerPacketIn)serverPacketInByte; - Console.WriteLine($"Handling message {serverPacketIn} from {remoteEndPoint}..."); + Console.WriteLine($"Handling UDP message {serverPacketInByte} from {remoteEndPoint}..."); switch (serverPacketIn) { - case ServerPacketIn.AUTH: - AuthMessage msg = new(stream); - - AuthResponseMessage resp = msg.Username == "aaronyarbz" && msg.Password == "password123" - ? new(true, Guid.NewGuid().ToString(), null) - : new(false, null, AuthResponseFailure.IncorrectLoginOrPassword); - - byte[] buffer = resp.Serialize(); - _ = await UdpClient.SendAsync(buffer, buffer.Length, remoteEndPoint); - - break; - - case ServerPacketIn.LIST_SERVERS: - throw new NotImplementedException(); - default: - Console.WriteLine($"Received unsupported packet."); - break; + throw new NotImplementedException($"Received unsupported packet {serverPacketInByte}"); } } diff --git a/notes b/notes new file mode 100644 index 0000000..468cda7 --- /dev/null +++ b/notes @@ -0,0 +1,5 @@ +potentially move flag type to short from byte + + +single thread accept + - spin up multiple threads to deal with actions \ No newline at end of file