the concurrency model which is used for a QUIC domain. A detailed introduction
to these concepts can be found in L<openssl-quic-concurrency(7)>.
-The flags comprise zero or more of the following flags:
+Applications may use either one the flags here:
=over 4
=item B<SSL_DOMAIN_FLAG_THREAD_ASSISTED>
-Specifying this flag configures the Thread-Assisted Concurrency Modle (TACM).
+Specifying this flag configures the Thread-Assisted Concurrency Model (TACM).
It implies B<SSL_DOMAIN_FLAG_MULTI_THREAD> and B<SSL_DOMAIN_FLAG_BLOCKING>.
This concurrency model is not available if OpenSSL was built without thread
The B<Single-Threaded Concurrency Model (SCM)> performs no locking or
synchronisation. It is entirely up to the application to synchronise access to
-the QUIC domain and its subsidary SSL objects.
+the QUIC domain and its subsidiary SSL objects.
This concurrency model is also useful for an application which wants to use the
OpenSSL QUIC implementation as a pure state machine.
=item B<SSL_DOMAIN_FLAG_THREAD_ASSISTED>
-Specifying this flag configures the Thread-Assisted Concurrency Modle (TACM).
+Specifying this flag configures the Thread-Assisted Concurrency Model (TACM).
It implies B<SSL_DOMAIN_FLAG_MULTI_THREAD>.
=item B<SSL_DOMAIN_FLAG_BLOCKING>
=back
The default concurrency model may vary between releases of OpenSSL. An
-application may specify one of more of the domain flags above to ensure
+application may specify one or more of the domain flags above to ensure
consistent usage of a specific concurrency model between releases.
=head2 Configuration of Concurrency Models with Implicit QUIC Domains
* the reactor interface.
*/
struct quic_tick_result_st {
+ OSSL_TIME tick_deadline;
char net_read_desired;
char net_write_desired;
char notify_other_threads;
- OSSL_TIME tick_deadline;
};
static ossl_inline ossl_unused void
/*
* Count of the current number of blocking waiters. Like everything else,
- * this is protected the caller's mutex (i.e., the engine mutex).
+ * this is protected by the caller's mutex (i.e., the engine mutex).
*/
size_t cur_blocking_waiters;
ch_rx_check_forged_pkt_limit(ch);
- if (handled_any)
+ if (handled_any && notify_other_threads != NULL)
*notify_other_threads = 1;
/*
}
/*
- * Given a QCSO, QSSO or QLSO, initialises a QCTX, determining the contextually
- * applicable QUIC_LISTENER, QUIC_CONNECTION and QUIC_XSO pointers.
+ * Given a QDSO, QCSO, QSSO or QLSO, initialises a QCTX, determining the
+ * contextually applicable QUIC_LISTENER, QUIC_CONNECTION and QUIC_XSO
+ * pointers.
*
* After this returns 1, all fields of the passed QCTX are initialised.
* Returns 0 on failure. This function is intended to be used to provide API
#if defined(OPENSSL_THREADS)
ossl_crypto_mutex_free(&ctx->ql->mutex);
#endif
- }
-
- if (ctx->ql->domain != NULL)
+ } else {
SSL_free(&ctx->ql->domain->obj.ssl);
+ }
}
/* SSL_free */
QCTX ctx;
QUIC_LISTENER *ql = NULL;
QUIC_PORT_ARGS port_args = {0};
- int reffed = 0;
if (!expect_quic_domain(ssl, &ctx))
return NULL;
if (!SSL_up_ref(&ctx.qd->obj.ssl))
return NULL;
- reffed = 1;
qctx_lock(&ctx);
if ((ql = OPENSSL_zalloc(sizeof(*ql))) == NULL) {
OPENSSL_free(ql);
qctx_unlock(&ctx);
- if (reffed)
- SSL_free(&ctx.qd->obj.ssl);
+ SSL_free(&ctx.qd->obj.ssl);
return NULL;
}
if ((qd = OPENSSL_zalloc(sizeof(*qd))) == NULL) {
QUIC_RAISE_NON_NORMAL_ERROR(NULL, ERR_R_CRYPTO_LIB, NULL);
- goto err;
+ return NULL;
}
#if defined(OPENSSL_THREADS)
return &qd->obj.ssl;
err:
- if (qd != NULL)
- ossl_quic_engine_free(qd->engine);
-
+ ossl_quic_engine_free(qd->engine);
#if defined(OPENSSL_THREADS)
ossl_crypto_mutex_free(&qd->mutex);
#endif
FD_ZERO(&wfd_set);
FD_ZERO(&efd_set);
- if (rfd != -1 && rfd_want_read)
+ if (rfd != INVALID_SOCKET && rfd_want_read)
openssl_fdset(rfd, &rfd_set);
- if (wfd != -1 && wfd_want_write)
+ if (wfd != INVALID_SOCKET && wfd_want_write)
openssl_fdset(wfd, &wfd_set);
/* Always check for error conditions. */
- if (rfd != -1)
+ if (rfd != INVALID_SOCKET)
openssl_fdset(rfd, &efd_set);
- if (wfd != -1)
+ if (wfd != INVALID_SOCKET)
openssl_fdset(wfd, &efd_set);
/* Check for notifier FD readability. */
- if (notify_rfd != -1) {
+ if (notify_rfd != INVALID_SOCKET) {
openssl_fdset(notify_rfd, &rfd_set);
openssl_fdset(notify_rfd, &efd_set);
}
if (notify_rfd > maxfd)
maxfd = notify_rfd;
- if (!ossl_assert(rfd != -1 || wfd != -1
+ if (!ossl_assert(rfd != INVALID_SOCKET || wfd != INVALID_SOCKET
|| !ossl_time_is_infinite(deadline)))
/* Do not block forever; should not happen. */
return 0;
+ /*
+ * The mutex dance (unlock/re-locak after poll/seclect) is
+ * potentially problematic. This may create a situation when
+ * two threads arrive to select/poll with the same file
+ * descriptors. We just need to be aware of this.
+ */
# if defined(OPENSSL_THREADS)
if (mutex != NULL)
ossl_crypto_mutex_unlock(mutex);
OSSL_TIME tick_deadline;
notifier_fd
- = (rtor->have_notifier ? ossl_rio_notifier_as_fd(&rtor->notifier) : -1);
+ = (rtor->have_notifier ? ossl_rio_notifier_as_fd(&rtor->notifier)
+ : INVALID_SOCKET);
for (;;) {
if ((flags & SKIP_FIRST_TICK) != 0)
* Second, the thread which happened to be the one which decremented
* cur_blocking_waiters to 0 unsignals the notifier and is then
* responsible for broadcasting to a CV to indicate to the other
- * threads that the synchronised wakeup has been cmpleted. Other
+ * threads that the synchronised wakeup has been completed. Other
* threads wait for this CV to be signalled.
*
*/
*/
fd = (int)WSASocketA(domain, socktype, protocol, NULL, 0,
WSA_FLAG_NO_HANDLE_INHERIT);
- if (fd < 0)
+ if (fd == INVALID_SOCKET)
return -1;
/* Prevent interference with the socket from other processes on Windows. */
# endif
fd = BIO_socket(domain, socktype, protocol, 0);
- if (fd < 0)
+ if (fd == INVALID_SOCKET)
return -1;
/*
/* Create a close-on-exec socket. */
lfd = create_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (lfd < 0)
+ if (lfd == INVALID_SOCKET)
return 0;
/* Bind the socket to a random loopback port. */
# ifndef OPENSSL_NO_QUIC
ret->domain_flags = 0;
if (IS_QUIC_METHOD(meth)) {
-# if defined(OPENSSL_THREADS)
+# if defined(OPENSSL_THREADS)
if (meth == OSSL_QUIC_client_thread_method())
ret->domain_flags
= SSL_DOMAIN_FLAG_MULTI_THREAD
ret->domain_flags
= SSL_DOMAIN_FLAG_MULTI_THREAD
| SSL_DOMAIN_FLAG_LEGACY_BLOCKING;
-# else
+# else
ret->domain_flags
= SSL_DOMAIN_FLAG_SINGLE_THREAD
| SSL_DOMAIN_FLAG_LEGACY_BLOCKING;
-# endif
+# endif
}
# endif