Skip to main content

dig_ip/
lib.rs

1//! # dig-ip — canonical address-family discovery + IPv6-first happy-eyeballs dial
2//!
3//! The ONE ecosystem implementation of CLAUDE.md §5.2 (IPv6-first, IPv4-fallback for peer comms).
4//! Before this crate, three drifting copies of the happy-eyeballs racer lived in `dig-nat`,
5//! `dig-gossip`, and `dig-node-core`, and NONE of them filtered by LOCAL capability — so an
6//! IPv4-only host still emitted IPv6 SYNs, and an IPv6-only peer from an IPv4-only host was
7//! attempted-then-timed-out rather than reported cleanly unreachable. `dig-ip` consolidates them and
8//! adds the missing half: the local∩peer family INTERSECTION.
9//!
10//! ## The pipeline
11//!
12//! 1. [`LocalStack`] — which families THIS host can reach (`detect` / `cached` / `from_flags`).
13//! 2. [`PeerCandidates`] — a peer's family-tagged candidate addresses, aggregated from every
14//!    discovery source ([`CandidateSource`]) and de-duplicated.
15//! 3. [`dial_order`] — the local∩peer family intersection, IPv6-first; a typed [`NoCommonFamily`]
16//!    when disjoint. Its output NEVER contains a family the local host or the peer lacks.
17//! 4. [`connect`] — the RFC-8305 happy-eyeballs racer over that order, IPv6-preferred with graceful
18//!    IPv4 fallback; the transport dial is a caller-supplied closure so this crate stays a leaf with
19//!    no TLS/socket dependency.
20//!
21//! ## The core guarantee
22//!
23//! An address of a family the LOCAL host lacks, or a family the PEER lacks, is NEVER dialed — this is
24//! enforced structurally by [`dial_order`] (which [`connect`] builds its attempt list from), not by
25//! convention. That is the anti-mis-dial rule the user asked for: "an IPv6 client doesn't try to
26//! connect to an IPv4-only client" (and vice-versa).
27
28#![forbid(unsafe_code)]
29#![warn(missing_docs)]
30
31mod candidate;
32mod connect;
33mod dial;
34mod family;
35mod local;
36
37pub use candidate::{Candidate, CandidateSource, PeerCandidates};
38pub use connect::{connect, ConnectError, DialConfig, DialWinner, FromTimeout};
39pub use dial::{dial_order, NoCommonFamily};
40pub use family::Family;
41pub use local::LocalStack;