Browse Source

update portable projects

Luke Pulverenti 8 years ago
parent
commit
a8b340cbb2
84 changed files with 1044 additions and 910 deletions
  1. 2 2
      BDInfo/BDROM.cs
  2. 5 5
      BDInfo/TSPlaylistFile.cs
  3. 7 7
      BDInfo/TSStreamClipFile.cs
  4. 5 5
      Emby.Common.Implementations/BaseApplicationHost.cs
  5. 5 12
      Emby.Common.Implementations/Cryptography/CryptographyProvider.cs
  6. 2 2
      Emby.Common.Implementations/HttpClientManager/HttpClientManager.cs
  7. 85 0
      Emby.Common.Implementations/Net/NetSocket.cs
  8. 111 0
      Emby.Common.Implementations/Net/SocketAcceptor.cs
  9. 25 12
      Emby.Common.Implementations/Net/SocketFactory.cs
  10. 2 10
      Emby.Common.Implementations/Net/UdpSocket.cs
  11. 77 14
      Emby.Common.Implementations/Networking/BaseNetworkManager.cs
  12. 4 9
      Emby.Common.Implementations/TextEncoding/TextEncoding.cs
  13. 2 4
      Emby.Dlna/Main/DlnaEntryPoint.cs
  14. 6 5
      Emby.Dlna/PlayTo/PlayToManager.cs
  15. 4 4
      Emby.Server.Implementations/Connect/ConnectEntryPoint.cs
  16. 1 1
      Emby.Server.Implementations/Connect/ConnectManager.cs
  17. 10 0
      Emby.Server.Implementations/Emby.Server.Implementations.csproj
  18. 1 1
      Emby.Server.Implementations/HttpServer/LoggerUtils.cs
  19. 1 7
      Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs
  20. 14 12
      Emby.Server.Implementations/HttpServer/ResponseFilter.cs
  21. 12 0
      Emby.Server.Implementations/HttpServer/SocketSharp/Extensions.cs
  22. 1 7
      Emby.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs
  23. 49 62
      Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs
  24. 58 6
      Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs
  25. 3 3
      Emby.Server.Implementations/Library/UserManager.cs
  26. 5 5
      Emby.Server.Implementations/Security/MBLicenseFile.cs
  27. 2 2
      Emby.Server.Implementations/Security/PluginSecurityManager.cs
  28. 4 4
      Emby.Server.Implementations/ServerManager/ServerManager.cs
  29. 5 5
      Emby.Server.Implementations/ServerManager/WebSocketConnection.cs
  30. 3 3
      Emby.Server.Implementations/Sync/MediaSync.cs
  31. 2 2
      Emby.Server.Implementations/Sync/MultiProviderSync.cs
  32. 2 2
      Emby.Server.Implementations/Sync/ServerSyncScheduledTask.cs
  33. 2 2
      Emby.Server.Implementations/Sync/SyncManager.cs
  34. 2 2
      Emby.Server.Implementations/Sync/TargetDataProvider.cs
  35. 3 3
      Emby.Server.Implementations/Updates/InstallationManager.cs
  36. 2 2
      MediaBrowser.Api/Dlna/DlnaServerService.cs
  37. 1 0
      MediaBrowser.Api/Playback/BaseStreamingService.cs
  38. 1 1
      MediaBrowser.Common/Extensions/BaseExtensions.cs
  39. 5 0
      MediaBrowser.Common/Net/INetworkManager.cs
  40. 1 1
      MediaBrowser.Controller/IServerApplicationHost.cs
  41. 2 1
      MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs
  42. 2 12
      MediaBrowser.Controller/Net/AuthenticatedAttribute.cs
  43. 3 3
      MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs
  44. 2 2
      MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
  45. 2 2
      MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
  46. 4 4
      MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
  47. 13 0
      MediaBrowser.Model/Cryptography/ICryptoProvider.cs
  48. 0 14
      MediaBrowser.Model/Cryptography/ICryptographyProvider.cs
  49. 2 1
      MediaBrowser.Model/IO/IMemoryStreamFactory.cs
  50. 5 3
      MediaBrowser.Model/MediaBrowser.Model.csproj
  51. 16 0
      MediaBrowser.Model/Net/ISocket.cs
  52. 13 1
      MediaBrowser.Model/Net/ISocketFactory.cs
  53. 28 1
      MediaBrowser.Model/Net/IpAddressInfo.cs
  54. 13 1
      MediaBrowser.Model/Net/IpEndPointInfo.cs
  55. 1 12
      MediaBrowser.Model/Services/IHasRequestFilter.cs
  56. 47 0
      MediaBrowser.Model/Services/IHttpResult.cs
  57. 0 10
      MediaBrowser.Model/Services/IRequest.cs
  58. 25 6
      MediaBrowser.Model/Services/QueryParamCollection.cs
  59. 10 0
      MediaBrowser.Model/Text/ITextEncoding.cs
  60. 0 12
      MediaBrowser.Model/TextEncoding/IEncoding.cs
  61. 2 2
      MediaBrowser.Providers/Manager/ImageSaver.cs
  62. 2 2
      MediaBrowser.Providers/Manager/ProviderManager.cs
  63. 9 4
      MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs
  64. 2 2
      MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs
  65. 1 10
      MediaBrowser.Server.Implementations/HttpServer/ContainerAdapter.cs
  66. 217 154
      MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
  67. 1 0
      MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs
  68. 9 6
      MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs
  69. 0 46
      MediaBrowser.Server.Implementations/HttpServer/ServerLogFactory.cs
  70. 0 194
      MediaBrowser.Server.Implementations/HttpServer/ServerLogger.cs
  71. 0 28
      MediaBrowser.Server.Implementations/HttpServer/SocketSharp/Extensions.cs
  72. 6 7
      MediaBrowser.Server.Implementations/HttpServer/SocketSharp/RequestMono.cs
  73. 23 77
      MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs
  74. 14 2
      MediaBrowser.Server.Implementations/IO/MemoryStreamProvider.cs
  75. 2 16
      MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
  76. 2 2
      MediaBrowser.Server.Implementations/Persistence/DataExtensions.cs
  77. 2 2
      MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs
  78. 2 2
      MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
  79. 2 2
      MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs
  80. 0 1
      MediaBrowser.Server.Implementations/packages.config
  81. 20 34
      MediaBrowser.Server.Startup.Common/ApplicationHost.cs
  82. 1 1
      Nuget/MediaBrowser.Common.nuspec
  83. 2 2
      Nuget/MediaBrowser.Server.Core.nuspec
  84. 5 5
      OpenSubtitlesHandler/Utilities.cs

+ 2 - 2
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;
             //

+ 5 - 5
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<TSStreamClip> clips, IFileSystem fileSystem, IEncoding textEncoding)
+            List<TSStreamClip> 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;
 

+ 7 - 7
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<ushort,TSStream>();
 
         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}",

+ 5 - 5
Emby.Common.Implementations/BaseApplicationHost.cs

@@ -170,7 +170,7 @@ namespace Emby.Common.Implementations
         /// <value><c>true</c> if this instance is running as service; otherwise, <c>false</c>.</value>
         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; }
 
         /// <summary>
         /// 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<string>();
 
@@ -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)

+ 5 - 12
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())
             {

+ 2 - 2
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;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="HttpClientManager" /> class.
@@ -53,7 +53,7 @@ namespace Emby.Common.Implementations.HttpClientManager
         /// <exception cref="System.ArgumentNullException">appPaths
         /// or
         /// logger</exception>
-        public HttpClientManager(IApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem, IMemoryStreamProvider memoryStreamProvider)
+        public HttpClientManager(IApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem, IMemoryStreamFactory memoryStreamProvider)
         {
             if (appPaths == null)
             {

+ 85 - 0
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<ISocket> onAccept, Func<bool> isClosed)
+        {
+            _acceptor = new SocketAcceptor(_logger, Socket, onAccept, isClosed);
+
+            _acceptor.StartAccept();
+        }
+
+        public void Dispose()
+        {
+            Socket.Dispose();
+        }
+    }
+}

+ 111 - 0
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<bool> _isClosed;
+        private readonly Action<ISocket> _onAccept;
+
+        public SocketAcceptor(ILogger logger, Socket originalSocket, Action<ISocket> onAccept, Func<bool> 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<SocketAsyncEventArgs>(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);
+            }
+        }
+    }
+}

+ 25 - 12
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
         /// </summary>
         private IPAddress _LocalIP;
 
-        /// <summary>
-        /// Default constructor.
-        /// </summary>
-        /// <param name="localIP">A string containing the IP address of the local network adapter to bind sockets to. Null or empty string will use <see cref="IPAddress.Any"/>.</param>
-        public SocketFactory(string localIP)
+        private ILogger _logger;
+
+        public SocketFactory(ILogger logger)
+        {
+            _logger = logger;
+            _LocalIP = IPAddress.Any;
+        }
+
+        public ISocket CreateSocket(IpAddressFamily family, MediaBrowser.Model.Net.SocketType socketType, MediaBrowser.Model.Net.ProtocolType protocolType, bool dualMode)
         {
-            if (String.IsNullOrEmpty(localIP))
-                _LocalIP = IPAddress.Any;
-            else
-                _LocalIP = IPAddress.Parse(localIP);
+            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
             {

+ 2 - 10
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)

+ 77 - 14
Emby.Common.Implementations/Networking/BaseNetworkManager.cs

@@ -22,14 +22,10 @@ namespace Emby.Common.Implementations.Networking
             Logger = logger;
         }
 
-        private List<IPAddress> _localIpAddresses;
+        private List<IpAddressInfo> _localIpAddresses;
         private readonly object _localIpAddressSyncLock = new object();
 
-        /// <summary>
-        /// Gets the machine's local ip address
-        /// </summary>
-        /// <returns>IPAddress.</returns>
-		public IEnumerable<IPAddress> GetLocalIpAddresses()
+        public IEnumerable<IpAddressInfo> 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<IpAddressInfo[]> GetHostAddressesAsync(string host)
+        {
+            var addresses = await Dns.GetHostAddressesAsync(host).ConfigureAwait(false);
+            return addresses.Select(ToIpAddressInfo).ToArray();
+        }
     }
 }

+ 4 - 9
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)

+ 2 - 4
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
                 {

+ 6 - 5
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<string> GetServerAddress(string ipAddress, bool isIpv6)
+        private Task<string> 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()

+ 4 - 4
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;

+ 1 - 1
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 + "]";
                     }

+ 10 - 0
Emby.Server.Implementations/Emby.Server.Implementations.csproj

@@ -68,11 +68,18 @@
     <Compile Include="FileOrganization\OrganizerScheduledTask.cs" />
     <Compile Include="FileOrganization\TvFolderOrganizer.cs" />
     <Compile Include="HttpServer\GetSwaggerResource.cs" />
+    <Compile Include="HttpServer\LoggerUtils.cs" />
+    <Compile Include="HttpServer\RangeRequestWriter.cs" />
+    <Compile Include="HttpServer\ResponseFilter.cs" />
+    <Compile Include="HttpServer\SocketSharp\Extensions.cs" />
     <Compile Include="HttpServer\SocketSharp\HttpUtility.cs" />
     <Compile Include="HttpServer\IHttpListener.cs" />
     <Compile Include="HttpServer\Security\AuthorizationContext.cs" />
     <Compile Include="HttpServer\Security\AuthService.cs" />
     <Compile Include="HttpServer\Security\SessionContext.cs" />
+    <Compile Include="HttpServer\SocketSharp\SharpWebSocket.cs" />
+    <Compile Include="HttpServer\SocketSharp\WebSocketSharpListener.cs" />
+    <Compile Include="HttpServer\SocketSharp\WebSocketSharpResponse.cs" />
     <Compile Include="HttpServer\StreamWriter.cs" />
     <Compile Include="HttpServer\SwaggerService.cs" />
     <Compile Include="Images\BaseDynamicImageProvider.cs" />
@@ -254,6 +261,9 @@
       <Project>{442b5058-dcaf-4263-bb6a-f21e31120a1b}</Project>
       <Name>MediaBrowser.Providers</Name>
     </ProjectReference>
+    <Reference Include="SocketHttpListener.Portable">
+      <HintPath>..\ThirdParty\emby\SocketHttpListener.Portable.dll</HintPath>
+    </Reference>
     <Reference Include="UniversalDetector, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
       <HintPath>..\packages\UniversalDetector.1.0.1\lib\portable-net45+sl4+wp71+win8+wpa81\UniversalDetector.dll</HintPath>
       <Private>True</Private>

+ 1 - 1
MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs → 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
     {

+ 1 - 7
MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs → 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
         /// </summary>
         private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
 
-        public Func<IDisposable> ResultScope { get; set; }
         public List<Cookie> Cookies { get; private set; }
 
         /// <summary>
@@ -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; }
     }
 }

