{
int s = -1;
char* err;
-#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_V6ONLY) || defined(IP_TRANSPARENT) || defined(IP_BINDANY) || defined(IP_FREEBIND) || defined(SO_BINDANY)
+#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) \
+ || defined(IPV6_V6ONLY) || defined(IP_TRANSPARENT) \
+ || defined(IP_BINDANY) || defined(IP_FREEBIND) \
+ || defined(SO_BINDANY) || defined(TCP_NODELAY)
int on = 1;
#endif
#ifdef HAVE_SYSTEMD
return 1;
}
-/** see if interface is ssl, its port number == the ssl port number */
-static int
-if_is_ssl(const char* ifname, const char* port, int ssl_port,
- struct config_strlist* tls_additional_port)
-{
- struct config_strlist* s;
- char* p = strchr(ifname, '@');
- if(!p && atoi(port) == ssl_port)
- return 1;
- if(p && atoi(p+1) == ssl_port)
- return 1;
- for(s = tls_additional_port; s; s = s->next) {
- if(p && atoi(p+1) == atoi(s->str))
- return 1;
- if(!p && atoi(port) == atoi(s->str))
- return 1;
- }
- return 0;
-}
-
/**
* Helper for ports_open. Creates one interface (or NULL for default).
* @param ifname: The interface ip address.
int quic_port, int http_notls_downstream, int sock_queue_timeout)
{
int s, noip6=0;
+ int is_ssl = if_is_ssl(ifname, port, ssl_port, tls_additional_port);
int is_https = if_is_https(ifname, port, https_port);
int is_dnscrypt = if_is_dnscrypt(ifname, port, dnscrypt_port);
int is_pp2 = if_is_pp2(ifname, port, proxy_protocol_port);
- int nodelay = is_https && http2_nodelay;
+ /* Always set TCP_NODELAY on TLS connection as it speeds up the TLS
+ * handshake. DoH had already such option so we respect it.
+ * Otherwise the server waits before sending more handshake data for
+ * the client ACK (Nagle's algorithm), which is delayed because the
+ * client waits for more data before ACKing (delayed ACK). */
+ int nodelay = is_https?http2_nodelay:is_ssl;
struct unbound_socket* ub_sock;
int is_doq = if_is_quic(ifname, port, quic_port);
const char* add = NULL;
/** get TCP file descriptor for address, returns -1 on failure,
* tcp_mss is 0 or maxseg size to set for TCP packets. */
int
-outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss, int dscp)
+outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen,
+ int tcp_mss, int dscp, int nodelay)
{
int s;
int af;
char* err;
-#if defined(SO_REUSEADDR) || defined(IP_BIND_ADDRESS_NO_PORT)
+#if defined(SO_REUSEADDR) || defined(IP_BIND_ADDRESS_NO_PORT) \
+ || defined(TCP_NODELAY)
int on = 1;
#endif
#ifdef INET6
" setsockopt(.. IP_BIND_ADDRESS_NO_PORT ..) failed");
}
#endif /* IP_BIND_ADDRESS_NO_PORT */
+ if(nodelay) {
+#if defined(IPPROTO_TCP) && defined(TCP_NODELAY)
+ if(setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (void*)&on,
+ (socklen_t)sizeof(on)) < 0) {
+ verbose(VERB_ALGO, "outgoing tcp:"
+ " setsockopt(.. TCP_NODELAY ..) failed");
+ }
+#else
+ verbose(VERB_ALGO, "outgoing tcp:"
+ " setsockopt(.. TCP_NODELAY ..) unsupported");
+#endif /* defined(IPPROTO_TCP) && defined(TCP_NODELAY) */
+ }
return s;
}
}
/* open socket */
- s = outnet_get_tcp_fd(&w->addr, w->addrlen, w->outnet->tcp_mss, w->outnet->ip_dscp);
+ s = outnet_get_tcp_fd(&w->addr, w->addrlen, w->outnet->tcp_mss,
+ w->outnet->ip_dscp, w->ssl_upstream);
if(s == -1)
return 0;
sldns_buffer* query, int timeout, int ssl, char* host)
{
struct comm_point* cp;
- int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss, outnet->ip_dscp);
+ int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss,
+ outnet->ip_dscp, ssl);
if(fd == -1) {
return 0;
}
{
/* cp calls cb with err=NETEVENT_DONE when transfer is done */
struct comm_point* cp;
- int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss, outnet->ip_dscp);
+ int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss,
+ outnet->ip_dscp, ssl);
if(fd == -1) {
return 0;
}
void reuse_write_wait_push_back(struct reuse_tcp* reuse, struct waiting_tcp* w);
/** get TCP file descriptor for address, returns -1 on failure,
- * tcp_mss is 0 or maxseg size to set for TCP packets. */
+ * tcp_mss is 0 or maxseg size to set for TCP packets,
+ * nodelay (TCP_NODELAY) should be set for TLS connections to speed up the TLS
+ * handshake.*/
int outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen,
- int tcp_mss, int dscp);
+ int tcp_mss, int dscp, int nodelay);
/**
* Create udp commpoint suitable for sending packets to the destination.
}
int outnet_get_tcp_fd(struct sockaddr_storage* ATTR_UNUSED(addr),
- socklen_t ATTR_UNUSED(addrlen), int ATTR_UNUSED(tcp_mss), int ATTR_UNUSED(dscp))
+ socklen_t ATTR_UNUSED(addrlen), int ATTR_UNUSED(tcp_mss),
+ int ATTR_UNUSED(dscp), int ATTR_UNUSED(nodelay))
{
log_assert(0);
return -1;
return 0;
}
+/** see if interface is ssl, its port number == the ssl port number */
+int
+if_is_ssl(const char* ifname, const char* port, int ssl_port,
+ struct config_strlist* tls_additional_port)
+{
+ struct config_strlist* s;
+ char* p = strchr(ifname, '@');
+ if(!p && atoi(port) == ssl_port)
+ return 1;
+ if(p && atoi(p+1) == ssl_port)
+ return 1;
+ for(s = tls_additional_port; s; s = s->next) {
+ if(p && atoi(p+1) == atoi(s->str))
+ return 1;
+ if(!p && atoi(port) == atoi(s->str))
+ return 1;
+ }
+ return 0;
+}
+
/** see if interface is PROXYv2, its port number == the proxy port number */
int
if_is_pp2(const char* ifname, const char* port,
*/
int cfg_has_https(struct config_file* cfg);
+/** see if interface is ssl, its port number == the ssl port number */
+int if_is_ssl(const char* ifname, const char* port, int ssl_port,
+ struct config_strlist* tls_additional_port);
+
/** see if interface is PROXYv2, its port number == the proxy port number */
int if_is_pp2(const char* ifname, const char* port,
struct config_strlist* proxy_protocol_port);