using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net.Sockets; using System.Net; using DuckEmulator.Security; using DuckEmulator.HabboHotel.Outside.Clients; using System.Diagnostics; namespace DuckEmulator.HabboHotel.Inside.NET { class RemoteSocket { private Socket fSocket; private const ushort BACKLOG_COUNT = 1000; private int fId; private SecurityDictionary RemoteConnections; private EndPoint fEndPoint; private AsyncCallback fAsync; private readonly string fAllowedIp; private Object fSyncState = new Object(); private readonly Object _Lock = new Object(); /// /// Returns an SocketId /// /// DuplicateId private int GenerateId() { lock (_Lock) { fId++; return fId; } } internal RemoteSocket() { // Makes a standard ip and port IPAddress fIp = IPAddress.Any; int fPort = 30001; // Makes allowed connection fAllowedIp = DuckEnvironment.ConfigManager.KeyVals["remote.ip"]; // Checks if the port is valid if (!int.TryParse(DuckEnvironment.ConfigManager.KeyVals["remote.port"],out fPort)) { DuckEnvironment.WriteLine("Remote Port is invalid, check your details!", ConsoleColor.Red); return; } // Creates the structure fAsync = new AsyncCallback(Interval); fSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); fEndPoint = new IPEndPoint(fIp, fPort); fSocket.Bind(fEndPoint); fSocket.Listen(BACKLOG_COUNT); RemoteConnections = new SecurityDictionary(); if (!TryAccept()) { DuckEnvironment.WriteLine("Remote Socket could not Accept any incoming Connections!", ConsoleColor.Yellow); } else { DuckEnvironment.WriteLine("Remote Socket is listening on " + fAllowedIp + ":" + fPort, ConsoleColor.Yellow); } } /// /// Trys to Begin Accept a new Remote-Connection /// /// Valid state of Socket protected virtual Boolean TryAccept() { if(GetSocket() == null) { return false; } fSyncState = GetSocket().BeginAccept(GetAsync(), GetSyncState()).AsyncState; return (fSyncState != null); } private void Interval(IAsyncResult Result) { if (Result == null) { return; } Socket i = null; try { i = GetSocket().EndAccept(Result); goto CONTINUE; } catch { goto STOP; } STOP: { if (i != null) { i.Close(); } goto CYCLE; } CONTINUE: { if (ValidConnection(i)) { int fId = GenerateId(); i = new Socket(i.DuplicateAndClose(Process.GetCurrentProcess().Id)); RemoveConnection myConn = new RemoveConnection(fId, i); RemoteConnections.Add(fId, myConn); RemoteConnections[fId].Receive(); } else { goto STOP; } goto CYCLE; } CYCLE: { TryAccept(); } } protected virtual Boolean ValidConnection(Socket Socket) { return (Socket.RemoteEndPoint.ToString().Split(':')[0] == fAllowedIp); } internal SecurityDictionary SerializeConnections() { return this.RemoteConnections; } internal Object GetSyncState() { return this.fSyncState; } internal AsyncCallback GetAsync() { return this.fAsync; } internal Socket GetSocket() { return this.fSocket; } } class RemoveConnection { private readonly int fId; private Socket fSocket; private AsyncCallback fAsyncRecv; private AsyncCallback fAsyncSend; private Object RecvSyncState = new Object(); private Object SendSyncState = new Object(); private byte[] BUFFER = new byte[1024]; internal RemoveConnection(int Id, Socket Sock) { this.fId = Id; this.fSocket = Sock; this.fAsyncRecv = new AsyncCallback(InteractReceive); this.fAsyncSend = new AsyncCallback(InteractSend); } internal void Receive() { if (GetSocket() != null) { try { RecvSyncState = GetSocket().BeginReceive(BUFFER, 0, BUFFER.Length, SocketFlags.None, GetAsyncRecv(), RecvSyncState).AsyncState; } catch { Close(); } } } internal void Send(byte[] Bytes) { if (GetSocket() != null) { try { SendSyncState = GetSocket().BeginSend(Bytes, 0, Bytes.Length, SocketFlags.None, GetAsyncRecv(), SendSyncState).AsyncState; } catch { Close(); } } } private void InteractReceive(IAsyncResult Result) { if (Result == null) { return; } ushort Bits = new ushort(); try { Bits = (ushort)fSocket.EndReceive(Result); } catch { Close(); return; } if (Bits > 0) { if (ParseCommand(Bits)) { Send(new byte[65]); // True } else { Send(new byte[64]); // False } } else if (Bits <= 0) { Close(); } Receive(); } private void InteractSend(IAsyncResult Result) { ushort Bits = new ushort(); try { Bits = (ushort)fSocket.EndSend(Result); } catch { Close(); return; } } private Boolean ParseCommand(ushort Bits) { string Line = Encoding.Default.GetString(BUFFER, 0, Bits); if (Line == null || Line == "") { return false; } var DataBits = Line.Split(Convert.ToChar(1)); var Header = DataBits[0]; var Params = DataBits.ToList().Remove(DataBits[0]); switch (Convert.ToInt16(Header)) { case 0: // Shutdown Hotel { DuckEnvironment.Dispose(); } return true; case 1: // Send HotelAlert { foreach (Client Client in DuckEnvironment.ClientManager.Clients.Values.ToList()) { Client.SendNotif(Convert.ToString(Params), true); } } return true; } return false; } private void Close() { if (DuckEnvironment.RemoteSocket.SerializeConnections().ContainsKey(fId)) { DuckEnvironment.RemoteSocket.SerializeConnections().Remove(fId); } fAsyncRecv = null; fAsyncSend = null; if (GetSocket() != null) { GetSocket().Shutdown(SocketShutdown.Both); fSocket = null; } } internal Socket GetSocket() { return this.fSocket; } internal AsyncCallback GetAsyncRecv() { return this.fAsyncRecv; } internal AsyncCallback GetAsyncSend() { return this.fAsyncSend; } } }