From 8ceec939a84e54b0a34f8e60e016e0534b1abf2b Mon Sep 17 00:00:00 2001 From: Peter Eisenlohr Date: Thu, 5 Nov 2026 20:29:54 +0000 Subject: [PATCH 1/5] docs: tidy the index at the top of net.hpp Group the names by topic in the order of asio/net.hpp, and list what this file declares itself in a block of its own instead of "-- below" tags. Add the missing get_socket() and UdpSocket, and say which of the shared declarations src/net.cpp defines and which each runtime does. Co-Authored-By: Claude Opus 5.5 --- include/anyhttp/net.hpp | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/include/anyhttp/net.hpp b/include/anyhttp/net.hpp index 8dbca02..22575b8 100644 --- a/include/anyhttp/net.hpp +++ b/include/anyhttp/net.hpp @@ -3,23 +3,30 @@ // // The network half of the runtime layer, see anyhttp/runtime.hpp: TCP sockets, the acceptor, name // resolution, TLS over TCP, what the sessions need from the stream they run on, and UDP sockets. +// Addresses and endpoints are the runtime's own, see anyhttp/runtime.hpp. // -// TcpSocket, TcpAcceptor, TlsContext, TlsStream, PlainServerStream -// ANYHTTP_SERVER_STREAMS(X), ANYHTTP_CLIENT_STREAMS(X) -- what the backends instantiate for -// SocketStream, stream_traits<>, is_tls(), async_teardown() -// io::shutdown(), io::cancel(), io::close(), io::remote_endpoint() -// io::make_socket(), io::make_acceptor(), io::listen(), io::local_endpoint(), io::accept() -// io::no_delay(), io::buffer_sizes(), io::set_buffer_sizes(), io::resolve(), io::connect() -// make_server_tls_context(), make_client_tls_context(), io::make_tls_stream() -// io::set_peer_name(), io::handshake(), io::alpn(), io::tls_info(), io::is_truncated() -// io::drain() -- below -// UdpSocket, io::make_udp_socket(), io::open(), io::cancel(), io::close() -// io::bind(), io::connect(), io::local_endpoint(), io::set_option(), io::send() -- below -// io::make_address(), SocketAddress, io::to_sockaddr(), io::from_sockaddr() -- below -// Signal -- a wake-up for any thread +// Each runtime defines, in asio/net.hpp or corosio/net.hpp (documented in asio/net.hpp): // -// asio/net.hpp has the documentation of each, except of those declared below. Addresses and -// endpoints are the runtime's own, see anyhttp/runtime.hpp. +// Types TcpSocket, TcpAcceptor, TlsContext, TlsStream, UdpSocket, PlainServerStream, +// ANYHTTP_SERVER_STREAMS(X), ANYHTTP_CLIENT_STREAMS(X) +// Streams SocketStream, stream_traits<>, get_socket(), is_tls(), io::shutdown(), +// io::cancel(), io::close(), io::remote_endpoint(), async_teardown() +// TCP io::make_socket(), io::make_acceptor(), io::listen(), io::local_endpoint(), +// io::accept(), io::no_delay(), io::buffer_sizes(), io::set_buffer_sizes(), +// io::resolve(), io::connect() +// TLS make_server_tls_context(), make_client_tls_context(), io::make_tls_stream(), +// io::set_peer_name(), io::handshake(), io::alpn(), io::tls_info(), +// io::is_truncated() +// UDP io::make_udp_socket(), io::open(), io::cancel(), io::close() +// Threads Signal, a wake-up that may be sent from any thread +// +// Declared and documented here, the same for both runtimes: +// +// Streams io::drain() +// Addresses io::make_address(), SocketAddress, io::to_sockaddr(), io::from_sockaddr() +// (defined by each runtime, in src/asio/net.cpp and src/corosio/net.cpp) +// UDP io::bind(), io::connect(), io::local_endpoint(), io::set_option(), io::send() +// (defined once, in src/net.cpp, on the native handle) // #include "anyhttp/common.hpp" From 08867908af4c3f983dabe75c6f46085d14c152cb Mon Sep 17 00:00:00 2001 From: Peter Eisenlohr Date: Thu, 5 Nov 2026 20:33:06 +0000 Subject: [PATCH 2/5] chore: move capy to bdadc6a and corosio to fd8e95a capy renamed begin/end of a buffer sequence to buffer_sequence_begin/_end, as Asio has them, and removed buffer_param, which corosio made an implementation detail in the same step; the two have to move together. Of the rest, capy aligns coroutine frames allocated through a standard allocator and corosio caches a socket's family and reads a single buffer with recv after a parked read. Co-Authored-By: Claude Opus 5.5 --- CMakeLists.txt | 4 ++-- include/anyhttp/corosio/net.hpp | 2 +- include/anyhttp/reader.hpp | 3 ++- include/anyhttp/writer.hpp | 3 ++- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f04de7..16750b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -163,11 +163,11 @@ elseif (ANYHTTP_API STREQUAL "COROSIO") endforeach() FetchContent_Declare(capy GIT_REPOSITORY https://github.com/cppalliance/capy.git - GIT_TAG 24c54af2cf967ccbf8d3809af4bcd9c8f61f553b + GIT_TAG bdadc6adef8c8eb79da6454373175bb1428be524 EXCLUDE_FROM_ALL) FetchContent_Declare(corosio GIT_REPOSITORY https://github.com/cppalliance/corosio.git - GIT_TAG 41d0de18b6e4fa1b397c38a866f2daf52c6c36b5 + GIT_TAG fd8e95a7125047d5385068a4c640da8232b9588e EXCLUDE_FROM_ALL) FetchContent_MakeAvailable(capy corosio) message(STATUS "Using API style: COROSIO (capy/corosio)") diff --git a/include/anyhttp/corosio/net.hpp b/include/anyhttp/corosio/net.hpp index 02cfbf5..7185081 100644 --- a/include/anyhttp/corosio/net.hpp +++ b/include/anyhttp/corosio/net.hpp @@ -92,7 +92,7 @@ class TlsStream capy::const_buffer linearize(const ConstBufferSequence& buffers) { size_t used = 0; - for (auto it = capy::begin(buffers), end = capy::end(buffers); + for (auto it = capy::buffer_sequence_begin(buffers), end = capy::buffer_sequence_end(buffers); it != end && used < linearize_size;) { capy::const_buffer buffer = *it++; diff --git a/include/anyhttp/reader.hpp b/include/anyhttp/reader.hpp index 78caeb7..21bd17b 100644 --- a/include/anyhttp/reader.hpp +++ b/include/anyhttp/reader.hpp @@ -160,7 +160,8 @@ class Reader template Task> read_some(Buffers buffers) { - for (auto it = capy::begin(buffers); it != capy::end(buffers); ++it) + for (auto it = capy::buffer_sequence_begin(buffers); it != capy::buffer_sequence_end(buffers); + ++it) if (capy::mutable_buffer buffer = *it; buffer.size() > 0) return read_some(asio::mutable_buffer(buffer.data(), buffer.size())); return read_some(asio::mutable_buffer{}); diff --git a/include/anyhttp/writer.hpp b/include/anyhttp/writer.hpp index 1945b29..c0e0d84 100644 --- a/include/anyhttp/writer.hpp +++ b/include/anyhttp/writer.hpp @@ -147,7 +147,8 @@ class Writer template Task> write_some(Buffers buffers) { - for (auto it = capy::begin(buffers); it != capy::end(buffers); ++it) + for (auto it = capy::buffer_sequence_begin(buffers); it != capy::buffer_sequence_end(buffers); + ++it) if (capy::const_buffer buffer = *it; buffer.size() > 0) { auto [ec] = co_await write(asio::const_buffer(buffer.data(), buffer.size())); From 10c12dbb3c7c7d6d97951bb6c74841bb95e55391 Mon Sep 17 00:00:00 2001 From: Peter Eisenlohr Date: Thu, 5 Nov 2026 20:39:59 +0000 Subject: [PATCH 3/5] chore: bench.sh stays quiet when the server is up to date Filter ninja's glob re-check and "no work to do" out of the build output and announce the build only when there is something else to show. A shell loop rather than awk, as mawk reads its input in blocks and held the compiler's output back. Co-Authored-By: Claude Opus 5.5 --- .cspell.json | 2 ++ scripts/bench.sh | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/.cspell.json b/.cspell.json index dbeb092..601633f 100644 --- a/.cspell.json +++ b/.cspell.json @@ -23,6 +23,7 @@ "dcid", "dcidlen", "demuxed", + "docroot", "ECDH", "Eisenlohr", "epoll", @@ -46,6 +47,7 @@ "logwd", "malloc", "marp", + "mawk", "mlogd", "mloge", "mlogi", diff --git a/scripts/bench.sh b/scripts/bench.sh index 2c6160c..1e3bd68 100755 --- a/scripts/bench.sh +++ b/scripts/bench.sh @@ -97,8 +97,19 @@ for server in "${servers[@]}"; do echo "configuring $tree/ (scripts/configure.sh)" >&2 scripts/configure.sh "$tree" >&2 fi - echo "building $tree/ (server)" >&2 - cmake --build "$tree" --target server >&2 + # Quiet when up to date: drop ninja's glob re-check and "no work to do", and announce the + # build only once it has something else to say. A shell loop, not awk: mawk reads its input + # in blocks, which holds the compiler's output back. + cmake --build "$tree" --target server 2>&1 | { + said=0 + while IFS= read -r line || [[ -n $line ]]; do + case $line in + *"Re-checking globbed directories"* | "ninja: no work to do.") continue ;; + esac + ((said)) || { echo "building $tree/ (server)"; said=1; } + printf '%s\n' "$line" + done + } >&2 elif [[ ! -x $tree/src/server ]]; then echo "error: $tree/src/server does not exist, run without -n" >&2 exit 1 From 3a46dae606e529e5a1e683cc1491b189b0f1d82d Mon Sep 17 00:00:00 2001 From: Peter Eisenlohr Date: Thu, 5 Nov 2026 22:18:51 +0000 Subject: [PATCH 4/5] chore: move to psedoc/anyhttp:0.32, on cpp-devcontainer 0.32 AWS-LC 5.12.0, nghttp3 1.19.0, ngtcp2 1.26.0, libbpf 1.8.0, nghttp2 1.71.0 and nghttp2-v2 0.2.0, its first release, which is a tag now rather than a commit. libbpf gets an ARG like the others. ngtcp2's examples and their tests are built with clang and libc++: since 1.26.0 the tests print ranges with std::format, which trixie's GCC 14 does not have. Its OpenSSL backend is asked for as --with-openssl, the name configure knows. Co-Authored-By: Claude Opus 5.5 --- .devcontainer/Dockerfile | 2 +- .devcontainer/base/Dockerfile | 33 +++++++++++++++++++++------------ .github/workflows/release.yml | 2 +- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 01a989e..d89d4d8 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -2,7 +2,7 @@ # The dependencies of this project have been moved into another Dockerfile that can be built # separately. This image can be pushed to the HUB, speeding up codespace creation considerably. # -FROM docker.io/psedoc/anyhttp:0.31 +FROM docker.io/psedoc/anyhttp:0.32 # ================================================================================================== diff --git a/.devcontainer/base/Dockerfile b/.devcontainer/base/Dockerfile index d8ecb8f..e4cacda 100644 --- a/.devcontainer/base/Dockerfile +++ b/.devcontainer/base/Dockerfile @@ -2,7 +2,7 @@ # https://github.com/microsoft/vscode-dev-containers/tree/main/containers/debian # https://github.com/pgit/cpp-devcontainer # -FROM docker.io/psedoc/cpp-devcontainer:0.31 +FROM docker.io/psedoc/cpp-devcontainer:0.32 # # GDB libc++ pretty printer (works for string, but not for map with llvm-18) @@ -66,7 +66,7 @@ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive && \ # With debian trixie, we now have OpenSSL 3 with QUIC support. Whether or not that is any good, # seems to be up for debate: https://www.haproxy.com/blog/state-of-ssl-stacks # -ARG AWS_LC_VERSION=v5.10.0 +ARG AWS_LC_VERSION=v5.12.0 RUN git clone --depth 1 -b ${AWS_LC_VERSION} https://github.com/aws/aws-lc && \ cd aws-lc && \ cmake -B build \ @@ -80,7 +80,7 @@ RUN git clone --depth 1 -b ${AWS_LC_VERSION} https://github.com/aws/aws-lc && \ cd .. && \ rm -rf aws-lc -ARG NGHTTP3_VERSION=v1.18.0 +ARG NGHTTP3_VERSION=v1.19.0 RUN git clone --recursive --depth 1 --branch ${NGHTTP3_VERSION} https://github.com/ngtcp2/nghttp3 && \ cd nghttp3 && \ autoreconf -i && \ @@ -99,14 +99,25 @@ RUN git clone --recursive --depth 1 --branch ${NGHTTP3_VERSION} https://github.c # 'osslclient'/'osslserver' are the OpenSSL variants, replacing the copy of the example sources # that used to live in src/ngtcp2/ as 'ngtcp-client'/'ngtcp-server'. # -ARG NGTCP2_VERSION=v1.25.0 +# CXX is clang with libc++: since v1.26.0, the examples' unit tests print ranges with std::format, +# which libstdc++ supports only from GCC 15 on, and trixie has GCC 14. The libraries are C; only +# the examples and their tests are C++, so this changes nothing but which libc++ they link. +# munitxx.h uses std::ranges::equal_to & co. without including , which libstdc++ +# brings along with and libc++ does not, so we add the include. +# +# The OpenSSL backend is '--with-openssl' (there is no '--with-ossl'). It is on by default when +# OpenSSL is found; requesting it makes configure fail instead of silently leaving it out. +# +ARG NGTCP2_VERSION=v1.26.0 RUN git clone --recursive --depth 1 --branch ${NGTCP2_VERSION} https://github.com/ngtcp2/ngtcp2 && \ cd ngtcp2 && \ + sed -i 's/^#include $/&\n#include /' tests/munit/munitxx.h && \ autoreconf -i && \ ./configure --prefix=/usr/local \ BORINGSSL_CFLAGS="-I/opt/boringssl/include" \ BORINGSSL_LIBS="-L/opt/boringssl/lib -lssl -lcrypto" \ - --with-boringssl --with-ossl && \ + --with-boringssl --with-openssl \ + CXX="clang++ -stdlib=libc++" && \ make -j$(nproc) check && make install && \ make -j$(nproc) -C examples osslclient osslserver && \ install -m 755 -t /usr/local/bin examples/osslclient examples/osslserver && \ @@ -120,7 +131,8 @@ RUN git clone --recursive --depth 1 --branch ${NGTCP2_VERSION} https://github.co # ================================================================================================== -RUN git clone --depth 1 -b v1.7.0 https://github.com/libbpf/libbpf && \ +ARG LIBBPF_VERSION=v1.8.0 +RUN git clone --depth 1 -b ${LIBBPF_VERSION} https://github.com/libbpf/libbpf && \ cd libbpf && \ PREFIX=/usr/local LIBDIR=/usr/local/lib make -j$(nproc) -C src install && \ cd .. && rm -rf libbpf @@ -133,7 +145,7 @@ RUN git clone --depth 1 -b v1.7.0 https://github.com/libbpf/libbpf && \ # CC=clang: the eBPF program for --with-libbpf is compiled with '$(CC) -target bpf', which GCC # does not understand. # -ARG NGHTTP2_VERSION=v1.70.0 +ARG NGHTTP2_VERSION=v1.71.0 RUN git clone --recursive --depth 1 --branch ${NGHTTP2_VERSION} https://github.com/nghttp2/nghttp2.git && \ cd nghttp2 && \ autoreconf -i && \ @@ -155,8 +167,6 @@ RUN git clone --recursive --depth 1 --branch ${NGHTTP2_VERSION} https://github.c # nghttp2_check_header_name/_value, nghttp2_check_authority and the four nghttp2_rcbuf_*), so the # two cannot be linked into one binary: which one a build uses is a compile-time decision. # -# No releases yet (the library calls itself 0.2.0-DEV), hence a pinned commit rather than a tag. -# # 'make -C lib install', not 'make install': the latter also installs doc/'s nghttp.1, nghttpd.1, # nghttpx.1 and h2load.1, overwriting v1's man pages even though --enable-lib-only builds none of # those programs. lib/ has the headers, the libraries and the .pc file, which is all we want. @@ -164,10 +174,9 @@ RUN git clone --recursive --depth 1 --branch ${NGHTTP2_VERSION} https://github.c # Of the submodules, lib/sfparse is part of the library and tests/munit is what 'make check' # needs; the rest (mruby, neverbleed, urlparse) belong to the applications. # -ARG NGHTTP2_V2_VERSION=5f55a2e9db3005530bd8405f53ab11daa8d7b8dc -RUN git clone https://github.com/nghttp2/nghttp2-v2.git && \ +ARG NGHTTP2_V2_VERSION=v0.2.0 +RUN git clone --depth 1 --branch ${NGHTTP2_V2_VERSION} https://github.com/nghttp2/nghttp2-v2.git && \ cd nghttp2-v2 && \ - git checkout --detach ${NGHTTP2_V2_VERSION} && \ git submodule update --init --recursive lib/sfparse tests/munit && \ autoreconf -i && \ ./configure --prefix=/usr/local --enable-lib-only && \ diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a44ac9c..1e245b4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -34,7 +34,7 @@ jobs: name: ${{ matrix.api }} ${{ matrix.flavor }} runs-on: &runs_on ubuntu-26.04 container: &container - image: docker.io/psedoc/anyhttp:0.31 + image: docker.io/psedoc/anyhttp:0.32 # The Ubuntu 26.04 runner kernel's ASLR entropy is high enough that the binary can land in # TSAN's fixed shadow region. TSAN then re-execs itself with # personality(ADDR_NO_RANDOMIZE), which docker's default seccomp profile refuses -- the job From 4e8deb006dd67995f023fd07de3fc0bdacb8c7e6 Mon Sep 17 00:00:00 2001 From: Peter Eisenlohr Date: Thu, 5 Nov 2026 22:31:20 +0000 Subject: [PATCH 5/5] chore: keep btop/htop settings and an extra .bashrc in /commandhistory The volume outlives a container rebuild, so the tools' configuration and personal shell setup survive it too. Co-Authored-By: Claude Opus 5.5 --- .devcontainer/.bash_aliases | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.devcontainer/.bash_aliases b/.devcontainer/.bash_aliases index ac524bd..ec03e4e 100644 --- a/.devcontainer/.bash_aliases +++ b/.devcontainer/.bash_aliases @@ -3,3 +3,9 @@ alias gs="git status" alias gd="git diff" alias gds="git diff --staged" alias tma="tmux attach" + +mkdir -p ~/.config/{btop,htop} +[[ -f ~/.config/btop/btop.conf ]] || ln -sf /commandhistory/btop.conf ~/.config/btop/ +[[ -f ~/.config/htop/htoprc ]] || ln -sf /commandhistory/htoprc ~/.config/htop/ + +[[ -f /commandhistory/.bashrc ]] && source /commandhistory/.bashrc