options.cpp 18.4 KB
Newer Older
1
/*
2
    Copyright (c) 2007-2014 Contributors as noted in the AUTHORS file
3 4 5 6

    This file is part of 0MQ.

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

    0MQ 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
14
    GNU Lesser General Public License for more details.
15

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

20 21
#include <string.h>

22
#include "options.hpp"
23
#include "err.hpp"
24
#include "../include/zmq_utils.h"
25 26

zmq::options_t::options_t () :
27 28
    sndhwm (1000),
    rcvhwm (1000),
malosek's avatar
malosek committed
29
    affinity (0),
30
    identity_size (0),
31
    rate (100),
32
    recovery_ivl (10000),
33
    multicast_hops (1),
34 35
    sndbuf (0),
    rcvbuf (0),
36
    tos (0),
37
    type (-1),
38
    linger (-1),
39
    reconnect_ivl (100),
40
    reconnect_ivl_max (0),
41
    backlog (100),
42
    maxmsgsize (-1),
43 44
    rcvtimeo (-1),
    sndtimeo (-1),
Pieter Hintjens's avatar
Pieter Hintjens committed
45
    ipv6 (0),
46
    immediate (0),
47
    filter (false),
48
    recv_identity (false),
Martin Hurton's avatar
Martin Hurton committed
49
    raw_sock (false),
50 51 52 53
    tcp_keepalive (-1),
    tcp_keepalive_cnt (-1),
    tcp_keepalive_idle (-1),
    tcp_keepalive_intvl (-1),
54
    mechanism (ZMQ_NULL),
55
    as_server (0),
danielkr's avatar
danielkr committed
56 57
    socket_id (0),
    conflate (false)
58 59
{
}
60 61 62 63

int zmq::options_t::setsockopt (int option_, const void *optval_,
    size_t optvallen_)
{
64 65
    bool is_int = (optvallen_ == sizeof (int));
    int value = is_int? *((int *) optval_): 0;
66

67
    switch (option_) {
68
        case ZMQ_SNDHWM:
69
            if (is_int && value >= 0) {
70
                sndhwm = value;
71 72
                return 0;
            }
73
            break;
74

75
        case ZMQ_RCVHWM:
76
            if (is_int && value >= 0) {
77
                rcvhwm = value;
78 79
                return 0;
            }
80
            break;
81

82
        case ZMQ_AFFINITY:
83
            if (optvallen_ == sizeof (uint64_t)) {
84
                affinity = *((uint64_t*) optval_);
85 86
                return 0;
            }
87 88 89 90 91 92 93 94 95 96
            break;

        case ZMQ_IDENTITY:
            //  Empty identity is invalid as well as identity longer than
            //  255 bytes. Identity starting with binary zero is invalid
            //  as these are used for auto-generated identities.
            if (optvallen_ > 0 && optvallen_ < 256
            && *((const unsigned char *) optval_) != 0) {
                identity_size = optvallen_;
                memcpy (identity, optval_, identity_size);
97
                return 0;
98 99
            }
            break;
100

101
        case ZMQ_RATE:
102
            if (is_int && value > 0) {
103
                rate = value;
104 105
                return 0;
            }
106
            break;
107

108
        case ZMQ_RECOVERY_IVL:
109
            if (is_int && value >= 0) {
110
                recovery_ivl = value;
111 112 113
                return 0;
            }
            break;
114

115
        case ZMQ_SNDBUF:
116
            if (is_int && value >= 0) {
117
                sndbuf = value;
118 119
                return 0;
            }
120
            break;
121

122
        case ZMQ_RCVBUF:
123
            if (is_int && value >= 0) {
124
                rcvbuf = value;
125 126
                return 0;
            }
127
            break;
128

129 130 131 132 133 134 135
        case ZMQ_TOS:
            if (is_int && value >= 0) {
                tos = value;
                return 0;
            }
            break;

136
        case ZMQ_LINGER:
137
            if (is_int && value >= -1) {
138
                linger = value;
139 140
                return 0;
            }
141
            break;
142

143
        case ZMQ_RECONNECT_IVL:
144
            if (is_int && value >= -1) {
145
                reconnect_ivl = value;
146 147
                return 0;
            }
148
            break;
149

150
        case ZMQ_RECONNECT_IVL_MAX:
151
            if (is_int && value >= 0) {
152
                reconnect_ivl_max = value;
153 154
                return 0;
            }
155
            break;
156

157
        case ZMQ_BACKLOG:
158
            if (is_int && value >= 0) {
159
                backlog = value;
160 161
                return 0;
            }
162
            break;
163

164
        case ZMQ_MAXMSGSIZE:
165
            if (optvallen_ == sizeof (int64_t)) {
166
                maxmsgsize = *((int64_t *) optval_);
167 168
                return 0;
            }
169
            break;
170

171
        case ZMQ_MULTICAST_HOPS:
172
            if (is_int && value > 0) {
173
                multicast_hops = value;
174 175
                return 0;
            }
176
            break;
177

178
        case ZMQ_RCVTIMEO:
179
            if (is_int && value >= -1) {
180
                rcvtimeo = value;
181 182
                return 0;
            }
183
            break;
184

185
        case ZMQ_SNDTIMEO:
186
            if (is_int && value >= -1) {
187
                sndtimeo = value;
188 189
                return 0;
            }
190
            break;
191

Pieter Hintjens's avatar
Pieter Hintjens committed
192
        /*  Deprecated in favor of ZMQ_IPV6  */
