zenith-stack 0.1.0

Zenith 全协议栈框架:AF_XDP + eBPF + TLS 1.3 + HTTP/1-2-3 + Web + Proxy + WAF,按需导入
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
//! # hello_server — Zenith Web 真实网络 E2E 演示
//!
//! 演示真实 `std::net::TcpListener` / `std::net::UdpSocket` 端口监听 +
//! `ProtocolServer` 全链路处理(TLS 1.3 / QUIC / HTTP/1.1 / HTTP/3 真实加解密 +
//! HTTP/1.1 keep-alive + 路由 + 中间件)。
//!
//! ## 运行(顶层 workspace 根目录)
//!
//! ```sh
//! # 1) 明文 HTTP (默认端口 18080):
//! cargo run --features web --example hello_server -- --mode plain
//!
//! # 2) HTTPS TLS 1.3 (默认端口 18443,需环境变量提供证书/私钥):
//! ZENITH_DEMO_CERT_PATH=cert.pem ZENITH_DEMO_KEY_PATH=key.pem \
//! cargo run --features web,tls --example hello_server -- --mode tls
//!
//! # 3) HTTP/3 over QUIC over UDP (默认端口 18443,需环境变量提供证书/私钥):
//! ZENITH_DEMO_CERT_PATH=cert.pem ZENITH_DEMO_KEY_PATH=key.pem \
//! cargo run --features web,tls,http3 --example hello_server -- --mode h3
//! ```
//!
//! ## 验证请求
//!
//! ```sh
//! # 明文
//! curl -v http://127.0.0.1:18080/
//! curl -v http://127.0.0.1:18080/hello/world
//! curl -v -X POST http://127.0.0.1:18080/echo -d 'ping'
//! curl -v http://127.0.0.1:18080/status
//!
//! # TLS (自签证书,-k 跳过校验):
//! curl -vk https://127.0.0.1:18443/
//! curl -vk https://localhost:18443/hello/tls
//!
//! # HTTP/3 over QUIC (curl 需要 --http3 标志,现代 curl 7.66+ 内置):
//! curl -vk --http3 https://localhost:18443/
//! curl -vk --http3 https://127.0.0.1:18443/status
//! curl -vk --http3 -X POST https://127.0.0.1:18443/echo -d 'ping'
//! ```
//!
//! ## 退出
//! 按 Ctrl+C 或发送 SIGINT。

#![deny(unsafe_code)]

use std::env;
use std::net::{SocketAddr, TcpStream};
use std::process::ExitCode;
use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::Arc;
use std::time::{SystemTime, UNIX_EPOCH};

use zenith_stack::api::CanonicalResponse;
use zenith_stack::web::app::{success_response, App};
use zenith_stack::web::server::{ProtocolServer, ServerConfig, ServerError};

#[cfg(feature = "tls")]
use zenith_stack::tls::{CertGeneration, TlsAcceptor, TlsConfig};

#[cfg(all(feature = "tls", feature = "http3"))]
use zenith_stack::web::quic_server::QuicServerConfig;

// ─────────────────────────────────────────────────────────────────────────────
// 演示证书/私钥已移出源码(安全审计:禁止入库私钥)。
// 运行时通过环境变量加载文件路径:
//   ZENITH_DEMO_CERT_PATH=/path/to/cert.pem
//   ZENITH_DEMO_KEY_PATH=/path/to/key.pem
// 真实部署请用 CertGeneration::from_pem() 加载来自证书管理器的证书。
// ─────────────────────────────────────────────────────────────────────────────

#[derive(Debug, Clone, Copy)]
enum Mode {
    Plain,
    #[cfg(feature = "tls")]
    Tls,
    #[cfg(all(feature = "tls", feature = "http3"))]
    H3,
}

struct Args {
    mode: Mode,
    bind: SocketAddr,
    /// 审计日志落盘路径(JSON Lines;None = 仅内存环形缓冲)
    audit_log: Option<String>,
}

