Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 80 additions & 23 deletions examples/echoserver/echoserver.c
Original file line number Diff line number Diff line change
Expand Up @@ -1132,11 +1132,21 @@ static int sftp_worker(thread_ctx_t* threadCtx)
WS_SOCKET_T sockfd;
int select_ret = 0;

error = wolfSSH_get_error(threadCtx->ssh);
sockfd = (WS_SOCKET_T)wolfSSH_get_fd(threadCtx->ssh);
do {
if (threadCtx->nonBlock) {
if (error == WS_WANT_READ)
if (error == WS_WANT_READ) {
WOLFSSH_CHANNEL* c;
printf("... sftp server would read block\n");

/* if all channels are closed then close connection */
c = wolfSSH_ChannelNext(threadCtx->ssh, NULL);
if (c && wolfSSH_ChannelGetEof(c)) {
ret = 0;
break;
}
}
else if (error == WS_WANT_WRITE) {
word32 c;
printf("... sftp server would write block\n");
Expand All @@ -1148,24 +1158,31 @@ static int sftp_worker(thread_ctx_t* threadCtx)
}
}

if (wolfSSH_stream_peek(threadCtx->ssh, tmp, 1) > 0) {
select_ret = WS_SELECT_RECV_READY;
/* if there is a current send in progress then continue to process it */
if (wolfSSH_SFTP_PendingSend(threadCtx->ssh)) {
ret = wolfSSH_SFTP_read(threadCtx->ssh);
error = wolfSSH_get_error(threadCtx->ssh);
}
else {
select_ret = tcp_select(sockfd, TEST_SFTP_TIMEOUT);
}
if (wolfSSH_stream_peek(threadCtx->ssh, tmp, 1) > 0) {
select_ret = WS_SELECT_RECV_READY;
}
else {
select_ret = tcp_select(sockfd, TEST_SFTP_TIMEOUT);
}

if (select_ret == WS_SELECT_RECV_READY ||
select_ret == WS_SELECT_ERROR_READY ||
error == WS_WANT_WRITE)
{
ret = wolfSSH_SFTP_read(threadCtx->ssh);
error = wolfSSH_get_error(threadCtx->ssh);
if (select_ret == WS_SELECT_RECV_READY ||
select_ret == WS_SELECT_ERROR_READY ||
error == WS_WANT_WRITE)
{
ret = wolfSSH_SFTP_read(threadCtx->ssh);
error = wolfSSH_get_error(threadCtx->ssh);
}
else if (select_ret == WS_SELECT_TIMEOUT)
error = WS_WANT_READ;
else
error = WS_FATAL_ERROR;
}
else if (select_ret == WS_SELECT_TIMEOUT)
error = WS_WANT_READ;
else
error = WS_FATAL_ERROR;

if (error == WS_WANT_READ || error == WS_WANT_WRITE ||
error == WS_CHAN_RXD || error == WS_REKEYING ||
Expand All @@ -1181,7 +1198,7 @@ static int sftp_worker(thread_ctx_t* threadCtx)
}
}

} while (ret != WS_FATAL_ERROR);
} while (ret != WS_FATAL_ERROR && ret != WS_SOCKET_ERROR_E);

return ret;
}
Expand Down Expand Up @@ -1279,8 +1296,43 @@ static THREAD_RETURN WOLFSSH_THREAD server_worker(void* vArgs)
}

