Introduce webrtc::SdpType, the chosen enum for offer/pranswer/answer
This change introduces a new method |GetType()| in SessionDescriptionInterface which returns an enum for the SDP type rather than a string. Additionally, new overloads were added for CreateSessionDescription to take SdpType instead of a type string. Bug: webrtc:8613 Change-Id: I52b342f12155daf8d623646b0c21b7562f69d101 Reviewed-on: https://webrtc-review.googlesource.com/29380 Reviewed-by: Peter Thatcher <pthatcher@webrtc.org> Reviewed-by: Zhi Huang <zhihuang@webrtc.org> Commit-Queue: Steve Anton <steveanton@webrtc.org> Cr-Commit-Position: refs/heads/master@{#21100}
This commit is contained in:
parent
3fa0b98522
commit
88f2cb9479
47
api/jsep.h
47
api/jsep.h
@ -22,9 +22,11 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "api/optional.h"
|
||||
#include "rtc_base/refcount.h"
|
||||
|
||||
namespace cricket {
|
||||
@ -55,7 +57,7 @@ class IceCandidateInterface {
|
||||
// m= section in SDP, which identifies the m= section.
|
||||
virtual std::string sdp_mid() const = 0;
|
||||
// This indicates the index (starting at zero) of m= section this candidate
|
||||
// is assocated with. Needed when an endpoint doesn't support MIDs.
|
||||
// is associated with. Needed when an endpoint doesn't support MIDs.
|
||||
virtual int sdp_mline_index() const = 0;
|
||||
// Only for use internally.
|
||||
virtual const cricket::Candidate& candidate() const = 0;
|
||||
@ -86,6 +88,26 @@ class IceCandidateCollection {
|
||||
virtual const IceCandidateInterface* at(size_t index) const = 0;
|
||||
};
|
||||
|
||||
// Enum that describes the type of the SessionDescriptionInterface.
|
||||
// Corresponds to RTCSdpType in the WebRTC specification.
|
||||
// https://w3c.github.io/webrtc-pc/#dom-rtcsdptype
|
||||
enum class SdpType {
|
||||
kOffer, // Description must be treated as an SDP offer.
|
||||
kPrAnswer, // Description must be treated as an SDP answer, but not a final
|
||||
// answer.
|
||||
kAnswer // Description must be treated as an SDP final answer, and the offer-
|
||||
// answer exchange must be considered complete after receiving this.
|
||||
};
|
||||
|
||||
// Returns the string form of the given SDP type. String forms are defined in
|
||||
// SessionDescriptionInterface.
|
||||
const char* SdpTypeToString(SdpType type);
|
||||
|
||||
// Returns the SdpType from its string form. The string form can be one of the
|
||||
// constants defined in SessionDescriptionInterface. Passing in any other string
|
||||
// results in nullopt.
|
||||
rtc::Optional<SdpType> SdpTypeFromString(const std::string& type_str);
|
||||
|
||||
// Class representation of an SDP session description.
|
||||
//
|
||||
// An instance of this interface is supposed to be owned by one class at a time
|
||||
@ -94,7 +116,7 @@ class IceCandidateCollection {
|
||||
// An instance can be created by CreateSessionDescription.
|
||||
class SessionDescriptionInterface {
|
||||
public:
|
||||
// Supported types:
|
||||
// String representations of the supported SDP types.
|
||||
static const char kOffer[];
|
||||
static const char kPrAnswer[];
|
||||
static const char kAnswer[];
|
||||
@ -110,7 +132,14 @@ class SessionDescriptionInterface {
|
||||
virtual std::string session_id() const = 0;
|
||||
virtual std::string session_version() const = 0;
|
||||
|
||||
// Returns the type of this session description as an SdpType. Descriptions of
|
||||
// the various types are found in the SdpType documentation.
|
||||
// TODO(steveanton): Remove default implementation once Chromium has been
|
||||
// updated.
|
||||
virtual SdpType GetType() const;
|
||||
|
||||
// kOffer/kPrAnswer/kAnswer
|
||||
// TODO(steveanton): Remove this in favor of |GetType| that returns SdpType.
|
||||
virtual std::string type() const = 0;
|
||||
|
||||
// Adds the specified candidate to the description.
|
||||
@ -143,10 +172,24 @@ class SessionDescriptionInterface {
|
||||
// Creates a SessionDescriptionInterface based on the SDP string and the type.
|
||||
// Returns null if the sdp string can't be parsed or the type is unsupported.
|
||||
// |error| may be null.
|
||||
// TODO(steveanton): This function is deprecated. Please use the functions below
|
||||
// which take an SdpType enum instead. Remove this once it is no longer used.
|
||||
SessionDescriptionInterface* CreateSessionDescription(const std::string& type,
|
||||
const std::string& sdp,
|
||||
SdpParseError* error);
|
||||
|
||||
// Creates a SessionDescriptionInterface based on the SDP string and the type.
|
||||
// Returns null if the SDP string cannot be parsed.
|
||||
// If using the signature with |error_out|, details of the parsing error may be
|
||||
// written to |error_out| if it is not null.
|
||||
std::unique_ptr<SessionDescriptionInterface> CreateSessionDescription(
|
||||
SdpType type,
|
||||
const std::string& sdp);
|
||||
std::unique_ptr<SessionDescriptionInterface> CreateSessionDescription(
|
||||
SdpType type,
|
||||
const std::string& sdp,
|
||||
SdpParseError* error_out);
|
||||
|
||||
// CreateOffer and CreateAnswer callback interface.
|
||||
class CreateSessionDescriptionObserver : public rtc::RefCountInterface {
|
||||
public:
|
||||
|
||||
@ -32,6 +32,8 @@ namespace webrtc {
|
||||
// Implementation of SessionDescriptionInterface.
|
||||
class JsepSessionDescription : public SessionDescriptionInterface {
|
||||
public:
|
||||
explicit JsepSessionDescription(SdpType type);
|
||||
// TODO(steveanton): Remove this once callers have switched to SdpType.
|
||||
explicit JsepSessionDescription(const std::string& type);
|
||||
virtual ~JsepSessionDescription();
|
||||
|
||||
@ -54,11 +56,9 @@ class JsepSessionDescription : public SessionDescriptionInterface {
|
||||
virtual std::string session_version() const {
|
||||
return session_version_;
|
||||
}
|
||||
virtual std::string type() const {
|
||||
return type_;
|
||||
}
|
||||
virtual SdpType GetType() const { return type_; }
|
||||
virtual std::string type() const { return SdpTypeToString(type_); }
|
||||
// Allows changing the type. Used for testing.
|
||||
void set_type(const std::string& type) { type_ = type; }
|
||||
virtual bool AddCandidate(const IceCandidateInterface* candidate);
|
||||
virtual size_t RemoveCandidates(
|
||||
const std::vector<cricket::Candidate>& candidates);
|
||||
@ -74,7 +74,7 @@ class JsepSessionDescription : public SessionDescriptionInterface {
|
||||
std::unique_ptr<cricket::SessionDescription> description_;
|
||||
std::string session_id_;
|
||||
std::string session_version_;
|
||||
std::string type_;
|
||||
SdpType type_;
|
||||
std::vector<JsepCandidateCollection> candidate_collection_;
|
||||
|
||||
bool GetMediasectionIndex(const IceCandidateInterface* candidate,
|
||||
|
||||
@ -12,46 +12,31 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "p2p/base/port.h"
|
||||
#include "pc/mediasession.h"
|
||||
#include "pc/webrtcsdp.h"
|
||||
#include "p2p/base/port.h"
|
||||
#include "rtc_base/arraysize.h"
|
||||
#include "rtc_base/ptr_util.h"
|
||||
#include "rtc_base/stringencode.h"
|
||||
|
||||
using cricket::SessionDescription;
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
static const char* kSupportedTypes[] = {
|
||||
JsepSessionDescription::kOffer,
|
||||
JsepSessionDescription::kPrAnswer,
|
||||
JsepSessionDescription::kAnswer
|
||||
};
|
||||
|
||||
static bool IsTypeSupported(const std::string& type) {
|
||||
bool type_supported = false;
|
||||
for (size_t i = 0; i < arraysize(kSupportedTypes); ++i) {
|
||||
if (kSupportedTypes[i] == type) {
|
||||
type_supported = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return type_supported;
|
||||
}
|
||||
namespace {
|
||||
|
||||
// RFC 5245
|
||||
// It is RECOMMENDED that default candidates be chosen based on the
|
||||
// likelihood of those candidates to work with the peer that is being
|
||||
// contacted. It is RECOMMENDED that relayed > reflexive > host.
|
||||
static const int kPreferenceUnknown = 0;
|
||||
static const int kPreferenceHost = 1;
|
||||
static const int kPreferenceReflexive = 2;
|
||||
static const int kPreferenceRelayed = 3;
|
||||
constexpr int kPreferenceUnknown = 0;
|
||||
constexpr int kPreferenceHost = 1;
|
||||
constexpr int kPreferenceReflexive = 2;
|
||||
constexpr int kPreferenceRelayed = 3;
|
||||
|
||||
static const char kDummyAddress[] = "0.0.0.0";
|
||||
static const int kDummyPort = 9;
|
||||
constexpr char kDummyAddress[] = "0.0.0.0";
|
||||
constexpr int kDummyPort = 9;
|
||||
|
||||
static int GetCandidatePreferenceFromType(const std::string& type) {
|
||||
int GetCandidatePreferenceFromType(const std::string& type) {
|
||||
int preference = kPreferenceUnknown;
|
||||
if (type == cricket::LOCAL_PORT_TYPE) {
|
||||
preference = kPreferenceHost;
|
||||
@ -67,7 +52,7 @@ static int GetCandidatePreferenceFromType(const std::string& type) {
|
||||
|
||||
// Update the connection address for the MediaContentDescription based on the
|
||||
// candidates.
|
||||
static void UpdateConnectionAddress(
|
||||
void UpdateConnectionAddress(
|
||||
const JsepCandidateCollection& candidate_collection,
|
||||
cricket::ContentDescription* content_description) {
|
||||
int port = kDummyPort;
|
||||
@ -107,6 +92,8 @@ static void UpdateConnectionAddress(
|
||||
->set_connection_address(connection_addr);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
const char SessionDescriptionInterface::kOffer[] = "offer";
|
||||
const char SessionDescriptionInterface::kPrAnswer[] = "pranswer";
|
||||
const char SessionDescriptionInterface::kAnswer[] = "answer";
|
||||
@ -114,23 +101,85 @@ const char SessionDescriptionInterface::kAnswer[] = "answer";
|
||||
const int JsepSessionDescription::kDefaultVideoCodecId = 100;
|
||||
const char JsepSessionDescription::kDefaultVideoCodecName[] = "VP8";
|
||||
|
||||
const char* SdpTypeToString(SdpType type) {
|
||||
switch (type) {
|
||||
case SdpType::kOffer:
|
||||
return SessionDescriptionInterface::kOffer;
|
||||
case SdpType::kPrAnswer:
|
||||
return SessionDescriptionInterface::kPrAnswer;
|
||||
case SdpType::kAnswer:
|
||||
return SessionDescriptionInterface::kAnswer;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
rtc::Optional<SdpType> SdpTypeFromString(const std::string& type_str) {
|
||||
if (type_str == SessionDescriptionInterface::kOffer) {
|
||||
return SdpType::kOffer;
|
||||
} else if (type_str == SessionDescriptionInterface::kPrAnswer) {
|
||||
return SdpType::kPrAnswer;
|
||||
} else if (type_str == SessionDescriptionInterface::kAnswer) {
|
||||
return SdpType::kAnswer;
|
||||
} else {
|
||||
return rtc::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(steveanton): Remove this default implementation once Chromium has been
|
||||
// updated.
|
||||
SdpType SessionDescriptionInterface::GetType() const {
|
||||
rtc::Optional<SdpType> maybe_type = SdpTypeFromString(type());
|
||||
if (maybe_type) {
|
||||
return *maybe_type;
|
||||
} else {
|
||||
RTC_LOG(LS_WARNING) << "Default implementation of "
|
||||
"SessionDescriptionInterface::GetType does not "
|
||||
"recognize the result from type(), returning "
|
||||
"kOffer.";
|
||||
return SdpType::kOffer;
|
||||
}
|
||||
}
|
||||
|
||||
SessionDescriptionInterface* CreateSessionDescription(const std::string& type,
|
||||
const std::string& sdp,
|
||||
SdpParseError* error) {
|
||||
if (!IsTypeSupported(type)) {
|
||||
return NULL;
|
||||
rtc::Optional<SdpType> maybe_type = SdpTypeFromString(type);
|
||||
if (!maybe_type) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JsepSessionDescription* jsep_desc = new JsepSessionDescription(type);
|
||||
if (!SdpDeserialize(sdp, jsep_desc, error)) {
|
||||
delete jsep_desc;
|
||||
return NULL;
|
||||
}
|
||||
return jsep_desc;
|
||||
return CreateSessionDescription(*maybe_type, sdp, error).release();
|
||||
}
|
||||
|
||||
JsepSessionDescription::JsepSessionDescription(const std::string& type)
|
||||
: type_(type) {
|
||||
std::unique_ptr<SessionDescriptionInterface> CreateSessionDescription(
|
||||
SdpType type,
|
||||
const std::string& sdp) {
|
||||
return CreateSessionDescription(type, sdp, nullptr);
|
||||
}
|
||||
|
||||
std::unique_ptr<SessionDescriptionInterface> CreateSessionDescription(
|
||||
SdpType type,
|
||||
const std::string& sdp,
|
||||
SdpParseError* error_out) {
|
||||
auto jsep_desc = rtc::MakeUnique<JsepSessionDescription>(type);
|
||||
if (!SdpDeserialize(sdp, jsep_desc.get(), error_out)) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::move(jsep_desc);
|
||||
}
|
||||
|
||||
JsepSessionDescription::JsepSessionDescription(SdpType type) : type_(type) {}
|
||||
|
||||
JsepSessionDescription::JsepSessionDescription(const std::string& type) {
|
||||
rtc::Optional<SdpType> maybe_type = SdpTypeFromString(type);
|
||||
if (maybe_type) {
|
||||
type_ = *maybe_type;
|
||||
} else {
|
||||
RTC_LOG(LS_WARNING)
|
||||
<< "JsepSessionDescription constructed with invalid type string: "
|
||||
<< type << ". Assuming it is an offer.";
|
||||
type_ = SdpType::kOffer;
|
||||
}
|
||||
}
|
||||
|
||||
JsepSessionDescription::~JsepSessionDescription() {}
|
||||
|
||||
@ -22,10 +22,12 @@
|
||||
#include "rtc_base/gunit.h"
|
||||
#include "rtc_base/stringencode.h"
|
||||
|
||||
using ::testing::Values;
|
||||
using webrtc::IceCandidateCollection;
|
||||
using webrtc::IceCandidateInterface;
|
||||
using webrtc::JsepIceCandidate;
|
||||
using webrtc::JsepSessionDescription;
|
||||
using webrtc::SdpType;
|
||||
using webrtc::SessionDescriptionInterface;
|
||||
|
||||
static const char kCandidateUfrag[] = "ufrag";
|
||||
@ -405,3 +407,20 @@ TEST_F(JsepSessionDescriptionTest, RemoveCandidateAndSetConnectionAddress) {
|
||||
ASSERT_TRUE(jsep_desc_->RemoveCandidates(candidates));
|
||||
EXPECT_EQ("0.0.0.0:9", media_desc->connection_address().ToString());
|
||||
}
|
||||
|
||||
class EnumerateAllSdpTypesTest : public ::testing::Test,
|
||||
public ::testing::WithParamInterface<SdpType> {
|
||||
};
|
||||
|
||||
TEST_P(EnumerateAllSdpTypesTest, TestIdentity) {
|
||||
SdpType type = GetParam();
|
||||
|
||||
const char* str = webrtc::SdpTypeToString(type);
|
||||
EXPECT_EQ(type, webrtc::SdpTypeFromString(str));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(JsepSessionDescriptionTest,
|
||||
EnumerateAllSdpTypesTest,
|
||||
Values(SdpType::kOffer,
|
||||
SdpType::kPrAnswer,
|
||||
SdpType::kAnswer));
|
||||
|
||||
@ -513,19 +513,6 @@ TEST_F(PeerConnectionCryptoUnitTest,
|
||||
// CreateOffer/CreateAnswer calls are made while waiting for the certificate,
|
||||
// they all finish after the certificate is generated.
|
||||
|
||||
// Whether the test will call CreateOffer or CreateAnswer.
|
||||
enum class SdpType { kOffer, kAnswer };
|
||||
std::ostream& operator<<(std::ostream& out, SdpType value) {
|
||||
switch (value) {
|
||||
case SdpType::kOffer:
|
||||
return out << "offer";
|
||||
case SdpType::kAnswer:
|
||||
return out << "answer";
|
||||
default:
|
||||
return out << "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
// Whether the certificate will be generated before calling CreateOffer or
|
||||
// while CreateOffer is executing.
|
||||
enum class CertGenTime { kBefore, kDuring };
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user