changeset 201:1b47afa59358

Also timeout on sends
author Sebastien Decugis <sdecugis@nict.go.jp>
date Wed, 10 Feb 2010 11:22:42 +0900
parents ff557d8b48d7
children b4380eb4174d
files freeDiameter/cnxctx.c freeDiameter/cnxctx.h freeDiameter/sctp.c freeDiameter/sctps.c
diffstat 4 files changed, 37 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/freeDiameter/cnxctx.c	Tue Feb 09 18:30:53 2010 +0900
+++ b/freeDiameter/cnxctx.c	Wed Feb 10 11:22:42 2010 +0900
@@ -506,6 +506,7 @@
 	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 @@
 /* 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 @@
 		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 @@
 				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;
--- a/freeDiameter/cnxctx.h	Tue Feb 09 18:30:53 2010 +0900
+++ b/freeDiameter/cnxctx.h	Wed Feb 10 11:22:42 2010 +0900
@@ -102,7 +102,7 @@
 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) */
--- a/freeDiameter/sctp.c	Tue Feb 09 18:30:53 2010 +0900
+++ b/freeDiameter/sctp.c	Wed Feb 10 11:22:42 2010 +0900
@@ -1041,7 +1041,7 @@
 }
 
 /* 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 @@
 		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 @@
 	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;
--- a/freeDiameter/sctps.c	Tue Feb 09 18:30:53 2010 +0900
+++ b/freeDiameter/sctps.c	Wed Feb 10 11:22:42 2010 +0900
@@ -165,7 +165,7 @@
 	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;
 }
"Welcome to our mercurial repository"