Skip to content

Commit

Permalink
refactor(iroh-net): generalize derp naming to relay to prepare fo…
Browse files Browse the repository at this point in the history
…r future refactors (#2091)

## Description

We have been making breaking changes to the DERP protocol and are
planning future changes that will better take advantage of / integrate
with QUIC in our hole-punching schemes.

## Change checklist

- [x] Self-review.
- [x] Documentation updates if relevant.
- [x] Tests if relevant.

---------

Co-authored-by: Asmir Avdicevic <asmir.avdicevic64@gmail.com>
  • Loading branch information
ramfox and Arqu authored Mar 21, 2024
1 parent b98ed9d commit 07c29f0
Show file tree
Hide file tree
Showing 79 changed files with 1,825 additions and 1,790 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
---
- name: Update derper node
- name: Update iroh-relay node
hosts: derper
become: yes

tasks:
- name: Fetch derper binary
- name: Fetch iroh-relay binary
get_url:
url: https://vorc.s3.us-east-2.amazonaws.com/derper-linux-amd64-{{ derper_version }}
mode: '0755'
Expand All @@ -13,8 +13,8 @@
- name: Allow ports
shell:
cmd: sudo setcap CAP_NET_BIND_SERVICE=+eip /usr/local/bin/derper
- name: Make sure derper is started
- name: Make sure iroh-relay is started
ansible.builtin.systemd:
state: restarted
enabled: yes
name: derper
name: derper
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ jobs:
- name: Copy binaries to right location
run: |
cp target/release/iroh ../chuck/netsim/bins/iroh
cp target/release/derper ../chuck/netsim/bins/derper
cp target/release/iroh-relay ../chuck/netsim/bins/derper
cp ../chuck/target/release/chuck ../chuck/netsim/bins/chuck
- name: Run tests
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/netsim.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ jobs:
- name: Copy binaries to right location
run: |
cp target/optimized-release/iroh ../chuck/netsim/bins/iroh
cp target/optimized-release/derper ../chuck/netsim/bins/derper
cp target/optimized-release/iroh-relay ../chuck/netsim/bins/derper
cp ../chuck/target/release/chuck ../chuck/netsim/bins/chuck
- name: Detect comment commands
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,10 @@ jobs:
if: matrix.os != 'windows-latest'
run: |
aws s3 cp ./target/optimized-release/iroh s3://vorc/iroh-${RELEASE_OS}-${RELEASE_ARCH}-${GITHUB_SHA::7} --no-progress
aws s3 cp ./target/optimized-release/derper s3://vorc/derper-${RELEASE_OS}-${RELEASE_ARCH}-${GITHUB_SHA::7} --no-progress
aws s3 cp ./target/optimized-release/iroh-relay s3://vorc/derper-${RELEASE_OS}-${RELEASE_ARCH}-${GITHUB_SHA::7} --no-progress
- name: push release latest
if: matrix.os != 'windows-latest'
run: |
aws s3 cp ./target/optimized-release/iroh s3://vorc/iroh-${RELEASE_OS}-${RELEASE_ARCH}-latest --no-progress
aws s3 cp ./target/optimized-release/derper s3://vorc/derper-${RELEASE_OS}-${RELEASE_ARCH}-latest --no-progress
aws s3 cp ./target/optimized-release/iroh-relay s3://vorc/derper-${RELEASE_OS}-${RELEASE_ARCH}-latest --no-progress
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
name: Deploy Test Derper
name: Deploy Test Relay Server

on:
workflow_dispatch:
schedule:
- cron: '0 4 * * *'

concurrency:
group: derper-${{ github.workflow }}-${{ github.ref }}
group: relay-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
Expand All @@ -17,7 +17,7 @@ env:
SCCACHE_CACHE_SIZE: "50G"

jobs:
build_derper:
build_relay_server:
runs-on: [self-hosted, linux, X64]
if: github.ref_name=='main'
env:
Expand All @@ -35,7 +35,7 @@ jobs:

- name: build release
run: |
cargo build --release --all-features --bin derper
cargo build --release --all-features --bin iroh-relay
- name: Setup awscli on linux
run: |
Expand All @@ -50,24 +50,24 @@ jobs:
- name: push release
run: |
aws s3 cp ./target/release/derper s3://vorc/derper-linux-amd64-${GITHUB_SHA::7} --no-progress
aws s3 cp ./target/release/iroh-relay s3://vorc/derper-linux-amd64-${GITHUB_SHA::7} --no-progress
- name: Set derper tag
- name: Set iroh-relay tag
id: set_tag
run: |
echo ::set-output name=tag::${GITHUB_SHA::7}

deploy_derper:
deploy_iroh-relay:
runs-on: ubuntu-latest
if: github.ref_name=='main'
needs: build_derper
needs: build_relay_server
steps:
- uses: actions/checkout@v4
- name: Run Staging Deploy Playbook
uses: arqu/action-ansible-playbook@master
with:
playbook: redeploy-derper.yml
playbook: redeploy-relay.yml
directory: .github/ansible
key: ${{ secrets.TEST_DERPER_SSH_PKEY }}
inventory: ${{ secrets.TEST_DERPER_INVENTORY }}
Expand Down
72 changes: 36 additions & 36 deletions iroh-base/src/node_addr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ impl NodeAddr {
}
}

