1
0
mirror of https://github.com/irssi/irssi.git synced 2024-06-30 06:45:25 +00:00

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
parent e81fdd7307
commit 1c9f45b4a4
16 changed files with 224 additions and 203 deletions

View File

@ -53,11 +53,11 @@
#define G_INPUT_READ (1 << 0) #define G_INPUT_READ (1 << 0)
#define G_INPUT_WRITE (1 << 1) #define G_INPUT_WRITE (1 << 1)
typedef void (*GInputFunction) (void *data, int source, int condition); typedef void (*GInputFunction) (void *data, GIOChannel *source, int condition);
int g_input_add(int source, int condition, int g_input_add(GIOChannel *source, int condition,
GInputFunction function, void *data); GInputFunction function, void *data);
int g_input_add_full(int source, int priority, int condition, int g_input_add_full(GIOChannel *source, int priority, int condition,
GInputFunction function, void *data); GInputFunction function, void *data);
#define MAX_INT_STRLEN ((sizeof(int) * CHAR_BIT + 2) / 3 + 1) #define MAX_INT_STRLEN ((sizeof(int) * CHAR_BIT + 2) / 3 + 1)

View File

@ -52,20 +52,17 @@ static int irssi_io_invoke(GIOChannel *source, GIOCondition condition,
if (condition & G_IO_OUT) if (condition & G_IO_OUT)
icond |= G_INPUT_WRITE; icond |= G_INPUT_WRITE;
if (rec->condition & icond) { if (rec->condition & icond)
rec->function(rec->data, g_io_channel_unix_get_fd(source), rec->function(rec->data, source, icond);
icond);
}
return TRUE; return TRUE;
} }
int g_input_add_full(int source, int priority, int condition, int g_input_add_full(GIOChannel *source, int priority, int condition,
GInputFunction function, void *data) GInputFunction function, void *data)
{ {
IRSSI_INPUT_REC *rec; IRSSI_INPUT_REC *rec;
unsigned int result; unsigned int result;
GIOChannel *channel;
GIOCondition cond; GIOCondition cond;
rec = g_new(IRSSI_INPUT_REC, 1); rec = g_new(IRSSI_INPUT_REC, 1);
@ -79,15 +76,13 @@ int g_input_add_full(int source, int priority, int condition,
if (condition & G_INPUT_WRITE) if (condition & G_INPUT_WRITE)
cond |= G_IO_OUT; cond |= G_IO_OUT;
channel = g_io_channel_unix_new (source); result = g_io_add_watch_full(source, priority, cond,
result = g_io_add_watch_full(channel, priority, cond,
irssi_io_invoke, rec, g_free); irssi_io_invoke, rec, g_free);
g_io_channel_unref(channel);
return result; return result;
} }
int g_input_add(int source, int condition, int g_input_add(GIOChannel *source, int condition,
GInputFunction function, void *data) GInputFunction function, void *data)
{ {
return g_input_add_full(source, G_PRIORITY_DEFAULT, condition, return g_input_add_full(source, G_PRIORITY_DEFAULT, condition,

View File

@ -29,7 +29,7 @@
typedef struct { typedef struct {
time_t created; time_t created;
int handle; GIOChannel *handle;
int tag; int tag;
} NET_DISCONNECT_REC; } NET_DISCONNECT_REC;
@ -85,7 +85,7 @@ static int sig_timeout_disconnect(void)
/* Try to let the other side close the connection, if it still isn't /* Try to let the other side close the connection, if it still isn't
disconnected after certain amount of time, close it ourself */ disconnected after certain amount of time, close it ourself */
void net_disconnect_later(int handle) void net_disconnect_later(GIOChannel *handle)
{ {
NET_DISCONNECT_REC *rec; NET_DISCONNECT_REC *rec;
@ -114,7 +114,7 @@ void net_disconnect_deinit(void)
#ifndef WIN32 #ifndef WIN32
NET_DISCONNECT_REC *rec; NET_DISCONNECT_REC *rec;
time_t now, max; time_t now, max;
int first; int first, fd;
struct timeval tv; struct timeval tv;
fd_set set; fd_set set;
@ -131,12 +131,13 @@ void net_disconnect_deinit(void)
continue; continue;
} }
fd = g_io_channel_unix_get_fd(rec->handle);
FD_ZERO(&set); FD_ZERO(&set);
FD_SET(rec->handle, &set); FD_SET(fd, &set);
tv.tv_sec = first ? 0 : max-now; tv.tv_sec = first ? 0 : max-now;
tv.tv_usec = first ? 100000 : 0; tv.tv_usec = first ? 100000 : 0;
if (select(rec->handle+1, &set, NULL, NULL, &tv) > 0 && if (select(fd+1, &set, NULL, NULL, &tv) > 0 &&
FD_ISSET(rec->handle, &set)) { FD_ISSET(fd, &set)) {
/* data coming .. check if we can close the handle */ /* data coming .. check if we can close the handle */
sig_disconnect(rec); sig_disconnect(rec);
} else if (first) { } else if (first) {

View File

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

View File

@ -20,18 +20,19 @@ typedef struct {
char *errorstr; char *errorstr;
} RESOLVED_NAME_REC; } RESOLVED_NAME_REC;
typedef void (*NET_CALLBACK) (int, void *); typedef void (*NET_CALLBACK) (GIOChannel *, void *);
typedef void (*NET_HOST_CALLBACK) (RESOLVED_NAME_REC *, void *); typedef void (*NET_HOST_CALLBACK) (RESOLVED_NAME_REC *, void *);
/* nonblocking gethostbyname(), PID of the resolver child is returned. */ /* nonblocking gethostbyname(), 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);
/* Get host's name, call func when finished */ /* Get host's name, call func when finished */
int net_gethostbyaddr_nonblock(IPADDR *ip, NET_HOST_CALLBACK func, void *data); int net_gethostbyaddr_nonblock(IPADDR *ip, NET_HOST_CALLBACK func, void *data);
/* get the resolved IP address. returns -1 if some error occured with read() */ /* get the resolved IP address. returns -1 if some error occured with read() */
int net_gethostbyname_return(int pipe, RESOLVED_IP_REC *rec); int net_gethostbyname_return(GIOChannel *pipe, RESOLVED_IP_REC *rec);
/* Connect to server, call func when finished */ /* Connect to server, call func when finished */
int net_connect_nonblock(const char *server, int port, const IPADDR *my_ip, NET_CALLBACK func, void *data); int net_connect_nonblock(const char *server, int port, const IPADDR *my_ip,
NET_CALLBACK func, void *data);
/* Kill the resolver child */ /* Kill the resolver child */
void net_disconnect_nonblock(int pid); void net_disconnect_nonblock(int pid);

View File

@ -24,7 +24,7 @@
#include "net-sendbuffer.h" #include "net-sendbuffer.h"
struct _NET_SENDBUF_REC { struct _NET_SENDBUF_REC {
int handle; GIOChannel *handle;
int bufsize; int bufsize;
int bufpos; int bufpos;
@ -36,11 +36,11 @@ static int timeout_tag;
/* Create new buffer - if `bufsize' is zero or less, DEFAULT_BUFFER_SIZE /* Create new buffer - if `bufsize' is zero or less, DEFAULT_BUFFER_SIZE
is used */ is used */
NET_SENDBUF_REC *net_sendbuffer_create(int handle, int bufsize) NET_SENDBUF_REC *net_sendbuffer_create(GIOChannel *handle, int bufsize)
{ {
NET_SENDBUF_REC *rec; NET_SENDBUF_REC *rec;
g_return_val_if_fail(handle != -1, NULL); g_return_val_if_fail(handle != NULL, NULL);
rec = g_new0(NET_SENDBUF_REC, 1); rec = g_new0(NET_SENDBUF_REC, 1);
rec->handle = handle; rec->handle = handle;
@ -148,9 +148,9 @@ int net_sendbuffer_send(NET_SENDBUF_REC *rec, const void *data, int size)
} }
/* Returns the socket handle */ /* Returns the socket handle */
int net_sendbuffer_handle(NET_SENDBUF_REC *rec) GIOChannel *net_sendbuffer_handle(NET_SENDBUF_REC *rec)
{ {
g_return_val_if_fail(rec != NULL, -1); g_return_val_if_fail(rec != NULL, NULL);
return rec->handle; return rec->handle;
} }

View File

@ -7,7 +7,7 @@ typedef struct _NET_SENDBUF_REC NET_SENDBUF_REC;
/* Create new buffer - if `bufsize' is zero or less, DEFAULT_BUFFER_SIZE /* Create new buffer - if `bufsize' is zero or less, DEFAULT_BUFFER_SIZE
is used */ is used */
NET_SENDBUF_REC *net_sendbuffer_create(int handle, int bufsize); NET_SENDBUF_REC *net_sendbuffer_create(GIOChannel *handle, int bufsize);
/* Destroy the buffer. `close' specifies if socket handle should be closed. */ /* Destroy the buffer. `close' specifies if socket handle should be closed. */
void net_sendbuffer_destroy(NET_SENDBUF_REC *rec, int close); void net_sendbuffer_destroy(NET_SENDBUF_REC *rec, int close);
@ -17,7 +17,7 @@ void net_sendbuffer_destroy(NET_SENDBUF_REC *rec, int close);
int net_sendbuffer_send(NET_SENDBUF_REC *rec, const void *data, int size); int net_sendbuffer_send(NET_SENDBUF_REC *rec, const void *data, int size);
/* Returns the socket handle */ /* Returns the socket handle */
int net_sendbuffer_handle(NET_SENDBUF_REC *rec); GIOChannel *net_sendbuffer_handle(NET_SENDBUF_REC *rec);
void net_sendbuffer_init(void); void net_sendbuffer_init(void);
void net_sendbuffer_deinit(void); void net_sendbuffer_deinit(void);

View File

@ -23,7 +23,11 @@
#include "net-internal.h" #include "net-internal.h"
#ifndef INADDR_NONE #ifndef INADDR_NONE
#define INADDR_NONE INADDR_BROADCAST # define INADDR_NONE INADDR_BROADCAST
#endif
#ifndef EINPROGRESS
# define EINPROGESS 0 /* win32 */
#endif #endif
union sockaddr_union { union sockaddr_union {
@ -41,6 +45,12 @@ union sockaddr_union {
# define SIZEOF_SOCKADDR(so) (sizeof(so.sin)) # define SIZEOF_SOCKADDR(so) (sizeof(so.sin))
#endif #endif
#ifdef WIN32
# define g_io_channel_new(handle) g_io_channel_win32_new_stream_socket(handle)
#else
# define g_io_channel_new(handle) g_io_channel_unix_new(handle)
#endif
/* Cygwin need this, don't know others.. */ /* Cygwin need this, don't know others.. */
/*#define BLOCKING_SOCKETS 1*/ /*#define BLOCKING_SOCKETS 1*/
@ -128,20 +138,20 @@ int sin_get_port(union sockaddr_union *so)
} }
/* Connect to socket */ /* Connect to socket */
int net_connect(const char *addr, int port, IPADDR *my_ip) GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip)
{ {
IPADDR ip; IPADDR ip;
g_return_val_if_fail(addr != NULL, -1); g_return_val_if_fail(addr != NULL, NULL);
if (net_gethostbyname(addr, &ip) == -1) if (net_gethostbyname(addr, &ip) == -1)
return -1; return NULL;
return net_connect_ip(&ip, port, my_ip); return net_connect_ip(&ip, port, my_ip);
} }
/* Connect to socket with ip address */ /* Connect to socket with ip address */
int net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip) GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip)
{ {
union sockaddr_union so; union sockaddr_union so;
int handle, ret, opt = 1; int handle, ret, opt = 1;
@ -152,7 +162,7 @@ int net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip)
handle = socket(ip->family, SOCK_STREAM, 0); handle = socket(ip->family, SOCK_STREAM, 0);
if (handle == -1) if (handle == -1)
return -1; return NULL;
/* set socket options */ /* set socket options */
#ifndef WIN32 #ifndef WIN32
@ -174,33 +184,32 @@ int net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip)
sin_set_port(&so, port); sin_set_port(&so, port);
ret = connect(handle, &so.sa, SIZEOF_SOCKADDR(so)); ret = connect(handle, &so.sa, SIZEOF_SOCKADDR(so));
#ifndef WIN32
if (ret < 0 && errno != EINPROGRESS) { if (ret < 0 && errno != EINPROGRESS) {
close(handle); close(handle);
return -1; return NULL;
} }
#endif
return handle; return g_io_channel_new(handle);
} }
/* Disconnect socket */ /* Disconnect socket */
void net_disconnect(int handle) void net_disconnect(GIOChannel *handle)
{ {
g_return_if_fail(handle != -1); g_return_if_fail(handle != NULL);
close(handle); g_io_channel_close(handle);
g_io_channel_unref(handle);
} }
/* Listen for connections on a socket. if `my_ip' is NULL, listen in any /* Listen for connections on a socket. if `my_ip' is NULL, listen in any
address. */ address. */
int net_listen(IPADDR *my_ip, int *port) GIOChannel *net_listen(IPADDR *my_ip, int *port)
{ {
union sockaddr_union so; union sockaddr_union so;
int ret, handle, opt = 1; int ret, handle, opt = 1;
socklen_t len; socklen_t len;
g_return_val_if_fail(port != NULL, -1); g_return_val_if_fail(port != NULL, NULL);
memset(&so, 0, sizeof(so)); memset(&so, 0, sizeof(so));
sin_set_port(&so, *port); sin_set_port(&so, *port);
@ -209,7 +218,7 @@ int net_listen(IPADDR *my_ip, int *port)
/* create the socket */ /* create the socket */
handle = socket(so.sin.sin_family, SOCK_STREAM, 0); handle = socket(so.sin.sin_family, SOCK_STREAM, 0);
if (handle == -1) if (handle == -1)
return -1; return NULL;
/* set socket options */ /* set socket options */
#ifndef WIN32 #ifndef WIN32
@ -222,44 +231,39 @@ int net_listen(IPADDR *my_ip, int *port)
/* specify the address/port we want to listen in */ /* specify the address/port we want to listen in */
ret = bind(handle, &so.sa, SIZEOF_SOCKADDR(so)); ret = bind(handle, &so.sa, SIZEOF_SOCKADDR(so));
if (ret < 0) { if (ret >= 0) {
close(handle); /* get the actual port we started listen */
return -1; len = SIZEOF_SOCKADDR(so);
ret = getsockname(handle, &so.sa, &len);
if (ret >= 0) {
*port = sin_get_port(&so);
/* start listening */
if (listen(handle, 1) >= 0)
return g_io_channel_new(handle);
}
} }
/* get the actual port we started listen */ /* error */
len = SIZEOF_SOCKADDR(so); close(handle);
ret = getsockname(handle, &so.sa, &len); return NULL;
if (ret < 0) {
close(handle);
return -1;
}
*port = sin_get_port(&so);
/* start listening */
if (listen(handle, 1) < 0) {
close(handle);
return -1;
}
return handle;
} }
/* Accept a connection on a socket */ /* Accept a connection on a socket */
int net_accept(int handle, IPADDR *addr, int *port) GIOChannel *net_accept(GIOChannel *handle, IPADDR *addr, int *port)
{ {
union sockaddr_union so; union sockaddr_union so;
int ret; int ret;
socklen_t addrlen; socklen_t addrlen;
g_return_val_if_fail(handle != -1, -1); g_return_val_if_fail(handle != NULL, NULL);
addrlen = SIZEOF_SOCKADDR(so); addrlen = SIZEOF_SOCKADDR(so);
ret = accept(handle, &so.sa, &addrlen); ret = accept(g_io_channel_unix_get_fd(handle), &so.sa, &addrlen);
if (ret < 0) if (ret < 0)
return -1; return NULL;
if (addr != NULL) sin_get_ip(&so, addr); if (addr != NULL) sin_get_ip(&so, addr);
if (port != NULL) *port = sin_get_port(&so); if (port != NULL) *port = sin_get_port(&so);
@ -267,68 +271,54 @@ int net_accept(int handle, IPADDR *addr, int *port)
#ifndef WIN32 #ifndef WIN32
fcntl(ret, F_SETFL, O_NONBLOCK); fcntl(ret, F_SETFL, O_NONBLOCK);
#endif #endif
return ret; return g_io_channel_new(ret);
} }
/* Read data from socket, return number of bytes read, -1 = error */ /* Read data from socket, return number of bytes read, -1 = error */
int net_receive(int handle, char *buf, int len) int net_receive(GIOChannel *handle, char *buf, int len)
{ {
#ifdef BLOCKING_SOCKETS int ret, err;
fd_set set;
struct timeval tv;
#endif
int ret;
g_return_val_if_fail(handle != -1, -1); g_return_val_if_fail(handle != NULL, -1);
g_return_val_if_fail(buf != NULL, -1); g_return_val_if_fail(buf != NULL, -1);
#ifdef BLOCKING_SOCKETS err = g_io_channel_read(handle, buf, len, &ret);
FD_ZERO(&set); if (err == 0 && ret == 0)
FD_SET(handle, &set);
tv.tv_sec = 0;
tv.tv_usec = 0;
if (select(handle+1, &set, NULL, NULL, &tv) <= 0 ||
!FD_ISSET(handle, &set)) return 0;
#endif
ret = recv(handle, buf, len, 0);
if (ret == 0)
return -1; /* disconnected */ return -1; /* disconnected */
if (ret == -1 && (errno == EWOULDBLOCK || errno == EAGAIN || if (err == G_IO_ERROR_AGAIN || errno == EINTR)
errno == EINTR))
return 0; /* no bytes received */ return 0; /* no bytes received */
return ret; return err == 0 ? ret : -1;
} }
/* Transmit data, return number of bytes sent, -1 = error */ /* Transmit data, return number of bytes sent, -1 = error */
int net_transmit(int handle, const char *data, int len) int net_transmit(GIOChannel *handle, const char *data, int len)
{ {
int n; int ret, err;
g_return_val_if_fail(handle != -1, -1); g_return_val_if_fail(handle != NULL, -1);
g_return_val_if_fail(data != NULL, -1); g_return_val_if_fail(data != NULL, -1);
n = send(handle, data, len, 0); err = g_io_channel_write(handle, (char *) data, len, &ret);
if (n == -1 && (errno == EWOULDBLOCK || errno == EAGAIN || if (err == G_IO_ERROR_AGAIN || errno == EINTR || errno == EPIPE)
errno == EINTR || errno == EPIPE))
return 0; return 0;
return n > 0 ? n : -1; return err == 0 ? ret : -1;
} }
/* Get socket address/port */ /* Get socket address/port */
int net_getsockname(int handle, IPADDR *addr, int *port) int net_getsockname(GIOChannel *handle, IPADDR *addr, int *port)
{ {
union sockaddr_union so; union sockaddr_union so;
socklen_t len; socklen_t len;
g_return_val_if_fail(handle != -1, -1); g_return_val_if_fail(handle != NULL, -1);
g_return_val_if_fail(addr != NULL, -1); g_return_val_if_fail(addr != NULL, -1);
len = SIZEOF_SOCKADDR(so); len = SIZEOF_SOCKADDR(so);
if (getsockname(handle, (struct sockaddr *) &so, &len) == -1) if (getsockname(g_io_channel_unix_get_fd(handle),
(struct sockaddr *) &so, &len) == -1)
return -1; return -1;
sin_get_ip(&so, addr); sin_get_ip(&so, addr);
@ -469,12 +459,13 @@ int net_host2ip(const char *host, IPADDR *ip)
} }
/* Get socket error */ /* Get socket error */
int net_geterror(int handle) int net_geterror(GIOChannel *handle)
{ {
int data; int data;
socklen_t len = sizeof(data); socklen_t len = sizeof(data);
if (getsockopt(handle, SOL_SOCKET, SO_ERROR, (void *) &data, &len) == -1) if (getsockopt(g_io_channel_unix_get_fd(handle),
SOL_SOCKET, SO_ERROR, (void *) &data, &len) == -1)
return -1; return -1;
return data; return data;

View File

@ -33,24 +33,24 @@ typedef struct _ipaddr IPADDR;
int net_ip_compare(IPADDR *ip1, IPADDR *ip2); int net_ip_compare(IPADDR *ip1, IPADDR *ip2);
/* Connect to socket */ /* Connect to socket */
int net_connect(const char *addr, int port, IPADDR *my_ip); GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip);
/* Connect to socket with ip address */ /* Connect to socket with ip address */
int net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip); GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip);
/* Disconnect socket */ /* Disconnect socket */
void net_disconnect(int handle); void net_disconnect(GIOChannel *handle);
/* Try to let the other side close the connection, if it still isn't /* Try to let the other side close the connection, if it still isn't
disconnected after certain amount of time, close it ourself */ disconnected after certain amount of time, close it ourself */
void net_disconnect_later(int handle); void net_disconnect_later(GIOChannel *handle);
/* Listen for connections on a socket */ /* Listen for connections on a socket */
int net_listen(IPADDR *my_ip, int *port); GIOChannel *net_listen(IPADDR *my_ip, int *port);
/* Accept a connection on a socket */ /* Accept a connection on a socket */
int net_accept(int handle, IPADDR *addr, int *port); GIOChannel *net_accept(GIOChannel *handle, IPADDR *addr, int *port);
/* Read data from socket, return number of bytes read, -1 = error */ /* Read data from socket, return number of bytes read, -1 = error */
int net_receive(int handle, char *buf, int len); int net_receive(GIOChannel *handle, char *buf, int len);
/* Transmit data, return number of bytes sent, -1 = error */ /* Transmit data, return number of bytes sent, -1 = error */
int net_transmit(int handle, const char *data, int len); int net_transmit(GIOChannel *handle, const char *data, int len);
/* Get IP address for host, returns 0 = ok, /* Get IP address for host, returns 0 = ok,
others = error code for net_gethosterror() */ others = error code for net_gethosterror() */
@ -65,13 +65,13 @@ const char *net_gethosterror(int error);
int net_hosterror_notfound(int error); int net_hosterror_notfound(int error);
/* Get socket address/port */ /* Get socket address/port */
int net_getsockname(int handle, IPADDR *addr, int *port); int net_getsockname(GIOChannel *handle, IPADDR *addr, int *port);
int net_ip2host(IPADDR *ip, char *host); int net_ip2host(IPADDR *ip, char *host);
int net_host2ip(const char *host, IPADDR *ip); int net_host2ip(const char *host, IPADDR *ip);
/* Get socket error */ /* Get socket error */
int net_geterror(int handle); int net_geterror(GIOChannel *handle);
int is_ipv4_address(const char *host); int is_ipv4_address(const char *host);
int is_ipv6_address(const char *host); int is_ipv6_address(const char *host);

View File

@ -17,7 +17,7 @@ void *handle; /* NET_SENDBUF_REC socket */
int readtag; /* input tag */ int readtag; /* input tag */
/* for net_connect_nonblock() */ /* for net_connect_nonblock() */
int connect_pipe[2]; GIOChannel *connect_pipe[2];
int connect_tag; int connect_tag;
int connect_pid; int connect_pid;

View File

@ -51,9 +51,11 @@ void server_connect_failed(SERVER_REC *server, const char *msg)
if (server->handle != NULL) if (server->handle != NULL)
net_sendbuffer_destroy(server->handle, TRUE); net_sendbuffer_destroy(server->handle, TRUE);
if (server->connect_pipe[0] != -1) { if (server->connect_pipe[0] != NULL) {
close(server->connect_pipe[0]); g_io_channel_close(server->connect_pipe[0]);
close(server->connect_pipe[1]); g_io_channel_unref(server->connect_pipe[0]);
g_io_channel_close(server->connect_pipe[1]);
g_io_channel_unref(server->connect_pipe[1]);
} }
MODULE_DATA_DEINIT(server); MODULE_DATA_DEINIT(server);
@ -129,7 +131,7 @@ void server_connect_finished(SERVER_REC *server)
signal_emit("server connected", 1, server); signal_emit("server connected", 1, server);
} }
static void server_connect_callback_init(SERVER_REC *server, int handle) static void server_connect_callback_init(SERVER_REC *server, GIOChannel *handle)
{ {
int error; int error;
@ -154,7 +156,7 @@ static void server_connect_callback_readpipe(SERVER_REC *server)
SERVER_CONNECT_REC *conn; SERVER_CONNECT_REC *conn;
RESOLVED_IP_REC iprec; RESOLVED_IP_REC iprec;
const char *errormsg; const char *errormsg;
int handle; GIOChannel *handle;
g_return_if_fail(IS_SERVER(server)); g_return_if_fail(IS_SERVER(server));
@ -163,18 +165,20 @@ static void server_connect_callback_readpipe(SERVER_REC *server)
net_gethostbyname_return(server->connect_pipe[0], &iprec); net_gethostbyname_return(server->connect_pipe[0], &iprec);
close(server->connect_pipe[0]); g_io_channel_close(server->connect_pipe[0]);
close(server->connect_pipe[1]); g_io_channel_unref(server->connect_pipe[0]);
g_io_channel_close(server->connect_pipe[1]);
g_io_channel_unref(server->connect_pipe[1]);
server->connect_pipe[0] = -1; server->connect_pipe[0] = NULL;
server->connect_pipe[1] = -1; server->connect_pipe[1] = NULL;
conn = server->connrec; conn = server->connrec;
handle = iprec.error != 0 ? -1 : handle = iprec.error != 0 ? NULL :
net_connect_ip(&iprec.ip, conn->proxy != NULL ? net_connect_ip(&iprec.ip, conn->proxy != NULL ?
conn->proxy_port : conn->port, conn->proxy_port : conn->port,
conn->own_ip != NULL ? conn->own_ip : NULL); conn->own_ip != NULL ? conn->own_ip : NULL);
if (handle == -1) { if (handle == NULL) {
/* failed */ /* failed */
if (iprec.error == 0 || !net_hosterror_notfound(iprec.error)) { if (iprec.error == 0 || !net_hosterror_notfound(iprec.error)) {
/* reconnect back only if either /* reconnect back only if either
@ -237,19 +241,23 @@ void server_connect_init(SERVER_REC *server)
int server_start_connect(SERVER_REC *server) int server_start_connect(SERVER_REC *server)
{ {
const char *connect_address; const char *connect_address;
int fd[2];
g_return_val_if_fail(server != NULL, FALSE); g_return_val_if_fail(server != NULL, FALSE);
if (server->connrec->port <= 0) return FALSE; if (server->connrec->port <= 0) return FALSE;
server_connect_init(server); server_connect_init(server);
if (pipe(server->connect_pipe) != 0) { if (pipe(fd) != 0) {
g_warning("server_connect(): pipe() failed."); g_warning("server_connect(): pipe() failed.");
g_free(server->tag); g_free(server->tag);
g_free(server->nick); g_free(server->nick);
return FALSE; return FALSE;
} }
server->connect_pipe[0] = g_io_channel_unix_new(fd[0]);
server->connect_pipe[1] = g_io_channel_unix_new(fd[1]);
connect_address = server->connrec->proxy != NULL ? connect_address = server->connrec->proxy != NULL ?
server->connrec->proxy : server->connrec->address; server->connrec->proxy : server->connrec->address;
server->connect_pid = server->connect_pid =

View File

@ -550,7 +550,9 @@ void gui_readline_init(void)
cutbuffer = NULL; cutbuffer = NULL;
redir = NULL; redir = NULL;
idle_time = time(NULL); idle_time = time(NULL);
readtag = g_input_add_full(0, G_PRIORITY_HIGH, G_INPUT_READ, (GInputFunction) readline, NULL); readtag = g_input_add_full(g_io_channel_unix_new(0),
G_PRIORITY_HIGH, G_INPUT_READ,
(GInputFunction) readline, NULL);
settings_add_str("history", "scroll_page_count", "/2"); settings_add_str("history", "scroll_page_count", "/2");

View File

@ -190,19 +190,20 @@ static void dcc_chat_input(DCC_REC *dcc)
static void dcc_chat_listen(DCC_REC *dcc) static void dcc_chat_listen(DCC_REC *dcc)
{ {
IPADDR ip; IPADDR ip;
int handle, port; GIOChannel *handle;
int port;
g_return_if_fail(dcc != NULL); g_return_if_fail(dcc != NULL);
/* accept connection */ /* accept connection */
handle = net_accept(dcc->handle, &ip, &port); handle = net_accept(dcc->handle, &ip, &port);
if (handle == -1) if (handle == NULL)
return; return;
/* TODO: add paranoia check - see dcc-files.c */ /* TODO: add paranoia check - see dcc-files.c */
g_source_remove(dcc->tagconn); g_source_remove(dcc->tagconn);
close(dcc->handle); net_disconnect(dcc->handle);
dcc->starttime = time(NULL); dcc->starttime = time(NULL);
dcc->handle = handle; dcc->handle = handle;
@ -243,14 +244,14 @@ static void dcc_chat_connect(DCC_REC *dcc)
g_return_if_fail(dcc != NULL); g_return_if_fail(dcc != NULL);
if (dcc->addrstr[0] == '\0' || if (dcc->addrstr[0] == '\0' ||
dcc->starttime != 0 || dcc->handle != -1) { dcc->starttime != 0 || dcc->handle != NULL) {
/* already sent a chat request / already chatting */ /* already sent a chat request / already chatting */
return; return;
} }
dcc->handle = net_connect_ip(&dcc->addr, dcc->port, dcc->handle = net_connect_ip(&dcc->addr, dcc->port,
source_host_ok ? source_host_ip : NULL); source_host_ok ? source_host_ip : NULL);
if (dcc->handle != -1) { if (dcc->handle != NULL) {
dcc->tagconn = g_input_add(dcc->handle, dcc->tagconn = g_input_add(dcc->handle,
G_INPUT_WRITE | G_INPUT_READ, G_INPUT_WRITE | G_INPUT_READ,
(GInputFunction) sig_chat_connected, dcc); (GInputFunction) sig_chat_connected, dcc);
@ -267,8 +268,9 @@ static void cmd_dcc_chat(const char *data, IRC_SERVER_REC *server)
void *free_arg; void *free_arg;
DCC_REC *dcc; DCC_REC *dcc;
IPADDR own_ip; IPADDR own_ip;
GIOChannel *handle;
char *nick, *str, host[MAX_IP_LEN]; char *nick, *str, host[MAX_IP_LEN];
int port, handle; int port;
g_return_if_fail(data != NULL); g_return_if_fail(data != NULL);
@ -288,12 +290,13 @@ static void cmd_dcc_chat(const char *data, IRC_SERVER_REC *server)
if (server == NULL || !server->connected) if (server == NULL || !server->connected)
cmd_param_error(CMDERR_NOT_CONNECTED); cmd_param_error(CMDERR_NOT_CONNECTED);
if (net_getsockname(net_sendbuffer_handle(server->handle), &own_ip, NULL) == -1) if (net_getsockname(net_sendbuffer_handle(server->handle),
&own_ip, NULL) == -1)
cmd_param_error(CMDERR_ERRNO); cmd_param_error(CMDERR_ERRNO);
port = settings_get_int("dcc_port"); port = settings_get_int("dcc_port");
handle = net_listen(&own_ip, &port); handle = net_listen(&own_ip, &port);
if (handle == -1) if (handle == NULL)
cmd_param_error(CMDERR_ERRNO); cmd_param_error(CMDERR_ERRNO);
dcc = dcc_create(DCC_TYPE_CHAT, handle, nick, "chat", server, NULL); dcc = dcc_create(DCC_TYPE_CHAT, handle, nick, "chat", server, NULL);

View File

@ -197,7 +197,7 @@ static void dcc_get_connect(DCC_REC *dcc)
{ {
dcc->handle = net_connect_ip(&dcc->addr, dcc->port, dcc->handle = net_connect_ip(&dcc->addr, dcc->port,
source_host_ok ? source_host_ip : NULL); source_host_ok ? source_host_ip : NULL);
if (dcc->handle != -1) { if (dcc->handle != NULL) {
dcc->tagconn = g_input_add(dcc->handle, dcc->tagconn = g_input_add(dcc->handle,
G_INPUT_WRITE | G_INPUT_READ, G_INPUT_WRITE | G_INPUT_READ,
(GInputFunction) sig_dccget_connected, dcc); (GInputFunction) sig_dccget_connected, dcc);
@ -209,7 +209,7 @@ static void dcc_get_connect(DCC_REC *dcc)
} }
#define dcc_is_unget(dcc) \ #define dcc_is_unget(dcc) \
((dcc)->type == DCC_TYPE_GET && (dcc)->handle == -1) ((dcc)->type == DCC_TYPE_GET && (dcc)->handle == NULL)
/* SYNTAX: DCC GET <nick> [<file>] */ /* SYNTAX: DCC GET <nick> [<file>] */
static void cmd_dcc_get(const char *data) static void cmd_dcc_get(const char *data)
@ -268,7 +268,7 @@ static void dcc_resume_send(DCC_REC *dcc, int port)
#define is_accept_ok(type, dcc) \ #define is_accept_ok(type, dcc) \
(g_strcasecmp(type, "ACCEPT") != 0 || \ (g_strcasecmp(type, "ACCEPT") != 0 || \
((dcc)->type == DCC_TYPE_GET && \ ((dcc)->type == DCC_TYPE_GET && \
(dcc)->get_type == DCC_GET_RESUME && (dcc)->handle == -1)) (dcc)->get_type == DCC_GET_RESUME && (dcc)->handle == NULL))
static void dcc_ctcp_msg(const char *data, IRC_SERVER_REC *server, static void dcc_ctcp_msg(const char *data, IRC_SERVER_REC *server,
const char *sender, const char *sendaddr, const char *sender, const char *sendaddr,
@ -453,14 +453,15 @@ static void dcc_send_read_size(DCC_REC *dcc)
/* input function: DCC SEND - someone tried to connect to our socket */ /* input function: DCC SEND - someone tried to connect to our socket */
static void dcc_send_init(DCC_REC *dcc) static void dcc_send_init(DCC_REC *dcc)
{ {
int handle, port; GIOChannel *handle;
IPADDR addr; IPADDR addr;
int port;
g_return_if_fail(dcc != NULL); g_return_if_fail(dcc != NULL);
/* accept connection */ /* accept connection */
handle = net_accept(dcc->handle, &addr, &port); handle = net_accept(dcc->handle, &addr, &port);
if (handle == -1) if (handle == NULL)
return; return;
/* TODO: some kind of paranoia check would be nice. it would check /* TODO: some kind of paranoia check would be nice. it would check
@ -468,7 +469,7 @@ static void dcc_send_init(DCC_REC *dcc)
address who connected us. */ address who connected us. */
g_source_remove(dcc->tagconn); g_source_remove(dcc->tagconn);
close(dcc->handle); net_disconnect(dcc->handle);
dcc->starttime = time(NULL); dcc->starttime = time(NULL);
dcc->fastsend = settings_get_bool("dcc_fast_send"); dcc->fastsend = settings_get_bool("dcc_fast_send");
@ -501,10 +502,11 @@ static void cmd_dcc_send(const char *data, IRC_SERVER_REC *server, void *item)
char *target, *fname, *str, *ptr; char *target, *fname, *str, *ptr;
void *free_arg; void *free_arg;
char host[MAX_IP_LEN]; char host[MAX_IP_LEN];
int hfile, hlisten, port; int hfile, port;
long fsize; long fsize;
DCC_REC *dcc, *chat; DCC_REC *dcc, *chat;
IPADDR own_ip; IPADDR own_ip;
GIOChannel *handle, *hlisten;
g_return_if_fail(data != NULL); g_return_if_fail(data != NULL);
@ -549,7 +551,9 @@ static void cmd_dcc_send(const char *data, IRC_SERVER_REC *server, void *item)
lseek(hfile, 0, SEEK_SET); lseek(hfile, 0, SEEK_SET);
/* get the IP address we use with IRC server */ /* get the IP address we use with IRC server */
if (net_getsockname(chat != NULL ? chat->handle : net_sendbuffer_handle(server->handle), &own_ip, NULL) == -1) { handle = chat != NULL ? chat->handle :
net_sendbuffer_handle(server->handle);
if (net_getsockname(handle, &own_ip, NULL) == -1) {
close(hfile); close(hfile);
cmd_param_error(CMDERR_ERRNO); cmd_param_error(CMDERR_ERRNO);
} }
@ -557,7 +561,7 @@ static void cmd_dcc_send(const char *data, IRC_SERVER_REC *server, void *item)
/* start listening */ /* start listening */
port = settings_get_int("dcc_port"); port = settings_get_int("dcc_port");
hlisten = net_listen(&own_ip, &port); hlisten = net_listen(&own_ip, &port);
if (hlisten == -1) { if (hlisten == NULL) {
close(hfile); close(hfile);
cmd_param_error(CMDERR_ERRNO); cmd_param_error(CMDERR_ERRNO);
} }

View File

@ -52,7 +52,7 @@ GSList *dcc_conns;
static int dcc_timeouttag; static int dcc_timeouttag;
/* Create new DCC record */ /* Create new DCC record */
DCC_REC *dcc_create(int type, int handle, const char *nick, const char *arg, DCC_REC *dcc_create(int type, GIOChannel *handle, const char *nick, const char *arg,
IRC_SERVER_REC *server, DCC_REC *chat) IRC_SERVER_REC *server, DCC_REC *chat)
{ {
DCC_REC *dcc; DCC_REC *dcc;
@ -110,7 +110,7 @@ void dcc_destroy(DCC_REC *dcc)
signal_emit("dcc destroyed", 1, dcc); signal_emit("dcc destroyed", 1, dcc);
if (dcc->fhandle != -1) close(dcc->fhandle); if (dcc->fhandle != -1) close(dcc->fhandle);
if (dcc->handle != -1) net_disconnect(dcc->handle); if (dcc->handle != NULL) net_disconnect(dcc->handle);
if (dcc->tagconn != -1) g_source_remove(dcc->tagconn); if (dcc->tagconn != -1) g_source_remove(dcc->tagconn);
if (dcc->tagread != -1) g_source_remove(dcc->tagread); if (dcc->tagread != -1) g_source_remove(dcc->tagread);
if (dcc->tagwrite != -1) g_source_remove(dcc->tagwrite); if (dcc->tagwrite != -1) g_source_remove(dcc->tagwrite);
@ -304,21 +304,21 @@ static void dcc_ctcp_msg(char *data, IRC_SERVER_REC *server, char *sender, char
if (olddcc != NULL) { if (olddcc != NULL) {
/* same DCC request offered again */ /* same DCC request offered again */
if (olddcc->type == DCC_TYPE_CHAT && if (olddcc->type == DCC_TYPE_CHAT &&
olddcc->handle != -1 && olddcc->starttime == 0) { olddcc->handle != NULL && olddcc->starttime == 0) {
/* we requested dcc chat, they requested /* we requested dcc chat, they requested
dcc chat from us .. allow it. */ dcc chat from us .. allow it. */
dcc_destroy(olddcc); dcc_destroy(olddcc);
} else { } else {
/* if the connection isn't open, update the port, /* if the connection isn't open, update the port,
otherwise just ignore */ otherwise just ignore */
if (olddcc->handle == -1) if (olddcc->handle == NULL)
olddcc->port = port; olddcc->port = port;
cmd_params_free(free_arg); cmd_params_free(free_arg);
return; return;
} }
} }
dcc = dcc_create(dcctype, -1, sender, arg, server, chat); dcc = dcc_create(dcctype, NULL, sender, arg, server, chat);
dcc_get_address(addrstr, &dcc->addr); dcc_get_address(addrstr, &dcc->addr);
net_ip2host(&dcc->addr, dcc->addrstr); net_ip2host(&dcc->addr, dcc->addrstr);
dcc->port = port; dcc->port = port;

View File

@ -40,7 +40,7 @@ typedef struct DCC_REC {
int port; /* port we're connected in */ int port; /* port we're connected in */
long size, transfd, skipped; /* file size / bytes transferred / skipped at start */ long size, transfd, skipped; /* file size / bytes transferred / skipped at start */
int handle; /* socket handle */ GIOChannel *handle; /* socket handle */
void *sendbuf; void *sendbuf;
int tagconn, tagread, tagwrite; int tagconn, tagread, tagwrite;
int fhandle; /* file handle */ int fhandle; /* file handle */
@ -80,7 +80,7 @@ const char *dcc_type2str(int type);
int dcc_str2type(const char *type); int dcc_str2type(const char *type);
void dcc_make_address(IPADDR *ip, char *host); void dcc_make_address(IPADDR *ip, char *host);
DCC_REC *dcc_create(int type, int handle, const char *nick, const char *arg, IRC_SERVER_REC *server, DCC_REC *chat); DCC_REC *dcc_create(int type, GIOChannel *handle, const char *nick, const char *arg, IRC_SERVER_REC *server, DCC_REC *chat);
void dcc_destroy(DCC_REC *dcc); void dcc_destroy(DCC_REC *dcc);
/* Send a CTCP message/notify to target. Send the CTCP via DCC chat if /* Send a CTCP message/notify to target. Send the CTCP via DCC chat if