Compare commits

...

227 Commits

Author SHA1 Message Date
Pieter Hintjens
98df4b6182 Merge pull request #97 from hintjens/master
Updated NEWS for 4.0.5
2014-10-14 10:06:24 +02:00
Pieter Hintjens
9be6c076cb Updated NEWS for 4.0.5 2014-10-14 10:05:46 +02:00
Pieter Hintjens
47227672ef Merge pull request #95 from ceph/master
Spec file fixes: missing manpages/binaries, renamed library files, doc build requirements
2014-10-01 07:47:45 +02:00
Dan Mick
2d7614961c zeromq.spec.in: missing manpage files
Signed-off-by: Dan Mick <dmick@redhat.com>
2014-09-30 20:06:12 -07:00
Dan Mick
87b35ded47 zeromq.spec.in: shared library version bump
Signed-off-by: Dan Mick <dmick@redhat.com>
2014-09-30 20:06:12 -07:00
Dan Mick
93096d461c zeromq.spec.in: missing binary curve_keygen
Signed-off-by: Dan Mick <dmick@redhat.com>
2014-09-30 20:06:12 -07:00
Dan Mick
b2cb9b9ec2 zeromq.spec.in: Missing build dependencies in specfile: asciidoc, xmlto
Signed-off-by: Dan Mick <dmick@redhat.com>
2014-09-30 20:06:04 -07:00
Dan Mick
f94de6e736 zeromq.spec.in/Makefile: README is no more; replace with README.md
Signed-off-by: Dan Mick <dan.mick@redhat.com>
2014-09-30 20:05:49 -07:00
Pieter Hintjens
eae9cbe72f Merge pull request #93 from hintjens/master
Security fixes
2014-09-20 20:50:51 +02:00
Pieter Hintjens
f024eef27c Updated NEWS for #1190 and #1191 2014-09-20 20:50:25 +02:00
Pieter Hintjens
73e59be321 Updated CURVE test case 2014-09-20 10:39:13 +02:00
Pieter Hintjens
d73b240880 Merged patch for #1190 2014-09-20 10:37:18 +02:00
Pieter Hintjens
88e56365ef Merge pull request #91 from jbreams/master
Clean up after using randombytes from libsodium
2014-09-01 09:22:01 +02:00
Jonathan Reams
16b2db6062 Clean up after using randombytes from libsodium
When Curve authentication is used, libsodium opens a file
descriptor to /dev/urandom to generate random bytes. When
the ZMQ context terminates, it should ensure that file gets
closed.
2014-08-31 14:02:57 -04:00
Pieter Hintjens
ce75ea7448 Merge pull request #90 from vogonsoft/master
Corrected typo in ZMQ_STREAM example
2014-08-03 04:01:19 +02:00
Aleksandar J
7413afe6d6 Corrected typo in ZMQ_STREAM example 2014-08-02 18:42:24 -04:00
Pieter Hintjens
37203c4964 Merge pull request #89 from ewen-naos-nz/zos
z/OS UNIX System Services port
2014-07-24 07:54:38 +02:00
Ewen McNeill
30ba11d970 z/OS: Avoid removing libzmq.pc.in in makeclean 2014-07-24 11:14:07 +12:00
Ewen McNeill
85eac38e53 z/OS: Transferrring from GitHub to z/OS UNIX
Updated:
   builds/zos/README.md: Outlined process to transfer source from
     GitHub to z/OS UNIX System Services, including character set
     conversion for the source
2014-07-24 11:11:54 +12:00
Ewen McNeill
c06ab77c3b z/OS: signal(SIGPIPE, SIG_IGN) for tests
Updated:
   tests/testutil.hpp: Add signal(SIGPIPE, SIG_IGN) to
        setup_test_environment(), on z/OS (__MVS__)
2014-07-24 11:11:54 +12:00
Ewen McNeill
f35d0b6f8d z/OS: Loop on EAGAIN on close() in ~signaler
Updated:
    src/signaler.cpp: Add close_wait_ms() static function to loop
       when receiving EAGAIN in response to close(), with ms long
       sleeps, up to a maximum limit (default 2000ms == 2 seconds);
       used in signaler_t::~signaler_t() destructor.
2014-07-24 11:11:54 +12:00
Ewen McNeill
66d258f0e7 z/OS: Make builds/zos scripts executable 2014-07-24 11:11:54 +12:00
Ewen McNeill
1e6036d0df z/OS: Documented SIGPIPE considerations
Updated:
    README.md: Documented need for application to handle/ignore SIGPIPE
2014-07-24 11:11:54 +12:00
Ewen McNeill
1034bf90c0 Extend z/OS UNIX port to allow building DLL
Updated:
   README.md:  describes process of building/using DLL
   makelibzmq: Build DLL as well as static library (unless BUILD_DLL=false)
   maketests:  Dynamically link to ../src/libzmq.so if present
   runtests:   Explicitly place ../src at start of LIBPATH
   makeclean:  Also remove files created for DLL
   cxxall:     Bumped updated date to reflect last edit
