• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

zeromq / cppzmq / 6106326776

07 Sep 2023 06:40AM UTC coverage: 86.965% (+0.7%) from 86.313%
6106326776

Pull #612

github

web-flow
Merge 72730168d into 945d60c36
Pull Request #612: Feature/expose monitor socket for active poller

70 of 70 new or added lines in 1 file covered. (100.0%)

854 of 982 relevant lines covered (86.97%)

23.71 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.74
/zmq.hpp
1
/*
2
    Copyright (c) 2016-2017 ZeroMQ community
3
    Copyright (c) 2009-2011 250bpm s.r.o.
4
    Copyright (c) 2011 Botond Ballo
5
    Copyright (c) 2007-2009 iMatix Corporation
6

7
    Permission is hereby granted, free of charge, to any person obtaining a copy
8
    of this software and associated documentation files (the "Software"), to
9
    deal in the Software without restriction, including without limitation the
10
    rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
11
    sell copies of the Software, and to permit persons to whom the Software is
12
    furnished to do so, subject to the following conditions:
13

14
    The above copyright notice and this permission notice shall be included in
15
    all copies or substantial portions of the Software.
16

17
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23
    IN THE SOFTWARE.
24
*/
25

26
#ifndef __ZMQ_HPP_INCLUDED__
27
#define __ZMQ_HPP_INCLUDED__
28

29
#ifdef _WIN32
30
#ifndef NOMINMAX
31
#define NOMINMAX
32
#endif
33
#endif
34

35
// included here for _HAS_CXX* macros
36
#include <zmq.h>
37

38
#if defined(_MSVC_LANG)
39
#define CPPZMQ_LANG _MSVC_LANG
40
#else
41
#define CPPZMQ_LANG __cplusplus
42
#endif
43
// overwrite if specific language macros indicate higher version
44
#if defined(_HAS_CXX14) && _HAS_CXX14 && CPPZMQ_LANG < 201402L
45
#undef CPPZMQ_LANG
46
#define CPPZMQ_LANG 201402L
47
#endif
48
#if defined(_HAS_CXX17) && _HAS_CXX17 && CPPZMQ_LANG < 201703L
49
#undef CPPZMQ_LANG
50
#define CPPZMQ_LANG 201703L
51
#endif
52

53
// macros defined if has a specific standard or greater
54
#if CPPZMQ_LANG >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900)
55
#define ZMQ_CPP11
56
#endif
57
#if CPPZMQ_LANG >= 201402L
58
#define ZMQ_CPP14
59
#endif
60
#if CPPZMQ_LANG >= 201703L
61
#define ZMQ_CPP17
62
#endif
63

64
#if defined(ZMQ_CPP14) && !defined(_MSC_VER)
65
#define ZMQ_DEPRECATED(msg) [[deprecated(msg)]]
66
#elif defined(_MSC_VER)
67
#define ZMQ_DEPRECATED(msg) __declspec(deprecated(msg))
68
#elif defined(__GNUC__)
69
#define ZMQ_DEPRECATED(msg) __attribute__((deprecated(msg)))
70
#else
71
#define ZMQ_DEPRECATED(msg)
72
#endif
73

74
#if defined(ZMQ_CPP17)
75
#define ZMQ_NODISCARD [[nodiscard]]
76
#else
77
#define ZMQ_NODISCARD
78
#endif
79

80
#if defined(ZMQ_CPP11)
81
#define ZMQ_NOTHROW noexcept
82
#define ZMQ_EXPLICIT explicit
83
#define ZMQ_OVERRIDE override
84
#define ZMQ_NULLPTR nullptr
85
#define ZMQ_CONSTEXPR_FN constexpr
86
#define ZMQ_CONSTEXPR_VAR constexpr
87
#define ZMQ_CPP11_DEPRECATED(msg) ZMQ_DEPRECATED(msg)
88
#else
89
#define ZMQ_NOTHROW throw()
90
#define ZMQ_EXPLICIT
91
#define ZMQ_OVERRIDE
92
#define ZMQ_NULLPTR 0
93
#define ZMQ_CONSTEXPR_FN
94
#define ZMQ_CONSTEXPR_VAR const
95
#define ZMQ_CPP11_DEPRECATED(msg)
96
#endif
97
#if defined(ZMQ_CPP14) && (!defined(_MSC_VER) || _MSC_VER > 1900) && (!defined(__GNUC__) || __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ > 3))
98
#define ZMQ_EXTENDED_CONSTEXPR
99
#endif
100
#if defined(ZMQ_CPP17)
101
#define ZMQ_INLINE_VAR inline
102
#define ZMQ_CONSTEXPR_IF constexpr
103
#else
104
#define ZMQ_INLINE_VAR
105
#define ZMQ_CONSTEXPR_IF
106
#endif
107

108
#include <cassert>
109
#include <cstring>
110

111
#include <algorithm>
112
#include <exception>
113
#include <iomanip>
114
#include <sstream>
115
#include <string>
116
#include <vector>
117
#ifdef ZMQ_CPP11
118
#include <array>
119
#include <chrono>
120
#include <tuple>
121
#include <memory>
122
#endif
123

124
#if defined(__has_include) && defined(ZMQ_CPP17)
125
#define CPPZMQ_HAS_INCLUDE_CPP17(X) __has_include(X)
126
#else
127
#define CPPZMQ_HAS_INCLUDE_CPP17(X) 0
128
#endif
129

130
#if CPPZMQ_HAS_INCLUDE_CPP17(<optional>) && !defined(CPPZMQ_HAS_OPTIONAL)
131
#define CPPZMQ_HAS_OPTIONAL 1
132
#endif
133
#ifndef CPPZMQ_HAS_OPTIONAL
134
#define CPPZMQ_HAS_OPTIONAL 0
135
#elif CPPZMQ_HAS_OPTIONAL
136
#include <optional>
137
#endif
138

139
#if CPPZMQ_HAS_INCLUDE_CPP17(<string_view>) && !defined(CPPZMQ_HAS_STRING_VIEW)
140
#define CPPZMQ_HAS_STRING_VIEW 1
141
#endif
142
#ifndef CPPZMQ_HAS_STRING_VIEW
143
#define CPPZMQ_HAS_STRING_VIEW 0
144
#elif CPPZMQ_HAS_STRING_VIEW
145
#include <string_view>
146
#endif
147

148
/*  Version macros for compile-time API version detection                     */
149
#define CPPZMQ_VERSION_MAJOR 4
150
#define CPPZMQ_VERSION_MINOR 10
151
#define CPPZMQ_VERSION_PATCH 0
152

153
#define CPPZMQ_VERSION                                                              \
154
    ZMQ_MAKE_VERSION(CPPZMQ_VERSION_MAJOR, CPPZMQ_VERSION_MINOR,                    \
155
                     CPPZMQ_VERSION_PATCH)
156

157
//  Detect whether the compiler supports C++11 rvalue references.
158
#if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2))   \
159
     && defined(__GXX_EXPERIMENTAL_CXX0X__))
160
#define ZMQ_HAS_RVALUE_REFS
161
#define ZMQ_DELETED_FUNCTION = delete
162
#elif defined(__clang__)
163
#if __has_feature(cxx_rvalue_references)
164
#define ZMQ_HAS_RVALUE_REFS
165
#endif
166

167
#if __has_feature(cxx_deleted_functions)
168
#define ZMQ_DELETED_FUNCTION = delete
169
#else
170
#define ZMQ_DELETED_FUNCTION
171
#endif
172
#elif defined(_MSC_VER) && (_MSC_VER >= 1900)
173
#define ZMQ_HAS_RVALUE_REFS
174
#define ZMQ_DELETED_FUNCTION = delete
175
#elif defined(_MSC_VER) && (_MSC_VER >= 1600)
176
#define ZMQ_HAS_RVALUE_REFS
177
#define ZMQ_DELETED_FUNCTION
178
#else
179
#define ZMQ_DELETED_FUNCTION
180
#endif
181

182
#if defined(ZMQ_CPP11) && !defined(__llvm__) && !defined(__INTEL_COMPILER)          \
183
  && defined(__GNUC__) && __GNUC__ < 5
184
#define ZMQ_CPP11_PARTIAL
185
#elif defined(__GLIBCXX__) && __GLIBCXX__ < 20160805
186
//the date here is the last date of gcc 4.9.4, which
187
// effectively means libstdc++ from gcc 5.5 and higher won't trigger this branch
188
#define ZMQ_CPP11_PARTIAL
189
#endif
190

191
#ifdef ZMQ_CPP11
192
#ifdef ZMQ_CPP11_PARTIAL
193
#define ZMQ_IS_TRIVIALLY_COPYABLE(T) __has_trivial_copy(T)
194
#else
195
#include <type_traits>
196
#define ZMQ_IS_TRIVIALLY_COPYABLE(T) std::is_trivially_copyable<T>::value
197
#endif
198
#endif
199

200
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3, 3, 0)
201
#define ZMQ_NEW_MONITOR_EVENT_LAYOUT
202
#endif
203

204
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 1, 0)
205
#define ZMQ_HAS_PROXY_STEERABLE
206
/*  Socket event data  */
207
typedef struct
208
{
209
    uint16_t event; // id of the event as bitfield
210
    int32_t value;  // value is either error code, fd or reconnect interval
211
} zmq_event_t;
212
#endif
213

214
// Avoid using deprecated message receive function when possible
215
#if ZMQ_VERSION < ZMQ_MAKE_VERSION(3, 2, 0)
216
#define zmq_msg_recv(msg, socket, flags) zmq_recvmsg(socket, msg, flags)
217
#endif
218

219

220
// In order to prevent unused variable warnings when building in non-debug
221
// mode use this macro to make assertions.
222
#ifndef NDEBUG
223
#define ZMQ_ASSERT(expression) assert(expression)
224
#else
225
#define ZMQ_ASSERT(expression) (void) (expression)
226
#endif
227

