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