diff --git a/CMakeLists.txt b/CMakeLists.txt index 96334054..4d1026ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,7 @@ macro(set_option_from_env OPTION_NAME) message(STATUS "${OPTION_NAME}: ${${OPTION_NAME}}") endmacro() -option(ZMQ_DRAFT "Build and install draft APIs" OFF) +option(ZMQ_DRAFT "Build and install draft APIs (e.g. `server-client`, `radio-dish`, `scatter-gather`)" ON) set_option_from_env(ZMQ_DRAFT) option(ZMQ_CURVE "Enable CURVE security" ON) diff --git a/README.md b/README.md index 1ccdfe09..496f8110 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,8 @@ - High performance. - Fully usable with TypeScript (3+). - Compatible with Zeromq 4/5 via "zeromq/v5-compat" +- Secure Curve protocol support +- Zeromq Draft API support ## Useful links @@ -28,7 +30,7 @@ - [Installation](#installation) - [Prebuilt binaries](#prebuilt-binaries) - [Building from source](#building-from-source) - - [Available Build Options](#available-build-options) + - [Available Build Options](#available-build-options) - [Curve with Libsodium support](#curve-with-libsodium-support) - [Draft support](#draft-support) - [Websocket support](#websocket-support) @@ -104,31 +106,38 @@ source: To install from source, specify `build_from_source=true` in a `.npmrc` file -``` +```ini build_from_source=true ``` +#### Available Build Options + When building from source, you can also specify additional build options in a `.npmrc` file in your project: -### Available Build Options -
👉🏻 Options ### Curve with Libsodium support -Enables CURVE security for encrypted communications. Zeromq uses libsodium for CURVE security. To enable CURVE support, add the following to your .npmrc: +(Enabled by default) + +Enables CURVE security for encrypted communications. Zeromq uses libsodium for +CURVE security. To enable CURVE support, add the following to your .npmrc: ```ini zmq_curve="true" zmq_sodium="true" ``` -Building libsodium requires these dependencies on Linux/MacOS: `autoconf automake libtool`, which can be installed via `apt-get` or `brew`, etc. +Building libsodium requires these dependencies on Linux/MacOS: +`autoconf automake libtool`, which can be installed via `apt-get` or `brew`, +etc. #### Draft support +(Enabled by default) + By default `libzmq` is built with support for `Draft` patterns (e.g. `server-client`, `radio-dish`, `scatter-gather`). If you want to build `libzmq` without support for `Draft`, you can specify the following in `.npmrc`: diff --git a/src/module.h b/src/module.h index 5e3a70a7..8aa28099 100644 --- a/src/module.h +++ b/src/module.h @@ -32,7 +32,8 @@ struct Terminator { }); using namespace std::chrono_literals; - if (terminate.wait_for(500ms) == std::future_status::timeout) { + const auto timeout = 500ms; + if (terminate.wait_for(timeout) == std::future_status::timeout) { /* We can't use process.emitWarning, because the Node.js runtime has already shut down. So we mimic it instead. */ (void)fprintf(stderr, diff --git a/src/outgoing_msg.cc b/src/outgoing_msg.cc index 64c80fc5..9652db64 100644 --- a/src/outgoing_msg.cc +++ b/src/outgoing_msg.cc @@ -121,18 +121,18 @@ bool OutgoingMsg::Parts::SetGroup(Napi::Value value) { auto group = [&]() { if (value.IsString()) { return std::string(value.As()); - } else if (value.IsBuffer()) { - Napi::Object buf = value.As(); + } + if (value.IsBuffer()) { + auto buf = value.As(); auto length = buf.As>().Length(); - auto value = buf.As>().Data(); + auto* value = buf.As>().Data(); return std::string(value, length); - } else { - return std::string(); } + return std::string(); }(); for (auto& part : parts) { - if (zmq_msg_set_group(part, group.c_str()) < 0) { + if (zmq_msg_set_group(part.get(), group.c_str()) < 0) { ErrnoException(value.Env(), zmq_errno()).ThrowAsJavaScriptException(); return false; } @@ -142,15 +142,15 @@ bool OutgoingMsg::Parts::SetGroup(Napi::Value value) { } bool OutgoingMsg::Parts::SetRoutingId(Napi::Value value) { - if (value.IsUndefined()) { + if (value.IsUndefined()) {https://clang.llvm.org/extra/clang-tidy/checks/readability/identifier-length.html ErrnoException(value.Env(), EINVAL).ThrowAsJavaScriptException(); return false; } - auto id = value.As().Uint32Value(); + auto routing_id = value.As().Uint32Value(); for (auto& part : parts) { - if (zmq_msg_set_routing_id(part, id) < 0) { + if (zmq_msg_set_routing_id(part.get(), routing_id) < 0) { ErrnoException(value.Env(), zmq_errno()).ThrowAsJavaScriptException(); return false; } diff --git a/src/socket.cc b/src/socket.cc index 5e43011a..53e91142 100644 --- a/src/socket.cc +++ b/src/socket.cc @@ -103,7 +103,6 @@ Socket::Socket(const Napi::CallbackInfo& info) } uv_os_sock_t file_descriptor = 0; - std::function const finalize = nullptr; const auto error = [this]() { [[maybe_unused]] auto err = zmq_close(socket); @@ -125,12 +124,14 @@ Socket::Socket(const Napi::CallbackInfo& info) } #endif + std::function finalize = nullptr; + /* Currently only some DRAFT sockets are threadsafe. */ if (thread_safe) { #ifdef ZMQ_HAS_POLLABLE_THREAD_SAFE /* Threadsafe sockets do not expose an FD we can integrate into the event loop, so we have to construct one by creating a zmq_poller. */ - auto poll = zmq_poller_new(); + auto* poll = zmq_poller_new(); if (poll == nullptr) { ErrnoException(Env(), zmq_errno()).ThrowAsJavaScriptException(); error(); @@ -138,7 +139,7 @@ Socket::Socket(const Napi::CallbackInfo& info) /* Callback to free the underlying poller. Move the poller to transfer ownership after the constructor has completed. */ - finalize = [=]() mutable { + finalize = [&]() { [[maybe_unused]] auto err = zmq_poller_destroy(&poll); assert(err == 0); }; @@ -149,7 +150,7 @@ Socket::Socket(const Napi::CallbackInfo& info) error(); } - if (zmq_poller_fd(poll, &fd) < 0) { + if (zmq_poller_fd(poll, &file_descriptor) < 0) { ErrnoException(Env(), zmq_errno()).ThrowAsJavaScriptException(); finalize(); error(); @@ -327,17 +328,17 @@ void Socket::Receive(const Napi::Promise::Deferred& res) { switch (type) { case ZMQ_SERVER: { auto meta = Napi::Object::New(Env()); - meta.Set("routingId", zmq_msg_routing_id(part)); - list[i++] = meta; + meta.Set("routingId", zmq_msg_routing_id(part.get())); + list[i_part++] = meta; break; } case ZMQ_DISH: { auto meta = Napi::Object::New(Env()); - auto data = zmq_msg_group(part); + const auto* data = zmq_msg_group(part.get()); auto length = strnlen(data, ZMQ_GROUP_MAX_LENGTH); meta.Set("group", Napi::Buffer::Copy(Env(), data, length)); - list[i++] = meta; + list[i_part++] = meta; break; } } @@ -534,7 +535,9 @@ Napi::Value Socket::Send(const Napi::CallbackInfo& info) { Arg::Required("Options must be an object"), }; - if (args.ThrowIfInvalid(info)) return Env().Undefined(); + if (args.ThrowIfInvalid(info)) { + return Env().Undefined(); + } break; } @@ -676,19 +679,22 @@ void Socket::Join([[maybe_unused]] const Napi::CallbackInfo& info) { Arg::Required("Group must be a string or buffer"), }; - if (args.ThrowIfInvalid(info)) return; + if (args.ThrowIfInvalid(info)) { + return; + } - if (!ValidateOpen()) return; + if (!ValidateOpen()) { + return; + } auto str = [&]() { if (info[0].IsString()) { return std::string(info[0].As()); - } else { - Napi::Object buf = info[0].As(); - auto length = buf.As>().Length(); - auto value = buf.As>().Data(); - return std::string(value, length); } + auto buf = info[0].As(); + auto length = buf.As>().Length(); + auto* value = buf.As>().Data(); + return std::string(value, length); }(); if (zmq_join(socket, str.c_str()) < 0) { @@ -704,19 +710,22 @@ void Socket::Leave([[maybe_unused]] const Napi::CallbackInfo& info) { Arg::Required("Group must be a string or buffer"), }; - if (args.ThrowIfInvalid(info)) return; + if (args.ThrowIfInvalid(info)) { + return; + } - if (!ValidateOpen()) return; + if (!ValidateOpen()) { + return; + } auto str = [&]() { if (info[0].IsString()) { return std::string(info[0].As()); - } else { - Napi::Object buf = info[0].As(); - auto length = buf.As>().Length(); - auto value = buf.As>().Data(); - return std::string(value, length); } + auto buf = info[0].As(); + auto length = buf.As>().Length(); + auto* value = buf.As>().Data(); + return std::string(value, length); }(); if (zmq_leave(socket, str.c_str()) < 0) {