diff --git a/services/tunnelbroker/CMakeLists.txt b/services/tunnelbroker/CMakeLists.txt --- a/services/tunnelbroker/CMakeLists.txt +++ b/services/tunnelbroker/CMakeLists.txt @@ -9,6 +9,7 @@ endif(COMMAND cmake_policy) set(CMAKE_CXX_STANDARD 17) + # For C++17 on MacOS, we must set minimum target to 10.14+ set(CMAKE_OSX_DEPLOYMENT_TARGET 10.14) @@ -67,12 +68,6 @@ find_package(OpenSSL REQUIRED) find_package(glog) -# Corrosion Rust integration -find_package(Corrosion REQUIRED) -corrosion_import_crate(MANIFEST_PATH "rust-notifications/Cargo.toml") -set(RUST_HEADERS_INCLUDE_DIR "rust-notifications/extern") -set(RUST_LIBS "rust-notifications") - file(GLOB_RECURSE SOURCE_CODE "./src/*.cpp") set( diff --git a/services/tunnelbroker/rust-notifications/src/apns.rs b/services/tunnelbroker/rust-notifications/src/apns.rs new file mode 100644 --- /dev/null +++ b/services/tunnelbroker/rust-notifications/src/apns.rs @@ -0,0 +1,33 @@ +use a2::{ + Client, Endpoint, NotificationBuilder, NotificationOptions, + PlainNotificationBuilder, Response, +}; +use std::fs::File; + +#[allow(non_snake_case)] +pub async fn sendByA2Client( + certificatePath: &String, + certificatePassword: &String, + deviceToken: &String, + message: &String, + sandbox: bool, +) -> Response { + let mut certificate = File::open(certificatePath).unwrap(); + // Which service to call: test or production + let endpoint = if sandbox { + Endpoint::Sandbox + } else { + Endpoint::Production + }; + let client = + Client::certificate(&mut certificate, &certificatePassword, endpoint) + .unwrap(); + let options = NotificationOptions { + ..Default::default() + }; + let mut builder = PlainNotificationBuilder::new(message.as_ref()); + builder.set_sound("default"); + builder.set_badge(1u32); + let payload = builder.build(deviceToken.as_ref(), options); + client.send(payload).await.unwrap() +} diff --git a/services/tunnelbroker/rust-notifications/src/lib.rs b/services/tunnelbroker/rust-notifications/src/lib.rs --- a/services/tunnelbroker/rust-notifications/src/lib.rs +++ b/services/tunnelbroker/rust-notifications/src/lib.rs @@ -1 +1,60 @@ +use lazy_static::lazy_static; +use log::{error, info}; +use tokio::runtime::Runtime; +pub mod apns; + +#[cxx::bridge] +mod ffi { + extern "Rust" { + fn sendNotifToAPNS( + certificatePath: String, + certificatePassword: String, + deviceToken: String, + message: String, + sandbox: bool, + ) -> bool; + } +} + +lazy_static! { + // Lazy static Tokio runtime initialization + pub static ref RUNTIME: Runtime = Runtime::new().unwrap(); +} + +#[allow(non_snake_case)] +pub fn sendNotifToAPNS( + certificatePath: String, + certificatePassword: String, + deviceToken: String, + message: String, + sandbox: bool, +) -> bool { + // Because of C++ doesn't know how to 'Panic' we need to catch all the panics + let result = std::panic::catch_unwind(|| { + RUNTIME.block_on(async { + apns::sendByA2Client( + &certificatePath, + &certificatePassword, + &deviceToken, + &message, + sandbox, + ) + .await; + }) + }); + match result { + Ok(runtimeResult) => { + info!("Push notification to device {:?} was sent to APNS with the result {:?}", + deviceToken, runtimeResult + ); + } + Err(err) => { + error!("Error: Panic in the Rust notification library in a sendByA2Client: {:?}", + err + ); + return false; + } + } + true +}