Skip to content

Commit 04128a7

Browse files
committed
echoserver: let the cleanup callback tear down
WOLFSSH_FWD_LOCAL_CLEANUP now runs, and it runs from DoChannelClose() ahead of the WS_CHANNEL_CLOSED the worker sees. The handler has already closed the socket and moved the state on by then, so the recovery branch no longer matched and left ssh_worker() holding a closed descriptor. - guard the handler's close: the open can fail after the setup, with nothing yet connected - have the recovery branch clear its stale copy of the descriptor when the handler got there first, and still do the whole teardown for a locally opened forward, which draws no callback - clear the pending direct connect as well: it is only cleared on success, so a refused target left it set and the worker connected again with the host name the handler had just freed
1 parent cfa9794 commit 04128a7

1 file changed

Lines changed: 30 additions & 14 deletions

File tree

examples/echoserver/echoserver.c

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -508,8 +508,12 @@ static int wolfSSH_FwdDefaultActions(WS_FwdCbAction action, void* vCtx,
508508
appCtx->state = APP_STATE_CONNECT;
509509
}
510510
else if (action == WOLFSSH_FWD_LOCAL_CLEANUP) {
511-
WCLOSESOCKET(appCtx->appFd);
512-
appCtx->appFd = -1;
511+
/* This runs now, so the socket may already be gone: the open can
512+
* fail after the setup, before anything connected. */
513+
if (appCtx->appFd != (WS_SOCKET_T)-1) {
514+
WCLOSESOCKET(appCtx->appFd);
515+
appCtx->appFd = -1;
516+
}
513517
if (fwdCbCtx->hostName) {
514518
WFREE(fwdCbCtx->hostName, NULL, 0);
515519
fwdCbCtx->hostName = NULL;
@@ -518,6 +522,8 @@ static int wolfSSH_FwdDefaultActions(WS_FwdCbAction action, void* vCtx,
518522
WFREE(fwdCbCtx->originName, NULL, 0);
519523
fwdCbCtx->originName = NULL;
520524
}
525+
/* A refused connect leaves this set; retire it with the channel. */
526+
fwdCbCtx->isDirect = 0;
521527
appCtx->state = APP_STATE_INIT;
522528
}
523529
else if (action == WOLFSSH_FWD_REMOTE_SETUP) {
@@ -1181,21 +1187,31 @@ static int ssh_worker(thread_ctx_t* threadCtx)
11811187
}
11821188
else if (rc == WS_CHANNEL_CLOSED) {
11831189
#ifdef WOLFSSH_FWD
1184-
if (threadCtx->fwdCtx.state == APP_STATE_CONNECTED &&
1185-
lastChannel == threadCtx->fwdCtx.channelId) {
1186-
/* Read zero-returned. Socket is closed. Go back
1187-
to listening. */
1188-
if (fwdFd != -1) {
1189-
WCLOSESOCKET(fwdFd);
1190+
if (lastChannel == threadCtx->fwdCtx.channelId) {
1191+
if (threadCtx->fwdCtx.appFd == -1) {
1192+
/* The LOCAL_CLEANUP handler ran ahead of
1193+
* this and closed the socket; only this
1194+
* copy of the descriptor is stale. */
11901195
fwdFd = -1;
1191-
threadCtx->fwdCtx.appFd = -1;
11921196
}
1193-
if (threadCtx->fwdCbCtx.originName != NULL) {
1194-
WFREE(threadCtx->fwdCbCtx.originName,
1195-
NULL, 0);
1196-
threadCtx->fwdCbCtx.originName = NULL;
1197+
else if (threadCtx->fwdCtx.state
1198+
== APP_STATE_CONNECTED) {
1199+
/* A locally opened forward is armed by no
1200+
* LOCAL_SETUP and so draws no cleanup. Its
1201+
* teardown is still ours: go back to
1202+
* listening. */
1203+
if (fwdFd != -1) {
1204+
WCLOSESOCKET(fwdFd);
1205+
fwdFd = -1;
1206+
threadCtx->fwdCtx.appFd = -1;
1207+
}
1208+
if (threadCtx->fwdCbCtx.originName != NULL) {
1209+
WFREE(threadCtx->fwdCbCtx.originName,
1210+
NULL, 0);
1211+
threadCtx->fwdCbCtx.originName = NULL;
1212+
}
1213+
threadCtx->fwdCtx.state = APP_STATE_LISTEN;
11971214
}
1198-
threadCtx->fwdCtx.state = APP_STATE_LISTEN;
11991215
}
12001216
#endif
12011217
continue;

0 commit comments

Comments
 (0)