diff --git a/services/tunnelbroker/rust-notifications/src/apns.rs b/services/tunnelbroker/rust-notifications/src/apns.rs --- a/services/tunnelbroker/rust-notifications/src/apns.rs +++ b/services/tunnelbroker/rust-notifications/src/apns.rs @@ -1,8 +1,10 @@ +use crate::ffi::apns_status; use a2::{ - Client, Endpoint, NotificationBuilder, NotificationOptions, - PlainNotificationBuilder, + Client, Endpoint, Error, + ErrorReason::{BadDeviceToken, Unregistered}, + NotificationBuilder, NotificationOptions, PlainNotificationBuilder, }; -use anyhow::Result; +use anyhow::{anyhow, Result}; use std::fs::File; pub async fn send_by_a2_client( @@ -12,7 +14,7 @@ topic: &str, message: &str, sandbox: bool, -) -> Result { +) -> Result { let mut certificate = File::open(certificate_path)?; let endpoint = if sandbox { Endpoint::Sandbox @@ -28,6 +30,27 @@ let builder = PlainNotificationBuilder::new(message); let mut payload = builder.build(device_token, options); payload.aps.content_available = Some(1); - let response = client.send(payload).await?; - Ok(response.code) + match client.send(payload).await { + Ok(_) => Ok(apns_status::Ok), + Err(Error::ResponseError(response)) => { + if let Some(error_body) = response.error { + match error_body.reason { + // We are returning `Ok` with the error types here to distinguish the exact + // error type in a C++ side + BadDeviceToken => Ok(apns_status::BadDeviceToken), + Unregistered => Ok(apns_status::Unregistered), + _ => Err(anyhow!( + "Notification was not accepted by APNs, reason: {:?}", + error_body.reason + )), + } + } else { + Err(anyhow!( + "Unhandled response error from APNs, response: {:?}", + response + )) + } + } + Err(error) => Err(anyhow::Error::new(error)), + } } 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,3 +1,4 @@ +use crate::ffi::apns_status; use anyhow::Result; use env_logger; use lazy_static::lazy_static; @@ -8,6 +9,12 @@ #[cxx::bridge] mod ffi { + #[cxx_name = "apnsReturnStatus"] + enum apns_status { + Ok, + Unregistered, + BadDeviceToken, + } extern "Rust" { #[cxx_name = "sendNotifToAPNS"] fn send_notif_to_apns( @@ -17,7 +24,7 @@ topic: &str, message: &str, sandbox: bool, - ) -> Result; + ) -> Result; #[cxx_name = "sendNotifToFCM"] fn send_notif_to_fcm( @@ -44,7 +51,7 @@ topic: &str, message: &str, sandbox: bool, -) -> Result { +) -> Result { RUNTIME.block_on(apns::send_by_a2_client( certificate_path, certificate_password,