diff --git a/auto_tests/TCP_test.c b/auto_tests/TCP_test.c index cb27d27ff6..4a13ef2481 100644 --- a/auto_tests/TCP_test.c +++ b/auto_tests/TCP_test.c @@ -8,6 +8,7 @@ #include "../toxcore/TCP_server.h" #include "../toxcore/crypto_core.h" #include "../toxcore/mono_time.h" +#include "../toxcore/network.h" #include "auto_test_support.h" #define NUM_PORTS 3 @@ -73,8 +74,9 @@ static void test_basic(void) for (uint8_t i = 0; i < NUM_PORTS; i++) { sock = net_socket(ns, net_family_ipv6(), TOX_SOCK_STREAM, TOX_PROTO_TCP); localhost.port = net_htons(ports[i]); - bool ret = net_connect(ns, mem, logger, sock, &localhost); - ck_assert_msg(ret, "Failed to connect to created TCP relay server on port %d (%d).", ports[i], errno); + Net_Err_Connect err; + bool ret = net_connect(ns, mem, logger, sock, &localhost, &err); + ck_assert_msg(ret, "Failed to connect to created TCP relay server on port %d (%d, %s).", ports[i], errno, net_err_connect_to_string(err)); // Leave open one connection for the next test. if (i + 1 < NUM_PORTS) { @@ -218,8 +220,9 @@ static struct sec_TCP_con *new_tcp_con(const Logger *logger, const Memory *mem, localhost.ip = get_loopback(); localhost.port = net_htons(ports[random_u32(rng) % NUM_PORTS]); - bool ok = net_connect(ns, mem, logger, sock, &localhost); - ck_assert_msg(ok, "Failed to connect to the test TCP relay server."); + Net_Err_Connect err; + bool ok = net_connect(ns, mem, logger, sock, &localhost, &err); + ck_assert_msg(ok, "Failed to connect to the test TCP relay server: %s.", net_err_connect_to_string(err)); uint8_t f_secret_key[CRYPTO_SECRET_KEY_SIZE]; crypto_new_keypair(rng, sec_c->public_key, f_secret_key); diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index 5e13134bec..e80c0622e7 100644 --- a/toxcore/TCP_client.c +++ b/toxcore/TCP_client.c @@ -109,11 +109,23 @@ void tcp_con_set_custom_uint(TCP_Client_Connection *con, uint32_t value) non_null() static bool connect_sock_to(const Network *ns, const Logger *logger, const Memory *mem, Socket sock, const IP_Port *ip_port, const TCP_Proxy_Info *proxy_info) { + Net_Err_Connect err; if (proxy_info->proxy_type != TCP_PROXY_NONE) { - return net_connect(ns, mem, logger, sock, &proxy_info->ip_port); + net_connect(ns, mem, logger, sock, &proxy_info->ip_port, &err); } else { - return net_connect(ns, mem, logger, sock, ip_port); + net_connect(ns, mem, logger, sock, ip_port, &err); } + switch (err) { + case NET_ERR_CONNECT_OK: + case NET_ERR_CONNECT_FAILED: { + /* nonblocking socket, connect will never return success */ + return true; + } + case NET_ERR_CONNECT_INVALID_FAMILY: + return false; + } + LOGGER_ERROR(logger, "unexpected error code %d from net_connect", err); + return false; } /** diff --git a/toxcore/network.c b/toxcore/network.c index 673e2732ed..ce1a9cfddc 100644 --- a/toxcore/network.c +++ b/toxcore/network.c @@ -2015,7 +2015,21 @@ bool addr_resolve_or_parse_ip(const Network *ns, const Memory *mem, const char * return addr_parse_ip(address, to); } -bool net_connect(const Network *ns, const Memory *mem, const Logger *log, Socket sock, const IP_Port *ip_port) +const char *net_err_connect_to_string(Net_Err_Connect err) +{ + switch (err) { + case NET_ERR_CONNECT_OK: + return "NET_ERR_CONNECT_OK"; + case NET_ERR_CONNECT_FAILED: + return "NET_ERR_CONNECT_FAILED"; + case NET_ERR_CONNECT_INVALID_FAMILY: + return "NET_ERR_CONNECT_INVALID_FAMILY"; + } + + return ""; +} + +bool net_connect(const Network *ns, const Memory *mem, const Logger *log, Socket sock, const IP_Port *ip_port, Net_Err_Connect *err) { Network_Addr addr = {{0}}; @@ -2037,11 +2051,13 @@ bool net_connect(const Network *ns, const Memory *mem, const Logger *log, Socket Ip_Ntoa ip_str; LOGGER_ERROR(log, "cannot connect to %s:%d which is neither IPv4 nor IPv6", net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port)); + *err = NET_ERR_CONNECT_INVALID_FAMILY; return false; } #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION if ((true)) { + *err = NET_ERR_CONNECT_OK; return true; } #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ @@ -2060,10 +2076,12 @@ bool net_connect(const Network *ns, const Memory *mem, const Logger *log, Socket LOGGER_WARNING(log, "failed to connect to %s:%d: %d (%s)", net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port), error, net_strerror); net_kill_strerror(net_strerror); + *err = NET_ERR_CONNECT_FAILED; return false; } } + *err = NET_ERR_CONNECT_OK; return true; } diff --git a/toxcore/network.h b/toxcore/network.h index 34eb1f411a..40dd2dee53 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -499,13 +499,22 @@ void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handl non_null(1) nullable(2) void networking_poll(const Networking_Core *net, void *userdata); +typedef enum Net_Err_Connect { + NET_ERR_CONNECT_OK, + NET_ERR_CONNECT_INVALID_FAMILY, + NET_ERR_CONNECT_FAILED, +} Net_Err_Connect; + +const char *net_err_connect_to_string(Net_Err_Connect err); + /** @brief Connect a socket to the address specified by the ip_port. * - * Return true on success. - * Return false on failure. + * @param[out] err Set to NET_ERR_CONNECT_OK on success, otherwise an error code. + * + * @retval true on success, false on failure. */ non_null() -bool net_connect(const Network *ns, const Memory *mem, const Logger *log, Socket sock, const IP_Port *ip_port); +bool net_connect(const Network *ns, const Memory *mem, const Logger *log, Socket sock, const IP_Port *ip_port, Net_Err_Connect *err); /** @brief High-level getaddrinfo implementation. *