diff --git a/src/async_client.rs b/src/async_client.rs index 8dc8b1fd..f74e469e 100644 --- a/src/async_client.rs +++ b/src/async_client.rs @@ -375,7 +375,7 @@ impl AsyncClient { timeout: sync_settings.timeout, }; - let response = self.send(request).await?; + let mut response = self.send(request).await?; for (room_id, room) in &response.rooms.join { let room_id = room_id.to_string(); @@ -418,7 +418,7 @@ impl AsyncClient { } let mut client = self.base_client.write().await; - client.receive_sync_response(&response); + client.receive_sync_response(&mut response).await; Ok(response) } diff --git a/src/base_client.rs b/src/base_client.rs index 0cbc7170..a6283902 100644 --- a/src/base_client.rs +++ b/src/base_client.rs @@ -294,8 +294,20 @@ impl Client { /// # Arguments /// /// * `response` - The response that we received after a successful sync. - pub fn receive_sync_response(&mut self, response: &api::sync::sync_events::IncomingResponse) { + pub async fn receive_sync_response( + &mut self, + response: &mut api::sync::sync_events::IncomingResponse, + ) { self.sync_token = Some(response.next_batch.clone()); + + #[cfg(feature = "encryption")] + { + let olm = self.olm.lock().await; + + if let Some(o) = &*olm { + o.receive_sync_response(response); + } + } } /// Should account or one-time keys be uploaded to the server. diff --git a/src/crypto/machine.rs b/src/crypto/machine.rs index 5419425a..f2a5e830 100644 --- a/src/crypto/machine.rs +++ b/src/crypto/machine.rs @@ -29,7 +29,11 @@ use serde_json::Value; use ruma_client_api::r0::keys::{ AlgorithmAndDeviceId, DeviceKeys, KeyAlgorithm, OneTimeKey, SignedKey, }; -use ruma_events::Algorithm; +use ruma_client_api::r0::sync::sync_events::IncomingResponse as SyncResponse; +use ruma_events::{ + to_device::{ToDevice as ToDeviceEvent, ToDeviceEncrypted, ToDeviceRoomKeyRequest}, + Algorithm, EventResult, +}; use ruma_identifiers::{DeviceId, UserId}; pub type OneTimeKeys = HashMap; @@ -311,6 +315,54 @@ impl OlmMachine { Ok((device_keys, one_time_keys)) } + + /// Decrypt a to-device event. + /// + /// Returns a decrypted `ToDeviceEvent` if the decryption was successful, + /// an error indicating why decryption failed otherwise. + /// + /// # Arguments + /// + /// * `event` - The to-device event that should be decrypted. + fn decrypt_to_device_event(&self, _: &ToDeviceEncrypted) -> Result { + Err(()) + } + + fn handle_room_key_request(&self, _: &ToDeviceRoomKeyRequest) { + // TODO handle room key requests here. + } + + fn handle_verification_event(&self, _: &ToDeviceEvent) { + // TODO handle to-device verification events here. + } + + pub fn receive_sync_response(&self, response: &mut SyncResponse) { + for event in response.to_device.events.iter() { + let event = if let EventResult::Ok(e) = event { + e + } else { + // Skip invalid events. + // TODO log here + continue; + }; + + match event { + ToDeviceEvent::RoomEncrypted(e) => { + // TODO put the decrypted event into a vec so we can replace + // them in the sync response. + let _ = self.decrypt_to_device_event(e); + } + ToDeviceEvent::RoomKeyRequest(e) => self.handle_room_key_request(e), + ToDeviceEvent::KeyVerificationAccept(..) + | ToDeviceEvent::KeyVerificationCancel(..) + | ToDeviceEvent::KeyVerificationKey(..) + | ToDeviceEvent::KeyVerificationMac(..) + | ToDeviceEvent::KeyVerificationRequest(..) + | ToDeviceEvent::KeyVerificationStart(..) => self.handle_verification_event(event), + _ => continue, + } + } + } } #[cfg(test)]