//----------------------------------------------------------------------------------------------
//
// 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));
}
}
}
}
}