1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
//! Which streaming transport an attach settles on, and on what terms.
//!
//! There is no wire magic and no first-bytes handshake to hide one in: the
//! attach exchange already names a transport, so negotiation is three small
//! decisions layered onto it.
//!
//! 1. The sender lists what it can be asked to `connect()` on
//! ([`advertised_keys`]).
//! 2. The receiver intersects that with what it has installed and answers with
//! one key ([`select`]), plus the credit window if that key is the mux.
//! 3. The sender decides what the answer obliges it to do ([`choose`]).
//!
//! Every asymmetry here exists to keep a mixed deployment working. The receiver
//! prefers `messenger-mux-v1` **only** when the sender named it, because
//! `resolve_transport` hard-errors on a key it does not know and a receiver that
//! answered the mux unilaterally would break every older sender. A node with the
//! mux enabled therefore registers both it and the configured legacy transport,
//! and keeps serving legacy peers unchanged.
//!
//! The credit fields carry the rest of the agreement, and their two zeros mean
//! different things: no window means *not offering the mux*, no byte cap means
//! *use the default*. [`NegotiatedLimits::from_wire`] is the one place that
//! split is decided; nothing here re-derives it.
use HashMap;
use Arc;
use TransportKey;
use ;
use ;
use FrameTransport;
/// The streaming-transport registry an [`AnchorManager`] resolves keys against.
///
/// [`AnchorManager`]: crate::streaming::AnchorManager
pub type TransportRegistry = ;
/// The transports a sender advertises on its attach request.
///
/// Exactly what this node can be asked to `connect()` on: the registry's keys,
/// or the default transport's key when no registry was populated (the
/// convenience path `resolve_transport` mirrors). The mux is unioned in
/// explicitly so "installed" and "advertised" cannot drift apart — that
/// equivalence is what makes disabling the mux a complete rollback, since a key
/// never advertised is a key never selected.
///
/// Sorted so the advertisement is stable across runs; `HashMap` iteration order
/// is not.
pub
/// What the receiver picked for one attach, and what it owes the sender.
pub
/// Intersect the sender's advertisement with what is installed here.
///
/// The mux wins only when both sides named it; everything else falls through to
/// the behaviour that shipped before negotiation — answer with the local default
/// transport's key. An empty `offered` (an older sender, which omits the field
/// entirely) cannot intersect, so such a sender always takes that path.
pub
/// How the sender must honour the key the receiver answered with.
pub
/// Read the receiver's answer.
///
/// A key that is not the mux is the legacy path and the credit fields are not
/// its business — an older receiver names its own transport and sends no credit
/// at all, which is the ordinary mixed-deployment case and lands here.
///
/// The mux key with no window is the case that cannot be honoured. It is
/// unreachable from any shipped peer: no version before this one answers
/// `messenger-mux-v1`, and this one refuses to build a mux at zero credit. So it
/// means a peer that bound a mux receiver and then told us to ignore it, and
/// there is no safe reading of that — connecting over any other transport would
/// reach nothing the peer is listening on and hang until the anchor's watchdog
/// fires. Failing the attach says so immediately.
pub