Merge remote-tracking branch 'upstream/main' into conduwuit-changes

This commit is contained in:
strawberry 2024-09-17 17:55:49 -04:00
commit 9900d06765
6 changed files with 88 additions and 22 deletions

View File

@ -23,7 +23,9 @@ use ruma_events::{
};
use serde::{de::Error as _, Deserialize, Serialize};
use super::{v5, DeviceLists, UnreadNotificationsCount};
#[cfg(feature = "unstable-msc4186")]
use super::v5;
use super::{DeviceLists, UnreadNotificationsCount};
const METADATA: Metadata = metadata! {
method: POST,
@ -928,6 +930,7 @@ impl Typing {
}
}
#[cfg(feature = "unstable-msc4186")]
impl From<v5::Request> for Request {
fn from(value: v5::Request) -> Self {
Self {
@ -952,6 +955,7 @@ impl From<v5::Request> for Request {
}
}
#[cfg(feature = "unstable-msc4186")]
impl From<v5::request::List> for SyncRequestList {
fn from(value: v5::request::List) -> Self {
Self {
@ -974,12 +978,14 @@ impl From<v5::request::List> for SyncRequestList {
}
}
#[cfg(feature = "unstable-msc4186")]
impl From<v5::request::RoomDetails> for RoomDetailsConfig {
fn from(value: v5::request::RoomDetails) -> Self {
Self { required_state: value.required_state, timeline_limit: value.timeline_limit }
}
}
#[cfg(feature = "unstable-msc4186")]
impl From<v5::request::ListFilters> for SyncRequestListFilters {
fn from(value: v5::request::ListFilters) -> Self {
Self {
@ -990,6 +996,7 @@ impl From<v5::request::ListFilters> for SyncRequestListFilters {
}
}
#[cfg(feature = "unstable-msc4186")]
impl From<v5::request::RoomSubscription> for RoomSubscription {
fn from(value: v5::request::RoomSubscription) -> Self {
Self {
@ -1000,6 +1007,7 @@ impl From<v5::request::RoomSubscription> for RoomSubscription {
}
}
#[cfg(feature = "unstable-msc4186")]
impl From<v5::request::Extensions> for ExtensionsConfig {
fn from(value: v5::request::Extensions) -> Self {
Self {
@ -1014,6 +1022,7 @@ impl From<v5::request::Extensions> for ExtensionsConfig {
}
}
#[cfg(feature = "unstable-msc4186")]
impl From<v5::request::ToDevice> for ToDeviceConfig {
fn from(value: v5::request::ToDevice) -> Self {
Self {
@ -1026,18 +1035,21 @@ impl From<v5::request::ToDevice> for ToDeviceConfig {
}
}
#[cfg(feature = "unstable-msc4186")]
impl From<v5::request::E2EE> for E2EEConfig {
fn from(value: v5::request::E2EE) -> Self {
Self { enabled: value.enabled }
}
}
#[cfg(feature = "unstable-msc4186")]
impl From<v5::request::AccountData> for AccountDataConfig {
fn from(value: v5::request::AccountData) -> Self {
Self { enabled: value.enabled, lists: value.lists, rooms: value.rooms }
}
}
#[cfg(feature = "unstable-msc4186")]
impl From<v5::request::Receipts> for ReceiptsConfig {
fn from(value: v5::request::Receipts) -> Self {
Self {
@ -1048,6 +1060,7 @@ impl From<v5::request::Receipts> for ReceiptsConfig {
}
}
#[cfg(feature = "unstable-msc4186")]
impl From<v5::request::ReceiptsRoom> for RoomReceiptConfig {
fn from(value: v5::request::ReceiptsRoom) -> Self {
match value {
@ -1057,6 +1070,7 @@ impl From<v5::request::ReceiptsRoom> for RoomReceiptConfig {
}
}
#[cfg(feature = "unstable-msc4186")]
impl From<v5::request::Typing> for TypingConfig {
fn from(value: v5::request::Typing) -> Self {
Self { enabled: value.enabled, lists: value.lists, rooms: value.rooms }

View File

@ -18,6 +18,11 @@ Improvements:
- Stabilize support for muting in VoIP calls, according to Matrix 1.11
- All the root `Any*EventContent` types now have a `EventContentFromType` implementations
automatically derived by the `event_enum!` macro.
- `CallMemberEventContent` now supports two different formats: Session memberships and Legacy memberships.
The new format (Session) is required to reliably display the call member count (reliable call member events).
`CallMemberEventContent` is now an enum to model the two different formats.
- `CallMemberStateKey` (instead of `OwnedUserId`) is now used as the state key type for `CallMemberEventContent`.
This guarantees correct formatting of the event key.
Breaking changes:

View File

@ -11,7 +11,7 @@ mod member_state_key;
pub use focus::*;
pub use member_data::*;
pub use member_state_key::*;
use ruma_common::MilliSecondsSinceUnixEpoch;
use ruma_common::{MilliSecondsSinceUnixEpoch, OwnedDeviceId};
use ruma_macros::{EventContent, StringEnum};
use serde::{Deserialize, Serialize};
@ -56,7 +56,7 @@ impl CallMemberEventContent {
/// Creates a new [`CallMemberEventContent`] with [`SessionMembershipData`].
pub fn new(
application: Application,
device_id: String,
device_id: OwnedDeviceId,
focus_active: ActiveFocus,
foci_preferred: Vec<Focus>,
created_ts: Option<MilliSecondsSinceUnixEpoch>,
@ -234,8 +234,8 @@ mod tests {
use assert_matches2::assert_matches;
use ruma_common::{
device_id, user_id, MilliSecondsSinceUnixEpoch as TS, OwnedEventId, OwnedRoomId,
OwnedUserId,
device_id, owned_device_id, user_id, MilliSecondsSinceUnixEpoch as TS, OwnedEventId,
OwnedRoomId, OwnedUserId,
};
use serde_json::{from_value as from_json_value, json, Value as JsonValue};
@ -257,7 +257,7 @@ mod tests {
call_id: "123456".to_owned(),
scope: CallScope::Room,
}),
device_id: "ABCDE".to_owned(),
device_id: owned_device_id!("ABCDE"),
expires: Duration::from_secs(3600),
foci_active: vec![Focus::Livekit(LivekitFocus {
alias: "1".to_owned(),
@ -274,7 +274,7 @@ mod tests {
call_id: "123456".to_owned(),
scope: CallScope::Room,
}),
"ABCDE".to_owned(),
owned_device_id!("ABCDE"),
ActiveFocus::Livekit(ActiveLivekitFocus {
focus_selection: FocusSelection::OldestMembership,
}),
@ -354,7 +354,7 @@ mod tests {
call_id: "123456".to_owned(),
scope: CallScope::Room,
}),
"THIS_DEVICE".to_owned(),
owned_device_id!("THIS_DEVICE"),
ActiveFocus::Livekit(ActiveLivekitFocus {
focus_selection: FocusSelection::OldestMembership,
}),
@ -404,7 +404,7 @@ mod tests {
call_id: "123456".to_owned(),
scope: CallScope::Room,
}),
device_id: "THIS_DEVICE".to_owned(),
device_id: owned_device_id!("THIS_DEVICE"),
expires: Duration::from_secs(3600),
foci_active: vec![Focus::Livekit(LivekitFocus {
alias: "room1".to_owned(),
@ -418,7 +418,7 @@ mod tests {
call_id: "".to_owned(),
scope: CallScope::Room,
}),
device_id: "OTHER_DEVICE".to_owned(),
device_id: owned_device_id!("OTHER_DEVICE"),
expires: Duration::from_secs(3600),
foci_active: vec![Focus::Livekit(LivekitFocus {
alias: "room2".to_owned(),
@ -526,7 +526,7 @@ mod tests {
call_id: "".to_owned(),
scope: CallScope::Room,
}),
device_id: "THIS_DEVICE".to_owned(),
device_id: owned_device_id!("THIS_DEVICE"),
foci_preferred: [Focus::Livekit(LivekitFocus {
alias: "room1".to_owned(),
service_url: "https://livekit1.com".to_owned(),

View File

@ -5,7 +5,7 @@
use std::time::Duration;
use as_variant::as_variant;
use ruma_common::MilliSecondsSinceUnixEpoch;
use ruma_common::{DeviceId, MilliSecondsSinceUnixEpoch, OwnedDeviceId};
use ruma_macros::StringEnum;
use serde::{Deserialize, Serialize};
use tracing::warn;
@ -41,7 +41,7 @@ impl<'a> MembershipData<'a> {
}
/// The device id of this membership.
pub fn device_id(&self) -> &String {
pub fn device_id(&self) -> &DeviceId {
match self {
MembershipData::Legacy(data) => &data.device_id,
MembershipData::Session(data) => &data.device_id,
@ -121,7 +121,7 @@ pub struct LegacyMembershipData {
/// The device id of this membership.
///
/// The same user can join with their phone/computer.
pub device_id: String,
pub device_id: OwnedDeviceId,
/// The duration in milliseconds relative to the time this membership joined
/// during which the membership is valid.
@ -190,7 +190,7 @@ pub struct LegacyMembershipDataInit {
/// The device id of this membership.
///
/// The same user can join with their phone/computer.
pub device_id: String,
pub device_id: OwnedDeviceId,
/// The duration in milliseconds relative to the time this membership joined
/// during which the membership is valid.
@ -236,7 +236,7 @@ pub struct SessionMembershipData {
/// The device id of this membership.
///
/// The same user can join with their phone/computer.
pub device_id: String,
pub device_id: OwnedDeviceId,
/// A list of the foci that this membership proposes to use.
pub foci_preferred: Vec<Focus>,

View File

@ -16,11 +16,11 @@ pub struct CallMemberStateKey {
impl CallMemberStateKey {
/// Constructs a new CallMemberStateKey there are three possible formats:
/// - "_{UserId}_{DeviceId}" example: "_@test:user.org_DEVICE". `device_id`: Some`, `underscore:
/// - `_{UserId}_{DeviceId}` example: `_@test:user.org_DEVICE`. `device_id: Some`, `underscore:
/// true`
/// - "{UserId}_{DeviceId}" example: "@test:user.org_DEVICE". `device_id`: Some`, `underscore:
/// - `{UserId}_{DeviceId}` example: `@test:user.org_DEVICE`. `device_id: Some`, `underscore:
/// false`
/// - "{UserId}" example example: "@test:user.org". `device_id`: None`, underscore is ignored:
/// - `{UserId}` example: `@test:user.org`. `device_id: None`, underscore is ignored:
/// `underscore: false|true`
///
/// Dependent on the parameters the correct CallMemberStateKey will be constructed.

View File

@ -174,12 +174,20 @@ fn try_from_multipart_mixed_response<T: AsRef<[u8]>>(
let mut full_boundary = Vec::with_capacity(boundary.len() + 4);
full_boundary.extend_from_slice(b"\r\n--");
full_boundary.extend_from_slice(boundary);
let full_boundary_no_crlf = full_boundary.strip_prefix(b"\r\n").unwrap();
let mut boundaries = memchr::memmem::find_iter(body, &full_boundary);
let metadata_start = boundaries.next().ok_or_else(|| {
MultipartMixedDeserializationError::MissingBodyParts { expected: 2, found: 0 }
})? + full_boundary.len();
let metadata_start = if body.starts_with(full_boundary_no_crlf) {
// If there is no preamble before the first boundary, it may omit the
// preceding CRLF.
full_boundary_no_crlf.len()
} else {
boundaries.next().ok_or_else(|| MultipartMixedDeserializationError::MissingBodyParts {
expected: 2,
found: 0,
})? + full_boundary.len()
};
let metadata_end = boundaries.next().ok_or_else(|| {
MultipartMixedDeserializationError::MissingBodyParts { expected: 2, found: 0 }
})?;
@ -417,6 +425,15 @@ mod tests {
.unwrap();
try_from_multipart_mixed_response(response).unwrap_err();
// Boundary without CRLF with preamble.
let body = "foo--abcdef\r\n\r\n{}\r\n--abcdef\r\n\r\nsome plain text\r\n--abcdef--";
let response = http::Response::builder()
.header(http::header::CONTENT_TYPE, "multipart/mixed; boundary=abcdef")
.body(body)
.unwrap();
try_from_multipart_mixed_response(response).unwrap_err();
}
#[test]
@ -483,6 +500,36 @@ mod tests {
assert_eq!(file_content.content_type.unwrap(), "text/plain");
assert_eq!(file_content.content_disposition, None);
// No leading CRLF (and no preamble)
let body = "--abcdef\r\n\r\n{}\r\n--abcdef\r\n\r\nsome plain text\r\n--abcdef--";
let response = http::Response::builder()
.header(http::header::CONTENT_TYPE, "multipart/mixed; boundary=abcdef")
.body(body)
.unwrap();
let (_metadata, content) = try_from_multipart_mixed_response(response).unwrap();
assert_matches!(content, FileOrLocation::File(file_content));
assert_eq!(file_content.file, b"some plain text");
assert_eq!(file_content.content_type, None);
assert_eq!(file_content.content_disposition, None);
// Boundary text in preamble, but no leading CRLF, so it should be
// ignored.
let body =
"foo--abcdef\r\n--abcdef\r\n\r\n{}\r\n--abcdef\r\n\r\nsome plain text\r\n--abcdef--";
let response = http::Response::builder()
.header(http::header::CONTENT_TYPE, "multipart/mixed; boundary=abcdef")
.body(body)
.unwrap();
let (_metadata, content) = try_from_multipart_mixed_response(response).unwrap();
assert_matches!(content, FileOrLocation::File(file_content));
assert_eq!(file_content.file, b"some plain text");
assert_eq!(file_content.content_type, None);
assert_eq!(file_content.content_disposition, None);
// No body part headers.
let body = "\r\n--abcdef\r\n\r\n{}\r\n--abcdef\r\n\r\nsome plain text\r\n--abcdef--";
let response = http::Response::builder()