options.cpp 26.7 KB
Newer Older
1
/*
2
    Copyright (c) 2007-2015 Contributors as noted in the AUTHORS file
3

4
    This file is part of libzmq, the ZeroMQ core engine in C++.
5

6 7 8
    libzmq is free software; you can redistribute it and/or modify it under
    the terms of the GNU Lesser General Public License (LGPL) as published
    by the Free Software Foundation; either version 3 of the License, or
9 10
    (at your option) any later version.

11 12 13 14 15 16 17 18 19 20 21 22 23 24
    As a special exception, the Contributors give you permission to link
    this library with independent modules to produce an executable,
    regardless of the license terms of these independent modules, and to
    copy and distribute the resulting executable under terms of your choice,
    provided that you also meet, for each linked independent module, the
    terms and conditions of the license of that module. An independent
    module is a module which is not derived from or based on this library.
    If you modify this library, you must extend this exception to your
    version of the library.

    libzmq is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
    License for more details.
25

26
    You should have received a copy of the GNU Lesser General Public License
27 28 29
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

30 31
#include <string.h>

32
#include "options.hpp"
33
#include "err.hpp"
34
#include "../include/zmq_utils.h"
35 36

zmq::options_t::options_t () :
37 38
    sndhwm (1000),
    rcvhwm (1000),
malosek's avatar
malosek committed
39
    affinity (0),
40
    identity_size (0),
41
    rate (100),
42
    recovery_ivl (10000),
43
    multicast_hops (1),
44 45
    sndbuf (-1),
    rcvbuf (-1),
46
    tos (0),
47
    type (-1),
48
    linger (-1),
49
    reconnect_ivl (100),
50
    reconnect_ivl_max (0),
51
    backlog (100),
52
    maxmsgsize (-1),
53 54
    rcvtimeo (-1),
    sndtimeo (-1),
Pieter Hintjens's avatar
Pieter Hintjens committed
55
    ipv6 (0),
56
    immediate (0),
57
    filter (false),
58
    invert_matching(false),
59
    recv_identity (false),
60 61
    raw_socket (false),
    raw_notify (false),
62 63 64 65
    tcp_keepalive (-1),
    tcp_keepalive_cnt (-1),
    tcp_keepalive_idle (-1),
    tcp_keepalive_intvl (-1),
66
    mechanism (ZMQ_NULL),
67
    as_server (0),
68
    gss_plaintext (false),
danielkr's avatar
danielkr committed
69
    socket_id (0),
70
    conflate (false),
71
    handshake_ivl (30000),
Jonathan Reams's avatar
Jonathan Reams committed
72 73 74
    connected (false),
    heartbeat_ttl (0),
    heartbeat_interval (0),
75
    heartbeat_timeout (-1)
76 77
{
}
78 79 80 81

int zmq::options_t::setsockopt (int option_, const void *optval_,
    size_t optvallen_)
{
82 83
    bool is_int = (optvallen_ == sizeof (int));
    int value = is_int? *((int *) optval_): 0;
84
#if defined (ZMQ_ACT_MILITANT)
85
    bool malformed = true;          //  Did caller pass a bad option value?
86
#endif
87

88
    switch (option_) {
89
        case ZMQ_SNDHWM:
90
            if (is_int && value >= 0) {
91
                sndhwm = value;
92 93
                return 0;
            }
94
            break;
95

96
        case ZMQ_RCVHWM:
97
            if (is_int && value >= 0) {
98
                rcvhwm = value;
99 100
                return 0;
            }
101
            break;
102

103
        case ZMQ_AFFINITY:
104
            if (optvallen_ == sizeof (uint64_t)) {
105
                affinity = *((uint64_t*) optval_);
106 107
                return 0;
            }
108 109 110
            break;

        case ZMQ_IDENTITY:
111 112
            //  Identity is any binary string from 1 to 255 octets
            if (optvallen_ > 0 && optvallen_ < 256) {
113
                identity_size = (unsigned char) optvallen_;
114
                memcpy (identity, optval_, identity_size);
115
                return 0;
116 117
            }
            break;
118

119
        case ZMQ_RATE:
120
            if (is_int && value > 0) {
121
                rate = value;
122 123
                return 0;
            }
124
            break;
125

126
        case ZMQ_RECOVERY_IVL:
127
            if (is_int && value >= 0) {
128
                recovery_ivl = value;
129 130 131
                return 0;
            }
            break;
132

133
        case ZMQ_SNDBUF:
134
            if (is_int && value >= 0) {
135
                sndbuf = value;
136 137
                return 0;
            }
138
            break;
139

140
        case ZMQ_RCVBUF:
141
            if (is_int && value >= 0) {
142
                rcvbuf = value;
143 144
                return 0;
            }
145
            break;
146

147 148 149 150 151 152 153
        case ZMQ_TOS:
            if (is_int && value >= 0) {
                tos = value;
                return 0;
            }
            break;

154
        case ZMQ_LINGER:
155
            if (is_int && value >= -1) {
156
                linger = value;
157 158
                return 0;
            }
159
            break;
160

161
        case ZMQ_RECONNECT_IVL:
162
            if (is_int && value >= -1) {
163
                reconnect_ivl = value;
164 165
                return 0;
            }
166
            break;
167

168
        case ZMQ_RECONNECT_IVL_MAX:
169
            if (is_int && value >= 0) {
170
                reconnect_ivl_max = value;
171 172
                return 0;
            }
173
            break;
174

175
        case ZMQ_BACKLOG:
176
            if (is_int && value >= 0) {
177
                backlog = value;
178 179
                return 0;
            }
180
            break;
181

182
        case ZMQ_MAXMSGSIZE:
183
            if (optvallen_ == sizeof (int64_t)) {
184
                maxmsgsize = *((int64_t *) optval_);
185 186
                return 0;
            }
187
            break;
188

189
        case ZMQ_MULTICAST_HOPS:
190
            if (is_int && value > 0) {
191
                multicast_hops = value;
192 193
                return 0;
            }
194
            break;
195

196
        case ZMQ_RCVTIMEO:
197
            if (is_int && value >= -1) {
198
                rcvtimeo = value;
199 200
                return 0;
            }
201
            break;
202

203
        case ZMQ_SNDTIMEO:
204
            if (is_int && value >= -1) {
205
                sndtimeo = value;
206 207
                return 0;
            }
208
            break;
209

Pieter Hintjens's avatar
Pieter Hintjens committed
210
        /*  Deprecated in favor of ZMQ_IPV6  */
