=head1 NAME
-SSL_CTX_set_quiet_shutdown, SSL_CTX_get_quiet_shutdown, SSL_set_quiet_shutdown, SSL_get_quiet_shutdown - manipulate shutdown behaviour
+SSL_CTX_set_quiet_shutdown, SSL_CTX_get_quiet_shutdown, SSL_set_quiet_shutdown,
+SSL_get_quiet_shutdown - manipulate shutdown behaviour
=head1 SYNOPSIS
SSL_CTX_set_quiet_shutdown() and SSL_set_quiet_shutdown() do not return
diagnostic information.
-SSL_CTX_get_quiet_shutdown() and SSL_get_quiet_shutdown return the current
+SSL_CTX_get_quiet_shutdown() and SSL_get_quiet_shutdown() return the current
setting.
=head1 SEE ALSO
for setting SSL_SENT_SHUTDOWN the application must however still call
L<SSL_shutdown(3)> or SSL_set_shutdown() itself.
-These functions are not supported for QUIC SSL objects.
+SSL_set_shutdown() is not supported for QUIC SSL objects.
=head1 RETURN VALUES
SSL_set_shutdown() does not return diagnostic information.
-SSL_get_shutdown() returns the current setting.
+SSL_get_shutdown() returns the current shutdown state as set or based
+on the actual connection state.
+
+SSL_get_shutdown() returns 0 if called on a QUIC stream SSL object. If it
+is called on a QUIC connection SSL object, it returns a value with
+SSL_SENT_SHUTDOWN set if CONNECTION_CLOSE has been sent to the peer and
+it returns a value with SSL_RECEIVED_SHUTDOWN set if CONNECTION_CLOSE
+has been received from the peer or the QUIC connection is fully terminated
+for other reasons.
=head1 SEE ALSO
int ossl_quic_channel_is_term_any(const QUIC_CHANNEL *ch);
const QUIC_TERMINATE_CAUSE *
ossl_quic_channel_get_terminate_cause(const QUIC_CHANNEL *ch);
+int ossl_quic_channel_is_closing(const QUIC_CHANNEL *ch);
int ossl_quic_channel_is_terminated(const QUIC_CHANNEL *ch);
int ossl_quic_channel_is_active(const QUIC_CHANNEL *ch);
int ossl_quic_channel_is_handshake_complete(const QUIC_CHANNEL *ch);
QUIC_CHANNEL *ossl_quic_conn_get_channel(SSL *s);
int ossl_quic_has_pending(const SSL *s);
+int ossl_quic_get_shutdown(const SSL *s);
# endif
return ch != NULL && ch->state == QUIC_CHANNEL_STATE_ACTIVE;
}
-static int ossl_quic_channel_is_closing(const QUIC_CHANNEL *ch)
+int ossl_quic_channel_is_closing(const QUIC_CHANNEL *ch)
{
return ch->state == QUIC_CHANNEL_STATE_TERMINATING_CLOSING;
}
return NULL;
}
+/*
+ * SSL_get_shutdown()
+ * ------------------
+ */
+int ossl_quic_get_shutdown(const SSL *s)
+{
+ QCTX ctx;
+ int shut = 0;
+
+ if (!expect_quic_conn_only(s, &ctx))
+ return 0;
+
+ if (ossl_quic_channel_is_term_any(ctx.qc->ch)) {
+ shut |= SSL_SENT_SHUTDOWN;
+ if (!ossl_quic_channel_is_closing(ctx.qc->ch))
+ shut |= SSL_RECEIVED_SHUTDOWN;
+ }
+
+ return shut;
+}
+
/*
* Internal Testing APIs
* =====================
{
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL_ONLY(s);
- /* TODO(QUIC): Currently not supported for QUIC. */
+ /* Not supported with QUIC */
if (sc == NULL)
return;
{
const SSL_CONNECTION *sc = SSL_CONNECTION_FROM_CONST_SSL_ONLY(s);
- /* TODO(QUIC): Currently not supported for QUIC. */
+ /* Not supported with QUIC */
if (sc == NULL)
return 0;
{
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL_ONLY(s);
- /* TODO(QUIC): Do we want this for QUIC? */
+ /* Not supported with QUIC */
if (sc == NULL)
return;
{
const SSL_CONNECTION *sc = SSL_CONNECTION_FROM_CONST_SSL_ONLY(s);
- /* TODO(QUIC): Do we want this for QUIC? */
+#ifndef OPENSSL_NO_QUIC
+ /* QUIC: Just indicate whether the connection was shutdown cleanly. */
+ if (IS_QUIC(s))
+ return ossl_quic_get_shutdown(s);
+#endif
+
if (sc == NULL)
return 0;
return testresult;
}
+/*
+ * Test SSL_get_shutdown() behavior.
+ */
+static int test_get_shutdown(void)
+{
+ SSL_CTX *cctx = SSL_CTX_new_ex(libctx, NULL, OSSL_QUIC_client_method());
+ SSL *clientquic = NULL;
+ QUIC_TSERVER *qtserv = NULL;
+ int testresult = 0;
+
+ if (!TEST_ptr(cctx)
+ || !TEST_true(qtest_create_quic_objects(libctx, cctx, NULL, cert,
+ privkey,
+ QTEST_FLAG_FAKE_TIME,
+ &qtserv, &clientquic,
+ NULL, NULL))
+ || !TEST_true(qtest_create_quic_connection(qtserv, clientquic)))
+ goto err;
+
+ if (!TEST_int_eq(SSL_get_shutdown(clientquic), 0))
+ goto err;
+
+ if (!TEST_int_eq(SSL_shutdown(clientquic), 0))
+ goto err;
+
+ if (!TEST_int_eq(SSL_get_shutdown(clientquic), SSL_SENT_SHUTDOWN))
+ goto err;
+
+ do {
+ ossl_quic_tserver_tick(qtserv);
+ qtest_add_time(100);
+ } while (SSL_shutdown(clientquic) == 0);
+
+ if (!TEST_int_eq(SSL_get_shutdown(clientquic),
+ SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN))
+ goto err;
+
+ testresult = 1;
+ err:
+ ossl_quic_tserver_free(qtserv);
+ SSL_free(clientquic);
+ SSL_CTX_free(cctx);
+
+ return testresult;
+}
+
#define MAX_LOOPS 2000
/*
ADD_ALL_TESTS(test_client_auth, 2);
ADD_ALL_TESTS(test_alpn, 2);
ADD_ALL_TESTS(test_noisy_dgram, 2);
+ ADD_TEST(test_get_shutdown);
return 1;
err: