options.cpp 12.9 KB
Newer Older
1
/*
2
    Copyright (c) 2007-2012 iMatix Corporation
Martin Sustrik's avatar
Martin Sustrik committed
3
    Copyright (c) 2009-2011 250bpm s.r.o.
4
    Copyright (c) 2011 VMware, Inc.
5
    Copyright (c) 2007-2011 Other contributors as noted in the AUTHORS file
6 7 8 9

    This file is part of 0MQ.

    0MQ is free software; you can redistribute it and/or modify it under
10
    the terms of the GNU Lesser General Public License as published by
11 12 13 14 15 16
    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
17
    GNU Lesser General Public License for more details.
18

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

23 24
#include <string.h>

25
#include "options.hpp"
26
#include "err.hpp"
27 28

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

int zmq::options_t::setsockopt (int option_, const void *optval_,
    size_t optvallen_)
{
64 65 66 67
    bool valid = true;
    bool is_int = (optvallen_ == sizeof (int));
    int value = is_int? *((int *) optval_): 0;
    
68
    switch (option_) {
69 70 71 72 73 74 75 76 77 78 79 80 81
        case ZMQ_SNDHWM:
            if (is_int && value >= 0)
                sndhwm = value;
            else
                valid = false;
            break;
        
        case ZMQ_RCVHWM:
            if (is_int && value >= 0)
                rcvhwm = value;
            else
                valid = false;
            break;
82

83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
        case ZMQ_AFFINITY:
            if (optvallen_ == sizeof (uint64_t))
                affinity = *((uint64_t*) optval_);
            else
                valid = false;
            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);
            }
            else
                valid = false;
            break;
102

103 104 105 106 107 108
        case ZMQ_RATE:
            if (is_int && value > 0)
                rate = value;
            else
                valid = false;
            break;
109

110 111 112 113 114
        case ZMQ_RECOVERY_IVL:
            if (is_int && value >= 0)
                recovery_ivl = value;
            else
                valid = false;
115

116 117 118 119 120 121
        case ZMQ_SNDBUF:
            if (is_int && value >= 0)
                sndbuf = value;
            else
                valid = false;
            break;
122

123 124 125 126 127 128
        case ZMQ_RCVBUF:
            if (is_int && value >= 0)
                rcvbuf = value;
            else
                valid = false;
            break;
129

130 131 132 133 134 135
        case ZMQ_LINGER:
            if (is_int && value >= -1)
                linger = value;
            else
                valid = false;
            break;
136

137 138 139 140 141 142
        case ZMQ_RECONNECT_IVL:
            if (is_int && value >= -1)
                reconnect_ivl = value;
            else
                valid = false;
            break;
143

144 145 146
        case ZMQ_RECONNECT_IVL_MAX:
            if (is_int && value >= 0)
                reconnect_ivl_max = value;
147
            else 
148 149
                valid = false;
            break;
150

151 152 153 154 155 156
        case ZMQ_BACKLOG:
            if (is_int && value >= 0)
                backlog = value;
            else
                valid = false;
            break;
157

158 159 160 161 162
        case ZMQ_MAXMSGSIZE:
            if (optvallen_ == sizeof (int64_t))
                maxmsgsize = *((int64_t *) optval_);
            else
                valid = false;
163
            break;
164

165 166 167 168 169 170
        case ZMQ_MULTICAST_HOPS:
            if (is_int && value > 0)
                multicast_hops = value;
            else
                valid = false;
            break;
171

172 173 174 175 176 177
        case ZMQ_RCVTIMEO:
            if (is_int && value >= -1)
                rcvtimeo = value;
            else
                valid = false;
            break;
178

179 180 181 182 183 184
        case ZMQ_SNDTIMEO:
            if (is_int && value >= -1)
                sndtimeo = value;
            else
                valid = false;
            break;
185

Pieter Hintjens's avatar
Pieter Hintjens committed
186
        /*  Deprecated in favor of ZMQ_IPV6  */
187 188
        case ZMQ_IPV4ONLY:
            if (is_int && (value == 0 || value == 1))
189
                ipv6 = (value == 0);
190 191 192
            else
                valid = false;
            break;
193

194 195 196
        /*  To replace the somewhat surprising IPV4ONLY */
        case ZMQ_IPV6:
            if (is_int && (value == 0 || value == 1))
197
                ipv6 = (value != 0);
198 199 200
            else
                valid = false;
            break;
201

202 203 204 205 206 207
        case ZMQ_TCP_KEEPALIVE:
            if (is_int && (value >= -1 || value <= 1))
                tcp_keepalive = value;
            else
                valid = false;
            break;
208

209 210 211 212 213 214
        case ZMQ_TCP_KEEPALIVE_CNT:
            if (is_int && (value == -1 || value >= 0))
                tcp_keepalive_cnt = value;
            else
                valid = false;
            break;
