@cc-remote/iroh 1.0.0-rc.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.yarnrc.yml +3 -0
- package/Cargo.toml +30 -0
- package/README.md +38 -0
- package/index.d.ts +478 -0
- package/index.js +603 -0
- package/package.json +66 -0
- package/src/endpoint.rs +1018 -0
- package/src/key.rs +173 -0
- package/src/lib.rs +59 -0
- package/src/net.rs +106 -0
- package/src/path.rs +167 -0
- package/src/relay.rs +194 -0
- package/src/services.rs +167 -0
- package/src/ticket.rs +46 -0
- package/src/watch.rs +111 -0
- package/test/endpoint.mjs +176 -0
- package/test/key.mjs +71 -0
- package/test/relay.mjs +40 -0
- package/test/services.mjs +47 -0
- package/tsconfig.json +11 -0
- package/typedoc.json +9 -0
package/src/endpoint.rs
ADDED
|
@@ -0,0 +1,1018 @@
|
|
|
1
|
+
use std::{str::FromStr, sync::Arc};
|
|
2
|
+
|
|
3
|
+
use iroh::endpoint::{self, presets, presets::Preset as _};
|
|
4
|
+
use napi::{bindgen_prelude::*, threadsafe_function::ThreadsafeFunction};
|
|
5
|
+
use napi_derive::napi;
|
|
6
|
+
use tokio::sync::Mutex;
|
|
7
|
+
|
|
8
|
+
use crate::{EndpointAddr, RelayMode, SecretKey, WatchHandle, path, watch};
|
|
9
|
+
|
|
10
|
+
/// A mutable handle to an endpoint builder.
|
|
11
|
+
///
|
|
12
|
+
/// Mirrors the uniffi `EndpointBuilder`. A "preset" in JS is simply any
|
|
13
|
+
/// function `(builder: EndpointBuilder) => void` — call one of the built-in
|
|
14
|
+
/// [`presetN0`] / [`presetMinimal`] / [`presetN0DisableRelay`] helpers (which
|
|
15
|
+
/// install the crypto provider) and then layer on your own configuration.
|
|
16
|
+
///
|
|
17
|
+
/// ```js
|
|
18
|
+
/// const b = Endpoint.builder()
|
|
19
|
+
/// presetMinimal(b)
|
|
20
|
+
/// b.alpns([alpn])
|
|
21
|
+
/// const ep = await b.bind()
|
|
22
|
+
/// ```
|
|
23
|
+
#[napi]
|
|
24
|
+
pub struct EndpointBuilder {
|
|
25
|
+
inner: std::sync::Mutex<Option<iroh::endpoint::Builder>>,
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
impl EndpointBuilder {
|
|
29
|
+
fn new(builder: iroh::endpoint::Builder) -> Self {
|
|
30
|
+
Self {
|
|
31
|
+
inner: std::sync::Mutex::new(Some(builder)),
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
fn map<F>(&self, f: F)
|
|
36
|
+
where
|
|
37
|
+
F: FnOnce(iroh::endpoint::Builder) -> iroh::endpoint::Builder,
|
|
38
|
+
{
|
|
39
|
+
let mut guard = self.inner.lock().unwrap();
|
|
40
|
+
let b = guard.take().expect("EndpointBuilder consumed");
|
|
41
|
+
*guard = Some(f(b));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
#[napi]
|
|
46
|
+
impl EndpointBuilder {
|
|
47
|
+
/// Replay the n0 production preset (relays + discovery + crypto provider).
|
|
48
|
+
#[napi]
|
|
49
|
+
pub fn apply_n0(&self) {
|
|
50
|
+
self.map(|b| presets::N0.apply(b));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/// Replay the minimal preset (crypto provider only, no external deps).
|
|
54
|
+
#[napi]
|
|
55
|
+
pub fn apply_minimal(&self) {
|
|
56
|
+
self.map(|b| presets::Minimal.apply(b));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/// Replay the n0 preset with relays disabled.
|
|
60
|
+
#[napi]
|
|
61
|
+
pub fn apply_n0_disable_relay(&self) {
|
|
62
|
+
self.map(|b| presets::N0DisableRelay.apply(b));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/// Set the endpoint secret key (32 bytes).
|
|
66
|
+
#[napi]
|
|
67
|
+
pub fn secret_key(&self, bytes: Vec<u8>) -> Result<()> {
|
|
68
|
+
let key: [u8; 32] = bytes
|
|
69
|
+
.try_into()
|
|
70
|
+
.map_err(|_| anyhow::anyhow!("secret_key must be 32 bytes"))?;
|
|
71
|
+
self.map(|b| b.secret_key(iroh::SecretKey::from_bytes(&key)));
|
|
72
|
+
Ok(())
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/// Set the advertised ALPNs.
|
|
76
|
+
#[napi]
|
|
77
|
+
pub fn alpns(&self, alpns: Vec<Vec<u8>>) {
|
|
78
|
+
self.map(|b| b.alpns(alpns));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/// Set the relay mode.
|
|
82
|
+
#[napi]
|
|
83
|
+
pub fn relay_mode(&self, mode: &RelayMode) {
|
|
84
|
+
let mode = mode.0.clone();
|
|
85
|
+
self.map(|b| b.relay_mode(mode));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/// Remove all IP based transports, forcing all traffic over relays.
|
|
89
|
+
///
|
|
90
|
+
/// This must be called *after* any preset (e.g. [`applyN0`]) that
|
|
91
|
+
/// installs IP transports, otherwise the preset will re-add them.
|
|
92
|
+
#[napi]
|
|
93
|
+
pub fn clear_ip_transports(&self) {
|
|
94
|
+
self.map(|b| b.clear_ip_transports());
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/// Only publish relay addresses (no direct IPs) to discovery.
|
|
98
|
+
///
|
|
99
|
+
/// Installs `AddrFilter::relay_only()` so the addresses published to
|
|
100
|
+
/// discovery (pkarr/DNS) are limited to relay URLs.
|
|
101
|
+
#[napi]
|
|
102
|
+
pub fn addr_filter_relay_only(&self) {
|
|
103
|
+
self.map(|b| b.addr_filter(iroh::address_lookup::AddrFilter::relay_only()));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/// Set the address the endpoint binds to (`host:port`).
|
|
107
|
+
#[napi]
|
|
108
|
+
pub fn bind_addr(&self, addr: String) -> Result<()> {
|
|
109
|
+
let socket = std::net::SocketAddr::from_str(&addr).map_err(anyhow::Error::from)?;
|
|
110
|
+
let mut guard = self.inner.lock().unwrap();
|
|
111
|
+
let b = guard.take().expect("EndpointBuilder consumed");
|
|
112
|
+
*guard = Some(b.bind_addr(socket).map_err(anyhow::Error::from)?);
|
|
113
|
+
Ok(())
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/// Bind the endpoint.
|
|
117
|
+
#[napi]
|
|
118
|
+
pub async fn bind(&self) -> Result<Endpoint> {
|
|
119
|
+
let builder = self
|
|
120
|
+
.inner
|
|
121
|
+
.lock()
|
|
122
|
+
.unwrap()
|
|
123
|
+
.take()
|
|
124
|
+
.ok_or_else(|| anyhow::anyhow!("EndpointBuilder already consumed"))?;
|
|
125
|
+
let endpoint = builder.bind().await.map_err(|e| anyhow::anyhow!("{e:?}"))?;
|
|
126
|
+
Ok(Endpoint { inner: endpoint })
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/// The n0 production preset (relays + discovery).
|
|
131
|
+
#[napi]
|
|
132
|
+
pub fn preset_n0(builder: &EndpointBuilder) {
|
|
133
|
+
builder.apply_n0();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/// The minimal preset (no external dependencies; good for tests / offline).
|
|
137
|
+
#[napi]
|
|
138
|
+
pub fn preset_minimal(builder: &EndpointBuilder) {
|
|
139
|
+
builder.apply_minimal();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/// The n0 preset with relays disabled.
|
|
143
|
+
#[napi]
|
|
144
|
+
pub fn preset_n0_disable_relay(builder: &EndpointBuilder) {
|
|
145
|
+
builder.apply_n0_disable_relay();
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/// Which side of a connection we are.
|
|
149
|
+
#[derive(Debug, Clone, Copy)]
|
|
150
|
+
#[napi(string_enum)]
|
|
151
|
+
pub enum Side {
|
|
152
|
+
Client,
|
|
153
|
+
Server,
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
impl From<iroh::endpoint::Side> for Side {
|
|
157
|
+
fn from(s: iroh::endpoint::Side) -> Self {
|
|
158
|
+
match s {
|
|
159
|
+
iroh::endpoint::Side::Client => Side::Client,
|
|
160
|
+
iroh::endpoint::Side::Server => Side::Server,
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/// Where an incoming connection came from.
|
|
166
|
+
#[derive(Debug, Clone)]
|
|
167
|
+
#[napi(object)]
|
|
168
|
+
pub struct IncomingAddr {
|
|
169
|
+
/// One of "ip" | "relay" | "custom".
|
|
170
|
+
pub kind: String,
|
|
171
|
+
/// `ip:port` for ip, relay URL for relay.
|
|
172
|
+
pub addr: Option<String>,
|
|
173
|
+
/// Remote endpoint id (relay only).
|
|
174
|
+
pub endpoint_id: Option<String>,
|
|
175
|
+
/// Debug description (custom only).
|
|
176
|
+
pub description: Option<String>,
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
impl From<iroh::endpoint::IncomingAddr> for IncomingAddr {
|
|
180
|
+
fn from(addr: iroh::endpoint::IncomingAddr) -> Self {
|
|
181
|
+
match addr {
|
|
182
|
+
iroh::endpoint::IncomingAddr::Ip(socket) => IncomingAddr {
|
|
183
|
+
kind: "ip".into(),
|
|
184
|
+
addr: Some(socket.to_string()),
|
|
185
|
+
endpoint_id: None,
|
|
186
|
+
description: None,
|
|
187
|
+
},
|
|
188
|
+
iroh::endpoint::IncomingAddr::Relay { url, endpoint_id } => IncomingAddr {
|
|
189
|
+
kind: "relay".into(),
|
|
190
|
+
addr: Some(url.to_string()),
|
|
191
|
+
endpoint_id: Some(endpoint_id.to_string()),
|
|
192
|
+
description: None,
|
|
193
|
+
},
|
|
194
|
+
iroh::endpoint::IncomingAddr::Custom(c) => IncomingAddr {
|
|
195
|
+
kind: "custom".into(),
|
|
196
|
+
addr: None,
|
|
197
|
+
endpoint_id: None,
|
|
198
|
+
description: Some(format!("{c:?}")),
|
|
199
|
+
},
|
|
200
|
+
_ => IncomingAddr {
|
|
201
|
+
kind: "custom".into(),
|
|
202
|
+
addr: None,
|
|
203
|
+
endpoint_id: None,
|
|
204
|
+
description: Some("unknown".into()),
|
|
205
|
+
},
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/// The local address that received an incoming connection.
|
|
211
|
+
#[derive(Debug, Clone)]
|
|
212
|
+
#[napi(object)]
|
|
213
|
+
pub struct IncomingLocalAddr {
|
|
214
|
+
/// One of "ip" | "relay" | "custom".
|
|
215
|
+
pub kind: String,
|
|
216
|
+
pub addr: Option<String>,
|
|
217
|
+
pub description: Option<String>,
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
impl From<iroh::endpoint::LocalTransportAddr> for IncomingLocalAddr {
|
|
221
|
+
fn from(value: iroh::endpoint::LocalTransportAddr) -> Self {
|
|
222
|
+
match value {
|
|
223
|
+
iroh::endpoint::LocalTransportAddr::Ip(ip) => IncomingLocalAddr {
|
|
224
|
+
kind: "ip".into(),
|
|
225
|
+
addr: ip.map(|i| i.to_string()),
|
|
226
|
+
description: None,
|
|
227
|
+
},
|
|
228
|
+
iroh::endpoint::LocalTransportAddr::Relay(url) => IncomingLocalAddr {
|
|
229
|
+
kind: "relay".into(),
|
|
230
|
+
addr: Some(url.to_string()),
|
|
231
|
+
description: None,
|
|
232
|
+
},
|
|
233
|
+
iroh::endpoint::LocalTransportAddr::Custom(c) => IncomingLocalAddr {
|
|
234
|
+
kind: "custom".into(),
|
|
235
|
+
addr: None,
|
|
236
|
+
description: c.map(|c| format!("{c:?}")),
|
|
237
|
+
},
|
|
238
|
+
_ => IncomingLocalAddr {
|
|
239
|
+
kind: "custom".into(),
|
|
240
|
+
addr: None,
|
|
241
|
+
description: None,
|
|
242
|
+
},
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/// A snapshot value for a single endpoint metric.
|
|
248
|
+
#[derive(Debug, Clone)]
|
|
249
|
+
#[napi(object)]
|
|
250
|
+
pub struct CounterStats {
|
|
251
|
+
pub value: u32,
|
|
252
|
+
pub description: String,
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/// Flat snapshot of headline connection statistics.
|
|
256
|
+
#[derive(Debug, Clone)]
|
|
257
|
+
#[napi(object)]
|
|
258
|
+
pub struct ConnectionStats {
|
|
259
|
+
pub udp_tx_datagrams: i64,
|
|
260
|
+
pub udp_tx_bytes: i64,
|
|
261
|
+
pub udp_rx_datagrams: i64,
|
|
262
|
+
pub udp_rx_bytes: i64,
|
|
263
|
+
pub lost_packets: i64,
|
|
264
|
+
pub lost_bytes: i64,
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/// Options passed to [`Endpoint::bind`].
|
|
268
|
+
///
|
|
269
|
+
/// `bind` applies the n0 preset by default. For a custom preset use
|
|
270
|
+
/// [`Endpoint::builder`] + the `EndpointBuilder` surface.
|
|
271
|
+
#[derive(Debug, Default)]
|
|
272
|
+
#[napi(object)]
|
|
273
|
+
pub struct EndpointOptions {
|
|
274
|
+
pub bind_addr: Option<String>,
|
|
275
|
+
pub secret_key: Option<Vec<u8>>,
|
|
276
|
+
pub alpns: Option<Vec<Vec<u8>>>,
|
|
277
|
+
/// Force all traffic over relays ("relay-only" mode).
|
|
278
|
+
///
|
|
279
|
+
/// When `true`, removes all IP based transports (no direct connections or
|
|
280
|
+
/// hole punching) and limits the addresses published to discovery to relay
|
|
281
|
+
/// URLs only. Defaults to `false` (n0 preset behaviour unchanged).
|
|
282
|
+
pub relay_only: Option<bool>,
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/// An iroh endpoint.
|
|
286
|
+
#[napi]
|
|
287
|
+
pub struct Endpoint {
|
|
288
|
+
inner: endpoint::Endpoint,
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
impl Endpoint {
|
|
292
|
+
pub(crate) fn raw(&self) -> &endpoint::Endpoint {
|
|
293
|
+
&self.inner
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
#[napi]
|
|
298
|
+
impl Endpoint {
|
|
299
|
+
/// Create an endpoint builder (starts empty — apply a preset).
|
|
300
|
+
#[napi]
|
|
301
|
+
pub fn builder() -> EndpointBuilder {
|
|
302
|
+
EndpointBuilder::new(iroh::endpoint::Builder::empty())
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/// Bind a new endpoint. Applies the n0 preset, then the given options.
|
|
306
|
+
/// For a custom preset use [`Endpoint::builder`].
|
|
307
|
+
#[napi(factory)]
|
|
308
|
+
pub async fn bind(
|
|
309
|
+
options: Option<EndpointOptions>,
|
|
310
|
+
relay_mode: Option<&RelayMode>,
|
|
311
|
+
) -> Result<Self> {
|
|
312
|
+
let options = options.unwrap_or_default();
|
|
313
|
+
let wrapper = EndpointBuilder::new(iroh::endpoint::Builder::empty());
|
|
314
|
+
wrapper.apply_n0();
|
|
315
|
+
|
|
316
|
+
if let Some(secret_key) = options.secret_key {
|
|
317
|
+
wrapper.secret_key(secret_key)?;
|
|
318
|
+
}
|
|
319
|
+
if let Some(alpns) = options.alpns {
|
|
320
|
+
wrapper.alpns(alpns);
|
|
321
|
+
}
|
|
322
|
+
if let Some(relay_mode) = relay_mode {
|
|
323
|
+
wrapper.relay_mode(relay_mode);
|
|
324
|
+
}
|
|
325
|
+
if let Some(addr) = options.bind_addr {
|
|
326
|
+
wrapper.bind_addr(addr)?;
|
|
327
|
+
}
|
|
328
|
+
// Apply relay-only last so it also clears any IP transport that the
|
|
329
|
+
// n0 preset or `bind_addr` installed above.
|
|
330
|
+
if options.relay_only.unwrap_or(false) {
|
|
331
|
+
wrapper.clear_ip_transports();
|
|
332
|
+
wrapper.addr_filter_relay_only();
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
wrapper.bind().await
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/// This endpoint's id.
|
|
339
|
+
#[napi]
|
|
340
|
+
pub fn id(&self) -> crate::EndpointId {
|
|
341
|
+
self.inner.id().into()
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/// The [`EndpointAddr`] for this endpoint.
|
|
345
|
+
#[napi]
|
|
346
|
+
pub fn addr(&self) -> EndpointAddr {
|
|
347
|
+
self.inner.addr().into()
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/// Look up cached information about a remote endpoint, if any.
|
|
351
|
+
#[napi]
|
|
352
|
+
pub async fn remote_addr(&self, id: &crate::EndpointId) -> Result<Option<EndpointAddr>> {
|
|
353
|
+
let id: iroh::EndpointId = id.into();
|
|
354
|
+
let info = match self.inner.remote_info(id).await {
|
|
355
|
+
Some(i) => i,
|
|
356
|
+
None => return Ok(None),
|
|
357
|
+
};
|
|
358
|
+
let id = info.id();
|
|
359
|
+
let addrs = info.into_addrs().map(|a| a.into_addr());
|
|
360
|
+
Ok(Some(iroh::EndpointAddr::from_parts(id, addrs).into()))
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/// Current statistics for this endpoint.
|
|
364
|
+
#[napi]
|
|
365
|
+
pub fn stats(&self) -> std::collections::HashMap<String, CounterStats> {
|
|
366
|
+
use iroh_metrics::{MetricValue, MetricsGroupSet};
|
|
367
|
+
self.inner
|
|
368
|
+
.metrics()
|
|
369
|
+
.iter()
|
|
370
|
+
.map(|(group, item)| {
|
|
371
|
+
let name = format!("{}:{}", group, item.name());
|
|
372
|
+
let value = match item.value() {
|
|
373
|
+
MetricValue::Counter(v) => u32::try_from(v).unwrap_or(u32::MAX),
|
|
374
|
+
MetricValue::Gauge(v) => u32::try_from(v.max(0)).unwrap_or(u32::MAX),
|
|
375
|
+
_ => 0,
|
|
376
|
+
};
|
|
377
|
+
(
|
|
378
|
+
name,
|
|
379
|
+
CounterStats {
|
|
380
|
+
value,
|
|
381
|
+
description: item.help().to_string(),
|
|
382
|
+
},
|
|
383
|
+
)
|
|
384
|
+
})
|
|
385
|
+
.collect()
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/// The secret key backing this endpoint's identity.
|
|
389
|
+
#[napi]
|
|
390
|
+
pub fn secret_key(&self) -> SecretKey {
|
|
391
|
+
self.inner.secret_key().clone().into()
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/// Replace the set of advertised ALPNs.
|
|
395
|
+
#[napi]
|
|
396
|
+
pub fn set_alpns(&self, alpns: Vec<Vec<u8>>) {
|
|
397
|
+
self.inner.set_alpns(alpns);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/// Add an external (manually-known) socket address.
|
|
401
|
+
#[napi]
|
|
402
|
+
pub async fn add_external_addr(&self, addr: String) -> Result<()> {
|
|
403
|
+
let socket = std::net::SocketAddr::from_str(&addr).map_err(anyhow::Error::from)?;
|
|
404
|
+
self.inner.add_external_addr(socket).await;
|
|
405
|
+
Ok(())
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/// Remove a previously-added external address.
|
|
409
|
+
#[napi]
|
|
410
|
+
pub async fn remove_external_addr(&self, addr: String) -> Result<bool> {
|
|
411
|
+
let socket = std::net::SocketAddr::from_str(&addr).map_err(anyhow::Error::from)?;
|
|
412
|
+
Ok(self.inner.remove_external_addr(&socket).await)
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/// The local socket addresses this endpoint is bound to.
|
|
416
|
+
#[napi]
|
|
417
|
+
pub fn bound_sockets(&self) -> Vec<String> {
|
|
418
|
+
self.inner
|
|
419
|
+
.bound_sockets()
|
|
420
|
+
.into_iter()
|
|
421
|
+
.map(|a| a.to_string())
|
|
422
|
+
.collect()
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/// Resolves once the endpoint has a usable home relay.
|
|
426
|
+
#[napi]
|
|
427
|
+
pub async fn online(&self) {
|
|
428
|
+
self.inner.online().await;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/// Insert (or replace) a relay configuration at runtime.
|
|
432
|
+
#[napi]
|
|
433
|
+
pub async fn insert_relay(&self, config: crate::RelayConfig) -> Result<()> {
|
|
434
|
+
let config: iroh::RelayConfig = config.try_into()?;
|
|
435
|
+
let url = config.url.clone();
|
|
436
|
+
self.inner.insert_relay(url, Arc::new(config)).await;
|
|
437
|
+
Ok(())
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/// Remove a relay configuration at runtime.
|
|
441
|
+
#[napi]
|
|
442
|
+
pub async fn remove_relay(&self, url: String) -> Result<bool> {
|
|
443
|
+
let url = iroh::RelayUrl::from_str(&url).map_err(anyhow::Error::from)?;
|
|
444
|
+
Ok(self.inner.remove_relay(&url).await.is_some())
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/// Connect to a remote endpoint via the given ALPN.
|
|
448
|
+
#[napi]
|
|
449
|
+
pub async fn connect(&self, addr: &EndpointAddr, alpn: Vec<u8>) -> Result<Connection> {
|
|
450
|
+
let addr: iroh::EndpointAddr = addr.try_into()?;
|
|
451
|
+
let conn = self
|
|
452
|
+
.inner
|
|
453
|
+
.connect(addr, &alpn)
|
|
454
|
+
.await
|
|
455
|
+
.map_err(|e| anyhow::anyhow!("{e:?}"))?;
|
|
456
|
+
Ok(Connection(Arc::new(conn)))
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/// Begin a connection attempt, returning the in-progress handle.
|
|
460
|
+
#[napi]
|
|
461
|
+
pub async fn connect_pending(&self, addr: &EndpointAddr, alpn: Vec<u8>) -> Result<Connecting> {
|
|
462
|
+
let addr: iroh::EndpointAddr = addr.try_into()?;
|
|
463
|
+
let connecting = self
|
|
464
|
+
.inner
|
|
465
|
+
.connect_with_opts(addr, &alpn, iroh::endpoint::ConnectOptions::default())
|
|
466
|
+
.await
|
|
467
|
+
.map_err(|e| anyhow::anyhow!("{e:?}"))?;
|
|
468
|
+
Ok(Connecting(Mutex::new(Some(connecting))))
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/// Pull the next incoming connection attempt.
|
|
472
|
+
#[napi]
|
|
473
|
+
pub async fn accept_next(&self) -> Option<Incoming> {
|
|
474
|
+
let inner = self.inner.accept().await?;
|
|
475
|
+
Some(Incoming(Mutex::new(Some(inner))))
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/// Watch for changes to this endpoint's address.
|
|
479
|
+
#[napi(ts_args_type = "callback: (addr: EndpointAddr) => void")]
|
|
480
|
+
pub fn watch_addr(&self, callback: ThreadsafeFunction<EndpointAddr>) -> WatchHandle {
|
|
481
|
+
watch::spawn_watch_addr(self.inner.clone(), callback)
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/// Watch for changes to the connected relays.
|
|
485
|
+
#[napi(ts_args_type = "callback: (relayUrls: Array<string>) => void")]
|
|
486
|
+
pub fn watch_home_relay(&self, callback: ThreadsafeFunction<Vec<String>>) -> WatchHandle {
|
|
487
|
+
watch::spawn_home_relay_watch(self.inner.clone(), callback)
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/// Watch for network-stack changes.
|
|
491
|
+
#[napi(ts_args_type = "callback: () => void")]
|
|
492
|
+
pub fn watch_network_change(&self, callback: ThreadsafeFunction<()>) -> WatchHandle {
|
|
493
|
+
watch::spawn_network_change_watch(self.inner.clone(), callback)
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/// Close the endpoint.
|
|
497
|
+
#[napi]
|
|
498
|
+
pub async fn close(&self) {
|
|
499
|
+
self.inner.close().await;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
/// True if the endpoint is closed.
|
|
503
|
+
#[napi]
|
|
504
|
+
pub fn is_closed(&self) -> bool {
|
|
505
|
+
self.inner.is_closed()
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/// An incoming connection that has not yet begun its server-side handshake.
|
|
510
|
+
#[napi]
|
|
511
|
+
pub struct Incoming(Mutex<Option<iroh::endpoint::Incoming>>);
|
|
512
|
+
|
|
513
|
+
#[napi]
|
|
514
|
+
impl Incoming {
|
|
515
|
+
#[napi]
|
|
516
|
+
pub async fn accept(&self) -> Result<Accepting> {
|
|
517
|
+
let inner = self
|
|
518
|
+
.0
|
|
519
|
+
.lock()
|
|
520
|
+
.await
|
|
521
|
+
.take()
|
|
522
|
+
.ok_or_else(|| anyhow::anyhow!("Incoming already consumed"))?;
|
|
523
|
+
let accepting = inner.accept().map_err(|e| anyhow::anyhow!("{e:?}"))?;
|
|
524
|
+
Ok(Accepting(Mutex::new(Some(accepting))))
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
#[napi]
|
|
528
|
+
pub async fn refuse(&self) -> Result<()> {
|
|
529
|
+
let inner = self
|
|
530
|
+
.0
|
|
531
|
+
.lock()
|
|
532
|
+
.await
|
|
533
|
+
.take()
|
|
534
|
+
.ok_or_else(|| anyhow::anyhow!("Incoming already consumed"))?;
|
|
535
|
+
inner.refuse();
|
|
536
|
+
Ok(())
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
#[napi]
|
|
540
|
+
pub async fn retry(&self) -> Result<()> {
|
|
541
|
+
let inner = self
|
|
542
|
+
.0
|
|
543
|
+
.lock()
|
|
544
|
+
.await
|
|
545
|
+
.take()
|
|
546
|
+
.ok_or_else(|| anyhow::anyhow!("Incoming already consumed"))?;
|
|
547
|
+
inner
|
|
548
|
+
.retry()
|
|
549
|
+
.map_err(|e| anyhow::anyhow!("retry failed: {e:?}").into())
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
#[napi]
|
|
553
|
+
pub async fn ignore(&self) -> Result<()> {
|
|
554
|
+
let inner = self
|
|
555
|
+
.0
|
|
556
|
+
.lock()
|
|
557
|
+
.await
|
|
558
|
+
.take()
|
|
559
|
+
.ok_or_else(|| anyhow::anyhow!("Incoming already consumed"))?;
|
|
560
|
+
inner.ignore();
|
|
561
|
+
Ok(())
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
#[napi]
|
|
565
|
+
pub async fn local_addr(&self) -> Result<IncomingLocalAddr> {
|
|
566
|
+
let guard = self.0.lock().await;
|
|
567
|
+
let inner = guard
|
|
568
|
+
.as_ref()
|
|
569
|
+
.ok_or_else(|| anyhow::anyhow!("Incoming already consumed"))?;
|
|
570
|
+
Ok(inner.local_addr().into())
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
#[napi]
|
|
574
|
+
pub async fn remote_addr(&self) -> Result<IncomingAddr> {
|
|
575
|
+
let guard = self.0.lock().await;
|
|
576
|
+
let inner = guard
|
|
577
|
+
.as_ref()
|
|
578
|
+
.ok_or_else(|| anyhow::anyhow!("Incoming already consumed"))?;
|
|
579
|
+
Ok(inner.remote_addr().into())
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
#[napi]
|
|
583
|
+
pub async fn remote_addr_validated(&self) -> Result<bool> {
|
|
584
|
+
let guard = self.0.lock().await;
|
|
585
|
+
let inner = guard
|
|
586
|
+
.as_ref()
|
|
587
|
+
.ok_or_else(|| anyhow::anyhow!("Incoming already consumed"))?;
|
|
588
|
+
Ok(inner.remote_addr_validated())
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/// A server-side handshake in progress.
|
|
593
|
+
#[napi]
|
|
594
|
+
pub struct Accepting(Mutex<Option<iroh::endpoint::Accepting>>);
|
|
595
|
+
|
|
596
|
+
#[napi]
|
|
597
|
+
impl Accepting {
|
|
598
|
+
#[napi]
|
|
599
|
+
pub async fn connect(&self) -> Result<Connection> {
|
|
600
|
+
let inner = self
|
|
601
|
+
.0
|
|
602
|
+
.lock()
|
|
603
|
+
.await
|
|
604
|
+
.take()
|
|
605
|
+
.ok_or_else(|| anyhow::anyhow!("Accepting already consumed"))?;
|
|
606
|
+
let conn = inner.await.map_err(|e| anyhow::anyhow!("{e:?}"))?;
|
|
607
|
+
Ok(Connection(Arc::new(conn)))
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
#[napi]
|
|
611
|
+
pub async fn alpn(&self) -> Result<Vec<u8>> {
|
|
612
|
+
let mut guard = self.0.lock().await;
|
|
613
|
+
let inner = guard
|
|
614
|
+
.as_mut()
|
|
615
|
+
.ok_or_else(|| anyhow::anyhow!("Accepting already consumed"))?;
|
|
616
|
+
inner
|
|
617
|
+
.alpn()
|
|
618
|
+
.await
|
|
619
|
+
.map_err(|e| anyhow::anyhow!("{e:?}").into())
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
/// A client-side handshake in progress.
|
|
624
|
+
#[napi]
|
|
625
|
+
pub struct Connecting(Mutex<Option<iroh::endpoint::Connecting>>);
|
|
626
|
+
|
|
627
|
+
#[napi]
|
|
628
|
+
impl Connecting {
|
|
629
|
+
#[napi]
|
|
630
|
+
pub async fn connect(&self) -> Result<Connection> {
|
|
631
|
+
let inner = self
|
|
632
|
+
.0
|
|
633
|
+
.lock()
|
|
634
|
+
.await
|
|
635
|
+
.take()
|
|
636
|
+
.ok_or_else(|| anyhow::anyhow!("Connecting already consumed"))?;
|
|
637
|
+
let conn = inner.await.map_err(|e| anyhow::anyhow!("{e:?}"))?;
|
|
638
|
+
Ok(Connection(Arc::new(conn)))
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
#[napi]
|
|
642
|
+
pub async fn alpn(&self) -> Result<Vec<u8>> {
|
|
643
|
+
let mut guard = self.0.lock().await;
|
|
644
|
+
let inner = guard
|
|
645
|
+
.as_mut()
|
|
646
|
+
.ok_or_else(|| anyhow::anyhow!("Connecting already consumed"))?;
|
|
647
|
+
inner
|
|
648
|
+
.alpn()
|
|
649
|
+
.await
|
|
650
|
+
.map_err(|e| anyhow::anyhow!("{e:?}").into())
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
#[napi]
|
|
654
|
+
pub async fn remote_id(&self) -> Result<crate::EndpointId> {
|
|
655
|
+
let guard = self.0.lock().await;
|
|
656
|
+
let inner = guard
|
|
657
|
+
.as_ref()
|
|
658
|
+
.ok_or_else(|| anyhow::anyhow!("Connecting already consumed"))?;
|
|
659
|
+
Ok(inner.remote_id().into())
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
/// An active QUIC connection.
|
|
664
|
+
#[napi]
|
|
665
|
+
pub struct Connection(Arc<endpoint::Connection>);
|
|
666
|
+
|
|
667
|
+
#[napi]
|
|
668
|
+
impl Connection {
|
|
669
|
+
#[napi]
|
|
670
|
+
pub fn alpn(&self) -> Vec<u8> {
|
|
671
|
+
self.0.alpn().to_vec()
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
#[napi]
|
|
675
|
+
pub fn remote_id(&self) -> crate::EndpointId {
|
|
676
|
+
self.0.remote_id().into()
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
#[napi]
|
|
680
|
+
pub fn side(&self) -> Side {
|
|
681
|
+
self.0.side().into()
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
#[napi]
|
|
685
|
+
pub async fn open_uni(&self) -> Result<SendStream> {
|
|
686
|
+
let s = self
|
|
687
|
+
.0
|
|
688
|
+
.open_uni()
|
|
689
|
+
.await
|
|
690
|
+
.map_err(|e| anyhow::anyhow!("{e:?}"))?;
|
|
691
|
+
Ok(SendStream::new(s))
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
#[napi]
|
|
695
|
+
pub async fn accept_uni(&self) -> Result<RecvStream> {
|
|
696
|
+
let r = self
|
|
697
|
+
.0
|
|
698
|
+
.accept_uni()
|
|
699
|
+
.await
|
|
700
|
+
.map_err(|e| anyhow::anyhow!("{e:?}"))?;
|
|
701
|
+
Ok(RecvStream::new(r))
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
#[napi]
|
|
705
|
+
pub async fn open_bi(&self) -> Result<BiStream> {
|
|
706
|
+
let (s, r) = self
|
|
707
|
+
.0
|
|
708
|
+
.open_bi()
|
|
709
|
+
.await
|
|
710
|
+
.map_err(|e| anyhow::anyhow!("{e:?}"))?;
|
|
711
|
+
Ok(BiStream {
|
|
712
|
+
send: SendStream::new(s),
|
|
713
|
+
recv: RecvStream::new(r),
|
|
714
|
+
})
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
#[napi]
|
|
718
|
+
pub async fn accept_bi(&self) -> Result<BiStream> {
|
|
719
|
+
let (s, r) = self
|
|
720
|
+
.0
|
|
721
|
+
.accept_bi()
|
|
722
|
+
.await
|
|
723
|
+
.map_err(|e| anyhow::anyhow!("{e:?}"))?;
|
|
724
|
+
Ok(BiStream {
|
|
725
|
+
send: SendStream::new(s),
|
|
726
|
+
recv: RecvStream::new(r),
|
|
727
|
+
})
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
#[napi]
|
|
731
|
+
pub async fn read_datagram(&self) -> Result<Vec<u8>> {
|
|
732
|
+
let res = self
|
|
733
|
+
.0
|
|
734
|
+
.read_datagram()
|
|
735
|
+
.await
|
|
736
|
+
.map_err(|e| anyhow::anyhow!("{e:?}"))?;
|
|
737
|
+
Ok(res.to_vec())
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
#[napi]
|
|
741
|
+
pub async fn closed(&self) -> String {
|
|
742
|
+
self.0.closed().await.to_string()
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
#[napi]
|
|
746
|
+
pub fn close_reason(&self) -> Option<String> {
|
|
747
|
+
self.0.close_reason().map(|s| s.to_string())
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
#[napi]
|
|
751
|
+
pub fn close(&self, error_code: BigInt, reason: Vec<u8>) -> Result<()> {
|
|
752
|
+
let code =
|
|
753
|
+
endpoint::VarInt::from_u64(error_code.get_u64().1).map_err(anyhow::Error::from)?;
|
|
754
|
+
self.0.close(code, &reason);
|
|
755
|
+
Ok(())
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
#[napi]
|
|
759
|
+
pub fn send_datagram(&self, data: Vec<u8>) -> Result<()> {
|
|
760
|
+
self.0
|
|
761
|
+
.send_datagram(data.into())
|
|
762
|
+
.map_err(|e| anyhow::anyhow!("{e:?}"))?;
|
|
763
|
+
Ok(())
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
#[napi]
|
|
767
|
+
pub async fn send_datagram_wait(&self, data: Vec<u8>) -> Result<()> {
|
|
768
|
+
self.0
|
|
769
|
+
.send_datagram_wait(data.into())
|
|
770
|
+
.await
|
|
771
|
+
.map_err(|e| anyhow::anyhow!("{e:?}"))?;
|
|
772
|
+
Ok(())
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
#[napi]
|
|
776
|
+
pub fn max_datagram_size(&self) -> Option<i64> {
|
|
777
|
+
self.0.max_datagram_size().map(|s| s as i64)
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
#[napi]
|
|
781
|
+
pub fn datagram_send_buffer_space(&self) -> i64 {
|
|
782
|
+
self.0.datagram_send_buffer_space() as i64
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
#[napi]
|
|
786
|
+
pub fn stable_id(&self) -> u32 {
|
|
787
|
+
self.0.stable_id() as _
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
#[napi]
|
|
791
|
+
pub fn rtt(&self) -> Option<i64> {
|
|
792
|
+
self.0
|
|
793
|
+
.paths()
|
|
794
|
+
.iter()
|
|
795
|
+
.find(|p| p.is_selected())
|
|
796
|
+
.map(|p| p.rtt().as_millis() as i64)
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
#[napi]
|
|
800
|
+
pub fn stats(&self) -> ConnectionStats {
|
|
801
|
+
let s = self.0.stats();
|
|
802
|
+
ConnectionStats {
|
|
803
|
+
udp_tx_datagrams: s.udp_tx.datagrams as i64,
|
|
804
|
+
udp_tx_bytes: s.udp_tx.bytes as i64,
|
|
805
|
+
udp_rx_datagrams: s.udp_rx.datagrams as i64,
|
|
806
|
+
udp_rx_bytes: s.udp_rx.bytes as i64,
|
|
807
|
+
lost_packets: s.lost_packets as i64,
|
|
808
|
+
lost_bytes: s.lost_bytes as i64,
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
#[napi]
|
|
813
|
+
pub fn paths(&self) -> Vec<path::PathSnapshot> {
|
|
814
|
+
path::snapshot_paths(&self.0)
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
#[napi(ts_args_type = "callback: (paths: Array<PathSnapshot>) => void")]
|
|
818
|
+
pub fn watch_paths(
|
|
819
|
+
&self,
|
|
820
|
+
callback: ThreadsafeFunction<Vec<path::PathSnapshot>>,
|
|
821
|
+
) -> WatchHandle {
|
|
822
|
+
watch::spawn_paths_watch((*self.0).clone(), callback)
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
#[napi(ts_args_type = "callback: (event: PathEvent) => void")]
|
|
826
|
+
pub fn watch_path_events(&self, callback: ThreadsafeFunction<path::PathEvent>) -> WatchHandle {
|
|
827
|
+
watch::spawn_path_events_watch((*self.0).clone(), callback)
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
#[napi]
|
|
831
|
+
pub fn set_max_concurrent_uni_streams(&self, count: BigInt) -> Result<()> {
|
|
832
|
+
let n = endpoint::VarInt::from_u64(count.get_u64().1).map_err(anyhow::Error::from)?;
|
|
833
|
+
self.0.set_max_concurrent_uni_streams(n);
|
|
834
|
+
Ok(())
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
#[napi]
|
|
838
|
+
pub fn set_receive_window(&self, count: BigInt) -> Result<()> {
|
|
839
|
+
let n = endpoint::VarInt::from_u64(count.get_u64().1).map_err(anyhow::Error::from)?;
|
|
840
|
+
self.0.set_receive_window(n);
|
|
841
|
+
Ok(())
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
#[napi]
|
|
845
|
+
pub fn set_max_concurrent_bi_streams(&self, count: BigInt) -> Result<()> {
|
|
846
|
+
let n = endpoint::VarInt::from_u64(count.get_u64().1).map_err(anyhow::Error::from)?;
|
|
847
|
+
self.0.set_max_concurrent_bi_streams(n);
|
|
848
|
+
Ok(())
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
/// A bidirectional QUIC stream pair.
|
|
853
|
+
#[napi]
|
|
854
|
+
pub struct BiStream {
|
|
855
|
+
send: SendStream,
|
|
856
|
+
recv: RecvStream,
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
#[napi]
|
|
860
|
+
impl BiStream {
|
|
861
|
+
#[napi(getter)]
|
|
862
|
+
pub fn send(&self) -> SendStream {
|
|
863
|
+
self.send.clone()
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
#[napi(getter)]
|
|
867
|
+
pub fn recv(&self) -> RecvStream {
|
|
868
|
+
self.recv.clone()
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
/// The outgoing half of a QUIC stream.
|
|
873
|
+
#[derive(Clone)]
|
|
874
|
+
#[napi]
|
|
875
|
+
pub struct SendStream(Arc<Mutex<endpoint::SendStream>>);
|
|
876
|
+
|
|
877
|
+
impl SendStream {
|
|
878
|
+
fn new(s: endpoint::SendStream) -> Self {
|
|
879
|
+
SendStream(Arc::new(Mutex::new(s)))
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
#[napi]
|
|
884
|
+
impl SendStream {
|
|
885
|
+
#[napi]
|
|
886
|
+
pub async fn write(&self, buf: Vec<u8>) -> Result<i64> {
|
|
887
|
+
let mut s = self.0.lock().await;
|
|
888
|
+
let n = s.write(&buf).await.map_err(|e| anyhow::anyhow!("{e:?}"))?;
|
|
889
|
+
Ok(n as i64)
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
#[napi]
|
|
893
|
+
pub async fn write_all(&self, buf: Vec<u8>) -> Result<()> {
|
|
894
|
+
let mut s = self.0.lock().await;
|
|
895
|
+
s.write_all(&buf)
|
|
896
|
+
.await
|
|
897
|
+
.map_err(|e| anyhow::anyhow!("{e:?}"))?;
|
|
898
|
+
Ok(())
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
#[napi]
|
|
902
|
+
pub async fn finish(&self) -> Result<()> {
|
|
903
|
+
let mut s = self.0.lock().await;
|
|
904
|
+
s.finish().map_err(|e| anyhow::anyhow!("{e:?}"))?;
|
|
905
|
+
Ok(())
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
#[napi]
|
|
909
|
+
pub async fn reset(&self, error_code: BigInt) -> Result<()> {
|
|
910
|
+
let code =
|
|
911
|
+
endpoint::VarInt::from_u64(error_code.get_u64().1).map_err(anyhow::Error::from)?;
|
|
912
|
+
let mut s = self.0.lock().await;
|
|
913
|
+
s.reset(code).map_err(|e| anyhow::anyhow!("{e:?}"))?;
|
|
914
|
+
Ok(())
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
#[napi]
|
|
918
|
+
pub async fn set_priority(&self, p: i32) -> Result<()> {
|
|
919
|
+
let s = self.0.lock().await;
|
|
920
|
+
s.set_priority(p).map_err(|e| anyhow::anyhow!("{e:?}"))?;
|
|
921
|
+
Ok(())
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
#[napi]
|
|
925
|
+
pub async fn priority(&self) -> Result<i32> {
|
|
926
|
+
let s = self.0.lock().await;
|
|
927
|
+
s.priority().map_err(|e| anyhow::anyhow!("{e:?}").into())
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
#[napi]
|
|
931
|
+
pub async fn stopped(&self) -> Result<Option<i64>> {
|
|
932
|
+
let s = self.0.lock().await;
|
|
933
|
+
let res = s.stopped().await.map_err(|e| anyhow::anyhow!("{e:?}"))?;
|
|
934
|
+
Ok(res.map(|r| r.into_inner() as i64))
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
#[napi]
|
|
938
|
+
pub async fn id(&self) -> String {
|
|
939
|
+
self.0.lock().await.id().to_string()
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
/// The incoming half of a QUIC stream.
|
|
944
|
+
#[derive(Clone)]
|
|
945
|
+
#[napi]
|
|
946
|
+
pub struct RecvStream(Arc<Mutex<endpoint::RecvStream>>);
|
|
947
|
+
|
|
948
|
+
impl RecvStream {
|
|
949
|
+
fn new(s: endpoint::RecvStream) -> Self {
|
|
950
|
+
RecvStream(Arc::new(Mutex::new(s)))
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
#[napi]
|
|
955
|
+
impl RecvStream {
|
|
956
|
+
#[napi]
|
|
957
|
+
pub async fn read(&self, size_limit: u32) -> Result<Vec<u8>> {
|
|
958
|
+
let mut buf = vec![0u8; size_limit as usize];
|
|
959
|
+
let mut r = self.0.lock().await;
|
|
960
|
+
let res = r
|
|
961
|
+
.read(&mut buf)
|
|
962
|
+
.await
|
|
963
|
+
.map_err(|e| anyhow::anyhow!("{e:?}"))?;
|
|
964
|
+
let len = res.unwrap_or(0);
|
|
965
|
+
buf.truncate(len);
|
|
966
|
+
Ok(buf)
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
#[napi]
|
|
970
|
+
pub async fn read_exact(&self, size: u32) -> Result<Vec<u8>> {
|
|
971
|
+
let mut buf = vec![0u8; size as usize];
|
|
972
|
+
let mut r = self.0.lock().await;
|
|
973
|
+
r.read_exact(&mut buf)
|
|
974
|
+
.await
|
|
975
|
+
.map_err(|e| anyhow::anyhow!("{e:?}"))?;
|
|
976
|
+
Ok(buf)
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
#[napi]
|
|
980
|
+
pub async fn read_to_end(&self, size_limit: u32) -> Result<Vec<u8>> {
|
|
981
|
+
let mut r = self.0.lock().await;
|
|
982
|
+
let res = r
|
|
983
|
+
.read_to_end(size_limit as usize)
|
|
984
|
+
.await
|
|
985
|
+
.map_err(|e| anyhow::anyhow!("{e:?}"))?;
|
|
986
|
+
Ok(res)
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
#[napi]
|
|
990
|
+
pub async fn id(&self) -> String {
|
|
991
|
+
self.0.lock().await.id().to_string()
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
#[napi]
|
|
995
|
+
pub async fn bytes_read(&self) -> Result<i64> {
|
|
996
|
+
let r = self.0.lock().await;
|
|
997
|
+
Ok(r.bytes_read().map_err(|e| anyhow::anyhow!("{e:?}"))? as i64)
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
#[napi]
|
|
1001
|
+
pub async fn stop(&self, error_code: BigInt) -> Result<()> {
|
|
1002
|
+
let code =
|
|
1003
|
+
endpoint::VarInt::from_u64(error_code.get_u64().1).map_err(anyhow::Error::from)?;
|
|
1004
|
+
let mut r = self.0.lock().await;
|
|
1005
|
+
r.stop(code).map_err(|e| anyhow::anyhow!("{e:?}"))?;
|
|
1006
|
+
Ok(())
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
#[napi]
|
|
1010
|
+
pub async fn received_reset(&self) -> Result<Option<i64>> {
|
|
1011
|
+
let mut r = self.0.lock().await;
|
|
1012
|
+
let code = r
|
|
1013
|
+
.received_reset()
|
|
1014
|
+
.await
|
|
1015
|
+
.map_err(|e| anyhow::anyhow!("{e:?}"))?;
|
|
1016
|
+
Ok(code.map(|c| c.into_inner() as i64))
|
|
1017
|
+
}
|
|
1018
|
+
}
|