[mdns] connection test: don't wait if connect() succeeds immediately

This commit is contained in:
ejurgensen 2018-09-10 19:42:04 +02:00
parent 475c598d0e
commit 2c1f2f1b15

View File

@ -499,49 +499,55 @@ connection_test(int family, const char *address, const char *address_log, int po
ret = getaddrinfo(address, strport, &hints, &ai); ret = getaddrinfo(address, strport, &hints, &ai);
if (ret < 0) if (ret < 0)
{ {
DPRINTF(E_DBG, L_MDNS, "Connection test to %s:%d failed with getaddrinfo error: %s\n", address_log, port, gai_strerror(ret)); DPRINTF(E_WARN, L_MDNS, "Connection test to %s:%d failed with getaddrinfo error: %s\n", address_log, port, gai_strerror(ret));
return -1; return -1;
} }
sock = socket(ai->ai_family, ai->ai_socktype | SOCK_NONBLOCK, ai->ai_protocol); sock = socket(ai->ai_family, ai->ai_socktype | SOCK_NONBLOCK, ai->ai_protocol);
if (sock < 0) if (sock < 0)
{ {
DPRINTF(E_DBG, L_MDNS, "Connection test to %s:%d failed with socket error: %s\n", address_log, port, strerror(errno)); DPRINTF(E_WARN, L_MDNS, "Connection test to %s:%d failed with socket error: %s\n", address_log, port, strerror(errno));
goto out_free_ai; goto out_free_ai;
} }
ret = connect(sock, ai->ai_addr, ai->ai_addrlen); ret = connect(sock, ai->ai_addr, ai->ai_addrlen);
if (ret < 0 && errno != EALREADY && errno != EINPROGRESS) if (ret < 0 && errno != EINPROGRESS)
{ {
DPRINTF(E_DBG, L_MDNS, "Connection test to %s:%d failed with connect error: %s\n", address_log, port, strerror(errno)); DPRINTF(E_WARN, L_MDNS, "Connection test to %s:%d failed with connect error: %s\n", address_log, port, strerror(errno));
goto out_close_socket; goto out_close_socket;
} }
FD_ZERO(&fdset); // We often need to wait for the connection. On Linux this seems always to be
FD_SET(sock, &fdset); // the case, but FreeBSD connect() sometimes returns immediate success.
if (ret != 0)
ret = select(sock + 1, NULL, &fdset, NULL, &timeout);
if (ret != 1)
{ {
if (errno == EINPROGRESS) FD_ZERO(&fdset);
DPRINTF(E_DBG, L_MDNS, "Connection test to %s:%d timed out (limit is %d seconds)\n", address_log, port, MDNS_CONNECT_TEST_TIMEOUT); FD_SET(sock, &fdset);
else
DPRINTF(E_DBG, L_MDNS, "Connection test to %s:%d failed with select error: %s\n", address_log, port, strerror(errno));
goto out_close_socket;
}
len = sizeof(error); ret = select(sock + 1, NULL, &fdset, NULL, &timeout);
ret = getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len); if (ret < 0)
if (ret < 0) {
{ DPRINTF(E_WARN, L_MDNS, "Connection test to %s:%d failed with select error: %s\n", address_log, port, strerror(errno));
DPRINTF(E_DBG, L_MDNS, "Connection test to %s:%d failed with getsockopt error: %s\n", address_log, port, strerror(errno)); goto out_close_socket;
goto out_close_socket; }
} else if (ret == 0)
{
DPRINTF(E_WARN, L_MDNS, "Connection test to %s:%d timed out (limit is %d seconds)\n", address_log, port, MDNS_CONNECT_TEST_TIMEOUT);
goto out_close_socket;
}
if (error) len = sizeof(error);
{ ret = getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len);
DPRINTF(E_DBG, L_MDNS, "Connection test to %s:%d failed with getsockopt return: %s\n", address_log, port, strerror(error)); if (ret < 0)
goto out_close_socket; {
DPRINTF(E_WARN, L_MDNS, "Connection test to %s:%d failed with getsockopt error: %s\n", address_log, port, strerror(errno));
goto out_close_socket;
}
else if (error)
{
DPRINTF(E_WARN, L_MDNS, "Connection test to %s:%d failed with getsockopt return: %s\n", address_log, port, strerror(error));
goto out_close_socket;
}
} }
DPRINTF(E_DBG, L_MDNS, "Connection test to %s:%d completed successfully\n", address_log, port); DPRINTF(E_DBG, L_MDNS, "Connection test to %s:%d completed successfully\n", address_log, port);