aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Networking
diff options
context:
space:
mode:
authorLukePulverenti <luke.pulverenti@gmail.com>2013-02-26 16:05:52 -0500
committerLukePulverenti <luke.pulverenti@gmail.com>2013-02-26 16:05:52 -0500
commit51b3c32e2cc84778212531d72665d2c5f567f34a (patch)
tree68fe93852dd6b3dffac09b3d7917dd6370b2784b /MediaBrowser.Networking
parentfbac08feada72c198cd5151e25008bca2b435cda (diff)
a little more consolidation
Diffstat (limited to 'MediaBrowser.Networking')
-rw-r--r--MediaBrowser.Networking/HttpManager/HttpManager.cs482
-rw-r--r--MediaBrowser.Networking/HttpServer/BaseRestService.cs453
-rw-r--r--MediaBrowser.Networking/HttpServer/HttpServer.cs551
-rw-r--r--MediaBrowser.Networking/HttpServer/NativeWebSocket.cs165
-rw-r--r--MediaBrowser.Networking/HttpServer/ServerFactory.cs27
-rw-r--r--MediaBrowser.Networking/Management/NativeMethods.cs72
-rw-r--r--MediaBrowser.Networking/Management/NetworkManager.cs377
-rw-r--r--MediaBrowser.Networking/Management/NetworkShares.cs638
-rw-r--r--MediaBrowser.Networking/MediaBrowser.Networking.csproj11
-rw-r--r--MediaBrowser.Networking/Udp/UdpServer.cs203
-rw-r--r--MediaBrowser.Networking/WebSocket/AlchemyServer.cs113
-rw-r--r--MediaBrowser.Networking/WebSocket/AlchemyWebSocket.cs132
12 files changed, 0 insertions, 3224 deletions
diff --git a/MediaBrowser.Networking/HttpManager/HttpManager.cs b/MediaBrowser.Networking/HttpManager/HttpManager.cs
deleted file mode 100644
index 2f44fa74b4..0000000000
--- a/MediaBrowser.Networking/HttpManager/HttpManager.cs
+++ /dev/null
@@ -1,482 +0,0 @@
-using MediaBrowser.Common.IO;
-using MediaBrowser.Common.Kernel;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Model.Logging;
-using MediaBrowser.Model.Net;
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Net.Cache;
-using System.Net.Http;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Networking.HttpManager
-{
- /// <summary>
- /// Class HttpManager
- /// </summary>
- public class HttpManager : IHttpClient
- {
- /// <summary>
- /// The _logger
- /// </summary>
- private readonly ILogger _logger;
-
- /// <summary>
- /// The _app paths
- /// </summary>
- private readonly IApplicationPaths _appPaths;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="HttpManager" /> class.
- /// </summary>
- /// <param name="appPaths">The kernel.</param>
- /// <param name="logger">The logger.</param>
- public HttpManager(IApplicationPaths appPaths, ILogger logger)
- {
- if (appPaths == null)
- {
- throw new ArgumentNullException("appPaths");
- }
- if (logger == null)
- {
- throw new ArgumentNullException("logger");
- }
-
- _logger = logger;
- _appPaths = appPaths;
- }
-
- /// <summary>
- /// Holds a dictionary of http clients by host. Use GetHttpClient(host) to retrieve or create a client for web requests.
- /// DON'T dispose it after use.
- /// </summary>
- /// <value>The HTTP clients.</value>
- private readonly ConcurrentDictionary<string, HttpClient> _httpClients = new ConcurrentDictionary<string, HttpClient>();
-
- /// <summary>
- /// Gets
- /// </summary>
- /// <param name="host">The host.</param>
- /// <returns>HttpClient.</returns>
- /// <exception cref="System.ArgumentNullException">host</exception>
- private HttpClient GetHttpClient(string host)
- {
- if (string.IsNullOrEmpty(host))
- {
- throw new ArgumentNullException("host");
- }
-
- HttpClient client;
- if (!_httpClients.TryGetValue(host, out client))
- {
- var handler = new WebRequestHandler
- {
- AutomaticDecompression = DecompressionMethods.Deflate,
- CachePolicy = new RequestCachePolicy(RequestCacheLevel.Revalidate)
- };
-
- client = new HttpClient(handler);
- client.DefaultRequestHeaders.Add("Accept", "application/json,image/*");
- client.Timeout = TimeSpan.FromSeconds(15);
- _httpClients.TryAdd(host, client);
- }
-
- return client;
- }
-
- /// <summary>
- /// Performs a GET request and returns the resulting stream
- /// </summary>
- /// <param name="url">The URL.</param>
- /// <param name="resourcePool">The resource pool.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task{Stream}.</returns>
- /// <exception cref="MediaBrowser.Model.Net.HttpException"></exception>
- public async Task<Stream> Get(string url, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
- {
- ValidateParams(url, resourcePool, cancellationToken);
-
- cancellationToken.ThrowIfCancellationRequested();
-
- await resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
-
- _logger.Info("HttpManager.Get url: {0}", url);
-
- try
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- var msg = await GetHttpClient(GetHostFromUrl(url)).GetAsync(url, cancellationToken).ConfigureAwait(false);
-
- EnsureSuccessStatusCode(msg);
-
- return await msg.Content.ReadAsStreamAsync().ConfigureAwait(false);
- }
- catch (OperationCanceledException ex)
- {
- throw GetCancellationException(url, cancellationToken, ex);
- }
- catch (HttpRequestException ex)
- {
- _logger.ErrorException("Error getting response from " + url, ex);
-
- throw new HttpException(ex.Message, ex);
- }
- finally
- {
- resourcePool.Release();
- }
- }
-
- /// <summary>
- /// Performs a POST request
- /// </summary>
- /// <param name="url">The URL.</param>
- /// <param name="postData">Params to add to the POST data.</param>
- /// <param name="resourcePool">The resource pool.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>stream on success, null on failure</returns>
- /// <exception cref="System.ArgumentNullException">postData</exception>
- /// <exception cref="MediaBrowser.Model.Net.HttpException"></exception>
- public async Task<Stream> Post(string url, Dictionary<string, string> postData, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
- {
- ValidateParams(url, resourcePool, cancellationToken);
-
- if (postData == null)
- {
- throw new ArgumentNullException("postData");
- }
-
- cancellationToken.ThrowIfCancellationRequested();
-
- var strings = postData.Keys.Select(key => string.Format("{0}={1}", key, postData[key]));
- var postContent = string.Join("&", strings.ToArray());
- var content = new StringContent(postContent, Encoding.UTF8, "application/x-www-form-urlencoded");
-
- await resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
-
- _logger.Info("HttpManager.Post url: {0}", url);
-
- try
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- var msg = await GetHttpClient(GetHostFromUrl(url)).PostAsync(url, content, cancellationToken).ConfigureAwait(false);
-
- EnsureSuccessStatusCode(msg);
-
- return await msg.Content.ReadAsStreamAsync().ConfigureAwait(false);
- }
- catch (OperationCanceledException ex)
- {
- throw GetCancellationException(url, cancellationToken, ex);
- }
- catch (HttpRequestException ex)
- {
- _logger.ErrorException("Error getting response from " + url, ex);
-
- throw new HttpException(ex.Message, ex);
- }
- finally
- {
- resourcePool.Release();
- }
- }
-
- /// <summary>
- /// Downloads the contents of a given url into a temporary location
- /// </summary>
- /// <param name="url">The URL.</param>
- /// <param name="resourcePool">The resource pool.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <param name="progress">The progress.</param>
- /// <param name="userAgent">The user agent.</param>
- /// <returns>Task{System.String}.</returns>
- /// <exception cref="System.ArgumentNullException">progress</exception>
- /// <exception cref="MediaBrowser.Model.Net.HttpException"></exception>
- public async Task<string> GetTempFile(string url, SemaphoreSlim resourcePool, CancellationToken cancellationToken, IProgress<double> progress, string userAgent = null)
- {
- ValidateParams(url, resourcePool, cancellationToken);
-
- if (progress == null)
- {
- throw new ArgumentNullException("progress");
- }
-
- cancellationToken.ThrowIfCancellationRequested();
-
- var tempFile = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid() + ".tmp");
-
- var message = new HttpRequestMessage(HttpMethod.Get, url);
-
- if (!string.IsNullOrEmpty(userAgent))
- {
- message.Headers.Add("User-Agent", userAgent);
- }
-
- await resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
-
- _logger.Info("HttpManager.GetTempFile url: {0}, temp file: {1}", url, tempFile);
-
- try
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- using (var response = await GetHttpClient(GetHostFromUrl(url)).SendAsync(message, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false))
- {
- EnsureSuccessStatusCode(response);
-
- cancellationToken.ThrowIfCancellationRequested();
-
- IEnumerable<string> lengthValues;
-
- if (!response.Headers.TryGetValues("content-length", out lengthValues) &&
- !response.Content.Headers.TryGetValues("content-length", out lengthValues))
- {
- // We're not able to track progress
- using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
- {
- using (var fs = new FileStream(tempFile, FileMode.Create, FileAccess.Write, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous))
- {
- await stream.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, cancellationToken).ConfigureAwait(false);
- }
- }
- }
- else
- {
- var length = long.Parse(string.Join(string.Empty, lengthValues.ToArray()));
-
- using (var stream = ProgressStream.CreateReadProgressStream(await response.Content.ReadAsStreamAsync().ConfigureAwait(false), progress.Report, length))
- {
- using (var fs = new FileStream(tempFile, FileMode.Create, FileAccess.Write, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous))
- {
- await stream.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, cancellationToken).ConfigureAwait(false);
- }
- }
- }
-
- progress.Report(100);
-
- cancellationToken.ThrowIfCancellationRequested();
- }
-
- return tempFile;
- }
- catch (OperationCanceledException ex)
- {
- // Cleanup
- if (File.Exists(tempFile))
- {
- File.Delete(tempFile);
- }
-
- throw GetCancellationException(url, cancellationToken, ex);
- }
- catch (HttpRequestException ex)
- {
- _logger.ErrorException("Error getting response from " + url, ex);
-
- // Cleanup
- if (File.Exists(tempFile))
- {
- File.Delete(tempFile);
- }
-
- throw new HttpException(ex.Message, ex);
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error getting response from " + url, ex);
-
- // Cleanup
- if (File.Exists(tempFile))
- {
- File.Delete(tempFile);
- }
-
- throw;
- }
- finally
- {
- resourcePool.Release();
- }
- }
-
- /// <summary>
- /// Downloads the contents of a given url into a MemoryStream
- /// </summary>
- /// <param name="url">The URL.</param>
- /// <param name="resourcePool">The resource pool.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task{MemoryStream}.</returns>
- /// <exception cref="MediaBrowser.Model.Net.HttpException"></exception>
- public async Task<MemoryStream> GetMemoryStream(string url, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
- {
- ValidateParams(url, resourcePool, cancellationToken);
-
- cancellationToken.ThrowIfCancellationRequested();
-
- var message = new HttpRequestMessage(HttpMethod.Get, url);
-
- await resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
-
- var ms = new MemoryStream();
-
- _logger.Info("HttpManager.GetMemoryStream url: {0}", url);
-
- try
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- using (var response = await GetHttpClient(GetHostFromUrl(url)).SendAsync(message, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false))
- {
- EnsureSuccessStatusCode(response);
-
- cancellationToken.ThrowIfCancellationRequested();
-
- using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
- {
- await stream.CopyToAsync(ms, StreamDefaults.DefaultCopyToBufferSize, cancellationToken).ConfigureAwait(false);
- }
-
- cancellationToken.ThrowIfCancellationRequested();
- }
-
- ms.Position = 0;
-
- return ms;
- }
- catch (OperationCanceledException ex)
- {
- ms.Dispose();
-
- throw GetCancellationException(url, cancellationToken, ex);
- }
- catch (HttpRequestException ex)
- {
- _logger.ErrorException("Error getting response from " + url, ex);
-
- ms.Dispose();
-
- throw new HttpException(ex.Message, ex);
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error getting response from " + url, ex);
-
- ms.Dispose();
-
- throw;
- }
- finally
- {
- resourcePool.Release();
- }
- }
-
- /// <summary>
- /// Validates the params.
- /// </summary>
- /// <param name="url">The URL.</param>
- /// <param name="resourcePool">The resource pool.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <exception cref="System.ArgumentNullException">url</exception>
- private void ValidateParams(string url, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
- {
- if (string.IsNullOrEmpty(url))
- {
- throw new ArgumentNullException("url");
- }
-
- if (resourcePool == null)
- {
- throw new ArgumentNullException("resourcePool");
- }
-
- if (cancellationToken == null)
- {
- throw new ArgumentNullException("cancellationToken");
- }
- }
-
- /// <summary>
- /// Gets the host from URL.
- /// </summary>
- /// <param name="url">The URL.</param>
- /// <returns>System.String.</returns>
- private string GetHostFromUrl(string url)
- {
- var start = url.IndexOf("://", StringComparison.OrdinalIgnoreCase) + 3;
- var len = url.IndexOf('/', start) - start;
- return url.Substring(start, len);
- }
-
- /// <summary>
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
- /// </summary>
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- /// <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)
- {
- foreach (var client in _httpClients.Values.ToList())
- {
- client.Dispose();
- }
-
- _httpClients.Clear();
- }
- }
-
- /// <summary>
- /// Throws the cancellation exception.
- /// </summary>
- /// <param name="url">The URL.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <param name="exception">The exception.</param>
- /// <returns>Exception.</returns>
- private Exception GetCancellationException(string url, CancellationToken cancellationToken, OperationCanceledException exception)
- {
- // If the HttpClient's timeout is reached, it will cancel the Task internally
- if (!cancellationToken.IsCancellationRequested)
- {
- var msg = string.Format("Connection to {0} timed out", url);
-
- _logger.Error(msg);
-
- // Throw an HttpException so that the caller doesn't think it was cancelled by user code
- return new HttpException(msg, exception) { IsTimedOut = true };
- }
-
- return exception;
- }
-
- /// <summary>
- /// Ensures the success status code.
- /// </summary>
- /// <param name="response">The response.</param>
- /// <exception cref="MediaBrowser.Model.Net.HttpException"></exception>
- private void EnsureSuccessStatusCode(HttpResponseMessage response)
- {
- if (!response.IsSuccessStatusCode)
- {
- throw new HttpException(response.ReasonPhrase) { StatusCode = response.StatusCode };
- }
- }
- }
-}
diff --git a/MediaBrowser.Networking/HttpServer/BaseRestService.cs b/MediaBrowser.Networking/HttpServer/BaseRestService.cs
deleted file mode 100644
index d499f07814..0000000000
--- a/MediaBrowser.Networking/HttpServer/BaseRestService.cs
+++ /dev/null
@@ -1,453 +0,0 @@
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Common.IO;
-using MediaBrowser.Common.Kernel;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Model.Logging;
-using ServiceStack.Common;
-using ServiceStack.Common.Web;
-using ServiceStack.ServiceHost;
-using ServiceStack.ServiceInterface;
-using ServiceStack.WebHost.Endpoints;
-using System;
-using System.Globalization;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Threading.Tasks;
-using MimeTypes = MediaBrowser.Common.Net.MimeTypes;
-using StreamWriter = MediaBrowser.Common.Net.StreamWriter;
-
-namespace MediaBrowser.Networking.HttpServer
-{
- /// <summary>
- /// Class BaseRestService
- /// </summary>
- public class BaseRestService : Service, IRestfulService
- {
- /// <summary>
- /// Gets or sets the kernel.
- /// </summary>
- /// <value>The kernel.</value>
- public IKernel Kernel { get; set; }
-
- /// <summary>
- /// Gets or sets the logger.
- /// </summary>
- /// <value>The logger.</value>
- public ILogger Logger { get; set; }
-
- /// <summary>
- /// Gets a value indicating whether this instance is range request.
- /// </summary>
- /// <value><c>true</c> if this instance is range request; otherwise, <c>false</c>.</value>
- protected bool IsRangeRequest
- {
- get
- {
- return Request.Headers.AllKeys.Contains("Range");
- }
- }
-
- /// <summary>
- /// To the optimized result.
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="result">The result.</param>
- /// <returns>System.Object.</returns>
- /// <exception cref="System.ArgumentNullException">result</exception>
- protected object ToOptimizedResult<T>(T result)
- where T : class
- {
- if (result == null)
- {
- throw new ArgumentNullException("result");
- }
-
- Response.AddHeader("Vary", "Accept-Encoding");
-
- return RequestContext.ToOptimizedResult(result);
- }
-
- /// <summary>
- /// To the optimized result using cache.
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="cacheKey">The cache key.</param>
- /// <param name="lastDateModified">The last date modified.</param>
- /// <param name="cacheDuration">Duration of the cache.</param>
- /// <param name="factoryFn">The factory fn.</param>
- /// <returns>System.Object.</returns>
- /// <exception cref="System.ArgumentNullException">cacheKey</exception>
- protected object ToOptimizedResultUsingCache<T>(Guid cacheKey, DateTime lastDateModified, TimeSpan? cacheDuration, Func<T> factoryFn)
- where T : class
- {
- if (cacheKey == Guid.Empty)
- {
- throw new ArgumentNullException("cacheKey");
- }
- if (factoryFn == null)
- {
- throw new ArgumentNullException("factoryFn");
- }
-
- var key = cacheKey.ToString("N");
-
- var result = PreProcessCachedResult(cacheKey, key, lastDateModified, cacheDuration, string.Empty);
-
- if (result != null)
- {
- return result;
- }
-
- return ToOptimizedResult(factoryFn());
- }
-
- /// <summary>
- /// To the cached result.
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="cacheKey">The cache key.</param>
- /// <param name="lastDateModified">The last date modified.</param>
- /// <param name="cacheDuration">Duration of the cache.</param>
- /// <param name="factoryFn">The factory fn.</param>
- /// <param name="contentType">Type of the content.</param>
- /// <returns>System.Object.</returns>
- /// <exception cref="System.ArgumentNullException">cacheKey</exception>
- protected object ToCachedResult<T>(Guid cacheKey, DateTime lastDateModified, TimeSpan? cacheDuration, Func<T> factoryFn, string contentType)
- where T : class
- {
- if (cacheKey == Guid.Empty)
- {
- throw new ArgumentNullException("cacheKey");
- }
- if (factoryFn == null)
- {
- throw new ArgumentNullException("factoryFn");
- }
-
- var key = cacheKey.ToString("N");
-
- var result = PreProcessCachedResult(cacheKey, key, lastDateModified, cacheDuration, contentType);
-
- if (result != null)
- {
- return result;
- }
-
- return factoryFn();
- }
-
- /// <summary>
- /// To the static file result.
- /// </summary>
- /// <param name="path">The path.</param>
- /// <returns>System.Object.</returns>
- /// <exception cref="System.ArgumentNullException">path</exception>
- protected object ToStaticFileResult(string path)
- {
- if (string.IsNullOrEmpty(path))
- {
- throw new ArgumentNullException("path");
- }
-
- var dateModified = File.GetLastWriteTimeUtc(path);
-
- var cacheKey = path + dateModified.Ticks;
-
- return ToStaticResult(cacheKey.GetMD5(), dateModified, null, MimeTypes.GetMimeType(path), () => Task.FromResult(GetFileStream(path)));
- }
-
- /// <summary>
- /// Gets the file stream.
- /// </summary>
- /// <param name="path">The path.</param>
- /// <returns>Stream.</returns>
- private Stream GetFileStream(string path)
- {
- return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous);
- }
-
- /// <summary>
- /// To the static result.
- /// </summary>
- /// <param name="cacheKey">The cache key.</param>
- /// <param name="lastDateModified">The last date modified.</param>
- /// <param name="cacheDuration">Duration of the cache.</param>
- /// <param name="contentType">Type of the content.</param>
- /// <param name="factoryFn">The factory fn.</param>
- /// <returns>System.Object.</returns>
- /// <exception cref="System.ArgumentNullException">cacheKey</exception>
- protected object ToStaticResult(Guid cacheKey, DateTime? lastDateModified, TimeSpan? cacheDuration, string contentType, Func<Task<Stream>> factoryFn)
- {
- if (cacheKey == Guid.Empty)
- {
- throw new ArgumentNullException("cacheKey");
- }
- if (factoryFn == null)
- {
- throw new ArgumentNullException("factoryFn");
- }
-
- var key = cacheKey.ToString("N");
-
- var result = PreProcessCachedResult(cacheKey, key, lastDateModified, cacheDuration, contentType);
-
- if (result != null)
- {
- return result;
- }
-
- var compress = ShouldCompressResponse(contentType);
-
- if (compress)
- {
- Response.AddHeader("Vary", "Accept-Encoding");
- }
-
- return ToStaticResult(contentType, factoryFn, compress).Result;
- }
-
- /// <summary>
- /// Shoulds the compress response.
- /// </summary>
- /// <param name="contentType">Type of the content.</param>
- /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
- private bool ShouldCompressResponse(string contentType)
- {
- // It will take some work to support compression with byte range requests
- if (IsRangeRequest)
- {
- return false;
- }
-
- // Don't compress media
- if (contentType.StartsWith("audio/", StringComparison.OrdinalIgnoreCase) || contentType.StartsWith("video/", StringComparison.OrdinalIgnoreCase))
- {
- return false;
- }
-
- // Don't compress images
- if (contentType.StartsWith("image/", StringComparison.OrdinalIgnoreCase))
- {
- return false;
- }
-
- if (contentType.StartsWith("font/", StringComparison.OrdinalIgnoreCase))
- {
- return false;
- }
- if (contentType.StartsWith("application/", StringComparison.OrdinalIgnoreCase))
- {
- return false;
- }
-
- return true;
- }
-
- /// <summary>
- /// To the static result.
- /// </summary>
- /// <param name="contentType">Type of the content.</param>
- /// <param name="factoryFn">The factory fn.</param>
- /// <param name="compress">if set to <c>true</c> [compress].</param>
- /// <returns>System.Object.</returns>
- private async Task<object> ToStaticResult(string contentType, Func<Task<Stream>> factoryFn, bool compress)
- {
- if (!compress || string.IsNullOrEmpty(RequestContext.CompressionType))
- {
- Response.ContentType = contentType;
-
- var stream = await factoryFn().ConfigureAwait(false);
-
- return new StreamWriter(stream);
- }
-
- string content;
-
- using (var stream = await factoryFn().ConfigureAwait(false))
- {
- using (var reader = new StreamReader(stream))
- {
- content = await reader.ReadToEndAsync().ConfigureAwait(false);
- }
- }
-
- var contents = content.Compress(RequestContext.CompressionType);
-
- return new CompressedResult(contents, RequestContext.CompressionType, contentType);
- }
-
- /// <summary>
- /// Pres the process optimized result.
- /// </summary>
- /// <param name="cacheKey">The cache key.</param>
- /// <param name="cacheKeyString">The cache key string.</param>
- /// <param name="lastDateModified">The last date modified.</param>
- /// <param name="cacheDuration">Duration of the cache.</param>
- /// <param name="contentType">Type of the content.</param>
- /// <returns>System.Object.</returns>
- private object PreProcessCachedResult(Guid cacheKey, string cacheKeyString, DateTime? lastDateModified, TimeSpan? cacheDuration, string contentType)
- {
- Response.AddHeader("ETag", cacheKeyString);
-
- if (IsNotModified(cacheKey, lastDateModified, cacheDuration))
- {
- AddAgeHeader(lastDateModified);
- AddExpiresHeader(cacheKeyString, cacheDuration);
- //ctx.Response.SendChunked = false;
-
- if (!string.IsNullOrEmpty(contentType))
- {
- Response.ContentType = contentType;
- }
-
- return new HttpResult(new byte[] { }, HttpStatusCode.NotModified);
- }
-
- SetCachingHeaders(cacheKeyString, lastDateModified, cacheDuration);
-
- return null;
- }
-
- /// <summary>
- /// Determines whether [is not modified] [the specified cache key].
- /// </summary>
- /// <param name="cacheKey">The cache key.</param>
- /// <param name="lastDateModified">The last date modified.</param>
- /// <param name="cacheDuration">Duration of the cache.</param>
- /// <returns><c>true</c> if [is not modified] [the specified cache key]; otherwise, <c>false</c>.</returns>
- private bool IsNotModified(Guid? cacheKey, DateTime? lastDateModified, TimeSpan? cacheDuration)
- {
- var isNotModified = true;
-
- if (Request.Headers.AllKeys.Contains("If-Modified-Since"))
- {
- DateTime ifModifiedSince;
-
- if (DateTime.TryParse(Request.Headers["If-Modified-Since"], out ifModifiedSince))
- {
- isNotModified = IsNotModified(ifModifiedSince.ToUniversalTime(), cacheDuration, lastDateModified);
- }
- }
-
- // Validate If-None-Match
- if (isNotModified && (cacheKey.HasValue || !string.IsNullOrEmpty(Request.Headers["If-None-Match"])))
- {
- Guid ifNoneMatch;
-
- if (Guid.TryParse(Request.Headers["If-None-Match"] ?? string.Empty, out ifNoneMatch))
- {
- if (cacheKey.HasValue && cacheKey.Value == ifNoneMatch)
- {
- return true;
- }
- }
- }
-
- return false;
- }
-
- /// <summary>
- /// Determines whether [is not modified] [the specified if modified since].
- /// </summary>
- /// <param name="ifModifiedSince">If modified since.</param>
- /// <param name="cacheDuration">Duration of the cache.</param>
- /// <param name="dateModified">The date modified.</param>
- /// <returns><c>true</c> if [is not modified] [the specified if modified since]; otherwise, <c>false</c>.</returns>
- private bool IsNotModified(DateTime ifModifiedSince, TimeSpan? cacheDuration, DateTime? dateModified)
- {
- if (dateModified.HasValue)
- {
- var lastModified = NormalizeDateForComparison(dateModified.Value);
- ifModifiedSince = NormalizeDateForComparison(ifModifiedSince);
-
- return lastModified <= ifModifiedSince;
- }
-
- if (cacheDuration.HasValue)
- {
- var cacheExpirationDate = ifModifiedSince.Add(cacheDuration.Value);
-
- if (DateTime.UtcNow < cacheExpirationDate)
- {
- return true;
- }
- }
-
- return false;
- }
-
-
- /// <summary>
- /// When the browser sends the IfModifiedDate, it's precision is limited to seconds, so this will account for that
- /// </summary>
- /// <param name="date">The date.</param>
- /// <returns>DateTime.</returns>
- private DateTime NormalizeDateForComparison(DateTime date)
- {
- return new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, date.Kind);
- }
-
- /// <summary>
- /// Sets the caching headers.
- /// </summary>
- /// <param name="cacheKey">The cache key.</param>
- /// <param name="lastDateModified">The last date modified.</param>
- /// <param name="cacheDuration">Duration of the cache.</param>
- private void SetCachingHeaders(string cacheKey, DateTime? lastDateModified, TimeSpan? cacheDuration)
- {
- // Don't specify both last modified and Etag, unless caching unconditionally. They are redundant
- // https://developers.google.com/speed/docs/best-practices/caching#LeverageBrowserCaching
- if (lastDateModified.HasValue && (string.IsNullOrEmpty(cacheKey) || cacheDuration.HasValue))
- {
- AddAgeHeader(lastDateModified);
- Response.AddHeader("LastModified", lastDateModified.Value.ToString("r"));
- }
-
- if (cacheDuration.HasValue)
- {
- Response.AddHeader("Cache-Control", "public, max-age=" + Convert.ToInt32(cacheDuration.Value.TotalSeconds));
- }
- else if (!string.IsNullOrEmpty(cacheKey))
- {
- Response.AddHeader("Cache-Control", "public");
- }
- else
- {
- Response.AddHeader("Cache-Control", "no-cache, no-store, must-revalidate");
- Response.AddHeader("pragma", "no-cache, no-store, must-revalidate");
- }
-
- AddExpiresHeader(cacheKey, cacheDuration);
- }
-
- /// <summary>
- /// Adds the expires header.
- /// </summary>
- /// <param name="cacheKey">The cache key.</param>
- /// <param name="cacheDuration">Duration of the cache.</param>
- private void AddExpiresHeader(string cacheKey, TimeSpan? cacheDuration)
- {
- if (cacheDuration.HasValue)
- {
- Response.AddHeader("Expires", DateTime.UtcNow.Add(cacheDuration.Value).ToString("r"));
- }
- else if (string.IsNullOrEmpty(cacheKey))
- {
- Response.AddHeader("Expires", "-1");
- }
- }
-
- /// <summary>
- /// Adds the age header.
- /// </summary>
- /// <param name="lastDateModified">The last date modified.</param>
- private void AddAgeHeader(DateTime? lastDateModified)
- {
- if (lastDateModified.HasValue)
- {
- Response.AddHeader("Age", Convert.ToInt64((DateTime.UtcNow - lastDateModified.Value).TotalSeconds).ToString(CultureInfo.InvariantCulture));
- }
- }
- }
-}
diff --git a/MediaBrowser.Networking/HttpServer/HttpServer.cs b/MediaBrowser.Networking/HttpServer/HttpServer.cs
deleted file mode 100644
index 08a6b3561e..0000000000
--- a/MediaBrowser.Networking/HttpServer/HttpServer.cs
+++ /dev/null
@@ -1,551 +0,0 @@
-using Funq;
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Common.Kernel;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Model.Logging;
-using MediaBrowser.Model.Serialization;
-using ServiceStack.Api.Swagger;
-using ServiceStack.Common.Web;
-using ServiceStack.Configuration;
-using ServiceStack.Logging.NLogger;
-using ServiceStack.ServiceHost;
-using ServiceStack.ServiceInterface.Cors;
-using ServiceStack.Text;
-using ServiceStack.WebHost.Endpoints;
-using ServiceStack.WebHost.Endpoints.Extensions;
-using ServiceStack.WebHost.Endpoints.Support;
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Net.WebSockets;
-using System.Reactive.Linq;
-using System.Reflection;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Networking.HttpServer
-{
- /// <summary>
- /// Class HttpServer
- /// </summary>
- public class HttpServer : HttpListenerBase, IHttpServer
- {
- /// <summary>
- /// The logger
- /// </summary>
- private readonly ILogger _logger;
-
- /// <summary>
- /// Gets the URL prefix.
- /// </summary>
- /// <value>The URL prefix.</value>
- public string UrlPrefix { get; private set; }
-
- /// <summary>
- /// The _rest services
- /// </summary>
- private readonly List<IRestfulService> _restServices = new List<IRestfulService>();
-
- /// <summary>
- /// Gets or sets the application host.
- /// </summary>
- /// <value>The application host.</value>
- private IApplicationHost ApplicationHost { get; set; }
-
- /// <summary>
- /// This subscribes to HttpListener requests and finds the appropriate BaseHandler to process it
- /// </summary>
- /// <value>The HTTP listener.</value>
- private IDisposable HttpListener { get; set; }
-
- /// <summary>
- /// Gets or sets the protobuf serializer.
- /// </summary>
- /// <value>The protobuf serializer.</value>
- private IProtobufSerializer ProtobufSerializer { get; set; }
-
- /// <summary>
- /// Occurs when [web socket connected].
- /// </summary>
- public event EventHandler<WebSocketConnectEventArgs> WebSocketConnected;
-
- /// <summary>
- /// Gets the default redirect path.
- /// </summary>
- /// <value>The default redirect path.</value>
- private string DefaultRedirectPath { get; set; }
-
- /// <summary>
- /// Gets or sets the name of the server.
- /// </summary>
- /// <value>The name of the server.</value>
- private string ServerName { get; set; }
-
- /// <summary>
- /// Initializes a new instance of the <see cref="HttpServer" /> class.
- /// </summary>
- /// <param name="applicationHost">The application host.</param>
- /// <param name="protobufSerializer">The protobuf serializer.</param>
- /// <param name="logger">The logger.</param>
- /// <param name="serverName">Name of the server.</param>
- /// <param name="defaultRedirectpath">The default redirectpath.</param>
- /// <exception cref="System.ArgumentNullException">urlPrefix</exception>
- public HttpServer(IApplicationHost applicationHost, IProtobufSerializer protobufSerializer, ILogger logger, string serverName, string defaultRedirectpath)
- : base()
- {
- if (protobufSerializer == null)
- {
- throw new ArgumentNullException("protobufSerializer");
- }
- if (logger == null)
- {
- throw new ArgumentNullException("logger");
- }
- if (applicationHost == null)
- {
- throw new ArgumentNullException("applicationHost");
- }
- if (string.IsNullOrEmpty(serverName))
- {
- throw new ArgumentNullException("serverName");
- }
- if (string.IsNullOrEmpty(defaultRedirectpath))
- {
- throw new ArgumentNullException("defaultRedirectpath");
- }
-
- ServerName = serverName;
- DefaultRedirectPath = defaultRedirectpath;
- ProtobufSerializer = protobufSerializer;
- _logger = logger;
- ApplicationHost = applicationHost;
-
- EndpointHostConfig.Instance.ServiceStackHandlerFactoryPath = null;
- EndpointHostConfig.Instance.MetadataRedirectPath = "metadata";
- }
-
- /// <summary>
- /// Configures the specified container.
- /// </summary>
- /// <param name="container">The container.</param>
- public override void Configure(Container container)
- {
- JsConfig.DateHandler = JsonDateHandler.ISO8601;
- JsConfig.ExcludeTypeInfo = true;
- JsConfig.IncludeNullValues = false;
-
- SetConfig(new EndpointHostConfig
- {
- DefaultRedirectPath = DefaultRedirectPath,
-
- // Tell SS to bubble exceptions up to here
- WriteErrorsToResponse = false,
-
- DebugMode = true
- });
-
- container.Adapter = new ContainerAdapter(ApplicationHost);
-
- Plugins.Add(new SwaggerFeature());
- Plugins.Add(new CorsFeature());
-
- ServiceStack.Logging.LogManager.LogFactory = new NLogFactory();
- }
-
- /// <summary>
- /// Starts the Web Service
- /// </summary>
- /// <param name="urlBase">A Uri that acts as the base that the server is listening on.
- /// Format should be: http://127.0.0.1:8080/ or http://127.0.0.1:8080/somevirtual/
- /// Note: the trailing slash is required! For more info see the
- /// HttpListener.Prefixes property on MSDN.</param>
- public override void Start(string urlBase)
- {
- if (string.IsNullOrEmpty(urlBase))
- {
- throw new ArgumentNullException("urlBase");
- }
-
- // *** Already running - just leave it in place
- if (IsStarted)
- {
- return;
- }
-
- if (Listener == null)
- {
- Listener = new HttpListener();
- }
-
- EndpointHost.Config.ServiceStackHandlerFactoryPath = HttpListenerRequestWrapper.GetHandlerPathIfAny(urlBase);
-
- UrlPrefix = urlBase;
-
- Listener.Prefixes.Add(urlBase);
-
- IsStarted = true;
- Listener.Start();
-
- HttpListener = CreateObservableStream().Subscribe(ProcessHttpRequestAsync);
- }
-
- /// <summary>
- /// Creates the observable stream.
- /// </summary>
- /// <returns>IObservable{HttpListenerContext}.</returns>
- private IObservable<HttpListenerContext> CreateObservableStream()
- {
- return Observable.Create<HttpListenerContext>(obs =>
- Observable.FromAsync(() => Listener.GetContextAsync())
- .Subscribe(obs))
- .Repeat()
- .Retry()
- .Publish()
- .RefCount();
- }
-
- /// <summary>
- /// Processes incoming http requests by routing them to the appropiate handler
- /// </summary>
- /// <param name="context">The CTX.</param>
- private async void ProcessHttpRequestAsync(HttpListenerContext context)
- {
- LogHttpRequest(context);
-
- if (context.Request.IsWebSocketRequest)
- {
- await ProcessWebSocketRequest(context).ConfigureAwait(false);
- return;
- }
-
-
- Task.Run(() =>
- {
- RaiseReceiveWebRequest(context);
-
- try
- {
- ProcessRequest(context);
- }
- catch (InvalidOperationException ex)
- {
- HandleException(context.Response, ex, 422);
-
- throw;
- }
- catch (ResourceNotFoundException ex)
- {
- HandleException(context.Response, ex, 404);
-
- throw;
- }
- catch (FileNotFoundException ex)
- {
- HandleException(context.Response, ex, 404);
-
- throw;
- }
- catch (DirectoryNotFoundException ex)
- {
- HandleException(context.Response, ex, 404);
-
- throw;
- }
- catch (UnauthorizedAccessException ex)
- {
- HandleException(context.Response, ex, 401);
-
- throw;
- }
- catch (ArgumentException ex)
- {
- HandleException(context.Response, ex, 400);
-
- throw;
- }
- catch (Exception ex)
- {
- HandleException(context.Response, ex, 500);
-
- throw;
- }
- });
- }
-
- /// <summary>
- /// Processes the web socket request.
- /// </summary>
- /// <param name="ctx">The CTX.</param>
- /// <returns>Task.</returns>
- private async Task ProcessWebSocketRequest(HttpListenerContext ctx)
- {
- try
- {
- var webSocketContext = await ctx.AcceptWebSocketAsync(null).ConfigureAwait(false);
-
- if (WebSocketConnected != null)
- {
- WebSocketConnected(this, new WebSocketConnectEventArgs { WebSocket = new NativeWebSocket(webSocketContext.WebSocket, _logger), Endpoint = ctx.Request.RemoteEndPoint.ToString() });
- }
- }
- catch (Exception ex)
- {
- _logger.ErrorException("AcceptWebSocketAsync error", ex);
-
- ctx.Response.StatusCode = 500;
- ctx.Response.Close();
- }
- }
-
- /// <summary>
- /// Logs the HTTP request.
- /// </summary>
- /// <param name="ctx">The CTX.</param>
- private void LogHttpRequest(HttpListenerContext ctx)
- {
- var log = new StringBuilder();
-
- log.AppendLine("Url: " + ctx.Request.Url);
- log.AppendLine("Headers: " + string.Join(",", ctx.Request.Headers.AllKeys.Select(k => k + "=" + ctx.Request.Headers[k])));
-
- var type = ctx.Request.IsWebSocketRequest ? "Web Socket" : "HTTP " + ctx.Request.HttpMethod;
-
- if (EnableHttpRequestLogging)
- {
- _logger.LogMultiline(type + " request received from " + ctx.Request.RemoteEndPoint, LogSeverity.Debug, log);
- }
- }
-
- /// <summary>
- /// Appends the error message.
- /// </summary>
- /// <param name="response">The response.</param>
- /// <param name="ex">The ex.</param>
- /// <param name="statusCode">The status code.</param>
- private void HandleException(HttpListenerResponse response, Exception ex, int statusCode)
- {
- _logger.ErrorException("Error processing request", ex);
-
- response.StatusCode = statusCode;
-
- response.Headers.Add("Status", statusCode.ToString(new CultureInfo("en-US")));
-
- response.Headers.Remove("Age");
- response.Headers.Remove("Expires");
- response.Headers.Remove("Cache-Control");
- response.Headers.Remove("Etag");
- response.Headers.Remove("Last-Modified");
-
- response.ContentType = "text/plain";
-
- if (!string.IsNullOrEmpty(ex.Message))
- {
- response.AddHeader("X-Application-Error-Code", ex.Message);
- }
-
- // This could fail, but try to add the stack trace as the body content
- try
- {
- var sb = new StringBuilder();
- sb.AppendLine("{");
- sb.AppendLine("\"ResponseStatus\":{");
- sb.AppendFormat(" \"ErrorCode\":{0},\n", ex.GetType().Name.EncodeJson());
- sb.AppendFormat(" \"Message\":{0},\n", ex.Message.EncodeJson());
- sb.AppendFormat(" \"StackTrace\":{0}\n", ex.StackTrace.EncodeJson());
- sb.AppendLine("}");
- sb.AppendLine("}");
-
- response.StatusCode = 500;
- response.ContentType = ContentType.Json;
- var sbBytes = sb.ToString().ToUtf8Bytes();
- response.OutputStream.Write(sbBytes, 0, sbBytes.Length);
- response.Close();
- }
- catch (Exception errorEx)
- {
- _logger.ErrorException("Error processing failed request", errorEx);
- }
- }
-
-
- /// <summary>
- /// Overridable method that can be used to implement a custom hnandler
- /// </summary>
- /// <param name="context">The context.</param>
- /// <exception cref="System.NotImplementedException">Cannot execute handler: + handler + at PathInfo: + httpReq.PathInfo</exception>
- protected override void ProcessRequest(HttpListenerContext context)
- {
- if (string.IsNullOrEmpty(context.Request.RawUrl)) return;
-
- var operationName = context.Request.GetOperationName();
-
- var httpReq = new HttpListenerRequestWrapper(operationName, context.Request);
- var httpRes = new HttpListenerResponseWrapper(context.Response);
- var handler = ServiceStackHttpHandlerFactory.GetHandler(httpReq);
-
- var serviceStackHandler = handler as IServiceStackHttpHandler;
-
- if (serviceStackHandler != null)
- {
- var restHandler = serviceStackHandler as RestHandler;
- if (restHandler != null)
- {
- httpReq.OperationName = operationName = restHandler.RestPath.RequestType.Name;
- }
- serviceStackHandler.ProcessRequest(httpReq, httpRes, operationName);
- LogResponse(context);
- httpRes.Close();
- return;
- }
-
- throw new NotImplementedException("Cannot execute handler: " + handler + " at PathInfo: " + httpReq.PathInfo);
- }
-
- /// <summary>
- /// Logs the response.
- /// </summary>
- /// <param name="ctx">The CTX.</param>
- private void LogResponse(HttpListenerContext ctx)
- {
- var statusode = ctx.Response.StatusCode;
-
- var log = new StringBuilder();
-
- log.AppendLine(string.Format("Url: {0}", ctx.Request.Url));
-
- log.AppendLine("Headers: " + string.Join(",", ctx.Response.Headers.AllKeys.Select(k => k + "=" + ctx.Response.Headers[k])));
-
- var msg = "Http Response Sent (" + statusode + ") to " + ctx.Request.RemoteEndPoint;
-
- if (EnableHttpRequestLogging)
- {
- _logger.LogMultiline(msg, LogSeverity.Debug, log);
- }
- }
-
- /// <summary>
- /// Creates the service manager.
- /// </summary>
- /// <param name="assembliesWithServices">The assemblies with services.</param>
- /// <returns>ServiceManager.</returns>
- protected override ServiceManager CreateServiceManager(params Assembly[] assembliesWithServices)
- {
- var types = _restServices.Select(r => r.GetType()).ToArray();
-
- return new ServiceManager(new Container(), new ServiceController(() => types));
- }
-
- /// <summary>
- /// Shut down the Web Service
- /// </summary>
- public override void Stop()
- {
- if (HttpListener != null)
- {
- HttpListener.Dispose();
- HttpListener = null;
- }
-
- if (Listener != null)
- {
- Listener.Prefixes.Remove(UrlPrefix);
- }
-
- base.Stop();
- }
-
- /// <summary>
- /// The _supports native web socket
- /// </summary>
- private bool? _supportsNativeWebSocket;
-
- /// <summary>
- /// Gets a value indicating whether [supports web sockets].
- /// </summary>
- /// <value><c>true</c> if [supports web sockets]; otherwise, <c>false</c>.</value>
- public bool SupportsWebSockets
- {
- get
- {
- if (!_supportsNativeWebSocket.HasValue)
- {
- try
- {
- new ClientWebSocket();
-
- _supportsNativeWebSocket = true;
- }
- catch (PlatformNotSupportedException)
- {
- _supportsNativeWebSocket = false;
- }
- }
-
- return _supportsNativeWebSocket.Value;
- }
- }
-
-
- /// <summary>
- /// Gets or sets a value indicating whether [enable HTTP request logging].
- /// </summary>
- /// <value><c>true</c> if [enable HTTP request logging]; otherwise, <c>false</c>.</value>
- public bool EnableHttpRequestLogging { get; set; }
-
- /// <summary>
- /// Adds the rest handlers.
- /// </summary>
- /// <param name="services">The services.</param>
- public void Init(IEnumerable<IRestfulService> services)
- {
- _restServices.AddRange(services);
-
- EndpointHost.ConfigureHost(this, ServerName, CreateServiceManager());
- ContentTypeFilters.Register(ContentType.ProtoBuf, (reqCtx, res, stream) => ProtobufSerializer.SerializeToStream(res, stream), (type, stream) => ProtobufSerializer.DeserializeFromStream(stream, type));
-
- Init();
- }
- }
-
- /// <summary>
- /// Class ContainerAdapter
- /// </summary>
- class ContainerAdapter : IContainerAdapter
- {
- /// <summary>
- /// The _app host
- /// </summary>
- private readonly IApplicationHost _appHost;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="ContainerAdapter" /> class.
- /// </summary>
- /// <param name="appHost">The app host.</param>
- public ContainerAdapter(IApplicationHost appHost)
- {
- _appHost = appHost;
- }
- /// <summary>
- /// Resolves this instance.
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <returns>``0.</returns>
- public T Resolve<T>()
- {
- return _appHost.Resolve<T>();
- }
-
- /// <summary>
- /// Tries the resolve.
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <returns>``0.</returns>
- public T TryResolve<T>()
- {
- return _appHost.TryResolve<T>();
- }
- }
-} \ No newline at end of file
diff --git a/MediaBrowser.Networking/HttpServer/NativeWebSocket.cs b/MediaBrowser.Networking/HttpServer/NativeWebSocket.cs
deleted file mode 100644
index 84d163be87..0000000000
--- a/MediaBrowser.Networking/HttpServer/NativeWebSocket.cs
+++ /dev/null
@@ -1,165 +0,0 @@
-using MediaBrowser.Common.Net;
-using MediaBrowser.Model.Logging;
-using System;
-using System.Net.WebSockets;
-using System.Threading;
-using System.Threading.Tasks;
-using WebSocketMessageType = MediaBrowser.Common.Net.WebSocketMessageType;
-using WebSocketState = MediaBrowser.Common.Net.WebSocketState;
-
-namespace MediaBrowser.Networking.HttpServer
-{
- /// <summary>
- /// Class NativeWebSocket
- /// </summary>
- public class NativeWebSocket : IWebSocket
- {
- /// <summary>
- /// The logger
- /// </summary>
- private readonly ILogger _logger;
-
- /// <summary>
- /// Gets or sets the web socket.
- /// </summary>
- /// <value>The web socket.</value>
- private System.Net.WebSockets.WebSocket WebSocket { get; set; }
-
- /// <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 NativeWebSocket(System.Net.WebSockets.WebSocket socket, ILogger logger)
- {
- if (socket == null)
- {
- throw new ArgumentNullException("socket");
- }
-
- if (logger == null)
- {
- throw new ArgumentNullException("logger");
- }
-
- _logger = logger;
- WebSocket = socket;
-
- Receive();
- }
-
- /// <summary>
- /// Gets or sets the state.
- /// </summary>
- /// <value>The state.</value>
- public WebSocketState State
- {
- get
- {
- WebSocketState commonState;
-
- if (!Enum.TryParse(WebSocket.State.ToString(), true, out commonState))
- {
- _logger.Warn("Unrecognized WebSocketState: {0}", WebSocket.State.ToString());
- }
-
- return commonState;
- }
- }
-
- /// <summary>
- /// Receives this instance.
- /// </summary>
- private async void Receive()
- {
- while (true)
- {
- byte[] bytes;
-
- try
- {
- bytes = await ReceiveBytesAsync(CancellationToken.None).ConfigureAwait(false);
- }
- catch (WebSocketException ex)
- {
- _logger.ErrorException("Error reveiving web socket message", ex);
-
- break;
- }
-
- if (OnReceiveDelegate != null)
- {
- OnReceiveDelegate(bytes);
- }
- }
- }
-
- /// <summary>
- /// Receives the async.
- /// </summary>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task{WebSocketMessageInfo}.</returns>
- /// <exception cref="System.Net.WebSockets.WebSocketException">Connection closed</exception>
- private async Task<byte[]> ReceiveBytesAsync(CancellationToken cancellationToken)
- {
- var bytes = new byte[4096];
- var buffer = new ArraySegment<byte>(bytes);
-
- var result = await WebSocket.ReceiveAsync(buffer, cancellationToken).ConfigureAwait(false);
-
- if (result.CloseStatus.HasValue)
- {
- throw new WebSocketException("Connection closed");
- }
-
- return buffer.Array;
- }
-
- /// <summary>
- /// Sends the async.
- /// </summary>
- /// <param name="bytes">The bytes.</param>
- /// <param name="type">The type.</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, WebSocketMessageType type, bool endOfMessage, CancellationToken cancellationToken)
- {
- System.Net.WebSockets.WebSocketMessageType nativeType;
-
- if (!Enum.TryParse(type.ToString(), true, out nativeType))
- {
- _logger.Warn("Unrecognized WebSocketMessageType: {0}", type.ToString());
- }
-
- return WebSocket.SendAsync(new ArraySegment<byte>(bytes), nativeType, true, cancellationToken);
- }
-
- /// <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.Dispose();
- }
- }
-
- /// <summary>
- /// Gets or sets the receive action.
- /// </summary>
- /// <value>The receive action.</value>
- public Action<byte[]> OnReceiveDelegate { get; set; }
- }
-}
diff --git a/MediaBrowser.Networking/HttpServer/ServerFactory.cs b/MediaBrowser.Networking/HttpServer/ServerFactory.cs
deleted file mode 100644
index 716fd450a5..0000000000
--- a/MediaBrowser.Networking/HttpServer/ServerFactory.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using MediaBrowser.Common.Kernel;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Model.Logging;
-using MediaBrowser.Model.Serialization;
-
-namespace MediaBrowser.Networking.HttpServer
-{
- /// <summary>
- /// Class ServerFactory
- /// </summary>
- public static class ServerFactory
- {
- /// <summary>
- /// Creates the server.
- /// </summary>
- /// <param name="applicationHost">The application host.</param>
- /// <param name="protobufSerializer">The protobuf serializer.</param>
- /// <param name="logger">The logger.</param>
- /// <param name="serverName">Name of the server.</param>
- /// <param name="defaultRedirectpath">The default redirectpath.</param>
- /// <returns>IHttpServer.</returns>
- public static IHttpServer CreateServer(IApplicationHost applicationHost, IProtobufSerializer protobufSerializer, ILogger logger, string serverName, string defaultRedirectpath)
- {
- return new HttpServer(applicationHost, protobufSerializer, logger, serverName, defaultRedirectpath);
- }
- }
-}
diff --git a/MediaBrowser.Networking/Management/NativeMethods.cs b/MediaBrowser.Networking/Management/NativeMethods.cs
deleted file mode 100644
index 9a888fab2b..0000000000
--- a/MediaBrowser.Networking/Management/NativeMethods.cs
+++ /dev/null
@@ -1,72 +0,0 @@
-using System;
-using System.Runtime.InteropServices;
-using System.Security;
-
-namespace MediaBrowser.Networking.Management
-{
- /// <summary>
- /// Class NativeMethods
- /// </summary>
- [SuppressUnmanagedCodeSecurity]
- public static class NativeMethods
- {
- //declare the Netapi32 : NetServerEnum method import
- /// <summary>
- /// Nets the server enum.
- /// </summary>
- /// <param name="ServerName">Name of the server.</param>
- /// <param name="dwLevel">The dw level.</param>
- /// <param name="pBuf">The p buf.</param>
- /// <param name="dwPrefMaxLen">The dw pref max len.</param>
- /// <param name="dwEntriesRead">The dw entries read.</param>
- /// <param name="dwTotalEntries">The dw total entries.</param>
- /// <param name="dwServerType">Type of the dw server.</param>
- /// <param name="domain">The domain.</param>
- /// <param name="dwResumeHandle">The dw resume handle.</param>
- /// <returns>System.Int32.</returns>
- [DllImport("Netapi32", CharSet = CharSet.Auto, SetLastError = true),
- SuppressUnmanagedCodeSecurityAttribute]
-
- public static extern int NetServerEnum(
- string ServerName, // must be null
- int dwLevel,
- ref IntPtr pBuf,
- int dwPrefMaxLen,
- out int dwEntriesRead,
- out int dwTotalEntries,
- int dwServerType,
- string domain, // null for login domain
- out int dwResumeHandle
- );
-
- //declare the Netapi32 : NetApiBufferFree method import
- /// <summary>
- /// Nets the API buffer free.
- /// </summary>
- /// <param name="pBuf">The p buf.</param>
- /// <returns>System.Int32.</returns>
- [DllImport("Netapi32", SetLastError = true),
- SuppressUnmanagedCodeSecurityAttribute]
-
- public static extern int NetApiBufferFree(
- IntPtr pBuf);
- }
-
- //create a _SERVER_INFO_100 STRUCTURE
- /// <summary>
- /// Struct _SERVER_INFO_100
- /// </summary>
- [StructLayout(LayoutKind.Sequential)]
- public struct _SERVER_INFO_100
- {
- /// <summary>
- /// The sv100_platform_id
- /// </summary>
- internal int sv100_platform_id;
- /// <summary>
- /// The sv100_name
- /// </summary>
- [MarshalAs(UnmanagedType.LPWStr)]
- internal string sv100_name;
- }
-}
diff --git a/MediaBrowser.Networking/Management/NetworkManager.cs b/MediaBrowser.Networking/Management/NetworkManager.cs
deleted file mode 100644
index 208c64a6ed..0000000000
--- a/MediaBrowser.Networking/Management/NetworkManager.cs
+++ /dev/null
@@ -1,377 +0,0 @@
-using MediaBrowser.Common.Net;
-using MediaBrowser.Model.Net;
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
-using System.Management;
-using System.Net;
-using System.Net.Sockets;
-using System.Runtime.InteropServices;
-
-namespace MediaBrowser.Networking.Management
-{
- /// <summary>
- /// Class NetUtils
- /// </summary>
- public class NetworkManager : INetworkManager
- {
- /// <summary>
- /// Gets the machine's local ip address
- /// </summary>
- /// <returns>IPAddress.</returns>
- public string GetLocalIpAddress()
- {
- var host = Dns.GetHostEntry(Dns.GetHostName());
-
- var ip = host.AddressList.FirstOrDefault(i => i.AddressFamily == AddressFamily.InterNetwork);
-
- if (ip == null)
- {
- return null;
- }
-
- return ip.ToString();
- }
-
- /// <summary>
- /// Gets a random port number that is currently available
- /// </summary>
- /// <returns>System.Int32.</returns>
- public int GetRandomUnusedPort()
- {
- var listener = new TcpListener(IPAddress.Any, 0);
- listener.Start();
- var port = ((IPEndPoint)listener.LocalEndpoint).Port;
- listener.Stop();
- return port;
- }
-
- /// <summary>
- /// Creates the netsh URL registration.
- /// </summary>
- public void AuthorizeHttpListening(string url)
- {
- var startInfo = new ProcessStartInfo
- {
- FileName = "netsh",
- Arguments = string.Format("http add urlacl url={0} user=\"NT AUTHORITY\\Authenticated Users\"", url),
- CreateNoWindow = true,
- WindowStyle = ProcessWindowStyle.Hidden,
- Verb = "runas",
- ErrorDialog = false
- };
-
- using (var process = Process.Start(startInfo))
- {
- process.WaitForExit();
- }
- }
-
- /// <summary>
- /// Adds the windows firewall rule.
- /// </summary>
- /// <param name="port">The port.</param>
- /// <param name="protocol">The protocol.</param>
- public void AddSystemFirewallRule(int port, NetworkProtocol protocol)
- {
- // First try to remove it so we don't end up creating duplicates
- RemoveSystemFirewallRule(port, protocol);
-
- var args = string.Format("advfirewall firewall add rule name=\"Port {0}\" dir=in action=allow protocol={1} localport={0}", port, protocol);
-
- RunNetsh(args);
- }
-
- /// <summary>
- /// Removes the windows firewall rule.
- /// </summary>
- /// <param name="port">The port.</param>
- /// <param name="protocol">The protocol.</param>
- public void RemoveSystemFirewallRule(int port, NetworkProtocol protocol)
- {
- var args = string.Format("advfirewall firewall delete rule name=\"Port {0}\" protocol={1} localport={0}", port, protocol);
-
- RunNetsh(args);
- }
-
- /// <summary>
- /// Runs the netsh.
- /// </summary>
- /// <param name="args">The args.</param>
- private void RunNetsh(string args)
- {
- var startInfo = new ProcessStartInfo
- {
- FileName = "netsh",
- Arguments = args,
- CreateNoWindow = true,
- WindowStyle = ProcessWindowStyle.Hidden,
- Verb = "runas",
- ErrorDialog = false
- };
-
- using (var process = new Process { StartInfo = startInfo })
- {
- process.Start();
- process.WaitForExit();
- }
- }
-
- /// <summary>
- /// Returns MAC Address from first Network Card in Computer
- /// </summary>
- /// <returns>[string] MAC Address</returns>
- public string GetMacAddress()
- {
- var mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
- var moc = mc.GetInstances();
- var macAddress = String.Empty;
- foreach (ManagementObject mo in moc)
- {
- if (macAddress == String.Empty) // only return MAC Address from first card
- {
- try
- {
- if ((bool)mo["IPEnabled"]) macAddress = mo["MacAddress"].ToString();
- }
- catch
- {
- mo.Dispose();
- return "";
- }
- }
- mo.Dispose();
- }
-
- return macAddress.Replace(":", "");
- }
-
- /// <summary>
- /// Uses the DllImport : NetServerEnum with all its required parameters
- /// (see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/netmgmt/netmgmt/netserverenum.asp
- /// for full details or method signature) to retrieve a list of domain SV_TYPE_WORKSTATION
- /// and SV_TYPE_SERVER PC's
- /// </summary>
- /// <returns>Arraylist that represents all the SV_TYPE_WORKSTATION and SV_TYPE_SERVER
- /// PC's in the Domain</returns>
- public IEnumerable<string> GetNetworkDevices()
- {
- //local fields
- const int MAX_PREFERRED_LENGTH = -1;
- var SV_TYPE_WORKSTATION = 1;
- var SV_TYPE_SERVER = 2;
- var buffer = IntPtr.Zero;
- var tmpBuffer = IntPtr.Zero;
- var entriesRead = 0;
- var totalEntries = 0;
- var resHandle = 0;
- var sizeofINFO = Marshal.SizeOf(typeof(_SERVER_INFO_100));
-
- try
- {
- //call the DllImport : NetServerEnum with all its required parameters
- //see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/netmgmt/netmgmt/netserverenum.asp
- //for full details of method signature
- var ret = NativeMethods.NetServerEnum(null, 100, ref buffer, MAX_PREFERRED_LENGTH, out entriesRead, out totalEntries, SV_TYPE_WORKSTATION | SV_TYPE_SERVER, null, out resHandle);
-
- //if the returned with a NERR_Success (C++ term), =0 for C#
- if (ret == 0)
- {
- //loop through all SV_TYPE_WORKSTATION and SV_TYPE_SERVER PC's
- for (var i = 0; i < totalEntries; i++)
- {
- //get pointer to, Pointer to the buffer that received the data from
- //the call to NetServerEnum. Must ensure to use correct size of
- //STRUCTURE to ensure correct location in memory is pointed to
- tmpBuffer = new IntPtr((int)buffer + (i * sizeofINFO));
- //Have now got a pointer to the list of SV_TYPE_WORKSTATION and
- //SV_TYPE_SERVER PC's, which is unmanaged memory
- //Needs to Marshal data from an unmanaged block of memory to a
- //managed object, again using STRUCTURE to ensure the correct data
- //is marshalled
- var svrInfo = (_SERVER_INFO_100)Marshal.PtrToStructure(tmpBuffer, typeof(_SERVER_INFO_100));
-
- //add the PC names to the ArrayList
- if (!string.IsNullOrEmpty(svrInfo.sv100_name))
- {
- yield return svrInfo.sv100_name;
- }
- }
- }
- }
- finally
- {
- //The NetApiBufferFree function frees
- //the memory that the NetApiBufferAllocate function allocates
- NativeMethods.NetApiBufferFree(buffer);
- }
- }
-
-
- /// <summary>
- /// Gets the network shares.
- /// </summary>
- /// <param name="path">The path.</param>
- /// <returns>IEnumerable{NetworkShare}.</returns>
- public IEnumerable<NetworkShare> GetNetworkShares(string path)
- {
- return new ShareCollection(path).OfType<Share>().Select(ToNetworkShare);
- }
-
- /// <summary>
- /// To the network share.
- /// </summary>
- /// <param name="share">The share.</param>
- /// <returns>NetworkShare.</returns>
- private NetworkShare ToNetworkShare(Share share)
- {
- return new NetworkShare
- {
- Name = share.NetName,
- Path = share.Path,
- Remark = share.Remark,
- Server = share.Server,
- ShareType = ToNetworkShareType(share.ShareType)
- };
- }
-
- /// <summary>
- /// To the type of the network share.
- /// </summary>
- /// <param name="shareType">Type of the share.</param>
- /// <returns>NetworkShareType.</returns>
- /// <exception cref="System.ArgumentException">Unknown share type</exception>
- private NetworkShareType ToNetworkShareType(ShareType shareType)
- {
- switch (shareType)
- {
- case ShareType.Device:
- return NetworkShareType.Device;
- case ShareType.Disk :
- return NetworkShareType.Disk;
- case ShareType.IPC :
- return NetworkShareType.Ipc;
- case ShareType.Printer :
- return NetworkShareType.Printer;
- case ShareType.Special:
- return NetworkShareType.Special;
- default:
- throw new ArgumentException("Unknown share type");
- }
- }
-
- /// <summary>
- /// Parses the specified endpointstring.
- /// </summary>
- /// <param name="endpointstring">The endpointstring.</param>
- /// <returns>IPEndPoint.</returns>
- public IPEndPoint Parse(string endpointstring)
- {
- return Parse(endpointstring, -1);
- }
-
- /// <summary>
- /// Parses the specified endpointstring.
- /// </summary>
- /// <param name="endpointstring">The endpointstring.</param>
- /// <param name="defaultport">The defaultport.</param>
- /// <returns>IPEndPoint.</returns>
- /// <exception cref="System.ArgumentException">Endpoint descriptor may not be empty.</exception>
- /// <exception cref="System.FormatException"></exception>
- private static IPEndPoint Parse(string endpointstring, int defaultport)
- {
- if (string.IsNullOrEmpty(endpointstring)
- || endpointstring.Trim().Length == 0)
- {
- throw new ArgumentException("Endpoint descriptor may not be empty.");
- }
-
- if (defaultport != -1 &&
- (defaultport < IPEndPoint.MinPort
- || defaultport > IPEndPoint.MaxPort))
- {
- throw new ArgumentException(string.Format("Invalid default port '{0}'", defaultport));
- }
-
- string[] values = endpointstring.Split(new char[] { ':' });
- IPAddress ipaddy;
- int port = -1;
-
- //check if we have an IPv6 or ports
- if (values.Length <= 2) // ipv4 or hostname
- {
- if (values.Length == 1)
- //no port is specified, default
- port = defaultport;
- else
- port = GetPort(values[1]);
-
- //try to use the address as IPv4, otherwise get hostname
- if (!IPAddress.TryParse(values[0], out ipaddy))
- ipaddy = GetIPfromHost(values[0]);
- }
- else if (values.Length > 2) //ipv6
- {
- //could [a:b:c]:d
- if (values[0].StartsWith("[") && values[values.Length - 2].EndsWith("]"))
- {
- string ipaddressstring = string.Join(":", values.Take(values.Length - 1).ToArray());
- ipaddy = IPAddress.Parse(ipaddressstring);
- port = GetPort(values[values.Length - 1]);
- }
- else //[a:b:c] or a:b:c
- {
- ipaddy = IPAddress.Parse(endpointstring);
- port = defaultport;
- }
- }
- else
- {
- throw new FormatException(string.Format("Invalid endpoint ipaddress '{0}'", endpointstring));
- }
-
- if (port == -1)
- throw new ArgumentException(string.Format("No port specified: '{0}'", endpointstring));
-
- return new IPEndPoint(ipaddy, port);
- }
-
- /// <summary>
- /// Gets the port.
- /// </summary>
- /// <param name="p">The p.</param>
- /// <returns>System.Int32.</returns>
- /// <exception cref="System.FormatException"></exception>
- private static int GetPort(string p)
- {
- int port;
-
- if (!int.TryParse(p, out port)
- || port < IPEndPoint.MinPort
- || port > IPEndPoint.MaxPort)
- {
- throw new FormatException(string.Format("Invalid end point port '{0}'", p));
- }
-
- return port;
- }
-
- /// <summary>
- /// Gets the I pfrom host.
- /// </summary>
- /// <param name="p">The p.</param>
- /// <returns>IPAddress.</returns>
- /// <exception cref="System.ArgumentException"></exception>
- private static IPAddress GetIPfromHost(string p)
- {
- var hosts = Dns.GetHostAddresses(p);
-
- if (hosts == null || hosts.Length == 0)
- throw new ArgumentException(string.Format("Host not found: {0}", p));
-
- return hosts[0];
- }
- }
-
-}
diff --git a/MediaBrowser.Networking/Management/NetworkShares.cs b/MediaBrowser.Networking/Management/NetworkShares.cs
deleted file mode 100644
index 0239ddead8..0000000000
--- a/MediaBrowser.Networking/Management/NetworkShares.cs
+++ /dev/null
@@ -1,638 +0,0 @@
-using System;
-using System.IO;
-using System.Collections;
-using System.Runtime.InteropServices;
-
-namespace MediaBrowser.Networking.Management
-{
- /// <summary>
- /// Type of share
- /// </summary>
- [Flags]
- public enum ShareType
- {
- /// <summary>Disk share</summary>
- Disk = 0,
- /// <summary>Printer share</summary>
- Printer = 1,
- /// <summary>Device share</summary>
- Device = 2,
- /// <summary>IPC share</summary>
- IPC = 3,
- /// <summary>Special share</summary>
- Special = -2147483648, // 0x80000000,
- }
-
- #region Share
-
- /// <summary>
- /// Information about a local share
- /// </summary>
- public class Share
- {
- #region Private data
-
- private string _server;
- private string _netName;
- private string _path;
- private ShareType _shareType;
- private string _remark;
-
- #endregion
-
- #region Constructor
-
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="Server"></param>
- /// <param name="shi"></param>
- public Share(string server, string netName, string path, ShareType shareType, string remark)
- {
- if (ShareType.Special == shareType && "IPC$" == netName)
- {
- shareType |= ShareType.IPC;
- }
-
- _server = server;
- _netName = netName;
- _path = path;
- _shareType = shareType;
- _remark = remark;
- }
-
- #endregion
-
- #region Properties
-
- /// <summary>
- /// The name of the computer that this share belongs to
- /// </summary>
- public string Server
- {
- get { return _server; }
- }
-
- /// <summary>
- /// Share name
- /// </summary>
- public string NetName
- {
- get { return _netName; }
- }
-
- /// <summary>
- /// Local path
- /// </summary>
- public string Path
- {
- get { return _path; }
- }
-
- /// <summary>
- /// Share type
- /// </summary>
- public ShareType ShareType
- {
- get { return _shareType; }
- }
-
- /// <summary>
- /// Comment
- /// </summary>
- public string Remark
- {
- get { return _remark; }
- }
-
- /// <summary>
- /// Returns true if this is a file system share
- /// </summary>
- public bool IsFileSystem
- {
- get
- {
- // Shared device
- if (0 != (_shareType & ShareType.Device)) return false;
- // IPC share
- if (0 != (_shareType & ShareType.IPC)) return false;
- // Shared printer
- if (0 != (_shareType & ShareType.Printer)) return false;
-
- // Standard disk share
- if (0 == (_shareType & ShareType.Special)) return true;
-
- // Special disk share (e.g. C$)
- return ShareType.Special == _shareType && !string.IsNullOrEmpty(_netName);
- }
- }
-
- /// <summary>
- /// Get the root of a disk-based share
- /// </summary>
- public DirectoryInfo Root
- {
- get
- {
- if (IsFileSystem)
- {
- if (string.IsNullOrEmpty(_server))
- if (string.IsNullOrEmpty(_path))
- return new DirectoryInfo(ToString());
- else
- return new DirectoryInfo(_path);
- return new DirectoryInfo(ToString());
- }
- return null;
- }
- }
-
- #endregion
-
- /// <summary>
- /// Returns the path to this share
- /// </summary>
- /// <returns></returns>
- public override string ToString()
- {
- if (string.IsNullOrEmpty(_server))
- {
- return string.Format(@"\\{0}\{1}", Environment.MachineName, _netName);
- }
- return string.Format(@"\\{0}\{1}", _server, _netName);
- }
-
- /// <summary>
- /// Returns true if this share matches the local path
- /// </summary>
- /// <param name="path"></param>
- /// <returns></returns>
- public bool MatchesPath(string path)
- {
- if (!IsFileSystem) return false;
- if (string.IsNullOrEmpty(path)) return true;
-
- return path.ToLower().StartsWith(_path.ToLower());
- }
- }
-
- #endregion
-
- /// <summary>
- /// A collection of shares
- /// </summary>
- public class ShareCollection : ReadOnlyCollectionBase
- {
- #region Platform
-
- /// <summary>
- /// Is this an NT platform?
- /// </summary>
- protected static bool IsNT
- {
- get { return (PlatformID.Win32NT == Environment.OSVersion.Platform); }
- }
-
- /// <summary>
- /// Returns true if this is Windows 2000 or higher
- /// </summary>
- protected static bool IsW2KUp
- {
- get
- {
- OperatingSystem os = Environment.OSVersion;
- if (PlatformID.Win32NT == os.Platform && os.Version.Major >= 5)
- return true;
- else
- return false;
- }
- }
-
- #endregion
-
- #region Interop
-
- #region Constants
-
- /// <summary>Maximum path length</summary>
- protected const int MAX_PATH = 260;
- /// <summary>No error</summary>
- protected const int NO_ERROR = 0;
- /// <summary>Access denied</summary>
- protected const int ERROR_ACCESS_DENIED = 5;
- /// <summary>Access denied</summary>
- protected const int ERROR_WRONG_LEVEL = 124;
- /// <summary>More data available</summary>
- protected const int ERROR_MORE_DATA = 234;
- /// <summary>Not connected</summary>
- protected const int ERROR_NOT_CONNECTED = 2250;
- /// <summary>Level 1</summary>
- protected const int UNIVERSAL_NAME_INFO_LEVEL = 1;
- /// <summary>Max extries (9x)</summary>
- protected const int MAX_SI50_ENTRIES = 20;
-
- #endregion
-
- #region Structures
-
- /// <summary>Unc name</summary>
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
- protected struct UNIVERSAL_NAME_INFO
- {
- [MarshalAs(UnmanagedType.LPTStr)]
- public string lpUniversalName;
- }
-
- /// <summary>Share information, NT, level 2</summary>
- /// <remarks>
- /// Requires admin rights to work.
- /// </remarks>
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- protected struct SHARE_INFO_2
- {
- [MarshalAs(UnmanagedType.LPWStr)]
- public string NetName;
- public ShareType ShareType;
- [MarshalAs(UnmanagedType.LPWStr)]
- public string Remark;
- public int Permissions;
- public int MaxUsers;
- public int CurrentUsers;
- [MarshalAs(UnmanagedType.LPWStr)]
- public string Path;
- [MarshalAs(UnmanagedType.LPWStr)]
- public string Password;
- }
-
- /// <summary>Share information, NT, level 1</summary>
- /// <remarks>
- /// Fallback when no admin rights.
- /// </remarks>
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- protected struct SHARE_INFO_1
- {
- [MarshalAs(UnmanagedType.LPWStr)]
- public string NetName;
- public ShareType ShareType;
- [MarshalAs(UnmanagedType.LPWStr)]
- public string Remark;
- }
-
- /// <summary>Share information, Win9x</summary>
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
- protected struct SHARE_INFO_50
- {
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 13)]
- public string NetName;
-
- public byte bShareType;
- public ushort Flags;
-
- [MarshalAs(UnmanagedType.LPTStr)]
- public string Remark;
- [MarshalAs(UnmanagedType.LPTStr)]
- public string Path;
-
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 9)]
- public string PasswordRW;
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 9)]
- public string PasswordRO;
-
- public ShareType ShareType
- {
- get { return (ShareType)((int)bShareType & 0x7F); }
- }
- }
-
- /// <summary>Share information level 1, Win9x</summary>
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
- protected struct SHARE_INFO_1_9x
- {
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 13)]
- public string NetName;
- public byte Padding;
-
- public ushort bShareType;
-
- [MarshalAs(UnmanagedType.LPTStr)]
- public string Remark;
-
- public ShareType ShareType
- {
- get { return (ShareType)((int)bShareType & 0x7FFF); }
- }
- }
-
- #endregion
-
- #region Functions
-
- /// <summary>Get a UNC name</summary>
- [DllImport("mpr", CharSet = CharSet.Auto)]
- protected static extern int WNetGetUniversalName(string lpLocalPath,
- int dwInfoLevel, ref UNIVERSAL_NAME_INFO lpBuffer, ref int lpBufferSize);
-
- /// <summary>Get a UNC name</summary>
- [DllImport("mpr", CharSet = CharSet.Auto)]
- protected static extern int WNetGetUniversalName(string lpLocalPath,
- int dwInfoLevel, IntPtr lpBuffer, ref int lpBufferSize);
-
- /// <summary>Enumerate shares (NT)</summary>
- [DllImport("netapi32", CharSet = CharSet.Unicode)]
- protected static extern int NetShareEnum(string lpServerName, int dwLevel,
- out IntPtr lpBuffer, int dwPrefMaxLen, out int entriesRead,
- out int totalEntries, ref int hResume);
-
- /// <summary>Enumerate shares (9x)</summary>
- [DllImport("svrapi", CharSet = CharSet.Ansi)]
- protected static extern int NetShareEnum(
- [MarshalAs(UnmanagedType.LPTStr)] string lpServerName, int dwLevel,
- IntPtr lpBuffer, ushort cbBuffer, out ushort entriesRead,
- out ushort totalEntries);
-
- /// <summary>Free the buffer (NT)</summary>
- [DllImport("netapi32")]
- protected static extern int NetApiBufferFree(IntPtr lpBuffer);
-
- #endregion
-
- #region Enumerate shares
-
- /// <summary>
- /// Enumerates the shares on Windows NT
- /// </summary>
- /// <param name="server">The server name</param>
- /// <param name="shares">The ShareCollection</param>
- protected static void EnumerateSharesNT(string server, ShareCollection shares)
- {
- int level = 2;
- int entriesRead, totalEntries, nRet, hResume = 0;
- IntPtr pBuffer = IntPtr.Zero;
-
- try
- {
- nRet = NetShareEnum(server, level, out pBuffer, -1,
- out entriesRead, out totalEntries, ref hResume);
-
- if (ERROR_ACCESS_DENIED == nRet)
- {
- //Need admin for level 2, drop to level 1
- level = 1;
- nRet = NetShareEnum(server, level, out pBuffer, -1,
- out entriesRead, out totalEntries, ref hResume);
- }
-
- if (NO_ERROR == nRet && entriesRead > 0)
- {
- Type t = (2 == level) ? typeof(SHARE_INFO_2) : typeof(SHARE_INFO_1);
- int offset = Marshal.SizeOf(t);
-
- for (int i = 0, lpItem = pBuffer.ToInt32(); i < entriesRead; i++, lpItem += offset)
- {
- IntPtr pItem = new IntPtr(lpItem);
- if (1 == level)
- {
- SHARE_INFO_1 si = (SHARE_INFO_1)Marshal.PtrToStructure(pItem, t);
- shares.Add(si.NetName, string.Empty, si.ShareType, si.Remark);
- }
- else
- {
- SHARE_INFO_2 si = (SHARE_INFO_2)Marshal.PtrToStructure(pItem, t);
- shares.Add(si.NetName, si.Path, si.ShareType, si.Remark);
- }
- }
- }
-
- }
- finally
- {
- // Clean up buffer allocated by system
- if (IntPtr.Zero != pBuffer)
- NetApiBufferFree(pBuffer);
- }
- }
-
- /// <summary>
- /// Enumerates the shares on Windows 9x
- /// </summary>
- /// <param name="server">The server name</param>
- /// <param name="shares">The ShareCollection</param>
- protected static void EnumerateShares9x(string server, ShareCollection shares)
- {
- int level = 50;
- int nRet = 0;
- ushort entriesRead, totalEntries;
-
- Type t = typeof(SHARE_INFO_50);
- int size = Marshal.SizeOf(t);
- ushort cbBuffer = (ushort)(MAX_SI50_ENTRIES * size);
- //On Win9x, must allocate buffer before calling API
- IntPtr pBuffer = Marshal.AllocHGlobal(cbBuffer);
-
- try
- {
- nRet = NetShareEnum(server, level, pBuffer, cbBuffer,
- out entriesRead, out totalEntries);
-
- if (ERROR_WRONG_LEVEL == nRet)
- {
- level = 1;
- t = typeof(SHARE_INFO_1_9x);
- size = Marshal.SizeOf(t);
-
- nRet = NetShareEnum(server, level, pBuffer, cbBuffer,
- out entriesRead, out totalEntries);
- }
-
- if (NO_ERROR == nRet || ERROR_MORE_DATA == nRet)
- {
- for (int i = 0, lpItem = pBuffer.ToInt32(); i < entriesRead; i++, lpItem += size)
- {
- IntPtr pItem = new IntPtr(lpItem);
-
- if (1 == level)
- {
- SHARE_INFO_1_9x si = (SHARE_INFO_1_9x)Marshal.PtrToStructure(pItem, t);
- shares.Add(si.NetName, string.Empty, si.ShareType, si.Remark);
- }
- else
- {
- SHARE_INFO_50 si = (SHARE_INFO_50)Marshal.PtrToStructure(pItem, t);
- shares.Add(si.NetName, si.Path, si.ShareType, si.Remark);
- }
- }
- }
- else
- Console.WriteLine(nRet);
-
- }
- finally
- {
- //Clean up buffer
- Marshal.FreeHGlobal(pBuffer);
- }
- }
-
- /// <summary>
- /// Enumerates the shares
- /// </summary>
- /// <param name="server">The server name</param>
- /// <param name="shares">The ShareCollection</param>
- protected static void EnumerateShares(string server, ShareCollection shares)
- {
- if (null != server && 0 != server.Length && !IsW2KUp)
- {
- server = server.ToUpper();
-
- // On NT4, 9x and Me, server has to start with "\\"
- if (!('\\' == server[0] && '\\' == server[1]))
- server = @"\\" + server;
- }
-
- if (IsNT)
- EnumerateSharesNT(server, shares);
- else
- EnumerateShares9x(server, shares);
- }
-
- #endregion
-
- #endregion
-
- #region Static methods
-
- /// <summary>
- /// Returns true if fileName is a valid local file-name of the form:
- /// X:\, where X is a drive letter from A-Z
- /// </summary>
- /// <param name="fileName">The filename to check</param>
- /// <returns></returns>
- public static bool IsValidFilePath(string fileName)
- {
- if (null == fileName || 0 == fileName.Length) return false;
-
- char drive = char.ToUpper(fileName[0]);
- if ('A' > drive || drive > 'Z')
- return false;
-
- else if (Path.VolumeSeparatorChar != fileName[1])
- return false;
- else if (Path.DirectorySeparatorChar != fileName[2])
- return false;
- else
- return true;
- }
-
- #endregion
-
- /// <summary>The name of the server this collection represents</summary>
- private string _server;
-
- #region Constructor
-
- /// <summary>
- /// Default constructor - local machine
- /// </summary>
- public ShareCollection()
- {
- _server = string.Empty;
- EnumerateShares(_server, this);
- }
-
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="Server"></param>
- public ShareCollection(string server)
- {
- _server = server;
- EnumerateShares(_server, this);
- }
-
- #endregion
-
- #region Add
-
- protected void Add(Share share)
- {
- InnerList.Add(share);
- }
-
- protected void Add(string netName, string path, ShareType shareType, string remark)
- {
- InnerList.Add(new Share(_server, netName, path, shareType, remark));
- }
-
- #endregion
-
- #region Properties
-
- /// <summary>
- /// Returns the name of the server this collection represents
- /// </summary>
- public string Server
- {
- get { return _server; }
- }
-
- /// <summary>
- /// Returns the <see cref="Share"/> at the specified index.
- /// </summary>
- public Share this[int index]
- {
- get { return (Share)InnerList[index]; }
- }
-
- /// <summary>
- /// Returns the <see cref="Share"/> which matches a given local path
- /// </summary>
- /// <param name="path">The path to match</param>
- public Share this[string path]
- {
- get
- {
- if (null == path || 0 == path.Length) return null;
-
- path = Path.GetFullPath(path);
- if (!IsValidFilePath(path)) return null;
-
- Share match = null;
-
- for (int i = 0; i < InnerList.Count; i++)
- {
- Share s = (Share)InnerList[i];
-
- if (s.IsFileSystem && s.MatchesPath(path))
- {
- //Store first match
- if (null == match)
- match = s;
-
- // If this has a longer path,
- // and this is a disk share or match is a special share,
- // then this is a better match
- else if (match.Path.Length < s.Path.Length)
- {
- if (ShareType.Disk == s.ShareType || ShareType.Disk != match.ShareType)
- match = s;
- }
- }
- }
-
- return match;
- }
- }
-
- #endregion
-
- /// <summary>
- /// Copy this collection to an array
- /// </summary>
- /// <param name="array"></param>
- /// <param name="index"></param>
- public void CopyTo(Share[] array, int index)
- {
- InnerList.CopyTo(array, index);
- }
- }
-} \ No newline at end of file
diff --git a/MediaBrowser.Networking/MediaBrowser.Networking.csproj b/MediaBrowser.Networking/MediaBrowser.Networking.csproj
index 3ef7832dfc..b7d269eeee 100644
--- a/MediaBrowser.Networking/MediaBrowser.Networking.csproj
+++ b/MediaBrowser.Networking/MediaBrowser.Networking.csproj
@@ -106,18 +106,7 @@
<Compile Include="..\SharedVersion.cs">
<Link>Properties\SharedVersion.cs</Link>
</Compile>
- <Compile Include="HttpManager\HttpManager.cs" />
- <Compile Include="HttpServer\BaseRestService.cs" />
- <Compile Include="Udp\UdpServer.cs" />
- <Compile Include="WebSocket\AlchemyServer.cs" />
- <Compile Include="WebSocket\AlchemyWebSocket.cs" />
- <Compile Include="HttpServer\HttpServer.cs" />
- <Compile Include="Management\NativeMethods.cs" />
- <Compile Include="Management\NetworkManager.cs" />
- <Compile Include="Management\NetworkShares.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
- <Compile Include="HttpServer\ServerFactory.cs" />
- <Compile Include="HttpServer\NativeWebSocket.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj">
diff --git a/MediaBrowser.Networking/Udp/UdpServer.cs b/MediaBrowser.Networking/Udp/UdpServer.cs
deleted file mode 100644
index 00eb2a0d13..0000000000
--- a/MediaBrowser.Networking/Udp/UdpServer.cs
+++ /dev/null
@@ -1,203 +0,0 @@
-using MediaBrowser.Common.Net;
-using MediaBrowser.Model.Logging;
-using MediaBrowser.Networking.Management;
-using System;
-using System.Net;
-using System.Net.Sockets;
-using System.Reactive.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Networking.Udp
-{
- /// <summary>
- /// Provides a Udp Server
- /// </summary>
- public class UdpServer : IUdpServer
- {
- /// <summary>
- /// Occurs when [message received].
- /// </summary>
- public event EventHandler<UdpMessageReceivedEventArgs> MessageReceived;
-
- /// <summary>
- /// Gets or sets the logger.
- /// </summary>
- /// <value>The logger.</value>
- private ILogger Logger { get; set; }
-
- /// <summary>
- /// Initializes a new instance of the <see cref="UdpServer" /> class.
- /// </summary>
- /// <param name="logger">The logger.</param>
- public UdpServer(ILogger logger)
- {
- Logger = logger;
- }
-
- /// <summary>
- /// Raises the <see cref="E:MessageReceived" /> event.
- /// </summary>
- /// <param name="e">The <see cref="UdpMessageReceivedEventArgs" /> instance containing the event data.</param>
- protected virtual void OnMessageReceived(UdpMessageReceivedEventArgs e)
- {
- EventHandler<UdpMessageReceivedEventArgs> handler = MessageReceived;
- if (handler != null) handler(this, e);
- }
-
- /// <summary>
- /// The _udp client
- /// </summary>
- private UdpClient _udpClient;
-
- /// <summary>
- /// Starts the specified port.
- /// </summary>
- /// <param name="port">The port.</param>
- public void Start(int port)
- {
- _udpClient = new UdpClient(new IPEndPoint(IPAddress.Any, port));
-
- _udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
-
- CreateObservable().Subscribe(OnMessageReceived);
- }
-
- /// <summary>
- /// Creates the observable.
- /// </summary>
- /// <returns>IObservable{UdpReceiveResult}.</returns>
- private IObservable<UdpReceiveResult> CreateObservable()
- {
- return Observable.Create<UdpReceiveResult>(obs =>
- Observable.FromAsync(() =>
- {
- try
- {
- return _udpClient.ReceiveAsync();
- }
- catch (ObjectDisposedException)
- {
- return Task.FromResult(new UdpReceiveResult(new byte[]{}, new IPEndPoint(IPAddress.Any, 0)));
- }
- catch (Exception ex)
- {
- Logger.ErrorException("Error receiving udp message", ex);
- return Task.FromResult(new UdpReceiveResult(new byte[] { }, new IPEndPoint(IPAddress.Any, 0)));
- }
- })
-
- .Subscribe(obs))
- .Repeat()
- .Retry()
- .Publish()
- .RefCount();
- }
-
- /// <summary>
- /// Called when [message received].
- /// </summary>
- /// <param name="message">The message.</param>
- private void OnMessageReceived(UdpReceiveResult message)
- {
- if (message.RemoteEndPoint.Port == 0)
- {
- return;
- }
- var bytes = message.Buffer;
-
- OnMessageReceived(new UdpMessageReceivedEventArgs
- {
- Bytes = bytes,
- RemoteEndPoint = message.RemoteEndPoint.ToString()
- });
- }
-
- /// <summary>
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
- /// </summary>
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- /// <summary>
- /// Stops this instance.
- /// </summary>
- public void Stop()
- {
- _udpClient.Close();
- }
-
- /// <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)
- {
- Stop();
- }
- }
-
- /// <summary>
- /// Sends the async.
- /// </summary>
- /// <param name="data">The data.</param>
- /// <param name="ipAddress">The ip address.</param>
- /// <param name="port">The port.</param>
- /// <returns>Task{System.Int32}.</returns>
- /// <exception cref="System.ArgumentNullException">data</exception>
- public Task SendAsync(string data, string ipAddress, int port)
- {
- return SendAsync(Encoding.UTF8.GetBytes(data), ipAddress, port);
- }
-
- /// <summary>
- /// Sends the async.
- /// </summary>
- /// <param name="bytes">The bytes.</param>
- /// <param name="ipAddress">The ip address.</param>
- /// <param name="port">The port.</param>
- /// <returns>Task{System.Int32}.</returns>
- /// <exception cref="System.ArgumentNullException">bytes</exception>
- public Task SendAsync(byte[] bytes, string ipAddress, int port)
- {
- if (bytes == null)
- {
- throw new ArgumentNullException("bytes");
- }
-
- if (string.IsNullOrEmpty(ipAddress))
- {
- throw new ArgumentNullException("ipAddress");
- }
-
- return _udpClient.SendAsync(bytes, bytes.Length, ipAddress, port);
- }
-
- /// <summary>
- /// Sends the async.
- /// </summary>
- /// <param name="bytes">The bytes.</param>
- /// <param name="remoteEndPoint">The remote end point.</param>
- /// <returns>Task.</returns>
- public Task SendAsync(byte[] bytes, string remoteEndPoint)
- {
- if (bytes == null)
- {
- throw new ArgumentNullException("bytes");
- }
-
- if (string.IsNullOrEmpty(remoteEndPoint))
- {
- throw new ArgumentNullException("remoteEndPoint");
- }
-
- return _udpClient.SendAsync(bytes, bytes.Length, new NetworkManager().Parse(remoteEndPoint));
- }
- }
-
-}
diff --git a/MediaBrowser.Networking/WebSocket/AlchemyServer.cs b/MediaBrowser.Networking/WebSocket/AlchemyServer.cs
deleted file mode 100644
index b3d5d710ec..0000000000
--- a/MediaBrowser.Networking/WebSocket/AlchemyServer.cs
+++ /dev/null
@@ -1,113 +0,0 @@
-using Alchemy;
-using Alchemy.Classes;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Model.Logging;
-using System;
-using System.Net;
-
-namespace MediaBrowser.Networking.WebSocket
-{
- /// <summary>
- /// Class AlchemyServer
- /// </summary>
- public class AlchemyServer : IWebSocketServer
- {
- /// <summary>
- /// Occurs when [web socket connected].
- /// </summary>
- public event EventHandler<WebSocketConnectEventArgs> WebSocketConnected;
-
- /// <summary>
- /// Gets or sets the web socket server.
- /// </summary>
- /// <value>The web socket server.</value>
- private WebSocketServer WebSocketServer { get; set; }
-
- /// <summary>
- /// The _logger
- /// </summary>
- private readonly ILogger _logger;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="AlchemyServer" /> class.
- /// </summary>
- /// <param name="logger">The logger.</param>
- /// <exception cref="System.ArgumentNullException">logger</exception>
- public AlchemyServer(ILogger logger)
- {
- if (logger == null)
- {
- throw new ArgumentNullException("logger");
- }
- _logger = logger;
- }
-
- /// <summary>
- /// Gets the port.
- /// </summary>
- /// <value>The port.</value>
- public int Port { get; private set; }
-
- /// <summary>
- /// Starts the specified port number.
- /// </summary>
- /// <param name="portNumber">The port number.</param>
- public void Start(int portNumber)
- {
- WebSocketServer = new WebSocketServer(portNumber, IPAddress.Any)
- {
- OnConnected = OnAlchemyWebSocketClientConnected,
- TimeOut = TimeSpan.FromMinutes(60)
- };
-
- WebSocketServer.Start();
-
- Port = portNumber;
-
- _logger.Info("Alchemy Web Socket Server started");
- }
-
- /// <summary>
- /// Called when [alchemy web socket client connected].
- /// </summary>
- /// <param name="context">The context.</param>
- private void OnAlchemyWebSocketClientConnected(UserContext context)
- {
- if (WebSocketConnected != null)
- {
- var socket = new AlchemyWebSocket(context, _logger);
-
- WebSocketConnected(this, new WebSocketConnectEventArgs
- {
- WebSocket = socket,
- Endpoint = context.ClientAddress.ToString()
- });
- }
- }
-
- /// <summary>
- /// Stops this instance.
- /// </summary>
- public void Stop()
- {
- }
-
- /// <summary>
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
- /// </summary>
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- /// <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)
- {
-
- }
- }
-}
diff --git a/MediaBrowser.Networking/WebSocket/AlchemyWebSocket.cs b/MediaBrowser.Networking/WebSocket/AlchemyWebSocket.cs
deleted file mode 100644
index c8ab58ca40..0000000000
--- a/MediaBrowser.Networking/WebSocket/AlchemyWebSocket.cs
+++ /dev/null
@@ -1,132 +0,0 @@
-using Alchemy.Classes;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Model.Logging;
-using System;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Networking.WebSocket
-{
- /// <summary>
- /// Class AlchemyWebSocket
- /// </summary>
- public class AlchemyWebSocket : IWebSocket
- {
- /// <summary>
- /// The logger
- /// </summary>
- private readonly ILogger _logger;
-
- /// <summary>
- /// Gets or sets the web socket.
- /// </summary>
- /// <value>The web socket.</value>
- private UserContext UserContext { get; set; }
-
- /// <summary>
- /// Initializes a new instance of the <see cref="AlchemyWebSocket" /> class.
- /// </summary>
- /// <param name="context">The context.</param>
- /// <param name="logger">The logger.</param>
- /// <exception cref="System.ArgumentNullException">context</exception>
- public AlchemyWebSocket(UserContext context, ILogger logger)
- {
- if (context == null)
- {
- throw new ArgumentNullException("context");
- }
-
- _logger = logger;
- UserContext = context;
-
- context.SetOnDisconnect(OnDisconnected);
- context.SetOnReceive(OnReceive);
-
- _logger.Info("Client connected from {0}", context.ClientAddress);
- }
-
- /// <summary>
- /// The _disconnected
- /// </summary>
- private bool _disconnected = false;
- /// <summary>
- /// Gets or sets the state.
- /// </summary>
- /// <value>The state.</value>
- public WebSocketState State
- {
- get { return _disconnected ? WebSocketState.Closed : WebSocketState.Open; }
- }
-
- /// <summary>
- /// Called when [disconnected].
- /// </summary>
- /// <param name="context">The context.</param>
- private void OnDisconnected(UserContext context)
- {
- _disconnected = true;
- }
-
- /// <summary>
- /// Called when [receive].
- /// </summary>
- /// <param name="context">The context.</param>
- private void OnReceive(UserContext context)
- {
- if (OnReceiveDelegate != null)
- {
- var json = context.DataFrame.ToString();
-
- if (!string.IsNullOrWhiteSpace(json))
- {
- try
- {
- var bytes = Encoding.UTF8.GetBytes(json);
-
- OnReceiveDelegate(bytes);
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error processing web socket message", ex);
- }
- }
- }
- }
-
- /// <summary>
- /// Sends the async.
- /// </summary>
- /// <param name="bytes">The bytes.</param>
- /// <param name="type">The type.</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, WebSocketMessageType type, bool endOfMessage, CancellationToken cancellationToken)
- {
- return Task.Run(() => UserContext.Send(bytes));
- }
-
- /// <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)
- {
- }
-
- /// <summary>
- /// Gets or sets the receive action.
- /// </summary>
- /// <value>The receive action.</value>
- public Action<byte[]> OnReceiveDelegate { get; set; }
- }
-}