Пример #1
0
        public async Task ClientReceivesInternalServerErrorWhenTheApplicationFails()
        {
            using (StartVerifiableLog())
            {
                var pair       = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);
                var connection = new HttpConnectionContext("foo", connectionToken: null, LoggerFactory.CreateLogger(nameof(HttpConnectionContext)))
                {
                    Transport   = pair.Transport,
                    Application = pair.Application,
                };

                using (var feature = new TestWebSocketConnectionFeature())
                {
                    var connectionContext = new HttpConnectionContext(string.Empty, null, null);
                    var ws = new WebSocketsServerTransport(new WebSocketOptions(), connection.Application, connectionContext, LoggerFactory);

                    // Give the server socket to the transport and run it
                    var transport = ws.ProcessSocketAsync(await feature.AcceptAsync());

                    // Run the client socket
                    var client = feature.Client.ExecuteAndCaptureFramesAsync();

                    // Fail in the app
                    connection.Transport.Output.Complete(new InvalidOperationException("Catastrophic failure."));
                    var clientSummary = await client.OrTimeout();

                    Assert.Equal(WebSocketCloseStatus.InternalServerError, clientSummary.CloseResult.CloseStatus);

                    // Close from the client
                    await feature.Client.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None);

                    await transport.OrTimeout();
                }
            }
        }
Пример #2
0
            public Task StartAsync(Uri url, TransferFormat transferFormat)
            {
                var options = ClientPipeOptions.DefaultOptions;
                var pair    = DuplexPipe.CreateConnectionPair(options, options);

                _transport   = pair.Transport;
                _application = pair.Application;
                _tries++;
                Assert.True(QueryHelpers.ParseQuery(url.Query).TryGetValue("id", out var id));
                if (_prevConnectionId == null)
                {
                    _prevConnectionId = id;
                }
                else
                {
                    Assert.True(_prevConnectionId != id);
                    _prevConnectionId = id;
                }

                if (_tries < availableTransports)
                {
                    return(Task.FromException(new Exception()));
                }
                else
                {
                    return(Task.CompletedTask);
                }
            }
Пример #3
0
        public TestInput(IKestrelTrace log = null, ITimeoutControl timeoutControl = null)
        {
            _memoryPool = PinnedBlockMemoryPoolFactory.Create();
            var options = new PipeOptions(pool: _memoryPool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);
            var pair    = DuplexPipe.CreateConnectionPair(options, options);

            Transport   = pair.Transport;
            Application = pair.Application;

            var connectionFeatures = new FeatureCollection();

            connectionFeatures.Set(Mock.Of <IConnectionLifetimeFeature>());

            Http1ConnectionContext = TestContextFactory.CreateHttpConnectionContext(
                serviceContext: new TestServiceContext
            {
                Log = log ?? Mock.Of <IKestrelTrace>()
            },
                connectionContext: Mock.Of <ConnectionContext>(),
                transport: Transport,
                timeoutControl: timeoutControl ?? Mock.Of <ITimeoutControl>(),
                memoryPool: _memoryPool,
                connectionFeatures: connectionFeatures);

            Http1Connection = new Http1Connection(Http1ConnectionContext);
            Http1Connection.HttpResponseControl = Mock.Of <IHttpResponseControl>();
            Http1Connection.Reset();
        }
Пример #4
0
        public void Setup()
        {
            _memoryPool = SlabMemoryPoolFactory.Create();
            var options = new PipeOptions(_memoryPool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);
            var pair    = DuplexPipe.CreateConnectionPair(options, options);

            var serviceContext = TestContextFactory.CreateServiceContext(
                serverOptions: new KestrelServerOptions(),
                httpParser: new HttpParser <Http1ParsingHandler>(),
                dateHeaderValueManager: new DateHeaderValueManager(),
                log: new MockTrace());

            var connectionContext = TestContextFactory.CreateHttpConnectionContext(
                serviceContext: serviceContext,
                connectionContext: null,
                transport: pair.Transport,
                memoryPool: _memoryPool,
                connectionFeatures: new FeatureCollection(),
                timeoutControl: new TimeoutControl(timeoutHandler: null));

            var http1Connection = new Http1Connection(connectionContext);

            http1Connection.Reset();

            Http1Connection = http1Connection;
            Pipe            = new Pipe(new PipeOptions(_memoryPool));
        }
Пример #5
0
        public void GlobalSetup()
        {
            _hubLifetimeManager = new DefaultHubLifetimeManager <Hub>(NullLogger <DefaultHubLifetimeManager <Hub> > .Instance);


            IHubProtocol protocol;

            if (Protocol == "json")
            {
                protocol = new JsonHubProtocol();
            }
            else
            {
                protocol = new MessagePackHubProtocol();
            }

            var options = new PipeOptions();

            for (var i = 0; i < Connections; ++i)
            {
                var pair          = DuplexPipe.CreateConnectionPair(options, options);
                var connection    = new DefaultConnectionContext(Guid.NewGuid().ToString(), pair.Application, pair.Transport);
                var hubConnection = new HubConnectionContext(connection, Timeout.InfiniteTimeSpan, NullLoggerFactory.Instance);
                hubConnection.Protocol = protocol;
                _hubLifetimeManager.OnConnectedAsync(hubConnection).GetAwaiter().GetResult();

                _ = ConsumeAsync(connection.Application);
            }

            _hubContext = new HubContext <Hub>(_hubLifetimeManager);
        }
Пример #6
0
        public QuicStreamContext(QuicStream stream, QuicConnectionContext connection, QuicTransportContext context)
        {
            _stream     = stream;
            _connection = connection;
            _context    = context;
            _log        = context.Log;
            MemoryPool  = connection.MemoryPool;

            ConnectionClosed = _streamClosedTokenSource.Token;

            var maxReadBufferSize  = context.Options.MaxReadBufferSize ?? 0;
            var maxWriteBufferSize = context.Options.MaxWriteBufferSize ?? 0;

            // TODO should we allow these PipeScheduler to be configurable here?
            var inputOptions  = new PipeOptions(MemoryPool, PipeScheduler.ThreadPool, PipeScheduler.Inline, maxReadBufferSize, maxReadBufferSize / 2, useSynchronizationContext: false);
            var outputOptions = new PipeOptions(MemoryPool, PipeScheduler.Inline, PipeScheduler.ThreadPool, maxWriteBufferSize, maxWriteBufferSize / 2, useSynchronizationContext: false);

            var pair = DuplexPipe.CreateConnectionPair(inputOptions, outputOptions);

            Features.Set <IStreamDirectionFeature>(this);
            Features.Set <IProtocolErrorCodeFeature>(this);
            Features.Set <IStreamIdFeature>(this);

            // TODO populate the ITlsConnectionFeature (requires client certs).
            Features.Set <ITlsConnectionFeature>(new FakeTlsConnectionFeature());
            CanRead  = stream.CanRead;
            CanWrite = stream.CanWrite;

            Transport   = _originalTransport = pair.Transport;
            Application = pair.Application;
        }
        private TestHttp1Connection MakeHttp1Connection()
        {
            var options = new PipeOptions(_memoryPool, useSynchronizationContext: false);
            var pair    = DuplexPipe.CreateConnectionPair(options, options);

            _pair = pair;

            var serviceContext = TestContextFactory.CreateServiceContext(
                serverOptions: new KestrelServerOptions(),
                httpParser: new HttpParser <Http1ParsingHandler>(),
                dateHeaderValueManager: new DateHeaderValueManager(),
                log: new MockTrace());

            var connectionContext = TestContextFactory.CreateHttpConnectionContext(
                serviceContext: serviceContext,
                connectionContext: null,
                transport: pair.Transport,
                timeoutControl: new TimeoutControl(timeoutHandler: null),
                memoryPool: _memoryPool,
                connectionFeatures: new FeatureCollection());

            var http1Connection = new TestHttp1Connection(connectionContext);

            http1Connection.Reset();
            http1Connection.InitializeBodyControl(MessageBody.ZeroContentLengthKeepAlive);
            serviceContext.DateHeaderValueManager.OnHeartbeat(DateTimeOffset.UtcNow);

            return(http1Connection);
        }
Пример #8
0
        public async Task SSEWritesVeryLargeMessages()
        {
            using (StartVerifiableLog())
            {
                var pair       = DuplexPipe.CreateConnectionPair(PipeOptions.Default, new PipeOptions(readerScheduler: PipeScheduler.Inline));
                var connection = new DefaultConnectionContext("foo", pair.Transport, pair.Application);
                var context    = new DefaultHttpContext();

                var ms = new MemoryStream();
                context.Response.Body = ms;
                var sse = new ServerSentEventsServerTransport(connection.Application.Input, connectionId: string.Empty, LoggerFactory);

                var task = sse.ProcessRequestAsync(context, context.RequestAborted);

                string hText = new string('H', 60000);
                string wText = new string('W', 60000);

                await connection.Transport.Output.WriteAsync(Encoding.ASCII.GetBytes(hText + wText));

                connection.Transport.Output.Complete();
                await task.OrTimeout();

                Assert.Equal(":\r\ndata: " + hText + wText + "\r\n\r\n", Encoding.ASCII.GetString(ms.ToArray()));
            }
        }
