Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"dcid",
"dcidlen",
"demuxed",
"docroot",
"ECDH",
"Eisenlohr",
"epoll",
Expand All @@ -46,6 +47,7 @@
"logwd",
"malloc",
"marp",
"mawk",
"mlogd",
"mloge",
"mlogi",
Expand Down
6 changes: 6 additions & 0 deletions .devcontainer/.bash_aliases
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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

# ==================================================================================================

Expand Down
33 changes: 21 additions & 12 deletions .devcontainer/base/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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 \
Expand All @@ -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 && \
Expand All @@ -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 <functional>, which libstdc++
# brings along with <format> 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 <span>$/&\n#include <functional>/' 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 && \
Expand All @@ -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
Expand All @@ -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 && \
Expand All @@ -155,19 +167,16 @@ 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.
#
# 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 && \
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)")
Expand Down
2 changes: 1 addition & 1 deletion include/anyhttp/corosio/net.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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++;
Expand Down
37 changes: 22 additions & 15 deletions include/anyhttp/net.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
3 changes: 2 additions & 1 deletion include/anyhttp/reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ class Reader
template <capy::MutableBufferSequence Buffers>
Task<std::tuple<error_code, size_t>> 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{});
Expand Down
3 changes: 2 additions & 1 deletion include/anyhttp/writer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ class Writer
template <capy::ConstBufferSequence Buffers>
Task<std::tuple<error_code, size_t>> 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()));
Expand Down
15 changes: 13 additions & 2 deletions scripts/bench.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down