Skip to content

Commit a0da4e3

Browse files
authored
Merge pull request #431 from JacobBarthelmeh/sftp
handle files with . in name and fix for window resize want write case
2 parents 7c1fd84 + 941a295 commit a0da4e3

6 files changed

Lines changed: 169 additions & 110 deletions

File tree

examples/echoserver/echoserver.c

Lines changed: 80 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1132,11 +1132,21 @@ static int sftp_worker(thread_ctx_t* threadCtx)
11321132
WS_SOCKET_T sockfd;
11331133
int select_ret = 0;
11341134

1135+
error = wolfSSH_get_error(threadCtx->ssh);
11351136
sockfd = (WS_SOCKET_T)wolfSSH_get_fd(threadCtx->ssh);
11361137
do {
11371138
if (threadCtx->nonBlock) {
1138-
if (error == WS_WANT_READ)
1139+
if (error == WS_WANT_READ) {
1140+
WOLFSSH_CHANNEL* c;
11391141
printf("... sftp server would read block\n");
1142+
1143+
/* if all channels are closed then close connection */
1144+
c = wolfSSH_ChannelNext(threadCtx->ssh, NULL);
1145+
if (c && wolfSSH_ChannelGetEof(c)) {
1146+
ret = 0;
1147+
break;
1148+
}
1149+
}
11401150
else if (error == WS_WANT_WRITE) {
11411151
word32 c;
11421152
printf("... sftp server would write block\n");
@@ -1148,24 +1158,31 @@ static int sftp_worker(thread_ctx_t* threadCtx)
11481158
}
11491159
}
11501160

1151-
if (wolfSSH_stream_peek(threadCtx->ssh, tmp, 1) > 0) {
1152-
select_ret = WS_SELECT_RECV_READY;
1161+
/* if there is a current send in progress then continue to process it */
1162+
if (wolfSSH_SFTP_PendingSend(threadCtx->ssh)) {
1163+
ret = wolfSSH_SFTP_read(threadCtx->ssh);
1164+
error = wolfSSH_get_error(threadCtx->ssh);
11531165
}
11541166
else {
1155-
select_ret = tcp_select(sockfd, TEST_SFTP_TIMEOUT);
1156-
}
1167+
if (wolfSSH_stream_peek(threadCtx->ssh, tmp, 1) > 0) {
1168+
select_ret = WS_SELECT_RECV_READY;
1169+
}
1170+
else {
1171+
select_ret = tcp_select(sockfd, TEST_SFTP_TIMEOUT);
1172+
}
11571173

1158-
if (select_ret == WS_SELECT_RECV_READY ||
1159-
select_ret == WS_SELECT_ERROR_READY ||
1160-
error == WS_WANT_WRITE)
1161-
{
1162-
ret = wolfSSH_SFTP_read(threadCtx->ssh);
1163-
error = wolfSSH_get_error(threadCtx->ssh);
1174+
if (select_ret == WS_SELECT_RECV_READY ||
1175+
select_ret == WS_SELECT_ERROR_READY ||
1176+
error == WS_WANT_WRITE)
1177+
{
1178+
ret = wolfSSH_SFTP_read(threadCtx->ssh);
1179+
error = wolfSSH_get_error(threadCtx->ssh);
1180+
}
1181+
else if (select_ret == WS_SELECT_TIMEOUT)
1182+
error = WS_WANT_READ;
1183+
else
1184+
error = WS_FATAL_ERROR;
11641185
}
1165-
else if (select_ret == WS_SELECT_TIMEOUT)
1166-
error = WS_WANT_READ;
1167-
else
1168-
error = WS_FATAL_ERROR;
11691186

11701187
if (error == WS_WANT_READ || error == WS_WANT_WRITE ||
11711188
error == WS_CHAN_RXD || error == WS_REKEYING ||
@@ -1181,7 +1198,7 @@ static int sftp_worker(thread_ctx_t* threadCtx)
11811198
}
11821199
}
11831200

1184-
} while (ret != WS_FATAL_ERROR);
1201+
} while (ret != WS_FATAL_ERROR && ret != WS_SOCKET_ERROR_E);
11851202

11861203
return ret;
11871204
}
@@ -1279,8 +1296,43 @@ static THREAD_RETURN WOLFSSH_THREAD server_worker(void* vArgs)
12791296
}
12801297

12811298
if (error != WS_SOCKET_ERROR_E && error != WS_FATAL_ERROR) {
1282-
if (wolfSSH_shutdown(threadCtx->ssh) != WS_SUCCESS) {
1283-
fprintf(stderr, "Error with SSH shutdown.\n");
1299+
ret = wolfSSH_shutdown(threadCtx->ssh);
1300+
1301+
/* peer hung up, stop shutdown */
1302+
if (ret == WS_SOCKET_ERROR_E) {
1303+
ret = 0;
1304+
}
1305+
1306+
error = wolfSSH_get_error(threadCtx->ssh);
1307+
if (error != WS_SOCKET_ERROR_E &&
1308+
(error == WS_WANT_READ || error == WS_WANT_WRITE)) {
1309+
int maxAttempt = 10; /* make 10 attempts max before giving up */
1310+
int attempt;
1311+
1312+
for (attempt = 0; attempt < maxAttempt; attempt++) {
1313+
ret = wolfSSH_worker(threadCtx->ssh, NULL);
1314+
error = wolfSSH_get_error(threadCtx->ssh);
1315+
1316+
/* peer succesfully closed down gracefully */
1317+
if (ret == WS_CHANNEL_CLOSED) {
1318+
ret = 0;
1319+
break;
1320+
}
1321+
1322+
/* peer hung up, stop shutdown */
1323+
if (ret == WS_SOCKET_ERROR_E) {
1324+
ret = 0;
1325+
break;
1326+
}
1327+
1328+
if (error != WS_WANT_READ && error != WS_WANT_WRITE) {
1329+
break;
1330+
}
1331+
}
1332+
1333+
if (attempt == maxAttempt) {
1334+
printf("Gave up on gracefull shutdown, closing the socket\n");
1335+
}
12841336
}
12851337
}
12861338

@@ -1838,11 +1890,16 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
18381890
break;
18391891

18401892
case 'p':
1841-
port = (word16)atoi(myoptarg);
1842-
#if !defined(NO_MAIN_DRIVER) || defined(USE_WINDOWS_API)
1843-
if (port == 0)
1844-
err_sys("port number cannot be 0");
1845-
#endif
1893+
if (myoptarg == NULL) {
1894+
err_sys("NULL port value");
1895+
}
1896+
else {
1897+
port = (word16)atoi(myoptarg);
1898+
#if !defined(NO_MAIN_DRIVER) || defined(USE_WINDOWS_API)
1899+
if (port == 0)
1900+
err_sys("port number cannot be 0");
1901+
#endif
1902+
}
18461903
break;
18471904

18481905
case 'R':

src/internal.c

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,7 +1148,7 @@ byte NameToId(const char* name, word32 nameSz)
11481148
word32 i;
11491149

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

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

14371437
inBuf = &channel->inputBuffer;
14381438

1439+
/* sanity check the current state to see if is too much data */
1440+
if (dataSz > channel->windowSz) {
1441+
WLOG(WS_LOG_ERROR, "Internal state error, too much data");
1442+
return WS_FATAL_ERROR;
1443+
}
1444+
14391445
if (inBuf->length < inBuf->bufferSz &&
14401446
inBuf->length + dataSz <= inBuf->bufferSz) {
14411447

@@ -1445,7 +1451,7 @@ int ChannelPutData(WOLFSSH_CHANNEL* channel, byte* data, word32 dataSz)
14451451
WLOG(WS_LOG_INFO, " dataSz = %u", dataSz);
14461452
WLOG(WS_LOG_INFO, " windowSz = %u", channel->windowSz);
14471453
channel->windowSz -= dataSz;
1448-
WLOG(WS_LOG_INFO, " windowSz = %u", channel->windowSz);
1454+
WLOG(WS_LOG_INFO, " update windowSz = %u", channel->windowSz);
14491455
}
14501456
else {
14511457
return WS_RECV_OVERFLOW_E;
@@ -9856,6 +9862,18 @@ int SendChannelData(WOLFSSH* ssh, word32 channelId,
98569862
ret = WS_REKEYING;
98579863
}
98589864

9865+
/* if already having data pending try to flush it first and do not continue
9866+
* to que more on fail */
9867+
if (ret == WS_SUCCESS && ssh->outputBuffer.plainSz > 0) {
9868+
WLOG(WS_LOG_DEBUG, "Flushing out want write data");
9869+
ret = wolfSSH_SendPacket(ssh);
9870+
if (ret != WS_SUCCESS) {
9871+
WLOG(WS_LOG_DEBUG, "Leaving SendChannelData(), ret = %d", ret);
9872+
return ret;
9873+
}
9874+
9875+
}
9876+
98599877
if (ret == WS_SUCCESS) {
98609878
if (ssh->outputBuffer.length != 0)
98619879
ret = wolfSSH_SendPacket(ssh);
@@ -9914,10 +9932,12 @@ int SendChannelData(WOLFSSH* ssh, word32 channelId,
99149932
WLOG(WS_LOG_INFO, " update peerWindowSz = %u", channel->peerWindowSz);
99159933
}
99169934

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

9920-
if (ret == WS_SUCCESS)
9940+
if (ret == WS_SUCCESS || ret == WS_WANT_WRITE)
99219941
ret = dataSz;
99229942

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

10457-
/* remove any ./ patterns */
10458-
for (i = 1; i < sz - 1; i++) {
10459-
if (path[i] == '.' && path[i - 1] != '.' && path[i + 1] == WS_DELIM) {
10460-
WMEMMOVE(path + i, path + i + 1, sz - i - 1);
10461-
path[sz - 1] = '\0';
10462-
i--;
10463-
}
10464-
}
10465-
sz = (int)WSTRLEN(path);
10466-
10467-
/* remove any /./ patterns */
10478+
/* remove any /./ patterns, direcotries, exclude cases like ./ok./test */
1046810479
for (i = 1; i + 1 < sz; i++) {
1046910480
if (path[i] == '.' && path[i - 1] == WS_DELIM && path[i + 1] == WS_DELIM) {
1047010481
WMEMMOVE(path + i, path + i + 1, sz - i + 1);
@@ -10583,7 +10594,7 @@ int wolfSSH_CleanPath(WOLFSSH* ssh, char* in)
1058310594
WFREE(path, ssh->ctx->heap, DYNTYPE_PATH);
1058410595
return WS_BUFFER_E;
1058510596
}
10586-
sz = WSTRLEN(path);
10597+
sz = (long)WSTRLEN(path);
1058710598
WMEMCPY(in, path, sz);
1058810599
in[sz] = '\0';
1058910600
WFREE(path, ssh->ctx->heap, DYNTYPE_PATH);

src/io.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -404,11 +404,7 @@ int wsEmbedSend(WOLFSSH* ssh, void* data, word32 sz, void* ctx)
404404
#endif /* MICROCHIP_MPLAB_HARMONY */
405405

406406
sent = (int)SEND_FUNCTION(sd, buf, sz, ssh->wflags);
407-
408407
sent = TranslateReturnCode(sent, sd);
409-
410-
WLOG(WS_LOG_DEBUG,"Embed Send sent %d", sent);
411-
412408
if (sent < 0) {
413409
err = LastError();
414410
WLOG(WS_LOG_DEBUG,"Embed Send error");
@@ -434,6 +430,7 @@ int wsEmbedSend(WOLFSSH* ssh, void* data, word32 sz, void* ctx)
434430
return WS_CBIO_ERR_GENERAL;
435431
}
436432
}
433+
WLOG(WS_LOG_DEBUG,"Embed Send sent %d", sent);
437434
return sent;
438435
}
439436

src/ssh.c

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -947,10 +947,14 @@ int wolfSSH_shutdown(WOLFSSH* ssh)
947947
if (ret == WS_SUCCESS)
948948
ret = SendChannelEof(ssh, ssh->channelList->peerChannel);
949949

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

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

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

10151019
WLOG(WS_LOG_DEBUG, "Making more room: %u", usedSz);
1020+
WLOG(WS_LOG_DEBUG, " Current index into buffer = %u", inputBuffer->idx);
1021+
WLOG(WS_LOG_DEBUG, " Current max index for available data = %u",
1022+
inputBuffer->length);
1023+
WLOG(WS_LOG_DEBUG, " Current total buffer size = %u",
1024+
inputBuffer->bufferSz);
10161025
if (usedSz) {
1017-
WLOG(WS_LOG_DEBUG, " ...moving data down");
1026+
WLOG(WS_LOG_DEBUG, " ...moving %d used bytes down", usedSz);
10181027
WMEMMOVE(inputBuffer->buffer, inputBuffer->buffer + bytesToAdd, usedSz);
1028+
inputBuffer->length = usedSz;
1029+
inputBuffer->idx = 0;
10191030
}
10201031

10211032
ret = SendChannelWindowAdjust(ssh, ssh->channelList->channel,
10221033
bytesToAdd);
1023-
if (ret != WS_SUCCESS) {
1034+
if (ret != WS_SUCCESS && ret != WS_WANT_WRITE) {
10241035
WLOG(WS_LOG_ERROR, "Error adjusting window");
10251036
}
10261037
else {
@@ -1065,7 +1076,11 @@ int wolfSSH_stream_read(WOLFSSH* ssh, byte* buf, word32 bufSz)
10651076

10661077

10671078
if (ret == WS_SUCCESS) {
1079+
WLOG(WS_LOG_DEBUG, " Stream read index of %u", inputBuffer->idx);
1080+
WLOG(WS_LOG_DEBUG, " Stream read ava data %u", inputBuffer->length);
10681081
while (inputBuffer->length - inputBuffer->idx == 0) {
1082+
WLOG(WS_LOG_DEBUG, "Starting to recieve data at current index of %u",
1083+
inputBuffer->idx);
10691084
ret = DoReceive(ssh);
10701085
if (ssh->channelList == NULL || ssh->channelList->eofRxd)
10711086
ret = WS_EOF;
@@ -1109,19 +1124,6 @@ int wolfSSH_stream_send(WOLFSSH* ssh, byte* buf, word32 bufSz)
11091124
if (ssh == NULL || buf == NULL || ssh->channelList == NULL)
11101125
return WS_BAD_ARGUMENT;
11111126

1112-
/* case of WANT WRITE and data stored in output buffer */
1113-
if (ssh->outputBuffer.plainSz && ssh->outputBuffer.length != 0) {
1114-
int ret;
1115-
1116-
bytesTxd = ssh->outputBuffer.plainSz;
1117-
WLOG(WS_LOG_DEBUG, "Trying to resend %d bytes", bytesTxd);
1118-
ssh->error = WS_SUCCESS;
1119-
ret = wolfSSH_SendPacket(ssh);
1120-
1121-
/* return the amount sent on success otherwise return error found */
1122-
return (ret == WS_SUCCESS)? bytesTxd : ret;
1123-
}
1124-
11251127
bytesTxd = SendChannelData(ssh, ssh->channelList->channel, buf, bufSz);
11261128

11271129
WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_stream_send(), txd = %d", bytesTxd);
@@ -2029,6 +2031,8 @@ static int _UpdateChannelWindow(WOLFSSH_CHANNEL* channel)
20292031
WLOG(WS_LOG_DEBUG, " ...moving data down");
20302032
WMEMMOVE(inputBuffer->buffer,
20312033
inputBuffer->buffer + bytesToAdd, usedSz);
2034+
inputBuffer->length = usedSz;
2035+
inputBuffer->idx = 0;
20322036
}
20332037

20342038
sendResult = SendChannelWindowAdjust(channel->ssh, channel->channel,

0 commit comments

Comments
 (0)