diff options
| author | Luke Pulverenti <luke.pulverenti@gmail.com> | 2014-05-20 20:56:24 -0400 |
|---|---|---|
| committer | Luke Pulverenti <luke.pulverenti@gmail.com> | 2014-05-20 20:56:24 -0400 |
| commit | 1774e5b1ac9f809fd97c1d95666fc563afa87914 (patch) | |
| tree | f0c2c3f84de84def4f9e80d1f187069e4763f496 /MediaBrowser.Dlna/Service | |
| parent | ad3c30c14535780fcbd11b049603991e8d3cfe9e (diff) | |
added upnp ConnectionManager.cs
Diffstat (limited to 'MediaBrowser.Dlna/Service')
| -rw-r--r-- | MediaBrowser.Dlna/Service/BaseControlHandler.cs | 112 | ||||
| -rw-r--r-- | MediaBrowser.Dlna/Service/ControlErrorHandler.cs | 41 | ||||
| -rw-r--r-- | MediaBrowser.Dlna/Service/ServiceXmlBuilder.cs | 90 |
3 files changed, 243 insertions, 0 deletions
diff --git a/MediaBrowser.Dlna/Service/BaseControlHandler.cs b/MediaBrowser.Dlna/Service/BaseControlHandler.cs new file mode 100644 index 0000000000..2185d51a58 --- /dev/null +++ b/MediaBrowser.Dlna/Service/BaseControlHandler.cs @@ -0,0 +1,112 @@ +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Dlna; +using MediaBrowser.Dlna.Server; +using MediaBrowser.Model.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml; + +namespace MediaBrowser.Dlna.Service +{ + public abstract class BaseControlHandler + { + private const string NS_SOAPENV = "http://schemas.xmlsoap.org/soap/envelope/"; + + protected readonly IServerConfigurationManager Config; + protected readonly ILogger Logger; + + protected BaseControlHandler(IServerConfigurationManager config, ILogger logger) + { + Config = config; + Logger = logger; + } + + public ControlResponse ProcessControlRequest(ControlRequest request) + { + try + { + if (Config.Configuration.DlnaOptions.EnableDebugLogging) + { + LogRequest(request); + } + + return ProcessControlRequestInternal(request); + } + catch (Exception ex) + { + Logger.ErrorException("Error processing control request", ex); + + return new ControlErrorHandler().GetResponse(ex); + } + } + + private ControlResponse ProcessControlRequestInternal(ControlRequest request) + { + var soap = new XmlDocument(); + soap.LoadXml(request.InputXml); + var sparams = new Headers(); + var body = soap.GetElementsByTagName("Body", NS_SOAPENV).Item(0); + + var method = body.FirstChild; + + foreach (var p in method.ChildNodes) + { + var e = p as XmlElement; + if (e == null) + { + continue; + } + sparams.Add(e.LocalName, e.InnerText.Trim()); + } + + Logger.Debug("Received control request {0}", method.LocalName); + + IEnumerable<KeyValuePair<string, string>> result = GetResult(method.LocalName, sparams); + + var env = new XmlDocument(); + env.AppendChild(env.CreateXmlDeclaration("1.0", "utf-8", string.Empty)); + var envelope = env.CreateElement("SOAP-ENV", "Envelope", NS_SOAPENV); + env.AppendChild(envelope); + envelope.SetAttribute("encodingStyle", NS_SOAPENV, "http://schemas.xmlsoap.org/soap/encoding/"); + + var rbody = env.CreateElement("SOAP-ENV:Body", NS_SOAPENV); + env.DocumentElement.AppendChild(rbody); + + var response = env.CreateElement(String.Format("u:{0}Response", method.LocalName), method.NamespaceURI); + rbody.AppendChild(response); + + foreach (var i in result) + { + var ri = env.CreateElement(i.Key); + ri.InnerText = i.Value; + response.AppendChild(ri); + } + + var controlResponse = new ControlResponse + { + Xml = env.OuterXml, + IsSuccessful = true + }; + + controlResponse.Headers.Add("EXT", string.Empty); + + return controlResponse; + } + + protected abstract IEnumerable<KeyValuePair<string, string>> GetResult(string methodName, Headers methodParams); + + private void LogRequest(ControlRequest request) + { + var builder = new StringBuilder(); + + var headers = string.Join(", ", request.Headers.Select(i => string.Format("{0}={1}", i.Key, i.Value)).ToArray()); + builder.AppendFormat("Headers: {0}", headers); + builder.AppendLine(); + builder.Append(request.InputXml); + + Logger.LogMultiline("Control request", LogSeverity.Debug, builder); + } + } +} diff --git a/MediaBrowser.Dlna/Service/ControlErrorHandler.cs b/MediaBrowser.Dlna/Service/ControlErrorHandler.cs new file mode 100644 index 0000000000..42b1fcbc99 --- /dev/null +++ b/MediaBrowser.Dlna/Service/ControlErrorHandler.cs @@ -0,0 +1,41 @@ +using MediaBrowser.Controller.Dlna; +using System; +using System.Xml; + +namespace MediaBrowser.Dlna.Service +{ + public class ControlErrorHandler + { + private const string NS_SOAPENV = "http://schemas.xmlsoap.org/soap/envelope/"; + + public ControlResponse GetResponse(Exception ex) + { + var env = new XmlDocument(); + env.AppendChild(env.CreateXmlDeclaration("1.0", "utf-8", "yes")); + var envelope = env.CreateElement("SOAP-ENV", "Envelope", NS_SOAPENV); + env.AppendChild(envelope); + envelope.SetAttribute("encodingStyle", NS_SOAPENV, "http://schemas.xmlsoap.org/soap/encoding/"); + + var rbody = env.CreateElement("SOAP-ENV:Body", NS_SOAPENV); + env.DocumentElement.AppendChild(rbody); + + var fault = env.CreateElement("SOAP-ENV", "Fault", NS_SOAPENV); + var faultCode = env.CreateElement("faultcode"); + faultCode.InnerText = "500"; + fault.AppendChild(faultCode); + var faultString = env.CreateElement("faultstring"); + faultString.InnerText = ex.ToString(); + fault.AppendChild(faultString); + var detail = env.CreateDocumentFragment(); + detail.InnerXml = "<detail><UPnPError xmlns=\"urn:schemas-upnp-org:control-1-0\"><errorCode>401</errorCode><errorDescription>Invalid Action</errorDescription></UPnPError></detail>"; + fault.AppendChild(detail); + rbody.AppendChild(fault); + + return new ControlResponse + { + Xml = env.OuterXml, + IsSuccessful = false + }; + } + } +} diff --git a/MediaBrowser.Dlna/Service/ServiceXmlBuilder.cs b/MediaBrowser.Dlna/Service/ServiceXmlBuilder.cs new file mode 100644 index 0000000000..fae604f85c --- /dev/null +++ b/MediaBrowser.Dlna/Service/ServiceXmlBuilder.cs @@ -0,0 +1,90 @@ +using MediaBrowser.Dlna.Common; +using System.Collections.Generic; +using System.Security; +using System.Text; + +namespace MediaBrowser.Dlna.Service +{ + public class ServiceXmlBuilder + { + public string GetXml(IEnumerable<ServiceAction> actions, IEnumerable<StateVariable> stateVariables) + { + var builder = new StringBuilder(); + + builder.Append("<?xml version=\"1.0\"?>"); + builder.Append("<scpd xmlns=\"urn:schemas-upnp-org:service-1-0\">"); + + builder.Append("<specVersion>"); + builder.Append("<major>1</major>"); + builder.Append("<minor>0</minor>"); + builder.Append("</specVersion>"); + + AppendActionList(builder, actions); + AppendServiceStateTable(builder, stateVariables); + + builder.Append("</scpd>"); + + return builder.ToString(); + } + + private void AppendActionList(StringBuilder builder, IEnumerable<ServiceAction> actions) + { + builder.Append("<actionList>"); + + foreach (var item in actions) + { + builder.Append("<action>"); + + builder.Append("<name>" + SecurityElement.Escape(item.Name ?? string.Empty) + "</name>"); + + builder.Append("<argumentList>"); + + foreach (var argument in item.ArgumentList) + { + builder.Append("<argument>"); + + builder.Append("<name>" + SecurityElement.Escape(argument.Name ?? string.Empty) + "</name>"); + builder.Append("<direction>" + SecurityElement.Escape(argument.Direction ?? string.Empty) + "</direction>"); + builder.Append("<relatedStateVariable>" + SecurityElement.Escape(argument.RelatedStateVariable ?? string.Empty) + "</relatedStateVariable>"); + + builder.Append("</argument>"); + } + + builder.Append("</argumentList>"); + + builder.Append("</action>"); + } + + builder.Append("</actionList>"); + } + + private void AppendServiceStateTable(StringBuilder builder, IEnumerable<StateVariable> stateVariables) + { + builder.Append("<serviceStateTable>"); + + foreach (var item in stateVariables) + { + var sendEvents = item.SendsEvents ? "yes" : "no"; + + builder.Append("<stateVariable sendEvents=\"" + sendEvents + "\">"); + + builder.Append("<name>" + SecurityElement.Escape(item.Name ?? string.Empty) + "</name>"); + builder.Append("<dataType>" + SecurityElement.Escape(item.DataType ?? string.Empty) + "</dataType>"); + + if (item.AllowedValues.Count > 0) + { + builder.Append("<allowedValueList>"); + foreach (var allowedValue in item.AllowedValues) + { + builder.Append("<allowedValue>" + SecurityElement.Escape(allowedValue) + "</allowedValue>"); + } + builder.Append("</allowedValueList>"); + } + + builder.Append("</stateVariable>"); + } + + builder.Append("</serviceStateTable>"); + } + } +} |