+ 14 - 12
MediaBrowser.Server.Implementations/HttpServer/ResponseFilter.cs → 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;
-
-                        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;
-                        }
+                        //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 (sharpResponse != null)
                         {

+ 12 - 0
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];
+        }
+    }
+}

+ 1 - 7
MediaBrowser.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs → 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();
 
-        /// <summary>
-        /// Initializes a new instance of the <see cref="NativeWebSocket" /> class.
-        /// </summary>
-        /// <param name="socket">The socket.</param>
-        /// <param name="logger">The logger.</param>
-        /// <exception cref="System.ArgumentNullException">socket</exception>
         public SharpWebSocket(SocketHttpListener.WebSocket socket, ILogger logger)
         {
             if (socket == null)

+ 49 - 62
MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs → 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;
-
-        public WebSocketSharpListener(ILogger logger, string certificatePath, 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<HttpListenerContext, IHttpRequest> _httpRequestFactory;
+
+        public WebSocketSharpListener(ILogger logger, ICertificate certificate, IMemoryStreamFactory memoryStreamProvider, ITextEncoding textEncoding, INetworkManager networkManager, ISocketFactory socketFactory, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, Func<HttpListenerContext, IHttpRequest> httpRequestFactory)
         {
             _logger = logger;
-            _certificatePath = certificatePath;
+            _certificate = certificate;
             _memoryStreamProvider = memoryStreamProvider;
+            _textEncoding = textEncoding;
+            _networkManager = networkManager;
+            _socketFactory = socketFactory;
+            _cryptoProvider = cryptoProvider;
+            _streamFactory = streamFactory;
+            _httpRequestFactory = httpRequestFactory;
         }
 
         public Action<Exception, IRequest> ErrorHandler { get; set; }
-
         public Func<IHttpRequest, Uri, Task> RequestHandler { get; set; }
 
         public Action<WebSocketConnectingEventArgs> WebSocketConnecting { get; set; }
@@ -41,7 +53,12 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
         public void Start(IEnumerable<string> 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);
-            }
-        }
-
-        private Task ProcessRequestAsync(HttpListenerContext context)
-        {
-            var request = context.Request;
-
-            if (request.IsWebSocketRequest)
-            {
-                LoggerUtils.LogRequest(_logger, request);
+                _logger.ErrorException("Error processing request", ex);
 
-                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
             }
         }
     }
+
 }

+ 58 - 6
MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs → 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; }

+ 3 - 3
Emby.Server.Implementations/Library/UserManager.cs

@@ -70,10 +70,10 @@ namespace Emby.Server.Implementations.Library
         private readonly Func<IConnectManager> _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<IImageProcessor> imageProcessorFactory, Func<IDtoService> dtoServiceFactory, Func<IConnectManager> connectFactory, IServerApplicationHost appHost, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ICryptographyProvider cryptographyProvider, string defaultUserName)
+        public UserManager(ILogger logger, IServerConfigurationManager configurationManager, IUserRepository userRepository, IXmlSerializer xmlSerializer, INetworkManager networkManager, Func<IImageProcessor> imageProcessorFactory, Func<IDtoService> dtoServiceFactory, Func<IConnectManager> connectFactory, IServerApplicationHost appHost, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ICryptoProvider cryptographyProvider, string defaultUserName)
         {
             _logger = logger;
             UserRepository = userRepository;
@@ -334,7 +334,7 @@ namespace Emby.Server.Implementations.Library
         /// <returns>System.String.</returns>
         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);
         }
 
         /// <summary>

+ 5 - 5
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;

+ 2 - 2
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<IRequiresRegistration> _registeredEntities;
         protected IEnumerable<IRequiresRegistration> RegisteredEntities
@@ -79,7 +79,7 @@ namespace Emby.Server.Implementations.Security
         /// Initializes a new instance of the <see cref="PluginSecurityManager" /> class.
         /// </summary>
         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)
             {

+ 4 - 4
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<IWebSocketListener> _webSocketListeners = new List<IWebSocketListener>();
 
         private bool _disposed;
-        private readonly IMemoryStreamProvider _memoryStreamProvider;
-        private readonly IEncoding _textEncoding;
+        private readonly IMemoryStreamFactory _memoryStreamProvider;
+        private readonly ITextEncoding _textEncoding;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="ServerManager" /> class.
@@ -86,7 +86,7 @@ namespace Emby.Server.Implementations.ServerManager
         /// <param name="logger">The logger.</param>
         /// <param name="configurationManager">The configuration manager.</param>
         /// <exception cref="System.ArgumentNullException">applicationHost</exception>
-        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)
             {

+ 5 - 5
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
         /// </summary>
         /// <value>The query string.</value>
         public QueryParamCollection QueryString { get; set; }
-        private readonly IMemoryStreamProvider _memoryStreamProvider;
-        private readonly IEncoding _textEncoding;
+        private readonly IMemoryStreamFactory _memoryStreamProvider;
+        private readonly ITextEncoding _textEncoding;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="WebSocketConnection" /> class.
@@ -88,7 +88,7 @@ namespace Emby.Server.Implementations.ServerManager
         /// <param name="jsonSerializer">The json serializer.</param>
         /// <param name="logger">The logger.</param>
         /// <exception cref="System.ArgumentNullException">socket</exception>
-        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)

+ 3 - 3
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)

+ 2 - 2
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;

+ 2 - 2
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;

+ 2 - 2
Emby.Server.Implementations/Sync/SyncManager.cs

@@ -51,7 +51,7 @@ namespace Emby.Server.Implementations.Sync
         private readonly Func<IMediaSourceManager> _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<GenericEventArgs<SyncJobItem>> SyncJobItemUpdated;
         public event EventHandler<GenericEventArgs<SyncJobItem>> SyncJobItemCreated;
 
-        public SyncManager(ILibraryManager libraryManager, ISyncRepository repo, IImageProcessor imageProcessor, ILogger logger, IUserManager userManager, Func<IDtoService> dtoService, IServerApplicationHost appHost, ITVSeriesManager tvSeriesManager, Func<IMediaEncoder> mediaEncoder, IFileSystem fileSystem, Func<ISubtitleEncoder> subtitleEncoder, IConfigurationManager config, IUserDataManager userDataManager, Func<IMediaSourceManager> mediaSourceManager, IJsonSerializer json, ITaskManager taskManager, IMemoryStreamProvider memoryStreamProvider)
+        public SyncManager(ILibraryManager libraryManager, ISyncRepository repo, IImageProcessor imageProcessor, ILogger logger, IUserManager userManager, Func<IDtoService> dtoService, IServerApplicationHost appHost, ITVSeriesManager tvSeriesManager, Func<IMediaEncoder> mediaEncoder, IFileSystem fileSystem, Func<ISubtitleEncoder> subtitleEncoder, IConfigurationManager config, IUserDataManager userDataManager, Func<IMediaSourceManager> mediaSourceManager, IJsonSerializer json, ITaskManager taskManager, IMemoryStreamFactory memoryStreamProvider)
         {
             _libraryManager = libraryManager;
             _repo = repo;

+ 2 - 2
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;

+ 3 - 3
Emby.Server.Implementations/Updates/InstallationManager.cs

@@ -119,9 +119,9 @@ namespace Emby.Server.Implementations.Updates
         /// <value>The application host.</value>
         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));

+ 2 - 2
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;

+ 1 - 0
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 &&

+ 1 - 1
MediaBrowser.Common/Extensions/BaseExtensions.cs

@@ -10,7 +10,7 @@ namespace MediaBrowser.Common.Extensions
     /// </summary>
     public static class BaseExtensions
     {
-        public static ICryptographyProvider CryptographyProvider { get; set; }
+        public static ICryptoProvider CryptographyProvider { get; set; }
 
         /// <summary>
         /// Strips the HTML.

+ 5 - 0
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
         /// <returns><c>true</c> if [is in local network] [the specified endpoint]; otherwise, <c>false</c>.</returns>
         bool IsInLocalNetwork(string endpoint);
 
+        IEnumerable<IpAddressInfo> GetLocalIpAddresses();
+
         IpAddressInfo ParseIpAddress(string ipAddress);
 
         bool TryParseIpAddress(string ipAddress, out IpAddressInfo ipAddressInfo);
 
+        Task<IpAddressInfo[]> GetHostAddressesAsync(string host);
+
         /// <summary>
         /// Generates a self signed certificate at the locatation specified by <paramref name="certificatePath"/>.
         /// </summary>

+ 1 - 1
MediaBrowser.Controller/IServerApplicationHost.cs

@@ -85,7 +85,7 @@ namespace MediaBrowser.Controller
         /// <summary>
         /// Gets the local API URL.
         /// </summary>
-        string GetLocalApiUrl(string ipAddress, bool isIpv6);
+        string GetLocalApiUrl(IpAddressInfo address);
 
         void LaunchUrl(string url);
 

+ 2 - 1
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)

+ 2 - 12
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; }
 
         /// <summary>
         /// Gets or sets the roles.
@@ -26,7 +26,7 @@ namespace MediaBrowser.Controller.Net
         /// </summary>
         /// <value><c>true</c> if [allow before startup wizard]; otherwise, <c>false</c>.</value>
         public bool AllowBeforeStartupWizard { get; set; }
-        
+
         /// <summary>
         /// The request filter is executed before the service.
         /// </summary>
@@ -40,15 +40,6 @@ namespace MediaBrowser.Controller.Net
             AuthService.Authenticate(serviceRequest, this);
         }
 
-        /// <summary>
-        /// A new shallow copy of this filter is used on every request.
-        /// </summary>
-        /// <returns>IHasRequestFilter.</returns>
-        public IHasRequestFilter Copy()
-        {
-            return this;
-        }
-
         /// <summary>
         /// Order in which Request Filters are executed.
         /// &lt;0 Executed before global request filters
@@ -60,7 +51,6 @@ namespace MediaBrowser.Controller.Net
             get { return 0; }
         }
 
-
         public IEnumerable<string> GetRoles()
         {
             return (Roles ?? string.Empty).Split(',')

+ 3 - 3
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;

+ 2 - 2
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<ProcessWrapper> _runningProcesses = new List<ProcessWrapper>();
         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<ISubtitleEncoder> subtitleEncoder, Func<IMediaSourceManager> 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<ISubtitleEncoder> subtitleEncoder, Func<IMediaSourceManager> mediaSourceManager, IHttpClient httpClient, IZipClient zipClient, IMemoryStreamFactory memoryStreamProvider, IProcessFactory processFactory, 
             int defaultImageExtractionTimeoutMs, 
             bool enableEncoderFontFile)
         {

+ 2 - 2
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;

+ 4 - 4
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;

+ 13 - 0
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);
+    }
+}

+ 0 - 14
MediaBrowser.Model/Cryptography/ICryptographyProvider.cs

@@ -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);
-    }
-}

+ 2 - 1
MediaBrowser.Model/IO/IMemoryStreamProvider.cs → 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);
     }
 }

+ 5 - 3
MediaBrowser.Model/MediaBrowser.Model.csproj

@@ -100,7 +100,7 @@
     <Compile Include="Connect\PinExchangeResult.cs" />
     <Compile Include="Connect\PinStatusResult.cs" />
     <Compile Include="Connect\UserLinkType.cs" />
-    <Compile Include="Cryptography\ICryptographyProvider.cs" />
+    <Compile Include="Cryptography\ICryptoProvider.cs" />
     <Compile Include="Devices\DeviceOptions.cs" />
     <Compile Include="Devices\DeviceQuery.cs" />
     <Compile Include="Devices\LocalFileInfo.cs" />
@@ -138,17 +138,19 @@
     <Compile Include="Dto\NameIdPair.cs" />
     <Compile Include="Dto\NameValuePair.cs" />
     <Compile Include="Net\IpEndPointInfo.cs" />
+    <Compile Include="Net\ISocket.cs" />
     <Compile Include="Net\ISocketFactory.cs" />
     <Compile Include="Net\IUdpSocket.cs" />
     <Compile Include="Net\SocketReceiveResult.cs" />
+    <Compile Include="Services\IHttpResult.cs" />
     <Compile Include="System\IEnvironmentInfo.cs" />
-    <Compile Include="TextEncoding\IEncoding.cs" />
+    <Compile Include="Text\ITextEncoding.cs" />
     <Compile Include="Extensions\LinqExtensions.cs" />
     <Compile Include="FileOrganization\SmartMatchInfo.cs" />
     <Compile Include="Health\IHealthMonitor.cs" />
     <Compile Include="IO\FileSystemMetadata.cs" />
     <Compile Include="IO\IFileSystem.cs" />
-    <Compile Include="IO\IMemoryStreamProvider.cs" />
+    <Compile Include="IO\IMemoryStreamFactory.cs" />
     <Compile Include="IO\IShortcutHandler.cs" />
     <Compile Include="IO\StreamDefaults.cs" />
     <Compile Include="Globalization\ILocalizationManager.cs" />

+ 16 - 0
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<ISocket> onAccept, Func<bool> isClosed);
+    }
+}

+ 13 - 1
MediaBrowser.Model/Net/ISocketFactory.cs

@@ -27,5 +27,17 @@ namespace MediaBrowser.Model.Net
         /// <param name="localPort">The local port to bind to.</param>
         /// <returns>A <see cref="IUdpSocket"/> implementation.</returns>
         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
+    }
 }

+ 28 - 1
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
+    }
 }

+ 13 - 1
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);
         }
     }
 }

+ 1 - 12
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
         /// <param name="res">The http response wrapper</param>
         /// <param name="requestDto">The request DTO</param>
         void RequestFilter(IRequest req, IResponse res, object requestDto);
-
-        /// <summary>
-        /// A new shallow copy of this filter is used on every request.
-        /// </summary>
-        /// <returns></returns>
-        IHasRequestFilter Copy();
     }
 }

+ 47 - 0
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
+    {
+        /// <summary>
+        /// The HTTP Response Status
+        /// </summary>
+        int Status { get; set; }
+
+        /// <summary>
+        /// The HTTP Response Status Code
+        /// </summary>
+        HttpStatusCode StatusCode { get; set; }
+
+        /// <summary>
+        /// The HTTP Status Description
+        /// </summary>
+        string StatusDescription { get; set; }
+
+        /// <summary>
+        /// The HTTP Response ContentType
+        /// </summary>
+        string ContentType { get; set; }
+
+        /// <summary>
+        /// Additional HTTP Cookies
+        /// </summary>
+        List<Cookie> Cookies { get; }
+
+        /// <summary>
+        /// Response DTO
+        /// </summary>
+        object Response { get; set; }
+
+        /// <summary>
+        /// Holds the request call context
+        /// </summary>
+        IRequest RequestContext { get; set; }
+    }
+}

+ 0 - 10
MediaBrowser.Model/Services/IRequest.cs

@@ -60,16 +60,6 @@ namespace MediaBrowser.Model.Services
         QueryParamCollection QueryString { get; }
 
         QueryParamCollection FormData { get; }
-        /// <summary>
-        /// Buffer the Request InputStream so it can be re-read
-        /// </summary>
-        bool UseBufferedStream { get; set; }
-
-        /// <summary>
-        /// The entire string contents of Request.InputStream
-        /// </summary>
-        /// <returns></returns>
-        string GetRawBody();
 
         string RawUrl { get; }
 

+ 25 - 6
MediaBrowser.Model/Services/QueryParamCollection.cs

@@ -9,7 +9,7 @@ namespace MediaBrowser.Model.Services
     {
         public QueryParamCollection()
         {
-            
+
         }
 
         public QueryParamCollection(IDictionary<string, string> 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) };
+        }
+
         /// <summary>
         /// Adds a new query parameter.
         /// </summary>
-        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
         /// </summary>
         /// <returns>The number of parameters that were removed</returns>
         /// <exception cref="ArgumentNullException"><paramref name="name" /> is null.</exception>
-        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();
 

+ 10 - 0
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);
+    }
+}

+ 0 - 12
MediaBrowser.Model/TextEncoding/IEncoding.cs

@@ -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);
-    }
-}

+ 2 - 2
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;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="ImageSaver" /> class.
@@ -49,7 +49,7 @@ namespace MediaBrowser.Providers.Manager
         /// <param name="libraryMonitor">The directory watchers.</param>
         /// <param name="fileSystem">The file system.</param>
         /// <param name="logger">The logger.</param>
-        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;

+ 2 - 2
MediaBrowser.Providers/Manager/ProviderManager.cs

@@ -66,7 +66,7 @@ namespace MediaBrowser.Providers.Manager
         private IExternalId[] _externalIds;
 
         private readonly Func<ILibraryManager> _libraryManagerFactory;
-        private readonly IMemoryStreamProvider _memoryStreamProvider;
+        private readonly IMemoryStreamFactory _memoryStreamProvider;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="ProviderManager" /> class.
@@ -76,7 +76,7 @@ namespace MediaBrowser.Providers.Manager
         /// <param name="libraryMonitor">The directory watchers.</param>
         /// <param name="logManager">The log manager.</param>
         /// <param name="fileSystem">The file system.</param>
-        public ProviderManager(IHttpClient httpClient, IServerConfigurationManager configurationManager, ILibraryMonitor libraryMonitor, ILogManager logManager, IFileSystem fileSystem, IServerApplicationPaths appPaths, Func<ILibraryManager> libraryManagerFactory, IJsonSerializer json, IMemoryStreamProvider memoryStreamProvider)
+        public ProviderManager(IHttpClient httpClient, IServerConfigurationManager configurationManager, ILibraryMonitor libraryMonitor, ILogManager logManager, IFileSystem fileSystem, IServerApplicationPaths appPaths, Func<ILibraryManager> libraryManagerFactory, IJsonSerializer json, IMemoryStreamFactory memoryStreamProvider)
         {
             _logger = logManager.GetLogger("ProviderManager");
             _httpClient = httpClient;

+ 9 - 4
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" };
             }
         }
 

+ 2 - 2
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;

+ 1 - 10
MediaBrowser.Server.Implementations/HttpServer/ContainerAdapter.cs

@@ -6,7 +6,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
     /// <summary>
     /// Class ContainerAdapter
     /// </summary>
-    class ContainerAdapter : IContainerAdapter, IRelease
+    class ContainerAdapter : IContainerAdapter
     {
         /// <summary>
         /// The _app host
@@ -40,14 +40,5 @@ namespace MediaBrowser.Server.Implementations.HttpServer
         {
             return _appHost.TryResolve<T>();
         }
-
-        /// <summary>
-        /// Releases the specified instance.
-        /// </summary>
-        /// <param name="instance">The instance.</param>
-        public void Release(object instance)
-        {
-            // Leave this empty so SS doesn't try to dispose our objects
-        }
     }
 }

+ 217 - 154
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<Type, int>
             {
@@ -94,19 +107,12 @@ namespace MediaBrowser.Server.Implementations.HttpServer
             };
 
             HostConfig.Instance.GlobalResponseHeaders = new Dictionary<string, string>();
-            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<ISessionContext>()),
@@ -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 (_disposed)
+                {
+                    httpRes.StatusCode = 503;
+                    return;
+                }
 
-            if (!ValidateHost(url))
-            {
-                httpRes.StatusCode = 400;
-                httpRes.ContentType = "text/plain";
-                httpRes.Write("Invalid host");
+                if (!ValidateHost(url))
+                {
+                    httpRes.StatusCode = 400;
+                    httpRes.ContentType = "text/plain";
+                    httpRes.Write("Invalid host");
+                    return;
+                }
 
-                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";
+                    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";
+                var operationName = httpReq.OperationName;
+                var localPath = url.LocalPath;
 
-                httpRes.Close();
-            }
+                var urlString = url.OriginalString;
+                enableLog = EnableLogging(urlString, localPath);
+                urlToLog = urlString;
 
-            var operationName = httpReq.OperationName;
-            var localPath = url.LocalPath;
+                if (enableLog)
+                {
+                    urlToLog = GetUrlToLog(urlString);
+                    remoteIp = httpReq.RemoteIp;
 
-            var urlString = url.OriginalString;
-            var enableLog = EnableLogging(urlString, localPath);
-            var urlToLog = urlString;
+                    LoggerUtils.LogRequest(_logger, urlToLog, httpReq.HttpMethod, httpReq.UserAgent);
+                }
 
-            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))
+                {
+                    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, "/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(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(
+                            "<!doctype html><html><head><title>Emby</title></head><body>Please update your Emby bookmark to <a href=\"" +
+                            newUrl + "\">" + newUrl + "</a></body></html>");
+                        return;
+                    }
+                }
 
-                if (!string.Equals(newUrl, urlString, StringComparison.OrdinalIgnoreCase))
+                if (localPath.IndexOf("dashboard/", StringComparison.OrdinalIgnoreCase) != -1 &&
+                    localPath.IndexOf("web/dashboard", StringComparison.OrdinalIgnoreCase) == -1)
                 {
-                    httpRes.Write("<!doctype html><html><head><title>Emby</title></head><body>Please update your Emby bookmark to <a href=\"" + newUrl + "\">" + newUrl + "</a></body></html>");
+                    httpRes.StatusCode = 200;
+                    httpRes.ContentType = "text/html";
+                    var newUrl = urlString.Replace("mediabrowser", "emby", StringComparison.OrdinalIgnoreCase)
+                        .Replace("/dashboard/", "/web/", StringComparison.OrdinalIgnoreCase);
 
-                    httpRes.Close();
-                    return;
+                    if (!string.Equals(newUrl, urlString, StringComparison.OrdinalIgnoreCase))
+                    {
+                        httpRes.Write(
+                            "<!doctype html><html><head><title>Emby</title></head><body>Please update your Emby bookmark to <a href=\"" +
+                            newUrl + "\">" + newUrl + "</a></body></html>");
+                        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(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(newUrl, urlString, StringComparison.OrdinalIgnoreCase))
+                if (string.Equals(localPath, "/emby/pin", StringComparison.OrdinalIgnoreCase))
                 {
-                    httpRes.Write("<!doctype html><html><head><title>Emby</title></head><body>Please update your Emby bookmark to <a href=\"" + newUrl + "\">" + newUrl + "</a></body></html>");
+                    RedirectToUrl(httpRes, "web/pin.html");
+                    return;
+                }
 
-                    httpRes.Close();
+                if (!string.IsNullOrWhiteSpace(GlobalResponse))
+                {
+                    httpRes.StatusCode = 503;
+                    httpRes.ContentType = "text/html";
+                    httpRes.Write(GlobalResponse);
                     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;
-            }
+                var handler = HttpHandlerFactory.GetHandler(httpReq);
 
-            if (string.Equals(localPath, "/emby/pin", StringComparison.OrdinalIgnoreCase))
-            {
-                httpRes.RedirectToUrl("web/pin.html");
-                return;
+                if (handler != null)
+                {
+                    await handler.ProcessRequestAsync(httpReq, httpRes, operationName).ConfigureAwait(false);
+                }
             }
-
-            if (!string.IsNullOrWhiteSpace(GlobalResponse))
+            catch (Exception ex)
             {
-                httpRes.StatusCode = 503;
-                httpRes.ContentType = "text/html";
-                httpRes.Write(GlobalResponse);
-
-                httpRes.Close();
-                return;
+                ErrorHandler(ex, httpReq);
             }
-
-            var handler = HttpHandlerFactory.GetHandler(httpReq);
-
-            var remoteIp = httpReq.RemoteIp;
-
-            var serviceStackHandler = handler as IServiceStackHandler;
-            if (serviceStackHandler != null)
+            finally
             {
-                var restHandler = serviceStackHandler as RestHandler;
-                if (restHandler != null)
-                {
-                    httpReq.OperationName = operationName = restHandler.RestPath.RequestType.GetOperationName();
-                }
+                httpRes.Close();
 
-                try
-                {
-                    await serviceStackHandler.ProcessRequestAsync(httpReq, httpRes, operationName).ConfigureAwait(false);
-                }
-                finally
+                if (enableLog)
                 {
-                    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();
+        }
+
+
         /// <summary>
         /// Adds the rest handlers.
         /// </summary>
@@ -653,15 +692,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer
             return "mediabrowser/" + path;
         }
 
-        /// <summary>
-        /// Releases the specified instance.
-        /// </summary>
-        /// <param name="instance">The instance.</param>
-        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; }
+    }
 }

+ 1 - 0
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;

+ 9 - 6
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);
         }
     }
 }

+ 0 - 46
MediaBrowser.Server.Implementations/HttpServer/ServerLogFactory.cs

@@ -1,46 +0,0 @@
-using System;
-using MediaBrowser.Model.Logging;
-using ServiceStack.Logging;
-
-namespace MediaBrowser.Server.Implementations.HttpServer
-{
-    /// <summary>
-    /// Class ServerLogFactory
-    /// </summary>
-    public class ServerLogFactory : ILogFactory
-    {
-        /// <summary>
-        /// The _log manager
-        /// </summary>
-        private readonly ILogManager _logManager;
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ServerLogFactory"/> class.
-        /// </summary>
-        /// <param name="logManager">The log manager.</param>
-        public ServerLogFactory(ILogManager logManager)
-        {
-            _logManager = logManager;
-        }
-
-        /// <summary>
-        /// Gets the logger.
-        /// </summary>
-        /// <param name="typeName">Name of the type.</param>
-        /// <returns>ILog.</returns>
-        public ILog GetLogger(string typeName)
-        {
-            return new ServerLogger(_logManager.GetLogger(typeName));
-        }
-
-        /// <summary>
-        /// Gets the logger.
-        /// </summary>
-        /// <param name="type">The type.</param>
-        /// <returns>ILog.</returns>
-        public ILog GetLogger(Type type)
-        {
-            return GetLogger(type.Name);
-        }
-    }
-}

+ 0 - 194
MediaBrowser.Server.Implementations/HttpServer/ServerLogger.cs

