// inbound. internal MsQuicStream(MsQuicConnection.State connectionState, SafeMsQuicStreamHandle streamHandle, QUIC_STREAM_OPEN_FLAGS flags) { _state.Handle = streamHandle; _state.ConnectionState = connectionState; _canRead = true; _canWrite = !flags.HasFlag(QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL); _started = true; _stateHandle = GCHandle.Alloc(_state); try { MsQuicApi.Api.SetCallbackHandlerDelegate( _state.Handle, s_streamDelegate, GCHandle.ToIntPtr(_stateHandle)); } catch { _stateHandle.Free(); throw; } if (NetEventSource.Log.IsEnabled()) { NetEventSource.Info( _state, $"[Stream#{_state.GetHashCode()}] inbound {(_canWrite ? "bi" : "uni")}directional stream created " + $"in Connection#{_state.ConnectionState.GetHashCode()}."); } }
// outbound. internal MsQuicStream(MsQuicConnection.State connectionState, QUIC_STREAM_OPEN_FLAGS flags) { Debug.Assert(connectionState.Handle != null); _canRead = !flags.HasFlag(QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL); _canWrite = true; _state.StateGCHandle = GCHandle.Alloc(_state); if (!_canRead) { _state.ReadState = ReadState.Closed; } try { uint status = MsQuicApi.Api.StreamOpenDelegate( connectionState.Handle, flags, s_streamDelegate, GCHandle.ToIntPtr(_state.StateGCHandle), out _state.Handle); QuicExceptionHelpers.ThrowIfFailed(status, "Failed to open stream to peer."); status = MsQuicApi.Api.StreamStartDelegate(_state.Handle, QUIC_STREAM_START_FLAGS.FAIL_BLOCKED); QuicExceptionHelpers.ThrowIfFailed(status, "Could not start stream."); } catch { _state.Handle?.Dispose(); _state.StateGCHandle.Free(); throw; } if (!connectionState.TryAddStream(this)) { _state.Handle?.Dispose(); _state.StateGCHandle.Free(); throw new ObjectDisposedException(nameof(QuicConnection)); } _state.ConnectionState = connectionState; if (NetEventSource.Log.IsEnabled()) { NetEventSource.Info( _state, $"[Stream#{_state.GetHashCode()}] outbound {(flags.HasFlag(QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL) ? "uni" : "bi")}directional stream created " + $"in Connection#{_state.ConnectionState.GetHashCode()}."); } }