aboutsummaryrefslogtreecommitdiff
path: root/Emby.Dlna/Service/BaseControlHandler.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Dlna/Service/BaseControlHandler.cs')
-rw-r--r--Emby.Dlna/Service/BaseControlHandler.cs196
1 files changed, 91 insertions, 105 deletions
diff --git a/Emby.Dlna/Service/BaseControlHandler.cs b/Emby.Dlna/Service/BaseControlHandler.cs
index 5f78674b8..581e4a286 100644
--- a/Emby.Dlna/Service/BaseControlHandler.cs
+++ b/Emby.Dlna/Service/BaseControlHandler.cs
@@ -1,81 +1,70 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.IO;
-using System.Linq;
using System.Text;
+using System.Threading.Tasks;
using System.Xml;
+using Diacritics.Extensions;
using Emby.Dlna.Didl;
using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Extensions;
-using MediaBrowser.Model.Xml;
using Microsoft.Extensions.Logging;
namespace Emby.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 readonly IXmlReaderSettingsFactory XmlReaderSettingsFactory;
+ private const string NsSoapEnv = "http://schemas.xmlsoap.org/soap/envelope/";
- protected BaseControlHandler(IServerConfigurationManager config, ILogger logger, IXmlReaderSettingsFactory xmlReaderSettingsFactory)
+ protected BaseControlHandler(IServerConfigurationManager config, ILogger logger)
{
Config = config;
- _logger = logger;
- XmlReaderSettingsFactory = xmlReaderSettingsFactory;
+ Logger = logger;
}
- public ControlResponse ProcessControlRequest(ControlRequest request)
+ protected IServerConfigurationManager Config { get; }
+
+ protected ILogger Logger { get; }
+
+ public async Task<ControlResponse> ProcessControlRequestAsync(ControlRequest request)
{
try
{
- var enableDebugLogging = Config.GetDlnaConfiguration().EnableDebugLog;
-
- if (enableDebugLogging)
- {
- LogRequest(request);
- }
-
- var response = ProcessControlRequestInternal(request);
-
- if (enableDebugLogging)
- {
- LogResponse(response);
- }
+ LogRequest(request);
+ var response = await ProcessControlRequestInternalAsync(request).ConfigureAwait(false);
+ LogResponse(response);
return response;
}
catch (Exception ex)
{
- _logger.LogError(ex, "Error processing control request");
+ Logger.LogError(ex, "Error processing control request");
- return new ControlErrorHandler().GetResponse(ex);
+ return ControlErrorHandler.GetResponse(ex);
}
}
- private ControlResponse ProcessControlRequestInternal(ControlRequest request)
+ private async Task<ControlResponse> ProcessControlRequestInternalAsync(ControlRequest request)
{
- ControlRequestInfo requestInfo = null;
+ ControlRequestInfo? requestInfo = null;
- using (var streamReader = new StreamReader(request.InputXml))
+ using (var streamReader = new StreamReader(request.InputXml, Encoding.UTF8))
{
- var readerSettings = XmlReaderSettingsFactory.Create(false);
-
- readerSettings.CheckCharacters = false;
- readerSettings.IgnoreProcessingInstructions = true;
- readerSettings.IgnoreComments = true;
-
- using (var reader = XmlReader.Create(streamReader, readerSettings))
+ var readerSettings = new XmlReaderSettings()
{
- requestInfo = ParseRequest(reader);
- }
+ ValidationType = ValidationType.None,
+ CheckCharacters = false,
+ IgnoreProcessingInstructions = true,
+ IgnoreComments = true,
+ Async = true
+ };
+
+ using var reader = XmlReader.Create(streamReader, readerSettings);
+ requestInfo = await ParseRequestAsync(reader).ConfigureAwait(false);
}
- _logger.LogDebug("Received control request {0}", requestInfo.LocalName);
-
- var result = GetResult(requestInfo.LocalName, requestInfo.Headers);
+ Logger.LogDebug("Received control request {0}", requestInfo.LocalName);
var settings = new XmlWriterSettings
{
@@ -89,17 +78,14 @@ namespace Emby.Dlna.Service
{
writer.WriteStartDocument(true);
- writer.WriteStartElement("SOAP-ENV", "Envelope", NS_SOAPENV);
- writer.WriteAttributeString(string.Empty, "encodingStyle", NS_SOAPENV, "http://schemas.xmlsoap.org/soap/encoding/");
+ writer.WriteStartElement("SOAP-ENV", "Envelope", NsSoapEnv);
+ writer.WriteAttributeString(string.Empty, "encodingStyle", NsSoapEnv, "http://schemas.xmlsoap.org/soap/encoding/");
- writer.WriteStartElement("SOAP-ENV", "Body", NS_SOAPENV);
+ writer.WriteStartElement("SOAP-ENV", "Body", NsSoapEnv);
writer.WriteStartElement("u", requestInfo.LocalName + "Response", requestInfo.NamespaceURI);
- foreach (var i in result)
- {
- writer.WriteStartElement(i.Key);
- writer.WriteString(i.Value);
- writer.WriteFullEndElement();
- }
+
+ WriteResult(requestInfo.LocalName, requestInfo.Headers, writer);
+
writer.WriteFullEndElement();
writer.WriteFullEndElement();
@@ -107,25 +93,19 @@ namespace Emby.Dlna.Service
writer.WriteEndDocument();
}
- var xml = builder.ToString().Replace("xmlns:m=", "xmlns:u=");
-
- var controlResponse = new ControlResponse
- {
- Xml = xml,
- IsSuccessful = true
- };
+ var xml = builder.ToString().Replace("xmlns:m=", "xmlns:u=", StringComparison.Ordinal);
- //logger.LogDebug(xml);
+ var controlResponse = new ControlResponse(xml, true);
controlResponse.Headers.Add("EXT", string.Empty);
return controlResponse;
}
- private ControlRequestInfo ParseRequest(XmlReader reader)
+ private async Task<ControlRequestInfo> ParseRequestAsync(XmlReader reader)
{
- reader.MoveToContent();
- reader.Read();
+ await reader.MoveToContentAsync().ConfigureAwait(false);
+ await reader.ReadAsync().ConfigureAwait(false);
// Loop through each element
while (!reader.EOF && reader.ReadState == ReadState.Interactive)
@@ -138,74 +118,78 @@ namespace Emby.Dlna.Service
{
if (!reader.IsEmptyElement)
{
- using (var subReader = reader.ReadSubtree())
- {
- return ParseBodyTag(subReader);
- }
+ using var subReader = reader.ReadSubtree();
+ return await ParseBodyTagAsync(subReader).ConfigureAwait(false);
}
else
{
- reader.Read();
+ await reader.ReadAsync().ConfigureAwait(false);
}
+
break;
}
+
default:
{
- reader.Skip();
+ await reader.SkipAsync().ConfigureAwait(false);
break;
}
}
}
else
{
- reader.Read();
+ await reader.ReadAsync().ConfigureAwait(false);
}
}
- return new ControlRequestInfo();
+ throw new EndOfStreamException("Stream ended but no body tag found.");
}
- private ControlRequestInfo ParseBodyTag(XmlReader reader)
+ private async Task<ControlRequestInfo> ParseBodyTagAsync(XmlReader reader)
{
- var result = new ControlRequestInfo();
+ string? namespaceURI = null, localName = null;
- reader.MoveToContent();
- reader.Read();
+ await reader.MoveToContentAsync().ConfigureAwait(false);
+ await reader.ReadAsync().ConfigureAwait(false);
// Loop through each element
while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{
if (reader.NodeType == XmlNodeType.Element)
{
- result.LocalName = reader.LocalName;
- result.NamespaceURI = reader.NamespaceURI;
+ localName = reader.LocalName;
+ namespaceURI = reader.NamespaceURI;
if (!reader.IsEmptyElement)
{
- using (var subReader = reader.ReadSubtree())
- {
- ParseFirstBodyChild(subReader, result.Headers);
- return result;
- }
+ var result = new ControlRequestInfo(localName, namespaceURI);
+ using var subReader = reader.ReadSubtree();
+ await ParseFirstBodyChildAsync(subReader, result.Headers).ConfigureAwait(false);
+ return result;
}
else
{
- reader.Read();
+ await reader.ReadAsync().ConfigureAwait(false);
}
}
else
{
- reader.Read();
+ await reader.ReadAsync().ConfigureAwait(false);
}
}
- return result;
+ if (localName != null && namespaceURI != null)
+ {
+ return new ControlRequestInfo(localName, namespaceURI);
+ }
+
+ throw new EndOfStreamException("Stream ended but no control found.");
}
- private void ParseFirstBodyChild(XmlReader reader, IDictionary<string, string> headers)
+ private async Task ParseFirstBodyChildAsync(XmlReader reader, IDictionary<string, string> headers)
{
- reader.MoveToContent();
- reader.Read();
+ await reader.MoveToContentAsync().ConfigureAwait(false);
+ await reader.ReadAsync().ConfigureAwait(false);
// Loop through each element
while (!reader.EOF && reader.ReadState == ReadState.Interactive)
@@ -213,23 +197,16 @@ namespace Emby.Dlna.Service
if (reader.NodeType == XmlNodeType.Element)
{
// TODO: Should we be doing this here, or should it be handled earlier when decoding the request?
- headers[reader.LocalName.RemoveDiacritics()] = reader.ReadElementContentAsString();
+ headers[reader.LocalName.RemoveDiacritics()] = await reader.ReadElementContentAsStringAsync().ConfigureAwait(false);
}
else
{
- reader.Read();
+ await reader.ReadAsync().ConfigureAwait(false);
}
}
}
- private class ControlRequestInfo
- {
- public string LocalName;
- public string NamespaceURI;
- public IDictionary<string, string> Headers = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
- }
-
- protected abstract IEnumerable<KeyValuePair<string, string>> GetResult(string methodName, IDictionary<string, string> methodParams);
+ protected abstract void WriteResult(string methodName, IReadOnlyDictionary<string, string> methodParams, XmlWriter xmlWriter);
private void LogRequest(ControlRequest request)
{
@@ -238,10 +215,7 @@ namespace Emby.Dlna.Service
return;
}
- var originalHeaders = request.Headers;
- var headers = string.Join(", ", originalHeaders.Select(i => string.Format("{0}={1}", i.Key, i.Value)).ToArray());
-
- _logger.LogDebug("Control request. Headers: {0}", headers);
+ Logger.LogDebug("Control request. Headers: {@Headers}", request.Headers);
}
private void LogResponse(ControlResponse response)
@@ -251,11 +225,23 @@ namespace Emby.Dlna.Service
return;
}
- var originalHeaders = response.Headers;
- var headers = string.Join(", ", originalHeaders.Select(i => string.Format("{0}={1}", i.Key, i.Value)).ToArray());
- //builder.Append(response.Xml);
+ Logger.LogDebug("Control response. Headers: {@Headers}\n{Xml}", response.Headers, response.Xml);
+ }
+
+ private class ControlRequestInfo
+ {
+ public ControlRequestInfo(string localName, string namespaceUri)
+ {
+ LocalName = localName;
+ NamespaceURI = namespaceUri;
+ Headers = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+ }
+
+ public string LocalName { get; set; }
+
+ public string NamespaceURI { get; set; }
- _logger.LogDebug("Control response. Headers: {0}", headers);
+ public Dictionary<string, string> Headers { get; }
}
}
}