update portable projects

This commit is contained in:
Luke Pulverenti
2016-11-08 13:44:23 -05:00
parent 05a5ce58a9
commit a8b340cbb2
84 changed files with 1055 additions and 921 deletions

View File

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

View File

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

View File

@@ -1,172 +0,0 @@
using MediaBrowser.Common.Events;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Logging;
using System;
using System.Threading;
using System.Threading.Tasks;
using WebSocketState = MediaBrowser.Model.Net.WebSocketState;
namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
{
public class SharpWebSocket : IWebSocket
{
/// <summary>
/// The logger
/// </summary>
private readonly ILogger _logger;
public event EventHandler<EventArgs> Closed;
/// <summary>
/// Gets or sets the web socket.
/// </summary>
/// <value>The web socket.</value>
private SocketHttpListener.WebSocket WebSocket { get; set; }
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)
{
throw new ArgumentNullException("socket");
}
if (logger == null)
{
throw new ArgumentNullException("logger");
}
_logger = logger;
WebSocket = socket;
socket.OnMessage += socket_OnMessage;
socket.OnClose += socket_OnClose;
socket.OnError += socket_OnError;
WebSocket.ConnectAsServer();
}
void socket_OnError(object sender, SocketHttpListener.ErrorEventArgs e)
{
_logger.Error("Error in SharpWebSocket: {0}", e.Message ?? string.Empty);
//EventHelper.FireEventIfNotNull(Closed, this, EventArgs.Empty, _logger);
}
void socket_OnClose(object sender, SocketHttpListener.CloseEventArgs e)
{
EventHelper.FireEventIfNotNull(Closed, this, EventArgs.Empty, _logger);
}
void socket_OnMessage(object sender, SocketHttpListener.MessageEventArgs e)
{
//if (!string.IsNullOrWhiteSpace(e.Data))
//{
// if (OnReceive != null)
// {
// OnReceive(e.Data);
// }
// return;
//}
if (OnReceiveBytes != null)
{
OnReceiveBytes(e.RawData);
}
}
/// <summary>
/// Gets or sets the state.
/// </summary>
/// <value>The state.</value>
public WebSocketState State
{
get
{
WebSocketState commonState;
if (!Enum.TryParse(WebSocket.ReadyState.ToString(), true, out commonState))
{
_logger.Warn("Unrecognized WebSocketState: {0}", WebSocket.ReadyState.ToString());
}
return commonState;
}
}
/// <summary>
/// Sends the async.
/// </summary>
/// <param name="bytes">The bytes.</param>
/// <param name="endOfMessage">if set to <c>true</c> [end of message].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public Task SendAsync(byte[] bytes, bool endOfMessage, CancellationToken cancellationToken)
{
var completionSource = new TaskCompletionSource<bool>();
WebSocket.SendAsync(bytes, res => completionSource.TrySetResult(true));
return completionSource.Task;
}
/// <summary>
/// Sends the asynchronous.
/// </summary>
/// <param name="text">The text.</param>
/// <param name="endOfMessage">if set to <c>true</c> [end of message].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public Task SendAsync(string text, bool endOfMessage, CancellationToken cancellationToken)
{
var completionSource = new TaskCompletionSource<bool>();
WebSocket.SendAsync(text, res => completionSource.TrySetResult(true));
return completionSource.Task;
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
Dispose(true);
}
/// <summary>
/// Releases unmanaged and - optionally - managed resources.
/// </summary>
/// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
protected virtual void Dispose(bool dispose)
{
if (dispose)
{
WebSocket.OnMessage -= socket_OnMessage;
WebSocket.OnClose -= socket_OnClose;
WebSocket.OnError -= socket_OnError;
_cancellationTokenSource.Cancel();
WebSocket.Close();
}
}
/// <summary>
/// Gets or sets the receive action.
/// </summary>
/// <value>The receive action.</value>
public Action<byte[]> OnReceiveBytes { get; set; }
/// <summary>
/// Gets or sets the on receive.
/// </summary>
/// <value>The on receive.</value>
public Action<string> OnReceive { get; set; }
}
}

View File

