From 92eb995917d43a7e4fe9afeb8516424ba7e72fc7 Mon Sep 17 00:00:00 2001 From: Sebastien Helleu Date: Wed, 8 Sep 2004 16:56:56 +0000 Subject: [PATCH] Receive DCC packets (for DCC file) --- src/irc/irc-dcc.c | 104 +++++++++++++++++++++++++++++++++++++- src/irc/irc.h | 1 + weechat/src/irc/irc-dcc.c | 104 +++++++++++++++++++++++++++++++++++++- weechat/src/irc/irc.h | 1 + 4 files changed, 206 insertions(+), 4 deletions(-) diff --git a/src/irc/irc-dcc.c b/src/irc/irc-dcc.c index d2276ef7c..6b6bf97bc 100644 --- a/src/irc/irc-dcc.c +++ b/src/irc/irc-dcc.c @@ -25,7 +25,12 @@ #endif #include +#include #include +#include +#include +#include +#include #include "../common/weechat.h" #include "irc.h" @@ -44,8 +49,21 @@ char *dcc_status_string[] = /* strings for DCC status */ */ void -dcc_connect () +dcc_connect (t_dcc *dcc) { + struct sockaddr_in addr; + + dcc->status = DCC_CONNECTING; + + dcc->sock = socket (AF_INET, SOCK_STREAM, 0); + if (dcc->sock == -1) + return; + memset (&addr, 0, sizeof (addr)); + addr.sin_port = htons (dcc->port); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl (dcc->addr); + fcntl (dcc->sock, F_SETFL, O_NONBLOCK); + connect (dcc->sock, (struct sockaddr *) &addr, sizeof (addr)); } /* @@ -87,10 +105,11 @@ dcc_add (t_irc_server *server, int type, unsigned long addr, int port, char *nic } new_dcc->server = server; new_dcc->type = type; - new_dcc->status = DCC_ACTIVE; + new_dcc->status = DCC_WAITING; new_dcc->addr = addr; new_dcc->port = port; new_dcc->nick = strdup (nick); + new_dcc->sock = -1; new_dcc->file = -1; new_dcc->filename = strdup (filename); new_dcc->size = size; @@ -103,5 +122,86 @@ dcc_add (t_irc_server *server, int type, unsigned long addr, int port, char *nic type, nick, addr >> 24, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff, port, filename, size); + + if (type == DCC_FILE_RECV) + { + dcc_connect (new_dcc); + if (new_dcc->sock == -1) + new_dcc->status = DCC_FAILED; + else + new_dcc->status = DCC_ACTIVE; + } + + return new_dcc; } + +/* + * dcc_handle: receive/send data for each active DCC + */ + +void +dcc_handle () +{ + t_dcc *ptr_dcc; + int num; + char buffer[8192]; + uint32_t pos; + + for (ptr_dcc = dcc_list; ptr_dcc; ptr_dcc = ptr_dcc->next_dcc) + { + if (ptr_dcc->status == DCC_ACTIVE) + { + if (ptr_dcc->type == DCC_FILE_RECV) + { + num = recv (ptr_dcc->sock, buffer, sizeof (buffer), 0); + if (num != -1) + { + if (num == 0) + { + ptr_dcc->status = DCC_FAILED; + close (ptr_dcc->sock); + ptr_dcc->sock = -1; + } + else + { + gui_printf (NULL, "DCC: file \"%s\": %d bytes received\n", + ptr_dcc->filename, num); + ptr_dcc->pos += (unsigned long) num; + pos = htonl (ptr_dcc->pos); + send (ptr_dcc->sock, (char *) &pos, 4, 0); + if (ptr_dcc->pos >= ptr_dcc->size) + { + ptr_dcc->status = DCC_DONE; + gui_printf (NULL, "DCC: file \"%s\": done!\n", + ptr_dcc->filename); + close (ptr_dcc->sock); + ptr_dcc->sock = -1; + } + } + } + } + } + } +} + +/* + * dcc_end: close all opened sockets (called when WeeChat is exiting) + */ + +void +dcc_end () +{ + t_dcc *ptr_dcc; + + for (ptr_dcc = dcc_list; ptr_dcc; ptr_dcc = ptr_dcc->next_dcc) + { + if (ptr_dcc->sock != -1) + { + if (ptr_dcc->status == DCC_ACTIVE) + wee_log_printf (_("aborting active DCC: \"%s\" from %s\n"), + ptr_dcc->filename, ptr_dcc->nick); + close (ptr_dcc->sock); + } + } +} \ No newline at end of file diff --git a/src/irc/irc.h b/src/irc/irc.h index e3f08440a..905e87952 100644 --- a/src/irc/irc.h +++ b/src/irc/irc.h @@ -184,6 +184,7 @@ struct t_dcc unsigned long addr; /* IP address */ int port; /* port */ char *nick; /* remote nick */ + int sock; /* socket for connection */ int file; /* local file (for reading or writing) */ char *filename; /* local filename */ unsigned long size; /* file size */ diff --git a/weechat/src/irc/irc-dcc.c b/weechat/src/irc/irc-dcc.c index d2276ef7c..6b6bf97bc 100644 --- a/weechat/src/irc/irc-dcc.c +++ b/weechat/src/irc/irc-dcc.c @@ -25,7 +25,12 @@ #endif #include +#include #include +#include +#include +#include +#include #include "../common/weechat.h" #include "irc.h" @@ -44,8 +49,21 @@ char *dcc_status_string[] = /* strings for DCC status */ */ void -dcc_connect () +dcc_connect (t_dcc *dcc) { + struct sockaddr_in addr; + + dcc->status = DCC_CONNECTING; + + dcc->sock = socket (AF_INET, SOCK_STREAM, 0); + if (dcc->sock == -1) + return; + memset (&addr, 0, sizeof (addr)); + addr.sin_port = htons (dcc->port); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl (dcc->addr); + fcntl (dcc->sock, F_SETFL, O_NONBLOCK); + connect (dcc->sock, (struct sockaddr *) &addr, sizeof (addr)); } /* @@ -87,10 +105,11 @@ dcc_add (t_irc_server *server, int type, unsigned long addr, int port, char *nic } new_dcc->server = server; new_dcc->type = type; - new_dcc->status = DCC_ACTIVE; + new_dcc->status = DCC_WAITING; new_dcc->addr = addr; new_dcc->port = port; new_dcc->nick = strdup (nick); + new_dcc->sock = -1; new_dcc->file = -1; new_dcc->filename = strdup (filename); new_dcc->size = size; @@ -103,5 +122,86 @@ dcc_add (t_irc_server *server, int type, unsigned long addr, int port, char *nic type, nick, addr >> 24, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff, port, filename, size); + + if (type == DCC_FILE_RECV) + { + dcc_connect (new_dcc); + if (new_dcc->sock == -1) + new_dcc->status = DCC_FAILED; + else + new_dcc->status = DCC_ACTIVE; + } + + return new_dcc; } + +/* + * dcc_handle: receive/send data for each active DCC + */ + +void +dcc_handle () +{ + t_dcc *ptr_dcc; + int num; + char buffer[8192]; + uint32_t pos; + + for (ptr_dcc = dcc_list; ptr_dcc; ptr_dcc = ptr_dcc->next_dcc) + { + if (ptr_dcc->status == DCC_ACTIVE) + { + if (ptr_dcc->type == DCC_FILE_RECV) + { + num = recv (ptr_dcc->sock, buffer, sizeof (buffer), 0); + if (num != -1) + { + if (num == 0) + { + ptr_dcc->status = DCC_FAILED; + close (ptr_dcc->sock); + ptr_dcc->sock = -1; + } + else + { + gui_printf (NULL, "DCC: file \"%s\": %d bytes received\n", + ptr_dcc->filename, num); + ptr_dcc->pos += (unsigned long) num; + pos = htonl (ptr_dcc->pos); + send (ptr_dcc->sock, (char *) &pos, 4, 0); + if (ptr_dcc->pos >= ptr_dcc->size) + { + ptr_dcc->status = DCC_DONE; + gui_printf (NULL, "DCC: file \"%s\": done!\n", + ptr_dcc->filename); + close (ptr_dcc->sock); + ptr_dcc->sock = -1; + } + } + } + } + } + } +} + +/* + * dcc_end: close all opened sockets (called when WeeChat is exiting) + */ + +void +dcc_end () +{ + t_dcc *ptr_dcc; + + for (ptr_dcc = dcc_list; ptr_dcc; ptr_dcc = ptr_dcc->next_dcc) + { + if (ptr_dcc->sock != -1) + { + if (ptr_dcc->status == DCC_ACTIVE) + wee_log_printf (_("aborting active DCC: \"%s\" from %s\n"), + ptr_dcc->filename, ptr_dcc->nick); + close (ptr_dcc->sock); + } + } +} \ No newline at end of file diff --git a/weechat/src/irc/irc.h b/weechat/src/irc/irc.h index e3f08440a..905e87952 100644 --- a/weechat/src/irc/irc.h +++ b/weechat/src/irc/irc.h @@ -184,6 +184,7 @@ struct t_dcc unsigned long addr; /* IP address */ int port; /* port */ char *nick; /* remote nick */ + int sock; /* socket for connection */ int file; /* local file (for reading or writing) */ char *filename; /* local filename */ unsigned long size; /* file size */