diff options
-rw-r--r-- | ChangeLog.adoc | 1 | ||||
-rw-r--r-- | doc/en/weechat_dev.en.adoc | 1 | ||||
-rw-r--r-- | doc/fr/weechat_dev.fr.adoc | 1 | ||||
-rw-r--r-- | doc/ja/weechat_dev.ja.adoc | 2 | ||||
-rw-r--r-- | doc/sr/weechat_dev.sr.adoc | 2 | ||||
-rw-r--r-- | src/core/weechat.c | 1 | ||||
-rw-r--r-- | src/plugins/xfer/xfer-network.c | 108 | ||||
-rw-r--r-- | src/plugins/xfer/xfer-network.h | 7 | ||||
-rw-r--r-- | src/plugins/xfer/xfer.c | 75 | ||||
-rw-r--r-- | tests/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/Makefile.am | 3 | ||||
-rw-r--r-- | tests/unit/plugins/xfer/test-xfer-network.cpp | 58 |
12 files changed, 193 insertions, 67 deletions
diff --git a/ChangeLog.adoc b/ChangeLog.adoc index 3b91cb98d..0f3f02f42 100644 --- a/ChangeLog.adoc +++ b/ChangeLog.adoc @@ -51,6 +51,7 @@ Bug fixes:: * xfer: fix crash when closing DCC chat buffer * xfer: disconnect all active DCC chats and files on `/upgrade` * xfer: fix refresh of xfer buffer after `/upgrade` + * xfer: fix DCC file receive on Termux (issue #1811) Tests:: diff --git a/doc/en/weechat_dev.en.adoc b/doc/en/weechat_dev.en.adoc index f06b2d5ad..a2a44ec14 100644 --- a/doc/en/weechat_dev.en.adoc +++ b/doc/en/weechat_dev.en.adoc @@ -455,6 +455,7 @@ WeeChat "core" is located in following directories: | test-relay-auth.cpp | Tests: clients authentication. | xfer/ | Root of unit tests for Xfer plugin. | test-xfer-file.cpp | Tests: file functions. +| test-xfer-network.cpp | Tests: network functions. |=== [[documentation_translations]] diff --git a/doc/fr/weechat_dev.fr.adoc b/doc/fr/weechat_dev.fr.adoc index 8b61d80f6..4ed060136 100644 --- a/doc/fr/weechat_dev.fr.adoc +++ b/doc/fr/weechat_dev.fr.adoc @@ -457,6 +457,7 @@ Le cœur de WeeChat est situé dans les répertoires suivants : | test-relay-auth.cpp | Tests : authentification des clients. | xfer/ | Racine des tests unitaires pour l'extension Xfer. | test-xfer-file.cpp | Tests : fonctions sur les fichiers. +| test-xfer-network.cpp | Tests : fonctions réseau. |=== [[documentation_translations]] diff --git a/doc/ja/weechat_dev.ja.adoc b/doc/ja/weechat_dev.ja.adoc index 4779b2ccf..6e2fdb3a2 100644 --- a/doc/ja/weechat_dev.ja.adoc +++ b/doc/ja/weechat_dev.ja.adoc @@ -510,6 +510,8 @@ WeeChat "core" は以下のディレクトリに配置されています: | xfer/ | Root of unit tests for Xfer plugin. // TRANSLATION MISSING | test-xfer-file.cpp | Tests: file functions. +// TRANSLATION MISSING +| test-xfer-network.cpp | Tests: network functions. |=== [[documentation_translations]] diff --git a/doc/sr/weechat_dev.sr.adoc b/doc/sr/weechat_dev.sr.adoc index 1e60e2c4c..167743f51 100644 --- a/doc/sr/weechat_dev.sr.adoc +++ b/doc/sr/weechat_dev.sr.adoc @@ -459,6 +459,8 @@ WeeChat „језгро” се налази у следећим директо | xfer/ | Root of unit tests for Xfer plugin. // TRANSLATION MISSING | test-xfer-file.cpp | Tests: file functions. +// TRANSLATION MISSING +| test-xfer-network.cpp | Tests: network functions. |=== [[documentation_translations]] diff --git a/src/core/weechat.c b/src/core/weechat.c index 246c1636a..b9af73f6e 100644 --- a/src/core/weechat.c +++ b/src/core/weechat.c @@ -445,6 +445,7 @@ weechat_startup_message () gui_chat_printf (NULL, "---"); gui_chat_printf (NULL, ""); } + gui_chat_printf (NULL, "TEST SEB xfer termux"); } /* diff --git a/src/plugins/xfer/xfer-network.c b/src/plugins/xfer/xfer-network.c index aa19be6a8..446c13db1 100644 --- a/src/plugins/xfer/xfer-network.c +++ b/src/plugins/xfer/xfer-network.c @@ -29,9 +29,11 @@ #include <sys/wait.h> #include <sys/socket.h> #include <netinet/in.h> +#include <arpa/nameser.h> +#include <netdb.h> +#include <resolv.h> #include <signal.h> #include <time.h> -#include <netdb.h> #include "../weechat-plugin.h" #include "xfer.h" @@ -43,6 +45,110 @@ /* + * Converts integer address (as string) to IPv4 string using notation + * "a.b.c.d". + * + * For example: "3232235778" -> "192.168.1.2" + * + * Note: result must be freed after use. + */ + +char * +xfer_network_convert_integer_to_ipv4 (const char *str_address) +{ + char *error, result[64]; + long number; + + if (!str_address || !str_address[0]) + return NULL; + + number = strtol (str_address, &error, 10); + if (!error || error[0] || (number <= 0)) + return NULL; + + snprintf (result, sizeof (result), + "%ld.%ld.%ld.%ld", + (number >> 24) & 0xFF, + (number >> 16) & 0xFF, + (number >> 8) & 0xFF, + number & 0xFF); + + return strdup (result); +} + +/* + * Resolves address. + * + * Returns: + * 1: OK + * 0: error + */ + +int +xfer_network_resolve_addr (const char *str_address, const char *str_port, + struct sockaddr *addr, socklen_t *addr_len, + int ai_flags) +{ + struct addrinfo *ainfo, hints; + char *converted_address; + int rc; + + memset (&hints, 0, sizeof (struct addrinfo)); + hints.ai_flags = ai_flags; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + hints.ai_canonname = NULL; + hints.ai_addr = NULL; + hints.ai_next = NULL; + + res_init (); + + rc = getaddrinfo (str_address, str_port, &hints, &ainfo); + + /* + * workaround for termux where an IP address as integer is not supported: + * it returns an error EAI_NONAME (8); in this case we manually convert + * the integer to IPv4 string, for example: 3232235778 -> 192.168.1.2 + */ + if (rc == EAI_NONAME) + { + converted_address = xfer_network_convert_integer_to_ipv4 (str_address); + if (converted_address) + { + rc = getaddrinfo (converted_address, str_port, &hints, &ainfo); + free (converted_address); + } + } + + if ((rc == 0) && ainfo && ainfo->ai_addr) + { + if (ainfo->ai_addrlen > *addr_len) + { + weechat_printf (NULL, + _("%s%s: address \"%s\" resolved to a larger " + "sockaddr than expected"), + weechat_prefix ("error"), XFER_PLUGIN_NAME, + str_address); + freeaddrinfo (ainfo); + return 0; + } + memcpy (addr, ainfo->ai_addr, ainfo->ai_addrlen); + *addr_len = ainfo->ai_addrlen; + freeaddrinfo (ainfo); + return 1; + } + + weechat_printf (NULL, + _("%s%s: invalid address \"%s\": error %d %s"), + weechat_prefix ("error"), XFER_PLUGIN_NAME, + str_address, rc, gai_strerror (rc)); + if ((rc == 0) && ainfo) + freeaddrinfo (ainfo); + return 0; +} + +/* * Creates pipe for communication with child process. * * Returns: diff --git a/src/plugins/xfer/xfer-network.h b/src/plugins/xfer/xfer-network.h index cb9be323e..1790d3494 100644 --- a/src/plugins/xfer/xfer-network.h +++ b/src/plugins/xfer/xfer-network.h @@ -20,6 +20,13 @@ #ifndef WEECHAT_PLUGIN_XFER_NETWORK_H #define WEECHAT_PLUGIN_XFER_NETWORK_H +#include <sys/socket.h> + +extern int xfer_network_resolve_addr (const char *str_address, + const char *str_port, + struct sockaddr *addr, + socklen_t *addr_len, + int ai_flags); extern void xfer_network_write_pipe (struct t_xfer *xfer, int status, int error); extern void xfer_network_connect_init (struct t_xfer *xfer); diff --git a/src/plugins/xfer/xfer.c b/src/plugins/xfer/xfer.c index 331c5f521..20879836b 100644 --- a/src/plugins/xfer/xfer.c +++ b/src/plugins/xfer/xfer.c @@ -28,10 +28,7 @@ #include <sys/stat.h> #include <time.h> #include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/nameser.h> #include <netdb.h> -#include <resolv.h> #include <gcrypt.h> #include <arpa/inet.h> @@ -971,59 +968,6 @@ xfer_free_all () } /* - * Resolves address. - * - * Returns: - * 1: OK - * 0: error - */ - -int -xfer_resolve_addr (const char *str_address, const char *str_port, - struct sockaddr *addr, socklen_t *addr_len, int ai_flags) -{ - struct addrinfo *ainfo, hints; - int rc; - - memset (&hints, 0, sizeof (struct addrinfo)); - hints.ai_flags = ai_flags; - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; - hints.ai_canonname = NULL; - hints.ai_addr = NULL; - hints.ai_next = NULL; - - res_init (); - rc = getaddrinfo (str_address, str_port, &hints, &ainfo); - if ((rc == 0) && ainfo && ainfo->ai_addr) - { - if (ainfo->ai_addrlen > *addr_len) - { - weechat_printf (NULL, - _("%s%s: address \"%s\" resolved to a larger " - "sockaddr than expected"), - weechat_prefix ("error"), XFER_PLUGIN_NAME, - str_address); - freeaddrinfo (ainfo); - return 0; - } - memcpy (addr, ainfo->ai_addr, ainfo->ai_addrlen); - *addr_len = ainfo->ai_addrlen; - freeaddrinfo (ainfo); - return 1; - } - - weechat_printf (NULL, - _("%s%s: invalid address \"%s\": error %d %s"), - weechat_prefix ("error"), XFER_PLUGIN_NAME, - str_address, rc, gai_strerror (rc)); - if ((rc == 0) && ainfo) - freeaddrinfo (ainfo); - return 0; -} - -/* * Callback for signal "xfer_add". */ @@ -1208,9 +1152,9 @@ xfer_add_cb (const void *pointer, void *data, snprintf (str_port_temp, sizeof (str_port_temp), "%d", port); str_port = str_port_temp; length = sizeof (addr); - if (!xfer_resolve_addr (str_address, str_port, - (struct sockaddr*)&addr, &length, - AI_NUMERICSERV | AI_NUMERICHOST)) + if (!xfer_network_resolve_addr (str_address, str_port, + (struct sockaddr*)&addr, &length, + AI_NUMERICSERV | AI_NUMERICHOST)) { goto error; } @@ -1227,9 +1171,10 @@ xfer_add_cb (const void *pointer, void *data, str_address = weechat_config_string (xfer_config_network_own_ip); length = sizeof (own_ip_addr); - if (!xfer_resolve_addr (str_address, NULL, - (struct sockaddr*)&own_ip_addr, &length, - AI_NUMERICSERV)) + if (!xfer_network_resolve_addr (str_address, NULL, + (struct sockaddr*)&own_ip_addr, + &length, + AI_NUMERICSERV)) { goto error; } @@ -1245,9 +1190,9 @@ xfer_add_cb (const void *pointer, void *data, /* no own_ip, so bind_addr's family comes from irc connection */ str_address = weechat_infolist_string (infolist, "local_address"); length = sizeof (addr); - if (!xfer_resolve_addr (str_address, NULL, - (struct sockaddr*)&addr, &length, - AI_NUMERICSERV | AI_NUMERICHOST)) + if (!xfer_network_resolve_addr (str_address, NULL, + (struct sockaddr*)&addr, &length, + AI_NUMERICSERV | AI_NUMERICHOST)) { goto error; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0f5bd1e27..c040c2d8a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -104,6 +104,7 @@ endif() if(ENABLE_XFER) list(APPEND LIB_WEECHAT_UNIT_TESTS_PLUGINS_SRC unit/plugins/xfer/test-xfer-file.cpp + unit/plugins/xfer/test-xfer-network.cpp ) endif() diff --git a/tests/Makefile.am b/tests/Makefile.am index 0ae07b746..4b974636b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -108,7 +108,8 @@ tests_typing = unit/plugins/typing/test-typing.cpp \ endif if PLUGIN_XFER -tests_xfer = unit/plugins/xfer/test-xfer-file.cpp +tests_xfer = unit/plugins/xfer/test-xfer-file.cpp \ + unit/plugins/xfer/test-xfer-network.cpp endif lib_weechat_unit_tests_plugins_la_SOURCES = unit/plugins/test-plugins.cpp \ diff --git a/tests/unit/plugins/xfer/test-xfer-network.cpp b/tests/unit/plugins/xfer/test-xfer-network.cpp new file mode 100644 index 000000000..d9d3ae6f5 --- /dev/null +++ b/tests/unit/plugins/xfer/test-xfer-network.cpp @@ -0,0 +1,58 @@ +/* + * test-xfer-network.cpp - test xfer network functions + * + * Copyright (C) 2022 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "CppUTest/TestHarness.h" + +#include "tests/tests.h" + +extern "C" +{ +#include "src/plugins/xfer/xfer-network.h" + +extern char *xfer_network_convert_integer_to_ipv4 (const char *str_address); +} + +TEST_GROUP(XferNetwork) +{ +}; + +/* + * Tests functions: + * xfer_network_convert_integer_to_ipv4 + */ + +TEST(XferNetwork, ConvertIntegerToIpv4) +{ + char *str; + + POINTERS_EQUAL(NULL, xfer_network_convert_integer_to_ipv4 (NULL)); + POINTERS_EQUAL(NULL, xfer_network_convert_integer_to_ipv4 ("")); + POINTERS_EQUAL(NULL, xfer_network_convert_integer_to_ipv4 ("abc")); + POINTERS_EQUAL(NULL, xfer_network_convert_integer_to_ipv4 ("0")); + POINTERS_EQUAL(NULL, xfer_network_convert_integer_to_ipv4 ("-1")); + + WEE_TEST_STR("0.0.0.1", xfer_network_convert_integer_to_ipv4 ("1")); + WEE_TEST_STR("0.0.1.0", xfer_network_convert_integer_to_ipv4 ("256")); + WEE_TEST_STR("0.1.0.0", xfer_network_convert_integer_to_ipv4 ("65536")); + WEE_TEST_STR("1.0.0.0", xfer_network_convert_integer_to_ipv4 ("16777216")); + WEE_TEST_STR("127.0.0.1", xfer_network_convert_integer_to_ipv4 ("2130706433")); + WEE_TEST_STR("192.168.1.2", xfer_network_convert_integer_to_ipv4 ("3232235778")); +} |