Commit f108a53c authored by Sebastien Decugis's avatar Sebastien Decugis
Browse files

Also timeout on sends

parent a29c97bd
......@@ -506,6 +506,7 @@ void fd_cnx_s_setto(int sock)
memset(&tv, 0, sizeof(tv));
tv.tv_sec = 3; /* allow 3 seconds timeout for TLS session cleanup */
CHECK_SYS_DO( setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)), /* best effort only */ );
CHECK_SYS_DO( setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)), /* Also timeout for sending, to avoid waiting forever */ );
}
/* A recv-like function, taking a cnxctx object instead of socket as entry. Only used to filter timeouts error (GNUTLS does not like these...) */
......@@ -532,7 +533,22 @@ again:
/* Send */
static ssize_t fd_cnx_s_send(struct cnxctx * conn, void *buffer, size_t length)
{
return send(conn->cc_socket, buffer, length, 0);
ssize_t ret = 0;
int timedout = 0;
again:
ret = send(conn->cc_socket, buffer, length, 0);
/* Handle special case of timeout */
if ((ret < 0) && (errno == EAGAIN)) {
if (!conn->cc_closing)
goto again; /* don't care, just ignore */
if (!timedout) {
timedout ++; /* allow for one timeout while closing */
goto again;
}
CHECK_SYS_DO(ret, /* continue */);
}
return ret;
}
/* Receiver thread (TCP & noTLS) : incoming message is directly saved into the target queue */
......@@ -1235,7 +1251,7 @@ static int send_simple(struct cnxctx * conn, unsigned char * buf, size_t len)
if (conn->cc_tls) {
CHECK_GNUTLS_DO( ret = fd_tls_send_handle_error(conn, conn->cc_tls_para.session, buf + sent, len - sent), return ENOTCONN );
} else {
CHECK_SYS( ret = send(conn->cc_socket, buf + sent, len - sent, 0) ); /* better to replace with sendmsg for atomic sending? */
CHECK_SYS( ret = fd_cnx_s_send(conn, buf + sent, len - sent) ); /* better to replace with sendmsg for atomic sending? */
}
sent += ret;
} while ( sent < len );
......@@ -1271,7 +1287,7 @@ int fd_cnx_send(struct cnxctx * conn, unsigned char * buf, size_t len)
CHECK_FCT( send_simple(conn, buf, len) );
} else {
if (!conn->cc_tls) {
CHECK_FCT( fd_sctp_sendstr(conn->cc_socket, conn->cc_sctp_para.next, buf, len) );
CHECK_FCT( fd_sctp_sendstr(conn->cc_socket, conn->cc_sctp_para.next, buf, len, &conn->cc_closing) );
} else {
/* push the record to the appropriate session */
ssize_t ret;
......
......@@ -102,7 +102,7 @@ int fd_sctp_client( int *sock, int no_ip6, uint16_t port, struct fd_list * list
int fd_sctp_get_local_ep(int sock, struct fd_list * list);
int fd_sctp_get_remote_ep(int sock, struct fd_list * list);
int fd_sctp_get_str_info( int sock, uint16_t *in, uint16_t *out, sSS *primary );
int fd_sctp_sendstr(int sock, uint16_t strid, uint8_t * buf, size_t len);
int fd_sctp_sendstr(int sock, uint16_t strid, uint8_t * buf, size_t len, int * cc_closing);
int fd_sctp_recvmeta(int sock, uint16_t * strid, uint8_t ** buf, size_t * len, int *event, int * cc_closing);
/* TLS over SCTP (multi-stream) */
......
......@@ -1041,7 +1041,7 @@ next:
}
/* Send a buffer over a specified stream */
int fd_sctp_sendstr(int sock, uint16_t strid, uint8_t * buf, size_t len)
int fd_sctp_sendstr(int sock, uint16_t strid, uint8_t * buf, size_t len, int * cc_closing)
{
struct msghdr mhdr;
struct iovec iov;
......@@ -1050,8 +1050,10 @@ int fd_sctp_sendstr(int sock, uint16_t strid, uint8_t * buf, size_t len)
struct sctp_sndrcvinfo sndrcv;
} anci;
ssize_t ret;
int timedout = 0;
TRACE_ENTRY("%d %hu %p %zd", sock, strid, buf, len);
TRACE_ENTRY("%d %hu %p %zd %p", sock, strid, buf, len, cc_closing);
CHECK_PARAMS(cc_closing);
memset(&mhdr, 0, sizeof(mhdr));
memset(&iov, 0, sizeof(iov));
......@@ -1077,8 +1079,19 @@ int fd_sctp_sendstr(int sock, uint16_t strid, uint8_t * buf, size_t len)
mhdr.msg_controllen = sizeof(anci);
TRACE_DEBUG(FULL, "Sending %db data on stream %hu of socket %d", len, strid, sock);
again:
ret = sendmsg(sock, &mhdr, 0);
/* Handle special case of timeout */
if ((ret < 0) && (errno == EAGAIN)) {
if (!*cc_closing)
goto again; /* don't care, just ignore */
if (!timedout) {
timedout ++; /* allow for one timeout while closing */
goto again;
}
}
CHECK_SYS( ret = sendmsg(sock, &mhdr, 0) );
CHECK_SYS( ret );
ASSERT( ret == len ); /* There should not be partial delivery with sendmsg... */
return 0;
......
......@@ -165,7 +165,7 @@ static ssize_t sctps_push(gnutls_transport_ptr_t tr, const void * data, size_t l
TRACE_ENTRY("%p %p %zd", tr, data, len);
CHECK_PARAMS_DO( tr && data, { errno = EINVAL; return -1; } );
CHECK_FCT_DO( fd_sctp_sendstr(ctx->parent->cc_socket, ctx->strid, (uint8_t *)data, len), /* errno is already set */ return -1 );
CHECK_FCT_DO( fd_sctp_sendstr(ctx->parent->cc_socket, ctx->strid, (uint8_t *)data, len, &ctx->parent->cc_closing), /* errno is already set */ return -1 );
return len;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment