aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Common/Net
diff options
context:
space:
mode:
authorLukePulverenti <luke.pulverenti@gmail.com>2013-02-23 17:31:51 -0500
committerLukePulverenti <luke.pulverenti@gmail.com>2013-02-23 17:31:51 -0500
commit2e4db7554041ecf481d3a38656fccc309e13eb5b (patch)
tree73c064988db630f97edc18bbc3ea5fac9132483b /MediaBrowser.Common/Net
parent1a423c43b4284848e155fc4a060ef7061b084ed8 (diff)
extracted http server, web socket server and udp server dependancies
Diffstat (limited to 'MediaBrowser.Common/Net')
-rw-r--r--MediaBrowser.Common/Net/AlchemyWebSocket.cs132
-rw-r--r--MediaBrowser.Common/Net/HttpServer.cs489
-rw-r--r--MediaBrowser.Common/Net/IHttpServer.cs44
-rw-r--r--MediaBrowser.Common/Net/IUdpServer.cs43
-rw-r--r--MediaBrowser.Common/Net/IWebSocketServer.cs26
-rw-r--r--MediaBrowser.Common/Net/UdpMessageReceivedEventArgs.cs21
-rw-r--r--MediaBrowser.Common/Net/UdpServer.cs142
-rw-r--r--MediaBrowser.Common/Net/WebSocketConnectEventArgs.cs22
-rw-r--r--MediaBrowser.Common/Net/WebSocketConnection.cs6
9 files changed, 157 insertions, 768 deletions
diff --git a/MediaBrowser.Common/Net/AlchemyWebSocket.cs b/MediaBrowser.Common/Net/AlchemyWebSocket.cs
deleted file mode 100644
index 584efa999..000000000
--- a/MediaBrowser.Common/Net/AlchemyWebSocket.cs
+++ /dev/null
@@ -1,132 +0,0 @@
-using Alchemy.Classes;
-using MediaBrowser.Common.Serialization;
-using MediaBrowser.Model.Logging;
-using System;
-using System.Net.WebSockets;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Common.Net
-{
- /// <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 messageResult = JsonSerializer.DeserializeFromString<WebSocketMessageInfo>(json);
-
- OnReceiveDelegate(messageResult);
- }
- 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<WebSocketMessageInfo> OnReceiveDelegate { get; set; }
- }
-}
diff --git a/MediaBrowser.Common/Net/HttpServer.cs b/MediaBrowser.Common/Net/HttpServer.cs
deleted file mode 100644
index 20ee615ad..000000000
--- a/MediaBrowser.Common/Net/HttpServer.cs
+++ /dev/null
@@ -1,489 +0,0 @@
-using Funq;
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Common.Kernel;
-using MediaBrowser.Model.Logging;
-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.Globalization;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Reactive.Linq;
-using System.Reflection;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Common.Net
-{
- /// <summary>
- /// Class HttpServer
- /// </summary>
- public class HttpServer : HttpListenerBase
- {
- /// <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>
- /// Gets or sets the kernel.
- /// </summary>
- /// <value>The kernel.</value>
- private IKernel Kernel { get; set; }
-
- /// <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>
- /// Occurs when [web socket connected].
- /// </summary>
- public event EventHandler<WebSocketConnectEventArgs> WebSocketConnected;
-
- /// <summary>
- /// Gets the default redirect path.
- /// </summary>
- /// <value>The default redirect path.</value>
- public string DefaultRedirectPath { get; private set; }
-
- /// <summary>
- /// Initializes a new instance of the <see cref="HttpServer" /> class.
- /// </summary>
- /// <param name="urlPrefix">The URL.</param>
- /// <param name="serverName">Name of the product.</param>
- /// <param name="applicationHost">The application host.</param>
- /// <param name="kernel">The kernel.</param>
- /// <param name="logger">The logger.</param>
- /// <param name="defaultRedirectpath">The default redirectpath.</param>
- /// <exception cref="System.ArgumentNullException">urlPrefix</exception>
- public HttpServer(string urlPrefix, string serverName, IApplicationHost applicationHost, IKernel kernel, ILogger logger, string defaultRedirectpath = null)
- : base()
- {
- if (string.IsNullOrEmpty(urlPrefix))
- {
- throw new ArgumentNullException("urlPrefix");
- }
- if (kernel == null)
- {
- throw new ArgumentNullException("kernel");
- }
- if (logger == null)
- {
- throw new ArgumentNullException("logger");
- }
- if (applicationHost == null)
- {
- throw new ArgumentNullException("applicationHost");
- }
-
- DefaultRedirectPath = defaultRedirectpath;
- _logger = logger;
- ApplicationHost = applicationHost;
-
- EndpointHostConfig.Instance.ServiceStackHandlerFactoryPath = null;
- EndpointHostConfig.Instance.MetadataRedirectPath = "metadata";
-
- UrlPrefix = urlPrefix;
- Kernel = kernel;
-
- EndpointHost.ConfigureHost(this, serverName, CreateServiceManager());
-
- ContentTypeFilters.Register(ContentType.ProtoBuf, (reqCtx, res, stream) => Kernel.ProtobufSerializer.SerializeToStream(res, stream), (type, stream) => Kernel.ProtobufSerializer.DeserializeFromStream(stream, type));
-
- Init();
- Start(urlPrefix);
- }
-
- /// <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>
- /// Configures the specified container.
- /// </summary>
- /// <param name="container">The container.</param>
- public override void Configure(Container container)
- {
- if (!string.IsNullOrEmpty(DefaultRedirectPath))
- {
- SetConfig(new EndpointHostConfig
- {
- DefaultRedirectPath = DefaultRedirectPath,
-
- // Tell SS to bubble exceptions up to here
- WriteErrorsToResponse = false,
-
- DebugMode = true
- });
- }
-
- container.Adapter = new ContainerAdapter(ApplicationHost);
-
- container.Register(Kernel);
- container.Register(_logger);
- container.Register(ApplicationHost);
-
- foreach (var service in Kernel.RestServices)
- {
- service.Configure(this);
- }
-
- Plugins.Add(new SwaggerFeature());
- Plugins.Add(new CorsFeature());
-
- Serialization.JsonSerializer.Configure();
-
- 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)
- {
- // *** Already running - just leave it in place
- if (IsStarted)
- {
- return;
- }
-
- if (Listener == null)
- {
- Listener = new HttpListener();
- }
-
- EndpointHost.Config.ServiceStackHandlerFactoryPath = HttpListenerRequestWrapper.GetHandlerPathIfAny(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 });
- }
- }
- 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 (Kernel.Configuration.EnableHttpLevelLogging)
- {
- _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 (Kernel.Configuration.EnableHttpLevelLogging)
- {
- _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 = Kernel.RestServices.Select(r => r.GetType()).ToArray();
-
- return new ServiceManager(new Container(), new ServiceController(() => types));
- }
- }
-
- /// <summary>
- /// Class WebSocketConnectEventArgs
- /// </summary>
- public class WebSocketConnectEventArgs : EventArgs
- {
- /// <summary>
- /// Gets or sets the web socket.
- /// </summary>
- /// <value>The web socket.</value>
- public IWebSocket WebSocket { get; set; }
- /// <summary>
- /// Gets or sets the endpoint.
- /// </summary>
- /// <value>The endpoint.</value>
- public IPEndPoint Endpoint { get; set; }
- }
-
- class ContainerAdapter : IContainerAdapter
- {
- private readonly IApplicationHost _appHost;
-
- public ContainerAdapter(IApplicationHost appHost)
- {
- _appHost = appHost;
- }
- public T Resolve<T>()
- {
- return _appHost.Resolve<T>();
- }
-
- public T TryResolve<T>()
- {
- return _appHost.TryResolve<T>();
- }
- }
-} \ No newline at end of file
diff --git a/MediaBrowser.Common/Net/IHttpServer.cs b/MediaBrowser.Common/Net/IHttpServer.cs
new file mode 100644
index 000000000..a640fb262
--- /dev/null
+++ b/MediaBrowser.Common/Net/IHttpServer.cs
@@ -0,0 +1,44 @@
+using System;
+
+namespace MediaBrowser.Common.Net
+{
+ /// <summary>
+ /// Interface IHttpServer
+ /// </summary>
+ public interface IHttpServer : IDisposable
+ {
+ /// <summary>
+ /// Gets the URL prefix.
+ /// </summary>
+ /// <value>The URL prefix.</value>
+ string UrlPrefix { get; }
+
+ /// <summary>
+ /// Starts the specified server name.
+ /// </summary>
+ /// <param name="urlPrefix">The URL.</param>
+ void Start(string urlPrefix);
+
+ /// <summary>
+ /// Gets a value indicating whether [supports web sockets].
+ /// </summary>
+ /// <value><c>true</c> if [supports web sockets]; otherwise, <c>false</c>.</value>
+ bool SupportsWebSockets { get; }
+
+ /// <summary>
+ /// Stops this instance.
+ /// </summary>
+ void Stop();
+
+ /// <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>
+ bool EnableHttpRequestLogging { get; set; }
+
+ /// <summary>
+ /// Occurs when [web socket connected].
+ /// </summary>
+ event EventHandler<WebSocketConnectEventArgs> WebSocketConnected;
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Common/Net/IUdpServer.cs b/MediaBrowser.Common/Net/IUdpServer.cs
index 01a8ef021..036977eab 100644
--- a/MediaBrowser.Common/Net/IUdpServer.cs
+++ b/MediaBrowser.Common/Net/IUdpServer.cs
@@ -1,7 +1,46 @@
-
+using System;
+using System.Threading.Tasks;
+
namespace MediaBrowser.Common.Net
{
- public interface IUdpServer
+ /// <summary>
+ /// Interface IUdpServer
+ /// </summary>
+ public interface IUdpServer : IDisposable
{
+ /// <summary>
+ /// Occurs when [message received].
+ /// </summary>
+ event EventHandler<UdpMessageReceivedEventArgs> MessageReceived;
+
+ /// <summary>
+ /// Starts the specified port.
+ /// </summary>
+ /// <param name="port">The port.</param>
+ void Start(int port);
+
+ /// <summary>
+ /// Stops this instance.
+ /// </summary>
+ void Stop();
+
+ /// <summary>
+ /// Sends the async.
+ /// </summary>
+ /// <param name="bytes">The bytes.</param>
+ /// <param name="remoteEndPoint">The remote end point.</param>
+ /// <returns>Task.</returns>
+ /// <exception cref="System.ArgumentNullException">data</exception>
+ Task SendAsync(byte[] bytes, string remoteEndPoint);
+
+ /// <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.</returns>
+ /// <exception cref="System.ArgumentNullException">bytes</exception>
+ Task SendAsync(byte[] bytes, string ipAddress, int port);
}
}
diff --git a/MediaBrowser.Common/Net/IWebSocketServer.cs b/MediaBrowser.Common/Net/IWebSocketServer.cs
new file mode 100644
index 000000000..5ce571fbb
--- /dev/null
+++ b/MediaBrowser.Common/Net/IWebSocketServer.cs
@@ -0,0 +1,26 @@
+using System;
+
+namespace MediaBrowser.Common.Net
+{
+ /// <summary>
+ /// Interface IWebSocketServer
+ /// </summary>
+ public interface IWebSocketServer : IDisposable
+ {
+ /// <summary>
+ /// Starts the specified port number.
+ /// </summary>
+ /// <param name="portNumber">The port number.</param>
+ void Start(int portNumber);
+
+ /// <summary>
+ /// Stops this instance.
+ /// </summary>
+ void Stop();
+
+ /// <summary>
+ /// Occurs when [web socket connected].
+ /// </summary>
+ event EventHandler<WebSocketConnectEventArgs> WebSocketConnected;
+ }
+}
diff --git a/MediaBrowser.Common/Net/UdpMessageReceivedEventArgs.cs b/MediaBrowser.Common/Net/UdpMessageReceivedEventArgs.cs
new file mode 100644
index 000000000..bd5034c47
--- /dev/null
+++ b/MediaBrowser.Common/Net/UdpMessageReceivedEventArgs.cs
@@ -0,0 +1,21 @@
+using System;
+
+namespace MediaBrowser.Common.Net
+{
+ /// <summary>
+ /// Class UdpMessageReceivedEventArgs
+ /// </summary>
+ public class UdpMessageReceivedEventArgs : EventArgs
+ {
+ /// <summary>
+ /// Gets or sets the bytes.
+ /// </summary>
+ /// <value>The bytes.</value>
+ public byte[] Bytes { get; set; }
+ /// <summary>
+ /// Gets or sets the remote end point.
+ /// </summary>
+ /// <value>The remote end point.</value>
+ public string RemoteEndPoint { get; set; }
+ }
+}
diff --git a/MediaBrowser.Common/Net/UdpServer.cs b/MediaBrowser.Common/Net/UdpServer.cs
deleted file mode 100644
index a3c6a8a78..000000000
--- a/MediaBrowser.Common/Net/UdpServer.cs
+++ /dev/null
@@ -1,142 +0,0 @@
-using System;
-using System.Net;
-using System.Net.Sockets;
-using System.Reactive.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Common.Net
-{
- /// <summary>
- /// Provides a Udp Server
- /// </summary>
- public class UdpServer : IObservable<UdpReceiveResult>, IDisposable
- {
- /// <summary>
- /// The _udp client
- /// </summary>
- private readonly UdpClient _udpClient;
- /// <summary>
- /// The _stream
- /// </summary>
- private readonly IObservable<UdpReceiveResult> _stream;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="UdpServer" /> class.
- /// </summary>
- /// <param name="endPoint">The end point.</param>
- /// <exception cref="System.ArgumentNullException">endPoint</exception>
- public UdpServer(IPEndPoint endPoint)
- {
- if (endPoint == null)
- {
- throw new ArgumentNullException("endPoint");
- }
-
- _udpClient = new UdpClient(endPoint);
-
- _udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
- //_udpClient.ExclusiveAddressUse = false;
-
- _stream = CreateObservable();
- }
-
- /// <summary>
- /// Creates the observable.
- /// </summary>
- /// <returns>IObservable{UdpReceiveResult}.</returns>
- private IObservable<UdpReceiveResult> CreateObservable()
- {
- return Observable.Create<UdpReceiveResult>(obs =>
- Observable.FromAsync(() => _udpClient.ReceiveAsync())
- .Subscribe(obs))
- .Repeat()
- .Retry()
- .Publish()
- .RefCount();
- }
-
- /// <summary>
- /// Subscribes the specified observer.
- /// </summary>
- /// <param name="observer">The observer.</param>
- /// <returns>IDisposable.</returns>
- /// <exception cref="System.ArgumentNullException">observer</exception>
- public IDisposable Subscribe(IObserver<UdpReceiveResult> observer)
- {
- if (observer == null)
- {
- throw new ArgumentNullException("observer");
- }
-
- return _stream.Subscribe(observer);
- }
-
- /// <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)
- {
- _udpClient.Close();
- }
- }
-
- /// <summary>
- /// Sends the async.
- /// </summary>
- /// <param name="data">The data.</param>
- /// <param name="endPoint">The end point.</param>
- /// <returns>Task{System.Int32}.</returns>
- /// <exception cref="System.ArgumentNullException">data</exception>
- public async Task<int> SendAsync(string data, IPEndPoint endPoint)
- {
- if (data == null)
- {
- throw new ArgumentNullException("data");
- }
-
- if (endPoint == null)
- {
- throw new ArgumentNullException("endPoint");
- }
-
- var bytes = Encoding.UTF8.GetBytes(data);
-
- return await _udpClient.SendAsync(bytes, bytes.Length, endPoint).ConfigureAwait(false);
- }
-
- /// <summary>
- /// Sends the async.
- /// </summary>
- /// <param name="bytes">The bytes.</param>
- /// <param name="endPoint">The end point.</param>
- /// <returns>Task{System.Int32}.</returns>
- /// <exception cref="System.ArgumentNullException">bytes</exception>
- public async Task<int> SendAsync(byte[] bytes, IPEndPoint endPoint)
- {
- if (bytes == null)
- {
- throw new ArgumentNullException("bytes");
- }
-
- if (endPoint == null)
- {
- throw new ArgumentNullException("endPoint");
- }
-
- return await _udpClient.SendAsync(bytes, bytes.Length, endPoint).ConfigureAwait(false);
- }
- }
-}
diff --git a/MediaBrowser.Common/Net/WebSocketConnectEventArgs.cs b/MediaBrowser.Common/Net/WebSocketConnectEventArgs.cs
new file mode 100644
index 000000000..711da7a50
--- /dev/null
+++ b/MediaBrowser.Common/Net/WebSocketConnectEventArgs.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Net;
+
+namespace MediaBrowser.Common.Net
+{
+ /// <summary>
+ /// Class WebSocketConnectEventArgs
+ /// </summary>
+ public class WebSocketConnectEventArgs : EventArgs
+ {
+ /// <summary>
+ /// Gets or sets the web socket.
+ /// </summary>
+ /// <value>The web socket.</value>
+ public IWebSocket WebSocket { get; set; }
+ /// <summary>
+ /// Gets or sets the endpoint.
+ /// </summary>
+ /// <value>The endpoint.</value>
+ public string Endpoint { get; set; }
+ }
+}
diff --git a/MediaBrowser.Common/Net/WebSocketConnection.cs b/MediaBrowser.Common/Net/WebSocketConnection.cs
index d274d390d..ab691c823 100644
--- a/MediaBrowser.Common/Net/WebSocketConnection.cs
+++ b/MediaBrowser.Common/Net/WebSocketConnection.cs
@@ -21,7 +21,7 @@ namespace MediaBrowser.Common.Net
/// <summary>
/// The _remote end point
/// </summary>
- public readonly EndPoint RemoteEndPoint;
+ public readonly string RemoteEndPoint;
/// <summary>
/// The _cancellation token source
@@ -45,13 +45,13 @@ namespace MediaBrowser.Common.Net
/// <param name="remoteEndPoint">The remote end point.</param>
/// <param name="receiveAction">The receive action.</param>
/// <exception cref="System.ArgumentNullException">socket</exception>
- public WebSocketConnection(IWebSocket socket, EndPoint remoteEndPoint, Action<WebSocketMessageInfo> receiveAction, ILogger logger)
+ public WebSocketConnection(IWebSocket socket, string remoteEndPoint, Action<WebSocketMessageInfo> receiveAction, ILogger logger)
{
if (socket == null)
{
throw new ArgumentNullException("socket");
}
- if (remoteEndPoint == null)
+ if (string.IsNullOrEmpty(remoteEndPoint))
{
throw new ArgumentNullException("remoteEndPoint");
}