2014-07-24 11:11:54 +12:00
Ewen McNeill
8454fddf5a builds/zos/* portability files to z/OS UNIX
builds/zos includes:
    README.md: Overview of z/OS UNIX System Services port (Markdown)
    makelibzmq: Compile src/*.cpp and make libzmq.a
    maketests:  Compile tests/*.cpp and make test_* executables
    runtests:   Run tests/test_* executables and report results
    makeclean:  Remove built files
    zc++: /bin/c++ wrapper supplying required build arguments
    cxxall: run zc++ for all *.cpp files in directory

    platform.hpp: pre-generated (and edited) src/platform.hpp for z/OS
    test_fork.cpp: updated tests/test_fork.cpp that completes on z/OS
2014-07-24 11:11:54 +12:00
Pieter Hintjens
b4f4d23faf Merge pull request #87 from guidefloripa/master
Add static compilation on CMake
2014-07-02 21:59:49 +02:00
Guilherme Steinmann
bc7b0fd383 Add static compilation on CMake 2014-07-02 10:36:35 -03:00
Pieter Hintjens
678ad54a12 Merge pull request #86 from hintjens/master
Fixed typo in doc example
2014-06-23 20:25:54 +02:00
Pieter Hintjens
03fadb92b4 Fixed typo in doc example 2014-06-23 20:25:05 +02:00
Pieter Hintjens
966c8930b0 Merge pull request #84 from hintjens/master
Fix failed assertion for WSAENOTSOCK
2014-06-10 15:07:21 +02:00
Olaf Mandel
eaf732c25e Fix failed assertion for WSAENOTSOCK
In de9eef306, the error number assigned to WSAENOTSOCK was EFAULT, but
zmq.cpp:919 expects an ENOTSOCK in this case.
2014-06-10 15:06:27 +02:00
Pieter Hintjens
90dbc100c4 Merge pull request #83 from olafmandel/backport_1072
Extend zmq::wsa_error_to_errno()
2014-06-04 17:56:39 +02:00
Olaf Mandel
2c754fc0a9 Extend zmq::wsa_error_to_errno()
The list of error codes is taken from zmq::wsa_error_no(). Most of the
new WSA error codes result in EFAULT, but some return a more specific
value (even EAGAIN).

Backport of zeromq/libzmq#1072
2014-06-04 17:41:03 +02:00
Pieter Hintjens
dd478a0d20 Merge pull request #82 from hintjens/master
Updated NEWS
2014-05-23 10:13:33 +02:00
Pieter Hintjens
a6e85ded33 Updated for #1015 2014-05-23 10:13:13 +02:00
Pieter Hintjens
2dc95612a8 Updated NEWS 2014-05-23 10:13:12 +02:00
Pieter Hintjens
9766baa9d3 Merge pull request #81 from olafmandel/issue_1015
Backport of test and fix for zeromq/libzmq#1015
2014-05-23 10:10:58 +02:00
Olaf Mandel
d4d26b1cc0 Fix race condition in connecting inproc sockets
This is a backport of libzmq:3678c32b9
by Martin Hurton <hurtonm@gmail.com>
2014-05-21 17:02:01 +02:00
Olaf Mandel
a6bd295210 Add failing test reproducing issue #1015.
There is a race condition when connect and bind on a new inproc
endpoint happen "simultaneously" in threads.  Causes the error:
  Assertion failed: ok (ctx.cpp:474)

This is a backport of libzmq:5cf74db6b
by Joe Eli McIlvain <joe.eli.mac@gmail.com>
2014-05-21 16:58:01 +02:00
Pieter Hintjens
bb30e9efc7 Merge pull request #79 from olafmandel/master
Fix identity handling for inproc transport
2014-05-12 16:32:57 +02:00
Olaf Mandel
550c32ed10 Fix identity handling for inproc transport
Fixes #872

Backport of hurtonm/libzmq@a09407829; included as
zeromq/libzmq@e376ad278 in development repos.
2014-05-12 15:21:56 +02:00
Pieter Hintjens
c639251c3e Merge pull request #78 from hintjens/master
Fixed issue #994
2014-05-01 16:31:19 +02:00
Pieter Hintjens
65763041df Problem: generates incompatible libzmq.so.3.1.0
See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=743508

The ABI in fact changed in two significant ways, one with inproc
connects, and one with socket monitoring

Solution: generate libzmq.so.4.0.0 library instead.

This change should be backported to zeromq-4.x

Conflicts:
	.gitignore
2014-05-01 16:30:11 +02:00
Pieter Hintjens
7a0425be9e Updated NEWS 2014-04-29 22:52:19 +02:00
Pieter Hintjens
4f4723a684 Merge pull request #76 from mditzel/master
Fix issue #75
2014-04-14 14:02:11 +02:00
Maarten Ditzel
2394784995 Merge branch 'master' of https://github.com/mditzel/zeromq4-x 2014-04-14 13:36:57 +02:00
Maarten Ditzel
488cf5e04c Merge branch 'master' of https://github.com/zeromq/zeromq4-x 2014-04-14 13:36:27 +02:00
Maarten Ditzel
b69cf0d70d Merge branch 'master' of https://github.com/zeromq/zeromq4-x 2014-04-14 11:13:49 +02:00
Maarten Ditzel
75fbd4f8d6 Fix issue #75 2014-04-14 11:01:49 +02:00
Maarten Ditzel
66b49261a8 Fixed link error when cross-compiling with mingw. 2014-04-11 10:10:30 +02:00
Pieter Hintjens
f3cc00b4af Merge pull request #74 from mditzel/master
Fix #73: link error when cross-compiling with mingw.
2014-04-11 09:51:51 +02:00
Pieter Hintjens
dd488421c8 Merge pull request #72 from hintjens/master
Resolve issue #939
2014-04-03 20:49:35 +02:00
Martin Hurton
2ae11cdc8d Resolve issue #939
This bug is caused by fq which can terminate pipe before sending all
frames of a message first. So sometimes two messages were mixed and this
confused ZAP handler.

This patch just modifies one pipe parameter so that socket consumes all
messages before dropping the pipe.
2014-04-03 20:37:10 +02:00
Pieter Hintjens
e02fd0ce36 Merge pull request #71 from hintjens/master
Added man page for zmq_proxy_steerable
2014-03-25 15:22:54 +01:00
Pieter Hintjens
612f6ac862 Added man page for zmq_proxy_steerable 2014-03-25 15:22:01 +01:00
Pieter Hintjens
e2d9aaeb88 Merge pull request #70 from hintjens/master
Backported #797
2014-03-25 07:13:38 +01:00
Pieter Hintjens
c83cc01e03 Backported #797 2014-03-25 07:13:00 +01:00
KIU Shueng Chuan
c1b055a6d8 fix: win32 tcp_keepalive gets set even when option is -1 2014-03-25 07:12:06 +01:00
Pieter Hintjens
0da2a0bed6 Merge pull request #68 from hintjens/master
Bumped version for next release
2014-03-21 07:43:14 +02:00
Pieter Hintjens
3e65ddfce3 Bumped version for next release 2014-03-21 07:42:28 +02:00
Pieter Hintjens
25b692b109 Merge pull request #67 from cosmoharrigan/proxy
Backport zmq_proxy_steerable and fix error in proxy function prototype
2014-03-19 09:53:39 +02:00
Cosmo Harrigan
e0f718bbd2 Backport zmq_proxy_steerable and fix error in proxy function prototype. 2014-03-17 17:55:59 -07:00
Pieter Hintjens
1ac53ed1f7 Merge pull request #66 from hintjens/master
Source package did not build
2014-03-10 22:41:14 +01:00
Pieter Hintjens
7f08204e9f Source package did not build 2014-03-10 22:40:48 +01:00
Pieter Hintjens
2eb63360d6 Merge pull request #64 from hintjens/master
Bumped NEWS for 4.0.4 release
2014-03-10 13:41:48 +01:00
Pieter Hintjens
930ef37738 Bumped NEWS for 4.0.4 release 2014-03-10 13:40:49 +01:00
Pieter Hintjens
e5473a7a69 Merge pull request #63 from hintjens/master
Backported fix for #909
2014-03-03 12:10:18 +01:00
Josh Blum
dd5603d6e9 Updated NEWS for #909 2014-03-03 12:09:40 +01:00
Pieter Hintjens
03dc70c350 Updated for #60 2014-02-13 19:21:42 +01:00
Pieter Hintjens
97292367eb Updated NEWS 2014-02-13 19:20:56 +01:00
Pieter Hintjens
ebbbdf89cb Merge pull request #60 from ricnewton/master
Fix hang on terminate when inproc is connected but never bound
2014-02-13 19:20:28 +01:00
Richard Newton
c7a7de12a3 Backported fix for #888 2014-02-13 14:56:09 +00:00
Pieter Hintjens
e655fd138d Merge pull request #57 from Debian/counter
Fix timestamp counter on s390/s390x
2014-02-05 21:11:10 +01:00
Pieter Hintjens
0e147bb691 Merge pull request #56 from Debian/symbols
Only export zmq_* symbols
2014-02-05 21:10:49 +01:00
Alessandro Ghedini
4b9cd7764a Only export zmq_* symbols 2014-02-05 20:43:13 +01:00
Alessandro Ghedini
2493a99735 Fix timestamp counter on s390/s390x
Fixes #811
2014-02-05 20:42:40 +01:00
Pieter Hintjens
d4f988649d Merge pull request #55 from hintjens/master
Fixed issue #868
2014-02-03 02:55:18 -08:00
Pieter Hintjens
830e022987 Fixed #868 2014-02-03 11:22:22 +01:00
Pieter Hintjens
5a576d22db Updated NEWS for #584 2014-02-03 11:22:22 +01:00
Pieter Hintjens
89c762fb0a Clarified ZMQ_IDENTITY doc for duplicate identities 2014-02-03 11:22:22 +01:00
Pieter Hintjens
0b11c3174e Merge pull request #51 from EricMCornelius/master
Corrects ypipe initialization when conflate is NOT enabled.
2014-01-15 22:11:50 -08:00
Pieter Hintjens
129cb00d8f Update README.md 2014-01-15 21:39:21 +01:00
Pieter Hintjens
6982e69da4 Update README.md 2014-01-15 21:39:00 +01:00
Eric Cornelius
63fe43a101 Corrects ypipe initialization when conflate is NOT enabled. Fixes LIBZMQ-584 2014-01-15 12:18:50 -08:00
Pieter Hintjens
3f3f9dcec2 Merge pull request #47 from vortechs2000/fix_news
Adjust NEWS to include LIBZMQ-576
2014-01-02 14:45:47 -08:00
AJ Lewis
53bef03e7b Adjust NEWS to include LIBZMQ-576 2014-01-02 16:39:03 -06:00
Pieter Hintjens
a37c198c7d Merge pull request #46 from vortechs2000/fix-libzmq-576
Fix LIBZMQ-576 - Revert "Merge pull request #510 from miniway/master"
2014-01-02 13:12:18 -08:00
AJ Lewis
047bd130cf Fix LIBZMQ-576 - Revert "Merge pull request #510 from miniway/master"
This reverts commit f27eb67e1abb0484c41050e454404cce30647b63, reversing
changes made to a3ae0d4c16c892a4e6c96d626a7c8b7068450336.

Conflicts:
	src/stream_engine.cpp

Conflicts were around additional defaults to the constructor after the
'terminating' default.  The additional defaults were left alone, and
the 'terminating' default was removed.
2014-01-02 11:04:43 -06:00
Pieter Hintjens
5db0acb044 Merge pull request #44 from hintjens/master
Issue 797
2013-12-23 04:18:04 -08:00
Pieter Hintjens
845ee0c7bc Updated NEWS 2013-12-23 13:17:38 +01:00
Alex Grönholm
2ba0d159b5 Fixed setting TCP keepalive parameters on Windows 2013-12-23 13:16:18 +01:00
Pieter Hintjens
571c668fa2 Merge pull request #43 from hintjens/master
Backporting fixes from master
2013-12-06 14:30:23 -08:00
Pieter Hintjens
0552d9119b Updated news for #775 2013-12-05 16:52:36 +01:00
KIU Shueng Chuan
3dc89feafc use enum retired_fd instead of -1
using -1 causes a warning on Windows platform because SOCKET is unsigned.
2013-12-05 16:50:15 +01:00
Pieter Hintjens
97e1ecce22 Merge pull request #40 from hintjens/master
Backported fix for #763
2013-12-01 02:55:48 -08:00
Pieter Hintjens
d958b675c7 Updated NEWS for #763 2013-12-01 11:54:55 +01:00
Martin Hurton
ff8f97e7d7 Fix issue #763 2013-12-01 11:53:12 +01:00
Pieter Hintjens
75ba4c7292 Updated version number for release 4.0.4 2013-11-24 19:00:18 +01:00
Pieter Hintjens
8b9a82476b Merge pull request #37 from hintjens/master
Fixed test_many_sockets
2013-11-24 09:58:59 -08:00
Pieter Hintjens
4363b75b4d Release notes for 4.0.3 2013-11-24 18:56:50 +01:00
Pieter Hintjens
c022c048dc Fixed test_many_sockets
* failed on systems where process could not allocate 1024 sockets by default
* include path for platform.hpp was wrong; fixed it
2013-11-24 18:55:28 +01:00
Pieter Hintjens
78b741bd71 Merge pull request #36 from hintjens/master
Updated version number for 4.0.2
2013-11-24 03:47:58 -08:00
Pieter Hintjens
ba7c065c3d Updated version number for 4.0.2
- also moved macros to top of zmq.h for better visibility
2013-11-24 12:45:47 +01:00
Pieter Hintjens
d743ddafda Merge pull request #35 from hintjens/master
Updated NEWS for release 4.0.2
2013-11-24 03:42:01 -08:00
Pieter Hintjens
84c0caf42e Updated NEWS for release 4.0.2 2013-11-24 12:41:20 +01:00
Pieter Hintjens
e1939155ff Merge pull request #34 from hintjens/master
Backporting fixes from master
2013-11-19 02:01:23 -08:00
Pieter Hintjens
9ece2d322a Added links to RFCs for socket patterns 2013-11-19 11:00:45 +01:00
KIU Shueng Chuan
589bf436dd remove all asserts during critical section
the size of the critical section is reduced by only entering the critical
section right before the bind().
2013-11-19 11:00:39 +01:00
KIU Shueng Chuan
e54e55835e return error to caller on bind error 2013-11-19 11:00:28 +01:00
Richard Newton
111c20dc22 Fix signed/unsigned comparison 2013-11-19 11:00:07 +01:00
Richard Newton
3a4896f4a3 Fix signed/unsigned comparison 2013-11-19 10:59:57 +01:00
Richard Newton
0855c28069 Reduce default maximum number of sockets by 1 so there is room for the reaper socket. 2013-11-19 10:58:34 +01:00
Richard Newton
737b6afc97 Revert "Make FD_SETSIZE = ZMQ_MAX_SOCKETS_DFLT + 1 so there is room for the repear socket."
This reverts commit 0b92831b2a82c3bbc0e9371662c546b94915a3ea.
2013-11-19 10:58:28 +01:00
psl-felipefarinon
8f85bafe37 issue #583 removing C++11 code. 2013-11-19 10:58:20 +01:00
Bruno D. Rodrigues
f72dbb35d5 Fix socket creation above sistem limits for all 'other' OS not covered by eventfd, windows or vms; enhanced test to create sockets up to a bigger limit to really test hitting the OS limit 2013-11-19 10:55:48 +01:00
Pieter Hintjens
5d6e7a74c1 Added test case to ignore 2013-11-09 09:59:21 +01:00
Pieter Hintjens
30309d660e Merge pull request #32 from hintjens/master
Cherry picking changes from libzmq master
2013-11-09 00:56:52 -08:00
Pieter Hintjens
e0c8a112a4 Cherry picking fixes from master 2013-11-09 09:56:21 +01:00
Martin Hurton
f6293d257d Signal that the peer performed orderly shutdown 2013-11-09 09:52:09 +01:00
Richard Newton
f33bdcf02e Fix formatting. 2013-11-09 09:52:08 +01:00
Richard Newton
fef24a8c1f Make FD_SETSIZE = ZMQ_MAX_SOCKETS_DFLT + 1 so there is room for the repear socket. 2013-11-09 09:52:05 +01:00
Richard Newton
bfc3deb43a Get maximum number of sockets it can handle from poller_t 2013-11-09 09:52:02 +01:00
psl-felipefarinon
dccf1dce1e Fixing broken build issue #583 2013-11-09 09:51:59 +01:00
Richard Newton
24311dee1b Add test case for many sockets
Conflicts:
	CMakeLists.txt
	tests/Makefile.am
2013-11-09 09:50:43 +01:00
psl-felipefarinon
27d20aacc7 Fixing issue #583. Using low resolution timer for clock::now_ms 2013-11-09 09:47:41 +01:00
Pieter Hintjens
b2698474d2 Simplified fdpair reset after fork 2013-11-09 09:47:40 +01:00
Pieter Hintjens
0465e9abe9 Simplified error handling for make_fdpair on Windows 2013-11-09 09:47:04 +01:00
Pieter Hintjens
885c816e57 Fix for issue 574 2013-11-09 09:47:02 +01:00
Pieter Hintjens
7f3d0995cd Removed over-long pauses in tests
- used msleep (10) in most places instead of zmq_sleep (1)
- may cause failures on slower machines
- to change, modify SETTLE_TIME in testutil.h
- tested down to 1 msec on fast boxes

Conflicts:
	tests/test_connect_delay_tipc.cpp
	tests/test_proxy.cpp
	tests/test_sub_forward_tipc.cpp
	tests/test_term_endpoint_tipc.cpp
	tests/testutil.hpp
2013-11-09 09:44:17 +01:00
Pieter Hintjens
f745e4ce64 Merge pull request #31 from hintjens/master
Backported fixes for libzmq-39 and other patches.
2013-11-06 11:26:05 -08:00
Richard Newton
de239f358e Fix race condition on shutdown 2013-11-06 20:16:03 +01:00
Richard Newton
30f470eff5 Fix test warning. 2013-11-06 20:16:03 +01:00
Richard Newton
f0b69bba28 Fix test warning. 2013-11-06 20:16:03 +01:00
MinRK
60032ef330 test zmq_msg_close after sending empty message on ROUTER_RAW 2013-11-06 20:16:03 +01:00
MinRK
c663f37761 add missing msg->init for ROUTER_RAW with empty message 2013-11-06 20:16:03 +01:00
Pieter Hintjens
806f57e7f6 Merge pull request #30 from hintjens/master
Cherry picking fixes from libzmq
2013-11-04 08:44:38 -08:00
Pieter Hintjens
b22c2e4f8a Updated NEWS 2013-11-04 17:37:15 +01:00
Denis Mingulov
54a3ebcac6 Doc examples with zmq_msg_close usage - parameter is 'zmq_msg_t *'
Documentation examples for zmq_msg_get and zmq_msg_more functions have an
incorrect call to zmq_msg_close function - with 'zmq_msg_t' as a parameter
despite 'zmq_msg_t *' is required, so it is impossible to compile these
examples properly.

Also for zmq_msg_get example - declaration of zmq_msg_t variable is added
(like it is done in other examples).
2013-11-04 17:35:47 +01:00
Pieter Hintjens
aede37e3e5 Fixed issue 578 - corrected type usage 2013-11-04 17:34:54 +01:00
Pieter Hintjens
2949f2dbc5 Fixed issue 578 2013-11-04 17:34:14 +01:00
Pieter Hintjens
28b7c991af Merge pull request #28 from hintjens/master
Fixed configure error on non-Linux boxes
2013-10-28 03:58:52 -07:00
Pieter Hintjens
1c70e91c6f Fixed configure error on non-Linux boxes 2013-10-28 11:58:29 +01:00
Pieter Hintjens
c85fbaf22e Merge pull request #27 from hintjens/master
Fixed ref to zmq_socket_monitor
2013-10-28 03:49:45 -07:00
Pieter Hintjens
b58055794b Fixed ref to zmq_socket_monitor 2013-10-28 11:49:23 +01:00
Pieter Hintjens
cb3c82271a Merge pull request #26 from hintjens/master
Backporting fixes from master
2013-10-25 01:04:06 -07:00
Pieter Hintjens
9bf10a83a1 Updated NEWS 2013-10-25 10:03:42 +02:00
Pieter Hintjens
8efd7affc6 test_stream failed when response was broken into frames 2013-10-25 09:56:04 +02:00
Pieter Hintjens
bf97ea8ed8 Merge pull request #25 from hintjens/master
Clarified use of secret/public keys
2013-10-23 07:04:20 -07:00
Pieter Hintjens
cd2afebd0a Clarified use of secret/public keys 2013-10-23 16:03:45 +02:00
Pieter Hintjens
2b8d86c24a Merge pull request #24 from hintjens/master
Fixed man page for CURVE key options
2013-10-23 03:05:44 -07:00
Pieter Hintjens
bd411bbf11 Fixed man page for CURVE key options 2013-10-23 12:04:57 +02:00
Pieter Hintjens
573d7b0c0b Merge pull request #23 from hintjens/master
Backporting LIBZMQ-569 fix from master
2013-10-13 23:05:54 -07:00
Pieter Hintjens
dcb9312ba6 Updated NEWS for backport 2013-10-14 08:04:57 +02:00
Martin Hurton
5490794666 Load identity message to decoder at start 2013-10-14 08:03:36 +02:00
Pieter Hintjens
07d7cf69d0 Merge pull request #22 from hintjens/master
Temporary workaround for broken libsodium install
2013-10-13 05:47:11 -07:00
Pieter Hintjens
b24db36057 Temporary workaround for broken libsodium install 2013-10-13 14:46:08 +02:00
Pieter Hintjens
4f2ac39d28 Merge pull request #21 from hintjens/master
Backporting fixes from master
2013-10-11 03:12:27 -07:00
Pieter Hintjens
a32c02ae47 Identity can only be set on sockets that can connect to ROUTER 2013-10-11 11:47:33 +02:00
Martin Hurton
622e3b5476 Rename engine's methods to improve code readability 2013-10-11 11:47:12 +02:00
xantares
6c036b39ae Fixed out-of-source build 2013-10-11 11:46:50 +02:00
Pieter Hintjens
8cdff6fa2e Fixed NEWS 2013-10-08 17:54:41 +02:00
Pieter Hintjens
f8cebb460a Revert "replace macro constants with enum types for user facing constants"
This reverts commit 4fb74539250d83e82e40e85d39e2e756eccdb8a3.
2013-10-08 15:02:58 +02:00
Pieter Hintjens
d62e7a0734 Revert "distinguish between options and defaults"
This reverts commit e7db680f5b709ce821f79b1e8956f4cbd1931c11.
2013-10-08 15:02:47 +02:00
Pieter Hintjens
a44bd65d03 Fixed NEWS for 4.0.1 release 2013-10-08 10:46:47 +02:00
Pieter Hintjens
437e4070a3 Merge pull request #19 from hintjens/master
Updated NEWS for 4.0.1
2013-10-08 01:36:58 -07:00
Pieter Hintjens
0bfcd4da2f Updated NEWS for 4.0.1 2013-10-08 10:33:50 +02:00
Pieter Hintjens
c852620f5f Merge pull request #18 from hintjens/master
Cherry picking changes from libzmq master
2013-10-08 00:20:40 -07:00
Volodymyr Korniichuk
ca122e9d01 Typo in type name "emTPy_slots_t"
https://zeromq.jira.com/browse/LIBZMQ-565
2013-10-08 09:20:15 +02:00
Dylan Cali
e7db680f5b distinguish between options and defaults 2013-10-08 09:19:55 +02:00
Dylan Cali
4fb7453925 replace macro constants with enum types for user facing constants 2013-10-08 09:19:49 +02:00
Brandon Carpenter
813166019e Add tests/test_abstract_ipc to .gitignore. 2013-10-07 20:53:20 +02:00
Brandon Carpenter
127cd7585a Fix detection of abstract ipc pathname and length calculation.
Abstract socket pathnames must have a NULL character in the first
position, but the second character must also be checked to differentiate
an abstract name from the empty string.  The address length must also
indicate the length of the pathname because the kernel uses the entire
address as the name, including NULL characters.  ZMQ uses
NULL-terminated strings for the address, so the abstract address length
is the length of the string following the initial NULL byte plus 3; two
bytes for the address family and one for the initial NULL character.
2013-10-07 20:53:10 +02:00
Brandon Carpenter
0666152b21 Add note on Linux abstract namespace to ipc documentation. 2013-10-07 20:53:00 +02:00
Volodymyr Korniichuk
9293153f71 useless checks were removed 2013-10-05 09:22:56 +02:00
Pieter Hintjens
163aebbacf Merge pull request #17 from hintjens/master
Cherry picking changes from libzmq master
2013-10-05 00:20:49 -07:00
Brandon Carpenter
80d657a2c5 Add test for abstract namespace support in ipc sockets on Linux.
See issue 567.
2013-10-05 09:20:20 +02:00
Brandon Carpenter
668f000cb1 Add abstract namespace support for IPC sockets on Linux.
Converts an initial strudel or "at sign" (@) in the Unix socket path to
a NULL character ('\0') indicating that the socket uses the abstract
namespace instead of the filesystem namespace.  For instance, binding a
socket to 'ipc://@/tmp/tester' will not create a file associated with
the socket whereas binding to 'ipc:///tmp/tester' will create the file
/tmp/tester.  See issue 567 for more information.
2013-10-05 09:20:13 +02:00
KIU Shueng Chuan
a570b18931 WinSock2.h filename should be all lowercase 2013-10-05 09:20:06 +02:00
KIU Shueng Chuan
5493d4d180 test for _MSC_VER before using MSVC specific code 2013-10-05 09:19:58 +02:00
Pieter Hintjens
b20573c841 Merge pull request #16 from hintjens/master
Cherry picking changes from libzmq master
2013-10-04 00:19:57 -07:00
Martin Hurton
814b93e0cf Stop curve handshake when cookie box verification fails 2013-10-04 09:19:11 +02:00
Pieter Hintjens
d723b08c13 Updated libzmq CURVE to track RFC 27
* The INITIATE command vouch box is Box[C',S](C->S') instead of Box[C'](C->S),
  as recommended by https://codesinchaos.wordpress.com/2012/09/09/curvecp-1/,
  to reduce the risk of client impersonation.

* Mirrors the change in libcurve and CurveZMQ specifications.
2013-10-04 09:19:04 +02:00
Matt Connolly
62fd6fa861 git ignore test run output files: tests/test*.{log|trs} 2013-10-04 09:17:34 +02:00
Pieter Hintjens
a78ccf293f Disabled randomly failing part of test 2013-10-04 09:13:35 +02:00
Pieter Hintjens
d82ba6bd53 Clarified that zmq.h constants are part of the public contract 2013-10-04 09:13:17 +02:00
Dylan Cali
9da52ddf59 fix minor typo in zmq_ctx_get doc example 2013-10-04 09:13:11 +02:00
Pieter Hintjens
a69fa9ecde Packaging for zmq_curve_keypair function
* Added new man page for this
* Added test case, in tests/test_security_curve.cpp
* Noted in zmq_utils.h that these methods are documented
2013-10-04 09:13:05 +02:00
MinRK
facb96ffca use zmq_curve_keypair in curve_keygen 2013-10-04 09:12:56 +02:00
MinRK
3c469d04c1 return NULL and set EINVAL on bad z85 input
asserts aren't appropriate for checking user input.
2013-10-04 09:12:33 +02:00
MinRK
870233522c add zmq_curve_keypair to zmq_utils 2013-10-04 09:12:09 +02:00
Pieter Hintjens
34471cd591 Merge pull request #12 from hintjens/master
Backporting fixes from master
2013-09-29 08:04:10 -07:00
Pieter Hintjens
453ceb65b4 Fixed merge conflict error 2013-09-29 17:03:44 +02:00
Matt Connolly
4d82544c34 config for libsodium in alternate path, using CPP flags for both C and C++ sources. 2013-09-29 17:01:15 +02:00
MinRK
bd6bca7c82 include missing platform.hpp in curve_keygen
it was excluded, so HAVE_SODIUM would never be defined,
leading to curve_keygen always reporting "recompile with libsodium"
2013-09-29 17:01:00 +02:00
MinRK
087ddac593 declare z85_encode / decode in zmq_utils
they are used by curve_keygen, but not available
2013-09-29 17:00:22 +02:00
Matt Connolly
d1b686b644 Disable compiler warning for Solaris 2013-09-27 13:39:10 +02:00
Matt Connolly
4dc36c0dba Add '-lssp' linker flag for Solaris. Check for libraries after host specific setup. 2013-09-27 13:38:55 +02:00
Pieter Hintjens
17d12a6be1 Merge pull request #9 from hintjens/master
Cherry picking changes from libzmq master
2013-09-26 05:48:49 -07:00
Pieter Hintjens
89b97cbe59 Updated CMake project for test_issue_566 2013-09-26 14:46:49 +02:00
Pieter Hintjens
b0059211d5 Added test case for issue 566
* Tests dealer-to-router connection 100 times
* This was failing in ZMQ v4.0.0 RC1
2013-09-26 14:46:35 +02:00
Pieter Hintjens
cd452d5019 Merge pull request #8 from hintjens/master
Backporting fixes from master
2013-09-26 03:32:10 -07:00
Pieter Hintjens
dd185e13bf Bumped version for 4.0.1 2013-09-26 12:31:43 +02:00
Pieter Hintjens
517601de10 curve_keygen needed assert.h 2013-09-26 12:17:36 +02:00
Pieter Hintjens
5e25b32c36 Build/test errors on OS/X with clang++ 2013-09-26 12:17:28 +02:00
Martin Hurton
a5152245bd Call flush after writing the identity message 2013-09-26 10:07:29 +02:00
Pieter Hintjens
9cbcc49a4a Merge pull request #6 from ipechorin/master
stdint.h is not available on all platforms
2013-09-24 03:32:02 -07:00
Pieter Hintjens
2d5bad96e3 Merge pull request #7 from hintjens/master
Fixed build for MSVC 2008
2013-09-24 03:31:08 -07:00
Pieter Hintjens
c99b727f6d Fixed build for MSVC 2008 2013-09-24 12:29:29 +02:00
Ivan Pechorin
8a931a7554 stdint.h is not available on all platforms 2013-09-24 14:00:08 +04:00
Pieter Hintjens
b04df2c530 Merge pull request #4 from hintjens/master
Updated library ABI version
2013-09-24 00:12:03 -07:00
Pieter Hintjens
4df7cb043e Bumped library version and age 2013-09-24 09:11:17 +02:00
Pieter Hintjens
201454e866 Move away from port 8080 which is occupied on some boxes 2013-09-20 23:17:01 +02:00
Richard Newton
ad1bae2160 Merge pull request #3 from vortechs2000/fix_aix
Revert "Reference platform.h by ../src/platform.h - AIX is ignoring -I flags"
2013-09-20 12:48:29 -07:00
AJ Lewis
77f394a681 Revert "Reference platform.h by ../src/platform.h - AIX is ignoring -I flags"
This reverts commit 1e8e4d79c885b27831e2196d94987cc2817e0f04.
2013-09-20 14:39:01 -05:00
Pieter Hintjens
61d8bf9b11 Merge pull request #2 from vortechs2000/fix_aix
Reference platform.h by ../src/platform.h - AIX is ignoring -I flags
2013-09-20 09:54:03 -07:00
AJ Lewis
1e8e4d79c8 Reference platform.h by ../src/platform.h - AIX is ignoring -I flags 2013-09-20 11:43:53 -05:00
Pieter Hintjens
c0c8ce5508 File was missing from Makefile.am 2013-09-20 16:41:08 +02:00
Pieter Hintjens
66b1bc6d7f Added link to security tutorial 2013-09-20 16:15:53 +02:00
Pieter Hintjens
f5ecc826d9 Merge pull request #1 from hintjens/master
Preparation for 4.0.0 release
2013-09-20 07:06:48 -07:00
Pieter Hintjens
a31fe9565a Source distribution was broken 2013-09-20 16:03:14 +02:00
Pieter Hintjens
2f4905500d Version number is 4.0.0 2013-09-20 16:02:55 +02:00
Pieter Hintjens
c10a3ec526 Updated NEWS for 4.0.0 2013-09-20 15:53:27 +02:00
Pieter Hintjens
e0676a2b26 Renamed new socket options to be clearer
* ZMQ_REQ_STRICT was negative option (default 1) which goes against
  the standard, where defaults are zero. I renamed this to
  ZMQ_REQ_RELAXED.

* ZMQ_REQ_REQUEST_IDS felt clumsy and describes the technical solution
  rather than the problem/requirement. I changed to ZMQ_REQ_CORRELATE
  which seems more explicit.
2013-09-20 15:50:25 +02:00
Pieter Hintjens
b411a3561d Removed inaccurate note in zmq_poll man page 2013-09-20 15:35:20 +02:00
Pieter Hintjens
4ce9b42405 Built zmq_send_const man page properly 2013-09-20 15:35:11 +02:00
Pieter Hintjens
fef4fa8fc5 Renamed test_connect_delay to test_immediate
* The ZMQ_CONNECT_DELAY option was renamed to ZMQ_IMMEDIATE
2013-09-20 15:34:55 +02:00
Pieter Hintjens
4298f71cbf Updated NEWS for 3.2.x releases 2013-09-20 13:28:25 +02:00
106 changed files with 3237 additions and 567 deletions

27
.gitignore vendored
View File

@ -22,6 +22,7 @@ autom4te.cache
.*~
tools/curve_keygen.o
tools/curve_keygen
tests/test_issue_566
tests/test_ctx_destroy
tests/test_term_endpoint
tests/test_system
@ -43,7 +44,7 @@ tests/test_invalid_rep
tests/test_msg_flags
tests/test_ts_context
tests/test_connect_resolve
tests/test_connect_delay
tests/test_immediate
tests/test_term_endpoint
tests/test_router_mandatory
tests/test_disconnect_inproc
@ -60,14 +61,34 @@ tests/test_spec_pushpull
tests/test_spec_rep
tests/test_spec_req
tests/test_spec_router
tests/test_req_request_ids
tests/test_req_strict
tests/test_req_correlate
tests/test_req_relaxed
tests/test_fork
tests/test_conflate
tests/test_inproc_connect
tests/test_linger
tests/test_security_null
tests/test_security_plain
tests/test_abstract_ipc
tests/test_connect_delay_tipc
tests/test_pair_tipc
tests/test_reqrep_device_tipc
tests/test_reqrep_tipc
tests/test_router_handover
tests/test_router_mandatory_tipc
tests/test_router_raw_empty
tests/test_shutdown_stress_tipc
tests/test_sub_forward_tipc
tests/test_term_endpoint_tipc
tests/test_many_sockets
tests/test_diffserv
tests/test_connect_rid
tests/test_srcfd
tests/test_stream_disconnect
tests/test_proxy_chain
tests/test_bind_src_address
tests/test*.log
tests/test*.trs
src/platform.hpp*
src/stamp-h1
perf/local_lat

View File

@ -6,8 +6,11 @@ language: c
before_script:
# libsodium
# Commit 8d0942 broke installation (sodium.h not found) so for now
# we're checking out the last good commit.
- git clone git://github.com/jedisct1/libsodium.git
- cd libsodium
- git checkout e2a30a
- ./autogen.sh
- ./configure && make check
- sudo make install
@ -15,4 +18,4 @@ before_script:
- cd ..
# Build and check libzmq
script: ./autogen.sh && ./configure && make && make check
script: ./autogen.sh && ./configure && make V=1 && make check

View File

@ -20,6 +20,7 @@ Ben Gray <ben@benjamg.com>
Bernd Prager <bernd@prager.ws>
Bernd Melchers <melchers@ZEDAT.FU-Berlin.DE>
Bob Beaty <rbeaty@peak6.com>
Brandon Carpenter <hashstat@yahoo.com>
Brian Buchanan <bwb@holo.org>
Brett Cameron <Brett.Cameron@hp.com>
Burak Arslan <burak-github@arskom.com.tr>

View File

@ -365,7 +365,7 @@ if(MINGW)
set(CMAKE_RC_COMPILER_INIT windres)
enable_language(RC)
set(CMAKE_RC_COMPILE_OBJECT
"<CMAKE_RC_COMPILER> <FLAGS> --target=${rc_target} <DEFINES> -i <SOURCE> -o <OBJECT>")
"<CMAKE_RC_COMPILER> <FLAGS> -O coff --target=${rc_target} <DEFINES> -i <SOURCE> -o <OBJECT>")
endmacro()
if( ${CMAKE_SYSTEM_PROCESSOR} MATCHES "i386"
@ -412,10 +412,6 @@ foreach(source ${cxx-sources})
list(APPEND sources ${CMAKE_CURRENT_SOURCE_DIR}/src/${source})
endforeach()
foreach(source ${rc-sources})
list(APPEND sources ${CMAKE_CURRENT_BINARY_DIR}/${source})
endforeach()
foreach(source ${rc-sources})
list(APPEND sources ${CMAKE_CURRENT_BINARY_DIR}/${source})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/${source}.in ${CMAKE_CURRENT_BINARY_DIR}/${source})
@ -526,6 +522,11 @@ else()
OUTPUT_NAME "zmq"
PUBLIC_HEADER "${public_headers}")
endif()
add_library(libzmq-static STATIC ${sources} ${public_headers} ${html-docs} ${readme-docs} ${zmq-pkgconfig})
set_target_properties(libzmq-static PROPERTIES
PUBLIC_HEADER "${public_headers}"
COMPILE_FLAGS "-DZMQ_STATIC"
OUTPUT_NAME "zmq-static")
endif()
target_link_libraries(libzmq ${CMAKE_THREAD_LIBS_INIT})
@ -579,7 +580,7 @@ endif()
enable_testing()
set(tests
test_system
test_connect_delay
test_immediate
test_connect_resolve
test_ctx_destroy
test_ctx_options
@ -592,8 +593,8 @@ set(tests
test_pair_inproc
test_pair_tcp
test_probe_router
test_req_request_ids
test_req_strict
test_req_correlate
test_req_relaxed
test_reqrep_device
test_reqrep_inproc
test_reqrep_tcp
@ -610,7 +611,10 @@ set(tests
test_sub_forward
test_term_endpoint
test_timeo
test_inproc_connect)
test_inproc_connect
test_issue_566
test_many_sockets
)
if(NOT WIN32)
list(APPEND tests
test_monitor
@ -656,7 +660,7 @@ if(MSVC)
COMPONENT Runtime)
endif()
else()
install(TARGETS libzmq
install(TARGETS libzmq libzmq-static
RUNTIME DESTINATION bin
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib

View File

@ -12,6 +12,7 @@ EXTRA_DIST = \
autogen.sh \
version.sh \
MAINTAINERS \
README.md \
foreign/openpgm/@pgm_basename@.tar.gz
MAINTAINERCLEANFILES = \
$(srcdir)/aclocal.m4 \

262
NEWS
View File

@ -1,3 +1,263 @@
0MQ version 4.0.5 stable, released on 2014/10/14
================================================
* Fixed #1191; CURVE mechanism does not verify short term nonces.
* Fixed #1190; stream_engine is vulnerable to downgrade attacks.
* Fixed #1088; assertion failure for WSAENOTSOCK on Windows.
* Fixed #1015; race condition while connecting inproc sockets.
* Fixed #994; bump so library number to 4.0.0
* Fixed #939, assertion failed: !more (fq.cpp:99) after many ZAP requests.
* Fixed #872; lost first part of message over inproc://.
* Fixed #797, keep-alive on Windows.
0MQ version 4.0.4 stable, released on 2014/03/10
================================================
Bug Fixes
---------
* Fixed #909; out of tree build issue on Linux.
* Fixed #888; hangs on terminate when inproc connected but never bound.
* Fixed #868; assertion failure at ip.cpp:137 when using port scanner.
* Fixed #818; fix timestamp counter on s390/s390x.
* Fixed #817; only export zmq_* symbols.
* Fixed #797; fixed setting TCP keepalive on Windows.
* Fixed #775; compile error on Windows.
* Fixed #763; when talking to a ZMTP v1 peer (libzmq 2.2), a socket would
send an extra identity frame at the start of the connection.
* Fixed LIBZMQ-576 - Crash closing a socket after zmq_msg_send returns
EAGAIN (reverts LIBZMQ-497)
* Fixed LIBZMQ-584; subscription filters getting lost on reconnection.
0MQ version 4.0.3 stable, released on 2013/11/24
================================================
Bug Fixes
---------
* Fixed test_many_sockets case, which failed when process socket limit
was 1024.
0MQ version 4.0.2 stable, released on 2013/11/24
================================================
Bug Fixes
---------
* Fixed LIBZMQ-583 - improved low-res timer for Windows
* Fixed LIBZMQ-578 - z85_decode was extremely slow
* Fixed LIBZMQ-577 - fault in man pages.
* Fixed LIBZMQ-574 - assertion failure when ran out of system file handles
* Fixed LIBZMQ-571 - test_stream failing in some cases
* Fixed LIBZMQ-569 - Socket server crashes with random client data and when
talking to 2.2 versions
* Fixed LIBZMQ-39 - Bad file descriptor during shutdown
* Pulled expected failing test_linger.cpp from release
* Reduced pause time in tests to allow "make check" to run faster
0MQ version 4.0.1 stable, released on 2013/10/08
================================================
Changes
-------
* Updated CURVE mechanism to track revised RFC 27 (INITIATE vouch).
The INITIATE command vouch box is Box[C',S](C->S') instead of
Box[C'](C->S), to reduce the risk of client impersonation, as per
https://codesinchaos.wordpress.com/2012/09/09/curvecp-1/.
* Fixed LIBZMQ-567, adding abstract namespaces for IPC sockets on Linux.
Converts an initial strudel or "at sign" (@) in the Unix socket path to
a NULL character ('\0') indicating that the socket uses the abstract
namespace instead of the filesystem namespace. For instance, binding a
socket to 'ipc://@/tmp/tester' will not create a file associated with
the socket whereas binding to 'ipc:///tmp/tester' will create the file
/tmp/tester. See issue 567 for more information.
* Added zmq_z85_encode and zmq_z85_decode to core libzmq API.
* Added zmq_curve_keypair to core libzmq API.
* Bumped library ABI version to 4:0:1.
Bug fixes
---------
* Fixed some build/test errors on OS/X + Clang++.
* Fixed LIBZMQ-565, typo in code.
* Fixed LIBZMQ-566, dealer-to-router connections sometimes failing.
* Fixed builds for AIX, MSVC 2008, OS/X with clang++, Solaris.
* Improved CURVE handshake error handling.
0MQ version 4.0.0 (RC1), released on 2013/09/20
===============================================
Major changes
-------------
* New wire level protocol, ZMTP/3.0, see http://rfc.zeromq.org/spec:23.
Does not yet implement the SUBSCRIBE, CANCEL, PING, and PONG commands.
* New security framework, from plain user+password to strong encryption,
see section below. See http://hintjens.com/blog:49 for a tutorial.
* New ZMQ_STREAM socket type for working as a TCP client or server. See:
tests/test_stream.cpp.
Improvements
------------
* You can now connect to an inproc:// endpoint that does not already
exist. This means inproc:// no longer needs careful set-up, but it may
break code that relied on the old behaviour. See:
tests/test_inproc_connect.cpp.
* Libzmq now checks socket types at connection time, so that trying to
connect a 'wrong' socket type will fail.
* New zmq_ctx_shutdown API method will shutdown a context and send ETERM
to blocking calls, without blocking. Use zmq_ctx_term to finalise the
process.
* The regression test suite has been significantly extended and improved.
* Contexts can now be terminated in forked child processes. See:
tests/test_fork.cpp.
* zmq_disconnect now respects the linger setting on sockets.
* New zmq_send_const API method to send constant data (without copying).
See: tests/test_inproc_connect.cpp.
* Added CMake support for static libraries.
* Added test cases for socket semantics as defined in RFCs 28, 29, 30, 31.
See: tests/test_spec_*.cpp.
* New socket option, ZMQ_PROBE_ROUTER triggers an empty message on connect.
See: tests/test_probe_router.cpp.
* New socket option, ZMQ_REQ_CORRELATE allows for correlation of replies
from a REP socket. See: tests/test_req_correlate.cpp.
* New socket option, ZMQ_REQ_RELAXED, lets you disable the state machine
on a REQ socket, so you can send multiple requests without waiting for
replies, and without getting an EFSM error. See:
tests/test_req_relaxed.cpp.
* New socket option, ZMQ_CONFLATE restricts the outgoing and incoming
socket buffers to a single message. See: tests/test_conflate.cpp.
Deprecated Options
------------------
* ZMQ_IPV4ONLY deprecated and renamed to ZMQ_IPV6 so that options are
consistently "off" by default.
* ZMQ_DELAY_ATTACH_ON_CONNECT deprecated, and renamed to ZMQ_IMMEDIATE.
See: tests/test_immediate.cpp.
Security Framework
------------------
Based on new ZMTP wire level protocol that negotiates a security
"mechanism" between client and server before exchanging any other data.
Security mechanisms are extensible. ZMTP defines three by default:
* NULL - classic ZeroMQ, with no authentication. See
http://rfc.zeromq.org/spec:23.
* PLAIN - plain-text username + password authentication. See
http://rfc.zeromq.org/spec:24.
* CURVE - secure authentication and encryption based on elliptic curve
cryptography, using the Curve25519 algorithm from Daniel Bernstein and
based on CurveCP's security handshake. See http://rfc.zeromq.org/spec:25,
http://rfc.zeromq.org/spec:26, and http://curvecp.org.
Authentication is done by pluggable "authenticators" that connect to libzmq
over an inproc endpoint, see http://rfc.zeromq.org/spec:27.
Socket options to configure PLAIN security on client or server:
* ZMQ_PLAIN_SERVER, ZMQ_PLAIN_USERNAME, ZMQ_PLAIN_PASSWORD. See
tests/test_security_plain.
Socket options to configure CURVE security on client or server:
* ZMQ_CURVE_SERVER, ZMQ_CURVE_PUBLICKEY, ZMQ_CURVE_SECRETKEY,
ZMQ_CURVE_SERVERKEY. See tests/test_security_curve.cpp.
Socket options to configure "domain" for ZAP handler:
* ZMQ_ZAP_DOMAIN, see tests/test_security_null.cpp.
Support for encoding/decoding CURVE binary keys to ASCII:
* zmq_z85_encode, zmq_z85_decode.
Other issues addressed in this release
--------------------------------------
* LIBZMQ-525 Multipart upstreaming from XSUB to XPUB
0MQ version 3.2.4 stable, released on 2013/09/20
================================================
* LIBZMQ-84 (Windows) Assertion failed: Address already in use at signaler.cpp:80
* LIBZMQ-456 ZMQ_XPUB_VERBOSE does not propagate in a tree of XPUB/XSUB devices
* LIBZMQ-532 (Windows) critical section not released on error
* LIBZMQ-569 Detect OpenPGM 5.2 system library
* LIBZMQ-563 Subscribers sometimes stopped receiving messages (aka LIBZMQ-541)
* LIBZMQ-XXX Added support for Travis Continuous Integration
* LIBZMQ-XXX Several improvements to MSVC support
0MQ version 3.2.3 stable, released on 2013/05/02
================================================
Issues addressed in this release
--------------------------------
* LIBZMQ-526 Assertion failure "Invalid argument (tcp_connecter.cpp:285)"
* LIBZMQ-446 Setting the DSCP bits by default causes CAP_NET_ADMIN error
* LIBZMQ-496 Crash on heavy socket opening/closing: Device or resource busy (mutex.hpp:90)
* LIBZMQ-462 test_connect_delay fails at test_connect_delay.cpp:80
* LIBZMQ-497 Messages getting dropped
* LIBZMQ-488 signaler.cpp leaks the win32 Event Handle
* LIBZMQ-476 zmq_disconnect has no effect for inproc sockets
* LIBZMQ-475 zmq_disconnect does not sent unsubscribe messages
0MQ version 3.2.2 stable, released on 2012/11/23
================================================
@ -13,7 +273,6 @@ Issues addressed in this release
* LIBZMQ-450 lt-test_monitor: fails with assertion at test_monitor.cpp:81
* LIBZMQ-451 ZMQ_ROUTER_MANDATORY blocks forever
* LIBZMQ-452 test_connect_delay.cpp:175:12: error: 'sleep' was not declared in this scope
* LIBZMQ-456 ZMQ_XPUB_VERBOSE does not propagate in a tree of XPUB/XSUB devices
* LIBZMQ-458 lt-test_router_mandatory fails with assertion at test_router_mandatory.cpp:53
* LIBZMQ-459 Assertion failed: encoder (stream_engine.cpp:266
* LIBZMQ-464 PUB socket with HWM set leaks memory
@ -21,6 +280,7 @@ Issues addressed in this release
* LIBZMQ-468 ZMQ_XPUB_VERBOSE & unsubscribe
* LIBZMQ-472 Segfault in zmq_poll in REQ to ROUTER dialog
0MQ version 3.2.1 (RC2), released on 2012/10/15
===============================================

View File

@ -11,6 +11,12 @@ abstraction of asynchronous message queues, multiple messaging patterns,
message filtering (subscriptions), seamless access to multiple transport
protocols and more.
## Stable Fork
This repository is used for making stable releases. Please do not send
pull requests here unless they are specifically and only for this fork.
Rather, send them to libzmq/master. Issues with test cases may be back
ported to this repository by its maintainers.
## Building and installation

View File

@ -8,7 +8,7 @@ URL: http://www.zeromq.org/
Source: http://download.zeromq.org/%{name}-%{version}.tar.gz
Prefix: %{_prefix}
Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root
BuildRequires: gcc, make, gcc-c++, libstdc++-devel
BuildRequires: gcc, make, gcc-c++, libstdc++-devel, asciidoc, xmlto
Requires: libstdc++
%if 0%{?rhel}
@ -87,11 +87,14 @@ This package contains ZeroMQ related development libraries and header files.
%defattr(-,root,root,-)
# docs in the main package
%doc AUTHORS ChangeLog COPYING COPYING.LESSER NEWS README
%doc AUTHORS ChangeLog COPYING COPYING.LESSER NEWS README.md
# binaries
%{_bindir}/curve_keygen
# libraries
%{_libdir}/libzmq.so.3
%{_libdir}/libzmq.so.3.0.0
%{_libdir}/libzmq.so.4
%{_libdir}/libzmq.so.4.0.0
%{_mandir}/man7/zmq.7.gz
@ -144,11 +147,19 @@ This package contains ZeroMQ related development libraries and header files.
%{_mandir}/man3/zmq_term.3.gz
%{_mandir}/man3/zmq_version.3.gz
%{_mandir}/man3/zmq_unbind.3.gz
%{_mandir}/man3/zmq_curve_keypair.3.gz
%{_mandir}/man3/zmq_proxy_steerable.3.gz
%{_mandir}/man3/zmq_send_const.3.gz
%{_mandir}/man3/zmq_z85_decode.3.gz
%{_mandir}/man3/zmq_z85_encode.3.gz
%{_mandir}/man7/zmq_epgm.7.gz
%{_mandir}/man7/zmq_inproc.7.gz
%{_mandir}/man7/zmq_ipc.7.gz
%{_mandir}/man7/zmq_pgm.7.gz
%{_mandir}/man7/zmq_tcp.7.gz
%{_mandir}/man7/zmq_null.7.gz
%{_mandir}/man7/zmq_plain.7.gz
%{_mandir}/man7/zmq_curve.7.gz
%changelog
* Mon Nov 26 2012 Justin Cook <jhcook@gmail.com> 3.2.2

426
builds/zos/README.md Normal file
View File

@ -0,0 +1,426 @@
# ZeroMQ on z/OS UNIX System Services
ZeroMQ has been successfully built on z/OS, using [z/OS UNIX System
Services](http://www-03.ibm.com/systems/z/os/zos/features/unix/),
a certified UNIX environment for the [IBM
z-series](http://www-03.ibm.com/systems/z/). The build is possible
with the shell scripts in this directory, as described below.
Tested build combinations:
* ZeroMQ 4.0.4, using IBM XL C/C++ compiler, as XPLINK in ILP32 mode
* ZeroMQ 4.0.4, using IBM XL C/C++ compiler, as XPLINK in LP64 mode
Other combinations are likely to work, possibly with minor changes,
but have not been tested. Both static library and DLL modes have been
tested.
There are some minor limitations (detailed below), but all core
functionality tests run successfully.
## Quickstart: building ZeroMQ on z/OS UNIX System Services
Assuming [z/OS UNIX System
Services](http://www-03.ibm.com/systems/z/os/zos/features/unix/) is
installed, and the [z/OS XL C/C++
compiler suite](http://www-03.ibm.com/software/products/en/czos) is
installed, ZeroMQ can be built as follows:
* Download and extract ZeroMQ tar file
* Ensure contents of this directory are present at `builds/zos`
within that extracted diretory (eg, `zeromq-VERSION/builds/zos/`;
copy these files in, if not already present, and make sure the
shell scripts are executable)
* (Optional) set ZCXXFLAGS for additional compile flags (see below)
* Build `libzmq.a` static library and `libzmq.so` dynamic
library, with:
cd zeromq-VERSION
builds/zos/makelibzmq
or to skip the `libzmq.so` dynamic library (only building `libzmq.a`):
cd zeromq-VERSION
BUILD_DLL=false
export BUILD_DLL
builds/zos/makelibzmq
* (Optional, but recommended) build and run the core tests with:
cd zeromq-VERSION
builds/zos/maketests
builds/zos/runtests
* To remove built files, to start again (eg, rebuild with different
compile/link flags):
cd zeromq-VERSION
builds/zos/makeclean
There are details on specifying alternative compilation flags below.
## Quickstart: using ZeroMQ on z/OS UNIX System Services
### Static linking
Install `include/*.h` somewhere on your compiler include path.
Install `src/libzmq.a` somewhere on your library search path.
Compile and link application with:
c++ -Wc,xplink -Wl,xplink ... -+ -o myprog myprog.cpp -lzmq
Run with:
./myprog
### Dynamic linking
Install `include/*.h` somewhere on your compiler include path.
Install `src/libzmq.so` somewhere on your LIBPATH.
Install `src/libzmq.x` somewhere you can reference for import linking.
Compile and link application:
c++ -Wc,xplink -Wc,dll ... -+ -c -o myprog.o myprog.cpp
c++ -Wl,xplink -o myprog myprog.o /PATH/TO/libzmq.x
Run with:
LIBPATH=/DIR/OF/LIBZMQ.SO:/lib:/usr/lib:... # if not in default path
export LIBPATH
./myprog
## ZeroMQ on z/OS UNIX System Services: Application considerations
z/0S UNIX System Services does not provide a way to block the
[`SIGPIPE` signal being generated when a thread writes to a closed socket](http://pic.dhe.ibm.com/infocenter/zvm/v6r2/index.jsp?topic=%2Fcom.ibm.zos.r12.cbcpx01%2Fcbcpg1b0287.htm)
(compare with other platforms that support the `SO_NOSIGPIPE` socket
option, and/or the `MSG_NOSIGNAL` flag on `send()`; z/OS UNIX System
Services supports neither).
As a result, applications using ZeroMQ on z/OS UNIX System Services
have to expect to encounter `SIGPIPE` at various times during the use
of the library, if sockets are unexpectedly disconnected. Normally
`SIGPIPE` will terminate the application.
A simple solution, if `SIGPIPE` is not required for normal operation
of the application (eg, it is not part of a unix pipeline, the
traditional use of `SIGPIPE`), is to set `SIGPIPE` to be ignored
with code like:
#include <signal.h>
...
signal(SIGPIPE, SIG_IGN);
near the start of the application (eg, before initialising the ZeroMQ
library).
If `SIGPIPE` is required for normal operation it is recommended that
the application install a signal handler that flags the signal was
received, and allows the application main loop to determine if it
was received for one of its own file descriptors -- and ignores it if it
none of the applications own file descriptors seems to have changed.
Linking to the `libzmq.a` static library will pull in substantially
all of the library code, which will add about 4MB to the application
size (per executable statically linked with ZeroMQ). If this is a
significant consideration, use of the DLL version is recommended.
See also ZeroMQ test status on z/OS UNIX System Services below
for other caveats.
## Setting other compilation flags
### Optimisation
To build with optimisation:
* set `ZCXXFLAGS` to "`-O2`" before starting build process above
### Full debugging symbols
To build with debugging symbols:
* set `ZCXXFLAGS` to "`-g`" before starting build process above
### 64-bit mode (LP64/amode=64)
To build in 64-bit mode:
The default build is
[ILP32](http://publib.boulder.ibm.com/infocenter/zvm/v6r1/index.jsp?topic=/com.ibm.zos.r9.cbcux01/lp64cop.htm),
the default for the IBM XL C/C++ compiler. To build in LP64 mode
(64-bit):
* set `ZCXXFLAGS` to "`-Wc,lp64 -Wl,lp64`" before starting build
(64-bit mode can be combined with optimisation or debug symbols.)
### Combining compilation flags
Other build flags can be used in `ZXCCFLAGS` if desired. Beware that
they are passed through (Bourne) shell expansion, and passed to both
the compile and link stages; some experimentation of argument quoting
may be required (and arguments requiring parenthesis are particularly
complicated).
## ZeroMQ test status on z/OS UNIX System Services
As of 2014-07-22, 41 of the 43 tests in the core ZeroMQ test suite
pass. There are two tests that are expected to fail:
0. `test_abstract_ipc`: tests Linux-specific IPC functions, and is
expected to fail on non-Linux platforms.
0. `test_fork`: tests ability to use ZeroMQ both before *and* after
fork (and before exec()); this relies on the ability to use
pthreads both before *and* after fork. On z/OS (and some other
UNIX compliant platforms) functions like `pthreads_create` (used
by ZeroMQ) cannot be used after fork and before exec; on z/OS the
call after fork fails with `ELEMULTITHREADFORK` (errno=257) if
ZeroMQ was also used before fork. (On z/OS it appears possible
to use z/OS *after* fork, *providing* it has not been used before
fork -- the problem is the two separate initialisations of the
threading library, before and after fork, attempting to mix
together.) In practice this is unlikely to affect many real-world
programs -- most programs use threads or fork without exec, but
not both.
These two "expected to fail" tests are listed as XFAIL_TESTS, and
`runtests` will still consider the test run successful when they fail
as expected.
In addition `test_security_curve` does not do any meaningful testing,
as a result of the CURVE support not being compiled in; it requires
[`libsodium`](http://doc.libsodium.org/), which has not been
ported to z/OS UNIX System Services yet.
Multicast (via `libpgm`) is also not ported or compiled in.
## ZeroMQ on z/OS UNIX System Services: Library portability notes
### *.cpp
The source code in ZeroMQ is a combination of a C++ core library
(in `*.cpp` and `*.hpp` files), and a C wrapper (also in `*.cpp`
files). It is all compiled with the C++ compiler. The IBM XL C/C++
complier (at least the version used for initial porting) insists
that C++ source be in `*.C` files (note capital C). To work around
this issue the compile flag `-+` is used (specified in the `zc++`
compiler wrapper), which tells the compiler the file should be
considered C++ despite the file extension.
### XPLINK
The library (and tests) are built in
[XPLINK](http://www.redbooks.ibm.com/abstracts/sg245991.html) mode
with the flags `-Wc,xplink -Wl,xplink` (specified in the `zc++`
compiler wrapper). This is [recommended by IBM for C++
code](http://publib.boulder.ibm.com/infocenter/zvm/v5r4/index.jsp?topic=/com.ibm.zos.r9.ceea200/xplrunt.htm)
due to the small functions. (Amongst other things, using XPLINK
enables function calls with some arguments passed in registers.)
### long long
ZeroMQ makes use of `uint64_t` (which is `unsigned long long` in ILP32
mode). To enable this the compile flag `-Wc,lang(longlong)` is passed
to enable `long long`. This is passed from the `zc++` compiler wrapper
in order to be able to specifically quote the argument to protect the
parentheses from shell expansion.
### BSD-style sockets, with IPv6 support
ZeroMQ uses BSD-style socket handling, with extensions to support IPv6.
BSD-style sockets were merged into SysV-derived UNIX at least a decade
ago, and are required as part of the X/Open Portability Guide at least
as of XPG 4.2. To access this functionality two feature macros are
defined:
_XOPEN_SOURCE_EXTENDED=1
_OPEN_SYS_SOCK_IPV6
The first enables the XPG 4.2 features (including functionality like
`getsockname()`), and the latter exposes IPv6 specific functionality
like `sa_family_t`. These flags are defined in the `cxxall` script.
(The traditional BSD-sockets API, exposed with `_OE_SOCKETS` cannot
be used because it does not support functions like `getsockname()`,
nor does it support IPv6 -- and the API definitions prevent compiling
in LP64 mode due to assumptions about long being 32 bits. Using
`_XOPEN_SOURCE_EXTENDED=1` avoids all these problems.)
### pthreads
ZeroMQ uses the pthreads library to create additional threads to handle
background communication without blocking the main application. This
functionaity is enabled on z/OS UNIX System Services by defining:
_OPEN_THREADS=3
which is done in the `cxxall` script. (The "3" value exposes later
pthreads functionality like `pthread_atfork`, although ZeroMQ does not
currently use all these features.)
## `platform.hpp` on z/OS UNIX System Services
The build (described above) on z/OS UNIX System Services uses a static
pre-built `platform.hpp` file. (By default `src/platform.hpp` is
dynamically generated as a result of running the `./configure` script.)
The master version of this is in `builds/zos/platform.hpp`.
The pre-built file is used because z/OS does not have the GNU auto tools
(`automake`, `autoconf`, `libtool`, etc) installed, and particularly the
libtool replacement does not work properly with the IBM XL C/C++
compiler.
The `./configure` script (only supplied in the tarballs); built with
`automake` and `autoconf` on another platform), with one small edit,
was used to generate the z/OS `platform.hpp` and then two small changes
(described below) were made by hand to the generated `platform.hpp`.
To be able to run the ./configure script to completion (in tcsh
syntax):
* Edit `./configure` and add:
openedition)
;;
immediately before the line:
as_fn_error $? "unsupported system: ${host_os}." "$LINENO" 5
(somewhere around 17637). This avoids the configure script giving
up early because `openedition` is not recognised.
* set `CXX` to point that the full path to the `builds/zos/zc++` wrapper, eg
setenv CXX "/u/0mq/zeromq-4.0.4/builds/zos/zc++"
* set `CPPFLAGS` to for the feature macros required, eg:
setenv CPPFLAGS "-D_XOPEN_SOURCE_EXTENDED=1 -D_OPEN_THREADS=3 -D_OPEN_SYS_SOCK_IPV6"
* set `CXXFLAGS` to enable XPLINK:
setenv CXXFLAGS "-Wc,xplink -Wl,xplink -+"
* run configure script with `--disable-eventfd` (`sys/eventfd.h` does
not exist, but the test for its existance has a false positive on
z/OS UNIX System Services, apparently due to the way the `c++`
compiler wrapper passes errors back from the IBM XL C/C++ compiler), viz:
./configure --disable-eventfd
All going well several Makefiles, and `src/platform.hpp` should be
produced. Two additional changes are required to `src/platform.hpp`
which can be appended to the end:
/* ---- Special case for z/OS Unix Services: openedition ---- */
#include <pthread.h>
#ifndef NI_MAXHOST
#define NI_MAXHOST 1025
#endif
(many includes require pthreads-related methods or data structures to
be defined, but not all of them include `pthread.h`, and the value
`NI_MAXHOST` is not defined on z/OS UNIX System Services -- the 1025
value is the conventional value on other platforms).
Having done this the Makefiles can be used to compile individual files
if desired, eg:
cd src
make zmq.o
but note:
* IBM Make will warn of duplicate prerequisites on *every* run of
`make`, and both the generated `src/Makefile` and `tests/Makefile`
have several duplicates. (For `src/Makefile` edit
`libzmq_la_SOURCES` to remove the duplicates.)
* IBM Make does not understand the `@` prefix (eg, `@echo`) as a way
to avoid echoing the command, resulting in an error and the command
being echoed anyway.
* Many of the make targets result in GNU auto tools (`aclocal`, etc)
being invoked, which are likely to fail, and most of the
library-related targets will invoke `libtool` which will cause
compile failures (due to differences in expected arguments).
However running `./configure` to regenerate `src/platform.hpp` may
be useful for later versions of ZeroMQ which add more feature tests.
## Transferring from GitHub to z/OS UNIX System Services
The process of transferring files from GitHub to z/OS UNIX System
Services is somewhat convoluted because:
* There is not a port of git for z/OS UNIX System Services; and
* z/OS uses the EBCDIC (IBM-1047) character set rather than the
ASCII/ISO-8859-1 character set used by the ZeroMQ source code
on GitHub
A workable transfer process is:
* On an ASCII/ISO-8859-1/UTF-8 system with `git` (eg, a Linux system):
git clone https://github.com/zeromq/libzmq.git
git archive --prefix=libzmq-git/ -o /var/tmp/libzmq-git.tar master
* On a ASCII/ISO-8859-1/UTF-8 system with `tar`, and `pax`, and
optionally the GNU auto tools (eg, the same Linux system):
mkdir /var/tmp/zos
cd /var/tmp/zos
tar -xpf /var/tmp/libzmq-git.tar
cd libzmq-git
./autogen.sh # Optional: to be able to run ./configure
cd ..
pax -wf /var/tmp/libzmq-git.pax libzmq-git
compress libzmq-git.pax # If available, reduce transfer size
* Transfer the resulting file (`libzmq-git.pax` or `libzmq-git.pax.Z`)
to the z/OS UNIX System Services system. If using FTP be sure to
transfer the file in `bin` (binary/Image) mode to avoid corruption.
* On the z/OS UNIX System Services system, unpack the `pax` file and
convert all the files to EBCDIC with:
pax -o from=iso8859-1 -pp -rvf libzmq-git-2014-07-23.pax
or if the file was compressed:
pax -o from=iso8859-1 -pp -rvzf libzmq-git-2014-07-23.pax.Z
The result should be a `libzmq-git` directory with the source in
EBCDIC format, on the z/OS UNIX System Services system ready to start
building.
See also the [`pax` man
page](http://pic.dhe.ibm.com/infocenter/zos/v1r13/index.jsp?topic=%2Fcom.ibm.zos.r13.bpxa500%2Fr4paxsh.htm),
some [`pax` conversion
examples](http://pic.dhe.ibm.com/infocenter/zos/v1r13/index.jsp?topic=%2Fcom.ibm.zos.r13.bpxa400%2Fbpxza4c0291.htm),
and [IBM's advice on ASCII to EBCDIC conversion
options](http://www-03.ibm.com/systems/z/os/zos/features/unix/bpxa1p03.html)

62
builds/zos/cxxall Executable file
View File

@ -0,0 +1,62 @@
#! /bin/sh
# Attempt to compile all *.cpp files in the current directory, that are
# not already compiled. Uses zc++ wrapper around C++ compiler, to add
# additional compile arguments.
#
# Written by Ewen McNeill <ewen@imatix.com>, 2014-07-19
# Updated by Ewen McNeill <ewen@imatix.com>, 2014-07-22
#---------------------------------------------------------------------------
VERBOSE="${VERBOSE:-}" # Set to non-empty for already done status
export VERBOSE
# Locate compiler wrapper
BIN_DIR=$(dirname $0)
if [ -z "${BIN_DIR}" ]; then BIN_DIR="."; fi
case "${BIN_DIR}" in
.) BIN_DIR="$(pwd)"; ;;
/*) ;;
*) BIN_DIR="$(pwd)/${BIN_DIR}"; ;;
esac
ZCXX="${BIN_DIR}/zc++"
# Determine compile flags
CPPFLAGS="-D_XOPEN_SOURCE_EXTENDED=1 -D_OPEN_THREADS=3 -D_OPEN_SYS_SOCK_IPV6"
CXXFLAGS="-DHAVE_CONFIG_H -D_REENTRANT -D_THREAD_SAFE -DZMQ_FORCE_POLL"
case $(pwd) in
*src) CXXFLAGS="${CXXFLAGS} -I."
;;
*tests) CXXFLAGS="${CXXFLAGS} -I. -I../src -I../include"
;;
*) echo "Currently only builds in src/ and tests/" >&2
exit 1
;;
esac
skip() {
SRC="$1"
OBJ="$2"
if [ -n "${VERBOSE}" ]; then
echo " ${SRC} compiled already"
fi
}
compile() {
SRC="$1"
OBJ="$2"
echo "CXX ${SRC}"
"${ZCXX}" ${CXXFLAGS} ${CPPFLAGS} -+ -c -o "${OBJ}" "${SRC}"
}
for SRC in *.cpp; do
OBJ=$(echo $SRC | sed 's/\.cpp/.o/;')
if [ -f "${OBJ}" ]; then
if [ "${OBJ}" -nt "${SRC}" ]; then
skip "${SRC}" "${OBJ}"
else
compile "${SRC}" "${OBJ}"
fi
else
compile "${SRC}" "${OBJ}"
fi
done

36
builds/zos/makeclean Executable file
View File

@ -0,0 +1,36 @@
#! /bin/sh
# Remove built object files and test executables
#
# Written by Ewen McNeill <ewen@imatix.com>, 2014-07-22
# Updated by Ewen McNeill <ewen@imatix.com>, 2014-07-24
#---------------------------------------------------------------------------
set -e # Stop on errors
# Figure out where we are
BIN_DIR=$(dirname $0)
if [ -z "${BIN_DIR}" ]; then BIN_DIR="."; fi
case "${BIN_DIR}" in
.) BIN_DIR="$(pwd)"; ;;
/*) ;;
*) BIN_DIR="$(pwd)/${BIN_DIR}"; ;;
esac
# Locate top of source tree, assuming we're in builds/zos
TOP="${BIN_DIR}/../.."
SRC="${TOP}/src"
TESTS="${TOP}/tests"
# Remove object/library files
echo "Removing libzmq built files"
(cd "${SRC}" && rm -f *.o *.a *.dbg *.x *.so libzmq)
# Remove test object files
echo "Removing libzmq tests"
(cd "${TESTS}" && rm -f *.o *.dbg)
(cd "${TESTS}";
EXES=$(ls test_* | grep -v "\.")
if [ -n "${EXES}" ]; then
rm ${EXES}
fi
)

54
builds/zos/makelibzmq Executable file
View File

@ -0,0 +1,54 @@
#! /bin/sh
# Build libzmq.a static library and libzmq.so dynamic library
#
# Usage: makelibzmq
# BUILD_DLL=false makelibzmq # Skip building DLL
#
# NOTE: We do a single compile run for both static and dynamic libraries
# which results in the static library having -Wc,exportall compiled objects;
# in practice this doesn't seem to cause a problem beyond using some extra
# space (around 10%).
#
# Written by Ewen McNeill <ewen@imatix.com>, 2014-07-21
# Updated by Ewen McNeill <ewen@imatix.com>, 2014-07-22
#---------------------------------------------------------------------------
set -e # Stop on errors
BUILD_DLL="${BUILD_DLL:-true}" # Build DLL by default
# Figure out where we are
BIN_DIR=$(dirname $0)
if [ -z "${BIN_DIR}" ]; then BIN_DIR="."; fi
case "${BIN_DIR}" in
.) BIN_DIR="$(pwd)"; ;;
/*) ;;
*) BIN_DIR="$(pwd)/${BIN_DIR}"; ;;
esac
ZCXX="${BIN_DIR}/zc++"
# Locate top of source tree, assuming we're in builds/zos
TOP="${BIN_DIR}/../.."
SRC="${TOP}/src"
# Install pre-generated platform.hpp
cp -p "${BIN_DIR}/platform.hpp" "${SRC}/platform.hpp"
# Compile all the source (optionally ready for a DLL)
if [ "${BUILD_DLL}" = "true" ]; then
ZCXXFLAGS="${ZCXXFLAGS} -Wc,exportall"
export ZCXXFLAGS
#echo "Building DLL with ${ZCXXFLAGS}"
fi
cd "${SRC}"
"${BIN_DIR}/cxxall"
# Make static library
ar r libzmq.a *.o
# Optionally Make dynamic library
if [ "${BUILD_DLL}" = "true" ]; then
#echo "Building libzmq.so DLL"
"${ZCXX}" -Wl,DLL -o libzmq.so *.o
fi

102
builds/zos/maketests Executable file
View File

@ -0,0 +1,102 @@
#! /bin/sh
# Build tests/* executables; assumes that libzmq.a or libzmq.so/libzmq.x
# is already built
#
# If libzmq.so and libzmq.x exist, then dynamic linking is used, otherwise
# static linking is used.
#
# Written by Ewen McNeill <ewen@imatix.com>, 2014-07-21
# Updated by Ewen McNeill <ewen@imatix.com>, 2014-07-22
#---------------------------------------------------------------------------
set -e # Stop on errors
VERBOSE="${VERBOSE:-}" # Set to non-empty for already done status
export VERBOSE
# Figure out where we are
BIN_DIR=$(dirname $0)
if [ -z "${BIN_DIR}" ]; then BIN_DIR="."; fi
case "${BIN_DIR}" in
.) BIN_DIR="$(pwd)"; ;;
/*) ;;
*) BIN_DIR="$(pwd)/${BIN_DIR}"; ;;
esac
# Locate compiler wrapper
ZCXX="${BIN_DIR}/zc++"
# Locate top of source tree, assuming we're in builds/zos
TOP="${BIN_DIR}/../.."
SRC="${TOP}/src"
TESTS="${TOP}/tests"
# Figure out how we are going to link to ZMQ
LINK_TYPE=unknown
if [ -f "${SRC}/platform.hpp" -a -f "${SRC}/libzmq.so" -a -f "${SRC}/libzmq.x" ]; then
LINK_TYPE=dynamic
elif [ -f "${SRC}/platform.hpp" -a -f "${SRC}/libzmq.a" ]; then
LINK_TYPE=static
else
echo "Error: run makezmqlib to build libzmq.a and/or libzmq.so/libzmq.x first" >&2
exit 1
fi
# Copy in replacement test with timeout, if main version is not already
# up to date
#
if [ -f "${TESTS}/test_fork.cpp" ] &&
grep "TIMEOUT" "${TESTS}/test_fork.cpp" >/dev/null 2>&1; then
: # Already copied in
else
echo "Updating test_fork.cpp to version with master timeout"
cp -p "${BIN_DIR}/test_fork.cpp" "${TESTS}/test_fork.cpp"
fi
# Compile all the source
if [ "${LINK_TYPE}" = "dynamic" ]; then
ZCXXFLAGS="${ZCXXFLAGS} -Wc,DLL"
export ZXCCFLAGS
echo "Building tests to use DLL: ${ZCXXFLAGS}"
fi
cd "${TESTS}"
"${BIN_DIR}/cxxall"
# Link all the executables that are not already linked
skip() {
OBJ="$1"
EXE="$2"
if [ -n "${VERBOSE}" ]; then
echo "${OBJ} linked to ${EXE}"
fi
}
link() {
OBJ="$1"
EXE="$2"
echo " LD ${EXE}"
case "${LINK_TYPE}" in
static) "${ZCXX}" -L ../src -o "${EXE}" "${OBJ}" -lzmq
;;
dynamic) "${ZCXX}" -o "${EXE}" "${OBJ}" ../src/libzmq.x
;;
*) echo "Do not know how to do ${LINK_TYPE} linking!" 2>&1
exit 1
;;
esac
}
for OBJ in *.o; do
EXE=$(echo "${OBJ}" | sed 's/\.o//;')
if [ -f "${EXE}" ]; then
if [ "${EXE}" -nt "${OBJ}" ]; then
skip "${OBJ}" "${EXE}"
else
link "${OBJ}" "${EXE}"
fi
else
link "${OBJ}" "${EXE}"
fi
done

277
builds/zos/platform.hpp Normal file
View File

@ -0,0 +1,277 @@
/* src/platform.hpp. Generated from platform.hpp.in by configure. */
/* src/platform.hpp.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the <alloca.h> header file. */
/* #undef HAVE_ALLOCA_H */
/* Define to 1 if you have the <arpa/inet.h> header file. */
#define HAVE_ARPA_INET_H 1
/* Define to 1 if you have the `clock_gettime' function. */
/* #undef HAVE_CLOCK_GETTIME */
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define to 1 if you have the <errno.h> header file. */
#define HAVE_ERRNO_H 1
/* Define to 1 if you have the `fork' function. */
#define HAVE_FORK 1
/* Define to 1 if you have the `freeifaddrs' function. */
#define HAVE_FREEIFADDRS 1
/* Define to 1 if you have the `gethrtime' function. */
/* #undef HAVE_GETHRTIME */
/* Define to 1 if you have the `getifaddrs' function. */
#define HAVE_GETIFADDRS 1
/* Define to 1 if you have the `gettimeofday' function. */
#define HAVE_GETTIMEOFDAY 1
/* Define to 1 if you have the <ifaddrs.h> header file. */
#define HAVE_IFADDRS_H 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the `iphlpapi' library (-liphlpapi). */
/* #undef HAVE_LIBIPHLPAPI */
/* Define to 1 if you have the `nsl' library (-lnsl). */
/* #undef HAVE_LIBNSL */
/* Define to 1 if you have the `pthread' library (-lpthread). */
/* #undef HAVE_LIBPTHREAD */
/* Define to 1 if you have the `rpcrt4' library (-lrpcrt4). */
/* #undef HAVE_LIBRPCRT4 */
/* Define to 1 if you have the `rt' library (-lrt). */
/* #undef HAVE_LIBRT */
/* Define to 1 if you have the `socket' library (-lsocket). */
/* #undef HAVE_LIBSOCKET */
/* Define to 1 if you have the `sodium' library (-lsodium). */
/* #undef HAVE_LIBSODIUM */
/* Define to 1 if you have the `ws2_32' library (-lws2_32). */
/* #undef HAVE_LIBWS2_32 */
/* Define to 1 if you have the <limits.h> header file. */
#define HAVE_LIMITS_H 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the `memset' function. */
#define HAVE_MEMSET 1
/* Define to 1 if you have the <netinet/in.h> header file. */
#define HAVE_NETINET_IN_H 1
/* Define to 1 if you have the <netinet/tcp.h> header file. */
#define HAVE_NETINET_TCP_H 1
/* Define to 1 if you have the `perror' function. */
#define HAVE_PERROR 1
/* Define to 1 if you have the `socket' function. */
#define HAVE_SOCKET 1
/* Define to 1 if stdbool.h conforms to C99. */
/* #undef HAVE_STDBOOL_H */
/* Define to 1 if you have the <stddef.h> header file. */
#define HAVE_STDDEF_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/eventfd.h> header file. */
/* #undef HAVE_SYS_EVENTFD_H */
/* Define to 1 if you have the <sys/socket.h> header file. */
#define HAVE_SYS_SOCKET_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/time.h> header file. */
#define HAVE_SYS_TIME_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <sys/uio.h> header file. */
#define HAVE_SYS_UIO_H 1
/* Define to 1 if you have the <time.h> header file. */
#define HAVE_TIME_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if you have the <windows.h> header file. */
/* #undef HAVE_WINDOWS_H */
/* Define to 1 if the system has the type `_Bool'. */
/* #undef HAVE__BOOL */
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#define LT_OBJDIR ".libs/"
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
#define NO_MINUS_C_MINUS_O 1
/* Name of package */
#define PACKAGE "zeromq"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "zeromq-dev@lists.zeromq.org"
/* Define to the full name of this package. */
#define PACKAGE_NAME "zeromq"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "zeromq 4.0.4"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "zeromq"
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "4.0.4"
/* Define as the return type of signal handlers (`int' or `void'). */
#define RETSIGTYPE void
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#define TIME_WITH_SYS_TIME 1
/* Version number of package */
#define VERSION "4.0.4"
/* Force to use mutexes */
/* #undef ZMQ_FORCE_MUTEXES */
/* Have AIX OS */
/* #undef ZMQ_HAVE_AIX */
/* Have Android OS */
/* #undef ZMQ_HAVE_ANDROID */
/* Have Cygwin */
/* #undef ZMQ_HAVE_CYGWIN */
/* Have eventfd extension. */
/* #undef ZMQ_HAVE_EVENTFD */
/* Have FreeBSD OS */
/* #undef ZMQ_HAVE_FREEBSD */
/* Have HPUX OS */
/* #undef ZMQ_HAVE_HPUX */
/* Have ifaddrs.h header. */
#define ZMQ_HAVE_IFADDRS 1
/* Have Linux OS */
/* #undef ZMQ_HAVE_LINUX */
/* Have MinGW32 */
/* #undef ZMQ_HAVE_MINGW32 */
/* Have NetBSD OS */
/* #undef ZMQ_HAVE_NETBSD */
/* Have OpenBSD OS */
/* #undef ZMQ_HAVE_OPENBSD */
/* Have OpenPGM extension */
/* #undef ZMQ_HAVE_OPENPGM */
/* Have DarwinOSX OS */
/* #undef ZMQ_HAVE_OSX */
/* Have QNX Neutrino OS */
/* #undef ZMQ_HAVE_QNXNTO */
/* Whether SOCK_CLOEXEC is defined and functioning. */
/* #undef ZMQ_HAVE_SOCK_CLOEXEC */
/* Have Solaris OS */
/* #undef ZMQ_HAVE_SOLARIS */
/* Whether SO_KEEPALIVE is supported. */
/* #undef ZMQ_HAVE_SO_KEEPALIVE */
/* Whether TCP_KEEPALIVE is supported. */
/* #undef ZMQ_HAVE_TCP_KEEPALIVE */
/* Whether TCP_KEEPCNT is supported. */
/* #undef ZMQ_HAVE_TCP_KEEPCNT */
/* Whether TCP_KEEPIDLE is supported. */
/* #undef ZMQ_HAVE_TCP_KEEPIDLE */
/* Whether TCP_KEEPINTVL is supported. */
/* #undef ZMQ_HAVE_TCP_KEEPINTVL */
/* Have uio.h header. */
#define ZMQ_HAVE_UIO 1
/* Have Windows OS */
/* #undef ZMQ_HAVE_WINDOWS */
/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
#define below would cause a syntax error. */
/* #undef _UINT32_T */
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
/* #undef inline */
#endif
/* Define to `unsigned int' if <sys/types.h> does not define. */
/* #undef size_t */
/* Define to `int' if <sys/types.h> does not define. */
/* #undef ssize_t */
/* Define to the type of an unsigned integer type of width exactly 32 bits if
such a type exists and the standard includes do not define it. */
/* #undef uint32_t */
/* Define to empty if the keyword `volatile' does not work. Warning: valid
code using `volatile' can become incorrect without. Disable with care. */
/* #undef volatile */
/* ---- Special case for z/OS Unix Services: openedition ---- */
#include <pthread.h>
#ifndef NI_MAXHOST
#define NI_MAXHOST 1025
#endif

216
builds/zos/runtests Executable file
View File

@ -0,0 +1,216 @@
#! /bin/sh
# Run ZeroMQ tests, in order. This is extracted from the tests/Makefile
# which won't run as-is because it relies on libtool building things, and
# thus creating various libtool files, which don't work well on z/OS
#
# noinst_PROGRAMS needs to be kept in sync with tests/Makefile.am, as it
# defines the order in which tests are run.
#
# Written by Ewen McNeill <ewen@imatix.com>, 2014-07-19
# Updated by Ewen McNeill <ewen@imatix.com>, 2014-07-22
#---------------------------------------------------------------------------
set -e # Stop if a test fails
# Test order taken from tests/Makefile.am
noinst_PROGRAMS="test_system
test_pair_inproc
test_pair_tcp
test_reqrep_inproc
test_reqrep_tcp
test_hwm
test_reqrep_device
test_sub_forward
test_invalid_rep
test_msg_flags
test_connect_resolve
test_immediate
test_last_endpoint
test_term_endpoint
test_monitor
test_router_mandatory
test_router_raw_empty
test_probe_router
test_stream
test_disconnect_inproc
test_ctx_options
test_ctx_destroy
test_security_null
test_security_plain
test_security_curve
test_iov
test_spec_req
test_spec_rep
test_spec_dealer
test_spec_router
test_spec_pushpull
test_req_correlate
test_req_relaxed
test_conflate
test_inproc_connect
test_issue_566
test_abstract_ipc
test_many_sockets
test_shutdown_stress
test_pair_ipc
test_reqrep_ipc
test_timeo
test_fork"
if [ -n "${1}" ]; then
TESTS="$*" # Run tests on command line
else
TESTS="${noinst_PROGRAMS}"
fi
# Explanation of tests expected to fail:
# test_abstract_ipc: Relies on Linux-specific IPC functionality
# test_fork: Relies on using pthreads _after_ fork, _before_ exec
#
# (Note: there _must_ be spaces either side of the tests names to match)
XFAIL_TESTS="
test_abstract_ipc
test_fork
"
verbose() {
echo "Starting: $@" >&2
"$@"
}
# Uncomment TESTS_ENVIRONMENT=verbose to see "Starting: TEST" messages
#TESTS_ENVIRONMENT=verbose
TESTS_ENVIRONMENT=
#---------------------------------------------------------------------------
# Change to tests directory if necessary
# Figure out where we are
BIN_DIR=$(dirname $0)
if [ -z "${BIN_DIR}" ]; then BIN_DIR="."; fi
case "${BIN_DIR}" in
.) BIN_DIR="$(pwd)"; ;;
/*) ;;
*) BIN_DIR="$(pwd)/${BIN_DIR}"; ;;
esac
# Locate top of source tree, assuming we're in builds/zos
TOP="${BIN_DIR}/../.."
SRCDIR="${TOP}/src"
TESTDIR="${TOP}/tests"
case "$(pwd)" in
*tests) ;;
*) echo "Changing to ${TESTDIR}"
cd "${TESTDIR}"
;;
esac
if [ -x "test_system" ]; then
:
else
echo "Run makelibzmq and maketests before runtests" >&2
exit 1
fi
# Explicitly add SRCDIR into library serach path, to make sure we
# use our just-built version
LIBPATH="${SRCDIR}:/lib:/usr/lib"
export LIBPATH
#---------------------------------------------------------------------------
# check-TESTS: target from tests/Makefile, converted from Make syntax to
# shell syntax
failed=0; all=0; xfail=0; xpass=0; skip=0;
srcdir=.; export srcdir;
list="${TESTS}";
red=""; grn=""; lgn=""; blu=""; std="";
if test -n "$list"; then
for tst in $list; do
if test -f ./$tst; then dir=./;
elif test -f $tst; then dir=;
else dir="${srcdir}/"; fi;
if ${TESTS_ENVIRONMENT} ${dir}$tst; then
all=`expr $all + 1`;
case " ${XFAIL_TESTS} " in
*"$tst"*)
xpass=`expr $xpass + 1`;
failed=`expr $failed + 1`;
col=$red; res=XPASS;
;;
*)
col=$grn; res=PASS;
;;
esac;
elif test $? -ne 77; then
all=`expr $all + 1`;
case " ${XFAIL_TESTS} " in
*"$tst"*)
xfail=`expr $xfail + 1`;
col=$lgn; res=XFAIL;
;;
*)
failed=`expr $failed + 1`;
col=$red; res=FAIL;
;;
esac;
else
skip=`expr $skip + 1`;
col=$blu; res=SKIP;
fi;
echo "${col}$res${std}: $tst";
done;
if test "$all" -eq 1; then
tests="test";
All="";
else
tests="tests";
All="All ";
fi;
if test "$failed" -eq 0; then
if test "$xfail" -eq 0; then
banner="$All$all $tests passed";
else
if test "$xfail" -eq 1; then failures=failure; else failures=failures; fi;
banner="$All$all $tests behaved as expected ($xfail expected $failures)";
fi;
else
if test "$xpass" -eq 0; then
banner="$failed of $all $tests failed";
else
if test "$xpass" -eq 1; then passes=pass; else passes=passes; fi;
banner="$failed of $all $tests did not behave as expected ($xpass unexpected $passes)";
fi;
fi;
dashes="$banner";
skipped="";
if test "$skip" -ne 0; then
if test "$skip" -eq 1; then
skipped="($skip test was not run)";
else
skipped="($skip tests were not run)";
fi;
test `echo "$skipped" | wc -c` -le `echo "$banner" | wc -c` ||
dashes="$skipped"; \
fi;
report="";
if test "$failed" -ne 0 && test -n "${PACKAGE_BUGREPORT}"; then
report="Please report to ${PACKAGE_BUGREPORT}";
test `echo "$report" | wc -c` -le `echo "$banner" | wc -c` ||
dashes="$report";
fi;
dashes=`echo "$dashes" | sed s/./=/g`;
if test "$failed" -eq 0; then
col="$grn";
else
col="$red";
fi;
echo "${col}$dashes${std}";
echo "${col}$banner${std}";
test -z "$skipped" || echo "${col}$skipped${std}";
test -z "$report" || echo "${col}$report${std}";
echo "${col}$dashes${std}";
test "$failed" -eq 0;
else :; fi

85
builds/zos/test_fork.cpp Normal file
View File

@ -0,0 +1,85 @@
/*
Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file
This file is part of 0MQ.
0MQ is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
0MQ is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include <unistd.h> // For alarm()
const char *address = "tcp://127.0.0.1:6571";
#define NUM_MESSAGES 5
#define TIMEOUT_SECS 5 // Global timeout
int main (void)
{
setup_test_environment ();
void *ctx = zmq_ctx_new ();
assert (ctx);
// Create and bind pull socket to receive messages
void *pull = zmq_socket (ctx, ZMQ_PULL);
assert (pull);
int rc = zmq_bind (pull, address);
assert (rc == 0);
int pid = fork ();
if (pid == 0) {
// Child process
// Immediately close parent sockets and context
zmq_close (pull);
zmq_term (ctx);
// Create new context, socket, connect and send some messages
void *child_ctx = zmq_ctx_new ();
assert (child_ctx);
void *push = zmq_socket (child_ctx, ZMQ_PUSH);
assert (push);
rc = zmq_connect (push, address);
assert (rc == 0);
int count;
for (count = 0; count < NUM_MESSAGES; count++)
zmq_send (push, "Hello", 5, 0);
zmq_close (push);
zmq_ctx_destroy (child_ctx);
exit (0);
}
else {
// Parent process
alarm(TIMEOUT_SECS); // Set upper limit on runtime
int count;
for (count = 0; count < NUM_MESSAGES; count++) {
char buffer [5];
int num_bytes = zmq_recv (pull, buffer, 5, 0);
assert (num_bytes == 5);
}
int child_status;
while (true) {
rc = waitpid (pid, &child_status, 0);
if (rc == -1 && errno == EINTR)
continue;
assert (rc > 0);
// Verify the status code of the child was zero
assert (WEXITSTATUS (child_status) == 0);
break;
}
exit (0);
}
return 0;
}

42
builds/zos/zc++ Executable file
View File

@ -0,0 +1,42 @@
#! /bin/sh
# Wrapper around IBM C++ compiler to add "-+" to preprocessor calls
# and thus work with C++ in files other than *.C. Also add -Wc,lang(longlong)
# with appropriate quoting to avoid shell confusion -- this is difficult
# to get through both ./configure arguments _and_ Makefile/shell expansion
# safely so more easily added in this wrapper.
#
# Finally, by default will enable xplink for C++ compatibilty and performance
# (c++ standard library requires xplink enabled).
#
# Additional compile/link flags can be passed in as ZCXXFLAGS, eg:
#
# For debug: ZXCCFLAGS=-g ...
#
# Written by Ewen McNeill <ewen@imatix.com>, 2014-07-18
# Updated by Ewen McNeill <ewen@imatix.com>, 2014-07-21
#---------------------------------------------------------------------------
CPPFLAGS="-+"
LONGLONG="-Wc,lang(longlong)"
XPLINK="${XPLINK:--Wc,xplink -Wl,xplink}"
CXX="/bin/c++"
ZCXXFLAGS="${ZCXXFLAGS:-}" # Extra compile/link arguments, eg "-g"
# For debugging calling conventions issues
#echo "Called with: $0 $@" >>/tmp/zc++.log 2>&1
#exec >>/tmp/zc++.log 2>&1
#set -x
case "$1" in
-E) exec "${CXX}" "${CPPFLAGS}" "$@"
;;
-o) exec "${CXX}" ${ZCXXFLAGS} "${LONGLONG}" "${CPPFLAGS}" ${XPLINK} "$@"
;;
-c) exec "${CXX}" ${ZCXXFLAGS} "${LONGLONG}" "${CPPFLAGS}" ${XPLINK} "$@"
;;
-L) # Special case for linking via C++, called from linkall
exec "${CXX}" ${ZCXXFLAGS} ${XPLINK} "$@"
;;
*) exec "${CXX}" ${ZCXXFLAGS} "${LONGLONG}" ${XPLINK} "$@"
;;
esac

View File

@ -29,9 +29,10 @@ AC_SUBST(PACKAGE_VERSION)
# ZeroMQ versions 2.1.x: 1:0:0 (ABI version 1)
# ZeroMQ version 3.0: 2:0:0 (ABI version 2)
# ZeroMQ version 3.1: 3:0:0 (ABI version 3)
# ZeroMQ version 4.0: 4:0:0 (ABI version 4)
#
# libzmq -version-info current:revision:age
LTVER="3:0:0"
LTVER="4:0:0"
AC_SUBST(LTVER)
# Take a copy of original flags
@ -62,10 +63,44 @@ LIBZMQ_CHECK_ENABLE_DEBUG
# Check wheter to enable code coverage
LIBZMQ_WITH_GCOV
# Checks for libraries
AC_CHECK_LIB([pthread], [pthread_create])
AC_CHECK_LIB([rt], [clock_gettime])
AC_CHECK_LIB([sodium], [sodium_init],,AC_MSG_WARN(libsodium is needed for CURVE security))
# Allow libsodium to be installed in a custom path:
AC_ARG_WITH([libsodium],
[AS_HELP_STRING([--with-libsodium],
[Specify libsodium prefix])],
[zmq_search_libsodium="yes"],
[])
if test "x$zmq_search_libsodium" = "xyes"; then
if test -r "${with_libsodium}/include/sodium.h"; then
CPPFLAGS="-I${with_libsodium}/include ${CPPFLAGS}"
LDFLAGS="-L${with_libsodium}/lib ${LDFLAGS}"
fi
fi
AC_ARG_WITH([libsodium-include-dir],
[AS_HELP_STRING([--with-libsodium-include-dir],
[Specify libsodium include prefix])],
[zmq_search_libsodium_include="yes"],
[])
if test "x$zmq_search_libsodium_include" = "xyes"; then
if test -r "${with_libsodium_include_dir}/sodium.h"; then
CPPFLAGS="-I${with_libsodium_include_dir}/include ${CPPFLAGS}"
fi
fi
AC_ARG_WITH([libsodium_lib_dir],
[AS_HELP_STRING([--with-libsodium-lib-dir],
[Specify libsodium library prefix])],
[zmq_search_libsodium_lib="yes"],
[])
if test "x$zmq_search_libsodium_lib" = "xyes"; then
if test -r "${with_libsodium_lib_dir}/libsodium.{a|so|dylib}"; then
LDFLAGS="-L${with_libsodium}/lib ${LDFLAGS}"
fi
fi
# Set pedantic
libzmq_pedantic="yes"
@ -79,6 +114,7 @@ libzmq_dso_visibility="yes"
# Platform specific checks
libzmq_on_mingw32="no"
libzmq_on_android="no"
libzmq_on_linux="no"
# Set some default features required by 0MQ code.
CPPFLAGS="-D_REENTRANT -D_THREAD_SAFE $CPPFLAGS"
@ -94,6 +130,7 @@ case "${host_os}" in
CPPFLAGS="-D_GNU_SOURCE $CPPFLAGS"
fi
AC_DEFINE(ZMQ_HAVE_LINUX, 1, [Have Linux OS])
libzmq_on_linux="yes"
case "${host_os}" in
*android*)
@ -121,6 +158,9 @@ case "${host_os}" in
if test "x$solaris_has_atomic" = "xno"; then
AC_DEFINE(ZMQ_FORCE_MUTEXES, 1, [Force to use mutexes])
fi
# ssp library is required for libsodium on Solaris-like systems
LDFLAGS="-lssp $LDFLAGS"
CPPFLAGS="$CPPFLAGS -Wno-long-long"
;;
*freebsd*)
# Define on FreeBSD to enable all library features
@ -214,6 +254,11 @@ case "${host_os}" in
;;
esac
# Checks for libraries
AC_CHECK_LIB([pthread], [pthread_create])
AC_CHECK_LIB([rt], [clock_gettime])
AC_CHECK_LIB([sodium], [sodium_init],,AC_MSG_WARN(libsodium is needed for CURVE security))
#
# Check if the compiler supports -fvisibility=hidden flag. MinGW32 uses __declspec
#
@ -385,6 +430,7 @@ AC_LANG_POP([C++])
AM_CONDITIONAL(BUILD_PGM, test "x$libzmq_pgm_ext" = "xyes")
AM_CONDITIONAL(ON_MINGW, test "x$libzmq_on_mingw32" = "xyes")
AM_CONDITIONAL(ON_ANDROID, test "x$libzmq_on_android" = "xyes")
AM_CONDITIONAL(ON_LINUX, test "x$libzmq_on_linux" = "xyes")
# Checks for library functions.
AC_TYPE_SIGNAL

View File

@ -3,13 +3,13 @@ MAN3 = zmq_bind.3 zmq_unbind.3 zmq_connect.3 zmq_disconnect.3 zmq_close.3 \
zmq_msg_init.3 zmq_msg_init_data.3 zmq_msg_init_size.3 \
zmq_msg_move.3 zmq_msg_copy.3 zmq_msg_size.3 zmq_msg_data.3 zmq_msg_close.3 \
zmq_msg_send.3 zmq_msg_recv.3 \
zmq_send.3 zmq_recv.3 \
zmq_send.3 zmq_recv.3 zmq_send_const.3 \
zmq_msg_get.3 zmq_msg_set.3 zmq_msg_more.3 \
zmq_getsockopt.3 zmq_setsockopt.3 \
zmq_socket.3 zmq_socket_monitor.3 zmq_poll.3 \
zmq_errno.3 zmq_strerror.3 zmq_version.3 zmq_proxy.3 \
zmq_errno.3 zmq_strerror.3 zmq_version.3 zmq_proxy.3 zmq_proxy_steerable.3 \
zmq_sendmsg.3 zmq_recvmsg.3 zmq_init.3 zmq_term.3 \
zmq_z85_encode.3 zmq_z85_decode.3
zmq_z85_encode.3 zmq_z85_decode.3 zmq_curve_keypair.3
MAN7 = zmq.7 zmq_tcp.7 zmq_pgm.7 zmq_epgm.7 zmq_inproc.7 zmq_ipc.7 \
zmq_null.7 zmq_plain.7 zmq_curve.7

View File

@ -44,9 +44,6 @@ Work with context properties::
Destroy a 0MQ context::
linkzmq:zmq_ctx_term[3]
Monitor a 0MQ context::
linkzmq:zmq_ctx_set_monitor[3]
These deprecated functions let you create and destroy 'contexts':
Initialise 0MQ context::
@ -140,6 +137,10 @@ Sending and receiving messages::
linkzmq:zmq_msg_recv[3]
linkzmq:zmq_send[3]
linkzmq:zmq_recv[3]
linkzmq:zmq_send_const[3]
Monitoring socket events:
linkzmq:zmq_socket_monitor[3]
.Input/output multiplexing
0MQ provides a mechanism for applications to multiplex input/output events over
@ -193,6 +194,15 @@ Plain-text authentication using username and password::
Elliptic curve authentication and encryption::
linkzmq:zmq_curve[7]
Generate a CURVE keypair in armored text format:
linkzmq:zmq_curve_keypair[3]
Convert an armored key into a 32-byte binary key:
linkzmq:zmq_z85_decode[3]
Convert a 32-byte binary CURVE key to an armored text string:
linkzmq:zmq_z85_encode[3]
ERROR HANDLING
--------------

View File

@ -54,7 +54,7 @@ EXAMPLE
.Setting a limit on the number of sockets
----
void *context = zmq_ctx_new ();
zmq_ctx_get (context, ZMQ_MAX_SOCKETS, 256);
zmq_ctx_set (context, ZMQ_MAX_SOCKETS, 256);
int max_sockets = zmq_ctx_get (context, ZMQ_MAX_SOCKETS);
assert (max_sockets == 256);
----

56
doc/zmq_curve_keypair.txt Normal file
View File

@ -0,0 +1,56 @@
zmq_curve_keypair(3)
====================
NAME
----
zmq_curve_keypair - generate a new CURVE keypair
SYNOPSIS
--------
*int zmq_curve_keypair (char *z85_public_key, char *z85_secret_key);*
DESCRIPTION
-----------
The _zmq_curve_keypair()_ function shall return a newly generated random
keypair consisting of a public key and a secret key. The caller provides
two buffers, each at least 41 octets large, in which this method will
store the keys. The keys are encoded using linkzmq:zmq_z85_encode[3].
RETURN VALUE
------------
The _zmq_curve_keypair()_ function shall return 0 if successful, else it
shall return `-1` and set 'errno' to one of the values defined below.
ERRORS
------
*ENOTSUP*::
The libzmq library was not built with cryptographic support (libsodium).
EXAMPLE
-------
.Generating a new CURVE keypair
----
char public_key [41];
char secret_key [41];
int rc = crypto_box_keypair (public_key, secret_key);
assert (rc == 0);
----
SEE ALSO
--------
linkzmq:zmq_z85_decode[3]
linkzmq:zmq_z85_encode[3]
linkzmq:zmq_curve[7]
AUTHORS
-------
This page was written by the 0MQ community. To make a change please
read the 0MQ Contribution Policy at <http://www.zeromq.org/docs:contributing>.

View File

@ -120,8 +120,8 @@ Default value:: 0
Applicable socket types:: N/A
ZMQ_IDENTITY: Set socket identity
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ZMQ_IDENTITY: Retrieve socket identity
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The 'ZMQ_IDENTITY' option shall retrieve the identity of the specified 'socket'.
Socket identity is used only by request/reply pattern. Namely, it can be used
in tandem with ROUTER socket to route messages to the peer with specific
@ -134,7 +134,7 @@ starting with binary zero are reserved for use by 0MQ infrastructure.
Option value type:: binary data
Option value unit:: N/A
Default value:: NULL
Applicable socket types:: all
Applicable socket types:: ZMQ_REP, ZMQ_REQ, ZMQ_ROUTER, ZMQ_DEALER.
ZMQ_RATE: Retrieve multicast data rate
@ -352,8 +352,8 @@ Default value:: 1 (true)
Applicable socket types:: all, when using TCP transports.
ZMQ_DELAY_ATTACH_ON_CONNECT: Retrieve attach-on-connect value
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ZMQ_IMMEDIATE: Retrieve attach-on-connect value
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Retrieve the state of the attach on connect value. If set to `1`, will delay the
attachment of a pipe on connect until the underlying connection has completed.
This will cause the socket to block if there are no other connections, but will

View File

@ -48,6 +48,11 @@ NOTE: the endpoint pathname must be writable by the process. When the endpoint
starts with '/', e.g., `ipc:///pathname`, this will be an _absolute_ pathname.
If the endpoint specifies a directory that does not exist, the bind shall fail.
NOTE: on Linux only, when the endpoint pathname starts with `@`, the abstract
namespace shall be used. The abstract namespace is independent of the
filesystem and if a process attempts to bind an endpoint already bound by a
process, it will fail. See unix(7) for details.
Connecting a socket
~~~~~~~~~~~~~~~~~~~
When connecting a 'socket' to a peer address using _zmq_connect()_ with the

View File

@ -40,6 +40,7 @@ EXAMPLE
-------
.Receiving a multi-frame message
----
zmq_msg_t frame;
while (true) {
// Create an empty 0MQ message to hold the message frame
int rc = zmq_msg_init (&frame);
@ -53,7 +54,7 @@ while (true) {
fprintf (stderr, "end\n");
break;
}
zmq_msg_close (frame);
zmq_msg_close (&frame);
}
----

View File

@ -45,7 +45,7 @@ while (true) {
fprintf (stderr, "end\n");
break;
}
zmq_msg_close (part);
zmq_msg_close (&part);
}
----

View File

@ -73,10 +73,6 @@ NOTE: The _zmq_poll()_ function may be implemented or emulated using operating
system interfaces other than _poll()_, and as such may be subject to the limits
of those interfaces in ways not defined in this documentation.
NOTE: The _zmq_send()_ function will clear all pending events on a socket. Thus,
if you use _zmq_poll()_ to monitor input on a socket, use it before output as
well, and process all events after each _zmq_poll()_ call.
RETURN VALUE
------------
Upon successful completion, the _zmq_poll()_ function shall return the number

View File

@ -0,0 +1,99 @@
zmq_proxy_steerable(3)
======================
NAME
----
zmq_proxy_steerable - start built-in 0MQ proxy with PAUSE/RESUME/TERMINATE
control flow
SYNOPSIS
--------
*int zmq_proxy_steerable (const void '*frontend', const void '*backend',
const void '*capture', const void '*control');*
DESCRIPTION
-----------
The _zmq_proxy_steerable()_ function starts the built-in 0MQ proxy in the
current application thread, as _zmq_proxy()_ do. Please, refer to this function
for the general description and usage. We describe here only the additional
control flow provided by the socket passed as the fourth argument "control".
If the control socket is not NULL, the proxy supports control flow. If
'PAUSE' is received on this socket, the proxy suspends its activities. If
'RESUME' is received, it goes on. If 'TERMINATE' is received, it terminates
smoothly. At start, the proxy runs normally as if zmq_proxy was used.
If the control socket is NULL, the function behave exactly as if zmq_proxy
had been called.
Refer to linkzmq:zmq_socket[3] for a description of the available socket types.
Refer to linkzmq:zmq_proxy[3] for a description of the zmq_proxy.
EXAMPLE USAGE
-------------
cf zmq_proxy
RETURN VALUE
------------
The _zmq_proxy_steerable()_ function returns 0 if TERMINATE is sent to its
control socket. Otherwise, it returns `-1` and 'errno' set to *ETERM* (the
0MQ 'context' associated with either of the specified sockets was terminated).
EXAMPLE
-------
.Creating a shared queue proxy
----
// Create frontend, backend and control sockets
void *frontend = zmq_socket (context, ZMQ_ROUTER);
assert (backend);
void *backend = zmq_socket (context, ZMQ_DEALER);
assert (frontend);
void *control = zmq_socket (context, ZMQ_SUB);
assert (control);
// Bind sockets to TCP ports
assert (zmq_bind (frontend, "tcp://*:5555") == 0);
assert (zmq_bind (backend, "tcp://*:5556") == 0);
assert (zmq_connect (control, "tcp://*:5557") == 0);
// Subscribe to the control socket since we have chosen SUB here
assert (zmq_setsockopt (control, ZMQ_SUBSCRIBE, "", 0));
// Start the queue proxy, which runs until ETERM or "TERMINATE"
// received on the control socket
zmq_proxy_steerable (frontend, backend, NULL, control);
----
.Set up a controller in another node, process or whatever
----
void *control = zmq_socket (context, ZMQ_PUB);
assert (control);
assert (zmq_bind (control, "tcp://*:5557") == 0);
// pause the proxy
assert (zmq_send (control, "PAUSE", 5, 0) == 0);
// resume the proxy
assert (zmq_send (control, "RESUME", 6, 0) == 0);
// terminate the proxy
assert (zmq_send (control, "TERMINATE", 9, 0) == 0);
---
SEE ALSO
--------
linkzmq:zmq_proxy[3]
linkzmq:zmq_bind[3]
linkzmq:zmq_connect[3]
linkzmq:zmq_socket[3]
linkzmq:zmq[7]
AUTHORS
-------
This page was written by the 0MQ community. To make a change please
read the 0MQ Contribution Policy at <http://www.zeromq.org/docs:contributing>.

View File

@ -1,5 +1,5 @@
zmq_send_const(3)
===========
=================
NAME

View File

@ -14,7 +14,7 @@ SYNOPSIS
Caution: All options, with the exception of ZMQ_SUBSCRIBE, ZMQ_UNSUBSCRIBE,
ZMQ_LINGER, ZMQ_ROUTER_MANDATORY, ZMQ_PROBE_ROUTER, ZMQ_XPUB_VERBOSE,
ZMQ_REQ_STRICT, ZMQ_REQ_REQUEST_IDS only take effect for subsequent socket
ZMQ_REQ_CORRELATE, and ZMQ_REQ_RELAXED, only take effect for subsequent socket
bind/connects.
Specifically, security options take effect for subsequent bind/connect calls,
@ -135,22 +135,19 @@ Applicable socket types:: ZMQ_SUB
ZMQ_IDENTITY: Set socket identity
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The 'ZMQ_IDENTITY' option shall set the identity of the specified 'socket'.
Socket identity is used only by request/reply pattern. Namely, it can be used
in tandem with ROUTER socket to route messages to the peer with specific
identity.
The 'ZMQ_IDENTITY' option shall set the identity of the specified 'socket'
when connecting to a ROUTER socket. The identity should be from 1 to 255
bytes long and MAY NOT start with binary zero.
Identity should be at least one byte and at most 255 bytes long. Identities
starting with binary zero are reserved for use by 0MQ infrastructure.
If two peers use the same identity when connecting to a third peer, the
results shall be undefined.
If two clients use the same identity when connecting to a ROUTER, the
ROUTER socket shall accept only the first such client and reject the
others.
[horizontal]
Option value type:: binary data
Option value unit:: N/A
Default value:: NULL
Applicable socket types:: all
Applicable socket types:: ZMQ_REQ, ZMQ_REP, ZMQ_ROUTER, ZMQ_DEALER.
ZMQ_RATE: Set multicast data rate
@ -461,11 +458,11 @@ Default value:: 0
Applicable socket types:: ZMQ_XPUB
ZMQ_REQ_REQUEST_IDS: enable extra request identity frames
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ZMQ_REQ_CORRELATE: match replies with requests
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The default behavior of REQ sockets is to rely on the ordering of messages
to match requests and responses and that is usually sufficient. When this option
The default behavior of REQ sockets is to rely on the ordering of messages to
match requests and responses and that is usually sufficient. When this option
is set to 1, the REQ socket will prefix outgoing messages with an extra frame
containing a request id. That means the full message is (request id, 0,
user frames...). The REQ socket will discard all incoming messages that don't
@ -478,25 +475,25 @@ Default value:: 0
Applicable socket types:: ZMQ_REQ
ZMQ_REQ_STRICT: enforce strict alternation between request and reply
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ZMQ_REQ_RELAXED: relax strict alternation between request and reply
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When set to 1, a REQ socket does not allow initiating a new request with
By default, a REQ socket does not allow initiating a new request with
_zmq_send(3)_ until the reply to the previous one has been received.
When set to 0, sending another message is allowed and has the effect of
When set to 1, sending another message is allowed and has the effect of
disconnecting the underlying connection to the peer from which the reply was
expected, triggering a reconnection attempt on transports that support it.
The request-reply state machine is reset and a new request is sent to the
next available peer.
If set to 0, also enable ZMQ_REQ_REQUEST_IDS to ensure correct
matching of requests and replies. Otherwise a late reply to an aborted request
can be reported as the reply to the superseding request.
If set to 1, also enable ZMQ_REQ_CORRELATE to ensure correct matching of
requests and replies. Otherwise a late reply to an aborted request can be
reported as the reply to the superseding request.
[horizontal]
Option value type:: int
Option value unit:: 0, 1
Default value:: 1
Default value:: 0
Applicable socket types:: ZMQ_REQ
@ -624,7 +621,9 @@ linkzmq:zmq_curve[7]. A value of '1' means the socket will act as
CURVE server. A value of '0' means the socket will not act as CURVE
server, and its security role then depends on other option settings.
Setting this to '0' shall reset the socket security to NULL. When you
set this you must also set the ZMQ_CURVE_PUBLICKEY option.
set this you must also set the server's secret key using the
ZMQ_CURVE_SECRETKEY option. A server socket does not need to know
its own public key.
[horizontal]
Option value type:: int
@ -636,14 +635,11 @@ Applicable socket types:: all, when using TCP transport
ZMQ_CURVE_PUBLICKEY: Set CURVE public key
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sets the socket's long term public key. You must set this on a CURVE
client or server socket, see linkzmq:zmq_curve[7]. You can provide the
key as 32 binary bytes, or as a 40-character string encoded in the Z85
encoding format. For servers, the public key must be persisted and
shared through some unspecified but secure mechanism to clients. The
public key must always be used with the matching secret key generated
at the same time. To generate a public/secret key pair, use the
tools/curve_keygen tool.
Sets the socket's long term public key. You must set this on CURVE client
sockets, see linkzmq:zmq_curve[7]. You can provide the key as 32 binary
bytes, or as a 40-character string encoded in the Z85 encoding format.
The public key must always be used with the matching secret key. To
generate a public/secret key pair, use linkzmq:zmq_curve_keypair[3].
[horizontal]
Option value type:: binary data or Z85 text string
@ -655,10 +651,11 @@ Applicable socket types:: all, when using TCP transport
ZMQ_CURVE_SECRETKEY: Set CURVE secret key
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sets the socket's long term secret key. You must set this on a CURVE
client socket, see linkzmq:zmq_curve[7]. You can provide the key as
32 binary bytes, or as a 40-character string encoded in the Z85 encoding
format.
Sets the socket's long term secret key. You must set this on both CURVE
client and server sockets, see linkzmq:zmq_curve[7]. You can provide the
key as 32 binary bytes, or as a 40-character string encoded in the Z85
encoding format. To generate a public/secret key pair, use
linkzmq:zmq_curve_keypair[3].
[horizontal]
Option value type:: binary data or Z85 text string
@ -670,11 +667,10 @@ Applicable socket types:: all, when using TCP transport
ZMQ_CURVE_SERVERKEY: Set CURVE server key
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sets the socket's long term server key. You must set this on a CURVE
client socket, see linkzmq:zmq_curve[7]. You can provide the key as
32 binary bytes, or as a 40-character string encoded in the Z85 encoding
format. This key must be the same as the public key set on the server
socket.
Sets the socket's long term server key. You must set this on CURVE client
sockets, see linkzmq:zmq_curve[7]. You can provide the key as 32 binary
bytes, or as a 40-character string encoded in the Z85 encoding format.
This key must have been generated together with the server's secret key.
[horizontal]
Option value type:: binary data or Z85 text string

View File

@ -62,6 +62,7 @@ The request-reply pattern is used for sending requests from a ZMQ_REQ _client_
to one or more ZMQ_REP _services_, and receiving subsequent replies to each
request sent.
The request-reply pattern is formally defined by http://rfc.zeromq.org/spec:28.
ZMQ_REQ
^^^^^^^
@ -168,6 +169,7 @@ Publish-subscribe pattern
The publish-subscribe pattern is used for one-to-many distribution of data from
a single _publisher_ to multiple _subscribers_ in a fan out fashion.
The publish-subscribe pattern is formally defined by http://rfc.zeromq.org/spec:29.
ZMQ_PUB
^^^^^^^
@ -249,6 +251,7 @@ a pipeline. Data always flows down the pipeline, and each stage of the pipeline
is connected to at least one _node_. When a pipeline stage is connected to
multiple _nodes_ data is round-robined among all connected _nodes_.
The pipeline pattern is formally defined by http://rfc.zeromq.org/spec:30.
ZMQ_PUSH
^^^^^^^^
@ -296,6 +299,7 @@ The exclusive pair pattern is used to connect a peer to precisely one other
peer. This pattern is used for inter-thread communication across the inproc
transport.
The exclusive pair pattern is formally defined by http://rfc.zeromq.org/spec:31.
ZMQ_PAIR
^^^^^^^^
@ -400,7 +404,7 @@ uint8_t id [256];
size_t id_size = 256;
while (1) {
/* Get HTTP request; ID frame and then request */
id_size = zmq_recv (server, id, 256, 0);
id_size = zmq_recv (socket, id, 256, 0);
assert (id_size > 0);
/* Prepares the response */
char http_response [] =

View File

@ -66,7 +66,7 @@ EXAMPLES
.Assigning a local address to a socket
----
// TCP port 5555 on all available interfaces
rc = zmq_bind(socket, "tcp:/// :5555");
rc = zmq_bind(socket, "tcp://*:5555");
assert (rc == 0);
// TCP port 5555 on the local loop-back interface on all platforms
rc = zmq_bind(socket, "tcp://127.0.0.1:5555");

View File

@ -31,7 +31,6 @@ EXAMPLE
-------
.Decoding a CURVE key
----
#include <sodium.h>
char decoded [] = "rq:rM>}U?@Lns47E1%kR.o@n%FcmmsL/@{H8]yf7";
uint8_t public_key [32];
zmq_z85_decode (public_key, decoded);
@ -41,6 +40,7 @@ zmq_z85_decode (public_key, decoded);
SEE ALSO
--------
linkzmq:zmq_z85_decode[3]
linkzmq:zmq_curve_keypair[3]
linkzmq:zmq_curve[7]

View File

@ -47,6 +47,7 @@ puts (encoded);
SEE ALSO
--------
linkzmq:zmq_z85_decode[3]
linkzmq:zmq_curve_keypair[3]
linkzmq:zmq_curve[7]

View File

@ -15,11 +15,29 @@
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*************************************************************************
NOTE to contributors. This file comprises the principal public contract
for ZeroMQ API users (along with zmq_utils.h). Any change to this file
supplied in a stable release SHOULD not break existing applications.
In practice this means that the value of constants must not change, and
that old values may not be reused for new constants.
*************************************************************************
*/
#ifndef __ZMQ_H_INCLUDED__
#define __ZMQ_H_INCLUDED__
/* Version macros for compile-time API version detection */
#define ZMQ_VERSION_MAJOR 4
#define ZMQ_VERSION_MINOR 0
#define ZMQ_VERSION_PATCH 5
#define ZMQ_MAKE_VERSION(major, minor, patch) \
((major) * 10000 + (minor) * 100 + (patch))
#define ZMQ_VERSION \
ZMQ_MAKE_VERSION(ZMQ_VERSION_MAJOR, ZMQ_VERSION_MINOR, ZMQ_VERSION_PATCH)
#ifdef __cplusplus
extern "C" {
#endif
@ -62,28 +80,14 @@ typedef __int32 int32_t;
# ifndef uint16_t
typedef unsigned __int16 uint16_t;
# endif
# ifndef uint8_t
typedef unsigned __int8 uint8_t;
# endif
#else
# include <stdint.h>
#endif
/******************************************************************************/
/* 0MQ versioning support. */
/******************************************************************************/
/* Version macros for compile-time API version detection */
#define ZMQ_VERSION_MAJOR 3
#define ZMQ_VERSION_MINOR 3
#define ZMQ_VERSION_PATCH 0
#define ZMQ_MAKE_VERSION(major, minor, patch) \
((major) * 10000 + (minor) * 100 + (patch))
#define ZMQ_VERSION \
ZMQ_MAKE_VERSION(ZMQ_VERSION_MAJOR, ZMQ_VERSION_MINOR, ZMQ_VERSION_PATCH)
/* Run-time API version detection */
ZMQ_EXPORT void zmq_version (int *major, int *minor, int *patch);
/******************************************************************************/
/* 0MQ errors. */
/******************************************************************************/
@ -154,6 +158,9 @@ ZMQ_EXPORT void zmq_version (int *major, int *minor, int *patch);
#define ETERM (ZMQ_HAUSNUMERO + 53)
#define EMTHREAD (ZMQ_HAUSNUMERO + 54)
/* Run-time API version detection */
ZMQ_EXPORT void zmq_version (int *major, int *minor, int *patch);
/* This function retrieves the errno as it is known to 0MQ library. The goal */
/* of this function is to make the code 100% portable, including where 0MQ */
/* compiled with certain CRT library (on Windows) is linked to an */
@ -174,7 +181,7 @@ ZMQ_EXPORT const char *zmq_strerror (int errnum);
/* Default for new contexts */
#define ZMQ_IO_THREADS_DFLT 1
#define ZMQ_MAX_SOCKETS_DFLT 1024
#define ZMQ_MAX_SOCKETS_DFLT 1023
ZMQ_EXPORT void *zmq_ctx_new (void);
ZMQ_EXPORT int zmq_ctx_term (void *context);
@ -277,8 +284,8 @@ ZMQ_EXPORT int zmq_msg_set (zmq_msg_t *msg, int option, int optval);
#define ZMQ_CURVE_SECRETKEY 49
#define ZMQ_CURVE_SERVERKEY 50
#define ZMQ_PROBE_ROUTER 51
#define ZMQ_REQ_REQUEST_IDS 52
#define ZMQ_REQ_STRICT 53
#define ZMQ_REQ_CORRELATE 52
#define ZMQ_REQ_RELAXED 53
#define ZMQ_CONFLATE 54
#define ZMQ_ZAP_DOMAIN 55
@ -385,6 +392,7 @@ ZMQ_EXPORT int zmq_poll (zmq_pollitem_t *items, int nitems, long timeout);
/* Built-in message proxy (3-way) */
ZMQ_EXPORT int zmq_proxy (void *frontend, void *backend, void *capture);
ZMQ_EXPORT int zmq_proxy_steerable (void *frontend, void *backend, void *capture, void *control);
/* Encode a binary key as printable text using ZMQ RFC 32 */
ZMQ_EXPORT char *zmq_z85_encode (char *dest, uint8_t *data, size_t size);

View File

@ -22,9 +22,22 @@
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
/* Define integer types needed for event interface */
#if defined ZMQ_HAVE_SOLARIS || defined ZMQ_HAVE_OPENVMS
# include <inttypes.h>
#elif defined _MSC_VER && _MSC_VER < 1600
# ifndef int32_t
typedef __int32 int32_t;
# endif
# ifndef uint16_t
typedef unsigned __int16 uint16_t;
# endif
#else
# include <stdint.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -48,8 +61,22 @@ extern "C" {
# endif
#endif
/* These functions are documented by man pages */
/* Encode data with Z85 encoding. Returns encoded data */
ZMQ_EXPORT char *zmq_z85_encode (char *dest, uint8_t *data, size_t size);
/* Decode data with Z85 encoding. Returns decoded data */
ZMQ_EXPORT uint8_t *zmq_z85_decode (uint8_t *dest, char *string);
/* Generate z85-encoded public and private keypair with libsodium. */
/* Returns 0 on success. */
ZMQ_EXPORT int zmq_curve_keypair (char *z85_public_key, char *z85_secret_key);
typedef void (zmq_thread_fn) (void*);
/* These functions are not documented by man pages */
/* Helper functions are used by perf tests so that they don't have to care */
/* about minutiae of time-related functions on different OS platforms. */

View File

@ -88,7 +88,7 @@ libzmq_la_SOURCES = \
dealer.hpp \
xsub.hpp \
ypipe.hpp \
ypipe_flat.hpp \
ypipe_base.hpp \
yqueue.hpp \
address.cpp \
clock.cpp \
@ -173,9 +173,15 @@ else
if ON_ANDROID
libzmq_la_LDFLAGS = -avoid-version -version-info @LTVER@ @LIBZMQ_EXTRA_LDFLAGS@
else
libzmq_la_LDFLAGS = -version-info @LTVER@ @LIBZMQ_EXTRA_LDFLAGS@
if ON_LINUX
libzmq_la_LDFLAGS = -version-info @LTVER@ @LIBZMQ_EXTRA_LDFLAGS@ -Wl,--version-script=$(srcdir)/libzmq.vers
else
libzmq_la_LDFLAGS = -version-info @LTVER@ @LIBZMQ_EXTRA_LDFLAGS@ -Wl
endif
endif
endif
EXTRA_DIST = libzmq.vers
libzmq_la_CXXFLAGS = @LIBZMQ_EXTRA_CXXFLAGS@

View File

@ -22,6 +22,7 @@
#include "likely.hpp"
#include "config.hpp"
#include "err.hpp"
#include "mutex.hpp"
#include <stddef.h>
@ -41,9 +42,49 @@
#include <time.h>
#endif
#ifdef ZMQ_HAVE_WINDOWS
typedef ULONGLONG (*f_compatible_get_tick_count64)();
static zmq::mutex_t compatible_get_tick_count64_mutex;
ULONGLONG compatible_get_tick_count64()
{
compatible_get_tick_count64_mutex.lock();
static DWORD s_wrap = 0;
static DWORD s_last_tick = 0;
const DWORD current_tick = ::GetTickCount();
if (current_tick < s_last_tick)
++s_wrap;
s_last_tick = current_tick;
const ULONGLONG result = (static_cast<ULONGLONG>(s_wrap) << 32) + static_cast<ULONGLONG>(current_tick);
compatible_get_tick_count64_mutex.unlock();
return result;
}
f_compatible_get_tick_count64 init_compatible_get_tick_count64()
{
f_compatible_get_tick_count64 func = NULL;
HMODULE module = ::LoadLibraryA("Kernel32.dll");
if (module != NULL)
func = reinterpret_cast<f_compatible_get_tick_count64>(::GetProcAddress(module, "GetTickCount64"));
if (func == NULL)
func = compatible_get_tick_count64;
return func;
}
static f_compatible_get_tick_count64 my_get_tick_count64 = init_compatible_get_tick_count64();
#endif
zmq::clock_t::clock_t () :
last_tsc (rdtsc ()),
#ifdef ZMQ_HAVE_WINDOWS
last_time (static_cast<uint64_t>((*my_get_tick_count64)()))
#else
last_time (now_us () / 1000)
#endif
{
}
@ -106,7 +147,17 @@ uint64_t zmq::clock_t::now_ms ()
// If TSC is not supported, get precise time and chop off the microseconds.
if (!tsc)
{
#ifdef ZMQ_HAVE_WINDOWS
// Under Windows, now_us is not so reliable since QueryPerformanceCounter
// does not guarantee that it will use a hardware that offers a monotonic timer.
// So, lets use GetTickCount when GetTickCount64 is not available with an workaround
// to its 32 bit limitation.
return static_cast<uint64_t>((*my_get_tick_count64)());
#else
return now_us () / 1000;
#endif
}
// If TSC haven't jumped back (in case of migration to a different
// CPU core) and if not too much time elapsed since last measurement,
@ -115,7 +166,11 @@ uint64_t zmq::clock_t::now_ms ()
return last_time;
last_tsc = tsc;
#ifdef ZMQ_HAVE_WINDOWS
last_time = static_cast<uint64_t>((*my_get_tick_count64)());
#else
last_time = now_us () / 1000;
#endif
return last_time;
}
@ -138,7 +193,6 @@ uint64_t zmq::clock_t::rdtsc ()
#elif defined(__s390__)
uint64_t tsc;
asm("\tstck\t%0\n" : "=Q" (tsc) : : "cc");
tsc >>= 12; /* convert to microseconds just to be consistent */
return(tsc);
#else
return 0;

View File

@ -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.
@ -35,9 +35,21 @@
#include "err.hpp"
#include "msg.hpp"
#ifdef HAVE_LIBSODIUM
#include <sodium.h>
#endif
#define ZMQ_CTX_TAG_VALUE_GOOD 0xabadcafe
#define ZMQ_CTX_TAG_VALUE_BAD 0xdeadbeef
int clipped_maxsocket(int max_requested)
{
if (max_requested >= zmq::poller_t::max_fds () && zmq::poller_t::max_fds () != -1)
max_requested = zmq::poller_t::max_fds () - 1; // -1 because we need room for the repear mailbox.
return max_requested;
}
zmq::ctx_t::ctx_t () :
tag (ZMQ_CTX_TAG_VALUE_GOOD),
starting (true),
@ -45,7 +57,7 @@ zmq::ctx_t::ctx_t () :
reaper (NULL),
slot_count (0),
slots (NULL),
max_sockets (ZMQ_MAX_SOCKETS_DFLT),
max_sockets (clipped_maxsocket (ZMQ_MAX_SOCKETS_DFLT)),
io_thread_count (ZMQ_IO_THREADS_DFLT),
ipv6 (false)
{
@ -74,14 +86,18 @@ zmq::ctx_t::~ctx_t ()
delete io_threads [i];
// Deallocate the reaper thread object.
if (reaper)
delete reaper;
delete reaper;
// Deallocate the array of mailboxes. No special work is
// needed as mailboxes themselves were deallocated with their
// corresponding io_thread/socket objects.
if (slots)
free (slots);
free (slots);
// If we've done any Curve encryption, we may have a file handle
// to /dev/urandom open that needs to be cleaned up.
#ifdef HAVE_LIBSODIUM
randombytes_close();
#endif
// Remove the tag, so that the object is considered dead.
tag = ZMQ_CTX_TAG_VALUE_BAD;
@ -89,6 +105,14 @@ zmq::ctx_t::~ctx_t ()
int zmq::ctx_t::terminate ()
{
// Connect up any pending inproc connections, otherwise we will hang
pending_connections_t copy = pending_connections;
for (pending_connections_t::iterator p = copy.begin (); p != copy.end (); ++p) {
zmq::socket_base_t *s = create_socket (ZMQ_PAIR);
s->bind (p->first.c_str ());
s->close ();
}
slot_sync.lock ();
if (!starting) {
@ -109,7 +133,6 @@ int zmq::ctx_t::terminate ()
// restarted.
bool restarted = terminating;
terminating = true;
slot_sync.unlock ();
// First attempt to terminate the context.
if (!restarted) {
@ -117,13 +140,12 @@ int zmq::ctx_t::terminate ()
// First send stop command to sockets so that any blocking calls
// can be interrupted. If there are no sockets we can ask reaper
// thread to stop.
slot_sync.lock ();
for (sockets_t::size_type i = 0; i != sockets.size (); i++)
sockets [i]->stop ();
if (sockets.empty ())
reaper->stop ();
slot_sync.unlock ();
}
slot_sync.unlock();
// Wait till reaper thread closes all the sockets.
command_t cmd;
@ -165,7 +187,7 @@ int zmq::ctx_t::shutdown ()
int zmq::ctx_t::set (int option_, int optval_)
{
int rc = 0;
if (option_ == ZMQ_MAX_SOCKETS && optval_ >= 1) {
if (option_ == ZMQ_MAX_SOCKETS && optval_ >= 1 && optval_ == clipped_maxsocket (optval_)) {
opt_sync.lock ();
max_sockets = optval_;
opt_sync.unlock ();
@ -433,6 +455,14 @@ void zmq::ctx_t::connect_inproc_sockets(zmq::socket_base_t *bind_socket_, option
bind_socket_->inc_seqnum();
pending_connection_.bind_pipe->set_tid(bind_socket_->get_tid());
if (!bind_options.recv_identity) {
msg_t msg;
const bool ok = pending_connection_.bind_pipe->read (&msg);
zmq_assert (ok);
const int rc = msg.close ();
errno_assert (rc == 0);
}
if (side_ == bind_side)
{
command_t cmd;
@ -464,17 +494,6 @@ void zmq::ctx_t::connect_inproc_sockets(zmq::socket_base_t *bind_socket_, option
pending_connection_.connect_pipe->set_hwms(hwms [1], hwms [0]);
pending_connection_.bind_pipe->set_hwms(hwms [0], hwms [1]);
if (bind_options.recv_identity) {
msg_t id;
int rc = id.init_size (pending_connection_.endpoint.options.identity_size);
errno_assert (rc == 0);
memcpy (id.data (), pending_connection_.endpoint.options.identity, pending_connection_.endpoint.options.identity_size);
id.set_flags (msg_t::identity);
bool written = pending_connection_.connect_pipe->write (&id);
zmq_assert (written);
pending_connection_.connect_pipe->flush ();
}
if (pending_connection_.endpoint.options.recv_identity) {
msg_t id;
int rc = id.init_size (bind_options.identity_size);

View File

@ -132,8 +132,8 @@ namespace zmq
sockets_t sockets;
// List of unused thread slots.
typedef std::vector <uint32_t> emtpy_slots_t;
emtpy_slots_t empty_slots;
typedef std::vector <uint32_t> empty_slots_t;
empty_slots_t empty_slots;
// If true, zmq_init has been called but no socket has been created
// yet. Launching of I/O threads is delayed.

View File

@ -297,34 +297,38 @@ int zmq::curve_client_t::process_welcome (msg_t *msg_)
int zmq::curve_client_t::produce_initiate (msg_t *msg_)
{
uint8_t vouch_nonce [crypto_box_NONCEBYTES];
uint8_t vouch_plaintext [crypto_box_ZEROBYTES + 32];
uint8_t vouch_box [crypto_box_BOXZEROBYTES + 48];
uint8_t vouch_plaintext [crypto_box_ZEROBYTES + 64];
uint8_t vouch_box [crypto_box_BOXZEROBYTES + 80];
// Create vouch = Box [C'](C->S)
// Create vouch = Box [C',S](C->S')
memset (vouch_plaintext, 0, crypto_box_ZEROBYTES);
memcpy (vouch_plaintext + crypto_box_ZEROBYTES, cn_public, 32);
memcpy (vouch_plaintext + crypto_box_ZEROBYTES + 32, server_key, 32);
memcpy (vouch_nonce, "VOUCH---", 8);
randombytes (vouch_nonce + 8, 16);
int rc = crypto_box (vouch_box, vouch_plaintext,
sizeof vouch_plaintext,
vouch_nonce, server_key, secret_key);
vouch_nonce, cn_server, secret_key);
zmq_assert (rc == 0);
// Assume here that metadata is limited to 256 bytes
uint8_t initiate_nonce [crypto_box_NONCEBYTES];
uint8_t initiate_plaintext [crypto_box_ZEROBYTES + 96 + 256];
uint8_t initiate_box [crypto_box_BOXZEROBYTES + 112 + 256];
uint8_t initiate_plaintext [crypto_box_ZEROBYTES + 128 + 256];
uint8_t initiate_box [crypto_box_BOXZEROBYTES + 144 + 256];
// Create Box [C + vouch + metadata](C'->S')
memset (initiate_plaintext, 0, crypto_box_ZEROBYTES);
memcpy (initiate_plaintext + crypto_box_ZEROBYTES, public_key, 32);
memcpy (initiate_plaintext + crypto_box_ZEROBYTES,
public_key, 32);
memcpy (initiate_plaintext + crypto_box_ZEROBYTES + 32,
vouch_nonce + 8, 16);
memcpy (initiate_plaintext + crypto_box_ZEROBYTES + 48,
vouch_box + crypto_box_BOXZEROBYTES, 48);
vouch_box + crypto_box_BOXZEROBYTES, 80);
uint8_t *ptr = initiate_plaintext + crypto_box_ZEROBYTES + 96;
// Metadata starts after vouch
uint8_t *ptr = initiate_plaintext + crypto_box_ZEROBYTES + 128;
// Add socket type property
const char *socket_type = socket_type_string (options.type);
@ -335,7 +339,7 @@ int zmq::curve_client_t::produce_initiate (msg_t *msg_)
|| options.type == ZMQ_DEALER
|| options.type == ZMQ_ROUTER)
ptr += add_property (ptr, "Identity",
options.identity, options.identity_size);
options.identity, options.identity_size);
const size_t mlen = ptr - initiate_plaintext;
@ -359,7 +363,6 @@ int zmq::curve_client_t::produce_initiate (msg_t *msg_)
// Box [C + vouch + metadata](C'->S')
memcpy (initiate + 113, initiate_box + crypto_box_BOXZEROBYTES,
mlen - crypto_box_BOXZEROBYTES);
cn_nonce++;
return 0;

View File

@ -338,7 +338,7 @@ int zmq::curve_server_t::produce_welcome (msg_t *msg_)
int zmq::curve_server_t::process_initiate (msg_t *msg_)
{
if (msg_->size () < 225) {
if (msg_->size () < 257) {
errno = EPROTO;
return -1;
}
@ -369,19 +369,17 @@ int zmq::curve_server_t::process_initiate (msg_t *msg_)
}
// Check cookie plain text is as expected [C' + s']
if (memcmp (cookie_plaintext + crypto_secretbox_ZEROBYTES,
cn_client, 32)
|| memcmp (cookie_plaintext + crypto_secretbox_ZEROBYTES + 32,
cn_secret, 32)) {
errno = EAGAIN;
if (memcmp (cookie_plaintext + crypto_secretbox_ZEROBYTES, cn_client, 32)
|| memcmp (cookie_plaintext + crypto_secretbox_ZEROBYTES + 32, cn_secret, 32)) {
errno = EPROTO;
return -1;
}
const size_t clen = (msg_->size () - 113) + crypto_box_BOXZEROBYTES;
uint8_t initiate_nonce [crypto_box_NONCEBYTES];
uint8_t initiate_plaintext [crypto_box_ZEROBYTES + 96 + 256];
uint8_t initiate_box [crypto_box_BOXZEROBYTES + 112 + 256];
uint8_t initiate_plaintext [crypto_box_ZEROBYTES + 128 + 256];
uint8_t initiate_box [crypto_box_BOXZEROBYTES + 144 + 256];
// Open Box [C + vouch + metadata](C'->S')
memset (initiate_box, 0, crypto_box_BOXZEROBYTES);
@ -401,13 +399,13 @@ int zmq::curve_server_t::process_initiate (msg_t *msg_)
const uint8_t *client_key = initiate_plaintext + crypto_box_ZEROBYTES;
uint8_t vouch_nonce [crypto_box_NONCEBYTES];
uint8_t vouch_plaintext [crypto_box_ZEROBYTES + 32];
uint8_t vouch_box [crypto_box_BOXZEROBYTES + 48];
uint8_t vouch_plaintext [crypto_box_ZEROBYTES + 64];
uint8_t vouch_box [crypto_box_BOXZEROBYTES + 80];
// Open Box [C'](C->S) and check contents
// Open Box Box [C',S](C->S') and check contents
memset (vouch_box, 0, crypto_box_BOXZEROBYTES);
memcpy (vouch_box + crypto_box_BOXZEROBYTES,
initiate_plaintext + crypto_box_ZEROBYTES + 48, 48);
initiate_plaintext + crypto_box_ZEROBYTES + 48, 80);
memcpy (vouch_nonce, "VOUCH---", 8);
memcpy (vouch_nonce + 8,
@ -415,7 +413,7 @@ int zmq::curve_server_t::process_initiate (msg_t *msg_)
rc = crypto_box_open (vouch_plaintext, vouch_box,
sizeof vouch_box,
vouch_nonce, client_key, secret_key);
vouch_nonce, client_key, cn_secret);
if (rc != 0) {
errno = EPROTO;
return -1;
@ -443,8 +441,8 @@ int zmq::curve_server_t::process_initiate (msg_t *msg_)
}
}
return parse_metadata (initiate_plaintext + crypto_box_ZEROBYTES + 96,
clen - crypto_box_ZEROBYTES - 96);
return parse_metadata (initiate_plaintext + crypto_box_ZEROBYTES + 128,
clen - crypto_box_ZEROBYTES - 128);
}
int zmq::curve_server_t::produce_ready (msg_t *msg_)

View File

@ -133,6 +133,11 @@ void zmq::devpoll_t::stop ()
stopping = true;
}
int zmq::devpoll_t::max_fds ()
{
return -1;
}
void zmq::devpoll_t::loop ()
{
while (!stopping) {

View File

@ -56,6 +56,8 @@ namespace zmq
void start ();
void stop ();
static int max_fds ();
private:
// Main worker thread routine.

View File

@ -127,11 +127,6 @@ namespace zmq
(static_cast <T*> (this)->*next) ();
}
inline bool has_data ()
{
return to_write > 0;
}
protected:
// Prototype of state machine action.

View File

@ -126,6 +126,11 @@ void zmq::epoll_t::stop ()
stopping = true;
}
int zmq::epoll_t::max_fds ()
{
return -1;
}
void zmq::epoll_t::loop ()
{
epoll_event ev_buf [max_io_events];

View File

@ -58,6 +58,8 @@ namespace zmq
void start ();
void stop ();
static int max_fds ();
private:
// Main worker thread routine.

View File

@ -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.
@ -216,6 +216,9 @@ void zmq::win_error (char *buffer_, size_t buffer_size_)
int zmq::wsa_error_to_errno (int errcode)
{
switch (errcode) {
// 10004 - Interrupted system call.
case WSAEINTR:
return EINTR;
// 10009 - File handle is not valid.
case WSAEBADF:
return EBADF;
@ -231,15 +234,42 @@ int zmq::wsa_error_to_errno (int errcode)
// 10024 - Too many open files.
case WSAEMFILE:
return EMFILE;
// 10035 - Operation would block.
case WSAEWOULDBLOCK:
return EBUSY;
// 10036 - Operation now in progress.
case WSAEINPROGRESS:
return EAGAIN;
// 10037 - Operation already in progress.
case WSAEALREADY:
return EAGAIN;
// 10038 - Socket operation on non-socket.
case WSAENOTSOCK:
return ENOTSOCK;
// 10039 - Destination address required.
case WSAEDESTADDRREQ:
return EFAULT;
// 10040 - Message too long.
case WSAEMSGSIZE:
return EMSGSIZE;
// 10041 - Protocol wrong type for socket.
case WSAEPROTOTYPE:
return EFAULT;
// 10042 - Bad protocol option.
case WSAENOPROTOOPT:
return EINVAL;
// 10043 - Protocol not supported.
case WSAEPROTONOSUPPORT:
return EPROTONOSUPPORT;
// 10044 - Socket type not supported.
case WSAESOCKTNOSUPPORT:
return EFAULT;
// 10045 - Operation not supported on socket.
case WSAEOPNOTSUPP:
return EFAULT;
// 10046 - Protocol family not supported.
case WSAEPFNOSUPPORT:
return EPROTONOSUPPORT;
// 10047 - Address family not supported by protocol family.
case WSAEAFNOSUPPORT:
return EAFNOSUPPORT;
@ -267,18 +297,75 @@ int zmq::wsa_error_to_errno (int errcode)
// 10055 - No buffer space available.
case WSAENOBUFS:
return ENOBUFS;
// 10056 - Socket is already connected.
case WSAEISCONN:
return EFAULT;
// 10057 - Socket is not connected.
case WSAENOTCONN:
return ENOTCONN;
// 10058 - Can't send after socket shutdown.
case WSAESHUTDOWN:
return EFAULT;
// 10059 - Too many references can't splice.
case WSAETOOMANYREFS:
return EFAULT;
// 10060 - Connection timed out.
case WSAETIMEDOUT:
return ETIMEDOUT;
// 10061 - Connection refused.
case WSAECONNREFUSED:
return ECONNREFUSED;
// 10062 - Too many levels of symbolic links.
case WSAELOOP:
return EFAULT;
// 10063 - File name too long.
case WSAENAMETOOLONG:
return EFAULT;
// 10064 - Host is down.
case WSAEHOSTDOWN:
return EAGAIN;
// 10065 - No route to host.
case WSAEHOSTUNREACH:
return EHOSTUNREACH;
// 10066 - Directory not empty.
case WSAENOTEMPTY:
return EFAULT;
// 10067 - Too many processes.
case WSAEPROCLIM:
return EFAULT;
// 10068 - Too many users.
case WSAEUSERS:
return EFAULT;
// 10069 - Disc Quota Exceeded.
case WSAEDQUOT:
return EFAULT;
// 10070 - Stale NFS file handle.
case WSAESTALE:
return EFAULT;
// 10071 - Too many levels of remote in path.
case WSAEREMOTE:
return EFAULT;
// 10091 - Network SubSystem is unavailable.
case WSASYSNOTREADY:
return EFAULT;
// 10092 - WINSOCK DLL Version out of range.
case WSAVERNOTSUPPORTED:
return EFAULT;
// 10093 - Successful WSASTARTUP not yet performed.
case WSANOTINITIALISED:
return EFAULT;
// 11001 - Host not found.
case WSAHOST_NOT_FOUND:
return EFAULT;
// 11002 - Non-Authoritative Host not found.
case WSATRY_AGAIN:
return EFAULT;
// 11003 - Non-Recoverable errors: FORMERR REFUSED NOTIMP.
case WSANO_RECOVERY:
return EFAULT;
// 11004 - Valid name no data record of requested.
case WSANO_DATA:
return EFAULT;
default:
wsa_assert (false);
}

View File

@ -43,7 +43,6 @@ namespace zmq
// Load a new message into encoder.
virtual void load_msg (msg_t *msg_) = 0;
virtual bool has_data () = 0;
};
}

View File

@ -41,11 +41,11 @@ namespace zmq
// This method is called by the session to signalise that more
// messages can be written to the pipe.
virtual void activate_in () = 0;
virtual void restart_input () = 0;
// This method is called by the session to signalise that there
// are messages to send available.
virtual void activate_out () = 0;
virtual void restart_output () = 0;
virtual void zap_msg_available () = 0;
};

View File

@ -133,7 +133,6 @@ bool zmq::get_peer_ip_address (fd_t sockfd_, std::string &ip_addr_)
errno_assert (errno != EBADF &&
errno != EFAULT &&
errno != EINVAL &&
errno != ENOTCONN &&
errno != ENOTSOCK);
return false;
}

View File

@ -51,9 +51,20 @@ int zmq::ipc_address_t::resolve (const char *path_)
errno = ENAMETOOLONG;
return -1;
}
#if defined ZMQ_HAVE_LINUX
if (path_[0] == '@' && !path_[1]) {
errno = EINVAL;
return -1;
}
#endif
address.sun_family = AF_UNIX;
strcpy (address.sun_path, path_);
#if defined ZMQ_HAVE_LINUX
/* Abstract sockets on Linux start with '\0' */
if (path_[0] == '@')
*address.sun_path = '\0';
#endif
return 0;
}
@ -65,7 +76,15 @@ int zmq::ipc_address_t::to_string (std::string &addr_)
}
std::stringstream s;
#if !defined ZMQ_HAVE_LINUX
s << "ipc://" << address.sun_path;
#else
s << "ipc://";
if (!address.sun_path[0] && address.sun_path[1])
s << "@" << address.sun_path + 1;
else
s << address.sun_path;
#endif
addr_ = s.str ();
return 0;
}
@ -77,6 +96,10 @@ const sockaddr *zmq::ipc_address_t::addr () const
socklen_t zmq::ipc_address_t::addrlen () const
{
#if defined ZMQ_HAVE_LINUX
if (!address.sun_path[0] && address.sun_path[1])
return (socklen_t) strlen(address.sun_path + 1) + sizeof (sa_family_t) + 1;
#endif
return (socklen_t) sizeof (address);
}