if (error != WS_SOCKET_ERROR_E && error != WS_FATAL_ERROR) {
if (wolfSSH_shutdown(threadCtx->ssh) != WS_SUCCESS) {
fprintf(stderr, "Error with SSH shutdown.\n");
ret = wolfSSH_shutdown(threadCtx->ssh);

/* peer hung up, stop shutdown */
if (ret == WS_SOCKET_ERROR_E) {
ret = 0;
}

error = wolfSSH_get_error(threadCtx->ssh);
if (error != WS_SOCKET_ERROR_E &&
(error == WS_WANT_READ || error == WS_WANT_WRITE)) {
int maxAttempt = 10; /* make 10 attempts max before giving up */
int attempt;

for (attempt = 0; attempt < maxAttempt; attempt++) {
ret = wolfSSH_worker(threadCtx->ssh, NULL);
error = wolfSSH_get_error(threadCtx->ssh);

/* peer succesfully closed down gracefully */
if (ret == WS_CHANNEL_CLOSED) {
ret = 0;
break;
}

/* peer hung up, stop shutdown */
if (ret == WS_SOCKET_ERROR_E) {
ret = 0;
break;
}

if (error != WS_WANT_READ && error != WS_WANT_WRITE) {
break;
}
}

if (attempt == maxAttempt) {
printf("Gave up on gracefull shutdown, closing the socket\n");
}
}
}

Expand Down Expand Up @@ -1838,11 +1890,16 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
break;

case 'p':
port = (word16)atoi(myoptarg);
#if !defined(NO_MAIN_DRIVER) || defined(USE_WINDOWS_API)
if (port == 0)
err_sys("port number cannot be 0");
#endif
if (myoptarg == NULL) {
err_sys("NULL port value");
}
else {
port = (word16)atoi(myoptarg);
#if !defined(NO_MAIN_DRIVER) || defined(USE_WINDOWS_API)
if (port == 0)
err_sys("port number cannot be 0");
#endif
}
break;

case 'R':
Expand Down
41 changes: 26 additions & 15 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -1148,7 +1148,7 @@ byte NameToId(const char* name, word32 nameSz)
word32 i;

for (i = 0; i < (sizeof(NameIdMap)/sizeof(NameIdPair)); i++) {
if (nameSz == WSTRLEN(NameIdMap[i].name) &&
if (nameSz == (word32)WSTRLEN(NameIdMap[i].name) &&
XMEMCMP(name, NameIdMap[i].name, nameSz) == 0) {

id = NameIdMap[i].id;
Expand Down Expand Up @@ -1436,6 +1436,12 @@ int ChannelPutData(WOLFSSH_CHANNEL* channel, byte* data, word32 dataSz)

inBuf = &channel->inputBuffer;

/* sanity check the current state to see if is too much data */
if (dataSz > channel->windowSz) {
WLOG(WS_LOG_ERROR, "Internal state error, too much data");
return WS_FATAL_ERROR;
}

if (inBuf->length < inBuf->bufferSz &&
inBuf->length + dataSz <= inBuf->bufferSz) {

Expand All @@ -1445,7 +1451,7 @@ int ChannelPutData(WOLFSSH_CHANNEL* channel, byte* data, word32 dataSz)
WLOG(WS_LOG_INFO, " dataSz = %u", dataSz);
WLOG(WS_LOG_INFO, " windowSz = %u", channel->windowSz);
channel->windowSz -= dataSz;
WLOG(WS_LOG_INFO, " windowSz = %u", channel->windowSz);
WLOG(WS_LOG_INFO, " update windowSz = %u", channel->windowSz);
}
else {
return WS_RECV_OVERFLOW_E;
Expand Down Expand Up @@ -9856,6 +9862,18 @@ int SendChannelData(WOLFSSH* ssh, word32 channelId,
ret = WS_REKEYING;
}

/* if already having data pending try to flush it first and do not continue
* to que more on fail */
if (ret == WS_SUCCESS && ssh->outputBuffer.plainSz > 0) {
WLOG(WS_LOG_DEBUG, "Flushing out want write data");
ret = wolfSSH_SendPacket(ssh);
if (ret != WS_SUCCESS) {
WLOG(WS_LOG_DEBUG, "Leaving SendChannelData(), ret = %d", ret);
return ret;
}

}

if (ret == WS_SUCCESS) {
if (ssh->outputBuffer.length != 0)
ret = wolfSSH_SendPacket(ssh);
Expand Down Expand Up @@ -9914,10 +9932,12 @@ int SendChannelData(WOLFSSH* ssh, word32 channelId,
WLOG(WS_LOG_INFO, " update peerWindowSz = %u", channel->peerWindowSz);
}

/* at this point the data has been loaded into WOLFSSH structure and is
* considered consumed */
if (ret == WS_SUCCESS)
ret = wolfSSH_SendPacket(ssh);

if (ret == WS_SUCCESS)
if (ret == WS_SUCCESS || ret == WS_WANT_WRITE)
ret = dataSz;

if (ssh && ssh->error == WS_WANT_WRITE)
Expand Down Expand Up @@ -10453,18 +10473,9 @@ int wolfSSH_CleanPath(WOLFSSH* ssh, char* in)
if (path[i] == '/') path[i] = '\\';
}
#endif
sz = (long)WSTRLEN(path);

/* remove any ./ patterns */
for (i = 1; i < sz - 1; i++) {
if (path[i] == '.' && path[i - 1] != '.' && path[i + 1] == WS_DELIM) {
WMEMMOVE(path + i, path + i + 1, sz - i - 1);
path[sz - 1] = '\0';
i--;
}
}
sz = (int)WSTRLEN(path);

/* remove any /./ patterns */
/* remove any /./ patterns, direcotries, exclude cases like ./ok./test */
for (i = 1; i + 1 < sz; i++) {
if (path[i] == '.' && path[i - 1] == WS_DELIM && path[i + 1] == WS_DELIM) {
WMEMMOVE(path + i, path + i + 1, sz - i + 1);
Expand Down Expand Up @@ -10583,7 +10594,7 @@ int wolfSSH_CleanPath(WOLFSSH* ssh, char* in)
WFREE(path, ssh->ctx->heap, DYNTYPE_PATH);
return WS_BUFFER_E;
}
sz = WSTRLEN(path);
sz = (long)WSTRLEN(path);
WMEMCPY(in, path, sz);
in[sz] = '\0';
WFREE(path, ssh->ctx->heap, DYNTYPE_PATH);
Expand Down
5 changes: 1 addition & 4 deletions src/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -404,11 +404,7 @@ int wsEmbedSend(WOLFSSH* ssh, void* data, word32 sz, void* ctx)
#endif /* MICROCHIP_MPLAB_HARMONY */

sent = (int)SEND_FUNCTION(sd, buf, sz, ssh->wflags);

sent = TranslateReturnCode(sent, sd);

WLOG(WS_LOG_DEBUG,"Embed Send sent %d", sent);

if (sent < 0) {
err = LastError();
WLOG(WS_LOG_DEBUG,"Embed Send error");
Expand All @@ -434,6 +430,7 @@ int wsEmbedSend(WOLFSSH* ssh, void* data, word32 sz, void* ctx)
return WS_CBIO_ERR_GENERAL;
}
}
WLOG(WS_LOG_DEBUG,"Embed Send sent %d", sent);
return sent;
}

Expand Down
38 changes: 21 additions & 17 deletions src/ssh.c
Original file line number Diff line number Diff line change
Expand Up @@ -947,10 +947,14 @@ int wolfSSH_shutdown(WOLFSSH* ssh)
if (ret == WS_SUCCESS)
ret = SendChannelEof(ssh, ssh->channelList->peerChannel);

if (ret == WS_SUCCESS)
/* continue on success and in case where queing up send packets */
if (ret == WS_SUCCESS ||
(ret != WS_BAD_ARGUMENT && ssh->error == WS_WANT_WRITE))
ret = SendChannelExit(ssh, ssh->channelList->peerChannel, 0);

if (ret == WS_SUCCESS)
/* continue on success and in case where queing up send packets */
if (ret == WS_SUCCESS ||
(ret != WS_BAD_ARGUMENT && ssh->error == WS_WANT_WRITE))
ret = SendChannelClose(ssh, ssh->channelList->peerChannel);

if (ssh != NULL && ssh->channelList == NULL) {
Expand Down Expand Up @@ -1013,14 +1017,21 @@ static int wolfSSH_stream_adjust_window(WOLFSSH* ssh)
bytesToAdd = inputBuffer->idx;

WLOG(WS_LOG_DEBUG, "Making more room: %u", usedSz);
WLOG(WS_LOG_DEBUG, " Current index into buffer = %u", inputBuffer->idx);
WLOG(WS_LOG_DEBUG, " Current max index for available data = %u",
inputBuffer->length);
WLOG(WS_LOG_DEBUG, " Current total buffer size = %u",
inputBuffer->bufferSz);
if (usedSz) {
WLOG(WS_LOG_DEBUG, " ...moving data down");
WLOG(WS_LOG_DEBUG, " ...moving %d used bytes down", usedSz);
WMEMMOVE(inputBuffer->buffer, inputBuffer->buffer + bytesToAdd, usedSz);
inputBuffer->length = usedSz;
inputBuffer->idx = 0;
}

ret = SendChannelWindowAdjust(ssh, ssh->channelList->channel,
bytesToAdd);
if (ret != WS_SUCCESS) {
if (ret != WS_SUCCESS && ret != WS_WANT_WRITE) {
WLOG(WS_LOG_ERROR, "Error adjusting window");
}
else {
Expand Down Expand Up @@ -1065,7 +1076,11 @@ int wolfSSH_stream_read(WOLFSSH* ssh, byte* buf, word32 bufSz)


if (ret == WS_SUCCESS) {
WLOG(WS_LOG_DEBUG, " Stream read index of %u", inputBuffer->idx);
WLOG(WS_LOG_DEBUG, " Stream read ava data %u", inputBuffer->length);
while (inputBuffer->length - inputBuffer->idx == 0) {
WLOG(WS_LOG_DEBUG, "Starting to recieve data at current index of %u",
inputBuffer->idx);
ret = DoReceive(ssh);
if (ssh->channelList == NULL || ssh->channelList->eofRxd)
ret = WS_EOF;
Expand Down Expand Up @@ -1109,19 +1124,6 @@ int wolfSSH_stream_send(WOLFSSH* ssh, byte* buf, word32 bufSz)
if (ssh == NULL || buf == NULL || ssh->channelList == NULL)
return WS_BAD_ARGUMENT;

/* case of WANT WRITE and data stored in output buffer */
if (ssh->outputBuffer.plainSz && ssh->outputBuffer.length != 0) {
int ret;

bytesTxd = ssh->outputBuffer.plainSz;
WLOG(WS_LOG_DEBUG, "Trying to resend %d bytes", bytesTxd);
ssh->error = WS_SUCCESS;
ret = wolfSSH_SendPacket(ssh);

/* return the amount sent on success otherwise return error found */
return (ret == WS_SUCCESS)? bytesTxd : ret;
}

bytesTxd = SendChannelData(ssh, ssh->channelList->channel, buf, bufSz);

WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_stream_send(), txd = %d", bytesTxd);
Expand Down Expand Up @@ -2029,6 +2031,8 @@ static int _UpdateChannelWindow(WOLFSSH_CHANNEL* channel)
WLOG(WS_LOG_DEBUG, " ...moving data down");
WMEMMOVE(inputBuffer->buffer,
inputBuffer->buffer + bytesToAdd, usedSz);
inputBuffer->length = usedSz;
inputBuffer->idx = 0;
}

sendResult = SendChannelWindowAdjust(channel->ssh, channel->channel,
Expand Down
Loading