Skip to content

Commit a5e9283

Browse files
feat(iroh-base, iroh-net-report)!: intro net-report as a crate (#2921)
## Description Introduces net-report as its own crate. For this, introduces a new feature flag `relay` in `iroh-base` for the relay topology types. - in `iroh-base`, the `RelayUrl` is moved to its own file. It can still be used as before, this is not a breaking change. - `RelayMap`, `RelayNode` are moved to `iroh-base` under the `relay` feature flag. - `RelayMode` is moved to `endpoint`. See the NOTES section about this. - net-report now has metrics as a feature flag. I'm not sure how is that this was not feature flagged before but still worked. - ping is moved without changes from `iroh-net` to `iroh-net-report`. This is the only place where it's used so it should have probably been part of `netcheck` as a module from the beginig. - Adds missing license files ## Breaking Changes - `iroh-net`'s `NetcheckMetrics` are now called `NetReportMetrics` ## Notes & open questions - `RelayMode` remains in `iroh-net` instead of moving to `iroh-base` with other relay related because this is coupled with the staging and prod configuration of relay urls. Since this is more configuration than concept I think it's best to keep it in iroh-net. - The crate is called `iroh-net-report` because -at least currently- it depends on relay concepts. For example, the tests depend heavily on the internal order of the `RelayMap`. Can we change this? yes. Should we change this? we can discuss it. Is this PR the place for any of that? No. - The api needs some love. Some types that are supposed to be internal are used by dependents (in this case `iroh-net`) It's not terrible but it could be improved. ## Change checklist - [x] Self-review. - [x] Documentation updates following the [style guide](https://rust-lang.github.io/rfcs/1574-more-api-documentation-conventions.html#appendix-a-full-conventions-text), if relevant. - [ ] ~Tests if relevant.~ - [ ] ~All breaking changes documented.~
1 parent 4e58b1f commit a5e9283

34 files changed

+918
-384
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ jobs:
190190
# uses: obi1kenobi/cargo-semver-checks-action@v2
191191
uses: n0-computer/cargo-semver-checks-action@feat-baseline
192192
with:
193-
package: iroh, iroh-base, iroh-cli, iroh-dns-server, iroh-metrics, iroh-net, iroh-net-bench, iroh-node-util, iroh-router, netwatch, portmapper, iroh-relay
193+
package: iroh, iroh-base, iroh-cli, iroh-dns-server, iroh-metrics, iroh-net, iroh-net-bench, iroh-node-util, iroh-router, netwatch, portmapper, iroh-relay, iroh-net-report
194194
baseline-rev: ${{ env.HEAD_COMMIT_SHA }}
195195
use-cache: false
196196

.github/workflows/tests.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ env:
2323
RUSTFLAGS: -Dwarnings
2424
RUSTDOCFLAGS: -Dwarnings
2525
SCCACHE_CACHE_SIZE: "50G"
26-
CRATES_LIST: "iroh,iroh-node-util,iroh-metrics,iroh-net,iroh-net-bench,iroh-test,iroh-cli,iroh-dns-server,iroh-router,netwatch,portmapper,iroh-relay"
26+
CRATES_LIST: "iroh,iroh-node-util,iroh-metrics,iroh-net,iroh-net-bench,iroh-test,iroh-cli,iroh-dns-server,iroh-router,netwatch,portmapper,iroh-relay,iroh-net-report"
2727
IROH_FORCE_STAGING_RELAYS: "1"
2828

2929
jobs:

Cargo.lock

Lines changed: 32 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ members = [
1212
"iroh-router",
1313
"net-tools/netwatch",
1414
"net-tools/portmapper",
15+
"iroh-net-report",
1516
"iroh-node-util",
1617
]
1718
resolver = "2"

iroh-base/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,13 @@ serde_json = "1.0.107"
4747
serde_test = "1.0.176"
4848

4949
[features]
50-
default = ["hash", "base32"]
50+
default = ["hash", "base32", "relay"]
5151
hash = ["dep:blake3", "dep:data-encoding", "dep:postcard", "dep:derive_more", "base32"]
5252
base32 = ["dep:data-encoding", "dep:postcard"]
5353
redb = ["dep:redb"]
5454
key = ["dep:ed25519-dalek", "dep:once_cell", "dep:rand", "dep:rand_core", "dep:ssh-key", "dep:ttl_cache", "dep:aead", "dep:crypto_box", "dep:zeroize", "dep:url", "dep:derive_more", "dep:getrandom"]
5555
wasm = ["getrandom?/js"]
56+
relay = ["dep:url", "dep:derive_more"]
5657

5758
[package.metadata.docs.rs]
5859
all-features = true

iroh-base/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ pub mod key;
1313
#[cfg(feature = "key")]
1414
#[cfg_attr(iroh_docsrs, doc(cfg(feature = "key")))]
1515
pub mod node_addr;
16+
#[cfg(feature = "relay")]
17+
#[cfg_attr(iroh_docsrs, doc(cfg(feature = "relay")))]
18+
pub mod relay_map;
19+
#[cfg(any(feature = "relay", feature = "key"))]
20+
mod relay_url;
1621
#[cfg(feature = "base32")]
1722
#[cfg_attr(iroh_docsrs, doc(cfg(feature = "base32")))]
1823
pub mod ticket;

iroh-base/src/node_addr.rs

Lines changed: 2 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,12 @@
66
//!
77
//! The primary way of addressing a node is by using the [`NodeAddr`].
88
9-
use std::{collections::BTreeSet, fmt, net::SocketAddr, ops::Deref, str::FromStr};
9+
use std::{collections::BTreeSet, net::SocketAddr};
1010

11-
use anyhow::Context;
1211
use serde::{Deserialize, Serialize};
13-
use url::Url;
1412

1513
use crate::key::{NodeId, PublicKey};
14+
pub use crate::relay_url::RelayUrl;
1615

1716
/// Network-level addressing information for an iroh-net node.
1817
///
@@ -199,120 +198,3 @@ pub enum AddrInfoOptions {
199198
/// Includes the Node ID and the direct addresses.
200199
Addresses,
201200
}
202-
203-
/// A URL identifying a relay server.
204-
///
205-
/// This is but a wrapper around [`Url`], with a few custom tweaks:
206-
///
207-
/// - A relay URL is never a relative URL, so an implicit `.` is added at the end of the
208-
/// domain name if missing.
209-
///
210-
/// - [`fmt::Debug`] is implemented so it prints the URL rather than the URL struct fields.
211-
/// Useful when logging e.g. `Option<RelayUrl>`.
212-
///
213-
/// To create a [`RelayUrl`] use the `From<Url>` implementation.
214-
#[derive(
215-
Clone, derive_more::Display, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
216-
)]
217-
pub struct RelayUrl(Url);
218-
219-
impl From<Url> for RelayUrl {
220-
fn from(mut url: Url) -> Self {
221-
if let Some(domain) = url.domain() {
222-
if !domain.ends_with('.') {
223-
let domain = String::from(domain) + ".";
224-
225-
// This can fail, though it is unlikely the resulting URL is usable as a
226-
// relay URL, probably it has the wrong scheme or is not a base URL or the
227-
// like. We don't do full URL validation however, so just silently leave
228-
// this bad URL in place. Something will fail later.
229-
url.set_host(Some(&domain)).ok();
230-
}
231-
}
232-
Self(url)
233-
}
234-
}
235-
236-
/// Support for parsing strings directly.
237-
///
238-
/// If you need more control over the error first create a [`Url`] and use [`RelayUrl::from`]
239-
/// instead.
240-
impl FromStr for RelayUrl {
241-
type Err = anyhow::Error;
242-
243-
fn from_str(s: &str) -> Result<Self, Self::Err> {
244-
let inner = Url::from_str(s).context("invalid URL")?;
245-
Ok(RelayUrl::from(inner))
246-
}
247-
}
248-
249-
impl From<RelayUrl> for Url {
250-
fn from(value: RelayUrl) -> Self {
251-
value.0
252-
}
253-
}
254-
255-
/// Dereferences to the wrapped [`Url`].
256-
///
257-
/// Note that [`DerefMut`] is not implemented on purpose, so this type has more flexibility
258-
/// to change the inner later.
259-
///
260-
/// [`DerefMut`]: std::ops::DerefMut
261-
impl Deref for RelayUrl {
262-
type Target = Url;
263-
264-
fn deref(&self) -> &Self::Target {
265-
&self.0
266-
}
267-
}
268-
269-
impl fmt::Debug for RelayUrl {
270-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
271-
f.debug_tuple("RelayUrl")
272-
.field(&DbgStr(self.0.as_str()))
273-
.finish()
274-
}
275-
}
276-
277-
/// Helper struct to format a &str without allocating a String.
278-
///
279-
/// Maybe this is entirely unneeded and the compiler would be smart enough to never allocate
280-
/// the String anyway. Who knows. Writing this was faster than checking the assembler
281-
/// output.
282-
struct DbgStr<'a>(&'a str);
283-
284-
impl<'a> fmt::Debug for DbgStr<'a> {
285-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
286-
write!(f, r#""{}""#, self.0)
287-
}
288-
}
289-
290-
#[cfg(test)]
291-
mod tests {
292-
use super::*;
293-
294-
#[test]
295-
fn test_relay_url_debug_display() {
296-
let url = RelayUrl::from(Url::parse("https://example.com").unwrap());
297-
298-
assert_eq!(format!("{url:?}"), r#"RelayUrl("https://example.com./")"#);
299-
300-
assert_eq!(format!("{url}"), "https://example.com./");
301-
}
302-
303-
#[test]
304-
fn test_relay_url_absolute() {
305-
let url = RelayUrl::from(Url::parse("https://example.com").unwrap());
306-
307-
assert_eq!(url.domain(), Some("example.com."));
308-
309-
let url1 = RelayUrl::from(Url::parse("https://example.com.").unwrap());
310-
assert_eq!(url, url1);
311-
312-
let url2 = RelayUrl::from(Url::parse("https://example.com./").unwrap());
313-
assert_eq!(url, url2);
314-
315-
let url3 = RelayUrl::from(Url::parse("https://example.com/").unwrap());
316-
assert_eq!(url, url3);
317-
}
318-
}

iroh-net/src/relay_map.rs renamed to iroh-base/src/relay_map.rs

Lines changed: 4 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,39 +3,14 @@
33
use std::{collections::BTreeMap, fmt, sync::Arc};
44

55
use anyhow::{ensure, Result};
6-
pub use iroh_relay::RelayUrl;
76
use serde::{Deserialize, Serialize};
87

9-
use crate::defaults::DEFAULT_STUN_PORT;
8+
pub use crate::relay_url::RelayUrl;
109

11-
/// Configuration of the relay servers for an [`Endpoint`].
10+
/// The default STUN port used by the Relay server.
1211
///
13-
/// [`Endpoint`]: crate::endpoint::Endpoint
14-
#[derive(Debug, Clone, PartialEq, Eq)]
15-
pub enum RelayMode {
16-
/// Disable relay servers completely.
17-
Disabled,
18-
/// Use the default relay map, with production relay servers from n0.
19-
///
20-
/// See [`crate::defaults::prod`] for the severs used.
21-
Default,
22-
/// Use the staging relay servers from n0.
23-
Staging,
24-
/// Use a custom relay map.
25-
Custom(RelayMap),
26-
}
27-
28-
impl RelayMode {
29-
/// Returns the relay map for this mode.
30-
pub fn relay_map(&self) -> RelayMap {
31-
match self {
32-
RelayMode::Disabled => RelayMap::empty(),
33-
RelayMode::Default => crate::defaults::prod::default_relay_map(),
34-
RelayMode::Staging => crate::defaults::staging::default_relay_map(),
35-
RelayMode::Custom(relay_map) => relay_map.clone(),
36-
}
37-
}
38-
}
12+
/// The STUN port as defined by [RFC 8489](<https://www.rfc-editor.org/rfc/rfc8489#section-18.6>)
13+
const DEFAULT_STUN_PORT: u16 = 3478;
3914

4015
/// Configuration of all the relay servers that can be used.
4116
#[derive(Debug, Clone, PartialEq, Eq)]

0 commit comments

Comments
 (0)