228
namespace zmq
229
{
230
#ifdef ZMQ_CPP11
231
namespace detail
232
{
233
namespace ranges
234
{
235
using std::begin;
236
using std::end;
237
template<class T> auto begin(T &&r) -> decltype(begin(std::forward<T>(r)))
238
{
239
    return begin(std::forward<T>(r));
240
}
241
template<class T> auto end(T &&r) -> decltype(end(std::forward<T>(r)))
242
{
243
    return end(std::forward<T>(r));
244
}
245
} // namespace ranges
246

247
template<class T> using void_t = void;
248

249
template<class Iter>
250
using iter_value_t = typename std::iterator_traits<Iter>::value_type;
251

252
template<class Range>
253
using range_iter_t = decltype(
254
  ranges::begin(std::declval<typename std::remove_reference<Range>::type &>()));
255

256
template<class Range> using range_value_t = iter_value_t<range_iter_t<Range>>;
257

258
template<class T, class = void> struct is_range : std::false_type
259
{
260
};
261

262
template<class T>
263
struct is_range<
264
  T,
265
  void_t<decltype(
266
    ranges::begin(std::declval<typename std::remove_reference<T>::type &>())
267
    == ranges::end(std::declval<typename std::remove_reference<T>::type &>()))>>
268
    : std::true_type
269
{
270
};
271

272
} // namespace detail
273
#endif
274

275
typedef zmq_free_fn free_fn;
276
typedef zmq_pollitem_t pollitem_t;
277

278
// duplicate definition from libzmq 4.3.3
279
#if defined _WIN32
280
#if defined _WIN64
281
typedef unsigned __int64 fd_t;
282
#else
283
typedef unsigned int fd_t;
284
#endif
285
#else
286
typedef int fd_t;
287
#endif
288

289
class error_t : public std::exception
290
{
291
  public:
292
    error_t() ZMQ_NOTHROW : errnum(zmq_errno()) {}
34✔
293
    explicit error_t(int err) ZMQ_NOTHROW : errnum(err) {}
1✔
294
    virtual const char *what() const ZMQ_NOTHROW ZMQ_OVERRIDE
6✔
295
    {
296
        return zmq_strerror(errnum);
6✔
297
    }
298
    int num() const ZMQ_NOTHROW { return errnum; }
9✔
299

300
  private:
301
    int errnum;
302
};
303

304
namespace detail {
305
inline int poll(zmq_pollitem_t *items_, size_t nitems_, long timeout_)
26✔
306
{
307
    int rc = zmq_poll(items_, static_cast<int>(nitems_), timeout_);
26✔
308
    if (rc < 0)
26✔
309
        throw error_t();
×
310
    return rc;
26✔
311
}
312
}
313

314
#ifdef ZMQ_CPP11
315
ZMQ_DEPRECATED("from 4.8.0, use poll taking std::chrono::duration instead of long")
316
inline int poll(zmq_pollitem_t *items_, size_t nitems_, long timeout_)
317
#else
318
inline int poll(zmq_pollitem_t *items_, size_t nitems_, long timeout_ = -1)
319
#endif
320
{
321
    return detail::poll(items_, nitems_, timeout_);
322
}
323

324
ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items")
325
inline int poll(zmq_pollitem_t const *items_, size_t nitems_, long timeout_ = -1)
326
{
327
    return detail::poll(const_cast<zmq_pollitem_t *>(items_), nitems_, timeout_);
328
}
329

330
#ifdef ZMQ_CPP11
331
ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items")
332
inline int
333
poll(zmq_pollitem_t const *items, size_t nitems, std::chrono::milliseconds timeout)
334
{
335
    return detail::poll(const_cast<zmq_pollitem_t *>(items), nitems,
336
                static_cast<long>(timeout.count()));
337
}
338

339
ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items")
340
inline int poll(std::vector<zmq_pollitem_t> const &items,
341
                std::chrono::milliseconds timeout)
342
{
343
    return detail::poll(const_cast<zmq_pollitem_t *>(items.data()), items.size(),
344
                static_cast<long>(timeout.count()));
345
}
346

347
ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items")
348
inline int poll(std::vector<zmq_pollitem_t> const &items, long timeout_ = -1)
349
{
350
    return detail::poll(const_cast<zmq_pollitem_t *>(items.data()), items.size(), timeout_);
351
}
352

353
inline int
354
poll(zmq_pollitem_t *items, size_t nitems, std::chrono::milliseconds timeout = std::chrono::milliseconds{-1})
20✔
355
{
356
    return detail::poll(items, nitems, static_cast<long>(timeout.count()));
26✔
357
}
358

359
inline int poll(std::vector<zmq_pollitem_t> &items,
360
                std::chrono::milliseconds timeout = std::chrono::milliseconds{-1})
361
{
362
    return detail::poll(items.data(), items.size(), static_cast<long>(timeout.count()));
363
}
364

365
ZMQ_DEPRECATED("from 4.3.1, use poll taking std::chrono::duration instead of long")
366
inline int poll(std::vector<zmq_pollitem_t> &items, long timeout_)
367
{
368
    return detail::poll(items.data(), items.size(), timeout_);
369
}
370

371
template<std::size_t SIZE>
372
inline int poll(std::array<zmq_pollitem_t, SIZE> &items,
373
                std::chrono::milliseconds timeout = std::chrono::milliseconds{-1})
374
{
375
    return detail::poll(items.data(), items.size(), static_cast<long>(timeout.count()));
376
}
377
#endif
378

379

380
inline void version(int *major_, int *minor_, int *patch_)
381
{
382
    zmq_version(major_, minor_, patch_);
383
}
384

385
#ifdef ZMQ_CPP11
386
inline std::tuple<int, int, int> version()
387
{
388
    std::tuple<int, int, int> v;
389
    zmq_version(&std::get<0>(v), &std::get<1>(v), &std::get<2>(v));
390
    return v;
391
}
392

393
#if !defined(ZMQ_CPP11_PARTIAL)
394
namespace detail
395
{
396
template<class T> struct is_char_type
397
{
398
    // true if character type for string literals in C++11
399
    static constexpr bool value =
400
      std::is_same<T, char>::value || std::is_same<T, wchar_t>::value
401
      || std::is_same<T, char16_t>::value || std::is_same<T, char32_t>::value;
402
};
403
}
404
#endif
405

406
#endif
407

408
class message_t
409
{
410
  public:
411
    message_t() ZMQ_NOTHROW
78✔
412
    {
78✔
413
        int rc = zmq_msg_init(&msg);
78✔
414
        ZMQ_ASSERT(rc == 0);
78✔
415
    }
78✔
416

417
    explicit message_t(size_t size_)
25✔
418
    {
25✔
419
        int rc = zmq_msg_init_size(&msg, size_);
25✔
420
        if (rc != 0)
25✔
421
            throw error_t();
×
422
    }
25✔
423

424
    template<class ForwardIter> message_t(ForwardIter first, ForwardIter last)
4✔
425
    {
426
        typedef typename std::iterator_traits<ForwardIter>::value_type value_t;
427

428
        assert(std::distance(first, last) >= 0);
4✔
429
        size_t const size_ =
4✔
430
          static_cast<size_t>(std::distance(first, last)) * sizeof(value_t);
4✔
431
        int const rc = zmq_msg_init_size(&msg, size_);
4✔
432
        if (rc != 0)
4✔
433
            throw error_t();
×
434
        std::copy(first, last, data<value_t>());
4✔
435
    }
4✔
436

437
    message_t(const void *data_, size_t size_)
99✔
438
    {
99✔
439
        int rc = zmq_msg_init_size(&msg, size_);
99✔
440
        if (rc != 0)
99✔
441
            throw error_t();
×
442
        if (size_) {
99✔
443
            // this constructor allows (nullptr, 0),
444
            // memcpy with a null pointer is UB
445
            memcpy(data(), data_, size_);
99✔
446
        }
447
    }
99✔
448

449
    message_t(void *data_, size_t size_, free_fn *ffn_, void *hint_ = ZMQ_NULLPTR)
450
    {
451
        int rc = zmq_msg_init_data(&msg, data_, size_, ffn_, hint_);
452
        if (rc != 0)
453
            throw error_t();
454
    }
455

456
    // overload set of string-like types and generic containers
457
#if defined(ZMQ_CPP11) && !defined(ZMQ_CPP11_PARTIAL)
458
    // NOTE this constructor will include the null terminator
459
    // when called with a string literal.
460
    // An overload taking const char* can not be added because
461
    // it would be preferred over this function and break compatiblity.
462
    template<
463
      class Char,
464
      size_t N,
465
      typename = typename std::enable_if<detail::is_char_type<Char>::value>::type>
466
    ZMQ_DEPRECATED("from 4.7.0, use constructors taking iterators, (pointer, size) "
467
                   "or strings instead")
468
    explicit message_t(const Char (&data)[N]) :
2✔
469
        message_t(detail::ranges::begin(data), detail::ranges::end(data))
2✔
470
    {
471
    }
2✔
472

473
    template<class Range,
474
             typename = typename std::enable_if<
475
               detail::is_range<Range>::value
476
               && ZMQ_IS_TRIVIALLY_COPYABLE(detail::range_value_t<Range>)
477
               && !detail::is_char_type<detail::range_value_t<Range>>::value
478
               && !std::is_same<Range, message_t>::value>::type>
479
    explicit message_t(const Range &rng) :
1✔
480
        message_t(detail::ranges::begin(rng), detail::ranges::end(rng))
1✔
481
    {
482
    }
1✔
483

484
    explicit message_t(const std::string &str) : message_t(str.data(), str.size()) {}
35✔
485

486
#if CPPZMQ_HAS_STRING_VIEW
487
    explicit message_t(std::string_view str) : message_t(str.data(), str.size()) {}
1✔
488
#endif
489

490
#endif
491

492
#ifdef ZMQ_HAS_RVALUE_REFS
493
    message_t(message_t &&rhs) ZMQ_NOTHROW : msg(rhs.msg)
97✔
494
    {
495
        int rc = zmq_msg_init(&rhs.msg);
97✔
496
        ZMQ_ASSERT(rc == 0);
97✔
497
    }
97✔
498

499
    message_t &operator=(message_t &&rhs) ZMQ_NOTHROW
12✔
500
    {
501
        std::swap(msg, rhs.msg);
12✔
502
        return *this;
12✔
503
    }
504
#endif
505

506
    ~message_t() ZMQ_NOTHROW
303✔
507
    {
303✔
508
        int rc = zmq_msg_close(&msg);
303✔
509
        ZMQ_ASSERT(rc == 0);
303✔
510
    }
303✔
511

512
    void rebuild()
513
    {
514
        int rc = zmq_msg_close(&msg);
515
        if (rc != 0)
516
            throw error_t();
517
        rc = zmq_msg_init(&msg);
518
        ZMQ_ASSERT(rc == 0);
519
    }
520

521
    void rebuild(size_t size_)
522
    {
523
        int rc = zmq_msg_close(&msg);
524
        if (rc != 0)
525
            throw error_t();
526
        rc = zmq_msg_init_size(&msg, size_);
527
        if (rc != 0)
528
            throw error_t();
529
    }
530

531
    void rebuild(const void *data_, size_t size_)
532
    {
533
        int rc = zmq_msg_close(&msg);
534
        if (rc != 0)
535
            throw error_t();
536
        rc = zmq_msg_init_size(&msg, size_);
537
        if (rc != 0)
538
            throw error_t();
539
        memcpy(data(), data_, size_);
540
    }
541
    
542
    void rebuild(const std::string &str)
543
    {
544
        rebuild(str.data(), str.size());
545
    }
546

547
    void rebuild(void *data_, size_t size_, free_fn *ffn_, void *hint_ = ZMQ_NULLPTR)
548
    {
549
        int rc = zmq_msg_close(&msg);
550
        if (rc != 0)
551
            throw error_t();
552
        rc = zmq_msg_init_data(&msg, data_, size_, ffn_, hint_);
553
        if (rc != 0)
554
            throw error_t();
555
    }
556

557
    ZMQ_DEPRECATED("from 4.3.1, use move taking non-const reference instead")
558
    void move(message_t const *msg_)
559
    {
560
        int rc = zmq_msg_move(&msg, const_cast<zmq_msg_t *>(msg_->handle()));
561
        if (rc != 0)
562
            throw error_t();
563
    }
564

565
    void move(message_t &msg_)
1✔
566
    {
567
        int rc = zmq_msg_move(&msg, msg_.handle());
1✔
568
        if (rc != 0)
1✔
569
            throw error_t();
×
570
    }
1✔
571

572
    ZMQ_DEPRECATED("from 4.3.1, use copy taking non-const reference instead")
573
    void copy(message_t const *msg_)
574
    {
575
        int rc = zmq_msg_copy(&msg, const_cast<zmq_msg_t *>(msg_->handle()));
576
        if (rc != 0)
577
            throw error_t();
578
    }
579

580
    void copy(message_t &msg_)
1✔
581
    {
582
        int rc = zmq_msg_copy(&msg, msg_.handle());
1✔
583
        if (rc != 0)
1✔
584
            throw error_t();
×
585
    }
1✔
586

587
    bool more() const ZMQ_NOTHROW
25✔
588
    {
589
        int rc = zmq_msg_more(const_cast<zmq_msg_t *>(&msg));
25✔
590
        return rc != 0;
25✔
591
    }
592

593
    void *data() ZMQ_NOTHROW { return zmq_msg_data(&msg); }
175✔
594

595
    const void *data() const ZMQ_NOTHROW
67✔
596
    {
597
        return zmq_msg_data(const_cast<zmq_msg_t *>(&msg));
67✔
598
    }
599

600
    size_t size() const ZMQ_NOTHROW
191✔
601
    {
602
        return zmq_msg_size(const_cast<zmq_msg_t *>(&msg));
191✔
603
    }
604

605
    ZMQ_NODISCARD bool empty() const ZMQ_NOTHROW { return size() == 0u; }
3✔
606

607
    template<typename T> T *data() ZMQ_NOTHROW { return static_cast<T *>(data()); }
63✔
608

609
    template<typename T> T const *data() const ZMQ_NOTHROW
12✔
610
    {
611
        return static_cast<T const *>(data());
12✔
612
    }
613

614
    ZMQ_DEPRECATED("from 4.3.0, use operator== instead")
615
    bool equal(const message_t *other) const ZMQ_NOTHROW { return *this == *other; }
616

617
    bool operator==(const message_t &other) const ZMQ_NOTHROW
15✔
618
    {
619
        const size_t my_size = size();
15✔
620
        return my_size == other.size() && 0 == memcmp(data(), other.data(), my_size);
15✔
621
    }
622

623
    bool operator!=(const message_t &other) const ZMQ_NOTHROW
12✔
624
    {
625
        return !(*this == other);
12✔
626
    }
627

628
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3, 2, 0)
629
    int get(int property_)
5✔
630
    {
631
        int value = zmq_msg_get(&msg, property_);
5✔
632
        if (value == -1)
5✔
633
            throw error_t();
×
634
        return value;
5✔
635
    }
636
#endif
637

638
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 1, 0)
639
    const char *gets(const char *property_)
640
    {
641
        const char *value = zmq_msg_gets(&msg, property_);
642
        if (value == ZMQ_NULLPTR)
643
            throw error_t();
644
        return value;
645
    }
646
#endif
647

648
#if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 0)
649
    uint32_t routing_id() const
1✔
650
    {
651
        return zmq_msg_routing_id(const_cast<zmq_msg_t *>(&msg));
1✔
652
    }
653

654
    void set_routing_id(uint32_t routing_id)
1✔
655
    {
656
        int rc = zmq_msg_set_routing_id(&msg, routing_id);
1✔
657
        if (rc != 0)
1✔
658
            throw error_t();
×
659
    }
1✔
660

661
    const char *group() const
1✔
662
    {
663
        return zmq_msg_group(const_cast<zmq_msg_t *>(&msg));
1✔
664
    }
665

666
    void set_group(const char *group)
1✔
667
    {
668
        int rc = zmq_msg_set_group(&msg, group);
1✔
669
        if (rc != 0)
1✔
670
            throw error_t();
×
671
    }
1✔
672
#endif
673

674
    // interpret message content as a string
675
    std::string to_string() const
13✔
676
    {
677
        return std::string(static_cast<const char *>(data()), size());
13✔
678
    }
679
#if CPPZMQ_HAS_STRING_VIEW
680
    // interpret message content as a string
681
    std::string_view to_string_view() const noexcept
2✔
682
    {
683
        return std::string_view(static_cast<const char *>(data()), size());
2✔
684
    }
685
#endif
686

687
    /** Dump content to string for debugging.
688
    *   Ascii chars are readable, the rest is printed as hex.
689
    *   Probably ridiculously slow.
690
    *   Use to_string() or to_string_view() for
691
    *   interpreting the message as a string.
692
    */
693
    std::string str() const
×
694
    {
695
        // Partly mutuated from the same method in zmq::multipart_t
696
        std::stringstream os;
×
697

698
        const unsigned char *msg_data = this->data<unsigned char>();
×
699
        unsigned char byte;
700
        size_t size = this->size();
×
701
        int is_ascii[2] = {0, 0};
×
702

703
        os << "zmq::message_t [size " << std::dec << std::setw(3)
×
704
           << std::setfill('0') << size << "] (";
×
705
        // Totally arbitrary
706
        if (size >= 1000) {
×
707
            os << "... too big to print)";
×
708
        } else {
709
            while (size--) {
×
710
                byte = *msg_data++;
×
711

712
                is_ascii[1] = (byte >= 32 && byte < 127);
×
713
                if (is_ascii[1] != is_ascii[0])
×
714
                    os << " "; // Separate text/non text
×
715

716
                if (is_ascii[1]) {
×
717
                    os << byte;
×
718
                } else {
719
                    os << std::hex << std::uppercase << std::setw(2)
×
720
                       << std::setfill('0') << static_cast<short>(byte);
×
721
                }
722
                is_ascii[0] = is_ascii[1];
×
723
            }
724
            os << ")";
×
725
        }
726
        return os.str();
×
727
    }
728

729
    void swap(message_t &other) ZMQ_NOTHROW
2✔
730
    {
731
        // this assumes zmq::msg_t from libzmq is trivially relocatable
732
        std::swap(msg, other.msg);
2✔
733
    }
2✔
734

735
    ZMQ_NODISCARD zmq_msg_t *handle() ZMQ_NOTHROW { return &msg; }
112✔
736
    ZMQ_NODISCARD const zmq_msg_t *handle() const ZMQ_NOTHROW { return &msg; }
737

738
  private:
739
    //  The underlying message
740
    zmq_msg_t msg;
741

742
    //  Disable implicit message copying, so that users won't use shared
743
    //  messages (less efficient) without being aware of the fact.
