diff --git a/.gitignore b/.gitignore index e364447..2ba455d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,9 @@ /zeromq-*.tar.* /zeromq-*.src.rpm /zeromq-*.*.*/ -/libzmq-*.*.*/ /clog .build-*.*.log /noarch/ /x86_64/ /i?86/ /tarballs/ -/libzmq-*.*.*.tar.gz diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ae98bd8 --- /dev/null +++ b/LICENSE @@ -0,0 +1,17 @@ + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. diff --git a/sources b/sources index 69632ce..6ce4e29 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (zeromq-4.3.5.tar.gz) = a71d48aa977ad8941c1609947d8db2679fc7a951e4cd0c3a1127ae026d883c11bd4203cf315de87f95f5031aec459a731aec34e5ce5b667b8d0559b157952541 +a611ecc93fffeb6d058c0e6edf4ad4fb zeromq-4.1.4.tar.gz diff --git a/zeromq-configure-c99.patch b/zeromq-configure-c99.patch deleted file mode 100644 index 0bee83b..0000000 --- a/zeromq-configure-c99.patch +++ /dev/null @@ -1,37 +0,0 @@ -Build with -D_DEFAULT_SOURCE along with -std=c11 - -On its own, -std=c11 hides POSIX and other extensions from C headers -such as when building against glibc. This causes the -posix_memalign probe to fail incorrectly with compilers that do not -accept implicit function declarations. _DEFAULT_SOURCE is ignored by -most non-GNU/Linux systems or not relevant in this context, so there -is no separate check for adding it. - -Submitted upstream: - -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 68fb7251..f956f3fd 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -122,7 +122,7 @@ if (NOT MSVC) - if(NOT CMAKE_C_FLAGS MATCHES "-std=" AND NOT C_STANDARD AND NOT CMAKE_C_STANDARD) - check_c_compiler_flag("-std=c11" COMPILER_SUPPORTS_C11) - if(COMPILER_SUPPORTS_C11) -- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11") -+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_DEFAULT_SOURCE -std=c11") - else() - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99") - endif() -diff --git a/configure.ac b/configure.ac -index b9e13d4f..ffcc145b 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -66,7 +66,7 @@ ZMQ_ORIG_CXXFLAGS="${CXXFLAGS:-none}" - - # Checks for programs. - AC_PROG_CC --AX_CHECK_COMPILE_FLAG([-std=c11], [CFLAGS+=" -std=c11"], [AC_PROG_CC_C99]) -+AX_CHECK_COMPILE_FLAG([-std=c11], [CFLAGS+=" -std=c11 -D_DEFAULT_SOURCE"], [AC_PROG_CC_C99]) - AC_PROG_CXX - AX_CODE_COVERAGE - AM_PROG_CC_C_O diff --git a/zeromq.spec b/zeromq.spec index a4f31f1..c7fe1aa 100644 --- a/zeromq.spec +++ b/zeromq.spec @@ -1,29 +1,30 @@ %bcond_without pgm -%bcond_without unwind Name: zeromq -Version: 4.3.5 -Release: %autorelease +Version: 4.1.4 +Release: 5%{?dist} Summary: Software library for fast, message-based applications -License: MPL-2.0 AND BSD-3-Clause AND MIT -URL: https://zeromq.org -Source0: https://github.com/%{name}/libzmq/archive/v%{version}/%{name}-%{version}.tar.gz -Patch1: zeromq-configure-c99.patch +Group: System Environment/Libraries +License: LGPLv3+ +URL: http://www.zeromq.org +# VCS: git:http://github.com/zeromq/zeromq2.git +Source0: http://download.zeromq.org/zeromq-%{version}.tar.gz +Source1: https://raw.githubusercontent.com/zeromq/cppzmq/master/zmq.hpp +Source2: https://raw.githubusercontent.com/zeromq/cppzmq/master/LICENSE -BuildRequires: make BuildRequires: autoconf BuildRequires: automake -BuildRequires: gcc-c++ BuildRequires: libtool -BuildRequires: asciidoc -BuildRequires: xmlto BuildRequires: libsodium-devel -%if %{with unwind} -BuildRequires: libunwind-devel +BuildRequires: glib2-devel +%if ! (0%{?fedora} > 12 || 0%{?rhel} > 5) +BuildRequires: e2fsprogs-devel +BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) +%else +BuildRequires: libuuid-devel %endif - %if %{with pgm} BuildRequires: openpgm-devel BuildRequires: krb5-devel @@ -42,6 +43,7 @@ This package contains the ZeroMQ shared library. %package devel Summary: Development files for %{name} +Group: Development/Libraries Requires: %{name}%{?_isa} = %{version}-%{release} @@ -50,64 +52,200 @@ The %{name}-devel package contains libraries and header files for developing applications that use %{name}. +%package -n cppzmq-devel +Summary: Development files for cppzmq +Group: Development/Libraries +License: MIT +Requires: %{name}-devel%{?_isa} = %{version}-%{release} + + +%description -n cppzmq-devel +The cppzmq-devel package contains libraries and header files for +developing applications that use the C++ header files of %{name}. + + %prep -%autosetup -p1 +%setup -q +cp -a %{SOURCE2} . -# Remove bundled code. -rm -rf external/wepoll +# zeromq.x86_64: W: file-not-utf8 /usr/share/doc/zeromq/ChangeLog +iconv -f iso8859-1 -t utf-8 ChangeLog > ChangeLog.conv && mv -f ChangeLog.conv ChangeLog -# Fix permissions. -chmod -x src/xsub.hpp +# Don't turn warnings into errors +sed -i "s/libzmq_werror=\"yes\"/libzmq_werror=\"no\"/g" \ + configure + +# Sed version number of openpgm into configure +%global openpgm_pc $(basename %{_libdir}/pkgconfig/openpgm*.pc .pc) +sed -i "s/openpgm-[0-9].[0-9]/%{openpgm_pc}/g" \ + configure* %build autoreconf -fi +# Don't turn warnings into errors +sed -i "s/libzmq_werror=\"yes\"/libzmq_werror=\"no\"/g" \ + configure %configure \ %if %{with pgm} --with-pgm \ --with-libgssapi_krb5 \ %endif - --with-libsodium \ - --enable-drafts \ -%if %{with unwind} - --enable-libunwind \ -%endif - --disable-Werror \ --disable-static -%make_build +make %{?_smp_mflags} V=1 %install -%make_install +rm -rf %{buildroot} +make install DESTDIR=%{buildroot} INSTALL="install -p" +install -m 644 -p %{SOURCE1} %{buildroot}%{_includedir}/ # remove *.la rm %{buildroot}%{_libdir}/libzmq.la %check -%ifarch s390x -make check V=1 XFAIL_TESTS=tests/test_radio_dish || ( cat test-suite.log && exit 1 ) -%endif +make check V=1 -%ldconfig_scriptlets +%post -p /sbin/ldconfig + + +%postun -p /sbin/ldconfig %files -%doc README.md AUTHORS NEWS -%license LICENSE +%doc AUTHORS ChangeLog MAINTAINERS NEWS +%license COPYING COPYING.LESSER %{_bindir}/curve_keygen -%{_libdir}/libzmq.so.5* -%{_mandir}/man3/zmq_* -%{_mandir}/man7/zmq_* -%{_mandir}/man7/zmq.* +%{_libdir}/libzmq.so.* %files devel %{_libdir}/libzmq.so %{_libdir}/pkgconfig/libzmq.pc %{_includedir}/zmq*.h +%{_mandir}/man3/zmq* +%{_mandir}/man7/zmq* + +%files -n cppzmq-devel +%license LICENSE +%{_includedir}/zmq.hpp %changelog -%autochangelog +* Mon Mar 07 2016 Remi Collet - 4.1.4-5 +- rebuild for new libsodium soname +* Sun Feb 14 2016 Thomas Spura - 4.1.4-4 +- Remove Werror from compile flags + +* Fri Feb 05 2016 Fedora Release Engineering - 4.1.4-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Sun Jan 24 2016 Thomas Spura - 4.1.4-2 +- Enable krb5 and fix building of pgm (#1301197) + +* Sat Dec 19 2015 Thomas Spura - 4.1.4-1 +- update to 4.1.4 (#1292814) +- refresh zmq.hpp + +* Mon Aug 24 2015 Thomas Spura - 4.1.3-1 +- update to 4.1.3 (#1256209) +- ipv6 patch included upstream +- refresh zmq.hpp + +* Tue Jun 23 2015 Thomas Spura - 4.1.2-1 +- update to 4.1.2 +- add upstream patch to fix problem with ipv6 + +* Fri Jun 19 2015 Fedora Release Engineering - 4.0.5-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Mon Jun 08 2015 Thomas Spura - 4.0.5-4 +- Add zmq.hpp, which originally belonged to zeromq: + https://github.com/zeromq/cppzmq/issues/48 + +* Tue May 19 2015 Thomas Spura - 4.0.5-3 +- Cherry-pick patch for protocol downgrade attack (#1221666, CVE-2014-9721) +- Remove Obsoletes:zeromq-utils +- Remove %%defattr + +* Sat May 02 2015 Kalev Lember - 4.0.5-2 +- Rebuilt for GCC 5 C++11 ABI change + +* Mon Nov 17 2014 Thomas Spura - 4.0.5-1 +- update to 4.0.5 + +* Mon Aug 18 2014 Fedora Release Engineering - 2.2.0-10 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Sat Jun 07 2014 Fedora Release Engineering - 2.2.0-9 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Sun Aug 04 2013 Fedora Release Engineering - 2.2.0-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild + +* Fri May 17 2013 Thomas Spura - 2.2.0-7 +- Rebuilt for openpm-5.2 and sed correct version into configure (#963894) + +* Wed Mar 27 2013 Thomas Spura - 2.2.0-6 +- run autoreconf before configure so aarch64 is supported (#926859) + +* Fri Feb 15 2013 Fedora Release Engineering - 2.2.0-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Mon Jan 14 2013 Thomas Spura - 2.2.0-4 +- delete foreign files with dubious license in %%prep (#892111) + +* Mon Dec 24 2012 Thomas Spura - 2.2.0-3 +- add bcond_without pgm macro (Jose Pedro Oliveira, #867182) +- remove bundled pgm +- build against openpgm + +* Sun Jul 22 2012 Fedora Release Engineering - 2.2.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Thu Apr 26 2012 Thomas Spura - 2.2.0-1 +- update to 2.2.0 + +* Sat Jan 7 2012 Thomas Spura - 2.1.11-1 +- update to 2.1.11 (as part of rebuilding with gcc-4.7) + +* Tue Sep 20 2011 Thomas Spura - 2.1.9-1 +- update to 2.1.9 +- add check section + +* Wed Apr 6 2011 Thomas Spura - 2.1.4-1 +- update to new version (#690199) + +* Wed Mar 23 2011 Thomas Spura - 2.1.3-1 +- update to new version (#690199) +- utils subpackage was removed upstream + (obsolete it) + +* Tue Feb 08 2011 Fedora Release Engineering - 2.0.10-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Thu Jan 13 2011 Pavel Zhukov - 2.0.10-1 +- update version +- add rpath delete +- change includedir filelist + +* Fri Aug 27 2010 Thomas Spura - 2.0.8-1 +- update to new version + +* Fri Jul 23 2010 Thomas Spura - 2.0.7-4 +- upstream VCS changed +- remove buildroot / %%clean +- change descriptions + +* Tue Jul 20 2010 Thomas Spura - 2.0.7-3 +- move binaries to seperate utils package + +* Sat Jun 12 2010 Thomas Spura - 2.0.7-2 +- remove BR: libstdc++-devel +- move man3 to the devel package +- change group to System Environment/Libraries + +* Sat Jun 12 2010 Thomas Spura - 2.0.7-1 +- initial package (based on upstreams example one) diff --git a/zmq.hpp b/zmq.hpp new file mode 100644 index 0000000..e4ed26d --- /dev/null +++ b/zmq.hpp @@ -0,0 +1,789 @@ +/* + Copyright (c) 2009-2011 250bpm s.r.o. + Copyright (c) 2011 Botond Ballo + Copyright (c) 2007-2009 iMatix Corporation + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. +*/ + +#ifndef __ZMQ_HPP_INCLUDED__ +#define __ZMQ_HPP_INCLUDED__ + +#if __cplusplus >= 201103L +#define ZMQ_CPP11 +#define ZMQ_NOTHROW noexcept +#define ZMQ_EXPLICIT explicit +#else + #define ZMQ_CPP03 + #define ZMQ_NOTHROW + #define ZMQ_EXPLICIT +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifdef ZMQ_CPP11 +#include +#include +#endif + +// Detect whether the compiler supports C++11 rvalue references. +#if (defined(__GNUC__) && (__GNUC__ > 4 || \ + (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) && \ + defined(__GXX_EXPERIMENTAL_CXX0X__)) + #define ZMQ_HAS_RVALUE_REFS + #define ZMQ_DELETED_FUNCTION = delete +#elif defined(__clang__) + #if __has_feature(cxx_rvalue_references) + #define ZMQ_HAS_RVALUE_REFS + #endif + + #if __has_feature(cxx_deleted_functions) + #define ZMQ_DELETED_FUNCTION = delete + #else + #define ZMQ_DELETED_FUNCTION + #endif +#elif defined(_MSC_VER) && (_MSC_VER >= 1600) + #define ZMQ_HAS_RVALUE_REFS + #define ZMQ_DELETED_FUNCTION +#else + #define ZMQ_DELETED_FUNCTION +#endif + +#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3, 3, 0) +#define ZMQ_NEW_MONITOR_EVENT_LAYOUT +#endif + +#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 1, 0) +#define ZMQ_HAS_PROXY_STEERABLE +/* Socket event data */ +typedef struct { + uint16_t event; // id of the event as bitfield + int32_t value ; // value is either error code, fd or reconnect interval +} zmq_event_t; +#endif + +// Avoid using deprecated message receive function when possible +#if ZMQ_VERSION < ZMQ_MAKE_VERSION(3, 2, 0) +# define zmq_msg_recv(msg, socket, flags) zmq_recvmsg(socket, msg, flags) +#endif + + +// In order to prevent unused variable warnings when building in non-debug +// mode use this macro to make assertions. +#ifndef NDEBUG +# define ZMQ_ASSERT(expression) assert(expression) +#else +# define ZMQ_ASSERT(expression) (void)(expression) +#endif + +namespace zmq +{ + + typedef zmq_free_fn free_fn; + typedef zmq_pollitem_t pollitem_t; + + class error_t : public std::exception + { + public: + + error_t () : errnum (zmq_errno ()) {} + + virtual const char *what () const throw () + { + return zmq_strerror (errnum); + } + + int num () const + { + return errnum; + } + + private: + + int errnum; + }; + + inline int poll (zmq_pollitem_t const* items_, size_t nitems_, long timeout_ = -1) + { + int rc = zmq_poll (const_cast(items_), static_cast(nitems_), timeout_); + if (rc < 0) + throw error_t (); + return rc; + } + + inline int poll(zmq_pollitem_t const* items, size_t nitems) + { + return poll(items, nitems, -1); + } + + #ifdef ZMQ_CPP11 + inline int poll(zmq_pollitem_t const* items, size_t nitems, std::chrono::milliseconds timeout) + { + return poll(items, nitems, timeout.count() ); + } + + inline int poll(std::vector const& items, std::chrono::milliseconds timeout) + { + return poll(items.data(), items.size(), timeout.count() ); + } + + inline int poll(std::vector const& items, long timeout_ = -1) + { + return poll(items.data(), items.size(), timeout_); + } + #endif + + + + inline void proxy (void *frontend, void *backend, void *capture) + { + int rc = zmq_proxy (frontend, backend, capture); + if (rc != 0) + throw error_t (); + } + +#ifdef ZMQ_HAS_PROXY_STEERABLE + inline void proxy_steerable (void *frontend, void *backend, void *capture, void *control) + { + int rc = zmq_proxy_steerable (frontend, backend, capture, control); + if (rc != 0) + throw error_t (); + } +#endif + + inline void version (int *major_, int *minor_, int *patch_) + { + zmq_version (major_, minor_, patch_); + } + + #ifdef ZMQ_CPP11 + inline std::tuple version() + { + std::tuple v; + zmq_version(&std::get<0>(v), &std::get<1>(v), &std::get<2>(v) ); + return v; + } + #endif + + class message_t + { + friend class socket_t; + + public: + + inline message_t () + { + int rc = zmq_msg_init (&msg); + if (rc != 0) + throw error_t (); + } + + inline explicit message_t (size_t size_) + { + int rc = zmq_msg_init_size (&msg, size_); + if (rc != 0) + throw error_t (); + } + + template message_t(I first, I last): + msg() + { + typedef typename std::iterator_traits::difference_type size_type; + typedef typename std::iterator_traits::value_type value_t; + + size_type const size_ = std::distance(first, last)*sizeof(value_t); + int const rc = zmq_msg_init_size (&msg, size_); + if (rc != 0) + throw error_t (); + value_t* dest = data(); + while (first != last) + { + *dest = *first; + ++dest; ++first; + } + } + + inline message_t (const void *data_, size_t size_) + { + int rc = zmq_msg_init_size (&msg, size_); + if (rc != 0) + throw error_t (); + memcpy(data(), data_, size_); + } + + inline message_t (void *data_, size_t size_, free_fn *ffn_, + void *hint_ = NULL) + { + int rc = zmq_msg_init_data (&msg, data_, size_, ffn_, hint_); + if (rc != 0) + throw error_t (); + } + +#ifdef ZMQ_HAS_RVALUE_REFS + inline message_t (message_t &&rhs): msg (rhs.msg) + { + int rc = zmq_msg_init (&rhs.msg); + if (rc != 0) + throw error_t (); + } + + inline message_t &operator = (message_t &&rhs) ZMQ_NOTHROW + { + std::swap (msg, rhs.msg); + return *this; + } +#endif + + inline ~message_t () ZMQ_NOTHROW + { + int rc = zmq_msg_close (&msg); + ZMQ_ASSERT (rc == 0); + } + + inline void rebuild () + { + int rc = zmq_msg_close (&msg); + if (rc != 0) + throw error_t (); + rc = zmq_msg_init (&msg); + if (rc != 0) + throw error_t (); + } + + inline void rebuild (size_t size_) + { + int rc = zmq_msg_close (&msg); + if (rc != 0) + throw error_t (); + rc = zmq_msg_init_size (&msg, size_); + if (rc != 0) + throw error_t (); + } + + inline void rebuild (const void *data_, size_t size_) + { + int rc = zmq_msg_close (&msg); + if (rc != 0) + throw error_t (); + rc = zmq_msg_init_size (&msg, size_); + if (rc != 0) + throw error_t (); + memcpy(data(), data_, size_); + } + + inline void rebuild (void *data_, size_t size_, free_fn *ffn_, + void *hint_ = NULL) + { + int rc = zmq_msg_close (&msg); + if (rc != 0) + throw error_t (); + rc = zmq_msg_init_data (&msg, data_, size_, ffn_, hint_); + if (rc != 0) + throw error_t (); + } + + inline void move (message_t const *msg_) + { + int rc = zmq_msg_move (&msg, const_cast(&(msg_->msg))); + if (rc != 0) + throw error_t (); + } + + inline void copy (message_t const *msg_) + { + int rc = zmq_msg_copy (&msg, const_cast(&(msg_->msg))); + if (rc != 0) + throw error_t (); + } + + inline bool more () const ZMQ_NOTHROW + { + int rc = zmq_msg_more (const_cast(&msg) ); + return rc != 0; + } + + inline void *data () ZMQ_NOTHROW + { + return zmq_msg_data (&msg); + } + + inline const void* data () const ZMQ_NOTHROW + { + return zmq_msg_data (const_cast(&msg)); + } + + inline size_t size () const ZMQ_NOTHROW + { + return zmq_msg_size (const_cast(&msg)); + } + + template T* data() ZMQ_NOTHROW + { + return static_cast( data() ); + } + + template T const* data() const ZMQ_NOTHROW + { + return static_cast( data() ); + } + + + private: + // The underlying message + zmq_msg_t msg; + + // Disable implicit message copying, so that users won't use shared + // messages (less efficient) without being aware of the fact. + message_t (const message_t&) ZMQ_DELETED_FUNCTION; + void operator = (const message_t&) ZMQ_DELETED_FUNCTION; + }; + + class context_t + { + friend class socket_t; + + public: + inline context_t () + { + ptr = zmq_ctx_new (); + if (ptr == NULL) + throw error_t (); + } + + + inline explicit context_t (int io_threads_, int max_sockets_ = ZMQ_MAX_SOCKETS_DFLT) + { + ptr = zmq_ctx_new (); + if (ptr == NULL) + throw error_t (); + + int rc = zmq_ctx_set (ptr, ZMQ_IO_THREADS, io_threads_); + ZMQ_ASSERT (rc == 0); + + rc = zmq_ctx_set (ptr, ZMQ_MAX_SOCKETS, max_sockets_); + ZMQ_ASSERT (rc == 0); + } + +#ifdef ZMQ_HAS_RVALUE_REFS + inline context_t (context_t &&rhs) ZMQ_NOTHROW : ptr (rhs.ptr) + { + rhs.ptr = NULL; + } + inline context_t &operator = (context_t &&rhs) ZMQ_NOTHROW + { + std::swap (ptr, rhs.ptr); + return *this; + } +#endif + + inline ~context_t () ZMQ_NOTHROW + { + int rc = zmq_ctx_destroy (ptr); + ZMQ_ASSERT (rc == 0); + } + + inline void close() ZMQ_NOTHROW + { + int rc = zmq_ctx_shutdown (ptr); + ZMQ_ASSERT (rc == 0); + } + + // Be careful with this, it's probably only useful for + // using the C api together with an existing C++ api. + // Normally you should never need to use this. + inline ZMQ_EXPLICIT operator void* () ZMQ_NOTHROW + { + return ptr; + } + + inline ZMQ_EXPLICIT operator void const* () const ZMQ_NOTHROW + { + return ptr; + } + private: + + void *ptr; + + context_t (const context_t&) ZMQ_DELETED_FUNCTION; + void operator = (const context_t&) ZMQ_DELETED_FUNCTION; + }; + + #ifdef ZMQ_CPP11 + enum class socket_type: int + { + req = ZMQ_REQ, + rep = ZMQ_REP, + dealer = ZMQ_DEALER, + router = ZMQ_ROUTER, + pub = ZMQ_PUB, + sub = ZMQ_SUB, + xpub = ZMQ_XPUB, + xsub = ZMQ_XSUB, + push = ZMQ_PUSH, + pull = ZMQ_PULL, +#if ZMQ_VERSION_MAJOR < 4 + pair = ZMQ_PAIR +#else + pair = ZMQ_PAIR, + stream = ZMQ_STREAM +#endif + }; + #endif + + class socket_t + { + friend class monitor_t; + public: + inline socket_t(context_t& context_, int type_) + { + init(context_, type_); + } + + #ifdef ZMQ_CPP11 + inline socket_t(context_t& context_, socket_type type_) + { + init(context_, static_cast(type_)); + } + #endif + +#ifdef ZMQ_HAS_RVALUE_REFS + inline socket_t(socket_t&& rhs) ZMQ_NOTHROW : ptr(rhs.ptr) + { + rhs.ptr = NULL; + } + inline socket_t& operator=(socket_t&& rhs) ZMQ_NOTHROW + { + std::swap(ptr, rhs.ptr); + return *this; + } +#endif + + inline ~socket_t () ZMQ_NOTHROW + { + close(); + } + + inline ZMQ_EXPLICIT operator void* () ZMQ_NOTHROW + { + return ptr; + } + + inline ZMQ_EXPLICIT operator void const* () const ZMQ_NOTHROW + { + return ptr; + } + + inline void close() ZMQ_NOTHROW + { + if(ptr == NULL) + // already closed + return ; + int rc = zmq_close (ptr); + ZMQ_ASSERT (rc == 0); + ptr = 0 ; + } + + template void setsockopt(int option_, T const& optval) + { + setsockopt(option_, &optval, sizeof(T) ); + } + + inline void setsockopt (int option_, const void *optval_, + size_t optvallen_) + { + int rc = zmq_setsockopt (ptr, option_, optval_, optvallen_); + if (rc != 0) + throw error_t (); + } + + inline void getsockopt (int option_, void *optval_, + size_t *optvallen_) const + { + int rc = zmq_getsockopt (ptr, option_, optval_, optvallen_); + if (rc != 0) + throw error_t (); + } + + template T getsockopt(int option_) const + { + T optval; + size_t optlen = sizeof(T); + getsockopt(option_, &optval, &optlen ); + return optval; + } + + inline void bind(std::string const& addr) + { + bind(addr.c_str()); + } + + inline void bind (const char *addr_) + { + int rc = zmq_bind (ptr, addr_); + if (rc != 0) + throw error_t (); + } + + inline void unbind(std::string const& addr) + { + unbind(addr.c_str()); + } + + inline void unbind (const char *addr_) + { + int rc = zmq_unbind (ptr, addr_); + if (rc != 0) + throw error_t (); + } + + inline void connect(std::string const& addr) + { + connect(addr.c_str()); + } + + inline void connect (const char *addr_) + { + int rc = zmq_connect (ptr, addr_); + if (rc != 0) + throw error_t (); + } + + inline void disconnect(std::string const& addr) + { + disconnect(addr.c_str()); + } + + inline void disconnect (const char *addr_) + { + int rc = zmq_disconnect (ptr, addr_); + if (rc != 0) + throw error_t (); + } + + inline bool connected() const ZMQ_NOTHROW + { + return(ptr != NULL); + } + + inline size_t send (const void *buf_, size_t len_, int flags_ = 0) + { + int nbytes = zmq_send (ptr, buf_, len_, flags_); + if (nbytes >= 0) + return (size_t) nbytes; + if (zmq_errno () == EAGAIN) + return 0; + throw error_t (); + } + + inline bool send (message_t &msg_, int flags_ = 0) + { + int nbytes = zmq_msg_send (&(msg_.msg), ptr, flags_); + if (nbytes >= 0) + return true; + if (zmq_errno () == EAGAIN) + return false; + throw error_t (); + } + + template bool send(I first, I last, int flags_=0) + { + zmq::message_t msg(first, last); + return send(msg, flags_); + } + +#ifdef ZMQ_HAS_RVALUE_REFS + inline bool send (message_t &&msg_, int flags_ = 0) + { + return send(msg_, flags_); + } +#endif + + inline size_t recv (void *buf_, size_t len_, int flags_ = 0) + { + int nbytes = zmq_recv (ptr, buf_, len_, flags_); + if (nbytes >= 0) + return (size_t) nbytes; + if (zmq_errno () == EAGAIN) + return 0; + throw error_t (); + } + + inline bool recv (message_t *msg_, int flags_ = 0) + { + int nbytes = zmq_msg_recv (&(msg_->msg), ptr, flags_); + if (nbytes >= 0) + return true; + if (zmq_errno () == EAGAIN) + return false; + throw error_t (); + } + + private: + inline void init(context_t& context_, int type_) + { + ctxptr = context_.ptr; + ptr = zmq_socket (context_.ptr, type_ ); + if (ptr == NULL) + throw error_t (); + } + + void *ptr; + void *ctxptr; + + socket_t (const socket_t&) ZMQ_DELETED_FUNCTION; + void operator = (const socket_t&) ZMQ_DELETED_FUNCTION; + }; + + class monitor_t + { + public: + monitor_t() : socketPtr(NULL) {} + virtual ~monitor_t() {} + + void monitor(socket_t &socket, std::string const& addr, int events = ZMQ_EVENT_ALL) + { + monitor(socket, addr.c_str(), events); + } + + void monitor(socket_t &socket, const char *addr_, int events = ZMQ_EVENT_ALL) + { + int rc = zmq_socket_monitor(socket.ptr, addr_, events); + if (rc != 0) + throw error_t (); + + socketPtr = socket.ptr; + void *s = zmq_socket (socket.ctxptr, ZMQ_PAIR); + assert (s); + + rc = zmq_connect (s, addr_); + assert (rc == 0); + + on_monitor_started(); + + while (true) { + zmq_msg_t eventMsg; + zmq_msg_init (&eventMsg); + rc = zmq_msg_recv (&eventMsg, s, 0); + if (rc == -1 && zmq_errno() == ETERM) + break; + assert (rc != -1); +#if ZMQ_VERSION_MAJOR >= 4 + const char* data = static_cast(zmq_msg_data(&eventMsg)); + zmq_event_t msgEvent; + memcpy(&msgEvent.event, data, sizeof(uint16_t)); data += sizeof(uint16_t); + memcpy(&msgEvent.value, data, sizeof(int32_t)); + zmq_event_t* event = &msgEvent; +#else + zmq_event_t* event = static_cast(zmq_msg_data(&eventMsg)); +#endif + +#ifdef ZMQ_NEW_MONITOR_EVENT_LAYOUT + zmq_msg_t addrMsg; + zmq_msg_init (&addrMsg); + rc = zmq_msg_recv (&addrMsg, s, 0); + if (rc == -1 && zmq_errno() == ETERM) + break; + assert (rc != -1); + const char* str = static_cast(zmq_msg_data (&addrMsg)); + std::string address(str, str + zmq_msg_size(&addrMsg)); + zmq_msg_close (&addrMsg); +#else + // Bit of a hack, but all events in the zmq_event_t union have the same layout so this will work for all event types. + std::string address = event->data.connected.addr; +#endif + +#ifdef ZMQ_EVENT_MONITOR_STOPPED + if (event->event == ZMQ_EVENT_MONITOR_STOPPED) + break; +#endif + + switch (event->event) { + case ZMQ_EVENT_CONNECTED: + on_event_connected(*event, address.c_str()); + break; + case ZMQ_EVENT_CONNECT_DELAYED: + on_event_connect_delayed(*event, address.c_str()); + break; + case ZMQ_EVENT_CONNECT_RETRIED: + on_event_connect_retried(*event, address.c_str()); + break; + case ZMQ_EVENT_LISTENING: + on_event_listening(*event, address.c_str()); + break; + case ZMQ_EVENT_BIND_FAILED: + on_event_bind_failed(*event, address.c_str()); + break; + case ZMQ_EVENT_ACCEPTED: + on_event_accepted(*event, address.c_str()); + break; + case ZMQ_EVENT_ACCEPT_FAILED: + on_event_accept_failed(*event, address.c_str()); + break; + case ZMQ_EVENT_CLOSED: + on_event_closed(*event, address.c_str()); + break; + case ZMQ_EVENT_CLOSE_FAILED: + on_event_close_failed(*event, address.c_str()); + break; + case ZMQ_EVENT_DISCONNECTED: + on_event_disconnected(*event, address.c_str()); + break; + default: + on_event_unknown(*event, address.c_str()); + break; + } + zmq_msg_close (&eventMsg); + } + zmq_close (s); + socketPtr = NULL; + } + +#ifdef ZMQ_EVENT_MONITOR_STOPPED + void abort() + { + if (socketPtr) + zmq_socket_monitor(socketPtr, NULL, 0); + } +#endif + virtual void on_monitor_started() {} + virtual void on_event_connected(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } + virtual void on_event_connect_delayed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } + virtual void on_event_connect_retried(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } + virtual void on_event_listening(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } + virtual void on_event_bind_failed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } + virtual void on_event_accepted(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } + virtual void on_event_accept_failed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } + virtual void on_event_closed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } + virtual void on_event_close_failed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } + virtual void on_event_disconnected(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } + virtual void on_event_unknown(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } + private: + void* socketPtr; + }; +} + +#endif