1
0
mirror of https://github.com/weechat/weechat.git synced 2026-07-08 18:53:12 +02:00

IRC DCC chat and file (without resume) reintroduced, via xfer plugin (called by /dcc command)

This commit is contained in:
Sebastien Helleu
2008-05-06 16:51:30 +02:00
parent e7a16efa0c
commit e9603acb1a
37 changed files with 2155 additions and 1271 deletions
+1
View File
@@ -18,6 +18,7 @@ ADD_LIBRARY(xfer MODULE
xfer.c xfer.h
xfer-buffer.c xfer-buffer.h
xfer-chat.c xfer-chat.h
xfer-command.c xfer-command.h
xfer-config.c xfer-config.h
xfer-dcc.c xfer-dcc.h
xfer-file.c xfer-file.h
+2
View File
@@ -26,6 +26,8 @@ xfer_la_SOURCES = xfer.c \
xfer-buffer.h \
xfer-chat.c \
xfer-chat.h \
xfer-command.c \
xfer-command.h \
xfer-config.c \
xfer-config.h \
xfer-dcc.c \
+252 -50
View File
@@ -21,17 +21,262 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "../weechat-plugin.h"
#include "xfer.h"
#include "xfer-buffer.h"
#include "xfer-config.h"
#include "xfer-network.h"
struct t_gui_buffer *xfer_buffer = NULL;
int xfer_buffer_selected_line = 0;
/*
* xfer_buffer_refresh: update a xfer in buffer and update hotlist for xfer buffer
*/
void
xfer_buffer_refresh (char *hotlist)
{
struct t_xfer *ptr_xfer;
char str_color[256], status[64], date[128], *progress_bar, format[128];
char format_per_sec[128], bytes_per_sec[256], eta[128];
int i, length, line, progress_bar_size, num_bars, num_unit;
int num_unit_per_sec;
unsigned long pct_complete;
char *unit_name[] = { N_("bytes"), N_("KB"), N_("MB"), N_("GB") };
char *unit_format[] = { "%.0f", "%.1f", "%.02f", "%.02f" };
float unit_divide[] = { 1, 1024, 1024*1024, 1024*1024*1024 };
struct tm *date_tmp;
if (xfer_buffer)
{
weechat_buffer_clear (xfer_buffer);
line = 0;
for (ptr_xfer = xfer_list; ptr_xfer; ptr_xfer = ptr_xfer->next_xfer)
{
snprintf (str_color, sizeof (str_color),
"%s,%s",
weechat_config_string (xfer_config_color_text),
weechat_config_string (xfer_config_color_text_bg));
/* display first line with remote nick and filename */
weechat_printf_y (xfer_buffer, line * 2,
"%s%s%-25s %s%s%s",
weechat_color(str_color),
(line == xfer_buffer_selected_line) ?
"*** " : " ",
ptr_xfer->remote_nick,
(XFER_IS_FILE(ptr_xfer->type)) ? "\"" : "",
(XFER_IS_FILE(ptr_xfer->type)) ?
ptr_xfer->filename : _("xfer chat"),
(XFER_IS_FILE(ptr_xfer->type)) ? "\"" : "");
snprintf (status, sizeof (status),
"%s", _(xfer_status_string[ptr_xfer->status]));
length = strlen (status);
if (length < 20)
{
for (i = 0; i < 20 - length; i++)
{
strcat (status, " ");
}
}
if (XFER_IS_CHAT(ptr_xfer->type))
{
/* display second line for chat with status and date */
date_tmp = localtime (&(ptr_xfer->start_time));
strftime (date, sizeof (date),
"%a, %d %b %Y %H:%M:%S", date_tmp);
weechat_printf_y (xfer_buffer, (line * 2) + 1,
"%s%s%s %s%s %s%s%s",
weechat_color(str_color),
(line == xfer_buffer_selected_line) ?
"*** " : " ",
(XFER_IS_SEND(ptr_xfer->type)) ?
"<<--" : "-->>",
weechat_color(weechat_config_string (xfer_config_color_status[ptr_xfer->status])),
status,
weechat_color ("reset"),
weechat_color (str_color),
date);
}
else
{
/* build progress bar */
progress_bar = NULL;
progress_bar_size = weechat_config_integer (xfer_config_look_progress_bar_size);
if (progress_bar_size > 0)
{
progress_bar = malloc (1 + progress_bar_size + 1 + 1);
strcpy (progress_bar, "[");
if (ptr_xfer->size == 0)
{
if (ptr_xfer->status == XFER_STATUS_DONE)
num_bars = progress_bar_size;
else
num_bars = 0;
}
else
num_bars = (int)(((float)(ptr_xfer->pos)/(float)(ptr_xfer->size)) * (float)progress_bar_size);
for (i = 0; i < num_bars - 1; i++)
{
strcat (progress_bar, "=");
}
if (num_bars > 0)
strcat (progress_bar, ">");
for (i = 0; i < progress_bar_size - num_bars; i++)
{
strcat (progress_bar, " ");
}
strcat (progress_bar, "]");
}
/* computes pourcentage */
if (ptr_xfer->size < 1024*10)
num_unit = 0;
else if (ptr_xfer->size < 1024*1024)
num_unit = 1;
else if (ptr_xfer->size < 1024*1024*1024)
num_unit = 2;
else
num_unit = 3;
if (ptr_xfer->size == 0)
{
if (ptr_xfer->status == XFER_STATUS_DONE)
pct_complete = 100;
else
pct_complete = 0;
}
else
pct_complete = (unsigned long)(((float)(ptr_xfer->pos)/(float)(ptr_xfer->size)) * 100);
snprintf (format, sizeof (format),
"%%s%%s%%s %%s%%s%%s%%s %%3lu%%%% %s %%s / %s %%s (%%s%%s)",
unit_format[num_unit],
unit_format[num_unit]);
/* bytes per second */
bytes_per_sec[0] = '\0';
if (ptr_xfer->bytes_per_sec < 1024*10)
num_unit_per_sec = 0;
else if (ptr_xfer->bytes_per_sec < 1024*1024)
num_unit_per_sec = 1;
else if (ptr_xfer->bytes_per_sec < 1024*1024*1024)
num_unit_per_sec = 2;
else
num_unit_per_sec = 3;
snprintf (format_per_sec, sizeof (format_per_sec),
"%s %%s/s",
unit_format[num_unit_per_sec]);
snprintf (bytes_per_sec, sizeof (bytes_per_sec),
format_per_sec,
((float)ptr_xfer->bytes_per_sec) / ((float)(unit_divide[num_unit_per_sec])),
_(unit_name[num_unit_per_sec]));
/* ETA */
eta[0] = '\0';
if (ptr_xfer->status == XFER_STATUS_ACTIVE)
{
snprintf (eta, sizeof (eta),
"%s: %.2lu:%.2lu:%.2lu - ",
_("ETA"),
ptr_xfer->eta / 3600,
(ptr_xfer->eta / 60) % 60,
ptr_xfer->eta % 60);
}
/* display second line for file with status, progress bar and estimated time */
weechat_printf_y (xfer_buffer, (line * 2) + 1,
format,
weechat_color(str_color),
(line == xfer_buffer_selected_line) ?
"*** " : " ",
(XFER_IS_SEND(ptr_xfer->type)) ?
"<<--" : "-->>",
weechat_color(weechat_config_string (xfer_config_color_status[ptr_xfer->status])),
status,
weechat_color (str_color),
(progress_bar) ? progress_bar : "",
pct_complete,
((float)(ptr_xfer->pos)) / unit_divide[num_unit],
_(unit_name[num_unit]),
((float)(ptr_xfer->size)) / unit_divide[num_unit],
_(unit_name[num_unit]),
eta,
bytes_per_sec);
}
line++;
}
weechat_buffer_set (xfer_buffer, "hotlist", hotlist);
}
}
/*
* xfer_buffer_input_cb: callback called when user send data to xfer list
* buffer
*/
int
xfer_buffer_input_cb (void *data, struct t_gui_buffer *buffer,
char *input_data)
{
struct t_xfer *xfer, *ptr_xfer, *next_xfer;
/* make C compiler happy */
(void) data;
(void) buffer;
xfer = xfer_search_by_number (xfer_buffer_selected_line);
/* accept xfer */
if (weechat_strcasecmp (input_data, "a") == 0)
{
if (xfer && XFER_IS_RECV(xfer->type)
&& (xfer->status == XFER_STATUS_WAITING))
{
xfer_network_accept (xfer);
}
}
/* cancel xfer */
else if (weechat_strcasecmp (input_data, "c") == 0)
{
if (xfer && !XFER_HAS_ENDED(xfer->status))
{
xfer_close (xfer, XFER_STATUS_ABORTED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
}
}
/* purge old xfer */
else if (weechat_strcasecmp (input_data, "p") == 0)
{
ptr_xfer = xfer_list;
while (ptr_xfer)
{
next_xfer = ptr_xfer->next_xfer;
if (XFER_HAS_ENDED(ptr_xfer->status))
xfer_free (ptr_xfer);
ptr_xfer = next_xfer;
}
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
}
/* remove xfer */
else if (weechat_strcasecmp (input_data, "r") == 0)
{
if (xfer && XFER_HAS_ENDED(xfer->status))
{
xfer_free (xfer);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
}
}
return WEECHAT_RC_OK;
}
/*
* xfer_buffer_close_cb: callback called when xfer buffer is closed
*/
@@ -57,61 +302,18 @@ xfer_buffer_open ()
{
if (!xfer_buffer)
{
xfer_buffer = weechat_buffer_new ("xfer", "xfer",
NULL, NULL,
xfer_buffer = weechat_buffer_new ("xfer", "list",
&xfer_buffer_input_cb, NULL,
&xfer_buffer_close_cb, NULL);
/* failed to create buffer ? then exit */
if (!xfer_buffer)
return;
weechat_buffer_set (xfer_buffer, "type", "free");
weechat_buffer_set (xfer_buffer, "title", _("Xfer list"));
}
}
/*
* xfer_buffer_refresh: update a xfer in buffer and update hotlist for xfer buffer
*/
void
xfer_buffer_refresh (char *hotlist)
{
struct t_xfer *ptr_xfer;
char str_color[256];
int line;
if (xfer_buffer)
{
line = 0;
for (ptr_xfer = xfer_list; ptr_xfer; ptr_xfer = ptr_xfer->next_xfer)
{
if (XFER_IS_FILE(ptr_xfer->type))
{
snprintf (str_color, sizeof (str_color),
"%s,%s",
weechat_config_string (xfer_config_color_text),
weechat_config_string (xfer_config_color_text_bg));
weechat_printf_y (xfer_buffer, line * 2,
"%s%s%-20s \"%s\"",
weechat_color(str_color),
(line == xfer_buffer_selected_line) ?
"*** " : " ",
ptr_xfer->nick, ptr_xfer->filename);
weechat_printf_y (xfer_buffer, (line * 2) + 1,
"%s%s%s %s%-15s ",
weechat_color(str_color),
(line == xfer_buffer_selected_line) ?
"*** " : " ",
(XFER_IS_SEND(ptr_xfer->type)) ?
"<<--" : "-->>",
weechat_color(
weechat_config_string (
xfer_config_color_status[ptr_xfer->status])),
_(xfer_status_string[ptr_xfer->status]));
}
line++;
}
weechat_buffer_set (xfer_buffer, "hotlist", hotlist);
weechat_buffer_set (xfer_buffer, "key_bind_meta2-A", "/xfer up");
weechat_buffer_set (xfer_buffer, "key_bind_meta2-B", "/xfer down");
weechat_buffer_set (xfer_buffer, "display", "1");
}
}
+3 -2
View File
@@ -21,8 +21,9 @@
#define __WEECHAT_XFER_DISPLAY_H 1
extern struct t_gui_buffer *xfer_buffer;
extern int xfer_buffer_selected_line;
extern void xfer_buffer_open ();
extern void xfer_buffer_refresh (char *hotlist);
extern void xfer_buffer_open ();
#endif /* xfer.h */
#endif /* xfer-buffer.h */
+97 -19
View File
@@ -74,37 +74,25 @@ xfer_chat_sendf (struct t_xfer *xfer, char *format, ...)
{
weechat_printf (NULL,
_("%s%s: error sending data to \"%s\" via xfer chat"),
weechat_prefix ("error"), "xfer", xfer->nick);
weechat_prefix ("error"), "xfer", xfer->remote_nick);
xfer_close (xfer, XFER_STATUS_FAILED);
}
}
/*
* xfer_chat_recv: receive data from xfer chat remote host
* xfer_chat_recv_cb: receive data from xfer chat remote host
*/
void
xfer_chat_recv (struct t_xfer *xfer)
int
xfer_chat_recv_cb (void *arg_xfer)
{
fd_set read_fd;
static struct timeval timeout;
struct t_xfer *xfer;
static char buffer[4096 + 2];
char *buf2, *pos, *ptr_buf, *next_ptr_buf;
int num_read;
FD_ZERO (&read_fd);
FD_SET (xfer->sock, &read_fd);
timeout.tv_sec = 0;
timeout.tv_usec = 0;
xfer = (struct t_xfer *)arg_xfer;
/* something to read on socket? */
if (select (FD_SETSIZE, &read_fd, NULL, NULL, &timeout) <= 0)
return;
if (!FD_ISSET (xfer->sock, &read_fd))
return;
/* there's something to read on socket! */
num_read = recv (xfer->sock, buffer, sizeof (buffer) - 2, 0);
if (num_read > 0)
{
@@ -144,7 +132,7 @@ xfer_chat_recv (struct t_xfer *xfer)
if (ptr_buf)
{
weechat_printf (xfer->buffer, "%s\t%s", xfer->nick, ptr_buf);
weechat_printf (xfer->buffer, "%s\t%s", xfer->remote_nick, ptr_buf);
}
ptr_buf = next_ptr_buf;
@@ -158,4 +146,94 @@ xfer_chat_recv (struct t_xfer *xfer)
xfer_close (xfer, XFER_STATUS_ABORTED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
}
return WEECHAT_RC_OK;
}
/*
* xfer_chat_buffer_input_cb: callback called when user send data to xfer chat
* buffer
*/
int
xfer_chat_buffer_input_cb (void *data, struct t_gui_buffer *buffer,
char *input_data)
{
struct t_xfer *xfer;
xfer = (struct t_xfer *)data;
if (!XFER_HAS_ENDED(xfer->status))
{
xfer_chat_sendf (xfer, "%s\n", input_data);
if (!XFER_HAS_ENDED(xfer->status))
{
weechat_printf (buffer,
"%s\t%s",
xfer->local_nick,
input_data);
}
}
return WEECHAT_RC_OK;
}
/*
* xfer_chat_close_buffer_cb: callback called when a buffer with direct chat
* is closed
*/
int
xfer_chat_buffer_close_cb (void *data, struct t_gui_buffer *buffer)
{
struct t_xfer *xfer;
/* make C compiler happy */
(void) buffer;
xfer = (struct t_xfer *)data;
if (!XFER_HAS_ENDED(xfer->status))
{
xfer_close (xfer, XFER_STATUS_ABORTED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
}
xfer->buffer = NULL;
return WEECHAT_RC_OK;
}
/*
* xfer_chat_open_buffer: create channel for DCC chat
*/
void
xfer_chat_open_buffer (struct t_xfer *xfer)
{
char *name;
int length;
length = strlen (xfer->plugin_name) + 1 + strlen (xfer->remote_nick) + 1;
name = malloc (length);
if (name)
{
snprintf (name, length, "%s_%s", xfer->plugin_name, xfer->remote_nick);
xfer->buffer = weechat_buffer_new ("xfer", name,
&xfer_chat_buffer_input_cb, xfer,
&xfer_chat_buffer_close_cb, xfer);
if (xfer->buffer)
{
weechat_buffer_set (xfer->buffer, "title", _("xfer chat"));
weechat_printf (xfer->buffer,
_("Connected to %s (%d.%d.%d.%d) via "
"xfer chat"),
xfer->remote_nick,
xfer->address >> 24,
(xfer->address >> 16) & 0xff,
(xfer->address >> 8) & 0xff,
xfer->address & 0xff);
}
free (name);
}
}
+2
View File
@@ -20,5 +20,7 @@
#ifndef __WEECHAT_XFER_CHAT_H
#define __WEECHAT_XFER_CHAT_H 1
extern int xfer_chat_recv_cb (void *arg_xfer);
extern void xfer_chat_open_buffer (struct t_xfer *xfer);
#endif /* xfer-chat.h */
+83
View File
@@ -0,0 +1,83 @@
/*
* Copyright (c) 2003-2008 by FlashCode <flashcode@flashtux.org>
* See README for License detail, AUTHORS for developers list.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/* xfer-command.c: xfer command */
#include <stdlib.h>
#include <string.h>
#include "../weechat-plugin.h"
#include "xfer.h"
#include "xfer-buffer.h"
/*
* xfer_command_xfer: command /xfer
*/
int
xfer_command_xfer (void *data, struct t_gui_buffer *buffer, int argc,
char **argv, char **argv_eol)
{
/* make C compiler happy */
(void) data;
(void) buffer;
(void) argc;
(void) argv;
(void) argv_eol;
if (!xfer_buffer)
xfer_buffer_open ();
if (argc > 1)
{
if (strcmp (argv[1], "up") == 0)
{
if (xfer_buffer_selected_line > 0)
{
xfer_buffer_selected_line--;
xfer_buffer_refresh (NULL);
}
}
else if (strcmp (argv[1], "down") == 0)
{
if (xfer_buffer_selected_line < xfer_count - 1)
{
xfer_buffer_selected_line++;
xfer_buffer_refresh (NULL);
}
}
}
return WEECHAT_RC_OK;
}
/*
* xfer_command: xfer command
*/
void
xfer_command_init ()
{
weechat_hook_command ("xfer",
N_("xfer control"),
"",
_("Open buffer with xfer list"),
NULL, &xfer_command_xfer, NULL);
}
+25
View File
@@ -0,0 +1,25 @@
/*
* Copyright (c) 2003-2008 by FlashCode <flashcode@flashtux.org>
* See README for License detail, AUTHORS for developers list.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef __WEECHAT_XFER_COMMAND_H
#define __WEECHAT_XFER_COMMAND_H 1
extern void xfer_command_init ();
#endif /* xfer-command.h */
+7
View File
@@ -32,6 +32,7 @@ struct t_config_file *xfer_config_file = NULL;
/* xfer config, look section */
struct t_config_option *xfer_config_look_auto_open_buffer;
struct t_config_option *xfer_config_look_progress_bar_size;
/* xfer config, color section */
@@ -104,6 +105,12 @@ xfer_config_init ()
N_("auto open xfer buffer and switch to it when a new xfer is added "
"to list"),
NULL, 0, 0, "on", NULL, NULL, NULL, NULL, NULL, NULL);
xfer_config_look_progress_bar_size = weechat_config_new_option (
xfer_config_file, ptr_section,
"progress_bar_size", "integer",
N_("size of progress bar, in chars (if 0, progress bar is disabled)"),
NULL, 0, XFER_CONFIG_PROGRESS_BAR_MAX_SIZE, "20",
NULL, NULL, NULL, NULL, NULL, NULL);
ptr_section = weechat_config_new_section (xfer_config_file, "color",
0, 0,
+3
View File
@@ -22,9 +22,12 @@
#define XFER_CONFIG_NAME "xfer"
#define XFER_CONFIG_PROGRESS_BAR_MAX_SIZE 256
extern struct t_config_file *xfer_config;
extern struct t_config_option *xfer_config_look_auto_open_buffer;
extern struct t_config_option *xfer_config_look_progress_bar_size;
extern struct t_config_option *xfer_config_color_text;
extern struct t_config_option *xfer_config_color_text_bg;
-1
View File
@@ -31,7 +31,6 @@
#include "../weechat-plugin.h"
#include "xfer.h"
#include "xfer-dcc.h"
#include "xfer-network.h"
+2 -2
View File
@@ -101,7 +101,7 @@ xfer_file_find_filename (struct t_xfer *xfer)
}
xfer->local_filename = malloc (strlen (dir2) +
strlen (xfer->nick) +
strlen (xfer->remote_nick) +
strlen (xfer->filename) + 4);
if (!xfer->local_filename)
return;
@@ -111,7 +111,7 @@ xfer_file_find_filename (struct t_xfer *xfer)
if (dir_separator
&& (xfer->local_filename[strlen (xfer->local_filename) - 1] != dir_separator[0]))
strcat (xfer->local_filename, dir_separator);
strcat (xfer->local_filename, xfer->nick);
strcat (xfer->local_filename, xfer->remote_nick);
strcat (xfer->local_filename, ".");
strcat (xfer->local_filename, xfer->filename);
+263 -74
View File
@@ -28,58 +28,17 @@
#include <sys/socket.h>
#include <signal.h>
#include <time.h>
#include <netdb.h>
#include "../weechat-plugin.h"
#include "xfer.h"
#include "xfer-network.h"
#include "xfer-buffer.h"
#include "xfer-chat.h"
#include "xfer-config.h"
#include "xfer-dcc.h"
#include "xfer-file.h"
/*
* xfer_network_connect: connect to another host
*/
int
xfer_network_connect (struct t_xfer *xfer)
{
if (xfer->type == XFER_TYPE_CHAT_SEND)
xfer->status = XFER_STATUS_WAITING;
else
xfer->status = XFER_STATUS_CONNECTING;
if (xfer->sock < 0)
{
xfer->sock = socket (AF_INET, SOCK_STREAM, 0);
if (xfer->sock < 0)
return 0;
}
/* for chat or file sending, listen to socket for a connection */
if (XFER_IS_SEND(xfer->type))
{
if (fcntl (xfer->sock, F_SETFL, O_NONBLOCK) == -1)
return 0;
if (listen (xfer->sock, 1) == -1)
return 0;
if (fcntl (xfer->sock, F_SETFL, 0) == -1)
return 0;
}
/* for chat receiving, connect to listening host */
if (xfer->type == XFER_TYPE_CHAT_RECV)
{
if (fcntl (xfer->sock, F_SETFL, O_NONBLOCK) == -1)
return 0;
weechat_network_connect_to (xfer->sock, xfer->address, xfer->port);
}
/* for file receiving, connection is made in child process (blocking) */
return 1;
}
/*
* xfer_network_create_pipe: create pipe for communication with child process
* return 1 if ok, 0 if error
@@ -312,36 +271,6 @@ xfer_network_recv_file_fork (struct t_xfer *xfer)
xfer);
}
/*
* xfer_network_connect_init: connect to sender and init file or chat
*/
void
xfer_network_connect_init (struct t_xfer *xfer)
{
if (!xfer_network_connect (xfer))
{
xfer_close (xfer, XFER_STATUS_FAILED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
}
else
{
/* for a file: launch child process */
if (XFER_IS_FILE(xfer->type))
{
xfer->status = XFER_STATUS_CONNECTING;
xfer_network_recv_file_fork (xfer);
}
else
{
/* for a chat => associate with buffer */
xfer->status = XFER_STATUS_ACTIVE;
// TODO: create buffer for xfer chat
}
}
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
}
/*
* xfer_network_child_kill: kill child process and close pipe
*/
@@ -369,3 +298,263 @@ xfer_network_child_kill (struct t_xfer *xfer)
xfer->child_write = -1;
}
}
/*
* xfer_network_fd_cb: callback called when data is available on xfer socket
*/
int
xfer_network_fd_cb (void *arg_xfer)
{
struct t_xfer *xfer;
int sock;
struct sockaddr_in addr;
socklen_t length;
xfer = (struct t_xfer *)arg_xfer;
if (xfer->status == XFER_STATUS_CONNECTING)
{
if (xfer->type == XFER_TYPE_FILE_SEND)
{
xfer->last_activity = time (NULL);
length = sizeof (addr);
sock = accept (xfer->sock,
(struct sockaddr *) &addr, &length);
weechat_unhook (xfer->hook_fd);
xfer->hook_fd = NULL;
close (xfer->sock);
xfer->sock = -1;
if (sock < 0)
{
weechat_printf (NULL,
_("%s%s: unable to create socket for sending "
"file"),
weechat_prefix ("error"), "xfer");
xfer_close (xfer, XFER_STATUS_FAILED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
return WEECHAT_RC_OK;
}
xfer->sock = sock;
if (fcntl (xfer->sock, F_SETFL, O_NONBLOCK) == -1)
{
weechat_printf (NULL,
_("%s%s: unable to set option \"nonblock\" "
"for socket"),
weechat_prefix ("error"), "xfer");
xfer_close (xfer, XFER_STATUS_FAILED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
return WEECHAT_RC_OK;
}
xfer->address = ntohl (addr.sin_addr.s_addr);
xfer->status = XFER_STATUS_ACTIVE;
xfer->start_transfer = time (NULL);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
xfer_network_send_file_fork (xfer);
}
/*
if (xfer->type == XFER_TYPE_FILE_RECV)
{
if (xfer->child_read != -1)
irc_dcc_file_child_read (dcc);
}
*/
}
if (xfer->status == XFER_STATUS_WAITING)
{
if (xfer->type == XFER_TYPE_CHAT_SEND)
{
length = sizeof (addr);
sock = accept (xfer->sock, (struct sockaddr *) &addr, &length);
weechat_unhook (xfer->hook_fd);
xfer->hook_fd = NULL;
close (xfer->sock);
xfer->sock = -1;
if (sock < 0)
{
weechat_printf (NULL,
_("%s%s: unable to create socket for sending "
"file"),
weechat_prefix ("error"), "xfer");
xfer_close (xfer, XFER_STATUS_FAILED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
return WEECHAT_RC_OK;
}
xfer->sock = sock;
if (fcntl (xfer->sock, F_SETFL, O_NONBLOCK) == -1)
{
weechat_printf (NULL,
_("%s%s: unable to set option \"nonblock\" "
"for socket"),
weechat_prefix ("error"), "xfer");
xfer_close (xfer, XFER_STATUS_FAILED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
return WEECHAT_RC_OK;
}
xfer->address = ntohl (addr.sin_addr.s_addr);
xfer->status = XFER_STATUS_ACTIVE;
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
xfer->hook_fd = weechat_hook_fd (xfer->sock,
1, 0, 0,
&xfer_chat_recv_cb,
xfer);
xfer_chat_open_buffer (xfer);
}
}
/*
if (xfer->status == XFER_STATUS_ACTIVE)
{
if (XFER_IS_CHAT(dcc->type))
{
irc_dcc_chat_recv (dcc);
}
else
irc_dcc_file_child_read (dcc);
}
*/
return WEECHAT_RC_OK;
}
/*
* xfer_network_timer_cb: callback called to check if there's a timeout for xfer
* (called only one time for xfer)
*/
int
xfer_network_timer_cb (void *arg_xfer)
{
struct t_xfer *xfer;
xfer = (struct t_xfer *)arg_xfer;
if ((xfer->status == XFER_STATUS_WAITING)
|| (xfer->status == XFER_STATUS_CONNECTING))
{
weechat_printf (NULL,
_("%s%s: timeout for \"%s\" with %s"),
weechat_prefix ("error"), "xfer",
xfer->filename, xfer->remote_nick);
xfer_close (xfer, XFER_STATUS_FAILED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
}
return WEECHAT_RC_OK;
}
/*
* xfer_network_connect: connect to another host
*/
int
xfer_network_connect (struct t_xfer *xfer)
{
if (xfer->type == XFER_TYPE_CHAT_SEND)
xfer->status = XFER_STATUS_WAITING;
else
xfer->status = XFER_STATUS_CONNECTING;
if (xfer->sock < 0)
{
xfer->sock = socket (AF_INET, SOCK_STREAM, 0);
if (xfer->sock < 0)
return 0;
}
if (XFER_IS_SEND(xfer->type))
{
/* listen to socket */
if (fcntl (xfer->sock, F_SETFL, O_NONBLOCK) == -1)
return 0;
if (listen (xfer->sock, 1) == -1)
return 0;
if (fcntl (xfer->sock, F_SETFL, 0) == -1)
return 0;
xfer->hook_fd = weechat_hook_fd (xfer->sock,
1, 0, 0,
&xfer_network_fd_cb,
xfer);
/* add timeout */
if (weechat_config_integer (xfer_config_network_timeout) > 0)
{
xfer->hook_timer = weechat_hook_timer (weechat_config_integer (xfer_config_network_timeout) * 1000,
0, 1,
&xfer_network_timer_cb,
xfer);
}
}
/* for chat receiving, connect to listening host */
if (xfer->type == XFER_TYPE_CHAT_RECV)
{
if (fcntl (xfer->sock, F_SETFL, O_NONBLOCK) == -1)
return 0;
weechat_network_connect_to (xfer->sock, xfer->address, xfer->port);
xfer->hook_fd = weechat_hook_fd (xfer->sock,
1, 0, 0,
&xfer_chat_recv_cb,
xfer);
}
/* for file receiving, connection is made in child process (blocking) */
return 1;
}
/*
* xfer_network_connect_init: connect to sender and init file or chat
*/
void
xfer_network_connect_init (struct t_xfer *xfer)
{
if (!xfer_network_connect (xfer))
{
xfer_close (xfer, XFER_STATUS_FAILED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
}
else
{
/* for a file: launch child process */
if (XFER_IS_FILE(xfer->type))
{
xfer->status = XFER_STATUS_CONNECTING;
xfer_network_recv_file_fork (xfer);
}
else
{
/* for a chat => associate with buffer */
xfer->status = XFER_STATUS_ACTIVE;
xfer_chat_open_buffer (xfer);
}
}
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
}
/*
* xfer_network_accept: accept a xfer file or chat request
*/
void
xfer_network_accept (struct t_xfer *xfer)
{
if (XFER_IS_FILE(xfer->type) && (xfer->start_resume > 0))
{
xfer->status = XFER_STATUS_CONNECTING;
xfer_send_signal (xfer, "xfer_accepted");
/*
irc_server_sendf (dcc->server,
(strchr (dcc->filename, ' ')) ?
"PRIVMSG %s :\01DCC RESUME \"%s\" %d %u\01\n" :
"PRIVMSG %s :\01DCC RESUME %s %d %u\01",
dcc->nick, dcc->filename,
dcc->port, dcc->start_resume);
*/
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
}
else
xfer_network_connect_init (xfer);
}
+2 -1
View File
@@ -20,11 +20,12 @@
#ifndef __WEECHAT_XFER_NETWORK_H
#define __WEECHAT_XFER_NETWORK_H 1
extern int xfer_network_connect (struct t_xfer *xfer);
extern int xfer_network_create_pipe (struct t_xfer *xfer);
extern void xfer_network_write_pipe (struct t_xfer *xfer, int status,
int error);
extern void xfer_network_connect_init (struct t_xfer *xfer);
extern void xfer_network_child_kill (struct t_xfer *xfer);
extern int xfer_network_connect (struct t_xfer *xfer);
extern void xfer_network_accept (struct t_xfer *xfer);
#endif /* xfer-network.h */
+395 -356
View File
@@ -32,6 +32,7 @@
#include "../weechat-plugin.h"
#include "xfer.h"
#include "xfer-buffer.h"
#include "xfer-command.h"
#include "xfer-config.h"
#include "xfer-file.h"
#include "xfer-network.h"
@@ -64,6 +65,7 @@ char *xfer_status_string[] = /* strings for status */
struct t_xfer *xfer_list = NULL; /* list of files/chats */
struct t_xfer *last_xfer = NULL; /* last file/chat in list */
int xfer_count = 0; /* number of xfer */
int xfer_debug = 0;
@@ -155,339 +157,25 @@ xfer_search (enum t_xfer_type type, enum t_xfer_status status, int port)
}
/*
* xfer_port_in_use: return 1 if a port is in used
* (by an active or connecting xfer)
* xfer_search_by_number: search a xfer by number (first xfer is 0)
*/
int
xfer_port_in_use (int port)
struct t_xfer *
xfer_search_by_number (int number)
{
struct t_xfer *ptr_xfer;
int i;
/* skip any currently used ports */
i = 0;
for (ptr_xfer = xfer_list; ptr_xfer; ptr_xfer = ptr_xfer->next_xfer)
{
if ((ptr_xfer->port == port) && (!XFER_HAS_ENDED(ptr_xfer->status)))
return 1;
if (i == number)
return ptr_xfer;
i++;
}
/* port not in use */
return 0;
}
/*
* xfer_send_signal: send a signal for a xfer
*/
void
xfer_send_signal (struct t_xfer *xfer, char *signal)
{
struct t_plugin_infolist *infolist;
struct t_plugin_infolist_item *item;
char str_long[128];
infolist = weechat_infolist_new ();
if (infolist)
{
item = weechat_infolist_new_item (infolist);
if (item)
{
weechat_infolist_new_var_string (item, "plugin_id",
xfer->plugin_id);
weechat_infolist_new_var_string (item, "type",
xfer_type_string[xfer->type]);
weechat_infolist_new_var_string (item, "protocol",
xfer_protocol_string[xfer->protocol]);
weechat_infolist_new_var_string (item, "nick",
xfer->nick);
weechat_infolist_new_var_string (item, "filename",
xfer->filename);
snprintf (str_long, sizeof (str_long), "%lu", xfer->size);
weechat_infolist_new_var_string (item, "size",
str_long);
snprintf (str_long, sizeof (str_long), "%lu", xfer->address);
weechat_infolist_new_var_string (item, "address",
str_long);
weechat_infolist_new_var_integer (item, "port",
xfer->port);
weechat_hook_signal_send (signal, WEECHAT_HOOK_SIGNAL_POINTER,
infolist);
}
weechat_infolist_free (infolist);
}
}
/*
* xfer_alloc: allocate a new xfer
*/
struct t_xfer *
xfer_alloc ()
{
struct t_xfer *new_xfer;
time_t time_now;
/* create new xfer struct */
if ((new_xfer = malloc (sizeof (*new_xfer))) == NULL)
return NULL;
time_now = time (NULL);
/* default values */
new_xfer->filename = NULL;
new_xfer->size = 0;
new_xfer->address = 0;
new_xfer->port = 0;
new_xfer->nick = NULL;
new_xfer->type = 0;
new_xfer->protocol = 0;
new_xfer->status = 0;
new_xfer->buffer = NULL;
new_xfer->fast_send = weechat_config_boolean (xfer_config_network_fast_send);
new_xfer->blocksize = weechat_config_integer (xfer_config_network_blocksize);
new_xfer->start_time = time_now;
new_xfer->start_transfer = time_now;
new_xfer->sock = -1;
new_xfer->child_pid = 0;
new_xfer->child_read = -1;
new_xfer->child_write = -1;
new_xfer->hook_fd = NULL;
new_xfer->unterminated_message = NULL;
new_xfer->file = -1;
new_xfer->local_filename = NULL;
new_xfer->filename_suffix = -1;
new_xfer->pos = 0;
new_xfer->ack = 0;
new_xfer->start_resume = 0;
new_xfer->last_check_time = time_now;
new_xfer->last_check_pos = time_now;
new_xfer->last_activity = 0;
new_xfer->bytes_per_sec = 0;
new_xfer->eta = 0;
new_xfer->prev_xfer = NULL;
new_xfer->next_xfer = xfer_list;
if (xfer_list)
xfer_list->prev_xfer = new_xfer;
else
last_xfer = new_xfer;
xfer_list = new_xfer;
return new_xfer;
}
/*
* xfer_accept: accept a xfer file or chat request
*/
void
xfer_accept (struct t_xfer *xfer)
{
if (XFER_IS_FILE(xfer->type) && (xfer->start_resume > 0))
{
xfer->status = XFER_STATUS_CONNECTING;
xfer_send_signal (xfer, "xfer_accepted");
/*
irc_server_sendf (dcc->server,
(strchr (dcc->filename, ' ')) ?
"PRIVMSG %s :\01DCC RESUME \"%s\" %d %u\01\n" :
"PRIVMSG %s :\01DCC RESUME %s %d %u\01",
dcc->nick, dcc->filename,
dcc->port, dcc->start_resume);
*/
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
}
else
xfer_network_connect_init (xfer);
}
/*
* xfer_new: add a xfer to list
*/
struct t_xfer *
xfer_new (char *plugin_id, enum t_xfer_type type,
enum t_xfer_protocol protocol, char *nick, char *filename,
unsigned long size, unsigned long address, int port, int sock,
char *local_filename)
{
struct t_xfer *new_xfer;
new_xfer = xfer_alloc ();
if (!new_xfer)
{
weechat_printf (NULL,
_("%s%s: not enough memory for new xfer"),
weechat_prefix ("error"), "xfer");
return NULL;
}
if (!xfer_buffer
&& weechat_config_boolean (xfer_config_look_auto_open_buffer))
{
xfer_buffer_open ();
}
/* initialize new xfer */
new_xfer->plugin_id = strdup (plugin_id);
new_xfer->type = type;
new_xfer->protocol = protocol;
new_xfer->nick = strdup (nick);
if (XFER_IS_FILE(type))
new_xfer->filename = (filename) ? strdup (filename) : NULL;
new_xfer->size = size;
new_xfer->address = address;
new_xfer->port = port;
new_xfer->status = XFER_STATUS_WAITING;
new_xfer->sock = sock;
if (local_filename)
new_xfer->local_filename = strdup (local_filename);
else
xfer_file_find_filename (new_xfer);
/* write info message on server buffer */
switch (type)
{
case XFER_TYPE_FILE_RECV:
weechat_printf (NULL,
_("%s: incoming file from %s "
"(%d.%d.%d.%d): %s, %lu bytes (protocol: %s)"),
"xfer",
nick,
address >> 24,
(address >> 16) & 0xff,
(address >> 8) & 0xff,
address & 0xff,
filename,
size,
xfer_protocol_string[protocol]);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
break;
case XFER_TYPE_FILE_SEND:
weechat_printf (NULL,
_("%s: sending file to %s: %s "
"(local filename: %s), %lu bytes (protocol: %s)"),
"xfer",
nick,
filename,
local_filename,
size,
xfer_protocol_string[protocol]);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
break;
case XFER_TYPE_CHAT_RECV:
weechat_printf (NULL,
_("%s: incoming chat request from %s "
"(%d.%d.%d.%d)"),
"xfer",
nick,
address >> 24,
(address >> 16) & 0xff,
(address >> 8) & 0xff,
address & 0xff);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
break;
case XFER_TYPE_CHAT_SEND:
weechat_printf (NULL,
_("%s: sending chat request to %s"),
"xfer",
nick);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
break;
case XFER_NUM_TYPES:
break;
}
if (XFER_IS_FILE(type) && (!new_xfer->local_filename))
{
xfer_close (new_xfer, XFER_STATUS_FAILED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
return NULL;
}
if (XFER_IS_FILE(type) && (new_xfer->start_resume > 0))
{
weechat_printf (NULL,
_("%s: file %s (local filename: %s) "
"will be resumed at position %u"),
"xfer",
new_xfer->filename,
new_xfer->local_filename,
new_xfer->start_resume);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
}
/* connect if needed and display again xfer buffer */
if (XFER_IS_SEND(type))
{
if (!xfer_network_connect (new_xfer))
{
xfer_close (new_xfer, XFER_STATUS_FAILED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
return NULL;
}
}
if ( ( (type == XFER_TYPE_CHAT_RECV)
&& (weechat_config_boolean (xfer_config_file_auto_accept_chats)) )
|| ( (type == XFER_TYPE_FILE_RECV)
&& (weechat_config_boolean (xfer_config_file_auto_accept_files)) ) )
xfer_accept (new_xfer);
else
xfer_buffer_refresh (WEECHAT_HOTLIST_PRIVATE);
return new_xfer;
}
/*
* xfer_free: free xfer struct and remove it from list
*/
void
xfer_free (struct t_xfer *xfer)
{
struct t_xfer *new_xfer_list;
if (!xfer)
return;
/* close chat buffer */
if (xfer->buffer)
{
/* TODO: close chat buffer */
}
/* remove xfer from list */
if (last_xfer == xfer)
last_xfer = xfer->prev_xfer;
if (xfer->prev_xfer)
{
(xfer->prev_xfer)->next_xfer = xfer->next_xfer;
new_xfer_list = xfer_list;
}
else
new_xfer_list = xfer->next_xfer;
if (xfer->next_xfer)
(xfer->next_xfer)->prev_xfer = xfer->prev_xfer;
/* free data */
if (xfer->plugin_id)
free (xfer->plugin_id);
if (xfer->nick)
free (xfer->nick);
if (xfer->filename)
free (xfer->filename);
if (xfer->unterminated_message)
free (xfer->unterminated_message);
if (xfer->local_filename)
free (xfer->local_filename);
free (xfer);
xfer_list = new_xfer_list;
/* xfer not found */
return NULL;
}
/*
@@ -503,15 +191,27 @@ xfer_close (struct t_xfer *xfer, enum t_xfer_status status)
if (XFER_HAS_ENDED(xfer->status))
{
if (xfer->hook_fd)
{
weechat_unhook (xfer->hook_fd);
xfer->hook_fd = NULL;
}
if (xfer->hook_timer)
{
weechat_unhook (xfer->hook_timer);
xfer->hook_timer = NULL;
}
if (XFER_IS_FILE(xfer->type))
{
weechat_printf (NULL,
_("%s: file %s %s %s: %s"),
_("%s%s: file %s %s %s: %s"),
(xfer->status == XFER_STATUS_DONE) ?
"" : weechat_prefix ("error"),
"xfer",
xfer->filename,
(xfer->type == XFER_TYPE_FILE_SEND) ?
_("sent to") : _("received from"),
xfer->nick,
xfer->remote_nick,
(xfer->status == XFER_STATUS_DONE) ?
_("OK") : _("FAILED"));
xfer_network_child_kill (xfer);
@@ -525,7 +225,7 @@ xfer_close (struct t_xfer *xfer, enum t_xfer_status status)
_("%s: chat closed with %s "
"(%d.%d.%d.%d)"),
"xfer",
xfer->nick,
xfer->remote_nick,
xfer->address >> 24,
(xfer->address >> 16) & 0xff,
(xfer->address >> 8) & 0xff,
@@ -564,6 +264,335 @@ xfer_close (struct t_xfer *xfer, enum t_xfer_status status)
}
}
/*
* xfer_port_in_use: return 1 if a port is in used
* (by an active or connecting xfer)
*/
int
xfer_port_in_use (int port)
{
struct t_xfer *ptr_xfer;
/* skip any currently used ports */
for (ptr_xfer = xfer_list; ptr_xfer; ptr_xfer = ptr_xfer->next_xfer)
{
if ((ptr_xfer->port == port) && (!XFER_HAS_ENDED(ptr_xfer->status)))
return 1;
}
/* port not in use */
return 0;
}
/*
* xfer_send_signal: send a signal for a xfer
*/
void
xfer_send_signal (struct t_xfer *xfer, char *signal)
{
struct t_plugin_infolist *infolist;
struct t_plugin_infolist_item *item;
char str_long[128];
infolist = weechat_infolist_new ();
if (infolist)
{
item = weechat_infolist_new_item (infolist);
if (item)
{
weechat_infolist_new_var_string (item, "plugin_name",
xfer->plugin_name);
weechat_infolist_new_var_string (item, "plugin_id",
xfer->plugin_id);
weechat_infolist_new_var_string (item, "type",
xfer_type_string[xfer->type]);
weechat_infolist_new_var_string (item, "protocol",
xfer_protocol_string[xfer->protocol]);
weechat_infolist_new_var_string (item, "remote_nick",
xfer->remote_nick);
weechat_infolist_new_var_string (item, "local_nick",
xfer->local_nick);
weechat_infolist_new_var_string (item, "filename",
xfer->filename);
snprintf (str_long, sizeof (str_long), "%lu", xfer->size);
weechat_infolist_new_var_string (item, "size",
str_long);
snprintf (str_long, sizeof (str_long), "%lu", xfer->address);
weechat_infolist_new_var_string (item, "address",
str_long);
weechat_infolist_new_var_integer (item, "port",
xfer->port);
weechat_hook_signal_send (signal, WEECHAT_HOOK_SIGNAL_POINTER,
infolist);
}
weechat_infolist_free (infolist);
}
}
/*
* xfer_alloc: allocate a new xfer
*/
struct t_xfer *
xfer_alloc ()
{
struct t_xfer *new_xfer;
time_t time_now;
/* create new xfer struct */
if ((new_xfer = malloc (sizeof (*new_xfer))) == NULL)
return NULL;
time_now = time (NULL);
/* default values */
new_xfer->filename = NULL;
new_xfer->size = 0;
new_xfer->address = 0;
new_xfer->port = 0;
new_xfer->remote_nick = NULL;
new_xfer->local_nick = NULL;
new_xfer->type = 0;
new_xfer->protocol = 0;
new_xfer->status = 0;
new_xfer->buffer = NULL;
new_xfer->fast_send = weechat_config_boolean (xfer_config_network_fast_send);
new_xfer->blocksize = weechat_config_integer (xfer_config_network_blocksize);
new_xfer->start_time = time_now;
new_xfer->start_transfer = time_now;
new_xfer->sock = -1;
new_xfer->child_pid = 0;
new_xfer->child_read = -1;
new_xfer->child_write = -1;
new_xfer->hook_fd = NULL;
new_xfer->hook_timer = NULL;
new_xfer->unterminated_message = NULL;
new_xfer->file = -1;
new_xfer->local_filename = NULL;
new_xfer->filename_suffix = -1;
new_xfer->pos = 0;
new_xfer->ack = 0;
new_xfer->start_resume = 0;
new_xfer->last_check_time = time_now;
new_xfer->last_check_pos = time_now;
new_xfer->last_activity = 0;
new_xfer->bytes_per_sec = 0;
new_xfer->eta = 0;
new_xfer->prev_xfer = NULL;
new_xfer->next_xfer = xfer_list;
if (xfer_list)
xfer_list->prev_xfer = new_xfer;
else
last_xfer = new_xfer;
xfer_list = new_xfer;
xfer_count++;
return new_xfer;
}
/*
* xfer_new: add a xfer to list
*/
struct t_xfer *
xfer_new (char *plugin_name, char *plugin_id, enum t_xfer_type type,
enum t_xfer_protocol protocol, char *remote_nick, char *local_nick,
char *filename,
unsigned long size, unsigned long address, int port, int sock,
char *local_filename)
{
struct t_xfer *new_xfer;
new_xfer = xfer_alloc ();
if (!new_xfer)
{
weechat_printf (NULL,
_("%s%s: not enough memory for new xfer"),
weechat_prefix ("error"), "xfer");
return NULL;
}
if (!xfer_buffer
&& weechat_config_boolean (xfer_config_look_auto_open_buffer))
{
xfer_buffer_open ();
}
/* initialize new xfer */
new_xfer->plugin_name = strdup (plugin_name);
new_xfer->plugin_id = strdup (plugin_id);
new_xfer->type = type;
new_xfer->protocol = protocol;
new_xfer->remote_nick = strdup (remote_nick);
new_xfer->local_nick = (local_nick) ? strdup (local_nick) : NULL;
if (XFER_IS_FILE(type))
new_xfer->filename = (filename) ? strdup (filename) : NULL;
else
new_xfer->filename = strdup (_("xfer chat"));
new_xfer->size = size;
new_xfer->address = address;
new_xfer->port = port;
new_xfer->status = XFER_STATUS_WAITING;
new_xfer->sock = sock;
if (local_filename)
new_xfer->local_filename = strdup (local_filename);
else
xfer_file_find_filename (new_xfer);
/* write info message on server buffer */
switch (type)
{
case XFER_TYPE_FILE_RECV:
weechat_printf (NULL,
_("%s: incoming file from %s "
"(%d.%d.%d.%d): %s, %lu bytes (protocol: %s)"),
"xfer",
remote_nick,
address >> 24,
(address >> 16) & 0xff,
(address >> 8) & 0xff,
address & 0xff,
filename,
size,
xfer_protocol_string[protocol]);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
break;
case XFER_TYPE_FILE_SEND:
weechat_printf (NULL,
_("%s: sending file to %s: %s "
"(local filename: %s), %lu bytes (protocol: %s)"),
"xfer",
remote_nick,
filename,
local_filename,
size,
xfer_protocol_string[protocol]);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
break;
case XFER_TYPE_CHAT_RECV:
weechat_printf (NULL,
_("%s: incoming chat request from %s "
"(%d.%d.%d.%d)"),
"xfer",
remote_nick,
address >> 24,
(address >> 16) & 0xff,
(address >> 8) & 0xff,
address & 0xff);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
break;
case XFER_TYPE_CHAT_SEND:
weechat_printf (NULL,
_("%s: sending chat request to %s"),
"xfer",
remote_nick);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
break;
case XFER_NUM_TYPES:
break;
}
if (XFER_IS_FILE(type) && (!new_xfer->local_filename))
{
xfer_close (new_xfer, XFER_STATUS_FAILED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
return NULL;
}
if (XFER_IS_FILE(type) && (new_xfer->start_resume > 0))
{
weechat_printf (NULL,
_("%s: file %s (local filename: %s) "
"will be resumed at position %u"),
"xfer",
new_xfer->filename,
new_xfer->local_filename,
new_xfer->start_resume);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
}
/* connect if needed and display again xfer buffer */
if (XFER_IS_SEND(type))
{
if (!xfer_network_connect (new_xfer))
{
xfer_close (new_xfer, XFER_STATUS_FAILED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
return NULL;
}
}
if ( ( (type == XFER_TYPE_FILE_RECV)
&& (weechat_config_boolean (xfer_config_file_auto_accept_files)) )
|| ( (type == XFER_TYPE_CHAT_RECV)
&& (weechat_config_boolean (xfer_config_file_auto_accept_chats)) ) )
xfer_network_accept (new_xfer);
else
xfer_buffer_refresh (WEECHAT_HOTLIST_PRIVATE);
return new_xfer;
}
/*
* xfer_free: free xfer struct and remove it from list
*/
void
xfer_free (struct t_xfer *xfer)
{
struct t_xfer *new_xfer_list;
if (!xfer)
return;
if (xfer->buffer)
{
weechat_buffer_close (xfer->buffer, 1);
}
/* remove xfer from list */
if (last_xfer == xfer)
last_xfer = xfer->prev_xfer;
if (xfer->prev_xfer)
{
(xfer->prev_xfer)->next_xfer = xfer->next_xfer;
new_xfer_list = xfer_list;
}
else
new_xfer_list = xfer->next_xfer;
if (xfer->next_xfer)
(xfer->next_xfer)->prev_xfer = xfer->prev_xfer;
/* free data */
if (xfer->plugin_id)
free (xfer->plugin_id);
if (xfer->remote_nick)
free (xfer->remote_nick);
if (xfer->local_nick)
free (xfer->local_nick);
if (xfer->filename)
free (xfer->filename);
if (xfer->unterminated_message)
free (xfer->unterminated_message);
if (xfer->local_filename)
free (xfer->local_filename);
free (xfer);
xfer_list = new_xfer_list;
xfer_count--;
if (xfer_buffer_selected_line >= xfer_count)
xfer_buffer_selected_line = (xfer_count == 0) ? 0 : xfer_count - 1;
}
/*
* xfer_add_cb: callback for "xfer_add" signal
*/
@@ -572,7 +601,8 @@ int
xfer_add_cb (void *data, char *signal, char *type_data, void *signal_data)
{
struct t_plugin_infolist *infolist;
char *plugin_id, *str_type, *nick, *filename, *str_protocol;
char *plugin_name, *plugin_id, *str_type, *str_protocol;
char *remote_nick, *local_nick, *filename;
int type, protocol;
char *weechat_dir, *dir1, *dir2, *filename2, *short_filename, *pos;
int spaces, args, port_start, port_end;
@@ -612,14 +642,16 @@ xfer_add_cb (void *data, char *signal, char *type_data, void *signal_data)
return WEECHAT_RC_ERROR;
}
plugin_name = weechat_infolist_string (infolist, "plugin_name");
plugin_id = weechat_infolist_string (infolist, "plugin_id");
str_type = weechat_infolist_string (infolist, "type");
nick = weechat_infolist_string (infolist, "nick");
filename = weechat_infolist_string (infolist, "filename");
str_protocol = weechat_infolist_string (infolist, "protocol");
remote_nick = weechat_infolist_string (infolist, "remote_nick");
local_nick = weechat_infolist_string (infolist, "local_nick");
filename = weechat_infolist_string (infolist, "filename");
protocol = XFER_NO_PROTOCOL;
if (!plugin_id || !str_type || !nick)
if (!plugin_name || !plugin_id || !str_type || !remote_nick || !local_nick)
{
weechat_printf (NULL,
_("%s%s: missing arguments"),
@@ -636,19 +668,11 @@ xfer_add_cb (void *data, char *signal, char *type_data, void *signal_data)
return WEECHAT_RC_ERROR;
}
if (XFER_IS_FILE(type) && !filename)
if (XFER_IS_FILE(type) && (!filename || !str_protocol))
{
weechat_printf (NULL,
_("%s%s: filename missing for type \"%s\""),
weechat_prefix ("error"), "xfer", str_type);
return WEECHAT_RC_ERROR;
}
if (XFER_IS_FILE(type) && !str_protocol)
{
weechat_printf (NULL,
_("%s%s: protocol missing for type \"%s\""),
weechat_prefix ("error"), "xfer", str_type);
_("%s%s: missing arguments"),
weechat_prefix ("error"), "xfer");
return WEECHAT_RC_ERROR;
}
@@ -670,11 +694,10 @@ xfer_add_cb (void *data, char *signal, char *type_data, void *signal_data)
if (type == XFER_TYPE_FILE_RECV)
{
filename2 = weechat_infolist_string (infolist, "filename");
filename2 = strdup (filename);
sscanf (weechat_infolist_string (infolist, "size"), "%lu", &file_size);
port = weechat_infolist_integer (infolist, "port");
}
if (type == XFER_TYPE_FILE_SEND)
{
/* add home if filename not beginning with '/' or '~' (not for Win32) */
@@ -744,7 +767,7 @@ xfer_add_cb (void *data, char *signal, char *type_data, void *signal_data)
if (XFER_IS_RECV(type))
{
sscanf (weechat_infolist_string (infolist, "address"), "%lu", &local_addr);
sscanf (weechat_infolist_string (infolist, "size"), "%lu", &file_size);
port = weechat_infolist_integer (infolist, "port");
}
else
{
@@ -848,7 +871,7 @@ xfer_add_cb (void *data, char *signal, char *type_data, void *signal_data)
}
}
if (type == XFER_TYPE_FILE_SEND)
if (XFER_IS_FILE(type))
{
/* extract short filename (without path) */
pos = strrchr (filename2, DIR_SEPARATOR_CHAR);
@@ -872,14 +895,25 @@ xfer_add_cb (void *data, char *signal, char *type_data, void *signal_data)
pos++;
}
}
if (type == XFER_TYPE_FILE_RECV)
{
if (filename2)
{
free (filename2);
filename2 = NULL;
}
}
/* add xfer entry and listen to socket if type is file or chat "send" */
if (XFER_IS_FILE(type))
ptr_xfer = xfer_new (plugin_id, type, protocol, nick, short_filename,
ptr_xfer = xfer_new (plugin_name, plugin_id, type, protocol,
remote_nick, local_nick, short_filename,
file_size, local_addr, port, sock, filename2);
else
ptr_xfer = xfer_new (plugin_id, type, protocol, nick, NULL, 0,
local_addr, port, sock, NULL);
ptr_xfer = xfer_new (plugin_name, plugin_id, type, protocol,
remote_nick, local_nick, NULL, 0, local_addr,
port, sock, NULL);
if (!ptr_xfer)
{
@@ -896,7 +930,8 @@ xfer_add_cb (void *data, char *signal, char *type_data, void *signal_data)
}
/* send signal if type is file or chat "send" */
xfer_send_signal (ptr_xfer, "xfer_send_ready");
if (XFER_IS_SEND(ptr_xfer->type))
xfer_send_signal (ptr_xfer, "xfer_send_ready");
if (short_filename)
free (short_filename);
@@ -919,11 +954,13 @@ xfer_print_log ()
{
weechat_log_printf ("");
weechat_log_printf ("[xfer (addr:0x%x)]", ptr_xfer);
weechat_log_printf (" plugin_name . . . . : '%s'", ptr_xfer->plugin_name);
weechat_log_printf (" plugin_id . . . . . : '%s'", ptr_xfer->plugin_id);
weechat_log_printf (" type. . . . . . . . : %d (%s)",
ptr_xfer->type,
xfer_type_string[ptr_xfer->type]);
weechat_log_printf (" nick. . . . . . . . : '%s'", ptr_xfer->nick);
weechat_log_printf (" remote_nick . . . . : '%s'", ptr_xfer->remote_nick);
weechat_log_printf (" local_nick. . . . . : '%s'", ptr_xfer->local_nick);
weechat_log_printf (" filename. . . . . . : '%s'", ptr_xfer->filename);
weechat_log_printf (" size. . . . . . . . : %lu", ptr_xfer->size);
weechat_log_printf (" address . . . . . . : %lu", ptr_xfer->address);
@@ -1002,6 +1039,8 @@ weechat_plugin_init (struct t_weechat_plugin *plugin)
xfer_create_directories ();
xfer_command_init ();
weechat_hook_signal ("xfer_add", &xfer_add_cb, NULL);
weechat_hook_signal ("debug_dump", &xfer_debug_dump_cb, NULL);
@@ -1029,10 +1068,10 @@ weechat_plugin_end (struct t_weechat_plugin *plugin)
weechat_printf (NULL,
_("%s%s: aborting active xfer: \"%s\" from %s"),
weechat_prefix ("error"), "xfer",
ptr_xfer->filename, ptr_xfer->nick);
weechat_log_printf (_("%s: aborting active xfer: \"%s\" from %s"),
"xfer",
ptr_xfer->filename, ptr_xfer->nick);
ptr_xfer->filename, ptr_xfer->remote_nick);
weechat_log_printf (_("%s%s: aborting active xfer: \"%s\" from %s"),
"", "xfer",
ptr_xfer->filename, ptr_xfer->remote_nick);
}
xfer_close (ptr_xfer, XFER_STATUS_FAILED);
}
+9 -3
View File
@@ -106,10 +106,12 @@ enum t_xfer_error
struct t_xfer
{
/* data received by xfer to initiate a transfer */
char *plugin_id; /* plugin identifier */
char *plugin_name; /* plugin name */
char *plugin_id; /* id used by plugin */
enum t_xfer_type type; /* xfer type (send/recv file) */
enum t_xfer_protocol protocol; /* xfer protocol (for file transfer) */
char *nick; /* remote nick */
char *remote_nick; /* remote nick */
char *local_nick; /* local nick */
char *filename; /* filename */
unsigned long size; /* file size */
unsigned long address; /* local or remote IP address */
@@ -127,6 +129,7 @@ struct t_xfer
int child_read; /* to read into child pipe */
int child_write; /* to write into child pipe */
struct t_hook *hook_fd; /* hook for socket or child pipe */
struct t_hook *hook_timer; /* timeout for recever accept */
char *unterminated_message; /* beginning of a message */
int file; /* local file (read or write) */
char *local_filename; /* local filename (with path) */
@@ -148,9 +151,12 @@ extern char *xfer_type_string[];
extern char *xfer_protocol_string[];
extern char *xfer_status_string[];
extern struct t_xfer *xfer_list, *last_xfer;
extern int xfer_count;
extern int xfer_debug;
extern struct t_xfer *xfer_search_by_number (int number);
extern void xfer_close (struct t_xfer *xfer, enum t_xfer_status status);
extern struct t_xfer *xfer_alloc ();
extern void xfer_send_signal (struct t_xfer *xfer, char *signal);
extern void xfer_free (struct t_xfer *xfer);
#endif /* xfer.h */