211
        case ZMQ_IPV4ONLY:
212
            if (is_int && (value == 0 || value == 1)) {
213
                ipv6 = (value == 0);
214 215
                return 0;
            }
216
            break;
217

218 219
        /*  To replace the somewhat surprising IPV4ONLY */
        case ZMQ_IPV6:
220
            if (is_int && (value == 0 || value == 1)) {
221
                ipv6 = (value != 0);
222 223
                return 0;
            }
224
            break;
225

226 227 228 229 230 231 232 233 234 235 236 237 238
        case ZMQ_SOCKS_PROXY:
            if (optval_ == NULL && optvallen_ == 0) {
                socks_proxy_address.clear ();
                return 0;
            }
            else
            if (optval_ != NULL && optvallen_ > 0 ) {
                socks_proxy_address =
                    std::string ((const char *) optval_, optvallen_);
                return 0;
            }
            break;

239
        case ZMQ_TCP_KEEPALIVE:
240
            if (is_int && (value == -1 || value == 0 || value == 1)) {
241
                tcp_keepalive = value;
242 243
                return 0;
            }
244
            break;
245

246
        case ZMQ_TCP_KEEPALIVE_CNT:
247
            if (is_int && (value == -1 || value >= 0)) {
248
                tcp_keepalive_cnt = value;
249 250
                return 0;
            }
251
            break;
252

253
        case ZMQ_TCP_KEEPALIVE_IDLE:
