]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
libssh: use libssh sftp_aio to upload file
authorxiaofeng <zuoxf1@lenovo.com>
Fri, 22 Nov 2024 07:02:00 +0000 (15:02 +0800)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 2 Dec 2024 20:33:24 +0000 (21:33 +0100)
Support async sftp upload for curl built with libssh.

Closes #15625

lib/vssh/libssh.c
lib/vssh/ssh.h

index eeef5ca01d6e3016a962432c9c6c34d12ef4a6d3..6bae061ac4ec9ed4ca2edb314b2a46cc4b389b73 100644 (file)
@@ -1368,7 +1368,9 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
          state machine to move on as soon as possible so we set a very short
          timeout here */
       Curl_expire(data, 0, EXPIRE_RUN_NOW);
-
+#if LIBSSH_VERSION_INT > SSH_VERSION_INT(0, 11, 0)
+      sshc->sftp_send_state = 0;
+#endif
       state(data, SSH_STOP);
       break;
     }
@@ -1772,6 +1774,13 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
       /* during times we get here due to a broken transfer and then the
          sftp_handle might not have been taken down so make sure that is done
          before we proceed */
+      ssh_set_blocking(sshc->ssh_session, 0);
+#if LIBSSH_VERSION_INT > SSH_VERSION_INT(0, 11, 0)
+      if(sshc->sftp_aio) {
+        sftp_aio_free(sshc->sftp_aio);
+        sshc->sftp_aio = NULL;
+      }
+#endif
 
       if(sshc->sftp_file) {
         sftp_close(sshc->sftp_file);
@@ -2570,7 +2579,39 @@ static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
    */
   if(len > 32768)
     len = 32768;
-
+#if LIBSSH_VERSION_INT > SSH_VERSION_INT(0, 11, 0)
+  switch(conn->proto.sshc.sftp_send_state) {
+    case 0:
+      sftp_file_set_nonblocking(conn->proto.sshc.sftp_file);
+      if(sftp_aio_begin_write(conn->proto.sshc.sftp_file, mem, len,
+                              &conn->proto.sshc.sftp_aio) == SSH_ERROR) {
+        *err = CURLE_SEND_ERROR;
+        return -1;
+      }
+      conn->proto.sshc.sftp_send_state = 1;
+      FALLTHROUGH();
+    case 1:
+      nwrite = sftp_aio_wait_write(&conn->proto.sshc.sftp_aio);
+      myssh_block2waitfor(conn, (nwrite == SSH_AGAIN) ? TRUE : FALSE);
+      if(nwrite == SSH_AGAIN) {
+        *err = CURLE_AGAIN;
+        return 0;
+      }
+      else if(nwrite < 0) {
+        *err = CURLE_SEND_ERROR;
+        return -1;
+      }
+      if(conn->proto.sshc.sftp_aio) {
+        sftp_aio_free(conn->proto.sshc.sftp_aio);
+        conn->proto.sshc.sftp_aio = NULL;
+      }
+      conn->proto.sshc.sftp_send_state = 0;
+      return nwrite;
+    default:
+      /* we never reach here */
+      return -1;
+  }
+#else
   nwrite = sftp_write(conn->proto.sshc.sftp_file, mem, len);
 
   myssh_block2waitfor(conn, FALSE);
@@ -2588,6 +2629,7 @@ static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
   }
 
   return nwrite;
+#endif
 }
 
 /*
index f2d42a3de2aed89f0ec0aa5c5c863196c3452cb9..8d8a9b380787027adcab9bb53a3a77e2188045f9 100644 (file)
@@ -177,6 +177,10 @@ struct ssh_conn {
   sftp_dir sftp_dir;
 
   unsigned sftp_recv_state; /* 0 or 1 */
+#if LIBSSH_VERSION_INT > SSH_VERSION_INT(0, 11, 0)
+  sftp_aio sftp_aio;
+  unsigned sftp_send_state; /* 0 or 1 */
+#endif
   int sftp_file_index; /* for async read */
   sftp_attributes readdir_attrs; /* used by the SFTP readdir actions */
   sftp_attributes readdir_link_attrs; /* used by the SFTP readdir actions */