using System; using System.Net; using System.Net.Sockets; using System.Threading; namespace FilterAPI.Networking { public abstract class ClientMulti : IDisposable { private Socket ClientSocket; public IPEndPoint ClientEndPoint; private const Int32 CMaxReceiveBuffer = 5120; private Byte[] CReceiveBuffer; private Int32 CReceiveLength; private Socket ServerSocket; public IPEndPoint ServerEndPoint; private const Int32 SMaxReceiveBuffer = 25600; private Byte[] SReceiveBuffer; private Int32 SReceiveLength; public ClientMulti(Socket CS, IPEndPoint CIPEP, IPAddress SIP, Int32 SP, Boolean LingarSocket = true) { ClientSocket = CS; if (LingarSocket) { ClientSocket.LingerState = new LingerOption(true, 2); } ClientEndPoint = CIPEP; ServerEndPoint = new IPEndPoint(SIP, SP); ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); if (LingarSocket) { ServerSocket.LingerState = new LingerOption(true, 2); } SocketAsyncEventArgs AsyncArgs = new SocketAsyncEventArgs(); AsyncArgs.UserToken = ServerSocket; AsyncArgs.Completed += ServerConnected; AsyncArgs.RemoteEndPoint = ServerEndPoint; try { if (!ServerSocket.ConnectAsync(AsyncArgs)) { ServerConnected(this, AsyncArgs); } } catch { if (AsyncArgs != null) { AsyncArgs.Dispose(); } Dispose(); } } private void ServerConnected(Object Sender, SocketAsyncEventArgs AsyncArgs) { if (disposed) { AsyncArgs.Dispose(); return; } else if (AsyncArgs.SocketError != SocketError.Success) { AsyncArgs.Dispose(); Dispose(); return; } CReceiveBuffer = new Byte[CMaxReceiveBuffer]; SReceiveBuffer = new Byte[SMaxReceiveBuffer]; ReceiveClient(); ReceiveServer(); AsyncArgs.Dispose(); } public void ReceiveClient() { if (disposed) { return; } try { ClientSocket.BeginReceive(CReceiveBuffer, 0, 1, SocketFlags.None, new AsyncCallback(ReceivedSmallSizeClient), null); } catch { Dispose(); } } private void ReceivedSmallSizeClient(IAsyncResult IAR) { if (disposed) { return; } Int32 ReceivedBytes; try { ReceivedBytes = ClientSocket.EndReceive(IAR); } catch { Dispose(); return; } if (ReceivedBytes == 1) { CReceiveLength = CReceiveBuffer[0]; if (CReceiveLength == 0) { try { ClientSocket.BeginReceive(CReceiveBuffer, 0, 2, SocketFlags.None, new AsyncCallback(ReceivedBigSizeClient), null); } catch { Dispose(); } } else { try { ClientSocket.BeginReceive(CReceiveBuffer, 0, CReceiveLength, SocketFlags.None, new AsyncCallback(ReceivedPacketClient), null); } catch { Dispose(); } } } else { Dispose(); } } private void ReceivedBigSizeClient(IAsyncResult IAR) { if (disposed) { return; } Int32 ReceivedBytes; try { ReceivedBytes = ClientSocket.EndReceive(IAR); } catch { Dispose(); return; } if (ReceivedBytes == 2) { CReceiveLength = BitConverter.ToInt16(CReceiveBuffer, 0); try { ClientSocket.BeginReceive(CReceiveBuffer, 0, CReceiveLength, SocketFlags.None, new AsyncCallback(ReceivedPacketClient), null); } catch { Dispose(); } } else { Dispose(); } } private void ReceivedPacketClient(IAsyncResult IAR) { if (disposed) { return; } Int32 ReceivedBytes; try { ReceivedBytes = ClientSocket.EndReceive(IAR); } catch { Dispose(); return; } if (ReceivedBytes == CReceiveLength) { Byte[] PacketData = new Byte[CReceiveLength]; Buffer.BlockCopy(CReceiveBuffer, 0, PacketData, 0, CReceiveLength); ReceivedClient(PacketData); ReceiveClient(); } else { Dispose(); } } public abstract void ReceivedClient(Byte[] Buffer); public void SendClient(Byte[] Buffer) { if (disposed) { return; } try { ClientSocket.BeginSend(Buffer, 0, Buffer.Length, SocketFlags.None, new AsyncCallback(SentClient), null); } catch { Dispose(); } } private void SentClient(IAsyncResult IAR) { if (disposed) { return; } Int32 SentBytes; try { SentBytes = ClientSocket.EndSend(IAR); } catch { Dispose(); return; } if (SentBytes <= 0) { Dispose(); } } public void ReceiveServer() { if (disposed) { return; } try { ServerSocket.BeginReceive(SReceiveBuffer, 0, 1, SocketFlags.None, new AsyncCallback(ReceivedSmallSizeServer), null); } catch { Dispose(); } } private void ReceivedSmallSizeServer(IAsyncResult IAR) { if (disposed) { return; } Int32 ReceivedBytes; try { ReceivedBytes = ServerSocket.EndReceive(IAR); } catch { Dispose(); return; } if (ReceivedBytes == 1) { SReceiveLength = SReceiveBuffer[0]; if (SReceiveLength == 0) { try { ServerSocket.BeginReceive(SReceiveBuffer, 0, 2, SocketFlags.None, new AsyncCallback(ReceivedBigSizeServer), null); } catch { Dispose(); } } else { try { ServerSocket.BeginReceive(SReceiveBuffer, 0, SReceiveLength, SocketFlags.None, new AsyncCallback(ReceivedPacketServer), null); } catch { Dispose(); } } } else { Dispose(); } } private void ReceivedBigSizeServer(IAsyncResult IAR) { if (disposed) { return; } Int32 ReceivedBytes; try { ReceivedBytes = ServerSocket.EndReceive(IAR); } catch { Dispose(); return; } if (ReceivedBytes == 2) { SReceiveLength = BitConverter.ToInt16(SReceiveBuffer, 0); try { ServerSocket.BeginReceive(SReceiveBuffer, 0, SReceiveLength, SocketFlags.None, new AsyncCallback(ReceivedPacketServer), null); } catch { Dispose(); } } else { Dispose(); } } private void ReceivedPacketServer(IAsyncResult IAR) { if (disposed) { return; } Int32 ReceivedBytes; try { ReceivedBytes = ServerSocket.EndReceive(IAR); } catch { Dispose(); return; } if (ReceivedBytes == SReceiveLength) { Byte[] PacketData = new Byte[SReceiveLength]; Buffer.BlockCopy(SReceiveBuffer, 0, PacketData, 0, SReceiveLength); ReceivedServer(PacketData); ReceiveServer(); } else { Dispose(); } } public abstract void ReceivedServer(Byte[] Buffer); public void SendServer(Byte[] Buffer) { if (disposed) { return; } try { ServerSocket.BeginSend(Buffer, 0, Buffer.Length, SocketFlags.None, new AsyncCallback(SentServer), null); } catch { Dispose(); } } private void SentServer(IAsyncResult IAR) { if (disposed) { return; } Int32 SentBytes; try { SentBytes = ServerSocket.EndSend(IAR); } catch { Dispose(); return; } if (SentBytes <= 0) { Dispose(); } } public abstract void Disconnected(); private bool disposed = false; protected virtual void Dispose(bool disposing) { if (!disposed) { if (disposing) { if (ServerSocket != null) { try { ServerSocket.Close(); ServerSocket.Dispose(); } catch { } } if (ClientSocket != null) { try { ClientSocket.Close(); ClientSocket.Dispose(); } catch { } } } disposed = true; Disconnected(); } } public void Dispose() { Dispose(true); } ~ClientMulti() { Dispose(false); } } }