Пример #9
0
        public TestClient(bool synchronousCallbacks = false, IHubProtocol protocol = null, IInvocationBinder invocationBinder = null, bool addClaimId = false)
        {
            var options = new PipeOptions(readerScheduler: synchronousCallbacks ? PipeScheduler.Inline : null);
            var pair    = DuplexPipe.CreateConnectionPair(options, options);

            Connection = new DefaultConnectionContext(Guid.NewGuid().ToString(), pair.Transport, pair.Application);

            var claimValue = Interlocked.Increment(ref _id).ToString();
            var claims     = new List <Claim> {
                new Claim(ClaimTypes.Name, claimValue)
            };

            if (addClaimId)
            {
                claims.Add(new Claim(ClaimTypes.NameIdentifier, claimValue));
            }

            Connection.User = new ClaimsPrincipal(new ClaimsIdentity(claims));
            Connection.Metadata["ConnectedTask"] = new TaskCompletionSource <bool>();

            protocol = protocol ?? new JsonHubProtocol();
            _protocolReaderWriter = new HubProtocolReaderWriter(protocol, new PassThroughEncoder());
            _invocationBinder     = invocationBinder ?? new DefaultInvocationBinder();

            _cts = new CancellationTokenSource();

            using (var memoryStream = new MemoryStream())
            {
                NegotiationProtocol.WriteMessage(new NegotiationMessage(protocol.Name), memoryStream);
                Connection.Application.Output.WriteAsync(memoryStream.ToArray());
            }
        }
        public virtual void GlobalSetup()
        {
            _memoryPool = PinnedBlockMemoryPoolFactory.Create();
            _httpFrame  = new Http2Frame();

            var options = new PipeOptions(_memoryPool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);

            _connectionPair = DuplexPipe.CreateConnectionPair(options, options);

            _httpRequestHeaders = new HttpRequestHeaders();
            _httpRequestHeaders.HeaderMethod    = new StringValues("GET");
            _httpRequestHeaders.HeaderPath      = new StringValues("/");
            _httpRequestHeaders.HeaderScheme    = new StringValues("http");
            _httpRequestHeaders.HeaderAuthority = new StringValues("localhost:80");

            _headersBuffer = new byte[1024 * 16];
            _hpackEncoder  = new DynamicHPackEncoder();

            var serviceContext = TestContextFactory.CreateServiceContext(
                serverOptions: new KestrelServerOptions(),
                dateHeaderValueManager: new DateHeaderValueManager(),
                systemClock: new MockSystemClock(),
                log: new MockTrace());

            serviceContext.DateHeaderValueManager.OnHeartbeat(default);
Пример #11
0
        public LibuvConnection(UvStreamHandle socket,
                               ILibuvTrace log,
                               LibuvThread thread,
                               IPEndPoint remoteEndPoint,
                               IPEndPoint localEndPoint,
                               PipeOptions inputOptions  = null,
                               PipeOptions outputOptions = null,
                               long?maxReadBufferSize    = null,
                               long?maxWriteBufferSize   = null)
        {
            _socket = socket;

            LocalEndPoint  = localEndPoint;
            RemoteEndPoint = remoteEndPoint;

            ConnectionClosed = _connectionClosedTokenSource.Token;
            Log    = log;
            Thread = thread;

            maxReadBufferSize ??= 0;
            maxWriteBufferSize ??= 0;

            inputOptions ??= new PipeOptions(MemoryPool, PipeScheduler.ThreadPool, Thread, maxReadBufferSize.Value, maxReadBufferSize.Value / 2, useSynchronizationContext: false);
            outputOptions ??= new PipeOptions(MemoryPool, Thread, PipeScheduler.ThreadPool, maxWriteBufferSize.Value, maxWriteBufferSize.Value / 2, useSynchronizationContext: false);

            var pair = DuplexPipe.CreateConnectionPair(inputOptions, outputOptions);

            // Set the transport and connection id
            Transport   = pair.Transport;
            Application = pair.Application;
        }
Пример #12
0
        public Http1ConnectionTests()
        {
            _pipelineFactory = KestrelMemoryPool.Create();
            var options = new PipeOptions(_pipelineFactory, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);
            var pair    = DuplexPipe.CreateConnectionPair(options, options);

            _transport   = pair.Transport;
            _application = pair.Application;

            var connectionFeatures = new FeatureCollection();

            connectionFeatures.Set(Mock.Of <IConnectionLifetimeFeature>());

            _serviceContext         = new TestServiceContext();
            _timeoutControl         = new Mock <ITimeoutControl>();
            _http1ConnectionContext = new HttpConnectionContext
            {
                ServiceContext     = _serviceContext,
                ConnectionContext  = Mock.Of <ConnectionContext>(),
                ConnectionFeatures = connectionFeatures,
                MemoryPool         = _pipelineFactory,
                TimeoutControl     = _timeoutControl.Object,
                Transport          = pair.Transport
            };

            _http1Connection = new TestHttp1Connection(_http1ConnectionContext);
            _http1Connection.Reset();
        }
Пример #13
0
        private TestHttp1Connection MakeHttp1Connection()
        {
            var options = new PipeOptions(_memoryPool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);
            var pair    = DuplexPipe.CreateConnectionPair(options, options);

            _pair = pair;

            var serviceContext = new ServiceContext
            {
                DateHeaderValueManager = new DateHeaderValueManager(),
                ServerOptions          = new KestrelServerOptions(),
                Log        = new MockTrace(),
                HttpParser = new HttpParser <Http1ParsingHandler>()
            };

            var http1Connection = new TestHttp1Connection(new HttpConnectionContext
            {
                ServiceContext     = serviceContext,
                ConnectionFeatures = new FeatureCollection(),
                MemoryPool         = _memoryPool,
                TimeoutControl     = new TimeoutControl(timeoutHandler: null),
                Transport          = pair.Transport
            });

            http1Connection.Reset();
            http1Connection.InitializeBodyControl(MessageBody.ZeroContentLengthKeepAlive);
            serviceContext.DateHeaderValueManager.OnHeartbeat(DateTimeOffset.UtcNow);

            return(http1Connection);
        }
        public void Setup()
        {
            _memoryPool = KestrelMemoryPool.Create();
            var options = new PipeOptions(_memoryPool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);
            var pair    = DuplexPipe.CreateConnectionPair(options, options);

            var serviceContext = new ServiceContext
            {
                DateHeaderValueManager = new DateHeaderValueManager(),
                ServerOptions          = new KestrelServerOptions(),
                Log        = new MockTrace(),
                HttpParser = new HttpParser <Http1ParsingHandler>()
            };

            var http1Connection = new Http1Connection(new HttpConnectionContext
            {
                ServiceContext     = serviceContext,
                ConnectionFeatures = new FeatureCollection(),
                MemoryPool         = _memoryPool,
                Transport          = pair.Transport,
                TimeoutControl     = new TimeoutControl(timeoutHandler: null)
            });

            http1Connection.Reset();

            Http1Connection = http1Connection;
            Pipe            = new Pipe(new PipeOptions(_memoryPool));
        }
Пример #15
0
        public async Task ShortMaskedViaManagedWebsocketWorks()
        {
            var options    = new PipeOptions(useSynchronizationContext: false);
            var duplexPipe = DuplexPipe.CreateConnectionPair(options, options);

            var webSocket = WebSocket.CreateFromStream(new DuplexPipeStream(duplexPipe.Transport.Input, duplexPipe.Transport.Output), false, null, TimeSpan.FromSeconds(30));
            var data      = new ReadOnlyMemory <byte>(Encoding.UTF8.GetBytes("This is a test payload."));

            await webSocket.SendAsync(data, WebSocketMessageType.Binary, true, default);

            var result = await duplexPipe.Application.Input.ReadAsync();

            var maskingKey = ReadMaskingKey(result.Buffer, 2);

            duplexPipe.Application.Input.AdvanceTo(result.Buffer.GetPosition(6));
            result = await duplexPipe.Application.Input.ReadAsync();

            var reader           = new WebSocketPayloadReader(new WebSocketHeader(true, WebSocketOpcode.Binary, true, 23, maskingKey));
            SequencePosition pos = default;

            reader.TryParseMessage(result.Buffer, ref pos, ref pos, out var message);

            var resultString = Encoding.UTF8.GetString(result.Buffer.ToArray());

            Assert.Equal("This is a test payload.", resultString);
        }
        public void Setup()
        {
            var memoryPool = PinnedBlockMemoryPoolFactory.Create();
            var options    = new PipeOptions(memoryPool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);
            var pair       = DuplexPipe.CreateConnectionPair(options, options);

            var serviceContext = TestContextFactory.CreateServiceContext(
                serverOptions: new KestrelServerOptions(),
                httpParser: new HttpParser <Http1ParsingHandler>(),
                dateHeaderValueManager: _dateHeaderValueManager,
                log: new MockTrace());

            var connectionContext = TestContextFactory.CreateHttpConnectionContext(
                serviceContext: serviceContext,
                connectionContext: null,
                transport: pair.Transport,
                memoryPool: memoryPool,
                connectionFeatures: new FeatureCollection());

            var http1Connection = new Http1Connection(connectionContext);

            http1Connection.Reset();
            serviceContext.DateHeaderValueManager.OnHeartbeat(DateTimeOffset.UtcNow);

            _responseHeadersDirect = (HttpResponseHeaders)http1Connection.ResponseHeaders;
            var context = new DefaultHttpContext(http1Connection);

            _response = context.Response;

            switch (Type)
            {
            case BenchmarkTypes.ContentLengthNumeric:
                SetContentLengthNumeric(1);
                GetContentLengthNumeric(1);
                break;

            case BenchmarkTypes.ContentLengthString:
                SetContentLengthString(1);
                GetContentLengthString(1);
                break;

            case BenchmarkTypes.Plaintext:
                SetPlaintext(1);
                GetPlaintext(1);
                break;

            case BenchmarkTypes.Common:
                SetCommon(1);
                GetCommon(1);
                break;

            case BenchmarkTypes.Unknown:
                SetUnknown(1);
                GetUnknown(1);
                break;
            }
        }
    public Http3HttpProtocolFeatureCollectionTests()
    {
        var streamContext = TestContextFactory.CreateHttp3StreamContext(transport: DuplexPipe.CreateConnectionPair(new PipeOptions(), new PipeOptions()).Application);

        var http3Stream = new TestHttp3Stream();

        http3Stream.Initialize(streamContext);
        _http3Collection = http3Stream;
    }
Пример #18
0
        public async Task SSETransportStopsSendAndReceiveLoopsWhenTransportStopped()
        {
            var eventStreamCts  = new CancellationTokenSource();
            var mockHttpHandler = new Mock <HttpMessageHandler>();

            mockHttpHandler.Protected()
            .Setup <Task <HttpResponseMessage> >("SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>())
            .Returns <HttpRequestMessage, CancellationToken>((request, cancellationToken) =>
            {
                var mockStream = new Mock <Stream>();
                mockStream
                .Setup(s => s.CopyToAsync(It.IsAny <Stream>(), It.IsAny <int>(), It.IsAny <CancellationToken>()))
                .Returns <Stream, int, CancellationToken>(async(stream, bufferSize, t) =>
                {
                    await Task.Yield();
                    var buffer = Encoding.ASCII.GetBytes("data: 3:abc\r\n\r\n");
                    while (!eventStreamCts.IsCancellationRequested)
                    {
                        await stream.WriteAsync(buffer, 0, buffer.Length).OrTimeout();
                    }
                });
                mockStream.Setup(s => s.CanRead).Returns(true);

                return(Task.FromResult(new HttpResponseMessage {
                    Content = new StreamContent(mockStream.Object)
                }));
            });

            Task transportActiveTask;

            using (var httpClient = new HttpClient(mockHttpHandler.Object))
            {
                var sseTransport = new ServerSentEventsTransport(httpClient);

                try
                {
                    var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);

                    await sseTransport.StartAsync(
                        new Uri("http://fakeuri.org"), pair.Application, TransferFormat.Text, connection : Mock.Of <IConnection>()).OrTimeout();

                    transportActiveTask = sseTransport.Running;
                    Assert.False(transportActiveTask.IsCompleted);
                    var message = await pair.Transport.Input.ReadSingleAsync().OrTimeout();

                    Assert.StartsWith("3:abc", Encoding.ASCII.GetString(message));
                }
                finally
                {
                    await sseTransport.StopAsync().OrTimeout();
                }

                await transportActiveTask.OrTimeout();

                eventStreamCts.Cancel();
            }
        }
Пример #19
0
        internal SocketConnection(Socket socket,
                                  MemoryPool <byte> memoryPool,
                                  PipeScheduler scheduler,
                                  ISocketsTrace trace,
                                  long?maxReadBufferSize  = null,
                                  long?maxWriteBufferSize = null,
                                  bool deferSends         = true,
                                  bool deferReceives      = true,
                                  SocketContinuationScheduler socketScheduler = SocketContinuationScheduler.ThreadPool,
                                  InputScheduler inputScheduler             = InputScheduler.ThreadPool,
                                  bool dontAllocateMemoryForIdleConnections = true,
                                  OutputScheduler outputScheduler           = OutputScheduler.IOQueue)
        {
            Debug.Assert(socket != null);
            Debug.Assert(memoryPool != null);
            Debug.Assert(trace != null);

            _socket              = socket;
            MemoryPool           = memoryPool;
            _trace               = trace;
            _waitForReceiveReady = dontAllocateMemoryForIdleConnections;

            LocalEndPoint  = _socket.LocalEndPoint;
            RemoteEndPoint = _socket.RemoteEndPoint;

            ConnectionClosed = _connectionClosedTokenSource.Token;

            // On *nix platforms, Sockets already dispatches to the ThreadPool.
            // Yes, the IOQueues are still used for the PipeSchedulers. This is intentional.
            // https://github.com/aspnet/KestrelHttpServer/issues/2573
            var awaiterScheduler = IsWindows ? scheduler : PipeScheduler.Inline;

            _receiver = new SocketReceiver(_socket, awaiterScheduler, runContinuationsAsynchronously: socketScheduler == SocketContinuationScheduler.ThreadPool, preferSynchronousCompletion: !deferReceives);
            _sender   = new SocketSender(_socket, awaiterScheduler, runContinuationsAsynchronously: socketScheduler == SocketContinuationScheduler.ThreadPool, preferSynchronousCompletion: !deferSends);

            maxReadBufferSize ??= 0;
            maxWriteBufferSize ??= 0;

            PipeScheduler pipeScheduler = outputScheduler switch
            {
                OutputScheduler.Inline => PipeScheduler.Inline,
                OutputScheduler.IOQueue => scheduler,
                OutputScheduler.IOThread => _socket.IOThreadScheduler,
                OutputScheduler.ThreadPool => PipeScheduler.ThreadPool,
                _ => throw new IndexOutOfRangeException()
            };

            var appScheduler  = inputScheduler == InputScheduler.Inline ? PipeScheduler.Inline : PipeScheduler.ThreadPool;
            var inputOptions  = new PipeOptions(MemoryPool, appScheduler, scheduler, maxReadBufferSize.Value, maxReadBufferSize.Value / 2, useSynchronizationContext: false);
            var outputOptions = new PipeOptions(MemoryPool, pipeScheduler, appScheduler, maxWriteBufferSize.Value, maxWriteBufferSize.Value / 2, useSynchronizationContext: false);

            var pair = DuplexPipe.CreateConnectionPair(inputOptions, outputOptions);

            // Set the transport and connection id
            Transport   = pair.Transport;
            Application = pair.Application;
        }
Пример #20
0
        public async Task TransportCommunicatesErrorToApplicationWhenClientDisconnectsAbnormally()
        {
            using (StartVerifiableLog())
            {
                var pair       = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);
                var connection = new HttpConnectionContext("foo", connectionToken: null, LoggerFactory.CreateLogger("HttpConnectionContext1"))
                {
                    Transport   = pair.Transport,
                    Application = pair.Application,
                };

                using (var feature = new TestWebSocketConnectionFeature())
                {
                    async Task CompleteApplicationAfterTransportCompletes()
                    {
                        try
                        {
                            // Wait until the transport completes so that we can end the application
                            var result = await connection.Transport.Input.ReadAsync();

                            connection.Transport.Input.AdvanceTo(result.Buffer.End);
                        }
                        catch (Exception ex)
                        {
                            Assert.IsType <WebSocketError>(ex);
                        }
                        finally
                        {
                            // Complete the application so that the connection unwinds without aborting
                            connection.Transport.Output.Complete();
                        }
                    }

                    var connectionContext = new HttpConnectionContext(string.Empty, connectionToken: null, LoggerFactory.CreateLogger("HttpConnectionContext2"));
                    var ws = new WebSocketsServerTransport(new WebSocketOptions(), connection.Application, connectionContext, LoggerFactory);

                    // Give the server socket to the transport and run it
                    var transport = ws.ProcessSocketAsync(await feature.AcceptAsync());

                    // Run the client socket
                    var client = feature.Client.ExecuteAndCaptureFramesAsync();

                    // When the close frame is received, we complete the application so the send
                    // loop unwinds
                    _ = CompleteApplicationAfterTransportCompletes();

                    // Terminate the client to server channel with an exception
                    feature.Client.SendAbort();

                    // Wait for the transport
                    await transport.OrTimeout();

                    await client.OrTimeout();
                }
            }
        }
