diff options
author | Damien Miller <djm@mindrot.org> | 2002-02-13 14:04:37 +1100 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2002-02-13 14:04:37 +1100 |
commit | 5873dfd829558cd3fdeb56f22c893b3fdc8e87c9 (patch) | |
tree | 11d962daea998b90800c73782eb82528a07ad7e1 | |
parent | 16a133339a40396064effee3de55f6b2a887d3d2 (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-- | ChangeLog | 6 | ||||
-rw-r--r-- | sftp-client.c | 57 |
2 files changed, 53 insertions, 10 deletions
@@ -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 | ||
24 | 20020210 | 28 | 20020210 |
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" |
31 | RCSID("$OpenBSD: sftp-client.c,v 1.21 2002/02/12 12:32:27 djm Exp $"); | 31 | RCSID("$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; |