ssh_statemach_act() is now modified to loop over the switch() to perform as

much as possible in one go, as long as it doesn't block and hasn't reached the
end of the state machine.
This avoids spurious -1 returns from curl_multi_fdset() simply because
previously it would return from this function without anything in EWOUDLBLOCK
and thus basically it wasn't actually waiting for anything!!
This commit is contained in:
Daniel Stenberg
2010-01-11 23:10:53 +00:00
parent 2158e234aa
commit d17416190b

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@@ -459,10 +459,10 @@ static int sshkeycallback(CURL *easy,
#endif #endif
/* /*
* ssh_statemach_act() runs the SSH statemachine "one round" and returns. The * ssh_statemach_act() runs the SSH state machine as far as it can without
* data the pointer 'block' points to will be set to TRUE if the libssh2 * blocking and without reaching the end. The data the pointer 'block' points
* function returns LIBSSH2_ERROR_EAGAIN meaning it wants to be called again * to will be set to TRUE if the libssh2 function returns LIBSSH2_ERROR_EAGAIN
* when the socket is ready * meaning it wants to be called again when the socket is ready
*/ */
static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
@@ -481,6 +481,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
int seekerr = CURL_SEEKFUNC_OK; int seekerr = CURL_SEEKFUNC_OK;
*block = 0; /* we're not blocking by default */ *block = 0; /* we're not blocking by default */
do {
switch(sshc->state) { switch(sshc->state) {
case SSH_S_STARTUP: case SSH_S_STARTUP:
sshc->secondCreateDirs = 0; sshc->secondCreateDirs = 0;
@@ -1429,9 +1431,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sshc->actualcode = err>= LIBSSH2_FX_OK? sshc->actualcode = err>= LIBSSH2_FX_OK?
sftp_libssh2_error_to_CURLE(err):CURLE_SSH; sftp_libssh2_error_to_CURLE(err):CURLE_SSH;
if(!sshc->actualcode) { if(!sshc->actualcode) {
/* Sometimes, for some reason libssh2_sftp_last_error() returns zero /* Sometimes, for some reason libssh2_sftp_last_error() returns
even though libssh2_sftp_open() failed previously! We need to zero even though libssh2_sftp_open() failed previously! We need
work around that! */ to work around that! */
sshc->actualcode = CURLE_SSH; sshc->actualcode = CURLE_SSH;
err=-1; err=-1;
} }
@@ -1442,7 +1444,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
} }
} }
/* If we have restart point then we need to seek to the correct position. */ /* If we have restart point then we need to seek to the correct
position. */
if(data->state.resume_from > 0) { if(data->state.resume_from > 0) {
/* Let's read off the proper amount of bytes from the input. */ /* Let's read off the proper amount of bytes from the input. */
if(conn->seek_func) { if(conn->seek_func) {
@@ -1508,8 +1511,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sshc->actualcode = result; sshc->actualcode = result;
} }
else { else {
/* store this original bitmask setup to use later on if we can't figure /* store this original bitmask setup to use later on if we can't
out a "real" bitmask */ figure out a "real" bitmask */
sshc->orig_waitfor = data->req.keepon; sshc->orig_waitfor = data->req.keepon;
state(conn, SSH_STOP); state(conn, SSH_STOP);
@@ -1552,9 +1555,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(rc == -1) { if(rc == -1) {
unsigned int sftp_err = 0; unsigned int sftp_err = 0;
/* /*
* abort if failure wasn't that the dir already exists or the * Abort if failure wasn't that the dir already exists or the
* permission was denied (creation might succeed further * permission was denied (creation might succeed further down the
* down the path) - retry on unspecific FAILURE also * path) - retry on unspecific FAILURE also
*/ */
sftp_err = libssh2_sftp_last_error(sshc->sftp_session); sftp_err = libssh2_sftp_last_error(sshc->sftp_session);
if((sftp_err != LIBSSH2_FX_FILE_ALREADY_EXISTS) && if((sftp_err != LIBSSH2_FX_FILE_ALREADY_EXISTS) &&
@@ -1571,8 +1574,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
case SSH_SFTP_READDIR_INIT: case SSH_SFTP_READDIR_INIT:
/* /*
* This is a directory that we are trying to get, so produce a * This is a directory that we are trying to get, so produce a directory
* directory listing * listing
*/ */
sshc->sftp_handle = libssh2_sftp_opendir(sshc->sftp_session, sshc->sftp_handle = libssh2_sftp_opendir(sshc->sftp_session,
sftp_scp->path); sftp_scp->path);
@@ -1638,8 +1641,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
state(conn, SSH_STOP); state(conn, SSH_STOP);
break; break;
} }
/* since this counts what we send to the client, we include the newline /* since this counts what we send to the client, we include the
in this counter */ newline in this counter */
data->req.bytecount += sshc->readdir_len+1; data->req.bytecount += sshc->readdir_len+1;
/* output debug output if that is requested */ /* output debug output if that is requested */
@@ -2236,6 +2239,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break; break;
} }
} while(!rc && (sshc->state != SSH_STOP));
if(rc == LIBSSH2_ERROR_EAGAIN) { if(rc == LIBSSH2_ERROR_EAGAIN) {
/* we would block, we need to wait for the socket to be ready (in the /* we would block, we need to wait for the socket to be ready (in the
right direction too)! */ right direction too)! */