1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
//! The live connect side.
//!
//! The twin of [`crate::serve_handle`]; see that module for why they are
//! separate files.
use ;
use Arc;
use Duration;
use crate;
use crate;
/// A live connect side.
///
/// Teardown semantics match [`ServeHandle`](crate::ServeHandle): dropping tears down without
/// waiting, [`shutdown`](Self::shutdown) waits.
///
/// When the far end is quiet, this side does not guess: unreachability
/// shows as [`PipeStatus::Idle`] while it retries, and it keeps retrying.
/// A sleeping laptop is indistinguishable from a dead one, so timeout
/// policy belongs to the embedder.
///
/// That covers the first dial too. [`connect`](fn@crate::connect) returns
/// once the local port is bound, so a handle begins life at
/// [`PipeStatus::Idle`] whether the peer is absent or merely not reached
/// yet — the two are the same fact, and the handle reports it rather than
/// picking a deadline on the embedder's behalf.
///
/// A listener that has restarted since the ticket was issued is *also*
/// this case, and deliberately not a distinct one. Without an identity
/// file the endpoint key is minted per process, so the restarted listener
/// is a different endpoint entirely and dialing the ticket reaches nobody,
/// exactly as an offline peer does. With one it is the same endpoint and
/// this side reconnects to it — which is what
/// [`ServeOptions::identity`](crate::ServeOptions#structfield.identity)
/// buys, over a network where discovery is reachable. There is no
/// rejection to observe in either case, because there is nobody to
/// reject. [`PipeStatus::Closed`] therefore means this side is gone —
/// shut down, dropped, or dead after an unrecoverable transport failure
/// — never that the far side declined the pairing.
///
/// Deliberately shares no trait with [`ServeHandle`](crate::ServeHandle): the overlap is
/// three methods, and embedders driving both sides duplicate a small
/// park-and-watch loop. If that ever grows past a nuisance, a shared
/// trait is an additive, non-breaking change — the decision is recorded
/// here so the duplication reads as chosen, not overlooked.
// Dropping a handle tears its side down best-effort and without waiting,
// which is the other half of "`shutdown` drains, `Drop` cuts". The close is
// published synchronously so a watcher sees `Closed` immediately; anything
// that needs an await is handed to the runtime, and a handle dropped
// outside one does the synchronous half only — the process is going away
// regardless.
/// The URL to point a client at.
///
/// Not the bind address verbatim. A wildcard bind is a listen address, not
/// a destination — nobody can connect to `0.0.0.0` — so it renders as
/// loopback, which is a place the client can actually reach. An IPv6 zone
/// id is dropped rather than emitted, because no URL parser accepts one.
pub