]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
ssh: dedupe state change function
authorViktor Szakats <commit@vsz.me>
Thu, 29 Jan 2026 15:07:26 +0000 (16:07 +0100)
committerViktor Szakats <commit@vsz.me>
Fri, 30 Jan 2026 12:27:03 +0000 (13:27 +0100)
Closes #20473

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

index 3d75cffcba2d82b3db24ef591ec75eade05c0d20..0a86d121519695159a2f9f1f133c557026111839 100644 (file)
@@ -108,101 +108,6 @@ static CURLcode sftp_error_to_CURLE(int err)
   return CURLE_SSH;
 }
 
-#ifdef CURLVERBOSE
-static const char *myssh_statename(sshstate state)
-{
-  static const char * const names[] = {
-    "SSH_STOP",
-    "SSH_INIT",
-    "SSH_S_STARTUP",
-    "SSH_HOSTKEY",
-    "SSH_AUTHLIST",
-    "SSH_AUTH_PKEY_INIT",
-    "SSH_AUTH_PKEY",
-    "SSH_AUTH_PASS_INIT",
-    "SSH_AUTH_PASS",
-    "SSH_AUTH_AGENT_INIT",
-    "SSH_AUTH_AGENT_LIST",
-    "SSH_AUTH_AGENT",
-    "SSH_AUTH_HOST_INIT",
-    "SSH_AUTH_HOST",
-    "SSH_AUTH_KEY_INIT",
-    "SSH_AUTH_KEY",
-    "SSH_AUTH_GSSAPI",
-    "SSH_AUTH_DONE",
-    "SSH_SFTP_INIT",
-    "SSH_SFTP_REALPATH",
-    "SSH_SFTP_QUOTE_INIT",
-    "SSH_SFTP_POSTQUOTE_INIT",
-    "SSH_SFTP_QUOTE",
-    "SSH_SFTP_NEXT_QUOTE",
-    "SSH_SFTP_QUOTE_STAT",
-    "SSH_SFTP_QUOTE_SETSTAT",
-    "SSH_SFTP_QUOTE_SYMLINK",
-    "SSH_SFTP_QUOTE_MKDIR",
-    "SSH_SFTP_QUOTE_RENAME",
-    "SSH_SFTP_QUOTE_RMDIR",
-    "SSH_SFTP_QUOTE_UNLINK",
-    "SSH_SFTP_QUOTE_STATVFS",
-    "SSH_SFTP_GETINFO",
-    "SSH_SFTP_FILETIME",
-    "SSH_SFTP_TRANS_INIT",
-    "SSH_SFTP_UPLOAD_INIT",
-    "SSH_SFTP_CREATE_DIRS_INIT",
-    "SSH_SFTP_CREATE_DIRS",
-    "SSH_SFTP_CREATE_DIRS_MKDIR",
-    "SSH_SFTP_READDIR_INIT",
-    "SSH_SFTP_READDIR",
-    "SSH_SFTP_READDIR_LINK",
-    "SSH_SFTP_READDIR_BOTTOM",
-    "SSH_SFTP_READDIR_DONE",
-    "SSH_SFTP_DOWNLOAD_INIT",
-    "SSH_SFTP_DOWNLOAD_STAT",
-    "SSH_SFTP_CLOSE",
-    "SSH_SFTP_SHUTDOWN",
-    "SSH_SCP_TRANS_INIT",
-    "SSH_SCP_UPLOAD_INIT",
-    "SSH_SCP_DOWNLOAD_INIT",
-    "SSH_SCP_DOWNLOAD",
-    "SSH_SCP_DONE",
-    "SSH_SCP_SEND_EOF",
-    "SSH_SCP_WAIT_EOF",
-    "SSH_SCP_WAIT_CLOSE",
-    "SSH_SCP_CHANNEL_FREE",
-    "SSH_SESSION_DISCONNECT",
-    "SSH_SESSION_FREE",
-    "QUIT"
-  };
-  /* a precaution to make sure the lists are in sync */
-  DEBUGASSERT(CURL_ARRAYSIZE(names) == SSH_LAST);
-  return ((size_t)state < CURL_ARRAYSIZE(names)) ? names[state] : "";
-}
-#else
-#define myssh_statename(x)    ""
-#endif /* CURLVERBOSE */
-
-#define myssh_to(x, y, z) myssh_set_state(x, y, z)
-
-/*
- * SSH State machine related code
- */
-/* This is the ONLY way to change SSH state! */
-static void myssh_set_state(struct Curl_easy *data,
-                            struct ssh_conn *sshc,
-                            sshstate nowstate)
-{
-#ifdef CURLVERBOSE
-  if(sshc->state != nowstate) {
-    CURL_TRC_SSH(data, "[%s] -> [%s]",
-                 myssh_statename(sshc->state),
-                 myssh_statename(nowstate));
-  }
-#else
-  (void)data;
-#endif
-  sshc->state = nowstate;
-}
-
 /* Multiple options:
  * 1. data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5] is set with an MD5
  *    hash (90s style auth, not sure we should have it here)
@@ -2345,7 +2250,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
   if(!result && (sshc->state == SSH_STOP))
     result = sshc->actualcode;
   CURL_TRC_SSH(data, "[%s] statemachine() -> %d, block=%d",
-               myssh_statename(sshc->state), result, *block);
+               Curl_ssh_statename(sshc->state), result, *block);
   return result;
 }
 
index 5b3dfa8a562588735c8c87b10f11e13d35c1ff46..cf04adcca22d903ada77187b7e39e716b76e8787 100644 (file)
@@ -251,101 +251,6 @@ static LIBSSH2_FREE_FUNC(my_libssh2_free)
     Curl_cfree(ptr);
 }
 
-#ifdef CURLVERBOSE
-static const char *myssh_statename(sshstate state)
-{
-  static const char * const names[] = {
-    "SSH_STOP",
-    "SSH_INIT",
-    "SSH_S_STARTUP",
-    "SSH_HOSTKEY",
-    "SSH_AUTHLIST",
-    "SSH_AUTH_PKEY_INIT",
-    "SSH_AUTH_PKEY",
-    "SSH_AUTH_PASS_INIT",
-    "SSH_AUTH_PASS",
-    "SSH_AUTH_AGENT_INIT",
-    "SSH_AUTH_AGENT_LIST",
-    "SSH_AUTH_AGENT",
-    "SSH_AUTH_HOST_INIT",
-    "SSH_AUTH_HOST",
-    "SSH_AUTH_KEY_INIT",
-    "SSH_AUTH_KEY",
-    "SSH_AUTH_GSSAPI",
-    "SSH_AUTH_DONE",
-    "SSH_SFTP_INIT",
-    "SSH_SFTP_REALPATH",
-    "SSH_SFTP_QUOTE_INIT",
-    "SSH_SFTP_POSTQUOTE_INIT",
-    "SSH_SFTP_QUOTE",
-    "SSH_SFTP_NEXT_QUOTE",
-    "SSH_SFTP_QUOTE_STAT",
-    "SSH_SFTP_QUOTE_SETSTAT",
-    "SSH_SFTP_QUOTE_SYMLINK",
-    "SSH_SFTP_QUOTE_MKDIR",
-    "SSH_SFTP_QUOTE_RENAME",
-    "SSH_SFTP_QUOTE_RMDIR",
-    "SSH_SFTP_QUOTE_UNLINK",
-    "SSH_SFTP_QUOTE_STATVFS",
-    "SSH_SFTP_GETINFO",
-    "SSH_SFTP_FILETIME",
-    "SSH_SFTP_TRANS_INIT",
-    "SSH_SFTP_UPLOAD_INIT",
-    "SSH_SFTP_CREATE_DIRS_INIT",
-    "SSH_SFTP_CREATE_DIRS",
-    "SSH_SFTP_CREATE_DIRS_MKDIR",
-    "SSH_SFTP_READDIR_INIT",
-    "SSH_SFTP_READDIR",
-    "SSH_SFTP_READDIR_LINK",
-    "SSH_SFTP_READDIR_BOTTOM",
-    "SSH_SFTP_READDIR_DONE",
-    "SSH_SFTP_DOWNLOAD_INIT",
-    "SSH_SFTP_DOWNLOAD_STAT",
-    "SSH_SFTP_CLOSE",
-    "SSH_SFTP_SHUTDOWN",
-    "SSH_SCP_TRANS_INIT",
-    "SSH_SCP_UPLOAD_INIT",
-    "SSH_SCP_DOWNLOAD_INIT",
-    "SSH_SCP_DOWNLOAD",
-    "SSH_SCP_DONE",
-    "SSH_SCP_SEND_EOF",
-    "SSH_SCP_WAIT_EOF",
-    "SSH_SCP_WAIT_CLOSE",
-    "SSH_SCP_CHANNEL_FREE",
-    "SSH_SESSION_DISCONNECT",
-    "SSH_SESSION_FREE",
-    "QUIT"
-  };
-  /* a precaution to make sure the lists are in sync */
-  DEBUGASSERT(CURL_ARRAYSIZE(names) == SSH_LAST);
-  return ((size_t)state < CURL_ARRAYSIZE(names)) ? names[state] : "";
-}
-#else
-#define myssh_statename(x)    ""
-#endif /* CURLVERBOSE */
-
-#define myssh_state(x, y, z) myssh_set_state(x, y, z)
-
-/*
- * SSH State machine related code
- */
-/* This is the ONLY way to change SSH state! */
-static void myssh_set_state(struct Curl_easy *data,
-                            struct ssh_conn *sshc,
-                            sshstate nowstate)
-{
-#ifdef CURLVERBOSE
-  if(sshc->state != nowstate) {
-    CURL_TRC_SSH(data, "[%s] -> [%s]",
-                 myssh_statename(sshc->state),
-                 myssh_statename(nowstate));
-  }
-#else
-  (void)data;
-#endif
-  sshc->state = nowstate;
-}
-
 static int sshkeycallback(CURL *easy,
                           const struct curl_khkey *knownkey, /* known */
                           const struct curl_khkey *foundkey, /* found */
@@ -502,7 +407,7 @@ static CURLcode ssh_knownhost(struct Curl_easy *data,
     switch(rc) {
     default: /* unknown return codes will equal reject */
     case CURLKHSTAT_REJECT:
-      myssh_state(data, sshc, SSH_SESSION_FREE);
+      myssh_to(data, sshc, SSH_SESSION_FREE);
       FALLTHROUGH();
     case CURLKHSTAT_DEFER:
       /* DEFER means bail out but keep the SSH_HOSTKEY state */
@@ -573,7 +478,7 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data,
       failf(data,
             "Denied establishing ssh session: sha256 fingerprint "
             "not available");
-      myssh_state(data, sshc, SSH_SESSION_FREE);
+      myssh_to(data, sshc, SSH_SESSION_FREE);
       return CURLE_PEER_FAILED_VERIFICATION;
     }
 
@@ -581,13 +486,13 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data,
      * See libssh2_hostkey_hash documentation. */
     if(curlx_base64_encode((const uint8_t *)fingerprint, 32, &fingerprint_b64,
                            &fingerprint_b64_len) != CURLE_OK) {
-      myssh_state(data, sshc, SSH_SESSION_FREE);
+      myssh_to(data, sshc, SSH_SESSION_FREE);
       return CURLE_PEER_FAILED_VERIFICATION;
     }
 
     if(!fingerprint_b64) {
       failf(data, "sha256 fingerprint could not be encoded");
-      myssh_state(data, sshc, SSH_SESSION_FREE);
+      myssh_to(data, sshc, SSH_SESSION_FREE);
       return CURLE_PEER_FAILED_VERIFICATION;
     }
 
@@ -613,7 +518,7 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data,
             "Denied establishing ssh session: mismatch sha256 fingerprint. "
             "Remote %s is not equal to %s", fingerprint_b64, pubkey_sha256);
       curlx_free(fingerprint_b64);
-      myssh_state(data, sshc, SSH_SESSION_FREE);
+      myssh_to(data, sshc, SSH_SESSION_FREE);
       return CURLE_PEER_FAILED_VERIFICATION;
     }
 
@@ -653,7 +558,7 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data,
               "Denied establishing ssh session: md5 fingerprint "
               "not available");
       }
-      myssh_state(data, sshc, SSH_SESSION_FREE);
+      myssh_to(data, sshc, SSH_SESSION_FREE);
       return CURLE_PEER_FAILED_VERIFICATION;
     }
     infof(data, "MD5 checksum match");
@@ -674,12 +579,12 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data,
                                        (int)keytype, remotekey, keylen);
         Curl_set_in_callback(data, FALSE);
         if(rc != CURLKHMATCH_OK) {
-          myssh_state(data, sshc, SSH_SESSION_FREE);
+          myssh_to(data, sshc, SSH_SESSION_FREE);
           return CURLE_PEER_FAILED_VERIFICATION;
         }
       }
       else {
-        myssh_state(data, sshc, SSH_SESSION_FREE);
+        myssh_to(data, sshc, SSH_SESSION_FREE);
         return CURLE_PEER_FAILED_VERIFICATION;
       }
       return CURLE_OK;
@@ -860,7 +765,7 @@ static CURLcode sftp_quote(struct Curl_easy *data,
     result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
     curlx_free(tmp);
     if(!result)
-      myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE);
+      myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
     return result;
   }
 
@@ -910,7 +815,7 @@ static CURLcode sftp_quote(struct Curl_easy *data,
       return_quote_error(data, sshc);
 
     memset(&sshp->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
-    myssh_state(data, sshc, SSH_SFTP_QUOTE_STAT);
+    myssh_to(data, sshc, SSH_SFTP_QUOTE_STAT);
     return result;
   }
   if(!strncmp(cmd, "ln ", 3) ||
@@ -927,14 +832,14 @@ static CURLcode sftp_quote(struct Curl_easy *data,
     }
     if(*cp)
       return_quote_error(data, sshc);
-    myssh_state(data, sshc, SSH_SFTP_QUOTE_SYMLINK);
+    myssh_to(data, sshc, SSH_SFTP_QUOTE_SYMLINK);
     return result;
   }
   else if(!strncmp(cmd, "mkdir ", 6)) {
     if(*cp)
       return_quote_error(data, sshc);
     /* create directory */
-    myssh_state(data, sshc, SSH_SFTP_QUOTE_MKDIR);
+    myssh_to(data, sshc, SSH_SFTP_QUOTE_MKDIR);
     return result;
   }
   else if(!strncmp(cmd, "rename ", 7)) {
@@ -950,26 +855,26 @@ static CURLcode sftp_quote(struct Curl_easy *data,
     }
     if(*cp)
       return_quote_error(data, sshc);
-    myssh_state(data, sshc, SSH_SFTP_QUOTE_RENAME);
+    myssh_to(data, sshc, SSH_SFTP_QUOTE_RENAME);
     return result;
   }
   else if(!strncmp(cmd, "rmdir ", 6)) {
     if(*cp)
       return_quote_error(data, sshc);
     /* delete directory */
-    myssh_state(data, sshc, SSH_SFTP_QUOTE_RMDIR);
+    myssh_to(data, sshc, SSH_SFTP_QUOTE_RMDIR);
     return result;
   }
   else if(!strncmp(cmd, "rm ", 3)) {
     if(*cp)
       return_quote_error(data, sshc);
-    myssh_state(data, sshc, SSH_SFTP_QUOTE_UNLINK);
+    myssh_to(data, sshc, SSH_SFTP_QUOTE_UNLINK);
     return result;
   }
   else if(!strncmp(cmd, "statvfs ", 8)) {
     if(*cp)
       return_quote_error(data, sshc);
-    myssh_state(data, sshc, SSH_SFTP_QUOTE_STATVFS);
+    myssh_to(data, sshc, SSH_SFTP_QUOTE_STATVFS);
     return result;
   }
 
@@ -1057,7 +962,7 @@ static CURLcode sftp_upload_init(struct Curl_easy *data,
       sftperr = LIBSSH2_FX_OK; /* not an sftp error at all */
 
     if(sshc->secondCreateDirs) {
-      myssh_state(data, sshc, SSH_SFTP_CLOSE);
+      myssh_to(data, sshc, SSH_SFTP_CLOSE);
       failf(data, "Creating the dir/file failed: %s",
             sftp_libssh2_strerror(sftperr));
       return sftp_libssh2_error_to_CURLE(sftperr);
@@ -1069,10 +974,10 @@ static CURLcode sftp_upload_init(struct Curl_easy *data,
         (strlen(sshp->path) > 1))) {
       /* try to create the path remotely */
       sshc->secondCreateDirs = 1;
-      myssh_state(data, sshc, SSH_SFTP_CREATE_DIRS_INIT);
+      myssh_to(data, sshc, SSH_SFTP_CREATE_DIRS_INIT);
       return CURLE_OK;
     }
-    myssh_state(data, sshc, SSH_SFTP_CLOSE);
+    myssh_to(data, sshc, SSH_SFTP_CLOSE);
     result = sftp_libssh2_error_to_CURLE(sftperr);
     if(!result) {
       /* Sometimes, for some reason libssh2_sftp_last_error() returns zero
@@ -1156,7 +1061,7 @@ static CURLcode sftp_upload_init(struct Curl_easy *data,
      state machine to move on as soon as possible so mark this as dirty */
   Curl_multi_mark_dirty(data);
 
-  myssh_state(data, sshc, SSH_STOP);
+  myssh_to(data, sshc, SSH_STOP);
   return CURLE_OK;
 }
 
@@ -1235,7 +1140,7 @@ static CURLcode ssh_state_pkey_init(struct Curl_easy *data,
     if(out_of_memory || !sshc->rsa) {
       Curl_safefree(sshc->rsa);
       Curl_safefree(sshc->rsa_pub);
-      myssh_state(data, sshc, SSH_SESSION_FREE);
+      myssh_to(data, sshc, SSH_SESSION_FREE);
       return CURLE_OUT_OF_MEMORY;
     }
 
@@ -1247,10 +1152,10 @@ static CURLcode ssh_state_pkey_init(struct Curl_easy *data,
       infof(data, "Using SSH public key file '%s'", sshc->rsa_pub);
     infof(data, "Using SSH private key file '%s'", sshc->rsa);
 
-    myssh_state(data, sshc, SSH_AUTH_PKEY);
+    myssh_to(data, sshc, SSH_AUTH_PKEY);
   }
   else {
-    myssh_state(data, sshc, SSH_AUTH_PASS_INIT);
+    myssh_to(data, sshc, SSH_AUTH_PASS_INIT);
   }
   return 0;
 }
@@ -1358,7 +1263,7 @@ static CURLcode sftp_quote_stat(struct Curl_easy *data,
   }
 
   /* Now send the completed structure... */
-  myssh_state(data, sshc, SSH_SFTP_QUOTE_SETSTAT);
+  myssh_to(data, sshc, SSH_SFTP_QUOTE_SETSTAT);
   return CURLE_OK;
 fail:
   Curl_safefree(sshc->quote_path1);
@@ -1448,7 +1353,7 @@ static CURLcode sftp_download_stat(struct Curl_easy *data,
     /* no data to transfer */
     Curl_xfer_setup_nop(data);
     infof(data, "File already completely downloaded");
-    myssh_state(data, sshc, SSH_STOP);
+    myssh_to(data, sshc, SSH_STOP);
     return CURLE_OK;
   }
   Curl_xfer_setup_recv(data, FIRSTSOCKET, data->req.size);
@@ -1456,7 +1361,7 @@ static CURLcode sftp_download_stat(struct Curl_easy *data,
   /* not set by Curl_xfer_setup to preserve keepon bits */
   data->conn->send_idx = 0;
 
-  myssh_state(data, sshc, SSH_STOP);
+  myssh_to(data, sshc, SSH_STOP);
 
   return CURLE_OK;
 }
@@ -1497,17 +1402,17 @@ static CURLcode sftp_readdir(struct Curl_easy *data,
             LIBSSH2_SFTP_S_IFLNK)) {
           result = curlx_dyn_addf(&sshp->readdir_link, "%s%s", sshp->path,
                                   sshp->readdir_filename);
-          myssh_state(data, sshc, SSH_SFTP_READDIR_LINK);
+          myssh_to(data, sshc, SSH_SFTP_READDIR_LINK);
         }
         else {
-          myssh_state(data, sshc, SSH_SFTP_READDIR_BOTTOM);
+          myssh_to(data, sshc, SSH_SFTP_READDIR_BOTTOM);
         }
       }
       return result;
     }
   }
   else if(!rc) {
-    myssh_state(data, sshc, SSH_SFTP_READDIR_DONE);
+    myssh_to(data, sshc, SSH_SFTP_READDIR_DONE);
   }
   else {
     unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
@@ -1515,7 +1420,7 @@ static CURLcode sftp_readdir(struct Curl_easy *data,
     failf(data, "Could not open remote file for reading: %s :: %d",
           sftp_libssh2_strerror(sftperr),
           libssh2_session_last_errno(sshc->ssh_session));
-    myssh_state(data, sshc, SSH_SFTP_CLOSE);
+    myssh_to(data, sshc, SSH_SFTP_CLOSE);
   }
   return result;
 }
