@ -8,12 +8,8 @@ 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.Tasks ;
using Emby.Common.Implementations.Net ;
using Emby.Server.Implementations.HttpServer ;
using Emby.Server.Implementations.HttpServer.SocketSharp ;
using MediaBrowser.Common.Net ;
@ -25,12 +21,12 @@ using MediaBrowser.Model.IO;
using MediaBrowser.Model.Net ;
using MediaBrowser.Model.Serialization ;
using MediaBrowser.Model.Services ;
using MediaBrowser.Model.System ;
using MediaBrowser.Model.Text ;
using ServiceStack.Text.Jsv ;
using SocketHttpListener.Net ;
using SocketHttpListener.Primitives ;
namespace MediaBrowser .Server.Implementations.HttpServer
namespace Emby .Server.Implementations.HttpServer
{
public class HttpListenerHost : ServiceStackHost , IHttpServer
{
@ -46,8 +42,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer
public event EventHandler < WebSocketConnectEventArgs > WebSocketConnected ;
public event EventHandler < WebSocketConnectingEventArgs > WebSocketConnecting ;
public string CertificatePath { get ; private set ; }
private readonly IServerConfigurationManager _config ;
private readonly INetworkManager _networkManager ;
private readonly IMemoryStreamFactory _memoryStreamProvider ;
@ -60,12 +54,16 @@ namespace MediaBrowser.Server.Implementations.HttpServer
private readonly IJsonSerializer _jsonSerializer ;
private readonly IXmlSerializer _xmlSerializer ;
private readonly ICertificate _certificate ;
private readonly IEnvironmentInfo _environment ;
private readonly IStreamFactory _streamFactory ;
private readonly Func < Type , Func < string , object > > _funcParseFn ;
public HttpListenerHost ( IServerApplicationHost applicationHost ,
ILogManager logManager ,
ILog ger log ger,
IServerConfigurationManager config ,
string serviceName ,
string defaultRedirectPath , INetworkManager networkManager , IMemoryStreamFactory memoryStreamProvider , ITextEncoding textEncoding , ISocketFactory socketFactory , ICryptoProvider cryptoProvider , IJsonSerializer jsonSerializer , IXmlSerializer xmlSerializer )
string defaultRedirectPath , INetworkManager networkManager , IMemoryStreamFactory memoryStreamProvider , ITextEncoding textEncoding , ISocketFactory socketFactory , ICryptoProvider cryptoProvider , IJsonSerializer jsonSerializer , IXmlSerializer xmlSerializer , IEnvironmentInfo environment , ICertificate certificate , IStreamFactory streamFactory , Func < Type , Func < string , object > > funcParseFn )
: base ( serviceName , new Assembly [ ] { } )
{
_appHost = applicationHost ;
@ -77,9 +75,13 @@ namespace MediaBrowser.Server.Implementations.HttpServer
_cryptoProvider = cryptoProvider ;
_jsonSerializer = jsonSerializer ;
_xmlSerializer = xmlSerializer ;
_environment = environment ;
_certificate = certificate ;
_streamFactory = streamFactory ;
_funcParseFn = funcParseFn ;
_config = config ;
_logger = logManager . GetLogger ( "HttpServer" ) ;
_logger = log ger;
}
public string GlobalResponse { get ; set ; }
@ -92,11 +94,10 @@ namespace MediaBrowser.Server.Implementations.HttpServer
{ typeof ( NotImplementedException ) , 500 } ,
{ typeof ( ResourceNotFoundException ) , 404 } ,
{ typeof ( FileNotFoundException ) , 404 } ,
{ typeof ( DirectoryNotFoundException ) , 404 } ,
//{typeof (DirectoryNotFoundException), 404} ,
{ typeof ( SecurityException ) , 401 } ,
{ typeof ( PaymentRequiredException ) , 402 } ,
{ typeof ( UnauthorizedAccessException ) , 500 } ,
{ typeof ( ApplicationException ) , 500 } ,
{ typeof ( PlatformNotSupportedException ) , 500 } ,
{ typeof ( NotSupportedException ) , 500 }
} ;
@ -123,16 +124,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer
return _appHost . Resolve < T > ( ) ;
}
public override Type [ ] GetGenericArguments ( Type type )
{
return type . GetGenericArguments ( ) ;
}
public override bool IsAssignableFrom ( Type type1 , Type type2 )
{
return type1 . IsAssignableFrom ( type2 ) ;
}
public override T TryResolve < T > ( )
{
return _appHost . TryResolve < T > ( ) ;
@ -187,34 +178,18 @@ namespace MediaBrowser.Server.Implementations.HttpServer
private IHttpListener GetListener ( )
{
var cert = ! string . IsNullOrWhiteSpace ( CertificatePath ) & & File . Exists ( CertificatePath )
? GetCert ( CertificatePath ) :
null ;
var enableDualMode = Environment . OSVersion . Platform = = PlatformID . Win32NT ;
var enableDualMode = _environment . OperatingSystem = = OperatingSystem . Windows ;
return new WebSocketSharpListener ( _logger , cert , _memoryStreamProvider , _textEncoding , _networkManager , _socketFactory , _cryptoProvider , new StreamFactory ( ) , enableDualMode , GetRequest ) ;
}
public ICertificate GetCert ( string certificateLocation )
{
try
{
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 ) ;
}
catch ( Exception ex )
{
Logger . ErrorException ( "Error loading cert from {0}" , ex , certificateLocation ) ;
return null ;
}
return new WebSocketSharpListener ( _logger ,
_certificate ,
_memoryStreamProvider ,
_textEncoding ,
_networkManager ,
_socketFactory ,
_cryptoProvider ,
_streamFactory ,
enableDualMode ,
GetRequest ) ;
}
private IHttpRequest GetRequest ( HttpListenerContext httpContext )
@ -328,7 +303,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer
// this gets all the query string key value pairs as a collection
var newQueryString = MyHttpUtility . ParseQueryString ( uri . Query ) ;
if ( newQueryString . Count = = 0 )
var originalCount = newQueryString . Count ;
if ( originalCount = = 0 )
{
return url ;
}
@ -336,8 +313,13 @@ namespace MediaBrowser.Server.Implementations.HttpServer
// this removes the key if exists
newQueryString . Remove ( key ) ;
if ( originalCount = = newQueryString . Count )
{
return url ;
}
// this gets the page path from root without QueryString
string pagePathWithoutQueryString = uri . GetLeftPart ( UriPartial . Path ) ;
string pagePathWithoutQueryString = ur l. Split ( new [ ] { '?' } , StringSplitOptions . RemoveEmptyEntries ) [ 0 ] ;
return newQueryString . Count > 0
? String . Format ( "{0}?{1}" , pagePathWithoutQueryString , newQueryString )
@ -578,28 +560,28 @@ namespace MediaBrowser.Server.Implementations.HttpServer
base . Init ( ) ;
}
public override Model. Services . RouteAttribute[ ] GetRouteAttributes ( Type requestType )
public override RouteAttribute[ ] GetRouteAttributes ( Type requestType )
{
var routes = base . GetRouteAttributes ( requestType ) . ToList ( ) ;
var clone = routes . ToList ( ) ;
foreach ( var route in clone )
{
routes . Add ( new Model. Services . RouteAttribute( NormalizeEmbyRoutePath ( route . Path ) , route . Verbs )
routes . Add ( new RouteAttribute( NormalizeEmbyRoutePath ( route . Path ) , route . Verbs )
{
Notes = route . Notes ,
Priority = route . Priority ,
Summary = route . Summary
} ) ;
routes . Add ( new Model. Services . RouteAttribute( NormalizeRoutePath ( route . Path ) , route . Verbs )
routes . Add ( new RouteAttribute( NormalizeRoutePath ( route . Path ) , route . Verbs )
{
Notes = route . Notes ,
Priority = route . Priority ,
Summary = route . Summary
} ) ;
routes . Add ( new Model. Services . RouteAttribute( DoubleNormalizeEmbyRoutePath ( route . Path ) , route . Verbs )
routes . Add ( new RouteAttribute( DoubleNormalizeEmbyRoutePath ( route . Path ) , route . Verbs )
{
Notes = route . Notes ,
Priority = route . Priority ,
@ -622,14 +604,14 @@ namespace MediaBrowser.Server.Implementations.HttpServer
task . Wait ( ) ;
var type = task . GetType ( ) ;
var type = task . GetType ( ) .GetTypeInfo ( ) ;
if ( ! type . IsGenericType )
{
return null ;
}
Logger . Warn ( "Getting task result from " + requestName + " using reflection. For better performance have your api return Task<object>" ) ;
return type . Get Property( "Result" ) . GetValue ( task ) ;
return type . Get Declared Property( "Result" ) . GetValue ( task ) ;
}
catch ( TypeAccessException )
{
@ -639,9 +621,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
public override Func < string , object > GetParseFn ( Type propertyType )
{
var fn = JsvReader . GetParseFn ( propertyType ) ;
return s = > fn ( s ) ;
return _funcParseFn ( propertyType ) ;
}
public override void SerializeToJson ( object o , Stream stream )
@ -721,44 +701,10 @@ namespace MediaBrowser.Server.Implementations.HttpServer
GC . SuppressFinalize ( this ) ;
}
public void StartServer ( IEnumerable < string > urlPrefixes , string certificatePath )
public void StartServer ( IEnumerable < string > urlPrefixes )
{
CertificatePath = certificatePath ;
UrlPrefixes = urlPrefixes . ToList ( ) ;
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 ; }
}
}