Commit Graph
3 Commits
Author SHA1 Message Date
Max Lv ee7539155d C++20 port 16/16: config parsing on arenas, unit tests in C++ (#3080)
* Rename test_jconf.c to test_jconf_cpp.cpp

* Parse the config file on arenas

read_jconf now reads the file and builds the JSON tree in a scratch arena
that is released before it returns, and copies the parsed strings into one
process-lifetime arena instead of a malloc per string. parse_addr and the
config parser share one address splitter.

Port test_jconf to C++ and cover every field copied out of the parse tree,
a re-read, and the densest file the size limit accepts.

* tests: rename remaining C unit tests to .cpp (no content changes)

* tests: port remaining C unit tests to the C++ test harness

Convert acl, acl_literal, aead2022, base64, buffer, cache (legacy
reference), crypto, ipset, ipset_reference, json, netutils, ppbloom,
process, ref, ssurl and utils tests to test_helpers.hpp. ctest names are
unchanged; every assertion is kept. Build the ported sources with the
strict C++ warning set.

* Run clang-tidy on every ported test

The test regex skipped file names with digits (test_aead2022_cpp.cpp,
test_base64_cpp.cpp); include them, fix the two optional accesses it then
reports, and build test_jconf with the strict warning set.

* docs: per-connection RSS on Linux against the C relay

* test_jconf: check read_jconf results before using them
2026-10-15 10:17:23 +08:00
Max Lv 5c62b2544e C++20 port 11/14: one TCP and UDP relay engine for all programs (#3075)
* Rewrite the resolver in C++ on a fixed query pool

Queries live in pool slots with their first A and AAAA answer inline,
c-ares sockets are watched from a fixed table, and answers reach the
waiter through a callback plus opaque words instead of a back-pointer.
resolv.cpp keeps the C API as a shim. The event Loop can now adopt the
ss_event loop, and a Poll can stop watching a socket it does not own.

* Add the C++ TCP relay engine and run ss-tunnel on it

One engine (src/relay/tcp) for the four TCP relays: connections live in a
fixed pool owned through PoolPtr, handshake, cipher state and buffers are
inline, timeouts are intrusive deadline lists on one timer and DNS answers
come back through generation-checked handles. A full pool refuses new
connections and pauses accepting until a slot frees.

ss-tunnel is the first user; its hand-written relay callbacks are gone.
tests/tunnel_interop.py covers every method against ss-server and
shadowsocks-rust.

* Run ss-local and libshadowsocks-c on the C++ TCP relay engine

The SOCKS5 handshake, the ACL bypass decision (with its own resolver for
host-name rules) and the short wait for a first payload are now engine
code; local.cpp keeps only option parsing and startup. The library entry
points start the same engine.

* Run ss-server on the C++ TCP relay engine

The request header, outbound ACL, target resolution through the relay's
resolver, the anti-probing stop stage and the manager traffic counters
are engine code now; the connmark-to-TOS tracker becomes a pair of relay
hooks. server.cpp keeps option parsing, nftables and the stats timer.

* Fix the build with GCC and libstdc++

crypto.h's min/max macros broke <algorithm> in C++ sources that include
it first, netutils.h's linux/tcp.h clashed with the netinet/tcp.h libuv
includes, and GCC rejects memcpy into crypto_t. Apple clang accepted all
three.

* Run ss-redir and every UDP relay on the C++ engines

ss-redir's TCP side moves onto the relay engine (per-listener TOS for the
DSCP ports). src/relay/udp replaces udprelay.cpp: sessions keyed by
client address own their upstream socket and live in a fixed LRU,
AEAD-2022 server sessions are shared through RefPtr between the
session-ID table and the relays using them, and datagrams waiting for
DNS sit in pool slots. Packets are received into and built in
relay-owned buffers instead of a 64 KiB allocation per datagram. The
programs no longer call crypto_init(); Method sets up libsodium and the
replay filter.

* Let the allocation audit target an IP so DNS costs show separately

* Copy the literal ACL address without strncpy

GCC 13 at -O3 rejects the strncpy from the 256-byte host into the
INET6_ADDRSTRLEN buffer (-Wstringop-truncation) on glibc and UCRT64.

* Include <ctime> for std::time in the UDP relay (libstdc++)

* Build the UDP relay with Clang on musl

musl's CMSG_NXTHDR compares a size_t with a ptrdiff_t, which Clang's
-Wsign-compare rejects in C++. Call it from one helper that suppresses
the warning there.

* Keep clang-tidy clean in the relay engine
2026-10-15 10:05:43 +08:00
Max Lv 5dbcbcbb89 C++20 port 10/14: allocation-free SIP022 codecs (#3074)
* Add allocation-free C++ SIP022 codecs

TCP request/response streams with the salt echo between the two
directions, an exact-match salt pool on FixedLru, and UDP packets sealed
and opened in place with caller-owned session state. Differentially
tested against aead2022.cpp in both roles; the steady phase allocates
nothing.

* Include <algorithm> for std::min in test_crypto_aead2022_cpp.cpp

* Include C++ headers before crypto.h in test_crypto_aead2022_cpp.cpp

crypto.h defines min/max macros for the C sources; libstdc++ headers
included after it fail to parse.
2026-10-15 10:04:04 +08:00