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)
if(ENABLE_UBSAN)
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} -fsanitize=undefined")
set(UBSAN_FLAGS "${UBSAN_FLAGS} -fsanitize=implicit-conversion")
@ -118,15 +118,15 @@ endif()
if (NOT MSVC)
if(NOT CMAKE_CXX_FLAGS MATCHES "-std=")
# 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)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
endif()
endif()
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)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu11")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11")
else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99")
endif()
@ -156,19 +156,19 @@ if(APPLE)
endif()
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)
else()
message(STATUS "Not building draft classes and methods")
option(ENABLE_DRAFTS "Build and install draft classes and methods" OFF)
endif()
# Enable WebSocket transport and RadixTree
if(ENABLE_DRAFTS)
message(STATUS "Building draft classes and methods")
set(ZMQ_BUILD_DRAFT_API 1)
option(ENABLE_WS "Enable WebSocket transport" ON)
option(ENABLE_RADIX_TREE "Use radix tree implementation to manage subscriptions" ON)
else()
message(STATUS "Not building draft classes and methods")
option(ENABLE_WS "Enable WebSocket transport" OFF)
option(ENABLE_RADIX_TREE "Use radix tree implementation to manage subscriptions" OFF)
endif()
@ -263,15 +263,11 @@ endif()
option(WITH_LIBSODIUM "Use libsodium instead of built-in tweetnacl" ON)
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)
if(ENABLE_CURVE)
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")
if(SODIUM_FOUND)
message(STATUS "Using libsodium for CURVE security")
@ -281,6 +277,9 @@ if(ENABLE_CURVE)
endif()
set(ZMQ_USE_LIBSODIUM 1)
set(ZMQ_HAVE_CURVE 1)
if (ENABLE_LIBSODIUM_RANDOMBYTES_CLOSE)
set(ZMQ_LIBSODIUM_RANDOMBYTES_CLOSE 1)
endif()
else()
message(
WARNING
@ -474,6 +473,7 @@ message(STATUS "Using polling method in zmq_poll(er)_* API: ${API_POLLER}")
string(TOUPPER ${API_POLLER} UPPER_API_POLLER)
set(ZMQ_POLL_BASED_ON_${UPPER_API_POLLER} 1)
# special alignment settings
execute_process(
COMMAND getconf LEVEL1_DCACHE_LINESIZE
OUTPUT_VARIABLE CACHELINE_SIZE
@ -486,6 +486,7 @@ else()
set(ZMQ_CACHELINE_SIZE ${CACHELINE_SIZE})
endif()
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)
# 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(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(SO_BUSY_POLL sys/socket.h ZMQ_HAVE_BUSY_POLL)
endif()
if(NOT MINGW)

View File

@ -1024,19 +1024,19 @@ endif
endif
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
test_pair_vmci_LDADD = ${TESTUTIL_LIBS} src/libzmq.la
test_pair_vmci_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
test_pair_vmci_LDFLAGS = @LIBZMQ_VMCI_LDFLAGS@
test_pair_vmci_CXXFLAGS = @LIBZMQ_VMCI_CXXFLAGS@
tests_test_pair_vmci_SOURCES = tests/test_pair_vmci.cpp
tests_test_pair_vmci_LDADD = ${TESTUTIL_LIBS} src/libzmq.la
tests_test_pair_vmci_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_pair_vmci_LDFLAGS = @LIBZMQ_VMCI_LDFLAGS@
tests_test_pair_vmci_CXXFLAGS = @LIBZMQ_VMCI_CXXFLAGS@
test_reqrep_vmci_SOURCES = tests/test_reqrep_vmci.cpp
test_reqrep_vmci_LDADD = ${TESTUTIL_LIBS} src/libzmq.la
test_reqrep_vmci_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
test_reqrep_vmci_LDFLAGS = @LIBZMQ_VMCI_LDFLAGS@
test_reqrep_vmci_CXXFLAGS = @LIBZMQ_VMCI_CXXFLAGS@
tests_test_reqrep_vmci_SOURCES = tests/test_reqrep_vmci.cpp
tests_test_reqrep_vmci_LDADD = ${TESTUTIL_LIBS} src/libzmq.la
tests_test_reqrep_vmci_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_reqrep_vmci_LDFLAGS = @LIBZMQ_VMCI_LDFLAGS@
tests_test_reqrep_vmci_CXXFLAGS = @LIBZMQ_VMCI_CXXFLAGS@
endif
@ -1056,7 +1056,8 @@ test_apps += tests/test_poller \
tests/test_msg_init \
tests/test_hello_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_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_LDADD = ${TESTUTIL_LIBS} src/libzmq.la
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
if FUZZING_ENGINE_LIB

View File

@ -1,6 +1,6 @@
# 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)
[![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
zmq_cacheline_size=$(cat /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size 2>/dev/null || echo 64)
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
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])

View File

@ -175,11 +175,15 @@ install:
- cmd: echo "Generator='%CMAKE_GENERATOR%'"
- cmd: echo "Platform='%Platform%'"
- 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" (
if not exist "%LIBSODIUMDIR%" (
git clone --branch stable --depth 1 --quiet "https://github.com/jedisct1/libsodium.git" %LIBSODIUMDIR%
) 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
@ -272,18 +276,18 @@ test_script:
- cmd: if "%APPVEYOR_REPO_TAG%"=="false" (ctest -C "%Configuration%" -V %TEST_OPTIONS%)
deploy:
- provider: BinTray
username: somdoron
api_key:
secure: B4TC4GvUMbwX13Skh2Kvyc6SnqLkjNS9W0gtN2yxUC2Y4oQSCK2F4eRgtpMpCasg
subject: zeromq
repo: generic
package: libzmq
publish: true
override: true
version: ${ZMQ_VERSION}
on:
APPVEYOR_REPO_TAG: true
- provider: GitHub
tag: $(APPVEYOR_REPO_TAG_NAME)
release: libzmq $(APPVEYOR_REPO_TAG_NAME)
description: |
Windows binaries for libzmq $(APPVEYOR_REPO_TAG_NAME), uploaded from appveyor.
Edit after appveyor is done uploading.
auth_token:
secure: vmAeVtN2qiQgFBCB2I5FDDRtADQ7GUdR9NwAJJyakbiV5OHzLHExDcC/D9Oh5r67
draft: true
prerelease: false
force_update: true # adds files, clobbers release name and description
# the analysis build is repeated; apparently appveyor only uses the first section that matches some branch
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.
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:
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
well as the NDK version, e.g:

View File

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

View File

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

View File

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

View File

@ -84,7 +84,9 @@ do
--prefix=${BUILDARCHDIR} \
--disable-shared \
--enable-static \
--host=${HOST}
--host=${HOST} \
--disable-perf \
--disable-curve-keygen
echo "Building ${LIBNAME} for ${ARCH}..."
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
CONFIG_OPTS+=("--enable-force-CXX98-compat=yes")
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.
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
AX_CODE_COVERAGE
AM_PROG_CC_C_O
@ -550,6 +550,20 @@ AS_IF([test "x$with_libsodium" = "xyes"], [
AC_ARG_ENABLE([curve],
[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
curve_library=""
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_DEFINE(ZMQ_HAVE_CURVE, [1], [Using 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"
enable_curve="yes"

View File

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

View File

@ -87,6 +87,21 @@ Default value:: not set
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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This option name is now deprecated. Use ZMQ_CONNECT_ROUTING_ID instead.
@ -241,6 +256,21 @@ Option value unit:: N/A
Default value:: NULL
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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Defines whether communications on the socket will be encrypted, see

View File

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

View File

@ -57,21 +57,6 @@ extern "C" {
#endif
#include <stddef.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 */
#if defined _WIN32
@ -683,11 +668,13 @@ ZMQ_EXPORT void zmq_threadclose (void *thread_);
#define ZMQ_HELLO_MSG 110
#define ZMQ_DISCONNECT_MSG 111
#define ZMQ_PRIORITY 112
#define ZMQ_BUSY_POLL 113
#define ZMQ_HICCUP_MSG 114
/* DRAFT ZMQ_RECONNECT_STOP options */
#define ZMQ_RECONNECT_STOP_CONN_REFUSED 0x1
#define ZMQ_RECONNECT_STOP_HANDSHAKE_FAILED 0x2
#define ZMQ_RECONNECT_STOP_AFTER_DISCONNECT 0x3
#define ZMQ_RECONNECT_STOP_AFTER_DISCONNECT 0x4
/* DRAFT Context options */
#define ZMQ_ZERO_COPY_RECV 10

View File

@ -13,8 +13,8 @@ Name: zeromq
Version: 4.3.5
Release: 1%{?dist}
Summary: The ZeroMQ messaging library
Group: Applications/Internet
License: LGPLv3+
Group: Development/Libraries/C and C++
License: LGPL-3.0-or-later
URL: http://www.zeromq.org/
Source: http://download.zeromq.org/%{name}-%{version}.tar.gz
Prefix: %{_prefix}
@ -228,11 +228,12 @@ autoreconf -fi
%{__make} %{?_smp_mflags}
%check
%{__make} check VERBOSE=1
%install
[ "%{buildroot}" != "/" ] && %{__rm} -rf %{buildroot}
# Install the package to build area
%{__make} check VERBOSE=1
%makeinstall
%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.can_send_hello_msg = true;
options.can_recv_hiccup_msg = true;
}
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 ();
#endif
#ifndef ZMQ_HAVE_WINDOWS
const uint64_t usecs_per_msec = 1000;
const uint64_t usecs_per_sec = 1000000;
const uint64_t nsecs_per_usec = 1000;
#endif
const uint64_t usecs_per_sec = 1000000;
zmq::clock_t::clock_t () :
_last_tsc (rdtsc ()),
@ -193,6 +195,7 @@ uint64_t zmq::clock_t::now_us ()
#else
LIBZMQ_UNUSED (nsecs_per_usec);
// Use POSIX gettimeofday function to get precise time.
struct timeval tv;
int rc = gettimeofday (&tv, NULL);

View File

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

View File

@ -180,6 +180,12 @@ struct curve_client_tools_t
// Create Box [C + vouch + metadata](C'->S')
std::fill (initiate_plaintext.begin (),
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 + 32], vouch_nonce + 8,
16);
@ -189,6 +195,10 @@ struct curve_client_tools_t
memcpy (&initiate_plaintext[crypto_box_ZEROBYTES + 48 + 80],
metadata_plaintext_, metadata_length_);
}
#if __GNUC__ >= 11
#pragma GCC diagnostic pop
#pragma GCC diagnostic pop
#endif
memcpy (initiate_nonce, "CurveZMQINITIATE", 16);
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.can_send_hello_msg = true;
options.can_recv_hiccup_msg = true;
}
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_) :
socket_base_t (parent_, tid_, sid_),
_pipe (NULL),
_last_in (NULL),
_more_out (false)
{
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_)
{
if (pipe_ == _pipe) {
if (_last_in == _pipe) {
_last_in = NULL;
}
_pipe = NULL;
}
}
@ -147,7 +143,6 @@ int zmq::dgram_t::xrecv (msg_t *msg_)
errno = EAGAIN;
return -1;
}
_last_in = _pipe;
return 0;
}

View File

@ -62,8 +62,6 @@ class dgram_t ZMQ_FINAL : public socket_base_t
private:
zmq::pipe_t *_pipe;
zmq::pipe_t *_last_in;
// If true, more outgoing message parts are expected.
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_)
{
// If pipe is already matching do nothing.

View File

@ -51,6 +51,9 @@ class dist_t
// Adds the pipe to the distributor object.
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.
void activated (zmq::pipe_t *pipe_);

View File

@ -131,7 +131,7 @@ void zmq::epoll_t::reset_pollin (handle_t handle_)
{
check_thread ();
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);
errno_assert (rc != -1);
}
@ -149,7 +149,7 @@ void zmq::epoll_t::reset_pollout (handle_t handle_)
{
check_thread ();
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);
errno_assert (rc != -1);
}

