From 6d72bef8d21f9034afe47050cfdf7cd548a0e68d Mon Sep 17 00:00:00 2001 From: MaxXor Date: Wed, 9 Sep 2015 00:19:48 +0200 Subject: [PATCH] Fixes to networking code --- Server/Core/Networking/Client.cs | 70 ++++----- Server/Core/Networking/Server.cs | 145 ++++++++---------- Server/Core/Networking/ServerHandler.cs | 15 +- .../Core/ReverseProxy/ReverseProxyServer.cs | 3 + Server/Forms/FrmMain.cs | 4 +- 5 files changed, 116 insertions(+), 121 deletions(-) diff --git a/Server/Core/Networking/Client.cs b/Server/Core/Networking/Client.cs index 067cd01f..8db20951 100644 --- a/Server/Core/Networking/Client.cs +++ b/Server/Core/Networking/Client.cs @@ -7,12 +7,11 @@ using System.Threading; using xServer.Core.Compression; using xServer.Core.Cryptography; using xServer.Core.Extensions; -using xServer.Core.NetSerializer; using xServer.Core.Packets; namespace xServer.Core.Networking { - public class Client + public class Client : IEquatable { /// /// Occurs when the state of the client changes. @@ -102,12 +101,13 @@ namespace xServer.Core.Networking /// Checks whether the clients are equal. /// /// Client to compare with. - /// + /// True if equal, else False. public bool Equals(Client c) { try { - return this.EndPoint.Port == c.EndPoint.Port; // this port is always unique for each client + // the port is always unique for each client + return this.EndPoint.Port.Equals(c.EndPoint.Port); } catch (Exception) { @@ -115,6 +115,30 @@ namespace xServer.Core.Networking } } + public override bool Equals(object obj) + { + return this.Equals(obj as Client); + } + + public static bool operator ==(Client lhs, Client rhs) + { + return ReferenceEquals(lhs, null) ? ReferenceEquals(rhs, null) : lhs.Equals(rhs); + } + + public static bool operator !=(Client lhs, Client rhs) + { + return !(lhs == rhs); + } + + /// + /// Returns the hashcode for this instance. + /// + /// A hash code for the current instance. + public override int GetHashCode() + { + return this.EndPoint.Port.GetHashCode(); + } + /// /// The type of the packet received. /// @@ -222,29 +246,17 @@ namespace xServer.Core.Networking /// private bool _appendHeader; - /// - /// The packet serializer. - /// - private Serializer _serializer; - private const bool encryptionEnabled = true; private const bool compressionEnabled = true; - public Client() - { - } - - internal Client(Server server, Socket sock, Type[] packets) + public Client(Server parentServer, Socket socket) { try { - _parentServer = server; - _parentServer.AddClient(this); - AddTypesToSerializer(packets); - if (_serializer == null) throw new Exception("Serializer not initialized"); + _parentServer = parentServer; Initialize(); - _handle = sock; + _handle = socket; _handle.SetKeepAliveEx(_parentServer.KEEP_ALIVE_INTERVAL, _parentServer.KEEP_ALIVE_TIME); EndPoint = (IPEndPoint)_handle.RemoteEndPoint; @@ -488,7 +500,7 @@ namespace xServer.Core.Networking { try { - IPacket packet = (IPacket)_serializer.Deserialize(deserialized); + IPacket packet = (IPacket)_parentServer.Serializer.Deserialize(deserialized); OnClientRead(packet); } @@ -538,7 +550,7 @@ namespace xServer.Core.Networking { using (MemoryStream ms = new MemoryStream()) { - _serializer.Serialize(ms, packet); + _parentServer.Serializer.Serialize(ms, packet); byte[] payload = ms.ToArray(); @@ -665,23 +677,11 @@ namespace xServer.Core.Networking Value.Dispose(); Value = null; } - - if (_parentServer.BufferManager != null) - _parentServer.BufferManager.ReturnBuffer(_readBuffer); + + _parentServer.BufferManager.ReturnBuffer(_readBuffer); } - _parentServer.RemoveClient(this); - OnClientState(false); } - - /// - /// Adds Types to the serializer. - /// - /// Types to add. - public void AddTypesToSerializer(Type[] types) - { - _serializer = new Serializer(types); - } } } \ No newline at end of file diff --git a/Server/Core/Networking/Server.cs b/Server/Core/Networking/Server.cs index 99119e49..1289e6b0 100644 --- a/Server/Core/Networking/Server.cs +++ b/Server/Core/Networking/Server.cs @@ -1,10 +1,10 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Net; using System.Net.Sockets; using System.Windows.Forms; using xServer.Core.Data; +using xServer.Core.NetSerializer; using xServer.Core.Networking.Utilities; using xServer.Core.Packets; @@ -29,7 +29,7 @@ namespace xServer.Core.Networking /// Fires an event that informs subscribers that the server has changed it's state. /// /// The new listening state of the server. - private void OnServerState(bool listening) + protected void OnServerState(bool listening) { if (Listening == listening) return; @@ -45,7 +45,7 @@ namespace xServer.Core.Networking /// /// Occurs when the state of a client changes. /// - protected event ClientStateEventHandler ClientState; + public event ClientStateEventHandler ClientState; /// /// Represents a method that will handle a change in a client's state. @@ -53,16 +53,20 @@ namespace xServer.Core.Networking /// The server, the client is connected to. /// The client which changed its state. /// The new connection state of the client. - protected delegate void ClientStateEventHandler(Server s, Client c, bool connected); + public delegate void ClientStateEventHandler(Server s, Client c, bool connected); /// /// Fires an event that informs subscribers that a client has changed its state. /// /// The client which changed its state. /// The new connection state of the client. - private void OnClientState(Client c, bool connected) + protected void OnClientState(Client c, bool connected) { var handler = ClientState; + + if (!connected) + RemoveClient(c); + if (handler != null) { handler(this, c, connected); @@ -72,7 +76,7 @@ namespace xServer.Core.Networking /// /// Occurs when a packet is received by a client. /// - protected event ClientReadEventHandler ClientRead; + public event ClientReadEventHandler ClientRead; /// /// Represents a method that will handle a packet received from a client. @@ -80,7 +84,7 @@ namespace xServer.Core.Networking /// The server, the client is connected to. /// The client that has received the packet. /// The packet that received by the client. - protected delegate void ClientReadEventHandler(Server s, Client c, IPacket packet); + public delegate void ClientReadEventHandler(Server s, Client c, IPacket packet); /// /// Fires an event that informs subscribers that a packet has been @@ -88,7 +92,7 @@ namespace xServer.Core.Networking /// /// The client that has received the packet. /// The packet that received by the client. - private void OnClientRead(Client c, IPacket packet) + protected void OnClientRead(Client c, IPacket packet) { var handler = ClientRead; if (handler != null) @@ -100,7 +104,7 @@ namespace xServer.Core.Networking /// /// Occurs when a packet is sent by a client. /// - protected event ClientWriteEventHandler ClientWrite; + public event ClientWriteEventHandler ClientWrite; /// /// Represents the method that will handle the sent packet by a client. @@ -110,7 +114,7 @@ namespace xServer.Core.Networking /// The packet that has been sent by the client. /// The length of the packet. /// The packet in raw bytes. - protected delegate void ClientWriteEventHandler(Server s, Client c, IPacket packet, long length, byte[] rawData); + public delegate void ClientWriteEventHandler(Server s, Client c, IPacket packet, long length, byte[] rawData); /// /// Fires an event that informs subscribers that the client has sent a packet. @@ -119,7 +123,7 @@ namespace xServer.Core.Networking /// The packet that has been sent by the client. /// The length of the packet. /// The packet in raw bytes. - private void OnClientWrite(Client c, IPacket packet, long length, byte[] rawData) + protected void OnClientWrite(Client c, IPacket packet, long length, byte[] rawData) { var handler = ClientWrite; if (handler != null) @@ -188,11 +192,16 @@ namespace xServer.Core.Networking { lock (_clientsLock) { - return Listening ? _clients.ToArray() : new Client[0]; + return _clients.ToArray(); } } } + /// + /// The packet serializer. + /// + public Serializer Serializer { get; protected set; } + /// /// Handle of the Server Socket. /// @@ -213,11 +222,6 @@ namespace xServer.Core.Networking /// private readonly object _clientsLock = new object(); - /// - /// List of all supported Packet Types by the server. - /// - private List PacketTypes { get; set; } - /// /// Determines if the server is currently processing Disconnect method. /// @@ -226,9 +230,10 @@ namespace xServer.Core.Networking /// /// Constructor of the server, initializes variables. /// - public Server() + protected Server() { - PacketTypes = new List(); + _clients = new List(); + BufferManager = new PooledBufferManager(BUFFER_SIZE, 1) { ClearOnReturn = false }; } /// @@ -237,29 +242,17 @@ namespace xServer.Core.Networking /// Port to listen for clients on. public void Listen(ushort port) { - if (PacketTypes.Count == 0) throw new Exception("No packet types added"); - this.Port = port; try { if (!Listening) { - lock (_clientsLock) - { - _clients = new List(); - } - - _item = new SocketAsyncEventArgs(); - _item.Completed += AcceptClient; - if (_handle != null) { _handle.Close(); + _handle = null; } - if (BufferManager == null) - BufferManager = new PooledBufferManager(BUFFER_SIZE, 1) { ClearOnReturn = true }; - _handle = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); _handle.Bind(new IPEndPoint(IPAddress.Any, port)); _handle.Listen(1000); @@ -268,6 +261,15 @@ namespace xServer.Core.Networking OnServerState(true); + if (_item != null) + { + _item.Dispose(); + _item = null; + } + + _item = new SocketAsyncEventArgs(); + _item.Completed += AcceptClient; + if (!_handle.AcceptAsync(_item)) AcceptClient(null, _item); } @@ -294,17 +296,7 @@ namespace xServer.Core.Networking } /// - /// Adds Types to the serializer. - /// - /// Types to add. - public void AddTypesToSerializer(Type[] types) - { - PacketTypes.AddRange(types.Where(t => t != null)); - } - - /// - /// Processes an incoming client; adding the client to the list of clients, - /// hooking up the client's events, and finally accepts the client. + /// Processes and accepts an incoming client. /// /// Unused, use null. /// Asynchronously Socket Event @@ -320,10 +312,8 @@ namespace xServer.Core.Networking if (BufferManager.BuffersAvailable == 0) BufferManager.IncreaseBufferCount(1); - Client client = new Client(this, e.AcceptSocket, PacketTypes.ToArray()); - client.ClientState += OnClientState; - client.ClientRead += OnClientRead; - client.ClientWrite += OnClientWrite; + Client client = new Client(this, e.AcceptSocket /*, PacketTypes.ToArray()*/); + AddClient(client); OnClientState(client, true); break; case SocketError.ConnectionReset: @@ -345,45 +335,36 @@ namespace xServer.Core.Networking } /// - /// Adds a connected client to the list of clients. + /// Adds a connected client to the list of clients, + /// subscribes to the client's events. /// /// The client to add. - public void AddClient(Client client) + private void AddClient(Client client) { lock (_clientsLock) { + client.ClientState += OnClientState; + client.ClientRead += OnClientRead; + client.ClientWrite += OnClientWrite; _clients.Add(client); } } /// - /// Removes a disconnected client from the list of clients. + /// Removes a disconnected client from the list of clients, + /// unsubscribes from the client's events. /// /// The client to remove. - public void RemoveClient(Client client) + private void RemoveClient(Client client) { if (_processing) return; lock (_clientsLock) { - int index = -1; - for (int i = 0; i < _clients.Count; i++) - if (_clients[i].Equals(client)) - { - index = i; - break; - } - - if (index < 0) - return; - - try - { - _clients.RemoveAt(index); - } - catch - { - } + client.ClientState -= OnClientState; + client.ClientRead -= OnClientRead; + client.ClientWrite -= OnClientWrite; + _clients.Remove(client); } } @@ -402,20 +383,26 @@ namespace xServer.Core.Networking _handle = null; } + if (_item != null) + { + _item.Dispose(); + _item = null; + } + lock (_clientsLock) { - if (_clients != null) + while (_clients.Count != 0) { - while (_clients.Count != 0) + try + { + _clients[0].Disconnect(); + _clients[0].ClientState -= OnClientState; + _clients[0].ClientRead -= OnClientRead; + _clients[0].ClientWrite -= OnClientWrite; + _clients.RemoveAt(0); + } + catch { - try - { - _clients[0].Disconnect(); - _clients.RemoveAt(0); - } - catch - { - } } } } diff --git a/Server/Core/Networking/ServerHandler.cs b/Server/Core/Networking/ServerHandler.cs index c846d40a..12348ab8 100644 --- a/Server/Core/Networking/ServerHandler.cs +++ b/Server/Core/Networking/ServerHandler.cs @@ -1,5 +1,7 @@ using System; +using System.Linq; using xServer.Core.Commands; +using xServer.Core.NetSerializer; using xServer.Core.Packets; namespace xServer.Core.Networking @@ -9,7 +11,12 @@ namespace xServer.Core.Networking /// /// The amount of currently connected and authenticated clients. /// - public int ConnectedClients { get; private set; } + public int ConnectedClients { + get + { + return Clients.Count(c => c != null && c.Authenticated); + } + } /// /// Occurs when a client connected. @@ -62,9 +69,9 @@ namespace xServer.Core.Networking /// /// Constructor, initializes required objects and subscribes to events of the server. /// - public ServerHandler() + public ServerHandler() : base() { - base.AddTypesToSerializer(new Type[] + base.Serializer = new Serializer(new Type[] { typeof (Packets.ServerPackets.GetAuthentication), typeof (Packets.ServerPackets.DoClientDisconnect), @@ -139,7 +146,6 @@ namespace xServer.Core.Networking case false: if (client.Authenticated) { - ConnectedClients--; OnClientDisconnected(client); } break; @@ -161,7 +167,6 @@ namespace xServer.Core.Networking if (type == typeof (Packets.ClientPackets.GetAuthenticationResponse)) { client.Authenticated = true; - ConnectedClients++; new Packets.ServerPackets.SetAuthenticationSuccess().Execute(client); // finish handshake CommandHandler.HandleGetAuthenticationResponse(client, (Packets.ClientPackets.GetAuthenticationResponse) packet); diff --git a/Server/Core/ReverseProxy/ReverseProxyServer.cs b/Server/Core/ReverseProxy/ReverseProxyServer.cs index 12bd155f..761509f3 100644 --- a/Server/Core/ReverseProxy/ReverseProxyServer.cs +++ b/Server/Core/ReverseProxy/ReverseProxyServer.cs @@ -104,7 +104,10 @@ namespace xServer.Core.ReverseProxy public void Stop() { if (_socket != null) + { _socket.Close(); + _socket = null; + } lock (_clients) { diff --git a/Server/Forms/FrmMain.cs b/Server/Forms/FrmMain.cs index 331b3fa9..cacbec11 100644 --- a/Server/Forms/FrmMain.cs +++ b/Server/Forms/FrmMain.cs @@ -215,7 +215,7 @@ namespace xServer.Forms lock (_lockClients) { foreach (ListViewItem lvi in lstClients.Items.Cast() - .Where(lvi => lvi != null && (lvi.Tag as Client) != null && c.Equals((Client) lvi.Tag))) + .Where(lvi => lvi != null && c.Equals(lvi.Tag))) { lvi.Remove(); break; @@ -286,7 +286,7 @@ namespace xServer.Forms lstClients.Invoke((MethodInvoker) delegate { itemClient = lstClients.Items.Cast() - .FirstOrDefault(lvi => lvi != null && lvi.Tag is Client && c.Equals((Client)lvi.Tag)); + .FirstOrDefault(lvi => lvi != null && c.Equals(lvi.Tag)); }); return itemClient;