Skip to content

Commit 714f252

Browse files
committed
Packed APS encoding
1 parent 937dc64 commit 714f252

9 files changed

Lines changed: 918 additions & 116 deletions

File tree

src/aps.rs

Lines changed: 847 additions & 84 deletions
Large diffs are not rendered by default.

src/auth.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -771,7 +771,7 @@ impl<S: RequestState> SignedRequest<S> {
771771
debug!("sending apns query {:?}", request);
772772

773773
let receiver = aps.subscribe().await;
774-
aps.send_message(topic, plist_to_bin(&request)?, None).await?;
774+
aps.send_message(topic, request, None).await?;
775775

776776
let response = aps.wait_for_timeout(receiver, get_message(|payload| {
777777
let Some(recv_id) = payload.as_dictionary().unwrap().get("U") else {
@@ -1397,7 +1397,7 @@ impl IdmsAuthListener {
13971397
}
13981398

13991399
pub fn handle(&self, message: APSMessage) -> Result<Option<IdmsMessage>, PushError> {
1400-
let APSMessage::Notification { topic, payload, .. } = message else { return Ok(None) };
1400+
let APSMessage::Notification { topic, payload: Value::Data(payload), .. } = message else { return Ok(None) };
14011401
if &topic != &sha1("com.apple.idmsauth".as_bytes()) { return Ok(None) }
14021402

14031403
let data: serde_json::value::Map<String, serde_json::Value> = serde_json::from_slice(&payload)?;

src/icloud/cloudkit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -625,7 +625,7 @@ pub struct CloudKitNotifWatcher {
625625

626626
impl CloudKitNotifWatcher {
627627
pub async fn handle(&self, msg: &APSMessage) -> Result<Vec<RecordZoneIdentifier>, PushError> {
628-
let APSMessage::Notification { topic, payload, .. } = &msg else { return Ok(vec![]) };
628+
let APSMessage::Notification { topic, payload: Value::Data(payload), .. } = &msg else { return Ok(vec![]) };
629629
if topic != &self.for_topic { return Ok(vec![]) }
630630

631631
let data = std::str::from_utf8(payload).expect("Failed to decode?");

src/ids/identity_manager.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rand::RngCore;
1515
use uuid::Uuid;
1616
use std::str::FromStr;
1717
use std::fmt::Debug;
18-
use crate::util::{DebugMutex, DebugRwLock};
18+
use crate::{aps::new_aps_id, util::{DebugMutex, DebugRwLock}};
1919

2020
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}};
2121

@@ -718,7 +718,7 @@ impl IdentityResource {
718718
}
719719

720720
pub async fn handle(&self, msg: APSMessage) -> Result<bool, PushError> {
721-
let APSMessage::Notification { id: _, topic, token: _, payload, channel: _ } = msg else { return Ok(false) };
721+
let APSMessage::Notification { id: _, topic, token: _, payload: Value::Data(payload), channel: _ } = msg else { return Ok(false) };
722722
if topic != sha1("com.apple.private.ids".as_bytes()) { return Ok(false) };
723723

724724
#[derive(Deserialize)]
@@ -766,9 +766,9 @@ impl IdentityResource {
766766
pub async fn receive_message(&self, msg: APSMessage, topics: &[&'static str]) -> Result<Option<IDSRecvMessage>, PushError> {
767767
let APSMessage::Notification { id: _, topic, token: _, payload, channel: _ } = msg else { return Ok(None) };
768768
let Some(topic) = topics.iter().find(|t| sha1(t.as_bytes()) == topic) else { return Ok(None) };
769-
debug!("ID got message {topic} {:?}", plist::from_bytes::<Value>(&payload)?);
769+
debug!("ID got message {topic} {:?}", &payload);
770770

771-
let mut payload = plist::from_bytes::<IDSRecvMessage>(&payload)?;
771+
let mut payload = plist::from_value::<IDSRecvMessage>(&payload)?;
772772

773773

774774
payload.topic = *topic;
@@ -882,7 +882,7 @@ impl IdentityResource {
882882

883883
pub async fn certify_delivery(&self, topic: &'static str, delivery: &CertifiedContext, notify: bool) -> Result<(), PushError> {
884884
debug!("Certifying delivery for message {} notify {notify}", Uuid::from_bytes(delivery.uuid.clone().try_into().expect("Bad message uuid size!")).to_string());
885-
let msg_id = rand::thread_rng().next_u32();
885+
let msg_id = new_aps_id();
886886
let mut dict = Dictionary::from_iter([
887887
// sends APN ack
888888
("cdr", Value::Data(delivery.receipt.clone())),
@@ -902,7 +902,7 @@ impl IdentityResource {
902902
("gd".to_string(), Value::Boolean(true)),
903903
]);
904904
}
905-
self.aps.send_message(topic, plist_to_bin(&dict)?, Some(msg_id)).await?;
905+
self.aps.send_message(topic, dict, Some(msg_id)).await?;
906906

907907
Ok(())
908908
}
@@ -1014,7 +1014,7 @@ pub struct SendMessage {
10141014
pub user_agent: String,
10151015
pub v: Option<u32>,
10161016
#[serde(rename = "i")]
1017-
pub message_id: u32,
1017+
pub message_id: i32,
10181018
#[serde(rename = "U")]
10191019
pub uuid: Data,
10201020
#[serde(rename = "dtl")]
@@ -1107,7 +1107,7 @@ impl InnerSendJob {
11071107

11081108
let mut messages = self.conn.subscribe().await;
11091109

1110-
let msg_id = rand::thread_rng().next_u32();
1110+
let msg_id = new_aps_id();
11111111
let uuid = Uuid::from_str(&message.id).unwrap().as_bytes().to_vec();
11121112
let is_relay_message = message.relay.is_some();
11131113
let apns_topic = if is_relay_message {
@@ -1147,8 +1147,7 @@ impl InnerSendJob {
11471147

11481148
debug!("Sending value {value:?}");
11491149

1150-
let binary = plist_to_bin(&value)?;
1151-
self.conn.send_message(apns_topic, binary, Some(msg_id)).await?
1150+
self.conn.send_message(apns_topic, value, Some(msg_id)).await?
11521151
}
11531152

11541153
if !message.no_response {

src/imessage/aps_client.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ impl IMClient {
181181
e: duration_since_epoch().as_nanos() as u64,
182182
};
183183

184-
conn.send_message("com.apple.madrid", plist_to_bin(&msg).unwrap(), None).await?;
184+
conn.send_message("com.apple.madrid", msg, None).await?;
185185
}
186186
Ok(())
187187
}

src/imessage/messages.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use async_recursion::async_recursion;
1414
use std::io::Seek;
1515
use rand::RngCore;
1616

17-
use crate::{aps::get_message, ids::{identity_manager::{IDSSendMessage, MessageTarget, Raw}, CertifiedContext, IDSRecvMessage}, mmcs::{self, put_authorize_body, AuthorizedOperation, MMCSReceipt, ReadContainer, WriteContainer}, util::{base64_decode, base64_encode, bin_deserialize, bin_serialize, duration_since_epoch, plist_to_string, KeyedArchive, NSArray, NSArrayClass, NSDataClass, NSDictionary, NSDictionaryClass}, OSConfig};
17+
use crate::{OSConfig, aps::{get_message, new_aps_id}, ids::{CertifiedContext, IDSRecvMessage, identity_manager::{IDSSendMessage, MessageTarget, Raw}}, mmcs::{self, AuthorizedOperation, MMCSReceipt, ReadContainer, WriteContainer, put_authorize_body}, util::{KeyedArchive, NSArray, NSArrayClass, NSDataClass, NSDictionary, NSDictionaryClass, base64_decode, base64_encode, bin_deserialize, bin_serialize, duration_since_epoch, plist_to_string}};
1818

1919
use crate::{aps::APSConnectionResource, error::PushError, mmcs::{get_mmcs, prepare_put, put_mmcs, MMCSConfig, Container, DataCacher, PreparedPut}, mmcsp, util::{decode_hex, encode_hex, gzip, plist_to_bin, ungzip}};
2020

@@ -1161,7 +1161,7 @@ struct RequestMMCSUpload {
11611161
v: u64,
11621162
ua: String,
11631163
c: u64,
1164-
i: u32,
1164+
i: i32,
11651165
#[serde(rename = "cV")]
11661166
cv: u32,
11671167
#[serde(rename = "cH")]
@@ -1249,7 +1249,7 @@ impl MMCSFile {
12491249
let mut inputs = vec![(&prepared.mmcs, None, send_container)];
12501250
let (headers, body) = put_authorize_body(&mmcs_config, &inputs);
12511251

1252-
let msg_id = rand::thread_rng().next_u32();
1252+
let msg_id = new_aps_id();
12531253
let complete = RequestMMCSUpload {
12541254
c: 150,
12551255
ua: mmcs_config.mini_ua.clone(),
@@ -1261,9 +1261,8 @@ impl MMCSFile {
12611261
headers: format!("{}\n", headers.into_iter().map(|(k, v)| format!("{}:{}", k, v)).collect::<Vec<_>>().join("\n")),
12621262
body: body.into()
12631263
};
1264-
let binary = plist_to_bin(&complete)?;
12651264
let recv = apns.subscribe().await;
1266-
apns.send_message("com.apple.madrid", binary, Some(msg_id)).await?;
1265+
apns.send_message("com.apple.madrid", complete, Some(msg_id)).await?;
12671266

12681267
let reader = apns.wait_for_timeout(recv, get_message(|loaded| {
12691268
let Some(c) = loaded.as_dictionary().unwrap().get("c") else {
@@ -1272,7 +1271,7 @@ impl MMCSFile {
12721271
let Some(i) = loaded.as_dictionary().unwrap().get("i") else {
12731272
return None
12741273
};
1275-
if c.as_unsigned_integer().unwrap() == 150 && i.as_unsigned_integer().unwrap() as u32 == msg_id {
1274+
if c.as_unsigned_integer().unwrap() == 150 && i.as_signed_integer().unwrap() as i32 == msg_id {
12761275
Some(loaded)
12771276
} else { None }
12781277
}, &["com.apple.madrid"])).await?;
@@ -1311,7 +1310,7 @@ impl MMCSFile {
13111310
v: u64,
13121311
ua: String,
13131312
c: u64,
1314-
i: u32,
1313+
i: i32,
13151314
#[serde(rename = "cH")]
13161315
headers: String,
13171316
#[serde(rename = "mR")]
@@ -1341,7 +1340,7 @@ impl MMCSFile {
13411340
let recieve_container = IMessageContainer::new(&self.key, writer, true);
13421341

13431342
let domain = self.url.replace(&format!("/{}", &self.object), "");
1344-
let msg_id = rand::thread_rng().next_u32();
1343+
let msg_id = new_aps_id();
13451344
let header = format!("x-mme-client-info:{}", mmcs_config.mme_client_info);
13461345
let request_download = RequestMMCSDownload {
13471346
object: self.object.to_string(),
@@ -1363,9 +1362,8 @@ impl MMCSFile {
13631362

13641363
info!("mmcs obj {} sig {}", self.object, encode_hex(&self.signature));
13651364

1366-
let binary = plist_to_bin(&request_download)?;
13671365
let recv = apns.subscribe().await;
1368-
apns.send_message("com.apple.madrid", binary, Some(msg_id)).await?;
1366+
apns.send_message("com.apple.madrid", request_download, Some(msg_id)).await?;
13691367

13701368
let reader = apns.wait_for_timeout(recv, get_message(|loaded| {
13711369
let Some(c) = loaded.as_dictionary().unwrap().get("c") else {
@@ -1374,7 +1372,7 @@ impl MMCSFile {
13741372
let Some(i) = loaded.as_dictionary().unwrap().get("i") else {
13751373
return None
13761374
};
1377-
if c.as_unsigned_integer().unwrap() == 151 && i.as_unsigned_integer().unwrap() as u32 == msg_id {
1375+
if c.as_unsigned_integer().unwrap() == 151 && i.as_signed_integer().unwrap() as i32 == msg_id {
13781376
Some(loaded)
13791377
} else { None }
13801378
}, &["com.apple.madrid"])).await?;

src/sharedstreams.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ impl<P: AnisetteProvider> SharedStreamClient<P> {
567567
}
568568

569569
pub async fn handle(&self, msg: APSMessage) -> Result<Option<Vec<String>>, PushError> {
570-
let APSMessage::Notification { id: _, topic, token: _, payload, channel: _ } = msg else { return Ok(None) };
570+
let APSMessage::Notification { id: _, topic, token: _, payload: Value::Data(payload), channel: _ } = msg else { return Ok(None) };
571571
if topic != sha1("com.apple.sharedstreams".as_bytes()) { return Ok(None) };
572572

573573
#[derive(Deserialize)]

src/statuskit.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use tokio::sync::{broadcast, mpsc};
1616
use uuid::Uuid;
1717
use rand::{rngs::OsRng, RngCore};
1818

19-
use crate::{APSConnection, APSMessage, IdentityManager, OSConfig, PushError, TokenProvider, aps::{APSChannel, APSChannelIdentifier, APSInterestToken, get_message}, ids::{IDSRecvMessage, identity_manager::{IDSSendMessage, Raw}, user::QueryOptions}, util::{DebugMutex, DebugRwLock, base64_decode, base64_encode, decode_hex, encode_hex, plist_to_bin}};
19+
use crate::{APSConnection, APSMessage, IdentityManager, OSConfig, PushError, TokenProvider, aps::{APSChannel, APSChannelIdentifier, APSInterestToken, get_message, new_aps_id}, ids::{IDSRecvMessage, identity_manager::{IDSSendMessage, Raw}, user::QueryOptions}, util::{DebugMutex, DebugRwLock, base64_decode, base64_encode, decode_hex, encode_hex, plist_to_bin}};
2020
use crate::util::{CompactECKey, ec_serialize, ec_serialize_priv, bin_serialize, bin_deserialize, proto_serialize, proto_deserialize, ec_deserialize_priv_compact, ec_deserialize_compact, proto_serialize_vec, proto_deserialize_vec};
2121
use aes_gcm::KeyInit;
2222

@@ -197,7 +197,7 @@ pub struct ManageRequest {
197197
#[serde(rename = "v")]
198198
version: u32,
199199
#[serde(rename = "i")]
200-
id: u32,
200+
id: i32,
201201
#[serde(rename = "U")]
202202
uuid: Data,
203203
}
@@ -419,7 +419,7 @@ impl<T: AnisetteProvider + Send + Sync + 'static> StatusKitClient<T> {
419419

420420
pub async fn send_manage_request<ReqMsg: Message, ResMsg: Message + Default>(&self, request: ReqMsg, command: u8) -> Result<ResMsg, PushError> {
421421
debug!("Sending channel manage request {command}, {request:?}");
422-
let msg_id = rand::thread_rng().next_u32();
422+
let msg_id = new_aps_id();
423423
let req = ManageRequest {
424424
request: request.encode_to_vec().into(),
425425
command,
@@ -431,14 +431,14 @@ impl<T: AnisetteProvider + Send + Sync + 'static> StatusKitClient<T> {
431431
};
432432

433433
let recv = self.conn.subscribe().await;
434-
self.conn.send_message("com.apple.icloud.presence.channel.management", plist_to_bin(&req)?, Some(msg_id)).await?;
434+
self.conn.send_message("com.apple.icloud.presence.channel.management", req, Some(msg_id)).await?;
435435

436436
Ok(ResMsg::decode(Cursor::new(self.conn.wait_for_timeout(recv, get_message(|loaded| {
437437
debug!("Got message {:?}", loaded);
438438
#[derive(Deserialize)]
439439
struct Res {
440440
c: u8,
441-
i: u32,
441+
i: i32,
442442
#[serde(rename = "scRes")]
443443
sc_res: Data,
444444
}
@@ -716,7 +716,7 @@ impl<T: AnisetteProvider + Send + Sync + 'static> StatusKitClient<T> {
716716
}
717717

718718
pub async fn handle(&self, msg: APSMessage) -> Result<Option<StatusKitMessage>, PushError> {
719-
let APSMessage::Notification { id: _, topic, token: _, payload, channel } = msg.clone() else { return Ok(None) };
719+
let APSMessage::Notification { id: _, topic, token: _, payload: Value::Data(payload), channel } = msg.clone() else { return Ok(None) };
720720
if let Some(channel) = &channel {
721721
let mut state = self.state.write().await;
722722
if let Some(local_channel) = state.recent_channels.iter_mut().find(|c| c.identifier.id == channel.id && sha1(c.identifier.topic.as_bytes()) == topic) {

src/util.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2598,3 +2598,45 @@ impl Into<String> for NSURL {
25982598
}
25992599

26002600

2601+
2602+
use std::io;
2603+
2604+
pub trait BinaryReadExt: Read {
2605+
fn read_u8_exact(&mut self) -> io::Result<u8> {
2606+
let mut buf = [0u8; 1];
2607+
self.read_exact(&mut buf)?;
2608+
Ok(buf[0])
2609+
}
2610+
2611+
fn read_u16_le(&mut self) -> io::Result<u16> {
2612+
let mut buf = [0u8; 2];
2613+
self.read_exact(&mut buf)?;
2614+
Ok(u16::from_le_bytes(buf))
2615+
}
2616+
2617+
fn read_u16_be(&mut self) -> io::Result<u16> {
2618+
let mut buf = [0u8; 2];
2619+
self.read_exact(&mut buf)?;
2620+
Ok(u16::from_be_bytes(buf))
2621+
}
2622+
2623+
fn read_u32_le(&mut self) -> io::Result<u32> {
2624+
let mut buf = [0u8; 4];
2625+
self.read_exact(&mut buf)?;
2626+
Ok(u32::from_le_bytes(buf))
2627+
}
2628+
2629+
fn read_u32_be(&mut self) -> io::Result<u32> {
2630+
let mut buf = [0u8; 4];
2631+
self.read_exact(&mut buf)?;
2632+
Ok(u32::from_be_bytes(buf))
2633+
}
2634+
2635+
fn read_n(&mut self, n: usize) -> io::Result<Vec<u8>> {
2636+
let mut buf = vec![0u8; n];
2637+
self.read_exact(&mut buf)?;
2638+
Ok(buf)
2639+
}
2640+
}
2641+
2642+
impl<R: Read + ?Sized> BinaryReadExt for R {}

0 commit comments

Comments
 (0)