@@ -45,6 +45,7 @@ namespace libp2p::transport::lsquic {
4545
4646 lsquic_engine_settings settings{};
4747 lsquic_engine_init_settings (&settings, flags);
48+ settings.es_versions = 1 << LSQVER_I001;
4849 settings.es_init_max_stream_data_bidi_remote =
4950 mux_config.maximum_window_size ;
5051 settings.es_init_max_stream_data_bidi_local =
@@ -58,10 +59,10 @@ namespace libp2p::transport::lsquic {
5859
5960 static lsquic_stream_if stream_if{};
6061 stream_if.on_new_conn = +[](void *void_self, lsquic_conn_t *conn) {
61- auto self = static_cast <Engine *>(void_self);
62+ auto * self = static_cast <Engine *>(void_self);
6263 auto op = qtils::optionTake (self->connecting_ );
6364 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
64- auto conn_ctx = new ConnCtx{self, conn, std::move (op)};
65+ auto * conn_ctx = new ConnCtx{self, conn, std::move (op)};
6566 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
6667 auto _conn_ctx = reinterpret_cast <lsquic_conn_ctx_t *>(conn_ctx);
6768 lsquic_conn_set_ctx (conn, _conn_ctx);
@@ -72,7 +73,7 @@ namespace libp2p::transport::lsquic {
7273 };
7374 stream_if.on_conn_closed = +[](lsquic_conn_t *conn) {
7475 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
75- auto conn_ctx = reinterpret_cast <ConnCtx *>(lsquic_conn_get_ctx (conn));
76+ auto * conn_ctx = reinterpret_cast <ConnCtx *>(lsquic_conn_get_ctx (conn));
7677 if (auto op = qtils::optionTake (conn_ctx->connecting )) {
7778 op->cb (QuicError::CONN_CLOSED);
7879 }
@@ -85,7 +86,7 @@ namespace libp2p::transport::lsquic {
8586 };
8687 stream_if.on_hsk_done = +[](lsquic_conn_t *conn, lsquic_hsk_status status) {
8788 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
88- auto conn_ctx = reinterpret_cast <ConnCtx *>(lsquic_conn_get_ctx (conn));
89+ auto * conn_ctx = reinterpret_cast <ConnCtx *>(lsquic_conn_get_ctx (conn));
8990 auto self = conn_ctx->engine ;
9091 auto ok = status == LSQ_HSK_OK or status == LSQ_HSK_RESUMED_OK;
9192 auto op = qtils::optionTake (conn_ctx->connecting );
@@ -122,12 +123,12 @@ namespace libp2p::transport::lsquic {
122123 }
123124 };
124125 stream_if.on_new_stream = +[](void *void_self, lsquic_stream_t *stream) {
125- auto self = static_cast <Engine *>(void_self);
126+ auto * self = static_cast <Engine *>(void_self);
126127 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
127- auto conn_ctx = reinterpret_cast <ConnCtx *>(
128+ auto * conn_ctx = reinterpret_cast <ConnCtx *>(
128129 lsquic_conn_get_ctx (lsquic_stream_conn (stream)));
129130 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
130- auto stream_ctx = new StreamCtx{self, stream};
131+ auto * stream_ctx = new StreamCtx{self, stream};
131132 if (auto conn = conn_ctx->conn .lock ()) {
132133 auto stream = std::make_shared<QuicStream>(
133134 conn, stream_ctx, conn_ctx->new_stream .has_value ());
@@ -146,29 +147,36 @@ namespace libp2p::transport::lsquic {
146147 stream_if.on_close =
147148 +[](lsquic_stream_t *stream, lsquic_stream_ctx_t *_stream_ctx) {
148149 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
149- auto stream_ctx = reinterpret_cast <StreamCtx *>(_stream_ctx);
150- if (auto op = qtils::optionTake (stream_ctx->reading )) {
151- op->cb (QuicError::STREAM_CLOSED);
152- }
150+ auto *stream_ctx = reinterpret_cast <StreamCtx *>(_stream_ctx);
153151 if (auto stream = stream_ctx->stream .lock ()) {
154152 stream->onClose ();
155153 }
154+ if (auto reading = qtils::optionTake (stream_ctx->reading )) {
155+ reading.value ()();
156+ }
157+ if (auto writing = qtils::optionTake (stream_ctx->writing )) {
158+ writing.value ()();
159+ }
156160 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
157161 delete stream_ctx;
158162 };
159163 stream_if.on_read =
160164 +[](lsquic_stream_t *stream, lsquic_stream_ctx_t *_stream_ctx) {
161165 lsquic_stream_wantread (stream, 0 );
162166 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
163- auto stream_ctx = reinterpret_cast <StreamCtx *>(_stream_ctx);
164- auto op = qtils::optionTake (stream_ctx->reading ).value ();
165- auto n = lsquic_stream_read (stream, op.out .data (), op.out .size ());
166- outcome::result<size_t > r = QuicError::STREAM_CLOSED;
167- if (n > 0 ) {
168- r = n;
167+ auto *stream_ctx = reinterpret_cast <StreamCtx *>(_stream_ctx);
168+ if (auto reading = qtils::optionTake (stream_ctx->reading )) {
169+ reading.value ()();
170+ }
171+ };
172+ stream_if.on_write =
173+ +[](lsquic_stream_t *stream, lsquic_stream_ctx_t *_stream_ctx) {
174+ lsquic_stream_wantwrite (stream, 0 );
175+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
176+ auto *stream_ctx = reinterpret_cast <StreamCtx *>(_stream_ctx);
177+ if (auto writing = qtils::optionTake (stream_ctx->writing )) {
178+ writing.value ()();
169179 }
170- post (*stream_ctx->engine ->io_context_ ,
171- [cb{std::move (op.cb )}, r] { cb (r); });
172180 };
173181
174182 lsquic_engine_api api{};
@@ -179,7 +187,7 @@ namespace libp2p::transport::lsquic {
179187 api.ea_packets_out = +[](void *void_self,
180188 const lsquic_out_spec *out_spec,
181189 unsigned n_packets_out) {
182- auto self = static_cast <Engine *>(void_self);
190+ auto * self = static_cast <Engine *>(void_self);
183191 // https://github.com/cbodley/nexus/blob/d1d8486f713fd089917331239d755932c7c8ed8e/src/socket.cc#L218
184192 int r = 0 ;
185193 for (auto &spec : std::span{out_spec, n_packets_out}) {
@@ -216,7 +224,7 @@ namespace libp2p::transport::lsquic {
216224 };
217225 api.ea_packets_out_ctx = this ;
218226 api.ea_get_ssl_ctx = +[](void *void_self, const sockaddr *) {
219- auto self = static_cast <Engine *>(void_self);
227+ auto * self = static_cast <Engine *>(void_self);
220228 return self->ssl_context_ ->native_handle ();
221229 };
222230
@@ -261,7 +269,7 @@ namespace libp2p::transport::lsquic {
261269 if (auto op = qtils::optionTake (connecting_)) {
262270 op->cb (QuicError::CANT_CREATE_CONNECTION);
263271 }
264- process ();
272+ wantProcess ();
265273 }
266274
267275 outcome::result<std::shared_ptr<QuicStream>> Engine::newStream (
@@ -281,7 +289,47 @@ namespace libp2p::transport::lsquic {
281289 return stream;
282290 }
283291
292+ void Engine::wantProcess () {
293+ if (want_process_) {
294+ return ;
295+ }
296+ want_process_ = true ;
297+ boost::asio::post (*io_context_, [weak_self{weak_from_this ()}] {
298+ if (auto self = weak_self.lock ()) {
299+ self->process ();
300+ }
301+ });
302+ }
303+
304+ void Engine::wantFlush (StreamCtx *stream_ctx) {
305+ if (stream_ctx->want_flush ) {
306+ return ;
307+ }
308+ stream_ctx->want_flush = true ;
309+ if (stream_ctx->stream .expired ()) {
310+ return ;
311+ }
312+ want_flush_.emplace_back (stream_ctx->stream );
313+ wantProcess ();
314+ }
315+
284316 void Engine::process () {
317+ want_process_ = false ;
318+ auto want_flush = std::exchange (want_flush_, {});
319+ for (auto &weak_stream : want_flush) {
320+ auto stream = weak_stream.lock ();
321+ if (not stream) {
322+ continue ;
323+ }
324+ if (stream->stream_ctx_ == nullptr ) {
325+ continue ;
326+ }
327+ if (stream->stream_ctx_ ->ls_stream == nullptr ) {
328+ continue ;
329+ }
330+ stream->stream_ctx_ ->want_flush = false ;
331+ lsquic_stream_flush (stream->stream_ctx_ ->ls_stream );
332+ }
285333 lsquic_engine_process_conns (engine_);
286334 int us = 0 ;
287335 if (not lsquic_engine_earliest_adv_tick (engine_, &us)) {
0 commit comments