Compare commits
2 Commits
v2.12.2
...
wip/connec
Author | SHA1 | Date | |
---|---|---|---|
480fa3cefc | |||
eb08bcfacf |
32
configure.ac
32
configure.ac
@ -38,7 +38,6 @@ AH_VERBATIM([OLD_PERL],[#undef OLD_PERL])
|
|||||||
AH_VERBATIM([PREFIX],[#undef PREFIX])
|
AH_VERBATIM([PREFIX],[#undef PREFIX])
|
||||||
AH_VERBATIM([HEXCHATLIBDIR],[#undef HEXCHATLIBDIR])
|
AH_VERBATIM([HEXCHATLIBDIR],[#undef HEXCHATLIBDIR])
|
||||||
AH_VERBATIM([HEXCHATSHAREDIR],[#undef HEXCHATSHAREDIR])
|
AH_VERBATIM([HEXCHATSHAREDIR],[#undef HEXCHATSHAREDIR])
|
||||||
AH_VERBATIM([USE_LIBPROXY],[#undef USE_LIBPROXY])
|
|
||||||
AH_VERBATIM([HAVE_ISO_CODES],[#undef HAVE_ISO_CODES])
|
AH_VERBATIM([HAVE_ISO_CODES],[#undef HAVE_ISO_CODES])
|
||||||
AH_VERBATIM([HAVE_GTK_MAC],[#undef HAVE_GTK_MAC])
|
AH_VERBATIM([HAVE_GTK_MAC],[#undef HAVE_GTK_MAC])
|
||||||
AH_VERBATIM([USE_LIBNOTIFY],[#undef USE_LIBNOTIFY])
|
AH_VERBATIM([USE_LIBNOTIFY],[#undef USE_LIBNOTIFY])
|
||||||
@ -139,10 +138,6 @@ AC_ARG_ENABLE(libcanberra,
|
|||||||
[AS_HELP_STRING([--disable-libcanberra],[disable libcanberra support])],
|
[AS_HELP_STRING([--disable-libcanberra],[disable libcanberra support])],
|
||||||
libcanberra=$enableval, libcanberra=yes)
|
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,
|
AC_ARG_ENABLE(isocodes,
|
||||||
[AS_HELP_STRING([--disable-isocodes],[disable iso-codes with spell-check])],
|
[AS_HELP_STRING([--disable-isocodes],[disable iso-codes with spell-check])],
|
||||||
isocodes=$enableval, isocodes=yes)
|
isocodes=$enableval, isocodes=yes)
|
||||||
@ -175,11 +170,11 @@ dnl *********************************************************************
|
|||||||
dnl ** GLIB *************************************************************
|
dnl ** GLIB *************************************************************
|
||||||
dnl *********************************************************************
|
dnl *********************************************************************
|
||||||
|
|
||||||
AM_PATH_GLIB_2_0([2.32.0], [], [AC_MSG_ERROR([Glib not found!])], [gmodule gobject gio])
|
AM_PATH_GLIB_2_0([2.36.0], [], [AC_MSG_ERROR([Glib not found!])], [gmodule gobject gio])
|
||||||
COMMON_CFLAGS="$GLIB_CFLAGS -DG_DISABLE_SINGLE_INCLUDES"
|
COMMON_CFLAGS="$GLIB_CFLAGS -DG_DISABLE_SINGLE_INCLUDES"
|
||||||
COMMON_LIBS="$GLIB_LIBS"
|
COMMON_LIBS="$GLIB_LIBS"
|
||||||
AC_DEFINE([GLIB_VERSION_MIN_REQUIRED], [GLIB_VERSION_2_32], [Dont warn using older APIs])
|
AC_DEFINE([GLIB_VERSION_MIN_REQUIRED], [GLIB_VERSION_2_36], [Dont warn using older APIs])
|
||||||
AC_DEFINE([GLIB_VERSION_MAX_ALLOWED], [GLIB_VERSION_2_32], [Prevents using newer APIs])
|
AC_DEFINE([GLIB_VERSION_MAX_ALLOWED], [GLIB_VERSION_2_36], [Prevents using newer APIs])
|
||||||
|
|
||||||
dnl *********************************************************************
|
dnl *********************************************************************
|
||||||
dnl ** GTK **************************************************************
|
dnl ** GTK **************************************************************
|
||||||
@ -400,26 +395,6 @@ if test "$retry" = "yes"; then
|
|||||||
LIBS=$SAVED_LIBS
|
LIBS=$SAVED_LIBS
|
||||||
fi
|
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 *********************************************************************
|
||||||
dnl ** PLUGIN ***********************************************************
|
dnl ** PLUGIN ***********************************************************
|
||||||
dnl *********************************************************************
|
dnl *********************************************************************
|
||||||
@ -817,7 +792,6 @@ echo D-Bus support ......... : $dbus
|
|||||||
echo libnotify support ..... : $libnotify
|
echo libnotify support ..... : $libnotify
|
||||||
echo libcanberra support ... : $libcanberra
|
echo libcanberra support ... : $libcanberra
|
||||||
echo Plugin interface ...... : $plugin
|
echo Plugin interface ...... : $plugin
|
||||||
echo libproxy support ...... : $libproxy
|
|
||||||
echo
|
echo
|
||||||
echo Perl .................. : $perl
|
echo Perl .................. : $perl
|
||||||
echo Python ................ : $python
|
echo Python ................ : $python
|
||||||
|
@ -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 \
|
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 \
|
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
|
$(ssl_c) text.c tree.c url.c userlist.c util.c
|
||||||
libhexchatcommon_a_CFLAGS = $(LIBPROXY_CFLAGS)
|
|
||||||
|
|
||||||
textenums.h: textevents.h
|
textenums.h: textevents.h
|
||||||
|
|
||||||
|
@ -529,9 +529,7 @@ const struct prefs vars[] =
|
|||||||
{"irc_whois_front", P_OFFINT (hex_irc_whois_front), TYPE_BOOL},
|
{"irc_whois_front", P_OFFINT (hex_irc_whois_front), TYPE_BOOL},
|
||||||
|
|
||||||
{"net_auto_reconnect", P_OFFINT (hex_net_auto_reconnect), TYPE_BOOL},
|
{"net_auto_reconnect", P_OFFINT (hex_net_auto_reconnect), TYPE_BOOL},
|
||||||
#ifndef WIN32 /* FIXME fix reconnect crashes and remove this ifdef! */
|
|
||||||
{"net_auto_reconnectonfail", P_OFFINT (hex_net_auto_reconnectonfail), TYPE_BOOL},
|
{"net_auto_reconnectonfail", P_OFFINT (hex_net_auto_reconnectonfail), TYPE_BOOL},
|
||||||
#endif
|
|
||||||
{"net_bind_host", P_OFFSET (hex_net_bind_host), TYPE_STR},
|
{"net_bind_host", P_OFFSET (hex_net_bind_host), TYPE_STR},
|
||||||
{"net_ping_timeout", P_OFFINT (hex_net_ping_timeout), TYPE_INT},
|
{"net_ping_timeout", P_OFFINT (hex_net_ping_timeout), TYPE_INT},
|
||||||
{"net_proxy_auth", P_OFFINT (hex_net_proxy_auth), TYPE_BOOL},
|
{"net_proxy_auth", P_OFFINT (hex_net_proxy_auth), TYPE_BOOL},
|
||||||
|
@ -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 (GIOChannel *, GIOCondition, struct DCC *);
|
||||||
static gboolean dcc_read_ack (GIOChannel *source, GIOCondition condition, struct DCC *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 new_id()
|
||||||
{
|
{
|
||||||
static int id = 0;
|
static int id = 0;
|
||||||
@ -1668,6 +1677,7 @@ dcc_listen_init (struct DCC *dcc, session *sess)
|
|||||||
if (dcc->sok == -1)
|
if (dcc->sok == -1)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
#if 0
|
||||||
memset (&SAddr, 0, sizeof (struct sockaddr_in));
|
memset (&SAddr, 0, sizeof (struct sockaddr_in));
|
||||||
|
|
||||||
len = sizeof (SAddr);
|
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));
|
setsockopt (dcc->sok, SOL_SOCKET, SO_REUSEADDR, (char *) &len, sizeof (len));
|
||||||
|
|
||||||
} else
|
} else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
/* try random port */
|
/* try random port */
|
||||||
SAddr.sin_port = 0;
|
SAddr.sin_port = 0;
|
||||||
|
@ -123,5 +123,6 @@ void handle_dcc (session *sess, char *nick, char *word[], char *word_eol[],
|
|||||||
void dcc_show_list (session *sess);
|
void dcc_show_list (session *sess);
|
||||||
guint32 dcc_get_my_address (void);
|
guint32 dcc_get_my_address (void);
|
||||||
void dcc_get_with_destfile (struct DCC *dcc, char *utf8file);
|
void dcc_get_with_destfile (struct DCC *dcc, char *utf8file);
|
||||||
|
char *net_ip (guint32 addr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -56,10 +56,6 @@
|
|||||||
#include <glib-object.h> /* for g_type_init() */
|
#include <glib-object.h> /* for g_type_init() */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_LIBPROXY
|
|
||||||
#include <proxy.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
GSList *popup_list = 0;
|
GSList *popup_list = 0;
|
||||||
GSList *button_list = 0;
|
GSList *button_list = 0;
|
||||||
GSList *dlgbutton_list = 0;
|
GSList *dlgbutton_list = 0;
|
||||||
@ -110,10 +106,6 @@ struct session *current_tab;
|
|||||||
struct session *current_sess = 0;
|
struct session *current_sess = 0;
|
||||||
struct hexchatprefs prefs;
|
struct hexchatprefs prefs;
|
||||||
|
|
||||||
#ifdef USE_LIBPROXY
|
|
||||||
pxProxyFactory *libproxy_factory;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update the priority queue of the "interesting sessions"
|
* Update the priority queue of the "interesting sessions"
|
||||||
* (sess_list_by_lastact).
|
* (sess_list_by_lastact).
|
||||||
@ -1048,10 +1040,6 @@ main (int argc, char *argv[])
|
|||||||
hexchat_remote ();
|
hexchat_remote ();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_LIBPROXY
|
|
||||||
libproxy_factory = px_proxy_factory_new();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
fe_init ();
|
fe_init ();
|
||||||
|
|
||||||
/* This is done here because cfgfiles.c is too early in
|
/* This is done here because cfgfiles.c is too early in
|
||||||
@ -1079,10 +1067,6 @@ main (int argc, char *argv[])
|
|||||||
|
|
||||||
fe_main ();
|
fe_main ();
|
||||||
|
|
||||||
#ifdef USE_LIBPROXY
|
|
||||||
px_proxy_factory_free(libproxy_factory);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
WSACleanup ();
|
WSACleanup ();
|
||||||
#endif
|
#endif
|
||||||
|
@ -471,14 +471,10 @@ typedef struct server
|
|||||||
int (*p_raw)(struct server *, char *raw);
|
int (*p_raw)(struct server *, char *raw);
|
||||||
int (*p_cmp)(const char *s1, const char *s2);
|
int (*p_cmp)(const char *s1, const char *s2);
|
||||||
|
|
||||||
int port;
|
guint16 port;
|
||||||
int sok; /* is equal to sok4 or sok6 (the one we are using) */
|
GSocket *sok; /* is equal to sok4 or sok6 (the one we are using) */
|
||||||
int sok4; /* tcp4 socket */
|
GSocket *sok4; /* tcp4 socket */
|
||||||
int sok6; /* tcp6 socket */
|
GSocket *sok6; /* tcp6 socket */
|
||||||
int proxy_type;
|
|
||||||
int proxy_sok; /* Additional information for MS Proxy beast */
|
|
||||||
int proxy_sok4;
|
|
||||||
int proxy_sok6;
|
|
||||||
int id; /* unique ID number (for plugin API) */
|
int id; /* unique ID number (for plugin API) */
|
||||||
#ifdef USE_OPENSSL
|
#ifdef USE_OPENSSL
|
||||||
SSL_CTX *ctx;
|
SSL_CTX *ctx;
|
||||||
@ -487,9 +483,7 @@ typedef struct server
|
|||||||
#else
|
#else
|
||||||
void *ssl;
|
void *ssl;
|
||||||
#endif
|
#endif
|
||||||
int childread;
|
GCancellable *cancellable; /* to cancel connecting thread */
|
||||||
int childwrite;
|
|
||||||
int childpid;
|
|
||||||
int iotag;
|
int iotag;
|
||||||
int recondelay_tag; /* reconnect delay timeout */
|
int recondelay_tag; /* reconnect delay timeout */
|
||||||
int joindelay_tag; /* waiting before we send JOIN */
|
int joindelay_tag; /* waiting before we send JOIN */
|
||||||
|
@ -20,53 +20,18 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
#include <gio/gio.h>
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define WANTSOCKET
|
|
||||||
#define WANTARPA
|
|
||||||
#define WANTDNS
|
|
||||||
#include "inet.h"
|
|
||||||
|
|
||||||
#define NETWORK_PRIVATE
|
|
||||||
#include "network.h"
|
#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
|
void
|
||||||
net_store_destroy (netstore * ns)
|
net_store_destroy (netstore *ns)
|
||||||
{
|
{
|
||||||
if (ns->ip6_hostent)
|
g_return_if_fail (ns != NULL);
|
||||||
freeaddrinfo (ns->ip6_hostent);
|
|
||||||
|
g_resolver_free_addresses (ns->addrs);
|
||||||
g_free (ns);
|
g_free (ns);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,115 +41,208 @@ net_store_new (void)
|
|||||||
return g_new0 (netstore, 1);
|
return g_new0 (netstore, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* =================== IPV6 ================== */
|
|
||||||
|
|
||||||
char *
|
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;
|
GResolver *res;
|
||||||
char ipstring[MAX_HOSTNAME];
|
GList *addrs;
|
||||||
char portstring[MAX_HOSTNAME];
|
GInetAddress *addr;
|
||||||
int ret;
|
char *ipstring;
|
||||||
|
|
||||||
/* if (ns->ip6_hostent)
|
res = g_resolver_get_default ();
|
||||||
freeaddrinfo (ns->ip6_hostent);*/
|
|
||||||
|
|
||||||
sprintf (portstring, "%d", port);
|
// todo: lookup by irc service?
|
||||||
|
addrs = g_resolver_lookup_by_name (res, hostname, NULL, error);
|
||||||
memset (&hints, 0, sizeof (struct addrinfo));
|
if (!addrs)
|
||||||
hints.ai_family = PF_UNSPEC; /* support ipv6 and ipv4 */
|
{
|
||||||
hints.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
|
g_object_unref (res);
|
||||||
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)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef LOOKUPD /* See note about lookupd above the IPv4 version of net_resolve. */
|
ns->addrs = addrs;
|
||||||
struct addrinfo *tmp;
|
addr = G_INET_ADDRESS(addrs->data);
|
||||||
int count = 0;
|
ipstring = g_inet_address_to_string (addr);
|
||||||
|
|
||||||
for (tmp = ns->ip6_hostent; tmp; tmp = tmp->ai_next)
|
if (real_host)
|
||||||
count ++;
|
{
|
||||||
|
if (!(*real_host = g_resolver_lookup_by_address (res, addr, NULL, NULL)))
|
||||||
|
*real_host = g_strdup (hostname);
|
||||||
|
}
|
||||||
|
|
||||||
count = RAND_INT(count);
|
g_object_unref (res);
|
||||||
|
|
||||||
while (count--) ns->ip6_hostent = ns->ip6_hostent->ai_next;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* find the numeric IP number */
|
return ipstring;
|
||||||
ipstring[0] = 0;
|
|
||||||
getnameinfo (ns->ip6_hostent->ai_addr, ns->ip6_hostent->ai_addrlen,
|
|
||||||
ipstring, sizeof (ipstring), NULL, 0, NI_NUMERICHOST);
|
|
||||||
|
|
||||||
if (ns->ip6_hostent->ai_canonname)
|
|
||||||
*real_host = g_strdup (ns->ip6_hostent->ai_canonname);
|
|
||||||
else
|
|
||||||
*real_host = g_strdup (hostname);
|
|
||||||
|
|
||||||
return g_strdup (ipstring);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the only thing making this interface unclean, this shitty sok4, sok6 business */
|
/* the only thing making this interface unclean, this shitty sok4, sok6 business */
|
||||||
|
|
||||||
int
|
GSocket *
|
||||||
net_connect (netstore * ns, int sok4, int sok6, int *sok_return)
|
net_connect (netstore *ns, guint16 port, GSocket *sok4, GSocket *sok6, GError **error)
|
||||||
{
|
{
|
||||||
struct addrinfo *res, *res0;
|
GSocket *sok;
|
||||||
int error = -1;
|
GList *addrs;
|
||||||
|
gboolean success;
|
||||||
|
|
||||||
res0 = ns->ip6_hostent;
|
for (addrs = ns->addrs; addrs; addrs = g_list_next (addrs))
|
||||||
|
|
||||||
for (res = res0; res; res = res->ai_next)
|
|
||||||
{
|
{
|
||||||
/* sok = socket (res->ai_family, res->ai_socktype, res->ai_protocol);
|
GInetAddress *inet_addr = G_INET_ADDRESS(addrs->data);
|
||||||
if (sok < 0)
|
GSocketAddress *sok_addr;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error == 0)
|
g_clear_error (error); /* Last failed attempt set */
|
||||||
break;
|
|
||||||
|
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
|
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,
|
if (type)
|
||||||
tobindto->ip6_hostent->ai_addrlen);
|
{
|
||||||
bind (sok6, tobindto->ip6_hostent->ai_addr,
|
char *scheme = g_uri_parse_scheme (proxy_uri);
|
||||||
tobindto->ip6_hostent->ai_addrlen);
|
|
||||||
|
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
|
guint16
|
||||||
net_sockets (int *sok4, int *sok6)
|
net_get_local_port (GSocket *sok)
|
||||||
{
|
{
|
||||||
*sok4 = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
GSocketAddress *addr;
|
||||||
*sok6 = socket (AF_INET6, SOCK_STREAM, IPPROTO_TCP);
|
guint16 port;
|
||||||
net_set_socket_options (*sok4);
|
|
||||||
net_set_socket_options (*sok6);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
addr = g_socket_get_local_address (sok, NULL);
|
||||||
udp_sockets (int *sok4, int *sok6)
|
if (!addr)
|
||||||
{
|
return 0;
|
||||||
*sok4 = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
|
||||||
*sok6 = socket (AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS(addr));
|
||||||
|
g_object_unref (addr);
|
||||||
|
|
||||||
|
return port;
|
||||||
}
|
}
|
||||||
|
@ -22,21 +22,18 @@
|
|||||||
|
|
||||||
typedef struct netstore_
|
typedef struct netstore_
|
||||||
{
|
{
|
||||||
#ifdef NETWORK_PRIVATE
|
GList *addrs;
|
||||||
struct addrinfo *ip6_hostent;
|
|
||||||
#else
|
|
||||||
int _dummy; /* some compilers don't like empty structs */
|
|
||||||
#endif
|
|
||||||
} netstore;
|
} netstore;
|
||||||
|
|
||||||
#define MAX_HOSTNAME 128
|
#define MAX_HOSTNAME 128
|
||||||
|
|
||||||
netstore *net_store_new (void);
|
netstore *net_store_new (void);
|
||||||
void net_store_destroy (netstore *ns);
|
void net_store_destroy (netstore *ns);
|
||||||
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);
|
||||||
char *net_resolve (netstore *ns, char *hostname, int port, char **real_host);
|
char *net_resolve (netstore *ns, char *hostname, char **real_host, GError **error);
|
||||||
void net_bind (netstore *tobindto, int sok4, int sok6);
|
char * net_resolve_proxy (const char *hostname, guint16 port, GError **error);
|
||||||
char *net_ip (guint32 addr);
|
gboolean net_bind (netstore *ns, GSocket *sok4, GSocket *sok6, GError **error4, GError **error6);
|
||||||
void net_sockets (int *sok4, int *sok6);
|
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
|
#endif
|
||||||
|
@ -907,7 +907,7 @@ cmd_debug (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
|||||||
{
|
{
|
||||||
v = (struct server *) list->data;
|
v = (struct server *) list->data;
|
||||||
sprintf (tbuf, "%p %-5d %s\n",
|
sprintf (tbuf, "%p %-5d %s\n",
|
||||||
v, v->sok, v->servername);
|
v, g_socket_get_fd (v->sok), v->servername);
|
||||||
PrintText (sess, tbuf);
|
PrintText (sess, tbuf);
|
||||||
list = list->next;
|
list = list->next;
|
||||||
}
|
}
|
||||||
@ -3205,7 +3205,7 @@ cmd_send (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
|||||||
|
|
||||||
if (!word[2][0])
|
if (!word[2][0])
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
#if 0
|
||||||
addr = dcc_get_my_address ();
|
addr = dcc_get_my_address ();
|
||||||
if (addr == 0)
|
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]);
|
g_snprintf (tbuf, 512, "DCC PSEND %s", word_eol[2]);
|
||||||
else
|
else
|
||||||
g_snprintf (tbuf, 512, "DCC SEND %s", word_eol[2]);
|
g_snprintf (tbuf, 512, "DCC SEND %s", word_eol[2]);
|
||||||
|
#endif
|
||||||
handle_command (sess, tbuf, FALSE);
|
handle_command (sess, tbuf, FALSE);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -61,9 +61,7 @@
|
|||||||
#include "ssl.h"
|
#include "ssl.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_LIBPROXY
|
#define HEXCHAT_CONNECTION_ERROR g_quark_from_static_string("hexchat-connection-error")
|
||||||
#include <proxy.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_OPENSSL
|
#ifdef USE_OPENSSL
|
||||||
/* local variables */
|
/* local variables */
|
||||||
@ -78,9 +76,13 @@ static void server_disconnect (session * sess, int sendquit, int err);
|
|||||||
static int server_cleanup (server * serv);
|
static int server_cleanup (server * serv);
|
||||||
static void server_connect (server *serv, char *hostname, int port, int no_login);
|
static void server_connect (server *serv, char *hostname, int port, int no_login);
|
||||||
|
|
||||||
#ifdef USE_LIBPROXY
|
enum
|
||||||
extern pxProxyFactory *libproxy_factory;
|
{
|
||||||
#endif
|
RESOLVE_FAILED = 1,
|
||||||
|
CONNECTION_FAILED,
|
||||||
|
BIND_FAILED,
|
||||||
|
PROXY_FAILED
|
||||||
|
};
|
||||||
|
|
||||||
/* actually send to the socket. This might do a character translation or
|
/* actually send to the socket. This might do a character translation or
|
||||||
send via SSL. server/dcc both use this function. */
|
send via SSL. server/dcc both use this function. */
|
||||||
@ -148,7 +150,7 @@ server_send_real (server *serv, char *buf, int len)
|
|||||||
|
|
||||||
url_check_line (buf);
|
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);
|
buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,15 +286,15 @@ tcp_sendf (server *serv, const char *fmt, ...)
|
|||||||
static int
|
static int
|
||||||
close_socket_cb (gpointer sok)
|
close_socket_cb (gpointer sok)
|
||||||
{
|
{
|
||||||
closesocket (GPOINTER_TO_INT (sok));
|
g_object_unref (sok);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
close_socket (int sok)
|
close_socket (GSocket *sok)
|
||||||
{
|
{
|
||||||
/* close the socket in 5 seconds so the QUIT message is not lost */
|
/* 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 */
|
/* handle 1 line of text received from the server */
|
||||||
@ -401,7 +403,7 @@ server_inline (server *serv, char *line, gssize len)
|
|||||||
static gboolean
|
static gboolean
|
||||||
server_read (GIOChannel *source, GIOCondition condition, server *serv)
|
server_read (GIOChannel *source, GIOCondition condition, server *serv)
|
||||||
{
|
{
|
||||||
int sok = serv->sok;
|
int sok = g_socket_get_fd (serv->sok);
|
||||||
int error, i, len;
|
int error, i, len;
|
||||||
char lbuf[2050];
|
char lbuf[2050];
|
||||||
|
|
||||||
@ -479,8 +481,8 @@ server_connected (server * serv)
|
|||||||
serv->ping_recv = time (0);
|
serv->ping_recv = time (0);
|
||||||
serv->lag_sent = 0;
|
serv->lag_sent = 0;
|
||||||
serv->connected = TRUE;
|
serv->connected = TRUE;
|
||||||
set_nonblocking (serv->sok);
|
g_socket_set_blocking (serv->sok, FALSE);
|
||||||
serv->iotag = fe_input_add (serv->sok, FIA_READ|FIA_EX, server_read, serv);
|
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)
|
if (!serv->no_login)
|
||||||
{
|
{
|
||||||
EMIT_SIGNAL (XP_TE_CONNECTED, serv->server_session, NULL, NULL, NULL,
|
EMIT_SIGNAL (XP_TE_CONNECTED, serv->server_session, NULL, NULL, NULL,
|
||||||
@ -538,25 +540,6 @@ server_stopconnecting (server * serv)
|
|||||||
serv->joindelay_tag = 0;
|
serv->joindelay_tag = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
/* kill the child process trying to connect */
|
|
||||||
kill (serv->childpid, SIGKILL);
|
|
||||||
waitpid (serv->childpid, NULL, 0);
|
|
||||||
|
|
||||||
close (serv->childwrite);
|
|
||||||
close (serv->childread);
|
|
||||||
#else
|
|
||||||
PostThreadMessage (serv->childpid, WM_QUIT, 0, 0);
|
|
||||||
|
|
||||||
{
|
|
||||||
/* if we close the pipe now, giowin32 will crash. */
|
|
||||||
int *pipefd = g_new (int, 2);
|
|
||||||
pipefd[0] = serv->childwrite;
|
|
||||||
pipefd[1] = serv->childread;
|
|
||||||
g_idle_add ((GSourceFunc)server_close_pipe, pipefd);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_OPENSSL
|
#ifdef USE_OPENSSL
|
||||||
if (serv->ssl_do_connect_tag)
|
if (serv->ssl_do_connect_tag)
|
||||||
{
|
{
|
||||||
@ -565,6 +548,12 @@ server_stopconnecting (server * serv)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (serv->cancellable)
|
||||||
|
{
|
||||||
|
g_object_unref (serv->cancellable);
|
||||||
|
serv->cancellable = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
fe_progressbar_end (serv);
|
fe_progressbar_end (serv);
|
||||||
|
|
||||||
serv->connecting = FALSE;
|
serv->connecting = FALSE;
|
||||||
@ -863,7 +852,7 @@ server_connect_success (server *serv)
|
|||||||
|
|
||||||
/* it'll be a memory leak, if connection isn't terminated by
|
/* it'll be a memory leak, if connection isn't terminated by
|
||||||
server_cleanup() */
|
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)))
|
if ((err = _SSL_set_verify (serv->ctx, ssl_cb_verify, NULL)))
|
||||||
{
|
{
|
||||||
EMIT_SIGNAL (XP_TE_CONNFAIL, serv->server_session, err, NULL,
|
EMIT_SIGNAL (XP_TE_CONNFAIL, serv->server_session, err, NULL,
|
||||||
@ -873,7 +862,7 @@ server_connect_success (server *serv)
|
|||||||
}
|
}
|
||||||
/* FIXME: it'll be needed by new servers */
|
/* FIXME: it'll be needed by new servers */
|
||||||
/* send(serv->sok, "STLS\r\n", 6, 0); sleep(1); */
|
/* 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,
|
serv->ssl_do_connect_tag = fe_timeout_add (SSLDOCONNTMOUT,
|
||||||
ssl_do_connect, serv);
|
ssl_do_connect, serv);
|
||||||
return;
|
return;
|
||||||
@ -886,124 +875,6 @@ server_connect_success (server *serv)
|
|||||||
server_connected (serv);
|
server_connected (serv);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* receive info from the child-process about connection progress */
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
server_read_child (GIOChannel *source, GIOCondition condition, server *serv)
|
|
||||||
{
|
|
||||||
session *sess = serv->server_session;
|
|
||||||
char tbuf[128];
|
|
||||||
char outbuf[512];
|
|
||||||
char host[100];
|
|
||||||
char ip[100];
|
|
||||||
|
|
||||||
waitline2 (source, tbuf, sizeof tbuf);
|
|
||||||
|
|
||||||
switch (tbuf[0])
|
|
||||||
{
|
|
||||||
case '0': /* print some text */
|
|
||||||
waitline2 (source, tbuf, sizeof tbuf);
|
|
||||||
PrintText (serv->server_session, tbuf);
|
|
||||||
break;
|
|
||||||
case '1': /* unknown host */
|
|
||||||
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);
|
|
||||||
EMIT_SIGNAL (XP_TE_UKNHOST, sess, NULL, NULL, NULL, NULL, 0);
|
|
||||||
if (!servlist_cycle (serv))
|
|
||||||
if (prefs.hex_net_auto_reconnectonfail)
|
|
||||||
auto_reconnect (serv, FALSE, -1);
|
|
||||||
break;
|
|
||||||
case '2': /* connection failed */
|
|
||||||
waitline2 (source, tbuf, sizeof tbuf);
|
|
||||||
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);
|
|
||||||
EMIT_SIGNAL (XP_TE_CONNFAIL, sess, errorstring (atoi (tbuf)), NULL,
|
|
||||||
NULL, NULL, 0);
|
|
||||||
if (!servlist_cycle (serv))
|
|
||||||
if (prefs.hex_net_auto_reconnectonfail)
|
|
||||||
auto_reconnect (serv, FALSE, -1);
|
|
||||||
break;
|
|
||||||
case '3': /* gethostbyname finished */
|
|
||||||
waitline2 (source, host, sizeof host);
|
|
||||||
waitline2 (source, ip, sizeof ip);
|
|
||||||
waitline2 (source, outbuf, sizeof outbuf);
|
|
||||||
EMIT_SIGNAL (XP_TE_CONNECT, sess, host, ip, outbuf, NULL, 0);
|
|
||||||
break;
|
|
||||||
case '4': /* success */
|
|
||||||
waitline2 (source, tbuf, sizeof (tbuf));
|
|
||||||
serv->sok = atoi (tbuf);
|
|
||||||
/* close the one we didn't end up using */
|
|
||||||
if (serv->sok == serv->sok4)
|
|
||||||
closesocket (serv->sok6);
|
|
||||||
else
|
|
||||||
closesocket (serv->sok4);
|
|
||||||
if (serv->proxy_sok != -1)
|
|
||||||
{
|
|
||||||
if (serv->proxy_sok == serv->proxy_sok4)
|
|
||||||
closesocket (serv->proxy_sok6);
|
|
||||||
else
|
|
||||||
closesocket (serv->proxy_sok4);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
struct sockaddr addr;
|
|
||||||
int addr_len = sizeof (addr);
|
|
||||||
guint16 port;
|
|
||||||
|
|
||||||
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 (outbuf, sizeof (outbuf), "IDENTD %"G_GUINT16_FORMAT" ", port);
|
|
||||||
if (serv->network && ((ircnet *)serv->network)->user)
|
|
||||||
g_strlcat (outbuf, ((ircnet *)serv->network)->user, sizeof (outbuf));
|
|
||||||
else
|
|
||||||
g_strlcat (outbuf, prefs.hex_irc_user_name, sizeof (outbuf));
|
|
||||||
|
|
||||||
handle_command (serv->server_session, outbuf, FALSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
server_connect_success (serv);
|
|
||||||
break;
|
|
||||||
case '5': /* prefs ip discovered */
|
|
||||||
waitline2 (source, tbuf, sizeof tbuf);
|
|
||||||
prefs.local_ip = inet_addr (tbuf);
|
|
||||||
break;
|
|
||||||
case '7': /* gethostbyname (prefs.hex_net_bind_host) failed */
|
|
||||||
sprintf (outbuf,
|
|
||||||
_("Cannot resolve hostname %s\nCheck your IP Settings!\n"),
|
|
||||||
prefs.hex_net_bind_host);
|
|
||||||
PrintText (sess, outbuf);
|
|
||||||
break;
|
|
||||||
case '8':
|
|
||||||
PrintText (sess, _("Proxy traversal failed.\n"));
|
|
||||||
server_disconnect (sess, FALSE, -1);
|
|
||||||
break;
|
|
||||||
case '9':
|
|
||||||
waitline2 (source, tbuf, sizeof tbuf);
|
|
||||||
EMIT_SIGNAL (XP_TE_SERVERLOOKUP, sess, tbuf, NULL, NULL, NULL, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* kill all sockets & iotags of a server. Stop a connection attempt, or
|
/* kill all sockets & iotags of a server. Stop a connection attempt, or
|
||||||
disconnect if already connected. */
|
disconnect if already connected. */
|
||||||
|
|
||||||
@ -1036,21 +907,16 @@ server_cleanup (server * serv)
|
|||||||
if (serv->connecting)
|
if (serv->connecting)
|
||||||
{
|
{
|
||||||
server_stopconnecting (serv);
|
server_stopconnecting (serv);
|
||||||
closesocket (serv->sok4);
|
if (serv->sok4)
|
||||||
if (serv->proxy_sok4 != -1)
|
g_object_unref (serv->sok4);
|
||||||
closesocket (serv->proxy_sok4);
|
if (serv->sok6)
|
||||||
if (serv->sok6 != -1)
|
g_object_unref (serv->sok6);
|
||||||
closesocket (serv->sok6);
|
|
||||||
if (serv->proxy_sok6 != -1)
|
|
||||||
closesocket (serv->proxy_sok6);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serv->connected)
|
if (serv->connected)
|
||||||
{
|
{
|
||||||
close_socket (serv->sok);
|
close_socket (serv->sok);
|
||||||
if (serv->proxy_sok)
|
|
||||||
close_socket (serv->proxy_sok);
|
|
||||||
serv->connected = FALSE;
|
serv->connected = FALSE;
|
||||||
serv->end_of_motd = FALSE;
|
serv->end_of_motd = FALSE;
|
||||||
return 2;
|
return 2;
|
||||||
@ -1072,7 +938,6 @@ server_disconnect (session * sess, int sendquit, int err)
|
|||||||
{
|
{
|
||||||
server *serv = sess->server;
|
server *serv = sess->server;
|
||||||
GSList *list;
|
GSList *list;
|
||||||
char tbuf[64];
|
|
||||||
gboolean shutup = FALSE;
|
gboolean shutup = FALSE;
|
||||||
|
|
||||||
/* send our QUIT reason */
|
/* send our QUIT reason */
|
||||||
@ -1090,8 +955,8 @@ server_disconnect (session * sess, int sendquit, int err)
|
|||||||
notc_msg (sess);
|
notc_msg (sess);
|
||||||
return;
|
return;
|
||||||
case 1: /* it was in the process of connecting */
|
case 1: /* it was in the process of connecting */
|
||||||
sprintf (tbuf, "%d", sess->server->childpid);
|
EMIT_SIGNAL (XP_TE_STOPCONNECT, sess, NULL, NULL, NULL, NULL, 0);
|
||||||
EMIT_SIGNAL (XP_TE_STOPCONNECT, sess, tbuf, NULL, NULL, NULL, 0);
|
g_cancellable_cancel (serv->cancellable);
|
||||||
return;
|
return;
|
||||||
case 3:
|
case 3:
|
||||||
shutup = TRUE; /* won't print "disconnected" in channels */
|
shutup = TRUE; /* won't print "disconnected" in channels */
|
||||||
@ -1124,15 +989,6 @@ server_disconnect (session * sess, int sendquit, int err)
|
|||||||
notify_cleanup ();
|
notify_cleanup ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send a "print text" command to the parent process - MUST END IN \n! */
|
|
||||||
|
|
||||||
static void
|
|
||||||
proxy_error (int fd, char *msg)
|
|
||||||
{
|
|
||||||
write (fd, "0\n", 2);
|
|
||||||
write (fd, msg, strlen (msg));
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sock_connect
|
struct sock_connect
|
||||||
{
|
{
|
||||||
char version;
|
char version;
|
||||||
@ -1147,7 +1003,7 @@ struct sock_connect
|
|||||||
* 1 socks traversal failed */
|
* 1 socks traversal failed */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
traverse_socks (int print_fd, int sok, char *serverAddr, int port)
|
traverse_socks (int sok, char *serverAddr, int port, GError **error)
|
||||||
{
|
{
|
||||||
struct sock_connect sc;
|
struct sock_connect sc;
|
||||||
unsigned char buf[256];
|
unsigned char buf[256];
|
||||||
@ -1165,7 +1021,7 @@ traverse_socks (int print_fd, int sok, char *serverAddr, int port)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
g_snprintf (buf, sizeof (buf), "SOCKS\tServer reported error %d,%d.\n", buf[0], buf[1]);
|
g_snprintf (buf, sizeof (buf), "SOCKS\tServer reported error %d,%d.\n", buf[0], buf[1]);
|
||||||
proxy_error (print_fd, buf);
|
*error = g_error_new_literal (HEXCHAT_CONNECTION_ERROR, PROXY_FAILED, buf);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1177,7 +1033,7 @@ struct sock5_connect1
|
|||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
traverse_socks5 (int print_fd, int sok, char *serverAddr, int port)
|
traverse_socks5 (int sok, char *serverAddr, int port, GError **error)
|
||||||
{
|
{
|
||||||
struct sock5_connect1 sc1;
|
struct sock5_connect1 sc1;
|
||||||
unsigned char *sc2;
|
unsigned char *sc2;
|
||||||
@ -1197,7 +1053,7 @@ traverse_socks5 (int print_fd, int sok, char *serverAddr, int port)
|
|||||||
|
|
||||||
if (buf[0] != 5)
|
if (buf[0] != 5)
|
||||||
{
|
{
|
||||||
proxy_error (print_fd, "SOCKS\tServer is not socks version 5.\n");
|
*error = g_error_new_literal (HEXCHAT_CONNECTION_ERROR, PROXY_FAILED, "SOCKS\tServer is not socks version 5.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1212,7 +1068,7 @@ traverse_socks5 (int print_fd, int sok, char *serverAddr, int port)
|
|||||||
/* authentication sub-negotiation (RFC1929) */
|
/* authentication sub-negotiation (RFC1929) */
|
||||||
if (buf[1] != 2) /* UPA not supported by server */
|
if (buf[1] != 2) /* UPA not supported by server */
|
||||||
{
|
{
|
||||||
proxy_error (print_fd, "SOCKS\tServer doesn't support UPA authentication.\n");
|
*error = g_error_new_literal (HEXCHAT_CONNECTION_ERROR, PROXY_FAILED, "SOCKS\tServer doesn't support UPA authentication.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1232,7 +1088,7 @@ traverse_socks5 (int print_fd, int sok, char *serverAddr, int port)
|
|||||||
goto read_error;
|
goto read_error;
|
||||||
if ( buf[1] != 0 )
|
if ( buf[1] != 0 )
|
||||||
{
|
{
|
||||||
proxy_error (print_fd, "SOCKS\tAuthentication failed. "
|
*error = g_error_new_literal (HEXCHAT_CONNECTION_ERROR, PROXY_FAILED, "SOCKS\tAuthentication failed. "
|
||||||
"Is username and password correct?\n");
|
"Is username and password correct?\n");
|
||||||
return 1; /* UPA failed! */
|
return 1; /* UPA failed! */
|
||||||
}
|
}
|
||||||
@ -1241,7 +1097,7 @@ traverse_socks5 (int print_fd, int sok, char *serverAddr, int port)
|
|||||||
{
|
{
|
||||||
if (buf[1] != 0)
|
if (buf[1] != 0)
|
||||||
{
|
{
|
||||||
proxy_error (print_fd, "SOCKS\tAuthentication required but disabled in settings.\n");
|
*error = g_error_new_literal (HEXCHAT_CONNECTION_ERROR, PROXY_FAILED, "SOCKS\tAuthentication required but disabled in settings.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1268,7 +1124,7 @@ traverse_socks5 (int print_fd, int sok, char *serverAddr, int port)
|
|||||||
g_snprintf (buf, sizeof (buf), "SOCKS\tProxy refused to connect to host (not allowed).\n");
|
g_snprintf (buf, sizeof (buf), "SOCKS\tProxy refused to connect to host (not allowed).\n");
|
||||||
else
|
else
|
||||||
g_snprintf (buf, sizeof (buf), "SOCKS\tProxy failed to connect to host (error %d).\n", buf[1]);
|
g_snprintf (buf, sizeof (buf), "SOCKS\tProxy failed to connect to host (error %d).\n", buf[1]);
|
||||||
proxy_error (print_fd, buf);
|
*error = g_error_new_literal (HEXCHAT_CONNECTION_ERROR, PROXY_FAILED, buf);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (buf[3] == 1) /* IPV4 32bit address */
|
if (buf[3] == 1) /* IPV4 32bit address */
|
||||||
@ -1291,12 +1147,12 @@ traverse_socks5 (int print_fd, int sok, char *serverAddr, int port)
|
|||||||
return 0; /* success */
|
return 0; /* success */
|
||||||
|
|
||||||
read_error:
|
read_error:
|
||||||
proxy_error (print_fd, "SOCKS\tRead error from server.\n");
|
*error = g_error_new_literal (HEXCHAT_CONNECTION_ERROR, PROXY_FAILED, "SOCKS\tRead error from server.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
traverse_wingate (int print_fd, int sok, char *serverAddr, int port)
|
traverse_wingate (int sok, char *serverAddr, int port, GError **error)
|
||||||
{
|
{
|
||||||
char buf[128];
|
char buf[128];
|
||||||
|
|
||||||
@ -1358,30 +1214,7 @@ base64_encode (char *to, char *from, unsigned int len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
http_read_line (int print_fd, int sok, char *buf, int len)
|
traverse_http (int sok, char *serverAddr, int port, GError **error)
|
||||||
{
|
|
||||||
len = waitline (sok, buf, len, TRUE);
|
|
||||||
if (len >= 1)
|
|
||||||
{
|
|
||||||
/* print the message out (send it to the parent process) */
|
|
||||||
write (print_fd, "0\n", 2);
|
|
||||||
|
|
||||||
if (buf[len-1] == '\r')
|
|
||||||
{
|
|
||||||
buf[len-1] = '\n';
|
|
||||||
write (print_fd, buf, len);
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
write (print_fd, buf, len);
|
|
||||||
write (print_fd, "\n", 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
traverse_http (int print_fd, int sok, char *serverAddr, int port)
|
|
||||||
{
|
{
|
||||||
char buf[512];
|
char buf[512];
|
||||||
char auth_data[256];
|
char auth_data[256];
|
||||||
@ -1400,16 +1233,18 @@ traverse_http (int print_fd, int sok, char *serverAddr, int port)
|
|||||||
n += g_snprintf (buf+n, sizeof (buf)-n, "\r\n");
|
n += g_snprintf (buf+n, sizeof (buf)-n, "\r\n");
|
||||||
send (sok, buf, n, 0);
|
send (sok, buf, n, 0);
|
||||||
|
|
||||||
n = http_read_line (print_fd, sok, buf, sizeof (buf));
|
n = waitline (sok, buf, sizeof(buf), TRUE);
|
||||||
|
|
||||||
/* "HTTP/1.0 200 OK" */
|
/* "HTTP/1.0 200 OK" */
|
||||||
if (n < 12)
|
if (n < 12 || (memcmp (buf, "HTTP/", 5) || memcmp (buf + 9, "200", 3)))
|
||||||
return 1;
|
{
|
||||||
if (memcmp (buf, "HTTP/", 5) || memcmp (buf + 9, "200", 3))
|
*error = g_error_new_literal (HEXCHAT_CONNECTION_ERROR, PROXY_FAILED, buf);
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
/* read until blank line */
|
/* read until blank line */
|
||||||
n = http_read_line (print_fd, sok, buf, sizeof (buf));
|
n = waitline (sok, buf, sizeof(buf), TRUE);
|
||||||
if (n < 1 || (n == 1 && buf[0] == '\n'))
|
if (n < 1 || (n == 1 && buf[0] == '\n'))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1417,214 +1252,306 @@ traverse_http (int print_fd, int sok, char *serverAddr, int port)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
traverse_proxy (int proxy_type, int print_fd, int sok, char *ip, int port, netstore *ns_proxy, int csok4, int csok6, int *csok, char bound)
|
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)
|
switch (proxy_type)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
return traverse_wingate (print_fd, sok, ip, port);
|
return traverse_wingate (sok, ip, port, error);
|
||||||
case 2:
|
case 2:
|
||||||
return traverse_socks (print_fd, sok, ip, port);
|
return traverse_socks (sok, ip, port, error);
|
||||||
case 3:
|
case 3:
|
||||||
return traverse_socks5 (print_fd, sok, ip, port);
|
return traverse_socks5 (sok, ip, port, error);
|
||||||
case 4:
|
case 4:
|
||||||
return traverse_http (print_fd, sok, ip, port);
|
return traverse_http (sok, ip, port, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* this is the child process making the connection attempt */
|
struct connect_data
|
||||||
|
{
|
||||||
|
server *serv;
|
||||||
|
char *local_ip;
|
||||||
|
char *hostname;
|
||||||
|
char *proxy_hostname;
|
||||||
|
char *ip;
|
||||||
|
char *port;
|
||||||
|
};
|
||||||
|
|
||||||
static int
|
static void
|
||||||
server_child (server * serv)
|
connect_data_free (struct connect_data *data)
|
||||||
|
{
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
g_free (data->local_ip);
|
||||||
|
g_free (data->hostname);
|
||||||
|
g_free (data->proxy_hostname);
|
||||||
|
g_free (data->ip);
|
||||||
|
g_free (data->port);
|
||||||
|
g_free (data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
server_connect_finish (GObject *source, GAsyncResult *res, gpointer user_data)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
server *serv;
|
||||||
|
session *sess;
|
||||||
|
struct connect_data *data;
|
||||||
|
gboolean retry = FALSE;
|
||||||
|
char buf[256];
|
||||||
|
|
||||||
|
data = (struct connect_data*)g_task_get_task_data (G_TASK(res));
|
||||||
|
serv = data->serv;
|
||||||
|
|
||||||
|
if (!is_server(serv))
|
||||||
|
{
|
||||||
|
g_warning ("Server destroyed before connection finished!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sess = serv->server_session;
|
||||||
|
|
||||||
|
/* These print after the fact, but should be good enough */
|
||||||
|
if (data->proxy_hostname)
|
||||||
|
EMIT_SIGNAL (XP_TE_SERVERLOOKUP, sess, data->proxy_hostname, NULL, NULL, NULL, 0);
|
||||||
|
|
||||||
|
EMIT_SIGNAL (XP_TE_CONNECT, sess, data->hostname, data->ip, data->port, NULL, 0);
|
||||||
|
|
||||||
|
/* Update local ip for dcc */
|
||||||
|
if (data->local_ip)
|
||||||
|
prefs.local_ip = inet_addr (data->local_ip);
|
||||||
|
|
||||||
|
serv->sok = g_task_propagate_pointer (G_TASK(res), &error);
|
||||||
|
if (!error)
|
||||||
|
{
|
||||||
|
if (serv->sok == serv->sok4)
|
||||||
|
g_object_unref (serv->sok6);
|
||||||
|
else
|
||||||
|
g_object_unref (serv->sok4);
|
||||||
|
{
|
||||||
|
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
|
||||||
|
g_strlcat (buf, prefs.hex_irc_user_name, sizeof (buf));
|
||||||
|
|
||||||
|
handle_command (serv->server_session, buf, FALSE);
|
||||||
|
}
|
||||||
|
server_connect_success (serv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_warning ("%s\n", error->message);
|
||||||
|
|
||||||
|
switch (error->code)
|
||||||
|
{
|
||||||
|
case RESOLVE_FAILED:
|
||||||
|
retry = TRUE;
|
||||||
|
EMIT_SIGNAL (XP_TE_UKNHOST, sess, NULL, NULL, NULL, NULL, 0);
|
||||||
|
goto close_connection;
|
||||||
|
case CONNECTION_FAILED:
|
||||||
|
retry = TRUE;
|
||||||
|
EMIT_SIGNAL (XP_TE_CONNFAIL, sess, error->message, NULL, NULL, NULL, 0);
|
||||||
|
goto close_connection;
|
||||||
|
case BIND_FAILED:
|
||||||
|
PrintText (sess, error->message);
|
||||||
|
break;
|
||||||
|
case PROXY_FAILED:
|
||||||
|
PrintTextf (sess, _("Proxy Traveral Failed: %s\n"), error->message);
|
||||||
|
server_disconnect (sess, FALSE, -1);
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
EMIT_SIGNAL (XP_TE_SERVERLOOKUP, sess, error->message, NULL, NULL, NULL, 0);
|
||||||
|
break;
|
||||||
|
case G_IO_ERROR_CANCELLED:
|
||||||
|
EMIT_SIGNAL (XP_TE_STOPCONNECT, sess, NULL, NULL, NULL, NULL, 0);
|
||||||
|
goto close_connection;
|
||||||
|
default:
|
||||||
|
g_warning ("%d\n", error->code);
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
close_connection:
|
||||||
|
server_stopconnecting (serv);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
server_connect_thread (GTask *task, gpointer source, gpointer task_data, GCancellable *cancellable)
|
||||||
{
|
{
|
||||||
netstore *ns_server;
|
netstore *ns_server;
|
||||||
netstore *ns_proxy = NULL;
|
struct connect_data *data = (struct connect_data*)task_data;
|
||||||
netstore *ns_local;
|
server *serv = data->serv;
|
||||||
int port = serv->port;
|
GSocket *sok = NULL, *psok;
|
||||||
int error;
|
|
||||||
int sok, psok;
|
|
||||||
char *hostname = serv->hostname;
|
|
||||||
char *real_hostname = NULL;
|
|
||||||
char *ip;
|
|
||||||
char *proxy_ip = NULL;
|
char *proxy_ip = NULL;
|
||||||
char *local_ip;
|
|
||||||
int connect_port;
|
|
||||||
char buf[512];
|
|
||||||
char bound = 0;
|
|
||||||
int proxy_type = 0;
|
int proxy_type = 0;
|
||||||
char *proxy_host = NULL;
|
char *proxy_host = NULL, *hostname;
|
||||||
int proxy_port;
|
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 ();
|
ns_server = net_store_new ();
|
||||||
|
|
||||||
/* is a hostname set? - bind to it */
|
/* Bind local address if configured */
|
||||||
if (prefs.hex_net_bind_host[0])
|
if (prefs.hex_net_bind_host[0])
|
||||||
{
|
{
|
||||||
ns_local = net_store_new ();
|
netstore *ns_local = net_store_new ();
|
||||||
local_ip = net_resolve (ns_local, prefs.hex_net_bind_host, 0, &real_hostname);
|
|
||||||
if (local_ip != NULL)
|
data->local_ip = net_resolve (ns_local, prefs.hex_net_bind_host, NULL, &err);
|
||||||
|
if (!err)
|
||||||
{
|
{
|
||||||
g_snprintf (buf, sizeof (buf), "5\n%s\n", local_ip);
|
net_bind (ns_local, serv->sok4, serv->sok6, &err4, &err6);
|
||||||
write (serv->childwrite, buf, strlen (buf));
|
if (err4 || err6)
|
||||||
net_bind (ns_local, serv->sok4, serv->sok6);
|
{
|
||||||
bound = 1;
|
net_store_destroy (ns_local);
|
||||||
} else
|
if (err4) /* TODO: could handle this better? */
|
||||||
{
|
{
|
||||||
write (serv->childwrite, "7\n", 2);
|
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_error (task, err);
|
||||||
|
net_store_destroy (ns_local);
|
||||||
|
goto error_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
net_store_destroy (ns_local);
|
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)
|
if (prefs.hex_net_proxy_type == 5)
|
||||||
{
|
{
|
||||||
char **proxy_list;
|
char *proxy;
|
||||||
char *url, *proxy;
|
|
||||||
|
|
||||||
url = g_strdup_printf ("irc://%s:%d", hostname, port);
|
proxy = net_resolve_proxy (hostname, port, &err);
|
||||||
proxy_list = px_proxy_factory_get_proxies (libproxy_factory, url);
|
if (err)
|
||||||
|
{
|
||||||
if (proxy_list) {
|
g_task_return_error (task, err);
|
||||||
/* can use only one */
|
goto error_cleanup;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (proxy_type) {
|
if (proxy)
|
||||||
char *c;
|
{
|
||||||
c = strchr (proxy, ':') + 3;
|
net_parse_proxy_uri (proxy, &proxy_host, &proxy_port, &proxy_type);
|
||||||
proxy_host = g_strdup (c);
|
g_free (proxy);
|
||||||
c = strchr (proxy_host, ':');
|
|
||||||
*c = '\0';
|
|
||||||
proxy_port = atoi (c + 1);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
g_strfreev (proxy_list);
|
proxy_type = 0;
|
||||||
g_free (url);
|
|
||||||
}
|
}
|
||||||
#endif
|
else if (prefs.hex_net_proxy_host[0])
|
||||||
if (prefs.hex_net_proxy_host[0] &&
|
|
||||||
prefs.hex_net_proxy_type > 0 &&
|
|
||||||
prefs.hex_net_proxy_use != 2) /* proxy is NOT dcc-only */
|
|
||||||
{
|
{
|
||||||
proxy_type = prefs.hex_net_proxy_type;
|
proxy_type = prefs.hex_net_proxy_type;
|
||||||
proxy_host = g_strdup (prefs.hex_net_proxy_host);
|
proxy_host = g_strdup (prefs.hex_net_proxy_host);
|
||||||
proxy_port = prefs.hex_net_proxy_port;
|
proxy_port = prefs.hex_net_proxy_port;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
data->proxy_hostname = proxy_host;
|
||||||
|
|
||||||
serv->proxy_type = proxy_type;
|
|
||||||
|
|
||||||
/* first resolve where we want to connect to */
|
|
||||||
if (proxy_type > 0)
|
if (proxy_type > 0)
|
||||||
{
|
{
|
||||||
g_snprintf (buf, sizeof (buf), "9\n%s\n", proxy_host);
|
data->ip = net_resolve (ns_server, proxy_host, &data->hostname, &err);
|
||||||
write (serv->childwrite, buf, strlen (buf));
|
if (!data->ip)
|
||||||
ip = net_resolve (ns_server, proxy_host, proxy_port, &real_hostname);
|
|
||||||
g_free (proxy_host);
|
|
||||||
if (!ip)
|
|
||||||
{
|
{
|
||||||
write (serv->childwrite, "1\n", 2);
|
g_task_return_error (task, err);
|
||||||
goto xit;
|
goto error_cleanup;
|
||||||
}
|
}
|
||||||
connect_port = proxy_port;
|
connect_port = proxy_port;
|
||||||
|
|
||||||
/* if using socks4 or MS Proxy, attempt to resolve ip for irc server */
|
/* if using socks4, attempt to resolve ip for irc server */
|
||||||
if ((proxy_type == 2) || (proxy_type == 5))
|
if (proxy_type == 2)
|
||||||
{
|
{
|
||||||
ns_proxy = net_store_new ();
|
netstore *ns_proxy = net_store_new ();
|
||||||
proxy_ip = net_resolve (ns_proxy, hostname, port, &real_hostname);
|
g_free (data->hostname);
|
||||||
if (!proxy_ip)
|
proxy_ip = net_resolve (ns_proxy, hostname, &data->hostname, &err);
|
||||||
|
net_store_destroy (ns_proxy);
|
||||||
|
if (err)
|
||||||
{
|
{
|
||||||
write (serv->childwrite, "1\n", 2);
|
g_task_return_error (task, err);
|
||||||
goto xit;
|
goto error_cleanup;
|
||||||
}
|
}
|
||||||
} else /* otherwise we can just use the hostname */
|
} else /* otherwise we can just use the hostname */
|
||||||
proxy_ip = g_strdup (hostname);
|
proxy_ip = g_strdup (hostname);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
ip = net_resolve (ns_server, hostname, port, &real_hostname);
|
data->ip = net_resolve (ns_server, hostname, &data->hostname, &err);
|
||||||
if (!ip)
|
if (err)
|
||||||
{
|
{
|
||||||
write (serv->childwrite, "1\n", 2);
|
g_task_return_error (task, err);
|
||||||
goto xit;
|
goto error_cleanup;
|
||||||
}
|
}
|
||||||
connect_port = port;
|
connect_port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_snprintf (buf, sizeof (buf), "3\n%s\n%s\n%d\n",
|
data->port = g_strdup_printf ("%d", connect_port);
|
||||||
real_hostname, ip, connect_port);
|
|
||||||
write (serv->childwrite, buf, strlen (buf));
|
|
||||||
|
|
||||||
if (!serv->dont_use_proxy && (proxy_type == 5))
|
if (!serv->dont_use_proxy)
|
||||||
error = net_connect (ns_server, serv->proxy_sok4, serv->proxy_sok6, &psok);
|
psok = net_connect (ns_server, connect_port, serv->sok4, serv->sok6, &err);
|
||||||
else
|
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;
|
psok = sok;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error != 0)
|
if (err)
|
||||||
{
|
{
|
||||||
g_snprintf (buf, sizeof (buf), "2\n%d\n", sock_error ());
|
g_task_return_error (task, err);
|
||||||
write (serv->childwrite, buf, strlen (buf));
|
goto error_cleanup;
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
/* connect succeeded */
|
/* connect succeeded */
|
||||||
if (proxy_ip)
|
if (proxy_ip && traverse_proxy (proxy_type, psok, proxy_ip, port, &err))
|
||||||
{
|
{
|
||||||
switch (traverse_proxy (proxy_type, serv->childwrite, psok, proxy_ip, port, ns_proxy, serv->sok4, serv->sok6, &sok, bound))
|
g_task_return_error (task, err);
|
||||||
{
|
goto error_cleanup;
|
||||||
case 0: /* success */
|
|
||||||
g_snprintf (buf, sizeof (buf), "4\n%d\n", sok); /* success */
|
|
||||||
write (serv->childwrite, buf, strlen (buf));
|
|
||||||
break;
|
|
||||||
case 1: /* socks traversal failed */
|
|
||||||
write (serv->childwrite, "8\n", 2);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
g_snprintf (buf, sizeof (buf), "4\n%d\n", sok); /* success */
|
|
||||||
write (serv->childwrite, buf, strlen (buf));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
xit:
|
error_cleanup:
|
||||||
|
|
||||||
/* this is probably not needed */
|
|
||||||
net_store_destroy (ns_server);
|
net_store_destroy (ns_server);
|
||||||
if (ns_proxy)
|
|
||||||
net_store_destroy (ns_proxy);
|
|
||||||
|
|
||||||
/* no need to free ip/real_hostname, this process is exiting */
|
|
||||||
#ifdef WIN32
|
|
||||||
/* under win32 we use a thread -> shared memory, must free! */
|
|
||||||
g_free (proxy_ip);
|
g_free (proxy_ip);
|
||||||
g_free (ip);
|
g_task_return_pointer (task, sok, g_object_unref); /* Does nothing if error'd */
|
||||||
g_free (real_hostname);
|
return;
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
/* cppcheck-suppress memleak */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
server_connect (server *serv, char *hostname, int port, int no_login)
|
server_connect (server *serv, char *hostname, int port, int no_login)
|
||||||
{
|
{
|
||||||
int pid, read_des[2];
|
|
||||||
session *sess = serv->server_session;
|
session *sess = serv->server_session;
|
||||||
|
GTask *task;
|
||||||
|
struct connect_data *data;
|
||||||
|
|
||||||
#ifdef USE_OPENSSL
|
#ifdef USE_OPENSSL
|
||||||
if (!serv->ctx && serv->use_ssl)
|
if (!serv->ctx && serv->use_ssl)
|
||||||
@ -1700,55 +1627,17 @@ server_connect (server *serv, char *hostname, int port, int no_login)
|
|||||||
fe_set_away (serv);
|
fe_set_away (serv);
|
||||||
server_flush_queue (serv);
|
server_flush_queue (serv);
|
||||||
|
|
||||||
#ifdef WIN32
|
net_sockets (&serv->sok4, &serv->sok6, NULL, NULL);
|
||||||
if (_pipe (read_des, 4096, _O_BINARY) < 0)
|
|
||||||
#else
|
|
||||||
if (pipe (read_des) < 0)
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
#ifdef __EMX__ /* os/2 */
|
|
||||||
setmode (read_des[0], O_BINARY);
|
|
||||||
setmode (read_des[1], O_BINARY);
|
|
||||||
#endif
|
|
||||||
serv->childread = read_des[0];
|
|
||||||
serv->childwrite = read_des[1];
|
|
||||||
|
|
||||||
/* create both sockets now, drop one later */
|
/* start the connection in a thread */
|
||||||
net_sockets (&serv->sok4, &serv->sok6);
|
data = g_new0 (struct connect_data, 1);
|
||||||
serv->proxy_sok4 = -1;
|
data->serv = serv;
|
||||||
serv->proxy_sok6 = -1;
|
serv->cancellable = g_cancellable_new ();
|
||||||
|
task = g_task_new (NULL, serv->cancellable, server_connect_finish, NULL);
|
||||||
#ifdef WIN32
|
g_task_set_task_data (task, data, (GDestroyNotify)connect_data_free);
|
||||||
CloseHandle (CreateThread (NULL, 0,
|
g_task_set_return_on_cancel (task, TRUE);
|
||||||
(LPTHREAD_START_ROUTINE)server_child,
|
g_task_run_in_thread (task, server_connect_thread);
|
||||||
serv, 0, (DWORD *)&pid));
|
g_object_unref (task);
|
||||||
#else
|
|
||||||
#ifdef LOOKUPD
|
|
||||||
/* CL: net_resolve calls rand() when LOOKUPD is set, so prepare a different
|
|
||||||
* seed for each child. This method gives a bigger variation in seed values
|
|
||||||
* than calling srand(time(0)) in the child itself.
|
|
||||||
*/
|
|
||||||
rand();
|
|
||||||
#endif
|
|
||||||
switch (pid = fork ())
|
|
||||||
{
|
|
||||||
case -1:
|
|
||||||
return;
|
|
||||||
|
|
||||||
case 0:
|
|
||||||
/* this is the child */
|
|
||||||
setuid (getuid ());
|
|
||||||
server_child (serv);
|
|
||||||
_exit (0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
serv->childpid = pid;
|
|
||||||
#ifdef WIN32
|
|
||||||
serv->iotag = fe_input_add (serv->childread, FIA_READ|FIA_FD, server_read_child,
|
|
||||||
#else
|
|
||||||
serv->iotag = fe_input_add (serv->childread, FIA_READ, server_read_child,
|
|
||||||
#endif
|
|
||||||
serv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1807,7 +1696,6 @@ server_new (void)
|
|||||||
server_fill_her_up (serv);
|
server_fill_her_up (serv);
|
||||||
|
|
||||||
serv->id = id++;
|
serv->id = id++;
|
||||||
serv->sok = -1;
|
|
||||||
strcpy (serv->nick, prefs.hex_irc_nick1);
|
strcpy (serv->nick, prefs.hex_irc_nick1);
|
||||||
server_set_defaults (serv);
|
server_set_defaults (serv);
|
||||||
|
|
||||||
|
@ -751,8 +751,8 @@ n2
|
|||||||
Stop Connection
|
Stop Connection
|
||||||
XP_TE_STOPCONNECT
|
XP_TE_STOPCONNECT
|
||||||
pevt_sconnect_help
|
pevt_sconnect_help
|
||||||
%C23*%O$tStopped previous connection attempt (%C24$1%O)
|
%C23*%O$tStopped previous connection attempt
|
||||||
1
|
0
|
||||||
|
|
||||||
Topic
|
Topic
|
||||||
XP_TE_TOPIC
|
XP_TE_TOPIC
|
||||||
|
@ -207,34 +207,6 @@ waitline (int sok, char *buf, int bufsize, int use_recv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
/* waitline2 using win32 file descriptor and glib instead of _read. win32 can't _read() sok! */
|
|
||||||
int
|
|
||||||
waitline2 (GIOChannel *source, char *buf, int bufsize)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
gsize len;
|
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
g_io_channel_set_buffered (source, FALSE);
|
|
||||||
g_io_channel_set_encoding (source, NULL, &error);
|
|
||||||
|
|
||||||
if (g_io_channel_read_chars (source, &buf[i], 1, &len, &error) != G_IO_STATUS_NORMAL)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (buf[i] == '\n' || bufsize == i + 1)
|
|
||||||
{
|
|
||||||
buf[i] = 0;
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* checks for "~" in a file and expands */
|
/* checks for "~" in a file and expands */
|
||||||
|
|
||||||
char *
|
char *
|
||||||
|
@ -61,10 +61,7 @@ int strip_hidden_attribute (char *src, char *dst);
|
|||||||
char *errorstring (int err);
|
char *errorstring (int err);
|
||||||
int waitline (int sok, char *buf, int bufsize, int);
|
int waitline (int sok, char *buf, int bufsize, int);
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
int waitline2 (GIOChannel *source, char *buf, int bufsize);
|
|
||||||
int get_cpu_arch (void);
|
int get_cpu_arch (void);
|
||||||
#else
|
|
||||||
#define waitline2(source,buf,size) waitline(serv->childread,buf,size,0)
|
|
||||||
#endif
|
#endif
|
||||||
unsigned long make_ping_time (void);
|
unsigned long make_ping_time (void);
|
||||||
void move_file (char *src_dir, char *dst_dir, char *fname, int dccpermissions);
|
void move_file (char *src_dir, char *dst_dir, char *fname, int dccpermissions);
|
||||||
|
@ -560,9 +560,7 @@ static const char *const proxytypes[] =
|
|||||||
N_("Socks4"),
|
N_("Socks4"),
|
||||||
N_("Socks5"),
|
N_("Socks5"),
|
||||||
N_("HTTP"),
|
N_("HTTP"),
|
||||||
#ifdef USE_LIBPROXY
|
|
||||||
N_("Auto"),
|
N_("Auto"),
|
||||||
#endif
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user