1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-08 00:37:15 +01:00

Update ZMQ to current git.

This commit is contained in:
Sandu Liviu Catalin 2021-08-22 20:09:16 +03:00
parent b78b3e8ede
commit fa4644d00f
72 changed files with 1309 additions and 884 deletions

View File

@ -75,7 +75,7 @@ endif()
option(ENABLE_UBSAN "Build with undefined behavior sanitizer" OFF) option(ENABLE_UBSAN "Build with undefined behavior sanitizer" OFF)
if(ENABLE_UBSAN) if(ENABLE_UBSAN)
message(STATUS "Instrumenting with Undefined Behavior Sanitizer") message(STATUS "Instrumenting with Undefined Behavior Sanitizer")
set(CMAKE_BUILD_TYPE "RelWithDebInfo") set(CMAKE_BUILD_TYPE "Debug")
set(UBSAN_FLAGS "${UBSAN_FLAGS} -fno-omit-frame-pointer") set(UBSAN_FLAGS "${UBSAN_FLAGS} -fno-omit-frame-pointer")
set(UBSAN_FLAGS "${UBSAN_FLAGS} -fsanitize=undefined") set(UBSAN_FLAGS "${UBSAN_FLAGS} -fsanitize=undefined")
set(UBSAN_FLAGS "${UBSAN_FLAGS} -fsanitize=implicit-conversion") set(UBSAN_FLAGS "${UBSAN_FLAGS} -fsanitize=implicit-conversion")
@ -118,15 +118,15 @@ endif()
if (NOT MSVC) if (NOT MSVC)
if(NOT CMAKE_CXX_FLAGS MATCHES "-std=") if(NOT CMAKE_CXX_FLAGS MATCHES "-std=")
# use C++11 by default if supported # use C++11 by default if supported
check_cxx_compiler_flag("-std=gnu++11" COMPILER_SUPPORTS_CXX11) check_cxx_compiler_flag("-std=c++11" COMPILER_SUPPORTS_CXX11)
if(COMPILER_SUPPORTS_CXX11) if(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
endif() endif()
endif() endif()
if(NOT CMAKE_C_FLAGS MATCHES "-std=") if(NOT CMAKE_C_FLAGS MATCHES "-std=")
check_c_compiler_flag("-std=gnu11" COMPILER_SUPPORTS_C11) check_c_compiler_flag("-std=c11" COMPILER_SUPPORTS_C11)
if(COMPILER_SUPPORTS_C11) if(COMPILER_SUPPORTS_C11)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu11") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11")
else() else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99")
endif() endif()
@ -156,19 +156,19 @@ if(APPLE)
endif() endif()
if(EXISTS "${CMAKE_SOURCE_DIR}/.git") if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
message(STATUS "Build and install draft classes and methods")
option(ENABLE_DRAFTS "Build and install draft classes and methods" ON) option(ENABLE_DRAFTS "Build and install draft classes and methods" ON)
else() else()
message(STATUS "Not building draft classes and methods")
option(ENABLE_DRAFTS "Build and install draft classes and methods" OFF) option(ENABLE_DRAFTS "Build and install draft classes and methods" OFF)
endif() endif()
# Enable WebSocket transport and RadixTree # Enable WebSocket transport and RadixTree
if(ENABLE_DRAFTS) if(ENABLE_DRAFTS)
message(STATUS "Building draft classes and methods")
set(ZMQ_BUILD_DRAFT_API 1) set(ZMQ_BUILD_DRAFT_API 1)
option(ENABLE_WS "Enable WebSocket transport" ON) option(ENABLE_WS "Enable WebSocket transport" ON)
option(ENABLE_RADIX_TREE "Use radix tree implementation to manage subscriptions" ON) option(ENABLE_RADIX_TREE "Use radix tree implementation to manage subscriptions" ON)
else() else()
message(STATUS "Not building draft classes and methods")
option(ENABLE_WS "Enable WebSocket transport" OFF) option(ENABLE_WS "Enable WebSocket transport" OFF)
option(ENABLE_RADIX_TREE "Use radix tree implementation to manage subscriptions" OFF) option(ENABLE_RADIX_TREE "Use radix tree implementation to manage subscriptions" OFF)
endif() endif()
@ -263,15 +263,11 @@ endif()
option(WITH_LIBSODIUM "Use libsodium instead of built-in tweetnacl" ON) option(WITH_LIBSODIUM "Use libsodium instead of built-in tweetnacl" ON)
option(WITH_LIBSODIUM_STATIC "Use static libsodium library" OFF) option(WITH_LIBSODIUM_STATIC "Use static libsodium library" OFF)
option(ENABLE_LIBSODIUM_RANDOMBYTES_CLOSE "Automatically close libsodium randombytes. Not threadsafe without getrandom()" ON)
option(ENABLE_CURVE "Enable CURVE security" ON) option(ENABLE_CURVE "Enable CURVE security" ON)
if(ENABLE_CURVE) if(ENABLE_CURVE)
if(WITH_LIBSODIUM) if(WITH_LIBSODIUM)
# The package name passed to `find_package_handle_standard_args` (sodium)
# does not match the name of the calling package (Sodium). This can lead to
# problems in calling code that expects `find_package` result variables
# (e.g., `_FOUND`) to follow a certain pattern.
#find_package("Sodium")
find_package("sodium") find_package("sodium")
if(SODIUM_FOUND) if(SODIUM_FOUND)
message(STATUS "Using libsodium for CURVE security") message(STATUS "Using libsodium for CURVE security")
@ -281,6 +277,9 @@ if(ENABLE_CURVE)
endif() endif()
set(ZMQ_USE_LIBSODIUM 1) set(ZMQ_USE_LIBSODIUM 1)
set(ZMQ_HAVE_CURVE 1) set(ZMQ_HAVE_CURVE 1)
if (ENABLE_LIBSODIUM_RANDOMBYTES_CLOSE)
set(ZMQ_LIBSODIUM_RANDOMBYTES_CLOSE 1)
endif()
else() else()
message( message(
WARNING WARNING
@ -474,6 +473,7 @@ message(STATUS "Using polling method in zmq_poll(er)_* API: ${API_POLLER}")
string(TOUPPER ${API_POLLER} UPPER_API_POLLER) string(TOUPPER ${API_POLLER} UPPER_API_POLLER)
set(ZMQ_POLL_BASED_ON_${UPPER_API_POLLER} 1) set(ZMQ_POLL_BASED_ON_${UPPER_API_POLLER} 1)
# special alignment settings
execute_process( execute_process(
COMMAND getconf LEVEL1_DCACHE_LINESIZE COMMAND getconf LEVEL1_DCACHE_LINESIZE
OUTPUT_VARIABLE CACHELINE_SIZE OUTPUT_VARIABLE CACHELINE_SIZE
@ -486,6 +486,7 @@ else()
set(ZMQ_CACHELINE_SIZE ${CACHELINE_SIZE}) set(ZMQ_CACHELINE_SIZE ${CACHELINE_SIZE})
endif() endif()
message(STATUS "Using ${ZMQ_CACHELINE_SIZE} bytes alignment for lock-free data structures") message(STATUS "Using ${ZMQ_CACHELINE_SIZE} bytes alignment for lock-free data structures")
check_cxx_symbol_exists(posix_memalign stdlib.h HAVE_POSIX_MEMALIGN)
if(NOT CYGWIN) if(NOT CYGWIN)
# TODO cannot we simply do 'if(WIN32) set(ZMQ_HAVE_WINDOWS ON)' or similar? # TODO cannot we simply do 'if(WIN32) set(ZMQ_HAVE_WINDOWS ON)' or similar?
@ -565,6 +566,7 @@ else()
check_cxx_symbol_exists(if_nametoindex net/if.h HAVE_IF_NAMETOINDEX) check_cxx_symbol_exists(if_nametoindex net/if.h HAVE_IF_NAMETOINDEX)
check_cxx_symbol_exists(SO_PEERCRED sys/socket.h ZMQ_HAVE_SO_PEERCRED) check_cxx_symbol_exists(SO_PEERCRED sys/socket.h ZMQ_HAVE_SO_PEERCRED)
check_cxx_symbol_exists(LOCAL_PEERCRED sys/socket.h ZMQ_HAVE_LOCAL_PEERCRED) check_cxx_symbol_exists(LOCAL_PEERCRED sys/socket.h ZMQ_HAVE_LOCAL_PEERCRED)
check_cxx_symbol_exists(SO_BUSY_POLL sys/socket.h ZMQ_HAVE_BUSY_POLL)
endif() endif()
if(NOT MINGW) if(NOT MINGW)
@ -1375,7 +1377,7 @@ else()
add_library(libzmq SHARED $<TARGET_OBJECTS:objects> ${public_headers} ${html-docs} ${readme-docs} add_library(libzmq SHARED $<TARGET_OBJECTS:objects> ${public_headers} ${html-docs} ${readme-docs}
${zmq-pkgconfig} ${CMAKE_CURRENT_BINARY_DIR}/version.rc) ${zmq-pkgconfig} ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
endif() endif()
endif() endif()
# NOTE: the SOVERSION and VERSION MUST be the same as the one generated by libtool! It is NOT the same as the # NOTE: the SOVERSION and VERSION MUST be the same as the one generated by libtool! It is NOT the same as the
# version of the package. # version of the package.

View File

@ -1024,19 +1024,19 @@ endif
endif endif
if HAVE_VMCI if HAVE_VMCI
test_apps += test_pair_vmci test_reqrep_vmci test_apps += tests/test_pair_vmci tests/test_reqrep_vmci
test_pair_vmci_SOURCES = tests/test_pair_vmci.cpp tests_test_pair_vmci_SOURCES = tests/test_pair_vmci.cpp
test_pair_vmci_LDADD = ${TESTUTIL_LIBS} src/libzmq.la tests_test_pair_vmci_LDADD = ${TESTUTIL_LIBS} src/libzmq.la
test_pair_vmci_CPPFLAGS = ${TESTUTIL_CPPFLAGS} tests_test_pair_vmci_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
test_pair_vmci_LDFLAGS = @LIBZMQ_VMCI_LDFLAGS@ tests_test_pair_vmci_LDFLAGS = @LIBZMQ_VMCI_LDFLAGS@
test_pair_vmci_CXXFLAGS = @LIBZMQ_VMCI_CXXFLAGS@ tests_test_pair_vmci_CXXFLAGS = @LIBZMQ_VMCI_CXXFLAGS@
test_reqrep_vmci_SOURCES = tests/test_reqrep_vmci.cpp tests_test_reqrep_vmci_SOURCES = tests/test_reqrep_vmci.cpp
test_reqrep_vmci_LDADD = ${TESTUTIL_LIBS} src/libzmq.la tests_test_reqrep_vmci_LDADD = ${TESTUTIL_LIBS} src/libzmq.la
test_reqrep_vmci_CPPFLAGS = ${TESTUTIL_CPPFLAGS} tests_test_reqrep_vmci_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
test_reqrep_vmci_LDFLAGS = @LIBZMQ_VMCI_LDFLAGS@ tests_test_reqrep_vmci_LDFLAGS = @LIBZMQ_VMCI_LDFLAGS@
test_reqrep_vmci_CXXFLAGS = @LIBZMQ_VMCI_CXXFLAGS@ tests_test_reqrep_vmci_CXXFLAGS = @LIBZMQ_VMCI_CXXFLAGS@
endif endif
@ -1056,7 +1056,8 @@ test_apps += tests/test_poller \
tests/test_msg_init \ tests/test_msg_init \
tests/test_hello_msg \ tests/test_hello_msg \
tests/test_disconnect_msg \ tests/test_disconnect_msg \
tests/test_channel tests/test_channel \
tests/test_hiccup_msg
tests_test_poller_SOURCES = tests/test_poller.cpp tests_test_poller_SOURCES = tests/test_poller.cpp
tests_test_poller_LDADD = ${TESTUTIL_LIBS} src/libzmq.la tests_test_poller_LDADD = ${TESTUTIL_LIBS} src/libzmq.la
@ -1121,6 +1122,10 @@ tests_test_disconnect_msg_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_channel_SOURCES = tests/test_channel.cpp tests_test_channel_SOURCES = tests/test_channel.cpp
tests_test_channel_LDADD = ${TESTUTIL_LIBS} src/libzmq.la tests_test_channel_LDADD = ${TESTUTIL_LIBS} src/libzmq.la
tests_test_channel_CPPFLAGS = ${TESTUTIL_CPPFLAGS} tests_test_channel_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_hiccup_msg_SOURCES = tests/test_hiccup_msg.cpp
tests_test_hiccup_msg_LDADD = ${TESTUTIL_LIBS} src/libzmq.la
tests_test_hiccup_msg_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
endif endif
if FUZZING_ENGINE_LIB if FUZZING_ENGINE_LIB

View File

@ -1,6 +1,6 @@
# ZeroMQ # ZeroMQ
[![Build Status](https://travis-ci.org/zeromq/libzmq.png?branch=master)](https://travis-ci.org/zeromq/libzmq) [![Build Status](https://travis-ci.com/zeromq/libzmq.svg?branch=master)](https://travis-ci.com/zeromq/libzmq)
[![Build status](https://ci.appveyor.com/api/projects/status/e2ks424yrs1un3wt?svg=true)](https://ci.appveyor.com/project/zeromq/libzmq) [![Build status](https://ci.appveyor.com/api/projects/status/e2ks424yrs1un3wt?svg=true)](https://ci.appveyor.com/project/zeromq/libzmq)
[![Coverage Status](https://coveralls.io/repos/github/zeromq/libzmq/badge.svg?branch=master)](https://coveralls.io/github/zeromq/libzmq?branch=master) [![Coverage Status](https://coveralls.io/repos/github/zeromq/libzmq/badge.svg?branch=master)](https://coveralls.io/github/zeromq/libzmq?branch=master)

View File

@ -0,0 +1,13 @@
# Permission to Relicense under MPLv2
This is a statement by the Netherlands eScience Center
that grants permission to relicense its copyrights in the libzmq C++
library (ZeroMQ) under the Mozilla Public License v2 (MPLv2).
A portion of the commits made by the Github handle "egpbos", with
commit author "E. G. Patrick Bos p.bos@esciencecenter.nl", are copyright of the Netherlands eScience Center.
This document hereby grants the libzmq project team to relicense libzmq,
including all past, present and future contributions of the author listed above.
Rob van Nieuwpoort <R.vanNieuwpoort@esciencecenter.nl>
2021/06/15

15
vendor/ZMQ/RELICENSE/christhrasher.md vendored Normal file
View File

@ -0,0 +1,15 @@
# Permission to Relicense under MPLv2 or any other OSI approved license chosen by the current ZeroMQ BDFL
This is a statement by Chris Thrasher that grants permission to relicense
its copyrights in the libzmq C++ library (ZeroMQ) under the Mozilla Public
License v2 (MPLv2) or any other Open Source Initiative approved license chosen
by the current ZeroMQ BDFL (Benevolent Dictator for Life).
A portion of the commits made by the Github handle "ChrisThrasher", with
commit author "Chris Thrasher <chris.j.thrasher@gmail.com>", are copyright of
Chris Thrasher. This document hereby grants the libzmq project team to
relicense libzmq, including all past, present and future contributions of the
author listed above.
Chris Thrasher
2021/07/01

13
vendor/ZMQ/RELICENSE/jlsantiago0.md vendored Normal file
View File

@ -0,0 +1,13 @@
Permission to Relicense under MPLv2
This is a statement by Jose L. Santiago
that grants permission to relicense its copyrights in the libzmq C++
library (ZeroMQ) under the Mozilla Public License v2 (MPLv2).
A portion of the commits made by the Github handle "jlsantiago0", with
commit author "Jose L. Santiago", are copyright of Jose L. Santiago.
This document hereby grants the libzmq project team to relicense libzmq,
including all past, present and future contributions of the author listed above.
Jose L. Santiago
2021/02/18

16
vendor/ZMQ/RELICENSE/sabotagebeats.md vendored Normal file
View File

@ -0,0 +1,16 @@
# Permission to Relicense under MPLv2 or any other OSI approved license chosen by the current ZeroMQ BDFL
This is a statement by sabotagebeats
that grants permission to relicense its copyrights in the libzmq C++
library (ZeroMQ) under the Mozilla Public License v2 (MPLv2) or any other
Open Source Initiative approved license chosen by the current ZeroMQ
BDFL (Benevolent Dictator for Life).
A portion of the commits made by the Github handle "sabotagebeats", with
commit author "sabotagebeats", are copyright of sabotagebeats .
This document hereby grants the libzmq project team to relicense libzmq,
including all past, present and future contributions of the author listed above.
sabotagebeats
2021/7/24

15
vendor/ZMQ/RELICENSE/saschavv.md vendored Normal file
View File

@ -0,0 +1,15 @@
# Permission to Relicense under MPLv2 or any other OSI approved license chosen by the current ZeroMQ BDFL
This is a statement by Sascha van Vliet
that grants permission to relicense its copyrights in the libzmq C++
library (ZeroMQ) under the Mozilla Public License v2 (MPLv2) or any other
Open Source Initiative approved license chosen by the current ZeroMQ
BDFL (Benevolent Dictator for Life).
A portion of the commits made by the Github handle "saschavv", with
commit author "Sascha van Vliet <saschavv@gmail.com>", are copyright of Sascha van Vliet.
This document hereby grants the libzmq project team to relicense libzmq,
including all past, present and future contributions of the author listed above.
Sascha van Vliet
2021/07/30

15
vendor/ZMQ/RELICENSE/yitzchak.md vendored Normal file
View File

@ -0,0 +1,15 @@
# Permission to Relicense under MPLv2 or any other OSI approved license chosen by the current ZeroMQ BDFL
This is a statement by Tarn W. Burton
that grants permission to relicense its copyrights in the libzmq C++
library (ZeroMQ) under the Mozilla Public License v2 (MPLv2) or any other
Open Source Initiative approved license chosen by the current ZeroMQ
BDFL (Benevolent Dictator for Life).
A portion of the commits made by the Github handle "yitzchak", with
commit author "Tarn W. Burton", are copyright of Tarn W. Burton.
This document hereby grants the libzmq project team to relicense libzmq,
including all past, present and future contributions of the author listed above.
Tarn W. Burton
2021/05/16

View File

@ -1212,6 +1212,11 @@ AC_DEFUN([LIBZMQ_CHECK_CACHELINE], [{
# the value the kernel knows on Linux # the value the kernel knows on Linux
zmq_cacheline_size=$(cat /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size 2>/dev/null || echo 64) zmq_cacheline_size=$(cat /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size 2>/dev/null || echo 64)
fi fi
fi
if test "x$zmq_cacheline_size" = "xundefined"; then
# On some platforms e.g. Fedora33 s390x the cacheline size reported
# by getconf as 'undefined'.
zmq_cacheline_size=64
fi fi
AC_MSG_NOTICE([Using "$zmq_cacheline_size" bytes alignment for lock-free data structures]) AC_MSG_NOTICE([Using "$zmq_cacheline_size" bytes alignment for lock-free data structures])
AC_DEFINE_UNQUOTED(ZMQ_CACHELINE_SIZE, $zmq_cacheline_size, [Using "$zmq_cacheline_size" bytes alignment for lock-free data structures]) AC_DEFINE_UNQUOTED(ZMQ_CACHELINE_SIZE, $zmq_cacheline_size, [Using "$zmq_cacheline_size" bytes alignment for lock-free data structures])

View File

@ -175,11 +175,15 @@ install:
- cmd: echo "Generator='%CMAKE_GENERATOR%'" - cmd: echo "Generator='%CMAKE_GENERATOR%'"
- cmd: echo "Platform='%Platform%'" - cmd: echo "Platform='%Platform%'"
- cmd: if "%WITH_LIBSODIUM%"=="ON" set LIBSODIUMDIR=C:\projects\libsodium - cmd: if "%WITH_LIBSODIUM%"=="ON" set LIBSODIUMDIR=C:\projects\libsodium
- cmd: if "%WITH_LIBSODIUM%"=="ON" (
git config --global user.email "test@appveyor.com" &&
git config --global user.name "appveyor"
)
- cmd: if "%WITH_LIBSODIUM%"=="ON" ( - cmd: if "%WITH_LIBSODIUM%"=="ON" (
if not exist "%LIBSODIUMDIR%" ( if not exist "%LIBSODIUMDIR%" (
git clone --branch stable --depth 1 --quiet "https://github.com/jedisct1/libsodium.git" %LIBSODIUMDIR% git clone --branch stable --depth 1 --quiet "https://github.com/jedisct1/libsodium.git" %LIBSODIUMDIR%
) else ( ) else (
git -C "%LIBSODIUMDIR%" pull git -C "%LIBSODIUMDIR%" fetch --all && git -C "%LIBSODIUMDIR%" reset --hard origin/stable
) )
) )
- cmd: if "%WITH_LIBSODIUM%"=="ON" msbuild /v:minimal /maxcpucount:%NUMBER_OF_PROCESSORS% /p:Configuration=%Configuration%DLL %LIBSODIUMDIR%\builds\msvc\%MSVCYEAR%\libsodium\libsodium.vcxproj - cmd: if "%WITH_LIBSODIUM%"=="ON" msbuild /v:minimal /maxcpucount:%NUMBER_OF_PROCESSORS% /p:Configuration=%Configuration%DLL %LIBSODIUMDIR%\builds\msvc\%MSVCYEAR%\libsodium\libsodium.vcxproj
@ -272,18 +276,18 @@ test_script:
- cmd: if "%APPVEYOR_REPO_TAG%"=="false" (ctest -C "%Configuration%" -V %TEST_OPTIONS%) - cmd: if "%APPVEYOR_REPO_TAG%"=="false" (ctest -C "%Configuration%" -V %TEST_OPTIONS%)
deploy: deploy:
- provider: BinTray - provider: GitHub
username: somdoron tag: $(APPVEYOR_REPO_TAG_NAME)
api_key: release: libzmq $(APPVEYOR_REPO_TAG_NAME)
secure: B4TC4GvUMbwX13Skh2Kvyc6SnqLkjNS9W0gtN2yxUC2Y4oQSCK2F4eRgtpMpCasg description: |
subject: zeromq Windows binaries for libzmq $(APPVEYOR_REPO_TAG_NAME), uploaded from appveyor.
repo: generic Edit after appveyor is done uploading.
package: libzmq auth_token:
publish: true secure: vmAeVtN2qiQgFBCB2I5FDDRtADQ7GUdR9NwAJJyakbiV5OHzLHExDcC/D9Oh5r67
override: true draft: true
version: ${ZMQ_VERSION} prerelease: false
on: force_update: true # adds files, clobbers release name and description
APPVEYOR_REPO_TAG: true
# the analysis build is repeated; apparently appveyor only uses the first section that matches some branch # the analysis build is repeated; apparently appveyor only uses the first section that matches some branch
for: for:

View File

@ -7,10 +7,10 @@ You need the Android Native Development Kit (NDK) installed. See
This project is tested against Android NDK version r21d. This project is tested against Android NDK version r21d.
If you installed version r21d all you have to do is to expose the NDK root If you installed version r21e all you have to do is to expose the NDK root
directory as environment variable, e.g: directory as environment variable, e.g:
export ANDROID_NDK_ROOT=$HOME/android-ndk-r21d export ANDROID_NDK_ROOT=$HOME/android-ndk-r21e
If you installed another version you have to expose the NDK root directory as If you installed another version you have to expose the NDK root directory as
well as the NDK version, e.g: well as the NDK version, e.g:

View File

@ -35,8 +35,8 @@ esac
# Set default values used in ci builds # Set default values used in ci builds
export NDK_VERSION=${NDK_VERSION:-android-ndk-r21d} export NDK_VERSION=${NDK_VERSION:-android-ndk-r21e}
# With NDK r21d, the minimum SDK version range is [16, 29]. # With NDK r21e, the minimum SDK version range is [16, 29].
# SDK version 21 is the minimum version for 64-bit builds. # SDK version 21 is the minimum version for 64-bit builds.
export MIN_SDK_VERSION=${MIN_SDK_VERSION:-21} export MIN_SDK_VERSION=${MIN_SDK_VERSION:-21}

View File

@ -1,6 +1,6 @@
#!/usr/bin/env bash #!/usr/bin/env bash
export NDK_VERSION=android-ndk-r21d export NDK_VERSION=android-ndk-r21e
export ANDROID_NDK_ROOT="/tmp/${NDK_VERSION}" export ANDROID_NDK_ROOT="/tmp/${NDK_VERSION}"
case $(uname | tr '[:upper:]' '[:lower:]') in case $(uname | tr '[:upper:]' '[:lower:]') in

View File

@ -16,6 +16,7 @@
#cmakedefine ZMQ_POLL_BASED_ON_SELECT #cmakedefine ZMQ_POLL_BASED_ON_SELECT
#cmakedefine ZMQ_POLL_BASED_ON_POLL #cmakedefine ZMQ_POLL_BASED_ON_POLL
#cmakedefine HAVE_POSIX_MEMALIGN @HAVE_POSIX_MEMALIGN@
#cmakedefine ZMQ_CACHELINE_SIZE @ZMQ_CACHELINE_SIZE@ #cmakedefine ZMQ_CACHELINE_SIZE @ZMQ_CACHELINE_SIZE@
#cmakedefine ZMQ_FORCE_MUTEXES #cmakedefine ZMQ_FORCE_MUTEXES
@ -35,6 +36,7 @@
#cmakedefine ZMQ_HAVE_SO_PEERCRED #cmakedefine ZMQ_HAVE_SO_PEERCRED
#cmakedefine ZMQ_HAVE_LOCAL_PEERCRED #cmakedefine ZMQ_HAVE_LOCAL_PEERCRED
#cmakedefine ZMQ_HAVE_BUSY_POLL
#cmakedefine ZMQ_HAVE_O_CLOEXEC #cmakedefine ZMQ_HAVE_O_CLOEXEC

View File

@ -84,7 +84,9 @@ do
--prefix=${BUILDARCHDIR} \ --prefix=${BUILDARCHDIR} \
--disable-shared \ --disable-shared \
--enable-static \ --enable-static \
--host=${HOST} --host=${HOST} \
--disable-perf \
--disable-curve-keygen
echo "Building ${LIBNAME} for ${ARCH}..." echo "Building ${LIBNAME} for ${ARCH}..."
cd ${LIBDIR} cd ${LIBDIR}

10
vendor/ZMQ/config.sh vendored
View File

@ -66,4 +66,14 @@ function set_config_opts() {
if [ -n "$FORCE_98" ] && [ "$FORCE_98" = "enabled" ]; then if [ -n "$FORCE_98" ] && [ "$FORCE_98" = "enabled" ]; then
CONFIG_OPTS+=("--enable-force-CXX98-compat=yes") CONFIG_OPTS+=("--enable-force-CXX98-compat=yes")
fi fi
if [ -n "$VMCI" ] && [ "$VMCI" = "enabled" ]; then
CONFIG_OPTS+=("--with-vmci=$PWD/vmci")
# VMWare headeers are not ISO C++ compliant
CONFIG_OPTS+=("--disable-pedantic")
git clone --depth 1 https://github.com/vmware/open-vm-tools.git
mkdir -p vmci
# Linux headers are redefined, so we can't just add -I to the whole dir
cp open-vm-tools/open-vm-tools/lib/include/vmci_* vmci/
fi
} }

View File

@ -65,7 +65,7 @@ ZMQ_ORIG_CXXFLAGS="${CXXFLAGS:-none}"
# Checks for programs. # Checks for programs.
AC_PROG_CC AC_PROG_CC
AX_CHECK_COMPILE_FLAG([-std=gnu11], [CFLAGS+=" -std=gnu11"], [AC_PROG_CC_C99]) AX_CHECK_COMPILE_FLAG([-std=c11], [CFLAGS+=" -std=c11"], [AC_PROG_CC_C99])
AC_PROG_CXX AC_PROG_CXX
AX_CODE_COVERAGE AX_CODE_COVERAGE
AM_PROG_CC_C_O AM_PROG_CC_C_O
@ -550,6 +550,20 @@ AS_IF([test "x$with_libsodium" = "xyes"], [
AC_ARG_ENABLE([curve], AC_ARG_ENABLE([curve],
[AS_HELP_STRING([--disable-curve], [disable CURVE security [default=no]])]) [AS_HELP_STRING([--disable-curve], [disable CURVE security [default=no]])])
AC_ARG_ENABLE(
[libsodium_randombytes_close],
[AS_HELP_STRING(
[--disable-libsodium_randombytes_close],
[Do not call libsodium randombytes_close() when terminating contexts.
If disabled, may leave one FD open on /dev/urandom
until randombytes_close() is called explicitly,
but fixes a crash when multiple contexts are used with CURVE.
Has no effect when getrandom() is available. [default=enabled]]
)],
[],
[enable_libsodium_randombytes_close=yes]
)
if test "x$enable_curve" = "xno"; then if test "x$enable_curve" = "xno"; then
curve_library="" curve_library=""
AC_MSG_NOTICE([CURVE security is disabled]) AC_MSG_NOTICE([CURVE security is disabled])
@ -558,6 +572,12 @@ elif test "x$with_libsodium" = "xyes"; then
AC_MSG_NOTICE([Using libsodium for CURVE security]) AC_MSG_NOTICE([Using libsodium for CURVE security])
AC_DEFINE(ZMQ_HAVE_CURVE, [1], [Using curve encryption]) AC_DEFINE(ZMQ_HAVE_CURVE, [1], [Using curve encryption])
AC_DEFINE(ZMQ_USE_LIBSODIUM, [1], [Using libsodium for curve encryption]) AC_DEFINE(ZMQ_USE_LIBSODIUM, [1], [Using libsodium for curve encryption])
if test "x$enable_libsodium_randombytes_close" = "xyes"; then
AC_DEFINE(ZMQ_LIBSODIUM_RANDOMBYTES_CLOSE, [1], [Automatically close libsodium randombytes. Not threadsafe without getrandom()])
else
AC_MSG_NOTICE([Disabling libsodium randombytes_close(). randombytes_close() may need to be called in applcation code.])
fi
curve_library="libsodium" curve_library="libsodium"
enable_curve="yes" enable_curve="yes"

View File

@ -25,7 +25,7 @@ array. The *zmq_pollitem_t* structure is defined as follows:
typedef struct typedef struct
{ {
void '*socket'; void '*socket';
int 'fd'; zmq_fd_t 'fd';
short 'events'; short 'events';
short 'revents'; short 'revents';
} zmq_pollitem_t; } zmq_pollitem_t;

View File

@ -87,6 +87,21 @@ Default value:: not set
Applicable socket types:: all, when using TCP or UDP transports. Applicable socket types:: all, when using TCP or UDP transports.
ZMQ_BUSY_POLL: This removes delays caused by the interrupt and the resultant context switch.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Busy polling helps reduce latency in the network receive path by allowing socket layer code
to poll the receive queue of a network device, and disabling network interrupts. This removes
delays caused by the interrupt and the resultant context switch. However, it also increases
CPU utilization. Busy polling also prevents the CPU from sleeping, which can incur additional
power consumption.
[horizontal]
Option value type:: int
Option value unit:: 0,1
Default value:: 0
Applicable socket types:: all
ZMQ_CONNECT_RID: Assign the next outbound connection id ZMQ_CONNECT_RID: Assign the next outbound connection id
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This option name is now deprecated. Use ZMQ_CONNECT_ROUTING_ID instead. This option name is now deprecated. Use ZMQ_CONNECT_ROUTING_ID instead.
@ -241,6 +256,21 @@ Option value unit:: N/A
Default value:: NULL Default value:: NULL
Applicable socket types:: ZMQ_ROUTER, ZMQ_SERVER and ZMQ_PEER Applicable socket types:: ZMQ_ROUTER, ZMQ_SERVER and ZMQ_PEER
ZMQ_HICCUP_MSG: set a hiccup message that the socket will generate when connected peer temporarly disconnect
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When set, the socket will generate a hiccup message when connect peer has been disconnected.
You may set this on DEALER, CLIENT and PEER sockets.
The combination with ZMQ_HEARTBEAT_IVL is powerful and simplify protocols, when heartbeat recognize a connection drop it
will generate a hiccup message that can match the protocol of the application.
[horizontal]
Option value type:: binary data
Option value unit:: N/A
Default value:: NULL
Applicable socket types:: ZMQ_DEALER, ZMQ_CLIENT and ZMQ_PEER
ZMQ_GSSAPI_PLAINTEXT: Disable GSSAPI encryption ZMQ_GSSAPI_PLAINTEXT: Disable GSSAPI encryption
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Defines whether communications on the socket will be encrypted, see Defines whether communications on the socket will be encrypted, see

View File

@ -1,7 +1,7 @@
wepoll - epoll for Windows wepoll - epoll for Windows
https://github.com/piscisaureus/wepoll https://github.com/piscisaureus/wepoll
Copyright 2012-2018, Bert Belder <bertbelder@gmail.com> Copyright 2012-2020, Bert Belder <bertbelder@gmail.com>
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without

View File

@ -1 +1 @@
https://github.com/piscisaureus/wepoll/tree/v1.5.4 https://github.com/piscisaureus/wepoll/tree/v1.5.8

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
* wepoll - epoll for Windows * wepoll - epoll for Windows
* https://github.com/piscisaureus/wepoll * https://github.com/piscisaureus/wepoll
* *
* Copyright 2012-2018, Bert Belder <bertbelder@gmail.com> * Copyright 2012-2020, Bert Belder <bertbelder@gmail.com>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -38,8 +38,6 @@
#include <stdint.h> #include <stdint.h>
/* clang-format off */
enum EPOLL_EVENTS { enum EPOLL_EVENTS {
EPOLLIN = (int) (1U << 0), EPOLLIN = (int) (1U << 0),
EPOLLPRI = (int) (1U << 1), EPOLLPRI = (int) (1U << 1),
@ -72,8 +70,6 @@ enum EPOLL_EVENTS {
#define EPOLL_CTL_MOD 2 #define EPOLL_CTL_MOD 2
#define EPOLL_CTL_DEL 3 #define EPOLL_CTL_DEL 3
/* clang-format on */
typedef void* HANDLE; typedef void* HANDLE;
typedef uintptr_t SOCKET; typedef uintptr_t SOCKET;

View File

@ -57,21 +57,6 @@ extern "C" {
#endif #endif
#include <stddef.h> #include <stddef.h>
#include <stdio.h> #include <stdio.h>
#if defined _WIN32
// Set target version to Windows Server 2008, Windows Vista or higher.
// Windows XP (0x0501) is supported but without client & server socket types.
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0600
#endif
#ifdef __MINGW32__
// Require Windows XP or higher with MinGW for getaddrinfo().
#if (_WIN32_WINNT >= 0x0501)
#else
#error You need at least Windows XP target
#endif
#endif
#endif
/* Handle DSO symbol visibility */ /* Handle DSO symbol visibility */
#if defined _WIN32 #if defined _WIN32
@ -683,11 +668,13 @@ ZMQ_EXPORT void zmq_threadclose (void *thread_);
#define ZMQ_HELLO_MSG 110 #define ZMQ_HELLO_MSG 110
#define ZMQ_DISCONNECT_MSG 111 #define ZMQ_DISCONNECT_MSG 111
#define ZMQ_PRIORITY 112 #define ZMQ_PRIORITY 112
#define ZMQ_BUSY_POLL 113
#define ZMQ_HICCUP_MSG 114
/* DRAFT ZMQ_RECONNECT_STOP options */ /* DRAFT ZMQ_RECONNECT_STOP options */
#define ZMQ_RECONNECT_STOP_CONN_REFUSED 0x1 #define ZMQ_RECONNECT_STOP_CONN_REFUSED 0x1
#define ZMQ_RECONNECT_STOP_HANDSHAKE_FAILED 0x2 #define ZMQ_RECONNECT_STOP_HANDSHAKE_FAILED 0x2
#define ZMQ_RECONNECT_STOP_AFTER_DISCONNECT 0x3 #define ZMQ_RECONNECT_STOP_AFTER_DISCONNECT 0x4
/* DRAFT Context options */ /* DRAFT Context options */
#define ZMQ_ZERO_COPY_RECV 10 #define ZMQ_ZERO_COPY_RECV 10

View File

@ -13,8 +13,8 @@ Name: zeromq
Version: 4.3.5 Version: 4.3.5
Release: 1%{?dist} Release: 1%{?dist}
Summary: The ZeroMQ messaging library Summary: The ZeroMQ messaging library
Group: Applications/Internet Group: Development/Libraries/C and C++
License: LGPLv3+ License: LGPL-3.0-or-later
URL: http://www.zeromq.org/ URL: http://www.zeromq.org/
Source: http://download.zeromq.org/%{name}-%{version}.tar.gz Source: http://download.zeromq.org/%{name}-%{version}.tar.gz
Prefix: %{_prefix} Prefix: %{_prefix}
@ -228,11 +228,12 @@ autoreconf -fi
%{__make} %{?_smp_mflags} %{__make} %{?_smp_mflags}
%check
%{__make} check VERBOSE=1
%install %install
[ "%{buildroot}" != "/" ] && %{__rm} -rf %{buildroot} [ "%{buildroot}" != "/" ] && %{__rm} -rf %{buildroot}
# Install the package to build area # Install the package to build area
%{__make} check VERBOSE=1
%makeinstall %makeinstall
%post %post

View File

@ -38,6 +38,7 @@ zmq::client_t::client_t (class ctx_t *parent_, uint32_t tid_, int sid_) :
{ {
options.type = ZMQ_CLIENT; options.type = ZMQ_CLIENT;
options.can_send_hello_msg = true; options.can_send_hello_msg = true;
options.can_recv_hiccup_msg = true;
} }
zmq::client_t::~client_t () zmq::client_t::~client_t ()

View File

@ -126,9 +126,11 @@ static f_compatible_get_tick_count64 my_get_tick_count64 =
init_compatible_get_tick_count64 (); init_compatible_get_tick_count64 ();
#endif #endif
#ifndef ZMQ_HAVE_WINDOWS
const uint64_t usecs_per_msec = 1000; const uint64_t usecs_per_msec = 1000;
const uint64_t usecs_per_sec = 1000000;
const uint64_t nsecs_per_usec = 1000; const uint64_t nsecs_per_usec = 1000;
#endif
const uint64_t usecs_per_sec = 1000000;
zmq::clock_t::clock_t () : zmq::clock_t::clock_t () :
_last_tsc (rdtsc ()), _last_tsc (rdtsc ()),
@ -193,6 +195,7 @@ uint64_t zmq::clock_t::now_us ()
#else #else
LIBZMQ_UNUSED (nsecs_per_usec);
// Use POSIX gettimeofday function to get precise time. // Use POSIX gettimeofday function to get precise time.
struct timeval tv; struct timeval tv;
int rc = gettimeofday (&tv, NULL); int rc = gettimeofday (&tv, NULL);

View File

@ -33,6 +33,7 @@
#include <string> #include <string>
#include "stdint.hpp" #include "stdint.hpp"
#include "endpoint.hpp" #include "endpoint.hpp"
#include "platform.hpp"
namespace zmq namespace zmq
{ {
@ -44,12 +45,7 @@ class socket_base_t;
// This structure defines the commands that can be sent between threads. // This structure defines the commands that can be sent between threads.
#ifdef _MSC_VER struct command_t
#pragma warning(push)
#pragma warning(disable : 4324) // C4324: alignment padding warnings
__declspec(align (64))
#endif
struct command_t
{ {
// Object to process the command. // Object to process the command.
zmq::object_t *destination; zmq::object_t *destination;
@ -216,9 +212,12 @@ __declspec(align (64))
} args; } args;
#ifdef _MSC_VER #ifdef _MSC_VER
}; };
#pragma warning(pop)
#else #else
} __attribute__ ((aligned (64))); }
#ifdef HAVE_POSIX_MEMALIGN
__attribute__ ((aligned (ZMQ_CACHELINE_SIZE)))
#endif
;
#endif #endif
} }

View File

@ -180,6 +180,12 @@ struct curve_client_tools_t
// Create Box [C + vouch + metadata](C'->S') // Create Box [C + vouch + metadata](C'->S')
std::fill (initiate_plaintext.begin (), std::fill (initiate_plaintext.begin (),
initiate_plaintext.begin () + crypto_box_ZEROBYTES, 0); initiate_plaintext.begin () + crypto_box_ZEROBYTES, 0);
// False positives due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578
#if __GNUC__ >= 11
#pragma GCC diagnostic ignored "-Warray-bounds"
#pragma GCC diagnostic ignored "-Wstringop-overflow="
#endif
memcpy (&initiate_plaintext[crypto_box_ZEROBYTES], public_key_, 32); memcpy (&initiate_plaintext[crypto_box_ZEROBYTES], public_key_, 32);
memcpy (&initiate_plaintext[crypto_box_ZEROBYTES + 32], vouch_nonce + 8, memcpy (&initiate_plaintext[crypto_box_ZEROBYTES + 32], vouch_nonce + 8,
16); 16);
@ -189,6 +195,10 @@ struct curve_client_tools_t
memcpy (&initiate_plaintext[crypto_box_ZEROBYTES + 48 + 80], memcpy (&initiate_plaintext[crypto_box_ZEROBYTES + 48 + 80],
metadata_plaintext_, metadata_length_); metadata_plaintext_, metadata_length_);
} }
#if __GNUC__ >= 11
#pragma GCC diagnostic pop
#pragma GCC diagnostic pop
#endif
memcpy (initiate_nonce, "CurveZMQINITIATE", 16); memcpy (initiate_nonce, "CurveZMQINITIATE", 16);
put_uint64 (initiate_nonce + 16, cn_nonce_); put_uint64 (initiate_nonce + 16, cn_nonce_);

View File

@ -39,6 +39,7 @@ zmq::dealer_t::dealer_t (class ctx_t *parent_, uint32_t tid_, int sid_) :
{ {
options.type = ZMQ_DEALER; options.type = ZMQ_DEALER;
options.can_send_hello_msg = true; options.can_send_hello_msg = true;
options.can_recv_hiccup_msg = true;
} }
zmq::dealer_t::~dealer_t () zmq::dealer_t::~dealer_t ()

View File

@ -39,7 +39,6 @@
zmq::dgram_t::dgram_t (class ctx_t *parent_, uint32_t tid_, int sid_) : zmq::dgram_t::dgram_t (class ctx_t *parent_, uint32_t tid_, int sid_) :
socket_base_t (parent_, tid_, sid_), socket_base_t (parent_, tid_, sid_),
_pipe (NULL), _pipe (NULL),
_last_in (NULL),
_more_out (false) _more_out (false)
{ {
options.type = ZMQ_DGRAM; options.type = ZMQ_DGRAM;
@ -71,9 +70,6 @@ void zmq::dgram_t::xattach_pipe (pipe_t *pipe_,
void zmq::dgram_t::xpipe_terminated (pipe_t *pipe_) void zmq::dgram_t::xpipe_terminated (pipe_t *pipe_)
{ {
if (pipe_ == _pipe) { if (pipe_ == _pipe) {
if (_last_in == _pipe) {
_last_in = NULL;
}
_pipe = NULL; _pipe = NULL;
} }
} }
@ -147,7 +143,6 @@ int zmq::dgram_t::xrecv (msg_t *msg_)
errno = EAGAIN; errno = EAGAIN;
return -1; return -1;
} }
_last_in = _pipe;
return 0; return 0;
} }

View File

@ -62,8 +62,6 @@ class dgram_t ZMQ_FINAL : public socket_base_t
private: private:
zmq::pipe_t *_pipe; zmq::pipe_t *_pipe;
zmq::pipe_t *_last_in;
// If true, more outgoing message parts are expected. // If true, more outgoing message parts are expected.
bool _more_out; bool _more_out;

View File

@ -64,6 +64,18 @@ void zmq::dist_t::attach (pipe_t *pipe_)
} }
} }
bool zmq::dist_t::has_pipe (pipe_t *pipe_)
{
std::size_t claimed_index = _pipes.index (pipe_);
// If pipe claims to be outside the available index space it can't be in the distributor.
if (claimed_index >= _pipes.size ()) {
return false;
}
return _pipes[claimed_index] == pipe_;
}
void zmq::dist_t::match (pipe_t *pipe_) void zmq::dist_t::match (pipe_t *pipe_)
{ {
// If pipe is already matching do nothing. // If pipe is already matching do nothing.

View File

@ -51,6 +51,9 @@ class dist_t
// Adds the pipe to the distributor object. // Adds the pipe to the distributor object.
void attach (zmq::pipe_t *pipe_); void attach (zmq::pipe_t *pipe_);
// Checks if this pipe is present in the distributor.
bool has_pipe (zmq::pipe_t *pipe_);
// Activates pipe that have previously reached high watermark. // Activates pipe that have previously reached high watermark.
void activated (zmq::pipe_t *pipe_); void activated (zmq::pipe_t *pipe_);

View File

@ -131,7 +131,7 @@ void zmq::epoll_t::reset_pollin (handle_t handle_)
{ {
check_thread (); check_thread ();
poll_entry_t *pe = static_cast<poll_entry_t *> (handle_); poll_entry_t *pe = static_cast<poll_entry_t *> (handle_);
pe->ev.events &= ~(static_cast<short> (EPOLLIN)); pe->ev.events &= ~(static_cast<uint32_t> (EPOLLIN));
const int rc = epoll_ctl (_epoll_fd, EPOLL_CTL_MOD, pe->fd, &pe->ev); const int rc = epoll_ctl (_epoll_fd, EPOLL_CTL_MOD, pe->fd, &pe->ev);
errno_assert (rc != -1); errno_assert (rc != -1);
} }
@ -149,7 +149,7 @@ void zmq::epoll_t::reset_pollout (handle_t handle_)
{ {
check_thread (); check_thread ();
poll_entry_t *pe = static_cast<poll_entry_t *> (handle_); poll_entry_t *pe = static_cast<poll_entry_t *> (handle_);
pe->ev.events &= ~(static_cast<short> (EPOLLOUT)); pe->ev.events &= ~(static_cast<uint32_t> (EPOLLOUT));
const int rc = epoll_ctl (_epoll_fd, EPOLL_CTL_MOD, pe->fd, &pe->ev); const int rc = epoll_ctl (_epoll_fd, EPOLL_CTL_MOD, pe->fd, &pe->ev);
errno_assert (rc != -1); errno_assert (rc != -1);
} }

View File

@ -33,7 +33,7 @@
#include "err.hpp" #include "err.hpp"
#include "msg.hpp" #include "msg.hpp"
zmq::fq_t::fq_t () : _active (0), _last_in (NULL), _current (0), _more (false) zmq::fq_t::fq_t () : _active (0), _current (0), _more (false)
{ {
} }
@ -62,10 +62,6 @@ void zmq::fq_t::pipe_terminated (pipe_t *pipe_)
_current = 0; _current = 0;
} }
_pipes.erase (pipe_); _pipes.erase (pipe_);
if (_last_in == pipe_) {
_last_in = NULL;
}
} }
void zmq::fq_t::activated (pipe_t *pipe_) void zmq::fq_t::activated (pipe_t *pipe_)
@ -100,7 +96,6 @@ int zmq::fq_t::recvpipe (msg_t *msg_, pipe_t **pipe_)
*pipe_ = _pipes[_current]; *pipe_ = _pipes[_current];
_more = (msg_->flags () & msg_t::more) != 0; _more = (msg_->flags () & msg_t::more) != 0;
if (!_more) { if (!_more) {
_last_in = _pipes[_current];
_current = (_current + 1) % _active; _current = (_current + 1) % _active;
} }
return 0; return 0;

View File

@ -65,11 +65,6 @@ class fq_t
// beginning of the pipes array. // beginning of the pipes array.
pipes_t::size_type _active; pipes_t::size_type _active;
// Pointer to the last pipe we received message from.
// NULL when no message has been received or the pipe
// has terminated.
pipe_t *_last_in;
// Index of the next bound pipe to read a message from. // Index of the next bound pipe to read a message from.
pipes_t::size_type _current; pipes_t::size_type _current;

32
vendor/ZMQ/src/ip.cpp vendored
View File

@ -868,24 +868,48 @@ void zmq::assert_success_or_recoverable (zmq::fd_t s_, int rc_)
} }
#ifdef ZMQ_HAVE_IPC #ifdef ZMQ_HAVE_IPC
#if defined ZMQ_HAVE_WINDOWS
char *widechar_to_utf8 (const wchar_t *widestring)
{
int nch, n;
char *utf8 = 0;
nch = WideCharToMultiByte (CP_UTF8, 0, widestring, -1, 0, 0, NULL, NULL);
if (nch > 0) {
utf8 = (char *) malloc ((nch + 1) * sizeof (char));
n = WideCharToMultiByte (CP_UTF8, 0, widestring, -1, utf8, nch, NULL,
NULL);
utf8[nch] = 0;
}
return utf8;
}
#endif
int zmq::create_ipc_wildcard_address (std::string &path_, std::string &file_) int zmq::create_ipc_wildcard_address (std::string &path_, std::string &file_)
{ {
#if defined ZMQ_HAVE_WINDOWS #if defined ZMQ_HAVE_WINDOWS
char buffer[MAX_PATH]; wchar_t buffer[MAX_PATH];
{ {
const errno_t rc = tmpnam_s (buffer); const errno_t rc = _wtmpnam_s (buffer);
errno_assert (rc == 0); errno_assert (rc == 0);
} }
// TODO or use CreateDirectoryA and specify permissions? // TODO or use CreateDirectoryA and specify permissions?
const int rc = _mkdir (buffer); const int rc = _wmkdir (buffer);
if (rc != 0) { if (rc != 0) {
return -1; return -1;
} }
path_.assign (buffer); char *tmp = widechar_to_utf8 (buffer);
if (tmp == 0) {
return -1;
}
path_.assign (tmp);
file_ = path_ + "/socket"; file_ = path_ + "/socket";
free (tmp);
#else #else
std::string tmp_path; std::string tmp_path;

View File

@ -35,7 +35,7 @@
// Mutex class encapsulates OS mutex in a platform-independent way. // Mutex class encapsulates OS mutex in a platform-independent way.
#ifdef ZMQ_HAVE_WINDOWS #if defined(ZMQ_HAVE_WINDOWS) && !defined(ZMQ_USE_CV_IMPL_PTHREADS)
#include "windows.hpp" #include "windows.hpp"

View File

@ -254,7 +254,10 @@ zmq::options_t::options_t () :
hello_msg (), hello_msg (),
can_send_hello_msg (false), can_send_hello_msg (false),
disconnect_msg (), disconnect_msg (),
can_recv_disconnect_msg (false) can_recv_disconnect_msg (false),
hiccup_msg (),
can_recv_hiccup_msg (false),
busy_poll (0)
{ {
memset (curve_public_key, 0, CURVE_KEYSIZE); memset (curve_public_key, 0, CURVE_KEYSIZE);
memset (curve_secret_key, 0, CURVE_KEYSIZE); memset (curve_secret_key, 0, CURVE_KEYSIZE);
@ -802,6 +805,12 @@ int zmq::options_t::setsockopt (int option_,
} }
break; break;
case ZMQ_BUSY_POLL:
if (is_int) {
busy_poll = value;
return 0;
}
break;
#ifdef ZMQ_HAVE_WSS #ifdef ZMQ_HAVE_WSS
case ZMQ_WSS_KEY_PEM: case ZMQ_WSS_KEY_PEM:
// TODO: check if valid certificate // TODO: check if valid certificate
@ -852,6 +861,18 @@ int zmq::options_t::setsockopt (int option_,
} }
break; break;
case ZMQ_HICCUP_MSG:
if (optvallen_ > 0) {
unsigned char *bytes = (unsigned char *) optval_;
hiccup_msg =
std::vector<unsigned char> (bytes, bytes + optvallen_);
} else {
hiccup_msg = std::vector<unsigned char> ();
}
return 0;
#endif #endif
default: default:
@ -1285,6 +1306,12 @@ int zmq::options_t::getsockopt (int option_,
return 0; return 0;
} }
break; break;
case ZMQ_BUSY_POLL:
if (is_int) {
*value = busy_poll;
}
break;
#endif #endif

View File

@ -308,6 +308,13 @@ struct options_t
// Disconnect msg // Disconnect msg
std::vector<unsigned char> disconnect_msg; std::vector<unsigned char> disconnect_msg;
bool can_recv_disconnect_msg; bool can_recv_disconnect_msg;
// Hiccup msg
std::vector<unsigned char> hiccup_msg;
bool can_recv_hiccup_msg;
// This option removes several delays caused by scheduling, interrupts and context switching.
int busy_poll;
}; };
inline bool get_effective_conflate_option (const options_t &options) inline bool get_effective_conflate_option (const options_t &options)

View File

@ -36,8 +36,7 @@
zmq::pair_t::pair_t (class ctx_t *parent_, uint32_t tid_, int sid_) : zmq::pair_t::pair_t (class ctx_t *parent_, uint32_t tid_, int sid_) :
socket_base_t (parent_, tid_, sid_), socket_base_t (parent_, tid_, sid_),
_pipe (NULL), _pipe (NULL)
_last_in (NULL)
{ {
options.type = ZMQ_PAIR; options.type = ZMQ_PAIR;
} }
@ -67,9 +66,6 @@ void zmq::pair_t::xattach_pipe (pipe_t *pipe_,
void zmq::pair_t::xpipe_terminated (pipe_t *pipe_) void zmq::pair_t::xpipe_terminated (pipe_t *pipe_)
{ {
if (pipe_ == _pipe) { if (pipe_ == _pipe) {
if (_last_in == _pipe) {
_last_in = NULL;
}
_pipe = NULL; _pipe = NULL;
} }
} }
@ -117,7 +113,6 @@ int zmq::pair_t::xrecv (msg_t *msg_)
errno = EAGAIN; errno = EAGAIN;
return -1; return -1;
} }
_last_in = _pipe;
return 0; return 0;
} }

View File

@ -62,8 +62,6 @@ class pair_t ZMQ_FINAL : public socket_base_t
private: private:
zmq::pipe_t *_pipe; zmq::pipe_t *_pipe;
zmq::pipe_t *_last_in;
ZMQ_NON_COPYABLE_NOR_MOVABLE (pair_t) ZMQ_NON_COPYABLE_NOR_MOVABLE (pair_t)
}; };
} }

View File

@ -42,6 +42,7 @@ zmq::peer_t::peer_t (class ctx_t *parent_, uint32_t tid_, int sid_) :
options.type = ZMQ_PEER; options.type = ZMQ_PEER;
options.can_send_hello_msg = true; options.can_send_hello_msg = true;
options.can_recv_disconnect_msg = true; options.can_recv_disconnect_msg = true;
options.can_recv_hiccup_msg = true;
} }
uint32_t zmq::peer_t::connect_peer (const char *endpoint_uri_) uint32_t zmq::peer_t::connect_peer (const char *endpoint_uri_)

View File

@ -597,7 +597,7 @@ void zmq::pipe_t::process_pipe_peer_stats (uint64_t queue_count_,
void zmq::pipe_t::send_disconnect_msg () void zmq::pipe_t::send_disconnect_msg ()
{ {
if (_disconnect_msg.size () > 0) { if (_disconnect_msg.size () > 0 && _out_pipe) {
// Rollback any incomplete message in the pipe, and push the disconnect message. // Rollback any incomplete message in the pipe, and push the disconnect message.
rollback (); rollback ();
@ -615,3 +615,15 @@ void zmq::pipe_t::set_disconnect_msg (
_disconnect_msg.init_buffer (&disconnect_[0], disconnect_.size ()); _disconnect_msg.init_buffer (&disconnect_[0], disconnect_.size ());
errno_assert (rc == 0); errno_assert (rc == 0);
} }
void zmq::pipe_t::send_hiccup_msg (const std::vector<unsigned char> &hiccup_)
{
if (!hiccup_.empty () && _out_pipe) {
msg_t msg;
const int rc = msg.init_buffer (&hiccup_[0], hiccup_.size ());
errno_assert (rc == 0);
_out_pipe->write (msg, false);
flush ();
}
}

View File

@ -150,6 +150,8 @@ class pipe_t ZMQ_FINAL : public object_t,
void send_disconnect_msg (); void send_disconnect_msg ();
void set_disconnect_msg (const std::vector<unsigned char> &disconnect_); void set_disconnect_msg (const std::vector<unsigned char> &disconnect_);
void send_hiccup_msg (const std::vector<unsigned char> &hiccup_);
private: private:
// Type of the underlying lock-free pipe. // Type of the underlying lock-free pipe.
typedef ypipe_base_t<msg_t> upipe_t; typedef ypipe_base_t<msg_t> upipe_t;

View File

@ -46,7 +46,7 @@ template <typename T, size_t S> class fast_vector_t
explicit fast_vector_t (const size_t nitems_) explicit fast_vector_t (const size_t nitems_)
{ {
if (nitems_ > S) { if (nitems_ > S) {
_buf = static_cast<T *> (malloc (nitems_ * sizeof (T))); _buf = new (std::nothrow) T[nitems_];
// TODO since this function is called by a client, we could return errno == ENOMEM here // TODO since this function is called by a client, we could return errno == ENOMEM here
alloc_assert (_buf); alloc_assert (_buf);
} else { } else {
@ -59,7 +59,7 @@ template <typename T, size_t S> class fast_vector_t
~fast_vector_t () ~fast_vector_t ()
{ {
if (_buf != _static_buf) if (_buf != _static_buf)
free (_buf); delete[] _buf;
} }
private: private:
@ -109,9 +109,9 @@ timeout_t
compute_timeout (bool first_pass_, long timeout_, uint64_t now_, uint64_t end_); compute_timeout (bool first_pass_, long timeout_, uint64_t now_, uint64_t end_);
#elif defined ZMQ_POLL_BASED_ON_SELECT #elif defined ZMQ_POLL_BASED_ON_SELECT
#if defined ZMQ_HAVE_WINDOWS
inline size_t valid_pollset_bytes (const fd_set &pollset_) inline size_t valid_pollset_bytes (const fd_set &pollset_)
{ {
#if defined ZMQ_HAVE_WINDOWS
// On Windows we don't need to copy the whole fd_set. // On Windows we don't need to copy the whole fd_set.
// SOCKETS are continuous from the beginning of fd_array in fd_set. // SOCKETS are continuous from the beginning of fd_array in fd_set.
// We just need to copy fd_count elements of fd_array. // We just need to copy fd_count elements of fd_array.
@ -119,10 +119,14 @@ inline size_t valid_pollset_bytes (const fd_set &pollset_)
return reinterpret_cast<const char *> ( return reinterpret_cast<const char *> (
&pollset_.fd_array[pollset_.fd_count]) &pollset_.fd_array[pollset_.fd_count])
- reinterpret_cast<const char *> (&pollset_); - reinterpret_cast<const char *> (&pollset_);
#else
return sizeof (fd_set);
#endif
} }
#else
inline size_t valid_pollset_bytes (const fd_set & /*pollset_*/)
{
return sizeof (fd_set);
}
#endif
#if defined ZMQ_HAVE_WINDOWS #if defined ZMQ_HAVE_WINDOWS
// struct fd_set { // struct fd_set {

View File

@ -558,7 +558,7 @@ visit_keys (node_t node_,
for (size_t i = 0, edgecount = node_.edgecount (); i < edgecount; ++i) { for (size_t i = 0, edgecount = node_.edgecount (); i < edgecount; ++i) {
visit_keys (node_.node_at (i), buffer_, func_, arg_); visit_keys (node_.node_at (i), buffer_, func_, arg_);
} }
buffer_.resize (buffer_.size () - prefix_length); buffer_.resize (static_cast<uint32_t> (buffer_.size () - prefix_length));
} }
void zmq::radix_tree_t::apply ( void zmq::radix_tree_t::apply (

View File

@ -151,8 +151,13 @@ static void manage_random (bool init_)
if (init_) { if (init_) {
int rc = sodium_init (); int rc = sodium_init ();
zmq_assert (rc != -1); zmq_assert (rc != -1);
#if defined(ZMQ_LIBSODIUM_RANDOMBYTES_CLOSE)
} else { } else {
// randombytes_close either a no-op or not threadsafe
// doing this without refcounting can cause crashes
// if called while a context is active
randombytes_close (); randombytes_close ();
#endif
} }
#else #else
LIBZMQ_UNUSED (init_); LIBZMQ_UNUSED (init_);

View File

@ -460,14 +460,18 @@ void zmq::session_base_t::engine_error (bool handshaked_,
if (_pipe) { if (_pipe) {
clean_pipes (); clean_pipes ();
#ifdef ZMQ_BUILD_DRAFT_API
// Only send disconnect message if socket was accepted and handshake was completed // Only send disconnect message if socket was accepted and handshake was completed
if (!_active && handshaked_ && options.can_recv_disconnect_msg if (!_active && handshaked_ && options.can_recv_disconnect_msg
&& !options.disconnect_msg.empty ()) { && !options.disconnect_msg.empty ()) {
_pipe->set_disconnect_msg (options.disconnect_msg); _pipe->set_disconnect_msg (options.disconnect_msg);
_pipe->send_disconnect_msg (); _pipe->send_disconnect_msg ();
} }
#endif
// Only send hiccup message if socket was connected and handshake was completed
if (_active && handshaked_ && options.can_recv_hiccup_msg
&& !options.hiccup_msg.empty ()) {
_pipe->send_hiccup_msg (options.hiccup_msg);
}
} }
zmq_assert (reason_ == i_engine::connection_error zmq_assert (reason_ == i_engine::connection_error

View File

@ -341,6 +341,21 @@ void zmq::tcp_tune_loopback_fast_path (const fd_t socket_)
#endif #endif
} }
void zmq::tune_tcp_busy_poll (fd_t socket_, int busy_poll_)
{
#if defined(ZMQ_HAVE_BUSY_POLL)
if (busy_poll_ > 0) {
const int rc =
setsockopt (socket_, SOL_SOCKET, SO_BUSY_POLL,
reinterpret_cast<char *> (&busy_poll_), sizeof (int));
assert_success_or_recoverable (socket_, rc);
}
#else
LIBZMQ_UNUSED (socket_);
LIBZMQ_UNUSED (busy_poll_);
#endif
}
zmq::fd_t zmq::tcp_open_socket (const char *address_, zmq::fd_t zmq::tcp_open_socket (const char *address_,
const zmq::options_t &options_, const zmq::options_t &options_,
bool local_, bool local_,
@ -398,6 +413,9 @@ zmq::fd_t zmq::tcp_open_socket (const char *address_,
if (options_.rcvbuf >= 0) if (options_.rcvbuf >= 0)
set_tcp_receive_buffer (s, options_.rcvbuf); set_tcp_receive_buffer (s, options_.rcvbuf);
// This option removes several delays caused by scheduling, interrupts and context switching.
if (options_.busy_poll)
tune_tcp_busy_poll (s, options_.busy_poll);
return s; return s;
setsockopt_error: setsockopt_error:

View File

@ -68,6 +68,8 @@ int tcp_read (fd_t s_, void *data_, size_t size_);
void tcp_tune_loopback_fast_path (fd_t socket_); void tcp_tune_loopback_fast_path (fd_t socket_);
void tune_tcp_busy_poll (fd_t socket_, int busy_poll_);
// Resolves the given address_ string, opens a socket and sets socket options // Resolves the given address_ string, opens a socket and sets socket options
// according to the passed options_. On success, returns the socket // according to the passed options_. On success, returns the socket
// descriptor and assigns the resolved address to out_tcp_addr_. In case of // descriptor and assigns the resolved address to out_tcp_addr_. In case of

View File

@ -28,7 +28,9 @@
*/ */
#include "precompiled.hpp" #include "precompiled.hpp"
#include "ip.hpp"
#include "vmci.hpp" #include "vmci.hpp"
#include "vmci_address.hpp"
#if defined ZMQ_HAVE_VMCI #if defined ZMQ_HAVE_VMCI
@ -97,4 +99,23 @@ void zmq::tune_vmci_connect_timeout (ctx_t *context_,
#endif #endif
} }
zmq::fd_t zmq::vmci_open_socket (const char *address_,
const zmq::options_t &options_,
zmq::vmci_address_t *out_vmci_addr_)
{
// Convert the textual address into address structure.
int rc = out_vmci_addr_->resolve (address_);
if (rc != 0)
return retired_fd;
// Create the socket.
fd_t s = open_socket (out_vmci_addr_->family (), SOCK_STREAM, 0);
if (s == retired_fd) {
return retired_fd;
}
return s;
}
#endif #endif

View File

@ -59,6 +59,10 @@ void tune_vmci_connect_timeout (ctx_t *context_,
fd_t sockfd_, fd_t sockfd_,
struct timeval timeout_); struct timeval timeout_);
#endif #endif
fd_t vmci_open_socket (const char *address_,
const options_t &options_,
vmci_address_t *out_vmci_addr_);
} }
#endif #endif

View File

@ -39,6 +39,11 @@
#include "err.hpp" #include "err.hpp"
zmq::vmci_address_t::vmci_address_t ()
{
memset (&address, 0, sizeof address);
}
zmq::vmci_address_t::vmci_address_t (ctx_t *parent_) : parent (parent_) zmq::vmci_address_t::vmci_address_t (ctx_t *parent_) : parent (parent_)
{ {
memset (&address, 0, sizeof address); memset (&address, 0, sizeof address);
@ -56,10 +61,6 @@ zmq::vmci_address_t::vmci_address_t (const sockaddr *sa,
memcpy (&address, sa, sa_len); memcpy (&address, sa, sa_len);
} }
zmq::vmci_address_t::~vmci_address_t ()
{
}
int zmq::vmci_address_t::resolve (const char *path_) int zmq::vmci_address_t::resolve (const char *path_)
{ {
// Find the ':' at end that separates address from the port number. // Find the ':' at end that separates address from the port number.
@ -125,7 +126,7 @@ int zmq::vmci_address_t::resolve (const char *path_)
return 0; return 0;
} }
int zmq::vmci_address_t::to_string (std::string &addr_) int zmq::vmci_address_t::to_string (std::string &addr_) const
{ {
if (address.svm_family != parent->get_vmci_socket_family ()) { if (address.svm_family != parent->get_vmci_socket_family ()) {
addr_.clear (); addr_.clear ();
@ -164,4 +165,13 @@ socklen_t zmq::vmci_address_t::addrlen () const
return static_cast<socklen_t> (sizeof address); return static_cast<socklen_t> (sizeof address);
} }
#if defined ZMQ_HAVE_WINDOWS
unsigned short zmq::vmci_address_t::family () const
#else
sa_family_t zmq::vmci_address_t::family () const
#endif
{
return parent->get_vmci_socket_family ();
}
#endif #endif

View File

@ -43,16 +43,21 @@ namespace zmq
class vmci_address_t class vmci_address_t
{ {
public: public:
vmci_address_t ();
vmci_address_t (ctx_t *parent_); vmci_address_t (ctx_t *parent_);
vmci_address_t (const sockaddr *sa, socklen_t sa_len, ctx_t *parent_); vmci_address_t (const sockaddr *sa, socklen_t sa_len, ctx_t *parent_);
~vmci_address_t ();
// This function sets up the address for VMCI transport. // This function sets up the address for VMCI transport.
int resolve (const char *path_); int resolve (const char *path_);
// The opposite to resolve() // The opposite to resolve()
int to_string (std::string &addr_); int to_string (std::string &addr_) const;
#if defined ZMQ_HAVE_WINDOWS
unsigned short family () const;
#else
sa_family_t family () const;
#endif
const sockaddr *addr () const; const sockaddr *addr () const;
socklen_t addrlen () const; socklen_t addrlen () const;
@ -60,8 +65,6 @@ class vmci_address_t
struct sockaddr_vm address; struct sockaddr_vm address;
ctx_t *parent; ctx_t *parent;
vmci_address_t ();
ZMQ_NON_COPYABLE_NOR_MOVABLE (vmci_address_t) ZMQ_NON_COPYABLE_NOR_MOVABLE (vmci_address_t)
}; };
} }

View File

@ -35,69 +35,41 @@
#include <new> #include <new>
#include "stream_engine.hpp"
#include "io_thread.hpp" #include "io_thread.hpp"
#include "platform.hpp" #include "platform.hpp"
#include "random.hpp" #include "random.hpp"
#include "err.hpp" #include "err.hpp"
#include "ip.hpp" #include "ip.hpp"
#include "address.hpp" #include "address.hpp"
#include "session_base.hpp"
#include "vmci_address.hpp" #include "vmci_address.hpp"
#include "vmci.hpp" #include "vmci.hpp"
#include "session_base.hpp"
zmq::vmci_connecter_t::vmci_connecter_t (class io_thread_t *io_thread_, zmq::vmci_connecter_t::vmci_connecter_t (class io_thread_t *io_thread_,
class session_base_t *session_, class session_base_t *session_,
const options_t &options_, const options_t &options_,
const address_t *addr_, address_t *addr_,
bool delayed_start_) : bool delayed_start_) :
own_t (io_thread_, options_), stream_connecter_base_t (
io_object_t (io_thread_), io_thread_, session_, options_, addr_, delayed_start_),
addr (addr_), _connect_timer_started (false)
s (retired_fd),
handle_valid (false),
delayed_start (delayed_start_),
timer_started (false),
session (session_),
current_reconnect_ivl (options.reconnect_ivl)
{ {
zmq_assert (addr); zmq_assert (_addr->protocol == protocol_name::vmci);
zmq_assert (addr->protocol == "vmci");
addr->to_string (endpoint);
socket = session->get_socket ();
} }
zmq::vmci_connecter_t::~vmci_connecter_t () zmq::vmci_connecter_t::~vmci_connecter_t ()
{ {
zmq_assert (!timer_started); zmq_assert (!_connect_timer_started);
zmq_assert (!handle_valid);
zmq_assert (s == retired_fd);
}
void zmq::vmci_connecter_t::process_plug ()
{
if (delayed_start)
add_reconnect_timer ();
else
start_connecting ();
} }
void zmq::vmci_connecter_t::process_term (int linger_) void zmq::vmci_connecter_t::process_term (int linger_)
{ {
if (timer_started) { if (_connect_timer_started) {
cancel_timer (reconnect_timer_id); cancel_timer (connect_timer_id);
timer_started = false; _connect_timer_started = false;
} }
if (handle_valid) { stream_connecter_base_t::process_term (linger_);
rm_fd (handle);
handle_valid = false;
}
if (s != retired_fd)
close ();
own_t::process_term (linger_);
} }
void zmq::vmci_connecter_t::in_event () void zmq::vmci_connecter_t::in_event ()
@ -110,9 +82,26 @@ void zmq::vmci_connecter_t::in_event ()
void zmq::vmci_connecter_t::out_event () void zmq::vmci_connecter_t::out_event ()
{ {
fd_t fd = connect (); if (_connect_timer_started) {
rm_fd (handle); cancel_timer (connect_timer_id);
handle_valid = false; _connect_timer_started = false;
}
// TODO this is still very similar to (t)ipc_connecter_t, maybe the
// differences can be factored out
rm_handle ();
const fd_t fd = connect ();
if (fd == retired_fd
&& ((options.reconnect_stop & ZMQ_RECONNECT_STOP_CONN_REFUSED)
&& errno == ECONNREFUSED)) {
send_conn_failed (_session);
close ();
terminate ();
return;
}
// Handle the error condition by attempt to reconnect. // Handle the error condition by attempt to reconnect.
if (fd == retired_fd) { if (fd == retired_fd) {
@ -135,148 +124,154 @@ void zmq::vmci_connecter_t::out_event ()
#endif #endif
} }
// Create the engine object for this connection. create_engine (
stream_engine_t *engine = new (std::nothrow) stream_engine_t ( fd, zmq::vmci_connecter_t::get_socket_name (fd, socket_end_local));
fd, options, make_unconnected_bind_endpoint_pair (endpoint)); }
alloc_assert (engine);
// Attach the engine to the corresponding session object. std::string
send_attach (session, engine); zmq::vmci_connecter_t::get_socket_name (zmq::fd_t fd_,
socket_end_t socket_end_) const
{
struct sockaddr_storage ss;
const zmq_socklen_t sl = get_socket_address (fd_, socket_end_, &ss);
if (sl == 0) {
return std::string ();
}
// Shut the connecter down. const vmci_address_t addr (reinterpret_cast<struct sockaddr *> (&ss), sl,
terminate (); this->get_ctx ());
std::string address_string;
socket->event_connected (make_unconnected_bind_endpoint_pair (endpoint), addr.to_string (address_string);
fd); return address_string;
} }
void zmq::vmci_connecter_t::timer_event (int id_) void zmq::vmci_connecter_t::timer_event (int id_)
{ {
zmq_assert (id_ == reconnect_timer_id); if (id_ == connect_timer_id) {
timer_started = false; _connect_timer_started = false;
start_connecting (); rm_handle ();
close ();
add_reconnect_timer ();
} else
stream_connecter_base_t::timer_event (id_);
} }
void zmq::vmci_connecter_t::start_connecting () void zmq::vmci_connecter_t::start_connecting ()
{ {
// Open the connecting socket. // Open the connecting socket.
int rc = open (); const int rc = open ();
// Connect may succeed in synchronous manner. // Connect may succeed in synchronous manner.
if (rc == 0) { if (rc == 0) {
handle = add_fd (s); _handle = add_fd (_s);
handle_valid = true;
out_event (); out_event ();
} }
// Connection establishment may be delayed. Poll for its completion.
else if (rc == -1 && errno == EINPROGRESS) {
_handle = add_fd (_s);
set_pollout (_handle);
_socket->event_connect_delayed (
make_unconnected_connect_endpoint_pair (_endpoint), zmq_errno ());
// add userspace connect timeout
add_connect_timer ();
}
// Handle any other error condition by eventual reconnect. // Handle any other error condition by eventual reconnect.
else { else {
if (s != retired_fd) if (_s != retired_fd)
close (); close ();
add_reconnect_timer (); add_reconnect_timer ();
} }
} }
void zmq::vmci_connecter_t::add_reconnect_timer () void zmq::vmci_connecter_t::add_connect_timer ()
{ {
if (options.reconnect_ivl > 0) { if (options.connect_timeout > 0) {
int rc_ivl = get_new_reconnect_ivl (); add_timer (options.connect_timeout, connect_timer_id);
add_timer (rc_ivl, reconnect_timer_id); _connect_timer_started = true;
socket->event_connect_retried (
make_unconnected_bind_endpoint_pair (endpoint), rc_ivl);
timer_started = true;
} }
} }
int zmq::vmci_connecter_t::get_new_reconnect_ivl ()
{
// The new interval is the current interval + random value.
int this_interval =
current_reconnect_ivl + (generate_random () % options.reconnect_ivl);
// Only change the current reconnect interval if the maximum reconnect
// interval was set and if it's larger than the reconnect interval.
if (options.reconnect_ivl_max > 0
&& options.reconnect_ivl_max > options.reconnect_ivl) {
// Calculate the next interval
current_reconnect_ivl = current_reconnect_ivl * 2;
if (current_reconnect_ivl >= options.reconnect_ivl_max) {
current_reconnect_ivl = options.reconnect_ivl_max;
}
}
return this_interval;
}
int zmq::vmci_connecter_t::open () int zmq::vmci_connecter_t::open ()
{ {
zmq_assert (s == retired_fd); zmq_assert (_s == retired_fd);
int family = this->get_ctx ()->get_vmci_socket_family (); // Resolve the address
if (family == -1) if (_addr->resolved.vmci_addr != NULL) {
return -1; LIBZMQ_DELETE (_addr->resolved.vmci_addr);
}
// Create the socket. _addr->resolved.vmci_addr =
s = open_socket (family, SOCK_STREAM, 0); new (std::nothrow) vmci_address_t (this->get_ctx ());
#ifdef ZMQ_HAVE_WINDOWS alloc_assert (_addr->resolved.vmci_addr);
if (s == INVALID_SOCKET) { _s = vmci_open_socket (_addr->address.c_str (), options,
errno = wsa_error_to_errno (WSAGetLastError ()); _addr->resolved.vmci_addr);
if (_s == retired_fd) {
// TODO we should emit some event in this case!
LIBZMQ_DELETE (_addr->resolved.vmci_addr);
return -1; return -1;
} }
#else zmq_assert (_addr->resolved.vmci_addr != NULL);
if (s == -1)
return -1; // Set the socket to non-blocking mode so that we get async connect().
#endif unblock_socket (_s);
const vmci_address_t *const vmci_addr = _addr->resolved.vmci_addr;
int rc;
// Connect to the remote peer. // Connect to the remote peer.
int rc = ::connect (s, addr->resolved.vmci_addr->addr (), #if defined ZMQ_HAVE_VXWORKS
addr->resolved.vmci_addr->addrlen ()); rc = ::connect (_s, (sockaddr *) vmci_addr->addr (), vmci_addr->addrlen ());
// Connect was successful immediately.
if (rc == 0)
return 0;
// Forward the error.
return -1;
}
void zmq::vmci_connecter_t::close ()
{
zmq_assert (s != retired_fd);
#ifdef ZMQ_HAVE_WINDOWS
const int rc = closesocket (s);
wsa_assert (rc != SOCKET_ERROR);
#else #else
const int rc = ::close (s); rc = ::connect (_s, vmci_addr->addr (), vmci_addr->addrlen ());
errno_assert (rc == 0);
#endif #endif
socket->event_closed (make_unconnected_bind_endpoint_pair (endpoint), s); // Connect was successful immediately.
s = retired_fd; if (rc == 0) {
return 0;
}
// Translate error codes indicating asynchronous connect has been
// launched to a uniform EINPROGRESS.
#ifdef ZMQ_HAVE_WINDOWS
const int last_error = WSAGetLastError ();
if (last_error == WSAEINPROGRESS || last_error == WSAEWOULDBLOCK)
errno = EINPROGRESS;
else
errno = wsa_error_to_errno (last_error);
#else
if (errno == EINTR)
errno = EINPROGRESS;
#endif
return -1;
} }
zmq::fd_t zmq::vmci_connecter_t::connect () zmq::fd_t zmq::vmci_connecter_t::connect ()
{ {
// Following code should handle both Berkeley-derived socket // Async connect has finished. Check whether an error occurred
// implementations and Solaris.
int err = 0; int err = 0;
#if defined ZMQ_HAVE_HPUX #if defined ZMQ_HAVE_HPUX || defined ZMQ_HAVE_VXWORKS
int len = sizeof (err); int len = sizeof err;
#else #else
socklen_t len = sizeof (err); socklen_t len = sizeof err;
#endif #endif
int rc = getsockopt (s, SOL_SOCKET, SO_ERROR, (char *) &err, &len);
const int rc = getsockopt (_s, SOL_SOCKET, SO_ERROR,
reinterpret_cast<char *> (&err), &len);
// Assert if the error was caused by 0MQ bug. // Assert if the error was caused by 0MQ bug.
// Networking problems are OK. No need to assert. // Networking problems are OK. No need to assert.
#ifdef ZMQ_HAVE_WINDOWS #ifdef ZMQ_HAVE_WINDOWS
zmq_assert (rc == 0); zmq_assert (rc == 0);
if (err != 0) { if (err != 0) {
if (err != WSAECONNREFUSED && err != WSAETIMEDOUT if (err == WSAEBADF || err == WSAENOPROTOOPT || err == WSAENOTSOCK
&& err != WSAECONNABORTED && err != WSAEHOSTUNREACH || err == WSAENOBUFS) {
&& err != WSAENETUNREACH && err != WSAENETDOWN && err != WSAEACCES
&& err != WSAEINVAL && err != WSAEADDRINUSE
&& err != WSAECONNRESET) {
wsa_assert_no (err); wsa_assert_no (err);
} }
errno = wsa_error_to_errno (err);
return retired_fd; return retired_fd;
} }
#else #else
@ -286,16 +281,20 @@ zmq::fd_t zmq::vmci_connecter_t::connect ()
err = errno; err = errno;
if (err != 0) { if (err != 0) {
errno = err; errno = err;
errno_assert (errno == ECONNREFUSED || errno == ECONNRESET #if !defined(TARGET_OS_IPHONE) || !TARGET_OS_IPHONE
|| errno == ETIMEDOUT || errno == EHOSTUNREACH errno_assert (errno != EBADF && errno != ENOPROTOOPT
|| errno == ENETUNREACH || errno == ENETDOWN && errno != ENOTSOCK && errno != ENOBUFS);
|| errno == EINVAL); #else
errno_assert (errno != ENOPROTOOPT && errno != ENOTSOCK
&& errno != ENOBUFS);
#endif
return retired_fd; return retired_fd;
} }
#endif #endif
fd_t result = s; // Return the newly connected socket.
s = retired_fd; const fd_t result = _s;
_s = retired_fd;
return result; return result;
} }

View File

@ -38,6 +38,7 @@
#include "own.hpp" #include "own.hpp"
#include "stdint.hpp" #include "stdint.hpp"
#include "io_object.hpp" #include "io_object.hpp"
#include "stream_connecter_base.hpp"
namespace zmq namespace zmq
{ {
@ -45,8 +46,7 @@ class io_thread_t;
class session_base_t; class session_base_t;
struct address_t; struct address_t;
// TODO consider refactoring this to derive from stream_connecter_base_t class vmci_connecter_t ZMQ_FINAL : public stream_connecter_base_t
class vmci_connecter_t ZMQ_FINAL : public own_t, public io_object_t
{ {
public: public:
// If 'delayed_start' is true connecter first waits for a while, // If 'delayed_start' is true connecter first waits for a while,
@ -54,19 +54,21 @@ class vmci_connecter_t ZMQ_FINAL : public own_t, public io_object_t
vmci_connecter_t (zmq::io_thread_t *io_thread_, vmci_connecter_t (zmq::io_thread_t *io_thread_,
zmq::session_base_t *session_, zmq::session_base_t *session_,
const options_t &options_, const options_t &options_,
const address_t *addr_, address_t *addr_,
bool delayed_start_); bool delayed_start_);
~vmci_connecter_t (); ~vmci_connecter_t ();
protected:
std::string get_socket_name (fd_t fd_, socket_end_t socket_end_) const;
private: private:
// ID of the timer used to delay the reconnection. // ID of the timer used to check the connect timeout, must be different from stream_connecter_base_t::reconnect_timer_id.
enum enum
{ {
reconnect_timer_id = 1 connect_timer_id = 2
}; };
// Handlers for incoming commands. // Handlers for incoming commands.
void process_plug ();
void process_term (int linger_); void process_term (int linger_);
// Handlers for I/O events. // Handlers for I/O events.
@ -77,8 +79,8 @@ class vmci_connecter_t ZMQ_FINAL : public own_t, public io_object_t
// Internal function to start the actual connection establishment. // Internal function to start the actual connection establishment.
void start_connecting (); void start_connecting ();
// Internal function to add a reconnect timer // Internal function to add a connect timer
void add_reconnect_timer (); void add_connect_timer ();
// Internal function to return a reconnect backoff delay. // Internal function to return a reconnect backoff delay.
// Will modify the current_reconnect_ivl used for next call // Will modify the current_reconnect_ivl used for next call
@ -90,43 +92,12 @@ class vmci_connecter_t ZMQ_FINAL : public own_t, public io_object_t
// EAGAIN errno if async connect was launched. // EAGAIN errno if async connect was launched.
int open (); int open ();
// Close the connecting socket.
void close ();
// Get the file descriptor of newly created connection. Returns // Get the file descriptor of newly created connection. Returns
// retired_fd if the connection was unsuccessful. // retired_fd if the connection was unsuccessful.
fd_t connect (); fd_t connect ();
// Address to connect to. Owned by session_base_t.
const address_t *addr;
// Underlying socket.
fd_t s;
// Handle corresponding to the listening socket.
handle_t handle;
// If true file descriptor is registered with the poller and 'handle'
// contains valid value.
bool handle_valid;
// If true, connecter is waiting a while before trying to connect.
const bool delayed_start;
// True iff a timer has been started. // True iff a timer has been started.
bool timer_started; bool _connect_timer_started;
// Reference to the session we belong to.
zmq::session_base_t *session;
// Current reconnect ivl, updated for backoff strategy
int current_reconnect_ivl;
// String representation of endpoint to connect to
std::string endpoint;
// Socket
zmq::socket_base_t *socket;
ZMQ_NON_COPYABLE_NOR_MOVABLE (vmci_connecter_t) ZMQ_NON_COPYABLE_NOR_MOVABLE (vmci_connecter_t)
}; };

View File

@ -35,7 +35,7 @@
#include <new> #include <new>
#include "stream_engine.hpp" //#include "stream_engine.hpp"
#include "vmci_address.hpp" #include "vmci_address.hpp"
#include "io_thread.hpp" #include "io_thread.hpp"
#include "session_base.hpp" #include "session_base.hpp"
@ -55,40 +55,18 @@
zmq::vmci_listener_t::vmci_listener_t (io_thread_t *io_thread_, zmq::vmci_listener_t::vmci_listener_t (io_thread_t *io_thread_,
socket_base_t *socket_, socket_base_t *socket_,
const options_t &options_) : const options_t &options_) :
own_t (io_thread_, options_), stream_listener_base_t (io_thread_, socket_, options_)
io_object_t (io_thread_),
s (retired_fd),
socket (socket_)
{ {
} }
zmq::vmci_listener_t::~vmci_listener_t ()
{
zmq_assert (s == retired_fd);
}
void zmq::vmci_listener_t::process_plug ()
{
// Start polling for incoming connections.
handle = add_fd (s);
set_pollin (handle);
}
void zmq::vmci_listener_t::process_term (int linger_)
{
rm_fd (handle);
close ();
own_t::process_term (linger_);
}
void zmq::vmci_listener_t::in_event () void zmq::vmci_listener_t::in_event ()
{ {
fd_t fd = accept (); fd_t fd = accept ();
// If connection was reset by the peer in the meantime, just ignore it. // If connection was reset by the peer in the meantime, just ignore it.
if (fd == retired_fd) { if (fd == retired_fd) {
socket->event_accept_failed ( _socket->event_accept_failed (
make_unconnected_bind_endpoint_pair (endpoint), zmq_errno ()); make_unconnected_bind_endpoint_pair (_endpoint), zmq_errno ());
return; return;
} }
@ -107,41 +85,24 @@ void zmq::vmci_listener_t::in_event ()
} }
// Create the engine object for this connection. // Create the engine object for this connection.
stream_engine_t *engine = new (std::nothrow) stream_engine_t ( create_engine (fd);
fd, options, make_unconnected_bind_endpoint_pair (endpoint));
alloc_assert (engine);
// Choose I/O thread to run connecter in. Given that we are already
// running in an I/O thread, there must be at least one available.
io_thread_t *io_thread = choose_io_thread (options.affinity);
zmq_assert (io_thread);
// Create and launch a session object.
session_base_t *session =
session_base_t::create (io_thread, false, socket, options, NULL);
errno_assert (session);
session->inc_seqnum ();
launch_child (session);
send_attach (session, engine, false);
socket->event_accepted (make_unconnected_bind_endpoint_pair (endpoint), fd);
} }
int zmq::vmci_listener_t::get_local_address (std::string &addr_) std::string
zmq::vmci_listener_t::get_socket_name (zmq::fd_t fd_,
socket_end_t socket_end_) const
{ {
struct sockaddr_storage ss; struct sockaddr_storage ss;
#ifdef ZMQ_HAVE_HPUX const zmq_socklen_t sl = get_socket_address (fd_, socket_end_, &ss);
int sl = sizeof (ss); if (sl == 0) {
#else return std::string ();
socklen_t sl = sizeof (ss);
#endif
int rc = getsockname (s, (sockaddr *) &ss, &sl);
if (rc != 0) {
addr_.clear ();
return rc;
} }
vmci_address_t addr ((struct sockaddr *) &ss, sl, this->get_ctx ()); const vmci_address_t addr (reinterpret_cast<struct sockaddr *> (&ss), sl,
return addr.to_string (addr_); this->get_ctx ());
std::string address_string;
addr.to_string (address_string);
return address_string;
} }
int zmq::vmci_listener_t::set_local_address (const char *addr_) int zmq::vmci_listener_t::set_local_address (const char *addr_)
@ -156,7 +117,7 @@ int zmq::vmci_listener_t::set_local_address (const char *addr_)
return -1; return -1;
// Create a listening socket. // Create a listening socket.
s = _s =
open_socket (this->get_ctx ()->get_vmci_socket_family (), SOCK_STREAM, 0); open_socket (this->get_ctx ()->get_vmci_socket_family (), SOCK_STREAM, 0);
#ifdef ZMQ_HAVE_WINDOWS #ifdef ZMQ_HAVE_WINDOWS
if (s == INVALID_SOCKET) { if (s == INVALID_SOCKET) {
@ -165,18 +126,18 @@ int zmq::vmci_listener_t::set_local_address (const char *addr_)
} }
#if !defined _WIN32_WCE #if !defined _WIN32_WCE
// On Windows, preventing sockets to be inherited by child processes. // On Windows, preventing sockets to be inherited by child processes.
BOOL brc = SetHandleInformation ((HANDLE) s, HANDLE_FLAG_INHERIT, 0); BOOL brc = SetHandleInformation ((HANDLE) _s, HANDLE_FLAG_INHERIT, 0);
win_assert (brc); win_assert (brc);
#endif #endif
#else #else
if (s == -1) if (_s == -1)
return -1; return -1;
#endif #endif
address.to_string (endpoint); address.to_string (_endpoint);
// Bind the socket. // Bind the socket.
rc = bind (s, address.addr (), address.addrlen ()); rc = bind (_s, address.addr (), address.addrlen ());
#ifdef ZMQ_HAVE_WINDOWS #ifdef ZMQ_HAVE_WINDOWS
if (rc == SOCKET_ERROR) { if (rc == SOCKET_ERROR) {
errno = wsa_error_to_errno (WSAGetLastError ()); errno = wsa_error_to_errno (WSAGetLastError ());
@ -188,7 +149,7 @@ int zmq::vmci_listener_t::set_local_address (const char *addr_)
#endif #endif
// Listen for incoming connections. // Listen for incoming connections.
rc = listen (s, options.backlog); rc = listen (_s, options.backlog);
#ifdef ZMQ_HAVE_WINDOWS #ifdef ZMQ_HAVE_WINDOWS
if (rc == SOCKET_ERROR) { if (rc == SOCKET_ERROR) {
errno = wsa_error_to_errno (WSAGetLastError ()); errno = wsa_error_to_errno (WSAGetLastError ());
@ -199,7 +160,8 @@ int zmq::vmci_listener_t::set_local_address (const char *addr_)
goto error; goto error;
#endif #endif
socket->event_listening (make_unconnected_bind_endpoint_pair (endpoint), s); _socket->event_listening (make_unconnected_bind_endpoint_pair (_endpoint),
_s);
return 0; return 0;
error: error:
@ -209,27 +171,13 @@ error:
return -1; return -1;
} }
void zmq::vmci_listener_t::close ()
{
zmq_assert (s != retired_fd);
#ifdef ZMQ_HAVE_WINDOWS
int rc = closesocket (s);
wsa_assert (rc != SOCKET_ERROR);
#else
int rc = ::close (s);
errno_assert (rc == 0);
#endif
socket->event_closed (make_unconnected_bind_endpoint_pair (endpoint), s);
s = retired_fd;
}
zmq::fd_t zmq::vmci_listener_t::accept () zmq::fd_t zmq::vmci_listener_t::accept ()
{ {
// Accept one connection and deal with different failure modes. // Accept one connection and deal with different failure modes.
// The situation where connection cannot be accepted due to insufficient // The situation where connection cannot be accepted due to insufficient
// resources is considered valid and treated by ignoring the connection. // resources is considered valid and treated by ignoring the connection.
zmq_assert (s != retired_fd); zmq_assert (_s != retired_fd);
fd_t sock = ::accept (s, NULL, NULL); fd_t sock = ::accept (_s, NULL, NULL);
#ifdef ZMQ_HAVE_WINDOWS #ifdef ZMQ_HAVE_WINDOWS
if (sock == INVALID_SOCKET) { if (sock == INVALID_SOCKET) {

View File

@ -37,57 +37,37 @@
#include <string> #include <string>
#include "fd.hpp" #include "fd.hpp"
#include "own.hpp" #include "vmci_address.hpp"
#include "stdint.hpp" #include "stream_listener_base.hpp"
#include "io_object.hpp"
namespace zmq namespace zmq
{ {
class io_thread_t; class vmci_listener_t ZMQ_FINAL : public stream_listener_base_t
class socket_base_t;
// TODO consider refactoring this to derive from stream_listener_base_t
class vmci_listener_t ZMQ_FINAL : public own_t, public io_object_t
{ {
public: public:
vmci_listener_t (zmq::io_thread_t *io_thread_, vmci_listener_t (zmq::io_thread_t *io_thread_,
zmq::socket_base_t *socket_, zmq::socket_base_t *socket_,
const options_t &options_); const options_t &options_);
~vmci_listener_t ();
// Set address to listen on. // Set address to listen on.
int set_local_address (const char *addr_); int set_local_address (const char *addr_);
// Get the bound address for use with wildcards protected:
int get_local_address (std::string &addr_); std::string get_socket_name (fd_t fd_, socket_end_t socket_end_) const;
private: private:
// Handlers for incoming commands.
void process_plug ();
void process_term (int linger_);
// Handlers for I/O events. // Handlers for I/O events.
void in_event (); void in_event ();
// Close the listening socket.
void close ();
// Accept the new connection. Returns the file descriptor of the // Accept the new connection. Returns the file descriptor of the
// newly created connection. The function may return retired_fd // newly created connection. The function may return retired_fd
// if the connection was dropped while waiting in the listen backlog. // if the connection was dropped while waiting in the listen backlog.
fd_t accept (); fd_t accept ();
// Underlying socket. int create_socket (const char *addr_);
fd_t s;
// Handle corresponding to the listening socket. // Address to listen on.
handle_t handle; vmci_address_t _address;
// Socket the listerner belongs to.
zmq::socket_base_t *socket;
// String representation of endpoint to bind to
std::string endpoint;
ZMQ_NON_COPYABLE_NOR_MOVABLE (vmci_listener_t) ZMQ_NON_COPYABLE_NOR_MOVABLE (vmci_listener_t)
}; };

View File

@ -453,20 +453,20 @@ bool zmq::ws_engine_t::server_handshake ()
if (strcasecmp ("upgrade", _header_name) == 0) if (strcasecmp ("upgrade", _header_name) == 0)
_header_upgrade_websocket = _header_upgrade_websocket =
strcasecmp ("websocket", _header_value) == 0; strcasecmp ("websocket", _header_value) == 0;
else if (strcasecmp ("connection", _header_name) == 0){ else if (strcasecmp ("connection", _header_name) == 0) {
char *element = strtok (_header_value, ","); char *rest = NULL;
while (element != NULL){ char *element = strtok_r (_header_value, ",", &rest);
while (element != NULL) {
while (*element == ' ') while (*element == ' ')
element++; element++;
if (strcasecmp ("upgrade", element) == 0){ if (strcasecmp ("upgrade", element) == 0) {
_header_connection_upgrade = true; _header_connection_upgrade = true;
break; break;
} }
element = strtok (NULL, ","); element = strtok_r (NULL, ",", &rest);
} }
} } else if (strcasecmp ("Sec-WebSocket-Key", _header_name)
else if (strcasecmp ("Sec-WebSocket-Key", _header_name) == 0)
== 0)
strcpy_s (_websocket_key, _header_value); strcpy_s (_websocket_key, _header_value);
else if (strcasecmp ("Sec-WebSocket-Protocol", _header_name) else if (strcasecmp ("Sec-WebSocket-Protocol", _header_name)
== 0) { == 0) {
@ -474,7 +474,7 @@ bool zmq::ws_engine_t::server_handshake ()
// Sec-WebSocket-Protocol can appear multiple times or be a comma separated list // Sec-WebSocket-Protocol can appear multiple times or be a comma separated list
// if _websocket_protocol is already set we skip the check // if _websocket_protocol is already set we skip the check
if (_websocket_protocol[0] == '\0') { if (_websocket_protocol[0] == '\0') {
char *rest = 0; char *rest = NULL;
char *p = strtok_r (_header_value, ",", &rest); char *p = strtok_r (_header_value, ",", &rest);
while (p != NULL) { while (p != NULL) {
if (*p == ' ') if (*p == ' ')

View File

@ -272,6 +272,12 @@ void zmq::xpub_t::xpipe_terminated (pipe_t *pipe_)
// care of by the manual call above. subscriptions is the real mtrie, // care of by the manual call above. subscriptions is the real mtrie,
// so the pipe must be removed from there or it will be left over. // so the pipe must be removed from there or it will be left over.
_subscriptions.rm (pipe_, stub, static_cast<void *> (NULL), false); _subscriptions.rm (pipe_, stub, static_cast<void *> (NULL), false);
// In case the pipe is currently set as last we must clear it to prevent
// subscriptions from being re-added.
if (pipe_ == _last_pipe) {
_last_pipe = NULL;
}
} else { } else {
// Remove the pipe from the trie. If there are topics that nobody // Remove the pipe from the trie. If there are topics that nobody
// is interested in anymore, send corresponding unsubscriptions // is interested in anymore, send corresponding unsubscriptions
@ -348,6 +354,12 @@ int zmq::xpub_t::xrecv (msg_t *msg_)
if (_manual && !_pending_pipes.empty ()) { if (_manual && !_pending_pipes.empty ()) {
_last_pipe = _pending_pipes.front (); _last_pipe = _pending_pipes.front ();
_pending_pipes.pop_front (); _pending_pipes.pop_front ();
// If the distributor doesn't know about this pipe it must have already
// been terminated and thus we can't allow manual subscriptions.
if (_last_pipe != NULL && !_dist.has_pipe (_last_pipe)) {
_last_pipe = NULL;
}
} }
int rc = msg_->close (); int rc = msg_->close ();

View File

@ -35,6 +35,7 @@
#include "err.hpp" #include "err.hpp"
#include "atomic_ptr.hpp" #include "atomic_ptr.hpp"
#include "platform.hpp"
namespace zmq namespace zmq
{ {
@ -50,7 +51,7 @@ namespace zmq
// T is the type of the object in the queue. // T is the type of the object in the queue.
// N is granularity of the queue (how many pushes have to be done till // N is granularity of the queue (how many pushes have to be done till
// actual memory allocation is required). // actual memory allocation is required).
#ifdef HAVE_POSIX_MEMALIGN #if defined HAVE_POSIX_MEMALIGN
// ALIGN is the memory alignment size to use in the case where we have // ALIGN is the memory alignment size to use in the case where we have
// posix_memalign available. Default value is 64, this alignment will // posix_memalign available. Default value is 64, this alignment will
// prevent two queue chunks from occupying the same CPU cache line on // prevent two queue chunks from occupying the same CPU cache line on
@ -181,7 +182,7 @@ template <typename T, int N> class yqueue_t
static inline chunk_t *allocate_chunk () static inline chunk_t *allocate_chunk ()
{ {
#ifdef HAVE_POSIX_MEMALIGN #if defined HAVE_POSIX_MEMALIGN
void *pv; void *pv;
if (posix_memalign (&pv, ALIGN, sizeof (chunk_t)) == 0) if (posix_memalign (&pv, ALIGN, sizeof (chunk_t)) == 0)
return (chunk_t *) pv; return (chunk_t *) pv;

View File

@ -69,11 +69,13 @@
#define ZMQ_HELLO_MSG 110 #define ZMQ_HELLO_MSG 110
#define ZMQ_DISCONNECT_MSG 111 #define ZMQ_DISCONNECT_MSG 111
#define ZMQ_PRIORITY 112 #define ZMQ_PRIORITY 112
#define ZMQ_BUSY_POLL 113
#define ZMQ_HICCUP_MSG 114
/* DRAFT ZMQ_RECONNECT_STOP options */ /* DRAFT ZMQ_RECONNECT_STOP options */
#define ZMQ_RECONNECT_STOP_CONN_REFUSED 0x1 #define ZMQ_RECONNECT_STOP_CONN_REFUSED 0x1
#define ZMQ_RECONNECT_STOP_HANDSHAKE_FAILED 0x2 #define ZMQ_RECONNECT_STOP_HANDSHAKE_FAILED 0x2
#define ZMQ_RECONNECT_STOP_AFTER_DISCONNECT 0x3 #define ZMQ_RECONNECT_STOP_AFTER_DISCONNECT 0x4
/* DRAFT Context options */ /* DRAFT Context options */
#define ZMQ_ZERO_COPY_RECV 10 #define ZMQ_ZERO_COPY_RECV 10

View File

@ -161,7 +161,11 @@ if(ENABLE_DRAFTS)
test_channel test_channel
test_hello_msg test_hello_msg
test_disconnect_msg test_disconnect_msg
test_hiccup_msg
) )
if(ZMQ_HAVE_BUSY_POLL)
list(APPEND tests test_busy_poll)
endif()
endif() endif()
if(ZMQ_HAVE_WS) if(ZMQ_HAVE_WS)

58
vendor/ZMQ/tests/test_busy_poll.cpp vendored Normal file
View File

@ -0,0 +1,58 @@
/*
Copyright (c) 2007-2021 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test_busy_poll ()
{
// Create a socket
void *socket = test_context_socket (ZMQ_DEALER);
// set socket ZMQ_BUSY_POLL options
int busy_poll = 1;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (socket, ZMQ_BUSY_POLL, &busy_poll, sizeof (int)));
// bind socket
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (socket, "tcp://127.0.0.1:*"));
// Clean up.
test_context_socket_close (socket);
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_busy_poll);
return UNITY_END ();
}

76
vendor/ZMQ/tests/test_hiccup_msg.cpp vendored Normal file
View File

@ -0,0 +1,76 @@
/*
Copyright (c) 2007-2021 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test ()
{
char address[MAX_SOCKET_STRING];
size_t addr_length = sizeof (address);
// Create a server
void *server = test_context_socket (ZMQ_SERVER);
// bind server
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (server, "tcp://127.0.0.1:*"));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (server, ZMQ_LAST_ENDPOINT, address, &addr_length));
// Create a client
void *client = test_context_socket (ZMQ_CLIENT);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (client, ZMQ_HELLO_MSG, "HELLO", 5));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (client, ZMQ_HICCUP_MSG, "HICCUP", 6));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, address));
// Receive the hello message from client
recv_string_expect_success (server, "HELLO", 0);
// Kill the server
test_context_socket_close (server);
// Receive the hiccup message
recv_string_expect_success (client, "HICCUP", 0);
// Clean up.
test_context_socket_close (client);
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test);
return UNITY_END ();
}

View File

@ -54,8 +54,9 @@ static void simult_conn (void *endpt_)
// Connect // Connect
// do not use test_context_socket here, as it is not thread-safe // do not use test_context_socket here, as it is not thread-safe
void *connect_socket = zmq_socket (get_test_context (), ZMQ_SUB); void *connect_socket = zmq_socket (get_test_context (), ZMQ_PAIR);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (connect_socket, endpt)); TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (connect_socket, endpt));
recv_string_expect_success (connect_socket, "foobar", 0);
// Cleanup // Cleanup
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (connect_socket)); TEST_ASSERT_SUCCESS_ERRNO (zmq_close (connect_socket));
@ -68,8 +69,9 @@ static void simult_bind (void *endpt_)
// Bind // Bind
// do not use test_context_socket here, as it is not thread-safe // do not use test_context_socket here, as it is not thread-safe
void *bind_socket = zmq_socket (get_test_context (), ZMQ_PUB); void *bind_socket = zmq_socket (get_test_context (), ZMQ_PAIR);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (bind_socket, endpt)); TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (bind_socket, endpt));
send_string_expect_success (bind_socket, "foobar", 0);
// Cleanup // Cleanup
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (bind_socket)); TEST_ASSERT_SUCCESS_ERRNO (zmq_close (bind_socket));

View File

@ -48,10 +48,10 @@ void test_pair_vmci ()
void *sc = test_context_socket (ZMQ_PAIR); void *sc = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, endpoint.c_str ())); TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, endpoint.c_str ()));
bounce (sb, sc); expect_bounce_fail (sb, sc);
test_context_socket_close (sc); test_context_socket_close_zero_linger (sc);
test_context_socket_close (sb); test_context_socket_close_zero_linger (sb);
} }
int main (void) int main (void)

View File

@ -42,16 +42,16 @@ void test_reqrep_vmci ()
s << "vmci://" << VMCISock_GetLocalCID () << ":" << 5560; s << "vmci://" << VMCISock_GetLocalCID () << ":" << 5560;
std::string endpoint = s.str (); std::string endpoint = s.str ();
void *sb = test_context_socket (ZMQ_REP); void *sb = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb, endpoint.c_str ())); TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb, endpoint.c_str ()));
void *sc = test_context_socket (ZMQ_REQ); void *sc = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, endpoint.c_str ())); TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, endpoint.c_str ()));
bounce (sb, sc); expect_bounce_fail (sb, sc);
test_context_socket_close (sc); test_context_socket_close_zero_linger (sc);
test_context_socket_close (sb); test_context_socket_close_zero_linger (sb);
} }
int main (void) int main (void)

View File

@ -41,7 +41,12 @@
// For AF_INET and IPPROTO_TCP // For AF_INET and IPPROTO_TCP
#if defined _WIN32 #if defined _WIN32
#include "../src/windows.hpp" #include "../src/windows.hpp"
#if defined(__MINGW32__)
#include <unistd.h>
#endif
#else #else
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>