mirror of
https://github.com/aljazceru/pubky-core.git
synced 2025-12-31 04:44:37 +01:00
feat(homeserver): use Pkarr Relay in testnet and new Config simplifications
This commit is contained in:
163
Cargo.lock
generated
163
Cargo.lock
generated
@@ -631,6 +631,19 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dashmap"
|
||||
version = "5.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"hashbrown 0.14.5",
|
||||
"lock_api",
|
||||
"once_cell",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.7.9"
|
||||
@@ -834,6 +847,16 @@ dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "forwarded-header-value"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8835f84f38484cc86f110a805655697908257fb9a7af005234060891557198e9"
|
||||
dependencies = [
|
||||
"nonempty",
|
||||
"thiserror 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.31"
|
||||
@@ -918,6 +941,12 @@ version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
|
||||
|
||||
[[package]]
|
||||
name = "futures-timer"
|
||||
version = "3.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.31"
|
||||
@@ -982,6 +1011,26 @@ version = "0.31.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||
|
||||
[[package]]
|
||||
name = "governor"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68a7f542ee6b35af73b06abc0dad1c1bae89964e4e253bc4b587b91c9637867b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"dashmap",
|
||||
"futures",
|
||||
"futures-timer",
|
||||
"no-std-compat",
|
||||
"nonzero_ext",
|
||||
"parking_lot",
|
||||
"portable-atomic",
|
||||
"quanta",
|
||||
"rand",
|
||||
"smallvec",
|
||||
"spinning_top",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.4.6"
|
||||
@@ -1010,6 +1059,12 @@ dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.1"
|
||||
@@ -1404,7 +1459,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
"hashbrown 0.15.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1520,8 +1575,7 @@ checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38"
|
||||
[[package]]
|
||||
name = "mainline"
|
||||
version = "4.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e18c8b0210572062a02c4de8c448865f4ca89824c4ac7da64a0c2669ea2c405"
|
||||
source = "git+https://github.com/pubky/mainline?branch=v5#2948896ac074cd5bf9728966dcd076de35e7e763"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"crc",
|
||||
@@ -1629,6 +1683,24 @@ dependencies = [
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "no-std-compat"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c"
|
||||
|
||||
[[package]]
|
||||
name = "nonempty"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7"
|
||||
|
||||
[[package]]
|
||||
name = "nonzero_ext"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21"
|
||||
|
||||
[[package]]
|
||||
name = "nu-ansi-term"
|
||||
version = "0.46.0"
|
||||
@@ -1849,7 +1921,7 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
[[package]]
|
||||
name = "pkarr"
|
||||
version = "3.0.0"
|
||||
source = "git+https://github.com/Pubky/pkarr?branch=v4#caaf12b437b952cae3e189afc035e35815933eae"
|
||||
source = "git+https://github.com/Pubky/pkarr?branch=v3#c3510a82c5a3a496349d8dc030edd96f750f1471"
|
||||
dependencies = [
|
||||
"base32",
|
||||
"byteorder",
|
||||
@@ -1883,6 +1955,33 @@ dependencies = [
|
||||
"wasm-bindgen-futures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkarr-relay"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/Pubky/pkarr?branch=v3#c3510a82c5a3a496349d8dc030edd96f750f1471"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
"axum-server",
|
||||
"bytes",
|
||||
"clap",
|
||||
"dirs-next",
|
||||
"governor",
|
||||
"http",
|
||||
"httpdate",
|
||||
"pkarr",
|
||||
"pubky-timestamp",
|
||||
"rustls",
|
||||
"serde",
|
||||
"thiserror 2.0.6",
|
||||
"tokio",
|
||||
"toml",
|
||||
"tower-http",
|
||||
"tower_governor",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkcs8"
|
||||
version = "0.10.2"
|
||||
@@ -1910,6 +2009,12 @@ dependencies = [
|
||||
"universal-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6"
|
||||
|
||||
[[package]]
|
||||
name = "postcard"
|
||||
version = "1.1.1"
|
||||
@@ -2015,6 +2120,7 @@ dependencies = [
|
||||
"httpdate",
|
||||
"page_size",
|
||||
"pkarr",
|
||||
"pkarr-relay",
|
||||
"postcard",
|
||||
"pubky-common",
|
||||
"serde",
|
||||
@@ -2053,6 +2159,21 @@ dependencies = [
|
||||
"psl-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quanta"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e5167a477619228a0b284fac2674e3c388cba90631d7b7de620e6f1fcd08da5"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"raw-cpuid",
|
||||
"wasi",
|
||||
"web-sys",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quinn"
|
||||
version = "0.11.6"
|
||||
@@ -2144,6 +2265,15 @@ dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "raw-cpuid"
|
||||
version = "11.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ab240315c661615f2ee9f0f2cd32d5a7343a84d5ebcccb99d46e6637565e7b0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.7"
|
||||
@@ -2634,6 +2764,15 @@ dependencies = [
|
||||
"lock_api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spinning_top"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spki"
|
||||
version = "0.7.3"
|
||||
@@ -3021,6 +3160,22 @@ version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
|
||||
|
||||
[[package]]
|
||||
name = "tower_governor"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aea939ea6cfa7c4880f3e7422616624f97a567c16df67b53b11f0d03917a8e46"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"forwarded-header-value",
|
||||
"governor",
|
||||
"http",
|
||||
"pin-project",
|
||||
"thiserror 1.0.69",
|
||||
"tower 0.5.1",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.41"
|
||||
|
||||
@@ -10,7 +10,7 @@ members = [
|
||||
resolver = "2"
|
||||
|
||||
[workspace.dependencies]
|
||||
pkarr = { git = "https://github.com/Pubky/pkarr", branch = "v4", package = "pkarr" }
|
||||
pkarr = { git = "https://github.com/Pubky/pkarr", branch = "v3", package = "pkarr" }
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
|
||||
@@ -16,13 +16,13 @@ name = "request"
|
||||
path = "./request/main.rs"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.86"
|
||||
anyhow = "1.0.94"
|
||||
base64 = "0.22.1"
|
||||
clap = { version = "4.5.16", features = ["derive"] }
|
||||
clap = { version = "4.5.23", features = ["derive"] }
|
||||
pubky = { path = "../pubky" }
|
||||
pubky-common = { version = "0.1.0", path = "../pubky-common" }
|
||||
reqwest = "0.12.8"
|
||||
reqwest = "0.12.9"
|
||||
rpassword = "7.3.1"
|
||||
tokio = { version = "1.40.0", features = ["macros", "rt-multi-thread"] }
|
||||
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
||||
url = "2.5.2"
|
||||
tokio = { version = "1.42.0", features = ["macros", "rt-multi-thread"] }
|
||||
tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }
|
||||
url = "2.5.4"
|
||||
|
||||
@@ -31,3 +31,4 @@ axum-server = { version = "0.7.1", features = ["tls-rustls-no-provider"] }
|
||||
tower = "0.5.1"
|
||||
page_size = "0.6.0"
|
||||
|
||||
pkarr-relay = { git = "https://github.com/Pubky/pkarr", branch = "v3", package = "pkarr-relay" }
|
||||
|
||||
@@ -23,3 +23,11 @@ Run with an optional config file
|
||||
```bash
|
||||
../target/release/pubky-homeserver --config=./src/config.toml
|
||||
```
|
||||
|
||||
## Testnet
|
||||
|
||||
To run a local homeserver for testing with an internal Pkarr Relay, hardcoded well known publickey and only connected to local Mainline testnet:
|
||||
|
||||
```bash
|
||||
cargo run -- --testnet
|
||||
```
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# Use testnet network (local DHT) for testing.
|
||||
# testnet = false
|
||||
|
||||
# Secret key (in hex) to generate the Homeserver's Keypair
|
||||
# secret_key = "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
|
||||
|
||||
@@ -8,9 +8,6 @@ use std::{
|
||||
path::{Path, PathBuf},
|
||||
time::Duration,
|
||||
};
|
||||
use tracing::info;
|
||||
|
||||
use pubky_common::timestamp::Timestamp;
|
||||
|
||||
// === Database ===
|
||||
const DEFAULT_STORAGE_DIR: &str = "pubky";
|
||||
@@ -22,7 +19,6 @@ pub const DEFAULT_MAX_LIST_LIMIT: u16 = 1000;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq)]
|
||||
struct ConfigToml {
|
||||
testnet: Option<bool>,
|
||||
port: Option<u16>,
|
||||
bootstrap: Option<Vec<String>>,
|
||||
domain: Option<String>,
|
||||
@@ -37,90 +33,42 @@ struct ConfigToml {
|
||||
/// Server configuration
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Config {
|
||||
/// Whether or not this server is running in a testnet.
|
||||
testnet: bool,
|
||||
/// The configured port for this server.
|
||||
port: u16,
|
||||
pub port: u16,
|
||||
/// Bootstrapping DHT nodes.
|
||||
///
|
||||
/// Helpful to run the server locally or in testnet.
|
||||
bootstrap: Option<Vec<String>>,
|
||||
pub bootstrap: Option<Vec<String>>,
|
||||
/// A public domain for this server
|
||||
/// necessary for web browsers running in https environment.
|
||||
domain: Option<String>,
|
||||
pub domain: Option<String>,
|
||||
/// Path to the storage directory.
|
||||
///
|
||||
/// Defaults to a directory in the OS data directory
|
||||
storage: PathBuf,
|
||||
pub storage: PathBuf,
|
||||
/// Server keypair.
|
||||
///
|
||||
/// Defaults to a random keypair.
|
||||
keypair: Keypair,
|
||||
dht_request_timeout: Option<Duration>,
|
||||
pub keypair: Keypair,
|
||||
pub dht_request_timeout: Option<Duration>,
|
||||
/// The default limit of a list api if no `limit` query parameter is provided.
|
||||
///
|
||||
/// Defaults to `100`
|
||||
default_list_limit: u16,
|
||||
pub default_list_limit: u16,
|
||||
/// The maximum limit of a list api, even if a `limit` query parameter is provided.
|
||||
///
|
||||
/// Defaults to `1000`
|
||||
max_list_limit: u16,
|
||||
pub max_list_limit: u16,
|
||||
|
||||
// === Database params ===
|
||||
db_map_size: usize,
|
||||
pub db_map_size: usize,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
fn try_from_str(value: &str) -> Result<Self> {
|
||||
let config_toml: ConfigToml = toml::from_str(value)?;
|
||||
|
||||
let keypair = if let Some(secret_key) = config_toml.secret_key {
|
||||
let secret_key = deserialize_secret_key(secret_key)?;
|
||||
Keypair::from_secret_key(&secret_key)
|
||||
} else {
|
||||
Keypair::random()
|
||||
};
|
||||
|
||||
let storage = {
|
||||
let dir = if let Some(storage) = config_toml.storage {
|
||||
storage
|
||||
} else {
|
||||
let path = dirs_next::data_dir().ok_or_else(|| {
|
||||
anyhow!("operating environment provides no directory for application data")
|
||||
})?;
|
||||
path.join(DEFAULT_STORAGE_DIR)
|
||||
};
|
||||
|
||||
dir.join("homeserver")
|
||||
};
|
||||
|
||||
let config = Config {
|
||||
testnet: config_toml.testnet.unwrap_or(false),
|
||||
port: config_toml.port.unwrap_or(0),
|
||||
bootstrap: config_toml.bootstrap,
|
||||
domain: config_toml.domain,
|
||||
keypair,
|
||||
storage,
|
||||
dht_request_timeout: config_toml.dht_request_timeout,
|
||||
default_list_limit: config_toml.default_list_limit.unwrap_or(DEFAULT_LIST_LIMIT),
|
||||
max_list_limit: config_toml
|
||||
.default_list_limit
|
||||
.unwrap_or(DEFAULT_MAX_LIST_LIMIT),
|
||||
db_map_size: config_toml.db_map_size.unwrap_or(DEFAULT_MAP_SIZE),
|
||||
};
|
||||
|
||||
if config.testnet {
|
||||
let testnet_config = Config::testnet();
|
||||
|
||||
return Ok(Config {
|
||||
bootstrap: testnet_config.bootstrap,
|
||||
port: testnet_config.port,
|
||||
keypair: testnet_config.keypair,
|
||||
..config
|
||||
});
|
||||
}
|
||||
|
||||
Ok(config)
|
||||
config_toml.try_into()
|
||||
}
|
||||
|
||||
/// Load the config from a file.
|
||||
@@ -132,82 +80,25 @@ impl Config {
|
||||
Config::try_from_str(&s)
|
||||
}
|
||||
|
||||
/// Testnet configurations
|
||||
pub fn testnet() -> Self {
|
||||
let testnet = pkarr::mainline::Testnet::new(10).unwrap();
|
||||
info!(?testnet.bootstrap, "Testnet bootstrap nodes");
|
||||
|
||||
Config {
|
||||
port: 15411,
|
||||
dht_request_timeout: None,
|
||||
db_map_size: DEFAULT_MAP_SIZE,
|
||||
keypair: Keypair::from_secret_key(&[0; 32]),
|
||||
..Self::test(&testnet)
|
||||
}
|
||||
}
|
||||
|
||||
/// Test configurations
|
||||
pub fn test(testnet: &pkarr::mainline::Testnet) -> Self {
|
||||
let bootstrap = Some(testnet.bootstrap.to_owned());
|
||||
let storage = std::env::temp_dir()
|
||||
.join(Timestamp::now().to_string())
|
||||
.join(pubky_common::timestamp::Timestamp::now().to_string())
|
||||
.join(DEFAULT_STORAGE_DIR);
|
||||
|
||||
Self {
|
||||
testnet: true,
|
||||
bootstrap,
|
||||
storage,
|
||||
db_map_size: 10485760,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_testnet(&self) -> bool {
|
||||
self.testnet
|
||||
}
|
||||
|
||||
pub fn port(&self) -> u16 {
|
||||
self.port
|
||||
}
|
||||
|
||||
pub fn bootstrap(&self) -> Option<Vec<String>> {
|
||||
self.bootstrap.to_owned()
|
||||
}
|
||||
|
||||
pub fn domain(&self) -> Option<&String> {
|
||||
self.domain.as_ref()
|
||||
}
|
||||
|
||||
pub fn keypair(&self) -> &Keypair {
|
||||
&self.keypair
|
||||
}
|
||||
|
||||
pub fn default_list_limit(&self) -> u16 {
|
||||
self.default_list_limit
|
||||
}
|
||||
|
||||
pub fn max_list_limit(&self) -> u16 {
|
||||
self.max_list_limit
|
||||
}
|
||||
|
||||
/// Get the path to the storage directory
|
||||
pub fn storage(&self) -> &PathBuf {
|
||||
&self.storage
|
||||
}
|
||||
|
||||
pub(crate) fn dht_request_timeout(&self) -> Option<Duration> {
|
||||
self.dht_request_timeout
|
||||
}
|
||||
|
||||
pub(crate) fn db_map_size(&self) -> usize {
|
||||
self.db_map_size
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
testnet: false,
|
||||
port: 0,
|
||||
bootstrap: None,
|
||||
domain: None,
|
||||
@@ -222,6 +113,44 @@ impl Default for Config {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<ConfigToml> for Config {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(value: ConfigToml) -> std::result::Result<Self, Self::Error> {
|
||||
let keypair = if let Some(secret_key) = value.secret_key {
|
||||
let secret_key = deserialize_secret_key(secret_key)?;
|
||||
Keypair::from_secret_key(&secret_key)
|
||||
} else {
|
||||
Keypair::random()
|
||||
};
|
||||
|
||||
let storage = {
|
||||
let dir = if let Some(storage) = value.storage {
|
||||
storage
|
||||
} else {
|
||||
let path = dirs_next::data_dir().ok_or_else(|| {
|
||||
anyhow!("operating environment provides no directory for application data")
|
||||
})?;
|
||||
path.join(DEFAULT_STORAGE_DIR)
|
||||
};
|
||||
|
||||
dir.join("homeserver")
|
||||
};
|
||||
|
||||
Ok(Config {
|
||||
port: value.port.unwrap_or(0),
|
||||
bootstrap: value.bootstrap,
|
||||
domain: value.domain,
|
||||
keypair,
|
||||
storage,
|
||||
dht_request_timeout: value.dht_request_timeout,
|
||||
default_list_limit: value.default_list_limit.unwrap_or(DEFAULT_LIST_LIMIT),
|
||||
max_list_limit: value.default_list_limit.unwrap_or(DEFAULT_MAX_LIST_LIMIT),
|
||||
db_map_size: value.db_map_size.unwrap_or(DEFAULT_MAP_SIZE),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_secret_key(s: String) -> anyhow::Result<[u8; 32]> {
|
||||
let bytes =
|
||||
hex::decode(s).map_err(|_| anyhow!("secret_key in config.toml should hex encoded"))?;
|
||||
@@ -279,7 +208,6 @@ mod tests {
|
||||
assert_eq!(
|
||||
config,
|
||||
Config {
|
||||
testnet: true,
|
||||
bootstrap: testnet.bootstrap.into(),
|
||||
db_map_size: 10485760,
|
||||
|
||||
@@ -291,36 +219,17 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn config_testnet() {
|
||||
let config = Config::testnet();
|
||||
|
||||
assert_eq!(
|
||||
config,
|
||||
Config {
|
||||
testnet: true,
|
||||
port: 15411,
|
||||
|
||||
bootstrap: config.bootstrap.clone(),
|
||||
storage: config.storage.clone(),
|
||||
keypair: config.keypair.clone(),
|
||||
..Default::default()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_with_testnet_flag() {
|
||||
fn parse() {
|
||||
let config = Config::try_from_str(
|
||||
r#"
|
||||
# Secret key (in hex) to generate the Homeserver's Keypair
|
||||
secret_key = "0123000000000000000000000000000000000000000000000000000000000000"
|
||||
secret_key = "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
# Domain to be published in Pkarr records for this server to be accessible by.
|
||||
domain = "localhost"
|
||||
# Port for the Homeserver to listen on.
|
||||
port = 6287
|
||||
# Storage directory Defaults to <System's Data Directory>
|
||||
storage = "/homeserver"
|
||||
testnet = true
|
||||
|
||||
bootstrap = ["foo", "bar"]
|
||||
|
||||
@@ -332,8 +241,8 @@ mod tests {
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(config.keypair, Keypair::from_secret_key(&[0; 32]));
|
||||
assert_eq!(config.port, 15411);
|
||||
assert_ne!(
|
||||
assert_eq!(config.port, 6287);
|
||||
assert_eq!(
|
||||
config.bootstrap,
|
||||
Some(vec!["foo".to_string(), "bar".to_string()])
|
||||
);
|
||||
|
||||
@@ -11,43 +11,57 @@ use crate::core::config::Config;
|
||||
|
||||
use tables::{Tables, TABLES_COUNT};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DB {
|
||||
pub(crate) env: Env,
|
||||
pub(crate) tables: Tables,
|
||||
pub(crate) config: Config,
|
||||
pub(crate) buffers_dir: PathBuf,
|
||||
pub(crate) max_chunk_size: usize,
|
||||
}
|
||||
pub use protected::DB;
|
||||
|
||||
impl DB {
|
||||
/// # Safety
|
||||
/// Opening [LMDB][heed::EnvOpenOptions::open] is backed by a memory map which comes with some safety precautions.
|
||||
pub unsafe fn open(config: Config) -> anyhow::Result<Self> {
|
||||
let buffers_dir = config.storage().clone().join("buffers");
|
||||
/// Protecting fields from being mutated by modules in crate::database
|
||||
mod protected {
|
||||
use super::*;
|
||||
|
||||
// Cleanup buffers.
|
||||
let _ = fs::remove_dir(&buffers_dir);
|
||||
fs::create_dir_all(&buffers_dir)?;
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DB {
|
||||
pub(crate) env: Env,
|
||||
pub(crate) tables: Tables,
|
||||
pub(crate) buffers_dir: PathBuf,
|
||||
pub(crate) max_chunk_size: usize,
|
||||
config: Config,
|
||||
}
|
||||
|
||||
let env = unsafe {
|
||||
EnvOpenOptions::new()
|
||||
.max_dbs(TABLES_COUNT)
|
||||
.map_size(config.db_map_size())
|
||||
.open(config.storage())
|
||||
}?;
|
||||
impl DB {
|
||||
/// # Safety
|
||||
/// DB uses LMDB, [opening][heed::EnvOpenOptions::open] which is marked unsafe,
|
||||
/// because the possible Undefined Behavior (UB) if the lock file is broken.
|
||||
pub unsafe fn open(config: Config) -> anyhow::Result<Self> {
|
||||
let buffers_dir = config.storage.clone().join("buffers");
|
||||
|
||||
let tables = migrations::run(&env)?;
|
||||
// Cleanup buffers.
|
||||
let _ = fs::remove_dir(&buffers_dir);
|
||||
fs::create_dir_all(&buffers_dir)?;
|
||||
|
||||
let db = DB {
|
||||
env,
|
||||
tables,
|
||||
config,
|
||||
buffers_dir,
|
||||
max_chunk_size: max_chunk_size(),
|
||||
};
|
||||
let env = unsafe {
|
||||
EnvOpenOptions::new()
|
||||
.max_dbs(TABLES_COUNT)
|
||||
.map_size(config.db_map_size)
|
||||
.open(&config.storage)
|
||||
}?;
|
||||
|
||||
Ok(db)
|
||||
let tables = migrations::run(&env)?;
|
||||
|
||||
let db = DB {
|
||||
env,
|
||||
tables,
|
||||
config,
|
||||
buffers_dir,
|
||||
max_chunk_size: max_chunk_size(),
|
||||
};
|
||||
|
||||
Ok(db)
|
||||
}
|
||||
|
||||
// === Getters ===
|
||||
|
||||
pub fn config(&self) -> &Config {
|
||||
&self.config
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +69,7 @@ impl DB {
|
||||
/// - https://lmdb.readthedocs.io/en/release/#storage-efficiency-limits
|
||||
/// - https://github.com/lmdbjava/benchmarks/blob/master/results/20160710/README.md#test-2-determine-24816-kb-byte-values
|
||||
fn max_chunk_size() -> usize {
|
||||
let page_size = unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize };
|
||||
let page_size = page_size::get();
|
||||
|
||||
// - 16 bytes Header per page (LMDB)
|
||||
// - Each page has to contain 2 records
|
||||
|
||||
@@ -107,7 +107,7 @@ impl DB {
|
||||
|
||||
/// Return a list of pubky urls.
|
||||
///
|
||||
/// - limit defaults to [Config::default_list_limit] and capped by [Config::max_list_limit]
|
||||
/// - limit defaults to [crate::Config::default_list_limit] and capped by [crate::Config::max_list_limit]
|
||||
pub fn list(
|
||||
&self,
|
||||
txn: &RoTxn,
|
||||
@@ -121,8 +121,8 @@ impl DB {
|
||||
let mut results = Vec::new();
|
||||
|
||||
let limit = limit
|
||||
.unwrap_or(self.config.default_list_limit())
|
||||
.min(self.config.max_list_limit());
|
||||
.unwrap_or(self.config().default_list_limit)
|
||||
.min(self.config().max_list_limit);
|
||||
|
||||
// TODO: make this more performant than split and allocations?
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ impl Event {
|
||||
impl DB {
|
||||
/// Returns a list of events formatted as `<OP> <url>`.
|
||||
///
|
||||
/// - limit defaults to [Config::default_list_limit] and capped by [Config::max_list_limit]
|
||||
/// - limit defaults to [crate::Config::default_list_limit] and capped by [crate::Config::max_list_limit]
|
||||
/// - cursor is a 13 character string encoding of a timestamp
|
||||
pub fn list_events(
|
||||
&self,
|
||||
@@ -72,8 +72,8 @@ impl DB {
|
||||
let txn = self.env.read_txn()?;
|
||||
|
||||
let limit = limit
|
||||
.unwrap_or(self.config.default_list_limit())
|
||||
.min(self.config.max_list_limit());
|
||||
.unwrap_or(self.config().default_list_limit)
|
||||
.min(self.config().max_list_limit);
|
||||
|
||||
let cursor = cursor.unwrap_or("0000000000000".to_string());
|
||||
|
||||
|
||||
@@ -78,8 +78,8 @@ impl From<pubky_common::auth::Error> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<pkarr::errors::SignedPacketError> for Error {
|
||||
fn from(error: pkarr::errors::SignedPacketError) -> Self {
|
||||
impl From<pkarr::errors::SignedPacketVerifyError> for Error {
|
||||
fn from(error: pkarr::errors::SignedPacketVerifyError) -> Self {
|
||||
Self::new(StatusCode::BAD_REQUEST, Some(error))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,16 +25,19 @@ pub(crate) struct AppState {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
/// An I/O-less Core of the [Homeserver].
|
||||
/// A side-effect-free Core of the [Homeserver].
|
||||
pub struct HomeserverCore {
|
||||
pub(crate) config: Config,
|
||||
config: Config,
|
||||
pub(crate) state: AppState,
|
||||
pub(crate) router: Router,
|
||||
}
|
||||
|
||||
impl HomeserverCore {
|
||||
/// Create a side-effect-free Homeserver core.
|
||||
///
|
||||
/// # Safety
|
||||
/// HomeserverCore uses LMDB, [opening][heed::EnvOpenOptions::open] which comes with some safety precautions.
|
||||
/// HomeserverCore uses LMDB, [opening][heed::EnvOpenOptions::open] which is marked unsafe,
|
||||
/// because the possible Undefined Behavior (UB) if the lock file is broken.
|
||||
pub unsafe fn new(config: &Config) -> Result<Self> {
|
||||
let db = unsafe { DB::open(config.clone())? };
|
||||
|
||||
@@ -62,12 +65,16 @@ impl HomeserverCore {
|
||||
|
||||
// === Getters ===
|
||||
|
||||
pub fn config(&self) -> &Config {
|
||||
&self.config
|
||||
}
|
||||
|
||||
pub fn keypair(&self) -> &Keypair {
|
||||
self.config.keypair()
|
||||
&self.config.keypair
|
||||
}
|
||||
|
||||
pub fn public_key(&self) -> PublicKey {
|
||||
self.config.keypair().public_key()
|
||||
self.config.keypair.public_key()
|
||||
}
|
||||
|
||||
// === Public Methods ===
|
||||
|
||||
@@ -10,6 +10,7 @@ use axum_server::{
|
||||
tls_rustls::{RustlsAcceptor, RustlsConfig},
|
||||
Handle,
|
||||
};
|
||||
use futures_util::TryFutureExt;
|
||||
|
||||
use crate::core::HomeserverCore;
|
||||
|
||||
@@ -38,11 +39,12 @@ impl HttpServers {
|
||||
core.router
|
||||
.clone()
|
||||
.into_make_service_with_connect_info::<SocketAddr>(),
|
||||
),
|
||||
)
|
||||
.map_err(|error| tracing::error!(?error, "Homeserver http server error")),
|
||||
);
|
||||
|
||||
let https_listener =
|
||||
TcpListener::bind(SocketAddr::from(([0, 0, 0, 0], core.config.port())))?;
|
||||
TcpListener::bind(SocketAddr::from(([0, 0, 0, 0], core.config().port)))?;
|
||||
|
||||
let https_handle = Handle::new();
|
||||
|
||||
@@ -56,7 +58,8 @@ impl HttpServers {
|
||||
core.router
|
||||
.clone()
|
||||
.into_make_service_with_connect_info::<SocketAddr>(),
|
||||
),
|
||||
)
|
||||
.map_err(|error| tracing::error!(?error, "Homeserver https server error")),
|
||||
);
|
||||
|
||||
// let mock_pkarr_relay_listener = TcpListener::bind(SocketAddr::from(([0, 0, 0, 0], 15411)))?;
|
||||
@@ -81,6 +84,7 @@ impl HttpServers {
|
||||
}
|
||||
}
|
||||
|
||||
/// Shutdown all HTTP servers.
|
||||
pub fn shutdown(&self) {
|
||||
self.http_handle.shutdown();
|
||||
self.https_handle.shutdown();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use ::pkarr::{mainline::Testnet, PublicKey};
|
||||
use ::pkarr::{Keypair, PublicKey};
|
||||
use anyhow::Result;
|
||||
use http::HttpServers;
|
||||
use pkarr::PkarrServer;
|
||||
@@ -9,6 +9,34 @@ use crate::{Config, HomeserverCore};
|
||||
mod http;
|
||||
mod pkarr;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct HomeserverBuilder(Config);
|
||||
|
||||
impl HomeserverBuilder {
|
||||
/// Configure the Homeserver's keypair
|
||||
pub fn keypair(mut self, keypair: Keypair) -> Self {
|
||||
self.0.keypair = keypair;
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Configure the Mainline DHT bootstrap nodes. Useful for testnet configurations.
|
||||
pub fn bootstrap(mut self, bootstrap: Vec<String>) -> Self {
|
||||
self.0.bootstrap = Some(bootstrap);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Start running a Homeserver
|
||||
///
|
||||
/// # Safety
|
||||
/// Homeserver uses LMDB, [opening][heed::EnvOpenOptions::open] which is marked unsafe,
|
||||
/// because the possible Undefined Behavior (UB) if the lock file is broken.
|
||||
pub async unsafe fn build(self) -> Result<Homeserver> {
|
||||
Homeserver::start(self.0).await
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
/// Homeserver [Core][HomeserverCore] + I/O (http server and pkarr publishing).
|
||||
pub struct Homeserver {
|
||||
@@ -17,8 +45,15 @@ pub struct Homeserver {
|
||||
}
|
||||
|
||||
impl Homeserver {
|
||||
pub fn builder() -> HomeserverBuilder {
|
||||
HomeserverBuilder::default()
|
||||
}
|
||||
|
||||
/// Start running a Homeserver
|
||||
///
|
||||
/// # Safety
|
||||
/// Homeserver uses LMDB, [opening][heed::EnvOpenOptions::open] which comes with some safety precautions.
|
||||
/// Homeserver uses LMDB, [opening][heed::EnvOpenOptions::open] which is marked unsafe,
|
||||
/// because the possible Undefined Behavior (UB) if the lock file is broken.
|
||||
pub async unsafe fn start(config: Config) -> Result<Self> {
|
||||
tracing::debug!(?config, "Starting homeserver with configurations");
|
||||
|
||||
@@ -33,20 +68,47 @@ impl Homeserver {
|
||||
|
||||
info!("Publishing Pkarr packet..");
|
||||
|
||||
let pkarr_server = PkarrServer::new(config)?;
|
||||
pkarr_server
|
||||
.publish_server_packet(http_servers.https_address().await?.port())
|
||||
.await?;
|
||||
let pkarr_server = PkarrServer::new(config, http_servers.https_address().await?.port())?;
|
||||
pkarr_server.publish_server_packet().await?;
|
||||
|
||||
info!("Homeserver listening on https://{}", core.public_key());
|
||||
|
||||
Ok(Self { http_servers, core })
|
||||
}
|
||||
|
||||
/// Test version of [Homeserver::start], using mainline Testnet, and a temporary storage.
|
||||
pub async fn start_test(testnet: &Testnet) -> Result<Self> {
|
||||
info!("Running testnet..");
|
||||
/// Start a homeserver in a Testnet mode.
|
||||
///
|
||||
/// - Homeserver address is hardcoded to ``
|
||||
/// - Run a pkarr Relay on port `15411`
|
||||
///
|
||||
/// # Safety
|
||||
/// See [Self::start]
|
||||
pub async unsafe fn start_testnet() -> Result<Self> {
|
||||
let testnet = ::pkarr::mainline::Testnet::new(10)?;
|
||||
|
||||
let relay = unsafe {
|
||||
let mut config = pkarr_relay::Config {
|
||||
http_port: 15411,
|
||||
..Default::default()
|
||||
};
|
||||
config.pkarr_config.dht_config.bootstrap = testnet.bootstrap.clone();
|
||||
|
||||
pkarr_relay::Relay::start(config).await?
|
||||
};
|
||||
|
||||
tracing::info!(relay_address=?relay.relay_address(), bootstrap=?relay.resolver_address(),"Running in Testnet mode");
|
||||
|
||||
unsafe {
|
||||
Homeserver::builder()
|
||||
.keypair(Keypair::from_secret_key(&[0; 32]))
|
||||
.bootstrap(testnet.bootstrap)
|
||||
.build()
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
/// Test version of [Homeserver::start], using mainline Testnet, and a temporary storage.
|
||||
pub async fn start_test(testnet: &::pkarr::mainline::Testnet) -> Result<Self> {
|
||||
unsafe { Homeserver::start(Config::test(testnet)).await }
|
||||
}
|
||||
|
||||
|
||||
@@ -7,60 +7,68 @@ use crate::Config;
|
||||
|
||||
pub struct PkarrServer {
|
||||
client: pkarr::Client,
|
||||
config: Config,
|
||||
signed_packet: SignedPacket,
|
||||
}
|
||||
|
||||
impl PkarrServer {
|
||||
pub fn new(config: Config) -> Result<Self> {
|
||||
let mut dht_settings = pkarr::mainline::Settings::default();
|
||||
pub fn new(config: Config, port: u16) -> Result<Self> {
|
||||
let mut dht_config = pkarr::mainline::Config::default();
|
||||
|
||||
if let Some(bootstrap) = config.bootstrap() {
|
||||
dht_settings = dht_settings.bootstrap(&bootstrap);
|
||||
if let Some(bootstrap) = config.bootstrap.clone() {
|
||||
dht_config.bootstrap = bootstrap;
|
||||
}
|
||||
if let Some(request_timeout) = config.dht_request_timeout() {
|
||||
dht_settings = dht_settings.request_timeout(request_timeout);
|
||||
if let Some(request_timeout) = config.dht_request_timeout {
|
||||
dht_config.request_timeout = request_timeout;
|
||||
}
|
||||
|
||||
let client = pkarr::Client::builder()
|
||||
.dht_settings(dht_settings)
|
||||
.build()?;
|
||||
let client = pkarr::Client::builder().dht_config(dht_config).build()?;
|
||||
|
||||
Ok(Self { client, config })
|
||||
let signed_packet = create_signed_packet(config, port)?;
|
||||
|
||||
Ok(Self {
|
||||
client,
|
||||
signed_packet,
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn publish_server_packet(&self, port: u16) -> anyhow::Result<()> {
|
||||
// TODO: Try to resolve first before publishing.
|
||||
pub async fn publish_server_packet(&self) -> anyhow::Result<()> {
|
||||
// TODO: warn if packet is not most recent, which means the
|
||||
// user is publishing a Packet from somewhere else.
|
||||
|
||||
let default = ".".to_string();
|
||||
let target = self.config.domain().unwrap_or(&default);
|
||||
let mut svcb = SVCB::new(0, target.as_str().try_into()?);
|
||||
|
||||
svcb.priority = 1;
|
||||
svcb.set_port(port);
|
||||
|
||||
let mut signed_packet_builder =
|
||||
SignedPacket::builder().https(".".try_into().unwrap(), svcb.clone(), 60 * 60);
|
||||
|
||||
if self.config.domain().is_none() {
|
||||
// TODO: remove after remvoing Pubky shared/public
|
||||
// and add local host IP address instead.
|
||||
svcb.target = "localhost".try_into().unwrap();
|
||||
|
||||
signed_packet_builder = signed_packet_builder
|
||||
.https(".".try_into().unwrap(), svcb, 60 * 60)
|
||||
.address(
|
||||
".".try_into().unwrap(),
|
||||
"127.0.0.1".parse().unwrap(),
|
||||
60 * 60,
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: announce A/AAAA records as well for TLS connections?
|
||||
|
||||
let signed_packet = signed_packet_builder.build(self.config.keypair())?;
|
||||
|
||||
self.client.publish(&signed_packet).await?;
|
||||
self.client.publish(&self.signed_packet).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_signed_packet(config: Config, port: u16) -> Result<SignedPacket> {
|
||||
// TODO: Try to resolve first before publishing.
|
||||
|
||||
let default = ".".to_string();
|
||||
let target = config.domain.clone().unwrap_or(default);
|
||||
let mut svcb = SVCB::new(0, target.as_str().try_into()?);
|
||||
|
||||
svcb.priority = 1;
|
||||
svcb.set_port(port);
|
||||
|
||||
let mut signed_packet_builder =
|
||||
SignedPacket::builder().https(".".try_into().unwrap(), svcb.clone(), 60 * 60);
|
||||
|
||||
if config.domain.is_none() {
|
||||
// TODO: remove after remvoing Pubky shared/public
|
||||
// and add local host IP address instead.
|
||||
svcb.target = "localhost".try_into().unwrap();
|
||||
|
||||
signed_packet_builder = signed_packet_builder
|
||||
.https(".".try_into().unwrap(), svcb, 60 * 60)
|
||||
.address(
|
||||
".".try_into().unwrap(),
|
||||
"127.0.0.1".parse().unwrap(),
|
||||
60 * 60,
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: announce A/AAAA records as well for TLS connections?
|
||||
|
||||
Ok(signed_packet_builder.build(&config.keypair)?)
|
||||
}
|
||||
|
||||
@@ -32,14 +32,13 @@ async fn main() -> Result<()> {
|
||||
.init();
|
||||
|
||||
let server = unsafe {
|
||||
Homeserver::start(if args.testnet {
|
||||
Config::testnet()
|
||||
if args.testnet {
|
||||
Homeserver::start_testnet().await?
|
||||
} else if let Some(config_path) = args.config {
|
||||
Config::load(config_path).await?
|
||||
Homeserver::start(Config::load(config_path).await?).await?
|
||||
} else {
|
||||
Config::default()
|
||||
})
|
||||
.await?
|
||||
Homeserver::builder().build().await?
|
||||
}
|
||||
};
|
||||
|
||||
tokio::signal::ctrl_c().await?;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"url": "git+https://github.com/pubky/pubky-core.git"
|
||||
},
|
||||
"scripts": {
|
||||
"testnet": "cargo run -p pubky_homeserver -- --testnet",
|
||||
"testnet": "cargo run -p pubky-homeserver -- --testnet",
|
||||
"test": "npm run test-nodejs && npm run test-browser",
|
||||
"test-nodejs": "tape test/*.js -cov",
|
||||
"test-browser": "browserify test/*.js -p esmify | npx tape-run",
|
||||
|
||||
@@ -6,7 +6,7 @@ const TLD = '8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo';
|
||||
|
||||
// TODO: test HTTPs too somehow.
|
||||
|
||||
test.skip("basic fetch", async (t) => {
|
||||
test.only("basic fetch", async (t) => {
|
||||
let client = Client.testnet();
|
||||
|
||||
// Normal TLD
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::{sync::Arc, time::Duration};
|
||||
use std::{net::ToSocketAddrs, sync::Arc, time::Duration};
|
||||
|
||||
use pkarr::mainline::Testnet;
|
||||
|
||||
@@ -15,13 +15,14 @@ static DEFAULT_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CAR
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Settings {
|
||||
pkarr_settings: pkarr::Settings,
|
||||
pkarr_config: pkarr::Config,
|
||||
}
|
||||
|
||||
impl Settings {
|
||||
/// Set Pkarr client [pkarr::Settings].
|
||||
pub fn pkarr_settings(mut self, settings: pkarr::Settings) -> Self {
|
||||
self.pkarr_settings = settings;
|
||||
pub fn pkarr_config(mut self, settings: pkarr::Config) -> Self {
|
||||
self.pkarr_config = settings;
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
@@ -32,23 +33,26 @@ impl Settings {
|
||||
pub fn testnet(mut self, testnet: &Testnet) -> Self {
|
||||
let bootstrap = testnet.bootstrap.clone();
|
||||
|
||||
let mut dht_settings = pkarr::mainline::Settings::default().bootstrap(&bootstrap);
|
||||
self.pkarr_config.resolvers = Some(
|
||||
bootstrap
|
||||
.iter()
|
||||
.flat_map(|resolver| resolver.to_socket_addrs())
|
||||
.flatten()
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
self.pkarr_config.dht_config.bootstrap = bootstrap;
|
||||
|
||||
if std::env::var("CI").is_err() {
|
||||
dht_settings = dht_settings.request_timeout(Duration::from_millis(500));
|
||||
self.pkarr_config.dht_config.request_timeout = Duration::from_millis(500);
|
||||
}
|
||||
|
||||
self.pkarr_settings = self
|
||||
.pkarr_settings
|
||||
.dht_settings(dht_settings)
|
||||
.resolvers(Some(bootstrap));
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Build [Client]
|
||||
pub fn build(self) -> Result<Client, std::io::Error> {
|
||||
let pkarr = pkarr::Client::new(self.pkarr_settings)?;
|
||||
let pkarr = pkarr::Client::new(self.pkarr_config)?;
|
||||
|
||||
let cookie_store = Arc::new(CookieJar::default());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user