fn parse_args() -> Result<Args, String> {
    let mut mode = Mode::Plain;
    let mut port: u16 = 18080;
    let mut host: String = "::".to_string();
    let mut audit_log: Option<String> = None;

    let mut it = env::args().skip(1);
    while let Some(arg) = it.next() {
        match arg.as_str() {
            "--mode" => {
                #[allow(unreachable_patterns)]
                let val = it.next().ok_or("--mode 需要 <plain|tls|h3>")?;
                match val.as_str() {
                    "plain" => {
                        mode = Mode::Plain;
                        if port == 18443 {
                            port = 18080;
                        }
                    }
                    #[cfg(feature = "tls")]
                    "tls" => {
                        mode = Mode::Tls;
                        if port == 18080 {
                            port = 18443;
                        }
                    }
                    #[cfg(all(feature = "tls", feature = "http3"))]
                    "h3" => {
                        mode = Mode::H3;
                        if port == 18080 {
                            port = 18443;
                        }
                    }
                    #[cfg(not(feature = "tls"))]
                    "tls" | "h3" => {
                        return Err(
                            "tls/h3 模式需要启用 tls feature: cargo run --features web,tls ..."
                                .to_string(),
                        );
                    }
                    #[cfg(all(feature = "tls", not(feature = "http3")))]
                    "h3" => {
                        return Err(
                            "h3 模式需要启用 http3 feature: cargo run --features web,tls,http3 ..."
                                .to_string(),
                        );
                    }
                    other => return Err(format!("未知 --mode {other:?},可选 <plain|tls|h3>")),
                }
            }
            "--port" => {
                let val = it.next().ok_or("--port 需要 <PORT>")?;
                port = val.parse::<u16>().map_err(|e| format!("--port 解析失败: {e}"))?;
            }
            "--host" => {
                host = it.next().ok_or("--host 需要 <HOST>")?;
            }
            "--bind" => {
                let val = it.next().ok_or("--bind 需要 <HOST:PORT>")?;
                let sa: SocketAddr = val.parse().map_err(|e| format!("--bind 解析失败: {e}"))?;
                host = sa.ip().to_string();
                port = sa.port();
            }
            "--audit-log" => {
                let val = it.next().ok_or("--audit-log 需要 <PATH>")?;
                audit_log = Some(val);
            }
            "-h" | "--help" => {
                println!(
                    "{}",
                    concat!(
                        "hello_server — Zenith Web 真实端口监听演示\n",
                        "USAGE:\n",
                        "  hello_server [--mode plain|tls|h3] [--port PORT] [--host HOST]\n",
                        "FLAGS:\n",
                        "  -h, --help    显示帮助\n",
                        "OPTIONS:\n",
                        "  --mode <plain|tls|h3>   运行模式,默认 plain\n",
                        "                         plain  = HTTP/1.1 over TCP (明文)\n",
                        "                         tls    = HTTP/1.1 + TLS 1.3 over TCP\n",
                        "                         h3     = HTTP/3 over QUIC over UDP\n",
                        "  --port <u16>            监听端口,默认 plain=18080 / tls=18443 / h3=18443\n",
                        "  --host <ip>             监听地址,默认 ::\n",
                        "  --bind <HOST:PORT>      便捷合并写法(等价于同时指定 --host 和 --port)\n",
                        "  --audit-log <PATH>      审计日志落盘(JSON Lines 追加写;缺省仅内存)\n",
                    )
                );
                std::process::exit(0);
            }
            other => return Err(format!("未知参数 {other:?},使用 -h 查看帮助")),
        }
    }

    // IPv6 地址需要方括号包裹(如 [::]:8080),IPv4 不需要
    let bind: SocketAddr = if host.contains(':') {
        format!("[{host}]:{port}")
    } else {
        format!("{host}:{port}")
    }
    .parse()
    .map_err(|e| format!("SocketAddr 解析失败: {e}"))?;

    Ok(Args { mode, bind, audit_log })
}

/// 构建 ProtocolServer(指定 --audit-log 时 fail-closed:落盘打开失败直接报错)
/// WAF 严格按需:本示例显式开启,演示内置 5 检测器拦截。
fn build_server(app: App, args: &Args) -> Result<ProtocolServer, String> {
    let cfg = ServerConfig::new().with_waf(true);
    match &args.audit_log {
        Some(path) => ProtocolServer::try_with_config(app, cfg.with_audit_log_path(path.clone()))
            .map_err(|e| format!("审计日志落盘初始化失败 ({path}): {e}")),
        None => Ok(ProtocolServer::with_config(app, cfg)),
    }
}