744
    message_t(const message_t &) ZMQ_DELETED_FUNCTION;
745
    void operator=(const message_t &) ZMQ_DELETED_FUNCTION;
746
};
747

748
inline void swap(message_t &a, message_t &b) ZMQ_NOTHROW
2✔
749
{
750
    a.swap(b);
2✔
751
}
2✔
752

753
#ifdef ZMQ_CPP11
754
enum class ctxopt
755
{
756
#ifdef ZMQ_BLOCKY
757
    blocky = ZMQ_BLOCKY,
758
#endif
759
#ifdef ZMQ_IO_THREADS
760
    io_threads = ZMQ_IO_THREADS,
761
#endif
762
#ifdef ZMQ_THREAD_SCHED_POLICY
763
    thread_sched_policy = ZMQ_THREAD_SCHED_POLICY,
764
#endif
765
#ifdef ZMQ_THREAD_PRIORITY
766
    thread_priority = ZMQ_THREAD_PRIORITY,
767
#endif
768
#ifdef ZMQ_THREAD_AFFINITY_CPU_ADD
769
    thread_affinity_cpu_add = ZMQ_THREAD_AFFINITY_CPU_ADD,
770
#endif
771
#ifdef ZMQ_THREAD_AFFINITY_CPU_REMOVE
772
    thread_affinity_cpu_remove = ZMQ_THREAD_AFFINITY_CPU_REMOVE,
773
#endif
774
#ifdef ZMQ_THREAD_NAME_PREFIX
775
    thread_name_prefix = ZMQ_THREAD_NAME_PREFIX,
776
#endif
777
#ifdef ZMQ_MAX_MSGSZ
778
    max_msgsz = ZMQ_MAX_MSGSZ,
779
#endif
780
#ifdef ZMQ_ZERO_COPY_RECV
781
    zero_copy_recv = ZMQ_ZERO_COPY_RECV,
782
#endif
783
#ifdef ZMQ_MAX_SOCKETS
784
    max_sockets = ZMQ_MAX_SOCKETS,
785
#endif
786
#ifdef ZMQ_SOCKET_LIMIT
787
    socket_limit = ZMQ_SOCKET_LIMIT,
788
#endif
789
#ifdef ZMQ_IPV6
790
    ipv6 = ZMQ_IPV6,
791
#endif
792
#ifdef ZMQ_MSG_T_SIZE
793
    msg_t_size = ZMQ_MSG_T_SIZE
794
#endif
795
};
796
#endif
797

798
class context_t
799
{
800
  public:
801
    context_t()
104✔
802
    {
104✔
803
        ptr = zmq_ctx_new();
104✔
804
        if (ptr == ZMQ_NULLPTR)
104✔
805
            throw error_t();
×
806
    }
104✔
807

808

809
    explicit context_t(int io_threads_, int max_sockets_ = ZMQ_MAX_SOCKETS_DFLT)
22✔
810
    {
22✔
811
        ptr = zmq_ctx_new();
22✔
812
        if (ptr == ZMQ_NULLPTR)
22✔
813
            throw error_t();
×
814

815
        int rc = zmq_ctx_set(ptr, ZMQ_IO_THREADS, io_threads_);
22✔
816
        ZMQ_ASSERT(rc == 0);
22✔
817

818
        rc = zmq_ctx_set(ptr, ZMQ_MAX_SOCKETS, max_sockets_);
22✔
819
        ZMQ_ASSERT(rc == 0);
22✔
820
    }
22✔
821

822
#ifdef ZMQ_HAS_RVALUE_REFS
823
    context_t(context_t &&rhs) ZMQ_NOTHROW : ptr(rhs.ptr) { rhs.ptr = ZMQ_NULLPTR; }
50✔
824
    context_t &operator=(context_t &&rhs) ZMQ_NOTHROW
825
    {
826
        close();
827
        std::swap(ptr, rhs.ptr);
828
        return *this;
829
    }
830
#endif
831

832
    ~context_t() ZMQ_NOTHROW { close(); }
176✔
833

834
    ZMQ_CPP11_DEPRECATED("from 4.7.0, use set taking zmq::ctxopt instead")
835
    int setctxopt(int option_, int optval_)
836
    {
837
        int rc = zmq_ctx_set(ptr, option_, optval_);
838
        ZMQ_ASSERT(rc == 0);
839
        return rc;
840
    }
841

842
    ZMQ_CPP11_DEPRECATED("from 4.7.0, use get taking zmq::ctxopt instead")
843
    int getctxopt(int option_) { return zmq_ctx_get(ptr, option_); }
844

845
#ifdef ZMQ_CPP11
846
    void set(ctxopt option, int optval)
3✔
847
    {
848
        int rc = zmq_ctx_set(ptr, static_cast<int>(option), optval);
3✔
849
        if (rc == -1)
3✔
850
            throw error_t();
1✔
851
    }
2✔
852

853
    ZMQ_NODISCARD int get(ctxopt option)
2✔
854
    {
855
        int rc = zmq_ctx_get(ptr, static_cast<int>(option));
2✔
856
        // some options have a default value of -1
857
        // which is unfortunate, and may result in errors
858
        // that don't make sense
859
        if (rc == -1)
2✔
860
            throw error_t();
1✔
861
        return rc;
1✔
862
    }
863
#endif
864

865
    // Terminates context (see also shutdown()).
866
    void close() ZMQ_NOTHROW
181✔
867
    {
868
        if (ptr == ZMQ_NULLPTR)
181✔
869
            return;
55✔
870

871
        int rc;
872
        do {
×
873
            rc = zmq_ctx_term(ptr);
126✔
874
        } while (rc == -1 && errno == EINTR);
126✔
875

876
        ZMQ_ASSERT(rc == 0);
126✔
877
        ptr = ZMQ_NULLPTR;
126✔
878
    }
879

880
    // Shutdown context in preparation for termination (close()).
881
    // Causes all blocking socket operations and any further
882
    // socket operations to return with ETERM.
883
    void shutdown() ZMQ_NOTHROW
4✔
884
    {
885
        if (ptr == ZMQ_NULLPTR)
4✔
886
            return;
×
887
        int rc = zmq_ctx_shutdown(ptr);
4✔
888
        ZMQ_ASSERT(rc == 0);
4✔
889
    }
890

891
    //  Be careful with this, it's probably only useful for
892
    //  using the C api together with an existing C++ api.
893
    //  Normally you should never need to use this.
894
    ZMQ_EXPLICIT operator void *() ZMQ_NOTHROW { return ptr; }
895

896
    ZMQ_EXPLICIT operator void const *() const ZMQ_NOTHROW { return ptr; }
897

898
    ZMQ_NODISCARD void *handle() ZMQ_NOTHROW { return ptr; }
407✔
899

900
    ZMQ_DEPRECATED("from 4.7.0, use handle() != nullptr instead")
901
    operator bool() const ZMQ_NOTHROW { return ptr != ZMQ_NULLPTR; }
902

903
    void swap(context_t &other) ZMQ_NOTHROW { std::swap(ptr, other.ptr); }
1✔
904

905
  private:
906
    void *ptr;
907

908
    context_t(const context_t &) ZMQ_DELETED_FUNCTION;
909
    void operator=(const context_t &) ZMQ_DELETED_FUNCTION;
910
};
911

912
inline void swap(context_t &a, context_t &b) ZMQ_NOTHROW
1✔
913
{
914
    a.swap(b);
1✔
915
}
1✔
916

917
#ifdef ZMQ_CPP11
918

919
struct recv_buffer_size
920
{
921
    size_t size;             // number of bytes written to buffer
922
    size_t untruncated_size; // untruncated message size in bytes
923

924
    ZMQ_NODISCARD bool truncated() const noexcept
3✔
925
    {
926
        return size != untruncated_size;
3✔
927
    }
928
};
929

930
#if CPPZMQ_HAS_OPTIONAL
931

932
using send_result_t = std::optional<size_t>;
933
using recv_result_t = std::optional<size_t>;
934
using recv_buffer_result_t = std::optional<recv_buffer_size>;
935

936
#else
937

938
namespace detail
939
{
940
// A C++11 type emulating the most basic
941
// operations of std::optional for trivial types
942
template<class T> class trivial_optional
943
{
944
  public:
945
    static_assert(std::is_trivial<T>::value, "T must be trivial");
946
    using value_type = T;
947

948
    trivial_optional() = default;
949
    trivial_optional(T value) noexcept : _value(value), _has_value(true) {}
950

951
    const T *operator->() const noexcept
952
    {
953
        assert(_has_value);
954
        return &_value;
955
    }
956
    T *operator->() noexcept
957
    {
958
        assert(_has_value);
959
        return &_value;
960
    }
961

962
    const T &operator*() const noexcept
963
    {
964
        assert(_has_value);
965
        return _value;
966
    }
967
    T &operator*() noexcept
968
    {
969
        assert(_has_value);
970
        return _value;
971
    }
972

973
    T &value()
974
    {
975
        if (!_has_value)
976
            throw std::exception();
977
        return _value;
978
    }
979
    const T &value() const
980
    {
981
        if (!_has_value)
982
            throw std::exception();
983
        return _value;
984
    }
985

986
    explicit operator bool() const noexcept { return _has_value; }
987
    bool has_value() const noexcept { return _has_value; }
988

989
  private:
990
    T _value{};
991
    bool _has_value{false};
992
};
993
} // namespace detail
994

995
using send_result_t = detail::trivial_optional<size_t>;
996
using recv_result_t = detail::trivial_optional<size_t>;
997
using recv_buffer_result_t = detail::trivial_optional<recv_buffer_size>;
998

999
#endif
1000

1001
namespace detail
1002
{
1003
template<class T> constexpr T enum_bit_or(T a, T b) noexcept
28✔
1004
{
1005
    static_assert(std::is_enum<T>::value, "must be enum");
1006
    using U = typename std::underlying_type<T>::type;
1007
    return static_cast<T>(static_cast<U>(a) | static_cast<U>(b));
28✔
1008
}
1009
template<class T> constexpr T enum_bit_and(T a, T b) noexcept
7✔
1010
{
1011
    static_assert(std::is_enum<T>::value, "must be enum");
1012
    using U = typename std::underlying_type<T>::type;
1013
    return static_cast<T>(static_cast<U>(a) & static_cast<U>(b));
7✔
1014
}
1015
template<class T> constexpr T enum_bit_xor(T a, T b) noexcept
3✔
1016
{
1017
    static_assert(std::is_enum<T>::value, "must be enum");
1018
    using U = typename std::underlying_type<T>::type;
1019
    return static_cast<T>(static_cast<U>(a) ^ static_cast<U>(b));
3✔
1020
}
1021
template<class T> constexpr T enum_bit_not(T a) noexcept
4✔
1022
{
1023
    static_assert(std::is_enum<T>::value, "must be enum");
1024
    using U = typename std::underlying_type<T>::type;
1025
    return static_cast<T>(~static_cast<U>(a));
4✔
1026
}
1027
} // namespace detail
1028

1029
// partially satisfies named requirement BitmaskType
1030
enum class send_flags : int
1031
{
1032
    none = 0,
1033
    dontwait = ZMQ_DONTWAIT,
1034
    sndmore = ZMQ_SNDMORE
1035
};
1036

1037
constexpr send_flags operator|(send_flags a, send_flags b) noexcept
19✔
1038
{
1039
    return detail::enum_bit_or(a, b);
19✔
1040
}
1041
constexpr send_flags operator&(send_flags a, send_flags b) noexcept
1✔
1042
{
1043
    return detail::enum_bit_and(a, b);
1✔
1044
}
1045
constexpr send_flags operator^(send_flags a, send_flags b) noexcept
1✔
1046
{
1047
    return detail::enum_bit_xor(a, b);
1✔
1048
}
1049
constexpr send_flags operator~(send_flags a) noexcept
1✔
1050
{
1051
    return detail::enum_bit_not(a);
1✔
1052
}
1053

1054
// partially satisfies named requirement BitmaskType
1055
enum class recv_flags : int
1056
{
1057
    none = 0,
1058
    dontwait = ZMQ_DONTWAIT
1059
};
1060

1061
constexpr recv_flags operator|(recv_flags a, recv_flags b) noexcept
1✔
1062
{
1063
    return detail::enum_bit_or(a, b);
1✔
1064
}
1065
constexpr recv_flags operator&(recv_flags a, recv_flags b) noexcept
1✔
1066
{
1067
    return detail::enum_bit_and(a, b);
1✔
1068
}
1069
constexpr recv_flags operator^(recv_flags a, recv_flags b) noexcept
1✔
1070
{
1071
    return detail::enum_bit_xor(a, b);
1✔
1072
}
1073
constexpr recv_flags operator~(recv_flags a) noexcept
1✔
1074
{
1075
    return detail::enum_bit_not(a);
1✔
1076
}
1077

1078

1079
// mutable_buffer, const_buffer and buffer are based on
1080
// the Networking TS specification, draft:
1081
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/n4771.pdf
1082

1083
class mutable_buffer
1084
{
1085
  public:
1086
    constexpr mutable_buffer() noexcept : _data(nullptr), _size(0) {}
1087
    constexpr mutable_buffer(void *p, size_t n) noexcept : _data(p), _size(n)
92✔
1088
    {
1089
#ifdef ZMQ_EXTENDED_CONSTEXPR
1090
        assert(p != nullptr || n == 0);
92✔
1091
#endif
1092
    }
92✔
1093

1094
    constexpr void *data() const noexcept { return _data; }
106✔
1095
    constexpr size_t size() const noexcept { return _size; }
115✔
1096
    mutable_buffer &operator+=(size_t n) noexcept
1✔
1097
    {
1098
        // (std::min) is a workaround for when a min macro is defined
1099
        const auto shift = (std::min)(n, _size);
1✔
1100
        _data = static_cast<char *>(_data) + shift;
1✔
1101
        _size -= shift;
1✔
1102
        return *this;
1✔
1103
    }
1104

1105
  private:
1106
    void *_data;
1107
    size_t _size;
1108
};
1109

1110
inline mutable_buffer operator+(const mutable_buffer &mb, size_t n) noexcept
2✔
1111
{
1112
    return mutable_buffer(static_cast<char *>(mb.data()) + (std::min)(n, mb.size()),
2✔
1113
                          mb.size() - (std::min)(n, mb.size()));
4✔
1114
}
1115
inline mutable_buffer operator+(size_t n, const mutable_buffer &mb) noexcept
1✔
1116
{
1117
    return mb + n;
1✔
1118
}
1119

