// outbound. internal MsQuicStream(SafeMsQuicConnectionHandle connection, QUIC_STREAM_OPEN_FLAGS flags) { Debug.Assert(connection != null); _canRead = !flags.HasFlag(QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL); _canWrite = true; _stateHandle = GCHandle.Alloc(_state); try { uint status = MsQuicApi.Api.StreamOpenDelegate( connection, flags, s_streamDelegate, GCHandle.ToIntPtr(_stateHandle), out _state.Handle); QuicExceptionHelpers.ThrowIfFailed(status, "Failed to open stream to peer."); status = MsQuicApi.Api.StreamStartDelegate(_state.Handle, QUIC_STREAM_START_FLAGS.ASYNC); QuicExceptionHelpers.ThrowIfFailed(status, "Could not start stream."); } catch { _state.Handle?.Dispose(); _stateHandle.Free(); throw; } }
// 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()}."); } }
public bool TryQueueNewStream(SafeMsQuicStreamHandle streamHandle, QUIC_STREAM_OPEN_FLAGS flags) { var stream = new MsQuicStream(this, streamHandle, flags); if (AcceptQueue.Writer.TryWrite(stream)) { return(true); } else { stream.Dispose(); return(false); } }
// inbound. internal MsQuicStream(SafeMsQuicStreamHandle streamHandle, QUIC_STREAM_OPEN_FLAGS flags) { _state.Handle = streamHandle; _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; } }
private async ValueTask <MsQuicStream> OpenStreamAsync(QUIC_STREAM_OPEN_FLAGS flags, CancellationToken cancellationToken) { ThrowIfDisposed(); if (!Connected) { throw new InvalidOperationException(SR.net_quic_not_connected); } var stream = new MsQuicStream(_state, flags); try { await stream.StartAsync(cancellationToken).ConfigureAwait(false); } catch { stream.Dispose(); throw; } return(stream); }
// 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()}."); } }
/// <summary> /// Initializes a new instance of an inbound <see cref="QuicStream" />. /// </summary> /// <param name="connectionState">Connection state</param> /// <param name="connectionHandle"><see cref="QuicConnection"/> safe handle, used to increment/decrement reference count with each associated stream.</param> /// <param name="handle">Native handle.</param> /// <param name="flags">Related data from the PEER_STREAM_STARTED connection event.</param> /// <param name="defaultErrorCode">Error code used when the stream needs to abort read or write side of the stream internally.</param> internal unsafe QuicStream(QuicConnection.State connectionState, MsQuicContextSafeHandle connectionHandle, QUIC_HANDLE *handle, QUIC_STREAM_OPEN_FLAGS flags, long defaultErrorCode) { _connectionState = connectionState; GCHandle context = GCHandle.Alloc(this, GCHandleType.Weak); try { delegate * unmanaged[Cdecl] < QUIC_HANDLE *, void *, QUIC_STREAM_EVENT *, int > nativeCallback = &NativeCallback; MsQuicApi.Api.ApiTable->SetCallbackHandler( handle, nativeCallback, (void *)GCHandle.ToIntPtr(context)); _handle = new MsQuicContextSafeHandle(handle, context, MsQuicApi.Api.ApiTable->StreamClose, SafeHandleType.Stream, connectionHandle); } catch { context.Free(); throw; } _defaultErrorCode = defaultErrorCode; _canRead = true; _canWrite = !flags.HasFlag(QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL); if (!_canWrite) { _sendTcs.TrySetResult(final: true); } _id = (long)GetMsQuicParameter <ulong>(_handle, QUIC_PARAM_STREAM_ID); _type = flags.HasFlag(QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL) ? QuicStreamType.Unidirectional : QuicStreamType.Bidirectional; _startedTcs.TrySetResult(); }