Esempio n. 1
0
        internal void OnActionCalled(CpAction action, IList <object> inParams, object clientState)
        {
            if (!action.IsConnected)
            {
                throw new UPnPDisconnectedException("Action '{0}' is not connected to a UPnP network action", action.FullQualifiedName);
            }
            CpService         service = action.ParentService;
            ServiceDescriptor sd      = GetServiceDescriptor(service);
            string            message = SOAPHandler.EncodeCall(action, inParams, _rootDescriptor.SSDPRootEntry.UPnPVersion);

            HttpWebRequest  request = CreateActionCallRequest(sd, action);
            ActionCallState state   = new ActionCallState(action, clientState, request);

            state.SetRequestMessage(message);
            lock (_cpData.SyncObj)
                _pendingCalls.Add(state);
            IAsyncResult result = state.Request.BeginGetResponse(OnCallResponseReceived, state);

            NetworkHelper.AddTimeout(request, result, PENDING_ACTION_CALL_TIMEOUT * 1000);
        }
Esempio n. 2
0
        private void OnCallResponseReceived(IAsyncResult ar)
        {
            ActionCallState state = (ActionCallState)ar.AsyncState;

            lock (_cpData.SyncObj)
                _pendingCalls.Remove(state);
            HttpWebResponse response = null;
            Stream          body     = null;

            try
            {
                Encoding contentEncoding;
                try
                {
                    response = (HttpWebResponse)state.Request.EndGetResponse(ar);
                    body     = CompressionHelper.Decompress(response);
                    string mediaType;
                    if (!EncodingUtils.TryParseContentTypeEncoding(response.ContentType, Encoding.UTF8, out mediaType, out contentEncoding) ||
                        mediaType != "text/xml")
                    {
                        SOAPHandler.ActionFailed(state.Action, state.ClientState, "Invalid content type");
                        return;
                    }
                }
                catch (WebException e)
                {
                    response = (HttpWebResponse)e.Response;
                    if (response == null)
                    {
                        SOAPHandler.ActionFailed(state.Action, state.ClientState, string.Format("Network error when invoking action '{0}': {1}", state.Action.Name, e.Message));
                    }
                    else if (response.StatusCode == HttpStatusCode.InternalServerError)
                    {
                        string mediaType;
                        if (!EncodingUtils.TryParseContentTypeEncoding(response.ContentType, Encoding.UTF8, out mediaType, out contentEncoding) ||
                            mediaType != "text/xml")
                        {
                            SOAPHandler.ActionFailed(state.Action, state.ClientState, "Invalid content type");
                            return;
                        }
                        using (TextReader reader = new StreamReader(response.GetResponseStream(), contentEncoding))
                            SOAPHandler.HandleErrorResult(reader, state.Action, state.ClientState);
                    }
                    else
                    {
                        SOAPHandler.ActionFailed(state.Action, state.ClientState, string.Format("Network error {0} when invoking action '{1}'", response.StatusCode, state.Action.Name));
                    }
                    return;
                }
                UPnPVersion uPnPVersion;
                lock (_cpData.SyncObj)
                    uPnPVersion = _rootDescriptor.SSDPRootEntry.UPnPVersion;
                SOAPHandler.HandleResult(body, contentEncoding, state.Action, state.ClientState, uPnPVersion);
            }
            finally
            {
                if (body != null)
                {
                    body.Dispose();
                }
                if (response != null)
                {
                    response.Close();
                }
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Handles all kinds of HTTP over TCP requests - Description, Control and Event subscriptions.
        /// </summary>
        /// <param name="context">HTTP client context of the current request.</param>
        protected async Task HandleHTTPRequest(IOwinContext context)
        {
            var    request      = context.Request;
            var    response     = context.Response;
            Uri    uri          = request.Uri;
            string hostName     = uri.Host;
            string pathAndQuery = uri.LocalPath; // Unfortunately, Uri.PathAndQuery doesn't decode characters like '{' and '}', so we use the Uri.LocalPath property

            try
            {
                DvService service;
                ICollection <EndpointConfiguration> endpoints;
                lock (_serverData.SyncObj)
                    endpoints = _serverData.UPnPEndPoints;
                foreach (EndpointConfiguration config in endpoints)
                {
                    if (!NetworkHelper.HostNamesEqual(hostName, NetworkHelper.IPAddrToHostName(config.EndPointIPAddress)))
                    {
                        continue;
                    }

                    // Common check for supported encodings
                    string acceptEncoding = request.Headers.Get("ACCEPT-ENCODING") ?? string.Empty;

                    // Handle different HTTP methods here
                    if (request.Method == "GET")
                    { // GET of descriptions
                        if (pathAndQuery.StartsWith(config.DescriptionPathBase))
                        {
                            string      acceptLanguage = request.Headers.Get("ACCEPT-LANGUAGE");
                            CultureInfo culture        = GetFirstCultureOrDefault(acceptLanguage, CultureInfo.InvariantCulture);

                            string   description = null;
                            DvDevice rootDevice;
                            lock (_serverData.SyncObj)
                                if (config.RootDeviceDescriptionPathsToRootDevices.TryGetValue(pathAndQuery, out rootDevice))
                                {
                                    description = rootDevice.BuildRootDeviceDescription(request, _serverData, config, culture);
                                }
                                else if (config.SCPDPathsToServices.TryGetValue(pathAndQuery, out service))
                                {
                                    description = service.BuildSCPDDocument(config, _serverData);
                                }
                            if (description != null)
                            {
                                response.StatusCode  = (int)HttpStatusCode.OK;
                                response.ContentType = "text/xml; charset=utf-8";
                                if (!string.IsNullOrEmpty(acceptLanguage))
                                {
                                    response.Headers["CONTENT-LANGUAGE"] = culture.ToString();
                                }
                                using (MemoryStream responseStream = new MemoryStream(UPnPConsts.UTF8_NO_BOM.GetBytes(description)))
                                    await CompressionHelper.WriteCompressedStream(acceptEncoding, response, responseStream);
                                return;
                            }
                        }
                    }
                    else if (request.Method == "POST")
                    { // POST of control messages
                        if (config.ControlPathsToServices.TryGetValue(pathAndQuery, out service))
                        {
                            string contentType  = request.Headers.Get("CONTENT-TYPE");
                            string userAgentStr = request.Headers.Get("USER-AGENT");
                            int    minorVersion;
                            if (string.IsNullOrEmpty(userAgentStr))
                            {
                                minorVersion = 0;
                            }
                            else if (!ParserHelper.ParseUserAgentUPnP1MinorVersion(userAgentStr, out minorVersion))
                            {
                                response.StatusCode = (int)HttpStatusCode.BadRequest;
                                return;
                            }
                            string   mediaType;
                            Encoding encoding;
                            if (!EncodingUtils.TryParseContentTypeEncoding(contentType, Encoding.UTF8, out mediaType, out encoding))
                            {
                                throw new ArgumentException("Unable to parse content type");
                            }
                            if (mediaType != "text/xml")
                            { // As specified in (DevArch), 3.2.1
                                response.StatusCode = (int)HttpStatusCode.UnsupportedMediaType;
                                return;
                            }
                            response.Headers["DATE"]         = DateTime.Now.ToUniversalTime().ToString("R");
                            response.Headers["SERVER"]       = UPnPConfiguration.UPnPMachineInfoHeader;
                            response.Headers["CONTENT-TYPE"] = "text/xml; charset=\"utf-8\"";
                            string         result;
                            HttpStatusCode status;
                            try
                            {
                                CallContext callContext = new CallContext(request, context, config);
                                status = SOAPHandler.HandleRequest(service, request.Body, encoding, minorVersion >= 1, callContext, out result);
                            }
                            catch (Exception e)
                            {
                                UPnPConfiguration.LOGGER.Warn("Action invocation failed", e);
                                result = SOAPHandler.CreateFaultDocument(501, "Action failed");
                                status = HttpStatusCode.InternalServerError;
                            }
                            response.StatusCode = (int)status;
                            using (MemoryStream responseStream = new MemoryStream(encoding.GetBytes(result)))
                                await CompressionHelper.WriteCompressedStream(acceptEncoding, response, responseStream);
                            return;
                        }
                    }
                    else if (request.Method == "SUBSCRIBE" || request.Method == "UNSUBSCRIBE")
                    {
                        GENAServerController gsc;
                        lock (_serverData.SyncObj)
                            gsc = _serverData.GENAController;
                        if (gsc.HandleHTTPRequest(request, context, config))
                        {
                            return;
                        }
                    }
                    else
                    {
                        context.Response.StatusCode = (int)HttpStatusCode.MethodNotAllowed;
                        //context.Respond(HttpHelper.HTTP11, HttpStatusCode.MethodNotAllowed, null);
                        return;
                    }
                }
                // Url didn't match
                context.Response.StatusCode = (int)HttpStatusCode.NotFound;
                //context.Respond(HttpHelper.HTTP11, HttpStatusCode.NotFound, null);
            }
            catch (Exception e)
            {
                UPnPConfiguration.LOGGER.Error("UPnPServer: Error handling HTTP request '{0}'", e, uri);
                response.StatusCode = (int)HttpStatusCode.InternalServerError;
            }
        }
Esempio n. 4
0
        private void SOAPCallback(IAsyncResult result)
        {
            SOAPHandler handler = (SOAPHandler)result.AsyncState;

            handler.EndInvoke(result);
        }