193
        case ZMQ_IPV4ONLY:
194
            if (is_int && (value == 0 || value == 1)) {
195
                ipv6 = (value == 0);
196 197
                return 0;
            }
198
            break;
199

200 201
        /*  To replace the somewhat surprising IPV4ONLY */
        case ZMQ_IPV6:
202
            if (is_int && (value == 0 || value == 1)) {
203
                ipv6 = (value != 0);
204 205
                return 0;
            }
206
            break;
207

208
        case ZMQ_TCP_KEEPALIVE:
209
            if (is_int && (value == -1 || value == 0 || value == 1)) {
210
                tcp_keepalive = value;
211 212
                return 0;
            }
213
            break;
214

215
        case ZMQ_TCP_KEEPALIVE_CNT:
216
            if (is_int && (value == -1 || value >= 0)) {
217
                tcp_keepalive_cnt = value;
218 219
                return 0;
            }
220
            break;
221

222
        case ZMQ_TCP_KEEPALIVE_IDLE:
223
            if (is_int && (value == -1 || value >= 0)) {
224
                tcp_keepalive_idle = value;
225 226
                return 0;
            }
227
            break;
228

229
        case ZMQ_TCP_KEEPALIVE_INTVL:
230
            if (is_int && (value == -1 || value >= 0)) {
231
                tcp_keepalive_intvl = value;
232 233
                return 0;
            }
234
            break;
235

236
        case ZMQ_IMMEDIATE:
237
            if (is_int && (value == 0 || value == 1)) {
238
                immediate = value;
239 240
                return 0;
            }
241
            break;
242

243
        case ZMQ_TCP_ACCEPT_FILTER:
244
            if (optvallen_ == 0 && optval_ == NULL) {
245
                tcp_accept_filters.clear ();
246 247
                return 0;
            }
248
            else
249
            if (optvallen_ > 0 && optvallen_ < 256 && optval_ != NULL && *((const char*) optval_) != 0) {
250
                std::string filter_str ((const char *) optval_, optvallen_);
251
                tcp_address_mask_t mask;
Pieter Hintjens's avatar
Pieter Hintjens committed
252
                int rc = mask.resolve (filter_str.c_str (), ipv6);
253
                if (rc == 0) {
254
                    tcp_accept_filters.push_back (mask);
255 256 257 258
                    return 0;
                }
            }
            break;
259

260
#       if defined ZMQ_HAVE_SO_PEERCRED || defined ZMQ_HAVE_LOCAL_PEERCRED
261
        case ZMQ_IPC_FILTER_UID:
262 263 264 265 266 267 268 269 270 271 272
            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;

273
        case ZMQ_IPC_FILTER_GID:
274 275 276 277 278 279 280 281 282 283 284 285 286
            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
287
        case ZMQ_IPC_FILTER_PID:
288 289 290 291 292 293 294 295 296 297 298 299
            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

300 301
        case ZMQ_PLAIN_SERVER:
            if (is_int && (value == 0 || value == 1)) {
302
                as_server = value;
303
                mechanism = value? ZMQ_PLAIN: ZMQ_NULL;
304 305 306
                return 0;
            }
            break;
307

308 309 310 311 312 313
        case ZMQ_PLAIN_USERNAME:
            if (optvallen_ == 0 && optval_ == NULL) {
                mechanism = ZMQ_NULL;
                return 0;
            }
            else
314
            if (optvallen_ > 0 && optvallen_ < 256 && optval_ != NULL) {
315
                plain_username.assign ((const char *) optval_, optvallen_);
316
                as_server = 0;
317 318 319 320
                mechanism = ZMQ_PLAIN;
                return 0;
            }
            break;
321

322 323 324 325 326 327
        case ZMQ_PLAIN_PASSWORD:
            if (optvallen_ == 0 && optval_ == NULL) {
                mechanism = ZMQ_NULL;
                return 0;
            }
            else
328
            if (optvallen_ > 0 && optvallen_ < 256 && optval_ != NULL) {
329
                plain_password.assign ((const char *) optval_, optvallen_);
330
                as_server = 0;
331 332
                mechanism = ZMQ_PLAIN;
                return 0;
333
            }
