Rx Window

1. Remove the CheckPendingReceive() function and the WIOCTL wrapper.
2. If the peer's receive window is considered full, call wolfSSH_worker()
which will process a receive.
pull/252/head
John Safranek 2020-03-12 13:21:04 -07:00
parent 2c710dcfd8
commit 66f8a47a6a
No known key found for this signature in database
GPG Key ID: 8CE817DE0D3CCB4A
7 changed files with 25 additions and 100 deletions

View File

@ -20,9 +20,7 @@
*/
#define RENESAS_CSPLUS
#define WIOCTL ws_Ioctl
//#define DEBUG_WOLFSSH
#define WOLFSSH_NO_TIMESTAMP
#define WOLFSSH_USER_IO
#define FIONREAD 1
#define WOLFSSH_THREAD

View File

@ -287,6 +287,9 @@ const char* GetErrorString(int err)
case WC_CHANGE_AUTH_E:
return "changing auth type attempt";
case WS_WINDOW_FULL:
return "peer's channel window full";
default:
return "Unknown error code";
}
@ -8180,6 +8183,13 @@ int SendChannelData(WOLFSSH* ssh, word32 peerChannel,
}
}
if (ret == WS_SUCCESS) {
if (channel->peerWindowSz == 0) {
WLOG(WS_LOG_DEBUG, "channel window is full");
ret = WS_WINDOW_FULL;
}
}
if (ret == WS_SUCCESS) {
word32 bound = min(channel->peerWindowSz, channel->peerMaxPacketSz);

View File

@ -1645,41 +1645,6 @@ int wolfSSH_ChannelGetEof(WOLFSSH_CHANNEL* channel)
}
/* Protocols that have loops over wolfSSH_stream_send without doing any reads
* will run into the issue of not checking for a peer window adjustment packet.
* This function allows for checking for a peer window adjustment packet without
* requiring a read buffer and call to wolfSSH_stream_read.
*
* Data that is read and is not related to packet headers is stored in the
* WOLFSSH input buffer and can be gotten with a call to wolfSSH_stream_read. If
* more data is stored then MAX_PACKET_SZ then no more window adjustment packets
* are searched for.
*/
void wolfSSH_CheckReceivePending(WOLFSSH* ssh)
{
int bytes = 0;
Buffer* inputBuffer;
WLOG(WS_LOG_DEBUG, "Entering wolfSSH_CheckReceivePending()");
if (ssh == NULL)
return;
inputBuffer = &ssh->channelList->inputBuffer;
WIOCTL(wolfSSH_get_fd(ssh), WFIONREAD, &bytes);
while (bytes > 0) { /* there is something to read off the wire */
if (inputBuffer->length - inputBuffer->idx > MAX_PACKET_SZ) {
WLOG(WS_LOG_DEBUG, "Application data to be read");
break; /* too much application data! */
}
if (DoReceive(ssh) < 0) {
WLOG(WS_LOG_ERROR, "Error trying to read potential window adjust");
}
WIOCTL(wolfSSH_get_fd(ssh), WFIONREAD, &bytes);
}
}
#ifdef WOLFSSH_SHOW_SIZES
void wolfSSH_ShowSizes(void)

View File

@ -574,7 +574,11 @@ int DoScpSource(WOLFSSH* ssh)
ret = wolfSSH_stream_send(ssh, ssh->scpFileBuffer,
ssh->scpBufferedSz);
wolfSSH_CheckReceivePending(ssh); /*check for adjust window packet*/
if (ret == WS_WINDOW_FULL) {
ret = wolfSSH_worker(ssh, NULL);
if (ret == WS_SUCCESS)
continue;
}
if (ret < 0) {
WLOG(WS_LOG_ERROR, scpError, "failed to send file", ret);
break;
@ -1575,7 +1579,7 @@ static int wolfSSH_SCP_cmd(WOLFSSH* ssh, const char* localName,
else {
WLOG(WS_LOG_SCP, "Cannot build scp command");
ssh->error = WS_MEMORY_E;
ret = WS_FATAL_ERROR;
ret = WS_ERROR;
}
return ret;

View File

@ -1205,7 +1205,8 @@ int wolfSSH_SFTP_read(WOLFSSH* ssh)
state->sz - state->idx);
if (ret < 0) {
if (ssh->error != WS_WANT_READ &&
ssh->error != WS_WANT_WRITE)
ssh->error != WS_WANT_WRITE &&
ssh->error != WS_WINDOW_FULL)
wolfSSH_SFTP_ClearState(ssh, STATE_ID_RECV);
return WS_FATAL_ERROR;
}
@ -1217,7 +1218,7 @@ int wolfSSH_SFTP_read(WOLFSSH* ssh)
state->toSend = 1;
if ((int)state->idx < state->sz) {
wolfSSH_CheckReceivePending(ssh);
ret = wolfSSH_worker(ssh, NULL);
if (ssh->error == WS_WANT_READ) {
/* was something there to read, try again */
state->toSend = 2;
@ -4607,7 +4608,8 @@ int SendPacketType(WOLFSSH* ssh, byte type, byte* buf, word32 bufSz)
/* check for adjust window packet */
err = wolfSSH_get_error(ssh);
wolfSSH_CheckReceivePending(ssh);
if (err == WS_WINDOW_FULL)
ret = wolfSSH_worker(ssh, NULL);
ssh->error = err; /* don't save potential want read here */
if (ret > 0)
state->idx += (word32)ret;
@ -7672,7 +7674,8 @@ int wolfSSH_SFTP_Put(WOLFSSH* ssh, char* from, char* to, byte resume,
state->r, state->rSz);
if (sz <= 0) {
if (ssh->error == WS_WANT_READ ||
ssh->error == WS_WANT_WRITE)
ssh->error == WS_WANT_WRITE ||
ssh->error == WS_WINDOW_FULL)
return WS_FATAL_ERROR;
}
else {
@ -7686,8 +7689,6 @@ int wolfSSH_SFTP_Put(WOLFSSH* ssh, char* from, char* to, byte resume,
statusCb(ssh, state->pOfst, from);
}
}
/* check for adjust window packet */
wolfSSH_CheckReceivePending(ssh);
} while (sz > 0 && ssh->sftpInt == 0);
if (ssh->sftpInt) {

View File

@ -111,8 +111,9 @@ enum WS_ErrorCodes {
WS_SSH_CTX_NULL_E = -1070, /* SSH_CTX was null */
WS_CHANNEL_NOT_CONF = -1071, /* Channel open not confirmed. */
WC_CHANGE_AUTH_E = -1072, /* Changing auth type attempt */
WS_WINDOW_FULL = -1073,
WS_LAST_E = -1072 /* Update this to indicate last error */
WS_LAST_E = -1073 /* Update this to indicate last error */
};

View File

@ -1078,60 +1078,6 @@ extern "C" {
#define FALL_THROUGH
#endif
/* used for checking bytes on wire for window adjust packet read */
#ifndef WIOCTL
#ifdef WOLFSSL_NUCLEUS
#include "nucleus.h"
#include "networking/nu_networking.h"
#define WFIONREAD FIONREAD
static inline void ws_Ioctl(int fd, int flag, int* ret)
{
SCK_IOCTL_OPTION op;
op.s_optval = (unsigned char*)&fd;
if (NU_Ioctl(flag, &op, sizeof(op)) != NU_SUCCESS) {
*ret = 0;
}
else {
*ret = op.s_ret.sck_bytes_pending;
}
}
#define WIOCTL ws_Ioctl
#elif defined(FREESCALE_MQX)
/* MQX does not have FIONREAD, use SO_RCVNUM with getsockopt() instead */
#include <ioctl.h>
#include <rtcs.h>
#define WFIONREAD SO_RCVNUM
static inline void ws_Ioctl(int fd, int flag, int* ret)
{
int status;
uint32_t bytesSz;
bytesSz = sizeof(*ret);
status = getsockopt(fd, SOL_SOCKET, SO_RCVNUM, ret, &bytesSz);
if (status != RTCS_OK) {
WLOG(WS_LOG_ERROR, "Error calling getsockopt()");
*ret = 0;
}
}
#define WIOCTL ws_Ioctl
#elif defined(USE_WINDOWS_API)
#define WFIONREAD FIONREAD
#define WIOCTL ioctlsocket
#elif defined(WOLFSSL_VXWORKS)
#include "ioLib.h"
#include <sys/ioctl.h>
#define WIOCTL ioctl
#else
#if defined(__CYGWIN__) && !defined(FIONREAD)
/* Cygwin defines FIONREAD in socket.h instead of ioctl.h */
#include <sys/socket.h>
#endif
#include <sys/ioctl.h>
#define WFIONREAD FIONREAD
#define WIOCTL ioctl
#endif
#endif /* WIOCTL */
#if defined(USE_WINDOWS_API)
#define WS_SOCKET_T SOCKET