diff --git a/BDInfo/BDROM.cs b/BDInfo/BDROM.cs index 2a23645b16..97dbfbf3bd 100644 --- a/BDInfo/BDROM.cs +++ b/BDInfo/BDROM.cs @@ -22,7 +22,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using MediaBrowser.Model.IO; -using MediaBrowser.Model.TextEncoding; +using MediaBrowser.Model.Text; namespace BDInfo { @@ -75,7 +75,7 @@ namespace BDInfo public event OnPlaylistFileScanError PlaylistFileScanError; public BDROM( - string path, IFileSystem fileSystem, IEncoding textEncoding) + string path, IFileSystem fileSystem, ITextEncoding textEncoding) { _fileSystem = fileSystem; // diff --git a/BDInfo/TSPlaylistFile.cs b/BDInfo/TSPlaylistFile.cs index 2826b3c803..46d66f513e 100644 --- a/BDInfo/TSPlaylistFile.cs +++ b/BDInfo/TSPlaylistFile.cs @@ -23,14 +23,14 @@ using System.Collections.Generic; using System.IO; using System.Text; using MediaBrowser.Model.IO; -using MediaBrowser.Model.TextEncoding; +using MediaBrowser.Model.Text; namespace BDInfo { public class TSPlaylistFile { private readonly IFileSystem _fileSystem; - private readonly IEncoding _textEncoding; + private readonly ITextEncoding _textEncoding; private FileSystemMetadata FileInfo = null; public string FileType = null; public bool IsInitialized = false; @@ -67,7 +67,7 @@ namespace BDInfo public TSPlaylistFile( BDROM bdrom, - FileSystemMetadata fileInfo, IFileSystem fileSystem, IEncoding textEncoding) + FileSystemMetadata fileInfo, IFileSystem fileSystem, ITextEncoding textEncoding) { BDROM = bdrom; FileInfo = fileInfo; @@ -79,7 +79,7 @@ namespace BDInfo public TSPlaylistFile( BDROM bdrom, string name, - List clips, IFileSystem fileSystem, IEncoding textEncoding) + List clips, IFileSystem fileSystem, ITextEncoding textEncoding) { BDROM = bdrom; Name = name; @@ -1247,7 +1247,7 @@ namespace BDInfo ref int pos) { string val = - _textEncoding.GetASCIIString(data, pos, count); + _textEncoding.GetASCIIEncoding().GetString(data, pos, count); pos += count; diff --git a/BDInfo/TSStreamClipFile.cs b/BDInfo/TSStreamClipFile.cs index 118e3b5fce..f2accb88d8 100644 --- a/BDInfo/TSStreamClipFile.cs +++ b/BDInfo/TSStreamClipFile.cs @@ -23,14 +23,14 @@ using System.Collections.Generic; using System.IO; using System.Text; using MediaBrowser.Model.IO; -using MediaBrowser.Model.TextEncoding; +using MediaBrowser.Model.Text; namespace BDInfo { public class TSStreamClipFile { private readonly IFileSystem _fileSystem; - private readonly IEncoding _textEncoding; + private readonly ITextEncoding _textEncoding; public FileSystemMetadata FileInfo = null; public string FileType = null; public bool IsValid = false; @@ -40,7 +40,7 @@ namespace BDInfo new Dictionary(); public TSStreamClipFile( - FileSystemMetadata fileInfo, IFileSystem fileSystem, IEncoding textEncoding) + FileSystemMetadata fileInfo, IFileSystem fileSystem, ITextEncoding textEncoding) { FileInfo = fileInfo; _fileSystem = fileSystem; @@ -70,7 +70,7 @@ namespace BDInfo byte[] fileType = new byte[8]; Array.Copy(data, 0, fileType, 0, fileType.Length); - FileType = _textEncoding.GetASCIIString(fileType, 0, fileType.Length); + FileType = _textEncoding.GetASCIIEncoding().GetString(fileType, 0, fileType.Length); if (FileType != "HDMV0100" && FileType != "HDMV0200") { @@ -167,7 +167,7 @@ namespace BDInfo Array.Copy(clipData, streamOffset + 3, languageBytes, 0, languageBytes.Length); string languageCode = - _textEncoding.GetASCIIString(languageBytes, 0, languageBytes.Length); + _textEncoding.GetASCIIEncoding().GetString(languageBytes, 0, languageBytes.Length); TSChannelLayout channelLayout = (TSChannelLayout) (clipData[streamOffset + 2] >> 4); @@ -198,7 +198,7 @@ namespace BDInfo Array.Copy(clipData, streamOffset + 2, languageBytes, 0, languageBytes.Length); string languageCode = - _textEncoding.GetASCIIString(languageBytes, 0, languageBytes.Length); + _textEncoding.GetASCIIEncoding().GetString(languageBytes, 0, languageBytes.Length); stream = new TSGraphicsStream(); stream.LanguageCode = languageCode; @@ -218,7 +218,7 @@ namespace BDInfo Array.Copy(clipData, streamOffset + 3, languageBytes, 0, languageBytes.Length); string languageCode = - _textEncoding.GetASCIIString(languageBytes, 0, languageBytes.Length); + _textEncoding.GetASCIIEncoding().GetString(languageBytes, 0, languageBytes.Length); #if DEBUG Debug.WriteLine(string.Format( "\t{0} {1} {2}", diff --git a/Emby.Common.Implementations/BaseApplicationHost.cs b/Emby.Common.Implementations/BaseApplicationHost.cs index 9585abb2a2..0cf11e8255 100644 --- a/Emby.Common.Implementations/BaseApplicationHost.cs +++ b/Emby.Common.Implementations/BaseApplicationHost.cs @@ -170,7 +170,7 @@ namespace Emby.Common.Implementations /// true if this instance is running as service; otherwise, false. public abstract bool IsRunningAsService { get; } - protected ICryptographyProvider CryptographyProvider = new CryptographyProvider(); + protected ICryptoProvider CryptographyProvider = new CryptographyProvider(); protected IEnvironmentInfo EnvironmentInfo = new Emby.Common.Implementations.EnvironmentInfo.EnvironmentInfo(); @@ -183,7 +183,7 @@ namespace Emby.Common.Implementations { _deviceId = new DeviceId(ApplicationPaths, LogManager.GetLogger("SystemId"), FileSystemManager); } - + return _deviceId.Value; } } @@ -193,7 +193,7 @@ namespace Emby.Common.Implementations get { return EnvironmentInfo.OperatingSystemName; } } - public IMemoryStreamProvider MemoryStreamProvider { get; set; } + public IMemoryStreamFactory MemoryStreamProvider { get; set; } /// /// The container @@ -209,7 +209,7 @@ namespace Emby.Common.Implementations { // hack alert, until common can target .net core BaseExtensions.CryptographyProvider = CryptographyProvider; - + XmlSerializer = new MyXmlSerializer(fileSystem, logManager.GetLogger("XmlSerializer")); FailedAssemblies = new List(); @@ -267,7 +267,7 @@ namespace Emby.Common.Implementations progress.Report(100); } - protected abstract IMemoryStreamProvider CreateMemoryStreamProvider(); + protected abstract IMemoryStreamFactory CreateMemoryStreamProvider(); protected abstract ISystemEvents CreateSystemEvents(); protected virtual void OnLoggerLoaded(bool isFirstLoad) diff --git a/Emby.Common.Implementations/Cryptography/CryptographyProvider.cs b/Emby.Common.Implementations/Cryptography/CryptographyProvider.cs index 7b8d95b96c..01a31bcc03 100644 --- a/Emby.Common.Implementations/Cryptography/CryptographyProvider.cs +++ b/Emby.Common.Implementations/Cryptography/CryptographyProvider.cs @@ -6,21 +6,14 @@ using MediaBrowser.Model.Cryptography; namespace Emby.Common.Implementations.Cryptography { - public class CryptographyProvider : ICryptographyProvider + public class CryptographyProvider : ICryptoProvider { public Guid GetMD5(string str) { - return new Guid(GetMD5Bytes(str)); - } - public byte[] GetMD5Bytes(string str) - { - using (var provider = MD5.Create()) - { - return provider.ComputeHash(Encoding.Unicode.GetBytes(str)); - } + return new Guid(ComputeMD5(Encoding.Unicode.GetBytes(str))); } - public byte[] GetSHA1Bytes(byte[] bytes) + public byte[] ComputeSHA1(byte[] bytes) { using (var provider = SHA1.Create()) { @@ -28,7 +21,7 @@ namespace Emby.Common.Implementations.Cryptography } } - public byte[] GetMD5Bytes(Stream str) + public byte[] ComputeMD5(Stream str) { using (var provider = MD5.Create()) { @@ -36,7 +29,7 @@ namespace Emby.Common.Implementations.Cryptography } } - public byte[] GetMD5Bytes(byte[] bytes) + public byte[] ComputeMD5(byte[] bytes) { using (var provider = MD5.Create()) { diff --git a/Emby.Common.Implementations/HttpClientManager/HttpClientManager.cs b/Emby.Common.Implementations/HttpClientManager/HttpClientManager.cs index 85fcb556f0..06af5af536 100644 --- a/Emby.Common.Implementations/HttpClientManager/HttpClientManager.cs +++ b/Emby.Common.Implementations/HttpClientManager/HttpClientManager.cs @@ -42,7 +42,7 @@ namespace Emby.Common.Implementations.HttpClientManager private readonly IApplicationPaths _appPaths; private readonly IFileSystem _fileSystem; - private readonly IMemoryStreamProvider _memoryStreamProvider; + private readonly IMemoryStreamFactory _memoryStreamProvider; /// /// Initializes a new instance of the class. @@ -53,7 +53,7 @@ namespace Emby.Common.Implementations.HttpClientManager /// appPaths /// or /// logger - public HttpClientManager(IApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem, IMemoryStreamProvider memoryStreamProvider) + public HttpClientManager(IApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem, IMemoryStreamFactory memoryStreamProvider) { if (appPaths == null) { diff --git a/Emby.Common.Implementations/Net/NetSocket.cs b/Emby.Common.Implementations/Net/NetSocket.cs new file mode 100644 index 0000000000..72faa41a9a --- /dev/null +++ b/Emby.Common.Implementations/Net/NetSocket.cs @@ -0,0 +1,85 @@ +using System; +using System.Net; +using System.Net.Sockets; +using System.Threading; +using Emby.Common.Implementations.Networking; +using MediaBrowser.Model.Net; +using MediaBrowser.Model.Logging; + +namespace Emby.Common.Implementations.Net +{ + public class NetSocket : ISocket + { + public Socket Socket { get; private set; } + private readonly ILogger _logger; + + public NetSocket(Socket socket, ILogger logger) + { + Socket = socket; + _logger = logger; + } + + public IpEndPointInfo LocalEndPoint + { + get + { + return BaseNetworkManager.ToIpEndPointInfo((IPEndPoint)Socket.LocalEndPoint); + } + } + + public IpEndPointInfo RemoteEndPoint + { + get + { + return BaseNetworkManager.ToIpEndPointInfo((IPEndPoint)Socket.RemoteEndPoint); + } + } + + public void Close() + { +#if NET46 + Socket.Close(); +#else + Socket.Dispose(); +#endif + } + + public void Shutdown(bool both) + { + if (both) + { + Socket.Shutdown(SocketShutdown.Both); + } + else + { + // Change interface if ever needed + throw new NotImplementedException(); + } + } + + public void Listen(int backlog) + { + Socket.Listen(backlog); + } + + public void Bind(IpEndPointInfo endpoint) + { + var nativeEndpoint = BaseNetworkManager.ToIPEndPoint(endpoint); + + Socket.Bind(nativeEndpoint); + } + + private SocketAcceptor _acceptor; + public void StartAccept(Action onAccept, Func isClosed) + { + _acceptor = new SocketAcceptor(_logger, Socket, onAccept, isClosed); + + _acceptor.StartAccept(); + } + + public void Dispose() + { + Socket.Dispose(); + } + } +} diff --git a/Emby.Common.Implementations/Net/SocketAcceptor.cs b/Emby.Common.Implementations/Net/SocketAcceptor.cs new file mode 100644 index 0000000000..fd65e9fbc8 --- /dev/null +++ b/Emby.Common.Implementations/Net/SocketAcceptor.cs @@ -0,0 +1,111 @@ +using System; +using System.Net.Sockets; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Net; + +namespace Emby.Common.Implementations.Net +{ + public class SocketAcceptor + { + private readonly ILogger _logger; + private readonly Socket _originalSocket; + private readonly Func _isClosed; + private readonly Action _onAccept; + + public SocketAcceptor(ILogger logger, Socket originalSocket, Action onAccept, Func isClosed) + { + _logger = logger; + _originalSocket = originalSocket; + _isClosed = isClosed; + _onAccept = onAccept; + } + + public void StartAccept() + { + Socket dummy = null; + StartAccept(null, ref dummy); + } + + public void StartAccept(SocketAsyncEventArgs acceptEventArg, ref Socket accepted) + { + if (acceptEventArg == null) + { + acceptEventArg = new SocketAsyncEventArgs(); + acceptEventArg.Completed += new EventHandler(AcceptEventArg_Completed); + } + else + { + // socket must be cleared since the context object is being reused + acceptEventArg.AcceptSocket = null; + } + + try + { + bool willRaiseEvent = _originalSocket.AcceptAsync(acceptEventArg); + + if (!willRaiseEvent) + { + ProcessAccept(acceptEventArg); + } + } + catch (Exception ex) + { + if (accepted != null) + { + try + { +#if NET46 + accepted.Close(); +#else + accepted.Dispose(); +#endif + } + catch + { + } + accepted = null; + } + } + } + + // This method is the callback method associated with Socket.AcceptAsync + // operations and is invoked when an accept operation is complete + // + void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e) + { + ProcessAccept(e); + } + + private void ProcessAccept(SocketAsyncEventArgs e) + { + if (_isClosed()) + { + return; + } + + // http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.acceptasync%28v=vs.110%29.aspx + // Under certain conditions ConnectionReset can occur + // Need to attept to re-accept + if (e.SocketError == SocketError.ConnectionReset) + { + _logger.Error("SocketError.ConnectionReset reported. Attempting to re-accept."); + Socket dummy = null; + StartAccept(e, ref dummy); + return; + } + + var acceptSocket = e.AcceptSocket; + if (acceptSocket != null) + { + //ProcessAccept(acceptSocket); + _onAccept(new NetSocket(acceptSocket, _logger)); + } + + if (_originalSocket != null) + { + // Accept the next connection request + StartAccept(e, ref acceptSocket); + } + } + } +} diff --git a/Emby.Common.Implementations/Net/SocketFactory.cs b/Emby.Common.Implementations/Net/SocketFactory.cs index bb38c72da5..922b0f3cc5 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 MediaBrowser.Model.Logging; using MediaBrowser.Model.Net; namespace Emby.Common.Implementations.Net @@ -22,16 +23,28 @@ namespace Emby.Common.Implementations.Net /// private IPAddress _LocalIP; - /// - /// Default constructor. - /// - /// A string containing the IP address of the local network adapter to bind sockets to. Null or empty string will use . - public SocketFactory(string localIP) + private ILogger _logger; + + public SocketFactory(ILogger logger) { - if (String.IsNullOrEmpty(localIP)) - _LocalIP = IPAddress.Any; - else - _LocalIP = IPAddress.Parse(localIP); + _logger = logger; + _LocalIP = IPAddress.Any; + } + + public ISocket CreateSocket(IpAddressFamily family, MediaBrowser.Model.Net.SocketType socketType, MediaBrowser.Model.Net.ProtocolType protocolType, bool dualMode) + { + var addressFamily = family == IpAddressFamily.InterNetwork + ? AddressFamily.InterNetwork + : AddressFamily.InterNetworkV6; + + var socket = new Socket(addressFamily, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp); + + if (dualMode) + { + socket.DualMode = true; + } + + return new NetSocket(socket, _logger); } #region ISocketFactory Members @@ -44,7 +57,7 @@ namespace Emby.Common.Implementations.Net { if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort"); - var retVal = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + var retVal = new Socket(AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp); try { retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); @@ -68,7 +81,7 @@ namespace Emby.Common.Implementations.Net { if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort"); - var retVal = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + var retVal = new Socket(AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp); try { retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); @@ -99,7 +112,7 @@ namespace Emby.Common.Implementations.Net if (multicastTimeToLive <= 0) throw new ArgumentException("multicastTimeToLive cannot be zero or less.", "multicastTimeToLive"); if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort"); - var retVal = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + var retVal = new Socket(AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp); try { diff --git a/Emby.Common.Implementations/Net/UdpSocket.cs b/Emby.Common.Implementations/Net/UdpSocket.cs index d999d3fe87..244b37bb41 100644 --- a/Emby.Common.Implementations/Net/UdpSocket.cs +++ b/Emby.Common.Implementations/Net/UdpSocket.cs @@ -5,6 +5,7 @@ using System.Net; using System.Net.Sockets; using System.Security; using System.Threading.Tasks; +using Emby.Common.Implementations.Networking; using MediaBrowser.Model.Net; namespace Emby.Common.Implementations.Net @@ -174,16 +175,7 @@ namespace Emby.Common.Implementations.Net return null; } - return new IpEndPointInfo - { - IpAddress = new IpAddressInfo - { - Address = endpoint.Address.ToString(), - IsIpv6 = endpoint.AddressFamily == AddressFamily.InterNetworkV6 - }, - - Port = endpoint.Port - }; + return BaseNetworkManager.ToIpEndPointInfo(endpoint); } private void ProcessResponse(IAsyncResult asyncResult) diff --git a/Emby.Common.Implementations/Networking/BaseNetworkManager.cs b/Emby.Common.Implementations/Networking/BaseNetworkManager.cs index 10d0db9684..f1ac8413be 100644 --- a/Emby.Common.Implementations/Networking/BaseNetworkManager.cs +++ b/Emby.Common.Implementations/Networking/BaseNetworkManager.cs @@ -22,14 +22,10 @@ namespace Emby.Common.Implementations.Networking Logger = logger; } - private List _localIpAddresses; + private List _localIpAddresses; private readonly object _localIpAddressSyncLock = new object(); - /// - /// Gets the machine's local ip address - /// - /// IPAddress. - public IEnumerable GetLocalIpAddresses() + public IEnumerable GetLocalIpAddresses() { const int cacheMinutes = 5; @@ -39,7 +35,7 @@ namespace Emby.Common.Implementations.Networking if (_localIpAddresses == null || forceRefresh) { - var addresses = GetLocalIpAddressesInternal().ToList(); + var addresses = GetLocalIpAddressesInternal().Select(ToIpAddressInfo).ToList(); _localIpAddresses = addresses; _lastRefresh = DateTime.UtcNow; @@ -405,18 +401,85 @@ namespace Emby.Common.Implementations.Networking IPAddress address; if (IPAddress.TryParse(ipAddress, out address)) { - - ipAddressInfo = new IpAddressInfo - { - Address = address.ToString(), - IsIpv6 = address.AddressFamily == AddressFamily.InterNetworkV6 - }; - + ipAddressInfo = ToIpAddressInfo(address); return true; } ipAddressInfo = null; return false; } + + public static IpEndPointInfo ToIpEndPointInfo(IPEndPoint endpoint) + { + if (endpoint == null) + { + return null; + } + + return new IpEndPointInfo(ToIpAddressInfo(endpoint.Address), endpoint.Port); + } + + public static IPEndPoint ToIPEndPoint(IpEndPointInfo endpoint) + { + if (endpoint == null) + { + return null; + } + + return new IPEndPoint(ToIPAddress(endpoint.IpAddress), endpoint.Port); + } + + public static IPAddress ToIPAddress(IpAddressInfo address) + { + if (address.Equals(IpAddressInfo.Any)) + { + return IPAddress.Any; + } + if (address.Equals(IpAddressInfo.IPv6Any)) + { + return IPAddress.IPv6Any; + } + if (address.Equals(IpAddressInfo.Loopback)) + { + return IPAddress.Loopback; + } + if (address.Equals(IpAddressInfo.IPv6Loopback)) + { + return IPAddress.IPv6Loopback; + } + + return IPAddress.Parse(address.Address); + } + + public static IpAddressInfo ToIpAddressInfo(IPAddress address) + { + if (address.Equals(IPAddress.Any)) + { + return IpAddressInfo.Any; + } + if (address.Equals(IPAddress.IPv6Any)) + { + return IpAddressInfo.IPv6Any; + } + if (address.Equals(IPAddress.Loopback)) + { + return IpAddressInfo.Loopback; + } + if (address.Equals(IPAddress.IPv6Loopback)) + { + return IpAddressInfo.IPv6Loopback; + } + return new IpAddressInfo + { + Address = address.ToString(), + AddressFamily = address.AddressFamily == AddressFamily.InterNetworkV6 ? IpAddressFamily.InterNetworkV6 : IpAddressFamily.InterNetwork + }; + } + + public async Task GetHostAddressesAsync(string host) + { + var addresses = await Dns.GetHostAddressesAsync(host).ConfigureAwait(false); + return addresses.Select(ToIpAddressInfo).ToArray(); + } } } diff --git a/Emby.Common.Implementations/TextEncoding/TextEncoding.cs b/Emby.Common.Implementations/TextEncoding/TextEncoding.cs index 35b869e43b..254d352224 100644 --- a/Emby.Common.Implementations/TextEncoding/TextEncoding.cs +++ b/Emby.Common.Implementations/TextEncoding/TextEncoding.cs @@ -1,10 +1,10 @@ using System.Text; using MediaBrowser.Model.IO; -using MediaBrowser.Model.TextEncoding; +using MediaBrowser.Model.Text; namespace Emby.Common.Implementations.TextEncoding { - public class TextEncoding : IEncoding + public class TextEncoding : ITextEncoding { private readonly IFileSystem _fileSystem; @@ -13,14 +13,9 @@ namespace Emby.Common.Implementations.TextEncoding _fileSystem = fileSystem; } - public byte[] GetASCIIBytes(string text) + public Encoding GetASCIIEncoding() { - return Encoding.ASCII.GetBytes(text); - } - - public string GetASCIIString(byte[] bytes, int startIndex, int length) - { - return Encoding.ASCII.GetString(bytes, 0, bytes.Length); + return Encoding.ASCII; } public Encoding GetFileEncoding(string srcFile) diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs index 142b9f96e7..ef27c029dc 100644 --- a/Emby.Dlna/Main/DlnaEntryPoint.cs +++ b/Emby.Dlna/Main/DlnaEntryPoint.cs @@ -250,14 +250,12 @@ namespace Emby.Dlna.Main // continue; //} - var addressString = address.ToString(); - var fullService = "urn:schemas-upnp-org:device:MediaServer:1"; - _logger.Info("Registering publisher for {0} on {1}", fullService, addressString); + _logger.Info("Registering publisher for {0} on {1}", fullService, address.ToString()); var descriptorUri = "/dlna/" + udn + "/description.xml"; - var uri = new Uri(_appHost.GetLocalApiUrl(addressString, address.IsIpv6) + descriptorUri); + var uri = new Uri(_appHost.GetLocalApiUrl(address) + descriptorUri); var device = new SsdpRootDevice { diff --git a/Emby.Dlna/PlayTo/PlayToManager.cs b/Emby.Dlna/PlayTo/PlayToManager.cs index b714f4ac01..a93f7da14e 100644 --- a/Emby.Dlna/PlayTo/PlayToManager.cs +++ b/Emby.Dlna/PlayTo/PlayToManager.cs @@ -16,6 +16,7 @@ using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Events; using MediaBrowser.Model.Globalization; +using MediaBrowser.Model.Net; using MediaBrowser.Model.Threading; namespace Emby.Dlna.PlayTo @@ -131,11 +132,11 @@ namespace Emby.Dlna.PlayTo string serverAddress; if (info.LocalIpAddress == null) { - serverAddress = await GetServerAddress(null, false).ConfigureAwait(false); + serverAddress = await GetServerAddress(null).ConfigureAwait(false); } else { - serverAddress = await GetServerAddress(info.LocalIpAddress.Address, info.LocalIpAddress.IsIpv6).ConfigureAwait(false); + serverAddress = await GetServerAddress(info.LocalIpAddress).ConfigureAwait(false); } string accessToken = null; @@ -189,14 +190,14 @@ namespace Emby.Dlna.PlayTo } } - private Task GetServerAddress(string ipAddress, bool isIpv6) + private Task GetServerAddress(IpAddressInfo address) { - if (string.IsNullOrWhiteSpace(ipAddress)) + if (address == null) { return _appHost.GetLocalApiUrl(); } - return Task.FromResult(_appHost.GetLocalApiUrl(ipAddress, isIpv6)); + return Task.FromResult(_appHost.GetLocalApiUrl(address)); } public void Dispose() diff --git a/Emby.Server.Implementations/Connect/ConnectEntryPoint.cs b/Emby.Server.Implementations/Connect/ConnectEntryPoint.cs index d7574d466c..170ef07f31 100644 --- a/Emby.Server.Implementations/Connect/ConnectEntryPoint.cs +++ b/Emby.Server.Implementations/Connect/ConnectEntryPoint.cs @@ -64,7 +64,7 @@ namespace Emby.Server.Implementations.Connect validIpAddress = await GetIpAddress(ipLookupUrl).ConfigureAwait(false); // Try to find the ipv4 address, if present - if (!validIpAddress.IsIpv6) + if (validIpAddress.AddressFamily != IpAddressFamily.InterNetworkV6) { break; } @@ -77,9 +77,9 @@ namespace Emby.Server.Implementations.Connect _logger.ErrorException("Error getting connection info", ex); } } - + // If this produced an ipv6 address, try again - if (validIpAddress != null && validIpAddress.IsIpv6) + if (validIpAddress != null && validIpAddress.AddressFamily == IpAddressFamily.InterNetworkV6) { foreach (var ipLookupUrl in _ipLookups) { @@ -88,7 +88,7 @@ namespace Emby.Server.Implementations.Connect var newAddress = await GetIpAddress(ipLookupUrl, true).ConfigureAwait(false); // Try to find the ipv4 address, if present - if (!newAddress.IsIpv6) + if (newAddress.AddressFamily != IpAddressFamily.InterNetworkV6) { validIpAddress = newAddress; break; diff --git a/Emby.Server.Implementations/Connect/ConnectManager.cs b/Emby.Server.Implementations/Connect/ConnectManager.cs index 6c2ac40c32..079bfe8685 100644 --- a/Emby.Server.Implementations/Connect/ConnectManager.cs +++ b/Emby.Server.Implementations/Connect/ConnectManager.cs @@ -74,7 +74,7 @@ namespace Emby.Server.Implementations.Connect if (string.IsNullOrWhiteSpace(address) && DiscoveredWanIpAddress != null) { - if (DiscoveredWanIpAddress.IsIpv6) + if (DiscoveredWanIpAddress.AddressFamily == IpAddressFamily.InterNetworkV6) { address = "[" + DiscoveredWanIpAddress + "]"; } diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 894ba334d9..806702dfd3 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -68,11 +68,18 @@ + + + + + + + @@ -254,6 +261,9 @@ {442b5058-dcaf-4263-bb6a-f21e31120a1b} MediaBrowser.Providers + + ..\ThirdParty\emby\SocketHttpListener.Portable.dll + ..\packages\UniversalDetector.1.0.1\lib\portable-net45+sl4+wp71+win8+wpa81\UniversalDetector.dll True diff --git a/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs b/Emby.Server.Implementations/HttpServer/LoggerUtils.cs similarity index 96% rename from MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs rename to Emby.Server.Implementations/HttpServer/LoggerUtils.cs index bfbb228edf..8fc92a09a7 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs +++ b/Emby.Server.Implementations/HttpServer/LoggerUtils.cs @@ -3,7 +3,7 @@ using System; using System.Globalization; using SocketHttpListener.Net; -namespace MediaBrowser.Server.Implementations.HttpServer +namespace Emby.Server.Implementations.HttpServer { public static class LoggerUtils { diff --git a/MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs b/Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs similarity index 96% rename from MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs rename to Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs index 7d4cd3b4dc..e88994bec0 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs +++ b/Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs @@ -1,5 +1,4 @@ using MediaBrowser.Model.Logging; -using ServiceStack.Web; using System; using System.Collections.Generic; using System.Globalization; @@ -9,7 +8,7 @@ using System.Threading; using System.Threading.Tasks; using MediaBrowser.Model.Services; -namespace MediaBrowser.Server.Implementations.HttpServer +namespace Emby.Server.Implementations.HttpServer { public class RangeRequestWriter : IAsyncStreamWriter, IHttpResult { @@ -41,7 +40,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer /// private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - public Func ResultScope { get; set; } public List Cookies { get; private set; } /// @@ -213,8 +211,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer public object Response { get; set; } - public IContentTypeWriter ResponseFilter { get; set; } - public int Status { get; set; } public HttpStatusCode StatusCode @@ -224,7 +220,5 @@ namespace MediaBrowser.Server.Implementations.HttpServer } public string StatusDescription { get; set; } - - public int PaddingLength { get; set; } } } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/HttpServer/ResponseFilter.cs b/Emby.Server.Implementations/HttpServer/ResponseFilter.cs similarity index 80% rename from MediaBrowser.Server.Implementations/HttpServer/ResponseFilter.cs rename to Emby.Server.Implementations/HttpServer/ResponseFilter.cs index 6247e4c170..6d9d7d921d 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/ResponseFilter.cs +++ b/Emby.Server.Implementations/HttpServer/ResponseFilter.cs @@ -1,12 +1,11 @@ using MediaBrowser.Model.Logging; -using MediaBrowser.Server.Implementations.HttpServer.SocketSharp; using System; using System.Globalization; -using System.Net; using System.Text; +using Emby.Server.Implementations.HttpServer.SocketSharp; using MediaBrowser.Model.Services; -namespace MediaBrowser.Server.Implementations.HttpServer +namespace Emby.Server.Implementations.HttpServer { public class ResponseFilter { @@ -28,6 +27,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer { // Try to prevent compatibility view res.AddHeader("X-UA-Compatible", "IE=Edge"); + res.AddHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Range, X-MediaBrowser-Token, X-Emby-Authorization"); + res.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, PATCH, OPTIONS"); + res.AddHeader("Access-Control-Allow-Origin", "*"); var exception = dto as Exception; @@ -68,15 +70,15 @@ namespace MediaBrowser.Server.Implementations.HttpServer { res.SetContentLength(length); - var listenerResponse = res.OriginalResponse as HttpListenerResponse; + //var listenerResponse = res.OriginalResponse as HttpListenerResponse; - if (listenerResponse != null) - { - // Disable chunked encoding. Technically this is only needed when using Content-Range, but - // anytime we know the content length there's no need for it - listenerResponse.SendChunked = false; - return; - } + //if (listenerResponse != null) + //{ + // // Disable chunked encoding. Technically this is only needed when using Content-Range, but + // // anytime we know the content length there's no need for it + // listenerResponse.SendChunked = false; + // return; + //} if (sharpResponse != null) { diff --git a/Emby.Server.Implementations/HttpServer/SocketSharp/Extensions.cs b/Emby.Server.Implementations/HttpServer/SocketSharp/Extensions.cs new file mode 100644 index 0000000000..07a338f198 --- /dev/null +++ b/Emby.Server.Implementations/HttpServer/SocketSharp/Extensions.cs @@ -0,0 +1,12 @@ +using SocketHttpListener.Net; + +namespace Emby.Server.Implementations.HttpServer.SocketSharp +{ + public static class Extensions + { + public static string GetOperationName(this HttpListenerRequest request) + { + return request.Url.Segments[request.Url.Segments.Length - 1]; + } + } +} diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs b/Emby.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs similarity index 93% rename from MediaBrowser.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs rename to Emby.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs index d363c4de6c..0a312f7b96 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs +++ b/Emby.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs @@ -6,7 +6,7 @@ using System.Threading; using System.Threading.Tasks; using WebSocketState = MediaBrowser.Model.Net.WebSocketState; -namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp +namespace Emby.Server.Implementations.HttpServer.SocketSharp { public class SharpWebSocket : IWebSocket { @@ -25,12 +25,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource(); - /// - /// Initializes a new instance of the class. - /// - /// The socket. - /// The logger. - /// socket public SharpWebSocket(SocketHttpListener.WebSocket socket, ILogger logger) { if (socket == null) diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs b/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs similarity index 66% rename from MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs rename to Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs index 56f8ab429c..0cb4d428bc 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs +++ b/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs @@ -1,37 +1,49 @@ -using System.Collections.Specialized; -using MediaBrowser.Controller.Net; +using MediaBrowser.Controller.Net; using MediaBrowser.Model.Logging; using SocketHttpListener.Net; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Emby.Server.Implementations.HttpServer; using Emby.Server.Implementations.Logging; -using MediaBrowser.Common.IO; +using MediaBrowser.Common.Net; +using MediaBrowser.Model.Cryptography; using MediaBrowser.Model.IO; +using MediaBrowser.Model.Net; using MediaBrowser.Model.Services; -using ServiceStack; +using MediaBrowser.Model.Text; +using SocketHttpListener.Primitives; -namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp +namespace Emby.Server.Implementations.HttpServer.SocketSharp { public class WebSocketSharpListener : IHttpListener { private HttpListener _listener; private readonly ILogger _logger; - private readonly string _certificatePath; - private readonly IMemoryStreamProvider _memoryStreamProvider; + private readonly ICertificate _certificate; + private readonly IMemoryStreamFactory _memoryStreamProvider; + private readonly ITextEncoding _textEncoding; + private readonly INetworkManager _networkManager; + private readonly ISocketFactory _socketFactory; + private readonly ICryptoProvider _cryptoProvider; + private readonly IStreamFactory _streamFactory; + private readonly Func _httpRequestFactory; - public WebSocketSharpListener(ILogger logger, string certificatePath, IMemoryStreamProvider memoryStreamProvider) + public WebSocketSharpListener(ILogger logger, ICertificate certificate, IMemoryStreamFactory memoryStreamProvider, ITextEncoding textEncoding, INetworkManager networkManager, ISocketFactory socketFactory, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, Func httpRequestFactory) { _logger = logger; - _certificatePath = certificatePath; + _certificate = certificate; _memoryStreamProvider = memoryStreamProvider; + _textEncoding = textEncoding; + _networkManager = networkManager; + _socketFactory = socketFactory; + _cryptoProvider = cryptoProvider; + _streamFactory = streamFactory; + _httpRequestFactory = httpRequestFactory; } public Action ErrorHandler { get; set; } - public Func RequestHandler { get; set; } public Action WebSocketConnecting { get; set; } @@ -41,7 +53,12 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp public void Start(IEnumerable urlPrefixes) { if (_listener == null) - _listener = new HttpListener(new PatternsLogger(_logger), _certificatePath); + _listener = new HttpListener(new PatternsLogger(_logger), _cryptoProvider, _streamFactory, _socketFactory, _networkManager, _textEncoding, _memoryStreamProvider); + + if (_certificate != null) + { + _listener.LoadCert(_certificate); + } foreach (var prefix in urlPrefixes) { @@ -59,41 +76,32 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp Task.Factory.StartNew(() => InitTask(context)); } - private void InitTask(HttpListenerContext context) + private Task InitTask(HttpListenerContext context) { + IHttpRequest httpReq = null; + var request = context.Request; + try { - var task = this.ProcessRequestAsync(context); - task.ContinueWith(x => HandleError(x.Exception, context), TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.AttachedToParent); + if (request.IsWebSocketRequest) + { + LoggerUtils.LogRequest(_logger, request); - //if (task.Status == TaskStatus.Created) - //{ - // task.RunSynchronously(); - //} + ProcessWebSocketRequest(context); + return Task.FromResult(true); + } + + httpReq = GetRequest(context); } catch (Exception ex) { - HandleError(ex, context); - } - } + _logger.ErrorException("Error processing request", ex); - private Task ProcessRequestAsync(HttpListenerContext context) - { - var request = context.Request; - - if (request.IsWebSocketRequest) - { - LoggerUtils.LogRequest(_logger, request); - - ProcessWebSocketRequest(context); + httpReq = httpReq ?? GetRequest(context); + ErrorHandler(ex, httpReq); return Task.FromResult(true); } - if (string.IsNullOrEmpty(context.Request.RawUrl)) - return ((object)null).AsTaskResult(); - - var httpReq = GetRequest(context); - return RequestHandler(httpReq, request.Url); } @@ -103,19 +111,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp { var endpoint = ctx.Request.RemoteEndPoint.ToString(); var url = ctx.Request.RawUrl; - var queryString = ctx.Request.QueryString ?? new NameValueCollection(); - - var queryParamCollection = new QueryParamCollection(); - - foreach (var key in queryString.AllKeys) - { - queryParamCollection[key] = queryString[key]; - } var connectingArgs = new WebSocketConnectingEventArgs { Url = url, - QueryString = queryParamCollection, + QueryString = ctx.Request.QueryString, Endpoint = endpoint }; @@ -135,7 +135,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp WebSocketConnected(new WebSocketConnectEventArgs { Url = url, - QueryString = queryParamCollection, + QueryString = ctx.Request.QueryString, WebSocket = new SharpWebSocket(webSocketContext.WebSocket, _logger), Endpoint = endpoint }); @@ -158,21 +158,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp private IHttpRequest GetRequest(HttpListenerContext httpContext) { - var operationName = httpContext.Request.GetOperationName(); - - var req = new WebSocketSharpRequest(httpContext, operationName, RequestAttributes.None, _logger, _memoryStreamProvider); - - return req; - } - - private void HandleError(Exception ex, HttpListenerContext context) - { - var httpReq = GetRequest(context); - - if (ErrorHandler != null) - { - ErrorHandler(ex, httpReq); - } + return _httpRequestFactory(httpContext); } public void Stop() @@ -213,4 +199,5 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp } } } + } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs b/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs similarity index 69% rename from MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs rename to Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs index 3aae6c9ca6..de0b33fe30 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs +++ b/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs @@ -2,14 +2,13 @@ using System.Collections.Generic; using System.IO; using System.Net; +using System.Text; using MediaBrowser.Model.Logging; -using ServiceStack; -using ServiceStack.Host; using HttpListenerResponse = SocketHttpListener.Net.HttpListenerResponse; using IHttpResponse = MediaBrowser.Model.Services.IHttpResponse; using IRequest = MediaBrowser.Model.Services.IRequest; -namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp +namespace Emby.Server.Implementations.HttpServer.SocketSharp { public class WebSocketSharpResponse : IHttpResponse { @@ -98,7 +97,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp try { - this._response.CloseOutputStream(_logger); + CloseOutputStream(this._response); } catch (Exception ex) { @@ -107,6 +106,20 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp } } + public void CloseOutputStream(HttpListenerResponse response) + { + try + { + response.OutputStream.Flush(); + response.OutputStream.Dispose(); + response.Close(); + } + catch (Exception ex) + { + _logger.ErrorException("Error in HttpListenerResponseWrapper: " + ex.Message, ex); + } + } + public void End() { Close(); @@ -133,10 +146,49 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp public void SetCookie(Cookie cookie) { - var cookieStr = cookie.AsHeaderValue(); - _response.Headers.Add(HttpHeaders.SetCookie, cookieStr); + var cookieStr = AsHeaderValue(cookie); + _response.Headers.Add("Set-Cookie", cookieStr); } + public static string AsHeaderValue(Cookie cookie) + { + var defaultExpires = DateTime.MinValue; + + var path = cookie.Expires == defaultExpires + ? "/" + : cookie.Path ?? "/"; + + var sb = new StringBuilder(); + + sb.Append($"{cookie.Name}={cookie.Value};path={path}"); + + if (cookie.Expires != defaultExpires) + { + sb.Append($";expires={cookie.Expires:R}"); + } + + if (!string.IsNullOrEmpty(cookie.Domain)) + { + sb.Append($";domain={cookie.Domain}"); + } + //else if (restrictAllCookiesToDomain != null) + //{ + // sb.Append($";domain={restrictAllCookiesToDomain}"); + //} + + if (cookie.Secure) + { + sb.Append(";Secure"); + } + if (cookie.HttpOnly) + { + sb.Append(";HttpOnly"); + } + + return sb.ToString(); + } + + public bool SendChunked { get { return _response.SendChunked; } diff --git a/Emby.Server.Implementations/Library/UserManager.cs b/Emby.Server.Implementations/Library/UserManager.cs index 9c1d7fdf13..2a5706b3bf 100644 --- a/Emby.Server.Implementations/Library/UserManager.cs +++ b/Emby.Server.Implementations/Library/UserManager.cs @@ -70,10 +70,10 @@ namespace Emby.Server.Implementations.Library private readonly Func _connectFactory; private readonly IServerApplicationHost _appHost; private readonly IFileSystem _fileSystem; - private readonly ICryptographyProvider _cryptographyProvider; + private readonly ICryptoProvider _cryptographyProvider; private readonly string _defaultUserName; - public UserManager(ILogger logger, IServerConfigurationManager configurationManager, IUserRepository userRepository, IXmlSerializer xmlSerializer, INetworkManager networkManager, Func imageProcessorFactory, Func dtoServiceFactory, Func connectFactory, IServerApplicationHost appHost, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ICryptographyProvider cryptographyProvider, string defaultUserName) + public UserManager(ILogger logger, IServerConfigurationManager configurationManager, IUserRepository userRepository, IXmlSerializer xmlSerializer, INetworkManager networkManager, Func imageProcessorFactory, Func dtoServiceFactory, Func connectFactory, IServerApplicationHost appHost, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ICryptoProvider cryptographyProvider, string defaultUserName) { _logger = logger; UserRepository = userRepository; @@ -334,7 +334,7 @@ namespace Emby.Server.Implementations.Library /// System.String. private string GetSha1String(string str) { - return BitConverter.ToString(_cryptographyProvider.GetSHA1Bytes(Encoding.UTF8.GetBytes(str))).Replace("-", string.Empty); + return BitConverter.ToString(_cryptographyProvider.ComputeSHA1(Encoding.UTF8.GetBytes(str))).Replace("-", string.Empty); } /// diff --git a/Emby.Server.Implementations/Security/MBLicenseFile.cs b/Emby.Server.Implementations/Security/MBLicenseFile.cs index 7cb6165a52..4b6a82b6cf 100644 --- a/Emby.Server.Implementations/Security/MBLicenseFile.cs +++ b/Emby.Server.Implementations/Security/MBLicenseFile.cs @@ -15,7 +15,7 @@ namespace Emby.Server.Implementations.Security { private readonly IApplicationPaths _appPaths; private readonly IFileSystem _fileSystem; - private readonly ICryptographyProvider _cryptographyProvider; + private readonly ICryptoProvider _cryptographyProvider; public string RegKey { @@ -43,7 +43,7 @@ namespace Emby.Server.Implementations.Security private readonly object _fileLock = new object(); private string _regKey; - public MBLicenseFile(IApplicationPaths appPaths, IFileSystem fileSystem, ICryptographyProvider cryptographyProvider) + public MBLicenseFile(IApplicationPaths appPaths, IFileSystem fileSystem, ICryptoProvider cryptographyProvider) { _appPaths = appPaths; _fileSystem = fileSystem; @@ -59,7 +59,7 @@ namespace Emby.Server.Implementations.Security public void AddRegCheck(string featureId) { - var key = new Guid(_cryptographyProvider.GetMD5Bytes(Encoding.Unicode.GetBytes(featureId))); + var key = new Guid(_cryptographyProvider.ComputeMD5(Encoding.Unicode.GetBytes(featureId))); var value = DateTime.UtcNow; SetUpdateRecord(key, value); @@ -68,7 +68,7 @@ namespace Emby.Server.Implementations.Security public void RemoveRegCheck(string featureId) { - var key = new Guid(_cryptographyProvider.GetMD5Bytes(Encoding.Unicode.GetBytes(featureId))); + var key = new Guid(_cryptographyProvider.ComputeMD5(Encoding.Unicode.GetBytes(featureId))); DateTime val; _updateRecords.TryRemove(key, out val); @@ -79,7 +79,7 @@ namespace Emby.Server.Implementations.Security public DateTime LastChecked(string featureId) { DateTime last; - _updateRecords.TryGetValue(new Guid(_cryptographyProvider.GetMD5Bytes(Encoding.Unicode.GetBytes(featureId))), out last); + _updateRecords.TryGetValue(new Guid(_cryptographyProvider.ComputeMD5(Encoding.Unicode.GetBytes(featureId))), out last); // guard agains people just putting a large number in the file return last < DateTime.UtcNow ? last : DateTime.MinValue; diff --git a/Emby.Server.Implementations/Security/PluginSecurityManager.cs b/Emby.Server.Implementations/Security/PluginSecurityManager.cs index c3a7e9450e..61d4f52528 100644 --- a/Emby.Server.Implementations/Security/PluginSecurityManager.cs +++ b/Emby.Server.Implementations/Security/PluginSecurityManager.cs @@ -64,7 +64,7 @@ namespace Emby.Server.Implementations.Security private readonly ILogger _logger; private readonly IApplicationPaths _appPaths; private readonly IFileSystem _fileSystem; - private readonly ICryptographyProvider _cryptographyProvider; + private readonly ICryptoProvider _cryptographyProvider; private IEnumerable _registeredEntities; protected IEnumerable RegisteredEntities @@ -79,7 +79,7 @@ namespace Emby.Server.Implementations.Security /// Initializes a new instance of the class. /// public PluginSecurityManager(IServerApplicationHost appHost, IHttpClient httpClient, IJsonSerializer jsonSerializer, - IApplicationPaths appPaths, ILogManager logManager, IFileSystem fileSystem, ICryptographyProvider cryptographyProvider) + IApplicationPaths appPaths, ILogManager logManager, IFileSystem fileSystem, ICryptoProvider cryptographyProvider) { if (httpClient == null) { diff --git a/Emby.Server.Implementations/ServerManager/ServerManager.cs b/Emby.Server.Implementations/ServerManager/ServerManager.cs index 83ce0b6a35..f660d01ec5 100644 --- a/Emby.Server.Implementations/ServerManager/ServerManager.cs +++ b/Emby.Server.Implementations/ServerManager/ServerManager.cs @@ -15,7 +15,7 @@ using System.Threading.Tasks; using MediaBrowser.Common.IO; using MediaBrowser.Model.IO; using MediaBrowser.Model.Services; -using MediaBrowser.Model.TextEncoding; +using MediaBrowser.Model.Text; namespace Emby.Server.Implementations.ServerManager { @@ -75,8 +75,8 @@ namespace Emby.Server.Implementations.ServerManager private readonly List _webSocketListeners = new List(); private bool _disposed; - private readonly IMemoryStreamProvider _memoryStreamProvider; - private readonly IEncoding _textEncoding; + private readonly IMemoryStreamFactory _memoryStreamProvider; + private readonly ITextEncoding _textEncoding; /// /// Initializes a new instance of the class. @@ -86,7 +86,7 @@ namespace Emby.Server.Implementations.ServerManager /// The logger. /// The configuration manager. /// applicationHost - public ServerManager(IServerApplicationHost applicationHost, IJsonSerializer jsonSerializer, ILogger logger, IServerConfigurationManager configurationManager, IMemoryStreamProvider memoryStreamProvider, IEncoding textEncoding) + public ServerManager(IServerApplicationHost applicationHost, IJsonSerializer jsonSerializer, ILogger logger, IServerConfigurationManager configurationManager, IMemoryStreamFactory memoryStreamProvider, ITextEncoding textEncoding) { if (applicationHost == null) { diff --git a/Emby.Server.Implementations/ServerManager/WebSocketConnection.cs b/Emby.Server.Implementations/ServerManager/WebSocketConnection.cs index dd17edea52..4608a13e6f 100644 --- a/Emby.Server.Implementations/ServerManager/WebSocketConnection.cs +++ b/Emby.Server.Implementations/ServerManager/WebSocketConnection.cs @@ -12,7 +12,7 @@ using System.Threading.Tasks; using MediaBrowser.Common.IO; using MediaBrowser.Model.IO; using MediaBrowser.Model.Services; -using MediaBrowser.Model.TextEncoding; +using MediaBrowser.Model.Text; using UniversalDetector; namespace Emby.Server.Implementations.ServerManager @@ -77,8 +77,8 @@ namespace Emby.Server.Implementations.ServerManager /// /// The query string. public QueryParamCollection QueryString { get; set; } - private readonly IMemoryStreamProvider _memoryStreamProvider; - private readonly IEncoding _textEncoding; + private readonly IMemoryStreamFactory _memoryStreamProvider; + private readonly ITextEncoding _textEncoding; /// /// Initializes a new instance of the class. @@ -88,7 +88,7 @@ namespace Emby.Server.Implementations.ServerManager /// The json serializer. /// The logger. /// socket - public WebSocketConnection(IWebSocket socket, string remoteEndPoint, IJsonSerializer jsonSerializer, ILogger logger, IMemoryStreamProvider memoryStreamProvider, IEncoding textEncoding) + public WebSocketConnection(IWebSocket socket, string remoteEndPoint, IJsonSerializer jsonSerializer, ILogger logger, IMemoryStreamFactory memoryStreamProvider, ITextEncoding textEncoding) { if (socket == null) { @@ -145,7 +145,7 @@ namespace Emby.Server.Implementations.ServerManager } else { - OnReceiveInternal(_textEncoding.GetASCIIString(bytes, 0, bytes.Length)); + OnReceiveInternal(_textEncoding.GetASCIIEncoding().GetString(bytes, 0, bytes.Length)); } } private string DetectCharset(byte[] bytes) diff --git a/Emby.Server.Implementations/Sync/MediaSync.cs b/Emby.Server.Implementations/Sync/MediaSync.cs index b420a3df43..fa8388b6cd 100644 --- a/Emby.Server.Implementations/Sync/MediaSync.cs +++ b/Emby.Server.Implementations/Sync/MediaSync.cs @@ -29,12 +29,12 @@ namespace Emby.Server.Implementations.Sync private readonly ILogger _logger; private readonly IFileSystem _fileSystem; private readonly IConfigurationManager _config; - private readonly ICryptographyProvider _cryptographyProvider; + private readonly ICryptoProvider _cryptographyProvider; public const string PathSeparatorString = "/"; public const char PathSeparatorChar = '/'; - public MediaSync(ILogger logger, ISyncManager syncManager, IServerApplicationHost appHost, IFileSystem fileSystem, IConfigurationManager config, ICryptographyProvider cryptographyProvider) + public MediaSync(ILogger logger, ISyncManager syncManager, IServerApplicationHost appHost, IFileSystem fileSystem, IConfigurationManager config, ICryptoProvider cryptographyProvider) { _logger = logger; _syncManager = syncManager; @@ -370,7 +370,7 @@ namespace Emby.Server.Implementations.Sync private byte[] CreateMd5(byte[] value) { - return _cryptographyProvider.GetMD5Bytes(value); + return _cryptographyProvider.ComputeMD5(value); } public LocalItem CreateLocalItem(IServerSyncProvider provider, SyncedItem syncedItem, SyncJob job, SyncTarget target, BaseItemDto libraryItem, string serverId, string serverName, string originalFileName) diff --git a/Emby.Server.Implementations/Sync/MultiProviderSync.cs b/Emby.Server.Implementations/Sync/MultiProviderSync.cs index db6cfcbd6d..8189b8550f 100644 --- a/Emby.Server.Implementations/Sync/MultiProviderSync.cs +++ b/Emby.Server.Implementations/Sync/MultiProviderSync.cs @@ -23,9 +23,9 @@ namespace Emby.Server.Implementations.Sync private readonly ILogger _logger; private readonly IFileSystem _fileSystem; private readonly IConfigurationManager _config; - private readonly ICryptographyProvider _cryptographyProvider; + private readonly ICryptoProvider _cryptographyProvider; - public MultiProviderSync(SyncManager syncManager, IServerApplicationHost appHost, ILogger logger, IFileSystem fileSystem, IConfigurationManager config, ICryptographyProvider cryptographyProvider) + public MultiProviderSync(SyncManager syncManager, IServerApplicationHost appHost, ILogger logger, IFileSystem fileSystem, IConfigurationManager config, ICryptoProvider cryptographyProvider) { _syncManager = syncManager; _appHost = appHost; diff --git a/Emby.Server.Implementations/Sync/ServerSyncScheduledTask.cs b/Emby.Server.Implementations/Sync/ServerSyncScheduledTask.cs index 17171633e7..09a0bfde4c 100644 --- a/Emby.Server.Implementations/Sync/ServerSyncScheduledTask.cs +++ b/Emby.Server.Implementations/Sync/ServerSyncScheduledTask.cs @@ -20,9 +20,9 @@ namespace Emby.Server.Implementations.Sync private readonly IFileSystem _fileSystem; private readonly IServerApplicationHost _appHost; private readonly IConfigurationManager _config; - private readonly ICryptographyProvider _cryptographyProvider; + private readonly ICryptoProvider _cryptographyProvider; - public ServerSyncScheduledTask(ISyncManager syncManager, ILogger logger, IFileSystem fileSystem, IServerApplicationHost appHost, IConfigurationManager config, ICryptographyProvider cryptographyProvider) + public ServerSyncScheduledTask(ISyncManager syncManager, ILogger logger, IFileSystem fileSystem, IServerApplicationHost appHost, IConfigurationManager config, ICryptoProvider cryptographyProvider) { _syncManager = syncManager; _logger = logger; diff --git a/Emby.Server.Implementations/Sync/SyncManager.cs b/Emby.Server.Implementations/Sync/SyncManager.cs index d06ed49fd0..13f60f5eea 100644 --- a/Emby.Server.Implementations/Sync/SyncManager.cs +++ b/Emby.Server.Implementations/Sync/SyncManager.cs @@ -51,7 +51,7 @@ namespace Emby.Server.Implementations.Sync private readonly Func _mediaSourceManager; private readonly IJsonSerializer _json; private readonly ITaskManager _taskManager; - private readonly IMemoryStreamProvider _memoryStreamProvider; + private readonly IMemoryStreamFactory _memoryStreamProvider; private ISyncProvider[] _providers = { }; @@ -61,7 +61,7 @@ namespace Emby.Server.Implementations.Sync public event EventHandler> SyncJobItemUpdated; public event EventHandler> SyncJobItemCreated; - public SyncManager(ILibraryManager libraryManager, ISyncRepository repo, IImageProcessor imageProcessor, ILogger logger, IUserManager userManager, Func dtoService, IServerApplicationHost appHost, ITVSeriesManager tvSeriesManager, Func mediaEncoder, IFileSystem fileSystem, Func subtitleEncoder, IConfigurationManager config, IUserDataManager userDataManager, Func mediaSourceManager, IJsonSerializer json, ITaskManager taskManager, IMemoryStreamProvider memoryStreamProvider) + public SyncManager(ILibraryManager libraryManager, ISyncRepository repo, IImageProcessor imageProcessor, ILogger logger, IUserManager userManager, Func dtoService, IServerApplicationHost appHost, ITVSeriesManager tvSeriesManager, Func mediaEncoder, IFileSystem fileSystem, Func subtitleEncoder, IConfigurationManager config, IUserDataManager userDataManager, Func mediaSourceManager, IJsonSerializer json, ITaskManager taskManager, IMemoryStreamFactory memoryStreamProvider) { _libraryManager = libraryManager; _repo = repo; diff --git a/Emby.Server.Implementations/Sync/TargetDataProvider.cs b/Emby.Server.Implementations/Sync/TargetDataProvider.cs index a0e0f4313f..fbd82aa7af 100644 --- a/Emby.Server.Implementations/Sync/TargetDataProvider.cs +++ b/Emby.Server.Implementations/Sync/TargetDataProvider.cs @@ -26,9 +26,9 @@ namespace Emby.Server.Implementations.Sync private readonly IFileSystem _fileSystem; private readonly IApplicationPaths _appPaths; private readonly IServerApplicationHost _appHost; - private readonly IMemoryStreamProvider _memoryStreamProvider; + private readonly IMemoryStreamFactory _memoryStreamProvider; - public TargetDataProvider(IServerSyncProvider provider, SyncTarget target, IServerApplicationHost appHost, ILogger logger, IJsonSerializer json, IFileSystem fileSystem, IApplicationPaths appPaths, IMemoryStreamProvider memoryStreamProvider) + public TargetDataProvider(IServerSyncProvider provider, SyncTarget target, IServerApplicationHost appHost, ILogger logger, IJsonSerializer json, IFileSystem fileSystem, IApplicationPaths appPaths, IMemoryStreamFactory memoryStreamProvider) { _logger = logger; _json = json; diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 3c7a8242cb..52bf09284b 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -119,9 +119,9 @@ namespace Emby.Server.Implementations.Updates /// The application host. private readonly IApplicationHost _applicationHost; - private readonly ICryptographyProvider _cryptographyProvider; + private readonly ICryptoProvider _cryptographyProvider; - public InstallationManager(ILogger logger, IApplicationHost appHost, IApplicationPaths appPaths, IHttpClient httpClient, IJsonSerializer jsonSerializer, ISecurityManager securityManager, IConfigurationManager config, IFileSystem fileSystem, ICryptographyProvider cryptographyProvider) + public InstallationManager(ILogger logger, IApplicationHost appHost, IApplicationPaths appPaths, IHttpClient httpClient, IJsonSerializer jsonSerializer, ISecurityManager securityManager, IConfigurationManager config, IFileSystem fileSystem, ICryptoProvider cryptographyProvider) { if (logger == null) { @@ -606,7 +606,7 @@ namespace Emby.Server.Implementations.Updates { using (var stream = _fileSystem.OpenRead(tempFile)) { - var check = Guid.Parse(BitConverter.ToString(_cryptographyProvider.GetMD5Bytes(stream)).Replace("-", String.Empty)); + var check = Guid.Parse(BitConverter.ToString(_cryptographyProvider.ComputeMD5(stream)).Replace("-", String.Empty)); if (check != packageChecksum) { throw new Exception(string.Format("Download validation failed for {0}. Probably corrupted during transfer.", package.name)); diff --git a/MediaBrowser.Api/Dlna/DlnaServerService.cs b/MediaBrowser.Api/Dlna/DlnaServerService.cs index 93d0b3d551..8125951b5d 100644 --- a/MediaBrowser.Api/Dlna/DlnaServerService.cs +++ b/MediaBrowser.Api/Dlna/DlnaServerService.cs @@ -111,9 +111,9 @@ namespace MediaBrowser.Api.Dlna private readonly IMediaReceiverRegistrar _mediaReceiverRegistrar; private const string XMLContentType = "text/xml; charset=UTF-8"; - private readonly IMemoryStreamProvider _memoryStreamProvider; + private readonly IMemoryStreamFactory _memoryStreamProvider; - public DlnaServerService(IDlnaManager dlnaManager, IContentDirectory contentDirectory, IConnectionManager connectionManager, IMediaReceiverRegistrar mediaReceiverRegistrar, IMemoryStreamProvider memoryStreamProvider) + public DlnaServerService(IDlnaManager dlnaManager, IContentDirectory contentDirectory, IConnectionManager connectionManager, IMediaReceiverRegistrar mediaReceiverRegistrar, IMemoryStreamFactory memoryStreamProvider) { _dlnaManager = dlnaManager; _contentDirectory = contentDirectory; diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index c628892149..4fa663b194 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1263,6 +1263,7 @@ namespace MediaBrowser.Api.Playback private bool EnableThrottling(StreamState state) { + return false; // do not use throttling with hardware encoders return state.InputProtocol == MediaProtocol.File && state.RunTimeTicks.HasValue && diff --git a/MediaBrowser.Common/Extensions/BaseExtensions.cs b/MediaBrowser.Common/Extensions/BaseExtensions.cs index 09f6e8706b..d7f4424faa 100644 --- a/MediaBrowser.Common/Extensions/BaseExtensions.cs +++ b/MediaBrowser.Common/Extensions/BaseExtensions.cs @@ -10,7 +10,7 @@ namespace MediaBrowser.Common.Extensions /// public static class BaseExtensions { - public static ICryptographyProvider CryptographyProvider { get; set; } + public static ICryptoProvider CryptographyProvider { get; set; } /// /// Strips the HTML. diff --git a/MediaBrowser.Common/Net/INetworkManager.cs b/MediaBrowser.Common/Net/INetworkManager.cs index fe60c7ebfa..779db0a828 100644 --- a/MediaBrowser.Common/Net/INetworkManager.cs +++ b/MediaBrowser.Common/Net/INetworkManager.cs @@ -2,6 +2,7 @@ using MediaBrowser.Model.IO; using MediaBrowser.Model.Net; using System.Collections.Generic; using System.Net; +using System.Threading.Tasks; namespace MediaBrowser.Common.Net { @@ -46,10 +47,14 @@ namespace MediaBrowser.Common.Net /// true if [is in local network] [the specified endpoint]; otherwise, false. bool IsInLocalNetwork(string endpoint); + IEnumerable GetLocalIpAddresses(); + IpAddressInfo ParseIpAddress(string ipAddress); bool TryParseIpAddress(string ipAddress, out IpAddressInfo ipAddressInfo); + Task GetHostAddressesAsync(string host); + /// /// Generates a self signed certificate at the locatation specified by . /// diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index 2fd96577a8..d2cf23f43f 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -85,7 +85,7 @@ namespace MediaBrowser.Controller /// /// Gets the local API URL. /// - string GetLocalApiUrl(string ipAddress, bool isIpv6); + string GetLocalApiUrl(IpAddressInfo address); void LaunchUrl(string url); diff --git a/MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs b/MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs index 52199c5a21..8169cc7d9f 100644 --- a/MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs +++ b/MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs @@ -69,7 +69,8 @@ namespace MediaBrowser.Controller.MediaEncoding // if the audio language is not understood by the user, load their preferred subs, if there are any if (!ContainsOrdinal(preferredLanguages, audioTrackLanguage)) { - stream = streams.Where(s => !s.IsForced).FirstOrDefault(s => ContainsOrdinal(preferredLanguages, s.Language)); + stream = streams.Where(s => !s.IsForced).FirstOrDefault(s => ContainsOrdinal(preferredLanguages, s.Language)) ?? + streams.FirstOrDefault(s => ContainsOrdinal(preferredLanguages, s.Language)); } } else if (mode == SubtitlePlaybackMode.Always) diff --git a/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs b/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs index d45416f53f..b025011d7e 100644 --- a/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs +++ b/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs @@ -7,7 +7,7 @@ namespace MediaBrowser.Controller.Net { public class AuthenticatedAttribute : Attribute, IHasRequestFilter, IAuthenticationAttributes { - public IAuthService AuthService { get; set; } + public static IAuthService AuthService { get; set; } /// /// Gets or sets the roles. @@ -26,7 +26,7 @@ namespace MediaBrowser.Controller.Net /// /// true if [allow before startup wizard]; otherwise, false. public bool AllowBeforeStartupWizard { get; set; } - + /// /// The request filter is executed before the service. /// @@ -40,15 +40,6 @@ namespace MediaBrowser.Controller.Net AuthService.Authenticate(serviceRequest, this); } - /// - /// A new shallow copy of this filter is used on every request. - /// - /// IHasRequestFilter. - public IHasRequestFilter Copy() - { - return this; - } - /// /// Order in which Request Filters are executed. /// <0 Executed before global request filters @@ -60,7 +51,6 @@ namespace MediaBrowser.Controller.Net get { return 0; } } - public IEnumerable GetRoles() { return (Roles ?? string.Empty).Split(',') diff --git a/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs b/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs index ee7cb9dda9..bf7343f3d2 100644 --- a/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs +++ b/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using MediaBrowser.Model.IO; -using MediaBrowser.Model.TextEncoding; +using MediaBrowser.Model.Text; namespace MediaBrowser.MediaEncoding.BdInfo { @@ -15,9 +15,9 @@ namespace MediaBrowser.MediaEncoding.BdInfo public class BdInfoExaminer : IBlurayExaminer { private readonly IFileSystem _fileSystem; - private readonly IEncoding _textEncoding; + private readonly ITextEncoding _textEncoding; - public BdInfoExaminer(IFileSystem fileSystem, IEncoding textEncoding) + public BdInfoExaminer(IFileSystem fileSystem, ITextEncoding textEncoding) { _fileSystem = fileSystem; _textEncoding = textEncoding; diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 098cd14dbf..0d7a7912a4 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -79,7 +79,7 @@ namespace MediaBrowser.MediaEncoding.Encoder private readonly IHttpClient _httpClient; private readonly IZipClient _zipClient; private readonly IProcessFactory _processFactory; - private readonly IMemoryStreamProvider _memoryStreamProvider; + private readonly IMemoryStreamFactory _memoryStreamProvider; private readonly List _runningProcesses = new List(); private readonly bool _hasExternalEncoder; @@ -88,7 +88,7 @@ namespace MediaBrowser.MediaEncoding.Encoder private readonly int DefaultImageExtractionTimeoutMs; private readonly bool EnableEncoderFontFile; - public MediaEncoder(ILogger logger, IJsonSerializer jsonSerializer, string ffMpegPath, string ffProbePath, bool hasExternalEncoder, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ILiveTvManager liveTvManager, IIsoManager isoManager, ILibraryManager libraryManager, IChannelManager channelManager, ISessionManager sessionManager, Func subtitleEncoder, Func mediaSourceManager, IHttpClient httpClient, IZipClient zipClient, IMemoryStreamProvider memoryStreamProvider, IProcessFactory processFactory, + public MediaEncoder(ILogger logger, IJsonSerializer jsonSerializer, string ffMpegPath, string ffProbePath, bool hasExternalEncoder, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ILiveTvManager liveTvManager, IIsoManager isoManager, ILibraryManager libraryManager, IChannelManager channelManager, ISessionManager sessionManager, Func subtitleEncoder, Func mediaSourceManager, IHttpClient httpClient, IZipClient zipClient, IMemoryStreamFactory memoryStreamProvider, IProcessFactory processFactory, int defaultImageExtractionTimeoutMs, bool enableEncoderFontFile) { diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index f0c4c465d0..6a1583094c 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -23,9 +23,9 @@ namespace MediaBrowser.MediaEncoding.Probing private readonly CultureInfo _usCulture = new CultureInfo("en-US"); private readonly ILogger _logger; private readonly IFileSystem _fileSystem; - private readonly IMemoryStreamProvider _memoryStreamProvider; + private readonly IMemoryStreamFactory _memoryStreamProvider; - public ProbeResultNormalizer(ILogger logger, IFileSystem fileSystem, IMemoryStreamProvider memoryStreamProvider) + public ProbeResultNormalizer(ILogger logger, IFileSystem fileSystem, IMemoryStreamFactory memoryStreamProvider) { _logger = logger; _fileSystem = fileSystem; diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 0baee67eae..5d065f5283 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -19,7 +19,7 @@ using System.Threading; using System.Threading.Tasks; using MediaBrowser.Model.IO; using MediaBrowser.Model.Diagnostics; -using MediaBrowser.Model.TextEncoding; +using MediaBrowser.Model.Text; using UniversalDetector; namespace MediaBrowser.MediaEncoding.Subtitles @@ -34,11 +34,11 @@ namespace MediaBrowser.MediaEncoding.Subtitles private readonly IJsonSerializer _json; private readonly IHttpClient _httpClient; private readonly IMediaSourceManager _mediaSourceManager; - private readonly IMemoryStreamProvider _memoryStreamProvider; + private readonly IMemoryStreamFactory _memoryStreamProvider; private readonly IProcessFactory _processFactory; - private readonly IEncoding _textEncoding; + private readonly ITextEncoding _textEncoding; - public SubtitleEncoder(ILibraryManager libraryManager, ILogger logger, IApplicationPaths appPaths, IFileSystem fileSystem, IMediaEncoder mediaEncoder, IJsonSerializer json, IHttpClient httpClient, IMediaSourceManager mediaSourceManager, IMemoryStreamProvider memoryStreamProvider, IProcessFactory processFactory, IEncoding textEncoding) + public SubtitleEncoder(ILibraryManager libraryManager, ILogger logger, IApplicationPaths appPaths, IFileSystem fileSystem, IMediaEncoder mediaEncoder, IJsonSerializer json, IHttpClient httpClient, IMediaSourceManager mediaSourceManager, IMemoryStreamFactory memoryStreamProvider, IProcessFactory processFactory, ITextEncoding textEncoding) { _libraryManager = libraryManager; _logger = logger; diff --git a/MediaBrowser.Model/Cryptography/ICryptoProvider.cs b/MediaBrowser.Model/Cryptography/ICryptoProvider.cs new file mode 100644 index 0000000000..7a82dee52b --- /dev/null +++ b/MediaBrowser.Model/Cryptography/ICryptoProvider.cs @@ -0,0 +1,13 @@ +using System; +using System.IO; + +namespace MediaBrowser.Model.Cryptography +{ + public interface ICryptoProvider + { + Guid GetMD5(string str); + byte[] ComputeMD5(Stream str); + byte[] ComputeMD5(byte[] bytes); + byte[] ComputeSHA1(byte[] bytes); + } +} \ No newline at end of file diff --git a/MediaBrowser.Model/Cryptography/ICryptographyProvider.cs b/MediaBrowser.Model/Cryptography/ICryptographyProvider.cs deleted file mode 100644 index a3f86f9e28..0000000000 --- a/MediaBrowser.Model/Cryptography/ICryptographyProvider.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.IO; - -namespace MediaBrowser.Model.Cryptography -{ - public interface ICryptographyProvider - { - Guid GetMD5(string str); - byte[] GetMD5Bytes(string str); - byte[] GetSHA1Bytes(byte[] bytes); - byte[] GetMD5Bytes(Stream str); - byte[] GetMD5Bytes(byte[] bytes); - } -} \ No newline at end of file diff --git a/MediaBrowser.Model/IO/IMemoryStreamProvider.cs b/MediaBrowser.Model/IO/IMemoryStreamFactory.cs similarity index 64% rename from MediaBrowser.Model/IO/IMemoryStreamProvider.cs rename to MediaBrowser.Model/IO/IMemoryStreamFactory.cs index 82a758d9a1..f4f1746430 100644 --- a/MediaBrowser.Model/IO/IMemoryStreamProvider.cs +++ b/MediaBrowser.Model/IO/IMemoryStreamFactory.cs @@ -2,10 +2,11 @@ namespace MediaBrowser.Model.IO { - public interface IMemoryStreamProvider + public interface IMemoryStreamFactory { MemoryStream CreateNew(); MemoryStream CreateNew(int capacity); MemoryStream CreateNew(byte[] buffer); + bool TryGetBuffer(MemoryStream stream, out byte[] buffer); } } diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 52e477b1a0..ee75826198 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -100,7 +100,7 @@ - + @@ -138,17 +138,19 @@ + + - + - + diff --git a/MediaBrowser.Model/Net/ISocket.cs b/MediaBrowser.Model/Net/ISocket.cs new file mode 100644 index 0000000000..371fbc5675 --- /dev/null +++ b/MediaBrowser.Model/Net/ISocket.cs @@ -0,0 +1,16 @@ +using System; + +namespace MediaBrowser.Model.Net +{ + public interface ISocket : IDisposable + { + IpEndPointInfo LocalEndPoint { get; } + IpEndPointInfo RemoteEndPoint { get; } + void Close(); + void Shutdown(bool both); + void Listen(int backlog); + void Bind(IpEndPointInfo endpoint); + + void StartAccept(Action onAccept, Func isClosed); + } +} diff --git a/MediaBrowser.Model/Net/ISocketFactory.cs b/MediaBrowser.Model/Net/ISocketFactory.cs index 3f1ddf84f9..599292ddf8 100644 --- a/MediaBrowser.Model/Net/ISocketFactory.cs +++ b/MediaBrowser.Model/Net/ISocketFactory.cs @@ -27,5 +27,17 @@ namespace MediaBrowser.Model.Net /// The local port to bind to. /// A implementation. IUdpSocket CreateUdpMulticastSocket(string ipAddress, int multicastTimeToLive, int localPort); - } + + ISocket CreateSocket(IpAddressFamily family, SocketType socketType, ProtocolType protocolType, bool dualMode); + } + + public enum SocketType + { + Stream + } + + public enum ProtocolType + { + Tcp + } } diff --git a/MediaBrowser.Model/Net/IpAddressInfo.cs b/MediaBrowser.Model/Net/IpAddressInfo.cs index b48347d1d0..47ffe5118c 100644 --- a/MediaBrowser.Model/Net/IpAddressInfo.cs +++ b/MediaBrowser.Model/Net/IpAddressInfo.cs @@ -4,12 +4,39 @@ namespace MediaBrowser.Model.Net { public class IpAddressInfo { + public static IpAddressInfo Any = new IpAddressInfo("0.0.0.0", IpAddressFamily.InterNetwork); + public static IpAddressInfo IPv6Any = new IpAddressInfo("00000000000000000000", IpAddressFamily.InterNetworkV6); + public static IpAddressInfo Loopback = new IpAddressInfo("127.0.0.1", IpAddressFamily.InterNetwork); + public static IpAddressInfo IPv6Loopback = new IpAddressInfo("IPv6Loopback", IpAddressFamily.InterNetworkV6); + public string Address { get; set; } - public bool IsIpv6 { get; set; } + public IpAddressFamily AddressFamily { get; set; } + + public IpAddressInfo() + { + + } + + public IpAddressInfo(string address, IpAddressFamily addressFamily) + { + Address = address; + AddressFamily = addressFamily; + } + + public bool Equals(IpAddressInfo address) + { + return string.Equals(address.Address, Address, StringComparison.OrdinalIgnoreCase); + } public override String ToString() { return Address; } } + + public enum IpAddressFamily + { + InterNetwork, + InterNetworkV6 + } } diff --git a/MediaBrowser.Model/Net/IpEndPointInfo.cs b/MediaBrowser.Model/Net/IpEndPointInfo.cs index 5fd331a166..b5cadc4299 100644 --- a/MediaBrowser.Model/Net/IpEndPointInfo.cs +++ b/MediaBrowser.Model/Net/IpEndPointInfo.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; namespace MediaBrowser.Model.Net { @@ -8,11 +9,22 @@ namespace MediaBrowser.Model.Net public int Port { get; set; } + public IpEndPointInfo() + { + + } + + public IpEndPointInfo(IpAddressInfo address, int port) + { + IpAddress = address; + Port = port; + } + public override string ToString() { var ipAddresString = IpAddress == null ? string.Empty : IpAddress.ToString(); - return ipAddresString + ":" + this.Port.ToString(); + return ipAddresString + ":" + Port.ToString(CultureInfo.InvariantCulture); } } } diff --git a/MediaBrowser.Model/Services/IHasRequestFilter.cs b/MediaBrowser.Model/Services/IHasRequestFilter.cs index c5c6ccf592..2164179d50 100644 --- a/MediaBrowser.Model/Services/IHasRequestFilter.cs +++ b/MediaBrowser.Model/Services/IHasRequestFilter.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - + namespace MediaBrowser.Model.Services { public interface IHasRequestFilter @@ -22,11 +17,5 @@ namespace MediaBrowser.Model.Services /// The http response wrapper /// The request DTO void RequestFilter(IRequest req, IResponse res, object requestDto); - - /// - /// A new shallow copy of this filter is used on every request. - /// - /// - IHasRequestFilter Copy(); } } diff --git a/MediaBrowser.Model/Services/IHttpResult.cs b/MediaBrowser.Model/Services/IHttpResult.cs new file mode 100644 index 0000000000..36ffeb2847 --- /dev/null +++ b/MediaBrowser.Model/Services/IHttpResult.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading.Tasks; + +namespace MediaBrowser.Model.Services +{ + public interface IHttpResult : IHasHeaders + { + /// + /// The HTTP Response Status + /// + int Status { get; set; } + + /// + /// The HTTP Response Status Code + /// + HttpStatusCode StatusCode { get; set; } + + /// + /// The HTTP Status Description + /// + string StatusDescription { get; set; } + + /// + /// The HTTP Response ContentType + /// + string ContentType { get; set; } + + /// + /// Additional HTTP Cookies + /// + List Cookies { get; } + + /// + /// Response DTO + /// + object Response { get; set; } + + /// + /// Holds the request call context + /// + IRequest RequestContext { get; set; } + } +} diff --git a/MediaBrowser.Model/Services/IRequest.cs b/MediaBrowser.Model/Services/IRequest.cs index 45dc97b76c..5dc995b06f 100644 --- a/MediaBrowser.Model/Services/IRequest.cs +++ b/MediaBrowser.Model/Services/IRequest.cs @@ -60,16 +60,6 @@ namespace MediaBrowser.Model.Services QueryParamCollection QueryString { get; } QueryParamCollection FormData { get; } - /// - /// Buffer the Request InputStream so it can be re-read - /// - bool UseBufferedStream { get; set; } - - /// - /// The entire string contents of Request.InputStream - /// - /// - string GetRawBody(); string RawUrl { get; } diff --git a/MediaBrowser.Model/Services/QueryParamCollection.cs b/MediaBrowser.Model/Services/QueryParamCollection.cs index 1ab3f0bfb7..dfea628213 100644 --- a/MediaBrowser.Model/Services/QueryParamCollection.cs +++ b/MediaBrowser.Model/Services/QueryParamCollection.cs @@ -9,7 +9,7 @@ namespace MediaBrowser.Model.Services { public QueryParamCollection() { - + } public QueryParamCollection(IDictionary headers) @@ -30,15 +30,30 @@ namespace MediaBrowser.Model.Services return StringComparer.OrdinalIgnoreCase; } + public string GetKey(int index) + { + return this[index].Name; + } + + public string Get(int index) + { + return this[index].Value; + } + + public virtual string[] GetValues(int index) + { + return new[] { Get(index) }; + } + /// /// Adds a new query parameter. /// - public void Add(string key, string value) + public virtual void Add(string key, string value) { Add(new NameValuePair(key, value)); } - public void Set(string key, string value) + public virtual void Set(string key, string value) { if (string.IsNullOrWhiteSpace(value)) { @@ -81,17 +96,21 @@ namespace MediaBrowser.Model.Services /// /// The number of parameters that were removed /// is null. - public int Remove(string name) + public virtual int Remove(string name) { return RemoveAll(p => p.Name == name); } public string Get(string name) { - return GetValues(name).FirstOrDefault(); + var stringComparison = GetStringComparison(); + + return this.Where(p => string.Equals(p.Name, name, stringComparison)) + .Select(p => p.Value) + .FirstOrDefault(); } - public string[] GetValues(string name) + public virtual string[] GetValues(string name) { var stringComparison = GetStringComparison(); diff --git a/MediaBrowser.Model/Text/ITextEncoding.cs b/MediaBrowser.Model/Text/ITextEncoding.cs new file mode 100644 index 0000000000..6901f1f944 --- /dev/null +++ b/MediaBrowser.Model/Text/ITextEncoding.cs @@ -0,0 +1,10 @@ +using System.Text; + +namespace MediaBrowser.Model.Text +{ + public interface ITextEncoding + { + Encoding GetASCIIEncoding(); + Encoding GetFileEncoding(string path); + } +} diff --git a/MediaBrowser.Model/TextEncoding/IEncoding.cs b/MediaBrowser.Model/TextEncoding/IEncoding.cs deleted file mode 100644 index 3d884c9d2d..0000000000 --- a/MediaBrowser.Model/TextEncoding/IEncoding.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Text; - -namespace MediaBrowser.Model.TextEncoding -{ - public interface IEncoding - { - byte[] GetASCIIBytes(string text); - string GetASCIIString(byte[] bytes, int startIndex, int length); - - Encoding GetFileEncoding(string path); - } -} diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index d4bfad1742..59d67740d8 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -40,7 +40,7 @@ namespace MediaBrowser.Providers.Manager private readonly ILibraryMonitor _libraryMonitor; private readonly IFileSystem _fileSystem; private readonly ILogger _logger; - private readonly IMemoryStreamProvider _memoryStreamProvider; + private readonly IMemoryStreamFactory _memoryStreamProvider; /// /// Initializes a new instance of the class. @@ -49,7 +49,7 @@ namespace MediaBrowser.Providers.Manager /// The directory watchers. /// The file system. /// The logger. - public ImageSaver(IServerConfigurationManager config, ILibraryMonitor libraryMonitor, IFileSystem fileSystem, ILogger logger, IMemoryStreamProvider memoryStreamProvider) + public ImageSaver(IServerConfigurationManager config, ILibraryMonitor libraryMonitor, IFileSystem fileSystem, ILogger logger, IMemoryStreamFactory memoryStreamProvider) { _config = config; _libraryMonitor = libraryMonitor; diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 67ad21dbb3..5e00b356ae 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -66,7 +66,7 @@ namespace MediaBrowser.Providers.Manager private IExternalId[] _externalIds; private readonly Func _libraryManagerFactory; - private readonly IMemoryStreamProvider _memoryStreamProvider; + private readonly IMemoryStreamFactory _memoryStreamProvider; /// /// Initializes a new instance of the class. @@ -76,7 +76,7 @@ namespace MediaBrowser.Providers.Manager /// The directory watchers. /// The log manager. /// The file system. - public ProviderManager(IHttpClient httpClient, IServerConfigurationManager configurationManager, ILibraryMonitor libraryMonitor, ILogManager logManager, IFileSystem fileSystem, IServerApplicationPaths appPaths, Func libraryManagerFactory, IJsonSerializer json, IMemoryStreamProvider memoryStreamProvider) + public ProviderManager(IHttpClient httpClient, IServerConfigurationManager configurationManager, ILibraryMonitor libraryMonitor, ILogManager logManager, IFileSystem fileSystem, IServerApplicationPaths appPaths, Func libraryManagerFactory, IJsonSerializer json, IMemoryStreamFactory memoryStreamProvider) { _logger = logManager.GetLogger("ProviderManager"); _httpClient = httpClient; diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs index e4becec560..313feda52a 100644 --- a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs +++ b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs @@ -45,6 +45,11 @@ namespace MediaBrowser.Providers.MediaInfo var codec = Path.GetExtension(fullName).ToLower().TrimStart('.'); + if (string.Equals(codec, "txt", StringComparison.OrdinalIgnoreCase)) + { + codec = "srt"; + } + // If the subtitle file matches the video file name if (string.Equals(videoFileNameWithoutExtension, fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase)) { @@ -74,9 +79,9 @@ namespace MediaBrowser.Providers.MediaInfo // Try to translate to three character code // Be flexible and check against both the full and three character versions var culture = _localization.GetCultures() - .FirstOrDefault(i => string.Equals(i.DisplayName, language, StringComparison.OrdinalIgnoreCase) || - string.Equals(i.Name, language, StringComparison.OrdinalIgnoreCase) || - string.Equals(i.ThreeLetterISOLanguageName, language, StringComparison.OrdinalIgnoreCase) || + .FirstOrDefault(i => string.Equals(i.DisplayName, language, StringComparison.OrdinalIgnoreCase) || + string.Equals(i.Name, language, StringComparison.OrdinalIgnoreCase) || + string.Equals(i.ThreeLetterISOLanguageName, language, StringComparison.OrdinalIgnoreCase) || string.Equals(i.TwoLetterISOLanguageName, language, StringComparison.OrdinalIgnoreCase)); if (culture != null) @@ -119,7 +124,7 @@ namespace MediaBrowser.Providers.MediaInfo { get { - return new[] { ".srt", ".ssa", ".ass", ".sub", ".smi", ".sami" }; + return new[] { ".srt", ".ssa", ".ass", ".sub", ".smi", ".sami", ".txt" }; } } diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs index 66adf6c8af..5147e9d104 100644 --- a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs @@ -40,10 +40,10 @@ namespace MediaBrowser.Providers.TV private readonly CultureInfo _usCulture = new CultureInfo("en-US"); private readonly ILogger _logger; private readonly ILibraryManager _libraryManager; - private readonly IMemoryStreamProvider _memoryStreamProvider; + private readonly IMemoryStreamFactory _memoryStreamProvider; private readonly ILocalizationManager _localizationManager; - public TvdbSeriesProvider(IZipClient zipClient, IHttpClient httpClient, IFileSystem fileSystem, IServerConfigurationManager config, ILogger logger, ILibraryManager libraryManager, IMemoryStreamProvider memoryStreamProvider, IXmlReaderSettingsFactory xmlSettings, ILocalizationManager localizationManager) + public TvdbSeriesProvider(IZipClient zipClient, IHttpClient httpClient, IFileSystem fileSystem, IServerConfigurationManager config, ILogger logger, ILibraryManager libraryManager, IMemoryStreamFactory memoryStreamProvider, IXmlReaderSettingsFactory xmlSettings, ILocalizationManager localizationManager) { _zipClient = zipClient; _httpClient = httpClient; diff --git a/MediaBrowser.Server.Implementations/HttpServer/ContainerAdapter.cs b/MediaBrowser.Server.Implementations/HttpServer/ContainerAdapter.cs index 93d224b8db..235b62f69a 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/ContainerAdapter.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/ContainerAdapter.cs @@ -6,7 +6,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer /// /// Class ContainerAdapter /// - class ContainerAdapter : IContainerAdapter, IRelease + class ContainerAdapter : IContainerAdapter { /// /// The _app host @@ -40,14 +40,5 @@ namespace MediaBrowser.Server.Implementations.HttpServer { return _appHost.TryResolve(); } - - /// - /// Releases the specified instance. - /// - /// The instance. - public void Release(object instance) - { - // Leave this empty so SS doesn't try to dispose our objects - } } } diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index 805cb0353e..ebb282503e 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -8,24 +8,31 @@ using MediaBrowser.Server.Implementations.HttpServer.SocketSharp; using ServiceStack; using ServiceStack.Host; using ServiceStack.Host.Handlers; -using ServiceStack.Logging; using ServiceStack.Web; using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Net.Security; +using System.Net.Sockets; using System.Reflection; +using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; +using Emby.Common.Implementations.Net; using Emby.Server.Implementations.HttpServer; using Emby.Server.Implementations.HttpServer.SocketSharp; using MediaBrowser.Common.Net; using MediaBrowser.Common.Security; using MediaBrowser.Controller; +using MediaBrowser.Model.Cryptography; using MediaBrowser.Model.Extensions; using MediaBrowser.Model.IO; +using MediaBrowser.Model.Net; using MediaBrowser.Model.Services; -using ServiceStack.Api.Swagger; +using MediaBrowser.Model.Text; +using SocketHttpListener.Net; +using SocketHttpListener.Primitives; namespace MediaBrowser.Server.Implementations.HttpServer { @@ -49,21 +56,28 @@ namespace MediaBrowser.Server.Implementations.HttpServer private readonly IServerConfigurationManager _config; private readonly INetworkManager _networkManager; - private readonly IMemoryStreamProvider _memoryStreamProvider; + private readonly IMemoryStreamFactory _memoryStreamProvider; private readonly IServerApplicationHost _appHost; + private readonly ITextEncoding _textEncoding; + private readonly ISocketFactory _socketFactory; + private readonly ICryptoProvider _cryptoProvider; + public HttpListenerHost(IServerApplicationHost applicationHost, ILogManager logManager, IServerConfigurationManager config, string serviceName, - string defaultRedirectPath, INetworkManager networkManager, IMemoryStreamProvider memoryStreamProvider, params Assembly[] assembliesWithServices) - : base(serviceName, assembliesWithServices) + string defaultRedirectPath, INetworkManager networkManager, IMemoryStreamFactory memoryStreamProvider, ITextEncoding textEncoding, ISocketFactory socketFactory, ICryptoProvider cryptoProvider) + : base(serviceName, new Assembly[] { }) { _appHost = applicationHost; DefaultRedirectPath = defaultRedirectPath; _networkManager = networkManager; _memoryStreamProvider = memoryStreamProvider; + _textEncoding = textEncoding; + _socketFactory = socketFactory; + _cryptoProvider = cryptoProvider; _config = config; _logger = logManager.GetLogger("HttpServer"); @@ -73,10 +87,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer public string GlobalResponse { get; set; } - public override void Configure(Container container) + public override void Configure() { HostConfig.Instance.DefaultRedirectPath = DefaultRedirectPath; - HostConfig.Instance.LogUnobservedTaskExceptions = false; HostConfig.Instance.MapExceptionToStatusCode = new Dictionary { @@ -94,19 +107,12 @@ namespace MediaBrowser.Server.Implementations.HttpServer }; HostConfig.Instance.GlobalResponseHeaders = new Dictionary(); - HostConfig.Instance.DebugMode = false; - - HostConfig.Instance.LogFactory = LogManager.LogFactory; - HostConfig.Instance.AllowJsonpRequests = false; // The Markdown feature causes slow startup times (5 mins+) on cold boots for some users // Custom format allows images HostConfig.Instance.EnableFeatures = Feature.Html | Feature.Json | Feature.Xml | Feature.CustomFormat; - container.Adapter = _containerAdapter; - - Plugins.Add(new SwaggerFeature()); - Plugins.Add(new CorsFeature(allowedHeaders: "Content-Type, Authorization, Range, X-MediaBrowser-Token, X-Emby-Authorization")); + Container.Adapter = _containerAdapter; //Plugins.Add(new AuthFeature(() => new AuthUserSession(), new IAuthProvider[] { // new SessionAuthProvider(_containerAdapter.Resolve()), @@ -130,6 +136,14 @@ namespace MediaBrowser.Server.Implementations.HttpServer HostContext.GlobalResponseFilters.Add(new ResponseFilter(_logger).FilterResponse); } + protected override ILogger Logger + { + get + { + return _logger; + } + } + public override void OnAfterInit() { SetAppDomainData(); @@ -207,7 +221,33 @@ namespace MediaBrowser.Server.Implementations.HttpServer private IHttpListener GetListener() { - return new WebSocketSharpListener(_logger, CertificatePath, _memoryStreamProvider); + var cert = !string.IsNullOrWhiteSpace(CertificatePath) && File.Exists(CertificatePath) + ? GetCert(CertificatePath) : + null; + + return new WebSocketSharpListener(_logger, cert, _memoryStreamProvider, _textEncoding, _networkManager, _socketFactory, _cryptoProvider, new StreamFactory(), GetRequest); + } + + public static ICertificate GetCert(string certificateLocation) + { + X509Certificate2 localCert = new X509Certificate2(certificateLocation); + //localCert.PrivateKey = PrivateKey.CreateFromFile(pvk_file).RSA; + if (localCert.PrivateKey == null) + { + //throw new FileNotFoundException("Secure requested, no private key included", certificateLocation); + return null; + } + + return new Certificate(localCert); + } + + private IHttpRequest GetRequest(HttpListenerContext httpContext) + { + var operationName = httpContext.Request.GetOperationName(); + + var req = new WebSocketSharpRequest(httpContext, operationName, _logger, _memoryStreamProvider); + + return req; } private void OnWebSocketConnecting(WebSocketConnectingEventArgs args) @@ -259,11 +299,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer var contentType = httpReq.ResponseContentType; - var serializer = HostContext.ContentTypes.GetResponseSerializer(contentType); + var serializer = ContentTypes.Instance.GetResponseSerializer(contentType); if (serializer == null) { contentType = HostContext.Config.DefaultContentType; - serializer = HostContext.ContentTypes.GetResponseSerializer(contentType); + serializer = ContentTypes.Instance.GetResponseSerializer(contentType); } var httpError = ex as IHttpError; @@ -411,171 +451,170 @@ namespace MediaBrowser.Server.Implementations.HttpServer protected async Task RequestHandler(IHttpRequest httpReq, Uri url) { var date = DateTime.Now; - var httpRes = httpReq.Response; + bool enableLog = false; + string urlToLog = null; + string remoteIp = null; - if (_disposed) + try { - httpRes.StatusCode = 503; - httpRes.Close(); - return ; - } - - if (!ValidateHost(url)) - { - httpRes.StatusCode = 400; - httpRes.ContentType = "text/plain"; - httpRes.Write("Invalid host"); - - httpRes.Close(); - return; - } - - if (string.Equals(httpReq.Verb, "OPTIONS", StringComparison.OrdinalIgnoreCase)) - { - httpRes.StatusCode = 200; - httpRes.AddHeader("Access-Control-Allow-Origin", "*"); - httpRes.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, PATCH, OPTIONS"); - httpRes.AddHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Range, X-MediaBrowser-Token, X-Emby-Authorization"); - httpRes.ContentType = "text/html"; - - httpRes.Close(); - } - - var operationName = httpReq.OperationName; - var localPath = url.LocalPath; - - var urlString = url.OriginalString; - var enableLog = EnableLogging(urlString, localPath); - var urlToLog = urlString; - - if (enableLog) - { - urlToLog = GetUrlToLog(urlString); - LoggerUtils.LogRequest(_logger, urlToLog, httpReq.HttpMethod, httpReq.UserAgent); - } - - if (string.Equals(localPath, "/emby/", StringComparison.OrdinalIgnoreCase) || - string.Equals(localPath, "/mediabrowser/", StringComparison.OrdinalIgnoreCase)) - { - httpRes.RedirectToUrl(DefaultRedirectPath); - return; - } - if (string.Equals(localPath, "/emby", StringComparison.OrdinalIgnoreCase) || - string.Equals(localPath, "/mediabrowser", StringComparison.OrdinalIgnoreCase)) - { - httpRes.RedirectToUrl("emby/" + DefaultRedirectPath); - return; - } - - if (string.Equals(localPath, "/mediabrowser/", StringComparison.OrdinalIgnoreCase) || - string.Equals(localPath, "/mediabrowser", StringComparison.OrdinalIgnoreCase) || - localPath.IndexOf("mediabrowser/web", StringComparison.OrdinalIgnoreCase) != -1) - { - httpRes.StatusCode = 200; - httpRes.ContentType = "text/html"; - var newUrl = urlString.Replace("mediabrowser", "emby", StringComparison.OrdinalIgnoreCase) - .Replace("/dashboard/", "/web/", StringComparison.OrdinalIgnoreCase); - - if (!string.Equals(newUrl, urlString, StringComparison.OrdinalIgnoreCase)) + if (_disposed) { - httpRes.Write("EmbyPlease update your Emby bookmark to " + newUrl + ""); - - httpRes.Close(); + httpRes.StatusCode = 503; return; } - } - if (localPath.IndexOf("dashboard/", StringComparison.OrdinalIgnoreCase) != -1 && - localPath.IndexOf("web/dashboard", StringComparison.OrdinalIgnoreCase) == -1) - { - httpRes.StatusCode = 200; - httpRes.ContentType = "text/html"; - var newUrl = urlString.Replace("mediabrowser", "emby", StringComparison.OrdinalIgnoreCase) - .Replace("/dashboard/", "/web/", StringComparison.OrdinalIgnoreCase); - - if (!string.Equals(newUrl, urlString, StringComparison.OrdinalIgnoreCase)) + if (!ValidateHost(url)) { - httpRes.Write("EmbyPlease update your Emby bookmark to " + newUrl + ""); - - httpRes.Close(); + httpRes.StatusCode = 400; + httpRes.ContentType = "text/plain"; + httpRes.Write("Invalid host"); return; } - } - if (string.Equals(localPath, "/web", StringComparison.OrdinalIgnoreCase)) - { - httpRes.RedirectToUrl(DefaultRedirectPath); - return; - } - if (string.Equals(localPath, "/web/", StringComparison.OrdinalIgnoreCase)) - { - httpRes.RedirectToUrl("../" + DefaultRedirectPath); - return; - } - if (string.Equals(localPath, "/", StringComparison.OrdinalIgnoreCase)) - { - httpRes.RedirectToUrl(DefaultRedirectPath); - return; - } - if (string.IsNullOrEmpty(localPath)) - { - httpRes.RedirectToUrl("/" + DefaultRedirectPath); - return; - } + if (string.Equals(httpReq.Verb, "OPTIONS", StringComparison.OrdinalIgnoreCase)) + { + httpRes.StatusCode = 200; + httpRes.AddHeader("Access-Control-Allow-Origin", "*"); + httpRes.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, PATCH, OPTIONS"); + httpRes.AddHeader("Access-Control-Allow-Headers", + "Content-Type, Authorization, Range, X-MediaBrowser-Token, X-Emby-Authorization"); + httpRes.ContentType = "text/html"; + return; + } - if (string.Equals(localPath, "/emby/pin", StringComparison.OrdinalIgnoreCase)) - { - httpRes.RedirectToUrl("web/pin.html"); - return; + var operationName = httpReq.OperationName; + var localPath = url.LocalPath; + + var urlString = url.OriginalString; + enableLog = EnableLogging(urlString, localPath); + urlToLog = urlString; + + if (enableLog) + { + urlToLog = GetUrlToLog(urlString); + remoteIp = httpReq.RemoteIp; + + LoggerUtils.LogRequest(_logger, urlToLog, httpReq.HttpMethod, httpReq.UserAgent); + } + + if (string.Equals(localPath, "/emby/", StringComparison.OrdinalIgnoreCase) || + string.Equals(localPath, "/mediabrowser/", StringComparison.OrdinalIgnoreCase)) + { + RedirectToUrl(httpRes, DefaultRedirectPath); + return; + } + if (string.Equals(localPath, "/emby", StringComparison.OrdinalIgnoreCase) || + string.Equals(localPath, "/mediabrowser", StringComparison.OrdinalIgnoreCase)) + { + RedirectToUrl(httpRes, "emby/" + DefaultRedirectPath); + return; + } + + if (string.Equals(localPath, "/mediabrowser/", StringComparison.OrdinalIgnoreCase) || + string.Equals(localPath, "/mediabrowser", StringComparison.OrdinalIgnoreCase) || + localPath.IndexOf("mediabrowser/web", StringComparison.OrdinalIgnoreCase) != -1) + { + httpRes.StatusCode = 200; + httpRes.ContentType = "text/html"; + var newUrl = urlString.Replace("mediabrowser", "emby", StringComparison.OrdinalIgnoreCase) + .Replace("/dashboard/", "/web/", StringComparison.OrdinalIgnoreCase); + + if (!string.Equals(newUrl, urlString, StringComparison.OrdinalIgnoreCase)) + { + httpRes.Write( + "EmbyPlease update your Emby bookmark to " + newUrl + ""); + return; + } + } + + if (localPath.IndexOf("dashboard/", StringComparison.OrdinalIgnoreCase) != -1 && + localPath.IndexOf("web/dashboard", StringComparison.OrdinalIgnoreCase) == -1) + { + httpRes.StatusCode = 200; + httpRes.ContentType = "text/html"; + var newUrl = urlString.Replace("mediabrowser", "emby", StringComparison.OrdinalIgnoreCase) + .Replace("/dashboard/", "/web/", StringComparison.OrdinalIgnoreCase); + + if (!string.Equals(newUrl, urlString, StringComparison.OrdinalIgnoreCase)) + { + httpRes.Write( + "EmbyPlease update your Emby bookmark to " + newUrl + ""); + return; + } + } + + if (string.Equals(localPath, "/web", StringComparison.OrdinalIgnoreCase)) + { + RedirectToUrl(httpRes, DefaultRedirectPath); + return; + } + if (string.Equals(localPath, "/web/", StringComparison.OrdinalIgnoreCase)) + { + RedirectToUrl(httpRes, "../" + DefaultRedirectPath); + return; + } + if (string.Equals(localPath, "/", StringComparison.OrdinalIgnoreCase)) + { + RedirectToUrl(httpRes, DefaultRedirectPath); + return; + } + if (string.IsNullOrEmpty(localPath)) + { + RedirectToUrl(httpRes, "/" + DefaultRedirectPath); + return; + } + + if (string.Equals(localPath, "/emby/pin", StringComparison.OrdinalIgnoreCase)) + { + RedirectToUrl(httpRes, "web/pin.html"); + return; + } + + if (!string.IsNullOrWhiteSpace(GlobalResponse)) + { + httpRes.StatusCode = 503; + httpRes.ContentType = "text/html"; + httpRes.Write(GlobalResponse); + return; + } + + var handler = HttpHandlerFactory.GetHandler(httpReq); + + if (handler != null) + { + await handler.ProcessRequestAsync(httpReq, httpRes, operationName).ConfigureAwait(false); + } } - - if (!string.IsNullOrWhiteSpace(GlobalResponse)) + catch (Exception ex) + { + ErrorHandler(ex, httpReq); + } + finally { - httpRes.StatusCode = 503; - httpRes.ContentType = "text/html"; - httpRes.Write(GlobalResponse); - httpRes.Close(); - return; - } - var handler = HttpHandlerFactory.GetHandler(httpReq); - - var remoteIp = httpReq.RemoteIp; - - var serviceStackHandler = handler as IServiceStackHandler; - if (serviceStackHandler != null) - { - var restHandler = serviceStackHandler as RestHandler; - if (restHandler != null) + if (enableLog) { - httpReq.OperationName = operationName = restHandler.RestPath.RequestType.GetOperationName(); - } - - try - { - await serviceStackHandler.ProcessRequestAsync(httpReq, httpRes, operationName).ConfigureAwait(false); - } - finally - { - httpRes.Close(); var statusCode = httpRes.StatusCode; var duration = DateTime.Now - date; - if (enableLog) - { - LoggerUtils.LogResponse(_logger, statusCode, urlToLog, remoteIp, duration); - } + LoggerUtils.LogResponse(_logger, statusCode, urlToLog, remoteIp, duration); } } - else - { - httpRes.Close(); - } } + public static void RedirectToUrl(IResponse httpRes, string url) + { + httpRes.StatusCode = 302; + httpRes.AddHeader(HttpHeaders.Location, url); + httpRes.EndRequest(); + } + + /// /// Adds the rest handlers. /// @@ -653,15 +692,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer return "mediabrowser/" + path; } - /// - /// Releases the specified instance. - /// - /// The instance. - public override void Release(object instance) - { - // Leave this empty so SS doesn't try to dispose our objects - } - private bool _disposed; private readonly object _disposeLock = new object(); protected virtual void Dispose(bool disposing) @@ -696,4 +726,37 @@ namespace MediaBrowser.Server.Implementations.HttpServer Start(UrlPrefixes.First()); } } + + public class StreamFactory : IStreamFactory + { + public Stream CreateNetworkStream(ISocket socket, bool ownsSocket) + { + var netSocket = (NetSocket)socket; + + return new NetworkStream(netSocket.Socket, ownsSocket); + } + + public Task AuthenticateSslStreamAsServer(Stream stream, ICertificate certificate) + { + var sslStream = (SslStream)stream; + var cert = (Certificate)certificate; + + return sslStream.AuthenticateAsServerAsync(cert.X509Certificate); + } + + public Stream CreateSslStream(Stream innerStream, bool leaveInnerStreamOpen) + { + return new SslStream(innerStream, leaveInnerStreamOpen); + } + } + + public class Certificate : ICertificate + { + public Certificate(X509Certificate x509Certificate) + { + X509Certificate = x509Certificate; + } + + public X509Certificate X509Certificate { get; private set; } + } } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs index 95e1a35e6e..4c251ba24c 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs @@ -9,6 +9,7 @@ using System.IO; using System.Net; using System.Text; using System.Threading.Tasks; +using Emby.Server.Implementations.HttpServer; using MediaBrowser.Model.IO; using MediaBrowser.Model.Services; using ServiceStack; diff --git a/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs b/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs index 4dff2d5a3c..5da5159006 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs @@ -2,9 +2,11 @@ using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Net; +using MediaBrowser.Model.Cryptography; using MediaBrowser.Model.IO; using MediaBrowser.Model.Logging; -using ServiceStack.Logging; +using MediaBrowser.Model.Net; +using MediaBrowser.Model.Text; namespace MediaBrowser.Server.Implementations.HttpServer { @@ -21,13 +23,14 @@ namespace MediaBrowser.Server.Implementations.HttpServer ILogManager logManager, IServerConfigurationManager config, INetworkManager networkmanager, - IMemoryStreamProvider streamProvider, + IMemoryStreamFactory streamProvider, string serverName, - string defaultRedirectpath) + string defaultRedirectpath, + ITextEncoding textEncoding, + ISocketFactory socketFactory, + ICryptoProvider cryptoProvider) { - LogManager.LogFactory = new ServerLogFactory(logManager); - - return new HttpListenerHost(applicationHost, logManager, config, serverName, defaultRedirectpath, networkmanager, streamProvider); + return new HttpListenerHost(applicationHost, logManager, config, serverName, defaultRedirectpath, networkmanager, streamProvider, textEncoding, socketFactory, cryptoProvider); } } } diff --git a/MediaBrowser.Server.Implementations/HttpServer/ServerLogFactory.cs b/MediaBrowser.Server.Implementations/HttpServer/ServerLogFactory.cs deleted file mode 100644 index 40af3f3b05..0000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/ServerLogFactory.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using MediaBrowser.Model.Logging; -using ServiceStack.Logging; - -namespace MediaBrowser.Server.Implementations.HttpServer -{ - /// - /// Class ServerLogFactory - /// - public class ServerLogFactory : ILogFactory - { - /// - /// The _log manager - /// - private readonly ILogManager _logManager; - - /// - /// Initializes a new instance of the class. - /// - /// The log manager. - public ServerLogFactory(ILogManager logManager) - { - _logManager = logManager; - } - - /// - /// Gets the logger. - /// - /// Name of the type. - /// ILog. - public ILog GetLogger(string typeName) - { - return new ServerLogger(_logManager.GetLogger(typeName)); - } - - /// - /// Gets the logger. - /// - /// The type. - /// ILog. - public ILog GetLogger(Type type) - { - return GetLogger(type.Name); - } - } -} \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/HttpServer/ServerLogger.cs b/MediaBrowser.Server.Implementations/HttpServer/ServerLogger.cs deleted file mode 100644 index bf79247841..0000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/ServerLogger.cs +++ /dev/null @@ -1,194 +0,0 @@ -using MediaBrowser.Model.Logging; -using ServiceStack.Logging; -using System; - -namespace MediaBrowser.Server.Implementations.HttpServer -{ - /// - /// Class ServerLogger - /// - public class ServerLogger : ILog - { - /// - /// The _logger - /// - private readonly ILogger _logger; - - /// - /// Initializes a new instance of the class. - /// - /// The logger. - public ServerLogger(ILogger logger) - { - _logger = logger; - } - - /// - /// Logs a Debug message and exception. - /// - /// The message. - /// The exception. - public void Debug(object message, Exception exception) - { - _logger.ErrorException(GetMesssage(message), exception); - } - - /// - /// Logs a Debug message. - /// - /// The message. - public void Debug(object message) - { - // Way too verbose. Can always make this configurable if needed again. - //_logger.Debug(GetMesssage(message)); - } - - /// - /// Logs a Debug format message. - /// - /// The format. - /// The args. - public void DebugFormat(string format, params object[] args) - { - // Way too verbose. Can always make this configurable if needed again. - //_logger.Debug(format, args); - } - - /// - /// Logs a Error message and exception. - /// - /// The message. - /// The exception. - public void Error(object message, Exception exception) - { - _logger.ErrorException(GetMesssage(message), exception); - } - - /// - /// Logs a Error message. - /// - /// The message. - public void Error(object message) - { - _logger.Error(GetMesssage(message)); - } - - /// - /// Logs a Error format message. - /// - /// The format. - /// The args. - public void ErrorFormat(string format, params object[] args) - { - _logger.Error(format, args); - } - - /// - /// Logs a Fatal message and exception. - /// - /// The message. - /// The exception. - public void Fatal(object message, Exception exception) - { - _logger.FatalException(GetMesssage(message), exception); - } - - /// - /// Logs a Fatal message. - /// - /// The message. - public void Fatal(object message) - { - _logger.Fatal(GetMesssage(message)); - } - - /// - /// Logs a Error format message. - /// - /// The format. - /// The args. - public void FatalFormat(string format, params object[] args) - { - _logger.Fatal(format, args); - } - - /// - /// Logs an Info message and exception. - /// - /// The message. - /// The exception. - public void Info(object message, Exception exception) - { - _logger.ErrorException(GetMesssage(message), exception); - } - - /// - /// Logs an Info message and exception. - /// - /// The message. - public void Info(object message) - { - _logger.Info(GetMesssage(message)); - } - - /// - /// Logs an Info format message. - /// - /// The format. - /// The args. - public void InfoFormat(string format, params object[] args) - { - _logger.Info(format, args); - } - - /// - /// Gets or sets a value indicating whether this instance is debug enabled. - /// - /// true if this instance is debug enabled; otherwise, false. - public bool IsDebugEnabled - { - get { return true; } - } - - /// - /// Logs a Warning message and exception. - /// - /// The message. - /// The exception. - public void Warn(object message, Exception exception) - { - _logger.ErrorException(GetMesssage(message), exception); - } - - /// - /// Logs a Warning message. - /// - /// The message. - public void Warn(object message) - { - // Hide StringMapTypeDeserializer messages - // _logger.Warn(GetMesssage(message)); - } - - /// - /// Logs a Warning format message. - /// - /// The format. - /// The args. - public void WarnFormat(string format, params object[] args) - { - // Hide StringMapTypeDeserializer messages - // _logger.Warn(format, args); - } - - /// - /// Gets the messsage. - /// - /// The o. - /// System.String. - private string GetMesssage(object o) - { - return o == null ? string.Empty : o.ToString(); - } - } -} diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/Extensions.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/Extensions.cs deleted file mode 100644 index 154313fb90..0000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/Extensions.cs +++ /dev/null @@ -1,28 +0,0 @@ -using MediaBrowser.Model.Logging; -using SocketHttpListener.Net; -using System; - -namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp -{ - public static class Extensions - { - public static string GetOperationName(this HttpListenerRequest request) - { - return request.Url.Segments[request.Url.Segments.Length - 1]; - } - - public static void CloseOutputStream(this HttpListenerResponse response, ILogger logger) - { - try - { - response.OutputStream.Flush(); - response.OutputStream.Close(); - response.Close(); - } - catch (Exception ex) - { - logger.ErrorException("Error in HttpListenerResponseWrapper: " + ex.Message, ex); - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/RequestMono.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/RequestMono.cs index 13ae48cff3..543eb4afe2 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/RequestMono.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/RequestMono.cs @@ -2,11 +2,10 @@ using System.Collections.Specialized; using System.Globalization; using System.IO; +using System.Net; using System.Text; using System.Threading.Tasks; -using System.Web; using MediaBrowser.Model.Services; -using ServiceStack; namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp { @@ -128,7 +127,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp { get { - return string.IsNullOrEmpty(request.Headers[HttpHeaders.Accept]) ? null : request.Headers[HttpHeaders.Accept]; + return string.IsNullOrEmpty(request.Headers["Accept"]) ? null : request.Headers["Accept"]; } } @@ -136,7 +135,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp { get { - return string.IsNullOrEmpty(request.Headers[HttpHeaders.Authorization]) ? null : request.Headers[HttpHeaders.Authorization]; + return string.IsNullOrEmpty(request.Headers["Authorization"]) ? null : request.Headers["Authorization"]; } } @@ -152,7 +151,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp string msg = String.Format("A potentially dangerous Request.{0} value was " + "detected from the client ({1}={2}).", name, key, v); - throw new HttpRequestValidationException(msg); + throw new Exception(msg); } static void ValidateNameValueCollection(string name, QueryParamCollection coll) @@ -278,9 +277,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp void AddRawKeyValue(StringBuilder key, StringBuilder value) { - string decodedKey = HttpUtility.UrlDecode(key.ToString(), ContentEncoding); + string decodedKey = WebUtility.UrlDecode(key.ToString()); form.Add(decodedKey, - HttpUtility.UrlDecode(value.ToString(), ContentEncoding)); + WebUtility.UrlDecode(value.ToString())); key.Length = 0; value.Length = 0; diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs index 72047609d9..6f44fcce75 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs @@ -1,17 +1,14 @@ using System; using System.Collections.Generic; -using System.Collections.Specialized; using System.IO; using System.Text; using Emby.Server.Implementations.HttpServer.SocketSharp; using Funq; -using MediaBrowser.Common.IO; using MediaBrowser.Model.IO; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Services; using ServiceStack; using ServiceStack.Host; -using ServiceStack.Web; using SocketHttpListener.Net; using IHttpFile = MediaBrowser.Model.Services.IHttpFile; using IHttpRequest = MediaBrowser.Model.Services.IHttpRequest; @@ -25,9 +22,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp public Container Container { get; set; } private readonly HttpListenerRequest request; private readonly IHttpResponse response; - private readonly IMemoryStreamProvider _memoryStreamProvider; + private readonly IMemoryStreamFactory _memoryStreamProvider; - public WebSocketSharpRequest(HttpListenerContext httpContext, string operationName, RequestAttributes requestAttributes, ILogger logger, IMemoryStreamProvider memoryStreamProvider) + public WebSocketSharpRequest(HttpListenerContext httpContext, string operationName, ILogger logger, IMemoryStreamFactory memoryStreamProvider) { this.OperationName = operationName; _memoryStreamProvider = memoryStreamProvider; @@ -55,36 +52,10 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp get { return response; } } - public T TryResolve() - { - if (typeof(T) == typeof(IHttpRequest)) - throw new Exception("You don't need to use IHttpRequest.TryResolve to resolve itself"); - - if (typeof(T) == typeof(IHttpResponse)) - throw new Exception("Resolve IHttpResponse with 'Response' property instead of IHttpRequest.TryResolve"); - - return Container == null - ? HostContext.TryResolve() - : Container.TryResolve(); - } - public string OperationName { get; set; } public object Dto { get; set; } - public string GetRawBody() - { - if (bufferedStream != null) - { - return bufferedStream.ToArray().FromUtf8Bytes(); - } - - using (var reader = new StreamReader(InputStream)) - { - return reader.ReadToEnd(); - } - } - public string RawUrl { get { return request.RawUrl; } @@ -104,7 +75,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp { get { - return String.IsNullOrEmpty(request.Headers[HttpHeaders.XForwardedFor]) ? null : request.Headers[HttpHeaders.XForwardedFor]; + return String.IsNullOrEmpty(request.Headers["X-Forwarded-For"]) ? null : request.Headers["X-Forwarded-For"]; } } @@ -112,7 +83,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp { get { - return string.IsNullOrEmpty(request.Headers[HttpHeaders.XForwardedPort]) ? (int?)null : int.Parse(request.Headers[HttpHeaders.XForwardedPort]); + return string.IsNullOrEmpty(request.Headers["X-Forwarded-Port"]) ? (int?)null : int.Parse(request.Headers["X-Forwarded-Port"]); } } @@ -120,7 +91,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp { get { - return string.IsNullOrEmpty(request.Headers[HttpHeaders.XForwardedProtocol]) ? null : request.Headers[HttpHeaders.XForwardedProtocol]; + return string.IsNullOrEmpty(request.Headers["X-Forwarded-Proto"]) ? null : request.Headers["X-Forwarded-Proto"]; } } @@ -128,7 +99,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp { get { - return String.IsNullOrEmpty(request.Headers[HttpHeaders.XRealIp]) ? null : request.Headers[HttpHeaders.XRealIp]; + return String.IsNullOrEmpty(request.Headers["X-Real-IP"]) ? null : request.Headers["X-Real-IP"]; } } @@ -140,7 +111,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp return remoteIp ?? (remoteIp = (CheckBadChars(XForwardedFor)) ?? (NormalizeIp(CheckBadChars(XRealIp)) ?? - (request.RemoteEndPoint != null ? NormalizeIp(request.RemoteEndPoint.Address.ToString()) : null))); + (request.RemoteEndPoint != null ? NormalizeIp(request.RemoteEndPoint.IpAddress.ToString()) : null))); } } @@ -280,7 +251,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp defaultContentType = HostContext.Config.DefaultContentType; } - var customContentTypes = HostContext.ContentTypes.ContentTypeFormats.Values; + var customContentTypes = ContentTypes.Instance.ContentTypeFormats.Values; var preferredContentTypes = new string[] {}; var acceptsAnything = false; @@ -328,11 +299,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp } } - if (httpReq.ContentType.MatchesContentType(MimeTypes.Soap12)) - { - return MimeTypes.Soap12; - } - if (acceptContentTypes == null && httpReq.ContentType == MimeTypes.Soap11) { return MimeTypes.Soap11; @@ -344,10 +310,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp private static string GetQueryStringContentType(IRequest httpReq) { - var callback = httpReq.QueryString[Keywords.Callback]; - if (!string.IsNullOrEmpty(callback)) return MimeTypes.Json; - - var format = httpReq.QueryString[Keywords.Format]; + var format = httpReq.QueryString["format"]; if (format == null) { const int formatMaxLength = 4; @@ -359,12 +322,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp } format = format.LeftPart('.').ToLower(); - if (format.Contains("json")) return MimeTypes.Json; + if (format.Contains("json")) return "application/json"; if (format.Contains("xml")) return MimeTypes.Xml; - if (format.Contains("jsv")) return MimeTypes.Jsv; string contentType; - HostContext.ContentTypes.ContentTypeFormats.TryGetValue(format, out contentType); + ContentTypes.Instance.ContentTypeFormats.TryGetValue(format, out contentType); return contentType; } @@ -474,10 +436,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp get { return request.UserAgent; } } - private QueryParamCollection headers; public QueryParamCollection Headers { - get { return headers ?? (headers = ToQueryParams(request.Headers)); } + get { return request.Headers; } } private QueryParamCollection queryString; @@ -492,18 +453,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp get { return formData ?? (formData = this.Form); } } - private QueryParamCollection ToQueryParams(NameValueCollection collection) - { - var result = new QueryParamCollection(); - - foreach (var key in collection.AllKeys) - { - result[key] = collection[key]; - } - - return result; - } - public bool IsLocal { get { return request.IsLocal; } @@ -563,21 +512,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp } } - public bool UseBufferedStream - { - get { return bufferedStream != null; } - set - { - bufferedStream = value - ? bufferedStream ?? _memoryStreamProvider.CreateNew(request.InputStream.ReadFully()) - : null; - } - } - - private MemoryStream bufferedStream; public Stream InputStream { - get { return bufferedStream ?? request.InputStream; } + get { return request.InputStream; } } public long ContentLength @@ -613,7 +550,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp } } - static Stream GetSubStream(Stream stream, IMemoryStreamProvider streamProvider) + static Stream GetSubStream(Stream stream, IMemoryStreamFactory streamProvider) { if (stream is MemoryStream) { @@ -654,4 +591,13 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp return pathInfo; } } + + public class HttpFile : IHttpFile + { + public string Name { get; set; } + public string FileName { get; set; } + public long ContentLength { get; set; } + public string ContentType { get; set; } + public Stream InputStream { get; set; } + } } diff --git a/MediaBrowser.Server.Implementations/IO/MemoryStreamProvider.cs b/MediaBrowser.Server.Implementations/IO/MemoryStreamProvider.cs index 0a0a04d5d6..cb62ffa980 100644 --- a/MediaBrowser.Server.Implementations/IO/MemoryStreamProvider.cs +++ b/MediaBrowser.Server.Implementations/IO/MemoryStreamProvider.cs @@ -4,7 +4,7 @@ using Microsoft.IO; namespace MediaBrowser.Server.Implementations.IO { - public class RecyclableMemoryStreamProvider : IMemoryStreamProvider + public class RecyclableMemoryStreamProvider : IMemoryStreamFactory { readonly RecyclableMemoryStreamManager _manager = new RecyclableMemoryStreamManager(); @@ -22,9 +22,15 @@ namespace MediaBrowser.Server.Implementations.IO { return _manager.GetStream("RecyclableMemoryStream", buffer, 0, buffer.Length); } + + public bool TryGetBuffer(MemoryStream stream, out byte[] buffer) + { + buffer = stream.GetBuffer(); + return true; + } } - public class MemoryStreamProvider : IMemoryStreamProvider + public class MemoryStreamProvider : IMemoryStreamFactory { public MemoryStream CreateNew() { @@ -40,5 +46,11 @@ namespace MediaBrowser.Server.Implementations.IO { return new MemoryStream(buffer); } + + public bool TryGetBuffer(MemoryStream stream, out byte[] buffer) + { + buffer = stream.GetBuffer(); + return true; + } } } diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 42e2e0d7b9..4096d71dc6 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -69,16 +69,12 @@ ..\packages\Patterns.Logging.1.0.0.6\lib\portable-net45+win8\Patterns.Logging.dll True - - ..\ThirdParty\ServiceStack\ServiceStack.Api.Swagger.dll - False ..\ThirdParty\SharpCompress\SharpCompress.dll - - ..\packages\SocketHttpListener.1.0.0.44\lib\net45\SocketHttpListener.dll - True + + ..\ThirdParty\emby\SocketHttpListener.Portable.dll @@ -88,7 +84,6 @@ - ..\ThirdParty\ServiceStack\ServiceStack.dll @@ -119,18 +114,9 @@ - - - - - - - - - diff --git a/MediaBrowser.Server.Implementations/Persistence/DataExtensions.cs b/MediaBrowser.Server.Implementations/Persistence/DataExtensions.cs index 86ecbd24d9..179101ca29 100644 --- a/MediaBrowser.Server.Implementations/Persistence/DataExtensions.cs +++ b/MediaBrowser.Server.Implementations/Persistence/DataExtensions.cs @@ -55,7 +55,7 @@ namespace MediaBrowser.Server.Implementations.Persistence /// /// Stream. /// reader - public static Stream GetMemoryStream(this IDataReader reader, int ordinal, IMemoryStreamProvider streamProvider) + public static Stream GetMemoryStream(this IDataReader reader, int ordinal, IMemoryStreamFactory streamProvider) { if (reader == null) { @@ -134,7 +134,7 @@ namespace MediaBrowser.Server.Implementations.Persistence /// /// System.Byte[][]. /// obj - public static byte[] SerializeToBytes(this IJsonSerializer json, object obj, IMemoryStreamProvider streamProvider) + public static byte[] SerializeToBytes(this IJsonSerializer json, object obj, IMemoryStreamFactory streamProvider) { if (obj == null) { diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs index 3d20cad36c..c97ba87927 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs @@ -20,9 +20,9 @@ namespace MediaBrowser.Server.Implementations.Persistence /// public class SqliteDisplayPreferencesRepository : BaseSqliteRepository, IDisplayPreferencesRepository { - private readonly IMemoryStreamProvider _memoryStreamProvider; + private readonly IMemoryStreamFactory _memoryStreamProvider; - public SqliteDisplayPreferencesRepository(ILogManager logManager, IJsonSerializer jsonSerializer, IApplicationPaths appPaths, IDbConnector dbConnector, IMemoryStreamProvider memoryStreamProvider) + public SqliteDisplayPreferencesRepository(ILogManager logManager, IJsonSerializer jsonSerializer, IApplicationPaths appPaths, IDbConnector dbConnector, IMemoryStreamFactory memoryStreamProvider) : base(logManager, dbConnector) { _jsonSerializer = jsonSerializer; diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 5fcd38f87d..3577d1883e 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -99,12 +99,12 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _updateInheritedTagsCommand; public const int LatestSchemaVersion = 109; - private readonly IMemoryStreamProvider _memoryStreamProvider; + private readonly IMemoryStreamFactory _memoryStreamProvider; /// /// Initializes a new instance of the class. /// - public SqliteItemRepository(IServerConfigurationManager config, IJsonSerializer jsonSerializer, ILogManager logManager, IDbConnector connector, IMemoryStreamProvider memoryStreamProvider) + public SqliteItemRepository(IServerConfigurationManager config, IJsonSerializer jsonSerializer, ILogManager logManager, IDbConnector connector, IMemoryStreamFactory memoryStreamProvider) : base(logManager, connector) { if (config == null) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs index c3cf4acc44..0c1367e0a2 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs @@ -20,9 +20,9 @@ namespace MediaBrowser.Server.Implementations.Persistence public class SqliteUserRepository : BaseSqliteRepository, IUserRepository { private readonly IJsonSerializer _jsonSerializer; - private readonly IMemoryStreamProvider _memoryStreamProvider; + private readonly IMemoryStreamFactory _memoryStreamProvider; - public SqliteUserRepository(ILogManager logManager, IServerApplicationPaths appPaths, IJsonSerializer jsonSerializer, IDbConnector dbConnector, IMemoryStreamProvider memoryStreamProvider) : base(logManager, dbConnector) + public SqliteUserRepository(ILogManager logManager, IServerApplicationPaths appPaths, IJsonSerializer jsonSerializer, IDbConnector dbConnector, IMemoryStreamFactory memoryStreamProvider) : base(logManager, dbConnector) { _jsonSerializer = jsonSerializer; _memoryStreamProvider = memoryStreamProvider; diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index 909246f689..84a5d5a1d8 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -5,6 +5,5 @@ - \ No newline at end of file diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index fd84940dd5..c0f184befe 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -126,7 +126,7 @@ using MediaBrowser.Model.Reflection; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Services; using MediaBrowser.Model.Social; -using MediaBrowser.Model.TextEncoding; +using MediaBrowser.Model.Text; using MediaBrowser.Model.Xml; using MediaBrowser.Server.Implementations.Archiving; using MediaBrowser.Server.Implementations.Serialization; @@ -252,6 +252,8 @@ namespace MediaBrowser.Server.Startup.Common /// The zip client. protected IZipClient ZipClient { get; private set; } + protected IAuthService AuthService { get; private set; } + private readonly StartupOptions _startupOptions; private readonly string _releaseAssetFilename; @@ -410,7 +412,7 @@ namespace MediaBrowser.Server.Startup.Common LogManager.RemoveConsoleOutput(); } - protected override IMemoryStreamProvider CreateMemoryStreamProvider() + protected override IMemoryStreamFactory CreateMemoryStreamProvider() { if (Environment.OSVersion.Platform == PlatformID.Win32NT) { @@ -555,7 +557,7 @@ namespace MediaBrowser.Server.Startup.Common StringExtensions.LocalizationManager = LocalizationManager; RegisterSingleInstance(LocalizationManager); - IEncoding textEncoding = new TextEncoding(FileSystemManager); + ITextEncoding textEncoding = new TextEncoding(FileSystemManager); RegisterSingleInstance(textEncoding); Utilities.EncodingHelper = textEncoding; RegisterSingleInstance(() => new BdInfoExaminer(FileSystemManager, textEncoding)); @@ -601,7 +603,7 @@ namespace MediaBrowser.Server.Startup.Common RegisterSingleInstance(() => new SearchEngine(LogManager, LibraryManager, UserManager)); - HttpServer = ServerFactory.CreateServer(this, LogManager, ServerConfigurationManager, NetworkManager, MemoryStreamProvider, "Emby", "web/index.html"); + HttpServer = ServerFactory.CreateServer(this, LogManager, ServerConfigurationManager, NetworkManager, MemoryStreamProvider, "Emby", "web/index.html", textEncoding, SocketFactory, CryptographyProvider); HttpServer.GlobalResponse = LocalizationManager.GetLocalizedString("StartupEmbyServerIsLoading"); RegisterSingleInstance(HttpServer, false); progress.Report(10); @@ -702,7 +704,9 @@ namespace MediaBrowser.Server.Startup.Common var authContext = new AuthorizationContext(AuthenticationRepository, ConnectManager); RegisterSingleInstance(authContext); RegisterSingleInstance(new SessionContext(UserManager, authContext, SessionManager)); - RegisterSingleInstance(new AuthService(UserManager, authContext, ServerConfigurationManager, ConnectManager, SessionManager, DeviceManager)); + + AuthService = new AuthService(UserManager, authContext, ServerConfigurationManager, ConnectManager, SessionManager, DeviceManager); + RegisterSingleInstance(AuthService); SubtitleEncoder = new SubtitleEncoder(LibraryManager, LogManager.GetLogger("SubtitleEncoder"), ApplicationPaths, FileSystemManager, MediaEncoder, JsonSerializer, HttpClient, MediaSourceManager, MemoryStreamProvider, ProcessFactory, textEncoding); RegisterSingleInstance(SubtitleEncoder); @@ -900,6 +904,7 @@ namespace MediaBrowser.Server.Startup.Common BaseStreamingService.AppHost = this; BaseStreamingService.HttpClient = HttpClient; Utilities.CryptographyProvider = CryptographyProvider; + AuthenticatedAttribute.AuthService = AuthService; } /// @@ -1291,7 +1296,7 @@ namespace MediaBrowser.Server.Startup.Common try { // Return the first matched address, if found, or the first known local address - var address = (await GetLocalIpAddressesInternal().ConfigureAwait(false)).FirstOrDefault(i => !IPAddress.IsLoopback(i)); + var address = (await GetLocalIpAddresses().ConfigureAwait(false)).FirstOrDefault(i => !i.Equals(IpAddressInfo.Loopback) && !i.Equals(IpAddressInfo.IPv6Loopback)); if (address != null) { @@ -1308,19 +1313,14 @@ namespace MediaBrowser.Server.Startup.Common return null; } - public string GetLocalApiUrl(IPAddress ipAddress) + public string GetLocalApiUrl(IpAddressInfo ipAddress) { - return GetLocalApiUrl(ipAddress.ToString(), ipAddress.AddressFamily == AddressFamily.InterNetworkV6); - } - - public string GetLocalApiUrl(string ipAddress, bool isIpv6) - { - if (isIpv6) + if (ipAddress.AddressFamily == IpAddressFamily.InterNetworkV6) { - return GetLocalApiUrl("[" + ipAddress + "]"); + return GetLocalApiUrl("[" + ipAddress.Address + "]"); } - return GetLocalApiUrl(ipAddress); + return GetLocalApiUrl(ipAddress.Address); } public string GetLocalApiUrl(string host) @@ -1332,23 +1332,8 @@ namespace MediaBrowser.Server.Startup.Common public async Task> GetLocalIpAddresses() { - var list = await GetLocalIpAddressesInternal().ConfigureAwait(false); - - return list.Select(i => new IpAddressInfo - { - Address = i.ToString(), - IsIpv6 = i.AddressFamily == AddressFamily.InterNetworkV6 - - }).ToList(); - } - - private async Task> GetLocalIpAddressesInternal() - { - // Need to do this until Common will compile with this method - var nativeNetworkManager = (BaseNetworkManager)NetworkManager; - - var addresses = nativeNetworkManager.GetLocalIpAddresses().ToList(); - var list = new List(); + var addresses = NetworkManager.GetLocalIpAddresses().ToList(); + var list = new List(); foreach (var address in addresses) { @@ -1364,9 +1349,10 @@ namespace MediaBrowser.Server.Startup.Common private readonly ConcurrentDictionary _validAddressResults = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); private DateTime _lastAddressCacheClear; - private async Task IsIpAddressValidAsync(IPAddress address) + private async Task IsIpAddressValidAsync(IpAddressInfo address) { - if (IPAddress.IsLoopback(address)) + if (address.Equals(IpAddressInfo.Loopback) || + address.Equals(IpAddressInfo.IPv6Loopback)) { return true; } diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index e813c0a0aa..7b949fcb14 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common - 3.0.684 + 3.0.688 Emby.Common Emby Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index 9b0c10cbbd..96986de9ba 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Server.Core - 3.0.684 + 3.0.688 Emby.Server.Core Emby Team ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains core components required to build plugins for Emby Server. Copyright © Emby 2013 - + diff --git a/OpenSubtitlesHandler/Utilities.cs b/OpenSubtitlesHandler/Utilities.cs index b2ad2d0f1d..3fe606c782 100644 --- a/OpenSubtitlesHandler/Utilities.cs +++ b/OpenSubtitlesHandler/Utilities.cs @@ -24,7 +24,7 @@ using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Net; using MediaBrowser.Model.Cryptography; -using MediaBrowser.Model.TextEncoding; +using MediaBrowser.Model.Text; namespace OpenSubtitlesHandler { @@ -33,9 +33,9 @@ namespace OpenSubtitlesHandler /// public sealed class Utilities { - public static ICryptographyProvider CryptographyProvider { get; set; } + public static ICryptoProvider CryptographyProvider { get; set; } public static IHttpClient HttpClient { get; set; } - public static IEncoding EncodingHelper { get; set; } + public static ITextEncoding EncodingHelper { get; set; } private const string XML_RPC_SERVER = "https://api.opensubtitles.org/xml-rpc"; @@ -124,13 +124,13 @@ namespace OpenSubtitlesHandler data.Add((byte)r); } var bytes = data.ToArray(); - return EncodingHelper.GetASCIIString(bytes, 0, bytes.Length); + return EncodingHelper.GetASCIIEncoding().GetString(bytes, 0, bytes.Length); } } public static byte[] GetASCIIBytes(string text) { - return EncodingHelper.GetASCIIBytes(text); + return EncodingHelper.GetASCIIEncoding().GetBytes(text); } ///