1
0
mirror of https://github.com/weechat/weechat.git synced 2026-06-30 06:46:38 +02:00

xfer: add support of IPv6 for DCC chat/file (patch #7992)

This commit is contained in:
Andrew Potter
2014-01-09 12:48:54 +01:00
committed by Sebastien Helleu
parent 9040dfbf52
commit 144dc60d0a
13 changed files with 394 additions and 243 deletions
+1
View File
@@ -97,6 +97,7 @@ http://weechat.org/files/releasenotes/ReleaseNotes-devel.html[release notes]
* lua: fix crash on calls to callbacks during load of script
* python: fix load of scripts with python >= 3.3
* ruby: fix ruby init with ruby >= 2.0 (bug #41115)
* xfer: add support of IPv6 for DCC chat/file (patch #7992)
* xfer: use same infolist for hook and signals (patch #7974)
* xfer: add option xfer.file.auto_check_crc32 (patch #7963)
+57 -29
View File
@@ -645,56 +645,84 @@ network_connect (int sock, const struct sockaddr *addr, socklen_t addrlen)
* process.
*
* Returns:
* 1: OK
* 0: error
* >= 0: connected socket fd
* -1: error
*/
int
network_connect_to (const char *proxy, int sock,
unsigned long address, int port)
network_connect_to (const char *proxy, struct sockaddr *address,
socklen_t address_length)
{
struct t_proxy *ptr_proxy;
struct sockaddr_in addr;
struct hostent *hostent;
char *ip4;
struct addrinfo *proxy_addrinfo, hints;
char str_port[16], ip[NI_MAXHOST];
int port, sock;
sock = -1;
proxy_addrinfo = NULL;
ptr_proxy = NULL;
if (proxy && proxy[0])
{
ptr_proxy = proxy_search (proxy);
if (!ptr_proxy)
return 0;
return -1;
}
if (ptr_proxy)
{
memset (&addr, 0, sizeof (addr));
addr.sin_addr.s_addr = htonl (address);
ip4 = inet_ntoa(addr.sin_addr);
/* get IP address/port */
if (getnameinfo (address, address_length, ip, sizeof (ip),
str_port, sizeof (str_port),
NI_NUMERICHOST | NI_NUMERICSERV) != 0)
{
goto error;
}
port = atoi (str_port);
memset (&addr, 0, sizeof (addr));
addr.sin_port = htons (CONFIG_INTEGER(ptr_proxy->options[PROXY_OPTION_PORT]));
addr.sin_family = AF_INET;
hostent = gethostbyname (CONFIG_STRING(ptr_proxy->options[PROXY_OPTION_ADDRESS]));
if (!hostent)
return 0;
memcpy(&(addr.sin_addr), *(hostent->h_addr_list), sizeof(struct in_addr));
if (!network_connect (sock, (struct sockaddr *) &addr, sizeof (addr)))
return 0;
if (!network_pass_proxy (proxy, sock, ip4, port))
return 0;
/* get sockaddr for proxy */
memset (&hints, 0, sizeof (hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_NUMERICSERV;
snprintf (str_port, sizeof (str_port), "%d",
CONFIG_INTEGER(ptr_proxy->options[PROXY_OPTION_PORT]));
if (getaddrinfo (CONFIG_STRING(ptr_proxy->options[PROXY_OPTION_ADDRESS]),
str_port, &hints, &proxy_addrinfo) != 0)
{
goto error;
}
/* connect and pass address to proxy */
sock = socket (proxy_addrinfo->ai_family, SOCK_STREAM, 0);
if (sock == -1)
goto error;
if (!network_connect (sock, proxy_addrinfo->ai_addr,
proxy_addrinfo->ai_addrlen))
goto error;
if (!network_pass_proxy (proxy, sock, ip, port))
goto error;
}
else
{
memset (&addr, 0, sizeof (addr));
addr.sin_port = htons (port);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl (address);
if (!network_connect (sock, (struct sockaddr *) &addr, sizeof (addr)))
return 0;
sock = socket (address->sa_family, SOCK_STREAM, 0);
if (sock == -1)
goto error;
if (!network_connect (sock, address, address_length))
goto error;
}
return 1;
if (proxy_addrinfo)
freeaddrinfo (proxy_addrinfo);
return sock;
error:
if (sock >= 0)
close (sock);
if (proxy_addrinfo)
freeaddrinfo (proxy_addrinfo);
return -1;
}
/*
+5 -2
View File
@@ -20,6 +20,9 @@
#ifndef __WEECHAT_NETWORK_H
#define __WEECHAT_NETWORK_H 1
#include <sys/types.h>
#include <sys/socket.h>
struct t_hook;
struct t_network_socks4
@@ -48,8 +51,8 @@ extern void network_init_gnutls ();
extern void network_end ();
extern int network_pass_proxy (const char *proxy, int sock,
const char *address, int port);
extern int network_connect_to (const char *proxy, int sock,
unsigned long address, int port);
extern int network_connect_to (const char *proxy, struct sockaddr *address,
socklen_t address_length);
extern void network_connect_with_fork (struct t_hook *hook_connect);
#endif /* __WEECHAT_NETWORK_H */
+17 -11
View File
@@ -29,6 +29,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include "../weechat-plugin.h"
#include "irc.h"
@@ -1380,12 +1381,12 @@ int
irc_command_dcc (void *data, struct t_gui_buffer *buffer, int argc,
char **argv, char **argv_eol)
{
struct sockaddr_in addr;
struct sockaddr_storage addr;
socklen_t length;
unsigned long address;
struct t_infolist *infolist;
struct t_infolist_item *item;
char str_address[128], charset_modifier[256];
char str_address[NI_MAXHOST], charset_modifier[256];
int rc;
IRC_BUFFER_GET_SERVER_CHANNEL(buffer);
IRC_COMMAND_CHECK_SERVER("dcc", 1);
@@ -1396,11 +1397,20 @@ irc_command_dcc (void *data, struct t_gui_buffer *buffer, int argc,
if (argc > 1)
{
/* use the local interface, from the server socket */
memset (&addr, 0, sizeof (struct sockaddr_in));
memset (&addr, 0, sizeof (addr));
length = sizeof (addr);
getsockname (ptr_server->sock, (struct sockaddr *) &addr, &length);
addr.sin_family = AF_INET;
address = ntohl (addr.sin_addr.s_addr);
getsockname (ptr_server->sock, (struct sockaddr *)&addr, &length);
rc = getnameinfo ((struct sockaddr *)&addr, length, str_address,
sizeof (str_address), NULL, 0, NI_NUMERICHOST);
if (rc != 0)
{
weechat_printf (ptr_server->buffer,
_("%s%s: unable to resolve local address of server "
"socket: error %d %s"),
weechat_prefix ("error"), IRC_PLUGIN_NAME,
rc, gai_strerror (rc));
return WEECHAT_RC_OK;
}
/* DCC SEND file */
if (weechat_strcasecmp (argv[1], "send") == 0)
@@ -1422,8 +1432,6 @@ irc_command_dcc (void *data, struct t_gui_buffer *buffer, int argc,
weechat_infolist_new_var_string (item, "remote_nick", argv[2]);
weechat_infolist_new_var_string (item, "local_nick", ptr_server->nick);
weechat_infolist_new_var_string (item, "filename", argv_eol[3]);
snprintf (str_address, sizeof (str_address),
"%lu", address);
weechat_infolist_new_var_string (item, "local_address", str_address);
weechat_infolist_new_var_integer (item, "socket", ptr_server->sock);
weechat_hook_signal_send ("xfer_add",
@@ -1454,8 +1462,6 @@ irc_command_dcc (void *data, struct t_gui_buffer *buffer, int argc,
snprintf (charset_modifier, sizeof (charset_modifier),
"irc.%s.%s", ptr_server->name, argv[2]);
weechat_infolist_new_var_string (item, "charset_modifier", charset_modifier);
snprintf (str_address, sizeof (str_address),
"%lu", address);
weechat_infolist_new_var_string (item, "local_address", str_address);
weechat_hook_signal_send ("xfer_add",
WEECHAT_HOOK_SIGNAL_POINTER,
+39 -7
View File
@@ -36,6 +36,9 @@
#include <sys/socket.h>
#include <sys/time.h>
#endif
#include <sys/types.h>
#include <netdb.h>
#include <arpa/inet.h>
#ifdef HAVE_GNUTLS
#include <gnutls/gnutls.h>
@@ -4402,8 +4405,11 @@ irc_server_xfer_send_ready_cb (void *data, const char *signal,
{
struct t_infolist *infolist;
struct t_irc_server *ptr_server;
const char *plugin_name, *plugin_id, *type, *filename;
int spaces_in_name;
const char *plugin_name, *plugin_id, *type, *filename, *local_address;
char converted_addr[NI_MAXHOST];
struct addrinfo *ainfo;
struct sockaddr_in *saddr;
int spaces_in_name, rc;
/* make C compiler happy */
(void) data;
@@ -4416,14 +4422,40 @@ irc_server_xfer_send_ready_cb (void *data, const char *signal,
{
plugin_name = weechat_infolist_string (infolist, "plugin_name");
plugin_id = weechat_infolist_string (infolist, "plugin_id");
if (plugin_name && (strcmp (plugin_name, IRC_PLUGIN_NAME) == 0) && plugin_id)
if (plugin_name && (strcmp (plugin_name, IRC_PLUGIN_NAME) == 0)
&& plugin_id)
{
ptr_server = irc_server_search (plugin_id);
if (ptr_server)
{
type = weechat_infolist_string (infolist, "type_string");
if (type)
converted_addr[0] = '\0';
local_address = weechat_infolist_string (infolist,
"local_address");
if (local_address)
{
rc = getaddrinfo (local_address, NULL, NULL, &ainfo);
if ((rc == 0) && ainfo && ainfo->ai_addr)
{
if (ainfo->ai_family == AF_INET)
{
/* transform dotted 4 IP address to ulong string */
saddr = (struct sockaddr_in *)ainfo->ai_addr;
snprintf (converted_addr, sizeof (converted_addr),
"%lu",
(unsigned long)ntohl (saddr->sin_addr.s_addr));
}
else
{
snprintf (converted_addr, sizeof (converted_addr),
"%s", local_address);
}
}
}
type = weechat_infolist_string (infolist, "type_string");
if (type && converted_addr[0])
{
/* send DCC PRIVMSG */
if (strcmp (type, "file_send") == 0)
{
filename = weechat_infolist_string (infolist, "filename");
@@ -4436,7 +4468,7 @@ irc_server_xfer_send_ready_cb (void *data, const char *signal,
(spaces_in_name) ? "\"" : "",
filename,
(spaces_in_name) ? "\"" : "",
weechat_infolist_string (infolist, "local_address"),
converted_addr,
weechat_infolist_integer (infolist, "port"),
weechat_infolist_string (infolist, "size"));
}
@@ -4446,7 +4478,7 @@ irc_server_xfer_send_ready_cb (void *data, const char *signal,
IRC_SERVER_SEND_OUTQ_PRIO_HIGH, NULL,
"PRIVMSG %s :\01DCC CHAT chat %s %d\01",
weechat_infolist_string (infolist, "remote_nick"),
weechat_infolist_string (infolist, "local_address"),
converted_addr,
weechat_infolist_integer (infolist, "port"));
}
}
+9 -6
View File
@@ -27,6 +27,7 @@ extern "C" {
#endif
#include <sys/types.h>
#include <sys/socket.h>
/* some systems like GNU/Hurd do not define PATH_MAX */
#ifndef PATH_MAX
@@ -56,7 +57,7 @@ struct timeval;
* please change the date with current one; for a second change at same
* date, increment the 01, otherwise please keep 01.
*/
#define WEECHAT_PLUGIN_API_VERSION "20140105-01"
#define WEECHAT_PLUGIN_API_VERSION "20140109-01"
/* macros for defining plugin infos */
#define WEECHAT_PLUGIN_NAME(__name) \
@@ -807,8 +808,9 @@ struct t_weechat_plugin
/* network */
int (*network_pass_proxy) (const char *proxy, int sock,
const char *address, int port);
int (*network_connect_to) (const char *proxy, int sock,
unsigned long address, int port);
int (*network_connect_to) (const char *proxy,
struct sockaddr *address,
socklen_t address_length);
/* infos */
const char *(*info_get) (struct t_weechat_plugin *plugin,
@@ -1587,9 +1589,10 @@ extern int weechat_plugin_end (struct t_weechat_plugin *plugin);
#define weechat_network_pass_proxy(__proxy, __sock, __address, __port) \
weechat_plugin->network_pass_proxy(__proxy, __sock, __address, \
__port)
#define weechat_network_connect_to(__proxy, __sock, __address, __port) \
weechat_plugin->network_connect_to(__proxy, __sock, __address, \
__port)
#define weechat_network_connect_to(__proxy, __address, \
__address_length) \
weechat_plugin->network_connect_to(__proxy, __address, \
__address_length)
/* infos */
#define weechat_info_get(__info_name, __arguments) \
+4 -7
View File
@@ -44,7 +44,7 @@ xfer_buffer_refresh (const char *hotlist)
{
struct t_xfer *ptr_xfer, *xfer_selected;
char str_color[256], suffix[32], status[64], date[128], eta[128];
char str_ip[32], str_hash[128];
char str_ip[128], str_hash[128];
char *progress_bar, *str_pos, *str_total, *str_bytes_per_sec;
int i, length, line, progress_bar_size, num_bars;
unsigned long long pos, pct_complete;
@@ -93,14 +93,11 @@ xfer_buffer_refresh (const char *hotlist)
weechat_config_string (xfer_config_color_text_bg));
str_ip[0] = '\0';
if (ptr_xfer->remote_address != 0)
if (ptr_xfer->remote_address_str)
{
snprintf (str_ip, sizeof (str_ip),
" (%ld.%ld.%ld.%ld)",
ptr_xfer->remote_address >> 24,
(ptr_xfer->remote_address >> 16) & 0xff,
(ptr_xfer->remote_address >> 8) & 0xff,
ptr_xfer->remote_address & 0xff);
" (%s)",
ptr_xfer->remote_address_str);
}
str_hash[0] = '\0';
+2 -5
View File
@@ -372,14 +372,11 @@ xfer_chat_open_buffer (struct t_xfer *xfer)
}
weechat_printf (xfer->buffer,
_("%s%s: connected to %s (%ld.%ld.%ld.%ld)"),
_("%s%s: connected to %s (%s) via xfer chat"),
weechat_prefix ("network"),
XFER_PLUGIN_NAME,
xfer->remote_nick,
xfer->remote_address >> 24,
(xfer->remote_address >> 16) & 0xff,
(xfer->remote_address >> 8) & 0xff,
xfer->remote_address & 0xff);
xfer->remote_address_str);
free (name);
}
+2 -5
View File
@@ -157,15 +157,12 @@ xfer_command_xfer_list (int full)
weechat_printf (NULL,
_(" plugin: %s (id: %s), file: %llu "
"bytes (position: %llu), address: "
"%ld.%ld.%ld.%ld (port %d)"),
"%s (port %d)"),
ptr_xfer->plugin_name,
ptr_xfer->plugin_id,
ptr_xfer->size,
ptr_xfer->pos,
ptr_xfer->remote_address >> 24,
(ptr_xfer->remote_address >> 16) & 0xff,
(ptr_xfer->remote_address >> 8) & 0xff,
ptr_xfer->remote_address & 0xff,
ptr_xfer->remote_address_str,
ptr_xfer->port);
date[0] = '\0';
date_tmp = localtime (&(ptr_xfer->start_transfer));
+4 -2
View File
@@ -327,8 +327,10 @@ xfer_dcc_recv_file_child (struct t_xfer *xfer)
}
/* first connect to sender (blocking) */
if (!weechat_network_connect_to (xfer->proxy, xfer->sock,
xfer->remote_address, xfer->port))
xfer->sock = weechat_network_connect_to (xfer->proxy,
xfer->remote_address,
xfer->remote_address_length);
if (xfer->sock == -1)
{
xfer_network_write_pipe (xfer, XFER_STATUS_FAILED,
XFER_ERROR_CONNECT_SENDER);
+43 -18
View File
@@ -253,14 +253,11 @@ xfer_network_send_file_fork (struct t_xfer *xfer)
}
weechat_printf (NULL,
_("%s: sending file to %s (%ld.%ld.%ld.%ld, %s.%s), "
_("%s: sending file to %s (%s, %s.%s), "
"name: %s (local filename: %s), %llu bytes (protocol: %s)"),
XFER_PLUGIN_NAME,
xfer->remote_nick,
xfer->remote_address >> 24,
(xfer->remote_address >> 16) & 0xff,
(xfer->remote_address >> 8) & 0xff,
xfer->remote_address & 0xff,
xfer->remote_address_str,
xfer->plugin_name,
xfer->plugin_id,
xfer->filename,
@@ -375,12 +372,15 @@ xfer_network_fd_cb (void *arg_xfer, int fd)
{
struct t_xfer *xfer;
int sock, flags, error;
struct sockaddr_in addr;
struct sockaddr_storage addr;
socklen_t length;
char str_address[NI_MAXHOST];
/* make C compiler happy */
(void) fd;
length = sizeof (addr);
memset (&addr, 0, length);
xfer = (struct t_xfer *)arg_xfer;
if (xfer->status == XFER_STATUS_CONNECTING)
@@ -388,7 +388,6 @@ xfer_network_fd_cb (void *arg_xfer, int fd)
if (xfer->type == XFER_TYPE_FILE_SEND)
{
xfer->last_activity = time (NULL);
length = sizeof (addr);
sock = accept (xfer->sock,
(struct sockaddr *) &addr, &length);
error = errno;
@@ -422,7 +421,15 @@ xfer_network_fd_cb (void *arg_xfer, int fd)
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
return WEECHAT_RC_OK;
}
xfer->remote_address = ntohl (addr.sin_addr.s_addr);
error = getnameinfo ((struct sockaddr *)&addr, length, str_address,
sizeof (str_address), NULL, 0, NI_NUMERICHOST);
if (error != 0)
{
snprintf (str_address, sizeof (str_address),
"error: %s", gai_strerror (error));
}
xfer_set_remote_address (xfer, (struct sockaddr *)&addr, length,
str_address);
xfer->status = XFER_STATUS_ACTIVE;
xfer->start_transfer = time (NULL);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
@@ -467,7 +474,15 @@ xfer_network_fd_cb (void *arg_xfer, int fd)
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
return WEECHAT_RC_OK;
}
xfer->remote_address = ntohl (addr.sin_addr.s_addr);
error = getnameinfo ((struct sockaddr *)&addr, length, str_address,
sizeof (str_address), NULL, 0, NI_NUMERICHOST);
if (error != 0)
{
snprintf (str_address, sizeof (str_address),
"error: %s", gai_strerror (error));
}
xfer_set_remote_address (xfer, (struct sockaddr *)&addr, length,
str_address);
xfer->status = XFER_STATUS_ACTIVE;
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
xfer->hook_fd = weechat_hook_fd (xfer->sock,
@@ -528,15 +543,17 @@ xfer_network_connect (struct t_xfer *xfer)
else
xfer->status = XFER_STATUS_CONNECTING;
if (xfer->sock < 0)
{
xfer->sock = socket (AF_INET, SOCK_STREAM, 0);
if (xfer->sock < 0)
return 0;
}
if (XFER_IS_SEND(xfer->type))
{
/* create socket */
if (xfer->sock < 0)
{
xfer->sock = socket (xfer->remote_address->sa_family, SOCK_STREAM,
0);
if (xfer->sock < 0)
return 0;
}
/* listen to socket */
flags = fcntl (xfer->sock, F_GETFL);
if (flags == -1)
@@ -566,13 +583,21 @@ xfer_network_connect (struct t_xfer *xfer)
/* for chat receiving, connect to listening host */
if (xfer->type == XFER_TYPE_CHAT_RECV)
{
xfer->sock = weechat_network_connect_to (xfer->proxy,
xfer->remote_address,
xfer->remote_address_length);
if (xfer->sock < 0)
return 0;
flags = fcntl (xfer->sock, F_GETFL);
if (flags == -1)
flags = 0;
if (fcntl (xfer->sock, F_SETFL, flags | O_NONBLOCK) == -1)
{
close (xfer->sock);
xfer->sock = -1;
return 0;
weechat_network_connect_to (xfer->proxy, xfer->sock,
xfer->remote_address, xfer->port);
}
xfer->hook_fd = weechat_hook_fd (xfer->sock,
1, 0, 0,
+202 -149
View File
@@ -31,6 +31,7 @@
#include <netinet/in.h>
#include <netdb.h>
#include <gcrypt.h>
#include <arpa/inet.h>
#include "../weechat-plugin.h"
#include "xfer.h"
@@ -300,16 +301,13 @@ xfer_close (struct t_xfer *xfer, enum t_xfer_status status)
if (XFER_IS_FILE(xfer->type))
{
weechat_printf (NULL,
_("%s%s: file %s %s %s (%ld.%ld.%ld.%ld): %s"),
_("%s%s: file %s %s %s (%s): %s"),
(xfer->status == XFER_STATUS_DONE) ? "" : weechat_prefix ("error"),
XFER_PLUGIN_NAME,
xfer->filename,
(xfer->type == XFER_TYPE_FILE_SEND) ? _("sent to") : _("received from"),
xfer->remote_nick,
xfer->remote_address >> 24,
(xfer->remote_address >> 16) & 0xff,
(xfer->remote_address >> 8) & 0xff,
xfer->remote_address & 0xff,
xfer->remote_address_str,
(xfer->status == XFER_STATUS_DONE) ? _("OK") : _("FAILED"));
xfer_network_child_kill (xfer);
}
@@ -320,14 +318,11 @@ xfer_close (struct t_xfer *xfer, enum t_xfer_status status)
{
weechat_printf (xfer->buffer,
_("%s%s: chat closed with %s "
"(%ld.%ld.%ld.%ld)"),
"(%s)"),
weechat_prefix ("network"),
XFER_PLUGIN_NAME,
xfer->remote_nick,
xfer->remote_address >> 24,
(xfer->remote_address >> 16) & 0xff,
(xfer->remote_address >> 8) & 0xff,
xfer->remote_address & 0xff);
xfer->remote_address_str);
}
}
@@ -457,8 +452,12 @@ xfer_alloc ()
/* default values */
new_xfer->filename = NULL;
new_xfer->size = 0;
new_xfer->local_address = 0;
new_xfer->remote_address = 0;
new_xfer->local_address = NULL;
new_xfer->local_address_length = 0;
new_xfer->local_address_str = NULL;
new_xfer->remote_address = NULL;
new_xfer->remote_address_length = 0;
new_xfer->remote_address_str = NULL;
new_xfer->port = 0;
new_xfer->remote_nick = NULL;
new_xfer->local_nick = NULL;
@@ -616,11 +615,14 @@ 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, unsigned long address,
int port, int sock, const char *local_filename)
unsigned long long size, const char *proxy, struct sockaddr *address,
socklen_t address_length, int port, int sock,
const char *local_filename)
{
struct t_xfer *new_xfer;
const char *ptr_color, *ptr_crc32;
char str_address[NI_MAXHOST];
int rc;
new_xfer = xfer_alloc ();
if (!new_xfer)
@@ -653,17 +655,36 @@ xfer_new (const char *plugin_name, const char *plugin_id,
new_xfer->filename = strdup (_("xfer chat"));
new_xfer->size = size;
new_xfer->proxy = (proxy) ? strdup (proxy) : NULL;
new_xfer->port = port;
rc = getnameinfo ((struct sockaddr *)address, 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), "?");
}
new_xfer->local_address = calloc (1, sizeof (struct sockaddr_storage));
new_xfer->local_address_length = sizeof (struct sockaddr_storage);
new_xfer->remote_address = calloc (1, sizeof (struct sockaddr_storage));
new_xfer->remote_address_length = sizeof (struct sockaddr_storage);
if (XFER_IS_RECV(type))
{
new_xfer->local_address = 0;
new_xfer->remote_address = address;
new_xfer->local_address_str = strdup ("");
new_xfer->remote_address_str = strdup (str_address);
memcpy (new_xfer->remote_address, address, address_length);
}
else
{
new_xfer->local_address = address;
new_xfer->remote_address = 0;
new_xfer->local_address_str = strdup (str_address);
memcpy (new_xfer->local_address, address, address_length);
new_xfer->remote_address_str = strdup ("");
}
new_xfer->port = port;
new_xfer->status = XFER_STATUS_WAITING;
new_xfer->sock = sock;
@@ -708,14 +729,11 @@ xfer_new (const char *plugin_name, const char *plugin_id,
case XFER_TYPE_FILE_RECV:
weechat_printf (NULL,
_("%s: incoming file from %s "
"(%ld.%ld.%ld.%ld, %s.%s), name: %s, %llu bytes "
"(%s, %s.%s), name: %s, %llu bytes "
"(protocol: %s)"),
XFER_PLUGIN_NAME,
remote_nick,
address >> 24,
(address >> 16) & 0xff,
(address >> 8) & 0xff,
address & 0xff,
str_address,
plugin_name,
plugin_id,
filename,
@@ -740,13 +758,10 @@ xfer_new (const char *plugin_name, const char *plugin_id,
case XFER_TYPE_CHAT_RECV:
weechat_printf (NULL,
_("%s: incoming chat request from %s "
"(%ld.%ld.%ld.%ld, %s.%s)"),
"(%s, %s.%s)"),
XFER_PLUGIN_NAME,
remote_nick,
address >> 24,
(address >> 16) & 0xff,
(address >> 8) & 0xff,
address & 0xff,
str_address,
plugin_name,
plugin_id);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
@@ -814,6 +829,25 @@ xfer_new (const char *plugin_name, const char *plugin_id,
return new_xfer;
}
/*
* Sets the remote address field.
*/
void
xfer_set_remote_address (struct t_xfer *xfer, struct sockaddr *address,
socklen_t length, char *address_str)
{
if (xfer->remote_address)
free (xfer->remote_address);
xfer->remote_address = calloc (1, length);
xfer->remote_address_length = length;
memcpy (xfer->remote_address, address, length);
if (xfer->remote_address_str)
free (xfer->remote_address_str);
xfer->remote_address_str = strdup ((address_str) ? address_str : "");
}
/*
* Frees xfer struct and removes it from list.
*/
@@ -850,6 +884,14 @@ xfer_free (struct t_xfer *xfer)
free (xfer->charset_modifier);
if (xfer->filename)
free (xfer->filename);
if (xfer->local_address)
free (xfer->local_address);
if (xfer->local_address_str)
free (xfer->local_address_str);
if (xfer->remote_address)
free (xfer->remote_address);
if (xfer->remote_address_str)
free (xfer->remote_address_str);
if (xfer->remote_nick_color)
free (xfer->remote_nick_color);
if (xfer->unterminated_message)
@@ -884,15 +926,13 @@ xfer_add_cb (void *data, const char *signal, const char *type_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;
int type, protocol, args, port_start, port_end, sock, port;
const char *weechat_dir;
char *dir1, *dir2, *filename2, *short_filename, *pos;
const char *weechat_dir, *str_address, *str_port;
int type, protocol, args, port_start, port_end, sock, port, rc, own_ip_used;
char *dir1, *dir2, *filename2, *short_filename, *pos, str_port_temp[16];
struct stat st;
struct hostent *host;
struct sockaddr_in addr;
struct addrinfo *ainfo, hints;
struct sockaddr_storage addr;
socklen_t length;
struct in_addr tmpaddr;
unsigned long local_addr;
unsigned long long file_size;
struct t_xfer *ptr_xfer;
@@ -921,6 +961,7 @@ xfer_add_cb (void *data, const char *signal, const char *type_data,
filename2 = NULL;
short_filename = NULL;
file_size = 0;
sock = -1;
port = 0;
@@ -974,10 +1015,6 @@ xfer_add_cb (void *data, const char *signal, const char *type_data,
}
}
filename2 = NULL;
file_size = 0;
port = 0;
if (type == XFER_TYPE_FILE_RECV)
{
filename2 = strdup (filename);
@@ -1029,10 +1066,8 @@ xfer_add_cb (void *data, const char *signal, const char *type_data,
if (filename2[strlen (filename2) - 1] != DIR_SEPARATOR_CHAR)
strcat (filename2, DIR_SEPARATOR);
strcat (filename2, filename);
if (dir1)
free (dir1);
if (dir2)
free (dir2);
free (dir1);
free (dir2);
}
#endif
/* check if file exists */
@@ -1042,66 +1077,75 @@ xfer_add_cb (void *data, const char *signal, const char *type_data,
_("%s%s: cannot access file \"%s\""),
weechat_prefix ("error"), XFER_PLUGIN_NAME,
filename2);
if (filename2)
free (filename2);
goto error;
}
file_size = st.st_size;
}
port = weechat_infolist_integer (infolist, "port");
/* set address */
memset (&hints, 0, sizeof (struct addrinfo));
hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
hints.ai_family = AF_UNSPEC; /* allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = 0;
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;
own_ip_used = 0;
if (XFER_IS_RECV(type))
{
sscanf (weechat_infolist_string (infolist, "remote_address"), "%lu", &local_addr);
port = weechat_infolist_integer (infolist, "port");
str_address = weechat_infolist_string (infolist, "remote_address");
snprintf (str_port_temp, sizeof (str_port_temp), "%d", port);
str_port = str_port_temp;
}
else
{
/* get local IP address */
sscanf (weechat_infolist_string (infolist, "local_address"), "%lu", &local_addr);
memset (&addr, 0, sizeof (struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl (local_addr);
/* look up the IP address from network_own_ip, if set */
if (weechat_config_string(xfer_config_network_own_ip)
&& weechat_config_string(xfer_config_network_own_ip)[0])
str_port = NULL;
if (weechat_config_string (xfer_config_network_own_ip)
&& weechat_config_string (xfer_config_network_own_ip)[0])
{
host = gethostbyname (weechat_config_string (xfer_config_network_own_ip));
if (host)
{
memcpy (&tmpaddr, host->h_addr_list[0], sizeof(struct in_addr));
local_addr = ntohl (tmpaddr.s_addr);
sock = weechat_infolist_integer (infolist, "socket");
if (sock > 0)
{
memset (&addr, 0, sizeof (struct sockaddr_in));
length = sizeof (addr);
getsockname (sock, (struct sockaddr *) &addr, &length);
addr.sin_family = AF_INET;
}
}
else
{
weechat_printf (NULL,
_("%s%s: could not find address for \"%s\", "
"falling back to local IP"),
weechat_prefix ("error"), XFER_PLUGIN_NAME,
weechat_config_string (xfer_config_network_own_ip));
}
str_address = weechat_config_string (xfer_config_network_own_ip);
hints.ai_flags = AI_NUMERICSERV;
own_ip_used = 1;
}
else
str_address = weechat_infolist_string (infolist, "local_address");
}
rc = getaddrinfo (str_address, str_port, &hints, &ainfo);
if ((rc == 0) && ainfo && ainfo->ai_addr)
{
memset (&addr, 0, sizeof (addr));
memcpy (&addr, ainfo->ai_addr, ainfo->ai_addrlen);
length = ainfo->ai_addrlen;
freeaddrinfo (ainfo);
}
else
{
weechat_printf (NULL,
(own_ip_used) ?
_("%s%s: invalid address \"%s\" (option "
"xfer.network.own_ip): error %d %s") :
_("%s%s: unable to find address for \"%s\": "
"error %d %s"),
weechat_prefix ("error"), XFER_PLUGIN_NAME,
str_address, rc, gai_strerror (rc));
goto error;
}
if (XFER_IS_SEND(type))
{
/* open socket for xfer */
sock = socket (AF_INET, SOCK_STREAM, 0);
sock = socket (addr.ss_family, SOCK_STREAM, 0);
if (sock < 0)
{
weechat_printf (NULL,
_("%s%s: cannot create socket for xfer: error %d %s"),
weechat_prefix ("error"), XFER_PLUGIN_NAME,
errno, strerror (errno));
if (filename2)
free (filename2);
goto error;
}
@@ -1126,8 +1170,11 @@ xfer_add_cb (void *data, const char *signal, const char *type_data,
if (!xfer_port_in_use (port))
{
/* attempt to bind to the free port */
addr.sin_port = htons (port);
if (bind (sock, (struct sockaddr *) &addr, sizeof (addr)) == 0)
if (addr.ss_family == AF_INET)
((struct sockaddr_in *)&addr)->sin_port = htons (port);
else
((struct sockaddr_in6 *)&addr)->sin6_port = htons (port);
if (bind (sock, (struct sockaddr *)&addr, length) == 0)
break;
}
port++;
@@ -1141,12 +1188,13 @@ xfer_add_cb (void *data, const char *signal, const char *type_data,
if (port == 0)
{
/* find port automatically */
addr.sin_port = 0;
if (bind (sock, (struct sockaddr *) &addr, sizeof (addr)) == 0)
if (bind (sock, (struct sockaddr *)&addr, length) == 0)
{
length = sizeof (addr);
getsockname (sock, (struct sockaddr *) &addr, &length);
port = ntohs (addr.sin_port);
getsockname (sock, (struct sockaddr *)&addr, &length);
if (addr.ss_family == AF_INET)
port = ntohs (((struct sockaddr_in *)&addr)->sin_port);
else
port = ntohs (((struct sockaddr_in6 *)&addr)->sin6_port);
}
else
port = -1;
@@ -1159,8 +1207,6 @@ xfer_add_cb (void *data, const char *signal, const char *type_data,
_("%s%s: cannot find available port for xfer"),
weechat_prefix ("error"), XFER_PLUGIN_NAME);
close (sock);
if (filename2)
free (filename2);
goto error;
}
}
@@ -1198,14 +1244,20 @@ xfer_add_cb (void *data, const char *signal, const char *type_data,
/* add xfer entry and listen to socket if type is file or chat "send" */
if (XFER_IS_FILE(type))
{
ptr_xfer = xfer_new (plugin_name, plugin_id, type, protocol,
remote_nick, local_nick, charset_modifier,
short_filename, file_size, proxy, local_addr,
port, sock, filename2);
short_filename, file_size, proxy,
(struct sockaddr *)&addr, length, port, sock,
filename2);
}
else
{
ptr_xfer = xfer_new (plugin_name, plugin_id, type, protocol,
remote_nick, local_nick, charset_modifier, NULL,
0, proxy, local_addr, port, sock, NULL);
0, proxy, (struct sockaddr *)&addr, length,
port, sock, NULL);
}
if (!ptr_xfer)
{
@@ -1213,10 +1265,6 @@ xfer_add_cb (void *data, const char *signal, const char *type_data,
_("%s%s: error creating xfer"),
weechat_prefix ("error"), XFER_PLUGIN_NAME);
close (sock);
if (short_filename)
free (short_filename);
if (filename2)
free (filename2);
goto error;
}
@@ -1224,15 +1272,18 @@ xfer_add_cb (void *data, const char *signal, const char *type_data,
if (XFER_IS_SEND(ptr_xfer->type) && !XFER_HAS_ENDED(ptr_xfer->status))
xfer_send_signal (ptr_xfer, "xfer_send_ready");
if (short_filename)
free (short_filename);
if (filename2)
free (filename2);
if (short_filename)
free (short_filename);
weechat_infolist_reset_item_cursor (infolist);
return WEECHAT_RC_OK;
error:
if (filename2)
free (filename2);
if (short_filename)
free (short_filename);
weechat_infolist_reset_item_cursor (infolist);
return WEECHAT_RC_ERROR;
}
@@ -1458,11 +1509,9 @@ xfer_add_to_infolist (struct t_infolist *infolist, struct t_xfer *xfer)
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "proxy", xfer->proxy))
return 0;
snprintf (value, sizeof (value), "%lu", xfer->local_address);
if (!weechat_infolist_new_var_string (ptr_item, "local_address", value))
if (!weechat_infolist_new_var_string (ptr_item, "local_address", xfer->local_address_str))
return 0;
snprintf (value, sizeof (value), "%lu", xfer->remote_address);
if (!weechat_infolist_new_var_string (ptr_item, "remote_address", value))
if (!weechat_infolist_new_var_string (ptr_item, "remote_address", xfer->remote_address_str))
return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "port", xfer->port))
return 0;
@@ -1548,57 +1597,61 @@ xfer_print_log ()
{
weechat_log_printf ("");
weechat_log_printf ("[xfer (addr:0x%lx)]", ptr_xfer);
weechat_log_printf (" plugin_name . . . . : '%s'", ptr_xfer->plugin_name);
weechat_log_printf (" plugin_id . . . . . : '%s'", ptr_xfer->plugin_id);
weechat_log_printf (" type. . . . . . . . : %d (%s)",
weechat_log_printf (" plugin_name . . . . . . : '%s'", ptr_xfer->plugin_name);
weechat_log_printf (" plugin_id . . . . . . . : '%s'", ptr_xfer->plugin_id);
weechat_log_printf (" type. . . . . . . . . . : %d (%s)",
ptr_xfer->type,
xfer_type_string[ptr_xfer->type]);
weechat_log_printf (" protocol. . . . . . : %d (%s)",
weechat_log_printf (" protocol. . . . . . . . : %d (%s)",
ptr_xfer->protocol,
xfer_protocol_string[ptr_xfer->protocol]);
weechat_log_printf (" remote_nick . . . . : '%s'", ptr_xfer->remote_nick);
weechat_log_printf (" local_nick. . . . . : '%s'", ptr_xfer->local_nick);
weechat_log_printf (" charset_modifier. . : '%s'", ptr_xfer->charset_modifier);
weechat_log_printf (" filename. . . . . . : '%s'", ptr_xfer->filename);
weechat_log_printf (" size. . . . . . . . : %llu", ptr_xfer->size);
weechat_log_printf (" proxy . . . . . . . : '%s'", ptr_xfer->proxy);
weechat_log_printf (" local_address . . . : %lu", ptr_xfer->local_address);
weechat_log_printf (" remote_address. . . : %lu", ptr_xfer->remote_address);
weechat_log_printf (" port. . . . . . . . : %d", ptr_xfer->port);
weechat_log_printf (" remote_nick . . . . . . : '%s'", ptr_xfer->remote_nick);
weechat_log_printf (" local_nick. . . . . . . : '%s'", ptr_xfer->local_nick);
weechat_log_printf (" charset_modifier. . . . : '%s'", ptr_xfer->charset_modifier);
weechat_log_printf (" filename. . . . . . . . : '%s'", ptr_xfer->filename);
weechat_log_printf (" size. . . . . . . . . . : %llu", ptr_xfer->size);
weechat_log_printf (" proxy . . . . . . . . . : '%s'", ptr_xfer->proxy);
weechat_log_printf (" local_address . . . . . : 0x%lx", ptr_xfer->local_address);
weechat_log_printf (" local_address_length. . : %d", ptr_xfer->local_address_length);
weechat_log_printf (" local_address_str . . . : '%s'" , ptr_xfer->local_address_str);
weechat_log_printf (" remote_address. . . . . : 0x%lx", ptr_xfer->remote_address);
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 (" status. . . . . . . : %d (%s)",
weechat_log_printf (" status. . . . . . . . . : %d (%s)",
ptr_xfer->status,
xfer_status_string[ptr_xfer->status]);
weechat_log_printf (" buffer. . . . . . . : 0x%lx", ptr_xfer->buffer);
weechat_log_printf (" remote_nick_color . : '%s'", ptr_xfer->remote_nick_color);
weechat_log_printf (" fast_send . . . . . : %d", ptr_xfer->fast_send);
weechat_log_printf (" blocksize . . . . . : %d", ptr_xfer->blocksize);
weechat_log_printf (" start_time. . . . . : %ld", ptr_xfer->start_time);
weechat_log_printf (" start_transfer. . . : %ld", ptr_xfer->start_transfer);
weechat_log_printf (" sock. . . . . . . . : %d", ptr_xfer->sock);
weechat_log_printf (" child_pid . . . . . : %d", ptr_xfer->child_pid);
weechat_log_printf (" child_read. . . . . : %d", ptr_xfer->child_read);
weechat_log_printf (" child_write . . . . : %d", ptr_xfer->child_write);
weechat_log_printf (" hook_fd . . . . . . : 0x%lx", ptr_xfer->hook_fd);
weechat_log_printf (" hook_timer. . . . . : 0x%lx", ptr_xfer->hook_timer);
weechat_log_printf (" unterminated_message: '%s'", ptr_xfer->unterminated_message);
weechat_log_printf (" file. . . . . . . . : %d", ptr_xfer->file);
weechat_log_printf (" local_filename. . . : '%s'", ptr_xfer->local_filename);
weechat_log_printf (" filename_suffix . . : %d", ptr_xfer->filename_suffix);
weechat_log_printf (" pos . . . . . . . . : %llu", ptr_xfer->pos);
weechat_log_printf (" ack . . . . . . . . : %llu", ptr_xfer->ack);
weechat_log_printf (" start_resume. . . . : %llu", ptr_xfer->start_resume);
weechat_log_printf (" last_check_time . . : %ld", ptr_xfer->last_check_time);
weechat_log_printf (" last_check_pos. . . : %llu", ptr_xfer->last_check_pos);
weechat_log_printf (" last_activity . . . : %ld", ptr_xfer->last_activity);
weechat_log_printf (" bytes_per_sec . . . : %llu", ptr_xfer->bytes_per_sec);
weechat_log_printf (" eta . . . . . . . . : %llu", ptr_xfer->eta);
weechat_log_printf (" hash_target . . . . : '%s'", ptr_xfer->hash_target);
weechat_log_printf (" hash_status . . . . : %d (%s)",
weechat_log_printf (" buffer. . . . . . . . . : 0x%lx", ptr_xfer->buffer);
weechat_log_printf (" remote_nick_color . . . : '%s'", ptr_xfer->remote_nick_color);
weechat_log_printf (" fast_send . . . . . . . : %d", ptr_xfer->fast_send);
weechat_log_printf (" blocksize . . . . . . . : %d", ptr_xfer->blocksize);
weechat_log_printf (" start_time. . . . . . . : %ld", ptr_xfer->start_time);
weechat_log_printf (" start_transfer. . . . . : %ld", ptr_xfer->start_transfer);
weechat_log_printf (" sock. . . . . . . . . . : %d", ptr_xfer->sock);
weechat_log_printf (" child_pid . . . . . . . : %d", ptr_xfer->child_pid);
weechat_log_printf (" child_read. . . . . . . : %d", ptr_xfer->child_read);
weechat_log_printf (" child_write . . . . . . : %d", ptr_xfer->child_write);
weechat_log_printf (" hook_fd . . . . . . . . : 0x%lx", ptr_xfer->hook_fd);
weechat_log_printf (" hook_timer. . . . . . . : 0x%lx", ptr_xfer->hook_timer);
weechat_log_printf (" unterminated_message. . : '%s'", ptr_xfer->unterminated_message);
weechat_log_printf (" file. . . . . . . . . . : %d", ptr_xfer->file);
weechat_log_printf (" local_filename. . . . . : '%s'", ptr_xfer->local_filename);
weechat_log_printf (" filename_suffix . . . . : %d", ptr_xfer->filename_suffix);
weechat_log_printf (" pos . . . . . . . . . . : %llu", ptr_xfer->pos);
weechat_log_printf (" ack . . . . . . . . . . : %llu", ptr_xfer->ack);
weechat_log_printf (" start_resume. . . . . . : %llu", ptr_xfer->start_resume);
weechat_log_printf (" last_check_time . . . . : %ld", ptr_xfer->last_check_time);
weechat_log_printf (" last_check_pos. . . . . : %llu", ptr_xfer->last_check_pos);
weechat_log_printf (" last_activity . . . . . : %ld", ptr_xfer->last_activity);
weechat_log_printf (" bytes_per_sec . . . . . : %llu", ptr_xfer->bytes_per_sec);
weechat_log_printf (" eta . . . . . . . . . . : %llu", ptr_xfer->eta);
weechat_log_printf (" hash_target . . . . . . : '%s'", ptr_xfer->hash_target);
weechat_log_printf (" hash_status . . . . . . : %d (%s)",
ptr_xfer->hash_status,
xfer_hash_status_string[ptr_xfer->hash_status]);
weechat_log_printf (" prev_xfer . . . . . : 0x%lx", ptr_xfer->prev_xfer);
weechat_log_printf (" next_xfer . . . . . : 0x%lx", ptr_xfer->next_xfer);
weechat_log_printf (" prev_xfer . . . . . . . : 0x%lx", ptr_xfer->prev_xfer);
weechat_log_printf (" next_xfer . . . . . . . : 0x%lx", ptr_xfer->next_xfer);
}
}
+9 -2
View File
@@ -140,8 +140,12 @@ struct t_xfer
char *filename; /* filename */
unsigned long long size; /* file size */
char *proxy; /* proxy to use (optional) */
unsigned long local_address; /* local IP address */
unsigned long remote_address; /* remote IP address */
struct sockaddr *local_address; /* local IP address */
socklen_t local_address_length; /* local sockaddr length */
char *local_address_str; /* local IP address as string */
struct sockaddr *remote_address; /* remote IP address */
socklen_t remote_address_length; /* remote sockaddr length */
char *remote_address_str; /* remote IP address as string */
int port; /* remote port */
/* internal data */
@@ -191,6 +195,9 @@ extern struct t_xfer *xfer_search_by_number (int number);
extern struct t_xfer *xfer_search_by_buffer (struct t_gui_buffer *buffer);
extern void xfer_close (struct t_xfer *xfer, enum t_xfer_status status);
extern void xfer_send_signal (struct t_xfer *xfer, const char *signal);
extern void xfer_set_remote_address (struct t_xfer *xfer,
struct sockaddr *address, socklen_t length,
char *address_str);
extern void xfer_free (struct t_xfer *xfer);
extern int xfer_add_to_infolist (struct t_infolist *infolist,
struct t_xfer *xfer);