mirror of
https://github.com/zeromq/libzmq.git
synced 2025-08-11 04:58:16 +02:00
Compare commits
257 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
cf6e78ff82 | ||
![]() |
cfcebb3605 | ||
![]() |
509c746852 | ||
![]() |
10c54d122b | ||
![]() |
95019b00a0 | ||
![]() |
60568f2b30 | ||
![]() |
683059d3a2 | ||
![]() |
1a86783d42 | ||
![]() |
b2d444dc58 | ||
![]() |
95ba372e60 | ||
![]() |
4bba965d98 | ||
![]() |
8a9fece30a | ||
![]() |
399b71cbad | ||
![]() |
1c139eb42f | ||
![]() |
a1d1222dcc | ||
![]() |
812c2016b1 | ||
![]() |
3d13448a33 | ||
![]() |
b589fb98b8 | ||
![]() |
5cd98ee7cd | ||
![]() |
749dd8ce86 | ||
![]() |
9513148e27 | ||
![]() |
1dc65d360a | ||
![]() |
d8d9d17b21 | ||
![]() |
3d353659f7 | ||
![]() |
faaf455026 | ||
![]() |
b6e3e0f601 | ||
![]() |
77ef79e3b5 | ||
![]() |
f6968ecd41 | ||
![]() |
a19682307f | ||
![]() |
f584947368 | ||
![]() |
98df4b6182 | ||
![]() |
9be6c076cb | ||
![]() |
47227672ef | ||
![]() |
2d7614961c | ||
![]() |
87b35ded47 | ||
![]() |
93096d461c | ||
![]() |
b2cb9b9ec2 | ||
![]() |
f94de6e736 | ||
![]() |
eae9cbe72f | ||
![]() |
f024eef27c | ||
![]() |
73e59be321 | ||
![]() |
d73b240880 | ||
![]() |
88e56365ef | ||
![]() |
16b2db6062 | ||
![]() |
ce75ea7448 | ||
![]() |
7413afe6d6 | ||
![]() |
37203c4964 | ||
![]() |
30ba11d970 | ||
![]() |
85eac38e53 | ||
![]() |
c06ab77c3b | ||
![]() |
f35d0b6f8d | ||
![]() |
66d258f0e7 | ||
![]() |
1e6036d0df | ||
![]() |
1034bf90c0 | ||
![]() |
8454fddf5a | ||
![]() |
b4f4d23faf | ||
![]() |
bc7b0fd383 | ||
![]() |
678ad54a12 | ||
![]() |
03fadb92b4 | ||
![]() |
966c8930b0 | ||
![]() |
eaf732c25e | ||
![]() |
90dbc100c4 | ||
![]() |
2c754fc0a9 | ||
![]() |
dd478a0d20 | ||
![]() |
a6e85ded33 | ||
![]() |
2dc95612a8 | ||
![]() |
9766baa9d3 | ||
![]() |
d4d26b1cc0 | ||
![]() |
a6bd295210 | ||
![]() |
bb30e9efc7 | ||
![]() |
550c32ed10 | ||
![]() |
c639251c3e | ||
![]() |
65763041df | ||
![]() |
7a0425be9e | ||
![]() |
4f4723a684 | ||
![]() |
2394784995 | ||
![]() |
488cf5e04c | ||
![]() |
b69cf0d70d | ||
![]() |
75fbd4f8d6 | ||
![]() |
66b49261a8 | ||
![]() |
f3cc00b4af | ||
![]() |
dd488421c8 | ||
![]() |
2ae11cdc8d | ||
![]() |
e02fd0ce36 | ||
![]() |
612f6ac862 | ||
![]() |
e2d9aaeb88 | ||
![]() |
c83cc01e03 | ||
![]() |
c1b055a6d8 | ||
![]() |
0da2a0bed6 | ||
![]() |
3e65ddfce3 | ||
![]() |
25b692b109 | ||
![]() |
e0f718bbd2 | ||
![]() |
1ac53ed1f7 | ||
![]() |
7f08204e9f | ||
![]() |
2eb63360d6 | ||
![]() |
930ef37738 | ||
![]() |
e5473a7a69 | ||
![]() |
dd5603d6e9 | ||
![]() |
03dc70c350 | ||
![]() |
97292367eb | ||
![]() |
ebbbdf89cb | ||
![]() |
c7a7de12a3 | ||
![]() |
e655fd138d | ||
![]() |
0e147bb691 | ||
![]() |
4b9cd7764a | ||
![]() |
2493a99735 | ||
![]() |
d4f988649d | ||
![]() |
830e022987 | ||
![]() |
5a576d22db | ||
![]() |
89c762fb0a | ||
![]() |
0b11c3174e | ||
![]() |
129cb00d8f | ||
![]() |
6982e69da4 | ||
![]() |
63fe43a101 | ||
![]() |
3f3f9dcec2 | ||
![]() |
53bef03e7b | ||
![]() |
a37c198c7d | ||
![]() |
047bd130cf | ||
![]() |
5db0acb044 | ||
![]() |
845ee0c7bc | ||
![]() |
2ba0d159b5 | ||
![]() |
571c668fa2 | ||
![]() |
0552d9119b | ||
![]() |
3dc89feafc | ||
![]() |
97e1ecce22 | ||
![]() |
d958b675c7 | ||
![]() |
ff8f97e7d7 | ||
![]() |
75ba4c7292 | ||
![]() |
8b9a82476b | ||
![]() |
4363b75b4d | ||
![]() |
c022c048dc | ||
![]() |
78b741bd71 | ||
![]() |
ba7c065c3d | ||
![]() |
d743ddafda | ||
![]() |
84c0caf42e | ||
![]() |
e1939155ff | ||
![]() |
9ece2d322a | ||
![]() |
589bf436dd | ||
![]() |
e54e55835e | ||
![]() |
111c20dc22 | ||
![]() |
3a4896f4a3 | ||
![]() |
0855c28069 | ||
![]() |
737b6afc97 | ||
![]() |
8f85bafe37 | ||
![]() |
f72dbb35d5 | ||
![]() |
5d6e7a74c1 | ||
![]() |
30309d660e | ||
![]() |
e0c8a112a4 | ||
![]() |
f6293d257d | ||
![]() |
f33bdcf02e | ||
![]() |
fef24a8c1f | ||
![]() |
bfc3deb43a | ||
![]() |
dccf1dce1e | ||
![]() |
24311dee1b | ||
![]() |
27d20aacc7 | ||
![]() |
b2698474d2 | ||
![]() |
0465e9abe9 | ||
![]() |
885c816e57 | ||
![]() |
7f3d0995cd | ||
![]() |
f745e4ce64 | ||
![]() |
de239f358e | ||
![]() |
30f470eff5 | ||
![]() |
f0b69bba28 | ||
![]() |
60032ef330 | ||
![]() |
c663f37761 | ||
![]() |
806f57e7f6 | ||
![]() |
b22c2e4f8a | ||
![]() |
54a3ebcac6 | ||
![]() |
aede37e3e5 | ||
![]() |
2949f2dbc5 | ||
![]() |
28b7c991af | ||
![]() |
1c70e91c6f | ||
![]() |
c85fbaf22e | ||
![]() |
b58055794b | ||
![]() |
cb3c82271a | ||
![]() |
9bf10a83a1 | ||
![]() |
8efd7affc6 | ||
![]() |
bf97ea8ed8 | ||
![]() |
cd2afebd0a | ||
![]() |
2b8d86c24a | ||
![]() |
bd411bbf11 | ||
![]() |
573d7b0c0b | ||
![]() |
dcb9312ba6 | ||
![]() |
5490794666 | ||
![]() |
07d7cf69d0 | ||
![]() |
b24db36057 | ||
![]() |
4f2ac39d28 | ||
![]() |
a32c02ae47 | ||
![]() |
622e3b5476 | ||
![]() |
6c036b39ae | ||
![]() |
8cdff6fa2e | ||
![]() |
f8cebb460a | ||
![]() |
d62e7a0734 | ||
![]() |
a44bd65d03 | ||
![]() |
437e4070a3 | ||
![]() |
0bfcd4da2f | ||
![]() |
c852620f5f | ||
![]() |
ca122e9d01 | ||
![]() |
e7db680f5b | ||
![]() |
4fb7453925 | ||
![]() |
813166019e | ||
![]() |
127cd7585a | ||
![]() |
0666152b21 | ||
![]() |
9293153f71 | ||
![]() |
163aebbacf | ||
![]() |
80d657a2c5 | ||
![]() |
668f000cb1 | ||
![]() |
a570b18931 | ||
![]() |
5493d4d180 | ||
![]() |
b20573c841 | ||
![]() |
814b93e0cf | ||
![]() |
d723b08c13 | ||
![]() |
62fd6fa861 | ||
![]() |
a78ccf293f | ||
![]() |
d82ba6bd53 | ||
![]() |
9da52ddf59 | ||
![]() |
a69fa9ecde | ||
![]() |
facb96ffca | ||
![]() |
3c469d04c1 | ||
![]() |
870233522c | ||
![]() |
34471cd591 | ||
![]() |
453ceb65b4 | ||
![]() |
4d82544c34 | ||
![]() |
bd6bca7c82 | ||
![]() |
087ddac593 | ||
![]() |
d1b686b644 | ||
![]() |
4dc36c0dba | ||
![]() |
17d12a6be1 | ||
![]() |
89b97cbe59 | ||
![]() |
b0059211d5 | ||
![]() |
cd452d5019 | ||
![]() |
dd185e13bf | ||
![]() |
517601de10 | ||
![]() |
5e25b32c36 | ||
![]() |
a5152245bd | ||
![]() |
9cbcc49a4a | ||
![]() |
2d5bad96e3 | ||
![]() |
c99b727f6d | ||
![]() |
8a931a7554 | ||
![]() |
b04df2c530 | ||
![]() |
4df7cb043e | ||
![]() |
201454e866 | ||
![]() |
ad1bae2160 | ||
![]() |
77f394a681 | ||
![]() |
61d8bf9b11 | ||
![]() |
1e8e4d79c8 | ||
![]() |
c0c8ce5508 | ||
![]() |
66b1bc6d7f | ||
![]() |
f5ecc826d9 | ||
![]() |
a31fe9565a | ||
![]() |
2f4905500d | ||
![]() |
c10a3ec526 | ||
![]() |
e0676a2b26 | ||
![]() |
b411a3561d | ||
![]() |
4ce9b42405 | ||
![]() |
fef4fa8fc5 | ||
![]() |
4298f71cbf |
28
.gitignore
vendored
28
.gitignore
vendored
@ -22,6 +22,7 @@ autom4te.cache
|
|||||||
.*~
|
.*~
|
||||||
tools/curve_keygen.o
|
tools/curve_keygen.o
|
||||||
tools/curve_keygen
|
tools/curve_keygen
|
||||||
|
tests/test_issue_566
|
||||||
tests/test_ctx_destroy
|
tests/test_ctx_destroy
|
||||||
tests/test_term_endpoint
|
tests/test_term_endpoint
|
||||||
tests/test_system
|
tests/test_system
|
||||||
@ -43,7 +44,7 @@ tests/test_invalid_rep
|
|||||||
tests/test_msg_flags
|
tests/test_msg_flags
|
||||||
tests/test_ts_context
|
tests/test_ts_context
|
||||||
tests/test_connect_resolve
|
tests/test_connect_resolve
|
||||||
tests/test_connect_delay
|
tests/test_immediate
|
||||||
tests/test_term_endpoint
|
tests/test_term_endpoint
|
||||||
tests/test_router_mandatory
|
tests/test_router_mandatory
|
||||||
tests/test_disconnect_inproc
|
tests/test_disconnect_inproc
|
||||||
@ -60,14 +61,35 @@ tests/test_spec_pushpull
|
|||||||
tests/test_spec_rep
|
tests/test_spec_rep
|
||||||
tests/test_spec_req
|
tests/test_spec_req
|
||||||
tests/test_spec_router
|
tests/test_spec_router
|
||||||
tests/test_req_request_ids
|
tests/test_req_correlate
|
||||||
tests/test_req_strict
|
tests/test_req_relaxed
|
||||||
tests/test_fork
|
tests/test_fork
|
||||||
tests/test_conflate
|
tests/test_conflate
|
||||||
tests/test_inproc_connect
|
tests/test_inproc_connect
|
||||||
tests/test_linger
|
tests/test_linger
|
||||||
tests/test_security_null
|
tests/test_security_null
|
||||||
tests/test_security_plain
|
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_proxy_terminate
|
||||||
|
tests/test*.log
|
||||||
|
tests/test*.trs
|
||||||
src/platform.hpp*
|
src/platform.hpp*
|
||||||
src/stamp-h1
|
src/stamp-h1
|
||||||
perf/local_lat
|
perf/local_lat
|
||||||
|
@ -6,8 +6,11 @@ language: c
|
|||||||
before_script:
|
before_script:
|
||||||
|
|
||||||
# libsodium
|
# 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
|
- git clone git://github.com/jedisct1/libsodium.git
|
||||||
- cd libsodium
|
- cd libsodium
|
||||||
|
- git checkout e2a30a
|
||||||
- ./autogen.sh
|
- ./autogen.sh
|
||||||
- ./configure && make check
|
- ./configure && make check
|
||||||
- sudo make install
|
- sudo make install
|
||||||
@ -15,4 +18,4 @@ before_script:
|
|||||||
- cd ..
|
- cd ..
|
||||||
|
|
||||||
# Build and check libzmq
|
# Build and check libzmq
|
||||||
script: ./autogen.sh && ./configure && make && make check
|
script: ./autogen.sh && ./configure && make V=1 && make check
|
||||||
|
2
AUTHORS
2
AUTHORS
@ -20,6 +20,7 @@ Ben Gray <ben@benjamg.com>
|
|||||||
Bernd Prager <bernd@prager.ws>
|
Bernd Prager <bernd@prager.ws>
|
||||||
Bernd Melchers <melchers@ZEDAT.FU-Berlin.DE>
|
Bernd Melchers <melchers@ZEDAT.FU-Berlin.DE>
|
||||||
Bob Beaty <rbeaty@peak6.com>
|
Bob Beaty <rbeaty@peak6.com>
|
||||||
|
Brandon Carpenter <hashstat@yahoo.com>
|
||||||
Brian Buchanan <bwb@holo.org>
|
Brian Buchanan <bwb@holo.org>
|
||||||
Brett Cameron <Brett.Cameron@hp.com>
|
Brett Cameron <Brett.Cameron@hp.com>
|
||||||
Burak Arslan <burak-github@arskom.com.tr>
|
Burak Arslan <burak-github@arskom.com.tr>
|
||||||
@ -77,6 +78,7 @@ Philip Kovacs <phil@philkovacs.com>
|
|||||||
Pieter Hintjens <ph@imatix.com>
|
Pieter Hintjens <ph@imatix.com>
|
||||||
Piotr Trojanek <piotr.trojanek@gmail.com>
|
Piotr Trojanek <piotr.trojanek@gmail.com>
|
||||||
Richard Newton <richard_newton@waters.com>
|
Richard Newton <richard_newton@waters.com>
|
||||||
|
Rik van der Heijden <mail@rikvanderheijden.com>
|
||||||
Robert G. Jakabosky <bobby@sharedrealm.com>
|
Robert G. Jakabosky <bobby@sharedrealm.com>
|
||||||
Sebastian Otaegui <feniix@gmail.com>
|
Sebastian Otaegui <feniix@gmail.com>
|
||||||
Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de>
|
Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de>
|
||||||
|
@ -264,12 +264,15 @@ set(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/lib)
|
|||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
# platform specifics
|
# platform specifics
|
||||||
|
|
||||||
|
if(MSVC OR MINGW)
|
||||||
|
# NB: May require tweaking for highly connected applications.
|
||||||
|
add_definitions(-DFD_SETSIZE=1024)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
add_definitions(
|
add_definitions(
|
||||||
-DWIN32
|
-DWIN32
|
||||||
-DDLL_EXPORT
|
-DDLL_EXPORT
|
||||||
# NB: May require tweaking for highly connected applications.
|
|
||||||
-DFD_SETSIZE=1024
|
|
||||||
-D_CRT_SECURE_NO_WARNINGS)
|
-D_CRT_SECURE_NO_WARNINGS)
|
||||||
|
|
||||||
# Parallel make.
|
# Parallel make.
|
||||||
@ -365,7 +368,7 @@ if(MINGW)
|
|||||||
set(CMAKE_RC_COMPILER_INIT windres)
|
set(CMAKE_RC_COMPILER_INIT windres)
|
||||||
enable_language(RC)
|
enable_language(RC)
|
||||||
set(CMAKE_RC_COMPILE_OBJECT
|
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()
|
endmacro()
|
||||||
|
|
||||||
if( ${CMAKE_SYSTEM_PROCESSOR} MATCHES "i386"
|
if( ${CMAKE_SYSTEM_PROCESSOR} MATCHES "i386"
|
||||||
@ -412,10 +415,6 @@ foreach(source ${cxx-sources})
|
|||||||
list(APPEND sources ${CMAKE_CURRENT_SOURCE_DIR}/src/${source})
|
list(APPEND sources ${CMAKE_CURRENT_SOURCE_DIR}/src/${source})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
foreach(source ${rc-sources})
|
|
||||||
list(APPEND sources ${CMAKE_CURRENT_BINARY_DIR}/${source})
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
foreach(source ${rc-sources})
|
foreach(source ${rc-sources})
|
||||||
list(APPEND sources ${CMAKE_CURRENT_BINARY_DIR}/${source})
|
list(APPEND sources ${CMAKE_CURRENT_BINARY_DIR}/${source})
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/${source}.in ${CMAKE_CURRENT_BINARY_DIR}/${source})
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/${source}.in ${CMAKE_CURRENT_BINARY_DIR}/${source})
|
||||||
@ -526,6 +525,11 @@ else()
|
|||||||
OUTPUT_NAME "zmq"
|
OUTPUT_NAME "zmq"
|
||||||
PUBLIC_HEADER "${public_headers}")
|
PUBLIC_HEADER "${public_headers}")
|
||||||
endif()
|
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()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(libzmq ${CMAKE_THREAD_LIBS_INIT})
|
target_link_libraries(libzmq ${CMAKE_THREAD_LIBS_INIT})
|
||||||
@ -577,9 +581,9 @@ if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") # Why?
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
enable_testing()
|
enable_testing()
|
||||||
set(tests
|
set(tests
|
||||||
test_system
|
test_system
|
||||||
test_connect_delay
|
test_immediate
|
||||||
test_connect_resolve
|
test_connect_resolve
|
||||||
test_ctx_destroy
|
test_ctx_destroy
|
||||||
test_ctx_options
|
test_ctx_options
|
||||||
@ -592,8 +596,8 @@ set(tests
|
|||||||
test_pair_inproc
|
test_pair_inproc
|
||||||
test_pair_tcp
|
test_pair_tcp
|
||||||
test_probe_router
|
test_probe_router
|
||||||
test_req_request_ids
|
test_req_correlate
|
||||||
test_req_strict
|
test_req_relaxed
|
||||||
test_reqrep_device
|
test_reqrep_device
|
||||||
test_reqrep_inproc
|
test_reqrep_inproc
|
||||||
test_reqrep_tcp
|
test_reqrep_tcp
|
||||||
@ -610,14 +614,18 @@ set(tests
|
|||||||
test_sub_forward
|
test_sub_forward
|
||||||
test_term_endpoint
|
test_term_endpoint
|
||||||
test_timeo
|
test_timeo
|
||||||
test_inproc_connect)
|
test_inproc_connect
|
||||||
|
test_issue_566
|
||||||
|
test_many_sockets
|
||||||
|
test_proxy_terminate
|
||||||
|
)
|
||||||
if(NOT WIN32)
|
if(NOT WIN32)
|
||||||
list(APPEND tests
|
list(APPEND tests
|
||||||
test_monitor
|
test_monitor
|
||||||
test_pair_ipc
|
test_pair_ipc
|
||||||
test_reqrep_ipc
|
test_reqrep_ipc
|
||||||
test_stream)
|
test_stream)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
foreach(test ${tests})
|
foreach(test ${tests})
|
||||||
add_executable(${test} tests/${test}.cpp)
|
add_executable(${test} tests/${test}.cpp)
|
||||||
@ -630,7 +638,7 @@ foreach(test ${tests})
|
|||||||
add_test(NAME ${test} WORKING_DIRECTORY ${LIBRARY_OUTPUT_PATH} COMMAND ${test})
|
add_test(NAME ${test} WORKING_DIRECTORY ${LIBRARY_OUTPUT_PATH} COMMAND ${test})
|
||||||
else()
|
else()
|
||||||
add_test(NAME ${test} COMMAND ${test})
|
add_test(NAME ${test} COMMAND ${test})
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
@ -656,7 +664,7 @@ if(MSVC)
|
|||||||
COMPONENT Runtime)
|
COMPONENT Runtime)
|
||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
install(TARGETS libzmq
|
install(TARGETS libzmq libzmq-static
|
||||||
RUNTIME DESTINATION bin
|
RUNTIME DESTINATION bin
|
||||||
ARCHIVE DESTINATION lib
|
ARCHIVE DESTINATION lib
|
||||||
LIBRARY DESTINATION lib
|
LIBRARY DESTINATION lib
|
||||||
|
@ -12,6 +12,7 @@ EXTRA_DIST = \
|
|||||||
autogen.sh \
|
autogen.sh \
|
||||||
version.sh \
|
version.sh \
|
||||||
MAINTAINERS \
|
MAINTAINERS \
|
||||||
|
README.md \
|
||||||
foreign/openpgm/@pgm_basename@.tar.gz
|
foreign/openpgm/@pgm_basename@.tar.gz
|
||||||
MAINTAINERCLEANFILES = \
|
MAINTAINERCLEANFILES = \
|
||||||
$(srcdir)/aclocal.m4 \
|
$(srcdir)/aclocal.m4 \
|
||||||
|
276
NEWS
276
NEWS
@ -1,3 +1,277 @@
|
|||||||
|
0MQ version 4.0.6 stable, released on 2015/06/02
|
||||||
|
================================================
|
||||||
|
|
||||||
|
* Fixed #1273 - V3 protocol handler vulnerable to downgrade attacks.
|
||||||
|
|
||||||
|
* Fixed #1362 - SUB socket sometimes fails to resubscribe properly.
|
||||||
|
|
||||||
|
* Fixed #1377, #1144 - failed with WSANOTINITIALISED in some cases.
|
||||||
|
|
||||||
|
* Fixed #1389 - PUB, PUSH sockets had slow memory leak.
|
||||||
|
|
||||||
|
* Fixed #1382 - zmq_proxy did not terminate if there were no readers.
|
||||||
|
|
||||||
|
|
||||||
|
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
|
0MQ version 3.2.2 stable, released on 2012/11/23
|
||||||
================================================
|
================================================
|
||||||
|
|
||||||
@ -13,7 +287,6 @@ Issues addressed in this release
|
|||||||
* LIBZMQ-450 lt-test_monitor: fails with assertion at test_monitor.cpp:81
|
* LIBZMQ-450 lt-test_monitor: fails with assertion at test_monitor.cpp:81
|
||||||
* LIBZMQ-451 ZMQ_ROUTER_MANDATORY blocks forever
|
* LIBZMQ-451 ZMQ_ROUTER_MANDATORY blocks forever
|
||||||
* LIBZMQ-452 test_connect_delay.cpp:175:12: error: 'sleep' was not declared in this scope
|
* 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-458 lt-test_router_mandatory fails with assertion at test_router_mandatory.cpp:53
|
||||||
* LIBZMQ-459 Assertion failed: encoder (stream_engine.cpp:266
|
* LIBZMQ-459 Assertion failed: encoder (stream_engine.cpp:266
|
||||||
* LIBZMQ-464 PUB socket with HWM set leaks memory
|
* LIBZMQ-464 PUB socket with HWM set leaks memory
|
||||||
@ -21,6 +294,7 @@ Issues addressed in this release
|
|||||||
* LIBZMQ-468 ZMQ_XPUB_VERBOSE & unsubscribe
|
* LIBZMQ-468 ZMQ_XPUB_VERBOSE & unsubscribe
|
||||||
* LIBZMQ-472 Segfault in zmq_poll in REQ to ROUTER dialog
|
* LIBZMQ-472 Segfault in zmq_poll in REQ to ROUTER dialog
|
||||||
|
|
||||||
|
|
||||||
0MQ version 3.2.1 (RC2), released on 2012/10/15
|
0MQ version 3.2.1 (RC2), released on 2012/10/15
|
||||||
===============================================
|
===============================================
|
||||||
|
|
||||||
|
@ -11,6 +11,12 @@ abstraction of asynchronous message queues, multiple messaging patterns,
|
|||||||
message filtering (subscriptions), seamless access to multiple transport
|
message filtering (subscriptions), seamless access to multiple transport
|
||||||
protocols and more.
|
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
|
## Building and installation
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ URL: http://www.zeromq.org/
|
|||||||
Source: http://download.zeromq.org/%{name}-%{version}.tar.gz
|
Source: http://download.zeromq.org/%{name}-%{version}.tar.gz
|
||||||
Prefix: %{_prefix}
|
Prefix: %{_prefix}
|
||||||
Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root
|
Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root
|
||||||
BuildRequires: gcc, make, gcc-c++, libstdc++-devel
|
BuildRequires: gcc, make, gcc-c++, libstdc++-devel, asciidoc, xmlto
|
||||||
Requires: libstdc++
|
Requires: libstdc++
|
||||||
|
|
||||||
%if 0%{?rhel}
|
%if 0%{?rhel}
|
||||||
@ -87,11 +87,14 @@ This package contains ZeroMQ related development libraries and header files.
|
|||||||
%defattr(-,root,root,-)
|
%defattr(-,root,root,-)
|
||||||
|
|
||||||
# docs in the main package
|
# 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
|
# libraries
|
||||||
%{_libdir}/libzmq.so.3
|
%{_libdir}/libzmq.so.4
|
||||||
%{_libdir}/libzmq.so.3.0.0
|
%{_libdir}/libzmq.so.4.0.0
|
||||||
|
|
||||||
%{_mandir}/man7/zmq.7.gz
|
%{_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_term.3.gz
|
||||||
%{_mandir}/man3/zmq_version.3.gz
|
%{_mandir}/man3/zmq_version.3.gz
|
||||||
%{_mandir}/man3/zmq_unbind.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_epgm.7.gz
|
||||||
%{_mandir}/man7/zmq_inproc.7.gz
|
%{_mandir}/man7/zmq_inproc.7.gz
|
||||||
%{_mandir}/man7/zmq_ipc.7.gz
|
%{_mandir}/man7/zmq_ipc.7.gz
|
||||||
%{_mandir}/man7/zmq_pgm.7.gz
|
%{_mandir}/man7/zmq_pgm.7.gz
|
||||||
%{_mandir}/man7/zmq_tcp.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
|
%changelog
|
||||||
* Mon Nov 26 2012 Justin Cook <jhcook@gmail.com> 3.2.2
|
* Mon Nov 26 2012 Justin Cook <jhcook@gmail.com> 3.2.2
|
||||||
|
426
builds/zos/README.md
Normal file
426
builds/zos/README.md
Normal 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
62
builds/zos/cxxall
Executable 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
36
builds/zos/makeclean
Executable 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
54
builds/zos/makelibzmq
Executable 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
102
builds/zos/maketests
Executable 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
277
builds/zos/platform.hpp
Normal 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
216
builds/zos/runtests
Executable 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
85
builds/zos/test_fork.cpp
Normal 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
42
builds/zos/zc++
Executable 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
|
61
configure.ac
61
configure.ac
@ -29,9 +29,10 @@ AC_SUBST(PACKAGE_VERSION)
|
|||||||
# ZeroMQ versions 2.1.x: 1:0:0 (ABI version 1)
|
# ZeroMQ versions 2.1.x: 1:0:0 (ABI version 1)
|
||||||
# ZeroMQ version 3.0: 2:0:0 (ABI version 2)
|
# ZeroMQ version 3.0: 2:0:0 (ABI version 2)
|
||||||
# ZeroMQ version 3.1: 3:0:0 (ABI version 3)
|
# 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
|
# libzmq -version-info current:revision:age
|
||||||
LTVER="3:0:0"
|
LTVER="4:0:0"
|
||||||
AC_SUBST(LTVER)
|
AC_SUBST(LTVER)
|
||||||
|
|
||||||
# Take a copy of original flags
|
# Take a copy of original flags
|
||||||
@ -62,10 +63,44 @@ LIBZMQ_CHECK_ENABLE_DEBUG
|
|||||||
# Check wheter to enable code coverage
|
# Check wheter to enable code coverage
|
||||||
LIBZMQ_WITH_GCOV
|
LIBZMQ_WITH_GCOV
|
||||||
|
|
||||||
# Checks for libraries
|
# Allow libsodium to be installed in a custom path:
|
||||||
AC_CHECK_LIB([pthread], [pthread_create])
|
|
||||||
AC_CHECK_LIB([rt], [clock_gettime])
|
AC_ARG_WITH([libsodium],
|
||||||
AC_CHECK_LIB([sodium], [sodium_init],,AC_MSG_WARN(libsodium is needed for CURVE security))
|
[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
|
# Set pedantic
|
||||||
libzmq_pedantic="yes"
|
libzmq_pedantic="yes"
|
||||||
@ -79,6 +114,7 @@ libzmq_dso_visibility="yes"
|
|||||||
# Platform specific checks
|
# Platform specific checks
|
||||||
libzmq_on_mingw32="no"
|
libzmq_on_mingw32="no"
|
||||||
libzmq_on_android="no"
|
libzmq_on_android="no"
|
||||||
|
libzmq_on_linux="no"
|
||||||
|
|
||||||
# Set some default features required by 0MQ code.
|
# Set some default features required by 0MQ code.
|
||||||
CPPFLAGS="-D_REENTRANT -D_THREAD_SAFE $CPPFLAGS"
|
CPPFLAGS="-D_REENTRANT -D_THREAD_SAFE $CPPFLAGS"
|
||||||
@ -94,6 +130,7 @@ case "${host_os}" in
|
|||||||
CPPFLAGS="-D_GNU_SOURCE $CPPFLAGS"
|
CPPFLAGS="-D_GNU_SOURCE $CPPFLAGS"
|
||||||
fi
|
fi
|
||||||
AC_DEFINE(ZMQ_HAVE_LINUX, 1, [Have Linux OS])
|
AC_DEFINE(ZMQ_HAVE_LINUX, 1, [Have Linux OS])
|
||||||
|
libzmq_on_linux="yes"
|
||||||
|
|
||||||
case "${host_os}" in
|
case "${host_os}" in
|
||||||
*android*)
|
*android*)
|
||||||
@ -121,6 +158,9 @@ case "${host_os}" in
|
|||||||
if test "x$solaris_has_atomic" = "xno"; then
|
if test "x$solaris_has_atomic" = "xno"; then
|
||||||
AC_DEFINE(ZMQ_FORCE_MUTEXES, 1, [Force to use mutexes])
|
AC_DEFINE(ZMQ_FORCE_MUTEXES, 1, [Force to use mutexes])
|
||||||
fi
|
fi
|
||||||
|
# ssp library is required for libsodium on Solaris-like systems
|
||||||
|
LDFLAGS="-lssp $LDFLAGS"
|
||||||
|
CPPFLAGS="$CPPFLAGS -Wno-long-long"
|
||||||
;;
|
;;
|
||||||
*freebsd*)
|
*freebsd*)
|
||||||
# Define on FreeBSD to enable all library features
|
# Define on FreeBSD to enable all library features
|
||||||
@ -214,6 +254,16 @@ case "${host_os}" in
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
# Checks for libraries
|
||||||
|
AC_CHECK_LIB([pthread], [pthread_create])
|
||||||
|
AC_CHECK_LIB([rt], [clock_gettime])
|
||||||
|
|
||||||
|
if test "x$with_libsodium" != "xno"; then
|
||||||
|
AC_CHECK_LIB([sodium], [sodium_init],,AC_MSG_WARN(libsodium is needed for CURVE security))
|
||||||
|
else
|
||||||
|
AC_MSG_WARN(libsodium is needed for CURVE security)
|
||||||
|
fi
|
||||||
|
|
||||||
#
|
#
|
||||||
# Check if the compiler supports -fvisibility=hidden flag. MinGW32 uses __declspec
|
# Check if the compiler supports -fvisibility=hidden flag. MinGW32 uses __declspec
|
||||||
#
|
#
|
||||||
@ -385,6 +435,7 @@ AC_LANG_POP([C++])
|
|||||||
AM_CONDITIONAL(BUILD_PGM, test "x$libzmq_pgm_ext" = "xyes")
|
AM_CONDITIONAL(BUILD_PGM, test "x$libzmq_pgm_ext" = "xyes")
|
||||||
AM_CONDITIONAL(ON_MINGW, test "x$libzmq_on_mingw32" = "xyes")
|
AM_CONDITIONAL(ON_MINGW, test "x$libzmq_on_mingw32" = "xyes")
|
||||||
AM_CONDITIONAL(ON_ANDROID, test "x$libzmq_on_android" = "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.
|
# Checks for library functions.
|
||||||
AC_TYPE_SIGNAL
|
AC_TYPE_SIGNAL
|
||||||
|
@ -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_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_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_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_msg_get.3 zmq_msg_set.3 zmq_msg_more.3 \
|
||||||
zmq_getsockopt.3 zmq_setsockopt.3 \
|
zmq_getsockopt.3 zmq_setsockopt.3 \
|
||||||
zmq_socket.3 zmq_socket_monitor.3 zmq_poll.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_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 \
|
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
|
zmq_null.7 zmq_plain.7 zmq_curve.7
|
||||||
|
16
doc/zmq.txt
16
doc/zmq.txt
@ -44,9 +44,6 @@ Work with context properties::
|
|||||||
Destroy a 0MQ context::
|
Destroy a 0MQ context::
|
||||||
linkzmq:zmq_ctx_term[3]
|
linkzmq:zmq_ctx_term[3]
|
||||||
|
|
||||||
Monitor a 0MQ context::
|
|
||||||
linkzmq:zmq_ctx_set_monitor[3]
|
|
||||||
|
|
||||||
These deprecated functions let you create and destroy 'contexts':
|
These deprecated functions let you create and destroy 'contexts':
|
||||||
|
|
||||||
Initialise 0MQ context::
|
Initialise 0MQ context::
|
||||||
@ -140,6 +137,10 @@ Sending and receiving messages::
|
|||||||
linkzmq:zmq_msg_recv[3]
|
linkzmq:zmq_msg_recv[3]
|
||||||
linkzmq:zmq_send[3]
|
linkzmq:zmq_send[3]
|
||||||
linkzmq:zmq_recv[3]
|
linkzmq:zmq_recv[3]
|
||||||
|
linkzmq:zmq_send_const[3]
|
||||||
|
|
||||||
|
Monitoring socket events:
|
||||||
|
linkzmq:zmq_socket_monitor[3]
|
||||||
|
|
||||||
.Input/output multiplexing
|
.Input/output multiplexing
|
||||||
0MQ provides a mechanism for applications to multiplex input/output events over
|
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::
|
Elliptic curve authentication and encryption::
|
||||||
linkzmq:zmq_curve[7]
|
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
|
ERROR HANDLING
|
||||||
--------------
|
--------------
|
||||||
|
@ -54,7 +54,7 @@ EXAMPLE
|
|||||||
.Setting a limit on the number of sockets
|
.Setting a limit on the number of sockets
|
||||||
----
|
----
|
||||||
void *context = zmq_ctx_new ();
|
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);
|
int max_sockets = zmq_ctx_get (context, ZMQ_MAX_SOCKETS);
|
||||||
assert (max_sockets == 256);
|
assert (max_sockets == 256);
|
||||||
----
|
----
|
||||||
|
@ -23,8 +23,8 @@ Context termination is performed in the following steps:
|
|||||||
exception of _zmq_close()_, any further operations on sockets open within
|
exception of _zmq_close()_, any further operations on sockets open within
|
||||||
'context' shall fail with an error code of ETERM.
|
'context' shall fail with an error code of ETERM.
|
||||||
|
|
||||||
2. After interrupting all blocking calls, _zmq_ctx_term()_ shall _block_ until the
|
2. After interrupting all blocking calls, _zmq_ctx_term()_ shall _block_ until
|
||||||
following conditions are satisfied:
|
the following conditions are satisfied:
|
||||||
|
|
||||||
* All sockets open within 'context' have been closed with _zmq_close()_.
|
* All sockets open within 'context' have been closed with _zmq_close()_.
|
||||||
|
|
||||||
@ -39,6 +39,15 @@ option in linkzmq:zmq_setsockopt[3].
|
|||||||
This function replaces the deprecated function linkzmq:zmq_term[3].
|
This function replaces the deprecated function linkzmq:zmq_term[3].
|
||||||
|
|
||||||
|
|
||||||
|
WARNING
|
||||||
|
-------
|
||||||
|
|
||||||
|
As _ZMQ_LINGER_ defaults to "infinite", by default this function will block
|
||||||
|
indefinitely if there are any pending connects or sends. We strongly
|
||||||
|
recommend to (a) set _ZMQ_LINGER_ to zero on all sockets and (b) close all
|
||||||
|
sockets, before calling this function.
|
||||||
|
|
||||||
|
|
||||||
RETURN VALUE
|
RETURN VALUE
|
||||||
------------
|
------------
|
||||||
The _zmq_ctx_term()_ function shall return zero if successful. Otherwise
|
The _zmq_ctx_term()_ function shall return zero if successful. Otherwise
|
||||||
|
56
doc/zmq_curve_keypair.txt
Normal file
56
doc/zmq_curve_keypair.txt
Normal 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>.
|
@ -120,8 +120,8 @@ Default value:: 0
|
|||||||
Applicable socket types:: N/A
|
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'.
|
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
|
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
|
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 type:: binary data
|
||||||
Option value unit:: N/A
|
Option value unit:: N/A
|
||||||
Default value:: NULL
|
Default value:: NULL
|
||||||
Applicable socket types:: all
|
Applicable socket types:: ZMQ_REP, ZMQ_REQ, ZMQ_ROUTER, ZMQ_DEALER.
|
||||||
|
|
||||||
|
|
||||||
ZMQ_RATE: Retrieve multicast data rate
|
ZMQ_RATE: Retrieve multicast data rate
|
||||||
@ -352,8 +352,8 @@ Default value:: 1 (true)
|
|||||||
Applicable socket types:: all, when using TCP transports.
|
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
|
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.
|
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
|
This will cause the socket to block if there are no other connections, but will
|
||||||
|
@ -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.
|
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.
|
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
|
Connecting a socket
|
||||||
~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~
|
||||||
When connecting a 'socket' to a peer address using _zmq_connect()_ with the
|
When connecting a 'socket' to a peer address using _zmq_connect()_ with the
|
||||||
|
@ -40,6 +40,7 @@ EXAMPLE
|
|||||||
-------
|
-------
|
||||||
.Receiving a multi-frame message
|
.Receiving a multi-frame message
|
||||||
----
|
----
|
||||||
|
zmq_msg_t frame;
|
||||||
while (true) {
|
while (true) {
|
||||||
// Create an empty 0MQ message to hold the message frame
|
// Create an empty 0MQ message to hold the message frame
|
||||||
int rc = zmq_msg_init (&frame);
|
int rc = zmq_msg_init (&frame);
|
||||||
@ -53,7 +54,7 @@ while (true) {
|
|||||||
fprintf (stderr, "end\n");
|
fprintf (stderr, "end\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
zmq_msg_close (frame);
|
zmq_msg_close (&frame);
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
@ -28,8 +28,7 @@ _zmq_msg_init_size()_ are mutually exclusive. Never initialize the same
|
|||||||
|
|
||||||
RETURN VALUE
|
RETURN VALUE
|
||||||
------------
|
------------
|
||||||
The _zmq_msg_init()_ function shall return zero if successful. Otherwise it
|
The _zmq_msg_init()_ function always returns zero.
|
||||||
shall return `-1` and set 'errno' to one of the values defined below.
|
|
||||||
|
|
||||||
|
|
||||||
ERRORS
|
ERRORS
|
||||||
|
@ -45,7 +45,7 @@ while (true) {
|
|||||||
fprintf (stderr, "end\n");
|
fprintf (stderr, "end\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
zmq_msg_close (part);
|
zmq_msg_close (&part);
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
@ -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
|
system interfaces other than _poll()_, and as such may be subject to the limits
|
||||||
of those interfaces in ways not defined in this documentation.
|
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
|
RETURN VALUE
|
||||||
------------
|
------------
|
||||||
Upon successful completion, the _zmq_poll()_ function shall return the number
|
Upon successful completion, the _zmq_poll()_ function shall return the number
|
||||||
|
99
doc/zmq_proxy_steerable.txt
Normal file
99
doc/zmq_proxy_steerable.txt
Normal 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>.
|
@ -1,5 +1,5 @@
|
|||||||
zmq_send_const(3)
|
zmq_send_const(3)
|
||||||
===========
|
=================
|
||||||
|
|
||||||
|
|
||||||
NAME
|
NAME
|
||||||
|
@ -14,7 +14,7 @@ SYNOPSIS
|
|||||||
|
|
||||||
Caution: All options, with the exception of ZMQ_SUBSCRIBE, ZMQ_UNSUBSCRIBE,
|
Caution: All options, with the exception of ZMQ_SUBSCRIBE, ZMQ_UNSUBSCRIBE,
|
||||||
ZMQ_LINGER, ZMQ_ROUTER_MANDATORY, ZMQ_PROBE_ROUTER, ZMQ_XPUB_VERBOSE,
|
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.
|
bind/connects.
|
||||||
|
|
||||||
Specifically, security options take effect for subsequent bind/connect calls,
|
Specifically, security options take effect for subsequent bind/connect calls,
|
||||||
@ -135,22 +135,19 @@ Applicable socket types:: ZMQ_SUB
|
|||||||
|
|
||||||
ZMQ_IDENTITY: Set socket identity
|
ZMQ_IDENTITY: Set socket identity
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
The 'ZMQ_IDENTITY' option shall set the identity of the specified 'socket'.
|
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
|
when connecting to a ROUTER socket. The identity should be from 1 to 255
|
||||||
in tandem with ROUTER socket to route messages to the peer with specific
|
bytes long and MAY NOT start with binary zero.
|
||||||
identity.
|
|
||||||
|
|
||||||
Identity should be at least one byte and at most 255 bytes long. Identities
|
If two clients use the same identity when connecting to a ROUTER, the
|
||||||
starting with binary zero are reserved for use by 0MQ infrastructure.
|
ROUTER socket shall accept only the first such client and reject the
|
||||||
|
others.
|
||||||
If two peers use the same identity when connecting to a third peer, the
|
|
||||||
results shall be undefined.
|
|
||||||
|
|
||||||
[horizontal]
|
[horizontal]
|
||||||
Option value type:: binary data
|
Option value type:: binary data
|
||||||
Option value unit:: N/A
|
Option value unit:: N/A
|
||||||
Default value:: NULL
|
Default value:: NULL
|
||||||
Applicable socket types:: all
|
Applicable socket types:: ZMQ_REQ, ZMQ_REP, ZMQ_ROUTER, ZMQ_DEALER.
|
||||||
|
|
||||||
|
|
||||||
ZMQ_RATE: Set multicast data rate
|
ZMQ_RATE: Set multicast data rate
|
||||||
@ -461,11 +458,11 @@ Default value:: 0
|
|||||||
Applicable socket types:: ZMQ_XPUB
|
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
|
The default behavior of REQ sockets is to rely on the ordering of messages to
|
||||||
to match requests and responses and that is usually sufficient. When this option
|
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
|
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,
|
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
|
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
|
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.
|
_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
|
disconnecting the underlying connection to the peer from which the reply was
|
||||||
expected, triggering a reconnection attempt on transports that support it.
|
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
|
The request-reply state machine is reset and a new request is sent to the
|
||||||
next available peer.
|
next available peer.
|
||||||
|
|
||||||
If set to 0, also enable ZMQ_REQ_REQUEST_IDS to ensure correct
|
If set to 1, also enable ZMQ_REQ_CORRELATE to ensure correct matching of
|
||||||
matching of requests and replies. Otherwise a late reply to an aborted request
|
requests and replies. Otherwise a late reply to an aborted request can be
|
||||||
can be reported as the reply to the superseding request.
|
reported as the reply to the superseding request.
|
||||||
|
|
||||||
[horizontal]
|
[horizontal]
|
||||||
Option value type:: int
|
Option value type:: int
|
||||||
Option value unit:: 0, 1
|
Option value unit:: 0, 1
|
||||||
Default value:: 1
|
Default value:: 0
|
||||||
Applicable socket types:: ZMQ_REQ
|
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
|
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.
|
server, and its security role then depends on other option settings.
|
||||||
Setting this to '0' shall reset the socket security to NULL. When you
|
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]
|
[horizontal]
|
||||||
Option value type:: int
|
Option value type:: int
|
||||||
@ -636,14 +635,11 @@ Applicable socket types:: all, when using TCP transport
|
|||||||
ZMQ_CURVE_PUBLICKEY: Set CURVE public key
|
ZMQ_CURVE_PUBLICKEY: Set CURVE public key
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Sets the socket's long term public key. You must set this on a CURVE
|
Sets the socket's long term public key. You must set this on CURVE client
|
||||||
client or server socket, see linkzmq:zmq_curve[7]. You can provide the
|
sockets, see linkzmq:zmq_curve[7]. You can provide the key as 32 binary
|
||||||
key as 32 binary bytes, or as a 40-character string encoded in the Z85
|
bytes, or as a 40-character string encoded in the Z85 encoding format.
|
||||||
encoding format. For servers, the public key must be persisted and
|
The public key must always be used with the matching secret key. To
|
||||||
shared through some unspecified but secure mechanism to clients. The
|
generate a public/secret key pair, use linkzmq:zmq_curve_keypair[3].
|
||||||
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.
|
|
||||||
|
|
||||||
[horizontal]
|
[horizontal]
|
||||||
Option value type:: binary data or Z85 text string
|
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
|
ZMQ_CURVE_SECRETKEY: Set CURVE secret key
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Sets the socket's long term secret key. You must set this on a CURVE
|
Sets the socket's long term secret key. You must set this on both CURVE
|
||||||
client socket, see linkzmq:zmq_curve[7]. You can provide the key as
|
client and server sockets, see linkzmq:zmq_curve[7]. You can provide the
|
||||||
32 binary bytes, or as a 40-character string encoded in the Z85 encoding
|
key as 32 binary bytes, or as a 40-character string encoded in the Z85
|
||||||
format.
|
encoding format. To generate a public/secret key pair, use
|
||||||
|
linkzmq:zmq_curve_keypair[3].
|
||||||
|
|
||||||
[horizontal]
|
[horizontal]
|
||||||
Option value type:: binary data or Z85 text string
|
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
|
ZMQ_CURVE_SERVERKEY: Set CURVE server key
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Sets the socket's long term server key. You must set this on a CURVE
|
Sets the socket's long term server key. You must set this on CURVE client
|
||||||
client socket, see linkzmq:zmq_curve[7]. You can provide the key as
|
sockets, see linkzmq:zmq_curve[7]. You can provide the key as 32 binary
|
||||||
32 binary bytes, or as a 40-character string encoded in the Z85 encoding
|
bytes, or as a 40-character string encoded in the Z85 encoding format.
|
||||||
format. This key must be the same as the public key set on the server
|
This key must have been generated together with the server's secret key.
|
||||||
socket.
|
|
||||||
|
|
||||||
[horizontal]
|
[horizontal]
|
||||||
Option value type:: binary data or Z85 text string
|
Option value type:: binary data or Z85 text string
|
||||||
|
@ -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
|
to one or more ZMQ_REP _services_, and receiving subsequent replies to each
|
||||||
request sent.
|
request sent.
|
||||||
|
|
||||||
|
The request-reply pattern is formally defined by http://rfc.zeromq.org/spec:28.
|
||||||
|
|
||||||
ZMQ_REQ
|
ZMQ_REQ
|
||||||
^^^^^^^
|
^^^^^^^
|
||||||
@ -168,6 +169,7 @@ Publish-subscribe pattern
|
|||||||
The publish-subscribe pattern is used for one-to-many distribution of data from
|
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.
|
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
|
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
|
is connected to at least one _node_. When a pipeline stage is connected to
|
||||||
multiple _nodes_ data is round-robined among all connected _nodes_.
|
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
|
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
|
peer. This pattern is used for inter-thread communication across the inproc
|
||||||
transport.
|
transport.
|
||||||
|
|
||||||
|
The exclusive pair pattern is formally defined by http://rfc.zeromq.org/spec:31.
|
||||||
|
|
||||||
ZMQ_PAIR
|
ZMQ_PAIR
|
||||||
^^^^^^^^
|
^^^^^^^^
|
||||||
@ -400,7 +404,7 @@ uint8_t id [256];
|
|||||||
size_t id_size = 256;
|
size_t id_size = 256;
|
||||||
while (1) {
|
while (1) {
|
||||||
/* Get HTTP request; ID frame and then request */
|
/* 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);
|
assert (id_size > 0);
|
||||||
/* Prepares the response */
|
/* Prepares the response */
|
||||||
char http_response [] =
|
char http_response [] =
|
||||||
|
@ -66,7 +66,7 @@ EXAMPLES
|
|||||||
.Assigning a local address to a socket
|
.Assigning a local address to a socket
|
||||||
----
|
----
|
||||||
// TCP port 5555 on all available interfaces
|
// TCP port 5555 on all available interfaces
|
||||||
rc = zmq_bind(socket, "tcp:/// :5555");
|
rc = zmq_bind(socket, "tcp://*:5555");
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
// TCP port 5555 on the local loop-back interface on all platforms
|
// TCP port 5555 on the local loop-back interface on all platforms
|
||||||
rc = zmq_bind(socket, "tcp://127.0.0.1:5555");
|
rc = zmq_bind(socket, "tcp://127.0.0.1:5555");
|
||||||
|
@ -31,7 +31,6 @@ EXAMPLE
|
|||||||
-------
|
-------
|
||||||
.Decoding a CURVE key
|
.Decoding a CURVE key
|
||||||
----
|
----
|
||||||
#include <sodium.h>
|
|
||||||
char decoded [] = "rq:rM>}U?@Lns47E1%kR.o@n%FcmmsL/@{H8]yf7";
|
char decoded [] = "rq:rM>}U?@Lns47E1%kR.o@n%FcmmsL/@{H8]yf7";
|
||||||
uint8_t public_key [32];
|
uint8_t public_key [32];
|
||||||
zmq_z85_decode (public_key, decoded);
|
zmq_z85_decode (public_key, decoded);
|
||||||
@ -41,6 +40,7 @@ zmq_z85_decode (public_key, decoded);
|
|||||||
SEE ALSO
|
SEE ALSO
|
||||||
--------
|
--------
|
||||||
linkzmq:zmq_z85_decode[3]
|
linkzmq:zmq_z85_decode[3]
|
||||||
|
linkzmq:zmq_curve_keypair[3]
|
||||||
linkzmq:zmq_curve[7]
|
linkzmq:zmq_curve[7]
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,6 +47,7 @@ puts (encoded);
|
|||||||
SEE ALSO
|
SEE ALSO
|
||||||
--------
|
--------
|
||||||
linkzmq:zmq_z85_decode[3]
|
linkzmq:zmq_z85_decode[3]
|
||||||
|
linkzmq:zmq_curve_keypair[3]
|
||||||
linkzmq:zmq_curve[7]
|
linkzmq:zmq_curve[7]
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,11 +15,29 @@
|
|||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
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/>.
|
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__
|
#ifndef __ZMQ_H_INCLUDED__
|
||||||
#define __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 6
|
||||||
|
|
||||||
|
#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
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
@ -62,28 +80,14 @@ typedef __int32 int32_t;
|
|||||||
# ifndef uint16_t
|
# ifndef uint16_t
|
||||||
typedef unsigned __int16 uint16_t;
|
typedef unsigned __int16 uint16_t;
|
||||||
# endif
|
# endif
|
||||||
|
# ifndef uint8_t
|
||||||
|
typedef unsigned __int8 uint8_t;
|
||||||
|
# endif
|
||||||
#else
|
#else
|
||||||
# include <stdint.h>
|
# include <stdint.h>
|
||||||
#endif
|
#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. */
|
/* 0MQ errors. */
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@ -154,6 +158,9 @@ ZMQ_EXPORT void zmq_version (int *major, int *minor, int *patch);
|
|||||||
#define ETERM (ZMQ_HAUSNUMERO + 53)
|
#define ETERM (ZMQ_HAUSNUMERO + 53)
|
||||||
#define EMTHREAD (ZMQ_HAUSNUMERO + 54)
|
#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 */
|
/* 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 */
|
/* of this function is to make the code 100% portable, including where 0MQ */
|
||||||
/* compiled with certain CRT library (on Windows) is linked to an */
|
/* 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 */
|
/* Default for new contexts */
|
||||||
#define ZMQ_IO_THREADS_DFLT 1
|
#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 void *zmq_ctx_new (void);
|
||||||
ZMQ_EXPORT int zmq_ctx_term (void *context);
|
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_SECRETKEY 49
|
||||||
#define ZMQ_CURVE_SERVERKEY 50
|
#define ZMQ_CURVE_SERVERKEY 50
|
||||||
#define ZMQ_PROBE_ROUTER 51
|
#define ZMQ_PROBE_ROUTER 51
|
||||||
#define ZMQ_REQ_REQUEST_IDS 52
|
#define ZMQ_REQ_CORRELATE 52
|
||||||
#define ZMQ_REQ_STRICT 53
|
#define ZMQ_REQ_RELAXED 53
|
||||||
#define ZMQ_CONFLATE 54
|
#define ZMQ_CONFLATE 54
|
||||||
#define ZMQ_ZAP_DOMAIN 55
|
#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) */
|
/* Built-in message proxy (3-way) */
|
||||||
|
|
||||||
ZMQ_EXPORT int zmq_proxy (void *frontend, void *backend, void *capture);
|
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 */
|
/* 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);
|
ZMQ_EXPORT char *zmq_z85_encode (char *dest, uint8_t *data, size_t size);
|
||||||
|
@ -22,9 +22,22 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.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
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
@ -48,8 +61,22 @@ extern "C" {
|
|||||||
# endif
|
# endif
|
||||||
#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*);
|
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 */
|
/* 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. */
|
/* about minutiae of time-related functions on different OS platforms. */
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ libzmq_la_SOURCES = \
|
|||||||
dealer.hpp \
|
dealer.hpp \
|
||||||
xsub.hpp \
|
xsub.hpp \
|
||||||
ypipe.hpp \
|
ypipe.hpp \
|
||||||
ypipe_flat.hpp \
|
ypipe_base.hpp \
|
||||||
yqueue.hpp \
|
yqueue.hpp \
|
||||||
address.cpp \
|
address.cpp \
|
||||||
clock.cpp \
|
clock.cpp \
|
||||||
@ -173,9 +173,15 @@ else
|
|||||||
if ON_ANDROID
|
if ON_ANDROID
|
||||||
libzmq_la_LDFLAGS = -avoid-version -version-info @LTVER@ @LIBZMQ_EXTRA_LDFLAGS@
|
libzmq_la_LDFLAGS = -avoid-version -version-info @LTVER@ @LIBZMQ_EXTRA_LDFLAGS@
|
||||||
else
|
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
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
EXTRA_DIST = libzmq.vers
|
||||||
|
|
||||||
libzmq_la_CXXFLAGS = @LIBZMQ_EXTRA_CXXFLAGS@
|
libzmq_la_CXXFLAGS = @LIBZMQ_EXTRA_CXXFLAGS@
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "likely.hpp"
|
#include "likely.hpp"
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
#include "err.hpp"
|
#include "err.hpp"
|
||||||
|
#include "mutex.hpp"
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
@ -41,9 +42,49 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#endif
|
#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 () :
|
zmq::clock_t::clock_t () :
|
||||||
last_tsc (rdtsc ()),
|
last_tsc (rdtsc ()),
|
||||||
|
#ifdef ZMQ_HAVE_WINDOWS
|
||||||
|
last_time (static_cast<uint64_t>((*my_get_tick_count64)()))
|
||||||
|
#else
|
||||||
last_time (now_us () / 1000)
|
last_time (now_us () / 1000)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +106,7 @@ uint64_t zmq::clock_t::now_us ()
|
|||||||
|
|
||||||
// Convert the tick number into the number of seconds
|
// Convert the tick number into the number of seconds
|
||||||
// since the system was started.
|
// since the system was started.
|
||||||
double ticks_div = ticksPerSecond.QuadPart / 1000000.0;
|
double ticks_div = ticksPerSecond.QuadPart / 1000000.0;
|
||||||
return (uint64_t) (tick.QuadPart / ticks_div);
|
return (uint64_t) (tick.QuadPart / ticks_div);
|
||||||
|
|
||||||
#elif defined HAVE_CLOCK_GETTIME && defined CLOCK_MONOTONIC
|
#elif defined HAVE_CLOCK_GETTIME && defined CLOCK_MONOTONIC
|
||||||
@ -74,7 +115,7 @@ uint64_t zmq::clock_t::now_us ()
|
|||||||
struct timespec tv;
|
struct timespec tv;
|
||||||
int rc = clock_gettime (CLOCK_MONOTONIC, &tv);
|
int rc = clock_gettime (CLOCK_MONOTONIC, &tv);
|
||||||
// Fix case where system has clock_gettime but CLOCK_MONOTONIC is not supported.
|
// Fix case where system has clock_gettime but CLOCK_MONOTONIC is not supported.
|
||||||
// This should be a configuration check, but I looked into it and writing an
|
// This should be a configuration check, but I looked into it and writing an
|
||||||
// AC_FUNC_CLOCK_MONOTONIC seems beyond my powers.
|
// AC_FUNC_CLOCK_MONOTONIC seems beyond my powers.
|
||||||
if( rc != 0) {
|
if( rc != 0) {
|
||||||
// Use POSIX gettimeofday function to get precise time.
|
// Use POSIX gettimeofday function to get precise time.
|
||||||
@ -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 is not supported, get precise time and chop off the microseconds.
|
||||||
if (!tsc)
|
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;
|
return now_us () / 1000;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// If TSC haven't jumped back (in case of migration to a different
|
// 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,
|
// 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;
|
return last_time;
|
||||||
|
|
||||||
last_tsc = tsc;
|
last_tsc = tsc;
|
||||||
|
#ifdef ZMQ_HAVE_WINDOWS
|
||||||
|
last_time = static_cast<uint64_t>((*my_get_tick_count64)());
|
||||||
|
#else
|
||||||
last_time = now_us () / 1000;
|
last_time = now_us () / 1000;
|
||||||
|
#endif
|
||||||
return last_time;
|
return last_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +193,6 @@ uint64_t zmq::clock_t::rdtsc ()
|
|||||||
#elif defined(__s390__)
|
#elif defined(__s390__)
|
||||||
uint64_t tsc;
|
uint64_t tsc;
|
||||||
asm("\tstck\t%0\n" : "=Q" (tsc) : : "cc");
|
asm("\tstck\t%0\n" : "=Q" (tsc) : : "cc");
|
||||||
tsc >>= 12; /* convert to microseconds just to be consistent */
|
|
||||||
return(tsc);
|
return(tsc);
|
||||||
#else
|
#else
|
||||||
return 0;
|
return 0;
|
||||||
|
61
src/ctx.cpp
61
src/ctx.cpp
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file
|
Copyright (c) 2007-2014 Contributors as noted in the AUTHORS file
|
||||||
|
|
||||||
This file is part of 0MQ.
|
This file is part of 0MQ.
|
||||||
|
|
||||||
@ -35,9 +35,21 @@
|
|||||||
#include "err.hpp"
|
#include "err.hpp"
|
||||||
#include "msg.hpp"
|
#include "msg.hpp"
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBSODIUM
|
||||||
|
#include <sodium.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define ZMQ_CTX_TAG_VALUE_GOOD 0xabadcafe
|
#define ZMQ_CTX_TAG_VALUE_GOOD 0xabadcafe
|
||||||
#define ZMQ_CTX_TAG_VALUE_BAD 0xdeadbeef
|
#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 () :
|
zmq::ctx_t::ctx_t () :
|
||||||
tag (ZMQ_CTX_TAG_VALUE_GOOD),
|
tag (ZMQ_CTX_TAG_VALUE_GOOD),
|
||||||
starting (true),
|
starting (true),
|
||||||
@ -45,7 +57,7 @@ zmq::ctx_t::ctx_t () :
|
|||||||
reaper (NULL),
|
reaper (NULL),
|
||||||
slot_count (0),
|
slot_count (0),
|
||||||
slots (NULL),
|
slots (NULL),
|
||||||
max_sockets (ZMQ_MAX_SOCKETS_DFLT),
|
max_sockets (clipped_maxsocket (ZMQ_MAX_SOCKETS_DFLT)),
|
||||||
io_thread_count (ZMQ_IO_THREADS_DFLT),
|
io_thread_count (ZMQ_IO_THREADS_DFLT),
|
||||||
ipv6 (false)
|
ipv6 (false)
|
||||||
{
|
{
|
||||||
@ -74,14 +86,18 @@ zmq::ctx_t::~ctx_t ()
|
|||||||
delete io_threads [i];
|
delete io_threads [i];
|
||||||
|
|
||||||
// Deallocate the reaper thread object.
|
// Deallocate the reaper thread object.
|
||||||
if (reaper)
|
delete reaper;
|
||||||
delete reaper;
|
|
||||||
|
|
||||||
// Deallocate the array of mailboxes. No special work is
|
// Deallocate the array of mailboxes. No special work is
|
||||||
// needed as mailboxes themselves were deallocated with their
|
// needed as mailboxes themselves were deallocated with their
|
||||||
// corresponding io_thread/socket objects.
|
// 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.
|
// Remove the tag, so that the object is considered dead.
|
||||||
tag = ZMQ_CTX_TAG_VALUE_BAD;
|
tag = ZMQ_CTX_TAG_VALUE_BAD;
|
||||||
@ -89,6 +105,14 @@ zmq::ctx_t::~ctx_t ()
|
|||||||
|
|
||||||
int zmq::ctx_t::terminate ()
|
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 ();
|
slot_sync.lock ();
|
||||||
if (!starting) {
|
if (!starting) {
|
||||||
|
|
||||||
@ -109,7 +133,6 @@ int zmq::ctx_t::terminate ()
|
|||||||
// restarted.
|
// restarted.
|
||||||
bool restarted = terminating;
|
bool restarted = terminating;
|
||||||
terminating = true;
|
terminating = true;
|
||||||
slot_sync.unlock ();
|
|
||||||
|
|
||||||
// First attempt to terminate the context.
|
// First attempt to terminate the context.
|
||||||
if (!restarted) {
|
if (!restarted) {
|
||||||
@ -117,13 +140,12 @@ int zmq::ctx_t::terminate ()
|
|||||||
// First send stop command to sockets so that any blocking calls
|
// First send stop command to sockets so that any blocking calls
|
||||||
// can be interrupted. If there are no sockets we can ask reaper
|
// can be interrupted. If there are no sockets we can ask reaper
|
||||||
// thread to stop.
|
// thread to stop.
|
||||||
slot_sync.lock ();
|
|
||||||
for (sockets_t::size_type i = 0; i != sockets.size (); i++)
|
for (sockets_t::size_type i = 0; i != sockets.size (); i++)
|
||||||
sockets [i]->stop ();
|
sockets [i]->stop ();
|
||||||
if (sockets.empty ())
|
if (sockets.empty ())
|
||||||
reaper->stop ();
|
reaper->stop ();
|
||||||
slot_sync.unlock ();
|
|
||||||
}
|
}
|
||||||
|
slot_sync.unlock();
|
||||||
|
|
||||||
// Wait till reaper thread closes all the sockets.
|
// Wait till reaper thread closes all the sockets.
|
||||||
command_t cmd;
|
command_t cmd;
|
||||||
@ -165,7 +187,7 @@ int zmq::ctx_t::shutdown ()
|
|||||||
int zmq::ctx_t::set (int option_, int optval_)
|
int zmq::ctx_t::set (int option_, int optval_)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
if (option_ == ZMQ_MAX_SOCKETS && optval_ >= 1) {
|
if (option_ == ZMQ_MAX_SOCKETS && optval_ >= 1 && optval_ == clipped_maxsocket (optval_)) {
|
||||||
opt_sync.lock ();
|
opt_sync.lock ();
|
||||||
max_sockets = optval_;
|
max_sockets = optval_;
|
||||||
opt_sync.unlock ();
|
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();
|
bind_socket_->inc_seqnum();
|
||||||
pending_connection_.bind_pipe->set_tid(bind_socket_->get_tid());
|
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)
|
if (side_ == bind_side)
|
||||||
{
|
{
|
||||||
command_t cmd;
|
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_.connect_pipe->set_hwms(hwms [1], hwms [0]);
|
||||||
pending_connection_.bind_pipe->set_hwms(hwms [0], hwms [1]);
|
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) {
|
if (pending_connection_.endpoint.options.recv_identity) {
|
||||||
msg_t id;
|
msg_t id;
|
||||||
int rc = id.init_size (bind_options.identity_size);
|
int rc = id.init_size (bind_options.identity_size);
|
||||||
|
@ -132,8 +132,8 @@ namespace zmq
|
|||||||
sockets_t sockets;
|
sockets_t sockets;
|
||||||
|
|
||||||
// List of unused thread slots.
|
// List of unused thread slots.
|
||||||
typedef std::vector <uint32_t> emtpy_slots_t;
|
typedef std::vector <uint32_t> empty_slots_t;
|
||||||
emtpy_slots_t empty_slots;
|
empty_slots_t empty_slots;
|
||||||
|
|
||||||
// If true, zmq_init has been called but no socket has been created
|
// If true, zmq_init has been called but no socket has been created
|
||||||
// yet. Launching of I/O threads is delayed.
|
// yet. Launching of I/O threads is delayed.
|
||||||
|
@ -297,34 +297,38 @@ int zmq::curve_client_t::process_welcome (msg_t *msg_)
|
|||||||
int zmq::curve_client_t::produce_initiate (msg_t *msg_)
|
int zmq::curve_client_t::produce_initiate (msg_t *msg_)
|
||||||
{
|
{
|
||||||
uint8_t vouch_nonce [crypto_box_NONCEBYTES];
|
uint8_t vouch_nonce [crypto_box_NONCEBYTES];
|
||||||
uint8_t vouch_plaintext [crypto_box_ZEROBYTES + 32];
|
uint8_t vouch_plaintext [crypto_box_ZEROBYTES + 64];
|
||||||
uint8_t vouch_box [crypto_box_BOXZEROBYTES + 48];
|
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);
|
memset (vouch_plaintext, 0, crypto_box_ZEROBYTES);
|
||||||
memcpy (vouch_plaintext + crypto_box_ZEROBYTES, cn_public, 32);
|
memcpy (vouch_plaintext + crypto_box_ZEROBYTES, cn_public, 32);
|
||||||
|
memcpy (vouch_plaintext + crypto_box_ZEROBYTES + 32, server_key, 32);
|
||||||
|
|
||||||
memcpy (vouch_nonce, "VOUCH---", 8);
|
memcpy (vouch_nonce, "VOUCH---", 8);
|
||||||
randombytes (vouch_nonce + 8, 16);
|
randombytes (vouch_nonce + 8, 16);
|
||||||
|
|
||||||
int rc = crypto_box (vouch_box, vouch_plaintext,
|
int rc = crypto_box (vouch_box, vouch_plaintext,
|
||||||
sizeof vouch_plaintext,
|
sizeof vouch_plaintext,
|
||||||
vouch_nonce, server_key, secret_key);
|
vouch_nonce, cn_server, secret_key);
|
||||||
zmq_assert (rc == 0);
|
zmq_assert (rc == 0);
|
||||||
|
|
||||||
|
// Assume here that metadata is limited to 256 bytes
|
||||||
uint8_t initiate_nonce [crypto_box_NONCEBYTES];
|
uint8_t initiate_nonce [crypto_box_NONCEBYTES];
|
||||||
uint8_t initiate_plaintext [crypto_box_ZEROBYTES + 96 + 256];
|
uint8_t initiate_plaintext [crypto_box_ZEROBYTES + 128 + 256];
|
||||||
uint8_t initiate_box [crypto_box_BOXZEROBYTES + 112 + 256];
|
uint8_t initiate_box [crypto_box_BOXZEROBYTES + 144 + 256];
|
||||||
|
|
||||||
// Create Box [C + vouch + metadata](C'->S')
|
// Create Box [C + vouch + metadata](C'->S')
|
||||||
memset (initiate_plaintext, 0, crypto_box_ZEROBYTES);
|
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,
|
memcpy (initiate_plaintext + crypto_box_ZEROBYTES + 32,
|
||||||
vouch_nonce + 8, 16);
|
vouch_nonce + 8, 16);
|
||||||
memcpy (initiate_plaintext + crypto_box_ZEROBYTES + 48,
|
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
|
// Add socket type property
|
||||||
const char *socket_type = socket_type_string (options.type);
|
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_DEALER
|
||||||
|| options.type == ZMQ_ROUTER)
|
|| options.type == ZMQ_ROUTER)
|
||||||
ptr += add_property (ptr, "Identity",
|
ptr += add_property (ptr, "Identity",
|
||||||
options.identity, options.identity_size);
|
options.identity, options.identity_size);
|
||||||
|
|
||||||
const size_t mlen = ptr - initiate_plaintext;
|
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')
|
// Box [C + vouch + metadata](C'->S')
|
||||||
memcpy (initiate + 113, initiate_box + crypto_box_BOXZEROBYTES,
|
memcpy (initiate + 113, initiate_box + crypto_box_BOXZEROBYTES,
|
||||||
mlen - crypto_box_BOXZEROBYTES);
|
mlen - crypto_box_BOXZEROBYTES);
|
||||||
|
|
||||||
cn_nonce++;
|
cn_nonce++;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -338,7 +338,7 @@ int zmq::curve_server_t::produce_welcome (msg_t *msg_)
|
|||||||
|
|
||||||
int zmq::curve_server_t::process_initiate (msg_t *msg_)
|
int zmq::curve_server_t::process_initiate (msg_t *msg_)
|
||||||
{
|
{
|
||||||
if (msg_->size () < 225) {
|
if (msg_->size () < 257) {
|
||||||
errno = EPROTO;
|
errno = EPROTO;
|
||||||
return -1;
|
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']
|
// Check cookie plain text is as expected [C' + s']
|
||||||
if (memcmp (cookie_plaintext + crypto_secretbox_ZEROBYTES,
|
if (memcmp (cookie_plaintext + crypto_secretbox_ZEROBYTES, cn_client, 32)
|
||||||
cn_client, 32)
|
|| memcmp (cookie_plaintext + crypto_secretbox_ZEROBYTES + 32, cn_secret, 32)) {
|
||||||
|| memcmp (cookie_plaintext + crypto_secretbox_ZEROBYTES + 32,
|
errno = EPROTO;
|
||||||
cn_secret, 32)) {
|
|
||||||
errno = EAGAIN;
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t clen = (msg_->size () - 113) + crypto_box_BOXZEROBYTES;
|
const size_t clen = (msg_->size () - 113) + crypto_box_BOXZEROBYTES;
|
||||||
|
|
||||||
uint8_t initiate_nonce [crypto_box_NONCEBYTES];
|
uint8_t initiate_nonce [crypto_box_NONCEBYTES];
|
||||||
uint8_t initiate_plaintext [crypto_box_ZEROBYTES + 96 + 256];
|
uint8_t initiate_plaintext [crypto_box_ZEROBYTES + 128 + 256];
|
||||||
uint8_t initiate_box [crypto_box_BOXZEROBYTES + 112 + 256];
|
uint8_t initiate_box [crypto_box_BOXZEROBYTES + 144 + 256];
|
||||||
|
|
||||||
// Open Box [C + vouch + metadata](C'->S')
|
// Open Box [C + vouch + metadata](C'->S')
|
||||||
memset (initiate_box, 0, crypto_box_BOXZEROBYTES);
|
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;
|
const uint8_t *client_key = initiate_plaintext + crypto_box_ZEROBYTES;
|
||||||
|
|
||||||
uint8_t vouch_nonce [crypto_box_NONCEBYTES];
|
uint8_t vouch_nonce [crypto_box_NONCEBYTES];
|
||||||
uint8_t vouch_plaintext [crypto_box_ZEROBYTES + 32];
|
uint8_t vouch_plaintext [crypto_box_ZEROBYTES + 64];
|
||||||
uint8_t vouch_box [crypto_box_BOXZEROBYTES + 48];
|
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);
|
memset (vouch_box, 0, crypto_box_BOXZEROBYTES);
|
||||||
memcpy (vouch_box + 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, "VOUCH---", 8);
|
||||||
memcpy (vouch_nonce + 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,
|
rc = crypto_box_open (vouch_plaintext, vouch_box,
|
||||||
sizeof vouch_box,
|
sizeof vouch_box,
|
||||||
vouch_nonce, client_key, secret_key);
|
vouch_nonce, client_key, cn_secret);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
errno = EPROTO;
|
errno = EPROTO;
|
||||||
return -1;
|
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,
|
return parse_metadata (initiate_plaintext + crypto_box_ZEROBYTES + 128,
|
||||||
clen - crypto_box_ZEROBYTES - 96);
|
clen - crypto_box_ZEROBYTES - 128);
|
||||||
}
|
}
|
||||||
|
|
||||||
int zmq::curve_server_t::produce_ready (msg_t *msg_)
|
int zmq::curve_server_t::produce_ready (msg_t *msg_)
|
||||||
|
@ -133,6 +133,11 @@ void zmq::devpoll_t::stop ()
|
|||||||
stopping = true;
|
stopping = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int zmq::devpoll_t::max_fds ()
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
void zmq::devpoll_t::loop ()
|
void zmq::devpoll_t::loop ()
|
||||||
{
|
{
|
||||||
while (!stopping) {
|
while (!stopping) {
|
||||||
|
@ -56,6 +56,8 @@ namespace zmq
|
|||||||
void start ();
|
void start ();
|
||||||
void stop ();
|
void stop ();
|
||||||
|
|
||||||
|
static int max_fds ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Main worker thread routine.
|
// Main worker thread routine.
|
||||||
|
@ -127,11 +127,6 @@ namespace zmq
|
|||||||
(static_cast <T*> (this)->*next) ();
|
(static_cast <T*> (this)->*next) ();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool has_data ()
|
|
||||||
{
|
|
||||||
return to_write > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Prototype of state machine action.
|
// Prototype of state machine action.
|
||||||
|
@ -126,6 +126,11 @@ void zmq::epoll_t::stop ()
|
|||||||
stopping = true;
|
stopping = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int zmq::epoll_t::max_fds ()
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
void zmq::epoll_t::loop ()
|
void zmq::epoll_t::loop ()
|
||||||
{
|
{
|
||||||
epoll_event ev_buf [max_io_events];
|
epoll_event ev_buf [max_io_events];
|
||||||
|
@ -58,6 +58,8 @@ namespace zmq
|
|||||||
void start ();
|
void start ();
|
||||||
void stop ();
|
void stop ();
|
||||||
|
|
||||||
|
static int max_fds ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Main worker thread routine.
|
// Main worker thread routine.
|
||||||
|
89
src/err.cpp
89
src/err.cpp
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file
|
Copyright (c) 2007-2014 Contributors as noted in the AUTHORS file
|
||||||
|
|
||||||
This file is part of 0MQ.
|
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)
|
int zmq::wsa_error_to_errno (int errcode)
|
||||||
{
|
{
|
||||||
switch (errcode) {
|
switch (errcode) {
|
||||||
|
// 10004 - Interrupted system call.
|
||||||
|
case WSAEINTR:
|
||||||
|
return EINTR;
|
||||||
// 10009 - File handle is not valid.
|
// 10009 - File handle is not valid.
|
||||||
case WSAEBADF:
|
case WSAEBADF:
|
||||||
return EBADF;
|
return EBADF;
|
||||||
@ -231,15 +234,42 @@ int zmq::wsa_error_to_errno (int errcode)
|
|||||||
// 10024 - Too many open files.
|
// 10024 - Too many open files.
|
||||||
case WSAEMFILE:
|
case WSAEMFILE:
|
||||||
return EMFILE;
|
return EMFILE;
|
||||||
|
// 10035 - Operation would block.
|
||||||
|
case WSAEWOULDBLOCK:
|
||||||
|
return EBUSY;
|
||||||
// 10036 - Operation now in progress.
|
// 10036 - Operation now in progress.
|
||||||
case WSAEINPROGRESS:
|
case WSAEINPROGRESS:
|
||||||
return EAGAIN;
|
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.
|
// 10040 - Message too long.
|
||||||
case WSAEMSGSIZE:
|
case WSAEMSGSIZE:
|
||||||
return EMSGSIZE;
|
return EMSGSIZE;
|
||||||
|
// 10041 - Protocol wrong type for socket.
|
||||||
|
case WSAEPROTOTYPE:
|
||||||
|
return EFAULT;
|
||||||
|
// 10042 - Bad protocol option.
|
||||||
|
case WSAENOPROTOOPT:
|
||||||
|
return EINVAL;
|
||||||
// 10043 - Protocol not supported.
|
// 10043 - Protocol not supported.
|
||||||
case WSAEPROTONOSUPPORT:
|
case WSAEPROTONOSUPPORT:
|
||||||
return EPROTONOSUPPORT;
|
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.
|
// 10047 - Address family not supported by protocol family.
|
||||||
case WSAEAFNOSUPPORT:
|
case WSAEAFNOSUPPORT:
|
||||||
return EAFNOSUPPORT;
|
return EAFNOSUPPORT;
|
||||||
@ -267,18 +297,75 @@ int zmq::wsa_error_to_errno (int errcode)
|
|||||||
// 10055 - No buffer space available.
|
// 10055 - No buffer space available.
|
||||||
case WSAENOBUFS:
|
case WSAENOBUFS:
|
||||||
return ENOBUFS;
|
return ENOBUFS;
|
||||||
|
// 10056 - Socket is already connected.
|
||||||
|
case WSAEISCONN:
|
||||||
|
return EFAULT;
|
||||||
// 10057 - Socket is not connected.
|
// 10057 - Socket is not connected.
|
||||||
case WSAENOTCONN:
|
case WSAENOTCONN:
|
||||||
return ENOTCONN;
|
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.
|
// 10060 - Connection timed out.
|
||||||
case WSAETIMEDOUT:
|
case WSAETIMEDOUT:
|
||||||
return ETIMEDOUT;
|
return ETIMEDOUT;
|
||||||
// 10061 - Connection refused.
|
// 10061 - Connection refused.
|
||||||
case WSAECONNREFUSED:
|
case WSAECONNREFUSED:
|
||||||
return ECONNREFUSED;
|
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.
|
// 10065 - No route to host.
|
||||||
case WSAEHOSTUNREACH:
|
case WSAEHOSTUNREACH:
|
||||||
return EHOSTUNREACH;
|
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:
|
default:
|
||||||
wsa_assert (false);
|
wsa_assert (false);
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,6 @@ namespace zmq
|
|||||||
// Load a new message into encoder.
|
// Load a new message into encoder.
|
||||||
virtual void load_msg (msg_t *msg_) = 0;
|
virtual void load_msg (msg_t *msg_) = 0;
|
||||||
|
|
||||||
virtual bool has_data () = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -41,11 +41,11 @@ namespace zmq
|
|||||||
|
|
||||||
// This method is called by the session to signalise that more
|
// This method is called by the session to signalise that more
|
||||||
// messages can be written to the pipe.
|
// 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
|
// This method is called by the session to signalise that there
|
||||||
// are messages to send available.
|
// are messages to send available.
|
||||||
virtual void activate_out () = 0;
|
virtual void restart_output () = 0;
|
||||||
|
|
||||||
virtual void zap_msg_available () = 0;
|
virtual void zap_msg_available () = 0;
|
||||||
};
|
};
|
||||||
|
@ -133,7 +133,6 @@ bool zmq::get_peer_ip_address (fd_t sockfd_, std::string &ip_addr_)
|
|||||||
errno_assert (errno != EBADF &&
|
errno_assert (errno != EBADF &&
|
||||||
errno != EFAULT &&
|
errno != EFAULT &&
|
||||||
errno != EINVAL &&
|
errno != EINVAL &&
|
||||||
errno != ENOTCONN &&
|
|
||||||
errno != ENOTSOCK);
|
errno != ENOTSOCK);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -51,9 +51,20 @@ int zmq::ipc_address_t::resolve (const char *path_)
|
|||||||
errno = ENAMETOOLONG;
|
errno = ENAMETOOLONG;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
#if defined ZMQ_HAVE_LINUX
|
||||||
|
if (path_[0] == '@' && !path_[1]) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
address.sun_family = AF_UNIX;
|
address.sun_family = AF_UNIX;
|
||||||
strcpy (address.sun_path, path_);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +76,15 @@ int zmq::ipc_address_t::to_string (std::string &addr_)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::stringstream s;
|
std::stringstream s;
|
||||||
|
#if !defined ZMQ_HAVE_LINUX
|
||||||
s << "ipc://" << address.sun_path;
|
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 ();
|
addr_ = s.str ();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -77,6 +96,10 @@ const sockaddr *zmq::ipc_address_t::addr () const
|
|||||||
|
|
||||||
socklen_t zmq::ipc_address_t::addrlen () 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);
|
return (socklen_t) sizeof (address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,6 +152,11 @@ void zmq::kqueue_t::stop ()
|
|||||||
stopping = true;
|
stopping = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int zmq::kqueue_t::max_fds ()
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
void zmq::kqueue_t::loop ()
|
void zmq::kqueue_t::loop ()
|
||||||
{
|
{
|
||||||
while (!stopping) {
|
while (!stopping) {
|
||||||
|
@ -58,6 +58,8 @@ namespace zmq
|
|||||||
void start ();
|
void start ();
|
||||||
void stop ();
|
void stop ();
|
||||||
|
|
||||||
|
static int max_fds ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Main worker thread routine.
|
// Main worker thread routine.
|
||||||
|
4
src/libzmq.vers
Normal file
4
src/libzmq.vers
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
global: zmq_*;
|
||||||
|
local: *;
|
||||||
|
};
|
@ -54,8 +54,7 @@ zmq::mtrie_t::~mtrie_t ()
|
|||||||
else
|
else
|
||||||
if (count > 1) {
|
if (count > 1) {
|
||||||
for (unsigned short i = 0; i != count; ++i)
|
for (unsigned short i = 0; i != count; ++i)
|
||||||
if (next.table [i])
|
delete next.table [i];
|
||||||
delete next.table [i];
|
|
||||||
free (next.table);
|
free (next.table);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -286,7 +286,7 @@ int zmq::options_t::setsockopt (int option_, const void *optval_,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ZMQ_ZAP_DOMAIN:
|
case ZMQ_ZAP_DOMAIN:
|
||||||
if (optvallen_ >= 0 && optvallen_ < 256) {
|
if (optvallen_ < 256) {
|
||||||
zap_domain.assign ((const char *) optval_, optvallen_);
|
zap_domain.assign ((const char *) optval_, optvallen_);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -102,12 +102,12 @@ void zmq::pgm_receiver_t::terminate ()
|
|||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void zmq::pgm_receiver_t::activate_out ()
|
void zmq::pgm_receiver_t::restart_output ()
|
||||||
{
|
{
|
||||||
drop_subscriptions ();
|
drop_subscriptions ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void zmq::pgm_receiver_t::activate_in ()
|
void zmq::pgm_receiver_t::restart_input ()
|
||||||
{
|
{
|
||||||
zmq_assert (session != NULL);
|
zmq_assert (session != NULL);
|
||||||
zmq_assert (active_tsi != NULL);
|
zmq_assert (active_tsi != NULL);
|
||||||
|
@ -57,8 +57,8 @@ namespace zmq
|
|||||||
void plug (zmq::io_thread_t *io_thread_,
|
void plug (zmq::io_thread_t *io_thread_,
|
||||||
zmq::session_base_t *session_);
|
zmq::session_base_t *session_);
|
||||||
void terminate ();
|
void terminate ();
|
||||||
void activate_in ();
|
void restart_input ();
|
||||||
void activate_out ();
|
void restart_output ();
|
||||||
void zap_msg_available () {}
|
void zap_msg_available () {}
|
||||||
|
|
||||||
// i_poll_events interface implementation.
|
// i_poll_events interface implementation.
|
||||||
|
@ -119,13 +119,13 @@ void zmq::pgm_sender_t::terminate ()
|
|||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void zmq::pgm_sender_t::activate_out ()
|
void zmq::pgm_sender_t::restart_output ()
|
||||||
{
|
{
|
||||||
set_pollout (handle);
|
set_pollout (handle);
|
||||||
out_event ();
|
out_event ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void zmq::pgm_sender_t::activate_in ()
|
void zmq::pgm_sender_t::restart_input ()
|
||||||
{
|
{
|
||||||
zmq_assert (false);
|
zmq_assert (false);
|
||||||
}
|
}
|
||||||
|
@ -56,8 +56,8 @@ namespace zmq
|
|||||||
void plug (zmq::io_thread_t *io_thread_,
|
void plug (zmq::io_thread_t *io_thread_,
|
||||||
zmq::session_base_t *session_);
|
zmq::session_base_t *session_);
|
||||||
void terminate ();
|
void terminate ();
|
||||||
void activate_in ();
|
void restart_input ();
|
||||||
void activate_out ();
|
void restart_output ();
|
||||||
void zap_msg_available () {}
|
void zap_msg_available () {}
|
||||||
|
|
||||||
// i_poll_events interface implementation.
|
// i_poll_events interface implementation.
|
||||||
|
11
src/pipe.cpp
11
src/pipe.cpp
@ -154,7 +154,7 @@ bool zmq::pipe_t::read (msg_t *msg_)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(msg_->flags () & msg_t::more))
|
if (!(msg_->flags () & msg_t::more) && !msg_->is_identity ())
|
||||||
msgs_read++;
|
msgs_read++;
|
||||||
|
|
||||||
if (lwm > 0 && msgs_read % lwm == 0)
|
if (lwm > 0 && msgs_read % lwm == 0)
|
||||||
@ -184,8 +184,9 @@ bool zmq::pipe_t::write (msg_t *msg_)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool more = msg_->flags () & msg_t::more ? true : false;
|
bool more = msg_->flags () & msg_t::more ? true : false;
|
||||||
|
const bool is_identity = msg_->is_identity ();
|
||||||
outpipe->write (*msg_, more);
|
outpipe->write (*msg_, more);
|
||||||
if (!more)
|
if (!more && !is_identity)
|
||||||
msgs_written++;
|
msgs_written++;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -241,6 +242,8 @@ void zmq::pipe_t::process_hiccup (void *pipe_)
|
|||||||
outpipe->flush ();
|
outpipe->flush ();
|
||||||
msg_t msg;
|
msg_t msg;
|
||||||
while (outpipe->read (&msg)) {
|
while (outpipe->read (&msg)) {
|
||||||
|
if (!(msg.flags () & msg_t::more))
|
||||||
|
msgs_written--;
|
||||||
int rc = msg.close ();
|
int rc = msg.close ();
|
||||||
errno_assert (rc == 0);
|
errno_assert (rc == 0);
|
||||||
}
|
}
|
||||||
@ -466,10 +469,10 @@ void zmq::pipe_t::hiccup ()
|
|||||||
// Create new inpipe.
|
// Create new inpipe.
|
||||||
if (conflate)
|
if (conflate)
|
||||||
inpipe = new (std::nothrow)
|
inpipe = new (std::nothrow)
|
||||||
ypipe_t <msg_t, message_pipe_granularity> ();
|
ypipe_conflate_t <msg_t, message_pipe_granularity> ();
|
||||||
else
|
else
|
||||||
inpipe = new (std::nothrow)
|
inpipe = new (std::nothrow)
|
||||||
ypipe_conflate_t <msg_t, message_pipe_granularity> ();
|
ypipe_t <msg_t, message_pipe_granularity> ();
|
||||||
|
|
||||||
alloc_assert (inpipe);
|
alloc_assert (inpipe);
|
||||||
in_active = true;
|
in_active = true;
|
||||||
|
@ -114,6 +114,11 @@ void zmq::poll_t::stop ()
|
|||||||
stopping = true;
|
stopping = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int zmq::poll_t::max_fds ()
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
void zmq::poll_t::loop ()
|
void zmq::poll_t::loop ()
|
||||||
{
|
{
|
||||||
while (!stopping) {
|
while (!stopping) {
|
||||||
|
@ -59,6 +59,8 @@ namespace zmq
|
|||||||
void start ();
|
void start ();
|
||||||
void stop ();
|
void stop ();
|
||||||
|
|
||||||
|
static int max_fds ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Main worker thread routine.
|
// Main worker thread routine.
|
||||||
|
@ -57,7 +57,8 @@
|
|||||||
int zmq::proxy (
|
int zmq::proxy (
|
||||||
class socket_base_t *frontend_,
|
class socket_base_t *frontend_,
|
||||||
class socket_base_t *backend_,
|
class socket_base_t *backend_,
|
||||||
class socket_base_t *capture_)
|
class socket_base_t *capture_,
|
||||||
|
class socket_base_t *control_)
|
||||||
{
|
{
|
||||||
msg_t msg;
|
msg_t msg;
|
||||||
int rc = msg.init ();
|
int rc = msg.init ();
|
||||||
@ -71,16 +72,76 @@ int zmq::proxy (
|
|||||||
size_t moresz;
|
size_t moresz;
|
||||||
zmq_pollitem_t items [] = {
|
zmq_pollitem_t items [] = {
|
||||||
{ frontend_, 0, ZMQ_POLLIN, 0 },
|
{ 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);
|
||||||
|
zmq_pollitem_t itemsout [] = {
|
||||||
|
{ frontend_, 0, ZMQ_POLLOUT, 0 },
|
||||||
|
{ backend_, 0, ZMQ_POLLOUT, 0 }
|
||||||
|
};
|
||||||
|
// 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.
|
// 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))
|
if (unlikely (rc < 0))
|
||||||
return -1;
|
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;
|
||||||
|
|
||||||
|
// Get the pollout separately because when combining this with pollin it maxes the CPU
|
||||||
|
// because pollout shall most of the time return directly
|
||||||
|
rc = zmq_poll (&itemsout [0], 2, 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
|
// Process a request
|
||||||
if (items [0].revents & ZMQ_POLLIN) {
|
if (state == active
|
||||||
|
&& items [0].revents & ZMQ_POLLIN
|
||||||
|
&& itemsout [1].revents & ZMQ_POLLOUT) {
|
||||||
while (true) {
|
while (true) {
|
||||||
rc = frontend_->recv (&msg, 0);
|
rc = frontend_->recv (&msg, 0);
|
||||||
if (unlikely (rc < 0))
|
if (unlikely (rc < 0))
|
||||||
@ -112,7 +173,9 @@ int zmq::proxy (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Process a reply
|
// Process a reply
|
||||||
if (items [1].revents & ZMQ_POLLIN) {
|
if (state == active
|
||||||
|
&& items [1].revents & ZMQ_POLLIN
|
||||||
|
&& itemsout [0].revents & ZMQ_POLLOUT) {
|
||||||
while (true) {
|
while (true) {
|
||||||
rc = backend_->recv (&msg, 0);
|
rc = backend_->recv (&msg, 0);
|
||||||
if (unlikely (rc < 0))
|
if (unlikely (rc < 0))
|
||||||
|
@ -25,7 +25,8 @@ namespace zmq
|
|||||||
int proxy (
|
int proxy (
|
||||||
class socket_base_t *frontend_,
|
class socket_base_t *frontend_,
|
||||||
class socket_base_t *backend_,
|
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
|
#endif
|
||||||
|
13
src/pub.cpp
13
src/pub.cpp
@ -18,6 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pub.hpp"
|
#include "pub.hpp"
|
||||||
|
#include "pipe.hpp"
|
||||||
|
#include "err.hpp"
|
||||||
#include "msg.hpp"
|
#include "msg.hpp"
|
||||||
|
|
||||||
zmq::pub_t::pub_t (class ctx_t *parent_, uint32_t tid_, int sid_) :
|
zmq::pub_t::pub_t (class ctx_t *parent_, uint32_t tid_, int sid_) :
|
||||||
@ -30,6 +32,17 @@ zmq::pub_t::~pub_t ()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void zmq::pub_t::xattach_pipe (pipe_t *pipe_, bool subscribe_to_all_)
|
||||||
|
{
|
||||||
|
zmq_assert (pipe_);
|
||||||
|
|
||||||
|
// Don't delay pipe termination as there is no one
|
||||||
|
// to receive the delimiter.
|
||||||
|
pipe_->set_nodelay ();
|
||||||
|
|
||||||
|
xpub_t::xattach_pipe (pipe_, subscribe_to_all_);
|
||||||
|
}
|
||||||
|
|
||||||
int zmq::pub_t::xrecv (class msg_t *)
|
int zmq::pub_t::xrecv (class msg_t *)
|
||||||
{
|
{
|
||||||
// Messages cannot be received from PUB socket.
|
// Messages cannot be received from PUB socket.
|
||||||
|
@ -38,6 +38,7 @@ namespace zmq
|
|||||||
~pub_t ();
|
~pub_t ();
|
||||||
|
|
||||||
// Implementations of virtual functions from socket_base_t.
|
// Implementations of virtual functions from socket_base_t.
|
||||||
|
void xattach_pipe (zmq::pipe_t *pipe_, bool subscribe_to_all_ = false);
|
||||||
int xrecv (zmq::msg_t *msg_);
|
int xrecv (zmq::msg_t *msg_);
|
||||||
bool xhas_in ();
|
bool xhas_in ();
|
||||||
|
|
||||||
|
@ -36,6 +36,9 @@ void zmq::push_t::xattach_pipe (pipe_t *pipe_, bool subscribe_to_all_)
|
|||||||
{
|
{
|
||||||
// subscribe_to_all_ is unused
|
// subscribe_to_all_ is unused
|
||||||
(void)subscribe_to_all_;
|
(void)subscribe_to_all_;
|
||||||
|
// Don't delay pipe termination as there is no one
|
||||||
|
// to receive the delimiter.
|
||||||
|
pipe_->set_nodelay ();
|
||||||
|
|
||||||
zmq_assert (pipe_);
|
zmq_assert (pipe_);
|
||||||
lb.attach (pipe_);
|
lb.attach (pipe_);
|
||||||
|
@ -198,16 +198,16 @@ int zmq::req_t::xsetsockopt (int option_, const void *optval_, size_t optvallen_
|
|||||||
bool is_int = (optvallen_ == sizeof (int));
|
bool is_int = (optvallen_ == sizeof (int));
|
||||||
int value = is_int? *((int *) optval_): 0;
|
int value = is_int? *((int *) optval_): 0;
|
||||||
switch (option_) {
|
switch (option_) {
|
||||||
case ZMQ_REQ_REQUEST_IDS:
|
case ZMQ_REQ_CORRELATE:
|
||||||
if (is_int && value >= 0) {
|
if (is_int && value >= 0) {
|
||||||
request_id_frames_enabled = (value != 0);
|
request_id_frames_enabled = (value != 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZMQ_REQ_STRICT:
|
case ZMQ_REQ_RELAXED:
|
||||||
if (is_int && value >= 0) {
|
if (is_int && value >= 0) {
|
||||||
strict = (value != 0);
|
strict = (value == 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -225,6 +225,8 @@ int zmq::router_t::xsend (msg_t *msg_)
|
|||||||
current_out->terminate (false);
|
current_out->terminate (false);
|
||||||
int rc = msg_->close ();
|
int rc = msg_->close ();
|
||||||
errno_assert (rc == 0);
|
errno_assert (rc == 0);
|
||||||
|
rc = msg_->init ();
|
||||||
|
errno_assert (rc == 0);
|
||||||
current_out = NULL;
|
current_out = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -144,6 +144,11 @@ void zmq::select_t::stop ()
|
|||||||
stopping = true;
|
stopping = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int zmq::select_t::max_fds ()
|
||||||
|
{
|
||||||
|
return FD_SETSIZE;
|
||||||
|
}
|
||||||
|
|
||||||
void zmq::select_t::loop ()
|
void zmq::select_t::loop ()
|
||||||
{
|
{
|
||||||
while (!stopping) {
|
while (!stopping) {
|
||||||
|
@ -69,6 +69,8 @@ namespace zmq
|
|||||||
void start ();
|
void start ();
|
||||||
void stop ();
|
void stop ();
|
||||||
|
|
||||||
|
static int max_fds ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Main worker thread routine.
|
// Main worker thread routine.
|
||||||
|
@ -96,8 +96,7 @@ zmq::session_base_t::~session_base_t ()
|
|||||||
if (engine)
|
if (engine)
|
||||||
engine->terminate ();
|
engine->terminate ();
|
||||||
|
|
||||||
if (addr)
|
delete addr;
|
||||||
delete addr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void zmq::session_base_t::attach_pipe (pipe_t *pipe_)
|
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))
|
if (likely (pipe_ == pipe))
|
||||||
engine->activate_out ();
|
engine->restart_output ();
|
||||||
else
|
else
|
||||||
engine->zap_msg_available ();
|
engine->zap_msg_available ();
|
||||||
}
|
}
|
||||||
@ -258,7 +257,7 @@ void zmq::session_base_t::write_activated (pipe_t *pipe_)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (engine)
|
if (engine)
|
||||||
engine->activate_in ();
|
engine->restart_input ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void zmq::session_base_t::hiccuped (pipe_t *)
|
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_nodelay ();
|
||||||
zap_pipe->set_event_sink (this);
|
zap_pipe->set_event_sink (this);
|
||||||
|
|
||||||
new_pipes [1]->set_nodelay ();
|
|
||||||
send_bind (peer.socket, new_pipes [1], false);
|
send_bind (peer.socket, new_pipes [1], false);
|
||||||
|
|
||||||
// Send empty identity if required by the peer.
|
// Send empty identity if required by the peer.
|
||||||
@ -325,6 +323,14 @@ int zmq::session_base_t::zap_connect ()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool zmq::session_base_t::zap_enabled ()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
options.mechanism != ZMQ_NULL ||
|
||||||
|
(options.mechanism == ZMQ_NULL && options.zap_domain.length() > 0)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void zmq::session_base_t::process_attach (i_engine *engine_)
|
void zmq::session_base_t::process_attach (i_engine *engine_)
|
||||||
{
|
{
|
||||||
zmq_assert (engine_ != NULL);
|
zmq_assert (engine_ != NULL);
|
||||||
|
@ -68,7 +68,8 @@ namespace zmq
|
|||||||
int push_msg (msg_t *msg_);
|
int push_msg (msg_t *msg_);
|
||||||
|
|
||||||
int zap_connect ();
|
int zap_connect ();
|
||||||
|
bool zap_enabled ();
|
||||||
|
|
||||||
// Fetches a message. Returns 0 if successful; -1 otherwise.
|
// Fetches a message. Returns 0 if successful; -1 otherwise.
|
||||||
// The caller is responsible for freeing the message when no
|
// The caller is responsible for freeing the message when no
|
||||||
// longer used.
|
// longer used.
|
||||||
|
242
src/signaler.cpp
242
src/signaler.cpp
@ -77,16 +77,62 @@
|
|||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#endif
|
#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 ()
|
zmq::signaler_t::signaler_t ()
|
||||||
{
|
{
|
||||||
// Create the socketpair for signaling.
|
// Create the socketpair for signaling.
|
||||||
int rc = make_fdpair (&r, &w);
|
if (make_fdpair (&r, &w) == 0) {
|
||||||
errno_assert (rc == 0);
|
unblock_socket (w);
|
||||||
|
unblock_socket (r);
|
||||||
// Set both fds to non-blocking mode.
|
}
|
||||||
unblock_socket (w);
|
|
||||||
unblock_socket (r);
|
|
||||||
|
|
||||||
#ifdef HAVE_FORK
|
#ifdef HAVE_FORK
|
||||||
pid = getpid();
|
pid = getpid();
|
||||||
#endif
|
#endif
|
||||||
@ -95,21 +141,24 @@ zmq::signaler_t::signaler_t ()
|
|||||||
zmq::signaler_t::~signaler_t ()
|
zmq::signaler_t::~signaler_t ()
|
||||||
{
|
{
|
||||||
#if defined ZMQ_HAVE_EVENTFD
|
#if defined ZMQ_HAVE_EVENTFD
|
||||||
int rc = close (r);
|
int rc = close_wait_ms (r);
|
||||||
errno_assert (rc == 0);
|
errno_assert (rc == 0);
|
||||||
#elif defined ZMQ_HAVE_WINDOWS
|
#elif defined ZMQ_HAVE_WINDOWS
|
||||||
struct linger so_linger = { 1, 0 };
|
struct linger so_linger = { 1, 0 };
|
||||||
int rc = setsockopt (w, SOL_SOCKET, SO_LINGER,
|
int rc = setsockopt (w, SOL_SOCKET, SO_LINGER,
|
||||||
(char *)&so_linger, sizeof (so_linger));
|
(const char *) &so_linger, sizeof so_linger);
|
||||||
wsa_assert (rc != SOCKET_ERROR);
|
// Only check shutdown if WSASTARTUP was previously done
|
||||||
rc = closesocket (w);
|
if (rc == 0 || WSAGetLastError () != WSANOTINITIALISED) {
|
||||||
wsa_assert (rc != SOCKET_ERROR);
|
wsa_assert (rc != SOCKET_ERROR);
|
||||||
rc = closesocket (r);
|
rc = closesocket (w);
|
||||||
wsa_assert (rc != SOCKET_ERROR);
|
wsa_assert (rc != SOCKET_ERROR);
|
||||||
|
rc = closesocket (r);
|
||||||
|
wsa_assert (rc != SOCKET_ERROR);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
int rc = close (w);
|
int rc = close_wait_ms (w);
|
||||||
errno_assert (rc == 0);
|
errno_assert (rc == 0);
|
||||||
rc = close (r);
|
rc = close_wait_ms (r);
|
||||||
errno_assert (rc == 0);
|
errno_assert (rc == 0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -184,8 +233,7 @@ int zmq::signaler_t::wait (int timeout_)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_FORK
|
#ifdef HAVE_FORK
|
||||||
if (unlikely(pid != getpid()))
|
if (unlikely(pid != getpid())) {
|
||||||
{
|
|
||||||
// we have forked and the file descriptor is closed. Emulate an interupt
|
// we have forked and the file descriptor is closed. Emulate an interupt
|
||||||
// response.
|
// response.
|
||||||
//printf("Child process %d signaler_t::wait returning simulating interrupt #2\n", getpid());
|
//printf("Child process %d signaler_t::wait returning simulating interrupt #2\n", getpid());
|
||||||
@ -266,42 +314,30 @@ void zmq::signaler_t::recv ()
|
|||||||
#ifdef HAVE_FORK
|
#ifdef HAVE_FORK
|
||||||
void zmq::signaler_t::forked()
|
void zmq::signaler_t::forked()
|
||||||
{
|
{
|
||||||
int oldr = r;
|
// Close file descriptors created in the parent and create new pair
|
||||||
#if !defined ZMQ_HAVE_EVENTFD
|
close (r);
|
||||||
int oldw = w;
|
close (w);
|
||||||
#endif
|
make_fdpair (&r, &w);
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Returns -1 if we could not make the socket pair successfully
|
||||||
|
|
||||||
|
|
||||||
int zmq::signaler_t::make_fdpair (fd_t *r_, fd_t *w_)
|
int zmq::signaler_t::make_fdpair (fd_t *r_, fd_t *w_)
|
||||||
{
|
{
|
||||||
#if defined ZMQ_HAVE_EVENTFD
|
#if defined ZMQ_HAVE_EVENTFD
|
||||||
|
|
||||||
// Create eventfd object.
|
|
||||||
fd_t fd = eventfd (0, 0);
|
fd_t fd = eventfd (0, 0);
|
||||||
errno_assert (fd != -1);
|
if (fd == -1) {
|
||||||
*w_ = fd;
|
errno_assert (errno == ENFILE || errno == EMFILE);
|
||||||
*r_ = fd;
|
*w_ = *r_ = -1;
|
||||||
return 0;
|
return -1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*w_ = *r_ = fd;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#elif defined ZMQ_HAVE_WINDOWS
|
#elif defined ZMQ_HAVE_WINDOWS
|
||||||
#if !defined _WIN32_WCE
|
# if !defined _WIN32_WCE
|
||||||
// Windows CE does not manage security attributes
|
// Windows CE does not manage security attributes
|
||||||
SECURITY_DESCRIPTOR sd;
|
SECURITY_DESCRIPTOR sd;
|
||||||
SECURITY_ATTRIBUTES sa;
|
SECURITY_ATTRIBUTES sa;
|
||||||
@ -313,7 +349,7 @@ int zmq::signaler_t::make_fdpair (fd_t *r_, fd_t *w_)
|
|||||||
|
|
||||||
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||||
sa.lpSecurityDescriptor = &sd;
|
sa.lpSecurityDescriptor = &sd;
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
// This function has to be in a system-wide critical section so that
|
// This function has to be in a system-wide critical section so that
|
||||||
// two instances of the library don't accidentally create signaler
|
// two instances of the library don't accidentally create signaler
|
||||||
@ -322,20 +358,17 @@ int zmq::signaler_t::make_fdpair (fd_t *r_, fd_t *w_)
|
|||||||
// Note that if the event object already exists, the CreateEvent requests
|
// Note that if the event object already exists, the CreateEvent requests
|
||||||
// EVENT_ALL_ACCESS access right. If this fails, we try to open
|
// EVENT_ALL_ACCESS access right. If this fails, we try to open
|
||||||
// the event object asking for SYNCHRONIZE access only.
|
// 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"));
|
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"));
|
HANDLE sync = CreateEvent (NULL, FALSE, TRUE, TEXT ("Global\\zmq-signaler-port-sync"));
|
||||||
#endif
|
# endif
|
||||||
if (sync == NULL && GetLastError () == ERROR_ACCESS_DENIED)
|
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);
|
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
|
// Windows has no 'socketpair' function. CreatePipe is no good as pipe
|
||||||
// handles cannot be polled on. Here we create the socketpair by hand.
|
// handles cannot be polled on. Here we create the socketpair by hand.
|
||||||
*w_ = INVALID_SOCKET;
|
*w_ = INVALID_SOCKET;
|
||||||
@ -356,58 +389,51 @@ int zmq::signaler_t::make_fdpair (fd_t *r_, fd_t *w_)
|
|||||||
(char *)&tcp_nodelay, sizeof (tcp_nodelay));
|
(char *)&tcp_nodelay, sizeof (tcp_nodelay));
|
||||||
wsa_assert (rc != SOCKET_ERROR);
|
wsa_assert (rc != SOCKET_ERROR);
|
||||||
|
|
||||||
// Bind listening socket to signaler port.
|
// Init sockaddr to signaler port.
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
memset (&addr, 0, sizeof (addr));
|
memset (&addr, 0, sizeof (addr));
|
||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
|
addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
|
||||||
addr.sin_port = htons (signaler_port);
|
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.
|
// 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);
|
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.
|
// Set TCP_NODELAY on writer socket.
|
||||||
rc = setsockopt (*w_, IPPROTO_TCP, TCP_NODELAY,
|
rc = setsockopt (*w_, IPPROTO_TCP, TCP_NODELAY,
|
||||||
(char *)&tcp_nodelay, sizeof (tcp_nodelay));
|
(char *)&tcp_nodelay, sizeof (tcp_nodelay));
|
||||||
wsa_assert (rc != SOCKET_ERROR);
|
wsa_assert (rc != SOCKET_ERROR);
|
||||||
|
|
||||||
// Connect writer to the listener.
|
// Enter the critical section.
|
||||||
rc = connect (*w_, (struct sockaddr*) &addr, sizeof (addr));
|
DWORD dwrc = WaitForSingleObject (sync, INFINITE);
|
||||||
|
zmq_assert (dwrc == WAIT_OBJECT_0);
|
||||||
|
|
||||||
// Save errno if connection fails
|
// Bind listening socket to signaler port.
|
||||||
int conn_errno = 0;
|
rc = bind (listener, (const struct sockaddr*) &addr, sizeof (addr));
|
||||||
if (rc == SOCKET_ERROR) {
|
|
||||||
conn_errno = WSAGetLastError ();
|
// Listen for incoming connections.
|
||||||
} else {
|
if (rc != SOCKET_ERROR)
|
||||||
// Accept connection from writer.
|
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);
|
*r_ = accept (listener, NULL, NULL);
|
||||||
|
|
||||||
if (*r_ == INVALID_SOCKET) {
|
// Save errno if error occurred in bind/listen/connect/accept.
|
||||||
conn_errno = WSAGetLastError ();
|
int saved_errno = 0;
|
||||||
}
|
if (*r_ == INVALID_SOCKET)
|
||||||
}
|
saved_errno = WSAGetLastError ();
|
||||||
|
|
||||||
// We don't need the listening socket anymore. Close it.
|
// We don't need the listening socket anymore. Close it.
|
||||||
rc = closesocket (listener);
|
closesocket (listener);
|
||||||
wsa_assert (rc != SOCKET_ERROR);
|
|
||||||
|
|
||||||
// Exit the critical section.
|
// Exit the critical section.
|
||||||
brc = SetEvent (sync);
|
BOOL brc = SetEvent (sync);
|
||||||
win_assert (brc != 0);
|
win_assert (brc != 0);
|
||||||
|
|
||||||
// Release the kernel object
|
// Release the kernel object
|
||||||
@ -415,27 +441,22 @@ int zmq::signaler_t::make_fdpair (fd_t *r_, fd_t *w_)
|
|||||||
win_assert (brc != 0);
|
win_assert (brc != 0);
|
||||||
|
|
||||||
if (*r_ != INVALID_SOCKET) {
|
if (*r_ != INVALID_SOCKET) {
|
||||||
#if !defined _WIN32_WCE
|
# if !defined _WIN32_WCE
|
||||||
// On Windows, preventing sockets to be inherited by child processes.
|
// On Windows, preventing sockets to be inherited by child processes.
|
||||||
brc = SetHandleInformation ((HANDLE) *r_, HANDLE_FLAG_INHERIT, 0);
|
brc = SetHandleInformation ((HANDLE) *r_, HANDLE_FLAG_INHERIT, 0);
|
||||||
win_assert (brc);
|
win_assert (brc);
|
||||||
#endif
|
# endif
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
// Cleanup writer if connection failed
|
// Cleanup writer if connection failed
|
||||||
rc = closesocket (*w_);
|
if (*w_ != INVALID_SOCKET) {
|
||||||
wsa_assert (rc != SOCKET_ERROR);
|
rc = closesocket (*w_);
|
||||||
|
wsa_assert (rc != SOCKET_ERROR);
|
||||||
*w_ = INVALID_SOCKET;
|
*w_ = INVALID_SOCKET;
|
||||||
|
}
|
||||||
// Set errno from saved value
|
// Set errno from saved value
|
||||||
errno = wsa_error_to_errno (conn_errno);
|
errno = wsa_error_to_errno (saved_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);
|
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -463,7 +484,7 @@ int zmq::signaler_t::make_fdpair (fd_t *r_, fd_t *w_)
|
|||||||
rc = setsockopt (listener, IPPROTO_TCP, TCP_NODELACK, &on, sizeof (on));
|
rc = setsockopt (listener, IPPROTO_TCP, TCP_NODELACK, &on, sizeof (on));
|
||||||
errno_assert (rc != -1);
|
errno_assert (rc != -1);
|
||||||
|
|
||||||
rc = bind(listener, (struct sockaddr*) &lcladdr, sizeof (lcladdr));
|
rc = bind (listener, (struct sockaddr*) &lcladdr, sizeof (lcladdr));
|
||||||
errno_assert (rc != -1);
|
errno_assert (rc != -1);
|
||||||
|
|
||||||
socklen_t lcladdr_len = sizeof (lcladdr);
|
socklen_t lcladdr_len = sizeof (lcladdr);
|
||||||
@ -493,15 +514,20 @@ int zmq::signaler_t::make_fdpair (fd_t *r_, fd_t *w_)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#else // All other implementations support socketpair()
|
#else
|
||||||
|
// All other implementations support socketpair()
|
||||||
int sv [2];
|
int sv [2];
|
||||||
int rc = socketpair (AF_UNIX, SOCK_STREAM, 0, sv);
|
int rc = socketpair (AF_UNIX, SOCK_STREAM, 0, sv);
|
||||||
errno_assert (rc == 0);
|
if (rc == -1) {
|
||||||
*w_ = sv [0];
|
errno_assert (errno == ENFILE || errno == EMFILE);
|
||||||
*r_ = sv [1];
|
*w_ = *r_ = -1;
|
||||||
return 0;
|
return -1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*w_ = sv [0];
|
||||||
|
*r_ = sv [1];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,8 @@ namespace zmq
|
|||||||
// to pass the signals.
|
// to pass the signals.
|
||||||
static int make_fdpair (fd_t *r_, fd_t *w_);
|
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 w;
|
||||||
fd_t r;
|
fd_t r;
|
||||||
|
|
||||||
@ -74,7 +75,6 @@ namespace zmq
|
|||||||
void close_internal();
|
void close_internal();
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -79,47 +79,49 @@ zmq::socket_base_t *zmq::socket_base_t::create (int type_, class ctx_t *parent_,
|
|||||||
{
|
{
|
||||||
socket_base_t *s = NULL;
|
socket_base_t *s = NULL;
|
||||||
switch (type_) {
|
switch (type_) {
|
||||||
|
case ZMQ_PAIR:
|
||||||
case ZMQ_PAIR:
|
s = new (std::nothrow) pair_t (parent_, tid_, sid_);
|
||||||
s = new (std::nothrow) pair_t (parent_, tid_, sid_);
|
break;
|
||||||
break;
|
case ZMQ_PUB:
|
||||||
case ZMQ_PUB:
|
s = new (std::nothrow) pub_t (parent_, tid_, sid_);
|
||||||
s = new (std::nothrow) pub_t (parent_, tid_, sid_);
|
break;
|
||||||
break;
|
case ZMQ_SUB:
|
||||||
case ZMQ_SUB:
|
s = new (std::nothrow) sub_t (parent_, tid_, sid_);
|
||||||
s = new (std::nothrow) sub_t (parent_, tid_, sid_);
|
break;
|
||||||
break;
|
case ZMQ_REQ:
|
||||||
case ZMQ_REQ:
|
s = new (std::nothrow) req_t (parent_, tid_, sid_);
|
||||||
s = new (std::nothrow) req_t (parent_, tid_, sid_);
|
break;
|
||||||
break;
|
case ZMQ_REP:
|
||||||
case ZMQ_REP:
|
s = new (std::nothrow) rep_t (parent_, tid_, sid_);
|
||||||
s = new (std::nothrow) rep_t (parent_, tid_, sid_);
|
break;
|
||||||
break;
|
case ZMQ_DEALER:
|
||||||
case ZMQ_DEALER:
|
s = new (std::nothrow) dealer_t (parent_, tid_, sid_);
|
||||||
s = new (std::nothrow) dealer_t (parent_, tid_, sid_);
|
break;
|
||||||
break;
|
case ZMQ_ROUTER:
|
||||||
case ZMQ_ROUTER:
|
s = new (std::nothrow) router_t (parent_, tid_, sid_);
|
||||||
s = new (std::nothrow) router_t (parent_, tid_, sid_);
|
break;
|
||||||
break;
|
case ZMQ_PULL:
|
||||||
case ZMQ_PULL:
|
s = new (std::nothrow) pull_t (parent_, tid_, sid_);
|
||||||
s = new (std::nothrow) pull_t (parent_, tid_, sid_);
|
break;
|
||||||
break;
|
case ZMQ_PUSH:
|
||||||
case ZMQ_PUSH:
|
s = new (std::nothrow) push_t (parent_, tid_, sid_);
|
||||||
s = new (std::nothrow) push_t (parent_, tid_, sid_);
|
break;
|
||||||
break;
|
case ZMQ_XPUB:
|
||||||
case ZMQ_XPUB:
|
s = new (std::nothrow) xpub_t (parent_, tid_, sid_);
|
||||||
s = new (std::nothrow) xpub_t (parent_, tid_, sid_);
|
break;
|
||||||
break;
|
case ZMQ_XSUB:
|
||||||
case ZMQ_XSUB:
|
s = new (std::nothrow) xsub_t (parent_, tid_, sid_);
|
||||||
s = new (std::nothrow) xsub_t (parent_, tid_, sid_);
|
break;
|
||||||
break;
|
case ZMQ_STREAM:
|
||||||
case ZMQ_STREAM:
|
s = new (std::nothrow) stream_t (parent_, tid_, sid_);
|
||||||
s = new (std::nothrow) stream_t (parent_, tid_, sid_);
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
errno = EINVAL;
|
||||||
errno = EINVAL;
|
return NULL;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
if (s->mailbox.get_fd () == retired_fd)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
alloc_assert (s);
|
alloc_assert (s);
|
||||||
return 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 local end of the pipe to this socket object.
|
||||||
attach_pipe (new_pipes [0]);
|
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};
|
endpoint_t endpoint = {this, options};
|
||||||
pending_connection_t pending_connection = {endpoint, new_pipes [0], new_pipes [1]};
|
pending_connection_t pending_connection = {endpoint, new_pipes [0], new_pipes [1]};
|
||||||
pend_connection (addr_, pending_connection);
|
pend_connection (addr_, pending_connection);
|
||||||
|
@ -68,14 +68,13 @@ zmq::stream_engine_t::stream_engine_t (fd_t fd_, const options_t &options_,
|
|||||||
options (options_),
|
options (options_),
|
||||||
endpoint (endpoint_),
|
endpoint (endpoint_),
|
||||||
plugged (false),
|
plugged (false),
|
||||||
terminating (false),
|
|
||||||
read_msg (&stream_engine_t::read_identity),
|
read_msg (&stream_engine_t::read_identity),
|
||||||
write_msg (&stream_engine_t::write_identity),
|
write_msg (&stream_engine_t::write_identity),
|
||||||
io_error (false),
|
io_error (false),
|
||||||
subscription_required (false),
|
subscription_required (false),
|
||||||
mechanism (NULL),
|
mechanism (NULL),
|
||||||
input_paused (false),
|
input_stopped (false),
|
||||||
output_paused (false),
|
output_stopped (false),
|
||||||
socket (NULL)
|
socket (NULL)
|
||||||
{
|
{
|
||||||
int rc = tx_msg.init ();
|
int rc = tx_msg.init ();
|
||||||
@ -114,12 +113,9 @@ zmq::stream_engine_t::~stream_engine_t ()
|
|||||||
int rc = tx_msg.close ();
|
int rc = tx_msg.close ();
|
||||||
errno_assert (rc == 0);
|
errno_assert (rc == 0);
|
||||||
|
|
||||||
if (encoder != NULL)
|
delete encoder;
|
||||||
delete encoder;
|
delete decoder;
|
||||||
if (decoder != NULL)
|
delete mechanism;
|
||||||
delete decoder;
|
|
||||||
if (mechanism != NULL)
|
|
||||||
delete mechanism;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void zmq::stream_engine_t::plug (io_thread_t *io_thread_,
|
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 ()
|
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 ();
|
unplug ();
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
@ -207,7 +198,7 @@ void zmq::stream_engine_t::in_event ()
|
|||||||
zmq_assert (decoder);
|
zmq_assert (decoder);
|
||||||
|
|
||||||
// If there has been an I/O error, stop polling.
|
// If there has been an I/O error, stop polling.
|
||||||
if (input_paused) {
|
if (input_stopped) {
|
||||||
rm_fd (handle);
|
rm_fd (handle);
|
||||||
io_error = true;
|
io_error = true;
|
||||||
return;
|
return;
|
||||||
@ -220,17 +211,22 @@ void zmq::stream_engine_t::in_event ()
|
|||||||
// Note that buffer can be arbitrarily large. However, we assume
|
// Note that buffer can be arbitrarily large. However, we assume
|
||||||
// the underlying TCP layer has fixed buffer size and thus the
|
// the underlying TCP layer has fixed buffer size and thus the
|
||||||
// number of bytes read will be always limited.
|
// number of bytes read will be always limited.
|
||||||
decoder->get_buffer (&inpos, &insize);
|
size_t bufsize = 0;
|
||||||
const int bytes_read = read (inpos, insize);
|
decoder->get_buffer (&inpos, &bufsize);
|
||||||
|
|
||||||
// Check whether the peer has closed the connection.
|
int const rc = read (inpos, bufsize);
|
||||||
if (bytes_read == -1) {
|
if (rc == 0) {
|
||||||
error ();
|
error ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (rc == -1) {
|
||||||
|
if (errno != EAGAIN)
|
||||||
|
error ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Adjust input size
|
// Adjust input size
|
||||||
insize = static_cast <size_t> (bytes_read);
|
insize = static_cast <size_t> (rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
@ -255,7 +251,7 @@ void zmq::stream_engine_t::in_event ()
|
|||||||
error ();
|
error ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
input_paused = true;
|
input_stopped = true;
|
||||||
reset_pollin (handle);
|
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 there is no data to send, stop polling for output.
|
||||||
if (outsize == 0) {
|
if (outsize == 0) {
|
||||||
output_paused = true;
|
output_stopped = true;
|
||||||
reset_pollout (handle);
|
reset_pollout (handle);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -312,8 +308,6 @@ void zmq::stream_engine_t::out_event ()
|
|||||||
// this is necessary to prevent losing incoming messages.
|
// this is necessary to prevent losing incoming messages.
|
||||||
if (nbytes == -1) {
|
if (nbytes == -1) {
|
||||||
reset_pollout (handle);
|
reset_pollout (handle);
|
||||||
if (unlikely (terminating))
|
|
||||||
terminate ();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,20 +319,16 @@ void zmq::stream_engine_t::out_event ()
|
|||||||
if (unlikely (handshaking))
|
if (unlikely (handshaking))
|
||||||
if (outsize == 0)
|
if (outsize == 0)
|
||||||
reset_pollout (handle);
|
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))
|
if (unlikely (io_error))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (likely (output_paused)) {
|
if (likely (output_stopped)) {
|
||||||
set_pollout (handle);
|
set_pollout (handle);
|
||||||
output_paused = false;
|
output_stopped = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Speculative write: The assumption is that at the moment new message
|
// Speculative write: The assumption is that at the moment new message
|
||||||
@ -348,9 +338,9 @@ void zmq::stream_engine_t::activate_out ()
|
|||||||
out_event ();
|
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 (session != NULL);
|
||||||
zmq_assert (decoder != NULL);
|
zmq_assert (decoder != NULL);
|
||||||
|
|
||||||
@ -382,7 +372,7 @@ void zmq::stream_engine_t::activate_in ()
|
|||||||
if (rc == -1 || io_error)
|
if (rc == -1 || io_error)
|
||||||
error ();
|
error ();
|
||||||
else {
|
else {
|
||||||
input_paused = false;
|
input_stopped = false;
|
||||||
set_pollin (handle);
|
set_pollin (handle);
|
||||||
session->flush ();
|
session->flush ();
|
||||||
|
|
||||||
@ -399,12 +389,15 @@ bool zmq::stream_engine_t::handshake ()
|
|||||||
while (greeting_bytes_read < greeting_size) {
|
while (greeting_bytes_read < greeting_size) {
|
||||||
const int n = read (greeting_recv + greeting_bytes_read,
|
const int n = read (greeting_recv + greeting_bytes_read,
|
||||||
greeting_size - greeting_bytes_read);
|
greeting_size - greeting_bytes_read);
|
||||||
if (n == -1) {
|
if (n == 0) {
|
||||||
error ();
|
error ();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (n == 0)
|
if (n == -1) {
|
||||||
|
if (errno != EAGAIN)
|
||||||
|
error ();
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
greeting_bytes_read += n;
|
greeting_bytes_read += n;
|
||||||
|
|
||||||
@ -471,6 +464,11 @@ bool zmq::stream_engine_t::handshake ()
|
|||||||
// Is the peer using ZMTP/1.0 with no revision number?
|
// Is the peer using ZMTP/1.0 with no revision number?
|
||||||
// If so, we send and receive rest of identity message
|
// If so, we send and receive rest of identity message
|
||||||
if (greeting_recv [0] != 0xff || !(greeting_recv [9] & 0x01)) {
|
if (greeting_recv [0] != 0xff || !(greeting_recv [9] & 0x01)) {
|
||||||
|
if (session->zap_enabled ()) {
|
||||||
|
// Reject ZMTP 1.0 connections if ZAP is enabled
|
||||||
|
error ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
encoder = new (std::nothrow) v1_encoder_t (out_batch_size);
|
encoder = new (std::nothrow) v1_encoder_t (out_batch_size);
|
||||||
alloc_assert (encoder);
|
alloc_assert (encoder);
|
||||||
|
|
||||||
@ -483,6 +481,13 @@ bool zmq::stream_engine_t::handshake ()
|
|||||||
// header data away.
|
// header data away.
|
||||||
const size_t header_size = options.identity_size + 1 >= 255 ? 10 : 2;
|
const size_t header_size = options.identity_size + 1 >= 255 ? 10 : 2;
|
||||||
unsigned char tmp [10], *bufferp = tmp;
|
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);
|
size_t buffer_size = encoder->encode (&bufferp, header_size);
|
||||||
zmq_assert (buffer_size == header_size);
|
zmq_assert (buffer_size == header_size);
|
||||||
|
|
||||||
@ -495,9 +500,21 @@ bool zmq::stream_engine_t::handshake ()
|
|||||||
// message into the incoming message stream.
|
// message into the incoming message stream.
|
||||||
if (options.type == ZMQ_PUB || options.type == ZMQ_XPUB)
|
if (options.type == ZMQ_PUB || options.type == ZMQ_XPUB)
|
||||||
subscription_required = true;
|
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
|
else
|
||||||
if (greeting_recv [revision_pos] == ZMTP_1_0) {
|
if (greeting_recv [revision_pos] == ZMTP_1_0) {
|
||||||
|
if (session->zap_enabled ()) {
|
||||||
|
// Reject ZMTP 1.0 connections if ZAP is enabled
|
||||||
|
error ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
encoder = new (std::nothrow) v1_encoder_t (
|
encoder = new (std::nothrow) v1_encoder_t (
|
||||||
out_batch_size);
|
out_batch_size);
|
||||||
alloc_assert (encoder);
|
alloc_assert (encoder);
|
||||||
@ -508,6 +525,11 @@ bool zmq::stream_engine_t::handshake ()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (greeting_recv [revision_pos] == ZMTP_2_0) {
|
if (greeting_recv [revision_pos] == ZMTP_2_0) {
|
||||||
|
if (session->zap_enabled ()) {
|
||||||
|
// Reject ZMTP 1.0 connections if ZAP is enabled
|
||||||
|
error ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
encoder = new (std::nothrow) v2_encoder_t (out_batch_size);
|
encoder = new (std::nothrow) v2_encoder_t (out_batch_size);
|
||||||
alloc_assert (encoder);
|
alloc_assert (encoder);
|
||||||
|
|
||||||
@ -523,20 +545,23 @@ bool zmq::stream_engine_t::handshake ()
|
|||||||
in_batch_size, options.maxmsgsize);
|
in_batch_size, options.maxmsgsize);
|
||||||
alloc_assert (decoder);
|
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)
|
mechanism = new (std::nothrow)
|
||||||
null_mechanism_t (session, peer_address, options);
|
null_mechanism_t (session, peer_address, options);
|
||||||
alloc_assert (mechanism);
|
alloc_assert (mechanism);
|
||||||
}
|
}
|
||||||
else
|
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)
|
mechanism = new (std::nothrow)
|
||||||
plain_mechanism_t (session, peer_address, options);
|
plain_mechanism_t (session, peer_address, options);
|
||||||
alloc_assert (mechanism);
|
alloc_assert (mechanism);
|
||||||
}
|
}
|
||||||
#ifdef HAVE_LIBSODIUM
|
#ifdef HAVE_LIBSODIUM
|
||||||
else
|
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)
|
if (options.as_server)
|
||||||
mechanism = new (std::nothrow)
|
mechanism = new (std::nothrow)
|
||||||
curve_server_t (session, peer_address, options);
|
curve_server_t (session, peer_address, options);
|
||||||
@ -617,8 +642,8 @@ int zmq::stream_engine_t::process_handshake_command (msg_t *msg_)
|
|||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
if (mechanism->is_handshake_complete ())
|
if (mechanism->is_handshake_complete ())
|
||||||
mechanism_ready ();
|
mechanism_ready ();
|
||||||
if (output_paused)
|
if (output_stopped)
|
||||||
activate_out ();
|
restart_output ();
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
@ -633,10 +658,10 @@ void zmq::stream_engine_t::zap_msg_available ()
|
|||||||
error ();
|
error ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (input_paused)
|
if (input_stopped)
|
||||||
activate_in ();
|
restart_input ();
|
||||||
if (output_paused)
|
if (output_stopped)
|
||||||
activate_out ();
|
restart_output ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void zmq::stream_engine_t::mechanism_ready ()
|
void zmq::stream_engine_t::mechanism_ready ()
|
||||||
@ -652,6 +677,7 @@ void zmq::stream_engine_t::mechanism_ready ()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
errno_assert (rc == 0);
|
errno_assert (rc == 0);
|
||||||
|
session->flush ();
|
||||||
}
|
}
|
||||||
|
|
||||||
read_msg = &stream_engine_t::pull_and_encode;
|
read_msg = &stream_engine_t::pull_and_encode;
|
||||||
@ -738,7 +764,7 @@ int zmq::stream_engine_t::write (const void *data_, size_t size_)
|
|||||||
// we'll get an error (this may happen during the speculative write).
|
// we'll get an error (this may happen during the speculative write).
|
||||||
if (nbytes == SOCKET_ERROR && WSAGetLastError () == WSAEWOULDBLOCK)
|
if (nbytes == SOCKET_ERROR && WSAGetLastError () == WSAEWOULDBLOCK)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Signalise peer failure.
|
// Signalise peer failure.
|
||||||
if (nbytes == SOCKET_ERROR && (
|
if (nbytes == SOCKET_ERROR && (
|
||||||
WSAGetLastError () == WSAENETDOWN ||
|
WSAGetLastError () == WSAENETDOWN ||
|
||||||
@ -787,58 +813,45 @@ int zmq::stream_engine_t::read (void *data_, size_t size_)
|
|||||||
{
|
{
|
||||||
#ifdef ZMQ_HAVE_WINDOWS
|
#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
|
// 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).
|
// we'll get an error (this may happen during the speculative read).
|
||||||
if (nbytes == SOCKET_ERROR && WSAGetLastError () == WSAEWOULDBLOCK)
|
if (rc == SOCKET_ERROR) {
|
||||||
return 0;
|
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.
|
return rc == SOCKET_ERROR? -1: rc;
|
||||||
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;
|
|
||||||
|
|
||||||
#else
|
#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
|
// 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
|
// be able to read a single byte from the socket. Also, SIGSTOP issued
|
||||||
// by a debugging tool can result in EINTR error.
|
// by a debugging tool can result in EINTR error.
|
||||||
if (nbytes == -1 && (errno == EAGAIN || errno == EWOULDBLOCK ||
|
if (rc == -1) {
|
||||||
errno == EINTR))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// Signalise peer failure.
|
|
||||||
if (nbytes == -1) {
|
|
||||||
errno_assert (errno != EBADF
|
errno_assert (errno != EBADF
|
||||||
&& errno != EFAULT
|
&& errno != EFAULT
|
||||||
&& errno != EINVAL
|
&& errno != EINVAL
|
||||||
&& errno != ENOMEM
|
&& errno != ENOMEM
|
||||||
&& errno != ENOTSOCK);
|
&& errno != ENOTSOCK);
|
||||||
return -1;
|
if (errno == EWOULDBLOCK || errno == EINTR)
|
||||||
|
errno = EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Orderly shutdown by the peer.
|
return static_cast <int> (rc);
|
||||||
if (nbytes == 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return static_cast <int> (nbytes);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -60,8 +60,8 @@ namespace zmq
|
|||||||
void plug (zmq::io_thread_t *io_thread_,
|
void plug (zmq::io_thread_t *io_thread_,
|
||||||
zmq::session_base_t *session_);
|
zmq::session_base_t *session_);
|
||||||
void terminate ();
|
void terminate ();
|
||||||
void activate_in ();
|
void restart_input ();
|
||||||
void activate_out ();
|
void restart_output ();
|
||||||
void zap_msg_available ();
|
void zap_msg_available ();
|
||||||
|
|
||||||
// i_poll_events interface implementation.
|
// i_poll_events interface implementation.
|
||||||
@ -87,10 +87,9 @@ namespace zmq
|
|||||||
// of error or orderly shutdown by the other peer -1 is returned.
|
// of error or orderly shutdown by the other peer -1 is returned.
|
||||||
int write (const void *data_, size_t size_);
|
int write (const void *data_, size_t size_);
|
||||||
|
|
||||||
// Reads data from the socket (up to 'size' bytes). Returns the number
|
// Reads data from the socket (up to 'size' bytes).
|
||||||
// of bytes actually read (even zero is to be considered to be
|
// Returns the number of bytes actually read or -1 on error.
|
||||||
// a success). In case of error or orderly shutdown by the other
|
// Zero indicates the peer has closed the connection.
|
||||||
// peer -1 is returned.
|
|
||||||
int read (void *data_, size_t size_);
|
int read (void *data_, size_t size_);
|
||||||
|
|
||||||
int read_identity (msg_t *msg_);
|
int read_identity (msg_t *msg_);
|
||||||
@ -163,7 +162,6 @@ namespace zmq
|
|||||||
std::string endpoint;
|
std::string endpoint;
|
||||||
|
|
||||||
bool plugged;
|
bool plugged;
|
||||||
bool terminating;
|
|
||||||
|
|
||||||
int (stream_engine_t::*read_msg) (msg_t *msg_);
|
int (stream_engine_t::*read_msg) (msg_t *msg_);
|
||||||
|
|
||||||
@ -179,10 +177,10 @@ namespace zmq
|
|||||||
mechanism_t *mechanism;
|
mechanism_t *mechanism;
|
||||||
|
|
||||||
// True iff the engine couldn't consume the last decoded message.
|
// 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.
|
// True iff the engine doesn't have any message to encode.
|
||||||
bool output_paused;
|
bool output_stopped;
|
||||||
|
|
||||||
// Socket
|
// Socket
|
||||||
zmq::socket_base_t *socket;
|
zmq::socket_base_t *socket;
|
||||||
|
32
src/tcp.cpp
Normal file → Executable file
32
src/tcp.cpp
Normal file → Executable 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
|
// Tuning TCP keep-alives if platform allows it
|
||||||
// All values = -1 means skip and leave it for OS
|
// 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
|
#ifdef ZMQ_HAVE_SO_KEEPALIVE
|
||||||
if (keepalive_ != -1) {
|
if (keepalive_ != -1) {
|
||||||
int rc = setsockopt (s_, SOL_SOCKET, SO_KEEPALIVE, (char*) &keepalive_, sizeof (int));
|
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);
|
errno_assert (rc == 0);
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ZMQ_HAVE_TCP_KEEPCNT
|
#ifdef ZMQ_HAVE_TCP_KEEPCNT
|
||||||
if (keepalive_cnt_ != -1) {
|
if (keepalive_cnt_ != -1) {
|
||||||
int rc = setsockopt (s_, IPPROTO_TCP, TCP_KEEPCNT, &keepalive_cnt_, sizeof (int));
|
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);
|
errno_assert (rc == 0);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#endif // ZMQ_HAVE_TCP_KEEPCNT
|
#endif // ZMQ_HAVE_TCP_KEEPCNT
|
||||||
|
|
||||||
#ifdef ZMQ_HAVE_TCP_KEEPIDLE
|
#ifdef ZMQ_HAVE_TCP_KEEPIDLE
|
||||||
if (keepalive_idle_ != -1) {
|
if (keepalive_idle_ != -1) {
|
||||||
int rc = setsockopt (s_, IPPROTO_TCP, TCP_KEEPIDLE, &keepalive_idle_, sizeof (int));
|
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);
|
errno_assert (rc == 0);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#else // ZMQ_HAVE_TCP_KEEPIDLE
|
#else // ZMQ_HAVE_TCP_KEEPIDLE
|
||||||
#ifdef ZMQ_HAVE_TCP_KEEPALIVE
|
#ifdef ZMQ_HAVE_TCP_KEEPALIVE
|
||||||
if (keepalive_idle_ != -1) {
|
if (keepalive_idle_ != -1) {
|
||||||
int rc = setsockopt (s_, IPPROTO_TCP, TCP_KEEPALIVE, &keepalive_idle_, sizeof (int));
|
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);
|
errno_assert (rc == 0);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#endif // ZMQ_HAVE_TCP_KEEPALIVE
|
#endif // ZMQ_HAVE_TCP_KEEPALIVE
|
||||||
#endif // ZMQ_HAVE_TCP_KEEPIDLE
|
#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
|
#ifdef ZMQ_HAVE_TCP_KEEPINTVL
|
||||||
if (keepalive_intvl_ != -1) {
|
if (keepalive_intvl_ != -1) {
|
||||||
int rc = setsockopt (s_, IPPROTO_TCP, TCP_KEEPINTVL, &keepalive_intvl_, sizeof (int));
|
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);
|
errno_assert (rc == 0);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#endif // ZMQ_HAVE_TCP_KEEPINTVL
|
#endif // ZMQ_HAVE_TCP_KEEPINTVL
|
||||||
}
|
}
|
||||||
#endif // ZMQ_HAVE_SO_KEEPALIVE
|
#endif // ZMQ_HAVE_SO_KEEPALIVE
|
||||||
|
#endif // ZMQ_HAVE_WINDOWS
|
||||||
}
|
}
|
||||||
|
@ -48,8 +48,7 @@ zmq::trie_t::~trie_t ()
|
|||||||
else
|
else
|
||||||
if (count > 1) {
|
if (count > 1) {
|
||||||
for (unsigned short i = 0; i != count; ++i)
|
for (unsigned short i = 0; i != count; ++i)
|
||||||
if (next.table [i])
|
delete next.table [i];
|
||||||
delete next.table [i];
|
|
||||||
free (next.table);
|
free (next.table);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
19
src/windows.hpp
Normal file → Executable file
19
src/windows.hpp
Normal file → Executable file
@ -152,8 +152,6 @@
|
|||||||
#define _WIN32_WINNT 0x0501
|
#define _WIN32_WINNT 0x0501
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
#ifdef __MINGW32__
|
#ifdef __MINGW32__
|
||||||
// Require Windows XP or higher with MinGW for getaddrinfo().
|
// Require Windows XP or higher with MinGW for getaddrinfo().
|
||||||
#if(_WIN32_WINNT >= 0x0501)
|
#if(_WIN32_WINNT >= 0x0501)
|
||||||
@ -164,8 +162,25 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
|
#include <windows.h>
|
||||||
#include <mswsock.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 <ws2tcpip.h>
|
||||||
#include <ipexport.h>
|
#include <ipexport.h>
|
||||||
#if !defined _WIN32_WCE
|
#if !defined _WIN32_WCE
|
||||||
|
@ -72,8 +72,7 @@ namespace zmq
|
|||||||
}
|
}
|
||||||
|
|
||||||
chunk_t *sc = spare_chunk.xchg (NULL);
|
chunk_t *sc = spare_chunk.xchg (NULL);
|
||||||
if (sc)
|
free (sc);
|
||||||
free (sc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns reference to the front element of the queue.
|
// 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
|
// so for cache reasons we'll get rid of the spare and
|
||||||
// use 'o' as the spare.
|
// use 'o' as the spare.
|
||||||
chunk_t *cs = spare_chunk.xchg (o);
|
chunk_t *cs = spare_chunk.xchg (o);
|
||||||
if (cs)
|
free (cs);
|
||||||
free (cs);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
15
src/zmq.cpp
15
src/zmq.cpp
@ -1016,7 +1016,7 @@ int zmq_poll (zmq_pollitem_t *items_, int nitems_, long timeout_)
|
|||||||
|
|
||||||
// The proxy functionality
|
// The proxy functionality
|
||||||
|
|
||||||
int zmq_proxy (void *frontend_, void *backend_, void *control_)
|
int zmq_proxy (void *frontend_, void *backend_, void *capture_)
|
||||||
{
|
{
|
||||||
if (!frontend_ || !backend_) {
|
if (!frontend_ || !backend_) {
|
||||||
errno = EFAULT;
|
errno = EFAULT;
|
||||||
@ -1025,6 +1025,19 @@ int zmq_proxy (void *frontend_, void *backend_, void *control_)
|
|||||||
return zmq::proxy (
|
return zmq::proxy (
|
||||||
(zmq::socket_base_t*) frontend_,
|
(zmq::socket_base_t*) frontend_,
|
||||||
(zmq::socket_base_t*) backend_,
|
(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_);
|
(zmq::socket_base_t*) control_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,10 @@
|
|||||||
#else
|
#else
|
||||||
#include "windows.hpp"
|
#include "windows.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_LIBSODIUM
|
||||||
|
# include <sodium.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void zmq_sleep (int seconds_)
|
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
|
// 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
|
// size * 5 / 4 bytes long plus 1 byte for the null terminator. Returns
|
||||||
// dest. Size must be a multiple of 4.
|
// 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)
|
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 char_nbr = 0;
|
||||||
unsigned int byte_nbr = 0;
|
unsigned int byte_nbr = 0;
|
||||||
uint32_t value = 0;
|
uint32_t value = 0;
|
||||||
@ -125,19 +133,24 @@ char *zmq_z85_encode (char *dest, uint8_t *data, size_t size)
|
|||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// Decode an encoded string into a binary frame; dest must be at least
|
// Decode an encoded string into a binary frame; dest must be at least
|
||||||
// strlen (string) * 4 / 5 bytes long. Returns dest. strlen (string)
|
// strlen (string) * 4 / 5 bytes long. Returns dest. strlen (string)
|
||||||
// must be a multiple of 5.
|
// 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)
|
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 byte_nbr = 0;
|
||||||
unsigned int char_nbr = 0;
|
unsigned int char_nbr = 0;
|
||||||
|
unsigned int string_len = strlen (string);
|
||||||
uint32_t value = 0;
|
uint32_t value = 0;
|
||||||
while (char_nbr < strlen (string)) {
|
while (char_nbr < string_len) {
|
||||||
// Accumulate value in base 85
|
// Accumulate value in base 85
|
||||||
value = value * 85 + decoder [(uint8_t) string [char_nbr++] - 32];
|
value = value * 85 + decoder [(uint8_t) string [char_nbr++] - 32];
|
||||||
if (char_nbr % 5 == 0) {
|
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);
|
assert (byte_nbr == strlen (string) * 4 / 5);
|
||||||
return dest;
|
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
|
||||||
|
}
|
||||||
|
@ -14,12 +14,12 @@ noinst_PROGRAMS = test_system \
|
|||||||
test_invalid_rep \
|
test_invalid_rep \
|
||||||
test_msg_flags \
|
test_msg_flags \
|
||||||
test_connect_resolve \
|
test_connect_resolve \
|
||||||
test_connect_delay \
|
test_immediate \
|
||||||
test_last_endpoint \
|
test_last_endpoint \
|
||||||
test_term_endpoint \
|
test_term_endpoint \
|
||||||
test_linger \
|
|
||||||
test_monitor \
|
test_monitor \
|
||||||
test_router_mandatory \
|
test_router_mandatory \
|
||||||
|
test_router_raw_empty \
|
||||||
test_probe_router \
|
test_probe_router \
|
||||||
test_stream \
|
test_stream \
|
||||||
test_disconnect_inproc \
|
test_disconnect_inproc \
|
||||||
@ -34,10 +34,14 @@ noinst_PROGRAMS = test_system \
|
|||||||
test_spec_dealer \
|
test_spec_dealer \
|
||||||
test_spec_router \
|
test_spec_router \
|
||||||
test_spec_pushpull \
|
test_spec_pushpull \
|
||||||
test_req_request_ids \
|
test_req_correlate \
|
||||||
test_req_strict \
|
test_req_relaxed \
|
||||||
test_conflate \
|
test_conflate \
|
||||||
test_inproc_connect
|
test_inproc_connect \
|
||||||
|
test_issue_566 \
|
||||||
|
test_abstract_ipc \
|
||||||
|
test_proxy_terminate \
|
||||||
|
test_many_sockets
|
||||||
|
|
||||||
if !ON_MINGW
|
if !ON_MINGW
|
||||||
noinst_PROGRAMS += test_shutdown_stress \
|
noinst_PROGRAMS += test_shutdown_stress \
|
||||||
@ -56,14 +60,14 @@ test_hwm_SOURCES = test_hwm.cpp
|
|||||||
test_reqrep_device_SOURCES = test_reqrep_device.cpp
|
test_reqrep_device_SOURCES = test_reqrep_device.cpp
|
||||||
test_sub_forward_SOURCES = test_sub_forward.cpp
|
test_sub_forward_SOURCES = test_sub_forward.cpp
|
||||||
test_invalid_rep_SOURCES = test_invalid_rep.cpp
|
test_invalid_rep_SOURCES = test_invalid_rep.cpp
|
||||||
test_linger_SOURCES = test_linger.cpp
|
|
||||||
test_msg_flags_SOURCES = test_msg_flags.cpp
|
test_msg_flags_SOURCES = test_msg_flags.cpp
|
||||||
test_connect_resolve_SOURCES = test_connect_resolve.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_last_endpoint_SOURCES = test_last_endpoint.cpp
|
||||||
test_term_endpoint_SOURCES = test_term_endpoint.cpp
|
test_term_endpoint_SOURCES = test_term_endpoint.cpp
|
||||||
test_monitor_SOURCES = test_monitor.cpp
|
test_monitor_SOURCES = test_monitor.cpp
|
||||||
test_router_mandatory_SOURCES = test_router_mandatory.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_probe_router_SOURCES = test_probe_router.cpp
|
||||||
test_stream_SOURCES = test_stream.cpp
|
test_stream_SOURCES = test_stream.cpp
|
||||||
test_disconnect_inproc_SOURCES = test_disconnect_inproc.cpp
|
test_disconnect_inproc_SOURCES = test_disconnect_inproc.cpp
|
||||||
@ -78,10 +82,14 @@ test_spec_rep_SOURCES = test_spec_rep.cpp
|
|||||||
test_spec_dealer_SOURCES = test_spec_dealer.cpp
|
test_spec_dealer_SOURCES = test_spec_dealer.cpp
|
||||||
test_spec_router_SOURCES = test_spec_router.cpp
|
test_spec_router_SOURCES = test_spec_router.cpp
|
||||||
test_spec_pushpull_SOURCES = test_spec_pushpull.cpp
|
test_spec_pushpull_SOURCES = test_spec_pushpull.cpp
|
||||||
test_req_request_ids_SOURCES = test_req_request_ids.cpp
|
test_req_correlate_SOURCES = test_req_correlate.cpp
|
||||||
test_req_strict_SOURCES = test_req_strict.cpp
|
test_req_relaxed_SOURCES = test_req_relaxed.cpp
|
||||||
test_conflate_SOURCES = test_conflate.cpp
|
test_conflate_SOURCES = test_conflate.cpp
|
||||||
test_inproc_connect_SOURCES = test_inproc_connect.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
|
||||||
|
test_proxy_terminate_SOURCES = test_proxy_terminate.cpp
|
||||||
if !ON_MINGW
|
if !ON_MINGW
|
||||||
test_shutdown_stress_SOURCES = test_shutdown_stress.cpp
|
test_shutdown_stress_SOURCES = test_shutdown_stress.cpp
|
||||||
test_pair_ipc_SOURCES = test_pair_ipc.cpp testutil.hpp
|
test_pair_ipc_SOURCES = test_pair_ipc.cpp testutil.hpp
|
||||||
@ -92,4 +100,7 @@ endif
|
|||||||
|
|
||||||
# Run the test cases
|
# Run the test cases
|
||||||
TESTS = $(noinst_PROGRAMS)
|
TESTS = $(noinst_PROGRAMS)
|
||||||
XFAIL_TESTS = test_linger
|
|
||||||
|
if !ON_LINUX
|
||||||
|
XFAIL_TESTS = test_abstract_ipc
|
||||||
|
endif
|
||||||
|
57
tests/test_abstract_ipc.cpp
Normal file
57
tests/test_abstract_ipc.cpp
Normal 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 ;
|
||||||
|
}
|
@ -45,7 +45,6 @@ int main (int argc, char *argv [])
|
|||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
|
|
||||||
int message_count = 20;
|
int message_count = 20;
|
||||||
|
|
||||||
for (int j = 0; j < message_count; ++j) {
|
for (int j = 0; j < message_count; ++j) {
|
||||||
rc = zmq_send(s_out, (void*)&j, sizeof(int), 0);
|
rc = zmq_send(s_out, (void*)&j, sizeof(int), 0);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
@ -53,15 +52,13 @@ int main (int argc, char *argv [])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
msleep (SETTLE_TIME);
|
||||||
zmq_sleep (1);
|
|
||||||
|
|
||||||
int payload_recved = 0;
|
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 (rc > 0);
|
||||||
assert (payload_recved == message_count - 1);
|
assert (payload_recved == message_count - 1);
|
||||||
|
|
||||||
|
|
||||||
rc = zmq_close (s_in);
|
rc = zmq_close (s_in);
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ void test_ctx_shutdown()
|
|||||||
void *receiver_thread = zmq_threadstart (&receiver, socket);
|
void *receiver_thread = zmq_threadstart (&receiver, socket);
|
||||||
|
|
||||||
// Wait for thread to start up and block
|
// Wait for thread to start up and block
|
||||||
zmq_sleep (1);
|
msleep (SETTLE_TIME);
|
||||||
|
|
||||||
// Shutdown context, if we used destroy here we would deadlock.
|
// Shutdown context, if we used destroy here we would deadlock.
|
||||||
rc = zmq_ctx_shutdown (ctx);
|
rc = zmq_ctx_shutdown (ctx);
|
||||||
|
@ -33,7 +33,7 @@ int main (void)
|
|||||||
assert (zmq_ctx_get (ctx, ZMQ_IPV6) == 0);
|
assert (zmq_ctx_get (ctx, ZMQ_IPV6) == 0);
|
||||||
|
|
||||||
rc = zmq_ctx_set (ctx, ZMQ_IPV6, true);
|
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);
|
void *router = zmq_socket (ctx, ZMQ_ROUTER);
|
||||||
int ipv6;
|
int ipv6;
|
||||||
|
@ -117,7 +117,7 @@ int main (void)
|
|||||||
|
|
||||||
// Set the key flag
|
// Set the key flag
|
||||||
val = 1;
|
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);
|
assert (rc == 0);
|
||||||
|
|
||||||
// Connect to the invalid socket
|
// Connect to the invalid socket
|
||||||
@ -170,9 +170,9 @@ int main (void)
|
|||||||
rc = zmq_setsockopt (frontend, ZMQ_LINGER, &zero, sizeof (zero));
|
rc = zmq_setsockopt (frontend, ZMQ_LINGER, &zero, sizeof (zero));
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
|
|
||||||
// Frontend connects to backend using DELAY_ATTACH_ON_CONNECT
|
// Frontend connects to backend using IMMEDIATE
|
||||||
int on = 1;
|
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);
|
assert (rc == 0);
|
||||||
rc = zmq_bind (backend, "tcp://127.0.0.1:5560");
|
rc = zmq_bind (backend, "tcp://127.0.0.1:5560");
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
@ -193,8 +193,7 @@ int main (void)
|
|||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
|
|
||||||
// Give time to process disconnect
|
// Give time to process disconnect
|
||||||
// There's no way to do this except with a sleep
|
msleep (SETTLE_TIME);
|
||||||
zmq_sleep(1);
|
|
||||||
|
|
||||||
// Send a message, should fail
|
// Send a message, should fail
|
||||||
rc = zmq_send (frontend, "Hello", 5, ZMQ_DONTWAIT);
|
rc = zmq_send (frontend, "Hello", 5, ZMQ_DONTWAIT);
|
@ -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.
|
This file is part of 0MQ.
|
||||||
|
|
||||||
@ -36,6 +36,40 @@ static void pusher (void *ctx)
|
|||||||
assert (rc == 0);
|
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 test_bind_before_connect()
|
||||||
{
|
{
|
||||||
void *ctx = zmq_ctx_new ();
|
void *ctx = zmq_ctx_new ();
|
||||||
@ -142,7 +176,7 @@ void test_connect_before_bind_pub_sub()
|
|||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
|
|
||||||
// Wait for pub-sub connection to happen
|
// Wait for pub-sub connection to happen
|
||||||
zmq_sleep (1);
|
msleep (SETTLE_TIME);
|
||||||
|
|
||||||
// Queue up some data, this not will be dropped
|
// Queue up some data, this not will be dropped
|
||||||
rc = zmq_send_const (connectSocket, "after", 6, 0);
|
rc = zmq_send_const (connectSocket, "after", 6, 0);
|
||||||
@ -268,6 +302,42 @@ void test_multiple_threads()
|
|||||||
assert (rc == 0);
|
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()
|
void test_identity()
|
||||||
{
|
{
|
||||||
// Create the infrastructure
|
// Create the infrastructure
|
||||||
@ -324,6 +394,23 @@ void test_identity()
|
|||||||
assert (rc == 0);
|
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)
|
int main (void)
|
||||||
{
|
{
|
||||||
setup_test_environment();
|
setup_test_environment();
|
||||||
@ -333,7 +420,9 @@ int main (void)
|
|||||||
test_connect_before_bind_pub_sub ();
|
test_connect_before_bind_pub_sub ();
|
||||||
test_multiple_connects ();
|
test_multiple_connects ();
|
||||||
test_multiple_threads ();
|
test_multiple_threads ();
|
||||||
|
test_simultaneous_connect_bind_threads ();
|
||||||
test_identity ();
|
test_identity ();
|
||||||
|
test_connect_only ();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,7 @@ int main (void)
|
|||||||
rc = zmq_bind (sb, "inproc://a");
|
rc = zmq_bind (sb, "inproc://a");
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
|
|
||||||
zmq_sleep(1);
|
msleep (SETTLE_TIME);
|
||||||
void *sc = zmq_socket (ctx, ZMQ_PUSH);
|
void *sc = zmq_socket (ctx, ZMQ_PUSH);
|
||||||
|
|
||||||
rc = zmq_connect (sc, "inproc://a");
|
rc = zmq_connect (sc, "inproc://a");
|
||||||
|
85
tests/test_issue_566.cpp
Normal file
85
tests/test_issue_566.cpp
Normal 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;
|
||||||
|
}
|
90
tests/test_many_sockets.cpp
Normal file
90
tests/test_many_sockets.cpp
Normal 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;
|
||||||
|
}
|
@ -211,7 +211,7 @@ int main (void)
|
|||||||
rc = zmq_socket_monitor (req, "inproc://monitor.req", ZMQ_EVENT_ALL);
|
rc = zmq_socket_monitor (req, "inproc://monitor.req", ZMQ_EVENT_ALL);
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
threads [1] = zmq_threadstart(&req_socket_monitor, ctx);
|
threads [1] = zmq_threadstart(&req_socket_monitor, ctx);
|
||||||
zmq_sleep(1);
|
msleep (SETTLE_TIME);
|
||||||
|
|
||||||
// Bind REQ and REP
|
// Bind REQ and REP
|
||||||
rc = zmq_bind (rep, addr.c_str());
|
rc = zmq_bind (rep, addr.c_str());
|
||||||
@ -238,8 +238,8 @@ int main (void)
|
|||||||
rc = zmq_close (rep);
|
rc = zmq_close (rep);
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
|
|
||||||
// Allow some time for detecting error states
|
// Allow enough time for detecting error states
|
||||||
zmq_sleep(1);
|
msleep (250);
|
||||||
|
|
||||||
// Close the REQ socket
|
// Close the REQ socket
|
||||||
rc = zmq_close (req);
|
rc = zmq_close (req);
|
||||||
|
113
tests/test_proxy_terminate.cpp
Normal file
113
tests/test_proxy_terminate.cpp
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2007-2015 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 "../include/zmq_utils.h"
|
||||||
|
|
||||||
|
// This is a test for issue #1382. The server thread creates a SUB-PUSH
|
||||||
|
// steerable proxy. The main process then sends messages to the SUB
|
||||||
|
// but there is no pull on the other side, previously the proxy blocks
|
||||||
|
// in writing to the backend, preventing the proxy from terminating
|
||||||
|
|
||||||
|
void
|
||||||
|
server_task (void *ctx)
|
||||||
|
{
|
||||||
|
// Frontend socket talks to main process
|
||||||
|
void *frontend = zmq_socket (ctx, ZMQ_SUB);
|
||||||
|
assert (frontend);
|
||||||
|
int rc = zmq_setsockopt (frontend, ZMQ_SUBSCRIBE, "", 0);
|
||||||
|
assert (rc == 0);
|
||||||
|
rc = zmq_bind (frontend, "tcp://127.0.0.1:15564");
|
||||||
|
assert (rc == 0);
|
||||||
|
|
||||||
|
// Nice socket which is never read
|
||||||
|
void *backend = zmq_socket (ctx, ZMQ_PUSH);
|
||||||
|
assert (backend);
|
||||||
|
rc = zmq_bind (backend, "tcp://127.0.0.1:15563");
|
||||||
|
assert (rc == 0);
|
||||||
|
|
||||||
|
// Control socket receives terminate command from main over inproc
|
||||||
|
void *control = zmq_socket (ctx, ZMQ_SUB);
|
||||||
|
assert (control);
|
||||||
|
rc = zmq_setsockopt (control, ZMQ_SUBSCRIBE, "", 0);
|
||||||
|
assert (rc == 0);
|
||||||
|
rc = zmq_connect (control, "inproc://control");
|
||||||
|
assert (rc == 0);
|
||||||
|
|
||||||
|
// Connect backend to frontend via a proxy
|
||||||
|
zmq_proxy_steerable (frontend, backend, NULL, control);
|
||||||
|
|
||||||
|
rc = zmq_close (frontend);
|
||||||
|
assert (rc == 0);
|
||||||
|
rc = zmq_close (backend);
|
||||||
|
assert (rc == 0);
|
||||||
|
rc = zmq_close (control);
|
||||||
|
assert (rc == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// The main thread simply starts a basic steerable proxy server, publishes some messages, and then
|
||||||
|
// waits for the server to terminate.
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
setup_test_environment ();
|
||||||
|
|
||||||
|
void *ctx = zmq_ctx_new ();
|
||||||
|
assert (ctx);
|
||||||
|
// Control socket receives terminate command from main over inproc
|
||||||
|
void *control = zmq_socket (ctx, ZMQ_PUB);
|
||||||
|
assert (control);
|
||||||
|
int rc = zmq_bind (control, "inproc://control");
|
||||||
|
assert (rc == 0);
|
||||||
|
|
||||||
|
void *thread = zmq_threadstart(&server_task, ctx);
|
||||||
|
msleep (500); // Run for 500 ms
|
||||||
|
|
||||||
|
// Start a secondary publisher which writes data to the SUB-PUSH server socket
|
||||||
|
void *publisher = zmq_socket (ctx, ZMQ_PUB);
|
||||||
|
assert (publisher);
|
||||||
|
rc = zmq_connect (publisher, "tcp://127.0.0.1:15564");
|
||||||
|
assert (rc == 0);
|
||||||
|
|
||||||
|
msleep (50);
|
||||||
|
rc = zmq_send (publisher, "This is a test", 14, 0);
|
||||||
|
assert (rc == 14);
|
||||||
|
|
||||||
|
msleep (50);
|
||||||
|
rc = zmq_send (publisher, "This is a test", 14, 0);
|
||||||
|
assert (rc == 14);
|
||||||
|
|
||||||
|
msleep (50);
|
||||||
|
rc = zmq_send (publisher, "This is a test", 14, 0);
|
||||||
|
assert (rc == 14);
|
||||||
|
rc = zmq_send (control, "TERMINATE", 9, 0);
|
||||||
|
assert (rc == 9);
|
||||||
|
|
||||||
|
rc = zmq_close (publisher);
|
||||||
|
assert (rc == 0);
|
||||||
|
rc = zmq_close (control);
|
||||||
|
assert (rc == 0);
|
||||||
|
|
||||||
|
zmq_threadclose (thread);
|
||||||
|
|
||||||
|
rc = zmq_ctx_term (ctx);
|
||||||
|
assert (rc == 0);
|
||||||
|
return 0;
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user