// ─────────────────────────────────────────────────────────────────────────────
// 构建 Web App:路由 + 处理器
// ─────────────────────────────────────────────────────────────────────────────
fn build_app() -> App {
    let mut app = App::new();

    // GET / — 欢迎页
    app.get("/", |_req, _rm| {
        let body = concat!(
            "<!doctype html><html><body style=\"font-family:sans-serif;padding:2rem\">",
            "<h1>Zenith Hello Server ✓</h1>",
            "<p>真实链路:std::net::TcpListener → ProtocolServer::serve_std_tcp_conn → ",
            "Router → Handler</p>",
            "<ul>",
            "<li><code>GET  /</code>            — 本页</li>",
            "<li><code>GET  /hello/:name</code> — 路径参数问候</li>",
            "<li><code>POST /echo</code>        — 回显请求体</li>",
            "<li><code>GET  /status</code>      — 服务器状态 JSON</li>",
            "<li><code>GET  /404</code>         — 404 演示</li>",
            "</ul></body></html>\n"
        );
        Ok(success_response(body, "text/html; charset=utf-8"))
    });

    // GET /hello/:name — 路径参数
    app.get("/hello/:name", |_req, rm| {
        let name = rm.get("name").unwrap_or("stranger");
        Ok(success_response(
            format!("Hello, {name}! 🚀\n"),
            "text/plain; charset=utf-8",
        ))
    });

    // POST /echo — 回显请求体
    app.post("/echo", |req, _rm| {
        // 查找 content-type 头(大小写不敏感查找)
        let ct: Vec<u8> = req
            .find_header("content-type")
            .map(|h| {
                let len = h.value_len as usize;
                h.value[..len].to_vec()
            })
            .unwrap_or_else(|| b"application/octet-stream".to_vec());
        let mut resp = CanonicalResponse::new(200);
        let _ = resp.add_header(b"content-type", &ct);
        let _ = resp.add_header(b"x-echoed-length", &req.body().len().to_string().into_bytes());
        resp.set_body(req.body().to_vec());
        Ok(resp)
    });

    // GET /status — JSON 状态
    app.get("/status", |_req, _rm| {
        let ts = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .map(|d| d.as_secs())
            .unwrap_or(0);
        let json = format!(
            concat!(
                "{{",
                "\"ok\":true,",
                "\"server\":\"zenith-web\",",
                "\"protocol\":\"HTTP/1.1 (+TLS 1.3 when tls mode)\",",
                "\"timestamp_sec\":{ts}",
                "}}\n"
            ),
            ts = ts,
        );
        Ok(success_response(json, "application/json"))
    });

    if let Err(e) = app.validate() {
        eprintln!("[hello_server] 路由配置错误: {e}");
        // 返回一个空 App 以让调用方处理错误
    }
    app
}

// ─────────────────────────────────────────────────────────────────────────────
// 明文连接处理(始终可编译)
// ─────────────────────────────────────────────────────────────────────────────
fn handle_conn_plain(
    server: &ProtocolServer,
    stream: TcpStream,
    peer: SocketAddr,
) -> Result<(), ServerError> {
    // 明文:直接用 serve_std_tcp_conn,tls_acceptor = None
    // 内部会走「peek 24B → 检测协议 → Http1 handle_http1_connection」分支
    server.serve_std_tcp_conn(stream, peer, None)
}

// ─────────────────────────────────────────────────────────────────────────────
// TLS 连接处理(仅 feature = "tls")
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(feature = "tls")]
fn handle_conn_tls(
    server: &ProtocolServer,
    stream: TcpStream,
    peer: SocketAddr,
    tls_acceptor: &mut TlsAcceptor,
) -> Result<(), ServerError> {
    // TLS:传入 &mut TlsAcceptor
    // 内部严格链路:
    //   1. stream.peek(16KB) 预读 ClientHello(不移动游标,StreamOwned 完整握手)
    //   2. 解析 SNI / ALPN;按 SNI resolve_server_config(无证书 fail-closed)
    //   3. 构造 TlsStream::new(stream, config) → rustls StreamOwned 真实加解密
    //   4. dispatch_protocol(Http1) → handle_http1_connection 完整 keep-alive
    server.serve_std_tcp_conn(stream, peer, Some(tls_acceptor))
}

#[cfg(feature = "tls")]
fn build_demo_cert() -> Result<CertGeneration, ExitCode> {
    // 优先从环境变量加载证书/私钥文件(真实部署推荐方式);
    // 未设置时自动生成临时自签证书(openssl req -x509),保证开箱即用。
    let cert_path = env::var("ZENITH_DEMO_CERT_PATH");
    let key_path = env::var("ZENITH_DEMO_KEY_PATH");
    if let (Ok(c), Ok(k)) = (cert_path, key_path) {
        let cert_pem = std::fs::read(&c).map_err(|e| {
            eprintln!("[hello_server] 读取证书文件失败 ({c}): {e}");
            ExitCode::from(1)
        })?;
        let key_pem = std::fs::read(&k).map_err(|e| {
            eprintln!("[hello_server] 读取私钥文件失败 ({k}): {e}");
            ExitCode::from(1)
        })?;
        return CertGeneration::from_pem(&cert_pem, &key_pem).map_err(|e| {
            eprintln!("[hello_server] 演示证书 PEM 解析失败: {e}");
            ExitCode::from(1)
        });
    }
    // 环境变量未设置:用 openssl 生成临时自签证书(CN=localhost, RSA 2048, 1 天)
    // 使用 temp_dir + PID + 时间戳构建唯一路径,加载后立即删除(禁止私钥残留磁盘)
    let ts = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .map(|d| d.as_nanos())
        .unwrap_or(0);
    let suffix = format!("{}_{}", std::process::id(), ts);
    let tmp_cert = std::env::temp_dir()
        .join(format!("zenith_demo_cert_{suffix}.pem"))
        .to_string_lossy()
        .into_owned();
    let tmp_key = std::env::temp_dir()
        .join(format!("zenith_demo_key_{suffix}.pem"))
        .to_string_lossy()
        .into_owned();
    let status = std::process::Command::new("openssl")
        .args([
            "req", "-x509", "-newkey", "rsa:2048",
            "-keyout", tmp_key.as_str(), "-out", tmp_cert.as_str(),
            "-days", "1", "-nodes", "-subj", "/CN=localhost",
        ])
        .stdout(std::process::Stdio::null())
        .stderr(std::process::Stdio::null())
        .status();
    match status {
        Ok(s) if s.success() => {
            let cert_pem = std::fs::read(&tmp_cert).map_err(|e| {
                eprintln!("[hello_server] 读取临时证书失败: {e}");
                ExitCode::from(1)
            })?;
            let key_pem = std::fs::read(&tmp_key).map_err(|e| {
                eprintln!("[hello_server] 读取临时私钥失败: {e}");
                ExitCode::from(1)
            })?;
            // 加载后立即删除临时证书/私钥文件(安全:禁止残留私钥到磁盘)
            let _ = std::fs::remove_file(&tmp_cert);
            let _ = std::fs::remove_file(&tmp_key);
            CertGeneration::from_pem(&cert_pem, &key_pem).map_err(|e| {
                eprintln!("[hello_server] 临时证书 PEM 解析失败: {e}");
                ExitCode::from(1)
            })
        }
        _ => {
            eprintln!(
                "[hello_server] openssl 不可用,无法生成临时证书。\n  \
                 请设置环境变量:\n  \
                 export ZENITH_DEMO_CERT_PATH=/path/to/cert.pem\n  \
                 export ZENITH_DEMO_KEY_PATH=/path/to/key.pem"
            );
            Err(ExitCode::from(1))
        }
    }
}

#[cfg(feature = "tls")]
fn build_tls_acceptor() -> Result<TlsAcceptor, ExitCode> {
    // 严格 RFC 7301:ALPN 只宣告本端真实支持的协议。
    // std-TCP/TLS 传输层已集成 HTTP/1.1(串行 keep-alive)和 HTTP/2(完整帧状态机),
    // 因此同时宣告 h2 和 http/1.1,让客户端通过 ALPN 选择最优协议。
    // h3 仍需 QUIC 传输层(AF_XDP DGRAM),此处不宣告。
    let std_transport_alpn: Vec<Vec<u8>> = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
    let mut tls_config = TlsConfig::new().with_alpn(std_transport_alpn);
    // 启用 TLS 1.2 + 1.3:兼容 h2spec / blazehttp 等测试工具
    // (部分 Go-based 工具的 TLS 栈以 1.2 为默认协商起点)
    tls_config.min_version = Some(zenith_stack::tls::TlsVersion::Tls12);
    tls_config.max_version = Some(zenith_stack::tls::TlsVersion::Tls13);
    let mut acceptor = TlsAcceptor::new(tls_config);
    let demo_cert = build_demo_cert()?;
    acceptor.set_default_cert(demo_cert.clone()).map_err(|e| {
        eprintln!("[hello_server] 设置默认证书失败: {e}");
        ExitCode::from(4)
    })?;
    acceptor.set_cert_for_domain("localhost", demo_cert).map_err(|e| {
        eprintln!("[hello_server] 设置 localhost SNI 证书失败: {e}");
        ExitCode::from(4)
    })?;
    Ok(acceptor)
}

