community: every ledger takes its write lock, so the inbox check can no longer land on top of a friend accept
This commit is contained in:
1 parent
07227a90a7
commit
4d03cf849b
6 files changed
+89
-29
No files matched your search
@@ -30,6 +30,7 @@ use serde::{Deserialize, Serialize};
|
||||
use tauri::{Emitter, Manager};
|
||||
|
||||
use crate::inbox::{self, Cargo};
|
||||
use crate::ledger;
|
||||
use crate::persona;
|
||||
use crate::slsk_link;
|
||||
use crate::state::AppState;
|
||||
@@ -114,8 +115,11 @@ fn path(app: &tauri::AppHandle) -> Result<PathBuf, String> {
|
||||
.app_data_dir()
|
||||
.map_err(|e| e.to_string())?
|
||||
.join("freenet")
|
||||
.join("friends.json"))
|
||||
.join(LEDGER_FILE))
|
||||
}
|
||||
/// Both the file the ledger lives in and the key its write lock is taken on.
|
||||
const LEDGER_FILE: &str = "friends.json";
|
||||
|
||||
fn load(app: &tauri::AppHandle) -> Store {
|
||||
path(app)
|
||||
.ok()
|
||||
@@ -294,6 +298,7 @@ async fn start_request(
|
||||
updated_at: now,
|
||||
};
|
||||
deliver(app, &mut rel, Cargo::FriendRequest(req.clone()), encode(REQ_PREFIX, &req)?).await?;
|
||||
let _ledger = ledger::hold(LEDGER_FILE).await;
|
||||
let mut store = load(app);
|
||||
store.relationships.insert(id.clone(), rel);
|
||||
save(app, &store)?;
|
||||
@@ -322,6 +327,7 @@ pub async fn request_by_key(app: &tauri::AppHandle, persona_key: &str) -> Result
|
||||
|
||||
pub async fn accept(app: &tauri::AppHandle, id: &str) -> Result<RelationshipView, String> {
|
||||
let me = my_key(app).await?;
|
||||
let _ledger = ledger::hold(LEDGER_FILE).await;
|
||||
let mut store = load(app);
|
||||
let rel = store.relationships.get_mut(id).ok_or("no such request")?;
|
||||
if rel.request_from_me {
|
||||
@@ -340,6 +346,7 @@ pub async fn accept(app: &tauri::AppHandle, id: &str) -> Result<RelationshipView
|
||||
}
|
||||
|
||||
pub async fn decline(app: &tauri::AppHandle, id: &str) -> Result<RelationshipView, String> {
|
||||
let _ledger = ledger::hold(LEDGER_FILE).await;
|
||||
let mut store = load(app);
|
||||
let rel = store.relationships.get_mut(id).ok_or("no such request")?;
|
||||
let now = now_secs();
|
||||
@@ -355,6 +362,7 @@ pub async fn decline(app: &tauri::AppHandle, id: &str) -> Result<RelationshipVie
|
||||
/// "revoked" — the design's honesty about what a removal can and cannot do.
|
||||
pub async fn remove(app: &tauri::AppHandle, id: &str) -> Result<RelationshipView, String> {
|
||||
let me = my_key(app).await?;
|
||||
let _ledger = ledger::hold(LEDGER_FILE).await;
|
||||
let mut store = load(app);
|
||||
let rel = store.relationships.get_mut(id).ok_or("no such relationship")?;
|
||||
let their = key_of(&rel.their_key)?;
|
||||
@@ -368,7 +376,8 @@ pub async fn remove(app: &tauri::AppHandle, id: &str) -> Result<RelationshipView
|
||||
Ok(v)
|
||||
}
|
||||
|
||||
pub fn forget(app: &tauri::AppHandle, id: &str) -> Result<(), String> {
|
||||
pub async fn forget(app: &tauri::AppHandle, id: &str) -> Result<(), String> {
|
||||
let _ledger = ledger::hold(LEDGER_FILE).await;
|
||||
let mut store = load(app);
|
||||
store.relationships.remove(id);
|
||||
save(app, &store)
|
||||
@@ -444,6 +453,7 @@ async fn store_request(app: &tauri::AppHandle, from: From, req: fr::FriendReques
|
||||
}
|
||||
};
|
||||
let id = b58(&req.relationship_id);
|
||||
let _ledger = ledger::hold(LEDGER_FILE).await;
|
||||
let mut store = load(app);
|
||||
if store.relationships.contains_key(&id) {
|
||||
return;
|
||||
@@ -479,6 +489,7 @@ async fn apply_assertion(app: &tauri::AppHandle, from: From, a: fr::FriendAssert
|
||||
return;
|
||||
}
|
||||
let id = b58(&a.relationship_id);
|
||||
let _ledger = ledger::hold(LEDGER_FILE).await;
|
||||
let mut store = load(app);
|
||||
let Some(rel) = store.relationships.get_mut(&id) else {
|
||||
log::debug!("friends: assertion for an unknown relationship");
|
||||
@@ -533,7 +544,8 @@ async fn apply_assertion(app: &tauri::AppHandle, from: From, a: fr::FriendAssert
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_decline(app: &tauri::AppHandle, from: From, id: &str) {
|
||||
async fn apply_decline(app: &tauri::AppHandle, from: From, id: &str) {
|
||||
let _ledger = ledger::hold(LEDGER_FILE).await;
|
||||
let mut store = load(app);
|
||||
let Some(rel) = store.relationships.get_mut(id) else { return };
|
||||
let sender_ok = match &from {
|
||||
@@ -555,8 +567,8 @@ pub(crate) async fn on_inbox_request(app: &tauri::AppHandle, sender: [u8; 32], r
|
||||
pub(crate) async fn on_inbox_assertion(app: &tauri::AppHandle, sender: [u8; 32], a: fr::FriendAssertion) {
|
||||
apply_assertion(app, From::Inbox(sender), a).await;
|
||||
}
|
||||
pub(crate) fn on_inbox_decline(app: &tauri::AppHandle, sender: [u8; 32], id: [u8; 16]) {
|
||||
apply_decline(app, From::Inbox(sender), &b58(&id));
|
||||
pub(crate) async fn on_inbox_decline(app: &tauri::AppHandle, sender: [u8; 32], id: [u8; 16]) {
|
||||
apply_decline(app, From::Inbox(sender), &b58(&id)).await;
|
||||
}
|
||||
|
||||
/// The event pump hands every private message here after the link proof.
|
||||
@@ -579,7 +591,10 @@ pub fn intercept_pm(app: &tauri::AppHandle, from: &str, message: &str) -> bool {
|
||||
return true;
|
||||
}
|
||||
if let Some(rest) = msg.strip_prefix(DECLINE_PREFIX) {
|
||||
apply_decline(app, From::Pm(from.to_string()), rest.trim());
|
||||
// Its own task like the two above: this now takes the ledger, and an
|
||||
// inline await here deadlocks the event pump.
|
||||
let (app, from, id) = (app.clone(), from.to_string(), rest.trim().to_string());
|
||||
tauri::async_runtime::spawn(async move { apply_decline(&app, From::Pm(from), &id).await });
|
||||
return true;
|
||||
}
|
||||
false
|
||||
@@ -612,6 +627,6 @@ pub async fn friend_remove(app: tauri::AppHandle, id: String) -> Result<Relation
|
||||
remove(&app, &id).await
|
||||
}
|
||||
#[tauri::command]
|
||||
pub fn friend_forget(app: tauri::AppHandle, id: String) -> Result<(), String> {
|
||||
forget(&app, &id)
|
||||
pub async fn friend_forget(app: tauri::AppHandle, id: String) -> Result<(), String> {
|
||||
forget(&app, &id).await
|
||||
}
|
||||
Reference in new issue
Block a user