diff --git a/radicle-node/src/address.rs b/radicle-node/src/address.rs deleted file mode 100644 index bc609522..00000000 --- a/radicle-node/src/address.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod store; -mod types; - -pub use store::*; -pub use types::*; diff --git a/radicle-node/src/lib.rs b/radicle-node/src/lib.rs index 30ca32cb..7b22bc25 100644 --- a/radicle-node/src/lib.rs +++ b/radicle-node/src/lib.rs @@ -1,4 +1,3 @@ -pub mod address; pub mod bounded; pub mod control; pub mod deserializer; diff --git a/radicle-node/src/runtime.rs b/radicle-node/src/runtime.rs index 53a7262b..fc1687aa 100644 --- a/radicle-node/src/runtime.rs +++ b/radicle-node/src/runtime.rs @@ -14,12 +14,12 @@ use reactor::Reactor; use thiserror::Error; use radicle::git; +use radicle::node::address; use radicle::node::Handle as _; use radicle::node::{ADDRESS_DB_FILE, ROUTING_DB_FILE, TRACKING_DB_FILE}; use radicle::profile::Home; use radicle::Storage; -use crate::address; use crate::control; use crate::crypto::Signer; use crate::node::{routing, NodeId}; diff --git a/radicle-node/src/service.rs b/radicle-node/src/service.rs index 708212f9..d1025bbc 100644 --- a/radicle-node/src/service.rs +++ b/radicle-node/src/service.rs @@ -19,8 +19,9 @@ use fastrand::Rng; use localtime::{LocalDuration, LocalTime}; use log::*; -use crate::address; -use crate::address::{AddressBook, KnownAddress}; +use radicle::node::address; +use radicle::node::address::{AddressBook, KnownAddress}; + use crate::crypto; use crate::crypto::{Signer, Verified}; use crate::identity::IdentityError; diff --git a/radicle-node/src/test/peer.rs b/radicle-node/src/test/peer.rs index 94a3f0d7..7544ef32 100644 --- a/radicle-node/src/test/peer.rs +++ b/radicle-node/src/test/peer.rs @@ -4,12 +4,13 @@ use std::net; use std::ops::{Deref, DerefMut}; use log::*; + +use radicle::node::address; +use radicle::node::address::Store; use radicle::rad; use radicle::storage::ReadRepository; use radicle::Storage; -use crate::address; -use crate::address::Store; use crate::crypto::test::signer::MockSigner; use crate::crypto::Signer; use crate::identity::Id; diff --git a/radicle-node/src/wire/protocol.rs b/radicle-node/src/wire/protocol.rs index 95553565..d683ad54 100644 --- a/radicle-node/src/wire/protocol.rs +++ b/radicle-node/src/wire/protocol.rs @@ -22,11 +22,12 @@ use netservices::{NetConnection, NetProtocol, NetReader, NetWriter}; use reactor::Timestamp; use radicle::collections::HashMap; -use radicle::node::{routing, NodeId}; +use radicle::node::{address, routing, NodeId}; use radicle::storage::WriteStorage; use crate::crypto::Signer; use crate::prelude::Deserializer; +use crate::service; use crate::service::io::Io; use crate::service::{session, DisconnectReason, Service}; use crate::wire::frame; @@ -35,7 +36,6 @@ use crate::wire::Encode; use crate::worker; use crate::worker::{ChannelEvent, FetchRequest, FetchResult, Task, TaskResult}; use crate::Link; -use crate::{address, service}; /// NoiseXK handshake pattern. pub const NOISE_XK: HandshakePattern = HandshakePattern { diff --git a/radicle/src/lib.rs b/radicle/src/lib.rs index ea6bc609..aaa98143 100644 --- a/radicle/src/lib.rs +++ b/radicle/src/lib.rs @@ -1,7 +1,6 @@ #![allow(clippy::match_like_matches_macro)] #![allow(clippy::explicit_auto_deref)] // TODO: This can be removed when the clippy bugs are fixed #![allow(clippy::iter_nth_zero)] -#![cfg_attr(not(test), warn(clippy::unwrap_used))] pub extern crate radicle_crypto as crypto; diff --git a/radicle/src/node.rs b/radicle/src/node.rs index 60b405e7..ef9e0670 100644 --- a/radicle/src/node.rs +++ b/radicle/src/node.rs @@ -1,5 +1,6 @@ mod features; +pub mod address; pub mod events; pub mod routing; pub mod tracking; diff --git a/radicle/src/node/address.rs b/radicle/src/node/address.rs new file mode 100644 index 00000000..a491c9fd --- /dev/null +++ b/radicle/src/node/address.rs @@ -0,0 +1,51 @@ +mod store; +mod types; + +pub use store::*; +pub use types::*; + +use crate::node::Address; +use cyphernet::addr::HostName; +use std::net; + +/// Address type. +#[repr(u8)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum AddressType { + Ipv4 = 1, + Ipv6 = 2, + Hostname = 3, + Onion = 4, +} + +impl From for u8 { + fn from(other: AddressType) -> Self { + other as u8 + } +} + +impl From<&Address> for AddressType { + fn from(a: &Address) -> Self { + match a.host { + HostName::Ip(net::IpAddr::V4(_)) => AddressType::Ipv4, + HostName::Ip(net::IpAddr::V6(_)) => AddressType::Ipv6, + HostName::Dns(_) => AddressType::Hostname, + HostName::Tor(_) => AddressType::Onion, + _ => todo!(), // FIXME(cloudhead): Maxim will remove `non-exhaustive` + } + } +} + +impl TryFrom for AddressType { + type Error = u8; + + fn try_from(other: u8) -> Result { + match other { + 1 => Ok(AddressType::Ipv4), + 2 => Ok(AddressType::Ipv6), + 3 => Ok(AddressType::Hostname), + 4 => Ok(AddressType::Onion), + _ => Err(other), + } + } +} diff --git a/radicle-node/src/address/schema.sql b/radicle/src/node/address/schema.sql similarity index 100% rename from radicle-node/src/address/schema.sql rename to radicle/src/node/address/schema.sql diff --git a/radicle-node/src/address/store.rs b/radicle/src/node/address/store.rs similarity index 96% rename from radicle-node/src/address/store.rs rename to radicle/src/node/address/store.rs index be7c904f..fd106193 100644 --- a/radicle-node/src/address/store.rs +++ b/radicle/src/node/address/store.rs @@ -1,18 +1,19 @@ use std::path::Path; use std::{fmt, io}; -use radicle::node; -use radicle::node::Address; -use radicle::prelude::Timestamp; -use radicle::sql::transaction; +use localtime::LocalTime; use sqlite as sql; use thiserror::Error; -use crate::address::types; -use crate::address::{KnownAddress, Source}; -use crate::service::NodeId; -use crate::wire::AddressType; -use crate::LocalTime; +use crate::node; +use crate::node::address::{KnownAddress, Source}; +use crate::node::Address; +use crate::node::NodeId; +use crate::prelude::Timestamp; +use crate::sql::transaction; + +use super::types; +use super::AddressType; #[derive(Error, Debug)] pub enum Error { @@ -47,6 +48,15 @@ impl Book { Ok(Self { db }) } + /// Same as [`Self::open`], but in read-only mode. This is useful to have multiple + /// open databases, as no locking is required. + pub fn reader>(path: P) -> Result { + let db = sql::Connection::open_with_flags(path, sqlite::OpenFlags::new().set_read_only())?; + db.execute(Self::SCHEMA)?; + + Ok(Self { db }) + } + /// Create a new in-memory address book. pub fn memory() -> Result { let db = sql::Connection::open(":memory:")?; @@ -341,7 +351,7 @@ mod test { use super::*; use crate::test::arbitrary; - use crate::LocalTime; + use localtime::LocalTime; #[test] fn test_empty() { diff --git a/radicle-node/src/address/types.rs b/radicle/src/node/address/types.rs similarity index 97% rename from radicle-node/src/address/types.rs rename to radicle/src/node/address/types.rs index 3edf819d..0e02f8db 100644 --- a/radicle-node/src/address/types.rs +++ b/radicle/src/node/address/types.rs @@ -1,12 +1,12 @@ use std::ops::{Deref, DerefMut}; +use localtime::LocalTime; use nonempty::NonEmpty; -use radicle::node; -use radicle::node::Address; -use radicle::prelude::Timestamp; use crate::collections::HashMap; -use crate::LocalTime; +use crate::node; +use crate::node::Address; +use crate::prelude::Timestamp; /// A map with the ability to randomly select values. #[derive(Debug, Clone)] diff --git a/radicle/src/profile.rs b/radicle/src/profile.rs index f5ec4600..04c6b06a 100644 --- a/radicle/src/profile.rs +++ b/radicle/src/profile.rs @@ -18,7 +18,8 @@ use thiserror::Error; use crate::crypto::ssh::agent::Agent; use crate::crypto::ssh::{keystore, Keystore, Passphrase}; use crate::crypto::{PublicKey, Signer}; -use crate::node::{self, routing, tracking}; +use crate::node; +use crate::node::{address, routing, tracking}; use crate::prelude::Did; use crate::storage::git::transport; use crate::storage::git::Storage; @@ -143,6 +144,14 @@ impl Profile { Ok(router) } + /// Return a handle to the address database of the node. + pub fn addresses(&self) -> Result { + let path = self.home.node().join(node::ADDRESS_DB_FILE); + let addresses = address::Book::reader(path)?; + + Ok(addresses) + } + /// Return the path to the keys folder. pub fn keys(&self) -> PathBuf { self.home.keys()