mirror of
https://github.com/shadowsocks/shadowsocks-libev.git
synced 2026-10-29 12:36:53 +00:00
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
This commit is contained in:
@@ -92,12 +92,14 @@ const std::uint8_t kAddr[] = { 0x03, 11, 'e', 'x', 'a', 'm', 'p', 'l', 'e', '.',
|
||||
std::vector<std::uint8_t> cpp_decrypt_all(sc::Aead2022TcpDecryptor &dec, const std::vector<std::uint8_t> &wire)
|
||||
{
|
||||
std::vector<std::uint8_t> got;
|
||||
std::vector<std::uint8_t> out(sc::k2022MaxChunk);
|
||||
std::vector<std::uint8_t> out(70000);
|
||||
for (std::size_t off = 0; off < wire.size();) {
|
||||
std::size_t n = std::min<std::size_t>(1 + randombytes_uniform(9000), wire.size() - off);
|
||||
std::span<const std::uint8_t> in(wire.data() + off, n);
|
||||
for (;;) {
|
||||
auto step = dec.decrypt(in, out);
|
||||
// Output windows of any size, down to one byte.
|
||||
std::size_t room = randombytes_uniform(4) == 0 ? 1 + randombytes_uniform(16) : 1 + randombytes_uniform(70000);
|
||||
auto step = dec.decrypt(in, std::span<std::uint8_t>(out).first(room));
|
||||
SS_CHECK(step);
|
||||
got.insert(got.end(), out.begin(), out.begin() + step->produced);
|
||||
in = in.subspan(step->consumed);
|
||||
|
||||
Reference in New Issue
Block a user