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); } }
private static async void HandleIncomingConnectionsAndCreateStreams(string deviceId, ServiceClient serviceClient, TcpClient tcpClient) { DeviceStreamRequest deviceStreamRequest = new DeviceStreamRequest( streamName: "ProxyStreamFromSvc" ); using (var localStream = tcpClient.GetStream()) { Update("Awaiting connection"); using (cancellationTokenSourceOuter = new CancellationTokenSource()) { DeviceStreamResponse result = await serviceClient.CreateStreamAsync(deviceId, deviceStreamRequest, cancellationTokenSourceOuter.Token).ConfigureAwait(false); Update($"Stream response received: Name={deviceStreamRequest.StreamName} IsAccepted={result.IsAccepted}"); if (result.IsAccepted) { try { using (cancellationTokenSource = new CancellationTokenSource()) using (ClientWebSocket remoteStream = await DeviceStreamingCommon.GetStreamingClientAsync(result.Url, result.AuthorizationToken, cancellationTokenSource.Token).ConfigureAwait(false)) { Update("Starting streaming"); counter = 0; await Task.WhenAny( HandleIncomingDataAsync(localStream, remoteStream, cancellationTokenSource.Token), HandleOutgoingDataAsync(localStream, remoteStream, cancellationTokenSource.Token)).ConfigureAwait(false); } Update("Done streaming"); } catch (Exception ex) { ErrorMsg("Service got an exception: {0}", ex); } } } } tcpClient.Close(); }
private async Task RunSvcAsync() { string errorMsg = ""; string updateMsg = ""; using (cancellationTokenSourceManual = new CancellationTokenSource()) { ClientWebSocket stream = null; try { DeviceStreamRequest deviceStreamRequest = new DeviceStreamRequest( streamName: "TestStream" ); updateMsg = "Starting Svc TestStream"; UpdateStatus(updateMsg); cancellationTokenSourceManual.Token.Register(() => { _serviceClient?.CloseAsync(); _serviceClient?.Dispose(); }); DeviceStreamResponse result = await _serviceClient.CreateStreamAsync(_deviceId, deviceStreamRequest).ConfigureAwait(false); updateMsg = string.Format("Svc Stream response received: Name={0} IsAccepted={1}", deviceStreamRequest.StreamName, result.IsAccepted); UpdateStatus(updateMsg); if (result.IsAccepted) { using (cancellationTokenSourceTimeout = new CancellationTokenSource(DeviceStreamingCommon.DeviceTimeout)) { try { using (stream = await DeviceStreamingCommon.GetStreamingClientAsync(result.Url, result.AuthorizationToken, cancellationTokenSourceTimeout.Token).ConfigureAwait(false)) { updateMsg = "Stream is open."; UpdateStatus(updateMsg); bool keepAlive = false; MsgOutWaitHandle = new AutoResetEvent(true); do { //Nb: Not waited on first entry as waiting for msgOut, which we already have. updateMsg = "Stream is open. Waiting for msg to send."; UpdateStatus(updateMsg); MsgOutWaitHandle.WaitOne(); updateMsg = "Sending msg."; UpdateStatus(updateMsg); bool caught = false; try { MsgOut = SvcCurrentSettings.ProcessMsgOut(MsgOut, SvcCurrentSettings.KeepAlive, SvcCurrentSettings.ResponseExpected, DevKeepListening , DevAutoStart ); } catch (NotImplementedException ) { errorMsg += "DeviceCurrentSettings not properly implemented"; keepAlive = false; caught = true; } if (!caught) { await SendMsg(stream, MsgOut, cancellationTokenSourceTimeout); updateMsg = "Sent msg."; UpdateStatus(updateMsg); if (this.SvcCurrentSettings.ResponseExpected) { byte[] receiveBuffer = new byte[1024]; System.ArraySegment<byte> ReceiveBuffer = new ArraySegment<byte>(receiveBuffer); var receiveResult = await stream.ReceiveAsync(ReceiveBuffer, cancellationTokenSourceTimeout.Token).ConfigureAwait(false); MsgIn = Encoding.UTF8.GetString(receiveBuffer, 0, receiveResult.Count); string subStrn = Azure_IoTHub_DeviceStreaming.DeviceStreamingCommon.DeviceInSimuatedDeviceModeStrn; int subStrnLen = subStrn.Length; string subStrn2 = Azure_IoTHub_Sensors.TelemetryDataPoint.Prefix; int subStrnLen2 = subStrn2.Length; if (MsgIn.Length>= subStrnLen) if (MsgIn.Substring(0,subStrnLen) == subStrn) { MsgIn = MsgIn.Substring(subStrnLen); Azure_IoTHub_Telemetry.SyntheticIoTMessage iotHubMessage = Azure_IoTHub_Telemetry.SyntheticIoTMessage.Deserialize(MsgIn); Microsoft.Azure.Devices.Client.Message message = iotHubMessage.ToMessage(); Microsoft.Azure.EventHubs.EventData eventData = Azure_IoTHub_Telemetry.SyntheticIoTMessage.ToEventData(message); MsgIn = Azure_IoTHub_Telemetry.SyntheticIoTMessage.EventData_ToString(eventData); } else if (MsgIn.Length >= subStrnLen2) if (MsgIn.Substring(0, subStrnLen2) == subStrn2) { MsgIn = MsgIn.Substring(subStrnLen2); Azure_IoTHub_Sensors.TelemetryDataPoint telemetry = Azure_IoTHub_Sensors.TelemetryDataPoint.Deserialize(MsgIn); MsgIn = telemetry.ToString(); //Microsoft.Azure.Devices.Client.Message message = iotHubMessage.ToMessage(); //Microsoft.Azure.EventHubs.EventData eventData = Azure_IoTHub_Telemetry.SyntheticIoTMessage.ToEventData(message); //MsgIn = Azure_IoTHub_Telemetry.SyntheticIoTMessage.EventData_ToString(eventData); } keepAlive = false; if (SvcCurrentSettings != null) keepAlive = this.SvcCurrentSettings.KeepAlive; try { if (OnRecvdTextD != null) OnRecvdTextD(MsgIn); } catch (Exception exx) { errorMsg += "OnRecvdTextD not properly implemented: " + exx.Message; keepAlive = false; } updateMsg = string.Format("Svc Received stream data: {0}", MsgIn); UpdateStatus(updateMsg); } MsgOutWaitHandle.Reset(); } } while (keepAlive) ; MsgOutWaitHandle = null; updateMsg = "Closing Svc Socket"; UpdateStatus(updateMsg); await stream.CloseAsync(WebSocketCloseStatus.NormalClosure, String.Empty, cancellationTokenSourceTimeout.Token).ConfigureAwait(false); stream = null; } } catch (Microsoft.Azure.Devices.Client.Exceptions.IotHubCommunicationException) { System.Diagnostics.Debug.WriteLine("1 Error RunSvcAsync(): Hub connection failure"); errorMsg = "Hub connection failure"; } catch (Microsoft.Azure.Devices.Common.Exceptions.DeviceNotFoundException) { System.Diagnostics.Debug.WriteLine("1 Error RunSvcAsync(): Device not found"); errorMsg = "Device not found"; } catch (TaskCanceledException) { System.Diagnostics.Debug.WriteLine("1 Error RunSvcAsync(): Task cancelled"); errorMsg = "Task cancelled"; } catch (OperationCanceledException) { System.Diagnostics.Debug.WriteLine("1 Error RunSvcAsync(): Operation cancelled"); 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("2 Error RunSvcAsync(): Timed out"); errorMsg = "Timed Out"; } } } } } catch (Microsoft.Azure.Devices.Client.Exceptions.IotHubCommunicationException) { System.Diagnostics.Debug.WriteLine("2 Error RunSvcAsync(): Hub connection failure"); errorMsg += " Hub connection failure"; } catch (Microsoft.Azure.Devices.Common.Exceptions.DeviceNotFoundException) { System.Diagnostics.Debug.WriteLine("2 Error RunSvcAsync(): Device not found"); errorMsg += " Device not found"; } catch (TaskCanceledException) { System.Diagnostics.Debug.WriteLine("2 Error RunSvcAsync(): Task cancelled"); errorMsg += " Task cancelled"; } catch (OperationCanceledException) { System.Diagnostics.Debug.WriteLine("2 Error RunSvcAsync(): Operation cancelled"); 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 (stream != null) { if (stream.CloseStatus != WebSocketCloseStatus.NormalClosure) { updateMsg= "Aborting Svc Socket as is errant or cancelled: " + errorMsg; UpdateStatus(updateMsg); stream.Abort(); updateMsg = "Aborted Svc Socket as was errant or cancelled:" + errorMsg; UpdateStatus(updateMsg); } else { updateMsg = "Socket closed normally: " + errorMsg; UpdateStatus(updateMsg); } stream = null; } else { updateMsg = "Socket closed Normally: " + errorMsg; UpdateStatus(updateMsg); } deviceStream_Svc = null; MsgOutWaitHandle = null; cancellationTokenSourceTimeout = null; } }
/// <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; }