Пример #21
0
        public async Task ReadMessagesAsynchronouslyWorks()
        {
            var options = new PipeOptions(useSynchronizationContext: false, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline);
            var pair    = DuplexPipe.CreateConnectionPair(options, options);

            await using var connection = new DefaultConnectionContext(Guid.NewGuid().ToString(), pair.Transport, pair.Application);
            var data     = Encoding.UTF8.GetBytes("Hello World");
            var protocol = new TestProtocol();

            async Task WritingTask()
            {
                var writer = connection.Application.Output;

                for (var i = 0; i < 3; i++)
                {
                    protocol.WriteMessage(data, writer);
                    await writer.FlushAsync().ConfigureAwait(false);
                }

                await writer.CompleteAsync().ConfigureAwait(false);
            }

            async Task ReadingTask()
            {
                var reader = connection.CreatePipeReader(protocol);

                while (true)
                {
                    var result = await reader.ReadAsync().ConfigureAwait(false);

                    var buffer = result.Buffer;

                    if (buffer.Length < 3 * data.Length)
                    {
                        reader.AdvanceTo(buffer.Start, buffer.End);
                        continue;
                    }

                    Assert.Equal(Enumerable.Repeat(data, 3).SelectMany(a => a).ToArray(), buffer.ToArray());

                    reader.AdvanceTo(buffer.End);
                    result = await reader.ReadAsync().ConfigureAwait(false);

                    Assert.True(result.IsCompleted);
                    break;
                }

                await reader.CompleteAsync();
            }

            var readingTask = ReadingTask();
            var writingTask = WritingTask();

            await writingTask;
            await readingTask;
        }
