Add missing documentation to peerstate.rs

This commit is contained in:
link2xt
2023-01-23 14:50:47 +00:00
parent 37f20c6889
commit 800125c7a9

View File

@@ -1,7 +1,5 @@
//! # [Autocrypt Peer State](https://autocrypt.org/level1.html#peer-state-management) module.
#![allow(missing_docs)]
use std::collections::HashSet;
use anyhow::{Context as _, Error, Result};
@@ -20,40 +18,81 @@ use crate::mimeparser::SystemMessage;
use crate::sql::Sql;
use crate::stock_str;
/// Type of the public key stored inside the peerstate.
#[derive(Debug)]
pub enum PeerstateKeyType {
/// Pubilc key sent in the `Autocrypt-Gossip` header.
GossipKey,
/// Public key sent in the `Autocrypt` header.
PublicKey,
}
/// Verification status of the contact peerstate.
#[derive(Debug, PartialEq, Eq, Clone, Copy, FromPrimitive)]
#[repr(u8)]
pub enum PeerstateVerifiedStatus {
/// Peerstate is not verified.
Unverified = 0,
//Verified = 1, // not used
/// Peerstate is verified and we assume that the contact has verified our peerstate.
BidirectVerified = 2,
}
/// Peerstate represents the state of an Autocrypt peer.
#[derive(Debug, PartialEq, Eq)]
pub struct Peerstate {
/// E-mail address of the contact.
pub addr: String,
/// Timestamp of the latest peerstate update.
///
/// Updated when a message is received from a contact,
/// either with or without `Autocrypt` header.
pub last_seen: i64,
/// Timestamp of the latest `Autocrypt` header reception.
pub last_seen_autocrypt: i64,
/// Encryption preference of the contact.
pub prefer_encrypt: EncryptPreference,
/// Public key of the contact received in `Autocrypt` header.
pub public_key: Option<SignedPublicKey>,
/// Fingerprint of the contact public key.
pub public_key_fingerprint: Option<Fingerprint>,
/// Public key of the contact received in `Autocrypt-Gossip` header.
pub gossip_key: Option<SignedPublicKey>,
/// Timestamp of the latest `Autocrypt-Gossip` header reception.
///
/// It is stored to avoid applying outdated gossiped key
/// from delayed or reordered messages.
pub gossip_timestamp: i64,
/// Fingerprint of the contact gossip key.
pub gossip_key_fingerprint: Option<Fingerprint>,
/// Public key of the contact at the time it was verified,
/// either directly or via gossip from the verified contact.
pub verified_key: Option<SignedPublicKey>,
/// Fingerprint of the verified public key.
pub verified_key_fingerprint: Option<Fingerprint>,
/// True if it was detected
/// that the fingerprint of the key used in chats with
/// opportunistic encryption was changed after Peerstate creation.
pub fingerprint_changed: bool,
/// The address that verified this contact
pub verifier: Option<String>,
}
impl Peerstate {
/// Creates a peerstate from the `Autocrypt` header.
pub fn from_header(header: &Aheader, message_time: i64) -> Self {
Peerstate {
addr: header.addr.clone(),
@@ -72,7 +111,7 @@ impl Peerstate {
}
}
/// Create peerstate from gossip
/// Create a peerstate from the `Autocrypt-Gossip` header.
pub fn from_gossip(gossip_header: &Aheader, message_time: i64) -> Self {
Peerstate {
addr: gossip_header.addr.clone(),
@@ -98,6 +137,7 @@ impl Peerstate {
}
}
/// Loads peerstate corresponding to the given address from the database.
pub async fn from_addr(context: &Context, addr: &str) -> Result<Option<Peerstate>> {
let query = "SELECT addr, last_seen, last_seen_autocrypt, prefer_encrypted, public_key, \
gossip_timestamp, gossip_key, public_key_fingerprint, gossip_key_fingerprint, \
@@ -107,6 +147,7 @@ impl Peerstate {
Self::from_stmt(context, query, paramsv![addr]).await
}
/// Loads peerstate corresponding to the given fingerprint from the database.
pub async fn from_fingerprint(
context: &Context,
fingerprint: &Fingerprint,
@@ -122,6 +163,10 @@ impl Peerstate {
Self::from_stmt(context, query, paramsv![fp, fp, fp]).await
}
/// Loads peerstate by address or verified fingerprint.
///
/// If the address is different but verified fingerprint is the same,
/// peerstate with corresponding verified fingerprint is preferred.
pub async fn from_verified_fingerprint_or_addr(
context: &Context,
fingerprint: &Fingerprint,
@@ -231,11 +276,15 @@ impl Peerstate {
}
}
/// Reset Autocrypt peerstate.
///
/// Used when it is detected that the contact no longer uses Autocrypt.
pub fn degrade_encryption(&mut self, message_time: i64) {
self.prefer_encrypt = EncryptPreference::Reset;
self.last_seen = message_time;
}
/// Updates peerstate according to the given `Autocrypt` header.
pub fn apply_header(&mut self, header: &Aheader, message_time: i64) {
if !addr_cmp(&self.addr, &header.addr) {
return;
@@ -258,6 +307,7 @@ impl Peerstate {
}
}
/// Updates peerstate according to the given `Autocrypt-Gossip` header.
pub fn apply_gossip(&mut self, gossip_header: &Aheader, message_time: i64) {
if self.addr.to_lowercase() != gossip_header.addr.to_lowercase() {
return;
@@ -290,6 +340,7 @@ impl Peerstate {
};
}
/// Returns the contents of the `Autocrypt-Gossip` header for outgoing messages.
pub fn render_gossip_header(&self, min_verified: PeerstateVerifiedStatus) -> Option<String> {
if let Some(key) = self.peek_key(min_verified) {
let header = Aheader::new(
@@ -311,6 +362,9 @@ impl Peerstate {
}
}
/// Converts the peerstate into the contact public key.
///
/// Similar to [`Self::peek_key`], but consumes the peerstate and returns owned key.
pub fn take_key(mut self, min_verified: PeerstateVerifiedStatus) -> Option<SignedPublicKey> {
match min_verified {
PeerstateVerifiedStatus::BidirectVerified => self.verified_key.take(),
@@ -320,6 +374,15 @@ impl Peerstate {
}
}
/// Returns a reference to the contact public key.
///
/// `min_verified` determines the minimum required verification status of the key.
/// If verified key is requested, returns the verified key,
/// otherwise returns the Autocrypt key.
///
/// Returned key is suitable for sending in `Autocrypt-Gossip` header.
///
/// Returns `None` if there is no suitable public key.
pub fn peek_key(&self, min_verified: PeerstateVerifiedStatus) -> Option<&SignedPublicKey> {
match min_verified {
PeerstateVerifiedStatus::BidirectVerified => self.verified_key.as_ref(),
@@ -380,6 +443,7 @@ impl Peerstate {
}
}
/// Saves the peerstate to the database.
pub async fn save_to_db(&self, sql: &Sql) -> Result<()> {
sql.execute(
"INSERT INTO acpeerstates (
@@ -428,6 +492,7 @@ impl Peerstate {
Ok(())
}
/// Returns true if verified key is contained in the given set of fingerprints.
pub fn has_verified_key(&self, fingerprints: &HashSet<Fingerprint>) -> bool {
if let Some(vkc) = &self.verified_key_fingerprint {
fingerprints.contains(vkc) && self.verified_key.is_some()