diff options
author | Timo Sirainen <cras@irssi.org> | 2003-10-01 16:02:43 +0000 |
---|---|---|
committer | cras <cras@dbcabf3a-b0e7-0310-adc4-f8d773084564> | 2003-10-01 16:02:43 +0000 |
commit | 65463924d217501bb07c02e1e760669130329af0 (patch) | |
tree | acfa99d520f34068b3cfd41efeb0f3721a7a959c | |
parent | 579c1c2efd1e95ab510aeae80ff615791bb03053 (diff) | |
download | irssi-65463924d217501bb07c02e1e760669130329af0.zip |
Added DCC SERVER support by Mark Trumbull
git-svn-id: http://svn.irssi.org/repos/irssi/trunk@3127 dbcabf3a-b0e7-0310-adc4-f8d773084564
-rw-r--r-- | docs/help/in/dcc.in | 4 | ||||
-rw-r--r-- | src/fe-common/irc/dcc/Makefile.am | 3 | ||||
-rw-r--r-- | src/fe-common/irc/dcc/fe-dcc.c | 5 | ||||
-rw-r--r-- | src/fe-common/irc/dcc/module-formats.c | 3 | ||||
-rw-r--r-- | src/fe-common/irc/dcc/module-formats.h | 5 | ||||
-rw-r--r-- | src/irc/dcc/Makefile.am | 6 | ||||
-rw-r--r-- | src/irc/dcc/dcc-chat.c | 4 | ||||
-rw-r--r-- | src/irc/dcc/dcc-get.c | 40 | ||||
-rw-r--r-- | src/irc/dcc/dcc-get.h | 1 | ||||
-rw-r--r-- | src/irc/dcc/dcc-server.c | 416 | ||||
-rw-r--r-- | src/irc/dcc/dcc-server.h | 30 | ||||
-rw-r--r-- | src/irc/dcc/dcc.c | 10 |
12 files changed, 506 insertions, 21 deletions
diff --git a/docs/help/in/dcc.in b/docs/help/in/dcc.in index e2a3da3a..48e7c0ab 100644 --- a/docs/help/in/dcc.in +++ b/docs/help/in/dcc.in @@ -22,6 +22,10 @@ files. queues them. File names may contain shell expansion characters: * ? [] ~ (~ expansion may not be supported on all platforms). Files with spaces in their names need to be quoted (eg. "file name"). +/DCC SERVER [<+|-scf> <port>] + - Starts a DCC SERVER on the specified port. The remote can connect to this + server and initiate chat, send and fserve requests. You can specify + or - + using any combination of the flags 's' (Send), 'c' (Chat), or 'f' (Fserver). /DCC CLOSE <type> <nick> [<file>] - Closes a DCC-connection. Type can be either SEND, GET or CHAT. diff --git a/src/fe-common/irc/dcc/Makefile.am b/src/fe-common/irc/dcc/Makefile.am index dbe31f30..84813cfb 100644 --- a/src/fe-common/irc/dcc/Makefile.am +++ b/src/fe-common/irc/dcc/Makefile.am @@ -16,7 +16,8 @@ libfe_irc_dcc_a_SOURCES = \ fe-dcc-chat-messages.c \ fe-dcc-get.c \ fe-dcc-send.c \ - module-formats.c + module-formats.c \ + fe-dcc-server.c noinst_HEADERS = \ module.h \ diff --git a/src/fe-common/irc/dcc/fe-dcc.c b/src/fe-common/irc/dcc/fe-dcc.c index 8d82c3ba..38ac07a4 100644 --- a/src/fe-common/irc/dcc/fe-dcc.c +++ b/src/fe-common/irc/dcc/fe-dcc.c @@ -42,6 +42,9 @@ void fe_dcc_get_deinit(void); void fe_dcc_send_init(void); void fe_dcc_send_deinit(void); +void fe_dcc_server_init(void); +void fe_dcc_server_deinit(void); + char *dcc_get_size_str(uoff_t size) { if (size < 1024) @@ -155,6 +158,7 @@ void fe_irc_dcc_init(void) fe_dcc_chat_init(); fe_dcc_get_init(); fe_dcc_send_init(); + fe_dcc_server_init(); signal_add("dcc request", (SIGNAL_FUNC) dcc_request); signal_add("dcc rejected", (SIGNAL_FUNC) dcc_rejected); @@ -173,6 +177,7 @@ void fe_irc_dcc_deinit(void) fe_dcc_chat_deinit(); fe_dcc_get_deinit(); fe_dcc_send_deinit(); + fe_dcc_server_deinit(); theme_unregister(); diff --git a/src/fe-common/irc/dcc/module-formats.c b/src/fe-common/irc/dcc/module-formats.c index 13258819..b8eb4a0a 100644 --- a/src/fe-common/irc/dcc/module-formats.c +++ b/src/fe-common/irc/dcc/module-formats.c @@ -71,6 +71,9 @@ FORMAT_REC fecommon_irc_dcc_formats[] = { { "dcc_list_line_file", "{dcc $0 $1: %|$2 of $3 ($4%%) - $5kB/s - ETA $7 - $6}", 8, { 0, 0, 0, 0, 1, 3, 0, 0 } }, { "dcc_list_line_queued_send", "{dcc - $0 $2 (queued)}", 3, { 0, 0, 0 } }, { "dcc_list_footer", "", 0 }, + { "dcc_list_line_server", "{dcc $0: Port($1) - Send($2) - Chat($3) - Fserve($4)}", 5, { 0, 1, 0, 0, 0 } }, + { "dcc_server_started", "{dcc DCC SERVER started on port {hilight $0}}", 1, { 1 } }, + { "dcc_server_closed", "{dcc DCC SERVER on port {hilight $0} closed}", 1, { 1 } }, { NULL, NULL, 0 } }; diff --git a/src/fe-common/irc/dcc/module-formats.h b/src/fe-common/irc/dcc/module-formats.h index b2266816..d1bcc3ba 100644 --- a/src/fe-common/irc/dcc/module-formats.h +++ b/src/fe-common/irc/dcc/module-formats.h @@ -48,7 +48,10 @@ enum { IRCTXT_DCC_LIST_LINE_CHAT, IRCTXT_DCC_LIST_LINE_FILE, IRCTXT_DCC_LIST_LINE_QUEUED_SEND, - IRCTXT_DCC_LIST_FOOTER + IRCTXT_DCC_LIST_FOOTER, + IRCTXT_DCC_LIST_LINE_SERVER, + IRCTXT_DCC_SERVER_STARTED, + IRCTXT_DCC_SERVER_CLOSED }; extern FORMAT_REC fecommon_irc_dcc_formats[]; diff --git a/src/irc/dcc/Makefile.am b/src/irc/dcc/Makefile.am index 85ccdac7..d2b1cf02 100644 --- a/src/irc/dcc/Makefile.am +++ b/src/irc/dcc/Makefile.am @@ -13,7 +13,8 @@ libirc_dcc_a_SOURCES = \ dcc-send.c \ dcc-resume.c \ dcc-autoget.c \ - dcc-queue.c + dcc-queue.c \ + dcc-server.c noinst_HEADERS = \ dcc-rec.h \ @@ -24,4 +25,5 @@ noinst_HEADERS = \ dcc-get.h \ dcc-send.h \ dcc-queue.h \ - module.h + module.h \ + dcc-server.h diff --git a/src/irc/dcc/dcc-chat.c b/src/irc/dcc/dcc-chat.c index d7ae68df..3d97ae0c 100644 --- a/src/irc/dcc/dcc-chat.c +++ b/src/irc/dcc/dcc-chat.c @@ -55,7 +55,7 @@ static char *dcc_chat_get_new_id(const char *nick) } } -static CHAT_DCC_REC *dcc_chat_create(IRC_SERVER_REC *server, +CHAT_DCC_REC *dcc_chat_create(IRC_SERVER_REC *server, CHAT_DCC_REC *chat, const char *nick, const char *arg) { @@ -285,7 +285,7 @@ static void cmd_ctcp(const char *data, SERVER_REC *server) } /* input function: DCC CHAT received some data.. */ -static void dcc_chat_input(CHAT_DCC_REC *dcc) +void dcc_chat_input(CHAT_DCC_REC *dcc) { char tmpbuf[512], *str; int recvlen, ret; diff --git a/src/irc/dcc/dcc-get.c b/src/irc/dcc/dcc-get.c index 9340645d..aa0c6390 100644 --- a/src/irc/dcc/dcc-get.c +++ b/src/irc/dcc/dcc-get.c @@ -31,7 +31,7 @@ static int dcc_file_create_mode; -static GET_DCC_REC *dcc_get_create(IRC_SERVER_REC *server, CHAT_DCC_REC *chat, +GET_DCC_REC *dcc_get_create(IRC_SERVER_REC *server, CHAT_DCC_REC *chat, const char *nick, const char *arg) { GET_DCC_REC *dcc; @@ -172,21 +172,23 @@ static void sig_dccget_receive(GET_DCC_REC *dcc) } /* callback: net_connect() finished for DCC GET */ -static void sig_dccget_connected(GET_DCC_REC *dcc) +void sig_dccget_connected(GET_DCC_REC *dcc) { struct stat statbuf; - char *fname, *tempfname; + char *fname, *tempfname, *str; int ret, ret_errno, temphandle, old_umask; - if (net_geterror(dcc->handle) != 0) { - /* error connecting */ - signal_emit("dcc error connect", 1, dcc); - dcc_destroy(DCC(dcc)); - return; - } + if (!dcc->from_dccserver) { + if (net_geterror(dcc->handle) != 0) { + /* error connecting */ + signal_emit("dcc error connect", 1, dcc); + dcc_destroy(DCC(dcc)); + return; + } - g_source_remove(dcc->tagconn); - dcc->tagconn = -1; + g_source_remove(dcc->tagconn); + dcc->tagconn = -1; + } g_free_not_null(dcc->file); dcc->file = dcc_get_download_path(dcc->arg); @@ -253,6 +255,12 @@ static void sig_dccget_connected(GET_DCC_REC *dcc) dcc->tagread = g_input_add(dcc->handle, G_INPUT_READ, (GInputFunction) sig_dccget_receive, dcc); signal_emit("dcc connected", 1, dcc); + + if (dcc->from_dccserver) { + str = g_strdup_printf("121 %s %d\n", + dcc->server ? dcc->server->nick : "??", 0); + net_transmit(dcc->handle, str, strlen(str)); + } } void dcc_get_connect(GET_DCC_REC *dcc) @@ -262,7 +270,13 @@ void dcc_get_connect(GET_DCC_REC *dcc) DCC_GET_RENAME : DCC_GET_OVERWRITE; } + if (dcc->from_dccserver) { + sig_dccget_connected(dcc); + return; + } + dcc->handle = dcc_connect_ip(&dcc->addr, dcc->port); + if (dcc->handle != NULL) { dcc->tagconn = g_input_add(dcc->handle, @@ -408,8 +422,8 @@ void cmd_dcc_receive(const char *data, DCC_GET_FUNC accept_func) GET_DCC_REC *dcc = tmp->data; next = tmp->next; - if (IS_DCC_GET(dcc) && dcc_is_waiting_user(dcc) && - g_strcasecmp(dcc->nick, nick) == 0 && + if (IS_DCC_GET(dcc) && g_strcasecmp(dcc->nick, nick) == 0 && + (dcc_is_waiting_user(dcc) || dcc->from_dccserver) && (*fname == '\0' || strcmp(dcc->arg, fname) == 0)) { found = TRUE; accept_func(dcc); diff --git a/src/irc/dcc/dcc-get.h b/src/irc/dcc/dcc-get.h index 65f5b682..321a8b4e 100644 --- a/src/irc/dcc/dcc-get.h +++ b/src/irc/dcc/dcc-get.h @@ -24,6 +24,7 @@ typedef struct { char *file; /* file name we're really moving, arg is just the reference */ unsigned int file_quoted:1; /* file name was received quoted ("file name") */ + unsigned int from_dccserver:1; /* get is using dccserver method */ } GET_DCC_REC; #define DCC_GET_TYPE module_get_uniq_id_str("DCC", "GET") diff --git a/src/irc/dcc/dcc-server.c b/src/irc/dcc/dcc-server.c new file mode 100644 index 00000000..0a073a9d --- /dev/null +++ b/src/irc/dcc/dcc-server.c @@ -0,0 +1,416 @@ +/* + dcc-server.c : irssi + + Copyright (C) 2003 Mark Trumbull + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "module.h" +#include "signals.h" +#include "commands.h" +#include "network.h" +#include "net-sendbuffer.h" +#include "line-split.h" +#include "misc.h" + +#include "irc-servers.h" + +#include "dcc-chat.h" +#include "dcc-get.h" +#include "dcc-server.h" + +void sig_dccget_connected(GET_DCC_REC *dcc); +GET_DCC_REC *dcc_get_create(IRC_SERVER_REC *server, CHAT_DCC_REC *chat, + const char *nick, const char *arg); + +void dcc_chat_input(CHAT_DCC_REC *dcc); +CHAT_DCC_REC *dcc_chat_create(IRC_SERVER_REC *server, CHAT_DCC_REC *chat, + const char *nick, const char *arg); + +static void sig_dcc_destroyed(SERVER_DCC_REC *dcc) +{ + if (!IS_DCC_SERVER(dcc)) + return; + + if (dcc->sendbuf != NULL) + net_sendbuffer_destroy(dcc->sendbuf, FALSE); + line_split_free(dcc->readbuf); +} + +/* Start listening for incoming connections */ +static GIOChannel *dcc_listen_port(GIOChannel *iface, IPADDR *ip, int port) +{ + if (net_getsockname(iface, ip, NULL) == -1) + return NULL; + + if (IPADDR_IS_V6(ip)) + return net_listen(NULL, &port); + else + return net_listen(&ip4_any, &port); +} + +/* input function: DCC SERVER received some data.. */ +static void dcc_server_input(SERVER_DCC_REC *dcc) +{ + char tmpbuf[512], *str; + int recvlen, ret; + + g_return_if_fail(IS_DCC_SERVER(dcc)); + + do { + recvlen = net_receive(dcc->handle, tmpbuf, sizeof(tmpbuf)); + + ret = line_split(tmpbuf, recvlen, &str, &dcc->readbuf); + if (ret == -1) { + /* connection lost */ + dcc_close(DCC(dcc)); + break; + } + + if (ret > 0) { + dcc->transfd += ret; + signal_emit("dcc server message", 2, dcc, str); + } + + if (dcc->connection_established) { + /* We set handle to NULL first because the new (chat/get) is using the same */ + /* handle and we don't want dcc_close to disconnect it.*/ + dcc->handle = NULL; + dcc_close(DCC(dcc)); + break; + } + } while (ret > 0); +} + +static void dcc_server_update_flags(SERVER_DCC_REC *dcc, const char *flags) +{ + g_return_if_fail(dcc != NULL); + g_return_if_fail(IS_DCC_SERVER(dcc)); + + if (*flags == '+' || *flags == '-') { + const char *ptr = flags + 1; + unsigned int value = (*flags == '+') ? 1 : 0; + + while (*ptr) { + if (*ptr == 's' || *ptr == 'S') { dcc->accept_send = value; } + else if (*ptr == 'c' || *ptr == 'C') { dcc->accept_chat = value; } + else if (*ptr == 'f' || *ptr == 'F') { dcc->accept_fserve = value; } + ptr++; + } + } +} + +/* Initialize DCC record */ +static void dcc_init_server_rec(SERVER_DCC_REC *dcc, IRC_SERVER_REC *server) +{ + g_return_if_fail(dcc != NULL); + g_return_if_fail(server != NULL); + g_return_if_fail(IS_DCC_SERVER(dcc)); + + MODULE_DATA_INIT(dcc); + dcc->created = time(NULL); + dcc->chat = NULL; + dcc->arg = NULL; + dcc->nick = NULL; + dcc->tagconn = dcc->tagread = dcc->tagwrite = -1; + dcc->server = server; + dcc->mynick = g_strdup(server != NULL ? server->nick : "??"); + dcc->servertag = server != NULL ? g_strdup(server->tag) : NULL; + + dcc_conns = g_slist_append(dcc_conns, dcc); + signal_emit("dcc created", 1, dcc); +} + +static SERVER_DCC_REC *dcc_server_create(IRC_SERVER_REC *server, const char *flags) +{ + SERVER_DCC_REC *dcc; + + dcc = g_new0(SERVER_DCC_REC, 1); + dcc->orig_type = dcc->type = DCC_SERVER_TYPE; + dcc_server_update_flags(dcc, flags); + + dcc_init_server_rec(dcc, server); + return dcc; +} + +static SERVER_DCC_REC *dcc_server_clone(SERVER_DCC_REC *dcc) +{ + SERVER_DCC_REC *newdcc; + + g_return_val_if_fail(IS_DCC_SERVER(dcc), NULL); + + newdcc = g_new0(SERVER_DCC_REC, 1); + newdcc->orig_type = newdcc->type = DCC_SERVER_TYPE; + newdcc->accept_send = dcc->accept_send; + newdcc->accept_chat = dcc->accept_chat; + newdcc->accept_fserve = dcc->accept_fserve; + + dcc_init_server_rec(newdcc, dcc->server); + return newdcc; +} + +/* input function: DCC SERVER - someone tried to connect to our socket */ +static void dcc_server_listen(SERVER_DCC_REC *dcc) +{ + SERVER_DCC_REC *newdcc; + IPADDR ip; + GIOChannel *handle; + int port; + + g_return_if_fail(IS_DCC_SERVER(dcc)); + + /* accept connection */ + handle = net_accept(dcc->handle, &ip, &port); + if (handle == NULL) + return; + + /* Create a new DCC SERVER to handle this connection */ + newdcc = dcc_server_clone(dcc); + + newdcc->starttime = time(NULL); + newdcc->handle = handle; + newdcc->sendbuf = net_sendbuffer_create(handle, 0); + memcpy(&newdcc->addr, &ip, sizeof(IPADDR)); + net_ip2host(&newdcc->addr, newdcc->addrstr); + newdcc->port = port; + newdcc->tagread = g_input_add(handle, G_INPUT_READ, + (GInputFunction) dcc_server_input, newdcc); + + signal_emit("dcc connected", 1, newdcc); +} + +/* DCC SERVER: text received */ +static void dcc_server_msg(SERVER_DCC_REC *dcc, const char *msg) +{ + g_return_if_fail(IS_DCC_SERVER(dcc)); + g_return_if_fail(msg != NULL); + + /* Check for CHAT protocol */ + if (g_strncasecmp(msg, "100 ", 4) == 0) { + msg += 4; + /* Check if this server is accepting chat requests.*/ + if (dcc->accept_chat) { + /* Connect and start DCC Chat */ + char *str; + CHAT_DCC_REC *dccchat = dcc_chat_create(dcc->server, NULL, msg, "chat"); + + dccchat->starttime = time(NULL); + dccchat->handle = dcc->handle; + dccchat->sendbuf = net_sendbuffer_create(dccchat->handle, 0); + memcpy(&dccchat->addr, &dcc->addr, sizeof(IPADDR)); + net_ip2host(&dccchat->addr, dccchat->addrstr); + dccchat->port = dcc->port; + dccchat->tagread = g_input_add(dccchat->handle, G_INPUT_READ, + (GInputFunction) dcc_chat_input, dccchat); + + dcc->connection_established = 1; + signal_emit("dcc connected", 1, dccchat); + + str = g_strdup_printf("101 %s\n", + (dccchat->server) ? dccchat->server->nick : "??"); + net_sendbuffer_send(dccchat->sendbuf, str, strlen(str)); + g_free(str); + } + } + + /* Check for FSERVE protocol */ + if (g_strncasecmp(msg, "110 ", 4) == 0) { + msg += 4; + /* Check if this server is accepting fserve requests.*/ + if (dcc->accept_fserve) { + /* TODO - Connect and start DCC Fserve */ + } + } + + /* Check for SEND protocol */ + if (g_strncasecmp(msg, "120 ", 4) == 0) { + msg += 4; + /* Check if this server is accepting send requests.*/ + if (dcc->accept_send) { + /* Connect and start DCC Send */ + GET_DCC_REC *dccget; + char **params, *fname, *nick; + int paramcount, len, quoted = FALSE; + uoff_t size; + + /* 120 clientnickname filesize filename */ + params = g_strsplit(msg, " ", -1); + paramcount = strarray_length(params); + + if (paramcount < 3) { + g_strfreev(params); + signal_stop(); + return; + } + + nick = params[0]; + size = str_to_uofft(params[1]); + fname = g_strjoinv(" ", ¶ms[2]); + + len = strlen(fname); + if (len > 1 && *fname == '"' && fname[len-1] == '"') { + /* "file name" - MIRC sends filenames with spaces like this */ + fname[len-1] = '\0'; + g_memmove(fname, fname+1, len); + quoted = TRUE; + } + + dccget = dcc_get_create(dcc->server, NULL, nick, fname); + dccget->handle = dcc->handle; + dccget->target = g_strdup(dcc->server ? dcc->server->nick : "??"); + memcpy(&dccget->addr, &dcc->addr, sizeof(dcc->addr)); + if (dccget->addr.family == AF_INET) { + net_ip2host(&dccget->addr, dccget->addrstr); + } else { + /* with IPv6, show it to us as it was sent */ + memcpy(dccget->addrstr, dcc->addrstr, sizeof(dccget->addrstr)); + } + dccget->port = dcc->port; + dccget->size = size; + dccget->file_quoted = quoted; + dccget->from_dccserver = 1; + + dcc->connection_established = 1; + signal_emit("dcc request", 2, dccget, dccget->addrstr); + + g_strfreev(params); + g_free(fname); + } + } + + signal_stop(); +} + +SERVER_DCC_REC *dcc_server_find_port(const char *port_str) +{ + GSList *tmp; + unsigned int port = 0; + + g_return_val_if_fail(port_str != NULL, NULL); + + port = atoi(port_str); + + for (tmp = dcc_conns; tmp != NULL; tmp = tmp->next) { + SERVER_DCC_REC *dcc = tmp->data; + + if (IS_DCC_SERVER(dcc) && dcc->port == port) + return dcc; + } + + return NULL; +} + +/* SYNTAX: DCC SERVER [+|-scf] [port] */ +static void cmd_dcc_server(const char *data, IRC_SERVER_REC *server) +{ + void *free_arg; + GIOChannel *handle; + SERVER_DCC_REC *dcc; + IPADDR own_ip; + char *flags, *port; + + g_return_if_fail(data != NULL); + + if (!cmd_get_params(data, &free_arg, 2, &flags, &port)) + return; + + dcc = dcc_server_find_port(port); + if (dcc != NULL) { + /* Server is already running, update it */ + dcc_server_update_flags(dcc, flags); + cmd_params_free(free_arg); + return; + } + + /* start listening */ + if (!IS_IRC_SERVER(server) || !server->connected) { + cmd_param_error(CMDERR_NOT_CONNECTED); + } + + handle = dcc_listen_port(net_sendbuffer_handle(server->handle), + &own_ip, atoi(port)); + + if (handle == NULL) { + cmd_param_error(CMDERR_ERRNO); + } + + dcc = dcc_server_create(server, flags); + dcc->handle = handle; + dcc->port = atoi(port); + dcc->tagconn = g_input_add(dcc->handle, G_INPUT_READ, + (GInputFunction) dcc_server_listen, dcc); + + signal_emit("dcc server started", 1, dcc); + + cmd_params_free(free_arg); +} + +/* DCC CLOSE SERVER <port> */ +static void cmd_dcc_close(char *data, SERVER_REC *server) +{ + GSList *tmp, *next; + char *port_str; + void *free_arg; + int found, port; + + g_return_if_fail(data != NULL); + + if (g_strncasecmp(data, "SERVER ", 7) != 0 || + !cmd_get_params(data, &free_arg, 2, NULL, &port_str)) { + return; + } + + if (*port_str == '\0') { + cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); + } + + port = atoi(port_str); + found = FALSE; + for (tmp = dcc_conns; tmp != NULL; tmp = next) { + SERVER_DCC_REC *dcc = tmp->data; + + next = tmp->next; + if (IS_DCC_SERVER(dcc) && dcc->port == port) { + found = TRUE; + dcc_close(DCC(dcc)); + } + } + + if (found) { + signal_stop(); + } + + cmd_params_free(free_arg); +} + +void dcc_server_init(void) +{ + dcc_register_type("SERVER"); + command_bind("dcc server", NULL, (SIGNAL_FUNC) cmd_dcc_server); + command_bind("dcc close", NULL, (SIGNAL_FUNC) cmd_dcc_close); + signal_add("dcc destroyed", (SIGNAL_FUNC) sig_dcc_destroyed); + signal_add_first("dcc server message", (SIGNAL_FUNC) dcc_server_msg); +} + +void dcc_server_deinit(void) +{ + dcc_unregister_type("SERVER"); + command_unbind("dcc server", (SIGNAL_FUNC) cmd_dcc_server); + command_unbind("dcc close", (SIGNAL_FUNC) cmd_dcc_close); + signal_remove("dcc destroyed", (SIGNAL_FUNC) sig_dcc_destroyed); + signal_remove("dcc server message", (SIGNAL_FUNC) dcc_server_msg); +} + diff --git a/src/irc/dcc/dcc-server.h b/src/irc/dcc/dcc-server.h new file mode 100644 index 00000000..4f6f248e --- /dev/null +++ b/src/irc/dcc/dcc-server.h @@ -0,0 +1,30 @@ +#ifndef __DCC_SERVER_H +#define __DCC_SERVER_H + +#include "dcc.h" + +#define DCC_SERVER(dcc) \ + MODULE_CHECK_CAST_MODULE(dcc, SERVER_DCC_REC, type, "DCC", "SERVER") + +#define IS_DCC_SERVER(dcc) \ + (DCC_SERVER(dcc) ? TRUE : FALSE) + +struct SERVER_DCC_REC { +#include "dcc-rec.h" + LINEBUF_REC *readbuf; + NET_SENDBUF_REC *sendbuf; + + unsigned int accept_send:1; /* Accept SEND connections */ + unsigned int accept_chat:1; /* Accept CHAT connections */ + unsigned int accept_fserve:1; /* Accept FSERVE connections */ + unsigned int connection_established:1; /* We have made a connection */ +}; + +#define DCC_SERVER_TYPE module_get_uniq_id_str("DCC", "SERVER") + +typedef struct SERVER_DCC_REC SERVER_DCC_REC; + +void dcc_server_init(void); +void dcc_server_deinit(void); + +#endif diff --git a/src/irc/dcc/dcc.c b/src/irc/dcc/dcc.c index 8bbca251..2fd6317f 100644 --- a/src/irc/dcc/dcc.c +++ b/src/irc/dcc/dcc.c @@ -34,6 +34,7 @@ #include "dcc-chat.h" #include "dcc-get.h" #include "dcc-send.h" +#include "dcc-server.h" void dcc_resume_init(void); void dcc_resume_deinit(void); @@ -431,11 +432,13 @@ static int dcc_timeout_func(void) DCC_REC *dcc = tmp->data; next = tmp->next; - if (dcc->tagread == -1 && now > dcc->created) { + if (dcc->tagread == -1 && now > dcc->created && !IS_DCC_SERVER(dcc)) { /* Timed out - don't send DCC REJECT CTCP so CTCP flooders won't affect us and it really doesn't matter that much anyway if the other side doen't - get it.. */ + get it.. + + We don't want dcc servers to time out. */ dcc_close(dcc); } } @@ -540,6 +543,7 @@ void irc_dcc_init(void) dcc_send_init(); dcc_resume_init(); dcc_autoget_init(); + dcc_server_init(); module_register("dcc", "irc"); } @@ -554,6 +558,7 @@ void irc_dcc_deinit(void) dcc_send_deinit(); dcc_resume_deinit(); dcc_autoget_deinit(); + dcc_server_deinit(); signal_remove("event connected", (SIGNAL_FUNC) sig_connected); signal_remove("server disconnected", (SIGNAL_FUNC) sig_server_disconnected); @@ -569,3 +574,4 @@ void irc_dcc_deinit(void) g_source_remove(dcc_timeouttag); } + |