From 4b303402a76a5d2fe85ff8cdaf7a98d6dcfa94ee Mon Sep 17 00:00:00 2001 From: Sergey KHripchenko Date: Fri, 6 Apr 2012 20:04:35 +0400 Subject: [PATCH] more flexible keepalive options detection + awful options documentation --- acinclude.m4 | 112 +++++++++++++++++++++++++++++++++++------ configure.in | 27 ++++++++-- doc/zmq_getsockopt.txt | 63 +++++++++++++++++++++++ doc/zmq_setsockopt.txt | 66 ++++++++++++++++++++++++ src/ip.cpp | 37 ++++++++++++-- src/options.cpp | 9 ++-- 6 files changed, 286 insertions(+), 28 deletions(-) diff --git a/acinclude.m4 b/acinclude.m4 index 3e2c63ac..c5c27481 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -604,10 +604,10 @@ int main (int argc, char *argv []) }]) dnl ################################################################################ -dnl # LIBZMQ_CHECK_TCP_KEEPALIVE([action-if-found], [action-if-not-found]) # +dnl # LIBZMQ_CHECK_SO_KEEPALIVE([action-if-found], [action-if-not-found]) # dnl # Check if SO_KEEPALIVE is supported # dnl ################################################################################ -AC_DEFUN([LIBZMQ_CHECK_TCP_KEEPALIVE], [{ +AC_DEFUN([LIBZMQ_CHECK_SO_KEEPALIVE], [{ AC_MSG_CHECKING(whether SO_KEEPALIVE is supported) AC_TRY_RUN([/* SO_KEEPALIVE test */ #include @@ -622,19 +622,75 @@ int main (int argc, char *argv []) ); } ], - [AC_MSG_RESULT(yes) ; libzmq_cv_tcp_keepalive="yes" ; $1], - [AC_MSG_RESULT(no) ; libzmq_cv_tcp_keepalive="no" ; $2], - [AC_MSG_RESULT(not during cross-compile) ; libzmq_cv_tcp_keepalive="no"] + [AC_MSG_RESULT(yes) ; libzmq_cv_so_keepalive="yes" ; $1], + [AC_MSG_RESULT(no) ; libzmq_cv_so_keepalive="no" ; $2], + [AC_MSG_RESULT(not during cross-compile) ; libzmq_cv_so_keepalive="no"] + ) +}]) + +dnl ################################################################################ +dnl # LIBZMQ_CHECK_TCP_KEEPCNT([action-if-found], [action-if-not-found]) # +dnl # Check if TCP_KEEPCNT is supported # +dnl ################################################################################ +AC_DEFUN([LIBZMQ_CHECK_TCP_KEEPCNT], [{ + AC_MSG_CHECKING(whether TCP_KEEPCNT is supported) + AC_TRY_RUN([/* TCP_KEEPCNT test */ +#include +#include +#include +#include + +int main (int argc, char *argv []) +{ + int s, rc, opt = 1; + return ( + ((s = socket (PF_INET, SOCK_STREAM, 0)) == -1) || + ((rc = setsockopt (s, SOL_SOCKET, SO_KEEPALIVE, (char*) &opt, sizeof (int))) == -1) || + ((rc = setsockopt (s, IPPROTO_TCP, TCP_KEEPCNT, (char*) &opt, sizeof (int))) == -1) + ); +} + ], + [AC_MSG_RESULT(yes) ; libzmq_cv_tcp_keepcnt="yes" ; $1], + [AC_MSG_RESULT(no) ; libzmq_cv_tcp_keepcnt="no" ; $2], + [AC_MSG_RESULT(not during cross-compile) ; libzmq_cv_tcp_keepcnt="no"] ) }]) dnl ################################################################################ -dnl # LIBZMQ_CHECK_TCP_KEEPALIVE_OPTS([action-if-found], [action-if-not-found]) # -dnl # Check if TCP_KEEPCNT, TCP_KEEPIDLE, TCP_KEEPINTVL are supported # +dnl # LIBZMQ_CHECK_TCP_KEEPIDLE([action-if-found], [action-if-not-found]) # +dnl # Check if TCP_KEEPIDLE is supported # dnl ################################################################################ -AC_DEFUN([LIBZMQ_CHECK_TCP_KEEPALIVE_OPTS], [{ - AC_MSG_CHECKING(whether TCP_KEEPCNT TCP_KEEPIDLE TCP_KEEPINTVL are supported) - AC_TRY_RUN([/* TCP_KEEPCNT TCP_KEEPIDLE TCP_KEEPINTVL test */ +AC_DEFUN([LIBZMQ_CHECK_TCP_KEEPIDLE], [{ + AC_MSG_CHECKING(whether TCP_KEEPIDLE is supported) + AC_TRY_RUN([/* TCP_KEEPIDLE test */ +#include +#include +#include +#include + +int main (int argc, char *argv []) +{ + int s, rc, opt = 1; + return ( + ((s = socket (PF_INET, SOCK_STREAM, 0)) == -1) || + ((rc = setsockopt (s, SOL_SOCKET, SO_KEEPALIVE, (char*) &opt, sizeof (int))) == -1) || + ((rc = setsockopt (s, IPPROTO_TCP, TCP_KEEPIDLE, (char*) &opt, sizeof (int))) == -1) + ); +} + ], + [AC_MSG_RESULT(yes) ; libzmq_cv_tcp_keepidle="yes" ; $1], + [AC_MSG_RESULT(no) ; libzmq_cv_tcp_keepidle="no" ; $2], + [AC_MSG_RESULT(not during cross-compile) ; libzmq_cv_tcp_keepidle="no"] + ) +}]) + +dnl ################################################################################ +dnl # LIBZMQ_CHECK_TCP_KEEPINTVL([action-if-found], [action-if-not-found]) # +dnl # Check if TCP_KEEPINTVL is supported # +dnl ################################################################################ +AC_DEFUN([LIBZMQ_CHECK_TCP_KEEPINTVL], [{ + AC_MSG_CHECKING(whether TCP_KEEPINTVL is supported) + AC_TRY_RUN([/* TCP_KEEPINTVL test */ #include #include #include @@ -646,15 +702,41 @@ int main (int argc, char *argv []) return ( ((s = socket (PF_INET, SOCK_STREAM, 0)) == -1) || ((rc = setsockopt (s, SOL_SOCKET, SO_KEEPALIVE, (char*) &opt, sizeof (int))) == -1) || - ((rc = setsockopt (s, IPPROTO_TCP, TCP_KEEPCNT, (char*) &opt, sizeof (int))) == -1) || - ((rc = setsockopt (s, IPPROTO_TCP, TCP_KEEPIDLE, (char*) &opt, sizeof (int))) == -1) || ((rc = setsockopt (s, IPPROTO_TCP, TCP_KEEPINTVL, (char*) &opt, sizeof (int))) == -1) ); } ], - [AC_MSG_RESULT(yes) ; libzmq_cv_tcp_keepalive_opts="yes" ; $1], - [AC_MSG_RESULT(no) ; libzmq_cv_tcp_keepalive_opts="no" ; $2], - [AC_MSG_RESULT(not during cross-compile) ; libzmq_cv_tcp_keepalive_opts="no"] + [AC_MSG_RESULT(yes) ; libzmq_cv_tcp_keepintvl="yes" ; $1], + [AC_MSG_RESULT(no) ; libzmq_cv_tcp_keepintvl="no" ; $2], + [AC_MSG_RESULT(not during cross-compile) ; libzmq_cv_tcp_keepintvl="no"] + ) +}]) + +dnl ################################################################################ +dnl # LIBZMQ_CHECK_TCP_KEEPALIVE([action-if-found], [action-if-not-found]) # +dnl # Check if TCP_KEEPALIVE is supported # +dnl ################################################################################ +AC_DEFUN([LIBZMQ_CHECK_TCP_KEEPALIVE], [{ + AC_MSG_CHECKING(whether TCP_KEEPALIVE is supported) + AC_TRY_RUN([/* TCP_KEEPALIVE test */ +#include +#include +#include +#include + +int main (int argc, char *argv []) +{ + int s, rc, opt = 1; + return ( + ((s = socket (PF_INET, SOCK_STREAM, 0)) == -1) || + ((rc = setsockopt (s, SOL_SOCKET, SO_KEEPALIVE, (char*) &opt, sizeof (int))) == -1) || + ((rc = setsockopt (s, IPPROTO_TCP, TCP_KEEPALIVE, (char*) &opt, sizeof (int))) == -1) + ); +} + ], + [AC_MSG_RESULT(yes) ; libzmq_cv_tcp_keepalive="yes" ; $1], + [AC_MSG_RESULT(no) ; libzmq_cv_tcp_keepalive="no" ; $2], + [AC_MSG_RESULT(not during cross-compile) ; libzmq_cv_tcp_keepalive="no"] ) }]) diff --git a/configure.in b/configure.in index fd8ea0aa..71520151 100644 --- a/configure.in +++ b/configure.in @@ -383,15 +383,32 @@ LIBZMQ_CHECK_SOCK_CLOEXEC([AC_DEFINE( [1], [Whether SOCK_CLOEXEC is defined and functioning.]) ]) -LIBZMQ_CHECK_TCP_KEEPALIVE([AC_DEFINE( - [ZMQ_HAVE_TCP_KEEPALIVE], + +# TCP keep-alives Checks. +LIBZMQ_CHECK_SO_KEEPALIVE([AC_DEFINE( + [ZMQ_HAVE_SO_KEEPALIVE], [1], [Whether SO_KEEPALIVE is supported.]) ]) -LIBZMQ_CHECK_TCP_KEEPALIVE_OPTS([AC_DEFINE( - [ZMQ_HAVE_TCP_KEEPALIVE_OPTS], +LIBZMQ_CHECK_TCP_KEEPCNT([AC_DEFINE( + [ZMQ_HAVE_TCP_KEEPCNT], + [1], + [Whether TCP_KEEPCNT is supported.]) + ]) +LIBZMQ_CHECK_TCP_KEEPIDLE([AC_DEFINE( + [ZMQ_HAVE_TCP_KEEPIDLE], + [1], + [Whether TCP_KEEPIDLE is supported.]) + ]) +LIBZMQ_CHECK_TCP_KEEPINTVL([AC_DEFINE( + [ZMQ_HAVE_TCP_KEEPINTVL], + [1], + [Whether TCP_KEEPINTVL is supported.]) + ]) +LIBZMQ_CHECK_TCP_KEEPALIVE([AC_DEFINE( + [ZMQ_HAVE_TCP_KEEPALIVE], [1], - [Whether TCP_KEEPCNT, TCP_KEEPIDLE, TCP_KEEPINTVL are supported.]) + [Whether TCP_KEEPALIVE is supported.]) ]) # Subst LIBZMQ_EXTRA_CFLAGS & CXXFLAGS & LDFLAGS diff --git a/doc/zmq_getsockopt.txt b/doc/zmq_getsockopt.txt index c110abaa..91b95f51 100644 --- a/doc/zmq_getsockopt.txt +++ b/doc/zmq_getsockopt.txt @@ -404,6 +404,69 @@ Option value unit:: N/A Default value:: NULL Applicable socket types:: all, when binding TCP or IPC transports +ZMQ_TCP_KEEPALIVE: Retrieve override TCP keepalives flag +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Retrieve override OS TCP keepalives on/off flag (maps to SO_KEEPALIVE socket option). +When equal to `1`(or `0`) TCP keepalives will be turned on(or off) for each new TCP connection +of ZeroMQ socket, `-1` value disables TCP keepalives adjustments. +If the host OS does not support it then setsockopt() call will return `0` but leave this option equal to `-1`. + +TCP keepalives are zero-length TCP packets automatically generated by OS +and transparrent to application socket, used to update state of TCP connection. +This also can be used to prevent the infrastructure (VPNs, NATs and similar) to terminate +connections with no activity. + +[horizontal] +Option value type:: int +Option value unit:: -1,0,1 +Default value:: -1 (leave for OS default) +Applicable socket types:: all, when using TCP transports. + +ZMQ_TCP_KEEPALIVE_IDLE: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Retrieve option value to override the interval between the last data packet sent over +the TCP socket and the first keepalive probe (maps to TCP_KEEPCNT or TCP_KEEPALIVE socket option). + +Default value `-1` disables adjustment. +If the host OS does not support it then setsockopt() call will return `0` but leave this option equal to `-1`. + +[horizontal] +Option value type:: int +Option value unit:: -1,>0 +Default value:: -1 (leave for OS default) +Applicable socket types:: all, when using TCP transports. + +ZMQ_TCP_KEEPALIVE_CNT: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Retrieve option value to override the number of unacknowledged keepalive probes +to send over the TCP socket before considering the connection dead and notifying +the application ZeroMQ layer (maps to TCP_KEEPCNT socket option). + +Default value `-1` disables adjustment. +If the host OS does not support it then setsockopt() call will return `0` but leave this option equal to `-1`. + +[horizontal] +Option value type:: int +Option value unit:: -1,>0 +Default value:: -1 (leave for OS default) +Applicable socket types:: all, when using TCP transports. + +ZMQ_TCP_KEEPALIVE_INTVL: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Retrieve option value to override the interval between subsequential keepalive probes, +regardless of what the TCP connection has exchanged in the meantime +(maps to TCP_KEEPINTVL socket option). + +Default value `-1` disables adjustment. +If the host OS does not support it then setsockopt() call will return `0` but leave this option equal to `-1`. + +[horizontal] +Option value type:: int +Option value unit:: -1,>0 +Default value:: -1 (leave for OS default) +Applicable socket types:: all, when using TCP transports. + + RETURN VALUE ------------ The _zmq_getsockopt()_ function shall return zero if successful. Otherwise it diff --git a/doc/zmq_setsockopt.txt b/doc/zmq_setsockopt.txt index 7efb29cb..e0217fc6 100644 --- a/doc/zmq_setsockopt.txt +++ b/doc/zmq_setsockopt.txt @@ -367,6 +367,72 @@ Default value:: 0 (false) Applicable socket types:: ZMQ_ROUTER +ZMQ_TCP_KEEPALIVE: Set TCP keepalives flag +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Sets the option to override TCP keepalives on/off flag (maps to SO_KEEPALIVE socket option). +When set to `1`(or `0`) TCP keepalives will be turned on(or off) for each new TCP connection +of ZeroMQ socket, `-1` value disables TCP keepalives adjustments. +If the host OS does not support it then setsockopt() call will return `0` but leave this option equal to `-1`. + +TCP keepalives are zero-length TCP packets automatically generated by OS +and transparrent to application socket, used to update state of TCP connection. +This also can be used to prevent the infrastructure (VPNs, NATs and similar) to terminate +connections with no activity. + +[horizontal] +Option value type:: int +Option value unit:: -1,0,1 +Default value:: -1 (leave for OS default) +Applicable socket types:: all, when using TCP transports. + + +ZMQ_TCP_KEEPALIVE_IDLE: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Sets option value to override the interval between the last data packet sent over +the TCP socket and the first keepalive probe (maps to TCP_KEEPCNT or TCP_KEEPALIVE socket option). + +Default value `-1` disables adjustment. +If the host OS does not support it then setsockopt() call will return `0` but leave this option equal to `-1`. + +[horizontal] +Option value type:: int +Option value unit:: -1,>0 +Default value:: -1 (leave for OS default) +Applicable socket types:: all, when using TCP transports. + + +ZMQ_TCP_KEEPALIVE_CNT: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Sets option value to override the number of unacknowledged keepalive probes +to send over the TCP socket before considering the connection dead and notifying +the application ZeroMQ layer (maps to TCP_KEEPCNT socket option). + +Default value `-1` disables adjustment. +If the host OS does not support it then setsockopt() call will return `0` but leave this option equal to `-1`. + +[horizontal] +Option value type:: int +Option value unit:: -1,>0 +Default value:: -1 (leave for OS default) +Applicable socket types:: all, when using TCP transports. + + +ZMQ_TCP_KEEPALIVE_INTVL: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Sets option value to override the interval between subsequential keepalive probes, +regardless of what the TCP connection has exchanged in the meantime +(maps to TCP_KEEPINTVL socket option). + +Default value `-1` disables adjustment. +If the host OS does not support it then setsockopt() call will return `0` but leave this option equal to `-1`. + +[horizontal] +Option value type:: int +Option value unit:: -1,>0 +Default value:: -1 (leave for OS default) +Applicable socket types:: all, when using TCP transports. + + RETURN VALUE ------------ The _zmq_setsockopt()_ function shall return zero if successful. Otherwise it diff --git a/src/ip.cpp b/src/ip.cpp index 60f2244e..a6456e82 100644 --- a/src/ip.cpp +++ b/src/ip.cpp @@ -87,7 +87,7 @@ void zmq::tune_tcp_keepalives (fd_t s_, int keepalive_, int keepalive_cnt_, int { // Tuning TCP keep-alives if platform allows it // All values = -1 means skip and leave it for OS -#ifdef ZMQ_HAVE_TCP_KEEPALIVE +#ifdef ZMQ_HAVE_SO_KEEPALIVE if (keepalive_ != -1) { int rc = setsockopt (s_, SOL_SOCKET, SO_KEEPALIVE, (char*) &keepalive_, sizeof (int)); #ifdef ZMQ_HAVE_WINDOWS @@ -96,22 +96,51 @@ void zmq::tune_tcp_keepalives (fd_t s_, int keepalive_, int keepalive_cnt_, int errno_assert (rc == 0); #endif -#if defined ZMQ_HAVE_TCP_KEEPALIVE_OPTS && !defined ZMQ_HAVE_WINDOWS +#ifdef ZMQ_HAVE_TCP_KEEPCNT if (keepalive_cnt_ != -1) { int rc = setsockopt (s_, IPPROTO_TCP, TCP_KEEPCNT, &keepalive_cnt_, sizeof (int)); +#ifdef ZMQ_HAVE_WINDOWS + wsa_assert (rc != SOCKET_ERROR); +#else errno_assert (rc == 0); +#endif } +#endif // ZMQ_HAVE_TCP_KEEPCNT + +#ifdef ZMQ_HAVE_TCP_KEEPIDLE if (keepalive_idle_ != -1) { int rc = setsockopt (s_, IPPROTO_TCP, TCP_KEEPIDLE, &keepalive_idle_, sizeof (int)); +#ifdef ZMQ_HAVE_WINDOWS + wsa_assert (rc != SOCKET_ERROR); +#else errno_assert (rc == 0); +#endif } +#else // ZMQ_HAVE_TCP_KEEPIDLE +#ifdef ZMQ_HAVE_TCP_KEEPALIVE + if (keepalive_idle_ != -1) { + int rc = setsockopt (s_, IPPROTO_TCP, TCP_KEEPALIVE, &keepalive_idle_, sizeof (int)); +#ifdef ZMQ_HAVE_WINDOWS + wsa_assert (rc != SOCKET_ERROR); +#else + errno_assert (rc == 0); +#endif + } +#endif // ZMQ_HAVE_TCP_KEEPALIVE +#endif // ZMQ_HAVE_TCP_KEEPIDLE + +#ifdef ZMQ_HAVE_TCP_KEEPINTVL if (keepalive_intvl_ != -1) { int rc = setsockopt (s_, IPPROTO_TCP, TCP_KEEPINTVL, &keepalive_intvl_, sizeof (int)); +#ifdef ZMQ_HAVE_WINDOWS + wsa_assert (rc != SOCKET_ERROR); +#else errno_assert (rc == 0); - } #endif + } +#endif // ZMQ_HAVE_TCP_KEEPINTVL } -#endif +#endif // ZMQ_HAVE_SO_KEEPALIVE } void zmq::unblock_socket (fd_t s_) diff --git a/src/options.cpp b/src/options.cpp index 6c9f6482..ef608829 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -230,7 +230,7 @@ int zmq::options_t::setsockopt (int option_, const void *optval_, errno = EINVAL; return -1; } -#ifdef ZMQ_HAVE_TCP_KEEPALIVE +#if defined ZMQ_HAVE_SO_KEEPALIVE tcp_keepalive = val; #endif return 0; @@ -247,7 +247,7 @@ int zmq::options_t::setsockopt (int option_, const void *optval_, errno = EINVAL; return -1; } -#if defined ZMQ_HAVE_TCP_KEEPALIVE && defined ZMQ_HAVE_TCP_KEEPALIVE_OPTS +#if defined ZMQ_HAVE_SO_KEEPALIVE && defined ZMQ_HAVE_TCP_KEEPCNT tcp_keepalive_cnt = val; #endif return 0; @@ -264,7 +264,8 @@ int zmq::options_t::setsockopt (int option_, const void *optval_, errno = EINVAL; return -1; } -#if defined ZMQ_HAVE_TCP_KEEPALIVE && defined ZMQ_HAVE_TCP_KEEPALIVE_OPTS + +#if defined ZMQ_HAVE_SO_KEEPALIVE && (defined ZMQ_HAVE_TCP_KEEPIDLE || defined ZMQ_HAVE_TCP_KEEPALIVE) tcp_keepalive_idle = val; #endif return 0; @@ -281,7 +282,7 @@ int zmq::options_t::setsockopt (int option_, const void *optval_, errno = EINVAL; return -1; } -#if defined ZMQ_HAVE_TCP_KEEPALIVE && defined ZMQ_HAVE_TCP_KEEPALIVE_OPTS +#if defined ZMQ_HAVE_SO_KEEPALIVE && defined ZMQ_HAVE_TCP_KEEPINTVL tcp_keepalive_intvl = val; #endif return 0;