Bug 1436080: Implemented RsdparsaSdp::AddMediaSection, r=dminor
authorJohannes Willbold <j.willbold@mozilla.com>
Thu, 14 Jun 2018 11:20:50 -0700
changeset 477549 301f7d8a5ba2f6cf0bba236647eb929dd00c6408
parent 477548 c346e724399d16c5e5a3a66626942da2dd2f0e1f
child 477550 dbafc571a6a8d2426e179698f9038a1a3379fa8c
push id9385
push userdluca@mozilla.com
push dateFri, 22 Jun 2018 15:47:18 +0000
treeherdermozilla-beta@82a9a1027e2b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdminor
bugs1436080
milestone62.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1436080: Implemented RsdparsaSdp::AddMediaSection, r=dminor Implemented RsdparsaSdp::AddMediaSection Added sdp_add_media_section to Rust/C++ glue code Added SdpSession::add_media in Rust Added C++ unit test CheckAddMediaSection MozReview-Commit-ID: 8cUviY3atsb
media/webrtc/signaling/gtest/sdp_unittests.cpp
media/webrtc/signaling/src/sdp/RsdparsaSdp.cpp
media/webrtc/signaling/src/sdp/RsdparsaSdpInc.h
media/webrtc/signaling/src/sdp/rsdparsa/src/lib.rs
media/webrtc/signaling/src/sdp/rsdparsa_capi/src/lib.rs
--- a/media/webrtc/signaling/gtest/sdp_unittests.cpp
+++ b/media/webrtc/signaling/gtest/sdp_unittests.cpp
@@ -3978,16 +3978,90 @@ TEST_P(NewSdpTest, CheckClearCodecs) {
 
      mSdp->GetMediaSection(0).ClearCodecs();
 
      ASSERT_EQ(0U,mSdp->GetMediaSection(0).GetFormats().size());
      ASSERT_FALSE(mSdp->GetMediaSection(0).GetAttributeList().
                   HasAttribute(SdpAttribute::kRtpmapAttribute));
 }
 
