public QuicConnectionListener(QuicTransportOptions options, IQuicTrace log, EndPoint endpoint, SslServerAuthenticationOptions sslServerAuthenticationOptions)
        {
            if (options.Alpn == null)
            {
                throw new InvalidOperationException("QuicTransportOptions.Alpn must be configured with a value.");
            }

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

            // TODO Should HTTP/3 specific ALPN still be global? Revisit whether it can be statically set once HTTP/3 is finalized.
            sslServerAuthenticationOptions.ApplicationProtocols = new List <SslApplicationProtocol>()
            {
                new SslApplicationProtocol(options.Alpn)
            };

            quicListenerOptions.ServerAuthenticationOptions = sslServerAuthenticationOptions;
            quicListenerOptions.ListenEndPoint = endpoint as IPEndPoint;
            quicListenerOptions.IdleTimeout    = options.IdleTimeout;

            _listener = new QuicListener(QuicImplementationProviders.MsQuic, quicListenerOptions);

            // Listener endpoint will resolve an ephemeral port, e.g. 127.0.0.1:0, into the actual port.
            EndPoint = _listener.ListenEndPoint;
        }
예제 #2
0
        public QuicStreamContext(QuicStream stream, QuicConnectionContext connection, QuicTransportContext context)
        {
            _stream     = stream;
            _connection = connection;
            _context    = context;
            _log        = context.Log;

            ConnectionClosed = _streamClosedTokenSource.Token;

            var maxReadBufferSize  = context.Options.MaxReadBufferSize.Value;
            var maxWriteBufferSize = context.Options.MaxWriteBufferSize.Value;

            // 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   = pair.Transport;
            Application = pair.Application;

            _processingTask = StartAsync();
        }
예제 #3
0
        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);
        }
예제 #4
0
 public QuicConnectionContext(QuicConnection connection, QuicTransportContext context)
 {
     _log             = context.Log;
     _context         = context;
     _connection      = connection;
     ConnectionClosed = _connectionClosedTokenSource.Token;
     Features.Set <ITlsConnectionFeature>(new FakeTlsConnectionFeature());
     Features.Set <IProtocolErrorCodeFeature>(this);
 }
예제 #5
0
        public QuicConnectionContext(QuicConnection connection, QuicTransportContext context)
        {
            _log        = context.Log;
            _context    = context;
            _connection = connection;
            Features.Set <ITlsConnectionFeature>(new FakeTlsConnectionFeature());
            Features.Set <IProtocolErrorCodeFeature>(this);

            _log.NewConnection(ConnectionId);
        }
예제 #6
0
        public QuicConnectionContext(QuicConnection connection, QuicTransportContext context)
        {
            _log        = context.Log;
            _context    = context;
            _connection = connection;
            Features.Set <ITlsConnectionFeature>(new FakeTlsConnectionFeature());
            Features.Set <IQuicStreamListenerFeature>(this);
            Features.Set <IQuicCreateStreamFeature>(this);

            _log.NewConnection(ConnectionId);
        }
예제 #7
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();
        }
        public QuicConnectionListener(QuicTransportOptions options, IQuicTrace log, EndPoint endpoint)
        {
            _log     = log;
            _context = new QuicTransportContext(_log, options);
            EndPoint = endpoint;
            var sslConfig = new SslServerAuthenticationOptions();

            sslConfig.ServerCertificate    = options.Certificate;
            sslConfig.ApplicationProtocols = new List <SslApplicationProtocol>()
            {
                new SslApplicationProtocol(options.Alpn)
            };
            _listener = new QuicListener(QuicImplementationProviders.MsQuic, endpoint as IPEndPoint, sslConfig);
            _listener.Start();
        }
예제 #9
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}.");
            }

            // Workaround for issue in System.Net.Quic
            // https://github.com/dotnet/runtime/issues/57241
            if (listenEndPoint.Address.Equals(IPAddress.Any) && listenEndPoint.Address != IPAddress.Any)
            {
                listenEndPoint = new IPEndPoint(IPAddress.Any, listenEndPoint.Port);
            }
            if (listenEndPoint.Address.Equals(IPAddress.IPv6Any) && listenEndPoint.Address != IPAddress.IPv6Any)
            {
                listenEndPoint = new IPEndPoint(IPAddress.IPv6Any, listenEndPoint.Port);
            }

            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;
        }
예제 #10
0
        public QuicConnectionListener(QuicTransportOptions options, IQuicTrace 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();

            quicListenerOptions.ServerAuthenticationOptions = sslServerAuthenticationOptions;
            quicListenerOptions.ListenEndPoint           = endpoint as IPEndPoint;
            quicListenerOptions.IdleTimeout              = options.IdleTimeout;
            quicListenerOptions.MaxBidirectionalStreams  = options.MaxBidirectionalStreamCount;
            quicListenerOptions.MaxUnidirectionalStreams = options.MaxUnidirectionalStreamCount;

            _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;
        }