Skip to content

Commit d587f6c

Browse files
committed
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 do
1 parent 557f3df commit d587f6c

2 files changed

Lines changed: 45 additions & 0 deletions

File tree

src/wolfscp.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,40 @@ int DoScpSource(WOLFSSH* ssh)
883883
return ret;
884884
}
885885

886+
/* Contract is in wolfssh/wolfscp.h. */
887+
int wolfSSH_SCP_accept(WOLFSSH* ssh)
888+
{
889+
int ret;
890+
891+
if (ssh == NULL)
892+
return WS_BAD_ARGUMENT;
893+
894+
/* Clear a want left by the previous call so the retry starts clean,
895+
* the way the other re-entrant entry points do. */
896+
if (ssh->error == WS_WANT_READ || ssh->error == WS_WANT_WRITE)
897+
ssh->error = WS_SUCCESS;
898+
899+
ret = DoScpRequest(ssh);
900+
901+
if (ret >= WS_SUCCESS) {
902+
/* The tail of DoScpRequest() passes a read count through, so treat
903+
* anything non-negative as done the way wolfSSH_accept() does. */
904+
ret = WS_SCP_COMPLETE;
905+
}
906+
else {
907+
/* A non-blocking want on a read path surfaces as a generic error
908+
* with the want recorded in ssh->error (see GetInputData), so
909+
* report it as the want the caller is told to retry on. */
910+
int err = wolfSSH_get_error(ssh);
911+
912+
if (err == WS_WANT_READ || err == WS_WANT_WRITE)
913+
ret = err;
914+
}
915+
916+
return ret;
917+
}
918+
919+
886920
int DoScpRequest(WOLFSSH* ssh)
887921
{
888922
int ret = WS_SUCCESS;

wolfssh/wolfscp.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,17 @@ WOLFSSH_API int wolfSSH_SCP_to(WOLFSSH* ssh, const char* src,
158158
const char* dst);
159159
WOLFSSH_API int wolfSSH_SCP_from(WOLFSSH* ssh, const char* src,
160160
const char* dst);
161+
/* Server side. Drives an SCP transfer on a channel whose "exec scp ..."
162+
* command is already bound. This is the same work wolfSSH_accept() does
163+
* through its WS_SCP_INIT re-entry, exposed so an application can start the
164+
* transfer itself; use one or the other, not both. Call it once
165+
* wolfSSH_accept() has returned and the exec channel-request callback has
166+
* reported an SCP command, not from inside that callback.
167+
*
168+
* Returns WS_SCP_COMPLETE when the transfer is done. On a non-blocking
169+
* socket it returns WS_WANT_READ or WS_WANT_WRITE with the transfer part
170+
* done; call it again on the same session until it completes. */
171+
WOLFSSH_API int wolfSSH_SCP_accept(WOLFSSH* ssh);
161172

162173

163174
#ifdef __cplusplus

0 commit comments

Comments
 (0)