rustls: implement connect_blocking

Closes #11647
This commit is contained in:
Jacob Hoffman-Andrews 2023-06-23 16:58:54 -07:00 committed by Daniel Stenberg
parent 79147a76cd
commit ad040e1262
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2

View File

@ -39,6 +39,7 @@
#include "select.h"
#include "strerror.h"
#include "multiif.h"
#include "connect.h" /* for the connect timeout */
struct rustls_ssl_backend_data
{
@ -75,14 +76,6 @@ cr_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data)
return backend->data_pending;
}
static CURLcode
cr_connect(struct Curl_cfilter *cf UNUSED_PARAM,
struct Curl_easy *data UNUSED_PARAM)
{
infof(data, "rustls_connect: unimplemented");
return CURLE_SSL_CONNECT_ERROR;
}
struct io_ctx {
struct Curl_cfilter *cf;
struct Curl_easy *data;
@ -485,9 +478,20 @@ cr_set_negotiated_alpn(struct Curl_cfilter *cf, struct Curl_easy *data,
Curl_alpn_set_negotiated(cf, data, protocol, len);
}
/* Given an established network connection, do a TLS handshake.
*
* If `blocking` is true, this function will block until the handshake is
* complete. Otherwise it will return as soon as I/O would block.
*
* For the non-blocking I/O case, this function will set `*done` to true
* once the handshake is complete. This function never reads the value of
* `*done*`.
*/
static CURLcode
cr_connect_nonblocking(struct Curl_cfilter *cf,
struct Curl_easy *data, bool *done)
cr_connect_common(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool blocking,
bool *done)
{
struct ssl_connect_data *const connssl = cf->ctx;
curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
@ -501,6 +505,8 @@ cr_connect_nonblocking(struct Curl_cfilter *cf,
bool wants_write;
curl_socket_t writefd;
curl_socket_t readfd;
timediff_t timeout_ms;
timediff_t socket_check_timeout;
DEBUGASSERT(backend);
@ -538,12 +544,29 @@ cr_connect_nonblocking(struct Curl_cfilter *cf,
writefd = wants_write?sockfd:CURL_SOCKET_BAD;
readfd = wants_read?sockfd:CURL_SOCKET_BAD;
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, 0);
/* check allowed time left */
timeout_ms = Curl_timeleft(data, NULL, TRUE);
if(timeout_ms < 0) {
/* no need to continue if time already is up */
failf(data, "rustls: operation timed out before socket check");
return CURLE_OPERATION_TIMEDOUT;
}
socket_check_timeout = blocking?timeout_ms:0;
what = Curl_socket_check(
readfd, CURL_SOCKET_BAD, writefd, socket_check_timeout);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
return CURLE_SSL_CONNECT_ERROR;
}
if(blocking && 0 == what) {
failf(data, "rustls connection timeout after %d ms",
socket_check_timeout);
return CURLE_OPERATION_TIMEDOUT;
}
if(0 == what) {
infof(data, "Curl_socket_check: %s would block",
wants_read&&wants_write ? "writing and reading" :
@ -588,6 +611,21 @@ cr_connect_nonblocking(struct Curl_cfilter *cf,
DEBUGASSERT(false);
}
static CURLcode
cr_connect_nonblocking(struct Curl_cfilter *cf,
struct Curl_easy *data, bool *done)
{
return cr_connect_common(cf, data, false, done);
}
static CURLcode
cr_connect_blocking(struct Curl_cfilter *cf UNUSED_PARAM,
struct Curl_easy *data UNUSED_PARAM)
{
bool done; /* unused */
return cr_connect_common(cf, data, true, &done);
}
static void cr_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct easy_pollset *ps)
@ -670,7 +708,7 @@ const struct Curl_ssl Curl_ssl_rustls = {
cr_data_pending, /* data_pending */
Curl_none_random, /* random */
Curl_none_cert_status_request, /* cert_status_request */
cr_connect, /* connect */
cr_connect_blocking, /* connect */
cr_connect_nonblocking, /* connect_nonblocking */
cr_adjust_pollset, /* adjust_pollset */
cr_get_internals, /* get_internals */