Skip to content

Commit 31f831b

Browse files
ejohnstownphilljj
authored andcommitted
portfwd: drain the buffer before leaving on EOF
A zero read on the local socket left the loop at once, and anything read but not yet accepted by wolfSSH_ChannelSend() went with it. With the peer's window full that tail is up to a buffer's worth, so a transfer that ends while the window is being credited comes out short. - stop polling the socket on end-of-input and keep looping until the buffer is empty - leave anyway once the channel is gone, so a forward whose open failed cannot hold the loop on a buffer nothing can take
1 parent ee7fa04 commit 31f831b

1 file changed

Lines changed: 12 additions & 2 deletions

File tree

examples/portfwd/portfwd.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,7 @@ THREAD_RETURN WOLFSSH_THREAD portfwd_worker(void* args)
432432
int ch;
433433
int appFdSet = 0;
434434
int appFdHalfClosed = 0;
435+
int appEof = 0;
435436
int reverse = 0;
436437
int fwdFromPortSet = 0;
437438
PortfwdState fwdState;
@@ -728,8 +729,12 @@ THREAD_RETURN WOLFSSH_THREAD portfwd_worker(void* args)
728729
appBuffer + appBufferUsed, appBufferSz - appBufferUsed, 0);
729730
if (rxd > 0)
730731
appBufferUsed += rxd;
731-
else
732-
break;
732+
else {
733+
/* Local end-of-input. Stop polling the socket and leave once
734+
* what is buffered has gone out; leaving now would drop it. */
735+
appEof = 1;
736+
FD_CLR(appFd, &templateFds);
737+
}
733738
}
734739
if (FD_ISSET(sshFd, &rxFds)) {
735740
word32 channelId = 0;
@@ -868,6 +873,11 @@ THREAD_RETURN WOLFSSH_THREAD portfwd_worker(void* args)
868873
#endif
869874
}
870875
}
876+
/* Nothing left to hand over, or nothing left to hand it to: without
877+
* the channel check a failed open would leave the buffer forever
878+
* unsendable and the loop with no way out. */
879+
if (appEof && (appBufferUsed == 0 || fwdChannel == NULL))
880+
break;
871881
}
872882

873883
if (reverse) {

0 commit comments

Comments
 (0)