mirror of https://github.com/quasar/Quasar.git
Fixes to networking code
This commit is contained in:
parent
cc8bfddaf3
commit
6d72bef8d2
|
@ -7,12 +7,11 @@
|
|||
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<Client>
|
||||
{
|
||||
/// <summary>
|
||||
/// Occurs when the state of the client changes.
|
||||
|
@ -102,12 +101,13 @@ private void OnClientWrite(IPacket packet, long length, byte[] rawData)
|
|||
/// Checks whether the clients are equal.
|
||||
/// </summary>
|
||||
/// <param name="c">Client to compare with.</param>
|
||||
/// <returns></returns>
|
||||
/// <returns>True if equal, else False.</returns>
|
||||
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 @@ public bool Equals(Client c)
|
|||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the hashcode for this instance.
|
||||
/// </summary>
|
||||
/// <returns>A hash code for the current instance.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this.EndPoint.Port.GetHashCode();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The type of the packet received.
|
||||
/// </summary>
|
||||
|
@ -222,29 +246,17 @@ public enum ReceiveType
|
|||
/// </summary>
|
||||
private bool _appendHeader;
|
||||
|
||||
/// <summary>
|
||||
/// The packet serializer.
|
||||
/// </summary>
|
||||
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 @@ private void AsyncReceive(object state)
|
|||
{
|
||||
try
|
||||
{
|
||||
IPacket packet = (IPacket)_serializer.Deserialize(deserialized);
|
||||
IPacket packet = (IPacket)_parentServer.Serializer.Deserialize(deserialized);
|
||||
|
||||
OnClientRead(packet);
|
||||
}
|
||||
|
@ -538,7 +550,7 @@ private void AsyncReceive(object state)
|
|||
{
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
_serializer.Serialize(ms, packet);
|
||||
_parentServer.Serializer.Serialize(ms, packet);
|
||||
|
||||
byte[] payload = ms.ToArray();
|
||||
|
||||
|
@ -665,23 +677,11 @@ public void Disconnect()
|
|||
Value.Dispose();
|
||||
Value = null;
|
||||
}
|
||||
|
||||
if (_parentServer.BufferManager != null)
|
||||
_parentServer.BufferManager.ReturnBuffer(_readBuffer);
|
||||
|
||||
_parentServer.BufferManager.ReturnBuffer(_readBuffer);
|
||||
}
|
||||
|
||||
_parentServer.RemoveClient(this);
|
||||
|
||||
OnClientState(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds Types to the serializer.
|
||||
/// </summary>
|
||||
/// <param name="types">Types to add.</param>
|
||||
public void AddTypesToSerializer(Type[] types)
|
||||
{
|
||||
_serializer = new Serializer(types);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 @@ public class Server
|
|||
/// Fires an event that informs subscribers that the server has changed it's state.
|
||||
/// </summary>
|
||||
/// <param name="listening">The new listening state of the server.</param>
|
||||
private void OnServerState(bool listening)
|
||||
protected void OnServerState(bool listening)
|
||||
{
|
||||
if (Listening == listening) return;
|
||||
|
||||
|
@ -45,7 +45,7 @@ private void OnServerState(bool listening)
|
|||
/// <summary>
|
||||
/// Occurs when the state of a client changes.
|
||||
/// </summary>
|
||||
protected event ClientStateEventHandler ClientState;
|
||||
public event ClientStateEventHandler ClientState;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a method that will handle a change in a client's state.
|
||||
|
@ -53,16 +53,20 @@ private void OnServerState(bool listening)
|
|||
/// <param name="s">The server, the client is connected to.</param>
|
||||
/// <param name="c">The client which changed its state.</param>
|
||||
/// <param name="connected">The new connection state of the client.</param>
|
||||
protected delegate void ClientStateEventHandler(Server s, Client c, bool connected);
|
||||
public delegate void ClientStateEventHandler(Server s, Client c, bool connected);
|
||||
|
||||
/// <summary>
|
||||
/// Fires an event that informs subscribers that a client has changed its state.
|
||||
/// </summary>
|
||||
/// <param name="c">The client which changed its state.</param>
|
||||
/// <param name="connected">The new connection state of the client.</param>
|
||||
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 @@ private void OnClientState(Client c, bool connected)
|
|||
/// <summary>
|
||||
/// Occurs when a packet is received by a client.
|
||||
/// </summary>
|
||||
protected event ClientReadEventHandler ClientRead;
|
||||
public event ClientReadEventHandler ClientRead;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a method that will handle a packet received from a client.
|
||||
|
@ -80,7 +84,7 @@ private void OnClientState(Client c, bool connected)
|
|||
/// <param name="s">The server, the client is connected to.</param>
|
||||
/// <param name="c">The client that has received the packet.</param>
|
||||
/// <param name="packet">The packet that received by the client.</param>
|
||||
protected delegate void ClientReadEventHandler(Server s, Client c, IPacket packet);
|
||||
public delegate void ClientReadEventHandler(Server s, Client c, IPacket packet);
|
||||
|
||||
/// <summary>
|
||||
/// Fires an event that informs subscribers that a packet has been
|
||||
|
@ -88,7 +92,7 @@ private void OnClientState(Client c, bool connected)
|
|||
/// </summary>
|
||||
/// <param name="c">The client that has received the packet.</param>
|
||||
/// <param name="packet">The packet that received by the client.</param>
|
||||
private void OnClientRead(Client c, IPacket packet)
|
||||
protected void OnClientRead(Client c, IPacket packet)
|
||||
{
|
||||
var handler = ClientRead;
|
||||
if (handler != null)
|
||||
|
@ -100,7 +104,7 @@ private void OnClientRead(Client c, IPacket packet)
|
|||
/// <summary>
|
||||
/// Occurs when a packet is sent by a client.
|
||||
/// </summary>
|
||||
protected event ClientWriteEventHandler ClientWrite;
|
||||
public event ClientWriteEventHandler ClientWrite;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the method that will handle the sent packet by a client.
|
||||
|
@ -110,7 +114,7 @@ private void OnClientRead(Client c, IPacket packet)
|
|||
/// <param name="packet">The packet that has been sent by the client.</param>
|
||||
/// <param name="length">The length of the packet.</param>
|
||||
/// <param name="rawData">The packet in raw bytes.</param>
|
||||
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);
|
||||
|
||||
/// <summary>
|
||||
/// Fires an event that informs subscribers that the client has sent a packet.
|
||||
|
@ -119,7 +123,7 @@ private void OnClientRead(Client c, IPacket packet)
|
|||
/// <param name="packet">The packet that has been sent by the client.</param>
|
||||
/// <param name="length">The length of the packet.</param>
|
||||
/// <param name="rawData">The packet in raw bytes.</param>
|
||||
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 @@ public Client[] Clients
|
|||
{
|
||||
lock (_clientsLock)
|
||||
{
|
||||
return Listening ? _clients.ToArray() : new Client[0];
|
||||
return _clients.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The packet serializer.
|
||||
/// </summary>
|
||||
public Serializer Serializer { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Handle of the Server Socket.
|
||||
/// </summary>
|
||||
|
@ -213,11 +222,6 @@ public Client[] Clients
|
|||
/// </summary>
|
||||
private readonly object _clientsLock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// List of all supported Packet Types by the server.
|
||||
/// </summary>
|
||||
private List<Type> PacketTypes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the server is currently processing Disconnect method.
|
||||
/// </summary>
|
||||
|
@ -226,9 +230,10 @@ public Client[] Clients
|
|||
/// <summary>
|
||||
/// Constructor of the server, initializes variables.
|
||||
/// </summary>
|
||||
public Server()
|
||||
protected Server()
|
||||
{
|
||||
PacketTypes = new List<Type>();
|
||||
_clients = new List<Client>();
|
||||
BufferManager = new PooledBufferManager(BUFFER_SIZE, 1) { ClearOnReturn = false };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -237,29 +242,17 @@ public Server()
|
|||
/// <param name="port">Port to listen for clients on.</param>
|
||||
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<Client>();
|
||||
}
|
||||
|
||||
_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 @@ public void Listen(ushort port)
|
|||
|
||||
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 @@ public void Listen(ushort port)
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds Types to the serializer.
|
||||
/// </summary>
|
||||
/// <param name="types">Types to add.</param>
|
||||
public void AddTypesToSerializer(Type[] types)
|
||||
{
|
||||
PacketTypes.AddRange(types.Where(t => t != null));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="s">Unused, use null.</param>
|
||||
/// <param name="e">Asynchronously Socket Event</param>
|
||||
|
@ -320,10 +312,8 @@ private void AcceptClient(object s, SocketAsyncEventArgs e)
|
|||
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 @@ private void AcceptClient(object s, SocketAsyncEventArgs e)
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a connected client to the list of clients.
|
||||
/// Adds a connected client to the list of clients,
|
||||
/// subscribes to the client's events.
|
||||
/// </summary>
|
||||
/// <param name="client">The client to add.</param>
|
||||
public void AddClient(Client client)
|
||||
private void AddClient(Client client)
|
||||
{
|
||||
lock (_clientsLock)
|
||||
{
|
||||
client.ClientState += OnClientState;
|
||||
client.ClientRead += OnClientRead;
|
||||
client.ClientWrite += OnClientWrite;
|
||||
_clients.Add(client);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a disconnected client from the list of clients.
|
||||
/// Removes a disconnected client from the list of clients,
|
||||
/// unsubscribes from the client's events.
|
||||
/// </summary>
|
||||
/// <param name="client">The client to remove.</param>
|
||||
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 @@ public void Disconnect()
|
|||
_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
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 @@ public class ServerHandler : Server
|
|||
/// <summary>
|
||||
/// The amount of currently connected and authenticated clients.
|
||||
/// </summary>
|
||||
public int ConnectedClients { get; private set; }
|
||||
public int ConnectedClients {
|
||||
get
|
||||
{
|
||||
return Clients.Count(c => c != null && c.Authenticated);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a client connected.
|
||||
|
@ -62,9 +69,9 @@ private void OnClientDisconnected(Client client)
|
|||
/// <summary>
|
||||
/// Constructor, initializes required objects and subscribes to events of the server.
|
||||
/// </summary>
|
||||
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 @@ private void ClientStateHandler(Server server, Client client, bool connected)
|
|||
case false:
|
||||
if (client.Authenticated)
|
||||
{
|
||||
ConnectedClients--;
|
||||
OnClientDisconnected(client);
|
||||
}
|
||||
break;
|
||||
|
@ -161,7 +167,6 @@ private void ClientReadHandler(Server server, Client client, IPacket packet)
|
|||
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);
|
||||
|
|
|
@ -104,7 +104,10 @@ private void AsyncAccept(IAsyncResult ar)
|
|||
public void Stop()
|
||||
{
|
||||
if (_socket != null)
|
||||
{
|
||||
_socket.Close();
|
||||
_socket = null;
|
||||
}
|
||||
|
||||
lock (_clients)
|
||||
{
|
||||
|
|
|
@ -215,7 +215,7 @@ private void RemoveClientFromListview(Client c)
|
|||
lock (_lockClients)
|
||||
{
|
||||
foreach (ListViewItem lvi in lstClients.Items.Cast<ListViewItem>()
|
||||
.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 @@ private ListViewItem GetListViewItemByClient(Client c)
|
|||
lstClients.Invoke((MethodInvoker) delegate
|
||||
{
|
||||
itemClient = lstClients.Items.Cast<ListViewItem>()
|
||||
.FirstOrDefault(lvi => lvi != null && lvi.Tag is Client && c.Equals((Client)lvi.Tag));
|
||||
.FirstOrDefault(lvi => lvi != null && c.Equals(lvi.Tag));
|
||||
});
|
||||
|
||||
return itemClient;
|
||||
|
|
Loading…
Reference in New Issue