diff --git a/services/tunnelbroker/rust-notifications/src/fcm.rs b/services/tunnelbroker/rust-notifications/src/fcm.rs index a065034fc..5f40b1997 100644 --- a/services/tunnelbroker/rust-notifications/src/fcm.rs +++ b/services/tunnelbroker/rust-notifications/src/fcm.rs @@ -1,24 +1,48 @@ +use crate::ffi::fcm_status; use anyhow::{anyhow, Result}; -use fcm::{Client, MessageBuilder, NotificationBuilder}; +use fcm::{ + response::ErrorReason::{InvalidRegistration, NotRegistered}, + Client, MessageBuilder, NotificationBuilder, +}; pub async fn send_by_fcm_client( fcm_api_key: &str, device_registration_id: &str, message_title: &str, message_body: &str, -) -> Result { +) -> Result { let client = Client::new(); let mut notification_builder = NotificationBuilder::new(); notification_builder.title(message_title); notification_builder.body(message_body); - let notification = notification_builder.finalize(); + let mut message_builder = MessageBuilder::new(fcm_api_key, device_registration_id); message_builder.notification(notification); + let result = client.send(message_builder.finalize()).await?; - match result.message_id { - Some(message_id) => Ok(message_id), - None => Err(anyhow!("FCM client returned an empty message id")), + match result.results { + Some(results) => { + if results.len() == 0 { + return Err(anyhow!("FCM client returned zero size results")); + } + if let Some(result_error) = results[0].error { + match result_error { + // We are returning `Ok` with the error types here to distinguish the exact + // error type in a C++ side + InvalidRegistration => return Ok(fcm_status::InvalidRegistration), + NotRegistered => return Ok(fcm_status::NotRegistered), + _ => { + return Err(anyhow!( + "Notification was not accepted by FCM, reason: {:?}", + result_error + )) + } + } + } + } + None => return Err(anyhow!("FCM client has no results set")), } + Ok(fcm_status::Ok) } diff --git a/services/tunnelbroker/rust-notifications/src/lib.rs b/services/tunnelbroker/rust-notifications/src/lib.rs index 030bf7532..af6a4faab 100644 --- a/services/tunnelbroker/rust-notifications/src/lib.rs +++ b/services/tunnelbroker/rust-notifications/src/lib.rs @@ -1,77 +1,83 @@ -use crate::ffi::apns_status; +use crate::ffi::{apns_status, fcm_status}; use anyhow::Result; use env_logger; use lazy_static::lazy_static; use log::info; use tokio::runtime::Runtime; pub mod apns; pub mod fcm; #[cxx::bridge] mod ffi { #[cxx_name = "apnsReturnStatus"] enum apns_status { Ok, Unregistered, BadDeviceToken, } + #[cxx_name = "fcmReturnStatus"] + enum fcm_status { + Ok, + InvalidRegistration, + NotRegistered, + } extern "Rust" { #[cxx_name = "sendNotifToAPNS"] fn send_notif_to_apns( certificate_path: &str, certificate_password: &str, device_token: &str, topic: &str, message: &str, sandbox: bool, ) -> Result; #[cxx_name = "sendNotifToFCM"] fn send_notif_to_fcm( fcm_api_key: &str, device_registration_id: &str, message_title: &str, message_body: &str, - ) -> Result; + ) -> Result; } } lazy_static! { pub static ref RUNTIME: Runtime = { env_logger::init(); info!("Tokio runtime initialization"); Runtime::new().unwrap() }; } pub fn send_notif_to_apns( certificate_path: &str, certificate_password: &str, device_token: &str, topic: &str, message: &str, sandbox: bool, ) -> Result { RUNTIME.block_on(apns::send_by_a2_client( certificate_path, certificate_password, device_token, topic, message, sandbox, )) } pub fn send_notif_to_fcm( fcm_api_key: &str, device_registration_id: &str, message_title: &str, message_body: &str, -) -> Result { +) -> Result { RUNTIME.block_on(fcm::send_by_fcm_client( fcm_api_key, device_registration_id, message_title, message_body, )) }