summaryrefslogtreecommitdiff
path: root/src/plugins/xfer/xfer.c
diff options
context:
space:
mode:
authorMario Campos <mario-campos@github.com>2023-08-22 18:59:59 -0500
committerSébastien Helleu <flashcode@flashtux.org>2023-09-06 14:11:35 +0200
commit7f0f947667ec6ed22b30e205627da51dffe620c4 (patch)
tree0aa2cdac02e136220bd6d2f1b95c6990d52ca962 /src/plugins/xfer/xfer.c
parent23d70b5101f8a8ca9cac92e25b783c8259ab14df (diff)
downloadweechat-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.c124
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,