示例#1
0
 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}");
     }
 }
示例#2
0
 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;
         }
     }
 }