1
0
mirror of https://github.com/weechat/weechat.git synced 2026-07-10 03:33:12 +02:00

xfer: fix freeze of DCC file received: use non-blocking socket after connection to sender and ensure the ACK is properly sent (bug #38340)

This commit is contained in:
Sebastien Helleu
2013-02-26 21:43:39 +01:00
parent 0e641e0c45
commit e890ac0a81
15 changed files with 184 additions and 103 deletions
+30 -3
View File
@@ -179,9 +179,10 @@ xfer_dcc_send_file_child (struct t_xfer *xfer)
void
xfer_dcc_recv_file_child (struct t_xfer *xfer)
{
int num_read;
int flags, num_read, num_sent, total_sent, length;
static char buffer[XFER_BLOCKSIZE_MAX];
uint32_t pos;
const void *ptr_buf;
time_t last_sent, new_time;
unsigned long long bytes_remaining;
@@ -198,6 +199,12 @@ xfer_dcc_recv_file_child (struct t_xfer *xfer)
xfer_network_write_pipe (xfer, XFER_STATUS_ACTIVE,
XFER_NO_ERROR);
/* make socket non-blocking */
flags = fcntl (xfer->sock, F_GETFL);
if (flags == -1)
flags = 0;
fcntl (xfer->sock, F_SETFL, flags | O_NONBLOCK);
last_sent = time (NULL);
while (1)
{
@@ -236,8 +243,28 @@ xfer_dcc_recv_file_child (struct t_xfer *xfer)
xfer->pos += (unsigned long long) num_read;
pos = htonl (xfer->pos);
/* we don't check return code, not a problem if an ACK send failed */
send (xfer->sock, (char *) &pos, 4, 0);
/* send the ACK (and ensure the 4 bytes are sent) */
ptr_buf = &pos;
length = 4;
total_sent = 0;
num_sent = send (xfer->sock, ptr_buf, length, 0);
if (num_sent > 0)
total_sent += num_sent;
while (total_sent < length)
{
if ((num_sent == -1) && (errno != EAGAIN)
&& (errno != EWOULDBLOCK))
{
xfer_network_write_pipe (xfer, XFER_STATUS_FAILED,
XFER_ERROR_SEND_ACK);
return;
}
usleep (1000);
num_sent = send (xfer->sock, ptr_buf + total_sent,
length - total_sent, 0);
if (num_sent > 0)
total_sent += num_sent;
}
/* file received ok? */
if (xfer->pos >= xfer->size)
+5
View File
@@ -146,6 +146,11 @@ xfer_network_child_read_cb (void *arg_xfer, int fd)
_("%s%s: unable to write local file"),
weechat_prefix ("error"), XFER_PLUGIN_NAME);
break;
case XFER_ERROR_SEND_ACK:
weechat_printf (NULL,
_("%s%s: unable to send ACK to sender"),
weechat_prefix ("error"), XFER_PLUGIN_NAME);
break;
}
/* read new DCC status */
+3
View File
@@ -66,12 +66,15 @@ enum t_xfer_status
enum t_xfer_error
{
XFER_NO_ERROR = 0, /* no error to report, all ok! */
/* errors for sender: */
XFER_ERROR_READ_LOCAL, /* unable to read local file */
XFER_ERROR_SEND_BLOCK, /* unable to send block to receiver */
XFER_ERROR_READ_ACK, /* unable to read ACK from receiver */
/* errors for receiver: */
XFER_ERROR_CONNECT_SENDER, /* unable to connect to sender */
XFER_ERROR_RECV_BLOCK, /* unable to recv block from sender */
XFER_ERROR_WRITE_LOCAL, /* unable to write to local file */
XFER_ERROR_SEND_ACK, /* unable to send ACK to sender */
/* number of errors */
XFER_NUM_ERRORS,
};