Behave better when attempting to contact unresponsive TCP servers.

By default TCP connect takes minutes to fail when trying to
connect a server which is not responding and for which the
network layer doesn't generate HOSTUNREACH errors.

This is doubled because having failed to connect in FASTOPEN
mode, the code then tries again with a call to connect().

We set TCP_SYNCNT to 2, which make the timeout about 10 seconds.
This in an unportable Linux feature, so it doesn't work on other
platforms.

No longer try connect() if sendmsg in fastopen mode fails with
ETIMEDOUT or EHOSTUNREACH since the story will just be the same.

Signed-off-by: DL6ER <dl6er@dl6er.de>
This commit is contained in:
Simon Kelley 2023-05-26 17:55:35 +01:00 committed by DL6ER
parent d38a0a6dcd
commit 6b48e6d063
No known key found for this signature in database
GPG Key ID: 00135ACBD90B28DD
1 changed files with 14 additions and 2 deletions

View File

@ -2002,7 +2002,7 @@ static ssize_t tcp_talk(int first, int last, int start, unsigned char *packet,
while (1)
{
int data_sent = 0;
int data_sent = 0, timedout = 0;
struct server *serv;
if (firstsendto == -1)
@ -2040,15 +2040,27 @@ static ssize_t tcp_talk(int first, int last, int start, unsigned char *packet,
serv->tcpfd = -1;
continue;
}
#ifdef TCP_SYNCNT
/* TCP connections by default take ages to time out.
At least on Linux, we can reduce that to only two attempts
to get a reply. For DNS, that's more sensible. */
mark = 2;
setsockopt(serv->tcpfd, IPPROTO_TCP, TCP_SYNCNT, &mark, sizeof(unsigned int));
#endif
#ifdef MSG_FASTOPEN
server_send(serv, serv->tcpfd, packet, qsize + sizeof(u16), MSG_FASTOPEN);
if (errno == 0)
data_sent = 1;
else if (errno = ETIMEDOUT || errno == EHOSTUNREACH)
timedout = 1;
#endif
if (!data_sent && connect(serv->tcpfd, &serv->addr.sa, sa_len(&serv->addr)) == -1)
/* If fastopen failed due to lack of reply, then there's no point in
trying again in non-FASTOPEN mode. */
if (timedout || (!data_sent && connect(serv->tcpfd, &serv->addr.sa, sa_len(&serv->addr)) == -1))
{
close(serv->tcpfd);
serv->tcpfd = -1;