|
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|
|
using System.IO;
|
|
|
using System.Linq;
|
|
|
using System.Text;
|
|
|
+using System.Threading.Tasks;
|
|
|
using System.Xml;
|
|
|
using Emby.Dlna.Didl;
|
|
|
using MediaBrowser.Controller.Configuration;
|
|
@@ -15,44 +16,34 @@ namespace Emby.Dlna.Service
|
|
|
{
|
|
|
private const string NS_SOAPENV = "http://schemas.xmlsoap.org/soap/envelope/";
|
|
|
|
|
|
- protected readonly IServerConfigurationManager Config;
|
|
|
- protected readonly ILogger _logger;
|
|
|
+ protected IServerConfigurationManager Config { get; }
|
|
|
+ protected ILogger Logger { get; }
|
|
|
|
|
|
protected BaseControlHandler(IServerConfigurationManager config, ILogger logger)
|
|
|
{
|
|
|
Config = config;
|
|
|
- _logger = logger;
|
|
|
+ Logger = logger;
|
|
|
}
|
|
|
|
|
|
- public ControlResponse ProcessControlRequest(ControlRequest request)
|
|
|
+ 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;
|
|
|
|
|
@@ -63,16 +54,17 @@ namespace Emby.Dlna.Service
|
|
|
ValidationType = ValidationType.None,
|
|
|
CheckCharacters = false,
|
|
|
IgnoreProcessingInstructions = true,
|
|
|
- IgnoreComments = true
|
|
|
+ IgnoreComments = true,
|
|
|
+ Async = true
|
|
|
};
|
|
|
|
|
|
using (var reader = XmlReader.Create(streamReader, readerSettings))
|
|
|
{
|
|
|
- requestInfo = ParseRequest(reader);
|
|
|
+ requestInfo = await ParseRequestAsync(reader).ConfigureAwait(false);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- _logger.LogDebug("Received control request {0}", requestInfo.LocalName);
|
|
|
+ Logger.LogDebug("Received control request {0}", requestInfo.LocalName);
|
|
|
|
|
|
var result = GetResult(requestInfo.LocalName, requestInfo.Headers);
|
|
|
|
|
@@ -114,17 +106,15 @@ namespace Emby.Dlna.Service
|
|
|
IsSuccessful = true
|
|
|
};
|
|
|
|
|
|
- //logger.LogDebug(xml);
|
|
|
-
|
|
|
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)
|
|
@@ -139,37 +129,38 @@ namespace Emby.Dlna.Service
|
|
|
{
|
|
|
using (var subReader = reader.ReadSubtree())
|
|
|
{
|
|
|
- return ParseBodyTag(subReader);
|
|
|
+ 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();
|
|
|
}
|
|
|
|
|
|
- private ControlRequestInfo ParseBodyTag(XmlReader reader)
|
|
|
+ private async Task<ControlRequestInfo> ParseBodyTagAsync(XmlReader reader)
|
|
|
{
|
|
|
var result = new ControlRequestInfo();
|
|
|
|
|
|
- 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)
|
|
@@ -183,28 +174,28 @@ namespace Emby.Dlna.Service
|
|
|
{
|
|
|
using (var subReader = reader.ReadSubtree())
|
|
|
{
|
|
|
- ParseFirstBodyChild(subReader, result.Headers);
|
|
|
+ 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;
|
|
|
}
|
|
|
|
|
|
- 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)
|
|
@@ -212,20 +203,20 @@ 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);
|
|
|
+ public string LocalName { get; set; }
|
|
|
+ public string NamespaceURI { get; set; }
|
|
|
+ public Dictionary<string, string> Headers { get; } = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
|
|
}
|
|
|
|
|
|
protected abstract IEnumerable<KeyValuePair<string, string>> GetResult(string methodName, IDictionary<string, string> methodParams);
|
|
@@ -237,10 +228,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)
|
|
@@ -250,11 +238,7 @@ 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: {0}", headers);
|
|
|
+ Logger.LogDebug("Control response. Headers: {@Headers}\n{Xml}", response.Headers, response.Xml);
|
|
|
}
|
|
|
}
|
|
|
}
|