diff options
author | Timo Sirainen <cras@irssi.org> | 2000-12-04 22:57:18 +0000 |
---|---|---|
committer | cras <cras@dbcabf3a-b0e7-0310-adc4-f8d773084564> | 2000-12-04 22:57:18 +0000 |
commit | 1c9f45b4a41e5553c89393cd3228b8e8e9d6131b (patch) | |
tree | 2431f899730d091c2185e651184693d5f1853dce /src/core/net-nonblock.c | |
parent | e81fdd730752012a3b34af443226f50d4771cc54 (diff) | |
download | irssi-1c9f45b4a41e5553c89393cd3228b8e8e9d6131b.zip |
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
Diffstat (limited to 'src/core/net-nonblock.c')
-rw-r--r-- | src/core/net-nonblock.c | 118 |
1 files changed, 67 insertions, 51 deletions
diff --git a/src/core/net-nonblock.c b/src/core/net-nonblock.c index c6342e08..e1d99fd8 100644 --- a/src/core/net-nonblock.c +++ b/src/core/net-nonblock.c @@ -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; } |