crytpo: Mark verification requests as cancelled and as done

This commit is contained in:
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) {
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);

View file

@ -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<Requested>),
Ready(RequestState<Ready>),
Passive(RequestState<Passive>),
Done(RequestState<Done>),
Cancelled(RequestState<Cancelled>),
}
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<S: Clone> {
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> {
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;