334
            break;
335 336

        case ZMQ_ZAP_DOMAIN:
337
            if (optvallen_ < 256) {
338 339 340 341 342
                zap_domain.assign ((const char *) optval_, optvallen_);
                return 0;
            }
            break;

Pieter Hintjens's avatar
Pieter Hintjens committed
343
        //  If libsodium isn't installed, these options provoke EINVAL
344
#       ifdef HAVE_LIBSODIUM
345
        case ZMQ_CURVE_SERVER:
346
            if (is_int && (value == 0 || value == 1)) {
347
                as_server = value;
348
                mechanism = value? ZMQ_CURVE: ZMQ_NULL;
349 350 351
                return 0;
            }
            break;
352

353 354 355 356 357 358 359 360 361 362 363 364
        case ZMQ_CURVE_PUBLICKEY:
            if (optvallen_ == CURVE_KEYSIZE) {
                memcpy (curve_public_key, optval_, CURVE_KEYSIZE);
                mechanism = ZMQ_CURVE;
                return 0;
            }
            else
            if (optvallen_ == CURVE_KEYSIZE_Z85) {
                zmq_z85_decode (curve_public_key, (char *) optval_);
                mechanism = ZMQ_CURVE;
                return 0;
            }
365
            break;
366

367 368 369 370 371 372 373 374 375 376 377 378
        case ZMQ_CURVE_SECRETKEY:
            if (optvallen_ == CURVE_KEYSIZE) {
                memcpy (curve_secret_key, optval_, CURVE_KEYSIZE);
                mechanism = ZMQ_CURVE;
                return 0;
            }
            else
            if (optvallen_ == CURVE_KEYSIZE_Z85) {
                zmq_z85_decode (curve_secret_key, (char *) optval_);
                mechanism = ZMQ_CURVE;
                return 0;
            }
379 380
            break;

381 382 383 384 385 386 387 388 389 390 391 392 393 394
        case ZMQ_CURVE_SERVERKEY:
            if (optvallen_ == CURVE_KEYSIZE) {
                memcpy (curve_server_key, optval_, CURVE_KEYSIZE);
                as_server = 0;
                mechanism = ZMQ_CURVE;
                return 0;
            }
            else
            if (optvallen_ == CURVE_KEYSIZE_Z85) {
                zmq_z85_decode (curve_server_key, (char *) optval_);
                as_server = 0;
                mechanism = ZMQ_CURVE;
                return 0;
            }
395
            break;
396
#       endif
danielkr's avatar
danielkr committed
397 398 399 400 401 402 403 404 405 406

        case ZMQ_CONFLATE:
            if (is_int && (value == 0 || value == 1)) {
                conflate = (value != 0);
                return 0;
            }
            break;

        default:
            break;
407
    }
408 409
    errno = EINVAL;
    return -1;
410
}
411 412 413

int zmq::options_t::getsockopt (int option_, void *optval_, size_t *optvallen_)
{
414 415
    bool is_int = (*optvallen_ == sizeof (int));
    int *value = (int *) optval_;
416

417
    switch (option_) {
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474
        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;

475 476 477 478 479 480
        case ZMQ_TOS:
            if (is_int) {
                *value = tos;
                return 0;
            }
            break;
481 482 483 484 485 486 487 488 489 490 491 492 493
        case ZMQ_TYPE:
            if (is_int) {
                *value = type;
                return 0;
            }
            break;

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

495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550
        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;
551

552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599
        case ZMQ_IPV6:
            if (is_int) {
                *value = ipv6;
                return 0;
            }
            break;

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

        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;
600

601
        case ZMQ_PLAIN_SERVER:
602
            if (is_int) {
603
                *value = as_server && mechanism == ZMQ_PLAIN;
604 605 606
                return 0;
            }
            break;
607

608 609 610 611 612 613 614
        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;
615

616 617 618 619 620 621 622
        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;
623 624 625 626 627 628 629 630 631

        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
632
        //  If libsodium isn't installed, these options provoke EINVAL
633
#       ifdef HAVE_LIBSODIUM
634
        case ZMQ_CURVE_SERVER:
635
            if (is_int) {
636
                *value = as_server && mechanism == ZMQ_CURVE;
637 638 639
                return 0;
            }
            break;
640

641 642 643 644 645 646 647 648 649 650
        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;
            }
651
            break;
652

653 654 655 656 657 658 659 660 661 662
        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;
            }
663 664
            break;

665 666 667 668 669 670 671 672 673 674
        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;
            }
675
            break;
676
#       endif
danielkr's avatar
danielkr committed
677 678 679 680 681 682 683 684

        case ZMQ_CONFLATE:
            if (is_int) {
                *value = conflate;
                return 0;
            }
            break;

685 686 687 688
    }
    errno = EINVAL;
    return -1;
}