mirror of https://github.com/wolfSSL/wolfssh.git
Bound the client's queued send flush and let a rekey through
FlushQueuedSend() retried wolfSSH_worker() for as long as it reported WS_WANT_WRITE. A peer that stops reading never lets the socket drain, so the sending thread spun there, and at the shutdown drain that thread was main, leaving the client unable to exit. - Give the retry a ten second deadline - Return the still pending WS_WANT_WRITE to the caller - Take that for done at the shutdown drain, the socket closes next - Mask WS_REKEYING, the worker only reports it once the send is out, and readInput() was taking it for a send failurepull/1171/head
parent
62c0e2efa5
commit
7d43f9e189
|
|
@ -74,9 +74,8 @@
|
|||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#ifndef WOLFSSH_NO_TIMESTAMP
|
||||
#include <time.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef WOLFSSH_CERTS
|
||||
#include <wolfssl/wolfcrypt/asn.h>
|
||||
|
|
@ -303,14 +302,21 @@ static void PauseForSocket(void)
|
|||
}
|
||||
|
||||
|
||||
/* Seconds to keep pushing a queued packet at a peer that isn't reading. A
|
||||
* busy peer gets time to come back, a stalled one doesn't hang the client. */
|
||||
#define FLUSH_QUEUE_TIMEOUT 10
|
||||
|
||||
|
||||
/* A packet the socket wasn't ready for stays queued in the session, and the
|
||||
* send that queued it still reports the data as taken. The peer can't answer
|
||||
* a message it never received, so push the queue out here rather than go
|
||||
* back to waiting on the peer. The lock is NULL when no other thread is
|
||||
* using the session. */
|
||||
* using the session. Returns WS_WANT_WRITE with the packet still queued when
|
||||
* the peer stops reading for the whole timeout. */
|
||||
static int FlushQueuedSend(WOLFSSH* ssh, wolfSSL_Mutex* lock)
|
||||
{
|
||||
int ret;
|
||||
time_t deadline = WTIME(NULL) + FLUSH_QUEUE_TIMEOUT;
|
||||
|
||||
do {
|
||||
PauseForSocket();
|
||||
|
|
@ -326,11 +332,13 @@ static int FlushQueuedSend(WOLFSSH* ssh, wolfSSL_Mutex* lock)
|
|||
if (lock != NULL) {
|
||||
wc_UnLockMutex(lock);
|
||||
}
|
||||
} while (ret == WS_WANT_WRITE);
|
||||
} while (ret == WS_WANT_WRITE && WTIME(NULL) < deadline);
|
||||
|
||||
/* The queue is out. Whatever the worker made of the peer's end of the
|
||||
* conversation is for the reader to sort out. */
|
||||
if (ret == WS_WANT_READ || ret == WS_CHAN_RXD || ret == WS_EXTDATA) {
|
||||
* conversation is for the reader to sort out. A rekey started on the way
|
||||
* through is the reader's as well, the send itself went out. */
|
||||
if (ret == WS_WANT_READ || ret == WS_CHAN_RXD || ret == WS_EXTDATA
|
||||
|| ret == WS_REKEYING) {
|
||||
ret = WS_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -1321,6 +1329,11 @@ static THREAD_RETURN WOLFSSH_THREAD wolfSSH_Client(void* args)
|
|||
/* The close messages are queued and the threads are done, no
|
||||
* one else is going to send them. */
|
||||
ret = FlushQueuedSend(ssh, NULL);
|
||||
if (ret == WS_WANT_WRITE) {
|
||||
/* The peer stopped reading. The socket closes next, there is
|
||||
* nothing left to push the messages out with. */
|
||||
ret = WS_SUCCESS;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue