diff --git a/Cargo.lock b/Cargo.lock index 5395ee416cca..206579f46692 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8372,9 +8372,9 @@ dependencies = [ [[package]] name = "quic-rpc" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77b3ae032988c83ac7ce072be3c2605e90671e8830a34d6ebf24095add68b4d5" +checksum = "7b0ea1bd0b3124538bb71ed8cedbe92608fd1cf227e4f5ff53fb28746737b794" dependencies = [ "anyhow", "bincode 1.3.3", @@ -9550,7 +9550,7 @@ dependencies = [ [[package]] name = "sd-cloud-schema" version = "0.1.0" -source = "git+https://github.com/spacedriveapp/cloud-services-schema?rev=bbc69c5cb2#bbc69c5cb294ab19d18e640995eefd4a5201afb2" +source = "git+https://github.com/spacedriveapp/cloud-services-schema?rev=99d59e8fab#99d59e8fab398d065f1b2d3fd393f8fac4619062" dependencies = [ "argon2", "async-stream", diff --git a/Cargo.toml b/Cargo.toml index 9ea80477d57a..c403e7776b3f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ rust-version = "1.81" [workspace.dependencies] # First party dependencies -sd-cloud-schema = { git = "https://github.com/spacedriveapp/cloud-services-schema", rev = "bbc69c5cb2" } +sd-cloud-schema = { git = "https://github.com/spacedriveapp/cloud-services-schema", rev = "99d59e8fab" } # Third party dependencies used by one or more of our crates async-channel = "2.3" diff --git a/apps/mobile/modules/sd-core/ios/build-rust.sh b/apps/mobile/modules/sd-core/ios/build-rust.sh index a066bcf6c05a..310b208580c8 100755 --- a/apps/mobile/modules/sd-core/ios/build-rust.sh +++ b/apps/mobile/modules/sd-core/ios/build-rust.sh @@ -48,10 +48,10 @@ mkdir -p "$TARGET_DIRECTORY" TARGET_DIRECTORY="$(CDPATH='' cd -- "$TARGET_DIRECTORY" && pwd -P)" TARGET_CONFIG=debug -# if [ "${CONFIGURATION:-}" = "Release" ]; then -# set -- --release -# TARGET_CONFIG=release -# fi +if [ "${CONFIGURATION:-}" = "Release" ]; then + set -- --release + TARGET_CONFIG=release +fi trap 'if [ -e "${CARGO_CONFIG}.bak" ]; then mv "${CARGO_CONFIG}.bak" "$CARGO_CONFIG"; fi' EXIT diff --git a/core/crates/cloud-services/Cargo.toml b/core/crates/cloud-services/Cargo.toml index baffe812d53d..2908c9586ff3 100644 --- a/core/crates/cloud-services/Cargo.toml +++ b/core/crates/cloud-services/Cargo.toml @@ -41,7 +41,7 @@ anyhow = "1.0.86" dashmap = "6.1.0" iroh-net = { version = "0.27", features = ["discovery-local-network", "iroh-relay"] } paste = "=1.0.15" -quic-rpc = { version = "0.12.1", features = ["quinn-transport"] } +quic-rpc = { version = "0.13.0", features = ["quinn-transport"] } quinn = { package = "iroh-quinn", version = "0.11" } # Using whatever version of reqwest that reqwest-middleware uses, just putting here to enable some features reqwest = { version = "0.12", features = ["json", "native-tls-vendored", "stream"] } diff --git a/core/crates/cloud-services/src/client.rs b/core/crates/cloud-services/src/client.rs index d9ec361e16f0..24b427ef135b 100644 --- a/core/crates/cloud-services/src/client.rs +++ b/core/crates/cloud-services/src/client.rs @@ -1,12 +1,12 @@ use crate::p2p::{NotifyUser, UserResponse}; -use sd_cloud_schema::{Client, Service, ServicesALPN}; +use sd_cloud_schema::{Client, Request, Response, ServicesALPN}; use std::{net::SocketAddr, sync::Arc, time::Duration}; use futures::Stream; use iroh_net::relay::RelayUrl; -use quic_rpc::{transport::quinn::QuinnConnection, RpcClient}; +use quic_rpc::{transport::quinn::QuinnConnection, RpcClient, RpcMessage}; use quinn::{crypto::rustls::QuicClientConfig, ClientConfig, Endpoint}; use reqwest::{IntoUrl, Url}; use reqwest_middleware::{reqwest, ClientBuilder, ClientWithMiddleware}; @@ -19,10 +19,10 @@ use super::{ }; #[derive(Debug, Default, Clone)] -enum ClientState { +enum ClientState { #[default] NotConnected, - Connected(Client, Service>), + Connected(Client>), } /// Cloud services are a optional feature that allows you to interact with the cloud services @@ -35,7 +35,7 @@ enum ClientState { /// that core can always operate without the cloud services. #[derive(Debug)] pub struct CloudServices { - client_state: Arc>, + client_state: Arc>>, get_cloud_api_address: Url, http_client: ClientWithMiddleware, domain_name: String, @@ -157,7 +157,7 @@ impl CloudServices { http_client: &ClientWithMiddleware, get_cloud_api_address: Url, domain_name: String, - ) -> Result, Service>, Error> { + ) -> Result>, Error> { let cloud_api_address = http_client .get(get_cloud_api_address) .send() @@ -256,9 +256,6 @@ impl CloudServices { .map_err(Error::FailedToCreateEndpoint)?; endpoint.set_default_client_config(client_config); - // TODO(@fogodev): It's possible that we can't keep the connection alive all the time, - // and need to use single shot connections. I will only be sure when we have - // actually battle-tested the cloud services in core. Ok(Client::new(RpcClient::new(QuinnConnection::new( endpoint, cloud_api_address, @@ -271,9 +268,9 @@ impl CloudServices { /// If the client is not connected, it will try to connect to the cloud services. /// Available routes documented in /// [`sd_cloud_schema::Service`](https://github.com/spacedriveapp/cloud-services-schema). - pub async fn client(&self) -> Result, Service>, Error> { - if let ClientState::Connected(client) = { self.client_state.read().await.clone() } { - return Ok(client); + pub async fn client(&self) -> Result>, Error> { + if let ClientState::Connected(client) = { &*self.client_state.read().await } { + return Ok(client.clone()); } // If we're not connected, we need to try to connect. diff --git a/core/crates/cloud-services/src/error.rs b/core/crates/cloud-services/src/error.rs index f90ee028e0bc..ecb038aa395c 100644 --- a/core/crates/cloud-services/src/error.rs +++ b/core/crates/cloud-services/src/error.rs @@ -1,4 +1,4 @@ -use sd_cloud_schema::{cloud_p2p, sync::groups, Service}; +use sd_cloud_schema::{cloud_p2p, sync::groups, Request, Response}; use sd_utils::error::FileIOError; use std::{io, net::AddrParseError}; @@ -68,7 +68,9 @@ pub enum Error { #[error("Failed to connect to Cloud P2P node: {0}")] ConnectToCloudP2PNode(anyhow::Error), #[error("Communication error with Cloud P2P node: {0}")] - CloudP2PRpcCommunication(#[from] rpc::Error>), + CloudP2PRpcCommunication( + #[from] rpc::Error>, + ), #[error("Cloud P2P not initialized")] CloudP2PNotInitialized, #[error("Failed to initialize LocalSwarmDiscovery: {0}")] @@ -78,15 +80,15 @@ pub enum Error { // Communication errors #[error("Failed to communicate with RPC backend: {0}")] - RpcCommunication(#[from] rpc::Error>), + RpcCommunication(#[from] rpc::Error>), #[error("Failed to communicate with Server Streaming RPC backend: {0}")] - ServerStreamCommunication(#[from] server_streaming::Error>), + ServerStreamCommunication(#[from] server_streaming::Error>), #[error("Failed to receive next response from Server Streaming RPC backend: {0}")] - ServerStreamRecv(#[from] server_streaming::ItemError>), + ServerStreamRecv(#[from] server_streaming::ItemError>), #[error("Failed to communicate with Bidi Streaming RPC backend: {0}")] - BidiStreamCommunication(#[from] bidi_streaming::Error>), + BidiStreamCommunication(#[from] bidi_streaming::Error>), #[error("Failed to receive next response from Bidi Streaming RPC backend: {0}")] - BidiStreamRecv(#[from] bidi_streaming::ItemError>), + BidiStreamRecv(#[from] bidi_streaming::ItemError>), #[error("Error from backend: {0}")] Backend(#[from] sd_cloud_schema::Error), #[error("Failed to get access token from refresher: {0}")] diff --git a/core/crates/cloud-services/src/p2p/new_sync_messages_notifier.rs b/core/crates/cloud-services/src/p2p/new_sync_messages_notifier.rs index f4d0a3751078..704f3ea54d7d 100644 --- a/core/crates/cloud-services/src/p2p/new_sync_messages_notifier.rs +++ b/core/crates/cloud-services/src/p2p/new_sync_messages_notifier.rs @@ -1,7 +1,7 @@ use crate::{token_refresher::TokenRefresher, Error}; use sd_cloud_schema::{ - cloud_p2p::{Client, CloudP2PALPN, Service}, + cloud_p2p::{Client, CloudP2PALPN}, devices, sync::groups, }; @@ -24,8 +24,7 @@ pub async fn dispatch_notifier( devices: Option<(Instant, Vec<(devices::PubId, NodeId)>)>, msgs_tx: flume::Sender, cloud_services: sd_cloud_schema::Client< - QuinnConnection, - sd_cloud_schema::Service, + QuinnConnection, >, token_refresher: TokenRefresher, endpoint: Endpoint, @@ -64,8 +63,7 @@ async fn notify_peers( device_pub_id: devices::PubId, devices: Option<(Instant, Vec<(devices::PubId, NodeId)>)>, cloud_services: sd_cloud_schema::Client< - QuinnConnection, - sd_cloud_schema::Service, + QuinnConnection, >, token_refresher: TokenRefresher, endpoint: Endpoint, @@ -130,7 +128,7 @@ async fn connect_and_send_notification( connection_id: &NodeId, endpoint: &Endpoint, ) -> Result<(), Error> { - let client = Client::new(RpcClient::new(QuinnConnection::::from_connection( + let client = Client::new(RpcClient::new(QuinnConnection::from_connection( endpoint .connect(*connection_id, CloudP2PALPN::LATEST) .await diff --git a/core/crates/cloud-services/src/p2p/runner.rs b/core/crates/cloud-services/src/p2p/runner.rs index 3dfc33be2471..17e6da08b047 100644 --- a/core/crates/cloud-services/src/p2p/runner.rs +++ b/core/crates/cloud-services/src/p2p/runner.rs @@ -73,8 +73,7 @@ pub struct Runner { current_device_pub_id: devices::PubId, token_refresher: TokenRefresher, cloud_services: sd_cloud_schema::Client< - QuinnConnection, - sd_cloud_schema::Service, + QuinnConnection, >, msgs_tx: flume::Sender, endpoint: Endpoint, @@ -112,12 +111,14 @@ impl Clone for Runner { } struct PendingSyncGroupJoin { - channel: RpcChannel>, + channel: RpcChannel>, request: authorize_new_device_in_sync_group::Request, this_device: Device, since: Instant, } +type P2PServerEndpoint = QuinnServerEndpoint; + impl Runner { pub async fn new( current_device_pub_id: devices::PubId, @@ -152,10 +153,7 @@ impl Runner { #[allow(clippy::large_enum_variant)] enum StreamMessage { AcceptResult( - Result< - Accepting>, - RpcServerError>, - >, + Result, RpcServerError>, ), Message(Message), UserResponse(UserResponse), @@ -361,7 +359,7 @@ impl Runner { async fn handle_request( &self, request: cloud_p2p::Request, - channel: RpcChannel>, + channel: RpcChannel, ) { match request { cloud_p2p::Request::AuthorizeNewDeviceInSyncGroup( @@ -598,7 +596,7 @@ impl Runner { async fn connect_to_first_available_client( endpoint: &Endpoint, devices_in_group: &[(devices::PubId, NodeId)], -) -> Result, Service>, CloudP2PError> { +) -> Result>, CloudP2PError> { for (device_pub_id, device_connection_id) in devices_in_group { if let Ok(connection) = endpoint .connect(*device_connection_id, CloudP2PALPN::LATEST) @@ -607,8 +605,9 @@ async fn connect_to_first_available_client( |e| error!(?e, %device_pub_id, "Failed to connect to authorizor device candidate"), ) { debug!(%device_pub_id, "Connected to authorizor device candidate"); + return Ok(Client::new(RpcClient::new( - QuinnConnection::::from_connection(connection), + QuinnConnection::from_connection(connection), ))); } } @@ -618,10 +617,7 @@ async fn connect_to_first_available_client( fn setup_server_endpoint( endpoint: Endpoint, -) -> ( - RpcServer>, - JoinHandle<()>, -) { +) -> (RpcServer, JoinHandle<()>) { let local_addr = { let (ipv4_addr, maybe_ipv6_addr) = endpoint.bound_sockets(); // Trying to give preference to IPv6 addresses because it's 2024 @@ -631,7 +627,7 @@ fn setup_server_endpoint( let (connections_tx, connections_rx) = flume::bounded(16); ( - RpcServer::new(QuinnServerEndpoint::::handle_connections( + RpcServer::new(QuinnServerEndpoint::handle_connections( connections_rx, local_addr, )), diff --git a/core/crates/cloud-services/src/sync/receive.rs b/core/crates/cloud-services/src/sync/receive.rs index f4db4b4c5b94..363d379db889 100644 --- a/core/crates/cloud-services/src/sync/receive.rs +++ b/core/crates/cloud-services/src/sync/receive.rs @@ -6,7 +6,7 @@ use sd_cloud_schema::{ groups, messages::{pull, MessagesCollection}, }, - Client, Service, + Client, Request, Response, }; use sd_core_sync::{ cloud_crdt_op_db, CRDTOperation, CompressedCRDTOperationsPerModel, SyncManager, @@ -49,7 +49,7 @@ pub struct Receiver { sync_group_pub_id: groups::PubId, device_pub_id: devices::PubId, cloud_services: Arc, - cloud_client: Client>, + cloud_client: Client>, key_manager: Arc, sync: SyncManager, notifiers: Arc, diff --git a/core/crates/cloud-services/src/sync/send.rs b/core/crates/cloud-services/src/sync/send.rs index c0ab06e88fea..5a95240e6203 100644 --- a/core/crates/cloud-services/src/sync/send.rs +++ b/core/crates/cloud-services/src/sync/send.rs @@ -7,7 +7,7 @@ use sd_cloud_schema::{ devices, error::{ClientSideError, NotFoundError}, sync::{groups, messages}, - Client, Service, + Client, Request, Response, }; use sd_crypto::{ cloud::{OneShotEncryption, SecretKey, StreamEncryption}, @@ -60,7 +60,7 @@ pub struct Sender { sync_group_pub_id: groups::PubId, sync: SyncManager, cloud_services: Arc, - cloud_client: Client>, + cloud_client: Client>, key_manager: Arc, is_active: Arc, state_notify: Arc, diff --git a/core/src/api/cloud/devices.rs b/core/src/api/cloud/devices.rs index ca1a81ad685e..d775c7c86f92 100644 --- a/core/src/api/cloud/devices.rs +++ b/core/src/api/cloud/devices.rs @@ -10,7 +10,7 @@ use sd_cloud_schema::{ ClientRegistration, ClientRegistrationFinishParameters, ClientRegistrationFinishResult, ClientRegistrationStartResult, }, - Client, NodeId, Service, SpacedriveCipherSuite, + Client, NodeId, Request, Response, SpacedriveCipherSuite, }; use sd_crypto::{cloud::secret_key::SecretKey, CryptoRng}; @@ -149,7 +149,7 @@ pub fn mount() -> AlphaRouter { } pub async fn hello( - client: &Client, Service>, + client: &Client>, access_token: AccessToken, device_pub_id: PubId, hashed_pub_id: Hash, @@ -270,7 +270,7 @@ pub struct DeviceRegisterData { } pub async fn register( - client: &Client, Service>, + client: &Client>, access_token: AccessToken, DeviceRegisterData { pub_id, diff --git a/core/src/api/cloud/mod.rs b/core/src/api/cloud/mod.rs index 611fb0c31dbc..e2afdbbf6d50 100644 --- a/core/src/api/cloud/mod.rs +++ b/core/src/api/cloud/mod.rs @@ -10,7 +10,7 @@ use sd_cloud_schema::{ auth, error::{ClientSideError, Error}, sync::groups, - users, Client, SecretKey as IrohSecretKey, Service, + users, Client, Request, Response, SecretKey as IrohSecretKey, }; use sd_crypto::{CryptoRng, SeedableRng}; use sd_utils::error::report_error; @@ -32,7 +32,7 @@ mod sync_groups; async fn try_get_cloud_services_client( node: &Node, -) -> Result, Service>, sd_core_cloud_services::Error> { +) -> Result>, sd_core_cloud_services::Error> { node.cloud_services .client() .await @@ -302,7 +302,13 @@ async fn initialize_cloud_sync( async fn get_client_and_access_token( node: &Node, -) -> Result<(Client, Service>, auth::AccessToken), rspc::Error> { +) -> Result< + ( + Client>, + auth::AccessToken, + ), + rspc::Error, +> { ( try_get_cloud_services_client(node), node.cloud_services