fix: encryption and sync spam

next
Timo Kösters 2020-09-17 22:41:43 +02:00
parent 8bcfff2766
commit 267c721616
No known key found for this signature in database
GPG Key ID: 24DA7517711A2BA4
3 changed files with 67 additions and 44 deletions

View File

@ -100,47 +100,61 @@ pub async fn sync_events_route(
limited = true; limited = true;
} }
// Database queries:
let encrypted_room = db let encrypted_room = db
.rooms .rooms
.room_state_get(&room_id, &EventType::RoomEncryption, "")? .room_state_get(&room_id, &EventType::RoomEncryption, "")?
.is_some(); .is_some();
// Database queries: // These type is Option<Option<_>>. The outer Option is None when there is no event between
// since and the current room state, meaning there should be no updates.
// The inner Option is None when there is an event, but there is no state hash associated
// with it. This can happen for the RoomCreate event, so all updates should arrive.
let since_state_hash = db let since_state_hash = db
.rooms .rooms
.pdus_until(sender_id, &room_id, since) .pdus_after(sender_id, &room_id, since) // - 1 So we can get the event at since
.next() .next()
.and_then(|pdu| pdu.ok()) .map(|pdu| db.rooms.pdu_state_hash(&pdu.ok()?.0).ok()?);
.and_then(|pdu| db.rooms.pdu_state_hash(&pdu.0).ok()?);
let since_members = since_state_hash let since_members = since_state_hash.as_ref().map(|state_hash| {
.as_ref() state_hash.as_ref().and_then(|state_hash| {
.and_then(|state_hash| db.rooms.state_type(state_hash, &EventType::RoomMember).ok()); db.rooms
.state_type(&state_hash, &EventType::RoomMember)
.ok()
})
});
let since_encryption = since_state_hash.as_ref().and_then(|state_hash| { let since_encryption = since_state_hash.as_ref().map(|state_hash| {
db.rooms state_hash.as_ref().and_then(|state_hash| {
.state_get(&state_hash, &EventType::RoomEncryption, "") db.rooms
.ok() .state_get(&state_hash, &EventType::RoomEncryption, "")
.ok()
})
}); });
let current_members = db.rooms.room_state_type(&room_id, &EventType::RoomMember)?; let current_members = db.rooms.room_state_type(&room_id, &EventType::RoomMember)?;
// Calculations: // Calculations:
let new_encrypted_room = encrypted_room && since_encryption.is_none(); let new_encrypted_room =
encrypted_room && since_encryption.map_or(false, |encryption| encryption.is_none());
let send_member_count = since_members.as_ref().map_or(true, |since_members| { let send_member_count = since_members.as_ref().map_or(false, |since_members| {
current_members.len() != since_members.len() since_members.as_ref().map_or(true, |since_members| {
current_members.len() != since_members.len()
})
}); });
let since_sender_member = since_members.as_ref().and_then(|members| { let since_sender_member = since_members.as_ref().map(|since_members| {
members.get(sender_id.as_str()).and_then(|pdu| { since_members.as_ref().and_then(|members| {
serde_json::from_value::<Raw<ruma::events::room::member::MemberEventContent>>( members.get(sender_id.as_str()).and_then(|pdu| {
pdu.content.clone(), serde_json::from_value::<Raw<ruma::events::room::member::MemberEventContent>>(
) pdu.content.clone(),
.expect("Raw::from_value always works") )
.deserialize() .expect("Raw::from_value always works")
.map_err(|_| Error::bad_database("Invalid PDU in database.")) .deserialize()
.ok() .map_err(|_| Error::bad_database("Invalid PDU in database."))
.ok()
})
}) })
}); });
@ -154,20 +168,29 @@ pub async fn sync_events_route(
.map_err(|_| Error::bad_database("Invalid PDU in database."))? .map_err(|_| Error::bad_database("Invalid PDU in database."))?
.membership; .membership;
let since_membership = since_members let since_membership =
.as_ref() since_members
.and_then(|members| { .as_ref()
members.get(&user_id).and_then(|since_member| { .map_or(MembershipState::Join, |members| {
serde_json::from_value::< members
Raw<ruma::events::room::member::MemberEventContent>, .as_ref()
>(since_member.content.clone()) .and_then(|members| {
.expect("Raw::from_value always works") members.get(&user_id).and_then(|since_member| {
.deserialize() serde_json::from_value::<
.map_err(|_| Error::bad_database("Invalid PDU in database.")) Raw<ruma::events::room::member::MemberEventContent>,
.ok() >(
}) since_member.content.clone()
}) )
.map_or(MembershipState::Leave, |member| member.membership); .expect("Raw::from_value always works")
.deserialize()
.map_err(|_| {
Error::bad_database("Invalid PDU in database.")
})
.ok()
})
})
.map_or(MembershipState::Leave, |member| member.membership)
});
let user_id = UserId::try_from(user_id) let user_id = UserId::try_from(user_id)
.map_err(|_| Error::bad_database("Invalid UserId in member PDU."))?; .map_err(|_| Error::bad_database("Invalid UserId in member PDU."))?;
@ -188,8 +211,9 @@ pub async fn sync_events_route(
} }
} }
let joined_since_last_sync = let joined_since_last_sync = since_sender_member.map_or(false, |member| {
since_sender_member.map_or(true, |member| member.membership != MembershipState::Join); member.map_or(true, |member| member.membership != MembershipState::Join)
});
if joined_since_last_sync && encrypted_room || new_encrypted_room { if joined_since_last_sync && encrypted_room || new_encrypted_room {
// If the user is in a new encrypted room, give them all joined users // If the user is in a new encrypted room, give them all joined users
@ -434,7 +458,7 @@ pub async fn sync_events_route(
let since_member = db let since_member = db
.rooms .rooms
.pdus_until(sender_id, &room_id, since) .pdus_after(sender_id, &room_id, since)
.next() .next()
.and_then(|pdu| pdu.ok()) .and_then(|pdu| pdu.ok())
.and_then(|pdu| { .and_then(|pdu| {
@ -581,7 +605,7 @@ pub async fn sync_events_route(
changed: device_list_updates.into_iter().collect(), changed: device_list_updates.into_iter().collect(),
left: device_list_left.into_iter().collect(), left: device_list_left.into_iter().collect(),
}, },
device_one_time_keys_count: if db.users.last_one_time_keys_update(sender_id)? > since { device_one_time_keys_count: if db.users.last_one_time_keys_update(sender_id)? > since || since == 0 {
db.users.count_one_time_keys(sender_id, device_id)? db.users.count_one_time_keys(sender_id, device_id)?
} else { } else {
BTreeMap::new() BTreeMap::new()

View File

@ -521,8 +521,7 @@ impl Rooms {
if let Some(old_state_hash) = self.roomid_statehash.get(new_pdu.room_id.as_bytes())? { if let Some(old_state_hash) = self.roomid_statehash.get(new_pdu.room_id.as_bytes())? {
// Store state for event. The state does not include the event itself. // Store state for event. The state does not include the event itself.
// Instead it's the state before the pdu, so the room's old state. // Instead it's the state before the pdu, so the room's old state.
self.pduid_statehash self.pduid_statehash.insert(new_pdu_id, &old_state_hash)?;
.insert(new_pdu_id, &old_state_hash)?;
if new_pdu.state_key.is_none() { if new_pdu.state_key.is_none() {
return Ok(old_state_hash); return Ok(old_state_hash);
} }

View File

@ -603,7 +603,7 @@ impl Users {
.room_state_get(&room_id, &EventType::RoomEncryption, "")? .room_state_get(&room_id, &EventType::RoomEncryption, "")?
.is_none() .is_none()
{ {
return Ok(()); continue;
} }
let mut key = room_id.to_string().as_bytes().to_vec(); let mut key = room_id.to_string().as_bytes().to_vec();