aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Dlna/Service
diff options
context:
space:
mode:
authorLuke Pulverenti <luke.pulverenti@gmail.com>2014-05-20 20:56:24 -0400
committerLuke Pulverenti <luke.pulverenti@gmail.com>2014-05-20 20:56:24 -0400
commit1774e5b1ac9f809fd97c1d95666fc563afa87914 (patch)
treef0c2c3f84de84def4f9e80d1f187069e4763f496 /MediaBrowser.Dlna/Service
parentad3c30c14535780fcbd11b049603991e8d3cfe9e (diff)
added upnp ConnectionManager.cs
Diffstat (limited to 'MediaBrowser.Dlna/Service')
-rw-r--r--MediaBrowser.Dlna/Service/BaseControlHandler.cs112
-rw-r--r--MediaBrowser.Dlna/Service/ControlErrorHandler.cs41
-rw-r--r--MediaBrowser.Dlna/Service/ServiceXmlBuilder.cs90
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>");
+ }
+ }
+}