summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2002-02-13 14:04:37 +1100
committerDamien Miller <djm@mindrot.org>2002-02-13 14:04:37 +1100
commit5873dfd829558cd3fdeb56f22c893b3fdc8e87c9 (patch)
tree11d962daea998b90800c73782eb82528a07ad7e1
parent16a133339a40396064effee3de55f6b2a887d3d2 (diff)
- djm@cvs.openbsd.org 2002/02/12 12:44:46
[sftp-client.c] Let overlapped upload path handle servers which reorder ACKs. This may be permitted by the protocol spec; ok markus@
-rw-r--r--ChangeLog6
-rw-r--r--sftp-client.c57
2 files changed, 53 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index 6895f5267..aca92af35 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -20,6 +20,10 @@
20 [sftp.1 sftp.c sftp-client.c sftp-client.h sftp-int.c] 20 [sftp.1 sftp.c sftp-client.c sftp-client.h sftp-int.c]
21 Perform multiple overlapping read/write requests in file transfer. Mostly 21 Perform multiple overlapping read/write requests in file transfer. Mostly
22 done by Tobias Ringstrom <tori@ringstrom.mine.nu>; ok markus@ 22 done by Tobias Ringstrom <tori@ringstrom.mine.nu>; ok markus@
23 - djm@cvs.openbsd.org 2002/02/12 12:44:46
24 [sftp-client.c]
25 Let overlapped upload path handle servers which reorder ACKs. This may be
26 permitted by the protocol spec; ok markus@
23 27
2420020210 2820020210
25 - (djm) OpenBSD CVS Sync 29 - (djm) OpenBSD CVS Sync
@@ -7567,4 +7571,4 @@
7567 - Wrote replacements for strlcpy and mkdtemp 7571 - Wrote replacements for strlcpy and mkdtemp
7568 - Released 1.0pre1 7572 - Released 1.0pre1
7569 7573
7570$Id: ChangeLog,v 1.1844 2002/02/13 03:03:56 djm Exp $ 7574$Id: ChangeLog,v 1.1845 2002/02/13 03:04:37 djm Exp $
diff --git a/sftp-client.c b/sftp-client.c
index 835ae068a..cb11fd581 100644
--- a/sftp-client.c
+++ b/sftp-client.c
@@ -28,7 +28,7 @@
28/* XXX: copy between two remote sites */ 28/* XXX: copy between two remote sites */
29 29
30#include "includes.h" 30#include "includes.h"
31RCSID("$OpenBSD: sftp-client.c,v 1.21 2002/02/12 12:32:27 djm Exp $"); 31RCSID("$OpenBSD: sftp-client.c,v 1.22 2002/02/12 12:44:46 djm Exp $");
32 32
33#if defined(HAVE_SYS_QUEUE_H) && !defined(HAVE_BOGUS_SYS_QUEUE_H) 33#if defined(HAVE_SYS_QUEUE_H) && !defined(HAVE_BOGUS_SYS_QUEUE_H)
34#include <sys/queue.h> 34#include <sys/queue.h>
@@ -905,7 +905,7 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
905 int pflag, size_t buflen, int num_requests) 905 int pflag, size_t buflen, int num_requests)
906{ 906{
907 int local_fd, status; 907 int local_fd, status;
908 u_int handle_len, id; 908 u_int handle_len, id, type;
909 u_int64_t offset; 909 u_int64_t offset;
910 char *handle, *data; 910 char *handle, *data;
911 Buffer msg; 911 Buffer msg;
@@ -913,6 +913,16 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
913 Attrib a; 913 Attrib a;
914 u_int32_t startid; 914 u_int32_t startid;
915 u_int32_t ackid; 915 u_int32_t ackid;
916 struct outstanding_ack {
917 u_int id;
918 u_int len;
919 u_int64_t offset;
920 TAILQ_ENTRY(outstanding_ack) tq;
921 };
922 TAILQ_HEAD(ackhead, outstanding_ack) acks;
923 struct outstanding_ack *ack;
924
925 TAILQ_INIT(&acks);
916 926
917 if ((local_fd = open(local_path, O_RDONLY, 0)) == -1) { 927 if ((local_fd = open(local_path, O_RDONLY, 0)) == -1) {
918 error("Couldn't open local file \"%s\" for reading: %s", 928 error("Couldn't open local file \"%s\" for reading: %s",
@@ -975,21 +985,49 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
975 strerror(errno)); 985 strerror(errno));
976 986
977 if (len != 0) { 987 if (len != 0) {
988 ack = xmalloc(sizeof(*ack));
989 ack->id = ++id;
990 ack->offset = offset;
991 ack->len = len;
992 TAILQ_INSERT_TAIL(&acks, ack, tq);
993
978 buffer_clear(&msg); 994 buffer_clear(&msg);
979 buffer_put_char(&msg, SSH2_FXP_WRITE); 995 buffer_put_char(&msg, SSH2_FXP_WRITE);
980 buffer_put_int(&msg, ++id); 996 buffer_put_int(&msg, ack->id);
981 buffer_put_string(&msg, handle, handle_len); 997 buffer_put_string(&msg, handle, handle_len);
982 buffer_put_int64(&msg, offset); 998 buffer_put_int64(&msg, offset);
983 buffer_put_string(&msg, data, len); 999 buffer_put_string(&msg, data, len);
984 send_msg(fd_out, &msg); 1000 send_msg(fd_out, &msg);
985 debug3("Sent message SSH2_FXP_WRITE I:%d O:%llu S:%u", 1001 debug3("Sent message SSH2_FXP_WRITE I:%d O:%llu S:%u",
986 id, (u_int64_t)offset, len); 1002 id, (u_int64_t)offset, len);
987 } else if ( id < ackid ) 1003 } else if (TAILQ_FIRST(&acks) == NULL)
988 break; 1004 break;
989 1005
990 if (id == startid || len == 0 || 1006 if (ack == NULL)
991 id - ackid >= num_requests) { 1007 fatal("Unexpected ACK %u", id);
992 status = get_status(fd_in, ackid); 1008
1009 if (id == startid || len == 0 || id - ackid >= num_requests) {
1010 buffer_clear(&msg);
1011 get_msg(fd_in, &msg);
1012 type = buffer_get_char(&msg);
1013 id = buffer_get_int(&msg);
1014
1015 if (type != SSH2_FXP_STATUS)
1016 fatal("Expected SSH2_FXP_STATUS(%d) packet, "
1017 "got %d", SSH2_FXP_STATUS, type);
1018
1019 status = buffer_get_int(&msg);
1020 debug3("SSH2_FXP_STATUS %d", status);
1021
1022 /* Find the request in our queue */
1023 for(ack = TAILQ_FIRST(&acks);
1024 ack != NULL && ack->id != id;
1025 ack = TAILQ_NEXT(ack, tq))
1026 ;
1027 if (ack == NULL)
1028 fatal("Can't find request for ID %d", id);
1029 TAILQ_REMOVE(&acks, ack, tq);
1030
993 if (status != SSH2_FX_OK) { 1031 if (status != SSH2_FX_OK) {
994 error("Couldn't write to remote file \"%s\": %s", 1032 error("Couldn't write to remote file \"%s\": %s",
995 remote_path, fx2txt(status)); 1033 remote_path, fx2txt(status));
@@ -997,9 +1035,10 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
997 close(local_fd); 1035 close(local_fd);
998 goto done; 1036 goto done;
999 } 1037 }
1000 debug3("In write loop, got %d offset %llu", len, 1038 debug3("In write loop, ack for %u %d bytes at %llu",
1001 (u_int64_t)offset); 1039 ack->id, ack->len, ack->offset);
1002 ++ackid; 1040 ++ackid;
1041 free(ack);
1003 } 1042 }
1004 1043
1005 offset += len; 1044 offset += len;