fix: some compile time errors
Only 174 errors left!
This commit is contained in:
parent
82e7f57b38
commit
057f8364cc
118 changed files with 2139 additions and 2433 deletions
|
@ -1,22 +1,24 @@
|
|||
use ruma::{RoomId, RoomAliasId};
|
||||
|
||||
pub trait Data {
|
||||
/// Creates or updates the alias to the given room id.
|
||||
pub fn set_alias(
|
||||
fn set_alias(
|
||||
alias: &RoomAliasId,
|
||||
room_id: &RoomId
|
||||
) -> Result<()>;
|
||||
|
||||
/// Forgets about an alias. Returns an error if the alias did not exist.
|
||||
pub fn remove_alias(
|
||||
fn remove_alias(
|
||||
alias: &RoomAliasId,
|
||||
) -> Result<()>;
|
||||
|
||||
/// Looks up the roomid for the given alias.
|
||||
pub fn resolve_local_alias(
|
||||
fn resolve_local_alias(
|
||||
alias: &RoomAliasId,
|
||||
) -> Result<()>;
|
||||
|
||||
/// Returns all local aliases that point to the given room
|
||||
pub fn local_aliases_for_room(
|
||||
fn local_aliases_for_room(
|
||||
alias: &RoomAliasId,
|
||||
) -> Result<()>;
|
||||
}
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
mod data;
|
||||
pub use data::Data;
|
||||
|
||||
use crate::service::*;
|
||||
use ruma::{RoomAliasId, RoomId};
|
||||
|
||||
pub struct Service<D: Data> {
|
||||
db: D,
|
||||
}
|
||||
|
||||
impl Service<_> {
|
||||
#[tracing::instrument(skip(self, globals))]
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn set_alias(
|
||||
&self,
|
||||
alias: &RoomAliasId,
|
||||
|
@ -17,7 +16,7 @@ impl Service<_> {
|
|||
self.db.set_alias(alias, room_id)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self, globals))]
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn remove_alias(
|
||||
&self,
|
||||
alias: &RoomAliasId,
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::collections::HashSet;
|
||||
|
||||
pub trait Data {
|
||||
fn get_cached_eventid_authchain<'a>() -> Result<HashSet<u64>>;
|
||||
fn cache_eventid_authchain<'a>(shorteventid: u64, auth_chain: &HashSet<u64>) -> Result<HashSet<u64>>;
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
mod data;
|
||||
use std::{sync::Arc, collections::HashSet};
|
||||
|
||||
pub use data::Data;
|
||||
|
||||
use crate::service::*;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use ruma::RoomId;
|
||||
|
||||
pub trait Data {
|
||||
/// Adds the room to the public room directory
|
||||
fn set_public(room_id: &RoomId) -> Result<()>;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
mod data;
|
||||
pub use data::Data;
|
||||
use ruma::RoomId;
|
||||
|
||||
use crate::service::*;
|
||||
|
||||
|
@ -10,21 +11,21 @@ pub struct Service<D: Data> {
|
|||
impl Service<_> {
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn set_public(&self, room_id: &RoomId) -> Result<()> {
|
||||
self.db.set_public(&self, room_id)
|
||||
self.db.set_public(room_id)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn set_not_public(&self, room_id: &RoomId) -> Result<()> {
|
||||
self.db.set_not_public(&self, room_id)
|
||||
self.db.set_not_public(room_id)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn is_public_room(&self, room_id: &RoomId) -> Result<bool> {
|
||||
self.db.is_public_room(&self, room_id)
|
||||
self.db.is_public_room(room_id)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn public_rooms(&self) -> impl Iterator<Item = Result<Box<RoomId>>> + '_ {
|
||||
self.db.public_rooms(&self, room_id)
|
||||
self.db.public_rooms()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
pub mod presence;
|
||||
pub mod read_receipt;
|
||||
pub mod typing;
|
||||
|
||||
pub struct Service<D> {
|
||||
presence: presence::Service<D>,
|
||||
read_receipt: read_receipt::Service<D>,
|
||||
typing: typing::Service<D>,
|
||||
}
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use ruma::{UserId, RoomId, events::presence::PresenceEvent};
|
||||
|
||||
pub trait Data {
|
||||
/// Adds a presence event which will be saved until a new event replaces it.
|
||||
///
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
mod data;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub use data::Data;
|
||||
use ruma::{RoomId, UserId, events::presence::PresenceEvent};
|
||||
|
||||
use crate::service::*;
|
||||
|
||||
|
@ -108,7 +111,7 @@ impl Service<_> {
|
|||
}*/
|
||||
|
||||
/// Returns the most recent presence updates that happened after the event with id `since`.
|
||||
#[tracing::instrument(skip(self, since, _rooms, _globals))]
|
||||
#[tracing::instrument(skip(self, since, room_id))]
|
||||
pub fn presence_since(
|
||||
&self,
|
||||
room_id: &RoomId,
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use ruma::{RoomId, events::receipt::ReceiptEvent, UserId, serde::Raw};
|
||||
|
||||
pub trait Data {
|
||||
/// Replaces the previous read receipt.
|
||||
fn readreceipt_update(
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
mod data;
|
||||
pub use data::Data;
|
||||
|
||||
use crate::service::*;
|
||||
use ruma::{RoomId, UserId, events::receipt::ReceiptEvent, serde::Raw};
|
||||
|
||||
pub struct Service<D: Data> {
|
||||
db: D,
|
||||
|
@ -15,7 +14,7 @@ impl Service<_> {
|
|||
room_id: &RoomId,
|
||||
event: ReceiptEvent,
|
||||
) -> Result<()> {
|
||||
self.db.readreceipt_update(user_id, room_id, event);
|
||||
self.db.readreceipt_update(user_id, room_id, event)
|
||||
}
|
||||
|
||||
/// Returns an iterator over the most recent read_receipts in a room that happened after the event with id `since`.
|
||||
|
@ -35,7 +34,7 @@ impl Service<_> {
|
|||
}
|
||||
|
||||
/// Sets a private read marker at `count`.
|
||||
#[tracing::instrument(skip(self, globals))]
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn private_read_set(&self, room_id: &RoomId, user_id: &UserId, count: u64) -> Result<()> {
|
||||
self.db.private_read_set(room_id, user_id, count)
|
||||
}
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
use std::collections::HashSet;
|
||||
|
||||
use ruma::{UserId, RoomId};
|
||||
|
||||
pub trait Data {
|
||||
/// Sets a user as typing until the timeout timestamp is reached or roomtyping_remove is
|
||||
/// called.
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
mod data;
|
||||
pub use data::Data;
|
||||
use ruma::{UserId, RoomId};
|
||||
|
||||
use crate::service::*;
|
||||
|
||||
|
@ -66,7 +67,6 @@ impl Service<_> {
|
|||
*/
|
||||
|
||||
/// Returns the count of the last typing update in this room.
|
||||
#[tracing::instrument(skip(self, globals))]
|
||||
pub fn last_typing_update(&self, room_id: &RoomId) -> Result<u64> {
|
||||
self.db.last_typing_update(room_id)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,29 @@
|
|||
|
||||
/// An async function that can recursively call itself.
|
||||
type AsyncRecursiveType<'a, T> = Pin<Box<dyn Future<Output = T> + 'a + Send>>;
|
||||
|
||||
use crate::service::*;
|
||||
use std::{
|
||||
collections::{btree_map, hash_map, BTreeMap, HashMap, HashSet},
|
||||
pin::Pin,
|
||||
sync::{Arc, RwLock},
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
use futures_util::Future;
|
||||
use ruma::{
|
||||
api::{
|
||||
client::error::ErrorKind,
|
||||
federation::event::{get_event, get_room_state_ids},
|
||||
},
|
||||
events::{room::create::RoomCreateEventContent, StateEventType},
|
||||
int,
|
||||
serde::Base64,
|
||||
signatures::CanonicalJsonValue,
|
||||
state_res::{self, RoomVersion, StateMap},
|
||||
uint, EventId, MilliSecondsSinceUnixEpoch, RoomId, ServerName,
|
||||
};
|
||||
use tracing::{error, info, trace, warn};
|
||||
|
||||
use crate::{service::*, services, Error, PduEvent};
|
||||
|
||||
pub struct Service;
|
||||
|
||||
|
@ -31,45 +52,47 @@ impl Service {
|
|||
/// it
|
||||
/// 14. Use state resolution to find new room state
|
||||
// We use some AsyncRecursiveType hacks here so we can call this async funtion recursively
|
||||
#[tracing::instrument(skip(value, is_timeline_event, db, pub_key_map))]
|
||||
#[tracing::instrument(skip(value, is_timeline_event, pub_key_map))]
|
||||
pub(crate) async fn handle_incoming_pdu<'a>(
|
||||
&self,
|
||||
origin: &'a ServerName,
|
||||
event_id: &'a EventId,
|
||||
room_id: &'a RoomId,
|
||||
value: BTreeMap<String, CanonicalJsonValue>,
|
||||
is_timeline_event: bool,
|
||||
db: &'a Database,
|
||||
pub_key_map: &'a RwLock<BTreeMap<String, BTreeMap<String, Base64>>>,
|
||||
) -> Result<Option<Vec<u8>>> {
|
||||
db.rooms.exists(room_id)?.ok_or(Error::BadRequest(ErrorKind::NotFound, "Room is unknown to this server"))?;
|
||||
services().rooms.exists(room_id)?.ok_or(Error::BadRequest(
|
||||
ErrorKind::NotFound,
|
||||
"Room is unknown to this server",
|
||||
))?;
|
||||
|
||||
services()
|
||||
.rooms
|
||||
.is_disabled(room_id)?
|
||||
.ok_or(Error::BadRequest(
|
||||
ErrorKind::Forbidden,
|
||||
"Federation of this room is currently disabled on this server.",
|
||||
))?;
|
||||
|
||||
db.rooms.is_disabled(room_id)?.ok_or(Error::BadRequest(ErrorKind::Forbidden, "Federation of this room is currently disabled on this server."))?;
|
||||
|
||||
// 1. Skip the PDU if we already have it as a timeline event
|
||||
if let Some(pdu_id) = db.rooms.get_pdu_id(event_id)? {
|
||||
return Some(pdu_id.to_vec());
|
||||
if let Some(pdu_id) = services().rooms.get_pdu_id(event_id)? {
|
||||
return Ok(Some(pdu_id.to_vec()));
|
||||
}
|
||||
|
||||
let create_event = db
|
||||
let create_event = services()
|
||||
.rooms
|
||||
.room_state_get(room_id, &StateEventType::RoomCreate, "")?
|
||||
.ok_or_else(|| Error::bad_database("Failed to find create event in db."))?;
|
||||
|
||||
let first_pdu_in_room = db
|
||||
let first_pdu_in_room = services()
|
||||
.rooms
|
||||
.first_pdu_in_room(room_id)?
|
||||
.ok_or_else(|| Error::bad_database("Failed to find first pdu in db."))?;
|
||||
|
||||
let (incoming_pdu, val) = handle_outlier_pdu(
|
||||
origin,
|
||||
&create_event,
|
||||
event_id,
|
||||
room_id,
|
||||
value,
|
||||
db,
|
||||
pub_key_map,
|
||||
)
|
||||
.await?;
|
||||
let (incoming_pdu, val) = self
|
||||
.handle_outlier_pdu(origin, &create_event, event_id, room_id, value, pub_key_map)
|
||||
.await?;
|
||||
|
||||
// 8. if not timeline event: stop
|
||||
if !is_timeline_event {
|
||||
|
@ -82,15 +105,27 @@ impl Service {
|
|||
}
|
||||
|
||||
// 9. Fetch any missing prev events doing all checks listed here starting at 1. These are timeline events
|
||||
let sorted_prev_events = fetch_unknown_prev_events(incoming_pdu.prev_events.clone());
|
||||
let (sorted_prev_events, eventid_info) = self.fetch_unknown_prev_events(
|
||||
origin,
|
||||
&create_event,
|
||||
room_id,
|
||||
pub_key_map,
|
||||
incoming_pdu.prev_events.clone(),
|
||||
);
|
||||
|
||||
let mut errors = 0;
|
||||
for prev_id in dbg!(sorted) {
|
||||
for prev_id in dbg!(sorted_prev_events) {
|
||||
// Check for disabled again because it might have changed
|
||||
db.rooms.is_disabled(room_id)?.ok_or(Error::BadRequest(ErrorKind::Forbidden, "Federation of
|
||||
this room is currently disabled on this server."))?;
|
||||
services()
|
||||
.rooms
|
||||
.is_disabled(room_id)?
|
||||
.ok_or(Error::BadRequest(
|
||||
ErrorKind::Forbidden,
|
||||
"Federation of
|
||||
this room is currently disabled on this server.",
|
||||
))?;
|
||||
|
||||
if let Some((time, tries)) = db
|
||||
if let Some((time, tries)) = services()
|
||||
.globals
|
||||
.bad_event_ratelimiter
|
||||
.read()
|
||||
|
@ -120,26 +155,27 @@ impl Service {
|
|||
}
|
||||
|
||||
let start_time = Instant::now();
|
||||
db.globals
|
||||
services()
|
||||
.globals
|
||||
.roomid_federationhandletime
|
||||
.write()
|
||||
.unwrap()
|
||||
.insert(room_id.to_owned(), ((*prev_id).to_owned(), start_time));
|
||||
|
||||
if let Err(e) = upgrade_outlier_to_timeline_pdu(
|
||||
pdu,
|
||||
json,
|
||||
&create_event,
|
||||
origin,
|
||||
db,
|
||||
room_id,
|
||||
pub_key_map,
|
||||
)
|
||||
.await
|
||||
if let Err(e) = self
|
||||
.upgrade_outlier_to_timeline_pdu(
|
||||
pdu,
|
||||
json,
|
||||
&create_event,
|
||||
origin,
|
||||
room_id,
|
||||
pub_key_map,
|
||||
)
|
||||
.await
|
||||
{
|
||||
errors += 1;
|
||||
warn!("Prev event {} failed: {}", prev_id, e);
|
||||
match db
|
||||
match services()
|
||||
.globals
|
||||
.bad_event_ratelimiter
|
||||
.write()
|
||||
|
@ -155,7 +191,8 @@ impl Service {
|
|||
}
|
||||
}
|
||||
let elapsed = start_time.elapsed();
|
||||
db.globals
|
||||
services()
|
||||
.globals
|
||||
.roomid_federationhandletime
|
||||
.write()
|
||||
.unwrap()
|
||||
|
@ -172,22 +209,23 @@ impl Service {
|
|||
// Done with prev events, now handling the incoming event
|
||||
|
||||
let start_time = Instant::now();
|
||||
db.globals
|
||||
services()
|
||||
.globals
|
||||
.roomid_federationhandletime
|
||||
.write()
|
||||
.unwrap()
|
||||
.insert(room_id.to_owned(), (event_id.to_owned(), start_time));
|
||||
let r = upgrade_outlier_to_timeline_pdu(
|
||||
let r = services().rooms.event_handler.upgrade_outlier_to_timeline_pdu(
|
||||
incoming_pdu,
|
||||
val,
|
||||
&create_event,
|
||||
origin,
|
||||
db,
|
||||
room_id,
|
||||
pub_key_map,
|
||||
)
|
||||
.await;
|
||||
db.globals
|
||||
services()
|
||||
.globals
|
||||
.roomid_federationhandletime
|
||||
.write()
|
||||
.unwrap()
|
||||
|
@ -196,22 +234,23 @@ impl Service {
|
|||
r
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(create_event, value, db, pub_key_map))]
|
||||
#[tracing::instrument(skip(create_event, value, pub_key_map))]
|
||||
fn handle_outlier_pdu<'a>(
|
||||
&self,
|
||||
origin: &'a ServerName,
|
||||
create_event: &'a PduEvent,
|
||||
event_id: &'a EventId,
|
||||
room_id: &'a RoomId,
|
||||
value: BTreeMap<String, CanonicalJsonValue>,
|
||||
db: &'a Database,
|
||||
pub_key_map: &'a RwLock<BTreeMap<String, BTreeMap<String, Base64>>>,
|
||||
) -> AsyncRecursiveType<'a, Result<(Arc<PduEvent>, BTreeMap<String, CanonicalJsonValue>), String>> {
|
||||
) -> AsyncRecursiveType<'a, Result<(Arc<PduEvent>, BTreeMap<String, CanonicalJsonValue>), String>>
|
||||
{
|
||||
Box::pin(async move {
|
||||
// TODO: For RoomVersion6 we must check that Raw<..> is canonical do we anywhere?: https://matrix.org/docs/spec/rooms/v6#canonical-json
|
||||
|
||||
// We go through all the signatures we see on the value and fetch the corresponding signing
|
||||
// keys
|
||||
fetch_required_signing_keys(&value, pub_key_map, db)
|
||||
self.fetch_required_signing_keys(&value, pub_key_map, db)
|
||||
.await?;
|
||||
|
||||
// 2. Check signatures, otherwise drop
|
||||
|
@ -223,7 +262,8 @@ impl Service {
|
|||
})?;
|
||||
|
||||
let room_version_id = &create_event_content.room_version;
|
||||
let room_version = RoomVersion::new(room_version_id).expect("room version is supported");
|
||||
let room_version =
|
||||
RoomVersion::new(room_version_id).expect("room version is supported");
|
||||
|
||||
let mut val = match ruma::signatures::verify_event(
|
||||
&*pub_key_map.read().map_err(|_| "RwLock is poisoned.")?,
|
||||
|
@ -261,8 +301,7 @@ impl Service {
|
|||
// 5. Reject "due to auth events" if can't get all the auth events or some of the auth events are also rejected "due to auth events"
|
||||
// NOTE: Step 5 is not applied anymore because it failed too often
|
||||
warn!("Fetching auth events for {}", incoming_pdu.event_id);
|
||||
fetch_and_handle_outliers(
|
||||
db,
|
||||
self.fetch_and_handle_outliers(
|
||||
origin,
|
||||
&incoming_pdu
|
||||
.auth_events
|
||||
|
@ -284,7 +323,7 @@ impl Service {
|
|||
// Build map of auth events
|
||||
let mut auth_events = HashMap::new();
|
||||
for id in &incoming_pdu.auth_events {
|
||||
let auth_event = match db.rooms.get_pdu(id)? {
|
||||
let auth_event = match services().rooms.get_pdu(id)? {
|
||||
Some(e) => e,
|
||||
None => {
|
||||
warn!("Could not find auth event {}", id);
|
||||
|
@ -303,8 +342,9 @@ impl Service {
|
|||
v.insert(auth_event);
|
||||
}
|
||||
hash_map::Entry::Occupied(_) => {
|
||||
return Err(Error::BadRequest(ErrorKind::InvalidParam,
|
||||
"Auth event's type and state_key combination exists multiple times."
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::InvalidParam,
|
||||
"Auth event's type and state_key combination exists multiple times.",
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -316,7 +356,10 @@ impl Service {
|
|||
.map(|a| a.as_ref())
|
||||
!= Some(create_event)
|
||||
{
|
||||
return Err(Error::BadRequest(ErrorKind::InvalidParam("Incoming event refers to wrong create event.")));
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::InvalidParam,
|
||||
"Incoming event refers to wrong create event.",
|
||||
));
|
||||
}
|
||||
|
||||
if !state_res::event_auth::auth_check(
|
||||
|
@ -325,15 +368,21 @@ impl Service {
|
|||
None::<PduEvent>, // TODO: third party invite
|
||||
|k, s| auth_events.get(&(k.to_string().into(), s.to_owned())),
|
||||
)
|
||||
.map_err(|e| {error!(e); Error::BadRequest(ErrorKind::InvalidParam, "Auth check failed")})?
|
||||
{
|
||||
return Err(Error::BadRequest(ErrorKind::InvalidParam, "Auth check failed"));
|
||||
.map_err(|e| {
|
||||
error!(e);
|
||||
Error::BadRequest(ErrorKind::InvalidParam, "Auth check failed")
|
||||
})? {
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::InvalidParam,
|
||||
"Auth check failed",
|
||||
));
|
||||
}
|
||||
|
||||
info!("Validation successful.");
|
||||
|
||||
// 7. Persist the event as an outlier.
|
||||
db.rooms
|
||||
services()
|
||||
.rooms
|
||||
.add_pdu_outlier(&incoming_pdu.event_id, &val)?;
|
||||
|
||||
info!("Added pdu as outlier.");
|
||||
|
@ -342,22 +391,22 @@ impl Service {
|
|||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(incoming_pdu, val, create_event, db, pub_key_map))]
|
||||
async fn upgrade_outlier_to_timeline_pdu(
|
||||
#[tracing::instrument(skip(incoming_pdu, val, create_event, pub_key_map))]
|
||||
pub async fn upgrade_outlier_to_timeline_pdu(
|
||||
&self,
|
||||
incoming_pdu: Arc<PduEvent>,
|
||||
val: BTreeMap<String, CanonicalJsonValue>,
|
||||
create_event: &PduEvent,
|
||||
origin: &ServerName,
|
||||
db: &Database,
|
||||
room_id: &RoomId,
|
||||
pub_key_map: &RwLock<BTreeMap<String, BTreeMap<String, Base64>>>,
|
||||
) -> Result<Option<Vec<u8>>, String> {
|
||||
// Skip the PDU if we already have it as a timeline event
|
||||
if let Ok(Some(pduid)) = db.rooms.get_pdu_id(&incoming_pdu.event_id) {
|
||||
if let Ok(Some(pduid)) = services().rooms.get_pdu_id(&incoming_pdu.event_id) {
|
||||
return Ok(Some(pduid));
|
||||
}
|
||||
|
||||
if db
|
||||
if services()
|
||||
.rooms
|
||||
.is_event_soft_failed(&incoming_pdu.event_id)
|
||||
.map_err(|_| "Failed to ask db for soft fail".to_owned())?
|
||||
|
@ -387,32 +436,32 @@ impl Service {
|
|||
|
||||
if incoming_pdu.prev_events.len() == 1 {
|
||||
let prev_event = &*incoming_pdu.prev_events[0];
|
||||
let prev_event_sstatehash = db
|
||||
let prev_event_sstatehash = services()
|
||||
.rooms
|
||||
.pdu_shortstatehash(prev_event)
|
||||
.map_err(|_| "Failed talking to db".to_owned())?;
|
||||
|
||||
let state = if let Some(shortstatehash) = prev_event_sstatehash {
|
||||
Some(db.rooms.state_full_ids(shortstatehash).await)
|
||||
Some(services().rooms.state_full_ids(shortstatehash).await)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if let Some(Ok(mut state)) = state {
|
||||
info!("Using cached state");
|
||||
let prev_pdu =
|
||||
db.rooms.get_pdu(prev_event).ok().flatten().ok_or_else(|| {
|
||||
let prev_pdu = services()
|
||||
.rooms
|
||||
.get_pdu(prev_event)
|
||||
.ok()
|
||||
.flatten()
|
||||
.ok_or_else(|| {
|
||||
"Could not find prev event, but we know the state.".to_owned()
|
||||
})?;
|
||||
|
||||
if let Some(state_key) = &prev_pdu.state_key {
|
||||
let shortstatekey = db
|
||||
let shortstatekey = services()
|
||||
.rooms
|
||||
.get_or_create_shortstatekey(
|
||||
&prev_pdu.kind.to_string().into(),
|
||||
state_key,
|
||||
&db.globals,
|
||||
)
|
||||
.get_or_create_shortstatekey(&prev_pdu.kind.to_string().into(), state_key)
|
||||
.map_err(|_| "Failed to create shortstatekey.".to_owned())?;
|
||||
|
||||
state.insert(shortstatekey, Arc::from(prev_event));
|
||||
|
@ -427,19 +476,20 @@ impl Service {
|
|||
|
||||
let mut okay = true;
|
||||
for prev_eventid in &incoming_pdu.prev_events {
|
||||
let prev_event = if let Ok(Some(pdu)) = db.rooms.get_pdu(prev_eventid) {
|
||||
let prev_event = if let Ok(Some(pdu)) = services().rooms.get_pdu(prev_eventid) {
|
||||
pdu
|
||||
} else {
|
||||
okay = false;
|
||||
break;
|
||||
};
|
||||
|
||||
let sstatehash = if let Ok(Some(s)) = db.rooms.pdu_shortstatehash(prev_eventid) {
|
||||
s
|
||||
} else {
|
||||
okay = false;
|
||||
break;
|
||||
};
|
||||
let sstatehash =
|
||||
if let Ok(Some(s)) = services().rooms.pdu_shortstatehash(prev_eventid) {
|
||||
s
|
||||
} else {
|
||||
okay = false;
|
||||
break;
|
||||
};
|
||||
|
||||
extremity_sstatehashes.insert(sstatehash, prev_event);
|
||||
}
|
||||
|
@ -449,19 +499,18 @@ impl Service {
|
|||
let mut auth_chain_sets = Vec::with_capacity(extremity_sstatehashes.len());
|
||||
|
||||
for (sstatehash, prev_event) in extremity_sstatehashes {
|
||||
let mut leaf_state: BTreeMap<_, _> = db
|
||||
let mut leaf_state: BTreeMap<_, _> = services()
|
||||
.rooms
|
||||
.state_full_ids(sstatehash)
|
||||
.await
|
||||
.map_err(|_| "Failed to ask db for room state.".to_owned())?;
|
||||
|
||||
if let Some(state_key) = &prev_event.state_key {
|
||||
let shortstatekey = db
|
||||
let shortstatekey = services()
|
||||
.rooms
|
||||
.get_or_create_shortstatekey(
|
||||
&prev_event.kind.to_string().into(),
|
||||
state_key,
|
||||
&db.globals,
|
||||
)
|
||||
.map_err(|_| "Failed to create shortstatekey.".to_owned())?;
|
||||
leaf_state.insert(shortstatekey, Arc::from(&*prev_event.event_id));
|
||||
|
@ -472,7 +521,7 @@ impl Service {
|
|||
let mut starting_events = Vec::with_capacity(leaf_state.len());
|
||||
|
||||
for (k, id) in leaf_state {
|
||||
if let Ok((ty, st_key)) = db.rooms.get_statekey_from_short(k) {
|
||||
if let Ok((ty, st_key)) = services().rooms.get_statekey_from_short(k) {
|
||||
// FIXME: Undo .to_string().into() when StateMap
|
||||
// is updated to use StateEventType
|
||||
state.insert((ty.to_string().into(), st_key), id.clone());
|
||||
|
@ -483,7 +532,10 @@ impl Service {
|
|||
}
|
||||
|
||||
auth_chain_sets.push(
|
||||
get_auth_chain(room_id, starting_events, db)
|
||||
services()
|
||||
.rooms
|
||||
.auth_chain
|
||||
.get_auth_chain(room_id, starting_events, services())
|
||||
.await
|
||||
.map_err(|_| "Failed to load auth chain.".to_owned())?
|
||||
.collect(),
|
||||
|
@ -492,15 +544,16 @@ impl Service {
|
|||
fork_states.push(state);
|
||||
}
|
||||
|
||||
let lock = db.globals.stateres_mutex.lock();
|
||||
let lock = services().globals.stateres_mutex.lock();
|
||||
|
||||
let result = state_res::resolve(room_version_id, &fork_states, auth_chain_sets, |id| {
|
||||
let res = db.rooms.get_pdu(id);
|
||||
if let Err(e) = &res {
|
||||
error!("LOOK AT ME Failed to fetch event: {}", e);
|
||||
}
|
||||
res.ok().flatten()
|
||||
});
|
||||
let result =
|
||||
state_res::resolve(room_version_id, &fork_states, auth_chain_sets, |id| {
|
||||
let res = services().rooms.get_pdu(id);
|
||||
if let Err(e) = &res {
|
||||
error!("LOOK AT ME Failed to fetch event: {}", e);
|
||||
}
|
||||
res.ok().flatten()
|
||||
});
|
||||
drop(lock);
|
||||
|
||||
state_at_incoming_event = match result {
|
||||
|
@ -508,14 +561,15 @@ impl Service {
|
|||
new_state
|
||||
.into_iter()
|
||||
.map(|((event_type, state_key), event_id)| {
|
||||
let shortstatekey = db
|
||||
let shortstatekey = services()
|
||||
.rooms
|
||||
.get_or_create_shortstatekey(
|
||||
&event_type.to_string().into(),
|
||||
&state_key,
|
||||
&db.globals,
|
||||
)
|
||||
.map_err(|_| "Failed to get_or_create_shortstatekey".to_owned())?;
|
||||
.map_err(|_| {
|
||||
"Failed to get_or_create_shortstatekey".to_owned()
|
||||
})?;
|
||||
Ok((shortstatekey, event_id))
|
||||
})
|
||||
.collect::<Result<_, String>>()?,
|
||||
|
@ -532,10 +586,9 @@ impl Service {
|
|||
info!("Calling /state_ids");
|
||||
// Call /state_ids to find out what the state at this pdu is. We trust the server's
|
||||
// response to some extend, but we still do a lot of checks on the events
|
||||
match db
|
||||
match services()
|
||||
.sending
|
||||
.send_federation_request(
|
||||
&db.globals,
|
||||
origin,
|
||||
get_room_state_ids::v1::Request {
|
||||
room_id,
|
||||
|
@ -546,18 +599,18 @@ impl Service {
|
|||
{
|
||||
Ok(res) => {
|
||||
info!("Fetching state events at event.");
|
||||
let state_vec = fetch_and_handle_outliers(
|
||||
db,
|
||||
origin,
|
||||
&res.pdu_ids
|
||||
.iter()
|
||||
.map(|x| Arc::from(&**x))
|
||||
.collect::<Vec<_>>(),
|
||||
create_event,
|
||||
room_id,
|
||||
pub_key_map,
|
||||
)
|
||||
.await;
|
||||
let state_vec = self
|
||||
.fetch_and_handle_outliers(
|
||||
origin,
|
||||
&res.pdu_ids
|
||||
.iter()
|
||||
.map(|x| Arc::from(&**x))
|
||||
.collect::<Vec<_>>(),
|
||||
create_event,
|
||||
room_id,
|
||||
pub_key_map,
|
||||
)
|
||||
.await;
|
||||
|
||||
let mut state: BTreeMap<_, Arc<EventId>> = BTreeMap::new();
|
||||
for (pdu, _) in state_vec {
|
||||
|
@ -566,13 +619,9 @@ impl Service {
|
|||
.clone()
|
||||
.ok_or_else(|| "Found non-state pdu in state events.".to_owned())?;
|
||||
|
||||
let shortstatekey = db
|
||||
let shortstatekey = services()
|
||||
.rooms
|
||||
.get_or_create_shortstatekey(
|
||||
&pdu.kind.to_string().into(),
|
||||
&state_key,
|
||||
&db.globals,
|
||||
)
|
||||
.get_or_create_shortstatekey(&pdu.kind.to_string().into(), &state_key)
|
||||
.map_err(|_| "Failed to create shortstatekey.".to_owned())?;
|
||||
|
||||
match state.entry(shortstatekey) {
|
||||
|
@ -587,7 +636,7 @@ impl Service {
|
|||
}
|
||||
|
||||
// The original create event must still be in the state
|
||||
let create_shortstatekey = db
|
||||
let create_shortstatekey = services()
|
||||
.rooms
|
||||
.get_shortstatekey(&StateEventType::RoomCreate, "")
|
||||
.map_err(|_| "Failed to talk to db.")?
|
||||
|
@ -618,12 +667,13 @@ impl Service {
|
|||
&incoming_pdu,
|
||||
None::<PduEvent>, // TODO: third party invite
|
||||
|k, s| {
|
||||
db.rooms
|
||||
services()
|
||||
.rooms
|
||||
.get_shortstatekey(&k.to_string().into(), s)
|
||||
.ok()
|
||||
.flatten()
|
||||
.and_then(|shortstatekey| state_at_incoming_event.get(&shortstatekey))
|
||||
.and_then(|event_id| db.rooms.get_pdu(event_id).ok().flatten())
|
||||
.and_then(|event_id| services().rooms.get_pdu(event_id).ok().flatten())
|
||||
},
|
||||
)
|
||||
.map_err(|_e| "Auth check failed.".to_owned())?;
|
||||
|
@ -636,7 +686,8 @@ impl Service {
|
|||
// We start looking at current room state now, so lets lock the room
|
||||
|
||||
let mutex_state = Arc::clone(
|
||||
db.globals
|
||||
services()
|
||||
.globals
|
||||
.roomid_mutex_state
|
||||
.write()
|
||||
.unwrap()
|
||||
|
@ -648,7 +699,7 @@ impl Service {
|
|||
// Now we calculate the set of extremities this room has after the incoming event has been
|
||||
// applied. We start with the previous extremities (aka leaves)
|
||||
info!("Calculating extremities");
|
||||
let mut extremities = db
|
||||
let mut extremities = services()
|
||||
.rooms
|
||||
.get_pdu_leaves(room_id)
|
||||
.map_err(|_| "Failed to load room leaves".to_owned())?;
|
||||
|
@ -661,14 +712,16 @@ impl Service {
|
|||
}
|
||||
|
||||
// Only keep those extremities were not referenced yet
|
||||
extremities.retain(|id| !matches!(db.rooms.is_event_referenced(room_id, id), Ok(true)));
|
||||
extremities
|
||||
.retain(|id| !matches!(services().rooms.is_event_referenced(room_id, id), Ok(true)));
|
||||
|
||||
info!("Compressing state at event");
|
||||
let state_ids_compressed = state_at_incoming_event
|
||||
.iter()
|
||||
.map(|(shortstatekey, id)| {
|
||||
db.rooms
|
||||
.compress_state_event(*shortstatekey, id, &db.globals)
|
||||
services()
|
||||
.rooms
|
||||
.compress_state_event(*shortstatekey, id)
|
||||
.map_err(|_| "Failed to compress_state_event".to_owned())
|
||||
})
|
||||
.collect::<Result<_, _>>()?;
|
||||
|
@ -676,7 +729,7 @@ impl Service {
|
|||
// 13. Check if the event passes auth based on the "current state" of the room, if not "soft fail" it
|
||||
info!("Starting soft fail auth check");
|
||||
|
||||
let auth_events = db
|
||||
let auth_events = services()
|
||||
.rooms
|
||||
.get_auth_events(
|
||||
room_id,
|
||||
|
@ -696,11 +749,10 @@ impl Service {
|
|||
.map_err(|_e| "Auth check failed.".to_owned())?;
|
||||
|
||||
if soft_fail {
|
||||
append_incoming_pdu(
|
||||
db,
|
||||
self.append_incoming_pdu(
|
||||
&incoming_pdu,
|
||||
val,
|
||||
extremities.iter().map(Deref::deref),
|
||||
extremities.iter().map(std::ops::Deref::deref),
|
||||
state_ids_compressed,
|
||||
soft_fail,
|
||||
&state_lock,
|
||||
|
@ -712,7 +764,8 @@ impl Service {
|
|||
|
||||
// Soft fail, we keep the event as an outlier but don't add it to the timeline
|
||||
warn!("Event was soft failed: {:?}", incoming_pdu);
|
||||
db.rooms
|
||||
services()
|
||||
.rooms
|
||||
.mark_event_soft_failed(&incoming_pdu.event_id)
|
||||
.map_err(|_| "Failed to set soft failed flag".to_owned())?;
|
||||
return Err("Event has been soft failed".into());
|
||||
|
@ -720,13 +773,13 @@ impl Service {
|
|||
|
||||
if incoming_pdu.state_key.is_some() {
|
||||
info!("Loading current room state ids");
|
||||
let current_sstatehash = db
|
||||
let current_sstatehash = services()
|
||||
.rooms
|
||||
.current_shortstatehash(room_id)
|
||||
.map_err(|_| "Failed to load current state hash.".to_owned())?
|
||||
.expect("every room has state");
|
||||
|
||||
let current_state_ids = db
|
||||
let current_state_ids = services()
|
||||
.rooms
|
||||
.state_full_ids(current_sstatehash)
|
||||
.await
|
||||
|
@ -737,14 +790,14 @@ impl Service {
|
|||
|
||||
info!("Loading extremities");
|
||||
for id in dbg!(&extremities) {
|
||||
match db
|
||||
match services()
|
||||
.rooms
|
||||
.get_pdu(id)
|
||||
.map_err(|_| "Failed to ask db for pdu.".to_owned())?
|
||||
{
|
||||
Some(leaf_pdu) => {
|
||||
extremity_sstatehashes.insert(
|
||||
db.rooms
|
||||
services()
|
||||
.pdu_shortstatehash(&leaf_pdu.event_id)
|
||||
.map_err(|_| "Failed to ask db for pdu state hash.".to_owned())?
|
||||
.ok_or_else(|| {
|
||||
|
@ -777,13 +830,9 @@ impl Service {
|
|||
// We also add state after incoming event to the fork states
|
||||
let mut state_after = state_at_incoming_event.clone();
|
||||
if let Some(state_key) = &incoming_pdu.state_key {
|
||||
let shortstatekey = db
|
||||
let shortstatekey = services()
|
||||
.rooms
|
||||
.get_or_create_shortstatekey(
|
||||
&incoming_pdu.kind.to_string().into(),
|
||||
state_key,
|
||||
&db.globals,
|
||||
)
|
||||
.get_or_create_shortstatekey(&incoming_pdu.kind.to_string().into(), state_key)
|
||||
.map_err(|_| "Failed to create shortstatekey.".to_owned())?;
|
||||
|
||||
state_after.insert(shortstatekey, Arc::from(&*incoming_pdu.event_id));
|
||||
|
@ -801,8 +850,9 @@ impl Service {
|
|||
fork_states[0]
|
||||
.iter()
|
||||
.map(|(k, id)| {
|
||||
db.rooms
|
||||
.compress_state_event(*k, id, &db.globals)
|
||||
services()
|
||||
.rooms
|
||||
.compress_state_event(*k, id)
|
||||
.map_err(|_| "Failed to compress_state_event.".to_owned())
|
||||
})
|
||||
.collect::<Result<_, _>>()?
|
||||
|
@ -814,14 +864,16 @@ impl Service {
|
|||
let mut auth_chain_sets = Vec::new();
|
||||
for state in &fork_states {
|
||||
auth_chain_sets.push(
|
||||
get_auth_chain(
|
||||
room_id,
|
||||
state.iter().map(|(_, id)| id.clone()).collect(),
|
||||
db,
|
||||
)
|
||||
.await
|
||||
.map_err(|_| "Failed to load auth chain.".to_owned())?
|
||||
.collect(),
|
||||
services()
|
||||
.rooms
|
||||
.auth_chain
|
||||
.get_auth_chain(
|
||||
room_id,
|
||||
state.iter().map(|(_, id)| id.clone()).collect(),
|
||||
)
|
||||
.await
|
||||
.map_err(|_| "Failed to load auth chain.".to_owned())?
|
||||
.collect(),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -832,7 +884,8 @@ impl Service {
|
|||
.map(|map| {
|
||||
map.into_iter()
|
||||
.filter_map(|(k, id)| {
|
||||
db.rooms
|
||||
services()
|
||||
.rooms
|
||||
.get_statekey_from_short(k)
|
||||
// FIXME: Undo .to_string().into() when StateMap
|
||||
// is updated to use StateEventType
|
||||
|
@ -846,13 +899,13 @@ impl Service {
|
|||
|
||||
info!("Resolving state");
|
||||
|
||||
let lock = db.globals.stateres_mutex.lock();
|
||||
let lock = services().globals.stateres_mutex.lock();
|
||||
let state = match state_res::resolve(
|
||||
room_version_id,
|
||||
&fork_states,
|
||||
auth_chain_sets,
|
||||
|id| {
|
||||
let res = db.rooms.get_pdu(id);
|
||||
let res = services().rooms.get_pdu(id);
|
||||
if let Err(e) = &res {
|
||||
error!("LOOK AT ME Failed to fetch event: {}", e);
|
||||
}
|
||||
|
@ -872,16 +925,13 @@ impl Service {
|
|||
state
|
||||
.into_iter()
|
||||
.map(|((event_type, state_key), event_id)| {
|
||||
let shortstatekey = db
|
||||
let shortstatekey = services()
|
||||
.rooms
|
||||
.get_or_create_shortstatekey(
|
||||
&event_type.to_string().into(),
|
||||
&state_key,
|
||||
&db.globals,
|
||||
)
|
||||
.get_or_create_shortstatekey(&event_type.to_string().into(), &state_key)
|
||||
.map_err(|_| "Failed to get_or_create_shortstatekey".to_owned())?;
|
||||
db.rooms
|
||||
.compress_state_event(shortstatekey, &event_id, &db.globals)
|
||||
services()
|
||||
.rooms
|
||||
.compress_state_event(shortstatekey, &event_id)
|
||||
.map_err(|_| "Failed to compress state event".to_owned())
|
||||
})
|
||||
.collect::<Result<_, _>>()?
|
||||
|
@ -890,8 +940,9 @@ impl Service {
|
|||
// Set the new room state to the resolved state
|
||||
if update_state {
|
||||
info!("Forcing new room state");
|
||||
db.rooms
|
||||
.force_state(room_id, new_room_state, db)
|
||||
services()
|
||||
.rooms
|
||||
.force_state(room_id, new_room_state)
|
||||
.map_err(|_| "Failed to set new room state.".to_owned())?;
|
||||
}
|
||||
}
|
||||
|
@ -903,19 +954,19 @@ impl Service {
|
|||
// We use the `state_at_event` instead of `state_after` so we accurately
|
||||
// represent the state for this event.
|
||||
|
||||
let pdu_id = append_incoming_pdu(
|
||||
db,
|
||||
&incoming_pdu,
|
||||
val,
|
||||
extremities.iter().map(Deref::deref),
|
||||
state_ids_compressed,
|
||||
soft_fail,
|
||||
&state_lock,
|
||||
)
|
||||
.map_err(|e| {
|
||||
warn!("Failed to add pdu to db: {}", e);
|
||||
"Failed to add pdu to db.".to_owned()
|
||||
})?;
|
||||
let pdu_id = self
|
||||
.append_incoming_pdu(
|
||||
&incoming_pdu,
|
||||
val,
|
||||
extremities.iter().map(std::ops::Deref::deref),
|
||||
state_ids_compressed,
|
||||
soft_fail,
|
||||
&state_lock,
|
||||
)
|
||||
.map_err(|e| {
|
||||
warn!("Failed to add pdu to db: {}", e);
|
||||
"Failed to add pdu to db.".to_owned()
|
||||
})?;
|
||||
|
||||
info!("Appended incoming pdu");
|
||||
|
||||
|
@ -935,15 +986,22 @@ impl Service {
|
|||
/// d. TODO: Ask other servers over federation?
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub(crate) fn fetch_and_handle_outliers<'a>(
|
||||
db: &'a Database,
|
||||
&self,
|
||||
origin: &'a ServerName,
|
||||
events: &'a [Arc<EventId>],
|
||||
create_event: &'a PduEvent,
|
||||
room_id: &'a RoomId,
|
||||
pub_key_map: &'a RwLock<BTreeMap<String, BTreeMap<String, Base64>>>,
|
||||
) -> AsyncRecursiveType<'a, Vec<(Arc<PduEvent>, Option<BTreeMap<String, CanonicalJsonValue>>)>> {
|
||||
) -> AsyncRecursiveType<'a, Vec<(Arc<PduEvent>, Option<BTreeMap<String, CanonicalJsonValue>>)>>
|
||||
{
|
||||
Box::pin(async move {
|
||||
let back_off = |id| match db.globals.bad_event_ratelimiter.write().unwrap().entry(id) {
|
||||
let back_off = |id| match services()
|
||||
.globals
|
||||
.bad_event_ratelimiter
|
||||
.write()
|
||||
.unwrap()
|
||||
.entry(id)
|
||||
{
|
||||
hash_map::Entry::Vacant(e) => {
|
||||
e.insert((Instant::now(), 1));
|
||||
}
|
||||
|
@ -952,10 +1010,16 @@ impl Service {
|
|||
|
||||
let mut pdus = vec![];
|
||||
for id in events {
|
||||
if let Some((time, tries)) = db.globals.bad_event_ratelimiter.read().unwrap().get(&**id)
|
||||
if let Some((time, tries)) = services()
|
||||
.globals
|
||||
.bad_event_ratelimiter
|
||||
.read()
|
||||
.unwrap()
|
||||
.get(&**id)
|
||||
{
|
||||
// Exponential backoff
|
||||
let mut min_elapsed_duration = Duration::from_secs(5 * 60) * (*tries) * (*tries);
|
||||
let mut min_elapsed_duration =
|
||||
Duration::from_secs(5 * 60) * (*tries) * (*tries);
|
||||
if min_elapsed_duration > Duration::from_secs(60 * 60 * 24) {
|
||||
min_elapsed_duration = Duration::from_secs(60 * 60 * 24);
|
||||
}
|
||||
|
@ -969,7 +1033,7 @@ impl Service {
|
|||
// a. Look in the main timeline (pduid_pdu tree)
|
||||
// b. Look at outlier pdu tree
|
||||
// (get_pdu_json checks both)
|
||||
if let Ok(Some(local_pdu)) = db.rooms.get_pdu(id) {
|
||||
if let Ok(Some(local_pdu)) = services().rooms.get_pdu(id) {
|
||||
trace!("Found {} in db", id);
|
||||
pdus.push((local_pdu, None));
|
||||
continue;
|
||||
|
@ -992,16 +1056,15 @@ impl Service {
|
|||
tokio::task::yield_now().await;
|
||||
}
|
||||
|
||||
if let Ok(Some(_)) = db.rooms.get_pdu(&next_id) {
|
||||
if let Ok(Some(_)) = services().rooms.get_pdu(&next_id) {
|
||||
trace!("Found {} in db", id);
|
||||
continue;
|
||||
}
|
||||
|
||||
info!("Fetching {} over federation.", next_id);
|
||||
match db
|
||||
match services()
|
||||
.sending
|
||||
.send_federation_request(
|
||||
&db.globals,
|
||||
origin,
|
||||
get_event::v1::Request { event_id: &next_id },
|
||||
)
|
||||
|
@ -1010,7 +1073,7 @@ impl Service {
|
|||
Ok(res) => {
|
||||
info!("Got {} over federation", next_id);
|
||||
let (calculated_event_id, value) =
|
||||
match crate::pdu::gen_event_id_canonical_json(&res.pdu, &db) {
|
||||
match pdu::gen_event_id_canonical_json(&res.pdu) {
|
||||
Ok(t) => t,
|
||||
Err(_) => {
|
||||
back_off((*next_id).to_owned());
|
||||
|
@ -1051,16 +1114,16 @@ impl Service {
|
|||
}
|
||||
|
||||
for (next_id, value) in events_in_reverse_order.iter().rev() {
|
||||
match handle_outlier_pdu(
|
||||
origin,
|
||||
create_event,
|
||||
next_id,
|
||||
room_id,
|
||||
value.clone(),
|
||||
db,
|
||||
pub_key_map,
|
||||
)
|
||||
.await
|
||||
match self
|
||||
.handle_outlier_pdu(
|
||||
origin,
|
||||
create_event,
|
||||
next_id,
|
||||
room_id,
|
||||
value.clone(),
|
||||
pub_key_map,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok((pdu, json)) => {
|
||||
if next_id == id {
|
||||
|
@ -1078,9 +1141,14 @@ impl Service {
|
|||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
fn fetch_unknown_prev_events(initial_set: Vec<Arc<EventId>>) -> Vec<Arc<EventId>> {
|
||||
async fn fetch_unknown_prev_events(
|
||||
&self,
|
||||
origin: &ServerName,
|
||||
create_event: &PduEvent,
|
||||
room_id: &RoomId,
|
||||
pub_key_map: &RwLock<BTreeMap<String, BTreeMap<String, Base64>>>,
|
||||
initial_set: Vec<Arc<EventId>>,
|
||||
) -> Vec<(Arc<EventId>, HashMap<Arc<EventId>, (Arc<PduEvent>, BTreeMap<String, CanonicalJsonValue>)>)> {
|
||||
let mut graph: HashMap<Arc<EventId>, _> = HashMap::new();
|
||||
let mut eventid_info = HashMap::new();
|
||||
let mut todo_outlier_stack: Vec<Arc<EventId>> = initial_set;
|
||||
|
@ -1088,16 +1156,16 @@ impl Service {
|
|||
let mut amount = 0;
|
||||
|
||||
while let Some(prev_event_id) = todo_outlier_stack.pop() {
|
||||
if let Some((pdu, json_opt)) = fetch_and_handle_outliers(
|
||||
db,
|
||||
origin,
|
||||
&[prev_event_id.clone()],
|
||||
&create_event,
|
||||
room_id,
|
||||
pub_key_map,
|
||||
)
|
||||
.await
|
||||
.pop()
|
||||
if let Some((pdu, json_opt)) = self
|
||||
.fetch_and_handle_outliers(
|
||||
origin,
|
||||
&[prev_event_id.clone()],
|
||||
&create_event,
|
||||
room_id,
|
||||
pub_key_map,
|
||||
)
|
||||
.await
|
||||
.pop()
|
||||
{
|
||||
if amount > 100 {
|
||||
// Max limit reached
|
||||
|
@ -1106,9 +1174,13 @@ impl Service {
|
|||
continue;
|
||||
}
|
||||
|
||||
if let Some(json) =
|
||||
json_opt.or_else(|| db.rooms.get_outlier_pdu_json(&prev_event_id).ok().flatten())
|
||||
{
|
||||
if let Some(json) = json_opt.or_else(|| {
|
||||
services()
|
||||
.rooms
|
||||
.get_outlier_pdu_json(&prev_event_id)
|
||||
.ok()
|
||||
.flatten()
|
||||
}) {
|
||||
if pdu.origin_server_ts > first_pdu_in_room.origin_server_ts {
|
||||
amount += 1;
|
||||
for prev_prev in &pdu.prev_events {
|
||||
|
@ -1153,6 +1225,6 @@ impl Service {
|
|||
})
|
||||
.map_err(|_| "Error sorting prev events".to_owned())?;
|
||||
|
||||
sorted
|
||||
(sorted, eventid_info)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use ruma::{RoomId, DeviceId, UserId};
|
||||
|
||||
pub trait Data {
|
||||
fn lazy_load_was_sent_before(
|
||||
&self,
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
mod data;
|
||||
use std::collections::HashSet;
|
||||
|
||||
pub use data::Data;
|
||||
use ruma::{DeviceId, UserId, RoomId};
|
||||
|
||||
use crate::service::*;
|
||||
|
||||
|
@ -47,7 +50,7 @@ impl Service<_> {
|
|||
room_id: &RoomId,
|
||||
since: u64,
|
||||
) -> Result<()> {
|
||||
self.db.lazy_load_confirm_delivery(user_d, device_id, room_id, since)
|
||||
self.db.lazy_load_confirm_delivery(user_id, device_id, room_id, since)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
|
@ -57,6 +60,6 @@ impl Service<_> {
|
|||
device_id: &DeviceId,
|
||||
room_id: &RoomId,
|
||||
) -> Result<()> {
|
||||
self.db.lazy_load_reset(user_id, device_id, room_id);
|
||||
self.db.lazy_load_reset(user_id, device_id, room_id)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use ruma::RoomId;
|
||||
|
||||
pub trait Data {
|
||||
fn exists(&self, room_id: &RoomId) -> Result<bool>;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
mod data;
|
||||
pub use data::Data;
|
||||
use ruma::RoomId;
|
||||
|
||||
use crate::service::*;
|
||||
|
||||
|
|
|
@ -1,216 +1,37 @@
|
|||
mod edus;
|
||||
|
||||
pub use edus::RoomEdus;
|
||||
|
||||
use crate::{
|
||||
pdu::{EventHash, PduBuilder},
|
||||
utils, Database, Error, PduEvent, Result,
|
||||
};
|
||||
use lru_cache::LruCache;
|
||||
use regex::Regex;
|
||||
use ring::digest;
|
||||
use ruma::{
|
||||
api::{client::error::ErrorKind, federation},
|
||||
events::{
|
||||
direct::DirectEvent,
|
||||
ignored_user_list::IgnoredUserListEvent,
|
||||
push_rules::PushRulesEvent,
|
||||
room::{
|
||||
create::RoomCreateEventContent,
|
||||
member::{MembershipState, RoomMemberEventContent},
|
||||
power_levels::RoomPowerLevelsEventContent,
|
||||
},
|
||||
tag::TagEvent,
|
||||
AnyStrippedStateEvent, AnySyncStateEvent, GlobalAccountDataEventType,
|
||||
RoomAccountDataEventType, RoomEventType, StateEventType,
|
||||
},
|
||||
push::{Action, Ruleset, Tweak},
|
||||
serde::{CanonicalJsonObject, CanonicalJsonValue, Raw},
|
||||
state_res::{self, RoomVersion, StateMap},
|
||||
uint, DeviceId, EventId, RoomAliasId, RoomId, RoomVersionId, ServerName, UserId,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use serde_json::value::to_raw_value;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
collections::{hash_map, BTreeMap, HashMap, HashSet},
|
||||
fmt::Debug,
|
||||
iter,
|
||||
mem::size_of,
|
||||
sync::{Arc, Mutex, RwLock},
|
||||
};
|
||||
use tokio::sync::MutexGuard;
|
||||
use tracing::{error, warn};
|
||||
|
||||
use super::{abstraction::Tree, pusher};
|
||||
|
||||
/// The unique identifier of each state group.
|
||||
///
|
||||
/// This is created when a state group is added to the database by
|
||||
/// hashing the entire state.
|
||||
pub type StateHashId = Vec<u8>;
|
||||
pub type CompressedStateEvent = [u8; 2 * size_of::<u64>()];
|
||||
|
||||
pub struct Rooms {
|
||||
pub edus: RoomEdus,
|
||||
pub(super) pduid_pdu: Arc<dyn Tree>, // PduId = ShortRoomId + Count
|
||||
pub(super) eventid_pduid: Arc<dyn Tree>,
|
||||
pub(super) roomid_pduleaves: Arc<dyn Tree>,
|
||||
pub(super) alias_roomid: Arc<dyn Tree>,
|
||||
pub(super) aliasid_alias: Arc<dyn Tree>, // AliasId = RoomId + Count
|
||||
pub(super) publicroomids: Arc<dyn Tree>,
|
||||
|
||||
pub(super) tokenids: Arc<dyn Tree>, // TokenId = ShortRoomId + Token + PduIdCount
|
||||
|
||||
/// Participating servers in a room.
|
||||
pub(super) roomserverids: Arc<dyn Tree>, // RoomServerId = RoomId + ServerName
|
||||
pub(super) serverroomids: Arc<dyn Tree>, // ServerRoomId = ServerName + RoomId
|
||||
|
||||
pub(super) userroomid_joined: Arc<dyn Tree>,
|
||||
pub(super) roomuserid_joined: Arc<dyn Tree>,
|
||||
pub(super) roomid_joinedcount: Arc<dyn Tree>,
|
||||
pub(super) roomid_invitedcount: Arc<dyn Tree>,
|
||||
pub(super) roomuseroncejoinedids: Arc<dyn Tree>,
|
||||
pub(super) userroomid_invitestate: Arc<dyn Tree>, // InviteState = Vec<Raw<Pdu>>
|
||||
pub(super) roomuserid_invitecount: Arc<dyn Tree>, // InviteCount = Count
|
||||
pub(super) userroomid_leftstate: Arc<dyn Tree>,
|
||||
pub(super) roomuserid_leftcount: Arc<dyn Tree>,
|
||||
|
||||
pub(super) disabledroomids: Arc<dyn Tree>, // Rooms where incoming federation handling is disabled
|
||||
|
||||
pub(super) lazyloadedids: Arc<dyn Tree>, // LazyLoadedIds = UserId + DeviceId + RoomId + LazyLoadedUserId
|
||||
|
||||
pub(super) userroomid_notificationcount: Arc<dyn Tree>, // NotifyCount = u64
|
||||
pub(super) userroomid_highlightcount: Arc<dyn Tree>, // HightlightCount = u64
|
||||
|
||||
/// Remember the current state hash of a room.
|
||||
pub(super) roomid_shortstatehash: Arc<dyn Tree>,
|
||||
pub(super) roomsynctoken_shortstatehash: Arc<dyn Tree>,
|
||||
/// Remember the state hash at events in the past.
|
||||
pub(super) shorteventid_shortstatehash: Arc<dyn Tree>,
|
||||
/// StateKey = EventType + StateKey, ShortStateKey = Count
|
||||
pub(super) statekey_shortstatekey: Arc<dyn Tree>,
|
||||
pub(super) shortstatekey_statekey: Arc<dyn Tree>,
|
||||
|
||||
pub(super) roomid_shortroomid: Arc<dyn Tree>,
|
||||
|
||||
pub(super) shorteventid_eventid: Arc<dyn Tree>,
|
||||
pub(super) eventid_shorteventid: Arc<dyn Tree>,
|
||||
|
||||
pub(super) statehash_shortstatehash: Arc<dyn Tree>,
|
||||
pub(super) shortstatehash_statediff: Arc<dyn Tree>, // StateDiff = parent (or 0) + (shortstatekey+shorteventid++) + 0_u64 + (shortstatekey+shorteventid--)
|
||||
|
||||
pub(super) shorteventid_authchain: Arc<dyn Tree>,
|
||||
|
||||
/// RoomId + EventId -> outlier PDU.
|
||||
/// Any pdu that has passed the steps 1-8 in the incoming event /federation/send/txn.
|
||||
pub(super) eventid_outlierpdu: Arc<dyn Tree>,
|
||||
pub(super) softfailedeventids: Arc<dyn Tree>,
|
||||
|
||||
/// RoomId + EventId -> Parent PDU EventId.
|
||||
pub(super) referencedevents: Arc<dyn Tree>,
|
||||
|
||||
pub(super) pdu_cache: Mutex<LruCache<Box<EventId>, Arc<PduEvent>>>,
|
||||
pub(super) shorteventid_cache: Mutex<LruCache<u64, Arc<EventId>>>,
|
||||
pub(super) auth_chain_cache: Mutex<LruCache<Vec<u64>, Arc<HashSet<u64>>>>,
|
||||
pub(super) eventidshort_cache: Mutex<LruCache<Box<EventId>, u64>>,
|
||||
pub(super) statekeyshort_cache: Mutex<LruCache<(StateEventType, String), u64>>,
|
||||
pub(super) shortstatekey_cache: Mutex<LruCache<u64, (StateEventType, String)>>,
|
||||
pub(super) our_real_users_cache: RwLock<HashMap<Box<RoomId>, Arc<HashSet<Box<UserId>>>>>,
|
||||
pub(super) appservice_in_room_cache: RwLock<HashMap<Box<RoomId>, HashMap<String, bool>>>,
|
||||
pub(super) lazy_load_waiting:
|
||||
Mutex<HashMap<(Box<UserId>, Box<DeviceId>, Box<RoomId>, u64), HashSet<Box<UserId>>>>,
|
||||
pub(super) stateinfo_cache: Mutex<
|
||||
LruCache<
|
||||
u64,
|
||||
Vec<(
|
||||
u64, // sstatehash
|
||||
HashSet<CompressedStateEvent>, // full state
|
||||
HashSet<CompressedStateEvent>, // added
|
||||
HashSet<CompressedStateEvent>, // removed
|
||||
)>,
|
||||
>,
|
||||
>,
|
||||
pub(super) lasttimelinecount_cache: Mutex<HashMap<Box<RoomId>, u64>>,
|
||||
}
|
||||
|
||||
impl Rooms {
|
||||
/// Returns true if a given room version is supported
|
||||
#[tracing::instrument(skip(self, db))]
|
||||
pub fn is_supported_version(&self, db: &Database, room_version: &RoomVersionId) -> bool {
|
||||
db.globals.supported_room_versions().contains(room_version)
|
||||
}
|
||||
|
||||
/// This fetches auth events from the current state.
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn get_auth_events(
|
||||
&self,
|
||||
room_id: &RoomId,
|
||||
kind: &RoomEventType,
|
||||
sender: &UserId,
|
||||
state_key: Option<&str>,
|
||||
content: &serde_json::value::RawValue,
|
||||
) -> Result<StateMap<Arc<PduEvent>>> {
|
||||
let shortstatehash =
|
||||
if let Some(current_shortstatehash) = self.current_shortstatehash(room_id)? {
|
||||
current_shortstatehash
|
||||
} else {
|
||||
return Ok(HashMap::new());
|
||||
};
|
||||
|
||||
let auth_events = state_res::auth_types_for_event(kind, sender, state_key, content)
|
||||
.expect("content is a valid JSON object");
|
||||
|
||||
let mut sauthevents = auth_events
|
||||
.into_iter()
|
||||
.filter_map(|(event_type, state_key)| {
|
||||
self.get_shortstatekey(&event_type.to_string().into(), &state_key)
|
||||
.ok()
|
||||
.flatten()
|
||||
.map(|s| (s, (event_type, state_key)))
|
||||
})
|
||||
.collect::<HashMap<_, _>>();
|
||||
|
||||
let full_state = self
|
||||
.load_shortstatehash_info(shortstatehash)?
|
||||
.pop()
|
||||
.expect("there is always one layer")
|
||||
.1;
|
||||
|
||||
Ok(full_state
|
||||
.into_iter()
|
||||
.filter_map(|compressed| self.parse_compressed_state_event(compressed).ok())
|
||||
.filter_map(|(shortstatekey, event_id)| {
|
||||
sauthevents.remove(&shortstatekey).map(|k| (k, event_id))
|
||||
})
|
||||
.filter_map(|(k, event_id)| self.get_pdu(&event_id).ok().flatten().map(|pdu| (k, pdu)))
|
||||
.collect())
|
||||
}
|
||||
|
||||
/// Generate a new StateHash.
|
||||
///
|
||||
/// A unique hash made from hashing all PDU ids of the state joined with 0xff.
|
||||
fn calculate_hash(&self, bytes_list: &[&[u8]]) -> StateHashId {
|
||||
// We only hash the pdu's event ids, not the whole pdu
|
||||
let bytes = bytes_list.join(&0xff);
|
||||
let hash = digest::digest(&digest::SHA256, &bytes);
|
||||
hash.as_ref().into()
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn iter_ids(&self) -> impl Iterator<Item = Result<Box<RoomId>>> + '_ {
|
||||
self.roomid_shortroomid.iter().map(|(bytes, _)| {
|
||||
RoomId::parse(
|
||||
utils::string_from_bytes(&bytes).map_err(|_| {
|
||||
Error::bad_database("Room ID in publicroomids is invalid unicode.")
|
||||
})?,
|
||||
)
|
||||
.map_err(|_| Error::bad_database("Room ID in roomid_shortroomid is invalid."))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn is_disabled(&self, room_id: &RoomId) -> Result<bool> {
|
||||
Ok(self.disabledroomids.get(room_id.as_bytes())?.is_some())
|
||||
}
|
||||
pub mod alias;
|
||||
pub mod auth_chain;
|
||||
pub mod directory;
|
||||
pub mod edus;
|
||||
pub mod event_handler;
|
||||
pub mod lazy_loading;
|
||||
pub mod metadata;
|
||||
pub mod outlier;
|
||||
pub mod pdu_metadata;
|
||||
pub mod search;
|
||||
pub mod short;
|
||||
pub mod state;
|
||||
pub mod state_accessor;
|
||||
pub mod state_cache;
|
||||
pub mod state_compressor;
|
||||
pub mod timeline;
|
||||
pub mod user;
|
||||
|
||||
pub struct Service<D> {
|
||||
pub alias: alias::Service<D>,
|
||||
pub auth_chain: auth_chain::Service<D>,
|
||||
pub directory: directory::Service<D>,
|
||||
pub edus: edus::Service<D>,
|
||||
pub event_handler: event_handler::Service,
|
||||
pub lazy_loading: lazy_loading::Service<D>,
|
||||
pub metadata: metadata::Service<D>,
|
||||
pub outlier: outlier::Service<D>,
|
||||
pub pdu_metadata: pdu_metadata::Service<D>,
|
||||
pub search: search::Service<D>,
|
||||
pub short: short::Service<D>,
|
||||
pub state: state::Service<D>,
|
||||
pub state_accessor: state_accessor::Service<D>,
|
||||
pub state_cache: state_cache::Service<D>,
|
||||
pub state_compressor: state_compressor::Service<D>,
|
||||
pub timeline: timeline::Service<D>,
|
||||
pub user: user::Service<D>,
|
||||
}
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
use ruma::{EventId, signatures::CanonicalJsonObject};
|
||||
|
||||
use crate::PduEvent;
|
||||
|
||||
pub trait Data {
|
||||
fn get_outlier_pdu_json(&self, event_id: &EventId) -> Result<Option<CanonicalJsonObject>>;
|
||||
fn get_outlier_pdu(&self, event_id: &EventId) -> Result<Option<PduEvent>>;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
mod data;
|
||||
pub use data::Data;
|
||||
use ruma::{EventId, signatures::CanonicalJsonObject};
|
||||
|
||||
use crate::service::*;
|
||||
use crate::{service::*, PduEvent};
|
||||
|
||||
pub struct Service<D: Data> {
|
||||
db: D,
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use ruma::{EventId, RoomId};
|
||||
|
||||
pub trait Data {
|
||||
fn mark_as_referenced(&self, room_id: &RoomId, event_ids: &[Arc<EventId>]) -> Result<()>;
|
||||
fn is_event_referenced(&self, room_id: &RoomId, event_id: &EventId) -> Result<bool>;
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
mod data;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub use data::Data;
|
||||
use ruma::{RoomId, EventId};
|
||||
|
||||
use crate::service::*;
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
pub trait Data {
|
||||
pub fn index_pdu<'a>(&self, room_id: &RoomId, pdu_id: u64, message_body: String) -> Result<()>;
|
||||
use ruma::RoomId;
|
||||
|
||||
pub fn search_pdus<'a>(
|
||||
pub trait Data {
|
||||
fn index_pdu<'a>(&self, room_id: &RoomId, pdu_id: u64, message_body: String) -> Result<()>;
|
||||
|
||||
fn search_pdus<'a>(
|
||||
&'a self,
|
||||
room_id: &RoomId,
|
||||
search_string: &str,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
mod data;
|
||||
pub use data::Data;
|
||||
|
||||
use crate::service::*;
|
||||
use ruma::RoomId;
|
||||
|
||||
pub struct Service<D: Data> {
|
||||
db: D,
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
mod data;
|
||||
pub use data::Data;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::service::*;
|
||||
pub use data::Data;
|
||||
use ruma::{EventId, events::StateEventType};
|
||||
|
||||
use crate::{service::*, Error, utils};
|
||||
|
||||
pub struct Service<D: Data> {
|
||||
db: D,
|
||||
|
@ -188,7 +191,6 @@ impl Service<_> {
|
|||
fn get_or_create_shortstatehash(
|
||||
&self,
|
||||
state_hash: &StateHashId,
|
||||
globals: &super::globals::Globals,
|
||||
) -> Result<(u64, bool)> {
|
||||
Ok(match self.statehash_shortstatehash.get(state_hash)? {
|
||||
Some(shortstatehash) => (
|
||||
|
|
|
@ -1,14 +1,20 @@
|
|||
use std::sync::Arc;
|
||||
use std::{sync::MutexGuard, collections::HashSet};
|
||||
use std::fmt::Debug;
|
||||
|
||||
use ruma::{EventId, RoomId};
|
||||
|
||||
pub trait Data {
|
||||
/// Returns the last state hash key added to the db for the given room.
|
||||
fn get_room_shortstatehash(room_id: &RoomId);
|
||||
|
||||
/// Update the current state of the room.
|
||||
fn set_room_state(room_id: &RoomId, new_shortstatehash: u64
|
||||
fn set_room_state(room_id: &RoomId, new_shortstatehash: u64,
|
||||
_mutex_lock: &MutexGuard<'_, StateLock>, // Take mutex guard to make sure users get the room state mutex
|
||||
);
|
||||
|
||||
/// Associates a state with an event.
|
||||
fn set_event_state(shorteventid: u64, shortstatehash: u64) -> Result<()> {
|
||||
fn set_event_state(shorteventid: u64, shortstatehash: u64) -> Result<()>;
|
||||
|
||||
/// Returns all events we would send as the prev_events of the next event.
|
||||
fn get_forward_extremities(room_id: &RoomId) -> Result<HashSet<Arc<EventId>>>;
|
||||
|
@ -18,7 +24,7 @@ pub trait Data {
|
|||
room_id: &RoomId,
|
||||
event_ids: impl IntoIterator<Item = &'_ EventId> + Debug,
|
||||
_mutex_lock: &MutexGuard<'_, StateLock>, // Take mutex guard to make sure users get the room state mutex
|
||||
) -> Result<()> {
|
||||
) -> Result<()>;
|
||||
}
|
||||
|
||||
pub struct StateLock;
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
mod data;
|
||||
pub use data::Data;
|
||||
use std::collections::HashSet;
|
||||
|
||||
use crate::service::*;
|
||||
pub use data::Data;
|
||||
use ruma::{RoomId, events::{room::{member::MembershipState, create::RoomCreateEventContent}, AnyStrippedStateEvent, StateEventType}, UserId, EventId, serde::Raw, RoomVersionId};
|
||||
use serde::Deserialize;
|
||||
use tracing::warn;
|
||||
|
||||
use crate::{service::*, SERVICE, PduEvent, Error, utils::calculate_hash};
|
||||
|
||||
pub struct Service<D: Data> {
|
||||
db: D,
|
||||
|
@ -9,22 +14,20 @@ pub struct Service<D: Data> {
|
|||
|
||||
impl Service<_> {
|
||||
/// Set the room to the given statehash and update caches.
|
||||
#[tracing::instrument(skip(self, new_state_ids_compressed, db))]
|
||||
pub fn force_state(
|
||||
&self,
|
||||
room_id: &RoomId,
|
||||
shortstatehash: u64,
|
||||
statediffnew: HashSet<CompressedStateEvent>,
|
||||
statediffremoved: HashSet<CompressedStateEvent>,
|
||||
db: &Database,
|
||||
) -> Result<()> {
|
||||
|
||||
for event_id in statediffnew.into_iter().filter_map(|new| {
|
||||
state_compressor::parse_compressed_state_event(new)
|
||||
SERVICE.rooms.state_compressor.parse_compressed_state_event(new)
|
||||
.ok()
|
||||
.map(|(_, id)| id)
|
||||
}) {
|
||||
let pdu = match timeline::get_pdu_json(&event_id)? {
|
||||
let pdu = match SERVICE.rooms.timeline.get_pdu_json(&event_id)? {
|
||||
Some(pdu) => pdu,
|
||||
None => continue,
|
||||
};
|
||||
|
@ -60,12 +63,12 @@ impl Service<_> {
|
|||
Err(_) => continue,
|
||||
};
|
||||
|
||||
room::state_cache::update_membership(room_id, &user_id, membership, &pdu.sender, None, db, false)?;
|
||||
SERVICE.room.state_cache.update_membership(room_id, &user_id, membership, &pdu.sender, None, false)?;
|
||||
}
|
||||
|
||||
room::state_cache::update_joined_count(room_id, db)?;
|
||||
SERVICE.room.state_cache.update_joined_count(room_id)?;
|
||||
|
||||
db.set_room_state(room_id, new_shortstatehash);
|
||||
self.db.set_room_state(room_id, shortstatehash);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -74,19 +77,18 @@ impl Service<_> {
|
|||
///
|
||||
/// This adds all current state events (not including the incoming event)
|
||||
/// to `stateid_pduid` and adds the incoming event to `eventid_statehash`.
|
||||
#[tracing::instrument(skip(self, state_ids_compressed, globals))]
|
||||
#[tracing::instrument(skip(self, state_ids_compressed))]
|
||||
pub fn set_event_state(
|
||||
&self,
|
||||
event_id: &EventId,
|
||||
room_id: &RoomId,
|
||||
state_ids_compressed: HashSet<CompressedStateEvent>,
|
||||
globals: &super::globals::Globals,
|
||||
) -> Result<()> {
|
||||
let shorteventid = short::get_or_create_shorteventid(event_id, globals)?;
|
||||
let shorteventid = SERVICE.short.get_or_create_shorteventid(event_id)?;
|
||||
|
||||
let previous_shortstatehash = db.get_room_shortstatehash(room_id)?;
|
||||
let previous_shortstatehash = self.db.get_room_shortstatehash(room_id)?;
|
||||
|
||||
let state_hash = super::calculate_hash(
|
||||
let state_hash = calculate_hash(
|
||||
&state_ids_compressed
|
||||
.iter()
|
||||
.map(|s| &s[..])
|
||||
|
@ -94,11 +96,11 @@ impl Service<_> {
|
|||
);
|
||||
|
||||
let (shortstatehash, already_existed) =
|
||||
short::get_or_create_shortstatehash(&state_hash, globals)?;
|
||||
SERVICE.short.get_or_create_shortstatehash(&state_hash)?;
|
||||
|
||||
if !already_existed {
|
||||
let states_parents = previous_shortstatehash
|
||||
.map_or_else(|| Ok(Vec::new()), |p| room::state_compressor.load_shortstatehash_info(p))?;
|
||||
.map_or_else(|| Ok(Vec::new()), |p| SERVICE.room.state_compressor.load_shortstatehash_info(p))?;
|
||||
|
||||
let (statediffnew, statediffremoved) =
|
||||
if let Some(parent_stateinfo) = states_parents.last() {
|
||||
|
@ -117,7 +119,7 @@ impl Service<_> {
|
|||
} else {
|
||||
(state_ids_compressed, HashSet::new())
|
||||
};
|
||||
state_compressor::save_state_from_diff(
|
||||
SERVICE.room.state_compressor.save_state_from_diff(
|
||||
shortstatehash,
|
||||
statediffnew,
|
||||
statediffremoved,
|
||||
|
@ -126,7 +128,7 @@ impl Service<_> {
|
|||
)?;
|
||||
}
|
||||
|
||||
db.set_event_state(&shorteventid.to_be_bytes(), &shortstatehash.to_be_bytes())?;
|
||||
self.db.set_event_state(&shorteventid.to_be_bytes(), &shortstatehash.to_be_bytes())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -135,13 +137,12 @@ impl Service<_> {
|
|||
///
|
||||
/// This adds all current state events (not including the incoming event)
|
||||
/// to `stateid_pduid` and adds the incoming event to `eventid_statehash`.
|
||||
#[tracing::instrument(skip(self, new_pdu, globals))]
|
||||
#[tracing::instrument(skip(self, new_pdu))]
|
||||
pub fn append_to_state(
|
||||
&self,
|
||||
new_pdu: &PduEvent,
|
||||
globals: &super::globals::Globals,
|
||||
) -> Result<u64> {
|
||||
let shorteventid = self.get_or_create_shorteventid(&new_pdu.event_id, globals)?;
|
||||
let shorteventid = self.get_or_create_shorteventid(&new_pdu.event_id)?;
|
||||
|
||||
let previous_shortstatehash = self.get_room_shortstatehash(&new_pdu.room_id)?;
|
||||
|
||||
|
@ -157,10 +158,9 @@ impl Service<_> {
|
|||
let shortstatekey = self.get_or_create_shortstatekey(
|
||||
&new_pdu.kind.to_string().into(),
|
||||
state_key,
|
||||
globals,
|
||||
)?;
|
||||
|
||||
let new = self.compress_state_event(shortstatekey, &new_pdu.event_id, globals)?;
|
||||
let new = self.compress_state_event(shortstatekey, &new_pdu.event_id)?;
|
||||
|
||||
let replaces = states_parents
|
||||
.last()
|
||||
|
@ -176,7 +176,7 @@ impl Service<_> {
|
|||
}
|
||||
|
||||
// TODO: statehash with deterministic inputs
|
||||
let shortstatehash = globals.next_count()?;
|
||||
let shortstatehash = SERVICE.globals.next_count()?;
|
||||
|
||||
let mut statediffnew = HashSet::new();
|
||||
statediffnew.insert(new);
|
||||
|
@ -254,7 +254,23 @@ impl Service<_> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn db(&self) -> D {
|
||||
&self.db
|
||||
/// Returns the room's version.
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn get_room_version(&self, room_id: &RoomId) -> Result<RoomVersionId> {
|
||||
let create_event = self.room_state_get(room_id, &StateEventType::RoomCreate, "")?;
|
||||
|
||||
let create_event_content: Option<RoomCreateEventContent> = create_event
|
||||
.as_ref()
|
||||
.map(|create_event| {
|
||||
serde_json::from_str(create_event.content.get()).map_err(|e| {
|
||||
warn!("Invalid create event: {}", e);
|
||||
Error::bad_database("Invalid create event in db.")
|
||||
})
|
||||
})
|
||||
.transpose()?;
|
||||
let room_version = create_event_content
|
||||
.map(|create_event| create_event.room_version)
|
||||
.ok_or_else(|| Error::BadDatabase("Invalid room version"))?;
|
||||
Ok(room_version)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
use std::{sync::Arc, collections::HashMap};
|
||||
|
||||
use ruma::{EventId, events::StateEventType, RoomId};
|
||||
|
||||
use crate::PduEvent;
|
||||
|
||||
pub trait Data {
|
||||
/// Builds a StateMap by iterating over all keys that start
|
||||
/// with state_hash, this gives the full state for the given state_hash.
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
mod data;
|
||||
pub use data::Data;
|
||||
use std::{sync::Arc, collections::{HashMap, BTreeMap}};
|
||||
|
||||
use crate::service::*;
|
||||
pub use data::Data;
|
||||
use ruma::{events::StateEventType, RoomId, EventId};
|
||||
|
||||
use crate::{service::*, PduEvent};
|
||||
|
||||
pub struct Service<D: Data> {
|
||||
db: D,
|
||||
|
@ -42,7 +45,7 @@ impl Service<_> {
|
|||
event_type: &StateEventType,
|
||||
state_key: &str,
|
||||
) -> Result<Option<Arc<PduEvent>>> {
|
||||
self.db.pdu_state_get(event_id)
|
||||
self.db.pdu_state_get(shortstatehash, event_type, state_key)
|
||||
}
|
||||
|
||||
/// Returns the state hash for this pdu.
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use ruma::{UserId, RoomId};
|
||||
|
||||
pub trait Data {
|
||||
fn mark_as_once_joined(user_id: &UserId, room_id: &RoomId) -> Result<()>;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
mod data;
|
||||
pub use data::Data;
|
||||
use std::{collections::HashSet, sync::Arc};
|
||||
|
||||
use crate::service::*;
|
||||
pub use data::Data;
|
||||
use regex::Regex;
|
||||
use ruma::{RoomId, UserId, events::{room::{member::MembershipState, create::RoomCreateEventContent}, AnyStrippedStateEvent, StateEventType, tag::TagEvent, RoomAccountDataEventType, GlobalAccountDataEventType, direct::DirectEvent, ignored_user_list::IgnoredUserListEvent, AnySyncStateEvent}, serde::Raw, ServerName};
|
||||
|
||||
use crate::{service::*, SERVICE, utils, Error};
|
||||
|
||||
pub struct Service<D: Data> {
|
||||
db: D,
|
||||
|
@ -9,7 +13,7 @@ pub struct Service<D: Data> {
|
|||
|
||||
impl Service<_> {
|
||||
/// Update current membership data.
|
||||
#[tracing::instrument(skip(self, last_state, db))]
|
||||
#[tracing::instrument(skip(self, last_state))]
|
||||
pub fn update_membership(
|
||||
&self,
|
||||
room_id: &RoomId,
|
||||
|
@ -17,12 +21,11 @@ impl Service<_> {
|
|||
membership: MembershipState,
|
||||
sender: &UserId,
|
||||
last_state: Option<Vec<Raw<AnyStrippedStateEvent>>>,
|
||||
db: &Database,
|
||||
update_joined_count: bool,
|
||||
) -> Result<()> {
|
||||
// Keep track what remote users exist by adding them as "deactivated" users
|
||||
if user_id.server_name() != db.globals.server_name() {
|
||||
db.users.create(user_id, None)?;
|
||||
if user_id.server_name() != SERVICE.globals.server_name() {
|
||||
SERVICE.users.create(user_id, None)?;
|
||||
// TODO: displayname, avatar url
|
||||
}
|
||||
|
||||
|
@ -82,7 +85,7 @@ impl Service<_> {
|
|||
user_id,
|
||||
RoomAccountDataEventType::Tag,
|
||||
)? {
|
||||
db.account_data
|
||||
SERVICE.account_data
|
||||
.update(
|
||||
Some(room_id),
|
||||
user_id,
|
||||
|
@ -94,7 +97,7 @@ impl Service<_> {
|
|||
};
|
||||
|
||||
// Copy direct chat flag
|
||||
if let Some(mut direct_event) = db.account_data.get::<DirectEvent>(
|
||||
if let Some(mut direct_event) = SERVICE.account_data.get::<DirectEvent>(
|
||||
None,
|
||||
user_id,
|
||||
GlobalAccountDataEventType::Direct.to_string().into(),
|
||||
|
@ -109,12 +112,11 @@ impl Service<_> {
|
|||
}
|
||||
|
||||
if room_ids_updated {
|
||||
db.account_data.update(
|
||||
SERVICE.account_data.update(
|
||||
None,
|
||||
user_id,
|
||||
GlobalAccountDataEventType::Direct.to_string().into(),
|
||||
&direct_event,
|
||||
&db.globals,
|
||||
)?;
|
||||
}
|
||||
};
|
||||
|
@ -130,7 +132,7 @@ impl Service<_> {
|
|||
}
|
||||
MembershipState::Invite => {
|
||||
// We want to know if the sender is ignored by the receiver
|
||||
let is_ignored = db
|
||||
let is_ignored = SERVICE
|
||||
.account_data
|
||||
.get::<IgnoredUserListEvent>(
|
||||
None, // Ignored users are in global account data
|
||||
|
@ -186,7 +188,7 @@ impl Service<_> {
|
|||
}
|
||||
|
||||
#[tracing::instrument(skip(self, room_id, db))]
|
||||
pub fn update_joined_count(&self, room_id: &RoomId, db: &Database) -> Result<()> {
|
||||
pub fn update_joined_count(&self, room_id: &RoomId) -> Result<()> {
|
||||
let mut joinedcount = 0_u64;
|
||||
let mut invitedcount = 0_u64;
|
||||
let mut joined_servers = HashSet::new();
|
||||
|
@ -226,11 +228,10 @@ impl Service<_> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self, room_id, db))]
|
||||
#[tracing::instrument(skip(self, room_id))]
|
||||
pub fn get_our_real_users(
|
||||
&self,
|
||||
room_id: &RoomId,
|
||||
db: &Database,
|
||||
) -> Result<Arc<HashSet<Box<UserId>>>> {
|
||||
let maybe = self
|
||||
.our_real_users_cache
|
||||
|
@ -241,7 +242,7 @@ impl Service<_> {
|
|||
if let Some(users) = maybe {
|
||||
Ok(users)
|
||||
} else {
|
||||
self.update_joined_count(room_id, db)?;
|
||||
self.update_joined_count(room_id)?;
|
||||
Ok(Arc::clone(
|
||||
self.our_real_users_cache
|
||||
.read()
|
||||
|
@ -252,12 +253,11 @@ impl Service<_> {
|
|||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self, room_id, appservice, db))]
|
||||
#[tracing::instrument(skip(self, room_id, appservice))]
|
||||
pub fn appservice_in_room(
|
||||
&self,
|
||||
room_id: &RoomId,
|
||||
appservice: &(String, serde_yaml::Value),
|
||||
db: &Database,
|
||||
) -> Result<bool> {
|
||||
let maybe = self
|
||||
.appservice_in_room_cache
|
||||
|
@ -285,7 +285,7 @@ impl Service<_> {
|
|||
.get("sender_localpart")
|
||||
.and_then(|string| string.as_str())
|
||||
.and_then(|string| {
|
||||
UserId::parse_with_server_name(string, db.globals.server_name()).ok()
|
||||
UserId::parse_with_server_name(string, SERVICE.globals.server_name()).ok()
|
||||
});
|
||||
|
||||
let in_room = bridge_user_id
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
struct StateDiff {
|
||||
use crate::service::rooms::CompressedStateEvent;
|
||||
|
||||
pub struct StateDiff {
|
||||
parent: Option<u64>,
|
||||
added: Vec<CompressedStateEvent>,
|
||||
removed: Vec<CompressedStateEvent>,
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
mod data;
|
||||
pub use data::Data;
|
||||
pub mod data;
|
||||
use std::{mem::size_of, sync::Arc, collections::HashSet};
|
||||
|
||||
use crate::service::*;
|
||||
pub use data::Data;
|
||||
use ruma::{EventId, RoomId};
|
||||
|
||||
use crate::{service::*, utils};
|
||||
|
||||
use self::data::StateDiff;
|
||||
|
||||
pub struct Service<D: Data> {
|
||||
db: D,
|
||||
|
@ -30,9 +35,9 @@ impl Service<_> {
|
|||
return Ok(r.clone());
|
||||
}
|
||||
|
||||
self.db.get_statediff(shortstatehash)?;
|
||||
let StateDiff { parent, added, removed } = self.db.get_statediff(shortstatehash)?;
|
||||
|
||||
if parent != 0_u64 {
|
||||
if let Some(parent) = parent {
|
||||
let mut response = self.load_shortstatehash_info(parent)?;
|
||||
let mut state = response.last().unwrap().1.clone();
|
||||
state.extend(added.iter().copied());
|
||||
|
@ -155,7 +160,7 @@ impl Service<_> {
|
|||
|
||||
if parent_states.is_empty() {
|
||||
// There is no parent layer, create a new state
|
||||
self.db.save_statediff(shortstatehash, StateDiff { parent: 0, new: statediffnew, removed: statediffremoved })?;
|
||||
self.db.save_statediff(shortstatehash, StateDiff { parent: None, added: statediffnew, removed: statediffremoved })?;
|
||||
|
||||
return Ok(());
|
||||
};
|
||||
|
@ -197,7 +202,7 @@ impl Service<_> {
|
|||
)?;
|
||||
} else {
|
||||
// Diff small enough, we add diff as layer on top of parent
|
||||
self.db.save_statediff(shortstatehash, StateDiff { parent: parent.0, new: statediffnew, removed: statediffremoved })?;
|
||||
self.db.save_statediff(shortstatehash, StateDiff { parent: Some(parent.0), added: statediffnew, removed: statediffremoved })?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use ruma::{signatures::CanonicalJsonObject, EventId, UserId, RoomId};
|
||||
|
||||
use crate::PduEvent;
|
||||
|
||||
pub trait Data {
|
||||
fn last_timeline_count(&self, sender_user: &UserId, room_id: &RoomId) -> Result<u64>;
|
||||
|
||||
|
@ -5,34 +11,37 @@ pub trait Data {
|
|||
fn get_pdu_count(&self, event_id: &EventId) -> Result<Option<u64>>;
|
||||
|
||||
/// Returns the json of a pdu.
|
||||
pub fn get_pdu_json(&self, event_id: &EventId) -> Result<Option<CanonicalJsonObject>>;
|
||||
fn get_pdu_json(&self, event_id: &EventId) -> Result<Option<CanonicalJsonObject>>;
|
||||
|
||||
/// Returns the json of a pdu.
|
||||
pub fn get_non_outlier_pdu_json(
|
||||
fn get_non_outlier_pdu_json(
|
||||
&self,
|
||||
event_id: &EventId,
|
||||
) -> Result<Option<CanonicalJsonObject>>;
|
||||
|
||||
/// Returns the pdu's id.
|
||||
pub fn get_pdu_id(&self, event_id: &EventId) -> Result<Option<Vec<u8>>>;
|
||||
fn get_pdu_id(&self, event_id: &EventId) -> Result<Option<Vec<u8>>>;
|
||||
|
||||
/// Returns the pdu.
|
||||
///
|
||||
/// Checks the `eventid_outlierpdu` Tree if not found in the timeline.
|
||||
pub fn get_non_outlier_pdu(&self, event_id: &EventId) -> Result<Option<PduEvent>>;
|
||||
fn get_non_outlier_pdu(&self, event_id: &EventId) -> Result<Option<PduEvent>>;
|
||||
|
||||
/// Returns the pdu.
|
||||
///
|
||||
/// Checks the `eventid_outlierpdu` Tree if not found in the timeline.
|
||||
pub fn get_pdu(&self, event_id: &EventId) -> Result<Option<Arc<PduEvent>>>;
|
||||
fn get_pdu(&self, event_id: &EventId) -> Result<Option<Arc<PduEvent>>>;
|
||||
|
||||
/// Returns the pdu.
|
||||
///
|
||||
/// This does __NOT__ check the outliers `Tree`.
|
||||
pub fn get_pdu_from_id(&self, pdu_id: &[u8]) -> Result<Option<PduEvent>>;
|
||||
fn get_pdu_from_id(&self, pdu_id: &[u8]) -> Result<Option<PduEvent>>;
|
||||
|
||||
/// Returns the pdu as a `BTreeMap<String, CanonicalJsonValue>`.
|
||||
pub fn get_pdu_json_from_id(&self, pdu_id: &[u8]) -> Result<Option<CanonicalJsonObject>>;
|
||||
fn get_pdu_json_from_id(&self, pdu_id: &[u8]) -> Result<Option<CanonicalJsonObject>>;
|
||||
|
||||
/// Returns the `count` of this pdu's id.
|
||||
pub fn pdu_count(&self, pdu_id: &[u8]) -> Result<u64>;
|
||||
fn pdu_count(&self, pdu_id: &[u8]) -> Result<u64>;
|
||||
|
||||
/// Removes a pdu and creates a new one with the same id.
|
||||
fn replace_pdu(&self, pdu_id: &[u8], pdu: &PduEvent) -> Result<()>;
|
||||
|
@ -40,7 +49,7 @@ pub trait Data {
|
|||
/// Returns an iterator over all events in a room that happened after the event with id `since`
|
||||
/// in chronological order.
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn pdus_since<'a>(
|
||||
fn pdus_since<'a>(
|
||||
&'a self,
|
||||
user_id: &UserId,
|
||||
room_id: &RoomId,
|
||||
|
@ -50,14 +59,14 @@ pub trait Data {
|
|||
/// Returns an iterator over all events and their tokens in a room that happened before the
|
||||
/// event with id `until` in reverse-chronological order.
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn pdus_until<'a>(
|
||||
fn pdus_until<'a>(
|
||||
&'a self,
|
||||
user_id: &UserId,
|
||||
room_id: &RoomId,
|
||||
until: u64,
|
||||
) -> Result<impl Iterator<Item = Result<(Vec<u8>, PduEvent)>> + 'a>;
|
||||
|
||||
pub fn pdus_after<'a>(
|
||||
fn pdus_after<'a>(
|
||||
&'a self,
|
||||
user_id: &UserId,
|
||||
room_id: &RoomId,
|
||||
|
|
|
@ -1,7 +1,17 @@
|
|||
mod data;
|
||||
pub use data::Data;
|
||||
use std::{sync::MutexGuard, iter, collections::HashSet};
|
||||
use std::fmt::Debug;
|
||||
|
||||
use crate::service::*;
|
||||
pub use data::Data;
|
||||
use regex::Regex;
|
||||
use ruma::signatures::CanonicalJsonValue;
|
||||
use ruma::{EventId, signatures::CanonicalJsonObject, push::{Action, Tweak}, events::{push_rules::PushRulesEvent, GlobalAccountDataEventType, RoomEventType, room::{member::MembershipState, create::RoomCreateEventContent}, StateEventType}, UserId, RoomAliasId, RoomId, uint, state_res, api::client::error::ErrorKind, serde::to_canonical_value, ServerName};
|
||||
use serde::Deserialize;
|
||||
use serde_json::value::to_raw_value;
|
||||
use tracing::{warn, error};
|
||||
|
||||
use crate::SERVICE;
|
||||
use crate::{service::{*, pdu::{PduBuilder, EventHash}}, Error, PduEvent, utils};
|
||||
|
||||
pub struct Service<D: Data> {
|
||||
db: D,
|
||||
|
@ -126,13 +136,12 @@ impl Service<_> {
|
|||
/// in `append_pdu`.
|
||||
///
|
||||
/// Returns pdu id
|
||||
#[tracing::instrument(skip(self, pdu, pdu_json, leaves, db))]
|
||||
#[tracing::instrument(skip(self, pdu, pdu_json, leaves))]
|
||||
pub fn append_pdu<'a>(
|
||||
&self,
|
||||
pdu: &PduEvent,
|
||||
mut pdu_json: CanonicalJsonObject,
|
||||
leaves: impl IntoIterator<Item = &'a EventId> + Debug,
|
||||
db: &Database,
|
||||
) -> Result<Vec<u8>> {
|
||||
let shortroomid = self.get_shortroomid(&pdu.room_id)?.expect("room exists");
|
||||
|
||||
|
@ -249,7 +258,6 @@ impl Service<_> {
|
|||
&power_levels,
|
||||
&sync_pdu,
|
||||
&pdu.room_id,
|
||||
db,
|
||||
)? {
|
||||
match action {
|
||||
Action::DontNotify => notify = false,
|
||||
|
@ -446,9 +454,8 @@ impl Service<_> {
|
|||
pdu_builder: PduBuilder,
|
||||
sender: &UserId,
|
||||
room_id: &RoomId,
|
||||
db: &Database,
|
||||
_mutex_lock: &MutexGuard<'_, ()>, // Take mutex guard to make sure users get the room state mutex
|
||||
) -> (PduEvent, CanonicalJsonObj) {
|
||||
) -> (PduEvent, CanonicalJsonObject) {
|
||||
let PduBuilder {
|
||||
event_type,
|
||||
content,
|
||||
|
@ -457,14 +464,14 @@ impl Service<_> {
|
|||
redacts,
|
||||
} = pdu_builder;
|
||||
|
||||
let prev_events: Vec<_> = db
|
||||
let prev_events: Vec<_> = SERVICE
|
||||
.rooms
|
||||
.get_pdu_leaves(room_id)?
|
||||
.into_iter()
|
||||
.take(20)
|
||||
.collect();
|
||||
|
||||
let create_event = db
|
||||
let create_event = SERVICE
|
||||
.rooms
|
||||
.room_state_get(room_id, &StateEventType::RoomCreate, "")?;
|
||||
|
||||
|
@ -481,7 +488,7 @@ impl Service<_> {
|
|||
// If there was no create event yet, assume we are creating a room with the default
|
||||
// version right now
|
||||
let room_version_id = create_event_content
|
||||
.map_or(db.globals.default_room_version(), |create_event| {
|
||||
.map_or(SERVICE.globals.default_room_version(), |create_event| {
|
||||
create_event.room_version
|
||||
});
|
||||
let room_version =
|
||||
|
@ -575,8 +582,8 @@ impl Service<_> {
|
|||
);
|
||||
|
||||
match ruma::signatures::hash_and_sign_event(
|
||||
db.globals.server_name().as_str(),
|
||||
db.globals.keypair(),
|
||||
SERVICE.globals.server_name().as_str(),
|
||||
SERVICE.globals.keypair(),
|
||||
&mut pdu_json,
|
||||
&room_version_id,
|
||||
) {
|
||||
|
@ -614,22 +621,21 @@ impl Service<_> {
|
|||
|
||||
/// Creates a new persisted data unit and adds it to a room. This function takes a
|
||||
/// roomid_mutex_state, meaning that only this function is able to mutate the room state.
|
||||
#[tracing::instrument(skip(self, db, _mutex_lock))]
|
||||
#[tracing::instrument(skip(self, _mutex_lock))]
|
||||
pub fn build_and_append_pdu(
|
||||
&self,
|
||||
pdu_builder: PduBuilder,
|
||||
sender: &UserId,
|
||||
room_id: &RoomId,
|
||||
db: &Database,
|
||||
_mutex_lock: &MutexGuard<'_, ()>, // Take mutex guard to make sure users get the room state mutex
|
||||
) -> Result<Arc<EventId>> {
|
||||
|
||||
let (pdu, pdu_json) = create_hash_and_sign_event()?;
|
||||
let (pdu, pdu_json) = self.create_hash_and_sign_event()?;
|
||||
|
||||
|
||||
// We append to state before appending the pdu, so we don't have a moment in time with the
|
||||
// pdu without it's state. This is okay because append_pdu can't fail.
|
||||
let statehashid = self.append_to_state(&pdu, &db.globals)?;
|
||||
let statehashid = self.append_to_state(&pdu)?;
|
||||
|
||||
let pdu_id = self.append_pdu(
|
||||
&pdu,
|
||||
|
@ -637,7 +643,6 @@ impl Service<_> {
|
|||
// Since this PDU references all pdu_leaves we can update the leaves
|
||||
// of the room
|
||||
iter::once(&*pdu.event_id),
|
||||
db,
|
||||
)?;
|
||||
|
||||
// We set the room state after inserting the pdu, so that we never have a moment in time
|
||||
|
@ -659,9 +664,9 @@ impl Service<_> {
|
|||
}
|
||||
|
||||
// Remove our server from the server list since it will be added to it by room_servers() and/or the if statement above
|
||||
servers.remove(db.globals.server_name());
|
||||
servers.remove(SERVICE.globals.server_name());
|
||||
|
||||
db.sending.send_pdu(servers.into_iter(), &pdu_id)?;
|
||||
SERVICE.sending.send_pdu(servers.into_iter(), &pdu_id)?;
|
||||
|
||||
Ok(pdu.event_id)
|
||||
}
|
||||
|
@ -670,7 +675,6 @@ impl Service<_> {
|
|||
/// server that sent the event.
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn append_incoming_pdu<'a>(
|
||||
db: &Database,
|
||||
pdu: &PduEvent,
|
||||
pdu_json: CanonicalJsonObject,
|
||||
new_room_leaves: impl IntoIterator<Item = &'a EventId> + Clone + Debug,
|
||||
|
@ -680,21 +684,20 @@ impl Service<_> {
|
|||
) -> Result<Option<Vec<u8>>> {
|
||||
// We append to state before appending the pdu, so we don't have a moment in time with the
|
||||
// pdu without it's state. This is okay because append_pdu can't fail.
|
||||
db.rooms.set_event_state(
|
||||
SERVICE.rooms.set_event_state(
|
||||
&pdu.event_id,
|
||||
&pdu.room_id,
|
||||
state_ids_compressed,
|
||||
&db.globals,
|
||||
)?;
|
||||
|
||||
if soft_fail {
|
||||
db.rooms
|
||||
SERVICE.rooms
|
||||
.mark_as_referenced(&pdu.room_id, &pdu.prev_events)?;
|
||||
db.rooms.replace_pdu_leaves(&pdu.room_id, new_room_leaves)?;
|
||||
SERVICE.rooms.replace_pdu_leaves(&pdu.room_id, new_room_leaves)?;
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let pdu_id = db.rooms.append_pdu(pdu, pdu_json, new_room_leaves, db)?;
|
||||
let pdu_id = SERVICE.rooms.append_pdu(pdu, pdu_json, new_room_leaves)?;
|
||||
|
||||
Ok(Some(pdu_id))
|
||||
}
|
||||
|
@ -756,4 +759,4 @@ impl Service<_> {
|
|||
// If event does not exist, just noop
|
||||
Ok(())
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
mod data;
|
||||
pub use data::Data;
|
||||
use ruma::{RoomId, UserId};
|
||||
|
||||
use crate::service::*;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue