Ejemplo n.º 1
0
        /// <summary>
        /// Utility function to wrap the error message into a JSON message.
        /// </summary>
        /// <param name="err"></param>
        /// <returns></returns>
        private String JSONError(String err)
        {
            JSONstatus status = new JSONstatus();

            status.result = err;

            return(this.serializer.Serialize(status));
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Process the current HTTP/REST request
        /// </summary>
        /// <param name="Context">returned from the asynchronous httplistener</param>
        protected virtual void ProcessRequest(HttpListenerContext Context)
        {
            HttpListenerRequest request = Context.Request;
            HttpListenerResponse response = Context.Response;
            String cmd = request.Url.LocalPath.Substring(1).ToUpper();
            String responseString = null;

            response.StatusCode = (int)HttpStatusCode.OK;

            // Giant command processing switch
            switch (cmd) {
                case "WHOAMI":
                    IPAddress who =  request.RemoteEndPoint.Address;
                    JSONwhoami ami = new JSONwhoami();

                    Trace.WriteLine("DEBUG: I am " + who.ToString() + " " + request.Headers);
                    foreach (NetService service in sinkServices) {
                        IList addresses = service.Addresses;

                        foreach (IPEndPoint addr in addresses) {
                            Trace.WriteLine("DEBUG: am I sink " + addr.Address.ToString());
                            if (who.Equals(addr.Address)) {
                                if (service.Type.StartsWith(Shared.DisplayCastGlobals.PLAYER))
                                    ami.player = service.Name;
                                if (service.Type.StartsWith(Shared.DisplayCastGlobals.ARCHIVER))
                                    ami.archiver = service.Name;
                            }
                        }
                    }

                    foreach (NetService service in sourceServices) {
                        IList addresses = service.Addresses;

                        foreach (IPEndPoint addr in addresses) {
                            Trace.WriteLine("DEBUG: am I source " + addr.Address.ToString());
                            if (who.Equals(addr.Address)) {
                                if (service.Type.StartsWith(Shared.DisplayCastGlobals.STREAMER))
                                    ami.streamer = service.Name;
                            }
                        }
                    }
                    responseString = serializer.Serialize(ami);
                    break;

                case "LISTPLAYERS":
                    responseString = serializer.Serialize(players);
                    break;

                case "LISTARCHIVERS":
                    responseString = serializer.Serialize(archivers);
                    break;

                case "LISTSTREAMERS":
                    responseString = serializer.Serialize(streamers);
                    break;

                case "LISTSESSIONS":
                    responseString = serializer.Serialize(sessions);
                    break;

                case "STATUS":
                    if ((request.Url.Query == null) || (request.Url.Query.Length < 2)) {
                        response.StatusCode = (int)HttpStatusCode.BadRequest;
                        response.StatusDescription = DisplayCastGlobals.CONTROL_USAGE_STATUS;
                        responseString = JSONError(DisplayCastGlobals.CONTROL_JSON_SYNTAX_ERROR);
                    } else {
                        String id = request.Url.Query.Substring(1);
                        JSONSrcSink res = null;

                        // Could be status of players/archivers/streamers
                        foreach (JSONSrcSink clnt in players)
                            if (clnt.id.Equals(id)) {
                                res = clnt;
                                break;
                            }
                        if (res == null)
                            foreach (JSONSrcSink clnt in archivers)
                                if (clnt.id.Equals(id)) {
                                    res = clnt;
                                    break;
                                }
                        if (res == null)
                            foreach (JSONSrcSink clnt in streamers)
                                if (clnt.id.Equals(id)) {
                                    res = clnt;
                                    break;
                                }
                        if (res == null) {
                            response.StatusCode = (int)HttpStatusCode.NotFound;
                            response.StatusDescription = "ID: " + id + " unknown";
                            responseString = JSONError(DisplayCastGlobals.CONTROL_JSON_UNKNOWN_ERROR);
                        } else
                            responseString = serializer.Serialize(res);
                    }
                    break;

                case "SESSIONSTATUS":
                    if ((request.Url.Query == null) || (request.Url.Query.Length < 2)) {
                        response.StatusCode = (int)HttpStatusCode.BadRequest;
                        response.StatusDescription = DisplayCastGlobals.CONTROL_USAGE_SESSIONSTATUS;
                        responseString = JSONError(DisplayCastGlobals.CONTROL_JSON_SYNTAX_ERROR);
                    } else {
                        String id = request.Url.Query.Substring(1);
                        JSONSession res = null;

                        foreach (JSONSession sess in sessions)
                            if (sess.id.Equals(id)) {
                                res = sess;
                                break;
                            }
                        if (res == null) {
                            response.StatusCode = (int)HttpStatusCode.NotFound;
                            response.StatusDescription = "ID: " + id + " unknown";
                            responseString = JSONError(DisplayCastGlobals.CONTROL_JSON_UNKNOWN_ERROR);
                        } else
                            responseString = serializer.Serialize(res);
                    }
                    break;

                case "SNAPSHOT":
                    if ((request.Url.Query == null) || (request.Url.Query.Length < 2)) {
                        response.StatusCode = (int)HttpStatusCode.BadRequest;
                        response.StatusDescription = DisplayCastGlobals.CONTROL_USAGE_SNAPSHOT;
                        responseString = JSONError(DisplayCastGlobals.CONTROL_JSON_SYNTAX_ERROR);
                    } else {
                        String id = request.Url.Query.Substring(1);
                        char[] delimiters = { '=', '&' };
                        String[] words = id.Split(delimiters);

                        if ((words.Length < 2) || (!words[0].ToUpper().Equals("ID"))) {
                            response.StatusCode = (int)HttpStatusCode.BadRequest;
                            response.StatusDescription = DisplayCastGlobals.CONTROL_USAGE_SNAPSHOT;
                            responseString = JSONError(DisplayCastGlobals.CONTROL_JSON_SYNTAX_ERROR);
                        } else {
                            NetService service = null;

                            foreach (NetService s in sourceServices)
                                if (s.Name.Equals(words[1])) {
                                    service = s;

                                    break;
                                }
            #if DEBUG
                            else
                                responseString = responseString + "Are we: " + s.Name + "\n";
            #endif

                            if (service == null) {
                                response.StatusCode = (int)HttpStatusCode.NotFound;
                                response.StatusDescription = "ID: " + words[1] + " unknown";
                                responseString = JSONError(
            #if DEBUG
                                    responseString +
            #endif
                                    DisplayCastGlobals.CONTROL_JSON_UNKNOWN_ERROR + words[1]);
                            } else {
                                String port = null;

                                if (service.TXTRecordData != null) {
                                    byte[] txt = service.TXTRecordData;
                                    IDictionary dict = NetService.DictionaryFromTXTRecordData(txt);

                                    if (dict != null) {
                                        foreach (DictionaryEntry kvp in dict) {
                                            String key = (String)kvp.Key;

                                            key = key.ToUpper();
                                            if (key.Equals("IMAGEPORT")) {
                                                byte[] value = (byte[])kvp.Value;

                                                try {
                                                    port = Encoding.UTF8.GetString(value);
                                                } catch {
                                                }
                                                break;
                                            }
                                        }
                                    }
                                }

                                if (port == null) {
                                    response.ContentType = "image/png";
                                    Int32 reqWidth = 800, reqHeight = 600;

                                    if ((words.Length >= 4) && (words[3].ToUpper().Equals("WIDTH"))) {
                                        reqWidth = Convert.ToInt32(words[4]);
                                        reqHeight = reqWidth * reqHeight / 800;
                                    }

                                    Bitmap bmp = new Bitmap(reqWidth, reqHeight, PixelFormat.Format24bppRgb);
                                    Graphics g = Graphics.FromImage(bmp);
                                    Font rectangleFont = new Font("Arial", 10, FontStyle.Bold);

                                    g.SmoothingMode = SmoothingMode.AntiAlias;
                                    g.Clear(Color.LightGray);

                                    g.DrawString("Desktop snapshot from " + service.Name + " should go here", rectangleFont, SystemBrushes.WindowText, new PointF(10, 40));
                                    bmp.Save(response.OutputStream, ImageFormat.Png);

                                    g.Dispose();
                                    bmp.Dispose();
                                } else {
                                    IList addresses = service.Addresses;
                                    int portNum = Convert.ToInt32(port);

                                    foreach (System.Net.IPEndPoint addr in addresses) {
                                        System.Net.Sockets.TcpClient clntSocket = new System.Net.Sockets.TcpClient();
                                        try {
                                            clntSocket.Connect(addr.Address, portNum);
                                            if (clntSocket.Connected) {
                                                clntSocket.Close();

                                                response.Redirect("http://" + addr.Address.ToString() + ":" + port + request.Url.Query);
                                                break;
                                            }
                                        } catch (SocketException) {
                                            //Ignore and try the next address
                                        }
                                    }
                                    if (response.StatusCode != (int)HttpStatusCode.Redirect) {
                                        response.ContentType = "image/png";

                                        Int32 reqWidth = 800, reqHeight = 600;

                                        if ((words.Length >= 4) && (words[2].ToUpper().Equals("WIDTH"))) {
                                            reqWidth = Convert.ToInt32(words[3]);
                                            reqHeight = reqWidth * reqHeight / 800;
                                            Trace.WriteLine("DEBUG: Changed image dimensions to: " + reqWidth + "x" + reqHeight);
                                        }

                                        Bitmap bmp = new Bitmap(reqWidth, reqHeight, PixelFormat.Format24bppRgb);
                                        Graphics g = Graphics.FromImage(bmp);
                                        Font rectangleFont = new Font("Arial", 10, FontStyle.Bold);

                                        g.SmoothingMode = SmoothingMode.AntiAlias;
                                        g.Clear(Color.LightGray);

                                        g.DrawString("Desktop " + service.Name + "at " + port + " not responding", rectangleFont, SystemBrushes.WindowText, new PointF(10, 40));
                                        bmp.Save(response.OutputStream, ImageFormat.Png);

                                        g.Dispose();
                                        bmp.Dispose();
                                    }
                                }

                                response.Close();
                                return;
                            }
                        }
                    }
                    break;

                case "CONNECT":
                    if ((request.Url.Query == null) || (request.Url.Query.Length < 2)) {
                        response.StatusCode = (int)HttpStatusCode.BadRequest;
                        response.StatusDescription = DisplayCastGlobals.CONTROL_USAGE_CONNECT;
                        responseString = JSONError(DisplayCastGlobals.CONTROL_JSON_SYNTAX_ERROR);
                    } else {
                        String q = request.Url.Query.Substring(1);
                        char[] delimiters = { '=', '&' };
                        String[] words = q.Split(delimiters);

                        if (((words.Length == 4) || (words.Length == 6)) && words[0].ToUpper().Equals("SOURCE") && words[2].ToUpper().Equals("SINK")) {
                            String srcId = words[1], sinkId = words[3];
                            NetService service = null;

                            foreach (NetService s in sinkServices)
                                if (s.Name.Equals(sinkId)) {
                                    service = s;
                                    break;
                                }

                            // We don't sanity check sources. Let the sink report an error, maybe the sink knows something that we don't know
                            if (service == null) {
                                response.StatusCode = (int)HttpStatusCode.NotFound;
                                response.StatusDescription = "Unknown sink: " + sinkId;
                                responseString = JSONError(DisplayCastGlobals.CONTROL_JSON_UNKNOWN_ERROR);
                            } else {
                                JSONnewSession ns = new JSONnewSession();
                                ns.id = sendCommand(service, "SHOW " + srcId + "\n");
                                responseString = serializer.Serialize(ns);
                            }
                        } else {
                            response.StatusDescription = DisplayCastGlobals.CONTROL_USAGE_CONNECT;
                            response.StatusCode = (int)HttpStatusCode.BadRequest;
                            responseString = JSONError(DisplayCastGlobals.CONTROL_JSON_SYNTAX_ERROR);
                        }
                    }
                    break;

                case "DISCONNECT":
                    if ((request.Url.Query == null) || (request.Url.Query.Length < 2)) {
                        response.StatusCode = (int)HttpStatusCode.BadRequest;
                        response.StatusDescription = DisplayCastGlobals.CONTROL_USAGE_DISCONNECT;
                        responseString = JSONError(DisplayCastGlobals.CONTROL_JSON_SYNTAX_ERROR);
                    } else {
                        String g = request.Url.Query.Substring(1);
                        char[] delimiters = { '=', '&' };
                        String[] words = g.Split(delimiters);
                        NetService service = null;
                        String sinkId = null;

                        if (((words.Length == 4) || (words.Length == 2)) & (words[0].ToUpper().Equals("ID"))) {
                            String debug = null;
                            foreach (JSONSession sess in sessions) {
                                debug = debug + " " + sess.id;
                                if (words[1].Equals(sess.id)) {
                                    sinkId = sess.sinkId;

                                    break;
                                }
                            }
                            if (sinkId == null) {
                                response.StatusDescription = "Unknown session ID: " + words[1];
                                response.StatusCode = (int)HttpStatusCode.NotFound;
                                responseString = JSONError("UNKNOWN ID: " + words[1] + " looked at " + debug);
                            } else {
                                foreach (NetService s in sinkServices)
                                    if (s.Name.Equals(sinkId)) {
                                        service = s;
                                        break;
                                    }

                                if (service == null) {
                                    response.StatusDescription = "Unknown sink ID: " + sinkId;
                                    response.StatusCode = (int)HttpStatusCode.NotFound;
                                    responseString = JSONError(DisplayCastGlobals.CONTROL_JSON_UNKNOWN_ERROR);
                                } else {
                                    JSONstatus status = new JSONstatus();
                                    status.result = sendCommand(service, "CLOSE " + words[1] + "\n");
                                    responseString = serializer.Serialize(status);
                                }
                            }
                        } else {
                            response.StatusDescription = DisplayCastGlobals.CONTROL_USAGE_DISCONNECT;
                            response.StatusCode = (int)HttpStatusCode.BadRequest;
                            responseString = JSONError(DisplayCastGlobals.CONTROL_JSON_SYNTAX_ERROR);
                        }

                    }
                    break;

                case "MOVE":
                    if ((request.Url.Query == null) || (request.Url.Query.Length < 2)) {
                        response.StatusCode = (int)HttpStatusCode.BadRequest;
                        response.StatusDescription = DisplayCastGlobals.CONTROL_USAGE_MOVE;
                        responseString = JSONError(DisplayCastGlobals.CONTROL_JSON_SYNTAX_ERROR);
                    } else {
                        String q = request.Url.Query.Substring(1);
                        char[] delimiters = { '=', '&' };
                        String[] words = q.Split(delimiters);

                        if (((words.Length == 10) || (words.Length == 12)) && words[0].ToUpper().Equals("SESSIONID") && words[2].ToUpper().Equals("X") && words[4].ToUpper().Equals("Y") && words[6].ToUpper().Equals("WIDTH") && words[8].ToUpper().Equals("HEIGHT")) {
                            NetService service = null;
                            String sinkId = null;
                            JSONSession session = null;
                            String sessId = words[1];

                            foreach (JSONSession sess in sessions)
                                if (sessId.Equals(sess.id)) {
                                    sinkId = sess.sinkId;
                                    session = sess;
                                    break;
                                }

                            if (sinkId == null) {
                                response.StatusCode = (int)HttpStatusCode.NotFound;
                                response.StatusDescription = "Unknown session: " + sessId;
                                responseString = JSONError(DisplayCastGlobals.CONTROL_JSON_UNKNOWN_ERROR);
                            } else {
                                foreach (NetService s in sinkServices)
                                    if (s.Name.Equals(sinkId)) {
                                        service = s;
                                        break;
                                    }

                                if (service == null) {
                                    response.StatusCode = (int)HttpStatusCode.NotFound;
                                    response.StatusDescription = "Unknown sink";
                                    responseString = JSONError(DisplayCastGlobals.CONTROL_JSON_UNKNOWN_ERROR);
                                } else {
                                    JSONstatus status = new JSONstatus();
                                    status.result = sendCommand(service, "MOVE " + sessId + " " + words[3] + "x" + words[5] + "x" + words[7] + "x" + words[9] + "\n");

                                    responseString = serializer.Serialize(status);
                                }
                            }
                        } else {
                            response.StatusDescription = DisplayCastGlobals.CONTROL_USAGE_MOVE;
                            response.StatusCode = (int)HttpStatusCode.BadRequest;
                            responseString = JSONError(DisplayCastGlobals.CONTROL_JSON_SYNTAX_ERROR);
                        }
                    }
                    break;

                case "ICONIFY":
                    if ((request.Url.Query == null) || (request.Url.Query.Length < 2)) {
                        response.StatusCode = (int)HttpStatusCode.BadRequest;
                        response.StatusDescription = DisplayCastGlobals.CONTROL_USAGE_ICON;
                        responseString = JSONError(DisplayCastGlobals.CONTROL_JSON_SYNTAX_ERROR);
                    } else {
                        String sessId = request.Url.Query.Substring(1);
                        NetService service = null;
                        String sinkId = null;
                        JSONSession session = null;

                        foreach (JSONSession sess in sessions)
                            if (sessId.Equals(sess.id)) {
                                sinkId = sess.id;
                                session = sess;
                                break;
                            }

                        if (sinkId == null) {
                            response.StatusCode = (int)HttpStatusCode.NotFound;
                            response.StatusDescription = "Unknown session: " + sessId;
                            responseString = JSONError(DisplayCastGlobals.CONTROL_JSON_UNKNOWN_ERROR);
                        } else {
                            foreach (NetService s in sinkServices)
                                if (s.Name.Equals(sinkId)) {
                                    service = s;
                                    break;
                                }

                            if (service == null) {
                                response.StatusCode = (int)HttpStatusCode.NotFound;
                                response.StatusDescription = "Unknown sink";
                                responseString = JSONError(DisplayCastGlobals.CONTROL_JSON_UNKNOWN_ERROR);
                            } else {
                                JSONstatus status = new JSONstatus();
                                status.result = sendCommand(service, ((session.iconified == 0) ? "ICON " : "DICO ") + sessId + "\n");
                                responseString = serializer.Serialize(status);
                            }

                        }
                    }
                    break;

                case "FULLSCREEN":
                    if ((request.Url.Query == null) || (request.Url.Query.Length < 2)) {
                        response.StatusCode = (int)HttpStatusCode.BadRequest;
                        response.StatusDescription = DisplayCastGlobals.CONTROL_USAGE_FULLSCREEN;
                        responseString = JSONError(DisplayCastGlobals.CONTROL_JSON_SYNTAX_ERROR);
                    } else {
                        String sessId = request.Url.Query.Substring(1);
                        NetService service = null;
                        String sinkId = null;
                        JSONSession session = null;

                        foreach (JSONSession sess in sessions)
                            if (sessId.Equals(sess.id)) {
                                sinkId = sess.id;
                                session = sess;
                                break;
                            }

                        if (sinkId == null) {
                            response.StatusCode = (int)HttpStatusCode.NotFound;
                            response.StatusDescription = "Unknown id: " + sinkId;
                            responseString = JSONError(DisplayCastGlobals.CONTROL_JSON_UNKNOWN_ERROR);
                        } else {
                            foreach (NetService s in sinkServices)
                                if (s.Name.Equals(sinkId)) {
                                    service = s;
                                    break;
                                }

                            if (service == null) {
                                response.StatusCode = (int)HttpStatusCode.NotFound;
                                response.StatusDescription = "Unknown sink";
                                responseString = JSONError(DisplayCastGlobals.CONTROL_JSON_UNKNOWN_ERROR);
                            } else {
                                JSONstatus status = new JSONstatus();
                                status.result = sendCommand(service, ((session.fullScreen == 0) ? "FS " : "SF ") + sessId + "\n");
                                responseString = serializer.Serialize(status);
                            }
                        }
                    }
                    break;

                case "MASK":
                case "CREATEREGION":
                    if ((request.Url.Query == null) || (request.Url.Query.Length < 2)) {
                        response.StatusCode = (int)HttpStatusCode.BadRequest;
                        response.StatusDescription = DisplayCastGlobals.CONTROL_USAGE_MASK;
                        responseString = JSONError(DisplayCastGlobals.CONTROL_JSON_SYNTAX_ERROR);
                    } else {
                        String q = request.Url.Query.Substring(1);
                        char[] delimiters = { '=', '&' };
                        String[] words = q.Split(delimiters);

                        if (((words.Length == 10) || (words.Length == 12)) && words[0].ToUpper().Equals("SOURCE") && words[2].ToUpper().Equals("X") && words[4].ToUpper().Equals("Y") && words[6].ToUpper().Equals("WIDTH") && words[8].ToUpper().Equals("HEIGHT")) {
                            NetService service = null;
                            String srcId = words[1];

                            foreach (NetService s in sourceServices)
                                if (srcId.Equals(s.Name)) {
                                    service = s;
                                    break;
                                }

                            if (service == null) {
                                response.StatusCode = (int)HttpStatusCode.NotFound;
                                response.StatusDescription = "Unknown source: " + srcId;
                                responseString = JSONError(DisplayCastGlobals.CONTROL_JSON_UNKNOWN_ERROR);
                            } else {
                                Int32 port = -1;

                                if (service.TXTRecordData != null) {
                                    byte[] txt = service.TXTRecordData;
                                    IDictionary dict = NetService.DictionaryFromTXTRecordData(txt);

                                    if (dict != null) {
                                        foreach (DictionaryEntry kvp in dict) {
                                            String key = (String)kvp.Key;

                                            key = key.ToUpper();
                                            if (key.Equals("MASKPORT")) {
                                                byte[] value = (byte[])kvp.Value;

                                                try {
                                                    port = Convert.ToInt32(Encoding.UTF8.GetString(value));
                                                } catch {
                                                }
                                                break;
                                            }
                                        }
                                    }
                                }

                                if (port > 0) {
                                    JSONstatus status = new JSONstatus();
                                    status.result = sendCommand(service, port, "MASK " + words[3] + " " + words[5] + " " + words[7] + " " + words[9] + "\n");

                                    responseString = serializer.Serialize(status);
                                } else {
                                    response.StatusDescription = "Streamer does not support masking";
                                    response.StatusCode = (int)HttpStatusCode.NotImplemented;
                                    responseString = JSONError(DisplayCastGlobals.CONTROL_JSON_UNIMPL_ERROR);
                                }
                            }
                        } else {
                            response.StatusDescription = DisplayCastGlobals.CONTROL_USAGE_MASK;
                            response.StatusCode = (int)HttpStatusCode.BadRequest;
                            responseString = JSONError(DisplayCastGlobals.CONTROL_JSON_SYNTAX_ERROR);
                        }
                    }
                    break;

                default:
                    response.StatusCode = (int)HttpStatusCode.BadRequest;
                    response.StatusDescription = "Unknown command: " + request.RawUrl;
                    responseString = JSONError(DisplayCastGlobals.CONTROL_JSON_UNKNOWN_ERROR + request.RawUrl + " " + cmd);
                    break;
            }

            // Now wrap in JSONP response
            if (response.StatusCode == (int)HttpStatusCode.OK) {
                var sb = new System.Text.StringBuilder();
                var queryString = System.Web.HttpUtility.ParseQueryString(request.Url.Query);
                var callback = queryString["callback"] ?? "callback";
                sb.Append(callback + "(" + responseString + ");");
                responseString = sb.ToString();
            }

            // Send the response back
            byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
            response.ContentLength64 = buffer.Length;
            response.Headers.Set(HttpResponseHeader.Server, "FXPAL DisplayCast/" + DisplayCastGlobals.DISPLAYCAST_VERSION + " and not");
            response.OutputStream.Write(buffer, 0, buffer.Length);
            response.Close();
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Utility function to wrap the error message into a JSON message.
        /// </summary>
        /// <param name="err"></param>
        /// <returns></returns>
        private String JSONError(String err)
        {
            JSONstatus status = new JSONstatus();
            status.result = err;

            return this.serializer.Serialize(status);
        }