View File

@ -152,6 +152,11 @@ void zmq::kqueue_t::stop ()
stopping = true;
}
int zmq::kqueue_t::max_fds ()
{
return -1;
}
void zmq::kqueue_t::loop ()
{
while (!stopping) {

View File

@ -58,6 +58,8 @@ namespace zmq
void start ();
void stop ();
static int max_fds ();
private:
// Main worker thread routine.

4
src/libzmq.vers Normal file
View File

@ -0,0 +1,4 @@
{
global: zmq_*;
local: *;
};

View File

@ -54,8 +54,7 @@ zmq::mtrie_t::~mtrie_t ()
else
if (count > 1) {
for (unsigned short i = 0; i != count; ++i)
if (next.table [i])
delete next.table [i];
delete next.table [i];
free (next.table);
}
}

View File

@ -286,7 +286,7 @@ int zmq::options_t::setsockopt (int option_, const void *optval_,
break;
case ZMQ_ZAP_DOMAIN:
if (optvallen_ >= 0 && optvallen_ < 256) {
if (optvallen_ < 256) {
zap_domain.assign ((const char *) optval_, optvallen_);
return 0;
}

View File

@ -102,12 +102,12 @@ void zmq::pgm_receiver_t::terminate ()
delete this;
}
void zmq::pgm_receiver_t::activate_out ()
void zmq::pgm_receiver_t::restart_output ()
{
drop_subscriptions ();
}
void zmq::pgm_receiver_t::activate_in ()
void zmq::pgm_receiver_t::restart_input ()
{
zmq_assert (session != NULL);
zmq_assert (active_tsi != NULL);

View File

@ -57,8 +57,8 @@ namespace zmq
void plug (zmq::io_thread_t *io_thread_,
zmq::session_base_t *session_);
void terminate ();
void activate_in ();
void activate_out ();
void restart_input ();
void restart_output ();
void zap_msg_available () {}
// i_poll_events interface implementation.

View File

@ -119,13 +119,13 @@ void zmq::pgm_sender_t::terminate ()
delete this;
}
void zmq::pgm_sender_t::activate_out ()
void zmq::pgm_sender_t::restart_output ()
{
set_pollout (handle);
out_event ();
}
void zmq::pgm_sender_t::activate_in ()
void zmq::pgm_sender_t::restart_input ()
{
zmq_assert (false);
}

View File

@ -56,8 +56,8 @@ namespace zmq
void plug (zmq::io_thread_t *io_thread_,
zmq::session_base_t *session_);
void terminate ();
void activate_in ();
void activate_out ();
void restart_input ();
void restart_output ();
void zap_msg_available () {}
// i_poll_events interface implementation.

View File

@ -154,7 +154,7 @@ bool zmq::pipe_t::read (msg_t *msg_)
return false;
}
if (!(msg_->flags () & msg_t::more))
if (!(msg_->flags () & msg_t::more) && !msg_->is_identity ())
msgs_read++;
if (lwm > 0 && msgs_read % lwm == 0)
@ -184,8 +184,9 @@ bool zmq::pipe_t::write (msg_t *msg_)
return false;
bool more = msg_->flags () & msg_t::more ? true : false;
const bool is_identity = msg_->is_identity ();
outpipe->write (*msg_, more);
if (!more)
if (!more && !is_identity)
msgs_written++;
return true;
@ -466,10 +467,10 @@ void zmq::pipe_t::hiccup ()
// Create new inpipe.
if (conflate)
inpipe = new (std::nothrow)
ypipe_t <msg_t, message_pipe_granularity> ();
ypipe_conflate_t <msg_t, message_pipe_granularity> ();
else
inpipe = new (std::nothrow)
ypipe_conflate_t <msg_t, message_pipe_granularity> ();
ypipe_t <msg_t, message_pipe_granularity> ();
alloc_assert (inpipe);
in_active = true;

View File

@ -114,6 +114,11 @@ void zmq::poll_t::stop ()
stopping = true;
}
int zmq::poll_t::max_fds ()
{
return -1;
}
void zmq::poll_t::loop ()
{
while (!stopping) {

View File

@ -59,6 +59,8 @@ namespace zmq
void start ();
void stop ();
static int max_fds ();
private:
// Main worker thread routine.

View File

@ -57,7 +57,8 @@
int zmq::proxy (
class socket_base_t *frontend_,
class socket_base_t *backend_,
class socket_base_t *capture_)
class socket_base_t *capture_,
class socket_base_t *control_)
{
msg_t msg;
int rc = msg.init ();
@ -71,14 +72,63 @@ int zmq::proxy (
size_t moresz;
zmq_pollitem_t items [] = {
{ frontend_, 0, ZMQ_POLLIN, 0 },
{ backend_, 0, ZMQ_POLLIN, 0 }
{ backend_, 0, ZMQ_POLLIN, 0 },
{ control_, 0, ZMQ_POLLIN, 0 }
};
while (true) {
int qt_poll_items = (control_ ? 3 : 2);
// Proxy can be in these three states
enum {
active,
paused,
terminated
} state = active;
while (state != terminated) {
// Wait while there are either requests or replies to process.
rc = zmq_poll (&items [0], 2, -1);
rc = zmq_poll (&items [0], qt_poll_items, -1);
if (unlikely (rc < 0))
return -1;
// Process a control command if any
if (control_ && items [2].revents & ZMQ_POLLIN) {
rc = control_->recv (&msg, 0);
if (unlikely (rc < 0))
return -1;
moresz = sizeof more;
rc = control_->getsockopt (ZMQ_RCVMORE, &more, &moresz);
if (unlikely (rc < 0) || more)
return -1;
// Copy message to capture socket if any
if (capture_) {
msg_t ctrl;
int rc = ctrl.init ();
if (unlikely (rc < 0))
return -1;
rc = ctrl.copy (msg);
if (unlikely (rc < 0))
return -1;
rc = capture_->send (&ctrl, more? ZMQ_SNDMORE: 0);
if (unlikely (rc < 0))
return -1;
}
if (msg.size () == 5 && memcmp (msg.data (), "PAUSE", 5) == 0)
state = paused;
else
if (msg.size () == 6 && memcmp (msg.data (), "RESUME", 6) == 0)
state = active;
else
if (msg.size () == 9 && memcmp (msg.data (), "TERMINATE", 9) == 0)
state = terminated;
else {
// This is an API error, we should assert
puts ("E: invalid command sent to proxy");
zmq_assert (false);
}
}
// Process a request
if (items [0].revents & ZMQ_POLLIN) {
while (true) {

View File

@ -25,7 +25,8 @@ namespace zmq
int proxy (
class socket_base_t *frontend_,
class socket_base_t *backend_,
class socket_base_t *control_);
class socket_base_t *capture_,
class socket_base_t *control_ = NULL); // backward compatibility without this argument);
}
#endif

View File

@ -198,16 +198,16 @@ int zmq::req_t::xsetsockopt (int option_, const void *optval_, size_t optvallen_
bool is_int = (optvallen_ == sizeof (int));
int value = is_int? *((int *) optval_): 0;
switch (option_) {
case ZMQ_REQ_REQUEST_IDS:
case ZMQ_REQ_CORRELATE:
if (is_int && value >= 0) {
request_id_frames_enabled = (value != 0);
return 0;
}
break;
case ZMQ_REQ_STRICT:
case ZMQ_REQ_RELAXED:
if (is_int && value >= 0) {
strict = (value != 0);
strict = (value == 0);
return 0;
}
break;

View File

@ -225,6 +225,8 @@ int zmq::router_t::xsend (msg_t *msg_)
current_out->terminate (false);
int rc = msg_->close ();
errno_assert (rc == 0);
rc = msg_->init ();
errno_assert (rc == 0);
current_out = NULL;
return 0;
}

View File

@ -144,6 +144,11 @@ void zmq::select_t::stop ()
stopping = true;
}
int zmq::select_t::max_fds ()
{
return FD_SETSIZE;
}
void zmq::select_t::loop ()
{
while (!stopping) {

View File

@ -69,6 +69,8 @@ namespace zmq
void start ();
void stop ();
static int max_fds ();
private:
// Main worker thread routine.

View File

@ -96,8 +96,7 @@ zmq::session_base_t::~session_base_t ()
if (engine)
engine->terminate ();
if (addr)
delete addr;
delete addr;
}
void zmq::session_base_t::attach_pipe (pipe_t *pipe_)
@ -244,7 +243,7 @@ void zmq::session_base_t::read_activated (pipe_t *pipe_)
}
if (likely (pipe_ == pipe))
engine->activate_out ();
engine->restart_output ();
else
engine->zap_msg_available ();
}
@ -258,7 +257,7 @@ void zmq::session_base_t::write_activated (pipe_t *pipe_)
}
if (engine)
engine->activate_in ();
engine->restart_input ();
}
void zmq::session_base_t::hiccuped (pipe_t *)
@ -308,7 +307,6 @@ int zmq::session_base_t::zap_connect ()
zap_pipe->set_nodelay ();
zap_pipe->set_event_sink (this);
new_pipes [1]->set_nodelay ();
send_bind (peer.socket, new_pipes [1], false);
// Send empty identity if required by the peer.

View File

@ -77,16 +77,62 @@
#include <sys/socket.h>
#endif
#if !defined (ZMQ_HAVE_WINDOWS)
// Helper to sleep for specific number of milliseconds (or until signal)
//
static int sleep_ms (unsigned int ms_)
{
if (ms_ == 0)
return 0;
#if defined ZMQ_HAVE_WINDOWS
Sleep (ms_ > 0 ? ms_ : INFINITE);
return 0;
#elif defined ZMQ_HAVE_ANDROID
usleep (ms_ * 1000);
return 0;
#else
return usleep (ms_ * 1000);
#endif
}
// Helper to wait on close(), for non-blocking sockets, until it completes
// If EAGAIN is received, will sleep briefly (1-100ms) then try again, until
// the overall timeout is reached.
//
static int close_wait_ms (int fd_, unsigned int max_ms_ = 2000)
{
unsigned int ms_so_far = 0;
unsigned int step_ms = max_ms_ / 10;
if (step_ms < 1)
step_ms = 1;
if (step_ms > 100)
step_ms = 100;
int rc = 0; // do not sleep on first attempt
do
{
if (rc == -1 && errno == EAGAIN)
{
sleep_ms (step_ms);
ms_so_far += step_ms;
}
rc = close (fd_);
} while (ms_so_far < max_ms_ && rc == -1 && errno == EAGAIN);
return rc;
}
#endif
zmq::signaler_t::signaler_t ()
{
// Create the socketpair for signaling.
int rc = make_fdpair (&r, &w);
errno_assert (rc == 0);
// Set both fds to non-blocking mode.
unblock_socket (w);
unblock_socket (r);
if (make_fdpair (&r, &w) == 0) {
unblock_socket (w);
unblock_socket (r);
}
#ifdef HAVE_FORK
pid = getpid();
#endif
@ -95,7 +141,7 @@ zmq::signaler_t::signaler_t ()
zmq::signaler_t::~signaler_t ()
{
#if defined ZMQ_HAVE_EVENTFD
int rc = close (r);
int rc = close_wait_ms (r);
errno_assert (rc == 0);
#elif defined ZMQ_HAVE_WINDOWS
struct linger so_linger = { 1, 0 };
@ -107,9 +153,9 @@ zmq::signaler_t::~signaler_t ()
rc = closesocket (r);
wsa_assert (rc != SOCKET_ERROR);
#else
int rc = close (w);
int rc = close_wait_ms (w);
errno_assert (rc == 0);
rc = close (r);
rc = close_wait_ms (r);
errno_assert (rc == 0);
#endif
}
@ -184,8 +230,7 @@ int zmq::signaler_t::wait (int timeout_)
return -1;
}
#ifdef HAVE_FORK
if (unlikely(pid != getpid()))
{
if (unlikely(pid != getpid())) {
// we have forked and the file descriptor is closed. Emulate an interupt
// response.
//printf("Child process %d signaler_t::wait returning simulating interrupt #2\n", getpid());
@ -266,42 +311,30 @@ void zmq::signaler_t::recv ()
#ifdef HAVE_FORK
void zmq::signaler_t::forked()
{
int oldr = r;
#if !defined ZMQ_HAVE_EVENTFD
int oldw = w;
#endif
// replace the file descriptors created in the parent with new
// ones, and close the inherited ones
make_fdpair(&r, &w);
#if defined ZMQ_HAVE_EVENTFD
int rc = close (oldr);
errno_assert (rc == 0);
#else
int rc = close (oldw);
errno_assert (rc == 0);
rc = close (oldr);
errno_assert (rc == 0);
#endif
// Close file descriptors created in the parent and create new pair
close (r);
close (w);
make_fdpair (&r, &w);
}
#endif
// Returns -1 if we could not make the socket pair successfully
int zmq::signaler_t::make_fdpair (fd_t *r_, fd_t *w_)
{
#if defined ZMQ_HAVE_EVENTFD
// Create eventfd object.
fd_t fd = eventfd (0, 0);
errno_assert (fd != -1);
*w_ = fd;
*r_ = fd;
return 0;
if (fd == -1) {
errno_assert (errno == ENFILE || errno == EMFILE);
*w_ = *r_ = -1;
return -1;
}
else {
*w_ = *r_ = fd;
return 0;
}
#elif defined ZMQ_HAVE_WINDOWS
#if !defined _WIN32_WCE
# if !defined _WIN32_WCE
// Windows CE does not manage security attributes
SECURITY_DESCRIPTOR sd;
SECURITY_ATTRIBUTES sa;
@ -313,7 +346,7 @@ int zmq::signaler_t::make_fdpair (fd_t *r_, fd_t *w_)
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = &sd;
#endif
# endif
// This function has to be in a system-wide critical section so that
// two instances of the library don't accidentally create signaler
@ -322,20 +355,17 @@ int zmq::signaler_t::make_fdpair (fd_t *r_, fd_t *w_)
// Note that if the event object already exists, the CreateEvent requests
// EVENT_ALL_ACCESS access right. If this fails, we try to open
// the event object asking for SYNCHRONIZE access only.
#if !defined _WIN32_WCE
# if !defined _WIN32_WCE
HANDLE sync = CreateEvent (&sa, FALSE, TRUE, TEXT ("Global\\zmq-signaler-port-sync"));
#else
# else
HANDLE sync = CreateEvent (NULL, FALSE, TRUE, TEXT ("Global\\zmq-signaler-port-sync"));
#endif
# endif
if (sync == NULL && GetLastError () == ERROR_ACCESS_DENIED)
sync = OpenEvent (SYNCHRONIZE | EVENT_MODIFY_STATE, FALSE, TEXT ("Global\\zmq-signaler-port-sync"));
sync = OpenEvent (SYNCHRONIZE | EVENT_MODIFY_STATE,
FALSE, TEXT ("Global\\zmq-signaler-port-sync"));
win_assert (sync != NULL);
// Enter the critical section.
DWORD dwrc = WaitForSingleObject (sync, INFINITE);
zmq_assert (dwrc == WAIT_OBJECT_0);
// Windows has no 'socketpair' function. CreatePipe is no good as pipe
// handles cannot be polled on. Here we create the socketpair by hand.
*w_ = INVALID_SOCKET;
@ -356,58 +386,51 @@ int zmq::signaler_t::make_fdpair (fd_t *r_, fd_t *w_)
(char *)&tcp_nodelay, sizeof (tcp_nodelay));
wsa_assert (rc != SOCKET_ERROR);
// Bind listening socket to signaler port.
// Init sockaddr to signaler port.
struct sockaddr_in addr;
memset (&addr, 0, sizeof (addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
addr.sin_port = htons (signaler_port);
rc = bind (listener, (const struct sockaddr*) &addr, sizeof (addr));
wsa_assert (rc != SOCKET_ERROR);
// Listen for incomming connections.
rc = listen (listener, 1);
wsa_assert (rc != SOCKET_ERROR);
// Create the writer socket.
*w_ = WSASocket (AF_INET, SOCK_STREAM, 0, NULL, 0, 0);
*w_ = open_socket (AF_INET, SOCK_STREAM, 0);
wsa_assert (*w_ != INVALID_SOCKET);
#if !defined _WIN32_WCE
// On Windows, preventing sockets to be inherited by child processes.
BOOL brc = SetHandleInformation ((HANDLE) *w_, HANDLE_FLAG_INHERIT, 0);
win_assert (brc);
#else
BOOL brc;
#endif
// Set TCP_NODELAY on writer socket.
rc = setsockopt (*w_, IPPROTO_TCP, TCP_NODELAY,
(char *)&tcp_nodelay, sizeof (tcp_nodelay));
wsa_assert (rc != SOCKET_ERROR);
// Connect writer to the listener.
rc = connect (*w_, (struct sockaddr*) &addr, sizeof (addr));
// Enter the critical section.
DWORD dwrc = WaitForSingleObject (sync, INFINITE);
zmq_assert (dwrc == WAIT_OBJECT_0);
// Save errno if connection fails
int conn_errno = 0;
if (rc == SOCKET_ERROR) {
conn_errno = WSAGetLastError ();
} else {
// Accept connection from writer.
// Bind listening socket to signaler port.
rc = bind (listener, (const struct sockaddr*) &addr, sizeof (addr));
// Listen for incoming connections.
if (rc != SOCKET_ERROR)
rc = listen (listener, 1);
// Connect writer to the listener.
if (rc != SOCKET_ERROR)
rc = connect (*w_, (struct sockaddr*) &addr, sizeof (addr));
// Accept connection from writer.
if (rc != SOCKET_ERROR)
*r_ = accept (listener, NULL, NULL);
if (*r_ == INVALID_SOCKET) {
conn_errno = WSAGetLastError ();
}
}
// Save errno if error occurred in bind/listen/connect/accept.
int saved_errno = 0;
if (*r_ == INVALID_SOCKET)
saved_errno = WSAGetLastError ();
// We don't need the listening socket anymore. Close it.
rc = closesocket (listener);
wsa_assert (rc != SOCKET_ERROR);
closesocket (listener);
// Exit the critical section.
brc = SetEvent (sync);
BOOL brc = SetEvent (sync);
win_assert (brc != 0);
// Release the kernel object
@ -415,27 +438,22 @@ int zmq::signaler_t::make_fdpair (fd_t *r_, fd_t *w_)
win_assert (brc != 0);
if (*r_ != INVALID_SOCKET) {
#if !defined _WIN32_WCE
# if !defined _WIN32_WCE
// On Windows, preventing sockets to be inherited by child processes.
brc = SetHandleInformation ((HANDLE) *r_, HANDLE_FLAG_INHERIT, 0);
win_assert (brc);
#endif
# endif
return 0;
} else {
}
else {
// Cleanup writer if connection failed
rc = closesocket (*w_);
wsa_assert (rc != SOCKET_ERROR);
*w_ = INVALID_SOCKET;
if (*w_ != INVALID_SOCKET) {
rc = closesocket (*w_);
wsa_assert (rc != SOCKET_ERROR);
*w_ = INVALID_SOCKET;
}
// Set errno from saved value
errno = wsa_error_to_errno (conn_errno);
// Ideally, we would return errno to the caller signaler_t()
// Unfortunately, it uses errno_assert() which gives "Unknown error"
// We might as well assert here and print the actual error message
wsa_assert_no (conn_errno);
errno = wsa_error_to_errno (saved_errno);
return -1;
}
@ -463,7 +481,7 @@ int zmq::signaler_t::make_fdpair (fd_t *r_, fd_t *w_)
rc = setsockopt (listener, IPPROTO_TCP, TCP_NODELACK, &on, sizeof (on));
errno_assert (rc != -1);
rc = bind(listener, (struct sockaddr*) &lcladdr, sizeof (lcladdr));
rc = bind (listener, (struct sockaddr*) &lcladdr, sizeof (lcladdr));
errno_assert (rc != -1);
socklen_t lcladdr_len = sizeof (lcladdr);
@ -493,15 +511,20 @@ int zmq::signaler_t::make_fdpair (fd_t *r_, fd_t *w_)
return 0;
#else // All other implementations support socketpair()
#else
// All other implementations support socketpair()
int sv [2];
int rc = socketpair (AF_UNIX, SOCK_STREAM, 0, sv);
errno_assert (rc == 0);
*w_ = sv [0];
*r_ = sv [1];
return 0;
if (rc == -1) {
errno_assert (errno == ENFILE || errno == EMFILE);
*w_ = *r_ = -1;
return -1;
}
else {
*w_ = sv [0];
*r_ = sv [1];
return 0;
}
#endif
}

View File

@ -58,7 +58,8 @@ namespace zmq
// to pass the signals.
static int make_fdpair (fd_t *r_, fd_t *w_);
// Underlying write & read file descriptor.
// Underlying write & read file descriptor
// Will be -1 if we exceeded number of available handles
fd_t w;
fd_t r;
@ -74,7 +75,6 @@ namespace zmq
void close_internal();
#endif
};
}
#endif

View File

@ -79,47 +79,49 @@ zmq::socket_base_t *zmq::socket_base_t::create (int type_, class ctx_t *parent_,
{
socket_base_t *s = NULL;
switch (type_) {
case ZMQ_PAIR:
s = new (std::nothrow) pair_t (parent_, tid_, sid_);
break;
case ZMQ_PUB:
s = new (std::nothrow) pub_t (parent_, tid_, sid_);
break;
case ZMQ_SUB:
s = new (std::nothrow) sub_t (parent_, tid_, sid_);
break;
case ZMQ_REQ:
s = new (std::nothrow) req_t (parent_, tid_, sid_);
break;
case ZMQ_REP:
s = new (std::nothrow) rep_t (parent_, tid_, sid_);
break;
case ZMQ_DEALER:
s = new (std::nothrow) dealer_t (parent_, tid_, sid_);
break;
case ZMQ_ROUTER:
s = new (std::nothrow) router_t (parent_, tid_, sid_);
break;
case ZMQ_PULL:
s = new (std::nothrow) pull_t (parent_, tid_, sid_);
break;
case ZMQ_PUSH:
s = new (std::nothrow) push_t (parent_, tid_, sid_);
break;
case ZMQ_XPUB:
s = new (std::nothrow) xpub_t (parent_, tid_, sid_);
break;
case ZMQ_XSUB:
s = new (std::nothrow) xsub_t (parent_, tid_, sid_);
break;
case ZMQ_STREAM:
s = new (std::nothrow) stream_t (parent_, tid_, sid_);
break;
default:
errno = EINVAL;
return NULL;
case ZMQ_PAIR:
s = new (std::nothrow) pair_t (parent_, tid_, sid_);
break;
case ZMQ_PUB:
s = new (std::nothrow) pub_t (parent_, tid_, sid_);
break;
case ZMQ_SUB:
s = new (std::nothrow) sub_t (parent_, tid_, sid_);
break;
case ZMQ_REQ:
s = new (std::nothrow) req_t (parent_, tid_, sid_);
break;
case ZMQ_REP:
s = new (std::nothrow) rep_t (parent_, tid_, sid_);
break;
case ZMQ_DEALER:
s = new (std::nothrow) dealer_t (parent_, tid_, sid_);
break;
case ZMQ_ROUTER:
s = new (std::nothrow) router_t (parent_, tid_, sid_);
break;
case ZMQ_PULL:
s = new (std::nothrow) pull_t (parent_, tid_, sid_);
break;
case ZMQ_PUSH:
s = new (std::nothrow) push_t (parent_, tid_, sid_);
break;
case ZMQ_XPUB:
s = new (std::nothrow) xpub_t (parent_, tid_, sid_);
break;
case ZMQ_XSUB:
s = new (std::nothrow) xsub_t (parent_, tid_, sid_);
break;
case ZMQ_STREAM:
s = new (std::nothrow) stream_t (parent_, tid_, sid_);
break;
default:
errno = EINVAL;
return NULL;
}
if (s->mailbox.get_fd () == retired_fd)
return NULL;
alloc_assert (s);
return s;
}
@ -468,8 +470,20 @@ int zmq::socket_base_t::connect (const char *addr_)
// Attach local end of the pipe to this socket object.
attach_pipe (new_pipes [0]);
if (!peer.socket)
{
if (!peer.socket) {
// The peer doesn't exist yet so we don't know whether
// to send the identity message or not. To resolve this,
// we always send our identity and drop it later if
// the peer doesn't expect it.
msg_t id;
rc = id.init_size (options.identity_size);
errno_assert (rc == 0);
memcpy (id.data (), options.identity, options.identity_size);
id.set_flags (msg_t::identity);
bool written = new_pipes [0]->write (&id);
zmq_assert (written);
new_pipes [0]->flush ();
endpoint_t endpoint = {this, options};
pending_connection_t pending_connection = {endpoint, new_pipes [0], new_pipes [1]};
pend_connection (addr_, pending_connection);

View File

@ -68,14 +68,13 @@ zmq::stream_engine_t::stream_engine_t (fd_t fd_, const options_t &options_,
options (options_),
endpoint (endpoint_),
plugged (false),
terminating (false),
read_msg (&stream_engine_t::read_identity),
write_msg (&stream_engine_t::write_identity),
io_error (false),
subscription_required (false),
mechanism (NULL),
input_paused (false),
output_paused (false),
input_stopped (false),
output_stopped (false),
socket (NULL)
{
int rc = tx_msg.init ();
@ -114,12 +113,9 @@ zmq::stream_engine_t::~stream_engine_t ()
int rc = tx_msg.close ();
errno_assert (rc == 0);
if (encoder != NULL)
delete encoder;
if (decoder != NULL)
delete decoder;
if (mechanism != NULL)
delete mechanism;
delete encoder;
delete decoder;
delete mechanism;
}
void zmq::stream_engine_t::plug (io_thread_t *io_thread_,
@ -186,11 +182,6 @@ void zmq::stream_engine_t::unplug ()
void zmq::stream_engine_t::terminate ()
{
if (!terminating && encoder && encoder->has_data ()) {
// Give io_thread a chance to send in the buffer
terminating = true;
return;
}
unplug ();
delete this;
}
@ -207,7 +198,7 @@ void zmq::stream_engine_t::in_event ()
zmq_assert (decoder);
// If there has been an I/O error, stop polling.
if (input_paused) {
if (input_stopped) {
rm_fd (handle);
io_error = true;
return;
@ -220,17 +211,22 @@ void zmq::stream_engine_t::in_event ()
// Note that buffer can be arbitrarily large. However, we assume
// the underlying TCP layer has fixed buffer size and thus the
// number of bytes read will be always limited.
decoder->get_buffer (&inpos, &insize);
const int bytes_read = read (inpos, insize);
size_t bufsize = 0;
decoder->get_buffer (&inpos, &bufsize);
// Check whether the peer has closed the connection.
if (bytes_read == -1) {
int const rc = read (inpos, bufsize);
if (rc == 0) {
error ();
return;
}
if (rc == -1) {
if (errno != EAGAIN)
error ();
return;
}
// Adjust input size
insize = static_cast <size_t> (bytes_read);
insize = static_cast <size_t> (rc);
}
int rc = 0;
@ -255,7 +251,7 @@ void zmq::stream_engine_t::in_event ()
error ();
return;
}
input_paused = true;
input_stopped = true;
reset_pollin (handle);
}
@ -294,7 +290,7 @@ void zmq::stream_engine_t::out_event ()
// If there is no data to send, stop polling for output.
if (outsize == 0) {
output_paused = true;
output_stopped = true;
reset_pollout (handle);
return;
}
@ -312,8 +308,6 @@ void zmq::stream_engine_t::out_event ()
// this is necessary to prevent losing incoming messages.
if (nbytes == -1) {
reset_pollout (handle);
if (unlikely (terminating))
terminate ();
return;
}
@ -325,20 +319,16 @@ void zmq::stream_engine_t::out_event ()
if (unlikely (handshaking))
if (outsize == 0)
reset_pollout (handle);
if (unlikely (terminating))
if (outsize == 0)
terminate ();
}
void zmq::stream_engine_t::activate_out ()
void zmq::stream_engine_t::restart_output ()
{
if (unlikely (io_error))
return;
if (likely (output_paused)) {
if (likely (output_stopped)) {
set_pollout (handle);
output_paused = false;
output_stopped = false;
}
// Speculative write: The assumption is that at the moment new message
@ -348,9 +338,9 @@ void zmq::stream_engine_t::activate_out ()
out_event ();
}
void zmq::stream_engine_t::activate_in ()
void zmq::stream_engine_t::restart_input ()
{
zmq_assert (input_paused);
zmq_assert (input_stopped);
zmq_assert (session != NULL);
zmq_assert (decoder != NULL);
@ -382,7 +372,7 @@ void zmq::stream_engine_t::activate_in ()
if (rc == -1 || io_error)
error ();
else {
input_paused = false;
input_stopped = false;
set_pollin (handle);
session->flush ();
@ -399,12 +389,15 @@ bool zmq::stream_engine_t::handshake ()
while (greeting_bytes_read < greeting_size) {
const int n = read (greeting_recv + greeting_bytes_read,
greeting_size - greeting_bytes_read);
if (n == -1) {
if (n == 0) {
error ();
return false;
}
if (n == 0)
if (n == -1) {
if (errno != EAGAIN)
error ();
return false;
}
greeting_bytes_read += n;
@ -483,6 +476,13 @@ bool zmq::stream_engine_t::handshake ()
// header data away.
const size_t header_size = options.identity_size + 1 >= 255 ? 10 : 2;
unsigned char tmp [10], *bufferp = tmp;
// Prepare the identity message and load it into encoder.
// Then consume bytes we have already sent to the peer.
const int rc = tx_msg.init_size (options.identity_size);
zmq_assert (rc == 0);
memcpy (tx_msg.data (), options.identity, options.identity_size);
encoder->load_msg (&tx_msg);
size_t buffer_size = encoder->encode (&bufferp, header_size);
zmq_assert (buffer_size == header_size);
@ -495,6 +495,13 @@ bool zmq::stream_engine_t::handshake ()
// message into the incoming message stream.
if (options.type == ZMQ_PUB || options.type == ZMQ_XPUB)
subscription_required = true;
// We are sending our identity now and the next message
// will come from the socket.
read_msg = &stream_engine_t::pull_msg_from_session;
// We are expecting identity message.
write_msg = &stream_engine_t::write_identity;
}
else
if (greeting_recv [revision_pos] == ZMTP_1_0) {
@ -523,20 +530,23 @@ bool zmq::stream_engine_t::handshake ()
in_batch_size, options.maxmsgsize);
alloc_assert (decoder);
if (memcmp (greeting_recv + 12, "NULL\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) == 0) {
if (options.mechanism == ZMQ_NULL
&& memcmp (greeting_recv + 12, "NULL\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) == 0) {
mechanism = new (std::nothrow)
null_mechanism_t (session, peer_address, options);
alloc_assert (mechanism);
}
else
if (memcmp (greeting_recv + 12, "PLAIN\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) == 0) {
if (options.mechanism == ZMQ_PLAIN
&& memcmp (greeting_recv + 12, "PLAIN\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) == 0) {
mechanism = new (std::nothrow)
plain_mechanism_t (session, peer_address, options);
alloc_assert (mechanism);
}
#ifdef HAVE_LIBSODIUM
else
if (memcmp (greeting_recv + 12, "CURVE\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) == 0) {
if (options.mechanism == ZMQ_CURVE
&& memcmp (greeting_recv + 12, "CURVE\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) == 0) {
if (options.as_server)
mechanism = new (std::nothrow)
curve_server_t (session, peer_address, options);
@ -617,8 +627,8 @@ int zmq::stream_engine_t::process_handshake_command (msg_t *msg_)
if (rc == 0) {
if (mechanism->is_handshake_complete ())
mechanism_ready ();
if (output_paused)
activate_out ();
if (output_stopped)
restart_output ();
}
return rc;
@ -633,10 +643,10 @@ void zmq::stream_engine_t::zap_msg_available ()
error ();
return;
}
if (input_paused)
activate_in ();
if (output_paused)
activate_out ();
if (input_stopped)
restart_input ();
if (output_stopped)
restart_output ();
}
void zmq::stream_engine_t::mechanism_ready ()
@ -652,6 +662,7 @@ void zmq::stream_engine_t::mechanism_ready ()
return;
}
errno_assert (rc == 0);
session->flush ();
}
read_msg = &stream_engine_t::pull_and_encode;
@ -787,58 +798,45 @@ int zmq::stream_engine_t::read (void *data_, size_t size_)
{
#ifdef ZMQ_HAVE_WINDOWS
int nbytes = recv (s, (char*) data_, (int) size_, 0);
const int rc = recv (s, (char*) data_, (int) size_, 0);
// If not a single byte can be read from the socket in non-blocking mode
// we'll get an error (this may happen during the speculative read).
if (nbytes == SOCKET_ERROR && WSAGetLastError () == WSAEWOULDBLOCK)
return 0;
if (rc == SOCKET_ERROR) {
if (WSAGetLastError () == WSAEWOULDBLOCK)
errno = EAGAIN;
else {
wsa_assert (WSAGetLastError () == WSAENETDOWN
|| WSAGetLastError () == WSAENETRESET
|| WSAGetLastError () == WSAECONNABORTED
|| WSAGetLastError () == WSAETIMEDOUT
|| WSAGetLastError () == WSAECONNRESET
|| WSAGetLastError () == WSAECONNREFUSED
|| WSAGetLastError () == WSAENOTCONN);
errno = wsa_error_to_errno (WSAGetLastError ());
}
}
// Connection failure.
if (nbytes == SOCKET_ERROR && (
WSAGetLastError () == WSAENETDOWN ||
WSAGetLastError () == WSAENETRESET ||
WSAGetLastError () == WSAECONNABORTED ||
WSAGetLastError () == WSAETIMEDOUT ||
WSAGetLastError () == WSAECONNRESET ||
WSAGetLastError () == WSAECONNREFUSED ||
WSAGetLastError () == WSAENOTCONN))
return -1;
wsa_assert (nbytes != SOCKET_ERROR);
// Orderly shutdown by the other peer.
if (nbytes == 0)
return -1;
return nbytes;
return rc == SOCKET_ERROR? -1: rc;
#else
ssize_t nbytes = recv (s, data_, size_, 0);
const ssize_t rc = recv (s, data_, size_, 0);
// Several errors are OK. When speculative read is being done we may not
// be able to read a single byte from the socket. Also, SIGSTOP issued
// by a debugging tool can result in EINTR error.
if (nbytes == -1 && (errno == EAGAIN || errno == EWOULDBLOCK ||
errno == EINTR))
return 0;
// Signalise peer failure.
if (nbytes == -1) {
if (rc == -1) {
errno_assert (errno != EBADF
&& errno != EFAULT
&& errno != EINVAL
&& errno != ENOMEM
&& errno != ENOTSOCK);
return -1;
if (errno == EWOULDBLOCK || errno == EINTR)
errno = EAGAIN;
}
// Orderly shutdown by the peer.
if (nbytes == 0)
return -1;
return static_cast <int> (nbytes);
return static_cast <int> (rc);
#endif
}

View File

@ -60,8 +60,8 @@ namespace zmq
void plug (zmq::io_thread_t *io_thread_,
zmq::session_base_t *session_);
void terminate ();
void activate_in ();
void activate_out ();
void restart_input ();
void restart_output ();
void zap_msg_available ();
// i_poll_events interface implementation.
@ -87,10 +87,9 @@ namespace zmq
// of error or orderly shutdown by the other peer -1 is returned.
int write (const void *data_, size_t size_);
// Reads data from the socket (up to 'size' bytes). Returns the number
// of bytes actually read (even zero is to be considered to be
// a success). In case of error or orderly shutdown by the other
// peer -1 is returned.
// Reads data from the socket (up to 'size' bytes).
// Returns the number of bytes actually read or -1 on error.
// Zero indicates the peer has closed the connection.
int read (void *data_, size_t size_);
int read_identity (msg_t *msg_);
@ -163,7 +162,6 @@ namespace zmq
std::string endpoint;
bool plugged;
bool terminating;
int (stream_engine_t::*read_msg) (msg_t *msg_);
@ -179,10 +177,10 @@ namespace zmq
mechanism_t *mechanism;
// True iff the engine couldn't consume the last decoded message.
bool input_paused;
bool input_stopped;
// True iff the engine doesn't have any message to encode.
bool output_paused;
bool output_stopped;
// Socket
zmq::socket_base_t *socket;

32
src/tcp.cpp Normal file → Executable file
View File

@ -94,44 +94,39 @@ 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_WINDOWS
if (keepalive_ != -1) {
tcp_keepalive keepalive_opts;
keepalive_opts.onoff = keepalive_;
keepalive_opts.keepalivetime = keepalive_idle_ != -1 ? keepalive_idle_ * 1000 : 7200000;
keepalive_opts.keepaliveinterval = keepalive_intvl_ != -1 ? keepalive_intvl_ * 1000 : 1000;
DWORD num_bytes_returned;
int rc = WSAIoctl(s_, SIO_KEEPALIVE_VALS, &keepalive_opts, sizeof(keepalive_opts), NULL, 0, &num_bytes_returned, NULL, NULL);
wsa_assert (rc != SOCKET_ERROR);
}
#else
#ifdef ZMQ_HAVE_SO_KEEPALIVE
if (keepalive_ != -1) {
int rc = setsockopt (s_, SOL_SOCKET, SO_KEEPALIVE, (char*) &keepalive_, sizeof (int));
#ifdef ZMQ_HAVE_WINDOWS
wsa_assert (rc != SOCKET_ERROR);
#else
errno_assert (rc == 0);
#endif
#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
@ -139,13 +134,10 @@ void zmq::tune_tcp_keepalives (fd_t s_, int keepalive_, int keepalive_cnt_, int
#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 // ZMQ_HAVE_SO_KEEPALIVE
#endif // ZMQ_HAVE_WINDOWS
}

View File

@ -48,8 +48,7 @@ zmq::trie_t::~trie_t ()
else
if (count > 1) {
for (unsigned short i = 0; i != count; ++i)
if (next.table [i])
delete next.table [i];
delete next.table [i];
free (next.table);
}
}

19
src/windows.hpp Normal file → Executable file
View File

@ -152,8 +152,6 @@
#define _WIN32_WINNT 0x0501
#endif
#include <windows.h>
#ifdef __MINGW32__
// Require Windows XP or higher with MinGW for getaddrinfo().
#if(_WIN32_WINNT >= 0x0501)
@ -164,8 +162,25 @@
#endif
#include <winsock2.h>
#include <windows.h>
#include <mswsock.h>
#if !defined __MINGW32__
#include <Mstcpip.h>
#endif
// Workaround missing Mstcpip.h in mingw32 (MinGW64 provides this)
// __MINGW64_VERSION_MAJOR is only defined (through inclusion of private _mingw.h via
// windows.h) in mingw-w64
#if defined __MINGW32__ && !defined SIO_KEEPALIVE_VALS && !defined __MINGW64_VERSION_MAJOR
struct tcp_keepalive {
u_long onoff;
u_long keepalivetime;
u_long keepaliveinterval;
};
#define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4)
#endif
#include <ws2tcpip.h>
#include <ipexport.h>
#if !defined _WIN32_WCE

View File

@ -72,8 +72,7 @@ namespace zmq
}
chunk_t *sc = spare_chunk.xchg (NULL);
if (sc)
free (sc);
free (sc);
}
// Returns reference to the front element of the queue.
@ -156,8 +155,7 @@ namespace zmq
// so for cache reasons we'll get rid of the spare and
// use 'o' as the spare.
chunk_t *cs = spare_chunk.xchg (o);
if (cs)
free (cs);
free (cs);
}
}

View File

@ -1016,7 +1016,7 @@ int zmq_poll (zmq_pollitem_t *items_, int nitems_, long timeout_)
// The proxy functionality
int zmq_proxy (void *frontend_, void *backend_, void *control_)
int zmq_proxy (void *frontend_, void *backend_, void *capture_)
{
if (!frontend_ || !backend_) {
errno = EFAULT;
@ -1025,6 +1025,19 @@ int zmq_proxy (void *frontend_, void *backend_, void *control_)
return zmq::proxy (
(zmq::socket_base_t*) frontend_,
(zmq::socket_base_t*) backend_,
(zmq::socket_base_t*) capture_);
}
int zmq_proxy_steerable (void *frontend_, void *backend_, void *capture_, void *control_)
{
if (!frontend_ || !backend_) {
errno = EFAULT;
return -1;
}
return zmq::proxy (
(zmq::socket_base_t*) frontend_,
(zmq::socket_base_t*) backend_,
(zmq::socket_base_t*) capture_,
(zmq::socket_base_t*) control_);
}

View File

@ -30,6 +30,10 @@
#else
#include "windows.hpp"
#endif
#ifdef HAVE_LIBSODIUM
# include <sodium.h>
#endif
void zmq_sleep (int seconds_)
{
@ -100,10 +104,14 @@ static uint8_t decoder [96] = {
// Encode a binary frame as a string; destination string MUST be at least
// size * 5 / 4 bytes long plus 1 byte for the null terminator. Returns
// dest. Size must be a multiple of 4.
// Returns NULL and sets errno = EINVAL for invalid input.
char *zmq_z85_encode (char *dest, uint8_t *data, size_t size)
{
assert (size % 4 == 0);
if (size % 4 != 0) {
errno = EINVAL;
return NULL;
}
unsigned int char_nbr = 0;
unsigned int byte_nbr = 0;
uint32_t value = 0;
@ -130,14 +138,19 @@ char *zmq_z85_encode (char *dest, uint8_t *data, size_t size)
// Decode an encoded string into a binary frame; dest must be at least
// strlen (string) * 4 / 5 bytes long. Returns dest. strlen (string)
// must be a multiple of 5.
// Returns NULL and sets errno = EINVAL for invalid input.
uint8_t *zmq_z85_decode (uint8_t *dest, char *string)
{
assert (strlen (string) % 5 == 0);
if (strlen (string) % 5 != 0) {
errno = EINVAL;
return NULL;
}
unsigned int byte_nbr = 0;
unsigned int char_nbr = 0;
unsigned int string_len = strlen (string);
uint32_t value = 0;
while (char_nbr < strlen (string)) {
while (char_nbr < string_len) {
// Accumulate value in base 85
value = value * 85 + decoder [(uint8_t) string [char_nbr++] - 32];
if (char_nbr % 5 == 0) {
@ -153,3 +166,35 @@ uint8_t *zmq_z85_decode (uint8_t *dest, char *string)
assert (byte_nbr == strlen (string) * 4 / 5);
return dest;
}
// --------------------------------------------------------------------------
// Generate a public/private keypair with libsodium.
// Generated keys will be 40 byte z85-encoded strings.
// Returns 0 on success, -1 on failure, setting errno.
// Sets errno = ENOTSUP in the absence of libsodium.
int zmq_curve_keypair (char *z85_public_key, char *z85_secret_key)
{
#ifdef HAVE_LIBSODIUM
# if crypto_box_PUBLICKEYBYTES != 32 \
|| crypto_box_SECRETKEYBYTES != 32
# error "libsodium not built correctly"
# endif
uint8_t public_key [32];
uint8_t secret_key [32];
int rc = crypto_box_keypair (public_key, secret_key);
// Is there a sensible errno to set here?
if (rc)
return rc;
zmq_z85_encode (z85_public_key, public_key, 32);
zmq_z85_encode (z85_secret_key, secret_key, 32);
return 0;
#else // requires libsodium
errno = ENOTSUP;
return -1;
#endif
}

View File

@ -14,12 +14,12 @@ noinst_PROGRAMS = test_system \
test_invalid_rep \
test_msg_flags \
test_connect_resolve \
test_connect_delay \
test_immediate \
test_last_endpoint \
test_term_endpoint \
test_linger \
test_monitor \
test_router_mandatory \
test_router_raw_empty \
test_probe_router \
test_stream \
test_disconnect_inproc \
@ -34,10 +34,13 @@ noinst_PROGRAMS = test_system \
test_spec_dealer \
test_spec_router \
test_spec_pushpull \
test_req_request_ids \
test_req_strict \
test_req_correlate \
test_req_relaxed \
test_conflate \
test_inproc_connect
test_inproc_connect \
test_issue_566 \
test_abstract_ipc \
test_many_sockets
if !ON_MINGW
noinst_PROGRAMS += test_shutdown_stress \
@ -56,14 +59,14 @@ test_hwm_SOURCES = test_hwm.cpp
test_reqrep_device_SOURCES = test_reqrep_device.cpp
test_sub_forward_SOURCES = test_sub_forward.cpp
test_invalid_rep_SOURCES = test_invalid_rep.cpp
test_linger_SOURCES = test_linger.cpp
test_msg_flags_SOURCES = test_msg_flags.cpp
test_connect_resolve_SOURCES = test_connect_resolve.cpp
test_connect_delay_SOURCES = test_connect_delay.cpp
test_immediate_SOURCES = test_immediate.cpp
test_last_endpoint_SOURCES = test_last_endpoint.cpp
test_term_endpoint_SOURCES = test_term_endpoint.cpp
test_monitor_SOURCES = test_monitor.cpp
test_router_mandatory_SOURCES = test_router_mandatory.cpp
test_router_raw_empty_SOURCES = test_router_raw_empty.cpp
test_probe_router_SOURCES = test_probe_router.cpp
test_stream_SOURCES = test_stream.cpp
test_disconnect_inproc_SOURCES = test_disconnect_inproc.cpp
@ -78,10 +81,13 @@ test_spec_rep_SOURCES = test_spec_rep.cpp
test_spec_dealer_SOURCES = test_spec_dealer.cpp
test_spec_router_SOURCES = test_spec_router.cpp
test_spec_pushpull_SOURCES = test_spec_pushpull.cpp
test_req_request_ids_SOURCES = test_req_request_ids.cpp
test_req_strict_SOURCES = test_req_strict.cpp
test_req_correlate_SOURCES = test_req_correlate.cpp
test_req_relaxed_SOURCES = test_req_relaxed.cpp
test_conflate_SOURCES = test_conflate.cpp
test_inproc_connect_SOURCES = test_inproc_connect.cpp
test_issue_566_SOURCES = test_issue_566.cpp
test_abstract_ipc_SOURCES = test_abstract_ipc.cpp
test_many_sockets_SOURCES = test_many_sockets.cpp
if !ON_MINGW
test_shutdown_stress_SOURCES = test_shutdown_stress.cpp
test_pair_ipc_SOURCES = test_pair_ipc.cpp testutil.hpp
@ -92,4 +98,7 @@ endif
# Run the test cases
TESTS = $(noinst_PROGRAMS)
XFAIL_TESTS = test_linger
if !ON_LINUX
XFAIL_TESTS = test_abstract_ipc
endif

View File

@ -0,0 +1,57 @@
/*
Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file
This file is part of 0MQ.
0MQ is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
0MQ is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
int main (void)
{
setup_test_environment();
void *ctx = zmq_ctx_new ();
assert (ctx);
void *sb = zmq_socket (ctx, ZMQ_PAIR);
assert (sb);
int rc = zmq_bind (sb, "ipc://@/tmp/tester");
assert (rc == 0);
char endpoint[200];
size_t size = sizeof(endpoint);
rc = zmq_getsockopt (sb, ZMQ_LAST_ENDPOINT, endpoint, &size);
assert (rc == 0);
rc = strncmp(endpoint, "ipc://@/tmp/tester", size);
assert (rc == 0);
void *sc = zmq_socket (ctx, ZMQ_PAIR);
assert (sc);
rc = zmq_connect (sc, "ipc://@/tmp/tester");
assert (rc == 0);
bounce (sb, sc);
rc = zmq_close (sc);
assert (rc == 0);
rc = zmq_close (sb);
assert (rc == 0);
rc = zmq_ctx_term (ctx);
assert (rc == 0);
return 0 ;
}

View File

@ -45,7 +45,6 @@ int main (int argc, char *argv [])
assert (rc == 0);
int message_count = 20;
for (int j = 0; j < message_count; ++j) {
rc = zmq_send(s_out, (void*)&j, sizeof(int), 0);
if (rc < 0) {
@ -53,15 +52,13 @@ int main (int argc, char *argv [])
return -1;
}
}
zmq_sleep (1);
msleep (SETTLE_TIME);
int payload_recved = 0;
rc = zmq_recv(s_in, (void*)&payload_recved, sizeof(int), 0);
rc = zmq_recv (s_in, (void*)&payload_recved, sizeof(int), 0);
assert (rc > 0);
assert (payload_recved == message_count - 1);
rc = zmq_close (s_in);
assert (rc == 0);

View File

@ -61,7 +61,7 @@ void test_ctx_shutdown()
void *receiver_thread = zmq_threadstart (&receiver, socket);
// Wait for thread to start up and block
zmq_sleep (1);
msleep (SETTLE_TIME);
// Shutdown context, if we used destroy here we would deadlock.
rc = zmq_ctx_shutdown (ctx);

View File

@ -33,7 +33,7 @@ int main (void)
assert (zmq_ctx_get (ctx, ZMQ_IPV6) == 0);
rc = zmq_ctx_set (ctx, ZMQ_IPV6, true);
assert (zmq_ctx_get (ctx, ZMQ_IPV6) == true);
assert (zmq_ctx_get (ctx, ZMQ_IPV6) == 1);
void *router = zmq_socket (ctx, ZMQ_ROUTER);
int ipv6;

View File

@ -117,7 +117,7 @@ int main (void)
// Set the key flag
val = 1;
rc = zmq_setsockopt (from, ZMQ_DELAY_ATTACH_ON_CONNECT, &val, sizeof(val));
rc = zmq_setsockopt (from, ZMQ_IMMEDIATE, &val, sizeof(val));
assert (rc == 0);
// Connect to the invalid socket
@ -170,9 +170,9 @@ int main (void)
rc = zmq_setsockopt (frontend, ZMQ_LINGER, &zero, sizeof (zero));
assert (rc == 0);
// Frontend connects to backend using DELAY_ATTACH_ON_CONNECT
// Frontend connects to backend using IMMEDIATE
int on = 1;
rc = zmq_setsockopt (frontend, ZMQ_DELAY_ATTACH_ON_CONNECT, &on, sizeof (on));
rc = zmq_setsockopt (frontend, ZMQ_IMMEDIATE, &on, sizeof (on));
assert (rc == 0);
rc = zmq_bind (backend, "tcp://127.0.0.1:5560");
assert (rc == 0);
@ -193,8 +193,7 @@ int main (void)
assert (rc == 0);
// Give time to process disconnect
// There's no way to do this except with a sleep
zmq_sleep(1);
msleep (SETTLE_TIME);
// Send a message, should fail
rc = zmq_send (frontend, "Hello", 5, ZMQ_DONTWAIT);

View File

@ -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.
@ -36,6 +36,40 @@ static void pusher (void *ctx)
assert (rc == 0);
}
static void simult_conn (void *payload)
{
// Pull out arguments - context followed by endpoint string
void* ctx = (void*)((void**)payload)[0];
char* endpt = (char*)((void**)payload)[1];
// Connect
void *connectSocket = zmq_socket (ctx, ZMQ_SUB);
assert (connectSocket);
int rc = zmq_connect (connectSocket, endpt);
assert (rc == 0);
// Cleanup
rc = zmq_close (connectSocket);
assert (rc == 0);
}
static void simult_bind (void *payload)
{
// Pull out arguments - context followed by endpoint string
void* ctx = (void*)((void**)payload)[0];
char* endpt = (char*)((void**)payload)[1];
// Bind
void *bindSocket = zmq_socket (ctx, ZMQ_PUB);
assert (bindSocket);
int rc = zmq_bind (bindSocket, endpt);
assert (rc == 0);
// Cleanup
rc = zmq_close (bindSocket);
assert (rc == 0);
}
void test_bind_before_connect()
{
void *ctx = zmq_ctx_new ();
@ -142,7 +176,7 @@ void test_connect_before_bind_pub_sub()
assert (rc == 0);
// Wait for pub-sub connection to happen
zmq_sleep (1);
msleep (SETTLE_TIME);
// Queue up some data, this not will be dropped
rc = zmq_send_const (connectSocket, "after", 6, 0);
@ -268,6 +302,42 @@ void test_multiple_threads()
assert (rc == 0);
}
void test_simultaneous_connect_bind_threads ()
{
const unsigned int no_of_times = 50;
void *ctx = zmq_ctx_new ();
assert (ctx);
void *threads[no_of_times*2];
void *thr_args[no_of_times][2];
char endpts[no_of_times][20];
// Set up thread arguments: context followed by endpoint string
for (unsigned int i = 0; i < no_of_times; ++i)
{
thr_args[i][0] = (void*) ctx;
thr_args[i][1] = (void*) endpts[i];
sprintf (endpts[i], "inproc://foo_%d", i);
}
// Spawn all threads as simultaneously as possible
for (unsigned int i = 0; i < no_of_times; ++i)
{
threads[i*2+0] = zmq_threadstart (&simult_conn, (void*)thr_args[i]);
threads[i*2+1] = zmq_threadstart (&simult_bind, (void*)thr_args[i]);
}
// Close all threads
for (unsigned int i = 0; i < no_of_times; ++i)
{
zmq_threadclose (threads[i*2+0]);
zmq_threadclose (threads[i*2+1]);
}
int rc = zmq_ctx_term (ctx);
assert (rc == 0);
}
void test_identity()
{
// Create the infrastructure
@ -324,6 +394,23 @@ void test_identity()
assert (rc == 0);
}
void test_connect_only ()
{
void *ctx = zmq_ctx_new ();
assert (ctx);
void *connectSocket = zmq_socket (ctx, ZMQ_PUSH);
assert (connectSocket);
int rc = zmq_connect (connectSocket, "inproc://a");
assert (rc == 0);
rc = zmq_close (connectSocket);
assert (rc == 0);
rc = zmq_ctx_term (ctx);
assert (rc == 0);
}
int main (void)
{
setup_test_environment();
@ -333,7 +420,9 @@ int main (void)
test_connect_before_bind_pub_sub ();
test_multiple_connects ();
test_multiple_threads ();
test_simultaneous_connect_bind_threads ();
test_identity ();
test_connect_only ();
return 0;
}

View File

@ -80,7 +80,7 @@ int main (void)
rc = zmq_bind (sb, "inproc://a");
assert (rc == 0);
zmq_sleep(1);
msleep (SETTLE_TIME);
void *sc = zmq_socket (ctx, ZMQ_PUSH);
rc = zmq_connect (sc, "inproc://a");

85
tests/test_issue_566.cpp Normal file
View File

@ -0,0 +1,85 @@
/*
Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file
This file is part of 0MQ.
0MQ is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
0MQ is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
// Issue 566 describes a problem in libzmq v4.0.0 where a dealer to router
// connection would fail randomly. The test works when the two sockets are
// on the same context, and failed when they were on separate contexts.
// Fixed by https://github.com/zeromq/libzmq/commit/be25cf.
int main (void)
{
setup_test_environment();
void *ctx1 = zmq_ctx_new ();
assert (ctx1);
void *ctx2 = zmq_ctx_new ();
assert (ctx2);
void *router = zmq_socket (ctx1, ZMQ_ROUTER);
int on = 1;
int rc = zmq_setsockopt (router, ZMQ_ROUTER_MANDATORY, &on, sizeof (on));
assert (rc == 0);
rc = zmq_bind (router, "tcp://127.0.0.1:5555");
assert (rc != -1);
// Repeat often enough to be sure this works as it should
for (int cycle = 0; cycle < 100; cycle++) {
// Create dealer with unique explicit identity
// We assume the router learns this out-of-band
void *dealer = zmq_socket (ctx2, ZMQ_DEALER);
char identity [10];
sprintf (identity, "%09d", cycle);
rc = zmq_setsockopt (dealer, ZMQ_IDENTITY, identity, 10);
assert (rc == 0);
int rcvtimeo = 1000;
rc = zmq_setsockopt (dealer, ZMQ_RCVTIMEO, &rcvtimeo, sizeof (int));
assert (rc == 0);
rc = zmq_connect (dealer, "tcp://127.0.0.1:5555");
assert (rc == 0);
// Router will try to send to dealer, at short intervals.
// It typically takes 2-5 msec for the connection to establish
// on a loopback interface, but we'll allow up to one second
// before failing the test (e.g. for running on a debugger or
// a very slow system).
for (int attempt = 0; attempt < 500; attempt++) {
zmq_poll (0, 0, 2);
rc = zmq_send (router, identity, 10, ZMQ_SNDMORE);
if (rc == -1 && errno == EHOSTUNREACH)
continue;
assert (rc == 10);
rc = zmq_send (router, "HELLO", 5, 0);
assert (rc == 5);
break;
}
uint8_t buffer [5];
rc = zmq_recv (dealer, buffer, 5, 0);
assert (rc == 5);
assert (memcmp (buffer, "HELLO", 5) == 0);
close_zero_linger (dealer);
}
zmq_close (router);
zmq_ctx_destroy (ctx1);
zmq_ctx_destroy (ctx2);
return 0;
}

View File

@ -0,0 +1,90 @@
/*
Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file
This file is part of 0MQ.
0MQ is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
0MQ is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include <zmq.h>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
void test_system_max ()
{
// Keep allocating sockets until we run out of system resources
const int no_of_sockets = 2 * 65536;
void *ctx = zmq_ctx_new ();
zmq_ctx_set (ctx, ZMQ_MAX_SOCKETS, no_of_sockets);
std::vector <void*> sockets;
while (true) {
void *socket = zmq_socket (ctx, ZMQ_PAIR);
if (!socket)
break;
sockets.push_back (socket);
}
assert ((int) sockets.size () < no_of_sockets);
// System is out of resources, further calls to zmq_socket should return NULL
for (unsigned int i = 0; i < 10; ++i) {
void *socket = zmq_socket (ctx, ZMQ_PAIR);
assert (socket == NULL);
}
// Clean up.
for (unsigned int i = 0; i < sockets.size (); ++i)
zmq_close (sockets [i]);
zmq_ctx_destroy (ctx);
}
void test_zmq_default_max ()
{
// Keep allocating sockets until we hit the default limit
void *ctx = zmq_ctx_new ();
std::vector<void*> sockets;
while (true) {
void *socket = zmq_socket (ctx, ZMQ_PAIR);
if (!socket)
break;
sockets.push_back (socket);
}
// We may stop sooner if system has fewer available sockets
assert (sockets.size () <= ZMQ_MAX_SOCKETS_DFLT);
// Further calls to zmq_socket should return NULL
for (unsigned int i = 0; i < 10; ++i) {
void *socket = zmq_socket (ctx, ZMQ_PAIR);
assert (socket == NULL);
}
// Clean up
for (unsigned int i = 0; i < sockets.size (); ++i)
zmq_close (sockets [i]);
zmq_ctx_destroy (ctx);
}
int main (void)
{
setup_test_environment ();
test_system_max ();
test_zmq_default_max ();
return 0;
}

View File

@ -211,7 +211,7 @@ int main (void)
rc = zmq_socket_monitor (req, "inproc://monitor.req", ZMQ_EVENT_ALL);
assert (rc == 0);
threads [1] = zmq_threadstart(&req_socket_monitor, ctx);
zmq_sleep(1);
msleep (SETTLE_TIME);
// Bind REQ and REP
rc = zmq_bind (rep, addr.c_str());
@ -238,8 +238,8 @@ int main (void)
rc = zmq_close (rep);
assert (rc == 0);
// Allow some time for detecting error states
zmq_sleep(1);
// Allow enough time for detecting error states
msleep (250);
// Close the REQ socket
rc = zmq_close (req);

View File

@ -32,7 +32,7 @@ int main (void)
assert (router);
int enabled = 1;
int rc = zmq_setsockopt (req, ZMQ_REQ_REQUEST_IDS, &enabled, sizeof (int));
int rc = zmq_setsockopt (req, ZMQ_REQ_CORRELATE, &enabled, sizeof (int));
assert (rc == 0);
int rcvtimeo = 100;

View File

@ -28,12 +28,11 @@ int main (void)
void *req = zmq_socket (ctx, ZMQ_REQ);
assert (req);
int disabled = 0;
int rc = zmq_setsockopt (req, ZMQ_REQ_STRICT, &disabled, sizeof (int));
int enabled = 1;
int rc = zmq_setsockopt (req, ZMQ_REQ_RELAXED, &enabled, sizeof (int));
assert (rc == 0);
int enabled = 1;
rc = zmq_setsockopt (req, ZMQ_REQ_REQUEST_IDS, &enabled, sizeof (int));
rc = zmq_setsockopt (req, ZMQ_REQ_CORRELATE, &enabled, sizeof (int));
assert (rc == 0);
rc = zmq_bind (req, "tcp://127.0.0.1:5555");
@ -55,7 +54,7 @@ int main (void)
// We have to give the connects time to finish otherwise the requests
// will not properly round-robin. We could alternatively connect the
// REQ sockets to the REP sockets.
zmq_sleep(1);
msleep (SETTLE_TIME);
// Case 1: Second send() before a reply arrives in a pipe.

View File

@ -0,0 +1,65 @@
/*
Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file
This file is part of 0MQ.
0MQ is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
0MQ is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
int main (void) {
setup_test_environment();
void *ctx = zmq_ctx_new();
assert(ctx);
void *router = zmq_socket(ctx, ZMQ_ROUTER);
assert(router);
void *dealer = zmq_socket(ctx, ZMQ_DEALER);
assert(dealer);
int one=1;
int rc = zmq_setsockopt(router, ZMQ_ROUTER_RAW, &one, sizeof(int));
assert(rc >= 0);
rc = zmq_setsockopt(router, ZMQ_ROUTER_MANDATORY, &one, sizeof(int));
assert(rc >= 0);
rc = zmq_bind(router, "tcp://127.0.0.1:5555");
rc = zmq_connect(dealer, "tcp://127.0.0.1:5555");
zmq_send(dealer, "", 0, 0);
zmq_msg_t ident, empty;
zmq_msg_init(&ident);
rc = zmq_msg_recv(&ident, router, 0);
assert(rc >= 0);
rc = zmq_msg_init_data(&empty, (void*)"", 0, NULL, NULL);
assert(rc >= 0);
rc = zmq_msg_send(&ident, router, ZMQ_SNDMORE);
assert(rc >= 0);
rc = zmq_msg_close(&ident);
assert(rc >= 0);
rc = zmq_msg_send(&empty, router, 0);
assert(rc >= 0);
// This close used to fail with Bad Address
rc = zmq_msg_close(&empty);
assert(rc >= 0);
close_zero_linger(dealer);
close_zero_linger(router);
zmq_ctx_term(ctx);
}

View File

@ -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.
@ -19,16 +19,15 @@
#include "testutil.hpp"
// Test keys from the zmq_curve man page
static char client_public [] = "Yne@$w-vo<fVvi]a<NY6T1ed:M$fCG*[IaLV{hID";
static char client_secret [] = "D:)Q[IlAW!ahhC2ac:9*A}h:p?([4%wOTJ%JR%cs";
static char server_public [] = "rq:rM>}U?@Lns47E1%kR.o@n%FcmmsL/@{H8]yf7";
static char server_secret [] = "JTKVSB%%)wK0E.X)V>+}o?pNmC{O&4W4b!Ni{Lh6";
// 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];
// --------------------------------------------------------------------------
// Encode a binary frame as a string; destination string MUST be at least
// size * 5 / 4 bytes long plus 1 byte for the null terminator. Returns
// dest. Size must be a multiple of 4.
// This methods receives and validates ZAP requestes (allowing or denying
// each client connection).
static void zap_handler (void *handler)
{
@ -47,7 +46,7 @@ static void zap_handler (void *handler)
int size = zmq_recv (handler, client_key, 32, 0);
assert (size == 32);
char client_key_text [41];
char client_key_text [40];
zmq_z85_encode (client_key_text, client_key, 32);
assert (streq (version, "1.0"));
@ -86,6 +85,13 @@ int main (void)
printf ("libsodium not installed, skipping CURVE test\n");
return 0;
#endif
// Generate new keypairs for this test
int rc = zmq_curve_keypair (client_public, client_secret);
assert (rc == 0);
rc = zmq_curve_keypair (server_public, server_secret);
assert (rc == 0);
setup_test_environment ();
void *ctx = zmq_ctx_new ();
assert (ctx);
@ -95,7 +101,7 @@ int main (void)
// where child thread does not start up fast enough.
void *handler = zmq_socket (ctx, ZMQ_REP);
assert (handler);
int rc = zmq_bind (handler, "inproc://zeromq.zap.01");
rc = zmq_bind (handler, "inproc://zeromq.zap.01");
assert (rc == 0);
void *zap_thread = zmq_threadstart (&zap_handler, handler);
@ -175,8 +181,9 @@ int main (void)
// Check CURVE security with bogus client credentials
// This must be caught by the ZAP handler
char bogus_public [] = "8)<]6{NT{}=MZBsH)i%l0k}y*^i#80n-Yf{I8Z+P";
char bogus_secret [] = "[m9E0TW2Mf?Ke3K>fuBGCrkBpc6aJbj4jv4451Nx";
char bogus_public [40];
char bogus_secret [40];
zmq_curve_keypair (bogus_public, bogus_secret);
client = zmq_socket (ctx, ZMQ_DEALER);
assert (client);
@ -191,6 +198,26 @@ int main (void)
expect_bounce_fail (server, client);
close_zero_linger (client);
// Check CURVE security with NULL client credentials
// This must be caught by the curve_server class, not passed to ZAP
client = zmq_socket (ctx, ZMQ_DEALER);
assert (client);
rc = zmq_connect (client, "tcp://localhost:9998");
assert (rc == 0);
expect_bounce_fail (server, client);
close_zero_linger (client);
// Check CURVE security with PLAIN client credentials
// This must be caught by the curve_server class, not passed to ZAP
client = zmq_socket (ctx, ZMQ_DEALER);
assert (client);
rc = zmq_setsockopt (client, ZMQ_PLAIN_USERNAME, "admin", 5);
assert (rc == 0);
rc = zmq_setsockopt (client, ZMQ_PLAIN_PASSWORD, "password", 8);
assert (rc == 0);
expect_bounce_fail (server, client);
close_zero_linger (client);
// Shutdown
rc = zmq_close (server);
assert (rc == 0);

View File

@ -57,6 +57,8 @@ void test_fair_queue_in (void *ctx)
s_send_seq (rep, "A", SEQ_END);
s_recv_seq (reqs [0], "A", SEQ_END);
// TODO: following test fails randomly on some boxes
#ifdef SOMEONE_FIXES_THIS
// send N requests
for (size_t peer = 0; peer < services; ++peer) {
char * str = strdup("A");
@ -69,12 +71,13 @@ void test_fair_queue_in (void *ctx)
for (size_t peer = 0; peer < services; ++peer) {
char * str = strdup("A");
str [0] += peer;
// Test fails here
s_recv_seq (rep, str, SEQ_END);
s_send_seq (rep, str, SEQ_END);
s_recv_seq (reqs [peer], str, SEQ_END);
free (str);
}
#endif
close_zero_linger (rep);
for (size_t peer = 0; peer < services; ++peer)

View File

@ -46,7 +46,7 @@ void test_round_robin_out (void *ctx)
// We have to give the connects time to finish otherwise the requests
// will not properly round-robin. We could alternatively connect the
// REQ sockets to the REP sockets.
zmq_sleep(1);
msleep (SETTLE_TIME);
// Send our peer-replies, and expect every REP it used once in order
for (size_t peer = 0; peer < services; peer++) {

View File

@ -89,20 +89,18 @@ test_stream_to_dealer (void)
assert (rc == sizeof (greeting));
// Now we expect the data from the DEALER socket
// First frame is, again, the identity of the connection
rc = zmq_msg_recv (&identity, stream, 0);
assert (rc > 0);
assert (zmq_msg_more (&identity));
// Second frame contains the rest of greeting along with
// the Ready command
// We want the rest of greeting along with the Ready command
int bytes_read = 0;
while (bytes_read < 97) {
// First frame is the identity of the connection (each time)
rc = zmq_msg_recv (&identity, stream, 0);
assert (rc > 0);
assert (zmq_msg_more (&identity));
// Second frame contains the next chunk of data
rc = zmq_recv (stream, buffer + bytes_read, 255 - bytes_read, 0);
assert (rc >= 0);
bytes_read += rc;
}
assert (rc == 97);
// First two bytes are major and minor version numbers.
assert (buffer [0] == 3); // ZMTP/3.0
@ -173,12 +171,12 @@ test_stream_to_stream (void)
void *server = zmq_socket (ctx, ZMQ_STREAM);
assert (server);
rc = zmq_bind (server, "tcp://127.0.0.1:8080");
rc = zmq_bind (server, "tcp://127.0.0.1:9080");
assert (rc == 0);
void *client = zmq_socket (ctx, ZMQ_STREAM);
assert (client);
rc = zmq_connect (client, "tcp://localhost:8080");
rc = zmq_connect (client, "tcp://localhost:9080");
assert (rc == 0);
// It would be less surprising to get an empty message instead
// of having to fetch the identity like this [PH 2013/06/27]

Some files were not shown because too many files have changed in this diff Show More