Commit 18a14aed authored by Pieter Hintjens's avatar Pieter Hintjens

Added ZMQ_IPV6 option, cleaned up setsockopt code, it was nasty

parent aa21e090
......@@ -241,7 +241,7 @@ ZMQ_EXPORT int zmq_msg_set (zmq_msg_t *msg, int option, int optval);
#define ZMQ_MULTICAST_HOPS 25
#define ZMQ_RCVTIMEO 27
#define ZMQ_SNDTIMEO 28
#define ZMQ_IPV4ONLY 31
#define ZMQ_IPV4ONLY 31 /* Request replacement by IPV6 */
#define ZMQ_LAST_ENDPOINT 32
#define ZMQ_ROUTER_MANDATORY 33
#define ZMQ_TCP_KEEPALIVE 34
......@@ -252,6 +252,7 @@ ZMQ_EXPORT int zmq_msg_set (zmq_msg_t *msg, int option, int optval);
#define ZMQ_DELAY_ATTACH_ON_CONNECT 39
#define ZMQ_XPUB_VERBOSE 40
#define ZMQ_ROUTER_RAW 41
#define ZMQ_IPV6 42
/* Message options */
......
......@@ -61,281 +61,203 @@ zmq::options_t::options_t () :
int zmq::options_t::setsockopt (int option_, const void *optval_,
size_t optvallen_)
{
bool valid = true;
bool is_int = (optvallen_ == sizeof (int));
int value = is_int? *((int *) optval_): 0;
switch (option_) {
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;
case ZMQ_SNDHWM:
if (optvallen_ != sizeof (int) || *((int*) optval_) < 0) {
errno = EINVAL;
return -1;
}
sndhwm = *((int*) optval_);
return 0;
case ZMQ_RCVHWM:
if (optvallen_ != sizeof (int) || *((int*) optval_) < 0) {
errno = EINVAL;
return -1;
}
rcvhwm = *((int*) optval_);
return 0;
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;
case ZMQ_AFFINITY:
if (optvallen_ != sizeof (uint64_t)) {
errno = EINVAL;
return -1;
}
affinity = *((uint64_t*) optval_);
return 0;
case ZMQ_RATE:
if (is_int && value > 0)
rate = value;
else
valid = false;
break;
case ZMQ_IDENTITY:
case ZMQ_RECOVERY_IVL:
if (is_int && value >= 0)
recovery_ivl = value;
else
valid = false;
// 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_ < 1 || optvallen_ > 255 ||
*((const unsigned char*) optval_) == 0) {
errno = EINVAL;
return -1;
}
identity_size = optvallen_;
memcpy (identity, optval_, identity_size);
return 0;
case ZMQ_SNDBUF:
if (is_int && value >= 0)
sndbuf = value;
else
valid = false;
break;
case ZMQ_RATE:
if (optvallen_ != sizeof (int) || *((int*) optval_) <= 0) {
errno = EINVAL;
return -1;
}
rate = *((int*) optval_);
return 0;
case ZMQ_RCVBUF:
if (is_int && value >= 0)
rcvbuf = value;
else
valid = false;
break;
case ZMQ_RECOVERY_IVL:
if (optvallen_ != sizeof (int) || *((int*) optval_) < 0) {
errno = EINVAL;
return -1;
}
recovery_ivl = *((int*) optval_);
return 0;
case ZMQ_LINGER:
if (is_int && value >= -1)
linger = value;
else
valid = false;
break;
case ZMQ_SNDBUF:
if (optvallen_ != sizeof (int) || *((int*) optval_) < 0) {
errno = EINVAL;
return -1;
}
sndbuf = *((int*) optval_);
return 0;
case ZMQ_RECONNECT_IVL:
if (is_int && value >= -1)
reconnect_ivl = value;
else
valid = false;
break;
case ZMQ_RCVBUF:
if (optvallen_ != sizeof (int) || *((int*) optval_) < 0) {
errno = EINVAL;
return -1;
}
rcvbuf = *((int*) optval_);
return 0;
case ZMQ_RECONNECT_IVL_MAX:
if (is_int && value >= 0)
reconnect_ivl_max = value;
else
valid = false;
break;
case ZMQ_LINGER:
if (optvallen_ != sizeof (int)) {
errno = EINVAL;
return -1;
}
linger = *((int*) optval_);
return 0;
case ZMQ_BACKLOG:
if (is_int && value >= 0)
backlog = value;
else
valid = false;
break;
case ZMQ_RECONNECT_IVL:
if (optvallen_ != sizeof (int)) {
errno = EINVAL;
return -1;
}
if (*((int*) optval_) < -1) {
errno = EINVAL;
return -1;
}
reconnect_ivl = *((int*) optval_);
return 0;
case ZMQ_MAXMSGSIZE:
if (optvallen_ == sizeof (int64_t))
maxmsgsize = *((int64_t *) optval_);
else
valid = false;
case ZMQ_RECONNECT_IVL_MAX:
if (optvallen_ != sizeof (int)) {
errno = EINVAL;
return -1;
}
if (*((int*) optval_) < 0) {
errno = EINVAL;
return -1;
}
reconnect_ivl_max = *((int*) optval_);
return 0;
case ZMQ_MULTICAST_HOPS:
if (is_int && value > 0)
multicast_hops = value;
else
valid = false;
break;
case ZMQ_BACKLOG:
if (optvallen_ != sizeof (int)) {
errno = EINVAL;
return -1;
}
backlog = *((int*) optval_);
return 0;
case ZMQ_RCVTIMEO:
if (is_int && value >= -1)
rcvtimeo = value;
else
valid = false;
break;
case ZMQ_MAXMSGSIZE:
if (optvallen_ != sizeof (int64_t)) {
errno = EINVAL;
return -1;
}
maxmsgsize = *((int64_t*) optval_);
return 0;
case ZMQ_SNDTIMEO:
if (is_int && value >= -1)
sndtimeo = value;
else
valid = false;
break;
case ZMQ_MULTICAST_HOPS:
if (optvallen_ != sizeof (int) || *((int*) optval_) <= 0) {
errno = EINVAL;
return -1;
}
multicast_hops = *((int*) optval_);
return 0;
case ZMQ_IPV4ONLY:
if (is_int && (value == 0 || value == 1))
ipv4only = value;
else
valid = false;
break;
case ZMQ_RCVTIMEO:
if (optvallen_ != sizeof (int)) {
errno = EINVAL;
return -1;
}
rcvtimeo = *((int*) optval_);
return 0;
/* To replace the somewhat surprising IPV4ONLY */
case ZMQ_IPV6:
if (is_int && (value == 0 || value == 1))
ipv4only = 1 - value;
else
valid = false;
break;
case ZMQ_SNDTIMEO:
if (optvallen_ != sizeof (int)) {
errno = EINVAL;
return -1;
}
sndtimeo = *((int*) optval_);
return 0;
case ZMQ_TCP_KEEPALIVE:
if (is_int && (value >= -1 || value <= 1))
tcp_keepalive = value;
else
valid = false;
break;
case ZMQ_IPV4ONLY:
{
if (optvallen_ != sizeof (int)) {
errno = EINVAL;
return -1;
}
int val = *((int*) optval_);
if (val != 0 && val != 1) {
errno = EINVAL;
return -1;
}
ipv4only = val;
return 0;
}
case ZMQ_TCP_KEEPALIVE_CNT:
if (is_int && (value == -1 || value >= 0))
tcp_keepalive_cnt = value;
else
valid = false;
break;
case ZMQ_TCP_KEEPALIVE:
{
if (optvallen_ != sizeof (int)) {
errno = EINVAL;
return -1;
}
int val = *((int*) optval_);
if (val != -1 && val != 0 && val != 1) {
errno = EINVAL;
return -1;
}
#if defined ZMQ_HAVE_SO_KEEPALIVE
tcp_keepalive = val;
#endif
return 0;
}
case ZMQ_TCP_KEEPALIVE_IDLE:
if (is_int && (value == -1 || value >= 0))
tcp_keepalive_idle = value;
else
valid = false;
break;
case ZMQ_TCP_KEEPALIVE_INTVL:
if (is_int && (value == -1 || value >= 0))
tcp_keepalive_intvl = value;
else
valid = false;
break;
case ZMQ_DELAY_ATTACH_ON_CONNECT:
{
if (optvallen_ != sizeof (int)) {
errno = EINVAL;
return -1;
}
int val = *((int*) optval_);
if (val != 0 && val != 1) {
errno = EINVAL;
return -1;
}
delay_attach_on_connect = val;
return 0;
}
case ZMQ_TCP_KEEPALIVE_CNT:
{
if (optvallen_ != sizeof (int)) {
errno = EINVAL;
return -1;
}
int val = *((int*) optval_);
if (val <= 0 && val != -1) {
errno = EINVAL;
return -1;
}
#if defined ZMQ_HAVE_SO_KEEPALIVE && defined ZMQ_HAVE_TCP_KEEPCNT
tcp_keepalive_cnt = val;
#endif
return 0;
}
case ZMQ_TCP_KEEPALIVE_IDLE:
{
if (optvallen_ != sizeof (int)) {
errno = EINVAL;
return -1;
}
int val = *((int*) optval_);
if (val <= 0 && val != -1) {
errno = EINVAL;
return -1;
}
#if defined ZMQ_HAVE_SO_KEEPALIVE && (defined ZMQ_HAVE_TCP_KEEPIDLE || defined ZMQ_HAVE_TCP_KEEPALIVE)
tcp_keepalive_idle = val;
#endif
return 0;
}
case ZMQ_TCP_KEEPALIVE_INTVL:
{
if (optvallen_ != sizeof (int)) {
errno = EINVAL;
return -1;
}
int val = *((int*) optval_);
if (val <= 0 && val != -1) {
errno = EINVAL;
return -1;
}
#if defined ZMQ_HAVE_SO_KEEPALIVE && defined ZMQ_HAVE_TCP_KEEPINTVL
tcp_keepalive_intvl = val;
#endif
return 0;
}
if (is_int && (value == 0 || value == 1))
delay_attach_on_connect = value;
else
valid = false;
break;
case ZMQ_TCP_ACCEPT_FILTER:
{
if (optvallen_ == 0 && optval_ == NULL) {
case ZMQ_TCP_ACCEPT_FILTER:
if (optvallen_ == 0 && optval_ == NULL)
tcp_accept_filters.clear ();
return 0;
}
else
if (optvallen_ < 1 || optvallen_ > 255 || optval_ == NULL || *((const char*) optval_) == 0) {
errno = EINVAL;
return -1;
}
if (optvallen_ < 1 || optvallen_ > 255 || optval_ == NULL || *((const char*) optval_) == 0)
valid = false;
else {
std::string filter_str ((const char*) optval_, optvallen_);
std::string filter_str ((const char *) optval_, optvallen_);
tcp_address_mask_t mask;
int rc = mask.resolve (filter_str.c_str (), ipv4only ? true : false);
if (rc != 0) {
errno = EINVAL;
return -1;
}
tcp_accept_filters.push_back(mask);
return 0;
int rc = mask.resolve (filter_str.c_str (), ipv4only);
if (rc == 0)
tcp_accept_filters.push_back (mask);
else
valid = false;
}
}
default:
{
errno = EINVAL;
return -1;
}
break;
default:
valid = false;
break;
}
if (valid)
return 0;
else {
errno = EINVAL;
return -1;
}
}
......@@ -505,6 +427,15 @@ int zmq::options_t::getsockopt (int option_, void *optval_, size_t *optvallen_)
*optvallen_ = sizeof (int);
return 0;
case ZMQ_IPV6:
if (*optvallen_ < sizeof (int)) {
errno = EINVAL;
return -1;
}
*((int*) optval_) = 1 - ipv4only;
*optvallen_ = sizeof (int);
return 0;
case ZMQ_DELAY_ATTACH_ON_CONNECT:
if (*optvallen_ < sizeof (int)) {
errno = EINVAL;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment