Пример #1
0
        public static void AcceptCallback(IAsyncResult ar)
        {
            m_AcceptEvent.Set();

            Socket          webSocket = m_ListeningSocket.EndAccept(ar);
            WebSocketClient client    = new WebSocketClient(webSocket);

            UOJS.Log("Client [{0}]: Connection Detected", client.WebSocket.RemoteEndPoint);
            webSocket.BeginReceive(client.WriteBuffer, 0, client.WriteBuffer.Length, SocketFlags.None, new AsyncCallback(ReadCallback), client);
        }
Пример #2
0
        public static void OnReceiveFromWebSocket(WebSocketClient client, byte[] data, int length)
        {
            try {
                switch ((char)data [0])
                {
                // Reconnect
                case 'R':
                {
                    if (client.UOSocket != null && client.UOSocket.Connected)
                    {
                        client.UOSocket.Close();
                    }
                    goto case 'C';
                }

                // Connect
                case 'C':
                {
                    string[] strData = Encoding.ASCII.GetString(data, 0, data.Length).Split(' ');
                    for (int i = 0; i < strData.Length; i++)
                    {
                        Console.Write(strData [i] + ",");
                    }
                    client.UOSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    Console.WriteLine(string.Join(",", strData));
                    client.UOSocket.BeginConnect(strData [1], int.Parse(strData [2]), new AsyncCallback(UOConnectCallback), client);
                    break;
                }

                // Version
                case 'V':
                {
                    GameProxy.Send(client, "Version {0}", UOJS.Version);
                    break;
                }


                default:
                {
                    client.UOSocket.BeginSend(data, 0, data.Length, SocketFlags.None, new AsyncCallback(UOSendCallback), client);
                    break;
                }
                }
            } catch (Exception e) {
                UOJS.Log("Client [d/c]: Threw {0}... closing!", e.GetType());
                UOJS.Log(e.StackTrace);
                client.Close();
            }
        }
Пример #3
0
        /// <summary>
        /// Initialize this instance.
        /// </summary>
        public static void Initialize()
        {
            if (!File.Exists(UltimaDllLocation))
            {
                UOJS.Log("Error: Cannot find Ultima.dll");
                return;
            }
            if (WebDirectory.Length <= 0 || !InitializeFiles())
            {
                UOJS.Log("Error: WebDirectory (\"{0}\") does not exist.", WebDirectory);
                return;
            }

            m_Ultima = Assembly.LoadFrom(UltimaDllLocation);
            m_SHA1   = SHA1.Create();

            UOJS.Log("Starting UOJS (version {0}, Ultima version {1}, port {2})", UOJS.Version, System.Diagnostics.FileVersionInfo.GetVersionInfo(m_Ultima.Location).FileVersion, ListeningPort);
            GameProxy.BeginListening();
        }
Пример #4
0
        /// <summary>
        /// Begins listening.
        /// </summary>
        protected static void Listen()
        {
            m_ListeningSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            m_ListeningSocket.Bind(new IPEndPoint(IPAddress.Loopback, ListeningPort));
            m_ListeningSocket.LingerState.Enabled = true;
            m_ListeningSocket.Listen(8);
            m_AcceptEvent = new ManualResetEvent(false);

            UOJS.Log("Listening: {0}", m_ListeningSocket.LocalEndPoint);

            while (m_Listening)
            {
                m_AcceptEvent.Reset();

                m_ListeningSocket.BeginAccept(new AsyncCallback(AcceptCallback), m_ListeningSocket);
                m_AcceptEvent.WaitOne();
            }
            UOJS.Log("Goodbye.");
        }
Пример #5
0
        public static void Send(WebSocketClient client, byte[] data, RequestType type, bool mask)
        {
            // masking isn't needed?
            int  headerLength = 2;
            byte payload      = 0;

            byte[] maskKeys = null;
            byte[] tmp      = new byte[data.Length + 1];
            tmp [0] = (byte)type;
            Array.Copy(data, 0, tmp, 1, data.Length);
            data = tmp;

            //data = Encoding.UTF8.GetBytes(((char)type) + Convert.ToBase64String(data));

            //data = Encoding.UTF8.GetBytes(Encoding.ASCII.GetString(data));
            //Console.WriteLine("Raw length={0}", data.Length);
            if (data.Length > short.MaxValue)
            {
                UOJS.Log("Client [{0}]: Sending Really Large Packet (not implemented)", client.WebSocket.RemoteEndPoint);
            }
            if (data.Length >= 126)
            {
                headerLength += 2;
                payload       = 126;
            }
            else
            {
                payload = (byte)data.Length;
            }
            if (mask)
            {
                headerLength += 4;
                Random r = new Random();
                maskKeys = new byte[] { 1, 2, 3, 4 };
                r.NextBytes(maskKeys);
            }

            byte[] allData = new byte[headerLength + data.Length];
            allData [0] = 0x80 | 0x02;
            allData [1] = (byte)((mask ? 0x80 : 0) | payload & 0x40 | payload & 0x20 | payload & 0x10 | payload & 0x8 | payload & 0x4 | payload & 0x2 | payload & 0x1);

            if (payload == 126)
            {
                byte[] lengthBytes = BitConverter.GetBytes((ushort)data.Length);
                allData [2] = lengthBytes [1];                 // (byte)((data.Length >> 8) & 0xFF);
                allData [3] = lengthBytes [0];                 // (byte)(data.Length & 0xFF);
            }

            Array.Copy(data, 0, allData, headerLength, data.Length);
            if (mask)
            {
                Array.Copy(maskKeys, 0, allData, 2, 4);
                for (int i = 0; i < data.Length; i++)
                {
                    allData [i + headerLength] ^= maskKeys [i % 4];
                }
            }


            if (client.WebSocket != null && client.WebSocket.Connected)
            {
                client.WebSocket.BeginSend(allData, 0, allData.Length, SocketFlags.None, new AsyncCallback(SendCallback), client);
            }
        }
