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


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Dec 6 2020 04:02:48