View File

@ -33,7 +33,7 @@
#include "err.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;
}
_pipes.erase (pipe_);
if (_last_in == pipe_) {
_last_in = NULL;
}
}
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];
_more = (msg_->flags () & msg_t::more) != 0;
if (!_more) {
_last_in = _pipes[_current];
_current = (_current + 1) % _active;
}
return 0;

View File

@ -65,11 +65,6 @@ class fq_t
// beginning of the pipes array.
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.
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
#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_)
{
#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);
}
// TODO or use CreateDirectoryA and specify permissions?
const int rc = _mkdir (buffer);
const int rc = _wmkdir (buffer);
if (rc != 0) {
return -1;
}
path_.assign (buffer);
char *tmp = widechar_to_utf8 (buffer);
if (tmp == 0) {
return -1;
}
path_.assign (tmp);
file_ = path_ + "/socket";
free (tmp);
#else
std::string tmp_path;

View File

@ -35,7 +35,7 @@
// 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"

View File

@ -254,7 +254,10 @@ zmq::options_t::options_t () :
hello_msg (),
can_send_hello_msg (false),
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_secret_key, 0, CURVE_KEYSIZE);
@ -802,6 +805,12 @@ int zmq::options_t::setsockopt (int option_,
}
break;
case ZMQ_BUSY_POLL:
if (is_int) {
busy_poll = value;
return 0;
}
break;
#ifdef ZMQ_HAVE_WSS
case ZMQ_WSS_KEY_PEM:
// TODO: check if valid certificate
@ -852,6 +861,18 @@ int zmq::options_t::setsockopt (int option_,
}
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
default:
@ -1285,6 +1306,12 @@ int zmq::options_t::getsockopt (int option_,
return 0;
}
break;
case ZMQ_BUSY_POLL:
if (is_int) {
*value = busy_poll;
}
break;
#endif

View File

@ -308,6 +308,13 @@ struct options_t
// Disconnect msg
std::vector<unsigned char> 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)

View File

@ -36,8 +36,7 @@
zmq::pair_t::pair_t (class ctx_t *parent_, uint32_t tid_, int sid_) :
socket_base_t (parent_, tid_, sid_),
_pipe (NULL),
_last_in (NULL)
_pipe (NULL)
{
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_)
{
if (pipe_ == _pipe) {
if (_last_in == _pipe) {
_last_in = NULL;
}
_pipe = NULL;
}
}
@ -117,7 +113,6 @@ int zmq::pair_t::xrecv (msg_t *msg_)
errno = EAGAIN;
return -1;
}
_last_in = _pipe;
return 0;
}

View File

@ -62,8 +62,6 @@ class pair_t ZMQ_FINAL : public socket_base_t
private:
zmq::pipe_t *_pipe;
zmq::pipe_t *_last_in;
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.can_send_hello_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_)

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 ()
{
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 ();
@ -615,3 +615,15 @@ void zmq::pipe_t::set_disconnect_msg (
_disconnect_msg.init_buffer (&disconnect_[0], disconnect_.size ());
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 set_disconnect_msg (const std::vector<unsigned char> &disconnect_);
void send_hiccup_msg (const std::vector<unsigned char> &hiccup_);
private:
// Type of the underlying lock-free pipe.
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_)
{
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
alloc_assert (_buf);
} else {
@ -59,7 +59,7 @@ template <typename T, size_t S> class fast_vector_t
~fast_vector_t ()
{
if (_buf != _static_buf)
free (_buf);
delete[] _buf;
}
private:
@ -109,9 +109,9 @@ timeout_t
compute_timeout (bool first_pass_, long timeout_, uint64_t now_, uint64_t end_);
#elif defined ZMQ_POLL_BASED_ON_SELECT
#if defined ZMQ_HAVE_WINDOWS
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.
// SOCKETS are continuous from the beginning of fd_array in fd_set.
// 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 *> (
&pollset_.fd_array[pollset_.fd_count])
- 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
// 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) {
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 (

View File

@ -151,8 +151,13 @@ static void manage_random (bool init_)
if (init_) {
int rc = sodium_init ();
zmq_assert (rc != -1);
#if defined(ZMQ_LIBSODIUM_RANDOMBYTES_CLOSE)
} 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 ();
#endif
}
#else
LIBZMQ_UNUSED (init_);

View File

@ -460,14 +460,18 @@ void zmq::session_base_t::engine_error (bool handshaked_,
if (_pipe) {
clean_pipes ();
#ifdef ZMQ_BUILD_DRAFT_API
// Only send disconnect message if socket was accepted and handshake was completed
if (!_active && handshaked_ && options.can_recv_disconnect_msg
&& !options.disconnect_msg.empty ()) {
_pipe->set_disconnect_msg (options.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

View File

@ -341,6 +341,21 @@ void zmq::tcp_tune_loopback_fast_path (const fd_t socket_)
#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_,
const zmq::options_t &options_,
bool local_,
@ -398,6 +413,9 @@ zmq::fd_t zmq::tcp_open_socket (const char *address_,
if (options_.rcvbuf >= 0)
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;
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 tune_tcp_busy_poll (fd_t socket_, int busy_poll_);
// Resolves the given address_ string, opens a socket and sets socket options
// according to the passed options_. On success, returns the socket
// descriptor and assigns the resolved address to out_tcp_addr_. In case of

View File

@ -28,7 +28,9 @@
*/
#include "precompiled.hpp"
#include "ip.hpp"
#include "vmci.hpp"
#include "vmci_address.hpp"
#if defined ZMQ_HAVE_VMCI
@ -97,4 +99,23 @@ void zmq::tune_vmci_connect_timeout (ctx_t *context_,
#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

View File

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

View File

@ -39,6 +39,11 @@
#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_)
{
memset (&address, 0, sizeof address);
@ -56,10 +61,6 @@ zmq::vmci_address_t::vmci_address_t (const sockaddr *sa,
memcpy (&address, sa, sa_len);
}
zmq::vmci_address_t::~vmci_address_t ()
{
}
int zmq::vmci_address_t::resolve (const char *path_)
{
// 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;
}
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 ()) {
addr_.clear ();
@ -164,4 +165,13 @@ socklen_t zmq::vmci_address_t::addrlen () const
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

View File

@ -43,16 +43,21 @@ namespace zmq
class vmci_address_t
{
public:
vmci_address_t ();
vmci_address_t (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.
int resolve (const char *path_);
// 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;
socklen_t addrlen () const;
@ -60,8 +65,6 @@ class vmci_address_t
struct sockaddr_vm address;
ctx_t *parent;
vmci_address_t ();
ZMQ_NON_COPYABLE_NOR_MOVABLE (vmci_address_t)
};
}

View File

@ -35,69 +35,41 @@
#include <new>
#include "stream_engine.hpp"
#include "io_thread.hpp"
#include "platform.hpp"
#include "random.hpp"
#include "err.hpp"
#include "ip.hpp"
#include "address.hpp"
#include "session_base.hpp"
#include "vmci_address.hpp"
#include "vmci.hpp"
#include "session_base.hpp"
zmq::vmci_connecter_t::vmci_connecter_t (class io_thread_t *io_thread_,
class session_base_t *session_,
const options_t &options_,
const address_t *addr_,
address_t *addr_,
bool delayed_start_) :
own_t (io_thread_, options_),
io_object_t (io_thread_),
addr (addr_),
s (retired_fd),
handle_valid (false),
delayed_start (delayed_start_),
timer_started (false),
session (session_),
current_reconnect_ivl (options.reconnect_ivl)
stream_connecter_base_t (
io_thread_, session_, options_, addr_, delayed_start_),
_connect_timer_started (false)
{
zmq_assert (addr);
zmq_assert (addr->protocol == "vmci");
addr->to_string (endpoint);
socket = session->get_socket ();
zmq_assert (_addr->protocol == protocol_name::vmci);
}
zmq::vmci_connecter_t::~vmci_connecter_t ()
{
zmq_assert (!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 ();
zmq_assert (!_connect_timer_started);
}
void zmq::vmci_connecter_t::process_term (int linger_)
{
if (timer_started) {
cancel_timer (reconnect_timer_id);
timer_started = false;
if (_connect_timer_started) {
cancel_timer (connect_timer_id);
_connect_timer_started = false;
}
if (handle_valid) {
rm_fd (handle);
handle_valid = false;
}
if (s != retired_fd)
close ();
own_t::process_term (linger_);
stream_connecter_base_t::process_term (linger_);
}
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 ()
{
fd_t fd = connect ();
rm_fd (handle);
handle_valid = false;
if (_connect_timer_started) {
cancel_timer (connect_timer_id);
_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.
if (fd == retired_fd) {
@ -135,148 +124,154 @@ void zmq::vmci_connecter_t::out_event ()
#endif
}
// Create the engine object for this connection.
stream_engine_t *engine = new (std::nothrow) stream_engine_t (
fd, options, make_unconnected_bind_endpoint_pair (endpoint));
alloc_assert (engine);
create_engine (
fd, zmq::vmci_connecter_t::get_socket_name (fd, socket_end_local));
}
// Attach the engine to the corresponding session object.
send_attach (session, engine);
std::string
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.
terminate ();
socket->event_connected (make_unconnected_bind_endpoint_pair (endpoint),
fd);
const vmci_address_t addr (reinterpret_cast<struct sockaddr *> (&ss), sl,
this->get_ctx ());
std::string address_string;
addr.to_string (address_string);
return address_string;
}
void zmq::vmci_connecter_t::timer_event (int id_)
{
zmq_assert (id_ == reconnect_timer_id);
timer_started = false;
start_connecting ();
if (id_ == connect_timer_id) {
_connect_timer_started = false;
rm_handle ();
close ();
add_reconnect_timer ();
} else
stream_connecter_base_t::timer_event (id_);
}
void zmq::vmci_connecter_t::start_connecting ()
{
// Open the connecting socket.
int rc = open ();
const int rc = open ();
// Connect may succeed in synchronous manner.
if (rc == 0) {
handle = add_fd (s);
handle_valid = true;
_handle = add_fd (_s);
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.
else {
if (s != retired_fd)
if (_s != retired_fd)
close ();
add_reconnect_timer ();
}
}
void zmq::vmci_connecter_t::add_reconnect_timer ()
void zmq::vmci_connecter_t::add_connect_timer ()
{
if (options.reconnect_ivl > 0) {
int rc_ivl = get_new_reconnect_ivl ();
add_timer (rc_ivl, reconnect_timer_id);
socket->event_connect_retried (
make_unconnected_bind_endpoint_pair (endpoint), rc_ivl);
timer_started = true;
if (options.connect_timeout > 0) {
add_timer (options.connect_timeout, connect_timer_id);
_connect_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 ()
{
zmq_assert (s == retired_fd);
zmq_assert (_s == retired_fd);
int family = this->get_ctx ()->get_vmci_socket_family ();
if (family == -1)
return -1;
// Resolve the address
if (_addr->resolved.vmci_addr != NULL) {
LIBZMQ_DELETE (_addr->resolved.vmci_addr);
}
// Create the socket.
s = open_socket (family, SOCK_STREAM, 0);
#ifdef ZMQ_HAVE_WINDOWS
if (s == INVALID_SOCKET) {
errno = wsa_error_to_errno (WSAGetLastError ());
_addr->resolved.vmci_addr =
new (std::nothrow) vmci_address_t (this->get_ctx ());
alloc_assert (_addr->resolved.vmci_addr);
_s = vmci_open_socket (_addr->address.c_str (), options,
_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;
}
#else
if (s == -1)
return -1;
#endif
zmq_assert (_addr->resolved.vmci_addr != NULL);
// Set the socket to non-blocking mode so that we get async connect().
unblock_socket (_s);
const vmci_address_t *const vmci_addr = _addr->resolved.vmci_addr;
int rc;
// Connect to the remote peer.
int rc = ::connect (s, addr->resolved.vmci_addr->addr (),
addr->resolved.vmci_addr->addrlen ());
#if defined ZMQ_HAVE_VXWORKS
rc = ::connect (_s, (sockaddr *) vmci_addr->addr (), vmci_addr->addrlen ());
#else
rc = ::connect (_s, vmci_addr->addr (), vmci_addr->addrlen ());
#endif
// Connect was successful immediately.
if (rc == 0)
if (rc == 0) {
return 0;
// Forward the error.
return -1;
}
void zmq::vmci_connecter_t::close ()
{
zmq_assert (s != retired_fd);
// Translate error codes indicating asynchronous connect has been
// launched to a uniform EINPROGRESS.
#ifdef ZMQ_HAVE_WINDOWS
const int rc = closesocket (s);
wsa_assert (rc != SOCKET_ERROR);
const int last_error = WSAGetLastError ();
if (last_error == WSAEINPROGRESS || last_error == WSAEWOULDBLOCK)
errno = EINPROGRESS;
else
errno = wsa_error_to_errno (last_error);
#else
const int rc = ::close (s);
errno_assert (rc == 0);
if (errno == EINTR)
errno = EINPROGRESS;
#endif
socket->event_closed (make_unconnected_bind_endpoint_pair (endpoint), s);
s = retired_fd;
return -1;
}
zmq::fd_t zmq::vmci_connecter_t::connect ()
{
// Following code should handle both Berkeley-derived socket
// implementations and Solaris.
// Async connect has finished. Check whether an error occurred
int err = 0;
#if defined ZMQ_HAVE_HPUX
int len = sizeof (err);
#if defined ZMQ_HAVE_HPUX || defined ZMQ_HAVE_VXWORKS
int len = sizeof err;
#else
socklen_t len = sizeof (err);
socklen_t len = sizeof err;
#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.
// Networking problems are OK. No need to assert.
#ifdef ZMQ_HAVE_WINDOWS
zmq_assert (rc == 0);
if (err != 0) {
if (err != WSAECONNREFUSED && err != WSAETIMEDOUT
&& err != WSAECONNABORTED && err != WSAEHOSTUNREACH
&& err != WSAENETUNREACH && err != WSAENETDOWN && err != WSAEACCES
&& err != WSAEINVAL && err != WSAEADDRINUSE
&& err != WSAECONNRESET) {
if (err == WSAEBADF || err == WSAENOPROTOOPT || err == WSAENOTSOCK
|| err == WSAENOBUFS) {
wsa_assert_no (err);
}
errno = wsa_error_to_errno (err);
return retired_fd;
}
#else
@ -286,16 +281,20 @@ zmq::fd_t zmq::vmci_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 == EINVAL);
#if !defined(TARGET_OS_IPHONE) || !TARGET_OS_IPHONE
errno_assert (errno != EBADF && errno != ENOPROTOOPT
&& errno != ENOTSOCK && errno != ENOBUFS);
#else
errno_assert (errno != ENOPROTOOPT && errno != ENOTSOCK
&& errno != ENOBUFS);
#endif
return retired_fd;
}
#endif
fd_t result = s;
s = retired_fd;
// Return the newly connected socket.
const fd_t result = _s;
_s = retired_fd;
return result;
}

View File

@ -38,6 +38,7 @@
#include "own.hpp"
#include "stdint.hpp"
#include "io_object.hpp"
#include "stream_connecter_base.hpp"
namespace zmq
{
@ -45,8 +46,7 @@ class io_thread_t;
class session_base_t;
struct address_t;
// TODO consider refactoring this to derive from stream_connecter_base_t
class vmci_connecter_t ZMQ_FINAL : public own_t, public io_object_t
class vmci_connecter_t ZMQ_FINAL : public stream_connecter_base_t
{
public:
// 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_,
zmq::session_base_t *session_,
const options_t &options_,
const address_t *addr_,
address_t *addr_,
bool delayed_start_);
~vmci_connecter_t ();
protected:
std::string get_socket_name (fd_t fd_, socket_end_t socket_end_) const;
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
{
reconnect_timer_id = 1
connect_timer_id = 2
};
// Handlers for incoming commands.
void process_plug ();
void process_term (int linger_);
// 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.
void start_connecting ();
// Internal function to add a reconnect timer
void add_reconnect_timer ();
// Internal function to add a connect timer
void add_connect_timer ();
// Internal function to return a reconnect backoff delay.
// 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.
int open ();
// Close the connecting socket.
void close ();
// Get the file descriptor of newly created connection. Returns
// retired_fd if the connection was unsuccessful.
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.
bool 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;
bool _connect_timer_started;
ZMQ_NON_COPYABLE_NOR_MOVABLE (vmci_connecter_t)
};

View File

@ -35,7 +35,7 @@
#include <new>
#include "stream_engine.hpp"
//#include "stream_engine.hpp"
#include "vmci_address.hpp"
#include "io_thread.hpp"
#include "session_base.hpp"
@ -55,40 +55,18 @@
zmq::vmci_listener_t::vmci_listener_t (io_thread_t *io_thread_,
socket_base_t *socket_,
const options_t &options_) :
own_t (io_thread_, options_),
io_object_t (io_thread_),
s (retired_fd),
socket (socket_)
stream_listener_base_t (io_thread_, socket_, options_)
{
}
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 ()
{
fd_t fd = accept ();
// If connection was reset by the peer in the meantime, just ignore it.
if (fd == retired_fd) {
socket->event_accept_failed (
make_unconnected_bind_endpoint_pair (endpoint), zmq_errno ());
_socket->event_accept_failed (
make_unconnected_bind_endpoint_pair (_endpoint), zmq_errno ());
return;
}
@ -107,41 +85,24 @@ void zmq::vmci_listener_t::in_event ()
}
// Create the engine object for this connection.
stream_engine_t *engine = new (std::nothrow) stream_engine_t (
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);
create_engine (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;
#ifdef ZMQ_HAVE_HPUX
int sl = sizeof (ss);
#else
socklen_t sl = sizeof (ss);
#endif
int rc = getsockname (s, (sockaddr *) &ss, &sl);
if (rc != 0) {
addr_.clear ();
return rc;
const zmq_socklen_t sl = get_socket_address (fd_, socket_end_, &ss);
if (sl == 0) {
return std::string ();
}
vmci_address_t addr ((struct sockaddr *) &ss, sl, this->get_ctx ());
return addr.to_string (addr_);
const vmci_address_t addr (reinterpret_cast<struct sockaddr *> (&ss), sl,
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_)
@ -156,7 +117,7 @@ int zmq::vmci_listener_t::set_local_address (const char *addr_)
return -1;
// Create a listening socket.
s =
_s =
open_socket (this->get_ctx ()->get_vmci_socket_family (), SOCK_STREAM, 0);
#ifdef ZMQ_HAVE_WINDOWS
if (s == INVALID_SOCKET) {
@ -165,18 +126,18 @@ int zmq::vmci_listener_t::set_local_address (const char *addr_)
}
#if !defined _WIN32_WCE
// 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);
#endif
#else
if (s == -1)
if (_s == -1)
return -1;
#endif
address.to_string (endpoint);
address.to_string (_endpoint);
// Bind the socket.
rc = bind (s, address.addr (), address.addrlen ());
rc = bind (_s, address.addr (), address.addrlen ());
#ifdef ZMQ_HAVE_WINDOWS
if (rc == SOCKET_ERROR) {
errno = wsa_error_to_errno (WSAGetLastError ());
@ -188,7 +149,7 @@ int zmq::vmci_listener_t::set_local_address (const char *addr_)
#endif
// Listen for incoming connections.
rc = listen (s, options.backlog);
rc = listen (_s, options.backlog);
#ifdef ZMQ_HAVE_WINDOWS
if (rc == SOCKET_ERROR) {
errno = wsa_error_to_errno (WSAGetLastError ());
@ -199,7 +160,8 @@ int zmq::vmci_listener_t::set_local_address (const char *addr_)
goto error;
#endif
socket->event_listening (make_unconnected_bind_endpoint_pair (endpoint), s);
_socket->event_listening (make_unconnected_bind_endpoint_pair (_endpoint),
_s);
return 0;
error:
@ -209,27 +171,13 @@ error:
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 ()
{
// Accept one connection and deal with different failure modes.
// The situation where connection cannot be accepted due to insufficient
// resources is considered valid and treated by ignoring the connection.
zmq_assert (s != retired_fd);
fd_t sock = ::accept (s, NULL, NULL);
zmq_assert (_s != retired_fd);
fd_t sock = ::accept (_s, NULL, NULL);
#ifdef ZMQ_HAVE_WINDOWS
if (sock == INVALID_SOCKET) {

View File

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

View File

@ -454,7 +454,8 @@ bool zmq::ws_engine_t::server_handshake ()
_header_upgrade_websocket =
strcasecmp ("websocket", _header_value) == 0;
else if (strcasecmp ("connection", _header_name) == 0) {
char *element = strtok (_header_value, ",");
char *rest = NULL;
char *element = strtok_r (_header_value, ",", &rest);
while (element != NULL) {
while (*element == ' ')
element++;
@ -462,10 +463,9 @@ bool zmq::ws_engine_t::server_handshake ()
_header_connection_upgrade = true;
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)
strcpy_s (_websocket_key, _header_value);
else if (strcasecmp ("Sec-WebSocket-Protocol", _header_name)
@ -474,7 +474,7 @@ bool zmq::ws_engine_t::server_handshake ()
// 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[0] == '\0') {
char *rest = 0;
char *rest = NULL;
char *p = strtok_r (_header_value, ",", &rest);
while (p != NULL) {
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,
// so the pipe must be removed from there or it will be left over.
_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 {
// Remove the pipe from the trie. If there are topics that nobody
// is interested in anymore, send corresponding unsubscriptions
@ -348,6 +354,12 @@ int zmq::xpub_t::xrecv (msg_t *msg_)
if (_manual && !_pending_pipes.empty ()) {
_last_pipe = _pending_pipes.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 ();

View File

@ -35,6 +35,7 @@
#include "err.hpp"
#include "atomic_ptr.hpp"
#include "platform.hpp"
namespace zmq
{
@ -50,7 +51,7 @@ namespace zmq
// T is the type of the object in the queue.
// N is granularity of the queue (how many pushes have to be done till
// 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
// posix_memalign available. Default value is 64, this alignment will
// 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 ()
{
#ifdef HAVE_POSIX_MEMALIGN
#if defined HAVE_POSIX_MEMALIGN
void *pv;
if (posix_memalign (&pv, ALIGN, sizeof (chunk_t)) == 0)
return (chunk_t *) pv;

View File

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

View File

@ -161,7 +161,11 @@ if(ENABLE_DRAFTS)
test_channel
test_hello_msg
test_disconnect_msg
test_hiccup_msg
)
if(ZMQ_HAVE_BUSY_POLL)
list(APPEND tests test_busy_poll)
endif()
endif()
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
// 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));
recv_string_expect_success (connect_socket, "foobar", 0);
// Cleanup
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (connect_socket));
@ -68,8 +69,9 @@ static void simult_bind (void *endpt_)
// Bind
// 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));
send_string_expect_success (bind_socket, "foobar", 0);
// Cleanup
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);
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 (sb);
test_context_socket_close_zero_linger (sc);
test_context_socket_close_zero_linger (sb);
}
int main (void)

View File

@ -42,16 +42,16 @@ void test_reqrep_vmci ()
s << "vmci://" << VMCISock_GetLocalCID () << ":" << 5560;
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 ()));
void *sc = test_context_socket (ZMQ_REQ);
void *sc = test_context_socket (ZMQ_DEALER);
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 (sb);
test_context_socket_close_zero_linger (sc);
test_context_socket_close_zero_linger (sb);
}
int main (void)

View File

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