Пример #6
0
        public static byte[] ParseWebRequest(WebSocketClient client, string shortUri, string fullUri)
        {
            try {
                switch (shortUri)
                {
                case "/td":
                {
                    Dictionary <string, string> query = ParseVars(fullUri);
                    int id = int.Parse(query ["id"]);
                    Dictionary <string, string> dict = new Dictionary <string, string> ();

                    PropertyInfo   info     = m_Ultima.GetType("Ultima.TileData").GetProperty("ItemTable", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
                    Type           itemData = m_Ultima.GetType("Ultima.ItemData");
                    object         o        = ((Array)info.GetValue(null, null)).GetValue(id);
                    PropertyInfo[] pubInfo  = itemData.GetProperties();
                    foreach (PropertyInfo p in pubInfo)
                    {
                        dict.Add(p.Name, p.GetValue(o, null).ToString());
                    }

                    return(m_Encoding.GetBytes(LitJson.JsonMapper.ToJson(dict)));
                }

                case "/getmapinfo":
                {
                    Dictionary <string, string> query = ParseVars(fullUri);
                    int    x = int.Parse(query ["x"]), y = int.Parse(query ["y"]), range = int.Parse(query ["r"]);
                    char   facet = query ["m"] [0];
                    string map;

                    switch (facet)
                    {
                    default:
                    case 'f':
                        map = "Felucca";
                        break;

                    case 't':
                        map = "Trammel";
                        break;

                    case 'i':
                        map = "Ilshenar";
                        break;

                    case 'm':
                        map = "Malas";
                        break;

                    case 'o':
                        map = "Tokuno";
                        break;                                                 // whoops
                    }

                    Type Map = m_Ultima.GetType("Ultima.Map");
                    Type Tile = m_Ultima.GetType("Ultima.Tile");
                    Type HuedTile = m_Ultima.GetType("Ultima.HuedTile");
                    Type TileMatrix = m_Ultima.GetType("Ultima.TileMatrix");
                    Dictionary <string, Dictionary <string, Dictionary <string, object> > > data
                        = new Dictionary <string, Dictionary <string, Dictionary <string, object> > > ();
                    object currentMap = ((FieldInfo)Map.GetMember(map) [0]).GetValue(null);
                    object tiles = Map.GetProperty("Tiles").GetValue(currentMap, null);

                    for (int i = 0; i < range; i++)
                    {
                        Dictionary <string, Dictionary <string, object> > row;
                        data.Add((i + x).ToString(), row = new Dictionary <string, Dictionary <string, object> > ());

                        for (int j = 0; j < range; j++)
                        {
                            Dictionary <string, object> cell = new Dictionary <string, object> ();
                            object landTile    = TileMatrix.GetMethod("GetLandTile").Invoke(tiles, new object[] { x + i, y + j });
                            Array  staticTiles = (Array)TileMatrix.GetMethod("GetStaticTiles").Invoke(tiles, new object[] { x + i, y + j });
                            int    id          = (int)Tile.GetProperty("ID").GetValue(landTile, null);
                            int    z           = (int)Tile.GetProperty("Z").GetValue(landTile, null);

                            cell.Add("id", id);
                            cell.Add("z", z);
                            cell.Add("length", staticTiles.Length);
                            TileInfo[] stiles = new TileInfo[staticTiles.Length];
                            for (int k = 0; k < stiles.Length; k++)
                            {
                                stiles [k].ID = (int)(HuedTile.GetProperty("ID").GetValue(staticTiles.GetValue(k), null)) % 0x4000;

                                stiles [k].Hue = (int)HuedTile.GetProperty("Hue").GetValue(staticTiles.GetValue(k), null);
                                stiles [k].Z   = (int)HuedTile.GetProperty("Z").GetValue(staticTiles.GetValue(k), null);
                            }
                            cell.Add("o", stiles);
                            row.Add((j + y).ToString(), cell);
                        }
                    }

                    return(m_Encoding.GetBytes(LitJson.JsonMapper.ToJson(data)));
                }


                case "/getgump":
                {
                    Dictionary <string, string> query = ParseVars(fullUri);
                    foreach (KeyValuePair <string, string> kvp in query)
                    {
                        Console.WriteLine(kvp);
                    }
                    int  id    = int.Parse(query ["id"]);
                    Type Gumps = m_Ultima.GetType("Ultima.Gumps");

                    //int hueIdx = int.Parse (query ["h"]);

                    //Hue hue = hueIdx == 0 ? null : Hues.List [(hueIdx & 0x3FFF) - 1];

                    //Bitmap b = (Bitmap)(Gumps.GetGump (id).Clone ());

                    Bitmap b = (Bitmap)Gumps.GetMethod("GetGump", new Type[] { typeof(Int32) }).Invoke(null, new object[] { id });
                    //if (hue != null)
                    //	hue.ApplyTo (b, true);

                    MemoryStream ms = new MemoryStream();
                    b.Save(ms, System.Drawing.Imaging.ImageFormat.Png);

                    return(ms.GetBuffer());
                }

                case "/getobj":
                {
                    Dictionary <string, string> query = ParseVars(fullUri);
                    char type   = query ["t"] [0];
                    int  id     = int.Parse(query ["i"]);
                    int  hueIdx = int.Parse(query ["h"]);

                    string crop = query.ContainsKey("c") ? query ["c"] : "";
                    Type   Art  = m_Ultima.GetType("Ultima.Art");
                    Bitmap b    = (Bitmap)(Art.GetMethod(type == 'l' ? "GetLand" : "GetStatic", new Type[] { typeof(Int32) }).Invoke(null, new object[] { id }));
                    //Bitmap b = (Bitmap)(type == 'l' ? Art.GetLand (id) : Art.GetStatic (id)); //don't hue the cached, clone it
                    //if (b == null)
                    //	b = Art.GetLand (0);
                    b = (Bitmap)b.Clone();

                    //TODO: clone before hue (prevent modifying cache object)
                    //Hue hue = hueIdx == 0 ? null : Hues.List [(hueIdx & 0x3FFF) - 1];
                    //if (hue != null)
                    //	hue.ApplyTo (b, type == 'l');

                    switch (crop)
                    {
                    // why can't this be done on the client side by only drawing half after
                    // the transformation? set the sX to the half or set the sW to the half
                    // depending on the side??
                    case "right":
                    {
                        for (int x = 0; x < b.Width / 2; x++)
                        {
                            for (int y = 0; y < b.Height; y++)
                            {
                                b.SetPixel(x, y, Color.Transparent);
                            }
                        }
                        break;
                    }

                    case "left":
                    {
                        for (int x = b.Width / 2; x < b.Width; x++)
                        {
                            for (int y = 0; y < b.Height; y++)
                            {
                                b.SetPixel(x, y, Color.Transparent);
                            }
                        }
                        break;
                    }
                    }
                    MemoryStream ms = new MemoryStream();
                    b.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
                    return(ms.GetBuffer());
                }

                case "/getcliloc":
                {
                    Dictionary <string, string> query = ParseVars(fullUri);
                    int  message = int.Parse(query ["i"]), i = 0;
                    Type StringList = m_Ultima.GetType("Ultima.StringList");
                    System.Collections.Hashtable table = (System.Collections.Hashtable)StringList.GetProperty("Table").GetValue(StringList.GetProperty("EnglishStringList", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy).GetValue(null, null), null);
                    if (!table.ContainsKey(message))
                    {
                        return(m_Encoding.GetBytes("{\"text\": null}"));
                    }

                    string entry = (string)table [message];

                    return(UTF8Encoding.UTF8.GetBytes(entry));
                    //string replace = Regex.Replace (entry, @"~[A-Za-z0-9_]+~", match => (query.ContainsKey ("" + (++i)) ? query ["" + (i)] : ""));

                    //return UTF8Encoding.UTF8.GetBytes ("{\"text\":\"" + replace.Replace ("\"", "\\\"") + "\"}");
                }

                case "/getaniminfo":
                {
                    Dictionary <string, string> query = ParseVars(fullUri);
                    int    bodyId = int.Parse(query ["i"]);
                    int    action = int.Parse(query ["a"]);
                    int    dir    = int.Parse(query ["d"]);
                    int    hash   = (bodyId << 16) | (action << 8) | (dir);
                    byte[] widths = null;

                    if (m_Widths.ContainsKey(hash))
                    {
                        widths = m_Widths [hash];
                    }
                    else
                    {
                        Type  Animations = m_Ultima.GetType("Ultima.Animations");
                        Type  Frame      = m_Ultima.GetType("Ultima.Frame");
                        Array frames     = (Array)Animations.GetMethod("GetAnimation").Invoke(null, new object[] {
                                bodyId,
                                action,
                                dir,
                                0,
                                true
                            });
                        //Frame[] frames = Animations.GetAnimation (bodyId, action, dir, 0, true);

                        if (frames == null)
                        {
                            widths = new byte[0];
                        }
                        else
                        {
                            widths = new byte[frames.Length];
                            for (int i = 0; i < frames.Length; i++)
                            {
                                System.Drawing.Bitmap b = (System.Drawing.Bitmap)Frame.GetProperty("Bitmap").GetValue(frames.GetValue(i), null);
                                widths [i] = (byte)b.Width;
                            }
                        }
                    }
                    List <string> tmp = new List <string> ();
                    foreach (byte b in widths)
                    {
                        tmp.Add(b.ToString());
                    }

                    return(ASCIIEncoding.ASCII.GetBytes("{\"widths\": [" + string.Join(",", tmp.ToArray()) + "]}"));
                }

                case "/getanim":
                {
                    //todo: check if wearable and adjust bitmap accordingly if human
                    Dictionary <string, string> query = ParseVars(fullUri);
                    int   bodyId     = int.Parse(query ["i"]);
                    int   action     = int.Parse(query ["a"]);
                    int   dir        = int.Parse(query ["d"]);
                    int   hueIdx     = int.Parse(query ["h"]);
                    Type  Animations = m_Ultima.GetType("Ultima.Animations");
                    Type  Frame      = m_Ultima.GetType("Ultima.Frame");
                    Array frames     = (Array)Animations.GetMethod("GetAnimation").Invoke(null, new object[] {
                            bodyId,
                            action,
                            dir,
                            0,
                            true
                        });
                    //Frame[] frames = Animations.GetAnimation (bodyId, action, dir, 0, true);
                    //Hue hue = hueIdx == 0 ? null : Hues.List [(hueIdx & 0x3FFF) - 1];
                    int hash = (bodyId << 16) | (action << 8) | (dir);
                    if (frames == null)
                    {
                        return new byte[] { }
                    }
                    ;

                    int maxWidth = 0, maxHeight = 0;
                    for (int i = 0; i < frames.Length; i++)
                    {
                        System.Drawing.Bitmap b = (System.Drawing.Bitmap)Frame.GetProperty("Bitmap").GetValue(frames.GetValue(i), null);
                        if (b.Width > maxWidth)
                        {
                            maxWidth = b.Width;                                             // +Math.Abs(frame.Center.X);
                        }
                        if (b.Height > maxHeight)
                        {
                            maxHeight = b.Height;                                             // +Math.Abs(frame.Center.Y);
                        }
                    }
                    // should we cache full animation bitmaps?
                    Bitmap   bitmap = new Bitmap(maxWidth * frames.Length, maxHeight);
                    Graphics g      = Graphics.FromImage(bitmap);

                    byte[] widths = new byte[frames.Length];
                    for (int i = 0; i < frames.Length; i++)
                    {
                        object frame = frames.GetValue(i);
                        System.Drawing.Bitmap single = (System.Drawing.Bitmap)Frame.GetProperty("Bitmap").GetValue(frames.GetValue(i), null);

                        widths [i] = (byte)single.Width;
                        g.DrawImageUnscaled(single, i * maxWidth, 0);
                    }
                    if (!m_Widths.ContainsKey(hash))
                    {
                        m_Widths.Add(hash, widths);
                    }
                    //if (hueIdx != 0)
                    //	hue.ApplyTo (bitmap, TileData.AnimationData.ContainsKey (bodyId) && (TileData.AnimationData [bodyId].Flags & TileFlag.PartialHue) != 0);
                    bitmap.SetPixel(0, 0, Color.FromArgb(0, 0, 0, frames.Length));
                    MemoryStream ms = new MemoryStream();
                    bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
                    return(ms.GetBuffer());
                }
                }
            } catch (Exception e) {
                UOJS.Log("Error {0}\r\n{1}", e.Message, e.StackTrace);
                return(ASCIIEncoding.ASCII.GetBytes(string.Format("An error has occurred: {0}\r\n{1}", e.Message, e.StackTrace)));
            }
            return(new byte[] { });
        }
Пример #7
0
        public static void ReadCallback(IAsyncResult ar)
        {
            WebSocketClient client    = (WebSocketClient)ar.AsyncState;
            Socket          webSocket = client.WebSocket;
            int             read;

            try {
                read = webSocket.Connected ? webSocket.EndReceive(ar) : 0;
            } catch (Exception e) {
                read = 0;
                Console.WriteLine("Socket [disposed]: {0}", e.Message);
            }
            if (read > 0)
            {
                if (!client.SentHeaders)
                {
                    string      sendHeaders, shortUri, fullUri;
                    RequestType type = CreateHeaders(m_Encoding.GetString(client.WriteBuffer),
                                                     out sendHeaders,
                                                     out shortUri,
                                                     out fullUri);

                    switch (type)
                    {
                    case RequestType.GameRequest:
                    {
                        client.WebSocket.BeginSend(ASCIIEncoding.ASCII.GetBytes(sendHeaders), 0, sendHeaders.Length, SocketFlags.None, new AsyncCallback(SendCallback), client);
                        Console.WriteLine("Client [{0}]: Handshake OK", client.WebSocket.RemoteEndPoint);
                        break;
                    }

                    case RequestType.WebRequest:
                    {
                        Console.WriteLine("WebReq [{0}]: Parsed", client.WebSocket.RemoteEndPoint);
                        byte[] toSend  = ParseWebRequest(client, shortUri, fullUri);
                        byte[] headers = ASCIIEncoding.ASCII.GetBytes(sendHeaders);
                        byte[] all     = new byte[headers.Length + toSend.Length];

                        Array.Copy(headers, all, headers.Length);
                        Array.Copy(toSend, 0, all, headers.Length, toSend.Length);

                        client.WebSocket.BeginSend(all, 0, all.Length, SocketFlags.None, new AsyncCallback(WebSendCallback), client);
                        return;
                    }
                    }
                    client.SentHeaders = true;
                }
                else if (client.CurrentPacket != null)
                {
                    int length = client.CurrentPacket.Data.Length;

                    if (client.CurrentPacket.Data.Length < (client.CurrentPacket.Read + read))
                    {
                        //mismatch = true;
                        Console.WriteLine("packet length mismatch (should be {0}, but is {1})", client.CurrentPacket.Data.Length, (client.CurrentPacket.Read + read));

                        Array.Resize <byte> (ref client.CurrentPacket.Data, client.CurrentPacket.Read + read);
                        Array.Copy(client.WriteBuffer, 0, client.CurrentPacket.Data, client.CurrentPacket.Read, read);
                    }
                    for (int i = client.CurrentPacket.Read; i < client.CurrentPacket.Read + read; i++)
                    {
                        client.CurrentPacket.Data [i] ^= client.CurrentPacket.Mask [i % 4];
                    }
                    client.CurrentPacket.Read += read;

                    if (client.CurrentPacket.Read >= client.CurrentPacket.Data.Length)
                    {
                        OnReceiveFromWebSocket(client, client.CurrentPacket.Data, length);
                        client.CurrentPacket = null;
                    }
                }
                else
                {
                    byte zero   = client.WriteBuffer [0];
                    byte one    = client.WriteBuffer [1];
                    bool fin    = (zero & 0x80) == 0x80;
                    byte opCode = (byte)((zero & 0x8) | (zero & 0x4) | (zero & 0x2) | (zero & 0x1));

                    switch (opCode)
                    {
                    case 0x08:
                    {
                        Console.WriteLine("Client [{0}]: Closing Connection (browser sent 0x08)", client.WebSocket.RemoteEndPoint);
                        client.Close();
                        return;
                    }
                    }

                    bool mask    = (one & 0x80) == 0x80;
                    byte payload = (byte)((one & 0x40) | (one & 0x20) | (one & 0x10) | (one & 0x8) | (one & 0x4) | (one & 0x2) | (one & 0x1));
                    int  length  = 0;
                    int  s       = 0;

                    switch (payload)
                    {
                    case 126:
                        //16-bit
                        length = (int)((client.WriteBuffer [2] << 8) | client.WriteBuffer [3]);
                        s      = 2;
                        break;

                    case 127:
                        //32-bit???
                        UOJS.Log("Client [{0}]: Got a really big packet (over 16-bits size), so I'll just kill it...", client.WebSocket.RemoteEndPoint);
                        client.Close();
                        return;

                    default:
                        //8-bit
                        length = payload;
                        break;
                    }

                    client.CurrentPacket = new WebSocketPacket();
                    if (mask)
                    {
                        // create the bit mask?
                        // I'm still unsure why the masked is being forced
                        // in the websocket protocol. oh well.
                        client.CurrentPacket.Mask = new byte[] {
                            client.WriteBuffer [s + 2],
                            client.WriteBuffer [s + 3],
                            client.WriteBuffer [s + 4],
                            client.WriteBuffer [s + 5]
                        };
                        s += 6;
                    }

                    client.CurrentPacket.Data  = new byte[length];
                    client.CurrentPacket.Read += read - s;


                    Array.Copy(client.WriteBuffer, s, client.CurrentPacket.Data, 0, Math.Min(client.CurrentPacket.Read, client.CurrentPacket.Data.Length));
                    if (mask)
                    {
                        for (int i = 0; i < client.CurrentPacket.Data.Length; i++)
                        {
                            client.CurrentPacket.Data [i] ^= client.CurrentPacket.Mask [i % 4];
                        }
                    }
                    if (client.CurrentPacket.Read == client.CurrentPacket.Data.Length)
                    {
                        OnReceiveFromWebSocket(client, client.CurrentPacket.Data, client.CurrentPacket.Data.Length);
                        client.CurrentPacket = null;
                    }
                }
                if (webSocket != null && webSocket.Connected)
                {
                    webSocket.BeginReceive(client.WriteBuffer, 0, WebSocketClient.MaxBufferSize, SocketFlags.None, new AsyncCallback(ReadCallback), client);
                }
            }
            else
            {
                UOJS.Log("Client [disposed]: No data @ ReadCallback");
            }
        }