Skip to content

Commit 01dd6ec

Browse files
fixes for SFTP want read/write cases
1 parent b60c599 commit 01dd6ec

3 files changed

Lines changed: 92 additions & 15 deletions

File tree

examples/echoserver/echoserver.c

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1299,16 +1299,25 @@ static int sftp_worker(thread_ctx_t* threadCtx)
12991299
{
13001300
WOLFSSH* ssh = threadCtx->ssh;
13011301
WS_SOCKET_T s;
1302-
int ret = WS_SUCCESS;
1302+
int ret;
13031303
int error = -1;
13041304
int selected;
13051305
unsigned char peek_buf[1];
13061306
int timeout = TEST_SFTP_TIMEOUT;
13071307

13081308
s = (WS_SOCKET_T)wolfSSH_get_fd(ssh);
1309+
ret = error = wolfSSH_get_error(ssh);
1310+
1311+
/* there is an edge case where the last SFTP handshake message sent got a
1312+
* WANT_WRITE case, keep trying to send it here. */
1313+
while (error == WS_WANT_WRITE) {
1314+
ret = wolfSSH_worker(ssh, NULL);
1315+
error = wolfSSH_get_error(ssh);
1316+
}
13091317

13101318
do {
1311-
if (ret == WS_WANT_WRITE || wolfSSH_SFTP_PendingSend(ssh)) {
1319+
if (ret == WS_WANT_WRITE || ret == WS_CHAN_RXD ||
1320+
wolfSSH_SFTP_PendingSend(ssh)) {
13121321
/* Yes, process the SFTP data. */
13131322
ret = wolfSSH_SFTP_read(ssh);
13141323
error = wolfSSH_get_error(ssh);
@@ -1362,6 +1371,19 @@ static int sftp_worker(thread_ctx_t* threadCtx)
13621371
break;
13631372
}
13641373
if (ret != WS_SUCCESS && ret != WS_CHAN_RXD) {
1374+
#ifdef WOLFSSH_TEST_BLOCK
1375+
if (error == WS_WANT_READ) {
1376+
while (error == WS_WANT_READ) {
1377+
/* The socket had data but our test nonblocking code
1378+
* returned want read. Loop over wolfSSH_worker here
1379+
* until we get the data off the socket that select
1380+
* indicated was available. */
1381+
ret = wolfSSH_worker(ssh, NULL);
1382+
error = wolfSSH_get_error(ssh);
1383+
}
1384+
continue;
1385+
}
1386+
#endif
13651387
if (ret == WS_WANT_WRITE) {
13661388
/* recall wolfSSH_worker here because is likely our custom
13671389
* highwater callback that returned up a WS_WANT_WRITE */
@@ -1433,20 +1455,45 @@ static int NonBlockSSH_accept(WOLFSSH* ssh)
14331455
printf("... server would read block\n");
14341456
else if (error == WS_WANT_WRITE)
14351457
printf("... server would write block\n");
1458+
else if (error == WS_AUTH_PENDING)
1459+
printf("... server auth pending\n");
14361460

14371461
select_ret = tcp_select(sockfd, 1);
1438-
if (select_ret == WS_SELECT_RECV_READY ||
1439-
select_ret == WS_SELECT_ERROR_READY ||
1440-
error == WS_WANT_WRITE ||
1441-
error == WS_AUTH_PENDING)
1442-
{
1462+
if (select_ret == WS_SELECT_RECV_READY) {
14431463
ret = wolfSSH_accept(ssh);
14441464
error = wolfSSH_get_error(ssh);
1465+
1466+
#ifdef WOLFSSH_TEST_BLOCK
1467+
if (error == WS_WANT_READ) {
1468+
/* The socket had data but our test nonblocking code
1469+
* returned want read. Loop over wolfSSH_accept here until
1470+
* we get the data off the socket that select indicated was
1471+
* available. */
1472+
while (error == WS_WANT_READ) {
1473+
ret = wolfSSH_accept(ssh);
1474+
error = wolfSSH_get_error(ssh);
1475+
}
1476+
}
1477+
#endif
14451478
}
1446-
else if (select_ret == WS_SELECT_TIMEOUT)
1447-
error = WS_WANT_READ;
1448-
else
1479+
else if (select_ret == WS_SELECT_TIMEOUT) {
1480+
if (error == WS_WANT_WRITE || error == WS_AUTH_PENDING
1481+
#ifdef WOLFSSH_TEST_BLOCK
1482+
|| error == WS_WANT_READ
1483+
#endif
1484+
) {
1485+
/* For write or auth pending, we need to try again */
1486+
ret = wolfSSH_accept(ssh);
1487+
error = wolfSSH_get_error(ssh);
1488+
}
1489+
else {
1490+
error = WS_WANT_READ;
1491+
}
1492+
}
1493+
else {
14491494
error = WS_FATAL_ERROR;
1495+
break;
1496+
}
14501497
}
14511498

14521499
return ret;

examples/sftpclient/sftpclient.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,8 @@ static int NonBlockSSH_connect(void)
205205
sockfd = (SOCKET_T)wolfSSH_get_fd(ssh);
206206

207207
while (ret != WS_SUCCESS &&
208-
(error == WS_WANT_READ || error == WS_WANT_WRITE))
208+
(error == WS_WANT_READ || error == WS_WANT_WRITE ||
209+
error == WS_REKEYING || error == WS_AUTH_PENDING))
209210
{
210211
if (error == WS_WANT_READ)
211212
printf("... client would read block\n");
@@ -219,6 +220,19 @@ static int NonBlockSSH_connect(void)
219220
{
220221
ret = wolfSSH_SFTP_connect(ssh);
221222
error = wolfSSH_get_error(ssh);
223+
224+
#ifdef WOLFSSH_TEST_BLOCK
225+
if (select_ret == WS_SELECT_RECV_READY && error == WS_WANT_READ) {
226+
/* The socket has data to be read but the non blocking test
227+
* code returned want read. Loop over wolfSSH_SFTP_connect here
228+
* until we get the data off the socket that select indicated
229+
* was available. */
230+
while (error == WS_WANT_READ) {
231+
ret = wolfSSH_SFTP_connect(ssh);
232+
error = wolfSSH_get_error(ssh);
233+
}
234+
}
235+
#endif
222236
}
223237
else if (select_ret == WS_SELECT_TIMEOUT)
224238
error = WS_WANT_READ;

src/wolfsftp.c

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,7 @@ static int wolfSSH_SFTP_buffer_read(WOLFSSH* ssh, WS_SFTP_BUFFER* buffer,
543543
int readSz)
544544
{
545545
int ret;
546+
byte peekBuf[1];
546547

547548
if (buffer == NULL || ssh == NULL) {
548549
return WS_FATAL_ERROR;
@@ -563,8 +564,18 @@ static int wolfSSH_SFTP_buffer_read(WOLFSSH* ssh, WS_SFTP_BUFFER* buffer,
563564
}
564565

565566
do {
566-
ret = wolfSSH_stream_read(ssh, buffer->data + buffer->idx,
567+
if (!wolfSSH_stream_peek(ssh, peekBuf, 1)) {
568+
/* poll more data off the wire */
569+
ret = wolfSSH_worker(ssh, NULL);
570+
}
571+
else {
572+
ret = WS_CHAN_RXD; /* existing data found with peek */
573+
}
574+
575+
if (ret == WS_CHAN_RXD) {
576+
ret = wolfSSH_stream_read(ssh, buffer->data + buffer->idx,
567577
buffer->sz - buffer->idx);
578+
}
568579
if (ret < 0) {
569580
return WS_FATAL_ERROR;
570581
}
@@ -5666,14 +5677,19 @@ int wolfSSH_SFTP_RecvFSetSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
56665677
* returns WS_SUCCESS on success
56675678
*/
56685679
static int SFTP_ClientRecvInit(WOLFSSH* ssh) {
5669-
int len;
5680+
int len, ret;
56705681
byte id;
56715682
word32 sz = 0;
56725683
word32 version = 0;
56735684
byte buf[LENGTH_SZ + MSG_ID_SZ + UINT32_SZ];
56745685

56755686
switch (ssh->sftpState) {
56765687
case SFTP_RECV:
5688+
ret = wolfSSH_worker(ssh,NULL);
5689+
if (ret != WS_CHAN_RXD) {
5690+
return ret;
5691+
}
5692+
56775693
if ((len = wolfSSH_stream_read(ssh, buf, sizeof(buf)))
56785694
!= sizeof(buf)) {
56795695
/* @TODO partial read on small packet */
@@ -5785,7 +5801,7 @@ int wolfSSH_SFTP_connect(WOLFSSH* ssh)
57855801

57865802
switch (ssh->sftpState) {
57875803
case SFTP_BEGIN:
5788-
if ((ssh->error = SFTP_ClientSendInit(ssh)) != WS_SUCCESS) {
5804+
if (SFTP_ClientSendInit(ssh) != WS_SUCCESS) {
57895805
return WS_FATAL_ERROR;
57905806
}
57915807
ssh->sftpState = SFTP_RECV;
@@ -8174,7 +8190,7 @@ WS_SFTPNAME* wolfSSH_SFTP_RealPath(WOLFSSH* ssh, char* dir)
81748190
case SFTP_REAL_GET_PACKET:
81758191
/* read name response from Real Path packet */
81768192
ret = wolfSSH_SFTP_DoName(ssh);
8177-
if (ret != NULL || (ret == NULL && ssh->error != WS_WANT_READ)) {
8193+
if (ret != NULL || (ret == NULL && !NoticeError(ssh))) {
81788194
wolfSSH_SFTP_ClearState(ssh, STATE_ID_NAME);
81798195
ssh->realState = SFTP_REAL_SEND_PACKET;
81808196
}

0 commit comments

Comments
 (0)