コード例 #1
0
    /// <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();
    }
コード例 #2
0
    /// <summary>
    /// Initializes a new instance of an outbound <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="type">The type of the stream to open.</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, QuicStreamType type, long defaultErrorCode)
    {
        _connectionState = connectionState;
        GCHandle context = GCHandle.Alloc(this, GCHandleType.Weak);

        try
        {
            QUIC_HANDLE *handle;
            ThrowHelper.ThrowIfMsQuicError(MsQuicApi.Api.ApiTable->StreamOpen(
                                               connectionHandle.QuicHandle,
                                               type == QuicStreamType.Unidirectional ? QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL : QUIC_STREAM_OPEN_FLAGS.NONE,
                                               &NativeCallback,
                                               (void *)GCHandle.ToIntPtr(context),
                                               &handle),
                                           "StreamOpen failed");
            _handle = new MsQuicContextSafeHandle(handle, context, MsQuicApi.Api.ApiTable->StreamClose, SafeHandleType.Stream, connectionHandle);
        }
        catch
        {
            context.Free();
            throw;
        }

        _defaultErrorCode = defaultErrorCode;

        _canRead  = type == QuicStreamType.Bidirectional;
        _canWrite = true;
        if (!_canRead)
        {
            _receiveTcs.TrySetResult(final: true);
        }
        _type = type;
    }
コード例 #3
0
ファイル: QuicListener.cs プロジェクト: mikem8361/runtime
    /// <summary>
    /// Initializes and starts a new instance of a <see cref="QuicListener" />.
    /// </summary>
    /// <param name="options">Options to start the listener.</param>
    private unsafe QuicListener(QuicListenerOptions options)
    {
        GCHandle context = GCHandle.Alloc(this, GCHandleType.Weak);

        try
        {
            QUIC_HANDLE *handle;
            ThrowHelper.ThrowIfMsQuicError(MsQuicApi.Api.ApiTable->ListenerOpen(
                                               MsQuicApi.Api.Registration.QuicHandle,
                                               &NativeCallback,
                                               (void *)GCHandle.ToIntPtr(context),
                                               &handle),
                                           "ListenerOpen failed");
            _handle = new MsQuicContextSafeHandle(handle, context, MsQuicApi.Api.ApiTable->ListenerClose, SafeHandleType.Listener);
        }
        catch
        {
            context.Free();
            throw;
        }

        // Save the connection options before starting the listener
        _connectionOptionsCallback = options.ConnectionOptionsCallback;
        _acceptQueue = Channel.CreateBounded <PendingConnection>(new BoundedChannelOptions(options.ListenBacklog)
        {
            SingleWriter = true
        });

        // Start the listener, from now on MsQuic events will come.
        using MsQuicBuffers alpnBuffers = new MsQuicBuffers();
        alpnBuffers.Initialize(options.ApplicationProtocols, applicationProtocol => applicationProtocol.Protocol);
        QuicAddr address = options.ListenEndPoint.ToQuicAddr();

        if (options.ListenEndPoint.Address.Equals(IPAddress.IPv6Any))
        {
            // For IPv6Any, MsQuic would listen only for IPv6 connections. This would make it impossible
            // to connect the listener by using the IPv4 address (which could have been e.g. resolved by DNS).
            // Using the Unspecified family makes MsQuic handle connections from all IP addresses.
            address.Family = QUIC_ADDRESS_FAMILY_UNSPEC;
        }
        ThrowHelper.ThrowIfMsQuicError(MsQuicApi.Api.ApiTable->ListenerStart(
                                           _handle.QuicHandle,
                                           alpnBuffers.Buffers,
                                           (uint)alpnBuffers.Count,
                                           &address),
                                       "ListenerStart failed");

        // Get the actual listening endpoint.
        address       = GetMsQuicParameter <QuicAddr>(_handle, QUIC_PARAM_LISTENER_LOCAL_ADDRESS);
        LocalEndPoint = address.ToIPEndPoint(options.ListenEndPoint.AddressFamily);
    }
コード例 #4
0
    /// <summary>
    /// Initializes a new instance of an outbound <see cref="QuicConnection" />.
    /// </summary>
    private unsafe QuicConnection()
    {
        GCHandle context = GCHandle.Alloc(this, GCHandleType.Weak);

        try
        {
            QUIC_HANDLE *handle;
            ThrowHelper.ThrowIfMsQuicError(MsQuicApi.Api.ApiTable->ConnectionOpen(
                                               MsQuicApi.Api.Registration.QuicHandle,
                                               &NativeCallback,
                                               (void *)GCHandle.ToIntPtr(context),
                                               &handle),
                                           "ConnectionOpen failed");
            _handle = new MsQuicContextSafeHandle(handle, context, MsQuicApi.Api.ApiTable->ConnectionClose, SafeHandleType.Connection);
        }
        catch
        {
            context.Free();
            throw;
        }
    }
コード例 #5
0
    /// <summary>
    /// Initializes a new instance of an inbound <see cref="QuicConnection" />.
    /// </summary>
    /// <param name="handle">Native handle.</param>
    /// <param name="info">Related data from the NEW_CONNECTION listener event.</param>
    internal unsafe QuicConnection(QUIC_HANDLE *handle, QUIC_NEW_CONNECTION_INFO *info)
    {
        GCHandle context = GCHandle.Alloc(this, GCHandleType.Weak);

        try
        {
            delegate * unmanaged[Cdecl] < QUIC_HANDLE *, void *, QUIC_CONNECTION_EVENT *, int > nativeCallback = &NativeCallback;
            MsQuicApi.Api.ApiTable->SetCallbackHandler(
                handle,
                nativeCallback,
                (void *)GCHandle.ToIntPtr(context));
            _handle = new MsQuicContextSafeHandle(handle, context, MsQuicApi.Api.ApiTable->ConnectionClose, SafeHandleType.Connection);
        }
        catch
        {
            context.Free();
            throw;
        }

        _remoteEndPoint = info->RemoteAddress->ToIPEndPoint();
        _localEndPoint  = info->LocalAddress->ToIPEndPoint();
    }