diff --git a/Emby.Common.Implementations/Net/SocketFactory.cs b/Emby.Common.Implementations/Net/SocketFactory.cs
index c65593242e..1242520971 100644
--- a/Emby.Common.Implementations/Net/SocketFactory.cs
+++ b/Emby.Common.Implementations/Net/SocketFactory.cs
@@ -4,6 +4,7 @@ using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
+using Emby.Common.Implementations.Networking;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net;
@@ -18,11 +19,6 @@ namespace Emby.Common.Implementations.Net
// but that wasn't really the point so kept to YAGNI principal for now, even if the
// interfaces are a bit ugly, specific and make assumptions.
- ///
- /// Used by RSSDP components to create implementations of the interface, to perform platform agnostic socket communications.
- ///
- private IPAddress _LocalIP;
-
private readonly ILogger _logger;
public SocketFactory(ILogger logger)
@@ -33,7 +29,6 @@ namespace Emby.Common.Implementations.Net
}
_logger = logger;
- _LocalIP = IPAddress.Any;
}
public ISocket CreateSocket(IpAddressFamily family, MediaBrowser.Model.Net.SocketType socketType, MediaBrowser.Model.Net.ProtocolType protocolType, bool dualMode)
@@ -66,7 +61,7 @@ namespace Emby.Common.Implementations.Net
try
{
retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
- return new UdpSocket(retVal, localPort, _LocalIP);
+ return new UdpSocket(retVal, localPort, IPAddress.Any);
}
catch
{
@@ -80,9 +75,8 @@ namespace Emby.Common.Implementations.Net
///
/// Creates a new UDP socket that is a member of the SSDP multicast local admin group and binds it to the specified local port.
///
- /// An integer specifying the local port to bind the socket to.
/// An implementation of the interface used by RSSDP components to perform socket operations.
- public IUdpSocket CreateSsdpUdpSocket(int localPort)
+ public IUdpSocket CreateSsdpUdpSocket(IpAddressInfo localIpAddress, int localPort)
{
if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort");
@@ -91,8 +85,11 @@ namespace Emby.Common.Implementations.Net
{
retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 4);
- retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse("239.255.255.250"), _LocalIP));
- return new UdpSocket(retVal, localPort, _LocalIP);
+
+ var localIp = NetworkManager.ToIPAddress(localIpAddress);
+
+ retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse("239.255.255.250"), localIp));
+ return new UdpSocket(retVal, localPort, localIp);
}
catch
{
@@ -134,10 +131,13 @@ namespace Emby.Common.Implementations.Net
//retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);
retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, multicastTimeToLive);
- retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse(ipAddress), _LocalIP));
+
+ var localIp = IPAddress.Any;
+
+ retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse(ipAddress), localIp));
retVal.MulticastLoopback = true;
- return new UdpSocket(retVal, localPort, _LocalIP);
+ return new UdpSocket(retVal, localPort, localIp);
}
catch
{
diff --git a/Emby.Common.Implementations/Net/UdpSocket.cs b/Emby.Common.Implementations/Net/UdpSocket.cs
index 367d2242c6..b2af9d162e 100644
--- a/Emby.Common.Implementations/Net/UdpSocket.cs
+++ b/Emby.Common.Implementations/Net/UdpSocket.cs
@@ -20,7 +20,6 @@ namespace Emby.Common.Implementations.Net
private Socket _Socket;
private int _LocalPort;
-
#endregion
#region Constructors
@@ -31,12 +30,19 @@ namespace Emby.Common.Implementations.Net
_Socket = socket;
_LocalPort = localPort;
+ LocalIPAddress = NetworkManager.ToIpAddressInfo(ip);
_Socket.Bind(new IPEndPoint(ip, _LocalPort));
}
#endregion
+ public IpAddressInfo LocalIPAddress
+ {
+ get;
+ private set;
+ }
+
#region IUdpSocket Members
public Task ReceiveAsync()
@@ -50,18 +56,18 @@ namespace Emby.Common.Implementations.Net
state.TaskCompletionSource = tcs;
#if NETSTANDARD1_6
- _Socket.ReceiveFromAsync(new ArraySegment(state.Buffer),SocketFlags.None, state.EndPoint)
+ _Socket.ReceiveFromAsync(new ArraySegment(state.Buffer),SocketFlags.None, state.RemoteEndPoint)
.ContinueWith((task, asyncState) =>
{
if (task.Status != TaskStatus.Faulted)
{
var receiveState = asyncState as AsyncReceiveState;
- receiveState.EndPoint = task.Result.RemoteEndPoint;
- ProcessResponse(receiveState, () => task.Result.ReceivedBytes);
+ receiveState.RemoteEndPoint = task.Result.RemoteEndPoint;
+ ProcessResponse(receiveState, () => task.Result.ReceivedBytes, LocalIPAddress);
}
}, state);
#else
- _Socket.BeginReceiveFrom(state.Buffer, 0, state.Buffer.Length, SocketFlags.None, ref state.EndPoint, ProcessResponse, state);
+ _Socket.BeginReceiveFrom(state.Buffer, 0, state.Buffer.Length, SocketFlags.None, ref state.RemoteEndPoint, ProcessResponse, state);
#endif
return tcs.Task;
@@ -74,6 +80,8 @@ namespace Emby.Common.Implementations.Net
if (buffer == null) throw new ArgumentNullException("messageData");
if (endPoint == null) throw new ArgumentNullException("endPoint");
+ var ipEndPoint = NetworkManager.ToIPEndPoint(endPoint);
+
#if NETSTANDARD1_6
if (size != buffer.Length)
@@ -83,14 +91,14 @@ namespace Emby.Common.Implementations.Net
buffer = copy;
}
- _Socket.SendTo(buffer, new IPEndPoint(IPAddress.Parse(endPoint.IpAddress.ToString()), endPoint.Port));
+ _Socket.SendTo(buffer, ipEndPoint);
return Task.FromResult(true);
#else
var taskSource = new TaskCompletionSource();
try
{
- _Socket.BeginSendTo(buffer, 0, size, SocketFlags.None, new System.Net.IPEndPoint(IPAddress.Parse(endPoint.IpAddress.ToString()), endPoint.Port), result =>
+ _Socket.BeginSendTo(buffer, 0, size, SocketFlags.None, ipEndPoint, result =>
{
try
{
@@ -109,7 +117,7 @@ namespace Emby.Common.Implementations.Net
taskSource.TrySetException(ex);
}
- //_Socket.SendTo(messageData, new System.Net.IPEndPoint(IPAddress.Parse(endPoint.IPAddress), endPoint.Port));
+ //_Socket.SendTo(messageData, new System.Net.IPEndPoint(IPAddress.Parse(RemoteEndPoint.IPAddress), RemoteEndPoint.Port));
return taskSource.Task;
#endif
@@ -133,19 +141,20 @@ namespace Emby.Common.Implementations.Net
#region Private Methods
- private static void ProcessResponse(AsyncReceiveState state, Func receiveData)
+ private static void ProcessResponse(AsyncReceiveState state, Func receiveData, IpAddressInfo localIpAddress)
{
try
{
var bytesRead = receiveData();
- var ipEndPoint = state.EndPoint as IPEndPoint;
+ var ipEndPoint = state.RemoteEndPoint as IPEndPoint;
state.TaskCompletionSource.SetResult(
- new SocketReceiveResult()
+ new SocketReceiveResult
{
Buffer = state.Buffer,
ReceivedBytes = bytesRead,
- RemoteEndPoint = ToIpEndPointInfo(ipEndPoint)
+ RemoteEndPoint = ToIpEndPointInfo(ipEndPoint),
+ LocalIPAddress = localIpAddress
}
);
}
@@ -182,15 +191,16 @@ namespace Emby.Common.Implementations.Net
var state = asyncResult.AsyncState as AsyncReceiveState;
try
{
- var bytesRead = state.Socket.EndReceiveFrom(asyncResult, ref state.EndPoint);
+ var bytesRead = state.Socket.EndReceiveFrom(asyncResult, ref state.RemoteEndPoint);
- var ipEndPoint = state.EndPoint as IPEndPoint;
+ var ipEndPoint = state.RemoteEndPoint as IPEndPoint;
state.TaskCompletionSource.SetResult(
new SocketReceiveResult
{
Buffer = state.Buffer,
ReceivedBytes = bytesRead,
- RemoteEndPoint = ToIpEndPointInfo(ipEndPoint)
+ RemoteEndPoint = ToIpEndPointInfo(ipEndPoint),
+ LocalIPAddress = LocalIPAddress
}
);
}
@@ -211,13 +221,13 @@ namespace Emby.Common.Implementations.Net
private class AsyncReceiveState
{
- public AsyncReceiveState(Socket socket, EndPoint endPoint)
+ public AsyncReceiveState(Socket socket, EndPoint remoteEndPoint)
{
this.Socket = socket;
- this.EndPoint = endPoint;
+ this.RemoteEndPoint = remoteEndPoint;
}
- public EndPoint EndPoint;
+ public EndPoint RemoteEndPoint;
public byte[] Buffer = new byte[8192];
public Socket Socket { get; private set; }
diff --git a/Emby.Common.Implementations/Networking/NetworkManager.cs b/Emby.Common.Implementations/Networking/NetworkManager.cs
index a4f8f7ced0..b9100f9db3 100644
--- a/Emby.Common.Implementations/Networking/NetworkManager.cs
+++ b/Emby.Common.Implementations/Networking/NetworkManager.cs
@@ -27,7 +27,7 @@ namespace Emby.Common.Implementations.Networking
private List _localIpAddresses;
private readonly object _localIpAddressSyncLock = new object();
- public IEnumerable GetLocalIpAddresses()
+ public List GetLocalIpAddresses()
{
const int cacheMinutes = 5;
diff --git a/Emby.Dlna/ConnectionManager/ControlHandler.cs b/Emby.Dlna/ConnectionManager/ControlHandler.cs
index 0bc44db170..ae983c5e75 100644
--- a/Emby.Dlna/ConnectionManager/ControlHandler.cs
+++ b/Emby.Dlna/ConnectionManager/ControlHandler.cs
@@ -14,7 +14,7 @@ namespace Emby.Dlna.ConnectionManager
{
private readonly DeviceProfile _profile;
- protected override IEnumerable> GetResult(string methodName, Headers methodParams)
+ protected override IEnumerable> GetResult(string methodName, IDictionary methodParams)
{
if (string.Equals(methodName, "GetProtocolInfo", StringComparison.OrdinalIgnoreCase))
{
@@ -26,7 +26,7 @@ namespace Emby.Dlna.ConnectionManager
private IEnumerable> HandleGetProtocolInfo()
{
- return new Headers(true)
+ return new Dictionary(StringComparer.OrdinalIgnoreCase)
{
{ "Source", _profile.ProtocolInfo },
{ "Sink", "" }
diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs
index d77919e47a..98a151f295 100644
--- a/Emby.Dlna/ContentDirectory/ControlHandler.cs
+++ b/Emby.Dlna/ContentDirectory/ControlHandler.cs
@@ -65,7 +65,7 @@ namespace Emby.Dlna.ContentDirectory
_didlBuilder = new DidlBuilder(profile, user, imageProcessor, serverAddress, accessToken, userDataManager, localization, mediaSourceManager, Logger, libraryManager, mediaEncoder);
}
- protected override IEnumerable> GetResult(string methodName, Headers methodParams)
+ protected override IEnumerable> GetResult(string methodName, IDictionary methodParams)
{
var deviceId = "test";
@@ -118,17 +118,20 @@ namespace Emby.Dlna.ContentDirectory
_userDataManager.SaveUserData(user.Id, item, userdata, UserDataSaveReason.TogglePlayed,
CancellationToken.None);
- return new Headers();
+ return new Dictionary(StringComparer.OrdinalIgnoreCase);
}
private IEnumerable> HandleGetSearchCapabilities()
{
- return new Headers(true) { { "SearchCaps", "res@resolution,res@size,res@duration,dc:title,dc:creator,upnp:actor,upnp:artist,upnp:genre,upnp:album,dc:date,upnp:class,@id,@refID,@protocolInfo,upnp:author,dc:description,pv:avKeywords" } };
+ return new Dictionary(StringComparer.OrdinalIgnoreCase)
+ {
+ { "SearchCaps", "res@resolution,res@size,res@duration,dc:title,dc:creator,upnp:actor,upnp:artist,upnp:genre,upnp:album,dc:date,upnp:class,@id,@refID,@protocolInfo,upnp:author,dc:description,pv:avKeywords" }
+ };
}
private IEnumerable> HandleGetSortCapabilities()
{
- return new Headers(true)
+ return new Dictionary(StringComparer.OrdinalIgnoreCase)
{
{ "SortCaps", "res@duration,res@size,res@bitrate,dc:date,dc:title,dc:size,upnp:album,upnp:artist,upnp:albumArtist,upnp:episodeNumber,upnp:genre,upnp:originalTrackNumber,upnp:rating" }
};
@@ -136,7 +139,7 @@ namespace Emby.Dlna.ContentDirectory
private IEnumerable> HandleGetSortExtensionCapabilities()
{
- return new Headers(true)
+ return new Dictionary(StringComparer.OrdinalIgnoreCase)
{
{ "SortExtensionCaps", "res@duration,res@size,res@bitrate,dc:date,dc:title,dc:size,upnp:album,upnp:artist,upnp:albumArtist,upnp:episodeNumber,upnp:genre,upnp:originalTrackNumber,upnp:rating" }
};
@@ -144,14 +147,14 @@ namespace Emby.Dlna.ContentDirectory
private IEnumerable> HandleGetSystemUpdateID()
{
- var headers = new Headers(true);
+ var headers = new Dictionary(StringComparer.OrdinalIgnoreCase);
headers.Add("Id", _systemUpdateId.ToString(_usCulture));
return headers;
}
private IEnumerable> HandleGetFeatureList()
{
- return new Headers(true)
+ return new Dictionary(StringComparer.OrdinalIgnoreCase)
{
{ "FeatureList", GetFeatureListXml() }
};
@@ -159,7 +162,7 @@ namespace Emby.Dlna.ContentDirectory
private IEnumerable> HandleXGetFeatureList()
{
- return new Headers(true)
+ return new Dictionary(StringComparer.OrdinalIgnoreCase)
{
{ "FeatureList", GetFeatureListXml() }
};
@@ -183,12 +186,24 @@ namespace Emby.Dlna.ContentDirectory
return builder.ToString();
}
- private async Task>> HandleBrowse(Headers sparams, User user, string deviceId)
+ public string GetValueOrDefault(IDictionary sparams, string key, string defaultValue)
+ {
+ string val;
+
+ if (sparams.TryGetValue(key, out val))
+ {
+ return val;
+ }
+
+ return defaultValue;
+ }
+
+ private async Task>> HandleBrowse(IDictionary sparams, User user, string deviceId)
{
var id = sparams["ObjectID"];
var flag = sparams["BrowseFlag"];
- var filter = new Filter(sparams.GetValueOrDefault("Filter", "*"));
- var sortCriteria = new SortCriteria(sparams.GetValueOrDefault("SortCriteria", ""));
+ var filter = new Filter(GetValueOrDefault(sparams, "Filter", "*"));
+ var sortCriteria = new SortCriteria(GetValueOrDefault(sparams, "SortCriteria", ""));
var provided = 0;
@@ -294,11 +309,11 @@ namespace Emby.Dlna.ContentDirectory
};
}
- private async Task>> HandleSearch(Headers sparams, User user, string deviceId)
+ private async Task>> HandleSearch(IDictionary sparams, User user, string deviceId)
{
- var searchCriteria = new SearchCriteria(sparams.GetValueOrDefault("SearchCriteria", ""));
- var sortCriteria = new SortCriteria(sparams.GetValueOrDefault("SortCriteria", ""));
- var filter = new Filter(sparams.GetValueOrDefault("Filter", "*"));
+ var searchCriteria = new SearchCriteria(GetValueOrDefault(sparams, "SearchCriteria", ""));
+ var sortCriteria = new SortCriteria(GetValueOrDefault(sparams, "SortCriteria", ""));
+ var filter = new Filter(GetValueOrDefault(sparams, "Filter", "*"));
// sort example: dc:title, dc:date
diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj
index 0441cb3be0..4d1aacfec5 100644
--- a/Emby.Dlna/Emby.Dlna.csproj
+++ b/Emby.Dlna/Emby.Dlna.csproj
@@ -152,7 +152,6 @@
-
diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs
index 170b4cee0e..858b1ae9ec 100644
--- a/Emby.Dlna/Main/DlnaEntryPoint.cs
+++ b/Emby.Dlna/Main/DlnaEntryPoint.cs
@@ -54,6 +54,7 @@ namespace Emby.Dlna.Main
private readonly ITimerFactory _timerFactory;
private readonly ISocketFactory _socketFactory;
private readonly IEnvironmentInfo _environmentInfo;
+ private readonly INetworkManager _networkManager;
private ISsdpCommunicationsServer _communicationsServer;
@@ -69,7 +70,7 @@ namespace Emby.Dlna.Main
IUserDataManager userDataManager,
ILocalizationManager localization,
IMediaSourceManager mediaSourceManager,
- IDeviceDiscovery deviceDiscovery, IMediaEncoder mediaEncoder, ISocketFactory socketFactory, ITimerFactory timerFactory, IEnvironmentInfo environmentInfo)
+ IDeviceDiscovery deviceDiscovery, IMediaEncoder mediaEncoder, ISocketFactory socketFactory, ITimerFactory timerFactory, IEnvironmentInfo environmentInfo, INetworkManager networkManager)
{
_config = config;
_appHost = appHost;
@@ -87,6 +88,7 @@ namespace Emby.Dlna.Main
_socketFactory = socketFactory;
_timerFactory = timerFactory;
_environmentInfo = environmentInfo;
+ _networkManager = networkManager;
_logger = logManager.GetLogger("Dlna");
}
@@ -156,7 +158,7 @@ namespace Emby.Dlna.Main
{
if (_communicationsServer == null)
{
- _communicationsServer = new SsdpCommunicationsServer(_socketFactory)
+ _communicationsServer = new SsdpCommunicationsServer(_socketFactory, _networkManager, _logger)
{
IsShared = true
};
diff --git a/Emby.Dlna/MediaReceiverRegistrar/ControlHandler.cs b/Emby.Dlna/MediaReceiverRegistrar/ControlHandler.cs
index 5e232aeaca..daf46b1061 100644
--- a/Emby.Dlna/MediaReceiverRegistrar/ControlHandler.cs
+++ b/Emby.Dlna/MediaReceiverRegistrar/ControlHandler.cs
@@ -11,7 +11,7 @@ namespace Emby.Dlna.MediaReceiverRegistrar
{
public class ControlHandler : BaseControlHandler
{
- protected override IEnumerable> GetResult(string methodName, Headers methodParams)
+ protected override IEnumerable> GetResult(string methodName, IDictionary methodParams)
{
if (string.Equals(methodName, "IsAuthorized", StringComparison.OrdinalIgnoreCase))
return HandleIsAuthorized();
@@ -23,7 +23,7 @@ namespace Emby.Dlna.MediaReceiverRegistrar
private IEnumerable> HandleIsAuthorized()
{
- return new Headers(true)
+ return new Dictionary(StringComparer.OrdinalIgnoreCase)
{
{ "Result", "1" }
};
@@ -31,7 +31,7 @@ namespace Emby.Dlna.MediaReceiverRegistrar
private IEnumerable> HandleIsValidated()
{
- return new Headers(true)
+ return new Dictionary(StringComparer.OrdinalIgnoreCase)
{
{ "Result", "1" }
};
diff --git a/Emby.Dlna/Server/Headers.cs b/Emby.Dlna/Server/Headers.cs
deleted file mode 100644
index 47dd8e3215..0000000000
--- a/Emby.Dlna/Server/Headers.cs
+++ /dev/null
@@ -1,169 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Text.RegularExpressions;
-
-namespace Emby.Dlna.Server
-{
- public class Headers : IDictionary
- {
- private readonly bool _asIs = false;
- private readonly Dictionary _dict = new Dictionary();
- private readonly static Regex Validator = new Regex(@"^[a-z\d][a-z\d_.-]+$", RegexOptions.IgnoreCase);
-
- public Headers(bool asIs)
- {
- _asIs = asIs;
- }
-
- public Headers()
- : this(asIs: false)
- {
- }
-
- public int Count
- {
- get
- {
- return _dict.Count;
- }
- }
- public string HeaderBlock
- {
- get
- {
- var hb = new StringBuilder();
- foreach (var h in this)
- {
- hb.AppendFormat("{0}: {1}\r\n", h.Key, h.Value);
- }
- return hb.ToString();
- }
- }
- public bool IsReadOnly
- {
- get
- {
- return false;
- }
- }
- public ICollection Keys
- {
- get
- {
- return _dict.Keys;
- }
- }
- public ICollection Values
- {
- get
- {
- return _dict.Values;
- }
- }
-
-
- public string this[string key]
- {
- get
- {
- return _dict[Normalize(key)];
- }
- set
- {
- _dict[Normalize(key)] = value;
- }
- }
-
-
- private string Normalize(string header)
- {
- if (!_asIs)
- {
- header = header.ToLower();
- }
- header = header.Trim();
- if (!Validator.IsMatch(header))
- {
- throw new ArgumentException("Invalid header: " + header);
- }
- return header;
- }
-
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
- {
- return _dict.GetEnumerator();
- }
-
- public void Add(KeyValuePair item)
- {
- Add(item.Key, item.Value);
- }
-
- public void Add(string key, string value)
- {
- _dict.Add(Normalize(key), value);
- }
-
- public void Clear()
- {
- _dict.Clear();
- }
-
- public bool Contains(KeyValuePair item)
- {
- var p = new KeyValuePair(Normalize(item.Key), item.Value);
- return _dict.Contains(p);
- }
-
- public bool ContainsKey(string key)
- {
- return _dict.ContainsKey(Normalize(key));
- }
-
- public void CopyTo(KeyValuePair[] array, int arrayIndex)
- {
- throw new NotImplementedException();
- }
-
- public IEnumerator> GetEnumerator()
- {
- return _dict.GetEnumerator();
- }
-
- public bool Remove(string key)
- {
- return _dict.Remove(Normalize(key));
- }
-
- public bool Remove(KeyValuePair item)
- {
- return Remove(item.Key);
- }
-
- public override string ToString()
- {
- return string.Format("({0})", string.Join(", ", (from x in _dict
- select string.Format("{0}={1}", x.Key, x.Value))));
- }
-
- public bool TryGetValue(string key, out string value)
- {
- return _dict.TryGetValue(Normalize(key), out value);
- }
-
- public string GetValueOrDefault(string key, string defaultValue)
- {
- string val;
-
- if (TryGetValue(key, out val))
- {
- return val;
- }
-
- return defaultValue;
- }
- }
-}
diff --git a/Emby.Dlna/Service/BaseControlHandler.cs b/Emby.Dlna/Service/BaseControlHandler.cs
index 4ce047172e..3092589c12 100644
--- a/Emby.Dlna/Service/BaseControlHandler.cs
+++ b/Emby.Dlna/Service/BaseControlHandler.cs
@@ -9,6 +9,7 @@ using System.Linq;
using System.Text;
using System.Xml;
using Emby.Dlna.Didl;
+using MediaBrowser.Controller.Extensions;
using MediaBrowser.Model.Xml;
namespace Emby.Dlna.Service
@@ -185,8 +186,7 @@ namespace Emby.Dlna.Service
{
using (var subReader = reader.ReadSubtree())
{
- result.Headers = ParseFirstBodyChild(subReader);
-
+ ParseFirstBodyChild(subReader, result.Headers);
return result;
}
}
@@ -204,10 +204,8 @@ namespace Emby.Dlna.Service
return result;
}
- private Headers ParseFirstBodyChild(XmlReader reader)
+ private void ParseFirstBodyChild(XmlReader reader, IDictionary headers)
{
- var result = new Headers();
-
reader.MoveToContent();
reader.Read();
@@ -216,25 +214,24 @@ namespace Emby.Dlna.Service
{
if (reader.NodeType == XmlNodeType.Element)
{
- result.Add(reader.LocalName, reader.ReadElementContentAsString());
+ // TODO: Should we be doing this here, or should it be handled earlier when decoding the request?
+ headers[reader.LocalName.RemoveDiacritics()] = reader.ReadElementContentAsString();
}
else
{
reader.Read();
}
}
-
- return result;
}
private class ControlRequestInfo
{
public string LocalName;
public string NamespaceURI;
- public Headers Headers = new Headers();
+ public IDictionary Headers = new Dictionary(StringComparer.OrdinalIgnoreCase);
}
- protected abstract IEnumerable> GetResult(string methodName, Headers methodParams);
+ protected abstract IEnumerable> GetResult(string methodName, IDictionary methodParams);
private void LogRequest(ControlRequest request)
{
diff --git a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs
index 8a5ae2c3a5..0e1f5a5517 100644
--- a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs
+++ b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs
@@ -518,7 +518,7 @@ namespace Emby.Server.Implementations.HttpServer
return;
}
- var handler = HttpHandlerFactory.GetHandler(httpReq);
+ var handler = HttpHandlerFactory.GetHandler(httpReq, _logger);
if (handler != null)
{
diff --git a/ServiceStack/HttpHandlerFactory.cs b/ServiceStack/HttpHandlerFactory.cs
index d48bfeb5f8..5f4892d51c 100644
--- a/ServiceStack/HttpHandlerFactory.cs
+++ b/ServiceStack/HttpHandlerFactory.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Services;
using ServiceStack.Host;
@@ -9,12 +10,16 @@ namespace ServiceStack
public class HttpHandlerFactory
{
// Entry point for HttpListener
- public static RestHandler GetHandler(IHttpRequest httpReq)
+ public static RestHandler GetHandler(IHttpRequest httpReq, ILogger logger)
{
var pathInfo = httpReq.PathInfo;
var pathParts = pathInfo.TrimStart('/').Split('/');
- if (pathParts.Length == 0) return null;
+ if (pathParts.Length == 0)
+ {
+ logger.Error("Path parts empty for PathInfo: {0}, Url: {1}", pathInfo, httpReq.RawUrl);
+ return null;
+ }
string contentType;
var restPath = RestHandler.FindMatchingRestPath(httpReq.HttpMethod, pathInfo, out contentType);