/// Add a derp url to the peer's [`AddrInfo`].
pub fn with_derp_url(mut self, derp_url: DerpUrl) -> Self {
self.info.derp_url = Some(derp_url);
/// Add a relay url to the peer's [`AddrInfo`].
pub fn with_relay_url(mut self, relay_url: RelayUrl) -> Self {
self.info.relay_url = Some(relay_url);
self
}

Expand All @@ -44,19 +44,19 @@ impl NodeAddr {
self.info.direct_addresses.iter()
}

/// Get the derp url of this peer.
pub fn derp_url(&self) -> Option<&DerpUrl> {
self.info.derp_url.as_ref()
/// Get the relay url of this peer.
pub fn relay_url(&self) -> Option<&RelayUrl> {
self.info.relay_url.as_ref()
}
}

impl From<(PublicKey, Option<DerpUrl>, &[SocketAddr])> for NodeAddr {
fn from(value: (PublicKey, Option<DerpUrl>, &[SocketAddr])) -> Self {
let (node_id, derp_url, direct_addresses_iter) = value;
impl From<(PublicKey, Option<RelayUrl>, &[SocketAddr])> for NodeAddr {
fn from(value: (PublicKey, Option<RelayUrl>, &[SocketAddr])) -> Self {
let (node_id, relay_url, direct_addresses_iter) = value;
NodeAddr {
node_id,
info: AddrInfo {
derp_url,
relay_url,
direct_addresses: direct_addresses_iter.iter().copied().collect(),
},
}
Expand All @@ -66,60 +66,60 @@ impl From<(PublicKey, Option<DerpUrl>, &[SocketAddr])> for NodeAddr {
/// Addressing information to connect to a peer.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
pub struct AddrInfo {
/// The peer's home DERP url.
pub derp_url: Option<DerpUrl>,
/// The peer's home relay url.
pub relay_url: Option<RelayUrl>,
/// Socket addresses where the peer might be reached directly.
pub direct_addresses: BTreeSet<SocketAddr>,
}

impl AddrInfo {
/// Return whether this addressing information is empty.
pub fn is_empty(&self) -> bool {
self.derp_url.is_none() && self.direct_addresses.is_empty()
self.relay_url.is_none() && self.direct_addresses.is_empty()
}
}

impl NodeAddr {
/// Create a new [`NodeAddr`] from its parts.
pub fn from_parts(
node_id: PublicKey,
derp_url: Option<DerpUrl>,
relay_url: Option<RelayUrl>,
direct_addresses: Vec<SocketAddr>,
) -> Self {
Self {
node_id,
info: AddrInfo {
derp_url,
relay_url,
direct_addresses: direct_addresses.into_iter().collect(),
},
}
}
}

/// A URL identifying a DERP server.
/// A URL identifying a relay server.
///
/// This is but a wrapper around [`Url`], with a few custom tweaks:
///
/// - A DERP URL is never a relative URL, so an implicit `.` is added at the end of the
/// - A relay URL is never a relative URL, so an implicit `.` is added at the end of the
/// domain name if missing.
///
/// - [`fmt::Debug`] is implemented so it prints the URL rather than the URL struct fields.
/// Useful when logging e.g. `Option<DerpUrl>`.
/// Useful when logging e.g. `Option<RelayUrl>`.
///
/// To create a [`DerpUrl`] use the `From<Url>` implementation.
/// To create a [`RelayUrl`] use the `From<Url>` implementation.
#[derive(
Clone, derive_more::Display, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
)]
pub struct DerpUrl(Url);
pub struct RelayUrl(Url);

impl From<Url> for DerpUrl {
impl From<Url> for RelayUrl {
fn from(mut url: Url) -> Self {
if let Some(domain) = url.domain() {
if !domain.ends_with('.') {
let domain = String::from(domain) + ".";

// This can fail, though it is unlikely the resulting URL is usable as a
// DERP URL, probably it has the wrong scheme or is not a base URL or the
// relay URL, probably it has the wrong scheme or is not a base URL or the
// like. We don't do full URL validation however, so just silently leave
// this bad URL in place. Something will fail later.
url.set_host(Some(&domain)).ok();
Expand All @@ -131,14 +131,14 @@ impl From<Url> for DerpUrl {

/// This is a convenience only to directly parse strings.
///
/// If you need more control over the error first create a [`Url`] and use [`DerpUrl::from`]
/// If you need more control over the error first create a [`Url`] and use [`RelayUrl::from`]
/// instead.
impl FromStr for DerpUrl {
impl FromStr for RelayUrl {
type Err = anyhow::Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let inner = Url::from_str(s).context("invalid URL")?;
Ok(DerpUrl::from(inner))
Ok(RelayUrl::from(inner))
}
}

Expand All @@ -148,17 +148,17 @@ impl FromStr for DerpUrl {
/// to change the inner later.
///
/// [`DerefMut`]: std::ops::DerefMut
impl Deref for DerpUrl {
impl Deref for RelayUrl {
type Target = Url;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl fmt::Debug for DerpUrl {
impl fmt::Debug for RelayUrl {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("DerpUrl")
f.debug_tuple("RelayUrl")
.field(&DbgStr(self.0.as_str()))
.finish()
}
Expand All @@ -182,27 +182,27 @@ mod tests {
use super::*;

#[test]
fn test_derp_url_debug_display() {
let url = DerpUrl::from(Url::parse("https://example.com").unwrap());
fn test_relay_url_debug_display() {
let url = RelayUrl::from(Url::parse("https://example.com").unwrap());

assert_eq!(format!("{url:?}"), r#"DerpUrl("https://example.com./")"#);
assert_eq!(format!("{url:?}"), r#"RelayUrl("https://example.com./")"#);

assert_eq!(format!("{url}"), "https://example.com./");
}

#[test]
fn test_derp_url_absolute() {
let url = DerpUrl::from(Url::parse("https://example.com").unwrap());
fn test_relay_url_absolute() {
let url = RelayUrl::from(Url::parse("https://example.com").unwrap());

assert_eq!(url.domain(), Some("example.com."));

let url1 = DerpUrl::from(Url::parse("https://example.com.").unwrap());
let url1 = RelayUrl::from(Url::parse("https://example.com.").unwrap());
assert_eq!(url, url1);

let url2 = DerpUrl::from(Url::parse("https://example.com./").unwrap());
let url2 = RelayUrl::from(Url::parse("https://example.com./").unwrap());
assert_eq!(url, url2);

let url3 = DerpUrl::from(Url::parse("https://example.com/").unwrap());
let url3 = RelayUrl::from(Url::parse("https://example.com/").unwrap());
assert_eq!(url, url3);
}
}
6 changes: 3 additions & 3 deletions iroh-base/src/ticket/blob.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,10 @@ mod tests {
let hash = Hash::new(b"hi there");
let peer = SecretKey::generate().public();
let addr = SocketAddr::from_str("127.0.0.1:1234").unwrap();
let derp_url = None;
let relay_url = None;
BlobTicket {
hash,
node: NodeAddr::from_parts(peer, derp_url, vec![addr]),
node: NodeAddr::from_parts(peer, relay_url, vec![addr]),
format: BlobFormat::HashSeq,
}
}
Expand Down Expand Up @@ -174,7 +174,7 @@ mod tests {
let expected = parse_hexdump("
00 # discriminator for variant 0
ae58ff8833241ac82d6ff7611046ed67b5072d142c588d0063e942d9a75502b6 # node id, 32 bytes, see above
00 # derp url
00 # relay url
00 # number of addresses (0)
00 # format (raw)
0b84d358e4c8be6c38626b2182ff575818ba6bd3f4b90464994be14cb354a072 # hash, 32 bytes, see above
Expand Down
8 changes: 4 additions & 4 deletions iroh-base/src/ticket/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,9 @@ mod tests {
fn make_ticket() -> NodeTicket {
let peer = SecretKey::generate().public();
let addr = SocketAddr::from((Ipv4Addr::LOCALHOST, 1234));
let derp_url = None;
let relay_url = None;
NodeTicket {
node: NodeAddr::from_parts(peer, derp_url, vec![addr]),
node: NodeAddr::from_parts(peer, relay_url, vec![addr]),
}
}

Expand Down Expand Up @@ -140,8 +140,8 @@ mod tests {
let expected = parse_hexdump("
00 # variant
ae58ff8833241ac82d6ff7611046ed67b5072d142c588d0063e942d9a75502b6 # node id, 32 bytes, see above
01 # derp url present
10 687474703a2f2f646572702e6d652e2f # derp url, 16 bytes, see above
01 # relay url present
10 687474703a2f2f646572702e6d652e2f # relay url, 16 bytes, see above
01 # one direct address
00 # ipv4
7f000001 8008 # address, see above
Expand Down
1 change: 1 addition & 0 deletions iroh-bytes/src/store/bao_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ fn create_read_write(path: impl AsRef<Path>) -> io::Result<File> {
.read(true)
.write(true)
.create(true)
.truncate(false)
.open(path)
}

Expand Down
6 changes: 5 additions & 1 deletion iroh-bytes/src/store/file/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@ pub fn overwrite_and_sync(path: &Path, data: &[u8]) -> io::Result<std::fs::File>
// std::fs::create_dir_all(path.parent().unwrap()).unwrap();
// tracing::error!("{}", path.parent().unwrap().display());
// tracing::error!("{}", path.parent().unwrap().metadata().unwrap().is_dir());
let mut file = OpenOptions::new().write(true).create(true).open(path)?;
let mut file = OpenOptions::new()
.write(true)
.create(true)
.truncate(false)
.open(path)?;
file.write_all(data)?;
// todo: figure out if it is safe to not sync here
file.sync_all()?;
Expand Down
2 changes: 1 addition & 1 deletion iroh-cli/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ pub(crate) enum Commands {
#[clap(flatten)]
Rpc(#[clap(subcommand)] RpcCommands),

/// Diagnostic commands for the derp relay protocol.
/// Diagnostic commands for the relay protocol.
Doctor {
/// Commands for doctor - defined in the mod
#[clap(subcommand)]
Expand Down
Loading

0 comments on commit 07c29f0

Please sign in to comment.