203 Commits
Author SHA1 Message Date
Max Lv 002b4093fd C++20 port 14/14: remove the C shims, report, fixes (#3077)
* Remove ss_event and the C resolver shim

Each program's loop, signals, plugin watcher and stats timer now go
through ss::event::Program (src/event/program.hpp), held on main()'s
stack; ss-manager uses it too. ss-server resolves the manager address
with the relay resolver. With no C caller left, ss_event.cpp/.h,
resolv.cpp/.h and their C tests go; test_resolver_cpp.cpp replaces the
resolver tests against the same delayed local DNS server, and ss_ev is
now an interface target over libuv.

* Reinitialize the event loop after daemonize()

The loop is created before the programs fork into the background, and
kqueue/epoll descriptors do not survive fork(), so ss-server -f (which
ss-manager always uses) died as soon as it ran. Call uv_loop_fork() in
the child.

* Move the C codecs to tests/reference and drop uthash from ss-manager

The programs now use only the C++ codecs. The C stream/AEAD/AEAD-2022
implementations stay as the reference the differential tests and the C
unit tests compare against. Key derivation and the cipher tables used by
the doc snippets move to src/crypto/keys.{hpp,cpp}.

ss-manager keeps its servers in an ss_list (at most MAX_PORT_NUM,
looked up only on control messages) instead of a uthash table, and
tests/test_manager.py covers add/ping/list/remove end to end.

* Replace uthash and ss_list with the C++ containers

The C cache (now used only by the reference codecs) moves to
tests/reference and src/uthash.h is deleted. ACL rules and ss-manager's
servers are ListNodes on IntrusiveLists; destroying an element unlinks
it, so the free paths no longer have to remember to. core.h keeps only
ss_ip. test_rule is ported to C++ and also covers literal rules.

* Describe the C++20/libuv build in the Debian and snap metadata

* Keep clang-tidy clean in the new C++ tests

* Add --max-dns-queries / max_dns_queries

Sizes the resolver's query pool, the last of the capacity settings the
no-heap-after-startup design calls for. Defaults are unchanged: the
connection limit (plus 64 on ss-server, which also resolves for its
statistics).

* Report the C++20 rewrite: allocation, size, throughput and memory

docs/performance.md compares master (C) with the C++ engine on macOS
arm64: zero heap allocations per connection or datagram (from 27-89),
TCP throughput within noise, and about 20 MiB more RSS at 1,000 open
connections from the inline per-connection buffers. docs/cpp-core.md
and CLAUDE.md now describe the finished layout.

* Fix the MinGW build of ss-server: stat_resolver is POSIX-only

* Fix the fully static image and the build image for the C++ sources

docker/static: the C++ unit tests link the static libstdc++, whose error
paths need an unwinder that --rtlib=compiler-rt does not provide; link
llvm-libunwind. The programs themselves still need no C++ runtime.

docker/build: build in the default bundled mode with CMake instead of
against libev/udns (Alpine's Mbed TLS 4 is not supported by system
mode).

* Fall back to the system heap when a library realloc cannot be served

heap_realloc returned NULL when a block outgrew the largest size class or
the budget, and libuv aborts when growing its watcher array fails: a poll
on fd 8190 or above (about 4,000 connections) killed the process.
Move the block to the system heap instead, as malloc and calloc already
do. test_heap_guard_cpp polls fd 16380 with the heaps installed.

* Leave pool room for UDP sessions that are still closing

An evicted session keeps its pool slot until its socket's close callback
runs, so with pool capacity equal to the table's the acquire after an
eviction failed: a full table dropped new-session packets after evicting
a live session for nothing. The AEAD-2022 shared-session pool had the
same problem with entries still referenced by relay sessions.

* Time client-side TCP connections when idle, not only while connecting

ss-local, ss-tunnel and ss-redir only timed the upstream connect (as the
C relays did), so a client that never finished its SOCKS handshake, or a
stream whose peer vanished without a FIN, held a pool slot forever. With
the pool now a hard cap that pauses accepting when full, enough of them
stopped the listener for good. Every connection now starts with the idle
deadline, connected() re-arms it, and traffic refreshes it for all kinds
(the idle timeout keeps its 24 h floor, MIN_TCP_IDLE_TIMEOUT).

* Include <algorithm> for std::min in crypto/keys.cpp (CLANG64)

* test.py: accept host:port for --dns

The tunnel test hard-coded port 53, so it could only use a public
resolver or root. With a port it runs against a local DNS stand-in.

* Use the Mbed TLS compat wrappers for MD5 key derivation

* Fix the documentation build after moving the codecs

utils.cpp's \snippet aead.cpp and stream.cpp now live in src/crypto/,
which was not on Doxygen's EXAMPLE_PATH, so the man1 and HTML builds
failed. List the documentation sources explicitly instead of guessing
their extension.
2026-10-15 10:11:56 +08:00
Max Lv a577ae0927 C++20 port 3/14: compile crypto, config, DNS, ACL and plugin modules as C++ (#3067)
* Make the crypto, config, DNS and plugin modules compile as C++

Cast allocator and memchr results explicitly, pass mbedtls_operation_t
to mbedtls_cipher_setkey, and declare the two locals in
ss2022_encrypt_first() before the gotos that jump past them. Drop the
unused RESOLV_MODE global that resolv.c defined by accident through an
anonymous enum declaration. Still valid C.

* Raise the test origin's listen backlog

socketserver listens with a backlog of 5. With concurrent connections
through the proxy on a loaded machine (parallel ctest), the backlog
overflows, the kernel resets the origin connection, and the proxy
correctly drops the client, which surfaced as intermittent
alloc_audit_report failures ("getpeername: Invalid argument" in
ss-local, "Connection reset by peer" in ss-server). Reproduced
reliably at 64 concurrent connections; gone with a backlog of 256.

* Compile the crypto, config, DNS, ACL and plugin modules as C++

Rename netutils, jconf, stream, aead, aead2022, aead2022_udp, crypto,
acl, plugin, plugin_disabled and resolv from .c to .cpp without changing
their contents, and update source lists, snippet references, test
comments and debian/copyright.

The Doxygen source list and scripts/check_cli_docs.py now accept either
extension for each module, so the remaining programs can move one at a
time. The new .cpp files are added to the no-heap ratchet baseline.
2026-10-15 09:52:17 +08:00
Max Lv 384810efce C++20 port 2/14: compile the leaf modules as C++ (#3066)
* Make headers and leaf modules compile as C++

Wrap the declarations of every project header in extern "C" (after the
system includes, which must keep C++ linkage), so converted modules and
the remaining C files agree on linkage.

In the leaf modules, cast allocator and memchr results explicitly,
rename identifiers called new, replace the getpwnam_r VLA with the
fixed 16 KiB buffer the loop already capped itself at, and make the
rlimit initialiser conversion explicit. All of this is still valid C.

* Compile the leaf modules as C++

Rename base64, json, ipset, process, ppbloom, rule, ssurl and cache from
.c to .cpp without touching their contents, and update the CMake source
lists, debian/copyright and the docs.

Ported code keeps -Wall; -Wextra is now opt-in through
ss_strict_warnings() for code written as C++ (the core tests).
check_no_heap.py gains a ratchet baseline for the converted modules,
which still allocate the way the C code did. A new check_cxx_runtime
test verifies with nm that the programs and libshadowsocks-c.a still
need no C++ runtime library, so C consumers are unaffected.

* Fix the Windows branches of process.cpp for C++

Cast allocator results and the thread argument explicitly and
value-initialise JOBOBJECT_EXTENDED_LIMIT_INFORMATION with {}. Found by
the zig x86_64-windows-gnu cross build.

* Keep clang-tidy clean for the converted modules

Once the C headers are included from C++ translation units,
bugprone-dynamic-static-initializers reports each extern variable
declaration in them; none is defined in a header, so disable the check.
Mark the two bounded memchr searches in ssurl.cpp, which
bugprone-not-null-terminated-result misreads as string copies.

* check_cxx_runtime: ignore glibc symbol versions

nm on glibc prints __cxa_atexit@GLIBC_2.2.5, which the allowlist for the
libc-provided __cxa_atexit/__cxa_finalize did not match.

* Keep GCC's C++-only warnings off for modules converted from C

GCC's C++ -Wall includes -Wsign-compare and -Wclass-memaccess, which C's
-Wall does not, so the converted modules failed -Werror on GCC (Linux,
UCRT64) although nothing in them changed. They keep the warning set they
were written against; code under ss_strict_warnings() re-enables both.
2026-10-15 09:48:18 +08:00
Max Lv f5d5bf0be1 Publish native Doxygen documentation with GitHub Pages 2026-09-12 14:46:42 +08:00
Max Lv bdc77408cb Rename to shadowsocks-c with libuv, async DNS and CI lint (#3051)
Rename the project to shadowsocks-c while retaining ss-* commands, the embedding ABI, and legacy library/package lookup compatibility.

Replace libev with bundled libuv for IOCP/kqueue event backends, expand asynchronous runtime DNS coverage, and add actionlint/Ruff with strict clang-tidy failure handling. Validate native platforms, static builds, packaging, interoperability, sanitizers, and canonical/legacy consumers.

All 22 hosted checks pass at reviewed head a8493250eb.
2026-09-11 14:18:37 +08:00
Max Lv 201e70c4bd Modernize C builds with offline dependencies and portable runtime helpers (#3050)
Bundle pinned offline dependencies, remove libcork/libipset and submodule requirements, and add portable runtime helpers with relocatable static/shared library installations.

Add Clang static build validation for Linux/musl, macOS and Windows, real TCP/UDP and SIP003 interoperability coverage, and recorded performance tradeoffs. All 21 hosted checks pass at the reviewed PR head 8d504e6218.
2026-09-11 13:42:11 +08:00
Max LvandClaude Opus 4.6 c5e8788013 Bump version to 3.3.6
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 09:15:12 +08:00
Max LvandClaude Opus 4.6 6423c8e496 Add Debian package build test and statically link bundled submodules
Add tests/test_deb_build.sh with four phases:
1. Build .deb packages via dpkg-buildpackage
2. Verify all three packages contain expected files (binaries, man
   pages, shared library, headers, pkg-config)
3. Install packages and resolve dependencies
4. Smoke-test installed binaries, ldconfig, and headers

Add a Linux-only CI step in build.yml to run the test.

Statically link the bundled submodule libraries (libcork, libipset,
libbloom) into all targets instead of building them as shared libs.
These are vendored code built from git submodules, not system
libraries, so static linking is correct and eliminates
dpkg-shlibdeps warnings about missing .so files.

Pass -DWITH_STATIC=OFF in debian/rules since debian build-depends
only provide shared library dev packages.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 11:32:13 +08:00
mesher2024 d52d4015d1 Update configure parameter in debian/rules 2026-02-08 09:59:34 +08:00
mesher2024 bb104036d2 Remove configure parameters in debian/rules 2026-02-08 09:59:34 +08:00
mesher2024 2d8af6e56c Update build-depends in debian/control
Replace libpcre3-dev with libpcre2-dev.
2026-02-08 09:59:34 +08:00
Max Lv d1171f44d0 Revert ""DynamicUser=true" makes "/etc/init.d/shadowsocks-libev start" fail."
This reverts commit ca4caabac6.
2021-05-13 12:33:57 +08:00
abner_bob ca4caabac6 "DynamicUser=true" makes "/etc/init.d/shadowsocks-libev start" fail. 2021-05-12 16:12:56 +08:00
Maxim Shpak 6329526199 Run systemd service after network is available (unit file fix)
There is a race condition between shadowsocks-libev.service and
systemd-resolved.service after reboot/on boot. The shadowsocks
service tries to start before the dns service is started properly
and fails showing the corresponding errors in the logs.
2021-03-31 07:39:59 +08:00
Max Lv 8285e5a7de Bump version 2020-09-15 10:30:48 +08:00
Roger Shimizu 5f947a8466 debian/rules: Fix #2675
Regression caused by commit [0d96da4].
2020-04-18 21:21:07 +09:00
Roger Shimizu 0d96da4471 Sync debian/ folder with debian version 3.3.4+ds-3 2020-03-29 17:49:39 +09:00
Mygod 301fea635b Remove sniparser 2020-02-11 23:48:30 -05:00
Max Lv 72d7d9217c Bump version 2020-01-10 09:48:42 +08:00
Max Lv e2765847cc Bump version 2019-10-31 15:16:05 +08:00
Max Lv 346ab1be47 Bump version 2019-10-12 15:20:52 +08:00
Max Lv 715f26e285 Change the default timeout value to 24h 2019-09-02 09:39:24 +08:00
Max Lv 615588bd39 Bump version 2019-08-09 15:17:53 +08:00
Suilong Liang c04e6dfe2d Change from network.target to network-online.target in systemd service files. 2019-06-26 11:51:37 +08:00
Max Lv ffad914ddd Bump version 2019-06-08 08:01:47 +08:00
Max Lv b0c6ba4945 Bump version 2019-03-09 19:07:22 +08:00
Max Lv c9159fc927 Bump version 2019-02-26 12:33:30 +08:00
Max Lv 545c04182f Bump version 2018-11-28 00:48:15 -08:00
Max Lv c8ea784ded Bump version 2018-11-26 21:04:24 -08:00
Max Lv 1d83944f5e Fix typos 2018-11-07 22:49:14 -08:00
Max Lv b9ed8da571 Bump version 2018-11-07 22:46:20 -08:00
edsgerlin 0496416387 Add AmbientCapabilities for all. 2018-09-15 17:20:57 +09:00
edsgerlin d5d28580f9 Add CAP_NET_BIND_SERVICE to shadowsocks-libev.service
It ensures process have permission to bind to port <=1000.
Other systemd config files already have it except this one.
2018-09-15 01:39:49 +09:00
Boyuan Yang 8a4b9d04e9 debian: Remove debian/*.symbols file (#2177)
Symbols file are meant to be used by distribution maintainers and
it is rather useless for upstream repository.
2018-09-12 07:56:05 +08:00
Max Lv 8c98bdecac Bump version 2018-05-28 19:55:12 -07:00
Max Lv 85a64ae836 Bump version 2018-01-15 17:25:03 -08:00
Max Lv cba94db423 Bump version 2017-12-28 21:09:40 -08:00
Roger Shimizu 24ecf4d780 Sync debian/ folder with debian release 3.1.1+ds-1~exp1 2017-11-23 20:06:38 +09:00
Max Lv 82198aece8 Bump version 2017-11-20 12:22:43 +08:00
Max Lv 69c41d9752 Bump version 2017-09-14 19:31:13 -07:00
Howard Liu 7525d518de Fixed Debian Package Control (#1656)
Removed dependency libudns-dev, added libc-ares-dev
2017-09-01 09:21:23 +08:00
Max Lv f1dd1354a9 Bump version 2017-07-27 11:22:27 +08:00
Max Lv c11b2c08e4 Bump version 2017-06-27 14:17:53 +08:00
Max Lv bc96aed3b0 Bump version 2017-04-26 15:02:56 +08:00
Daniel 82edb21595 Updates the ciphersuite method in debian/config.json.
This commit changes the "method" parameter in the debian/config.json
from "rc4-md5" to "chacha20-ietf-poly1305". rc4-md5 is unsafe and
there is support for a better AEAD ciphersuite.
2017-04-09 07:53:51 +08:00
Max Lv 48f5a3bec8 Bump version 2017-03-21 13:56:13 +08:00
Max Lv b725d575f2 Bump version 2017-03-16 14:21:11 +08:00
Rick Lei e63de4ce23 Turn off errexit option when detecting the apg command
Commit https://github.com/shadowsocks/shadowsocks-libev/commit/f32ac38c2f7aab09ec25131209954957518de42a
allows to use pwgen to generate the initial password at the first
installation. However it won't work when apg isn't installed because:

* the postinst script has errexit option set ("set -e")
* at the first installation of ss-libev, apg or pwgen will be called to
  generate the initial password in config.json
* when apg isn't installed, "pathfind apg" would return 1
* and the postinst script will immediately exit due to "set -e"

This commit temporarily turn off the errexit option for pathfind()
2017-03-09 12:48:37 +08:00
Patrick Li f32ac38c2f Allow the use of pwgen to generate passwords 2017-03-07 16:26:46 +08:00
Max Lv 661429e579 Bump version 2017-02-24 12:16:20 +08:00