diff --git a/crates/ruma-common/CHANGELOG.md b/crates/ruma-common/CHANGELOG.md index 514c145e..5a28a2da 100644 --- a/crates/ruma-common/CHANGELOG.md +++ b/crates/ruma-common/CHANGELOG.md @@ -13,6 +13,11 @@ Breaking changes: - Remove the `DontNotify` and `Coalesce` variants of `push::Action` according to MSC3987 - Old push rules will still deserialize successfully but the `Coalesce` variant will not return `true` for `Action::should_notify()` anymore +- Remove `AnswerSessionDescription` and `OfferSessionDescription` types, use `SessionDescription` + instead. + - Remove `SessionDescriptionType`, use a `String` instead. A clarification in MSC2746 / Matrix 1.7 + explains that the `type` field should not be validated but passed as-is to the WebRTC API. It + also avoids an unnecessary conversion between the WebRTC API and the Ruma type. Improvements: diff --git a/crates/ruma-common/src/events/call.rs b/crates/ruma-common/src/events/call.rs index b6c85617..bdc8a1e2 100644 --- a/crates/ruma-common/src/events/call.rs +++ b/crates/ruma-common/src/events/call.rs @@ -15,8 +15,6 @@ pub mod select_answer; use serde::{Deserialize, Serialize}; -use crate::{serde::StringEnum, PrivOwnedStr}; - /// A VoIP session description. /// /// This is the same type as WebRTC's [`RTCSessionDescriptionInit`]. @@ -26,8 +24,10 @@ use crate::{serde::StringEnum, PrivOwnedStr}; #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] pub struct SessionDescription { /// The type of session description. + /// + /// This is the `type` field of `RTCSessionDescriptionInit`. #[serde(rename = "type")] - pub session_type: SessionDescriptionType, + pub session_type: String, /// The SDP text of the session description. /// @@ -39,73 +39,11 @@ pub struct SessionDescription { impl SessionDescription { /// Creates a new `SessionDescription` with the given session type and SDP text. - pub fn new(session_type: SessionDescriptionType, sdp: String) -> Self { + pub fn new(session_type: String, sdp: String) -> Self { Self { session_type, sdp } } } -/// The type of VoIP session description. -/// -/// This is the same type as WebRTC's [`RTCSdpType`]. -/// -/// [`RTCSdpType`]: (https://www.w3.org/TR/webrtc/#dom-rtcsdptype): -#[doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/doc/string_enum.md"))] -#[derive(Clone, PartialEq, Eq, StringEnum)] -#[ruma_enum(rename_all = "lowercase")] -#[non_exhaustive] -pub enum SessionDescriptionType { - /// The description must be treated as an SDP final answer, and the offer-answer exchange must - /// be considered complete. - Answer, - - /// The description must be treated as an SDP offer. - Offer, - - /// The description must be treated as an SDP answer, but not final. - #[cfg(feature = "unstable-msc2746")] - PrAnswer, - - /// The description must be treated as cancelling the current SDP negotiation and moving the - /// SDP offer back to what it was in the previous stable state. - #[cfg(feature = "unstable-msc2746")] - Rollback, - - #[doc(hidden)] - _Custom(PrivOwnedStr), -} - -/// A VoIP answer session description. -#[derive(Clone, Debug, Deserialize, Serialize)] -#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] -#[serde(tag = "type", rename = "answer")] -pub struct AnswerSessionDescription { - /// The SDP text of the session description. - pub sdp: String, -} - -impl AnswerSessionDescription { - /// Creates a new `AnswerSessionDescription` with the given SDP text. - pub fn new(sdp: String) -> Self { - Self { sdp } - } -} - -/// A VoIP offer session description. -#[derive(Clone, Debug, Deserialize, Serialize)] -#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] -#[serde(tag = "type", rename = "offer")] -pub struct OfferSessionDescription { - /// The SDP text of the session description. - pub sdp: String, -} - -impl OfferSessionDescription { - /// Creates a new `OfferSessionDescription` with the given SDP text. - pub fn new(sdp: String) -> Self { - Self { sdp } - } -} - /// The capabilities of a client in a VoIP call. #[cfg(feature = "unstable-msc2747")] #[derive(Clone, Debug, Default, Serialize, Deserialize)] diff --git a/crates/ruma-common/src/events/call/answer.rs b/crates/ruma-common/src/events/call/answer.rs index c23fbf8f..a8cc0c60 100644 --- a/crates/ruma-common/src/events/call/answer.rs +++ b/crates/ruma-common/src/events/call/answer.rs @@ -5,9 +5,9 @@ use ruma_macros::EventContent; use serde::{Deserialize, Serialize}; -use super::AnswerSessionDescription; #[cfg(feature = "unstable-msc2747")] use super::CallCapabilities; +use super::SessionDescription; use crate::{OwnedVoipId, VoipVersionId}; /// The content of an `m.call.answer` event. @@ -18,7 +18,7 @@ use crate::{OwnedVoipId, VoipVersionId}; #[ruma_event(type = "m.call.answer", kind = MessageLike)] pub struct CallAnswerEventContent { /// The VoIP session description object. - pub answer: AnswerSessionDescription, + pub answer: SessionDescription, /// A unique identifier for the call. pub call_id: OwnedVoipId, @@ -39,11 +39,7 @@ pub struct CallAnswerEventContent { impl CallAnswerEventContent { /// Creates an `CallAnswerEventContent` with the given answer, call ID and VoIP version. - pub fn new( - answer: AnswerSessionDescription, - call_id: OwnedVoipId, - version: VoipVersionId, - ) -> Self { + pub fn new(answer: SessionDescription, call_id: OwnedVoipId, version: VoipVersionId) -> Self { Self { answer, call_id, @@ -57,7 +53,7 @@ impl CallAnswerEventContent { /// Convenience method to create a VoIP version 0 `CallAnswerEventContent` with all the required /// fields. - pub fn version_0(answer: AnswerSessionDescription, call_id: OwnedVoipId) -> Self { + pub fn version_0(answer: SessionDescription, call_id: OwnedVoipId) -> Self { Self::new(answer, call_id, VoipVersionId::V0) } @@ -65,7 +61,7 @@ impl CallAnswerEventContent { /// fields. #[cfg(feature = "unstable-msc2746")] pub fn version_1( - answer: AnswerSessionDescription, + answer: SessionDescription, call_id: OwnedVoipId, party_id: OwnedVoipId, ) -> Self { diff --git a/crates/ruma-common/src/events/call/invite.rs b/crates/ruma-common/src/events/call/invite.rs index 205a014e..132ad4d6 100644 --- a/crates/ruma-common/src/events/call/invite.rs +++ b/crates/ruma-common/src/events/call/invite.rs @@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize}; #[cfg(feature = "unstable-msc2747")] use super::CallCapabilities; -use super::OfferSessionDescription; +use super::SessionDescription; #[cfg(feature = "unstable-msc2746")] use crate::OwnedUserId; use crate::{OwnedVoipId, VoipVersionId}; @@ -35,7 +35,7 @@ pub struct CallInviteEventContent { pub lifetime: UInt, /// The session description object. - pub offer: OfferSessionDescription, + pub offer: SessionDescription, /// The version of the VoIP specification this messages adheres to. pub version: VoipVersionId, @@ -61,7 +61,7 @@ impl CallInviteEventContent { pub fn new( call_id: OwnedVoipId, lifetime: UInt, - offer: OfferSessionDescription, + offer: SessionDescription, version: VoipVersionId, ) -> Self { Self { @@ -80,7 +80,7 @@ impl CallInviteEventContent { /// Convenience method to create a version 0 `CallInviteEventContent` with all the required /// fields. - pub fn version_0(call_id: OwnedVoipId, lifetime: UInt, offer: OfferSessionDescription) -> Self { + pub fn version_0(call_id: OwnedVoipId, lifetime: UInt, offer: SessionDescription) -> Self { Self::new(call_id, lifetime, offer, VoipVersionId::V0) } @@ -91,7 +91,7 @@ impl CallInviteEventContent { call_id: OwnedVoipId, party_id: OwnedVoipId, lifetime: UInt, - offer: OfferSessionDescription, + offer: SessionDescription, ) -> Self { Self { call_id, diff --git a/crates/ruma-common/tests/events/call.rs b/crates/ruma-common/tests/events/call.rs index 54d9d2dd..616f69bd 100644 --- a/crates/ruma-common/tests/events/call.rs +++ b/crates/ruma-common/tests/events/call.rs @@ -8,7 +8,7 @@ use ruma_common::{ candidates::{CallCandidatesEventContent, Candidate}, hangup::CallHangupEventContent, invite::CallInviteEventContent, - AnswerSessionDescription, OfferSessionDescription, + SessionDescription, }, AnyMessageLikeEvent, AnySyncMessageLikeEvent, MessageLikeEvent, }, @@ -21,7 +21,7 @@ use serde_json::{from_value as from_json_value, json, to_value as to_json_value} #[test] fn answer_content_serialization() { let event_content = CallAnswerEventContent::version_0( - AnswerSessionDescription::new("not a real sdp".to_owned()), + SessionDescription::new("answer".to_owned(), "not a real sdp".to_owned()), "abcdef".into(), ); @@ -51,6 +51,7 @@ fn answer_content_deserialization() { let content = from_json_value::(json_data).unwrap(); + assert_eq!(content.answer.session_type, "answer"); assert_eq!(content.answer.sdp, "Hello"); assert_eq!(content.call_id, "foofoo"); assert_eq!(content.version, VoipVersionId::V0); @@ -85,6 +86,7 @@ fn answer_event_deserialization() { assert!(message_event.unsigned.is_empty()); let content = message_event.content; + assert_eq!(content.answer.session_type, "answer"); assert_eq!(content.answer.sdp, "Hello"); assert_eq!(content.call_id, "foofoo"); assert_eq!(content.version, VoipVersionId::V0); @@ -131,7 +133,7 @@ fn invite_content_serialization() { let event_content = CallInviteEventContent::version_0( "abcdef".into(), uint!(30000), - OfferSessionDescription::new("not a real sdp".to_owned()), + SessionDescription::new("offer".to_owned(), "not a real sdp".to_owned()), ); assert_eq!( @@ -203,8 +205,7 @@ mod msc2746 { negotiate::CallNegotiateEventContent, reject::CallRejectEventContent, select_answer::CallSelectAnswerEventContent, - AnswerSessionDescription, OfferSessionDescription, SessionDescription, - SessionDescriptionType, + SessionDescription, }, AnyMessageLikeEvent, MessageLikeEvent, }, @@ -218,7 +219,7 @@ mod msc2746 { "abcdef".into(), "9876".into(), uint!(60000), - OfferSessionDescription::new("not a real sdp".to_owned()), + SessionDescription::new("offer".to_owned(), "not a real sdp".to_owned()), ); assert_eq!( @@ -266,13 +267,14 @@ mod msc2746 { assert_eq!(content.party_id.unwrap(), "9876"); assert_eq!(content.lifetime, uint!(60000)); assert_eq!(content.version, VoipVersionId::V1); + assert_eq!(content.offer.session_type, "offer"); assert_eq!(content.offer.sdp, "not a real sdp"); } #[test] fn answer_event_serialization() { let content = CallAnswerEventContent::version_1( - AnswerSessionDescription::new("not a real sdp".to_owned()), + SessionDescription::new("answer".to_owned(), "not a real sdp".to_owned()), "abcdef".into(), "9876".into(), ); @@ -296,7 +298,7 @@ mod msc2746 { fn answer_event_capabilities_serialization() { let content = assign!( CallAnswerEventContent::version_1( - AnswerSessionDescription::new("not a real sdp".to_owned()), + SessionDescription::new("answer".to_owned(), "not a real sdp".to_owned()), "abcdef".into(), "9876".into() ), @@ -353,6 +355,7 @@ mod msc2746 { assert_eq!(content.call_id, "abcdef"); assert_eq!(content.party_id.unwrap(), "9876"); assert_eq!(content.version.as_ref(), "org.matrix.1b"); + assert_eq!(content.answer.session_type, "answer"); assert_eq!(content.answer.sdp, "not a real sdp"); #[cfg(feature = "unstable-msc2747")] assert!(content.capabilities.dtmf); @@ -485,7 +488,7 @@ mod msc2746 { "abcdef".into(), "9876".into(), uint!(30000), - SessionDescription::new(SessionDescriptionType::Offer, "not a real sdp".to_owned()), + SessionDescription::new("offer".to_owned(), "not a real sdp".to_owned()), ); assert_eq!( @@ -512,7 +515,7 @@ mod msc2746 { "version": "1", "lifetime": 30000, "description": { - "type": "pranswer", + "type": "answer", "sdp": "not a real sdp", } }, @@ -532,7 +535,7 @@ mod msc2746 { assert_eq!(content.call_id, "abcdef"); assert_eq!(content.party_id, "9876"); assert_eq!(content.lifetime, uint!(30000)); - assert_eq!(content.description.session_type, SessionDescriptionType::PrAnswer); + assert_eq!(content.description.session_type, "answer"); assert_eq!(content.description.sdp, "not a real sdp"); }