diff options
author | Sébastien Helleu <flashcode@flashtux.org> | 2019-04-06 14:11:07 +0200 |
---|---|---|
committer | Sébastien Helleu <flashcode@flashtux.org> | 2019-04-06 14:11:07 +0200 |
commit | a84c32cf30a369cd44d8ce7cc8df3277973051f1 (patch) | |
tree | 4f7dae7ce96f60fc63a277d0366a97f22f07abb5 /src/plugins | |
parent | 6ebd97cc63f7953d5ae78db6c1331184504e6b70 (diff) | |
download | weechat-a84c32cf30a369cd44d8ce7cc8df3277973051f1.zip |
xfer: add option xfer.network.speed_limit_recv (closes #269)
For consistency, the option xfer.network.speed_limit has been renamed to
xfer.network.speed_limit_send.
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/xfer/xfer-config.c | 14 | ||||
-rw-r--r-- | src/plugins/xfer/xfer-config.h | 3 | ||||
-rw-r--r-- | src/plugins/xfer/xfer-dcc.c | 207 |
3 files changed, 130 insertions, 94 deletions
diff --git a/src/plugins/xfer/xfer-config.c b/src/plugins/xfer/xfer-config.c index 9624dd61f..ddab21d82 100644 --- a/src/plugins/xfer/xfer-config.c +++ b/src/plugins/xfer/xfer-config.c @@ -50,7 +50,8 @@ struct t_config_option *xfer_config_network_fast_send; struct t_config_option *xfer_config_network_own_ip; struct t_config_option *xfer_config_network_port_range; struct t_config_option *xfer_config_network_send_ack; -struct t_config_option *xfer_config_network_speed_limit; +struct t_config_option *xfer_config_network_speed_limit_send; +struct t_config_option *xfer_config_network_speed_limit_recv; struct t_config_option *xfer_config_network_timeout; /* xfer config, file section */ @@ -294,13 +295,20 @@ xfer_config_init () "the acks are not sent immediately to the sender"), NULL, 0, 0, "on", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - xfer_config_network_speed_limit = weechat_config_new_option ( + xfer_config_network_speed_limit_send = weechat_config_new_option ( xfer_config_file, ptr_section, - "speed_limit", "integer", + "speed_limit_send", "integer", N_("speed limit for sending files, in kilo-bytes by second (0 means " "no limit)"), NULL, 0, INT_MAX, "0", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + xfer_config_network_speed_limit_recv = weechat_config_new_option ( + xfer_config_file, ptr_section, + "speed_limit_recv", "integer", + N_("speed limit for receiving files, in kilo-bytes by second (0 means " + "no limit)"), + NULL, 0, INT_MAX, "0", NULL, 0, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); xfer_config_network_timeout = weechat_config_new_option ( xfer_config_file, ptr_section, "timeout", "integer", diff --git a/src/plugins/xfer/xfer-config.h b/src/plugins/xfer/xfer-config.h index f8f224a5a..2a31f0408 100644 --- a/src/plugins/xfer/xfer-config.h +++ b/src/plugins/xfer/xfer-config.h @@ -40,7 +40,8 @@ extern struct t_config_option *xfer_config_network_fast_send; extern struct t_config_option *xfer_config_network_own_ip; extern struct t_config_option *xfer_config_network_port_range; extern struct t_config_option *xfer_config_network_send_ack; -extern struct t_config_option *xfer_config_network_speed_limit; +extern struct t_config_option *xfer_config_network_speed_limit_send; +extern struct t_config_option *xfer_config_network_speed_limit_recv; extern struct t_config_option *xfer_config_network_timeout; extern struct t_config_option *xfer_config_file_auto_accept_chats; diff --git a/src/plugins/xfer/xfer-dcc.c b/src/plugins/xfer/xfer-dcc.c index 7b6f74033..13306c96d 100644 --- a/src/plugins/xfer/xfer-dcc.c +++ b/src/plugins/xfer/xfer-dcc.c @@ -49,11 +49,11 @@ void xfer_dcc_send_file_child (struct t_xfer *xfer) { - int num_read, num_sent, blocksize; + int num_read, num_sent; static char buffer[XFER_BLOCKSIZE_MAX]; uint32_t ack; time_t last_sent, new_time, last_second, sent_ok; - unsigned long long sent_last_second; + unsigned long long blocksize, speed_limit, sent_last_second; /* empty file? just return immediately */ if (xfer->pos >= xfer->size) @@ -63,15 +63,15 @@ xfer_dcc_send_file_child (struct t_xfer *xfer) return; } - blocksize = xfer->blocksize; - if (weechat_config_integer (xfer_config_network_speed_limit) > 0) - { - if (blocksize > weechat_config_integer (xfer_config_network_speed_limit) * 1024) - blocksize = weechat_config_integer (xfer_config_network_speed_limit) * 1024; - } + speed_limit = (unsigned long long)weechat_config_integer ( + xfer_config_network_speed_limit_send); + + blocksize = (unsigned long long)(xfer->blocksize); + if ((speed_limit > 0) && (blocksize > speed_limit * 1024)) + blocksize = speed_limit * 1024; last_sent = time (NULL); - last_second = time (NULL); + last_second = last_sent; sent_ok = 0; sent_last_second = 0; while (1) @@ -113,8 +113,7 @@ xfer_dcc_send_file_child (struct t_xfer *xfer) if ((xfer->pos < xfer->size) && (xfer->fast_send || (xfer->pos <= xfer->ack))) { - if ((weechat_config_integer (xfer_config_network_speed_limit) > 0) - && (sent_last_second >= (unsigned long long)weechat_config_integer (xfer_config_network_speed_limit) * 1024)) + if ((speed_limit > 0) && (sent_last_second >= speed_limit * 1024)) { /* we're sending too fast (according to speed limit set by user) */ usleep (100); @@ -311,13 +310,20 @@ xfer_dcc_recv_file_child (struct t_xfer *xfer) { int flags, num_read, ready; static char buffer[XFER_BLOCKSIZE_MAX]; - time_t last_sent, new_time; - unsigned long long pos_last_ack; + time_t last_sent, last_second, new_time; + unsigned long long blocksize, pos_last_ack, speed_limit, recv_last_second; struct pollfd poll_fd; ssize_t written, total_written; unsigned char *bin_hash; char hash[9]; + speed_limit = (unsigned long long)weechat_config_integer ( + xfer_config_network_speed_limit_recv); + + blocksize = sizeof (buffer); + if ((speed_limit > 0) && (blocksize > speed_limit * 1024)) + blocksize = speed_limit * 1024; + /* if resuming, hash the portion of the file we have */ if ((xfer->start_resume > 0) && xfer->hash_handle) { @@ -361,6 +367,8 @@ xfer_dcc_recv_file_child (struct t_xfer *xfer) fcntl (xfer->sock, F_SETFL, flags | O_NONBLOCK); last_sent = time (NULL); + last_second = last_sent; + recv_last_second = 0; pos_last_ack = 0; while (1) @@ -385,114 +393,133 @@ xfer_dcc_recv_file_child (struct t_xfer *xfer) /* read maximum data on socket (until nothing is available) */ while (1) { - num_read = recv (xfer->sock, buffer, sizeof (buffer), 0); - if (num_read == -1) + if ((speed_limit > 0) && (recv_last_second >= speed_limit * 1024)) { - if ((errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINTR)) - { - xfer_network_write_pipe (xfer, XFER_STATUS_FAILED, - XFER_ERROR_RECV_BLOCK); - return; - } /* - * no more data available on socket: exit loop, send ACK, and - * wait for new data on socket + * we're receiving too fast + * (according to speed limit set by user) */ - break; + usleep (100); } else { - if ((num_read == 0) && (xfer->pos < xfer->size)) + num_read = recv (xfer->sock, buffer, blocksize, 0); + if (num_read == -1) { - xfer_network_write_pipe (xfer, XFER_STATUS_FAILED, - XFER_ERROR_RECV_BLOCK); - return; + if ((errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINTR)) + { + xfer_network_write_pipe (xfer, XFER_STATUS_FAILED, + XFER_ERROR_RECV_BLOCK); + return; + } + /* + * no more data available on socket: exit loop, send ACK, and + * wait for new data on socket + */ + break; } - - /* bytes received, write to disk */ - total_written = 0; - while (total_written < num_read) + else { - written = write (xfer->file, - buffer + total_written, - num_read - total_written); - if (written < 0) + if ((num_read == 0) && (xfer->pos < xfer->size)) { - if (errno == EINTR) - continue; xfer_network_write_pipe (xfer, XFER_STATUS_FAILED, - XFER_ERROR_WRITE_LOCAL); + XFER_ERROR_RECV_BLOCK); return; } - else + + /* bytes received, write to disk */ + total_written = 0; + while (total_written < num_read) { - if (xfer->hash_handle) + written = write (xfer->file, + buffer + total_written, + num_read - total_written); + if (written < 0) { - gcry_md_write (*xfer->hash_handle, - buffer + total_written, - written); + if (errno == EINTR) + continue; + xfer_network_write_pipe (xfer, XFER_STATUS_FAILED, + XFER_ERROR_WRITE_LOCAL); + return; + } + else + { + if (xfer->hash_handle) + { + gcry_md_write (*xfer->hash_handle, + buffer + total_written, + written); + } + total_written += written; } - total_written += written; } - } - xfer->pos += (unsigned long long) num_read; + xfer->pos += (unsigned long long) num_read; + recv_last_second += (unsigned long long) num_read; - /* file received OK? */ - if (xfer->pos >= xfer->size) - { - /* check hash and report result to pipe */ - if (xfer->hash_handle) + /* file received OK? */ + if (xfer->pos >= xfer->size) { - gcry_md_final (*xfer->hash_handle); - bin_hash = gcry_md_read (*xfer->hash_handle, 0); - if (bin_hash) + /* check hash and report result to pipe */ + if (xfer->hash_handle) { - snprintf (hash, sizeof (hash), "%.2X%.2X%.2X%.2X", - bin_hash[0], bin_hash[1], bin_hash[2], - bin_hash[3]); - if (weechat_strcasecmp (hash, - xfer->hash_target) == 0) - { - xfer_network_write_pipe (xfer, - XFER_STATUS_HASHED, - XFER_NO_ERROR); - } - else + gcry_md_final (*xfer->hash_handle); + bin_hash = gcry_md_read (*xfer->hash_handle, 0); + if (bin_hash) { - xfer_network_write_pipe (xfer, - XFER_STATUS_HASHED, - XFER_ERROR_HASH_MISMATCH); + snprintf (hash, sizeof (hash), "%.2X%.2X%.2X%.2X", + bin_hash[0], bin_hash[1], bin_hash[2], + bin_hash[3]); + if (weechat_strcasecmp (hash, + xfer->hash_target) == 0) + { + xfer_network_write_pipe (xfer, + XFER_STATUS_HASHED, + XFER_NO_ERROR); + } + else + { + xfer_network_write_pipe (xfer, + XFER_STATUS_HASHED, + XFER_ERROR_HASH_MISMATCH); + } } } - } - fsync (xfer->file); + fsync (xfer->file); - /* - * extra delay before sending ACK, otherwise the send of ACK - * may fail - */ - usleep (100000); + /* + * extra delay before sending ACK, otherwise the send of ACK + * may fail + */ + usleep (100000); - /* send ACK to sender without checking return code (file OK) */ - xfer_dcc_recv_file_send_ack (xfer); + /* send ACK to sender without checking return code (file OK) */ + xfer_dcc_recv_file_send_ack (xfer); - /* set status done and return */ - xfer_network_write_pipe (xfer, XFER_STATUS_DONE, - XFER_NO_ERROR); - return; - } + /* set status done and return */ + xfer_network_write_pipe (xfer, XFER_STATUS_DONE, + XFER_NO_ERROR); + return; + } - /* update status of DCC (parent process) */ - new_time = time (NULL); - if (last_sent != new_time) - { - last_sent = new_time; - xfer_network_write_pipe (xfer, XFER_STATUS_ACTIVE, - XFER_NO_ERROR); + /* update status of DCC (parent process) */ + new_time = time (NULL); + if (last_sent != new_time) + { + last_sent = new_time; + xfer_network_write_pipe (xfer, XFER_STATUS_ACTIVE, + XFER_NO_ERROR); + } } } + + new_time = time (NULL); + if (new_time > last_second) + { + last_second = new_time; + recv_last_second = 0; + } } /* send ACK to sender (if needed) */ |