feat: dial hint on Address for hosts that resolve DNS themselves
This commit is contained in:
parent
45987fe03d
commit
5559fcce31
2 changed files with 44 additions and 1 deletions
|
|
@ -35,6 +35,13 @@ pub struct Address {
|
|||
pub port: u16,
|
||||
pub scheme: Scheme,
|
||||
pub identity: Option<[u8; KEY_LEN]>,
|
||||
/// Where to dial instead of resolving `host` again: an embedder that
|
||||
/// resolves DNS itself (an Android app, whose native getaddrinfo can be
|
||||
/// dead while the platform resolver works) sets the address's IP here.
|
||||
/// The hostname keeps every identity role — pins, PoP, display — so
|
||||
/// `dial` is purely a routing hint, and `None` (the default) means
|
||||
/// fumi resolves `host` itself.
|
||||
pub dial: Option<String>,
|
||||
}
|
||||
|
||||
impl Address {
|
||||
|
|
@ -53,6 +60,15 @@ impl Address {
|
|||
format!("{}{}/{}", self.scheme.prefix(), self.short(), b32(identity))
|
||||
}
|
||||
|
||||
/// Routing hint: dial this address instead of resolving `host`. The
|
||||
/// hostname is untouched — pins, proof-of-possession and display all
|
||||
/// keep using it, so a dial override changes where the packets go and
|
||||
/// nothing about who the server is.
|
||||
pub fn with_dial(mut self, dial: &str) -> Address {
|
||||
self.dial = Some(dial.to_string());
|
||||
self
|
||||
}
|
||||
|
||||
/// The Reticulum destination hash, for the `rns` carrier only.
|
||||
pub fn destination(&self) -> Result<[u8; 16], Error> {
|
||||
if self.scheme != Scheme::Rns {
|
||||
|
|
@ -109,6 +125,7 @@ impl Address {
|
|||
port,
|
||||
scheme,
|
||||
identity,
|
||||
dial: None,
|
||||
}
|
||||
}
|
||||
Scheme::Rns => {
|
||||
|
|
@ -131,6 +148,7 @@ impl Address {
|
|||
port: 0,
|
||||
scheme,
|
||||
identity,
|
||||
dial: None,
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -197,6 +215,23 @@ fn valid_username(name: &str) -> Result<(), Error> {
|
|||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn dial_hint_routes_without_renaming() {
|
||||
let addr = Address::parse("alice@example.org:1961")
|
||||
.unwrap()
|
||||
.with_dial("192.0.2.10");
|
||||
// The hint changes where packets go, never who the server is: pins,
|
||||
// proof-of-possession and display all read `host`.
|
||||
assert_eq!(addr.dial.as_deref(), Some("192.0.2.10"));
|
||||
assert_eq!(addr.host, "example.org");
|
||||
assert_eq!(addr.short(), "alice@example.org:1961");
|
||||
assert_eq!(Address::parse("alice@example.org").unwrap().dial, None);
|
||||
}
|
||||
}
|
||||
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::crypto::b32;
|
||||
|
|
|
|||
|
|
@ -71,7 +71,15 @@ pub fn connect(
|
|||
host: addr.host.clone(),
|
||||
});
|
||||
}
|
||||
let transport = TcpTransport::connect(&addr.host, addr.port, pinned, timeout)?;
|
||||
// The dial hint lets a host that resolves DNS itself (an
|
||||
// Android app) reach the server by IP while `host` keeps its
|
||||
// identity roles.
|
||||
let transport = TcpTransport::connect(
|
||||
addr.dial.as_deref().unwrap_or(&addr.host),
|
||||
addr.port,
|
||||
pinned,
|
||||
timeout,
|
||||
)?;
|
||||
let unpinned_static = if pinned.is_none() {
|
||||
Some(*transport.server_static())
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue