using System; using System.Linq; using System.Net; using System.Threading; using System.Net.Sockets; using FiestaBot.Utilities; namespace FiestaBot.Instances.Networking { internal abstract class Client : IDisposable { public Socket ClientSocket; private IPEndPoint ClientEndPoint; private byte[] ClientBuffer; public string RemoteAddress; public int RemotePort; public int IsConnected; public Client(IPAddress ConnectIP, int ConnectPort) { RemoteAddress = Convert.ToString(ConnectIP); RemotePort = ConnectPort; ClientEndPoint = new IPEndPoint(ConnectIP, ConnectPort); ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); ClientSocket.BeginConnect(ClientEndPoint, new AsyncCallback(ConnectionOpened), null); } private void ConnectionOpened(IAsyncResult AsyncResult) { try { ClientSocket.EndConnect(AsyncResult); Connected(); } catch (Exception Exception) { Logger.Log(LogType.Error, Exception.Message); } } public abstract void Connected(); public abstract void ConnectFailed(SocketException Exception); public Client(Socket AcceptedSocket, IPEndPoint AcceptedEndPoint) { ClientSocket = AcceptedSocket; ClientEndPoint = AcceptedEndPoint; RemoteAddress = Convert.ToString(ClientEndPoint.Address); RemotePort = ClientEndPoint.Port; } public void Receive() { if (IsConnected != 0) { return; } ClientBuffer = new byte[1]; try { ClientSocket.BeginReceive(ClientBuffer, 0, ClientBuffer.Length, SocketFlags.None, new AsyncCallback(ReceivedSize), null); } catch { Disconnect(); } } private void ReceivedSize(IAsyncResult AsyncResult) { if (IsConnected != 0) { return; } int BytesReceived = 0; try { BytesReceived = ClientSocket.EndReceive(AsyncResult); } catch { Disconnect(); } if (BytesReceived > 0) { if (ClientBuffer[0] == 0) { ClientBuffer = new byte[2]; try { ClientSocket.BeginReceive(ClientBuffer, 0, 2, SocketFlags.None, new AsyncCallback(ReceivedBigSize), null); } catch { Disconnect(); } } else { ClientBuffer = new byte[ClientBuffer[0]]; try { ClientSocket.BeginReceive(ClientBuffer, 0, ClientBuffer.Length, SocketFlags.None, new AsyncCallback(ReceivedPacket), null); } catch { Disconnect(); } } } else { Disconnect(); } } private void ReceivedBigSize(IAsyncResult AsyncResult) { try { if (IsConnected != 0) { return; } int BytesReceived = 0; try { BytesReceived = ClientSocket.EndReceive(AsyncResult); } catch { Disconnect(); } if (BytesReceived > 0) { short ReceivedSize = BitConverter.ToInt16(ClientBuffer, 0); ClientBuffer = new byte[ReceivedSize]; try { ClientSocket.BeginReceive(ClientBuffer, 0, ReceivedSize, SocketFlags.None, new AsyncCallback(ReceivedPacket), null); } catch { Disconnect(); } } else { Disconnect(); } } catch { } } private void ReceivedPacket(IAsyncResult AsyncResult) { int BytesReceived = 0; try { BytesReceived = ClientSocket.EndReceive(AsyncResult); } catch { Disconnect(); } if (BytesReceived > 0) { Received(ClientBuffer); Receive(); } else { Disconnect(); } } public void Send(byte[] Buffer) { if (IsConnected != 0) { return; } try { ClientSocket.BeginSend(Buffer, 0, Buffer.Length, SocketFlags.None, new AsyncCallback(Sent), null); } catch { Disconnect(); } } private void Sent(IAsyncResult AsyncResult) { if (IsConnected != 0) { return; } try { ClientSocket.EndSend(AsyncResult); } catch { Disconnect(); } } public void Disconnect() { if (IsConnected == 0 && Interlocked.CompareExchange(ref IsConnected, 1, 0) == 0) { Disconnected(); try { ClientSocket.Dispose(); } catch { } } } ~Client() { Dispose(); } public void Dispose() { Disconnect(); } public abstract void Received(byte[] Buffer); public abstract void Disconnected(); } }