/// <inheritdoc /> public async Task <IMessage> ReadMessageAsync(CancellationToken cancellationToken, int timeout = Timeout.Infinite) { var headerBytes = new byte[6]; using (var cts = cancellationToken.AddTimeout(timeout)) { await this.sslStream.ReadAsync(headerBytes, 0, headerBytes.Length, cts.Token) .HandleTimeout(cts.Token).ConfigureAwait(false); } var type = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(headerBytes, 0)); var size = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(headerBytes, 2)); var messageBytes = new byte[size]; using (var cts = cancellationToken.AddTimeout(timeout)) { await this.sslStream.ReadAsync(messageBytes, 0, size, cts.Token) .HandleTimeout(cts.Token).ConfigureAwait(false); } if (type == (int)MessageType.UDPTunnel) { return(new UDPTunnel.Builder { Packet = ByteString.CopyFrom(messageBytes) }.Build()); } else { return(this.messageFactory.Deserialize((MessageType)type, ByteString.CopyFrom(messageBytes))); } }
public async Task <GrpcResponseEnvelope <TResponse> > Execute <TRequest, TResponse>(TRequest request, CancellationToken cancellationToken) { if (request == null) { throw new ArgumentNullException(); } // timeout cancellationToken = cancellationToken.AddTimeout(_configuration.TimeoutMs); // ch info var chInfo = _cqrsAdapter.ToCqrsChannelInfo().FirstOrDefault(x => x.ReqType == request.GetType() && x.RspType == typeof(TResponse)); if (chInfo == null) { throw new ArgumentException("Invaid request type."); } // calll var callMethod = GetType().GetMethods(BindingFlags.Instance | BindingFlags.NonPublic) .First(x => x.Name == nameof(GrpcCqrsClient.CallUnaryMethodAsync)) .MakeGenericMethod(chInfo.ReqType, chInfo.RspType, chInfo.ChReqType, chInfo.ChRspType, chInfo.ChRspEnvType); var execTask = callMethod.Invoke(this, new object[] { request, default(CancellationToken) }) as Task <GrpcResponseEnvelope <TResponse> >; var result = await execTask; return(result); }
public static async Task <InitializationResult <AuthenticatedStream> > RegisterWithServerAsync( Stream serverStream, byte[] presharedKey, Guid ownGuid, Guid serverGuid, IAuthenticatedConnectionFactory authenticatedConnectionFactory, X509Certificate2 clientCertificate, X509Certificate serverCertificate, ICryptographicService otp, CancellationToken token) { InitializationResult <AuthenticatedStream> From(CommunicationResult res) => From <AuthenticatedStream>(res); if (!otp.CanEncrypt) { throw new ArgumentException("otp needs to be able to encrypt"); } token = token.AddTimeout(DefaultTimeout); await serverStream.WriteSafelyAsync(presharedKey, token); var serverGuidResult = await serverStream.ReceiveGuidSafelyAsync(token); if (!serverGuidResult.Successful) { return(From(serverGuidResult)); } if (!serverGuidResult.Result.Equals(serverGuid)) { return(new InitializationResult <AuthenticatedStream> { Successful = false, Error = new InitializationError { ErrorType = InitializationErrorType.Identification, Message = $"Expected server to be '{serverGuid}', but instead found '{serverGuidResult.Result}'", }, }); } await serverStream.WriteSafelyAsync( ownGuid, (int)InitiationMode.Otp, token); var exportCertificate = clientCertificate.Export(X509ContentType.Cert); var encryptedCertificate = otp.Encrypt(exportCertificate); await serverStream.WriteSafelyAsync( (int)CommunicationData.PublicKey, encryptedCertificate.Length, encryptedCertificate, token); return(await EstablishEncryptedCommunication(false, serverGuid, authenticatedConnectionFactory, serverStream, token)); }
/// <summary> /// Write a message to the SSL stream /// </summary> /// <param name="type">Type of message</param> /// <param name="messageBytes">Byte array of serialized message</param> /// <param name="cancellationToken">The token to monitor for cancellation requests</param> /// <returns>Empty task</returns> private async Task WriteMessageAsync(MessageType type, byte[] messageBytes, CancellationToken cancellationToken) { var typeBytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)type)); var sizeBytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(messageBytes.Length)); await this.writeSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); using (var cts = cancellationToken.AddTimeout(WriteTimeout)) { await this.sslStream.WriteAsync(typeBytes, 0, typeBytes.Length, cts.Token) .HandleTimeout(cts.Token).ConfigureAwait(false); await this.sslStream.WriteAsync(sizeBytes, 0, sizeBytes.Length, cts.Token) .HandleTimeout(cts.Token).ConfigureAwait(false); await this.sslStream.WriteAsync(messageBytes, 0, messageBytes.Length, cts.Token) .HandleTimeout(cts.Token).ConfigureAwait(false); } this.writeSemaphore.Release(); }
/// <summary> /// Waits for a release signal that indicates that this activity has been executed /// successfully in the background. /// </summary> /// <param name="cancellationToken">The token to monitor for cancellation requests.</param> /// <returns>A Task that represents the asynchronous operation.</returns> public async STT.Task WaitForCompleteAsync(CancellationToken cancellationToken) { if (_finished) { return; } _waitingThreadId = Thread.CurrentThread.ManagedThreadId; var indexingActivity = this as IndexingActivityBase; SnTrace.IndexQueue.Write("IAQ: A{0} blocks the T{1}", indexingActivity?.Id, _waitingThreadId); if (Debugger.IsAttached) { // in debug mode wait without a timeout await _finishSignal.WaitAsync(cancellationToken).ConfigureAwait(false); } else { try { var timeOut = TimeSpan.FromSeconds(Configuration.Indexing.IndexingActivityTimeoutInSeconds); await _finishSignal.WaitAsync(cancellationToken.AddTimeout(timeOut)).ConfigureAwait(false); } catch (OperationCanceledException) { var message = indexingActivity != null ? $"IndexingActivity is timed out. Id: {indexingActivity.Id}, Type: {indexingActivity.ActivityType}. " + $"Max task id and exceptions: {IndexManager.DistributedIndexingActivityQueue.GetCurrentCompletionState()}" : "Activity is not finishing on a timely manner"; throw new ApplicationException(message); } } }
internal async Task <IncomingMessage> PerformRequestAsync(CancellationToken cancellationToken) { int retryCounter = 0; IncomingMessage reply; var reassembler = new MessageReassembler(ctrl, this); while (retryCounter++ < retries) { // send message if (await outgoingMsg.SendAsync().ConfigureAwait(false)) { // need to have a timeout to cancel the process task otherwise it may end up waiting forever for this to return // because we have an external cancellation token and the above timeout cancellation token, need to combine both reply = await reassembler.ProcessAsync(cancellationToken.AddTimeout(waitRetryTimeout)).ConfigureAwait(false); if (reply != null) { return(reply); } } else { // send failed Debug.WriteLine("SEND FAILED..."); } // something went wrong, retry with a progressive back-off strategy await Task.Delay(200 *retryCounter); } Debug.WriteLine("exceeded attempts count..."); return(null); }
/// <summary> /// Essential Rx method. Drives state machine by reading data and processing it. This works in /// conjunction with NotificationThreadWorker [Tx]. /// </summary> internal async Task <IncomingMessage> ProcessAsync(CancellationToken cancellationToken) { int count; int bytesRead; try { while (true) { if (cancellationToken.IsCancellationRequested) { // cancellation requested Debug.WriteLine("cancel token"); return(GetCompleteMessage()); } switch (_state) { case ReceiveState.Initialize: _rawPos = 0; _messageBase = new MessageBase(); _messageBase.Header = new Packet(); _messageRaw = new MessageRaw(); _messageRaw.Header = _parent.CreateConverter().Serialize(_messageBase.Header); _state = ReceiveState.WaitingForHeader; DebuggerEventSource.Log.WireProtocolReceiveState(_state); break; case ReceiveState.WaitingForHeader: count = _messageRaw.Header.Length - _rawPos; Debug.WriteLine("WaitingForHeader"); // need to have a timeout to cancel the read task otherwise it may end up waiting forever for this to return // because we have an external cancellation token and the above timeout cancellation token, need to combine both bytesRead = await _parent.ReadBufferAsync(_messageRaw.Header, _rawPos, count, request.waitRetryTimeout, cancellationToken.AddTimeout(request.waitRetryTimeout)); _rawPos += bytesRead; // sanity check if (bytesRead != 32) { // doesn't look like a header, better restart _state = ReceiveState.Initialize; break; } while (_rawPos > 0) { int flag_Debugger = ValidMarker(markerDebugger); int flag_Packet = ValidMarker(markerPacket); if (flag_Debugger == 1 || flag_Packet == 1) { _state = ReceiveState.ReadingHeader; DebuggerEventSource.Log.WireProtocolReceiveState(_state); break; } if (flag_Debugger == 0 || flag_Packet == 0) { break; // Partial match. } _parent.App.SpuriousCharacters(_messageRaw.Header, 0, 1); Array.Copy(_messageRaw.Header, 1, _messageRaw.Header, 0, --_rawPos); } break; case ReceiveState.ReadingHeader: count = _messageRaw.Header.Length - _rawPos; Debug.WriteLine("ReadingHeader"); // need to have a timeout to cancel the read task otherwise it may end up waiting forever for this to return // because we have an external cancellation token and the above timeout cancellation token, need to combine both bytesRead = await _parent.ReadBufferAsync(_messageRaw.Header, _rawPos, count, request.waitRetryTimeout, cancellationToken.AddTimeout(request.waitRetryTimeout)); _rawPos += bytesRead; if (bytesRead != count) { break; } _state = ReceiveState.CompleteHeader; DebuggerEventSource.Log.WireProtocolReceiveState(_state); break; case ReceiveState.CompleteHeader: try { Debug.WriteLine("CompleteHeader"); _parent.CreateConverter().Deserialize(_messageBase.Header, _messageRaw.Header); if (VerifyHeader() == true) { Debug.WriteLine("CompleteHeader, header OK"); bool fReply = (_messageBase.Header.Flags & Flags.c_Reply) != 0; DebuggerEventSource.Log.WireProtocolRxHeader(_messageBase.Header.CrcHeader, _messageBase.Header.CrcData, _messageBase.Header.Cmd, _messageBase.Header.Flags, _messageBase.Header.Seq, _messageBase.Header.SeqReply, _messageBase.Header.Size); if (_messageBase.Header.Size != 0) { _messageRaw.Payload = new byte[_messageBase.Header.Size]; //reuse m_rawPos for position in header to read. _rawPos = 0; _state = ReceiveState.ReadingPayload; DebuggerEventSource.Log.WireProtocolReceiveState(_state); break; } else { _state = ReceiveState.CompletePayload; DebuggerEventSource.Log.WireProtocolReceiveState(_state); break; } } Debug.WriteLine("CompleteHeader, header not valid"); } //catch (ThreadAbortException) //{ // throw; //} catch (Exception e) { Debug.WriteLine("Fault at payload deserialization:\n\n{0}", e.ToString()); } _state = ReceiveState.Initialize; DebuggerEventSource.Log.WireProtocolReceiveState(_state); if ((_messageBase.Header.Flags & Flags.c_NonCritical) == 0) { // FIXME // evaluate the purpose of this reply back to the NanoFramework device, the nanoCLR doesn't seem to have to handle this. In the end it looks like this does have any real purpose and will only be wasting CPU. //await IncomingMessage.ReplyBadPacketAsync(m_parent, Flags.c_BadHeader); return(GetCompleteMessage()); } break; case ReceiveState.ReadingPayload: count = _messageRaw.Payload.Length - _rawPos; Debug.WriteLine("ReadingPayload"); // need to have a timeout to cancel the read task otherwise it may end up waiting forever for this to return // because we have an external cancellation token and the above timeout cancellation token, need to combine both bytesRead = await _parent.ReadBufferAsync(_messageRaw.Payload, _rawPos, count, request.waitRetryTimeout, cancellationToken.AddTimeout(request.waitRetryTimeout)); _rawPos += bytesRead; if (bytesRead != count) { break; } _state = ReceiveState.CompletePayload; DebuggerEventSource.Log.WireProtocolReceiveState(_state); break; case ReceiveState.CompletePayload: Debug.WriteLine("CompletePayload"); if (VerifyPayload() == true) { Debug.WriteLine("CompletePayload payload OK"); try { bool fReply = (_messageBase.Header.Flags & Flags.c_Reply) != 0; if ((_messageBase.Header.Flags & Flags.c_NACK) != 0) { _messageRaw.Payload = null; } if (await ProcessMessage(GetCompleteMessage(), fReply, cancellationToken)) { DebuggerEventSource.Log.WireProtocolReceiveState(_state); //Debug.WriteLine("*** leaving reassembler"); return(GetCompleteMessage()); } else { // this is not the message we were waiting // FIXME } //m_parent.App.ProcessMessage(this.GetCompleteMessage(), fReply); //m_state = ReceiveState.Initialize; //return; } //catch (ThreadAbortException) //{ // throw; //} catch (Exception e) { Debug.WriteLine("Fault at payload deserialization:\n\n{0}", e.ToString()); } } else { Debug.WriteLine("CompletePayload payload not valid"); } _state = ReceiveState.Initialize; DebuggerEventSource.Log.WireProtocolReceiveState(_state); if ((_messageBase.Header.Flags & Flags.c_NonCritical) == 0) { // FIXME // evaluate the purpose of this reply back to the NanoFramework device, the nanoCLR doesn't seem to have to handle this. In the end it looks like this does have any real purpose and will only be wasting CPU. await IncomingMessage.ReplyBadPacketAsync(_parent, Flags.c_BadPayload, cancellationToken); return(GetCompleteMessage()); } break; } } } catch (Exception ex) { _state = ReceiveState.Initialize; DebuggerEventSource.Log.WireProtocolReceiveState(_state); Debug.WriteLine($"*** EXCEPTION IN STATE MACHINE***:\r\n{ex.Message} \r\n{ex.StackTrace}"); throw; } Debug.WriteLine("??????? leaving reassembler"); return(GetCompleteMessage()); }
public async Task <byte[]> ReadBufferAsync(uint bytesToRead, TimeSpan waiTimeout, CancellationToken cancellationToken) { // device must be connected if (EventHandlerForSerialDevice.Current.IsDeviceConnected) { // serial works as a "single channel" so we can only TX or RX, // meaning that access to the resource has to be protected with a semephore await semaphore.WaitAsync(); // create a stream reader with serial device InputStream, if there isn't one already if (inputStreamReader == null) { inputStreamReader = new DataReader(EventHandlerForSerialDevice.Current.Device.InputStream); } try { // need to have a timeout to cancel the read task otherwise it may end up waiting forever for this to return // because we have an external cancellation token and the above timeout cancellation token, need to combine both Task <UInt32> loadAsyncTask = inputStreamReader.LoadAsync(bytesToRead).AsTask(cancellationToken.AddTimeout(waiTimeout)); // get how many bytes are available to read uint bytesRead = await loadAsyncTask; byte[] readBuffer = new byte[bytesToRead]; inputStreamReader.ReadBytes(readBuffer); return(readBuffer); } catch (TaskCanceledException) { // this is expected to happen, don't do anything with it } catch (NullReferenceException) { // this is expected to happen when there is anything to read, don't do anything with it } catch (Exception ex) { Debug.WriteLine($"SendRawBufferAsync-Serial-Exception occurred: {ex.Message}\r\n {ex.StackTrace}"); } finally { // relase serial device semaphore semaphore.Release(); // detach read buffer inputStreamReader.DetachBuffer(); } } else { // FIXME // NotifyDeviceNotConnected Debug.WriteLine("NotifyDeviceNotConnected"); } // return empty byte array return(new byte[0]); }
public async Task <uint> SendBufferAsync(byte[] buffer, TimeSpan waiTimeout, CancellationToken cancellationToken) { uint bytesWritten = 0; // device must be connected if (EventHandlerForSerialDevice.Current.IsDeviceConnected) { // create a stream writer with serial device OutputStream, if there isn't one already if (outputStreamWriter == null) { outputStreamWriter = new DataWriter(EventHandlerForSerialDevice.Current.Device.OutputStream); } // serial works as a "single channel" so we can only TX or RX, // meaning that access to the resource has to be protected with a semephore await semaphore.WaitAsync(); try { // write buffer to device outputStreamWriter.WriteBytes(buffer); // need to have a timeout to cancel the read task otherwise it may end up waiting forever for this to return // because we have an external cancellation token and the above timeout cancellation token, need to combine both Task <uint> storeAsyncTask = outputStreamWriter.StoreAsync().AsTask(cancellationToken.AddTimeout(waiTimeout)); bytesWritten = await storeAsyncTask; if (bytesWritten > 0) { LastActivity = DateTime.Now; } } catch (TaskCanceledException) { // this is expected to happen, don't do anything with this } catch (Exception ex) { Debug.WriteLine($"SendRawBufferAsync-Serial-Exception occurred: {ex.Message}\r\n {ex.StackTrace}"); } finally { semaphore.Release(); outputStreamWriter.DetachBuffer(); } } else { // NotifyDeviceNotConnected Debug.WriteLine("NotifyDeviceNotConnected"); } return(bytesWritten); }
public static async Task <InitializationResult> HandleInitializationOfClient( Stream clientStream, byte[] presharedKey, Guid serverGuid, IAuthenticatedConnectionFactory authenticatedConnectionFactory, ICryptographicService otp, Action <Guid, AuthenticatedStream> onClientConnected, Action <Guid, X509Certificate> onClientRegistered, Func <Guid, X509Certificate> getClientPublicKey, CancellationToken token) { token = token.AddTimeout(DefaultTimeout); if (token.IsCancellationRequested) { return(new InitializationResult { Successful = false, Error = new InitializationError { ErrorType = InitializationErrorType.CancellationRequested, } }); } if (!await GetAndVerifyPresharedKey(clientStream, presharedKey, token)) { return(new InitializationResult { Successful = false, Error = new InitializationError { ErrorType = InitializationErrorType.Protocol, Message = "The received pre-shared key did not match the pre-shared key for this application", }, }); } await clientStream.WriteSafelyAsync(serverGuid, token); var clientGuidResult = await clientStream.ReceiveGuidSafelyAsync(token); if (!clientGuidResult.Successful) { return(InitializationResult.From(clientGuidResult)); } var clientGuid = clientGuidResult.Result; var initiationModeResult = await clientStream.ReceiveInt32SafelyAsync(token); if (!initiationModeResult.Successful) { return(InitializationResult.From(initiationModeResult)); } switch ((InitiationMode)initiationModeResult.Result) { case InitiationMode.Otp: var clientRegistrationResult = await HandleClientRegistrationSafelyAsync(clientStream, serverGuid, authenticatedConnectionFactory, otp, token); if (clientRegistrationResult.Successful) { var(certificate, stream) = clientRegistrationResult.Result; onClientRegistered(clientGuid, certificate); onClientConnected(clientGuid, stream); } else { return(clientRegistrationResult); } return(new InitializationResult { Successful = true, }); case InitiationMode.Standard: var clientCertificate = getClientPublicKey(clientGuid); if (clientCertificate == null) { return(InitializationResult.Failed); } //var sessionKey = SymmetricKey.GenerateNewKey(symmetric.KeyLength); var encryptedStreamResult = await EstablishEncryptedCommunication(true, serverGuid, authenticatedConnectionFactory, clientStream, token); if (!encryptedStreamResult.Successful) { return(encryptedStreamResult); } onClientConnected(clientGuid, encryptedStreamResult.Result); return(new InitializationResult { Successful = true, }); case InitiationMode.None: return(new InitializationResult() { Successful = false, Error = new InitializationError() { ErrorType = InitializationErrorType.Protocol, Message = "Client did not send a valid initiation mode", }, }); default: throw new ProtocolException($"invalid initiation mode {initiationModeResult.Result}"); } }
/// <summary> /// Essential Rx method. Drives state machine by reading data and processing it. This works in /// conjunction with NotificationThreadWorker [Tx]. /// </summary> internal async Task <IncomingMessage> ProcessAsync(CancellationToken cancellationToken) { int count; int bytesRead; try { switch (m_state) { case ReceiveState.Initialize: if (cancellationToken.IsCancellationRequested) { // cancellation requested return(null); } m_rawPos = 0; m_base = new MessageBase(); m_base.m_header = new Packet(); m_raw = new MessageRaw(); m_raw.m_header = m_parent.CreateConverter().Serialize(m_base.m_header); m_state = ReceiveState.WaitingForHeader; DebuggerEventSource.Log.WireProtocolReceiveState(m_state); goto case ReceiveState.WaitingForHeader; case ReceiveState.WaitingForHeader: count = m_raw.m_header.Length - m_rawPos; //Debug.WriteLine("WaitingForHeader"); // need to have a timeout to cancel the read task otherwise it may end up waiting forever for this to return // because we have an external cancellation token and the above timeout cancellation token, need to combine both bytesRead = await m_parent.ReadBufferAsync(m_raw.m_header, m_rawPos, count, request.waitRetryTimeout, cancellationToken.AddTimeout(request.waitRetryTimeout)).ConfigureAwait(false); m_rawPos += bytesRead; // sanity check if (bytesRead != 32) { // doesn't look like a header, better restart m_state = ReceiveState.Initialize; goto case ReceiveState.Initialize; } while (m_rawPos > 0) { int flag_Debugger = ValidSignature(marker_Debugger); int flag_Packet = ValidSignature(marker_Packet); if (flag_Debugger == 1 || flag_Packet == 1) { m_state = ReceiveState.ReadingHeader; DebuggerEventSource.Log.WireProtocolReceiveState(m_state); goto case ReceiveState.ReadingHeader; } if (flag_Debugger == 0 || flag_Packet == 0) { break; // Partial match. } m_parent.App.SpuriousCharacters(m_raw.m_header, 0, 1); Array.Copy(m_raw.m_header, 1, m_raw.m_header, 0, --m_rawPos); } break; case ReceiveState.ReadingHeader: count = m_raw.m_header.Length - m_rawPos; //Debug.WriteLine("ReadingHeader"); // need to have a timeout to cancel the read task otherwise it may end up waiting forever for this to return // because we have an external cancellation token and the above timeout cancellation token, need to combine both bytesRead = await m_parent.ReadBufferAsync(m_raw.m_header, m_rawPos, count, request.waitRetryTimeout, cancellationToken.AddTimeout(request.waitRetryTimeout)).ConfigureAwait(false); m_rawPos += bytesRead; if (bytesRead != count) { break; } m_state = ReceiveState.CompleteHeader; DebuggerEventSource.Log.WireProtocolReceiveState(m_state); goto case ReceiveState.CompleteHeader; //break; case ReceiveState.CompleteHeader: try { //Debug.WriteLine("CompleteHeader"); m_parent.CreateConverter().Deserialize(m_base.m_header, m_raw.m_header); if (VerifyHeader() == true) { //Debug.WriteLine("CompleteHeader, header OK"); bool fReply = (m_base.m_header.m_flags & Flags.c_Reply) != 0; DebuggerEventSource.Log.WireProtocolRxHeader(m_base.m_header.m_crcHeader, m_base.m_header.m_crcData, m_base.m_header.m_cmd, m_base.m_header.m_flags, m_base.m_header.m_seq, m_base.m_header.m_seqReply, m_base.m_header.m_size); if (m_base.m_header.m_size != 0) { m_raw.m_payload = new byte[m_base.m_header.m_size]; //reuse m_rawPos for position in header to read. m_rawPos = 0; m_state = ReceiveState.ReadingPayload; DebuggerEventSource.Log.WireProtocolReceiveState(m_state); goto case ReceiveState.ReadingPayload; } else { m_state = ReceiveState.CompletePayload; DebuggerEventSource.Log.WireProtocolReceiveState(m_state); goto case ReceiveState.CompletePayload; } } //Debug.WriteLine("CompleteHeader, header not valid"); } //catch (ThreadAbortException) //{ // throw; //} catch (Exception e) { Debug.WriteLine("Fault at payload deserialization:\n\n{0}", e.ToString()); } m_state = ReceiveState.Initialize; DebuggerEventSource.Log.WireProtocolReceiveState(m_state); if ((m_base.m_header.m_flags & Flags.c_NonCritical) == 0) { // FIXME // evaluate the purpose of this reply back to the NETMF device, the TinyCRL doesn't seem to have to handle this. In the end it looks like this does have any real purpose and will only be wasting CPU. //await IncomingMessage.ReplyBadPacketAsync(m_parent, Flags.c_BadHeader).ConfigureAwait(false); return(null); } break; case ReceiveState.ReadingPayload: count = m_raw.m_payload.Length - m_rawPos; //Debug.WriteLine("ReadingPayload"); // need to have a timeout to cancel the read task otherwise it may end up waiting forever for this to return // because we have an external cancellation token and the above timeout cancellation token, need to combine both bytesRead = await m_parent.ReadBufferAsync(m_raw.m_payload, m_rawPos, count, request.waitRetryTimeout, cancellationToken.AddTimeout(request.waitRetryTimeout)).ConfigureAwait(false); m_rawPos += bytesRead; if (bytesRead != count) { break; } m_state = ReceiveState.CompletePayload; DebuggerEventSource.Log.WireProtocolReceiveState(m_state); goto case ReceiveState.CompletePayload; case ReceiveState.CompletePayload: //Debug.WriteLine("CompletePayload"); if (VerifyPayload() == true) { //Debug.WriteLine("CompletePayload payload OK"); try { bool fReply = (m_base.m_header.m_flags & Flags.c_Reply) != 0; if ((m_base.m_header.m_flags & Flags.c_NACK) != 0) { m_raw.m_payload = null; } if (await ProcessMessage(this.GetCompleteMessage(), fReply).ConfigureAwait(false)) { DebuggerEventSource.Log.WireProtocolReceiveState(m_state); //Debug.WriteLine("*** leaving reassembler"); return(this.GetCompleteMessage()); } else { // this is not the message we were waiting // FIXME } //m_parent.App.ProcessMessage(this.GetCompleteMessage(), fReply); //m_state = ReceiveState.Initialize; //return; } //catch (ThreadAbortException) //{ // throw; //} catch (Exception e) { Debug.WriteLine("Fault at payload deserialization:\n\n{0}", e.ToString()); } } else { Debug.WriteLine("CompletePayload payload not valid"); } m_state = ReceiveState.Initialize; DebuggerEventSource.Log.WireProtocolReceiveState(m_state); if ((m_base.m_header.m_flags & Flags.c_NonCritical) == 0) { // FIXME // evaluate the purpose of this reply back to the NETMF device, the TinyCRL doesn't seem to have to handle this. In the end it looks like this does have any real purpose and will only be wasting CPU. await IncomingMessage.ReplyBadPacketAsync(m_parent, Flags.c_BadPayload).ConfigureAwait(false); return(null); } break; } } catch { m_state = ReceiveState.Initialize; DebuggerEventSource.Log.WireProtocolReceiveState(m_state); //Debug.WriteLine("*** leaving reassembler"); throw; } //Debug.WriteLine("*** leaving reassembler"); return(null); }