diff --git a/src/wolfscp.c b/src/wolfscp.c index 184d057c..e5d95a3e 100644 --- a/src/wolfscp.c +++ b/src/wolfscp.c @@ -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; diff --git a/wolfssh/wolfscp.h b/wolfssh/wolfscp.h index 32e9dc7d..1ebeb339 100644 --- a/wolfssh/wolfscp.h +++ b/wolfssh/wolfscp.h @@ -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