예제 #1
0
        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);
        }