//---------------------------------------------------------------------------------------------- // // Licensed under the MIT License. See LICENSE.TXT in the project root license information. // //---------------------------------------------------------------------------------------------- using System; using System.Diagnostics; using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Json; using System.Threading.Tasks; namespace Microsoft.Tools.WindowsDevicePortal { /// /// Internal Web socket message received event handler /// /// sender object /// Web socket message received args /// Return type for the websocket messages. internal delegate void WebSocketMessageReceivedEventInternalHandler(WebSocket sender, WebSocketMessageReceivedEventArgs args); /// /// Internal Web socket stream received event handler /// /// sender object /// Web socket message received args /// Return type for the websocket. internal delegate void WebSocketStreamReceivedEventInternalHandler(WebSocket sender, WebSocketMessageReceivedEventArgs args); /// /// HTTP Websocket Wrapper /// /// Return type for the websocket messages. internal partial class WebSocket { /// /// The device that the is connected to. /// private IDevicePortalConnection deviceConnection; /// /// Indicates whether the web socket should send streams instead of parsed objects /// private bool sendStreams = false; /// /// Gets or sets the message received handler. /// public event WebSocketMessageReceivedEventInternalHandler WebSocketMessageReceived; /// /// Gets or sets the stream received handler. /// public event WebSocketStreamReceivedEventInternalHandler WebSocketStreamReceived; /// /// Gets a value indicating whether the web socket is connected. /// public bool IsConnected { get; private set; } /// /// Gets a value indicating whether the web socket is listening for messages. /// public bool IsListeningForMessages { get; private set; } /// /// Initialize a connection to the websocket. /// /// The relative portion of the uri path that specifies the API to call. /// The query string portion of the uri path that provides the parameterized data. /// The task of opening the websocket connection. internal async Task ConnectAsync(string apiPath, string payload = null) { if (this.IsConnected) { return; } Uri uri = Utilities.BuildEndpoint( this.deviceConnection.WebSocketConnection, apiPath, payload); await this.ConnectInternalAsync(uri); } /// /// Closes the connection to the websocket and stop listening for messages. /// /// The task of closing the websocket connection. internal async Task CloseAsync() { if (this.IsConnected) { if (this.IsListeningForMessages) { await this.StopListeningForMessagesInternalAsync(); } await this.CloseInternalAsync(); } } /// /// Starts listening for messages from the websocket. Once they are received they are parsed and the WebSocketMessageReceived event is raised. /// /// The task of listening for messages from the websocket. internal async Task ReceiveMessagesAsync() { if (this.IsConnected && !this.IsListeningForMessages) { await this.StartListeningForMessagesInternalAsync(); } } /// /// Sends a message to the server. /// /// The message to send. /// The task of sending a message to the websocket. internal async Task SendMessageAsync(string message) { if (this.IsConnected) { await this.SendMessageInternalAsync(message); } } /// /// Converts received stream to a parsed object and passes it to /// the WebSocketMessageReceived handler. The sendstreams property can be used to /// override this and send the instead via the WebSocketStreamReceived handler. /// /// The received stream. private void ConvertStreamToMessage(Stream stream) { if (stream != null && stream.Length != 0) { if (this.sendStreams) { this.WebSocketStreamReceived?.Invoke( this, new WebSocketMessageReceivedEventArgs(stream)); } else { DataContractJsonSerializerSettings settings = new DataContractJsonSerializerSettings() { UseSimpleDictionaryFormat = true }; T message = DevicePortal.ReadJsonStream(stream, settings); this.WebSocketMessageReceived?.Invoke( this, new WebSocketMessageReceivedEventArgs(message)); } } } } }