Bug 1438290: Part 1: Implemented RsdparsaSdpMediaSection::AddDataChannel, r=dminor
Implemented RsdparsaSdpMediaSection::AddDataChannel
Added C++/Rust glue code for the "sctp port" attribute
Added C++/Rust glue code for the "max message size" attribute
MozReview-Commit-ID: 5MQC7I1MiU0
--- a/media/webrtc/signaling/src/sdp/RsdparsaSdpAttributeList.cpp
+++ b/media/webrtc/signaling/src/sdp/RsdparsaSdpAttributeList.cpp
@@ -437,16 +437,19 @@ RsdparsaSdpAttributeList::LoadAttribute(
LoadPtime(attributeList);
return;
case SdpAttribute::kIceLiteAttribute:
case SdpAttribute::kRtcpMuxAttribute:
case SdpAttribute::kBundleOnlyAttribute:
case SdpAttribute::kEndOfCandidatesAttribute:
LoadFlags(attributeList);
return;
+ case SdpAttribute::kMaxMessageSizeAttribute:
+ LoadMaxMessageSize(attributeList);
+ return ;
case SdpAttribute::kMidAttribute:
LoadMid(attributeList);
return;
case SdpAttribute::kMsidAttribute:
LoadMsid(attributeList);
return;
case SdpAttribute::kMsidSemanticAttribute:
LoadMsidSemantics(attributeList);
@@ -470,30 +473,31 @@ RsdparsaSdpAttributeList::LoadAttribute(
LoadDirection(attributeList);
return;
case SdpAttribute::kRemoteCandidatesAttribute:
LoadRemoteCandidates(attributeList);
return;
case SdpAttribute::kRidAttribute:
LoadRids(attributeList);
return;
+ case SdpAttribute::kSctpPortAttribute:
+ LoadSctpPort(attributeList);
+ return ;
case SdpAttribute::kExtmapAttribute:
LoadExtmap(attributeList);
return;
case SdpAttribute::kSimulcastAttribute:
LoadSimulcast(attributeList);
return;
case SdpAttribute::kDtlsMessageAttribute:
case SdpAttribute::kLabelAttribute:
case SdpAttribute::kMaxptimeAttribute:
case SdpAttribute::kSsrcGroupAttribute:
- case SdpAttribute::kMaxMessageSizeAttribute:
case SdpAttribute::kRtcpRsizeAttribute:
- case SdpAttribute::kSctpPortAttribute:
case SdpAttribute::kCandidateAttribute:
case SdpAttribute::kConnectionAttribute:
case SdpAttribute::kIceMismatchAttribute:
// TODO: Not implemented, or not applicable.
// Sort this out in Bug 1437165.
return;
}
}
@@ -805,16 +809,26 @@ RsdparsaSdpAttributeList::LoadFlags(Rust
SetAttribute(new SdpFlagAttribute(SdpAttribute::kBundleOnlyAttribute));
}
if (flags.endOfCandidates) {
SetAttribute(new SdpFlagAttribute(SdpAttribute::kEndOfCandidatesAttribute));
}
}
void
+RsdparsaSdpAttributeList::LoadMaxMessageSize(RustAttributeList* attributeList)
+{
+ int64_t max_msg_size = sdp_get_max_msg_sizse(attributeList);
+ if (max_msg_size >= 0) {
+ SetAttribute(new SdpNumberAttribute(SdpAttribute::kMaxMessageSizeAttribute,
+ static_cast<uint32_t>(max_msg_size)));
+ }
+}
+
+void
RsdparsaSdpAttributeList::LoadMid(RustAttributeList* attributeList)
{
StringView rustMid;
if (NS_SUCCEEDED(sdp_get_mid(attributeList, &rustMid))) {
std::string mid = convertStringView(rustMid);
SetAttribute(new SdpStringAttribute(SdpAttribute::kMidAttribute, mid));
}
}
@@ -1121,16 +1135,26 @@ RsdparsaSdpAttributeList::LoadRids(RustA
ridList->PushEntry(id, direction, formats, parameters, depends);
}
SetAttribute(ridList.release());
}
void
+RsdparsaSdpAttributeList::LoadSctpPort(RustAttributeList* attributeList)
+{
+ int64_t port = sdp_get_sctp_port(attributeList);
+ if (port >= 0) {
+ SetAttribute(new SdpNumberAttribute(SdpAttribute::kSctpPortAttribute,
+ static_cast<uint32_t>(port)));
+ }
+}
+
+void
RsdparsaSdpAttributeList::LoadExtmap(RustAttributeList* attributeList)
{
size_t numExtmap = sdp_get_extmap_count(attributeList);
if (numExtmap == 0) {
return;
}
auto rustExtmaps = MakeUnique<RustSdpAttributeExtmap[]>(numExtmap);
sdp_get_extmaps(attributeList, numExtmap,
--- a/media/webrtc/signaling/src/sdp/RsdparsaSdpAttributeList.h
+++ b/media/webrtc/signaling/src/sdp/RsdparsaSdpAttributeList.h
@@ -125,22 +125,24 @@ private:
void LoadIceOptions(RustAttributeList* attributeList);
void LoadFingerprint(RustAttributeList* attributeList);
void LoadSetup(RustAttributeList* attributeList);
void LoadSsrc(RustAttributeList* attributeList);
void LoadRtpmap(RustAttributeList* attributeList);
void LoadFmtp(RustAttributeList* attributeList);
void LoadPtime(RustAttributeList* attributeList);
void LoadFlags(RustAttributeList* attributeList);
+ void LoadMaxMessageSize(RustAttributeList* attributeList);
void LoadMid(RustAttributeList* attributeList);
void LoadMsid(RustAttributeList* attributeList);
void LoadMsidSemantics(RustAttributeList* attributeList);
void LoadGroup(RustAttributeList* attributeList);
void LoadRtcp(RustAttributeList* attributeList);
void LoadRtcpFb(RustAttributeList* attributeList);
+ void LoadSctpPort(RustAttributeList* attributeList);
void LoadSimulcast(RustAttributeList* attributeList);
void LoadImageattr(RustAttributeList* attributeList);
void LoadSctpmaps(RustAttributeList* attributeList);
void LoadDirection(RustAttributeList* attributeList);
void LoadRemoteCandidates(RustAttributeList* attributeList);
void LoadRids(RustAttributeList* attributeList);
void LoadExtmap(RustAttributeList* attributeList);
--- a/media/webrtc/signaling/src/sdp/RsdparsaSdpInc.h
+++ b/media/webrtc/signaling/src/sdp/RsdparsaSdpInc.h
@@ -300,16 +300,19 @@ nsresult sdp_get_media_connection(const
RustAttributeList*
sdp_get_media_attribute_list(const RustMediaSection* aMediaSec);
nsresult sdp_media_add_codec(const RustMediaSection* aMediaSec,
uint8_t aPT, StringView aCodecName,
uint32_t aClockrate, uint16_t channels);
void sdp_media_clear_codecs(const RustMediaSection* aMediaSec);
+nsresult sdp_media_add_datachannel(const RustMediaSection* aMediaSec,
+ StringView aName, uint16_t aPort,
+ uint16_t streams, uint32_t aMessageSize);
nsresult sdp_get_iceufrag(const RustAttributeList* aList, StringView* ret);
nsresult sdp_get_icepwd(const RustAttributeList* aList, StringView* ret);
nsresult sdp_get_identity(const RustAttributeList* aList, StringView* ret);
nsresult sdp_get_iceoptions(const RustAttributeList* aList, StringVec** ret);
size_t sdp_get_fingerprint_count(const RustAttributeList* aList);
void sdp_get_fingerprints(const RustAttributeList* aList, size_t listSize,
@@ -325,16 +328,18 @@ size_t sdp_get_rtpmap_count(const RustAt
void sdp_get_rtpmaps(const RustAttributeList* aList, size_t listSize,
RustSdpAttributeRtpmap* ret);
size_t sdp_get_fmtp_count(const RustAttributeList* aList);
size_t sdp_get_fmtp(const RustAttributeList* aList, size_t listSize,
RustSdpAttributeFmtp* ret);
int64_t sdp_get_ptime(const RustAttributeList* aList);
+int64_t sdp_get_max_msg_sizse(const RustAttributeList* aList);
+int64_t sdp_get_sctp_port(const RustAttributeList* aList);
RustSdpAttributeFlags sdp_get_attribute_flags(const RustAttributeList* aList);
nsresult sdp_get_mid(const RustAttributeList* aList, StringView* ret);
size_t sdp_get_msid_count(const RustAttributeList* aList);
void sdp_get_msids(const RustAttributeList* aList, size_t listSize,
RustSdpAttributeMsid* ret);
--- a/media/webrtc/signaling/src/sdp/RsdparsaSdpMediaSection.cpp
+++ b/media/webrtc/signaling/src/sdp/RsdparsaSdpMediaSection.cpp
@@ -185,17 +185,31 @@ RsdparsaSdpMediaSection::ClearCodecs()
mAttributeList->RemoveAttribute(SdpAttribute::kSctpmapAttribute);
mAttributeList->RemoveAttribute(SdpAttribute::kRtcpFbAttribute);
}
void
RsdparsaSdpMediaSection::AddDataChannel(const std::string& name, uint16_t port,
uint16_t streams, uint32_t message_size)
{
- //TODO: See 1438290
+ StringView rustName{name.c_str(), name.size()};
+ auto nr = sdp_media_add_datachannel(mSection, rustName, port,
+ streams, message_size);
+ if (NS_SUCCEEDED(nr)) {
+ // Update the formats
+ mFormats.clear();
+ LoadFormats();
+
+ // Update the attribute list
+ RsdparsaSessionHandle sessHandle(sdp_new_reference(mSession.get()));
+ auto sessAttributes = mAttributeList->mSessionAttributes;
+ mAttributeList.reset(new RsdparsaSdpAttributeList(std::move(sessHandle),
+ mSection,
+ sessAttributes));
+ }
}
void
RsdparsaSdpMediaSection::Serialize(std::ostream& os) const
{
os << "m=" << mMediaType << " " << GetPort();
if (GetPortCount()) {
os << "/" << GetPortCount();
--- a/media/webrtc/signaling/src/sdp/rsdparsa/src/media_type.rs
+++ b/media/webrtc/signaling/src/sdp/rsdparsa/src/media_type.rs
@@ -1,11 +1,11 @@
use std::fmt;
use {SdpType, SdpLine, SdpBandwidth, SdpConnection};
-use attribute_type::{SdpAttribute, SdpAttributeType, SdpAttributeRtpmap};
+use attribute_type::{SdpAttribute, SdpAttributeType, SdpAttributeRtpmap, SdpAttributeSctpmap};
use error::{SdpParserError, SdpParserInternalError};
#[derive(Clone)]
#[cfg_attr(feature="serialize", derive(Serialize))]
pub struct SdpMediaLine {
pub media: SdpMediaValue,
pub port: u32,
pub port_count: u32,
@@ -145,16 +145,25 @@ impl SdpMedia {
}
Ok(self.attribute.push(attr.clone()))
}
pub fn get_attribute(&self, t: SdpAttributeType) -> Option<&SdpAttribute> {
self.attribute.iter().filter(|a| SdpAttributeType::from(*a) == t).next()
}
+ pub fn remove_attribute(&mut self, t: SdpAttributeType) {
+ self.attribute.retain(|a| SdpAttributeType::from(a) != t);
+ }
+
+ pub fn set_attribute(&mut self, attr: &SdpAttribute) -> Result<(), SdpParserInternalError> {
+ self.remove_attribute(SdpAttributeType::from(attr));
+ self.add_attribute(attr)
+ }
+
pub fn remove_codecs(&mut self) {
match self.media.formats{
SdpFormatList::Integers(_) => self.media.formats = SdpFormatList::Integers(Vec::new()),
SdpFormatList::Strings(_) => self.media.formats = SdpFormatList::Strings(Vec::new()),
}
self.attribute.retain({|x|
match x {
@@ -192,16 +201,43 @@ impl SdpMedia {
pub fn set_connection(&mut self, c: &SdpConnection) -> Result<(), SdpParserInternalError> {
if self.connection.is_some() {
return Err(SdpParserInternalError::Generic("connection type already exists at this media level"
.to_string(),
));
}
Ok(self.connection = Some(c.clone()))
}
+
+ pub fn add_datachannel(&mut self, name: String, port: u16, streams: u16, msg_size:u32)
+ -> Result<(),SdpParserInternalError> {
+ // Only one allowed, for now. This may change as the specs (and deployments) evolve.
+ match self.media.proto {
+ SdpProtocolValue::UdpDtlsSctp |
+ SdpProtocolValue::TcpDtlsSctp => {
+ // new data channel format according to draft 21
+ self.media.formats = SdpFormatList::Strings(vec![name]);
+ self.set_attribute(&SdpAttribute::SctpPort(port as u64))?;
+ }
+ _ => {
+ // old data channels format according to draft 05
+ self.media.formats = SdpFormatList::Integers(vec![port as u32]);
+ self.set_attribute(&SdpAttribute::Sctpmap(SdpAttributeSctpmap {
+ port,
+ channels: streams as u32,
+ }))?;
+ }
+ }
+
+ if msg_size > 0 {
+ self.set_attribute(&SdpAttribute::MaxMessageSize(msg_size as u64))?;
+ }
+
+ Ok(())
+ }
}
#[cfg(test)]
#[cfg_attr(feature="serialize", derive(Serialize))]
pub fn create_dummy_media_section() -> SdpMedia {
let media_line = SdpMediaLine {
media: SdpMediaValue::Audio,
port: 9,
--- a/media/webrtc/signaling/src/sdp/rsdparsa_capi/src/attribute.rs
+++ b/media/webrtc/signaling/src/sdp/rsdparsa_capi/src/attribute.rs
@@ -434,16 +434,36 @@ pub unsafe extern "C" fn sdp_get_ptime(a
for attribute in (*attributes).iter() {
if let SdpAttribute::Ptime(time) = *attribute {
return time as int64_t;
}
}
-1
}
+#[no_mangle]
+pub unsafe extern "C" fn sdp_get_max_msg_sizse(attributes: *const Vec<SdpAttribute>) -> int64_t {
+ for attribute in (*attributes).iter() {
+ if let SdpAttribute::MaxMessageSize(max_msg_size) = *attribute {
+ return max_msg_size as int64_t;
+ }
+ }
+ -1
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn sdp_get_sctp_port(attributes: *const Vec<SdpAttribute>) -> int64_t {
+ for attribute in (*attributes).iter() {
+ if let SdpAttribute::SctpPort(port) = *attribute {
+ return port as int64_t;
+ }
+ }
+ -1
+}
+
#[repr(C)]
#[derive(Clone, Copy)]
pub struct RustSdpAttributeFlags {
pub ice_lite: bool,
pub rtcp_mux: bool,
pub bundle_only: bool,
pub end_of_candidates: bool
}
--- a/media/webrtc/signaling/src/sdp/rsdparsa_capi/src/media_section.rs
+++ b/media/webrtc/signaling/src/sdp/rsdparsa_capi/src/media_section.rs
@@ -173,8 +173,24 @@ pub unsafe extern "C" fn sdp_media_add_c
channels: Some(channels as u32),
};
match (*sdp_media).add_codec(rtpmap) {
Ok(_) => NS_OK,
Err(_) => NS_ERROR_INVALID_ARG,
}
}
+
+#[no_mangle]
+pub unsafe extern "C" fn sdp_media_add_datachannel(sdp_media: *mut SdpMedia, name: StringView,
+ port: u16, streams: u16, message_size: u32)
+ -> nsresult {
+ let name_str = match name.into() {
+ Ok(x) => x,
+ Err(_) => {
+ return NS_ERROR_INVALID_ARG;
+ }
+ };
+ match (*sdp_media).add_datachannel(name_str, port, streams, message_size){
+ Ok(_) => NS_OK,
+ Err(_) => NS_ERROR_INVALID_ARG
+ }
+}