using System; using System.Net; using System.Net.Sockets; using System.Threading; namespace FilterAPI.Networking { public abstract class SingleClient : IDisposable { public Socket CSock; public IPEndPoint CEP; public Boolean Ping; public Boolean SendName; public String ServiceName; private const Int32 MaxReceiveBuffer = 1024; private Byte[] ReceiveBuffer; private Int32 ReceiveLength; public Int32 IsSending; public SingleClient(IPAddress ConnectIP, Int32 ConnectPort, Boolean P = true) { CEP = new IPEndPoint(ConnectIP, ConnectPort); CSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); Ping = P; SocketAsyncEventArgs AsyncArgs = new SocketAsyncEventArgs(); AsyncArgs.UserToken = CSock; AsyncArgs.Completed += ConnectionOpened; AsyncArgs.RemoteEndPoint = CEP; try { if (!CSock.ConnectAsync(AsyncArgs)) { ConnectionOpened(this, AsyncArgs); } } catch { AsyncArgs.Dispose(); Dispose(); } } private void ConnectionOpened(Object Sender, SocketAsyncEventArgs AsyncArgs) { if (disposed) { if (AsyncArgs != null) { AsyncArgs.Dispose(); } return; } else if (AsyncArgs.SocketError != SocketError.Success) { if (AsyncArgs != null) { AsyncArgs.Dispose(); } Dispose(); return; } ReceiveBuffer = new Byte[MaxReceiveBuffer]; Receive(); if (Ping) { StartPacketSender(NETCMD.LOCAL_PING, 5); } Connected(); AsyncArgs.Dispose(); } public abstract void Connected(); private Boolean PSenderIsDone = true; public void StartPacketSender(NETCMD OPCode, Int32 Time) { Thread NewThread = new Thread(delegate () { while (!disposed) { if (PSenderIsDone) { RunPSender(OPCode); } Thread.Sleep(Time * 1000); } }); NewThread.Start(); } private void RunPSender(NETCMD OPCode) { if (disposed) { return; } PSenderIsDone = false; using (var P = new Packet(OPCode)) { Byte[] PacketBuffer; P.ToArray(out PacketBuffer); Send(PacketBuffer); } PSenderIsDone = true; } public SingleClient(Socket AcceptedSocket, IPEndPoint AcceptedEndPoint) { CSock = AcceptedSocket; CEP = AcceptedEndPoint; ReceiveBuffer = new Byte[MaxReceiveBuffer]; Receive(); } public void Receive() { if (disposed) { return; } try { CSock.BeginReceive(ReceiveBuffer, 0, 1, SocketFlags.None, new AsyncCallback(ReceivedSmallSize), null); } catch { Dispose(); } } private void ReceivedSmallSize(IAsyncResult IAR) { if (disposed) { return; } Int32 ReceivedBytes; try { ReceivedBytes = CSock.EndReceive(IAR); } catch { Dispose(); return; } if (ReceivedBytes == 1) { ReceiveLength = ReceiveBuffer[0]; if (ReceiveLength == 0) { try { CSock.BeginReceive(ReceiveBuffer, 0, 2, SocketFlags.None, new AsyncCallback(ReceivedBigSize), null); } catch { Dispose(); } } else { try { CSock.BeginReceive(ReceiveBuffer, 0, ReceiveLength, SocketFlags.None, new AsyncCallback(ReceivedPacket), null); } catch { Dispose(); } } } else { Dispose(); } } private void ReceivedBigSize(IAsyncResult IAR) { if (disposed) { return; } Int32 ReceivedBytes; try { ReceivedBytes = CSock.EndReceive(IAR); } catch { Dispose(); return; } if (ReceivedBytes == 2) { ReceiveLength = BitConverter.ToInt16(ReceiveBuffer, 0); ReceiveLength = ReceiveBuffer.Length; try { CSock.BeginReceive(ReceiveBuffer, 0, ReceiveLength, SocketFlags.None, new AsyncCallback(ReceivedPacket), null); } catch { Dispose(); } } else { Dispose(); } } private void ReceivedPacket(IAsyncResult IAR) { if (disposed) { return; } Int32 ReceivedBytes; try { ReceivedBytes = CSock.EndReceive(IAR); } catch { Dispose(); return; } if (ReceivedBytes == ReceiveLength) { Byte[] PacketData = new Byte[ReceiveLength]; Buffer.BlockCopy(ReceiveBuffer, 0, PacketData, 0, ReceiveLength); Received(PacketData); Thread.Sleep(1); Receive(); } else { Dispose(); } } public void Send(Byte[] Buffer) { if (disposed) { return; } try { CSock.BeginSend(Buffer, 0, Buffer.Length, SocketFlags.None, new AsyncCallback(Sent), null); } catch { Dispose(); } } private void Sent(IAsyncResult IAR) { if (disposed) { return; } Int32 SentBytes; try { SentBytes = CSock.EndSend(IAR); } catch { Dispose(); return; } if (SentBytes <= 0) { Dispose(); } } public abstract void Received(Byte[] Buffer); public abstract void Disconnected(); private bool disposed = false; protected virtual void Dispose(bool disposing) { if (!disposed) { if (disposing) { if (CSock != null) { try { CSock.Close(); CSock.Dispose(); } catch { } } } disposed = true; Disconnected(); } } public void Dispose() { Dispose(true); } ~SingleClient() { Dispose(false); } } }