internal static async Task <TResponse> SendReceiveAsync <TRequest, TResponse>(LightweightMethodStub methodStub, TRequest request, IRpcSerializer serializer) where TRequest : class where TResponse : class { TResponse response; var context = new LightweightCallContext(new TestRpcEndPoint(), null, ImmutableArray <KeyValuePair <string, ImmutableArray <byte> > > .Empty, CancellationToken.None); var requestPipe = new Pipe(); var responsePipe = new Pipe(); var duplexPipe = new DirectDuplexPipe(requestPipe.Reader, responsePipe.Writer); await using (var pipeline = new TestPipeline(duplexPipe)) { var payload = new ReadOnlySequence <byte>(serializer.Serialize(request)); var frame = new LightweightRpcFrame(RpcFrameType.UnaryRequest, null, 1, methodStub.OperationName, RpcOperationFlags.None, 0, payload, null); await methodStub.HandleMessage(pipeline, frame, null, context); var readResult = await responsePipe.Reader.ReadAsync(); var buffer = readResult.Buffer; bool hasResponseFrame = LightweightRpcFrame.TryRead(ref buffer, 65536, out var responseFrame) == RpcFrameState.Full; Assert.IsTrue(hasResponseFrame); response = (TResponse)serializer.Deserialize(responseFrame.Payload, typeof(TResponse)); return(response); } }
private async ValueTask <byte[]?> HandleDatagramAsync(LightweightRpcEndPoint endPoint, byte[] data, CancellationToken cancellationToken) { if (LightweightRpcFrame.TryRead(data, this.MaxRequestSize, out var frame) == RpcFrameState.Full) { if (frame.FrameType != RpcFrameType.UnaryRequest) { this.Logger.LogWarning("Datagram only handles unary requests."); return(null); } var methodStub = this.GetMethodDefinition(frame.RpcOperation); if (methodStub == null) { this.Logger.LogWarning("Unknown operation '{Operation}' in datagram frame.", frame.RpcOperation); return(null); } CancellationToken actualCancellationToken; CancellationTokenSource?timeoutCts = null; CancellationTokenSource?linkedCts = null; if (frame.Timeout > 0) { timeoutCts = new CancellationTokenSource(); timeoutCts.CancelAfter((int)frame.Timeout); if (cancellationToken.CanBeCanceled) { linkedCts = CancellationTokenSource.CreateLinkedTokenSource(timeoutCts.Token, cancellationToken); actualCancellationToken = linkedCts.Token; } else { actualCancellationToken = timeoutCts.Token; } } else { actualCancellationToken = cancellationToken; } try { var context = new LightweightCallContext(endPoint, null, frame.Headers, actualCancellationToken); using IServiceScope? scope = this.ServiceProvider?.CreateScope(); using var frameWriter = new LightweightRpcFrameWriter(65536); await methodStub.HandleMessage(frameWriter, frame, scope?.ServiceProvider, context).ContextFree(); return(frameWriter.GetFrameData()); } catch (Exception x) { this.Logger.LogWarning(x, "Error occurred in HandleDatagramAsync."); } finally { linkedCts?.Dispose(); timeoutCts?.Dispose(); } } else { this.Logger.LogInformation("Received incomplete datagram frame."); } return(null); }