From dac22840658d217534a86e01b40957c3d5b5e92f Mon Sep 17 00:00:00 2001 From: nazeh Date: Sun, 28 Jul 2024 12:22:20 +0300 Subject: [PATCH] feat(homeserver): add in memory pkarr relay api for testing --- Cargo.lock | 121 +++++++++++++++++++++++++++ pubky-homeserver/Cargo.toml | 2 + pubky-homeserver/src/main.rs | 27 +++++- pubky-homeserver/src/routes.rs | 9 +- pubky-homeserver/src/routes/pkarr.rs | 69 +++++++++++++++ pubky-homeserver/src/server.rs | 2 + 6 files changed, 227 insertions(+), 3 deletions(-) create mode 100644 pubky-homeserver/src/routes/pkarr.rs diff --git a/Cargo.lock b/Cargo.lock index dbb725b..61051c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,6 +26,55 @@ dependencies = [ "memchr", ] +[[package]] +name = "anstream" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" + +[[package]] +name = "anstyle-parse" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + [[package]] name = "anyhow" version = "1.0.86" @@ -271,12 +320,58 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clap" +version = "4.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35723e6a11662c2afb578bcf0b88bf6ea8e21282a953428f240574fcc3a2b5b3" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49eb96cbfa7cfa35017b7cd548c75b14c3118c98b423041d70562665e07fb0fa" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d029b67f89d30bbb547c89fd5161293c0aec155fc691d7924b64550662db93e" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" + [[package]] name = "cobs" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" +[[package]] +name = "colorchoice" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" + [[package]] name = "console_error_panic_hook" version = "0.1.7" @@ -819,6 +914,12 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "heed" version = "0.20.3" @@ -1019,6 +1120,12 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + [[package]] name = "itoa" version = "1.0.11" @@ -1525,10 +1632,12 @@ dependencies = [ "axum-extra", "base32", "bytes", + "clap", "dirs-next", "flume", "futures-util", "heed", + "once_cell", "pkarr", "postcard", "pubky-common", @@ -2043,6 +2152,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "subtle" version = "2.6.1" @@ -2446,6 +2561,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "valuable" version = "0.1.0" diff --git a/pubky-homeserver/Cargo.toml b/pubky-homeserver/Cargo.toml index da0c5c7..68e30f0 100644 --- a/pubky-homeserver/Cargo.toml +++ b/pubky-homeserver/Cargo.toml @@ -9,10 +9,12 @@ axum = "0.7.5" axum-extra = { version = "0.9.3", features = ["typed-header", "async-read-body"] } base32 = "0.5.1" bytes = "1.6.1" +clap = { version = "4.5.11", features = ["derive"] } dirs-next = "2.0.0" flume = "0.11.0" futures-util = "0.3.30" heed = "0.20.3" +once_cell = "1.19.0" pkarr = { version = "2.1.0", features = ["async"] } postcard = { version = "1.0.8", features = ["alloc"] } pubky-common = { version = "0.1.0", path = "../pubky-common" } diff --git a/pubky-homeserver/src/main.rs b/pubky-homeserver/src/main.rs index a54fba4..0d22194 100644 --- a/pubky-homeserver/src/main.rs +++ b/pubky-homeserver/src/main.rs @@ -1,13 +1,36 @@ use anyhow::Result; +use pkarr::mainline::Testnet; use pubky_homeserver::Homeserver; +use clap::Parser; + +#[derive(Parser, Debug)] +struct Cli { + /// [tracing_subscriber::EnvFilter] + #[clap(short, long)] + tracing_env_filter: Option, + #[clap(long)] + testnet: bool, +} + #[tokio::main] async fn main() -> Result<()> { + let args = Cli::parse(); + tracing_subscriber::fmt() - .with_env_filter("pubky_homeserver=debug,tower_http=debug") + .with_env_filter( + args.tracing_env_filter + .unwrap_or("pubky_homeserver=debug,tower_http=debug".to_string()), + ) .init(); - let server = Homeserver::start(Default::default()).await?; + let server = if args.testnet { + let testnet = Testnet::new(3); + + Homeserver::start_test(&testnet).await? + } else { + Homeserver::start(Default::default()).await? + }; server.run_until_done().await?; diff --git a/pubky-homeserver/src/routes.rs b/pubky-homeserver/src/routes.rs index 3b872c1..e1a4fef 100644 --- a/pubky-homeserver/src/routes.rs +++ b/pubky-homeserver/src/routes.rs @@ -8,11 +8,14 @@ use tower_http::trace::TraceLayer; use crate::server::AppState; +use self::pkarr::pkarr_router; + mod auth; +mod pkarr; mod public; mod root; -pub fn create_app(state: AppState) -> Router { +fn base(state: AppState) -> Router { Router::new() .route("/", get(root::handler)) .route("/:pubky", put(auth::signup)) @@ -28,3 +31,7 @@ pub fn create_app(state: AppState) -> Router { .layer(DefaultBodyLimit::max(16 * 1024)) .with_state(state) } + +pub fn create_app(state: AppState) -> Router { + base(state).merge(pkarr_router()) +} diff --git a/pubky-homeserver/src/routes/pkarr.rs b/pubky-homeserver/src/routes/pkarr.rs new file mode 100644 index 0000000..9c9253b --- /dev/null +++ b/pubky-homeserver/src/routes/pkarr.rs @@ -0,0 +1,69 @@ +use std::{collections::HashMap, sync::RwLock}; + +use axum::{ + body::{Body, Bytes}, + http::StatusCode, + response::IntoResponse, + routing::{get, put}, + Router, +}; +use futures_util::stream::StreamExt; +use once_cell::sync::OnceCell; + +use pkarr::{PublicKey, SignedPacket}; + +use crate::{ + error::{Error, Result}, + extractors::Pubky, +}; + +// TODO: maybe replace after we have local storage of users packets? +static IN_MEMORY: OnceCell>> = OnceCell::new(); + +/// Pkarr relay, helpful for testing. +/// +/// For real productioin, you should use a [production ready +/// relay](https://github.com/pubky/pkarr/server). +pub fn pkarr_router() -> Router { + Router::new() + .route("/pkarr/:pubky", put(pkarr_put)) + .route("/pkarr/:pubky", get(pkarr_get)) +} + +pub async fn pkarr_put(pubky: Pubky, body: Body) -> Result { + let mut bytes = Vec::with_capacity(1104); + + let mut stream = body.into_data_stream(); + + while let Some(chunk) = stream.next().await { + bytes.extend_from_slice(&chunk?) + } + + let public_key = pubky.public_key().to_owned(); + + let signed_packet = SignedPacket::from_relay_payload(&public_key, &Bytes::from(bytes))?; + + let mut store = IN_MEMORY + .get() + .expect("In memory pkarr store is not initialized") + .write() + .unwrap(); + + store.insert(public_key, signed_packet); + + Ok(()) +} + +pub async fn pkarr_get(pubky: Pubky) -> Result { + let store = IN_MEMORY + .get() + .expect("In memory pkarr store is not initialized") + .read() + .unwrap(); + + if let Some(signed_packet) = store.get(pubky.public_key()) { + return Ok(signed_packet.to_relay_payload()); + } + + Err(Error::with_status(StatusCode::NOT_FOUND)) +} diff --git a/pubky-homeserver/src/server.rs b/pubky-homeserver/src/server.rs index 0a2f3ae..7d37baf 100644 --- a/pubky-homeserver/src/server.rs +++ b/pubky-homeserver/src/server.rs @@ -82,6 +82,8 @@ impl Homeserver { /// Test version of [Homeserver::start], using mainline Testnet, and a temporary storage. pub async fn start_test(testnet: &Testnet) -> Result { + info!("Running testnet.."); + Homeserver::start(Config::test(testnet)).await }