@@ -1,216 +0,0 @@
using System.Collections.Specialized;
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.Model.IO;
using MediaBrowser.Model.Services;
using ServiceStack;
namespace MediaBrowser.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)
{
_logger = logger;
_certificatePath = certificatePath;
_memoryStreamProvider = memoryStreamProvider;
}
public Action<Exception, IRequest> ErrorHandler { get; set; }
public Func<IHttpRequest, Uri, Task> RequestHandler { get; set; }
public Action<WebSocketConnectingEventArgs> WebSocketConnecting { get; set; }
public Action<WebSocketConnectEventArgs> WebSocketConnected { get; set; }
public void Start(IEnumerable<string> urlPrefixes)
{
if (_listener == null)
_listener = new HttpListener(new PatternsLogger(_logger), _certificatePath);
foreach (var prefix in urlPrefixes)
{
_logger.Info("Adding HttpListener prefix " + prefix);
_listener.Prefixes.Add(prefix);
}
_listener.OnContext = ProcessContext;
_listener.Start();
}
private void ProcessContext(HttpListenerContext context)
{
Task.Factory.StartNew(() => InitTask(context));
}
private void InitTask(HttpListenerContext context)
{
try
{
var task = this.ProcessRequestAsync(context);
task.ContinueWith(x => HandleError(x.Exception, context), TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.AttachedToParent);
//if (task.Status == TaskStatus.Created)
//{
// task.RunSynchronously();
//}
}
catch (Exception ex)
{
HandleError(ex, context);
}
}
private Task ProcessRequestAsync(HttpListenerContext context)
{
var request = context.Request;
if (request.IsWebSocketRequest)
{
LoggerUtils.LogRequest(_logger, request);
ProcessWebSocketRequest(context);
return Task.FromResult(true);
}
if (string.IsNullOrEmpty(context.Request.RawUrl))
return ((object)null).AsTaskResult();
var httpReq = GetRequest(context);
return RequestHandler(httpReq, request.Url);
}
private void ProcessWebSocketRequest(HttpListenerContext ctx)
{
try
{
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,
Endpoint = endpoint
};
if (WebSocketConnecting != null)
{
WebSocketConnecting(connectingArgs);
}
if (connectingArgs.AllowConnection)
{
_logger.Debug("Web socket connection allowed");
var webSocketContext = ctx.AcceptWebSocket(null);
if (WebSocketConnected != null)
{
WebSocketConnected(new WebSocketConnectEventArgs
{
Url = url,
QueryString = queryParamCollection,
WebSocket = new SharpWebSocket(webSocketContext.WebSocket, _logger),
Endpoint = endpoint
});
}
}
else
{
_logger.Warn("Web socket connection not allowed");
ctx.Response.StatusCode = 401;
ctx.Response.Close();
}
}
catch (Exception ex)
{
_logger.ErrorException("AcceptWebSocketAsync error", ex);
ctx.Response.StatusCode = 500;
ctx.Response.Close();
}
}
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);
}
}
public void Stop()
{
if (_listener != null)
{
foreach (var prefix in _listener.Prefixes.ToList())
{
_listener.Prefixes.Remove(prefix);
}
_listener.Close();
}
}
public void Dispose()
{
Dispose(true);
}
private bool _disposed;
private readonly object _disposeLock = new object();
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;
lock (_disposeLock)
{
if (_disposed) return;
if (disposing)
{
Stop();
}
//release unmanaged resources here...
_disposed = true;
}
}
}
}

View File

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

View File

@@ -1,152 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
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
{
public class WebSocketSharpResponse : IHttpResponse
{
private readonly ILogger _logger;
private readonly HttpListenerResponse _response;
public WebSocketSharpResponse(ILogger logger, HttpListenerResponse response, IRequest request)
{
_logger = logger;
this._response = response;
Items = new Dictionary<string, object>();
Request = request;
}
public IRequest Request { get; private set; }
public bool UseBufferedStream { get; set; }
public Dictionary<string, object> Items { get; private set; }
public object OriginalResponse
{
get { return _response; }
}
public int StatusCode
{
get { return this._response.StatusCode; }
set { this._response.StatusCode = value; }
}
public string StatusDescription
{
get { return this._response.StatusDescription; }
set { this._response.StatusDescription = value; }
}
public string ContentType
{
get { return _response.ContentType; }
set { _response.ContentType = value; }
}
//public ICookies Cookies { get; set; }
public void AddHeader(string name, string value)
{
if (string.Equals(name, "Content-Type", StringComparison.OrdinalIgnoreCase))
{
ContentType = value;
return;
}
_response.AddHeader(name, value);
}
public string GetHeader(string name)
{
return _response.Headers[name];
}
public void Redirect(string url)
{
_response.Redirect(url);
}
public Stream OutputStream
{
get { return _response.OutputStream; }
}
public object Dto { get; set; }
public void Write(string text)
{
var bOutput = System.Text.Encoding.UTF8.GetBytes(text);
_response.ContentLength64 = bOutput.Length;
var outputStream = _response.OutputStream;
outputStream.Write(bOutput, 0, bOutput.Length);
Close();
}
public void Close()
{
if (!this.IsClosed)
{
this.IsClosed = true;
try
{
this._response.CloseOutputStream(_logger);
}
catch (Exception ex)
{
_logger.ErrorException("Error closing HttpListener output stream", ex);
}
}
}
public void End()
{
Close();
}
public void Flush()
{
_response.OutputStream.Flush();
}
public bool IsClosed
{
get;
private set;
}
public void SetContentLength(long contentLength)
{
//you can happily set the Content-Length header in Asp.Net
//but HttpListener will complain if you do - you have to set ContentLength64 on the response.
//workaround: HttpListener throws "The parameter is incorrect" exceptions when we try to set the Content-Length header
_response.ContentLength64 = contentLength;
}
public void SetCookie(Cookie cookie)
{
var cookieStr = cookie.AsHeaderValue();
_response.Headers.Add(HttpHeaders.SetCookie, cookieStr);
}
public bool SendChunked
{
get { return _response.SendChunked; }
set { _response.SendChunked = value; }
}
public bool KeepAlive { get; set; }
public void ClearCookies()
{
}
}
}