Пример #22
0
        protected override Task <ConnectionContext> CreateConnection(string target = null)
        {
            var pipeOptions = new PipeOptions();
            var duplex      = DuplexPipe.CreateConnectionPair(pipeOptions, pipeOptions);

            return(Task.FromResult <ConnectionContext>(new DefaultConnectionContext()
            {
                Application = duplex.Application,
                Transport = duplex.Transport
            }));
        }
Пример #23
0
        public ValueTask <IConnection> StartAsync()
        {
            _serialPort.Open();

            var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);

            Transport    = pair.Transport;
            _application = pair.Application;

            return(new ValueTask <IConnection>(this));
        }
Пример #24
0
            public Http3RequestStream(Http3TestBase testBase, Http3Connection connection)
            {
                _testBase   = testBase;
                _connection = connection;
                var inputPipeOptions  = GetInputPipeOptions(_testBase._serviceContext, _testBase._memoryPool, PipeScheduler.ThreadPool);
                var outputPipeOptions = GetOutputPipeOptions(_testBase._serviceContext, _testBase._memoryPool, PipeScheduler.ThreadPool);

                _pair = DuplexPipe.CreateConnectionPair(inputPipeOptions, outputPipeOptions);

                StreamContext = new TestStreamContext(canRead: true, canWrite: true, _pair, this);
            }
