mirror of https://github.com/wolfSSL/wolfssh.git
Report a disconnect from stream_peek
wolfSSH_stream_peek() is how the shell loops decide whether a channel is drained. It had no disconnect check, so a dead session looked exactly like a drained one: zero bytes available, nothing to tell them apart. - Report WS_DISCONNECT once the buffered data runs dry, the same shape wolfSSH_stream_read() uses. What is still buffered comes back first. - ssh.h and internal.h name peek alongside the read call, and no longer claim the read side is ungated outright. - regress.c: peek sees the buffered byte, then sees the disconnect. Raised from the channel-eof branch, where peek becomes the drain gate for the wolfsshd and echoserver shell loops. Issue: F-8837pull/1192/head
parent
285e0409cf
commit
bac3c8ba37
16
src/ssh.c
16
src/ssh.c
|
|
@ -1198,6 +1198,7 @@ int wolfSSH_TriggerKeyExchange(WOLFSSH* ssh)
|
|||
int wolfSSH_stream_peek(WOLFSSH* ssh, byte* buf, word32 bufSz)
|
||||
{
|
||||
WOLFSSH_BUFFER* inputBuffer;
|
||||
word32 avail;
|
||||
|
||||
WLOG(WS_LOG_DEBUG, "Entering wolfSSH_stream_peek()");
|
||||
|
||||
|
|
@ -1214,11 +1215,22 @@ int wolfSSH_stream_peek(WOLFSSH* ssh, byte* buf, word32 bufSz)
|
|||
}
|
||||
|
||||
inputBuffer = &ssh->channelList->inputBuffer;
|
||||
bufSz = min(bufSz, inputBuffer->length - inputBuffer->idx);
|
||||
avail = inputBuffer->length - inputBuffer->idx;
|
||||
|
||||
/* Report the disconnect only once the buffered data is drained, the
|
||||
* same way wolfSSH_stream_read() does. Callers use this to tell a
|
||||
* drained channel from one with more to come, and a dead session is
|
||||
* neither. */
|
||||
if (avail == 0 && ssh->disconnected) {
|
||||
ssh->error = WS_DISCONNECT;
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
bufSz = min(bufSz, avail);
|
||||
if (buf != NULL) {
|
||||
WMEMCPY(buf, inputBuffer->buffer + inputBuffer->idx, bufSz);
|
||||
}
|
||||
return bufSz;
|
||||
return (int)bufSz;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -3004,12 +3004,21 @@ static void TestDisconnectDrainsBufferedData(void)
|
|||
AssertIntEQ(wolfSSH_get_error(ssh), WS_DISCONNECT);
|
||||
AssertTrue(ssh->disconnected);
|
||||
|
||||
/* Peek is the drain gate the shell loops use, so it has to tell a
|
||||
* channel with data left from a session that is over. */
|
||||
ret = wolfSSH_stream_peek(ssh, NULL, 1);
|
||||
AssertIntEQ(ret, 1);
|
||||
|
||||
WMEMSET(data, 0, sizeof(data));
|
||||
ret = wolfSSH_stream_read(ssh, data, sizeof(data));
|
||||
AssertIntEQ(ret, (int)sizeof(payload));
|
||||
AssertIntEQ(WMEMCMP(data, payload, sizeof(payload)), 0);
|
||||
|
||||
/* Buffer is dry now, so the disconnect is what is left to report. */
|
||||
ret = wolfSSH_stream_peek(ssh, NULL, 1);
|
||||
AssertIntEQ(ret, WS_FATAL_ERROR);
|
||||
AssertIntEQ(wolfSSH_get_error(ssh), WS_DISCONNECT);
|
||||
|
||||
ret = wolfSSH_stream_read(ssh, data, sizeof(data));
|
||||
AssertIntEQ(ret, WS_FATAL_ERROR);
|
||||
AssertIntEQ(wolfSSH_get_error(ssh), WS_DISCONNECT);
|
||||
|
|
|
|||
|
|
@ -1103,10 +1103,10 @@ struct WOLFSSH {
|
|||
byte connReset;
|
||||
byte isClosed;
|
||||
/* Set when a DISCONNECT is sent or received. Gates every public send
|
||||
* call, so
|
||||
* nothing more goes out. The read calls are not gated: data that
|
||||
* arrived before the disconnect can still be drained. wolfSSH_worker()
|
||||
* is not gated either, since the shutdown paths still pump it. */
|
||||
* call, so nothing more goes out. Reads still hand back what arrived
|
||||
* before the disconnect; the head-of-list reads report it once their
|
||||
* buffer runs dry. wolfSSH_worker() is not gated, the shutdown paths
|
||||
* pump it. */
|
||||
byte disconnected;
|
||||
byte clientOpenSSH;
|
||||
|
||||
|
|
|
|||
|
|
@ -562,8 +562,8 @@ WOLFSSH_API int wolfSSH_shutdown(WOLFSSH* ssh);
|
|||
* every send call in this header, above this comment and below it,
|
||||
* reports WS_DISCONNECT from then on. Reads are not
|
||||
* gated, so channel data that arrived before the disconnect can still be
|
||||
* drained; wolfSSH_stream_read() reports WS_DISCONNECT once its buffer
|
||||
* runs dry. RFC 4253 section 11.1. */
|
||||
* drained; wolfSSH_stream_read() and wolfSSH_stream_peek() report
|
||||
* WS_DISCONNECT once their buffer runs dry. RFC 4253 section 11.1. */
|
||||
WOLFSSH_API int wolfSSH_stream_peek(WOLFSSH* ssh, byte* buf, word32 bufSz);
|
||||
WOLFSSH_API int wolfSSH_stream_read(WOLFSSH* ssh, byte* buf, word32 bufSz);
|
||||
WOLFSSH_API int wolfSSH_stream_send(WOLFSSH* ssh, byte* buf, word32 bufSz);
|
||||
|
|
|
|||
Loading…
Reference in New Issue