diff --git a/src/http3/uvcpp_h3_wt_session.cpp b/src/http3/uvcpp_h3_wt_session.cpp index 2459165..454e6fa 100644 --- a/src/http3/uvcpp_h3_wt_session.cpp +++ b/src/http3/uvcpp_h3_wt_session.cpp @@ -165,6 +165,13 @@ std::unique_ptr uvcpp_h3_wt_session::accept( raw->on_capsule_data(d, n); }, [raw]() { raw->on_capsule_end(); }); + // 服务端在 `200` 落进会话流的那一刻就算建立(draft 的服务端侧没有 "2xx 已 + // 送达" 这一拍),而 `on_open` 是应用拿到会话的唯一时机:流的落点、datagram + // 的分发都要在这个回调之后才被应用接上。客户端那条路在 + // `on_connect_response()` 里做的正是这一句 —— 服务端漏了它,会话虽然建得出来, + // 应用却永远接不上。 + std::function open_cb = raw->cbs_.on_open; + if (open_cb) open_cb(*raw); return s; } diff --git a/src/http3/uvcpp_h3_wt_session.h b/src/http3/uvcpp_h3_wt_session.h index 243b341..191a130 100644 --- a/src/http3/uvcpp_h3_wt_session.h +++ b/src/http3/uvcpp_h3_wt_session.h @@ -134,8 +134,9 @@ class UVCPP_API uvcpp_h3_wt_session { /** * @brief 会话**真正可用**了。**恰好一次。** * - * 服务端:`accept()` 发完 2xx 之后;客户端:收到 2xx 响应之后(`connect()` - * 之后先排队,见 `is_pending()`)。 + * 服务端:`accept()` 发完 2xx 之后、**返回之前**(应用此时还拿不到 + * `accept()` 的返回值,只能靠回调参数接上会话);客户端:收到 2xx 响应之后 + * (`connect()` 之后先排队,见 `is_pending()`)。 */ std::function on_open; /// 收到 `WT_DRAIN_SESSION`(只是通知,会话仍然可用)。 diff --git a/tests/functional/http3_webtransport_func.cpp b/tests/functional/http3_webtransport_func.cpp index 497d056..5827527 100644 --- a/tests/functional/http3_webtransport_func.cpp +++ b/tests/functional/http3_webtransport_func.cpp @@ -78,6 +78,7 @@ void test_webtransport() { std::unique_ptr srv_h3; std::unique_ptr srv_wt; bool server_accepted = false; + int srv_open_count = 0; bool srv_drain_seen = false; bool srv_bidi_end = false; std::string srv_bidi_got; @@ -105,6 +106,13 @@ void test_webtransport() { return; } uvcpp_h3_wt_session::callbacks wcb; + // 服务端只有这一个时机能拿到会话:`accept()` 的返回值要等它返回之后 + // 才有。所以这里必须触发,否则应用根本接不上(流的落点、datagram 的 + // 分发都在这之后才成立)。 + wcb.on_open = [&](uvcpp_h3_wt_session&) { + ++srv_open_count; + check(!server_accepted, "服务端 on_open 先于 accept() 返回"); + }; wcb.on_stream = [&](uvcpp_h3_wt_session&, uvcpp_h3_wt_stream& s, bool bidi) { if (bidi) { uvcpp_h3_wt_stream* sp = &s; @@ -206,6 +214,8 @@ void test_webtransport() { check(uvcpp_test::wait_until(&loop, [&] { return server_accepted; }, kDeadlineMs), "服务端接受了会话"); + check(srv_open_count == 1, "服务端 on_open 恰好触发一次(实际 " + + std::to_string(srv_open_count) + ")"); if (early) { std::string got; early->on_data([&](const uint8_t* d, size_t n) {