mirror of
https://github.com/zeromq/cppzmq.git
synced 2024-12-12 10:33:52 +01:00
Problem: Socket options lack type-safety (#393)
Solution: Implement a type for each socket option. Each option has an associated type, therefore they can't be simply defined as an enum class. Use new sockopt getter in test util Add socket option get function for strings and tests
This commit is contained in:
parent
10431084bb
commit
a3e5b54c3c
424
tests/socket.cpp
424
tests/socket.cpp
@ -47,22 +47,424 @@ TEST_CASE("socket swap", "[socket]")
|
||||
swap(socket1, socket2);
|
||||
}
|
||||
|
||||
#ifdef ZMQ_CPP11
|
||||
TEST_CASE("socket options", "[socket]")
|
||||
{
|
||||
zmq::context_t context;
|
||||
zmq::socket_t socket(context, zmq::socket_type::router);
|
||||
|
||||
#ifdef ZMQ_IMMEDIATE
|
||||
socket.set(zmq::sockopt::immediate, 0);
|
||||
socket.set(zmq::sockopt::immediate, false);
|
||||
CHECK(socket.get(zmq::sockopt::immediate) == false);
|
||||
// unit out of range
|
||||
CHECK_THROWS_AS(socket.set(zmq::sockopt::immediate, 80), const zmq::error_t &);
|
||||
#endif
|
||||
#ifdef ZMQ_LINGER
|
||||
socket.set(zmq::sockopt::linger, 55);
|
||||
CHECK(socket.get(zmq::sockopt::linger) == 55);
|
||||
#endif
|
||||
#ifdef ZMQ_ROUTING_ID
|
||||
const std::string id = "foobar";
|
||||
socket.set(zmq::sockopt::routing_id, "foobar");
|
||||
socket.set(zmq::sockopt::routing_id, zmq::buffer(id));
|
||||
socket.set(zmq::sockopt::routing_id, id);
|
||||
#ifdef ZMQ_CPP17
|
||||
socket.set(zmq::sockopt::routing_id, std::string_view{id});
|
||||
#endif
|
||||
|
||||
std::string id_ret(10, ' ');
|
||||
auto size = socket.get(zmq::sockopt::routing_id, zmq::buffer(id_ret));
|
||||
id_ret.resize(size);
|
||||
CHECK(id == id_ret);
|
||||
auto stropt = socket.get(zmq::sockopt::routing_id);
|
||||
CHECK(id == stropt);
|
||||
|
||||
std::string id_ret_small(3, ' ');
|
||||
// truncated
|
||||
CHECK_THROWS_AS(socket.get(zmq::sockopt::routing_id, zmq::buffer(id_ret_small)),
|
||||
const zmq::error_t &);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void check_array_opt(T opt,
|
||||
zmq::socket_t &sock,
|
||||
std::string info,
|
||||
bool set_only = false)
|
||||
{
|
||||
const std::string val = "foobar";
|
||||
INFO("setting " + info);
|
||||
sock.set(opt, val);
|
||||
if (set_only)
|
||||
return;
|
||||
|
||||
INFO("getting " + info);
|
||||
auto s = sock.get(opt);
|
||||
CHECK(s == val);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void check_array_opt_get(T opt, zmq::socket_t &sock, std::string info)
|
||||
{
|
||||
INFO("getting " + info);
|
||||
(void) sock.get(opt);
|
||||
}
|
||||
|
||||
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 0, 0)
|
||||
template<class T> void check_bin_z85(T opt, zmq::socket_t &sock, std::string str_val)
|
||||
{
|
||||
std::vector<uint8_t> bin_val(32);
|
||||
const auto dret = zmq_z85_decode(bin_val.data(), str_val.c_str());
|
||||
CHECK(dret != nullptr);
|
||||
|
||||
sock.set(opt, str_val);
|
||||
sock.set(opt, zmq::buffer(bin_val));
|
||||
auto sv = sock.get(opt);
|
||||
CHECK(sv == str_val);
|
||||
|
||||
auto bv = sock.get(opt, 32);
|
||||
REQUIRE(bv.size() == bin_val.size());
|
||||
CHECK(std::memcmp(bv.data(), bin_val.data(), bin_val.size()) == 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_CASE("socket check array options", "[socket]")
|
||||
{
|
||||
zmq::context_t context;
|
||||
zmq::socket_t router(context, zmq::socket_type::router);
|
||||
zmq::socket_t xpub(context, zmq::socket_type::xpub);
|
||||
zmq::socket_t sub(context, zmq::socket_type::sub);
|
||||
|
||||
#ifdef ZMQ_BINDTODEVICE
|
||||
// requires setting CAP_NET_RAW
|
||||
//check_array_opt(zmq::sockopt::bindtodevice, router, "bindtodevice");
|
||||
#endif
|
||||
#ifdef ZMQ_CONNECT_ROUTING_ID
|
||||
check_array_opt(zmq::sockopt::connect_routing_id, router, "connect_routing_id",
|
||||
true);
|
||||
#endif
|
||||
#ifdef ZMQ_LAST_ENDPOINT
|
||||
check_array_opt_get(zmq::sockopt::last_endpoint, router, "last_endpoint");
|
||||
#endif
|
||||
#ifdef ZMQ_METADATA
|
||||
router.set(zmq::sockopt::metadata, zmq::str_buffer("X-foo:bar"));
|
||||
#endif
|
||||
#ifdef ZMQ_PLAIN_PASSWORD
|
||||
check_array_opt(zmq::sockopt::plain_password, router, "plain_password");
|
||||
#endif
|
||||
#ifdef ZMQ_PLAIN_USERNAME
|
||||
check_array_opt(zmq::sockopt::plain_username, router, "plain_username");
|
||||
#endif
|
||||
#ifdef ZMQ_ROUTING_ID
|
||||
check_array_opt(zmq::sockopt::routing_id, router, "routing_id");
|
||||
#endif
|
||||
#ifdef ZMQ_SOCKS_PROXY
|
||||
check_array_opt(zmq::sockopt::socks_proxy, router, "socks_proxy");
|
||||
#endif
|
||||
#ifdef ZMQ_SUBSCRIBE
|
||||
check_array_opt(zmq::sockopt::subscribe, sub, "subscribe", true);
|
||||
#endif
|
||||
#ifdef ZMQ_UNSUBSCRIBE
|
||||
check_array_opt(zmq::sockopt::unsubscribe, sub, "unsubscribe", true);
|
||||
#endif
|
||||
#ifdef ZMQ_XPUB_WELCOME_MSG
|
||||
check_array_opt(zmq::sockopt::xpub_welcome_msg, xpub, "xpub_welcome_msg", true);
|
||||
#endif
|
||||
#ifdef ZMQ_ZAP_DOMAIN
|
||||
check_array_opt(zmq::sockopt::zap_domain, router, "zap_domain");
|
||||
#endif
|
||||
|
||||
// curve
|
||||
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 0, 0) && defined(ZMQ_HAS_CAPABILITIES)
|
||||
if (zmq_has("curve") == 1) {
|
||||
const std::string spk = "rq:rM>}U?@Lns47E1%kR.o@n%FcmmsL/@{H8]yf7";
|
||||
const std::string ssk = "JTKVSB%%)wK0E.X)V>+}o?pNmC{O&4W4b!Ni{Lh6";
|
||||
const std::string cpk = "Yne@$w-vo<fVvi]a<NY6T1ed:M$fCG*[IaLV{hID";
|
||||
const std::string csk = "D:)Q[IlAW!ahhC2ac:9*A}h:p?([4%wOTJ%JR%cs";
|
||||
|
||||
zmq::socket_t curve_server(context, zmq::socket_type::router);
|
||||
curve_server.set(zmq::sockopt::curve_server, true);
|
||||
CHECK(curve_server.get(zmq::sockopt::curve_server));
|
||||
check_bin_z85(zmq::sockopt::curve_secretkey, curve_server, ssk);
|
||||
|
||||
zmq::socket_t curve_client(context, zmq::socket_type::router);
|
||||
curve_client.set(zmq::sockopt::curve_server, false);
|
||||
CHECK_FALSE(curve_client.get(zmq::sockopt::curve_server));
|
||||
check_bin_z85(zmq::sockopt::curve_serverkey, curve_client, spk);
|
||||
check_bin_z85(zmq::sockopt::curve_publickey, curve_client, cpk);
|
||||
check_bin_z85(zmq::sockopt::curve_secretkey, curve_client, csk);
|
||||
}
|
||||
#endif
|
||||
|
||||
// gssapi
|
||||
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 1, 0) && defined(ZMQ_HAS_CAPABILITIES)
|
||||
if (zmq_has("gssapi") == 1 && false) // TODO enable
|
||||
{
|
||||
zmq::socket_t gss_server(context, zmq::socket_type::router);
|
||||
gss_server.set(zmq::sockopt::gssapi_server, true);
|
||||
CHECK(gss_server.get(zmq::sockopt::gssapi_server) == 1);
|
||||
gss_server.set(zmq::sockopt::gssapi_plaintext, false);
|
||||
CHECK(gss_server.get(zmq::sockopt::gssapi_plaintext) == 0);
|
||||
check_array_opt(zmq::sockopt::gssapi_principal, gss_server,
|
||||
"gssapi_principal");
|
||||
|
||||
zmq::socket_t gss_client(context, zmq::socket_type::router);
|
||||
CHECK(gss_client.get(zmq::sockopt::gssapi_server) == 0);
|
||||
check_array_opt(zmq::sockopt::gssapi_principal, gss_client,
|
||||
"gssapi_principal");
|
||||
check_array_opt(zmq::sockopt::gssapi_service_principal, gss_client,
|
||||
"gssapi_service_principal");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class T, class Opt>
|
||||
void check_integral_opt(Opt opt,
|
||||
zmq::socket_t &sock,
|
||||
std::string info,
|
||||
bool set_only = false)
|
||||
{
|
||||
const T val = 1;
|
||||
INFO("setting " + info);
|
||||
sock.set(opt, val);
|
||||
if (set_only)
|
||||
return;
|
||||
|
||||
INFO("getting " + info);
|
||||
auto s = sock.get(opt);
|
||||
CHECK(s == val);
|
||||
}
|
||||
|
||||
template<class T, class Opt>
|
||||
void check_integral_opt_get(Opt opt, zmq::socket_t &sock, std::string info)
|
||||
{
|
||||
INFO("getting " + info);
|
||||
(void) sock.get(opt);
|
||||
}
|
||||
|
||||
TEST_CASE("socket check integral options", "[socket]")
|
||||
{
|
||||
zmq::context_t context;
|
||||
zmq::socket_t router(context, zmq::socket_type::router);
|
||||
zmq::socket_t xpub(context, zmq::socket_type::xpub);
|
||||
zmq::socket_t req(context, zmq::socket_type::req);
|
||||
#ifdef ZMQ_STREAM_NOTIFY
|
||||
zmq::socket_t stream(context, zmq::socket_type::stream);
|
||||
#endif
|
||||
|
||||
#ifdef ZMQ_AFFINITY
|
||||
check_integral_opt<uint64_t>(zmq::sockopt::affinity, router, "affinity");
|
||||
#endif
|
||||
#ifdef ZMQ_BACKLOG
|
||||
check_integral_opt<int>(zmq::sockopt::backlog, router, "backlog");
|
||||
#endif
|
||||
#ifdef ZMQ_CONFLATE
|
||||
check_integral_opt<int>(zmq::sockopt::conflate, router, "conflate");
|
||||
#endif
|
||||
#ifdef ZMQ_CONNECT_TIMEOUT
|
||||
check_integral_opt<int>(zmq::sockopt::connect_timeout, router,
|
||||
"connect_timeout");
|
||||
#endif
|
||||
#ifdef ZMQ_EVENTS
|
||||
check_integral_opt_get<int>(zmq::sockopt::events, router, "events");
|
||||
#endif
|
||||
#ifdef ZMQ_FD
|
||||
check_integral_opt_get<zmq::sockopt::cppzmq_fd_t>(zmq::sockopt::fd, router,
|
||||
"fd");
|
||||
#endif
|
||||
#ifdef ZMQ_HANDSHAKE_IVL
|
||||
check_integral_opt<int>(zmq::sockopt::handshake_ivl, router, "handshake_ivl");
|
||||
#endif
|
||||
#ifdef ZMQ_HEARTBEAT_IVL
|
||||
check_integral_opt<int>(zmq::sockopt::heartbeat_ivl, router, "heartbeat_ivl");
|
||||
#endif
|
||||
#ifdef ZMQ_HEARTBEAT_TIMEOUT
|
||||
check_integral_opt<int>(zmq::sockopt::heartbeat_timeout, router,
|
||||
"heartbeat_timeout");
|
||||
#endif
|
||||
#ifdef ZMQ_HEARTBEAT_TTL
|
||||
router.set(zmq::sockopt::heartbeat_ttl, 100);
|
||||
CHECK(router.get(zmq::sockopt::heartbeat_ttl) == 100);
|
||||
#endif
|
||||
#ifdef ZMQ_IMMEDIATE
|
||||
check_integral_opt<int>(zmq::sockopt::immediate, router, "immediate");
|
||||
#endif
|
||||
#ifdef ZMQ_INVERT_MATCHING
|
||||
check_integral_opt<int>(zmq::sockopt::invert_matching, router,
|
||||
"invert_matching");
|
||||
#endif
|
||||
#ifdef ZMQ_IPV6
|
||||
check_integral_opt<int>(zmq::sockopt::ipv6, router, "ipv6");
|
||||
#endif
|
||||
#ifdef ZMQ_LINGER
|
||||
check_integral_opt<int>(zmq::sockopt::linger, router, "linger");
|
||||
#endif
|
||||
#ifdef ZMQ_MAXMSGSIZE
|
||||
check_integral_opt<int64_t>(zmq::sockopt::maxmsgsize, router, "maxmsgsize");
|
||||
#endif
|
||||
#ifdef ZMQ_MECHANISM
|
||||
check_integral_opt_get<int>(zmq::sockopt::mechanism, router, "mechanism");
|
||||
#endif
|
||||
#ifdef ZMQ_MULTICAST_HOPS
|
||||
check_integral_opt<int>(zmq::sockopt::multicast_hops, router, "multicast_hops");
|
||||
#endif
|
||||
#ifdef ZMQ_MULTICAST_LOOP
|
||||
check_integral_opt<int>(zmq::sockopt::multicast_loop, router, "multicast_loop");
|
||||
#endif
|
||||
#ifdef ZMQ_MULTICAST_MAXTPDU
|
||||
check_integral_opt<int>(zmq::sockopt::multicast_maxtpdu, router,
|
||||
"multicast_maxtpdu");
|
||||
#endif
|
||||
#ifdef ZMQ_PLAIN_SERVER
|
||||
check_integral_opt<int>(zmq::sockopt::plain_server, router, "plain_server");
|
||||
#endif
|
||||
#ifdef ZMQ_USE_FD
|
||||
check_integral_opt<int>(zmq::sockopt::use_fd, router, "use_fd");
|
||||
#endif
|
||||
#ifdef ZMQ_PROBE_ROUTER
|
||||
check_integral_opt<int>(zmq::sockopt::probe_router, router, "probe_router",
|
||||
true);
|
||||
#endif
|
||||
#ifdef ZMQ_RATE
|
||||
check_integral_opt<int>(zmq::sockopt::rate, router, "rate");
|
||||
#endif
|
||||
#ifdef ZMQ_RCVBUF
|
||||
check_integral_opt<int>(zmq::sockopt::rcvbuf, router, "rcvbuf");
|
||||
#endif
|
||||
#ifdef ZMQ_RCVHWM
|
||||
check_integral_opt<int>(zmq::sockopt::rcvhwm, router, "rcvhwm");
|
||||
#endif
|
||||
#ifdef ZMQ_RCVMORE
|
||||
check_integral_opt_get<int>(zmq::sockopt::rcvmore, router, "rcvmore");
|
||||
#endif
|
||||
#ifdef ZMQ_RCVTIMEO
|
||||
check_integral_opt<int>(zmq::sockopt::rcvtimeo, router, "rcvtimeo");
|
||||
#endif
|
||||
#ifdef ZMQ_RECONNECT_IVL
|
||||
check_integral_opt<int>(zmq::sockopt::reconnect_ivl, router, "reconnect_ivl");
|
||||
#endif
|
||||
#ifdef ZMQ_RECONNECT_IVL_MAX
|
||||
check_integral_opt<int>(zmq::sockopt::reconnect_ivl_max, router,
|
||||
"reconnect_ivl_max");
|
||||
#endif
|
||||
#ifdef ZMQ_RECOVERY_IVL
|
||||
check_integral_opt<int>(zmq::sockopt::recovery_ivl, router, "recovery_ivl");
|
||||
#endif
|
||||
#ifdef ZMQ_REQ_CORRELATE
|
||||
check_integral_opt<int>(zmq::sockopt::req_correlate, req, "req_correlate", true);
|
||||
#endif
|
||||
#ifdef ZMQ_REQ_RELAXED
|
||||
check_integral_opt<int>(zmq::sockopt::req_relaxed, req, "req_relaxed", true);
|
||||
#endif
|
||||
#ifdef ZMQ_ROUTER_HANDOVER
|
||||
check_integral_opt<int>(zmq::sockopt::router_handover, router, "router_handover",
|
||||
true);
|
||||
#endif
|
||||
#ifdef ZMQ_ROUTER_MANDATORY
|
||||
check_integral_opt<int>(zmq::sockopt::router_mandatory, router,
|
||||
"router_mandatory", true);
|
||||
#endif
|
||||
#ifdef ZMQ_ROUTER_NOTIFY
|
||||
check_integral_opt<int>(zmq::sockopt::router_notify, router, "router_notify");
|
||||
#endif
|
||||
#ifdef ZMQ_SNDBUF
|
||||
check_integral_opt<int>(zmq::sockopt::sndbuf, router, "sndbuf");
|
||||
#endif
|
||||
#ifdef ZMQ_SNDHWM
|
||||
check_integral_opt<int>(zmq::sockopt::sndhwm, router, "sndhwm");
|
||||
#endif
|
||||
#ifdef ZMQ_SNDTIMEO
|
||||
check_integral_opt<int>(zmq::sockopt::sndtimeo, router, "sndtimeo");
|
||||
#endif
|
||||
#ifdef ZMQ_STREAM_NOTIFY
|
||||
check_integral_opt<int>(zmq::sockopt::stream_notify, stream, "stream_notify",
|
||||
true);
|
||||
#endif
|
||||
#ifdef ZMQ_TCP_KEEPALIVE
|
||||
check_integral_opt<int>(zmq::sockopt::tcp_keepalive, router, "tcp_keepalive");
|
||||
#endif
|
||||
#ifdef ZMQ_TCP_KEEPALIVE_CNT
|
||||
check_integral_opt<int>(zmq::sockopt::tcp_keepalive_cnt, router,
|
||||
"tcp_keepalive_cnt");
|
||||
#endif
|
||||
#ifdef ZMQ_TCP_KEEPALIVE_IDLE
|
||||
check_integral_opt<int>(zmq::sockopt::tcp_keepalive_idle, router,
|
||||
"tcp_keepalive_idle");
|
||||
#endif
|
||||
#ifdef ZMQ_TCP_KEEPALIVE_INTVL
|
||||
check_integral_opt<int>(zmq::sockopt::tcp_keepalive_intvl, router,
|
||||
"tcp_keepalive_intvl");
|
||||
#endif
|
||||
#ifdef ZMQ_TCP_MAXRT
|
||||
check_integral_opt<int>(zmq::sockopt::tcp_maxrt, router, "tcp_maxrt");
|
||||
#endif
|
||||
#ifdef ZMQ_THREAD_SAFE
|
||||
check_integral_opt_get<bool>(zmq::sockopt::thread_safe, router, "thread_safe");
|
||||
#endif
|
||||
#ifdef ZMQ_TOS
|
||||
check_integral_opt<int>(zmq::sockopt::tos, router, "tos");
|
||||
#endif
|
||||
#ifdef ZMQ_TYPE
|
||||
check_integral_opt_get<int>(zmq::sockopt::type, router, "type");
|
||||
#endif
|
||||
|
||||
#ifdef ZMQ_HAVE_VMCI
|
||||
#ifdef ZMQ_VMCI_BUFFER_SIZE
|
||||
check_integral_opt<uint64_t>(zmq::sockopt::vmci_buffer_size, router,
|
||||
"vmci_buffer_size");
|
||||
#endif
|
||||
#ifdef ZMQ_VMCI_BUFFER_MIN_SIZE
|
||||
check_integral_opt<uint64_t>(zmq::sockopt::vmci_buffer_min_size, router,
|
||||
"vmci_buffer_min_size");
|
||||
#endif
|
||||
#ifdef ZMQ_VMCI_BUFFER_MAX_SIZE
|
||||
check_integral_opt<uint64_t>(zmq::sockopt::vmci_buffer_max_size, router,
|
||||
"vmci_buffer_max_size");
|
||||
#endif
|
||||
#ifdef ZMQ_VMCI_CONNECT_TIMEOUT
|
||||
check_integral_opt<int>(zmq::sockopt::vmci_connect_timeout, router,
|
||||
"vmci_connect_timeout");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ZMQ_XPUB_VERBOSE
|
||||
check_integral_opt<int>(zmq::sockopt::xpub_verbose, xpub, "xpub_verbose", true);
|
||||
#endif
|
||||
#ifdef ZMQ_XPUB_VERBOSER
|
||||
check_integral_opt<int>(zmq::sockopt::xpub_verboser, xpub, "xpub_verboser",
|
||||
true);
|
||||
#endif
|
||||
#ifdef ZMQ_XPUB_MANUAL
|
||||
check_integral_opt<int>(zmq::sockopt::xpub_manual, xpub, "xpub_manual", true);
|
||||
#endif
|
||||
#ifdef ZMQ_XPUB_NODROP
|
||||
check_integral_opt<int>(zmq::sockopt::xpub_nodrop, xpub, "xpub_nodrop", true);
|
||||
#endif
|
||||
#ifdef ZMQ_ZAP_ENFORCE_DOMAIN
|
||||
check_integral_opt<int>(zmq::sockopt::zap_enforce_domain, router,
|
||||
"zap_enforce_domain");
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
TEST_CASE("socket flags", "[socket]")
|
||||
{
|
||||
CHECK((zmq::recv_flags::dontwait | zmq::recv_flags::none)
|
||||
== static_cast<zmq::recv_flags>(ZMQ_DONTWAIT | 0));
|
||||
== static_cast<zmq::recv_flags>(ZMQ_DONTWAIT | 0));
|
||||
CHECK((zmq::recv_flags::dontwait & zmq::recv_flags::none)
|
||||
== static_cast<zmq::recv_flags>(ZMQ_DONTWAIT & 0));
|
||||
== static_cast<zmq::recv_flags>(ZMQ_DONTWAIT & 0));
|
||||
CHECK((zmq::recv_flags::dontwait ^ zmq::recv_flags::none)
|
||||
== static_cast<zmq::recv_flags>(ZMQ_DONTWAIT ^ 0));
|
||||
== static_cast<zmq::recv_flags>(ZMQ_DONTWAIT ^ 0));
|
||||
CHECK(~zmq::recv_flags::dontwait == static_cast<zmq::recv_flags>(~ZMQ_DONTWAIT));
|
||||
|
||||
CHECK((zmq::send_flags::dontwait | zmq::send_flags::sndmore)
|
||||
== static_cast<zmq::send_flags>(ZMQ_DONTWAIT | ZMQ_SNDMORE));
|
||||
== static_cast<zmq::send_flags>(ZMQ_DONTWAIT | ZMQ_SNDMORE));
|
||||
CHECK((zmq::send_flags::dontwait & zmq::send_flags::sndmore)
|
||||
== static_cast<zmq::send_flags>(ZMQ_DONTWAIT & ZMQ_SNDMORE));
|
||||
== static_cast<zmq::send_flags>(ZMQ_DONTWAIT & ZMQ_SNDMORE));
|
||||
CHECK((zmq::send_flags::dontwait ^ zmq::send_flags::sndmore)
|
||||
== static_cast<zmq::send_flags>(ZMQ_DONTWAIT ^ ZMQ_SNDMORE));
|
||||
== static_cast<zmq::send_flags>(ZMQ_DONTWAIT ^ ZMQ_SNDMORE));
|
||||
CHECK(~zmq::send_flags::dontwait == static_cast<zmq::send_flags>(~ZMQ_DONTWAIT));
|
||||
}
|
||||
|
||||
@ -125,8 +527,8 @@ TEST_CASE("socket send dontwait", "[socket]")
|
||||
std::vector<char> buf(4);
|
||||
auto res = s.send(zmq::buffer(buf), zmq::send_flags::dontwait);
|
||||
CHECK(!res);
|
||||
res = s.send(zmq::buffer(buf),
|
||||
zmq::send_flags::dontwait | zmq::send_flags::sndmore);
|
||||
res =
|
||||
s.send(zmq::buffer(buf), zmq::send_flags::dontwait | zmq::send_flags::sndmore);
|
||||
CHECK(!res);
|
||||
|
||||
zmq::message_t msg;
|
||||
@ -253,8 +655,7 @@ TEST_CASE("socket proxy", "[socket]")
|
||||
front.bind("inproc://test1");
|
||||
back.bind("inproc://test2");
|
||||
capture.bind("inproc://test3");
|
||||
auto f = std::async(std::launch::async, [&]()
|
||||
{
|
||||
auto f = std::async(std::launch::async, [&]() {
|
||||
auto s1 = std::move(front);
|
||||
auto s2 = std::move(back);
|
||||
auto s3 = std::move(capture);
|
||||
@ -279,8 +680,7 @@ TEST_CASE("socket proxy steerable", "[socket]")
|
||||
front.bind("inproc://test1");
|
||||
back.bind("inproc://test2");
|
||||
control.connect("inproc://test3");
|
||||
auto f = std::async(std::launch::async, [&]()
|
||||
{
|
||||
auto f = std::async(std::launch::async, [&]() {
|
||||
auto s1 = std::move(front);
|
||||
auto s2 = std::move(back);
|
||||
auto s3 = std::move(control);
|
||||
|
@ -4,30 +4,14 @@
|
||||
#include <zmq.hpp>
|
||||
|
||||
#if defined(ZMQ_CPP11)
|
||||
#include <array>
|
||||
|
||||
class loopback_ip4_binder
|
||||
inline std::string bind_ip4_loopback(zmq::socket_t &socket)
|
||||
{
|
||||
public:
|
||||
loopback_ip4_binder(zmq::socket_t &socket) { bind(socket); }
|
||||
std::string endpoint() { return endpoint_; }
|
||||
|
||||
private:
|
||||
// Helper function used in constructor
|
||||
// as Gtest allows ASSERT_* only in void returning functions
|
||||
// and constructor/destructor are not.
|
||||
void bind(zmq::socket_t &socket)
|
||||
{
|
||||
REQUIRE_NOTHROW(socket.bind("tcp://127.0.0.1:*"));
|
||||
std::array<char, 100> endpoint{};
|
||||
size_t endpoint_size = endpoint.size();
|
||||
REQUIRE_NOTHROW(
|
||||
socket.getsockopt(ZMQ_LAST_ENDPOINT, endpoint.data(), &endpoint_size));
|
||||
REQUIRE(endpoint_size < endpoint.size());
|
||||
endpoint_ = std::string{endpoint.data()};
|
||||
}
|
||||
std::string endpoint_;
|
||||
};
|
||||
socket.bind("tcp://127.0.0.1:*");
|
||||
std::string endpoint(100, ' ');
|
||||
endpoint.resize(socket.get(zmq::sockopt::last_endpoint, zmq::buffer(endpoint)));
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
struct common_server_client_setup
|
||||
{
|
||||
@ -39,7 +23,7 @@ struct common_server_client_setup
|
||||
|
||||
void init()
|
||||
{
|
||||
endpoint = loopback_ip4_binder{server}.endpoint();
|
||||
endpoint = bind_ip4_loopback(server);
|
||||
REQUIRE_NOTHROW(client.connect(endpoint));
|
||||
}
|
||||
|
||||
|
429
zmq.hpp
429
zmq.hpp
@ -80,6 +80,11 @@
|
||||
#define ZMQ_CONSTEXPR_VAR const
|
||||
#define ZMQ_CPP11_DEPRECATED(msg)
|
||||
#endif
|
||||
#if defined(ZMQ_CPP17)
|
||||
#define ZMQ_INLINE_VAR inline
|
||||
#else
|
||||
#define ZMQ_INLINE_VAR
|
||||
#endif
|
||||
|
||||
#include <zmq.h>
|
||||
|
||||
@ -1268,6 +1273,297 @@ constexpr const_buffer operator"" _zbuf(const char32_t *str, size_t len) noexcep
|
||||
|
||||
#endif // ZMQ_CPP11
|
||||
|
||||
|
||||
#ifdef ZMQ_CPP11
|
||||
namespace sockopt
|
||||
{
|
||||
// There are two types of options,
|
||||
// integral type with known compiler time size (int, bool, int64_t, uint64_t)
|
||||
// and arrays with dynamic size (strings, binary data).
|
||||
|
||||
// BoolUnit: if true accepts values of type bool (but passed as T into libzmq)
|
||||
template<int Opt, class T, bool BoolUnit = false> struct integral_option
|
||||
{
|
||||
};
|
||||
|
||||
// NullTerm:
|
||||
// 0: binary data
|
||||
// 1: null-terminated string (`getsockopt` size includes null)
|
||||
// 2: binary (size 32) or Z85 encoder string of size 41 (null included)
|
||||
template<int Opt, int NullTerm = 1> struct array_option
|
||||
{
|
||||
};
|
||||
|
||||
#define ZMQ_DEFINE_INTEGRAL_OPT(OPT, NAME, TYPE) \
|
||||
using NAME##_t = integral_option<OPT, TYPE, false>; \
|
||||
ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME
|
||||
#define ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(OPT, NAME, TYPE) \
|
||||
using NAME##_t = integral_option<OPT, TYPE, true>; \
|
||||
ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME
|
||||
#define ZMQ_DEFINE_ARRAY_OPT(OPT, NAME) \
|
||||
using NAME##_t = array_option<OPT>; \
|
||||
ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME
|
||||
#define ZMQ_DEFINE_ARRAY_OPT_BINARY(OPT, NAME) \
|
||||
using NAME##_t = array_option<OPT, 0>; \
|
||||
ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME
|
||||
#define ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(OPT, NAME) \
|
||||
using NAME##_t = array_option<OPT, 2>; \
|
||||
ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME
|
||||
|
||||
// duplicate definition from libzmq 4.3.3
|
||||
#if defined _WIN32
|
||||
#if defined _WIN64
|
||||
typedef unsigned __int64 cppzmq_fd_t;
|
||||
#else
|
||||
typedef unsigned int cppzmq_fd_t;
|
||||
#endif
|
||||
#else
|
||||
typedef int cppzmq_fd_t;
|
||||
#endif
|
||||
|
||||
#ifdef ZMQ_AFFINITY
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_AFFINITY, affinity, uint64_t);
|
||||
#endif
|
||||
#ifdef ZMQ_BACKLOG
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_BACKLOG, backlog, int);
|
||||
#endif
|
||||
#ifdef ZMQ_BINDTODEVICE
|
||||
ZMQ_DEFINE_ARRAY_OPT_BINARY(ZMQ_BINDTODEVICE, bindtodevice);
|
||||
#endif
|
||||
#ifdef ZMQ_CONFLATE
|
||||
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_CONFLATE, conflate, int);
|
||||
#endif
|
||||
#ifdef ZMQ_CONNECT_ROUTING_ID
|
||||
ZMQ_DEFINE_ARRAY_OPT(ZMQ_CONNECT_ROUTING_ID, connect_routing_id);
|
||||
#endif
|
||||
#ifdef ZMQ_CONNECT_TIMEOUT
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_CONNECT_TIMEOUT, connect_timeout, int);
|
||||
#endif
|
||||
#ifdef ZMQ_CURVE_PUBLICKEY
|
||||
ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(ZMQ_CURVE_PUBLICKEY, curve_publickey);
|
||||
#endif
|
||||
#ifdef ZMQ_CURVE_SECRETKEY
|
||||
ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(ZMQ_CURVE_SECRETKEY, curve_secretkey);
|
||||
#endif
|
||||
#ifdef ZMQ_CURVE_SERVER
|
||||
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_CURVE_SERVER, curve_server, int);
|
||||
#endif
|
||||
#ifdef ZMQ_CURVE_SERVERKEY
|
||||
ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(ZMQ_CURVE_SERVERKEY, curve_serverkey);
|
||||
#endif
|
||||
#ifdef ZMQ_EVENTS
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_EVENTS, events, int);
|
||||
#endif
|
||||
#ifdef ZMQ_FD
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_FD, fd, cppzmq_fd_t);
|
||||
#endif
|
||||
#ifdef ZMQ_GSSAPI_PLAINTEXT
|
||||
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_GSSAPI_PLAINTEXT, gssapi_plaintext, int);
|
||||
#endif
|
||||
#ifdef ZMQ_GSSAPI_SERVER
|
||||
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_GSSAPI_SERVER, gssapi_server, int);
|
||||
#endif
|
||||
#ifdef ZMQ_GSSAPI_SERVICE_PRINCIPAL
|
||||
ZMQ_DEFINE_ARRAY_OPT(ZMQ_GSSAPI_SERVICE_PRINCIPAL, gssapi_service_principal);
|
||||
#endif
|
||||
#ifdef ZMQ_GSSAPI_SERVICE_PRINCIPAL_NAMETYPE
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_GSSAPI_SERVICE_PRINCIPAL_NAMETYPE,
|
||||
gssapi_service_principal_nametype,
|
||||
int);
|
||||
#endif
|
||||
#ifdef ZMQ_GSSAPI_PRINCIPAL
|
||||
ZMQ_DEFINE_ARRAY_OPT(ZMQ_GSSAPI_PRINCIPAL, gssapi_principal);
|
||||
#endif
|
||||
#ifdef ZMQ_GSSAPI_PRINCIPAL_NAMETYPE
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_GSSAPI_PRINCIPAL_NAMETYPE,
|
||||
gssapi_principal_nametype,
|
||||
int);
|
||||
#endif
|
||||
#ifdef ZMQ_HANDSHAKE_IVL
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HANDSHAKE_IVL, handshake_ivl, int);
|
||||
#endif
|
||||
#ifdef ZMQ_HEARTBEAT_IVL
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HEARTBEAT_IVL, heartbeat_ivl, int);
|
||||
#endif
|
||||
#ifdef ZMQ_HEARTBEAT_TIMEOUT
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HEARTBEAT_TIMEOUT, heartbeat_timeout, int);
|
||||
#endif
|
||||
#ifdef ZMQ_HEARTBEAT_TTL
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HEARTBEAT_TTL, heartbeat_ttl, int);
|
||||
#endif
|
||||
#ifdef ZMQ_IMMEDIATE
|
||||
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_IMMEDIATE, immediate, int);
|
||||
#endif
|
||||
#ifdef ZMQ_INVERT_MATCHING
|
||||
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_INVERT_MATCHING, invert_matching, int);
|
||||
#endif
|
||||
#ifdef ZMQ_IPV6
|
||||
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_IPV6, ipv6, int);
|
||||
#endif
|
||||
#ifdef ZMQ_LAST_ENDPOINT
|
||||
ZMQ_DEFINE_ARRAY_OPT(ZMQ_LAST_ENDPOINT, last_endpoint);
|
||||
#endif
|
||||
#ifdef ZMQ_LINGER
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_LINGER, linger, int);
|
||||
#endif
|
||||
#ifdef ZMQ_MAXMSGSIZE
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MAXMSGSIZE, maxmsgsize, int64_t);
|
||||
#endif
|
||||
#ifdef ZMQ_MECHANISM
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MECHANISM, mechanism, int);
|
||||
#endif
|
||||
#ifdef ZMQ_METADATA
|
||||
ZMQ_DEFINE_ARRAY_OPT(ZMQ_METADATA, metadata);
|
||||
#endif
|
||||
#ifdef ZMQ_MULTICAST_HOPS
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MULTICAST_HOPS, multicast_hops, int);
|
||||
#endif
|
||||
#ifdef ZMQ_MULTICAST_LOOP
|
||||
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_MULTICAST_LOOP, multicast_loop, int);
|
||||
#endif
|
||||
#ifdef ZMQ_MULTICAST_MAXTPDU
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MULTICAST_MAXTPDU, multicast_maxtpdu, int);
|
||||
#endif
|
||||
#ifdef ZMQ_PLAIN_SERVER
|
||||
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_PLAIN_SERVER, plain_server, int);
|
||||
#endif
|
||||
#ifdef ZMQ_PLAIN_PASSWORD
|
||||
ZMQ_DEFINE_ARRAY_OPT(ZMQ_PLAIN_PASSWORD, plain_password);
|
||||
#endif
|
||||
#ifdef ZMQ_PLAIN_USERNAME
|
||||
ZMQ_DEFINE_ARRAY_OPT(ZMQ_PLAIN_USERNAME, plain_username);
|
||||
#endif
|
||||
#ifdef ZMQ_USE_FD
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_USE_FD, use_fd, int);
|
||||
#endif
|
||||
#ifdef ZMQ_PROBE_ROUTER
|
||||
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_PROBE_ROUTER, probe_router, int);
|
||||
#endif
|
||||
#ifdef ZMQ_RATE
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RATE, rate, int);
|
||||
#endif
|
||||
#ifdef ZMQ_RCVBUF
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RCVBUF, rcvbuf, int);
|
||||
#endif
|
||||
#ifdef ZMQ_RCVHWM
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RCVHWM, rcvhwm, int);
|
||||
#endif
|
||||
#ifdef ZMQ_RCVMORE
|
||||
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_RCVMORE, rcvmore, int);
|
||||
#endif
|
||||
#ifdef ZMQ_RCVTIMEO
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RCVTIMEO, rcvtimeo, int);
|
||||
#endif
|
||||
#ifdef ZMQ_RECONNECT_IVL
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RECONNECT_IVL, reconnect_ivl, int);
|
||||
#endif
|
||||
#ifdef ZMQ_RECONNECT_IVL_MAX
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RECONNECT_IVL_MAX, reconnect_ivl_max, int);
|
||||
#endif
|
||||
#ifdef ZMQ_RECOVERY_IVL
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RECOVERY_IVL, recovery_ivl, int);
|
||||
#endif
|
||||
#ifdef ZMQ_REQ_CORRELATE
|
||||
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_REQ_CORRELATE, req_correlate, int);
|
||||
#endif
|
||||
#ifdef ZMQ_REQ_RELAXED
|
||||
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_REQ_RELAXED, req_relaxed, int);
|
||||
#endif
|
||||
#ifdef ZMQ_ROUTER_HANDOVER
|
||||
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ROUTER_HANDOVER, router_handover, int);
|
||||
#endif
|
||||
#ifdef ZMQ_ROUTER_MANDATORY
|
||||
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ROUTER_MANDATORY, router_mandatory, int);
|
||||
#endif
|
||||
#ifdef ZMQ_ROUTER_NOTIFY
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_ROUTER_NOTIFY, router_notify, int);
|
||||
#endif
|
||||
#ifdef ZMQ_ROUTING_ID
|
||||
ZMQ_DEFINE_ARRAY_OPT_BINARY(ZMQ_ROUTING_ID, routing_id);
|
||||
#endif
|
||||
#ifdef ZMQ_SNDBUF
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_SNDBUF, sndbuf, int);
|
||||
#endif
|
||||
#ifdef ZMQ_SNDHWM
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_SNDHWM, sndhwm, int);
|
||||
#endif
|
||||
#ifdef ZMQ_SNDTIMEO
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_SNDTIMEO, sndtimeo, int);
|
||||
#endif
|
||||
#ifdef ZMQ_SOCKS_PROXY
|
||||
ZMQ_DEFINE_ARRAY_OPT(ZMQ_SOCKS_PROXY, socks_proxy);
|
||||
#endif
|
||||
#ifdef ZMQ_STREAM_NOTIFY
|
||||
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_STREAM_NOTIFY, stream_notify, int);
|
||||
#endif
|
||||
#ifdef ZMQ_SUBSCRIBE
|
||||
ZMQ_DEFINE_ARRAY_OPT(ZMQ_SUBSCRIBE, subscribe);
|
||||
#endif
|
||||
#ifdef ZMQ_TCP_KEEPALIVE
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE, tcp_keepalive, int);
|
||||
#endif
|
||||
#ifdef ZMQ_TCP_KEEPALIVE_CNT
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE_CNT, tcp_keepalive_cnt, int);
|
||||
#endif
|
||||
#ifdef ZMQ_TCP_KEEPALIVE_IDLE
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE_IDLE, tcp_keepalive_idle, int);
|
||||
#endif
|
||||
#ifdef ZMQ_TCP_KEEPALIVE_INTVL
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE_INTVL, tcp_keepalive_intvl, int);
|
||||
#endif
|
||||
#ifdef ZMQ_TCP_MAXRT
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_MAXRT, tcp_maxrt, int);
|
||||
#endif
|
||||
#ifdef ZMQ_THREAD_SAFE
|
||||
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_THREAD_SAFE, thread_safe, int);
|
||||
#endif
|
||||
#ifdef ZMQ_TOS
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TOS, tos, int);
|
||||
#endif
|
||||
#ifdef ZMQ_TYPE
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TYPE, type, int);
|
||||
#endif
|
||||
#ifdef ZMQ_UNSUBSCRIBE
|
||||
ZMQ_DEFINE_ARRAY_OPT(ZMQ_UNSUBSCRIBE, unsubscribe);
|
||||
#endif
|
||||
#ifdef ZMQ_VMCI_BUFFER_SIZE
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_BUFFER_SIZE, vmci_buffer_size, uint64_t);
|
||||
#endif
|
||||
#ifdef ZMQ_VMCI_BUFFER_MIN_SIZE
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_BUFFER_MIN_SIZE, vmci_buffer_min_size, uint64_t);
|
||||
#endif
|
||||
#ifdef ZMQ_VMCI_BUFFER_MAX_SIZE
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_BUFFER_MAX_SIZE, vmci_buffer_max_size, uint64_t);
|
||||
#endif
|
||||
#ifdef ZMQ_VMCI_CONNECT_TIMEOUT
|
||||
ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_CONNECT_TIMEOUT, vmci_connect_timeout, int);
|
||||
#endif
|
||||
#ifdef ZMQ_XPUB_VERBOSE
|
||||
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_VERBOSE, xpub_verbose, int);
|
||||
#endif
|
||||
#ifdef ZMQ_XPUB_VERBOSER
|
||||
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_VERBOSER, xpub_verboser, int);
|
||||
#endif
|
||||
#ifdef ZMQ_XPUB_MANUAL
|
||||
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_MANUAL, xpub_manual, int);
|
||||
#endif
|
||||
#ifdef ZMQ_XPUB_NODROP
|
||||
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_NODROP, xpub_nodrop, int);
|
||||
#endif
|
||||
#ifdef ZMQ_XPUB_WELCOME_MSG
|
||||
ZMQ_DEFINE_ARRAY_OPT(ZMQ_XPUB_WELCOME_MSG, xpub_welcome_msg);
|
||||
#endif
|
||||
#ifdef ZMQ_ZAP_ENFORCE_DOMAIN
|
||||
ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ZAP_ENFORCE_DOMAIN, zap_enforce_domain, int);
|
||||
#endif
|
||||
#ifdef ZMQ_ZAP_DOMAIN
|
||||
ZMQ_DEFINE_ARRAY_OPT(ZMQ_ZAP_DOMAIN, zap_domain);
|
||||
#endif
|
||||
|
||||
} // namespace sockopt
|
||||
#endif // ZMQ_CPP11
|
||||
|
||||
|
||||
namespace detail
|
||||
{
|
||||
class socket_base
|
||||
@ -1276,11 +1572,14 @@ class socket_base
|
||||
socket_base() ZMQ_NOTHROW : _handle(ZMQ_NULLPTR) {}
|
||||
ZMQ_EXPLICIT socket_base(void *handle) ZMQ_NOTHROW : _handle(handle) {}
|
||||
|
||||
template<typename T> void setsockopt(int option_, T const &optval)
|
||||
template<typename T>
|
||||
ZMQ_CPP11_DEPRECATED("from 4.7.0, use `set` taking option from zmq::sockopt")
|
||||
void setsockopt(int option_, T const &optval)
|
||||
{
|
||||
setsockopt(option_, &optval, sizeof(T));
|
||||
}
|
||||
|
||||
ZMQ_CPP11_DEPRECATED("from 4.7.0, use `set` taking option from zmq::sockopt")
|
||||
void setsockopt(int option_, const void *optval_, size_t optvallen_)
|
||||
{
|
||||
int rc = zmq_setsockopt(_handle, option_, optval_, optvallen_);
|
||||
@ -1288,6 +1587,7 @@ class socket_base
|
||||
throw error_t();
|
||||
}
|
||||
|
||||
ZMQ_CPP11_DEPRECATED("from 4.7.0, use `get` taking option from zmq::sockopt")
|
||||
void getsockopt(int option_, void *optval_, size_t *optvallen_) const
|
||||
{
|
||||
int rc = zmq_getsockopt(_handle, option_, optval_, optvallen_);
|
||||
@ -1295,7 +1595,9 @@ class socket_base
|
||||
throw error_t();
|
||||
}
|
||||
|
||||
template<typename T> T getsockopt(int option_) const
|
||||
template<typename T>
|
||||
ZMQ_CPP11_DEPRECATED("from 4.7.0, use `get` taking option from zmq::sockopt")
|
||||
T getsockopt(int option_) const
|
||||
{
|
||||
T optval;
|
||||
size_t optlen = sizeof(T);
|
||||
@ -1303,6 +1605,114 @@ class socket_base
|
||||
return optval;
|
||||
}
|
||||
|
||||
#ifdef ZMQ_CPP11
|
||||
// Set integral socket option, e.g.
|
||||
// `socket.set(zmq::sockopt::linger, 0)`
|
||||
template<int Opt, class T, bool BoolUnit>
|
||||
void set(sockopt::integral_option<Opt, T, BoolUnit>, const T &val)
|
||||
{
|
||||
static_assert(std::is_integral<T>::value, "T must be integral");
|
||||
set_option(Opt, &val, sizeof val);
|
||||
}
|
||||
|
||||
// Set integral socket option from boolean, e.g.
|
||||
// `socket.set(zmq::sockopt::immediate, false)`
|
||||
template<int Opt, class T>
|
||||
void set(sockopt::integral_option<Opt, T, true>, bool val)
|
||||
{
|
||||
static_assert(std::is_integral<T>::value, "T must be integral");
|
||||
T rep_val = val;
|
||||
set_option(Opt, &rep_val, sizeof rep_val);
|
||||
}
|
||||
|
||||
// Set array socket option, e.g.
|
||||
// `socket.set(zmq::sockopt::plain_username, "foo123")`
|
||||
template<int Opt, int NullTerm>
|
||||
void set(sockopt::array_option<Opt, NullTerm>, const char *buf)
|
||||
{
|
||||
set_option(Opt, buf, std::strlen(buf));
|
||||
}
|
||||
|
||||
// Set array socket option, e.g.
|
||||
// `socket.set(zmq::sockopt::routing_id, zmq::buffer(id))`
|
||||
template<int Opt, int NullTerm>
|
||||
void set(sockopt::array_option<Opt, NullTerm>, const_buffer buf)
|
||||
{
|
||||
set_option(Opt, buf.data(), buf.size());
|
||||
}
|
||||
|
||||
// Set array socket option, e.g.
|
||||
// `socket.set(zmq::sockopt::routing_id, id_str)`
|
||||
template<int Opt, int NullTerm>
|
||||
void set(sockopt::array_option<Opt, NullTerm>, const std::string &buf)
|
||||
{
|
||||
set_option(Opt, buf.data(), buf.size());
|
||||
}
|
||||
|
||||
#ifdef ZMQ_CPP17
|
||||
// Set array socket option, e.g.
|
||||
// `socket.set(zmq::sockopt::routing_id, id_str)`
|
||||
template<int Opt, int NullTerm>
|
||||
void set(sockopt::array_option<Opt, NullTerm>, std::string_view buf)
|
||||
{
|
||||
set_option(Opt, buf.data(), buf.size());
|
||||
}
|
||||
#endif
|
||||
|
||||
// Get scalar socket option, e.g.
|
||||
// `auto opt = socket.get(zmq::sockopt::linger)`
|
||||
template<int Opt, class T, bool BoolUnit>
|
||||
ZMQ_NODISCARD T get(sockopt::integral_option<Opt, T, BoolUnit>) const
|
||||
{
|
||||
static_assert(std::is_integral<T>::value, "T must be integral");
|
||||
T val;
|
||||
size_t size = sizeof val;
|
||||
get_option(Opt, &val, &size);
|
||||
assert(size == sizeof val);
|
||||
return val;
|
||||
}
|
||||
|
||||
// Get array socket option, writes to buf, returns option size in bytes, e.g.
|
||||
// `size_t optsize = socket.get(zmq::sockopt::routing_id, zmq::buffer(id))`
|
||||
template<int Opt, int NullTerm>
|
||||
ZMQ_NODISCARD size_t get(sockopt::array_option<Opt, NullTerm>,
|
||||
mutable_buffer buf) const
|
||||
{
|
||||
size_t size = buf.size();
|
||||
get_option(Opt, buf.data(), &size);
|
||||
return size;
|
||||
}
|
||||
|
||||
// Get array socket option as string (initializes the string buffer size to init_size) e.g.
|
||||
// `auto s = socket.get(zmq::sockopt::routing_id)`
|
||||
// Note: removes the null character from null-terminated string options,
|
||||
// i.e. the string size excludes the null character.
|
||||
template<int Opt, int NullTerm>
|
||||
ZMQ_NODISCARD std::string get(sockopt::array_option<Opt, NullTerm>,
|
||||
size_t init_size = 1024) const
|
||||
{
|
||||
if (NullTerm == 2 && init_size == 1024) {
|
||||
init_size = 41; // get as Z85 string
|
||||
}
|
||||
std::string str(init_size, '\0');
|
||||
size_t size = get(sockopt::array_option<Opt>{}, buffer(str));
|
||||
if (NullTerm == 1) {
|
||||
if (size > 0) {
|
||||
assert(str[size - 1] == '\0');
|
||||
--size;
|
||||
}
|
||||
} else if (NullTerm == 2) {
|
||||
assert(size == 32 || size == 41);
|
||||
if (size == 41) {
|
||||
assert(str[size - 1] == '\0');
|
||||
--size;
|
||||
}
|
||||
}
|
||||
str.resize(size);
|
||||
return str;
|
||||
}
|
||||
#endif
|
||||
|
||||
void bind(std::string const &addr) { bind(addr.c_str()); }
|
||||
|
||||
void bind(const char *addr_)
|
||||
@ -1502,6 +1912,21 @@ class socket_base
|
||||
|
||||
protected:
|
||||
void *_handle;
|
||||
|
||||
private:
|
||||
void set_option(int option_, const void *optval_, size_t optvallen_)
|
||||
{
|
||||
int rc = zmq_setsockopt(_handle, option_, optval_, optvallen_);
|
||||
if (rc != 0)
|
||||
throw error_t();
|
||||
}
|
||||
|
||||
void get_option(int option_, void *optval_, size_t *optvallen_) const
|
||||
{
|
||||
int rc = zmq_getsockopt(_handle, option_, optval_, optvallen_);
|
||||
if (rc != 0)
|
||||
throw error_t();
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user