SFTP: Increase speed and datasize in SFTP read
The function sftp_read never return more then 2000 bytes (as it should when I asked Daniel). I increased the MAX_SFTP_READ_SIZE to 30000 but didn't get the same speed as a sftp read in SecureSSH. I analyzed the code and found that a return always was dona when a chunk has been read. I changed it to a sliding buffer and worked on all available chunks. I got an increase in speed and non of the test I have done has failed (both local net and over Internet). Please review and test. I think 30000 is still not the optimal MAX_SFTP_READ_SIZE, my next goal is to make an API to enable changing this value (The SecureSSH sftp_read has more complete filled packages when comparing the network traffic)
Этот коммит содержится в:
родитель
6c14cc003a
Коммит
d754fee2f2
36
src/sftp.c
36
src/sftp.c
@ -204,7 +204,8 @@ sftp_packet_add(LIBSSH2_SFTP *sftp, unsigned char *data,
|
||||
LIBSSH2_SFTP_PACKET *packet;
|
||||
uint32_t request_id;
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Received packet %d (len %d)",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
|
||||
"Received packet type %d (len %d)",
|
||||
(int) data[0], data_len);
|
||||
|
||||
/*
|
||||
@ -250,6 +251,9 @@ sftp_packet_add(LIBSSH2_SFTP *sftp, unsigned char *data,
|
||||
|
||||
request_id = _libssh2_ntohu32(&data[1]);
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Received packet id %d",
|
||||
request_id);
|
||||
|
||||
/* Don't add the packet if it answers a request we've given up on. */
|
||||
if((data[0] == SSH_FXP_STATUS || data[0] == SSH_FXP_DATA)
|
||||
&& find_zombie_request(sftp, request_id)) {
|
||||
@ -1245,6 +1249,8 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
|
||||
ssize_t rc;
|
||||
struct _libssh2_sftp_handle_file_data *filep =
|
||||
&handle->u.file;
|
||||
size_t bytes_in_buffer = 0;
|
||||
char *sliding_bufferp = buffer;
|
||||
|
||||
/* This function can be interrupted in three different places where it
|
||||
might need to wait for data from the network. It returns EAGAIN to
|
||||
@ -1305,7 +1311,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
|
||||
without having been acked - until we reach EOF. */
|
||||
if(!filep->eof) {
|
||||
/* Number of bytes asked for that haven't been acked yet */
|
||||
size_t already = (filep->offset_sent - filep->offset);
|
||||
size_t already = (size_t)(filep->offset_sent - filep->offset);
|
||||
|
||||
size_t max_read_ahead = buffer_size*4;
|
||||
unsigned long recv_window;
|
||||
@ -1391,6 +1397,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
|
||||
_libssh2_list_add(&handle->packet_list, &chunk->node);
|
||||
count -= size; /* deduct the size we used, as we might have
|
||||
to create more packets */
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "read request id %d sent", request_id);
|
||||
}
|
||||
|
||||
case libssh2_NB_state_sent:
|
||||
@ -1475,7 +1482,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
|
||||
|
||||
if (rc32 == LIBSSH2_FX_EOF) {
|
||||
filep->eof = TRUE;
|
||||
return 0;
|
||||
return bytes_in_buffer;
|
||||
}
|
||||
else {
|
||||
sftp->last_errno = rc32;
|
||||
@ -1505,13 +1512,13 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
|
||||
filep->offset_sent -= (chunk->len - rc32);
|
||||
}
|
||||
|
||||
if(rc32 > buffer_size) {
|
||||
if((bytes_in_buffer + rc32) > buffer_size) {
|
||||
/* figure out the overlap amount */
|
||||
filep->data_left = rc32 - buffer_size;
|
||||
filep->data_left = (bytes_in_buffer + rc32) - buffer_size;
|
||||
|
||||
/* getting the full packet would overflow the buffer, so
|
||||
only get the correct amount and keep the remainder */
|
||||
rc32 = (uint32_t)buffer_size;
|
||||
rc32 = (uint32_t)buffer_size - bytes_in_buffer;
|
||||
|
||||
/* store data to keep for next call */
|
||||
filep->data = data;
|
||||
@ -1522,7 +1529,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
|
||||
|
||||
/* copy the received data from the received FXP_DATA packet to
|
||||
the buffer at the correct index */
|
||||
memcpy(buffer, data + 9, rc32);
|
||||
memcpy(sliding_bufferp, data + 9, rc32);
|
||||
filep->offset += rc32;
|
||||
|
||||
if(filep->data_len == 0)
|
||||
@ -1538,8 +1545,10 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
|
||||
chunk = NULL;
|
||||
|
||||
if(rc32 > 0) {
|
||||
/* we must return as we wrote some data to the buffer */
|
||||
return rc32;
|
||||
/* continue to the next chunk */
|
||||
bytes_in_buffer += rc32;
|
||||
sliding_bufferp += rc32;
|
||||
chunk = next;
|
||||
} else {
|
||||
/* A zero-byte read is not necessarily EOF so we must not
|
||||
* return 0 (that would signal EOF to the caller) so
|
||||
@ -1555,6 +1564,9 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
|
||||
}
|
||||
}
|
||||
|
||||
if (bytes_in_buffer > 0)
|
||||
return bytes_in_buffer;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1827,7 +1839,7 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer,
|
||||
acked but we haven't been able to return as such yet, so we will
|
||||
get that data as well passed in here again.
|
||||
*/
|
||||
already = (handle->u.file.offset_sent - handle->u.file.offset)+
|
||||
already = (size_t) (handle->u.file.offset_sent - handle->u.file.offset)+
|
||||
handle->u.file.acked;
|
||||
|
||||
if(count >= already) {
|
||||
@ -2767,7 +2779,7 @@ static int sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_STATVFS *st)
|
||||
st->f_ffree = _libssh2_ntohu64(data + 53);
|
||||
st->f_favail = _libssh2_ntohu64(data + 61);
|
||||
st->f_fsid = _libssh2_ntohu64(data + 69);
|
||||
flag = _libssh2_ntohu64(data + 77);
|
||||
flag = (unsigned int)_libssh2_ntohu64(data + 77);
|
||||
st->f_namemax = _libssh2_ntohu64(data + 85);
|
||||
|
||||
st->f_flag = (flag & SSH_FXE_STATVFS_ST_RDONLY)
|
||||
@ -2893,7 +2905,7 @@ static int sftp_statvfs(LIBSSH2_SFTP *sftp, const char *path,
|
||||
st->f_ffree = _libssh2_ntohu64(data + 53);
|
||||
st->f_favail = _libssh2_ntohu64(data + 61);
|
||||
st->f_fsid = _libssh2_ntohu64(data + 69);
|
||||
flag = _libssh2_ntohu64(data + 77);
|
||||
flag = (unsigned int)_libssh2_ntohu64(data + 77);
|
||||
st->f_namemax = _libssh2_ntohu64(data + 85);
|
||||
|
||||
st->f_flag = (flag & SSH_FXE_STATVFS_ST_RDONLY)
|
||||
|
@ -48,7 +48,7 @@
|
||||
/* MAX_SFTP_READ_SIZE is how much data is asked for at max in each FXP_READ
|
||||
* packets.
|
||||
*/
|
||||
#define MAX_SFTP_READ_SIZE 2000
|
||||
#define MAX_SFTP_READ_SIZE 30000
|
||||
|
||||
struct sftp_pipeline_chunk {
|
||||
struct list_node node;
|
||||
|
Загрузка…
Ссылка в новой задаче
Block a user