diff --git a/native/cpp/CommonCpp/grpc/grpc_client/build.rs b/native/cpp/CommonCpp/grpc/grpc_client/build.rs --- a/native/cpp/CommonCpp/grpc/grpc_client/build.rs +++ b/native/cpp/CommonCpp/grpc/grpc_client/build.rs @@ -2,6 +2,6 @@ tonic_build::compile_protos("../../../../../shared/protos/identity.proto") .unwrap_or_else(|e| panic!("Failed to compile protos {:?}", e)); let _cxx_build = - cxx_build::bridge("src/lib.rs").flag_if_supported("-std=c++11"); + cxx_build::bridge("src/lib.rs").flag_if_supported("-std=c++14"); println!("cargo:rerun-if-changed=src/hello.c"); } diff --git a/native/cpp/CommonCpp/grpc/grpc_client/cxx.h b/native/cpp/CommonCpp/grpc/grpc_client/cxx.h --- a/native/cpp/CommonCpp/grpc/grpc_client/cxx.h +++ b/native/cpp/CommonCpp/grpc/grpc_client/cxx.h @@ -1,4 +1,3 @@ -// @generated #pragma once #include #include diff --git a/native/cpp/CommonCpp/grpc/grpc_client/lib.rs.h b/native/cpp/CommonCpp/grpc/grpc_client/lib.rs.h --- a/native/cpp/CommonCpp/grpc/grpc_client/lib.rs.h +++ b/native/cpp/CommonCpp/grpc/grpc_client/lib.rs.h @@ -1,4 +1,3 @@ -// @generated #pragma once #include #include @@ -820,13 +819,10 @@ } // namespace cxxbridge1 } // namespace rust -namespace identity { struct Client; -} -namespace identity { -#ifndef CXXBRIDGE1_STRUCT_identity$Client -#define CXXBRIDGE1_STRUCT_identity$Client +#ifndef CXXBRIDGE1_STRUCT_Client +#define CXXBRIDGE1_STRUCT_Client struct Client final : public ::rust::Opaque { ~Client() = delete; @@ -837,23 +833,23 @@ static ::std::size_t align() noexcept; }; }; -#endif // CXXBRIDGE1_STRUCT_identity$Client +#endif // CXXBRIDGE1_STRUCT_Client -::rust::Box<::identity::Client> initialize_client() noexcept; +::rust::Box<::Client> initialize_client() noexcept; ::rust::String get_user_id_blocking( - ::rust::Box<::identity::Client> client, + ::rust::Box<::Client> client, ::std::int32_t auth_type, ::rust::String user_info); bool verify_user_token_blocking( - ::rust::Box<::identity::Client> client, + ::rust::Box<::Client> client, ::rust::String user_id, ::rust::String device_id, ::rust::String access_token); ::rust::String register_user_blocking( - ::rust::Box<::identity::Client> client, + ::rust::Box<::Client> client, ::rust::String user_id, ::rust::String device_id, ::rust::String username, @@ -861,16 +857,15 @@ ::rust::String user_public_key); ::rust::String login_user_pake_blocking( - ::rust::Box<::identity::Client> client, + ::rust::Box<::Client> client, ::rust::String user_id, ::rust::String device_id, ::rust::String password); ::rust::String login_user_wallet_blocking( - ::rust::Box<::identity::Client> client, + ::rust::Box<::Client> client, ::rust::String user_id, ::rust::String device_id, ::rust::String siwe_message, ::rust::Vec<::std::uint8_t> siwe_signature, ::rust::String user_public_key); -} // namespace identity diff --git a/native/cpp/CommonCpp/grpc/grpc_client/src/lib.rs b/native/cpp/CommonCpp/grpc/grpc_client/src/identity_client.rs copy from native/cpp/CommonCpp/grpc/grpc_client/src/lib.rs copy to native/cpp/CommonCpp/grpc/grpc_client/src/identity_client.rs --- a/native/cpp/CommonCpp/grpc/grpc_client/src/lib.rs +++ b/native/cpp/CommonCpp/grpc/grpc_client/src/identity_client.rs @@ -1,4 +1,3 @@ -use lazy_static::lazy_static; use opaque_ke::{ ClientLogin, ClientLoginFinishParameters, ClientLoginStartParameters, ClientLoginStartResult, ClientRegistration, @@ -6,18 +5,12 @@ CredentialResponse, RegistrationResponse, RegistrationUpload, }; use rand::{rngs::OsRng, CryptoRng, Rng}; -use std::sync::Arc; -use tokio::runtime::{Builder, Runtime}; use tokio::sync::mpsc; use tokio_stream::wrappers::ReceiverStream; -use tonic::{transport::Channel, Request, Status}; -use tracing::{error, instrument}; - -mod opaque; -use opaque::Cipher; +use tonic::{Request, Status}; +use tracing::error; use crate::identity::{ - identity_service_client::IdentityServiceClient, login_request::Data::PakeLoginRequest, login_request::Data::WalletLoginRequest, login_response::Data::PakeLoginResponse as LoginPakeLoginResponse, @@ -41,79 +34,10 @@ VerifyUserTokenRequest, WalletLoginRequest as WalletLoginRequestStruct, WalletLoginResponse as WalletLoginResponseStruct, }; -pub mod identity { - tonic::include_proto!("identity"); -} - -const IDENTITY_SERVICE_SOCKET_ADDR: &str = "https://[::1]:50051"; - -lazy_static! { - pub static ref RUNTIME: Arc = Arc::new( - Builder::new_multi_thread() - .worker_threads(1) - .max_blocking_threads(1) - .enable_all() - .build() - .unwrap() - ); -} +use crate::opaque::Cipher; +use crate::Client; -#[cxx::bridge(namespace = "identity")] -mod ffi { - extern "Rust" { - type Client; - fn initialize_client() -> Box; - fn get_user_id_blocking( - client: Box, - auth_type: i32, - user_info: String, - ) -> Result; - fn verify_user_token_blocking( - client: Box, - user_id: String, - device_id: String, - access_token: String, - ) -> Result; - fn register_user_blocking( - client: Box, - user_id: String, - device_id: String, - username: String, - password: String, - user_public_key: String, - ) -> Result; - fn login_user_pake_blocking( - client: Box, - user_id: String, - device_id: String, - password: String, - user_public_key: String, - ) -> Result; - fn login_user_wallet_blocking( - client: Box, - user_id: String, - device_id: String, - siwe_message: String, - siwe_signature: Vec, - user_public_key: String, - ) -> Result; - } -} - -#[derive(Debug)] -struct Client { - identity_client: IdentityServiceClient, -} - -fn initialize_client() -> Box { - Box::new(Client { - identity_client: RUNTIME - .block_on(IdentityServiceClient::connect(IDENTITY_SERVICE_SOCKET_ADDR)) - .unwrap(), - }) -} - -async fn get_user_id( +pub async fn get_user_id( mut client: Box, auth_type: i32, user_info: String, @@ -131,16 +55,7 @@ ) } -#[instrument] -fn get_user_id_blocking( - client: Box, - auth_type: i32, - user_info: String, -) -> Result { - RUNTIME.block_on(get_user_id(client, auth_type, user_info)) -} - -async fn verify_user_token( +pub async fn verify_user_token( mut client: Box, user_id: String, device_id: String, @@ -160,17 +75,7 @@ ) } -#[instrument] -fn verify_user_token_blocking( - client: Box, - user_id: String, - device_id: String, - access_token: String, -) -> Result { - RUNTIME.block_on(verify_user_token(client, user_id, device_id, access_token)) -} - -async fn register_user( +pub async fn register_user( mut client: Box, user_id: String, device_id: String, @@ -232,26 +137,7 @@ handle_registration_token_response(message) } -#[instrument] -fn register_user_blocking( - client: Box, - user_id: String, - device_id: String, - username: String, - password: String, - user_public_key: String, -) -> Result { - RUNTIME.block_on(register_user( - client, - user_id, - device_id, - username, - password, - user_public_key, - )) -} - -async fn login_user_pake( +pub async fn login_user_pake( mut client: Box, user_id: String, device_id: String, @@ -315,24 +201,7 @@ handle_login_token_response(message) } -#[instrument] -fn login_user_pake_blocking( - client: Box, - user_id: String, - device_id: String, - password: String, - user_public_key: String, -) -> Result { - RUNTIME.block_on(login_user_pake( - client, - user_id, - device_id, - password, - user_public_key, - )) -} - -async fn login_user_wallet( +pub async fn login_user_wallet( mut client: Box, user_id: String, device_id: String, @@ -374,25 +243,6 @@ handle_wallet_login_response(message) } -#[instrument] -fn login_user_wallet_blocking( - client: Box, - user_id: String, - device_id: String, - siwe_message: String, - siwe_signature: Vec, - user_public_key: String, -) -> Result { - RUNTIME.block_on(login_user_wallet( - client, - user_id, - device_id, - siwe_message, - siwe_signature, - user_public_key, - )) -} - fn pake_registration_start( rng: &mut (impl Rng + CryptoRng), user_id: String, diff --git a/native/cpp/CommonCpp/grpc/grpc_client/src/lib.rs b/native/cpp/CommonCpp/grpc/grpc_client/src/lib.rs --- a/native/cpp/CommonCpp/grpc/grpc_client/src/lib.rs +++ b/native/cpp/CommonCpp/grpc/grpc_client/src/lib.rs @@ -1,50 +1,21 @@ use lazy_static::lazy_static; -use opaque_ke::{ - ClientLogin, ClientLoginFinishParameters, ClientLoginStartParameters, - ClientLoginStartResult, ClientRegistration, - ClientRegistrationFinishParameters, CredentialFinalization, - CredentialResponse, RegistrationResponse, RegistrationUpload, -}; -use rand::{rngs::OsRng, CryptoRng, Rng}; use std::sync::Arc; use tokio::runtime::{Builder, Runtime}; -use tokio::sync::mpsc; -use tokio_stream::wrappers::ReceiverStream; -use tonic::{transport::Channel, Request, Status}; -use tracing::{error, instrument}; +use tonic::{transport::Channel, Status}; +use tracing::instrument; +mod identity_client; mod opaque; -use opaque::Cipher; - -use crate::identity::{ - identity_service_client::IdentityServiceClient, - login_request::Data::PakeLoginRequest, - login_request::Data::WalletLoginRequest, - login_response::Data::PakeLoginResponse as LoginPakeLoginResponse, - login_response::Data::WalletLoginResponse, - pake_login_request::Data::PakeCredentialFinalization as LoginPakeCredentialFinalization, - pake_login_request::Data::PakeCredentialRequestAndUserId, - pake_login_response::Data::AccessToken, - pake_login_response::Data::PakeCredentialResponse, - registration_request::Data::PakeCredentialFinalization as RegistrationPakeCredentialFinalization, - registration_request::Data::PakeRegistrationRequestAndUserId, - registration_request::Data::PakeRegistrationUploadAndCredentialRequest, - registration_response::Data::PakeLoginResponse as RegistrationPakeLoginResponse, - registration_response::Data::PakeRegistrationResponse, GetUserIdRequest, - LoginRequest, LoginResponse, - PakeCredentialRequestAndUserId as PakeCredentialRequestAndUserIdStruct, - PakeLoginRequest as PakeLoginRequestStruct, - PakeLoginResponse as PakeLoginResponseStruct, - PakeRegistrationRequestAndUserId as PakeRegistrationRequestAndUserIdStruct, - PakeRegistrationUploadAndCredentialRequest as PakeRegistrationUploadAndCredentialRequestStruct, - RegistrationRequest, RegistrationResponse as RegistrationResponseMessage, - VerifyUserTokenRequest, WalletLoginRequest as WalletLoginRequestStruct, - WalletLoginResponse as WalletLoginResponseStruct, -}; -pub mod identity { +mod identity { tonic::include_proto!("identity"); } +use identity::identity_service_client::IdentityServiceClient; +use identity_client::{ + get_user_id, login_user_pake, login_user_wallet, register_user, + verify_user_token, +}; + const IDENTITY_SERVICE_SOCKET_ADDR: &str = "https://[::1]:50051"; lazy_static! { @@ -58,7 +29,7 @@ ); } -#[cxx::bridge(namespace = "identity")] +#[cxx::bridge] mod ffi { extern "Rust" { type Client; @@ -101,7 +72,7 @@ } #[derive(Debug)] -struct Client { +pub struct Client { identity_client: IdentityServiceClient, } @@ -113,24 +84,6 @@ }) } -async fn get_user_id( - mut client: Box, - auth_type: i32, - user_info: String, -) -> Result { - Ok( - client - .identity_client - .get_user_id(GetUserIdRequest { - auth_type, - user_info, - }) - .await? - .into_inner() - .user_id, - ) -} - #[instrument] fn get_user_id_blocking( client: Box, @@ -140,26 +93,6 @@ RUNTIME.block_on(get_user_id(client, auth_type, user_info)) } -async fn verify_user_token( - mut client: Box, - user_id: String, - device_id: String, - access_token: String, -) -> Result { - Ok( - client - .identity_client - .verify_user_token(VerifyUserTokenRequest { - user_id, - device_id, - access_token, - }) - .await? - .into_inner() - .token_valid, - ) -} - #[instrument] fn verify_user_token_blocking( client: Box, @@ -170,68 +103,6 @@ RUNTIME.block_on(verify_user_token(client, user_id, device_id, access_token)) } -async fn register_user( - mut client: Box, - user_id: String, - device_id: String, - username: String, - password: String, - user_public_key: String, -) -> Result { - // Create a RegistrationRequest channel and use ReceiverStream to turn the - // MPSC receiver into a Stream for outbound messages - let (tx, rx) = mpsc::channel(1); - let stream = ReceiverStream::new(rx); - let request = Request::new(stream); - - // `response` is the Stream for inbound messages - let mut response = client - .identity_client - .register_user(request) - .await? - .into_inner(); - - // Start PAKE registration on client and send initial registration request - // to Identity service - let mut client_rng = OsRng; - let (registration_request, client_registration) = pake_registration_start( - &mut client_rng, - user_id, - &password, - device_id, - username, - user_public_key, - )?; - if let Err(e) = tx.send(registration_request).await { - error!("Response was dropped: {}", e); - return Err(Status::aborted("Dropped response")); - } - - // Handle responses from Identity service sequentially, making sure we get - // messages in the correct order - - // Finish PAKE registration and begin PAKE login; send the final - // registration request and initial login request together to reduce the - // number of trips - let message = response.message().await?; - let client_login = handle_registration_response( - message, - &mut client_rng, - client_registration, - &password, - tx.clone(), - ) - .await?; - - // Finish PAKE login; send final login request to Identity service - let message = response.message().await?; - handle_registration_credential_response(message, client_login, tx).await?; - - // Return access token - let message = response.message().await?; - handle_registration_token_response(message) -} - #[instrument] fn register_user_blocking( client: Box, @@ -251,70 +122,6 @@ )) } -async fn login_user_pake( - mut client: Box, - user_id: String, - device_id: String, - password: String, - user_public_key: String, -) -> Result { - // Create a LoginRequest channel and use ReceiverStream to turn the - // MPSC receiver into a Stream for outbound messages - let (tx, rx) = mpsc::channel(1); - let stream = ReceiverStream::new(rx); - let request = Request::new(stream); - - // `response` is the Stream for inbound messages - let mut response = client - .identity_client - .login_user(request) - .await? - .into_inner(); - - // Start PAKE login on client and send initial login request to Identity - // service - let mut client_rng = OsRng; - let client_login_start_result = pake_login_start(&mut client_rng, &password)?; - let login_request = LoginRequest { - data: Some(PakeLoginRequest(PakeLoginRequestStruct { - data: Some(PakeCredentialRequestAndUserId( - PakeCredentialRequestAndUserIdStruct { - user_id, - device_id, - pake_credential_request: client_login_start_result - .message - .serialize() - .map_err(|e| { - error!("Could not serialize credential request: {}", e); - Status::failed_precondition("PAKE failure") - })?, - user_public_key, - }, - )), - })), - }; - if let Err(e) = tx.send(login_request).await { - error!("Response was dropped: {}", e); - return Err(Status::aborted("Dropped response")); - } - - // Handle responses from Identity service sequentially, making sure we get - // messages in the correct order - - // Finish PAKE login; send final login request to Identity service - let message = response.message().await?; - handle_login_credential_response( - message, - client_login_start_result.state, - tx, - ) - .await?; - - // Return access token - let message = response.message().await?; - handle_login_token_response(message) -} - #[instrument] fn login_user_pake_blocking( client: Box, @@ -332,48 +139,6 @@ )) } -async fn login_user_wallet( - mut client: Box, - user_id: String, - device_id: String, - siwe_message: String, - siwe_signature: Vec, - user_public_key: String, -) -> Result { - // Create a LoginRequest channel and use ReceiverStream to turn the - // MPSC receiver into a Stream for outbound messages - let (tx, rx) = mpsc::channel(1); - let stream = ReceiverStream::new(rx); - let request = Request::new(stream); - - // `response` is the Stream for inbound messages - let mut response = client - .identity_client - .login_user(request) - .await? - .into_inner(); - - // Start wallet login on client and send initial login request to Identity - // service - let login_request = LoginRequest { - data: Some(WalletLoginRequest(WalletLoginRequestStruct { - user_id, - device_id, - siwe_message, - siwe_signature, - user_public_key, - })), - }; - if let Err(e) = tx.send(login_request).await { - error!("Response was dropped: {}", e); - return Err(Status::aborted("Dropped response")); - } - - // Return access token - let message = response.message().await?; - handle_wallet_login_response(message) -} - #[instrument] fn login_user_wallet_blocking( client: Box, @@ -392,262 +157,3 @@ user_public_key, )) } - -fn pake_registration_start( - rng: &mut (impl Rng + CryptoRng), - user_id: String, - password: &str, - device_id: String, - username: String, - user_public_key: String, -) -> Result<(RegistrationRequest, ClientRegistration), Status> { - let client_registration_start_result = - ClientRegistration::::start(rng, password.as_bytes()).map_err( - |e| { - error!("Failed to start PAKE registration: {}", e); - Status::failed_precondition("PAKE failure") - }, - )?; - let pake_registration_request = - client_registration_start_result.message.serialize(); - Ok(( - RegistrationRequest { - data: Some(PakeRegistrationRequestAndUserId( - PakeRegistrationRequestAndUserIdStruct { - user_id, - device_id, - pake_registration_request, - username, - user_public_key, - }, - )), - }, - client_registration_start_result.state, - )) -} - -fn pake_registration_finish( - rng: &mut (impl Rng + CryptoRng), - registration_response_bytes: &[u8], - client_registration: ClientRegistration, -) -> Result, Status> { - client_registration - .finish( - rng, - RegistrationResponse::deserialize(registration_response_bytes).map_err( - |e| { - error!("Could not deserialize registration response bytes: {}", e); - Status::aborted("Invalid response bytes") - }, - )?, - ClientRegistrationFinishParameters::default(), - ) - .map_err(|e| { - error!("Failed to finish PAKE registration: {}", e); - Status::aborted("PAKE failure") - }) - .map(|res| res.message) -} - -fn pake_login_start( - rng: &mut (impl Rng + CryptoRng), - password: &str, -) -> Result, Status> { - ClientLogin::::start( - rng, - password.as_bytes(), - ClientLoginStartParameters::default(), - ) - .map_err(|e| { - error!("Failed to start PAKE login: {}", e); - Status::failed_precondition("PAKE failure") - }) -} - -fn pake_login_finish( - credential_response_bytes: &[u8], - client_login: ClientLogin, -) -> Result, Status> { - client_login - .finish( - CredentialResponse::deserialize(credential_response_bytes).map_err( - |e| { - error!("Could not deserialize credential response bytes: {}", e); - Status::aborted("Invalid response bytes") - }, - )?, - ClientLoginFinishParameters::default(), - ) - .map_err(|e| { - error!("Failed to finish PAKE login: {}", e); - Status::aborted("PAKE failure") - }) - .map(|res| res.message) -} - -fn handle_unexpected_response( - message: Option, -) -> Status { - error!("Received an unexpected message: {:?}", message); - Status::invalid_argument("Invalid response data") -} - -async fn handle_registration_response( - message: Option, - client_rng: &mut (impl Rng + CryptoRng), - client_registration: ClientRegistration, - password: &str, - tx: mpsc::Sender, -) -> Result, Status> { - if let Some(RegistrationResponseMessage { - data: Some(PakeRegistrationResponse(registration_response_bytes)), - .. - }) = message - { - let pake_registration_upload = pake_registration_finish( - client_rng, - ®istration_response_bytes, - client_registration, - )? - .serialize(); - let client_login_start_result = pake_login_start(client_rng, password)?; - - // `registration_request` is a gRPC message containing serialized bytes to - // complete PAKE registration and begin PAKE login - let registration_request = RegistrationRequest { - data: Some(PakeRegistrationUploadAndCredentialRequest( - PakeRegistrationUploadAndCredentialRequestStruct { - pake_registration_upload, - pake_credential_request: client_login_start_result - .message - .serialize() - .map_err(|e| { - error!("Could not serialize credential request: {}", e); - Status::failed_precondition("PAKE failure") - })?, - }, - )), - }; - if let Err(e) = tx.send(registration_request).await { - error!("Response was dropped: {}", e); - return Err(Status::aborted("Dropped response")); - } - Ok(client_login_start_result.state) - } else { - Err(handle_unexpected_response(message)) - } -} - -async fn handle_registration_credential_response( - message: Option, - client_login: ClientLogin, - tx: mpsc::Sender, -) -> Result<(), Status> { - if let Some(RegistrationResponseMessage { - data: - Some(RegistrationPakeLoginResponse(PakeLoginResponseStruct { - data: Some(PakeCredentialResponse(credential_response_bytes)), - })), - }) = message - { - let registration_request = RegistrationRequest { - data: Some(RegistrationPakeCredentialFinalization( - pake_login_finish(&credential_response_bytes, client_login)? - .serialize() - .map_err(|e| { - error!("Could not serialize credential request: {}", e); - Status::failed_precondition("PAKE failure") - })?, - )), - }; - send_to_mpsc(tx, registration_request).await - } else { - Err(handle_unexpected_response(message)) - } -} - -async fn handle_login_credential_response( - message: Option, - client_login: ClientLogin, - tx: mpsc::Sender, -) -> Result<(), Status> { - if let Some(LoginResponse { - data: - Some(LoginPakeLoginResponse(PakeLoginResponseStruct { - data: Some(PakeCredentialResponse(credential_response_bytes)), - })), - }) = message - { - let login_request = LoginRequest { - data: Some(PakeLoginRequest(PakeLoginRequestStruct { - data: Some(LoginPakeCredentialFinalization( - pake_login_finish(&credential_response_bytes, client_login)? - .serialize() - .map_err(|e| { - error!("Could not serialize credential request: {}", e); - Status::failed_precondition("PAKE failure") - })?, - )), - })), - }; - send_to_mpsc(tx, login_request).await - } else { - Err(handle_unexpected_response(message)) - } -} - -fn handle_registration_token_response( - message: Option, -) -> Result { - if let Some(RegistrationResponseMessage { - data: - Some(RegistrationPakeLoginResponse(PakeLoginResponseStruct { - data: Some(AccessToken(access_token)), - })), - }) = message - { - Ok(access_token) - } else { - Err(handle_unexpected_response(message)) - } -} - -fn handle_login_token_response( - message: Option, -) -> Result { - if let Some(LoginResponse { - data: - Some(LoginPakeLoginResponse(PakeLoginResponseStruct { - data: Some(AccessToken(access_token)), - })), - }) = message - { - Ok(access_token) - } else { - Err(handle_unexpected_response(message)) - } -} - -fn handle_wallet_login_response( - message: Option, -) -> Result { - if let Some(LoginResponse { - data: Some(WalletLoginResponse(WalletLoginResponseStruct { access_token })), - }) = message - { - Ok(access_token) - } else { - Err(handle_unexpected_response(message)) - } -} - -async fn send_to_mpsc( - tx: mpsc::Sender, - request: T, -) -> Result<(), Status> { - if let Err(e) = tx.send(request).await { - error!("Response was dropped: {}", e); - return Err(Status::aborted("Dropped response")); - } - Ok(()) -} diff --git a/native/ios/Comm.xcodeproj/project.pbxproj b/native/ios/Comm.xcodeproj/project.pbxproj --- a/native/ios/Comm.xcodeproj/project.pbxproj +++ b/native/ios/Comm.xcodeproj/project.pbxproj @@ -39,7 +39,7 @@ 7F8D602326535E060053CB29 /* OpenSans-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7F8D602026535E060053CB29 /* OpenSans-Regular.ttf */; }; 7F8D602826535F240053CB29 /* IBMPlexSans-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7F8D602726535EEE0053CB29 /* IBMPlexSans-Bold.ttf */; }; 7F8D602926535F2A0053CB29 /* IBMPlexSans-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7F8D602626535EEE0053CB29 /* IBMPlexSans-Regular.ttf */; }; - 8B3EE8BE28C7C3AA00C8303A /* lib.rs.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8B3EE8BD28C7C3AA00C8303A /* lib.rs.cc */; }; + 8B99AF6628D5024800EB5ADB /* lib.rs.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8B99AF6428D5024700EB5ADB /* lib.rs.cc */; }; 8BF9F24D28B7943000E20C13 /* libgrpc_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8BF9F24C28B7943000E20C13 /* libgrpc_client.a */; }; B7162ABD28AAD461006588D3 /* CommIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = B7162ABC28AAD461006588D3 /* CommIcons.ttf */; }; B71AFF1F265EDD8600B22352 /* IBMPlexSans-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = B71AFF1E265EDD8600B22352 /* IBMPlexSans-Medium.ttf */; }; @@ -176,9 +176,9 @@ 7FCEA2DC2444010B004017B1 /* Comm-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Comm-Bridging-Header.h"; sourceTree = ""; }; 7FCFD8BD1E81B8DF00629B0E /* Comm.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = Comm.entitlements; path = Comm/Comm.entitlements; sourceTree = ""; }; 891D1495EE1F375F3AF6C7ED /* Pods-NotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.debug.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.debug.xcconfig"; sourceTree = ""; }; - 8B15717928CA36B400209C6A /* lib.rs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = lib.rs.h; path = grpc_client/lib.rs.h; sourceTree = ""; }; 8B15717B28CA442C00209C6A /* cxx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cxx.h; path = grpc_client/cxx.h; sourceTree = ""; }; - 8B3EE8BD28C7C3AA00C8303A /* lib.rs.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = lib.rs.cc; path = grpc_client/lib.rs.cc; sourceTree = ""; }; + 8B99AF6428D5024700EB5ADB /* lib.rs.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = lib.rs.cc; path = grpc_client/lib.rs.cc; sourceTree = ""; }; + 8B99AF6528D5024800EB5ADB /* lib.rs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = lib.rs.h; path = grpc_client/lib.rs.h; sourceTree = ""; }; 8BF9F24C28B7943000E20C13 /* libgrpc_client.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libgrpc_client.a; path = ../cpp/CommonCpp/grpc/grpc_client/target/universal/release/libgrpc_client.a; sourceTree = ""; }; 913E5A7BDECB327E3DE11053 /* Pods-NotificationService.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.release.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.release.xcconfig"; sourceTree = ""; }; 994BEBDD4E4959F69CEA0BC3 /* libPods-Comm.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Comm.a"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -315,9 +315,9 @@ 718A3C0426F22BD100F04A8D /* grpc */ = { isa = PBXGroup; children = ( + 8B99AF6428D5024700EB5ADB /* lib.rs.cc */, + 8B99AF6528D5024800EB5ADB /* lib.rs.h */, 8B15717B28CA442C00209C6A /* cxx.h */, - 8B15717928CA36B400209C6A /* lib.rs.h */, - 8B3EE8BD28C7C3AA00C8303A /* lib.rs.cc */, 71009A7926FDCD71002C8453 /* Client.cpp */, 71009A7A26FDCD71002C8453 /* Client.h */, B7BEE744279B3E20009CCA35 /* GRPCStreamHostObject.cpp */, @@ -883,7 +883,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "#!/bin/bash\nset -x\n# The $PATH used by Xcode likely won't contain Cargo, fix that.\n# In addition, the $PATH used by XCode has lots of Apple-specific\n# developer tools that your Cargo isn't expecting to use, fix that.\n# Note: This assumes a default `rustup` setup and default path.\nbuild_path=\"$HOME/.cargo/bin:/usr/local/bin:/usr/bin:/bin\"\n# cd to Cargo project\ncd ${SRCROOT}/../cpp/CommonCpp/grpc/grpc_client\n# Add iOS targets for cross-compilation\nenv PATH=\"${build_path}\" rustup target add aarch64-apple-ios\nenv PATH=\"${build_path}\" rustup target add x86_64-apple-ios\n# Install cargo lipo\nenv PATH=\"${build_path}\" cargo install cargo-lipo\n# Build cxx bridge\nenv PATH=\"${build_path}\" cargo build\n# Build universal static library (works on simulator and iOS)\nenv PATH=\"${build_path}\" cargo lipo --release \"${build_args[@]}\"\n# Copy the CXX files to the cargo project root to make them\n# available to XCode\ncp $(readlink target/cxxbridge/grpc_client/src/lib.rs.cc) .\ncp $(readlink target/cxxbridge/grpc_client/src/lib.rs.h) .\ncp $(readlink target/cxxbridge/rust/cxx.h) .\n"; + shellScript = "${SRCROOT}/../../scripts/build-rust-native-library.sh\n"; }; 8BFD334828CBC1910091411F /* Clean up generated CXX files */ = { isa = PBXShellScriptBuildPhase; @@ -902,7 +902,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "#!/bin/bash\nset -x\n# cd to Cargo project\ncd ${SRCROOT}/../cpp/CommonCpp/grpc/grpc_client\n# Remove the generated files from root of Cargo project\nrm lib.rs.cc\n"; + shellScript = "${SRCROOT}/../../scripts/clean-up-rust-native-library.sh\n"; }; DB38BFA0686C805CE44F051F /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; @@ -1014,7 +1014,7 @@ CB38B48228771C7A00171182 /* NonBlockingLock.mm in Sources */, B7BEE749279B3FB6009CCA35 /* GRPCStreamHostObject.cpp in Sources */, 718DE99E2653D41C00365824 /* WorkerThread.cpp in Sources */, - 8B3EE8BE28C7C3AA00C8303A /* lib.rs.cc in Sources */, + 8B99AF6628D5024800EB5ADB /* lib.rs.cc in Sources */, 71CA4AEC262F236100835C89 /* Tools.mm in Sources */, 71009A7B26FDCD72002C8453 /* Client.cpp in Sources */, 71762A75270D8AAE00F565ED /* PlatformSpecificTools.mm in Sources */, diff --git a/scripts/build-rust-native-library.sh b/scripts/build-rust-native-library.sh new file mode 100755 --- /dev/null +++ b/scripts/build-rust-native-library.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +set -x +# The $PATH used by Xcode likely won't contain Cargo, fix that. +# In addition, the $PATH used by XCode has lots of Apple-specific +# developer tools that your Cargo isn't expecting to use, fix that. +# Note: This assumes a default `rustup` setup and default path. +build_path="$HOME/.cargo/bin:/usr/local/bin:/usr/bin:/bin" +# cd to Cargo project +cd "${SRCROOT}/../cpp/CommonCpp/grpc/grpc_client" || exit +# Add iOS targets for cross-compilation +env PATH="${build_path}" rustup target add aarch64-apple-ios +env PATH="${build_path}" rustup target add x86_64-apple-ios +# Install cargo lipo +env PATH="${build_path}" cargo install cargo-lipo +# Set C++ standard and build cxx bridge +export CXXFLAGS="-std=c++14" +env PATH="${build_path}" cargo build +# Build universal static library (works on simulator and iOS) +env PATH="${build_path}" cargo lipo --release +# Unset the flag specifying C++ standard +unset CXXFLAGS +# Copy the CXX files to the cargo project root to make them +# available to XCode +cp "$(readlink target/cxxbridge/grpc_client/src/lib.rs.cc)" . +cp "$(readlink target/cxxbridge/grpc_client/src/lib.rs.h)" . +cp "$(readlink target/cxxbridge/rust/cxx.h)" . diff --git a/scripts/clean-up-rust-native-library.sh b/scripts/clean-up-rust-native-library.sh new file mode 100755 --- /dev/null +++ b/scripts/clean-up-rust-native-library.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +set -x +# cd to Cargo project +cd "${SRCROOT}/../cpp/CommonCpp/grpc/grpc_client" || exit +# Remove the generated files from root of Cargo project +rm lib.rs.cc