Skip to main content

ddns/core/parser/record/
endpoint.rs

1use std::{
2    convert::TryFrom,
3    fmt::Display,
4    hash::{Hash, Hasher},
5    net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6},
6    path::Path,
7};
8
9use base64::Engine;
10use bytes::BufMut;
11use dhttp_identity::certificate::{CertificateChainKey, CertificateChainKind, CertificateSequence};
12use dquic::qbase::net::addr::EndpointAddr as DquicEndpointAddr;
13use nom::{
14    IResult, Parser,
15    bytes::streaming::take,
16    combinator::{flat_map, map},
17    error::{ErrorKind, make_error},
18    number::streaming::{be_u8, be_u16, be_u32, be_u128},
19};
20use rustls::{SignatureScheme, pki_types::SubjectPublicKeyInfoDer};
21use snafu::{ResultExt, Snafu};
22
23use crate::core::parser::{
24    sigin,
25    varint::{VarInt, WriteVarInt, be_varint},
26};
27
28#[derive(Debug, Snafu)]
29#[snafu(module)]
30pub enum SignEndpointError {
31    #[snafu(display("failed to sign endpoint address"))]
32    Sign {
33        source: dhttp_identity::identity::SignError,
34    },
35    #[snafu(display("no supported signature scheme for endpoint address"))]
36    NoSupportedScheme,
37}
38
39/// EndpointAddress record (Type E = 266)
40///
41/// Unified endpoint format that encodes address family, routing, clustering and NAT information
42/// in a single flags byte, followed by optional fields.
43///
44/// ## Wire format
45///
46/// ```text
47/// +-------+-----------------+--------------------+----------------+----------------------------+
48/// | flags | sequence(varint)| addr               | load(optional) | signature (optional)       |
49/// +-------+-----------------+--------------------+----------------+----------------------------+
50/// | u8    | QUIC varint     | see addr layout    | f32            | scheme(u16)+len(varint)+N  |
51/// +-------+-----------------+--------------------+----------------+----------------------------+
52///
53/// addr layout:
54/// +---------+-----------------------------------------+
55/// | kind    | addr fields                             |
56/// +---------+-----------------------------------------+
57/// | direct  | port(u16) + IP(u32/u128)                |
58/// +---------+-----------------------------------------+
59/// | nat     | outer_port(u16) + outer_IP(u32/u128)    |
60/// |         | + agent_port(u16) + agent_IP(u32/u128)  |
61/// +---------+-----------------------------------------+
62/// ```
63///
64/// ## flags (u8) bit layout (bit 1 = MSB)
65///
66/// - bit 1 (0x80): FAMILY    — address family: 0=IPv4, 1=IPv6
67/// - bit 2 (0x40): MAIN      — primary/backup: 1=primary, 0=backup
68/// - bit 3 (0x20): CLUSTERED — multiple hosts share this name; record includes a device sequence number
69/// - bit 4 (0x10): NAT       — endpoint is behind NAT; record includes the agent endpoint address
70/// - bit 5 (0x08): LOAD      — record carries 1-minute load average (f32)
71/// - bit 6 (0x04): reserved
72/// - bit 7 (0x02): reserved
73/// - bit 8 (0x01): SIGNED    — record carries a publisher key signature to prevent DNS poisoning
74///
75/// ## Field order
76///
77/// `flags` → `sequence` (if CLUSTERED) → `addr` → `agent addr` (if NAT) → `load` (if LOAD) → `signature` (if SIGNED)
78///
79#[derive(Debug, Clone, PartialEq, Eq, Hash)]
80pub struct EndpointSignature {
81    scheme: u16,
82    signature: Vec<u8>,
83}
84
85#[derive(Debug, Clone)]
86pub struct EndpointAddr {
87    flags: u8,
88    /// Certificate-chain sequence used when multiple hosts share a domain (CLUSTERED).
89    /// None means no sequence number.
90    sequence: Option<CertificateSequence>,
91    /// 1-minute load average (present when LOAD flag is set)
92    load: Option<f32>,
93    signature: Option<EndpointSignature>,
94    /// Primary address (the direct address, or the outer/public address for NAT)
95    pub primary: SocketAddr,
96    /// Agent address used for NAT traversal (present when NAT flag is set)
97    pub agent: Option<SocketAddr>,
98}
99
100impl PartialEq for EndpointAddr {
101    fn eq(&self, other: &Self) -> bool {
102        self.flags == other.flags
103            && self.sequence == other.sequence
104            && self.load.map(f32::to_bits) == other.load.map(f32::to_bits)
105            && self.signature == other.signature
106            && self.primary == other.primary
107            && self.agent == other.agent
108    }
109}
110
111impl Eq for EndpointAddr {}
112
113impl Hash for EndpointAddr {
114    fn hash<H: Hasher>(&self, state: &mut H) {
115        self.flags.hash(state);
116        self.sequence.hash(state);
117        self.load.map(f32::to_bits).hash(state);
118        self.signature.hash(state);
119        self.primary.hash(state);
120        self.agent.hash(state);
121    }
122}
123
124impl EndpointAddr {
125    const FLAG_FAMILY: u8 = 0b1000_0000; // bit 1: 0=IPv4, 1=IPv6
126    const FLAG_MAIN: u8 = 0b0100_0000; // bit 2: 1=primary, 0=backup
127    const FLAG_CLUSTERED: u8 = 0b0010_0000; // bit 3: multiple hosts share this domain
128    const FLAG_NAT: u8 = 0b0001_0000; // bit 4: endpoint is behind NAT, agent address present
129    const FLAG_LOAD: u8 = 0b0000_1000; // bit 5: record carries load average
130    // bit 6 (0x04): reserved
131    // bit 7 (0x02): reserved
132    const FLAG_SIGNED: u8 = 0b0000_0001; // bit 8: record carries publisher signature
133
134    pub fn direct_v4(addr: SocketAddrV4) -> Self {
135        Self {
136            flags: 0, // IPv4 direct: FAMILY=0, NAT=0
137            sequence: None,
138            load: None,
139            signature: None,
140            primary: addr.into(),
141            agent: None,
142        }
143    }
144
145    pub fn direct_v6(addr: SocketAddrV6) -> Self {
146        Self {
147            flags: Self::FLAG_FAMILY, // IPv6 direct: FAMILY=1, NAT=0
148            sequence: None,
149            load: None,
150            signature: None,
151            primary: addr.into(),
152            agent: None,
153        }
154    }
155
156    /// Create an IPv4 endpoint that requires NAT traversal.
157    /// `outer` is the public address; `agent` is the NAT helper address.
158    pub fn nat_v4(outer: SocketAddrV4, agent: SocketAddrV4) -> Self {
159        Self {
160            flags: Self::FLAG_NAT, // IPv4 NAT: FAMILY=0, NAT=1
161            sequence: None,
162            load: None,
163            signature: None,
164            primary: outer.into(),
165            agent: Some(agent.into()),
166        }
167    }
168
169    /// Create an IPv6 endpoint that requires NAT traversal.
170    /// `outer` is the public address; `agent` is the NAT helper address.
171    pub fn nat_v6(outer: SocketAddrV6, agent: SocketAddrV6) -> Self {
172        Self {
173            flags: Self::FLAG_FAMILY | Self::FLAG_NAT, // IPv6 NAT: FAMILY=1, NAT=1
174            sequence: None,
175            load: None,
176            signature: None,
177            primary: outer.into(),
178            agent: Some(agent.into()),
179        }
180    }
181
182    /// Returns true if the address family is IPv6.
183    pub fn is_ipv6(&self) -> bool {
184        self.flags & Self::FLAG_FAMILY != 0
185    }
186
187    /// Returns true if NAT traversal is required (agent address is present).
188    pub fn is_nat(&self) -> bool {
189        self.flags & Self::FLAG_NAT != 0
190    }
191
192    /// Returns true if this domain maps to a cluster of hosts (sequence number is present).
193    pub fn is_clustered(&self) -> bool {
194        self.flags & Self::FLAG_CLUSTERED != 0
195    }
196
197    /// Returns true if the record carries a load average value.
198    pub fn is_load(&self) -> bool {
199        self.flags & Self::FLAG_LOAD != 0
200    }
201
202    pub fn set_clustered(&mut self, clustered: bool) {
203        if clustered {
204            self.flags |= Self::FLAG_CLUSTERED;
205        } else {
206            self.flags &= !Self::FLAG_CLUSTERED;
207            self.sequence = None; // clear sequence number
208        }
209    }
210
211    pub fn set_load(&mut self, load: Option<f32>) {
212        self.load = load;
213        if self.load.is_some() {
214            self.flags |= Self::FLAG_LOAD;
215        } else {
216            self.flags &= !Self::FLAG_LOAD;
217        }
218    }
219
220    pub async fn sign_with_authority(
221        &mut self,
222        authority: &(impl dhttp_identity::identity::LocalAuthority + ?Sized),
223    ) -> Result<(), SignEndpointError> {
224        self.set_signed(true);
225        let data = self.signed_data();
226
227        let scheme = authority
228            .cert_chain()
229            .first()
230            .and_then(|_| sigin::canonical_scheme_for_spki(authority.public_key()))
231            .ok_or(SignEndpointError::NoSupportedScheme)?;
232        let signature = authority
233            .sign(&data)
234            .await
235            .context(sign_endpoint_error::SignSnafu)?;
236
237        self.signature = Some(EndpointSignature {
238            scheme: u16::from(scheme),
239            signature,
240        });
241        Ok(())
242    }
243
244    pub fn verify_signature(
245        &self,
246        spki: SubjectPublicKeyInfoDer<'_>,
247    ) -> Result<bool, sigin::VerifyError> {
248        let Some(sig) = &self.signature else {
249            return Ok(false);
250        };
251        let data = self.signed_data();
252        sigin::verify(
253            spki,
254            SignatureScheme::from(sig.scheme),
255            &data,
256            &sig.signature,
257        )
258    }
259
260    pub fn verify_signature_from_der(&self, cert_der: &[u8]) -> Result<bool, sigin::VerifyError> {
261        let (_, cert) = x509_parser::parse_x509_certificate(cert_der).map_err(|e| {
262            sigin::VerifyError::InvalidCertificate {
263                details: e.to_string(),
264            }
265        })?;
266
267        let spki = SubjectPublicKeyInfoDer::from(cert.tbs_certificate.subject_pki.raw);
268        self.verify_signature(spki)
269    }
270
271    pub fn verify_signature_from_pem(&self, cert_pem: &[u8]) -> Result<bool, sigin::VerifyError> {
272        let mut reader = std::io::Cursor::new(cert_pem);
273        if let Some(item) = rustls_pemfile::certs(&mut reader).next() {
274            let cert_der = item.map_err(|e| sigin::VerifyError::InvalidPem { source: e })?;
275            return self.verify_signature_from_der(&cert_der);
276        }
277        Err(sigin::VerifyError::InvalidCertificate {
278            details: "No certificate found in PEM".to_string(),
279        })
280    }
281
282    pub fn verify_signature_from_base64(
283        &self,
284        cert_base64: &str,
285    ) -> Result<bool, sigin::VerifyError> {
286        let cert_base64 = cert_base64.trim();
287        let cert_der = base64::engine::general_purpose::STANDARD
288            .decode(cert_base64)
289            .map_err(|e| sigin::VerifyError::InvalidBase64 { source: e })?;
290        self.verify_signature_from_der(&cert_der)
291    }
292
293    pub fn verify_signature_from_file(
294        &self,
295        path: impl AsRef<Path>,
296    ) -> Result<bool, sigin::VerifyError> {
297        let contents = std::fs::read(path).map_err(|e| sigin::VerifyError::Io { source: e })?;
298        // Try PEM first
299        if let Ok(res) = self.verify_signature_from_pem(&contents) {
300            return Ok(res);
301        }
302        // If PEM failed, try DER
303        self.verify_signature_from_der(&contents)
304    }
305
306    pub fn is_main(&self) -> bool {
307        self.flags() & Self::FLAG_MAIN == Self::FLAG_MAIN
308    }
309
310    pub fn set_main(&mut self, is_main: bool) {
311        let flags = self.flags_mut();
312        if is_main {
313            *flags |= Self::FLAG_MAIN;
314        } else {
315            *flags &= !Self::FLAG_MAIN;
316        }
317    }
318
319    pub fn is_signed(&self) -> bool {
320        self.flags() & Self::FLAG_SIGNED == Self::FLAG_SIGNED
321    }
322
323    pub fn set_signed(&mut self, is_signed: bool) {
324        let flags = self.flags_mut();
325        if is_signed {
326            *flags |= Self::FLAG_SIGNED;
327        } else {
328            *flags &= !Self::FLAG_SIGNED;
329        }
330    }
331
332    pub fn encpding_size(&self) -> usize {
333        let mut meta_len = 1; // flags
334
335        // sequence is only encoded when CLUSTERED flag is set
336        if let Some(seq) = &self.sequence {
337            meta_len += VarInt::from_u32(seq.get()).encoding_size();
338        }
339
340        if self.load.is_some() {
341            meta_len += 4; // f32
342        }
343
344        if self.is_signed()
345            && let Some(sig) = &self.signature
346        {
347            let sig_len =
348                VarInt::try_from(sig.signature.len() as u64).unwrap_or(VarInt::from_u32(0));
349            meta_len += 2 + sig_len.encoding_size() + sig.signature.len();
350        }
351
352        let addr_len = match (self.is_ipv6(), self.is_nat()) {
353            (false, false) => 2 + 4,      // IPv4 direct: port + ipv4
354            (false, true) => (2 + 4) * 2, // IPv4 NAT: (port + ipv4) * 2
355            (true, false) => 2 + 16,      // IPv6 direct: port + ipv6
356            (true, true) => (2 + 16) * 2, // IPv6 NAT: (port + ipv6) * 2
357        };
358
359        meta_len + addr_len
360    }
361
362    pub fn addr(&self) -> SocketAddr {
363        self.primary
364    }
365
366    pub fn agent_addr(&self) -> Option<SocketAddr> {
367        self.agent
368    }
369
370    pub fn sequence(&self) -> Option<CertificateSequence> {
371        self.sequence
372    }
373
374    pub fn normalized_sequence(&self) -> CertificateSequence {
375        self.sequence
376            .unwrap_or_else(|| CertificateSequence::from(0u8))
377    }
378
379    pub fn set_sequence(&mut self, sequence: CertificateSequence) {
380        if sequence.get() > 0 {
381            self.sequence = Some(sequence);
382            self.set_clustered(true);
383        } else {
384            self.sequence = None;
385            self.set_clustered(false);
386        }
387    }
388
389    pub fn certificate_chain_key(&self) -> CertificateChainKey {
390        let kind = if self.is_main() {
391            CertificateChainKind::Primary
392        } else {
393            CertificateChainKind::Secondary
394        };
395        CertificateChainKey::new(self.normalized_sequence(), kind)
396    }
397
398    pub fn load(&self) -> Option<f32> {
399        self.load
400    }
401
402    fn flags(&self) -> u8 {
403        self.flags
404    }
405
406    fn flags_mut(&mut self) -> &mut u8 {
407        &mut self.flags
408    }
409
410    pub fn signature(&self) -> Option<&EndpointSignature> {
411        self.signature.as_ref()
412    }
413
414    pub fn signature_base64(&self) -> Option<String> {
415        self.signature
416            .as_ref()
417            .map(|sig| base64::engine::general_purpose::STANDARD.encode(&sig.signature))
418    }
419
420    fn write_base<B: BufMut>(&self, buf: &mut B) {
421        buf.put_u8(self.flags);
422
423        // Sequence is only written when CLUSTERED is set
424        if let Some(seq) = &self.sequence {
425            buf.put_varint(VarInt::from_u32(seq.get()));
426        }
427
428        // Write primary address
429        match self.primary {
430            SocketAddr::V4(addr) => buf.put_socket_addr_v4(&addr),
431            SocketAddr::V6(addr) => buf.put_socket_addr_v6(&addr),
432        }
433
434        // Write agent address when NAT traversal is required
435        if let Some(agent_addr) = &self.agent {
436            match agent_addr {
437                SocketAddr::V4(addr) => buf.put_socket_addr_v4(addr),
438                SocketAddr::V6(addr) => buf.put_socket_addr_v6(addr),
439            }
440        }
441
442        if let Some(load) = self.load {
443            buf.put_u32(load.to_bits());
444        }
445    }
446
447    fn signed_data(&self) -> Vec<u8> {
448        let mut unsigned = self.clone();
449        unsigned.set_signed(true);
450        unsigned.signature = None;
451        let mut buf = bytes::BytesMut::with_capacity(unsigned.encpding_size());
452        unsigned.write_base(&mut buf);
453        buf.to_vec()
454    }
455}
456
457pub(crate) trait WriteEndpointAddr {
458    fn put_endpoint_addr(&mut self, endpoint: &EndpointAddr);
459}
460
461impl<B: BufMut> WriteEndpointAddr for B {
462    fn put_endpoint_addr(&mut self, endpoint: &EndpointAddr) {
463        endpoint.write_base(self);
464        if endpoint.is_signed()
465            && let Some(sig) = endpoint.signature()
466        {
467            self.put_u16(sig.scheme);
468            let len = VarInt::try_from(sig.signature.len() as u64).unwrap_or(VarInt::from_u32(0));
469            self.put_varint(len);
470            self.put_slice(&sig.signature);
471        }
472    }
473}
474
475pub fn be_endpoint_addr(input: &[u8]) -> nom::IResult<&[u8], EndpointAddr> {
476    let (remain, flags) = be_u8(input)?;
477
478    let is_clustered = flags & EndpointAddr::FLAG_CLUSTERED != 0;
479    let is_ipv6 = flags & EndpointAddr::FLAG_FAMILY != 0;
480    let is_nat = flags & EndpointAddr::FLAG_NAT != 0;
481    let has_load = flags & EndpointAddr::FLAG_LOAD != 0;
482
483    // Sequence number is only present when CLUSTERED is set
484    let (remain, sequence) = if is_clustered {
485        let (remain, seq) = be_varint(remain)?;
486        let sequence = match CertificateSequence::try_from(seq.into_inner()) {
487            Ok(sequence) => sequence,
488            Err(_error) => {
489                return Err(nom::Err::Failure(make_error(remain, ErrorKind::TooLarge)));
490            }
491        };
492        (remain, Some(sequence))
493    } else {
494        (remain, None)
495    };
496
497    let (remain, primary) = if is_ipv6 {
498        let (remain, addr) = be_socket_addr_v6(remain)?;
499        (remain, SocketAddr::V6(addr))
500    } else {
501        let (remain, addr) = be_socket_addr_v4(remain)?;
502        (remain, SocketAddr::V4(addr))
503    };
504
505    let (remain, agent) = if is_nat {
506        let agent_addr = if is_ipv6 {
507            let (remain, addr) = be_socket_addr_v6(remain)?;
508            (remain, SocketAddr::V6(addr))
509        } else {
510            let (remain, addr) = be_socket_addr_v4(remain)?;
511            (remain, SocketAddr::V4(addr))
512        };
513        let (remain, addr) = agent_addr;
514        (remain, Some(addr))
515    } else {
516        (remain, None)
517    };
518
519    let (remain, load) = if has_load {
520        let (remain, load) = be_u32(remain)?;
521        (remain, Some(f32::from_bits(load)))
522    } else {
523        (remain, None)
524    };
525
526    let (remain, signature) = be_endpoint_signature(remain, flags)?;
527
528    Ok((
529        remain,
530        EndpointAddr {
531            flags,
532            sequence,
533            load,
534            signature,
535            primary,
536            agent,
537        },
538    ))
539}
540
541/// Parse an EndpointAddr with backward compatibility.
542///
543/// - If `rdlen` matches a legacy fixed length, parse as address-only and fill in default flags.
544/// - Otherwise parse as the modern format (with `flags` + optional fields).
545///
546/// Note: Legacy and modern records differ in their leading bytes.
547/// Disambiguation is done via `RDLENGTH` to avoid misinterpreting the port's high byte as `flags`.
548pub(crate) fn be_endpoint_addr_compat(
549    input: &[u8],
550    rdlen: u16,
551) -> nom::IResult<&[u8], EndpointAddr> {
552    // Check for legacy fixed lengths
553    let legacy_lengths = [
554        6,  // IPv4 direct: port(2) + ip(4)
555        12, // IPv4 NAT:    (port(2) + ip(4)) * 2
556        18, // IPv6 direct: port(2) + ip(16)
557        36, // IPv6 NAT:    (port(2) + ip(16)) * 2
558    ];
559
560    if legacy_lengths.contains(&(rdlen as usize)) {
561        return be_legacy_endpoint_addr_by_length(input, rdlen);
562    }
563
564    // Modern format
565    be_endpoint_addr(input)
566}
567
568/// Parse a legacy EndpointAddr record, identified by its fixed RDLENGTH.
569fn be_legacy_endpoint_addr_by_length(
570    input: &[u8],
571    rdlen: u16,
572) -> nom::IResult<&[u8], EndpointAddr> {
573    match rdlen {
574        6 => {
575            // IPv4 direct
576            let (remain, addr) = be_socket_addr_v4(input)?;
577            Ok((
578                remain,
579                EndpointAddr {
580                    flags: 0,
581                    sequence: None,
582                    load: None,
583                    signature: None,
584                    primary: addr.into(),
585                    agent: None,
586                },
587            ))
588        }
589        12 => {
590            // IPv4 NAT
591            let (remain, primary) = be_socket_addr_v4(input)?;
592            let (remain, agent) = be_socket_addr_v4(remain)?;
593            Ok((
594                remain,
595                EndpointAddr {
596                    flags: EndpointAddr::FLAG_NAT,
597                    sequence: None,
598                    load: None,
599                    signature: None,
600                    primary: primary.into(),
601                    agent: Some(agent.into()),
602                },
603            ))
604        }
605        18 => {
606            // IPv6 direct
607            let (remain, addr) = be_socket_addr_v6(input)?;
608            Ok((
609                remain,
610                EndpointAddr {
611                    flags: EndpointAddr::FLAG_FAMILY,
612                    sequence: None,
613                    load: None,
614                    signature: None,
615                    primary: addr.into(),
616                    agent: None,
617                },
618            ))
619        }
620        36 => {
621            // IPv6 NAT
622            let (remain, primary) = be_socket_addr_v6(input)?;
623            let (remain, agent) = be_socket_addr_v6(remain)?;
624            Ok((
625                remain,
626                EndpointAddr {
627                    flags: EndpointAddr::FLAG_FAMILY | EndpointAddr::FLAG_NAT,
628                    sequence: None,
629                    load: None,
630                    signature: None,
631                    primary: primary.into(),
632                    agent: Some(agent.into()),
633                },
634            ))
635        }
636        _ => Err(nom::Err::Error(nom::error::make_error(
637            input,
638            nom::error::ErrorKind::LengthValue,
639        ))),
640    }
641}
642
643fn be_endpoint_signature(input: &[u8], flags: u8) -> IResult<&[u8], Option<EndpointSignature>> {
644    if (flags & EndpointAddr::FLAG_SIGNED) != EndpointAddr::FLAG_SIGNED {
645        if !input.is_empty() {
646            return Err(nom::Err::Error(make_error(input, ErrorKind::Eof)));
647        }
648        return Ok((input, None));
649    }
650
651    let (remain, scheme_u16) = be_u16(input)?;
652    let (remain, sig_len) = be_varint(remain)?;
653    let sig_len = usize::try_from(sig_len.into_inner())
654        .map_err(|_| nom::Err::Error(make_error(remain, ErrorKind::TooLarge)))?;
655    let (remain, sig) = take(sig_len)(remain)?;
656    Ok((
657        remain,
658        Some(EndpointSignature {
659            scheme: scheme_u16,
660            signature: sig.to_vec(),
661        }),
662    ))
663}
664
665pub trait WriteSocketAddr {
666    fn put_socket_addr_v4(&mut self, addr: &SocketAddrV4);
667
668    fn put_socket_addr_v6(&mut self, addr: &SocketAddrV6);
669
670    fn put_socket_addr(&mut self, addr: &SocketAddr) {
671        match addr {
672            SocketAddr::V4(v4) => self.put_socket_addr_v4(v4),
673            SocketAddr::V6(v6) => self.put_socket_addr_v6(v6),
674        }
675    }
676}
677
678impl<T: BufMut> WriteSocketAddr for T {
679    fn put_socket_addr_v4(&mut self, addr: &SocketAddrV4) {
680        self.put_u16(addr.port());
681        self.put_u32(u32::from(*addr.ip()));
682    }
683
684    fn put_socket_addr_v6(&mut self, addr: &SocketAddrV6) {
685        self.put_u16(addr.port());
686        self.put_u128(u128::from(*addr.ip()));
687    }
688}
689
690pub fn be_socket_addr_v4(input: &[u8]) -> IResult<&[u8], SocketAddrV4> {
691    flat_map(be_u16, |port| {
692        map(be_ipv4_addr, move |ip| SocketAddrV4::new(ip, port))
693    })
694    .parse(input)
695}
696
697pub fn be_socket_addr_v6(input: &[u8]) -> IResult<&[u8], SocketAddrV6> {
698    flat_map(be_u16, |port| {
699        map(be_ipv6_addr, move |ip| SocketAddrV6::new(ip, port, 0, 0))
700    })
701    .parse(input)
702}
703
704pub fn be_ipv4_addr(input: &[u8]) -> IResult<&[u8], Ipv4Addr> {
705    map(be_u32, Ipv4Addr::from).parse(input)
706}
707
708pub fn be_ipv6_addr(input: &[u8]) -> IResult<&[u8], Ipv6Addr> {
709    map(be_u128, Ipv6Addr::from).parse(input)
710}
711
712pub fn be_ip_addr(is_v6: bool) -> impl Fn(&[u8]) -> IResult<&[u8], IpAddr> {
713    move |input| match is_v6 {
714        true => map(be_u128, |ip| IpAddr::V6(Ipv6Addr::from(ip))).parse(input),
715        false => map(be_u32, |ip| IpAddr::V4(Ipv4Addr::from(ip))).parse(input),
716    }
717}
718
719impl Display for EndpointAddr {
720    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
721        if let Some(agent_addr) = &self.agent {
722            write!(f, "{}-{agent_addr}", self.primary)
723        } else {
724            write!(f, "{}", self.primary)
725        }
726    }
727}
728
729impl TryFrom<DquicEndpointAddr> for EndpointAddr {
730    type Error = ();
731
732    fn try_from(value: DquicEndpointAddr) -> Result<Self, Self::Error> {
733        match value {
734            DquicEndpointAddr::Direct {
735                addr: SocketAddr::V4(addr),
736            } => Ok(Self::direct_v4(addr)),
737            DquicEndpointAddr::Direct {
738                addr: SocketAddr::V6(addr),
739            } => Ok(Self::direct_v6(addr)),
740            DquicEndpointAddr::Agent {
741                agent: SocketAddr::V4(agent),
742                outer: SocketAddr::V4(outer),
743            } => Ok(Self::nat_v4(outer, agent)),
744            DquicEndpointAddr::Agent {
745                agent: SocketAddr::V6(agent),
746                outer: SocketAddr::V6(outer),
747            } => Ok(Self::nat_v6(outer, agent)),
748            _ => Err(()),
749        }
750    }
751}
752
753impl TryFrom<EndpointAddr> for DquicEndpointAddr {
754    type Error = ();
755
756    fn try_from(value: EndpointAddr) -> Result<Self, Self::Error> {
757        if let Some(agent_addr) = value.agent {
758            match (value.primary, agent_addr) {
759                (SocketAddr::V4(outer), SocketAddr::V4(agent)) => Ok(DquicEndpointAddr::Agent {
760                    outer: SocketAddr::V4(outer),
761                    agent: SocketAddr::V4(agent),
762                }),
763                (SocketAddr::V6(outer), SocketAddr::V6(agent)) => Ok(DquicEndpointAddr::Agent {
764                    outer: SocketAddr::V6(outer),
765                    agent: SocketAddr::V6(agent),
766                }),
767                _ => Err(()),
768            }
769        } else {
770            match value.primary {
771                SocketAddr::V4(addr) => Ok(DquicEndpointAddr::Direct {
772                    addr: SocketAddr::V4(addr),
773                }),
774                SocketAddr::V6(addr) => Ok(DquicEndpointAddr::Direct {
775                    addr: SocketAddr::V6(addr),
776                }),
777            }
778        }
779    }
780}
781
782pub async fn sign_endponit_address(
783    server_id: u8,
784    authority: Option<&(impl dhttp_identity::identity::LocalAuthority + ?Sized)>,
785    endpoint: DquicEndpointAddr,
786) -> Option<EndpointAddr> {
787    let mut ep: EndpointAddr = endpoint.try_into().ok()?;
788    ep.set_main(server_id == 0);
789    ep.set_sequence(CertificateSequence::from(server_id));
790    if let Some(authority) = authority {
791        let _ = ep.sign_with_authority(authority).await;
792    }
793    Some(ep)
794}
795
796#[cfg(test)]
797mod tests {
798    use std::{
799        net::{Ipv4Addr, Ipv6Addr},
800        sync::Arc,
801    };
802
803    use bytes::BytesMut;
804    use futures::future::BoxFuture;
805    use ring::signature::KeyPair;
806    use rustls::sign::{Signer, SigningKey};
807
808    use super::*;
809
810    fn v4_outer() -> SocketAddrV4 {
811        SocketAddrV4::new(Ipv4Addr::new(203, 0, 113, 10), 4433)
812    }
813
814    #[test]
815    fn endpoint_certificate_chain_key_normalizes_missing_sequence() {
816        let mut endpoint = EndpointAddr::direct_v4(v4_outer());
817        endpoint.set_main(true);
818
819        let key = endpoint.certificate_chain_key();
820
821        assert_eq!(
822            key.kind(),
823            dhttp_identity::certificate::CertificateChainKind::Primary
824        );
825        assert_eq!(key.sequence().get(), 0);
826        assert_eq!(key.to_string(), "primary:0");
827    }
828
829    #[test]
830    fn endpoint_certificate_chain_key_uses_present_sequence() {
831        let mut endpoint = EndpointAddr::direct_v4(v4_outer());
832        endpoint.set_main(false);
833        endpoint.set_sequence(
834            dhttp_identity::certificate::CertificateSequence::try_from(7u32).unwrap(),
835        );
836
837        let key = endpoint.certificate_chain_key();
838
839        assert_eq!(
840            key.kind(),
841            dhttp_identity::certificate::CertificateChainKind::Secondary
842        );
843        assert_eq!(key.sequence().get(), 7);
844        assert_eq!(key.to_string(), "secondary:7");
845    }
846
847    #[test]
848    fn endpoint_parser_rejects_over_range_certificate_sequence() {
849        let sequence = crate::core::parser::varint::VarInt::from_u64(
850            dhttp_identity::certificate::CertificateSequence::MAX as u64 + 1,
851        )
852        .unwrap();
853        let mut packet = BytesMut::new();
854        packet.put_u8(EndpointAddr::FLAG_MAIN | EndpointAddr::FLAG_CLUSTERED);
855        packet.put_varint(sequence);
856        packet.put_u16(v4_outer().port());
857        packet.put_slice(&v4_outer().ip().octets());
858
859        assert!(be_endpoint_addr(&packet).is_err());
860    }
861
862    #[test]
863    fn legacy_endpoint_v4_direct_without_meta() {
864        let port = 5353u16;
865        let ip = Ipv4Addr::new(10, 0, 0, 1);
866        let mut buf = BytesMut::new();
867        buf.extend_from_slice(&port.to_be_bytes());
868        buf.extend_from_slice(&u32::from(ip).to_be_bytes());
869        let (remain, decoded) = be_endpoint_addr_compat(&buf, 6).unwrap();
870        assert!(remain.is_empty());
871        assert_eq!(
872            decoded,
873            EndpointAddr::direct_v4(SocketAddrV4::new(ip, port))
874        );
875    }
876
877    #[test]
878    fn legacy_endpoint_v4_nat_without_meta() {
879        let outer = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 1000);
880        let agent = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 2), 2000);
881        let mut buf = BytesMut::new();
882        buf.extend_from_slice(&outer.port().to_be_bytes());
883        buf.extend_from_slice(&u32::from(*outer.ip()).to_be_bytes());
884        buf.extend_from_slice(&agent.port().to_be_bytes());
885        buf.extend_from_slice(&u32::from(*agent.ip()).to_be_bytes());
886        let (remain, decoded) = be_endpoint_addr_compat(&buf, 12).unwrap();
887        assert!(remain.is_empty());
888        assert_eq!(decoded, EndpointAddr::nat_v4(outer, agent));
889    }
890
891    #[test]
892    fn flag_bit_ops_work() {
893        let addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 5353);
894        let mut ep = EndpointAddr {
895            flags: 0b0011_0000,
896            sequence: None,
897            load: None,
898            signature: None,
899            primary: addr.into(),
900            agent: None,
901        };
902
903        assert!(!ep.is_main());
904        assert!(!ep.is_signed());
905
906        ep.set_main(true);
907        assert!(ep.is_main());
908        assert_eq!(ep.flags, 0b0111_0000);
909
910        ep.set_signed(true);
911        assert!(ep.is_signed());
912        assert_eq!(ep.flags, 0b0111_0001);
913
914        ep.set_main(false);
915        assert!(!ep.is_main());
916        assert!(ep.is_signed());
917        assert_eq!(ep.flags, 0b0011_0001);
918
919        ep.set_signed(false);
920        assert!(!ep.is_signed());
921        assert_eq!(ep.flags, 0b0011_0000);
922    }
923
924    #[test]
925    fn varint_roundtrip_and_len() {
926        fn roundtrip(v: u64) {
927            let v = VarInt::from_u64(v).unwrap();
928            let mut buf = BytesMut::new();
929            buf.put_varint(v);
930            assert_eq!(buf.len(), v.encoding_size());
931            let (remain, decoded) = be_varint(&buf).unwrap();
932            assert!(remain.is_empty());
933            assert_eq!(decoded, v);
934        }
935
936        for v in [
937            0u64,
938            1,
939            63,
940            64,
941            16383,
942            16384,
943            (1 << 30) - 1,
944            1 << 30,
945            (1 << 62) - 1,
946        ] {
947            roundtrip(v);
948        }
949    }
950
951    #[test]
952    fn varint_rejects_overflow_and_incomplete() {
953        assert!(VarInt::from_u64((1 << 62) + 1).is_err());
954
955        let incomplete = [0b01_000000u8];
956        match be_varint(&incomplete) {
957            Err(nom::Err::Incomplete(_)) => {}
958            other => panic!("expected Incomplete, got {other:?}"),
959        }
960    }
961
962    #[test]
963    fn endpoint_encode_decode_roundtrip() {
964        let v4_outer = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 1000);
965        let v4_agent = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 2), 2000);
966        let v6_outer = SocketAddrV6::new(Ipv6Addr::LOCALHOST, 3000, 0, 0);
967        let v6_agent = SocketAddrV6::new(Ipv6Addr::LOCALHOST, 4000, 0, 0);
968
969        let mut with_load = EndpointAddr::direct_v4(v4_outer);
970        with_load.set_load(Some(0.42_f32));
971
972        let cases = vec![
973            // IPv4 direct, MAIN + CLUSTERED flags
974            EndpointAddr {
975                flags: EndpointAddr::FLAG_MAIN | EndpointAddr::FLAG_CLUSTERED,
976                sequence: Some(CertificateSequence::from(0u8)),
977                load: None,
978                signature: None,
979                primary: v4_outer.into(),
980                agent: None,
981            },
982            // IPv4 NAT, CLUSTERED flag
983            EndpointAddr {
984                flags: EndpointAddr::FLAG_NAT | EndpointAddr::FLAG_CLUSTERED,
985                sequence: Some(CertificateSequence::try_from(127u32).unwrap()),
986                load: None,
987                signature: None,
988                primary: v4_outer.into(),
989                agent: Some(v4_agent.into()),
990            },
991            // IPv6 direct, MAIN + CLUSTERED flags
992            EndpointAddr {
993                flags: EndpointAddr::FLAG_FAMILY
994                    | EndpointAddr::FLAG_MAIN
995                    | EndpointAddr::FLAG_CLUSTERED,
996                sequence: Some(CertificateSequence::try_from(128u32).unwrap()),
997                load: None,
998                signature: None,
999                primary: v6_outer.into(),
1000                agent: None,
1001            },
1002            // IPv6 NAT, CLUSTERED flag
1003            EndpointAddr {
1004                flags: EndpointAddr::FLAG_FAMILY
1005                    | EndpointAddr::FLAG_NAT
1006                    | EndpointAddr::FLAG_CLUSTERED,
1007                sequence: Some(CertificateSequence::try_from(16_384u32).unwrap()),
1008                load: None,
1009                signature: None,
1010                primary: v6_outer.into(),
1011                agent: Some(v6_agent.into()),
1012            },
1013            // IPv4 direct with LOAD
1014            with_load,
1015        ];
1016
1017        for ep in cases {
1018            let mut buf = BytesMut::new();
1019            buf.put_endpoint_addr(&ep);
1020            assert_eq!(buf.len(), ep.encpding_size());
1021
1022            let (remain, decoded) = be_endpoint_addr(&buf).unwrap();
1023            assert!(remain.is_empty());
1024            assert_eq!(decoded, ep);
1025        }
1026    }
1027
1028    #[test]
1029    fn endpoint_signature_roundtrip_and_verify() {
1030        #[derive(Debug)]
1031        struct Ed25519Key {
1032            keypair: Arc<ring::signature::Ed25519KeyPair>,
1033            cert_chain: Vec<rustls::pki_types::CertificateDer<'static>>,
1034        }
1035
1036        #[derive(Debug)]
1037        struct Ed25519Signer(Arc<ring::signature::Ed25519KeyPair>);
1038
1039        impl Signer for Ed25519Signer {
1040            fn sign(&self, message: &[u8]) -> Result<Vec<u8>, rustls::Error> {
1041                Ok(self.0.sign(message).as_ref().to_vec())
1042            }
1043
1044            fn scheme(&self) -> SignatureScheme {
1045                SignatureScheme::ED25519
1046            }
1047        }
1048
1049        impl SigningKey for Ed25519Key {
1050            fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>> {
1051                offered
1052                    .contains(&SignatureScheme::ED25519)
1053                    .then(|| Box::new(Ed25519Signer(self.keypair.clone())) as Box<dyn Signer>)
1054            }
1055
1056            fn algorithm(&self) -> rustls::SignatureAlgorithm {
1057                rustls::SignatureAlgorithm::ED25519
1058            }
1059        }
1060
1061        impl dhttp_identity::identity::LocalAuthority for Ed25519Key {
1062            fn name(&self) -> &str {
1063                "authority.example"
1064            }
1065
1066            fn cert_chain(&self) -> &[rustls::pki_types::CertificateDer<'static>] {
1067                &self.cert_chain
1068            }
1069
1070            fn sign(
1071                &self,
1072                data: &[u8],
1073            ) -> BoxFuture<'_, Result<Vec<u8>, dhttp_identity::identity::SignError>> {
1074                let result = dhttp_identity::identity::sign_with_key(self, data);
1075                Box::pin(std::future::ready(result))
1076            }
1077        }
1078
1079        let rng = ring::rand::SystemRandom::new();
1080        let pkcs8 = ring::signature::Ed25519KeyPair::generate_pkcs8(&rng).unwrap();
1081        let keypair =
1082            Arc::new(ring::signature::Ed25519KeyPair::from_pkcs8(pkcs8.as_ref()).unwrap());
1083        let mut spki = Vec::with_capacity(44);
1084        spki.extend_from_slice(&[
1085            0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00,
1086        ]);
1087        spki.extend_from_slice(keypair.public_key().as_ref());
1088        let key = Ed25519Key {
1089            keypair: keypair.clone(),
1090            cert_chain: vec![rustls::pki_types::CertificateDer::from(spki.clone())],
1091        };
1092
1093        let addr = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 5353);
1094        let mut ep = EndpointAddr::direct_v4(addr);
1095        ep.set_main(true);
1096        futures::executor::block_on(ep.sign_with_authority(&key)).unwrap();
1097
1098        let mut buf = BytesMut::new();
1099        buf.put_endpoint_addr(&ep);
1100        assert_eq!(buf.len(), ep.encpding_size());
1101
1102        let (remain, decoded) = be_endpoint_addr(&buf).unwrap();
1103        assert!(remain.is_empty());
1104        assert!(decoded.is_signed());
1105        assert!(decoded.signature().is_some());
1106        assert!(
1107            decoded
1108                .verify_signature(SubjectPublicKeyInfoDer::from(spki.as_slice()))
1109                .unwrap()
1110        );
1111
1112        let mut tampered = decoded.clone();
1113        tampered.set_main(false);
1114        assert!(
1115            !tampered
1116                .verify_signature(SubjectPublicKeyInfoDer::from(spki.as_slice()))
1117                .unwrap()
1118        );
1119    }
1120
1121    #[test]
1122    fn sign_with_authority_uses_canonical_scheme_from_public_key() {
1123        #[derive(Debug)]
1124        struct Ed25519Authority {
1125            cert_chain: Vec<rustls::pki_types::CertificateDer<'static>>,
1126        }
1127
1128        impl dhttp_identity::identity::LocalAuthority for Ed25519Authority {
1129            fn name(&self) -> &str {
1130                "authority.example"
1131            }
1132
1133            fn cert_chain(&self) -> &[rustls::pki_types::CertificateDer<'static>] {
1134                &self.cert_chain
1135            }
1136
1137            fn sign(
1138                &self,
1139                _data: &[u8],
1140            ) -> BoxFuture<'_, Result<Vec<u8>, dhttp_identity::identity::SignError>> {
1141                Box::pin(async move { Ok(vec![1, 2, 3]) })
1142            }
1143        }
1144
1145        let cert_chain = vec![rustls::pki_types::CertificateDer::from(vec![
1146            0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00, 0, 0, 0, 0, 0,
1147            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1148        ])];
1149        let mut ep = EndpointAddr::direct_v4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 5353));
1150        futures::executor::block_on(ep.sign_with_authority(&Ed25519Authority { cert_chain }))
1151            .unwrap();
1152
1153        let signature = ep.signature().unwrap();
1154        assert_eq!(
1155            SignatureScheme::from(signature.scheme),
1156            SignatureScheme::ED25519
1157        );
1158        assert_eq!(signature.signature, vec![1, 2, 3]);
1159    }
1160
1161    #[test]
1162    fn optional_fields_flags_follow_values() {
1163        let addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 5353);
1164        let mut ep = EndpointAddr::direct_v4(addr);
1165
1166        assert!(!ep.is_load());
1167
1168        ep.set_load(Some(0.5_f32));
1169
1170        assert!(ep.is_load());
1171        assert_eq!(ep.load(), Some(0.5_f32));
1172
1173        ep.set_load(None);
1174
1175        assert!(!ep.is_load());
1176        assert_eq!(ep.load(), None);
1177    }
1178}