Update talk to 51314459
R=mallinath@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/2100004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@4608 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/app/webrtc/jsepsessiondescription_unittest.cc b/talk/app/webrtc/jsepsessiondescription_unittest.cc
index 83f67cb..e2b59fb 100644
--- a/talk/app/webrtc/jsepsessiondescription_unittest.cc
+++ b/talk/app/webrtc/jsepsessiondescription_unittest.cc
@@ -79,16 +79,18 @@
cricket::NS_GINGLE_P2P,
std::vector<std::string>(),
kCandidateUfragVoice, kCandidatePwdVoice,
- cricket::ICEMODE_FULL, NULL,
- cricket::Candidates()))));
+ cricket::ICEMODE_FULL,
+ cricket::CONNECTIONROLE_NONE,
+ NULL, cricket::Candidates()))));
EXPECT_TRUE(desc->AddTransportInfo(
cricket::TransportInfo(cricket::CN_VIDEO,
cricket::TransportDescription(
cricket::NS_GINGLE_P2P,
std::vector<std::string>(),
kCandidateUfragVideo, kCandidatePwdVideo,
- cricket::ICEMODE_FULL, NULL,
- cricket::Candidates()))));
+ cricket::ICEMODE_FULL,
+ cricket::CONNECTIONROLE_NONE,
+ NULL, cricket::Candidates()))));
return desc;
}
diff --git a/talk/app/webrtc/webrtcsdp.cc b/talk/app/webrtc/webrtcsdp.cc
index 9910a51..a3bfa71 100644
--- a/talk/app/webrtc/webrtcsdp.cc
+++ b/talk/app/webrtc/webrtcsdp.cc
@@ -141,6 +141,7 @@
static const char kAttributeCandidatePassword[] = "password";
static const char kAttributeCandidateGeneration[] = "generation";
static const char kAttributeFingerprint[] = "fingerprint";
+static const char kAttributeSetup[] = "setup";
static const char kAttributeFmtp[] = "fmtp";
static const char kAttributeRtpmap[] = "rtpmap";
static const char kAttributeRtcp[] = "rtcp";
@@ -318,6 +319,9 @@
static bool ParseFingerprintAttribute(const std::string& line,
talk_base::SSLFingerprint** fingerprint,
SdpParseError* error);
+static bool ParseDtlsSetup(const std::string& line,
+ cricket::ConnectionRole* role,
+ SdpParseError* error);
// Helper functions
@@ -902,7 +906,8 @@
SdpParseError* error) {
std::string session_id;
std::string session_version;
- TransportDescription session_td(NS_JINGLE_ICE_UDP, Candidates());
+ TransportDescription session_td(NS_JINGLE_ICE_UDP,
+ std::string(), std::string());
RtpHeaderExtensions session_extmaps;
cricket::SessionDescription* desc = new cricket::SessionDescription();
std::vector<JsepIceCandidate*> candidates;
@@ -1226,8 +1231,23 @@
os << kSdpDelimiterColon
<< fp->algorithm << kSdpDelimiterSpace
<< fp->GetRfc4572Fingerprint();
-
AddLine(os.str(), message);
+
+ // Inserting setup attribute.
+ if (transport_info->description.connection_role !=
+ cricket::CONNECTIONROLE_NONE) {
+ // Making sure we are not using "passive" mode.
+ cricket::ConnectionRole role =
+ transport_info->description.connection_role;
+ ASSERT(role == cricket::CONNECTIONROLE_ACTIVE ||
+ role == cricket::CONNECTIONROLE_ACTPASS);
+ InitAttrLine(kAttributeSetup, &os);
+ std::string dtls_role_str = role == cricket::CONNECTIONROLE_ACTPASS ?
+ cricket::CONNECTIONROLE_ACTPASS_STR :
+ cricket::CONNECTIONROLE_ACTIVE_STR;
+ os << kSdpDelimiterColon << dtls_role_str;
+ AddLine(os.str(), message);
+ }
}
}
@@ -1796,6 +1816,10 @@
return false;
}
session_td->identity_fingerprint.reset(fingerprint);
+ } else if (HasAttribute(line, kAttributeSetup)) {
+ if (!ParseDtlsSetup(line, &(session_td->connection_role), error)) {
+ return false;
+ }
} else if (HasAttribute(line, kAttributeMsidSemantics)) {
std::string semantics;
if (!GetValue(line, kAttributeMsidSemantics, &semantics, error)) {
@@ -1876,6 +1900,24 @@
return true;
}
+static bool ParseDtlsSetup(const std::string& line,
+ cricket::ConnectionRole* role,
+ SdpParseError* error) {
+ // setup-attr = "a=setup:" role
+ // role = "active" / "passive" / "actpass" / "holdconn"
+ std::vector<std::string> fields;
+ talk_base::split(line.substr(kLinePrefixLength), kSdpDelimiterColon, &fields);
+ const size_t expected_fields = 2;
+ if (fields.size() != expected_fields) {
+ return ParseFailedExpectFieldNum(line, expected_fields, error);
+ }
+ std::string role_str = fields[1];
+ if (!cricket::StringToConnectionRole(role_str, role)) {
+ return ParseFailed(line, "Invalid attribute value.", error);
+ }
+ return true;
+}
+
// RFC 3551
// PT encoding media type clock rate channels
// name (Hz)
@@ -2039,6 +2081,7 @@
session_td.ice_ufrag,
session_td.ice_pwd,
session_td.ice_mode,
+ session_td.connection_role,
session_td.identity_fingerprint.get(),
Candidates());
@@ -2378,6 +2421,10 @@
return false;
}
transport->identity_fingerprint.reset(fingerprint);
+ } else if (HasAttribute(line, kAttributeSetup)) {
+ if (!ParseDtlsSetup(line, &(transport->connection_role), error)) {
+ return false;
+ }
} else if (is_rtp) {
//
// RTP specific attrubtes
diff --git a/talk/app/webrtc/webrtcsdp_unittest.cc b/talk/app/webrtc/webrtcsdp_unittest.cc
index 9e4c660..5fa8b0c 100644
--- a/talk/app/webrtc/webrtcsdp_unittest.cc
+++ b/talk/app/webrtc/webrtcsdp_unittest.cc
@@ -485,19 +485,13 @@
EXPECT_TRUE(desc_.AddTransportInfo(
TransportInfo(kAudioContentName,
TransportDescription(NS_JINGLE_ICE_UDP,
- std::vector<std::string>(),
kCandidateUfragVoice,
- kCandidatePwdVoice,
- cricket::ICEMODE_FULL,
- NULL, Candidates()))));
+ kCandidatePwdVoice))));
EXPECT_TRUE(desc_.AddTransportInfo(
TransportInfo(kVideoContentName,
TransportDescription(NS_JINGLE_ICE_UDP,
- std::vector<std::string>(),
kCandidateUfragVideo,
- kCandidatePwdVideo,
- cricket::ICEMODE_FULL,
- NULL, Candidates()))));
+ kCandidatePwdVideo))));
// v4 host
int port = 1234;
@@ -860,9 +854,7 @@
}
TransportInfo transport_info(
content_name, TransportDescription(NS_JINGLE_ICE_UDP,
- std::vector<std::string>(),
- ufrag, pwd, cricket::ICEMODE_FULL,
- NULL, Candidates()));
+ ufrag, pwd));
SessionDescription* desc =
const_cast<SessionDescription*>(jdesc->description());
desc->RemoveTransportInfoByName(content_name);
@@ -903,16 +895,18 @@
std::vector<std::string>(),
kCandidateUfragVoice,
kCandidatePwdVoice,
- cricket::ICEMODE_FULL, &fingerprint,
- Candidates()))));
+ cricket::ICEMODE_FULL,
+ cricket::CONNECTIONROLE_NONE,
+ &fingerprint, Candidates()))));
EXPECT_TRUE(desc_.AddTransportInfo(
TransportInfo(kVideoContentName,
TransportDescription(NS_JINGLE_ICE_UDP,
std::vector<std::string>(),
kCandidateUfragVideo,
kCandidatePwdVideo,
- cricket::ICEMODE_FULL, &fingerprint,
- Candidates()))));
+ cricket::ICEMODE_FULL,
+ cricket::CONNECTIONROLE_NONE,
+ &fingerprint, Candidates()))));
}
void AddExtmap() {
@@ -984,11 +978,8 @@
EXPECT_TRUE(desc_.AddTransportInfo(
TransportInfo(kDataContentName,
TransportDescription(NS_JINGLE_ICE_UDP,
- std::vector<std::string>(),
kCandidateUfragData,
- kCandidatePwdData,
- cricket::ICEMODE_FULL,
- NULL, Candidates()))));
+ kCandidatePwdData))));
}
void AddRtpDataChannel() {
@@ -1011,11 +1002,8 @@
EXPECT_TRUE(desc_.AddTransportInfo(
TransportInfo(kDataContentName,
TransportDescription(NS_JINGLE_ICE_UDP,
- std::vector<std::string>(),
kCandidateUfragData,
- kCandidatePwdData,
- cricket::ICEMODE_FULL,
- NULL, Candidates()))));
+ kCandidatePwdData))));
}
bool TestDeserializeDirection(cricket::MediaContentDirection direction) {
@@ -1966,3 +1954,60 @@
EXPECT_TRUE(SdpDeserialize(sdp_with_data, &jdesc_output));
EXPECT_EQ(sdp_with_data, webrtc::SdpSerialize(jdesc_output));
}
+
+TEST_F(WebRtcSdpTest, SerializeDtlsSetupAttribute) {
+ AddFingerprint();
+ TransportInfo audio_transport_info =
+ *(desc_.GetTransportInfoByName(kAudioContentName));
+ EXPECT_EQ(cricket::CONNECTIONROLE_NONE,
+ audio_transport_info.description.connection_role);
+ audio_transport_info.description.connection_role =
+ cricket::CONNECTIONROLE_ACTIVE;
+
+ TransportInfo video_transport_info =
+ *(desc_.GetTransportInfoByName(kVideoContentName));
+ EXPECT_EQ(cricket::CONNECTIONROLE_NONE,
+ video_transport_info.description.connection_role);
+ video_transport_info.description.connection_role =
+ cricket::CONNECTIONROLE_ACTIVE;
+
+ desc_.RemoveTransportInfoByName(kAudioContentName);
+ desc_.RemoveTransportInfoByName(kVideoContentName);
+
+ desc_.AddTransportInfo(audio_transport_info);
+ desc_.AddTransportInfo(video_transport_info);
+
+ ASSERT_TRUE(jdesc_.Initialize(desc_.Copy(),
+ jdesc_.session_id(),
+ jdesc_.session_version()));
+ std::string message = webrtc::SdpSerialize(jdesc_);
+ std::string sdp_with_dtlssetup = kSdpFullString;
+
+ // Fingerprint attribute is necessary to add DTLS setup attribute.
+ InjectAfter(kAttributeIcePwdVoice,
+ kFingerprint, &sdp_with_dtlssetup);
+ InjectAfter(kAttributeIcePwdVideo,
+ kFingerprint, &sdp_with_dtlssetup);
+ // Now adding |setup| attribute.
+ InjectAfter(kFingerprint,
+ "a=setup:active\r\n", &sdp_with_dtlssetup);
+ EXPECT_EQ(sdp_with_dtlssetup, message);
+}
+
+TEST_F(WebRtcSdpTest, DeserializeDtlsSetupAttribute) {
+ JsepSessionDescription jdesc_with_dtlssetup(kDummyString);
+ std::string sdp_with_dtlssetup = kSdpFullString;
+ InjectAfter(kSessionTime,
+ "a=setup:actpass\r\n",
+ &sdp_with_dtlssetup);
+ EXPECT_TRUE(SdpDeserialize(sdp_with_dtlssetup, &jdesc_with_dtlssetup));
+ cricket::SessionDescription* desc = jdesc_with_dtlssetup.description();
+ const cricket::TransportInfo* atinfo =
+ desc->GetTransportInfoByName("audio_content_name");
+ EXPECT_EQ(cricket::CONNECTIONROLE_ACTPASS,
+ atinfo->description.connection_role);
+ const cricket::TransportInfo* vtinfo =
+ desc->GetTransportInfoByName("video_content_name");
+ EXPECT_EQ(cricket::CONNECTIONROLE_ACTPASS,
+ vtinfo->description.connection_role);
+}
diff --git a/talk/app/webrtc/webrtcsession.cc b/talk/app/webrtc/webrtcsession.cc
index b056757..7016e2a 100644
--- a/talk/app/webrtc/webrtcsession.cc
+++ b/talk/app/webrtc/webrtcsession.cc
@@ -505,6 +505,26 @@
return webrtc_session_desc_factory_->secure();
}
+bool WebRtcSession::GetSslRole(talk_base::SSLRole* role) {
+ if (local_description() == NULL || remote_description() == NULL) {
+ LOG(LS_INFO) << "Local and Remote descriptions must be applied to get "
+ << "SSL Role of the session.";
+ return false;
+ }
+
+ // TODO(mallinath) - Return role of each transport, as role may differ from
+ // one another.
+ // In current implementaion we just return the role of first transport in the
+ // transport map.
+ for (cricket::TransportMap::const_iterator iter = transport_proxies().begin();
+ iter != transport_proxies().end(); ++iter) {
+ if (iter->second->impl()) {
+ return iter->second->impl()->GetSslRole(role);
+ }
+ }
+ return false;
+}
+
void WebRtcSession::CreateOffer(CreateSessionDescriptionObserver* observer,
const MediaConstraintsInterface* constraints) {
webrtc_session_desc_factory_->CreateOffer(observer, constraints);
@@ -517,42 +537,22 @@
bool WebRtcSession::SetLocalDescription(SessionDescriptionInterface* desc,
std::string* err_desc) {
- cricket::SecureMediaPolicy secure_policy =
- webrtc_session_desc_factory_->secure();
// Takes the ownership of |desc| regardless of the result.
talk_base::scoped_ptr<SessionDescriptionInterface> desc_temp(desc);
- if (error() != cricket::BaseSession::ERROR_NONE) {
- return BadLocalSdp(SessionErrorMsg(error()), err_desc);
- }
-
- if (!desc || !desc->description()) {
- return BadLocalSdp(kInvalidSdp, err_desc);
- }
-
- if (!VerifyBundleSettings(desc->description())) {
- return BadLocalSdp(kBundleWithoutRtcpMux, err_desc);
- }
-
- Action action = GetAction(desc->type());
- if (!ExpectSetLocalDescription(action)) {
- std::string type = desc->type();
- return BadLocalSdp(BadStateErrMsg(type, state()), err_desc);
- }
- if (secure_policy == cricket::SEC_REQUIRED &&
- !VerifyCrypto(desc->description())) {
- return BadLocalSdp(kSdpWithoutCrypto, err_desc);
- }
- if (action == kAnswer && !VerifyMediaDescriptions(
- desc->description(), remote_description()->description())) {
- return BadLocalSdp(kMlineMismatch, err_desc);
+ // Validate SDP.
+ if (!ValidateSessionDescription(desc, cricket::CS_LOCAL, err_desc)) {
+ return false;
}
// Update the initiator flag if this session is the initiator.
+ Action action = GetAction(desc->type());
if (state() == STATE_INIT && action == kOffer) {
set_initiator(true);
}
+ cricket::SecureMediaPolicy secure_policy =
+ webrtc_session_desc_factory_->secure();
// Update the MediaContentDescription crypto settings as per the policy set.
UpdateSessionDescriptionSecurePolicy(secure_policy, desc->description());
@@ -589,40 +589,16 @@
bool WebRtcSession::SetRemoteDescription(SessionDescriptionInterface* desc,
std::string* err_desc) {
- cricket::SecureMediaPolicy secure_policy =
- webrtc_session_desc_factory_->secure();
// Takes the ownership of |desc| regardless of the result.
talk_base::scoped_ptr<SessionDescriptionInterface> desc_temp(desc);
- if (error() != cricket::BaseSession::ERROR_NONE) {
- return BadRemoteSdp(SessionErrorMsg(error()), err_desc);
- }
-
- if (!desc || !desc->description()) {
- return BadRemoteSdp(kInvalidSdp, err_desc);
- }
-
- if (!VerifyBundleSettings(desc->description())) {
- return BadRemoteSdp(kBundleWithoutRtcpMux, err_desc);
- }
-
- Action action = GetAction(desc->type());
- if (!ExpectSetRemoteDescription(action)) {
- std::string type = desc->type();
- return BadRemoteSdp(BadStateErrMsg(type, state()), err_desc);
- }
-
- if (action == kAnswer && !VerifyMediaDescriptions(
- desc->description(), local_description()->description())) {
- return BadRemoteSdp(kMlineMismatch, err_desc);
- }
-
- if (secure_policy == cricket::SEC_REQUIRED &&
- !VerifyCrypto(desc->description())) {
- return BadRemoteSdp(kSdpWithoutCrypto, err_desc);
+ // Validate SDP.
+ if (!ValidateSessionDescription(desc, cricket::CS_REMOTE, err_desc)) {
+ return false;
}
// Transport and Media channels will be created only when offer is set.
+ Action action = GetAction(desc->type());
if (action == kOffer && !CreateChannels(desc->description())) {
// TODO(mallinath) - Handle CreateChannel failure, as new local description
// is applied. Restore back to old description.
@@ -1094,36 +1070,6 @@
ProcessNewLocalCandidate(proxy->content_name(), candidates);
}
-bool WebRtcSession::ExpectSetLocalDescription(Action action) {
- return ((action == kOffer && state() == STATE_INIT) ||
- // update local offer
- (action == kOffer && state() == STATE_SENTINITIATE) ||
- // update the current ongoing session.
- (action == kOffer && state() == STATE_RECEIVEDACCEPT) ||
- (action == kOffer && state() == STATE_SENTACCEPT) ||
- (action == kOffer && state() == STATE_INPROGRESS) ||
- // accept remote offer
- (action == kAnswer && state() == STATE_RECEIVEDINITIATE) ||
- (action == kAnswer && state() == STATE_SENTPRACCEPT) ||
- (action == kPrAnswer && state() == STATE_RECEIVEDINITIATE) ||
- (action == kPrAnswer && state() == STATE_SENTPRACCEPT));
-}
-
-bool WebRtcSession::ExpectSetRemoteDescription(Action action) {
- return ((action == kOffer && state() == STATE_INIT) ||
- // update remote offer
- (action == kOffer && state() == STATE_RECEIVEDINITIATE) ||
- // update the current ongoing session
- (action == kOffer && state() == STATE_RECEIVEDACCEPT) ||
- (action == kOffer && state() == STATE_SENTACCEPT) ||
- (action == kOffer && state() == STATE_INPROGRESS) ||
- // accept local offer
- (action == kAnswer && state() == STATE_SENTINITIATE) ||
- (action == kAnswer && state() == STATE_RECEIVEDPRACCEPT) ||
- (action == kPrAnswer && state() == STATE_SENTINITIATE) ||
- (action == kPrAnswer && state() == STATE_RECEIVEDPRACCEPT));
-}
-
void WebRtcSession::OnCandidatesAllocationDone() {
ASSERT(signaling_thread()->IsCurrent());
if (ice_observer_) {
@@ -1378,7 +1324,7 @@
}
// Returns false if bundle is enabled and rtcp_mux is disabled.
-bool WebRtcSession::VerifyBundleSettings(const SessionDescription* desc) {
+bool WebRtcSession::ValidateBundleSettings(const SessionDescription* desc) {
bool bundle_enabled = desc->HasGroup(cricket::GROUP_TYPE_BUNDLE);
if (!bundle_enabled)
return true;
@@ -1409,4 +1355,79 @@
return description->rtcp_mux();
}
+bool WebRtcSession::ValidateSessionDescription(
+ const SessionDescriptionInterface* sdesc,
+ cricket::ContentSource source, std::string* error_desc) {
+
+ if (error() != cricket::BaseSession::ERROR_NONE) {
+ return BadSdp(source, SessionErrorMsg(error()), error_desc);
+ }
+
+ if (!sdesc || !sdesc->description()) {
+ return BadSdp(source, kInvalidSdp, error_desc);
+ }
+
+ std::string type = sdesc->type();
+ Action action = GetAction(sdesc->type());
+ if (source == cricket::CS_LOCAL) {
+ if (!ExpectSetLocalDescription(action))
+ return BadSdp(source, BadStateErrMsg(type, state()), error_desc);
+ } else {
+ if (!ExpectSetRemoteDescription(action))
+ return BadSdp(source, BadStateErrMsg(type, state()), error_desc);
+ }
+
+ // Verify crypto settings.
+ if (webrtc_session_desc_factory_->secure() == cricket::SEC_REQUIRED &&
+ !VerifyCrypto(sdesc->description())) {
+ return BadSdp(source, kSdpWithoutCrypto, error_desc);
+ }
+
+ if (!ValidateBundleSettings(sdesc->description())) {
+ return BadSdp(source, kBundleWithoutRtcpMux, error_desc);
+ }
+
+ // Verify m-lines in Answer when compared against Offer.
+ if (action == kAnswer) {
+ const cricket::SessionDescription* offer_desc =
+ (source == cricket::CS_LOCAL) ? remote_description()->description() :
+ local_description()->description();
+ if (!VerifyMediaDescriptions(sdesc->description(), offer_desc)) {
+ return BadSdp(source, kMlineMismatch, error_desc);
+ }
+ }
+
+ return true;
+}
+
+bool WebRtcSession::ExpectSetLocalDescription(Action action) {
+ return ((action == kOffer && state() == STATE_INIT) ||
+ // update local offer
+ (action == kOffer && state() == STATE_SENTINITIATE) ||
+ // update the current ongoing session.
+ (action == kOffer && state() == STATE_RECEIVEDACCEPT) ||
+ (action == kOffer && state() == STATE_SENTACCEPT) ||
+ (action == kOffer && state() == STATE_INPROGRESS) ||
+ // accept remote offer
+ (action == kAnswer && state() == STATE_RECEIVEDINITIATE) ||
+ (action == kAnswer && state() == STATE_SENTPRACCEPT) ||
+ (action == kPrAnswer && state() == STATE_RECEIVEDINITIATE) ||
+ (action == kPrAnswer && state() == STATE_SENTPRACCEPT));
+}
+
+bool WebRtcSession::ExpectSetRemoteDescription(Action action) {
+ return ((action == kOffer && state() == STATE_INIT) ||
+ // update remote offer
+ (action == kOffer && state() == STATE_RECEIVEDINITIATE) ||
+ // update the current ongoing session
+ (action == kOffer && state() == STATE_RECEIVEDACCEPT) ||
+ (action == kOffer && state() == STATE_SENTACCEPT) ||
+ (action == kOffer && state() == STATE_INPROGRESS) ||
+ // accept local offer
+ (action == kAnswer && state() == STATE_SENTINITIATE) ||
+ (action == kAnswer && state() == STATE_RECEIVEDPRACCEPT) ||
+ (action == kPrAnswer && state() == STATE_SENTINITIATE) ||
+ (action == kPrAnswer && state() == STATE_RECEIVEDPRACCEPT));
+}
+
} // namespace webrtc
diff --git a/talk/app/webrtc/webrtcsession.h b/talk/app/webrtc/webrtcsession.h
index 202ca66..0cb049f 100644
--- a/talk/app/webrtc/webrtcsession.h
+++ b/talk/app/webrtc/webrtcsession.h
@@ -130,6 +130,9 @@
void set_secure_policy(cricket::SecureMediaPolicy secure_policy);
cricket::SecureMediaPolicy secure_policy() const;
+ // Get current ssl role from transport.
+ bool GetSslRole(talk_base::SSLRole* role);
+
// Generic error message callback from WebRtcSession.
// TODO - It may be necessary to supply error code as well.
sigslot::signal0<> SignalError;
@@ -152,9 +155,6 @@
return remote_desc_.get();
}
- void set_secure(cricket::SecureMediaPolicy secure_policy);
- cricket::SecureMediaPolicy secure();
-
// Get the id used as a media stream track's "id" field from ssrc.
virtual bool GetTrackIdBySsrc(uint32 ssrc, std::string* id);
@@ -223,10 +223,6 @@
const cricket::Candidates& candidates);
virtual void OnCandidatesAllocationDone();
- // Check if a call to SetLocalDescription is acceptable with |action|.
- bool ExpectSetLocalDescription(Action action);
- // Check if a call to SetRemoteDescription is acceptable with |action|.
- bool ExpectSetRemoteDescription(Action action);
// Creates local session description with audio and video contents.
bool CreateDefaultLocalDescription();
// Enables media channels to allow sending of media.
@@ -275,8 +271,20 @@
std::string BadStateErrMsg(const std::string& type, State state);
void SetIceConnectionState(PeerConnectionInterface::IceConnectionState state);
- bool VerifyBundleSettings(const cricket::SessionDescription* desc);
+ bool ValidateBundleSettings(const cricket::SessionDescription* desc);
bool HasRtcpMuxEnabled(const cricket::ContentInfo* content);
+ // Below methods are helper methods which verifies SDP.
+ bool ValidateSessionDescription(const SessionDescriptionInterface* sdesc,
+ cricket::ContentSource source,
+ std::string* error_desc);
+
+ // Check if a call to SetLocalDescription is acceptable with |action|.
+ bool ExpectSetLocalDescription(Action action);
+ // Check if a call to SetRemoteDescription is acceptable with |action|.
+ bool ExpectSetRemoteDescription(Action action);
+ // Verifies a=setup attribute as per RFC 5763.
+ bool ValidateDtlsSetupAttribute(const cricket::SessionDescription* desc,
+ Action action);
talk_base::scoped_ptr<cricket::VoiceChannel> voice_channel_;
talk_base::scoped_ptr<cricket::VideoChannel> video_channel_;
diff --git a/talk/app/webrtc/webrtcsessiondescriptionfactory.cc b/talk/app/webrtc/webrtcsessiondescriptionfactory.cc
index 2021085..13f54a7 100644
--- a/talk/app/webrtc/webrtcsessiondescriptionfactory.cc
+++ b/talk/app/webrtc/webrtcsessiondescriptionfactory.cc
@@ -343,6 +343,13 @@
// an answer should also contain new ice ufrag and password if an offer has
// been received with new ufrag and password.
request.options.transport_options.ice_restart = session_->IceRestartPending();
+ // We should pass current ssl role to the transport description factory, if
+ // there is already an existing ongoing session.
+ talk_base::SSLRole ssl_role;
+ if (session_->GetSslRole(&ssl_role)) {
+ request.options.transport_options.prefer_passive_role =
+ (talk_base::SSL_SERVER == ssl_role);
+ }
cricket::SessionDescription* desc(session_desc_factory_.CreateAnswer(
static_cast<cricket::BaseSession*>(session_)->remote_description(),