Mercurial > hg > freeDiameter
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; }