Compare commits
73 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b568b0136 | ||
|
|
61dda03ad6 | ||
|
|
8c0a9a2744 | ||
|
|
5cdfb5dc7a | ||
|
|
2ba6425a00 | ||
|
|
cb016e7317 | ||
|
|
c8ae1309ae | ||
|
|
1bc5134706 | ||
|
|
1cb438733f | ||
|
|
d1f897dccf | ||
|
|
0502eb1960 | ||
|
|
04ba3e0b7e | ||
|
|
9e6802e3b7 | ||
|
|
3dd626ffa0 | ||
|
|
13c901b7af | ||
|
|
b80422b75f | ||
|
|
0a97bab77b | ||
|
|
e47d99b391 | ||
|
|
12b8a0bc12 | ||
|
|
de1a0c8e35 | ||
|
|
e1c1539e16 | ||
|
|
7a106ac239 | ||
|
|
0108fed20c | ||
|
|
6666ee1fbe | ||
| 4899b764e8 | |||
|
|
690b1cc3cf | ||
|
|
b06c92b895 | ||
|
|
0da91cc706 | ||
|
|
c2c0544f92 | ||
|
|
9958f38243 | ||
|
|
1cff1e4bfa | ||
|
|
5226e5546b | ||
|
|
b11c5a2199 | ||
|
|
f46381246b | ||
|
|
135a5bb23b | ||
|
|
deb7fbd467 | ||
|
|
29fbd797d1 | ||
|
|
4f322ac6af | ||
|
|
4f02baed80 | ||
|
|
862d0b3419 | ||
|
|
d99d0bd41b | ||
|
|
f3609faa1b | ||
|
|
a31484cb1d | ||
|
|
8b1b433149 | ||
|
|
3fa0303d29 | ||
|
|
9e5b263a81 | ||
|
|
5aea20bcd5 | ||
|
|
5652a7377f | ||
|
|
6a4c511715 | ||
|
|
689cc9f6d7 | ||
|
|
dc32612980 | ||
|
|
7a004a7f33 | ||
|
|
23d1f54267 | ||
|
|
2e18705528 | ||
| 3eaf98a78b | |||
|
|
1b73cea19e | ||
|
2cefe81957 |
|||
| 015e3956e4 | |||
|
|
85bad0539d | ||
|
|
ce3866b8d6 | ||
|
|
8f64d3da25 | ||
|
|
e69895fec7 | ||
|
|
be57c1acb7 | ||
|
|
2c2ab1232d | ||
| 6e875bede4 | |||
|
|
eff758a05c | ||
|
|
9466daf312 | ||
|
|
4010976809 | ||
|
|
eb3bd66bd0 | ||
|
|
729573e58e | ||
|
|
f003bc5816 | ||
|
|
d930586b91 | ||
|
|
d9734a9779 |
7 changed files with 91 additions and 1211 deletions
20
.gitignore
vendored
20
.gitignore
vendored
|
|
@ -1,9 +1,11 @@
|
|||
zeromq-2.0.7.tar.gz
|
||||
/zeromq-2.0.8.tar.gz
|
||||
/zeromq-2.0.10.tar.gz
|
||||
/zeromq-2.1.3.tar.gz
|
||||
/zeromq-2.1.4.tar.gz
|
||||
/zeromq-2.1.9.tar.gz
|
||||
/zeromq-2.1.11.tar.gz
|
||||
/zeromq-2.2.0.tar.gz
|
||||
/zeromq-4.0.5.tar.gz
|
||||
/zeromq-*.tar.*
|
||||
/zeromq-*.src.rpm
|
||||
/zeromq-*.*.*/
|
||||
/libzmq-*.*.*/
|
||||
/clog
|
||||
.build-*.*.log
|
||||
/noarch/
|
||||
/x86_64/
|
||||
/i?86/
|
||||
/tarballs/
|
||||
/libzmq-*.*.*.tar.gz
|
||||
|
|
|
|||
17
LICENSE
17
LICENSE
|
|
@ -1,17 +0,0 @@
|
|||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
2
sources
2
sources
|
|
@ -1 +1 @@
|
|||
73c39f5eb01b9d7eaf74a5d899f1d03d zeromq-4.0.5.tar.gz
|
||||
SHA512 (zeromq-4.3.5.tar.gz) = a71d48aa977ad8941c1609947d8db2679fc7a951e4cd0c3a1127ae026d883c11bd4203cf315de87f95f5031aec459a731aec34e5ce5b667b8d0559b157952541
|
||||
|
|
|
|||
|
|
@ -1,430 +0,0 @@
|
|||
From 77ef79e3b565f120172c6d1c30fabec6185553da Mon Sep 17 00:00:00 2001
|
||||
From: Pieter Hintjens <ph@imatix.com>
|
||||
Date: Fri, 5 Dec 2014 09:07:37 +0100
|
||||
Subject: [PATCH] Problem: issue #1273, protocol downgrade attack
|
||||
|
||||
Solution: backport fix from libzmq master. Also backported test
|
||||
cases.
|
||||
---
|
||||
NEWS | 4 +-
|
||||
src/session_base.cpp | 8 +++
|
||||
src/session_base.hpp | 3 +-
|
||||
src/stream_engine.cpp | 15 ++++++
|
||||
tests/test_security_curve.cpp | 66 ++++++++++++++++++++---
|
||||
tests/test_security_null.cpp | 121 ++++++++++++++++++++++++++----------------
|
||||
tests/test_security_plain.cpp | 37 ++++++++++++-
|
||||
7 files changed, 197 insertions(+), 57 deletions(-)
|
||||
|
||||
diff --git a/src/session_base.cpp b/src/session_base.cpp
|
||||
index 537dcb3..0b58436 100644
|
||||
--- a/src/session_base.cpp
|
||||
+++ b/src/session_base.cpp
|
||||
@@ -323,6 +323,14 @@ int zmq::session_base_t::zap_connect ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
+bool zmq::session_base_t::zap_enabled ()
|
||||
+{
|
||||
+ return (
|
||||
+ options.mechanism != ZMQ_NULL ||
|
||||
+ (options.mechanism == ZMQ_NULL && options.zap_domain.length() > 0)
|
||||
+ );
|
||||
+}
|
||||
+
|
||||
void zmq::session_base_t::process_attach (i_engine *engine_)
|
||||
{
|
||||
zmq_assert (engine_ != NULL);
|
||||
diff --git a/src/session_base.hpp b/src/session_base.hpp
|
||||
index 2ef7dc5..63e16bd 100644
|
||||
--- a/src/session_base.hpp
|
||||
+++ b/src/session_base.hpp
|
||||
@@ -68,7 +68,8 @@ namespace zmq
|
||||
int push_msg (msg_t *msg_);
|
||||
|
||||
int zap_connect ();
|
||||
-
|
||||
+ bool zap_enabled ();
|
||||
+
|
||||
// Fetches a message. Returns 0 if successful; -1 otherwise.
|
||||
// The caller is responsible for freeing the message when no
|
||||
// longer used.
|
||||
diff --git a/src/stream_engine.cpp b/src/stream_engine.cpp
|
||||
index 4d252d8..3d84d8f 100644
|
||||
--- a/src/stream_engine.cpp
|
||||
+++ b/src/stream_engine.cpp
|
||||
@@ -464,6 +464,11 @@ bool zmq::stream_engine_t::handshake ()
|
||||
// Is the peer using ZMTP/1.0 with no revision number?
|
||||
// If so, we send and receive rest of identity message
|
||||
if (greeting_recv [0] != 0xff || !(greeting_recv [9] & 0x01)) {
|
||||
+ if (session->zap_enabled ()) {
|
||||
+ // Reject ZMTP 1.0 connections if ZAP is enabled
|
||||
+ error ();
|
||||
+ return false;
|
||||
+ }
|
||||
encoder = new (std::nothrow) v1_encoder_t (out_batch_size);
|
||||
alloc_assert (encoder);
|
||||
|
||||
@@ -505,6 +510,11 @@ bool zmq::stream_engine_t::handshake ()
|
||||
}
|
||||
else
|
||||
if (greeting_recv [revision_pos] == ZMTP_1_0) {
|
||||
+ if (session->zap_enabled ()) {
|
||||
+ // Reject ZMTP 1.0 connections if ZAP is enabled
|
||||
+ error ();
|
||||
+ return false;
|
||||
+ }
|
||||
encoder = new (std::nothrow) v1_encoder_t (
|
||||
out_batch_size);
|
||||
alloc_assert (encoder);
|
||||
@@ -515,6 +525,11 @@ bool zmq::stream_engine_t::handshake ()
|
||||
}
|
||||
else
|
||||
if (greeting_recv [revision_pos] == ZMTP_2_0) {
|
||||
+ if (session->zap_enabled ()) {
|
||||
+ // Reject ZMTP 1.0 connections if ZAP is enabled
|
||||
+ error ();
|
||||
+ return false;
|
||||
+ }
|
||||
encoder = new (std::nothrow) v2_encoder_t (out_batch_size);
|
||||
alloc_assert (encoder);
|
||||
|
||||
diff --git a/tests/test_security_curve.cpp b/tests/test_security_curve.cpp
|
||||
index a24466f..e99a4b3 100644
|
||||
--- a/tests/test_security_curve.cpp
|
||||
+++ b/tests/test_security_curve.cpp
|
||||
@@ -18,12 +18,23 @@
|
||||
*/
|
||||
|
||||
#include "testutil.hpp"
|
||||
+#if defined (ZMQ_HAVE_WINDOWS)
|
||||
+# include <winsock2.h>
|
||||
+# include <ws2tcpip.h>
|
||||
+# include <stdexcept>
|
||||
+# define close closesocket
|
||||
+#else
|
||||
+# include <sys/socket.h>
|
||||
+# include <netinet/in.h>
|
||||
+# include <arpa/inet.h>
|
||||
+# include <unistd.h>
|
||||
+#endif
|
||||
|
||||
// We'll generate random test keys at startup
|
||||
-static char client_public [40];
|
||||
-static char client_secret [40];
|
||||
-static char server_public [40];
|
||||
-static char server_secret [40];
|
||||
+static char client_public [41];
|
||||
+static char client_secret [41];
|
||||
+static char server_public [41];
|
||||
+static char server_secret [41];
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// This methods receives and validates ZAP requestes (allowing or denying
|
||||
@@ -46,7 +57,7 @@ static void zap_handler (void *handler)
|
||||
int size = zmq_recv (handler, client_key, 32, 0);
|
||||
assert (size == 32);
|
||||
|
||||
- char client_key_text [40];
|
||||
+ char client_key_text [41];
|
||||
zmq_z85_encode (client_key_text, client_key, 32);
|
||||
|
||||
assert (streq (version, "1.0"));
|
||||
@@ -181,8 +192,8 @@ int main (void)
|
||||
|
||||
// Check CURVE security with bogus client credentials
|
||||
// This must be caught by the ZAP handler
|
||||
- char bogus_public [40];
|
||||
- char bogus_secret [40];
|
||||
+ char bogus_public [41];
|
||||
+ char bogus_secret [41];
|
||||
zmq_curve_keypair (bogus_public, bogus_secret);
|
||||
|
||||
client = zmq_socket (ctx, ZMQ_DEALER);
|
||||
@@ -217,7 +228,46 @@ int main (void)
|
||||
assert (rc == 0);
|
||||
expect_bounce_fail (server, client);
|
||||
close_zero_linger (client);
|
||||
-
|
||||
+
|
||||
+ // Unauthenticated messages from a vanilla socket shouldn't be received
|
||||
+ struct sockaddr_in ip4addr;
|
||||
+ int s;
|
||||
+
|
||||
+ ip4addr.sin_family = AF_INET;
|
||||
+ ip4addr.sin_port = htons (9998);
|
||||
+ inet_pton (AF_INET, "127.0.0.1", &ip4addr.sin_addr);
|
||||
+
|
||||
+ s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
+ rc = connect (s, (struct sockaddr*) &ip4addr, sizeof (ip4addr));
|
||||
+ assert (rc > -1);
|
||||
+ // send anonymous ZMTP/1.0 greeting
|
||||
+ send (s, "\x01\x00", 2, 0);
|
||||
+ // send sneaky message that shouldn't be received
|
||||
+ send (s, "\x08\x00sneaky\0", 9, 0);
|
||||
+ int timeout = 150;
|
||||
+ zmq_setsockopt (server, ZMQ_RCVTIMEO, &timeout, sizeof (timeout));
|
||||
+ char *buf = s_recv (server);
|
||||
+ if (buf != NULL) {
|
||||
+ printf ("Received unauthenticated message: %s\n", buf);
|
||||
+ assert (buf == NULL);
|
||||
+ }
|
||||
+ close (s);
|
||||
+
|
||||
+ // Check return codes for invalid buffer sizes
|
||||
+ client = zmq_socket (ctx, ZMQ_DEALER);
|
||||
+ assert (client);
|
||||
+ errno = 0;
|
||||
+ rc = zmq_setsockopt (client, ZMQ_CURVE_SERVERKEY, server_public, 123);
|
||||
+ assert (rc == -1 && errno == EINVAL);
|
||||
+ errno = 0;
|
||||
+ rc = zmq_setsockopt (client, ZMQ_CURVE_PUBLICKEY, client_public, 123);
|
||||
+ assert (rc == -1 && errno == EINVAL);
|
||||
+ errno = 0;
|
||||
+ rc = zmq_setsockopt (client, ZMQ_CURVE_SECRETKEY, client_secret, 123);
|
||||
+ assert (rc == -1 && errno == EINVAL);
|
||||
+ rc = zmq_close (client);
|
||||
+ assert (rc == 0);
|
||||
+
|
||||
// Shutdown
|
||||
rc = zmq_close (server);
|
||||
assert (rc == 0);
|
||||
diff --git a/tests/test_security_null.cpp b/tests/test_security_null.cpp
|
||||
index 8a55632..6b74e8c 100644
|
||||
--- a/tests/test_security_null.cpp
|
||||
+++ b/tests/test_security_null.cpp
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
- Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file
|
||||
+ Copyright (c) 2007-2014 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of 0MQ.
|
||||
|
||||
@@ -18,6 +18,17 @@
|
||||
*/
|
||||
|
||||
#include "testutil.hpp"
|
||||
+#if defined (ZMQ_HAVE_WINDOWS)
|
||||
+# include <winsock2.h>
|
||||
+# include <ws2tcpip.h>
|
||||
+# include <stdexcept>
|
||||
+# define close closesocket
|
||||
+#else
|
||||
+# include <sys/socket.h>
|
||||
+# include <netinet/in.h>
|
||||
+# include <arpa/inet.h>
|
||||
+# include <unistd.h>
|
||||
+#endif
|
||||
|
||||
static void
|
||||
zap_handler (void *handler)
|
||||
@@ -27,6 +38,7 @@ zap_handler (void *handler)
|
||||
char *version = s_recv (handler);
|
||||
if (!version)
|
||||
break; // Terminating
|
||||
+
|
||||
char *sequence = s_recv (handler);
|
||||
char *domain = s_recv (handler);
|
||||
char *address = s_recv (handler);
|
||||
@@ -57,7 +69,7 @@ zap_handler (void *handler)
|
||||
free (identity);
|
||||
free (mechanism);
|
||||
}
|
||||
- zmq_close (handler);
|
||||
+ close_zero_linger (handler);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
@@ -76,72 +88,89 @@ int main (void)
|
||||
void *zap_thread = zmq_threadstart (&zap_handler, handler);
|
||||
|
||||
// We bounce between a binding server and a connecting client
|
||||
+
|
||||
+ // We first test client/server with no ZAP domain
|
||||
+ // Libzmq does not call our ZAP handler, the connect must succeed
|
||||
void *server = zmq_socket (ctx, ZMQ_DEALER);
|
||||
assert (server);
|
||||
void *client = zmq_socket (ctx, ZMQ_DEALER);
|
||||
assert (client);
|
||||
-
|
||||
- // We first test client/server with no ZAP domain
|
||||
- // Libzmq does not call our ZAP handler, the connect must succeed
|
||||
rc = zmq_bind (server, "tcp://127.0.0.1:9000");
|
||||
assert (rc == 0);
|
||||
- rc = zmq_connect (client, "tcp://localhost:9000");
|
||||
+ rc = zmq_connect (client, "tcp://127.0.0.1:9000");
|
||||
assert (rc == 0);
|
||||
bounce (server, client);
|
||||
- zmq_unbind (server, "tcp://127.0.0.1:9000");
|
||||
- zmq_disconnect (client, "tcp://localhost:9000");
|
||||
-
|
||||
+ close_zero_linger (client);
|
||||
+ close_zero_linger (server);
|
||||
+
|
||||
// Now define a ZAP domain for the server; this enables
|
||||
// authentication. We're using the wrong domain so this test
|
||||
// must fail.
|
||||
- // **************************************************************
|
||||
- // PH: the following causes libzmq to get confused, so that the
|
||||
- // next step fails. To reproduce, uncomment this block. Note that
|
||||
- // even creating a new client/server socket pair, the behaviour
|
||||
- // does not change.
|
||||
- // **************************************************************
|
||||
- // Destroying the old sockets and creating new ones isn't needed,
|
||||
- // but it shows that the problem isn't related to specific sockets.
|
||||
- //close_zero_linger (client);
|
||||
- //close_zero_linger (server);
|
||||
- //server = zmq_socket (ctx, ZMQ_DEALER);
|
||||
- //assert (server);
|
||||
- //client = zmq_socket (ctx, ZMQ_DEALER);
|
||||
- //assert (client);
|
||||
- //// The above code should not be required
|
||||
- //rc = zmq_setsockopt (server, ZMQ_ZAP_DOMAIN, "WRONG", 5);
|
||||
- //assert (rc == 0);
|
||||
- //rc = zmq_bind (server, "tcp://127.0.0.1:9001");
|
||||
- //assert (rc == 0);
|
||||
- //rc = zmq_connect (client, "tcp://localhost:9001");
|
||||
- //assert (rc == 0);
|
||||
- //expect_bounce_fail (server, client);
|
||||
- //zmq_unbind (server, "tcp://127.0.0.1:9001");
|
||||
- //zmq_disconnect (client, "tcp://localhost:9001");
|
||||
-
|
||||
+ server = zmq_socket (ctx, ZMQ_DEALER);
|
||||
+ assert (server);
|
||||
+ client = zmq_socket (ctx, ZMQ_DEALER);
|
||||
+ assert (client);
|
||||
+ rc = zmq_setsockopt (server, ZMQ_ZAP_DOMAIN, "WRONG", 5);
|
||||
+ assert (rc == 0);
|
||||
+ rc = zmq_bind (server, "tcp://127.0.0.1:9001");
|
||||
+ assert (rc == 0);
|
||||
+ rc = zmq_connect (client, "tcp://127.0.0.1:9001");
|
||||
+ assert (rc == 0);
|
||||
+ expect_bounce_fail (server, client);
|
||||
+ close_zero_linger (client);
|
||||
+ close_zero_linger (server);
|
||||
+
|
||||
// Now use the right domain, the test must pass
|
||||
+ server = zmq_socket (ctx, ZMQ_DEALER);
|
||||
+ assert (server);
|
||||
+ client = zmq_socket (ctx, ZMQ_DEALER);
|
||||
+ assert (client);
|
||||
rc = zmq_setsockopt (server, ZMQ_ZAP_DOMAIN, "TEST", 4);
|
||||
assert (rc == 0);
|
||||
rc = zmq_bind (server, "tcp://127.0.0.1:9002");
|
||||
assert (rc == 0);
|
||||
- rc = zmq_connect (client, "tcp://localhost:9002");
|
||||
+ rc = zmq_connect (client, "tcp://127.0.0.1:9002");
|
||||
assert (rc == 0);
|
||||
- // **************************************************************
|
||||
- // PH: it fails here; though the ZAP reply is 200 OK, and
|
||||
- // null_mechanism.cpp correctly parses that, the connection
|
||||
- // never succeeds and the test hangs.
|
||||
- // **************************************************************
|
||||
bounce (server, client);
|
||||
- zmq_unbind (server, "tcp://127.0.0.1:9002");
|
||||
- zmq_disconnect (client, "tcp://localhost:9002");
|
||||
-
|
||||
- // Shutdown
|
||||
close_zero_linger (client);
|
||||
close_zero_linger (server);
|
||||
- rc = zmq_ctx_term (ctx);
|
||||
+
|
||||
+ // Unauthenticated messages from a vanilla socket shouldn't be received
|
||||
+ server = zmq_socket (ctx, ZMQ_DEALER);
|
||||
+ assert (server);
|
||||
+ rc = zmq_setsockopt (server, ZMQ_ZAP_DOMAIN, "WRONG", 5);
|
||||
assert (rc == 0);
|
||||
+ rc = zmq_bind (server, "tcp://127.0.0.1:9003");
|
||||
+ assert (rc == 0);
|
||||
+
|
||||
+ struct sockaddr_in ip4addr;
|
||||
+ int s;
|
||||
+
|
||||
+ ip4addr.sin_family = AF_INET;
|
||||
+ ip4addr.sin_port = htons(9003);
|
||||
+ inet_pton(AF_INET, "127.0.0.1", &ip4addr.sin_addr);
|
||||
|
||||
- // Wait until ZAP handler terminates.
|
||||
+ s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
+ rc = connect (s, (struct sockaddr*) &ip4addr, sizeof ip4addr);
|
||||
+ assert (rc > -1);
|
||||
+ // send anonymous ZMTP/1.0 greeting
|
||||
+ send (s, "\x01\x00", 2, 0);
|
||||
+ // send sneaky message that shouldn't be received
|
||||
+ send (s, "\x08\x00sneaky\0", 9, 0);
|
||||
+ int timeout = 150;
|
||||
+ zmq_setsockopt (server, ZMQ_RCVTIMEO, &timeout, sizeof (timeout));
|
||||
+ char *buf = s_recv (server);
|
||||
+ if (buf != NULL) {
|
||||
+ printf ("Received unauthenticated message: %s\n", buf);
|
||||
+ assert (buf == NULL);
|
||||
+ }
|
||||
+ close (s);
|
||||
+ close_zero_linger (server);
|
||||
+
|
||||
+ // Shutdown
|
||||
+ rc = zmq_ctx_term (ctx);
|
||||
+ assert (rc == 0);
|
||||
+ // Wait until ZAP handler terminates
|
||||
zmq_threadclose (zap_thread);
|
||||
|
||||
return 0;
|
||||
diff --git a/tests/test_security_plain.cpp b/tests/test_security_plain.cpp
|
||||
index 74973fd..c257840 100644
|
||||
--- a/tests/test_security_plain.cpp
|
||||
+++ b/tests/test_security_plain.cpp
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
- Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file
|
||||
+ Copyright (c) 2007-2014 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of 0MQ.
|
||||
|
||||
@@ -18,6 +18,17 @@
|
||||
*/
|
||||
|
||||
#include "testutil.hpp"
|
||||
+#if defined (ZMQ_HAVE_WINDOWS)
|
||||
+# include <winsock2.h>
|
||||
+# include <ws2tcpip.h>
|
||||
+# include <stdexcept>
|
||||
+# define close closesocket
|
||||
+#else
|
||||
+# include <sys/socket.h>
|
||||
+# include <netinet/in.h>
|
||||
+# include <arpa/inet.h>
|
||||
+# include <unistd.h>
|
||||
+#endif
|
||||
|
||||
static void
|
||||
zap_handler (void *ctx)
|
||||
@@ -137,6 +148,30 @@ int main (void)
|
||||
expect_bounce_fail (server, client);
|
||||
close_zero_linger (client);
|
||||
|
||||
+ // Unauthenticated messages from a vanilla socket shouldn't be received
|
||||
+ struct sockaddr_in ip4addr;
|
||||
+ int s;
|
||||
+
|
||||
+ ip4addr.sin_family = AF_INET;
|
||||
+ ip4addr.sin_port = htons (9998);
|
||||
+ inet_pton (AF_INET, "127.0.0.1", &ip4addr.sin_addr);
|
||||
+
|
||||
+ s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
+ rc = connect (s, (struct sockaddr*) &ip4addr, sizeof (ip4addr));
|
||||
+ assert (rc > -1);
|
||||
+ // send anonymous ZMTP/1.0 greeting
|
||||
+ send (s, "\x01\x00", 2, 0);
|
||||
+ // send sneaky message that shouldn't be received
|
||||
+ send (s, "\x08\x00sneaky\0", 9, 0);
|
||||
+ int timeout = 150;
|
||||
+ zmq_setsockopt (server, ZMQ_RCVTIMEO, &timeout, sizeof (timeout));
|
||||
+ char *buf = s_recv (server);
|
||||
+ if (buf != NULL) {
|
||||
+ printf ("Received unauthenticated message: %s\n", buf);
|
||||
+ assert (buf == NULL);
|
||||
+ }
|
||||
+ close (s);
|
||||
+
|
||||
// Shutdown
|
||||
rc = zmq_close (server);
|
||||
assert (rc == 0);
|
||||
37
zeromq-configure-c99.patch
Normal file
37
zeromq-configure-c99.patch
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
Build with -D_DEFAULT_SOURCE along with -std=c11
|
||||
|
||||
On its own, -std=c11 hides POSIX and other extensions from C headers
|
||||
such as <stdlib.h> when building against glibc. This causes the
|
||||
posix_memalign probe to fail incorrectly with compilers that do not
|
||||
accept implicit function declarations. _DEFAULT_SOURCE is ignored by
|
||||
most non-GNU/Linux systems or not relevant in this context, so there
|
||||
is no separate check for adding it.
|
||||
|
||||
Submitted upstream: <https://github.com/zeromq/libzmq/pull/4635>
|
||||
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index 68fb7251..f956f3fd 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -122,7 +122,7 @@ if (NOT MSVC)
|
||||
if(NOT CMAKE_C_FLAGS MATCHES "-std=" AND NOT C_STANDARD AND NOT CMAKE_C_STANDARD)
|
||||
check_c_compiler_flag("-std=c11" COMPILER_SUPPORTS_C11)
|
||||
if(COMPILER_SUPPORTS_C11)
|
||||
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11")
|
||||
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_DEFAULT_SOURCE -std=c11")
|
||||
else()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99")
|
||||
endif()
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index b9e13d4f..ffcc145b 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -66,7 +66,7 @@ ZMQ_ORIG_CXXFLAGS="${CXXFLAGS:-none}"
|
||||
|
||||
# Checks for programs.
|
||||
AC_PROG_CC
|
||||
-AX_CHECK_COMPILE_FLAG([-std=c11], [CFLAGS+=" -std=c11"], [AC_PROG_CC_C99])
|
||||
+AX_CHECK_COMPILE_FLAG([-std=c11], [CFLAGS+=" -std=c11 -D_DEFAULT_SOURCE"], [AC_PROG_CC_C99])
|
||||
AC_PROG_CXX
|
||||
AX_CODE_COVERAGE
|
||||
AM_PROG_CC_C_O
|
||||
194
zeromq.spec
194
zeromq.spec
|
|
@ -1,32 +1,32 @@
|
|||
%bcond_without pgm
|
||||
%bcond_without unwind
|
||||
|
||||
Name: zeromq
|
||||
Version: 4.0.5
|
||||
Release: 4%{?dist}
|
||||
Version: 4.3.5
|
||||
Release: %autorelease
|
||||
Summary: Software library for fast, message-based applications
|
||||
|
||||
Group: System Environment/Libraries
|
||||
License: LGPLv3+
|
||||
URL: http://www.zeromq.org
|
||||
# VCS: git:http://github.com/zeromq/zeromq2.git
|
||||
Source0: http://download.zeromq.org/zeromq-%{version}.tar.gz
|
||||
Patch0: zeromq-4.0.5-downgrade-attack.patch
|
||||
Source1: https://raw.githubusercontent.com/zeromq/cppzmq/master/zmq.hpp
|
||||
Source2: https://raw.githubusercontent.com/zeromq/cppzmq/master/LICENSE
|
||||
License: MPL-2.0 AND BSD-3-Clause AND MIT
|
||||
URL: https://zeromq.org
|
||||
Source0: https://github.com/%{name}/libzmq/archive/v%{version}/%{name}-%{version}.tar.gz
|
||||
Patch1: zeromq-configure-c99.patch
|
||||
|
||||
BuildRequires: make
|
||||
BuildRequires: autoconf
|
||||
BuildRequires: automake
|
||||
BuildRequires: gcc-c++
|
||||
BuildRequires: libtool
|
||||
BuildRequires: asciidoc
|
||||
BuildRequires: xmlto
|
||||
BuildRequires: libsodium-devel
|
||||
|
||||
BuildRequires: glib2-devel
|
||||
%if ! (0%{?fedora} > 12 || 0%{?rhel} > 5)
|
||||
BuildRequires: e2fsprogs-devel
|
||||
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
|
||||
%else
|
||||
BuildRequires: libuuid-devel
|
||||
%if %{with unwind}
|
||||
BuildRequires: libunwind-devel
|
||||
%endif
|
||||
|
||||
%if %{with pgm}
|
||||
BuildRequires: openpgm-devel
|
||||
BuildRequires: krb5-devel
|
||||
%endif
|
||||
|
||||
%description
|
||||
|
|
@ -42,7 +42,6 @@ This package contains the ZeroMQ shared library.
|
|||
|
||||
%package devel
|
||||
Summary: Development files for %{name}
|
||||
Group: Development/Libraries
|
||||
Requires: %{name}%{?_isa} = %{version}-%{release}
|
||||
|
||||
|
||||
|
|
@ -51,173 +50,64 @@ The %{name}-devel package contains libraries and header files for
|
|||
developing applications that use %{name}.
|
||||
|
||||
|
||||
%package -n cppzmq-devel
|
||||
Summary: Development files for cppzmq
|
||||
Group: Development/Libraries
|
||||
License: MIT
|
||||
Requires: %{name}-devel%{?_isa} = %{version}-%{release}
|
||||
|
||||
|
||||
%description -n cppzmq-devel
|
||||
The cppzmq-devel package contains libraries and header files for
|
||||
developing applications that use the C++ header files of %{name}.
|
||||
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
%patch0 -p1
|
||||
cp -a %{SOURCE2} .
|
||||
%autosetup -p1
|
||||
|
||||
# zeromq.x86_64: W: file-not-utf8 /usr/share/doc/zeromq/ChangeLog
|
||||
iconv -f iso8859-1 -t utf-8 ChangeLog > ChangeLog.conv && mv -f ChangeLog.conv ChangeLog
|
||||
# Remove bundled code.
|
||||
rm -rf external/wepoll
|
||||
|
||||
# Don't turn warnings into errors
|
||||
sed -i "s/libzmq_werror=\"yes\"/libzmq_werror=\"no\"/g" \
|
||||
configure
|
||||
|
||||
# Sed version number of openpgm into configure
|
||||
%global openpgm_pc $(basename %{_libdir}/pkgconfig/openpgm*.pc .pc)
|
||||
sed -i "s/openpgm-[0-9].[0-9]/%{openpgm_pc}/g" \
|
||||
configure*
|
||||
|
||||
|
||||
# remove all files in foreign except Makefiles
|
||||
rm -v $(find foreign -type f | grep -v Makefile)
|
||||
# Fix permissions.
|
||||
chmod -x src/xsub.hpp
|
||||
|
||||
|
||||
%build
|
||||
autoreconf -fi
|
||||
%configure \
|
||||
%if %{with pgm}
|
||||
--with-system-pgm \
|
||||
--with-pgm \
|
||||
--with-libgssapi_krb5 \
|
||||
%endif
|
||||
--with-libsodium \
|
||||
--enable-drafts \
|
||||
%if %{with unwind}
|
||||
--enable-libunwind \
|
||||
%endif
|
||||
--disable-Werror \
|
||||
--disable-static
|
||||
make %{?_smp_mflags} V=1
|
||||
%make_build
|
||||
|
||||
|
||||
%install
|
||||
rm -rf %{buildroot}
|
||||
make install DESTDIR=%{buildroot} INSTALL="install -p"
|
||||
install -m 644 -p %{SOURCE1} %{buildroot}%{_includedir}/
|
||||
%make_install
|
||||
|
||||
# remove *.la
|
||||
rm %{buildroot}%{_libdir}/libzmq.la
|
||||
|
||||
|
||||
%check
|
||||
make check
|
||||
%ifarch s390x
|
||||
make check V=1 XFAIL_TESTS=tests/test_radio_dish || ( cat test-suite.log && exit 1 )
|
||||
%endif
|
||||
|
||||
|
||||
%post -p /sbin/ldconfig
|
||||
|
||||
|
||||
%postun -p /sbin/ldconfig
|
||||
%ldconfig_scriptlets
|
||||
|
||||
|
||||
%files
|
||||
%doc AUTHORS ChangeLog NEWS README.md
|
||||
%license COPYING COPYING.LESSER
|
||||
%doc README.md AUTHORS NEWS
|
||||
%license LICENSE
|
||||
%{_bindir}/curve_keygen
|
||||
%{_libdir}/libzmq.so.*
|
||||
%{_libdir}/libzmq.so.5*
|
||||
%{_mandir}/man3/zmq_*
|
||||
%{_mandir}/man7/zmq_*
|
||||
%{_mandir}/man7/zmq.*
|
||||
|
||||
%files devel
|
||||
%{_libdir}/libzmq.so
|
||||
%{_libdir}/pkgconfig/libzmq.pc
|
||||
%{_includedir}/zmq*.h
|
||||
%{_mandir}/man3/zmq*
|
||||
%{_mandir}/man7/zmq*
|
||||
|
||||
%files -n cppzmq-devel
|
||||
%license LICENSE
|
||||
%{_includedir}/zmq.hpp
|
||||
|
||||
|
||||
%changelog
|
||||
* Mon Jun 08 2015 Thomas Spura <tomspur@fedoraproject.org> - 4.0.5-4
|
||||
- Add zmq.hpp, which originally belonged to zeromq:
|
||||
https://github.com/zeromq/cppzmq/issues/48
|
||||
%autochangelog
|
||||
|
||||
* Tue May 19 2015 Thomas Spura <tomspur@fedoraproject.org> - 4.0.5-3
|
||||
- Cherry-pick patch for protocol downgrade attack (#1221666, CVE-2014-9721)
|
||||
- Remove Obsoletes:zeromq-utils
|
||||
- Remove %%defattr
|
||||
|
||||
* Sat May 02 2015 Kalev Lember <kalevlember@gmail.com> - 4.0.5-2
|
||||
- Rebuilt for GCC 5 C++11 ABI change
|
||||
|
||||
* Mon Nov 17 2014 Thomas Spura <tomspur@fedoraproject.org> - 4.0.5-1
|
||||
- update to 4.0.5
|
||||
|
||||
* Mon Aug 18 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.2.0-10
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild
|
||||
|
||||
* Sat Jun 07 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.2.0-9
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild
|
||||
|
||||
* Sun Aug 04 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.2.0-8
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild
|
||||
|
||||
* Fri May 17 2013 Thomas Spura <tomspur@fedoraproject.org> - 2.2.0-7
|
||||
- Rebuilt for openpm-5.2 and sed correct version into configure (#963894)
|
||||
|
||||
* Wed Mar 27 2013 Thomas Spura <tomspur@fedoraproject.org> - 2.2.0-6
|
||||
- run autoreconf before configure so aarch64 is supported (#926859)
|
||||
|
||||
* Fri Feb 15 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.2.0-5
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild
|
||||
|
||||
* Mon Jan 14 2013 Thomas Spura <tomspur@fedoraproject.org> - 2.2.0-4
|
||||
- delete foreign files with dubious license in %%prep (#892111)
|
||||
|
||||
* Mon Dec 24 2012 Thomas Spura <tomspur@fedoraproject.org> - 2.2.0-3
|
||||
- add bcond_without pgm macro (Jose Pedro Oliveira, #867182)
|
||||
- remove bundled pgm
|
||||
- build against openpgm
|
||||
|
||||
* Sun Jul 22 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.2.0-2
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild
|
||||
|
||||
* Thu Apr 26 2012 Thomas Spura <tomspur@fedoraproject.org> - 2.2.0-1
|
||||
- update to 2.2.0
|
||||
|
||||
* Sat Jan 7 2012 Thomas Spura <tomspur@fedoraproject.org> - 2.1.11-1
|
||||
- update to 2.1.11 (as part of rebuilding with gcc-4.7)
|
||||
|
||||
* Tue Sep 20 2011 Thomas Spura <tomspur@fedoraproject.org> - 2.1.9-1
|
||||
- update to 2.1.9
|
||||
- add check section
|
||||
|
||||
* Wed Apr 6 2011 Thomas Spura <tomspur@fedoraproject.org> - 2.1.4-1
|
||||
- update to new version (#690199)
|
||||
|
||||
* Wed Mar 23 2011 Thomas Spura <tomspur@fedoraproject.org> - 2.1.3-1
|
||||
- update to new version (#690199)
|
||||
- utils subpackage was removed upstream
|
||||
(obsolete it)
|
||||
|
||||
* Tue Feb 08 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.0.10-2
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
|
||||
|
||||
* Thu Jan 13 2011 Pavel Zhukov <pavel@zhukoff.net> - 2.0.10-1
|
||||
- update version
|
||||
- add rpath delete
|
||||
- change includedir filelist
|
||||
|
||||
* Fri Aug 27 2010 Thomas Spura <tomspur@fedoraproject.org> - 2.0.8-1
|
||||
- update to new version
|
||||
|
||||
* Fri Jul 23 2010 Thomas Spura <tomspur@fedoraproject.org> - 2.0.7-4
|
||||
- upstream VCS changed
|
||||
- remove buildroot / %%clean
|
||||
- change descriptions
|
||||
|
||||
* Tue Jul 20 2010 Thomas Spura <tomspur@fedoraproject.org> - 2.0.7-3
|
||||
- move binaries to seperate utils package
|
||||
|
||||
* Sat Jun 12 2010 Thomas Spura <tomspur@fedoraproject.org> - 2.0.7-2
|
||||
- remove BR: libstdc++-devel
|
||||
- move man3 to the devel package
|
||||
- change group to System Environment/Libraries
|
||||
|
||||
* Sat Jun 12 2010 Thomas Spura <tomspur@fedoraproject.org> - 2.0.7-1
|
||||
- initial package (based on upstreams example one)
|
||||
|
|
|
|||
602
zmq.hpp
602
zmq.hpp
|
|
@ -1,602 +0,0 @@
|
|||
/*
|
||||
Copyright (c) 2009-2011 250bpm s.r.o.
|
||||
Copyright (c) 2011 Botond Ballo
|
||||
Copyright (c) 2007-2009 iMatix Corporation
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_HPP_INCLUDED__
|
||||
#define __ZMQ_HPP_INCLUDED__
|
||||
|
||||
#include <zmq.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <exception>
|
||||
|
||||
// Detect whether the compiler supports C++11 rvalue references.
|
||||
#if (defined(__GNUC__) && (__GNUC__ > 4 || \
|
||||
(__GNUC__ == 4 && __GNUC_MINOR__ > 2)) && \
|
||||
defined(__GXX_EXPERIMENTAL_CXX0X__))
|
||||
#define ZMQ_HAS_RVALUE_REFS
|
||||
#define ZMQ_DELETED_FUNCTION = delete
|
||||
#elif defined(__clang__)
|
||||
#if __has_feature(cxx_rvalue_references)
|
||||
#define ZMQ_HAS_RVALUE_REFS
|
||||
#endif
|
||||
|
||||
#if __has_feature(cxx_deleted_functions)
|
||||
#define ZMQ_DELETED_FUNCTION = delete
|
||||
#else
|
||||
#define ZMQ_DELETED_FUNCTION
|
||||
#endif
|
||||
#elif defined(_MSC_VER) && (_MSC_VER >= 1600)
|
||||
#define ZMQ_HAS_RVALUE_REFS
|
||||
#define ZMQ_DELETED_FUNCTION
|
||||
#else
|
||||
#define ZMQ_DELETED_FUNCTION
|
||||
#endif
|
||||
|
||||
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3, 3, 0)
|
||||
#define ZMQ_NEW_MONITOR_EVENT_LAYOUT
|
||||
#endif
|
||||
|
||||
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 1, 0)
|
||||
#define ZMQ_HAS_PROXY_STEERABLE
|
||||
/* Socket event data */
|
||||
typedef struct {
|
||||
uint16_t event; // id of the event as bitfield
|
||||
int32_t value ; // value is either error code, fd or reconnect interval
|
||||
} zmq_event_t;
|
||||
#endif
|
||||
|
||||
// In order to prevent unused variable warnings when building in non-debug
|
||||
// mode use this macro to make assertions.
|
||||
#ifndef NDEBUG
|
||||
# define ZMQ_ASSERT(expression) assert(expression)
|
||||
#else
|
||||
# define ZMQ_ASSERT(expression) (void)(expression)
|
||||
#endif
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
|
||||
typedef zmq_free_fn free_fn;
|
||||
typedef zmq_pollitem_t pollitem_t;
|
||||
|
||||
class error_t : public std::exception
|
||||
{
|
||||
public:
|
||||
|
||||
error_t () : errnum (zmq_errno ()) {}
|
||||
|
||||
virtual const char *what () const throw ()
|
||||
{
|
||||
return zmq_strerror (errnum);
|
||||
}
|
||||
|
||||
int num () const
|
||||
{
|
||||
return errnum;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
int errnum;
|
||||
};
|
||||
|
||||
inline int poll (zmq_pollitem_t *items_, int nitems_, long timeout_ = -1)
|
||||
{
|
||||
int rc = zmq_poll (items_, nitems_, timeout_);
|
||||
if (rc < 0)
|
||||
throw error_t ();
|
||||
return rc;
|
||||
}
|
||||
|
||||
inline void proxy (void *frontend, void *backend, void *capture)
|
||||
{
|
||||
int rc = zmq_proxy (frontend, backend, capture);
|
||||
if (rc != 0)
|
||||
throw error_t ();
|
||||
}
|
||||
|
||||
#ifdef ZMQ_HAS_PROXY_STEERABLE
|
||||
inline void proxy_steerable (void *frontend, void *backend, void *capture, void *control)
|
||||
{
|
||||
int rc = zmq_proxy_steerable (frontend, backend, capture, control);
|
||||
if (rc != 0)
|
||||
throw error_t ();
|
||||
}
|
||||
#endif
|
||||
|
||||
inline void version (int *major_, int *minor_, int *patch_)
|
||||
{
|
||||
zmq_version (major_, minor_, patch_);
|
||||
}
|
||||
|
||||
class message_t
|
||||
{
|
||||
friend class socket_t;
|
||||
|
||||
public:
|
||||
|
||||
inline message_t ()
|
||||
{
|
||||
int rc = zmq_msg_init (&msg);
|
||||
if (rc != 0)
|
||||
throw error_t ();
|
||||
}
|
||||
|
||||
inline explicit message_t (size_t size_)
|
||||
{
|
||||
int rc = zmq_msg_init_size (&msg, size_);
|
||||
if (rc != 0)
|
||||
throw error_t ();
|
||||
}
|
||||
|
||||
inline message_t (void *data_, size_t size_, free_fn *ffn_,
|
||||
void *hint_ = NULL)
|
||||
{
|
||||
int rc = zmq_msg_init_data (&msg, data_, size_, ffn_, hint_);
|
||||
if (rc != 0)
|
||||
throw error_t ();
|
||||
}
|
||||
|
||||
#ifdef ZMQ_HAS_RVALUE_REFS
|
||||
inline message_t (message_t &&rhs) : msg (rhs.msg)
|
||||
{
|
||||
int rc = zmq_msg_init (&rhs.msg);
|
||||
if (rc != 0)
|
||||
throw error_t ();
|
||||
}
|
||||
|
||||
inline message_t &operator = (message_t &&rhs)
|
||||
{
|
||||
std::swap (msg, rhs.msg);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline ~message_t ()
|
||||
{
|
||||
int rc = zmq_msg_close (&msg);
|
||||
ZMQ_ASSERT (rc == 0);
|
||||
}
|
||||
|
||||
inline void rebuild ()
|
||||
{
|
||||
int rc = zmq_msg_close (&msg);
|
||||
if (rc != 0)
|
||||
throw error_t ();
|
||||
rc = zmq_msg_init (&msg);
|
||||
if (rc != 0)
|
||||
throw error_t ();
|
||||
}
|
||||
|
||||
inline void rebuild (size_t size_)
|
||||
{
|
||||
int rc = zmq_msg_close (&msg);
|
||||
if (rc != 0)
|
||||
throw error_t ();
|
||||
rc = zmq_msg_init_size (&msg, size_);
|
||||
if (rc != 0)
|
||||
throw error_t ();
|
||||
}
|
||||
|
||||
inline void rebuild (void *data_, size_t size_, free_fn *ffn_,
|
||||
void *hint_ = NULL)
|
||||
{
|
||||
int rc = zmq_msg_close (&msg);
|
||||
if (rc != 0)
|
||||
throw error_t ();
|
||||
rc = zmq_msg_init_data (&msg, data_, size_, ffn_, hint_);
|
||||
if (rc != 0)
|
||||
throw error_t ();
|
||||
}
|
||||
|
||||
inline void move (message_t *msg_)
|
||||
{
|
||||
int rc = zmq_msg_move (&msg, &(msg_->msg));
|
||||
if (rc != 0)
|
||||
throw error_t ();
|
||||
}
|
||||
|
||||
inline void copy (message_t *msg_)
|
||||
{
|
||||
int rc = zmq_msg_copy (&msg, &(msg_->msg));
|
||||
if (rc != 0)
|
||||
throw error_t ();
|
||||
}
|
||||
|
||||
inline bool more ()
|
||||
{
|
||||
int rc = zmq_msg_more (&msg);
|
||||
return rc != 0;
|
||||
}
|
||||
|
||||
inline void *data ()
|
||||
{
|
||||
return zmq_msg_data (&msg);
|
||||
}
|
||||
|
||||
inline const void* data () const
|
||||
{
|
||||
return zmq_msg_data (const_cast<zmq_msg_t*>(&msg));
|
||||
}
|
||||
|
||||
inline size_t size () const
|
||||
{
|
||||
return zmq_msg_size (const_cast<zmq_msg_t*>(&msg));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// The underlying message
|
||||
zmq_msg_t msg;
|
||||
|
||||
// Disable implicit message copying, so that users won't use shared
|
||||
// messages (less efficient) without being aware of the fact.
|
||||
message_t (const message_t&);
|
||||
void operator = (const message_t&);
|
||||
};
|
||||
|
||||
class context_t
|
||||
{
|
||||
friend class socket_t;
|
||||
|
||||
public:
|
||||
inline context_t ()
|
||||
{
|
||||
ptr = zmq_ctx_new ();
|
||||
if (ptr == NULL)
|
||||
throw error_t ();
|
||||
}
|
||||
|
||||
|
||||
inline explicit context_t (int io_threads_, int max_sockets_ = ZMQ_MAX_SOCKETS_DFLT)
|
||||
{
|
||||
ptr = zmq_ctx_new ();
|
||||
if (ptr == NULL)
|
||||
throw error_t ();
|
||||
|
||||
int rc = zmq_ctx_set (ptr, ZMQ_IO_THREADS, io_threads_);
|
||||
ZMQ_ASSERT (rc == 0);
|
||||
|
||||
rc = zmq_ctx_set (ptr, ZMQ_MAX_SOCKETS, max_sockets_);
|
||||
ZMQ_ASSERT (rc == 0);
|
||||
}
|
||||
|
||||
#ifdef ZMQ_HAS_RVALUE_REFS
|
||||
inline context_t (context_t &&rhs) : ptr (rhs.ptr)
|
||||
{
|
||||
rhs.ptr = NULL;
|
||||
}
|
||||
inline context_t &operator = (context_t &&rhs)
|
||||
{
|
||||
std::swap (ptr, rhs.ptr);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline ~context_t ()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
inline void close()
|
||||
{
|
||||
if (ptr == NULL)
|
||||
return;
|
||||
int rc = zmq_ctx_destroy (ptr);
|
||||
ZMQ_ASSERT (rc == 0);
|
||||
ptr = NULL;
|
||||
}
|
||||
|
||||
// Be careful with this, it's probably only useful for
|
||||
// using the C api together with an existing C++ api.
|
||||
// Normally you should never need to use this.
|
||||
inline operator void* ()
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void *ptr;
|
||||
|
||||
context_t (const context_t&);
|
||||
void operator = (const context_t&);
|
||||
};
|
||||
|
||||
class socket_t
|
||||
{
|
||||
friend class monitor_t;
|
||||
public:
|
||||
|
||||
inline socket_t (context_t &context_, int type_)
|
||||
{
|
||||
ctxptr = context_.ptr;
|
||||
ptr = zmq_socket (context_.ptr, type_);
|
||||
if (ptr == NULL)
|
||||
throw error_t ();
|
||||
}
|
||||
|
||||
#ifdef ZMQ_HAS_RVALUE_REFS
|
||||
inline socket_t(socket_t&& rhs) : ptr(rhs.ptr)
|
||||
{
|
||||
rhs.ptr = NULL;
|
||||
}
|
||||
inline socket_t& operator=(socket_t&& rhs)
|
||||
{
|
||||
std::swap(ptr, rhs.ptr);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline ~socket_t ()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
inline operator void* ()
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
inline void close()
|
||||
{
|
||||
if(ptr == NULL)
|
||||
// already closed
|
||||
return ;
|
||||
int rc = zmq_close (ptr);
|
||||
ZMQ_ASSERT (rc == 0);
|
||||
ptr = 0 ;
|
||||
}
|
||||
|
||||
inline void setsockopt (int option_, const void *optval_,
|
||||
size_t optvallen_)
|
||||
{
|
||||
int rc = zmq_setsockopt (ptr, option_, optval_, optvallen_);
|
||||
if (rc != 0)
|
||||
throw error_t ();
|
||||
}
|
||||
|
||||
inline void getsockopt (int option_, void *optval_,
|
||||
size_t *optvallen_)
|
||||
{
|
||||
int rc = zmq_getsockopt (ptr, option_, optval_, optvallen_);
|
||||
if (rc != 0)
|
||||
throw error_t ();
|
||||
}
|
||||
|
||||
inline void bind (const char *addr_)
|
||||
{
|
||||
int rc = zmq_bind (ptr, addr_);
|
||||
if (rc != 0)
|
||||
throw error_t ();
|
||||
}
|
||||
|
||||
inline void unbind (const char *addr_)
|
||||
{
|
||||
int rc = zmq_unbind (ptr, addr_);
|
||||
if (rc != 0)
|
||||
throw error_t ();
|
||||
}
|
||||
|
||||
inline void connect (const char *addr_)
|
||||
{
|
||||
int rc = zmq_connect (ptr, addr_);
|
||||
if (rc != 0)
|
||||
throw error_t ();
|
||||
}
|
||||
|
||||
inline void disconnect (const char *addr_)
|
||||
{
|
||||
int rc = zmq_disconnect (ptr, addr_);
|
||||
if (rc != 0)
|
||||
throw error_t ();
|
||||
}
|
||||
|
||||
inline bool connected()
|
||||
{
|
||||
return(ptr != NULL);
|
||||
}
|
||||
|
||||
inline size_t send (const void *buf_, size_t len_, int flags_ = 0)
|
||||
{
|
||||
int nbytes = zmq_send (ptr, buf_, len_, flags_);
|
||||
if (nbytes >= 0)
|
||||
return (size_t) nbytes;
|
||||
if (zmq_errno () == EAGAIN)
|
||||
return 0;
|
||||
throw error_t ();
|
||||
}
|
||||
|
||||
inline bool send (message_t &msg_, int flags_ = 0)
|
||||
{
|
||||
int nbytes = zmq_msg_send (&(msg_.msg), ptr, flags_);
|
||||
if (nbytes >= 0)
|
||||
return true;
|
||||
if (zmq_errno () == EAGAIN)
|
||||
return false;
|
||||
throw error_t ();
|
||||
}
|
||||
|
||||
#ifdef ZMQ_HAS_RVALUE_REFS
|
||||
inline bool send (message_t &&msg_, int flags_ = 0)
|
||||
{
|
||||
return send(msg_, flags_);
|
||||
}
|
||||
#endif
|
||||
|
||||
inline size_t recv (void *buf_, size_t len_, int flags_ = 0)
|
||||
{
|
||||
int nbytes = zmq_recv (ptr, buf_, len_, flags_);
|
||||
if (nbytes >= 0)
|
||||
return (size_t) nbytes;
|
||||
if (zmq_errno () == EAGAIN)
|
||||
return 0;
|
||||
throw error_t ();
|
||||
}
|
||||
|
||||
inline bool recv (message_t *msg_, int flags_ = 0)
|
||||
{
|
||||
int nbytes = zmq_msg_recv (&(msg_->msg), ptr, flags_);
|
||||
if (nbytes >= 0)
|
||||
return true;
|
||||
if (zmq_errno () == EAGAIN)
|
||||
return false;
|
||||
throw error_t ();
|
||||
}
|
||||
|
||||
private:
|
||||
void *ptr;
|
||||
void *ctxptr;
|
||||
|
||||
socket_t (const socket_t&) ZMQ_DELETED_FUNCTION;
|
||||
void operator = (const socket_t&) ZMQ_DELETED_FUNCTION;
|
||||
};
|
||||
|
||||
class monitor_t
|
||||
{
|
||||
public:
|
||||
monitor_t() : socketPtr(NULL) {}
|
||||
virtual ~monitor_t() {}
|
||||
|
||||
void monitor(socket_t &socket, const char *addr_, int events = ZMQ_EVENT_ALL)
|
||||
{
|
||||
int rc = zmq_socket_monitor(socket.ptr, addr_, events);
|
||||
if (rc != 0)
|
||||
throw error_t ();
|
||||
|
||||
socketPtr = socket.ptr;
|
||||
void *s = zmq_socket (socket.ctxptr, ZMQ_PAIR);
|
||||
assert (s);
|
||||
|
||||
rc = zmq_connect (s, addr_);
|
||||
assert (rc == 0);
|
||||
|
||||
on_monitor_started();
|
||||
|
||||
while (true) {
|
||||
zmq_msg_t eventMsg;
|
||||
zmq_msg_init (&eventMsg);
|
||||
rc = zmq_recvmsg (s, &eventMsg, 0);
|
||||
if (rc == -1 && zmq_errno() == ETERM)
|
||||
break;
|
||||
assert (rc != -1);
|
||||
#if ZMQ_VERSION_MAJOR >= 4
|
||||
const char* data = static_cast<const char*>(zmq_msg_data(&eventMsg));
|
||||
zmq_event_t msgEvent;
|
||||
memcpy(&msgEvent.event, data, sizeof(uint16_t)); data += sizeof(uint16_t);
|
||||
memcpy(&msgEvent.value, data, sizeof(int32_t));
|
||||
zmq_event_t* event = &msgEvent;
|
||||
#else
|
||||
zmq_event_t* event = static_cast<zmq_event_t*>(zmq_msg_data(&eventMsg));
|
||||
#endif
|
||||
|
||||
#ifdef ZMQ_NEW_MONITOR_EVENT_LAYOUT
|
||||
zmq_msg_t addrMsg;
|
||||
zmq_msg_init (&addrMsg);
|
||||
rc = zmq_recvmsg (s, &addrMsg, 0);
|
||||
if (rc == -1 && zmq_errno() == ETERM)
|
||||
break;
|
||||
assert (rc != -1);
|
||||
const char* str = static_cast<const char*>(zmq_msg_data (&addrMsg));
|
||||
std::string address(str, str + zmq_msg_size(&addrMsg));
|
||||
zmq_msg_close (&addrMsg);
|
||||
#else
|
||||
// Bit of a hack, but all events in the zmq_event_t union have the same layout so this will work for all event types.
|
||||
std::string address = event->data.connected.addr;
|
||||
#endif
|
||||
|
||||
#ifdef ZMQ_EVENT_MONITOR_STOPPED
|
||||
if (event->event == ZMQ_EVENT_MONITOR_STOPPED)
|
||||
break;
|
||||
#endif
|
||||
|
||||
switch (event->event) {
|
||||
case ZMQ_EVENT_CONNECTED:
|
||||
on_event_connected(*event, address.c_str());
|
||||
break;
|
||||
case ZMQ_EVENT_CONNECT_DELAYED:
|
||||
on_event_connect_delayed(*event, address.c_str());
|
||||
break;
|
||||
case ZMQ_EVENT_CONNECT_RETRIED:
|
||||
on_event_connect_retried(*event, address.c_str());
|
||||
break;
|
||||
case ZMQ_EVENT_LISTENING:
|
||||
on_event_listening(*event, address.c_str());
|
||||
break;
|
||||
case ZMQ_EVENT_BIND_FAILED:
|
||||
on_event_bind_failed(*event, address.c_str());
|
||||
break;
|
||||
case ZMQ_EVENT_ACCEPTED:
|
||||
on_event_accepted(*event, address.c_str());
|
||||
break;
|
||||
case ZMQ_EVENT_ACCEPT_FAILED:
|
||||
on_event_accept_failed(*event, address.c_str());
|
||||
break;
|
||||
case ZMQ_EVENT_CLOSED:
|
||||
on_event_closed(*event, address.c_str());
|
||||
break;
|
||||
case ZMQ_EVENT_CLOSE_FAILED:
|
||||
on_event_close_failed(*event, address.c_str());
|
||||
break;
|
||||
case ZMQ_EVENT_DISCONNECTED:
|
||||
on_event_disconnected(*event, address.c_str());
|
||||
break;
|
||||
default:
|
||||
on_event_unknown(*event, address.c_str());
|
||||
break;
|
||||
}
|
||||
zmq_msg_close (&eventMsg);
|
||||
}
|
||||
zmq_close (s);
|
||||
socketPtr = NULL;
|
||||
}
|
||||
|
||||
#ifdef ZMQ_EVENT_MONITOR_STOPPED
|
||||
void abort()
|
||||
{
|
||||
if (socketPtr)
|
||||
zmq_socket_monitor(socketPtr, NULL, 0);
|
||||
}
|
||||
#endif
|
||||
virtual void on_monitor_started() {}
|
||||
virtual void on_event_connected(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; }
|
||||
virtual void on_event_connect_delayed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; }
|
||||
virtual void on_event_connect_retried(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; }
|
||||
virtual void on_event_listening(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; }
|
||||
virtual void on_event_bind_failed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; }
|
||||
virtual void on_event_accepted(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; }
|
||||
virtual void on_event_accept_failed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; }
|
||||
virtual void on_event_closed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; }
|
||||
virtual void on_event_close_failed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; }
|
||||
virtual void on_event_disconnected(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; }
|
||||
virtual void on_event_unknown(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; }
|
||||
private:
|
||||
void* socketPtr;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue