Skip to content

Merge origin#27

Open
axelriet wants to merge 32 commits into
axelriet:masterfrom
zeromq:master
Open

Merge origin#27
axelriet wants to merge 32 commits into
axelriet:masterfrom
zeromq:master

Conversation

@axelriet

Copy link
Copy Markdown
Owner

Merge 7 minor commits from origin

stephan57160 and others added 30 commits June 6, 2025 11:56
This fix has to be reported in LIBZMQ as well and will fix #4744.
setting an upper bound improves forward-compatibility as legacy version support is dropped

- 3.5 compat is deprecated in 3.27 (2023), removed in 4.0 (2025)
- 3.10 compat is deprecated in 3.31 (2024)
Solution: update to clang-format-18 and apply diff

Co-authored-by: chris cunningham <crcunningham@users.noreply.github.com>
When sodium is enabled, also build curve_keygen binary. This is to
bring cmake builds to parity with autoconf.

Fixes: #4675
Solution: add -fprofile-update=atomic and --ignore-errors unused as indicated by log message

geninfo: ERROR: Unexpected negative count '-1' for /usr/include/c++/13/bits/stl_tree.h:2466.
	Perhaps you need to compile with '-fprofile-update=atomic

LCOV   --remove /tmp/*
lcov: ERROR: 'exclude' pattern '/tmp/*' is unused.
	(use "lcov --ignore-errors unused ..." to bypass this error)
verify that multicast is working on the system before running tests
that relies on this, or skipping those test otherwise.

In some circumstances this check itself hangs due to the recvfrom()
call being blocking waiting for data. The test is eventually killed
with a SIGALARM signal.

./config/test-driver: line 112: 1227308 Alarm clock             "$@" >> "$log_file" 2>&1
FAIL: tests/test_radio_dish

FAIL: tests/test_radio_dish
===========================

FAIL tests/test_radio_dish (exit status: 142)

$ tests/test_radio_dish
tests/test_radio_dish.cpp:511:test_leave_unjoined_fails:PASS
tests/test_radio_dish.cpp:512:test_join_too_long_fails:PASS
tests/test_radio_dish.cpp:513:test_long_group:PASS
tests/test_radio_dish.cpp:514:test_join_twice_fails:PASS
tests/test_radio_dish.cpp:515:test_radio_bind_fails_ipv4:PASS
tests/test_radio_dish.cpp:516:test_radio_bind_fails_ipv6:PASS
tests/test_radio_dish.cpp:517:test_dish_connect_fails_ipv4:PASS
tests/test_radio_dish.cpp:518:test_dish_connect_fails_ipv6:PASS
tests/test_radio_dish.cpp:519:test_radio_dish_tcp_poll_ipv4:PASS
tests/test_radio_dish.cpp:520:test_radio_dish_tcp_poll_ipv6:PASS
tests/test_radio_dish.cpp:521:test_radio_dish_udp_ipv4:PASS
tests/test_radio_dish.cpp:522:test_radio_dish_udp_ipv6:PASS
Alarm clock

With this commit, making the recvfrom() call non-blocking. The test
does noy hang, and the non-available multicast is detected and the
tests needing it are skipped:

PASS: tests/test_radio_dish

$ tests/test_radio_dish
tests/test_radio_dish.cpp:510:test_leave_unjoined_fails:PASS
tests/test_radio_dish.cpp:511:test_join_too_long_fails:PASS
tests/test_radio_dish.cpp:512:test_long_group:PASS
tests/test_radio_dish.cpp:513:test_join_twice_fails:PASS
tests/test_radio_dish.cpp:514:test_radio_bind_fails_ipv4:PASS
tests/test_radio_dish.cpp:515:test_radio_bind_fails_ipv6:PASS
tests/test_radio_dish.cpp:516:test_dish_connect_fails_ipv4:PASS
tests/test_radio_dish.cpp:517:test_dish_connect_fails_ipv6:PASS
tests/test_radio_dish.cpp:518:test_radio_dish_tcp_poll_ipv4:PASS
tests/test_radio_dish.cpp:519:test_radio_dish_tcp_poll_ipv6:PASS
tests/test_radio_dish.cpp:520:test_radio_dish_udp_ipv4:PASS
tests/test_radio_dish.cpp:521:test_radio_dish_udp_ipv6:PASS
tests/test_radio_dish.cpp:431:test_radio_dish_mcast_ipv4:IGNORE: No multicast available
tests/test_radio_dish.cpp:431:test_radio_dish_no_loop_ipv4:IGNORE: No multicast available
tests/test_radio_dish.cpp:431:test_radio_dish_mcast_ipv6:IGNORE: No multicast available
tests/test_radio_dish.cpp:431:test_radio_dish_no_loop_ipv6:IGNORE: No multicast available

-----------------------
16 Tests 0 Failures 4 Ignored
OK
make vmci_listener compile on windows again
You have configured zeromq with CMake.
Build environment is MinGW.
When you install the the package config files, they are copied into a "CMake" directory into the sysroot, but this is a nonsense.
Instead, they should be copied under ${LIBDIR}/cmake, as GNU tools require.
Hopefully, the solution is very easy.
This tiny PR fixes this error.
Background: JeroMQ added disconnectPeer(routingId) to allow dropping a single peer connection. In libzmq there was no C API to disconnect a single connection by its routing id; applications had to tear down entire endpoints or sockets. This also created divergence between JeroMQ and libzmq for the PEER/SERVER patterns.

solution: introduce a virtual xdisconnect_peer on socket_base_t and a public socket_base_t::disconnect_peer that delegates to it. Implement xdisconnect_peer in server_t to look up the outbound pipe by routing id and terminate it, which removes it from bookkeeping via xpipe_terminated. Expose a new DRAFT C API zmq_disconnect_peer(void*, uint32_t) that always calls socket_base_t::disconnect_peer (matching JeroMQ pattern of calling the socket regardless of type); unsupported types return ENOTSUP. This brings libzmq to feature parity with JeroMQ’s commit 57de9b8 (Peer support disconnect).

API: add draft function zmq_disconnect_peer(void *socket, uint32_t routing_id). For ZMQ_SERVER and ZMQ_PEER this disconnects that specific connection; subsequent sends to that routing id fail with EHOSTUNREACH until a new connection is formed. Other socket types return ENOTSUP. The method is thread-safe when using thread-safe sockets.

Tests: add tests/test_peer_disconnect.cpp which creates two ZMQ_PEER sockets, exchanges a message to learn the remote routing id, calls zmq_disconnect_peer on the bound side, and verifies sending back fails with EHOSTUNREACH. Hook the test into Makefile.am under ENABLE_DRAFTS.

Docs: add doc/zmq_disconnect_peer.adoc manpage; link it from doc/zmq_socket.adoc; include it in doc/Makefile.am MAN3 so it is built and installed. Note the draft status (requires --enable-drafts).

Implementation notes: the server_t override simply terminates the matched pipe; removal from maps happens in xpipe_terminated. The C shim intentionally does not gate by socket type and relies on the underlying implementation (returning ENOTSUP where appropriate), mirroring JeroMQ’s design. Reference JeroMQ change: 57de9b84 (kaplan-shaked: Peer support disconnect).
… systems

The msleep(1) in test_mock_pub_sub() can cause random failures onmachines under heavy load.
As this test seems to validates compatibility between different ZMTP version and not performance,
I propose Increase the wait time to allow the state machine to properly attach the pipe after handshake.

Note to simulate the overloaded machine in local I used:
stress-ng --cpu 24 --switch 16 --timer 8 --timeout 60s &
while tests/test_mock_pub_sub
do
    echo "PASS"
done
…sons

When getconf returns "undefined" (e.g., on s390x under qemu-user), the
STREQUAL "undefined" check comes after EQUAL 0 and EQUAL -1. While this
works in current CMake versions, performing numeric comparisons on
non-numeric strings before string comparisons is fragile and could have
undefined behavior in some CMake versions.

Solution: reorder conditions to check strings before numeric comparisons

Move STREQUAL "undefined" before the EQUAL comparisons. This ensures
proper string matching is attempted before any numeric coercion, making
the code more robust and easier to understand.

Verified with qemu-user s390x emulation (CMake 3.22):
- getconf LEVEL1_DCACHE_LINESIZE returns "undefined"
- Both orderings work, but string-first is safer

Fixes #4834
on mac, INADDR_ANY is not aconnectable host,
leading to EHOSTUNREACH when passed to `sendto`
VSOCK transport allows communication between the Host
and guests.

It requires linux on the host and Guest.

Fixes #4491
MinGW builds were falling back to select poller, which is incompatible with IPC
and causes compilation failure.
Default epoll is now enabled for both MSVC and MinGW to ensure consistent behavior.
Comments updated accordingly.
- add stream fuzzers: test_connect_stream_fuzzer, test_bind_stream_fuzzer
- add socket-options fuzzer: test_socket_options_fuzzer
- add ws fuzzers behind ZMQ_HAVE_WS + NOT WIN32: test_connect_ws_fuzzer, test_bind_ws_fuzzer
The out_event() send path copies group_size + body_size + 1 bytes
into the fixed MAX_UDP_MSG (8192) byte _out_buffer without checking
if the total exceeds the buffer capacity. Messages with body larger
than approximately 7936 bytes overflow the buffer and corrupt
adjacent heap memory.

Add a bounds check before the memcpy calls, discarding oversized
messages. This resolves the TODO comment that acknowledged the
missing check.

Signed-off-by: Tristan Music <tristmd@gmail.com>
When the group_size byte in a received UDP packet exceeds the actual
payload length, in_event() returns early without calling msg.close().
Since msg_t has no destructor, the allocated message memory is
permanently leaked. Repeated packets exhaust process memory.

Add msg.close() before the early return, matching the cleanup pattern
used elsewhere in the same function (e.g., line 564).

Signed-off-by: Tristan Music <tristmd@gmail.com>
On platforms where char is signed (Linux x86-64, MSVC, ARM with
-fsigned-char), _in_buffer[0] with a byte value >= 0x80 undergoes
sign extension when assigned to int group_size. For example, byte
0x80 becomes -128. This negative value is then implicitly cast to
size_t in msg.init_size(), producing a value near SIZE_MAX. The
allocation fails and errno_assert terminates the process.

The out_event() send path already correctly uses
static_cast<unsigned char> for the group size byte. Apply the same
cast on the receive path for consistency.

Signed-off-by: Tristan Music <tristmd@gmail.com>
Problem: When GSSAPI encryption is active, subscribe and cancel message
flags (msg_t::subscribe = 12, msg_t::cancel = 16) were not preserved
through the encode_message/decode_message round-trip.

encode_message() only captured the 'more' (bit 0) and 'command' (bit 1)
flags in the wire flags byte. The subscribe flag occupies bits 2-3
(value 12) and cancel occupies bit 4 (value 16) — both outside the
captured range, so they were silently zeroed on decoding.

After decode_message(), xpub_t::xread_activated() would not recognise
the arriving message as a subscribe or cancel command, causing
subscriptions to be silently dropped after reconnection (when
xhiccuped() re-sends cached subscriptions through the GSSAPI path).

Solution: Encode the subscribe flag into wire bit 2 (0x04) and the
cancel flag into wire bit 3 (0x08) in encode_message(), and restore
them via set_flags(msg_t::subscribe) / set_flags(msg_t::cancel) in
decode_message().
Solution: On Windows platform, implement custom WSA error to errno
translation in the poll() function. The goal is to make
Windows-specific poll() to appear more Unixy to the callers.
MarcoFalke and others added 2 commits July 4, 2026 10:04
Without the <new> include, compilation may fail:

```
src/polling_util.hpp:28:30: error: no member named 'nothrow' in namespace 'std'
   28 |             _buf = new (std::nothrow) T[nitems_];
      |                              ^~~~~~~
```
When a ZAP handler returned 300/400/500, gssapi_server_t ignored the
denial and transitioned to send_ready anyway, allowing the connection
to proceed unauthenticated.

Root cause: unlike PLAIN/CURVE (which use zap_client_common_handshake_t
and override handle_zap_status_code to update the state machine),
gssapi_server_t inherits directly from zap_client_t whose
handle_zap_status_code only fires a monitor event without touching
the GSSAPI state machine.

Fix both paths where ZAP is consulted:

1. Synchronous reply (process_handshake_command): check status_code
   after receive_and_process_zap_reply() succeeds; go to send_ready
   only on "2xx", otherwise go to the new `closing` state.

2. Asynchronous reply (zap_msg_available): same status_code check
   instead of always setting send_ready.

Add a `closing` state to the state machine and make status() return
mechanism_t::error for it so the session tears down the connection.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.