Changeset 1200:ce2b00dc86c1 in freeDiameter for libfdcore
- Timestamp:
- Jun 14, 2013, 11:14:11 AM (11 years ago)
- Branch:
- default
- Phase:
- public
- Location:
- libfdcore
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
libfdcore/cnxctx.c
r1198 r1200 625 625 /* Set a timeout on the socket so that in any case we are not stuck waiting for something */ 626 626 memset(&tv, 0, sizeof(tv)); 627 tv.tv_ sec = 3; /* allow 3 seconds timeout for TLS session cleanup*/628 CHECK_SYS_DO( setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)), /* best effort only */);629 CHECK_SYS_DO( setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)), /* Also timeout for sending, to avoid waiting forever */);627 tv.tv_usec = 100000L; /* 100ms, to react quickly to head-of-the-line blocking. */ 628 CHECK_SYS_DO( setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)), ); 629 CHECK_SYS_DO( setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)), ); 630 630 } 631 631 … … 675 675 } 676 676 677 /* Send, for older GNUTLS */678 #ifndef GNUTLS_VERSION_212679 static ssize_t fd_cnx_s_send(struct cnxctx * conn, const void *buffer, size_t length)680 {681 ssize_t ret = 0;682 int timedout = 0;683 again:684 ret = send(conn->cc_socket, buffer, length, 0);685 /* Handle special case of timeout */686 if ((ret < 0) && ((errno == EAGAIN) || (errno == EINTR))) {687 pthread_testcancel();688 if (! fd_cnx_teststate(conn, CC_STATUS_CLOSING ))689 goto again; /* don't care, just ignore */690 if (!timedout) {691 timedout ++; /* allow for one timeout while closing */692 goto again;693 }694 CHECK_SYS_DO(ret, /* continue */);695 }696 697 /* Mark the error */698 if (ret <= 0)699 fd_cnx_markerror(conn);700 701 return ret;702 }703 #endif /* GNUTLS_VERSION_212 */704 705 677 /* Send */ 706 678 static ssize_t fd_cnx_s_sendv(struct cnxctx * conn, const struct iovec * iov, int iovcnt) 707 679 { 708 680 ssize_t ret = 0; 709 int timedout = 0; 681 struct timespec ts, now; 682 CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &ts), return -1 ); 710 683 again: 711 684 ret = writev(conn->cc_socket, iov, iovcnt); 712 685 /* Handle special case of timeout */ 713 686 if ((ret < 0) && ((errno == EAGAIN) || (errno == EINTR))) { 687 ret = -errno; 714 688 pthread_testcancel(); 715 if (! fd_cnx_teststate(conn, CC_STATUS_CLOSING )) 689 690 /* Check how much time we were blocked for this sending. */ 691 CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &now), return -1 ); 692 if ( ((now.tv_sec - ts.tv_sec) * 1000 + ((now.tv_nsec - ts.tv_nsec) / 1000000L)) > MAX_HOTL_BLOCKING_TIME) { 693 LOG_D("Unable to send any data for %dms, closing the connection", MAX_HOTL_BLOCKING_TIME); 694 } else if (! fd_cnx_teststate(conn, CC_STATUS_CLOSING )) { 716 695 goto again; /* don't care, just ignore */ 717 if (!timedout) { 718 timedout ++; /* allow for one timeout while closing */ 719 goto again; 720 } 696 } 697 698 /* propagate the error */ 699 errno = -ret; 700 ret = -1; 721 701 CHECK_SYS_DO(ret, /* continue */); 722 702 } … … 728 708 return ret; 729 709 } 710 711 /* Send, for older GNUTLS */ 712 #ifndef GNUTLS_VERSION_212 713 static ssize_t fd_cnx_s_send(struct cnxctx * conn, const void *buffer, size_t length) 714 { 715 struct iovec iov; 716 iov.iov_base = (void *)buffer; 717 iov.iov_len = length; 718 return fd_cnx_s_sendv(conn, &iov, 1); 719 } 720 #endif /* GNUTLS_VERSION_212 */ 730 721 731 722 #define ALIGNOF(t) ((char *)(&((struct { char c; t _h; } *)0)->_h) - (char *)0) /* Could use __alignof__(t) on some systems but this is more portable probably */ … … 1008 999 { 1009 1000 ssize_t ret; 1001 struct timespec ts, now; 1002 CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &ts), return -1 ); 1010 1003 again: 1011 1004 CHECK_GNUTLS_DO( ret = gnutls_record_send(session, data, sz), 1012 1005 { 1006 pthread_testcancel(); 1013 1007 switch (ret) { 1014 1008 case GNUTLS_E_REHANDSHAKE: … … 1025 1019 case GNUTLS_E_AGAIN: 1026 1020 case GNUTLS_E_INTERRUPTED: 1027 if (!fd_cnx_teststate(conn, CC_STATUS_CLOSING)) 1021 CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &now), return -1 ); 1022 if ( ((now.tv_sec - ts.tv_sec) * 1000 + ((now.tv_nsec - ts.tv_nsec) / 1000000L)) > MAX_HOTL_BLOCKING_TIME) { 1023 LOG_D("Unable to send any data for %dms, closing the connection", MAX_HOTL_BLOCKING_TIME); 1024 } else if (! fd_cnx_teststate(conn, CC_STATUS_CLOSING )) { 1028 1025 goto again; 1029 TRACE_DEBUG(INFO, "Connection is closing, so abord gnutls_record_send now.");1026 } 1030 1027 break; 1031 1028 -
libfdcore/cnxctx.h
r1186 r1200 38 38 #ifndef _CNXCTX_H 39 39 #define _CNXCTX_H 40 41 /* Maximum time we allow a connection to be blocked because of head-of-the-line buffers. After this delay, connection is considered in error. */ 42 #define MAX_HOTL_BLOCKING_TIME 1000 /* ms */ 40 43 41 44 /* The connection context structure */ -
libfdcore/sctp.c
r1198 r1200 1084 1084 #endif /* OLD_SCTP_SOCKET_API */ 1085 1085 ssize_t ret; 1086 int timedout = 0;1086 struct timespec ts, now; 1087 1087 1088 1088 TRACE_ENTRY("%p %hu %p %d", conn, strid, iov, iovcnt); 1089 1089 CHECK_PARAMS_DO(conn && iov && iovcnt, { errno = EINVAL; return -1; } ); 1090 CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &ts), return -1 ); 1090 1091 1091 1092 memset(&mhdr, 0, sizeof(mhdr)); … … 1121 1122 if ((ret < 0) && ((errno == EAGAIN) || (errno == EINTR))) { 1122 1123 pthread_testcancel(); 1123 if (! fd_cnx_teststate(conn, CC_STATUS_CLOSING )) 1124 /* Check how much time we were blocked for this sending. */ 1125 CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &now), return -1 ); 1126 if ( ((now.tv_sec - ts.tv_sec) * 1000 + ((now.tv_nsec - ts.tv_nsec) / 1000000L)) > MAX_HOTL_BLOCKING_TIME) { 1127 LOG_D("Unable to send any data for %dms, closing the connection", MAX_HOTL_BLOCKING_TIME); 1128 } else if (! fd_cnx_teststate(conn, CC_STATUS_CLOSING )) { 1124 1129 goto again; /* don't care, just ignore */ 1125 if (!timedout) { 1126 timedout ++; /* allow for one timeout while closing */ 1127 goto again; 1128 } 1130 } 1131 1132 /* propagate the error */ 1133 errno = -ret; 1134 ret = -1; 1129 1135 } 1130 1136
Note: See TracChangeset
for help on using the changeset viewer.