육현진

Upload new file

1 +/*
2 + Copyright (c) 2016-2017 ZeroMQ community
3 + Copyright (c) 2009-2011 250bpm s.r.o.
4 + Copyright (c) 2011 Botond Ballo
5 + Copyright (c) 2007-2009 iMatix Corporation
6 +
7 + Permission is hereby granted, free of charge, to any person obtaining a copy
8 + of this software and associated documentation files (the "Software"), to
9 + deal in the Software without restriction, including without limitation the
10 + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
11 + sell copies of the Software, and to permit persons to whom the Software is
12 + furnished to do so, subject to the following conditions:
13 +
14 + The above copyright notice and this permission notice shall be included in
15 + all copies or substantial portions of the Software.
16 +
17 + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23 + IN THE SOFTWARE.
24 +*/
25 +
26 +#ifndef __ZMQ_HPP_INCLUDED__
27 +#define __ZMQ_HPP_INCLUDED__
28 +
29 +#ifdef _WIN32
30 +#ifndef NOMINMAX
31 +#define NOMINMAX
32 +#endif
33 +#endif
34 +
35 +// included here for _HAS_CXX* macros
36 +#include <zmq.h>
37 +
38 +#if defined(_MSVC_LANG)
39 +#define CPPZMQ_LANG _MSVC_LANG
40 +#else
41 +#define CPPZMQ_LANG __cplusplus
42 +#endif
43 +// overwrite if specific language macros indicate higher version
44 +#if defined(_HAS_CXX14) && _HAS_CXX14 && CPPZMQ_LANG < 201402L
45 +#undef CPPZMQ_LANG
46 +#define CPPZMQ_LANG 201402L
47 +#endif
48 +#if defined(_HAS_CXX17) && _HAS_CXX17 && CPPZMQ_LANG < 201703L
49 +#undef CPPZMQ_LANG
50 +#define CPPZMQ_LANG 201703L
51 +#endif
52 +
53 +// macros defined if has a specific standard or greater
54 +#if CPPZMQ_LANG >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900)
55 +#define ZMQ_CPP11
56 +#endif
57 +#if CPPZMQ_LANG >= 201402L
58 +#define ZMQ_CPP14
59 +#endif
60 +#if CPPZMQ_LANG >= 201703L
61 +#define ZMQ_CPP17
62 +#endif
63 +
64 +#if defined(ZMQ_CPP14) && !defined(_MSC_VER)
65 +#define ZMQ_DEPRECATED(msg) [[deprecated(msg)]]
66 +#elif defined(_MSC_VER)
67 +#define ZMQ_DEPRECATED(msg) __declspec(deprecated(msg))
68 +#elif defined(__GNUC__)
69 +#define ZMQ_DEPRECATED(msg) __attribute__((deprecated(msg)))
70 +#else
71 +#define ZMQ_DEPRECATED(msg)
72 +#endif
73 +
74 +#if defined(ZMQ_CPP17)
75 +#define ZMQ_NODISCARD [[nodiscard]]
76 +#else
77 +#define ZMQ_NODISCARD
78 +#endif
79 +
80 +#if defined(ZMQ_CPP11)
81 +#define ZMQ_NOTHROW noexcept
82 +#define ZMQ_EXPLICIT explicit
83 +#define ZMQ_OVERRIDE override
84 +#define ZMQ_NULLPTR nullptr
85 +#define ZMQ_CONSTEXPR_FN constexpr
86 +#define ZMQ_CONSTEXPR_VAR constexpr
87 +#define ZMQ_CPP11_DEPRECATED(msg) ZMQ_DEPRECATED(msg)
88 +#else
89 +#define ZMQ_NOTHROW throw()
90 +#define ZMQ_EXPLICIT
91 +#define ZMQ_OVERRIDE
92 +#define ZMQ_NULLPTR 0
93 +#define ZMQ_CONSTEXPR_FN
94 +#define ZMQ_CONSTEXPR_VAR const
95 +#define ZMQ_CPP11_DEPRECATED(msg)
96 +#endif
97 +#if defined(ZMQ_CPP14) && (!defined(_MSC_VER) || _MSC_VER > 1900) && (!defined(__GNUC__) || __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ > 3))
98 +#define ZMQ_EXTENDED_CONSTEXPR
99 +#endif
100 +#if defined(ZMQ_CPP17)
101 +#define ZMQ_INLINE_VAR inline
102 +#define ZMQ_CONSTEXPR_IF constexpr
103 +#else
104 +#define ZMQ_INLINE_VAR
105 +#define ZMQ_CONSTEXPR_IF
106 +#endif
107 +
108 +#include <cassert>
109 +#include <cstring>
110 +
111 +#include <algorithm>
112 +#include <exception>
113 +#include <iomanip>
114 +#include <sstream>
115 +#include <string>
116 +#include <vector>
117 +#ifdef ZMQ_CPP11
118 +#include <array>
119 +#include <chrono>
120 +#include <tuple>
121 +#include <memory>
122 +#endif
123 +
124 +#if defined(__has_include) && defined(ZMQ_CPP17)
125 +#define CPPZMQ_HAS_INCLUDE_CPP17(X) __has_include(X)
126 +#else
127 +#define CPPZMQ_HAS_INCLUDE_CPP17(X) 0
128 +#endif
129 +
130 +#if CPPZMQ_HAS_INCLUDE_CPP17(<optional>) && !defined(CPPZMQ_HAS_OPTIONAL)
131 +#define CPPZMQ_HAS_OPTIONAL 1
132 +#endif
133 +#ifndef CPPZMQ_HAS_OPTIONAL
134 +#define CPPZMQ_HAS_OPTIONAL 0
135 +#elif CPPZMQ_HAS_OPTIONAL
136 +#include <optional>
137 +#endif
138 +
139 +#if CPPZMQ_HAS_INCLUDE_CPP17(<string_view>) && !defined(CPPZMQ_HAS_STRING_VIEW)
140 +#define CPPZMQ_HAS_STRING_VIEW 1
141 +#endif
142 +#ifndef CPPZMQ_HAS_STRING_VIEW
143 +#define CPPZMQ_HAS_STRING_VIEW 0
144 +#elif CPPZMQ_HAS_STRING_VIEW
145 +#include <string_view>
146 +#endif
147 +
148 +/* Version macros for compile-time API version detection */
149 +#define CPPZMQ_VERSION_MAJOR 4
150 +#define CPPZMQ_VERSION_MINOR 8
151 +#define CPPZMQ_VERSION_PATCH 1
152 +
153 +#define CPPZMQ_VERSION \
154 + ZMQ_MAKE_VERSION(CPPZMQ_VERSION_MAJOR, CPPZMQ_VERSION_MINOR, \
155 + CPPZMQ_VERSION_PATCH)
156 +
157 +// Detect whether the compiler supports C++11 rvalue references.
158 +#if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) \
159 + && defined(__GXX_EXPERIMENTAL_CXX0X__))
160 +#define ZMQ_HAS_RVALUE_REFS
161 +#define ZMQ_DELETED_FUNCTION = delete
162 +#elif defined(__clang__)
163 +#if __has_feature(cxx_rvalue_references)
164 +#define ZMQ_HAS_RVALUE_REFS
165 +#endif
166 +
167 +#if __has_feature(cxx_deleted_functions)
168 +#define ZMQ_DELETED_FUNCTION = delete
169 +#else
170 +#define ZMQ_DELETED_FUNCTION
171 +#endif
172 +#elif defined(_MSC_VER) && (_MSC_VER >= 1900)
173 +#define ZMQ_HAS_RVALUE_REFS
174 +#define ZMQ_DELETED_FUNCTION = delete
175 +#elif defined(_MSC_VER) && (_MSC_VER >= 1600)
176 +#define ZMQ_HAS_RVALUE_REFS
177 +#define ZMQ_DELETED_FUNCTION
178 +#else
179 +#define ZMQ_DELETED_FUNCTION
180 +#endif
181 +
182 +#if defined(ZMQ_CPP11) && !defined(__llvm__) && !defined(__INTEL_COMPILER) \
183 + && defined(__GNUC__) && __GNUC__ < 5
184 +#define ZMQ_CPP11_PARTIAL
185 +#elif defined(__GLIBCXX__) && __GLIBCXX__ < 20160805
186 +//the date here is the last date of gcc 4.9.4, which
187 +// effectively means libstdc++ from gcc 5.5 and higher won't trigger this branch
188 +#define ZMQ_CPP11_PARTIAL
189 +#endif
190 +
191 +#ifdef ZMQ_CPP11
192 +#ifdef ZMQ_CPP11_PARTIAL
193 +#define ZMQ_IS_TRIVIALLY_COPYABLE(T) __has_trivial_copy(T)
194 +#else
195 +#include <type_traits>
196 +#define ZMQ_IS_TRIVIALLY_COPYABLE(T) std::is_trivially_copyable<T>::value
197 +#endif
198 +#endif
199 +
200 +#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3, 3, 0)
201 +#define ZMQ_NEW_MONITOR_EVENT_LAYOUT
202 +#endif
203 +
204 +#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 1, 0)
205 +#define ZMQ_HAS_PROXY_STEERABLE
206 +/* Socket event data */
207 +typedef struct
208 +{
209 + uint16_t event; // id of the event as bitfield
210 + int32_t value; // value is either error code, fd or reconnect interval
211 +} zmq_event_t;
212 +#endif
213 +
214 +// Avoid using deprecated message receive function when possible
215 +#if ZMQ_VERSION < ZMQ_MAKE_VERSION(3, 2, 0)
216 +#define zmq_msg_recv(msg, socket, flags) zmq_recvmsg(socket, msg, flags)
217 +#endif
218 +
219 +
220 +// In order to prevent unused variable warnings when building in non-debug
221 +// mode use this macro to make assertions.
222 +#ifndef NDEBUG
223 +#define ZMQ_ASSERT(expression) assert(expression)
224 +#else
225 +#define ZMQ_ASSERT(expression) (void) (expression)
226 +#endif
227 +
228 +namespace zmq
229 +{
230 +#ifdef ZMQ_CPP11
231 +namespace detail
232 +{
233 +namespace ranges
234 +{
235 +using std::begin;
236 +using std::end;
237 +template<class T> auto begin(T &&r) -> decltype(begin(std::forward<T>(r)))
238 +{
239 + return begin(std::forward<T>(r));
240 +}
241 +template<class T> auto end(T &&r) -> decltype(end(std::forward<T>(r)))
242 +{
243 + return end(std::forward<T>(r));
244 +}
245 +} // namespace ranges
246 +
247 +template<class T> using void_t = void;
248 +
249 +template<class Iter>
250 +using iter_value_t = typename std::iterator_traits<Iter>::value_type;
251 +
252 +template<class Range>
253 +using range_iter_t = decltype(
254 + ranges::begin(std::declval<typename std::remove_reference<Range>::type &>()));
255 +
256 +template<class Range> using range_value_t = iter_value_t<range_iter_t<Range>>;
257 +
258 +template<class T, class = void> struct is_range : std::false_type
259 +{
260 +};
261 +
262 +template<class T>
263 +struct is_range<
264 + T,
265 + void_t<decltype(
266 + ranges::begin(std::declval<typename std::remove_reference<T>::type &>())
267 + == ranges::end(std::declval<typename std::remove_reference<T>::type &>()))>>
268 + : std::true_type
269 +{
270 +};
271 +
272 +} // namespace detail
273 +#endif
274 +
275 +typedef zmq_free_fn free_fn;
276 +typedef zmq_pollitem_t pollitem_t;
277 +
278 +// duplicate definition from libzmq 4.3.3
279 +#if defined _WIN32
280 +#if defined _WIN64
281 +typedef unsigned __int64 fd_t;
282 +#else
283 +typedef unsigned int fd_t;
284 +#endif
285 +#else
286 +typedef int fd_t;
287 +#endif
288 +
289 +class error_t : public std::exception
290 +{
291 + public:
292 + error_t() ZMQ_NOTHROW : errnum(zmq_errno()) {}
293 + explicit error_t(int err) ZMQ_NOTHROW : errnum(err) {}
294 + virtual const char *what() const ZMQ_NOTHROW ZMQ_OVERRIDE
295 + {
296 + return zmq_strerror(errnum);
297 + }
298 + int num() const ZMQ_NOTHROW { return errnum; }
299 +
300 + private:
301 + int errnum;
302 +};
303 +
304 +namespace detail {
305 +inline int poll(zmq_pollitem_t *items_, size_t nitems_, long timeout_)
306 +{
307 + int rc = zmq_poll(items_, static_cast<int>(nitems_), timeout_);
308 + if (rc < 0)
309 + throw error_t();
310 + return rc;
311 +}
312 +}
313 +
314 +#ifdef ZMQ_CPP11
315 +ZMQ_DEPRECATED("from 4.8.0, use poll taking std::chrono::duration instead of long")
316 +inline int poll(zmq_pollitem_t *items_, size_t nitems_, long timeout_)
317 +#else
318 +inline int poll(zmq_pollitem_t *items_, size_t nitems_, long timeout_ = -1)
319 +#endif
320 +{
321 + return detail::poll(items_, nitems_, timeout_);
322 +}
323 +
324 +ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items")
325 +inline int poll(zmq_pollitem_t const *items_, size_t nitems_, long timeout_ = -1)
326 +{
327 + return detail::poll(const_cast<zmq_pollitem_t *>(items_), nitems_, timeout_);
328 +}
329 +
330 +#ifdef ZMQ_CPP11
331 +ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items")
332 +inline int
333 +poll(zmq_pollitem_t const *items, size_t nitems, std::chrono::milliseconds timeout)
334 +{
335 + return detail::poll(const_cast<zmq_pollitem_t *>(items), nitems,
336 + static_cast<long>(timeout.count()));
337 +}
338 +
339 +ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items")
340 +inline int poll(std::vector<zmq_pollitem_t> const &items,
341 + std::chrono::milliseconds timeout)
342 +{
343 + return detail::poll(const_cast<zmq_pollitem_t *>(items.data()), items.size(),
344 + static_cast<long>(timeout.count()));
345 +}
346 +
347 +ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items")
348 +inline int poll(std::vector<zmq_pollitem_t> const &items, long timeout_ = -1)
349 +{
350 + return detail::poll(const_cast<zmq_pollitem_t *>(items.data()), items.size(), timeout_);
351 +}
352 +
353 +inline int
354 +poll(zmq_pollitem_t *items, size_t nitems, std::chrono::milliseconds timeout = std::chrono::milliseconds{-1})
355 +{
356 + return detail::poll(items, nitems, static_cast<long>(timeout.count()));
357 +}
358 +
359 +inline int poll(std::vector<zmq_pollitem_t> &items,
360 + std::chrono::milliseconds timeout = std::chrono::milliseconds{-1})
361 +{
362 + return detail::poll(items.data(), items.size(), static_cast<long>(timeout.count()));
363 +}
364 +
365 +ZMQ_DEPRECATED("from 4.3.1, use poll taking std::chrono::duration instead of long")
366 +inline int poll(std::vector<zmq_pollitem_t> &items, long timeout_)
367 +{
368 + return detail::poll(items.data(), items.size(), timeout_);
369 +}
370 +
371 +template<std::size_t SIZE>
372 +inline int poll(std::array<zmq_pollitem_t, SIZE> &items,
373 + std::chrono::milliseconds timeout = std::chrono::milliseconds{-1})
374 +{
375 + return detail::poll(items.data(), items.size(), static_cast<long>(timeout.count()));
376 +}
377 +#endif
378 +
379 +
380 +inline void version(int *major_, int *minor_, int *patch_)
381 +{
382 + zmq_version(major_, minor_, patch_);
383 +}
384 +
385 +#ifdef ZMQ_CPP11
386 +inline std::tuple<int, int, int> version()
387 +{
388 + std::tuple<int, int, int> v;
389 + zmq_version(&std::get<0>(v), &std::get<1>(v), &std::get<2>(v));
390 + return v;
391 +}
392 +
393 +#if !defined(ZMQ_CPP11_PARTIAL)
394 +namespace detail
395 +{
396 +template<class T> struct is_char_type
397 +{
398 + // true if character type for string literals in C++11
399 + static constexpr bool value =
400 + std::is_same<T, char>::value || std::is_same<T, wchar_t>::value
401 + || std::is_same<T, char16_t>::value || std::is_same<T, char32_t>::value;
402 +};
403 +}
404 +#endif
405 +
406 +#endif
407 +
408 +class message_t
409 +{
410 + public:
411 + message_t() ZMQ_NOTHROW
412 + {
413 + int rc = zmq_msg_init(&msg);
414 + ZMQ_ASSERT(rc == 0);
415 + }
416 +
417 + explicit message_t(size_t size_)
418 + {
419 + int rc = zmq_msg_init_size(&msg, size_);
420 + if (rc != 0)
421 + throw error_t();
422 + }
423 +
424 + template<class ForwardIter> message_t(ForwardIter first, ForwardIter last)
425 + {
426 + typedef typename std::iterator_traits<ForwardIter>::value_type value_t;
427 +
428 + assert(std::distance(first, last) >= 0);
429 + size_t const size_ =
430 + static_cast<size_t>(std::distance(first, last)) * sizeof(value_t);
431 + int const rc = zmq_msg_init_size(&msg, size_);
432 + if (rc != 0)
433 + throw error_t();
434 + std::copy(first, last, data<value_t>());
435 + }
436 +
437 + message_t(const void *data_, size_t size_)
438 + {
439 + int rc = zmq_msg_init_size(&msg, size_);
440 + if (rc != 0)
441 + throw error_t();
442 + if (size_) {
443 + // this constructor allows (nullptr, 0),
444 + // memcpy with a null pointer is UB
445 + memcpy(data(), data_, size_);
446 + }
447 + }
448 +
449 + message_t(void *data_, size_t size_, free_fn *ffn_, void *hint_ = ZMQ_NULLPTR)
450 + {
451 + int rc = zmq_msg_init_data(&msg, data_, size_, ffn_, hint_);
452 + if (rc != 0)
453 + throw error_t();
454 + }
455 +
456 + // overload set of string-like types and generic containers
457 +#if defined(ZMQ_CPP11) && !defined(ZMQ_CPP11_PARTIAL)
458 + // NOTE this constructor will include the null terminator
459 + // when called with a string literal.
460 + // An overload taking const char* can not be added because
461 + // it would be preferred over this function and break compatiblity.
462 + template<
463 + class Char,
464 + size_t N,
465 + typename = typename std::enable_if<detail::is_char_type<Char>::value>::type>
466 + ZMQ_DEPRECATED("from 4.7.0, use constructors taking iterators, (pointer, size) "
467 + "or strings instead")
468 + explicit message_t(const Char (&data)[N]) :
469 + message_t(detail::ranges::begin(data), detail::ranges::end(data))
470 + {
471 + }
472 +
473 + template<class Range,
474 + typename = typename std::enable_if<
475 + detail::is_range<Range>::value
476 + && ZMQ_IS_TRIVIALLY_COPYABLE(detail::range_value_t<Range>)
477 + && !detail::is_char_type<detail::range_value_t<Range>>::value
478 + && !std::is_same<Range, message_t>::value>::type>
479 + explicit message_t(const Range &rng) :
480 + message_t(detail::ranges::begin(rng), detail::ranges::end(rng))
481 + {
482 + }
483 +
484 + explicit message_t(const std::string &str) : message_t(str.data(), str.size()) {}
485 +
486 +#if CPPZMQ_HAS_STRING_VIEW
487 + explicit message_t(std::string_view str) : message_t(str.data(), str.size()) {}
488 +#endif
489 +
490 +#endif
491 +
492 +#ifdef ZMQ_HAS_RVALUE_REFS
493 + message_t(message_t &&rhs) ZMQ_NOTHROW : msg(rhs.msg)
494 + {
495 + int rc = zmq_msg_init(&rhs.msg);
496 + ZMQ_ASSERT(rc == 0);
497 + }
498 +
499 + message_t &operator=(message_t &&rhs) ZMQ_NOTHROW
500 + {
501 + std::swap(msg, rhs.msg);
502 + return *this;
503 + }
504 +#endif
505 +
506 + ~message_t() ZMQ_NOTHROW
507 + {
508 + int rc = zmq_msg_close(&msg);
509 + ZMQ_ASSERT(rc == 0);
510 + }
511 +
512 + void rebuild()
513 + {
514 + int rc = zmq_msg_close(&msg);
515 + if (rc != 0)
516 + throw error_t();
517 + rc = zmq_msg_init(&msg);
518 + ZMQ_ASSERT(rc == 0);
519 + }
520 +
521 + void rebuild(size_t size_)
522 + {
523 + int rc = zmq_msg_close(&msg);
524 + if (rc != 0)
525 + throw error_t();
526 + rc = zmq_msg_init_size(&msg, size_);
527 + if (rc != 0)
528 + throw error_t();
529 + }
530 +
531 + void rebuild(const void *data_, size_t size_)
532 + {
533 + int rc = zmq_msg_close(&msg);
534 + if (rc != 0)
535 + throw error_t();
536 + rc = zmq_msg_init_size(&msg, size_);
537 + if (rc != 0)
538 + throw error_t();
539 + memcpy(data(), data_, size_);
540 + }
541 +
542 + void rebuild(void *data_, size_t size_, free_fn *ffn_, void *hint_ = ZMQ_NULLPTR)
543 + {
544 + int rc = zmq_msg_close(&msg);
545 + if (rc != 0)
546 + throw error_t();
547 + rc = zmq_msg_init_data(&msg, data_, size_, ffn_, hint_);
548 + if (rc != 0)
549 + throw error_t();
550 + }
551 +
552 + ZMQ_DEPRECATED("from 4.3.1, use move taking non-const reference instead")
553 + void move(message_t const *msg_)
554 + {
555 + int rc = zmq_msg_move(&msg, const_cast<zmq_msg_t *>(msg_->handle()));
556 + if (rc != 0)
557 + throw error_t();
558 + }
559 +
560 + void move(message_t &msg_)
561 + {
562 + int rc = zmq_msg_move(&msg, msg_.handle());
563 + if (rc != 0)
564 + throw error_t();
565 + }
566 +
567 + ZMQ_DEPRECATED("from 4.3.1, use copy taking non-const reference instead")
568 + void copy(message_t const *msg_)
569 + {
570 + int rc = zmq_msg_copy(&msg, const_cast<zmq_msg_t *>(msg_->handle()));
571 + if (rc != 0)
572 + throw error_t();
573 + }
574 +
575 + void copy(message_t &msg_)
576 + {
577 + int rc = zmq_msg_copy(&msg, msg_.handle());
578 + if (rc != 0)
579 + throw error_t();
580 + }
581 +
582 + bool more() const ZMQ_NOTHROW
583 + {
584 + int rc = zmq_msg_more(const_cast<zmq_msg_t *>(&msg));
585 + return rc != 0;
586 + }
587 +
588 + void *data() ZMQ_NOTHROW { return zmq_msg_data(&msg); }
589 +
590 + const void *data() const ZMQ_NOTHROW
591 + {
592 + return zmq_msg_data(const_cast<zmq_msg_t *>(&msg));
593 + }
594 +
595 + size_t size() const ZMQ_NOTHROW
596 + {
597 + return zmq_msg_size(const_cast<zmq_msg_t *>(&msg));
598 + }
599 +
600 + ZMQ_NODISCARD bool empty() const ZMQ_NOTHROW { return size() == 0u; }
601 +
602 + template<typename T> T *data() ZMQ_NOTHROW { return static_cast<T *>(data()); }
603 +
604 + template<typename T> T const *data() const ZMQ_NOTHROW
605 + {
606 + return static_cast<T const *>(data());
607 + }
608 +
609 + ZMQ_DEPRECATED("from 4.3.0, use operator== instead")
610 + bool equal(const message_t *other) const ZMQ_NOTHROW { return *this == *other; }
611 +
612 + bool operator==(const message_t &other) const ZMQ_NOTHROW
613 + {
614 + const size_t my_size = size();
615 + return my_size == other.size() && 0 == memcmp(data(), other.data(), my_size);
616 + }
617 +
618 + bool operator!=(const message_t &other) const ZMQ_NOTHROW
619 + {
620 + return !(*this == other);
621 + }
622 +
623 +#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3, 2, 0)
624 + int get(int property_)
625 + {
626 + int value = zmq_msg_get(&msg, property_);
627 + if (value == -1)
628 + throw error_t();
629 + return value;
630 + }
631 +#endif
632 +
633 +#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 1, 0)
634 + const char *gets(const char *property_)
635 + {
636 + const char *value = zmq_msg_gets(&msg, property_);
637 + if (value == ZMQ_NULLPTR)
638 + throw error_t();
639 + return value;
640 + }
641 +#endif
642 +
643 +#if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 0)
644 + uint32_t routing_id() const
645 + {
646 + return zmq_msg_routing_id(const_cast<zmq_msg_t *>(&msg));
647 + }
648 +
649 + void set_routing_id(uint32_t routing_id)
650 + {
651 + int rc = zmq_msg_set_routing_id(&msg, routing_id);
652 + if (rc != 0)
653 + throw error_t();
654 + }
655 +
656 + const char *group() const
657 + {
658 + return zmq_msg_group(const_cast<zmq_msg_t *>(&msg));
659 + }
660 +
661 + void set_group(const char *group)
662 + {
663 + int rc = zmq_msg_set_group(&msg, group);
664 + if (rc != 0)
665 + throw error_t();
666 + }
667 +#endif
668 +
669 + // interpret message content as a string
670 + std::string to_string() const
671 + {
672 + return std::string(static_cast<const char *>(data()), size());
673 + }
674 +#if CPPZMQ_HAS_STRING_VIEW
675 + // interpret message content as a string
676 + std::string_view to_string_view() const noexcept
677 + {
678 + return std::string_view(static_cast<const char *>(data()), size());
679 + }
680 +#endif
681 +
682 + /** Dump content to string for debugging.
683 + * Ascii chars are readable, the rest is printed as hex.
684 + * Probably ridiculously slow.
685 + * Use to_string() or to_string_view() for
686 + * interpreting the message as a string.
687 + */
688 + std::string str() const
689 + {
690 + // Partly mutuated from the same method in zmq::multipart_t
691 + std::stringstream os;
692 +
693 + const unsigned char *msg_data = this->data<unsigned char>();
694 + unsigned char byte;
695 + size_t size = this->size();
696 + int is_ascii[2] = {0, 0};
697 +
698 + os << "zmq::message_t [size " << std::dec << std::setw(3)
699 + << std::setfill('0') << size << "] (";
700 + // Totally arbitrary
701 + if (size >= 1000) {
702 + os << "... too big to print)";
703 + } else {
704 + while (size--) {
705 + byte = *msg_data++;
706 +
707 + is_ascii[1] = (byte >= 32 && byte < 127);
708 + if (is_ascii[1] != is_ascii[0])
709 + os << " "; // Separate text/non text
710 +
711 + if (is_ascii[1]) {
712 + os << byte;
713 + } else {
714 + os << std::hex << std::uppercase << std::setw(2)
715 + << std::setfill('0') << static_cast<short>(byte);
716 + }
717 + is_ascii[0] = is_ascii[1];
718 + }
719 + os << ")";
720 + }
721 + return os.str();
722 + }
723 +
724 + void swap(message_t &other) ZMQ_NOTHROW
725 + {
726 + // this assumes zmq::msg_t from libzmq is trivially relocatable
727 + std::swap(msg, other.msg);
728 + }
729 +
730 + ZMQ_NODISCARD zmq_msg_t *handle() ZMQ_NOTHROW { return &msg; }
731 + ZMQ_NODISCARD const zmq_msg_t *handle() const ZMQ_NOTHROW { return &msg; }
732 +
733 + private:
734 + // The underlying message
735 + zmq_msg_t msg;
736 +
737 + // Disable implicit message copying, so that users won't use shared
738 + // messages (less efficient) without being aware of the fact.
739 + message_t(const message_t &) ZMQ_DELETED_FUNCTION;
740 + void operator=(const message_t &) ZMQ_DELETED_FUNCTION;
741 +};
742 +
743 +inline void swap(message_t &a, message_t &b) ZMQ_NOTHROW
744 +{
745 + a.swap(b);
746 +}
747 +
748 +#ifdef ZMQ_CPP11
749 +enum class ctxopt
750 +{
751 +#ifdef ZMQ_BLOCKY
752 + blocky = ZMQ_BLOCKY,
753 +#endif
754 +#ifdef ZMQ_IO_THREADS
755 + io_threads = ZMQ_IO_THREADS,
756 +#endif
757 +#ifdef ZMQ_THREAD_SCHED_POLICY
758 + thread_sched_policy = ZMQ_THREAD_SCHED_POLICY,
759 +#endif
760 +#ifdef ZMQ_THREAD_PRIORITY
761 + thread_priority = ZMQ_THREAD_PRIORITY,
762 +#endif
763 +#ifdef ZMQ_THREAD_AFFINITY_CPU_ADD
764 + thread_affinity_cpu_add = ZMQ_THREAD_AFFINITY_CPU_ADD,
765 +#endif
766 +#ifdef ZMQ_THREAD_AFFINITY_CPU_REMOVE
767 + thread_affinity_cpu_remove = ZMQ_THREAD_AFFINITY_CPU_REMOVE,
768 +#endif
769 +#ifdef ZMQ_THREAD_NAME_PREFIX
770 + thread_name_prefix = ZMQ_THREAD_NAME_PREFIX,
771 +#endif
772 +#ifdef ZMQ_MAX_MSGSZ
773 + max_msgsz = ZMQ_MAX_MSGSZ,
774 +#endif
775 +#ifdef ZMQ_ZERO_COPY_RECV
776 + zero_copy_recv = ZMQ_ZERO_COPY_RECV,
777 +#endif
778 +#ifdef ZMQ_MAX_SOCKETS
779 + max_sockets = ZMQ_MAX_SOCKETS,
780 +#endif
781 +#ifdef ZMQ_SOCKET_LIMIT
782 + socket_limit = ZMQ_SOCKET_LIMIT,
783 +#endif
784 +#ifdef ZMQ_IPV6
785 + ipv6 = ZMQ_IPV6,
786 +#endif
787 +#ifdef ZMQ_MSG_T_SIZE
788 + msg_t_size = ZMQ_MSG_T_SIZE
789 +#endif
790 +};
791 +#endif
792 +
793 +class context_t
794 +{
795 + public:
796 + context_t()
797 + {
798 + ptr = zmq_ctx_new();
799 + if (ptr == ZMQ_NULLPTR)
800 + throw error_t();
801 + }
802 +
803 +
804 + explicit context_t(int io_threads_, int max_sockets_ = ZMQ_MAX_SOCKETS_DFLT)
805 + {
806 + ptr = zmq_ctx_new();
807 + if (ptr == ZMQ_NULLPTR)
808 + throw error_t();
809 +
810 + int rc = zmq_ctx_set(ptr, ZMQ_IO_THREADS, io_threads_);
811 + ZMQ_ASSERT(rc == 0);
812 +
813 + rc = zmq_ctx_set(ptr, ZMQ_MAX_SOCKETS, max_sockets_);
814 + ZMQ_ASSERT(rc == 0);
815 + }
816 +
817 +#ifdef ZMQ_HAS_RVALUE_REFS
818 + context_t(context_t &&rhs) ZMQ_NOTHROW : ptr(rhs.ptr) { rhs.ptr = ZMQ_NULLPTR; }
819 + context_t &operator=(context_t &&rhs) ZMQ_NOTHROW
820 + {
821 + close();
822 + std::swap(ptr, rhs.ptr);
823 + return *this;
824 + }
825 +#endif
826 +
827 + ~context_t() ZMQ_NOTHROW { close(); }
828 +
829 + ZMQ_CPP11_DEPRECATED("from 4.7.0, use set taking zmq::ctxopt instead")
830 + int setctxopt(int option_, int optval_)
831 + {
832 + int rc = zmq_ctx_set(ptr, option_, optval_);
833 + ZMQ_ASSERT(rc == 0);
834 + return rc;
835 + }
836 +
837 + ZMQ_CPP11_DEPRECATED("from 4.7.0, use get taking zmq::ctxopt instead")
838 + int getctxopt(int option_) { return zmq_ctx_get(ptr, option_); }
839 +
840 +#ifdef ZMQ_CPP11
841 + void set(ctxopt option, int optval)
842 + {
843 + int rc = zmq_ctx_set(ptr, static_cast<int>(option), optval);
844 + if (rc == -1)
845 + throw error_t();
846 + }
847 +
848 + ZMQ_NODISCARD int get(ctxopt option)
849 + {
850 + int rc = zmq_ctx_get(ptr, static_cast<int>(option));
851 + // some options have a default value of -1
852 + // which is unfortunate, and may result in errors
853 + // that don't make sense
854 + if (rc == -1)
855 + throw error_t();
856 + return rc;
857 + }
858 +#endif
859 +
860 + // Terminates context (see also shutdown()).
861 + void close() ZMQ_NOTHROW
862 + {
863 + if (ptr == ZMQ_NULLPTR)
864 + return;
865 +
866 + int rc;
867 + do {
868 + rc = zmq_ctx_term(ptr);
869 + } while (rc == -1 && errno == EINTR);
870 +
871 + ZMQ_ASSERT(rc == 0);
872 + ptr = ZMQ_NULLPTR;
873 + }
874 +
875 + // Shutdown context in preparation for termination (close()).
876 + // Causes all blocking socket operations and any further
877 + // socket operations to return with ETERM.
878 + void shutdown() ZMQ_NOTHROW
879 + {
880 + if (ptr == ZMQ_NULLPTR)
881 + return;
882 + int rc = zmq_ctx_shutdown(ptr);
883 + ZMQ_ASSERT(rc == 0);
884 + }
885 +
886 + // Be careful with this, it's probably only useful for
887 + // using the C api together with an existing C++ api.
888 + // Normally you should never need to use this.
889 + ZMQ_EXPLICIT operator void *() ZMQ_NOTHROW { return ptr; }
890 +
891 + ZMQ_EXPLICIT operator void const *() const ZMQ_NOTHROW { return ptr; }
892 +
893 + ZMQ_NODISCARD void *handle() ZMQ_NOTHROW { return ptr; }
894 +
895 + ZMQ_DEPRECATED("from 4.7.0, use handle() != nullptr instead")
896 + operator bool() const ZMQ_NOTHROW { return ptr != ZMQ_NULLPTR; }
897 +
898 + void swap(context_t &other) ZMQ_NOTHROW { std::swap(ptr, other.ptr); }
899 +
900 + private:
901 + void *ptr;
902 +
903 + context_t(const context_t &) ZMQ_DELETED_FUNCTION;
904 + void operator=(const context_t &) ZMQ_DELETED_FUNCTION;
905 +};
906 +
907 +inline void swap(context_t &a, context_t &b) ZMQ_NOTHROW
908 +{
909 + a.swap(b);
910 +}
911 +
912 +#ifdef ZMQ_CPP11
913 +
914 +struct recv_buffer_size
915 +{
916 + size_t size; // number of bytes written to buffer
917 + size_t untruncated_size; // untruncated message size in bytes
918 +
919 + ZMQ_NODISCARD bool truncated() const noexcept
920 + {
921 + return size != untruncated_size;
922 + }
923 +};
924 +
925 +#if CPPZMQ_HAS_OPTIONAL
926 +
927 +using send_result_t = std::optional<size_t>;
928 +using recv_result_t = std::optional<size_t>;
929 +using recv_buffer_result_t = std::optional<recv_buffer_size>;
930 +
931 +#else
932 +
933 +namespace detail
934 +{
935 +// A C++11 type emulating the most basic
936 +// operations of std::optional for trivial types
937 +template<class T> class trivial_optional
938 +{
939 + public:
940 + static_assert(std::is_trivial<T>::value, "T must be trivial");
941 + using value_type = T;
942 +
943 + trivial_optional() = default;
944 + trivial_optional(T value) noexcept : _value(value), _has_value(true) {}
945 +
946 + const T *operator->() const noexcept
947 + {
948 + assert(_has_value);
949 + return &_value;
950 + }
951 + T *operator->() noexcept
952 + {
953 + assert(_has_value);
954 + return &_value;
955 + }
956 +
957 + const T &operator*() const noexcept
958 + {
959 + assert(_has_value);
960 + return _value;
961 + }
962 + T &operator*() noexcept
963 + {
964 + assert(_has_value);
965 + return _value;
966 + }
967 +
968 + T &value()
969 + {
970 + if (!_has_value)
971 + throw std::exception();
972 + return _value;
973 + }
974 + const T &value() const
975 + {
976 + if (!_has_value)
977 + throw std::exception();
978 + return _value;
979 + }
980 +
981 + explicit operator bool() const noexcept { return _has_value; }
982 + bool has_value() const noexcept { return _has_value; }
983 +
984 + private:
985 + T _value{};
986 + bool _has_value{false};
987 +};
988 +} // namespace detail
989 +
990 +using send_result_t = detail::trivial_optional<size_t>;
991 +using recv_result_t = detail::trivial_optional<size_t>;
992 +using recv_buffer_result_t = detail::trivial_optional<recv_buffer_size>;
993 +
994 +#endif
995 +
996 +namespace detail
997 +{
998 +template<class T> constexpr T enum_bit_or(T a, T b) noexcept
999 +{
1000 + static_assert(std::is_enum<T>::value, "must be enum");
1001 + using U = typename std::underlying_type<T>::type;
1002 + return static_cast<T>(static_cast<U>(a) | static_cast<U>(b));
1003 +}
1004 +template<class T> constexpr T enum_bit_and(T a, T b) noexcept
1005 +{
1006 + static_assert(std::is_enum<T>::value, "must be enum");
1007 + using U = typename std::underlying_type<T>::type;
1008 + return static_cast<T>(static_cast<U>(a) & static_cast<U>(b));
1009 +}
1010 +template<class T> constexpr T enum_bit_xor(T a, T b) noexcept
1011 +{
1012 + static_assert(std::is_enum<T>::value, "must be enum");
1013 + using U = typename std::underlying_type<T>::type;
1014 + return static_cast<T>(static_cast<U>(a) ^ static_cast<U>(b));
1015 +}
1016 +template<class T> constexpr T enum_bit_not(T a) noexcept
1017 +{
1018 + static_assert(std::is_enum<T>::value, "must be enum");
1019 + using U = typename std::underlying_type<T>::type;
1020 + return static_cast<T>(~static_cast<U>(a));
1021 +}
1022 +} // namespace detail
1023 +
1024 +// partially satisfies named requirement BitmaskType
1025 +enum class send_flags : int
1026 +{
1027 + none = 0,
1028 + dontwait = ZMQ_DONTWAIT,
1029 + sndmore = ZMQ_SNDMORE
1030 +};
1031 +
1032 +constexpr send_flags operator|(send_flags a, send_flags b) noexcept
1033 +{
1034 + return detail::enum_bit_or(a, b);
1035 +}
1036 +constexpr send_flags operator&(send_flags a, send_flags b) noexcept
1037 +{
1038 + return detail::enum_bit_and(a, b);
1039 +}
1040 +constexpr send_flags operator^(send_flags a, send_flags b) noexcept
1041 +{
1042 + return detail::enum_bit_xor(a, b);
1043 +}
1044 +constexpr send_flags operator~(send_flags a) noexcept
1045 +{
1046 + return detail::enum_bit_not(a);
1047 +}
1048 +
1049 +// partially satisfies named requirement BitmaskType
1050 +enum class recv_flags : int
1051 +{
1052 + none = 0,
1053 + dontwait = ZMQ_DONTWAIT
1054 +};
1055 +
1056 +constexpr recv_flags operator|(recv_flags a, recv_flags b) noexcept
1057 +{
1058 + return detail::enum_bit_or(a, b);
1059 +}
1060 +constexpr recv_flags operator&(recv_flags a, recv_flags b) noexcept
1061 +{
1062 + return detail::enum_bit_and(a, b);
1063 +}
1064 +constexpr recv_flags operator^(recv_flags a, recv_flags b) noexcept
1065 +{
1066 + return detail::enum_bit_xor(a, b);
1067 +}
1068 +constexpr recv_flags operator~(recv_flags a) noexcept
1069 +{
1070 + return detail::enum_bit_not(a);
1071 +}
1072 +
1073 +
1074 +// mutable_buffer, const_buffer and buffer are based on
1075 +// the Networking TS specification, draft:
1076 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/n4771.pdf
1077 +
1078 +class mutable_buffer
1079 +{
1080 + public:
1081 + constexpr mutable_buffer() noexcept : _data(nullptr), _size(0) {}
1082 + constexpr mutable_buffer(void *p, size_t n) noexcept : _data(p), _size(n)
1083 + {
1084 +#ifdef ZMQ_EXTENDED_CONSTEXPR
1085 + assert(p != nullptr || n == 0);
1086 +#endif
1087 + }
1088 +
1089 + constexpr void *data() const noexcept { return _data; }
1090 + constexpr size_t size() const noexcept { return _size; }
1091 + mutable_buffer &operator+=(size_t n) noexcept
1092 + {
1093 + // (std::min) is a workaround for when a min macro is defined
1094 + const auto shift = (std::min)(n, _size);
1095 + _data = static_cast<char *>(_data) + shift;
1096 + _size -= shift;
1097 + return *this;
1098 + }
1099 +
1100 + private:
1101 + void *_data;
1102 + size_t _size;
1103 +};
1104 +
1105 +inline mutable_buffer operator+(const mutable_buffer &mb, size_t n) noexcept
1106 +{
1107 + return mutable_buffer(static_cast<char *>(mb.data()) + (std::min)(n, mb.size()),
1108 + mb.size() - (std::min)(n, mb.size()));
1109 +}
1110 +inline mutable_buffer operator+(size_t n, const mutable_buffer &mb) noexcept
1111 +{
1112 + return mb + n;
1113 +}
1114 +
1115 +class const_buffer
1116 +{
1117 + public:
1118 + constexpr const_buffer() noexcept : _data(nullptr), _size(0) {}
1119 + constexpr const_buffer(const void *p, size_t n) noexcept : _data(p), _size(n)
1120 + {
1121 +#ifdef ZMQ_EXTENDED_CONSTEXPR
1122 + assert(p != nullptr || n == 0);
1123 +#endif
1124 + }
1125 + constexpr const_buffer(const mutable_buffer &mb) noexcept :
1126 + _data(mb.data()), _size(mb.size())
1127 + {
1128 + }
1129 +
1130 + constexpr const void *data() const noexcept { return _data; }
1131 + constexpr size_t size() const noexcept { return _size; }
1132 + const_buffer &operator+=(size_t n) noexcept
1133 + {
1134 + const auto shift = (std::min)(n, _size);
1135 + _data = static_cast<const char *>(_data) + shift;
1136 + _size -= shift;
1137 + return *this;
1138 + }
1139 +
1140 + private:
1141 + const void *_data;
1142 + size_t _size;
1143 +};
1144 +
1145 +inline const_buffer operator+(const const_buffer &cb, size_t n) noexcept
1146 +{
1147 + return const_buffer(static_cast<const char *>(cb.data())
1148 + + (std::min)(n, cb.size()),
1149 + cb.size() - (std::min)(n, cb.size()));
1150 +}
1151 +inline const_buffer operator+(size_t n, const const_buffer &cb) noexcept
1152 +{
1153 + return cb + n;
1154 +}
1155 +
1156 +// buffer creation
1157 +
1158 +constexpr mutable_buffer buffer(void *p, size_t n) noexcept
1159 +{
1160 + return mutable_buffer(p, n);
1161 +}
1162 +constexpr const_buffer buffer(const void *p, size_t n) noexcept
1163 +{
1164 + return const_buffer(p, n);
1165 +}
1166 +constexpr mutable_buffer buffer(const mutable_buffer &mb) noexcept
1167 +{
1168 + return mb;
1169 +}
1170 +inline mutable_buffer buffer(const mutable_buffer &mb, size_t n) noexcept
1171 +{
1172 + return mutable_buffer(mb.data(), (std::min)(mb.size(), n));
1173 +}
1174 +constexpr const_buffer buffer(const const_buffer &cb) noexcept
1175 +{
1176 + return cb;
1177 +}
1178 +inline const_buffer buffer(const const_buffer &cb, size_t n) noexcept
1179 +{
1180 + return const_buffer(cb.data(), (std::min)(cb.size(), n));
1181 +}
1182 +
1183 +namespace detail
1184 +{
1185 +template<class T> struct is_buffer
1186 +{
1187 + static constexpr bool value =
1188 + std::is_same<T, const_buffer>::value || std::is_same<T, mutable_buffer>::value;
1189 +};
1190 +
1191 +template<class T> struct is_pod_like
1192 +{
1193 + // NOTE: The networking draft N4771 section 16.11 requires
1194 + // T in the buffer functions below to be
1195 + // trivially copyable OR standard layout.
1196 + // Here we decide to be conservative and require both.
1197 + static constexpr bool value =
1198 + ZMQ_IS_TRIVIALLY_COPYABLE(T) && std::is_standard_layout<T>::value;
1199 +};
1200 +
1201 +template<class C> constexpr auto seq_size(const C &c) noexcept -> decltype(c.size())
1202 +{
1203 + return c.size();
1204 +}
1205 +template<class T, size_t N>
1206 +constexpr size_t seq_size(const T (&/*array*/)[N]) noexcept
1207 +{
1208 + return N;
1209 +}
1210 +
1211 +template<class Seq>
1212 +auto buffer_contiguous_sequence(Seq &&seq) noexcept
1213 + -> decltype(buffer(std::addressof(*std::begin(seq)), size_t{}))
1214 +{
1215 + using T = typename std::remove_cv<
1216 + typename std::remove_reference<decltype(*std::begin(seq))>::type>::type;
1217 + static_assert(detail::is_pod_like<T>::value, "T must be POD");
1218 +
1219 + const auto size = seq_size(seq);
1220 + return buffer(size != 0u ? std::addressof(*std::begin(seq)) : nullptr,
1221 + size * sizeof(T));
1222 +}
1223 +template<class Seq>
1224 +auto buffer_contiguous_sequence(Seq &&seq, size_t n_bytes) noexcept
1225 + -> decltype(buffer_contiguous_sequence(seq))
1226 +{
1227 + using T = typename std::remove_cv<
1228 + typename std::remove_reference<decltype(*std::begin(seq))>::type>::type;
1229 + static_assert(detail::is_pod_like<T>::value, "T must be POD");
1230 +
1231 + const auto size = seq_size(seq);
1232 + return buffer(size != 0u ? std::addressof(*std::begin(seq)) : nullptr,
1233 + (std::min)(size * sizeof(T), n_bytes));
1234 +}
1235 +
1236 +} // namespace detail
1237 +
1238 +// C array
1239 +template<class T, size_t N> mutable_buffer buffer(T (&data)[N]) noexcept
1240 +{
1241 + return detail::buffer_contiguous_sequence(data);
1242 +}
1243 +template<class T, size_t N>
1244 +mutable_buffer buffer(T (&data)[N], size_t n_bytes) noexcept
1245 +{
1246 + return detail::buffer_contiguous_sequence(data, n_bytes);
1247 +}
1248 +template<class T, size_t N> const_buffer buffer(const T (&data)[N]) noexcept
1249 +{
1250 + return detail::buffer_contiguous_sequence(data);
1251 +}
1252 +template<class T, size_t N>
1253 +const_buffer buffer(const T (&data)[N], size_t n_bytes) noexcept
1254 +{
1255 + return detail::buffer_contiguous_sequence(data, n_bytes);
1256 +}
1257 +// std::array
1258 +template<class T, size_t N> mutable_buffer buffer(std::array<T, N> &data) noexcept
1259 +{
1260 + return detail::buffer_contiguous_sequence(data);
1261 +}
1262 +template<class T, size_t N>
1263 +mutable_buffer buffer(std::array<T, N> &data, size_t n_bytes) noexcept
1264 +{
1265 + return detail::buffer_contiguous_sequence(data, n_bytes);
1266 +}
1267 +template<class T, size_t N>
1268 +const_buffer buffer(std::array<const T, N> &data) noexcept
1269 +{
1270 + return detail::buffer_contiguous_sequence(data);
1271 +}
1272 +template<class T, size_t N>
1273 +const_buffer buffer(std::array<const T, N> &data, size_t n_bytes) noexcept
1274 +{
1275 + return detail::buffer_contiguous_sequence(data, n_bytes);
1276 +}
1277 +template<class T, size_t N>
1278 +const_buffer buffer(const std::array<T, N> &data) noexcept
1279 +{
1280 + return detail::buffer_contiguous_sequence(data);
1281 +}
1282 +template<class T, size_t N>
1283 +const_buffer buffer(const std::array<T, N> &data, size_t n_bytes) noexcept
1284 +{
1285 + return detail::buffer_contiguous_sequence(data, n_bytes);
1286 +}
1287 +// std::vector
1288 +template<class T, class Allocator>
1289 +mutable_buffer buffer(std::vector<T, Allocator> &data) noexcept
1290 +{
1291 + return detail::buffer_contiguous_sequence(data);
1292 +}
1293 +template<class T, class Allocator>
1294 +mutable_buffer buffer(std::vector<T, Allocator> &data, size_t n_bytes) noexcept
1295 +{
1296 + return detail::buffer_contiguous_sequence(data, n_bytes);
1297 +}
1298 +template<class T, class Allocator>
1299 +const_buffer buffer(const std::vector<T, Allocator> &data) noexcept
1300 +{
1301 + return detail::buffer_contiguous_sequence(data);
1302 +}
1303 +template<class T, class Allocator>
1304 +const_buffer buffer(const std::vector<T, Allocator> &data, size_t n_bytes) noexcept
1305 +{
1306 + return detail::buffer_contiguous_sequence(data, n_bytes);
1307 +}
1308 +// std::basic_string
1309 +template<class T, class Traits, class Allocator>
1310 +mutable_buffer buffer(std::basic_string<T, Traits, Allocator> &data) noexcept
1311 +{
1312 + return detail::buffer_contiguous_sequence(data);
1313 +}
1314 +template<class T, class Traits, class Allocator>
1315 +mutable_buffer buffer(std::basic_string<T, Traits, Allocator> &data,
1316 + size_t n_bytes) noexcept
1317 +{
1318 + return detail::buffer_contiguous_sequence(data, n_bytes);
1319 +}
1320 +template<class T, class Traits, class Allocator>
1321 +const_buffer buffer(const std::basic_string<T, Traits, Allocator> &data) noexcept
1322 +{
1323 + return detail::buffer_contiguous_sequence(data);
1324 +}
1325 +template<class T, class Traits, class Allocator>
1326 +const_buffer buffer(const std::basic_string<T, Traits, Allocator> &data,
1327 + size_t n_bytes) noexcept
1328 +{
1329 + return detail::buffer_contiguous_sequence(data, n_bytes);
1330 +}
1331 +
1332 +#if CPPZMQ_HAS_STRING_VIEW
1333 +// std::basic_string_view
1334 +template<class T, class Traits>
1335 +const_buffer buffer(std::basic_string_view<T, Traits> data) noexcept
1336 +{
1337 + return detail::buffer_contiguous_sequence(data);
1338 +}
1339 +template<class T, class Traits>
1340 +const_buffer buffer(std::basic_string_view<T, Traits> data, size_t n_bytes) noexcept
1341 +{
1342 + return detail::buffer_contiguous_sequence(data, n_bytes);
1343 +}
1344 +#endif
1345 +
1346 +// Buffer for a string literal (null terminated)
1347 +// where the buffer size excludes the terminating character.
1348 +// Equivalent to zmq::buffer(std::string_view("...")).
1349 +template<class Char, size_t N>
1350 +constexpr const_buffer str_buffer(const Char (&data)[N]) noexcept
1351 +{
1352 + static_assert(detail::is_pod_like<Char>::value, "Char must be POD");
1353 +#ifdef ZMQ_EXTENDED_CONSTEXPR
1354 + assert(data[N - 1] == Char{0});
1355 +#endif
1356 + return const_buffer(static_cast<const Char *>(data), (N - 1) * sizeof(Char));
1357 +}
1358 +
1359 +namespace literals
1360 +{
1361 +constexpr const_buffer operator"" _zbuf(const char *str, size_t len) noexcept
1362 +{
1363 + return const_buffer(str, len * sizeof(char));
1364 +}
1365 +constexpr const_buffer operator"" _zbuf(const wchar_t *str, size_t len) noexcept
1366 +{
1367 + return const_buffer(str, len * sizeof(wchar_t));
1368 +}
1369 +constexpr const_buffer operator"" _zbuf(const char16_t *str, size_t len) noexcept
1370 +{
1371 + return const_buffer(str, len * sizeof(char16_t));
1372 +}
1373 +constexpr const_buffer operator"" _zbuf(const char32_t *str, size_t len) noexcept
1374 +{
1375 + return const_buffer(str, len * sizeof(char32_t));
1376 +}
1377 +}
1378 +
1379 +#ifdef ZMQ_CPP11
1380 +enum class socket_type : int
1381 +{
1382 + req = ZMQ_REQ,
1383 + rep = ZMQ_REP,
1384 + dealer = ZMQ_DEALER,
1385 + router = ZMQ_ROUTER,
1386 + pub = ZMQ_PUB,
1387 + sub = ZMQ_SUB,
1388 + xpub = ZMQ_XPUB,
1389 + xsub = ZMQ_XSUB,
1390 + push = ZMQ_PUSH,
1391 + pull = ZMQ_PULL,
1392 +#if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 0)
1393 + server = ZMQ_SERVER,
1394 + client = ZMQ_CLIENT,
1395 + radio = ZMQ_RADIO,
1396 + dish = ZMQ_DISH,
1397 + gather = ZMQ_GATHER,
1398 + scatter = ZMQ_SCATTER,
1399 + dgram = ZMQ_DGRAM,
1400 +#endif
1401 +#if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 3, 3)
1402 + peer = ZMQ_PEER,
1403 + channel = ZMQ_CHANNEL,
1404 +#endif
1405 +#if ZMQ_VERSION_MAJOR >= 4
1406 + stream = ZMQ_STREAM,
1407 +#endif
1408 + pair = ZMQ_PAIR
1409 +};
1410 +#endif
1411 +
1412 +namespace sockopt
1413 +{
1414 +// There are two types of options,
1415 +// integral type with known compiler time size (int, bool, int64_t, uint64_t)
1416 +// and arrays with dynamic size (strings, binary data).
1417 +
1418 +// BoolUnit: if true accepts values of type bool (but passed as T into libzmq)
1419 +template<int Opt, class T, bool BoolUnit = false> struct integral_option
1420 +{
1421 +};
1422 +
1423 +// NullTerm:
1424 +// 0: binary data
1425 +// 1: null-terminated string (`getsockopt` size includes null)
1426 +// 2: binary (size 32) or Z85 encoder string of size 41 (null included)
1427 +template<int Opt, int NullTerm = 1> struct array_option
1428 +{
1429 +};
1430 +
1431 +#define ZMQ_DEFINE_INTEGRAL_OPT(OPT, NAME, TYPE) \
1432 + using NAME##_t = integral_option<OPT, TYPE, false>; \
1433 + ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1434 +#define ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(OPT, NAME, TYPE) \
1435 + using NAME##_t = integral_option<OPT, TYPE, true>; \
1436 + ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1437 +#define ZMQ_DEFINE_ARRAY_OPT(OPT, NAME) \
1438 + using NAME##_t = array_option<OPT>; \
1439 + ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1440 +#define ZMQ_DEFINE_ARRAY_OPT_BINARY(OPT, NAME) \
1441 + using NAME##_t = array_option<OPT, 0>; \
1442 + ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1443 +#define ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(OPT, NAME) \
1444 + using NAME##_t = array_option<OPT, 2>; \
1445 + ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1446 +
1447 +// deprecated, use zmq::fd_t
1448 +using cppzmq_fd_t = ::zmq::fd_t;
1449 +
1450 +#ifdef ZMQ_AFFINITY
1451 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_AFFINITY, affinity, uint64_t);
1452 +#endif
1453 +#ifdef ZMQ_BACKLOG
1454 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_BACKLOG, backlog, int);
1455 +#endif
1456 +#ifdef ZMQ_BINDTODEVICE
1457 +ZMQ_DEFINE_ARRAY_OPT_BINARY(ZMQ_BINDTODEVICE, bindtodevice);
1458 +#endif
1459 +#ifdef ZMQ_CONFLATE
1460 +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_CONFLATE, conflate, int);
1461 +#endif
1462 +#ifdef ZMQ_CONNECT_ROUTING_ID
1463 +ZMQ_DEFINE_ARRAY_OPT(ZMQ_CONNECT_ROUTING_ID, connect_routing_id);
1464 +#endif
1465 +#ifdef ZMQ_CONNECT_TIMEOUT
1466 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_CONNECT_TIMEOUT, connect_timeout, int);
1467 +#endif
1468 +#ifdef ZMQ_CURVE_PUBLICKEY
1469 +ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(ZMQ_CURVE_PUBLICKEY, curve_publickey);
1470 +#endif
1471 +#ifdef ZMQ_CURVE_SECRETKEY
1472 +ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(ZMQ_CURVE_SECRETKEY, curve_secretkey);
1473 +#endif
1474 +#ifdef ZMQ_CURVE_SERVER
1475 +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_CURVE_SERVER, curve_server, int);
1476 +#endif
1477 +#ifdef ZMQ_CURVE_SERVERKEY
1478 +ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(ZMQ_CURVE_SERVERKEY, curve_serverkey);
1479 +#endif
1480 +#ifdef ZMQ_EVENTS
1481 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_EVENTS, events, int);
1482 +#endif
1483 +#ifdef ZMQ_FD
1484 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_FD, fd, ::zmq::fd_t);
1485 +#endif
1486 +#ifdef ZMQ_GSSAPI_PLAINTEXT
1487 +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_GSSAPI_PLAINTEXT, gssapi_plaintext, int);
1488 +#endif
1489 +#ifdef ZMQ_GSSAPI_SERVER
1490 +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_GSSAPI_SERVER, gssapi_server, int);
1491 +#endif
1492 +#ifdef ZMQ_GSSAPI_SERVICE_PRINCIPAL
1493 +ZMQ_DEFINE_ARRAY_OPT(ZMQ_GSSAPI_SERVICE_PRINCIPAL, gssapi_service_principal);
1494 +#endif
1495 +#ifdef ZMQ_GSSAPI_SERVICE_PRINCIPAL_NAMETYPE
1496 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_GSSAPI_SERVICE_PRINCIPAL_NAMETYPE,
1497 + gssapi_service_principal_nametype,
1498 + int);
1499 +#endif
1500 +#ifdef ZMQ_GSSAPI_PRINCIPAL
1501 +ZMQ_DEFINE_ARRAY_OPT(ZMQ_GSSAPI_PRINCIPAL, gssapi_principal);
1502 +#endif
1503 +#ifdef ZMQ_GSSAPI_PRINCIPAL_NAMETYPE
1504 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_GSSAPI_PRINCIPAL_NAMETYPE,
1505 + gssapi_principal_nametype,
1506 + int);
1507 +#endif
1508 +#ifdef ZMQ_HANDSHAKE_IVL
1509 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HANDSHAKE_IVL, handshake_ivl, int);
1510 +#endif
1511 +#ifdef ZMQ_HEARTBEAT_IVL
1512 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HEARTBEAT_IVL, heartbeat_ivl, int);
1513 +#endif
1514 +#ifdef ZMQ_HEARTBEAT_TIMEOUT
1515 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HEARTBEAT_TIMEOUT, heartbeat_timeout, int);
1516 +#endif
1517 +#ifdef ZMQ_HEARTBEAT_TTL
1518 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HEARTBEAT_TTL, heartbeat_ttl, int);
1519 +#endif
1520 +#ifdef ZMQ_IMMEDIATE
1521 +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_IMMEDIATE, immediate, int);
1522 +#endif
1523 +#ifdef ZMQ_INVERT_MATCHING
1524 +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_INVERT_MATCHING, invert_matching, int);
1525 +#endif
1526 +#ifdef ZMQ_IPV6
1527 +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_IPV6, ipv6, int);
1528 +#endif
1529 +#ifdef ZMQ_LAST_ENDPOINT
1530 +ZMQ_DEFINE_ARRAY_OPT(ZMQ_LAST_ENDPOINT, last_endpoint);
1531 +#endif
1532 +#ifdef ZMQ_LINGER
1533 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_LINGER, linger, int);
1534 +#endif
1535 +#ifdef ZMQ_MAXMSGSIZE
1536 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MAXMSGSIZE, maxmsgsize, int64_t);
1537 +#endif
1538 +#ifdef ZMQ_MECHANISM
1539 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MECHANISM, mechanism, int);
1540 +#endif
1541 +#ifdef ZMQ_METADATA
1542 +ZMQ_DEFINE_ARRAY_OPT(ZMQ_METADATA, metadata);
1543 +#endif
1544 +#ifdef ZMQ_MULTICAST_HOPS
1545 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MULTICAST_HOPS, multicast_hops, int);
1546 +#endif
1547 +#ifdef ZMQ_MULTICAST_LOOP
1548 +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_MULTICAST_LOOP, multicast_loop, int);
1549 +#endif
1550 +#ifdef ZMQ_MULTICAST_MAXTPDU
1551 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MULTICAST_MAXTPDU, multicast_maxtpdu, int);
1552 +#endif
1553 +#ifdef ZMQ_PLAIN_SERVER
1554 +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_PLAIN_SERVER, plain_server, int);
1555 +#endif
1556 +#ifdef ZMQ_PLAIN_PASSWORD
1557 +ZMQ_DEFINE_ARRAY_OPT(ZMQ_PLAIN_PASSWORD, plain_password);
1558 +#endif
1559 +#ifdef ZMQ_PLAIN_USERNAME
1560 +ZMQ_DEFINE_ARRAY_OPT(ZMQ_PLAIN_USERNAME, plain_username);
1561 +#endif
1562 +#ifdef ZMQ_USE_FD
1563 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_USE_FD, use_fd, int);
1564 +#endif
1565 +#ifdef ZMQ_PROBE_ROUTER
1566 +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_PROBE_ROUTER, probe_router, int);
1567 +#endif
1568 +#ifdef ZMQ_RATE
1569 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RATE, rate, int);
1570 +#endif
1571 +#ifdef ZMQ_RCVBUF
1572 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RCVBUF, rcvbuf, int);
1573 +#endif
1574 +#ifdef ZMQ_RCVHWM
1575 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RCVHWM, rcvhwm, int);
1576 +#endif
1577 +#ifdef ZMQ_RCVMORE
1578 +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_RCVMORE, rcvmore, int);
1579 +#endif
1580 +#ifdef ZMQ_RCVTIMEO
1581 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RCVTIMEO, rcvtimeo, int);
1582 +#endif
1583 +#ifdef ZMQ_RECONNECT_IVL
1584 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RECONNECT_IVL, reconnect_ivl, int);
1585 +#endif
1586 +#ifdef ZMQ_RECONNECT_IVL_MAX
1587 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RECONNECT_IVL_MAX, reconnect_ivl_max, int);
1588 +#endif
1589 +#ifdef ZMQ_RECOVERY_IVL
1590 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RECOVERY_IVL, recovery_ivl, int);
1591 +#endif
1592 +#ifdef ZMQ_REQ_CORRELATE
1593 +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_REQ_CORRELATE, req_correlate, int);
1594 +#endif
1595 +#ifdef ZMQ_REQ_RELAXED
1596 +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_REQ_RELAXED, req_relaxed, int);
1597 +#endif
1598 +#ifdef ZMQ_ROUTER_HANDOVER
1599 +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ROUTER_HANDOVER, router_handover, int);
1600 +#endif
1601 +#ifdef ZMQ_ROUTER_MANDATORY
1602 +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ROUTER_MANDATORY, router_mandatory, int);
1603 +#endif
1604 +#ifdef ZMQ_ROUTER_NOTIFY
1605 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_ROUTER_NOTIFY, router_notify, int);
1606 +#endif
1607 +#ifdef ZMQ_ROUTING_ID
1608 +ZMQ_DEFINE_ARRAY_OPT_BINARY(ZMQ_ROUTING_ID, routing_id);
1609 +#endif
1610 +#ifdef ZMQ_SNDBUF
1611 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_SNDBUF, sndbuf, int);
1612 +#endif
1613 +#ifdef ZMQ_SNDHWM
1614 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_SNDHWM, sndhwm, int);
1615 +#endif
1616 +#ifdef ZMQ_SNDTIMEO
1617 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_SNDTIMEO, sndtimeo, int);
1618 +#endif
1619 +#ifdef ZMQ_SOCKS_PROXY
1620 +ZMQ_DEFINE_ARRAY_OPT(ZMQ_SOCKS_PROXY, socks_proxy);
1621 +#endif
1622 +#ifdef ZMQ_STREAM_NOTIFY
1623 +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_STREAM_NOTIFY, stream_notify, int);
1624 +#endif
1625 +#ifdef ZMQ_SUBSCRIBE
1626 +ZMQ_DEFINE_ARRAY_OPT(ZMQ_SUBSCRIBE, subscribe);
1627 +#endif
1628 +#ifdef ZMQ_TCP_KEEPALIVE
1629 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE, tcp_keepalive, int);
1630 +#endif
1631 +#ifdef ZMQ_TCP_KEEPALIVE_CNT
1632 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE_CNT, tcp_keepalive_cnt, int);
1633 +#endif
1634 +#ifdef ZMQ_TCP_KEEPALIVE_IDLE
1635 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE_IDLE, tcp_keepalive_idle, int);
1636 +#endif
1637 +#ifdef ZMQ_TCP_KEEPALIVE_INTVL
1638 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE_INTVL, tcp_keepalive_intvl, int);
1639 +#endif
1640 +#ifdef ZMQ_TCP_MAXRT
1641 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_MAXRT, tcp_maxrt, int);
1642 +#endif
1643 +#ifdef ZMQ_THREAD_SAFE
1644 +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_THREAD_SAFE, thread_safe, int);
1645 +#endif
1646 +#ifdef ZMQ_TOS
1647 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TOS, tos, int);
1648 +#endif
1649 +#ifdef ZMQ_TYPE
1650 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TYPE, type, int);
1651 +#ifdef ZMQ_CPP11
1652 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TYPE, socket_type, socket_type);
1653 +#endif // ZMQ_CPP11
1654 +#endif // ZMQ_TYPE
1655 +#ifdef ZMQ_UNSUBSCRIBE
1656 +ZMQ_DEFINE_ARRAY_OPT(ZMQ_UNSUBSCRIBE, unsubscribe);
1657 +#endif
1658 +#ifdef ZMQ_VMCI_BUFFER_SIZE
1659 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_BUFFER_SIZE, vmci_buffer_size, uint64_t);
1660 +#endif
1661 +#ifdef ZMQ_VMCI_BUFFER_MIN_SIZE
1662 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_BUFFER_MIN_SIZE, vmci_buffer_min_size, uint64_t);
1663 +#endif
1664 +#ifdef ZMQ_VMCI_BUFFER_MAX_SIZE
1665 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_BUFFER_MAX_SIZE, vmci_buffer_max_size, uint64_t);
1666 +#endif
1667 +#ifdef ZMQ_VMCI_CONNECT_TIMEOUT
1668 +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_CONNECT_TIMEOUT, vmci_connect_timeout, int);
1669 +#endif
1670 +#ifdef ZMQ_XPUB_VERBOSE
1671 +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_VERBOSE, xpub_verbose, int);
1672 +#endif
1673 +#ifdef ZMQ_XPUB_VERBOSER
1674 +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_VERBOSER, xpub_verboser, int);
1675 +#endif
1676 +#ifdef ZMQ_XPUB_MANUAL
1677 +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_MANUAL, xpub_manual, int);
1678 +#endif
1679 +#ifdef ZMQ_XPUB_NODROP
1680 +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_NODROP, xpub_nodrop, int);
1681 +#endif
1682 +#ifdef ZMQ_XPUB_WELCOME_MSG
1683 +ZMQ_DEFINE_ARRAY_OPT(ZMQ_XPUB_WELCOME_MSG, xpub_welcome_msg);
1684 +#endif
1685 +#ifdef ZMQ_ZAP_ENFORCE_DOMAIN
1686 +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ZAP_ENFORCE_DOMAIN, zap_enforce_domain, int);
1687 +#endif
1688 +#ifdef ZMQ_ZAP_DOMAIN
1689 +ZMQ_DEFINE_ARRAY_OPT(ZMQ_ZAP_DOMAIN, zap_domain);
1690 +#endif
1691 +
1692 +} // namespace sockopt
1693 +#endif // ZMQ_CPP11
1694 +
1695 +
1696 +namespace detail
1697 +{
1698 +class socket_base
1699 +{
1700 + public:
1701 + socket_base() ZMQ_NOTHROW : _handle(ZMQ_NULLPTR) {}
1702 + ZMQ_EXPLICIT socket_base(void *handle) ZMQ_NOTHROW : _handle(handle) {}
1703 +
1704 + template<typename T>
1705 + ZMQ_CPP11_DEPRECATED("from 4.7.0, use `set` taking option from zmq::sockopt")
1706 + void setsockopt(int option_, T const &optval)
1707 + {
1708 + setsockopt(option_, &optval, sizeof(T));
1709 + }
1710 +
1711 + ZMQ_CPP11_DEPRECATED("from 4.7.0, use `set` taking option from zmq::sockopt")
1712 + void setsockopt(int option_, const void *optval_, size_t optvallen_)
1713 + {
1714 + int rc = zmq_setsockopt(_handle, option_, optval_, optvallen_);
1715 + if (rc != 0)
1716 + throw error_t();
1717 + }
1718 +
1719 + ZMQ_CPP11_DEPRECATED("from 4.7.0, use `get` taking option from zmq::sockopt")
1720 + void getsockopt(int option_, void *optval_, size_t *optvallen_) const
1721 + {
1722 + int rc = zmq_getsockopt(_handle, option_, optval_, optvallen_);
1723 + if (rc != 0)
1724 + throw error_t();
1725 + }
1726 +
1727 + template<typename T>
1728 + ZMQ_CPP11_DEPRECATED("from 4.7.0, use `get` taking option from zmq::sockopt")
1729 + T getsockopt(int option_) const
1730 + {
1731 + T optval;
1732 + size_t optlen = sizeof(T);
1733 + getsockopt(option_, &optval, &optlen);
1734 + return optval;
1735 + }
1736 +
1737 +#ifdef ZMQ_CPP11
1738 + // Set integral socket option, e.g.
1739 + // `socket.set(zmq::sockopt::linger, 0)`
1740 + template<int Opt, class T, bool BoolUnit>
1741 + void set(sockopt::integral_option<Opt, T, BoolUnit>, const T &val)
1742 + {
1743 + static_assert(std::is_integral<T>::value, "T must be integral");
1744 + set_option(Opt, &val, sizeof val);
1745 + }
1746 +
1747 + // Set integral socket option from boolean, e.g.
1748 + // `socket.set(zmq::sockopt::immediate, false)`
1749 + template<int Opt, class T>
1750 + void set(sockopt::integral_option<Opt, T, true>, bool val)
1751 + {
1752 + static_assert(std::is_integral<T>::value, "T must be integral");
1753 + T rep_val = val;
1754 + set_option(Opt, &rep_val, sizeof rep_val);
1755 + }
1756 +
1757 + // Set array socket option, e.g.
1758 + // `socket.set(zmq::sockopt::plain_username, "foo123")`
1759 + template<int Opt, int NullTerm>
1760 + void set(sockopt::array_option<Opt, NullTerm>, const char *buf)
1761 + {
1762 + set_option(Opt, buf, std::strlen(buf));
1763 + }
1764 +
1765 + // Set array socket option, e.g.
1766 + // `socket.set(zmq::sockopt::routing_id, zmq::buffer(id))`
1767 + template<int Opt, int NullTerm>
1768 + void set(sockopt::array_option<Opt, NullTerm>, const_buffer buf)
1769 + {
1770 + set_option(Opt, buf.data(), buf.size());
1771 + }
1772 +
1773 + // Set array socket option, e.g.
1774 + // `socket.set(zmq::sockopt::routing_id, id_str)`
1775 + template<int Opt, int NullTerm>
1776 + void set(sockopt::array_option<Opt, NullTerm>, const std::string &buf)
1777 + {
1778 + set_option(Opt, buf.data(), buf.size());
1779 + }
1780 +
1781 +#if CPPZMQ_HAS_STRING_VIEW
1782 + // Set array socket option, e.g.
1783 + // `socket.set(zmq::sockopt::routing_id, id_str)`
1784 + template<int Opt, int NullTerm>
1785 + void set(sockopt::array_option<Opt, NullTerm>, std::string_view buf)
1786 + {
1787 + set_option(Opt, buf.data(), buf.size());
1788 + }
1789 +#endif
1790 +
1791 + // Get scalar socket option, e.g.
1792 + // `auto opt = socket.get(zmq::sockopt::linger)`
1793 + template<int Opt, class T, bool BoolUnit>
1794 + ZMQ_NODISCARD T get(sockopt::integral_option<Opt, T, BoolUnit>) const
1795 + {
1796 + static_assert(std::is_scalar<T>::value, "T must be scalar");
1797 + T val;
1798 + size_t size = sizeof val;
1799 + get_option(Opt, &val, &size);
1800 + assert(size == sizeof val);
1801 + return val;
1802 + }
1803 +
1804 + // Get array socket option, writes to buf, returns option size in bytes, e.g.
1805 + // `size_t optsize = socket.get(zmq::sockopt::routing_id, zmq::buffer(id))`
1806 + template<int Opt, int NullTerm>
1807 + ZMQ_NODISCARD size_t get(sockopt::array_option<Opt, NullTerm>,
1808 + mutable_buffer buf) const
1809 + {
1810 + size_t size = buf.size();
1811 + get_option(Opt, buf.data(), &size);
1812 + return size;
1813 + }
1814 +
1815 + // Get array socket option as string (initializes the string buffer size to init_size) e.g.
1816 + // `auto s = socket.get(zmq::sockopt::routing_id)`
1817 + // Note: removes the null character from null-terminated string options,
1818 + // i.e. the string size excludes the null character.
1819 + template<int Opt, int NullTerm>
1820 + ZMQ_NODISCARD std::string get(sockopt::array_option<Opt, NullTerm>,
1821 + size_t init_size = 1024) const
1822 + {
1823 + if ZMQ_CONSTEXPR_IF (NullTerm == 2) {
1824 + if (init_size == 1024) {
1825 + init_size = 41; // get as Z85 string
1826 + }
1827 + }
1828 + std::string str(init_size, '\0');
1829 + size_t size = get(sockopt::array_option<Opt>{}, buffer(str));
1830 + if ZMQ_CONSTEXPR_IF (NullTerm == 1) {
1831 + if (size > 0) {
1832 + assert(str[size - 1] == '\0');
1833 + --size;
1834 + }
1835 + } else if ZMQ_CONSTEXPR_IF (NullTerm == 2) {
1836 + assert(size == 32 || size == 41);
1837 + if (size == 41) {
1838 + assert(str[size - 1] == '\0');
1839 + --size;
1840 + }
1841 + }
1842 + str.resize(size);
1843 + return str;
1844 + }
1845 +#endif
1846 +
1847 + void bind(std::string const &addr) { bind(addr.c_str()); }
1848 +
1849 + void bind(const char *addr_)
1850 + {
1851 + int rc = zmq_bind(_handle, addr_);
1852 + if (rc != 0)
1853 + throw error_t();
1854 + }
1855 +
1856 + void unbind(std::string const &addr) { unbind(addr.c_str()); }
1857 +
1858 + void unbind(const char *addr_)
1859 + {
1860 + int rc = zmq_unbind(_handle, addr_);
1861 + if (rc != 0)
1862 + throw error_t();
1863 + }
1864 +
1865 + void connect(std::string const &addr) { connect(addr.c_str()); }
1866 +
1867 + void connect(const char *addr_)
1868 + {
1869 + int rc = zmq_connect(_handle, addr_);
1870 + if (rc != 0)
1871 + throw error_t();
1872 + }
1873 +
1874 + void disconnect(std::string const &addr) { disconnect(addr.c_str()); }
1875 +
1876 + void disconnect(const char *addr_)
1877 + {
1878 + int rc = zmq_disconnect(_handle, addr_);
1879 + if (rc != 0)
1880 + throw error_t();
1881 + }
1882 +
1883 + ZMQ_DEPRECATED("from 4.7.1, use handle() != nullptr or operator bool")
1884 + bool connected() const ZMQ_NOTHROW { return (_handle != ZMQ_NULLPTR); }
1885 +
1886 + ZMQ_CPP11_DEPRECATED("from 4.3.1, use send taking a const_buffer and send_flags")
1887 + size_t send(const void *buf_, size_t len_, int flags_ = 0)
1888 + {
1889 + int nbytes = zmq_send(_handle, buf_, len_, flags_);
1890 + if (nbytes >= 0)
1891 + return static_cast<size_t>(nbytes);
1892 + if (zmq_errno() == EAGAIN)
1893 + return 0;
1894 + throw error_t();
1895 + }
1896 +
1897 + ZMQ_CPP11_DEPRECATED("from 4.3.1, use send taking message_t and send_flags")
1898 + bool send(message_t &msg_,
1899 + int flags_ = 0) // default until removed
1900 + {
1901 + int nbytes = zmq_msg_send(msg_.handle(), _handle, flags_);
1902 + if (nbytes >= 0)
1903 + return true;
1904 + if (zmq_errno() == EAGAIN)
1905 + return false;
1906 + throw error_t();
1907 + }
1908 +
1909 + template<typename T>
1910 + ZMQ_CPP11_DEPRECATED(
1911 + "from 4.4.1, use send taking message_t or buffer (for contiguous "
1912 + "ranges), and send_flags")
1913 + bool send(T first, T last, int flags_ = 0)
1914 + {
1915 + zmq::message_t msg(first, last);
1916 + int nbytes = zmq_msg_send(msg.handle(), _handle, flags_);
1917 + if (nbytes >= 0)
1918 + return true;
1919 + if (zmq_errno() == EAGAIN)
1920 + return false;
1921 + throw error_t();
1922 + }
1923 +
1924 +#ifdef ZMQ_HAS_RVALUE_REFS
1925 + ZMQ_CPP11_DEPRECATED("from 4.3.1, use send taking message_t and send_flags")
1926 + bool send(message_t &&msg_,
1927 + int flags_ = 0) // default until removed
1928 + {
1929 +#ifdef ZMQ_CPP11
1930 + return send(msg_, static_cast<send_flags>(flags_)).has_value();
1931 +#else
1932 + return send(msg_, flags_);
1933 +#endif
1934 + }
1935 +#endif
1936 +
1937 +#ifdef ZMQ_CPP11
1938 + send_result_t send(const_buffer buf, send_flags flags = send_flags::none)
1939 + {
1940 + const int nbytes =
1941 + zmq_send(_handle, buf.data(), buf.size(), static_cast<int>(flags));
1942 + if (nbytes >= 0)
1943 + return static_cast<size_t>(nbytes);
1944 + if (zmq_errno() == EAGAIN)
1945 + return {};
1946 + throw error_t();
1947 + }
1948 +
1949 + send_result_t send(message_t &msg, send_flags flags)
1950 + {
1951 + int nbytes = zmq_msg_send(msg.handle(), _handle, static_cast<int>(flags));
1952 + if (nbytes >= 0)
1953 + return static_cast<size_t>(nbytes);
1954 + if (zmq_errno() == EAGAIN)
1955 + return {};
1956 + throw error_t();
1957 + }
1958 +
1959 + send_result_t send(message_t &&msg, send_flags flags)
1960 + {
1961 + return send(msg, flags);
1962 + }
1963 +#endif
1964 +
1965 + ZMQ_CPP11_DEPRECATED(
1966 + "from 4.3.1, use recv taking a mutable_buffer and recv_flags")
1967 + size_t recv(void *buf_, size_t len_, int flags_ = 0)
1968 + {
1969 + int nbytes = zmq_recv(_handle, buf_, len_, flags_);
1970 + if (nbytes >= 0)
1971 + return static_cast<size_t>(nbytes);
1972 + if (zmq_errno() == EAGAIN)
1973 + return 0;
1974 + throw error_t();
1975 + }
1976 +
1977 + ZMQ_CPP11_DEPRECATED(
1978 + "from 4.3.1, use recv taking a reference to message_t and recv_flags")
1979 + bool recv(message_t *msg_, int flags_ = 0)
1980 + {
1981 + int nbytes = zmq_msg_recv(msg_->handle(), _handle, flags_);
1982 + if (nbytes >= 0)
1983 + return true;
1984 + if (zmq_errno() == EAGAIN)
1985 + return false;
1986 + throw error_t();
1987 + }
1988 +
1989 +#ifdef ZMQ_CPP11
1990 + ZMQ_NODISCARD
1991 + recv_buffer_result_t recv(mutable_buffer buf,
1992 + recv_flags flags = recv_flags::none)
1993 + {
1994 + const int nbytes =
1995 + zmq_recv(_handle, buf.data(), buf.size(), static_cast<int>(flags));
1996 + if (nbytes >= 0) {
1997 + return recv_buffer_size{
1998 + (std::min)(static_cast<size_t>(nbytes), buf.size()),
1999 + static_cast<size_t>(nbytes)};
2000 + }
2001 + if (zmq_errno() == EAGAIN)
2002 + return {};
2003 + throw error_t();
2004 + }
2005 +
2006 + ZMQ_NODISCARD
2007 + recv_result_t recv(message_t &msg, recv_flags flags = recv_flags::none)
2008 + {
2009 + const int nbytes =
2010 + zmq_msg_recv(msg.handle(), _handle, static_cast<int>(flags));
2011 + if (nbytes >= 0) {
2012 + assert(msg.size() == static_cast<size_t>(nbytes));
2013 + return static_cast<size_t>(nbytes);
2014 + }
2015 + if (zmq_errno() == EAGAIN)
2016 + return {};
2017 + throw error_t();
2018 + }
2019 +#endif
2020 +
2021 +#if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 0)
2022 + void join(const char *group)
2023 + {
2024 + int rc = zmq_join(_handle, group);
2025 + if (rc != 0)
2026 + throw error_t();
2027 + }
2028 +
2029 + void leave(const char *group)
2030 + {
2031 + int rc = zmq_leave(_handle, group);
2032 + if (rc != 0)
2033 + throw error_t();
2034 + }
2035 +#endif
2036 +
2037 + ZMQ_NODISCARD void *handle() ZMQ_NOTHROW { return _handle; }
2038 + ZMQ_NODISCARD const void *handle() const ZMQ_NOTHROW { return _handle; }
2039 +
2040 + ZMQ_EXPLICIT operator bool() const ZMQ_NOTHROW { return _handle != ZMQ_NULLPTR; }
2041 + // note: non-const operator bool can be removed once
2042 + // operator void* is removed from socket_t
2043 + ZMQ_EXPLICIT operator bool() ZMQ_NOTHROW { return _handle != ZMQ_NULLPTR; }
2044 +
2045 + protected:
2046 + void *_handle;
2047 +
2048 + private:
2049 + void set_option(int option_, const void *optval_, size_t optvallen_)
2050 + {
2051 + int rc = zmq_setsockopt(_handle, option_, optval_, optvallen_);
2052 + if (rc != 0)
2053 + throw error_t();
2054 + }
2055 +
2056 + void get_option(int option_, void *optval_, size_t *optvallen_) const
2057 + {
2058 + int rc = zmq_getsockopt(_handle, option_, optval_, optvallen_);
2059 + if (rc != 0)
2060 + throw error_t();
2061 + }
2062 +};
2063 +} // namespace detail
2064 +
2065 +struct from_handle_t
2066 +{
2067 + struct _private
2068 + {
2069 + }; // disabling use other than with from_handle
2070 + ZMQ_CONSTEXPR_FN ZMQ_EXPLICIT from_handle_t(_private /*p*/) ZMQ_NOTHROW {}
2071 +};
2072 +
2073 +ZMQ_CONSTEXPR_VAR from_handle_t from_handle =
2074 + from_handle_t(from_handle_t::_private());
2075 +
2076 +// A non-owning nullable reference to a socket.
2077 +// The reference is invalidated on socket close or destruction.
2078 +class socket_ref : public detail::socket_base
2079 +{
2080 + public:
2081 + socket_ref() ZMQ_NOTHROW : detail::socket_base() {}
2082 +#ifdef ZMQ_CPP11
2083 + socket_ref(std::nullptr_t) ZMQ_NOTHROW : detail::socket_base() {}
2084 +#endif
2085 + socket_ref(from_handle_t /*fh*/, void *handle) ZMQ_NOTHROW
2086 + : detail::socket_base(handle)
2087 + {
2088 + }
2089 +};
2090 +
2091 +#ifdef ZMQ_CPP11
2092 +inline bool operator==(socket_ref sr, std::nullptr_t /*p*/) ZMQ_NOTHROW
2093 +{
2094 + return sr.handle() == nullptr;
2095 +}
2096 +inline bool operator==(std::nullptr_t /*p*/, socket_ref sr) ZMQ_NOTHROW
2097 +{
2098 + return sr.handle() == nullptr;
2099 +}
2100 +inline bool operator!=(socket_ref sr, std::nullptr_t /*p*/) ZMQ_NOTHROW
2101 +{
2102 + return !(sr == nullptr);
2103 +}
2104 +inline bool operator!=(std::nullptr_t /*p*/, socket_ref sr) ZMQ_NOTHROW
2105 +{
2106 + return !(sr == nullptr);
2107 +}
2108 +#endif
2109 +
2110 +inline bool operator==(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
2111 +{
2112 + return std::equal_to<const void *>()(a.handle(), b.handle());
2113 +}
2114 +inline bool operator!=(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
2115 +{
2116 + return !(a == b);
2117 +}
2118 +inline bool operator<(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
2119 +{
2120 + return std::less<const void *>()(a.handle(), b.handle());
2121 +}
2122 +inline bool operator>(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
2123 +{
2124 + return b < a;
2125 +}
2126 +inline bool operator<=(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
2127 +{
2128 + return !(a > b);
2129 +}
2130 +inline bool operator>=(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
2131 +{
2132 + return !(a < b);
2133 +}
2134 +
2135 +} // namespace zmq
2136 +
2137 +#ifdef ZMQ_CPP11
2138 +namespace std
2139 +{
2140 +template<> struct hash<zmq::socket_ref>
2141 +{
2142 + size_t operator()(zmq::socket_ref sr) const ZMQ_NOTHROW
2143 + {
2144 + return hash<void *>()(sr.handle());
2145 + }
2146 +};
2147 +} // namespace std
2148 +#endif
2149 +
2150 +namespace zmq
2151 +{
2152 +class socket_t : public detail::socket_base
2153 +{
2154 + friend class monitor_t;
2155 +
2156 + public:
2157 + socket_t() ZMQ_NOTHROW : detail::socket_base(ZMQ_NULLPTR), ctxptr(ZMQ_NULLPTR) {}
2158 +
2159 + socket_t(context_t &context_, int type_) :
2160 + detail::socket_base(zmq_socket(context_.handle(), type_)),
2161 + ctxptr(context_.handle())
2162 + {
2163 + if (_handle == ZMQ_NULLPTR)
2164 + throw error_t();
2165 + }
2166 +
2167 +#ifdef ZMQ_CPP11
2168 + socket_t(context_t &context_, socket_type type_) :
2169 + socket_t(context_, static_cast<int>(type_))
2170 + {
2171 + }
2172 +#endif
2173 +
2174 +#ifdef ZMQ_HAS_RVALUE_REFS
2175 + socket_t(socket_t &&rhs) ZMQ_NOTHROW : detail::socket_base(rhs._handle),
2176 + ctxptr(rhs.ctxptr)
2177 + {
2178 + rhs._handle = ZMQ_NULLPTR;
2179 + rhs.ctxptr = ZMQ_NULLPTR;
2180 + }
2181 + socket_t &operator=(socket_t &&rhs) ZMQ_NOTHROW
2182 + {
2183 + close();
2184 + std::swap(_handle, rhs._handle);
2185 + std::swap(ctxptr, rhs.ctxptr);
2186 + return *this;
2187 + }
2188 +#endif
2189 +
2190 + ~socket_t() ZMQ_NOTHROW { close(); }
2191 +
2192 + operator void *() ZMQ_NOTHROW { return _handle; }
2193 +
2194 + operator void const *() const ZMQ_NOTHROW { return _handle; }
2195 +
2196 + void close() ZMQ_NOTHROW
2197 + {
2198 + if (_handle == ZMQ_NULLPTR)
2199 + // already closed
2200 + return;
2201 + int rc = zmq_close(_handle);
2202 + ZMQ_ASSERT(rc == 0);
2203 + _handle = ZMQ_NULLPTR;
2204 + ctxptr = ZMQ_NULLPTR;
2205 + }
2206 +
2207 + void swap(socket_t &other) ZMQ_NOTHROW
2208 + {
2209 + std::swap(_handle, other._handle);
2210 + std::swap(ctxptr, other.ctxptr);
2211 + }
2212 +
2213 + operator socket_ref() ZMQ_NOTHROW { return socket_ref(from_handle, _handle); }
2214 +
2215 + private:
2216 + void *ctxptr;
2217 +
2218 + socket_t(const socket_t &) ZMQ_DELETED_FUNCTION;
2219 + void operator=(const socket_t &) ZMQ_DELETED_FUNCTION;
2220 +
2221 + // used by monitor_t
2222 + socket_t(void *context_, int type_) :
2223 + detail::socket_base(zmq_socket(context_, type_)), ctxptr(context_)
2224 + {
2225 + if (_handle == ZMQ_NULLPTR)
2226 + throw error_t();
2227 + if (ctxptr == ZMQ_NULLPTR)
2228 + throw error_t();
2229 + }
2230 +};
2231 +
2232 +inline void swap(socket_t &a, socket_t &b) ZMQ_NOTHROW
2233 +{
2234 + a.swap(b);
2235 +}
2236 +
2237 +ZMQ_DEPRECATED("from 4.3.1, use proxy taking socket_t objects")
2238 +inline void proxy(void *frontend, void *backend, void *capture)
2239 +{
2240 + int rc = zmq_proxy(frontend, backend, capture);
2241 + if (rc != 0)
2242 + throw error_t();
2243 +}
2244 +
2245 +inline void
2246 +proxy(socket_ref frontend, socket_ref backend, socket_ref capture = socket_ref())
2247 +{
2248 + int rc = zmq_proxy(frontend.handle(), backend.handle(), capture.handle());
2249 + if (rc != 0)
2250 + throw error_t();
2251 +}
2252 +
2253 +#ifdef ZMQ_HAS_PROXY_STEERABLE
2254 +ZMQ_DEPRECATED("from 4.3.1, use proxy_steerable taking socket_t objects")
2255 +inline void
2256 +proxy_steerable(void *frontend, void *backend, void *capture, void *control)
2257 +{
2258 + int rc = zmq_proxy_steerable(frontend, backend, capture, control);
2259 + if (rc != 0)
2260 + throw error_t();
2261 +}
2262 +
2263 +inline void proxy_steerable(socket_ref frontend,
2264 + socket_ref backend,
2265 + socket_ref capture,
2266 + socket_ref control)
2267 +{
2268 + int rc = zmq_proxy_steerable(frontend.handle(), backend.handle(),
2269 + capture.handle(), control.handle());
2270 + if (rc != 0)
2271 + throw error_t();
2272 +}
2273 +#endif
2274 +
2275 +class monitor_t
2276 +{
2277 + public:
2278 + monitor_t() : _socket(), _monitor_socket() {}
2279 +
2280 + virtual ~monitor_t() { close(); }
2281 +
2282 +#ifdef ZMQ_HAS_RVALUE_REFS
2283 + monitor_t(monitor_t &&rhs) ZMQ_NOTHROW : _socket(), _monitor_socket()
2284 + {
2285 + std::swap(_socket, rhs._socket);
2286 + std::swap(_monitor_socket, rhs._monitor_socket);
2287 + }
2288 +
2289 + monitor_t &operator=(monitor_t &&rhs) ZMQ_NOTHROW
2290 + {
2291 + close();
2292 + _socket = socket_ref();
2293 + std::swap(_socket, rhs._socket);
2294 + std::swap(_monitor_socket, rhs._monitor_socket);
2295 + return *this;
2296 + }
2297 +#endif
2298 +
2299 +
2300 + void
2301 + monitor(socket_t &socket, std::string const &addr, int events = ZMQ_EVENT_ALL)
2302 + {
2303 + monitor(socket, addr.c_str(), events);
2304 + }
2305 +
2306 + void monitor(socket_t &socket, const char *addr_, int events = ZMQ_EVENT_ALL)
2307 + {
2308 + init(socket, addr_, events);
2309 + while (true) {
2310 + check_event(-1);
2311 + }
2312 + }
2313 +
2314 + void init(socket_t &socket, std::string const &addr, int events = ZMQ_EVENT_ALL)
2315 + {
2316 + init(socket, addr.c_str(), events);
2317 + }
2318 +
2319 + void init(socket_t &socket, const char *addr_, int events = ZMQ_EVENT_ALL)
2320 + {
2321 + int rc = zmq_socket_monitor(socket.handle(), addr_, events);
2322 + if (rc != 0)
2323 + throw error_t();
2324 +
2325 + _socket = socket;
2326 + _monitor_socket = socket_t(socket.ctxptr, ZMQ_PAIR);
2327 + _monitor_socket.connect(addr_);
2328 +
2329 + on_monitor_started();
2330 + }
2331 +
2332 + bool check_event(int timeout = 0)
2333 + {
2334 + assert(_monitor_socket);
2335 +
2336 + zmq::message_t eventMsg;
2337 +
2338 + zmq::pollitem_t items[] = {
2339 + {_monitor_socket.handle(), 0, ZMQ_POLLIN, 0},
2340 + };
2341 +
2342 + #ifdef ZMQ_CPP11
2343 + zmq::poll(&items[0], 1, std::chrono::milliseconds(timeout));
2344 + #else
2345 + zmq::poll(&items[0], 1, timeout);
2346 + #endif
2347 +
2348 + if (items[0].revents & ZMQ_POLLIN) {
2349 + int rc = zmq_msg_recv(eventMsg.handle(), _monitor_socket.handle(), 0);
2350 + if (rc == -1 && zmq_errno() == ETERM)
2351 + return false;
2352 + assert(rc != -1);
2353 +
2354 + } else {
2355 + return false;
2356 + }
2357 +
2358 +#if ZMQ_VERSION_MAJOR >= 4
2359 + const char *data = static_cast<const char *>(eventMsg.data());
2360 + zmq_event_t msgEvent;
2361 + memcpy(&msgEvent.event, data, sizeof(uint16_t));
2362 + data += sizeof(uint16_t);
2363 + memcpy(&msgEvent.value, data, sizeof(int32_t));
2364 + zmq_event_t *event = &msgEvent;
2365 +#else
2366 + zmq_event_t *event = static_cast<zmq_event_t *>(eventMsg.data());
2367 +#endif
2368 +
2369 +#ifdef ZMQ_NEW_MONITOR_EVENT_LAYOUT
2370 + zmq::message_t addrMsg;
2371 + int rc = zmq_msg_recv(addrMsg.handle(), _monitor_socket.handle(), 0);
2372 + if (rc == -1 && zmq_errno() == ETERM) {
2373 + return false;
2374 + }
2375 +
2376 + assert(rc != -1);
2377 + std::string address = addrMsg.to_string();
2378 +#else
2379 + // 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.
2380 + std::string address = event->data.connected.addr;
2381 +#endif
2382 +
2383 +#ifdef ZMQ_EVENT_MONITOR_STOPPED
2384 + if (event->event == ZMQ_EVENT_MONITOR_STOPPED) {
2385 + return false;
2386 + }
2387 +
2388 +#endif
2389 +
2390 + switch (event->event) {
2391 + case ZMQ_EVENT_CONNECTED:
2392 + on_event_connected(*event, address.c_str());
2393 + break;
2394 + case ZMQ_EVENT_CONNECT_DELAYED:
2395 + on_event_connect_delayed(*event, address.c_str());
2396 + break;
2397 + case ZMQ_EVENT_CONNECT_RETRIED:
2398 + on_event_connect_retried(*event, address.c_str());
2399 + break;
2400 + case ZMQ_EVENT_LISTENING:
2401 + on_event_listening(*event, address.c_str());
2402 + break;
2403 + case ZMQ_EVENT_BIND_FAILED:
2404 + on_event_bind_failed(*event, address.c_str());
2405 + break;
2406 + case ZMQ_EVENT_ACCEPTED:
2407 + on_event_accepted(*event, address.c_str());
2408 + break;
2409 + case ZMQ_EVENT_ACCEPT_FAILED:
2410 + on_event_accept_failed(*event, address.c_str());
2411 + break;
2412 + case ZMQ_EVENT_CLOSED:
2413 + on_event_closed(*event, address.c_str());
2414 + break;
2415 + case ZMQ_EVENT_CLOSE_FAILED:
2416 + on_event_close_failed(*event, address.c_str());
2417 + break;
2418 + case ZMQ_EVENT_DISCONNECTED:
2419 + on_event_disconnected(*event, address.c_str());
2420 + break;
2421 +#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 3, 0) || (defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3))
2422 + case ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL:
2423 + on_event_handshake_failed_no_detail(*event, address.c_str());
2424 + break;
2425 + case ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL:
2426 + on_event_handshake_failed_protocol(*event, address.c_str());
2427 + break;
2428 + case ZMQ_EVENT_HANDSHAKE_FAILED_AUTH:
2429 + on_event_handshake_failed_auth(*event, address.c_str());
2430 + break;
2431 + case ZMQ_EVENT_HANDSHAKE_SUCCEEDED:
2432 + on_event_handshake_succeeded(*event, address.c_str());
2433 + break;
2434 +#elif defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 1)
2435 + case ZMQ_EVENT_HANDSHAKE_FAILED:
2436 + on_event_handshake_failed(*event, address.c_str());
2437 + break;
2438 + case ZMQ_EVENT_HANDSHAKE_SUCCEED:
2439 + on_event_handshake_succeed(*event, address.c_str());
2440 + break;
2441 +#endif
2442 + default:
2443 + on_event_unknown(*event, address.c_str());
2444 + break;
2445 + }
2446 +
2447 + return true;
2448 + }
2449 +
2450 +#ifdef ZMQ_EVENT_MONITOR_STOPPED
2451 + void abort()
2452 + {
2453 + if (_socket)
2454 + zmq_socket_monitor(_socket.handle(), ZMQ_NULLPTR, 0);
2455 +
2456 + _socket = socket_ref();
2457 + }
2458 +#endif
2459 + virtual void on_monitor_started() {}
2460 + virtual void on_event_connected(const zmq_event_t &event_, const char *addr_)
2461 + {
2462 + (void) event_;
2463 + (void) addr_;
2464 + }
2465 + virtual void on_event_connect_delayed(const zmq_event_t &event_,
2466 + const char *addr_)
2467 + {
2468 + (void) event_;
2469 + (void) addr_;
2470 + }
2471 + virtual void on_event_connect_retried(const zmq_event_t &event_,
2472 + const char *addr_)
2473 + {
2474 + (void) event_;
2475 + (void) addr_;
2476 + }
2477 + virtual void on_event_listening(const zmq_event_t &event_, const char *addr_)
2478 + {
2479 + (void) event_;
2480 + (void) addr_;
2481 + }
2482 + virtual void on_event_bind_failed(const zmq_event_t &event_, const char *addr_)
2483 + {
2484 + (void) event_;
2485 + (void) addr_;
2486 + }
2487 + virtual void on_event_accepted(const zmq_event_t &event_, const char *addr_)
2488 + {
2489 + (void) event_;
2490 + (void) addr_;
2491 + }
2492 + virtual void on_event_accept_failed(const zmq_event_t &event_, const char *addr_)
2493 + {
2494 + (void) event_;
2495 + (void) addr_;
2496 + }
2497 + virtual void on_event_closed(const zmq_event_t &event_, const char *addr_)
2498 + {
2499 + (void) event_;
2500 + (void) addr_;
2501 + }
2502 + virtual void on_event_close_failed(const zmq_event_t &event_, const char *addr_)
2503 + {
2504 + (void) event_;
2505 + (void) addr_;
2506 + }
2507 + virtual void on_event_disconnected(const zmq_event_t &event_, const char *addr_)
2508 + {
2509 + (void) event_;
2510 + (void) addr_;
2511 + }
2512 +#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3)
2513 + virtual void on_event_handshake_failed_no_detail(const zmq_event_t &event_,
2514 + const char *addr_)
2515 + {
2516 + (void) event_;
2517 + (void) addr_;
2518 + }
2519 + virtual void on_event_handshake_failed_protocol(const zmq_event_t &event_,
2520 + const char *addr_)
2521 + {
2522 + (void) event_;
2523 + (void) addr_;
2524 + }
2525 + virtual void on_event_handshake_failed_auth(const zmq_event_t &event_,
2526 + const char *addr_)
2527 + {
2528 + (void) event_;
2529 + (void) addr_;
2530 + }
2531 + virtual void on_event_handshake_succeeded(const zmq_event_t &event_,
2532 + const char *addr_)
2533 + {
2534 + (void) event_;
2535 + (void) addr_;
2536 + }
2537 +#elif ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 1)
2538 + virtual void on_event_handshake_failed(const zmq_event_t &event_,
2539 + const char *addr_)
2540 + {
2541 + (void) event_;
2542 + (void) addr_;
2543 + }
2544 + virtual void on_event_handshake_succeed(const zmq_event_t &event_,
2545 + const char *addr_)
2546 + {
2547 + (void) event_;
2548 + (void) addr_;
2549 + }
2550 +#endif
2551 + virtual void on_event_unknown(const zmq_event_t &event_, const char *addr_)
2552 + {
2553 + (void) event_;
2554 + (void) addr_;
2555 + }
2556 +
2557 + private:
2558 + monitor_t(const monitor_t &) ZMQ_DELETED_FUNCTION;
2559 + void operator=(const monitor_t &) ZMQ_DELETED_FUNCTION;
2560 +
2561 + socket_ref _socket;
2562 + socket_t _monitor_socket;
2563 +
2564 + void close() ZMQ_NOTHROW
2565 + {
2566 + if (_socket)
2567 + zmq_socket_monitor(_socket.handle(), ZMQ_NULLPTR, 0);
2568 + _monitor_socket.close();
2569 + }
2570 +};
2571 +
2572 +#if defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER)
2573 +
2574 +// polling events
2575 +enum class event_flags : short
2576 +{
2577 + none = 0,
2578 + pollin = ZMQ_POLLIN,
2579 + pollout = ZMQ_POLLOUT,
2580 + pollerr = ZMQ_POLLERR,
2581 + pollpri = ZMQ_POLLPRI
2582 +};
2583 +
2584 +constexpr event_flags operator|(event_flags a, event_flags b) noexcept
2585 +{
2586 + return detail::enum_bit_or(a, b);
2587 +}
2588 +constexpr event_flags operator&(event_flags a, event_flags b) noexcept
2589 +{
2590 + return detail::enum_bit_and(a, b);
2591 +}
2592 +constexpr event_flags operator^(event_flags a, event_flags b) noexcept
2593 +{
2594 + return detail::enum_bit_xor(a, b);
2595 +}
2596 +constexpr event_flags operator~(event_flags a) noexcept
2597 +{
2598 + return detail::enum_bit_not(a);
2599 +}
2600 +
2601 +struct no_user_data;
2602 +
2603 +// layout compatible with zmq_poller_event_t
2604 +template<class T = no_user_data> struct poller_event
2605 +{
2606 + socket_ref socket;
2607 + ::zmq::fd_t fd;
2608 + T *user_data;
2609 + event_flags events;
2610 +};
2611 +
2612 +template<typename T = no_user_data> class poller_t
2613 +{
2614 + public:
2615 + using event_type = poller_event<T>;
2616 +
2617 + poller_t() : poller_ptr(zmq_poller_new())
2618 + {
2619 + if (!poller_ptr)
2620 + throw error_t();
2621 + }
2622 +
2623 + template<
2624 + typename Dummy = void,
2625 + typename =
2626 + typename std::enable_if<!std::is_same<T, no_user_data>::value, Dummy>::type>
2627 + void add(zmq::socket_ref socket, event_flags events, T *user_data)
2628 + {
2629 + add_impl(socket, events, user_data);
2630 + }
2631 +
2632 + void add(zmq::socket_ref socket, event_flags events)
2633 + {
2634 + add_impl(socket, events, nullptr);
2635 + }
2636 +
2637 + void remove(zmq::socket_ref socket)
2638 + {
2639 + if (0 != zmq_poller_remove(poller_ptr.get(), socket.handle())) {
2640 + throw error_t();
2641 + }
2642 + }
2643 +
2644 + void modify(zmq::socket_ref socket, event_flags events)
2645 + {
2646 + if (0
2647 + != zmq_poller_modify(poller_ptr.get(), socket.handle(),
2648 + static_cast<short>(events))) {
2649 + throw error_t();
2650 + }
2651 + }
2652 +
2653 + size_t wait_all(std::vector<event_type> &poller_events,
2654 + const std::chrono::milliseconds timeout)
2655 + {
2656 + int rc = zmq_poller_wait_all(
2657 + poller_ptr.get(),
2658 + reinterpret_cast<zmq_poller_event_t *>(poller_events.data()),
2659 + static_cast<int>(poller_events.size()),
2660 + static_cast<long>(timeout.count()));
2661 + if (rc > 0)
2662 + return static_cast<size_t>(rc);
2663 +
2664 +#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3)
2665 + if (zmq_errno() == EAGAIN)
2666 +#else
2667 + if (zmq_errno() == ETIMEDOUT)
2668 +#endif
2669 + return 0;
2670 +
2671 + throw error_t();
2672 + }
2673 +
2674 +#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 3, 3)
2675 + size_t size() const noexcept
2676 + {
2677 + int rc = zmq_poller_size(const_cast<void *>(poller_ptr.get()));
2678 + ZMQ_ASSERT(rc >= 0);
2679 + return static_cast<size_t>(std::max(rc, 0));
2680 + }
2681 +#endif
2682 +
2683 + private:
2684 + struct destroy_poller_t
2685 + {
2686 + void operator()(void *ptr) noexcept
2687 + {
2688 + int rc = zmq_poller_destroy(&ptr);
2689 + ZMQ_ASSERT(rc == 0);
2690 + }
2691 + };
2692 +
2693 + std::unique_ptr<void, destroy_poller_t> poller_ptr;
2694 +
2695 + void add_impl(zmq::socket_ref socket, event_flags events, T *user_data)
2696 + {
2697 + if (0
2698 + != zmq_poller_add(poller_ptr.get(), socket.handle(), user_data,
2699 + static_cast<short>(events))) {
2700 + throw error_t();
2701 + }
2702 + }
2703 +};
2704 +#endif // defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER)
2705 +
2706 +inline std::ostream &operator<<(std::ostream &os, const message_t &msg)
2707 +{
2708 + return os << msg.str();
2709 +}
2710 +
2711 +} // namespace zmq
2712 +
2713 +#endif // __ZMQ_HPP_INCLUDED__