mirror of
https://github.com/zeromq/libzmq.git
synced 2025-08-11 13:08:16 +02:00
Compare commits
159 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
0fd30dc34a | ||
![]() |
d532e01abc | ||
![]() |
ec0706d5fa | ||
![]() |
f43148eaf9 | ||
![]() |
346527a1cf | ||
![]() |
00e5b37420 | ||
![]() |
6077e52425 | ||
![]() |
c7c5228a86 | ||
![]() |
0a703a4d06 | ||
![]() |
c9f5ec7da6 | ||
![]() |
9e6bdb5bc5 | ||
![]() |
ea9af1cadb | ||
![]() |
833a3c52d2 | ||
![]() |
f5bc82d9a4 | ||
![]() |
84f00c06d6 | ||
![]() |
b5312d38cc | ||
![]() |
aca1fce1cc | ||
![]() |
2742c4afd4 | ||
![]() |
29905ac56a | ||
![]() |
930252a737 | ||
![]() |
48cc4c74c4 | ||
![]() |
86717b2a29 | ||
![]() |
d0aa05fac4 | ||
![]() |
dbc42ee9af | ||
![]() |
15e4cf2c67 | ||
![]() |
f45dd95ed8 | ||
![]() |
289db060bd | ||
![]() |
e7fda86ce2 | ||
![]() |
a7f2ad0b24 | ||
![]() |
b36545fe70 | ||
![]() |
687ea29280 | ||
![]() |
2255369a69 | ||
![]() |
c832e3d1df | ||
![]() |
7f44310670 | ||
![]() |
ba597c6e47 | ||
![]() |
d1ea5e525e | ||
![]() |
d246aaceee | ||
![]() |
143ae519b4 | ||
![]() |
2aca7b233b | ||
![]() |
00c0d5835f | ||
![]() |
60b64748e5 | ||
![]() |
aeb87cf2cc | ||
![]() |
703c1a6e04 | ||
![]() |
7604dd2d47 | ||
![]() |
a941934e34 | ||
![]() |
51066c9767 | ||
![]() |
bd77676d99 | ||
![]() |
20cce750fa | ||
![]() |
1b5b18cba9 | ||
![]() |
8b6dcc8420 | ||
![]() |
3d353f8306 | ||
![]() |
ad14c562d7 | ||
![]() |
37a0ec5936 | ||
![]() |
e9755d2a39 | ||
![]() |
96fbeea5f6 | ||
![]() |
0836de2f2e | ||
![]() |
26b182fe76 | ||
![]() |
d7cad1b52a | ||
![]() |
573a1eab4b | ||
![]() |
0e5c98a9fe | ||
![]() |
2c55496d28 | ||
![]() |
094eceefb8 | ||
![]() |
14bb2e46a5 | ||
![]() |
11bae19cf8 | ||
![]() |
a3dafd408f | ||
![]() |
58c1ba8994 | ||
![]() |
c710a39b9e | ||
![]() |
400cbc208a | ||
![]() |
bdd72826c9 | ||
![]() |
1e435f59c3 | ||
![]() |
0f6e357894 | ||
![]() |
a85ddf3e1a | ||
![]() |
41b7f74d49 | ||
![]() |
69dbe0113a | ||
![]() |
894c0fb87b | ||
![]() |
521ed91289 | ||
![]() |
a436d14547 | ||
![]() |
1a17eb392e | ||
![]() |
4f1f68f6cc | ||
![]() |
5d3781a8bf | ||
![]() |
d6aaa4a7ba | ||
![]() |
b774772bb9 | ||
![]() |
a0a24a92af | ||
![]() |
6a7dcfb898 | ||
![]() |
8e748064ac | ||
![]() |
c436c8cdc3 | ||
![]() |
0df7bbbc9d | ||
![]() |
c2b6f06d0d | ||
![]() |
4a0410ad21 | ||
![]() |
572be0e82c | ||
![]() |
92446d81ce | ||
![]() |
96ce417422 | ||
![]() |
911387cfbb | ||
![]() |
2131e85cd7 | ||
![]() |
fbfd3c34d9 | ||
![]() |
1965e2d05d | ||
![]() |
a91779baf1 | ||
![]() |
8e6fdc56e1 | ||
![]() |
b0563c2103 | ||
![]() |
2388f27bfe | ||
![]() |
ba1fd8e82a | ||
![]() |
6d4e2ce93b | ||
![]() |
7541e38205 | ||
![]() |
c7786d4374 | ||
![]() |
ed8ab632c6 | ||
![]() |
2ae1bd2088 | ||
![]() |
3b268c6943 | ||
![]() |
025e218629 | ||
![]() |
61b936893d | ||
![]() |
bcf8916e17 | ||
![]() |
12f3f8a7f6 | ||
![]() |
9120741719 | ||
![]() |
efdb5cf076 | ||
![]() |
ae8c4a4adf | ||
![]() |
f9b6da0e78 | ||
![]() |
f5a9c328e9 | ||
![]() |
65a29e85ee | ||
![]() |
f0383bffad | ||
![]() |
a7438de239 | ||
![]() |
7f81575245 | ||
![]() |
c05a1b1f26 | ||
![]() |
f976e8cc98 | ||
![]() |
07122eefec | ||
![]() |
69fa792cae | ||
![]() |
30738e1123 | ||
![]() |
50b6da0c1c | ||
![]() |
0c0a351fa5 | ||
![]() |
36736e64cc | ||
![]() |
50e9d72dc4 | ||
![]() |
87c6ebb135 | ||
![]() |
4527d8db6f | ||
![]() |
ed9c7440d2 | ||
![]() |
fec6497976 | ||
![]() |
f56c6faf65 | ||
![]() |
1d9a3fd480 | ||
![]() |
fff267071d | ||
![]() |
ec8d935acc | ||
![]() |
08b0af5075 | ||
![]() |
b0576e8c54 | ||
![]() |
5b9de45a89 | ||
![]() |
2996b25039 | ||
![]() |
09c56c4493 | ||
![]() |
d9d7d9be54 | ||
![]() |
d95f8c5f55 | ||
![]() |
ceb388e371 | ||
![]() |
888c1bdb5b | ||
![]() |
a5da31eb07 | ||
![]() |
bbff2fc3f8 | ||
![]() |
c391966fbb | ||
![]() |
24ea41ce7a | ||
![]() |
d0eed09f6f | ||
![]() |
5e4f858c8e | ||
![]() |
bdbdf8bb7e | ||
![]() |
30e2da05a1 | ||
![]() |
2fe4a355fd | ||
![]() |
da7427b771 | ||
![]() |
e18b69bfa1 | ||
![]() |
05bd3ea8b9 | ||
![]() |
7735322151 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -42,6 +42,7 @@ tests/test_connect_resolve
|
||||
tests/test_connect_delay
|
||||
tests/test_term_endpoint
|
||||
tests/test_router_mandatory
|
||||
tests/test_disconnect_inproc
|
||||
src/platform.hpp*
|
||||
src/stamp-h1
|
||||
perf/local_lat
|
||||
|
2
.travis.yml
Normal file
2
.travis.yml
Normal file
@ -0,0 +1,2 @@
|
||||
script: ./autogen.sh && ./configure && make && make check
|
||||
language: c
|
1
AUTHORS
1
AUTHORS
@ -66,6 +66,7 @@ Pieter Hintjens <ph@imatix.com>
|
||||
Piotr Trojanek <piotr.trojanek@gmail.com>
|
||||
Robert G. Jakabosky <bobby@sharedrealm.com>
|
||||
Sebastian Otaegui <feniix@gmail.com>
|
||||
Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de>
|
||||
Steven McCoy <steven.mccoy@miru.hk>
|
||||
Stuart Webster <sw_webster@hotmail.com>
|
||||
Tamara Kustarova <kustarova.tamara@gmail.com>
|
||||
|
114
CMakeLists.txt
114
CMakeLists.txt
@ -1,6 +1,9 @@
|
||||
# CMake build script for ZeroMQ on Windows
|
||||
|
||||
cmake_minimum_required (VERSION 2.8)
|
||||
# 2.8.11 provides toolkit support
|
||||
# 2.8.11.2 provides MSVC2013 support
|
||||
|
||||
cmake_minimum_required (VERSION 2.8.11.2)
|
||||
project (ZeroMQ)
|
||||
|
||||
include (${CMAKE_SOURCE_DIR}/cmake/Modules/TestZMQVersion.cmake)
|
||||
@ -11,11 +14,36 @@ option (WITH_OPENPGM "Build with support for OpenPGM" OFF)
|
||||
# WARNING: Windows Python will override Cygwin yet not work with Asciidoc.
|
||||
#find_package (PythonInterp REQUIRED)
|
||||
# Workaround, manually set Python location
|
||||
set(PYTHON_EXECUTABLE c:/cygwin/bin/python2.6.exe CACHE FILEPATH "Python interpreter executable")
|
||||
set(PYTHON_EXECUTABLE c:/cygwin/bin/python2.7.exe CACHE FILEPATH "Python interpreter executable")
|
||||
# TODO: Replace with FindAsciidoc.cmake
|
||||
set(ASCIIDOC_EXECUTABLE c:/cygwin/bin/asciidoc CACHE FILEPATH "AsciiDoc executable")
|
||||
|
||||
set(OPENPGM_ROOT /libpgm/libpgm-5.1.118-1~dfsg/openpgm/pgm CACHE PATH "Location of OpenPGM")
|
||||
if (WITH_OPENPGM)
|
||||
# set(OPENPGM_ROOT "" CACHE PATH "Location of OpenPGM")
|
||||
set(OPENPGM_VERSION_MAJOR 5)
|
||||
set(OPENPGM_VERSION_MINOR 2)
|
||||
set(OPENPGM_VERSION_MICRO 122)
|
||||
if (CMAKE_CL_64)
|
||||
find_path(OPENPGM_ROOT include/pgm/pgm.h
|
||||
PATHS
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Miru\\OpenPGM ${OPENPGM_VERSION_MAJOR}.${OPENPGM_VERSION_MINOR}.${OPENPGM_VERSION_MICRO}]"
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
else (CMAKE_CL_64)
|
||||
find_path(OPENPGM_ROOT include/pgm/pgm.h
|
||||
PATHS
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Miru\\OpenPGM ${OPENPGM_VERSION_MAJOR}.${OPENPGM_VERSION_MINOR}.${OPENPGM_VERSION_MICRO}]"
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Miru\\OpenPGM ${OPENPGM_VERSION_MAJOR}.${OPENPGM_VERSION_MINOR}.${OPENPGM_VERSION_MICRO}]"
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
endif (CMAKE_CL_64)
|
||||
message(STATUS "OpenPGM detected - ${OPENPGM_ROOT}")
|
||||
set(OPENPGM_INCLUDE_DIRS ${OPENPGM_ROOT}/include)
|
||||
set(OPENPGM_LIBRARY_DIRS ${OPENPGM_ROOT}/lib)
|
||||
set(OPENPGM_LIBRARIES
|
||||
optimized libpgm${_zmq_TOOLSET}-mt-${OPENPGM_VERSION_MAJOR}_${OPENPGM_VERSION_MINOR}_${OPENPGM_VERSION_MICRO}.lib
|
||||
debug libpgm${_zmq_TOOLSET}-mt-gd-${OPENPGM_VERSION_MAJOR}_${OPENPGM_VERSION_MINOR}_${OPENPGM_VERSION_MICRO}.lib)
|
||||
endif (WITH_OPENPGM)
|
||||
|
||||
mark_as_advanced(PYTHON_EXECUTABLE ASCIIDOC_EXECUTABLE)
|
||||
|
||||
@ -54,6 +82,7 @@ add_definitions(
|
||||
# NB: May require tweaking for highly connected applications.
|
||||
-DFD_SETSIZE=1024
|
||||
-D_CRT_SECURE_NO_WARNINGS
|
||||
-D_WIN32_WINNT=${_zmq_WIN32_WINNT}
|
||||
)
|
||||
|
||||
# Parallel make.
|
||||
@ -160,28 +189,13 @@ if(WITH_OPENPGM)
|
||||
add_definitions(
|
||||
-DZMQ_HAVE_OPENPGM
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${OPENPGM_ROOT}/include
|
||||
${OPENPGM_INCLUDE_DIRS}
|
||||
)
|
||||
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
# Win64
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(OPENPGM_LIBRARYDIR ${OPENPGM_ROOT}/debug64/lib)
|
||||
else (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(OPENPGM_LIBRARYDIR ${OPENPGM_ROOT}/build64/lib)
|
||||
endif (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
else (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
# Win32
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(OPENPGM_LIBRARYDIR ${OPENPGM_ROOT}/debug/lib)
|
||||
else (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(OPENPGM_LIBRARYDIR ${OPENPGM_ROOT}/build/lib)
|
||||
endif (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
endif (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
link_directories(
|
||||
${OPENPGM_LIBRARYDIR}
|
||||
${OPENPGM_LIBRARY_DIRS}
|
||||
)
|
||||
set(OPTIONAL_LIBRARIES ${OPENPGM_LIBRARIES})
|
||||
endif(WITH_OPENPGM)
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
@ -207,11 +221,11 @@ add_custom_command(
|
||||
)
|
||||
list(APPEND sources ${CMAKE_BINARY_DIR}/platform.hpp)
|
||||
|
||||
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
if (CMAKE_CL_64)
|
||||
set (nsis-template ${CMAKE_SOURCE_DIR}/cmake/NSIS.template64.in)
|
||||
else (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
else (CMAKE_CL_64)
|
||||
set (nsis-template ${CMAKE_SOURCE_DIR}/cmake/NSIS.template32.in)
|
||||
endif (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
endif (CMAKE_CL_64)
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_BINARY_DIR}/NSIS.template.in
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
@ -252,19 +266,29 @@ endforeach (txt ${docs})
|
||||
#-----------------------------------------------------------------------------
|
||||
# output
|
||||
|
||||
message(targetting ${_zmq_TOOLSET})
|
||||
|
||||
add_library(libzmq SHARED ${sources} ${html-docs} ${CMAKE_BINARY_DIR}/NSIS.template.in)
|
||||
target_link_libraries(libzmq ws2_32.lib rpcrt4.lib)
|
||||
target_link_libraries(libzmq ws2_32.lib rpcrt4.lib ${OPTIONAL_LIBRARIES})
|
||||
set_target_properties(libzmq PROPERTIES
|
||||
RELEASE_POSTFIX "${_zmq_TOOLSET}-mt-${ZMQ_VERSION_MAJOR}_${ZMQ_VERSION_MINOR}_${ZMQ_VERSION_PATCH}"
|
||||
DEBUG_POSTFIX "${_zmq_TOOLSET}-mt-gd-${ZMQ_VERSION_MAJOR}_${ZMQ_VERSION_MINOR}_${ZMQ_VERSION_PATCH}"
|
||||
PDB_NAME "libzmq${_zmq_TOOLSET}-mt-gd-${ZMQ_VERSION_MAJOR}_${ZMQ_VERSION_MINOR}_${ZMQ_VERSION_PATCH}"
|
||||
PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib"
|
||||
)
|
||||
|
||||
set_target_properties(libzmq PROPERTIES RELEASE_POSTFIX "${_zmq_COMPILER}-mt" DEBUG_POSTFIX "${_zmq_COMPILER}-mt-gd")
|
||||
#-----------------------------------------------------------------------------
|
||||
# installer
|
||||
|
||||
install (TARGETS libzmq ARCHIVE DESTINATION lib COMPONENT SDK)
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
install (FILES ${CMAKE_BINARY_DIR}/lib/libzmq${_zmq_COMPILER}-mt-gd.dll DESTINATION bin COMPONENT SDK)
|
||||
install (FILES ${CMAKE_BINARY_DIR}/lib/libzmq${_zmq_COMPILER}-mt-gd.lib DESTINATION lib COMPONENT SDK)
|
||||
install (FILES ${CMAKE_BINARY_DIR}/lib/libzmq${_zmq_COMPILER}-mt-gd.pdb DESTINATION lib COMPONENT SDK)
|
||||
else (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
# no -op
|
||||
else ()
|
||||
install (TARGETS libzmq RUNTIME DESTINATION bin COMPONENT Runtime)
|
||||
install (FILES ${CMAKE_BINARY_DIR}/lib/libzmq${_zmq_COMPILER}-mt.lib DESTINATION lib COMPONENT SDK)
|
||||
endif (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
install (FILES ${CMAKE_BINARY_DIR}/lib/Debug/libzmq${_zmq_TOOLSET}-mt-gd-${ZMQ_VERSION_MAJOR}_${ZMQ_VERSION_MINOR}_${ZMQ_VERSION_PATCH}.lib DESTINATION lib COMPONENT SDK)
|
||||
install (FILES ${CMAKE_BINARY_DIR}/lib/Debug/libzmq${_zmq_TOOLSET}-mt-gd-${ZMQ_VERSION_MAJOR}_${ZMQ_VERSION_MINOR}_${ZMQ_VERSION_PATCH}.pdb DESTINATION lib COMPONENT SDK)
|
||||
install (FILES ${CMAKE_BINARY_DIR}/lib/Debug/libzmq${_zmq_TOOLSET}-mt-gd-${ZMQ_VERSION_MAJOR}_${ZMQ_VERSION_MINOR}_${ZMQ_VERSION_PATCH}.dll DESTINATION bin COMPONENT SDK)
|
||||
endif ()
|
||||
install (FILES ${headers} DESTINATION include COMPONENT SDK)
|
||||
|
||||
set (perf-tools
|
||||
@ -296,18 +320,28 @@ endif (WITH_DOC)
|
||||
|
||||
include (InstallRequiredSystemLibraries)
|
||||
|
||||
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
if (CMAKE_CL_64)
|
||||
set (CPACK_NSIS_DISPLAY_NAME "ZeroMQ ${ZMQ_VERSION_MAJOR}.${ZMQ_VERSION_MINOR}.${ZMQ_VERSION_PATCH} (x64)")
|
||||
set (CPACK_PACKAGE_FILE_NAME "ZeroMQ-${ZMQ_VERSION_MAJOR}.${ZMQ_VERSION_MINOR}.${ZMQ_VERSION_PATCH}-x64")
|
||||
set (CPACK_INSTALL_CMAKE_PROJECTS
|
||||
"${CMAKE_SOURCE_DIR}/build64;ZeroMQ;ALL;/"
|
||||
"${CMAKE_SOURCE_DIR}/debug64;ZeroMQ;ALL;/"
|
||||
"${CMAKE_SOURCE_DIR}/build/x64/v90;ZeroMQ;ALL;/"
|
||||
"${CMAKE_SOURCE_DIR}/build/x64/v110;ZeroMQ;ALL;/"
|
||||
"${CMAKE_SOURCE_DIR}/build/x64/v120;ZeroMQ;ALL;/"
|
||||
# default to 2008/Vista compatible CRT
|
||||
"${CMAKE_SOURCE_DIR}/build/x64/v100;ZeroMQ;ALL;/"
|
||||
)
|
||||
else (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
else (CMAKE_CL_64)
|
||||
set (CPACK_NSIS_DISPLAY_NAME "ZeroMQ ${ZMQ_VERSION_MAJOR}.${ZMQ_VERSION_MINOR}.${ZMQ_VERSION_PATCH}")
|
||||
set (CPACK_PACKAGE_FILE_NAME "ZeroMQ-${ZMQ_VERSION_MAJOR}.${ZMQ_VERSION_MINOR}.${ZMQ_VERSION_PATCH}-x86")
|
||||
set (CPACK_INSTALL_CMAKE_PROJECTS
|
||||
"${CMAKE_SOURCE_DIR}/build;ZeroMQ;ALL;/"
|
||||
"${CMAKE_SOURCE_DIR}/debug;ZeroMQ;ALL;/"
|
||||
"${CMAKE_SOURCE_DIR}/build/x86/v90;ZeroMQ;ALL;/"
|
||||
"${CMAKE_SOURCE_DIR}/build/x86/v100;ZeroMQ;ALL;/"
|
||||
"${CMAKE_SOURCE_DIR}/build/x86/v110;ZeroMQ;ALL;/"
|
||||
"${CMAKE_SOURCE_DIR}/build/x86/v120;ZeroMQ;ALL;/"
|
||||
# default to XP-compatible CRT
|
||||
"${CMAKE_SOURCE_DIR}/build/x86/v110_xp;ZeroMQ;ALL;/"
|
||||
)
|
||||
endif (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
|
||||
endif (CMAKE_CL_64)
|
||||
set (CMAKE_MODULE_PATH "${CMAKE_BINARY_DIR}")
|
||||
set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "ZeroMQ lightweight messaging kernel")
|
||||
set (CPACK_PACKAGE_VENDOR "Miru")
|
||||
|
7
INSTALL
7
INSTALL
@ -7,6 +7,13 @@ Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
|
||||
This file is free documentation; the Free Software Foundation gives
|
||||
unlimited permission to copy, distribute and modify it.
|
||||
|
||||
From GitHub
|
||||
===========
|
||||
|
||||
If you clone the Git repository then you should start by running the
|
||||
command `./autogen.sh`. This is not necessary if you get the source
|
||||
packages.
|
||||
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
|
59
NEWS
59
NEWS
@ -1,3 +1,62 @@
|
||||
0MQ version 3.2.5 stable, released on 2014/10/14
|
||||
================================================
|
||||
|
||||
* LIBZMQ-39 Assertion failure "Bad file descriptor" during shutdown (rare)
|
||||
* LIBZMQ-576 Crash closing a socket after zmq_msg_send returns EAGAIN (reverts LIBZMQ-497)
|
||||
* Fixed issue #1002: rare divide-by zero error when sending message.
|
||||
|
||||
|
||||
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
|
||||
================================================
|
||||
|
||||
Issues addressed in this release
|
||||
--------------------------------
|
||||
|
||||
* LIBZMQ-384 No meta data for ZMQ_EVENT_DISCONNECTED monitor event
|
||||
* LIBZMQ-414 Error in ARM/Thumb2 assembly (atomic_ptr.hpp)
|
||||
* LIBZMQ-417 zmq_assert (!incomplete_in) in session_base.cpp 228
|
||||
* LIBZMQ-447 socket_base_t::recv() packet loss and memory leak at high receiving rate
|
||||
* LIBZMQ-448 Builds fail on older versions of GCC
|
||||
* LIBZMQ-449 Builds fail on AIX
|
||||
* LIBZMQ-450 lt-test_monitor: fails with assertion at test_monitor.cpp:81
|
||||
* LIBZMQ-451 ZMQ_ROUTER_MANDATORY blocks forever
|
||||
* LIBZMQ-452 test_connect_delay.cpp:175:12: error: 'sleep' was not declared in this scope
|
||||
* LIBZMQ-458 lt-test_router_mandatory fails with assertion at test_router_mandatory.cpp:53
|
||||
* LIBZMQ-459 Assertion failed: encoder (stream_engine.cpp:266
|
||||
* LIBZMQ-464 PUB socket with HWM set leaks memory
|
||||
* LIBZMQ-465 PUB/SUB results in 80-90% of CPU load
|
||||
* LIBZMQ-468 ZMQ_XPUB_VERBOSE & unsubscribe
|
||||
* LIBZMQ-472 Segfault in zmq_poll in REQ to ROUTER dialog
|
||||
|
||||
|
||||
0MQ version 3.2.1 (RC2), released on 2012/10/15
|
||||
===============================================
|
||||
|
||||
|
85
build-windows-installers.cmd
Normal file
85
build-windows-installers.cmd
Normal file
@ -0,0 +1,85 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
set WITH_OPENPGM=true
|
||||
set WITH_DOC=true
|
||||
|
||||
:: Remove old build files
|
||||
echo Cleaning build area ...
|
||||
rmdir /s /q build 2> null
|
||||
md build\x86\v90 build\x86\v100 build\x86\v110 build\x86\v110_xp build\x86\v120 2> null
|
||||
md build\x64\v90 build\x64\v100 build\x64\v110 build\x64\v120 2> null
|
||||
|
||||
echo Starting build ...
|
||||
call:buildx86 build\x86 ..\..
|
||||
call:buildx64 build\x64 ..\..
|
||||
|
||||
echo Build finished.
|
||||
goto:eof
|
||||
|
||||
:buildx86
|
||||
echo Building targets for x86 ...
|
||||
setlocal
|
||||
cd %~1\v90
|
||||
call "%ProgramFiles(x86)%\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x86
|
||||
cmake -G "Visual Studio 12" ..\..\.. -T "v90" -DWITH_OPENPGM=%WITH_OPENPGM% > build.log && msbuild /nologo /property:Configuration=Debug /target:ALL_BUILD ZeroMQ.sln >> build.log && msbuild /nologo /property:Configuration=Release /target:ALL_BUILD ZeroMQ.sln >> build.log
|
||||
for /D %%f in (lib\*) do dir %%f\*.dll | findstr "\/"
|
||||
cd ..\v100
|
||||
cmake -G "Visual Studio 12" ..\..\.. -T "v100" -DWITH_OPENPGM=%WITH_OPENPGM% > build.log && msbuild /nologo /property:Configuration=Debug ALL_BUILD.vcxproj >> build.log && msbuild /nologo /property:Configuration=Release ALL_BUILD.vcxproj >> build.log
|
||||
for /D %%f in (lib\*) do dir %%f\*.dll | findstr "\/"
|
||||
cd ..\v110
|
||||
cmake -G "Visual Studio 12" ..\..\.. -T "v110" -DWITH_OPENPGM=%WITH_OPENPGM% > build.log && msbuild /nologo /property:Configuration=Debug ALL_BUILD.vcxproj >> build.log && msbuild /nologo /property:Configuration=Release ALL_BUILD.vcxproj >> build.log
|
||||
for /D %%f in (lib\*) do dir %%f\*.dll | findstr "\/"
|
||||
cd ..\v120
|
||||
cmake -G "Visual Studio 12" ..\..\.. -T "v120" -DWITH_OPENPGM=%WITH_OPENPGM% > build.log && msbuild /nologo /property:Configuration=Debug ALL_BUILD.vcxproj >> build.log && msbuild /nologo /property:Configuration=Release ALL_BUILD.vcxproj >> build.log
|
||||
for /D %%f in (lib\*) do dir %%f\*.dll | findstr "\/"
|
||||
cd ..\v110_xp
|
||||
cmake -G "Visual Studio 12" ..\..\.. -T "v110_xp" -DWITH_OPENPGM=%WITH_OPENPGM% -DWITH_DOC=%WITH_DOC% > build.log && msbuild /nologo /property:Configuration=Debug ALL_BUILD.vcxproj >> build.log && msbuild /nologo /property:Configuration=Release PACKAGE.vcxproj >> build.log
|
||||
(
|
||||
dir *.exe
|
||||
for /D %%f in (lib\*) do dir %%f\*.dll
|
||||
) | findstr "\/"
|
||||
cd %~2
|
||||
endlocal
|
||||
goto:eof
|
||||
|
||||
:buildx64
|
||||
echo Building targets for x64 ...
|
||||
cd %~1
|
||||
|
||||
setlocal
|
||||
call "%ProgramFiles(x86)%\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x64
|
||||
|
||||
:: If linker crashes out with LNK1000 error install KB948127 to fix
|
||||
:: https://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.aspx?DownloadID=11399
|
||||
(
|
||||
cd v90
|
||||
cmake -G "Visual Studio 12 Win64" ..\..\.. -T "v90" -DWITH_OPENPGM=%WITH_OPENPGM% > build.log && msbuild /nologo /property:Configuration=Debug /target:ALL_BUILD ZeroMQ.sln >> build.log && msbuild /nologo /property:Configuration=Release /target:ALL_BUILD ZeroMQ.sln >> build.log
|
||||
for /D %%f in (lib\*) do dir %%f\*.dll | findstr "\/"
|
||||
cd ..
|
||||
)
|
||||
(
|
||||
cd v100
|
||||
cmake -G "Visual Studio 12 Win64" ..\..\.. -T "v100" -DWITH_OPENPGM=%WITH_OPENPGM% > build.log && msbuild /nologo /property:Configuration=Debug ALL_BUILD.vcxproj >> build.log && msbuild /nologo /property:Configuration=Release ALL_BUILD.vcxproj >> build.log
|
||||
for /D %%f in (lib\*) do dir %%f\*.dll | findstr "\/"
|
||||
cd ..
|
||||
)
|
||||
(
|
||||
cd v110
|
||||
cmake -G "Visual Studio 12 Win64" ..\..\.. -T "v110" -DWITH_OPENPGM=%WITH_OPENPGM% > build.log && msbuild /nologo /property:Configuration=Debug ALL_BUILD.vcxproj >> build.log && msbuild /nologo /property:Configuration=Release ALL_BUILD.vcxproj >> build.log
|
||||
for /D %%f in (lib\*) do dir %%f\*.dll | findstr "\/"
|
||||
cd ..
|
||||
)
|
||||
(
|
||||
cd v120
|
||||
cmake -G "Visual Studio 12 Win64" ..\..\.. -T "v120" -DWITH_OPENPGM=%WITH_OPENPGM% -DWITH_DOC=%WITH_DOC% > build.log && msbuild /nologo /property:Configuration=Debug ALL_BUILD.vcxproj >> build.log && msbuild /nologo /property:Configuration=Release PACKAGE.vcxproj >> build.log
|
||||
(
|
||||
dir *.exe
|
||||
for /D %%f in (lib\*) do dir %%f\*.dll
|
||||
) | findstr "\/"
|
||||
cd ..
|
||||
)
|
||||
|
||||
endlocal
|
||||
cd %~2
|
||||
goto:eof
|
31
builds/mingw32/Makefile.mingw32
Normal file
31
builds/mingw32/Makefile.mingw32
Normal file
@ -0,0 +1,31 @@
|
||||
CC=gcc
|
||||
CFLAGS=-Wall -Os -g -DDLL_EXPORT -DFD_SETSIZE=1024 -I.
|
||||
LIBS=-lws2_32
|
||||
|
||||
OBJS = address.o clock.o ctx.o dealer.o decoder.o devpoll.o dist.o encoder.o epoll.o err.o fq.o \
|
||||
io_object.o io_thread.o ip.o ipc_address.o ipc_connecter.o ipc_listener.o kqueue.o lb.o \
|
||||
mailbox.o msg.o mtrie.o object.o options.o own.o pair.o pgm_receiver.o pgm_sender.o \
|
||||
pgm_socket.o pipe.o poll.o poller_base.o precompiled.o proxy.o pub.o pull.o push.o \
|
||||
random.o reaper.o rep.o req.o router.o select.o session_base.o \
|
||||
signaler.o socket_base.o stream_engine.o sub.o tcp.o tcp_address.o tcp_connecter.o tcp_listener.o \
|
||||
thread.o trie.o v1_decoder.o v1_encoder.o xpub.o xsub.o zmq.o zmq_utils.o
|
||||
|
||||
%.o: ../../src/%.cpp
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
%.o: ../../perf/%.cpp
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
all: libzmq.dll
|
||||
|
||||
perf: inproc_lat.exe inproc_thr.exe local_lat.exe local_thr.exe remote_lat.exe remote_thr.exe
|
||||
|
||||
libzmq.dll: $(OBJS)
|
||||
g++ -shared -o $@ $^ -Wl,--out-implib,$@.a $(LIBS)
|
||||
|
||||
%.exe: %.o libzmq.dll
|
||||
g++ -o $@ $^
|
||||
|
||||
clean:
|
||||
del *.o *.a *.dll *.exe
|
||||
|
32
builds/mingw32/platform.hpp
Normal file
32
builds/mingw32/platform.hpp
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
Copyright (c) 2007-2011 iMatix Corporation
|
||||
Copyright (c) 2007-2011 Other 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/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_PLATFORM_HPP_INCLUDED__
|
||||
#define __ZMQ_PLATFORM_HPP_INCLUDED__
|
||||
|
||||
// This is the platform definition for the MSVC platform.
|
||||
// As a first step of the build process it is copied to
|
||||
// zmq directory to take place of platform.hpp generated from
|
||||
// platform.hpp.in on platforms supported by GNU autotools.
|
||||
// Place any MSVC-specific definitions here.
|
||||
|
||||
#define ZMQ_HAVE_WINDOWS
|
||||
|
||||
#endif
|
@ -1,6 +1,7 @@
|
||||
LIBZMQ_DIST = libzmq/libzmq.vcproj libzmq/libzmq.vcxproj \
|
||||
libzmq/libzmq.vcxproj.filters \
|
||||
platform.hpp msvc.sln msvc10.sln
|
||||
platform.hpp msvc.sln msvc10.sln \
|
||||
errno.cpp errno.hpp
|
||||
|
||||
PERF_DIST = c_local_thr/c_local_thr.vcproj \
|
||||
c_local_thr/c_local_thr.vcxproj \
|
||||
|
@ -11,12 +11,15 @@ Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root
|
||||
BuildRequires: gcc, make, gcc-c++, libstdc++-devel
|
||||
Requires: libstdc++
|
||||
|
||||
%if %{?rhel}%{!?rhel:0} >= 6
|
||||
%if 0%{?rhel}
|
||||
%if 0%{?rhel} == 6
|
||||
BuildRequires: libuuid-devel
|
||||
Requires: libuuid
|
||||
%elseif %{?rhel}%{!?rhel:0} >= 5
|
||||
%endif
|
||||
%if 0%{?rhel} == 5
|
||||
BuildRequires: e2fsprogs-devel
|
||||
Requires: e2fsprogs
|
||||
%endif
|
||||
%else
|
||||
BuildRequires: uuid-devel
|
||||
Requires: uuid
|
||||
@ -57,7 +60,7 @@ This package contains ZeroMQ related development libraries and header files.
|
||||
|
||||
%build
|
||||
%ifarch pentium3 pentium4 athlon i386 i486 i586 i686 x86_64
|
||||
%configure --with-pgm
|
||||
%configure --with-pgm --with-pic --with-gnu-ld
|
||||
%else
|
||||
%configure
|
||||
%endif
|
||||
@ -87,17 +90,10 @@ This package contains ZeroMQ related development libraries and header files.
|
||||
%doc AUTHORS ChangeLog COPYING COPYING.LESSER NEWS README
|
||||
|
||||
# libraries
|
||||
%{_libdir}/libzmq.so.1
|
||||
%{_libdir}/libzmq.so.1.0.0
|
||||
|
||||
%attr(0755,root,root) %{_bindir}/zmq_forwarder
|
||||
%attr(0755,root,root) %{_bindir}/zmq_queue
|
||||
%attr(0755,root,root) %{_bindir}/zmq_streamer
|
||||
%{_libdir}/libzmq.so.3
|
||||
%{_libdir}/libzmq.so.3.0.0
|
||||
|
||||
%{_mandir}/man7/zmq.7.gz
|
||||
%{_mandir}/man1/zmq_forwarder.1.gz
|
||||
%{_mandir}/man1/zmq_queue.1.gz
|
||||
%{_mandir}/man1/zmq_streamer.1.gz
|
||||
|
||||
%files devel
|
||||
%defattr(-,root,root,-)
|
||||
@ -112,6 +108,12 @@ This package contains ZeroMQ related development libraries and header files.
|
||||
%{_mandir}/man3/zmq_bind.3.gz
|
||||
%{_mandir}/man3/zmq_close.3.gz
|
||||
%{_mandir}/man3/zmq_connect.3.gz
|
||||
%{_mandir}/man3/zmq_disconnect.3.gz
|
||||
%{_mandir}/man3/zmq_ctx_destroy.3.gz
|
||||
%{_mandir}/man3/zmq_ctx_get.3.gz
|
||||
%{_mandir}/man3/zmq_ctx_new.3.gz
|
||||
%{_mandir}/man3/zmq_ctx_set.3.gz
|
||||
%{_mandir}/man3/zmq_msg_recv.3.gz
|
||||
%{_mandir}/man3/zmq_errno.3.gz
|
||||
%{_mandir}/man3/zmq_getsockopt.3.gz
|
||||
%{_mandir}/man3/zmq_init.3.gz
|
||||
@ -123,16 +125,24 @@ This package contains ZeroMQ related development libraries and header files.
|
||||
%{_mandir}/man3/zmq_msg_init_size.3.gz
|
||||
%{_mandir}/man3/zmq_msg_move.3.gz
|
||||
%{_mandir}/man3/zmq_msg_size.3.gz
|
||||
%{_mandir}/man3/zmq_msg_get.3.gz
|
||||
%{_mandir}/man3/zmq_msg_more.3.gz
|
||||
%{_mandir}/man3/zmq_msg_recv.3.gz
|
||||
%{_mandir}/man3/zmq_msg_send.3.gz
|
||||
%{_mandir}/man3/zmq_msg_set.3.gz
|
||||
%{_mandir}/man3/zmq_poll.3.gz
|
||||
%{_mandir}/man3/zmq_proxy.3.gz
|
||||
%{_mandir}/man3/zmq_recv.3.gz
|
||||
%{_mandir}/man3/zmq_recvmsg.3.gz
|
||||
%{_mandir}/man3/zmq_send.3.gz
|
||||
%{_mandir}/man3/zmq_sendmsg.3.gz
|
||||
%{_mandir}/man3/zmq_setsockopt.3.gz
|
||||
%{_mandir}/man3/zmq_socket.3.gz
|
||||
%{_mandir}/man3/zmq_socket_monitor.3.gz
|
||||
%{_mandir}/man3/zmq_strerror.3.gz
|
||||
%{_mandir}/man3/zmq_term.3.gz
|
||||
%{_mandir}/man3/zmq_version.3.gz
|
||||
%{_mandir}/man3/zmq_unbind.3.gz
|
||||
%{_mandir}/man7/zmq_epgm.7.gz
|
||||
%{_mandir}/man7/zmq_inproc.7.gz
|
||||
%{_mandir}/man7/zmq_ipc.7.gz
|
||||
@ -140,6 +150,9 @@ This package contains ZeroMQ related development libraries and header files.
|
||||
%{_mandir}/man7/zmq_tcp.7.gz
|
||||
|
||||
%changelog
|
||||
* Mon Nov 26 2012 Justin Cook <jhcook@gmail.com> 3.2.2
|
||||
- Update packaged files
|
||||
|
||||
* Fri Apr 8 2011 Mikko Koppanen <mikko@kuut.io> 3.0.0-1
|
||||
- Update dependencies and packaged files
|
||||
|
||||
|
@ -24,12 +24,36 @@
|
||||
MESSAGE(STATUS "Detecting ZMQ - failed")
|
||||
ENDIF()
|
||||
|
||||
if(MSVC_VERSION MATCHES "1700")
|
||||
set(_zmq_COMPILER "-v110")
|
||||
elseif(MSVC10)
|
||||
set(_zmq_COMPILER "-v100")
|
||||
elseif(MSVC90)
|
||||
set(_zmq_COMPILER "-v90")
|
||||
if(CMAKE_GENERATOR_TOOLSET MATCHES "v120")
|
||||
set(_zmq_TOOLSET "-v120")
|
||||
set(_zmq_COMPILER "vc120")
|
||||
set(_zmq_WIN32_WINNT "0x0601")
|
||||
elseif(CMAKE_GENERATOR_TOOLSET MATCHES "v110_xp")
|
||||
set(_zmq_TOOLSET "-v110_xp")
|
||||
set(_zmq_COMPILER "vc110")
|
||||
set(_zmq_WIN32_WINNT "0x0501")
|
||||
elseif(CMAKE_GENERATOR_TOOLSET MATCHES "v110")
|
||||
set(_zmq_TOOLSET "-v110")
|
||||
set(_zmq_COMPILER "vc110")
|
||||
set(_zmq_WIN32_WINNT "0x0601")
|
||||
elseif(CMAKE_GENERATOR_TOOLSET MATCHES "v100")
|
||||
set(_zmq_TOOLSET "-v100")
|
||||
set(_zmq_COMPILER "vc100")
|
||||
if(CMAKE_CL_64)
|
||||
set(_zmq_WIN32_WINNT "0x0600")
|
||||
else()
|
||||
set(_zmq_WIN32_WINNT "0x0501")
|
||||
endif()
|
||||
elseif(CMAKE_GENERATOR_TOOLSET MATCHES "v90")
|
||||
set(_zmq_TOOLSET "-v90")
|
||||
set(_zmq_COMPILER "vc90")
|
||||
if(CMAKE_CL_64)
|
||||
set(_zmq_WIN32_WINNT "0x0600")
|
||||
else()
|
||||
set(_zmq_WIN32_WINNT "0x0501")
|
||||
endif()
|
||||
else()
|
||||
set(_zmq_TOOLSET "")
|
||||
set(_zmq_COMPILER "")
|
||||
set(_zmq_WIN32_WINNT "")
|
||||
endif()
|
||||
|
@ -75,7 +75,7 @@ Var AR_RegFlags
|
||||
|
||||
ClearErrors
|
||||
;Reading component status from registry
|
||||
ReadRegDWORD $AR_RegFlags HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@\Components\${SecName}" "Installed"
|
||||
ReadRegDWORD $AR_RegFlags HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@ (x64)\Components\${SecName}" "Installed"
|
||||
IfErrors "default_${SecName}"
|
||||
;Status will stay default if registry value not found
|
||||
;(component was never installed)
|
||||
@ -108,13 +108,13 @@ Var AR_RegFlags
|
||||
;Section is not selected:
|
||||
;Calling Section uninstall macro and writing zero installed flag
|
||||
!insertmacro "Remove_${${SecName}}"
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@\Components\${SecName}" \
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@ (x64)\Components\${SecName}" \
|
||||
"Installed" 0
|
||||
Goto "exit_${SecName}"
|
||||
|
||||
"leave_${SecName}:"
|
||||
;Section is selected:
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@\Components\${SecName}" \
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@ (x64)\Components\${SecName}" \
|
||||
"Installed" 1
|
||||
|
||||
"exit_${SecName}:"
|
||||
@ -494,7 +494,7 @@ Function ConditionalAddToRegisty
|
||||
Pop $0
|
||||
Pop $1
|
||||
StrCmp "$0" "" ConditionalAddToRegisty_EmptyString
|
||||
WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@" \
|
||||
WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@ (x64)" \
|
||||
"$1" "$0"
|
||||
;MessageBox MB_OK "Set Registry: '$1' to '$0'"
|
||||
DetailPrint "Set install registry entry: '$1' to '$0'"
|
||||
@ -810,17 +810,17 @@ FunctionEnd
|
||||
|
||||
Section "Uninstall"
|
||||
ReadRegStr $START_MENU SHCTX \
|
||||
"Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@" "StartMenu"
|
||||
"Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@ (x64)" "StartMenu"
|
||||
;MessageBox MB_OK "Start menu is in: $START_MENU"
|
||||
ReadRegStr $DO_NOT_ADD_TO_PATH SHCTX \
|
||||
"Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@" "DoNotAddToPath"
|
||||
"Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@ (x64)" "DoNotAddToPath"
|
||||
ReadRegStr $ADD_TO_PATH_ALL_USERS SHCTX \
|
||||
"Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@" "AddToPathAllUsers"
|
||||
"Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@ (x64)" "AddToPathAllUsers"
|
||||
ReadRegStr $ADD_TO_PATH_CURRENT_USER SHCTX \
|
||||
"Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@" "AddToPathCurrentUser"
|
||||
"Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@ (x64)" "AddToPathCurrentUser"
|
||||
;MessageBox MB_OK "Add to path: $DO_NOT_ADD_TO_PATH all users: $ADD_TO_PATH_ALL_USERS"
|
||||
ReadRegStr $INSTALL_DESKTOP SHCTX \
|
||||
"Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@" "InstallToDesktop"
|
||||
"Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@ (x64)" "InstallToDesktop"
|
||||
;MessageBox MB_OK "Install to desktop: $INSTALL_DESKTOP "
|
||||
|
||||
@CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS@
|
||||
@ -837,7 +837,7 @@ Section "Uninstall"
|
||||
|
||||
;Remove the uninstaller itself.
|
||||
Delete "$INSTDIR\Uninstall.exe"
|
||||
DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@"
|
||||
DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@ (x64)"
|
||||
|
||||
;Remove the installation directory if it is empty.
|
||||
RMDir "$INSTDIR"
|
||||
|
18
configure.in
18
configure.in
@ -10,7 +10,7 @@ AC_INIT([zeromq],[m4_esyscmd([./version.sh])],[zeromq-dev@lists.zeromq.org])
|
||||
|
||||
AC_CONFIG_AUX_DIR(config)
|
||||
AC_CONFIG_MACRO_DIR(config)
|
||||
AM_CONFIG_HEADER(src/platform.hpp)
|
||||
AC_CONFIG_HEADERS([src/platform.hpp])
|
||||
AM_INIT_AUTOMAKE(tar-ustar dist-zip foreign)
|
||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||
|
||||
@ -348,10 +348,18 @@ fi
|
||||
# Build with system openpgm
|
||||
if test "x$with_system_pgm_ext" != "xno"; then
|
||||
m4_ifdef([PKG_CHECK_MODULES], [
|
||||
PKG_CHECK_MODULES([OpenPGM], [openpgm-5.1 >= 5.1])
|
||||
AC_DEFINE(ZMQ_HAVE_OPENPGM, 1, [Have OpenPGM extension])
|
||||
LIBZMQ_EXTRA_CXXFLAGS="$OpenPGM_CFLAGS $LIBZMQ_EXTRA_CXXFLAGS"
|
||||
LIBS="$OpenPGM_LIBS $LIBS"
|
||||
have_pgm_system_library="no"
|
||||
PKG_CHECK_MODULES([OpenPGM], [openpgm-5.2 >= 5.2],
|
||||
[ have_pgm_system_library="yes" ],
|
||||
[PKG_CHECK_MODULES([OpenPGM], [openpgm-5.1 >= 5.1],
|
||||
[ have_pgm_system_library="yes" ])
|
||||
]
|
||||
)
|
||||
if test "x$have_pgm_system_library" = "xyes"; then
|
||||
AC_DEFINE(ZMQ_HAVE_OPENPGM, 1, [Have OpenPGM extension])
|
||||
LIBZMQ_EXTRA_CXXFLAGS="$OpenPGM_CFLAGS $LIBZMQ_EXTRA_CXXFLAGS"
|
||||
LIBS="$OpenPGM_LIBS $LIBS"
|
||||
fi
|
||||
],
|
||||
[AC_MSG_ERROR([--with-system-pgm requires a working pkg-config installation])])
|
||||
fi
|
||||
|
@ -1,12 +1,15 @@
|
||||
MAN3 = zmq_bind.3 zmq_close.3 zmq_connect.3 zmq_proxy.3 \
|
||||
MAN3 = zmq_bind.3 zmq_unbind.3 zmq_connect.3 zmq_disconnect.3 zmq_close.3 \
|
||||
zmq_ctx_new.3 zmq_ctx_destroy.3 zmq_ctx_get.3 zmq_ctx_set.3 \
|
||||
zmq_init.3 zmq_term.3 \
|
||||
zmq_msg_close.3 zmq_msg_copy.3 zmq_msg_data.3 zmq_msg_init.3 \
|
||||
zmq_msg_init_data.3 zmq_msg_init_size.3 zmq_msg_move.3 zmq_msg_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_send.3 zmq_msg_recv.3 \
|
||||
zmq_poll.3 zmq_recv.3 zmq_send.3 zmq_setsockopt.3 zmq_socket.3 \
|
||||
zmq_socket_monitor.3 zmq_strerror.3 zmq_version.3 zmq_getsockopt.3 zmq_errno.3 \
|
||||
zmq_sendmsg.3 zmq_recvmsg.3 zmq_msg_get.3 zmq_msg_set.3 zmq_msg_more.3
|
||||
zmq_send.3 zmq_recv.3 \
|
||||
zmq_msg_get.3 zmq_msg_set.3 zmq_msg_more.3 \
|
||||
zmq_getsockopt.3 zmq_setsockopt.3 \
|
||||
zmq_socket.3 zmq_socket_monitor.3 zmq_poll.3 \
|
||||
zmq_errno.3 zmq_strerror.3 zmq_version.3 zmq_proxy.3 \
|
||||
zmq_sendmsg.3 zmq_recvmsg.3 zmq_init.3 zmq_term.3
|
||||
|
||||
MAN7 = zmq.7 zmq_tcp.7 zmq_pgm.7 zmq_epgm.7 zmq_inproc.7 zmq_ipc.7
|
||||
|
||||
MAN_DOC = $(MAN1) $(MAN3) $(MAN7)
|
||||
|
@ -4,7 +4,7 @@ zmq_bind(3)
|
||||
|
||||
NAME
|
||||
----
|
||||
zmq_bind - accept connections on a socket
|
||||
zmq_bind - accept incoming connections on a socket
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
@ -14,34 +14,41 @@ SYNOPSIS
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
The _zmq_bind()_ function shall create an endpoint for accepting connections
|
||||
and bind it to the socket referenced by the 'socket' argument.
|
||||
The _zmq_bind()_ function binds the 'socket' to a local 'endpoint' and then
|
||||
accepts incoming connections on that endpoint.
|
||||
|
||||
The 'endpoint' argument is a string consisting of two parts as follows:
|
||||
'transport'`://`'address'. The 'transport' part specifies the underlying
|
||||
transport protocol to use. The meaning of the 'address' part is specific to
|
||||
the underlying transport protocol selected.
|
||||
The 'endpoint' is a string consisting of a 'transport'`://` followed by an
|
||||
'address'. The 'transport' specifies the underlying protocol to use. The
|
||||
'address' specifies the transport-specific address to bind to.
|
||||
|
||||
The following transports are defined:
|
||||
0MQ provides the the following transports:
|
||||
|
||||
'inproc':: local in-process (inter-thread) communication transport, see linkzmq:zmq_inproc[7]
|
||||
'ipc':: local inter-process communication transport, see linkzmq:zmq_ipc[7]
|
||||
'tcp':: unicast transport using TCP, see linkzmq:zmq_tcp[7]
|
||||
'ipc':: local inter-process communication transport, see linkzmq:zmq_ipc[7]
|
||||
'inproc':: local in-process (inter-thread) communication transport, see linkzmq:zmq_inproc[7]
|
||||
'pgm', 'epgm':: reliable multicast transport using PGM, see linkzmq:zmq_pgm[7]
|
||||
|
||||
ZeroMQ sockets support one-to-many and many-to-one semantics. With the exception
|
||||
of 'ZMQ_PAIR' sockets every ZeroMQ socket type supports being bound with
|
||||
_zmq_bind()_ as a singular endpoint or connecting with _zmq_connect()_ as one
|
||||
of many endpoints. This allows combinations such as 1 ZMQ_REP to 100 ZMQ_REP and
|
||||
100 ZMQ_REQ to 1 ZMQ_REP socket connections. Refer to linkzmq:zmq_socket[3] for
|
||||
a description of the exact semantics involved when connecting or binding a socket
|
||||
to multiple endpoints.
|
||||
Every 0MQ socket type except 'ZMQ_PAIR' supports one-to-many and many-to-one
|
||||
semantics. The precise semantics depend on the socket type and are defined in
|
||||
linkzmq:zmq_socket[3].
|
||||
|
||||
The 'ipc' and 'tcp' transports accept wildcard addresses: see linkzmq:zmq_ipc[7]
|
||||
and linkzmq:zmq_tcp[7] for details.
|
||||
|
||||
NOTE: the address syntax may be different for _zmq_bind()_ and _zmq_connect()_
|
||||
especially for the 'tcp', 'pgm' and 'epgm' transports.
|
||||
|
||||
NOTE: following a _zmq_bind()_, the socket enters a 'mute' state unless or
|
||||
until at least one incoming or outgoing connection is made, at which point
|
||||
the socket enters a 'ready' state. In the mute state, the socket blocks or
|
||||
drops messages according to the socket type, as defined in linkzmq:zmq_socket[3].
|
||||
By contrast, following a libzmq:zmq_connect[3], the socket enters the 'ready' state.
|
||||
|
||||
|
||||
RETURN VALUE
|
||||
------------
|
||||
The _zmq_bind()_ function shall return zero if successful. Otherwise it shall
|
||||
return `-1` and set 'errno' to one of the values defined below.
|
||||
The _zmq_bind()_ function returns zero if successful. Otherwise it returns
|
||||
`-1` and sets 'errno' to one of the values defined below.
|
||||
|
||||
|
||||
ERRORS
|
||||
@ -91,5 +98,5 @@ linkzmq:zmq[7]
|
||||
|
||||
AUTHORS
|
||||
-------
|
||||
This 0MQ manual page was written by Martin Sustrik <sustrik@250bpm.com> and
|
||||
Martin Lucina <mato@kotelna.sk>.
|
||||
This 0MQ manual page was written by Pieter Hintjens <ph@imatix.com>,
|
||||
Martin Sustrik <sustrik@250bpm.com> and Martin Lucina <mato@kotelna.sk>.
|
||||
|
@ -4,7 +4,7 @@ zmq_connect(3)
|
||||
|
||||
NAME
|
||||
----
|
||||
zmq_connect - connect a socket
|
||||
zmq_connect - create outgoing connection from socket
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
@ -14,42 +14,43 @@ SYNOPSIS
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
The _zmq_connect()_ function shall connect the socket referenced by the
|
||||
'socket' argument to the endpoint specified by the 'endpoint' argument.
|
||||
The _zmq_connect()_ function connects the 'socket' to an 'endpoint' and then
|
||||
accepts incoming connections on that endpoint.
|
||||
|
||||
The 'endpoint' argument is a string consisting of two parts as follows:
|
||||
'transport'`://`'address'. The 'transport' part specifies the underlying
|
||||
transport protocol to use. The meaning of the 'address' part is specific to
|
||||
the underlying transport protocol selected.
|
||||
The 'endpoint' is a string consisting of a 'transport'`://` followed by an
|
||||
'address'. The 'transport' specifies the underlying protocol to use. The
|
||||
'address' specifies the transport-specific address to connect to.
|
||||
|
||||
The following transports are defined:
|
||||
0MQ provides the the following transports:
|
||||
|
||||
'inproc':: local in-process (inter-thread) communication transport, see linkzmq:zmq_inproc[7]
|
||||
'ipc':: local inter-process communication transport, see linkzmq:zmq_ipc[7]
|
||||
'tcp':: unicast transport using TCP, see linkzmq:zmq_tcp[7]
|
||||
'ipc':: local inter-process communication transport, see linkzmq:zmq_ipc[7]
|
||||
'inproc':: local in-process (inter-thread) communication transport, see linkzmq:zmq_inproc[7]
|
||||
'pgm', 'epgm':: reliable multicast transport using PGM, see linkzmq:zmq_pgm[7]
|
||||
|
||||
ZeroMQ sockets support one-to-many and many-to-one semantics. With the exception
|
||||
of 'ZMQ_PAIR' sockets every ZeroMQ socket type supports being bound with
|
||||
_zmq_bind()_ as a singular endpoint or connecting with _zmq_connect()_ as one
|
||||
of many endpoints. This allows combinations such as 1 ZMQ_REP to 100 ZMQ_REP and
|
||||
100 ZMQ_REQ to 1 ZMQ_REP socket connections. Refer to linkzmq:zmq_socket[3] for
|
||||
a description of the exact semantics involved when connecting or binding a socket
|
||||
to multiple endpoints.
|
||||
Every 0MQ socket type except 'ZMQ_PAIR' supports one-to-many and many-to-one
|
||||
semantics. The precise semantics depend on the socket type and are defined in
|
||||
linkzmq:zmq_socket[3].
|
||||
|
||||
NOTE: The connection will not be performed immediately but as needed by 0MQ.
|
||||
Thus a successful invocation of _zmq_connect()_ does not indicate that a
|
||||
physical connection was or can actually be established. Because of this, for most
|
||||
socket types the order in which a listening socket is bound and a connecting socket
|
||||
is connected does not matter. However, for inproc:// scheme sockets, the zmq_bind()
|
||||
must be executed before any sockets zmq_connect() to that endpoint. Refer to
|
||||
linkzmq:zmq_inproc[7] for more details.
|
||||
NOTE: for most transports and socket types the connection is not performed
|
||||
immediately but as needed by 0MQ. Thus a successful call to _zmq_connect()_
|
||||
does not mean that the connection was or could actually be established.
|
||||
Because of this, for most transports and socket types the order in which
|
||||
a 'server' socket is bound and a 'client' socket is connected to it does not
|
||||
matter. The first exception is when using the inproc:// transport: you must
|
||||
call _zmq_bind()_ before calling _zmq_connect()_. The second exception are
|
||||
_ZMQ_PAIR_ sockets, which do not automatically reconnect to endpoints.
|
||||
|
||||
NOTE: following a _zmq_connect()_, the socket enters its normal 'ready' state.
|
||||
By contrast, following a _zmq_bind()_ alone, the socket enters a 'mute' state
|
||||
in which the socket blocks or drops messages according to the socket type, as
|
||||
defined in linkzmq:zmq_socket[3].
|
||||
|
||||
|
||||
RETURN VALUE
|
||||
------------
|
||||
The _zmq_connect()_ function shall return zero if successful. Otherwise it
|
||||
shall return `-1` and set 'errno' to one of the values defined below.
|
||||
The _zmq_connect()_ function returns zero if successful. Otherwise it returns
|
||||
`-1` and sets 'errno' to one of the values defined below.
|
||||
|
||||
|
||||
ERRORS
|
||||
@ -93,5 +94,5 @@ linkzmq:zmq[7]
|
||||
|
||||
AUTHORS
|
||||
-------
|
||||
This 0MQ manual page was written by Martin Sustrik <sustrik@250bpm.com> and
|
||||
Martin Lucina <mato@kotelna.sk>.
|
||||
This 0MQ manual page was written by Pieter Hintjens <ph@imatix.com>,
|
||||
Martin Sustrik <sustrik@250bpm.com> and Martin Lucina <mato@kotelna.sk>.
|
||||
|
@ -26,7 +26,7 @@ ZMQ_IO_THREADS: Get number of I/O threads
|
||||
The 'ZMQ_IO_THREADS' argument returns the size of the 0MQ thread pool
|
||||
for this context.
|
||||
|
||||
ZMQ_MAX_SOCKETS: Set maximum number of sockets
|
||||
ZMQ_MAX_SOCKETS: Get maximum number of sockets
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The 'ZMQ_MAX_SOCKETS' argument returns the maximum number of sockets
|
||||
allowed for this context.
|
||||
|
@ -34,6 +34,8 @@ The endpoint supplied is invalid.
|
||||
The 0MQ 'context' associated with the specified 'socket' was terminated.
|
||||
*ENOTSOCK*::
|
||||
The provided 'socket' was invalid.
|
||||
*ENOENT*::
|
||||
The provided endpoint is not connected.
|
||||
|
||||
|
||||
EXAMPLE
|
||||
|
@ -117,6 +117,7 @@ Option value unit:: N/A (bitmap)
|
||||
Default value:: 0
|
||||
Applicable socket types:: N/A
|
||||
|
||||
|
||||
ZMQ_IDENTITY: Set socket identity
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The 'ZMQ_IDENTITY' option shall retrieve the identity of the specified 'socket'.
|
||||
@ -270,7 +271,6 @@ Applicable socket types:: all, only for connection-oriented transports
|
||||
|
||||
ZMQ_MAXMSGSIZE: Maximum acceptable inbound message size
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The option shall retrieve limit for the inbound messages. If a peer sends
|
||||
a message larger than ZMQ_MAXMSGSIZE it is disconnected. Value of -1 means
|
||||
'no limit'.
|
||||
@ -284,7 +284,6 @@ Applicable socket types:: all
|
||||
|
||||
ZMQ_MULTICAST_HOPS: Maximum network hops for multicast packets
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The option shall retrieve time-to-live used for outbound multicast packets.
|
||||
The default of 1 means that the multicast packets don't leave the local network.
|
||||
|
||||
@ -297,7 +296,6 @@ Applicable socket types:: all, when using multicast transports
|
||||
|
||||
ZMQ_RCVTIMEO: Maximum time before a socket operation returns with EAGAIN
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Retrieve the timeout for recv operation on the socket. If the value is `0`,
|
||||
_zmq_recv(3)_ will return immediately, with a EAGAIN error if there is no
|
||||
message to receive. If the value is `-1`, it will block until a message is
|
||||
@ -313,7 +311,6 @@ Applicable socket types:: all
|
||||
|
||||
ZMQ_SNDTIMEO: Maximum time before a socket operation returns with EAGAIN
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Retrieve the timeout for send operation on the socket. If the value is `0`,
|
||||
_zmq_send(3)_ will return immediately, with a EAGAIN error if the message
|
||||
cannot be sent. If the value is `-1`, it will block until the message is sent.
|
||||
@ -329,7 +326,6 @@ Applicable socket types:: all
|
||||
|
||||
ZMQ_IPV4ONLY: Retrieve IPv4-only socket override status
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Retrieve the underlying native socket type. A value of `1` will use IPv4
|
||||
sockets, while the value of `0` will use IPv6 sockets. An IPv6 socket
|
||||
lets applications connect to and accept connections from both IPv4 and IPv6
|
||||
@ -342,9 +338,8 @@ Default value:: 1 (true)
|
||||
Applicable socket types:: all, when using TCP transports.
|
||||
|
||||
|
||||
ZMQ_DELAY_ATTACH_ON_CONNECT
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
ZMQ_DELAY_ATTACH_ON_CONNECT: Retrieve attach-on-connect value
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Retrieve the state of the attach on connect value. If set to `1`, will delay the
|
||||
attachment of a pipe on connect until the underlying connection has completed.
|
||||
This will cause the socket to block if there are no other connections, but will
|
||||
@ -413,6 +408,7 @@ Option value unit:: N/A (flags)
|
||||
Default value:: N/A
|
||||
Applicable socket types:: all
|
||||
|
||||
|
||||
ZMQ_LAST_ENDPOINT: Retrieve the last endpoint set
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The 'ZMQ_LAST_ENDPOINT' option shall retrieve the last endpoint bound for
|
||||
@ -426,6 +422,7 @@ Option value unit:: N/A
|
||||
Default value:: NULL
|
||||
Applicable socket types:: all, when binding TCP or IPC transports
|
||||
|
||||
|
||||
ZMQ_TCP_KEEPALIVE: Override SO_KEEPALIVE socket option
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Override 'SO_KEEPALIVE' socket option(where supported by OS).
|
||||
@ -437,6 +434,7 @@ Option value unit:: -1,0,1
|
||||
Default value:: -1 (leave to OS default)
|
||||
Applicable socket types:: all, when using TCP transports.
|
||||
|
||||
|
||||
ZMQ_TCP_KEEPALIVE_IDLE: Override TCP_KEEPCNT(or TCP_KEEPALIVE on some OS)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Override 'TCP_KEEPCNT'(or 'TCP_KEEPALIVE' on some OS) socket option(where supported by OS).
|
||||
@ -448,6 +446,7 @@ Option value unit:: -1,>0
|
||||
Default value:: -1 (leave to OS default)
|
||||
Applicable socket types:: all, when using TCP transports.
|
||||
|
||||
|
||||
ZMQ_TCP_KEEPALIVE_CNT: Override TCP_KEEPCNT socket option
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Override 'TCP_KEEPCNT' socket option(where supported by OS).
|
||||
@ -459,6 +458,7 @@ Option value unit:: -1,>0
|
||||
Default value:: -1 (leave to OS default)
|
||||
Applicable socket types:: all, when using TCP transports.
|
||||
|
||||
|
||||
ZMQ_TCP_KEEPALIVE_INTVL: Override TCP_KEEPINTVL socket option
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Override 'TCP_KEEPINTVL' socket option(where supported by OS).
|
||||
|
@ -20,11 +20,12 @@ linkzmq:zmq_init[3] for details.
|
||||
|
||||
ADDRESSING
|
||||
----------
|
||||
A 0MQ address string consists of two parts as follows:
|
||||
'transport'`://`'endpoint'. The 'transport' part specifies the underlying
|
||||
transport protocol to use, and for the in-process transport shall be set to
|
||||
`inproc`. The meaning of the 'endpoint' part for the in-process transport is
|
||||
defined below.
|
||||
A 0MQ endpoint is a string consisting of a 'transport'`://` followed by an
|
||||
'address'. The 'transport' specifies the underlying protocol to use. The
|
||||
'address' specifies the transport-specific address to connect to.
|
||||
|
||||
For the in-process transport, the transport is `inproc`, and the meaning of
|
||||
the 'address' part is defined below.
|
||||
|
||||
|
||||
Assigning a local address to a socket
|
||||
@ -45,29 +46,24 @@ created by assigning it to at least one 'socket' within the same 0MQ 'context'
|
||||
as the 'socket' being connected.
|
||||
|
||||
|
||||
WIRE FORMAT
|
||||
-----------
|
||||
Not applicable.
|
||||
|
||||
|
||||
EXAMPLES
|
||||
--------
|
||||
.Assigning a local address to a socket
|
||||
----
|
||||
/* Assign the in-process name "#1" */
|
||||
// Assign the in-process name "#1"
|
||||
rc = zmq_bind(socket, "inproc://#1");
|
||||
assert (rc == 0);
|
||||
/* Assign the in-process name "my-endpoint" */
|
||||
// Assign the in-process name "my-endpoint"
|
||||
rc = zmq_bind(socket, "inproc://my-endpoint");
|
||||
assert (rc == 0);
|
||||
----
|
||||
|
||||
.Connecting a socket
|
||||
----
|
||||
/* Connect to the in-process name "#1" */
|
||||
// Connect to the in-process name "#1"
|
||||
rc = zmq_connect(socket, "inproc://#1");
|
||||
assert (rc == 0);
|
||||
/* Connect to the in-process name "my-endpoint" */
|
||||
// Connect to the in-process name "my-endpoint"
|
||||
rc = zmq_connect(socket, "inproc://my-endpoint");
|
||||
assert (rc == 0);
|
||||
----
|
||||
@ -85,5 +81,5 @@ linkzmq:zmq[7]
|
||||
|
||||
AUTHORS
|
||||
-------
|
||||
This 0MQ manual page was written by Martin Sustrik <sustrik@250bpm.com> and
|
||||
Martin Lucina <mato@kotelna.sk>.
|
||||
This 0MQ manual page was written by Pieter Hintjens <ph@imatix.com>,
|
||||
Martin Sustrik <sustrik@250bpm.com> and Martin Lucina <mato@kotelna.sk>.
|
||||
|
@ -18,22 +18,31 @@ systems that provide UNIX domain sockets.
|
||||
|
||||
ADDRESSING
|
||||
----------
|
||||
A 0MQ address string consists of two parts as follows:
|
||||
'transport'`://`'endpoint'. The 'transport' part specifies the underlying
|
||||
transport protocol to use, and for the inter-process transport shall be set to
|
||||
`ipc`. The meaning of the 'endpoint' part for the inter-process transport is
|
||||
defined below.
|
||||
A 0MQ endpoint is a string consisting of a 'transport'`://` followed by an
|
||||
'address'. The 'transport' specifies the underlying protocol to use. The
|
||||
'address' specifies the transport-specific address to connect to.
|
||||
|
||||
For the inter-process transport, the transport is `ipc`, and the meaning of
|
||||
the 'address' part is defined below.
|
||||
|
||||
|
||||
Assigning a local address to a socket
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
When assigning a local address to a 'socket' using _zmq_bind()_ with the 'ipc'
|
||||
Binding a socket
|
||||
~~~~~~~~~~~~~~~~
|
||||
When binding a 'socket' to a local address using _zmq_bind()_ with the 'ipc'
|
||||
transport, the 'endpoint' shall be interpreted as an arbitrary string
|
||||
identifying the 'pathname' to create. The 'pathname' must be unique within the
|
||||
operating system namespace used by the 'ipc' implementation, and must fulfill
|
||||
any restrictions placed by the operating system on the format and length of a
|
||||
'pathname'.
|
||||
|
||||
When the address is `*`, _zmq_bind()_ shall generate a unique temporary
|
||||
pathname. The caller should retrieve this pathname using the ZMQ_LAST_ENDPOINT
|
||||
socket option. See linkzmq:zmq_getsockopt[3] for details.
|
||||
|
||||
NOTE: any existing binding to the same endpoint shall be overridden. In this
|
||||
behavior, the 'ipc' transport is not consistent with the 'tcp' or 'inproc'
|
||||
transports.
|
||||
|
||||
Connecting a socket
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
When connecting a 'socket' to a peer address using _zmq_connect()_ with the
|
||||
@ -43,23 +52,18 @@ previously created within the operating system namespace by assigning it to a
|
||||
'socket' with _zmq_bind()_.
|
||||
|
||||
|
||||
WIRE FORMAT
|
||||
-----------
|
||||
Not applicable.
|
||||
|
||||
|
||||
EXAMPLES
|
||||
--------
|
||||
.Assigning a local address to a socket
|
||||
----
|
||||
/* Assign the pathname "/tmp/feeds/0" */
|
||||
// Assign the pathname "/tmp/feeds/0"
|
||||
rc = zmq_bind(socket, "ipc:///tmp/feeds/0");
|
||||
assert (rc == 0);
|
||||
----
|
||||
|
||||
.Connecting a socket
|
||||
----
|
||||
/* Connect to the pathname "/tmp/feeds/0" */
|
||||
// Connect to the pathname "/tmp/feeds/0"
|
||||
rc = zmq_connect(socket, "ipc:///tmp/feeds/0");
|
||||
assert (rc == 0);
|
||||
----
|
||||
@ -71,10 +75,11 @@ linkzmq:zmq_connect[3]
|
||||
linkzmq:zmq_inproc[7]
|
||||
linkzmq:zmq_tcp[7]
|
||||
linkzmq:zmq_pgm[7]
|
||||
linkzmq:zmq_getsockopt[3]
|
||||
linkzmq:zmq[7]
|
||||
|
||||
|
||||
AUTHORS
|
||||
-------
|
||||
This 0MQ manual page was written by Martin Sustrik <sustrik@250bpm.com> and
|
||||
Martin Lucina <mato@kotelna.sk>.
|
||||
This 0MQ manual page was written by Pieter Hintjens <ph@imatix.com>,
|
||||
Martin Sustrik <sustrik@250bpm.com> and Martin Lucina <mato@kotelna.sk>.
|
||||
|
@ -17,8 +17,8 @@ DESCRIPTION
|
||||
-----------
|
||||
0MQ implements two variants of PGM, the standard protocol where PGM datagrams
|
||||
are layered directly on top of IP datagrams as defined by RFC 3208 (the 'pgm'
|
||||
transport) and "Encapsulated PGM" where PGM datagrams are encapsulated inside
|
||||
UDP datagrams (the 'epgm' transport).
|
||||
transport) and "Encapsulated PGM" or EPGM where PGM datagrams are encapsulated
|
||||
inside UDP datagrams (the 'epgm' transport).
|
||||
|
||||
The 'pgm' and 'epgm' transports can only be used with the 'ZMQ_PUB' and
|
||||
'ZMQ_SUB' socket types.
|
||||
@ -36,12 +36,12 @@ not require any special privileges.
|
||||
|
||||
ADDRESSING
|
||||
----------
|
||||
A 0MQ address string consists of two parts as follows:
|
||||
'transport'`://`'endpoint'. The 'transport' part specifies the underlying
|
||||
transport protocol to use. For the standard PGM protocol, 'transport' shall be
|
||||
set to `pgm`. For the "Encapsulated PGM" protocol 'transport' shall be set to
|
||||
`epgm`. The meaning of the 'endpoint' part for both the 'pgm' and 'epgm'
|
||||
transport is defined below.
|
||||
A 0MQ endpoint is a string consisting of a 'transport'`://` followed by an
|
||||
'address'. The 'transport' specifies the underlying protocol to use. The
|
||||
'address' specifies the transport-specific address to connect to.
|
||||
|
||||
For the PGM transport, the transport is `pgm`, and for the EPGM protocol the
|
||||
transport is `epgm`. The meaning of the 'address' part is defined below.
|
||||
|
||||
|
||||
Connecting a socket
|
||||
@ -134,14 +134,14 @@ EXAMPLE
|
||||
-------
|
||||
.Connecting a socket
|
||||
----
|
||||
/* Connecting to the multicast address 239.192.1.1, port 5555, */
|
||||
/* using the first Ethernet network interface on Linux */
|
||||
/* and the Encapsulated PGM protocol */
|
||||
// Connecting to the multicast address 239.192.1.1, port 5555,
|
||||
// using the first Ethernet network interface on Linux
|
||||
// and the Encapsulated PGM protocol
|
||||
rc = zmq_connect(socket, "epgm://eth0;239.192.1.1:5555");
|
||||
assert (rc == 0);
|
||||
/* Connecting to the multicast address 239.192.1.1, port 5555, */
|
||||
/* using the network interface with the address 192.168.1.1 */
|
||||
/* and the standard PGM protocol */
|
||||
// Connecting to the multicast address 239.192.1.1, port 5555,
|
||||
// using the network interface with the address 192.168.1.1
|
||||
// and the standard PGM protocol
|
||||
rc = zmq_connect(socket, "pgm://192.168.1.1;239.192.1.1:5555");
|
||||
assert (rc == 0);
|
||||
----
|
||||
@ -158,5 +158,5 @@ linkzmq:zmq[7]
|
||||
|
||||
AUTHORS
|
||||
-------
|
||||
This 0MQ manual page was written by Martin Sustrik <sustrik@250bpm.com> and
|
||||
Martin Lucina <mato@kotelna.sk>.
|
||||
This 0MQ manual page was written by Pieter Hintjens <ph@imatix.com>,
|
||||
Martin Sustrik <sustrik@250bpm.com> and Martin Lucina <mato@kotelna.sk>.
|
||||
|
@ -26,6 +26,8 @@ Specifies that the operation should be performed in non-blocking mode. If there
|
||||
are no messages available on the specified 'socket', the _zmq_recvmsg()_
|
||||
function shall fail with 'errno' set to EAGAIN.
|
||||
|
||||
NOTE: this API method is deprecated in favor of zmq_msg_recv(3).
|
||||
|
||||
|
||||
Multi-part messages
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -36,6 +36,7 @@ NOTE: A successful invocation of _zmq_sendmsg()_ does not indicate that the
|
||||
message has been transmitted to the network, only that it has been queued on
|
||||
the 'socket' and 0MQ has assumed responsibility for the message.
|
||||
|
||||
NOTE: this API method is deprecated in favor of zmq_msg_send(3).
|
||||
|
||||
Multi-part messages
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -39,6 +39,10 @@ blocking or dropping sent messages. Refer to the individual socket descriptions
|
||||
in linkzmq:zmq_socket[3] for details on the exact action taken for each socket
|
||||
type.
|
||||
|
||||
NOTE: 0MQ does not guarantee that the socket will accept as many as ZMQ_SNDHWM
|
||||
messages, and the actual limit may be as much as 60-70% lower depending on the
|
||||
flow of messages on the socket.
|
||||
|
||||
[horizontal]
|
||||
Option value type:: int
|
||||
Option value unit:: messages
|
||||
@ -125,22 +129,19 @@ Applicable socket types:: ZMQ_SUB
|
||||
|
||||
ZMQ_IDENTITY: Set socket identity
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The 'ZMQ_IDENTITY' option shall set the identity of the specified 'socket'.
|
||||
Socket identity is used only by request/reply pattern. Namely, it can be used
|
||||
in tandem with ROUTER socket to route messages to the peer with specific
|
||||
identity.
|
||||
The 'ZMQ_IDENTITY' option shall set the identity of the specified 'socket'
|
||||
when connecting to a ROUTER socket. The identity should be from 1 to 255
|
||||
bytes long and MAY NOT start with binary zero.
|
||||
|
||||
Identity should be at least one byte and at most 255 bytes long. Identities
|
||||
starting with binary zero are reserved for use by 0MQ infrastructure.
|
||||
|
||||
If two peers use the same identity when connecting to a third peer, the
|
||||
results shall be undefined.
|
||||
If two clients use the same identity when connecting to a ROUTER, the
|
||||
ROUTER socket shall accept only the first such client and reject the
|
||||
others.
|
||||
|
||||
[horizontal]
|
||||
Option value type:: binary data
|
||||
Option value unit:: N/A
|
||||
Default value:: NULL
|
||||
Applicable socket types:: all
|
||||
Applicable socket types:: ZMQ_REQ, ZMQ_REP, ZMQ_ROUTER, ZMQ_DEALER.
|
||||
|
||||
|
||||
ZMQ_RATE: Set multicast data rate
|
||||
@ -371,11 +372,8 @@ ZMQ_ROUTER_MANDATORY: accept only routable messages on ROUTER sockets
|
||||
|
||||
Sets the 'ROUTER' socket behavior when an unroutable message is encountered. A
|
||||
value of `0` is the default and discards the message silently when it cannot be
|
||||
routed. A value of `1` returns an 'EAGAIN' error code if the message cannot be
|
||||
routed.
|
||||
|
||||
Note: Setting this socket option may have unpredictable effects on reactor-type
|
||||
libraries that assume EAGAIN will only be sent in HWM-type situations.
|
||||
routed. A value of `1` returns an 'EHOSTUNREACH' error code if the message
|
||||
cannot be routed.
|
||||
|
||||
[horizontal]
|
||||
Option value type:: int
|
||||
|
@ -58,8 +58,8 @@ general _messaging pattern_ which is built from related socket types.
|
||||
|
||||
Request-reply pattern
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
The request-reply pattern is used for sending requests from a _client_ to one
|
||||
or more instances of a _service_, and receiving subsequent replies to each
|
||||
The request-reply pattern is used for sending requests from a ZMQ_REQ _client_
|
||||
to one or more ZMQ_REP _services_, and receiving subsequent replies to each
|
||||
request sent.
|
||||
|
||||
|
||||
@ -71,10 +71,10 @@ sequence of _zmq_send(request)_ and subsequent _zmq_recv(reply)_ calls. Each
|
||||
request sent is round-robined among all _services_, and each reply received is
|
||||
matched with the last issued request.
|
||||
|
||||
When a 'ZMQ_REQ' socket enters an exceptional state due to having reached the
|
||||
When a 'ZMQ_REQ' socket enters the 'mute' state due to having reached the
|
||||
high water mark for all _services_, or if there are no _services_ at all, then
|
||||
any linkzmq:zmq_send[3] operations on the socket shall block until the
|
||||
exceptional state ends or at least one _service_ becomes available for sending;
|
||||
'mute' state ends or at least one _service_ becomes available for sending;
|
||||
messages are not discarded.
|
||||
|
||||
[horizontal]
|
||||
@ -84,7 +84,7 @@ Direction:: Bidirectional
|
||||
Send/receive pattern:: Send, Receive, Send, Receive, ...
|
||||
Outgoing routing strategy:: Round-robin
|
||||
Incoming routing strategy:: Last peer
|
||||
ZMQ_HWM option action:: Block
|
||||
Action in mute state:: Block
|
||||
|
||||
|
||||
ZMQ_REP
|
||||
@ -96,9 +96,9 @@ request received is fair-queued from among all _clients_, and each reply sent
|
||||
is routed to the _client_ that issued the last request. If the original
|
||||
requester doesn't exist any more the reply is silently discarded.
|
||||
|
||||
When a 'ZMQ_REP' socket enters an exceptional state due to having reached the
|
||||
When a 'ZMQ_REP' socket enters the 'mute' state due to having reached the
|
||||
high water mark for a _client_, then any replies sent to the _client_ in
|
||||
question shall be dropped until the exceptional state ends.
|
||||
question shall be dropped until the mute state ends.
|
||||
|
||||
[horizontal]
|
||||
.Summary of ZMQ_REP characteristics
|
||||
@ -107,7 +107,7 @@ Direction:: Bidirectional
|
||||
Send/receive pattern:: Receive, Send, Receive, Send, ...
|
||||
Incoming routing strategy:: Fair-queued
|
||||
Outgoing routing strategy:: Last peer
|
||||
ZMQ_HWM option action:: Drop
|
||||
Action in mute state:: Drop
|
||||
|
||||
|
||||
ZMQ_DEALER
|
||||
@ -116,9 +116,9 @@ A socket of type 'ZMQ_DEALER' is an advanced pattern used for extending
|
||||
request/reply sockets. Each message sent is round-robined among all connected
|
||||
peers, and each message received is fair-queued from all connected peers.
|
||||
|
||||
When a 'ZMQ_DEALER' socket enters an exceptional state due to having reached the
|
||||
When a 'ZMQ_DEALER' socket enters the 'mute' state due to having reached the
|
||||
high water mark for all peers, or if there are no peers at all, then any
|
||||
linkzmq:zmq_send[3] operations on the socket shall block until the exceptional
|
||||
linkzmq:zmq_send[3] operations on the socket shall block until the mute
|
||||
state ends or at least one peer becomes available for sending; messages are not
|
||||
discarded.
|
||||
|
||||
@ -130,12 +130,12 @@ Deprecated alias: 'ZMQ_XREQ'.
|
||||
|
||||
[horizontal]
|
||||
.Summary of ZMQ_DEALER characteristics
|
||||
Compatible peer sockets:: 'ZMQ_ROUTER', 'ZMQ_REP'
|
||||
Compatible peer sockets:: 'ZMQ_ROUTER', 'ZMQ_REP', 'ZMQ_DEALER'
|
||||
Direction:: Bidirectional
|
||||
Send/receive pattern:: Unrestricted
|
||||
Outgoing routing strategy:: Round-robin
|
||||
Incoming routing strategy:: Fair-queued
|
||||
ZMQ_HWM option action:: Block
|
||||
Action in mute state:: Block
|
||||
|
||||
|
||||
ZMQ_ROUTER
|
||||
@ -150,9 +150,9 @@ the peer the message shall be routed to. If the peer does not exist anymore
|
||||
the message shall be silently discarded by default, unless 'ZMQ_ROUTER_BEHAVIOR'
|
||||
socket option is set to '1'.
|
||||
|
||||
When a 'ZMQ_ROUTER' socket enters an exceptional state due to having reached the
|
||||
When a 'ZMQ_ROUTER' socket enters the 'mute' state due to having reached the
|
||||
high water mark for all peers, then any messages sent to the socket shall be dropped
|
||||
until the exceptional state ends. Likewise, any messages routed to a peer for which
|
||||
until the mute state ends. Likewise, any messages routed to a peer for which
|
||||
the individual high water mark has been reached shall also be dropped.
|
||||
|
||||
When a 'ZMQ_REQ' socket is connected to a 'ZMQ_ROUTER' socket, in addition to the
|
||||
@ -166,12 +166,12 @@ Deprecated alias: 'ZMQ_XREP'.
|
||||
|
||||
[horizontal]
|
||||
.Summary of ZMQ_ROUTER characteristics
|
||||
Compatible peer sockets:: 'ZMQ_DEALER', 'ZMQ_REQ'
|
||||
Compatible peer sockets:: 'ZMQ_DEALER', 'ZMQ_REQ', 'ZMQ_ROUTER'
|
||||
Direction:: Bidirectional
|
||||
Send/receive pattern:: Unrestricted
|
||||
Outgoing routing strategy:: See text
|
||||
Incoming routing strategy:: Fair-queued
|
||||
ZMQ_HWM option action:: Drop
|
||||
Action in mute state:: Drop
|
||||
|
||||
|
||||
Publish-subscribe pattern
|
||||
@ -186,9 +186,9 @@ A socket of type 'ZMQ_PUB' is used by a _publisher_ to distribute data.
|
||||
Messages sent are distributed in a fan out fashion to all connected peers.
|
||||
The linkzmq:zmq_recv[3] function is not implemented for this socket type.
|
||||
|
||||
When a 'ZMQ_PUB' socket enters an exceptional state due to having reached the
|
||||
When a 'ZMQ_PUB' socket enters the 'mute' state due to having reached the
|
||||
high water mark for a _subscriber_, then any messages that would be sent to the
|
||||
_subscriber_ in question shall instead be dropped until the exceptional state
|
||||
_subscriber_ in question shall instead be dropped until the mute state
|
||||
ends. The _zmq_send()_ function shall never block for this socket type.
|
||||
|
||||
[horizontal]
|
||||
@ -198,7 +198,7 @@ Direction:: Unidirectional
|
||||
Send/receive pattern:: Send only
|
||||
Incoming routing strategy:: N/A
|
||||
Outgoing routing strategy:: Fan out
|
||||
ZMQ_HWM option action:: Drop
|
||||
Action in mute state:: Drop
|
||||
|
||||
|
||||
ZMQ_SUB
|
||||
@ -216,7 +216,7 @@ Direction:: Unidirectional
|
||||
Send/receive pattern:: Receive only
|
||||
Incoming routing strategy:: Fair-queued
|
||||
Outgoing routing strategy:: N/A
|
||||
ZMQ_HWM option action:: Drop
|
||||
Action in mute state:: Drop
|
||||
|
||||
|
||||
ZMQ_XPUB
|
||||
@ -233,7 +233,7 @@ Direction:: Unidirectional
|
||||
Send/receive pattern:: Send messages, receive subscriptions
|
||||
Incoming routing strategy:: N/A
|
||||
Outgoing routing strategy:: Fan out
|
||||
ZMQ_HWM option action:: Drop
|
||||
Action in mute state:: Drop
|
||||
|
||||
|
||||
ZMQ_XSUB
|
||||
@ -249,7 +249,7 @@ Direction:: Unidirectional
|
||||
Send/receive pattern:: Receive messages, send subscriptions
|
||||
Incoming routing strategy:: Fair-queued
|
||||
Outgoing routing strategy:: N/A
|
||||
ZMQ_HWM option action:: Drop
|
||||
Action in mute state:: Drop
|
||||
|
||||
|
||||
Pipeline pattern
|
||||
@ -267,10 +267,10 @@ to downstream pipeline _nodes_. Messages are round-robined to all connected
|
||||
downstream _nodes_. The _zmq_recv()_ function is not implemented for this
|
||||
socket type.
|
||||
|
||||
When a 'ZMQ_PUSH' socket enters an exceptional state due to having reached the
|
||||
When a 'ZMQ_PUSH' socket enters the 'mute' state due to having reached the
|
||||
high water mark for all downstream _nodes_, or if there are no downstream
|
||||
_nodes_ at all, then any linkzmq:zmq_send[3] operations on the socket shall
|
||||
block until the exceptional state ends or at least one downstream _node_
|
||||
block until the mute state ends or at least one downstream _node_
|
||||
becomes available for sending; messages are not discarded.
|
||||
|
||||
[horizontal]
|
||||
@ -280,7 +280,7 @@ Direction:: Unidirectional
|
||||
Send/receive pattern:: Send only
|
||||
Incoming routing strategy:: N/A
|
||||
Outgoing routing strategy:: Round-robin
|
||||
ZMQ_HWM option action:: Block
|
||||
Action in mute state:: Block
|
||||
|
||||
|
||||
ZMQ_PULL
|
||||
@ -297,7 +297,7 @@ Direction:: Unidirectional
|
||||
Send/receive pattern:: Receive only
|
||||
Incoming routing strategy:: Fair-queued
|
||||
Outgoing routing strategy:: N/A
|
||||
ZMQ_HWM option action:: Block
|
||||
Action in mute state:: Block
|
||||
|
||||
|
||||
Exclusive pair pattern
|
||||
@ -313,7 +313,7 @@ A socket of type 'ZMQ_PAIR' can only be connected to a single peer at any one
|
||||
time. No message routing or filtering is performed on messages sent over a
|
||||
'ZMQ_PAIR' socket.
|
||||
|
||||
When a 'ZMQ_PAIR' socket enters an exceptional state due to having reached the
|
||||
When a 'ZMQ_PAIR' socket enters the 'mute' state due to having reached the
|
||||
high water mark for the connected peer, or if no peer is connected, then
|
||||
any linkzmq:zmq_send[3] operations on the socket shall block until the peer
|
||||
becomes available for sending; messages are not discarded.
|
||||
@ -330,7 +330,7 @@ Direction:: Bidirectional
|
||||
Send/receive pattern:: Unrestricted
|
||||
Incoming routing strategy:: N/A
|
||||
Outgoing routing strategy:: N/A
|
||||
ZMQ_HWM option action:: Block
|
||||
Action in mute state:: Block
|
||||
|
||||
|
||||
RETURN VALUE
|
||||
|
111
doc/zmq_tcp.txt
111
doc/zmq_tcp.txt
@ -16,10 +16,12 @@ your first choice.
|
||||
|
||||
ADDRESSING
|
||||
----------
|
||||
A 0MQ address string consists of two parts as follows:
|
||||
'transport'`://`'endpoint'. The 'transport' part specifies the underlying
|
||||
transport protocol to use, and for the TCP transport shall be set to `tcp`.
|
||||
The meaning of the 'endpoint' part for the TCP transport is defined below.
|
||||
A 0MQ endpoint is a string consisting of a 'transport'`://` followed by an
|
||||
'address'. The 'transport' specifies the underlying protocol to use. The
|
||||
'address' specifies the transport-specific address to connect to.
|
||||
|
||||
For the TCP transport, the transport is `tcp`, and the meaning of the
|
||||
'address' part is defined below.
|
||||
|
||||
|
||||
Assigning a local address to a socket
|
||||
@ -33,12 +35,17 @@ An 'interface' may be specified by either of the following:
|
||||
* The wild-card `*`, meaning all available interfaces.
|
||||
* The primary IPv4 or IPv6 address assigned to the interface, in its numeric
|
||||
representation.
|
||||
* The interface name as defined by the operating system.
|
||||
* The non-portable interface name as defined by the operating system.
|
||||
|
||||
The TCP port number may be specified by:
|
||||
|
||||
* A numeric value, usually above 1024 on POSIX systems.
|
||||
* The wild-card `*`, meaning a system-assigned ephemeral port.
|
||||
|
||||
When using ephemeral ports, the caller should retrieve the actual assigned
|
||||
port using the ZMQ_LAST_ENDPOINT socket option. See linkzmq:zmq_getsockopt[3]
|
||||
for details.
|
||||
|
||||
NOTE: Interface names are not standardised in any way and should be assumed to
|
||||
be arbitrary and platform dependent. On Win32 platforms no short interface
|
||||
names exist, thus only the primary IP address may be used to specify an
|
||||
'interface'.
|
||||
|
||||
Connecting a socket
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
@ -49,98 +56,30 @@ a colon and the TCP port number to use.
|
||||
A 'peer address' may be specified by either of the following:
|
||||
|
||||
* The DNS name of the peer.
|
||||
* The IPv4 or IPv6 address of the peer, in it's numeric representation.
|
||||
|
||||
|
||||
WIRE FORMAT
|
||||
-----------
|
||||
0MQ messages are transmitted over TCP in frames consisting of an encoded
|
||||
'payload length', followed by a 'flags' field and the message body. The 'payload
|
||||
length' is defined as the combined length in octets of the message body and the
|
||||
'flags' field.
|
||||
|
||||
For frames with a 'payload length' not exceeding 254 octets, the 'payload
|
||||
length' shall be encoded as a single octet. The minimum valid 'payload length'
|
||||
of a frame is 1 octet, thus a 'payload length' of 0 octets is invalid and such
|
||||
frames SHOULD be ignored.
|
||||
|
||||
For frames with a 'payload length' exceeding 254 octets, the 'payload length'
|
||||
shall be encoded as a single octet with the value `255` followed by the
|
||||
'payload length' represented as a 64-bit unsigned integer in network byte
|
||||
order.
|
||||
|
||||
The 'flags' field consists of a single octet containing various control flags:
|
||||
|
||||
Bit 0 (MORE): _More message parts to follow_. A value of 0 indicates that there
|
||||
are no more message parts to follow; or that the message being sent is not a
|
||||
multi-part message. A value of 1 indicates that the message being sent is a
|
||||
multi-part message and more message parts are to follow.
|
||||
|
||||
Bits 1-7: _Reserved_. Bits 1-7 are reserved for future expansion and MUST be
|
||||
set to zero.
|
||||
|
||||
The following ABNF grammar represents a single 'frame':
|
||||
|
||||
....
|
||||
frame = (length flags data)
|
||||
length = OCTET / (escape 8OCTET)
|
||||
flags = OCTET
|
||||
escape = %xFF
|
||||
data = *OCTET
|
||||
....
|
||||
|
||||
The following diagram illustrates the layout of a frame with a 'payload length'
|
||||
not exceeding 254 octets:
|
||||
|
||||
....
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Payload length| Flags | Message body ... |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Message body ...
|
||||
+-+-+-+-+-+-+- ...
|
||||
....
|
||||
|
||||
The following diagram illustrates the layout of a frame with a 'payload length'
|
||||
exceeding 254 octets:
|
||||
|
||||
....
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| 0xff | Payload length ... |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Payload length ... |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Payload length| Flags | Message body ... |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Message body ...
|
||||
+-+-+-+-+-+-+-+ ...
|
||||
....
|
||||
* The IPv4 or IPv6 address of the peer, in its numeric representation.
|
||||
|
||||
|
||||
EXAMPLES
|
||||
--------
|
||||
.Assigning a local address to a socket
|
||||
----
|
||||
/* TCP port 5555 on all available interfaces */
|
||||
rc = zmq_bind(socket, "tcp://*:5555");
|
||||
// TCP port 5555 on all available interfaces
|
||||
rc = zmq_bind(socket, "tcp:/// :5555");
|
||||
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");
|
||||
assert (rc == 0);
|
||||
/* TCP port 5555 on the first Ethernet network interface on Linux */
|
||||
// TCP port 5555 on the first Ethernet network interface on Linux
|
||||
rc = zmq_bind(socket, "tcp://eth0:5555");
|
||||
assert (rc == 0);
|
||||
----
|
||||
|
||||
.Connecting a socket
|
||||
----
|
||||
/* Connecting using an IP address */
|
||||
// Connecting using an IP address
|
||||
rc = zmq_connect(socket, "tcp://192.168.1.1:5555");
|
||||
assert (rc == 0);
|
||||
/* Connecting using a DNS name */
|
||||
// Connecting using a DNS name
|
||||
rc = zmq_connect(socket, "tcp://server1:5555");
|
||||
assert (rc == 0);
|
||||
----
|
||||
@ -158,5 +97,5 @@ linkzmq:zmq[7]
|
||||
|
||||
AUTHORS
|
||||
-------
|
||||
This 0MQ manual page was written by Martin Sustrik <sustrik@250bpm.com> and
|
||||
Martin Lucina <mato@kotelna.sk>.
|
||||
This 0MQ manual page was written by Pieter Hintjens <ph@imatix.com>,
|
||||
Martin Sustrik <sustrik@250bpm.com> and Martin Lucina <mato@kotelna.sk>.
|
||||
|
@ -60,7 +60,7 @@ extern "C" {
|
||||
/* Version macros for compile-time API version detection */
|
||||
#define ZMQ_VERSION_MAJOR 3
|
||||
#define ZMQ_VERSION_MINOR 2
|
||||
#define ZMQ_VERSION_PATCH 1
|
||||
#define ZMQ_VERSION_PATCH 5
|
||||
|
||||
#define ZMQ_MAKE_VERSION(major, minor, patch) \
|
||||
((major) * 10000 + (minor) * 100 + (patch))
|
||||
@ -261,6 +261,7 @@ ZMQ_EXPORT int zmq_msg_set (zmq_msg_t *msg, int option, int optval);
|
||||
|
||||
/* Deprecated aliases */
|
||||
#define ZMQ_NOBLOCK ZMQ_DONTWAIT
|
||||
#define ZMQ_FAIL_UNROUTABLE ZMQ_ROUTER_MANDATORY
|
||||
#define ZMQ_ROUTER_BEHAVIOR ZMQ_ROUTER_MANDATORY
|
||||
|
||||
/******************************************************************************/
|
||||
@ -380,15 +381,15 @@ typedef struct
|
||||
|
||||
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);
|
||||
|
||||
// Deprecated aliases
|
||||
/* Deprecated aliases */
|
||||
#define ZMQ_STREAMER 1
|
||||
#define ZMQ_FORWARDER 2
|
||||
#define ZMQ_QUEUE 3
|
||||
// Deprecated method
|
||||
/* Deprecated method */
|
||||
ZMQ_EXPORT int zmq_device (int type, void *frontend, void *backend);
|
||||
|
||||
#undef ZMQ_EXPORT
|
||||
|
@ -23,6 +23,12 @@ libzmq_la_SOURCES = \
|
||||
err.hpp \
|
||||
fd.hpp \
|
||||
fq.hpp \
|
||||
i_encoder.hpp \
|
||||
i_decoder.hpp \
|
||||
i_engine.hpp \
|
||||
i_msg_sink.hpp \
|
||||
i_msg_source.hpp \
|
||||
i_poll_events.hpp \
|
||||
io_object.hpp \
|
||||
io_thread.hpp \
|
||||
ip.hpp \
|
||||
@ -134,7 +140,10 @@ libzmq_la_SOURCES = \
|
||||
router.cpp \
|
||||
dealer.cpp \
|
||||
v1_decoder.cpp \
|
||||
v1_decoder.hpp \
|
||||
v1_encoder.cpp \
|
||||
v1_encoder.hpp \
|
||||
v1_protocol.hpp \
|
||||
xsub.cpp \
|
||||
zmq.cpp \
|
||||
zmq_utils.cpp
|
||||
|
@ -91,7 +91,6 @@ int zmq::ctx_t::terminate ()
|
||||
// restarted.
|
||||
bool restarted = terminating;
|
||||
terminating = true;
|
||||
slot_sync.unlock ();
|
||||
|
||||
// First attempt to terminate the context.
|
||||
if (!restarted) {
|
||||
@ -99,13 +98,12 @@ int zmq::ctx_t::terminate ()
|
||||
// First send stop command to sockets so that any blocking calls
|
||||
// can be interrupted. If there are no sockets we can ask reaper
|
||||
// thread to stop.
|
||||
slot_sync.lock ();
|
||||
for (sockets_t::size_type i = 0; i != sockets.size (); i++)
|
||||
sockets [i]->stop ();
|
||||
if (sockets.empty ())
|
||||
reaper->stop ();
|
||||
slot_sync.unlock ();
|
||||
}
|
||||
slot_sync.unlock();
|
||||
|
||||
// Wait till reaper thread closes all the sockets.
|
||||
command_t cmd;
|
||||
|
@ -57,11 +57,6 @@ void zmq::decoder_t::set_msg_sink (i_msg_sink *msg_sink_)
|
||||
msg_sink = msg_sink_;
|
||||
}
|
||||
|
||||
bool zmq::decoder_t::stalled () const
|
||||
{
|
||||
return next == &decoder_t::message_ready;
|
||||
}
|
||||
|
||||
bool zmq::decoder_t::one_byte_size_ready ()
|
||||
{
|
||||
// First byte of size is read. If it is 0xff read 8-byte size.
|
||||
|
@ -35,8 +35,6 @@
|
||||
namespace zmq
|
||||
{
|
||||
|
||||
class i_msg_sink;
|
||||
|
||||
// Helper base class for decoders that know the amount of data to read
|
||||
// in advance at any moment. Knowing the amount in advance is a property
|
||||
// of the protocol used. 0MQ framing protocol is based size-prefixed
|
||||
@ -143,6 +141,32 @@ namespace zmq
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the decoder has been fed all required data
|
||||
// but cannot proceed with the next decoding step.
|
||||
// False is returned if the decoder has encountered an error.
|
||||
bool stalled ()
|
||||
{
|
||||
// Check whether there was decoding error.
|
||||
if (unlikely (!(static_cast <T*> (this)->next)))
|
||||
return false;
|
||||
|
||||
while (!to_read) {
|
||||
if (!(static_cast <T*> (this)->*next) ()) {
|
||||
if (unlikely (!(static_cast <T*> (this)->next)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool message_ready_size (size_t msg_sz)
|
||||
{
|
||||
zmq_assert (false);
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
// Prototype of state machine action. Action should return false if
|
||||
@ -166,13 +190,13 @@ namespace zmq
|
||||
next = NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Next step. If set to NULL, it means that associated data stream
|
||||
// is dead. Note that there can be still data in the process in such
|
||||
// case.
|
||||
step_t next;
|
||||
|
||||
private:
|
||||
|
||||
// Where to store the read data.
|
||||
unsigned char *read_pos;
|
||||
|
||||
@ -199,10 +223,6 @@ namespace zmq
|
||||
// Set the receiver of decoded messages.
|
||||
void set_msg_sink (i_msg_sink *msg_sink_);
|
||||
|
||||
// Returns true if there is a decoded message
|
||||
// waiting to be delivered to the session.
|
||||
bool stalled () const;
|
||||
|
||||
private:
|
||||
|
||||
bool one_byte_size_ready ();
|
||||
|
13
src/dist.cpp
Normal file → Executable file
13
src/dist.cpp
Normal file → Executable file
@ -80,12 +80,19 @@ void zmq::dist_t::terminated (pipe_t *pipe_)
|
||||
{
|
||||
// Remove the pipe from the list; adjust number of matching, active and/or
|
||||
// eligible pipes accordingly.
|
||||
if (pipes.index (pipe_) < matching)
|
||||
if (pipes.index (pipe_) < matching) {
|
||||
pipes.swap (pipes.index (pipe_), matching - 1);
|
||||
matching--;
|
||||
if (pipes.index (pipe_) < active)
|
||||
}
|
||||
if (pipes.index (pipe_) < active) {
|
||||
pipes.swap (pipes.index (pipe_), active - 1);
|
||||
active--;
|
||||
if (pipes.index (pipe_) < eligible)
|
||||
}
|
||||
if (pipes.index (pipe_) < eligible) {
|
||||
pipes.swap (pipes.index (pipe_), eligible - 1);
|
||||
eligible--;
|
||||
}
|
||||
|
||||
pipes.erase (pipe_);
|
||||
}
|
||||
|
||||
|
@ -40,8 +40,6 @@
|
||||
namespace zmq
|
||||
{
|
||||
|
||||
class i_msg_source;
|
||||
|
||||
// Helper base class for encoders. It implements the state machine that
|
||||
// fills the outgoing buffer. Derived classes should implement individual
|
||||
// state machine actions.
|
||||
|
@ -140,9 +140,10 @@ void zmq::epoll_t::loop ()
|
||||
// Wait for events.
|
||||
int n = epoll_wait (epoll_fd, &ev_buf [0], max_io_events,
|
||||
timeout ? timeout : -1);
|
||||
if (n == -1 && errno == EINTR)
|
||||
if (n == -1) {
|
||||
errno_assert (errno == EINTR);
|
||||
continue;
|
||||
errno_assert (n != -1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < n; i ++) {
|
||||
poll_entry_t *pe = ((poll_entry_t*) ev_buf [i].data.ptr);
|
||||
|
@ -26,7 +26,8 @@
|
||||
namespace zmq
|
||||
{
|
||||
|
||||
class i_msg_sink;
|
||||
// Forward declaration
|
||||
struct i_msg_sink;
|
||||
|
||||
// Interface to be implemented by message decoder.
|
||||
|
||||
@ -40,7 +41,7 @@ namespace zmq
|
||||
|
||||
virtual size_t process_buffer (unsigned char *data_, size_t size_) = 0;
|
||||
|
||||
virtual bool stalled () const = 0;
|
||||
virtual bool stalled () = 0;
|
||||
|
||||
};
|
||||
|
||||
|
@ -27,7 +27,7 @@ namespace zmq
|
||||
{
|
||||
|
||||
// Forward declaration
|
||||
class i_msg_source;
|
||||
struct i_msg_source;
|
||||
|
||||
// Interface to be implemented by message encoder.
|
||||
|
||||
|
@ -122,7 +122,7 @@ void zmq::ipc_connecter_t::out_event ()
|
||||
// Shut the connecter down.
|
||||
terminate ();
|
||||
|
||||
socket->event_connected (endpoint.c_str(), fd);
|
||||
socket->event_connected (endpoint, fd);
|
||||
}
|
||||
|
||||
void zmq::ipc_connecter_t::timer_event (int id_)
|
||||
@ -145,11 +145,12 @@ void zmq::ipc_connecter_t::start_connecting ()
|
||||
}
|
||||
|
||||
// Connection establishment may be delayed. Poll for its completion.
|
||||
else if (rc == -1 && errno == EINPROGRESS) {
|
||||
else
|
||||
if (rc == -1 && errno == EINPROGRESS) {
|
||||
handle = add_fd (s);
|
||||
handle_valid = true;
|
||||
set_pollout (handle);
|
||||
socket->event_connect_delayed (endpoint.c_str(), zmq_errno());
|
||||
socket->event_connect_delayed (endpoint, zmq_errno());
|
||||
}
|
||||
|
||||
// Handle any other error condition by eventual reconnect.
|
||||
@ -164,7 +165,7 @@ void zmq::ipc_connecter_t::add_reconnect_timer()
|
||||
{
|
||||
int rc_ivl = get_new_reconnect_ivl();
|
||||
add_timer (rc_ivl, reconnect_timer_id);
|
||||
socket->event_connect_retried (endpoint.c_str(), rc_ivl);
|
||||
socket->event_connect_retried (endpoint, rc_ivl);
|
||||
timer_started = true;
|
||||
}
|
||||
|
||||
@ -225,7 +226,7 @@ int zmq::ipc_connecter_t::close ()
|
||||
zmq_assert (s != retired_fd);
|
||||
int rc = ::close (s);
|
||||
errno_assert (rc == 0);
|
||||
socket->event_closed (endpoint.c_str(), s);
|
||||
socket->event_closed (endpoint, s);
|
||||
s = retired_fd;
|
||||
return 0;
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ void zmq::ipc_listener_t::in_event ()
|
||||
// If connection was reset by the peer in the meantime, just ignore it.
|
||||
// TODO: Handle specific errors like ENFILE/EMFILE etc.
|
||||
if (fd == retired_fd) {
|
||||
socket->event_accept_failed (endpoint.c_str(), zmq_errno());
|
||||
socket->event_accept_failed (endpoint, zmq_errno());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -96,7 +96,7 @@ void zmq::ipc_listener_t::in_event ()
|
||||
session->inc_seqnum ();
|
||||
launch_child (session);
|
||||
send_attach (session, engine, false);
|
||||
socket->event_accepted (endpoint.c_str(), fd);
|
||||
socket->event_accepted (endpoint, fd);
|
||||
}
|
||||
|
||||
int zmq::ipc_listener_t::get_address (std::string &addr_)
|
||||
@ -155,7 +155,7 @@ int zmq::ipc_listener_t::set_address (const char *addr_)
|
||||
if (rc != 0)
|
||||
goto error;
|
||||
|
||||
socket->event_listening (endpoint.c_str(), s);
|
||||
socket->event_listening (endpoint, s);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
@ -178,12 +178,12 @@ int zmq::ipc_listener_t::close ()
|
||||
if (has_file && !filename.empty ()) {
|
||||
rc = ::unlink(filename.c_str ());
|
||||
if (rc != 0) {
|
||||
socket->event_close_failed (endpoint.c_str(), zmq_errno());
|
||||
socket->event_close_failed (endpoint, zmq_errno());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
socket->event_closed (endpoint.c_str(), s);
|
||||
socket->event_closed (endpoint, s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -163,9 +163,10 @@ void zmq::kqueue_t::loop ()
|
||||
timespec ts = {timeout / 1000, (timeout % 1000) * 1000000};
|
||||
int n = kevent (kqueue_fd, NULL, 0, &ev_buf [0], max_io_events,
|
||||
timeout ? &ts: NULL);
|
||||
if (n == -1 && errno == EINTR)
|
||||
if (n == -1) {
|
||||
errno_assert (errno == EINTR);
|
||||
continue;
|
||||
errno_assert (n != -1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < n; i ++) {
|
||||
poll_entry_t *pe = (poll_entry_t*) ev_buf [i].udata;
|
||||
|
@ -113,7 +113,8 @@ int zmq::lb_t::send (msg_t *msg_, int flags_)
|
||||
more = msg_->flags () & msg_t::more? true: false;
|
||||
if (!more) {
|
||||
pipes [current]->flush ();
|
||||
current = (current + 1) % active;
|
||||
if (++current >= active)
|
||||
current = 0;
|
||||
}
|
||||
|
||||
// Detach the message from the data buffer.
|
||||
|
@ -35,6 +35,11 @@ zmq::mailbox_t::mailbox_t ()
|
||||
zmq::mailbox_t::~mailbox_t ()
|
||||
{
|
||||
// TODO: Retrieve and deallocate commands inside the cpipe.
|
||||
|
||||
// Work around problem that other threads might still be in our
|
||||
// send() method, by waiting on the mutex before disappearing.
|
||||
sync.lock ();
|
||||
sync.unlock ();
|
||||
}
|
||||
|
||||
zmq::fd_t zmq::mailbox_t::get_fd ()
|
||||
|
@ -283,7 +283,14 @@ bool zmq::msg_t::rm_refs (int refs_)
|
||||
|
||||
// The only message type that needs special care are long messages.
|
||||
if (!u.lmsg.content->refcnt.sub (refs_)) {
|
||||
close ();
|
||||
// We used "placement new" operator to initialize the reference
|
||||
// counter so we call the destructor explicitly now.
|
||||
u.lmsg.content->refcnt.~atomic_counter_t ();
|
||||
|
||||
if (u.lmsg.content->ffn)
|
||||
u.lmsg.content->ffn (u.lmsg.content->data, u.lmsg.content->hint);
|
||||
free (u.lmsg.content);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -338,10 +338,11 @@ int zmq::pgm_socket_t::init (bool udp_encapsulation_, const char *network_)
|
||||
goto err_abort;
|
||||
|
||||
// Expedited Forwarding PHB for network elements, no ECN.
|
||||
// Ignore return value due to varied runtime support.
|
||||
const int dscp = 0x2e << 2;
|
||||
if (AF_INET6 != sa_family && !pgm_setsockopt (sock,
|
||||
IPPROTO_PGM, PGM_TOS, &dscp, sizeof (dscp)))
|
||||
goto err_abort;
|
||||
if (AF_INET6 != sa_family)
|
||||
pgm_setsockopt (sock, IPPROTO_PGM, PGM_TOS,
|
||||
&dscp, sizeof (dscp));
|
||||
|
||||
const int nonblocking = 1;
|
||||
if (!pgm_setsockopt (sock, IPPROTO_PGM, PGM_NOBLOCK,
|
||||
|
@ -125,10 +125,10 @@ void zmq::poll_t::loop ()
|
||||
|
||||
// Wait for events.
|
||||
int rc = poll (&pollset [0], pollset.size (), timeout ? timeout : -1);
|
||||
if (rc == -1 && errno == EINTR)
|
||||
if (rc == -1) {
|
||||
errno_assert (errno == EINTR);
|
||||
continue;
|
||||
errno_assert (rc != -1);
|
||||
|
||||
}
|
||||
|
||||
// If there are no events (i.e. it's a timeout) there's no point
|
||||
// in checking the pollset.
|
||||
|
@ -19,13 +19,42 @@
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include "../include/zmq.h"
|
||||
#include "platform.hpp"
|
||||
#include "proxy.hpp"
|
||||
#include "socket_base.hpp"
|
||||
#include "likely.hpp"
|
||||
|
||||
#if defined ZMQ_FORCE_SELECT
|
||||
#define ZMQ_POLL_BASED_ON_SELECT
|
||||
#elif defined ZMQ_FORCE_POLL
|
||||
#define ZMQ_POLL_BASED_ON_POLL
|
||||
#elif defined ZMQ_HAVE_LINUX || defined ZMQ_HAVE_FREEBSD ||\
|
||||
defined ZMQ_HAVE_OPENBSD || defined ZMQ_HAVE_SOLARIS ||\
|
||||
defined ZMQ_HAVE_OSX || defined ZMQ_HAVE_QNXNTO ||\
|
||||
defined ZMQ_HAVE_HPUX || defined ZMQ_HAVE_AIX ||\
|
||||
defined ZMQ_HAVE_NETBSD
|
||||
#define ZMQ_POLL_BASED_ON_POLL
|
||||
#elif defined ZMQ_HAVE_WINDOWS || defined ZMQ_HAVE_OPENVMS ||\
|
||||
defined ZMQ_HAVE_CYGWIN
|
||||
#define ZMQ_POLL_BASED_ON_SELECT
|
||||
#endif
|
||||
|
||||
// On AIX platform, poll.h has to be included first to get consistent
|
||||
// definition of pollfd structure (AIX uses 'reqevents' and 'retnevents'
|
||||
// instead of 'events' and 'revents' and defines macros to map from POSIX-y
|
||||
// names to AIX-specific names).
|
||||
#if defined ZMQ_POLL_BASED_ON_POLL
|
||||
#include <poll.h>
|
||||
#endif
|
||||
|
||||
// These headers end up pulling in zmq.h somewhere in their include
|
||||
// dependency chain
|
||||
#include "socket_base.hpp"
|
||||
#include "err.hpp"
|
||||
|
||||
// zmq.h must be included *after* poll.h for AIX to build properly
|
||||
#include "../include/zmq.h"
|
||||
|
||||
|
||||
int zmq::proxy (
|
||||
class socket_base_t *frontend_,
|
||||
class socket_base_t *backend_,
|
||||
|
@ -162,7 +162,7 @@ int zmq::router_t::xsend (msg_t *msg_, int flags_)
|
||||
else
|
||||
if (mandatory) {
|
||||
more_out = false;
|
||||
errno = EAGAIN;
|
||||
errno = EHOSTUNREACH;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -168,9 +168,10 @@ void zmq::select_t::loop ()
|
||||
#else
|
||||
int rc = select (maxfd + 1, &readfds, &writefds, &exceptfds,
|
||||
timeout ? &tv : NULL);
|
||||
if (rc == -1 && errno == EINTR)
|
||||
if (rc == -1) {
|
||||
errno_assert (errno == EINTR);
|
||||
continue;
|
||||
errno_assert (rc != -1);
|
||||
}
|
||||
#endif
|
||||
|
||||
// If there are no events (i.e. it's a timeout) there's no point
|
||||
|
@ -223,7 +223,7 @@ void zmq::session_base_t::clean_pipes ()
|
||||
msg_t msg;
|
||||
int rc = msg.init ();
|
||||
errno_assert (rc == 0);
|
||||
if (!pull_msg (&msg)) {
|
||||
if (pull_msg (&msg) != 0) {
|
||||
zmq_assert (!incomplete_in);
|
||||
break;
|
||||
}
|
||||
|
@ -95,7 +95,11 @@ zmq::signaler_t::~signaler_t ()
|
||||
int rc = close (r);
|
||||
errno_assert (rc == 0);
|
||||
#elif defined ZMQ_HAVE_WINDOWS
|
||||
int rc = closesocket (w);
|
||||
struct linger so_linger = { 1, 0 };
|
||||
int rc = setsockopt (w, SOL_SOCKET, SO_LINGER,
|
||||
(char *)&so_linger, sizeof (so_linger));
|
||||
wsa_assert (rc != SOCKET_ERROR);
|
||||
rc = closesocket (w);
|
||||
wsa_assert (rc != SOCKET_ERROR);
|
||||
rc = closesocket (r);
|
||||
wsa_assert (rc != SOCKET_ERROR);
|
||||
@ -279,7 +283,7 @@ int zmq::signaler_t::make_fdpair (fd_t *r_, fd_t *w_)
|
||||
(char *)&tcp_nodelay, sizeof (tcp_nodelay));
|
||||
wsa_assert (rc != SOCKET_ERROR);
|
||||
|
||||
// Bind listening socket to any free local port.
|
||||
// Bind listening socket to signaler port.
|
||||
struct sockaddr_in addr;
|
||||
memset (&addr, 0, sizeof (addr));
|
||||
addr.sin_family = AF_INET;
|
||||
@ -307,15 +311,19 @@ int zmq::signaler_t::make_fdpair (fd_t *r_, fd_t *w_)
|
||||
|
||||
// Connect writer to the listener.
|
||||
rc = connect (*w_, (struct sockaddr*) &addr, sizeof (addr));
|
||||
wsa_assert (rc != SOCKET_ERROR);
|
||||
|
||||
// Accept connection from writer.
|
||||
*r_ = accept (listener, NULL, NULL);
|
||||
wsa_assert (*r_ != INVALID_SOCKET);
|
||||
// Save errno if connection fails
|
||||
int conn_errno = 0;
|
||||
if (rc == SOCKET_ERROR) {
|
||||
conn_errno = WSAGetLastError ();
|
||||
} else {
|
||||
// Accept connection from writer.
|
||||
*r_ = accept (listener, NULL, NULL);
|
||||
|
||||
// On Windows, preventing sockets to be inherited by child processes.
|
||||
brc = SetHandleInformation ((HANDLE) *r_, HANDLE_FLAG_INHERIT, 0);
|
||||
win_assert (brc);
|
||||
if (*r_ == INVALID_SOCKET) {
|
||||
conn_errno = WSAGetLastError ();
|
||||
}
|
||||
}
|
||||
|
||||
// We don't need the listening socket anymore. Close it.
|
||||
rc = closesocket (listener);
|
||||
@ -325,7 +333,33 @@ int zmq::signaler_t::make_fdpair (fd_t *r_, fd_t *w_)
|
||||
brc = SetEvent (sync);
|
||||
win_assert (brc != 0);
|
||||
|
||||
return 0;
|
||||
// Release the kernel object
|
||||
brc = CloseHandle (sync);
|
||||
win_assert (brc != 0);
|
||||
|
||||
if (*r_ != INVALID_SOCKET) {
|
||||
// On Windows, preventing sockets to be inherited by child processes.
|
||||
brc = SetHandleInformation ((HANDLE) *r_, HANDLE_FLAG_INHERIT, 0);
|
||||
win_assert (brc);
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
// Cleanup writer if connection failed
|
||||
rc = closesocket (*w_);
|
||||
wsa_assert (rc != SOCKET_ERROR);
|
||||
|
||||
*w_ = INVALID_SOCKET;
|
||||
|
||||
// Set errno from saved value
|
||||
errno = wsa_error_to_errno (conn_errno);
|
||||
|
||||
// Ideally, we would return errno to the caller signaler_t()
|
||||
// Unfortunately, it uses errno_assert() which gives "Unknown error"
|
||||
// We might as well assert here and print the actual error message
|
||||
wsa_assert_no (conn_errno);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#elif defined ZMQ_HAVE_OPENVMS
|
||||
|
||||
|
@ -357,7 +357,7 @@ int zmq::socket_base_t::bind (const char *addr_)
|
||||
int rc = listener->set_address (address.c_str ());
|
||||
if (rc != 0) {
|
||||
delete listener;
|
||||
event_bind_failed (addr_, zmq_errno());
|
||||
event_bind_failed (address, zmq_errno());
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -376,7 +376,7 @@ int zmq::socket_base_t::bind (const char *addr_)
|
||||
int rc = listener->set_address (address.c_str ());
|
||||
if (rc != 0) {
|
||||
delete listener;
|
||||
event_bind_failed (addr_, zmq_errno());
|
||||
event_bind_failed (address, zmq_errno());
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -428,15 +428,11 @@ int zmq::socket_base_t::connect (const char *addr_)
|
||||
|
||||
// The total HWM for an inproc connection should be the sum of
|
||||
// the binder's HWM and the connector's HWM.
|
||||
int sndhwm;
|
||||
int rcvhwm;
|
||||
if (options.sndhwm == 0 || peer.options.rcvhwm == 0)
|
||||
sndhwm = 0;
|
||||
else
|
||||
int sndhwm = 0;
|
||||
if (options.sndhwm != 0 && peer.options.rcvhwm != 0)
|
||||
sndhwm = options.sndhwm + peer.options.rcvhwm;
|
||||
if (options.rcvhwm == 0 || peer.options.sndhwm == 0)
|
||||
rcvhwm = 0;
|
||||
else
|
||||
int rcvhwm = 0;
|
||||
if (options.rcvhwm != 0 && peer.options.sndhwm != 0)
|
||||
rcvhwm = options.rcvhwm + peer.options.sndhwm;
|
||||
|
||||
// Create a bi-directional pipe to connect the peers.
|
||||
@ -482,6 +478,9 @@ int zmq::socket_base_t::connect (const char *addr_)
|
||||
// Save last endpoint URI
|
||||
options.last_endpoint.assign (addr_);
|
||||
|
||||
// remember inproc connections for disconnect
|
||||
inprocs.insert (inprocs_t::value_type (std::string (addr_), pipes[0]));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -507,7 +506,8 @@ int zmq::socket_base_t::connect (const char *addr_)
|
||||
}
|
||||
}
|
||||
#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS
|
||||
else if(protocol == "ipc") {
|
||||
else
|
||||
if (protocol == "ipc") {
|
||||
paddr->resolved.ipc_addr = new (std::nothrow) ipc_address_t ();
|
||||
alloc_assert (paddr->resolved.ipc_addr);
|
||||
int rc = paddr->resolved.ipc_addr->resolve (address.c_str ());
|
||||
@ -587,10 +587,38 @@ int zmq::socket_base_t::term_endpoint (const char *addr_)
|
||||
if (unlikely (rc != 0))
|
||||
return -1;
|
||||
|
||||
// Parse addr_ string.
|
||||
std::string protocol;
|
||||
std::string address;
|
||||
rc = parse_uri (addr_, protocol, address);
|
||||
if (rc != 0)
|
||||
return -1;
|
||||
|
||||
rc = check_protocol (protocol);
|
||||
if (rc != 0)
|
||||
return -1;
|
||||
|
||||
// Disconnect an inproc socket
|
||||
if (protocol == "inproc") {
|
||||
std::pair <inprocs_t::iterator, inprocs_t::iterator> range = inprocs.equal_range (std::string (addr_));
|
||||
if (range.first == range.second) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (inprocs_t::iterator it = range.first; it != range.second; ++it)
|
||||
it->second->terminate(true);
|
||||
inprocs.erase (range.first, range.second);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Find the endpoints range (if any) corresponding to the addr_ string.
|
||||
std::pair <endpoints_t::iterator, endpoints_t::iterator> range = endpoints.equal_range (std::string (addr_));
|
||||
if (range.first == range.second)
|
||||
if (range.first == range.second) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (endpoints_t::iterator it = range.first; it != range.second; ++it)
|
||||
term_child (it->second);
|
||||
@ -677,11 +705,6 @@ int zmq::socket_base_t::recv (msg_t *msg_, int flags_)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Get the message.
|
||||
int rc = xrecv (msg_, flags_);
|
||||
if (unlikely (rc != 0 && errno != EAGAIN))
|
||||
return -1;
|
||||
|
||||
// Once every inbound_poll_rate messages check for signals and process
|
||||
// incoming commands. This happens only if we are not polling altogether
|
||||
// because there are messages available all the time. If poll occurs,
|
||||
@ -696,6 +719,11 @@ int zmq::socket_base_t::recv (msg_t *msg_, int flags_)
|
||||
ticks = 0;
|
||||
}
|
||||
|
||||
// Get the message.
|
||||
int rc = xrecv (msg_, flags_);
|
||||
if (unlikely (rc != 0 && errno != EAGAIN))
|
||||
return -1;
|
||||
|
||||
// If we have the message, return immediately.
|
||||
if (rc == 0) {
|
||||
extract_flags (msg_);
|
||||
@ -983,6 +1011,14 @@ void zmq::socket_base_t::terminated (pipe_t *pipe_)
|
||||
// Notify the specific socket type about the pipe termination.
|
||||
xterminated (pipe_);
|
||||
|
||||
// Remove pipe from inproc pipes
|
||||
for (inprocs_t::iterator it = inprocs.begin(); it != inprocs.end(); ++it) {
|
||||
if (it->second == pipe_) {
|
||||
inprocs.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the pipe from the list of attached pipes and confirm its
|
||||
// termination if we are already shutting down.
|
||||
pipes.erase (pipe_);
|
||||
@ -1033,8 +1069,7 @@ int zmq::socket_base_t::monitor (const char *addr_, int events_)
|
||||
|
||||
// Register events to monitor
|
||||
monitor_events = events_;
|
||||
|
||||
monitor_socket = zmq_socket( get_ctx (), ZMQ_PAIR);
|
||||
monitor_socket = zmq_socket (get_ctx (), ZMQ_PAIR);
|
||||
if (monitor_socket == NULL)
|
||||
return -1;
|
||||
|
||||
@ -1051,114 +1086,144 @@ int zmq::socket_base_t::monitor (const char *addr_, int events_)
|
||||
return rc;
|
||||
}
|
||||
|
||||
void zmq::socket_base_t::event_connected (const char *addr_, int fd_)
|
||||
void zmq::socket_base_t::event_connected (std::string &addr_, int fd_)
|
||||
{
|
||||
zmq_event_t event;
|
||||
if (!(monitor_events & ZMQ_EVENT_CONNECTED)) return;
|
||||
event.event = ZMQ_EVENT_CONNECTED;
|
||||
event.data.connected.addr = (char *)addr_;
|
||||
event.data.connected.fd = fd_;
|
||||
monitor_event (event);
|
||||
if (monitor_events & ZMQ_EVENT_CONNECTED) {
|
||||
zmq_event_t event;
|
||||
event.event = ZMQ_EVENT_CONNECTED;
|
||||
event.data.connected.addr = (char *) malloc (addr_.size () + 1);
|
||||
copy_monitor_address (event.data.connected.addr, addr_);
|
||||
event.data.connected.fd = fd_;
|
||||
monitor_event (event);
|
||||
}
|
||||
}
|
||||
|
||||
void zmq::socket_base_t::event_connect_delayed (const char *addr_, int err_)
|
||||
void zmq::socket_base_t::event_connect_delayed (std::string &addr_, int err_)
|
||||
{
|
||||
zmq_event_t event;
|
||||
if (!(monitor_events & ZMQ_EVENT_CONNECT_DELAYED)) return;
|
||||
event.event = ZMQ_EVENT_CONNECT_DELAYED;
|
||||
event.data.connected.addr = (char *)addr_;
|
||||
event.data.connect_delayed.err = err_;
|
||||
monitor_event (event);
|
||||
if (monitor_events & ZMQ_EVENT_CONNECT_DELAYED) {
|
||||
zmq_event_t event;
|
||||
event.event = ZMQ_EVENT_CONNECT_DELAYED;
|
||||
event.data.connect_delayed.addr = (char *) malloc (addr_.size () + 1);
|
||||
copy_monitor_address (event.data.connect_delayed.addr, addr_);
|
||||
event.data.connect_delayed.err = err_;
|
||||
monitor_event (event);
|
||||
}
|
||||
}
|
||||
|
||||
void zmq::socket_base_t::event_connect_retried (const char *addr_, int interval_)
|
||||
void zmq::socket_base_t::event_connect_retried (std::string &addr_, int interval_)
|
||||
{
|
||||
zmq_event_t event;
|
||||
if (!(monitor_events & ZMQ_EVENT_CONNECT_RETRIED)) return;
|
||||
event.event = ZMQ_EVENT_CONNECT_RETRIED;
|
||||
event.data.connected.addr = (char *)addr_;
|
||||
event.data.connect_retried.interval = interval_;
|
||||
monitor_event (event);
|
||||
if (monitor_events & ZMQ_EVENT_CONNECT_RETRIED) {
|
||||
zmq_event_t event;
|
||||
event.event = ZMQ_EVENT_CONNECT_RETRIED;
|
||||
event.data.connect_retried.addr = (char *) malloc (addr_.size () + 1);
|
||||
copy_monitor_address (event.data.connect_retried.addr, addr_);
|
||||
event.data.connect_retried.interval = interval_;
|
||||
monitor_event (event);
|
||||
}
|
||||
}
|
||||
|
||||
void zmq::socket_base_t::event_listening (const char *addr_, int fd_)
|
||||
void zmq::socket_base_t::event_listening (std::string &addr_, int fd_)
|
||||
{
|
||||
zmq_event_t event;
|
||||
if (!(monitor_events & ZMQ_EVENT_LISTENING)) return;
|
||||
event.event = ZMQ_EVENT_LISTENING;
|
||||
event.data.connected.addr = (char *)addr_;
|
||||
event.data.listening.fd = fd_;
|
||||
monitor_event (event);
|
||||
if (monitor_events & ZMQ_EVENT_LISTENING) {
|
||||
zmq_event_t event;
|
||||
event.event = ZMQ_EVENT_LISTENING;
|
||||
event.data.listening.addr = (char *) malloc (addr_.size () + 1);
|
||||
copy_monitor_address (event.data.listening.addr, addr_);
|
||||
event.data.listening.fd = fd_;
|
||||
monitor_event (event);
|
||||
}
|
||||
}
|
||||
|
||||
void zmq::socket_base_t::event_bind_failed (const char *addr_, int err_)
|
||||
void zmq::socket_base_t::event_bind_failed (std::string &addr_, int err_)
|
||||
{
|
||||
zmq_event_t event;
|
||||
if (!(monitor_events & ZMQ_EVENT_BIND_FAILED)) return;
|
||||
event.event = ZMQ_EVENT_BIND_FAILED;
|
||||
event.data.connected.addr = (char *)addr_;
|
||||
event.data.bind_failed.err = err_;
|
||||
monitor_event (event);
|
||||
if (monitor_events & ZMQ_EVENT_BIND_FAILED) {
|
||||
zmq_event_t event;
|
||||
event.event = ZMQ_EVENT_BIND_FAILED;
|
||||
event.data.bind_failed.addr = (char *) malloc (addr_.size () + 1);
|
||||
copy_monitor_address (event.data.bind_failed.addr, addr_);
|
||||
event.data.bind_failed.err = err_;
|
||||
monitor_event (event);
|
||||
}
|
||||
}
|
||||
|
||||
void zmq::socket_base_t::event_accepted (const char *addr_, int fd_)
|
||||
void zmq::socket_base_t::event_accepted (std::string &addr_, int fd_)
|
||||
{
|
||||
zmq_event_t event;
|
||||
if (!(monitor_events & ZMQ_EVENT_ACCEPTED)) return;
|
||||
event.event = ZMQ_EVENT_ACCEPTED;
|
||||
event.data.connected.addr = (char *)addr_;
|
||||
event.data.accepted.fd = fd_;
|
||||
monitor_event (event);
|
||||
if (monitor_events & ZMQ_EVENT_ACCEPTED) {
|
||||
zmq_event_t event;
|
||||
event.event = ZMQ_EVENT_ACCEPTED;
|
||||
event.data.accepted.addr = (char *) malloc (addr_.size () + 1);
|
||||
copy_monitor_address (event.data.accepted.addr, addr_);
|
||||
event.data.accepted.fd = fd_;
|
||||
monitor_event (event);
|
||||
}
|
||||
}
|
||||
|
||||
void zmq::socket_base_t::event_accept_failed (const char *addr_, int err_)
|
||||
void zmq::socket_base_t::event_accept_failed (std::string &addr_, int err_)
|
||||
{
|
||||
zmq_event_t event;
|
||||
if (!(monitor_events & ZMQ_EVENT_ACCEPT_FAILED)) return;
|
||||
event.event = ZMQ_EVENT_ACCEPT_FAILED;
|
||||
event.data.connected.addr = (char *)addr_;
|
||||
event.data.accept_failed.err= err_;
|
||||
monitor_event (event);
|
||||
if (monitor_events & ZMQ_EVENT_ACCEPT_FAILED) {
|
||||
zmq_event_t event;
|
||||
event.event = ZMQ_EVENT_ACCEPT_FAILED;
|
||||
event.data.accept_failed.addr = (char *) malloc (addr_.size () + 1);
|
||||
copy_monitor_address (event.data.accept_failed.addr, addr_);
|
||||
event.data.accept_failed.err= err_;
|
||||
monitor_event (event);
|
||||
}
|
||||
}
|
||||
|
||||
void zmq::socket_base_t::event_closed (const char *addr_, int fd_)
|
||||
void zmq::socket_base_t::event_closed (std::string &addr_, int fd_)
|
||||
{
|
||||
zmq_event_t event;
|
||||
if (!(monitor_events & ZMQ_EVENT_CLOSED)) return;
|
||||
event.event = ZMQ_EVENT_CLOSED;
|
||||
event.data.connected.addr = (char *)addr_;
|
||||
event.data.closed.fd = fd_;
|
||||
monitor_event (event);
|
||||
}
|
||||
|
||||
void zmq::socket_base_t::event_close_failed (const char *addr_, int err_)
|
||||
{
|
||||
zmq_event_t event;
|
||||
if (!(monitor_events & ZMQ_EVENT_CLOSE_FAILED)) return;
|
||||
event.event = ZMQ_EVENT_CLOSE_FAILED;
|
||||
event.data.connected.addr = (char *)addr_;
|
||||
event.data.close_failed.err = err_;
|
||||
monitor_event (event);
|
||||
if (monitor_events & ZMQ_EVENT_CLOSED) {
|
||||
zmq_event_t event;
|
||||
event.event = ZMQ_EVENT_CLOSED;
|
||||
event.data.closed.addr = (char *) malloc (addr_.size () + 1);
|
||||
copy_monitor_address (event.data.closed.addr, addr_);
|
||||
event.data.closed.fd = fd_;
|
||||
monitor_event (event);
|
||||
}
|
||||
}
|
||||
|
||||
void zmq::socket_base_t::event_disconnected (const char *addr_, int fd_)
|
||||
void zmq::socket_base_t::event_close_failed (std::string &addr_, int err_)
|
||||
{
|
||||
zmq_event_t event;
|
||||
if (!(monitor_events & ZMQ_EVENT_DISCONNECTED)) return;
|
||||
event.event = ZMQ_EVENT_DISCONNECTED;
|
||||
event.data.connected.addr = (char *)addr_;
|
||||
event.data.disconnected.fd = fd_;
|
||||
monitor_event (event);
|
||||
if (monitor_events & ZMQ_EVENT_CLOSE_FAILED) {
|
||||
zmq_event_t event;
|
||||
event.event = ZMQ_EVENT_CLOSE_FAILED;
|
||||
event.data.close_failed.addr = (char *) malloc (addr_.size () + 1);
|
||||
copy_monitor_address (event.data.close_failed.addr, addr_);
|
||||
event.data.close_failed.err = err_;
|
||||
monitor_event (event);
|
||||
}
|
||||
}
|
||||
|
||||
void zmq::socket_base_t::event_disconnected (std::string &addr_, int fd_)
|
||||
{
|
||||
if (monitor_events & ZMQ_EVENT_DISCONNECTED) {
|
||||
zmq_event_t event;
|
||||
event.event = ZMQ_EVENT_DISCONNECTED;
|
||||
event.data.disconnected.addr = (char *) malloc (addr_.size () + 1);
|
||||
copy_monitor_address (event.data.disconnected.addr, addr_);
|
||||
event.data.disconnected.fd = fd_;
|
||||
monitor_event (event);
|
||||
}
|
||||
}
|
||||
|
||||
void zmq::socket_base_t::copy_monitor_address (char *dest_, std::string &src_)
|
||||
{
|
||||
alloc_assert (dest_);
|
||||
dest_[src_.size ()] = 0;
|
||||
memcpy (dest_, src_.c_str (), src_.size ());
|
||||
}
|
||||
|
||||
void zmq::socket_base_t::monitor_event (zmq_event_t event_)
|
||||
{
|
||||
zmq_msg_t msg;
|
||||
if (!monitor_socket) return;
|
||||
zmq_msg_init_size (&msg, sizeof (event_));
|
||||
memcpy (zmq_msg_data (&msg), &event_, sizeof (event_));
|
||||
zmq_sendmsg (monitor_socket, &msg, 0);
|
||||
zmq_msg_close (&msg);
|
||||
if (monitor_socket) {
|
||||
zmq_msg_t msg;
|
||||
void *event_data = malloc (sizeof (event_));
|
||||
alloc_assert (event_data);
|
||||
memcpy (event_data, &event_, sizeof (event_));
|
||||
zmq_msg_init_data (&msg, event_data, sizeof (event_), zmq_free_event, NULL);
|
||||
zmq_sendmsg (monitor_socket, &msg, 0);
|
||||
zmq_msg_close (&msg);
|
||||
}
|
||||
}
|
||||
|
||||
void zmq::socket_base_t::stop_monitor()
|
||||
@ -1168,4 +1233,4 @@ void zmq::socket_base_t::stop_monitor()
|
||||
monitor_socket = NULL;
|
||||
monitor_events = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,11 @@
|
||||
#include "clock.hpp"
|
||||
#include "pipe.hpp"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void zmq_free_event (void *data, void *hint);
|
||||
}
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
|
||||
@ -104,16 +109,16 @@ namespace zmq
|
||||
|
||||
int monitor(const char *endpoint_, int events_);
|
||||
|
||||
void event_connected(const char *addr_, int fd_);
|
||||
void event_connect_delayed(const char *addr_, int err_);
|
||||
void event_connect_retried(const char *addr_, int interval_);
|
||||
void event_listening(const char *addr_, int fd_);
|
||||
void event_bind_failed(const char *addr_, int err_);
|
||||
void event_accepted(const char *addr_, int fd_);
|
||||
void event_accept_failed(const char *addr_, int err_);
|
||||
void event_closed(const char *addr_, int fd_);
|
||||
void event_close_failed(const char *addr_, int fd_);
|
||||
void event_disconnected(const char *addr_, int fd_);
|
||||
void event_connected (std::string &addr_, int fd_);
|
||||
void event_connect_delayed (std::string &addr_, int err_);
|
||||
void event_connect_retried (std::string &addr_, int interval_);
|
||||
void event_listening (std::string &addr_, int fd_);
|
||||
void event_bind_failed (std::string &addr_, int err_);
|
||||
void event_accepted (std::string &addr_, int fd_);
|
||||
void event_accept_failed (std::string &addr_, int err_);
|
||||
void event_closed (std::string &addr_, int fd_);
|
||||
void event_close_failed (std::string &addr_, int fd_);
|
||||
void event_disconnected (std::string &addr_, int fd_);
|
||||
|
||||
protected:
|
||||
|
||||
@ -151,6 +156,9 @@ namespace zmq
|
||||
// Socket event data dispath
|
||||
void monitor_event (zmq_event_t data_);
|
||||
|
||||
// Copy monitor specific event endpoints to event messages
|
||||
void copy_monitor_address (char *dest_, std::string &src_);
|
||||
|
||||
// Monitor socket cleanup
|
||||
void stop_monitor ();
|
||||
|
||||
@ -162,6 +170,10 @@ namespace zmq
|
||||
typedef std::multimap <std::string, own_t *> endpoints_t;
|
||||
endpoints_t endpoints;
|
||||
|
||||
// Map of open inproc endpoints.
|
||||
typedef std::multimap <std::string, pipe_t *> inprocs_t;
|
||||
inprocs_t inprocs;
|
||||
|
||||
// To be called after processing commands or invoking any command
|
||||
// handlers explicitly. If required, it will deallocate the socket.
|
||||
void check_destroy ();
|
||||
@ -240,3 +252,4 @@ namespace zmq
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -50,10 +50,10 @@
|
||||
|
||||
zmq::stream_engine_t::stream_engine_t (fd_t fd_, const options_t &options_, const std::string &endpoint_) :
|
||||
s (fd_),
|
||||
io_enabled (false),
|
||||
inpos (NULL),
|
||||
insize (0),
|
||||
decoder (NULL),
|
||||
input_error (false),
|
||||
outpos (NULL),
|
||||
outsize (0),
|
||||
encoder (NULL),
|
||||
@ -132,6 +132,7 @@ void zmq::stream_engine_t::plug (io_thread_t *io_thread_,
|
||||
// Connect to I/O threads poller object.
|
||||
io_object_t::plug (io_thread_);
|
||||
handle = add_fd (s);
|
||||
io_enabled = true;
|
||||
|
||||
// Send the 'length' and 'flags' fields of the identity message.
|
||||
// The 'length' field is encoded in the long format.
|
||||
@ -153,7 +154,10 @@ void zmq::stream_engine_t::unplug ()
|
||||
plugged = false;
|
||||
|
||||
// Cancel all fd subscriptions.
|
||||
rm_fd (handle);
|
||||
if (io_enabled) {
|
||||
rm_fd (handle);
|
||||
io_enabled = false;
|
||||
}
|
||||
|
||||
// Disconnect from I/O threads poller object.
|
||||
io_object_t::unplug ();
|
||||
@ -225,9 +229,10 @@ void zmq::stream_engine_t::in_event ()
|
||||
// waiting for input events and postpone the termination
|
||||
// until after the session has accepted the message.
|
||||
if (disconnection) {
|
||||
input_error = true;
|
||||
if (decoder->stalled ())
|
||||
reset_pollin (handle);
|
||||
if (decoder->stalled ()) {
|
||||
rm_fd (handle);
|
||||
io_enabled = false;
|
||||
}
|
||||
else
|
||||
error ();
|
||||
}
|
||||
@ -238,8 +243,15 @@ void zmq::stream_engine_t::out_event ()
|
||||
// If write buffer is empty, try to read new data from the encoder.
|
||||
if (!outsize) {
|
||||
|
||||
// Even when we stop polling as soon as there is no
|
||||
// data to send, the poller may invoke out_event one
|
||||
// more time due to 'speculative write' optimisation.
|
||||
if (unlikely (encoder == NULL)) {
|
||||
zmq_assert (handshaking);
|
||||
return;
|
||||
}
|
||||
|
||||
outpos = NULL;
|
||||
zmq_assert (encoder);
|
||||
encoder->get_data (&outpos, &outsize);
|
||||
|
||||
// If there is no data to send, stop polling for output.
|
||||
@ -287,7 +299,7 @@ void zmq::stream_engine_t::activate_out ()
|
||||
|
||||
void zmq::stream_engine_t::activate_in ()
|
||||
{
|
||||
if (input_error) {
|
||||
if (unlikely (!io_enabled)) {
|
||||
// There was an input error but the engine could not
|
||||
// be terminated (due to the stalled decoder).
|
||||
// Flush the pending message and terminate the engine now.
|
||||
@ -447,7 +459,7 @@ int zmq::stream_engine_t::push_msg (msg_t *msg_)
|
||||
void zmq::stream_engine_t::error ()
|
||||
{
|
||||
zmq_assert (session);
|
||||
socket->event_disconnected (endpoint.c_str(), s);
|
||||
socket->event_disconnected (endpoint, s);
|
||||
session->detach ();
|
||||
unplug ();
|
||||
delete this;
|
||||
|
@ -96,12 +96,14 @@ namespace zmq
|
||||
// Preamble (10 bytes) + version (1 byte) + socket type (1 byte).
|
||||
const static size_t greeting_size = 12;
|
||||
|
||||
// True iff we are registered with an I/O poller.
|
||||
bool io_enabled;
|
||||
|
||||
handle_t handle;
|
||||
|
||||
unsigned char *inpos;
|
||||
size_t insize;
|
||||
i_decoder *decoder;
|
||||
bool input_error;
|
||||
|
||||
unsigned char *outpos;
|
||||
size_t outsize;
|
||||
|
@ -136,7 +136,7 @@ void zmq::tcp_connecter_t::out_event ()
|
||||
// Shut the connecter down.
|
||||
terminate ();
|
||||
|
||||
socket->event_connected (endpoint.c_str(), fd);
|
||||
socket->event_connected (endpoint, fd);
|
||||
}
|
||||
|
||||
void zmq::tcp_connecter_t::timer_event (int id_)
|
||||
@ -159,11 +159,12 @@ void zmq::tcp_connecter_t::start_connecting ()
|
||||
}
|
||||
|
||||
// Connection establishment may be delayed. Poll for its completion.
|
||||
else if (rc == -1 && errno == EINPROGRESS) {
|
||||
else
|
||||
if (rc == -1 && errno == EINPROGRESS) {
|
||||
handle = add_fd (s);
|
||||
handle_valid = true;
|
||||
set_pollout (handle);
|
||||
socket->event_connect_delayed (endpoint.c_str(), zmq_errno());
|
||||
socket->event_connect_delayed (endpoint, zmq_errno());
|
||||
}
|
||||
|
||||
// Handle any other error condition by eventual reconnect.
|
||||
@ -178,7 +179,7 @@ void zmq::tcp_connecter_t::add_reconnect_timer()
|
||||
{
|
||||
int rc_ivl = get_new_reconnect_ivl();
|
||||
add_timer (rc_ivl, reconnect_timer_id);
|
||||
socket->event_connect_retried (endpoint.c_str(), rc_ivl);
|
||||
socket->event_connect_retried (endpoint, rc_ivl);
|
||||
timer_started = true;
|
||||
}
|
||||
|
||||
@ -252,7 +253,7 @@ int zmq::tcp_connecter_t::open ()
|
||||
|
||||
zmq::fd_t zmq::tcp_connecter_t::connect ()
|
||||
{
|
||||
// Async connect have finished. Check whether an error occured.
|
||||
// Async connect has finished. Check whether an error occurred
|
||||
int err = 0;
|
||||
#if defined ZMQ_HAVE_HPUX
|
||||
int len = sizeof (err);
|
||||
@ -267,9 +268,13 @@ zmq::fd_t zmq::tcp_connecter_t::connect ()
|
||||
#ifdef ZMQ_HAVE_WINDOWS
|
||||
zmq_assert (rc == 0);
|
||||
if (err != 0) {
|
||||
if (err == WSAECONNREFUSED || err == WSAETIMEDOUT ||
|
||||
err == WSAECONNABORTED || err == WSAEHOSTUNREACH ||
|
||||
err == WSAENETUNREACH || err == WSAENETDOWN)
|
||||
if (err == WSAECONNREFUSED ||
|
||||
err == WSAETIMEDOUT ||
|
||||
err == WSAECONNABORTED ||
|
||||
err == WSAEHOSTUNREACH ||
|
||||
err == WSAENETUNREACH ||
|
||||
err == WSAENETDOWN ||
|
||||
err == WSAEINVAL)
|
||||
return retired_fd;
|
||||
wsa_assert_no (err);
|
||||
}
|
||||
@ -281,9 +286,14 @@ zmq::fd_t zmq::tcp_connecter_t::connect ()
|
||||
err = errno;
|
||||
if (err != 0) {
|
||||
errno = err;
|
||||
errno_assert (errno == ECONNREFUSED || errno == ECONNRESET ||
|
||||
errno == ETIMEDOUT || errno == EHOSTUNREACH ||
|
||||
errno == ENETUNREACH || errno == ENETDOWN);
|
||||
errno_assert (
|
||||
errno == ECONNREFUSED ||
|
||||
errno == ECONNRESET ||
|
||||
errno == ETIMEDOUT ||
|
||||
errno == EHOSTUNREACH ||
|
||||
errno == ENETUNREACH ||
|
||||
errno == ENETDOWN ||
|
||||
errno == EINVAL);
|
||||
return retired_fd;
|
||||
}
|
||||
#endif
|
||||
@ -304,6 +314,6 @@ void zmq::tcp_connecter_t::close ()
|
||||
int rc = ::close (s);
|
||||
errno_assert (rc == 0);
|
||||
#endif
|
||||
socket->event_closed (endpoint.c_str(), s);
|
||||
socket->event_closed (endpoint, s);
|
||||
s = retired_fd;
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ void zmq::tcp_listener_t::in_event ()
|
||||
// If connection was reset by the peer in the meantime, just ignore it.
|
||||
// TODO: Handle specific errors like ENFILE/EMFILE etc.
|
||||
if (fd == retired_fd) {
|
||||
socket->event_accept_failed (endpoint.c_str(), zmq_errno());
|
||||
socket->event_accept_failed (endpoint, zmq_errno());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -108,7 +108,7 @@ void zmq::tcp_listener_t::in_event ()
|
||||
session->inc_seqnum ();
|
||||
launch_child (session);
|
||||
send_attach (session, engine, false);
|
||||
socket->event_accepted (endpoint.c_str(), fd);
|
||||
socket->event_accepted (endpoint, fd);
|
||||
}
|
||||
|
||||
void zmq::tcp_listener_t::close ()
|
||||
@ -121,7 +121,7 @@ void zmq::tcp_listener_t::close ()
|
||||
int rc = ::close (s);
|
||||
errno_assert (rc == 0);
|
||||
#endif
|
||||
socket->event_closed (endpoint.c_str(), s);
|
||||
socket->event_closed (endpoint, s);
|
||||
s = retired_fd;
|
||||
}
|
||||
|
||||
@ -223,7 +223,7 @@ int zmq::tcp_listener_t::set_address (const char *addr_)
|
||||
goto error;
|
||||
#endif
|
||||
|
||||
socket->event_listening (endpoint.c_str(), s);
|
||||
socket->event_listening (endpoint, s);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
|
@ -58,11 +58,6 @@ void zmq::v1_decoder_t::set_msg_sink (i_msg_sink *msg_sink_)
|
||||
msg_sink = msg_sink_;
|
||||
}
|
||||
|
||||
bool zmq::v1_decoder_t::stalled () const
|
||||
{
|
||||
return next == &v1_decoder_t::message_ready;
|
||||
}
|
||||
|
||||
bool zmq::v1_decoder_t::flags_ready ()
|
||||
{
|
||||
msg_flags = 0;
|
||||
|
@ -44,8 +44,6 @@ namespace zmq
|
||||
// i_decoder interface.
|
||||
virtual void set_msg_sink (i_msg_sink *msg_sink_);
|
||||
|
||||
virtual bool stalled () const;
|
||||
|
||||
private:
|
||||
|
||||
bool flags_ready ();
|
||||
|
@ -29,8 +29,6 @@
|
||||
namespace zmq
|
||||
{
|
||||
|
||||
class i_msg_source;
|
||||
|
||||
// Encoder for 0MQ framing protocol. Converts messages into data stream.
|
||||
|
||||
class v1_encoder_t : public encoder_base_t <v1_encoder_t>
|
||||
|
@ -70,8 +70,8 @@ void zmq::xpub_t::xread_activated (pipe_t *pipe_)
|
||||
unique = subscriptions.add (data + 1, size - 1, pipe_);
|
||||
|
||||
// If the subscription is not a duplicate store it so that it can be
|
||||
// passed to used on next recv call.
|
||||
if (options.type == ZMQ_XPUB && (unique || verbose))
|
||||
// passed to used on next recv call. (Unsubscribe is not verbose.)
|
||||
if (options.type == ZMQ_XPUB && (unique || (*data && verbose)))
|
||||
pending.push_back (blob_t (data, size));
|
||||
}
|
||||
|
||||
|
@ -95,8 +95,12 @@ int zmq::xsub_t::xsend (msg_t *msg_, int flags_)
|
||||
|
||||
// Process the subscription.
|
||||
if (*data == 1) {
|
||||
if (subscriptions.add (data + 1, size - 1))
|
||||
return dist.send_to_all (msg_, flags_);
|
||||
// this used to filter out duplicate subscriptions,
|
||||
// however this is alread done on the XPUB side and
|
||||
// doing it here as well breaks ZMQ_XPUB_VERBOSE
|
||||
// when there are forwarding devices involved
|
||||
subscriptions.add (data + 1, size - 1);
|
||||
return dist.send_to_all (msg_, flags_);
|
||||
}
|
||||
else {
|
||||
if (subscriptions.rm (data + 1, size - 1))
|
||||
|
63
src/zmq.cpp
63
src/zmq.cpp
@ -674,15 +674,15 @@ int zmq_poll (zmq_pollitem_t *items_, int nitems_, long timeout_)
|
||||
int nevents = 0;
|
||||
|
||||
while (true) {
|
||||
|
||||
// Compute the timeout for the subsequent poll.
|
||||
int timeout;
|
||||
if (first_pass)
|
||||
timeout = 0;
|
||||
else if (timeout_ < 0)
|
||||
timeout = -1;
|
||||
else
|
||||
timeout = end - now;
|
||||
// Compute the timeout for the subsequent poll.
|
||||
int timeout;
|
||||
if (first_pass)
|
||||
timeout = 0;
|
||||
else
|
||||
if (timeout_ < 0)
|
||||
timeout = -1;
|
||||
else
|
||||
timeout = end - now;
|
||||
|
||||
// Wait for events.
|
||||
while (true) {
|
||||
@ -694,7 +694,6 @@ int zmq_poll (zmq_pollitem_t *items_, int nitems_, long timeout_)
|
||||
errno_assert (rc >= 0);
|
||||
break;
|
||||
}
|
||||
|
||||
// Check for the events.
|
||||
for (int i = 0; i != nitems_; i++) {
|
||||
|
||||
@ -848,7 +847,8 @@ int zmq_poll (zmq_pollitem_t *items_, int nitems_, long timeout_)
|
||||
timeout.tv_usec = 0;
|
||||
ptimeout = &timeout;
|
||||
}
|
||||
else if (timeout_ < 0)
|
||||
else
|
||||
if (timeout_ < 0)
|
||||
ptimeout = NULL;
|
||||
else {
|
||||
timeout.tv_sec = (long) ((end - now) / 1000);
|
||||
@ -987,6 +987,47 @@ int zmq_device (int type, void *frontend_, void *backend_)
|
||||
(zmq::socket_base_t*) backend_, NULL);
|
||||
}
|
||||
|
||||
// Callback to free socket event data
|
||||
|
||||
void zmq_free_event (void *event_data, void *hint)
|
||||
{
|
||||
zmq_event_t *event = (zmq_event_t *) event_data;
|
||||
|
||||
switch (event->event) {
|
||||
case ZMQ_EVENT_CONNECTED:
|
||||
free (event->data.connected.addr);
|
||||
break;
|
||||
case ZMQ_EVENT_CONNECT_DELAYED:
|
||||
free (event->data.connect_delayed.addr);
|
||||
break;
|
||||
case ZMQ_EVENT_CONNECT_RETRIED:
|
||||
free (event->data.connect_retried.addr);
|
||||
break;
|
||||
case ZMQ_EVENT_LISTENING:
|
||||
free (event->data.listening.addr);
|
||||
break;
|
||||
case ZMQ_EVENT_BIND_FAILED:
|
||||
free (event->data.bind_failed.addr);
|
||||
break;
|
||||
case ZMQ_EVENT_ACCEPTED:
|
||||
free (event->data.accepted.addr);
|
||||
break;
|
||||
case ZMQ_EVENT_ACCEPT_FAILED:
|
||||
free (event->data.accept_failed.addr);
|
||||
break;
|
||||
case ZMQ_EVENT_CLOSED:
|
||||
free (event->data.closed.addr);
|
||||
break;
|
||||
case ZMQ_EVENT_CLOSE_FAILED:
|
||||
free (event->data.close_failed.addr);
|
||||
break;
|
||||
case ZMQ_EVENT_DISCONNECTED:
|
||||
free (event->data.disconnected.addr);
|
||||
break;
|
||||
}
|
||||
free (event_data);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 0MQ utils - to be used by perf tests
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -17,7 +17,9 @@ noinst_PROGRAMS = test_pair_inproc \
|
||||
test_last_endpoint \
|
||||
test_term_endpoint \
|
||||
test_monitor \
|
||||
test_router_mandatory
|
||||
test_router_mandatory \
|
||||
test_disconnect_inproc
|
||||
|
||||
|
||||
if !ON_MINGW
|
||||
noinst_PROGRAMS += test_shutdown_stress \
|
||||
@ -40,6 +42,7 @@ test_connect_delay_SOURCES = test_connect_delay.cpp
|
||||
test_last_endpoint_SOURCES = test_last_endpoint.cpp
|
||||
test_term_endpoint_SOURCES = test_term_endpoint.cpp
|
||||
test_monitor_SOURCES = test_monitor.cpp
|
||||
test_disconnect_inproc_SOURCES = test_disconnect_inproc.cpp
|
||||
test_router_mandatory_SOURCES = test_router_mandatory.cpp
|
||||
|
||||
if !ON_MINGW
|
||||
|
@ -1,21 +1,20 @@
|
||||
/*
|
||||
Copyright (c) 2012 Ian Barber
|
||||
Copyright (c) 2012 Other contributors as noted in the AUTHORS file
|
||||
Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of 0MQ.
|
||||
|
||||
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 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.
|
||||
|
||||
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/>.
|
||||
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 "../include/zmq.h"
|
||||
@ -24,131 +23,32 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include <pthread.h>
|
||||
|
||||
#undef NDEBUG
|
||||
#include <assert.h>
|
||||
|
||||
static void *server (void *)
|
||||
{
|
||||
void *socket, *context;
|
||||
char buffer[16];
|
||||
int rc, val;
|
||||
|
||||
context = zmq_init (1);
|
||||
assert (context);
|
||||
|
||||
socket = zmq_socket (context, ZMQ_PULL);
|
||||
assert (socket);
|
||||
|
||||
val = 0;
|
||||
rc = zmq_setsockopt(socket, ZMQ_LINGER, &val, sizeof(val));
|
||||
assert (rc == 0);
|
||||
|
||||
rc = zmq_bind (socket, "ipc:///tmp/recon");
|
||||
assert (rc == 0);
|
||||
|
||||
memset (&buffer, 0, sizeof(buffer));
|
||||
rc = zmq_recv (socket, &buffer, sizeof(buffer), 0);
|
||||
|
||||
// Intentionally bail out
|
||||
rc = zmq_close (socket);
|
||||
assert (rc == 0);
|
||||
|
||||
rc = zmq_term (context);
|
||||
assert (rc == 0);
|
||||
|
||||
usleep (200000);
|
||||
|
||||
context = zmq_init (1);
|
||||
assert (context);
|
||||
|
||||
socket = zmq_socket (context, ZMQ_PULL);
|
||||
assert (socket);
|
||||
|
||||
val = 0;
|
||||
rc = zmq_setsockopt(socket, ZMQ_LINGER, &val, sizeof(val));
|
||||
assert (rc == 0);
|
||||
|
||||
rc = zmq_bind (socket, "ipc:///tmp/recon");
|
||||
assert (rc == 0);
|
||||
|
||||
usleep (200000);
|
||||
|
||||
memset (&buffer, 0, sizeof(buffer));
|
||||
rc = zmq_recv (socket, &buffer, sizeof(buffer), ZMQ_DONTWAIT);
|
||||
assert (rc != -1);
|
||||
|
||||
// Start closing the socket while the connecting process is underway.
|
||||
rc = zmq_close (socket);
|
||||
assert (rc == 0);
|
||||
|
||||
rc = zmq_term (context);
|
||||
assert (rc == 0);
|
||||
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
static void *worker (void *)
|
||||
{
|
||||
void *socket, *context;
|
||||
int rc, hadone, val;
|
||||
|
||||
context = zmq_init (1);
|
||||
assert (context);
|
||||
|
||||
socket = zmq_socket (context, ZMQ_PUSH);
|
||||
assert (socket);
|
||||
|
||||
val = 0;
|
||||
rc = zmq_setsockopt(socket, ZMQ_LINGER, &val, sizeof(val));
|
||||
assert (rc == 0);
|
||||
|
||||
val = 1;
|
||||
rc = zmq_setsockopt (socket, ZMQ_DELAY_ATTACH_ON_CONNECT, &val, sizeof(val));
|
||||
assert (rc == 0);
|
||||
|
||||
rc = zmq_connect (socket, "ipc:///tmp/recon");
|
||||
assert (rc == 0);
|
||||
|
||||
hadone = 0;
|
||||
// Not checking RC as some may be -1
|
||||
for (int i = 0; i < 6; i++) {
|
||||
usleep(200000);
|
||||
rc = zmq_send (socket, "hi", 2, ZMQ_DONTWAIT);
|
||||
if (rc != -1)
|
||||
hadone ++;
|
||||
}
|
||||
|
||||
assert (hadone >= 2);
|
||||
assert (hadone < 4);
|
||||
|
||||
rc = zmq_close (socket);
|
||||
assert (rc == 0);
|
||||
|
||||
rc = zmq_term (context);
|
||||
assert (rc == 0);
|
||||
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
fprintf (stderr, "test_connect_delay running...\n");
|
||||
int val;
|
||||
int rc;
|
||||
char buffer[16];
|
||||
int seen = 0;
|
||||
|
||||
// TEST 1.
|
||||
// First we're going to attempt to send messages to two
|
||||
// pipes, one connected, the other not. We should see
|
||||
// the PUSH load balancing to both pipes, and hence half
|
||||
// of the messages getting queued, as connect() creates a
|
||||
// pipe immediately.
|
||||
|
||||
void *context = zmq_ctx_new();
|
||||
assert (context);
|
||||
void *to = zmq_socket(context, ZMQ_PULL);
|
||||
assert (to);
|
||||
|
||||
// Bind the one valid receiver
|
||||
val = 0;
|
||||
rc = zmq_setsockopt(to, ZMQ_LINGER, &val, sizeof(val));
|
||||
assert (rc == 0);
|
||||
rc = zmq_bind(to, "tcp://*:5555");
|
||||
rc = zmq_bind (to, "tcp://127.0.0.1:6555");
|
||||
assert (rc == 0);
|
||||
|
||||
// Create a socket pushing to two endpoints - only 1 message should arrive.
|
||||
@ -156,28 +56,32 @@ int main (void)
|
||||
assert(from);
|
||||
|
||||
val = 0;
|
||||
zmq_setsockopt (from, ZMQ_LINGER, &val, sizeof(val));
|
||||
rc = zmq_connect (from, "tcp://localhost:5556");
|
||||
zmq_setsockopt (from, ZMQ_LINGER, &val, sizeof (val));
|
||||
// This pipe will not connect
|
||||
rc = zmq_connect (from, "tcp://127.0.0.1:5556");
|
||||
assert (rc == 0);
|
||||
rc = zmq_connect (from, "tcp://localhost:5555");
|
||||
// This pipe will
|
||||
rc = zmq_connect (from, "tcp://127.0.0.1:6555");
|
||||
assert (rc == 0);
|
||||
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
std::string message("message ");
|
||||
message += ('0' + i);
|
||||
rc = zmq_send (from, message.data(), message.size(), 0);
|
||||
assert(rc >= 0);
|
||||
// We send 10 messages, 5 should just get stuck in the queue
|
||||
// for the not-yet-connected pipe
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
rc = zmq_send (from, "Hello", 5, 0);
|
||||
assert (rc == 5);
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
seen = 0;
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
memset (&buffer, 0, sizeof(buffer));
|
||||
rc = zmq_recv (to, &buffer, sizeof(buffer), ZMQ_DONTWAIT);
|
||||
if( rc == -1)
|
||||
break;
|
||||
// We now consume from the connected pipe
|
||||
// - we should see just 5
|
||||
int timeout = 100;
|
||||
rc = zmq_setsockopt (to, ZMQ_RCVTIMEO, &timeout, sizeof (int));
|
||||
assert (rc == 0);
|
||||
|
||||
int seen = 0;
|
||||
while (true) {
|
||||
rc = zmq_recv (to, &buffer, sizeof (buffer), 0);
|
||||
if (rc == -1)
|
||||
break; // Break when we didn't get a message
|
||||
seen++;
|
||||
}
|
||||
assert (seen == 5);
|
||||
@ -188,15 +92,22 @@ int main (void)
|
||||
rc = zmq_close (to);
|
||||
assert (rc == 0);
|
||||
|
||||
rc = zmq_ctx_destroy(context);
|
||||
rc = zmq_term (context);
|
||||
assert (rc == 0);
|
||||
|
||||
// TEST 2
|
||||
// This time we will do the same thing, connect two pipes,
|
||||
// one of which will succeed in connecting to a bound
|
||||
// receiver, the other of which will fail. However, we will
|
||||
// also set the delay attach on connect flag, which should
|
||||
// cause the pipe attachment to be delayed until the connection
|
||||
// succeeds.
|
||||
context = zmq_ctx_new();
|
||||
fprintf (stderr, " Rerunning with DELAY_ATTACH_ON_CONNECT\n");
|
||||
|
||||
// Bind the valid socket
|
||||
to = zmq_socket (context, ZMQ_PULL);
|
||||
assert (to);
|
||||
rc = zmq_bind (to, "tcp://*:5560");
|
||||
rc = zmq_bind (to, "tcp://127.0.0.1:5560");
|
||||
assert (rc == 0);
|
||||
|
||||
val = 0;
|
||||
@ -211,33 +122,34 @@ int main (void)
|
||||
rc = zmq_setsockopt (from, ZMQ_LINGER, &val, sizeof(val));
|
||||
assert (rc == 0);
|
||||
|
||||
// Set the key flag
|
||||
val = 1;
|
||||
rc = zmq_setsockopt (from, ZMQ_DELAY_ATTACH_ON_CONNECT, &val, sizeof(val));
|
||||
assert (rc == 0);
|
||||
|
||||
rc = zmq_connect (from, "tcp://localhost:5561");
|
||||
// Connect to the invalid socket
|
||||
rc = zmq_connect (from, "tcp://127.0.0.1:5561");
|
||||
assert (rc == 0);
|
||||
// Connect to the valid socket
|
||||
rc = zmq_connect (from, "tcp://127.0.0.1:5560");
|
||||
assert (rc == 0);
|
||||
|
||||
rc = zmq_connect (from, "tcp://localhost:5560");
|
||||
assert (rc == 0);
|
||||
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
std::string message("message ");
|
||||
message += ('0' + i);
|
||||
rc = zmq_send (from, message.data(), message.size(), 0);
|
||||
assert (rc >= 0);
|
||||
// Send 10 messages, all should be routed to the connected pipe
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
rc = zmq_send (from, "Hello", 5, 0);
|
||||
assert (rc == 5);
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
|
||||
rc = zmq_setsockopt (to, ZMQ_RCVTIMEO, &timeout, sizeof (int));
|
||||
assert (rc == 0);
|
||||
|
||||
seen = 0;
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
memset(&buffer, 0, sizeof(buffer));
|
||||
rc = zmq_recv (to, &buffer, sizeof(buffer), ZMQ_DONTWAIT);
|
||||
assert (rc != -1);
|
||||
while (true) {
|
||||
rc = zmq_recv (to, &buffer, sizeof (buffer), 0);
|
||||
if (rc == -1)
|
||||
break; // Break when we didn't get a message
|
||||
seen++;
|
||||
}
|
||||
assert (seen == 10);
|
||||
|
||||
rc = zmq_close (from);
|
||||
assert (rc == 0);
|
||||
@ -245,18 +157,82 @@ int main (void)
|
||||
rc = zmq_close (to);
|
||||
assert (rc == 0);
|
||||
|
||||
rc = zmq_ctx_destroy(context);
|
||||
rc = zmq_term (context);
|
||||
assert (rc == 0);
|
||||
|
||||
fprintf (stderr, " Running DELAY_ATTACH_ON_CONNECT with disconnect\n");
|
||||
// TEST 3
|
||||
// This time we want to validate that the same blocking behaviour
|
||||
// occurs with an existing connection that is broken. We will send
|
||||
// messages to a connected pipe, disconnect and verify the messages
|
||||
// block. Then we reconnect and verify messages flow again.
|
||||
context = zmq_ctx_new ();
|
||||
|
||||
pthread_t serv, work;
|
||||
|
||||
rc = pthread_create (&serv, NULL, server, NULL);
|
||||
void *backend = zmq_socket (context, ZMQ_DEALER);
|
||||
assert (backend);
|
||||
void *frontend = zmq_socket (context, ZMQ_DEALER);
|
||||
assert (frontend);
|
||||
int zero = 0;
|
||||
rc = zmq_setsockopt (backend, ZMQ_LINGER, &zero, sizeof (zero));
|
||||
assert (rc == 0);
|
||||
rc = zmq_setsockopt (frontend, ZMQ_LINGER, &zero, sizeof (zero));
|
||||
assert (rc == 0);
|
||||
|
||||
rc = pthread_create (&work, NULL, worker, NULL);
|
||||
// Frontend connects to backend using DELAY_ATTACH_ON_CONNECT
|
||||
int on = 1;
|
||||
rc = zmq_setsockopt (frontend, ZMQ_DELAY_ATTACH_ON_CONNECT, &on, sizeof (on));
|
||||
assert (rc == 0);
|
||||
rc = zmq_bind (backend, "tcp://127.0.0.1:5560");
|
||||
assert (rc == 0);
|
||||
rc = zmq_connect (frontend, "tcp://127.0.0.1:5560");
|
||||
assert (rc == 0);
|
||||
|
||||
// Ping backend to frontend so we know when the connection is up
|
||||
rc = zmq_send (backend, "Hello", 5, 0);
|
||||
assert (rc == 5);
|
||||
rc = zmq_recv (frontend, buffer, 255, 0);
|
||||
assert (rc == 5);
|
||||
|
||||
// Send message from frontend to backend
|
||||
rc = zmq_send (frontend, "Hello", 5, ZMQ_DONTWAIT);
|
||||
assert (rc == 5);
|
||||
|
||||
rc = zmq_close (backend);
|
||||
assert (rc == 0);
|
||||
|
||||
pthread_exit(NULL);
|
||||
// Give time to process disconnect
|
||||
// There's no way to do this except with a sleep
|
||||
struct timespec t = { 0, 250 * 1000000 };
|
||||
nanosleep (&t, NULL);
|
||||
|
||||
// Send a message, should fail
|
||||
rc = zmq_send (frontend, "Hello", 5, ZMQ_DONTWAIT);
|
||||
assert (rc == -1);
|
||||
|
||||
// Recreate backend socket
|
||||
backend = zmq_socket (context, ZMQ_DEALER);
|
||||
assert (backend);
|
||||
rc = zmq_setsockopt (backend, ZMQ_LINGER, &zero, sizeof (zero));
|
||||
assert (rc == 0);
|
||||
rc = zmq_bind (backend, "tcp://127.0.0.1:5560");
|
||||
assert (rc == 0);
|
||||
|
||||
// Ping backend to frontend so we know when the connection is up
|
||||
rc = zmq_send (backend, "Hello", 5, 0);
|
||||
assert (rc == 5);
|
||||
rc = zmq_recv (frontend, buffer, 255, 0);
|
||||
assert (rc == 5);
|
||||
|
||||
// After the reconnect, should succeed
|
||||
rc = zmq_send (frontend, "Hello", 5, ZMQ_DONTWAIT);
|
||||
assert (rc == 5);
|
||||
|
||||
rc = zmq_close (backend);
|
||||
assert (rc == 0);
|
||||
|
||||
rc = zmq_close (frontend);
|
||||
assert (rc == 0);
|
||||
|
||||
rc = zmq_term (context);
|
||||
assert (rc == 0);
|
||||
}
|
||||
|
||||
|
113
tests/test_disconnect_inproc.cpp
Normal file
113
tests/test_disconnect_inproc.cpp
Normal file
@ -0,0 +1,113 @@
|
||||
#include <zmq.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
/// Initialize a zeromq message with a given null-terminated string
|
||||
#define ZMQ_PREPARE_STRING(msg, data, size) \
|
||||
zmq_msg_init(&msg) && printf("zmq_msg_init: %s\n", zmq_strerror(errno)); \
|
||||
zmq_msg_init_size (&msg, size + 1) && printf("zmq_msg_init_size: %s\n",zmq_strerror(errno)); \
|
||||
memcpy(zmq_msg_data(&msg), data, size + 1);
|
||||
|
||||
int publicationsReceived = 0;
|
||||
bool isSubscribed = false;
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
void* context = zmq_ctx_new();
|
||||
void* pubSocket;
|
||||
void* subSocket;
|
||||
|
||||
(pubSocket = zmq_socket(context, ZMQ_XPUB)) || printf("zmq_socket: %s\n", zmq_strerror(errno));
|
||||
(subSocket = zmq_socket(context, ZMQ_SUB)) || printf("zmq_socket: %s\n", zmq_strerror(errno));
|
||||
zmq_setsockopt(subSocket, ZMQ_SUBSCRIBE, "foo", 3) && printf("zmq_setsockopt: %s\n",zmq_strerror(errno));
|
||||
|
||||
zmq_bind(pubSocket, "inproc://someInProcDescriptor") && printf("zmq_bind: %s\n", zmq_strerror(errno));
|
||||
//zmq_bind(pubSocket, "tcp://127.0.0.1:30010") && printf("zmq_bind: %s\n", zmq_strerror(errno));
|
||||
|
||||
int32_t more;
|
||||
size_t more_size = sizeof(more);
|
||||
int iteration = 0;
|
||||
|
||||
while(1) {
|
||||
zmq_pollitem_t items [] = {
|
||||
{ subSocket, 0, ZMQ_POLLIN, 0 }, // read publications
|
||||
{ pubSocket, 0, ZMQ_POLLIN, 0 }, // read subscriptions
|
||||
};
|
||||
zmq_poll(items, 2, 500);
|
||||
|
||||
if (items[1].revents & ZMQ_POLLIN) {
|
||||
while (1) {
|
||||
zmq_msg_t msg;
|
||||
zmq_msg_init (&msg);
|
||||
zmq_msg_recv (&msg, pubSocket, 0);
|
||||
char* buffer = (char*)zmq_msg_data(&msg);
|
||||
|
||||
if (buffer[0] == 0) {
|
||||
assert(isSubscribed);
|
||||
isSubscribed = false;
|
||||
}
|
||||
else {
|
||||
assert(!isSubscribed);
|
||||
isSubscribed = true;
|
||||
}
|
||||
|
||||
zmq_getsockopt (pubSocket, ZMQ_RCVMORE, &more, &more_size);
|
||||
zmq_msg_close (&msg);
|
||||
|
||||
if (!more)
|
||||
break; // Last message part
|
||||
}
|
||||
}
|
||||
|
||||
if (items[0].revents & ZMQ_POLLIN) {
|
||||
while (1) {
|
||||
zmq_msg_t msg;
|
||||
zmq_msg_init (&msg);
|
||||
zmq_msg_recv (&msg, subSocket, 0);
|
||||
zmq_getsockopt (subSocket, ZMQ_RCVMORE, &more, &more_size);
|
||||
zmq_msg_close (&msg);
|
||||
|
||||
if (!more) {
|
||||
publicationsReceived++;
|
||||
break; // Last message part
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (iteration == 1) {
|
||||
zmq_connect(subSocket, "inproc://someInProcDescriptor") && printf("zmq_connect: %s\n", zmq_strerror(errno));
|
||||
//zmq_connect(subSocket, "tcp://127.0.0.1:30010") && printf("zmq_connect: %s\n", zmq_strerror(errno));
|
||||
}
|
||||
|
||||
if (iteration == 4) {
|
||||
zmq_disconnect(subSocket, "inproc://someInProcDescriptor") && printf("zmq_disconnect(%d): %s\n", errno, zmq_strerror(errno));
|
||||
//zmq_disconnect(subSocket, "tcp://127.0.0.1:30010") && printf("zmq_disconnect: %s\n", zmq_strerror(errno));
|
||||
}
|
||||
|
||||
if (iteration == 10) {
|
||||
break;
|
||||
}
|
||||
|
||||
zmq_msg_t channelEnvlp;
|
||||
ZMQ_PREPARE_STRING(channelEnvlp, "foo", 3);
|
||||
zmq_sendmsg(pubSocket, &channelEnvlp, ZMQ_SNDMORE) >= 0 || printf("zmq_sendmsg: %s\n",zmq_strerror(errno));
|
||||
zmq_msg_close(&channelEnvlp) && printf("zmq_msg_close: %s\n",zmq_strerror(errno));
|
||||
|
||||
zmq_msg_t message;
|
||||
ZMQ_PREPARE_STRING(message, "this is foo!", 12);
|
||||
zmq_sendmsg(pubSocket, &message, 0) >= 0 || printf("zmq_sendmsg: %s\n",zmq_strerror(errno));
|
||||
zmq_msg_close(&message) && printf("zmq_msg_close: %s\n",zmq_strerror(errno));
|
||||
|
||||
iteration++;
|
||||
}
|
||||
|
||||
assert(publicationsReceived == 3);
|
||||
assert(!isSubscribed);
|
||||
|
||||
zmq_close(pubSocket) && printf("zmq_close: %s", zmq_strerror(errno));
|
||||
zmq_close(subSocket) && printf("zmq_close: %s", zmq_strerror(errno));
|
||||
|
||||
zmq_ctx_destroy(context);
|
||||
return 0;
|
||||
}
|
||||
|
@ -29,11 +29,10 @@ static void do_bind_and_verify (void *s, const char *endpoint)
|
||||
{
|
||||
int rc = zmq_bind (s, endpoint);
|
||||
assert (rc == 0);
|
||||
|
||||
char test [255];
|
||||
size_t siz = 255;
|
||||
rc = zmq_getsockopt (s, ZMQ_LAST_ENDPOINT, test, &siz);
|
||||
assert (rc == 0 && strcmp (test, endpoint) == 0);
|
||||
char reported [255];
|
||||
size_t size = 255;
|
||||
rc = zmq_getsockopt (s, ZMQ_LAST_ENDPOINT, reported, &size);
|
||||
assert (rc == 0 && strcmp (reported, endpoint) == 0);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
@ -49,6 +48,12 @@ int main (void)
|
||||
do_bind_and_verify (sb, "tcp://127.0.0.1:5561");
|
||||
do_bind_and_verify (sb, "ipc:///tmp/testep");
|
||||
|
||||
return 0 ;
|
||||
int rc = zmq_close (sb);
|
||||
assert (rc == 0);
|
||||
|
||||
rc = zmq_term (ctx);
|
||||
assert (rc == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ int main (void)
|
||||
|
||||
// Send a message and check that it fails
|
||||
rc = zmq_send (sa, "UNKNOWN", 7, ZMQ_SNDMORE | ZMQ_DONTWAIT);
|
||||
assert (rc == -1 && errno == EAGAIN);
|
||||
assert (rc == -1 && errno == EHOSTUNREACH);
|
||||
|
||||
rc = zmq_close (sa);
|
||||
assert (rc == 0);
|
||||
|
Loading…
x
Reference in New Issue
Block a user