diff --git a/configure.ac b/configure.ac index 9bc2a6b4..8bc029c4 100644 --- a/configure.ac +++ b/configure.ac @@ -38,7 +38,6 @@ AH_VERBATIM([OLD_PERL],[#undef OLD_PERL]) AH_VERBATIM([PREFIX],[#undef PREFIX]) AH_VERBATIM([HEXCHATLIBDIR],[#undef HEXCHATLIBDIR]) AH_VERBATIM([HEXCHATSHAREDIR],[#undef HEXCHATSHAREDIR]) -AH_VERBATIM([USE_LIBPROXY],[#undef USE_LIBPROXY]) AH_VERBATIM([HAVE_ISO_CODES],[#undef HAVE_ISO_CODES]) AH_VERBATIM([HAVE_GTK_MAC],[#undef HAVE_GTK_MAC]) AH_VERBATIM([USE_LIBNOTIFY],[#undef USE_LIBNOTIFY]) @@ -139,10 +138,6 @@ AC_ARG_ENABLE(libcanberra, [AS_HELP_STRING([--disable-libcanberra],[disable libcanberra support])], libcanberra=$enableval, libcanberra=yes) -AC_ARG_ENABLE(libproxy, - [AS_HELP_STRING([--disable-libproxy],[disable libproxy support (default: auto)])], - libproxy=$enableval, libproxy=auto) - AC_ARG_ENABLE(isocodes, [AS_HELP_STRING([--disable-isocodes],[disable iso-codes with spell-check])], isocodes=$enableval, isocodes=yes) @@ -400,26 +395,6 @@ if test "$retry" = "yes"; then LIBS=$SAVED_LIBS fi -dnl ********************************************************************* -dnl ** LIBPROXY ********************************************************* -dnl ********************************************************************* - -if test "x$libproxy" = "xyes" -o "x$libproxy" = "xauto" ; then - PKG_CHECK_MODULES([LIBPROXY], [libproxy-1.0], [ - COMMON_LIBS="$COMMON_LIBS $LIBPROXY_LIBS" - COMMON_CFLAGS="$COMMON_CFLAGS $LIBPROXY_CFLAGS" - AC_DEFINE(USE_LIBPROXY) - libproxy=yes - ], [ - if test "x$libproxy" = "xyes" ; then - AC_MSG_ERROR(Cannot find libproxy!) - fi - libproxy=no - ]) -else - libproxy=no -fi - dnl ********************************************************************* dnl ** PLUGIN *********************************************************** dnl ********************************************************************* @@ -817,7 +792,6 @@ echo D-Bus support ......... : $dbus echo libnotify support ..... : $libnotify echo libcanberra support ... : $libcanberra echo Plugin interface ...... : $plugin -echo libproxy support ...... : $libproxy echo echo Perl .................. : $perl echo Python ................ : $python diff --git a/src/common/Makefile.am b/src/common/Makefile.am index ea941671..286a0ff2 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -63,7 +63,6 @@ libhexchatcommon_a_SOURCES = cfgfiles.c chanopt.c ctcp.c dcc.c hexchat.c \ history.c ignore.c inbound.c marshal.c modes.c network.c notify.c \ outbound.c plugin.c plugin-identd.c plugin-timer.c proto-irc.c server.c servlist.c \ $(ssl_c) text.c tree.c url.c userlist.c util.c -libhexchatcommon_a_CFLAGS = $(LIBPROXY_CFLAGS) textenums.h: textevents.h diff --git a/src/common/dcc.c b/src/common/dcc.c index 97cd5f14..b869566f 100644 --- a/src/common/dcc.c +++ b/src/common/dcc.c @@ -83,6 +83,15 @@ static gboolean dcc_send_data (GIOChannel *, GIOCondition, struct DCC *); static gboolean dcc_read (GIOChannel *, GIOCondition, struct DCC *); static gboolean dcc_read_ack (GIOChannel *source, GIOCondition condition, struct DCC *dcc); +char * +net_ip (guint32 addr) +{ + struct in_addr ia; + + ia.s_addr = htonl (addr); + return inet_ntoa (ia); +} + static int new_id() { static int id = 0; @@ -1668,6 +1677,7 @@ dcc_listen_init (struct DCC *dcc, session *sess) if (dcc->sok == -1) return FALSE; +#if 0 memset (&SAddr, 0, sizeof (struct sockaddr_in)); len = sizeof (SAddr); @@ -1704,6 +1714,7 @@ dcc_listen_init (struct DCC *dcc, session *sess) setsockopt (dcc->sok, SOL_SOCKET, SO_REUSEADDR, (char *) &len, sizeof (len)); } else +#endif { /* try random port */ SAddr.sin_port = 0; diff --git a/src/common/dcc.h b/src/common/dcc.h index e7115b32..2e624189 100644 --- a/src/common/dcc.h +++ b/src/common/dcc.h @@ -123,5 +123,6 @@ void handle_dcc (session *sess, char *nick, char *word[], char *word_eol[], void dcc_show_list (session *sess); guint32 dcc_get_my_address (void); void dcc_get_with_destfile (struct DCC *dcc, char *utf8file); +char *net_ip (guint32 addr); #endif diff --git a/src/common/hexchat.c b/src/common/hexchat.c index 7d8e462f..94dfe20c 100644 --- a/src/common/hexchat.c +++ b/src/common/hexchat.c @@ -56,10 +56,6 @@ #include /* for g_type_init() */ #endif -#ifdef USE_LIBPROXY -#include -#endif - GSList *popup_list = 0; GSList *button_list = 0; GSList *dlgbutton_list = 0; @@ -110,10 +106,6 @@ struct session *current_tab; struct session *current_sess = 0; struct hexchatprefs prefs; -#ifdef USE_LIBPROXY -pxProxyFactory *libproxy_factory; -#endif - /* * Update the priority queue of the "interesting sessions" * (sess_list_by_lastact). @@ -1048,10 +1040,6 @@ main (int argc, char *argv[]) hexchat_remote (); #endif -#ifdef USE_LIBPROXY - libproxy_factory = px_proxy_factory_new(); -#endif - fe_init (); /* This is done here because cfgfiles.c is too early in @@ -1079,10 +1067,6 @@ main (int argc, char *argv[]) fe_main (); -#ifdef USE_LIBPROXY - px_proxy_factory_free(libproxy_factory); -#endif - #ifdef WIN32 WSACleanup (); #endif diff --git a/src/common/hexchat.h b/src/common/hexchat.h index 94bd3afe..6d47db58 100644 --- a/src/common/hexchat.h +++ b/src/common/hexchat.h @@ -471,14 +471,10 @@ typedef struct server int (*p_raw)(struct server *, char *raw); int (*p_cmp)(const char *s1, const char *s2); - int port; - int sok; /* is equal to sok4 or sok6 (the one we are using) */ - int sok4; /* tcp4 socket */ - int sok6; /* tcp6 socket */ - int proxy_type; - int proxy_sok; /* Additional information for MS Proxy beast */ - int proxy_sok4; - int proxy_sok6; + guint16 port; + GSocket *sok; /* is equal to sok4 or sok6 (the one we are using) */ + GSocket *sok4; /* tcp4 socket */ + GSocket *sok6; /* tcp6 socket */ int id; /* unique ID number (for plugin API) */ #ifdef USE_OPENSSL SSL_CTX *ctx; diff --git a/src/common/network.c b/src/common/network.c index 3a5e9b14..c02244f7 100644 --- a/src/common/network.c +++ b/src/common/network.c @@ -20,53 +20,18 @@ #include "config.h" -#include #include -#include #include +#include -#ifndef WIN32 -#include -#endif - -#define WANTSOCKET -#define WANTARPA -#define WANTDNS -#include "inet.h" - -#define NETWORK_PRIVATE #include "network.h" -#define RAND_INT(n) ((int)(rand() / (RAND_MAX + 1.0) * (n))) - - -/* ================== COMMON ================= */ - -static void -net_set_socket_options (int sok) -{ - socklen_t sw; - - sw = 1; - setsockopt (sok, SOL_SOCKET, SO_REUSEADDR, (char *) &sw, sizeof (sw)); - sw = 1; - setsockopt (sok, SOL_SOCKET, SO_KEEPALIVE, (char *) &sw, sizeof (sw)); -} - -char * -net_ip (guint32 addr) -{ - struct in_addr ia; - - ia.s_addr = htonl (addr); - return inet_ntoa (ia); -} - void -net_store_destroy (netstore * ns) +net_store_destroy (netstore *ns) { - if (ns->ip6_hostent) - freeaddrinfo (ns->ip6_hostent); + g_return_if_fail (ns != NULL); + + g_resolver_free_addresses (ns->addrs); g_free (ns); } @@ -76,118 +41,208 @@ net_store_new (void) return g_new0 (netstore, 1); } -/* =================== IPV6 ================== */ - char * -net_resolve (netstore * ns, char *hostname, int port, char **real_host) +net_resolve (netstore *ns, char *hostname, char **real_host, GError **error) { - struct addrinfo hints; - char ipstring[MAX_HOSTNAME]; - char portstring[MAX_HOSTNAME]; - int ret; + GResolver *res; + GList *addrs; + GInetAddress *addr; + char *ipstring; -/* if (ns->ip6_hostent) - freeaddrinfo (ns->ip6_hostent);*/ + res = g_resolver_get_default (); - sprintf (portstring, "%d", port); - - memset (&hints, 0, sizeof (struct addrinfo)); - hints.ai_family = PF_UNSPEC; /* support ipv6 and ipv4 */ - hints.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; - hints.ai_socktype = SOCK_STREAM; - - if (port == 0) - ret = getaddrinfo (hostname, NULL, &hints, &ns->ip6_hostent); - else - ret = getaddrinfo (hostname, portstring, &hints, &ns->ip6_hostent); - if (ret != 0) + // todo: lookup by irc service? + addrs = g_resolver_lookup_by_name (res, hostname, NULL, error); + if (!addrs) + { + g_object_unref (res); return NULL; + } -#ifdef LOOKUPD /* See note about lookupd above the IPv4 version of net_resolve. */ - struct addrinfo *tmp; - int count = 0; - - for (tmp = ns->ip6_hostent; tmp; tmp = tmp->ai_next) - count ++; - - count = RAND_INT(count); - - while (count--) ns->ip6_hostent = ns->ip6_hostent->ai_next; -#endif - - /* find the numeric IP number */ - ipstring[0] = 0; - getnameinfo (ns->ip6_hostent->ai_addr, ns->ip6_hostent->ai_addrlen, - ipstring, sizeof (ipstring), NULL, 0, NI_NUMERICHOST); + ns->addrs = addrs; + addr = G_INET_ADDRESS(addrs->data); + ipstring = g_inet_address_to_string (addr); if (real_host) { - if (ns->ip6_hostent->ai_canonname) - *real_host = g_strdup (ns->ip6_hostent->ai_canonname); - else + if (!(*real_host = g_resolver_lookup_by_address (res, addr, NULL, NULL))) *real_host = g_strdup (hostname); } - return g_strdup (ipstring); + g_object_unref (res); + + return ipstring; } /* the only thing making this interface unclean, this shitty sok4, sok6 business */ -int -net_connect (netstore * ns, int sok4, int sok6, int *sok_return) +GSocket * +net_connect (netstore *ns, guint16 port, GSocket *sok4, GSocket *sok6, GError **error) { - struct addrinfo *res, *res0; - int error = -1; + GSocket *sok; + GList *addrs; + gboolean success; - res0 = ns->ip6_hostent; - - for (res = res0; res; res = res->ai_next) + for (addrs = ns->addrs; addrs; addrs = g_list_next (addrs)) { -/* sok = socket (res->ai_family, res->ai_socktype, res->ai_protocol); - if (sok < 0) - continue;*/ - switch (res->ai_family) - { - case AF_INET: - error = connect (sok4, res->ai_addr, res->ai_addrlen); - *sok_return = sok4; - break; - case AF_INET6: - error = connect (sok6, res->ai_addr, res->ai_addrlen); - *sok_return = sok6; - break; - default: - error = 1; - } + GInetAddress *inet_addr = G_INET_ADDRESS(addrs->data); + GSocketAddress *sok_addr; - if (error == 0) - break; + g_clear_error (error); /* Last failed attempt set */ + + sok_addr = g_inet_socket_address_new (inet_addr, port); + if (g_socket_address_get_family (sok_addr) == G_SOCKET_FAMILY_IPV4) + sok = sok4; + else + sok = sok6; + success = g_socket_connect (sok, sok_addr, NULL, error); + g_object_unref (sok_addr); + + if (success) + return sok; + } + return NULL; +} + +gboolean +net_bind (netstore *ns, GSocket *sok4, GSocket *sok6, GError **error4, GError **error6) +{ + GInetAddress *inet_addr = G_INET_ADDRESS(ns->addrs->data); + GSocketAddress *sok_addr; + gboolean success; + + sok_addr = g_inet_socket_address_new (inet_addr, 0); + success = g_socket_bind (sok4, sok_addr, TRUE, error4); + success &= g_socket_bind (sok6, sok_addr, TRUE, error6); + g_object_unref (sok_addr); + + return success; +} + +void +net_sockets (GSocket **sok4, GSocket **sok6, GError **error4, GError **error6) +{ + *sok4 = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP, error4); + *sok6 = g_socket_new (G_SOCKET_FAMILY_IPV6, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP, error6); + + if (!*sok4 || !*sok6) + { + g_warning ("Creating sockets failed\n"); + return; } - return error; + g_socket_set_keepalive (*sok4, TRUE); + g_socket_set_keepalive (*sok6, TRUE); +} + +char * +net_resolve_proxy (const char *hostname, guint16 port, GError **error) +{ + GProxyResolver *res; + char *uri; + char **proxies; + char *proxy = NULL; + guint i; + + res = g_proxy_resolver_get_default (); + if (!res) + return NULL; + + // FIXME: ircs also + uri = g_strdup_printf ("irc://%s:%d", hostname, port); + proxies = g_proxy_resolver_lookup (res, uri, NULL, error); + g_free (uri); + if (g_strv_length (proxies) == 0) + return NULL; + + for (i = 0; i < g_strv_length (proxies); i++) + { + int type; + + net_parse_proxy_uri (proxies[i], NULL, NULL, &type); + + if (type != -1) + { + proxy = g_strdup (proxies[i]); + break; + } + } + g_strfreev (proxies); + + if (!proxy) /* FIXME: error code */ + *error = g_error_new_literal (0, 0, "No system proxy found that is supported"); + + return proxy; } void -net_bind (netstore * tobindto, int sok4, int sok6) +net_parse_proxy_uri (const char *proxy_uri, char **host, guint16 *port, int *type) { - bind (sok4, tobindto->ip6_hostent->ai_addr, - tobindto->ip6_hostent->ai_addrlen); - bind (sok6, tobindto->ip6_hostent->ai_addr, - tobindto->ip6_hostent->ai_addrlen); + if (type) + { + char *scheme = g_uri_parse_scheme (proxy_uri); + + if (!strcmp (scheme, "direct")) + *type = 0; + else if (!strcmp (scheme, "http")) + *type = 4; + else if (!strcmp (scheme, "socks5")) + *type = 3; + else if (!strcmp (scheme, "socks")) + *type = 2; + else + *type = -1; + + g_free (scheme); + } + + if (host) + { + char *c1, *c2; + + c1 = strchr (proxy_uri, ':') + 3; + if (c1) + { + c2 = strrchr (c1, ':'); + + if (c2) + *host = g_strndup (c1, c2 - c1); + else + *host = g_strdup (c1); + } + else + *host = NULL; + } + + if (port) + { + char *c; + guint64 p; + + c = strrchr (proxy_uri, ':'); + if (c) + { + p = g_ascii_strtoull (c + 1, NULL, 0); + if (p <= G_MAXUINT16) + *port = (guint16)p; + } + else + *port = 0; + } } -void -net_sockets (int *sok4, int *sok6) +guint16 +net_get_local_port (GSocket *sok) { - *sok4 = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); - *sok6 = socket (AF_INET6, SOCK_STREAM, IPPROTO_TCP); - net_set_socket_options (*sok4); - net_set_socket_options (*sok6); -} + GSocketAddress *addr; + guint16 port; -void -udp_sockets (int *sok4, int *sok6) -{ - *sok4 = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); - *sok6 = socket (AF_INET6, SOCK_DGRAM, IPPROTO_UDP); + addr = g_socket_get_local_address (sok, NULL); + if (!addr) + return 0; + + port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS(addr)); + g_object_unref (addr); + + return port; } diff --git a/src/common/network.h b/src/common/network.h index 8c1c0c79..8b5143fa 100644 --- a/src/common/network.h +++ b/src/common/network.h @@ -22,21 +22,18 @@ typedef struct netstore_ { -#ifdef NETWORK_PRIVATE - struct addrinfo *ip6_hostent; -#else - int _dummy; /* some compilers don't like empty structs */ -#endif + GList *addrs; } netstore; #define MAX_HOSTNAME 128 netstore *net_store_new (void); void net_store_destroy (netstore *ns); -int net_connect (netstore *ns, int sok4, int sok6, int *sok_return); -char *net_resolve (netstore *ns, char *hostname, int port, char **real_host); -void net_bind (netstore *tobindto, int sok4, int sok6); -char *net_ip (guint32 addr); -void net_sockets (int *sok4, int *sok6); - +GSocket *net_connect (netstore *ns, guint16 port, GSocket *sok4, GSocket *sok6, GError **error); +char *net_resolve (netstore *ns, char *hostname, char **real_host, GError **error); +char * net_resolve_proxy (const char *hostname, guint16 port, GError **error); +gboolean net_bind (netstore *ns, GSocket *sok4, GSocket *sok6, GError **error4, GError **error6); +void net_sockets (GSocket **sok4, GSocket **sok6, GError **error4, GError **error6); +void net_parse_proxy_uri (const char *proxy_uri, char **host, guint16 *port, int *type); +guint16 net_get_local_port (GSocket *sok); #endif diff --git a/src/common/outbound.c b/src/common/outbound.c index fab573e4..05d4edf4 100644 --- a/src/common/outbound.c +++ b/src/common/outbound.c @@ -907,7 +907,7 @@ cmd_debug (struct session *sess, char *tbuf, char *word[], char *word_eol[]) { v = (struct server *) list->data; sprintf (tbuf, "%p %-5d %s\n", - v, v->sok, v->servername); + v, g_socket_get_fd (v->sok), v->servername); PrintText (sess, tbuf); list = list->next; } @@ -3205,7 +3205,7 @@ cmd_send (struct session *sess, char *tbuf, char *word[], char *word_eol[]) if (!word[2][0]) return FALSE; - +#if 0 addr = dcc_get_my_address (); if (addr == 0) { @@ -3223,7 +3223,7 @@ cmd_send (struct session *sess, char *tbuf, char *word[], char *word_eol[]) g_snprintf (tbuf, 512, "DCC PSEND %s", word_eol[2]); else g_snprintf (tbuf, 512, "DCC SEND %s", word_eol[2]); - +#endif handle_command (sess, tbuf, FALSE); return TRUE; diff --git a/src/common/server.c b/src/common/server.c index d0698342..69c38d10 100644 --- a/src/common/server.c +++ b/src/common/server.c @@ -61,10 +61,6 @@ #include "ssl.h" #endif -#ifdef USE_LIBPROXY -#include -#endif - #define HEXCHAT_CONNECTION_ERROR g_quark_from_static_string("hexchat-connection-error") #ifdef USE_OPENSSL @@ -80,10 +76,6 @@ static void server_disconnect (session * sess, int sendquit, int err); static int server_cleanup (server * serv); static void server_connect (server *serv, char *hostname, int port, int no_login); -#ifdef USE_LIBPROXY -extern pxProxyFactory *libproxy_factory; -#endif - enum { RESOLVE_FAILED = 1, @@ -158,7 +150,7 @@ server_send_real (server *serv, char *buf, int len) url_check_line (buf); - return tcp_send_real (serv->ssl, serv->sok, serv->encoding, serv->using_irc, + return tcp_send_real (serv->ssl, g_socket_get_fd (serv->sok), serv->encoding, serv->using_irc, buf, len); } @@ -294,15 +286,15 @@ tcp_sendf (server *serv, const char *fmt, ...) static int close_socket_cb (gpointer sok) { - closesocket (GPOINTER_TO_INT (sok)); + g_object_unref (sok); return 0; } static void -close_socket (int sok) +close_socket (GSocket *sok) { /* close the socket in 5 seconds so the QUIT message is not lost */ - fe_timeout_add (5000, close_socket_cb, GINT_TO_POINTER (sok)); + fe_timeout_add (5000, close_socket_cb, sok); } /* handle 1 line of text received from the server */ @@ -411,7 +403,7 @@ server_inline (server *serv, char *line, gssize len) static gboolean server_read (GIOChannel *source, GIOCondition condition, server *serv) { - int sok = serv->sok; + int sok = g_socket_get_fd (serv->sok); int error, i, len; char lbuf[2050]; @@ -489,8 +481,8 @@ server_connected (server * serv) serv->ping_recv = time (0); serv->lag_sent = 0; serv->connected = TRUE; - set_nonblocking (serv->sok); - serv->iotag = fe_input_add (serv->sok, FIA_READ|FIA_EX, server_read, serv); + g_socket_set_blocking (serv->sok, FALSE); + serv->iotag = fe_input_add (g_socket_get_fd(serv->sok), G_IO_OUT|G_IO_ERR|G_IO_PRI, server_read, serv); if (!serv->no_login) { EMIT_SIGNAL (XP_TE_CONNECTED, serv->server_session, NULL, NULL, NULL, @@ -860,7 +852,7 @@ server_connect_success (server *serv) /* it'll be a memory leak, if connection isn't terminated by server_cleanup() */ - serv->ssl = _SSL_socket (serv->ctx, serv->sok); + serv->ssl = _SSL_socket (serv->ctx, g_socket_get_fd (serv->sok)); if ((err = _SSL_set_verify (serv->ctx, ssl_cb_verify, NULL))) { EMIT_SIGNAL (XP_TE_CONNFAIL, serv->server_session, err, NULL, @@ -870,7 +862,7 @@ server_connect_success (server *serv) } /* FIXME: it'll be needed by new servers */ /* send(serv->sok, "STLS\r\n", 6, 0); sleep(1); */ - set_nonblocking (serv->sok); + g_socket_set_blocking (serv->sok, FALSE); serv->ssl_do_connect_tag = fe_timeout_add (SSLDOCONNTMOUT, ssl_do_connect, serv); return; @@ -915,21 +907,16 @@ server_cleanup (server * serv) if (serv->connecting) { server_stopconnecting (serv); - closesocket (serv->sok4); - if (serv->proxy_sok4 != -1) - closesocket (serv->proxy_sok4); - if (serv->sok6 != -1) - closesocket (serv->sok6); - if (serv->proxy_sok6 != -1) - closesocket (serv->proxy_sok6); + if (serv->sok4) + g_object_unref (serv->sok4); + if (serv->sok6) + g_object_unref (serv->sok6); return 1; } if (serv->connected) { close_socket (serv->sok); - if (serv->proxy_sok) - close_socket (serv->proxy_sok); serv->connected = FALSE; serv->end_of_motd = FALSE; return 2; @@ -1265,8 +1252,9 @@ traverse_http (int sok, char *serverAddr, int port, GError **error) } static int -traverse_proxy (int proxy_type, int sok, char *ip, int port, GError **error) +traverse_proxy (int proxy_type, GSocket *sok_r, char *ip, int port, GError **error) { + int sok = g_socket_get_fd (sok_r); switch (proxy_type) { case 1: @@ -1337,40 +1325,22 @@ server_connect_finish (GObject *source, GAsyncResult *res, gpointer user_data) if (data->local_ip) prefs.local_ip = inet_addr (data->local_ip); - serv->sok = g_task_propagate_int (G_TASK(res), &error); + serv->sok = g_task_propagate_pointer (G_TASK(res), &error); if (!error) { if (serv->sok == serv->sok4) - closesocket (serv->sok6); + g_object_unref (serv->sok6); else - closesocket (serv->sok4); - if (serv->proxy_sok != -1) + g_object_unref (serv->sok4); { - if (serv->proxy_sok == serv->proxy_sok4) - closesocket (serv->proxy_sok6); + guint16 port = net_get_local_port (serv->sok); + g_snprintf (buf, sizeof (buf), "IDENTD %"G_GUINT16_FORMAT" ", port); + if (serv->network && ((ircnet *)serv->network)->user) + g_strlcat (buf, ((ircnet *)serv->network)->user, sizeof (buf)); else - closesocket (serv->proxy_sok4); - } - { - struct sockaddr addr; - int addr_len = sizeof (addr); - guint16 port; + g_strlcat (buf, prefs.hex_irc_user_name, sizeof (buf)); - if (!getsockname (serv->sok, &addr, &addr_len)) - { - if (addr.sa_family == AF_INET) - port = ntohs(((struct sockaddr_in *)&addr)->sin_port); - else - port = ntohs(((struct sockaddr_in6 *)&addr)->sin6_port); - - g_snprintf (buf, sizeof (buf), "IDENTD %"G_GUINT16_FORMAT" ", port); - if (serv->network && ((ircnet *)serv->network)->user) - g_strlcat (buf, ((ircnet *)serv->network)->user, sizeof (buf)); - else - g_strlcat (buf, prefs.hex_irc_user_name, sizeof (buf)); - - handle_command (serv->server_session, buf, FALSE); - } + handle_command (serv->server_session, buf, FALSE); } server_connect_success (serv); return; @@ -1410,13 +1380,10 @@ server_connect_finish (GObject *source, GAsyncResult *res, gpointer user_data) close_connection: server_stopconnecting (serv); - closesocket (serv->sok4); - if (serv->proxy_sok4 != -1) - closesocket (serv->proxy_sok4); - if (serv->sok6 != -1) - closesocket (serv->sok6); - if (serv->proxy_sok6 != -1) - closesocket (serv->proxy_sok6); + if (serv->sok4) + g_object_unref (serv->sok4); + if (serv->sok6) + g_object_unref (serv->sok6); if (retry && !servlist_cycle (serv) && prefs.hex_net_auto_reconnectonfail) auto_reconnect (serv, FALSE, -1); @@ -1428,36 +1395,51 @@ server_connect_thread (GTask *task, gpointer source, gpointer task_data, GCancel netstore *ns_server; struct connect_data *data = (struct connect_data*)task_data; server *serv = data->serv; - int port = serv->port; - int error; - int sok = -1, psok; - char *hostname = serv->hostname; + GSocket *sok = NULL, *psok; char *proxy_ip = NULL; - int connect_port; int proxy_type = 0; - char *proxy_host = NULL; - int proxy_port; + char *proxy_host = NULL, *hostname; + guint16 proxy_port, connect_port, port; + GError *err = NULL, *err4 = NULL, *err6 = NULL; if (!is_server(serv)) { g_warning ("Server destroyed before connection started!\n"); return; } + port = serv->port; + hostname = serv->hostname; ns_server = net_store_new (); + /* Bind local address if configured */ if (prefs.hex_net_bind_host[0]) { netstore *ns_local = net_store_new (); - data->local_ip = net_resolve (ns_local, prefs.hex_net_bind_host, 0, NULL); - if (data->local_ip != NULL) + data->local_ip = net_resolve (ns_local, prefs.hex_net_bind_host, NULL, &err); + if (!err) { - net_bind (ns_local, serv->sok4, serv->sok6); - } else + net_bind (ns_local, serv->sok4, serv->sok6, &err4, &err6); + if (err4 || err6) + { + net_store_destroy (ns_local); + if (err4) /* TODO: could handle this better? */ + { + g_task_return_error (task, err4); + g_clear_error (&err6); + goto error_cleanup; + } + else + { + g_task_return_error (task, err4); + goto error_cleanup; + } + } + } + else { - g_task_return_new_error (task, HEXCHAT_CONNECTION_ERROR, BIND_FAILED, - "Cannot resolve hostname %s\nCheck your IP Settings!\n", prefs.hex_net_bind_host); + g_task_return_error (task, err); net_store_destroy (ns_local); goto error_cleanup; } @@ -1465,77 +1447,57 @@ server_connect_thread (GTask *task, gpointer source, gpointer task_data, GCancel net_store_destroy (ns_local); } - if (!serv->dont_use_proxy) /* blocked in serverlist? */ + /* Connect to proxy if configured */ + if (!serv->dont_use_proxy && prefs.hex_net_proxy_use != 2 && prefs.hex_net_proxy_type > 0) { -#ifdef USE_LIBPROXY if (prefs.hex_net_proxy_type == 5) { - char **proxy_list; - char *url, *proxy; + char *proxy; - url = g_strdup_printf ("irc://%s:%d", hostname, port); - proxy_list = px_proxy_factory_get_proxies (libproxy_factory, url); - - if (proxy_list) { - /* can use only one */ - proxy = proxy_list[0]; - if (!strncmp (proxy, "direct", 6)) - proxy_type = 0; - else if (!strncmp (proxy, "http", 4)) - proxy_type = 4; - else if (!strncmp (proxy, "socks5", 6)) - proxy_type = 3; - else if (!strncmp (proxy, "socks", 5)) - proxy_type = 2; + proxy = net_resolve_proxy (hostname, port, &err); + if (err) + { + g_task_return_error (task, err); + goto error_cleanup; } - if (proxy_type) { - char *c; - c = strchr (proxy, ':') + 3; - proxy_host = g_strdup (c); - c = strchr (proxy_host, ':'); - *c = '\0'; - proxy_port = atoi (c + 1); + if (proxy) + { + net_parse_proxy_uri (proxy, &proxy_host, &proxy_port, &proxy_type); + g_free (proxy); } - - g_strfreev (proxy_list); - g_free (url); + else + proxy_type = 0; } -#endif - if (prefs.hex_net_proxy_host[0] && - prefs.hex_net_proxy_type > 0 && - prefs.hex_net_proxy_use != 2) /* proxy is NOT dcc-only */ + else if (prefs.hex_net_proxy_host[0]) { proxy_type = prefs.hex_net_proxy_type; proxy_host = g_strdup (prefs.hex_net_proxy_host); proxy_port = prefs.hex_net_proxy_port; } } - serv->proxy_type = proxy_type; data->proxy_hostname = proxy_host; if (proxy_type > 0) { - data->ip = net_resolve (ns_server, proxy_host, proxy_port, &data->hostname); + data->ip = net_resolve (ns_server, proxy_host, &data->hostname, &err); if (!data->ip) { - g_task_return_new_error (task, HEXCHAT_CONNECTION_ERROR, RESOLVE_FAILED, - "Unknown hostname %s\n", proxy_host); + g_task_return_error (task, err); goto error_cleanup; } connect_port = proxy_port; /* if using socks4, attempt to resolve ip for irc server */ - if ((proxy_type == 2) || (proxy_type == 5)) + if (proxy_type == 2) { netstore *ns_proxy = net_store_new (); g_free (data->hostname); - proxy_ip = net_resolve (ns_proxy, hostname, port, &data->hostname); + proxy_ip = net_resolve (ns_proxy, hostname, &data->hostname, &err); net_store_destroy (ns_proxy); - if (!proxy_ip) + if (err) { - g_task_return_new_error (task, HEXCHAT_CONNECTION_ERROR, RESOLVE_FAILED, - "Unknown hostname %s\n", hostname); + g_task_return_error (task, err); goto error_cleanup; } } else /* otherwise we can just use the hostname */ @@ -1543,11 +1505,10 @@ server_connect_thread (GTask *task, gpointer source, gpointer task_data, GCancel } else { - data->ip = net_resolve (ns_server, hostname, port, &data->hostname); - if (!data->ip) + data->ip = net_resolve (ns_server, hostname, &data->hostname, &err); + if (err) { - g_task_return_new_error (task, HEXCHAT_CONNECTION_ERROR, RESOLVE_FAILED, - "Unknown hostname %s\n", hostname); + g_task_return_error (task, err); goto error_cleanup; } connect_port = port; @@ -1555,22 +1516,21 @@ server_connect_thread (GTask *task, gpointer source, gpointer task_data, GCancel data->port = g_strdup_printf ("%d", connect_port); - if (!serv->dont_use_proxy && (proxy_type == 5)) - error = net_connect (ns_server, serv->proxy_sok4, serv->proxy_sok6, &psok); + if (!serv->dont_use_proxy) + psok = net_connect (ns_server, connect_port, serv->sok4, serv->sok6, &err); else { - error = net_connect (ns_server, serv->sok4, serv->sok6, &sok); + sok = net_connect (ns_server, connect_port, serv->sok4, serv->sok6, &err); psok = sok; } - if (error != 0) + if (err) { - g_task_return_new_error (task, HEXCHAT_CONNECTION_ERROR, CONNECTION_FAILED, "%s", errorstring (sock_error())); + g_task_return_error (task, err); goto error_cleanup; } else { - GError *err = NULL; /* connect succeeded */ if (proxy_ip && traverse_proxy (proxy_type, psok, proxy_ip, port, &err)) { @@ -1582,7 +1542,7 @@ server_connect_thread (GTask *task, gpointer source, gpointer task_data, GCancel error_cleanup: net_store_destroy (ns_server); g_free (proxy_ip); - g_task_return_int (task, sok); /* Does nothing if error'd */ + g_task_return_pointer (task, sok, g_object_unref); /* Does nothing if error'd */ return; } @@ -1667,10 +1627,7 @@ server_connect (server *serv, char *hostname, int port, int no_login) fe_set_away (serv); server_flush_queue (serv); - /* create both sockets now, drop one later */ - net_sockets (&serv->sok4, &serv->sok6); - serv->proxy_sok4 = -1; - serv->proxy_sok6 = -1; + net_sockets (&serv->sok4, &serv->sok6, NULL, NULL); /* start the connection in a thread */ data = g_new0 (struct connect_data, 1); @@ -1739,7 +1696,6 @@ server_new (void) server_fill_her_up (serv); serv->id = id++; - serv->sok = -1; strcpy (serv->nick, prefs.hex_irc_nick1); server_set_defaults (serv); diff --git a/src/fe-gtk/setup.c b/src/fe-gtk/setup.c index e3969ff3..804c51f9 100644 --- a/src/fe-gtk/setup.c +++ b/src/fe-gtk/setup.c @@ -560,9 +560,7 @@ static const char *const proxytypes[] = N_("Socks4"), N_("Socks5"), N_("HTTP"), -#ifdef USE_LIBPROXY N_("Auto"), -#endif NULL };