zeromq/3ad076.patch
Marcus Rueckert c2b417b022 Accepting request 399056 from home:adamm:branches:devel:libraries:c_c++
- 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)

- Append test_log in build output if there are failures

- 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

OBS-URL: https://build.opensuse.org/request/show/399056
OBS-URL: https://build.opensuse.org/package/show/devel:libraries:c_c++/zeromq?expand=0&rev=43
2016-05-31 13:39:40 +00:00

411 lines
12 KiB
Diff

From 1586f3f25ebb4b479e4334eccb551634425bcb0f Mon Sep 17 00:00:00 2001
From: Luca Boccassi <luca.boccassi@gmail.com>
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 <string.h>
#if defined _WIN32
+# include "windows.hpp"
# if defined _MSC_VER
# include <crtdbg.h>
# pragma warning(disable:4996)
@@ -56,6 +57,9 @@
# include <signal.h>
# include <stdlib.h>
# include <sys/wait.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <arpa/inet.h>
#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 <luca.boccassi@gmail.com>
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 <endpoints_t::iterator, endpoints_t::iterator> 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 <endpoints_t::iterator, endpoints_t::iterator> 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);