@@ -1533,9 +1438,9 @@ static CURLcode ssh_state_init(struct Curl_easy *data,
 
   result = ssh_force_knownhost_key_type(data, sshc);
   if(result)
-    myssh_state(data, sshc, SSH_SESSION_FREE);
+    myssh_to(data, sshc, SSH_SESSION_FREE);
   else
-    myssh_state(data, sshc, SSH_S_STARTUP);
+    myssh_to(data, sshc, SSH_S_STARTUP);
   return result;
 }
 
@@ -1553,11 +1458,11 @@ static CURLcode ssh_state_startup(struct Curl_easy *data,
     (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
     failf(data, "Failure establishing ssh session: %d, %s", rc, err_msg);
 
-    myssh_state(data, sshc, SSH_SESSION_FREE);
+    myssh_to(data, sshc, SSH_SESSION_FREE);
     return CURLE_FAILED_INIT;
   }
 
-  myssh_state(data, sshc, SSH_HOSTKEY);
+  myssh_to(data, sshc, SSH_HOSTKEY);
   return CURLE_OK;
 }
 
@@ -1571,7 +1476,7 @@ static CURLcode ssh_state_hostkey(struct Curl_easy *data,
    */
   CURLcode result = ssh_check_fingerprint(data, sshc);
   if(!result)
-    myssh_state(data, sshc, SSH_AUTHLIST);
+    myssh_to(data, sshc, SSH_AUTHLIST);
   return result;
 }
 
@@ -1598,19 +1503,19 @@ static CURLcode ssh_state_authlist(struct Curl_easy *data,
     if(libssh2_userauth_authenticated(sshc->ssh_session)) {
       sshc->authed = TRUE;
       infof(data, "SSH user accepted with no authentication");
-      myssh_state(data, sshc, SSH_AUTH_DONE);
+      myssh_to(data, sshc, SSH_AUTH_DONE);
       return CURLE_OK;
     }
     rc = libssh2_session_last_errno(sshc->ssh_session);
     if(rc == LIBSSH2_ERROR_EAGAIN)
       return CURLE_AGAIN;
 
-    myssh_state(data, sshc, SSH_SESSION_FREE);
+    myssh_to(data, sshc, SSH_SESSION_FREE);
     return libssh2_session_error_to_CURLE(rc);
   }
   infof(data, "SSH authentication methods available: %s", sshc->authlist);
 
-  myssh_state(data, sshc, SSH_AUTH_PKEY_INIT);
+  myssh_to(data, sshc, SSH_AUTH_PKEY_INIT);
   return CURLE_OK;
 }
 
@@ -1636,7 +1541,7 @@ static CURLcode ssh_state_auth_pkey(struct Curl_easy *data,
   if(rc == 0) {
     sshc->authed = TRUE;
     infof(data, "Initialized SSH public key authentication");
-    myssh_state(data, sshc, SSH_AUTH_DONE);
+    myssh_to(data, sshc, SSH_AUTH_DONE);
   }
   else {
     char *err_msg = NULL;
@@ -1650,7 +1555,7 @@ static CURLcode ssh_state_auth_pkey(struct Curl_easy *data,
       (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
     }
     infof(data, "SSH public key authentication failed: %s", err_msg);
-    myssh_state(data, sshc, SSH_AUTH_PASS_INIT);
+    myssh_to(data, sshc, SSH_AUTH_PASS_INIT);
   }
   return CURLE_OK;
 }
@@ -1660,10 +1565,10 @@ static CURLcode ssh_state_auth_pass_init(struct Curl_easy *data,
 {
   if((data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) &&
      (strstr(sshc->authlist, "password") != NULL)) {
-    myssh_state(data, sshc, SSH_AUTH_PASS);
+    myssh_to(data, sshc, SSH_AUTH_PASS);
   }
   else {
-    myssh_state(data, sshc, SSH_AUTH_HOST_INIT);
+    myssh_to(data, sshc, SSH_AUTH_HOST_INIT);
   }
   return CURLE_OK;
 }
@@ -1684,10 +1589,10 @@ static CURLcode ssh_state_auth_pass(struct Curl_easy *data,
   if(rc == 0) {
     sshc->authed = TRUE;
     infof(data, "Initialized password authentication");
-    myssh_state(data, sshc, SSH_AUTH_DONE);
+    myssh_to(data, sshc, SSH_AUTH_DONE);
   }
   else {
-    myssh_state(data, sshc, SSH_AUTH_HOST_INIT);
+    myssh_to(data, sshc, SSH_AUTH_HOST_INIT);
   }
   return CURLE_OK;
 }
@@ -1697,10 +1602,10 @@ static CURLcode ssh_state_auth_host_init(struct Curl_easy *data,
 {
   if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) &&
      (strstr(sshc->authlist, "hostbased") != NULL)) {
-    myssh_state(data, sshc, SSH_AUTH_HOST);
+    myssh_to(data, sshc, SSH_AUTH_HOST);
   }
   else {
-    myssh_state(data, sshc, SSH_AUTH_AGENT_INIT);
+    myssh_to(data, sshc, SSH_AUTH_AGENT_INIT);
   }
   return CURLE_OK;
 }
@@ -1720,7 +1625,7 @@ static CURLcode ssh_state_auth_agent_init(struct Curl_easy *data,
       if(!sshc->ssh_agent) {
         infof(data, "Could not create agent object");
 
-        myssh_state(data, sshc, SSH_AUTH_KEY_INIT);
+        myssh_to(data, sshc, SSH_AUTH_KEY_INIT);
         return CURLE_OK;
       }
     }
@@ -1730,14 +1635,14 @@ static CURLcode ssh_state_auth_agent_init(struct Curl_easy *data,
       return CURLE_AGAIN;
     if(rc < 0) {
       infof(data, "Failure connecting to agent");
-      myssh_state(data, sshc, SSH_AUTH_KEY_INIT);
+      myssh_to(data, sshc, SSH_AUTH_KEY_INIT);
     }
     else {
-      myssh_state(data, sshc, SSH_AUTH_AGENT_LIST);
+      myssh_to(data, sshc, SSH_AUTH_AGENT_LIST);
     }
   }
   else
-    myssh_state(data, sshc, SSH_AUTH_KEY_INIT);
+    myssh_to(data, sshc, SSH_AUTH_KEY_INIT);
   return CURLE_OK;
 }
 
@@ -1750,10 +1655,10 @@ static CURLcode ssh_state_auth_agent_list(struct Curl_easy *data,
     return CURLE_AGAIN;
   if(rc < 0) {
     infof(data, "Failure requesting identities to agent");
-    myssh_state(data, sshc, SSH_AUTH_KEY_INIT);
+    myssh_to(data, sshc, SSH_AUTH_KEY_INIT);
   }
   else {
-    myssh_state(data, sshc, SSH_AUTH_AGENT);
+    myssh_to(data, sshc, SSH_AUTH_AGENT);
     sshc->sshagent_prev_identity = NULL;
   }
   return CURLE_OK;
@@ -1794,10 +1699,10 @@ static CURLcode ssh_state_auth_agent(struct Curl_easy *data,
   if(rc == LIBSSH2_ERROR_NONE) {
     sshc->authed = TRUE;
     infof(data, "Agent based authentication successful");
-    myssh_state(data, sshc, SSH_AUTH_DONE);
+    myssh_to(data, sshc, SSH_AUTH_DONE);
   }
   else {
-    myssh_state(data, sshc, SSH_AUTH_KEY_INIT);
+    myssh_to(data, sshc, SSH_AUTH_KEY_INIT);
   }
   return CURLE_OK;
 }
@@ -1807,10 +1712,10 @@ static CURLcode ssh_state_auth_key_init(struct Curl_easy *data,
 {
   if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD) &&
      (strstr(sshc->authlist, "keyboard-interactive") != NULL)) {
-    myssh_state(data, sshc, SSH_AUTH_KEY);
+    myssh_to(data, sshc, SSH_AUTH_KEY);
   }
   else {
-    myssh_state(data, sshc, SSH_AUTH_DONE);
+    myssh_to(data, sshc, SSH_AUTH_DONE);
   }
   return CURLE_OK;
 }
