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(); } }
internal unsafe uint ListenerCallbackHandler( ref ListenerEvent evt) { try { switch (evt.Type) { case QUIC_LISTENER_EVENT.NEW_CONNECTION: { NewConnectionInfo connectionInfo = *(NewConnectionInfo *)evt.Data.NewConnection.Info; IPEndPoint localEndPoint = MsQuicAddressHelpers.INetToIPEndPoint(*(SOCKADDR_INET *)connectionInfo.LocalAddress); IPEndPoint remoteEndPoint = MsQuicAddressHelpers.INetToIPEndPoint(*(SOCKADDR_INET *)connectionInfo.RemoteAddress); MsQuicConnection msQuicConnection = new MsQuicConnection(localEndPoint, remoteEndPoint, evt.Data.NewConnection.Connection); _acceptConnectionQueue.Writer.TryWrite(msQuicConnection); } // Always pend the new connection to wait for the security config to be resolved // TODO this doesn't need to be async always return(MsQuicStatusCodes.Pending); default: return(MsQuicStatusCodes.InternalError); } } catch (Exception ex) { Console.WriteLine(ex.Message); return(MsQuicStatusCodes.InternalError); } }
// 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(); }
internal static uint NativeCallbackHandler( IntPtr connection, IntPtr context, ref ConnectionEvent connectionEventStruct) { GCHandle handle = GCHandle.FromIntPtr(context); MsQuicConnection quicConnection = (MsQuicConnection)handle.Target !; return(quicConnection.HandleEvent(ref connectionEventStruct)); }
private static unsafe uint NativeCallbackHandler( IntPtr listener, IntPtr context, ref ListenerEvent evt) { if (evt.Type != QUIC_LISTENER_EVENT.NEW_CONNECTION) { return(MsQuicStatusCodes.InternalError); } GCHandle gcHandle = GCHandle.FromIntPtr(context); Debug.Assert(gcHandle.IsAllocated); Debug.Assert(gcHandle.Target is not null); var state = (State)gcHandle.Target; SafeMsQuicConnectionHandle?connectionHandle = null; try { ref NewConnectionInfo connectionInfo = ref *evt.Data.NewConnection.Info; IPEndPoint localEndPoint = MsQuicAddressHelpers.INetToIPEndPoint(ref *(SOCKADDR_INET *)connectionInfo.LocalAddress); IPEndPoint remoteEndPoint = MsQuicAddressHelpers.INetToIPEndPoint(ref *(SOCKADDR_INET *)connectionInfo.RemoteAddress); connectionHandle = new SafeMsQuicConnectionHandle(evt.Data.NewConnection.Connection); uint status = MsQuicApi.Api.ConnectionSetConfigurationDelegate(connectionHandle, state.ConnectionConfiguration); QuicExceptionHelpers.ThrowIfFailed(status, "ConnectionSetConfiguration failed."); var msQuicConnection = new MsQuicConnection(localEndPoint, remoteEndPoint, connectionHandle, state.RemoteCertificateRequired, state.RevocationMode, state.RemoteCertificateValidationCallback); msQuicConnection.SetNegotiatedAlpn(connectionInfo.NegotiatedAlpn, connectionInfo.NegotiatedAlpnLength); if (!state.AcceptConnectionQueue.Writer.TryWrite(msQuicConnection)) { // This handle will be cleaned up by MsQuic. connectionHandle.SetHandleAsInvalid(); msQuicConnection.Dispose(); return(MsQuicStatusCodes.InternalError); } return(MsQuicStatusCodes.Success); }
internal unsafe uint ListenerCallbackHandler(ref ListenerEvent evt) { try { switch (evt.Type) { case QUIC_LISTENER_EVENT.NEW_CONNECTION: { ref NewConnectionInfo connectionInfo = ref *(NewConnectionInfo *)evt.Data.NewConnection.Info; IPEndPoint localEndPoint = MsQuicAddressHelpers.INetToIPEndPoint(ref *(SOCKADDR_INET *)connectionInfo.LocalAddress); IPEndPoint remoteEndPoint = MsQuicAddressHelpers.INetToIPEndPoint(ref *(SOCKADDR_INET *)connectionInfo.RemoteAddress); MsQuicConnection msQuicConnection = new MsQuicConnection(localEndPoint, remoteEndPoint, evt.Data.NewConnection.Connection, _options.IdleTimeout); msQuicConnection.SetNegotiatedAlpn(connectionInfo.NegotiatedAlpn, connectionInfo.NegotiatedAlpnLength); _acceptConnectionQueue.Writer.TryWrite(msQuicConnection); } // Always pend the new connection to wait for the security config to be resolved // TODO this doesn't need to be async always return(MsQuicStatusCodes.Pending);
private static unsafe uint NativeCallbackHandler( IntPtr listener, IntPtr context, ListenerEvent *evt) { GCHandle gcHandle = GCHandle.FromIntPtr(context); Debug.Assert(gcHandle.IsAllocated); Debug.Assert(gcHandle.Target is not null); var state = (State)gcHandle.Target; if (evt->Type != QUIC_LISTENER_EVENT.NEW_CONNECTION) { return(MsQuicStatusCodes.InternalError); } SafeMsQuicConnectionHandle?connectionHandle = null; MsQuicConnection? msQuicConnection = null; try { ref NewConnectionInfo connectionInfo = ref *evt->Data.NewConnection.Info; IPEndPoint localEndPoint = MsQuicAddressHelpers.INetToIPEndPoint(ref *(SOCKADDR_INET *)connectionInfo.LocalAddress); IPEndPoint remoteEndPoint = MsQuicAddressHelpers.INetToIPEndPoint(ref *(SOCKADDR_INET *)connectionInfo.RemoteAddress); string targetHost = string.Empty; // compat with SslStream if (connectionInfo.ServerNameLength > 0 && connectionInfo.ServerName != IntPtr.Zero) { // TBD We should figure out what to do with international names. targetHost = Marshal.PtrToStringAnsi(connectionInfo.ServerName, connectionInfo.ServerNameLength); } SafeMsQuicConfigurationHandle?connectionConfiguration = state.ConnectionConfiguration; if (connectionConfiguration == null) { Debug.Assert(state.AuthenticationOptions.ServerCertificateSelectionCallback != null); try { // ServerCertificateSelectionCallback is synchronous. We will call it as needed when building configuration connectionConfiguration = SafeMsQuicConfigurationHandle.Create(state.ConnectionOptions, state.AuthenticationOptions, targetHost); } catch (Exception ex) { if (NetEventSource.Log.IsEnabled()) { NetEventSource.Error(state, $"[Listener#{state.GetHashCode()}] Exception occurred during creating configuration in connection callback: {ex}"); } } if (connectionConfiguration == null) { // We don't have safe handle yet so MsQuic will cleanup new connection. return(MsQuicStatusCodes.InternalError); } } connectionHandle = new SafeMsQuicConnectionHandle(evt->Data.NewConnection.Connection); uint status = MsQuicApi.Api.ConnectionSetConfigurationDelegate(connectionHandle, connectionConfiguration); if (MsQuicStatusHelper.SuccessfulStatusCode(status)) { msQuicConnection = new MsQuicConnection(localEndPoint, remoteEndPoint, state, connectionHandle, state.AuthenticationOptions.ClientCertificateRequired, state.AuthenticationOptions.CertificateRevocationCheckMode, state.AuthenticationOptions.RemoteCertificateValidationCallback); msQuicConnection.SetNegotiatedAlpn(connectionInfo.NegotiatedAlpn, connectionInfo.NegotiatedAlpnLength); if (!state.PendingConnections.TryAdd(connectionHandle.DangerousGetHandle(), msQuicConnection)) { msQuicConnection.Dispose(); } return(MsQuicStatusCodes.Success); } // If we fall-through here something wrong happened. }
#pragma warning restore CS3016 private static unsafe int NativeCallback(QUIC_HANDLE *listener, void *context, QUIC_LISTENER_EVENT *listenerEvent) { GCHandle gcHandle = GCHandle.FromIntPtr((IntPtr)context); Debug.Assert(gcHandle.IsAllocated); Debug.Assert(gcHandle.Target is not null); var state = (State)gcHandle.Target; if (listenerEvent->Type == QUIC_LISTENER_EVENT_TYPE.STOP_COMPLETE) { state.StopCompletion.TrySetResult(); return(QUIC_STATUS_SUCCESS); } if (listenerEvent->Type != QUIC_LISTENER_EVENT_TYPE.NEW_CONNECTION) { return(QUIC_STATUS_INTERNAL_ERROR); } SafeMsQuicConnectionHandle?connectionHandle = null; MsQuicConnection? msQuicConnection = null; try { ref QUIC_NEW_CONNECTION_INFO connectionInfo = ref *listenerEvent->NEW_CONNECTION.Info; IPEndPoint localEndPoint = MsQuicAddressHelpers.INetToIPEndPoint((IntPtr)connectionInfo.LocalAddress); IPEndPoint remoteEndPoint = MsQuicAddressHelpers.INetToIPEndPoint((IntPtr)connectionInfo.RemoteAddress); string targetHost = string.Empty; // compat with SslStream if (connectionInfo.ServerNameLength > 0 && (IntPtr)connectionInfo.ServerName != IntPtr.Zero) { // TBD We should figure out what to do with international names. targetHost = Marshal.PtrToStringAnsi((IntPtr)connectionInfo.ServerName, connectionInfo.ServerNameLength); } SafeMsQuicConfigurationHandle?connectionConfiguration = state.ConnectionConfiguration; if (connectionConfiguration == null) { Debug.Assert(state.AuthenticationOptions.ServerCertificateSelectionCallback != null); try { // ServerCertificateSelectionCallback is synchronous. We will call it as needed when building configuration connectionConfiguration = SafeMsQuicConfigurationHandle.Create(state.ConnectionOptions, state.AuthenticationOptions, targetHost); } catch (Exception ex) { if (NetEventSource.Log.IsEnabled()) { NetEventSource.Error(state, $"[Listener#{state.GetHashCode()}] Exception occurred during creating configuration in connection callback: {ex}"); } } if (connectionConfiguration == null) { // We don't have safe handle yet so MsQuic will cleanup new connection. return(QUIC_STATUS_INTERNAL_ERROR); } } connectionHandle = new SafeMsQuicConnectionHandle(listenerEvent->NEW_CONNECTION.Connection); Debug.Assert(!Monitor.IsEntered(state), "!Monitor.IsEntered(state)"); int status = MsQuicApi.Api.ApiTable->ConnectionSetConfiguration(connectionHandle.QuicHandle, connectionConfiguration.QuicHandle); if (StatusSucceeded(status)) { msQuicConnection = new MsQuicConnection(localEndPoint, remoteEndPoint, state, connectionHandle, state.AuthenticationOptions.ClientCertificateRequired, state.AuthenticationOptions.CertificateRevocationCheckMode, state.AuthenticationOptions.RemoteCertificateValidationCallback); msQuicConnection.SetNegotiatedAlpn((IntPtr)connectionInfo.NegotiatedAlpn, connectionInfo.NegotiatedAlpnLength); if (!state.PendingConnections.TryAdd(connectionHandle.DangerousGetHandle(), msQuicConnection)) { msQuicConnection.Dispose(); } return(QUIC_STATUS_SUCCESS); } // If we fall-through here something wrong happened. }