mirror of
https://github.com/irssi/irssi.git
synced 2024-12-04 14:46:39 -05:00
net_connect*() contains now error parameter, so it can be used to properly
check the errno if connect() fails. Added support for connecting to named UNIX sockets. Some cleanups with session handling / server connecting as well. git-svn-id: http://svn.irssi.org/repos/irssi/trunk@2819 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
parent
7437bbea5f
commit
6f7485b8fa
@ -80,6 +80,9 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strchr(addr, '/') != NULL)
|
||||
conn->unix_socket = TRUE;
|
||||
|
||||
if (g_hash_table_lookup(optlist, "6") != NULL)
|
||||
conn->family = AF_INET6;
|
||||
else if (g_hash_table_lookup(optlist, "4") != NULL)
|
||||
|
@ -118,8 +118,7 @@ static void sig_connected(SERVER_REC *server)
|
||||
|
||||
g_return_if_fail(IS_SERVER(server));
|
||||
|
||||
if (server->connrec->chatnet == NULL ||
|
||||
server->session_reconnect)
|
||||
if (server->connrec->chatnet == NULL || server->session_reconnect)
|
||||
return;
|
||||
|
||||
rec = chatnet_find(server->connrec->chatnet);
|
||||
|
@ -187,6 +187,7 @@ static void simple_readpipe(SIMPLE_THREAD_REC *rec, GIOChannel *pipe)
|
||||
RESOLVED_IP_REC iprec;
|
||||
GIOChannel *handle;
|
||||
IPADDR *ip;
|
||||
int error;
|
||||
|
||||
g_return_if_fail(rec != NULL);
|
||||
|
||||
@ -202,7 +203,7 @@ static void simple_readpipe(SIMPLE_THREAD_REC *rec, GIOChannel *pipe)
|
||||
|
||||
ip = iprec.ip4.family != 0 ? &iprec.ip4 : &iprec.ip6;
|
||||
handle = iprec.error == -1 ? NULL :
|
||||
net_connect_ip(ip, rec->port, rec->my_ip);
|
||||
net_connect_ip(ip, rec->port, rec->my_ip, &error);
|
||||
|
||||
g_free_not_null(rec->my_ip);
|
||||
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include "module.h"
|
||||
#include "network.h"
|
||||
|
||||
#include <sys/un.h>
|
||||
|
||||
#ifndef INADDR_NONE
|
||||
# define INADDR_NONE INADDR_BROADCAST
|
||||
#endif
|
||||
@ -133,7 +135,7 @@ int sin_get_port(union sockaddr_union *so)
|
||||
}
|
||||
|
||||
/* Connect to socket */
|
||||
GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip)
|
||||
GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip, int *error)
|
||||
{
|
||||
IPADDR ip4, ip6, *ip;
|
||||
int family;
|
||||
@ -141,8 +143,11 @@ GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip)
|
||||
g_return_val_if_fail(addr != NULL, NULL);
|
||||
|
||||
family = my_ip == NULL ? 0 : my_ip->family;
|
||||
if (net_gethostbyname(addr, &ip4, &ip6) == -1)
|
||||
if (net_gethostbyname(addr, &ip4, &ip6) == -1) {
|
||||
if (error != NULL)
|
||||
*error = errno;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (my_ip == NULL) {
|
||||
/* prefer IPv4 addresses */
|
||||
@ -165,11 +170,11 @@ GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip)
|
||||
}
|
||||
}
|
||||
|
||||
return net_connect_ip(ip, port, my_ip);
|
||||
return net_connect_ip(ip, port, my_ip, error);
|
||||
}
|
||||
|
||||
/* Connect to socket with ip address */
|
||||
GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip)
|
||||
GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip, int *error)
|
||||
{
|
||||
union sockaddr_union so;
|
||||
int handle, ret, opt = 1;
|
||||
@ -184,8 +189,11 @@ GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip)
|
||||
so.sin.sin_family = ip->family;
|
||||
handle = socket(ip->family, SOCK_STREAM, 0);
|
||||
|
||||
if (handle == -1)
|
||||
if (handle == -1) {
|
||||
if (error != NULL)
|
||||
*error = errno;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* set socket options */
|
||||
#ifndef WIN32
|
||||
@ -217,6 +225,44 @@ GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip)
|
||||
if (ret < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
|
||||
#endif
|
||||
{
|
||||
if (error != NULL)
|
||||
*error = errno;
|
||||
close(handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return g_io_channel_new(handle);
|
||||
}
|
||||
|
||||
/* Connect to named UNIX socket */
|
||||
GIOChannel *net_connect_unix(const char *path, int *error)
|
||||
{
|
||||
struct sockaddr_un sa;
|
||||
int handle, ret;
|
||||
|
||||
/* create the socket */
|
||||
handle = socket(PF_UNIX, SOCK_STREAM, 0);
|
||||
if (handle == -1) {
|
||||
if (error != NULL)
|
||||
*error = errno;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* set socket options */
|
||||
#ifndef WIN32
|
||||
fcntl(handle, F_SETFL, O_NONBLOCK);
|
||||
#endif
|
||||
|
||||
/* connect */
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sun_family = AF_UNIX;
|
||||
strncpy(sa.sun_path, path, sizeof(sa.sun_path)-1);
|
||||
sa.sun_path[sizeof(sa.sun_path)-1] = '\0';
|
||||
|
||||
ret = connect(handle, (struct sockaddr *) &sa, sizeof(sa));
|
||||
if (ret < 0 && errno != EINPROGRESS) {
|
||||
if (error != NULL)
|
||||
*error = errno;
|
||||
close(handle);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -43,9 +43,11 @@ struct _IPADDR {
|
||||
int net_ip_compare(IPADDR *ip1, IPADDR *ip2);
|
||||
|
||||
/* Connect to socket */
|
||||
GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip);
|
||||
GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip, int *error);
|
||||
/* Connect to socket with ip address */
|
||||
GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip);
|
||||
GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip, int *error);
|
||||
/* Connect to named UNIX socket */
|
||||
GIOChannel *net_connect_unix(const char *path, int *error);
|
||||
/* Disconnect socket */
|
||||
void net_disconnect(GIOChannel *handle);
|
||||
/* Try to let the other side close the connection, if it still isn't
|
||||
|
@ -23,8 +23,12 @@ char *nick;
|
||||
char *username;
|
||||
char *realname;
|
||||
|
||||
GIOChannel *connect_handle; /* connect using this handle */
|
||||
|
||||
/* when reconnecting, the old server status */
|
||||
unsigned int reconnection:1; /* we're trying to reconnect */
|
||||
unsigned int no_autojoin_channels:1; /* don't autojoin any channels */
|
||||
unsigned int unix_socket:1; /* Connect using named unix socket */
|
||||
unsigned int session_reconnect:1; /* Connected to this server with /UPGRADE */
|
||||
char *channels;
|
||||
char *away_reason;
|
||||
|
@ -161,16 +161,47 @@ static void server_connect_callback_init(SERVER_REC *server, GIOChannel *handle)
|
||||
server_connect_finished(server);
|
||||
}
|
||||
|
||||
static void server_real_connect(SERVER_REC *server, IPADDR *ip,
|
||||
const char *unix_socket)
|
||||
{
|
||||
GIOChannel *handle;
|
||||
IPADDR *own_ip;
|
||||
int port, error;
|
||||
|
||||
g_return_if_fail(ip != NULL || unix_socket != NULL);
|
||||
|
||||
signal_emit("server connecting", 2, server, ip);
|
||||
|
||||
if (ip != NULL) {
|
||||
own_ip = ip == NULL ? NULL :
|
||||
(IPADDR_IS_V6(ip) ? server->connrec->own_ip6 :
|
||||
server->connrec->own_ip4);
|
||||
port = server->connrec->proxy != NULL ?
|
||||
server->connrec->proxy_port : server->connrec->port;
|
||||
handle = net_connect_ip(ip, port, own_ip, &error);
|
||||
} else {
|
||||
handle = net_connect_unix(unix_socket, &error);
|
||||
}
|
||||
|
||||
if (handle == NULL) {
|
||||
/* failed */
|
||||
server->connection_lost = TRUE;
|
||||
server_connect_failed(server, g_strerror(error));
|
||||
} else {
|
||||
server->handle = net_sendbuffer_create(handle, 0);
|
||||
server->connect_tag =
|
||||
g_input_add(handle, G_INPUT_WRITE | G_INPUT_READ,
|
||||
(GInputFunction)
|
||||
server_connect_callback_init,
|
||||
server);
|
||||
}
|
||||
}
|
||||
|
||||
static void server_connect_callback_readpipe(SERVER_REC *server)
|
||||
{
|
||||
SERVER_CONNECT_REC *conn;
|
||||
RESOLVED_IP_REC iprec;
|
||||
GIOChannel *handle;
|
||||
IPADDR *ip, *own_ip;
|
||||
IPADDR *ip;
|
||||
const char *errormsg;
|
||||
int port;
|
||||
|
||||
g_return_if_fail(IS_SERVER(server));
|
||||
|
||||
g_source_remove(server->connect_tag);
|
||||
server->connect_tag = -1;
|
||||
@ -204,33 +235,18 @@ static void server_connect_callback_readpipe(SERVER_REC *server)
|
||||
&iprec.ip6 : &iprec.ip4;
|
||||
}
|
||||
|
||||
conn = server->connrec;
|
||||
port = conn->proxy != NULL ? conn->proxy_port : conn->port;
|
||||
own_ip = ip == NULL ? NULL :
|
||||
(IPADDR_IS_V6(ip) ? conn->own_ip6 : conn->own_ip4);
|
||||
|
||||
handle = NULL;
|
||||
if (ip != NULL) {
|
||||
signal_emit("server connecting", 2, server, ip);
|
||||
if (server->handle == NULL)
|
||||
handle = net_connect_ip(ip, port, own_ip);
|
||||
else
|
||||
handle = net_sendbuffer_handle(server->handle);
|
||||
}
|
||||
|
||||
if (handle == NULL) {
|
||||
/* failed */
|
||||
if (ip == NULL && (iprec.error == 0 ||
|
||||
net_hosterror_notfound(iprec.error))) {
|
||||
/* IP wasn't found for the host, don't try to reconnect
|
||||
back to this server */
|
||||
/* host lookup ok */
|
||||
server_real_connect(server, ip, NULL);
|
||||
errormsg = NULL;
|
||||
} else {
|
||||
if (iprec.error == 0 || net_hosterror_notfound(iprec.error)) {
|
||||
/* IP wasn't found for the host, don't try to
|
||||
reconnect back to this server */
|
||||
server->dns_error = TRUE;
|
||||
}
|
||||
|
||||
if (ip != NULL) {
|
||||
/* connect() failed */
|
||||
errormsg = g_strerror(errno);
|
||||
} else if (iprec.error == 0) {
|
||||
if (iprec.error == 0) {
|
||||
/* forced IPv4 or IPv6 address but it wasn't found */
|
||||
errormsg = server->connrec->family == AF_INET ?
|
||||
"IPv4 address not found for host" :
|
||||
@ -240,18 +256,12 @@ static void server_connect_callback_readpipe(SERVER_REC *server)
|
||||
errormsg = iprec.errorstr != NULL ? iprec.errorstr :
|
||||
"Host lookup failed";
|
||||
}
|
||||
|
||||
server->connection_lost = TRUE;
|
||||
server_connect_failed(server, errormsg);
|
||||
g_free_not_null(iprec.errorstr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (server->handle == NULL)
|
||||
server->handle = net_sendbuffer_create(handle, 0);
|
||||
server->connect_tag =
|
||||
g_input_add(handle, G_INPUT_WRITE | G_INPUT_READ,
|
||||
(GInputFunction) server_connect_callback_init,
|
||||
server);
|
||||
g_free(iprec.errorstr);
|
||||
}
|
||||
|
||||
/* initializes server record but doesn't start connecting */
|
||||
@ -282,6 +292,7 @@ void server_connect_init(SERVER_REC *server)
|
||||
}
|
||||
|
||||
server->tag = server_create_tag(server->connrec);
|
||||
server->connect_tag = -1;
|
||||
}
|
||||
|
||||
/* starts connecting to server */
|
||||
@ -291,10 +302,31 @@ int server_start_connect(SERVER_REC *server)
|
||||
int fd[2];
|
||||
|
||||
g_return_val_if_fail(server != NULL, FALSE);
|
||||
if (server->connrec->port <= 0) return FALSE;
|
||||
if (!server->connrec->unix_socket && server->connrec->port <= 0)
|
||||
return FALSE;
|
||||
|
||||
server_connect_init(server);
|
||||
server->rawlog = rawlog_create();
|
||||
|
||||
if (server->connrec->session_reconnect) {
|
||||
/* /UPGRADE connection - the session_connect is meant
|
||||
for us only once, move it into server->session_connect */
|
||||
server->connrec->session_reconnect = FALSE;
|
||||
server->session_reconnect = TRUE;
|
||||
}
|
||||
|
||||
if (server->connrec->connect_handle != NULL) {
|
||||
/* already connected */
|
||||
GIOChannel *handle = server->connrec->connect_handle;
|
||||
|
||||
server->connrec->connect_handle = NULL;
|
||||
server->handle = net_sendbuffer_create(handle, 0);
|
||||
server_connect_finished(server);
|
||||
} else if (server->connrec->unix_socket) {
|
||||
/* connect with unix socket */
|
||||
server_real_connect(server, NULL, server->connrec->address);
|
||||
} else {
|
||||
/* resolve host name */
|
||||
if (pipe(fd) != 0) {
|
||||
g_warning("server_connect(): pipe() failed.");
|
||||
g_free(server->tag);
|
||||
@ -312,13 +344,14 @@ int server_start_connect(SERVER_REC *server)
|
||||
server->connect_pipe[1]);
|
||||
server->connect_tag =
|
||||
g_input_add(server->connect_pipe[0], G_INPUT_READ,
|
||||
(GInputFunction) server_connect_callback_readpipe,
|
||||
(GInputFunction)
|
||||
server_connect_callback_readpipe,
|
||||
server);
|
||||
server->rawlog = rawlog_create();
|
||||
|
||||
lookup_servers = g_slist_append(lookup_servers, server);
|
||||
|
||||
signal_emit("server looking", 1, server);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -486,6 +519,9 @@ void server_connect_unref(SERVER_CONNECT_REC *conn)
|
||||
|
||||
CHAT_PROTOCOL(conn)->destroy_server_connect(conn);
|
||||
|
||||
if (conn->connect_handle != NULL)
|
||||
net_disconnect(conn->connect_handle);
|
||||
|
||||
g_free_not_null(conn->proxy);
|
||||
g_free_not_null(conn->proxy_string);
|
||||
g_free_not_null(conn->proxy_string_after);
|
||||
|
@ -276,11 +276,10 @@ static void session_restore_server(CONFIG_NODE *node)
|
||||
chatnet, password, nick);
|
||||
if (conn != NULL) {
|
||||
conn->reconnection = TRUE;
|
||||
conn->connect_handle = g_io_channel_unix_new(handle);
|
||||
conn->session_reconnect = TRUE;
|
||||
|
||||
server = proto->server_connect(conn);
|
||||
server->handle = net_sendbuffer_create(g_io_channel_unix_new(handle), 0);
|
||||
server->session_reconnect = TRUE;
|
||||
|
||||
signal_emit("session restore server", 2, server, node);
|
||||
}
|
||||
}
|
||||
|
@ -238,9 +238,12 @@ static void sig_server_connecting(SERVER_REC *server, IPADDR *ip)
|
||||
char ipaddr[MAX_IP_LEN];
|
||||
|
||||
g_return_if_fail(server != NULL);
|
||||
g_return_if_fail(ip != NULL);
|
||||
|
||||
if (ip == NULL)
|
||||
ipaddr[0] = '\0';
|
||||
else
|
||||
net_ip2host(ip, ipaddr);
|
||||
|
||||
printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, TXT_CONNECTING,
|
||||
server->connrec->address, ipaddr, server->connrec->port);
|
||||
}
|
||||
|
@ -610,6 +610,7 @@ void windows_init(void)
|
||||
|
||||
read_settings();
|
||||
signal_add("server looking", (SIGNAL_FUNC) sig_server_looking);
|
||||
signal_add("server connected", (SIGNAL_FUNC) sig_server_looking);
|
||||
signal_add("server disconnected", (SIGNAL_FUNC) sig_server_disconnected);
|
||||
signal_add("server connect failed", (SIGNAL_FUNC) sig_server_disconnected);
|
||||
signal_add("setup changed", (SIGNAL_FUNC) read_settings);
|
||||
@ -621,6 +622,7 @@ void windows_deinit(void)
|
||||
if (daycheck == 1) signal_remove("print text", (SIGNAL_FUNC) sig_print_text);
|
||||
|
||||
signal_remove("server looking", (SIGNAL_FUNC) sig_server_looking);
|
||||
signal_remove("server connected", (SIGNAL_FUNC) sig_server_looking);
|
||||
signal_remove("server disconnected", (SIGNAL_FUNC) sig_server_disconnected);
|
||||
signal_remove("server connect failed", (SIGNAL_FUNC) sig_server_disconnected);
|
||||
signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
|
||||
|
@ -160,7 +160,7 @@ static CHANNEL_REC *irc_channel_find_server(SERVER_REC *server,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void sig_server_looking(SERVER_REC *server)
|
||||
static void sig_server_connected(SERVER_REC *server)
|
||||
{
|
||||
if (!IS_IRC_SERVER(server))
|
||||
return;
|
||||
@ -198,7 +198,7 @@ static void sig_channel_destroyed(IRC_CHANNEL_REC *channel)
|
||||
|
||||
void irc_channels_init(void)
|
||||
{
|
||||
signal_add("server looking", (SIGNAL_FUNC) sig_server_looking);
|
||||
signal_add_first("server connected", (SIGNAL_FUNC) sig_server_connected);
|
||||
signal_add("channel created", (SIGNAL_FUNC) sig_channel_created);
|
||||
signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
|
||||
|
||||
@ -216,7 +216,7 @@ void irc_channels_init(void)
|
||||
|
||||
void irc_channels_deinit(void)
|
||||
{
|
||||
signal_remove("server looking", (SIGNAL_FUNC) sig_server_looking);
|
||||
signal_remove("server connected", (SIGNAL_FUNC) sig_server_connected);
|
||||
signal_remove("channel created", (SIGNAL_FUNC) sig_channel_created);
|
||||
signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
|
||||
|
||||
|
@ -87,16 +87,6 @@ static void send_message(SERVER_REC *server, const char *target,
|
||||
g_free(str);
|
||||
}
|
||||
|
||||
static void sig_server_looking(IRC_SERVER_REC *server)
|
||||
{
|
||||
if (!IS_IRC_SERVER(server))
|
||||
return;
|
||||
|
||||
server->isnickflag = isnickflag_func;
|
||||
server->ischannel = ischannel_func;
|
||||
server->send_message = send_message;
|
||||
}
|
||||
|
||||
static void server_init(IRC_SERVER_REC *server)
|
||||
{
|
||||
IRC_SERVER_CONNECT_REC *conn;
|
||||
@ -256,7 +246,12 @@ static void sig_connected(IRC_SERVER_REC *server)
|
||||
if (!IS_IRC_SERVER(server))
|
||||
return;
|
||||
|
||||
server->splits = g_hash_table_new((GHashFunc) g_istr_hash, (GCompareFunc) g_istr_equal);
|
||||
server->isnickflag = isnickflag_func;
|
||||
server->ischannel = ischannel_func;
|
||||
server->send_message = send_message;
|
||||
|
||||
server->splits = g_hash_table_new((GHashFunc) g_istr_hash,
|
||||
(GCompareFunc) g_istr_equal);
|
||||
|
||||
if (!server->session_reconnect)
|
||||
server_init(server);
|
||||
@ -575,7 +570,6 @@ void irc_servers_init(void)
|
||||
|
||||
cmd_tag = g_timeout_add(500, (GSourceFunc) servers_cmd_timeout, NULL);
|
||||
|
||||
signal_add_first("server looking", (SIGNAL_FUNC) sig_server_looking);
|
||||
signal_add_first("server connected", (SIGNAL_FUNC) sig_connected);
|
||||
signal_add_last("server disconnected", (SIGNAL_FUNC) sig_disconnected);
|
||||
signal_add_last("server quit", (SIGNAL_FUNC) sig_server_quit);
|
||||
@ -598,7 +592,6 @@ void irc_servers_deinit(void)
|
||||
{
|
||||
g_source_remove(cmd_tag);
|
||||
|
||||
signal_remove("server looking", (SIGNAL_FUNC) sig_server_looking);
|
||||
signal_remove("server connected", (SIGNAL_FUNC) sig_connected);
|
||||
signal_remove("server disconnected", (SIGNAL_FUNC) sig_disconnected);
|
||||
signal_remove("server quit", (SIGNAL_FUNC) sig_server_quit);
|
||||
|
@ -247,7 +247,7 @@ GIOChannel *dcc_connect_ip(IPADDR *ip, int port)
|
||||
own_ip = &temp_ip;
|
||||
}
|
||||
|
||||
return net_connect_ip(ip, port, own_ip);
|
||||
return net_connect_ip(ip, port, own_ip, NULL);
|
||||
}
|
||||
|
||||
/* Server connected - update server for DCC records that have
|
||||
|
Loading…
Reference in New Issue
Block a user