Skip to content

Commit edd8ecf

Browse files
committed
Better errors
1 parent 274f0f1 commit edd8ecf

4 files changed

Lines changed: 36 additions & 21 deletions

File tree

src/aps.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,7 @@ impl APSConnectionResource {
528528
}
529529

530530
pub async fn get_token(&self) -> [u8; 32] {
531-
self.state.read().await.token.expect("Token not found!")
531+
self.state.read().await.token.expect("Token not found; re-enter device details if persistent")
532532
}
533533

534534
pub async fn request_topics(&self, topics: &[&str]) -> APSInterestToken {

src/error.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use plist::Value;
1010
use thiserror::Error;
1111
use tokio::{sync::{broadcast::{self, error::SendError}, Mutex}, time::error::Elapsed};
1212

13-
use crate::{aps::APSMessage, ids::user::SupportAlert, util::ResourceFailure};
13+
use crate::{aps::APSMessage, ids::user::{IDSError, SupportAlert}, util::ResourceFailure};
1414

1515

1616
#[derive(Error, Debug)]
@@ -25,17 +25,17 @@ pub enum PushError {
2525
AuthError(plist::Value),
2626
#[error("Authentication establishment error {0:?}")]
2727
CertError(plist::Dictionary),
28-
#[error("Error registering with IDS: {0}")]
29-
RegisterFailed(u64),
28+
#[error("Registration Error {0}")]
29+
RegisterFailed(IDSError),
3030
#[error("IO error: {0}")]
3131
IoError(#[from] io::Error),
32-
#[error("IDS Lookup failed {0}")]
33-
LookupFailed(u64),
32+
#[error("Lookup Error {0}")]
33+
LookupFailed(IDSError),
3434
#[error("AES key error: {0:?}")]
3535
KeyError(KeyError),
3636
#[error("IDS key missing for {0}")]
3737
KeyNotFound(String),
38-
#[error("No valid IDS targets for message")]
38+
#[error("Could not deliver message. The recipient does not have iMessage or you are being rate-limited.")]
3939
NoValidTargets,
4040
#[error("Failed to connect to APS {0}")]
4141
APSConnectError(u8),
@@ -48,9 +48,9 @@ pub enum PushError {
4848
#[cfg(feature = "macos-validation-data")]
4949
#[error("Absinthe error {0}")]
5050
AbsintheError(#[from] AbsintheError),
51-
#[error("{0}")]
51+
#[error("Your iMessage access is temporarily disabled. Try again later, or ask Apple to allow you to use iMessage: https://apple.co/IMFT-mac. Apple left a message: {0}")]
5252
CustomerMessage(SupportAlert),
53-
#[error("Send timeout")]
53+
#[error("Send timeout; try again")]
5454
SendTimedOut,
5555
#[error("Send error {0}")]
5656
SendErr(i64),
@@ -63,7 +63,7 @@ pub enum PushError {
6363
#[error("Failed to authenticate. Try logging in to account.apple.com to fix your Apple Account or create a new one: {1:?} {0}")]
6464
MobileMeError(String, Option<String>),
6565
#[error("Bad auth cert {0}")]
66-
AuthInvalid(u64),
66+
AuthInvalid(IDSError),
6767
#[error("APS parse error {0}")]
6868
APSParseError(#[from] DekuError),
6969
#[error("Other side hung up! {0}")]
@@ -118,7 +118,7 @@ pub enum PushError {
118118
ProtobufError(#[from] prost::DecodeError),
119119
#[error("Alias error {0}")]
120120
AliasError(u32),
121-
#[error("Handle not found {0}")]
121+
#[error("The handle {0} no longer exists on your account. Did you lose your number? Go to the new chat creator to use a different handle.")]
122122
HandleNotFound(String),
123123
#[error("AES GCM error")]
124124
AESGCMError,

src/ids/identity_manager.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use uuid::Uuid;
1616
use std::str::FromStr;
1717
use std::fmt::Debug;
1818

19-
use crate::{APSConnectionResource, APSMessage, IDSUser, MessageInst, OSConfig, PushError, aps::{APSConnection, APSInterestToken, get_message}, ids::{MessageBody, user::{IDSLookupUser}}, register, util::{Resource, ResourceManager, base64_decode, base64_encode, bin_deserialize, bin_deserialize_sha, bin_serialize, duration_since_epoch, encode_hex, plist_to_bin, plist_to_string, ungzip}};
19+
use crate::{APSConnectionResource, APSMessage, IDSUser, MessageInst, OSConfig, PushError, aps::{APSConnection, APSInterestToken, get_message}, ids::{MessageBody, user::{IDSError, IDSLookupUser}}, register, util::{Resource, ResourceManager, base64_decode, base64_encode, bin_deserialize, bin_deserialize_sha, bin_serialize, duration_since_epoch, encode_hex, plist_to_bin, plist_to_string, ungzip}};
2020

2121
use super::{user::{IDSDeliveryData, IDSNGMIdentity, IDSPublicIdentity, IDSService, IDSUserIdentity, IDSUserType, PrivateDeviceInfo, QueryOptions, ReportMessage}, CertifiedContext, IDSRecvMessage};
2222

@@ -368,7 +368,7 @@ impl Resource for IdentityResource {
368368
debug!("Register failed {}!", err);
369369
drop(users_lock);
370370

371-
let needs_relog = matches!(err, PushError::AuthInvalid(6005) | PushError::RegisterFailed(6005));
371+
let needs_relog = matches!(err, PushError::AuthInvalid(IDSError(6005)) | PushError::RegisterFailed(IDSError(6005)));
372372
return Err(if needs_relog {
373373
info!("Auth returns 6005, relog required!");
374374
PushError::DoNotRetry(Box::new(err))
@@ -690,7 +690,7 @@ impl IdentityResource {
690690
let results = match self.user_by_handle(topic, &users, handle).await?.query(&*self.config, &self.aps, topic, self.get_main_service(topic), handle, chunk, meta).await {
691691
Ok(results) => results,
692692
Err(err) => {
693-
if let PushError::LookupFailed(6005) = err {
693+
if let PushError::LookupFailed(IDSError(6005)) = err {
694694
warn!("IDS returned 6005; attempting to re-register");
695695
drop(users);
696696
drop(id_lock);

src/ids/user.rs

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -830,7 +830,7 @@ impl IDSUser {
830830

831831
let parsed: HandleResult = plist::from_bytes(&request)?;
832832
let Some(handles) = parsed.handles else {
833-
return Err(PushError::AuthInvalid(parsed.status))
833+
return Err(PushError::AuthInvalid(IDSError(parsed.status)))
834834
};
835835

836836
Ok(handles)
@@ -851,7 +851,7 @@ impl IDSUser {
851851

852852
let status = parsed.as_dictionary().unwrap()["status"].as_unsigned_integer().unwrap();
853853
if status != 0 {
854-
return Err(PushError::AuthInvalid(status))
854+
return Err(PushError::AuthInvalid(IDSError(status)))
855855
}
856856

857857
let devices = parsed.as_dictionary().unwrap().get("registrations").unwrap().as_array().unwrap();
@@ -992,13 +992,28 @@ impl IDSUser {
992992

993993
let loaded: IDSLookupResp = plist::from_bytes(&request)?;
994994
if loaded.status != 0 || loaded.results.is_none() {
995-
return Err(PushError::LookupFailed(loaded.status))
995+
return Err(PushError::LookupFailed(IDSError(loaded.status)))
996996
}
997997

998998
Ok(loaded.results.unwrap())
999999
}
10001000
}
10011001

1002+
#[derive(Debug)]
1003+
pub struct IDSError(pub u64);
1004+
1005+
impl Display for IDSError {
1006+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1007+
match self.0 {
1008+
6001 => write!(f, "Incompatible; Make sure Contact Key Verification and Advanced Data Protection are off. (6001)"),
1009+
6004 => write!(f, "Please try again (6004)"),
1010+
6005 => write!(f, "Bad authentication, try again and re-enter device details if persistent. (6005)"),
1011+
6009 => write!(f, "Your iMessage access is temporarily disabled. Try again later, or ask Apple to allow you to use iMessage: https://apple.co/IMFT-mac (6009)"),
1012+
_unk => write!(f, "Unknown IDS error {_unk}")
1013+
}
1014+
}
1015+
}
1016+
10021017
pub struct IDSService {
10031018
pub name: &'static str,
10041019
pub sub_services: &'static [&'static str],
@@ -1110,7 +1125,7 @@ pub async fn register(config: &dyn OSConfig, aps: &APSState, id_services: &[&'st
11101125

11111126
let status = resp.as_dictionary().unwrap().get("status").unwrap().as_unsigned_integer().unwrap();
11121127
if status != 0 {
1113-
return Err(PushError::RegisterFailed(status))
1128+
return Err(PushError::RegisterFailed(IDSError(status)))
11141129
}
11151130

11161131
// update registrations
@@ -1119,7 +1134,7 @@ pub async fn register(config: &dyn OSConfig, aps: &APSState, id_services: &[&'st
11191134
for service in service_list {
11201135
let dict = service.as_dictionary().unwrap();
11211136
let service_name = dict.get("service").unwrap().as_string().unwrap();
1122-
let users_list = dict.get("users").ok_or(PushError::RegisterFailed(u64::MAX))?.as_array().unwrap();
1137+
let users_list = dict.get("users").ok_or(PushError::RegisterFailed(IDSError(u64::MAX)))?.as_array().unwrap();
11231138

11241139
let service = id_services.iter().find(|service| service.name == service_name).expect("Service not found??");
11251140

@@ -1134,7 +1149,7 @@ pub async fn register(config: &dyn OSConfig, aps: &APSState, id_services: &[&'st
11341149
return Err(PushError::CustomerMessage(plist::from_value(alert)?))
11351150
}
11361151
}
1137-
return Err(PushError::RegisterFailed(status));
1152+
return Err(PushError::RegisterFailed(IDSError(status)));
11381153
}
11391154

11401155
let mut my_handles = vec![];
@@ -1145,7 +1160,7 @@ pub async fn register(config: &dyn OSConfig, aps: &APSState, id_services: &[&'st
11451160
let uri = uri.as_dictionary().unwrap().get("uri").unwrap().as_string().unwrap();
11461161
if status != 0 {
11471162
error!("Failed to register {uri} status {}", status);
1148-
return Err(PushError::RegisterFailed(status));
1163+
return Err(PushError::RegisterFailed(IDSError(status)));
11491164
}
11501165
my_handles.push(uri.to_string());
11511166
}

0 commit comments

Comments
 (0)