@@ -1832,7 +1737,7 @@ static CURLcode ssh_state_auth_key(struct Curl_easy *data,
   if(rc == 0) {
     sshc->authed = TRUE;
     infof(data, "Initialized keyboard interactive authentication");
-    myssh_state(data, sshc, SSH_AUTH_DONE);
+    myssh_to(data, sshc, SSH_AUTH_DONE);
     return CURLE_OK;
   }
   return CURLE_LOGIN_DENIED;
@@ -1844,7 +1749,7 @@ static CURLcode ssh_state_auth_done(struct Curl_easy *data,
   struct connectdata *conn = data->conn;
   if(!sshc->authed) {
     failf(data, "Authentication failure");
-    myssh_state(data, sshc, SSH_SESSION_FREE);
+    myssh_to(data, sshc, SSH_SESSION_FREE);
     return CURLE_LOGIN_DENIED;
   }
 
@@ -1859,11 +1764,11 @@ static CURLcode ssh_state_auth_done(struct Curl_easy *data,
   conn->send_idx = -1;
 
   if(conn->scheme->protocol == CURLPROTO_SFTP) {
-    myssh_state(data, sshc, SSH_SFTP_INIT);
+    myssh_to(data, sshc, SSH_SFTP_INIT);
     return CURLE_OK;
   }
   infof(data, "SSH CONNECT phase done");
-  myssh_state(data, sshc, SSH_STOP);
+  myssh_to(data, sshc, SSH_STOP);
   return CURLE_OK;
 }
 
@@ -1882,10 +1787,10 @@ static CURLcode ssh_state_sftp_init(struct Curl_easy *data,
 
     (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
     failf(data, "Failure initializing sftp session: %s", err_msg);
-    myssh_state(data, sshc, SSH_SESSION_FREE);
+    myssh_to(data, sshc, SSH_SESSION_FREE);
     return CURLE_FAILED_INIT;
   }
-  myssh_state(data, sshc, SSH_SFTP_REALPATH);
+  myssh_to(data, sshc, SSH_SFTP_REALPATH);
   return CURLE_OK;
 }
 
@@ -1903,7 +1808,7 @@ static CURLcode ssh_state_sftp_realpath(struct Curl_easy *data,
   if(rc == LIBSSH2_ERROR_EAGAIN)
     return CURLE_AGAIN;
 
-  myssh_state(data, sshc, SSH_STOP);
+  myssh_to(data, sshc, SSH_STOP);
   if(rc > 0) {
     curlx_free(sshc->homedir);
     sshc->homedir = curlx_strdup(sshp->readdir_filename);
@@ -1942,17 +1847,17 @@ static CURLcode ssh_state_sftp_quote_init(struct Curl_easy *data,
 {
   CURLcode result = Curl_getworkingpath(data, sshc->homedir, &sshp->path);
   if(result) {
-    myssh_state(data, sshc, SSH_STOP);
+    myssh_to(data, sshc, SSH_STOP);
     return result;
   }
 
   if(data->set.quote) {
     infof(data, "Sending quote commands");
     sshc->quote_item = data->set.quote;
-    myssh_state(data, sshc, SSH_SFTP_QUOTE);
+    myssh_to(data, sshc, SSH_SFTP_QUOTE);
   }
   else {
-    myssh_state(data, sshc, SSH_SFTP_GETINFO);
+    myssh_to(data, sshc, SSH_SFTP_GETINFO);
   }
   return CURLE_OK;
 }
@@ -1963,10 +1868,10 @@ static CURLcode ssh_state_sftp_postquote_init(struct Curl_easy *data,
   if(data->set.postquote) {
     infof(data, "Sending quote commands");
     sshc->quote_item = data->set.postquote;
-    myssh_state(data, sshc, SSH_SFTP_QUOTE);
+    myssh_to(data, sshc, SSH_SFTP_QUOTE);
   }
   else {
-    myssh_state(data, sshc, SSH_STOP);
+    myssh_to(data, sshc, SSH_STOP);
   }
   return CURLE_OK;
 }
@@ -1978,7 +1883,7 @@ static CURLcode ssh_state_sftp_quote(struct Curl_easy *data,
   /* Send quote commands */
   CURLcode result = sftp_quote(data, sshc, sshp);
   if(result) {
-    myssh_state(data, sshc, SSH_SFTP_CLOSE);
+    myssh_to(data, sshc, SSH_SFTP_CLOSE);
     sshc->nextstate = SSH_NO_STATE;
   }
   return result;
@@ -1993,15 +1898,15 @@ static CURLcode ssh_state_sftp_next_quote(struct Curl_easy *data,
   sshc->quote_item = sshc->quote_item->next;
 
   if(sshc->quote_item) {
-    myssh_state(data, sshc, SSH_SFTP_QUOTE);
+    myssh_to(data, sshc, SSH_SFTP_QUOTE);
   }
   else {
     if(sshc->nextstate != SSH_NO_STATE) {
-      myssh_state(data, sshc, sshc->nextstate);
+      myssh_to(data, sshc, sshc->nextstate);
       sshc->nextstate = SSH_NO_STATE;
     }
     else {
-      myssh_state(data, sshc, SSH_SFTP_GETINFO);
+      myssh_to(data, sshc, SSH_SFTP_GETINFO);
     }
   }
   return CURLE_OK;
@@ -2014,7 +1919,7 @@ static CURLcode ssh_state_sftp_quote_stat(struct Curl_easy *data,
 {
   CURLcode result = sftp_quote_stat(data, sshc, sshp, blockp);
   if(result) {
-    myssh_state(data, sshc, SSH_SFTP_CLOSE);
+    myssh_to(data, sshc, SSH_SFTP_CLOSE);
     sshc->nextstate = SSH_NO_STATE;
   }
   return result;
@@ -2038,11 +1943,11 @@ static CURLcode ssh_state_sftp_quote_setstat(struct Curl_easy *data,
           sshc->quote_path2, sftp_libssh2_strerror(sftperr));
     Curl_safefree(sshc->quote_path1);
     Curl_safefree(sshc->quote_path2);
-    myssh_state(data, sshc, SSH_SFTP_CLOSE);
+    myssh_to(data, sshc, SSH_SFTP_CLOSE);
     sshc->nextstate = SSH_NO_STATE;
     return CURLE_QUOTE_ERROR;
   }
-  myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE);
+  myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
   return CURLE_OK;
 }
 
@@ -2065,11 +1970,11 @@ static CURLcode ssh_state_sftp_quote_symlink(struct Curl_easy *data,
           sftp_libssh2_strerror(sftperr));
     Curl_safefree(sshc->quote_path1);
     Curl_safefree(sshc->quote_path2);
-    myssh_state(data, sshc, SSH_SFTP_CLOSE);
+    myssh_to(data, sshc, SSH_SFTP_CLOSE);
     sshc->nextstate = SSH_NO_STATE;
     return CURLE_QUOTE_ERROR;
   }
-  myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE);
+  myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
   return CURLE_OK;
 }
 
@@ -2087,11 +1992,11 @@ static CURLcode ssh_state_sftp_quote_mkdir(struct Curl_easy *data,
     failf(data, "mkdir \"%s\" failed: %s",
           sshc->quote_path1, sftp_libssh2_strerror(sftperr));
     Curl_safefree(sshc->quote_path1);
-    myssh_state(data, sshc, SSH_SFTP_CLOSE);
+    myssh_to(data, sshc, SSH_SFTP_CLOSE);
     sshc->nextstate = SSH_NO_STATE;
     return CURLE_QUOTE_ERROR;
   }
-  myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE);
+  myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
   return CURLE_OK;
 }
 
@@ -2117,11 +2022,11 @@ static CURLcode ssh_state_sftp_quote_rename(struct Curl_easy *data,
           sftp_libssh2_strerror(sftperr));
     Curl_safefree(sshc->quote_path1);
     Curl_safefree(sshc->quote_path2);
-    myssh_state(data, sshc, SSH_SFTP_CLOSE);
+    myssh_to(data, sshc, SSH_SFTP_CLOSE);
     sshc->nextstate = SSH_NO_STATE;
     return CURLE_QUOTE_ERROR;
   }
-  myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE);
+  myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
   return CURLE_OK;
 }
 
@@ -2138,11 +2043,11 @@ static CURLcode ssh_state_sftp_quote_rmdir(struct Curl_easy *data,
     failf(data, "rmdir \"%s\" failed: %s",
           sshc->quote_path1, sftp_libssh2_strerror(sftperr));
     Curl_safefree(sshc->quote_path1);
-    myssh_state(data, sshc, SSH_SFTP_CLOSE);
+    myssh_to(data, sshc, SSH_SFTP_CLOSE);
     sshc->nextstate = SSH_NO_STATE;
     return CURLE_QUOTE_ERROR;
   }
-  myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE);
+  myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
   return CURLE_OK;
 }
 
@@ -2159,11 +2064,11 @@ static CURLcode ssh_state_sftp_quote_unlink(struct Curl_easy *data,
     failf(data, "rm \"%s\" failed: %s",
           sshc->quote_path1, sftp_libssh2_strerror(sftperr));
     Curl_safefree(sshc->quote_path1);
-    myssh_state(data, sshc, SSH_SFTP_CLOSE);
+    myssh_to(data, sshc, SSH_SFTP_CLOSE);
     sshc->nextstate = SSH_NO_STATE;
     return CURLE_QUOTE_ERROR;
   }
-  myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE);
+  myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
   return CURLE_OK;
 }
 
@@ -2183,7 +2088,7 @@ static CURLcode ssh_state_sftp_quote_statvfs(struct Curl_easy *data,
     failf(data, "statvfs \"%s\" failed: %s",
           sshc->quote_path1, sftp_libssh2_strerror(sftperr));
     Curl_safefree(sshc->quote_path1);
-    myssh_state(data, sshc, SSH_SFTP_CLOSE);
+    myssh_to(data, sshc, SSH_SFTP_CLOSE);
     sshc->nextstate = SSH_NO_STATE;
     return CURLE_QUOTE_ERROR;
   }
@@ -2213,7 +2118,7 @@ static CURLcode ssh_state_sftp_quote_statvfs(struct Curl_easy *data,
                               statvfs.f_fsid, statvfs.f_flag,
                               statvfs.f_namemax);
     if(!tmp) {
-      myssh_state(data, sshc, SSH_SFTP_CLOSE);
+      myssh_to(data, sshc, SSH_SFTP_CLOSE);
       sshc->nextstate = SSH_NO_STATE;
       return CURLE_OUT_OF_MEMORY;
     }
@@ -2221,12 +2126,12 @@ static CURLcode ssh_state_sftp_quote_statvfs(struct Curl_easy *data,
     result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
     curlx_free(tmp);
     if(result) {
-      myssh_state(data, sshc, SSH_SFTP_CLOSE);
+      myssh_to(data, sshc, SSH_SFTP_CLOSE);
       sshc->nextstate = SSH_NO_STATE;
       return result;
     }
   }
-  myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE);
+  myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
   return CURLE_OK;
 }
 
@@ -2253,11 +2158,11 @@ static CURLcode ssh_state_sftp_create_dirs_mkdir(struct Curl_easy *data,
     if((sftperr != LIBSSH2_FX_FILE_ALREADY_EXISTS) &&
        (sftperr != LIBSSH2_FX_FAILURE) &&
        (sftperr != LIBSSH2_FX_PERMISSION_DENIED)) {
-      myssh_state(data, sshc, SSH_SFTP_CLOSE);
+      myssh_to(data, sshc, SSH_SFTP_CLOSE);
       return sftp_libssh2_error_to_CURLE(sftperr);
     }
   }
-  myssh_state(data, sshc, SSH_SFTP_CREATE_DIRS);
+  myssh_to(data, sshc, SSH_SFTP_CREATE_DIRS);
   return CURLE_OK;
 }
 
@@ -2267,7 +2172,7 @@ static CURLcode ssh_state_sftp_readdir_init(struct Curl_easy *data,
 {
   Curl_pgrsSetDownloadSize(data, -1);
   if(data->req.no_body) {
-    myssh_state(data, sshc, SSH_STOP);
+    myssh_to(data, sshc, SSH_STOP);
     return CURLE_OK;
   }
 
@@ -2287,10 +2192,10 @@ static CURLcode ssh_state_sftp_readdir_init(struct Curl_easy *data,
     sftperr = libssh2_sftp_last_error(sshc->sftp_session);
     failf(data, "Could not open directory for reading: %s",
           sftp_libssh2_strerror(sftperr));
-    myssh_state(data, sshc, SSH_SFTP_CLOSE);
+    myssh_to(data, sshc, SSH_SFTP_CLOSE);
     return sftp_libssh2_error_to_CURLE(sftperr);
   }
-  myssh_state(data, sshc, SSH_SFTP_READDIR);
+  myssh_to(data, sshc, SSH_SFTP_READDIR);
   return CURLE_OK;
 }
 
@@ -2317,9 +2222,9 @@ static CURLcode ssh_state_sftp_readdir_link(struct Curl_easy *data,
   /* append filename and extra output */
   result = curlx_dyn_addf(&sshp->readdir, " -> %s", sshp->readdir_filename);
   if(result)
-    myssh_state(data, sshc, SSH_SFTP_CLOSE);
+    myssh_to(data, sshc, SSH_SFTP_CLOSE);
   else
-    myssh_state(data, sshc, SSH_SFTP_READDIR_BOTTOM);
+    myssh_to(data, sshc, SSH_SFTP_READDIR_BOTTOM);
   return result;
 }
 
@@ -2352,7 +2257,7 @@ static CURLcode ssh_state_scp_download_init(struct Curl_easy *data,
 
     ssh_err = libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
     failf(data, "%s", err_msg);
-    myssh_state(data, sshc, SSH_SCP_CHANNEL_FREE);
+    myssh_to(data, sshc, SSH_SCP_CHANNEL_FREE);
     return libssh2_session_error_to_CURLE(ssh_err);
   }
 
@@ -2364,7 +2269,7 @@ static CURLcode ssh_state_scp_download_init(struct Curl_easy *data,
   /* not set by Curl_xfer_setup to preserve keepon bits */
   data->conn->send_idx = 0;
 
-  myssh_state(data, sshc, SSH_STOP);
+  myssh_to(data, sshc, SSH_STOP);
   return CURLE_OK;
 }
 
@@ -2395,11 +2300,11 @@ static CURLcode ssh_state_sftp_close(struct Curl_easy *data,
      SSH_SFTP_CLOSE to pass the correct result back  */
   if(sshc->nextstate != SSH_NO_STATE &&
      sshc->nextstate != SSH_SFTP_CLOSE) {
-    myssh_state(data, sshc, sshc->nextstate);
+    myssh_to(data, sshc, sshc->nextstate);
     sshc->nextstate = SSH_SFTP_CLOSE;
   }
   else
-    myssh_state(data, sshc, SSH_STOP);
+    myssh_to(data, sshc, SSH_STOP);
 
   return CURLE_OK;
 }
@@ -2436,7 +2341,7 @@ static CURLcode ssh_state_sftp_shutdown(struct Curl_easy *data,
 
   Curl_safefree(sshc->homedir);
 
-  myssh_state(data, sshc, SSH_SESSION_DISCONNECT);
+  myssh_to(data, sshc, SSH_SESSION_DISCONNECT);
   return CURLE_OK;
 }
 
@@ -2461,10 +2366,10 @@ static CURLcode ssh_state_sftp_download_init(struct Curl_easy *data,
     sftperr = libssh2_sftp_last_error(sshc->sftp_session);
     failf(data, "Could not open remote file for reading: %s",
           sftp_libssh2_strerror(sftperr));
-    myssh_state(data, sshc, SSH_SFTP_CLOSE);
+    myssh_to(data, sshc, SSH_SFTP_CLOSE);
     return sftp_libssh2_error_to_CURLE(sftperr);
   }
-  myssh_state(data, sshc, SSH_SFTP_DOWNLOAD_STAT);
+  myssh_to(data, sshc, SSH_SFTP_DOWNLOAD_STAT);
   return CURLE_OK;
 }
 
@@ -2492,7 +2397,7 @@ static CURLcode ssh_state_scp_upload_init(struct Curl_easy *data,
 
     ssh_err = libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
     failf(data, "%s", err_msg);
-    myssh_state(data, sshc, SSH_SCP_CHANNEL_FREE);
+    myssh_to(data, sshc, SSH_SCP_CHANNEL_FREE);
     result = libssh2_session_error_to_CURLE(ssh_err);
 
     /* Map generic errors to upload failed */
@@ -2510,7 +2415,7 @@ static CURLcode ssh_state_scp_upload_init(struct Curl_easy *data,
   /* not set by Curl_xfer_setup to preserve keepon bits */
   data->conn->recv_idx = FIRSTSOCKET;
 
-  myssh_state(data, sshc, SSH_STOP);
+  myssh_to(data, sshc, SSH_STOP);
 
   return CURLE_OK;
 }
@@ -2549,7 +2454,7 @@ static CURLcode ssh_state_session_disconnect(struct Curl_easy *data,
 
   Curl_safefree(sshc->homedir);
 
-  myssh_state(data, sshc, SSH_SESSION_FREE);
+  myssh_to(data, sshc, SSH_SESSION_FREE);
   return CURLE_OK;
 }
 
@@ -2710,7 +2615,7 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
       break;
 
     case SSH_AUTH_HOST:
-      myssh_state(data, sshc, SSH_AUTH_AGENT_INIT);
+      myssh_to(data, sshc, SSH_AUTH_AGENT_INIT);
       break;
 
     case SSH_AUTH_AGENT_INIT:
@@ -2800,10 +2705,10 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
 
     case SSH_SFTP_GETINFO:
       if(data->set.get_filetime) {
-        myssh_state(data, sshc, SSH_SFTP_FILETIME);
+        myssh_to(data, sshc, SSH_SFTP_FILETIME);
       }
       else {
-        myssh_state(data, sshc, SSH_SFTP_TRANS_INIT);
+        myssh_to(data, sshc, SSH_SFTP_TRANS_INIT);
       }
       break;
 
@@ -2826,18 +2731,18 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
         data->info.filetime = (time_t)attrs.mtime;
       }
 
-      myssh_state(data, sshc, SSH_SFTP_TRANS_INIT);
+      myssh_to(data, sshc, SSH_SFTP_TRANS_INIT);
       break;
     }
 
     case SSH_SFTP_TRANS_INIT:
       if(data->state.upload)
-        myssh_state(data, sshc, SSH_SFTP_UPLOAD_INIT);
+        myssh_to(data, sshc, SSH_SFTP_UPLOAD_INIT);
       else if(sshp) {
         if(sshp->path[strlen(sshp->path) - 1] == '/')
-          myssh_state(data, sshc, SSH_SFTP_READDIR_INIT);
+          myssh_to(data, sshc, SSH_SFTP_READDIR_INIT);
         else
-          myssh_state(data, sshc, SSH_SFTP_DOWNLOAD_INIT);
+          myssh_to(data, sshc, SSH_SFTP_DOWNLOAD_INIT);
       }
       else
         result = CURLE_FAILED_INIT;
@@ -2847,7 +2752,7 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
       result = sshp ? sftp_upload_init(data, sshc, sshp, block) :
                CURLE_FAILED_INIT;
       if(result) {
-        myssh_state(data, sshc, SSH_SFTP_CLOSE);
+        myssh_to(data, sshc, SSH_SFTP_CLOSE);
         sshc->nextstate = SSH_NO_STATE;
       }
       break;
@@ -2857,10 +2762,10 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
         result = CURLE_FAILED_INIT;
       else if(strlen(sshp->path) > 1) {
         sshc->slash_pos = sshp->path + 1; /* ignore the leading '/' */
-        myssh_state(data, sshc, SSH_SFTP_CREATE_DIRS);
+        myssh_to(data, sshc, SSH_SFTP_CREATE_DIRS);
       }
       else {
-        myssh_state(data, sshc, SSH_SFTP_UPLOAD_INIT);
+        myssh_to(data, sshc, SSH_SFTP_UPLOAD_INIT);
       }
       break;
 
@@ -2874,10 +2779,10 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
         *sshc->slash_pos = 0;
 
         infof(data, "Creating directory '%s'", sshp->path);
-        myssh_state(data, sshc, SSH_SFTP_CREATE_DIRS_MKDIR);
+        myssh_to(data, sshc, SSH_SFTP_CREATE_DIRS_MKDIR);
         break;
       }
-      myssh_state(data, sshc, SSH_SFTP_UPLOAD_INIT);
+      myssh_to(data, sshc, SSH_SFTP_UPLOAD_INIT);
       break;
 
     case SSH_SFTP_CREATE_DIRS_MKDIR:
@@ -2894,7 +2799,7 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
       result = sshp ? sftp_readdir(data, sshc, sshp, block) :
                CURLE_FAILED_INIT;
       if(result) {
-        myssh_state(data, sshc, SSH_SFTP_CLOSE);
+        myssh_to(data, sshc, SSH_SFTP_CLOSE);
       }
       break;
 
@@ -2916,11 +2821,11 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
 
       if(result) {
         curlx_dyn_free(&sshp->readdir);
-        myssh_state(data, sshc, SSH_STOP);
+        myssh_to(data, sshc, SSH_STOP);
       }
       else {
         curlx_dyn_reset(&sshp->readdir);
-        myssh_state(data, sshc, SSH_SFTP_READDIR);
+        myssh_to(data, sshc, SSH_SFTP_READDIR);
       }
       break;
 
@@ -2932,7 +2837,7 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
 
         /* no data to transfer */
         Curl_xfer_setup_nop(data);
-        myssh_state(data, sshc, SSH_STOP);
+        myssh_to(data, sshc, SSH_STOP);
       }
       break;
 
@@ -2945,7 +2850,7 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
       result = sshp ? sftp_download_stat(data, sshc, sshp, block) :
                CURLE_FAILED_INIT;
       if(result) {
-        myssh_state(data, sshc, SSH_SFTP_CLOSE);
+        myssh_to(data, sshc, SSH_SFTP_CLOSE);
         sshc->nextstate = SSH_NO_STATE;
       }
       break;
@@ -2963,7 +2868,7 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
       result = sshp ? Curl_getworkingpath(data, sshc->homedir, &sshp->path) :
                CURLE_FAILED_INIT;
       if(result) {
-        myssh_state(data, sshc, SSH_STOP);
+        myssh_to(data, sshc, SSH_STOP);
         break;
       }
 
@@ -2971,13 +2876,13 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
         if(data->state.infilesize < 0) {
           failf(data, "SCP requires a known file size for upload");
           result = CURLE_UPLOAD_FAILED;
-          myssh_state(data, sshc, SSH_SCP_CHANNEL_FREE);
+          myssh_to(data, sshc, SSH_SCP_CHANNEL_FREE);
           break;
         }
-        myssh_state(data, sshc, SSH_SCP_UPLOAD_INIT);
+        myssh_to(data, sshc, SSH_SCP_UPLOAD_INIT);
       }
       else {
-        myssh_state(data, sshc, SSH_SCP_DOWNLOAD_INIT);
+        myssh_to(data, sshc, SSH_SCP_DOWNLOAD_INIT);
       }
       break;
 
@@ -2993,9 +2898,9 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
 
     case SSH_SCP_DONE:
       if(data->state.upload)
-        myssh_state(data, sshc, SSH_SCP_SEND_EOF);
+        myssh_to(data, sshc, SSH_SCP_SEND_EOF);
       else
-        myssh_state(data, sshc, SSH_SCP_CHANNEL_FREE);
+        myssh_to(data, sshc, SSH_SCP_CHANNEL_FREE);
       break;
 
     case SSH_SCP_SEND_EOF:
@@ -3013,7 +2918,7 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
                 rc, err_msg);
         }
       }
-      myssh_state(data, sshc, SSH_SCP_WAIT_EOF);
+      myssh_to(data, sshc, SSH_SCP_WAIT_EOF);
       break;
 
     case SSH_SCP_WAIT_EOF:
@@ -3030,7 +2935,7 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
           infof(data, "Failed to get channel EOF: %d %s", rc, err_msg);
         }
       }
-      myssh_state(data, sshc, SSH_SCP_WAIT_CLOSE);
+      myssh_to(data, sshc, SSH_SCP_WAIT_CLOSE);
       break;
 
     case SSH_SCP_WAIT_CLOSE:
@@ -3047,7 +2952,7 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
           infof(data, "Channel failed to close: %d %s", rc, err_msg);
         }
       }
-      myssh_state(data, sshc, SSH_SCP_CHANNEL_FREE);
+      myssh_to(data, sshc, SSH_SCP_CHANNEL_FREE);
       break;
 
     case SSH_SCP_CHANNEL_FREE:
@@ -3067,7 +2972,7 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
         sshc->ssh_channel = NULL;
       }
       CURL_TRC_SSH(data, "SCP DONE phase complete");
-      myssh_state(data, sshc, SSH_STOP);
+      myssh_to(data, sshc, SSH_STOP);
       break;
 
     case SSH_SESSION_DISCONNECT:
@@ -3082,13 +2987,13 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
       memset(sshc, 0, sizeof(struct ssh_conn));
       connclose(conn, "SSH session free");
       sshc->state = SSH_SESSION_FREE; /* current */
-      myssh_state(data, sshc, SSH_STOP);
+      myssh_to(data, sshc, SSH_STOP);
       break;
 
     case SSH_QUIT:
     default:
       /* internal error */
-      myssh_state(data, sshc, SSH_STOP);
+      myssh_to(data, sshc, SSH_STOP);
       break;
     }
 
@@ -3101,7 +3006,7 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
     result = CURLE_OK;
   }
   CURL_TRC_SSH(data, "[%s] statemachine() -> %d, block=%d",
-               myssh_statename(sshc->state), result, *block);
+               Curl_ssh_statename(sshc->state), result, *block);
 
   return result;
 }
@@ -3515,7 +3420,7 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
   infof(data, "SSH socket: %d", (int)sock);
 #endif /* CURL_LIBSSH2_DEBUG */
 
-  myssh_state(data, sshc, SSH_INIT);
+  myssh_to(data, sshc, SSH_INIT);
 
   result = ssh_multi_statemach(data, done);
 
@@ -3545,7 +3450,7 @@ static CURLcode scp_perform(struct Curl_easy *data,
     return CURLE_FAILED_INIT;
 
   /* start the first command in the DO phase */
-  myssh_state(data, sshc, SSH_SCP_TRANS_INIT);
+  myssh_to(data, sshc, SSH_SCP_TRANS_INIT);
 
   /* run the state-machine */
   result = ssh_multi_statemach(data, dophase_done);
@@ -3586,7 +3491,7 @@ static CURLcode scp_disconnect(struct Curl_easy *data,
 
   if(sshc && sshc->ssh_session) {
     /* only if there is a session still around to use! */
-    myssh_state(data, sshc, SSH_SESSION_DISCONNECT);
+    myssh_to(data, sshc, SSH_SESSION_DISCONNECT);
     result = ssh_block_statemach(data, sshc, sshp, TRUE);
   }
 
@@ -3626,7 +3531,7 @@ static CURLcode scp_done(struct Curl_easy *data, CURLcode status,
   (void)premature;
 
   if(sshc && !status)
-    myssh_state(data, sshc, SSH_SCP_DONE);
+    myssh_to(data, sshc, SSH_SCP_DONE);
 
   return ssh_done(data, status);
 }
@@ -3718,7 +3623,7 @@ static CURLcode sftp_perform(struct Curl_easy *data,
     return CURLE_FAILED_INIT;
 
   /* start the first command in the DO phase */
-  myssh_state(data, sshc, SSH_SFTP_QUOTE_INIT);
+  myssh_to(data, sshc, SSH_SFTP_QUOTE_INIT);
 
   /* run the state-machine */
   result = ssh_multi_statemach(data, dophase_done);
@@ -3759,7 +3664,7 @@ static CURLcode sftp_disconnect(struct Curl_easy *data,
     if(sshc->ssh_session) {
       /* only if there is a session still around to use! */
       CURL_TRC_SSH(data, "DISCONNECT starts now");
-      myssh_state(data, sshc, SSH_SFTP_SHUTDOWN);
+      myssh_to(data, sshc, SSH_SFTP_SHUTDOWN);
       result = ssh_block_statemach(data, sshc, sshp, TRUE);
       CURL_TRC_SSH(data, "DISCONNECT is done -> %d", result);
     }
@@ -3783,7 +3688,7 @@ static CURLcode sftp_done(struct Curl_easy *data, CURLcode status,
        operation */
     if(!premature && data->set.postquote && !conn->bits.retry)
       sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
-    myssh_state(data, sshc, SSH_SFTP_CLOSE);
+    myssh_to(data, sshc, SSH_SFTP_CLOSE);
   }
   return ssh_done(data, status);
 }
index d98070856c809435906c9af552c3578e29ac5e07..78889bf60e6b96c85d6683afb4ed07aa75f2df07 100644 (file)
@@ -238,6 +238,17 @@ struct ssh_conn {
 
 #ifdef USE_SSH
 
+#ifdef CURLVERBOSE
+const char *Curl_ssh_statename(sshstate state);
+#else
+#define Curl_ssh_statename(x) ""
+#endif
+void Curl_ssh_set_state(struct Curl_easy *data,
+                        struct ssh_conn *sshc,
+                        sshstate nowstate);
+
+#define myssh_to(x, y, z) Curl_ssh_set_state(x, y, z)
+
 /* generic SSH backend functions */
 CURLcode Curl_ssh_init(void);
 void Curl_ssh_cleanup(void);
index f51669906b976f06be7c9062b01a6f5321d1b8b0..e36c703780c3d5e6c9522d2e1b20de5c7dd88640 100644 (file)
 #include "../curl_trc.h"
 #include "../escape.h"
 
+#ifdef CURLVERBOSE
+const char *Curl_ssh_statename(sshstate state)
+{
+  static const char * const names[] = {
+    "SSH_STOP",
+    "SSH_INIT",
+    "SSH_S_STARTUP",
+    "SSH_HOSTKEY",
+    "SSH_AUTHLIST",
+    "SSH_AUTH_PKEY_INIT",
+    "SSH_AUTH_PKEY",
+    "SSH_AUTH_PASS_INIT",
+    "SSH_AUTH_PASS",
+    "SSH_AUTH_AGENT_INIT",
+    "SSH_AUTH_AGENT_LIST",
+    "SSH_AUTH_AGENT",
+    "SSH_AUTH_HOST_INIT",
+    "SSH_AUTH_HOST",
+    "SSH_AUTH_KEY_INIT",
+    "SSH_AUTH_KEY",
+    "SSH_AUTH_GSSAPI",
+    "SSH_AUTH_DONE",
+    "SSH_SFTP_INIT",
+    "SSH_SFTP_REALPATH",
+    "SSH_SFTP_QUOTE_INIT",
+    "SSH_SFTP_POSTQUOTE_INIT",
+    "SSH_SFTP_QUOTE",
+    "SSH_SFTP_NEXT_QUOTE",
+    "SSH_SFTP_QUOTE_STAT",
+    "SSH_SFTP_QUOTE_SETSTAT",
+    "SSH_SFTP_QUOTE_SYMLINK",
+    "SSH_SFTP_QUOTE_MKDIR",
+    "SSH_SFTP_QUOTE_RENAME",
+    "SSH_SFTP_QUOTE_RMDIR",
+    "SSH_SFTP_QUOTE_UNLINK",
+    "SSH_SFTP_QUOTE_STATVFS",
+    "SSH_SFTP_GETINFO",
+    "SSH_SFTP_FILETIME",
+    "SSH_SFTP_TRANS_INIT",
+    "SSH_SFTP_UPLOAD_INIT",
+    "SSH_SFTP_CREATE_DIRS_INIT",
+    "SSH_SFTP_CREATE_DIRS",
+    "SSH_SFTP_CREATE_DIRS_MKDIR",
+    "SSH_SFTP_READDIR_INIT",
+    "SSH_SFTP_READDIR",
+    "SSH_SFTP_READDIR_LINK",
+    "SSH_SFTP_READDIR_BOTTOM",
+    "SSH_SFTP_READDIR_DONE",
+    "SSH_SFTP_DOWNLOAD_INIT",
+    "SSH_SFTP_DOWNLOAD_STAT",
+    "SSH_SFTP_CLOSE",
+    "SSH_SFTP_SHUTDOWN",
+    "SSH_SCP_TRANS_INIT",
+    "SSH_SCP_UPLOAD_INIT",
+    "SSH_SCP_DOWNLOAD_INIT",
+    "SSH_SCP_DOWNLOAD",
+    "SSH_SCP_DONE",
+    "SSH_SCP_SEND_EOF",
+    "SSH_SCP_WAIT_EOF",
+    "SSH_SCP_WAIT_CLOSE",
+    "SSH_SCP_CHANNEL_FREE",
+    "SSH_SESSION_DISCONNECT",
+    "SSH_SESSION_FREE",
+    "QUIT"
+  };
+  /* a precaution to make sure the lists are in sync */
+  DEBUGASSERT(CURL_ARRAYSIZE(names) == SSH_LAST);
+  return ((size_t)state < CURL_ARRAYSIZE(names)) ? names[state] : "";
+}
+#endif /* CURLVERBOSE */
+
+/*
+ * SSH State machine related code
+ */
+/* This is the ONLY way to change SSH state! */
+void Curl_ssh_set_state(struct Curl_easy *data,
+                        struct ssh_conn *sshc,
+                        sshstate nowstate)
+{
+#ifdef CURLVERBOSE
+  if(sshc->state != nowstate) {
+    CURL_TRC_SSH(data, "[%s] -> [%s]",
+                 Curl_ssh_statename(sshc->state),
+                 Curl_ssh_statename(nowstate));
+  }
+#else
+  (void)data;
+#endif
+  sshc->state = nowstate;
+}
+
 #define MAX_SSHPATH_LEN 100000 /* arbitrary */
 
 /* figure out the path to work with in this particular request */