diff --git a/src/wolfscp.c b/src/wolfscp.c index 184d057cf..c247eacc4 100644 --- a/src/wolfscp.c +++ b/src/wolfscp.c @@ -883,6 +883,37 @@ 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 if (ret == WS_FATAL_ERROR && wolfSSH_get_error(ssh) == WS_WANT_READ) { + /* GetInputData() hides a read want behind WS_FATAL_ERROR. Write + * wants come back by value, and a stale WS_WANT_WRITE from an + * accepted short send can outlive a terminal result. */ + ret = WS_WANT_READ; + } + + return ret; +} + + int DoScpRequest(WOLFSSH* ssh) { int ret = WS_SUCCESS; diff --git a/wolfssh/wolfscp.h b/wolfssh/wolfscp.h index 32e9dc7de..1ebeb339f 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