mirror of
https://github.com/irssi/irssi.git
synced 2024-12-04 14:46:39 -05: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:
parent
e81fdd7307
commit
1c9f45b4a4
@ -53,11 +53,11 @@
|
||||
#define G_INPUT_READ (1 << 0)
|
||||
#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);
|
||||
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);
|
||||
|
||||
#define MAX_INT_STRLEN ((sizeof(int) * CHAR_BIT + 2) / 3 + 1)
|
||||
|
@ -52,20 +52,17 @@ static int irssi_io_invoke(GIOChannel *source, GIOCondition condition,
|
||||
if (condition & G_IO_OUT)
|
||||
icond |= G_INPUT_WRITE;
|
||||
|
||||
if (rec->condition & icond) {
|
||||
rec->function(rec->data, g_io_channel_unix_get_fd(source),
|
||||
icond);
|
||||
}
|
||||
if (rec->condition & icond)
|
||||
rec->function(rec->data, source, icond);
|
||||
|
||||
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)
|
||||
{
|
||||
IRSSI_INPUT_REC *rec;
|
||||
unsigned int result;
|
||||
GIOChannel *channel;
|
||||
GIOCondition cond;
|
||||
|
||||
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)
|
||||
cond |= G_IO_OUT;
|
||||
|
||||
channel = g_io_channel_unix_new (source);
|
||||
result = g_io_add_watch_full(channel, priority, cond,
|
||||
result = g_io_add_watch_full(source, priority, cond,
|
||||
irssi_io_invoke, rec, g_free);
|
||||
g_io_channel_unref(channel);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int g_input_add(int source, int condition,
|
||||
int g_input_add(GIOChannel *source, int condition,
|
||||
GInputFunction function, void *data)
|
||||
{
|
||||
return g_input_add_full(source, G_PRIORITY_DEFAULT, condition,
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
typedef struct {
|
||||
time_t created;
|
||||
int handle;
|
||||
GIOChannel *handle;
|
||||
int tag;
|
||||
} 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
|
||||
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;
|
||||
|
||||
@ -114,7 +114,7 @@ void net_disconnect_deinit(void)
|
||||
#ifndef WIN32
|
||||
NET_DISCONNECT_REC *rec;
|
||||
time_t now, max;
|
||||
int first;
|
||||
int first, fd;
|
||||
struct timeval tv;
|
||||
fd_set set;
|
||||
|
||||
@ -131,12 +131,13 @@ void net_disconnect_deinit(void)
|
||||
continue;
|
||||
}
|
||||
|
||||
fd = g_io_channel_unix_get_fd(rec->handle);
|
||||
FD_ZERO(&set);
|
||||
FD_SET(rec->handle, &set);
|
||||
FD_SET(fd, &set);
|
||||
tv.tv_sec = first ? 0 : max-now;
|
||||
tv.tv_usec = first ? 100000 : 0;
|
||||
if (select(rec->handle+1, &set, NULL, NULL, &tv) > 0 &&
|
||||
FD_ISSET(rec->handle, &set)) {
|
||||
if (select(fd+1, &set, NULL, NULL, &tv) > 0 &&
|
||||
FD_ISSET(fd, &set)) {
|
||||
/* data coming .. check if we can close the handle */
|
||||
sig_disconnect(rec);
|
||||
} else if (first) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -20,18 +20,19 @@ typedef struct {
|
||||
char *errorstr;
|
||||
} RESOLVED_NAME_REC;
|
||||
|
||||
typedef void (*NET_CALLBACK) (int, void *);
|
||||
typedef void (*NET_CALLBACK) (GIOChannel *, void *);
|
||||
typedef void (*NET_HOST_CALLBACK) (RESOLVED_NAME_REC *, void *);
|
||||
|
||||
/* 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 */
|
||||
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() */
|
||||
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 */
|
||||
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 */
|
||||
void net_disconnect_nonblock(int pid);
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "net-sendbuffer.h"
|
||||
|
||||
struct _NET_SENDBUF_REC {
|
||||
int handle;
|
||||
GIOChannel *handle;
|
||||
|
||||
int bufsize;
|
||||
int bufpos;
|
||||
@ -36,11 +36,11 @@ static int timeout_tag;
|
||||
|
||||
/* Create new buffer - if `bufsize' is zero or less, DEFAULT_BUFFER_SIZE
|
||||
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;
|
||||
|
||||
g_return_val_if_fail(handle != -1, NULL);
|
||||
g_return_val_if_fail(handle != NULL, NULL);
|
||||
|
||||
rec = g_new0(NET_SENDBUF_REC, 1);
|
||||
rec->handle = handle;
|
||||
@ -148,9 +148,9 @@ int net_sendbuffer_send(NET_SENDBUF_REC *rec, const void *data, int size)
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ typedef struct _NET_SENDBUF_REC NET_SENDBUF_REC;
|
||||
|
||||
/* Create new buffer - if `bufsize' is zero or less, DEFAULT_BUFFER_SIZE
|
||||
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. */
|
||||
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);
|
||||
|
||||
/* 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_deinit(void);
|
||||
|
@ -23,7 +23,11 @@
|
||||
#include "net-internal.h"
|
||||
|
||||
#ifndef INADDR_NONE
|
||||
#define INADDR_NONE INADDR_BROADCAST
|
||||
# define INADDR_NONE INADDR_BROADCAST
|
||||
#endif
|
||||
|
||||
#ifndef EINPROGRESS
|
||||
# define EINPROGESS 0 /* win32 */
|
||||
#endif
|
||||
|
||||
union sockaddr_union {
|
||||
@ -41,6 +45,12 @@ union sockaddr_union {
|
||||
# define SIZEOF_SOCKADDR(so) (sizeof(so.sin))
|
||||
#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.. */
|
||||
/*#define BLOCKING_SOCKETS 1*/
|
||||
|
||||
@ -128,20 +138,20 @@ int sin_get_port(union sockaddr_union *so)
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
g_return_val_if_fail(addr != NULL, -1);
|
||||
g_return_val_if_fail(addr != NULL, NULL);
|
||||
|
||||
if (net_gethostbyname(addr, &ip) == -1)
|
||||
return -1;
|
||||
return NULL;
|
||||
|
||||
return net_connect_ip(&ip, port, my_ip);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
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);
|
||||
|
||||
if (handle == -1)
|
||||
return -1;
|
||||
return NULL;
|
||||
|
||||
/* set socket options */
|
||||
#ifndef WIN32
|
||||
@ -174,33 +184,32 @@ int net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip)
|
||||
sin_set_port(&so, port);
|
||||
ret = connect(handle, &so.sa, SIZEOF_SOCKADDR(so));
|
||||
|
||||
#ifndef WIN32
|
||||
if (ret < 0 && errno != EINPROGRESS) {
|
||||
close(handle);
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return handle;
|
||||
return g_io_channel_new(handle);
|
||||
}
|
||||
|
||||
/* 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
|
||||
address. */
|
||||
int net_listen(IPADDR *my_ip, int *port)
|
||||
GIOChannel *net_listen(IPADDR *my_ip, int *port)
|
||||
{
|
||||
union sockaddr_union so;
|
||||
int ret, handle, opt = 1;
|
||||
socklen_t len;
|
||||
|
||||
g_return_val_if_fail(port != NULL, -1);
|
||||
g_return_val_if_fail(port != NULL, NULL);
|
||||
|
||||
memset(&so, 0, sizeof(so));
|
||||
sin_set_port(&so, *port);
|
||||
@ -209,7 +218,7 @@ int net_listen(IPADDR *my_ip, int *port)
|
||||
/* create the socket */
|
||||
handle = socket(so.sin.sin_family, SOCK_STREAM, 0);
|
||||
if (handle == -1)
|
||||
return -1;
|
||||
return NULL;
|
||||
|
||||
/* set socket options */
|
||||
#ifndef WIN32
|
||||
@ -222,44 +231,39 @@ int net_listen(IPADDR *my_ip, int *port)
|
||||
|
||||
/* specify the address/port we want to listen in */
|
||||
ret = bind(handle, &so.sa, SIZEOF_SOCKADDR(so));
|
||||
if (ret < 0) {
|
||||
close(handle);
|
||||
return -1;
|
||||
if (ret >= 0) {
|
||||
/* get the actual port we started listen */
|
||||
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 */
|
||||
len = SIZEOF_SOCKADDR(so);
|
||||
ret = getsockname(handle, &so.sa, &len);
|
||||
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;
|
||||
/* error */
|
||||
close(handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
int ret;
|
||||
socklen_t addrlen;
|
||||
|
||||
g_return_val_if_fail(handle != -1, -1);
|
||||
g_return_val_if_fail(handle != NULL, NULL);
|
||||
|
||||
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)
|
||||
return -1;
|
||||
return NULL;
|
||||
|
||||
if (addr != NULL) sin_get_ip(&so, addr);
|
||||
if (port != NULL) *port = sin_get_port(&so);
|
||||
@ -267,68 +271,54 @@ int net_accept(int handle, IPADDR *addr, int *port)
|
||||
#ifndef WIN32
|
||||
fcntl(ret, F_SETFL, O_NONBLOCK);
|
||||
#endif
|
||||
return ret;
|
||||
return g_io_channel_new(ret);
|
||||
}
|
||||
|
||||
/* 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
|
||||
fd_set set;
|
||||
struct timeval tv;
|
||||
#endif
|
||||
int ret;
|
||||
int ret, err;
|
||||
|
||||
g_return_val_if_fail(handle != -1, -1);
|
||||
g_return_val_if_fail(handle != NULL, -1);
|
||||
g_return_val_if_fail(buf != NULL, -1);
|
||||
|
||||
#ifdef BLOCKING_SOCKETS
|
||||
FD_ZERO(&set);
|
||||
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)
|
||||
err = g_io_channel_read(handle, buf, len, &ret);
|
||||
if (err == 0 && ret == 0)
|
||||
return -1; /* disconnected */
|
||||
|
||||
if (ret == -1 && (errno == EWOULDBLOCK || errno == EAGAIN ||
|
||||
errno == EINTR))
|
||||
if (err == G_IO_ERROR_AGAIN || errno == EINTR)
|
||||
return 0; /* no bytes received */
|
||||
|
||||
return ret;
|
||||
return err == 0 ? ret : -1;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
n = send(handle, data, len, 0);
|
||||
if (n == -1 && (errno == EWOULDBLOCK || errno == EAGAIN ||
|
||||
errno == EINTR || errno == EPIPE))
|
||||
err = g_io_channel_write(handle, (char *) data, len, &ret);
|
||||
if (err == G_IO_ERROR_AGAIN || errno == EINTR || errno == EPIPE)
|
||||
return 0;
|
||||
|
||||
return n > 0 ? n : -1;
|
||||
return err == 0 ? ret : -1;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
sin_get_ip(&so, addr);
|
||||
@ -469,12 +459,13 @@ int net_host2ip(const char *host, IPADDR *ip)
|
||||
}
|
||||
|
||||
/* Get socket error */
|
||||
int net_geterror(int handle)
|
||||
int net_geterror(GIOChannel *handle)
|
||||
{
|
||||
int 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 data;
|
||||
|
@ -33,24 +33,24 @@ typedef struct _ipaddr IPADDR;
|
||||
int net_ip_compare(IPADDR *ip1, IPADDR *ip2);
|
||||
|
||||
/* 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 */
|
||||
int net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip);
|
||||
GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip);
|
||||
/* 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
|
||||
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 */
|
||||
int net_listen(IPADDR *my_ip, int *port);
|
||||
GIOChannel *net_listen(IPADDR *my_ip, int *port);
|
||||
/* 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 */
|
||||
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 */
|
||||
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,
|
||||
others = error code for net_gethosterror() */
|
||||
@ -65,13 +65,13 @@ const char *net_gethosterror(int error);
|
||||
int net_hosterror_notfound(int error);
|
||||
|
||||
/* 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_host2ip(const char *host, IPADDR *ip);
|
||||
|
||||
/* Get socket error */
|
||||
int net_geterror(int handle);
|
||||
int net_geterror(GIOChannel *handle);
|
||||
|
||||
int is_ipv4_address(const char *host);
|
||||
int is_ipv6_address(const char *host);
|
||||
|
@ -17,7 +17,7 @@ void *handle; /* NET_SENDBUF_REC socket */
|
||||
int readtag; /* input tag */
|
||||
|
||||
/* for net_connect_nonblock() */
|
||||
int connect_pipe[2];
|
||||
GIOChannel *connect_pipe[2];
|
||||
int connect_tag;
|
||||
int connect_pid;
|
||||
|
||||
|
@ -51,9 +51,11 @@ void server_connect_failed(SERVER_REC *server, const char *msg)
|
||||
if (server->handle != NULL)
|
||||
net_sendbuffer_destroy(server->handle, TRUE);
|
||||
|
||||
if (server->connect_pipe[0] != -1) {
|
||||
close(server->connect_pipe[0]);
|
||||
close(server->connect_pipe[1]);
|
||||
if (server->connect_pipe[0] != NULL) {
|
||||
g_io_channel_close(server->connect_pipe[0]);
|
||||
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);
|
||||
@ -129,7 +131,7 @@ void server_connect_finished(SERVER_REC *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;
|
||||
|
||||
@ -154,7 +156,7 @@ static void server_connect_callback_readpipe(SERVER_REC *server)
|
||||
SERVER_CONNECT_REC *conn;
|
||||
RESOLVED_IP_REC iprec;
|
||||
const char *errormsg;
|
||||
int handle;
|
||||
GIOChannel *handle;
|
||||
|
||||
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);
|
||||
|
||||
close(server->connect_pipe[0]);
|
||||
close(server->connect_pipe[1]);
|
||||
g_io_channel_close(server->connect_pipe[0]);
|
||||
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[1] = -1;
|
||||
server->connect_pipe[0] = NULL;
|
||||
server->connect_pipe[1] = NULL;
|
||||
|
||||
conn = server->connrec;
|
||||
handle = iprec.error != 0 ? -1 :
|
||||
handle = iprec.error != 0 ? NULL :
|
||||
net_connect_ip(&iprec.ip, conn->proxy != NULL ?
|
||||
conn->proxy_port : conn->port,
|
||||
conn->own_ip != NULL ? conn->own_ip : NULL);
|
||||
if (handle == -1) {
|
||||
if (handle == NULL) {
|
||||
/* failed */
|
||||
if (iprec.error == 0 || !net_hosterror_notfound(iprec.error)) {
|
||||
/* reconnect back only if either
|
||||
@ -237,19 +241,23 @@ void server_connect_init(SERVER_REC *server)
|
||||
int server_start_connect(SERVER_REC *server)
|
||||
{
|
||||
const char *connect_address;
|
||||
int fd[2];
|
||||
|
||||
g_return_val_if_fail(server != NULL, FALSE);
|
||||
if (server->connrec->port <= 0) return FALSE;
|
||||
|
||||
server_connect_init(server);
|
||||
|
||||
if (pipe(server->connect_pipe) != 0) {
|
||||
if (pipe(fd) != 0) {
|
||||
g_warning("server_connect(): pipe() failed.");
|
||||
g_free(server->tag);
|
||||
g_free(server->nick);
|
||||
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 ?
|
||||
server->connrec->proxy : server->connrec->address;
|
||||
server->connect_pid =
|
||||
|
@ -550,7 +550,9 @@ void gui_readline_init(void)
|
||||
cutbuffer = NULL;
|
||||
redir = 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");
|
||||
|
||||
|
@ -190,19 +190,20 @@ static void dcc_chat_input(DCC_REC *dcc)
|
||||
static void dcc_chat_listen(DCC_REC *dcc)
|
||||
{
|
||||
IPADDR ip;
|
||||
int handle, port;
|
||||
GIOChannel *handle;
|
||||
int port;
|
||||
|
||||
g_return_if_fail(dcc != NULL);
|
||||
|
||||
/* accept connection */
|
||||
handle = net_accept(dcc->handle, &ip, &port);
|
||||
if (handle == -1)
|
||||
if (handle == NULL)
|
||||
return;
|
||||
|
||||
/* TODO: add paranoia check - see dcc-files.c */
|
||||
|
||||
g_source_remove(dcc->tagconn);
|
||||
close(dcc->handle);
|
||||
net_disconnect(dcc->handle);
|
||||
|
||||
dcc->starttime = time(NULL);
|
||||
dcc->handle = handle;
|
||||
@ -243,14 +244,14 @@ static void dcc_chat_connect(DCC_REC *dcc)
|
||||
g_return_if_fail(dcc != NULL);
|
||||
|
||||
if (dcc->addrstr[0] == '\0' ||
|
||||
dcc->starttime != 0 || dcc->handle != -1) {
|
||||
dcc->starttime != 0 || dcc->handle != NULL) {
|
||||
/* already sent a chat request / already chatting */
|
||||
return;
|
||||
}
|
||||
|
||||
dcc->handle = net_connect_ip(&dcc->addr, dcc->port,
|
||||
source_host_ok ? source_host_ip : NULL);
|
||||
if (dcc->handle != -1) {
|
||||
if (dcc->handle != NULL) {
|
||||
dcc->tagconn = g_input_add(dcc->handle,
|
||||
G_INPUT_WRITE | G_INPUT_READ,
|
||||
(GInputFunction) sig_chat_connected, dcc);
|
||||
@ -267,8 +268,9 @@ static void cmd_dcc_chat(const char *data, IRC_SERVER_REC *server)
|
||||
void *free_arg;
|
||||
DCC_REC *dcc;
|
||||
IPADDR own_ip;
|
||||
GIOChannel *handle;
|
||||
char *nick, *str, host[MAX_IP_LEN];
|
||||
int port, handle;
|
||||
int port;
|
||||
|
||||
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)
|
||||
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);
|
||||
|
||||
port = settings_get_int("dcc_port");
|
||||
handle = net_listen(&own_ip, &port);
|
||||
if (handle == -1)
|
||||
if (handle == NULL)
|
||||
cmd_param_error(CMDERR_ERRNO);
|
||||
|
||||
dcc = dcc_create(DCC_TYPE_CHAT, handle, nick, "chat", server, NULL);
|
||||
|
@ -197,7 +197,7 @@ static void dcc_get_connect(DCC_REC *dcc)
|
||||
{
|
||||
dcc->handle = net_connect_ip(&dcc->addr, dcc->port,
|
||||
source_host_ok ? source_host_ip : NULL);
|
||||
if (dcc->handle != -1) {
|
||||
if (dcc->handle != NULL) {
|
||||
dcc->tagconn = g_input_add(dcc->handle,
|
||||
G_INPUT_WRITE | G_INPUT_READ,
|
||||
(GInputFunction) sig_dccget_connected, dcc);
|
||||
@ -209,7 +209,7 @@ static void dcc_get_connect(DCC_REC *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>] */
|
||||
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) \
|
||||
(g_strcasecmp(type, "ACCEPT") != 0 || \
|
||||
((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,
|
||||
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 */
|
||||
static void dcc_send_init(DCC_REC *dcc)
|
||||
{
|
||||
int handle, port;
|
||||
GIOChannel *handle;
|
||||
IPADDR addr;
|
||||
int port;
|
||||
|
||||
g_return_if_fail(dcc != NULL);
|
||||
|
||||
/* accept connection */
|
||||
handle = net_accept(dcc->handle, &addr, &port);
|
||||
if (handle == -1)
|
||||
if (handle == NULL)
|
||||
return;
|
||||
|
||||
/* 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. */
|
||||
|
||||
g_source_remove(dcc->tagconn);
|
||||
close(dcc->handle);
|
||||
net_disconnect(dcc->handle);
|
||||
|
||||
dcc->starttime = time(NULL);
|
||||
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;
|
||||
void *free_arg;
|
||||
char host[MAX_IP_LEN];
|
||||
int hfile, hlisten, port;
|
||||
int hfile, port;
|
||||
long fsize;
|
||||
DCC_REC *dcc, *chat;
|
||||
IPADDR own_ip;
|
||||
GIOChannel *handle, *hlisten;
|
||||
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
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 */
|
||||
port = settings_get_int("dcc_port");
|
||||
hlisten = net_listen(&own_ip, &port);
|
||||
if (hlisten == -1) {
|
||||
if (hlisten == NULL) {
|
||||
close(hfile);
|
||||
cmd_param_error(CMDERR_ERRNO);
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ GSList *dcc_conns;
|
||||
static int dcc_timeouttag;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
DCC_REC *dcc;
|
||||
@ -110,7 +110,7 @@ void dcc_destroy(DCC_REC *dcc)
|
||||
signal_emit("dcc destroyed", 1, dcc);
|
||||
|
||||
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->tagread != -1) g_source_remove(dcc->tagread);
|
||||
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) {
|
||||
/* same DCC request offered again */
|
||||
if (olddcc->type == DCC_TYPE_CHAT &&
|
||||
olddcc->handle != -1 && olddcc->starttime == 0) {
|
||||
olddcc->handle != NULL && olddcc->starttime == 0) {
|
||||
/* we requested dcc chat, they requested
|
||||
dcc chat from us .. allow it. */
|
||||
dcc_destroy(olddcc);
|
||||
} else {
|
||||
/* if the connection isn't open, update the port,
|
||||
otherwise just ignore */
|
||||
if (olddcc->handle == -1)
|
||||
if (olddcc->handle == NULL)
|
||||
olddcc->port = port;
|
||||
cmd_params_free(free_arg);
|
||||
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);
|
||||
net_ip2host(&dcc->addr, dcc->addrstr);
|
||||
dcc->port = port;
|
||||
|
@ -40,7 +40,7 @@ typedef struct DCC_REC {
|
||||
int port; /* port we're connected in */
|
||||
|
||||
long size, transfd, skipped; /* file size / bytes transferred / skipped at start */
|
||||
int handle; /* socket handle */
|
||||
GIOChannel *handle; /* socket handle */
|
||||
void *sendbuf;
|
||||
int tagconn, tagread, tagwrite;
|
||||
int fhandle; /* file handle */
|
||||
@ -80,7 +80,7 @@ const char *dcc_type2str(int type);
|
||||
int dcc_str2type(const char *type);
|
||||
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);
|
||||
|
||||
/* Send a CTCP message/notify to target. Send the CTCP via DCC chat if
|
||||
|
Loading…
Reference in New Issue
Block a user