215

216 217 218 219 220 221
        case ZMQ_TCP_KEEPALIVE_IDLE:
            if (is_int && (value == -1 || value >= 0))
                tcp_keepalive_idle = value;
            else
                valid = false;
            break;
222

223 224 225 226 227 228 229
        case ZMQ_TCP_KEEPALIVE_INTVL:
            if (is_int && (value == -1 || value >= 0))
                tcp_keepalive_intvl = value;
            else
                valid = false;
            break;
            
230
        case ZMQ_DELAY_ATTACH_ON_CONNECT:
231 232 233 234 235
            if (is_int && (value == 0 || value == 1))
                delay_attach_on_connect = value;
            else
                valid = false;
            break;
236

237 238
        case ZMQ_TCP_ACCEPT_FILTER:
            if (optvallen_ == 0 && optval_ == NULL)
239 240
                tcp_accept_filters.clear ();
            else
241 242
            if (optvallen_ < 1 || optvallen_ > 255 || optval_ == NULL || *((const char*) optval_) == 0)
                valid = false;
243
            else {
244
                std::string filter_str ((const char *) optval_, optvallen_);
245
                tcp_address_mask_t mask;
Pieter Hintjens's avatar
Pieter Hintjens committed
246
                int rc = mask.resolve (filter_str.c_str (), ipv6);
247 248 249 250
                if (rc == 0)
                    tcp_accept_filters.push_back (mask);
                else
                    valid = false;
251
            }
252 253 254 255 256 257 258 259 260 261 262
            break;
            
        default:
            valid = false;
            break;
    }
    if (valid)
        return 0;
    else {
        errno = EINVAL;
        return -1;
263
    }
264
}
265 266 267 268 269

int zmq::options_t::getsockopt (int option_, void *optval_, size_t *optvallen_)
{
    switch (option_) {

270
    case ZMQ_SNDHWM:
271
        if (*optvallen_ < sizeof (int)) {
272 273 274
            errno = EINVAL;
            return -1;
        }
275 276 277 278 279 280 281 282 283 284 285
        *((int*) optval_) = sndhwm;
        *optvallen_ = sizeof (int);
        return 0;

    case ZMQ_RCVHWM:
        if (*optvallen_ < sizeof (int)) {
            errno = EINVAL;
            return -1;
        }
        *((int*) optval_) = rcvhwm;
        *optvallen_ = sizeof (int);
286 287 288 289 290 291 292 293 294 295 296
        return 0;

    case ZMQ_AFFINITY:
        if (*optvallen_ < sizeof (uint64_t)) {
            errno = EINVAL;
            return -1;
        }
        *((uint64_t*) optval_) = affinity;
        *optvallen_ = sizeof (uint64_t);
        return 0;

297 298 299 300 301 302 303 304 305
    case ZMQ_IDENTITY:
        if (*optvallen_ < identity_size) {
            errno = EINVAL;
            return -1;
        }
        memcpy (optval_, identity, identity_size);
        *optvallen_ = identity_size;
        return 0;

306
    case ZMQ_RATE:
307
        if (*optvallen_ < sizeof (int)) {
308 309 310
            errno = EINVAL;
            return -1;
        }
311 312
        *((int*) optval_) = rate;
        *optvallen_ = sizeof (int);
313
        return 0;
314

315
    case ZMQ_RECOVERY_IVL:
316
        if (*optvallen_ < sizeof (int)) {
317 318 319
            errno = EINVAL;
            return -1;
        }
320 321
        *((int*) optval_) = recovery_ivl;
        *optvallen_ = sizeof (int);
322 323 324
        return 0;

    case ZMQ_SNDBUF:
325
        if (*optvallen_ < sizeof (int)) {
326 327 328
            errno = EINVAL;
            return -1;
        }
329 330
        *((int*) optval_) = sndbuf;
        *optvallen_ = sizeof (int);
331 332 333
        return 0;

    case ZMQ_RCVBUF:
334
        if (*optvallen_ < sizeof (int)) {
335 336 337
            errno = EINVAL;
            return -1;
        }
338 339
        *((int*) optval_) = rcvbuf;
        *optvallen_ = sizeof (int);
340
        return 0;
341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368

    case ZMQ_TYPE:
        if (*optvallen_ < sizeof (int)) {
            errno = EINVAL;
            return -1;
        }
        *((int*) optval_) = type;
        *optvallen_ = sizeof (int);
        return 0;

    case ZMQ_LINGER:
        if (*optvallen_ < sizeof (int)) {
            errno = EINVAL;
            return -1;
        }
        *((int*) optval_) = linger;
        *optvallen_ = sizeof (int);
        return 0;

    case ZMQ_RECONNECT_IVL:
        if (*optvallen_ < sizeof (int)) {
            errno = EINVAL;
            return -1;
        }
        *((int*) optval_) = reconnect_ivl;
        *optvallen_ = sizeof (int);
        return 0;

369 370 371 372 373 374 375 376 377
    case ZMQ_RECONNECT_IVL_MAX:
        if (*optvallen_ < sizeof (int)) {
            errno = EINVAL;
            return -1;
        }
        *((int*) optval_) = reconnect_ivl_max;
        *optvallen_ = sizeof (int);
        return 0;

378 379 380 381 382 383 384 385 386
    case ZMQ_BACKLOG:
        if (*optvallen_ < sizeof (int)) {
            errno = EINVAL;
            return -1;
        }
        *((int*) optval_) = backlog;
        *optvallen_ = sizeof (int);
        return 0;

387 388 389 390 391 392 393 394 395
    case ZMQ_MAXMSGSIZE:
        if (*optvallen_ < sizeof (int64_t)) {
            errno = EINVAL;
            return -1;
        }
        *((int64_t*) optval_) = maxmsgsize;
        *optvallen_ = sizeof (int64_t);
        return 0;

396 397 398 399 400 401 402 403 404
    case ZMQ_MULTICAST_HOPS:
        if (*optvallen_ < sizeof (int)) {
            errno = EINVAL;
            return -1;
        }
        *((int*) optval_) = multicast_hops;
        *optvallen_ = sizeof (int);
        return 0;

405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422
    case ZMQ_RCVTIMEO:
        if (*optvallen_ < sizeof (int)) {
            errno = EINVAL;
            return -1;
        }
        *((int*) optval_) = rcvtimeo;
        *optvallen_ = sizeof (int);
        return 0;

    case ZMQ_SNDTIMEO:
        if (*optvallen_ < sizeof (int)) {
            errno = EINVAL;
            return -1;
        }
        *((int*) optval_) = sndtimeo;
        *optvallen_ = sizeof (int);
        return 0;

Steven McCoy's avatar
Steven McCoy committed
423 424 425 426 427
    case ZMQ_IPV4ONLY:
        if (*optvallen_ < sizeof (int)) {
            errno = EINVAL;
            return -1;
        }
Pieter Hintjens's avatar
Pieter Hintjens committed
428
        *((int*) optval_) = 1 - ipv6;
Steven McCoy's avatar
Steven McCoy committed
429 430
        *optvallen_ = sizeof (int);
        return 0;
431
        
432 433 434 435 436
    case ZMQ_IPV6:
        if (*optvallen_ < sizeof (int)) {
            errno = EINVAL;
            return -1;
        }
Pieter Hintjens's avatar
Pieter Hintjens committed
437
        *((int*) optval_) = ipv6;
438 439 440
        *optvallen_ = sizeof (int);
        return 0;

441
    case ZMQ_DELAY_ATTACH_ON_CONNECT:
Pieter Hintjens's avatar
Pieter Hintjens committed
442 443 444 445 446 447 448
        if (*optvallen_ < sizeof (int)) {
            errno = EINVAL;
            return -1;
        }
        *((int*) optval_) = delay_attach_on_connect;
        *optvallen_ = sizeof (int);
        return 0;
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 475 476 477 478 479 480 481 482 483 484 485

    case ZMQ_TCP_KEEPALIVE:
        if (*optvallen_ < sizeof (int)) {
            errno = EINVAL;
            return -1;
        }
        *((int*) optval_) = tcp_keepalive;
        *optvallen_ = sizeof (int);
        return 0;

    case ZMQ_TCP_KEEPALIVE_CNT:
        if (*optvallen_ < sizeof (int)) {
            errno = EINVAL;
            return -1;
        }
        *((int*) optval_) = tcp_keepalive_cnt;
        *optvallen_ = sizeof (int);
        return 0;

    case ZMQ_TCP_KEEPALIVE_IDLE:
        if (*optvallen_ < sizeof (int)) {
            errno = EINVAL;
            return -1;
        }
        *((int*) optval_) = tcp_keepalive_idle;
        *optvallen_ = sizeof (int);
        return 0;

    case ZMQ_TCP_KEEPALIVE_INTVL:
        if (*optvallen_ < sizeof (int)) {
            errno = EINVAL;
            return -1;
        }
        *((int*) optval_) = tcp_keepalive_intvl;
        *optvallen_ = sizeof (int);
        return 0;

486
    case ZMQ_LAST_ENDPOINT:
Pieter Hintjens's avatar
Pieter Hintjens committed
487
        /*  don't allow string which cannot contain the entire message */
488
        if (*optvallen_ < last_endpoint.size() + 1) {
489 490 491
            errno = EINVAL;
            return -1;
        }
492 493
        memcpy (optval_, last_endpoint.c_str(), last_endpoint.size()+1);
        *optvallen_ = last_endpoint.size()+1;
494
        return 0;
495 496 497 498 499
    }

    errno = EINVAL;
    return -1;
}