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)
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;
begin(T && r)237 template<class T> auto begin(T &&r) -> decltype(begin(std::forward<T>(r)))
238 {
239 return begin(std::forward<T>(r));
240 }
end(T && r)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:
error_t()292 error_t() ZMQ_NOTHROW : errnum(zmq_errno()) {}
error_t(int err)293 explicit error_t(int err) ZMQ_NOTHROW : errnum(err) {}
what() const294 virtual const char *what() const ZMQ_NOTHROW ZMQ_OVERRIDE
295 {
296 return zmq_strerror(errnum);
297 }
num() const298 int num() const ZMQ_NOTHROW { return errnum; }
299
300 private:
301 int errnum;
302 };
303
304 namespace detail {
poll(zmq_pollitem_t * items_,size_t nitems_,long timeout_)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")
poll(zmq_pollitem_t * items_,size_t nitems_,long timeout_)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")
poll(zmq_pollitem_t const * items_,size_t nitems_,long timeout_=-1)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
poll(zmq_pollitem_t const * items,size_t nitems,std::chrono::milliseconds timeout)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")
poll(std::vector<zmq_pollitem_t> const & items,std::chrono::milliseconds timeout)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")
poll(std::vector<zmq_pollitem_t> const & items,long timeout_=-1)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
poll(zmq_pollitem_t * items,size_t nitems,std::chrono::milliseconds timeout=std::chrono::milliseconds{-1})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
poll(std::vector<zmq_pollitem_t> & items,std::chrono::milliseconds timeout=std::chrono::milliseconds{-1})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")
poll(std::vector<zmq_pollitem_t> & items,long timeout_)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>
poll(std::array<zmq_pollitem_t,SIZE> & items,std::chrono::milliseconds timeout=std::chrono::milliseconds{-1})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
version(int * major_,int * minor_,int * patch_)380 inline void version(int *major_, int *minor_, int *patch_)
381 {
382 zmq_version(major_, minor_, patch_);
383 }
384
385 #ifdef ZMQ_CPP11
version()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:
message_t()411 message_t() ZMQ_NOTHROW
412 {
413 int rc = zmq_msg_init(&msg);
414 ZMQ_ASSERT(rc == 0);
415 }
416
message_t(size_t size_)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
message_t(ForwardIter first,ForwardIter last)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
message_t(const void * data_,size_t size_)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
message_t(void * data_,size_t size_,free_fn * ffn_,void * hint_=ZMQ_NULLPTR)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")
message_t(const Char (& data)[N])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>
message_t(const Range & rng)479 explicit message_t(const Range &rng) :
480 message_t(detail::ranges::begin(rng), detail::ranges::end(rng))
481 {
482 }
483
message_t(const std::string & str)484 explicit message_t(const std::string &str) : message_t(str.data(), str.size()) {}
485
486 #if CPPZMQ_HAS_STRING_VIEW
message_t(std::string_view str)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
message_t(message_t && rhs)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
operator =(message_t && rhs)499 message_t &operator=(message_t &&rhs) ZMQ_NOTHROW
500 {
501 std::swap(msg, rhs.msg);
502 return *this;
503 }
504 #endif
505
~message_t()506 ~message_t() ZMQ_NOTHROW
507 {
508 int rc = zmq_msg_close(&msg);
509 ZMQ_ASSERT(rc == 0);
510 }
511
rebuild()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
rebuild(size_t size_)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
rebuild(const void * data_,size_t size_)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
rebuild(void * data_,size_t size_,free_fn * ffn_,void * hint_=ZMQ_NULLPTR)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")
move(message_t const * msg_)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
move(message_t & msg_)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")
copy(message_t const * msg_)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
copy(message_t & msg_)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
more() const582 bool more() const ZMQ_NOTHROW
583 {
584 int rc = zmq_msg_more(const_cast<zmq_msg_t *>(&msg));
585 return rc != 0;
586 }
587
data()588 void *data() ZMQ_NOTHROW { return zmq_msg_data(&msg); }
589
data() const590 const void *data() const ZMQ_NOTHROW
591 {
592 return zmq_msg_data(const_cast<zmq_msg_t *>(&msg));
593 }
594
size() const595 size_t size() const ZMQ_NOTHROW
596 {
597 return zmq_msg_size(const_cast<zmq_msg_t *>(&msg));
598 }
599
empty() const600 ZMQ_NODISCARD bool empty() const ZMQ_NOTHROW { return size() == 0u; }
601
data()602 template<typename T> T *data() ZMQ_NOTHROW { return static_cast<T *>(data()); }
603
data() const604 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")
equal(const message_t * other) const610 bool equal(const message_t *other) const ZMQ_NOTHROW { return *this == *other; }
611
operator ==(const message_t & other) const612 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
operator !=(const message_t & other) const618 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)
get(int property_)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)
gets(const char * property_)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)
routing_id() const644 uint32_t routing_id() const
645 {
646 return zmq_msg_routing_id(const_cast<zmq_msg_t *>(&msg));
647 }
648
set_routing_id(uint32_t routing_id)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
group() const656 const char *group() const
657 {
658 return zmq_msg_group(const_cast<zmq_msg_t *>(&msg));
659 }
660
set_group(const char * group)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
to_string() const670 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
to_string_view() const676 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 */
str() const688 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
swap(message_t & other)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
handle()730 ZMQ_NODISCARD zmq_msg_t *handle() ZMQ_NOTHROW { return &msg; }
handle() const731 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
swap(message_t & a,message_t & b)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:
context_t()796 context_t()
797 {
798 ptr = zmq_ctx_new();
799 if (ptr == ZMQ_NULLPTR)
800 throw error_t();
801 }
802
803
context_t(int io_threads_,int max_sockets_=ZMQ_MAX_SOCKETS_DFLT)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
context_t(context_t && rhs)818 context_t(context_t &&rhs) ZMQ_NOTHROW : ptr(rhs.ptr) { rhs.ptr = ZMQ_NULLPTR; }
operator =(context_t && rhs)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
~context_t()827 ~context_t() ZMQ_NOTHROW { close(); }
828
829 ZMQ_CPP11_DEPRECATED("from 4.7.0, use set taking zmq::ctxopt instead")
setctxopt(int option_,int optval_)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")
getctxopt(int option_)838 int getctxopt(int option_) { return zmq_ctx_get(ptr, option_); }
839
840 #ifdef ZMQ_CPP11
set(ctxopt option,int optval)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
get(ctxopt option)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()).
close()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.
shutdown()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.
operator void*()889 ZMQ_EXPLICIT operator void *() ZMQ_NOTHROW { return ptr; }
890
operator void const*() const891 ZMQ_EXPLICIT operator void const *() const ZMQ_NOTHROW { return ptr; }
892
handle()893 ZMQ_NODISCARD void *handle() ZMQ_NOTHROW { return ptr; }
894
895 ZMQ_DEPRECATED("from 4.7.0, use handle() != nullptr instead")
operator bool() const896 operator bool() const ZMQ_NOTHROW { return ptr != ZMQ_NULLPTR; }
897
swap(context_t & other)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
swap(context_t & a,context_t & b)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
truncatedzmq::recv_buffer_size919 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;
trivial_optional(T value)944 trivial_optional(T value) noexcept : _value(value), _has_value(true) {}
945
operator ->() const946 const T *operator->() const noexcept
947 {
948 assert(_has_value);
949 return &_value;
950 }
operator ->()951 T *operator->() noexcept
952 {
953 assert(_has_value);
954 return &_value;
955 }
956
operator *() const957 const T &operator*() const noexcept
958 {
959 assert(_has_value);
960 return _value;
961 }
operator *()962 T &operator*() noexcept
963 {
964 assert(_has_value);
965 return _value;
966 }
967
value()968 T &value()
969 {
970 if (!_has_value)
971 throw std::exception();
972 return _value;
973 }
value() const974 const T &value() const
975 {
976 if (!_has_value)
977 throw std::exception();
978 return _value;
979 }
980
operator bool() const981 explicit operator bool() const noexcept { return _has_value; }
has_value() const982 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 {
enum_bit_or(T a,T b)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 }
enum_bit_and(T a,T b)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 }
enum_bit_xor(T a,T b)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 }
enum_bit_not(T a)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
operator |(send_flags a,send_flags b)1032 constexpr send_flags operator|(send_flags a, send_flags b) noexcept
1033 {
1034 return detail::enum_bit_or(a, b);
1035 }
operator &(send_flags a,send_flags b)1036 constexpr send_flags operator&(send_flags a, send_flags b) noexcept
1037 {
1038 return detail::enum_bit_and(a, b);
1039 }
operator ^(send_flags a,send_flags b)1040 constexpr send_flags operator^(send_flags a, send_flags b) noexcept
1041 {
1042 return detail::enum_bit_xor(a, b);
1043 }
operator ~(send_flags a)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
operator |(recv_flags a,recv_flags b)1056 constexpr recv_flags operator|(recv_flags a, recv_flags b) noexcept
1057 {
1058 return detail::enum_bit_or(a, b);
1059 }
operator &(recv_flags a,recv_flags b)1060 constexpr recv_flags operator&(recv_flags a, recv_flags b) noexcept
1061 {
1062 return detail::enum_bit_and(a, b);
1063 }
operator ^(recv_flags a,recv_flags b)1064 constexpr recv_flags operator^(recv_flags a, recv_flags b) noexcept
1065 {
1066 return detail::enum_bit_xor(a, b);
1067 }
operator ~(recv_flags a)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:
mutable_buffer()1081 constexpr mutable_buffer() noexcept : _data(nullptr), _size(0) {}
mutable_buffer(void * p,size_t n)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
data() const1089 constexpr void *data() const noexcept { return _data; }
size() const1090 constexpr size_t size() const noexcept { return _size; }
operator +=(size_t n)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
operator +(const mutable_buffer & mb,size_t n)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 }
operator +(size_t n,const mutable_buffer & mb)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:
const_buffer()1118 constexpr const_buffer() noexcept : _data(nullptr), _size(0) {}
const_buffer(const void * p,size_t n)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 }
const_buffer(const mutable_buffer & mb)1125 constexpr const_buffer(const mutable_buffer &mb) noexcept :
1126 _data(mb.data()), _size(mb.size())
1127 {
1128 }
1129
data() const1130 constexpr const void *data() const noexcept { return _data; }
size() const1131 constexpr size_t size() const noexcept { return _size; }
operator +=(size_t n)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
operator +(const const_buffer & cb,size_t n)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 }
operator +(size_t n,const const_buffer & cb)1151 inline const_buffer operator+(size_t n, const const_buffer &cb) noexcept
1152 {
1153 return cb + n;
1154 }
1155
1156 // buffer creation
1157
buffer(void * p,size_t n)1158 constexpr mutable_buffer buffer(void *p, size_t n) noexcept
1159 {
1160 return mutable_buffer(p, n);
1161 }
buffer(const void * p,size_t n)1162 constexpr const_buffer buffer(const void *p, size_t n) noexcept
1163 {
1164 return const_buffer(p, n);
1165 }
buffer(const mutable_buffer & mb)1166 constexpr mutable_buffer buffer(const mutable_buffer &mb) noexcept
1167 {
1168 return mb;
1169 }
buffer(const mutable_buffer & mb,size_t n)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 }
buffer(const const_buffer & cb)1174 constexpr const_buffer buffer(const const_buffer &cb) noexcept
1175 {
1176 return cb;
1177 }
buffer(const const_buffer & cb,size_t n)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
seq_size(const C & c)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>
seq_size(const T (&)[N])1206 constexpr size_t seq_size(const T (&/*array*/)[N]) noexcept
1207 {
1208 return N;
1209 }
1210
1211 template<class Seq>
buffer_contiguous_sequence(Seq && 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>
buffer_contiguous_sequence(Seq && seq,size_t n_bytes)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
buffer(T (& data)[N])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>
buffer(T (& data)[N],size_t n_bytes)1244 mutable_buffer buffer(T (&data)[N], size_t n_bytes) noexcept
1245 {
1246 return detail::buffer_contiguous_sequence(data, n_bytes);
1247 }
buffer(const T (& data)[N])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>
buffer(const T (& data)[N],size_t n_bytes)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
buffer(std::array<T,N> & data)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>
buffer(std::array<T,N> & data,size_t n_bytes)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>
buffer(std::array<const T,N> & data)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>
buffer(std::array<const T,N> & data,size_t n_bytes)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>
buffer(const std::array<T,N> & data)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>
buffer(const std::array<T,N> & data,size_t n_bytes)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>
buffer(std::vector<T,Allocator> & data)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>
buffer(std::vector<T,Allocator> & data,size_t n_bytes)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>
buffer(const std::vector<T,Allocator> & data)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>
buffer(const std::vector<T,Allocator> & data,size_t n_bytes)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>
buffer(std::basic_string<T,Traits,Allocator> & data)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>
buffer(std::basic_string<T,Traits,Allocator> & data,size_t n_bytes)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>
buffer(const std::basic_string<T,Traits,Allocator> & data)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>
buffer(const std::basic_string<T,Traits,Allocator> & data,size_t n_bytes)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>
buffer(std::basic_string_view<T,Traits> data)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>
buffer(std::basic_string_view<T,Traits> data,size_t n_bytes)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>
str_buffer(const Char (& data)[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 {
operator ""_zbuf(const char * str,size_t len)1361 constexpr const_buffer operator"" _zbuf(const char *str, size_t len) noexcept
1362 {
1363 return const_buffer(str, len * sizeof(char));
1364 }
operator ""_zbuf(const wchar_t * str,size_t len)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 }
operator ""_zbuf(const char16_t * str,size_t len)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 }
operator ""_zbuf(const char32_t * str,size_t len)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 namespace sockopt
1380 {
1381 // There are two types of options,
1382 // integral type with known compiler time size (int, bool, int64_t, uint64_t)
1383 // and arrays with dynamic size (strings, binary data).
1384
1385 // BoolUnit: if true accepts values of type bool (but passed as T into libzmq)
1386 template<int Opt, class T, bool BoolUnit = false> struct integral_option
1387 {
1388 };
1389
1390 // NullTerm:
1391 // 0: binary data
1392 // 1: null-terminated string (`getsockopt` size includes null)
1393 // 2: binary (size 32) or Z85 encoder string of size 41 (null included)
1394 template<int Opt, int NullTerm = 1> struct array_option
1395 {
1396 };
1397
1398 #define ZMQ_DEFINE_INTEGRAL_OPT(OPT, NAME, TYPE) \
1399 using NAME##_t = integral_option<OPT, TYPE, false>; \
1400 ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1401 #define ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(OPT, NAME, TYPE) \
1402 using NAME##_t = integral_option<OPT, TYPE, true>; \
1403 ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1404 #define ZMQ_DEFINE_ARRAY_OPT(OPT, NAME) \
1405 using NAME##_t = array_option<OPT>; \
1406 ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1407 #define ZMQ_DEFINE_ARRAY_OPT_BINARY(OPT, NAME) \
1408 using NAME##_t = array_option<OPT, 0>; \
1409 ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1410 #define ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(OPT, NAME) \
1411 using NAME##_t = array_option<OPT, 2>; \
1412 ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1413
1414 // deprecated, use zmq::fd_t
1415 using cppzmq_fd_t = ::zmq::fd_t;
1416
1417 #ifdef ZMQ_AFFINITY
1418 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_AFFINITY, affinity, uint64_t);
1419 #endif
1420 #ifdef ZMQ_BACKLOG
1421 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_BACKLOG, backlog, int);
1422 #endif
1423 #ifdef ZMQ_BINDTODEVICE
1424 ZMQ_DEFINE_ARRAY_OPT_BINARY(ZMQ_BINDTODEVICE, bindtodevice);
1425 #endif
1426 #ifdef ZMQ_CONFLATE
1427 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_CONFLATE, conflate, int);
1428 #endif
1429 #ifdef ZMQ_CONNECT_ROUTING_ID
1430 ZMQ_DEFINE_ARRAY_OPT(ZMQ_CONNECT_ROUTING_ID, connect_routing_id);
1431 #endif
1432 #ifdef ZMQ_CONNECT_TIMEOUT
1433 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_CONNECT_TIMEOUT, connect_timeout, int);
1434 #endif
1435 #ifdef ZMQ_CURVE_PUBLICKEY
1436 ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(ZMQ_CURVE_PUBLICKEY, curve_publickey);
1437 #endif
1438 #ifdef ZMQ_CURVE_SECRETKEY
1439 ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(ZMQ_CURVE_SECRETKEY, curve_secretkey);
1440 #endif
1441 #ifdef ZMQ_CURVE_SERVER
1442 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_CURVE_SERVER, curve_server, int);
1443 #endif
1444 #ifdef ZMQ_CURVE_SERVERKEY
1445 ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(ZMQ_CURVE_SERVERKEY, curve_serverkey);
1446 #endif
1447 #ifdef ZMQ_EVENTS
1448 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_EVENTS, events, int);
1449 #endif
1450 #ifdef ZMQ_FD
1451 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_FD, fd, ::zmq::fd_t);
1452 #endif
1453 #ifdef ZMQ_GSSAPI_PLAINTEXT
1454 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_GSSAPI_PLAINTEXT, gssapi_plaintext, int);
1455 #endif
1456 #ifdef ZMQ_GSSAPI_SERVER
1457 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_GSSAPI_SERVER, gssapi_server, int);
1458 #endif
1459 #ifdef ZMQ_GSSAPI_SERVICE_PRINCIPAL
1460 ZMQ_DEFINE_ARRAY_OPT(ZMQ_GSSAPI_SERVICE_PRINCIPAL, gssapi_service_principal);
1461 #endif
1462 #ifdef ZMQ_GSSAPI_SERVICE_PRINCIPAL_NAMETYPE
1463 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_GSSAPI_SERVICE_PRINCIPAL_NAMETYPE,
1464 gssapi_service_principal_nametype,
1465 int);
1466 #endif
1467 #ifdef ZMQ_GSSAPI_PRINCIPAL
1468 ZMQ_DEFINE_ARRAY_OPT(ZMQ_GSSAPI_PRINCIPAL, gssapi_principal);
1469 #endif
1470 #ifdef ZMQ_GSSAPI_PRINCIPAL_NAMETYPE
1471 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_GSSAPI_PRINCIPAL_NAMETYPE,
1472 gssapi_principal_nametype,
1473 int);
1474 #endif
1475 #ifdef ZMQ_HANDSHAKE_IVL
1476 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HANDSHAKE_IVL, handshake_ivl, int);
1477 #endif
1478 #ifdef ZMQ_HEARTBEAT_IVL
1479 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HEARTBEAT_IVL, heartbeat_ivl, int);
1480 #endif
1481 #ifdef ZMQ_HEARTBEAT_TIMEOUT
1482 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HEARTBEAT_TIMEOUT, heartbeat_timeout, int);
1483 #endif
1484 #ifdef ZMQ_HEARTBEAT_TTL
1485 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HEARTBEAT_TTL, heartbeat_ttl, int);
1486 #endif
1487 #ifdef ZMQ_IMMEDIATE
1488 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_IMMEDIATE, immediate, int);
1489 #endif
1490 #ifdef ZMQ_INVERT_MATCHING
1491 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_INVERT_MATCHING, invert_matching, int);
1492 #endif
1493 #ifdef ZMQ_IPV6
1494 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_IPV6, ipv6, int);
1495 #endif
1496 #ifdef ZMQ_LAST_ENDPOINT
1497 ZMQ_DEFINE_ARRAY_OPT(ZMQ_LAST_ENDPOINT, last_endpoint);
1498 #endif
1499 #ifdef ZMQ_LINGER
1500 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_LINGER, linger, int);
1501 #endif
1502 #ifdef ZMQ_MAXMSGSIZE
1503 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MAXMSGSIZE, maxmsgsize, int64_t);
1504 #endif
1505 #ifdef ZMQ_MECHANISM
1506 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MECHANISM, mechanism, int);
1507 #endif
1508 #ifdef ZMQ_METADATA
1509 ZMQ_DEFINE_ARRAY_OPT(ZMQ_METADATA, metadata);
1510 #endif
1511 #ifdef ZMQ_MULTICAST_HOPS
1512 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MULTICAST_HOPS, multicast_hops, int);
1513 #endif
1514 #ifdef ZMQ_MULTICAST_LOOP
1515 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_MULTICAST_LOOP, multicast_loop, int);
1516 #endif
1517 #ifdef ZMQ_MULTICAST_MAXTPDU
1518 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MULTICAST_MAXTPDU, multicast_maxtpdu, int);
1519 #endif
1520 #ifdef ZMQ_PLAIN_SERVER
1521 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_PLAIN_SERVER, plain_server, int);
1522 #endif
1523 #ifdef ZMQ_PLAIN_PASSWORD
1524 ZMQ_DEFINE_ARRAY_OPT(ZMQ_PLAIN_PASSWORD, plain_password);
1525 #endif
1526 #ifdef ZMQ_PLAIN_USERNAME
1527 ZMQ_DEFINE_ARRAY_OPT(ZMQ_PLAIN_USERNAME, plain_username);
1528 #endif
1529 #ifdef ZMQ_USE_FD
1530 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_USE_FD, use_fd, int);
1531 #endif
1532 #ifdef ZMQ_PROBE_ROUTER
1533 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_PROBE_ROUTER, probe_router, int);
1534 #endif
1535 #ifdef ZMQ_RATE
1536 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RATE, rate, int);
1537 #endif
1538 #ifdef ZMQ_RCVBUF
1539 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RCVBUF, rcvbuf, int);
1540 #endif
1541 #ifdef ZMQ_RCVHWM
1542 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RCVHWM, rcvhwm, int);
1543 #endif
1544 #ifdef ZMQ_RCVMORE
1545 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_RCVMORE, rcvmore, int);
1546 #endif
1547 #ifdef ZMQ_RCVTIMEO
1548 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RCVTIMEO, rcvtimeo, int);
1549 #endif
1550 #ifdef ZMQ_RECONNECT_IVL
1551 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RECONNECT_IVL, reconnect_ivl, int);
1552 #endif
1553 #ifdef ZMQ_RECONNECT_IVL_MAX
1554 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RECONNECT_IVL_MAX, reconnect_ivl_max, int);
1555 #endif
1556 #ifdef ZMQ_RECOVERY_IVL
1557 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RECOVERY_IVL, recovery_ivl, int);
1558 #endif
1559 #ifdef ZMQ_REQ_CORRELATE
1560 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_REQ_CORRELATE, req_correlate, int);
1561 #endif
1562 #ifdef ZMQ_REQ_RELAXED
1563 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_REQ_RELAXED, req_relaxed, int);
1564 #endif
1565 #ifdef ZMQ_ROUTER_HANDOVER
1566 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ROUTER_HANDOVER, router_handover, int);
1567 #endif
1568 #ifdef ZMQ_ROUTER_MANDATORY
1569 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ROUTER_MANDATORY, router_mandatory, int);
1570 #endif
1571 #ifdef ZMQ_ROUTER_NOTIFY
1572 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_ROUTER_NOTIFY, router_notify, int);
1573 #endif
1574 #ifdef ZMQ_ROUTING_ID
1575 ZMQ_DEFINE_ARRAY_OPT_BINARY(ZMQ_ROUTING_ID, routing_id);
1576 #endif
1577 #ifdef ZMQ_SNDBUF
1578 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_SNDBUF, sndbuf, int);
1579 #endif
1580 #ifdef ZMQ_SNDHWM
1581 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_SNDHWM, sndhwm, int);
1582 #endif
1583 #ifdef ZMQ_SNDTIMEO
1584 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_SNDTIMEO, sndtimeo, int);
1585 #endif
1586 #ifdef ZMQ_SOCKS_PROXY
1587 ZMQ_DEFINE_ARRAY_OPT(ZMQ_SOCKS_PROXY, socks_proxy);
1588 #endif
1589 #ifdef ZMQ_STREAM_NOTIFY
1590 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_STREAM_NOTIFY, stream_notify, int);
1591 #endif
1592 #ifdef ZMQ_SUBSCRIBE
1593 ZMQ_DEFINE_ARRAY_OPT(ZMQ_SUBSCRIBE, subscribe);
1594 #endif
1595 #ifdef ZMQ_TCP_KEEPALIVE
1596 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE, tcp_keepalive, int);
1597 #endif
1598 #ifdef ZMQ_TCP_KEEPALIVE_CNT
1599 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE_CNT, tcp_keepalive_cnt, int);
1600 #endif
1601 #ifdef ZMQ_TCP_KEEPALIVE_IDLE
1602 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE_IDLE, tcp_keepalive_idle, int);
1603 #endif
1604 #ifdef ZMQ_TCP_KEEPALIVE_INTVL
1605 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE_INTVL, tcp_keepalive_intvl, int);
1606 #endif
1607 #ifdef ZMQ_TCP_MAXRT
1608 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_MAXRT, tcp_maxrt, int);
1609 #endif
1610 #ifdef ZMQ_THREAD_SAFE
1611 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_THREAD_SAFE, thread_safe, int);
1612 #endif
1613 #ifdef ZMQ_TOS
1614 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TOS, tos, int);
1615 #endif
1616 #ifdef ZMQ_TYPE
1617 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TYPE, type, int);
1618 #endif
1619 #ifdef ZMQ_UNSUBSCRIBE
1620 ZMQ_DEFINE_ARRAY_OPT(ZMQ_UNSUBSCRIBE, unsubscribe);
1621 #endif
1622 #ifdef ZMQ_VMCI_BUFFER_SIZE
1623 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_BUFFER_SIZE, vmci_buffer_size, uint64_t);
1624 #endif
1625 #ifdef ZMQ_VMCI_BUFFER_MIN_SIZE
1626 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_BUFFER_MIN_SIZE, vmci_buffer_min_size, uint64_t);
1627 #endif
1628 #ifdef ZMQ_VMCI_BUFFER_MAX_SIZE
1629 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_BUFFER_MAX_SIZE, vmci_buffer_max_size, uint64_t);
1630 #endif
1631 #ifdef ZMQ_VMCI_CONNECT_TIMEOUT
1632 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_CONNECT_TIMEOUT, vmci_connect_timeout, int);
1633 #endif
1634 #ifdef ZMQ_XPUB_VERBOSE
1635 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_VERBOSE, xpub_verbose, int);
1636 #endif
1637 #ifdef ZMQ_XPUB_VERBOSER
1638 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_VERBOSER, xpub_verboser, int);
1639 #endif
1640 #ifdef ZMQ_XPUB_MANUAL
1641 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_MANUAL, xpub_manual, int);
1642 #endif
1643 #ifdef ZMQ_XPUB_NODROP
1644 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_NODROP, xpub_nodrop, int);
1645 #endif
1646 #ifdef ZMQ_XPUB_WELCOME_MSG
1647 ZMQ_DEFINE_ARRAY_OPT(ZMQ_XPUB_WELCOME_MSG, xpub_welcome_msg);
1648 #endif
1649 #ifdef ZMQ_ZAP_ENFORCE_DOMAIN
1650 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ZAP_ENFORCE_DOMAIN, zap_enforce_domain, int);
1651 #endif
1652 #ifdef ZMQ_ZAP_DOMAIN
1653 ZMQ_DEFINE_ARRAY_OPT(ZMQ_ZAP_DOMAIN, zap_domain);
1654 #endif
1655
1656 } // namespace sockopt
1657 #endif // ZMQ_CPP11
1658
1659
1660 namespace detail
1661 {
1662 class socket_base
1663 {
1664 public:
socket_base()1665 socket_base() ZMQ_NOTHROW : _handle(ZMQ_NULLPTR) {}
socket_base(void * handle)1666 ZMQ_EXPLICIT socket_base(void *handle) ZMQ_NOTHROW : _handle(handle) {}
1667
1668 template<typename T>
1669 ZMQ_CPP11_DEPRECATED("from 4.7.0, use `set` taking option from zmq::sockopt")
setsockopt(int option_,T const & optval)1670 void setsockopt(int option_, T const &optval)
1671 {
1672 setsockopt(option_, &optval, sizeof(T));
1673 }
1674
1675 ZMQ_CPP11_DEPRECATED("from 4.7.0, use `set` taking option from zmq::sockopt")
setsockopt(int option_,const void * optval_,size_t optvallen_)1676 void setsockopt(int option_, const void *optval_, size_t optvallen_)
1677 {
1678 int rc = zmq_setsockopt(_handle, option_, optval_, optvallen_);
1679 if (rc != 0)
1680 throw error_t();
1681 }
1682
1683 ZMQ_CPP11_DEPRECATED("from 4.7.0, use `get` taking option from zmq::sockopt")
getsockopt(int option_,void * optval_,size_t * optvallen_) const1684 void getsockopt(int option_, void *optval_, size_t *optvallen_) const
1685 {
1686 int rc = zmq_getsockopt(_handle, option_, optval_, optvallen_);
1687 if (rc != 0)
1688 throw error_t();
1689 }
1690
1691 template<typename T>
1692 ZMQ_CPP11_DEPRECATED("from 4.7.0, use `get` taking option from zmq::sockopt")
getsockopt(int option_) const1693 T getsockopt(int option_) const
1694 {
1695 T optval;
1696 size_t optlen = sizeof(T);
1697 getsockopt(option_, &optval, &optlen);
1698 return optval;
1699 }
1700
1701 #ifdef ZMQ_CPP11
1702 // Set integral socket option, e.g.
1703 // `socket.set(zmq::sockopt::linger, 0)`
1704 template<int Opt, class T, bool BoolUnit>
set(sockopt::integral_option<Opt,T,BoolUnit>,const T & val)1705 void set(sockopt::integral_option<Opt, T, BoolUnit>, const T &val)
1706 {
1707 static_assert(std::is_integral<T>::value, "T must be integral");
1708 set_option(Opt, &val, sizeof val);
1709 }
1710
1711 // Set integral socket option from boolean, e.g.
1712 // `socket.set(zmq::sockopt::immediate, false)`
1713 template<int Opt, class T>
set(sockopt::integral_option<Opt,T,true>,bool val)1714 void set(sockopt::integral_option<Opt, T, true>, bool val)
1715 {
1716 static_assert(std::is_integral<T>::value, "T must be integral");
1717 T rep_val = val;
1718 set_option(Opt, &rep_val, sizeof rep_val);
1719 }
1720
1721 // Set array socket option, e.g.
1722 // `socket.set(zmq::sockopt::plain_username, "foo123")`
1723 template<int Opt, int NullTerm>
set(sockopt::array_option<Opt,NullTerm>,const char * buf)1724 void set(sockopt::array_option<Opt, NullTerm>, const char *buf)
1725 {
1726 set_option(Opt, buf, std::strlen(buf));
1727 }
1728
1729 // Set array socket option, e.g.
1730 // `socket.set(zmq::sockopt::routing_id, zmq::buffer(id))`
1731 template<int Opt, int NullTerm>
set(sockopt::array_option<Opt,NullTerm>,const_buffer buf)1732 void set(sockopt::array_option<Opt, NullTerm>, const_buffer buf)
1733 {
1734 set_option(Opt, buf.data(), buf.size());
1735 }
1736
1737 // Set array socket option, e.g.
1738 // `socket.set(zmq::sockopt::routing_id, id_str)`
1739 template<int Opt, int NullTerm>
set(sockopt::array_option<Opt,NullTerm>,const std::string & buf)1740 void set(sockopt::array_option<Opt, NullTerm>, const std::string &buf)
1741 {
1742 set_option(Opt, buf.data(), buf.size());
1743 }
1744
1745 #if CPPZMQ_HAS_STRING_VIEW
1746 // Set array socket option, e.g.
1747 // `socket.set(zmq::sockopt::routing_id, id_str)`
1748 template<int Opt, int NullTerm>
set(sockopt::array_option<Opt,NullTerm>,std::string_view buf)1749 void set(sockopt::array_option<Opt, NullTerm>, std::string_view buf)
1750 {
1751 set_option(Opt, buf.data(), buf.size());
1752 }
1753 #endif
1754
1755 // Get scalar socket option, e.g.
1756 // `auto opt = socket.get(zmq::sockopt::linger)`
1757 template<int Opt, class T, bool BoolUnit>
get(sockopt::integral_option<Opt,T,BoolUnit>) const1758 ZMQ_NODISCARD T get(sockopt::integral_option<Opt, T, BoolUnit>) const
1759 {
1760 static_assert(std::is_integral<T>::value, "T must be integral");
1761 T val;
1762 size_t size = sizeof val;
1763 get_option(Opt, &val, &size);
1764 assert(size == sizeof val);
1765 return val;
1766 }
1767
1768 // Get array socket option, writes to buf, returns option size in bytes, e.g.
1769 // `size_t optsize = socket.get(zmq::sockopt::routing_id, zmq::buffer(id))`
1770 template<int Opt, int NullTerm>
get(sockopt::array_option<Opt,NullTerm>,mutable_buffer buf) const1771 ZMQ_NODISCARD size_t get(sockopt::array_option<Opt, NullTerm>,
1772 mutable_buffer buf) const
1773 {
1774 size_t size = buf.size();
1775 get_option(Opt, buf.data(), &size);
1776 return size;
1777 }
1778
1779 // Get array socket option as string (initializes the string buffer size to init_size) e.g.
1780 // `auto s = socket.get(zmq::sockopt::routing_id)`
1781 // Note: removes the null character from null-terminated string options,
1782 // i.e. the string size excludes the null character.
1783 template<int Opt, int NullTerm>
get(sockopt::array_option<Opt,NullTerm>,size_t init_size=1024) const1784 ZMQ_NODISCARD std::string get(sockopt::array_option<Opt, NullTerm>,
1785 size_t init_size = 1024) const
1786 {
1787 if ZMQ_CONSTEXPR_IF (NullTerm == 2) {
1788 if (init_size == 1024) {
1789 init_size = 41; // get as Z85 string
1790 }
1791 }
1792 std::string str(init_size, '\0');
1793 size_t size = get(sockopt::array_option<Opt>{}, buffer(str));
1794 if ZMQ_CONSTEXPR_IF (NullTerm == 1) {
1795 if (size > 0) {
1796 assert(str[size - 1] == '\0');
1797 --size;
1798 }
1799 } else if ZMQ_CONSTEXPR_IF (NullTerm == 2) {
1800 assert(size == 32 || size == 41);
1801 if (size == 41) {
1802 assert(str[size - 1] == '\0');
1803 --size;
1804 }
1805 }
1806 str.resize(size);
1807 return str;
1808 }
1809 #endif
1810
bind(std::string const & addr)1811 void bind(std::string const &addr) { bind(addr.c_str()); }
1812
bind(const char * addr_)1813 void bind(const char *addr_)
1814 {
1815 int rc = zmq_bind(_handle, addr_);
1816 if (rc != 0)
1817 throw error_t();
1818 }
1819
unbind(std::string const & addr)1820 void unbind(std::string const &addr) { unbind(addr.c_str()); }
1821
unbind(const char * addr_)1822 void unbind(const char *addr_)
1823 {
1824 int rc = zmq_unbind(_handle, addr_);
1825 if (rc != 0)
1826 throw error_t();
1827 }
1828
connect(std::string const & addr)1829 void connect(std::string const &addr) { connect(addr.c_str()); }
1830
connect(const char * addr_)1831 void connect(const char *addr_)
1832 {
1833 int rc = zmq_connect(_handle, addr_);
1834 if (rc != 0)
1835 throw error_t();
1836 }
1837
disconnect(std::string const & addr)1838 void disconnect(std::string const &addr) { disconnect(addr.c_str()); }
1839
disconnect(const char * addr_)1840 void disconnect(const char *addr_)
1841 {
1842 int rc = zmq_disconnect(_handle, addr_);
1843 if (rc != 0)
1844 throw error_t();
1845 }
1846
1847 ZMQ_DEPRECATED("from 4.7.1, use handle() != nullptr or operator bool")
connected() const1848 bool connected() const ZMQ_NOTHROW { return (_handle != ZMQ_NULLPTR); }
1849
1850 ZMQ_CPP11_DEPRECATED("from 4.3.1, use send taking a const_buffer and send_flags")
send(const void * buf_,size_t len_,int flags_=0)1851 size_t send(const void *buf_, size_t len_, int flags_ = 0)
1852 {
1853 int nbytes = zmq_send(_handle, buf_, len_, flags_);
1854 if (nbytes >= 0)
1855 return static_cast<size_t>(nbytes);
1856 if (zmq_errno() == EAGAIN)
1857 return 0;
1858 throw error_t();
1859 }
1860
1861 ZMQ_CPP11_DEPRECATED("from 4.3.1, use send taking message_t and send_flags")
send(message_t & msg_,int flags_=0)1862 bool send(message_t &msg_,
1863 int flags_ = 0) // default until removed
1864 {
1865 int nbytes = zmq_msg_send(msg_.handle(), _handle, flags_);
1866 if (nbytes >= 0)
1867 return true;
1868 if (zmq_errno() == EAGAIN)
1869 return false;
1870 throw error_t();
1871 }
1872
1873 template<typename T>
1874 ZMQ_CPP11_DEPRECATED(
1875 "from 4.4.1, use send taking message_t or buffer (for contiguous "
1876 "ranges), and send_flags")
send(T first,T last,int flags_=0)1877 bool send(T first, T last, int flags_ = 0)
1878 {
1879 zmq::message_t msg(first, last);
1880 int nbytes = zmq_msg_send(msg.handle(), _handle, flags_);
1881 if (nbytes >= 0)
1882 return true;
1883 if (zmq_errno() == EAGAIN)
1884 return false;
1885 throw error_t();
1886 }
1887
1888 #ifdef ZMQ_HAS_RVALUE_REFS
1889 ZMQ_CPP11_DEPRECATED("from 4.3.1, use send taking message_t and send_flags")
send(message_t && msg_,int flags_=0)1890 bool send(message_t &&msg_,
1891 int flags_ = 0) // default until removed
1892 {
1893 #ifdef ZMQ_CPP11
1894 return send(msg_, static_cast<send_flags>(flags_)).has_value();
1895 #else
1896 return send(msg_, flags_);
1897 #endif
1898 }
1899 #endif
1900
1901 #ifdef ZMQ_CPP11
send(const_buffer buf,send_flags flags=send_flags::none)1902 send_result_t send(const_buffer buf, send_flags flags = send_flags::none)
1903 {
1904 const int nbytes =
1905 zmq_send(_handle, buf.data(), buf.size(), static_cast<int>(flags));
1906 if (nbytes >= 0)
1907 return static_cast<size_t>(nbytes);
1908 if (zmq_errno() == EAGAIN)
1909 return {};
1910 throw error_t();
1911 }
1912
send(message_t & msg,send_flags flags)1913 send_result_t send(message_t &msg, send_flags flags)
1914 {
1915 int nbytes = zmq_msg_send(msg.handle(), _handle, static_cast<int>(flags));
1916 if (nbytes >= 0)
1917 return static_cast<size_t>(nbytes);
1918 if (zmq_errno() == EAGAIN)
1919 return {};
1920 throw error_t();
1921 }
1922
send(message_t && msg,send_flags flags)1923 send_result_t send(message_t &&msg, send_flags flags)
1924 {
1925 return send(msg, flags);
1926 }
1927 #endif
1928
1929 ZMQ_CPP11_DEPRECATED(
1930 "from 4.3.1, use recv taking a mutable_buffer and recv_flags")
recv(void * buf_,size_t len_,int flags_=0)1931 size_t recv(void *buf_, size_t len_, int flags_ = 0)
1932 {
1933 int nbytes = zmq_recv(_handle, buf_, len_, flags_);
1934 if (nbytes >= 0)
1935 return static_cast<size_t>(nbytes);
1936 if (zmq_errno() == EAGAIN)
1937 return 0;
1938 throw error_t();
1939 }
1940
1941 ZMQ_CPP11_DEPRECATED(
1942 "from 4.3.1, use recv taking a reference to message_t and recv_flags")
recv(message_t * msg_,int flags_=0)1943 bool recv(message_t *msg_, int flags_ = 0)
1944 {
1945 int nbytes = zmq_msg_recv(msg_->handle(), _handle, flags_);
1946 if (nbytes >= 0)
1947 return true;
1948 if (zmq_errno() == EAGAIN)
1949 return false;
1950 throw error_t();
1951 }
1952
1953 #ifdef ZMQ_CPP11
1954 ZMQ_NODISCARD
recv(mutable_buffer buf,recv_flags flags=recv_flags::none)1955 recv_buffer_result_t recv(mutable_buffer buf,
1956 recv_flags flags = recv_flags::none)
1957 {
1958 const int nbytes =
1959 zmq_recv(_handle, buf.data(), buf.size(), static_cast<int>(flags));
1960 if (nbytes >= 0) {
1961 return recv_buffer_size{
1962 (std::min)(static_cast<size_t>(nbytes), buf.size()),
1963 static_cast<size_t>(nbytes)};
1964 }
1965 if (zmq_errno() == EAGAIN)
1966 return {};
1967 throw error_t();
1968 }
1969
1970 ZMQ_NODISCARD
recv(message_t & msg,recv_flags flags=recv_flags::none)1971 recv_result_t recv(message_t &msg, recv_flags flags = recv_flags::none)
1972 {
1973 const int nbytes =
1974 zmq_msg_recv(msg.handle(), _handle, static_cast<int>(flags));
1975 if (nbytes >= 0) {
1976 assert(msg.size() == static_cast<size_t>(nbytes));
1977 return static_cast<size_t>(nbytes);
1978 }
1979 if (zmq_errno() == EAGAIN)
1980 return {};
1981 throw error_t();
1982 }
1983 #endif
1984
1985 #if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 0)
join(const char * group)1986 void join(const char *group)
1987 {
1988 int rc = zmq_join(_handle, group);
1989 if (rc != 0)
1990 throw error_t();
1991 }
1992
leave(const char * group)1993 void leave(const char *group)
1994 {
1995 int rc = zmq_leave(_handle, group);
1996 if (rc != 0)
1997 throw error_t();
1998 }
1999 #endif
2000
handle()2001 ZMQ_NODISCARD void *handle() ZMQ_NOTHROW { return _handle; }
handle() const2002 ZMQ_NODISCARD const void *handle() const ZMQ_NOTHROW { return _handle; }
2003
operator bool() const2004 ZMQ_EXPLICIT operator bool() const ZMQ_NOTHROW { return _handle != ZMQ_NULLPTR; }
2005 // note: non-const operator bool can be removed once
2006 // operator void* is removed from socket_t
operator bool()2007 ZMQ_EXPLICIT operator bool() ZMQ_NOTHROW { return _handle != ZMQ_NULLPTR; }
2008
2009 protected:
2010 void *_handle;
2011
2012 private:
set_option(int option_,const void * optval_,size_t optvallen_)2013 void set_option(int option_, const void *optval_, size_t optvallen_)
2014 {
2015 int rc = zmq_setsockopt(_handle, option_, optval_, optvallen_);
2016 if (rc != 0)
2017 throw error_t();
2018 }
2019
get_option(int option_,void * optval_,size_t * optvallen_) const2020 void get_option(int option_, void *optval_, size_t *optvallen_) const
2021 {
2022 int rc = zmq_getsockopt(_handle, option_, optval_, optvallen_);
2023 if (rc != 0)
2024 throw error_t();
2025 }
2026 };
2027 } // namespace detail
2028
2029 #ifdef ZMQ_CPP11
2030 enum class socket_type : int
2031 {
2032 req = ZMQ_REQ,
2033 rep = ZMQ_REP,
2034 dealer = ZMQ_DEALER,
2035 router = ZMQ_ROUTER,
2036 pub = ZMQ_PUB,
2037 sub = ZMQ_SUB,
2038 xpub = ZMQ_XPUB,
2039 xsub = ZMQ_XSUB,
2040 push = ZMQ_PUSH,
2041 pull = ZMQ_PULL,
2042 #if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 0)
2043 server = ZMQ_SERVER,
2044 client = ZMQ_CLIENT,
2045 radio = ZMQ_RADIO,
2046 dish = ZMQ_DISH,
2047 gather = ZMQ_GATHER,
2048 scatter = ZMQ_SCATTER,
2049 dgram = ZMQ_DGRAM,
2050 #endif
2051 #if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 3, 3)
2052 peer = ZMQ_PEER,
2053 channel = ZMQ_CHANNEL,
2054 #endif
2055 #if ZMQ_VERSION_MAJOR >= 4
2056 stream = ZMQ_STREAM,
2057 #endif
2058 pair = ZMQ_PAIR
2059 };
2060 #endif
2061
2062 struct from_handle_t
2063 {
2064 struct _private
2065 {
2066 }; // disabling use other than with from_handle
from_handle_tzmq::from_handle_t2067 ZMQ_CONSTEXPR_FN ZMQ_EXPLICIT from_handle_t(_private /*p*/) ZMQ_NOTHROW {}
2068 };
2069
2070 ZMQ_CONSTEXPR_VAR from_handle_t from_handle =
2071 from_handle_t(from_handle_t::_private());
2072
2073 // A non-owning nullable reference to a socket.
2074 // The reference is invalidated on socket close or destruction.
2075 class socket_ref : public detail::socket_base
2076 {
2077 public:
socket_ref()2078 socket_ref() ZMQ_NOTHROW : detail::socket_base() {}
2079 #ifdef ZMQ_CPP11
socket_ref(std::nullptr_t)2080 socket_ref(std::nullptr_t) ZMQ_NOTHROW : detail::socket_base() {}
2081 #endif
socket_ref(from_handle_t,void * handle)2082 socket_ref(from_handle_t /*fh*/, void *handle) ZMQ_NOTHROW
2083 : detail::socket_base(handle)
2084 {
2085 }
2086 };
2087
2088 #ifdef ZMQ_CPP11
operator ==(socket_ref sr,std::nullptr_t)2089 inline bool operator==(socket_ref sr, std::nullptr_t /*p*/) ZMQ_NOTHROW
2090 {
2091 return sr.handle() == nullptr;
2092 }
operator ==(std::nullptr_t,socket_ref sr)2093 inline bool operator==(std::nullptr_t /*p*/, socket_ref sr) ZMQ_NOTHROW
2094 {
2095 return sr.handle() == nullptr;
2096 }
operator !=(socket_ref sr,std::nullptr_t)2097 inline bool operator!=(socket_ref sr, std::nullptr_t /*p*/) ZMQ_NOTHROW
2098 {
2099 return !(sr == nullptr);
2100 }
operator !=(std::nullptr_t,socket_ref sr)2101 inline bool operator!=(std::nullptr_t /*p*/, socket_ref sr) ZMQ_NOTHROW
2102 {
2103 return !(sr == nullptr);
2104 }
2105 #endif
2106
operator ==(const detail::socket_base & a,const detail::socket_base & b)2107 inline bool operator==(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
2108 {
2109 return std::equal_to<const void *>()(a.handle(), b.handle());
2110 }
operator !=(const detail::socket_base & a,const detail::socket_base & b)2111 inline bool operator!=(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
2112 {
2113 return !(a == b);
2114 }
operator <(const detail::socket_base & a,const detail::socket_base & b)2115 inline bool operator<(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
2116 {
2117 return std::less<const void *>()(a.handle(), b.handle());
2118 }
operator >(const detail::socket_base & a,const detail::socket_base & b)2119 inline bool operator>(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
2120 {
2121 return b < a;
2122 }
operator <=(const detail::socket_base & a,const detail::socket_base & b)2123 inline bool operator<=(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
2124 {
2125 return !(a > b);
2126 }
operator >=(const detail::socket_base & a,const detail::socket_base & b)2127 inline bool operator>=(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
2128 {
2129 return !(a < b);
2130 }
2131
2132 } // namespace zmq
2133
2134 #ifdef ZMQ_CPP11
2135 namespace std
2136 {
2137 template<> struct hash<zmq::socket_ref>
2138 {
operator ()std::hash2139 size_t operator()(zmq::socket_ref sr) const ZMQ_NOTHROW
2140 {
2141 return hash<void *>()(sr.handle());
2142 }
2143 };
2144 } // namespace std
2145 #endif
2146
2147 namespace zmq
2148 {
2149 class socket_t : public detail::socket_base
2150 {
2151 friend class monitor_t;
2152
2153 public:
socket_t()2154 socket_t() ZMQ_NOTHROW : detail::socket_base(ZMQ_NULLPTR), ctxptr(ZMQ_NULLPTR) {}
2155
socket_t(context_t & context_,int type_)2156 socket_t(context_t &context_, int type_) :
2157 detail::socket_base(zmq_socket(context_.handle(), type_)),
2158 ctxptr(context_.handle())
2159 {
2160 if (_handle == ZMQ_NULLPTR)
2161 throw error_t();
2162 }
2163
2164 #ifdef ZMQ_CPP11
socket_t(context_t & context_,socket_type type_)2165 socket_t(context_t &context_, socket_type type_) :
2166 socket_t(context_, static_cast<int>(type_))
2167 {
2168 }
2169 #endif
2170
2171 #ifdef ZMQ_HAS_RVALUE_REFS
socket_t(socket_t && rhs)2172 socket_t(socket_t &&rhs) ZMQ_NOTHROW : detail::socket_base(rhs._handle),
2173 ctxptr(rhs.ctxptr)
2174 {
2175 rhs._handle = ZMQ_NULLPTR;
2176 rhs.ctxptr = ZMQ_NULLPTR;
2177 }
operator =(socket_t && rhs)2178 socket_t &operator=(socket_t &&rhs) ZMQ_NOTHROW
2179 {
2180 close();
2181 std::swap(_handle, rhs._handle);
2182 std::swap(ctxptr, rhs.ctxptr);
2183 return *this;
2184 }
2185 #endif
2186
~socket_t()2187 ~socket_t() ZMQ_NOTHROW { close(); }
2188
operator void*()2189 operator void *() ZMQ_NOTHROW { return _handle; }
2190
operator void const*() const2191 operator void const *() const ZMQ_NOTHROW { return _handle; }
2192
close()2193 void close() ZMQ_NOTHROW
2194 {
2195 if (_handle == ZMQ_NULLPTR)
2196 // already closed
2197 return;
2198 int rc = zmq_close(_handle);
2199 ZMQ_ASSERT(rc == 0);
2200 _handle = ZMQ_NULLPTR;
2201 ctxptr = ZMQ_NULLPTR;
2202 }
2203
swap(socket_t & other)2204 void swap(socket_t &other) ZMQ_NOTHROW
2205 {
2206 std::swap(_handle, other._handle);
2207 std::swap(ctxptr, other.ctxptr);
2208 }
2209
operator socket_ref()2210 operator socket_ref() ZMQ_NOTHROW { return socket_ref(from_handle, _handle); }
2211
2212 private:
2213 void *ctxptr;
2214
2215 socket_t(const socket_t &) ZMQ_DELETED_FUNCTION;
2216 void operator=(const socket_t &) ZMQ_DELETED_FUNCTION;
2217
2218 // used by monitor_t
socket_t(void * context_,int type_)2219 socket_t(void *context_, int type_) :
2220 detail::socket_base(zmq_socket(context_, type_)), ctxptr(context_)
2221 {
2222 if (_handle == ZMQ_NULLPTR)
2223 throw error_t();
2224 if (ctxptr == ZMQ_NULLPTR)
2225 throw error_t();
2226 }
2227 };
2228
swap(socket_t & a,socket_t & b)2229 inline void swap(socket_t &a, socket_t &b) ZMQ_NOTHROW
2230 {
2231 a.swap(b);
2232 }
2233
2234 ZMQ_DEPRECATED("from 4.3.1, use proxy taking socket_t objects")
proxy(void * frontend,void * backend,void * capture)2235 inline void proxy(void *frontend, void *backend, void *capture)
2236 {
2237 int rc = zmq_proxy(frontend, backend, capture);
2238 if (rc != 0)
2239 throw error_t();
2240 }
2241
2242 inline void
proxy(socket_ref frontend,socket_ref backend,socket_ref capture=socket_ref ())2243 proxy(socket_ref frontend, socket_ref backend, socket_ref capture = socket_ref())
2244 {
2245 int rc = zmq_proxy(frontend.handle(), backend.handle(), capture.handle());
2246 if (rc != 0)
2247 throw error_t();
2248 }
2249
2250 #ifdef ZMQ_HAS_PROXY_STEERABLE
2251 ZMQ_DEPRECATED("from 4.3.1, use proxy_steerable taking socket_t objects")
2252 inline void
proxy_steerable(void * frontend,void * backend,void * capture,void * control)2253 proxy_steerable(void *frontend, void *backend, void *capture, void *control)
2254 {
2255 int rc = zmq_proxy_steerable(frontend, backend, capture, control);
2256 if (rc != 0)
2257 throw error_t();
2258 }
2259
proxy_steerable(socket_ref frontend,socket_ref backend,socket_ref capture,socket_ref control)2260 inline void proxy_steerable(socket_ref frontend,
2261 socket_ref backend,
2262 socket_ref capture,
2263 socket_ref control)
2264 {
2265 int rc = zmq_proxy_steerable(frontend.handle(), backend.handle(),
2266 capture.handle(), control.handle());
2267 if (rc != 0)
2268 throw error_t();
2269 }
2270 #endif
2271
2272 class monitor_t
2273 {
2274 public:
monitor_t()2275 monitor_t() : _socket(), _monitor_socket() {}
2276
~monitor_t()2277 virtual ~monitor_t() { close(); }
2278
2279 #ifdef ZMQ_HAS_RVALUE_REFS
monitor_t(monitor_t && rhs)2280 monitor_t(monitor_t &&rhs) ZMQ_NOTHROW : _socket(), _monitor_socket()
2281 {
2282 std::swap(_socket, rhs._socket);
2283 std::swap(_monitor_socket, rhs._monitor_socket);
2284 }
2285
operator =(monitor_t && rhs)2286 monitor_t &operator=(monitor_t &&rhs) ZMQ_NOTHROW
2287 {
2288 close();
2289 _socket = socket_ref();
2290 std::swap(_socket, rhs._socket);
2291 std::swap(_monitor_socket, rhs._monitor_socket);
2292 return *this;
2293 }
2294 #endif
2295
2296
2297 void
monitor(socket_t & socket,std::string const & addr,int events=ZMQ_EVENT_ALL)2298 monitor(socket_t &socket, std::string const &addr, int events = ZMQ_EVENT_ALL)
2299 {
2300 monitor(socket, addr.c_str(), events);
2301 }
2302
monitor(socket_t & socket,const char * addr_,int events=ZMQ_EVENT_ALL)2303 void monitor(socket_t &socket, const char *addr_, int events = ZMQ_EVENT_ALL)
2304 {
2305 init(socket, addr_, events);
2306 while (true) {
2307 check_event(-1);
2308 }
2309 }
2310
init(socket_t & socket,std::string const & addr,int events=ZMQ_EVENT_ALL)2311 void init(socket_t &socket, std::string const &addr, int events = ZMQ_EVENT_ALL)
2312 {
2313 init(socket, addr.c_str(), events);
2314 }
2315
init(socket_t & socket,const char * addr_,int events=ZMQ_EVENT_ALL)2316 void init(socket_t &socket, const char *addr_, int events = ZMQ_EVENT_ALL)
2317 {
2318 int rc = zmq_socket_monitor(socket.handle(), addr_, events);
2319 if (rc != 0)
2320 throw error_t();
2321
2322 _socket = socket;
2323 _monitor_socket = socket_t(socket.ctxptr, ZMQ_PAIR);
2324 _monitor_socket.connect(addr_);
2325
2326 on_monitor_started();
2327 }
2328
check_event(int timeout=0)2329 bool check_event(int timeout = 0)
2330 {
2331 assert(_monitor_socket);
2332
2333 zmq::message_t eventMsg;
2334
2335 zmq::pollitem_t items[] = {
2336 {_monitor_socket.handle(), 0, ZMQ_POLLIN, 0},
2337 };
2338
2339 #ifdef ZMQ_CPP11
2340 zmq::poll(&items[0], 1, std::chrono::milliseconds(timeout));
2341 #else
2342 zmq::poll(&items[0], 1, timeout);
2343 #endif
2344
2345 if (items[0].revents & ZMQ_POLLIN) {
2346 int rc = zmq_msg_recv(eventMsg.handle(), _monitor_socket.handle(), 0);
2347 if (rc == -1 && zmq_errno() == ETERM)
2348 return false;
2349 assert(rc != -1);
2350
2351 } else {
2352 return false;
2353 }
2354
2355 #if ZMQ_VERSION_MAJOR >= 4
2356 const char *data = static_cast<const char *>(eventMsg.data());
2357 zmq_event_t msgEvent;
2358 memcpy(&msgEvent.event, data, sizeof(uint16_t));
2359 data += sizeof(uint16_t);
2360 memcpy(&msgEvent.value, data, sizeof(int32_t));
2361 zmq_event_t *event = &msgEvent;
2362 #else
2363 zmq_event_t *event = static_cast<zmq_event_t *>(eventMsg.data());
2364 #endif
2365
2366 #ifdef ZMQ_NEW_MONITOR_EVENT_LAYOUT
2367 zmq::message_t addrMsg;
2368 int rc = zmq_msg_recv(addrMsg.handle(), _monitor_socket.handle(), 0);
2369 if (rc == -1 && zmq_errno() == ETERM) {
2370 return false;
2371 }
2372
2373 assert(rc != -1);
2374 std::string address = addrMsg.to_string();
2375 #else
2376 // 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.
2377 std::string address = event->data.connected.addr;
2378 #endif
2379
2380 #ifdef ZMQ_EVENT_MONITOR_STOPPED
2381 if (event->event == ZMQ_EVENT_MONITOR_STOPPED) {
2382 return false;
2383 }
2384
2385 #endif
2386
2387 switch (event->event) {
2388 case ZMQ_EVENT_CONNECTED:
2389 on_event_connected(*event, address.c_str());
2390 break;
2391 case ZMQ_EVENT_CONNECT_DELAYED:
2392 on_event_connect_delayed(*event, address.c_str());
2393 break;
2394 case ZMQ_EVENT_CONNECT_RETRIED:
2395 on_event_connect_retried(*event, address.c_str());
2396 break;
2397 case ZMQ_EVENT_LISTENING:
2398 on_event_listening(*event, address.c_str());
2399 break;
2400 case ZMQ_EVENT_BIND_FAILED:
2401 on_event_bind_failed(*event, address.c_str());
2402 break;
2403 case ZMQ_EVENT_ACCEPTED:
2404 on_event_accepted(*event, address.c_str());
2405 break;
2406 case ZMQ_EVENT_ACCEPT_FAILED:
2407 on_event_accept_failed(*event, address.c_str());
2408 break;
2409 case ZMQ_EVENT_CLOSED:
2410 on_event_closed(*event, address.c_str());
2411 break;
2412 case ZMQ_EVENT_CLOSE_FAILED:
2413 on_event_close_failed(*event, address.c_str());
2414 break;
2415 case ZMQ_EVENT_DISCONNECTED:
2416 on_event_disconnected(*event, address.c_str());
2417 break;
2418 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 3, 0) || (defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3))
2419 case ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL:
2420 on_event_handshake_failed_no_detail(*event, address.c_str());
2421 break;
2422 case ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL:
2423 on_event_handshake_failed_protocol(*event, address.c_str());
2424 break;
2425 case ZMQ_EVENT_HANDSHAKE_FAILED_AUTH:
2426 on_event_handshake_failed_auth(*event, address.c_str());
2427 break;
2428 case ZMQ_EVENT_HANDSHAKE_SUCCEEDED:
2429 on_event_handshake_succeeded(*event, address.c_str());
2430 break;
2431 #elif defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 1)
2432 case ZMQ_EVENT_HANDSHAKE_FAILED:
2433 on_event_handshake_failed(*event, address.c_str());
2434 break;
2435 case ZMQ_EVENT_HANDSHAKE_SUCCEED:
2436 on_event_handshake_succeed(*event, address.c_str());
2437 break;
2438 #endif
2439 default:
2440 on_event_unknown(*event, address.c_str());
2441 break;
2442 }
2443
2444 return true;
2445 }
2446
2447 #ifdef ZMQ_EVENT_MONITOR_STOPPED
abort()2448 void abort()
2449 {
2450 if (_socket)
2451 zmq_socket_monitor(_socket.handle(), ZMQ_NULLPTR, 0);
2452
2453 _socket = socket_ref();
2454 }
2455 #endif
on_monitor_started()2456 virtual void on_monitor_started() {}
on_event_connected(const zmq_event_t & event_,const char * addr_)2457 virtual void on_event_connected(const zmq_event_t &event_, const char *addr_)
2458 {
2459 (void) event_;
2460 (void) addr_;
2461 }
on_event_connect_delayed(const zmq_event_t & event_,const char * addr_)2462 virtual void on_event_connect_delayed(const zmq_event_t &event_,
2463 const char *addr_)
2464 {
2465 (void) event_;
2466 (void) addr_;
2467 }
on_event_connect_retried(const zmq_event_t & event_,const char * addr_)2468 virtual void on_event_connect_retried(const zmq_event_t &event_,
2469 const char *addr_)
2470 {
2471 (void) event_;
2472 (void) addr_;
2473 }
on_event_listening(const zmq_event_t & event_,const char * addr_)2474 virtual void on_event_listening(const zmq_event_t &event_, const char *addr_)
2475 {
2476 (void) event_;
2477 (void) addr_;
2478 }
on_event_bind_failed(const zmq_event_t & event_,const char * addr_)2479 virtual void on_event_bind_failed(const zmq_event_t &event_, const char *addr_)
2480 {
2481 (void) event_;
2482 (void) addr_;
2483 }
on_event_accepted(const zmq_event_t & event_,const char * addr_)2484 virtual void on_event_accepted(const zmq_event_t &event_, const char *addr_)
2485 {
2486 (void) event_;
2487 (void) addr_;
2488 }
on_event_accept_failed(const zmq_event_t & event_,const char * addr_)2489 virtual void on_event_accept_failed(const zmq_event_t &event_, const char *addr_)
2490 {
2491 (void) event_;
2492 (void) addr_;
2493 }
on_event_closed(const zmq_event_t & event_,const char * addr_)2494 virtual void on_event_closed(const zmq_event_t &event_, const char *addr_)
2495 {
2496 (void) event_;
2497 (void) addr_;
2498 }
on_event_close_failed(const zmq_event_t & event_,const char * addr_)2499 virtual void on_event_close_failed(const zmq_event_t &event_, const char *addr_)
2500 {
2501 (void) event_;
2502 (void) addr_;
2503 }
on_event_disconnected(const zmq_event_t & event_,const char * addr_)2504 virtual void on_event_disconnected(const zmq_event_t &event_, const char *addr_)
2505 {
2506 (void) event_;
2507 (void) addr_;
2508 }
2509 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3)
on_event_handshake_failed_no_detail(const zmq_event_t & event_,const char * addr_)2510 virtual void on_event_handshake_failed_no_detail(const zmq_event_t &event_,
2511 const char *addr_)
2512 {
2513 (void) event_;
2514 (void) addr_;
2515 }
on_event_handshake_failed_protocol(const zmq_event_t & event_,const char * addr_)2516 virtual void on_event_handshake_failed_protocol(const zmq_event_t &event_,
2517 const char *addr_)
2518 {
2519 (void) event_;
2520 (void) addr_;
2521 }
on_event_handshake_failed_auth(const zmq_event_t & event_,const char * addr_)2522 virtual void on_event_handshake_failed_auth(const zmq_event_t &event_,
2523 const char *addr_)
2524 {
2525 (void) event_;
2526 (void) addr_;
2527 }
on_event_handshake_succeeded(const zmq_event_t & event_,const char * addr_)2528 virtual void on_event_handshake_succeeded(const zmq_event_t &event_,
2529 const char *addr_)
2530 {
2531 (void) event_;
2532 (void) addr_;
2533 }
2534 #elif ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 1)
on_event_handshake_failed(const zmq_event_t & event_,const char * addr_)2535 virtual void on_event_handshake_failed(const zmq_event_t &event_,
2536 const char *addr_)
2537 {
2538 (void) event_;
2539 (void) addr_;
2540 }
on_event_handshake_succeed(const zmq_event_t & event_,const char * addr_)2541 virtual void on_event_handshake_succeed(const zmq_event_t &event_,
2542 const char *addr_)
2543 {
2544 (void) event_;
2545 (void) addr_;
2546 }
2547 #endif
on_event_unknown(const zmq_event_t & event_,const char * addr_)2548 virtual void on_event_unknown(const zmq_event_t &event_, const char *addr_)
2549 {
2550 (void) event_;
2551 (void) addr_;
2552 }
2553
2554 private:
2555 monitor_t(const monitor_t &) ZMQ_DELETED_FUNCTION;
2556 void operator=(const monitor_t &) ZMQ_DELETED_FUNCTION;
2557
2558 socket_ref _socket;
2559 socket_t _monitor_socket;
2560
close()2561 void close() ZMQ_NOTHROW
2562 {
2563 if (_socket)
2564 zmq_socket_monitor(_socket.handle(), ZMQ_NULLPTR, 0);
2565 _monitor_socket.close();
2566 }
2567 };
2568
2569 #if defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER)
2570
2571 // polling events
2572 enum class event_flags : short
2573 {
2574 none = 0,
2575 pollin = ZMQ_POLLIN,
2576 pollout = ZMQ_POLLOUT,
2577 pollerr = ZMQ_POLLERR,
2578 pollpri = ZMQ_POLLPRI
2579 };
2580
operator |(event_flags a,event_flags b)2581 constexpr event_flags operator|(event_flags a, event_flags b) noexcept
2582 {
2583 return detail::enum_bit_or(a, b);
2584 }
operator &(event_flags a,event_flags b)2585 constexpr event_flags operator&(event_flags a, event_flags b) noexcept
2586 {
2587 return detail::enum_bit_and(a, b);
2588 }
operator ^(event_flags a,event_flags b)2589 constexpr event_flags operator^(event_flags a, event_flags b) noexcept
2590 {
2591 return detail::enum_bit_xor(a, b);
2592 }
operator ~(event_flags a)2593 constexpr event_flags operator~(event_flags a) noexcept
2594 {
2595 return detail::enum_bit_not(a);
2596 }
2597
2598 struct no_user_data;
2599
2600 // layout compatible with zmq_poller_event_t
2601 template<class T = no_user_data> struct poller_event
2602 {
2603 socket_ref socket;
2604 ::zmq::fd_t fd;
2605 T *user_data;
2606 event_flags events;
2607 };
2608
2609 template<typename T = no_user_data> class poller_t
2610 {
2611 public:
2612 using event_type = poller_event<T>;
2613
poller_t()2614 poller_t() : poller_ptr(zmq_poller_new())
2615 {
2616 if (!poller_ptr)
2617 throw error_t();
2618 }
2619
2620 template<
2621 typename Dummy = void,
2622 typename =
2623 typename std::enable_if<!std::is_same<T, no_user_data>::value, Dummy>::type>
add(zmq::socket_ref socket,event_flags events,T * user_data)2624 void add(zmq::socket_ref socket, event_flags events, T *user_data)
2625 {
2626 add_impl(socket, events, user_data);
2627 }
2628
add(zmq::socket_ref socket,event_flags events)2629 void add(zmq::socket_ref socket, event_flags events)
2630 {
2631 add_impl(socket, events, nullptr);
2632 }
2633
remove(zmq::socket_ref socket)2634 void remove(zmq::socket_ref socket)
2635 {
2636 if (0 != zmq_poller_remove(poller_ptr.get(), socket.handle())) {
2637 throw error_t();
2638 }
2639 }
2640
modify(zmq::socket_ref socket,event_flags events)2641 void modify(zmq::socket_ref socket, event_flags events)
2642 {
2643 if (0
2644 != zmq_poller_modify(poller_ptr.get(), socket.handle(),
2645 static_cast<short>(events))) {
2646 throw error_t();
2647 }
2648 }
2649
wait_all(std::vector<event_type> & poller_events,const std::chrono::milliseconds timeout)2650 size_t wait_all(std::vector<event_type> &poller_events,
2651 const std::chrono::milliseconds timeout)
2652 {
2653 int rc = zmq_poller_wait_all(
2654 poller_ptr.get(),
2655 reinterpret_cast<zmq_poller_event_t *>(poller_events.data()),
2656 static_cast<int>(poller_events.size()),
2657 static_cast<long>(timeout.count()));
2658 if (rc > 0)
2659 return static_cast<size_t>(rc);
2660
2661 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3)
2662 if (zmq_errno() == EAGAIN)
2663 #else
2664 if (zmq_errno() == ETIMEDOUT)
2665 #endif
2666 return 0;
2667
2668 throw error_t();
2669 }
2670
2671 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 3, 3)
size() const2672 size_t size() const noexcept
2673 {
2674 int rc = zmq_poller_size(const_cast<void *>(poller_ptr.get()));
2675 ZMQ_ASSERT(rc >= 0);
2676 return static_cast<size_t>(std::max(rc, 0));
2677 }
2678 #endif
2679
2680 private:
2681 struct destroy_poller_t
2682 {
operator ()zmq::poller_t::destroy_poller_t2683 void operator()(void *ptr) noexcept
2684 {
2685 int rc = zmq_poller_destroy(&ptr);
2686 ZMQ_ASSERT(rc == 0);
2687 }
2688 };
2689
2690 std::unique_ptr<void, destroy_poller_t> poller_ptr;
2691
add_impl(zmq::socket_ref socket,event_flags events,T * user_data)2692 void add_impl(zmq::socket_ref socket, event_flags events, T *user_data)
2693 {
2694 if (0
2695 != zmq_poller_add(poller_ptr.get(), socket.handle(), user_data,
2696 static_cast<short>(events))) {
2697 throw error_t();
2698 }
2699 }
2700 };
2701 #endif // defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER)
2702
operator <<(std::ostream & os,const message_t & msg)2703 inline std::ostream &operator<<(std::ostream &os, const message_t &msg)
2704 {
2705 return os << msg.str();
2706 }
2707
2708 } // namespace zmq
2709
2710 #endif // __ZMQ_HPP_INCLUDED__
2711