PSCP in SFTP mode now uses the fast download/upload manager.
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Mon, 29 Sep 2003 15:39:56 +0000 (15:39 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Mon, 29 Sep 2003 15:39:56 +0000 (15:39 +0000)
git-svn-id: svn://svn.tartarus.org/sgt/putty@3472 cda61777-01e9-0310-a592-d414129be87e

scp.c

diff --git a/scp.c b/scp.c
index 00852bc..de39484 100644 (file)
--- a/scp.c
+++ b/scp.c
@@ -673,6 +673,7 @@ static int scp_sftp_preserve, scp_sftp_recursive;
 static unsigned long scp_sftp_mtime, scp_sftp_atime;
 static int scp_has_times;
 static struct fxp_handle *scp_sftp_filehandle;
+static struct fxp_xfer *scp_sftp_xfer;
 static uint64 scp_sftp_fileoffset;
 
 void scp_source_setup(char *target, int shouldbedir)
@@ -767,6 +768,8 @@ int scp_send_filename(char *name, unsigned long size, int modes)
            return 1;
        }
        scp_sftp_fileoffset = uint64_make(0, 0);
+       scp_sftp_xfer = xfer_upload_init(scp_sftp_filehandle,
+                                        scp_sftp_fileoffset);
        sfree(fullname);
        return 0;
     } else {
@@ -784,23 +787,23 @@ int scp_send_filedata(char *data, int len)
     if (using_sftp) {
        int ret;
        struct sftp_packet *pktin;
-       struct sftp_request *req, *rreq;
 
        if (!scp_sftp_filehandle) {
            return 1;
        }
 
-       sftp_register(req = fxp_write_send(scp_sftp_filehandle,
-                                          data, scp_sftp_fileoffset, len));
-       rreq = sftp_find_request(pktin = sftp_recv());
-       assert(rreq == req);
-       ret = fxp_write_recv(pktin, rreq);
-
-       if (!ret) {
-           tell_user(stderr, "error while writing: %s\n", fxp_error());
-           errs++;
-           return 1;
+       while (!xfer_upload_ready(scp_sftp_xfer)) {
+           pktin = sftp_recv();
+           ret = xfer_upload_gotpkt(scp_sftp_xfer, pktin);
+           if (!ret) {
+               tell_user(stderr, "error while writing: %s\n", fxp_error());
+               errs++;
+               return 1;
+           }
        }
+
+       xfer_upload_data(scp_sftp_xfer, data, len);
+
        scp_sftp_fileoffset = uint64_add32(scp_sftp_fileoffset, len);
        return 0;
     } else {
@@ -830,6 +833,12 @@ int scp_send_finish(void)
        struct sftp_request *req, *rreq;
        int ret;
 
+       while (!xfer_done(scp_sftp_xfer)) {
+           pktin = sftp_recv();
+           xfer_upload_gotpkt(scp_sftp_xfer, pktin);
+       }
+       xfer_cleanup(scp_sftp_xfer);
+
        if (!scp_sftp_filehandle) {
            return 1;
        }
@@ -1388,6 +1397,8 @@ int scp_accept_filexfer(void)
            return 1;
        }
        scp_sftp_fileoffset = uint64_make(0, 0);
+       scp_sftp_xfer = xfer_download_init(scp_sftp_filehandle,
+                                          scp_sftp_fileoffset);
        sfree(scp_sftp_currentname);
        return 0;
     } else {
@@ -1400,21 +1411,30 @@ int scp_recv_filedata(char *data, int len)
 {
     if (using_sftp) {
        struct sftp_packet *pktin;
-       struct sftp_request *req, *rreq;
-       int actuallen;
+       int ret, actuallen;
+       void *vbuf;
 
-       sftp_register(req = fxp_read_send(scp_sftp_filehandle,
-                                         scp_sftp_fileoffset, len));
-       rreq = sftp_find_request(pktin = sftp_recv());
-       assert(rreq == req);
-       actuallen = fxp_read_recv(pktin, rreq, data, len);
+       xfer_download_queue(scp_sftp_xfer);
+       pktin = sftp_recv();
+       ret = xfer_download_gotpkt(scp_sftp_xfer, pktin);
 
-       if (actuallen == -1 && fxp_error_type() != SSH_FX_EOF) {
+       if (ret < 0) {
            tell_user(stderr, "pscp: error while reading: %s", fxp_error());
            errs++;
            return -1;
        }
-       if (actuallen < 0)
+
+       if (xfer_download_data(scp_sftp_xfer, &vbuf, &actuallen)) {
+           /*
+            * This assertion relies on the fact that the natural
+            * block size used in the xfer manager is at most that
+            * used in this module. I don't like crossing layers in
+            * this way, but it'll do for now.
+            */
+           assert(actuallen <= len);
+           memcpy(data, vbuf, actuallen);
+           sfree(vbuf);
+       } else
            actuallen = 0;
 
        scp_sftp_fileoffset = uint64_add32(scp_sftp_fileoffset, actuallen);
@@ -1431,6 +1451,23 @@ int scp_finish_filerecv(void)
        struct sftp_packet *pktin;
        struct sftp_request *req, *rreq;
 
+       /*
+        * Ensure that xfer_done() will work correctly, so we can
+        * clean up any outstanding requests from the file
+        * transfer.
+        */
+       xfer_set_error(scp_sftp_xfer);
+       while (!xfer_done(scp_sftp_xfer)) {
+           void *vbuf;
+           int len;
+
+           pktin = sftp_recv();
+           xfer_download_gotpkt(scp_sftp_xfer, pktin);
+           if (xfer_download_data(scp_sftp_xfer, &vbuf, &len))
+               sfree(vbuf);
+       }
+       xfer_cleanup(scp_sftp_xfer);
+
        sftp_register(req = fxp_close_send(scp_sftp_filehandle));
        rreq = sftp_find_request(pktin = sftp_recv());
        assert(rreq == req);