+TEST_P(NewSdpTest, CheckAddMediaSection) {
+  ParseSdp(kBasicAudioVideoOffer);
+
+  ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
+  ASSERT_EQ(3U, mSdp->GetMediaSectionCount())
+    << "Wrong number of media sections";
+
+  mSdp->AddMediaSection(SdpMediaSection::kVideo,
+                        SdpDirectionAttribute::Direction::kSendrecv,
+                        58000, SdpMediaSection::kUdpDtlsSctp,sdp::kIPv4,
+                        "127.0.0.1");
+
+  ASSERT_EQ(4U, mSdp->GetMediaSectionCount())
+    << "Wrong number of media sections after adding media section";
+
+  const SdpMediaSection& newMediaSection = mSdp->GetMediaSection(3);
+
+  ASSERT_EQ(SdpMediaSection::kVideo, newMediaSection.GetMediaType());
+  ASSERT_EQ(SdpDirectionAttribute::Direction::kSendrecv,
+            newMediaSection.GetDirectionAttribute().mValue);
+  ASSERT_EQ(58000U, newMediaSection.GetPort());
+  ASSERT_EQ(SdpMediaSection::kUdpDtlsSctp, newMediaSection.GetProtocol());
+  ASSERT_EQ(sdp::kIPv4, newMediaSection.GetConnection().GetAddrType());
+  ASSERT_EQ("127.0.0.1", newMediaSection.GetConnection().GetAddress());
+
+
+  mSdp->AddMediaSection(SdpMediaSection::kAudio,
+                        SdpDirectionAttribute::Direction::kSendonly,
+                        14006, SdpMediaSection::kTcpTlsRtpSavpf, sdp::kIPv6,
+                        "2607:f8b0:4004:801::2013");
+
+  ASSERT_EQ(5U, mSdp->GetMediaSectionCount())
+    << "Wrong number of media sections after adding media section";
+
+  const SdpMediaSection& nextNewMediaSection = mSdp->GetMediaSection(4);
+
+  ASSERT_EQ(SdpMediaSection::kAudio, nextNewMediaSection.GetMediaType());
+  ASSERT_EQ(SdpDirectionAttribute::Direction::kSendonly,
+            nextNewMediaSection.GetDirectionAttribute().mValue);
+  ASSERT_EQ(14006U, nextNewMediaSection.GetPort());
+  ASSERT_EQ(SdpMediaSection::kTcpTlsRtpSavpf,
+            nextNewMediaSection.GetProtocol());
+  ASSERT_EQ(sdp::kIPv6, nextNewMediaSection.GetConnection().GetAddrType());
+  ASSERT_EQ("2607:f8b0:4004:801::2013",
+            nextNewMediaSection.GetConnection().GetAddress());
+
+  if(!IsParsingWithSipccParser()) {
+    // All following AddMediaSection calls are expected to fail
+    // SdpMediaSection::kDccpRtpAvp is expected to cause a failure
+    mSdp->AddMediaSection(SdpMediaSection::kAudio,
+                          SdpDirectionAttribute::Direction::kSendonly,
+                          14006, SdpMediaSection::kDccpRtpAvp, sdp::kIPv6,
+                          "2607:f8b0:4004:801::2013");
+    ASSERT_EQ(5U, mSdp->GetMediaSectionCount())
+      << "Wrong number of media sections after adding media section";
+
+    // sdp::kAddrTypeNone is expected to cause a failure
+    mSdp->AddMediaSection(SdpMediaSection::kAudio,
+                          SdpDirectionAttribute::Direction::kSendonly,
+                          14006, SdpMediaSection::kDtlsSctp, sdp::kAddrTypeNone,
+                          "2607:f8b0:4004:801::2013");
+    ASSERT_EQ(5U, mSdp->GetMediaSectionCount())
+      << "Wrong number of media sections after adding media section";
+
+    // "NOT:AN.IP.ADDRESS" is expected to cause a failure
+    mSdp->AddMediaSection(SdpMediaSection::kAudio,
+                          SdpDirectionAttribute::Direction::kSendonly,
+                          14006, SdpMediaSection::kTcpTlsRtpSavpf, sdp::kIPv6,
+                          "NOT:AN.IP.ADDRESS");
+    ASSERT_EQ(5U, mSdp->GetMediaSectionCount())
+      << "Wrong number of media sections after adding media section";
+  }
+}
+
 TEST(NewSdpTestNoFixture, CheckAttributeTypeSerialize) {
   for (auto a = static_cast<size_t>(SdpAttribute::kFirstAttribute);
        a <= static_cast<size_t>(SdpAttribute::kLastAttribute);
        ++a) {
 
     SdpAttribute::AttributeType type =
       static_cast<SdpAttribute::AttributeType>(a);
 
--- a/media/webrtc/signaling/src/sdp/RsdparsaSdp.cpp
+++ b/media/webrtc/signaling/src/sdp/RsdparsaSdp.cpp
@@ -3,16 +3,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "signaling/src/sdp/RsdparsaSdp.h"
 
 #include <cstdlib>
 #include "mozilla/UniquePtr.h"
 #include "mozilla/Assertions.h"
 #include "nsError.h"
+#include <iostream>
 
 
 #include "signaling/src/sdp/SdpErrorHolder.h"
 #include "signaling/src/sdp/RsdparsaSdpInc.h"
 #include "signaling/src/sdp/RsdparsaSdpMediaSection.h"
 
 #ifdef CRLF
 #undef CRLF
@@ -80,18 +81,38 @@ RsdparsaSdp::GetMediaSection(size_t leve
 
 SdpMediaSection&
 RsdparsaSdp::AddMediaSection(SdpMediaSection::MediaType mediaType,
                              SdpDirectionAttribute::Direction dir,
                              uint16_t port,
                              SdpMediaSection::Protocol protocol,
                              sdp::AddrType addrType, const std::string& addr)
 {
-  //TODO: See Bug 1436080
-  MOZ_CRASH("Method not implemented");
+  StringView rustAddr{addr.c_str(),addr.size()};
+  auto nr = sdp_add_media_section(mSession.get(),mediaType,dir,port,
+                                                 protocol,addrType,rustAddr);
+
+  if (NS_SUCCEEDED(nr)) {
+    std::cout << "Hello World" << std::endl;
+    size_t level = mMediaSections.values.size();
+    RsdparsaSessionHandle newSessHandle(sdp_new_reference(mSession.get()));
+
+    auto rustMediaSection = sdp_get_media_section(mSession.get(), level);
+    auto mediaSection = new RsdparsaSdpMediaSection(level,
+                                                    std::move(newSessHandle),
+                                                    rustMediaSection,
+                                                    mAttributeList.get());
+    mMediaSections.values.push_back(mediaSection);
+
+    return *mediaSection;
+  } else {
+    // Return the last media section if the construction of this one fails
+    return GetMediaSection(mMediaSections.values.size()-1);
+  }
+
 }
 
 void
 RsdparsaSdp::Serialize(std::ostream& os) const
 {
   os << "v=0" << CRLF << mOrigin << "s=-" << CRLF;
 
   // We don't support creating i=, u=, e=, p=
--- a/media/webrtc/signaling/src/sdp/RsdparsaSdpInc.h
+++ b/media/webrtc/signaling/src/sdp/RsdparsaSdpInc.h
@@ -236,16 +236,20 @@ char* sdp_serialize_bandwidth(const Band
 bool sdp_session_has_connection(const RustSdpSession* aSess);
 nsresult sdp_get_session_connection(const RustSdpSession* aSess,
                                     RustSdpConnection* ret);
 RustAttributeList* get_sdp_session_attributes(const RustSdpSession* aSess);
 
 size_t sdp_media_section_count(const RustSdpSession* aSess);
 RustMediaSection* sdp_get_media_section(const RustSdpSession* aSess,
                                         size_t aLevel);
+nsresult sdp_add_media_section(RustSdpSession* aSess, uint32_t aMediaType,
+                               uint32_t aDirection, uint32_t aPort,
+                               uint32_t aProtocol, uint32_t aAddrType,
+                               StringView aAddr);
 RustSdpMediaValue sdp_rust_get_media_type(const RustMediaSection* aMediaSec);
 RustSdpProtocolValue
 sdp_get_media_protocol(const RustMediaSection* aMediaSec);
 RustSdpFormatType sdp_get_format_type(const RustMediaSection* aMediaSec);
 StringVec* sdp_get_format_string_vec(const RustMediaSection* aMediaSec);
 U32Vec* sdp_get_format_u32_vec(const RustMediaSection* aMediaSec);
 void sdp_set_media_port(const RustMediaSection* aMediaSec, uint32_t aPort);
 uint32_t sdp_get_media_port(const RustMediaSection* aMediaSec);
--- a/media/webrtc/signaling/src/sdp/rsdparsa/src/lib.rs
+++ b/media/webrtc/signaling/src/sdp/rsdparsa/src/lib.rs
@@ -2,27 +2,29 @@
 
 #[cfg(feature="serialize")]
 #[macro_use]
 extern crate serde_derive;
 #[cfg(feature="serialize")]
 extern crate serde;
 
 use std::net::IpAddr;
+use std::str::FromStr;
 use std::fmt;
 
 pub mod attribute_type;
 pub mod error;
 pub mod media_type;
 pub mod network;
 pub mod unsupported_types;
 
 use attribute_type::{SdpAttribute, SdpAttributeType, parse_attribute};
 use error::{SdpParserInternalError, SdpParserError};
-use media_type::{SdpMedia, SdpMediaLine, parse_media, parse_media_vector};
+use media_type::{SdpMedia, SdpMediaLine, parse_media, parse_media_vector, SdpProtocolValue,
+                 SdpMediaValue, SdpFormatList};
 use network::{parse_addrtype, parse_nettype, parse_unicast_addr};
 use unsupported_types::{parse_email, parse_information, parse_key, parse_phone, parse_repeat,
                         parse_uri, parse_zone};
 
 #[derive(Clone)]
 #[cfg_attr(feature="serialize", derive(Serialize))]
 pub enum SdpBandwidth {
     As(u32),
@@ -177,16 +179,40 @@ impl SdpSession {
 
     pub fn get_attribute(&self, t: SdpAttributeType) -> Option<&SdpAttribute> {
        self.attribute.iter().filter(|a| SdpAttributeType::from(*a) == t).next()
     }
 
     pub fn has_media(&self) -> bool {
         !self.media.is_empty()
     }
+
+    pub fn add_media(&mut self, media_type: SdpMediaValue, direction: SdpAttribute, port: u32,
+                     protocol: SdpProtocolValue, addr: String)
+                     -> Result<(),SdpParserInternalError> {
+       let mut media = SdpMedia::new(SdpMediaLine {
+           media: media_type,
+           port,
+           port_count: 1,
+           proto: protocol,
+           formats: SdpFormatList::Integers(Vec::new()),
+       });
+
+       media.add_attribute(&direction)?;
+
+       media.set_connection(&SdpConnection {
+           addr: IpAddr::from_str(addr.as_str())?,
+           ttl: None,
+           amount: None,
+       })?;
+
+       self.media.push(media);
+
+       Ok(())
+    }
 }
 
 fn parse_session(value: &str) -> Result<SdpType, SdpParserInternalError> {
     println!("session: {}", value);
     Ok(SdpType::Session(String::from(value)))
 }
 
 #[test]
--- a/media/webrtc/signaling/src/sdp/rsdparsa_capi/src/lib.rs
+++ b/media/webrtc/signaling/src/sdp/rsdparsa_capi/src/lib.rs
@@ -10,17 +10,18 @@ use std::error::Error;
 
 use libc::size_t;
 
 use std::rc::Rc;
 
 use nserror::{nsresult, NS_OK, NS_ERROR_INVALID_ARG};
 use rsdparsa::{SdpTiming, SdpBandwidth, SdpSession};
 use rsdparsa::error::SdpParserError;
-use rsdparsa::attribute_type::SdpAttribute;
+use rsdparsa::media_type::{SdpMediaValue, SdpProtocolValue};
+use rsdparsa::attribute_type::{SdpAttribute};
 
 pub mod types;
 pub mod network;
 pub mod attribute;
 pub mod media_section;
 
 pub use types::{StringView, NULL_STRING};
 use network::{RustSdpOrigin, origin_view_helper, RustSdpConnection,
@@ -135,16 +136,76 @@ pub unsafe extern "C" fn sdp_get_session
         Some(ref c) => {
             *connection = RustSdpConnection::from(c);
             NS_OK
         },
         None => NS_ERROR_INVALID_ARG
     }
 }
 
+#[no_mangle]
+pub unsafe extern "C" fn sdp_add_media_section(session: *mut SdpSession,
+                                               media_type: u32, direction: u32,
+                                               port: u16, protocol: u32,
+                                               addr_type: u32, addr: StringView) -> nsresult {
+
+    let addr_str:String = match addr.into() {
+       Ok(x) => x,
+       Err(boxed_error) => {
+           println!("Error while pasing string, description: {:?}", (*boxed_error).description());
+           return NS_ERROR_INVALID_ARG;
+       }
+    };
+
+    let media_type = match media_type {
+        0 => SdpMediaValue::Audio,       // MediaType::kAudio
+        1 => SdpMediaValue::Video,       // MediaType::kVideo
+        3 => SdpMediaValue::Application, // MediaType::kApplication
+        _ => {
+         return NS_ERROR_INVALID_ARG;
+     }
+    };
+    let protocol = match protocol {
+        20 => SdpProtocolValue::RtpSavpf,        // Protocol::kRtpSavpf
+        24 => SdpProtocolValue::UdpTlsRtpSavpf,  // Protocol::kUdpTlsRtpSavpf
+        25 => SdpProtocolValue::TcpTlsRtpSavpf,  // Protocol::kTcpTlsRtpSavpf
+        37 => SdpProtocolValue::DtlsSctp,        // Protocol::kDtlsSctp
+        38 => SdpProtocolValue::UdpDtlsSctp,     // Protocol::kUdpDtlsSctp
+        39 => SdpProtocolValue::TcpDtlsSctp,     // Protocol::kTcpDtlsSctp
+        _ => {
+            println!("INVALID PROTOCOL");
+          return NS_ERROR_INVALID_ARG;
+      }
+    };
+    let direction = match direction {
+        1 => SdpAttribute::Sendonly,
+        2 => SdpAttribute::Recvonly,
+        3 => SdpAttribute::Sendrecv,
+        _ => {
+          return NS_ERROR_INVALID_ARG;
+      }
+    };
+
+    // Check that the provided address type is valid. The rust parser will find out
+    // on his own which address type was provided
+    match addr_type {
+      // enum AddrType { kAddrTypeNone, kIPv4, kIPv6 };
+      // kAddrTypeNone is explicitly not covered as it is an 'invalid' flag
+      1...2 => (),
+      _ => {
+          return NS_ERROR_INVALID_ARG;
+      }
+    }
+
+    match (*session).add_media(media_type, direction, port as u32, protocol, addr_str) {
+        Ok(_) => NS_OK,
+        Err(_) => NS_ERROR_INVALID_ARG
+    }
+}
+
 #[repr(C)]
 #[derive(Clone)]
 pub struct RustSdpTiming {
     pub start: u64,
     pub stop: u64,
 }
 
 impl<'a> From<&'a SdpTiming> for RustSdpTiming {