crytpo: Mark verification requests as cancelled and as done

master
Damir Jelić 2021-06-04 17:07:11 +02:00
parent f9fb530480
commit 0a7fb2cbc3
2 changed files with 99 additions and 4 deletions

View File

@ -208,6 +208,8 @@ impl VerificationMachine {
} }
pub fn garbage_collect(&self) { pub fn garbage_collect(&self) {
self.requests.retain(|_, r| !(r.is_done() || r.is_cancelled()));
for request in self.verifications.garbage_collect() { for request in self.verifications.garbage_collect() {
self.verifications.add_request(request) self.verifications.add_request(request)
} }
@ -286,7 +288,11 @@ impl VerificationMachine {
self.requests.insert(request.flow_id().as_str().to_owned(), request); 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()) { if let Some(sas) = self.verifications.get_sas(flow_id.as_str()) {
// This won't produce an outgoing content // This won't produce an outgoing content
let _ = sas.receive_any_event(event.sender(), &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()) { if let Some(s) = self.verifications.get_sas(flow_id.as_str()) {
let content = s.receive_any_event(event.sender(), &content); let content = s.receive_any_event(event.sender(), &content);

View File

@ -20,6 +20,7 @@ use matrix_sdk_common::{
api::r0::to_device::DeviceIdOrAllDevices, api::r0::to_device::DeviceIdOrAllDevices,
events::{ events::{
key::verification::{ key::verification::{
cancel::CancelCode,
ready::{ReadyEventContent, ReadyToDeviceEventContent}, ready::{ReadyEventContent, ReadyToDeviceEventContent},
request::RequestToDeviceEventContent, request::RequestToDeviceEventContent,
start::StartMethod, start::StartMethod,
@ -35,9 +36,11 @@ use matrix_sdk_common::{
use tracing::{info, warn}; use tracing::{info, warn};
use super::{ use super::{
event_enums::{OutgoingContent, ReadyContent, RequestContent, StartContent}, event_enums::{
CancelContent, DoneContent, OutgoingContent, ReadyContent, RequestContent, StartContent,
},
sas::content_to_request, sas::content_to_request,
FlowId, VerificationCache, Cancelled, FlowId, VerificationCache,
}; };
use crate::{ use crate::{
olm::{PrivateCrossSigningIdentity, ReadOnlyAccount}, olm::{PrivateCrossSigningIdentity, ReadOnlyAccount},
@ -159,6 +162,17 @@ impl VerificationRequest {
&self.flow_id &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( pub(crate) fn from_request(
cache: VerificationCache, cache: VerificationCache,
account: ReadOnlyAccount, account: ReadOnlyAccount,
@ -230,6 +244,20 @@ impl VerificationRequest {
Ok(()) 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. /// Is the verification request ready to start a verification flow.
pub fn is_ready(&self) -> bool { pub fn is_ready(&self) -> bool {
matches!(&*self.inner.lock().unwrap(), InnerRequest::Ready(_)) matches!(&*self.inner.lock().unwrap(), InnerRequest::Ready(_))
@ -267,6 +295,8 @@ enum InnerRequest {
Requested(RequestState<Requested>), Requested(RequestState<Requested>),
Ready(RequestState<Ready>), Ready(RequestState<Ready>),
Passive(RequestState<Passive>), Passive(RequestState<Passive>),
Done(RequestState<Done>),
Cancelled(RequestState<Cancelled>),
} }
impl InnerRequest { impl InnerRequest {
@ -278,6 +308,8 @@ impl InnerRequest {
DeviceIdOrAllDevices::DeviceId(r.state.other_device_id.to_owned()) DeviceIdOrAllDevices::DeviceId(r.state.other_device_id.to_owned())
} }
InnerRequest::Passive(_) => DeviceIdOrAllDevices::AllDevices, 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::Requested(s) => &s.other_user_id,
InnerRequest::Ready(s) => &s.other_user_id, InnerRequest::Ready(s) => &s.other_user_id,
InnerRequest::Passive(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( fn to_started_sas(
&self, &self,
content: &StartContent, content: &StartContent,
@ -330,6 +386,32 @@ struct RequestState<S: Clone> {
state: S, state: S,
} }
impl<S: Clone> RequestState<S> {
fn into_done(self, _: &DoneContent) -> RequestState<Done> {
RequestState::<Done> {
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<Cancelled> {
RequestState::<Cancelled> {
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<Created> { impl RequestState<Created> {
fn new( fn new(
account: ReadOnlyAccount, account: ReadOnlyAccount,
@ -587,6 +669,9 @@ struct Passive {
pub flow_id: FlowId, pub flow_id: FlowId,
} }
#[derive(Clone, Debug)]
struct Done {}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use std::convert::TryFrom; use std::convert::TryFrom;