@@ -1,194 +0,0 @@
-using MediaBrowser.Model.Logging;
-using ServiceStack.Logging;
-using System;
-
-namespace MediaBrowser.Server.Implementations.HttpServer
-{
-    /// <summary>
-    /// Class ServerLogger
-    /// </summary>
-    public class ServerLogger : ILog
-    {
-        /// <summary>
-        /// The _logger
-        /// </summary>
-        private readonly ILogger _logger;
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ServerLogger"/> class.
-        /// </summary>
-        /// <param name="logger">The logger.</param>
-        public ServerLogger(ILogger logger)
-        {
-            _logger = logger;
-        }
-
-        /// <summary>
-        /// Logs a Debug message and exception.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        /// <param name="exception">The exception.</param>
-        public void Debug(object message, Exception exception)
-        {
-            _logger.ErrorException(GetMesssage(message), exception);
-        }
-
-        /// <summary>
-        /// Logs a Debug message.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        public void Debug(object message)
-        {
-            // Way too verbose. Can always make this configurable if needed again.
-            //_logger.Debug(GetMesssage(message));
-        }
-
-        /// <summary>
-        /// Logs a Debug format message.
-        /// </summary>
-        /// <param name="format">The format.</param>
-        /// <param name="args">The args.</param>
-        public void DebugFormat(string format, params object[] args)
-        {
-            // Way too verbose. Can always make this configurable if needed again.
-            //_logger.Debug(format, args);
-        }
-
-        /// <summary>
-        /// Logs a Error message and exception.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        /// <param name="exception">The exception.</param>
-        public void Error(object message, Exception exception)
-        {
-            _logger.ErrorException(GetMesssage(message), exception);
-        }
-
-        /// <summary>
-        /// Logs a Error message.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        public void Error(object message)
-        {
-            _logger.Error(GetMesssage(message));
-        }
-
-        /// <summary>
-        /// Logs a Error format message.
-        /// </summary>
-        /// <param name="format">The format.</param>
-        /// <param name="args">The args.</param>
-        public void ErrorFormat(string format, params object[] args)
-        {
-            _logger.Error(format, args);
-        }
-
-        /// <summary>
-        /// Logs a Fatal message and exception.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        /// <param name="exception">The exception.</param>
-        public void Fatal(object message, Exception exception)
-        {
-            _logger.FatalException(GetMesssage(message), exception);
-        }
-
-        /// <summary>
-        /// Logs a Fatal message.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        public void Fatal(object message)
-        {
-            _logger.Fatal(GetMesssage(message));
-        }
-
-        /// <summary>
-        /// Logs a Error format message.
-        /// </summary>
-        /// <param name="format">The format.</param>
-        /// <param name="args">The args.</param>
-        public void FatalFormat(string format, params object[] args)
-        {
-            _logger.Fatal(format, args);
-        }
-
-        /// <summary>
-        /// Logs an Info message and exception.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        /// <param name="exception">The exception.</param>
-        public void Info(object message, Exception exception)
-        {
-            _logger.ErrorException(GetMesssage(message), exception);
-        }
-
-        /// <summary>
-        /// Logs an Info message and exception.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        public void Info(object message)
-        {
-            _logger.Info(GetMesssage(message));
-        }
-
-        /// <summary>
-        /// Logs an Info format message.
-        /// </summary>
-        /// <param name="format">The format.</param>
-        /// <param name="args">The args.</param>
-        public void InfoFormat(string format, params object[] args)
-        {
-            _logger.Info(format, args);
-        }
-
-        /// <summary>
-        /// Gets or sets a value indicating whether this instance is debug enabled.
-        /// </summary>
-        /// <value><c>true</c> if this instance is debug enabled; otherwise, <c>false</c>.</value>
-        public bool IsDebugEnabled
-        {
-            get { return true; }
-        }
-
-        /// <summary>
-        /// Logs a Warning message and exception.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        /// <param name="exception">The exception.</param>
-        public void Warn(object message, Exception exception)
-        {
-            _logger.ErrorException(GetMesssage(message), exception);
-        }
-
-        /// <summary>
-        /// Logs a Warning message.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        public void Warn(object message)
-        {
-            // Hide StringMapTypeDeserializer messages
-            // _logger.Warn(GetMesssage(message));
-        }
-
-        /// <summary>
-        /// Logs a Warning format message.
-        /// </summary>
-        /// <param name="format">The format.</param>
-        /// <param name="args">The args.</param>
-        public void WarnFormat(string format, params object[] args)
-        {
-            // Hide StringMapTypeDeserializer messages
-            // _logger.Warn(format, args);
-        }
-
-        /// <summary>
-        /// Gets the messsage.
-        /// </summary>
-        /// <param name="o">The o.</param>
-        /// <returns>System.String.</returns>
-        private string GetMesssage(object o)
-        {
-            return o == null ? string.Empty : o.ToString();
-        }
-    }
-}

+ 0 - 28
MediaBrowser.Server.Implementations/HttpServer/SocketSharp/Extensions.cs

@@ -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);
-            }
-        }
-    }
-}

+ 6 - 7
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;

+ 23 - 77
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<T>()
-        {
-            if (typeof(T) == typeof(IHttpRequest))
-                throw new Exception("You don't need to use IHttpRequest.TryResolve<IHttpRequest> to resolve itself");
-
-            if (typeof(T) == typeof(IHttpResponse))
-                throw new Exception("Resolve IHttpResponse with 'Response' property instead of IHttpRequest.TryResolve<IHttpResponse>");
-
-            return Container == null
-                ? HostContext.TryResolve<T>()
-                : Container.TryResolve<T>();
-        }
-
         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; }
+    }
 }

+ 14 - 2
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;
+        }
     }
 }

+ 2 - 16
MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj

@@ -69,16 +69,12 @@
       <HintPath>..\packages\Patterns.Logging.1.0.0.6\lib\portable-net45+win8\Patterns.Logging.dll</HintPath>
       <Private>True</Private>
     </Reference>
-    <Reference Include="ServiceStack.Api.Swagger">
-      <HintPath>..\ThirdParty\ServiceStack\ServiceStack.Api.Swagger.dll</HintPath>
-    </Reference>
     <Reference Include="SharpCompress, Version=0.10.3.0, Culture=neutral, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
       <HintPath>..\ThirdParty\SharpCompress\SharpCompress.dll</HintPath>
     </Reference>
