From 0a7fb2cbc39150adcd2fcfb483d097b2a991507f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Fri, 4 Jun 2021 17:07:11 +0200 Subject: [PATCH] crytpo: Mark verification requests as cancelled and as done --- matrix_sdk_crypto/src/verification/machine.rs | 14 ++- .../src/verification/requests.rs | 89 ++++++++++++++++++- 2 files changed, 99 insertions(+), 4 deletions(-) diff --git a/matrix_sdk_crypto/src/verification/machine.rs b/matrix_sdk_crypto/src/verification/machine.rs index 275d9780..7bb65086 100644 --- a/matrix_sdk_crypto/src/verification/machine.rs +++ b/matrix_sdk_crypto/src/verification/machine.rs @@ -208,6 +208,8 @@ impl VerificationMachine { } pub fn garbage_collect(&self) { + self.requests.retain(|_, r| !(r.is_done() || r.is_cancelled())); + for request in self.verifications.garbage_collect() { self.verifications.add_request(request) } @@ -286,7 +288,11 @@ impl VerificationMachine { self.requests.insert(request.flow_id().as_str().to_owned(), request); } - AnyVerificationContent::Cancel(_) => { + AnyVerificationContent::Cancel(c) => { + if let Some(verification) = self.get_request(flow_id.as_str()) { + verification.receive_cancel(event.sender(), c); + } + if let Some(sas) = self.verifications.get_sas(flow_id.as_str()) { // This won't produce an outgoing content let _ = sas.receive_any_event(event.sender(), &content); @@ -368,7 +374,11 @@ impl VerificationMachine { } } } - AnyVerificationContent::Done(_) => { + AnyVerificationContent::Done(c) => { + if let Some(verification) = self.get_request(flow_id.as_str()) { + verification.receive_done(event.sender(), c); + } + if let Some(s) = self.verifications.get_sas(flow_id.as_str()) { let content = s.receive_any_event(event.sender(), &content); diff --git a/matrix_sdk_crypto/src/verification/requests.rs b/matrix_sdk_crypto/src/verification/requests.rs index d8e723cf..01576585 100644 --- a/matrix_sdk_crypto/src/verification/requests.rs +++ b/matrix_sdk_crypto/src/verification/requests.rs @@ -20,6 +20,7 @@ use matrix_sdk_common::{ api::r0::to_device::DeviceIdOrAllDevices, events::{ key::verification::{ + cancel::CancelCode, ready::{ReadyEventContent, ReadyToDeviceEventContent}, request::RequestToDeviceEventContent, start::StartMethod, @@ -35,9 +36,11 @@ use matrix_sdk_common::{ use tracing::{info, warn}; use super::{ - event_enums::{OutgoingContent, ReadyContent, RequestContent, StartContent}, + event_enums::{ + CancelContent, DoneContent, OutgoingContent, ReadyContent, RequestContent, StartContent, + }, sas::content_to_request, - FlowId, VerificationCache, + Cancelled, FlowId, VerificationCache, }; use crate::{ olm::{PrivateCrossSigningIdentity, ReadOnlyAccount}, @@ -159,6 +162,17 @@ impl VerificationRequest { &self.flow_id } + /// Has the verification flow that was started with this request finished. + pub fn is_done(&self) -> bool { + matches!(&*self.inner.lock().unwrap(), InnerRequest::Done(_)) + } + + /// Has the verification flow that was started with this request been + /// cancelled. + pub fn is_cancelled(&self) -> bool { + matches!(&*self.inner.lock().unwrap(), InnerRequest::Cancelled(_)) + } + pub(crate) fn from_request( cache: VerificationCache, account: ReadOnlyAccount, @@ -230,6 +244,20 @@ impl VerificationRequest { Ok(()) } + pub(crate) fn receive_done(&self, sender: &UserId, content: &DoneContent<'_>) { + if sender == self.other_user() { + let mut inner = self.inner.lock().unwrap().clone(); + inner.into_done(content); + } + } + + pub(crate) fn receive_cancel(&self, sender: &UserId, content: &CancelContent<'_>) { + if sender == self.other_user() { + let mut inner = self.inner.lock().unwrap().clone(); + inner.into_canceled(content.cancel_code()); + } + } + /// Is the verification request ready to start a verification flow. pub fn is_ready(&self) -> bool { matches!(&*self.inner.lock().unwrap(), InnerRequest::Ready(_)) @@ -267,6 +295,8 @@ enum InnerRequest { Requested(RequestState), Ready(RequestState), Passive(RequestState), + Done(RequestState), + Cancelled(RequestState), } impl InnerRequest { @@ -278,6 +308,8 @@ impl InnerRequest { DeviceIdOrAllDevices::DeviceId(r.state.other_device_id.to_owned()) } InnerRequest::Passive(_) => DeviceIdOrAllDevices::AllDevices, + InnerRequest::Done(_) => DeviceIdOrAllDevices::AllDevices, + InnerRequest::Cancelled(_) => DeviceIdOrAllDevices::AllDevices, } } @@ -287,6 +319,8 @@ impl InnerRequest { InnerRequest::Requested(s) => &s.other_user_id, InnerRequest::Ready(s) => &s.other_user_id, InnerRequest::Passive(s) => &s.other_user_id, + InnerRequest::Done(s) => &s.other_user_id, + InnerRequest::Cancelled(s) => &s.other_user_id, } } @@ -301,6 +335,28 @@ impl InnerRequest { } } + fn into_done(&mut self, content: &DoneContent) { + *self = InnerRequest::Done(match self { + InnerRequest::Created(s) => s.clone().into_done(content), + InnerRequest::Requested(s) => s.clone().into_done(content), + InnerRequest::Ready(s) => s.clone().into_done(content), + InnerRequest::Passive(s) => s.clone().into_done(content), + InnerRequest::Done(s) => s.clone().into_done(content), + InnerRequest::Cancelled(_) => return, + }) + } + + fn into_canceled(&mut self, cancel_code: &CancelCode) { + *self = InnerRequest::Cancelled(match self { + InnerRequest::Created(s) => s.clone().into_canceled(cancel_code), + InnerRequest::Requested(s) => s.clone().into_canceled(cancel_code), + InnerRequest::Ready(s) => s.clone().into_canceled(cancel_code), + InnerRequest::Passive(s) => s.clone().into_canceled(cancel_code), + InnerRequest::Done(_) => return, + InnerRequest::Cancelled(_) => return, + }) + } + fn to_started_sas( &self, content: &StartContent, @@ -330,6 +386,32 @@ struct RequestState { state: S, } +impl RequestState { + fn into_done(self, _: &DoneContent) -> RequestState { + RequestState:: { + account: self.account, + private_cross_signing_identity: self.private_cross_signing_identity, + verification_cache: self.verification_cache, + store: self.store, + flow_id: self.flow_id, + other_user_id: self.other_user_id, + state: Done {}, + } + } + + fn into_canceled(self, cancel_code: &CancelCode) -> RequestState { + RequestState:: { + account: self.account, + private_cross_signing_identity: self.private_cross_signing_identity, + verification_cache: self.verification_cache, + store: self.store, + flow_id: self.flow_id, + other_user_id: self.other_user_id, + state: Cancelled::new(cancel_code.clone()), + } + } +} + impl RequestState { fn new( account: ReadOnlyAccount, @@ -587,6 +669,9 @@ struct Passive { pub flow_id: FlowId, } +#[derive(Clone, Debug)] +struct Done {} + #[cfg(test)] mod test { use std::convert::TryFrom;