1120
class const_buffer
1121
{
1122
  public:
1123
    constexpr const_buffer() noexcept : _data(nullptr), _size(0) {}
1124
    constexpr const_buffer(const void *p, size_t n) noexcept : _data(p), _size(n)
42✔
1125
    {
1126
#ifdef ZMQ_EXTENDED_CONSTEXPR
1127
        assert(p != nullptr || n == 0);
42✔
1128
#endif
1129
    }
42✔
1130
    constexpr const_buffer(const mutable_buffer &mb) noexcept :
15✔
1131
        _data(mb.data()), _size(mb.size())
15✔
1132
    {
1133
    }
15✔
1134

1135
    constexpr const void *data() const noexcept { return _data; }
79✔
1136
    constexpr size_t size() const noexcept { return _size; }
91✔
1137
    const_buffer &operator+=(size_t n) noexcept
1✔
1138
    {
1139
        const auto shift = (std::min)(n, _size);
1✔
1140
        _data = static_cast<const char *>(_data) + shift;
1✔
1141
        _size -= shift;
1✔
1142
        return *this;
1✔
1143
    }
1144

1145
  private:
1146
    const void *_data;
1147
    size_t _size;
1148
};
1149

1150
inline const_buffer operator+(const const_buffer &cb, size_t n) noexcept
2✔
1151
{
1152
    return const_buffer(static_cast<const char *>(cb.data())
6✔
1153
                          + (std::min)(n, cb.size()),
2✔
1154
                        cb.size() - (std::min)(n, cb.size()));
4✔
1155
}
1156
inline const_buffer operator+(size_t n, const const_buffer &cb) noexcept
1✔
1157
{
1158
    return cb + n;
1✔
1159
}
1160

1161
// buffer creation
1162

1163
constexpr mutable_buffer buffer(void *p, size_t n) noexcept
83✔
1164
{
1165
    return mutable_buffer(p, n);
83✔
1166
}
1167
constexpr const_buffer buffer(const void *p, size_t n) noexcept
17✔
1168
{
1169
    return const_buffer(p, n);
17✔
1170
}
1171
constexpr mutable_buffer buffer(const mutable_buffer &mb) noexcept
1✔
1172
{
1173
    return mb;
1✔
1174
}
1175
inline mutable_buffer buffer(const mutable_buffer &mb, size_t n) noexcept
2✔
1176
{
1177
    return mutable_buffer(mb.data(), (std::min)(mb.size(), n));
2✔
1178
}
1179
constexpr const_buffer buffer(const const_buffer &cb) noexcept
1✔
1180
{
1181
    return cb;
1✔
1182
}
1183
inline const_buffer buffer(const const_buffer &cb, size_t n) noexcept
2✔
1184
{
1185
    return const_buffer(cb.data(), (std::min)(cb.size(), n));
2✔
1186
}
1187

1188
namespace detail
1189
{
1190
template<class T> struct is_buffer
1191
{
1192
    static constexpr bool value =
1193
      std::is_same<T, const_buffer>::value || std::is_same<T, mutable_buffer>::value;
1194
};
1195

1196
template<class T> struct is_pod_like
1197
{
1198
    // NOTE: The networking draft N4771 section 16.11 requires
1199
    // T in the buffer functions below to be
1200
    // trivially copyable OR standard layout.
1201
    // Here we decide to be conservative and require both.
1202
    static constexpr bool value =
1203
      ZMQ_IS_TRIVIALLY_COPYABLE(T) && std::is_standard_layout<T>::value;
1204
};
1205

1206
template<class C> constexpr auto seq_size(const C &c) noexcept -> decltype(c.size())
82✔
1207
{
1208
    return c.size();
82✔
1209
}
1210
template<class T, size_t N>
1211
constexpr size_t seq_size(const T (&/*array*/)[N]) noexcept
1212
{
1213
    return N;
1214
}
1215

1216
template<class Seq>
1217
auto buffer_contiguous_sequence(Seq &&seq) noexcept
86✔
1218
  -> decltype(buffer(std::addressof(*std::begin(seq)), size_t{}))
1219
{
1220
    using T = typename std::remove_cv<
1221
      typename std::remove_reference<decltype(*std::begin(seq))>::type>::type;
1222
    static_assert(detail::is_pod_like<T>::value, "T must be POD");
1223

1224
    const auto size = seq_size(seq);
86✔
1225
    return buffer(size != 0u ? std::addressof(*std::begin(seq)) : nullptr,
162✔
1226
                  size * sizeof(T));
86✔
1227
}
1228
template<class Seq>
1229
auto buffer_contiguous_sequence(Seq &&seq, size_t n_bytes) noexcept
11✔
1230
  -> decltype(buffer_contiguous_sequence(seq))
1231
{
1232
    using T = typename std::remove_cv<
1233
      typename std::remove_reference<decltype(*std::begin(seq))>::type>::type;
1234
    static_assert(detail::is_pod_like<T>::value, "T must be POD");
1235

1236
    const auto size = seq_size(seq);
11✔
1237
    return buffer(size != 0u ? std::addressof(*std::begin(seq)) : nullptr,
11✔
1238
                  (std::min)(size * sizeof(T), n_bytes));
22✔
1239
}
1240

1241
} // namespace detail
1242

1243
// C array
1244
template<class T, size_t N> mutable_buffer buffer(T (&data)[N]) noexcept
3✔
1245
{
1246
    return detail::buffer_contiguous_sequence(data);
3✔
1247
}
1248
template<class T, size_t N>
1249
mutable_buffer buffer(T (&data)[N], size_t n_bytes) noexcept
2✔
1250
{
1251
    return detail::buffer_contiguous_sequence(data, n_bytes);
2✔
1252
}
1253
template<class T, size_t N> const_buffer buffer(const T (&data)[N]) noexcept
2✔
1254
{
1255
    return detail::buffer_contiguous_sequence(data);
2✔
1256
}
1257
template<class T, size_t N>
1258
const_buffer buffer(const T (&data)[N], size_t n_bytes) noexcept
1✔
1259
{
1260
    return detail::buffer_contiguous_sequence(data, n_bytes);
1✔
1261
}
1262
// std::array
1263
template<class T, size_t N> mutable_buffer buffer(std::array<T, N> &data) noexcept
2✔
1264
{
1265
    return detail::buffer_contiguous_sequence(data);
2✔
1266
}
1267
template<class T, size_t N>
1268
mutable_buffer buffer(std::array<T, N> &data, size_t n_bytes) noexcept
1✔
1269
{
1270
    return detail::buffer_contiguous_sequence(data, n_bytes);
1✔
1271
}
1272
template<class T, size_t N>
1273
const_buffer buffer(std::array<const T, N> &data) noexcept
1✔
1274
{
1275
    return detail::buffer_contiguous_sequence(data);
1✔
1276
}
1277
template<class T, size_t N>
1278
const_buffer buffer(std::array<const T, N> &data, size_t n_bytes) noexcept
1✔
1279
{
1280
    return detail::buffer_contiguous_sequence(data, n_bytes);
1✔
1281
}
1282
template<class T, size_t N>
1283
const_buffer buffer(const std::array<T, N> &data) noexcept
1✔
1284
{
1285
    return detail::buffer_contiguous_sequence(data);
1✔
1286
}
1287
template<class T, size_t N>
1288
const_buffer buffer(const std::array<T, N> &data, size_t n_bytes) noexcept
1✔
1289
{
1290
    return detail::buffer_contiguous_sequence(data, n_bytes);
1✔
1291
}
1292
// std::vector
1293
template<class T, class Allocator>
1294
mutable_buffer buffer(std::vector<T, Allocator> &data) noexcept
17✔
1295
{
1296
    return detail::buffer_contiguous_sequence(data);
17✔
1297
}
1298
template<class T, class Allocator>
1299
mutable_buffer buffer(std::vector<T, Allocator> &data, size_t n_bytes) noexcept
1✔
1300
{
1301
    return detail::buffer_contiguous_sequence(data, n_bytes);
1✔
1302
}
1303
template<class T, class Allocator>
1304
const_buffer buffer(const std::vector<T, Allocator> &data) noexcept
2✔
1305
{
1306
    return detail::buffer_contiguous_sequence(data);
2✔
1307
}
1308
template<class T, class Allocator>
1309
const_buffer buffer(const std::vector<T, Allocator> &data, size_t n_bytes) noexcept
1✔
1310
{
1311
    return detail::buffer_contiguous_sequence(data, n_bytes);
1✔
1312
}
1313
// std::basic_string
1314
template<class T, class Traits, class Allocator>
1315
mutable_buffer buffer(std::basic_string<T, Traits, Allocator> &data) noexcept
55✔
1316
{
1317
    return detail::buffer_contiguous_sequence(data);
55✔
1318
}
1319
template<class T, class Traits, class Allocator>
1320
mutable_buffer buffer(std::basic_string<T, Traits, Allocator> &data,
1✔
1321
                      size_t n_bytes) noexcept
1322
{
1323
    return detail::buffer_contiguous_sequence(data, n_bytes);
1✔
1324
}
1325
template<class T, class Traits, class Allocator>
1326
const_buffer buffer(const std::basic_string<T, Traits, Allocator> &data) noexcept
2✔
1327
{
1328
    return detail::buffer_contiguous_sequence(data);
2✔
1329
}
1330
template<class T, class Traits, class Allocator>
1331
const_buffer buffer(const std::basic_string<T, Traits, Allocator> &data,
1✔
1332
                    size_t n_bytes) noexcept
1333
{
1334
    return detail::buffer_contiguous_sequence(data, n_bytes);
1✔
1335
}
1336

1337
#if CPPZMQ_HAS_STRING_VIEW
1338
// std::basic_string_view
1339
template<class T, class Traits>
1340
const_buffer buffer(std::basic_string_view<T, Traits> data) noexcept
1✔
1341
{
1342
    return detail::buffer_contiguous_sequence(data);
1✔
1343
}
1344
template<class T, class Traits>
1345
const_buffer buffer(std::basic_string_view<T, Traits> data, size_t n_bytes) noexcept
1✔
1346
{
1347
    return detail::buffer_contiguous_sequence(data, n_bytes);
1✔
1348
}
1349
#endif
1350

1351
// Buffer for a string literal (null terminated)
1352
// where the buffer size excludes the terminating character.
1353
// Equivalent to zmq::buffer(std::string_view("...")).
1354
template<class Char, size_t N>
1355
constexpr const_buffer str_buffer(const Char (&data)[N]) noexcept
16✔
1356
{
1357
    static_assert(detail::is_pod_like<Char>::value, "Char must be POD");
1358
#ifdef ZMQ_EXTENDED_CONSTEXPR
1359
    assert(data[N - 1] == Char{0});
16✔
1360
#endif
1361
    return const_buffer(static_cast<const Char *>(data), (N - 1) * sizeof(Char));
16✔
1362
}
1363

1364
namespace literals
1365
{
1366
constexpr const_buffer operator"" _zbuf(const char *str, size_t len) noexcept
1367
{
1368
    return const_buffer(str, len * sizeof(char));
1369
}
1370
constexpr const_buffer operator"" _zbuf(const wchar_t *str, size_t len) noexcept
1371
{
1372
    return const_buffer(str, len * sizeof(wchar_t));
1373
}
1374
constexpr const_buffer operator"" _zbuf(const char16_t *str, size_t len) noexcept
1375
{
1376
    return const_buffer(str, len * sizeof(char16_t));
1377
}
1378
constexpr const_buffer operator"" _zbuf(const char32_t *str, size_t len) noexcept
1379
{
1380
    return const_buffer(str, len * sizeof(char32_t));
1381
}
1382
}
1383

1384
#ifdef ZMQ_CPP11
1385
enum class socket_type : int
1386
{
1387
    req = ZMQ_REQ,
1388
    rep = ZMQ_REP,
1389
    dealer = ZMQ_DEALER,
1390
    router = ZMQ_ROUTER,
1391
    pub = ZMQ_PUB,
1392
    sub = ZMQ_SUB,
1393
    xpub = ZMQ_XPUB,
1394
    xsub = ZMQ_XSUB,
1395
    push = ZMQ_PUSH,
1396
    pull = ZMQ_PULL,
1397
#if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 0)
1398
    server = ZMQ_SERVER,
1399
    client = ZMQ_CLIENT,
1400
    radio = ZMQ_RADIO,
1401
    dish = ZMQ_DISH,
1402
    gather = ZMQ_GATHER,
1403
    scatter = ZMQ_SCATTER,
1404
    dgram = ZMQ_DGRAM,
1405
#endif
1406
#if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 3, 3)
1407
    peer = ZMQ_PEER,
1408
    channel = ZMQ_CHANNEL,
1409
#endif
1410
#if ZMQ_VERSION_MAJOR >= 4
1411
    stream = ZMQ_STREAM,
1412
#endif
1413
    pair = ZMQ_PAIR
1414
};
1415
#endif
1416

