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:
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user