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,34 @@ +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 { + // Read the private key and certificate from the disk + let mut certificate = File::open(certificatePath).unwrap(); + // Which service to call: test or production + let endpoint = if sandbox { + Endpoint::Sandbox + } else { + Endpoint::Production + }; + // Connects to APNs using a client certificate + let client = Client::certificate(&mut certificate, &certificatePassword, endpoint).unwrap(); + let options = NotificationOptions { + ..Default::default() + }; + // Notification payload + 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,62 @@ +use lazy_static::lazy_static; +use tokio::runtime::Runtime; +use log::info; +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 token {:?} was sent to APNS with the result {:?}", + deviceToken, runtimeResult + ); + } + Err(err) => { + eprintln!( + "Error: Panic catched from the Rust notification library in a sendByA2Client: {:?}", + err + ); + return false; + } + } + true +}