diff --git a/3ad076.patch b/3ad076.patch new file mode 100644 index 0000000..6876be4 --- /dev/null +++ b/3ad076.patch @@ -0,0 +1,410 @@ +From 1586f3f25ebb4b479e4334eccb551634425bcb0f Mon Sep 17 00:00:00 2001 +From: Luca Boccassi +Date: Mon, 18 Apr 2016 17:12:01 +0100 +Subject: [PATCH 1/3] Problem: can't test if IPv6 is available in tests + +Solution: add helper function is_ipv6_available to testutil.hpp to +test if IPv6 is available on the building platform. +This function will try to open and bind a socket to ::1:*, as it's +the ultimate way of knowing if, at least on the loopback, IPv6 is +enabled. +--- + tests/testutil.hpp | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 52 insertions(+) + +Index: zeromq-4.1.4/tests/testutil.hpp +=================================================================== +--- zeromq-4.1.4.orig/tests/testutil.hpp ++++ zeromq-4.1.4/tests/testutil.hpp +@@ -47,6 +47,7 @@ + #include + + #if defined _WIN32 ++# include "windows.hpp" + # if defined _MSC_VER + # include + # pragma warning(disable:4996) +@@ -56,6 +57,9 @@ + # include + # include + # include ++# include ++# include ++# include + #endif + + // Bounce a message from client to server and back +@@ -299,5 +303,53 @@ void msleep (int milliseconds) + #endif + } + ++// check if IPv6 is available (0/false if not, 1/true if it is) ++// only way to reliably check is to actually open a socket and try to bind it ++int ++is_ipv6_available(void) ++{ ++ int rc, ipv6 = 1; ++ struct sockaddr_in6 test_addr; ++ ++ memset (&test_addr, 0, sizeof (test_addr)); ++ test_addr.sin6_family = AF_INET6; ++ inet_pton (AF_INET6, "::1", &(test_addr.sin6_addr)); ++ ++#ifdef ZMQ_HAVE_WINDOWS ++ SOCKET fd = socket (AF_INET6, SOCK_STREAM, IPPROTO_IP); ++ if (fd == INVALID_SOCKET) ++ ipv6 = 0; ++ else { ++ setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&ipv6, sizeof(int)); ++ rc = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&ipv6, sizeof(int)); ++ if (rc == SOCKET_ERROR) ++ ipv6 = 0; ++ else { ++ rc = bind (fd, (struct sockaddr *)&test_addr, sizeof (test_addr)); ++ if (rc == SOCKET_ERROR) ++ ipv6 = 0; ++ } ++ closesocket (fd); ++ } ++#else ++ int fd = socket (AF_INET6, SOCK_STREAM, IPPROTO_IP); ++ if (fd == -1) ++ ipv6 = 0; ++ else { ++ setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &ipv6, sizeof(int)); ++ rc = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6, sizeof(int)); ++ if (rc != 0) ++ ipv6 = 0; ++ else { ++ rc = bind (fd, (struct sockaddr *)&test_addr, sizeof (test_addr)); ++ if (rc != 0) ++ ipv6 = 0; ++ } ++ close (fd); ++ } ++#endif ++ ++ return ipv6; ++} + + #endif +From 0af39a443f39c1a0bb5d7d60ca8667b4e33599f4 Mon Sep 17 00:00:00 2001 +From: Luca Boccassi +Date: Mon, 18 Apr 2016 00:02:36 +0100 +Subject: [PATCH 2/3] Problem: can't unbind with bound addr with IPv6 + +Solution: try to resolve the TCP endpoint passed by the user in the +zmq_unbind call before giving up, if it doesn't match. +This fixes a breakage in the API, where after a call to +zmq_bind(s, "tcp://127.0.0.1:9999") with IPv6 enabled on s would +result in the call to zmq_unbind(s, "tcp://127.0.0.1:9999") failing. +Add more test cases to increase coverage on all combinations of TCP +endpoints. +--- + src/socket_base.cpp | 32 +++++- + tests/test_unbind_wildcard.cpp | 228 +++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 259 insertions(+), 1 deletion(-) + +diff --git a/src/socket_base.cpp b/src/socket_base.cpp +index ec01836..9d34d7e 100644 +Index: zeromq-4.1.4/src/socket_base.cpp +=================================================================== +--- zeromq-4.1.4.orig/src/socket_base.cpp ++++ zeromq-4.1.4/src/socket_base.cpp +@@ -765,8 +765,38 @@ int zmq::socket_base_t::term_endpoint (c + return 0; + } + ++ std::string resolved_addr = std::string (addr_); ++ std::pair range; ++ ++ // The resolved last_endpoint is used as a key in the endpoints map. ++ // The address passed by the user might not match in the TCP case due to ++ // IPv4-in-IPv6 mapping (EG: tcp://[::ffff:127.0.0.1]:9999), so try to ++ // resolve before giving up. Given at this stage we don't know whether a ++ // socket is connected or bound, try with both. ++ if (protocol == "tcp") { ++ range = endpoints.equal_range (resolved_addr); ++ if (range.first == range.second) { ++ tcp_address_t *tcp_addr = new (std::nothrow) tcp_address_t (); ++ alloc_assert (tcp_addr); ++ rc = tcp_addr->resolve (address.c_str (), false, options.ipv6); ++ ++ if (rc == 0) { ++ tcp_addr->to_string (resolved_addr); ++ range = endpoints.equal_range (resolved_addr); ++ ++ if (range.first == range.second) { ++ rc = tcp_addr->resolve (address.c_str (), true, options.ipv6); ++ if (rc == 0) { ++ tcp_addr->to_string (resolved_addr); ++ } ++ } ++ } ++ delete tcp_addr; ++ } ++ } ++ + // Find the endpoints range (if any) corresponding to the addr_ string. +- std::pair range = endpoints.equal_range (std::string (addr_)); ++ range = endpoints.equal_range (resolved_addr); + if (range.first == range.second) { + errno = ENOENT; + return -1; +Index: zeromq-4.1.4/tests/test_unbind_wildcard.cpp +=================================================================== +--- zeromq-4.1.4.orig/tests/test_unbind_wildcard.cpp ++++ zeromq-4.1.4/tests/test_unbind_wildcard.cpp +@@ -22,11 +22,16 @@ + int main (void) + { + setup_test_environment(); ++ int ipv6 = is_ipv6_available (); + void *ctx = zmq_ctx_new (); + assert (ctx); + ++ /* Address wildcard, IPv6 disabled */ + void *sb = zmq_socket (ctx, ZMQ_REP); + assert (sb); ++ void *sc = zmq_socket (ctx, ZMQ_REQ); ++ assert (sc); ++ + int rc = zmq_bind (sb, "tcp://*:5555"); + assert (rc == 0); + +@@ -35,12 +40,235 @@ int main (void) + rc = zmq_getsockopt (sb, ZMQ_LAST_ENDPOINT, endpoint, &endpoint_len); + assert (rc == 0); + ++ rc = zmq_connect (sc, endpoint); ++ assert (rc == 0); ++ ++ bounce (sb, sc); ++ ++ rc = zmq_disconnect (sc, endpoint); ++ assert (rc == 0); ++ rc = zmq_unbind (sb, endpoint); ++ assert (rc == 0); ++ ++ rc = zmq_close (sc); ++ assert (rc == 0); ++ rc = zmq_close (sb); ++ assert (rc == 0); ++ ++ /* Address wildcard, IPv6 enabled */ ++ sb = zmq_socket (ctx, ZMQ_REP); ++ assert (sb); ++ sc = zmq_socket (ctx, ZMQ_REQ); ++ assert (sc); ++ ++ rc = zmq_setsockopt (sb, ZMQ_IPV6, &ipv6, sizeof (int)); ++ assert (rc == 0); ++ rc = zmq_setsockopt (sc, ZMQ_IPV6, &ipv6, sizeof (int)); ++ assert (rc == 0); ++ ++ rc = zmq_bind (sb, "tcp://*:5556"); ++ assert (rc == 0); ++ ++ endpoint_len = sizeof (endpoint); ++ memset(endpoint, 0, endpoint_len); ++ rc = zmq_getsockopt (sb, ZMQ_LAST_ENDPOINT, endpoint, &endpoint_len); ++ assert (rc == 0); ++ ++ rc = zmq_connect (sc, endpoint); ++ assert (rc == 0); ++ ++ bounce (sb, sc); ++ ++ rc = zmq_disconnect (sc, endpoint); ++ assert (rc == 0); + rc = zmq_unbind (sb, endpoint); + assert (rc == 0); + ++ rc = zmq_close (sc); ++ assert (rc == 0); + rc = zmq_close (sb); + assert (rc == 0); + ++ /* Port wildcard, IPv4 address, IPv6 disabled */ ++ sb = zmq_socket (ctx, ZMQ_REP); ++ assert (sb); ++ sc = zmq_socket (ctx, ZMQ_REQ); ++ assert (sc); ++ ++ rc = zmq_bind (sb, "tcp://127.0.0.1:*"); ++ assert (rc == 0); ++ ++ endpoint_len = sizeof (endpoint); ++ memset(endpoint, 0, endpoint_len); ++ rc = zmq_getsockopt (sb, ZMQ_LAST_ENDPOINT, endpoint, &endpoint_len); ++ assert (rc == 0); ++ ++ rc = zmq_connect (sc, endpoint); ++ assert (rc == 0); ++ ++ bounce (sb, sc); ++ ++ rc = zmq_disconnect (sc, endpoint); ++ assert (rc == 0); ++ rc = zmq_unbind (sb, endpoint); ++ assert (rc == 0); ++ ++ rc = zmq_close (sc); ++ assert (rc == 0); ++ rc = zmq_close (sb); ++ assert (rc == 0); ++ ++ /* Port wildcard, IPv4 address, IPv6 enabled */ ++ sb = zmq_socket (ctx, ZMQ_REP); ++ assert (sb); ++ sc = zmq_socket (ctx, ZMQ_REQ); ++ assert (sc); ++ ++ rc = zmq_setsockopt (sb, ZMQ_IPV6, &ipv6, sizeof (int)); ++ assert (rc == 0); ++ rc = zmq_setsockopt (sc, ZMQ_IPV6, &ipv6, sizeof (int)); ++ assert (rc == 0); ++ ++ rc = zmq_bind (sb, "tcp://127.0.0.1:*"); ++ assert (rc == 0); ++ ++ endpoint_len = sizeof (endpoint); ++ memset(endpoint, 0, endpoint_len); ++ rc = zmq_getsockopt (sb, ZMQ_LAST_ENDPOINT, endpoint, &endpoint_len); ++ assert (rc == 0); ++ ++ rc = zmq_connect (sc, endpoint); ++ assert (rc == 0); ++ ++ bounce (sb, sc); ++ ++ rc = zmq_disconnect (sc, endpoint); ++ assert (rc == 0); ++ rc = zmq_unbind (sb, endpoint); ++ assert (rc == 0); ++ ++ rc = zmq_close (sc); ++ assert (rc == 0); ++ rc = zmq_close (sb); ++ assert (rc == 0); ++ ++ if (ipv6) { ++ /* Port wildcard, IPv6 address, IPv6 enabled */ ++ sb = zmq_socket (ctx, ZMQ_REP); ++ assert (sb); ++ sc = zmq_socket (ctx, ZMQ_REQ); ++ assert (sc); ++ ++ rc = zmq_setsockopt (sb, ZMQ_IPV6, &ipv6, sizeof (int)); ++ assert (rc == 0); ++ rc = zmq_setsockopt (sc, ZMQ_IPV6, &ipv6, sizeof (int)); ++ assert (rc == 0); ++ ++ rc = zmq_bind (sb, "tcp://[::1]:*"); ++ assert (rc == 0); ++ ++ endpoint_len = sizeof (endpoint); ++ memset(endpoint, 0, endpoint_len); ++ rc = zmq_getsockopt (sb, ZMQ_LAST_ENDPOINT, endpoint, &endpoint_len); ++ assert (rc == 0); ++ ++ rc = zmq_connect (sc, endpoint); ++ assert (rc == 0); ++ ++ bounce (sb, sc); ++ ++ rc = zmq_disconnect (sc, endpoint); ++ assert (rc == 0); ++ rc = zmq_unbind (sb, endpoint); ++ assert (rc == 0); ++ ++ rc = zmq_close (sc); ++ assert (rc == 0); ++ rc = zmq_close (sb); ++ assert (rc == 0); ++ } ++ ++ /* No wildcard, IPv4 address, IPv6 disabled */ ++ sb = zmq_socket (ctx, ZMQ_REP); ++ assert (sb); ++ sc = zmq_socket (ctx, ZMQ_REQ); ++ assert (sc); ++ ++ rc = zmq_bind (sb, "tcp://127.0.0.1:5557"); ++ assert (rc == 0); ++ rc = zmq_connect (sc, "tcp://127.0.0.1:5557"); ++ assert (rc == 0); ++ ++ bounce (sb, sc); ++ ++ rc = zmq_disconnect (sc, "tcp://127.0.0.1:5557"); ++ assert (rc == 0); ++ rc = zmq_unbind (sb, "tcp://127.0.0.1:5557"); ++ assert (rc == 0); ++ ++ rc = zmq_close (sc); ++ assert (rc == 0); ++ rc = zmq_close (sb); ++ assert (rc == 0); ++ ++ /* No wildcard, IPv4 address, IPv6 enabled */ ++ sb = zmq_socket (ctx, ZMQ_REP); ++ assert (sb); ++ sc = zmq_socket (ctx, ZMQ_REQ); ++ assert (sc); ++ ++ rc = zmq_setsockopt (sb, ZMQ_IPV6, &ipv6, sizeof (int)); ++ assert (rc == 0); ++ rc = zmq_setsockopt (sc, ZMQ_IPV6, &ipv6, sizeof (int)); ++ assert (rc == 0); ++ ++ rc = zmq_bind (sb, "tcp://127.0.0.1:5558"); ++ assert (rc == 0); ++ rc = zmq_connect (sc, "tcp://127.0.0.1:5558"); ++ assert (rc == 0); ++ ++ bounce (sb, sc); ++ ++ rc = zmq_disconnect (sc, "tcp://127.0.0.1:5558"); ++ assert (rc == 0); ++ rc = zmq_unbind (sb, "tcp://127.0.0.1:5558"); ++ assert (rc == 0); ++ ++ rc = zmq_close (sc); ++ assert (rc == 0); ++ rc = zmq_close (sb); ++ assert (rc == 0); ++ ++ if (ipv6) { ++ /* No wildcard, IPv6 address, IPv6 enabled */ ++ sb = zmq_socket (ctx, ZMQ_REP); ++ assert (sb); ++ sc = zmq_socket (ctx, ZMQ_REQ); ++ assert (sc); ++ ++ rc = zmq_setsockopt (sb, ZMQ_IPV6, &ipv6, sizeof (int)); ++ assert (rc == 0); ++ rc = zmq_setsockopt (sc, ZMQ_IPV6, &ipv6, sizeof (int)); ++ assert (rc == 0); ++ ++ rc = zmq_bind (sb, "tcp://[::1]:5559"); ++ assert (rc == 0); ++ rc = zmq_connect (sc, "tcp://[::1]:5559"); ++ assert (rc == 0); ++ ++ bounce (sb, sc); ++ ++ rc = zmq_disconnect (sc, "tcp://[::1]:5559"); ++ assert (rc == 0); ++ rc = zmq_unbind (sb, "tcp://[::1]:5559"); ++ assert (rc == 0); ++ ++ rc = zmq_close (sc); ++ assert (rc == 0); ++ rc = zmq_close (sb); ++ assert (rc == 0); ++ } ++ + rc = zmq_ctx_term (ctx); + assert (rc == 0); + diff --git a/libsodium-init.patch b/libsodium-init.patch deleted file mode 100644 index 4d63400..0000000 --- a/libsodium-init.patch +++ /dev/null @@ -1,28 +0,0 @@ -Index: zeromq-4.1.3/src/curve_client.cpp -=================================================================== ---- zeromq-4.1.3.orig/src/curve_client.cpp -+++ zeromq-4.1.3/src/curve_client.cpp -@@ -57,8 +57,7 @@ zmq::curve_client_t::curve_client_t (con - unsigned char tmpbytes[4]; - randombytes(tmpbytes, 4); - #else -- // todo check return code -- sodium_init(); -+ zmq_assert (sodium_init() != -1); - #endif - - // Generate short-term key pair -Index: zeromq-4.1.3/src/curve_server.cpp -=================================================================== ---- zeromq-4.1.3.orig/src/curve_server.cpp -+++ zeromq-4.1.3/src/curve_server.cpp -@@ -60,8 +60,7 @@ zmq::curve_server_t::curve_server_t (ses - unsigned char tmpbytes[4]; - randombytes(tmpbytes, 4); - #else -- // todo check return code -- sodium_init(); -+ zmq_assert (sodium_init() != -1); - #endif - - // Generate short-term key pair diff --git a/zeromq-4.1.3.tar.gz b/zeromq-4.1.3.tar.gz deleted file mode 100644 index d2739a8..0000000 --- a/zeromq-4.1.3.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:61b31c830db377777e417235a24d3660a4bcc3f40d303ee58df082fcd68bf411 -size 1372069 diff --git a/zeromq-4.1.4.tar.gz b/zeromq-4.1.4.tar.gz new file mode 100644 index 0000000..fe51280 --- /dev/null +++ b/zeromq-4.1.4.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e99f44fde25c2e4cb84ce440f87ca7d3fe3271c2b8cfbc67d55e4de25e6fe378 +size 1400012 diff --git a/zeromq.changes b/zeromq.changes index f39f805..11acbe0 100644 --- a/zeromq.changes +++ b/zeromq.changes @@ -1,3 +1,33 @@ +------------------------------------------------------------------- +Mon May 30 10:02:29 UTC 2016 - adam.majer@suse.de + +- Added patch 3ad076.patch + * based on https://github.com/zeromq/zeromq4-1/commit/3ad076.patch + * refreshed and removed NEWS section + * fixes unbinding when IPv6 is available +- Add '--disable-dependency-tracking' since we are not rebuilding +- Re-enable concurrent check target, but fall back to sequential on + failure. This allows quick test building, while allows + sequential unit test run. Run tests 3x before 'official' failure as + some are a little flaky (upstream acknowledges this) + +------------------------------------------------------------------- +Mon May 30 09:23:12 UTC 2016 - adam.majer@suse.de + +- Append test_log in build output if there are failures + +------------------------------------------------------------------- +Mon May 30 08:42:24 UTC 2016 - adam.majer@suse.de + +- Update to 4.1.4 + * fixed build failure with latest libsodium + * handle IPv6 link local addresses + * fixed assertion failure in msg.cpp:390 on STREAM sockets + * fixed assertion failure in tcp.cpp after network reconnect + * fixed socket monitor hang +- Remove libsodium-init.patch - upstreamed +- Run %check rule sequentially to prevent assert failures + ------------------------------------------------------------------- Thu Nov 5 09:36:36 UTC 2015 - idonmez@suse.com diff --git a/zeromq.spec b/zeromq.spec index 96ccfe4..a05ce64 100644 --- a/zeromq.spec +++ b/zeromq.spec @@ -1,7 +1,7 @@ # # spec file for package zeromq # -# Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -21,14 +21,14 @@ %define with_pgm 1 %endif Name: zeromq -Version: 4.1.3 +Version: 4.1.4 Release: 0 Summary: Lightweight messaging kernel License: LGPL-3.0+ Group: Productivity/Networking/Web/Servers Url: http://www.zeromq.org/ Source: http://download.zeromq.org/%{name}-%{version}.tar.gz -Patch1: libsodium-init.patch +Patch: 3ad076.patch BuildRequires: asciidoc BuildRequires: gcc-c++ BuildRequires: pkgconfig @@ -110,7 +110,7 @@ This package holds the development files for ZeroMQ. %prep %setup -q -%patch1 -p1 +%patch -p1 %build %configure \ @@ -119,6 +119,7 @@ This package holds the development files for ZeroMQ. --with-pgm \ %endif --disable-static \ + --disable-dependency-tracking \ --with-pic make %{?_smp_mflags} @@ -127,7 +128,8 @@ make DESTDIR=%{buildroot} install %{?_smp_mflags} find %{buildroot} -type f -name "*.la" -delete -print %check -make check %{?_smp_mflags} +# Tests don't run well concurrently and some are flaky, hence 3x before fail +make check %{?_smp_mflags} || make check || make check || make check || (cat ./test-suite.log && false) %post -n %{lib_name} -p /sbin/ldconfig