1417
namespace sockopt
1418
{
1419
// There are two types of options,
1420
// integral type with known compiler time size (int, bool, int64_t, uint64_t)
1421
// and arrays with dynamic size (strings, binary data).
1422

1423
// BoolUnit: if true accepts values of type bool (but passed as T into libzmq)
1424
template<int Opt, class T, bool BoolUnit = false> struct integral_option
1425
{
1426
};
1427

1428
// NullTerm:
1429
// 0: binary data
1430
// 1: null-terminated string (`getsockopt` size includes null)
1431
// 2: binary (size 32) or Z85 encoder string of size 41 (null included)
1432
template<int Opt, int NullTerm = 1> struct array_option
1433
{
1434
};
1435

1436
#define ZMQ_DEFINE_INTEGRAL_OPT(OPT, NAME, TYPE)                                    \
1437
    using NAME##_t = integral_option<OPT, TYPE, false>;                             \
1438
    ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1439
#define ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(OPT, NAME, TYPE)                          \
1440
    using NAME##_t = integral_option<OPT, TYPE, true>;                              \
1441
    ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1442
#define ZMQ_DEFINE_ARRAY_OPT(OPT, NAME)                                             \
1443
    using NAME##_t = array_option<OPT>;                                             \
1444
    ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1445
#define ZMQ_DEFINE_ARRAY_OPT_BINARY(OPT, NAME)                                      \
1446
    using NAME##_t = array_option<OPT, 0>;                                          \
1447
    ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1448
#define ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(OPT, NAME)                                  \
1449
    using NAME##_t = array_option<OPT, 2>;                                          \
1450
    ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1451

1452
// deprecated, use zmq::fd_t
1453
using cppzmq_fd_t = ::zmq::fd_t;
1454

1455
#ifdef ZMQ_AFFINITY
1456
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_AFFINITY, affinity, uint64_t);
1457
#endif
1458
#ifdef ZMQ_BACKLOG
1459
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_BACKLOG, backlog, int);
1460
#endif
1461
#ifdef ZMQ_BINDTODEVICE
1462
ZMQ_DEFINE_ARRAY_OPT_BINARY(ZMQ_BINDTODEVICE, bindtodevice);
1463
#endif
1464
#ifdef ZMQ_CONFLATE
1465
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_CONFLATE, conflate, int);
1466
#endif
1467
#ifdef ZMQ_CONNECT_ROUTING_ID
1468
ZMQ_DEFINE_ARRAY_OPT(ZMQ_CONNECT_ROUTING_ID, connect_routing_id);
1469
#endif
1470
#ifdef ZMQ_CONNECT_TIMEOUT
1471
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_CONNECT_TIMEOUT, connect_timeout, int);
1472
#endif
1473
#ifdef ZMQ_CURVE_PUBLICKEY
1474
ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(ZMQ_CURVE_PUBLICKEY, curve_publickey);
1475
#endif
1476
#ifdef ZMQ_CURVE_SECRETKEY
1477
ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(ZMQ_CURVE_SECRETKEY, curve_secretkey);
1478
#endif
1479
#ifdef ZMQ_CURVE_SERVER
1480
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_CURVE_SERVER, curve_server, int);
1481
#endif
1482
#ifdef ZMQ_CURVE_SERVERKEY
1483
ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(ZMQ_CURVE_SERVERKEY, curve_serverkey);
1484
#endif
1485
#ifdef ZMQ_DISCONNECT_MSG
1486
ZMQ_DEFINE_ARRAY_OPT_BINARY(ZMQ_DISCONNECT_MSG, disconnect_msg);
1487
#endif
1488
#ifdef ZMQ_EVENTS
1489
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_EVENTS, events, int);
1490
#endif
1491
#ifdef ZMQ_FD
1492
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_FD, fd, ::zmq::fd_t);
1493
#endif
1494
#ifdef ZMQ_GSSAPI_PLAINTEXT
1495
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_GSSAPI_PLAINTEXT, gssapi_plaintext, int);
1496
#endif
1497
#ifdef ZMQ_GSSAPI_SERVER
1498
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_GSSAPI_SERVER, gssapi_server, int);
1499
#endif
1500
#ifdef ZMQ_GSSAPI_SERVICE_PRINCIPAL
1501
ZMQ_DEFINE_ARRAY_OPT(ZMQ_GSSAPI_SERVICE_PRINCIPAL, gssapi_service_principal);
1502
#endif
1503
#ifdef ZMQ_GSSAPI_SERVICE_PRINCIPAL_NAMETYPE
1504
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_GSSAPI_SERVICE_PRINCIPAL_NAMETYPE,
1505
                        gssapi_service_principal_nametype,
1506
                        int);
1507
#endif
1508
#ifdef ZMQ_GSSAPI_PRINCIPAL
1509
ZMQ_DEFINE_ARRAY_OPT(ZMQ_GSSAPI_PRINCIPAL, gssapi_principal);
1510
#endif
1511
#ifdef ZMQ_GSSAPI_PRINCIPAL_NAMETYPE
1512
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_GSSAPI_PRINCIPAL_NAMETYPE,
1513
                        gssapi_principal_nametype,
1514
                        int);
1515
#endif
1516
#ifdef ZMQ_HANDSHAKE_IVL
1517
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HANDSHAKE_IVL, handshake_ivl, int);
1518
#endif
1519
#ifdef ZMQ_HEARTBEAT_IVL
1520
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HEARTBEAT_IVL, heartbeat_ivl, int);
1521
#endif
1522
#ifdef ZMQ_HEARTBEAT_TIMEOUT
1523
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HEARTBEAT_TIMEOUT, heartbeat_timeout, int);
1524
#endif
1525
#ifdef ZMQ_HEARTBEAT_TTL
1526
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HEARTBEAT_TTL, heartbeat_ttl, int);
1527
#endif
1528
#ifdef ZMQ_HELLO_MSG
1529
ZMQ_DEFINE_ARRAY_OPT_BINARY(ZMQ_HELLO_MSG, hello_msg);
1530
#endif
1531
#ifdef ZMQ_IMMEDIATE
1532
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_IMMEDIATE, immediate, int);
1533
#endif
1534
#ifdef ZMQ_INVERT_MATCHING
1535
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_INVERT_MATCHING, invert_matching, int);
1536
#endif
1537
#ifdef ZMQ_IPV6
1538
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_IPV6, ipv6, int);
1539
#endif
1540
#ifdef ZMQ_LAST_ENDPOINT
1541
ZMQ_DEFINE_ARRAY_OPT(ZMQ_LAST_ENDPOINT, last_endpoint);
1542
#endif
1543
#ifdef ZMQ_LINGER
1544
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_LINGER, linger, int);
1545
#endif
1546
#ifdef ZMQ_MAXMSGSIZE
1547
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MAXMSGSIZE, maxmsgsize, int64_t);
1548
#endif
1549
#ifdef ZMQ_MECHANISM
1550
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MECHANISM, mechanism, int);
1551
#endif
1552
#ifdef ZMQ_METADATA
1553
ZMQ_DEFINE_ARRAY_OPT(ZMQ_METADATA, metadata);
1554
#endif
1555
#ifdef ZMQ_MULTICAST_HOPS
1556
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MULTICAST_HOPS, multicast_hops, int);
1557
#endif
1558
#ifdef ZMQ_MULTICAST_LOOP
1559
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_MULTICAST_LOOP, multicast_loop, int);
1560
#endif
1561
#ifdef ZMQ_MULTICAST_MAXTPDU
1562
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MULTICAST_MAXTPDU, multicast_maxtpdu, int);
1563
#endif
1564
#ifdef ZMQ_ONLY_FIRST_SUBSCRIBE
1565
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ONLY_FIRST_SUBSCRIBE, only_first_subscribe, int);
1566
#endif
1567
#ifdef ZMQ_PLAIN_SERVER
1568
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_PLAIN_SERVER, plain_server, int);
1569
#endif
1570
#ifdef ZMQ_PLAIN_PASSWORD
1571
ZMQ_DEFINE_ARRAY_OPT(ZMQ_PLAIN_PASSWORD, plain_password);
1572
#endif
1573
#ifdef ZMQ_PLAIN_USERNAME
1574
ZMQ_DEFINE_ARRAY_OPT(ZMQ_PLAIN_USERNAME, plain_username);
1575
#endif
1576
#ifdef ZMQ_PRIORITY
1577
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_PRIORITY, priority, int);
1578
#endif
1579
#ifdef ZMQ_USE_FD
1580
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_USE_FD, use_fd, int);
1581
#endif
1582
#ifdef ZMQ_PROBE_ROUTER
1583
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_PROBE_ROUTER, probe_router, int);
1584
#endif
1585
#ifdef ZMQ_RATE
1586
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RATE, rate, int);
1587
#endif
1588
#ifdef ZMQ_RCVBUF
1589
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RCVBUF, rcvbuf, int);
1590
#endif
1591
#ifdef ZMQ_RCVHWM
1592
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RCVHWM, rcvhwm, int);
1593
#endif
1594
#ifdef ZMQ_RCVMORE
1595
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_RCVMORE, rcvmore, int);
1596
#endif
1597
#ifdef ZMQ_RCVTIMEO
1598
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RCVTIMEO, rcvtimeo, int);
1599
#endif
1600
#ifdef ZMQ_RECONNECT_IVL
1601
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RECONNECT_IVL, reconnect_ivl, int);
1602
#endif
1603
#ifdef ZMQ_RECONNECT_IVL_MAX
1604
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RECONNECT_IVL_MAX, reconnect_ivl_max, int);
1605
#endif
1606
#ifdef ZMQ_RECONNECT_STOP
1607
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RECONNECT_STOP, reconnect_stop, int);
1608
#endif
1609
#ifdef ZMQ_RECOVERY_IVL
1610
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RECOVERY_IVL, recovery_ivl, int);
1611
#endif
1612
#ifdef ZMQ_REQ_CORRELATE
1613
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_REQ_CORRELATE, req_correlate, int);
1614
#endif
1615
#ifdef ZMQ_REQ_RELAXED
1616
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_REQ_RELAXED, req_relaxed, int);
1617
#endif
1618
#ifdef ZMQ_ROUTER_HANDOVER
1619
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ROUTER_HANDOVER, router_handover, int);
1620
#endif
1621
#ifdef ZMQ_ROUTER_MANDATORY
1622
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ROUTER_MANDATORY, router_mandatory, int);
1623
#endif
1624
#ifdef ZMQ_ROUTER_NOTIFY
1625
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_ROUTER_NOTIFY, router_notify, int);
1626
#endif
1627
#ifdef ZMQ_ROUTING_ID
1628
ZMQ_DEFINE_ARRAY_OPT_BINARY(ZMQ_ROUTING_ID, routing_id);
1629
#endif
1630
#ifdef ZMQ_SNDBUF
1631
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_SNDBUF, sndbuf, int);
1632
#endif
1633
#ifdef ZMQ_SNDHWM
1634
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_SNDHWM, sndhwm, int);
1635
#endif
1636
#ifdef ZMQ_SNDTIMEO
1637
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_SNDTIMEO, sndtimeo, int);
1638
#endif
1639
#ifdef ZMQ_SOCKS_PASSWORD
1640
ZMQ_DEFINE_ARRAY_OPT(ZMQ_SOCKS_PASSWORD, socks_password);
1641
#endif
1642
#ifdef ZMQ_SOCKS_PROXY
1643
ZMQ_DEFINE_ARRAY_OPT(ZMQ_SOCKS_PROXY, socks_proxy);
1644
#endif
1645
#ifdef ZMQ_SOCKS_USERNAME
1646
ZMQ_DEFINE_ARRAY_OPT(ZMQ_SOCKS_USERNAME, socks_username);
1647
#endif
1648
#ifdef ZMQ_STREAM_NOTIFY
1649
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_STREAM_NOTIFY, stream_notify, int);
1650
#endif
1651
#ifdef ZMQ_SUBSCRIBE
1652
ZMQ_DEFINE_ARRAY_OPT(ZMQ_SUBSCRIBE, subscribe);
1653
#endif
1654
#ifdef ZMQ_TCP_KEEPALIVE
1655
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE, tcp_keepalive, int);
1656
#endif
1657
#ifdef ZMQ_TCP_KEEPALIVE_CNT
1658
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE_CNT, tcp_keepalive_cnt, int);
1659
#endif
1660
#ifdef ZMQ_TCP_KEEPALIVE_IDLE
1661
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE_IDLE, tcp_keepalive_idle, int);
1662
#endif
1663
#ifdef ZMQ_TCP_KEEPALIVE_INTVL
1664
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE_INTVL, tcp_keepalive_intvl, int);
1665
#endif
1666
#ifdef ZMQ_TCP_MAXRT
1667
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_MAXRT, tcp_maxrt, int);
1668
#endif
1669
#ifdef ZMQ_THREAD_SAFE
1670
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_THREAD_SAFE, thread_safe, int);
1671
#endif
1672
#ifdef ZMQ_TOS
1673
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TOS, tos, int);
1674
#endif
1675
#ifdef ZMQ_TYPE
1676
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TYPE, type, int);
1677
#ifdef ZMQ_CPP11
1678
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TYPE, socket_type, socket_type);
1679
#endif // ZMQ_CPP11
1680
#endif // ZMQ_TYPE
1681
#ifdef ZMQ_UNSUBSCRIBE
1682
ZMQ_DEFINE_ARRAY_OPT(ZMQ_UNSUBSCRIBE, unsubscribe);
1683
#endif
1684
#ifdef ZMQ_VMCI_BUFFER_SIZE
1685
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_BUFFER_SIZE, vmci_buffer_size, uint64_t);
1686
#endif
1687
#ifdef ZMQ_VMCI_BUFFER_MIN_SIZE
1688
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_BUFFER_MIN_SIZE, vmci_buffer_min_size, uint64_t);
1689
#endif
1690
#ifdef ZMQ_VMCI_BUFFER_MAX_SIZE
1691
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_BUFFER_MAX_SIZE, vmci_buffer_max_size, uint64_t);
1692
#endif
1693
#ifdef ZMQ_VMCI_CONNECT_TIMEOUT
1694
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_CONNECT_TIMEOUT, vmci_connect_timeout, int);
1695
#endif
1696
#ifdef ZMQ_XPUB_VERBOSE
1697
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_VERBOSE, xpub_verbose, int);
1698
#endif
1699
#ifdef ZMQ_XPUB_VERBOSER
1700
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_VERBOSER, xpub_verboser, int);
1701
#endif
1702
#ifdef ZMQ_XPUB_MANUAL
1703
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_MANUAL, xpub_manual, int);
1704
#endif
1705
#ifdef ZMQ_XPUB_MANUAL_LAST_VALUE
1706
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_MANUAL_LAST_VALUE, xpub_manual_last_value, int);
1707
#endif
1708
#ifdef ZMQ_XPUB_NODROP
1709
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_NODROP, xpub_nodrop, int);
1710
#endif
1711
#ifdef ZMQ_XPUB_WELCOME_MSG
1712
ZMQ_DEFINE_ARRAY_OPT(ZMQ_XPUB_WELCOME_MSG, xpub_welcome_msg);
1713
#endif
1714
#ifdef ZMQ_ZAP_ENFORCE_DOMAIN
1715
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ZAP_ENFORCE_DOMAIN, zap_enforce_domain, int);
1716
#endif
1717
#ifdef ZMQ_ZAP_DOMAIN
1718
ZMQ_DEFINE_ARRAY_OPT(ZMQ_ZAP_DOMAIN, zap_domain);
1719
#endif
1720

1721
} // namespace sockopt
1722
#endif // ZMQ_CPP11
1723

