cypheraddr/
p2p.rs

1// Set of libraries for privacy-preserving networking apps
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5// Written in 2019-2023 by
6//     Dr. Maxim Orlovsky <orlovsky@cyphernet.org>
7//
8// Copyright 2022-2023 Cyphernet DAO, Switzerland
9//
10// Licensed under the Apache License, Version 2.0 (the "License");
11// you may not use this file except in compliance with the License.
12// You may obtain a copy of the License at
13//
14//     http://www.apache.org/licenses/LICENSE-2.0
15//
16// Unless required by applicable law or agreed to in writing, software
17// distributed under the License is distributed on an "AS IS" BASIS,
18// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19// See the License for the specific language governing permissions and
20// limitations under the License.
21
22use std::borrow::Borrow;
23use std::fmt::{self, Debug, Display, Formatter};
24use std::io;
25use std::net::{self, ToSocketAddrs};
26use std::str::FromStr;
27
28use cypher::EcPk;
29
30use crate::{Addr, AddrParseError, Host, NetAddr, PartialAddr, ToSocketAddr};
31
32#[derive(Debug, Display, Error, From)]
33#[display(doc_comments)]
34pub enum PeerAddrParseError<Id: Debug>
35where
36    Id: FromStr,
37    <Id as FromStr>::Err: std::error::Error,
38{
39    #[from]
40    #[from(net::AddrParseError)]
41    #[display(inner)]
42    Addr(AddrParseError),
43
44    /// invalid peer key. Details: {0}
45    Key(<Id as FromStr>::Err),
46
47    /// invalid peer address format. Peer address must contain peer key and peer
48    /// network address, separated by '@'
49    InvalidFormat,
50}
51
52#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
53pub struct PeerAddr<Id: EcPk, A: Addr> {
54    pub id: Id,
55    pub addr: A,
56}
57
58impl<Id: EcPk, A: Addr> PeerAddr<Id, A> {
59    pub fn new(id: Id, addr: A) -> Self { Self { id, addr } }
60}
61
62impl<Id: EcPk, A: Addr> Borrow<Id> for PeerAddr<Id, A> {
63    fn borrow(&self) -> &Id { &self.id }
64}
65
66impl<Id: EcPk, A: Addr> Host for PeerAddr<Id, A> {
67    fn requires_proxy(&self) -> bool { self.addr.requires_proxy() }
68}
69
70impl<Id: EcPk, A: Addr> Addr for PeerAddr<Id, A> {
71    fn port(&self) -> u16 { self.addr.port() }
72}
73
74impl<Id: EcPk, A: Addr + ToSocketAddr> ToSocketAddr for PeerAddr<Id, A> {
75    fn to_socket_addr(&self) -> net::SocketAddr { self.addr.to_socket_addr() }
76}
77
78impl<Id: EcPk, A: Addr> Display for PeerAddr<Id, A>
79where
80    Id: Display,
81    A: Display,
82{
83    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "{}@{}", self.id, self.addr) }
84}
85
86impl<Id: EcPk, A: Addr> FromStr for PeerAddr<Id, A>
87where
88    Id: FromStr + Debug,
89    <Id as FromStr>::Err: std::error::Error,
90    A: FromStr,
91    <A as FromStr>::Err: Into<PeerAddrParseError<Id>>,
92{
93    type Err = PeerAddrParseError<Id>;
94
95    fn from_str(s: &str) -> Result<Self, Self::Err> {
96        if let Some((pk, addr)) = s.split_once('@') {
97            Ok(PeerAddr {
98                id: Id::from_str(pk).map_err(PeerAddrParseError::Key)?,
99                addr: A::from_str(addr).map_err(<A as FromStr>::Err::into)?,
100            })
101        } else {
102            Err(PeerAddrParseError::InvalidFormat)
103        }
104    }
105}
106
107impl<Id: EcPk, H: Host, const DEFAULT_PORT: u16> From<PeerAddr<Id, PartialAddr<H, DEFAULT_PORT>>>
108    for PeerAddr<Id, NetAddr<H>>
109{
110    fn from(peer: PeerAddr<Id, PartialAddr<H, DEFAULT_PORT>>) -> Self {
111        PeerAddr {
112            addr: peer.addr.into(),
113            id: peer.id,
114        }
115    }
116}
117
118impl<Id: EcPk, A: Addr, To: Host> From<PeerAddr<Id, A>> for NetAddr<To>
119where NetAddr<To>: From<A>
120{
121    fn from(peer: PeerAddr<Id, A>) -> Self { peer.addr.into() }
122}
123
124impl<Id: EcPk, A: Addr + Into<net::SocketAddr>> From<PeerAddr<Id, A>> for net::SocketAddr {
125    fn from(peer: PeerAddr<Id, A>) -> Self { peer.addr.into() }
126}
127
128impl<Id: EcPk, A: Addr> PeerAddr<Id, A> {
129    pub fn with(id: impl Into<Id>, addr: impl Into<A>) -> Self {
130        PeerAddr {
131            id: id.into(),
132            addr: addr.into(),
133        }
134    }
135}
136
137impl<Id: EcPk, A> ToSocketAddrs for PeerAddr<Id, A>
138where A: Addr + ToSocketAddrs
139{
140    type Iter = A::Iter;
141
142    fn to_socket_addrs(&self) -> io::Result<A::Iter> { self.addr.to_socket_addrs() }
143}