Skip to content

Commit d95204d

Browse files
ssh, internal: flush the worker's queued output on every call
- wolfSSH_worker() calls wolfSSH_SendPacket() whenever ssh->outputBuffer holds bytes and the session is not disconnected, in place of doing so only for WS_SUCCESS, WS_WANT_READ, WS_CHAN_RXD or WS_EOF. A failed flush reaches the return only when the receive reported nothing, and ssh->error keeps the receive's code only when the receive itself failed. Drops the second DoReceive(), its WS_WINDOW_FULL case, the WOLFSSH_TEST_BLOCK fork, and the separate WS_CHANNEL_CLOSED flush the gate used to need. - wolfSSH_SendPacket() records its code in ssh->error on every transport failure path, and the comments on _ChannelRead(), _ChannelReadExt() and test_ChannelReadExtHardFailureReported() no longer describe the former contract. - The echoserver shell loop and the Windows wolfsshd shell loop treat a WS_WANT_WRITE from wolfSSH_worker() as non-fatal. - tests cover the flush on an idle receive, the owed flush across calls, what ssh->error holds after a receive failure, a hard send failure, channel data alongside a failed send, a discarded buffer and an out-of-bounds send, and that queued output stays unsent on the pass that receives a disconnect. ConnResetIoSend moves to the shared doubles beside a new OobIoSend.
1 parent d7b6e2a commit d95204d

2 files changed

Lines changed: 15 additions & 22 deletions

File tree

src/ssh.c

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3704,25 +3704,14 @@ int wolfSSH_worker(WOLFSSH* ssh, word32* channelId)
37043704
if (ret == WS_SUCCESS) {
37053705
ret = sendRet;
37063706
}
3707-
else if (rxErr != WS_WANT_READ
3708-
&& ssh->outputBuffer.length != 0) {
3709-
/* ret still reports the receive, so put the receive's status
3710-
* back */
3707+
else if (ret == WS_FATAL_ERROR && rxErr != WS_WANT_READ) {
3708+
/* Only a failed receive outranks the flush. A status return
3709+
* keeps the send's code */
37113710
ssh->error = rxErr;
37123711
}
37133712
}
37143713
}
37153714

3716-
/* DoChannelClose() bundles the reply inside DoReceive(), and callers
3717-
* treat the close as terminal, so flush it here. The close stays the
3718-
* return value; a short flush leaves WS_WANT_WRITE latched. */
3719-
if (ret == WS_CHANNEL_CLOSED && ssh->outputBuffer.length != 0) {
3720-
int closeErr = ssh->error;
3721-
3722-
if (wolfSSH_SendPacket(ssh) == WS_SUCCESS)
3723-
ssh->error = closeErr;
3724-
}
3725-
37263715
/* WS_EXTDATA and WS_EOF report the channel too, so a multi-channel caller
37273716
* can route the drain, or see which channel half-closed. */
37283717
if (ret == WS_SUCCESS || ret == WS_CHAN_RXD || ret == WS_EXTDATA

tests/unit.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6571,10 +6571,10 @@ static int test_WorkerHardSendErrorOnIdleReceive(void)
65716571
return result;
65726572
}
65736573

6574-
/* Channel data arrives and the flush fails on the same call.
6575-
* wolfSSH_worker() returns WS_CHAN_RXD so the caller can read the data.
6576-
* The next call puts the send failure in ssh->error. */
6577-
static int test_WorkerChanRxdOutranksHardSendError(void)
6574+
/* Channel data arrives and the flush fails on the same call. ret carries
6575+
* WS_CHAN_RXD so the caller reads the data, and ssh->error carries the send
6576+
* failure: wolfssh/ssh.h has the flush status supersede the receive's. */
6577+
static int test_WorkerChanRxdSurfacesSendError(void)
65786578
{
65796579
WOLFSSH_CTX* ctx = NULL;
65806580
WOLFSSH* ssh = NULL;
@@ -6614,10 +6614,14 @@ static int test_WorkerChanRxdOutranksHardSendError(void)
66146614

66156615
ret = wolfSSH_worker(ssh, NULL);
66166616
if (ret != WS_CHAN_RXD) { result = -1755; goto done; }
6617-
if (wolfSSH_get_error(ssh) != WS_CHAN_RXD) { result = -1756; goto done; }
6617+
if (wolfSSH_get_error(ssh) != WS_SOCKET_ERROR_E) {
6618+
result = -1756;
6619+
goto done;
6620+
}
6621+
/* A reset does not discard, so the bytes stay owed. */
66186622
if (ssh->outputBuffer.length == 0) { result = -1757; goto done; }
66196623

6620-
/* No data this time, so ssh->error now holds the send failure. */
6624+
/* And the failure persists rather than being a one-pass artefact. */
66216625
ret = wolfSSH_worker(ssh, NULL);
66226626
if (ret != WS_FATAL_ERROR) { result = -1758; goto done; }
66236627
if (wolfSSH_get_error(ssh) != WS_SOCKET_ERROR_E) {
@@ -20498,8 +20502,8 @@ int wolfSSH_UnitTest(int argc, char** argv)
2049820502
(unitResult == 0 ? "SUCCESS" : "FAILED"));
2049920503
testResult = testResult || unitResult;
2050020504

20501-
unitResult = test_WorkerChanRxdOutranksHardSendError();
20502-
printf("WorkerChanRxdOutranksHardSendError: %s\n",
20505+
unitResult = test_WorkerChanRxdSurfacesSendError();
20506+
printf("WorkerChanRxdSurfacesSendError: %s\n",
2050320507
(unitResult == 0 ? "SUCCESS" : "FAILED"));
2050420508
testResult = testResult || unitResult;
2050520509

0 commit comments

Comments
 (0)