1724

1725
namespace detail
1726
{
1727
class socket_base
1728
{
1729
  public:
1730
    socket_base() ZMQ_NOTHROW : _handle(ZMQ_NULLPTR) {}
75✔
1731
    ZMQ_EXPLICIT socket_base(void *handle) ZMQ_NOTHROW : _handle(handle) {}
491✔
1732

1733
    template<typename T>
1734
    ZMQ_CPP11_DEPRECATED("from 4.7.0, use `set` taking option from zmq::sockopt")
1735
    void setsockopt(int option_, T const &optval)
1736
    {
1737
        setsockopt(option_, &optval, sizeof(T));
1738
    }
1739

1740
    ZMQ_CPP11_DEPRECATED("from 4.7.0, use `set` taking option from zmq::sockopt")
1741
    void setsockopt(int option_, const void *optval_, size_t optvallen_)
1742
    {
1743
        int rc = zmq_setsockopt(_handle, option_, optval_, optvallen_);
1744
        if (rc != 0)
1745
            throw error_t();
1746
    }
1747

1748
    ZMQ_CPP11_DEPRECATED("from 4.7.0, use `get` taking option from zmq::sockopt")
1749
    void getsockopt(int option_, void *optval_, size_t *optvallen_) const
1750
    {
1751
        int rc = zmq_getsockopt(_handle, option_, optval_, optvallen_);
1752
        if (rc != 0)
1753
            throw error_t();
1754
    }
1755

1756
    template<typename T>
1757
    ZMQ_CPP11_DEPRECATED("from 4.7.0, use `get` taking option from zmq::sockopt")
1758
    T getsockopt(int option_) const
1759
    {
1760
        T optval;
1761
        size_t optlen = sizeof(T);
1762
        getsockopt(option_, &optval, &optlen);
1763
        return optval;
1764
    }
1765

1766
#ifdef ZMQ_CPP11
1767
    // Set integral socket option, e.g.
1768
    // `socket.set(zmq::sockopt::linger, 0)`
1769
    template<int Opt, class T, bool BoolUnit>
1770
    void set(sockopt::integral_option<Opt, T, BoolUnit>, const T &val)
49✔
1771
    {
1772
        static_assert(std::is_integral<T>::value, "T must be integral");
1773
        set_option(Opt, &val, sizeof val);
49✔
1774
    }
48✔
1775

1776
    // Set integral socket option from boolean, e.g.
1777
    // `socket.set(zmq::sockopt::immediate, false)`
1778
    template<int Opt, class T>
1779
    void set(sockopt::integral_option<Opt, T, true>, bool val)
3✔
1780
    {
1781
        static_assert(std::is_integral<T>::value, "T must be integral");
1782
        T rep_val = val;
3✔
1783
        set_option(Opt, &rep_val, sizeof rep_val);
3✔
1784
    }
3✔
1785

1786
    // Set array socket option, e.g.
1787
    // `socket.set(zmq::sockopt::plain_username, "foo123")`
1788
    template<int Opt, int NullTerm>
1789
    void set(sockopt::array_option<Opt, NullTerm>, const char *buf)
1✔
1790
    {
1791
        set_option(Opt, buf, std::strlen(buf));
1✔
1792
    }
1✔
1793

1794
    // Set array socket option, e.g.
1795
    // `socket.set(zmq::sockopt::routing_id, zmq::buffer(id))`
1796
    template<int Opt, int NullTerm>
1797
    void set(sockopt::array_option<Opt, NullTerm>, const_buffer buf)
6✔
1798
    {
1799
        set_option(Opt, buf.data(), buf.size());
6✔
1800
    }
6✔
1801

1802
    // Set array socket option, e.g.
1803
    // `socket.set(zmq::sockopt::routing_id, id_str)`
1804
    template<int Opt, int NullTerm>
1805
    void set(sockopt::array_option<Opt, NullTerm>, const std::string &buf)
14✔
1806
    {
1807
        set_option(Opt, buf.data(), buf.size());
14✔
1808
    }
14✔
1809

1810
#if CPPZMQ_HAS_STRING_VIEW
1811
    // Set array socket option, e.g.
1812
    // `socket.set(zmq::sockopt::routing_id, id_str)`
1813
    template<int Opt, int NullTerm>
1814
    void set(sockopt::array_option<Opt, NullTerm>, std::string_view buf)
1✔
1815
    {
1816
        set_option(Opt, buf.data(), buf.size());
1✔
1817
    }
1✔
1818
#endif
1819

1820
    // Get scalar socket option, e.g.
1821
    // `auto opt = socket.get(zmq::sockopt::linger)`
1822
    template<int Opt, class T, bool BoolUnit>
1823
    ZMQ_NODISCARD T get(sockopt::integral_option<Opt, T, BoolUnit>) const
47✔
1824
    {
1825
        static_assert(std::is_scalar<T>::value, "T must be scalar");
1826
        T val;
1827
        size_t size = sizeof val;
47✔
1828
        get_option(Opt, &val, &size);
47✔
1829
        assert(size == sizeof val);
47✔
1830
        return val;
47✔
1831
    }
1832

1833
    // Get array socket option, writes to buf, returns option size in bytes, e.g.
1834
    // `size_t optsize = socket.get(zmq::sockopt::routing_id, zmq::buffer(id))`
1835
    template<int Opt, int NullTerm>
1836
    ZMQ_NODISCARD size_t get(sockopt::array_option<Opt, NullTerm>,
54✔
1837
                             mutable_buffer buf) const
1838
    {
1839
        size_t size = buf.size();
54✔
1840
        get_option(Opt, buf.data(), &size);
54✔
1841
        return size;
53✔
1842
    }
1843

1844
    // Get array socket option as string (initializes the string buffer size to init_size) e.g.
1845
    // `auto s = socket.get(zmq::sockopt::routing_id)`
1846
    // Note: removes the null character from null-terminated string options,
1847
    // i.e. the string size excludes the null character.
1848
    template<int Opt, int NullTerm>
1849
    ZMQ_NODISCARD std::string get(sockopt::array_option<Opt, NullTerm>,
15✔
1850
                                  size_t init_size = 1024) const
1851
    {
1852
        if ZMQ_CONSTEXPR_IF (NullTerm == 2) {
1853
            if (init_size == 1024) {
8✔
1854
                init_size = 41; // get as Z85 string
4✔
1855
            }
1856
        }
1857
        std::string str(init_size, '\0');
15✔
1858
        size_t size = get(sockopt::array_option<Opt>{}, buffer(str));
15✔
1859
        if ZMQ_CONSTEXPR_IF (NullTerm == 1) {
1860
            if (size > 0) {
5✔
1861
                assert(str[size - 1] == '\0');
5✔
1862
                --size;
5✔
1863
            }
1864
        } else if ZMQ_CONSTEXPR_IF (NullTerm == 2) {
1865
            assert(size == 32 || size == 41);
8✔
1866
            if (size == 41) {
8✔
1867
                assert(str[size - 1] == '\0');
4✔
1868
                --size;
4✔
1869
            }
1870
        }
1871
        str.resize(size);
15✔
1872
        return str;
15✔
1873
    }
1874
#endif
1875

1876
    void bind(std::string const &addr) { bind(addr.c_str()); }
1877

1878
    void bind(const char *addr_)
76✔
1879
    {
1880
        int rc = zmq_bind(_handle, addr_);
76✔
1881
        if (rc != 0)
76✔
1882
            throw error_t();
×
1883
    }
76✔
1884

1885
    void unbind(std::string const &addr) { unbind(addr.c_str()); }
1886

1887
    void unbind(const char *addr_)
1888
    {
1889
        int rc = zmq_unbind(_handle, addr_);
1890
        if (rc != 0)
1891
            throw error_t();
1892
    }
1893

1894
    void connect(std::string const &addr) { connect(addr.c_str()); }
37✔
1895

1896
    void connect(const char *addr_)
74✔
1897
    {
1898
        int rc = zmq_connect(_handle, addr_);
74✔
1899
        if (rc != 0)
74✔
1900
            throw error_t();
1✔
1901
    }
73✔
1902

1903
    void disconnect(std::string const &addr) { disconnect(addr.c_str()); }
1904

1905
    void disconnect(const char *addr_)
1906
    {
1907
        int rc = zmq_disconnect(_handle, addr_);
1908
        if (rc != 0)
1909
            throw error_t();
1910
    }
1911

1912
    ZMQ_DEPRECATED("from 4.7.1, use handle() != nullptr or operator bool")
1913
    bool connected() const ZMQ_NOTHROW { return (_handle != ZMQ_NULLPTR); }
1914

1915
    ZMQ_CPP11_DEPRECATED("from 4.3.1, use send taking a const_buffer and send_flags")
1916
    size_t send(const void *buf_, size_t len_, int flags_ = 0)
1917
    {
1918
        int nbytes = zmq_send(_handle, buf_, len_, flags_);
1919
        if (nbytes >= 0)
1920
            return static_cast<size_t>(nbytes);
1921
        if (zmq_errno() == EAGAIN)
1922
            return 0;
1923
        throw error_t();
1924
    }
1925

1926
    ZMQ_CPP11_DEPRECATED("from 4.3.1, use send taking message_t and send_flags")
1927
    bool send(message_t &msg_,
1928
              int flags_ = 0) // default until removed
1929
    {
1930
        int nbytes = zmq_msg_send(msg_.handle(), _handle, flags_);
1931
        if (nbytes >= 0)
1932
            return true;
1933
        if (zmq_errno() == EAGAIN)
1934
            return false;
1935
        throw error_t();
1936
    }
1937

1938
    template<typename T>
1939
    ZMQ_CPP11_DEPRECATED(
1940
      "from 4.4.1, use send taking message_t or buffer (for contiguous "
1941
      "ranges), and send_flags")
1942
    bool send(T first, T last, int flags_ = 0)
1943
    {
1944
        zmq::message_t msg(first, last);
1945
        int nbytes = zmq_msg_send(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_HAS_RVALUE_REFS
1954
    ZMQ_CPP11_DEPRECATED("from 4.3.1, use send taking message_t and send_flags")
1955
    bool send(message_t &&msg_,
1956
              int flags_ = 0) // default until removed
1957
    {
1958
#ifdef ZMQ_CPP11
1959
        return send(msg_, static_cast<send_flags>(flags_)).has_value();
1960
#else
1961
        return send(msg_, flags_);
1962
#endif
1963
    }
1964
#endif
1965

1966
#ifdef ZMQ_CPP11
1967
    send_result_t send(const_buffer buf, send_flags flags = send_flags::none)
30✔
1968
    {
1969
        const int nbytes =
1970
          zmq_send(_handle, buf.data(), buf.size(), static_cast<int>(flags));
30✔
1971
        if (nbytes >= 0)
30✔
1972
            return static_cast<size_t>(nbytes);
26✔
1973
        if (zmq_errno() == EAGAIN)
4✔
1974
            return {};
3✔
1975
        throw error_t();
1✔
1976
    }
1977

1978
    send_result_t send(message_t &msg, send_flags flags)
59✔
1979
    {
1980
        int nbytes = zmq_msg_send(msg.handle(), _handle, static_cast<int>(flags));
59✔
1981
        if (nbytes >= 0)
59✔
1982
            return static_cast<size_t>(nbytes);
56✔
1983
        if (zmq_errno() == EAGAIN)
3✔
1984
            return {};
2✔
1985
        throw error_t();
1✔
1986
    }
1987

1988
    send_result_t send(message_t &&msg, send_flags flags)
36✔
1989
    {
1990
        return send(msg, flags);
36✔
1991
    }
1992
#endif
1993

1994
    ZMQ_CPP11_DEPRECATED(
1995
      "from 4.3.1, use recv taking a mutable_buffer and recv_flags")
1996
    size_t recv(void *buf_, size_t len_, int flags_ = 0)
1997
    {
1998
        int nbytes = zmq_recv(_handle, buf_, len_, flags_);
1999
        if (nbytes >= 0)
2000
            return static_cast<size_t>(nbytes);
2001
        if (zmq_errno() == EAGAIN)
2002
            return 0;
2003
        throw error_t();
2004
    }
2005

2006
    ZMQ_CPP11_DEPRECATED(
2007
      "from 4.3.1, use recv taking a reference to message_t and recv_flags")
2008
    bool recv(message_t *msg_, int flags_ = 0)
1✔
2009
    {
2010
        int nbytes = zmq_msg_recv(msg_->handle(), _handle, flags_);
1✔
2011
        if (nbytes >= 0)
1✔
2012
            return true;
1✔
2013
        if (zmq_errno() == EAGAIN)
×
2014
            return false;
×
2015
        throw error_t();
×
2016
    }
2017

2018
#ifdef ZMQ_CPP11
2019
    ZMQ_NODISCARD
2020
    recv_buffer_result_t recv(mutable_buffer buf,
5✔
2021
                              recv_flags flags = recv_flags::none)
2022
    {
2023
        const int nbytes =
2024
          zmq_recv(_handle, buf.data(), buf.size(), static_cast<int>(flags));
5✔
2025
        if (nbytes >= 0) {
5✔
2026
            return recv_buffer_size{
×
2027
              (std::min)(static_cast<size_t>(nbytes), buf.size()),
6✔
2028
              static_cast<size_t>(nbytes)};
3✔
2029
        }
2030
        if (zmq_errno() == EAGAIN)
2✔
2031
            return {};
1✔
2032
        throw error_t();
1✔
2033
    }
2034

2035
    ZMQ_NODISCARD
2036
    recv_result_t recv(message_t &msg, recv_flags flags = recv_flags::none)
36✔
2037
    {
2038
        const int nbytes =
2039
          zmq_msg_recv(msg.handle(), _handle, static_cast<int>(flags));
36✔
2040
        if (nbytes >= 0) {
36✔
2041
            assert(msg.size() == static_cast<size_t>(nbytes));
29✔
2042
            return static_cast<size_t>(nbytes);
29✔
2043
        }
2044
        if (zmq_errno() == EAGAIN)
7✔
2045
            return {};
5✔
2046
        throw error_t();
2✔
2047
    }
2048
#endif
2049

2050
#if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 0)
2051
    void join(const char *group)
2052
    {
2053
        int rc = zmq_join(_handle, group);
2054
        if (rc != 0)
2055
            throw error_t();
2056
    }
2057

2058
    void leave(const char *group)
2059
    {
2060
        int rc = zmq_leave(_handle, group);
2061
        if (rc != 0)
2062
            throw error_t();
2063
    }
2064
#endif
2065

2066
    ZMQ_NODISCARD void *handle() ZMQ_NOTHROW { return _handle; }
239✔
2067
    ZMQ_NODISCARD const void *handle() const ZMQ_NOTHROW { return _handle; }
70✔
2068

2069
    ZMQ_EXPLICIT operator bool() const ZMQ_NOTHROW { return _handle != ZMQ_NULLPTR; }
2✔
2070
    // note: non-const operator bool can be removed once
2071
    // operator void* is removed from socket_t
2072
    ZMQ_EXPLICIT operator bool() ZMQ_NOTHROW { return _handle != ZMQ_NULLPTR; }
28✔
2073

2074
  protected:
2075
    void *_handle;
2076

2077
  private:
2078
    void set_option(int option_, const void *optval_, size_t optvallen_)
74✔
2079
    {
2080
        int rc = zmq_setsockopt(_handle, option_, optval_, optvallen_);
74✔
2081
        if (rc != 0)
74✔
2082
            throw error_t();
1✔
2083
    }
73✔
2084

2085
    void get_option(int option_, void *optval_, size_t *optvallen_) const
101✔
2086
    {
2087
        int rc = zmq_getsockopt(_handle, option_, optval_, optvallen_);
101✔
2088
        if (rc != 0)
101✔
2089
            throw error_t();
1✔
2090
    }
100✔
2091
};
2092
} // namespace detail
2093

2094
struct from_handle_t
2095
{
2096
    struct _private
2097
    {
2098
    }; // disabling use other than with from_handle
2099
    ZMQ_CONSTEXPR_FN ZMQ_EXPLICIT from_handle_t(_private /*p*/) ZMQ_NOTHROW {}
2100
};
2101

2102
ZMQ_CONSTEXPR_VAR from_handle_t from_handle =
2103
  from_handle_t(from_handle_t::_private());
2104

2105
// A non-owning nullable reference to a socket.
2106
// The reference is invalidated on socket close or destruction.
2107
class socket_ref : public detail::socket_base
2108
{
2109
  public:
2110
    socket_ref() ZMQ_NOTHROW : detail::socket_base() {}
72✔
2111
#ifdef ZMQ_CPP11
2112
    socket_ref(std::nullptr_t) ZMQ_NOTHROW : detail::socket_base() {}
3✔
2113
#endif
2114
    socket_ref(from_handle_t /*fh*/, void *handle) ZMQ_NOTHROW
147✔
2115
        : detail::socket_base(handle)
147✔
2116
    {
2117
    }
147✔
2118
};
2119

2120
#ifdef ZMQ_CPP11
2121
inline bool operator==(socket_ref sr, std::nullptr_t /*p*/) ZMQ_NOTHROW
6✔
2122
{
2123
    return sr.handle() == nullptr;
6✔
2124
}
2125
inline bool operator==(std::nullptr_t /*p*/, socket_ref sr) ZMQ_NOTHROW
1✔
2126
{
2127
    return sr.handle() == nullptr;
1✔
2128
}
2129
inline bool operator!=(socket_ref sr, std::nullptr_t /*p*/) ZMQ_NOTHROW
2✔
2130
{
2131
    return !(sr == nullptr);
2✔
2132
}
2133
inline bool operator!=(std::nullptr_t /*p*/, socket_ref sr) ZMQ_NOTHROW
1✔
2134
{
2135
    return !(sr == nullptr);
1✔
2136
}
2137
#endif
2138

2139
inline bool operator==(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
31✔
2140
{
2141
    return std::equal_to<const void *>()(a.handle(), b.handle());
31✔
2142
}
2143
inline bool operator!=(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
3✔
2144
{
2145
    return !(a == b);
3✔
2146
}
2147
inline bool operator<(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
4✔
2148
{
2149
    return std::less<const void *>()(a.handle(), b.handle());
4✔
2150
}
2151
inline bool operator>(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
2✔
2152
{
2153
    return b < a;
2✔
2154
}
2155
inline bool operator<=(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
1✔
2156
{
2157
    return !(a > b);
1✔
2158
}
2159
inline bool operator>=(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
1✔
2160
{
2161
    return !(a < b);
1✔
2162
}
2163

2164
} // namespace zmq
2165

2166
#ifdef ZMQ_CPP11
2167
namespace std
2168
{
2169
template<> struct hash<zmq::socket_ref>
2170
{
2171
    size_t operator()(zmq::socket_ref sr) const ZMQ_NOTHROW
81✔
2172
    {
2173
        return hash<void *>()(sr.handle());
81✔
2174
    }
2175
};
2176
} // namespace std
2177
#endif
2178

2179
namespace zmq
2180
{
2181
class socket_t : public detail::socket_base
2182
{
2183
    friend class monitor_t;
2184

2185
  public:
2186
    socket_t() ZMQ_NOTHROW : detail::socket_base(ZMQ_NULLPTR), ctxptr(ZMQ_NULLPTR) {}
18✔
2187

2188
    socket_t(context_t &context_, int type_) :
201✔
2189
        detail::socket_base(zmq_socket(context_.handle(), type_)),
2190
        ctxptr(context_.handle())
201✔
2191
    {
2192
        if (_handle == ZMQ_NULLPTR)
201✔
2193
            throw error_t();
×
2194
    }
201✔
2195

2196
#ifdef ZMQ_CPP11
2197
    socket_t(context_t &context_, socket_type type_) :
139✔
2198
        socket_t(context_, static_cast<int>(type_))
139✔
2199
    {
2200
    }
139✔
2201
#endif
2202

2203
#ifdef ZMQ_HAS_RVALUE_REFS
2204
    socket_t(socket_t &&rhs) ZMQ_NOTHROW : detail::socket_base(rhs._handle),
117✔
2205
                                           ctxptr(rhs.ctxptr)
117✔
2206
    {
2207
        rhs._handle = ZMQ_NULLPTR;
117✔
2208
        rhs.ctxptr = ZMQ_NULLPTR;
117✔
2209
    }
117✔
2210
    socket_t &operator=(socket_t &&rhs) ZMQ_NOTHROW
20✔
2211
    {
2212
        close();
20✔
2213
        std::swap(_handle, rhs._handle);
20✔
2214
        std::swap(ctxptr, rhs.ctxptr);
20✔
2215
        return *this;
20✔
2216
    }
2217
#endif
2218

2219
    ~socket_t() ZMQ_NOTHROW { close(); }
344✔
2220

2221
    operator void *() ZMQ_NOTHROW { return _handle; }
20✔
2222

2223
    operator void const *() const ZMQ_NOTHROW { return _handle; }
×
2224

2225
    void close() ZMQ_NOTHROW
384✔
2226
    {
2227
        if (_handle == ZMQ_NULLPTR)
384✔
2228
            // already closed
2229
            return;
175✔
2230
        int rc = zmq_close(_handle);
209✔
2231
        ZMQ_ASSERT(rc == 0);
209✔
2232
        _handle = ZMQ_NULLPTR;
209✔
2233
        ctxptr = ZMQ_NULLPTR;
209✔
2234
    }
2235

2236
    void swap(socket_t &other) ZMQ_NOTHROW
1✔
2237
    {
2238
        std::swap(_handle, other._handle);
1✔
2239
        std::swap(ctxptr, other.ctxptr);
1✔
2240
    }
1✔
2241

2242
    operator socket_ref() ZMQ_NOTHROW { return socket_ref(from_handle, _handle); }
146✔
2243

2244
  private:
2245
    void *ctxptr;
2246

2247
    socket_t(const socket_t &) ZMQ_DELETED_FUNCTION;
2248
    void operator=(const socket_t &) ZMQ_DELETED_FUNCTION;
2249

2250
    // used by monitor_t
2251
    socket_t(void *context_, int type_) :
8✔
2252
        detail::socket_base(zmq_socket(context_, type_)), ctxptr(context_)
8✔
2253
    {
2254
        if (_handle == ZMQ_NULLPTR)
8✔
2255
            throw error_t();
×
2256
        if (ctxptr == ZMQ_NULLPTR)
8✔
2257
            throw error_t();
×
2258
    }
8✔
2259
};
2260

2261
inline void swap(socket_t &a, socket_t &b) ZMQ_NOTHROW
1✔
2262
{
2263
    a.swap(b);
1✔
2264
}
1✔
2265

2266
ZMQ_DEPRECATED("from 4.3.1, use proxy taking socket_t objects")
2267
inline void proxy(void *frontend, void *backend, void *capture)
2268
{
2269
    int rc = zmq_proxy(frontend, backend, capture);
2270
    if (rc != 0)
2271
        throw error_t();
2272
}
2273

2274
inline void
2275
proxy(socket_ref frontend, socket_ref backend, socket_ref capture = socket_ref())
1✔
2276
{
2277
    int rc = zmq_proxy(frontend.handle(), backend.handle(), capture.handle());
1✔
2278
    if (rc != 0)
1✔
2279
        throw error_t();
1✔
2280
}
×
2281

2282
#ifdef ZMQ_HAS_PROXY_STEERABLE
2283
ZMQ_DEPRECATED("from 4.3.1, use proxy_steerable taking socket_t objects")
2284
inline void
2285
proxy_steerable(void *frontend, void *backend, void *capture, void *control)
2286
{
2287
    int rc = zmq_proxy_steerable(frontend, backend, capture, control);
2288
    if (rc != 0)
2289
        throw error_t();
2290
}
2291

2292
inline void proxy_steerable(socket_ref frontend,
1✔
2293
                            socket_ref backend,
2294
                            socket_ref capture,
2295
                            socket_ref control)
2296
{
2297
    int rc = zmq_proxy_steerable(frontend.handle(), backend.handle(),
1✔
2298
                                 capture.handle(), control.handle());
2299
    if (rc != 0)
1✔
2300
        throw error_t();
1✔
2301
}
×
2302
#endif
2303

2304
class monitor_t
2305
{
2306
  public:
2307
    monitor_t() : _socket(), _monitor_socket() {}
13✔
2308

2309
    virtual ~monitor_t() { close(); }
15✔
2310

2311
#ifdef ZMQ_HAS_RVALUE_REFS
2312
    monitor_t(monitor_t &&rhs) ZMQ_NOTHROW : _socket(), _monitor_socket()
2✔
2313
    {
2314
        std::swap(_socket, rhs._socket);
2✔
2315
        std::swap(_monitor_socket, rhs._monitor_socket);
2✔
2316
    }
2✔
2317

2318
    monitor_t &operator=(monitor_t &&rhs) ZMQ_NOTHROW
3✔
2319
    {
2320
        close();
3✔
2321
        _socket = socket_ref();
3✔
2322
        std::swap(_socket, rhs._socket);
3✔
2323
        std::swap(_monitor_socket, rhs._monitor_socket);
3✔
2324
        return *this;
3✔
2325
    }
2326
#endif
2327

2328

2329
    void
2330
    monitor(socket_t &socket, std::string const &addr, int events = ZMQ_EVENT_ALL)
2331
    {
2332
        monitor(socket, addr.c_str(), events);
2333
    }
2334

2335
    void monitor(socket_t &socket, const char *addr_, int events = ZMQ_EVENT_ALL)
2336
    {
2337
        init(socket, addr_, events);
2338
        while (true) {
2339
            check_event(-1);
2340
        }
2341
    }
2342

2343
    void init(socket_t &socket, std::string const &addr, int events = ZMQ_EVENT_ALL)
2344
    {
2345
        init(socket, addr.c_str(), events);
2346
    }
2347

2348
    void init(socket_t &socket, const char *addr_, int events = ZMQ_EVENT_ALL)
8✔
2349
    {
2350
        int rc = zmq_socket_monitor(socket.handle(), addr_, events);
8✔
2351
        if (rc != 0)
8✔
2352
            throw error_t();
×
2353

2354
        _socket = socket;
8✔
2355
        _monitor_socket = socket_t(socket.ctxptr, ZMQ_PAIR);
8✔
2356
        _monitor_socket.connect(addr_);
8✔
2357

2358
        on_monitor_started();
8✔
2359
    }
8✔
2360

2361
    bool check_event(int timeout = 0)
6✔
2362
    {
2363
        assert(_monitor_socket);
6✔
2364

2365
        zmq::pollitem_t items[] = {
6✔
2366
          {_monitor_socket.handle(), 0, ZMQ_POLLIN, 0},
6✔
2367
        };
6✔
2368

2369
        #ifdef ZMQ_CPP11
2370
        zmq::poll(&items[0], 1, std::chrono::milliseconds(timeout));
6✔
2371
        #else
2372
        zmq::poll(&items[0], 1, timeout);
2373
        #endif
2374

2375
        return process_event(items[0].revents);
12✔
2376
    }
2377

2378
#ifdef ZMQ_EVENT_MONITOR_STOPPED
2379
    void abort()
1✔
2380
    {
2381
        if (_socket)
1✔
2382
            zmq_socket_monitor(_socket.handle(), ZMQ_NULLPTR, 0);
1✔
2383

2384
        _socket = socket_ref();
1✔
2385
    }
1✔
2386
#endif
2387
    virtual void on_monitor_started() {}
8✔
2388
    virtual void on_event_connected(const zmq_event_t &event_, const char *addr_)
×
2389
    {
2390
        (void) event_;
2391
        (void) addr_;
2392
    }
×
2393
    virtual void on_event_connect_delayed(const zmq_event_t &event_,
2✔
2394
                                          const char *addr_)
2395
    {
2396
        (void) event_;
2397
        (void) addr_;
2398
    }
2✔
2399
    virtual void on_event_connect_retried(const zmq_event_t &event_,
×
2400
                                          const char *addr_)
2401
    {
2402
        (void) event_;
2403
        (void) addr_;
2404
    }
×
2405
    virtual void on_event_listening(const zmq_event_t &event_, const char *addr_)
×
2406
    {
2407
        (void) event_;
2408
        (void) addr_;
2409
    }
×
2410
    virtual void on_event_bind_failed(const zmq_event_t &event_, const char *addr_)
×
2411
    {
2412
        (void) event_;
2413
        (void) addr_;
2414
    }
×
2415
    virtual void on_event_accepted(const zmq_event_t &event_, const char *addr_)
×
2416
    {
2417
        (void) event_;
2418
        (void) addr_;
2419
    }
×
2420
    virtual void on_event_accept_failed(const zmq_event_t &event_, const char *addr_)
×
2421
    {
2422
        (void) event_;
2423
        (void) addr_;
2424
    }
×
2425
    virtual void on_event_closed(const zmq_event_t &event_, const char *addr_)
×
2426
    {
2427
        (void) event_;
2428
        (void) addr_;
2429
    }
×
2430
    virtual void on_event_close_failed(const zmq_event_t &event_, const char *addr_)
×
2431
    {
2432
        (void) event_;
2433
        (void) addr_;
2434
    }
×
2435
    virtual void on_event_disconnected(const zmq_event_t &event_, const char *addr_)
×
2436
    {
2437
        (void) event_;
2438
        (void) addr_;
2439
    }
×
2440
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3)
2441
    virtual void on_event_handshake_failed_no_detail(const zmq_event_t &event_,
×
2442
                                                     const char *addr_)
2443
    {
2444
        (void) event_;
2445
        (void) addr_;
2446
    }
×
2447
    virtual void on_event_handshake_failed_protocol(const zmq_event_t &event_,
×
2448
                                                    const char *addr_)
2449
    {
2450
        (void) event_;
2451
        (void) addr_;
2452
    }
×
2453
    virtual void on_event_handshake_failed_auth(const zmq_event_t &event_,
×
2454
                                                const char *addr_)
2455
    {
2456
        (void) event_;
2457
        (void) addr_;
2458
    }
×
2459
    virtual void on_event_handshake_succeeded(const zmq_event_t &event_,
×
2460
                                              const char *addr_)
2461
    {
2462
        (void) event_;
2463
        (void) addr_;
2464
    }
×
2465
#elif ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 1)
2466
    virtual void on_event_handshake_failed(const zmq_event_t &event_,
2467
                                           const char *addr_)
2468
    {
2469
        (void) event_;
2470
        (void) addr_;
2471
    }
2472
    virtual void on_event_handshake_succeed(const zmq_event_t &event_,
2473
                                            const char *addr_)
2474
    {
2475
        (void) event_;
2476
        (void) addr_;
2477
    }
2478
#endif
2479
    virtual void on_event_unknown(const zmq_event_t &event_, const char *addr_)
×
2480
    {
2481
        (void) event_;
2482
        (void) addr_;
2483
    }
×
2484

2485
  protected:    
2486
    bool process_event(short events)
8✔
2487
    {
2488
        zmq::message_t eventMsg;
16✔
2489

2490
        if (events & ZMQ_POLLIN) {
8✔
2491
            int rc = zmq_msg_recv(eventMsg.handle(), _monitor_socket.handle(), 0);
7✔
2492
            if (rc == -1 && zmq_errno() == ETERM)
7✔
2493
                return false;
×
2494
            assert(rc != -1);
7✔
2495

2496
        } else {
2497
            return false;
1✔
2498
        }
2499

2500
#if ZMQ_VERSION_MAJOR >= 4
2501
        const char *data = static_cast<const char *>(eventMsg.data());
7✔
2502
        zmq_event_t msgEvent;
2503
        memcpy(&msgEvent.event, data, sizeof(uint16_t));
7✔
2504
        data += sizeof(uint16_t);
7✔
2505
        memcpy(&msgEvent.value, data, sizeof(int32_t));
7✔
2506
        zmq_event_t *event = &msgEvent;
7✔
2507
#else
2508
        zmq_event_t *event = static_cast<zmq_event_t *>(eventMsg.data());
2509
#endif
2510

2511
#ifdef ZMQ_NEW_MONITOR_EVENT_LAYOUT
2512
        zmq::message_t addrMsg;
14✔
2513
        int rc = zmq_msg_recv(addrMsg.handle(), _monitor_socket.handle(), 0);
7✔
2514
        if (rc == -1 && zmq_errno() == ETERM) {
7✔
2515
            return false;
×
2516
        }
2517

2518
        assert(rc != -1);
7✔
2519
        std::string address = addrMsg.to_string();
14✔
2520
#else
2521
        // 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.
2522
        std::string address = event->data.connected.addr;
2523
#endif
2524

2525
#ifdef ZMQ_EVENT_MONITOR_STOPPED
2526
        if (event->event == ZMQ_EVENT_MONITOR_STOPPED) {
7✔
2527
            return false;
1✔
2528
        }
2529

2530
#endif
2531

2532
        switch (event->event) {
6✔
2533
            case ZMQ_EVENT_CONNECTED:
2✔
2534
                on_event_connected(*event, address.c_str());
2✔
2535
                break;
2✔
2536
            case ZMQ_EVENT_CONNECT_DELAYED:
2✔
2537
                on_event_connect_delayed(*event, address.c_str());
2✔
2538
                break;
2✔
2539
            case ZMQ_EVENT_CONNECT_RETRIED:
×
2540
                on_event_connect_retried(*event, address.c_str());
×
2541
                break;
×
2542
            case ZMQ_EVENT_LISTENING:
×
2543
                on_event_listening(*event, address.c_str());
×
2544
                break;
×
2545
            case ZMQ_EVENT_BIND_FAILED:
×
2546
                on_event_bind_failed(*event, address.c_str());
×
2547
                break;
×
2548
            case ZMQ_EVENT_ACCEPTED:
1✔
2549
                on_event_accepted(*event, address.c_str());
1✔
2550
                break;
1✔
2551
            case ZMQ_EVENT_ACCEPT_FAILED:
×
2552
                on_event_accept_failed(*event, address.c_str());
×
2553
                break;
×
2554
            case ZMQ_EVENT_CLOSED:
×
2555
                on_event_closed(*event, address.c_str());
×
2556
                break;
×
2557
            case ZMQ_EVENT_CLOSE_FAILED:
×
2558
                on_event_close_failed(*event, address.c_str());
×
2559
                break;
×
2560
            case ZMQ_EVENT_DISCONNECTED:
1✔
2561
                on_event_disconnected(*event, address.c_str());
1✔
2562
                break;
1✔
2563
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 3, 0) || (defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3))
2564
            case ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL:
×
2565
                on_event_handshake_failed_no_detail(*event, address.c_str());
×
2566
                break;
×
2567
            case ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL:
×
2568
                on_event_handshake_failed_protocol(*event, address.c_str());
×
2569
                break;
×
2570
            case ZMQ_EVENT_HANDSHAKE_FAILED_AUTH:
×
2571
                on_event_handshake_failed_auth(*event, address.c_str());
×
2572
                break;
×
2573
            case ZMQ_EVENT_HANDSHAKE_SUCCEEDED:
×
2574
                on_event_handshake_succeeded(*event, address.c_str());
×
2575
                break;
×
2576
#elif defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 1)
2577
            case ZMQ_EVENT_HANDSHAKE_FAILED:
2578
                on_event_handshake_failed(*event, address.c_str());
2579
                break;
2580
            case ZMQ_EVENT_HANDSHAKE_SUCCEED:
2581
                on_event_handshake_succeed(*event, address.c_str());
2582
                break;
2583
#endif
2584
            default:
×
2585
                on_event_unknown(*event, address.c_str());
×
2586
                break;
×
2587
        }
2588

2589
        return true;
6✔
2590
    }
2591

2592
    socket_ref monitor_socket() {return _monitor_socket;}
1✔
2593

2594
  private:
2595
    monitor_t(const monitor_t &) ZMQ_DELETED_FUNCTION;
2596
    void operator=(const monitor_t &) ZMQ_DELETED_FUNCTION;
2597

2598
    socket_ref _socket;
2599
    socket_t _monitor_socket;
2600

2601
    void close() ZMQ_NOTHROW
18✔
2602
    {
2603
        if (_socket)
18✔
2604
            zmq_socket_monitor(_socket.handle(), ZMQ_NULLPTR, 0);
7✔
2605
        _monitor_socket.close();
18✔
2606
    }
18✔
2607
};
2608

2609
#if defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER)
2610

2611
// polling events
2612
enum class event_flags : short
2613
{
2614
    none = 0,
2615
    pollin = ZMQ_POLLIN,
2616
    pollout = ZMQ_POLLOUT,
2617
    pollerr = ZMQ_POLLERR,
2618
    pollpri = ZMQ_POLLPRI
2619
};
2620

2621
constexpr event_flags operator|(event_flags a, event_flags b) noexcept
8✔
2622
{
2623
    return detail::enum_bit_or(a, b);
8✔
2624
}
2625
constexpr event_flags operator&(event_flags a, event_flags b) noexcept
5✔
2626
{
2627
    return detail::enum_bit_and(a, b);
5✔
2628
}
2629
constexpr event_flags operator^(event_flags a, event_flags b) noexcept
1✔
2630
{
2631
    return detail::enum_bit_xor(a, b);
1✔
2632
}
2633
constexpr event_flags operator~(event_flags a) noexcept
2✔
2634
{
2635
    return detail::enum_bit_not(a);
2✔
2636
}
2637

2638
struct no_user_data;
2639

2640
// layout compatible with zmq_poller_event_t
2641
template<class T = no_user_data> struct poller_event
2642
{
2643
    socket_ref socket;
2644
    ::zmq::fd_t fd;
2645
    T *user_data;
2646
    event_flags events;
2647
};
2648

2649
template<typename T = no_user_data> class poller_t
2650
{
2651
  public:
2652
    using event_type = poller_event<T>;
2653

2654
    poller_t() : poller_ptr(zmq_poller_new())
67✔
2655
    {
2656
        if (!poller_ptr)
67✔
2657
            throw error_t();
×
2658
    }
67✔
2659

2660
    template<
2661
      typename Dummy = void,
2662
      typename =
2663
        typename std::enable_if<!std::is_same<T, no_user_data>::value, Dummy>::type>
2664
    void add(zmq::socket_ref socket, event_flags events, T *user_data)
38✔
2665
    {
2666
        add_impl(socket, events, user_data);
38✔
2667
    }
36✔
2668

2669
    void add(zmq::socket_ref socket, event_flags events)
24✔
2670
    {
2671
        add_impl(socket, events, nullptr);
24✔
2672
    }
21✔
2673

2674
    template<
2675
      typename Dummy = void,
2676
      typename =
2677
        typename std::enable_if<!std::is_same<T, no_user_data>::value, Dummy>::type>
2678
    void add(fd_t fd, event_flags events, T *user_data)
3✔
2679
    {
2680
        add_impl(fd, events, user_data);
3✔
2681
    }
3✔
2682

2683
    void add(fd_t fd, event_flags events) { add_impl(fd, events, nullptr); }
2684

2685
    void remove(zmq::socket_ref socket)
21✔
2686
    {
2687
        if (0 != zmq_poller_remove(poller_ptr.get(), socket.handle())) {
21✔
2688
            throw error_t();
4✔
2689
        }
2690
    }
17✔
2691

2692
    void remove(fd_t fd)
2✔
2693
    {
2694
        if (0 != zmq_poller_remove_fd(poller_ptr.get(), fd)) {
2✔
2695
            throw error_t();
1✔
2696
        }
2697
    }
1✔
2698

2699
    void modify(zmq::socket_ref socket, event_flags events)
10✔
2700
    {
2701
        if (0
10✔
2702
            != zmq_poller_modify(poller_ptr.get(), socket.handle(),
10✔
2703
                                 static_cast<short>(events))) {
2704
            throw error_t();
6✔
2705
        }
2706
    }
4✔
2707

2708
    void modify(fd_t fd, event_flags events)
2709
    {
2710
        if (0
2711
            != zmq_poller_modify_fd(poller_ptr.get(), fd,
2712
                                 static_cast<short>(events))) {
2713
            throw error_t();
2714
        }
2715
    }
2716

2717
    size_t wait_all(std::vector<event_type> &poller_events,
31✔
2718
                    const std::chrono::milliseconds timeout)
2719
    {
2720
        int rc = zmq_poller_wait_all(
31✔
2721
          poller_ptr.get(),
2722
          reinterpret_cast<zmq_poller_event_t *>(poller_events.data()),
31✔
2723
          static_cast<int>(poller_events.size()),
31✔
2724
          static_cast<long>(timeout.count()));
31✔
2725
        if (rc > 0)
31✔
2726
            return static_cast<size_t>(rc);
25✔
2727

2728
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3)
2729
        if (zmq_errno() == EAGAIN)
6✔
2730
#else
2731
        if (zmq_errno() == ETIMEDOUT)
2732
#endif
2733
            return 0;
×
2734

2735
        throw error_t();
6✔
2736
    }
2737

2738
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 3, 3)
2739
    size_t size() const noexcept
3✔
2740
    {
2741
        int rc = zmq_poller_size(const_cast<void *>(poller_ptr.get()));
3✔
2742
        ZMQ_ASSERT(rc >= 0);
3✔
2743
        return static_cast<size_t>(std::max(rc, 0));
3✔
2744
    }
2745
#endif
2746

2747
  private:
2748
    struct destroy_poller_t
2749
    {
2750
        void operator()(void *ptr) noexcept
67✔
2751
        {
2752
            int rc = zmq_poller_destroy(&ptr);
67✔
2753
            ZMQ_ASSERT(rc == 0);
67✔
2754
        }
67✔
2755
    };
2756

2757
    std::unique_ptr<void, destroy_poller_t> poller_ptr;
2758

2759
    void add_impl(zmq::socket_ref socket, event_flags events, T *user_data)
62✔
2760
    {
2761
        if (0
62✔
2762
            != zmq_poller_add(poller_ptr.get(), socket.handle(), user_data,
62✔
2763
                              static_cast<short>(events))) {
2764
            throw error_t();
5✔
2765
        }
2766
    }
57✔
2767

2768
    void add_impl(fd_t fd, event_flags events, T *user_data)
3✔
2769
    {
2770
        if (0
3✔
2771
            != zmq_poller_add_fd(poller_ptr.get(), fd, user_data,
3✔
2772
                                 static_cast<short>(events))) {
2773
            throw error_t();
×
2774
        }
2775
    }
3✔
2776
};
2777
#endif //  defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER)
2778

2779
inline std::ostream &operator<<(std::ostream &os, const message_t &msg)
×
2780
{
2781
    return os << msg.str();
×
2782
}
2783

2784
} // namespace zmq
2785

2786
#endif // __ZMQ_HPP_INCLUDED__
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc