diff options
author | Mario Campos <mario-campos@github.com> | 2023-08-22 18:59:59 -0500 |
---|---|---|
committer | Sébastien Helleu <flashcode@flashtux.org> | 2023-09-06 14:11:35 +0200 |
commit | 7f0f947667ec6ed22b30e205627da51dffe620c4 (patch) | |
tree | 0aa2cdac02e136220bd6d2f1b95c6990d52ca962 /src/plugins/xfer/xfer.c | |
parent | 23d70b5101f8a8ca9cac92e25b783c8259ab14df (diff) | |
download | weechat-7f0f947667ec6ed22b30e205627da51dffe620c4.zip |
xfer: add passive DCC support.
This commit also includes support for passive DCC RESUME.
There was also a potential segfault with calling `atoi(pos_token)` when `pos_token` is NULL, so `token` is set to be stored as a string. Although it is an integer, we don't need to store it as such. That's really more of an implementation detail.
Diffstat (limited to 'src/plugins/xfer/xfer.c')
-rw-r--r-- | src/plugins/xfer/xfer.c | 124 |
1 files changed, 81 insertions, 43 deletions
diff --git a/src/plugins/xfer/xfer.c b/src/plugins/xfer/xfer.c index e4a62a2dc..32767200c 100644 --- a/src/plugins/xfer/xfer.c +++ b/src/plugins/xfer/xfer.c @@ -637,9 +637,10 @@ xfer_new (const char *plugin_name, const char *plugin_id, enum t_xfer_type type, enum t_xfer_protocol protocol, const char *remote_nick, const char *local_nick, const char *charset_modifier, const char *filename, - unsigned long long size, const char *proxy, struct sockaddr *address, - socklen_t address_length, int port, int sock, - const char *local_filename) + unsigned long long size, const char *proxy, struct sockaddr *remote_address, + socklen_t remote_address_length, struct sockaddr *local_address, + socklen_t local_address_length, int port, int sock, + const char *local_filename, const char *token) { struct t_xfer *new_xfer; const char *ptr_crc32; @@ -680,27 +681,44 @@ xfer_new (const char *plugin_name, const char *plugin_id, new_xfer->size = size; new_xfer->proxy = (proxy) ? strdup (proxy) : NULL; new_xfer->port = port; + new_xfer->token = (token) ? strdup (token) : NULL; - rc = getnameinfo ((struct sockaddr *)address, address_length, str_address, - sizeof (str_address), NULL, 0, NI_NUMERICHOST); - if (rc != 0) + if (XFER_IS_RECV(type)) { - weechat_printf (NULL, - _("%s%s: unable to interpret address: error %d %s"), - weechat_prefix ("error"), XFER_PLUGIN_NAME, - rc, gai_strerror (rc)); - snprintf (str_address, sizeof (str_address), "?"); + rc = getnameinfo ((struct sockaddr *)remote_address, remote_address_length, str_address, + sizeof (str_address), NULL, 0, NI_NUMERICHOST); + if (rc != 0) + { + weechat_printf (NULL, + _("%s%s: unable to interpret address: error %d %s"), + weechat_prefix ("error"), XFER_PLUGIN_NAME, + rc, gai_strerror (rc)); + snprintf (str_address, sizeof (str_address), "?"); + } + xfer_set_remote_address (new_xfer, remote_address, remote_address_length, str_address); + } + else + { + new_xfer->remote_address_str = strdup (""); } - if (XFER_IS_RECV(type)) + if (XFER_IS_PASSIVE(type)) { - new_xfer->local_address_str = strdup (""); - xfer_set_remote_address (new_xfer, address, address_length, str_address); + rc = getnameinfo ((struct sockaddr *)local_address, local_address_length, str_address, + sizeof (str_address), NULL, 0, NI_NUMERICHOST); + if (rc != 0) + { + weechat_printf (NULL, + _("%s%s: unable to interpret address: error %d %s"), + weechat_prefix ("error"), XFER_PLUGIN_NAME, + rc, gai_strerror (rc)); + snprintf (str_address, sizeof (str_address), "?"); + } + xfer_set_local_address (new_xfer, local_address, local_address_length, str_address); } else { - xfer_set_local_address (new_xfer, address, address_length, str_address); - new_xfer->remote_address_str = strdup (""); + new_xfer->local_address_str = strdup (""); } new_xfer->status = XFER_STATUS_WAITING; @@ -744,13 +762,14 @@ xfer_new (const char *plugin_name, const char *plugin_id, switch (type) { case XFER_TYPE_FILE_RECV_ACTIVE: + case XFER_TYPE_FILE_RECV_PASSIVE: weechat_printf (NULL, _("%s: incoming file from %s " "(%s, %s.%s), name: %s, %llu bytes " "(protocol: %s)"), XFER_PLUGIN_NAME, remote_nick, - str_address, + new_xfer->remote_address_str, plugin_name, plugin_id, filename, @@ -758,6 +777,7 @@ xfer_new (const char *plugin_name, const char *plugin_id, xfer_protocol_string[protocol]); xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE); break; + case XFER_TYPE_FILE_SEND_ACTIVE: case XFER_TYPE_FILE_SEND_PASSIVE: weechat_printf (NULL, _("%s: offering file to %s (%s.%s), name: %s " @@ -778,7 +798,7 @@ xfer_new (const char *plugin_name, const char *plugin_id, "(%s, %s.%s)"), XFER_PLUGIN_NAME, remote_nick, - str_address, + new_xfer->remote_address_str, plugin_name, plugin_id); xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE); @@ -990,13 +1010,14 @@ xfer_add_cb (const void *pointer, void *data, struct t_infolist *infolist; const char *plugin_name, *plugin_id, *str_type, *str_protocol; const char *remote_nick, *local_nick, *charset_modifier, *filename, *proxy; - const char *str_address, *str_port; - int type, protocol, args, port_start, port_end, sock, port; + const char *str_address, *str_port, *token; + int type, protocol, args, port_start, port_end, sock, server_sock, port; char *path, *filename2, *short_filename, *pos, str_port_temp[16]; struct stat st; - struct sockaddr_storage addr, own_ip_addr, bind_addr; - struct sockaddr *out_addr = (struct sockaddr*)&addr; - socklen_t length, bind_addr_len; + struct sockaddr_storage local_addr_storage, remote_addr_storage, own_ip_addr, bind_addr; + struct sockaddr *local_addr = (struct sockaddr*)&local_addr_storage; + struct sockaddr *remote_addr = (struct sockaddr*)&remote_addr_storage; + socklen_t local_addr_length, remote_addr_length, bind_addr_len; unsigned long long file_size; struct t_xfer *ptr_xfer; struct t_hashtable *options; @@ -1040,6 +1061,7 @@ xfer_add_cb (const void *pointer, void *data, charset_modifier = weechat_infolist_string (infolist, "charset_modifier"); filename = weechat_infolist_string (infolist, "filename"); proxy = weechat_infolist_string (infolist, "proxy"); + token = weechat_infolist_string (infolist, "token"); protocol = XFER_NO_PROTOCOL; if (!plugin_name || !plugin_id || !str_type || !remote_nick || !local_nick) @@ -1080,7 +1102,7 @@ xfer_add_cb (const void *pointer, void *data, } } - if (type == XFER_TYPE_FILE_RECV_ACTIVE) + if (XFER_IS_RECV(type)) { filename2 = strdup (filename); sscanf (weechat_infolist_string (infolist, "size"), "%llu", &file_size); @@ -1157,20 +1179,31 @@ xfer_add_cb (const void *pointer, void *data, port = weechat_infolist_integer (infolist, "port"); /* resolve address */ - if (XFER_IS_RECV(type)) + if ((type == XFER_TYPE_CHAT_RECV) || (type == XFER_TYPE_FILE_RECV_ACTIVE)) { str_address = weechat_infolist_string (infolist, "remote_address"); snprintf (str_port_temp, sizeof (str_port_temp), "%d", port); str_port = str_port_temp; - length = sizeof (addr); + remote_addr_length = sizeof (remote_addr_storage); if (!xfer_network_resolve_addr (str_address, str_port, - (struct sockaddr*)&addr, &length, + (struct sockaddr*)&remote_addr_storage, &remote_addr_length, AI_NUMERICSERV | AI_NUMERICHOST)) { goto error; } } - else + if (type == XFER_TYPE_FILE_RECV_PASSIVE) + { + str_address = weechat_infolist_string (infolist, "remote_address"); + remote_addr_length = sizeof (remote_addr_storage); + if (!xfer_network_resolve_addr (str_address, NULL, + (struct sockaddr*)&remote_addr_storage, &remote_addr_length, + AI_NUMERICSERV | AI_NUMERICHOST)) + { + goto error; + } + } + if (XFER_IS_PASSIVE(type)) { memset (&bind_addr, 0, sizeof (bind_addr)); @@ -1180,18 +1213,18 @@ xfer_add_cb (const void *pointer, void *data, { /* resolve own_ip to a numeric address */ str_address = weechat_config_string (xfer_config_network_own_ip); - length = sizeof (own_ip_addr); + local_addr_length = sizeof (own_ip_addr); if (!xfer_network_resolve_addr (str_address, NULL, (struct sockaddr*)&own_ip_addr, - &length, + &local_addr_length, AI_NUMERICSERV)) { goto error; } /* set the advertised address to own_ip */ - out_addr = (struct sockaddr*)&own_ip_addr; + local_addr = (struct sockaddr*)&own_ip_addr; /* bind_addr's family should be the advertised family */ bind_addr.ss_family = own_ip_addr.ss_family; @@ -1199,15 +1232,15 @@ xfer_add_cb (const void *pointer, void *data, else { /* 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_network_resolve_addr (str_address, NULL, - (struct sockaddr*)&addr, &length, - AI_NUMERICSERV | AI_NUMERICHOST)) + /* use the local interface, from the server socket */ + memset (&local_addr_storage, 0, sizeof (local_addr_storage)); + local_addr_length = sizeof (local_addr_storage); + server_sock = weechat_infolist_integer (infolist, "socket"); + if (getsockname (server_sock, (struct sockaddr *)&local_addr_storage, &local_addr_length)) { goto error; } - bind_addr.ss_family = addr.ss_family; + bind_addr.ss_family = local_addr_storage.ss_family; } /* determine bind wildcard address */ @@ -1318,7 +1351,7 @@ xfer_add_cb (const void *pointer, void *data, } } - if (type == XFER_TYPE_FILE_RECV_ACTIVE) + if (XFER_IS_RECV(type)) { if (filename2) { @@ -1332,14 +1365,14 @@ xfer_add_cb (const void *pointer, void *data, { ptr_xfer = xfer_new (plugin_name, plugin_id, type, protocol, remote_nick, local_nick, charset_modifier, - short_filename, file_size, proxy, - out_addr, length, port, sock, filename2); + short_filename, file_size, proxy, remote_addr, + remote_addr_length, local_addr, local_addr_length, port, sock, filename2, token); } else { ptr_xfer = xfer_new (plugin_name, plugin_id, type, protocol, remote_nick, local_nick, charset_modifier, NULL, - 0, proxy, out_addr, length, port, sock, NULL); + 0, proxy, NULL, 0, local_addr, local_addr_length, port, sock, NULL, token); } if (!ptr_xfer) @@ -1382,7 +1415,7 @@ xfer_start_resume_cb (const void *pointer, void *data, { struct t_infolist *infolist; struct t_xfer *ptr_xfer; - const char *plugin_name, *plugin_id, *filename, *str_start_resume; + const char *plugin_name, *plugin_id, *filename, *str_start_resume, *token; int port; unsigned long long start_resume; @@ -1417,6 +1450,7 @@ xfer_start_resume_cb (const void *pointer, void *data, filename = weechat_infolist_string (infolist, "filename"); port = weechat_infolist_integer (infolist, "port"); str_start_resume = weechat_infolist_string (infolist, "start_resume"); + token = weechat_infolist_string (infolist, "token"); if (!plugin_name || !plugin_id || !filename || !str_start_resume) { @@ -1429,7 +1463,8 @@ xfer_start_resume_cb (const void *pointer, void *data, sscanf (str_start_resume, "%llu", &start_resume); - ptr_xfer = xfer_search (plugin_name, plugin_id, XFER_TYPE_FILE_RECV_ACTIVE, + ptr_xfer = xfer_search (plugin_name, plugin_id, + (!token) ? XFER_TYPE_FILE_RECV_ACTIVE : XFER_TYPE_FILE_RECV_PASSIVE, XFER_STATUS_CONNECTING, port); if (ptr_xfer) { @@ -1602,6 +1637,8 @@ xfer_add_to_infolist (struct t_infolist *infolist, struct t_xfer *xfer) return 0; if (!weechat_infolist_new_var_integer (ptr_item, "port", xfer->port)) return 0; + if (!weechat_infolist_new_var_string (ptr_item, "token", xfer->token)) + return 0; if (!weechat_infolist_new_var_integer (ptr_item, "status", xfer->status)) return 0; @@ -1709,6 +1746,7 @@ xfer_print_log () weechat_log_printf (" remote_address_length . : %d", ptr_xfer->remote_address_length); weechat_log_printf (" remote_address_str. . . : '%s'", ptr_xfer->remote_address_str); weechat_log_printf (" port. . . . . . . . . . : %d", ptr_xfer->port); + weechat_log_printf (" token . . . . . . . . . : %s", ptr_xfer->token); weechat_log_printf (" status. . . . . . . . . : %d (%s)", ptr_xfer->status, |