254
            if (is_int && (value == -1 || value >= 0)) {
255
                tcp_keepalive_idle = value;
256 257
                return 0;
            }
258
            break;
259

260
        case ZMQ_TCP_KEEPALIVE_INTVL:
261
            if (is_int && (value == -1 || value >= 0)) {
262
                tcp_keepalive_intvl = value;
263 264
                return 0;
            }
265
            break;
266

267
        case ZMQ_IMMEDIATE:
268
            if (is_int && (value == 0 || value == 1)) {
269
                immediate = value;
270 271
                return 0;
            }
272
            break;
273

274
        case ZMQ_TCP_ACCEPT_FILTER:
275
            if (optvallen_ == 0 && optval_ == NULL) {
276
                tcp_accept_filters.clear ();
277 278
                return 0;
            }
279
            else
280
            if (optvallen_ > 0 && optvallen_ < 256 && optval_ != NULL && *((const char*) optval_) != 0) {
281
                std::string filter_str ((const char *) optval_, optvallen_);
282
                tcp_address_mask_t mask;
Pieter Hintjens's avatar
Pieter Hintjens committed
283
                int rc = mask.resolve (filter_str.c_str (), ipv6);
284
                if (rc == 0) {
285
                    tcp_accept_filters.push_back (mask);
286 287 288 289
                    return 0;
                }
            }
            break;
290

291
#       if defined ZMQ_HAVE_SO_PEERCRED || defined ZMQ_HAVE_LOCAL_PEERCRED
292
        case ZMQ_IPC_FILTER_UID:
293 294 295 296 297 298 299 300 301 302 303
            if (optvallen_ == 0 && optval_ == NULL) {
                ipc_uid_accept_filters.clear ();
                return 0;
            }
            else
            if (optvallen_ == sizeof (uid_t) && optval_ != NULL) {
                ipc_uid_accept_filters.insert (*((uid_t *) optval_));
                return 0;
            }
            break;

304
        case ZMQ_IPC_FILTER_GID:
305 306 307 308 309 310 311 312 313 314 315 316 317
            if (optvallen_ == 0 && optval_ == NULL) {
                ipc_gid_accept_filters.clear ();
                return 0;
            }
            else
            if (optvallen_ == sizeof (gid_t) && optval_ != NULL) {
                ipc_gid_accept_filters.insert (*((gid_t *) optval_));
                return 0;
            }
            break;
#       endif

#       if defined ZMQ_HAVE_SO_PEERCRED
318
        case ZMQ_IPC_FILTER_PID:
319 320 321 322 323 324 325 326 327 328 329 330
            if (optvallen_ == 0 && optval_ == NULL) {
                ipc_pid_accept_filters.clear ();
                return 0;
            }
            else
            if (optvallen_ == sizeof (pid_t) && optval_ != NULL) {
                ipc_pid_accept_filters.insert (*((pid_t *) optval_));
                return 0;
            }
            break;
#       endif

331 332
        case ZMQ_PLAIN_SERVER:
            if (is_int && (value == 0 || value == 1)) {
333
                as_server = value;
334
                mechanism = value? ZMQ_PLAIN: ZMQ_NULL;
335 336 337
                return 0;
            }
            break;
338

339 340 341 342 343 344
        case ZMQ_PLAIN_USERNAME:
            if (optvallen_ == 0 && optval_ == NULL) {
                mechanism = ZMQ_NULL;
                return 0;
            }
            else
345
            if (optvallen_ > 0 && optvallen_ < 256 && optval_ != NULL) {
346
                plain_username.assign ((const char *) optval_, optvallen_);
347
                as_server = 0;
348 349 350 351
                mechanism = ZMQ_PLAIN;
                return 0;
            }
            break;
352

353 354 355 356 357 358
        case ZMQ_PLAIN_PASSWORD:
            if (optvallen_ == 0 && optval_ == NULL) {
                mechanism = ZMQ_NULL;
                return 0;
            }
            else
359
            if (optvallen_ > 0 && optvallen_ < 256 && optval_ != NULL) {
360
                plain_password.assign ((const char *) optval_, optvallen_);
361
                as_server = 0;
362 363
                mechanism = ZMQ_PLAIN;
                return 0;
364
            }
365
            break;
366 367

        case ZMQ_ZAP_DOMAIN:
368
            if (optvallen_ < 256) {
369 370 371 372 373
                zap_domain.assign ((const char *) optval_, optvallen_);
                return 0;
            }
            break;

Pieter Hintjens's avatar
Pieter Hintjens committed
374
        //  If libsodium isn't installed, these options provoke EINVAL
375
#       ifdef HAVE_LIBSODIUM
376
        case ZMQ_CURVE_SERVER:
377
            if (is_int && (value == 0 || value == 1)) {
378
                as_server = value;
379
                mechanism = value? ZMQ_CURVE: ZMQ_NULL;
380 381 382
                return 0;
            }
            break;
383

384
        case ZMQ_CURVE_PUBLICKEY:
385 386 387
            //  TODO: refactor repeated code for these three options
            //  into set_curve_key (destination, optval, optlen) method
            //  ==> set_curve_key (curve_public_key, optval_, optvallen_);
388 389 390 391 392 393
            if (optvallen_ == CURVE_KEYSIZE) {
                memcpy (curve_public_key, optval_, CURVE_KEYSIZE);
                mechanism = ZMQ_CURVE;
                return 0;
            }
            else
394
            if (optvallen_ == CURVE_KEYSIZE_Z85 + 1) {
395 396 397 398
                if (zmq_z85_decode (curve_public_key, (char *) optval_)) {
                    mechanism = ZMQ_CURVE;
                    return 0;
                }
399
            }
400 401 402
            else
            //  Deprecated, not symmetrical with zmq_getsockopt
            if (optvallen_ == CURVE_KEYSIZE_Z85) {
403
                char z85_key [CURVE_KEYSIZE_Z85 + 1];
404 405
                memcpy (z85_key, (char *) optval_, CURVE_KEYSIZE_Z85);
                z85_key [CURVE_KEYSIZE_Z85] = 0;
406 407 408 409
                if (zmq_z85_decode (curve_public_key, z85_key)) {
                    mechanism = ZMQ_CURVE;
                    return 0;
                }
410
            }
411
            break;
412

413 414 415 416 417 418 419
        case ZMQ_CURVE_SECRETKEY:
            if (optvallen_ == CURVE_KEYSIZE) {
                memcpy (curve_secret_key, optval_, CURVE_KEYSIZE);
                mechanism = ZMQ_CURVE;
                return 0;
            }
            else
420
            if (optvallen_ == CURVE_KEYSIZE_Z85 + 1) {
421 422 423 424
                if (zmq_z85_decode (curve_secret_key, (char *) optval_)) {
                    mechanism = ZMQ_CURVE;
                    return 0;
                }
425
            }
426 427 428
            else
            //  Deprecated, not symmetrical with zmq_getsockopt
            if (optvallen_ == CURVE_KEYSIZE_Z85) {
429
                char z85_key [CURVE_KEYSIZE_Z85 + 1];
430 431
                memcpy (z85_key, (char *) optval_, CURVE_KEYSIZE_Z85);
                z85_key [CURVE_KEYSIZE_Z85] = 0;
432 433 434 435
                if (zmq_z85_decode (curve_secret_key, z85_key)) {
                    mechanism = ZMQ_CURVE;
                    return 0;
                }
436
            }
437 438
            break;

439 440 441 442
        case ZMQ_CURVE_SERVERKEY:
            if (optvallen_ == CURVE_KEYSIZE) {
                memcpy (curve_server_key, optval_, CURVE_KEYSIZE);
                mechanism = ZMQ_CURVE;
443
                as_server = 0;
444 445 446
                return 0;
            }
            else
447
            if (optvallen_ == CURVE_KEYSIZE_Z85 + 1) {
448 449 450 451 452
                if (zmq_z85_decode (curve_server_key, (char *) optval_)) {
                    mechanism = ZMQ_CURVE;
                    as_server = 0;
                    return 0;
                }
453 454 455 456
            }
            else
            //  Deprecated, not symmetrical with zmq_getsockopt
            if (optvallen_ == CURVE_KEYSIZE_Z85) {
457
                char z85_key [CURVE_KEYSIZE_Z85 + 1];
458 459
                memcpy (z85_key, (char *) optval_, CURVE_KEYSIZE_Z85);
                z85_key [CURVE_KEYSIZE_Z85] = 0;
460 461 462 463 464
                if (zmq_z85_decode (curve_server_key, z85_key)) {
                    mechanism = ZMQ_CURVE;
                    as_server = 0;
                    return 0;
                }
465
            }
466
            break;
467
#       endif
Martin Hurton's avatar
Martin Hurton committed
468

danielkr's avatar
danielkr committed
469 470 471 472 473 474
        case ZMQ_CONFLATE:
            if (is_int && (value == 0 || value == 1)) {
                conflate = (value != 0);
                return 0;
            }
            break;
475 476 477

        //  If libgssapi isn't installed, these options provoke EINVAL
#       ifdef HAVE_LIBGSSAPI_KRB5
478 479 480 481 482 483 484
        case ZMQ_GSSAPI_SERVER:
            if (is_int && (value == 0 || value == 1)) {
                as_server = value;
                mechanism = ZMQ_GSSAPI;
                return 0;
            }
            break;
485

Chris Busbey's avatar
Chris Busbey committed
486
        case ZMQ_GSSAPI_PRINCIPAL:
487
            if (optvallen_ > 0 && optvallen_ < 256 && optval_ != NULL) {
Chris Busbey's avatar
Chris Busbey committed
488
                gss_principal.assign ((const char *) optval_, optvallen_);
489 490 491 492 493
                mechanism = ZMQ_GSSAPI;
                return 0;
            }
            break;

Chris Busbey's avatar
Chris Busbey committed
494
        case ZMQ_GSSAPI_SERVICE_PRINCIPAL:
495
            if (optvallen_ > 0 && optvallen_ < 256 && optval_ != NULL) {
Chris Busbey's avatar
Chris Busbey committed
496
                gss_service_principal.assign ((const char *) optval_, optvallen_);
497
                mechanism = ZMQ_GSSAPI;
Chris Busbey's avatar
Chris Busbey committed
498
                as_server = 0;
499 500 501
                return 0;
            }
            break;
danielkr's avatar
danielkr committed
502

503 504 505 506 507 508
        case ZMQ_GSSAPI_PLAINTEXT:
            if (is_int && (value == 0 || value == 1)) {
                gss_plaintext = (value != 0);
                return 0;
            }
            break;
509 510
#       endif

511 512 513 514 515 516 517
        case ZMQ_HANDSHAKE_IVL:
            if (is_int && value >= 0) {
                handshake_ivl = value;
                return 0;
            }
            break;

518 519 520 521 522 523 524
        case ZMQ_INVERT_MATCHING:
            if (is_int) {
                invert_matching = (value != 0);
                return 0;
            }
            break;

Jonathan Reams's avatar
Jonathan Reams committed
525 526 527 528 529 530 531 532
        case ZMQ_HEARTBEAT_IVL:
            if (is_int && value >= 0) {
                heartbeat_interval = value;
                return 0;
            }
            break;

        case ZMQ_HEARTBEAT_TTL:
533 534 535
            // Convert this to deciseconds from milliseconds
            value = value / 100;
            if (is_int && value >= 0 && value <= 6553) {
Jonathan Reams's avatar
Jonathan Reams committed
536 537 538 539 540 541 542 543 544 545 546 547
                heartbeat_ttl = (uint16_t)value;
                return 0;
            }
            break;

        case ZMQ_HEARTBEAT_TIMEOUT:
            if (is_int && value >= 0) {
                heartbeat_timeout = value;
                return 0;
            }
            break;

danielkr's avatar
danielkr committed
548
        default:
549
#if defined (ZMQ_ACT_MILITANT)
550 551 552 553 554
            //  There are valid scenarios for probing with unknown socket option
            //  values, e.g. to check if security is enabled or not. This will not
            //  provoke a militant assert. However, passing bad values to a valid
            //  socket option will, if ZMQ_ACT_MILITANT is defined.
            malformed = false;
555
#endif
danielkr's avatar
danielkr committed
556
            break;
557
    }
558 559 560 561 562 563 564
#if defined (ZMQ_ACT_MILITANT)
    //  There is no valid use case for passing an error back to the application
    //  when it sent malformed arguments to a socket option. Use ./configure
    //  --with-militant to enable this checking.
    if (malformed)
        zmq_assert (false);
#endif
565 566
    errno = EINVAL;
    return -1;
567
}
568

569
int zmq::options_t::getsockopt (int option_, void *optval_, size_t *optvallen_) const
570
{
571 572
    bool is_int = (*optvallen_ == sizeof (int));
    int *value = (int *) optval_;
573 574 575
#if defined (ZMQ_ACT_MILITANT)
    bool malformed = true;          //  Did caller pass a bad option value?
#endif
576

577
    switch (option_) {
578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634
        case ZMQ_SNDHWM:
            if (is_int) {
                *value = sndhwm;
                return 0;
            }
            break;

        case ZMQ_RCVHWM:
            if (is_int) {
                *value = rcvhwm;
                return 0;
            }
            break;

        case ZMQ_AFFINITY:
            if (*optvallen_ == sizeof (uint64_t)) {
                *((uint64_t *) optval_) = affinity;
                return 0;
            }
            break;

        case ZMQ_IDENTITY:
            if (*optvallen_ >= identity_size) {
                memcpy (optval_, identity, identity_size);
                *optvallen_ = identity_size;
                return 0;
            }
            break;

        case ZMQ_RATE:
            if (is_int) {
                *value = rate;
                return 0;
            }
            break;

        case ZMQ_RECOVERY_IVL:
            if (is_int) {
                *value = recovery_ivl;
                return 0;
            }
            break;

        case ZMQ_SNDBUF:
            if (is_int) {
                *value = sndbuf;
                return 0;
            }
            break;

        case ZMQ_RCVBUF:
            if (is_int) {
                *value = rcvbuf;
                return 0;
            }
            break;

635 636 637 638 639 640
        case ZMQ_TOS:
            if (is_int) {
                *value = tos;
                return 0;
            }
            break;
Martin Hurton's avatar
Martin Hurton committed
641

642 643 644 645 646 647 648 649 650 651 652 653 654
        case ZMQ_TYPE:
            if (is_int) {
                *value = type;
                return 0;
            }
            break;

        case ZMQ_LINGER:
            if (is_int) {
                *value = linger;
                return 0;
            }
            break;
655

656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711
        case ZMQ_RECONNECT_IVL:
            if (is_int) {
                *value = reconnect_ivl;
                return 0;
            }
            break;

        case ZMQ_RECONNECT_IVL_MAX:
            if (is_int) {
                *value = reconnect_ivl_max;
                return 0;
            }
            break;

        case ZMQ_BACKLOG:
            if (is_int) {
                *value = backlog;
                return 0;
            }
            break;

        case ZMQ_MAXMSGSIZE:
            if (*optvallen_ == sizeof (int64_t)) {
                *((int64_t *) optval_) = maxmsgsize;
                *optvallen_ = sizeof (int64_t);
                return 0;
            }
            break;

        case ZMQ_MULTICAST_HOPS:
            if (is_int) {
                *value = multicast_hops;
                return 0;
            }
            break;

        case ZMQ_RCVTIMEO:
            if (is_int) {
                *value = rcvtimeo;
                return 0;
            }
            break;

        case ZMQ_SNDTIMEO:
            if (is_int) {
                *value = sndtimeo;
                return 0;
            }
            break;

        case ZMQ_IPV4ONLY:
            if (is_int) {
                *value = 1 - ipv6;
                return 0;
            }
            break;
712

713 714 715 716 717 718 719 720 721 722 723 724 725 726
        case ZMQ_IPV6:
            if (is_int) {
                *value = ipv6;
                return 0;
            }
            break;

        case ZMQ_IMMEDIATE:
            if (is_int) {
                *value = immediate;
                return 0;
            }
            break;

727 728 729 730 731 732 733 734
        case ZMQ_SOCKS_PROXY:
            if (*optvallen_ >= socks_proxy_address.size () + 1) {
                memcpy (optval_, socks_proxy_address.c_str (), socks_proxy_address.size () + 1);
                *optvallen_ = socks_proxy_address.size () + 1;
                return 0;
            }
            break;

735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768
        case ZMQ_TCP_KEEPALIVE:
            if (is_int) {
                *value = tcp_keepalive;
                return 0;
            }
            break;

        case ZMQ_TCP_KEEPALIVE_CNT:
            if (is_int) {
                *value = tcp_keepalive_cnt;
                return 0;
            }
            break;

        case ZMQ_TCP_KEEPALIVE_IDLE:
            if (is_int) {
                *value = tcp_keepalive_idle;
                return 0;
            }
            break;

        case ZMQ_TCP_KEEPALIVE_INTVL:
            if (is_int) {
                *value = tcp_keepalive_intvl;
                return 0;
            }
            break;

        case ZMQ_MECHANISM:
            if (is_int) {
                *value = mechanism;
                return 0;
            }
            break;
769

770
        case ZMQ_PLAIN_SERVER:
771
            if (is_int) {
772
                *value = as_server && mechanism == ZMQ_PLAIN;
773 774 775
                return 0;
            }
            break;
776

777 778 779 780 781 782 783
        case ZMQ_PLAIN_USERNAME:
            if (*optvallen_ >= plain_username.size () + 1) {
                memcpy (optval_, plain_username.c_str (), plain_username.size () + 1);
                *optvallen_ = plain_username.size () + 1;
                return 0;
            }
            break;
784

785 786 787 788 789 790 791
        case ZMQ_PLAIN_PASSWORD:
            if (*optvallen_ >= plain_password.size () + 1) {
                memcpy (optval_, plain_password.c_str (), plain_password.size () + 1);
                *optvallen_ = plain_password.size () + 1;
                return 0;
            }
            break;
792 793 794 795 796 797 798 799 800

        case ZMQ_ZAP_DOMAIN:
            if (*optvallen_ >= zap_domain.size () + 1) {
                memcpy (optval_, zap_domain.c_str (), zap_domain.size () + 1);
                *optvallen_ = zap_domain.size () + 1;
                return 0;
            }
            break;

Pieter Hintjens's avatar
Pieter Hintjens committed
801
        //  If libsodium isn't installed, these options provoke EINVAL
802
#       ifdef HAVE_LIBSODIUM
803
        case ZMQ_CURVE_SERVER:
804
            if (is_int) {
805
                *value = as_server && mechanism == ZMQ_CURVE;
806 807 808
                return 0;
            }
            break;
809

810 811 812 813 814 815 816 817 818 819
        case ZMQ_CURVE_PUBLICKEY:
            if (*optvallen_ == CURVE_KEYSIZE) {
                memcpy (optval_, curve_public_key, CURVE_KEYSIZE);
                return 0;
            }
            else
            if (*optvallen_ == CURVE_KEYSIZE_Z85 + 1) {
                zmq_z85_encode ((char *) optval_, curve_public_key, CURVE_KEYSIZE);
                return 0;
            }
820
            break;
821

822 823 824 825 826 827 828 829 830 831
        case ZMQ_CURVE_SECRETKEY:
            if (*optvallen_ == CURVE_KEYSIZE) {
                memcpy (optval_, curve_secret_key, CURVE_KEYSIZE);
                return 0;
            }
            else
            if (*optvallen_ == CURVE_KEYSIZE_Z85 + 1) {
                zmq_z85_encode ((char *) optval_, curve_secret_key, CURVE_KEYSIZE);
                return 0;
            }
832 833
            break;

834 835 836 837 838 839 840 841 842 843
        case ZMQ_CURVE_SERVERKEY:
            if (*optvallen_ == CURVE_KEYSIZE) {
                memcpy (optval_, curve_server_key, CURVE_KEYSIZE);
                return 0;
            }
            else
            if (*optvallen_ == CURVE_KEYSIZE_Z85 + 1) {
                zmq_z85_encode ((char *) optval_, curve_server_key, CURVE_KEYSIZE);
                return 0;
            }
844
            break;
845
#       endif
danielkr's avatar
danielkr committed
846 847 848 849 850 851 852

        case ZMQ_CONFLATE:
            if (is_int) {
                *value = conflate;
                return 0;
            }
            break;
Martin Hurton's avatar
Martin Hurton committed
853

854 855
        //  If libgssapi isn't installed, these options provoke EINVAL
#       ifdef HAVE_LIBGSSAPI_KRB5
856 857 858 859 860 861
        case ZMQ_GSSAPI_SERVER:
            if (is_int) {
                *value = as_server && mechanism == ZMQ_GSSAPI;
                return 0;
            }
            break;
862

Chris Busbey's avatar
Chris Busbey committed
863 864 865 866
        case ZMQ_GSSAPI_PRINCIPAL:
            if (*optvallen_ >= gss_principal.size () + 1) {
                memcpy (optval_, gss_principal.c_str (), gss_principal.size () + 1);
                *optvallen_ = gss_principal.size () + 1;
867 868 869
                return 0;
            }
            break;
danielkr's avatar
danielkr committed
870

Chris Busbey's avatar
Chris Busbey committed
871 872 873 874
        case ZMQ_GSSAPI_SERVICE_PRINCIPAL:
            if (*optvallen_ >= gss_service_principal.size () + 1) {
                memcpy (optval_, gss_service_principal.c_str (), gss_service_principal.size () + 1);
                *optvallen_ = gss_service_principal.size () + 1;
875 876 877
                return 0;
            }
            break;
878

879 880 881 882 883 884
        case ZMQ_GSSAPI_PLAINTEXT:
            if (is_int) {
                *value = gss_plaintext;
                return 0;
            }
            break;
885 886
#endif

887 888 889 890 891 892
        case ZMQ_HANDSHAKE_IVL:
            if (is_int) {
                *value = handshake_ivl;
                return 0;
            }
            break;
893

894 895 896 897 898 899 900
        case ZMQ_INVERT_MATCHING:
            if (is_int) {
                *value = invert_matching;
                return 0;
            }
            break;

Jonathan Reams's avatar
Jonathan Reams committed
901 902 903 904 905 906 907 908 909
        case ZMQ_HEARTBEAT_IVL:
            if (is_int) {
                *value = heartbeat_interval;
                return 0;
            }
            break;

        case ZMQ_HEARTBEAT_TTL:
            if (is_int) {
910 911
                // Convert the internal deciseconds value to milliseconds
                *value = heartbeat_ttl * 100;
Jonathan Reams's avatar
Jonathan Reams committed
912 913 914 915 916 917 918 919 920 921 922
                return 0;
            }
            break;

        case ZMQ_HEARTBEAT_TIMEOUT:
            if (is_int) {
                *value = heartbeat_timeout;
                return 0;
            }
            break;

923 924 925 926 927
        default:
#if defined (ZMQ_ACT_MILITANT)
            malformed = false;
#endif
            break;
928
    }
929 930 931 932
#if defined (ZMQ_ACT_MILITANT)
    if (malformed)
        zmq_assert (false);
#endif
933 934 935
    errno = EINVAL;
    return -1;
}
936 937 938

bool zmq::options_t::is_valid (int option_) const
{
939
    return true;
940
}