mirror of https://github.com/wolfSSL/wolfssh.git
SCP: let the application start the transfer
An application that binds an "scp ..." command to a channel itself has no way to run the transfer; wolfSSH_accept() did it through a WS_SCP_INIT re-entry only that state machine can drive. - add wolfSSH_SCP_accept(), a wrapper over DoScpRequest() reporting WS_SCP_COMPLETE for any non-negative result, as accept() does - a receive-side want reaches the wrapper as a generic error with the want in ssh->error, so report the want itself and let the caller retry - state that resume contract beside the prototype, and clear a stale want on entry the way the other re-entrant entry points dopull/1245/head
parent
ba6bc667a9
commit
13b9e39f90
|
|
@ -883,6 +883,40 @@ int DoScpSource(WOLFSSH* ssh)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Contract is in wolfssh/wolfscp.h. */
|
||||
int wolfSSH_SCP_accept(WOLFSSH* ssh)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (ssh == NULL)
|
||||
return WS_BAD_ARGUMENT;
|
||||
|
||||
/* Clear a want left by the previous call so the retry starts clean,
|
||||
* the way the other re-entrant entry points do. */
|
||||
if (ssh->error == WS_WANT_READ || ssh->error == WS_WANT_WRITE)
|
||||
ssh->error = WS_SUCCESS;
|
||||
|
||||
ret = DoScpRequest(ssh);
|
||||
|
||||
if (ret >= WS_SUCCESS) {
|
||||
/* The tail of DoScpRequest() passes a read count through, so treat
|
||||
* anything non-negative as done the way wolfSSH_accept() does. */
|
||||
ret = WS_SCP_COMPLETE;
|
||||
}
|
||||
else {
|
||||
/* A non-blocking want on a read path surfaces as a generic error
|
||||
* with the want recorded in ssh->error (see GetInputData), so
|
||||
* report it as the want the caller is told to retry on. */
|
||||
int err = wolfSSH_get_error(ssh);
|
||||
|
||||
if (err == WS_WANT_READ || err == WS_WANT_WRITE)
|
||||
ret = err;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int DoScpRequest(WOLFSSH* ssh)
|
||||
{
|
||||
int ret = WS_SUCCESS;
|
||||
|
|
|
|||
|
|
@ -158,6 +158,17 @@ WOLFSSH_API int wolfSSH_SCP_to(WOLFSSH* ssh, const char* src,
|
|||
const char* dst);
|
||||
WOLFSSH_API int wolfSSH_SCP_from(WOLFSSH* ssh, const char* src,
|
||||
const char* dst);
|
||||
/* Server side. Drives an SCP transfer on a channel whose "exec scp ..."
|
||||
* command is already bound. This is the same work wolfSSH_accept() does
|
||||
* through its WS_SCP_INIT re-entry, exposed so an application can start the
|
||||
* transfer itself; use one or the other, not both. Call it once
|
||||
* wolfSSH_accept() has returned and the exec channel-request callback has
|
||||
* reported an SCP command, not from inside that callback.
|
||||
*
|
||||
* Returns WS_SCP_COMPLETE when the transfer is done. On a non-blocking
|
||||
* socket it returns WS_WANT_READ or WS_WANT_WRITE with the transfer part
|
||||
* done; call it again on the same session until it completes. */
|
||||
WOLFSSH_API int wolfSSH_SCP_accept(WOLFSSH* ssh);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
Loading…
Reference in New Issue