コード例 #1
0
    public QuicConnectionListener(QuicTransportOptions options, ILogger log, EndPoint endpoint, SslServerAuthenticationOptions sslServerAuthenticationOptions)
    {
        if (!QuicImplementationProviders.Default.IsSupported)
        {
            throw new NotSupportedException("QUIC is not supported or enabled on this platform. See https://aka.ms/aspnet/kestrel/http3reqs for details.");
        }

        _log     = log;
        _context = new QuicTransportContext(_log, options);
        var quicListenerOptions = new QuicListenerOptions();

        var listenEndPoint = endpoint as IPEndPoint;

        if (listenEndPoint == null)
        {
            throw new InvalidOperationException($"QUIC doesn't support listening on the configured endpoint type. Expected {nameof(IPEndPoint)} but got {endpoint.GetType().Name}.");
        }

        quicListenerOptions.ServerAuthenticationOptions = sslServerAuthenticationOptions;
        quicListenerOptions.ListenEndPoint           = listenEndPoint;
        quicListenerOptions.IdleTimeout              = options.IdleTimeout;
        quicListenerOptions.MaxBidirectionalStreams  = options.MaxBidirectionalStreamCount;
        quicListenerOptions.MaxUnidirectionalStreams = options.MaxUnidirectionalStreamCount;
        quicListenerOptions.ListenBacklog            = options.Backlog;

        _listener = new QuicListener(quicListenerOptions);

        // Listener endpoint will resolve an ephemeral port, e.g. 127.0.0.1:0, into the actual port.
        EndPoint = _listener.ListenEndPoint;
    }
コード例 #2
0
ファイル: QuicStreamContext.cs プロジェクト: pa-at/aspnetcore
    public QuicStreamContext(QuicConnectionContext connection, QuicTransportContext context)
    {
        _connection = connection;
        _context    = context;
        _log        = context.Log;
        MemoryPool  = connection.MemoryPool;
        MultiplexedConnectionFeatures = connection.Features;

        RemoteEndPoint = connection.RemoteEndPoint;
        LocalEndPoint  = connection.LocalEndPoint;

        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);

        _inputPipe  = new Pipe(inputOptions);
        _outputPipe = new Pipe(outputOptions);

        _transportPipeReader = new CompletionPipeReader(_inputPipe.Reader);
        _transportPipeWriter = new CompletionPipeWriter(_outputPipe.Writer);

        _originalApplication = new DuplexPipe(_outputPipe.Reader, _inputPipe.Writer);
        _originalTransport   = new DuplexPipe(_transportPipeReader, _transportPipeWriter);
    }
コード例 #3
0
    public QuicConnectionFactory(IOptions <QuicTransportOptions> options, ILoggerFactory loggerFactory)
    {
        if (options == null)
        {
            throw new ArgumentNullException(nameof(options));
        }

        var logger = loggerFactory.CreateLogger("Microsoft.AspNetCore.Server.Kestrel.Transport.Quic.Client");

        _transportContext = new QuicTransportContext(logger, options.Value);
    }
コード例 #4
0
    public QuicConnectionContext(QuicConnection connection, QuicTransportContext context)
    {
        _log             = context.Log;
        _context         = context;
        _connection      = connection;
        ConnectionClosed = _connectionClosedTokenSource.Token;

        StreamPool = new PooledStreamStack <QuicStreamContext>(InitialStreamPoolSize);

        RemoteEndPoint = connection.RemoteEndPoint;
        LocalEndPoint  = connection.LocalEndPoint;

        InitializeFeatures();
    }
コード例 #5
0
    public QuicConnectionListener(
        QuicTransportOptions options,
        ILogger log,
        EndPoint endpoint,
        TlsConnectionCallbackOptions tlsConnectionCallbackOptions)
    {
        if (!QuicListener.IsSupported)
        {
            throw new NotSupportedException("QUIC is not supported or enabled on this platform. See https://aka.ms/aspnet/kestrel/http3reqs for details.");
        }

        if (endpoint is not IPEndPoint listenEndPoint)
        {
            throw new InvalidOperationException($"QUIC doesn't support listening on the configured endpoint type. Expected {nameof(IPEndPoint)} but got {endpoint.GetType().Name}.");
        }

        if (tlsConnectionCallbackOptions.ApplicationProtocols.Count == 0)
        {
            throw new InvalidOperationException("No application protocols specified.");
        }

        _pendingConnections = new ConditionalWeakTable <QuicConnection, QuicConnectionContext>();
        _log = log;
        _tlsConnectionCallbackOptions = tlsConnectionCallbackOptions;
        _context             = new QuicTransportContext(_log, options);
        _quicListenerOptions = new QuicListenerOptions
        {
            ApplicationProtocols      = _tlsConnectionCallbackOptions.ApplicationProtocols,
            ListenEndPoint            = listenEndPoint,
            ListenBacklog             = options.Backlog,
            ConnectionOptionsCallback = async(connection, helloInfo, cancellationToken) =>
            {
                // Create the connection context inside the callback because it's passed
                // to the connection callback. The field is then read once AcceptConnectionAsync
                // finishes awaiting.
                var currentAcceptingConnection = new QuicConnectionContext(connection, _context);
                _pendingConnections.Add(connection, currentAcceptingConnection);

                var context = new TlsConnectionCallbackContext
                {
                    ClientHelloInfo = helloInfo,
                    State           = _tlsConnectionCallbackOptions.OnConnectionState,
                    Connection      = currentAcceptingConnection,
                };
                var serverAuthenticationOptions = await _tlsConnectionCallbackOptions.OnConnection(context, cancellationToken);

                // If the callback didn't set protocols then use the listener's list of protocols.
                if (serverAuthenticationOptions.ApplicationProtocols == null)
                {
                    serverAuthenticationOptions.ApplicationProtocols = _tlsConnectionCallbackOptions.ApplicationProtocols;
                }

                // If the SslServerAuthenticationOptions doesn't have a cert or protocols then the
                // QUIC connection will fail and the client receives an unhelpful message.
                // Validate the options on the server and log issues to improve debugging.
                ValidateServerAuthenticationOptions(serverAuthenticationOptions);

                var connectionOptions = new QuicServerConnectionOptions
                {
                    ServerAuthenticationOptions = serverAuthenticationOptions,
                    IdleTimeout = Timeout.InfiniteTimeSpan, // Kestrel manages connection lifetimes itself so it can send GoAway's.
                    MaxInboundBidirectionalStreams  = options.MaxBidirectionalStreamCount,
                    MaxInboundUnidirectionalStreams = options.MaxUnidirectionalStreamCount,
                    DefaultCloseErrorCode           = options.DefaultCloseErrorCode,
                    DefaultStreamErrorCode          = options.DefaultStreamErrorCode,
                };
                return(connectionOptions);
            }
        };

        // Setting to listenEndPoint to prevent the property from being null.
        // This will be initialized when CreateListenerAsync() is invoked.
        EndPoint = listenEndPoint;
    }