mirror of https://github.com/wolfSSL/wolfssh.git
commit
54df2e99b8
|
|
@ -438,6 +438,7 @@ static int SetupChroot(WOLFSSHD_CONFIG* usrConf)
|
|||
|
||||
#ifdef WOLFSSH_SFTP
|
||||
#define TEST_SFTP_TIMEOUT 1
|
||||
#define TEST_SFTP_TIMEOUT_NONE 0
|
||||
|
||||
/* handle SFTP operations
|
||||
* returns WS_SUCCESS on success
|
||||
|
|
@ -445,11 +446,12 @@ static int SetupChroot(WOLFSSHD_CONFIG* usrConf)
|
|||
static int SFTP_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh,
|
||||
WPASSWD* pPasswd, WOLFSSHD_CONFIG* usrConf)
|
||||
{
|
||||
byte tmp[1];
|
||||
int ret = WS_SUCCESS;
|
||||
int error = WS_SUCCESS;
|
||||
WS_SOCKET_T sockfd;
|
||||
int select_ret = 0;
|
||||
int timeout = TEST_SFTP_TIMEOUT_NONE;
|
||||
byte peek_buf[1];
|
||||
|
||||
/* temporarily elevate permissions to get users information */
|
||||
if (wolfSSHD_AuthRaisePermissions(conn->auth) != WS_SUCCESS) {
|
||||
|
|
@ -501,29 +503,67 @@ static int SFTP_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh,
|
|||
|
||||
sockfd = (WS_SOCKET_T)wolfSSH_get_fd(ssh);
|
||||
do {
|
||||
if (wolfSSH_stream_peek(ssh, tmp, 1) > 0) {
|
||||
select_ret = WS_SELECT_RECV_READY;
|
||||
}
|
||||
else {
|
||||
select_ret = tcp_select(sockfd, TEST_SFTP_TIMEOUT);
|
||||
select_ret = tcp_select(sockfd, timeout);
|
||||
if (select_ret == WS_SELECT_ERROR_READY) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (select_ret == WS_SELECT_RECV_READY ||
|
||||
select_ret == WS_SELECT_ERROR_READY ||
|
||||
error == WS_WANT_WRITE)
|
||||
{
|
||||
if (select_ret == WS_SELECT_RECV_READY) {
|
||||
ret = wolfSSH_worker(ssh, NULL);
|
||||
error = wolfSSH_get_error(ssh);
|
||||
if (ret == WS_REKEYING) {
|
||||
/* In a rekey, keeping turning the crank. */
|
||||
timeout = TEST_SFTP_TIMEOUT;
|
||||
continue;
|
||||
}
|
||||
if (error == WS_EOF) {
|
||||
break;
|
||||
}
|
||||
if (ret != WS_SUCCESS && ret != WS_CHAN_RXD) {
|
||||
/* If not successful and no channel data, leave. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (wolfSSH_SFTP_PendingSend(ssh)) {
|
||||
/* Yes, process the SFTP data. */
|
||||
ret = wolfSSH_SFTP_read(ssh);
|
||||
error = wolfSSH_get_error(ssh);
|
||||
timeout = (ret == WS_REKEYING) ?
|
||||
TEST_SFTP_TIMEOUT : TEST_SFTP_TIMEOUT_NONE;
|
||||
if (error == WS_WANT_READ || error == WS_WANT_WRITE ||
|
||||
error == WS_CHAN_RXD || error == WS_REKEYING ||
|
||||
error == WS_WINDOW_FULL)
|
||||
ret = error;
|
||||
if (error == WS_EOF)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
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 ||
|
||||
error == WS_WINDOW_FULL)
|
||||
ret = error;
|
||||
ret = wolfSSH_stream_peek(ssh, peek_buf, sizeof(peek_buf));
|
||||
if (ret > 0) {
|
||||
/* Yes, process the SFTP data. */
|
||||
ret = wolfSSH_SFTP_read(ssh);
|
||||
error = wolfSSH_get_error(ssh);
|
||||
timeout = (ret == WS_REKEYING) ?
|
||||
TEST_SFTP_TIMEOUT : TEST_SFTP_TIMEOUT_NONE;
|
||||
if (error == WS_WANT_READ || error == WS_WANT_WRITE ||
|
||||
error == WS_CHAN_RXD || error == WS_REKEYING ||
|
||||
error == WS_WINDOW_FULL)
|
||||
ret = error;
|
||||
if (error == WS_EOF)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
else if (ret == WS_REKEYING) {
|
||||
timeout = TEST_SFTP_TIMEOUT;
|
||||
continue;
|
||||
}
|
||||
else if (ret < 0) {
|
||||
error = wolfSSH_get_error(ssh);
|
||||
if (error == WS_EOF)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret == WS_FATAL_ERROR && error == 0) {
|
||||
WOLFSSH_CHANNEL* channel =
|
||||
|
|
@ -533,6 +573,8 @@ static int SFTP_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh,
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
timeout = TEST_SFTP_TIMEOUT;
|
||||
} while (ret != WS_FATAL_ERROR);
|
||||
|
||||
(void)conn;
|
||||
|
|
|
|||
|
|
@ -107,8 +107,6 @@
|
|||
|
||||
#ifndef NO_WOLFSSH_SERVER
|
||||
|
||||
#define TEST_SFTP_TIMEOUT 1
|
||||
|
||||
static const char echoserverBanner[] = "wolfSSH Example Echo Server\n";
|
||||
|
||||
static int quit = 0;
|
||||
|
|
@ -1133,84 +1131,81 @@ static int ssh_worker(thread_ctx_t* threadCtx)
|
|||
|
||||
|
||||
#ifdef WOLFSSH_SFTP
|
||||
|
||||
#define TEST_SFTP_TIMEOUT_NONE 0
|
||||
#define TEST_SFTP_TIMEOUT 1
|
||||
|
||||
/* handle SFTP operations
|
||||
* returns 0 on success
|
||||
*/
|
||||
static int sftp_worker(thread_ctx_t* threadCtx)
|
||||
{
|
||||
byte tmp[1];
|
||||
int ret = WS_SUCCESS;
|
||||
int error = WS_SUCCESS;
|
||||
WS_SOCKET_T sockfd;
|
||||
int select_ret = 0;
|
||||
WOLFSSH* ssh = threadCtx->ssh;
|
||||
WS_SOCKET_T s;
|
||||
int ret = WS_SUCCESS;
|
||||
int error;
|
||||
int selected;
|
||||
unsigned char peek_buf[1];
|
||||
int timeout = TEST_SFTP_TIMEOUT;
|
||||
|
||||
s = (WS_SOCKET_T)wolfSSH_get_fd(ssh);
|
||||
|
||||
error = wolfSSH_get_error(threadCtx->ssh);
|
||||
sockfd = (WS_SOCKET_T)wolfSSH_get_fd(threadCtx->ssh);
|
||||
do {
|
||||
if (threadCtx->nonBlock) {
|
||||
if (error == WS_WANT_READ) {
|
||||
WOLFSSH_CHANNEL* c;
|
||||
printf("... sftp server would read block\n");
|
||||
selected = tcp_select(s, timeout);
|
||||
if (selected == WS_SELECT_ERROR_READY) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* 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");
|
||||
|
||||
/* handle backlog of send packets */
|
||||
wolfSSH_worker(threadCtx->ssh, &c);
|
||||
ret = error = wolfSSH_get_error(threadCtx->ssh);
|
||||
if (selected == WS_SELECT_RECV_READY) {
|
||||
ret = wolfSSH_worker(ssh, NULL);
|
||||
error = wolfSSH_get_error(ssh);
|
||||
if (ret == WS_REKEYING) {
|
||||
/* In a rekey, keeping turning the crank. */
|
||||
timeout = TEST_SFTP_TIMEOUT;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 {
|
||||
if (wolfSSH_stream_peek(threadCtx->ssh, tmp, 1) > 0) {
|
||||
select_ret = WS_SELECT_RECV_READY;
|
||||
if (error == WS_EOF) {
|
||||
break;
|
||||
}
|
||||
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);
|
||||
}
|
||||
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 ||
|
||||
error == WS_WINDOW_FULL)
|
||||
ret = error;
|
||||
|
||||
if (ret == WS_FATAL_ERROR && error == 0) {
|
||||
WOLFSSH_CHANNEL* channel =
|
||||
wolfSSH_ChannelNext(threadCtx->ssh, NULL);
|
||||
if (channel && wolfSSH_ChannelGetEof(channel)) {
|
||||
ret = 0;
|
||||
if (ret != WS_SUCCESS && ret != WS_CHAN_RXD) {
|
||||
/* If not successful and no channel data, leave. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} while (ret != WS_FATAL_ERROR && ret != WS_SOCKET_ERROR_E);
|
||||
if (wolfSSH_SFTP_PendingSend(ssh)) {
|
||||
/* Yes, process the SFTP data. */
|
||||
ret = wolfSSH_SFTP_read(ssh);
|
||||
timeout = (ret == WS_REKEYING) ?
|
||||
TEST_SFTP_TIMEOUT : TEST_SFTP_TIMEOUT_NONE;
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = wolfSSH_stream_peek(ssh, peek_buf, sizeof(peek_buf));
|
||||
if (ret > 0) {
|
||||
/* Yes, process the SFTP data. */
|
||||
ret = wolfSSH_SFTP_read(ssh);
|
||||
timeout = (ret == WS_REKEYING) ?
|
||||
TEST_SFTP_TIMEOUT : TEST_SFTP_TIMEOUT_NONE;
|
||||
continue;
|
||||
}
|
||||
else if (ret == WS_REKEYING) {
|
||||
timeout = TEST_SFTP_TIMEOUT;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Old check for EOF here */
|
||||
{
|
||||
WOLFSSH_CHANNEL* channel =
|
||||
wolfSSH_ChannelNext(ssh, NULL);
|
||||
if (channel && wolfSSH_ChannelGetEof(channel)) {
|
||||
ret = WS_EOF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
timeout = TEST_SFTP_TIMEOUT;
|
||||
} while (1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1335,7 +1330,11 @@ static THREAD_RETURN WOLFSSH_THREAD server_worker(void* vArgs)
|
|||
break;
|
||||
}
|
||||
|
||||
if (error != WS_WANT_READ && error != WS_WANT_WRITE) {
|
||||
if (error == WS_WANT_READ || error == WS_WANT_WRITE) {
|
||||
/* Wanting read or wanting write. Clear ret. */
|
||||
ret = 0;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -501,8 +501,14 @@ static int doCmds(func_args* args)
|
|||
if (ret != WS_SUCCESS && ret == WS_FATAL_ERROR) {
|
||||
ret = wolfSSH_get_error(ssh);
|
||||
}
|
||||
while (ret == WS_REKEYING || ssh->error == WS_REKEYING) {
|
||||
ret = wolfSSH_worker(ssh, NULL);
|
||||
if (ret != WS_SUCCESS && ret == WS_FATAL_ERROR) {
|
||||
ret = wolfSSH_get_error(ssh);
|
||||
}
|
||||
}
|
||||
} while (ret == WS_WANT_READ || ret == WS_WANT_WRITE ||
|
||||
ret == WS_CHAN_RXD || ret == WS_REKEYING);
|
||||
ret == WS_CHAN_RXD);
|
||||
|
||||
#ifndef WOLFSSH_NO_TIMESTAMP
|
||||
WMEMSET(currentFile, 0, WOLFSSH_MAX_FILENAME);
|
||||
|
|
|
|||
|
|
@ -7411,7 +7411,8 @@ int DoReceive(WOLFSSH* ssh)
|
|||
ret = DoPacket(ssh);
|
||||
ssh->error = ret;
|
||||
if (ret < 0 && !(ret == WS_CHAN_RXD || ret == WS_EXTDATA ||
|
||||
ret == WS_CHANNEL_CLOSED || ret == WS_WANT_WRITE)) {
|
||||
ret == WS_CHANNEL_CLOSED || ret == WS_WANT_WRITE ||
|
||||
ret == WS_REKEYING)) {
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
WLOG(WS_LOG_DEBUG, "PR3: peerMacSz = %u", peerMacSz);
|
||||
|
|
@ -11896,6 +11897,7 @@ int SendChannelData(WOLFSSH* ssh, word32 channelId,
|
|||
|
||||
if (ret == WS_SUCCESS) {
|
||||
word32 bound = min(channel->peerWindowSz, channel->peerMaxPacketSz);
|
||||
bound = min(bound, channel->maxPacketSz);
|
||||
|
||||
if (dataSz > bound) {
|
||||
WLOG(WS_LOG_DEBUG,
|
||||
|
|
|
|||
36
src/ssh.c
36
src/ssh.c
|
|
@ -998,6 +998,15 @@ int wolfSSH_stream_peek(WOLFSSH* ssh, byte* buf, word32 bufSz)
|
|||
if (ssh == NULL || ssh->channelList == NULL)
|
||||
return WS_BAD_ARGUMENT;
|
||||
|
||||
if (ssh->isKeying) {
|
||||
ssh->error = WS_REKEYING;
|
||||
return WS_REKEYING;
|
||||
}
|
||||
if (ssh->channelList->eofRxd) {
|
||||
ssh->error = WS_EOF;
|
||||
return WS_ERROR;
|
||||
}
|
||||
|
||||
inputBuffer = &ssh->channelList->inputBuffer;
|
||||
bufSz = min(bufSz, inputBuffer->length - inputBuffer->idx);
|
||||
if (buf != NULL) {
|
||||
|
|
@ -1030,6 +1039,11 @@ int wolfSSH_stream_read(WOLFSSH* ssh, byte* buf, word32 bufSz)
|
|||
if (ssh == NULL || buf == NULL || bufSz == 0 || ssh->channelList == NULL)
|
||||
return WS_BAD_ARGUMENT;
|
||||
|
||||
if (ssh->channelList->eofRxd) {
|
||||
ssh->error = WS_EOF;
|
||||
return WS_ERROR;
|
||||
}
|
||||
|
||||
inputBuffer = &ssh->channelList->inputBuffer;
|
||||
ssh->error = WS_SUCCESS;
|
||||
|
||||
|
|
@ -1089,6 +1103,11 @@ int wolfSSH_stream_send(WOLFSSH* ssh, byte* buf, word32 bufSz)
|
|||
if (ssh == NULL || buf == NULL || ssh->channelList == NULL)
|
||||
return WS_BAD_ARGUMENT;
|
||||
|
||||
if (ssh->isKeying) {
|
||||
ssh->error = WS_REKEYING;
|
||||
return WS_REKEYING;
|
||||
}
|
||||
|
||||
bytesTxd = SendChannelData(ssh, ssh->channelList->channel, buf, bufSz);
|
||||
|
||||
WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_stream_send(), txd = %d", bytesTxd);
|
||||
|
|
@ -1764,15 +1783,24 @@ int wolfSSH_worker(WOLFSSH* ssh, word32* channelId)
|
|||
ret = DoReceive(ssh);
|
||||
}
|
||||
|
||||
if (channelId != NULL && ssh != NULL) {
|
||||
*channelId = ssh->lastRxId;
|
||||
if (ret == WS_SUCCESS) {
|
||||
if (channelId != NULL) {
|
||||
*channelId = ssh->lastRxId;
|
||||
}
|
||||
|
||||
if (ssh->isKeying) {
|
||||
ssh->error = WS_REKEYING;
|
||||
return WS_REKEYING;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == WS_CHAN_RXD)
|
||||
if (ret == WS_CHAN_RXD) {
|
||||
WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_worker(), "
|
||||
"data received on channel %u", ssh->lastRxId);
|
||||
else
|
||||
}
|
||||
else {
|
||||
WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_worker(), ret = %d", ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -404,7 +404,8 @@ static INLINE int NoticeError(WOLFSSH* ssh)
|
|||
{
|
||||
return (ssh->error == WS_WANT_READ ||
|
||||
ssh->error == WS_WANT_WRITE ||
|
||||
ssh->error == WS_CHAN_RXD);
|
||||
ssh->error == WS_CHAN_RXD ||
|
||||
ssh->error == WS_REKEYING);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -512,7 +513,7 @@ static int wolfSSH_SFTP_buffer_send(WOLFSSH* ssh, WS_SFTP_BUFFER* buffer)
|
|||
return WS_BUFFER_E;
|
||||
}
|
||||
|
||||
while (buffer->idx < buffer->sz && (ret > 0 || ret == WS_SUCCESS)) {
|
||||
if (buffer->idx < buffer->sz) {
|
||||
ret = wolfSSH_stream_send(ssh, buffer->data + buffer->idx,
|
||||
buffer->sz - buffer->idx);
|
||||
if (ret > 0) {
|
||||
|
|
@ -520,11 +521,6 @@ static int wolfSSH_SFTP_buffer_send(WOLFSSH* ssh, WS_SFTP_BUFFER* buffer)
|
|||
}
|
||||
WLOG(WS_LOG_SFTP, "SFTP buffer sent %d / %d bytes", buffer->idx,
|
||||
buffer->sz);
|
||||
|
||||
/* interupt sending for a rekey or full window */
|
||||
if (ret == WS_WINDOW_FULL || ret == WS_REKEYING) {
|
||||
ret = wolfSSH_worker(ssh, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -1488,12 +1484,26 @@ int wolfSSH_SFTP_read(WOLFSSH* ssh)
|
|||
case STATE_RECV_SEND:
|
||||
if (state->toSend) {
|
||||
ret = wolfSSH_SFTP_buffer_send(ssh, &state->buffer);
|
||||
if (ret == WS_SUCCESS || ret > 0) {
|
||||
ret = WS_SUCCESS;
|
||||
state->toSend = 0;
|
||||
wolfSSH_SFTP_ClearState(ssh, STATE_ID_RECV);
|
||||
if (ret < 0) {
|
||||
if (ret == WS_REKEYING || ssh->error == WS_REKEYING) {
|
||||
return WS_REKEYING;
|
||||
}
|
||||
if (ssh->error != WS_WANT_READ &&
|
||||
ssh->error != WS_WANT_WRITE &&
|
||||
ssh->error != WS_WINDOW_FULL) {
|
||||
wolfSSH_SFTP_ClearState(ssh, STATE_ID_RECV);
|
||||
}
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
if (wolfSSH_SFTP_buffer_idx(&state->buffer)
|
||||
< wolfSSH_SFTP_buffer_size(&state->buffer)) {
|
||||
ssh->error = WS_WANT_WRITE;
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
ret = WS_SUCCESS;
|
||||
state->toSend = 0;
|
||||
}
|
||||
wolfSSH_SFTP_ClearState(ssh, STATE_ID_RECV);
|
||||
return ret;
|
||||
|
||||
default:
|
||||
|
|
@ -3407,10 +3417,6 @@ int wolfSSH_SFTP_RecvRead(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
|
|||
return WS_BUFFER_E;
|
||||
}
|
||||
|
||||
if (sz > WOLFSSH_MAX_SFTP_RW) {
|
||||
sz = WOLFSSH_MAX_SFTP_RW;
|
||||
}
|
||||
|
||||
/* read from handle and send data back to client */
|
||||
out = (byte*)WMALLOC(sz + WOLFSSH_SFTP_HEADER + UINT32_SZ,
|
||||
ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
|
|
@ -6922,6 +6928,9 @@ int wolfSSH_SFTP_SendReadPacket(WOLFSSH* ssh, byte* handle, word32 handleSz,
|
|||
/* send header and type specific data */
|
||||
ret = wolfSSH_SFTP_buffer_send(ssh, &state->buffer);
|
||||
if (ret < 0) {
|
||||
if (ret == WS_REKEYING) {
|
||||
return ret;
|
||||
}
|
||||
if (ssh->error != WS_WANT_READ &&
|
||||
ssh->error != WS_WANT_WRITE) {
|
||||
state->state = STATE_SEND_READ_CLEANUP;
|
||||
|
|
|
|||
|
|
@ -816,14 +816,14 @@ static void test_wolfSSH_SFTP_SendReadPacket(void)
|
|||
}
|
||||
|
||||
/* partial read */
|
||||
outSz = tmp->atrb.sz[0] / 2;
|
||||
outSz = WOLFSSH_MAX_SFTP_RW / 2;
|
||||
rxSz = wolfSSH_SFTP_SendReadPacket(ssh, handle, handleSz,
|
||||
ofst, out, outSz);
|
||||
AssertIntGT(rxSz, 0);
|
||||
AssertIntLE(rxSz, outSz);
|
||||
|
||||
/* read all */
|
||||
outSz = tmp->atrb.sz[0];
|
||||
outSz = WOLFSSH_MAX_SFTP_RW;
|
||||
rxSz = wolfSSH_SFTP_SendReadPacket(ssh, handle, handleSz,
|
||||
ofst, out, outSz);
|
||||
AssertIntGT(rxSz, 0);
|
||||
|
|
|
|||
|
|
@ -681,7 +681,7 @@ static INLINE int tcp_select(SOCKET_T socketfd, int to_sec)
|
|||
{
|
||||
WFD_SET_TYPE recvfds, errfds;
|
||||
int nfds = (int)socketfd + 1;
|
||||
struct timeval timeout = {(to_sec > 0) ? to_sec : 0, 0};
|
||||
struct timeval timeout = {(to_sec > 0) ? to_sec : 0, 100};
|
||||
int result;
|
||||
|
||||
WFD_ZERO(&recvfds);
|
||||
|
|
|
|||
Loading…
Reference in New Issue