using System; using System.Net; using System.Net.Sockets; using System.Collections.Generic; using Holo.Managers; using Holo.Virtual.Users; using Holo.Virtual.Rooms; using System.Collections; namespace Holo.Socketservers { /// /// Asynchronous socket server for the MUS connections. /// public static class musSocketServer { private static Socket socketHandler; private static int _Port; private static string _musHost; /// /// Initializes the socket listener for MUS connections and starts listening. /// /// The port where the socket listener should be bound to. /// internal static bool Init(int bindPort, string musHost) { _Port = bindPort; _musHost = musHost; socketHandler = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { socketHandler.Bind(new IPEndPoint(IPAddress.Any, bindPort)); socketHandler.Listen(25); socketHandler.BeginAccept(new AsyncCallback(connectionRequest), socketHandler); return true; } catch { Out.WriteError("Error while setting up asynchronous socket server for MUS connections on port " + bindPort); Out.WriteError("Port " + bindPort + " could be invalid or in use already."); return false; } } private static void connectionRequest(IAsyncResult iAr) { Socket newSocket = ((Socket)iAr.AsyncState).EndAccept(iAr); musConnection newConnection = new musConnection(newSocket); socketHandler.BeginAccept(new AsyncCallback(connectionRequest), socketHandler); } /// /// Represents an asynchronous, one time usage, socket connection between the emulator and HoloCMS, used for various live updates between site & server. /// private class musConnection { private Socket Connector; private byte[] dataBuffer = new byte[10001]; /// /// Initializes the musConnection and listens for one single packet, processes it and closes the connection. On any error, the connection is closed. /// /// The socket of the musConnection. internal musConnection(Socket Connector) { this.Connector = Connector; Connector.BeginReceive(dataBuffer, 0, dataBuffer.Length, SocketFlags.None, new AsyncCallback(dataArrival), null); } /// /// Called when a packet is received, the packet will be processed and the connection will be closed (after processing packet) in all cases. No errors will be thrown. /// /// private void dataArrival(IAsyncResult iAr) { try { int bytesReceived = Connector.EndReceive(iAr); string Data = System.Text.Encoding.ASCII.GetString(dataBuffer, 0, bytesReceived); if (Data == "") killConnection(); string musHeader = Data.Substring(0, 4); string[] musData = Data.Substring(4).Split(Convert.ToChar(2)); //Out.WriteLine("DATA: " + Data); #region MUS trigger commands // Unsafe code, but on any error it jumps to the catch block & disconnects the socket switch (musHeader) { case "BDHK": // User profile - show new badge { int userID = int.Parse(musData[0].Split(Convert.ToChar(2))[0]); string badgeCode = musData[0].Split(Convert.ToChar(2))[1]; if (userManager.containsUser(userID)) { virtualUser User = userManager.getUser(userID); User.sendData("Fu" + Encoding.encodeVL64(User._Badges.Count + 1) + "H" + badgeCode + Convert.ToChar(2)); User.refreshBadges(); } break; } case "HKRC": // Housekeeping - rehash catalogue :: "HKRC" { catalogueManager.Init(false); break; } case "UPRA": // User profile - reload figure, sex and mission (poof!) { int userID = int.Parse(musData[0]); if (userManager.containsUser(userID)) userManager.getUser(userID).refreshAppearance(true, true, true, true); break; } case "UPRC": // User profile - reload credits { int userID = int.Parse(musData[0]); userManager.getUser(userID).refreshValueables(true, false); break; } case "UPRT": // User profile - reload tickets { int userID = int.Parse(musData[0]); if (userManager.containsUser(userID)) userManager.getUser(userID).refreshValueables(false, true); break; } case "UPRS": // User profile - reload subscription (and badges) { int userID = int.Parse(musData[0]); if (userManager.containsUser(userID)) { virtualUser User = userManager.getUser(userID); User.refreshClub(); User.refreshBadges(); } break; } case "UPRH":// User profile - reload hand { int userID = int.Parse(musData[0]); if (userManager.containsUser(userID)) userManager.getUser(userID).refreshHand("new"); break; } default: { Out.WriteError("UNKNOWN MUSDATA:" + musData); break; } } #endregion } catch { } finally { killConnection(); } } /// /// Closes the connection and destroys the object. /// private void killConnection() { try { Connector.Close(); } catch { } } } } }