diff --git a/examples/echoserver/echoserver.c b/examples/echoserver/echoserver.c index 38e2441e..ce855862 100644 --- a/examples/echoserver/echoserver.c +++ b/examples/echoserver/echoserver.c @@ -789,6 +789,20 @@ static int ssh_worker(thread_ctx_t* threadCtx) } #endif } + else if (rc == WS_CHANNEL_CLOSED) { + #ifdef WOLFSSH_FWD + /* Read zero-returned. Socket is closed. Go back + to listening. */ + WCLOSESOCKET(fwdFd); + fwdFd = -1; + if (threadCtx->fwdCbCtx.hostName != NULL) { + free(threadCtx->fwdCbCtx.hostName); + threadCtx->fwdCbCtx.hostName = NULL; + } + threadCtx->fwdCbCtx.state = FWD_STATE_LISTEN; + #endif + continue; + } else if (rc != WS_WANT_READ) { #ifdef SHELL_DEBUG printf("Break:read sshFd returns %d: errno =%x\n", diff --git a/src/internal.c b/src/internal.c index 6387a756..10a7eb5c 100644 --- a/src/internal.c +++ b/src/internal.c @@ -4767,7 +4767,8 @@ static int DoGlobalRequestFwd(WOLFSSH* ssh, if (ret == WS_SUCCESS) { if (ssh->ctx->fwdCb) { - ret = ssh->ctx->fwdCb(WOLFSSH_FWD_REMOTE_SETUP, + ret = ssh->ctx->fwdCb(isCancel ? WOLFSSH_FWD_REMOTE_CLEANUP : + WOLFSSH_FWD_REMOTE_SETUP, ssh->fwdCbCtx, bindAddr, bindPort); } } @@ -5129,8 +5130,13 @@ static int DoChannelEof(WOLFSSH* ssh, ret = WS_INVALID_CHANID; } - if (ret == WS_SUCCESS) - channel->receivedEof = 1; + if (ret == WS_SUCCESS) { + channel->eofRxd = 1; + if (!channel->eofTxd) { + ret = SendChannelEof(ssh, channel->peerChannel); + } + ssh->lastRxId = channelId; + } WLOG(WS_LOG_DEBUG, "Leaving DoChannelEof(), ret = %d", ret); return ret; @@ -5158,7 +5164,9 @@ static int DoChannelClose(WOLFSSH* ssh, } if (ret == WS_SUCCESS) { - ret = SendChannelClose(ssh, channel->peerChannel); + if (!channel->closeTxd) { + ret = SendChannelClose(ssh, channel->peerChannel); + } } if (ret == WS_SUCCESS) { @@ -5167,6 +5175,7 @@ static int DoChannelClose(WOLFSSH* ssh, if (ret == WS_SUCCESS) { ret = WS_CHANNEL_CLOSED; + ssh->lastRxId = channelId; } WLOG(WS_LOG_DEBUG, "Leaving DoChannelClose(), ret = %d", ret); @@ -5715,22 +5724,17 @@ static int DoPacket(WOLFSSH* ssh) ret = SendUnimplemented(ssh); } - if (ret == WS_SUCCESS || ret == WS_CHAN_RXD || ret == WS_EXTDATA) { - if (payloadSz > 0){ - idx += payloadIdx; - if (idx + padSz > len) - { - WLOG(WS_LOG_DEBUG, "Not enough data in buffer for pad."); - ret = WS_BUFFER_E; - } + if (payloadSz > 0) { + idx += payloadIdx; + if (idx + padSz > len) { + WLOG(WS_LOG_DEBUG, "Not enough data in buffer for pad."); + ret = WS_BUFFER_E; } } - if (ret == WS_SUCCESS || ret == WS_CHAN_RXD || ret == WS_EXTDATA) { - idx += padSz; - ssh->inputBuffer.idx = idx; - ssh->peerSeq++; - } + idx += padSz; + ssh->inputBuffer.idx = idx; + ssh->peerSeq++; return ret; } @@ -9337,6 +9341,14 @@ int SendChannelEof(WOLFSSH* ssh, word32 peerChannelId) ret = WS_INVALID_CHANID; } + if (ret == WS_SUCCESS) { + if (channel->eofTxd) { + WLOG(WS_LOG_DEBUG, "Already sent EOF"); + WLOG(WS_LOG_DEBUG, "Leaving SendChannelEof(), ret = %d", ret); + return ret; + } + } + if (ret == WS_SUCCESS) ret = PreparePacket(ssh, MSG_ID_SZ + UINT32_SZ); @@ -9356,6 +9368,9 @@ int SendChannelEof(WOLFSSH* ssh, word32 peerChannelId) if (ret == WS_SUCCESS) ret = wolfSSH_SendPacket(ssh); + if (ret == WS_SUCCESS) + channel->eofTxd = 1; + WLOG(WS_LOG_DEBUG, "Leaving SendChannelEof(), ret = %d", ret); return ret; } @@ -9482,7 +9497,7 @@ int SendChannelClose(WOLFSSH* ssh, word32 peerChannelId) channel = ChannelFind(ssh, peerChannelId, WS_CHANNEL_ID_PEER); if (channel == NULL) ret = WS_INVALID_CHANID; - else if (channel->closeSent) { + else if (channel->closeTxd) { WLOG(WS_LOG_DEBUG, "Leaving SendChannelClose(), already sent"); return ret; } @@ -9506,7 +9521,7 @@ int SendChannelClose(WOLFSSH* ssh, word32 peerChannelId) if (ret == WS_SUCCESS) { ret = wolfSSH_SendPacket(ssh); - channel->closeSent = 1; + channel->closeTxd = 1; } WLOG(WS_LOG_DEBUG, "Leaving SendChannelClose(), ret = %d", ret); diff --git a/src/ssh.c b/src/ssh.c index 5e382a80..d2d2b237 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -1036,7 +1036,7 @@ int wolfSSH_stream_read(WOLFSSH* ssh, byte* buf, word32 bufSz) if (ret == WS_SUCCESS) { while (inputBuffer->length - inputBuffer->idx == 0) { ret = DoReceive(ssh); - if (ssh->channelList == NULL || ssh->channelList->receivedEof) + if (ssh->channelList == NULL || ssh->channelList->eofRxd) ret = WS_EOF; if (ret < 0 && ret != WS_CHAN_RXD) { break; @@ -1767,12 +1767,12 @@ int wolfSSH_worker(WOLFSSH* ssh, word32* channelId) } /* Attempt to receive data from the peer. */ - if (ret == WS_SUCCESS) + if (ret == WS_SUCCESS) { ret = DoReceive(ssh); + } - if (ret == WS_CHAN_RXD) { - if (channelId != NULL) - *channelId = ssh->lastRxId; + if (channelId != NULL && ssh != NULL) { + *channelId = ssh->lastRxId; } if (ret == WS_CHAN_RXD) @@ -2127,7 +2127,7 @@ int wolfSSH_ChannelGetEof(WOLFSSH_CHANNEL* channel) WLOG(WS_LOG_DEBUG, "Entering wolfSSH_ChannelGetEof()"); if (channel) - eof = (int)channel->receivedEof; + eof = (int)channel->eofRxd; WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_ChannelGetEof(), %s", eof ? "true" : "false"); diff --git a/wolfssh/internal.h b/wolfssh/internal.h index fe1821cf..d7dea9c2 100644 --- a/wolfssh/internal.h +++ b/wolfssh/internal.h @@ -701,9 +701,11 @@ struct WOLFSSH { struct WOLFSSH_CHANNEL { byte channelType; byte sessionType; - byte closeSent; - byte receivedEof; - byte openConfirmed; + byte closeRxd : 1; + byte closeTxd : 1; + byte eofRxd : 1; + byte eofTxd : 1; + byte openConfirmed : 1; word32 channel; word32 windowSz; word32 maxPacketSz;