On Thu, Feb 13, 2003 at 09:42:55AM +0000, Athanasius wrote: > I've only just gotten the DCC GET working yesterday and haven't had > chance to test vanilla CVS to see if the same problem is there. I'll > try and get to that today and post a patch whatever by the end of the > day.
OK, it didn't like the changes in fe-common/irc/dcc/module-formats.h I'd made but actually never used, looks to be working now. Patch attached. This defines 5 new variables: 11:19 [dcc] 11:19 dcc_server_port = 9008 11:19 dcc_server_send = ON 11:19 dcc_server_fserve = OFF 11:19 dcc_server_chat = ON 11:19 dcc_server = ON dcc_server turns the whole thing on or off. dcc_server_port sets the port you listen on locally. Either change this to suit the fserve you're using, or you can do as I do if you have root and simply redirect requisite ip:port's to this port which also means I can make use of servers using port 59, for example. dcc_server_chat controls whether or not the client accepts chats done this way. dcc_server_send controls whether or not the client accepts file transfers done this way. dcc_server_fserve is there but currently unsupported (I've not seen anything using it). As for the patch itself, as I said before it's HACKY. Anyone more familiar with the irssi DCC code can feel free to rework it to be less hacky. Possibly re-working all of the DCC CHAT/SEND to split into parts that accept connection and then another that finishes setting things up once you have the open connection. src/irc/dcc/dcc-server.c is the heart of things (and the mess ;), with a few changes to other files in that directory, plus core/network.c to support the changes. Normal DCC CHAT/GEt should be entirely unaffected by these changes. It's POSSIBLE I've still got a race condition or two in there between reading a command on the initial TCP connection and converting it into a chat/get, but I think I finally got that sorted out. dcc_server_nick_resolve() is a horrible hack to match up an incoming connection to a server:nick we can currently see. convert_dcc_server_to_chat() and convert_dcc_server_to_send() are the bits that munge the extant TCP connection into a DCC CHAT or GET as required. I've actually only tested this locally so far, using mirc/sysreset under wine and a local ircd, so if there are any race conditions or bugs lurking in there using it on a full network will probably show them up. -Ath -- - Athanasius = Athanasius(at)miggy.org / http://www.miggy.org/ Finger athan(at)fysh.org for PGP key "And it's me who is my enemy. Me who beats me up. Me who makes the monsters. Me who strips my confidence." Paula Cole - ME
diff -r -u -N --exclude-from=irssi-dontdiff irssi-CVS-200302131108/src/core/network.c
irssi-CVS/src/core/network.c
--- irssi-CVS-200302131108/src/core/network.c Tue Dec 10 16:36:26 2002
+++ irssi-CVS/src/core/network.c Thu Feb 13 10:28:42 2003
@@ -410,6 +410,26 @@
return 0;
}
+/* Get socket peer address/port */
+int net_getpeername(GIOChannel *handle, IPADDR *addr, int *port)
+{
+ union sockaddr_union so;
+ socklen_t addrlen;
+
+ g_return_val_if_fail(handle != NULL, -1);
+ g_return_val_if_fail(addr != NULL, -1);
+
+ addrlen = sizeof(so);
+ if (getpeername(g_io_channel_unix_get_fd(handle),
+ (struct sockaddr *) &so, &addrlen) == -1)
+ return -1;
+
+ sin_get_ip(&so, addr);
+ if (port) *port = sin_get_port(&so);
+
+ return 0;
+}
+
/* Get IP addresses for host, both IPv4 and IPv6 if possible.
If ip->family is 0, the address wasn't found.
Returns 0 = ok, others = error code for net_gethosterror() */
diff -r -u -N --exclude-from=irssi-dontdiff
irssi-CVS-200302131108/src/irc/dcc/Makefile irssi-CVS/src/irc/dcc/Makefile
--- irssi-CVS-200302131108/src/irc/dcc/Makefile Thu Feb 13 11:10:43 2003
+++ irssi-CVS/src/irc/dcc/Makefile Thu Feb 13 10:55:15 2003
@@ -116,7 +116,7 @@
INCLUDES = -I$(top_srcdir)/src -I$(top_srcdir)/src/core/
-I$(top_srcdir)/src/irc/core/ $(GLIB_CFLAGS)
-libirc_dcc_a_SOURCES = dcc.c dcc-chat.c dcc-get.c dcc-send.c
dcc-resume.c dcc-autoget.c dcc-queue.c
+libirc_dcc_a_SOURCES = dcc.c dcc-chat.c dcc-get.c dcc-send.c
+ dcc-resume.c dcc-autoget.c dcc-queue.c dcc-server.c
noinst_HEADERS = dcc-rec.h dcc-file-rec.h dcc.h dcc-file.h
dcc-chat.h dcc-get.h dcc-send.h dcc-queue.h module.h
@@ -134,7 +134,7 @@
libirc_dcc_a_LIBADD =
libirc_dcc_a_OBJECTS = dcc.$(OBJEXT) dcc-chat.$(OBJEXT) \
dcc-get.$(OBJEXT) dcc-send.$(OBJEXT) dcc-resume.$(OBJEXT) \
-dcc-autoget.$(OBJEXT) dcc-queue.$(OBJEXT)
+dcc-autoget.$(OBJEXT) dcc-queue.$(OBJEXT) dcc-server.$(OBJEXT)
AR = ar
CFLAGS =
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@@ -151,7 +151,8 @@
TAR = tar
GZIP_ENV = --best
DEP_FILES = .deps/dcc-autoget.P .deps/dcc-chat.P .deps/dcc-get.P \
-.deps/dcc-queue.P .deps/dcc-resume.P .deps/dcc-send.P .deps/dcc.P
+.deps/dcc-queue.P .deps/dcc-resume.P .deps/dcc-send.P \
+.deps/dcc-server.P .deps/dcc.P
SOURCES = $(libirc_dcc_a_SOURCES)
OBJECTS = $(libirc_dcc_a_OBJECTS)
diff -r -u -N --exclude-from=irssi-dontdiff
irssi-CVS-200302131108/src/irc/dcc/Makefile.am irssi-CVS/src/irc/dcc/Makefile.am
--- irssi-CVS-200302131108/src/irc/dcc/Makefile.am Mon Nov 11 06:35:12 2002
+++ irssi-CVS/src/irc/dcc/Makefile.am Thu Feb 13 10:28:42 2003
@@ -13,7 +13,8 @@
dcc-send.c \
dcc-resume.c \
dcc-autoget.c \
- dcc-queue.c
+ dcc-queue.c \
+ dcc-server.c
noinst_HEADERS = \
dcc-rec.h \
diff -r -u -N --exclude-from=irssi-dontdiff
irssi-CVS-200302131108/src/irc/dcc/Makefile.in irssi-CVS/src/irc/dcc/Makefile.in
--- irssi-CVS-200302131108/src/irc/dcc/Makefile.in Thu Feb 13 11:10:38 2003
+++ irssi-CVS/src/irc/dcc/Makefile.in Thu Feb 13 10:28:42 2003
@@ -116,7 +116,7 @@
INCLUDES = -I$(top_srcdir)/src -I$(top_srcdir)/src/core/
-I$(top_srcdir)/src/irc/core/ $(GLIB_CFLAGS)
-libirc_dcc_a_SOURCES = dcc.c dcc-chat.c dcc-get.c dcc-send.c
dcc-resume.c dcc-autoget.c dcc-queue.c
+libirc_dcc_a_SOURCES = dcc.c dcc-chat.c dcc-get.c dcc-send.c
+ dcc-resume.c dcc-autoget.c dcc-queue.c dcc-server.c
noinst_HEADERS = dcc-rec.h dcc-file-rec.h dcc.h dcc-file.h
dcc-chat.h dcc-get.h dcc-send.h dcc-queue.h module.h
@@ -134,7 +134,7 @@
libirc_dcc_a_LIBADD =
libirc_dcc_a_OBJECTS = dcc.$(OBJEXT) dcc-chat.$(OBJEXT) \
dcc-get.$(OBJEXT) dcc-send.$(OBJEXT) dcc-resume.$(OBJEXT) \
-dcc-autoget.$(OBJEXT) dcc-queue.$(OBJEXT)
+dcc-autoget.$(OBJEXT) dcc-queue.$(OBJEXT) dcc-server.$(OBJEXT)
AR = ar
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@@ -151,7 +151,8 @@
TAR = tar
GZIP_ENV = --best
DEP_FILES = .deps/dcc-autoget.P .deps/dcc-chat.P .deps/dcc-get.P \
-.deps/dcc-queue.P .deps/dcc-resume.P .deps/dcc-send.P .deps/dcc.P
+.deps/dcc-queue.P .deps/dcc-resume.P .deps/dcc-send.P \
+.deps/dcc-server.P .deps/dcc.P
SOURCES = $(libirc_dcc_a_SOURCES)
OBJECTS = $(libirc_dcc_a_OBJECTS)
diff -r -u -N --exclude-from=irssi-dontdiff
irssi-CVS-200302131108/src/irc/dcc/dcc-chat.c irssi-CVS/src/irc/dcc/dcc-chat.c
--- irssi-CVS-200302131108/src/irc/dcc/dcc-chat.c Sun May 26 18:39:35 2002
+++ irssi-CVS/src/irc/dcc/dcc-chat.c Thu Feb 13 10:28:42 2003
@@ -34,7 +34,7 @@
#include "dcc-chat.h"
-static char *dcc_chat_get_new_id(const char *nick)
+char *dcc_chat_get_new_id(const char *nick)
{
char *id;
int num;
@@ -285,7 +285,7 @@
}
/* 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 -r -u -N --exclude-from=irssi-dontdiff
irssi-CVS-200302131108/src/irc/dcc/dcc-get.c irssi-CVS/src/irc/dcc/dcc-get.c
--- irssi-CVS-200302131108/src/irc/dcc/dcc-get.c Thu Nov 21 17:48:40 2002
+++ irssi-CVS/src/irc/dcc/dcc-get.c Thu Feb 13 10:28:42 2003
@@ -172,7 +172,7 @@
}
/* 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;
diff -r -u -N --exclude-from=irssi-dontdiff
irssi-CVS-200302131108/src/irc/dcc/dcc-resume.c irssi-CVS/src/irc/dcc/dcc-resume.c
--- irssi-CVS-200302131108/src/irc/dcc/dcc-resume.c Thu Nov 21 17:48:40 2002
+++ irssi-CVS/src/irc/dcc/dcc-resume.c Thu Feb 13 10:28:42 2003
@@ -123,7 +123,7 @@
}
/* Resume a DCC GET */
-static void dcc_send_resume(GET_DCC_REC *dcc)
+void dcc_send_resume(GET_DCC_REC *dcc)
{
off_t pos;
char *str;
diff -r -u -N --exclude-from=irssi-dontdiff
irssi-CVS-200302131108/src/irc/dcc/dcc-server.c irssi-CVS/src/irc/dcc/dcc-server.c
--- irssi-CVS-200302131108/src/irc/dcc/dcc-server.c Thu Jan 1 01:00:00 1970
+++ irssi-CVS/src/irc/dcc/dcc-server.c Thu Feb 13 10:13:42 2003
@@ -0,0 +1,536 @@
+/*
+ dcc-server.c : irssi
+
+ Copyright (C) 1999-2001 Timo Sirainen
+
+ 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 <ctype.h>
+
+#include "module.h"
+#include "signals.h"
+#include "commands.h"
+#include "network.h"
+#include "net-nonblock.h"
+#include "net-sendbuffer.h"
+#include "line-split.h"
+#include "misc.h"
+#include "settings.h"
+
+#include "irc-servers.h"
+#include "irc-queries.h"
+#include "masks.h"
+#include "nicklist.h"
+
+#include "dcc-server.h"
+#include "dcc-chat.h"
+#include "dcc-get.h"
+
+/* extern functions */
+extern char *dcc_chat_get_new_id(const char *nick);
+extern void dcc_chat_input(CHAT_DCC_REC *dcc);
+extern void sig_dccget_connected(GET_DCC_REC *dcc);
+
+/* Prototype local functions */
+
+void dcc_server_stop(void);
+static void sig_dcc_server_listen(void *data);
+static void dcc_server_input(DCC_SERVER_REC *rec);
+void dcc_server_destroy(DCC_SERVER_REC *rec);
+void convert_dcc_server_to_chat(DCC_SERVER_REC *rec);
+void convert_dcc_server_to_fserve(DCC_SERVER_REC *rec);
+void convert_dcc_server_to_send(DCC_SERVER_REC *rec, char *filesize,
+ char *filename);
+
+static int dcc_server;
+static u_int16_t dcc_server_port;
+static int dcc_server_chat;
+static int dcc_server_fserve;
+static int dcc_server_send;
+static int running = FALSE;
+static u_int16_t running_port = 0;
+GIOChannel *dcc_server_listen_handle = NULL;
+int dcc_server_listen_tag;
+
+void dcc_server_start(void)
+{
+ int port;
+
+ if (running)
+ {
+ /* Already running, might be able to leave it as-is, may need
+ * to make changes
+ */
+ if (running_port != dcc_server_port)
+ {
+ /* Need to restart on new port */
+ dcc_server_stop();
+ } else
+ {
+ return;
+ }
+ }
+
+ running = FALSE;
+ if (dcc_server_port < IPPORT_RESERVED)
+ {
+ g_warning("dcc_server_port must be at least %d\n", IPPORT_RESERVED);
+ return;
+ }
+ port = dcc_server_port;
+ dcc_server_listen_handle = net_listen(NULL, &port);
+ if (dcc_server_listen_handle == NULL)
+ {
+ g_warning("Couldn't start listening dcc server\n");
+ return;
+ }
+
+ running = TRUE;
+ running_port = dcc_server_port;
+ dcc_server_listen_tag = g_input_add(dcc_server_listen_handle,
+ G_INPUT_READ,
+ (GInputFunction) sig_dcc_server_listen, NULL);
+}
+
+void dcc_server_stop(void)
+{
+ if (!running)
+ {
+ return;
+ }
+
+ net_disconnect(dcc_server_listen_handle);
+ running = FALSE;
+ running_port = 0;
+}
+
+static void sig_dcc_server_listen(void *data)
+{
+ DCC_SERVER_REC *rec;
+ IPADDR ip;
+ GIOChannel *handle;
+ int ret;
+
+ handle = net_accept(dcc_server_listen_handle, &ip, NULL);
+ if (handle == NULL)
+ {
+ return;
+ }
+
+ rec = g_new0(DCC_SERVER_REC, 1);
+ rec->handle = handle;
+ rec->created = time(NULL);
+ rec->addr = ip;
+ net_ip2host(&rec->addr, rec->ipaddrstr);
+ if ((ret = net_gethostbyaddr(&rec->addr, &rec->addrstr)))
+ {
+ g_error("DCC Server: accepting connection, error - %s\n",
+net_gethosterror(ret));
+ }
+ net_getsockname(handle, &rec->addr, &rec->port);
+ rec->sendbuf = net_sendbuffer_create(handle, 0);
+ rec->tagread = g_input_add(handle, G_INPUT_READ,
+ (GInputFunction) dcc_server_input, rec);
+
+ signal_emit("dcc server connected", 1, rec);
+}
+
+static void dcc_server_input(DCC_SERVER_REC *rec)
+{
+ char tmpbuf[1024], *str;
+ int ret, recvlen;
+
+ recvlen = rec->handle == NULL ? -1 :
+ net_receive(rec->handle, tmpbuf, sizeof(tmpbuf));
+ if (recvlen == -1)
+ {
+ return;
+ }
+ ret = line_split(tmpbuf, recvlen, &str, &rec->readbuf);
+
+ if (ret != 0)
+ {
+ if (ret == -1)
+ {
+ /* connection lost */
+ dcc_server_destroy(rec);
+ } else
+ {
+ signal_emit("dcc server event", 2, rec, str);
+ memset(tmpbuf, 0, 1024);
+ }
+ }
+}
+
+void dcc_server_destroy(DCC_SERVER_REC *rec)
+{
+ line_split_free(rec->readbuf);
+ net_sendbuffer_destroy(rec->sendbuf, 0);
+ net_disconnect(rec->handle);
+}
+
+extern GSList *servers;
+
+int dcc_server_nick_resolve(DCC_SERVER_REC *rec, char *nick)
+{
+ GSList *s, *nicklist;
+ char *h;
+
+ g_return_val_if_fail(rec != NULL, FALSE);
+ rec->nickname = g_strdup(nick); /* some limit on nick length */
+ rec->id = g_strdup(nick);
+
+ /* Walk the list of servers */
+ for (s = servers ; s != NULL ; s = s->next)
+ {
+ /* Lookup rec->nick on this server */
+ SERVER_REC *server = s->data;
+ if (NULL != (nicklist = nicklist_get_same(server, rec->nickname)))
+ {
+ GSList *n;
+ NICK_REC *nick;
+ for (n = nicklist ; n != NULL ; n = n->next)
+ {
+ /* Does the nick's host match what's in rec->addr */
+ nick = n->data;
+ if (NULL == (h = strchr(nick->host, '@')))
+ {
+ continue;
+ }
+ h++;
+ if (strstr(rec->addrstr, h)
+ || strstr(rec->ipaddrstr, h))
+ {
+ rec->server = IRC_SERVER(server);
+ rec->nick = nick;
+ return TRUE;
+ }
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+/* The heart of the /dccserver protocol handling:
+ *
+ * Chat Protocol
+ * Client connects to Server and sends:
+ * 100 <client nickname>
+ * When Server receives this, it sends:
+ * 101 <server nickname>
+ * Connection is established, users can now chat.
+ *
+ * Fserve Protocol
+ * Client connects to Server and sends:
+ * 110 <client nickname>
+ * When Server receives this, it sends:
+ * 111 <server nickname>
+ * Connection is established, user can now access fserve.
+ *
+ * Send Protocol
+ * Client connects to Server and sends:
+ * 120 <client nickname> <file size> <filename>
+ * When Server receives this, it sends:
+ * 121 <server nickname> <resume position>
+ *
+ * Where resume position is between 0 and file size, and is required.
+ * Connection is established, and Server dcc gets the file.
+ *
+ * Get Protocol
+ * Client connects to Server and sends:
+ * 130 <client nickname> <filename>
+ * When Server receives this, it sends:
+ * 131 <server nickname> <file size>
+ * When Client receives this, it sends:
+ * 132 <client nickname> <resume position>
+ * Where resume position is between 0 and file size, and is required.
+ * Connection is established, and Server dcc sends the file.
+ *
+ * Other
+ * If server receives unexpected information, or doesn't receive info 15
+ * seconds after initial connection, it closes the connection.
+ *
+ * If service is unavailable, server sends:
+ * 150 unavailable
+ *
+ * If server rejects connection, it sends:
+ * 151 rejected
+ *
+ * Note the 'str' passed here has been through line_split() which strips
+ * any \n on the end, so we don't have to worry about that here.
+ */
+static void dcc_server_event(DCC_SERVER_REC *rec, char *str)
+{
+ char reply[1024];
+
+ if (!isdigit(str[0]))
+ {
+ /* Messages start with a numeric */
+ dcc_server_destroy(rec);
+ return;
+ }
+ if (!strncmp(str, "100 ", 4))
+ {
+ /* Chat request */
+ if (!settings_get_bool("dcc_server_chat"))
+ {
+ /* We're not accepting CHATs this way */
+ strncpy(reply, "150 unavailable\n", sizeof(reply) - 1);
+ net_transmit(rec->handle, reply, strlen(reply));
+ dcc_server_destroy(rec);
+ return;
+ }
+ str += 4; /* Now pointing to the nick they claim */
+ if (!dcc_server_nick_resolve(rec, str))
+ {
+ strncpy(reply, "151 rejected\n", sizeof(reply) - 1);
+ net_transmit(rec->handle, reply, strlen(reply));
+ dcc_server_destroy(rec);
+ return;
+ }
+ convert_dcc_server_to_chat(rec);
+ } else if (!strncmp(str, "110 ", 4))
+ {
+ /* Fserve request */
+ /* We don't support this */
+ strncpy(reply, "150 unavailable\n", sizeof(reply) - 1);
+ net_transmit(rec->handle, reply, strlen(reply));
+ dcc_server_destroy(rec);
+ return;
+#if 0
+ if (!settings_get_bool("dcc_server_fserve"))
+ {
+ /* We're not accepting CHATs this way */
+ strncpy(reply, "150 unavailable\n", sizeof(reply) - 1);
+ net_transmit(rec->handle, reply, strlen(reply));
+ dcc_server_destroy(rec);
+ return;
+ }
+ str += 4;
+ convert_dcc_server_to_fserve(rec);
+#endif
+ } else if (!strncmp(str, "120 ", 4))
+ {
+ /* Send request */
+ char *nick;
+ char *filesize;
+ char *filename;
+ if (!settings_get_bool("dcc_server_send"))
+ {
+ /* We're not accepting SENDs this way */
+ strncpy(reply, "150 unavailable\n", sizeof(reply) - 1);
+ net_transmit(rec->handle, reply, strlen(reply));
+ dcc_server_destroy(rec);
+ return;
+ }
+ str += 4; /* Now pointing to the nick they claim */
+ /* 120 <client nickname> <file size> <filename> */
+ nick = str;
+ if (NULL == (filesize = strchr(nick, ' ')))
+ {
+ strncpy(reply, "151 rejected\n", sizeof(reply) - 1);
+ net_transmit(rec->handle, reply, strlen(reply));
+ dcc_server_destroy(rec);
+ return;
+ }
+ *filesize++ = '\0';
+ if (NULL == (filename = strchr(filesize, ' ')))
+ {
+ strncpy(reply, "151 rejected\n", sizeof(reply) - 1);
+ net_transmit(rec->handle, reply, strlen(reply));
+ dcc_server_destroy(rec);
+ return;
+ }
+ *filename++ = '\0';
+ if (!dcc_server_nick_resolve(rec, nick))
+ {
+ strncpy(reply, "151 rejected\n", sizeof(reply) - 1);
+ net_transmit(rec->handle, reply, strlen(reply));
+ dcc_server_destroy(rec);
+ return;
+ }
+ convert_dcc_server_to_send(rec, filesize, filename);
+ } else if (!strncmp(str, "130 ", 4))
+ {
+ /* Get request */
+ /* We don't support this */
+ strncpy(reply, "150 unavailable\n", sizeof(reply) - 1);
+ net_transmit(rec->handle, reply, strlen(reply));
+ dcc_server_destroy(rec);
+ return;
+ /*
+ str += 4;
+ convert_dcc_server_to_get(rec);
+ */
+ } else
+ {
+ /* Unknown message */
+ strncpy(reply, "150 unavailable\n", sizeof(reply) - 1);
+ net_transmit(rec->handle, reply, strlen(reply));
+ dcc_server_destroy(rec);
+ }
+}
+
+/* The magical morphing functions, turn our DCC_SERVER_REC into
+ * one of the 'real' DCC types, without disconnecting or starting from
+ * scratch
+ */
+void convert_dcc_server_to_chat(DCC_SERVER_REC *rec)
+{
+ char reply[1024];
+ CHAT_DCC_REC *dcc;
+
+ dcc = g_new0(CHAT_DCC_REC, 1);
+ dcc->orig_type = dcc->type = DCC_CHAT_TYPE;
+ dcc->mirc_ctcp = settings_get_bool("dcc_mirc_ctcp");
+ dcc->id = dcc_chat_get_new_id(rec->nickname);
+
+ dcc_init_rec(DCC(dcc), rec->server, NULL, rec->nickname, "chat");
+
+ dcc->starttime = time(NULL);
+ dcc->handle = rec->handle;
+ dcc->sendbuf = net_sendbuffer_create(dcc->handle, 0);
+ memcpy(&dcc->addr, &rec->addr, sizeof(IPADDR));
+ net_ip2host(&dcc->addr, dcc->addrstr);
+ dcc->port = settings_get_int("dcc_server_port");
+ dcc->tagread = g_input_add(dcc->handle, G_INPUT_READ,
+ (GInputFunction) dcc_chat_input, dcc);
+ signal_emit("dcc connected", 1, dcc);
+
+ /* Done with the DCC_SERVER_REC *rec now */
+ g_source_remove(rec->tagread);
+ g_source_remove_by_user_data(rec);
+ line_split_free(rec->readbuf);
+ rec->readbuf = NULL;
+ net_sendbuffer_destroy(rec->sendbuf, 0);
+ rec->sendbuf = NULL;
+ g_free(rec);
+
+ /* Safe to send our response */
+ g_snprintf(reply, sizeof(reply), "101 %s\n", dcc->server->nick);
+ net_transmit(dcc->handle, reply, strlen(reply));
+}
+
+void convert_dcc_server_to_fserve(DCC_SERVER_REC *rec)
+{
+}
+
+void convert_dcc_server_to_send(DCC_SERVER_REC *rec, char *filesize, char *filename)
+{
+ char reply[1024];
+ GET_DCC_REC *dcc;
+ IPADDR ipaddr;
+ size_t fsize = atoi(filesize);
+ int len, quoted = FALSE;
+
+ len = strlen(filename);
+ if (len > 1 && *filename == '"' && filename[len-1] == '"') {
+ /* "file name" - MIRC sends filenames with spaces like
+ * this */
+ filename[len-1] = '\0';
+ g_memmove(filename, filename+1, len);
+ quoted = TRUE;
+ }
+ /* dcc_get_create() equivalent BEGIN */
+ dcc = g_new0(GET_DCC_REC, 1);
+ dcc->orig_type = module_get_uniq_id_str("DCC", "SEND");
+ dcc->type = module_get_uniq_id_str("DCC", "GET");
+ dcc->fhandle = -1;
+
+ dcc_init_rec(DCC(dcc), rec->server, NULL, rec->nickname, filename);
+
+ dcc->starttime = time(NULL);
+ dcc->handle = rec->handle;
+ /* dcc_get_create() equivalent END */
+
+ dcc->target = g_strdup(rec->nickname);
+ memcpy(&dcc->addr, &rec->addr, sizeof(IPADDR));
+ if (dcc->addr.family == AF_INET)
+ {
+ net_ip2host(&dcc->addr, dcc->addrstr);
+ }
+#if 0
+ else
+ {
+ /* with IPv6, show it to us as it was sent */
+ strncpy(dcc->addrstr, address, sizeof(dcc->addrstr)-1);
+ dcc->addrstr[sizeof(dcc->addrstr)-1] = '\0';
+ }
+#endif
+ net_getpeername(dcc->handle, &ipaddr, &dcc->port);
+ dcc->size = str_to_uofft(filesize);
+ dcc->file_quoted = quoted;
+
+ /* Done with the DCC_SERVER_REC *rec now */
+ g_source_remove(rec->tagread);
+ g_source_remove_by_user_data(rec);
+ line_split_free(rec->readbuf);
+ rec->readbuf = NULL;
+ net_sendbuffer_destroy(rec->sendbuf, 0);
+ rec->sendbuf = NULL;
+ g_free(rec);
+
+ /* Start the actual GET to receive it */
+ if (settings_get_bool("dcc_autoresume")) {
+ dcc_send_resume(dcc);
+ }
+ dcc->tagconn = g_input_add(dcc->handle,
+ G_INPUT_WRITE | G_INPUT_READ,
+ (GInputFunction) sig_dccget_connected,
+ dcc);
+ /* Safe to send our response
+ * 121 <server nickname> <resume position>
+ */
+ g_snprintf(reply, sizeof(reply), "121 %s %d\n", dcc->server->nick,
+ dcc->skipped);
+ net_transmit(dcc->handle, reply, strlen(reply));
+}
+
+static void read_settings(void)
+{
+ dcc_server = settings_get_bool("dcc_server");
+ dcc_server_port = settings_get_int("dcc_server_port");
+ dcc_server_chat = settings_get_bool("dcc_server_chat");
+ dcc_server_fserve = settings_get_bool("dcc_server_fserve");
+ dcc_server_send = settings_get_bool("dcc_server_send");
+
+ if (dcc_server)
+ {
+ dcc_server_start();
+ } else
+ {
+ dcc_server_stop();
+ }
+}
+
+void dcc_server_init(void)
+{
+ settings_add_int("dcc", "dcc_server_port", 9007);
+ settings_add_bool("dcc", "dcc_server_chat", FALSE);
+ settings_add_bool("dcc", "dcc_server_fserve", FALSE);
+ settings_add_bool("dcc", "dcc_server_send", FALSE);
+
+ read_settings();
+
+ signal_add("setup changed", (SIGNAL_FUNC) read_settings);
+ signal_add("dcc server event", (SIGNAL_FUNC) dcc_server_event);
+}
+
+void dcc_server_deinit(void)
+{
+ signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
+ signal_remove("dcc server event", (SIGNAL_FUNC) dcc_server_event);
+}
diff -r -u -N --exclude-from=irssi-dontdiff
irssi-CVS-200302131108/src/irc/dcc/dcc-server.h irssi-CVS/src/irc/dcc/dcc-server.h
--- irssi-CVS-200302131108/src/irc/dcc/dcc-server.h Thu Jan 1 01:00:00 1970
+++ irssi-CVS/src/irc/dcc/dcc-server.h Thu Feb 13 10:13:42 2003
@@ -0,0 +1,34 @@
+#ifndef __DCC_SERVER_H
+#define __DCC_SERVER_H
+
+#include "dcc.h"
+
+struct DCC_SERVER_REC {
+ char *id; /* unique identifier - usually same as nick. */
+
+ /* To pass through to DCC CHAT/SEND */
+ time_t created;
+ IRC_SERVER_REC *server;
+ NICK_REC *nick;
+ char *nickname;
+ IPADDR addr; /* address we're connected in */
+ char *addrstr; /* in readable form */
+ char ipaddrstr[MAX_IP_LEN]; /* in readable form */
+ int port; /* port we're connected in */
+ GIOChannel *handle; /* socket handle */
+
+ LINEBUF_REC *readbuf;
+ int tagread;
+ NET_SENDBUF_REC *sendbuf;
+
+ unsigned int connection_lost:1; /* other side closed connection */
+};
+
+#define DCC_SERVER_TYPE module_get_uniq_id_str("DCC", "SERVER")
+
+CHAT_DCC_REC *dcc_server_find_id(const char *id);
+
+void dcc_server_init(void);
+void dcc_server_deinit(void);
+
+#endif
diff -r -u -N --exclude-from=irssi-dontdiff irssi-CVS-200302131108/src/irc/dcc/dcc.c
irssi-CVS/src/irc/dcc/dcc.c
--- irssi-CVS-200302131108/src/irc/dcc/dcc.c Sat Dec 28 17:54:13 2002
+++ irssi-CVS/src/irc/dcc/dcc.c Thu Feb 13 10:28:42 2003
@@ -41,6 +41,9 @@
void dcc_autoget_init(void);
void dcc_autoget_deinit(void);
+void dcc_server_init(void);
+void dcc_server_deinit(void);
+
GSList *dcc_conns;
static GSList *dcc_types;
@@ -516,6 +519,7 @@
settings_add_str("dcc", "dcc_port", "0");
settings_add_time("dcc", "dcc_timeout", "5min");
settings_add_str("dcc", "dcc_own_ip", "");
+ settings_add_bool("dcc", "dcc_server", FALSE);
signal_add("event connected", (SIGNAL_FUNC) sig_connected);
signal_add("server disconnected", (SIGNAL_FUNC) sig_server_disconnected);
@@ -534,6 +538,7 @@
dcc_send_init();
dcc_resume_init();
dcc_autoget_init();
+ dcc_server_init();
module_register("dcc", "irc");
}
@@ -548,6 +553,7 @@
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);
diff -r -u -N --exclude-from=irssi-dontdiff irssi-CVS-200302131108/src/irc/dcc/dcc.h
irssi-CVS/src/irc/dcc/dcc.h
--- irssi-CVS-200302131108/src/irc/dcc/dcc.h Sun Nov 25 17:35:47 2001
+++ irssi-CVS/src/irc/dcc/dcc.h Thu Feb 13 10:28:42 2003
@@ -7,6 +7,7 @@
#define DCC(dcc) ((DCC_REC *) (dcc))
typedef struct CHAT_DCC_REC CHAT_DCC_REC;
+typedef struct DCC_SERVER_REC DCC_SERVER_REC;
typedef struct {
#include "dcc-rec.h"
msg00649/pgp00000.pgp
Description: PGP signature
