Commit 6f967c3a authored by Simon Giesecke's avatar Simon Giesecke

Problem: code duplication in getsockopt/setsockopt

Solution: extracted common code into do_getsockopt/do_setsockopt functions
parent 494c2a71
This diff is collapsed.
...@@ -46,6 +46,10 @@ ...@@ -46,6 +46,10 @@
#include <sys/ucred.h> #include <sys/ucred.h>
#endif #endif
#if __cplusplus >= 201103L
#include <type_traits>
#endif
// Normal base 256 key is 32 bytes // Normal base 256 key is 32 bytes
#define CURVE_KEYSIZE 32 #define CURVE_KEYSIZE 32
// Key encoded using Z85 is 40 bytes // Key encoded using Z85 is 40 bytes
...@@ -255,6 +259,33 @@ struct options_t ...@@ -255,6 +259,33 @@ struct options_t
// Use zero copy strategy for storing message content when decoding. // Use zero copy strategy for storing message content when decoding.
bool zero_copy; bool zero_copy;
}; };
int do_getsockopt (void *const optval_,
size_t *const optvallen_,
const void *value_,
const size_t value_len_);
template <typename T>
int do_getsockopt (void *const optval_, size_t *const optvallen_, T value_)
{
#if __cplusplus >= 201103L && (!defined(__GNUC__) || __GNUC__ > 5)
static_assert (std::is_trivially_copyable<T>::value,
"invalid use of do_getsockopt");
#endif
return do_getsockopt (optval_, optvallen_, &value_, sizeof (T));
}
int do_getsockopt (void *const optval_,
size_t *const optvallen_,
const std::string &value_);
int do_setsockopt_int_as_bool_strict (const void *const optval_,
const size_t optvallen_,
bool *out_value_);
int do_setsockopt_int_as_bool_relaxed (const void *const optval_,
const size_t optvallen_,
bool *out_value_);
} }
#endif #endif
...@@ -106,6 +106,8 @@ int zmq::router_t::xsetsockopt (int option_, ...@@ -106,6 +106,8 @@ int zmq::router_t::xsetsockopt (int option_,
switch (option_) { switch (option_) {
case ZMQ_CONNECT_ROUTING_ID: case ZMQ_CONNECT_ROUTING_ID:
// TODO why isn't it possible to set an empty connect_routing_id
// (which is the default value)
if (optval_ && optvallen_) { if (optval_ && optvallen_) {
connect_routing_id.assign ((char *) optval_, optvallen_); connect_routing_id.assign ((char *) optval_, optvallen_);
return 0; return 0;
......
...@@ -97,7 +97,6 @@ ...@@ -97,7 +97,6 @@
#include "scatter.hpp" #include "scatter.hpp"
#include "dgram.hpp" #include "dgram.hpp"
bool zmq::socket_base_t::check_tag () bool zmq::socket_base_t::check_tag ()
{ {
return tag == 0xbaddecaf; return tag == 0xbaddecaf;
...@@ -395,77 +394,41 @@ int zmq::socket_base_t::getsockopt (int option_, ...@@ -395,77 +394,41 @@ int zmq::socket_base_t::getsockopt (int option_,
} }
if (option_ == ZMQ_RCVMORE) { if (option_ == ZMQ_RCVMORE) {
if (*optvallen_ < sizeof (int)) { return do_getsockopt<int> (optval_, optvallen_, rcvmore ? 1 : 0);
errno = EINVAL;
return -1;
}
memset (optval_, 0, *optvallen_);
*((int *) optval_) = rcvmore ? 1 : 0;
*optvallen_ = sizeof (int);
return 0;
} }
if (option_ == ZMQ_FD) { if (option_ == ZMQ_FD) {
if (*optvallen_ < sizeof (fd_t)) {
errno = EINVAL;
return -1;
}
if (thread_safe) { if (thread_safe) {
// thread safe socket doesn't provide file descriptor // thread safe socket doesn't provide file descriptor
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
*((fd_t *) optval_) = ((mailbox_t *) mailbox)->get_fd (); return do_getsockopt<fd_t> (optval_, optvallen_,
*optvallen_ = sizeof (fd_t); ((mailbox_t *) mailbox)->get_fd ());
return 0;
} }
if (option_ == ZMQ_EVENTS) { if (option_ == ZMQ_EVENTS) {
if (*optvallen_ < sizeof (int)) {
errno = EINVAL;
return -1;
}
int rc = process_commands (0, false); int rc = process_commands (0, false);
if (rc != 0 && (errno == EINTR || errno == ETERM)) { if (rc != 0 && (errno == EINTR || errno == ETERM)) {
return -1; return -1;
} }
errno_assert (rc == 0); errno_assert (rc == 0);
*((int *) optval_) = 0;
if (has_out ()) return do_getsockopt<int> (optval_, optvallen_,
*((int *) optval_) |= ZMQ_POLLOUT; (has_out () ? ZMQ_POLLOUT : 0)
if (has_in ()) | (has_in () ? ZMQ_POLLIN : 0));
*((int *) optval_) |= ZMQ_POLLIN;
*optvallen_ = sizeof (int);
return 0;
} }
if (option_ == ZMQ_LAST_ENDPOINT) { if (option_ == ZMQ_LAST_ENDPOINT) {
if (*optvallen_ < last_endpoint.size () + 1) { return do_getsockopt (optval_, optvallen_, last_endpoint);
errno = EINVAL;
return -1;
}
strncpy (static_cast<char *> (optval_), last_endpoint.c_str (),
last_endpoint.size () + 1);
*optvallen_ = last_endpoint.size () + 1;
return 0;
} }
if (option_ == ZMQ_THREAD_SAFE) { if (option_ == ZMQ_THREAD_SAFE) {
if (*optvallen_ < sizeof (int)) { return do_getsockopt<int> (optval_, optvallen_, thread_safe ? 1 : 0);
errno = EINVAL;
return -1;
}
memset (optval_, 0, *optvallen_);
*((int *) optval_) = thread_safe ? 1 : 0;
*optvallen_ = sizeof (int);
return 0;
} }
int rc = options.getsockopt (option_, optval_, optvallen_); return options.getsockopt (option_, optval_, optvallen_);
return rc;
} }
int zmq::socket_base_t::join (const char *group_) int zmq::socket_base_t::join (const char *group_)
......
...@@ -175,13 +175,10 @@ int zmq::stream_t::xsetsockopt (int option_, ...@@ -175,13 +175,10 @@ int zmq::stream_t::xsetsockopt (int option_,
const void *optval_, const void *optval_,
size_t optvallen_) size_t optvallen_)
{ {
bool is_int = (optvallen_ == sizeof (int));
int value = 0;
if (is_int)
memcpy (&value, optval_, sizeof (int));
switch (option_) { switch (option_) {
case ZMQ_CONNECT_ROUTING_ID: case ZMQ_CONNECT_ROUTING_ID:
// TODO why isn't it possible to set an empty connect_routing_id
// (which is the default value)
if (optval_ && optvallen_) { if (optval_ && optvallen_) {
connect_routing_id.assign ((char *) optval_, optvallen_); connect_routing_id.assign ((char *) optval_, optvallen_);
return 0; return 0;
...@@ -189,10 +186,8 @@ int zmq::stream_t::xsetsockopt (int option_, ...@@ -189,10 +186,8 @@ int zmq::stream_t::xsetsockopt (int option_,
break; break;
case ZMQ_STREAM_NOTIFY: case ZMQ_STREAM_NOTIFY:
if (is_int && (value == 0 || value == 1)) { return do_setsockopt_int_as_bool_strict (optval_, optvallen_,
options.raw_notify = (value != 0); &options.raw_notify);
return 0;
}
break; break;
default: default:
......
...@@ -59,10 +59,7 @@ int zmq::sub_t::xsetsockopt (int option_, ...@@ -59,10 +59,7 @@ int zmq::sub_t::xsetsockopt (int option_,
int rc = msg.init_size (optvallen_ + 1); int rc = msg.init_size (optvallen_ + 1);
errno_assert (rc == 0); errno_assert (rc == 0);
unsigned char *data = (unsigned char *) msg.data (); unsigned char *data = (unsigned char *) msg.data ();
if (option_ == ZMQ_SUBSCRIBE) *data = (option_ == ZMQ_SUBSCRIBE);
*data = 1;
else if (option_ == ZMQ_UNSUBSCRIBE)
*data = 0;
// We explicitly allow a NULL subscription with size zero // We explicitly allow a NULL subscription with size zero
if (optvallen_) { if (optvallen_) {
assert (optval_); assert (optval_);
......
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