// ─────────────────────────────────────────────────────────────────────────────
// 主入口
// ─────────────────────────────────────────────────────────────────────────────
fn main() -> ExitCode {
    // tracing 生产链路接通:fmt subscriber(RUST_LOG 环境变量过滤,默认 info)
    let _ = tracing_subscriber::fmt()
        .with_env_filter(
            tracing_subscriber::EnvFilter::try_from_default_env()
                .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("info")),
        )
        .try_init();

    // 全局 tokio runtime 初始化(幂等;后台统计任务的执行引擎)
    let _global_rt = zenith_stack::rt::init_global(zenith_stack::rt::RuntimeConfig::auto());

    let args = match parse_args() {
        Ok(a) => a,
        Err(e) => {
            eprintln!("参数错误: {e}");
            return ExitCode::from(2);
        }
    };

    // ── 构建 App + Server(跨连接 Arc 共享,零拷贝) ────────────────────────
    let app = build_app();
    let route_count = app.route_count();

    println!(
        "[hello_server] mode={mode:?} bind={bind} routes={n}",
        mode = args.mode,
        bind = args.bind,
        n = route_count,
    );

    // ── HTTP/3 over QUIC over UDP:特殊分派路径(UDP socket + QUIC server) ──
    #[cfg(all(feature = "tls", feature = "http3"))]
    if matches!(args.mode, Mode::H3) {
        let mut server = match build_server(app, &args) {
            Ok(s) => s,
            Err(e) => {
                eprintln!("{e}");
                return ExitCode::from(2);
            }
        };
        let cert_gen = match build_demo_cert() {
            Ok(g) => g,
            Err(code) => return code,
        };
        let quic_cfg = QuicServerConfig {
            bind_addr: args.bind,
            ..QuicServerConfig::default()
        };
        if let Err(e) = server.bind_quic(quic_cfg, &cert_gen) {
            eprintln!("[hello_server] bind_quic({}) 失败: {e}", args.bind);
            return ExitCode::from(5);
        }
        println!(
            "[hello_server] QUIC/UDP 监听成功,本地 addr = {},证书 CN=localhost",
            server.quic_local_addr().unwrap_or(args.bind)
        );

        // ChangeSet 八态机热更新演示(真实调用,验证 prepare→commit 全链路)
        match server.trigger_changeset() {
            Ok(generation) => println!("[hello_server] ChangeSet 热更新演示成功,生成号 = {generation}"),
            Err(e) => eprintln!("[hello_server] ChangeSet 热更新演示失败: {e}"),
        }

        println!("[hello_server] Ctrl+C 退出。");
        match server.serve_udp_loop(65536) {
            Ok(()) => ExitCode::SUCCESS,
            Err(e) => {
                eprintln!("[hello_server] serve_udp_loop 错误: {e}");
                ExitCode::from(6)
            }
        }
    } else {
        run_tcp_server(args, app)
    }

    #[cfg(not(all(feature = "tls", feature = "http3")))]
    {
        run_tcp_server(args, app)
    }
}

/// TCP 模式 (plain / tls over TcpListener) — HTTP/1.1 事件循环
fn run_tcp_server(args: Args, app: App) -> ExitCode {
    let server = match build_server(app, &args) {
        Ok(s) => s,
        Err(e) => {
            eprintln!("{e}");
            return ExitCode::from(2);
        }
    };
    let server_arc: Arc<ProtocolServer> = Arc::new(server);

    // ChangeSet 八态机热更新演示(真实调用,验证 prepare→commit 全链路)
    match server_arc.trigger_changeset() {
        Ok(generation) => println!("[hello_server] ChangeSet 热更新演示成功,生成号 = {generation}"),
        Err(e) => eprintln!("[hello_server] ChangeSet 热更新演示失败: {e}"),
    }

    // ── TLS Acceptor 预构建(仅 tls 模式需要) ───────────────────────────────
    #[cfg(feature = "tls")]
    let tls_acceptor_maybe: Option<TlsAcceptor> = match args.mode {
        Mode::Plain => None,
        #[cfg(feature = "tls")]
        Mode::Tls => match build_tls_acceptor() {
            Ok(a) => {
                println!("[hello_server] TLS Acceptor 已就绪,证书代际已加载,CN=localhost");
                Some(a)
            }
            Err(code) => return code,
        },
        #[cfg(all(feature = "tls", feature = "http3"))]
        Mode::H3 => unreachable!("H3 模式已在上层分派"),
    };

    // ── 监听端口(使用项目全局 Tokio 运行时驱动异步 accept) ────────────────
    // 全链路闭环:accept 循环由 zenith_stack::rt 全局 Tokio 运行时驱动,
    // 每个连接的同步 I/O 处理器经 tokio::task::spawn_blocking 调度到
    // Tokio 有界阻塞线程池(自动按 CPU 核数缩放,无线程爆炸风险)。
    println!("[hello_server] Ctrl+C 退出。");

    const MAX_CONNECTIONS: u32 = 1024;
    let active_conns: Arc<AtomicU32> = Arc::new(AtomicU32::new(0));

    let _ = zenith_stack::rt::block_on(async move {
        let listener = match tokio::net::TcpListener::bind(args.bind).await {
            Ok(l) => l,
            Err(e) => {
                eprintln!("[hello_server] tokio TcpListener::bind({}) 失败: {e}", args.bind);
                return;
            }
        };
        println!(
            "[hello_server] tokio TcpListener 监听成功,本地 addr = {}",
            listener.local_addr().unwrap_or(args.bind)
        );

        // 全局 tokio runtime 后台统计任务(定期打印 /metrics 快照)
        let server_for_stats = server_arc.clone();
        zenith_stack::rt::spawn(async move {
            loop {
                tokio::time::sleep(std::time::Duration::from_secs(30)).await;
                let snapshot = server_for_stats.export_metrics();
                println!("[hello_server] 后台统计(30s 周期):\n{snapshot}");
            }
        });

        loop {
            let (stream, peer) = match listener.accept().await {
                Ok((s, p)) => (s, p),
                Err(e) => {
                    eprintln!("[hello_server] accept 错误: {e}");
                    continue;
                }
            };

            // 连接数上限检查(原子 CAS 防溢出)
            if active_conns.fetch_add(1, Ordering::Relaxed) >= MAX_CONNECTIONS {
                active_conns.fetch_sub(1, Ordering::Relaxed);
                eprintln!(
                    "[hello_server] 连接数已达上限 {MAX_CONNECTIONS},拒绝 peer={peer}"
                );
                let _ = stream.into_std();
                continue;
            }

            let server_clone: Arc<ProtocolServer> = Arc::clone(&server_arc);
            let conn_counter = Arc::clone(&active_conns);
            #[cfg(feature = "tls")]
            let tls_acc_clone = tls_acceptor_maybe.clone();
            let mode = args.mode;

            // 在全局 Tokio 运行时上 spawn 异步任务
            // 同步 I/O 处理器经 spawn_blocking 调度到有界阻塞线程池
            zenith_stack::rt::spawn(async move {
                // tokio TcpStream → std TcpStream(serve_std_tcp_conn 需要同步 I/O)
                // tokio 设为非阻塞模式,转换后必须恢复阻塞模式,否则 sync read/write 返回 EAGAIN
                let std_stream = match stream.into_std() {
                    Ok(s) => {
                        let _ = s.set_nonblocking(false);
                        s
                    }
                    Err(e) => {
                        eprintln!("[hello_server] stream 转换失败 peer={peer}: {e}");
                        conn_counter.fetch_sub(1, Ordering::Relaxed);
                        return;
                    }
                };

                // spawn_blocking:同步处理器运行在 Tokio 阻塞线程池
                // 线程池由运行时自动管理(默认上限 512,按 CPU 核数缩放)
                let result = tokio::task::spawn_blocking(move || {
                    let result: Result<(), ServerError> = match mode {
                        Mode::Plain => handle_conn_plain(&server_clone, std_stream, peer),
                        #[cfg(feature = "tls")]
                        Mode::Tls => {
                            let mut acc = tls_acc_clone.expect("tls mode should have built acceptor");
                            handle_conn_tls(&server_clone, std_stream, peer, &mut acc)
                        }
                        #[cfg(all(feature = "tls", feature = "http3"))]
                        Mode::H3 => unreachable!("H3 模式已在上层分派"),
                    };
                    match result {
                        Ok(()) => println!("[hello_server] 连接正常结束 peer={peer}"),
                        Err(ServerError::ConnectionClosed) => {
                            println!("[hello_server] 对端关闭 peer={peer}")
                        }
                        Err(e) => eprintln!("[hello_server] 连接处理错误 peer={peer}: {e}"),
                    }
                }).await;

                if let Err(e) = result {
                    eprintln!("[hello_server] spawn_blocking join 错误 peer={peer}: {e}");
                }
                conn_counter.fetch_sub(1, Ordering::Relaxed);
            });
        }
    });

    ExitCode::SUCCESS
}