Пример #25
0
        public TestConnection()
        {
            Features = new FeatureCollection();
            Items    = new ConcurrentDictionary <object, object>();

            var pipeOptions = new PipeOptions();
            var pair        = DuplexPipe.CreateConnectionPair(pipeOptions, pipeOptions);

            Transport   = pair.Transport;
            Application = pair.Application;
        }
        public InMemoryConnection()
        {
            var inputOptions  = new PipeOptions(useSynchronizationContext: false);
            var outputOptions = new PipeOptions(useSynchronizationContext: false);

            var pair = DuplexPipe.CreateConnectionPair(inputOptions, outputOptions);

            // Set the transport and connection id
            Transport   = pair.Transport;
            Application = pair.Application;
        }
Пример #27
0
        public async Task StartAsync()
        {
            await _socket.ConnectAsync(_endPoint);

            var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);

            _transport   = pair.Transport;
            _application = pair.Application;

            _ = ExecuteAsync();
        }
Пример #28
0
        public async Task StartAsync(Uri url, TransferFormat transferFormat)
        {
            if (url == null)
            {
                throw new ArgumentNullException(nameof(url));
            }

            if (transferFormat != TransferFormat.Binary && transferFormat != TransferFormat.Text)
            {
                throw new ArgumentException($"The '{transferFormat}' transfer format is not supported by this transport.", nameof(transferFormat));
            }

            _webSocketMessageType = transferFormat == TransferFormat.Binary
                ? WebSocketMessageType.Binary
                : WebSocketMessageType.Text;

            var resolvedUrl = ResolveWebSocketsUrl(url);

            // We don't need to capture to a local because we never change this delegate.
            if (_accessTokenProvider != null)
            {
                var accessToken = await _accessTokenProvider();

                if (!string.IsNullOrEmpty(accessToken))
                {
                    _webSocket.Options.SetRequestHeader("Authorization", $"Bearer {accessToken}");
                }
            }

            Log.StartTransport(_logger, transferFormat, resolvedUrl);

            try
            {
                await _webSocket.ConnectAsync(resolvedUrl, CancellationToken.None);
            }
            catch
            {
                _webSocket.Dispose();
                throw;
            }

            Log.StartedTransport(_logger);

            // Create the pipe pair (Application's writer is connected to Transport's reader, and vice versa)
            var options = ClientPipeOptions.DefaultOptions;
            var pair    = DuplexPipe.CreateConnectionPair(options, options);

            _transport   = pair.Transport;
            _application = pair.Application;

            // TODO: Handle TCP connection errors
            // https://github.com/SignalR/SignalR/blob/1fba14fa3437e24c204dfaf8a18db3fce8acad3c/src/Microsoft.AspNet.SignalR.Core/Owin/WebSockets/WebSocketHandler.cs#L248-L251
            Running = ProcessSocketAsync(_webSocket);
        }
Пример #29
0
        public async Task SubProtocolSelectorIsUsedToSelectSubProtocol()
        {
            const string ExpectedSubProtocol  = "expected";
            var          providedSubProtocols = new[] { "provided1", "provided2" };

            using (StartVerifiableLog())
            {
                var pair       = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);
                var connection = new HttpConnectionContext("foo", connectionToken: null, LoggerFactory.CreateLogger(nameof(HttpConnectionContext)))
                {
                    Transport   = pair.Transport,
                    Application = pair.Application,
                };

                using (var feature = new TestWebSocketConnectionFeature())
                {
                    var options = new WebSocketOptions
                    {
                        // We want to verify behavior without timeout affecting it
                        CloseTimeout        = TimeSpan.FromSeconds(20),
                        SubProtocolSelector = protocols => {
                            Assert.Equal(providedSubProtocols, protocols.ToArray());
                            return(ExpectedSubProtocol);
                        },
                    };

                    var connectionContext = new HttpConnectionContext(string.Empty, null, null);
                    var ws = new WebSocketsServerTransport(options, connection.Application, connectionContext, LoggerFactory);

                    // Create an HttpContext
                    var context = new DefaultHttpContext();
                    context.Request.Headers.Add(HeaderNames.WebSocketSubProtocols, providedSubProtocols.ToArray());
                    context.Features.Set <IHttpWebSocketFeature>(feature);
                    var transport = ws.ProcessRequestAsync(context, CancellationToken.None);

                    await feature.Accepted.OrThrowIfOtherFails(transport);

                    // Assert the feature got the right subprotocol
                    Assert.Equal(ExpectedSubProtocol, feature.SubProtocol);

                    // Run the client socket
                    var client = feature.Client.ExecuteAndCaptureFramesAsync();

                    await feature.Client.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, null, CancellationToken.None).OrTimeout();

                    // close the client to server channel
                    connection.Transport.Output.Complete();

                    _ = await client.OrTimeout();

                    await transport.OrTimeout();
                }
            }
        }
        public void Setup()
        {
            var memoryPool = KestrelMemoryPool.Create();
            var options    = new PipeOptions(memoryPool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);
            var pair       = DuplexPipe.CreateConnectionPair(options, options);

            var serviceContext = new ServiceContext
            {
                DateHeaderValueManager = _dateHeaderValueManager,
                ServerOptions          = new KestrelServerOptions(),
                Log        = new MockTrace(),
                HttpParser = new HttpParser <Http1ParsingHandler>()
            };

            var http1Connection = new Http1Connection(new HttpConnectionContext
            {
                ServiceContext     = serviceContext,
                ConnectionFeatures = new FeatureCollection(),
                MemoryPool         = memoryPool,
                Transport          = pair.Transport
            });

            http1Connection.Reset();
            serviceContext.DateHeaderValueManager.OnHeartbeat(DateTimeOffset.UtcNow);

            _responseHeadersDirect = (HttpResponseHeaders)http1Connection.ResponseHeaders;
            var context = new DefaultHttpContext(http1Connection);

            _response = new DefaultHttpResponse(context);

            switch (Type)
            {
            case BenchmarkTypes.ContentLengthNumeric:
                ContentLengthNumeric(1);
                break;

            case BenchmarkTypes.ContentLengthString:
                ContentLengthString(1);
                break;

            case BenchmarkTypes.Plaintext:
                Plaintext(1);
                break;

            case BenchmarkTypes.Common:
                Common(1);
                break;

            case BenchmarkTypes.Unknown:
                Unknown(1);
                break;
            }
        }