private void HandleReceivedMessage(RpcMessage message) { try { string logFrom = $"from {RemotePeer}, {message.Data.Length} bytes"; if (message.IsRpcMethod()) { // Received a method call. Execute it immediately and enqueue the result. var method = message.DecodeRpcMethod(); Log.Trace($"Receiving method {method.ID} {method.Name} {logFrom}"); // Do not await the method execution, since it could require some time and we do not // want to block the receiving loop during this time. _ = Task.Run(async() => { var result = new RpcResult { MethodID = method.ID }; try { result.ReturnValue = await executor.Execute(method, RemotePeer); } catch (RpcException ex) { result.Failure = ex.Failure; } catch (Exception ex) { result.Failure = new RpcFailure { Type = RpcFailureType.RemoteException, // Not retryable; the command failed on caller side Message = ex.Message // Some information for identifying the problem }; } Log.Trace($"Method executed" + (result.Failure != null ? ", result failure type is " + result.Failure?.Type : "")); resultsQueue.Enqueue(result); // Let the sending loop respond immediately sendingWaiter.TrySetResult(true); }); } else if (message.IsRpcResult()) { // Received a return value var result = message.DecodeRpcResult(); Log.Trace($"Receiving result {result.MethodID} {logFrom}" + (result.Failure != null ? $" with failure {result.Failure.Type}" : "")); // Set the result if (result.MethodID == currentCall?.Method.ID) { currentCall.Result = result; } else { throw new Exception("Out of order: Received return value for non-open call"); } sendingWaiter.TrySetResult(true); } else { // Unsupported message Log.Trace($"Unsupported message {logFrom}"); } } catch (Exception ex) { Log.Debug($"Problem when handling message from {RemotePeer}: {ex.Message}"); } }
public async Task Send(RpcMessage message, CancellationToken cancellationToken) { if (message.IsRpcMethod()) { // Peer sent us a div task. "Execute" the method (by waiting executionTimeMs) and // add the result to the receiving queue and log the div. var div = Div.FromMethod(message.DecodeRpcMethod()); Log.Trace($"Div {div.methodID} sent to DivMock"); SentDivs.Enqueue(div); Action setResult = () => { div.result = div.ComputeExpectedResult(); receiving.Enqueue(RpcMessage.Encode(div.result)); Log.Trace($"Div {div.methodID} executed on DivMock"); }; if (executionTimeMs > 0) { _ = Task.Delay(executionTimeMs).ContinueWith(_ => setResult()); } else { setResult(); // Immediate execution on the same thread } } else if (message.IsRpcResult()) { // Peer sent the result from a div call. Log it. var result = message.DecodeRpcResult(); var div = ReceivedDivs.AsEnumerable().FirstOrDefault(it => it.methodID == result.MethodID); if (div == null) { Debug.WriteLine("Unexpected method ID"); } else { div.result = result; } } }