/// <summary> /// Accepts the device stream request, connects to the local proxy target and maintains incoming and outgoing connections /// </summary> /// <param name="request">The device stream request</param> /// <param name="cancellationToken">Token used for cancelling this operation</param> /// <returns>An awaitable async task</returns> private async Task InitiateProxyConnectionsAsync(DeviceStreamRequest request, CancellationToken cancellationToken) { try { logger.LogInformation($"Starting a proxy connection. RequestId: {request.RequestId} Name: {request.Name}"); await deviceClient.AcceptDeviceStreamRequestAsync(request, cancellationToken).ConfigureAwait(false); using var streamClient = await GetStreamingClientAsync(request.Uri, request.AuthorizationToken, cancellationToken).ConfigureAwait(false); using (var tcpClient = new TcpClient()) { await tcpClient.ConnectAsync(settings.RemoteHost, settings.RemotePort).ConfigureAwait(false); using var networkStream = tcpClient.GetStream(); await Task.WhenAny( HandleIncomingDataAsync(networkStream, streamClient, cancellationToken), HandleOutgoingDataAsync(networkStream, streamClient, cancellationToken)).ConfigureAwait(false); networkStream.Close(); } await streamClient.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, cancellationToken).ConfigureAwait(false); } finally { logger.LogInformation($"Stopped a proxy connection. RequestId: {request.RequestId} Name: {request.Name}"); } }
public async Task RunSampleAsync(bool acceptDeviceStreamingRequest, CancellationTokenSource cancellationTokenSource) { try { Update("Awaiting connection."); DeviceStreamRequest streamRequest = await _deviceClient.WaitForDeviceStreamRequestAsync(cancellationTokenSource.Token).ConfigureAwait(false); Update("Got request."); if (streamRequest != null) { if (acceptDeviceStreamingRequest) { try { await _deviceClient.AcceptDeviceStreamRequestAsync(streamRequest, cancellationTokenSource.Token).ConfigureAwait(false); Update("Accepted request."); using (ClientWebSocket webSocket = await DeviceStreamingCommon.GetStreamingClientAsync(streamRequest.Url, streamRequest.AuthorizationToken, cancellationTokenSource.Token).ConfigureAwait(false)) { Update("Got client stream."); using (TcpClient tcpClient = new TcpClient()) { Update("Connecting to stream."); await tcpClient.ConnectAsync(_host, _port).ConfigureAwait(false); using (NetworkStream localStream = tcpClient.GetStream()) { Update("Device starting streaming"); counter = 0; await Task.WhenAny( HandleIncomingDataAsync(localStream, webSocket, cancellationTokenSource.Token), HandleOutgoingDataAsync(localStream, webSocket, cancellationTokenSource.Token)).ConfigureAwait(false); Update("Closing stream"); localStream.Close(); Update("Closed stream"); } } await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, String.Empty, cancellationTokenSource.Token).ConfigureAwait(false); } } catch (Exception ex) { Update("Device got an inner exception. Exiting connection."); //: {0}", ex); } } else { await _deviceClient.RejectDeviceStreamRequestAsync(streamRequest, cancellationTokenSource.Token).ConfigureAwait(false); } } } catch (Exception ex) { ErrorMsg("Device got an outer exception", ex); } }
public static async Task RegisterDeviceStreamCallback(this DeviceClient moduleClient, Func <ClientWebSocket, CancellationToken, Task> callback, CancellationToken ct) { int sleeptime = 1000; // This will run until the cancelation token is canceled while (!ct.IsCancellationRequested) { Console.WriteLine("Waiting for connection request"); DeviceStreamRequest request; try { request = await moduleClient.WaitForDeviceStreamRequestAsync(ct); Console.WriteLine("Got connection request"); await moduleClient.AcceptDeviceStreamRequestAsync(request, ct).ConfigureAwait(false); } catch (Exception ex) { Console.WriteLine("Request got exeption:"); Console.WriteLine(ex); Console.WriteLine($"Trying again in {sleeptime} seconds."); await Task.Delay(sleeptime); /* Max sleeptime is 10 minutes */ if (sleeptime < 1000 * 60 * 10) { sleeptime *= 2; } continue; } sleeptime = 1000; using (ClientWebSocket webSocket = await DeviceStreamWebsocket.MakeWebSocket(request.Url, request.AuthorizationToken, ct)) { try { await callback(webSocket, ct); } catch (WebSocketException ex) { Console.WriteLine("Websocket threw exception."); Console.WriteLine(ex); } Console.WriteLine("Finished Connection Request"); } Console.WriteLine("Closing websocket"); } }
public async Task RegisterDevice(IConfigurationRoot configuration) { string deviceConnectionString = configuration.GetValue <string>("DeviceConnectionString"); Console.WriteLine($"DeviceConnectionString: {deviceConnectionString}"); DeviceClient deviceClient = DeviceClient.CreateFromConnectionString(deviceConnectionString, TransportType.Amqp_WebSocket_Only); while (true) { try { Console.WriteLine("Waiting for stream request"); Console.WriteLine($"Before: {DateTime.Now.ToString()}"); DeviceStreamRequest streamRequest = await deviceClient.WaitForDeviceStreamRequestAsync(); Console.WriteLine("Received stream request"); if (streamRequest != null) { await deviceClient.AcceptDeviceStreamRequestAsync(streamRequest); using (ClientWebSocket webSocket = await GetStreamingClientAsync(streamRequest.Url, streamRequest.AuthorizationToken)) { using (TcpClient tcpClient = new TcpClient()) { string host = configuration.GetValue <string>("ProxyHostName"); int port = configuration.GetValue <int>("ProxyPort"); await tcpClient.ConnectAsync(host, port).ConfigureAwait(false); using (NetworkStream localStream = tcpClient.GetStream()) { Console.WriteLine("Starting streaming"); await Task.WhenAny( HandleIncomingDataAsync(localStream, webSocket), HandleOutgoingDataAsync(localStream, webSocket)); localStream.Close(); } } await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, String.Empty, CancellationToken.None); } } } catch (Exception e) { Console.WriteLine($"After: {DateTime.Now.ToString()}"); Console.WriteLine($"Exception: {e.ToString()}"); } } }
public async Task RunSampleAsync(bool acceptDeviceStreamingRequest = true) { byte[] buffer = new byte[1024]; using (var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMinutes(5))) { DeviceStreamRequest streamRequest = await _deviceClient .WaitForDeviceStreamRequestAsync(cancellationTokenSource.Token) .ConfigureAwait(false); if (streamRequest != null) { if (acceptDeviceStreamingRequest) { await _deviceClient .AcceptDeviceStreamRequestAsync(streamRequest, cancellationTokenSource.Token) .ConfigureAwait(false); using (ClientWebSocket webSocket = await DeviceStreamingCommon .GetStreamingClientAsync(streamRequest.Url, streamRequest.AuthorizationToken, cancellationTokenSource.Token) .ConfigureAwait(false)) { WebSocketReceiveResult receiveResult = await webSocket .ReceiveAsync(new ArraySegment <byte>(buffer, 0, buffer.Length), cancellationTokenSource.Token) .ConfigureAwait(false); Console.WriteLine("Received stream data: {0}", Encoding.UTF8.GetString(buffer, 0, receiveResult.Count)); await webSocket .SendAsync(new ArraySegment <byte>(buffer, 0, receiveResult.Count), WebSocketMessageType.Binary, true, cancellationTokenSource.Token) .ConfigureAwait(false); Console.WriteLine("Sent stream data: {0}", Encoding.UTF8.GetString(buffer, 0, receiveResult.Count)); await webSocket .CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, cancellationTokenSource.Token) .ConfigureAwait(false); } } else { await _deviceClient.RejectDeviceStreamRequestAsync(streamRequest, cancellationTokenSource.Token).ConfigureAwait(false); } } await _deviceClient.CloseAsync().ConfigureAwait(false); } }
public async Task RunSampleAsync(bool acceptDeviceStreamingRequest) { using (var cancellationTokenSource = new CancellationTokenSource(new TimeSpan(0, 5, 0))) { DeviceStreamRequest streamRequest = await _deviceClient.WaitForDeviceStreamRequestAsync(cancellationTokenSource.Token).ConfigureAwait(false); if (streamRequest != null) { if (acceptDeviceStreamingRequest) { await _deviceClient.AcceptDeviceStreamRequestAsync(streamRequest, cancellationTokenSource.Token).ConfigureAwait(false); using (ClientWebSocket webSocket = await DeviceStreamingCommon.GetStreamingClientAsync(streamRequest.Url, streamRequest.AuthorizationToken, cancellationTokenSource.Token).ConfigureAwait(false)) { using (TcpClient tcpClient = new TcpClient()) { await tcpClient.ConnectAsync(_host, _port).ConfigureAwait(false); using (NetworkStream localStream = tcpClient.GetStream()) { Console.WriteLine("Starting streaming"); await Task.WhenAny( HandleIncomingDataAsync(localStream, webSocket, cancellationTokenSource.Token), HandleOutgoingDataAsync(localStream, webSocket, cancellationTokenSource.Token)).ConfigureAwait(false); localStream.Close(); } } await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, String.Empty, cancellationTokenSource.Token).ConfigureAwait(false); } } else { await _deviceClient.RejectDeviceStreamRequestAsync(streamRequest, cancellationTokenSource.Token).ConfigureAwait(false); } } } }
/// <summary> /// The actual Device Streaming method at Device end of the pipe /// </summary> /// <param name="acceptDeviceStreamingRequest"></param> /// <returns></returns> private async Task RunDeviceAsync(bool acceptDeviceStreamingRequest) { isManualCancel = false; string errorMsg = ""; string updateMsg = ""; byte[] buffer = new byte[1024]; ClientWebSocket webSocket = null; byte[] sendBuffer; try { using (cancellationTokenSourceTimeout = new CancellationTokenSource(DeviceStreamingCommon.DeviceTimeout)) { try { cancellationTokenSourceTimeout.Token.Register(() => { webSocket?.Abort(); webSocket?.Dispose(); }); updateMsg = "Starting Device Stream Request."; System.Diagnostics.Debug.WriteLine(updateMsg); UpdateStatus(updateMsg); Microsoft.Azure.Devices.Client.DeviceStreamRequest streamRequest = await deviceClient.WaitForDeviceStreamRequestAsync(cancellationTokenSourceTimeout.Token).ConfigureAwait(false); if (streamRequest != null) { if (acceptDeviceStreamingRequest) { await deviceClient.AcceptDeviceStreamRequestAsync(streamRequest, cancellationTokenSourceTimeout.Token).ConfigureAwait(false); updateMsg = "Device got a connection."; UpdateStatus(updateMsg); using (webSocket = await DeviceStreamingCommon.GetStreamingClientAsync(streamRequest.Url, streamRequest.AuthorizationToken, cancellationTokenSourceTimeout.Token).ConfigureAwait(false)) { updateMsg = string.Format("Device got stream: Name={0}. Socket open.", streamRequest.Name); UpdateStatus(updateMsg); bool keepAlive = false; do { updateMsg = string.Format("Device is connected and listening"); UpdateStatus(updateMsg); WebSocketReceiveResult receiveResult = await webSocket.ReceiveAsync(new ArraySegment <byte>(buffer, 0, buffer.Length), cancellationTokenSourceTimeout.Token).ConfigureAwait(false); if (receiveResult.MessageType == WebSocketMessageType.Close) { UpdateStatus("Received Close msg"); keepAlive = false; } else { string MsgIn = Encoding.UTF8.GetString(buffer, 0, receiveResult.Count); //If the received text is more than one line only use the first line string[] lines = MsgIn.Split(new char[] { '\r', '\n' }); if (lines.Length > 1) { MsgIn = lines[0]; } updateMsg = string.Format("Device Received stream data: {0}.", MsgIn); UpdateStatus(updateMsg); //Get keepAlive and respond flags and strip from msg in bool respond = true; try { MsgIn = DeviceCurrentSettings.ProcessMsgIn(MsgIn); respond = DeviceCurrentSettings.ResponseExpected; keepAlive = DeviceCurrentSettings.KeepAlive; if (DeviceCurrentSettings.AutoStartDeviceChanged) { ActionCmdD?.Invoke(DeviceCurrentSettings.AutoStartDevice, "", 0, 0); } if (DeviceCurrentSettings.KeepDeviceListeningChanged) { ActionCmdD?.Invoke(DeviceCurrentSettings.KeepDeviceListening, "", 0, 1); } } catch (System.NotImplementedException) { errorMsg += "DeviceCurrentSettings not properly Implemented"; keepAlive = false; respond = false; } string msgOut = MsgIn; Message sendMessage = null; try { if (OnRecvdTextIO != null) { msgOut = OnRecvdTextIO(MsgIn, out sendMessage); } } catch (Exception exx) { errorMsg += "OnRecvdTextIO not properly Implemented: " + exx.Message; keepAlive = false; respond = false; } if (respond) { //if (sendMessage == null) //{ sendBuffer = Encoding.UTF8.GetBytes(msgOut); await webSocket.SendAsync(new ArraySegment <byte>(sendBuffer, 0, sendBuffer.Length), WebSocketMessageType.Binary, true, cancellationTokenSourceTimeout.Token).ConfigureAwait(false); //} //else //{ // sendBuffer = sendMessage.GetBytes(); // var xx = new ArraySegment<byte>(sendBuffer, 0, sendBuffer.Length); // byte[] longer = xx.Array; // byte[] shortArray = longer.Take(sendBuffer.Length).ToArray(); // Microsoft.Azure.Devices.Client.Message message = null; // message = new Microsoft.Azure.Devices.Client.Message(shortArray); // await webSocket.SendAsync(xx, WebSocketMessageType.Binary, true, cancellationTokenSourceTimeout.Token).ConfigureAwait(false); //} updateMsg = string.Format("Device Sent stream data: {0}", Encoding.UTF8.GetString(sendBuffer, 0, sendBuffer.Length)); UpdateStatus(updateMsg); } //By default do not loop } } while (keepAlive); updateMsg = "Closing Device Socket Normally."; UpdateStatus(updateMsg); await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, String.Empty, cancellationTokenSourceTimeout.Token).ConfigureAwait(false); webSocket = null; } } else { await deviceClient.RejectDeviceStreamRequestAsync(streamRequest, cancellationTokenSourceTimeout.Token).ConfigureAwait(false); } } await deviceClient.CloseAsync().ConfigureAwait(false); } catch (Microsoft.Azure.Devices.Client.Exceptions.IotHubCommunicationException) { if ((bool)cancellationTokenSourceTimeout?.IsCancellationRequested) { System.Diagnostics.Debug.WriteLine("1 Error RunSvcAsync(): Timed Out."); errorMsg += " Timed Out"; } else { System.Diagnostics.Debug.WriteLine("1 Error RunDeviceAsync(): Hub connection failure"); errorMsg = "Hub connection failure"; } } catch (Microsoft.Azure.Devices.Common.Exceptions.DeviceNotFoundException) { System.Diagnostics.Debug.WriteLine("1 Error RunDeviceAsync(): Device not found"); errorMsg = "Device not found"; } catch (TaskCanceledException) { System.Diagnostics.Debug.WriteLine("1 Error RunDeviceAsync(): Task cancelled"); errorMsg = "Task cancelled"; } catch (OperationCanceledException eex) { System.Diagnostics.Debug.WriteLine("1 Error RunDeviceAsync(): Operation cancelled \r\n" + eex.Message); errorMsg = "Operation cancelled"; } catch (Exception ex) { if ((bool)(cancellationTokenSourceManual?.IsCancellationRequested)) { System.Diagnostics.Debug.WriteLine("1 Error RunSvcAsync(): Cancelled."); errorMsg += " Cancelled"; } else if ((bool)(cancellationTokenSourceTimeout?.IsCancellationRequested)) { System.Diagnostics.Debug.WriteLine("1 Error RunSvcAsync(): Timed Out."); errorMsg += " Timed Out"; } else if (!ex.Message.Contains("Timed out")) { System.Diagnostics.Debug.WriteLine("1 Error RunSvcAsync(): " + ex.Message); errorMsg += " " + ex.Message; } else { System.Diagnostics.Debug.WriteLine("1 Error RunSvcAsync(): Timed out"); errorMsg += " Timed Out"; } } } } catch (Microsoft.Azure.Devices.Client.Exceptions.IotHubCommunicationException) { System.Diagnostics.Debug.WriteLine("2 Error RunDeviceAsync(): Hub connection failure"); errorMsg = "Hub connection failure"; } catch (Microsoft.Azure.Devices.Common.Exceptions.DeviceNotFoundException) { System.Diagnostics.Debug.WriteLine("2 Error RunDeviceAsync(): Device not found"); errorMsg = "Device not found"; } catch (TaskCanceledException) { System.Diagnostics.Debug.WriteLine("2 Error RunDeviceAsync(): Task cancelled"); errorMsg = "Task cancelled"; } catch (OperationCanceledException eex) { System.Diagnostics.Debug.WriteLine("2 Error RunDeviceAsync(): Operation cancelled \r\n" + eex.Message); errorMsg = "Operation cancelled"; } catch (Exception ex) { if ((bool)(cancellationTokenSourceManual?.IsCancellationRequested)) { System.Diagnostics.Debug.WriteLine("2 Error RunSvcAsync(): Cancelled."); errorMsg += " Cancelled"; } else if ((bool)(cancellationTokenSourceTimeout?.IsCancellationRequested)) { System.Diagnostics.Debug.WriteLine("2 Error RunSvcAsync(): Timed Out."); errorMsg += " Timed Out"; } else if (!ex.Message.Contains("Timed out")) { System.Diagnostics.Debug.WriteLine("2 Error RunSvcAsync(): " + ex.Message); errorMsg += " " + ex.Message; } else { System.Diagnostics.Debug.WriteLine("2 Error RunSvcAsync(): Timed out"); errorMsg += " Timed Out"; } }; if (webSocket != null) { if (webSocket.CloseStatus != WebSocketCloseStatus.NormalClosure) { updateMsg = "Aborting Device Socket as is errant or cancelled: " + errorMsg; UpdateStatus(updateMsg); webSocket.Abort(); updateMsg = "Aborted Device Socket as was errant or cancelled: " + errorMsg; UpdateStatus(updateMsg); } else { updateMsg = "Socket closed normally: " + errorMsg; UpdateStatus(updateMsg); } } else { if (isManualCancel) { updateMsg = "Socket closed Normally: Manually "; } else { updateMsg = "Socket closed Normally: " + errorMsg; } UpdateStatus(updateMsg); } webSocket = null; cancellationTokenSourceTimeout = null; }