Use GIOChannel instead of sockets directly. Helps porting to win32 :)

git-svn-id: http://svn.irssi.org/repos/irssi/trunk@962 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
Timo Sirainen 2000-12-04 22:57:18 +00:00 committed by cras
commit 1c9f45b4a4
16 changed files with 223 additions and 202 deletions

View file

@ -29,15 +29,49 @@ typedef struct {
NET_CALLBACK func;
void *data;
int pipes[2];
GIOChannel *pipes[2];
int port;
IPADDR *my_ip;
int tag;
} SIMPLE_THREAD_REC;
#define is_fatal_error(err) \
(err != 0 && err != G_IO_ERROR_AGAIN && errno != EINTR)
static int g_io_channel_write_block(GIOChannel *channel, void *data, int len)
{
int err, ret, sent;
sent = 0;
do {
err = g_io_channel_write(channel, (char *) data + sent,
len-sent, &ret);
sent += ret;
} while (ret < len && !is_fatal_error(err));
return err != 0 ? -1 : 0;
}
static int g_io_channel_read_block(GIOChannel *channel, void *data, int len)
{
time_t maxwait;
int err, ret, received;
maxwait = time(NULL)+2;
received = 0;
do {
err = g_io_channel_read(channel, (char *) data + received,
len-received, &ret);
received += ret;
} while (received < len && time(NULL) < maxwait &&
(ret != 0 || !is_fatal_error(err)));
return received < len ? -1 : 0;
}
/* nonblocking gethostbyname(), ip (IPADDR) + error (int, 0 = not error) is
written to pipe when found PID of the resolver child is returned */
int net_gethostbyname_nonblock(const char *addr, int pipe)
int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe)
{
RESOLVED_IP_REC rec;
const char *errorstr;
@ -72,9 +106,9 @@ int net_gethostbyname_nonblock(const char *addr, int pipe)
rec.errlen = strlen(errorstr)+1;
}
write(pipe, &rec, sizeof(rec));
g_io_channel_write_block(pipe, &rec, sizeof(rec));
if (rec.error != 0)
write(pipe, errorstr, rec.errlen);
g_io_channel_write_block(pipe, (void *) errorstr, rec.errlen);
#ifndef WIN32
if (pid == 0)
@ -86,45 +120,24 @@ int net_gethostbyname_nonblock(const char *addr, int pipe)
}
/* get the resolved IP address */
int net_gethostbyname_return(int pipe, RESOLVED_IP_REC *rec)
int net_gethostbyname_return(GIOChannel *pipe, RESOLVED_IP_REC *rec)
{
time_t maxwait;
int len, ret;
rec->error = -1;
rec->errorstr = NULL;
/* get ip+error - try for max. 1-2 seconds */
#ifndef WIN32
fcntl(pipe, F_SETFL, O_NONBLOCK);
fcntl(g_io_channel_unix_get_fd(pipe), F_SETFL, O_NONBLOCK);
#endif
maxwait = time(NULL)+2;
len = 0;
do {
ret = read(pipe, (char *) rec+len, sizeof(*rec)-len);
if (ret == -1) return -1;
len += ret;
} while (len < sizeof(*rec) && time(NULL) < maxwait);
if (len < sizeof(*rec))
return -1; /* timeout */
if (g_io_channel_read_block(pipe, rec, sizeof(*rec)) == -1)
return -1;
if (rec->error) {
/* read error string */
rec->errorstr = g_malloc(rec->errlen+1);
len = 0;
do {
ret = read(pipe, rec->errorstr+len, rec->errlen-len);
if (ret == -1) break;
len += ret;
} while (len < rec->errlen && time(NULL) < maxwait);
if (len < rec->errlen) {
/* just ignore the rest of the error message.. */
rec->errorstr[len] = '\0';
}
/* read error string, if we can't read everything for some
reason, just ignore it. */
rec->errorstr = g_malloc0(rec->errlen+1);
g_io_channel_read_block(pipe, rec->errorstr, rec->errlen);
}
return 0;
@ -133,7 +146,7 @@ int net_gethostbyname_return(int pipe, RESOLVED_IP_REC *rec)
/* Get host name, call func when finished */
int net_gethostbyaddr_nonblock(IPADDR *ip, NET_HOST_CALLBACK func, void *data)
{
/*FIXME*/
/* FIXME: not implemented */
return FALSE;
}
@ -147,7 +160,7 @@ void net_disconnect_nonblock(int pid)
#endif
}
static void simple_init(SIMPLE_THREAD_REC *rec, int handle)
static void simple_init(SIMPLE_THREAD_REC *rec, GIOChannel *handle)
{
g_return_if_fail(rec != NULL);
@ -155,18 +168,19 @@ static void simple_init(SIMPLE_THREAD_REC *rec, int handle)
if (net_geterror(handle) != 0) {
/* failed */
close(handle);
handle = -1;
g_io_channel_close(handle);
g_io_channel_unref(handle);
handle = NULL;
}
rec->func(handle, rec->data);
g_free(rec);
}
static void simple_readpipe(SIMPLE_THREAD_REC *rec, int pipe)
static void simple_readpipe(SIMPLE_THREAD_REC *rec, GIOChannel *pipe)
{
RESOLVED_IP_REC iprec;
int handle;
GIOChannel *handle;
g_return_if_fail(rec != NULL);
@ -175,17 +189,19 @@ static void simple_readpipe(SIMPLE_THREAD_REC *rec, int pipe)
net_gethostbyname_return(pipe, &iprec);
g_free_not_null(iprec.errorstr);
close(rec->pipes[0]);
close(rec->pipes[1]);
g_io_channel_close(rec->pipes[0]);
g_io_channel_unref(rec->pipes[0]);
g_io_channel_close(rec->pipes[1]);
g_io_channel_unref(rec->pipes[1]);
handle = iprec.error == -1 ? -1 :
handle = iprec.error == -1 ? NULL :
net_connect_ip(&iprec.ip, rec->port, rec->my_ip);
g_free_not_null(rec->my_ip);
if (handle == -1) {
if (handle == NULL) {
/* failed */
rec->func(-1, rec->data);
rec->func(NULL, rec->data);
g_free(rec);
return;
}
@ -209,9 +225,6 @@ int net_connect_nonblock(const char *server, int port, const IPADDR *my_ip,
return FALSE;
}
/* start nonblocking host name lookup */
net_gethostbyname_nonblock(server, fd[1]);
rec = g_new0(SIMPLE_THREAD_REC, 1);
rec->port = port;
if (my_ip != NULL) {
@ -220,10 +233,13 @@ int net_connect_nonblock(const char *server, int port, const IPADDR *my_ip,
}
rec->func = func;
rec->data = data;
rec->pipes[0] = fd[0];
rec->pipes[1] = fd[1];
rec->tag = g_input_add(fd[0], G_INPUT_READ,
rec->pipes[0] = g_io_channel_unix_new(fd[0]);
rec->pipes[1] = g_io_channel_unix_new(fd[1]);
/* start nonblocking host name lookup */
net_gethostbyname_nonblock(server, rec->pipes[1]);
rec->tag = g_input_add(rec->pipes[0], G_INPUT_READ,
(GInputFunction) simple_readpipe, rec);
return 1;
return TRUE;
}