Dadoum commited on 2026-09-28 17:49:52
Showing 2 changed files, with 22 additions and 15 deletions.
| ... | ... |
@@ -17,7 +17,8 @@ let device_data = grandslam::DeviceData {
|
| 17 | 17 |
connection.set_topics(&["com.apple.idmsauth"]).await?; |
| 18 | 18 |
loop {
|
| 19 | 19 |
let notification = connection.receive().await?; |
| 20 |
- // Interpret notification.payload according to its topic. |
|
| 20 |
+ // Accept or store notification.payload according to its topic. |
|
| 21 |
+ connection.acknowledge(¬ification).await?; |
|
| 21 | 22 |
} |
| 22 | 23 |
``` |
| 23 | 24 |
|
| ... | ... |
@@ -39,13 +40,15 @@ signer uses embedded constants and Rust cryptography. |
| 39 | 40 |
|
| 40 | 41 |
## Connection lifetime and persistence |
| 41 | 42 |
|
| 42 |
-`receive` handles notification acknowledgements and ping/pong traffic. Keep it |
|
| 43 |
-running while expecting pushes. There are no hidden background tasks or retry |
|
| 43 |
+`receive` returns notifications and handles ping/pong traffic. Call `acknowledge` |
|
| 44 |
+after accepting or storing each notification; it borrows the notification, so |
|
| 45 |
+an acknowledgement error leaves it available to the caller. Keep calling |
|
| 46 |
+`receive` while expecting pushes. There are no hidden background tasks or retry |
|
| 44 | 47 |
loops. Call `reconnect` after transport failure; it reuses the identity/token |
| 45 | 48 |
and restores the enabled topics. Use `close` to shut down deliberately. A |
| 46 | 49 |
token's existence does not mean a connection is currently reachable. |
| 47 |
-If cancelling `receive` during an acknowledgement or keepalive write, reconnect |
|
| 48 |
-before continuing. |
|
| 50 |
+If cancelling `acknowledge` during its write, or `receive` during a keepalive |
|
| 51 |
+write, reconnect before continuing. |
|
| 49 | 52 |
|
| 50 | 53 |
Persist the device certificate, private key, and latest token together. |
| 51 | 54 |
`PushIdentity::certificate` returns DER bytes; `private_key` exposes the RSA key |
| ... | ... |
@@ -186,8 +186,9 @@ impl PushConnection {
|
| 186 | 186 |
Ok(()) |
| 187 | 187 |
} |
| 188 | 188 |
|
| 189 |
- /// Receives and acknowledges the next notification, driving keepalive while |
|
| 190 |
- /// waiting. Reconnect after errors or cancellation during a protocol write. |
|
| 189 |
+ /// Receives the next notification, driving keepalive while waiting. |
|
| 190 |
+ /// Call `acknowledge` once the notification is accepted or stored. |
|
| 191 |
+ /// Reconnect after errors or cancellation during a keepalive write. |
|
| 191 | 192 |
pub async fn receive(&mut self) -> Result<Notification, CourierError> {
|
| 192 | 193 |
loop {
|
| 193 | 194 |
let deadline = self.pong_deadline.unwrap_or(self.next_ping); |
| ... | ... |
@@ -216,14 +217,6 @@ impl PushConnection {
|
| 216 | 217 |
if token != self.token.as_bytes() {
|
| 217 | 218 |
return Err(CourierError::TokenMismatch); |
| 218 | 219 |
} |
| 219 |
- // Validate the payload before acknowledging it. |
|
| 220 |
- frame.required(3)?; |
|
| 221 |
- Message::Ack {
|
|
| 222 |
- token: &self.token, |
|
| 223 |
- id, |
|
| 224 |
- } |
|
| 225 |
- .write(&mut self.stream) |
|
| 226 |
- .await?; |
|
| 227 | 220 |
return Ok(Notification {
|
| 228 | 221 |
id, |
| 229 | 222 |
topic, |
| ... | ... |
@@ -240,6 +233,17 @@ impl PushConnection {
|
| 240 | 233 |
} |
| 241 | 234 |
} |
| 242 | 235 |
|
| 236 |
+ /// Acknowledges receipt of a notification returned by this connection. |
|
| 237 |
+ /// Reconnect after errors or cancellation during the write. |
|
| 238 |
+ pub async fn acknowledge(&mut self, notification: &Notification) -> Result<(), CourierError> {
|
|
| 239 |
+ Message::Ack {
|
|
| 240 |
+ token: &self.token, |
|
| 241 |
+ id: notification.id, |
|
| 242 |
+ } |
|
| 243 |
+ .write(&mut self.stream) |
|
| 244 |
+ .await |
|
| 245 |
+ } |
|
| 246 |
+ |
|
| 243 | 247 |
pub async fn close(mut self) -> io::Result<()> {
|
| 244 | 248 |
timeout(TIMEOUT, self.stream.shutdown()) |
| 245 | 249 |
.await |
| 246 | 250 |