using MediaBrowser.Common.Serialization; using MediaBrowser.Model.Logging; using System; using System.IO; using System.Net.WebSockets; using System.Threading; using System.Threading.Tasks; namespace MediaBrowser.Common.Net { /// /// Class NativeWebSocket /// public class NativeWebSocket : IWebSocket { /// /// The logger /// private readonly ILogger _logger; /// /// Gets or sets the web socket. /// /// The web socket. private WebSocket WebSocket { get; set; } /// /// Initializes a new instance of the class. /// /// The socket. /// The logger. /// socket public NativeWebSocket(WebSocket socket, ILogger logger) { if (socket == null) { throw new ArgumentNullException("socket"); } if (logger == null) { throw new ArgumentNullException("logger"); } _logger = logger; WebSocket = socket; Receive(); } /// /// Gets or sets the state. /// /// The state. public WebSocketState State { get { return WebSocket.State; } } /// /// Receives this instance. /// 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) { using (var memoryStream = new MemoryStream(bytes)) { try { var messageResult = JsonSerializer.DeserializeFromStream(memoryStream); OnReceiveDelegate(messageResult); } catch (Exception ex) { _logger.ErrorException("Error processing web socket message", ex); } } } } } /// /// Receives the async. /// /// The cancellation token. /// Task{WebSocketMessageInfo}. /// Connection closed private async Task ReceiveBytesAsync(CancellationToken cancellationToken) { var bytes = new byte[4096]; var buffer = new ArraySegment(bytes); var result = await WebSocket.ReceiveAsync(buffer, cancellationToken).ConfigureAwait(false); if (result.CloseStatus.HasValue) { throw new WebSocketException("Connection closed"); } return buffer.Array; } /// /// Sends the async. /// /// The bytes. /// The type. /// if set to true [end of message]. /// The cancellation token. /// Task. public Task SendAsync(byte[] bytes, WebSocketMessageType type, bool endOfMessage, CancellationToken cancellationToken) { return WebSocket.SendAsync(new ArraySegment(bytes), type, true, cancellationToken); } /// /// 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.Dispose(); } } /// /// Gets or sets the receive action. /// /// The receive action. public Action OnReceiveDelegate { get; set; } } }