diff --git a/CMakeLists.txt b/CMakeLists.txt
index 626935f851..5826aec8ba 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -61,7 +61,6 @@ include(GroupSources)
include(AutoCollect)
find_package(PCHSupport)
-find_package(ZMQ REQUIRED)
find_package(MySQL)
if(NOT WITHOUT_GIT)
diff --git a/cmake/macros/FindZMQ.cmake b/cmake/macros/FindZMQ.cmake
deleted file mode 100644
index b86f5bd1a0..0000000000
--- a/cmake/macros/FindZMQ.cmake
+++ /dev/null
@@ -1,88 +0,0 @@
-#
-# Find the ZMQ includes and library
-#
-
-# This module defines
-# ZMQ_INCLUDE_DIR, where to find zmq.h
-# ZMQ_LIBRARY, the library needed to use ZMQ
-# ZMQ_FOUND, if false, you cannot build anything that requires ZMQ.
-
-set(ZMQ_FOUND 0)
-
-if (PLATFORM EQUAL 64)
- set(ZMQ_REGISTRY_PATH
- "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ZeroMQ (x64);DisplayIcon]"
- )
-else()
- set(ZMQ_REGISTRY_PATH
- "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ZeroMQ;DisplayIcon]"
- "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ZeroMQ;DisplayIcon]"
- )
-endif()
-
-find_path(ZMQ_ROOT_DIR
- NAMES
- include/zmq.h
- HINTS
- ${ZMQ_REGISTRY_PATH}
- PATHS
- /usr
- /usr/local
-)
-
-find_path(ZMQ_INCLUDE_DIR zmq.h ${ZMQ_ROOT_DIR}/include)
-
-if (MSVC)
- # Read registry key holding version
- if (PLATFORM EQUAL 64)
- get_filename_component(ZMQ_NAME "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ZeroMQ (x64);DisplayVersion]" NAME)
- else()
- get_filename_component(ZMQ_NAME "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ZeroMQ;DisplayVersion]" NAME)
- if (${ZMQ_NAME} MATCHES "registry") # if key was not found, the string "registry" is returned
- get_filename_component(ZMQ_NAME "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ZeroMQ;DisplayVersion]" NAME)
- endif()
- endif()
-
- # Replace dots with underscores
- string(REGEX REPLACE "\\." "_" ZMQ_NAME ${ZMQ_NAME})
-
- # Get Visual studio version number
- set(_VS_VERSIONS "140" "120")
-
- if (${ZMQ_NAME} MATCHES "registry") # if key was not found, the string "registry" is returned
- set(_ZMQ_VERSIONS "4_0_4" "4_0_3" "4_0_2" "4_0_1" "4_0_0" "3_2_5" "3_2_4" "3_2_3" "3_2_2" "3_2_1" "3_2_0" "3_1_0")
- set(ZMQ_LIBRARY_NAME)
- foreach(ver ${_ZMQ_VERSIONS})
- foreach(vs ${_VS_VERSIONS})
- list(APPEND ZMQ_LIBRARY_NAME "libzmq-v${vs}-mt-${ver}")
- endforeach()
- endforeach()
- else()
- # Format ZMQ library file name
- foreach(vs ${_VS_VERSIONS})
- set(ZMQ_LIBRARY_NAME "libzmq-v${vs}-mt-${ZMQ_NAME}")
- endforeach()
- endif()
-endif()
-
-find_library(ZMQ_LIBRARY
- NAMES
- zmq
- ${ZMQ_LIBRARY_NAME}
- PATHS
- /lib
- /usr/lib
- /usr/local/lib
- "${ZMQ_ROOT_DIR}/lib"
-)
-
-if (ZMQ_INCLUDE_DIR AND ZMQ_LIBRARY AND NOT ZMQ_LIBRARY-NOTFOUND)
- set(ZMQ_FOUND 1)
- message(STATUS "Found ZMQ library: ${ZMQ_LIBRARY}")
- message(STATUS "Found ZMQ headers: ${ZMQ_INCLUDE_DIR}")
-else()
- message(FATAL_ERROR "Could not find ZMQ libraries/headers! Please install ZMQ with libraries and headers, read README.md for more info")
-endif()
-
-# show the ZMQ_INCLUDE_DIR and ZMQ_LIBRARY variables only in the advanced view
-mark_as_advanced(ZMQ_ROOT_DIR ZMQ_INCLUDE_DIR ZMQ_LIBRARY ZMQ_FOUND)
diff --git a/dep/CMakeLists.txt b/dep/CMakeLists.txt
index 9f671bba30..139e51664f 100644
--- a/dep/CMakeLists.txt
+++ b/dep/CMakeLists.txt
@@ -39,7 +39,7 @@ if(SERVERS)
add_subdirectory(mysql)
add_subdirectory(readline)
add_subdirectory(gsoap)
- add_subdirectory(zmq)
+ add_subdirectory(libzmq)
add_subdirectory(zmqpp)
add_subdirectory(efsw)
endif()
diff --git a/dep/PackageList.txt b/dep/PackageList.txt
index b45988c93b..786febfa18 100644
--- a/dep/PackageList.txt
+++ b/dep/PackageList.txt
@@ -59,6 +59,10 @@ recastnavigation (Recast is state of the art navigation mesh construction toolse
StormLib (a pack of modules, written in C++, which are able to read and also to write files from/to the MPQ archives)
http://www.zezula.net/en/mpq/stormlib.html
Version: 8.04
+
+libzmq (ZeroMQ core engine in C++, implements ZMTP/3.1)
+ https://github.com/zeromq/libzmq
+ Version: 4.2.3 stable
zmqpp (C++ binding for 0mq/zmq is a 'high-level' library that hides most of the c-style interface core 0mq provides.)
https://github.com/zeromq/zmqpp
diff --git a/dep/libzmq/CMakeLists.txt b/dep/libzmq/CMakeLists.txt
new file mode 100644
index 0000000000..a569fffdcc
--- /dev/null
+++ b/dep/libzmq/CMakeLists.txt
@@ -0,0 +1,102 @@
+# Use the bundled source on windows
+set (libzmq_STAT_SRCS
+ src/address.cpp
+ src/client.cpp
+ src/clock.cpp
+ src/ctx.cpp
+ src/dealer.cpp
+ src/dgram.cpp
+ src/dist.cpp
+ src/err.cpp
+ src/fq.cpp
+ src/io_object.cpp
+ src/io_thread.cpp
+ src/ip.cpp
+ src/lb.cpp
+ src/mailbox.cpp
+ src/mailbox_safe.cpp
+ src/mechanism.cpp
+ src/mechanism_base.cpp
+ src/metadata.cpp
+ src/msg.cpp
+ src/mtrie.cpp
+ src/object.cpp
+ src/options.cpp
+ src/own.cpp
+ src/null_mechanism.cpp
+ src/pair.cpp
+ src/pipe.cpp
+ src/plain_client.cpp
+ src/plain_server.cpp
+ src/poller_base.cpp
+ src/proxy.cpp
+ src/pub.cpp
+ src/pull.cpp
+ src/push.cpp
+ src/random.cpp
+ src/raw_encoder.cpp
+ src/raw_decoder.cpp
+ src/reaper.cpp
+ src/rep.cpp
+ src/req.cpp
+ src/router.cpp
+ src/select.cpp
+ src/server.cpp
+ src/session_base.cpp
+ src/signaler.cpp
+ src/socket_base.cpp
+ src/socks.cpp
+ src/socks_connecter.cpp
+ src/stream.cpp
+ src/stream_engine.cpp
+ src/sub.cpp
+ src/tcp.cpp
+ src/tcp_address.cpp
+ src/tcp_connecter.cpp
+ src/tcp_listener.cpp
+ src/thread.cpp
+ src/trie.cpp
+ src/v1_decoder.cpp
+ src/v1_encoder.cpp
+ src/v2_decoder.cpp
+ src/v2_encoder.cpp
+ src/xpub.cpp
+ src/xsub.cpp
+ src/zmq.cpp
+ src/zmq_utils.cpp
+ src/decoder_allocators.cpp
+ src/socket_poller.cpp
+ src/timers.cpp
+ src/config.hpp
+ src/radio.cpp
+ src/dish.cpp
+ src/udp_engine.cpp
+ src/udp_address.cpp
+ src/scatter.cpp
+ src/gather.cpp
+ src/zap_client.cpp
+)
+
+add_definitions(-DZMQ_USE_SELECT)
+add_definitions(-DZMQ_STATIC)
+
+if (WIN32)
+ add_definitions(-DZMQ_HAVE_WINDOWS)
+elseif (APPLE)
+ add_definitions(-DZMQ_HAVE_OSX)
+elseif (UNIX)
+ add_definitions(-DZMQ_HAVE_LINUX)
+endif()
+
+add_library(libzmq STATIC ${libzmq_STAT_SRCS})
+
+target_include_directories(libzmq
+ PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}/include
+ PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}/src)
+
+set_target_properties(libzmq
+ PROPERTIES
+ FOLDER
+ "dep")
diff --git a/dep/libzmq/include/zmq.h b/dep/libzmq/include/zmq.h
new file mode 100644
index 0000000000..89f78af36e
--- /dev/null
+++ b/dep/libzmq/include/zmq.h
@@ -0,0 +1,708 @@
+/*
+ Copyright (c) 2007-2016 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 .
+
+ *************************************************************************
+ NOTE to contributors. This file comprises the principal public contract
+ for ZeroMQ API users. Any change to this file supplied in a stable
+ release SHOULD not break existing applications.
+ In practice this means that the value of constants must not change, and
+ that old values may not be reused for new constants.
+ *************************************************************************
+*/
+
+#ifndef __ZMQ_H_INCLUDED__
+#define __ZMQ_H_INCLUDED__
+
+/* Version macros for compile-time API version detection */
+#define ZMQ_VERSION_MAJOR 4
+#define ZMQ_VERSION_MINOR 2
+#define ZMQ_VERSION_PATCH 3
+
+#define ZMQ_MAKE_VERSION(major, minor, patch) \
+ ((major) * 10000 + (minor) * 100 + (patch))
+#define ZMQ_VERSION \
+ ZMQ_MAKE_VERSION(ZMQ_VERSION_MAJOR, ZMQ_VERSION_MINOR, ZMQ_VERSION_PATCH)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined _WIN32_WCE
+#include
+#endif
+#include
+#include
+#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
+#include
+#endif
+
+/* Handle DSO symbol visibility */
+#if defined _WIN32
+# if defined ZMQ_STATIC
+# define ZMQ_EXPORT
+# elif defined DLL_EXPORT
+# define ZMQ_EXPORT __declspec(dllexport)
+# else
+# define ZMQ_EXPORT __declspec(dllimport)
+# endif
+#else
+# if defined __SUNPRO_C || defined __SUNPRO_CC
+# define ZMQ_EXPORT __global
+# elif (defined __GNUC__ && __GNUC__ >= 4) || defined __INTEL_COMPILER
+# define ZMQ_EXPORT __attribute__ ((visibility("default")))
+# else
+# define ZMQ_EXPORT
+# endif
+#endif
+
+/* Define integer types needed for event interface */
+#define ZMQ_DEFINED_STDINT 1
+#if defined ZMQ_HAVE_SOLARIS || defined ZMQ_HAVE_OPENVMS
+# include
+#elif defined _MSC_VER && _MSC_VER < 1600
+# ifndef int32_t
+ typedef __int32 int32_t;
+# endif
+# ifndef uint32_t
+ typedef unsigned __int32 uint32_t;
+# endif
+# ifndef uint16_t
+ typedef unsigned __int16 uint16_t;
+# endif
+# ifndef uint8_t
+ typedef unsigned __int8 uint8_t;
+# endif
+#else
+# include
+#endif
+
+// 32-bit AIX's pollfd struct members are called reqevents and rtnevents so it
+// defines compatibility macros for them. Need to include that header first to
+// stop build failures since zmq_pollset_t defines them as events and revents.
+#ifdef ZMQ_HAVE_AIX
+ #include
+#endif
+
+
+/******************************************************************************/
+/* 0MQ errors. */
+/******************************************************************************/
+
+/* A number random enough not to collide with different errno ranges on */
+/* different OSes. The assumption is that error_t is at least 32-bit type. */
+#define ZMQ_HAUSNUMERO 156384712
+
+/* On Windows platform some of the standard POSIX errnos are not defined. */
+#ifndef ENOTSUP
+#define ENOTSUP (ZMQ_HAUSNUMERO + 1)
+#endif
+#ifndef EPROTONOSUPPORT
+#define EPROTONOSUPPORT (ZMQ_HAUSNUMERO + 2)
+#endif
+#ifndef ENOBUFS
+#define ENOBUFS (ZMQ_HAUSNUMERO + 3)
+#endif
+#ifndef ENETDOWN
+#define ENETDOWN (ZMQ_HAUSNUMERO + 4)
+#endif
+#ifndef EADDRINUSE
+#define EADDRINUSE (ZMQ_HAUSNUMERO + 5)
+#endif
+#ifndef EADDRNOTAVAIL
+#define EADDRNOTAVAIL (ZMQ_HAUSNUMERO + 6)
+#endif
+#ifndef ECONNREFUSED
+#define ECONNREFUSED (ZMQ_HAUSNUMERO + 7)
+#endif
+#ifndef EINPROGRESS
+#define EINPROGRESS (ZMQ_HAUSNUMERO + 8)
+#endif
+#ifndef ENOTSOCK
+#define ENOTSOCK (ZMQ_HAUSNUMERO + 9)
+#endif
+#ifndef EMSGSIZE
+#define EMSGSIZE (ZMQ_HAUSNUMERO + 10)
+#endif
+#ifndef EAFNOSUPPORT
+#define EAFNOSUPPORT (ZMQ_HAUSNUMERO + 11)
+#endif
+#ifndef ENETUNREACH
+#define ENETUNREACH (ZMQ_HAUSNUMERO + 12)
+#endif
+#ifndef ECONNABORTED
+#define ECONNABORTED (ZMQ_HAUSNUMERO + 13)
+#endif
+#ifndef ECONNRESET
+#define ECONNRESET (ZMQ_HAUSNUMERO + 14)
+#endif
+#ifndef ENOTCONN
+#define ENOTCONN (ZMQ_HAUSNUMERO + 15)
+#endif
+#ifndef ETIMEDOUT
+#define ETIMEDOUT (ZMQ_HAUSNUMERO + 16)
+#endif
+#ifndef EHOSTUNREACH
+#define EHOSTUNREACH (ZMQ_HAUSNUMERO + 17)
+#endif
+#ifndef ENETRESET
+#define ENETRESET (ZMQ_HAUSNUMERO + 18)
+#endif
+
+/* Native 0MQ error codes. */
+#define EFSM (ZMQ_HAUSNUMERO + 51)
+#define ENOCOMPATPROTO (ZMQ_HAUSNUMERO + 52)
+#define ETERM (ZMQ_HAUSNUMERO + 53)
+#define EMTHREAD (ZMQ_HAUSNUMERO + 54)
+
+/* This function retrieves the errno as it is known to 0MQ library. The goal */
+/* of this function is to make the code 100% portable, including where 0MQ */
+/* compiled with certain CRT library (on Windows) is linked to an */
+/* application that uses different CRT library. */
+ZMQ_EXPORT int zmq_errno (void);
+
+/* Resolves system errors and 0MQ errors to human-readable string. */
+ZMQ_EXPORT const char *zmq_strerror (int errnum);
+
+/* Run-time API version detection */
+ZMQ_EXPORT void zmq_version (int *major, int *minor, int *patch);
+
+/******************************************************************************/
+/* 0MQ infrastructure (a.k.a. context) initialisation & termination. */
+/******************************************************************************/
+
+/* Context options */
+#define ZMQ_IO_THREADS 1
+#define ZMQ_MAX_SOCKETS 2
+#define ZMQ_SOCKET_LIMIT 3
+#define ZMQ_THREAD_PRIORITY 3
+#define ZMQ_THREAD_SCHED_POLICY 4
+#define ZMQ_MAX_MSGSZ 5
+
+/* Default for new contexts */
+#define ZMQ_IO_THREADS_DFLT 1
+#define ZMQ_MAX_SOCKETS_DFLT 1023
+#define ZMQ_THREAD_PRIORITY_DFLT -1
+#define ZMQ_THREAD_SCHED_POLICY_DFLT -1
+
+ZMQ_EXPORT void *zmq_ctx_new (void);
+ZMQ_EXPORT int zmq_ctx_term (void *context);
+ZMQ_EXPORT int zmq_ctx_shutdown (void *context);
+ZMQ_EXPORT int zmq_ctx_set (void *context, int option, int optval);
+ZMQ_EXPORT int zmq_ctx_get (void *context, int option);
+
+/* Old (legacy) API */
+ZMQ_EXPORT void *zmq_init (int io_threads);
+ZMQ_EXPORT int zmq_term (void *context);
+ZMQ_EXPORT int zmq_ctx_destroy (void *context);
+
+
+/******************************************************************************/
+/* 0MQ message definition. */
+/******************************************************************************/
+
+/* Some architectures, like sparc64 and some variants of aarch64, enforce pointer
+ * alignment and raise sigbus on violations. Make sure applications allocate
+ * zmq_msg_t on addresses aligned on a pointer-size boundary to avoid this issue.
+ */
+typedef struct zmq_msg_t {
+#if defined (__GNUC__) || defined ( __INTEL_COMPILER) || \
+ (defined (__SUNPRO_C) && __SUNPRO_C >= 0x590) || \
+ (defined (__SUNPRO_CC) && __SUNPRO_CC >= 0x590)
+ unsigned char _ [64] __attribute__ ((aligned (sizeof (void *))));
+#elif defined (_MSC_VER) && (defined (_M_X64) || defined (_M_ARM64))
+ __declspec (align (8)) unsigned char _ [64];
+#elif defined (_MSC_VER) && (defined (_M_IX86) || defined (_M_ARM_ARMV7VE))
+ __declspec (align (4)) unsigned char _ [64];
+#else
+ unsigned char _ [64];
+#endif
+} zmq_msg_t;
+
+typedef void (zmq_free_fn) (void *data, void *hint);
+
+ZMQ_EXPORT int zmq_msg_init (zmq_msg_t *msg);
+ZMQ_EXPORT int zmq_msg_init_size (zmq_msg_t *msg, size_t size);
+ZMQ_EXPORT int zmq_msg_init_data (zmq_msg_t *msg, void *data,
+ size_t size, zmq_free_fn *ffn, void *hint);
+ZMQ_EXPORT int zmq_msg_send (zmq_msg_t *msg, void *s, int flags);
+ZMQ_EXPORT int zmq_msg_recv (zmq_msg_t *msg, void *s, int flags);
+ZMQ_EXPORT int zmq_msg_close (zmq_msg_t *msg);
+ZMQ_EXPORT int zmq_msg_move (zmq_msg_t *dest, zmq_msg_t *src);
+ZMQ_EXPORT int zmq_msg_copy (zmq_msg_t *dest, zmq_msg_t *src);
+ZMQ_EXPORT void *zmq_msg_data (zmq_msg_t *msg);
+ZMQ_EXPORT size_t zmq_msg_size (const zmq_msg_t *msg);
+ZMQ_EXPORT int zmq_msg_more (const zmq_msg_t *msg);
+ZMQ_EXPORT int zmq_msg_get (const zmq_msg_t *msg, int property);
+ZMQ_EXPORT int zmq_msg_set (zmq_msg_t *msg, int property, int optval);
+ZMQ_EXPORT const char *zmq_msg_gets (const zmq_msg_t *msg, const char *property);
+
+/******************************************************************************/
+/* 0MQ socket definition. */
+/******************************************************************************/
+
+/* Socket types. */
+#define ZMQ_PAIR 0
+#define ZMQ_PUB 1
+#define ZMQ_SUB 2
+#define ZMQ_REQ 3
+#define ZMQ_REP 4
+#define ZMQ_DEALER 5
+#define ZMQ_ROUTER 6
+#define ZMQ_PULL 7
+#define ZMQ_PUSH 8
+#define ZMQ_XPUB 9
+#define ZMQ_XSUB 10
+#define ZMQ_STREAM 11
+
+/* Deprecated aliases */
+#define ZMQ_XREQ ZMQ_DEALER
+#define ZMQ_XREP ZMQ_ROUTER
+
+/* Socket options. */
+#define ZMQ_AFFINITY 4
+#define ZMQ_ROUTING_ID 5
+#define ZMQ_SUBSCRIBE 6
+#define ZMQ_UNSUBSCRIBE 7
+#define ZMQ_RATE 8
+#define ZMQ_RECOVERY_IVL 9
+#define ZMQ_SNDBUF 11
+#define ZMQ_RCVBUF 12
+#define ZMQ_RCVMORE 13
+#define ZMQ_FD 14
+#define ZMQ_EVENTS 15
+#define ZMQ_TYPE 16
+#define ZMQ_LINGER 17
+#define ZMQ_RECONNECT_IVL 18
+#define ZMQ_BACKLOG 19
+#define ZMQ_RECONNECT_IVL_MAX 21
+#define ZMQ_MAXMSGSIZE 22
+#define ZMQ_SNDHWM 23
+#define ZMQ_RCVHWM 24
+#define ZMQ_MULTICAST_HOPS 25
+#define ZMQ_RCVTIMEO 27
+#define ZMQ_SNDTIMEO 28
+#define ZMQ_LAST_ENDPOINT 32
+#define ZMQ_ROUTER_MANDATORY 33
+#define ZMQ_TCP_KEEPALIVE 34
+#define ZMQ_TCP_KEEPALIVE_CNT 35
+#define ZMQ_TCP_KEEPALIVE_IDLE 36
+#define ZMQ_TCP_KEEPALIVE_INTVL 37
+#define ZMQ_IMMEDIATE 39
+#define ZMQ_XPUB_VERBOSE 40
+#define ZMQ_ROUTER_RAW 41
+#define ZMQ_IPV6 42
+#define ZMQ_MECHANISM 43
+#define ZMQ_PLAIN_SERVER 44
+#define ZMQ_PLAIN_USERNAME 45
+#define ZMQ_PLAIN_PASSWORD 46
+#define ZMQ_CURVE_SERVER 47
+#define ZMQ_CURVE_PUBLICKEY 48
+#define ZMQ_CURVE_SECRETKEY 49
+#define ZMQ_CURVE_SERVERKEY 50
+#define ZMQ_PROBE_ROUTER 51
+#define ZMQ_REQ_CORRELATE 52
+#define ZMQ_REQ_RELAXED 53
+#define ZMQ_CONFLATE 54
+#define ZMQ_ZAP_DOMAIN 55
+#define ZMQ_ROUTER_HANDOVER 56
+#define ZMQ_TOS 57
+#define ZMQ_CONNECT_ROUTING_ID 61
+#define ZMQ_GSSAPI_SERVER 62
+#define ZMQ_GSSAPI_PRINCIPAL 63
+#define ZMQ_GSSAPI_SERVICE_PRINCIPAL 64
+#define ZMQ_GSSAPI_PLAINTEXT 65
+#define ZMQ_HANDSHAKE_IVL 66
+#define ZMQ_SOCKS_PROXY 68
+#define ZMQ_XPUB_NODROP 69
+#define ZMQ_BLOCKY 70
+#define ZMQ_XPUB_MANUAL 71
+#define ZMQ_XPUB_WELCOME_MSG 72
+#define ZMQ_STREAM_NOTIFY 73
+#define ZMQ_INVERT_MATCHING 74
+#define ZMQ_HEARTBEAT_IVL 75
+#define ZMQ_HEARTBEAT_TTL 76
+#define ZMQ_HEARTBEAT_TIMEOUT 77
+#define ZMQ_XPUB_VERBOSER 78
+#define ZMQ_CONNECT_TIMEOUT 79
+#define ZMQ_TCP_MAXRT 80
+#define ZMQ_THREAD_SAFE 81
+#define ZMQ_MULTICAST_MAXTPDU 84
+#define ZMQ_VMCI_BUFFER_SIZE 85
+#define ZMQ_VMCI_BUFFER_MIN_SIZE 86
+#define ZMQ_VMCI_BUFFER_MAX_SIZE 87
+#define ZMQ_VMCI_CONNECT_TIMEOUT 88
+#define ZMQ_USE_FD 89
+
+/* Message options */
+#define ZMQ_MORE 1
+#define ZMQ_SHARED 3
+
+/* Send/recv options. */
+#define ZMQ_DONTWAIT 1
+#define ZMQ_SNDMORE 2
+
+/* Security mechanisms */
+#define ZMQ_NULL 0
+#define ZMQ_PLAIN 1
+#define ZMQ_CURVE 2
+#define ZMQ_GSSAPI 3
+
+/* RADIO-DISH protocol */
+#define ZMQ_GROUP_MAX_LENGTH 15
+
+/* Deprecated options and aliases */
+#define ZMQ_IDENTITY ZMQ_ROUTING_ID
+#define ZMQ_CONNECT_RID ZMQ_CONNECT_ROUTING_ID
+#define ZMQ_TCP_ACCEPT_FILTER 38
+#define ZMQ_IPC_FILTER_PID 58
+#define ZMQ_IPC_FILTER_UID 59
+#define ZMQ_IPC_FILTER_GID 60
+#define ZMQ_IPV4ONLY 31
+#define ZMQ_DELAY_ATTACH_ON_CONNECT ZMQ_IMMEDIATE
+#define ZMQ_NOBLOCK ZMQ_DONTWAIT
+#define ZMQ_FAIL_UNROUTABLE ZMQ_ROUTER_MANDATORY
+#define ZMQ_ROUTER_BEHAVIOR ZMQ_ROUTER_MANDATORY
+
+/* Deprecated Message options */
+#define ZMQ_SRCFD 2
+
+/******************************************************************************/
+/* 0MQ socket events and monitoring */
+/******************************************************************************/
+
+/* Socket transport events (TCP, IPC and TIPC only) */
+
+#define ZMQ_EVENT_CONNECTED 0x0001
+#define ZMQ_EVENT_CONNECT_DELAYED 0x0002
+#define ZMQ_EVENT_CONNECT_RETRIED 0x0004
+#define ZMQ_EVENT_LISTENING 0x0008
+#define ZMQ_EVENT_BIND_FAILED 0x0010
+#define ZMQ_EVENT_ACCEPTED 0x0020
+#define ZMQ_EVENT_ACCEPT_FAILED 0x0040
+#define ZMQ_EVENT_CLOSED 0x0080
+#define ZMQ_EVENT_CLOSE_FAILED 0x0100
+#define ZMQ_EVENT_DISCONNECTED 0x0200
+#define ZMQ_EVENT_MONITOR_STOPPED 0x0400
+#define ZMQ_EVENT_ALL 0xFFFF
+
+ZMQ_EXPORT void *zmq_socket (void *, int type);
+ZMQ_EXPORT int zmq_close (void *s);
+ZMQ_EXPORT int zmq_setsockopt (void *s, int option, const void *optval,
+ size_t optvallen);
+ZMQ_EXPORT int zmq_getsockopt (void *s, int option, void *optval,
+ size_t *optvallen);
+ZMQ_EXPORT int zmq_bind (void *s, const char *addr);
+ZMQ_EXPORT int zmq_connect (void *s, const char *addr);
+ZMQ_EXPORT int zmq_unbind (void *s, const char *addr);
+ZMQ_EXPORT int zmq_disconnect (void *s, const char *addr);
+ZMQ_EXPORT int zmq_send (void *s, const void *buf, size_t len, int flags);
+ZMQ_EXPORT int zmq_send_const (void *s, const void *buf, size_t len, int flags);
+ZMQ_EXPORT int zmq_recv (void *s, void *buf, size_t len, int flags);
+ZMQ_EXPORT int zmq_socket_monitor (void *s, const char *addr, int events);
+
+
+/******************************************************************************/
+/* Deprecated I/O multiplexing. Prefer using zmq_poller API */
+/******************************************************************************/
+
+#define ZMQ_POLLIN 1
+#define ZMQ_POLLOUT 2
+#define ZMQ_POLLERR 4
+#define ZMQ_POLLPRI 8
+
+typedef struct zmq_pollitem_t
+{
+ void *socket;
+#if defined _WIN32
+ SOCKET fd;
+#else
+ int fd;
+#endif
+ short events;
+ short revents;
+} zmq_pollitem_t;
+
+#define ZMQ_POLLITEMS_DFLT 16
+
+ZMQ_EXPORT int zmq_poll (zmq_pollitem_t *items, int nitems, long timeout);
+
+/******************************************************************************/
+/* Message proxying */
+/******************************************************************************/
+
+ZMQ_EXPORT int zmq_proxy (void *frontend, void *backend, void *capture);
+ZMQ_EXPORT int zmq_proxy_steerable (void *frontend, void *backend, void *capture, void *control);
+
+/******************************************************************************/
+/* Probe library capabilities */
+/******************************************************************************/
+
+#define ZMQ_HAS_CAPABILITIES 1
+ZMQ_EXPORT int zmq_has (const char *capability);
+
+/* Deprecated aliases */
+#define ZMQ_STREAMER 1
+#define ZMQ_FORWARDER 2
+#define ZMQ_QUEUE 3
+
+/* Deprecated methods */
+ZMQ_EXPORT int zmq_device (int type, void *frontend, void *backend);
+ZMQ_EXPORT int zmq_sendmsg (void *s, zmq_msg_t *msg, int flags);
+ZMQ_EXPORT int zmq_recvmsg (void *s, zmq_msg_t *msg, int flags);
+struct iovec;
+ZMQ_EXPORT int zmq_sendiov (void *s, struct iovec *iov, size_t count, int flags);
+ZMQ_EXPORT int zmq_recviov (void *s, struct iovec *iov, size_t *count, int flags);
+
+/******************************************************************************/
+/* Encryption functions */
+/******************************************************************************/
+
+/* Encode data with Z85 encoding. Returns encoded data */
+ZMQ_EXPORT char *zmq_z85_encode (char *dest, const uint8_t *data, size_t size);
+
+/* Decode data with Z85 encoding. Returns decoded data */
+ZMQ_EXPORT uint8_t *zmq_z85_decode (uint8_t *dest, const char *string);
+
+/* Generate z85-encoded public and private keypair with tweetnacl/libsodium. */
+/* Returns 0 on success. */
+ZMQ_EXPORT int zmq_curve_keypair (char *z85_public_key, char *z85_secret_key);
+
+/* Derive the z85-encoded public key from the z85-encoded secret key. */
+/* Returns 0 on success. */
+ZMQ_EXPORT int zmq_curve_public (char *z85_public_key, const char *z85_secret_key);
+
+/******************************************************************************/
+/* Atomic utility methods */
+/******************************************************************************/
+
+ZMQ_EXPORT void *zmq_atomic_counter_new (void);
+ZMQ_EXPORT void zmq_atomic_counter_set (void *counter, int value);
+ZMQ_EXPORT int zmq_atomic_counter_inc (void *counter);
+ZMQ_EXPORT int zmq_atomic_counter_dec (void *counter);
+ZMQ_EXPORT int zmq_atomic_counter_value (void *counter);
+ZMQ_EXPORT void zmq_atomic_counter_destroy (void **counter_p);
+
+
+/******************************************************************************/
+/* These functions are not documented by man pages -- use at your own risk. */
+/* If you need these to be part of the formal ZMQ API, then (a) write a man */
+/* page, and (b) write a test case in tests. */
+/******************************************************************************/
+
+/* Helper functions are used by perf tests so that they don't have to care */
+/* about minutiae of time-related functions on different OS platforms. */
+
+/* Starts the stopwatch. Returns the handle to the watch. */
+ZMQ_EXPORT void *zmq_stopwatch_start (void);
+
+/* Stops the stopwatch. Returns the number of microseconds elapsed since */
+/* the stopwatch was started. */
+ZMQ_EXPORT unsigned long zmq_stopwatch_stop (void *watch_);
+
+/* Sleeps for specified number of seconds. */
+ZMQ_EXPORT void zmq_sleep (int seconds_);
+
+typedef void (zmq_thread_fn) (void*);
+
+/* Start a thread. Returns a handle to the thread. */
+ZMQ_EXPORT void *zmq_threadstart (zmq_thread_fn* func, void* arg);
+
+/* Wait for thread to complete then free up resources. */
+ZMQ_EXPORT void zmq_threadclose (void* thread);
+
+
+/******************************************************************************/
+/* These functions are DRAFT and disabled in stable releases, and subject to */
+/* change at ANY time until declared stable. */
+/******************************************************************************/
+
+#ifdef ZMQ_BUILD_DRAFT_API
+
+/* DRAFT Socket types. */
+#define ZMQ_SERVER 12
+#define ZMQ_CLIENT 13
+#define ZMQ_RADIO 14
+#define ZMQ_DISH 15
+#define ZMQ_GATHER 16
+#define ZMQ_SCATTER 17
+#define ZMQ_DGRAM 18
+
+/* DRAFT Socket options. */
+#define ZMQ_GSSAPI_PRINCIPAL_NAMETYPE 90
+#define ZMQ_GSSAPI_SERVICE_PRINCIPAL_NAMETYPE 91
+#define ZMQ_BINDTODEVICE 92
+#define ZMQ_ZAP_ENFORCE_DOMAIN 93
+
+/* DRAFT 0MQ socket events and monitoring */
+/* Unspecified system errors during handshake. Event value is an errno. */
+#define ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL 0x0800
+/* Handshake complete successfully with successful authentication (if *
+ * enabled). Event value is unused. */
+#define ZMQ_EVENT_HANDSHAKE_SUCCEEDED 0x1000
+/* Protocol errors between ZMTP peers or between server and ZAP handler. *
+ * Event value is one of ZMQ_PROTOCOL_ERROR_* */
+#define ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL 0x2000
+/* Failed authentication requests. Event value is the numeric ZAP status *
+ * code, i.e. 300, 400 or 500. */
+#define ZMQ_EVENT_HANDSHAKE_FAILED_AUTH 0x4000
+
+#define ZMQ_PROTOCOL_ERROR_ZMTP_UNSPECIFIED 0x10000000
+#define ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND 0x10000001
+#define ZMQ_PROTOCOL_ERROR_ZMTP_INVALID_SEQUENCE 0x10000002
+#define ZMQ_PROTOCOL_ERROR_ZMTP_KEY_EXCHANGE 0x10000003
+#define ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_UNSPECIFIED 0x10000011
+#define ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_MESSAGE 0x10000012
+#define ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_HELLO 0x10000013
+#define ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_INITIATE 0x10000014
+#define ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_ERROR 0x10000015
+#define ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_READY 0x10000016
+#define ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_WELCOME 0x10000017
+#define ZMQ_PROTOCOL_ERROR_ZMTP_INVALID_METADATA 0x10000018
+
+// the following two may be due to erroneous configuration of a peer
+#define ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC 0x11000001
+#define ZMQ_PROTOCOL_ERROR_ZMTP_MECHANISM_MISMATCH 0x11000002
+
+#define ZMQ_PROTOCOL_ERROR_ZAP_UNSPECIFIED 0x20000000
+#define ZMQ_PROTOCOL_ERROR_ZAP_MALFORMED_REPLY 0x20000001
+#define ZMQ_PROTOCOL_ERROR_ZAP_BAD_REQUEST_ID 0x20000002
+#define ZMQ_PROTOCOL_ERROR_ZAP_BAD_VERSION 0x20000003
+#define ZMQ_PROTOCOL_ERROR_ZAP_INVALID_STATUS_CODE 0x20000004
+#define ZMQ_PROTOCOL_ERROR_ZAP_INVALID_METADATA 0x20000005
+
+/* DRAFT Context options */
+#define ZMQ_MSG_T_SIZE 6
+#define ZMQ_THREAD_AFFINITY_CPU_ADD 7
+#define ZMQ_THREAD_AFFINITY_CPU_REMOVE 8
+#define ZMQ_THREAD_NAME_PREFIX 9
+
+/* DRAFT Socket methods. */
+ZMQ_EXPORT int zmq_join (void *s, const char *group);
+ZMQ_EXPORT int zmq_leave (void *s, const char *group);
+
+/* DRAFT Msg methods. */
+ZMQ_EXPORT int zmq_msg_set_routing_id(zmq_msg_t *msg, uint32_t routing_id);
+ZMQ_EXPORT uint32_t zmq_msg_routing_id(zmq_msg_t *msg);
+ZMQ_EXPORT int zmq_msg_set_group(zmq_msg_t *msg, const char *group);
+ZMQ_EXPORT const char *zmq_msg_group(zmq_msg_t *msg);
+
+/* DRAFT Msg property names. */
+#define ZMQ_MSG_PROPERTY_ROUTING_ID "Routing-Id"
+#define ZMQ_MSG_PROPERTY_SOCKET_TYPE "Socket-Type"
+#define ZMQ_MSG_PROPERTY_USER_ID "User-Id"
+#define ZMQ_MSG_PROPERTY_PEER_ADDRESS "Peer-Address"
+
+/******************************************************************************/
+/* Poller polling on sockets,fd and thread-safe sockets */
+/******************************************************************************/
+
+#define ZMQ_HAVE_POLLER
+
+typedef struct zmq_poller_event_t
+{
+ void *socket;
+#if defined _WIN32
+ SOCKET fd;
+#else
+ int fd;
+#endif
+ void *user_data;
+ short events;
+} zmq_poller_event_t;
+
+ZMQ_EXPORT void *zmq_poller_new (void);
+ZMQ_EXPORT int zmq_poller_destroy (void **poller_p);
+ZMQ_EXPORT int zmq_poller_add (void *poller, void *socket, void *user_data, short events);
+ZMQ_EXPORT int zmq_poller_modify (void *poller, void *socket, short events);
+ZMQ_EXPORT int zmq_poller_remove (void *poller, void *socket);
+ZMQ_EXPORT int zmq_poller_wait (void *poller, zmq_poller_event_t *event, long timeout);
+ZMQ_EXPORT int zmq_poller_wait_all (void *poller, zmq_poller_event_t *events, int n_events, long timeout);
+
+#if defined _WIN32
+ZMQ_EXPORT int zmq_poller_add_fd (void *poller, SOCKET fd, void *user_data, short events);
+ZMQ_EXPORT int zmq_poller_modify_fd (void *poller, SOCKET fd, short events);
+ZMQ_EXPORT int zmq_poller_remove_fd (void *poller, SOCKET fd);
+#else
+ZMQ_EXPORT int zmq_poller_add_fd (void *poller, int fd, void *user_data, short events);
+ZMQ_EXPORT int zmq_poller_modify_fd (void *poller, int fd, short events);
+ZMQ_EXPORT int zmq_poller_remove_fd (void *poller, int fd);
+#endif
+
+ZMQ_EXPORT int zmq_socket_get_peer_state (void *socket,
+ const void *routing_id,
+ size_t routing_id_size);
+
+/******************************************************************************/
+/* Scheduling timers */
+/******************************************************************************/
+
+#define ZMQ_HAVE_TIMERS
+
+typedef void (zmq_timer_fn)(int timer_id, void *arg);
+
+ZMQ_EXPORT void *zmq_timers_new (void);
+ZMQ_EXPORT int zmq_timers_destroy (void **timers_p);
+ZMQ_EXPORT int zmq_timers_add (void *timers, size_t interval, zmq_timer_fn handler, void *arg);
+ZMQ_EXPORT int zmq_timers_cancel (void *timers, int timer_id);
+ZMQ_EXPORT int zmq_timers_set_interval (void *timers, int timer_id, size_t interval);
+ZMQ_EXPORT int zmq_timers_reset (void *timers, int timer_id);
+ZMQ_EXPORT long zmq_timers_timeout (void *timers);
+ZMQ_EXPORT int zmq_timers_execute (void *timers);
+
+/******************************************************************************/
+/* GSSAPI definitions */
+/******************************************************************************/
+
+/* GSSAPI principal name types */
+#define ZMQ_GSSAPI_NT_HOSTBASED 0
+#define ZMQ_GSSAPI_NT_USER_NAME 1
+#define ZMQ_GSSAPI_NT_KRB5_PRINCIPAL 2
+
+#endif // ZMQ_BUILD_DRAFT_API
+
+
+#undef ZMQ_EXPORT
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/dep/libzmq/include/zmq_utils.h b/dep/libzmq/include/zmq_utils.h
new file mode 100644
index 0000000000..f29638d553
--- /dev/null
+++ b/dep/libzmq/include/zmq_utils.h
@@ -0,0 +1,48 @@
+/*
+ Copyright (c) 2007-2016 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 .
+*/
+
+/* This file is deprecated, and all its functionality provided by zmq.h */
+/* Note that -Wpedantic compilation requires GCC to avoid using its custom
+ extensions such as #warning, hence the trick below. Also, pragmas for
+ warnings or other messages are not standard, not portable, and not all
+ compilers even have an equivalent concept.
+ So in the worst case, this include file is treated as silently empty. */
+
+#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER)
+#if defined(__GNUC__) || defined(__GNUG__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic warning "-Wcpp"
+#pragma GCC diagnostic ignored "-Werror"
+#pragma GCC diagnostic ignored "-Wall"
+#endif
+#pragma message("Warning: zmq_utils.h is deprecated. All its functionality is provided by zmq.h.")
+#if defined(__GNUC__) || defined(__GNUG__)
+#pragma GCC diagnostic pop
+#endif
+#endif
diff --git a/dep/libzmq/src/address.cpp b/dep/libzmq/src/address.cpp
new file mode 100644
index 0000000000..6e3d9954df
--- /dev/null
+++ b/dep/libzmq/src/address.cpp
@@ -0,0 +1,134 @@
+/*
+ Copyright (c) 2007-2016 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 .
+*/
+
+#include "precompiled.hpp"
+#include "macros.hpp"
+#include "address.hpp"
+#include "ctx.hpp"
+#include "err.hpp"
+#include "tcp_address.hpp"
+#include "udp_address.hpp"
+#include "ipc_address.hpp"
+#include "tipc_address.hpp"
+
+#if defined ZMQ_HAVE_VMCI
+#include "vmci_address.hpp"
+#endif
+
+#include
+#include
+
+zmq::address_t::address_t (
+ const std::string &protocol_, const std::string &address_, ctx_t *parent_)
+ : protocol (protocol_),
+ address (address_),
+ parent (parent_)
+{
+ memset (&resolved, 0, sizeof resolved);
+}
+
+zmq::address_t::~address_t ()
+{
+ if (protocol == "tcp") {
+ if (resolved.tcp_addr) {
+ LIBZMQ_DELETE(resolved.tcp_addr);
+ }
+ }
+ if (protocol == "udp") {
+ if (resolved.udp_addr) {
+ LIBZMQ_DELETE(resolved.udp_addr);
+ }
+ }
+#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS
+ else
+ if (protocol == "ipc") {
+ if (resolved.ipc_addr) {
+ LIBZMQ_DELETE(resolved.ipc_addr);
+ }
+ }
+#endif
+#if defined ZMQ_HAVE_TIPC
+ else
+ if (protocol == "tipc") {
+ if (resolved.tipc_addr) {
+ LIBZMQ_DELETE(resolved.tipc_addr);
+ }
+ }
+#endif
+#if defined ZMQ_HAVE_VMCI
+ else
+ if (protocol == "vmci") {
+ if (resolved.vmci_addr) {
+ LIBZMQ_DELETE(resolved.vmci_addr);
+ }
+ }
+#endif
+}
+
+int zmq::address_t::to_string (std::string &addr_) const
+{
+ if (protocol == "tcp") {
+ if (resolved.tcp_addr)
+ return resolved.tcp_addr->to_string (addr_);
+ }
+ if (protocol == "udp") {
+ if (resolved.udp_addr)
+ return resolved.udp_addr->to_string (addr_);
+ }
+#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS
+ else
+ if (protocol == "ipc") {
+ if (resolved.ipc_addr)
+ return resolved.ipc_addr->to_string (addr_);
+ }
+#endif
+#if defined ZMQ_HAVE_TIPC
+ else
+ if (protocol == "tipc") {
+ if (resolved.tipc_addr)
+ return resolved.tipc_addr->to_string (addr_);
+ }
+#endif
+#if defined ZMQ_HAVE_VMCI
+ else
+ if (protocol == "vmci") {
+ if (resolved.vmci_addr)
+ return resolved.vmci_addr->to_string (addr_);
+ }
+#endif
+
+ if (!protocol.empty () && !address.empty ()) {
+ std::stringstream s;
+ s << protocol << "://" << address;
+ addr_ = s.str ();
+ return 0;
+ }
+ addr_.clear ();
+ return -1;
+}
diff --git a/dep/libzmq/src/address.hpp b/dep/libzmq/src/address.hpp
new file mode 100644
index 0000000000..61feb4287a
--- /dev/null
+++ b/dep/libzmq/src/address.hpp
@@ -0,0 +1,77 @@
+/*
+ Copyright (c) 2007-2016 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 .
+*/
+
+#ifndef __ZMQ_ADDRESS_HPP_INCLUDED__
+#define __ZMQ_ADDRESS_HPP_INCLUDED__
+
+#include
+
+namespace zmq
+{
+ class ctx_t;
+ class tcp_address_t;
+ class udp_address_t;
+#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS
+ class ipc_address_t;
+#endif
+#if defined ZMQ_HAVE_LINUX
+ class tipc_address_t;
+#endif
+#if defined ZMQ_HAVE_VMCI
+ class vmci_address_t;
+#endif
+ struct address_t {
+ address_t (const std::string &protocol_, const std::string &address_, ctx_t *parent_);
+
+ ~address_t ();
+
+ const std::string protocol;
+ const std::string address;
+ ctx_t *parent;
+
+ // Protocol specific resolved address
+ union {
+ tcp_address_t *tcp_addr;
+ udp_address_t *udp_addr;
+#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS
+ ipc_address_t *ipc_addr;
+#endif
+#if defined ZMQ_HAVE_LINUX
+ tipc_address_t *tipc_addr;
+#endif
+#if defined ZMQ_HAVE_VMCI
+ vmci_address_t *vmci_addr;
+#endif
+ } resolved;
+
+ int to_string (std::string &addr_) const;
+ };
+}
+
+#endif
diff --git a/dep/libzmq/src/array.hpp b/dep/libzmq/src/array.hpp
new file mode 100644
index 0000000000..c6b5d93d7c
--- /dev/null
+++ b/dep/libzmq/src/array.hpp
@@ -0,0 +1,167 @@
+/*
+ Copyright (c) 2007-2016 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 .
+*/
+
+#ifndef __ZMQ_ARRAY_INCLUDED__
+#define __ZMQ_ARRAY_INCLUDED__
+
+#include
+#include
+
+namespace zmq
+{
+ // Implementation of fast arrays with O(1) access, insertion and
+ // removal. The array stores pointers rather than objects.
+ // O(1) is achieved by making items inheriting from
+ // array_item_t class which internally stores the position
+ // in the array.
+ // The ID template argument is used to differentiate among arrays
+ // and thus let an object be stored in different arrays.
+
+ // Base class for objects stored in the array. If you want to store
+ // same object in multiple arrays, each of those arrays has to have
+ // different ID. The item itself has to be derived from instantiations of
+ // array_item_t template for all relevant IDs.
+
+ template class array_item_t
+ {
+ public:
+
+ inline array_item_t () :
+ array_index (-1)
+ {
+ }
+
+ // The destructor doesn't have to be virtual. It is made virtual
+ // just to keep ICC and code checking tools from complaining.
+ inline virtual ~array_item_t ()
+ {
+ }
+
+ inline void set_array_index (int index_)
+ {
+ array_index = index_;
+ }
+
+ inline int get_array_index ()
+ {
+ return array_index;
+ }
+
+ private:
+
+ int array_index;
+
+ array_item_t (const array_item_t&);
+ const array_item_t &operator = (const array_item_t&);
+ };
+
+
+ template class array_t
+ {
+ private:
+
+ typedef array_item_t item_t;
+
+ public:
+
+ typedef typename std::vector ::size_type size_type;
+
+ inline array_t ()
+ {
+ }
+
+ inline ~array_t ()
+ {
+ }
+
+ inline size_type size ()
+ {
+ return items.size ();
+ }
+
+ inline bool empty ()
+ {
+ return items.empty ();
+ }
+
+ inline T *&operator [] (size_type index_)
+ {
+ return items [index_];
+ }
+
+ inline void push_back (T *item_)
+ {
+ if (item_)
+ ((item_t*) item_)->set_array_index ((int) items.size ());
+ items.push_back (item_);
+ }
+
+ inline void erase (T *item_) {
+ erase (((item_t*) item_)->get_array_index ());
+ }
+
+ inline void erase (size_type index_) {
+ if (items.back ())
+ ((item_t*) items.back ())->set_array_index ((int) index_);
+ items [index_] = items.back ();
+ items.pop_back ();
+ }
+
+ inline void swap (size_type index1_, size_type index2_)
+ {
+ if (items [index1_])
+ ((item_t*) items [index1_])->set_array_index ((int) index2_);
+ if (items [index2_])
+ ((item_t*) items [index2_])->set_array_index ((int) index1_);
+ std::swap (items [index1_], items [index2_]);
+ }
+
+ inline void clear ()
+ {
+ items.clear ();
+ }
+
+ inline size_type index (T *item_)
+ {
+ return (size_type) ((item_t*) item_)->get_array_index ();
+ }
+
+ private:
+
+ typedef std::vector items_t;
+ items_t items;
+
+ array_t (const array_t&);
+ const array_t &operator = (const array_t&);
+ };
+
+}
+
+#endif
+
diff --git a/dep/libzmq/src/atomic_counter.hpp b/dep/libzmq/src/atomic_counter.hpp
new file mode 100644
index 0000000000..23a7c50869
--- /dev/null
+++ b/dep/libzmq/src/atomic_counter.hpp
@@ -0,0 +1,249 @@
+/*
+ Copyright (c) 2007-2016 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 .
+*/
+
+#ifndef __ZMQ_ATOMIC_COUNTER_HPP_INCLUDED__
+#define __ZMQ_ATOMIC_COUNTER_HPP_INCLUDED__
+
+#include "stdint.hpp"
+
+#if defined ZMQ_FORCE_MUTEXES
+#define ZMQ_ATOMIC_COUNTER_MUTEX
+#elif defined ZMQ_HAVE_ATOMIC_INTRINSICS
+#define ZMQ_ATOMIC_COUNTER_INTRINSIC
+#elif (defined __cplusplus && __cplusplus >= 201103L)
+#define ZMQ_ATOMIC_COUNTER_CXX11
+#elif (defined __i386__ || defined __x86_64__) && defined __GNUC__
+#define ZMQ_ATOMIC_COUNTER_X86
+#elif defined __ARM_ARCH_7A__ && defined __GNUC__
+#define ZMQ_ATOMIC_COUNTER_ARM
+#elif defined ZMQ_HAVE_WINDOWS
+#define ZMQ_ATOMIC_COUNTER_WINDOWS
+#elif (defined ZMQ_HAVE_SOLARIS || defined ZMQ_HAVE_NETBSD || defined ZMQ_HAVE_GNU)
+#define ZMQ_ATOMIC_COUNTER_ATOMIC_H
+#elif defined __tile__
+#define ZMQ_ATOMIC_COUNTER_TILE
+#else
+#define ZMQ_ATOMIC_COUNTER_MUTEX
+#endif
+
+#if defined ZMQ_ATOMIC_COUNTER_MUTEX
+#include "mutex.hpp"
+#elif defined ZMQ_ATOMIC_COUNTER_CXX11
+#include
+#elif defined ZMQ_ATOMIC_COUNTER_WINDOWS
+#include "windows.hpp"
+#elif defined ZMQ_ATOMIC_COUNTER_ATOMIC_H
+#include
+#elif defined ZMQ_ATOMIC_COUNTER_TILE
+#include
+#endif
+
+namespace zmq
+{
+
+ // This class represents an integer that can be incremented/decremented
+ // in atomic fashion.
+ //
+ // In zmq::shared_message_memory_allocator a buffer with an atomic_counter_t
+ // at the start is allocated. If the class does not align to pointer size,
+ // access to pointers in structures in the buffer will cause SIGBUS on
+ // architectures that do not allow mis-aligned pointers (eg: SPARC).
+ // Force the compiler to align to pointer size, which will cause the object
+ // to grow from 4 bytes to 8 bytes on 64 bit architectures (when not using
+ // mutexes).
+
+#if defined (_MSC_VER) && (defined (_M_X64) || defined (_M_ARM64))
+ class __declspec (align (8)) atomic_counter_t
+#elif defined (_MSC_VER) && (defined (_M_IX86) || defined (_M_ARM_ARMV7VE))
+ class __declspec (align (4)) atomic_counter_t
+#else
+ class atomic_counter_t
+#endif
+ {
+ public:
+
+ typedef uint32_t integer_t;
+
+ inline atomic_counter_t (integer_t value_ = 0) :
+ value (value_)
+ {
+ }
+
+ inline ~atomic_counter_t ()
+ {
+ }
+
+ // Set counter value (not thread-safe).
+ inline void set (integer_t value_)
+ {
+ value = value_;
+ }
+
+ // Atomic addition. Returns the old value.
+ inline integer_t add (integer_t increment_)
+ {
+ integer_t old_value;
+
+#if defined ZMQ_ATOMIC_COUNTER_WINDOWS
+ old_value = InterlockedExchangeAdd ((LONG*) &value, increment_);
+#elif defined ZMQ_ATOMIC_COUNTER_INTRINSIC
+ old_value = __atomic_fetch_add(&value, increment_, __ATOMIC_ACQ_REL);
+#elif defined ZMQ_ATOMIC_COUNTER_CXX11
+ old_value = value.fetch_add(increment_, std::memory_order_acq_rel);
+#elif defined ZMQ_ATOMIC_COUNTER_ATOMIC_H
+ integer_t new_value = atomic_add_32_nv (&value, increment_);
+ old_value = new_value - increment_;
+#elif defined ZMQ_ATOMIC_COUNTER_TILE
+ old_value = arch_atomic_add (&value, increment_);
+#elif defined ZMQ_ATOMIC_COUNTER_X86
+ __asm__ volatile (
+ "lock; xadd %0, %1 \n\t"
+ : "=r" (old_value), "=m" (value)
+ : "0" (increment_), "m" (value)
+ : "cc", "memory");
+#elif defined ZMQ_ATOMIC_COUNTER_ARM
+ integer_t flag, tmp;
+ __asm__ volatile (
+ " dmb sy\n\t"
+ "1: ldrex %0, [%5]\n\t"
+ " add %2, %0, %4\n\t"
+ " strex %1, %2, [%5]\n\t"
+ " teq %1, #0\n\t"
+ " bne 1b\n\t"
+ " dmb sy\n\t"
+ : "=&r"(old_value), "=&r"(flag), "=&r"(tmp), "+Qo"(value)
+ : "Ir"(increment_), "r"(&value)
+ : "cc");
+#elif defined ZMQ_ATOMIC_COUNTER_MUTEX
+ sync.lock ();
+ old_value = value;
+ value += increment_;
+ sync.unlock ();
+#else
+#error atomic_counter is not implemented for this platform
+#endif
+ return old_value;
+ }
+
+ // Atomic subtraction. Returns false if the counter drops to zero.
+ inline bool sub (integer_t decrement)
+ {
+#if defined ZMQ_ATOMIC_COUNTER_WINDOWS
+ LONG delta = - ((LONG) decrement);
+ integer_t old = InterlockedExchangeAdd ((LONG*) &value, delta);
+ return old - decrement != 0;
+#elif defined ZMQ_ATOMIC_COUNTER_INTRINSIC
+ integer_t nv = __atomic_sub_fetch(&value, decrement, __ATOMIC_ACQ_REL);
+ return nv != 0;
+#elif defined ZMQ_ATOMIC_COUNTER_CXX11
+ integer_t old = value.fetch_sub(decrement, std::memory_order_acq_rel);
+ return old - decrement != 0;
+#elif defined ZMQ_ATOMIC_COUNTER_ATOMIC_H
+ int32_t delta = - ((int32_t) decrement);
+ integer_t nv = atomic_add_32_nv (&value, delta);
+ return nv != 0;
+#elif defined ZMQ_ATOMIC_COUNTER_TILE
+ int32_t delta = - ((int32_t) decrement);
+ integer_t nv = arch_atomic_add (&value, delta);
+ return nv != 0;
+#elif defined ZMQ_ATOMIC_COUNTER_X86
+ integer_t oldval = -decrement;
+ volatile integer_t *val = &value;
+ __asm__ volatile ("lock; xaddl %0,%1"
+ : "=r" (oldval), "=m" (*val)
+ : "0" (oldval), "m" (*val)
+ : "cc", "memory");
+ return oldval != decrement;
+#elif defined ZMQ_ATOMIC_COUNTER_ARM
+ integer_t old_value, flag, tmp;
+ __asm__ volatile (
+ " dmb sy\n\t"
+ "1: ldrex %0, [%5]\n\t"
+ " sub %2, %0, %4\n\t"
+ " strex %1, %2, [%5]\n\t"
+ " teq %1, #0\n\t"
+ " bne 1b\n\t"
+ " dmb sy\n\t"
+ : "=&r"(old_value), "=&r"(flag), "=&r"(tmp), "+Qo"(value)
+ : "Ir"(decrement), "r"(&value)
+ : "cc");
+ return old_value - decrement != 0;
+#elif defined ZMQ_ATOMIC_COUNTER_MUTEX
+ sync.lock ();
+ value -= decrement;
+ bool result = value ? true : false;
+ sync.unlock ();
+ return result;
+#else
+#error atomic_counter is not implemented for this platform
+#endif
+ }
+
+ inline integer_t get () const
+ {
+ return value;
+ }
+
+ private:
+
+#if defined ZMQ_ATOMIC_COUNTER_CXX11
+ std::atomic value;
+#else
+ volatile integer_t value;
+#endif
+
+#if defined ZMQ_ATOMIC_COUNTER_MUTEX
+ mutex_t sync;
+#endif
+
+#if ! defined ZMQ_ATOMIC_COUNTER_CXX11
+ atomic_counter_t (const atomic_counter_t&);
+ const atomic_counter_t& operator = (const atomic_counter_t&);
+#endif
+#if defined (__GNUC__) || defined ( __INTEL_COMPILER) || \
+ (defined (__SUNPRO_C) && __SUNPRO_C >= 0x590) || \
+ (defined (__SUNPRO_CC) && __SUNPRO_CC >= 0x590)
+ } __attribute__ ((aligned (sizeof (void *))));
+#else
+ };
+#endif
+
+}
+
+// Remove macros local to this file.
+#undef ZMQ_ATOMIC_COUNTER_MUTEX
+#undef ZMQ_ATOMIC_COUNTER_INTRINSIC
+#undef ZMQ_ATOMIC_COUNTER_CXX11
+#undef ZMQ_ATOMIC_COUNTER_X86
+#undef ZMQ_ATOMIC_COUNTER_ARM
+#undef ZMQ_ATOMIC_COUNTER_WINDOWS
+#undef ZMQ_ATOMIC_COUNTER_ATOMIC_H
+#undef ZMQ_ATOMIC_COUNTER_TILE
+
+#endif
diff --git a/dep/libzmq/src/atomic_ptr.hpp b/dep/libzmq/src/atomic_ptr.hpp
new file mode 100644
index 0000000000..53b0d5da17
--- /dev/null
+++ b/dep/libzmq/src/atomic_ptr.hpp
@@ -0,0 +1,227 @@
+/*
+ Copyright (c) 2007-2016 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 .
+*/
+
+#ifndef __ZMQ_ATOMIC_PTR_HPP_INCLUDED__
+#define __ZMQ_ATOMIC_PTR_HPP_INCLUDED__
+
+#if defined ZMQ_FORCE_MUTEXES
+#define ZMQ_ATOMIC_PTR_MUTEX
+#elif defined ZMQ_HAVE_ATOMIC_INTRINSICS
+#define ZMQ_ATOMIC_PTR_INTRINSIC
+#elif (defined __cplusplus && __cplusplus >= 201103L)
+#define ZMQ_ATOMIC_PTR_CXX11
+#elif (defined __i386__ || defined __x86_64__) && defined __GNUC__
+#define ZMQ_ATOMIC_PTR_X86
+#elif defined __ARM_ARCH_7A__ && defined __GNUC__
+#define ZMQ_ATOMIC_PTR_ARM
+#elif defined __tile__
+#define ZMQ_ATOMIC_PTR_TILE
+#elif defined ZMQ_HAVE_WINDOWS
+#define ZMQ_ATOMIC_PTR_WINDOWS
+#elif (defined ZMQ_HAVE_SOLARIS || defined ZMQ_HAVE_NETBSD || defined ZMQ_HAVE_GNU)
+#define ZMQ_ATOMIC_PTR_ATOMIC_H
+#else
+#define ZMQ_ATOMIC_PTR_MUTEX
+#endif
+
+#if defined ZMQ_ATOMIC_PTR_MUTEX
+#include "mutex.hpp"
+#elif defined ZMQ_ATOMIC_PTR_CXX11
+#include
+#elif defined ZMQ_ATOMIC_PTR_WINDOWS
+#include "windows.hpp"
+#elif defined ZMQ_ATOMIC_PTR_ATOMIC_H
+#include
+#elif defined ZMQ_ATOMIC_PTR_TILE
+#include
+#endif
+
+namespace zmq
+{
+
+ // This class encapsulates several atomic operations on pointers.
+
+ template class atomic_ptr_t
+ {
+ public:
+
+ // Initialise atomic pointer
+ inline atomic_ptr_t ()
+ {
+ ptr = NULL;
+ }
+
+ // Destroy atomic pointer
+ inline ~atomic_ptr_t ()
+ {
+ }
+
+ // Set value of atomic pointer in a non-threadsafe way
+ // Use this function only when you are sure that at most one
+ // thread is accessing the pointer at the moment.
+ inline void set (T *ptr_)
+ {
+ this->ptr = ptr_;
+ }
+
+ // Perform atomic 'exchange pointers' operation. Pointer is set
+ // to the 'val' value. Old value is returned.
+ inline T *xchg (T *val_)
+ {
+#if defined ZMQ_ATOMIC_PTR_WINDOWS
+ return (T*) InterlockedExchangePointer ((PVOID*) &ptr, val_);
+#elif defined ZMQ_ATOMIC_PTR_INTRINSIC
+ return (T*) __atomic_exchange_n (&ptr, val_, __ATOMIC_ACQ_REL);
+#elif defined ZMQ_ATOMIC_PTR_CXX11
+ return ptr.exchange(val_, std::memory_order_acq_rel);
+#elif defined ZMQ_ATOMIC_PTR_ATOMIC_H
+ return (T*) atomic_swap_ptr (&ptr, val_);
+#elif defined ZMQ_ATOMIC_PTR_TILE
+ return (T*) arch_atomic_exchange (&ptr, val_);
+#elif defined ZMQ_ATOMIC_PTR_X86
+ T *old;
+ __asm__ volatile (
+ "lock; xchg %0, %2"
+ : "=r" (old), "=m" (ptr)
+ : "m" (ptr), "0" (val_));
+ return old;
+#elif defined ZMQ_ATOMIC_PTR_ARM
+ T* old;
+ unsigned int flag;
+ __asm__ volatile (
+ " dmb sy\n\t"
+ "1: ldrex %1, [%3]\n\t"
+ " strex %0, %4, [%3]\n\t"
+ " teq %0, #0\n\t"
+ " bne 1b\n\t"
+ " dmb sy\n\t"
+ : "=&r"(flag), "=&r"(old), "+Qo"(ptr)
+ : "r"(&ptr), "r"(val_)
+ : "cc");
+ return old;
+#elif defined ZMQ_ATOMIC_PTR_MUTEX
+ sync.lock ();
+ T *old = (T*) ptr;
+ ptr = val_;
+ sync.unlock ();
+ return old;
+#else
+#error atomic_ptr is not implemented for this platform
+#endif
+ }
+
+ // Perform atomic 'compare and swap' operation on the pointer.
+ // The pointer is compared to 'cmp' argument and if they are
+ // equal, its value is set to 'val'. Old value of the pointer
+ // is returned.
+ inline T *cas (T *cmp_, T *val_)
+ {
+#if defined ZMQ_ATOMIC_PTR_WINDOWS
+ return (T*) InterlockedCompareExchangePointer (
+ (volatile PVOID*) &ptr, val_, cmp_);
+#elif defined ZMQ_ATOMIC_PTR_INTRINSIC
+ T *old = cmp_;
+ __atomic_compare_exchange_n (&ptr, (volatile T**) &old, val_, false,
+ __ATOMIC_RELEASE, __ATOMIC_ACQUIRE);
+ return old;
+#elif defined ZMQ_ATOMIC_PTR_CXX11
+ ptr.compare_exchange_strong(cmp_, val_, std::memory_order_acq_rel);
+ return cmp_;
+#elif defined ZMQ_ATOMIC_PTR_ATOMIC_H
+ return (T*) atomic_cas_ptr (&ptr, cmp_, val_);
+#elif defined ZMQ_ATOMIC_PTR_TILE
+ return (T*) arch_atomic_val_compare_and_exchange (&ptr, cmp_, val_);
+#elif defined ZMQ_ATOMIC_PTR_X86
+ T *old;
+ __asm__ volatile (
+ "lock; cmpxchg %2, %3"
+ : "=a" (old), "=m" (ptr)
+ : "r" (val_), "m" (ptr), "0" (cmp_)
+ : "cc");
+ return old;
+#elif defined ZMQ_ATOMIC_PTR_ARM
+ T *old;
+ unsigned int flag;
+ __asm__ volatile (
+ " dmb sy\n\t"
+ "1: ldrex %1, [%3]\n\t"
+ " mov %0, #0\n\t"
+ " teq %1, %4\n\t"
+ " it eq\n\t"
+ " strexeq %0, %5, [%3]\n\t"
+ " teq %0, #0\n\t"
+ " bne 1b\n\t"
+ " dmb sy\n\t"
+ : "=&r"(flag), "=&r"(old), "+Qo"(ptr)
+ : "r"(&ptr), "r"(cmp_), "r"(val_)
+ : "cc");
+ return old;
+#elif defined ZMQ_ATOMIC_PTR_MUTEX
+ sync.lock ();
+ T *old = (T*) ptr;
+ if (ptr == cmp_)
+ ptr = val_;
+ sync.unlock ();
+ return old;
+#else
+#error atomic_ptr is not implemented for this platform
+#endif
+ }
+
+ private:
+
+#if defined ZMQ_ATOMIC_PTR_CXX11
+ std::atomic ptr;
+#else
+ volatile T *ptr;
+#endif
+
+#if defined ZMQ_ATOMIC_PTR_MUTEX
+ mutex_t sync;
+#endif
+
+#if ! defined ZMQ_ATOMIC_PTR_CXX11
+ atomic_ptr_t (const atomic_ptr_t&);
+ const atomic_ptr_t &operator = (const atomic_ptr_t&);
+#endif
+ };
+
+}
+
+// Remove macros local to this file.
+#undef ZMQ_ATOMIC_PTR_MUTEX
+#undef ZMQ_ATOMIC_PTR_INTRINSIC
+#undef ZMQ_ATOMIC_PTR_CXX11
+#undef ZMQ_ATOMIC_PTR_X86
+#undef ZMQ_ATOMIC_PTR_ARM
+#undef ZMQ_ATOMIC_PTR_TILE
+#undef ZMQ_ATOMIC_PTR_WINDOWS
+#undef ZMQ_ATOMIC_PTR_ATOMIC_H
+
+#endif
diff --git a/dep/libzmq/src/blob.hpp b/dep/libzmq/src/blob.hpp
new file mode 100644
index 0000000000..9e21718e75
--- /dev/null
+++ b/dep/libzmq/src/blob.hpp
@@ -0,0 +1,186 @@
+/*
+ Copyright (c) 2007-2016 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 .
+*/
+
+#ifndef __ZMQ_BLOB_HPP_INCLUDED__
+#define __ZMQ_BLOB_HPP_INCLUDED__
+
+#include
+#include
+#include
+
+#if __cplusplus >= 201103L || defined(_MSC_VER) && _MSC_VER >= 1700
+#define ZMQ_HAS_MOVE_SEMANTICS
+#define ZMQ_MAP_INSERT_OR_EMPLACE(k, v) emplace (k,v)
+#define ZMQ_PUSH_OR_EMPLACE_BACK emplace_back
+#define ZMQ_MOVE(x) std::move (x)
+#else
+#define ZMQ_MAP_INSERT_OR_EMPLACE(k, v) insert (std::make_pair (k, v))
+#define ZMQ_PUSH_OR_EMPLACE_BACK push_back
+#define ZMQ_MOVE(x) (x)
+#endif
+
+namespace zmq
+{
+ struct reference_tag_t {};
+
+ // Object to hold dynamically allocated opaque binary data.
+ // On modern compilers, it will be movable but not copyable. Copies
+ // must be explicitly created by set_deep_copy.
+ // On older compilers, it is copyable for syntactical reasons.
+ struct blob_t
+ {
+ // Creates an empty blob_t.
+ blob_t () : data_ (0), size_ (0), owned_ (true) {}
+
+ // Creates a blob_t of a given size, with uninitialized content.
+ blob_t (const size_t size)
+ : data_ ((unsigned char*)malloc (size))
+ , size_ (size)
+ , owned_ (true)
+ {
+ }
+
+ // Creates a blob_t of a given size, an initializes content by copying
+ // from another buffer.
+ blob_t(const unsigned char * const data, const size_t size)
+ : data_ ((unsigned char*)malloc (size))
+ , size_ (size)
+ , owned_ (true)
+ {
+ memcpy(data_, data, size_);
+ }
+
+ // Creates a blob_t for temporary use that only references a
+ // pre-allocated block of data.
+ // Use with caution and ensure that the blob_t will not outlive
+ // the referenced data.
+ blob_t (unsigned char * const data, const size_t size, reference_tag_t)
+ : data_ (data)
+ , size_ (size)
+ , owned_ (false)
+ {
+ }
+
+ // Returns the size of the blob_t.
+ size_t size () const { return size_; }
+
+ // Returns a pointer to the data of the blob_t.
+ const unsigned char *data() const {
+ return data_;
+ }
+
+ // Returns a pointer to the data of the blob_t.
+ unsigned char *data() {
+ return data_;
+ }
+
+ // Defines an order relationship on blob_t.
+ bool operator< (blob_t const &other) const {
+ int cmpres = memcmp (data_, other.data_, std::min (size_, other.size_));
+ return cmpres < 0 || (cmpres == 0 && size_ < other.size_);
+ }
+
+ // Sets a blob_t to a deep copy of another blob_t.
+ void set_deep_copy (blob_t const &other)
+ {
+ clear ();
+ data_ = (unsigned char*)malloc (other.size_);
+ size_ = other.size_;
+ owned_ = true;
+ memcpy (data_, other.data_, size_);
+ }
+
+ // Sets a blob_t to a copy of a given buffer.
+ void set (const unsigned char * const data, const size_t size)
+ {
+ clear ();
+ data_ = (unsigned char*)malloc (size);
+ size_ = size;
+ owned_ = true;
+ memcpy (data_, data, size_);
+ }
+
+ // Empties a blob_t.
+ void clear () {
+ if (owned_) { free (data_); }
+ data_ = 0; size_ = 0;
+ }
+
+ ~blob_t () {
+ if (owned_) { free (data_); }
+ }
+
+#ifdef ZMQ_HAS_MOVE_SEMANTICS
+ blob_t (const blob_t &) = delete;
+ blob_t &operator= (const blob_t &) = delete;
+
+ blob_t (blob_t&& other)
+ : data_ (other.data_)
+ , size_ (other.size_)
+ , owned_ (other.owned_)
+ {
+ other.owned_ = false;
+ }
+ blob_t &operator= (blob_t&& other) {
+ if (this != &other)
+ {
+ clear ();
+ data_ = other.data_;
+ size_ = other.size_;
+ owned_ = other.owned_;
+ other.owned_ = false;
+ }
+ return *this;
+ }
+#else
+ blob_t (const blob_t &other)
+ : owned_(false)
+ {
+ set_deep_copy (other);
+ }
+ blob_t &operator= (const blob_t &other) {
+ if (this != &other)
+ {
+ clear ();
+ set_deep_copy (other);
+ }
+ return *this;
+ }
+#endif
+
+ private:
+ unsigned char *data_;
+ size_t size_;
+ bool owned_;
+ };
+
+}
+
+#endif
+
diff --git a/dep/libzmq/src/client.cpp b/dep/libzmq/src/client.cpp
new file mode 100644
index 0000000000..61f85e1df1
--- /dev/null
+++ b/dep/libzmq/src/client.cpp
@@ -0,0 +1,116 @@
+/*
+ Copyright (c) 2007-2016 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 .
+*/
+
+#include "precompiled.hpp"
+#include "macros.hpp"
+#include "client.hpp"
+#include "err.hpp"
+#include "msg.hpp"
+
+zmq::client_t::client_t (class ctx_t *parent_, uint32_t tid_, int sid_) :
+ socket_base_t (parent_, tid_, sid_, true)
+{
+ options.type = ZMQ_CLIENT;
+}
+
+zmq::client_t::~client_t ()
+{
+}
+
+void zmq::client_t::xattach_pipe (pipe_t *pipe_, bool subscribe_to_all_)
+{
+ LIBZMQ_UNUSED (subscribe_to_all_);
+
+ zmq_assert (pipe_);
+
+ fq.attach (pipe_);
+ lb.attach (pipe_);
+}
+
+int zmq::client_t::xsend (msg_t *msg_)
+{
+ // CLIENT sockets do not allow multipart data (ZMQ_SNDMORE)
+ if (msg_->flags () & msg_t::more) {
+ errno = EINVAL;
+ return -1;
+ }
+ return lb.sendpipe (msg_, NULL);
+}
+
+int zmq::client_t::xrecv (msg_t *msg_)
+{
+ int rc = fq.recvpipe (msg_, NULL);
+
+ // Drop any messages with more flag
+ while (rc == 0 && msg_->flags () & msg_t::more) {
+
+ // drop all frames of the current multi-frame message
+ rc = fq.recvpipe (msg_, NULL);
+
+ while (rc == 0 && msg_->flags () & msg_t::more)
+ rc = fq.recvpipe (msg_, NULL);
+
+ // get the new message
+ if (rc == 0)
+ rc = fq.recvpipe (msg_, NULL);
+ }
+
+ return rc;
+}
+
+bool zmq::client_t::xhas_in ()
+{
+ return fq.has_in ();
+}
+
+bool zmq::client_t::xhas_out ()
+{
+ return lb.has_out ();
+}
+
+const zmq::blob_t &zmq::client_t::get_credential () const
+{
+ return fq.get_credential ();
+}
+
+void zmq::client_t::xread_activated (pipe_t *pipe_)
+{
+ fq.activated (pipe_);
+}
+
+void zmq::client_t::xwrite_activated (pipe_t *pipe_)
+{
+ lb.activated (pipe_);
+}
+
+void zmq::client_t::xpipe_terminated (pipe_t *pipe_)
+{
+ fq.pipe_terminated (pipe_);
+ lb.pipe_terminated (pipe_);
+}
diff --git a/dep/libzmq/src/client.hpp b/dep/libzmq/src/client.hpp
new file mode 100644
index 0000000000..6d9be5f083
--- /dev/null
+++ b/dep/libzmq/src/client.hpp
@@ -0,0 +1,81 @@
+/*
+ Copyright (c) 2007-2016 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 .
+*/
+
+#ifndef __ZMQ_CLIENT_HPP_INCLUDED__
+#define __ZMQ_CLIENT_HPP_INCLUDED__
+
+#include "socket_base.hpp"
+#include "session_base.hpp"
+#include "fq.hpp"
+#include "lb.hpp"
+
+namespace zmq
+{
+
+ class ctx_t;
+ class msg_t;
+ class pipe_t;
+ class io_thread_t;
+ class socket_base_t;
+
+ class client_t :
+ public socket_base_t
+ {
+ public:
+
+ client_t (zmq::ctx_t *parent_, uint32_t tid_, int sid);
+ ~client_t ();
+
+ protected:
+
+ // Overrides of functions from socket_base_t.
+ void xattach_pipe (zmq::pipe_t *pipe_, bool subscribe_to_all_);
+ int xsend (zmq::msg_t *msg_);
+ int xrecv (zmq::msg_t *msg_);
+ bool xhas_in ();
+ bool xhas_out ();
+ const blob_t &get_credential () const;
+ void xread_activated (zmq::pipe_t *pipe_);
+ void xwrite_activated (zmq::pipe_t *pipe_);
+ void xpipe_terminated (zmq::pipe_t *pipe_);
+
+ private:
+
+ // Messages are fair-queued from inbound pipes. And load-balanced to
+ // the outbound pipes.
+ fq_t fq;
+ lb_t lb;
+
+ client_t (const client_t &);
+ const client_t &operator = (const client_t&);
+ };
+
+}
+
+#endif
diff --git a/dep/libzmq/src/clock.cpp b/dep/libzmq/src/clock.cpp
new file mode 100644
index 0000000000..b15bd743c5
--- /dev/null
+++ b/dep/libzmq/src/clock.cpp
@@ -0,0 +1,253 @@
+/*
+ Copyright (c) 2007-2016 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 .
+*/
+
+#include "precompiled.hpp"
+#include "clock.hpp"
+#include "likely.hpp"
+#include "config.hpp"
+#include "err.hpp"
+#include "mutex.hpp"
+
+#include
+
+#if defined _MSC_VER
+#if defined _WIN32_WCE
+#include
+#else
+#include
+#endif
+#endif
+
+#if !defined ZMQ_HAVE_WINDOWS
+#include
+#endif
+
+#if defined HAVE_CLOCK_GETTIME || defined HAVE_GETHRTIME
+#include
+#endif
+
+#if defined ZMQ_HAVE_OSX
+#include
+#include
+#include
+#include
+
+int alt_clock_gettime (int clock_id, timespec *ts)
+{
+ clock_serv_t cclock;
+ mach_timespec_t mts;
+ host_get_clock_service (mach_host_self (), clock_id, &cclock);
+ clock_get_time (cclock, &mts);
+ mach_port_deallocate (mach_task_self (), cclock);
+ ts->tv_sec = mts.tv_sec;
+ ts->tv_nsec = mts.tv_nsec;
+ return 0;
+}
+#endif
+
+#ifdef ZMQ_HAVE_WINDOWS
+typedef ULONGLONG (*f_compatible_get_tick_count64)();
+
+static zmq::mutex_t compatible_get_tick_count64_mutex;
+
+ULONGLONG compatible_get_tick_count64()
+{
+#ifdef ZMQ_HAVE_WINDOWS_UWP
+ const ULONGLONG result = ::GetTickCount64();
+ return result;
+#else
+ zmq::scoped_lock_t locker(compatible_get_tick_count64_mutex);
+
+ static DWORD s_wrap = 0;
+ static DWORD s_last_tick = 0;
+ const DWORD current_tick = ::GetTickCount();
+
+ if (current_tick < s_last_tick)
+ ++s_wrap;
+
+ s_last_tick = current_tick;
+ const ULONGLONG result = (static_cast(s_wrap) << 32) + static_cast(current_tick);
+
+ return result;
+#endif
+}
+
+f_compatible_get_tick_count64 init_compatible_get_tick_count64()
+{
+ f_compatible_get_tick_count64 func = NULL;
+#if !defined ZMQ_HAVE_WINDOWS_UWP
+
+ HMODULE module = ::LoadLibraryA("Kernel32.dll");
+ if (module != NULL)
+ func = reinterpret_cast(::GetProcAddress(module, "GetTickCount64"));
+#endif
+ if (func == NULL)
+ func = compatible_get_tick_count64;
+
+#if !defined ZMQ_HAVE_WINDOWS_UWP
+ ::FreeLibrary(module);
+#endif
+
+ return func;
+}
+
+static f_compatible_get_tick_count64 my_get_tick_count64 = init_compatible_get_tick_count64();
+#endif
+
+zmq::clock_t::clock_t () :
+ last_tsc (rdtsc ()),
+#ifdef ZMQ_HAVE_WINDOWS
+ last_time (static_cast((*my_get_tick_count64)()))
+#else
+ last_time (now_us () / 1000)
+#endif
+{
+}
+
+zmq::clock_t::~clock_t ()
+{
+}
+
+uint64_t zmq::clock_t::now_us ()
+{
+#if defined ZMQ_HAVE_WINDOWS
+
+ // Get the high resolution counter's accuracy.
+ LARGE_INTEGER ticksPerSecond;
+ QueryPerformanceFrequency (&ticksPerSecond);
+
+ // What time is it?
+ LARGE_INTEGER tick;
+ QueryPerformanceCounter (&tick);
+
+ // Convert the tick number into the number of seconds
+ // since the system was started.
+ double ticks_div = ticksPerSecond.QuadPart / 1000000.0;
+ return (uint64_t) (tick.QuadPart / ticks_div);
+
+#elif defined HAVE_CLOCK_GETTIME && defined CLOCK_MONOTONIC
+
+ // Use POSIX clock_gettime function to get precise monotonic time.
+ struct timespec tv;
+
+#if defined ZMQ_HAVE_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED < 101200 // less than macOS 10.12
+ int rc = alt_clock_gettime (SYSTEM_CLOCK, &tv);
+#else
+ int rc = clock_gettime (CLOCK_MONOTONIC, &tv);
+#endif
+ // Fix case where system has clock_gettime but CLOCK_MONOTONIC is not supported.
+ // This should be a configuration check, but I looked into it and writing an
+ // AC_FUNC_CLOCK_MONOTONIC seems beyond my powers.
+ if( rc != 0) {
+ // Use POSIX gettimeofday function to get precise time.
+ struct timeval tv;
+ int rc = gettimeofday (&tv, NULL);
+ errno_assert (rc == 0);
+ return (tv.tv_sec * (uint64_t) 1000000 + tv.tv_usec);
+ }
+ return (tv.tv_sec * (uint64_t) 1000000 + tv.tv_nsec / 1000);
+
+#elif defined HAVE_GETHRTIME
+
+ return (gethrtime () / 1000);
+
+#else
+
+ // Use POSIX gettimeofday function to get precise time.
+ struct timeval tv;
+ int rc = gettimeofday (&tv, NULL);
+ errno_assert (rc == 0);
+ return (tv.tv_sec * (uint64_t) 1000000 + tv.tv_usec);
+
+#endif
+}
+
+uint64_t zmq::clock_t::now_ms ()
+{
+ uint64_t tsc = rdtsc ();
+
+ // If TSC is not supported, get precise time and chop off the microseconds.
+ if (!tsc)
+ {
+#ifdef ZMQ_HAVE_WINDOWS
+ // Under Windows, now_us is not so reliable since QueryPerformanceCounter
+ // does not guarantee that it will use a hardware that offers a monotonic timer.
+ // So, lets use GetTickCount when GetTickCount64 is not available with an workaround
+ // to its 32 bit limitation.
+ return static_cast((*my_get_tick_count64)());
+#else
+ return now_us () / 1000;
+#endif
+ }
+
+ // If TSC haven't jumped back (in case of migration to a different
+ // CPU core) and if not too much time elapsed since last measurement,
+ // we can return cached time value.
+ if (likely (tsc - last_tsc <= (clock_precision / 2) && tsc >= last_tsc))
+ return last_time;
+
+ last_tsc = tsc;
+#ifdef ZMQ_HAVE_WINDOWS
+ last_time = static_cast((*my_get_tick_count64)());
+#else
+ last_time = now_us () / 1000;
+#endif
+ return last_time;
+}
+
+uint64_t zmq::clock_t::rdtsc ()
+{
+#if (defined _MSC_VER && (defined _M_IX86 || defined _M_X64))
+ return __rdtsc ();
+#elif (defined __GNUC__ && (defined __i386__ || defined __x86_64__))
+ uint32_t low, high;
+ __asm__ volatile ("rdtsc" : "=a" (low), "=d" (high));
+ return (uint64_t) high << 32 | low;
+#elif (defined __SUNPRO_CC && (__SUNPRO_CC >= 0x5100) && (defined __i386 || \
+ defined __amd64 || defined __x86_64))
+ union {
+ uint64_t u64val;
+ uint32_t u32val [2];
+ } tsc;
+ asm("rdtsc" : "=a" (tsc.u32val [0]), "=d" (tsc.u32val [1]));
+ return tsc.u64val;
+#elif defined(__s390__)
+ uint64_t tsc;
+ asm("\tstck\t%0\n" : "=Q" (tsc) : : "cc");
+ return(tsc);
+#else
+ struct timespec ts;
+ #if defined ZMQ_HAVE_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED < 101200 // less than macOS 10.12
+ alt_clock_gettime (SYSTEM_CLOCK, &ts);
+ #else
+ clock_gettime (CLOCK_MONOTONIC, &ts);
+ #endif
+ return (uint64_t)(ts.tv_sec) * 1000000000 + ts.tv_nsec;
+#endif
+}
diff --git a/dep/libzmq/src/clock.hpp b/dep/libzmq/src/clock.hpp
new file mode 100644
index 0000000000..ee80a9da1d
--- /dev/null
+++ b/dep/libzmq/src/clock.hpp
@@ -0,0 +1,83 @@
+/*
+ Copyright (c) 2007-2016 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 .
+*/
+
+#ifndef __ZMQ_CLOCK_HPP_INCLUDED__
+#define __ZMQ_CLOCK_HPP_INCLUDED__
+
+#include "stdint.hpp"
+
+#if defined ZMQ_HAVE_OSX
+#include
+#include
+#include
+#include
+int alt_clock_gettime (int clock_id, timespec *ts);
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+#ifndef HAVE_CLOCK_GETTIME
+#define HAVE_CLOCK_GETTIME
+#endif
+#endif
+
+namespace zmq
+{
+
+ class clock_t
+ {
+ public:
+
+ clock_t ();
+ ~clock_t ();
+
+ // CPU's timestamp counter. Returns 0 if it's not available.
+ static uint64_t rdtsc ();
+
+ // High precision timestamp.
+ static uint64_t now_us ();
+
+ // Low precision timestamp. In tight loops generating it can be
+ // 10 to 100 times faster than the high precision timestamp.
+ uint64_t now_ms ();
+
+ private:
+
+ // TSC timestamp of when last time measurement was made.
+ uint64_t last_tsc;
+
+ // Physical time corresponding to the TSC above (in milliseconds).
+ uint64_t last_time;
+
+ clock_t (const clock_t&);
+ const clock_t &operator = (const clock_t&);
+ };
+
+}
+
+#endif
diff --git a/dep/libzmq/src/command.hpp b/dep/libzmq/src/command.hpp
new file mode 100644
index 0000000000..ddb46d4675
--- /dev/null
+++ b/dep/libzmq/src/command.hpp
@@ -0,0 +1,188 @@
+/*
+ Copyright (c) 2007-2016 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 .
+*/
+
+#ifndef __ZMQ_COMMAND_HPP_INCLUDED__
+#define __ZMQ_COMMAND_HPP_INCLUDED__
+
+#include
+#include "stdint.hpp"
+
+namespace zmq
+{
+
+ class object_t;
+ class own_t;
+ struct i_engine;
+ class pipe_t;
+ 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.
+ zmq::object_t *destination;
+
+ enum type_t
+ {
+ stop,
+ plug,
+ own,
+ attach,
+ bind,
+ activate_read,
+ activate_write,
+ hiccup,
+ pipe_term,
+ pipe_term_ack,
+ pipe_hwm,
+ term_req,
+ term,
+ term_ack,
+ term_endpoint,
+ reap,
+ reaped,
+ inproc_connected,
+ done
+ } type;
+
+ union args_t
+ {
+
+ // Sent to I/O thread to let it know that it should
+ // terminate itself.
+ struct {
+ } stop;
+
+ // Sent to I/O object to make it register with its I/O thread.
+ struct {
+ } plug;
+
+ // Sent to socket to let it know about the newly created object.
+ struct {
+ zmq::own_t *object;
+ } own;
+
+ // Attach the engine to the session. If engine is NULL, it informs
+ // session that the connection have failed.
+ struct {
+ struct i_engine *engine;
+ } attach;
+
+ // Sent from session to socket to establish pipe(s) between them.
+ // Caller have used inc_seqnum beforehand sending the command.
+ struct {
+ zmq::pipe_t *pipe;
+ } bind;
+
+ // Sent by pipe writer to inform dormant pipe reader that there
+ // are messages in the pipe.
+ struct {
+ } activate_read;
+
+ // Sent by pipe reader to inform pipe writer about how many
+ // messages it has read so far.
+ struct {
+ uint64_t msgs_read;
+ } activate_write;
+
+ // Sent by pipe reader to writer after creating a new inpipe.
+ // The parameter is actually of type pipe_t::upipe_t, however,
+ // its definition is private so we'll have to do with void*.
+ struct {
+ void *pipe;
+ } hiccup;
+
+ // Sent by pipe reader to pipe writer to ask it to terminate
+ // its end of the pipe.
+ struct {
+ } pipe_term;
+
+ // Pipe writer acknowledges pipe_term command.
+ struct {
+ } pipe_term_ack;
+
+ // Sent by one of pipe to another part for modify hwm
+ struct {
+ int inhwm;
+ int outhwm;
+ } pipe_hwm;
+
+ // Sent by I/O object ot the socket to request the shutdown of
+ // the I/O object.
+ struct {
+ zmq::own_t *object;
+ } term_req;
+
+ // Sent by socket to I/O object to start its shutdown.
+ struct {
+ int linger;
+ } term;
+
+ // Sent by I/O object to the socket to acknowledge it has
+ // shut down.
+ struct {
+ } term_ack;
+
+ // Sent by session_base (I/O thread) to socket (application thread)
+ // to ask to disconnect the endpoint.
+ struct {
+ std::string *endpoint;
+ } term_endpoint;
+
+ // Transfers the ownership of the closed socket
+ // to the reaper thread.
+ struct {
+ zmq::socket_base_t *socket;
+ } reap;
+
+ // Closed socket notifies the reaper that it's already deallocated.
+ struct {
+ } reaped;
+
+ // Sent by reaper thread to the term thread when all the sockets
+ // are successfully deallocated.
+ struct {
+ } done;
+
+ } args;
+#ifdef _MSC_VER
+ };
+#pragma warning(pop)
+#else
+ } __attribute__((aligned(64)));
+#endif
+}
+
+#endif
diff --git a/dep/libzmq/src/condition_variable.hpp b/dep/libzmq/src/condition_variable.hpp
new file mode 100644
index 0000000000..6452b7814f
--- /dev/null
+++ b/dep/libzmq/src/condition_variable.hpp
@@ -0,0 +1,279 @@
+/*
+ Copyright (c) 2007-2016 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 .
+*/
+
+#ifndef __ZMQ_CONDITON_VARIABLE_HPP_INCLUDED__
+#define __ZMQ_CONDITON_VARIABLE_HPP_INCLUDED__
+
+#include "clock.hpp"
+#include "err.hpp"
+#include "mutex.hpp"
+
+// Condition variable class encapsulates OS mutex in a platform-independent way.
+
+#ifdef ZMQ_HAVE_WINDOWS
+
+#include "windows.hpp"
+#if defined(_MSC_VER)
+#if _MSC_VER >= 1800
+#define _SUPPORT_CONDITION_VARIABLE 1
+#else
+#define _SUPPORT_CONDITION_VARIABLE 0
+#endif
+#else
+#if _cplusplus >= 201103L
+#define _SUPPORT_CONDITION_VARIABLE 1
+#else
+#define _SUPPORT_CONDITION_VARIABLE 0
+#endif
+#endif
+
+// Condition variable is supported from Windows Vista only, to use condition variable define _WIN32_WINNT to 0x0600
+#if _WIN32_WINNT < 0x0600 && !_SUPPORT_CONDITION_VARIABLE
+
+namespace zmq
+{
+
+ class condition_variable_t
+ {
+ public:
+ inline condition_variable_t ()
+ {
+ zmq_assert(false);
+ }
+
+ inline ~condition_variable_t ()
+ {
+
+ }
+
+ inline int wait (mutex_t* mutex_, int timeout_ )
+ {
+ zmq_assert(false);
+ return -1;
+ }
+
+ inline void broadcast ()
+ {
+ zmq_assert(false);
+ }
+
+ private:
+
+ // Disable copy construction and assignment.
+ condition_variable_t (const condition_variable_t&);
+ void operator = (const condition_variable_t&);
+ };
+
+}
+
+#else
+
+#if _SUPPORT_CONDITION_VARIABLE || defined(ZMQ_HAVE_WINDOWS_TARGET_XP)
+#include
+#include
+#endif
+
+namespace zmq
+{
+
+#if !defined(ZMQ_HAVE_WINDOWS_TARGET_XP) && _WIN32_WINNT >= 0x0600
+ class condition_variable_t
+ {
+ public:
+ inline condition_variable_t ()
+ {
+ InitializeConditionVariable (&cv);
+ }
+
+ inline ~condition_variable_t ()
+ {
+
+ }
+
+ inline int wait (mutex_t* mutex_, int timeout_ )
+ {
+ int rc = SleepConditionVariableCS(&cv, mutex_->get_cs (), timeout_);
+
+ if (rc != 0)
+ return 0;
+
+ rc = GetLastError();
+
+ if (rc != ERROR_TIMEOUT)
+ win_assert(rc);
+
+ errno = EAGAIN;
+ return -1;
+ }
+
+ inline void broadcast ()
+ {
+ WakeAllConditionVariable(&cv);
+ }
+
+ private:
+
+ CONDITION_VARIABLE cv;
+
+ // Disable copy construction and assignment.
+ condition_variable_t (const condition_variable_t&);
+ void operator = (const condition_variable_t&);
+ };
+#else
+ class condition_variable_t
+ {
+ public:
+ inline condition_variable_t()
+ {
+
+ }
+
+ inline ~condition_variable_t()
+ {
+
+ }
+
+ inline int wait(mutex_t* mutex_, int timeout_)
+ {
+ std::unique_lock lck(mtx); // lock mtx
+ mutex_->unlock(); // unlock mutex_
+ int res = 0;
+ if(timeout_ == -1) {
+ cv.wait(lck); // unlock mtx and wait cv.notify_all(), lock mtx after cv.notify_all()
+ } else if (cv.wait_for(lck, std::chrono::milliseconds(timeout_)) == std::cv_status::timeout) {
+ // time expired
+ errno = EAGAIN;
+ res = -1;
+ }
+ lck.unlock(); // unlock mtx
+ mutex_->lock(); // lock mutex_
+ return res;
+ }
+
+ inline void broadcast()
+ {
+ std::unique_lock lck(mtx); // lock mtx
+ cv.notify_all();
+ }
+
+ private:
+
+ std::condition_variable cv;
+ std::mutex mtx;
+
+ // Disable copy construction and assignment.
+ condition_variable_t(const condition_variable_t&);
+ void operator = (const condition_variable_t&);
+ };
+
+#endif
+}
+
+#endif
+
+#else
+
+#include
+
+namespace zmq
+{
+
+ class condition_variable_t
+ {
+ public:
+ inline condition_variable_t ()
+ {
+ int rc = pthread_cond_init (&cond, NULL);
+ posix_assert (rc);
+ }
+
+ inline ~condition_variable_t ()
+ {
+ int rc = pthread_cond_destroy (&cond);
+ posix_assert (rc);
+ }
+
+ inline int wait (mutex_t* mutex_, int timeout_)
+ {
+ int rc;
+
+ if (timeout_ != -1) {
+ struct timespec timeout;
+
+#if defined ZMQ_HAVE_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED < 101200 // less than macOS 10.12
+ alt_clock_gettime(SYSTEM_CLOCK, &timeout);
+#else
+ clock_gettime(CLOCK_MONOTONIC, &timeout);
+#endif
+
+ timeout.tv_sec += timeout_ / 1000;
+ timeout.tv_nsec += (timeout_ % 1000) * 1000000;
+
+ if (timeout.tv_nsec > 1000000000) {
+ timeout.tv_sec++;
+ timeout.tv_nsec -= 1000000000;
+ }
+
+ rc = pthread_cond_timedwait (&cond, mutex_->get_mutex (), &timeout);
+ }
+ else
+ rc = pthread_cond_wait(&cond, mutex_->get_mutex());
+
+ if (rc == 0)
+ return 0;
+
+ if (rc == ETIMEDOUT){
+ errno= EAGAIN;
+ return -1;
+ }
+
+ posix_assert (rc);
+ return -1;
+ }
+
+ inline void broadcast ()
+ {
+ int rc = pthread_cond_broadcast (&cond);
+ posix_assert (rc);
+ }
+
+ private:
+
+ pthread_cond_t cond;
+
+ // Disable copy construction and assignment.
+ condition_variable_t (const condition_variable_t&);
+ const condition_variable_t &operator = (const condition_variable_t&);
+ };
+}
+
+#endif
+
+
+#endif
diff --git a/dep/libzmq/src/config.hpp b/dep/libzmq/src/config.hpp
new file mode 100644
index 0000000000..0a7433a812
--- /dev/null
+++ b/dep/libzmq/src/config.hpp
@@ -0,0 +1,98 @@
+/*
+ Copyright (c) 2007-2016 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 .
+*/
+
+#ifndef __ZMQ_CONFIG_HPP_INCLUDED__
+#define __ZMQ_CONFIG_HPP_INCLUDED__
+
+namespace zmq
+{
+
+ // Compile-time settings.
+
+ enum
+ {
+ // Number of new messages in message pipe needed to trigger new memory
+ // allocation. Setting this parameter to 256 decreases the impact of
+ // memory allocation by approximately 99.6%
+ message_pipe_granularity = 256,
+
+ // Commands in pipe per allocation event.
+ command_pipe_granularity = 16,
+
+ // Determines how often does socket poll for new commands when it
+ // still has unprocessed messages to handle. Thus, if it is set to 100,
+ // socket will process 100 inbound messages before doing the poll.
+ // If there are no unprocessed messages available, poll is done
+ // immediately. Decreasing the value trades overall latency for more
+ // real-time behaviour (less latency peaks).
+ inbound_poll_rate = 100,
+
+ // Maximal batching size for engines with receiving functionality.
+ // So, if there are 10 messages that fit into the batch size, all of
+ // them may be read by a single 'recv' system call, thus avoiding
+ // unnecessary network stack traversals.
+ in_batch_size = 8192,
+
+ // Maximal batching size for engines with sending functionality.
+ // So, if there are 10 messages that fit into the batch size, all of
+ // them may be written by a single 'send' system call, thus avoiding
+ // unnecessary network stack traversals.
+ out_batch_size = 8192,
+
+ // Maximal delta between high and low watermark.
+ max_wm_delta = 1024,
+
+ // Maximum number of events the I/O thread can process in one go.
+ max_io_events = 256,
+
+ // Maximal delay to process command in API thread (in CPU ticks).
+ // 3,000,000 ticks equals to 1 - 2 milliseconds on current CPUs.
+ // Note that delay is only applied when there is continuous stream of
+ // messages to process. If not so, commands are processed immediately.
+ max_command_delay = 3000000,
+
+ // Low-precision clock precision in CPU ticks. 1ms. Value of 1000000
+ // should be OK for CPU frequencies above 1GHz. If should work
+ // reasonably well for CPU frequencies above 500MHz. For lower CPU
+ // frequencies you may consider lowering this value to get best
+ // possible latencies.
+ clock_precision = 1000000,
+
+ // On some OSes the signaler has to be emulated using a TCP
+ // connection. In such cases following port is used.
+ // If 0, it lets the OS choose a free port without requiring use of a
+ // global mutex. The original implementation of a Windows signaler
+ // socket used port 5905 instead of letting the OS choose a free port.
+ // https://github.com/zeromq/libzmq/issues/1542
+ signaler_port = 0
+ };
+
+}
+
+#endif
diff --git a/dep/libzmq/src/ctx.cpp b/dep/libzmq/src/ctx.cpp
new file mode 100644
index 0000000000..59f3be987f
--- /dev/null
+++ b/dep/libzmq/src/ctx.cpp
@@ -0,0 +1,644 @@
+/*
+ Copyright (c) 2007-2017 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 .
+*/
+
+#include "precompiled.hpp"
+#include "macros.hpp"
+#ifndef ZMQ_HAVE_WINDOWS
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+
+#include "ctx.hpp"
+#include "socket_base.hpp"
+#include "io_thread.hpp"
+#include "reaper.hpp"
+#include "pipe.hpp"
+#include "err.hpp"
+#include "msg.hpp"
+#include "random.hpp"
+
+#ifdef ZMQ_HAVE_VMCI
+#include
+#endif
+
+#define ZMQ_CTX_TAG_VALUE_GOOD 0xabadcafe
+#define ZMQ_CTX_TAG_VALUE_BAD 0xdeadbeef
+
+int clipped_maxsocket (int max_requested)
+{
+ if (max_requested >= zmq::poller_t::max_fds () && zmq::poller_t::max_fds () != -1)
+ // -1 because we need room for the reaper mailbox.
+ max_requested = zmq::poller_t::max_fds () - 1;
+
+ return max_requested;
+}
+
+zmq::ctx_t::ctx_t () :
+ tag (ZMQ_CTX_TAG_VALUE_GOOD),
+ starting (true),
+ terminating (false),
+ reaper (NULL),
+ slot_count (0),
+ slots (NULL),
+ max_sockets (clipped_maxsocket (ZMQ_MAX_SOCKETS_DFLT)),
+ max_msgsz (INT_MAX),
+ io_thread_count (ZMQ_IO_THREADS_DFLT),
+ blocky (true),
+ ipv6 (false),
+ thread_priority (ZMQ_THREAD_PRIORITY_DFLT),
+ thread_sched_policy (ZMQ_THREAD_SCHED_POLICY_DFLT)
+{
+#ifdef HAVE_FORK
+ pid = getpid();
+#endif
+#ifdef ZMQ_HAVE_VMCI
+ vmci_fd = -1;
+ vmci_family = -1;
+#endif
+
+ // Initialise crypto library, if needed.
+ zmq::random_open ();
+}
+
+bool zmq::ctx_t::check_tag ()
+{
+ return tag == ZMQ_CTX_TAG_VALUE_GOOD;
+}
+
+zmq::ctx_t::~ctx_t ()
+{
+ // Check that there are no remaining sockets.
+ zmq_assert (sockets.empty ());
+
+ // Ask I/O threads to terminate. If stop signal wasn't sent to I/O
+ // thread subsequent invocation of destructor would hang-up.
+ for (io_threads_t::size_type i = 0; i != io_threads.size (); i++) {
+ io_threads [i]->stop ();
+ }
+
+ // Wait till I/O threads actually terminate.
+ for (io_threads_t::size_type i = 0; i != io_threads.size (); i++) {
+ LIBZMQ_DELETE(io_threads [i]);
+ }
+
+ // Deallocate the reaper thread object.
+ LIBZMQ_DELETE(reaper);
+
+ // Deallocate the array of mailboxes. No special work is
+ // needed as mailboxes themselves were deallocated with their
+ // corresponding io_thread/socket objects.
+ free (slots);
+
+ // De-initialise crypto library, if needed.
+ zmq::random_close ();
+
+ // Remove the tag, so that the object is considered dead.
+ tag = ZMQ_CTX_TAG_VALUE_BAD;
+}
+
+int zmq::ctx_t::terminate ()
+{
+ slot_sync.lock();
+
+ bool saveTerminating = terminating;
+ terminating = false;
+
+ // Connect up any pending inproc connections, otherwise we will hang
+ pending_connections_t copy = pending_connections;
+ for (pending_connections_t::iterator p = copy.begin (); p != copy.end (); ++p) {
+ zmq::socket_base_t *s = create_socket (ZMQ_PAIR);
+ // create_socket might fail eg: out of memory/sockets limit reached
+ zmq_assert (s);
+ s->bind (p->first.c_str ());
+ s->close ();
+ }
+ terminating = saveTerminating;
+
+ if (!starting) {
+
+#ifdef HAVE_FORK
+ if (pid != getpid ()) {
+ // we are a forked child process. Close all file descriptors
+ // inherited from the parent.
+ for (sockets_t::size_type i = 0; i != sockets.size (); i++)
+ sockets [i]->get_mailbox ()->forked ();
+
+ term_mailbox.forked ();
+ }
+#endif
+
+ // Check whether termination was already underway, but interrupted and now
+ // restarted.
+ bool restarted = terminating;
+ terminating = true;
+
+ // First attempt to terminate the context.
+ if (!restarted) {
+ // First send stop command to sockets so that any blocking calls
+ // can be interrupted. If there are no sockets we can ask reaper
+ // thread to stop.
+ for (sockets_t::size_type i = 0; i != sockets.size (); i++)
+ sockets [i]->stop ();
+ if (sockets.empty ())
+ reaper->stop ();
+ }
+ slot_sync.unlock();
+
+ // Wait till reaper thread closes all the sockets.
+ command_t cmd;
+ int rc = term_mailbox.recv (&cmd, -1);
+ if (rc == -1 && errno == EINTR)
+ return -1;
+ errno_assert (rc == 0);
+ zmq_assert (cmd.type == command_t::done);
+ slot_sync.lock ();
+ zmq_assert (sockets.empty ());
+ }
+ slot_sync.unlock ();
+
+#ifdef ZMQ_HAVE_VMCI
+ vmci_sync.lock ();
+
+ VMCISock_ReleaseAFValueFd (vmci_fd);
+ vmci_family = -1;
+ vmci_fd = -1;
+
+ vmci_sync.unlock ();
+#endif
+
+ // Deallocate the resources.
+ delete this;
+
+ return 0;
+}
+
+int zmq::ctx_t::shutdown ()
+{
+ scoped_lock_t locker(slot_sync);
+
+ if (!starting && !terminating) {
+ terminating = true;
+
+ // Send stop command to sockets so that any blocking calls
+ // can be interrupted. If there are no sockets we can ask reaper
+ // thread to stop.
+ for (sockets_t::size_type i = 0; i != sockets.size (); i++)
+ sockets [i]->stop ();
+ if (sockets.empty ())
+ reaper->stop ();
+ }
+
+ return 0;
+}
+
+int zmq::ctx_t::set (int option_, int optval_)
+{
+ int rc = 0;
+ if (option_ == ZMQ_MAX_SOCKETS
+ && optval_ >= 1 && optval_ == clipped_maxsocket (optval_)) {
+ scoped_lock_t locker(opt_sync);
+ max_sockets = optval_;
+ }
+ else
+ if (option_ == ZMQ_IO_THREADS && optval_ >= 0) {
+ scoped_lock_t locker(opt_sync);
+ io_thread_count = optval_;
+ }
+ else
+ if (option_ == ZMQ_IPV6 && optval_ >= 0) {
+ scoped_lock_t locker(opt_sync);
+ ipv6 = (optval_ != 0);
+ }
+ else
+ if (option_ == ZMQ_THREAD_PRIORITY && optval_ >= 0) {
+ scoped_lock_t locker(opt_sync);
+ thread_priority = optval_;
+ }
+ else
+ if (option_ == ZMQ_THREAD_SCHED_POLICY && optval_ >= 0) {
+ scoped_lock_t locker(opt_sync);
+ thread_sched_policy = optval_;
+ }
+ else
+ if (option_ == ZMQ_THREAD_AFFINITY_CPU_ADD && optval_ >= 0) {
+ scoped_lock_t locker(opt_sync);
+ thread_affinity_cpus.insert( optval_ );
+ }
+ else
+ if (option_ == ZMQ_THREAD_AFFINITY_CPU_REMOVE && optval_ >= 0) {
+ scoped_lock_t locker(opt_sync);
+ std::set::iterator it = thread_affinity_cpus.find( optval_ );
+ if (it != thread_affinity_cpus.end()) {
+ thread_affinity_cpus.erase( it );
+ } else {
+ errno = EINVAL;
+ rc = -1;
+ }
+ }
+ else
+ if (option_ == ZMQ_THREAD_NAME_PREFIX && optval_ >= 0) {
+ std::ostringstream s;
+ s << optval_;
+ scoped_lock_t locker(opt_sync);
+ thread_name_prefix = s.str();
+ }
+ else
+ if (option_ == ZMQ_BLOCKY && optval_ >= 0) {
+ scoped_lock_t locker(opt_sync);
+ blocky = (optval_ != 0);
+ }
+ else
+ if (option_ == ZMQ_MAX_MSGSZ && optval_ >= 0) {
+ scoped_lock_t locker(opt_sync);
+ max_msgsz = optval_ < INT_MAX? optval_: INT_MAX;
+ }
+ else {
+ errno = EINVAL;
+ rc = -1;
+ }
+ return rc;
+}
+
+int zmq::ctx_t::get (int option_)
+{
+ int rc = 0;
+ if (option_ == ZMQ_MAX_SOCKETS)
+ rc = max_sockets;
+ else
+ if (option_ == ZMQ_SOCKET_LIMIT)
+ rc = clipped_maxsocket (65535);
+ else
+ if (option_ == ZMQ_IO_THREADS)
+ rc = io_thread_count;
+ else
+ if (option_ == ZMQ_IPV6)
+ rc = ipv6;
+ else
+ if (option_ == ZMQ_BLOCKY)
+ rc = blocky;
+ else
+ if (option_ == ZMQ_MAX_MSGSZ)
+ rc = max_msgsz;
+ else
+ if (option_ == ZMQ_MSG_T_SIZE)
+ rc = sizeof (zmq_msg_t);
+ else {
+ errno = EINVAL;
+ rc = -1;
+ }
+ return rc;
+}
+
+zmq::socket_base_t *zmq::ctx_t::create_socket (int type_)
+{
+ scoped_lock_t locker(slot_sync);
+
+ if (unlikely (starting)) {
+
+ starting = false;
+ // Initialise the array of mailboxes. Additional three slots are for
+ // zmq_ctx_term thread and reaper thread.
+ opt_sync.lock ();
+ int mazmq = max_sockets;
+ int ios = io_thread_count;
+ opt_sync.unlock ();
+ slot_count = mazmq + ios + 2;
+ slots = (i_mailbox **) malloc (sizeof (i_mailbox*) * slot_count);
+ alloc_assert (slots);
+
+ // Initialise the infrastructure for zmq_ctx_term thread.
+ slots [term_tid] = &term_mailbox;
+
+ // Create the reaper thread.
+ reaper = new (std::nothrow) reaper_t (this, reaper_tid);
+ alloc_assert (reaper);
+ slots [reaper_tid] = reaper->get_mailbox ();
+ reaper->start ();
+
+ // Create I/O thread objects and launch them.
+ for (int i = 2; i != ios + 2; i++) {
+ io_thread_t *io_thread = new (std::nothrow) io_thread_t (this, i);
+ alloc_assert (io_thread);
+ io_threads.push_back (io_thread);
+ slots [i] = io_thread->get_mailbox ();
+ io_thread->start ();
+ }
+
+ // In the unused part of the slot array, create a list of empty slots.
+ for (int32_t i = (int32_t) slot_count - 1;
+ i >= (int32_t) ios + 2; i--) {
+ empty_slots.push_back (i);
+ slots [i] = NULL;
+ }
+ }
+
+ // Once zmq_ctx_term() was called, we can't create new sockets.
+ if (terminating) {
+ errno = ETERM;
+ return NULL;
+ }
+
+ // If max_sockets limit was reached, return error.
+ if (empty_slots.empty ()) {
+ errno = EMFILE;
+ return NULL;
+ }
+
+ // Choose a slot for the socket.
+ uint32_t slot = empty_slots.back ();
+ empty_slots.pop_back ();
+
+ // Generate new unique socket ID.
+ int sid = ((int) max_socket_id.add (1)) + 1;
+
+ // Create the socket and register its mailbox.
+ socket_base_t *s = socket_base_t::create (type_, this, slot, sid);
+ if (!s) {
+ empty_slots.push_back (slot);
+ return NULL;
+ }
+ sockets.push_back (s);
+ slots [slot] = s->get_mailbox ();
+
+ return s;
+}
+
+void zmq::ctx_t::destroy_socket (class socket_base_t *socket_)
+{
+ scoped_lock_t locker(slot_sync);
+
+ // Free the associated thread slot.
+ uint32_t tid = socket_->get_tid ();
+ empty_slots.push_back (tid);
+ slots [tid] = NULL;
+
+ // Remove the socket from the list of sockets.
+ sockets.erase (socket_);
+
+ // If zmq_ctx_term() was already called and there are no more socket
+ // we can ask reaper thread to terminate.
+ if (terminating && sockets.empty ())
+ reaper->stop ();
+}
+
+zmq::object_t *zmq::ctx_t::get_reaper ()
+{
+ return reaper;
+}
+
+void zmq::ctx_t::start_thread (thread_t &thread_, thread_fn *tfn_, void *arg_) const
+{
+ static unsigned int nthreads_started = 0;
+
+ thread_.setSchedulingParameters(thread_priority, thread_sched_policy, thread_affinity_cpus);
+ thread_.start(tfn_, arg_);
+#ifndef ZMQ_HAVE_ANDROID
+ std::ostringstream s;
+ if (!thread_name_prefix.empty())
+ s << thread_name_prefix << "/";
+ s << "ZMQbg/" << nthreads_started;
+ thread_.setThreadName (s.str().c_str());
+#endif
+ nthreads_started++;
+}
+
+void zmq::ctx_t::send_command (uint32_t tid_, const command_t &command_)
+{
+ slots [tid_]->send (command_);
+}
+
+zmq::io_thread_t *zmq::ctx_t::choose_io_thread (uint64_t affinity_)
+{
+ if (io_threads.empty ())
+ return NULL;
+
+ // Find the I/O thread with minimum load.
+ int min_load = -1;
+ io_thread_t *selected_io_thread = NULL;
+ for (io_threads_t::size_type i = 0; i != io_threads.size (); i++) {
+ if (!affinity_ || (affinity_ & (uint64_t (1) << i))) {
+ int load = io_threads [i]->get_load ();
+ if (selected_io_thread == NULL || load < min_load) {
+ min_load = load;
+ selected_io_thread = io_threads [i];
+ }
+ }
+ }
+ return selected_io_thread;
+}
+
+int zmq::ctx_t::register_endpoint (const char *addr_,
+ const endpoint_t &endpoint_)
+{
+ scoped_lock_t locker(endpoints_sync);
+
+ const bool inserted = endpoints.ZMQ_MAP_INSERT_OR_EMPLACE (addr_,
+ endpoint_).second;
+ if (!inserted) {
+ errno = EADDRINUSE;
+ return -1;
+ }
+ return 0;
+}
+
+int zmq::ctx_t::unregister_endpoint (
+ const std::string &addr_, socket_base_t *socket_)
+{
+ scoped_lock_t locker(endpoints_sync);
+
+ const endpoints_t::iterator it = endpoints.find (addr_);
+ if (it == endpoints.end () || it->second.socket != socket_) {
+ errno = ENOENT;
+ return -1;
+ }
+
+ // Remove endpoint.
+ endpoints.erase (it);
+
+ return 0;
+}
+
+void zmq::ctx_t::unregister_endpoints (socket_base_t *socket_)
+{
+ scoped_lock_t locker(endpoints_sync);
+
+ endpoints_t::iterator it = endpoints.begin ();
+ while (it != endpoints.end ()) {
+ if (it->second.socket == socket_) {
+ endpoints_t::iterator to_erase = it;
+ ++it;
+ endpoints.erase (to_erase);
+ continue;
+ }
+ ++it;
+ }
+}
+
+zmq::endpoint_t zmq::ctx_t::find_endpoint (const char *addr_)
+{
+ scoped_lock_t locker(endpoints_sync);
+
+ endpoints_t::iterator it = endpoints.find (addr_);
+ if (it == endpoints.end ()) {
+ errno = ECONNREFUSED;
+ endpoint_t empty = {NULL, options_t()};
+ return empty;
+ }
+ endpoint_t endpoint = it->second;
+
+ // Increment the command sequence number of the peer so that it won't
+ // get deallocated until "bind" command is issued by the caller.
+ // The subsequent 'bind' has to be called with inc_seqnum parameter
+ // set to false, so that the seqnum isn't incremented twice.
+ endpoint.socket->inc_seqnum ();
+
+ return endpoint;
+}
+
+void zmq::ctx_t::pend_connection (const std::string &addr_,
+ const endpoint_t &endpoint_, pipe_t **pipes_)
+{
+ scoped_lock_t locker(endpoints_sync);
+
+ const pending_connection_t pending_connection = {endpoint_, pipes_ [0], pipes_ [1]};
+
+ endpoints_t::iterator it = endpoints.find (addr_);
+ if (it == endpoints.end ()) {
+ // Still no bind.
+ endpoint_.socket->inc_seqnum ();
+ pending_connections.ZMQ_MAP_INSERT_OR_EMPLACE (addr_, pending_connection);
+ } else {
+ // Bind has happened in the mean time, connect directly
+ connect_inproc_sockets(it->second.socket, it->second.options, pending_connection, connect_side);
+ }
+}
+
+void zmq::ctx_t::connect_pending (const char *addr_, zmq::socket_base_t *bind_socket_)
+{
+ scoped_lock_t locker(endpoints_sync);
+
+ std::pair pending = pending_connections.equal_range(addr_);
+ for (pending_connections_t::iterator p = pending.first; p != pending.second; ++p)
+ connect_inproc_sockets(bind_socket_, endpoints[addr_].options, p->second, bind_side);
+
+ pending_connections.erase(pending.first, pending.second);
+}
+
+void zmq::ctx_t::connect_inproc_sockets (zmq::socket_base_t *bind_socket_,
+ options_t& bind_options, const pending_connection_t &pending_connection_, side side_)
+{
+ bind_socket_->inc_seqnum();
+ pending_connection_.bind_pipe->set_tid (bind_socket_->get_tid ());
+
+ if (!bind_options.recv_routing_id) {
+ msg_t msg;
+ const bool ok = pending_connection_.bind_pipe->read (&msg);
+ zmq_assert (ok);
+ const int rc = msg.close ();
+ errno_assert (rc == 0);
+ }
+
+ bool conflate = pending_connection_.endpoint.options.conflate &&
+ (pending_connection_.endpoint.options.type == ZMQ_DEALER ||
+ pending_connection_.endpoint.options.type == ZMQ_PULL ||
+ pending_connection_.endpoint.options.type == ZMQ_PUSH ||
+ pending_connection_.endpoint.options.type == ZMQ_PUB ||
+ pending_connection_.endpoint.options.type == ZMQ_SUB);
+
+ if (!conflate) {
+ pending_connection_.connect_pipe->set_hwms_boost(bind_options.sndhwm, bind_options.rcvhwm);
+ pending_connection_.bind_pipe->set_hwms_boost(pending_connection_.endpoint.options.sndhwm, pending_connection_.endpoint.options.rcvhwm);
+
+ pending_connection_.connect_pipe->set_hwms(pending_connection_.endpoint.options.rcvhwm, pending_connection_.endpoint.options.sndhwm);
+ pending_connection_.bind_pipe->set_hwms(bind_options.rcvhwm, bind_options.sndhwm);
+ }
+ else {
+ pending_connection_.connect_pipe->set_hwms(-1, -1);
+ pending_connection_.bind_pipe->set_hwms(-1, -1);
+ }
+
+ if (side_ == bind_side) {
+ command_t cmd;
+ cmd.type = command_t::bind;
+ cmd.args.bind.pipe = pending_connection_.bind_pipe;
+ bind_socket_->process_command (cmd);
+ bind_socket_->send_inproc_connected (pending_connection_.endpoint.socket);
+ }
+ else
+ pending_connection_.connect_pipe->send_bind (bind_socket_, pending_connection_.bind_pipe, false);
+
+ // When a ctx is terminated all pending inproc connection will be
+ // connected, but the socket will already be closed and the pipe will be
+ // in waiting_for_delimiter state, which means no more writes can be done
+ // and the routing id write fails and causes an assert. Check if the socket
+ // is open before sending.
+ if (pending_connection_.endpoint.options.recv_routing_id &&
+ pending_connection_.endpoint.socket->check_tag ()) {
+ msg_t routing_id;
+ const int rc = routing_id.init_size (bind_options.routing_id_size);
+ errno_assert (rc == 0);
+ memcpy (routing_id.data (), bind_options.routing_id, bind_options.routing_id_size);
+ routing_id.set_flags (msg_t::routing_id);
+ const bool written = pending_connection_.bind_pipe->write (&routing_id);
+ zmq_assert (written);
+ pending_connection_.bind_pipe->flush ();
+ }
+}
+
+#ifdef ZMQ_HAVE_VMCI
+
+int zmq::ctx_t::get_vmci_socket_family ()
+{
+ zmq::scoped_lock_t locker(vmci_sync);
+
+ if (vmci_fd == -1) {
+ vmci_family = VMCISock_GetAFValueFd (&vmci_fd);
+
+ if (vmci_fd != -1) {
+#ifdef FD_CLOEXEC
+ int rc = fcntl (vmci_fd, F_SETFD, FD_CLOEXEC);
+ errno_assert (rc != -1);
+#endif
+ }
+ }
+
+ return vmci_family;
+}
+
+#endif
+
+// The last used socket ID, or 0 if no socket was used so far. Note that this
+// is a global variable. Thus, even sockets created in different contexts have
+// unique IDs.
+zmq::atomic_counter_t zmq::ctx_t::max_socket_id;
diff --git a/dep/libzmq/src/ctx.hpp b/dep/libzmq/src/ctx.hpp
new file mode 100644
index 0000000000..500b75e5a7
--- /dev/null
+++ b/dep/libzmq/src/ctx.hpp
@@ -0,0 +1,242 @@
+/*
+ Copyright (c) 2007-2017 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 .
+*/
+
+#ifndef __ZMQ_CTX_HPP_INCLUDED__
+#define __ZMQ_CTX_HPP_INCLUDED__
+
+#include