Runtime fallback and FreeBSD compatible TFO

This commit is contained in:
Willem Toorop 2019-04-03 12:24:09 +02:00
parent b6e290f42a
commit b22768709a
2 changed files with 60 additions and 26 deletions

View File

@ -201,12 +201,14 @@ typedef struct getdns_upstream {
getdns_network_req *write_queue_last; getdns_network_req *write_queue_last;
_getdns_rbtree_t netreq_by_query_id; _getdns_rbtree_t netreq_by_query_id;
/* TCP specific connection handling*/
unsigned tfo_use_sendto : 1;
/* TLS specific connection handling*/ /* TLS specific connection handling*/
unsigned tls_fallback_ok : 1;
_getdns_tls_connection* tls_obj; _getdns_tls_connection* tls_obj;
_getdns_tls_session* tls_session; _getdns_tls_session* tls_session;
getdns_tls_hs_state_t tls_hs_state; getdns_tls_hs_state_t tls_hs_state;
getdns_auth_state_t tls_auth_state; getdns_auth_state_t tls_auth_state;
unsigned tls_fallback_ok : 1;
/* TLS settings */ /* TLS settings */
char *tls_cipher_list; char *tls_cipher_list;

View File

@ -385,6 +385,7 @@ tcp_connect(getdns_upstream *upstream, getdns_transport_list_t transport)
int fd = -1; int fd = -1;
upstream->tfo_use_sendto = 0;
DEBUG_STUB("%s %-35s: Creating TCP connection: %p\n", STUB_DEBUG_SETUP, DEBUG_STUB("%s %-35s: Creating TCP connection: %p\n", STUB_DEBUG_SETUP,
__FUNC__, (void*)upstream); __FUNC__, (void*)upstream);
if ((fd = socket(upstream->addr.ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1) if ((fd = socket(upstream->addr.ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1)
@ -413,21 +414,50 @@ tcp_connect(getdns_upstream *upstream, getdns_transport_list_t transport)
doesn't start till the sendto() lack of connection is often delayed until doesn't start till the sendto() lack of connection is often delayed until
then or even the subsequent event depending on the error and platform.*/ then or even the subsequent event depending on the error and platform.*/
# if defined(HAVE_DECL_TCP_FASTOPEN_CONNECT) && HAVE_DECL_TCP_FASTOPEN_CONNECT # if defined(HAVE_DECL_TCP_FASTOPEN_CONNECT) && HAVE_DECL_TCP_FASTOPEN_CONNECT
(void)setsockopt( fd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT if (setsockopt( fd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT
, (void *)&enable, sizeof(enable)); , (void *)&enable, sizeof(enable)) < 0) {
/* runtime fallback to TCP_FASTOPEN option */
_getdns_upstream_log(upstream,
GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_WARNING,
"%-40s : Upstream : "
"Could not setup TLS capable TFO connect\n",
upstream->addr_str);
# if defined(HAVE_DECL_TCP_FASTOPEN) && HAVE_DECL_TCP_FASTOPEN
/* TCP_FASTOPEN works for TCP only (not TLS) */
if (transport != GETDNS_TRANSPORT_TCP)
; /* This variant of TFO doesn't work with TLS */
else if (setsockopt( fd, IPPROTO_TCP, TCP_FASTOPEN
, (void *)&enable, sizeof(enable)) >= 0) {
upstream->tfo_use_sendto = 1;
return fd;
} else
_getdns_upstream_log(upstream,
GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_WARNING,
"%-40s : Upstream : "
"Could not fallback to TCP TFO\n",
upstream->addr_str);
# endif/* HAVE_DECL_TCP_FASTOPEN*/
}
/* On success regular connect is fine, TFO will happen automagically */
# else /* HAVE_DECL_TCP_FASTOPEN_CONNECT */ # else /* HAVE_DECL_TCP_FASTOPEN_CONNECT */
# if defined(HAVE_DECL_TCP_FASTOPEN) && HAVE_DECL_TCP_FASTOPEN # if defined(HAVE_DECL_TCP_FASTOPEN) && HAVE_DECL_TCP_FASTOPEN
(void)setsockopt( fd, IPPROTO_TCP, TCP_FASTOPEN /* TCP_FASTOPEN works for TCP only (not TLS) */
, (void *)&enable, sizeof(enable)); if (transport != GETDNS_TRANSPORT_TCP)
; /* This variant of TFO doesn't work with TLS */
else if (setsockopt( fd, IPPROTO_TCP, TCP_FASTOPEN
, (void *)&enable, sizeof(enable)) >= 0) {
upstream->tfo_use_sendto = 1;
return fd;
} else
_getdns_upstream_log(upstream,
GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_WARNING,
"%-40s : Upstream : Could not setup TCP TFO\n",
upstream->addr_str);
# endif/* HAVE_DECL_TCP_FASTOPEN*/ # endif/* HAVE_DECL_TCP_FASTOPEN*/
# endif /* HAVE_DECL_TCP_FASTOPEN_CONNECT */ # endif /* HAVE_DECL_TCP_FASTOPEN_CONNECT */
# if defined(HAVE_DECL_MSG_FASTOPEN) && HAVE_DECL_MSG_FASTOPEN
/* Leave the connect to the later call to sendto() if using TCP*/
if (transport == GETDNS_TRANSPORT_TCP)
return fd;
# else /* HAVE_DECL_MSG_FASTOPEN */
(void)transport;
# endif /* HAVE_DECL_MSG_FASTOPEN */
#endif /* USE_OSX_TCP_FASTOPEN */ #endif /* USE_OSX_TCP_FASTOPEN */
if (connect(fd, (struct sockaddr *)&upstream->addr, if (connect(fd, (struct sockaddr *)&upstream->addr,
upstream->addr_len) == -1) { upstream->addr_len) == -1) {
@ -758,7 +788,7 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
* Lets see how much of it we can write * Lets see how much of it we can write
*/ */
/* We use sendto() here which will do both a connect and send */ /* We use sendto() here which will do both a connect and send */
#ifdef USE_TCP_FASTOPEN if (netreq->upstream->tfo_use_sendto) {
written = sendto(fd, netreq->query - 2, pkt_len + 2, written = sendto(fd, netreq->query - 2, pkt_len + 2,
# if defined(HAVE_DECL_MSG_FASTOPEN) && HAVE_DECL_MSG_FASTOPEN # if defined(HAVE_DECL_MSG_FASTOPEN) && HAVE_DECL_MSG_FASTOPEN
MSG_FASTOPEN, MSG_FASTOPEN,
@ -769,11 +799,13 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
netreq->upstream->addr_len); netreq->upstream->addr_len);
/* If pipelining we will find that the connection is already up so /* If pipelining we will find that the connection is already up so
just fall back to a 'normal' write. */ just fall back to a 'normal' write. */
if (written == -1 && _getdns_socketerror() == _getdns_EISCONN) if (written == -1
written = write(fd, netreq->query - 2, pkt_len + 2); && _getdns_socketerror() == _getdns_EISCONN)
#else written = write(fd, netreq->query - 2
written = send(fd, (const char *)(netreq->query - 2), pkt_len + 2, 0); , pkt_len + 2);
#endif } else
written = send(fd, (const char *)(netreq->query - 2)
, pkt_len + 2, 0);
if ((written == -1 && _getdns_socketerror_wants_retry()) || if ((written == -1 && _getdns_socketerror_wants_retry()) ||
(size_t)written < pkt_len + 2) { (size_t)written < pkt_len + 2) {