diff --git a/doc/zmq_setsockopt.txt b/doc/zmq_setsockopt.txt index a7ab3ab60b..ea5bb7bd38 100644 --- a/doc/zmq_setsockopt.txt +++ b/doc/zmq_setsockopt.txt @@ -361,6 +361,7 @@ no effect. Option value type:: int Option value unit:: milliseconds Default value:: 0 +Maximum value:: 6553599 (which is 2^16-1 deciseconds) Applicable socket types:: all, when using connection-oriented transports diff --git a/src/options.cpp b/src/options.cpp index 036b382dcf..d1dfbf84af 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -282,6 +282,8 @@ int zmq::options_t::set_curve_key (uint8_t *destination, return -1; } +const int deciseconds_per_millisecond = 100; + int zmq::options_t::setsockopt (int option_, const void *optval_, size_t optvallen_) @@ -665,8 +667,8 @@ int zmq::options_t::setsockopt (int option_, case ZMQ_HEARTBEAT_TTL: // Convert this to deciseconds from milliseconds - value = value / 100; - if (is_int && value >= 0 && value <= 6553) { + value = value / deciseconds_per_millisecond; + if (is_int && value >= 0 && value <= UINT16_MAX) { heartbeat_ttl = static_cast (value); return 0; } diff --git a/src/stdint.hpp b/src/stdint.hpp index 4efc86f1a2..dc4d5df1f7 100644 --- a/src/stdint.hpp +++ b/src/stdint.hpp @@ -60,6 +60,9 @@ typedef unsigned __int32 uint32_t; #ifndef uint64_t typedef unsigned __int64 uint64_t; #endif +#ifndef UINT16_MAX +#define UINT16_MAX _UI16_MAX +#endif #ifndef UINT32_MAX #define UINT32_MAX _UI32_MAX #endif diff --git a/tests/test_heartbeats.cpp b/tests/test_heartbeats.cpp index 041f1909ee..a9a66e7e81 100644 --- a/tests/test_heartbeats.cpp +++ b/tests/test_heartbeats.cpp @@ -29,6 +29,14 @@ typedef SOCKET raw_socket; typedef int raw_socket; #endif +#include + +// TODO remove this here, either ensure that UINT16_MAX is always properly +// defined or handle this at a more central location +#ifndef UINT16_MAX +#define UINT16_MAX 65535 +#endif + #include "testutil_unity.hpp" void setUp () @@ -366,6 +374,48 @@ DEFINE_TESTS (pull, push, ZMQ_PULL, ZMQ_PUSH) DEFINE_TESTS (sub, pub, ZMQ_SUB, ZMQ_PUB) DEFINE_TESTS (pair, pair, ZMQ_PAIR, ZMQ_PAIR) +const int deciseconds_per_millisecond = 100; +const int heartbeat_ttl_max = + (UINT16_MAX + 1) * deciseconds_per_millisecond - 1; + +void test_setsockopt_heartbeat_success (const int value) +{ + void *const socket = test_context_socket (ZMQ_PAIR); + TEST_ASSERT_SUCCESS_ERRNO ( + zmq_setsockopt (socket, ZMQ_HEARTBEAT_TTL, &value, sizeof (value))); + + int value_read; + size_t value_read_size = sizeof (value_read); + TEST_ASSERT_SUCCESS_ERRNO (zmq_getsockopt (socket, ZMQ_HEARTBEAT_TTL, + &value_read, &value_read_size)); + + TEST_ASSERT_EQUAL_INT (value - value % deciseconds_per_millisecond, + value_read); + + test_context_socket_close (socket); +} + +void test_setsockopt_heartbeat_ttl_max () +{ + test_setsockopt_heartbeat_success (heartbeat_ttl_max); +} + +void test_setsockopt_heartbeat_ttl_more_than_max_fails () +{ + void *const socket = test_context_socket (ZMQ_PAIR); + const int value = heartbeat_ttl_max + 1; + TEST_ASSERT_FAILURE_ERRNO ( + EINVAL, + zmq_setsockopt (socket, ZMQ_HEARTBEAT_TTL, &value, sizeof (value))); + + test_context_socket_close (socket); +} + +void test_setsockopt_heartbeat_ttl_near_zero () +{ + test_setsockopt_heartbeat_success (deciseconds_per_millisecond - 1); +} + int main (void) { setup_test_environment (); @@ -381,6 +431,10 @@ int main (void) RUN_TEST (test_heartbeat_ttl_sub_pub); RUN_TEST (test_heartbeat_ttl_pair_pair); + RUN_TEST (test_setsockopt_heartbeat_ttl_max); + RUN_TEST (test_setsockopt_heartbeat_ttl_more_than_max_fails); + RUN_TEST (test_setsockopt_heartbeat_ttl_near_zero); + RUN_TEST (test_heartbeat_notimeout_dealer_router); RUN_TEST (test_heartbeat_notimeout_req_rep); RUN_TEST (test_heartbeat_notimeout_pull_push);