deploy: a2254973e64991a79f8210d1b919ed3f74b319d8

This commit is contained in:
flub
2026-03-27 11:59:52 +00:00
parent d1b6531810
commit 8b4448c19c
44 changed files with 6326 additions and 6294 deletions
+1 -1
View File
@@ -1 +1 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Documentation for Rustdoc"><title>Help</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2"href="./static.files/${f}">`).join(""))</script><link rel="stylesheet" href="./static.files/normalize-9960930a.css"><link rel="stylesheet" href="./static.files/rustdoc-ca0dd0c4.css"><meta name="rustdoc-vars" data-root-path="./" data-static-root-path="./static.files/" data-current-crate="certificate" data-themes="" data-resource-suffix="" data-rustdoc-version="1.92.0-nightly (b6f0945e4 2025-10-08)" data-channel="nightly" data-search-js="search-8d3311b9.js" data-stringdex-js="stringdex-828709d0.js" data-settings-js="settings-c38705f0.js" ><script src="./static.files/storage-e2aeef58.js"></script><script defer src="./static.files/main-ce535bd0.js"></script><noscript><link rel="stylesheet" href="./static.files/noscript-263c88ec.css"></noscript><link rel="alternate icon" type="image/png" href="./static.files/favicon-32x32-eab170b8.png"><link rel="icon" type="image/svg+xml" href="./static.files/favicon-044be391.svg"></head><body class="rustdoc mod sys"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><rustdoc-topbar><h2><a href="#">All</a></h2></rustdoc-topbar><nav class="sidebar"><div class="sidebar-crate"><a class="logo-container" href="./index.html"><img class="rust-logo" src="./static.files/rust-logo-9a9549ea.svg" alt="logo"></a><h2><a href="./index.html">Rustdoc</a><span class="version">1.92.0-nightly</span></h2></div><div class="version">(b6f0945e4 2025-10-08)</div><h2 class="location">Help</h2><div class="sidebar-elems"></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><section id="main-content" class="content"><div class="main-heading"><h1>Rustdoc help</h1><span class="out-of-band"><a id="back" href="javascript:void(0)" onclick="history.back();">Back</a></span></div><noscript><section><p>You need to enable JavaScript to use keyboard commands or search.</p><p>For more information, browse the <a href="https://doc.rust-lang.org/nightly/rustdoc/">rustdoc handbook</a>.</p></section></noscript></section></div></main></body></html>
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Documentation for Rustdoc"><title>Help</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2"href="./static.files/${f}">`).join(""))</script><link rel="stylesheet" href="./static.files/normalize-9960930a.css"><link rel="stylesheet" href="./static.files/rustdoc-ca0dd0c4.css"><meta name="rustdoc-vars" data-root-path="./" data-static-root-path="./static.files/" data-current-crate="noq_perf" data-themes="" data-resource-suffix="" data-rustdoc-version="1.92.0-nightly (b6f0945e4 2025-10-08)" data-channel="nightly" data-search-js="search-8d3311b9.js" data-stringdex-js="stringdex-828709d0.js" data-settings-js="settings-c38705f0.js" ><script src="./static.files/storage-e2aeef58.js"></script><script defer src="./static.files/main-ce535bd0.js"></script><noscript><link rel="stylesheet" href="./static.files/noscript-263c88ec.css"></noscript><link rel="alternate icon" type="image/png" href="./static.files/favicon-32x32-eab170b8.png"><link rel="icon" type="image/svg+xml" href="./static.files/favicon-044be391.svg"></head><body class="rustdoc mod sys"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><rustdoc-topbar><h2><a href="#">All</a></h2></rustdoc-topbar><nav class="sidebar"><div class="sidebar-crate"><a class="logo-container" href="./index.html"><img class="rust-logo" src="./static.files/rust-logo-9a9549ea.svg" alt="logo"></a><h2><a href="./index.html">Rustdoc</a><span class="version">1.92.0-nightly</span></h2></div><div class="version">(b6f0945e4 2025-10-08)</div><h2 class="location">Help</h2><div class="sidebar-elems"></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><section id="main-content" class="content"><div class="main-heading"><h1>Rustdoc help</h1><span class="out-of-band"><a id="back" href="javascript:void(0)" onclick="history.back();">Back</a></span></div><noscript><section><p>You need to enable JavaScript to use keyboard commands or search.</p><p>For more information, browse the <a href="https://doc.rust-lang.org/nightly/rustdoc/">rustdoc handbook</a>.</p></section></noscript></section></div></main></body></html>
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -1,4 +1,4 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Hints when the caller identifies a network change."><title>NetworkChangeHint in noq - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2"href="../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../static.files/rustdoc-ca0dd0c4.css"><meta name="rustdoc-vars" data-root-path="../" data-static-root-path="../static.files/" data-current-crate="noq" data-themes="" data-resource-suffix="" data-rustdoc-version="1.92.0-nightly (b6f0945e4 2025-10-08)" data-channel="nightly" data-search-js="search-8d3311b9.js" data-stringdex-js="stringdex-828709d0.js" data-settings-js="settings-c38705f0.js" ><script src="../static.files/storage-e2aeef58.js"></script><script defer src="sidebar-items.js"></script><script defer src="../static.files/main-ce535bd0.js"></script><noscript><link rel="stylesheet" href="../static.files/noscript-263c88ec.css"></noscript><link rel="alternate icon" type="image/png" href="../static.files/favicon-32x32-eab170b8.png"><link rel="icon" type="image/svg+xml" href="../static.files/favicon-044be391.svg"></head><body class="rustdoc trait"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><rustdoc-topbar><h2><a href="#">NetworkChangeHint</a></h2></rustdoc-topbar><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../noq/index.html">noq</a><span class="version">0.17.0</span></h2></div><div class="sidebar-elems"><section id="rustdoc-toc"><h2 class="location"><a href="#">Network<wbr>Change<wbr>Hint</a></h2><h3><a href="#required-methods">Required Methods</a></h3><ul class="block"><li><a href="#tymethod.is_path_recoverable" title="is_path_recoverable">is_path_recoverable</a></li></ul><h3><a href="#implementors">Implementors</a></h3></section><div id="rustdoc-modnav"><h2 class="in-crate"><a href="index.html">In crate noq</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="index.html">noq</a></div><h1>Trait <span class="trait">Network<wbr>Change<wbr>Hint</span>&nbsp;<button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../src/noq_proto/connection/mod.rs.html#7003">Source</a> </span></div><pre class="rust item-decl"><code>pub trait NetworkChangeHint: <a class="trait" href="https://doc.rust-lang.org/nightly/core/fmt/trait.Debug.html" title="trait core::fmt::Debug">Debug</a> + 'static {
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Hints when the caller identifies a network change."><title>NetworkChangeHint in noq - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2"href="../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../static.files/rustdoc-ca0dd0c4.css"><meta name="rustdoc-vars" data-root-path="../" data-static-root-path="../static.files/" data-current-crate="noq" data-themes="" data-resource-suffix="" data-rustdoc-version="1.92.0-nightly (b6f0945e4 2025-10-08)" data-channel="nightly" data-search-js="search-8d3311b9.js" data-stringdex-js="stringdex-828709d0.js" data-settings-js="settings-c38705f0.js" ><script src="../static.files/storage-e2aeef58.js"></script><script defer src="sidebar-items.js"></script><script defer src="../static.files/main-ce535bd0.js"></script><noscript><link rel="stylesheet" href="../static.files/noscript-263c88ec.css"></noscript><link rel="alternate icon" type="image/png" href="../static.files/favicon-32x32-eab170b8.png"><link rel="icon" type="image/svg+xml" href="../static.files/favicon-044be391.svg"></head><body class="rustdoc trait"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><rustdoc-topbar><h2><a href="#">NetworkChangeHint</a></h2></rustdoc-topbar><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../noq/index.html">noq</a><span class="version">0.17.0</span></h2></div><div class="sidebar-elems"><section id="rustdoc-toc"><h2 class="location"><a href="#">Network<wbr>Change<wbr>Hint</a></h2><h3><a href="#required-methods">Required Methods</a></h3><ul class="block"><li><a href="#tymethod.is_path_recoverable" title="is_path_recoverable">is_path_recoverable</a></li></ul><h3><a href="#implementors">Implementors</a></h3></section><div id="rustdoc-modnav"><h2 class="in-crate"><a href="index.html">In crate noq</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="index.html">noq</a></div><h1>Trait <span class="trait">Network<wbr>Change<wbr>Hint</span>&nbsp;<button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../src/noq_proto/connection/mod.rs.html#7006">Source</a> </span></div><pre class="rust item-decl"><code>pub trait NetworkChangeHint: <a class="trait" href="https://doc.rust-lang.org/nightly/core/fmt/trait.Debug.html" title="trait core::fmt::Debug">Debug</a> + 'static {
// Required method
fn <a href="#tymethod.is_path_recoverable" class="fn">is_path_recoverable</a>(
&amp;self,
@@ -6,7 +6,7 @@
network_path: <a class="struct" href="../noq_proto/struct.FourTuple.html" title="struct noq_proto::FourTuple">FourTuple</a>,
) -&gt; <a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.bool.html">bool</a>;
}</code></pre><details class="toggle top-doc" open><summary class="hideme"><span>Expand description</span></summary><div class="docblock"><p>Hints when the caller identifies a network change.</p>
</div></details><h2 id="required-methods" class="section-header">Required Methods<a href="#required-methods" class="anchor">§</a></h2><div class="methods"><details class="toggle method-toggle" open><summary><section id="tymethod.is_path_recoverable" class="method"><a class="src rightside" href="../src/noq_proto/connection/mod.rs.html#7012">Source</a><h4 class="code-header">fn <a href="#tymethod.is_path_recoverable" class="fn">is_path_recoverable</a>(&amp;self, path_id: <a class="struct" href="struct.PathId.html" title="struct noq::PathId">PathId</a>, network_path: <a class="struct" href="../noq_proto/struct.FourTuple.html" title="struct noq_proto::FourTuple">FourTuple</a>) -&gt; <a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.bool.html">bool</a></h4></section></summary><div class="docblock"><p>Inform the connection if a path may recover after a network change.</p>
</div></details><h2 id="required-methods" class="section-header">Required Methods<a href="#required-methods" class="anchor">§</a></h2><div class="methods"><details class="toggle method-toggle" open><summary><section id="tymethod.is_path_recoverable" class="method"><a class="src rightside" href="../src/noq_proto/connection/mod.rs.html#7015">Source</a><h4 class="code-header">fn <a href="#tymethod.is_path_recoverable" class="fn">is_path_recoverable</a>(&amp;self, path_id: <a class="struct" href="struct.PathId.html" title="struct noq::PathId">PathId</a>, network_path: <a class="struct" href="../noq_proto/struct.FourTuple.html" title="struct noq_proto::FourTuple">FourTuple</a>) -&gt; <a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.bool.html">bool</a></h4></section></summary><div class="docblock"><p>Inform the connection if a path may recover after a network change.</p>
<p>After network changes, paths may not be recoverable. In this case, waiting for the path to
become idle may take longer than what is desirable. If <a href="trait.NetworkChangeHint.html#tymethod.is_path_recoverable" title="method noq_proto::connection::NetworkChangeHint::is_path_recoverable::is_path_recoverable"><code>Self::is_path_recoverable</code></a>
returns <code>false</code>, a multipath-enabled, client-side connection will establish a new path to
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+9 -9
View File
@@ -33,7 +33,7 @@ increasing time. Specifically, calling <a href="struct.Connection.html#method.ha
with events of the same <a href="https://doc.rust-lang.org/nightly/std/time/struct.Instant.html" title="struct std::time::Instant"><code>Instant</code></a> may be interleaved in any order with a
call to <a href="struct.Connection.html#method.handle_event" title="method noq_proto::Connection::handle_event"><code>handle_event</code></a> at that same instant; however
events or timeouts with different instants must not be interleaved.</p>
</div></details><h2 id="implementations" class="section-header">Implementations<a href="#implementations" class="anchor">§</a></h2><div id="implementations-list"><details class="toggle implementors-toggle" open><summary><section id="impl-Connection" class="impl"><a class="src rightside" href="../src/noq_proto/connection/mod.rs.html#322-6992">Source</a><a href="#impl-Connection" class="anchor">§</a><h3 class="code-header">impl <a class="struct" href="struct.Connection.html" title="struct noq_proto::Connection">Connection</a></h3></section></summary><div class="impl-items"><details class="toggle method-toggle" open><summary><section id="method.poll_timeout" class="method"><a class="src rightside" href="../src/noq_proto/connection/mod.rs.html#464-466">Source</a><h4 class="code-header">pub fn <a href="#method.poll_timeout" class="fn">poll_timeout</a>(&amp;mut self) -&gt; <a class="enum" href="https://doc.rust-lang.org/nightly/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="https://doc.rust-lang.org/nightly/std/time/struct.Instant.html" title="struct std::time::Instant">Instant</a>&gt;</h4></section></summary><div class="docblock"><p>Returns the next time at which <code>handle_timeout</code> should be called</p>
</div></details><h2 id="implementations" class="section-header">Implementations<a href="#implementations" class="anchor">§</a></h2><div id="implementations-list"><details class="toggle implementors-toggle" open><summary><section id="impl-Connection" class="impl"><a class="src rightside" href="../src/noq_proto/connection/mod.rs.html#322-6995">Source</a><a href="#impl-Connection" class="anchor">§</a><h3 class="code-header">impl <a class="struct" href="struct.Connection.html" title="struct noq_proto::Connection">Connection</a></h3></section></summary><div class="impl-items"><details class="toggle method-toggle" open><summary><section id="method.poll_timeout" class="method"><a class="src rightside" href="../src/noq_proto/connection/mod.rs.html#464-466">Source</a><h4 class="code-header">pub fn <a href="#method.poll_timeout" class="fn">poll_timeout</a>(&amp;mut self) -&gt; <a class="enum" href="https://doc.rust-lang.org/nightly/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="https://doc.rust-lang.org/nightly/std/time/struct.Instant.html" title="struct std::time::Instant">Instant</a>&gt;</h4></section></summary><div class="docblock"><p>Returns the next time at which <code>handle_timeout</code> should be called</p>
<p>The value returned may change after:</p>
<ul>
<li>the application performed some I/O on the connection</li>
@@ -197,7 +197,7 @@ decrement by one for each time a remotely initiated stream of matching direction
</div></details><details class="toggle method-toggle" open><summary><section id="method.is_multipath_negotiated" class="method"><a class="src rightside" href="../src/noq_proto/connection/mod.rs.html#2760-2764">Source</a><h4 class="code-header">pub fn <a href="#method.is_multipath_negotiated" class="fn">is_multipath_negotiated</a>(&amp;self) -&gt; <a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.bool.html">bool</a></h4></section></summary><div class="docblock"><p>Whether the Multipath for QUIC extension is enabled.</p>
<p>Multipath is only enabled after the handshake is completed and if it was enabled by both
peers.</p>
</div></details><details class="toggle method-toggle" open><summary><section id="method.handle_network_change" class="method"><a class="src rightside" href="../src/noq_proto/connection/mod.rs.html#5488-5624">Source</a><h4 class="code-header">pub fn <a href="#method.handle_network_change" class="fn">handle_network_change</a>(
</div></details><details class="toggle method-toggle" open><summary><section id="method.handle_network_change" class="method"><a class="src rightside" href="../src/noq_proto/connection/mod.rs.html#5491-5627">Source</a><h4 class="code-header">pub fn <a href="#method.handle_network_change" class="fn">handle_network_change</a>(
&amp;mut self,
hint: <a class="enum" href="https://doc.rust-lang.org/nightly/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;&amp;dyn <a class="trait" href="trait.NetworkChangeHint.html" title="trait noq_proto::NetworkChangeHint">NetworkChangeHint</a>&gt;,
now: <a class="struct" href="https://doc.rust-lang.org/nightly/std/time/struct.Instant.html" title="struct std::time::Instant">Instant</a>,
@@ -212,26 +212,26 @@ paths as non recoverable when necessary accelerates connectivity re-establishmen
allow it altogether.</p>
<p>The optional <code>hint</code> allows callers to indicate when paths are non-recoverable and should be
migrated to new a <a href="struct.PathId.html" title="struct noq_proto::PathId"><code>PathId</code></a>.</p>
</div></details><details class="toggle method-toggle" open><summary><section id="method.current_mtu" class="method"><a class="src rightside" href="../src/noq_proto/connection/mod.rs.html#6685-6692">Source</a><h4 class="code-header">pub fn <a href="#method.current_mtu" class="fn">current_mtu</a>(&amp;self) -&gt; <a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.u16.html">u16</a></h4></section></summary><div class="docblock"><p>Storage size required for the largest packet that can be transmitted on all currently
</div></details><details class="toggle method-toggle" open><summary><section id="method.current_mtu" class="method"><a class="src rightside" href="../src/noq_proto/connection/mod.rs.html#6688-6695">Source</a><h4 class="code-header">pub fn <a href="#method.current_mtu" class="fn">current_mtu</a>(&amp;self) -&gt; <a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.u16.html">u16</a></h4></section></summary><div class="docblock"><p>Storage size required for the largest packet that can be transmitted on all currently
available paths</p>
<p>Buffers passed to <a href="struct.Connection.html#method.poll_transmit" title="method noq_proto::Connection::poll_transmit"><code>Connection::poll_transmit</code></a> should be at least this large.</p>
<p>When multipath is enabled, this value is the minimum MTU across all available paths.</p>
</div></details><details class="toggle method-toggle" open><summary><section id="method.add_nat_traversal_address" class="method"><a class="src rightside" href="../src/noq_proto/connection/mod.rs.html#6803-6811">Source</a><h4 class="code-header">pub fn <a href="#method.add_nat_traversal_address" class="fn">add_nat_traversal_address</a>(
</div></details><details class="toggle method-toggle" open><summary><section id="method.add_nat_traversal_address" class="method"><a class="src rightside" href="../src/noq_proto/connection/mod.rs.html#6806-6814">Source</a><h4 class="code-header">pub fn <a href="#method.add_nat_traversal_address" class="fn">add_nat_traversal_address</a>(
&amp;mut self,
address: <a class="enum" href="https://doc.rust-lang.org/nightly/core/net/socket_addr/enum.SocketAddr.html" title="enum core::net::socket_addr::SocketAddr">SocketAddr</a>,
) -&gt; <a class="enum" href="https://doc.rust-lang.org/nightly/core/result/enum.Result.html" title="enum core::result::Result">Result</a>&lt;<a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.unit.html">()</a>, <a class="enum" href="n0_nat_traversal/enum.Error.html" title="enum noq_proto::n0_nat_traversal::Error">Error</a>&gt;</h4></section></summary><div class="docblock"><p>Add addresses the local endpoint considers are reachable for nat traversal.</p>
</div></details><details class="toggle method-toggle" open><summary><section id="method.remove_nat_traversal_address" class="method"><a class="src rightside" href="../src/noq_proto/connection/mod.rs.html#6816-6827">Source</a><h4 class="code-header">pub fn <a href="#method.remove_nat_traversal_address" class="fn">remove_nat_traversal_address</a>(
</div></details><details class="toggle method-toggle" open><summary><section id="method.remove_nat_traversal_address" class="method"><a class="src rightside" href="../src/noq_proto/connection/mod.rs.html#6819-6830">Source</a><h4 class="code-header">pub fn <a href="#method.remove_nat_traversal_address" class="fn">remove_nat_traversal_address</a>(
&amp;mut self,
address: <a class="enum" href="https://doc.rust-lang.org/nightly/core/net/socket_addr/enum.SocketAddr.html" title="enum core::net::socket_addr::SocketAddr">SocketAddr</a>,
) -&gt; <a class="enum" href="https://doc.rust-lang.org/nightly/core/result/enum.Result.html" title="enum core::result::Result">Result</a>&lt;<a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.unit.html">()</a>, <a class="enum" href="n0_nat_traversal/enum.Error.html" title="enum noq_proto::n0_nat_traversal::Error">Error</a>&gt;</h4></section></summary><div class="docblock"><p>Removes an address the endpoing no longer considers reachable for nat traversal</p>
<p>Addresses not present in the set will be silently ignored.</p>
</div></details><details class="toggle method-toggle" open><summary><section id="method.get_local_nat_traversal_addresses" class="method"><a class="src rightside" href="../src/noq_proto/connection/mod.rs.html#6830-6834">Source</a><h4 class="code-header">pub fn <a href="#method.get_local_nat_traversal_addresses" class="fn">get_local_nat_traversal_addresses</a>(
</div></details><details class="toggle method-toggle" open><summary><section id="method.get_local_nat_traversal_addresses" class="method"><a class="src rightside" href="../src/noq_proto/connection/mod.rs.html#6833-6837">Source</a><h4 class="code-header">pub fn <a href="#method.get_local_nat_traversal_addresses" class="fn">get_local_nat_traversal_addresses</a>(
&amp;self,
) -&gt; <a class="enum" href="https://doc.rust-lang.org/nightly/core/result/enum.Result.html" title="enum core::result::Result">Result</a>&lt;<a class="struct" href="https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html" title="struct alloc::vec::Vec">Vec</a>&lt;<a class="enum" href="https://doc.rust-lang.org/nightly/core/net/socket_addr/enum.SocketAddr.html" title="enum core::net::socket_addr::SocketAddr">SocketAddr</a>&gt;, <a class="enum" href="n0_nat_traversal/enum.Error.html" title="enum noq_proto::n0_nat_traversal::Error">Error</a>&gt;</h4></section></summary><div class="docblock"><p>Get the current local nat traversal addresses</p>
</div></details><details class="toggle method-toggle" open><summary><section id="method.get_remote_nat_traversal_addresses" class="method"><a class="src rightside" href="../src/noq_proto/connection/mod.rs.html#6837-6844">Source</a><h4 class="code-header">pub fn <a href="#method.get_remote_nat_traversal_addresses" class="fn">get_remote_nat_traversal_addresses</a>(
</div></details><details class="toggle method-toggle" open><summary><section id="method.get_remote_nat_traversal_addresses" class="method"><a class="src rightside" href="../src/noq_proto/connection/mod.rs.html#6840-6847">Source</a><h4 class="code-header">pub fn <a href="#method.get_remote_nat_traversal_addresses" class="fn">get_remote_nat_traversal_addresses</a>(
&amp;self,
) -&gt; <a class="enum" href="https://doc.rust-lang.org/nightly/core/result/enum.Result.html" title="enum core::result::Result">Result</a>&lt;<a class="struct" href="https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html" title="struct alloc::vec::Vec">Vec</a>&lt;<a class="enum" href="https://doc.rust-lang.org/nightly/core/net/socket_addr/enum.SocketAddr.html" title="enum core::net::socket_addr::SocketAddr">SocketAddr</a>&gt;, <a class="enum" href="n0_nat_traversal/enum.Error.html" title="enum noq_proto::n0_nat_traversal::Error">Error</a>&gt;</h4></section></summary><div class="docblock"><p>Get the currently advertised nat traversal addresses by the server</p>
</div></details><details class="toggle method-toggle" open><summary><section id="method.initiate_nat_traversal_round" class="method"><a class="src rightside" href="../src/noq_proto/connection/mod.rs.html#6889-6968">Source</a><h4 class="code-header">pub fn <a href="#method.initiate_nat_traversal_round" class="fn">initiate_nat_traversal_round</a>(
</div></details><details class="toggle method-toggle" open><summary><section id="method.initiate_nat_traversal_round" class="method"><a class="src rightside" href="../src/noq_proto/connection/mod.rs.html#6892-6971">Source</a><h4 class="code-header">pub fn <a href="#method.initiate_nat_traversal_round" class="fn">initiate_nat_traversal_round</a>(
&amp;mut self,
now: <a class="struct" href="https://doc.rust-lang.org/nightly/std/time/struct.Instant.html" title="struct std::time::Instant">Instant</a>,
) -&gt; <a class="enum" href="https://doc.rust-lang.org/nightly/core/result/enum.Result.html" title="enum core::result::Result">Result</a>&lt;<a class="struct" href="https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html" title="struct alloc::vec::Vec">Vec</a>&lt;<a class="enum" href="https://doc.rust-lang.org/nightly/core/net/socket_addr/enum.SocketAddr.html" title="enum core::net::socket_addr::SocketAddr">SocketAddr</a>&gt;, <a class="enum" href="n0_nat_traversal/enum.Error.html" title="enum noq_proto::n0_nat_traversal::Error">Error</a>&gt;</h4></section></summary><div class="docblock"><p>Initiates a new nat traversal round</p>
@@ -241,7 +241,7 @@ initiated, the previous one is cancelled, and paths that have not been opened ar
<p>Returns the server addresses that are now being probed.
If addresses fail due to spurious errors, these might succeed later and not be returned in
this set.</p>
</div></details></div></details></div><h2 id="trait-implementations" class="section-header">Trait Implementations<a href="#trait-implementations" class="anchor">§</a></h2><div id="trait-implementations-list"><details class="toggle implementors-toggle" open><summary><section id="impl-Debug-for-Connection" class="impl"><a class="src rightside" href="../src/noq_proto/connection/mod.rs.html#6994-7000">Source</a><a href="#impl-Debug-for-Connection" class="anchor">§</a><h3 class="code-header">impl <a class="trait" href="https://doc.rust-lang.org/nightly/core/fmt/trait.Debug.html" title="trait core::fmt::Debug">Debug</a> for <a class="struct" href="struct.Connection.html" title="struct noq_proto::Connection">Connection</a></h3></section></summary><div class="impl-items"><details class="toggle method-toggle" open><summary><section id="method.fmt" class="method trait-impl"><a class="src rightside" href="../src/noq_proto/connection/mod.rs.html#6995-6999">Source</a><a href="#method.fmt" class="anchor">§</a><h4 class="code-header">fn <a href="https://doc.rust-lang.org/nightly/core/fmt/trait.Debug.html#tymethod.fmt" class="fn">fmt</a>(&amp;self, f: &amp;mut <a class="struct" href="https://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html" title="struct core::fmt::Formatter">Formatter</a>&lt;'_&gt;) -&gt; <a class="type" href="https://doc.rust-lang.org/nightly/core/fmt/type.Result.html" title="type core::fmt::Result">Result</a></h4></section></summary><div class='docblock'>Formats the value using the given formatter. <a href="https://doc.rust-lang.org/nightly/core/fmt/trait.Debug.html#tymethod.fmt">Read more</a></div></details></div></details></div><h2 id="synthetic-implementations" class="section-header">Auto Trait Implementations<a href="#synthetic-implementations" class="anchor">§</a></h2><div id="synthetic-implementations-list"><section id="impl-Freeze-for-Connection" class="impl"><a href="#impl-Freeze-for-Connection" class="anchor">§</a><h3 class="code-header">impl !<a class="trait" href="https://doc.rust-lang.org/nightly/core/marker/trait.Freeze.html" title="trait core::marker::Freeze">Freeze</a> for <a class="struct" href="struct.Connection.html" title="struct noq_proto::Connection">Connection</a></h3></section><section id="impl-RefUnwindSafe-for-Connection" class="impl"><a href="#impl-RefUnwindSafe-for-Connection" class="anchor">§</a><h3 class="code-header">impl !<a class="trait" href="https://doc.rust-lang.org/nightly/core/panic/unwind_safe/trait.RefUnwindSafe.html" title="trait core::panic::unwind_safe::RefUnwindSafe">RefUnwindSafe</a> for <a class="struct" href="struct.Connection.html" title="struct noq_proto::Connection">Connection</a></h3></section><section id="impl-Send-for-Connection" class="impl"><a href="#impl-Send-for-Connection" class="anchor">§</a><h3 class="code-header">impl <a class="trait" href="https://doc.rust-lang.org/nightly/core/marker/trait.Send.html" title="trait core::marker::Send">Send</a> for <a class="struct" href="struct.Connection.html" title="struct noq_proto::Connection">Connection</a></h3></section><section id="impl-Sync-for-Connection" class="impl"><a href="#impl-Sync-for-Connection" class="anchor">§</a><h3 class="code-header">impl <a class="trait" href="https://doc.rust-lang.org/nightly/core/marker/trait.Sync.html" title="trait core::marker::Sync">Sync</a> for <a class="struct" href="struct.Connection.html" title="struct noq_proto::Connection">Connection</a></h3></section><section id="impl-Unpin-for-Connection" class="impl"><a href="#impl-Unpin-for-Connection" class="anchor">§</a><h3 class="code-header">impl <a class="trait" href="https://doc.rust-lang.org/nightly/core/marker/trait.Unpin.html" title="trait core::marker::Unpin">Unpin</a> for <a class="struct" href="struct.Connection.html" title="struct noq_proto::Connection">Connection</a></h3></section><section id="impl-UnwindSafe-for-Connection" class="impl"><a href="#impl-UnwindSafe-for-Connection" class="anchor">§</a><h3 class="code-header">impl !<a class="trait" href="https://doc.rust-lang.org/nightly/core/panic/unwind_safe/trait.UnwindSafe.html" title="trait core::panic::unwind_safe::UnwindSafe">UnwindSafe</a> for <a class="struct" href="struct.Connection.html" title="struct noq_proto::Connection">Connection</a></h3></section></div><h2 id="blanket-implementations" class="section-header">Blanket Implementations<a href="#blanket-implementations" class="anchor">§</a></h2><div id="blanket-implementations-list"><details class="toggle implementors-toggle"><summary><section id="impl-Any-for-T" class="impl"><a class="src rightside" href="https://doc.rust-lang.org/nightly/src/core/any.rs.html#138">Source</a><a href="#impl-Any-for-T" class="anchor">§</a><h3 class="code-header">impl&lt;T&gt; <a class="trait" href="https://doc.rust-lang.org/nightly/core/any/trait.Any.html" title="trait core::any::Any">Any</a> for T<div class="where">where
</div></details></div></details></div><h2 id="trait-implementations" class="section-header">Trait Implementations<a href="#trait-implementations" class="anchor">§</a></h2><div id="trait-implementations-list"><details class="toggle implementors-toggle" open><summary><section id="impl-Debug-for-Connection" class="impl"><a class="src rightside" href="../src/noq_proto/connection/mod.rs.html#6997-7003">Source</a><a href="#impl-Debug-for-Connection" class="anchor">§</a><h3 class="code-header">impl <a class="trait" href="https://doc.rust-lang.org/nightly/core/fmt/trait.Debug.html" title="trait core::fmt::Debug">Debug</a> for <a class="struct" href="struct.Connection.html" title="struct noq_proto::Connection">Connection</a></h3></section></summary><div class="impl-items"><details class="toggle method-toggle" open><summary><section id="method.fmt" class="method trait-impl"><a class="src rightside" href="../src/noq_proto/connection/mod.rs.html#6998-7002">Source</a><a href="#method.fmt" class="anchor">§</a><h4 class="code-header">fn <a href="https://doc.rust-lang.org/nightly/core/fmt/trait.Debug.html#tymethod.fmt" class="fn">fmt</a>(&amp;self, f: &amp;mut <a class="struct" href="https://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html" title="struct core::fmt::Formatter">Formatter</a>&lt;'_&gt;) -&gt; <a class="type" href="https://doc.rust-lang.org/nightly/core/fmt/type.Result.html" title="type core::fmt::Result">Result</a></h4></section></summary><div class='docblock'>Formats the value using the given formatter. <a href="https://doc.rust-lang.org/nightly/core/fmt/trait.Debug.html#tymethod.fmt">Read more</a></div></details></div></details></div><h2 id="synthetic-implementations" class="section-header">Auto Trait Implementations<a href="#synthetic-implementations" class="anchor">§</a></h2><div id="synthetic-implementations-list"><section id="impl-Freeze-for-Connection" class="impl"><a href="#impl-Freeze-for-Connection" class="anchor">§</a><h3 class="code-header">impl !<a class="trait" href="https://doc.rust-lang.org/nightly/core/marker/trait.Freeze.html" title="trait core::marker::Freeze">Freeze</a> for <a class="struct" href="struct.Connection.html" title="struct noq_proto::Connection">Connection</a></h3></section><section id="impl-RefUnwindSafe-for-Connection" class="impl"><a href="#impl-RefUnwindSafe-for-Connection" class="anchor">§</a><h3 class="code-header">impl !<a class="trait" href="https://doc.rust-lang.org/nightly/core/panic/unwind_safe/trait.RefUnwindSafe.html" title="trait core::panic::unwind_safe::RefUnwindSafe">RefUnwindSafe</a> for <a class="struct" href="struct.Connection.html" title="struct noq_proto::Connection">Connection</a></h3></section><section id="impl-Send-for-Connection" class="impl"><a href="#impl-Send-for-Connection" class="anchor">§</a><h3 class="code-header">impl <a class="trait" href="https://doc.rust-lang.org/nightly/core/marker/trait.Send.html" title="trait core::marker::Send">Send</a> for <a class="struct" href="struct.Connection.html" title="struct noq_proto::Connection">Connection</a></h3></section><section id="impl-Sync-for-Connection" class="impl"><a href="#impl-Sync-for-Connection" class="anchor">§</a><h3 class="code-header">impl <a class="trait" href="https://doc.rust-lang.org/nightly/core/marker/trait.Sync.html" title="trait core::marker::Sync">Sync</a> for <a class="struct" href="struct.Connection.html" title="struct noq_proto::Connection">Connection</a></h3></section><section id="impl-Unpin-for-Connection" class="impl"><a href="#impl-Unpin-for-Connection" class="anchor">§</a><h3 class="code-header">impl <a class="trait" href="https://doc.rust-lang.org/nightly/core/marker/trait.Unpin.html" title="trait core::marker::Unpin">Unpin</a> for <a class="struct" href="struct.Connection.html" title="struct noq_proto::Connection">Connection</a></h3></section><section id="impl-UnwindSafe-for-Connection" class="impl"><a href="#impl-UnwindSafe-for-Connection" class="anchor">§</a><h3 class="code-header">impl !<a class="trait" href="https://doc.rust-lang.org/nightly/core/panic/unwind_safe/trait.UnwindSafe.html" title="trait core::panic::unwind_safe::UnwindSafe">UnwindSafe</a> for <a class="struct" href="struct.Connection.html" title="struct noq_proto::Connection">Connection</a></h3></section></div><h2 id="blanket-implementations" class="section-header">Blanket Implementations<a href="#blanket-implementations" class="anchor">§</a></h2><div id="blanket-implementations-list"><details class="toggle implementors-toggle"><summary><section id="impl-Any-for-T" class="impl"><a class="src rightside" href="https://doc.rust-lang.org/nightly/src/core/any.rs.html#138">Source</a><a href="#impl-Any-for-T" class="anchor">§</a><h3 class="code-header">impl&lt;T&gt; <a class="trait" href="https://doc.rust-lang.org/nightly/core/any/trait.Any.html" title="trait core::any::Any">Any</a> for T<div class="where">where
T: 'static + ?<a class="trait" href="https://doc.rust-lang.org/nightly/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a>,</div></h3></section></summary><div class="impl-items"><details class="toggle method-toggle" open><summary><section id="method.type_id" class="method trait-impl"><a class="src rightside" href="https://doc.rust-lang.org/nightly/src/core/any.rs.html#139">Source</a><a href="#method.type_id" class="anchor">§</a><h4 class="code-header">fn <a href="https://doc.rust-lang.org/nightly/core/any/trait.Any.html#tymethod.type_id" class="fn">type_id</a>(&amp;self) -&gt; <a class="struct" href="https://doc.rust-lang.org/nightly/core/any/struct.TypeId.html" title="struct core::any::TypeId">TypeId</a></h4></section></summary><div class='docblock'>Gets the <code>TypeId</code> of <code>self</code>. <a href="https://doc.rust-lang.org/nightly/core/any/trait.Any.html#tymethod.type_id">Read more</a></div></details></div></details><details class="toggle implementors-toggle"><summary><section id="impl-Borrow%3CT%3E-for-T" class="impl"><a class="src rightside" href="https://doc.rust-lang.org/nightly/src/core/borrow.rs.html#212">Source</a><a href="#impl-Borrow%3CT%3E-for-T" class="anchor">§</a><h3 class="code-header">impl&lt;T&gt; <a class="trait" href="https://doc.rust-lang.org/nightly/core/borrow/trait.Borrow.html" title="trait core::borrow::Borrow">Borrow</a>&lt;T&gt; for T<div class="where">where
T: ?<a class="trait" href="https://doc.rust-lang.org/nightly/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a>,</div></h3></section></summary><div class="impl-items"><details class="toggle method-toggle" open><summary><section id="method.borrow" class="method trait-impl"><a class="src rightside" href="https://doc.rust-lang.org/nightly/src/core/borrow.rs.html#214">Source</a><a href="#method.borrow" class="anchor">§</a><h4 class="code-header">fn <a href="https://doc.rust-lang.org/nightly/core/borrow/trait.Borrow.html#tymethod.borrow" class="fn">borrow</a>(&amp;self) -&gt; <a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.reference.html">&amp;T</a></h4></section></summary><div class='docblock'>Immutably borrows from an owned value. <a href="https://doc.rust-lang.org/nightly/core/borrow/trait.Borrow.html#tymethod.borrow">Read more</a></div></details></div></details><details class="toggle implementors-toggle"><summary><section id="impl-BorrowMut%3CT%3E-for-T" class="impl"><a class="src rightside" href="https://doc.rust-lang.org/nightly/src/core/borrow.rs.html#221">Source</a><a href="#impl-BorrowMut%3CT%3E-for-T" class="anchor">§</a><h3 class="code-header">impl&lt;T&gt; <a class="trait" href="https://doc.rust-lang.org/nightly/core/borrow/trait.BorrowMut.html" title="trait core::borrow::BorrowMut">BorrowMut</a>&lt;T&gt; for T<div class="where">where
T: ?<a class="trait" href="https://doc.rust-lang.org/nightly/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a>,</div></h3></section></summary><div class="impl-items"><details class="toggle method-toggle" open><summary><section id="method.borrow_mut" class="method trait-impl"><a class="src rightside" href="https://doc.rust-lang.org/nightly/src/core/borrow.rs.html#222">Source</a><a href="#method.borrow_mut" class="anchor">§</a><h4 class="code-header">fn <a href="https://doc.rust-lang.org/nightly/core/borrow/trait.BorrowMut.html#tymethod.borrow_mut" class="fn">borrow_mut</a>(&amp;mut self) -&gt; <a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.reference.html">&amp;mut T</a></h4></section></summary><div class='docblock'>Mutably borrows from an owned value. <a href="https://doc.rust-lang.org/nightly/core/borrow/trait.BorrowMut.html#tymethod.borrow_mut">Read more</a></div></details></div></details><details class="toggle implementors-toggle"><summary><section id="impl-From%3CT%3E-for-T" class="impl"><a class="src rightside" href="https://doc.rust-lang.org/nightly/src/core/convert/mod.rs.html#785">Source</a><a href="#impl-From%3CT%3E-for-T" class="anchor">§</a><h3 class="code-header">impl&lt;T&gt; <a class="trait" href="https://doc.rust-lang.org/nightly/core/convert/trait.From.html" title="trait core::convert::From">From</a>&lt;T&gt; for T</h3></section></summary><div class="impl-items"><details class="toggle method-toggle" open><summary><section id="method.from" class="method trait-impl"><a class="src rightside" href="https://doc.rust-lang.org/nightly/src/core/convert/mod.rs.html#788">Source</a><a href="#method.from" class="anchor">§</a><h4 class="code-header">fn <a href="https://doc.rust-lang.org/nightly/core/convert/trait.From.html#tymethod.from" class="fn">from</a>(t: T) -&gt; T</h4></section></summary><div class="docblock"><p>Returns the argument unchanged.</p>
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Hints when the caller identifies a network change."><title>NetworkChangeHint in noq_proto - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2"href="../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../static.files/rustdoc-ca0dd0c4.css"><meta name="rustdoc-vars" data-root-path="../" data-static-root-path="../static.files/" data-current-crate="noq_proto" data-themes="" data-resource-suffix="" data-rustdoc-version="1.92.0-nightly (b6f0945e4 2025-10-08)" data-channel="nightly" data-search-js="search-8d3311b9.js" data-stringdex-js="stringdex-828709d0.js" data-settings-js="settings-c38705f0.js" ><script src="../static.files/storage-e2aeef58.js"></script><script defer src="sidebar-items.js"></script><script defer src="../static.files/main-ce535bd0.js"></script><noscript><link rel="stylesheet" href="../static.files/noscript-263c88ec.css"></noscript><link rel="alternate icon" type="image/png" href="../static.files/favicon-32x32-eab170b8.png"><link rel="icon" type="image/svg+xml" href="../static.files/favicon-044be391.svg"></head><body class="rustdoc trait"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><rustdoc-topbar><h2><a href="#">NetworkChangeHint</a></h2></rustdoc-topbar><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../noq_proto/index.html">noq_<wbr>proto</a><span class="version">0.16.0</span></h2></div><div class="sidebar-elems"><section id="rustdoc-toc"><h2 class="location"><a href="#">Network<wbr>Change<wbr>Hint</a></h2><h3><a href="#required-methods">Required Methods</a></h3><ul class="block"><li><a href="#tymethod.is_path_recoverable" title="is_path_recoverable">is_path_recoverable</a></li></ul><h3><a href="#implementors">Implementors</a></h3></section><div id="rustdoc-modnav"><h2 class="in-crate"><a href="index.html">In crate noq_<wbr>proto</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="index.html">noq_proto</a></div><h1>Trait <span class="trait">Network<wbr>Change<wbr>Hint</span>&nbsp;<button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../src/noq_proto/connection/mod.rs.html#7003-7013">Source</a> </span></div><pre class="rust item-decl"><code>pub trait NetworkChangeHint: <a class="trait" href="https://doc.rust-lang.org/nightly/core/fmt/trait.Debug.html" title="trait core::fmt::Debug">Debug</a> + 'static {
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Hints when the caller identifies a network change."><title>NetworkChangeHint in noq_proto - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2"href="../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../static.files/rustdoc-ca0dd0c4.css"><meta name="rustdoc-vars" data-root-path="../" data-static-root-path="../static.files/" data-current-crate="noq_proto" data-themes="" data-resource-suffix="" data-rustdoc-version="1.92.0-nightly (b6f0945e4 2025-10-08)" data-channel="nightly" data-search-js="search-8d3311b9.js" data-stringdex-js="stringdex-828709d0.js" data-settings-js="settings-c38705f0.js" ><script src="../static.files/storage-e2aeef58.js"></script><script defer src="sidebar-items.js"></script><script defer src="../static.files/main-ce535bd0.js"></script><noscript><link rel="stylesheet" href="../static.files/noscript-263c88ec.css"></noscript><link rel="alternate icon" type="image/png" href="../static.files/favicon-32x32-eab170b8.png"><link rel="icon" type="image/svg+xml" href="../static.files/favicon-044be391.svg"></head><body class="rustdoc trait"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><rustdoc-topbar><h2><a href="#">NetworkChangeHint</a></h2></rustdoc-topbar><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../noq_proto/index.html">noq_<wbr>proto</a><span class="version">0.16.0</span></h2></div><div class="sidebar-elems"><section id="rustdoc-toc"><h2 class="location"><a href="#">Network<wbr>Change<wbr>Hint</a></h2><h3><a href="#required-methods">Required Methods</a></h3><ul class="block"><li><a href="#tymethod.is_path_recoverable" title="is_path_recoverable">is_path_recoverable</a></li></ul><h3><a href="#implementors">Implementors</a></h3></section><div id="rustdoc-modnav"><h2 class="in-crate"><a href="index.html">In crate noq_<wbr>proto</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="index.html">noq_proto</a></div><h1>Trait <span class="trait">Network<wbr>Change<wbr>Hint</span>&nbsp;<button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../src/noq_proto/connection/mod.rs.html#7006-7016">Source</a> </span></div><pre class="rust item-decl"><code>pub trait NetworkChangeHint: <a class="trait" href="https://doc.rust-lang.org/nightly/core/fmt/trait.Debug.html" title="trait core::fmt::Debug">Debug</a> + 'static {
// Required method
fn <a href="#tymethod.is_path_recoverable" class="fn">is_path_recoverable</a>(
&amp;self,
@@ -6,7 +6,7 @@
network_path: <a class="struct" href="struct.FourTuple.html" title="struct noq_proto::FourTuple">FourTuple</a>,
) -&gt; <a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.bool.html">bool</a>;
}</code></pre><details class="toggle top-doc" open><summary class="hideme"><span>Expand description</span></summary><div class="docblock"><p>Hints when the caller identifies a network change.</p>
</div></details><h2 id="required-methods" class="section-header">Required Methods<a href="#required-methods" class="anchor">§</a></h2><div class="methods"><details class="toggle method-toggle" open><summary><section id="tymethod.is_path_recoverable" class="method"><a class="src rightside" href="../src/noq_proto/connection/mod.rs.html#7012">Source</a><h4 class="code-header">fn <a href="#tymethod.is_path_recoverable" class="fn">is_path_recoverable</a>(&amp;self, path_id: <a class="struct" href="struct.PathId.html" title="struct noq_proto::PathId">PathId</a>, network_path: <a class="struct" href="struct.FourTuple.html" title="struct noq_proto::FourTuple">FourTuple</a>) -&gt; <a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.bool.html">bool</a></h4></section></summary><div class="docblock"><p>Inform the connection if a path may recover after a network change.</p>
</div></details><h2 id="required-methods" class="section-header">Required Methods<a href="#required-methods" class="anchor">§</a></h2><div class="methods"><details class="toggle method-toggle" open><summary><section id="tymethod.is_path_recoverable" class="method"><a class="src rightside" href="../src/noq_proto/connection/mod.rs.html#7015">Source</a><h4 class="code-header">fn <a href="#tymethod.is_path_recoverable" class="fn">is_path_recoverable</a>(&amp;self, path_id: <a class="struct" href="struct.PathId.html" title="struct noq_proto::PathId">PathId</a>, network_path: <a class="struct" href="struct.FourTuple.html" title="struct noq_proto::FourTuple">FourTuple</a>) -&gt; <a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.bool.html">bool</a></h4></section></summary><div class="docblock"><p>Inform the connection if a path may recover after a network change.</p>
<p>After network changes, paths may not be recoverable. In this case, waiting for the path to
become idle may take longer than what is desirable. If <a href="trait.NetworkChangeHint.html#tymethod.is_path_recoverable"><code>Self::is_path_recoverable</code></a>
returns <code>false</code>, a multipath-enabled, client-side connection will establish a new path to
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1 +1 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Settings of Rustdoc"><title>Settings</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2"href="./static.files/${f}">`).join(""))</script><link rel="stylesheet" href="./static.files/normalize-9960930a.css"><link rel="stylesheet" href="./static.files/rustdoc-ca0dd0c4.css"><meta name="rustdoc-vars" data-root-path="./" data-static-root-path="./static.files/" data-current-crate="certificate" data-themes="" data-resource-suffix="" data-rustdoc-version="1.92.0-nightly (b6f0945e4 2025-10-08)" data-channel="nightly" data-search-js="search-8d3311b9.js" data-stringdex-js="stringdex-828709d0.js" data-settings-js="settings-c38705f0.js" ><script src="./static.files/storage-e2aeef58.js"></script><script defer src="./static.files/main-ce535bd0.js"></script><noscript><link rel="stylesheet" href="./static.files/noscript-263c88ec.css"></noscript><link rel="alternate icon" type="image/png" href="./static.files/favicon-32x32-eab170b8.png"><link rel="icon" type="image/svg+xml" href="./static.files/favicon-044be391.svg"></head><body class="rustdoc mod sys"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><rustdoc-topbar><h2><a href="#">All</a></h2></rustdoc-topbar><nav class="sidebar"><div class="sidebar-crate"><a class="logo-container" href="./index.html"><img class="rust-logo" src="./static.files/rust-logo-9a9549ea.svg" alt="logo"></a><h2><a href="./index.html">Rustdoc</a><span class="version">1.92.0-nightly</span></h2></div><div class="version">(b6f0945e4 2025-10-08)</div><h2 class="location">Settings</h2><div class="sidebar-elems"></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><section id="main-content" class="content"><div class="main-heading"><h1>Rustdoc settings</h1><span class="out-of-band"><a id="back" href="javascript:void(0)" onclick="history.back();">Back</a></span></div><noscript><section>You need to enable JavaScript be able to update your settings.</section></noscript><script defer src="./static.files/settings-c38705f0.js"></script></section></div></main></body></html>
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Settings of Rustdoc"><title>Settings</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2"href="./static.files/${f}">`).join(""))</script><link rel="stylesheet" href="./static.files/normalize-9960930a.css"><link rel="stylesheet" href="./static.files/rustdoc-ca0dd0c4.css"><meta name="rustdoc-vars" data-root-path="./" data-static-root-path="./static.files/" data-current-crate="noq_perf" data-themes="" data-resource-suffix="" data-rustdoc-version="1.92.0-nightly (b6f0945e4 2025-10-08)" data-channel="nightly" data-search-js="search-8d3311b9.js" data-stringdex-js="stringdex-828709d0.js" data-settings-js="settings-c38705f0.js" ><script src="./static.files/storage-e2aeef58.js"></script><script defer src="./static.files/main-ce535bd0.js"></script><noscript><link rel="stylesheet" href="./static.files/noscript-263c88ec.css"></noscript><link rel="alternate icon" type="image/png" href="./static.files/favicon-32x32-eab170b8.png"><link rel="icon" type="image/svg+xml" href="./static.files/favicon-044be391.svg"></head><body class="rustdoc mod sys"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><rustdoc-topbar><h2><a href="#">All</a></h2></rustdoc-topbar><nav class="sidebar"><div class="sidebar-crate"><a class="logo-container" href="./index.html"><img class="rust-logo" src="./static.files/rust-logo-9a9549ea.svg" alt="logo"></a><h2><a href="./index.html">Rustdoc</a><span class="version">1.92.0-nightly</span></h2></div><div class="version">(b6f0945e4 2025-10-08)</div><h2 class="location">Settings</h2><div class="sidebar-elems"></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><section id="main-content" class="content"><div class="main-heading"><h1>Rustdoc settings</h1><span class="out-of-band"><a id="back" href="javascript:void(0)" onclick="history.back();">Back</a></span></div><noscript><section>You need to enable JavaScript be able to update your settings.</section></noscript><script defer src="./static.files/settings-c38705f0.js"></script></section></div></main></body></html>
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -110,7 +110,7 @@
<a href=#110 id=110 data-nosnippet>110</a>}
<a href=#111 id=111 data-nosnippet>111</a>
<a href=#112 id=112 data-nosnippet>112</a><span class="attr">#[cfg(feature = <span class="string">"lock_tracking"</span>)]
<a href=#113 id=113 data-nosnippet>113</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">use </span>tracking::Mutex;
<a href=#113 id=113 data-nosnippet>113</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">use </span>tracking::{Mutex, MutexGuard};
<a href=#114 id=114 data-nosnippet>114</a>
<a href=#115 id=115 data-nosnippet>115</a><span class="attr">#[cfg(not(feature = <span class="string">"lock_tracking"</span>))]
<a href=#116 id=116 data-nosnippet>116</a></span><span class="kw">mod </span>non_tracking {
@@ -160,4 +160,4 @@
<a href=#160 id=160 data-nosnippet>160</a>}
<a href=#161 id=161 data-nosnippet>161</a>
<a href=#162 id=162 data-nosnippet>162</a><span class="attr">#[cfg(not(feature = <span class="string">"lock_tracking"</span>))]
<a href=#163 id=163 data-nosnippet>163</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">use </span>non_tracking::Mutex;</code></pre></div></section></main></body></html>
<a href=#163 id=163 data-nosnippet>163</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">use </span>non_tracking::{Mutex, MutexGuard};</code></pre></div></section></main></body></html>
+286 -294
View File
@@ -118,305 +118,297 @@
<a href=#118 id=118 data-nosnippet>118</a><span class="kw">impl </span>Clone <span class="kw">for </span>Path {
<a href=#119 id=119 data-nosnippet>119</a> <span class="kw">fn </span>clone(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="self">Self </span>{
<a href=#120 id=120 data-nosnippet>120</a> <span class="self">self</span>.conn
<a href=#121 id=121 data-nosnippet>121</a> .state
<a href=#122 id=122 data-nosnippet>122</a> .lock(<span class="string">"Path::clone"</span>)
<a href=#123 id=123 data-nosnippet>123</a> .increment_path_refs(<span class="self">self</span>.id);
<a href=#124 id=124 data-nosnippet>124</a> <span class="self">Self </span>{
<a href=#125 id=125 data-nosnippet>125</a> id: <span class="self">self</span>.id,
<a href=#126 id=126 data-nosnippet>126</a> conn: <span class="self">self</span>.conn.clone(),
<a href=#127 id=127 data-nosnippet>127</a> }
<a href=#128 id=128 data-nosnippet>128</a> }
<a href=#129 id=129 data-nosnippet>129</a>}
<a href=#130 id=130 data-nosnippet>130</a>
<a href=#131 id=131 data-nosnippet>131</a><span class="kw">impl </span>Drop <span class="kw">for </span>Path {
<a href=#132 id=132 data-nosnippet>132</a> <span class="kw">fn </span>drop(<span class="kw-2">&amp;mut </span><span class="self">self</span>) {
<a href=#133 id=133 data-nosnippet>133</a> <span class="kw">let </span><span class="kw-2">mut </span>state = <span class="self">self</span>.conn.state.lock(<span class="string">"Path::drop"</span>);
<a href=#134 id=134 data-nosnippet>134</a> state.decrement_path_refs(<span class="self">self</span>.id);
<a href=#135 id=135 data-nosnippet>135</a> }
<a href=#136 id=136 data-nosnippet>136</a>}
<a href=#137 id=137 data-nosnippet>137</a>
<a href=#138 id=138 data-nosnippet>138</a><span class="kw">impl </span>Path {
<a href=#139 id=139 data-nosnippet>139</a> <span class="doccomment">/// Returns a [`Path`] for a path id, after checking that the path is not closed.
<a href=#140 id=140 data-nosnippet>140</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>new(conn: <span class="kw-2">&amp;</span>ConnectionRef, id: PathId) -&gt; <span class="prelude-ty">Option</span>&lt;<span class="self">Self</span>&gt; {
<a href=#141 id=141 data-nosnippet>141</a> {
<a href=#142 id=142 data-nosnippet>142</a> <span class="kw">let </span><span class="kw-2">mut </span>state = conn.state.lock(<span class="string">"Path::new"</span>);
<a href=#143 id=143 data-nosnippet>143</a> <span class="comment">// TODO(flub): Using this to know if the path still exists is... hacky.
<a href=#144 id=144 data-nosnippet>144</a> </span>state.inner.path_status(id).ok()<span class="question-mark">?</span>;
<a href=#145 id=145 data-nosnippet>145</a> state.increment_path_refs(id);
<a href=#146 id=146 data-nosnippet>146</a> }
<a href=#147 id=147 data-nosnippet>147</a> <span class="prelude-val">Some</span>(<span class="self">Self </span>{
<a href=#148 id=148 data-nosnippet>148</a> id,
<a href=#149 id=149 data-nosnippet>149</a> conn: conn.clone(),
<a href=#150 id=150 data-nosnippet>150</a> })
<a href=#151 id=151 data-nosnippet>151</a> }
<a href=#152 id=152 data-nosnippet>152</a>
<a href=#153 id=153 data-nosnippet>153</a> <span class="doccomment">/// Returns a [`Path`] for a path id without checking if the path exists or is closed.
<a href=#154 id=154 data-nosnippet>154</a> </span><span class="kw">fn </span>new_unchecked(conn: ConnectionRef, id: PathId) -&gt; <span class="self">Self </span>{
<a href=#155 id=155 data-nosnippet>155</a> conn.state
<a href=#156 id=156 data-nosnippet>156</a> .lock(<span class="string">"Path::new_unchecked"</span>)
<a href=#157 id=157 data-nosnippet>157</a> .increment_path_refs(id);
<a href=#158 id=158 data-nosnippet>158</a> <span class="self">Self </span>{ id, conn }
<a href=#159 id=159 data-nosnippet>159</a> }
<a href=#160 id=160 data-nosnippet>160</a>
<a href=#161 id=161 data-nosnippet>161</a> <span class="doccomment">/// Returns a [`WeakPathHandle`] for this path.
<a href=#162 id=162 data-nosnippet>162</a> ///
<a href=#163 id=163 data-nosnippet>163</a> /// Holding a [`WeakPathHandle`] does not keep a connection alive, but ensures that the
<a href=#164 id=164 data-nosnippet>164</a> /// path's stats are not dropped until the underlying connection is dropped, even if the
<a href=#165 id=165 data-nosnippet>165</a> /// path is abandoned.
<a href=#166 id=166 data-nosnippet>166</a> </span><span class="kw">pub fn </span>weak_handle(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; WeakPathHandle {
<a href=#167 id=167 data-nosnippet>167</a> <span class="self">self</span>.conn
<a href=#168 id=168 data-nosnippet>168</a> .state
<a href=#169 id=169 data-nosnippet>169</a> .lock(<span class="string">"Path::weak_handle"</span>)
<a href=#170 id=170 data-nosnippet>170</a> .increment_path_refs(<span class="self">self</span>.id);
<a href=#171 id=171 data-nosnippet>171</a> WeakPathHandle {
<a href=#172 id=172 data-nosnippet>172</a> id: <span class="self">self</span>.id,
<a href=#173 id=173 data-nosnippet>173</a> conn: <span class="self">self</span>.conn.weak_handle(),
<a href=#174 id=174 data-nosnippet>174</a> }
<a href=#175 id=175 data-nosnippet>175</a> }
<a href=#176 id=176 data-nosnippet>176</a>
<a href=#177 id=177 data-nosnippet>177</a> <span class="doccomment">/// The [`PathId`] of this path.
<a href=#178 id=178 data-nosnippet>178</a> </span><span class="kw">pub fn </span>id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; PathId {
<a href=#179 id=179 data-nosnippet>179</a> <span class="self">self</span>.id
<a href=#180 id=180 data-nosnippet>180</a> }
<a href=#181 id=181 data-nosnippet>181</a>
<a href=#182 id=182 data-nosnippet>182</a> <span class="doccomment">/// The current local [`PathStatus`] of this path.
<a href=#183 id=183 data-nosnippet>183</a> </span><span class="kw">pub fn </span>status(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;PathStatus, ClosedPath&gt; {
<a href=#184 id=184 data-nosnippet>184</a> <span class="self">self</span>.conn
<a href=#185 id=185 data-nosnippet>185</a> .state
<a href=#186 id=186 data-nosnippet>186</a> .lock(<span class="string">"path status"</span>)
<a href=#187 id=187 data-nosnippet>187</a> .inner
<a href=#188 id=188 data-nosnippet>188</a> .path_status(<span class="self">self</span>.id)
<a href=#189 id=189 data-nosnippet>189</a> }
<a href=#190 id=190 data-nosnippet>190</a>
<a href=#191 id=191 data-nosnippet>191</a> <span class="doccomment">/// Sets the [`PathStatus`] of this path.
<a href=#192 id=192 data-nosnippet>192</a> </span><span class="kw">pub fn </span>set_status(<span class="kw-2">&amp;</span><span class="self">self</span>, status: PathStatus) -&gt; <span class="prelude-ty">Result</span>&lt;(), SetPathStatusError&gt; {
<a href=#193 id=193 data-nosnippet>193</a> <span class="self">self</span>.conn
<a href=#194 id=194 data-nosnippet>194</a> .state
<a href=#195 id=195 data-nosnippet>195</a> .lock(<span class="string">"set path status"</span>)
<a href=#196 id=196 data-nosnippet>196</a> .inner
<a href=#197 id=197 data-nosnippet>197</a> .set_path_status(<span class="self">self</span>.id, status)<span class="question-mark">?</span>;
<a href=#198 id=198 data-nosnippet>198</a> <span class="prelude-val">Ok</span>(())
<a href=#199 id=199 data-nosnippet>199</a> }
<a href=#200 id=200 data-nosnippet>200</a>
<a href=#201 id=201 data-nosnippet>201</a> <span class="doccomment">/// Returns the [`PathStats`] for this path.
<a href=#202 id=202 data-nosnippet>202</a> </span><span class="kw">pub fn </span>stats(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; PathStats {
<a href=#203 id=203 data-nosnippet>203</a> <span class="comment">// The `expect` is safe:
<a href=#204 id=204 data-nosnippet>204</a> // - `Path` can only be created for non-closed paths.
<a href=#205 id=205 data-nosnippet>205</a> // - `Path` and its clones or `WeakPathHandle`s all increment the connection state's `path_ref`
<a href=#206 id=206 data-nosnippet>206</a> // reference counter
<a href=#207 id=207 data-nosnippet>207</a> // - As long as a path is not abandoned, its stats are available from `proto::Connection`
<a href=#208 id=208 data-nosnippet>208</a> // - If a path is abandoned, the `crate::Connection` stores the final stats as long as
<a href=#209 id=209 data-nosnippet>209</a> // the path's refcount is not 0
<a href=#210 id=210 data-nosnippet>210</a> // - Therefore, we always get stats here.
<a href=#211 id=211 data-nosnippet>211</a> </span><span class="self">self</span>.conn
<a href=#212 id=212 data-nosnippet>212</a> .state
<a href=#213 id=213 data-nosnippet>213</a> .lock(<span class="string">"Path::stats"</span>)
<a href=#214 id=214 data-nosnippet>214</a> .path_stats(<span class="self">self</span>.id)
<a href=#215 id=215 data-nosnippet>215</a> .expect(<span class="string">"either path stats or discarded path stats are always set as long as Path is not dropped"</span>)
<a href=#216 id=216 data-nosnippet>216</a> }
<a href=#217 id=217 data-nosnippet>217</a>
<a href=#218 id=218 data-nosnippet>218</a> <span class="doccomment">/// Closes this path.
<a href=#219 id=219 data-nosnippet>219</a> ///
<a href=#220 id=220 data-nosnippet>220</a> /// The path is immediately considered closed by the local endpoint. Once the state is removed,
<a href=#221 id=221 data-nosnippet>221</a> /// after a short period of time for any in-flight packets, a [`PathEvent::Abandoned`] is
<a href=#222 id=222 data-nosnippet>222</a> /// returned.
<a href=#223 id=223 data-nosnippet>223</a> </span><span class="kw">pub fn </span>close(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;(), ClosePathError&gt; {
<a href=#224 id=224 data-nosnippet>224</a> <span class="kw">let </span><span class="kw-2">mut </span>state = <span class="self">self</span>.conn.state.lock(<span class="string">"close_path"</span>);
<a href=#225 id=225 data-nosnippet>225</a> state.inner.close_path(
<a href=#226 id=226 data-nosnippet>226</a> <span class="kw">crate</span>::Instant::now(),
<a href=#227 id=227 data-nosnippet>227</a> <span class="self">self</span>.id,
<a href=#228 id=228 data-nosnippet>228</a> TransportErrorCode::APPLICATION_ABANDON_PATH.into(),
<a href=#229 id=229 data-nosnippet>229</a> )
<a href=#230 id=230 data-nosnippet>230</a> }
<a href=#231 id=231 data-nosnippet>231</a>
<a href=#232 id=232 data-nosnippet>232</a> <span class="doccomment">/// Sets the keep_alive_interval for a specific path
<a href=#233 id=233 data-nosnippet>233</a> ///
<a href=#234 id=234 data-nosnippet>234</a> /// See [`TransportConfig::default_path_keep_alive_interval`] for details.
<a href=#235 id=235 data-nosnippet>235</a> ///
<a href=#236 id=236 data-nosnippet>236</a> /// Returns the previous value of the setting.
<a href=#237 id=237 data-nosnippet>237</a> ///
<a href=#238 id=238 data-nosnippet>238</a> /// [`TransportConfig::default_path_keep_alive_interval`]: crate::TransportConfig::default_path_keep_alive_interval
<a href=#239 id=239 data-nosnippet>239</a> </span><span class="kw">pub fn </span>set_max_idle_timeout(
<a href=#240 id=240 data-nosnippet>240</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#241 id=241 data-nosnippet>241</a> timeout: <span class="prelude-ty">Option</span>&lt;Duration&gt;,
<a href=#242 id=242 data-nosnippet>242</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="prelude-ty">Option</span>&lt;Duration&gt;, ClosedPath&gt; {
<a href=#243 id=243 data-nosnippet>243</a> <span class="kw">let </span><span class="kw-2">mut </span>state = <span class="self">self</span>.conn.state.lock(<span class="string">"path_set_max_idle_timeout"</span>);
<a href=#244 id=244 data-nosnippet>244</a> <span class="kw">let </span>now = state.runtime.now();
<a href=#245 id=245 data-nosnippet>245</a> state.inner.set_path_max_idle_timeout(now, <span class="self">self</span>.id, timeout)
<a href=#246 id=246 data-nosnippet>246</a> }
<a href=#247 id=247 data-nosnippet>247</a>
<a href=#248 id=248 data-nosnippet>248</a> <span class="doccomment">/// Sets the keep_alive_interval for a specific path
<a href=#249 id=249 data-nosnippet>249</a> ///
<a href=#250 id=250 data-nosnippet>250</a> /// See [`TransportConfig::default_path_keep_alive_interval`] for details.
<a href=#251 id=251 data-nosnippet>251</a> ///
<a href=#252 id=252 data-nosnippet>252</a> /// Returns the previous value of the setting.
<a href=#253 id=253 data-nosnippet>253</a> ///
<a href=#254 id=254 data-nosnippet>254</a> /// [`TransportConfig::default_path_keep_alive_interval`]: crate::TransportConfig::default_path_keep_alive_interval
<a href=#255 id=255 data-nosnippet>255</a> </span><span class="kw">pub fn </span>set_keep_alive_interval(
<a href=#256 id=256 data-nosnippet>256</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#257 id=257 data-nosnippet>257</a> interval: <span class="prelude-ty">Option</span>&lt;Duration&gt;,
<a href=#258 id=258 data-nosnippet>258</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="prelude-ty">Option</span>&lt;Duration&gt;, ClosedPath&gt; {
<a href=#259 id=259 data-nosnippet>259</a> <span class="kw">let </span><span class="kw-2">mut </span>state = <span class="self">self</span>.conn.state.lock(<span class="string">"path_set_keep_alive_interval"</span>);
<a href=#260 id=260 data-nosnippet>260</a> state.inner.set_path_keep_alive_interval(<span class="self">self</span>.id, interval)
<a href=#261 id=261 data-nosnippet>261</a> }
<a href=#262 id=262 data-nosnippet>262</a>
<a href=#263 id=263 data-nosnippet>263</a> <span class="doccomment">/// Track changes on our external address as reported by the peer.
<a href=#264 id=264 data-nosnippet>264</a> ///
<a href=#265 id=265 data-nosnippet>265</a> /// If the address-discovery extension is not negotiated, the stream will never return.
<a href=#266 id=266 data-nosnippet>266</a> </span><span class="kw">pub fn </span>observed_external_addr(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;AddressDiscovery, ClosedPath&gt; {
<a href=#267 id=267 data-nosnippet>267</a> <span class="kw">let </span>state = <span class="self">self</span>.conn.state.lock(<span class="string">"per_path_observed_address"</span>);
<a href=#268 id=268 data-nosnippet>268</a> <span class="kw">let </span>path_events = state.path_events.subscribe();
<a href=#269 id=269 data-nosnippet>269</a> <span class="kw">let </span>initial_value = state.inner.path_observed_address(<span class="self">self</span>.id)<span class="question-mark">?</span>;
<a href=#270 id=270 data-nosnippet>270</a> <span class="prelude-val">Ok</span>(AddressDiscovery::new(
<a href=#271 id=271 data-nosnippet>271</a> <span class="self">self</span>.id,
<a href=#272 id=272 data-nosnippet>272</a> path_events,
<a href=#273 id=273 data-nosnippet>273</a> initial_value,
<a href=#274 id=274 data-nosnippet>274</a> state.runtime.clone(),
<a href=#275 id=275 data-nosnippet>275</a> ))
<a href=#121 id=121 data-nosnippet>121</a> .lock_without_waking(<span class="string">"Path::clone"</span>)
<a href=#122 id=122 data-nosnippet>122</a> .increment_path_refs(<span class="self">self</span>.id);
<a href=#123 id=123 data-nosnippet>123</a> <span class="self">Self </span>{
<a href=#124 id=124 data-nosnippet>124</a> id: <span class="self">self</span>.id,
<a href=#125 id=125 data-nosnippet>125</a> conn: <span class="self">self</span>.conn.clone(),
<a href=#126 id=126 data-nosnippet>126</a> }
<a href=#127 id=127 data-nosnippet>127</a> }
<a href=#128 id=128 data-nosnippet>128</a>}
<a href=#129 id=129 data-nosnippet>129</a>
<a href=#130 id=130 data-nosnippet>130</a><span class="kw">impl </span>Drop <span class="kw">for </span>Path {
<a href=#131 id=131 data-nosnippet>131</a> <span class="kw">fn </span>drop(<span class="kw-2">&amp;mut </span><span class="self">self</span>) {
<a href=#132 id=132 data-nosnippet>132</a> <span class="kw">let </span><span class="kw-2">mut </span>state = <span class="self">self</span>.conn.lock_without_waking(<span class="string">"Path::drop"</span>);
<a href=#133 id=133 data-nosnippet>133</a> state.decrement_path_refs(<span class="self">self</span>.id);
<a href=#134 id=134 data-nosnippet>134</a> }
<a href=#135 id=135 data-nosnippet>135</a>}
<a href=#136 id=136 data-nosnippet>136</a>
<a href=#137 id=137 data-nosnippet>137</a><span class="kw">impl </span>Path {
<a href=#138 id=138 data-nosnippet>138</a> <span class="doccomment">/// Returns a [`Path`] for a path id, after checking that the path is not closed.
<a href=#139 id=139 data-nosnippet>139</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>new(conn: <span class="kw-2">&amp;</span>ConnectionRef, id: PathId) -&gt; <span class="prelude-ty">Option</span>&lt;<span class="self">Self</span>&gt; {
<a href=#140 id=140 data-nosnippet>140</a> {
<a href=#141 id=141 data-nosnippet>141</a> <span class="kw">let </span><span class="kw-2">mut </span>state = conn.lock_without_waking(<span class="string">"Path::new"</span>);
<a href=#142 id=142 data-nosnippet>142</a> <span class="comment">// TODO(flub): Using this to know if the path still exists is... hacky.
<a href=#143 id=143 data-nosnippet>143</a> </span>state.inner.path_status(id).ok()<span class="question-mark">?</span>;
<a href=#144 id=144 data-nosnippet>144</a> state.increment_path_refs(id);
<a href=#145 id=145 data-nosnippet>145</a> }
<a href=#146 id=146 data-nosnippet>146</a> <span class="prelude-val">Some</span>(<span class="self">Self </span>{
<a href=#147 id=147 data-nosnippet>147</a> id,
<a href=#148 id=148 data-nosnippet>148</a> conn: conn.clone(),
<a href=#149 id=149 data-nosnippet>149</a> })
<a href=#150 id=150 data-nosnippet>150</a> }
<a href=#151 id=151 data-nosnippet>151</a>
<a href=#152 id=152 data-nosnippet>152</a> <span class="doccomment">/// Returns a [`Path`] for a path id without checking if the path exists or is closed.
<a href=#153 id=153 data-nosnippet>153</a> </span><span class="kw">fn </span>new_unchecked(conn: ConnectionRef, id: PathId) -&gt; <span class="self">Self </span>{
<a href=#154 id=154 data-nosnippet>154</a> conn.lock_without_waking(<span class="string">"Path::new_unchecked"</span>)
<a href=#155 id=155 data-nosnippet>155</a> .increment_path_refs(id);
<a href=#156 id=156 data-nosnippet>156</a> <span class="self">Self </span>{ id, conn }
<a href=#157 id=157 data-nosnippet>157</a> }
<a href=#158 id=158 data-nosnippet>158</a>
<a href=#159 id=159 data-nosnippet>159</a> <span class="doccomment">/// Returns a [`WeakPathHandle`] for this path.
<a href=#160 id=160 data-nosnippet>160</a> ///
<a href=#161 id=161 data-nosnippet>161</a> /// Holding a [`WeakPathHandle`] does not keep a connection alive, but ensures that the
<a href=#162 id=162 data-nosnippet>162</a> /// path's stats are not dropped until the underlying connection is dropped, even if the
<a href=#163 id=163 data-nosnippet>163</a> /// path is abandoned.
<a href=#164 id=164 data-nosnippet>164</a> </span><span class="kw">pub fn </span>weak_handle(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; WeakPathHandle {
<a href=#165 id=165 data-nosnippet>165</a> <span class="self">self</span>.conn
<a href=#166 id=166 data-nosnippet>166</a> .lock_without_waking(<span class="string">"Path::weak_handle"</span>)
<a href=#167 id=167 data-nosnippet>167</a> .increment_path_refs(<span class="self">self</span>.id);
<a href=#168 id=168 data-nosnippet>168</a> WeakPathHandle {
<a href=#169 id=169 data-nosnippet>169</a> id: <span class="self">self</span>.id,
<a href=#170 id=170 data-nosnippet>170</a> conn: <span class="self">self</span>.conn.weak_handle(),
<a href=#171 id=171 data-nosnippet>171</a> }
<a href=#172 id=172 data-nosnippet>172</a> }
<a href=#173 id=173 data-nosnippet>173</a>
<a href=#174 id=174 data-nosnippet>174</a> <span class="doccomment">/// The [`PathId`] of this path.
<a href=#175 id=175 data-nosnippet>175</a> </span><span class="kw">pub fn </span>id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; PathId {
<a href=#176 id=176 data-nosnippet>176</a> <span class="self">self</span>.id
<a href=#177 id=177 data-nosnippet>177</a> }
<a href=#178 id=178 data-nosnippet>178</a>
<a href=#179 id=179 data-nosnippet>179</a> <span class="doccomment">/// The current local [`PathStatus`] of this path.
<a href=#180 id=180 data-nosnippet>180</a> </span><span class="kw">pub fn </span>status(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;PathStatus, ClosedPath&gt; {
<a href=#181 id=181 data-nosnippet>181</a> <span class="self">self</span>.conn
<a href=#182 id=182 data-nosnippet>182</a> .lock_without_waking(<span class="string">"path status"</span>)
<a href=#183 id=183 data-nosnippet>183</a> .inner
<a href=#184 id=184 data-nosnippet>184</a> .path_status(<span class="self">self</span>.id)
<a href=#185 id=185 data-nosnippet>185</a> }
<a href=#186 id=186 data-nosnippet>186</a>
<a href=#187 id=187 data-nosnippet>187</a> <span class="doccomment">/// Sets the [`PathStatus`] of this path.
<a href=#188 id=188 data-nosnippet>188</a> </span><span class="kw">pub fn </span>set_status(<span class="kw-2">&amp;</span><span class="self">self</span>, status: PathStatus) -&gt; <span class="prelude-ty">Result</span>&lt;(), SetPathStatusError&gt; {
<a href=#189 id=189 data-nosnippet>189</a> <span class="self">self</span>.conn
<a href=#190 id=190 data-nosnippet>190</a> .lock_and_wake(<span class="string">"set path status"</span>)
<a href=#191 id=191 data-nosnippet>191</a> .inner
<a href=#192 id=192 data-nosnippet>192</a> .set_path_status(<span class="self">self</span>.id, status)<span class="question-mark">?</span>;
<a href=#193 id=193 data-nosnippet>193</a> <span class="prelude-val">Ok</span>(())
<a href=#194 id=194 data-nosnippet>194</a> }
<a href=#195 id=195 data-nosnippet>195</a>
<a href=#196 id=196 data-nosnippet>196</a> <span class="doccomment">/// Returns the [`PathStats`] for this path.
<a href=#197 id=197 data-nosnippet>197</a> </span><span class="kw">pub fn </span>stats(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; PathStats {
<a href=#198 id=198 data-nosnippet>198</a> <span class="comment">// The `expect` is safe:
<a href=#199 id=199 data-nosnippet>199</a> // - `Path` can only be created for non-closed paths.
<a href=#200 id=200 data-nosnippet>200</a> // - `Path` and its clones or `WeakPathHandle`s all increment the connection state's `path_ref`
<a href=#201 id=201 data-nosnippet>201</a> // reference counter
<a href=#202 id=202 data-nosnippet>202</a> // - As long as a path is not abandoned, its stats are available from `proto::Connection`
<a href=#203 id=203 data-nosnippet>203</a> // - If a path is abandoned, the `crate::Connection` stores the final stats as long as
<a href=#204 id=204 data-nosnippet>204</a> // the path's refcount is not 0
<a href=#205 id=205 data-nosnippet>205</a> // - Therefore, we always get stats here.
<a href=#206 id=206 data-nosnippet>206</a> </span><span class="self">self</span>.conn
<a href=#207 id=207 data-nosnippet>207</a> .lock_without_waking(<span class="string">"Path::stats"</span>)
<a href=#208 id=208 data-nosnippet>208</a> .path_stats(<span class="self">self</span>.id)
<a href=#209 id=209 data-nosnippet>209</a> .expect(<span class="string">"either path stats or discarded path stats are always set as long as Path is not dropped"</span>)
<a href=#210 id=210 data-nosnippet>210</a> }
<a href=#211 id=211 data-nosnippet>211</a>
<a href=#212 id=212 data-nosnippet>212</a> <span class="doccomment">/// Closes this path.
<a href=#213 id=213 data-nosnippet>213</a> ///
<a href=#214 id=214 data-nosnippet>214</a> /// The path is immediately considered closed by the local endpoint. Once the state is removed,
<a href=#215 id=215 data-nosnippet>215</a> /// after a short period of time for any in-flight packets, a [`PathEvent::Abandoned`] is
<a href=#216 id=216 data-nosnippet>216</a> /// returned.
<a href=#217 id=217 data-nosnippet>217</a> </span><span class="kw">pub fn </span>close(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;(), ClosePathError&gt; {
<a href=#218 id=218 data-nosnippet>218</a> <span class="kw">let </span><span class="kw-2">mut </span>state = <span class="self">self</span>.conn.lock_and_wake(<span class="string">"close_path"</span>);
<a href=#219 id=219 data-nosnippet>219</a> state.inner.close_path(
<a href=#220 id=220 data-nosnippet>220</a> <span class="kw">crate</span>::Instant::now(),
<a href=#221 id=221 data-nosnippet>221</a> <span class="self">self</span>.id,
<a href=#222 id=222 data-nosnippet>222</a> TransportErrorCode::APPLICATION_ABANDON_PATH.into(),
<a href=#223 id=223 data-nosnippet>223</a> )
<a href=#224 id=224 data-nosnippet>224</a> }
<a href=#225 id=225 data-nosnippet>225</a>
<a href=#226 id=226 data-nosnippet>226</a> <span class="doccomment">/// Sets the keep_alive_interval for a specific path
<a href=#227 id=227 data-nosnippet>227</a> ///
<a href=#228 id=228 data-nosnippet>228</a> /// See [`TransportConfig::default_path_keep_alive_interval`] for details.
<a href=#229 id=229 data-nosnippet>229</a> ///
<a href=#230 id=230 data-nosnippet>230</a> /// Returns the previous value of the setting.
<a href=#231 id=231 data-nosnippet>231</a> ///
<a href=#232 id=232 data-nosnippet>232</a> /// [`TransportConfig::default_path_keep_alive_interval`]: crate::TransportConfig::default_path_keep_alive_interval
<a href=#233 id=233 data-nosnippet>233</a> </span><span class="kw">pub fn </span>set_max_idle_timeout(
<a href=#234 id=234 data-nosnippet>234</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#235 id=235 data-nosnippet>235</a> timeout: <span class="prelude-ty">Option</span>&lt;Duration&gt;,
<a href=#236 id=236 data-nosnippet>236</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="prelude-ty">Option</span>&lt;Duration&gt;, ClosedPath&gt; {
<a href=#237 id=237 data-nosnippet>237</a> <span class="kw">let </span><span class="kw-2">mut </span>state = <span class="self">self</span>.conn.lock_and_wake(<span class="string">"path_set_max_idle_timeout"</span>);
<a href=#238 id=238 data-nosnippet>238</a> <span class="kw">let </span>now = state.runtime.now();
<a href=#239 id=239 data-nosnippet>239</a> state.inner.set_path_max_idle_timeout(now, <span class="self">self</span>.id, timeout)
<a href=#240 id=240 data-nosnippet>240</a> }
<a href=#241 id=241 data-nosnippet>241</a>
<a href=#242 id=242 data-nosnippet>242</a> <span class="doccomment">/// Sets the keep_alive_interval for a specific path
<a href=#243 id=243 data-nosnippet>243</a> ///
<a href=#244 id=244 data-nosnippet>244</a> /// See [`TransportConfig::default_path_keep_alive_interval`] for details.
<a href=#245 id=245 data-nosnippet>245</a> ///
<a href=#246 id=246 data-nosnippet>246</a> /// Returns the previous value of the setting.
<a href=#247 id=247 data-nosnippet>247</a> ///
<a href=#248 id=248 data-nosnippet>248</a> /// [`TransportConfig::default_path_keep_alive_interval`]: crate::TransportConfig::default_path_keep_alive_interval
<a href=#249 id=249 data-nosnippet>249</a> </span><span class="kw">pub fn </span>set_keep_alive_interval(
<a href=#250 id=250 data-nosnippet>250</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#251 id=251 data-nosnippet>251</a> interval: <span class="prelude-ty">Option</span>&lt;Duration&gt;,
<a href=#252 id=252 data-nosnippet>252</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="prelude-ty">Option</span>&lt;Duration&gt;, ClosedPath&gt; {
<a href=#253 id=253 data-nosnippet>253</a> <span class="kw">let </span><span class="kw-2">mut </span>state = <span class="self">self</span>.conn.lock_and_wake(<span class="string">"path_set_keep_alive_interval"</span>);
<a href=#254 id=254 data-nosnippet>254</a> state.inner.set_path_keep_alive_interval(<span class="self">self</span>.id, interval)
<a href=#255 id=255 data-nosnippet>255</a> }
<a href=#256 id=256 data-nosnippet>256</a>
<a href=#257 id=257 data-nosnippet>257</a> <span class="doccomment">/// Track changes on our external address as reported by the peer.
<a href=#258 id=258 data-nosnippet>258</a> ///
<a href=#259 id=259 data-nosnippet>259</a> /// If the address-discovery extension is not negotiated, the stream will never return.
<a href=#260 id=260 data-nosnippet>260</a> </span><span class="kw">pub fn </span>observed_external_addr(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;AddressDiscovery, ClosedPath&gt; {
<a href=#261 id=261 data-nosnippet>261</a> <span class="kw">let </span>state = <span class="self">self</span>.conn.lock_without_waking(<span class="string">"per_path_observed_address"</span>);
<a href=#262 id=262 data-nosnippet>262</a> <span class="kw">let </span>path_events = state.path_events.subscribe();
<a href=#263 id=263 data-nosnippet>263</a> <span class="kw">let </span>initial_value = state.inner.path_observed_address(<span class="self">self</span>.id)<span class="question-mark">?</span>;
<a href=#264 id=264 data-nosnippet>264</a> <span class="prelude-val">Ok</span>(AddressDiscovery::new(
<a href=#265 id=265 data-nosnippet>265</a> <span class="self">self</span>.id,
<a href=#266 id=266 data-nosnippet>266</a> path_events,
<a href=#267 id=267 data-nosnippet>267</a> initial_value,
<a href=#268 id=268 data-nosnippet>268</a> state.runtime.clone(),
<a href=#269 id=269 data-nosnippet>269</a> ))
<a href=#270 id=270 data-nosnippet>270</a> }
<a href=#271 id=271 data-nosnippet>271</a>
<a href=#272 id=272 data-nosnippet>272</a> <span class="doccomment">/// The peer's UDP address for this path.
<a href=#273 id=273 data-nosnippet>273</a> </span><span class="kw">pub fn </span>remote_address(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;SocketAddr, ClosedPath&gt; {
<a href=#274 id=274 data-nosnippet>274</a> <span class="kw">let </span>state = <span class="self">self</span>.conn.lock_without_waking(<span class="string">"per_path_remote_address"</span>);
<a href=#275 id=275 data-nosnippet>275</a> <span class="prelude-val">Ok</span>(state.inner.network_path(<span class="self">self</span>.id)<span class="question-mark">?</span>.remote())
<a href=#276 id=276 data-nosnippet>276</a> }
<a href=#277 id=277 data-nosnippet>277</a>
<a href=#278 id=278 data-nosnippet>278</a> <span class="doccomment">/// The peer's UDP address for this path.
<a href=#279 id=279 data-nosnippet>279</a> </span><span class="kw">pub fn </span>remote_address(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;SocketAddr, ClosedPath&gt; {
<a href=#280 id=280 data-nosnippet>280</a> <span class="kw">let </span>state = <span class="self">self</span>.conn.state.lock(<span class="string">"per_path_remote_address"</span>);
<a href=#281 id=281 data-nosnippet>281</a> <span class="prelude-val">Ok</span>(state.inner.network_path(<span class="self">self</span>.id)<span class="question-mark">?</span>.remote())
<a href=#278 id=278 data-nosnippet>278</a> <span class="doccomment">/// Ping the remote endpoint over this path.
<a href=#279 id=279 data-nosnippet>279</a> </span><span class="kw">pub fn </span>ping(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;(), ClosedPath&gt; {
<a href=#280 id=280 data-nosnippet>280</a> <span class="kw">let </span><span class="kw-2">mut </span>state = <span class="self">self</span>.conn.lock_and_wake(<span class="string">"ping"</span>);
<a href=#281 id=281 data-nosnippet>281</a> state.inner.ping_path(<span class="self">self</span>.id)
<a href=#282 id=282 data-nosnippet>282</a> }
<a href=#283 id=283 data-nosnippet>283</a>
<a href=#284 id=284 data-nosnippet>284</a> <span class="doccomment">/// Ping the remote endpoint over this path.
<a href=#285 id=285 data-nosnippet>285</a> </span><span class="kw">pub fn </span>ping(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;(), ClosedPath&gt; {
<a href=#286 id=286 data-nosnippet>286</a> <span class="kw">let </span><span class="kw-2">mut </span>state = <span class="self">self</span>.conn.state.lock(<span class="string">"ping"</span>);
<a href=#287 id=287 data-nosnippet>287</a> state.inner.ping_path(<span class="self">self</span>.id)
<a href=#283 id=283 data-nosnippet>283</a>}
<a href=#284 id=284 data-nosnippet>284</a>
<a href=#285 id=285 data-nosnippet>285</a><span class="kw">impl </span>PartialEq <span class="kw">for </span>Path {
<a href=#286 id=286 data-nosnippet>286</a> <span class="kw">fn </span>eq(<span class="kw-2">&amp;</span><span class="self">self</span>, other: <span class="kw-2">&amp;</span><span class="self">Self</span>) -&gt; bool {
<a href=#287 id=287 data-nosnippet>287</a> <span class="self">self</span>.id == other.id &amp;&amp; <span class="self">self</span>.conn.stable_id() == other.conn.stable_id()
<a href=#288 id=288 data-nosnippet>288</a> }
<a href=#289 id=289 data-nosnippet>289</a>}
<a href=#290 id=290 data-nosnippet>290</a>
<a href=#291 id=291 data-nosnippet>291</a><span class="kw">impl </span>PartialEq <span class="kw">for </span>Path {
<a href=#292 id=292 data-nosnippet>292</a> <span class="kw">fn </span>eq(<span class="kw-2">&amp;</span><span class="self">self</span>, other: <span class="kw-2">&amp;</span><span class="self">Self</span>) -&gt; bool {
<a href=#293 id=293 data-nosnippet>293</a> <span class="self">self</span>.id == other.id &amp;&amp; <span class="self">self</span>.conn.stable_id() == other.conn.stable_id()
<a href=#294 id=294 data-nosnippet>294</a> }
<a href=#295 id=295 data-nosnippet>295</a>}
<a href=#296 id=296 data-nosnippet>296</a>
<a href=#297 id=297 data-nosnippet>297</a><span class="doccomment">/// Weak handle for a [`Path`] that does not keep the connection alive.
<a href=#298 id=298 data-nosnippet>298</a>///
<a href=#299 id=299 data-nosnippet>299</a>/// As long as a [`WeakPathHandle`] for a path exists, that path's final stats will not be dropped even if
<a href=#300 id=300 data-nosnippet>300</a>/// the path was abandoned.
<a href=#301 id=301 data-nosnippet>301</a>///
<a href=#302 id=302 data-nosnippet>302</a>/// The [`WeakPathHandle`] can be upgraded to a [`Path`] as long as its [`Connection`] has not been dropped.
<a href=#303 id=303 data-nosnippet>303</a>///
<a href=#304 id=304 data-nosnippet>304</a>/// [`Connection`]: crate::Connection
<a href=#305 id=305 data-nosnippet>305</a></span><span class="attr">#[derive(Debug)]
<a href=#306 id=306 data-nosnippet>306</a></span><span class="kw">pub struct </span>WeakPathHandle {
<a href=#307 id=307 data-nosnippet>307</a> id: PathId,
<a href=#308 id=308 data-nosnippet>308</a> conn: WeakConnectionHandle,
<a href=#309 id=309 data-nosnippet>309</a>}
<a href=#310 id=310 data-nosnippet>310</a>
<a href=#311 id=311 data-nosnippet>311</a><span class="kw">impl </span>Clone <span class="kw">for </span>WeakPathHandle {
<a href=#312 id=312 data-nosnippet>312</a> <span class="kw">fn </span>clone(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="self">Self </span>{
<a href=#313 id=313 data-nosnippet>313</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(conn) = <span class="self">self</span>.conn.upgrade_to_ref() {
<a href=#314 id=314 data-nosnippet>314</a> conn.state
<a href=#315 id=315 data-nosnippet>315</a> .lock(<span class="string">"WeakPathHandle::clone"</span>)
<a href=#316 id=316 data-nosnippet>316</a> .increment_path_refs(<span class="self">self</span>.id);
<a href=#317 id=317 data-nosnippet>317</a> }
<a href=#318 id=318 data-nosnippet>318</a> <span class="self">Self </span>{
<a href=#319 id=319 data-nosnippet>319</a> id: <span class="self">self</span>.id,
<a href=#320 id=320 data-nosnippet>320</a> conn: <span class="self">self</span>.conn.clone(),
<a href=#321 id=321 data-nosnippet>321</a> }
<a href=#322 id=322 data-nosnippet>322</a> }
<a href=#323 id=323 data-nosnippet>323</a>}
<a href=#324 id=324 data-nosnippet>324</a>
<a href=#325 id=325 data-nosnippet>325</a><span class="kw">impl </span>PartialEq <span class="kw">for </span>WeakPathHandle {
<a href=#326 id=326 data-nosnippet>326</a> <span class="kw">fn </span>eq(<span class="kw-2">&amp;</span><span class="self">self</span>, other: <span class="kw-2">&amp;</span><span class="self">Self</span>) -&gt; bool {
<a href=#327 id=327 data-nosnippet>327</a> <span class="self">self</span>.id == other.id &amp;&amp; <span class="self">self</span>.conn.is_same_connection(<span class="kw-2">&amp;</span>other.conn)
<a href=#328 id=328 data-nosnippet>328</a> }
<a href=#329 id=329 data-nosnippet>329</a>}
<a href=#330 id=330 data-nosnippet>330</a>
<a href=#331 id=331 data-nosnippet>331</a><span class="kw">impl </span>Eq <span class="kw">for </span>WeakPathHandle {}
<a href=#332 id=332 data-nosnippet>332</a>
<a href=#333 id=333 data-nosnippet>333</a><span class="kw">impl </span>Drop <span class="kw">for </span>WeakPathHandle {
<a href=#334 id=334 data-nosnippet>334</a> <span class="kw">fn </span>drop(<span class="kw-2">&amp;mut </span><span class="self">self</span>) {
<a href=#335 id=335 data-nosnippet>335</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(conn) = <span class="self">self</span>.conn.upgrade_to_ref() {
<a href=#336 id=336 data-nosnippet>336</a> conn.state
<a href=#337 id=337 data-nosnippet>337</a> .lock(<span class="string">"WeakPathHandle::drop"</span>)
<a href=#338 id=338 data-nosnippet>338</a> .decrement_path_refs(<span class="self">self</span>.id);
<a href=#339 id=339 data-nosnippet>339</a> }
<a href=#340 id=340 data-nosnippet>340</a> }
<a href=#341 id=341 data-nosnippet>341</a>}
<a href=#342 id=342 data-nosnippet>342</a>
<a href=#343 id=343 data-nosnippet>343</a><span class="kw">impl </span>WeakPathHandle {
<a href=#344 id=344 data-nosnippet>344</a> <span class="doccomment">/// Returns the [`PathId`] of this path.
<a href=#345 id=345 data-nosnippet>345</a> </span><span class="kw">pub fn </span>id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; PathId {
<a href=#346 id=346 data-nosnippet>346</a> <span class="self">self</span>.id
<a href=#291 id=291 data-nosnippet>291</a><span class="doccomment">/// Weak handle for a [`Path`] that does not keep the connection alive.
<a href=#292 id=292 data-nosnippet>292</a>///
<a href=#293 id=293 data-nosnippet>293</a>/// As long as a [`WeakPathHandle`] for a path exists, that path's final stats will not be dropped even if
<a href=#294 id=294 data-nosnippet>294</a>/// the path was abandoned.
<a href=#295 id=295 data-nosnippet>295</a>///
<a href=#296 id=296 data-nosnippet>296</a>/// The [`WeakPathHandle`] can be upgraded to a [`Path`] as long as its [`Connection`] has not been dropped.
<a href=#297 id=297 data-nosnippet>297</a>///
<a href=#298 id=298 data-nosnippet>298</a>/// [`Connection`]: crate::Connection
<a href=#299 id=299 data-nosnippet>299</a></span><span class="attr">#[derive(Debug)]
<a href=#300 id=300 data-nosnippet>300</a></span><span class="kw">pub struct </span>WeakPathHandle {
<a href=#301 id=301 data-nosnippet>301</a> id: PathId,
<a href=#302 id=302 data-nosnippet>302</a> conn: WeakConnectionHandle,
<a href=#303 id=303 data-nosnippet>303</a>}
<a href=#304 id=304 data-nosnippet>304</a>
<a href=#305 id=305 data-nosnippet>305</a><span class="kw">impl </span>Clone <span class="kw">for </span>WeakPathHandle {
<a href=#306 id=306 data-nosnippet>306</a> <span class="kw">fn </span>clone(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="self">Self </span>{
<a href=#307 id=307 data-nosnippet>307</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(conn) = <span class="self">self</span>.conn.upgrade_to_ref() {
<a href=#308 id=308 data-nosnippet>308</a> conn.lock_without_waking(<span class="string">"WeakPathHandle::clone"</span>)
<a href=#309 id=309 data-nosnippet>309</a> .increment_path_refs(<span class="self">self</span>.id);
<a href=#310 id=310 data-nosnippet>310</a> }
<a href=#311 id=311 data-nosnippet>311</a> <span class="self">Self </span>{
<a href=#312 id=312 data-nosnippet>312</a> id: <span class="self">self</span>.id,
<a href=#313 id=313 data-nosnippet>313</a> conn: <span class="self">self</span>.conn.clone(),
<a href=#314 id=314 data-nosnippet>314</a> }
<a href=#315 id=315 data-nosnippet>315</a> }
<a href=#316 id=316 data-nosnippet>316</a>}
<a href=#317 id=317 data-nosnippet>317</a>
<a href=#318 id=318 data-nosnippet>318</a><span class="kw">impl </span>PartialEq <span class="kw">for </span>WeakPathHandle {
<a href=#319 id=319 data-nosnippet>319</a> <span class="kw">fn </span>eq(<span class="kw-2">&amp;</span><span class="self">self</span>, other: <span class="kw-2">&amp;</span><span class="self">Self</span>) -&gt; bool {
<a href=#320 id=320 data-nosnippet>320</a> <span class="self">self</span>.id == other.id &amp;&amp; <span class="self">self</span>.conn.is_same_connection(<span class="kw-2">&amp;</span>other.conn)
<a href=#321 id=321 data-nosnippet>321</a> }
<a href=#322 id=322 data-nosnippet>322</a>}
<a href=#323 id=323 data-nosnippet>323</a>
<a href=#324 id=324 data-nosnippet>324</a><span class="kw">impl </span>Eq <span class="kw">for </span>WeakPathHandle {}
<a href=#325 id=325 data-nosnippet>325</a>
<a href=#326 id=326 data-nosnippet>326</a><span class="kw">impl </span>Drop <span class="kw">for </span>WeakPathHandle {
<a href=#327 id=327 data-nosnippet>327</a> <span class="kw">fn </span>drop(<span class="kw-2">&amp;mut </span><span class="self">self</span>) {
<a href=#328 id=328 data-nosnippet>328</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(conn) = <span class="self">self</span>.conn.upgrade_to_ref() {
<a href=#329 id=329 data-nosnippet>329</a> conn.lock_without_waking(<span class="string">"WeakPathHandle::drop"</span>)
<a href=#330 id=330 data-nosnippet>330</a> .decrement_path_refs(<span class="self">self</span>.id);
<a href=#331 id=331 data-nosnippet>331</a> }
<a href=#332 id=332 data-nosnippet>332</a> }
<a href=#333 id=333 data-nosnippet>333</a>}
<a href=#334 id=334 data-nosnippet>334</a>
<a href=#335 id=335 data-nosnippet>335</a><span class="kw">impl </span>WeakPathHandle {
<a href=#336 id=336 data-nosnippet>336</a> <span class="doccomment">/// Returns the [`PathId`] of this path.
<a href=#337 id=337 data-nosnippet>337</a> </span><span class="kw">pub fn </span>id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; PathId {
<a href=#338 id=338 data-nosnippet>338</a> <span class="self">self</span>.id
<a href=#339 id=339 data-nosnippet>339</a> }
<a href=#340 id=340 data-nosnippet>340</a>
<a href=#341 id=341 data-nosnippet>341</a> <span class="doccomment">/// Upgrades to a [`Path`].
<a href=#342 id=342 data-nosnippet>342</a> ///
<a href=#343 id=343 data-nosnippet>343</a> /// Returns `None` if the connection was dropped.
<a href=#344 id=344 data-nosnippet>344</a> </span><span class="kw">pub fn </span>upgrade(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Option</span>&lt;Path&gt; {
<a href=#345 id=345 data-nosnippet>345</a> <span class="kw">let </span>conn = <span class="self">self</span>.conn.upgrade_to_ref()<span class="question-mark">?</span>;
<a href=#346 id=346 data-nosnippet>346</a> <span class="prelude-val">Some</span>(Path::new_unchecked(conn, <span class="self">self</span>.id))
<a href=#347 id=347 data-nosnippet>347</a> }
<a href=#348 id=348 data-nosnippet>348</a>
<a href=#349 id=349 data-nosnippet>349</a> <span class="doccomment">/// Upgrades to a [`Path`].
<a href=#350 id=350 data-nosnippet>350</a> ///
<a href=#351 id=351 data-nosnippet>351</a> /// Returns `None` if the connection was dropped.
<a href=#352 id=352 data-nosnippet>352</a> </span><span class="kw">pub fn </span>upgrade(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Option</span>&lt;Path&gt; {
<a href=#353 id=353 data-nosnippet>353</a> <span class="kw">let </span>conn = <span class="self">self</span>.conn.upgrade_to_ref()<span class="question-mark">?</span>;
<a href=#354 id=354 data-nosnippet>354</a> <span class="prelude-val">Some</span>(Path::new_unchecked(conn, <span class="self">self</span>.id))
<a href=#355 id=355 data-nosnippet>355</a> }
<a href=#356 id=356 data-nosnippet>356</a>}
<a href=#357 id=357 data-nosnippet>357</a>
<a href=#358 id=358 data-nosnippet>358</a><span class="doccomment">/// Stream produced by [`Path::observed_external_addr`]
<a href=#359 id=359 data-nosnippet>359</a>///
<a href=#360 id=360 data-nosnippet>360</a>/// This will always return the external address most recently reported by the remote over this
<a href=#361 id=361 data-nosnippet>361</a>/// path. If the extension is not negotiated, this stream will never return.
<a href=#362 id=362 data-nosnippet>362</a></span><span class="comment">// TODO(@divma): provide a way to check if the extension is negotiated.
<a href=#363 id=363 data-nosnippet>363</a></span><span class="kw">pub struct </span>AddressDiscovery {
<a href=#364 id=364 data-nosnippet>364</a> watcher: WatchStream&lt;SocketAddr&gt;,
<a href=#365 id=365 data-nosnippet>365</a>}
<a href=#366 id=366 data-nosnippet>366</a>
<a href=#367 id=367 data-nosnippet>367</a><span class="kw">impl </span>AddressDiscovery {
<a href=#368 id=368 data-nosnippet>368</a> <span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">fn </span>new(
<a href=#369 id=369 data-nosnippet>369</a> path_id: PathId,
<a href=#370 id=370 data-nosnippet>370</a> <span class="kw-2">mut </span>path_events: tokio::sync::broadcast::Receiver&lt;PathEvent&gt;,
<a href=#371 id=371 data-nosnippet>371</a> initial_value: <span class="prelude-ty">Option</span>&lt;SocketAddr&gt;,
<a href=#372 id=372 data-nosnippet>372</a> runtime: Arc&lt;<span class="kw">dyn </span>Runtime&gt;,
<a href=#373 id=373 data-nosnippet>373</a> ) -&gt; <span class="self">Self </span>{
<a href=#374 id=374 data-nosnippet>374</a> <span class="kw">let </span>(tx, rx) = watch::channel(initial_value.unwrap_or_else(||
<a href=#375 id=375 data-nosnippet>375</a> <span class="comment">// if the dummy value is used, it will be ignored
<a href=#376 id=376 data-nosnippet>376</a> </span>SocketAddr::new([<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>].into(), <span class="number">0</span>)));
<a href=#377 id=377 data-nosnippet>377</a> <span class="kw">let </span>filter = <span class="kw">async move </span>{
<a href=#378 id=378 data-nosnippet>378</a> <span class="kw">loop </span>{
<a href=#379 id=379 data-nosnippet>379</a> <span class="kw">match </span>path_events.recv().<span class="kw">await </span>{
<a href=#380 id=380 data-nosnippet>380</a> <span class="prelude-val">Ok</span>(PathEvent::ObservedAddr { id, addr: observed }) <span class="kw">if </span>id == path_id =&gt; {
<a href=#381 id=381 data-nosnippet>381</a> tx.send_if_modified(|addr| {
<a href=#382 id=382 data-nosnippet>382</a> <span class="kw">let </span>old = std::mem::replace(addr, observed);
<a href=#383 id=383 data-nosnippet>383</a> old != <span class="kw-2">*</span>addr
<a href=#384 id=384 data-nosnippet>384</a> });
<a href=#385 id=385 data-nosnippet>385</a> }
<a href=#386 id=386 data-nosnippet>386</a> <span class="prelude-val">Ok</span>(PathEvent::Discarded { id, .. }) <span class="kw">if </span>id == path_id =&gt; {
<a href=#387 id=387 data-nosnippet>387</a> <span class="comment">// If the path is closed, terminate the stream
<a href=#388 id=388 data-nosnippet>388</a> </span><span class="kw">break</span>;
<a href=#389 id=389 data-nosnippet>389</a> }
<a href=#390 id=390 data-nosnippet>390</a> <span class="prelude-val">Ok</span>(<span class="kw">_</span>) =&gt; {
<a href=#391 id=391 data-nosnippet>391</a> <span class="comment">// ignore any other event
<a href=#392 id=392 data-nosnippet>392</a> </span>}
<a href=#393 id=393 data-nosnippet>393</a> <span class="prelude-val">Err</span>(<span class="kw">_</span>) =&gt; {
<a href=#394 id=394 data-nosnippet>394</a> <span class="comment">// A lagged error should never happen since this (detached) task is
<a href=#395 id=395 data-nosnippet>395</a> // constantly reading from the channel. Therefore, if an error does happen,
<a href=#396 id=396 data-nosnippet>396</a> // the stream can terminate
<a href=#397 id=397 data-nosnippet>397</a> </span><span class="kw">break</span>;
<a href=#398 id=398 data-nosnippet>398</a> }
<a href=#399 id=399 data-nosnippet>399</a> }
<a href=#400 id=400 data-nosnippet>400</a> }
<a href=#401 id=401 data-nosnippet>401</a> };
<a href=#402 id=402 data-nosnippet>402</a>
<a href=#403 id=403 data-nosnippet>403</a> <span class="kw">let </span>watcher = <span class="kw">if </span>initial_value.is_some() {
<a href=#404 id=404 data-nosnippet>404</a> WatchStream::new(rx)
<a href=#405 id=405 data-nosnippet>405</a> } <span class="kw">else </span>{
<a href=#406 id=406 data-nosnippet>406</a> WatchStream::from_changes(rx)
<a href=#407 id=407 data-nosnippet>407</a> };
<a href=#408 id=408 data-nosnippet>408</a>
<a href=#409 id=409 data-nosnippet>409</a> runtime.spawn(Box::pin(filter));
<a href=#410 id=410 data-nosnippet>410</a> <span class="comment">// TODO(@divma): check if there's a way to ensure the future ends. AbortHandle is not an
<a href=#411 id=411 data-nosnippet>411</a> // option
<a href=#412 id=412 data-nosnippet>412</a> </span><span class="self">Self </span>{ watcher }
<a href=#348 id=348 data-nosnippet>348</a>}
<a href=#349 id=349 data-nosnippet>349</a>
<a href=#350 id=350 data-nosnippet>350</a><span class="doccomment">/// Stream produced by [`Path::observed_external_addr`]
<a href=#351 id=351 data-nosnippet>351</a>///
<a href=#352 id=352 data-nosnippet>352</a>/// This will always return the external address most recently reported by the remote over this
<a href=#353 id=353 data-nosnippet>353</a>/// path. If the extension is not negotiated, this stream will never return.
<a href=#354 id=354 data-nosnippet>354</a></span><span class="comment">// TODO(@divma): provide a way to check if the extension is negotiated.
<a href=#355 id=355 data-nosnippet>355</a></span><span class="kw">pub struct </span>AddressDiscovery {
<a href=#356 id=356 data-nosnippet>356</a> watcher: WatchStream&lt;SocketAddr&gt;,
<a href=#357 id=357 data-nosnippet>357</a>}
<a href=#358 id=358 data-nosnippet>358</a>
<a href=#359 id=359 data-nosnippet>359</a><span class="kw">impl </span>AddressDiscovery {
<a href=#360 id=360 data-nosnippet>360</a> <span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">fn </span>new(
<a href=#361 id=361 data-nosnippet>361</a> path_id: PathId,
<a href=#362 id=362 data-nosnippet>362</a> <span class="kw-2">mut </span>path_events: tokio::sync::broadcast::Receiver&lt;PathEvent&gt;,
<a href=#363 id=363 data-nosnippet>363</a> initial_value: <span class="prelude-ty">Option</span>&lt;SocketAddr&gt;,
<a href=#364 id=364 data-nosnippet>364</a> runtime: Arc&lt;<span class="kw">dyn </span>Runtime&gt;,
<a href=#365 id=365 data-nosnippet>365</a> ) -&gt; <span class="self">Self </span>{
<a href=#366 id=366 data-nosnippet>366</a> <span class="kw">let </span>(tx, rx) = watch::channel(initial_value.unwrap_or_else(||
<a href=#367 id=367 data-nosnippet>367</a> <span class="comment">// if the dummy value is used, it will be ignored
<a href=#368 id=368 data-nosnippet>368</a> </span>SocketAddr::new([<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>].into(), <span class="number">0</span>)));
<a href=#369 id=369 data-nosnippet>369</a> <span class="kw">let </span>filter = <span class="kw">async move </span>{
<a href=#370 id=370 data-nosnippet>370</a> <span class="kw">loop </span>{
<a href=#371 id=371 data-nosnippet>371</a> <span class="kw">match </span>path_events.recv().<span class="kw">await </span>{
<a href=#372 id=372 data-nosnippet>372</a> <span class="prelude-val">Ok</span>(PathEvent::ObservedAddr { id, addr: observed }) <span class="kw">if </span>id == path_id =&gt; {
<a href=#373 id=373 data-nosnippet>373</a> tx.send_if_modified(|addr| {
<a href=#374 id=374 data-nosnippet>374</a> <span class="kw">let </span>old = std::mem::replace(addr, observed);
<a href=#375 id=375 data-nosnippet>375</a> old != <span class="kw-2">*</span>addr
<a href=#376 id=376 data-nosnippet>376</a> });
<a href=#377 id=377 data-nosnippet>377</a> }
<a href=#378 id=378 data-nosnippet>378</a> <span class="prelude-val">Ok</span>(PathEvent::Discarded { id, .. }) <span class="kw">if </span>id == path_id =&gt; {
<a href=#379 id=379 data-nosnippet>379</a> <span class="comment">// If the path is closed, terminate the stream
<a href=#380 id=380 data-nosnippet>380</a> </span><span class="kw">break</span>;
<a href=#381 id=381 data-nosnippet>381</a> }
<a href=#382 id=382 data-nosnippet>382</a> <span class="prelude-val">Ok</span>(<span class="kw">_</span>) =&gt; {
<a href=#383 id=383 data-nosnippet>383</a> <span class="comment">// ignore any other event
<a href=#384 id=384 data-nosnippet>384</a> </span>}
<a href=#385 id=385 data-nosnippet>385</a> <span class="prelude-val">Err</span>(<span class="kw">_</span>) =&gt; {
<a href=#386 id=386 data-nosnippet>386</a> <span class="comment">// A lagged error should never happen since this (detached) task is
<a href=#387 id=387 data-nosnippet>387</a> // constantly reading from the channel. Therefore, if an error does happen,
<a href=#388 id=388 data-nosnippet>388</a> // the stream can terminate
<a href=#389 id=389 data-nosnippet>389</a> </span><span class="kw">break</span>;
<a href=#390 id=390 data-nosnippet>390</a> }
<a href=#391 id=391 data-nosnippet>391</a> }
<a href=#392 id=392 data-nosnippet>392</a> }
<a href=#393 id=393 data-nosnippet>393</a> };
<a href=#394 id=394 data-nosnippet>394</a>
<a href=#395 id=395 data-nosnippet>395</a> <span class="kw">let </span>watcher = <span class="kw">if </span>initial_value.is_some() {
<a href=#396 id=396 data-nosnippet>396</a> WatchStream::new(rx)
<a href=#397 id=397 data-nosnippet>397</a> } <span class="kw">else </span>{
<a href=#398 id=398 data-nosnippet>398</a> WatchStream::from_changes(rx)
<a href=#399 id=399 data-nosnippet>399</a> };
<a href=#400 id=400 data-nosnippet>400</a>
<a href=#401 id=401 data-nosnippet>401</a> runtime.spawn(Box::pin(filter));
<a href=#402 id=402 data-nosnippet>402</a> <span class="comment">// TODO(@divma): check if there's a way to ensure the future ends. AbortHandle is not an
<a href=#403 id=403 data-nosnippet>403</a> // option
<a href=#404 id=404 data-nosnippet>404</a> </span><span class="self">Self </span>{ watcher }
<a href=#405 id=405 data-nosnippet>405</a> }
<a href=#406 id=406 data-nosnippet>406</a>}
<a href=#407 id=407 data-nosnippet>407</a>
<a href=#408 id=408 data-nosnippet>408</a><span class="kw">impl </span>Stream <span class="kw">for </span>AddressDiscovery {
<a href=#409 id=409 data-nosnippet>409</a> <span class="kw">type </span>Item = SocketAddr;
<a href=#410 id=410 data-nosnippet>410</a>
<a href=#411 id=411 data-nosnippet>411</a> <span class="kw">fn </span>poll_next(<span class="kw-2">mut </span><span class="self">self</span>: Pin&lt;<span class="kw-2">&amp;mut </span><span class="self">Self</span>&gt;, cx: <span class="kw-2">&amp;mut </span>Context&lt;<span class="lifetime">'_</span>&gt;) -&gt; Poll&lt;<span class="prelude-ty">Option</span>&lt;<span class="self">Self</span>::Item&gt;&gt; {
<a href=#412 id=412 data-nosnippet>412</a> Pin::new(<span class="kw-2">&amp;mut </span><span class="self">self</span>.watcher).poll_next(cx)
<a href=#413 id=413 data-nosnippet>413</a> }
<a href=#414 id=414 data-nosnippet>414</a>}
<a href=#415 id=415 data-nosnippet>415</a>
<a href=#416 id=416 data-nosnippet>416</a><span class="kw">impl </span>Stream <span class="kw">for </span>AddressDiscovery {
<a href=#417 id=417 data-nosnippet>417</a> <span class="kw">type </span>Item = SocketAddr;
<a href=#418 id=418 data-nosnippet>418</a>
<a href=#419 id=419 data-nosnippet>419</a> <span class="kw">fn </span>poll_next(<span class="kw-2">mut </span><span class="self">self</span>: Pin&lt;<span class="kw-2">&amp;mut </span><span class="self">Self</span>&gt;, cx: <span class="kw-2">&amp;mut </span>Context&lt;<span class="lifetime">'_</span>&gt;) -&gt; Poll&lt;<span class="prelude-ty">Option</span>&lt;<span class="self">Self</span>::Item&gt;&gt; {
<a href=#420 id=420 data-nosnippet>420</a> Pin::new(<span class="kw-2">&amp;mut </span><span class="self">self</span>.watcher).poll_next(cx)
<a href=#421 id=421 data-nosnippet>421</a> }
<a href=#422 id=422 data-nosnippet>422</a>}</code></pre></div></section></main></body></html>
<a href=#414 id=414 data-nosnippet>414</a>}</code></pre></div></section></main></body></html>
+14 -14
View File
@@ -268,12 +268,12 @@
<a href=#268 id=268 data-nosnippet>268</a> /// Discards unread data and notifies the peer to stop transmitting. Once stopped, further
<a href=#269 id=269 data-nosnippet>269</a> /// attempts to operate on a stream will yield `ClosedStream` errors.
<a href=#270 id=270 data-nosnippet>270</a> </span><span class="kw">pub fn </span>stop(<span class="kw-2">&amp;mut </span><span class="self">self</span>, error_code: VarInt) -&gt; <span class="prelude-ty">Result</span>&lt;(), ClosedStream&gt; {
<a href=#271 id=271 data-nosnippet>271</a> <span class="kw">let </span><span class="kw-2">mut </span>conn = <span class="self">self</span>.conn.state.lock(<span class="string">"RecvStream::stop"</span>);
<a href=#271 id=271 data-nosnippet>271</a> <span class="kw">let </span><span class="kw-2">mut </span>conn = <span class="self">self</span>.conn.lock_and_wake(<span class="string">"RecvStream::stop"</span>);
<a href=#272 id=272 data-nosnippet>272</a> <span class="kw">if </span><span class="self">self</span>.is_0rtt &amp;&amp; conn.check_0rtt().is_err() {
<a href=#273 id=273 data-nosnippet>273</a> <span class="kw">return </span><span class="prelude-val">Ok</span>(());
<a href=#274 id=274 data-nosnippet>274</a> }
<a href=#275 id=275 data-nosnippet>275</a> conn.inner.recv_stream(<span class="self">self</span>.stream).stop(error_code)<span class="question-mark">?</span>;
<a href=#276 id=276 data-nosnippet>276</a> conn.wake();
<a href=#273 id=273 data-nosnippet>273</a> conn.skip_waking();
<a href=#274 id=274 data-nosnippet>274</a> <span class="kw">return </span><span class="prelude-val">Ok</span>(());
<a href=#275 id=275 data-nosnippet>275</a> }
<a href=#276 id=276 data-nosnippet>276</a> conn.inner.recv_stream(<span class="self">self</span>.stream).stop(error_code)<span class="question-mark">?</span>;
<a href=#277 id=277 data-nosnippet>277</a> <span class="self">self</span>.all_data_read = <span class="bool-val">true</span>;
<a href=#278 id=278 data-nosnippet>278</a> <span class="prelude-val">Ok</span>(())
<a href=#279 id=279 data-nosnippet>279</a> }
@@ -301,7 +301,7 @@
<a href=#301 id=301 data-nosnippet>301</a> /// This operation is cancel-safe.
<a href=#302 id=302 data-nosnippet>302</a> </span><span class="kw">pub async fn </span>received_reset(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="prelude-ty">Option</span>&lt;VarInt&gt;, ResetError&gt; {
<a href=#303 id=303 data-nosnippet>303</a> poll_fn(|cx| {
<a href=#304 id=304 data-nosnippet>304</a> <span class="kw">let </span><span class="kw-2">mut </span>conn = <span class="self">self</span>.conn.state.lock(<span class="string">"RecvStream::reset"</span>);
<a href=#304 id=304 data-nosnippet>304</a> <span class="kw">let </span><span class="kw-2">mut </span>conn = <span class="self">self</span>.conn.lock_without_waking(<span class="string">"RecvStream::reset"</span>);
<a href=#305 id=305 data-nosnippet>305</a> <span class="kw">if </span><span class="self">self</span>.is_0rtt &amp;&amp; conn.check_0rtt().is_err() {
<a href=#306 id=306 data-nosnippet>306</a> <span class="kw">return </span>Poll::Ready(<span class="prelude-val">Err</span>(ResetError::ZeroRttRejected));
<a href=#307 id=307 data-nosnippet>307</a> }
@@ -354,7 +354,7 @@
<a href=#354 id=354 data-nosnippet>354</a> <span class="kw">return </span>Poll::Ready(<span class="prelude-val">Ok</span>(<span class="prelude-val">None</span>));
<a href=#355 id=355 data-nosnippet>355</a> }
<a href=#356 id=356 data-nosnippet>356</a>
<a href=#357 id=357 data-nosnippet>357</a> <span class="kw">let </span><span class="kw-2">mut </span>conn = <span class="self">self</span>.conn.state.lock(<span class="string">"RecvStream::poll_read"</span>);
<a href=#357 id=357 data-nosnippet>357</a> <span class="kw">let </span><span class="kw-2">mut </span>conn = <span class="self">self</span>.conn.lock_without_waking(<span class="string">"RecvStream::poll_read"</span>);
<a href=#358 id=358 data-nosnippet>358</a> <span class="kw">if </span><span class="self">self</span>.is_0rtt {
<a href=#359 id=359 data-nosnippet>359</a> conn.check_0rtt().map_err(|()| ReadError::ZeroRttRejected)<span class="question-mark">?</span>;
<a href=#360 id=360 data-nosnippet>360</a> }
@@ -581,18 +581,18 @@
<a href=#581 id=581 data-nosnippet>581</a>
<a href=#582 id=582 data-nosnippet>582</a><span class="kw">impl </span>Drop <span class="kw">for </span>RecvStream {
<a href=#583 id=583 data-nosnippet>583</a> <span class="kw">fn </span>drop(<span class="kw-2">&amp;mut </span><span class="self">self</span>) {
<a href=#584 id=584 data-nosnippet>584</a> <span class="kw">let </span><span class="kw-2">mut </span>conn = <span class="self">self</span>.conn.state.lock(<span class="string">"RecvStream::drop"</span>);
<a href=#584 id=584 data-nosnippet>584</a> <span class="kw">let </span><span class="kw-2">mut </span>conn = <span class="self">self</span>.conn.lock_and_wake(<span class="string">"RecvStream::drop"</span>);
<a href=#585 id=585 data-nosnippet>585</a>
<a href=#586 id=586 data-nosnippet>586</a> <span class="comment">// clean up any previously registered wakers
<a href=#587 id=587 data-nosnippet>587</a> </span>conn.blocked_readers.remove(<span class="kw-2">&amp;</span><span class="self">self</span>.stream);
<a href=#588 id=588 data-nosnippet>588</a>
<a href=#589 id=589 data-nosnippet>589</a> <span class="kw">if </span>conn.error.is_some() || (<span class="self">self</span>.is_0rtt &amp;&amp; conn.check_0rtt().is_err()) {
<a href=#590 id=590 data-nosnippet>590</a> <span class="kw">return</span>;
<a href=#591 id=591 data-nosnippet>591</a> }
<a href=#592 id=592 data-nosnippet>592</a> <span class="kw">if </span>!<span class="self">self</span>.all_data_read {
<a href=#593 id=593 data-nosnippet>593</a> <span class="comment">// Ignore ClosedStream errors
<a href=#594 id=594 data-nosnippet>594</a> </span><span class="kw">let _ </span>= conn.inner.recv_stream(<span class="self">self</span>.stream).stop(<span class="number">0u32</span>.into());
<a href=#595 id=595 data-nosnippet>595</a> conn.wake();
<a href=#590 id=590 data-nosnippet>590</a> conn.skip_waking();
<a href=#591 id=591 data-nosnippet>591</a> <span class="kw">return</span>;
<a href=#592 id=592 data-nosnippet>592</a> }
<a href=#593 id=593 data-nosnippet>593</a> <span class="kw">if </span>!<span class="self">self</span>.all_data_read {
<a href=#594 id=594 data-nosnippet>594</a> <span class="comment">// Ignore ClosedStream errors
<a href=#595 id=595 data-nosnippet>595</a> </span><span class="kw">let _ </span>= conn.inner.recv_stream(<span class="self">self</span>.stream).stop(<span class="number">0u32</span>.into());
<a href=#596 id=596 data-nosnippet>596</a> }
<a href=#597 id=597 data-nosnippet>597</a> }
<a href=#598 id=598 data-nosnippet>598</a>}
+329 -322
View File
@@ -145,338 +145,345 @@
<a href=#145 id=145 data-nosnippet>145</a> </span>F: FnOnce(<span class="kw-2">&amp;mut </span>proto::SendStream&lt;<span class="lifetime">'_</span>&gt;) -&gt; <span class="prelude-ty">Result</span>&lt;R, proto::WriteError&gt;,
<a href=#146 id=146 data-nosnippet>146</a> {
<a href=#147 id=147 data-nosnippet>147</a> <span class="kw">use </span>proto::WriteError::<span class="kw-2">*</span>;
<a href=#148 id=148 data-nosnippet>148</a> <span class="kw">let </span><span class="kw-2">mut </span>conn = <span class="self">self</span>.conn.state.lock(<span class="string">"SendStream::poll_write"</span>);
<a href=#149 id=149 data-nosnippet>149</a> <span class="kw">if </span><span class="self">self</span>.is_0rtt {
<a href=#150 id=150 data-nosnippet>150</a> conn.check_0rtt()
<a href=#151 id=151 data-nosnippet>151</a> .map_err(|()| WriteError::ZeroRttRejected)<span class="question-mark">?</span>;
<a href=#148 id=148 data-nosnippet>148</a> <span class="kw">let </span><span class="kw-2">mut </span>conn = <span class="self">self</span>.conn.lock_and_wake(<span class="string">"SendStream::poll_write"</span>);
<a href=#149 id=149 data-nosnippet>149</a> <span class="kw">if </span><span class="self">self</span>.is_0rtt &amp;&amp; conn.check_0rtt().is_err() {
<a href=#150 id=150 data-nosnippet>150</a> conn.skip_waking();
<a href=#151 id=151 data-nosnippet>151</a> <span class="kw">return </span>Poll::Ready(<span class="prelude-val">Err</span>(WriteError::ZeroRttRejected));
<a href=#152 id=152 data-nosnippet>152</a> }
<a href=#153 id=153 data-nosnippet>153</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(<span class="kw-2">ref </span>x) = conn.error {
<a href=#154 id=154 data-nosnippet>154</a> <span class="kw">return </span>Poll::Ready(<span class="prelude-val">Err</span>(WriteError::ConnectionLost(x.clone())));
<a href=#155 id=155 data-nosnippet>155</a> }
<a href=#156 id=156 data-nosnippet>156</a>
<a href=#157 id=157 data-nosnippet>157</a> <span class="kw">let </span>result = <span class="kw">match </span>write_fn(<span class="kw-2">&amp;mut </span>conn.inner.send_stream(<span class="self">self</span>.stream)) {
<a href=#158 id=158 data-nosnippet>158</a> <span class="prelude-val">Ok</span>(result) =&gt; result,
<a href=#159 id=159 data-nosnippet>159</a> <span class="prelude-val">Err</span>(Blocked) =&gt; {
<a href=#160 id=160 data-nosnippet>160</a> conn.blocked_writers.insert(<span class="self">self</span>.stream, cx.waker().clone());
<a href=#161 id=161 data-nosnippet>161</a> <span class="kw">return </span>Poll::Pending;
<a href=#162 id=162 data-nosnippet>162</a> }
<a href=#163 id=163 data-nosnippet>163</a> <span class="prelude-val">Err</span>(Stopped(error_code)) =&gt; {
<a href=#164 id=164 data-nosnippet>164</a> <span class="kw">return </span>Poll::Ready(<span class="prelude-val">Err</span>(WriteError::Stopped(error_code)));
<a href=#165 id=165 data-nosnippet>165</a> }
<a href=#166 id=166 data-nosnippet>166</a> <span class="prelude-val">Err</span>(ClosedStream) =&gt; {
<a href=#167 id=167 data-nosnippet>167</a> <span class="kw">return </span>Poll::Ready(<span class="prelude-val">Err</span>(WriteError::ClosedStream));
<a href=#153 id=153 data-nosnippet>153</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(conn_err) = conn.error.clone() {
<a href=#154 id=154 data-nosnippet>154</a> conn.skip_waking();
<a href=#155 id=155 data-nosnippet>155</a> <span class="kw">return </span>Poll::Ready(<span class="prelude-val">Err</span>(WriteError::ConnectionLost(conn_err)));
<a href=#156 id=156 data-nosnippet>156</a> }
<a href=#157 id=157 data-nosnippet>157</a>
<a href=#158 id=158 data-nosnippet>158</a> <span class="kw">let </span>result = <span class="kw">match </span>write_fn(<span class="kw-2">&amp;mut </span>conn.inner.send_stream(<span class="self">self</span>.stream)) {
<a href=#159 id=159 data-nosnippet>159</a> <span class="prelude-val">Ok</span>(result) =&gt; result,
<a href=#160 id=160 data-nosnippet>160</a> <span class="prelude-val">Err</span>(Blocked) =&gt; {
<a href=#161 id=161 data-nosnippet>161</a> conn.blocked_writers.insert(<span class="self">self</span>.stream, cx.waker().clone());
<a href=#162 id=162 data-nosnippet>162</a> conn.skip_waking();
<a href=#163 id=163 data-nosnippet>163</a> <span class="kw">return </span>Poll::Pending;
<a href=#164 id=164 data-nosnippet>164</a> }
<a href=#165 id=165 data-nosnippet>165</a> <span class="prelude-val">Err</span>(Stopped(error_code)) =&gt; {
<a href=#166 id=166 data-nosnippet>166</a> conn.skip_waking();
<a href=#167 id=167 data-nosnippet>167</a> <span class="kw">return </span>Poll::Ready(<span class="prelude-val">Err</span>(WriteError::Stopped(error_code)));
<a href=#168 id=168 data-nosnippet>168</a> }
<a href=#169 id=169 data-nosnippet>169</a> };
<a href=#170 id=170 data-nosnippet>170</a>
<a href=#171 id=171 data-nosnippet>171</a> conn.wake();
<a href=#172 id=172 data-nosnippet>172</a> Poll::Ready(<span class="prelude-val">Ok</span>(result))
<a href=#173 id=173 data-nosnippet>173</a> }
<a href=#169 id=169 data-nosnippet>169</a> <span class="prelude-val">Err</span>(ClosedStream) =&gt; {
<a href=#170 id=170 data-nosnippet>170</a> conn.skip_waking();
<a href=#171 id=171 data-nosnippet>171</a> <span class="kw">return </span>Poll::Ready(<span class="prelude-val">Err</span>(WriteError::ClosedStream));
<a href=#172 id=172 data-nosnippet>172</a> }
<a href=#173 id=173 data-nosnippet>173</a> };
<a href=#174 id=174 data-nosnippet>174</a>
<a href=#175 id=175 data-nosnippet>175</a> <span class="doccomment">/// Notify the peer that no more data will ever be written to this stream
<a href=#176 id=176 data-nosnippet>176</a> ///
<a href=#177 id=177 data-nosnippet>177</a> /// It is an error to write to a [`SendStream`] after `finish()`ing it. [`reset()`](Self::reset)
<a href=#178 id=178 data-nosnippet>178</a> /// may still be called after `finish` to abandon transmission of any stream data that might
<a href=#179 id=179 data-nosnippet>179</a> /// still be buffered.
<a href=#180 id=180 data-nosnippet>180</a> ///
<a href=#181 id=181 data-nosnippet>181</a> /// To wait for the peer to receive all buffered stream data, see [`stopped()`](Self::stopped).
<a href=#182 id=182 data-nosnippet>182</a> ///
<a href=#183 id=183 data-nosnippet>183</a> /// May fail if [`finish()`](Self::finish) or [`reset()`](Self::reset) was previously
<a href=#184 id=184 data-nosnippet>184</a> /// called. This error is harmless and serves only to indicate that the caller may have
<a href=#185 id=185 data-nosnippet>185</a> /// incorrect assumptions about the stream's state.
<a href=#186 id=186 data-nosnippet>186</a> </span><span class="kw">pub fn </span>finish(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;(), ClosedStream&gt; {
<a href=#187 id=187 data-nosnippet>187</a> <span class="kw">let </span><span class="kw-2">mut </span>conn = <span class="self">self</span>.conn.state.lock(<span class="string">"finish"</span>);
<a href=#188 id=188 data-nosnippet>188</a> <span class="kw">match </span>conn.inner.send_stream(<span class="self">self</span>.stream).finish() {
<a href=#189 id=189 data-nosnippet>189</a> <span class="prelude-val">Ok</span>(()) =&gt; {
<a href=#190 id=190 data-nosnippet>190</a> conn.wake();
<a href=#191 id=191 data-nosnippet>191</a> <span class="prelude-val">Ok</span>(())
<a href=#192 id=192 data-nosnippet>192</a> }
<a href=#193 id=193 data-nosnippet>193</a> <span class="prelude-val">Err</span>(FinishError::ClosedStream) =&gt; <span class="prelude-val">Err</span>(ClosedStream::default()),
<a href=#194 id=194 data-nosnippet>194</a> <span class="comment">// Harmless. If the application needs to know about stopped streams at this point, it
<a href=#195 id=195 data-nosnippet>195</a> // should call `stopped`.
<a href=#196 id=196 data-nosnippet>196</a> </span><span class="prelude-val">Err</span>(FinishError::Stopped(<span class="kw">_</span>)) =&gt; <span class="prelude-val">Ok</span>(()),
<a href=#197 id=197 data-nosnippet>197</a> }
<a href=#198 id=198 data-nosnippet>198</a> }
<a href=#199 id=199 data-nosnippet>199</a>
<a href=#200 id=200 data-nosnippet>200</a> <span class="doccomment">/// Close the send stream immediately.
<a href=#201 id=201 data-nosnippet>201</a> ///
<a href=#202 id=202 data-nosnippet>202</a> /// No new data can be written after calling this method. Locally buffered data is dropped, and
<a href=#203 id=203 data-nosnippet>203</a> /// previously transmitted data will no longer be retransmitted if lost. If an attempt has
<a href=#204 id=204 data-nosnippet>204</a> /// already been made to finish the stream, the peer may still receive all written data.
<a href=#175 id=175 data-nosnippet>175</a> Poll::Ready(<span class="prelude-val">Ok</span>(result))
<a href=#176 id=176 data-nosnippet>176</a> }
<a href=#177 id=177 data-nosnippet>177</a>
<a href=#178 id=178 data-nosnippet>178</a> <span class="doccomment">/// Notify the peer that no more data will ever be written to this stream
<a href=#179 id=179 data-nosnippet>179</a> ///
<a href=#180 id=180 data-nosnippet>180</a> /// It is an error to write to a [`SendStream`] after `finish()`ing it. [`reset()`](Self::reset)
<a href=#181 id=181 data-nosnippet>181</a> /// may still be called after `finish` to abandon transmission of any stream data that might
<a href=#182 id=182 data-nosnippet>182</a> /// still be buffered.
<a href=#183 id=183 data-nosnippet>183</a> ///
<a href=#184 id=184 data-nosnippet>184</a> /// To wait for the peer to receive all buffered stream data, see [`stopped()`](Self::stopped).
<a href=#185 id=185 data-nosnippet>185</a> ///
<a href=#186 id=186 data-nosnippet>186</a> /// May fail if [`finish()`](Self::finish) or [`reset()`](Self::reset) was previously
<a href=#187 id=187 data-nosnippet>187</a> /// called. This error is harmless and serves only to indicate that the caller may have
<a href=#188 id=188 data-nosnippet>188</a> /// incorrect assumptions about the stream's state.
<a href=#189 id=189 data-nosnippet>189</a> </span><span class="kw">pub fn </span>finish(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;(), ClosedStream&gt; {
<a href=#190 id=190 data-nosnippet>190</a> <span class="kw">let </span><span class="kw-2">mut </span>conn = <span class="self">self</span>.conn.lock_and_wake(<span class="string">"finish"</span>);
<a href=#191 id=191 data-nosnippet>191</a> <span class="kw">if let </span><span class="prelude-val">Err</span>(e) = conn.inner.send_stream(<span class="self">self</span>.stream).finish() {
<a href=#192 id=192 data-nosnippet>192</a> conn.skip_waking();
<a href=#193 id=193 data-nosnippet>193</a> <span class="kw">match </span>e {
<a href=#194 id=194 data-nosnippet>194</a> FinishError::ClosedStream =&gt; <span class="prelude-val">Err</span>(ClosedStream::default()),
<a href=#195 id=195 data-nosnippet>195</a> <span class="comment">// Harmless. If the application needs to know about stopped streams at this point, it
<a href=#196 id=196 data-nosnippet>196</a> // should call `stopped`.
<a href=#197 id=197 data-nosnippet>197</a> </span>FinishError::Stopped(<span class="kw">_</span>) =&gt; <span class="prelude-val">Ok</span>(()),
<a href=#198 id=198 data-nosnippet>198</a> }
<a href=#199 id=199 data-nosnippet>199</a> } <span class="kw">else </span>{
<a href=#200 id=200 data-nosnippet>200</a> <span class="prelude-val">Ok</span>(())
<a href=#201 id=201 data-nosnippet>201</a> }
<a href=#202 id=202 data-nosnippet>202</a> }
<a href=#203 id=203 data-nosnippet>203</a>
<a href=#204 id=204 data-nosnippet>204</a> <span class="doccomment">/// Close the send stream immediately.
<a href=#205 id=205 data-nosnippet>205</a> ///
<a href=#206 id=206 data-nosnippet>206</a> /// May fail if [`finish()`](Self::finish) or [`reset()`](Self::reset) was previously
<a href=#207 id=207 data-nosnippet>207</a> /// called. This error is harmless and serves only to indicate that the caller may have
<a href=#208 id=208 data-nosnippet>208</a> /// incorrect assumptions about the stream's state.
<a href=#209 id=209 data-nosnippet>209</a> </span><span class="kw">pub fn </span>reset(<span class="kw-2">&amp;mut </span><span class="self">self</span>, error_code: VarInt) -&gt; <span class="prelude-ty">Result</span>&lt;(), ClosedStream&gt; {
<a href=#210 id=210 data-nosnippet>210</a> <span class="kw">let </span><span class="kw-2">mut </span>conn = <span class="self">self</span>.conn.state.lock(<span class="string">"SendStream::reset"</span>);
<a href=#211 id=211 data-nosnippet>211</a> <span class="kw">if </span><span class="self">self</span>.is_0rtt &amp;&amp; conn.check_0rtt().is_err() {
<a href=#212 id=212 data-nosnippet>212</a> <span class="kw">return </span><span class="prelude-val">Ok</span>(());
<a href=#213 id=213 data-nosnippet>213</a> }
<a href=#214 id=214 data-nosnippet>214</a> conn.inner.send_stream(<span class="self">self</span>.stream).reset(error_code)<span class="question-mark">?</span>;
<a href=#215 id=215 data-nosnippet>215</a> conn.wake();
<a href=#216 id=216 data-nosnippet>216</a> <span class="prelude-val">Ok</span>(())
<a href=#217 id=217 data-nosnippet>217</a> }
<a href=#218 id=218 data-nosnippet>218</a>
<a href=#219 id=219 data-nosnippet>219</a> <span class="doccomment">/// Set the priority of the send stream
<a href=#220 id=220 data-nosnippet>220</a> ///
<a href=#221 id=221 data-nosnippet>221</a> /// Every send stream has an initial priority of 0. Locally buffered data from streams with
<a href=#222 id=222 data-nosnippet>222</a> /// higher priority will be transmitted before data from streams with lower priority. Changing
<a href=#223 id=223 data-nosnippet>223</a> /// the priority of a stream with pending data may only take effect after that data has been
<a href=#224 id=224 data-nosnippet>224</a> /// transmitted. Using many different priority levels per connection may have a negative
<a href=#225 id=225 data-nosnippet>225</a> /// impact on performance.
<a href=#226 id=226 data-nosnippet>226</a> </span><span class="kw">pub fn </span>set_priority(<span class="kw-2">&amp;</span><span class="self">self</span>, priority: i32) -&gt; <span class="prelude-ty">Result</span>&lt;(), ClosedStream&gt; {
<a href=#227 id=227 data-nosnippet>227</a> <span class="kw">let </span><span class="kw-2">mut </span>conn = <span class="self">self</span>.conn.state.lock(<span class="string">"SendStream::set_priority"</span>);
<a href=#228 id=228 data-nosnippet>228</a> conn.inner.send_stream(<span class="self">self</span>.stream).set_priority(priority)<span class="question-mark">?</span>;
<a href=#229 id=229 data-nosnippet>229</a> <span class="prelude-val">Ok</span>(())
<a href=#230 id=230 data-nosnippet>230</a> }
<a href=#231 id=231 data-nosnippet>231</a>
<a href=#232 id=232 data-nosnippet>232</a> <span class="doccomment">/// Get the priority of the send stream
<a href=#233 id=233 data-nosnippet>233</a> </span><span class="kw">pub fn </span>priority(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;i32, ClosedStream&gt; {
<a href=#234 id=234 data-nosnippet>234</a> <span class="kw">let </span><span class="kw-2">mut </span>conn = <span class="self">self</span>.conn.state.lock(<span class="string">"SendStream::priority"</span>);
<a href=#235 id=235 data-nosnippet>235</a> conn.inner.send_stream(<span class="self">self</span>.stream).priority()
<a href=#236 id=236 data-nosnippet>236</a> }
<a href=#237 id=237 data-nosnippet>237</a>
<a href=#238 id=238 data-nosnippet>238</a> <span class="doccomment">/// Completes when the peer stops the stream or reads the stream to completion
<a href=#239 id=239 data-nosnippet>239</a> ///
<a href=#240 id=240 data-nosnippet>240</a> /// Yields `Some` with the stop error code if the peer stops the stream. Yields `None` if the
<a href=#241 id=241 data-nosnippet>241</a> /// local side [`finish()`](Self::finish)es the stream and then the peer acknowledges receipt
<a href=#242 id=242 data-nosnippet>242</a> /// of all stream data (although not necessarily the processing of it), after which the peer
<a href=#243 id=243 data-nosnippet>243</a> /// closing the stream is no longer meaningful.
<a href=#244 id=244 data-nosnippet>244</a> ///
<a href=#245 id=245 data-nosnippet>245</a> /// For a variety of reasons, the peer may not send acknowledgements immediately upon receiving
<a href=#246 id=246 data-nosnippet>246</a> /// data. As such, relying on `stopped` to know when the peer has read a stream to completion
<a href=#247 id=247 data-nosnippet>247</a> /// may introduce more latency than using an application-level response of some sort.
<a href=#248 id=248 data-nosnippet>248</a> </span><span class="kw">pub fn </span>stopped(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; Stopped {
<a href=#249 id=249 data-nosnippet>249</a> <span class="kw">let </span>notified = {
<a href=#250 id=250 data-nosnippet>250</a> <span class="comment">// Create an `OwnedNotified` to move into the future. By creating it before the first poll,
<a href=#251 id=251 data-nosnippet>251</a> // we make sure that we don't miss any notifications.
<a href=#252 id=252 data-nosnippet>252</a> </span><span class="kw">let </span><span class="kw-2">mut </span>conn = <span class="self">self</span>.conn.state.lock(<span class="string">"SendStream::stopped"</span>);
<a href=#253 id=253 data-nosnippet>253</a> conn.stopped
<a href=#254 id=254 data-nosnippet>254</a> .entry(<span class="self">self</span>.stream)
<a href=#255 id=255 data-nosnippet>255</a> .or_default()
<a href=#256 id=256 data-nosnippet>256</a> .clone()
<a href=#257 id=257 data-nosnippet>257</a> .notified_owned()
<a href=#258 id=258 data-nosnippet>258</a> };
<a href=#259 id=259 data-nosnippet>259</a> Stopped {
<a href=#260 id=260 data-nosnippet>260</a> conn: <span class="self">self</span>.conn.clone(),
<a href=#261 id=261 data-nosnippet>261</a> stream: <span class="self">self</span>.stream,
<a href=#262 id=262 data-nosnippet>262</a> is_0rtt: <span class="self">self</span>.is_0rtt,
<a href=#263 id=263 data-nosnippet>263</a> notified,
<a href=#264 id=264 data-nosnippet>264</a> }
<a href=#265 id=265 data-nosnippet>265</a> }
<a href=#266 id=266 data-nosnippet>266</a>
<a href=#267 id=267 data-nosnippet>267</a> <span class="doccomment">/// Get the identity of this stream
<a href=#268 id=268 data-nosnippet>268</a> </span><span class="kw">pub fn </span>id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; StreamId {
<a href=#269 id=269 data-nosnippet>269</a> <span class="self">self</span>.stream
<a href=#270 id=270 data-nosnippet>270</a> }
<a href=#271 id=271 data-nosnippet>271</a>
<a href=#272 id=272 data-nosnippet>272</a> <span class="doccomment">/// Attempt to write bytes from buf into the stream.
<a href=#273 id=273 data-nosnippet>273</a> ///
<a href=#274 id=274 data-nosnippet>274</a> /// On success, returns Poll::Ready(Ok(num_bytes_written)).
<a href=#275 id=275 data-nosnippet>275</a> ///
<a href=#276 id=276 data-nosnippet>276</a> /// If the stream is not ready for writing, the method returns Poll::Pending and arranges
<a href=#277 id=277 data-nosnippet>277</a> /// for the current task (via cx.waker().wake_by_ref()) to receive a notification when the
<a href=#278 id=278 data-nosnippet>278</a> /// stream becomes writable or is closed.
<a href=#279 id=279 data-nosnippet>279</a> </span><span class="kw">pub fn </span>poll_write(
<a href=#280 id=280 data-nosnippet>280</a> <span class="self">self</span>: Pin&lt;<span class="kw-2">&amp;mut </span><span class="self">Self</span>&gt;,
<a href=#281 id=281 data-nosnippet>281</a> cx: <span class="kw-2">&amp;mut </span>Context&lt;<span class="lifetime">'_</span>&gt;,
<a href=#282 id=282 data-nosnippet>282</a> buf: <span class="kw-2">&amp;</span>[u8],
<a href=#283 id=283 data-nosnippet>283</a> ) -&gt; Poll&lt;<span class="prelude-ty">Result</span>&lt;usize, WriteError&gt;&gt; {
<a href=#284 id=284 data-nosnippet>284</a> <span class="macro">pin!</span>(<span class="self">self</span>.get_mut().write(buf)).as_mut().poll(cx)
<a href=#285 id=285 data-nosnippet>285</a> }
<a href=#286 id=286 data-nosnippet>286</a>}
<a href=#287 id=287 data-nosnippet>287</a>
<a href=#288 id=288 data-nosnippet>288</a><span class="doccomment">/// Check if a send stream is stopped.
<a href=#289 id=289 data-nosnippet>289</a>///
<a href=#290 id=290 data-nosnippet>290</a>/// Returns `Some` if the stream is stopped or the connection is closed.
<a href=#291 id=291 data-nosnippet>291</a>/// Returns `None` if the stream is not stopped.
<a href=#292 id=292 data-nosnippet>292</a></span><span class="kw">fn </span>send_stream_stopped(
<a href=#293 id=293 data-nosnippet>293</a> conn: <span class="kw-2">&amp;mut </span>State,
<a href=#294 id=294 data-nosnippet>294</a> stream: StreamId,
<a href=#295 id=295 data-nosnippet>295</a> is_0rtt: bool,
<a href=#296 id=296 data-nosnippet>296</a>) -&gt; <span class="prelude-ty">Option</span>&lt;<span class="prelude-ty">Result</span>&lt;<span class="prelude-ty">Option</span>&lt;VarInt&gt;, StoppedError&gt;&gt; {
<a href=#297 id=297 data-nosnippet>297</a> <span class="kw">if </span>is_0rtt &amp;&amp; conn.check_0rtt().is_err() {
<a href=#298 id=298 data-nosnippet>298</a> <span class="kw">return </span><span class="prelude-val">Some</span>(<span class="prelude-val">Err</span>(StoppedError::ZeroRttRejected));
<a href=#299 id=299 data-nosnippet>299</a> }
<a href=#300 id=300 data-nosnippet>300</a> <span class="kw">match </span>conn.inner.send_stream(stream).stopped() {
<a href=#301 id=301 data-nosnippet>301</a> <span class="prelude-val">Err</span>(ClosedStream { .. }) =&gt; <span class="prelude-val">Some</span>(<span class="prelude-val">Ok</span>(<span class="prelude-val">None</span>)),
<a href=#302 id=302 data-nosnippet>302</a> <span class="prelude-val">Ok</span>(<span class="prelude-val">Some</span>(error_code)) =&gt; <span class="prelude-val">Some</span>(<span class="prelude-val">Ok</span>(<span class="prelude-val">Some</span>(error_code))),
<a href=#303 id=303 data-nosnippet>303</a> <span class="prelude-val">Ok</span>(<span class="prelude-val">None</span>) =&gt; conn.error.clone().map(|error| <span class="prelude-val">Err</span>(error.into())),
<a href=#304 id=304 data-nosnippet>304</a> }
<a href=#305 id=305 data-nosnippet>305</a>}
<a href=#306 id=306 data-nosnippet>306</a>
<a href=#307 id=307 data-nosnippet>307</a><span class="attr">#[cfg(feature = <span class="string">"futures-io"</span>)]
<a href=#308 id=308 data-nosnippet>308</a></span><span class="kw">impl </span>futures_io::AsyncWrite <span class="kw">for </span>SendStream {
<a href=#309 id=309 data-nosnippet>309</a> <span class="kw">fn </span>poll_write(
<a href=#310 id=310 data-nosnippet>310</a> <span class="self">self</span>: Pin&lt;<span class="kw-2">&amp;mut </span><span class="self">Self</span>&gt;,
<a href=#311 id=311 data-nosnippet>311</a> cx: <span class="kw-2">&amp;mut </span>Context&lt;<span class="lifetime">'_</span>&gt;,
<a href=#312 id=312 data-nosnippet>312</a> buf: <span class="kw-2">&amp;</span>[u8],
<a href=#313 id=313 data-nosnippet>313</a> ) -&gt; Poll&lt;io::Result&lt;usize&gt;&gt; {
<a href=#314 id=314 data-nosnippet>314</a> <span class="self">self</span>.poll_write(cx, buf).map_err(Into::into)
<a href=#315 id=315 data-nosnippet>315</a> }
<a href=#316 id=316 data-nosnippet>316</a>
<a href=#317 id=317 data-nosnippet>317</a> <span class="kw">fn </span>poll_flush(<span class="self">self</span>: Pin&lt;<span class="kw-2">&amp;mut </span><span class="self">Self</span>&gt;, _cx: <span class="kw-2">&amp;mut </span>Context&lt;<span class="lifetime">'_</span>&gt;) -&gt; Poll&lt;io::Result&lt;()&gt;&gt; {
<a href=#318 id=318 data-nosnippet>318</a> Poll::Ready(<span class="prelude-val">Ok</span>(()))
<a href=#206 id=206 data-nosnippet>206</a> /// No new data can be written after calling this method. Locally buffered data is dropped, and
<a href=#207 id=207 data-nosnippet>207</a> /// previously transmitted data will no longer be retransmitted if lost. If an attempt has
<a href=#208 id=208 data-nosnippet>208</a> /// already been made to finish the stream, the peer may still receive all written data.
<a href=#209 id=209 data-nosnippet>209</a> ///
<a href=#210 id=210 data-nosnippet>210</a> /// May fail if [`finish()`](Self::finish) or [`reset()`](Self::reset) was previously
<a href=#211 id=211 data-nosnippet>211</a> /// called. This error is harmless and serves only to indicate that the caller may have
<a href=#212 id=212 data-nosnippet>212</a> /// incorrect assumptions about the stream's state.
<a href=#213 id=213 data-nosnippet>213</a> </span><span class="kw">pub fn </span>reset(<span class="kw-2">&amp;mut </span><span class="self">self</span>, error_code: VarInt) -&gt; <span class="prelude-ty">Result</span>&lt;(), ClosedStream&gt; {
<a href=#214 id=214 data-nosnippet>214</a> <span class="kw">let </span><span class="kw-2">mut </span>conn = <span class="self">self</span>.conn.lock_and_wake(<span class="string">"SendStream::reset"</span>);
<a href=#215 id=215 data-nosnippet>215</a> <span class="kw">if </span><span class="self">self</span>.is_0rtt &amp;&amp; conn.check_0rtt().is_err() {
<a href=#216 id=216 data-nosnippet>216</a> conn.skip_waking();
<a href=#217 id=217 data-nosnippet>217</a> <span class="kw">return </span><span class="prelude-val">Ok</span>(());
<a href=#218 id=218 data-nosnippet>218</a> }
<a href=#219 id=219 data-nosnippet>219</a> conn.inner.send_stream(<span class="self">self</span>.stream).reset(error_code)<span class="question-mark">?</span>;
<a href=#220 id=220 data-nosnippet>220</a> <span class="prelude-val">Ok</span>(())
<a href=#221 id=221 data-nosnippet>221</a> }
<a href=#222 id=222 data-nosnippet>222</a>
<a href=#223 id=223 data-nosnippet>223</a> <span class="doccomment">/// Set the priority of the send stream
<a href=#224 id=224 data-nosnippet>224</a> ///
<a href=#225 id=225 data-nosnippet>225</a> /// Every send stream has an initial priority of 0. Locally buffered data from streams with
<a href=#226 id=226 data-nosnippet>226</a> /// higher priority will be transmitted before data from streams with lower priority. Changing
<a href=#227 id=227 data-nosnippet>227</a> /// the priority of a stream with pending data may only take effect after that data has been
<a href=#228 id=228 data-nosnippet>228</a> /// transmitted. Using many different priority levels per connection may have a negative
<a href=#229 id=229 data-nosnippet>229</a> /// impact on performance.
<a href=#230 id=230 data-nosnippet>230</a> </span><span class="kw">pub fn </span>set_priority(<span class="kw-2">&amp;</span><span class="self">self</span>, priority: i32) -&gt; <span class="prelude-ty">Result</span>&lt;(), ClosedStream&gt; {
<a href=#231 id=231 data-nosnippet>231</a> <span class="kw">let </span><span class="kw-2">mut </span>conn = <span class="self">self</span>.conn.lock_without_waking(<span class="string">"SendStream::set_priority"</span>);
<a href=#232 id=232 data-nosnippet>232</a> conn.inner.send_stream(<span class="self">self</span>.stream).set_priority(priority)<span class="question-mark">?</span>;
<a href=#233 id=233 data-nosnippet>233</a> <span class="prelude-val">Ok</span>(())
<a href=#234 id=234 data-nosnippet>234</a> }
<a href=#235 id=235 data-nosnippet>235</a>
<a href=#236 id=236 data-nosnippet>236</a> <span class="doccomment">/// Get the priority of the send stream
<a href=#237 id=237 data-nosnippet>237</a> </span><span class="kw">pub fn </span>priority(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;i32, ClosedStream&gt; {
<a href=#238 id=238 data-nosnippet>238</a> <span class="kw">let </span><span class="kw-2">mut </span>conn = <span class="self">self</span>.conn.lock_without_waking(<span class="string">"SendStream::priority"</span>);
<a href=#239 id=239 data-nosnippet>239</a> conn.inner.send_stream(<span class="self">self</span>.stream).priority()
<a href=#240 id=240 data-nosnippet>240</a> }
<a href=#241 id=241 data-nosnippet>241</a>
<a href=#242 id=242 data-nosnippet>242</a> <span class="doccomment">/// Completes when the peer stops the stream or reads the stream to completion
<a href=#243 id=243 data-nosnippet>243</a> ///
<a href=#244 id=244 data-nosnippet>244</a> /// Yields `Some` with the stop error code if the peer stops the stream. Yields `None` if the
<a href=#245 id=245 data-nosnippet>245</a> /// local side [`finish()`](Self::finish)es the stream and then the peer acknowledges receipt
<a href=#246 id=246 data-nosnippet>246</a> /// of all stream data (although not necessarily the processing of it), after which the peer
<a href=#247 id=247 data-nosnippet>247</a> /// closing the stream is no longer meaningful.
<a href=#248 id=248 data-nosnippet>248</a> ///
<a href=#249 id=249 data-nosnippet>249</a> /// For a variety of reasons, the peer may not send acknowledgements immediately upon receiving
<a href=#250 id=250 data-nosnippet>250</a> /// data. As such, relying on `stopped` to know when the peer has read a stream to completion
<a href=#251 id=251 data-nosnippet>251</a> /// may introduce more latency than using an application-level response of some sort.
<a href=#252 id=252 data-nosnippet>252</a> </span><span class="kw">pub fn </span>stopped(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; Stopped {
<a href=#253 id=253 data-nosnippet>253</a> <span class="kw">let </span>notified = {
<a href=#254 id=254 data-nosnippet>254</a> <span class="comment">// Create an `OwnedNotified` to move into the future. By creating it before the first poll,
<a href=#255 id=255 data-nosnippet>255</a> // we make sure that we don't miss any notifications.
<a href=#256 id=256 data-nosnippet>256</a> </span><span class="kw">let </span><span class="kw-2">mut </span>conn = <span class="self">self</span>.conn.lock_without_waking(<span class="string">"SendStream::stopped"</span>);
<a href=#257 id=257 data-nosnippet>257</a> conn.stopped
<a href=#258 id=258 data-nosnippet>258</a> .entry(<span class="self">self</span>.stream)
<a href=#259 id=259 data-nosnippet>259</a> .or_default()
<a href=#260 id=260 data-nosnippet>260</a> .clone()
<a href=#261 id=261 data-nosnippet>261</a> .notified_owned()
<a href=#262 id=262 data-nosnippet>262</a> };
<a href=#263 id=263 data-nosnippet>263</a> Stopped {
<a href=#264 id=264 data-nosnippet>264</a> conn: <span class="self">self</span>.conn.clone(),
<a href=#265 id=265 data-nosnippet>265</a> stream: <span class="self">self</span>.stream,
<a href=#266 id=266 data-nosnippet>266</a> is_0rtt: <span class="self">self</span>.is_0rtt,
<a href=#267 id=267 data-nosnippet>267</a> notified,
<a href=#268 id=268 data-nosnippet>268</a> }
<a href=#269 id=269 data-nosnippet>269</a> }
<a href=#270 id=270 data-nosnippet>270</a>
<a href=#271 id=271 data-nosnippet>271</a> <span class="doccomment">/// Get the identity of this stream
<a href=#272 id=272 data-nosnippet>272</a> </span><span class="kw">pub fn </span>id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; StreamId {
<a href=#273 id=273 data-nosnippet>273</a> <span class="self">self</span>.stream
<a href=#274 id=274 data-nosnippet>274</a> }
<a href=#275 id=275 data-nosnippet>275</a>
<a href=#276 id=276 data-nosnippet>276</a> <span class="doccomment">/// Attempt to write bytes from buf into the stream.
<a href=#277 id=277 data-nosnippet>277</a> ///
<a href=#278 id=278 data-nosnippet>278</a> /// On success, returns Poll::Ready(Ok(num_bytes_written)).
<a href=#279 id=279 data-nosnippet>279</a> ///
<a href=#280 id=280 data-nosnippet>280</a> /// If the stream is not ready for writing, the method returns Poll::Pending and arranges
<a href=#281 id=281 data-nosnippet>281</a> /// for the current task (via cx.waker().wake_by_ref()) to receive a notification when the
<a href=#282 id=282 data-nosnippet>282</a> /// stream becomes writable or is closed.
<a href=#283 id=283 data-nosnippet>283</a> </span><span class="kw">pub fn </span>poll_write(
<a href=#284 id=284 data-nosnippet>284</a> <span class="self">self</span>: Pin&lt;<span class="kw-2">&amp;mut </span><span class="self">Self</span>&gt;,
<a href=#285 id=285 data-nosnippet>285</a> cx: <span class="kw-2">&amp;mut </span>Context&lt;<span class="lifetime">'_</span>&gt;,
<a href=#286 id=286 data-nosnippet>286</a> buf: <span class="kw-2">&amp;</span>[u8],
<a href=#287 id=287 data-nosnippet>287</a> ) -&gt; Poll&lt;<span class="prelude-ty">Result</span>&lt;usize, WriteError&gt;&gt; {
<a href=#288 id=288 data-nosnippet>288</a> <span class="macro">pin!</span>(<span class="self">self</span>.get_mut().write(buf)).as_mut().poll(cx)
<a href=#289 id=289 data-nosnippet>289</a> }
<a href=#290 id=290 data-nosnippet>290</a>}
<a href=#291 id=291 data-nosnippet>291</a>
<a href=#292 id=292 data-nosnippet>292</a><span class="doccomment">/// Check if a send stream is stopped.
<a href=#293 id=293 data-nosnippet>293</a>///
<a href=#294 id=294 data-nosnippet>294</a>/// Returns `Some` if the stream is stopped or the connection is closed.
<a href=#295 id=295 data-nosnippet>295</a>/// Returns `None` if the stream is not stopped.
<a href=#296 id=296 data-nosnippet>296</a></span><span class="kw">fn </span>send_stream_stopped(
<a href=#297 id=297 data-nosnippet>297</a> conn: <span class="kw-2">&amp;mut </span>State,
<a href=#298 id=298 data-nosnippet>298</a> stream: StreamId,
<a href=#299 id=299 data-nosnippet>299</a> is_0rtt: bool,
<a href=#300 id=300 data-nosnippet>300</a>) -&gt; <span class="prelude-ty">Option</span>&lt;<span class="prelude-ty">Result</span>&lt;<span class="prelude-ty">Option</span>&lt;VarInt&gt;, StoppedError&gt;&gt; {
<a href=#301 id=301 data-nosnippet>301</a> <span class="kw">if </span>is_0rtt &amp;&amp; conn.check_0rtt().is_err() {
<a href=#302 id=302 data-nosnippet>302</a> <span class="kw">return </span><span class="prelude-val">Some</span>(<span class="prelude-val">Err</span>(StoppedError::ZeroRttRejected));
<a href=#303 id=303 data-nosnippet>303</a> }
<a href=#304 id=304 data-nosnippet>304</a> <span class="kw">match </span>conn.inner.send_stream(stream).stopped() {
<a href=#305 id=305 data-nosnippet>305</a> <span class="prelude-val">Err</span>(ClosedStream { .. }) =&gt; <span class="prelude-val">Some</span>(<span class="prelude-val">Ok</span>(<span class="prelude-val">None</span>)),
<a href=#306 id=306 data-nosnippet>306</a> <span class="prelude-val">Ok</span>(<span class="prelude-val">Some</span>(error_code)) =&gt; <span class="prelude-val">Some</span>(<span class="prelude-val">Ok</span>(<span class="prelude-val">Some</span>(error_code))),
<a href=#307 id=307 data-nosnippet>307</a> <span class="prelude-val">Ok</span>(<span class="prelude-val">None</span>) =&gt; conn.error.clone().map(|error| <span class="prelude-val">Err</span>(error.into())),
<a href=#308 id=308 data-nosnippet>308</a> }
<a href=#309 id=309 data-nosnippet>309</a>}
<a href=#310 id=310 data-nosnippet>310</a>
<a href=#311 id=311 data-nosnippet>311</a><span class="attr">#[cfg(feature = <span class="string">"futures-io"</span>)]
<a href=#312 id=312 data-nosnippet>312</a></span><span class="kw">impl </span>futures_io::AsyncWrite <span class="kw">for </span>SendStream {
<a href=#313 id=313 data-nosnippet>313</a> <span class="kw">fn </span>poll_write(
<a href=#314 id=314 data-nosnippet>314</a> <span class="self">self</span>: Pin&lt;<span class="kw-2">&amp;mut </span><span class="self">Self</span>&gt;,
<a href=#315 id=315 data-nosnippet>315</a> cx: <span class="kw-2">&amp;mut </span>Context&lt;<span class="lifetime">'_</span>&gt;,
<a href=#316 id=316 data-nosnippet>316</a> buf: <span class="kw-2">&amp;</span>[u8],
<a href=#317 id=317 data-nosnippet>317</a> ) -&gt; Poll&lt;io::Result&lt;usize&gt;&gt; {
<a href=#318 id=318 data-nosnippet>318</a> <span class="self">self</span>.poll_write(cx, buf).map_err(Into::into)
<a href=#319 id=319 data-nosnippet>319</a> }
<a href=#320 id=320 data-nosnippet>320</a>
<a href=#321 id=321 data-nosnippet>321</a> <span class="kw">fn </span>poll_close(<span class="self">self</span>: Pin&lt;<span class="kw-2">&amp;mut </span><span class="self">Self</span>&gt;, _cx: <span class="kw-2">&amp;mut </span>Context&lt;<span class="lifetime">'_</span>&gt;) -&gt; Poll&lt;io::Result&lt;()&gt;&gt; {
<a href=#322 id=322 data-nosnippet>322</a> Poll::Ready(<span class="self">self</span>.get_mut().finish().map_err(Into::into))
<a href=#321 id=321 data-nosnippet>321</a> <span class="kw">fn </span>poll_flush(<span class="self">self</span>: Pin&lt;<span class="kw-2">&amp;mut </span><span class="self">Self</span>&gt;, _cx: <span class="kw-2">&amp;mut </span>Context&lt;<span class="lifetime">'_</span>&gt;) -&gt; Poll&lt;io::Result&lt;()&gt;&gt; {
<a href=#322 id=322 data-nosnippet>322</a> Poll::Ready(<span class="prelude-val">Ok</span>(()))
<a href=#323 id=323 data-nosnippet>323</a> }
<a href=#324 id=324 data-nosnippet>324</a>}
<a href=#325 id=325 data-nosnippet>325</a>
<a href=#326 id=326 data-nosnippet>326</a><span class="kw">impl </span>tokio::io::AsyncWrite <span class="kw">for </span>SendStream {
<a href=#327 id=327 data-nosnippet>327</a> <span class="kw">fn </span>poll_write(
<a href=#328 id=328 data-nosnippet>328</a> <span class="self">self</span>: Pin&lt;<span class="kw-2">&amp;mut </span><span class="self">Self</span>&gt;,
<a href=#329 id=329 data-nosnippet>329</a> cx: <span class="kw-2">&amp;mut </span>Context&lt;<span class="lifetime">'_</span>&gt;,
<a href=#330 id=330 data-nosnippet>330</a> buf: <span class="kw-2">&amp;</span>[u8],
<a href=#331 id=331 data-nosnippet>331</a> ) -&gt; Poll&lt;io::Result&lt;usize&gt;&gt; {
<a href=#332 id=332 data-nosnippet>332</a> <span class="self">self</span>.poll_write(cx, buf).map_err(Into::into)
<a href=#333 id=333 data-nosnippet>333</a> }
<a href=#334 id=334 data-nosnippet>334</a>
<a href=#335 id=335 data-nosnippet>335</a> <span class="kw">fn </span>poll_flush(<span class="self">self</span>: Pin&lt;<span class="kw-2">&amp;mut </span><span class="self">Self</span>&gt;, _cx: <span class="kw-2">&amp;mut </span>Context&lt;<span class="lifetime">'_</span>&gt;) -&gt; Poll&lt;io::Result&lt;()&gt;&gt; {
<a href=#336 id=336 data-nosnippet>336</a> Poll::Ready(<span class="prelude-val">Ok</span>(()))
<a href=#324 id=324 data-nosnippet>324</a>
<a href=#325 id=325 data-nosnippet>325</a> <span class="kw">fn </span>poll_close(<span class="self">self</span>: Pin&lt;<span class="kw-2">&amp;mut </span><span class="self">Self</span>&gt;, _cx: <span class="kw-2">&amp;mut </span>Context&lt;<span class="lifetime">'_</span>&gt;) -&gt; Poll&lt;io::Result&lt;()&gt;&gt; {
<a href=#326 id=326 data-nosnippet>326</a> Poll::Ready(<span class="self">self</span>.get_mut().finish().map_err(Into::into))
<a href=#327 id=327 data-nosnippet>327</a> }
<a href=#328 id=328 data-nosnippet>328</a>}
<a href=#329 id=329 data-nosnippet>329</a>
<a href=#330 id=330 data-nosnippet>330</a><span class="kw">impl </span>tokio::io::AsyncWrite <span class="kw">for </span>SendStream {
<a href=#331 id=331 data-nosnippet>331</a> <span class="kw">fn </span>poll_write(
<a href=#332 id=332 data-nosnippet>332</a> <span class="self">self</span>: Pin&lt;<span class="kw-2">&amp;mut </span><span class="self">Self</span>&gt;,
<a href=#333 id=333 data-nosnippet>333</a> cx: <span class="kw-2">&amp;mut </span>Context&lt;<span class="lifetime">'_</span>&gt;,
<a href=#334 id=334 data-nosnippet>334</a> buf: <span class="kw-2">&amp;</span>[u8],
<a href=#335 id=335 data-nosnippet>335</a> ) -&gt; Poll&lt;io::Result&lt;usize&gt;&gt; {
<a href=#336 id=336 data-nosnippet>336</a> <span class="self">self</span>.poll_write(cx, buf).map_err(Into::into)
<a href=#337 id=337 data-nosnippet>337</a> }
<a href=#338 id=338 data-nosnippet>338</a>
<a href=#339 id=339 data-nosnippet>339</a> <span class="kw">fn </span>poll_shutdown(<span class="self">self</span>: Pin&lt;<span class="kw-2">&amp;mut </span><span class="self">Self</span>&gt;, _cx: <span class="kw-2">&amp;mut </span>Context&lt;<span class="lifetime">'_</span>&gt;) -&gt; Poll&lt;io::Result&lt;()&gt;&gt; {
<a href=#340 id=340 data-nosnippet>340</a> Poll::Ready(<span class="self">self</span>.get_mut().finish().map_err(Into::into))
<a href=#339 id=339 data-nosnippet>339</a> <span class="kw">fn </span>poll_flush(<span class="self">self</span>: Pin&lt;<span class="kw-2">&amp;mut </span><span class="self">Self</span>&gt;, _cx: <span class="kw-2">&amp;mut </span>Context&lt;<span class="lifetime">'_</span>&gt;) -&gt; Poll&lt;io::Result&lt;()&gt;&gt; {
<a href=#340 id=340 data-nosnippet>340</a> Poll::Ready(<span class="prelude-val">Ok</span>(()))
<a href=#341 id=341 data-nosnippet>341</a> }
<a href=#342 id=342 data-nosnippet>342</a>}
<a href=#343 id=343 data-nosnippet>343</a>
<a href=#344 id=344 data-nosnippet>344</a><span class="kw">impl </span>Drop <span class="kw">for </span>SendStream {
<a href=#345 id=345 data-nosnippet>345</a> <span class="kw">fn </span>drop(<span class="kw-2">&amp;mut </span><span class="self">self</span>) {
<a href=#346 id=346 data-nosnippet>346</a> <span class="kw">let </span><span class="kw-2">mut </span>conn = <span class="self">self</span>.conn.state.lock(<span class="string">"SendStream::drop"</span>);
<a href=#342 id=342 data-nosnippet>342</a>
<a href=#343 id=343 data-nosnippet>343</a> <span class="kw">fn </span>poll_shutdown(<span class="self">self</span>: Pin&lt;<span class="kw-2">&amp;mut </span><span class="self">Self</span>&gt;, _cx: <span class="kw-2">&amp;mut </span>Context&lt;<span class="lifetime">'_</span>&gt;) -&gt; Poll&lt;io::Result&lt;()&gt;&gt; {
<a href=#344 id=344 data-nosnippet>344</a> Poll::Ready(<span class="self">self</span>.get_mut().finish().map_err(Into::into))
<a href=#345 id=345 data-nosnippet>345</a> }
<a href=#346 id=346 data-nosnippet>346</a>}
<a href=#347 id=347 data-nosnippet>347</a>
<a href=#348 id=348 data-nosnippet>348</a> <span class="comment">// clean up any previously registered wakers
<a href=#349 id=349 data-nosnippet>349</a> </span>conn.blocked_writers.remove(<span class="kw-2">&amp;</span><span class="self">self</span>.stream);
<a href=#350 id=350 data-nosnippet>350</a>
<a href=#351 id=351 data-nosnippet>351</a> <span class="kw">if </span>conn.error.is_some() || (<span class="self">self</span>.is_0rtt &amp;&amp; conn.check_0rtt().is_err()) {
<a href=#352 id=352 data-nosnippet>352</a> <span class="kw">return</span>;
<a href=#353 id=353 data-nosnippet>353</a> }
<a href=#354 id=354 data-nosnippet>354</a> <span class="kw">match </span>conn.inner.send_stream(<span class="self">self</span>.stream).finish() {
<a href=#355 id=355 data-nosnippet>355</a> <span class="prelude-val">Ok</span>(()) =&gt; conn.wake(),
<a href=#356 id=356 data-nosnippet>356</a> <span class="prelude-val">Err</span>(FinishError::Stopped(reason)) =&gt; {
<a href=#357 id=357 data-nosnippet>357</a> <span class="kw">if </span>conn.inner.send_stream(<span class="self">self</span>.stream).reset(reason).is_ok() {
<a href=#358 id=358 data-nosnippet>358</a> conn.wake();
<a href=#359 id=359 data-nosnippet>359</a> }
<a href=#360 id=360 data-nosnippet>360</a> }
<a href=#361 id=361 data-nosnippet>361</a> <span class="comment">// Already finished or reset, which is fine.
<a href=#362 id=362 data-nosnippet>362</a> </span><span class="prelude-val">Err</span>(FinishError::ClosedStream) =&gt; {}
<a href=#363 id=363 data-nosnippet>363</a> }
<a href=#364 id=364 data-nosnippet>364</a> }
<a href=#365 id=365 data-nosnippet>365</a>}
<a href=#366 id=366 data-nosnippet>366</a>
<a href=#367 id=367 data-nosnippet>367</a><span class="doccomment">/// Errors that arise from writing to a stream
<a href=#368 id=368 data-nosnippet>368</a></span><span class="attr">#[derive(Debug, Error, Clone, PartialEq, Eq)]
<a href=#369 id=369 data-nosnippet>369</a></span><span class="kw">pub enum </span>WriteError {
<a href=#370 id=370 data-nosnippet>370</a> <span class="doccomment">/// The peer is no longer accepting data on this stream
<a href=#371 id=371 data-nosnippet>371</a> ///
<a href=#372 id=372 data-nosnippet>372</a> /// Carries an application-defined error code.
<a href=#373 id=373 data-nosnippet>373</a> </span><span class="attr">#[error(<span class="string">"sending stopped by peer: error {0}"</span>)]
<a href=#374 id=374 data-nosnippet>374</a> </span>Stopped(VarInt),
<a href=#375 id=375 data-nosnippet>375</a> <span class="doccomment">/// The connection was lost
<a href=#376 id=376 data-nosnippet>376</a> </span><span class="attr">#[error(<span class="string">"connection lost"</span>)]
<a href=#377 id=377 data-nosnippet>377</a> </span>ConnectionLost(<span class="attr">#[from] </span>ConnectionError),
<a href=#378 id=378 data-nosnippet>378</a> <span class="doccomment">/// The stream has already been finished or reset
<a href=#379 id=379 data-nosnippet>379</a> </span><span class="attr">#[error(<span class="string">"closed stream"</span>)]
<a href=#380 id=380 data-nosnippet>380</a> </span>ClosedStream,
<a href=#381 id=381 data-nosnippet>381</a> <span class="doccomment">/// This was a 0-RTT stream and the server rejected it
<a href=#382 id=382 data-nosnippet>382</a> ///
<a href=#383 id=383 data-nosnippet>383</a> /// Can only occur on clients for 0-RTT streams, which can be opened using
<a href=#384 id=384 data-nosnippet>384</a> /// [`Connecting::into_0rtt()`].
<a href=#385 id=385 data-nosnippet>385</a> ///
<a href=#386 id=386 data-nosnippet>386</a> /// [`Connecting::into_0rtt()`]: crate::Connecting::into_0rtt()
<a href=#387 id=387 data-nosnippet>387</a> </span><span class="attr">#[error(<span class="string">"0-RTT rejected"</span>)]
<a href=#388 id=388 data-nosnippet>388</a> </span>ZeroRttRejected,
<a href=#389 id=389 data-nosnippet>389</a>}
<a href=#390 id=390 data-nosnippet>390</a>
<a href=#391 id=391 data-nosnippet>391</a><span class="kw">impl </span>From&lt;ClosedStream&gt; <span class="kw">for </span>WriteError {
<a href=#392 id=392 data-nosnippet>392</a> <span class="attr">#[inline]
<a href=#393 id=393 data-nosnippet>393</a> </span><span class="kw">fn </span>from(<span class="kw">_</span>: ClosedStream) -&gt; <span class="self">Self </span>{
<a href=#394 id=394 data-nosnippet>394</a> <span class="self">Self</span>::ClosedStream
<a href=#395 id=395 data-nosnippet>395</a> }
<a href=#348 id=348 data-nosnippet>348</a><span class="kw">impl </span>Drop <span class="kw">for </span>SendStream {
<a href=#349 id=349 data-nosnippet>349</a> <span class="kw">fn </span>drop(<span class="kw-2">&amp;mut </span><span class="self">self</span>) {
<a href=#350 id=350 data-nosnippet>350</a> <span class="kw">let </span><span class="kw-2">mut </span>conn = <span class="self">self</span>.conn.lock_and_wake(<span class="string">"SendStream::drop"</span>);
<a href=#351 id=351 data-nosnippet>351</a>
<a href=#352 id=352 data-nosnippet>352</a> <span class="comment">// clean up any previously registered wakers
<a href=#353 id=353 data-nosnippet>353</a> </span>conn.blocked_writers.remove(<span class="kw-2">&amp;</span><span class="self">self</span>.stream);
<a href=#354 id=354 data-nosnippet>354</a>
<a href=#355 id=355 data-nosnippet>355</a> <span class="kw">if </span>conn.error.is_some() || (<span class="self">self</span>.is_0rtt &amp;&amp; conn.check_0rtt().is_err()) {
<a href=#356 id=356 data-nosnippet>356</a> conn.skip_waking();
<a href=#357 id=357 data-nosnippet>357</a> <span class="kw">return</span>;
<a href=#358 id=358 data-nosnippet>358</a> }
<a href=#359 id=359 data-nosnippet>359</a> <span class="kw">match </span>conn.inner.send_stream(<span class="self">self</span>.stream).finish() {
<a href=#360 id=360 data-nosnippet>360</a> <span class="prelude-val">Ok</span>(()) =&gt; {}
<a href=#361 id=361 data-nosnippet>361</a> <span class="prelude-val">Err</span>(FinishError::Stopped(reason)) =&gt; {
<a href=#362 id=362 data-nosnippet>362</a> <span class="kw">if </span>conn.inner.send_stream(<span class="self">self</span>.stream).reset(reason).is_err() {
<a href=#363 id=363 data-nosnippet>363</a> conn.skip_waking()
<a href=#364 id=364 data-nosnippet>364</a> }
<a href=#365 id=365 data-nosnippet>365</a> }
<a href=#366 id=366 data-nosnippet>366</a> <span class="comment">// Already finished or reset, which is fine.
<a href=#367 id=367 data-nosnippet>367</a> </span><span class="prelude-val">Err</span>(FinishError::ClosedStream) =&gt; {
<a href=#368 id=368 data-nosnippet>368</a> conn.skip_waking();
<a href=#369 id=369 data-nosnippet>369</a> }
<a href=#370 id=370 data-nosnippet>370</a> }
<a href=#371 id=371 data-nosnippet>371</a> }
<a href=#372 id=372 data-nosnippet>372</a>}
<a href=#373 id=373 data-nosnippet>373</a>
<a href=#374 id=374 data-nosnippet>374</a><span class="doccomment">/// Errors that arise from writing to a stream
<a href=#375 id=375 data-nosnippet>375</a></span><span class="attr">#[derive(Debug, Error, Clone, PartialEq, Eq)]
<a href=#376 id=376 data-nosnippet>376</a></span><span class="kw">pub enum </span>WriteError {
<a href=#377 id=377 data-nosnippet>377</a> <span class="doccomment">/// The peer is no longer accepting data on this stream
<a href=#378 id=378 data-nosnippet>378</a> ///
<a href=#379 id=379 data-nosnippet>379</a> /// Carries an application-defined error code.
<a href=#380 id=380 data-nosnippet>380</a> </span><span class="attr">#[error(<span class="string">"sending stopped by peer: error {0}"</span>)]
<a href=#381 id=381 data-nosnippet>381</a> </span>Stopped(VarInt),
<a href=#382 id=382 data-nosnippet>382</a> <span class="doccomment">/// The connection was lost
<a href=#383 id=383 data-nosnippet>383</a> </span><span class="attr">#[error(<span class="string">"connection lost"</span>)]
<a href=#384 id=384 data-nosnippet>384</a> </span>ConnectionLost(<span class="attr">#[from] </span>ConnectionError),
<a href=#385 id=385 data-nosnippet>385</a> <span class="doccomment">/// The stream has already been finished or reset
<a href=#386 id=386 data-nosnippet>386</a> </span><span class="attr">#[error(<span class="string">"closed stream"</span>)]
<a href=#387 id=387 data-nosnippet>387</a> </span>ClosedStream,
<a href=#388 id=388 data-nosnippet>388</a> <span class="doccomment">/// This was a 0-RTT stream and the server rejected it
<a href=#389 id=389 data-nosnippet>389</a> ///
<a href=#390 id=390 data-nosnippet>390</a> /// Can only occur on clients for 0-RTT streams, which can be opened using
<a href=#391 id=391 data-nosnippet>391</a> /// [`Connecting::into_0rtt()`].
<a href=#392 id=392 data-nosnippet>392</a> ///
<a href=#393 id=393 data-nosnippet>393</a> /// [`Connecting::into_0rtt()`]: crate::Connecting::into_0rtt()
<a href=#394 id=394 data-nosnippet>394</a> </span><span class="attr">#[error(<span class="string">"0-RTT rejected"</span>)]
<a href=#395 id=395 data-nosnippet>395</a> </span>ZeroRttRejected,
<a href=#396 id=396 data-nosnippet>396</a>}
<a href=#397 id=397 data-nosnippet>397</a>
<a href=#398 id=398 data-nosnippet>398</a><span class="kw">impl </span>From&lt;StoppedError&gt; <span class="kw">for </span>WriteError {
<a href=#399 id=399 data-nosnippet>399</a> <span class="kw">fn </span>from(x: StoppedError) -&gt; <span class="self">Self </span>{
<a href=#400 id=400 data-nosnippet>400</a> <span class="kw">match </span>x {
<a href=#401 id=401 data-nosnippet>401</a> StoppedError::ConnectionLost(e) =&gt; <span class="self">Self</span>::ConnectionLost(e),
<a href=#402 id=402 data-nosnippet>402</a> StoppedError::ZeroRttRejected =&gt; <span class="self">Self</span>::ZeroRttRejected,
<a href=#403 id=403 data-nosnippet>403</a> }
<a href=#404 id=404 data-nosnippet>404</a> }
<a href=#405 id=405 data-nosnippet>405</a>}
<a href=#406 id=406 data-nosnippet>406</a>
<a href=#407 id=407 data-nosnippet>407</a><span class="kw">impl </span>From&lt;WriteError&gt; <span class="kw">for </span>io::Error {
<a href=#408 id=408 data-nosnippet>408</a> <span class="kw">fn </span>from(x: WriteError) -&gt; <span class="self">Self </span>{
<a href=#409 id=409 data-nosnippet>409</a> <span class="kw">use </span>WriteError::<span class="kw-2">*</span>;
<a href=#410 id=410 data-nosnippet>410</a> <span class="kw">let </span>kind = <span class="kw">match </span>x {
<a href=#411 id=411 data-nosnippet>411</a> Stopped(<span class="kw">_</span>) | ZeroRttRejected =&gt; io::ErrorKind::ConnectionReset,
<a href=#412 id=412 data-nosnippet>412</a> ConnectionLost(<span class="kw">_</span>) | ClosedStream =&gt; io::ErrorKind::NotConnected,
<a href=#413 id=413 data-nosnippet>413</a> };
<a href=#414 id=414 data-nosnippet>414</a> <span class="self">Self</span>::new(kind, x)
<a href=#415 id=415 data-nosnippet>415</a> }
<a href=#416 id=416 data-nosnippet>416</a>}
<a href=#417 id=417 data-nosnippet>417</a>
<a href=#418 id=418 data-nosnippet>418</a><span class="doccomment">/// Errors that arise while monitoring for a send stream stop from the peer
<a href=#419 id=419 data-nosnippet>419</a></span><span class="attr">#[derive(Debug, Error, Clone, PartialEq, Eq)]
<a href=#420 id=420 data-nosnippet>420</a></span><span class="kw">pub enum </span>StoppedError {
<a href=#421 id=421 data-nosnippet>421</a> <span class="doccomment">/// The connection was lost
<a href=#422 id=422 data-nosnippet>422</a> </span><span class="attr">#[error(<span class="string">"connection lost"</span>)]
<a href=#423 id=423 data-nosnippet>423</a> </span>ConnectionLost(<span class="attr">#[from] </span>ConnectionError),
<a href=#424 id=424 data-nosnippet>424</a> <span class="doccomment">/// This was a 0-RTT stream and the server rejected it
<a href=#425 id=425 data-nosnippet>425</a> ///
<a href=#426 id=426 data-nosnippet>426</a> /// Can only occur on clients for 0-RTT streams, which can be opened using
<a href=#427 id=427 data-nosnippet>427</a> /// [`Connecting::into_0rtt()`].
<a href=#428 id=428 data-nosnippet>428</a> ///
<a href=#429 id=429 data-nosnippet>429</a> /// [`Connecting::into_0rtt()`]: crate::Connecting::into_0rtt()
<a href=#430 id=430 data-nosnippet>430</a> </span><span class="attr">#[error(<span class="string">"0-RTT rejected"</span>)]
<a href=#431 id=431 data-nosnippet>431</a> </span>ZeroRttRejected,
<a href=#432 id=432 data-nosnippet>432</a>}
<a href=#433 id=433 data-nosnippet>433</a>
<a href=#434 id=434 data-nosnippet>434</a><span class="kw">impl </span>From&lt;StoppedError&gt; <span class="kw">for </span>io::Error {
<a href=#435 id=435 data-nosnippet>435</a> <span class="kw">fn </span>from(x: StoppedError) -&gt; <span class="self">Self </span>{
<a href=#436 id=436 data-nosnippet>436</a> <span class="kw">use </span>StoppedError::<span class="kw-2">*</span>;
<a href=#437 id=437 data-nosnippet>437</a> <span class="kw">let </span>kind = <span class="kw">match </span>x {
<a href=#438 id=438 data-nosnippet>438</a> ZeroRttRejected =&gt; io::ErrorKind::ConnectionReset,
<a href=#439 id=439 data-nosnippet>439</a> ConnectionLost(<span class="kw">_</span>) =&gt; io::ErrorKind::NotConnected,
<a href=#440 id=440 data-nosnippet>440</a> };
<a href=#441 id=441 data-nosnippet>441</a> <span class="self">Self</span>::new(kind, x)
<a href=#442 id=442 data-nosnippet>442</a> }
<a href=#443 id=443 data-nosnippet>443</a>}
<a href=#444 id=444 data-nosnippet>444</a>
<a href=#445 id=445 data-nosnippet>445</a><span class="macro">pin_project!</span> {
<a href=#446 id=446 data-nosnippet>446</a> <span class="doccomment">/// Future returned from [`SendStream::stopped`].
<a href=#447 id=447 data-nosnippet>447</a> </span><span class="attr">#[derive(Debug)]
<a href=#448 id=448 data-nosnippet>448</a> </span><span class="kw">pub struct </span>Stopped {
<a href=#449 id=449 data-nosnippet>449</a> conn: ConnectionRef,
<a href=#450 id=450 data-nosnippet>450</a> stream: StreamId,
<a href=#451 id=451 data-nosnippet>451</a> is_0rtt: bool,
<a href=#452 id=452 data-nosnippet>452</a> <span class="attr">#[pin]
<a href=#453 id=453 data-nosnippet>453</a> </span>notified: OwnedNotified,
<a href=#454 id=454 data-nosnippet>454</a> }
<a href=#455 id=455 data-nosnippet>455</a>}
<a href=#456 id=456 data-nosnippet>456</a>
<a href=#457 id=457 data-nosnippet>457</a><span class="kw">impl </span>Future <span class="kw">for </span>Stopped {
<a href=#458 id=458 data-nosnippet>458</a> <span class="kw">type </span>Output = <span class="prelude-ty">Result</span>&lt;<span class="prelude-ty">Option</span>&lt;VarInt&gt;, StoppedError&gt;;
<a href=#459 id=459 data-nosnippet>459</a>
<a href=#460 id=460 data-nosnippet>460</a> <span class="kw">fn </span>poll(<span class="self">self</span>: Pin&lt;<span class="kw-2">&amp;mut </span><span class="self">Self</span>&gt;, cx: <span class="kw-2">&amp;mut </span>Context&lt;<span class="lifetime">'_</span>&gt;) -&gt; Poll&lt;<span class="self">Self</span>::Output&gt; {
<a href=#461 id=461 data-nosnippet>461</a> <span class="kw">let </span><span class="kw-2">mut </span>this = <span class="self">self</span>.project();
<a href=#462 id=462 data-nosnippet>462</a> <span class="kw">loop </span>{
<a href=#463 id=463 data-nosnippet>463</a> <span class="kw">let </span><span class="kw-2">mut </span>conn = this.conn.state.lock(<span class="string">"SendStream::stopped"</span>);
<a href=#464 id=464 data-nosnippet>464</a> <span class="comment">// Check if the stream is stopped before polling the notify. This makes sure that
<a href=#465 id=465 data-nosnippet>465</a> // no wakeups are missed.
<a href=#466 id=466 data-nosnippet>466</a> </span><span class="kw">if let </span><span class="prelude-val">Some</span>(output) = send_stream_stopped(<span class="kw-2">&amp;mut </span>conn, <span class="kw-2">*</span>this.stream, <span class="kw-2">*</span>this.is_0rtt) {
<a href=#467 id=467 data-nosnippet>467</a> <span class="kw">return </span>Poll::Ready(output);
<a href=#468 id=468 data-nosnippet>468</a> }
<a href=#469 id=469 data-nosnippet>469</a> <span class="macro">std::task::ready!</span>(this.notified.as_mut().poll(cx));
<a href=#470 id=470 data-nosnippet>470</a> }
<a href=#471 id=471 data-nosnippet>471</a> }
<a href=#472 id=472 data-nosnippet>472</a>}
<a href=#473 id=473 data-nosnippet>473</a>
<a href=#474 id=474 data-nosnippet>474</a><span class="attr">#[cfg(test)]
<a href=#475 id=475 data-nosnippet>475</a></span><span class="kw">mod </span>tests {
<a href=#476 id=476 data-nosnippet>476</a> <span class="kw">fn </span>check_is_send_sync&lt;A: Send + Sync&gt;() {}
<a href=#477 id=477 data-nosnippet>477</a>
<a href=#478 id=478 data-nosnippet>478</a> <span class="attr">#[allow(dead_code)]
<a href=#479 id=479 data-nosnippet>479</a> </span><span class="kw">fn </span>test_bounds() {
<a href=#480 id=480 data-nosnippet>480</a> check_is_send_sync::&lt;<span class="kw">super</span>::Stopped&gt;();
<a href=#481 id=481 data-nosnippet>481</a> }
<a href=#482 id=482 data-nosnippet>482</a>}</code></pre></div></section></main></body></html>
<a href=#398 id=398 data-nosnippet>398</a><span class="kw">impl </span>From&lt;ClosedStream&gt; <span class="kw">for </span>WriteError {
<a href=#399 id=399 data-nosnippet>399</a> <span class="attr">#[inline]
<a href=#400 id=400 data-nosnippet>400</a> </span><span class="kw">fn </span>from(<span class="kw">_</span>: ClosedStream) -&gt; <span class="self">Self </span>{
<a href=#401 id=401 data-nosnippet>401</a> <span class="self">Self</span>::ClosedStream
<a href=#402 id=402 data-nosnippet>402</a> }
<a href=#403 id=403 data-nosnippet>403</a>}
<a href=#404 id=404 data-nosnippet>404</a>
<a href=#405 id=405 data-nosnippet>405</a><span class="kw">impl </span>From&lt;StoppedError&gt; <span class="kw">for </span>WriteError {
<a href=#406 id=406 data-nosnippet>406</a> <span class="kw">fn </span>from(x: StoppedError) -&gt; <span class="self">Self </span>{
<a href=#407 id=407 data-nosnippet>407</a> <span class="kw">match </span>x {
<a href=#408 id=408 data-nosnippet>408</a> StoppedError::ConnectionLost(e) =&gt; <span class="self">Self</span>::ConnectionLost(e),
<a href=#409 id=409 data-nosnippet>409</a> StoppedError::ZeroRttRejected =&gt; <span class="self">Self</span>::ZeroRttRejected,
<a href=#410 id=410 data-nosnippet>410</a> }
<a href=#411 id=411 data-nosnippet>411</a> }
<a href=#412 id=412 data-nosnippet>412</a>}
<a href=#413 id=413 data-nosnippet>413</a>
<a href=#414 id=414 data-nosnippet>414</a><span class="kw">impl </span>From&lt;WriteError&gt; <span class="kw">for </span>io::Error {
<a href=#415 id=415 data-nosnippet>415</a> <span class="kw">fn </span>from(x: WriteError) -&gt; <span class="self">Self </span>{
<a href=#416 id=416 data-nosnippet>416</a> <span class="kw">use </span>WriteError::<span class="kw-2">*</span>;
<a href=#417 id=417 data-nosnippet>417</a> <span class="kw">let </span>kind = <span class="kw">match </span>x {
<a href=#418 id=418 data-nosnippet>418</a> Stopped(<span class="kw">_</span>) | ZeroRttRejected =&gt; io::ErrorKind::ConnectionReset,
<a href=#419 id=419 data-nosnippet>419</a> ConnectionLost(<span class="kw">_</span>) | ClosedStream =&gt; io::ErrorKind::NotConnected,
<a href=#420 id=420 data-nosnippet>420</a> };
<a href=#421 id=421 data-nosnippet>421</a> <span class="self">Self</span>::new(kind, x)
<a href=#422 id=422 data-nosnippet>422</a> }
<a href=#423 id=423 data-nosnippet>423</a>}
<a href=#424 id=424 data-nosnippet>424</a>
<a href=#425 id=425 data-nosnippet>425</a><span class="doccomment">/// Errors that arise while monitoring for a send stream stop from the peer
<a href=#426 id=426 data-nosnippet>426</a></span><span class="attr">#[derive(Debug, Error, Clone, PartialEq, Eq)]
<a href=#427 id=427 data-nosnippet>427</a></span><span class="kw">pub enum </span>StoppedError {
<a href=#428 id=428 data-nosnippet>428</a> <span class="doccomment">/// The connection was lost
<a href=#429 id=429 data-nosnippet>429</a> </span><span class="attr">#[error(<span class="string">"connection lost"</span>)]
<a href=#430 id=430 data-nosnippet>430</a> </span>ConnectionLost(<span class="attr">#[from] </span>ConnectionError),
<a href=#431 id=431 data-nosnippet>431</a> <span class="doccomment">/// This was a 0-RTT stream and the server rejected it
<a href=#432 id=432 data-nosnippet>432</a> ///
<a href=#433 id=433 data-nosnippet>433</a> /// Can only occur on clients for 0-RTT streams, which can be opened using
<a href=#434 id=434 data-nosnippet>434</a> /// [`Connecting::into_0rtt()`].
<a href=#435 id=435 data-nosnippet>435</a> ///
<a href=#436 id=436 data-nosnippet>436</a> /// [`Connecting::into_0rtt()`]: crate::Connecting::into_0rtt()
<a href=#437 id=437 data-nosnippet>437</a> </span><span class="attr">#[error(<span class="string">"0-RTT rejected"</span>)]
<a href=#438 id=438 data-nosnippet>438</a> </span>ZeroRttRejected,
<a href=#439 id=439 data-nosnippet>439</a>}
<a href=#440 id=440 data-nosnippet>440</a>
<a href=#441 id=441 data-nosnippet>441</a><span class="kw">impl </span>From&lt;StoppedError&gt; <span class="kw">for </span>io::Error {
<a href=#442 id=442 data-nosnippet>442</a> <span class="kw">fn </span>from(x: StoppedError) -&gt; <span class="self">Self </span>{
<a href=#443 id=443 data-nosnippet>443</a> <span class="kw">use </span>StoppedError::<span class="kw-2">*</span>;
<a href=#444 id=444 data-nosnippet>444</a> <span class="kw">let </span>kind = <span class="kw">match </span>x {
<a href=#445 id=445 data-nosnippet>445</a> ZeroRttRejected =&gt; io::ErrorKind::ConnectionReset,
<a href=#446 id=446 data-nosnippet>446</a> ConnectionLost(<span class="kw">_</span>) =&gt; io::ErrorKind::NotConnected,
<a href=#447 id=447 data-nosnippet>447</a> };
<a href=#448 id=448 data-nosnippet>448</a> <span class="self">Self</span>::new(kind, x)
<a href=#449 id=449 data-nosnippet>449</a> }
<a href=#450 id=450 data-nosnippet>450</a>}
<a href=#451 id=451 data-nosnippet>451</a>
<a href=#452 id=452 data-nosnippet>452</a><span class="macro">pin_project!</span> {
<a href=#453 id=453 data-nosnippet>453</a> <span class="doccomment">/// Future returned from [`SendStream::stopped`].
<a href=#454 id=454 data-nosnippet>454</a> </span><span class="attr">#[derive(Debug)]
<a href=#455 id=455 data-nosnippet>455</a> </span><span class="kw">pub struct </span>Stopped {
<a href=#456 id=456 data-nosnippet>456</a> conn: ConnectionRef,
<a href=#457 id=457 data-nosnippet>457</a> stream: StreamId,
<a href=#458 id=458 data-nosnippet>458</a> is_0rtt: bool,
<a href=#459 id=459 data-nosnippet>459</a> <span class="attr">#[pin]
<a href=#460 id=460 data-nosnippet>460</a> </span>notified: OwnedNotified,
<a href=#461 id=461 data-nosnippet>461</a> }
<a href=#462 id=462 data-nosnippet>462</a>}
<a href=#463 id=463 data-nosnippet>463</a>
<a href=#464 id=464 data-nosnippet>464</a><span class="kw">impl </span>Future <span class="kw">for </span>Stopped {
<a href=#465 id=465 data-nosnippet>465</a> <span class="kw">type </span>Output = <span class="prelude-ty">Result</span>&lt;<span class="prelude-ty">Option</span>&lt;VarInt&gt;, StoppedError&gt;;
<a href=#466 id=466 data-nosnippet>466</a>
<a href=#467 id=467 data-nosnippet>467</a> <span class="kw">fn </span>poll(<span class="self">self</span>: Pin&lt;<span class="kw-2">&amp;mut </span><span class="self">Self</span>&gt;, cx: <span class="kw-2">&amp;mut </span>Context&lt;<span class="lifetime">'_</span>&gt;) -&gt; Poll&lt;<span class="self">Self</span>::Output&gt; {
<a href=#468 id=468 data-nosnippet>468</a> <span class="kw">let </span><span class="kw-2">mut </span>this = <span class="self">self</span>.project();
<a href=#469 id=469 data-nosnippet>469</a> <span class="kw">loop </span>{
<a href=#470 id=470 data-nosnippet>470</a> <span class="kw">let </span><span class="kw-2">mut </span>conn = this.conn.lock_without_waking(<span class="string">"SendStream::stopped"</span>);
<a href=#471 id=471 data-nosnippet>471</a> <span class="comment">// Check if the stream is stopped before polling the notify. This makes sure that
<a href=#472 id=472 data-nosnippet>472</a> // no wakeups are missed.
<a href=#473 id=473 data-nosnippet>473</a> </span><span class="kw">if let </span><span class="prelude-val">Some</span>(output) = send_stream_stopped(<span class="kw-2">&amp;mut </span>conn, <span class="kw-2">*</span>this.stream, <span class="kw-2">*</span>this.is_0rtt) {
<a href=#474 id=474 data-nosnippet>474</a> <span class="kw">return </span>Poll::Ready(output);
<a href=#475 id=475 data-nosnippet>475</a> }
<a href=#476 id=476 data-nosnippet>476</a> <span class="macro">std::task::ready!</span>(this.notified.as_mut().poll(cx));
<a href=#477 id=477 data-nosnippet>477</a> }
<a href=#478 id=478 data-nosnippet>478</a> }
<a href=#479 id=479 data-nosnippet>479</a>}
<a href=#480 id=480 data-nosnippet>480</a>
<a href=#481 id=481 data-nosnippet>481</a><span class="attr">#[cfg(test)]
<a href=#482 id=482 data-nosnippet>482</a></span><span class="kw">mod </span>tests {
<a href=#483 id=483 data-nosnippet>483</a> <span class="kw">fn </span>check_is_send_sync&lt;A: Send + Sync&gt;() {}
<a href=#484 id=484 data-nosnippet>484</a>
<a href=#485 id=485 data-nosnippet>485</a> <span class="attr">#[allow(dead_code)]
<a href=#486 id=486 data-nosnippet>486</a> </span><span class="kw">fn </span>test_bounds() {
<a href=#487 id=487 data-nosnippet>487</a> check_is_send_sync::&lt;<span class="kw">super</span>::Stopped&gt;();
<a href=#488 id=488 data-nosnippet>488</a> }
<a href=#489 id=489 data-nosnippet>489</a>}</code></pre></div></section></main></body></html>
File diff suppressed because it is too large Load Diff