-    <Reference Include="SocketHttpListener, Version=1.0.6154.22657, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\SocketHttpListener.1.0.0.44\lib\net45\SocketHttpListener.dll</HintPath>
-      <Private>True</Private>
+    <Reference Include="SocketHttpListener.Portable">
+      <HintPath>..\ThirdParty\emby\SocketHttpListener.Portable.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core" />
@@ -88,7 +84,6 @@
     <Reference Include="System.Net" />
     <Reference Include="System.Runtime.Serialization" />
     <Reference Include="System.Security" />
-    <Reference Include="System.Web" />
     <Reference Include="System.Xml" />
     <Reference Include="ServiceStack">
       <HintPath>..\ThirdParty\ServiceStack\ServiceStack.dll</HintPath>
@@ -119,18 +114,9 @@
     <Compile Include="HttpServer\ContainerAdapter.cs" />
     <Compile Include="HttpServer\HttpListenerHost.cs" />
     <Compile Include="HttpServer\HttpResultFactory.cs" />
-    <Compile Include="HttpServer\LoggerUtils.cs" />
-    <Compile Include="HttpServer\RangeRequestWriter.cs" />
-    <Compile Include="HttpServer\ResponseFilter.cs" />
     <Compile Include="HttpServer\ServerFactory.cs" />
-    <Compile Include="HttpServer\ServerLogFactory.cs" />
-    <Compile Include="HttpServer\ServerLogger.cs" />
-    <Compile Include="HttpServer\SocketSharp\SharpWebSocket.cs" />
-    <Compile Include="HttpServer\SocketSharp\Extensions.cs" />
     <Compile Include="HttpServer\SocketSharp\RequestMono.cs" />
-    <Compile Include="HttpServer\SocketSharp\WebSocketSharpListener.cs" />
     <Compile Include="HttpServer\SocketSharp\WebSocketSharpRequest.cs" />
-    <Compile Include="HttpServer\SocketSharp\WebSocketSharpResponse.cs" />
     <Compile Include="IO\LibraryMonitor.cs" />
     <Compile Include="IO\MemoryStreamProvider.cs" />
     <Compile Include="LiveTv\TunerHosts\SatIp\ChannelScan.cs" />

+ 2 - 2
MediaBrowser.Server.Implementations/Persistence/DataExtensions.cs

@@ -55,7 +55,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
         /// </summary>
         /// <returns>Stream.</returns>
         /// <exception cref="System.ArgumentNullException">reader</exception>
-        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
         /// </summary>
         /// <returns>System.Byte[][].</returns>
         /// <exception cref="System.ArgumentNullException">obj</exception>
-        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)
             {

+ 2 - 2
MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs

@@ -20,9 +20,9 @@ namespace MediaBrowser.Server.Implementations.Persistence
     /// </summary>
     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;

+ 2 - 2
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;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="SqliteItemRepository"/> class.
         /// </summary>
-        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)

+ 2 - 2
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;

+ 0 - 1
MediaBrowser.Server.Implementations/packages.config

@@ -5,6 +5,5 @@
   <package id="MediaBrowser.Naming" version="1.0.0.59" targetFramework="net46" />
   <package id="Microsoft.IO.RecyclableMemoryStream" version="1.1.0.0" targetFramework="net46" />
   <package id="Patterns.Logging" version="1.0.0.6" targetFramework="net46" />
-  <package id="SocketHttpListener" version="1.0.0.44" targetFramework="net46" />
   <package id="UniversalDetector" version="1.0.1" targetFramework="net46" />
 </packages>

+ 20 - 34
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
         /// <value>The zip client.</value>
         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<IBlurayExaminer>(() => new BdInfoExaminer(FileSystemManager, textEncoding));
@@ -601,7 +603,7 @@ namespace MediaBrowser.Server.Startup.Common
 
             RegisterSingleInstance<ISearchEngine>(() => 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<IAuthorizationContext>(authContext);
             RegisterSingleInstance<ISessionContext>(new SessionContext(UserManager, authContext, SessionManager));
-            RegisterSingleInstance<IAuthService>(new AuthService(UserManager, authContext, ServerConfigurationManager, ConnectManager, SessionManager, DeviceManager));
+
+            AuthService = new AuthService(UserManager, authContext, ServerConfigurationManager, ConnectManager, SessionManager, DeviceManager);
+            RegisterSingleInstance<IAuthService>(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;
         }
 
         /// <summary>
@@ -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)
-        {
-            return GetLocalApiUrl(ipAddress.ToString(), ipAddress.AddressFamily == AddressFamily.InterNetworkV6);
-        }
-
-        public string GetLocalApiUrl(string ipAddress, bool isIpv6)
+        public string GetLocalApiUrl(IpAddressInfo ipAddress)
         {
-            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<List<IpAddressInfo>> 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<List<IPAddress>> 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<IPAddress>();
+            var addresses = NetworkManager.GetLocalIpAddresses().ToList();
+            var list = new List<IpAddressInfo>();
 
             foreach (var address in addresses)
             {
@@ -1364,9 +1349,10 @@ namespace MediaBrowser.Server.Startup.Common
 
         private readonly ConcurrentDictionary<string, bool> _validAddressResults = new ConcurrentDictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
         private DateTime _lastAddressCacheClear;
-        private async Task<bool> IsIpAddressValidAsync(IPAddress address)
+        private async Task<bool> IsIpAddressValidAsync(IpAddressInfo address)
         {
-            if (IPAddress.IsLoopback(address))
+            if (address.Equals(IpAddressInfo.Loopback) ||
+                address.Equals(IpAddressInfo.IPv6Loopback))
             {
                 return true;
             }

+ 1 - 1
Nuget/MediaBrowser.Common.nuspec

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
     <metadata>
         <id>MediaBrowser.Common</id>
-        <version>3.0.684</version>
+        <version>3.0.688</version>
         <title>Emby.Common</title>
         <authors>Emby Team</authors>
         <owners>ebr,Luke,scottisafool</owners>

+ 2 - 2
Nuget/MediaBrowser.Server.Core.nuspec

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
     <metadata>
         <id>MediaBrowser.Server.Core</id>
-        <version>3.0.684</version>
+        <version>3.0.688</version>
         <title>Emby.Server.Core</title>
         <authors>Emby Team</authors>
         <owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,7 @@
         <description>Contains core components required to build plugins for Emby Server.</description>
         <copyright>Copyright © Emby 2013</copyright>
         <dependencies>
-            <dependency id="MediaBrowser.Common" version="3.0.684" />
+            <dependency id="MediaBrowser.Common" version="3.0.688" />
         </dependencies>
     </metadata>
     <files>

+ 5 - 5
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
     /// </summary>
     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);
         }
 
         /// <summary>