private MsQuicStream StreamOpen(
            QUIC_STREAM_OPEN_FLAG flags)
        {
            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Enter(this);
            }

            IntPtr streamPtr = IntPtr.Zero;

            QuicExceptionHelpers.ThrowIfFailed(
                MsQuicApi.Api.StreamOpenDelegate(
                    _ptr,
                    (uint)flags,
                    MsQuicStream.NativeCallbackHandler,
                    IntPtr.Zero,
                    out streamPtr),
                "Failed to open stream to peer.");

            MsQuicStream stream = new MsQuicStream(this, flags, streamPtr, inbound: false);

            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Exit(this);
            }
            return(stream);
        }
        internal MsQuicStream(MsQuicConnection connection, QUIC_STREAM_OPEN_FLAG flags, IntPtr nativeObjPtr, bool inbound)
        {
            Debug.Assert(connection != null, "Connection null");

            _ptr = nativeObjPtr;

            _sendResettableCompletionSource    = new ResettableCompletionSource <uint>();
            _receiveResettableCompletionSource = new ResettableCompletionSource <uint>();
            SetCallbackHandler();

            bool isBidirectional = !flags.HasFlag(QUIC_STREAM_OPEN_FLAG.UNIDIRECTIONAL);

            if (inbound)
            {
                _canRead  = true;
                _canWrite = isBidirectional;
                _started  = true;
            }
            else
            {
                _canRead  = isBidirectional;
                _canWrite = true;
                StartLocalStream();
            }
        }
Exemple #3
0
        private async ValueTask <ConnectionContext> StartStreamAsync(QUIC_STREAM_OPEN_FLAG flags)
        {
            var stream = StreamOpen(flags);
            await stream.StartAsync();

            return(stream);
        }
Exemple #4
0
        // Creates a new MsQuicStream
        internal MsQuicStream(MsQuicConnection connection, QUIC_STREAM_OPEN_FLAG flags, IntPtr nativeObjPtr, bool inbound)
        {
            Debug.Assert(connection != null);

            _ptr = nativeObjPtr;

            if (inbound)
            {
                _started  = StartState.Finished;
                _canWrite = !flags.HasFlag(QUIC_STREAM_OPEN_FLAG.UNIDIRECTIONAL);
                _canRead  = true;
            }
            else
            {
                _started  = StartState.None;
                _canWrite = true;
                _canRead  = !flags.HasFlag(QUIC_STREAM_OPEN_FLAG.UNIDIRECTIONAL);
            }

            _sendResettableCompletionSource          = new ResettableCompletionSource <uint>();
            _receiveResettableCompletionSource       = new ResettableCompletionSource <uint>();
            _shutdownWriteResettableCompletionSource = new ResettableCompletionSource <uint>();

            SetCallbackHandler();
        }
Exemple #5
0
        public MsQuicStream StreamOpen(
            QUIC_STREAM_OPEN_FLAG flags)
        {
            var streamPtr = IntPtr.Zero;
            var status    = _api.StreamOpenDelegate(
                _nativeObjPtr,
                (uint)flags,
                MsQuicStream.NativeCallbackHandler,
                IntPtr.Zero,
                out streamPtr);

            MsQuicStatusException.ThrowIfFailed(status);

            return(new MsQuicStream(_api, this, _context, flags, streamPtr));
        }
Exemple #6
0
        private MsQuicStream StreamOpen(
            QUIC_STREAM_OPEN_FLAG flags)
        {
            IntPtr streamPtr = IntPtr.Zero;

            QuicExceptionHelpers.ThrowIfFailed(
                MsQuicApi.Api.StreamOpenDelegate(
                    _ptr,
                    (uint)flags,
                    MsQuicStream.s_streamDelegate,
                    IntPtr.Zero,
                    out streamPtr),
                "Failed to open stream to peer.");

            return(new MsQuicStream(this, flags, streamPtr, inbound: false));
        }
Exemple #7
0
        public MsQuicStream(MsQuicApi api, MsQuicConnection connection, MsQuicTransportContext context, QUIC_STREAM_OPEN_FLAG flags, IntPtr nativeObjPtr)
        {
            Debug.Assert(connection != null);

            Api           = api;
            _nativeObjPtr = nativeObjPtr;

            _connection = connection;
            MemoryPool  = context.Options.MemoryPoolFactory();
            _log        = context.Log;

            ConnectionClosed = _streamClosedTokenSource.Token;

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

            _resettableCompletion = new ResettableCompletionSource(this);

            // 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 <IQuicStreamFeature>(this);

            // TODO populate the ITlsConnectionFeature (requires client certs).
            Features.Set <ITlsConnectionFeature>(new FakeTlsConnectionFeature());
            if (flags.HasFlag(QUIC_STREAM_OPEN_FLAG.UNIDIRECTIONAL))
            {
                IsUnidirectional = true;
            }

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

            SetCallbackHandler();

            _processingTask = ProcessSends();
        }