Update libjingle to 59676287

R=wu@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/7229004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5390 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
sergeyu@chromium.org
2014-01-15 23:15:54 +00:00
parent 7a2ca7c621
commit 4b26e2eee3
47 changed files with 1203 additions and 718 deletions

View File

@@ -238,7 +238,7 @@ TEST_F(VideoSourceTest, MandatoryConstraintCif5Fps) {
ASSERT_TRUE(format != NULL); ASSERT_TRUE(format != NULL);
EXPECT_EQ(352, format->width); EXPECT_EQ(352, format->width);
EXPECT_EQ(288, format->height); EXPECT_EQ(288, format->height);
EXPECT_EQ(5, format->framerate()); EXPECT_EQ(30, format->framerate());
} }
// Test that the capture output is 720P if the camera support it and the // Test that the capture output is 720P if the camera support it and the
@@ -491,7 +491,7 @@ TEST_F(VideoSourceTest, MixedOptionsAndConstraints) {
ASSERT_TRUE(format != NULL); ASSERT_TRUE(format != NULL);
EXPECT_EQ(352, format->width); EXPECT_EQ(352, format->width);
EXPECT_EQ(288, format->height); EXPECT_EQ(288, format->height);
EXPECT_EQ(5, format->framerate()); EXPECT_EQ(30, format->framerate());
bool value = true; bool value = true;
EXPECT_TRUE(source_->options()->video_noise_reduction.Get(&value)); EXPECT_TRUE(source_->options()->video_noise_reduction.Get(&value));
@@ -554,6 +554,6 @@ TEST_F(VideoSourceTest, OptionalSubOneFpsConstraints) {
kMaxWaitMs); kMaxWaitMs);
const cricket::VideoFormat* format = capturer_->GetCaptureFormat(); const cricket::VideoFormat* format = capturer_->GetCaptureFormat();
ASSERT_TRUE(format != NULL); ASSERT_TRUE(format != NULL);
EXPECT_EQ(1, format->framerate()); EXPECT_EQ(30, format->framerate());
} }

View File

@@ -55,29 +55,22 @@ using cricket::TransportInfo;
namespace webrtc { namespace webrtc {
// Error messages // Error messages
const char kSetLocalSdpFailed[] = "SetLocalDescription failed: ";
const char kSetRemoteSdpFailed[] = "SetRemoteDescription failed: ";
const char kCreateChannelFailed[] = "Failed to create channels.";
const char kBundleWithoutRtcpMux[] = "RTCP-MUX must be enabled when BUNDLE " const char kBundleWithoutRtcpMux[] = "RTCP-MUX must be enabled when BUNDLE "
"is enabled."; "is enabled.";
const char kCreateChannelFailed[] = "Failed to create channels.";
const char kInvalidCandidates[] = "Description contains invalid candidates."; const char kInvalidCandidates[] = "Description contains invalid candidates.";
const char kInvalidSdp[] = "Invalid session description."; const char kInvalidSdp[] = "Invalid session description.";
const char kMlineMismatch[] = const char kMlineMismatch[] =
"Offer and answer descriptions m-lines are not matching. " "Offer and answer descriptions m-lines are not matching. Rejecting answer.";
"Rejecting answer."; const char kPushDownTDFailed[] =
"Failed to push down transport description:";
const char kSdpWithoutCrypto[] = "Called with a SDP without crypto enabled."; const char kSdpWithoutCrypto[] = "Called with a SDP without crypto enabled.";
const char kSdpWithoutSdesAndDtlsDisabled[] =
"Called with an SDP without SDES crypto and DTLS disabled locally.";
const char kSdpWithoutIceUfragPwd[] = const char kSdpWithoutIceUfragPwd[] =
"Called with an SDP without ice-ufrag and ice-pwd."; "Called with a SDP without ice-ufrag and ice-pwd.";
const char kSdpWithoutSdesAndDtlsDisabled[] =
"Called with a SDP without SDES crypto and DTLS disabled locally.";
const char kSessionError[] = "Session error code: "; const char kSessionError[] = "Session error code: ";
const char kUpdateStateFailed[] = "Failed to update session state: "; const char kSessionErrorDesc[] = "Session error description: ";
const char kPushDownOfferTDFailed[] =
"Failed to push down offer transport description.";
const char kPushDownPranswerTDFailed[] =
"Failed to push down pranswer transport description.";
const char kPushDownAnswerTDFailed[] =
"Failed to push down answer transport description.";
// Compares |answer| against |offer|. Comparision is done // Compares |answer| against |offer|. Comparision is done
// for number of m-lines in answer against offer. If matches true will be // for number of m-lines in answer against offer. If matches true will be
@@ -245,39 +238,60 @@ static bool GetTrackIdBySsrc(const SessionDescription* session_description,
return false; return false;
} }
static bool BadSdp(const std::string& desc, std::string* err_desc) { static bool BadSdp(const std::string& source,
const std::string& type,
const std::string& reason,
std::string* err_desc) {
std::ostringstream desc;
desc << "Failed to set " << source << " " << type << " sdp: " << reason;
if (err_desc) { if (err_desc) {
*err_desc = desc; *err_desc = desc.str();
} }
LOG(LS_ERROR) << desc; LOG(LS_ERROR) << desc.str();
return false; return false;
} }
static bool BadLocalSdp(const std::string& desc, std::string* err_desc) {
std::string set_local_sdp_failed = kSetLocalSdpFailed;
set_local_sdp_failed.append(desc);
return BadSdp(set_local_sdp_failed, err_desc);
}
static bool BadRemoteSdp(const std::string& desc, std::string* err_desc) {
std::string set_remote_sdp_failed = kSetRemoteSdpFailed;
set_remote_sdp_failed.append(desc);
return BadSdp(set_remote_sdp_failed, err_desc);
}
static bool BadSdp(cricket::ContentSource source, static bool BadSdp(cricket::ContentSource source,
const std::string& desc, std::string* err_desc) { const std::string& type,
const std::string& reason,
std::string* err_desc) {
if (source == cricket::CS_LOCAL) { if (source == cricket::CS_LOCAL) {
return BadLocalSdp(desc, err_desc); return BadSdp("local", type, reason, err_desc);
} else { } else {
return BadRemoteSdp(desc, err_desc); return BadSdp("remote", type, reason, err_desc);
} }
} }
static std::string SessionErrorMsg(cricket::BaseSession::Error error) { static bool BadLocalSdp(const std::string& type,
std::ostringstream desc; const std::string& reason,
desc << kSessionError << error; std::string* err_desc) {
return desc.str(); return BadSdp(cricket::CS_LOCAL, type, reason, err_desc);
}
static bool BadRemoteSdp(const std::string& type,
const std::string& reason,
std::string* err_desc) {
return BadSdp(cricket::CS_REMOTE, type, reason, err_desc);
}
static bool BadOfferSdp(cricket::ContentSource source,
const std::string& reason,
std::string* err_desc) {
return BadSdp(source, SessionDescriptionInterface::kOffer, reason, err_desc);
}
static bool BadPranswerSdp(cricket::ContentSource source,
const std::string& reason,
std::string* err_desc) {
return BadSdp(source, SessionDescriptionInterface::kPrAnswer,
reason, err_desc);
}
static bool BadAnswerSdp(cricket::ContentSource source,
const std::string& reason,
std::string* err_desc) {
return BadSdp(source, SessionDescriptionInterface::kAnswer, reason, err_desc);
} }
#define GET_STRING_OF_STATE(state) \ #define GET_STRING_OF_STATE(state) \
@@ -311,20 +325,20 @@ static std::string GetStateString(cricket::BaseSession::State state) {
return result; return result;
} }
#define GET_STRING_OF_ERROR(err) \ #define GET_STRING_OF_ERROR_CODE(err) \
case cricket::BaseSession::err: \ case cricket::BaseSession::err: \
result = #err; \ result = #err; \
break; break;
static std::string GetErrorString(cricket::BaseSession::Error err) { static std::string GetErrorCodeString(cricket::BaseSession::Error err) {
std::string result; std::string result;
switch (err) { switch (err) {
GET_STRING_OF_ERROR(ERROR_NONE) GET_STRING_OF_ERROR_CODE(ERROR_NONE)
GET_STRING_OF_ERROR(ERROR_TIME) GET_STRING_OF_ERROR_CODE(ERROR_TIME)
GET_STRING_OF_ERROR(ERROR_RESPONSE) GET_STRING_OF_ERROR_CODE(ERROR_RESPONSE)
GET_STRING_OF_ERROR(ERROR_NETWORK) GET_STRING_OF_ERROR_CODE(ERROR_NETWORK)
GET_STRING_OF_ERROR(ERROR_CONTENT) GET_STRING_OF_ERROR_CODE(ERROR_CONTENT)
GET_STRING_OF_ERROR(ERROR_TRANSPORT) GET_STRING_OF_ERROR_CODE(ERROR_TRANSPORT)
default: default:
ASSERT(false); ASSERT(false);
break; break;
@@ -332,12 +346,15 @@ static std::string GetErrorString(cricket::BaseSession::Error err) {
return result; return result;
} }
static bool SetSessionStateFailed(cricket::ContentSource source, static std::string MakeErrorString(const std::string& error,
cricket::BaseSession::Error err, const std::string& desc) {
std::string* err_desc) { std::ostringstream ret;
std::string set_state_err = kUpdateStateFailed; ret << error << " " << desc;
set_state_err.append(GetErrorString(err)); return ret.str();
return BadSdp(source, set_state_err, err_desc); }
static std::string MakeTdErrorString(const std::string& desc) {
return MakeErrorString(kPushDownTDFailed, desc);
} }
// Help class used to remember if a a remote peer has requested ice restart by // Help class used to remember if a a remote peer has requested ice restart by
@@ -604,15 +621,14 @@ bool WebRtcSession::SetLocalDescription(SessionDescriptionInterface* desc,
if (action == kOffer && !CreateChannels(local_desc_->description())) { if (action == kOffer && !CreateChannels(local_desc_->description())) {
// TODO(mallinath) - Handle CreateChannel failure, as new local description // TODO(mallinath) - Handle CreateChannel failure, as new local description
// is applied. Restore back to old description. // is applied. Restore back to old description.
return BadLocalSdp(kCreateChannelFailed, err_desc); return BadLocalSdp(desc->type(), kCreateChannelFailed, err_desc);
} }
// Remove channel and transport proxies, if MediaContentDescription is // Remove channel and transport proxies, if MediaContentDescription is
// rejected. // rejected.
RemoveUnusedChannelsAndTransports(local_desc_->description()); RemoveUnusedChannelsAndTransports(local_desc_->description());
if (!UpdateSessionState(action, cricket::CS_LOCAL, if (!UpdateSessionState(action, cricket::CS_LOCAL, err_desc)) {
local_desc_->description(), err_desc)) {
return false; return false;
} }
// Kick starting the ice candidates allocation. // Kick starting the ice candidates allocation.
@@ -627,7 +643,7 @@ bool WebRtcSession::SetLocalDescription(SessionDescriptionInterface* desc,
mediastream_signaling_->OnDtlsRoleReadyForSctp(role); mediastream_signaling_->OnDtlsRoleReadyForSctp(role);
} }
if (error() != cricket::BaseSession::ERROR_NONE) { if (error() != cricket::BaseSession::ERROR_NONE) {
return BadLocalSdp(SessionErrorMsg(error()), err_desc); return BadLocalSdp(desc->type(), GetSessionErrorMsg(), err_desc);
} }
return true; return true;
} }
@@ -647,7 +663,7 @@ bool WebRtcSession::SetRemoteDescription(SessionDescriptionInterface* desc,
if (action == kOffer && !CreateChannels(desc->description())) { if (action == kOffer && !CreateChannels(desc->description())) {
// TODO(mallinath) - Handle CreateChannel failure, as new local description // TODO(mallinath) - Handle CreateChannel failure, as new local description
// is applied. Restore back to old description. // is applied. Restore back to old description.
return BadRemoteSdp(kCreateChannelFailed, err_desc); return BadRemoteSdp(desc->type(), kCreateChannelFailed, err_desc);
} }
// Remove channel and transport proxies, if MediaContentDescription is // Remove channel and transport proxies, if MediaContentDescription is
@@ -657,15 +673,14 @@ bool WebRtcSession::SetRemoteDescription(SessionDescriptionInterface* desc,
// NOTE: Candidates allocation will be initiated only when SetLocalDescription // NOTE: Candidates allocation will be initiated only when SetLocalDescription
// is called. // is called.
set_remote_description(desc->description()->Copy()); set_remote_description(desc->description()->Copy());
if (!UpdateSessionState(action, cricket::CS_REMOTE, if (!UpdateSessionState(action, cricket::CS_REMOTE, err_desc)) {
desc->description(), err_desc)) {
return false; return false;
} }
// Update remote MediaStreams. // Update remote MediaStreams.
mediastream_signaling_->OnRemoteDescriptionChanged(desc); mediastream_signaling_->OnRemoteDescriptionChanged(desc);
if (local_description() && !UseCandidatesInSessionDescription(desc)) { if (local_description() && !UseCandidatesInSessionDescription(desc)) {
return BadRemoteSdp(kInvalidCandidates, err_desc); return BadRemoteSdp(desc->type(), kInvalidCandidates, err_desc);
} }
// Copy all saved candidates. // Copy all saved candidates.
@@ -685,47 +700,47 @@ bool WebRtcSession::SetRemoteDescription(SessionDescriptionInterface* desc,
} }
if (error() != cricket::BaseSession::ERROR_NONE) { if (error() != cricket::BaseSession::ERROR_NONE) {
return BadRemoteSdp(SessionErrorMsg(error()), err_desc); return BadRemoteSdp(desc->type(), GetSessionErrorMsg(), err_desc);
} }
return true; return true;
} }
bool WebRtcSession::UpdateSessionState( bool WebRtcSession::UpdateSessionState(
Action action, cricket::ContentSource source, Action action, cricket::ContentSource source,
const cricket::SessionDescription* desc,
std::string* err_desc) { std::string* err_desc) {
// If there's already a pending error then no state transition should happen. // If there's already a pending error then no state transition should happen.
// But all call-sites should be verifying this before calling us! // But all call-sites should be verifying this before calling us!
ASSERT(error() == cricket::BaseSession::ERROR_NONE); ASSERT(error() == cricket::BaseSession::ERROR_NONE);
std::string td_err;
if (action == kOffer) { if (action == kOffer) {
if (!PushdownTransportDescription(source, cricket::CA_OFFER)) { if (!PushdownTransportDescription(source, cricket::CA_OFFER, &td_err)) {
return BadSdp(source, kPushDownOfferTDFailed, err_desc); return BadOfferSdp(source, MakeTdErrorString(td_err), err_desc);
} }
SetState(source == cricket::CS_LOCAL ? SetState(source == cricket::CS_LOCAL ?
STATE_SENTINITIATE : STATE_RECEIVEDINITIATE); STATE_SENTINITIATE : STATE_RECEIVEDINITIATE);
if (error() != cricket::BaseSession::ERROR_NONE) { if (error() != cricket::BaseSession::ERROR_NONE) {
return SetSessionStateFailed(source, error(), err_desc); return BadOfferSdp(source, GetSessionErrorMsg(), err_desc);
} }
} else if (action == kPrAnswer) { } else if (action == kPrAnswer) {
if (!PushdownTransportDescription(source, cricket::CA_PRANSWER)) { if (!PushdownTransportDescription(source, cricket::CA_PRANSWER, &td_err)) {
return BadSdp(source, kPushDownPranswerTDFailed, err_desc); return BadPranswerSdp(source, MakeTdErrorString(td_err), err_desc);
} }
EnableChannels(); EnableChannels();
SetState(source == cricket::CS_LOCAL ? SetState(source == cricket::CS_LOCAL ?
STATE_SENTPRACCEPT : STATE_RECEIVEDPRACCEPT); STATE_SENTPRACCEPT : STATE_RECEIVEDPRACCEPT);
if (error() != cricket::BaseSession::ERROR_NONE) { if (error() != cricket::BaseSession::ERROR_NONE) {
return SetSessionStateFailed(source, error(), err_desc); return BadPranswerSdp(source, GetSessionErrorMsg(), err_desc);
} }
} else if (action == kAnswer) { } else if (action == kAnswer) {
if (!PushdownTransportDescription(source, cricket::CA_ANSWER)) { if (!PushdownTransportDescription(source, cricket::CA_ANSWER, &td_err)) {
return BadSdp(source, kPushDownAnswerTDFailed, err_desc); return BadAnswerSdp(source, MakeTdErrorString(td_err), err_desc);
} }
MaybeEnableMuxingSupport(); MaybeEnableMuxingSupport();
EnableChannels(); EnableChannels();
SetState(source == cricket::CS_LOCAL ? SetState(source == cricket::CS_LOCAL ?
STATE_SENTACCEPT : STATE_RECEIVEDACCEPT); STATE_SENTACCEPT : STATE_RECEIVEDACCEPT);
if (error() != cricket::BaseSession::ERROR_NONE) { if (error() != cricket::BaseSession::ERROR_NONE) {
return SetSessionStateFailed(source, error(), err_desc); return BadAnswerSdp(source, GetSessionErrorMsg(), err_desc);
} }
} }
return true; return true;
@@ -801,11 +816,9 @@ bool WebRtcSession::GetRemoteTrackId(uint32 ssrc, std::string* track_id) {
BaseSession::remote_description(), ssrc, track_id); BaseSession::remote_description(), ssrc, track_id);
} }
std::string WebRtcSession::BadStateErrMsg( std::string WebRtcSession::BadStateErrMsg(State state) {
const std::string& type, State state) {
std::ostringstream desc; std::ostringstream desc;
desc << "Called with type in wrong state, " desc << "Called in wrong state: " << GetStateString(state);
<< "type: " << type << " state: " << GetStateString(state);
return desc.str(); return desc.str();
} }
@@ -1447,40 +1460,40 @@ bool WebRtcSession::HasRtcpMuxEnabled(
bool WebRtcSession::ValidateSessionDescription( bool WebRtcSession::ValidateSessionDescription(
const SessionDescriptionInterface* sdesc, const SessionDescriptionInterface* sdesc,
cricket::ContentSource source, std::string* error_desc) { cricket::ContentSource source, std::string* err_desc) {
std::string type;
if (error() != cricket::BaseSession::ERROR_NONE) { if (error() != cricket::BaseSession::ERROR_NONE) {
return BadSdp(source, SessionErrorMsg(error()), error_desc); return BadSdp(source, type, GetSessionErrorMsg(), err_desc);
} }
if (!sdesc || !sdesc->description()) { if (!sdesc || !sdesc->description()) {
return BadSdp(source, kInvalidSdp, error_desc); return BadSdp(source, type, kInvalidSdp, err_desc);
} }
std::string type = sdesc->type(); type = sdesc->type();
Action action = GetAction(sdesc->type()); Action action = GetAction(sdesc->type());
if (source == cricket::CS_LOCAL) { if (source == cricket::CS_LOCAL) {
if (!ExpectSetLocalDescription(action)) if (!ExpectSetLocalDescription(action))
return BadSdp(source, BadStateErrMsg(type, state()), error_desc); return BadLocalSdp(type, BadStateErrMsg(state()), err_desc);
} else { } else {
if (!ExpectSetRemoteDescription(action)) if (!ExpectSetRemoteDescription(action))
return BadSdp(source, BadStateErrMsg(type, state()), error_desc); return BadRemoteSdp(type, BadStateErrMsg(state()), err_desc);
} }
// Verify crypto settings. // Verify crypto settings.
std::string crypto_error; std::string crypto_error;
if (webrtc_session_desc_factory_->Secure() == cricket::SEC_REQUIRED && if (webrtc_session_desc_factory_->Secure() == cricket::SEC_REQUIRED &&
!VerifyCrypto(sdesc->description(), dtls_enabled_, &crypto_error)) { !VerifyCrypto(sdesc->description(), dtls_enabled_, &crypto_error)) {
return BadSdp(source, crypto_error, error_desc); return BadSdp(source, type, crypto_error, err_desc);
} }
// Verify ice-ufrag and ice-pwd. // Verify ice-ufrag and ice-pwd.
if (!VerifyIceUfragPwdPresent(sdesc->description())) { if (!VerifyIceUfragPwdPresent(sdesc->description())) {
return BadSdp(source, kSdpWithoutIceUfragPwd, error_desc); return BadSdp(source, type, kSdpWithoutIceUfragPwd, err_desc);
} }
if (!ValidateBundleSettings(sdesc->description())) { if (!ValidateBundleSettings(sdesc->description())) {
return BadSdp(source, kBundleWithoutRtcpMux, error_desc); return BadSdp(source, type, kBundleWithoutRtcpMux, err_desc);
} }
// Verify m-lines in Answer when compared against Offer. // Verify m-lines in Answer when compared against Offer.
@@ -1489,7 +1502,7 @@ bool WebRtcSession::ValidateSessionDescription(
(source == cricket::CS_LOCAL) ? remote_description()->description() : (source == cricket::CS_LOCAL) ? remote_description()->description() :
local_description()->description(); local_description()->description();
if (!VerifyMediaDescriptions(sdesc->description(), offer_desc)) { if (!VerifyMediaDescriptions(sdesc->description(), offer_desc)) {
return BadSdp(source, kMlineMismatch, error_desc); return BadAnswerSdp(source, kMlineMismatch, err_desc);
} }
} }
@@ -1526,4 +1539,11 @@ bool WebRtcSession::ExpectSetRemoteDescription(Action action) {
(action == kPrAnswer && state() == STATE_RECEIVEDPRACCEPT)); (action == kPrAnswer && state() == STATE_RECEIVEDPRACCEPT));
} }
std::string WebRtcSession::GetSessionErrorMsg() {
std::ostringstream desc;
desc << kSessionError << GetErrorCodeString(error()) << ". ";
desc << kSessionErrorDesc << error_desc() << ".";
return desc.str();
}
} // namespace webrtc } // namespace webrtc

View File

@@ -57,21 +57,17 @@ class IceRestartAnswerLatch;
class MediaStreamSignaling; class MediaStreamSignaling;
class WebRtcSessionDescriptionFactory; class WebRtcSessionDescriptionFactory;
extern const char kSetLocalSdpFailed[];
extern const char kSetRemoteSdpFailed[];
extern const char kCreateChannelFailed[];
extern const char kBundleWithoutRtcpMux[]; extern const char kBundleWithoutRtcpMux[];
extern const char kCreateChannelFailed[];
extern const char kInvalidCandidates[]; extern const char kInvalidCandidates[];
extern const char kInvalidSdp[]; extern const char kInvalidSdp[];
extern const char kMlineMismatch[]; extern const char kMlineMismatch[];
extern const char kPushDownTDFailed[];
extern const char kSdpWithoutCrypto[]; extern const char kSdpWithoutCrypto[];
extern const char kSdpWithoutSdesAndDtlsDisabled[];
extern const char kSdpWithoutIceUfragPwd[]; extern const char kSdpWithoutIceUfragPwd[];
extern const char kSdpWithoutSdesAndDtlsDisabled[];
extern const char kSessionError[]; extern const char kSessionError[];
extern const char kUpdateStateFailed[]; extern const char kSessionErrorDesc[];
extern const char kPushDownOfferTDFailed[];
extern const char kPushDownPranswerTDFailed[];
extern const char kPushDownAnswerTDFailed[];
// ICE state callback interface. // ICE state callback interface.
class IceObserver { class IceObserver {
@@ -226,7 +222,6 @@ class WebRtcSession : public cricket::BaseSession,
// candidates allocation. // candidates allocation.
bool StartCandidatesAllocation(); bool StartCandidatesAllocation();
bool UpdateSessionState(Action action, cricket::ContentSource source, bool UpdateSessionState(Action action, cricket::ContentSource source,
const cricket::SessionDescription* desc,
std::string* err_desc); std::string* err_desc);
static Action GetAction(const std::string& type); static Action GetAction(const std::string& type);
@@ -285,7 +280,7 @@ class WebRtcSession : public cricket::BaseSession,
bool GetLocalTrackId(uint32 ssrc, std::string* track_id); bool GetLocalTrackId(uint32 ssrc, std::string* track_id);
bool GetRemoteTrackId(uint32 ssrc, std::string* track_id); bool GetRemoteTrackId(uint32 ssrc, std::string* track_id);
std::string BadStateErrMsg(const std::string& type, State state); std::string BadStateErrMsg(State state);
void SetIceConnectionState(PeerConnectionInterface::IceConnectionState state); void SetIceConnectionState(PeerConnectionInterface::IceConnectionState state);
bool ValidateBundleSettings(const cricket::SessionDescription* desc); bool ValidateBundleSettings(const cricket::SessionDescription* desc);
@@ -293,7 +288,7 @@ class WebRtcSession : public cricket::BaseSession,
// Below methods are helper methods which verifies SDP. // Below methods are helper methods which verifies SDP.
bool ValidateSessionDescription(const SessionDescriptionInterface* sdesc, bool ValidateSessionDescription(const SessionDescriptionInterface* sdesc,
cricket::ContentSource source, cricket::ContentSource source,
std::string* error_desc); std::string* err_desc);
// Check if a call to SetLocalDescription is acceptable with |action|. // Check if a call to SetLocalDescription is acceptable with |action|.
bool ExpectSetLocalDescription(Action action); bool ExpectSetLocalDescription(Action action);
@@ -303,6 +298,8 @@ class WebRtcSession : public cricket::BaseSession,
bool ValidateDtlsSetupAttribute(const cricket::SessionDescription* desc, bool ValidateDtlsSetupAttribute(const cricket::SessionDescription* desc,
Action action); Action action);
std::string GetSessionErrorMsg();
talk_base::scoped_ptr<cricket::VoiceChannel> voice_channel_; talk_base::scoped_ptr<cricket::VoiceChannel> voice_channel_;
talk_base::scoped_ptr<cricket::VideoChannel> video_channel_; talk_base::scoped_ptr<cricket::VideoChannel> video_channel_;
talk_base::scoped_ptr<cricket::DataChannel> data_channel_; talk_base::scoped_ptr<cricket::DataChannel> data_channel_;

View File

@@ -87,15 +87,15 @@ using webrtc::SessionDescriptionInterface;
using webrtc::StreamCollection; using webrtc::StreamCollection;
using webrtc::WebRtcSession; using webrtc::WebRtcSession;
using webrtc::kBundleWithoutRtcpMux; using webrtc::kBundleWithoutRtcpMux;
using webrtc::kCreateChannelFailed;
using webrtc::kInvalidSdp;
using webrtc::kMlineMismatch; using webrtc::kMlineMismatch;
using webrtc::kPushDownAnswerTDFailed; using webrtc::kPushDownTDFailed;
using webrtc::kPushDownPranswerTDFailed;
using webrtc::kSdpWithoutCrypto; using webrtc::kSdpWithoutCrypto;
using webrtc::kSdpWithoutIceUfragPwd; using webrtc::kSdpWithoutIceUfragPwd;
using webrtc::kSdpWithoutSdesAndDtlsDisabled; using webrtc::kSdpWithoutSdesAndDtlsDisabled;
using webrtc::kSessionError; using webrtc::kSessionError;
using webrtc::kSetLocalSdpFailed; using webrtc::kSessionErrorDesc;
using webrtc::kSetRemoteSdpFailed;
static const int kClientAddrPort = 0; static const int kClientAddrPort = 0;
static const char kClientAddrHost1[] = "11.11.11.11"; static const char kClientAddrHost1[] = "11.11.11.11";
@@ -475,8 +475,8 @@ class WebRtcSessionTest : public testing::Test {
CreateRemoteOffer(options, cricket::SEC_DISABLED)); CreateRemoteOffer(options, cricket::SEC_DISABLED));
ASSERT_TRUE(offer != NULL); ASSERT_TRUE(offer != NULL);
VerifyNoCryptoParams(offer->description(), false); VerifyNoCryptoParams(offer->description(), false);
SetRemoteDescriptionExpectError("Called with a SDP without crypto enabled", SetRemoteDescriptionOfferExpectError(
offer); "Called with a SDP without crypto enabled", offer);
const webrtc::SessionDescriptionInterface* answer = CreateAnswer(NULL); const webrtc::SessionDescriptionInterface* answer = CreateAnswer(NULL);
// Answer should be NULL as no crypto params in offer. // Answer should be NULL as no crypto params in offer.
ASSERT_TRUE(answer == NULL); ASSERT_TRUE(answer == NULL);
@@ -567,13 +567,26 @@ class WebRtcSessionTest : public testing::Test {
SetLocalDescriptionWithoutError(desc); SetLocalDescriptionWithoutError(desc);
EXPECT_EQ(expected_state, session_->state()); EXPECT_EQ(expected_state, session_->state());
} }
void SetLocalDescriptionExpectError(const std::string& expected_error, void SetLocalDescriptionExpectError(const std::string& action,
const std::string& expected_error,
SessionDescriptionInterface* desc) { SessionDescriptionInterface* desc) {
std::string error; std::string error;
EXPECT_FALSE(session_->SetLocalDescription(desc, &error)); EXPECT_FALSE(session_->SetLocalDescription(desc, &error));
EXPECT_NE(std::string::npos, error.find(kSetLocalSdpFailed)); std::string sdp_type = "local ";
sdp_type.append(action);
EXPECT_NE(std::string::npos, error.find(sdp_type));
EXPECT_NE(std::string::npos, error.find(expected_error)); EXPECT_NE(std::string::npos, error.find(expected_error));
} }
void SetLocalDescriptionOfferExpectError(const std::string& expected_error,
SessionDescriptionInterface* desc) {
SetLocalDescriptionExpectError(SessionDescriptionInterface::kOffer,
expected_error, desc);
}
void SetLocalDescriptionAnswerExpectError(const std::string& expected_error,
SessionDescriptionInterface* desc) {
SetLocalDescriptionExpectError(SessionDescriptionInterface::kAnswer,
expected_error, desc);
}
void SetRemoteDescriptionWithoutError(SessionDescriptionInterface* desc) { void SetRemoteDescriptionWithoutError(SessionDescriptionInterface* desc) {
EXPECT_TRUE(session_->SetRemoteDescription(desc, NULL)); EXPECT_TRUE(session_->SetRemoteDescription(desc, NULL));
} }
@@ -582,13 +595,31 @@ class WebRtcSessionTest : public testing::Test {
SetRemoteDescriptionWithoutError(desc); SetRemoteDescriptionWithoutError(desc);
EXPECT_EQ(expected_state, session_->state()); EXPECT_EQ(expected_state, session_->state());
} }
void SetRemoteDescriptionExpectError(const std::string& expected_error, void SetRemoteDescriptionExpectError(const std::string& action,
const std::string& expected_error,
SessionDescriptionInterface* desc) { SessionDescriptionInterface* desc) {
std::string error; std::string error;
EXPECT_FALSE(session_->SetRemoteDescription(desc, &error)); EXPECT_FALSE(session_->SetRemoteDescription(desc, &error));
EXPECT_NE(std::string::npos, error.find(kSetRemoteSdpFailed)); std::string sdp_type = "remote ";
sdp_type.append(action);
EXPECT_NE(std::string::npos, error.find(sdp_type));
EXPECT_NE(std::string::npos, error.find(expected_error)); EXPECT_NE(std::string::npos, error.find(expected_error));
} }
void SetRemoteDescriptionOfferExpectError(
const std::string& expected_error, SessionDescriptionInterface* desc) {
SetRemoteDescriptionExpectError(SessionDescriptionInterface::kOffer,
expected_error, desc);
}
void SetRemoteDescriptionPranswerExpectError(
const std::string& expected_error, SessionDescriptionInterface* desc) {
SetRemoteDescriptionExpectError(SessionDescriptionInterface::kPrAnswer,
expected_error, desc);
}
void SetRemoteDescriptionAnswerExpectError(
const std::string& expected_error, SessionDescriptionInterface* desc) {
SetRemoteDescriptionExpectError(SessionDescriptionInterface::kAnswer,
expected_error, desc);
}
void CreateCryptoOfferAndNonCryptoAnswer(SessionDescriptionInterface** offer, void CreateCryptoOfferAndNonCryptoAnswer(SessionDescriptionInterface** offer,
SessionDescriptionInterface** nocrypto_answer) { SessionDescriptionInterface** nocrypto_answer) {
@@ -998,6 +1029,15 @@ TEST_F(WebRtcSessionTest, TestStunError) {
EXPECT_EQ(6u, observer_.mline_1_candidates_.size()); EXPECT_EQ(6u, observer_.mline_1_candidates_.size());
} }
TEST_F(WebRtcSessionTest, SetSdpFailedOnInvalidSdp) {
Init(NULL);
SessionDescriptionInterface* offer = NULL;
// Since |offer| is NULL, there's no way to tell if it's an offer or answer.
std::string unknown_action;
SetLocalDescriptionExpectError(unknown_action, kInvalidSdp, offer);
SetRemoteDescriptionExpectError(unknown_action, kInvalidSdp, offer);
}
// Test creating offers and receive answers and make sure the // Test creating offers and receive answers and make sure the
// media engine creates the expected send and receive streams. // media engine creates the expected send and receive streams.
TEST_F(WebRtcSessionTest, TestCreateOfferReceiveAnswer) { TEST_F(WebRtcSessionTest, TestCreateOfferReceiveAnswer) {
@@ -1109,6 +1149,20 @@ TEST_F(WebRtcSessionTest, TestReceiveOfferCreateAnswer) {
EXPECT_EQ(0u, voice_channel_->send_streams().size()); EXPECT_EQ(0u, voice_channel_->send_streams().size());
} }
TEST_F(WebRtcSessionTest, SetLocalSdpFailedOnCreateChannel) {
Init(NULL);
media_engine_->set_fail_create_channel(true);
SessionDescriptionInterface* offer = CreateOffer(NULL);
ASSERT_TRUE(offer != NULL);
// SetRemoteDescription and SetLocalDescription will take the ownership of
// the offer.
SetRemoteDescriptionOfferExpectError(kCreateChannelFailed, offer);
offer = CreateOffer(NULL);
ASSERT_TRUE(offer != NULL);
SetLocalDescriptionOfferExpectError(kCreateChannelFailed, offer);
}
// Test we will return fail when apply an offer that doesn't have // Test we will return fail when apply an offer that doesn't have
// crypto enabled. // crypto enabled.
TEST_F(WebRtcSessionTest, SetNonCryptoOffer) { TEST_F(WebRtcSessionTest, SetNonCryptoOffer) {
@@ -1121,10 +1175,10 @@ TEST_F(WebRtcSessionTest, SetNonCryptoOffer) {
VerifyNoCryptoParams(offer->description(), false); VerifyNoCryptoParams(offer->description(), false);
// SetRemoteDescription and SetLocalDescription will take the ownership of // SetRemoteDescription and SetLocalDescription will take the ownership of
// the offer. // the offer.
SetRemoteDescriptionExpectError(kSdpWithoutCrypto, offer); SetRemoteDescriptionOfferExpectError(kSdpWithoutCrypto, offer);
offer = CreateRemoteOffer(options, cricket::SEC_DISABLED); offer = CreateRemoteOffer(options, cricket::SEC_DISABLED);
ASSERT_TRUE(offer != NULL); ASSERT_TRUE(offer != NULL);
SetLocalDescriptionExpectError(kSdpWithoutCrypto, offer); SetLocalDescriptionOfferExpectError(kSdpWithoutCrypto, offer);
} }
// Test we will return fail when apply an answer that doesn't have // Test we will return fail when apply an answer that doesn't have
@@ -1137,7 +1191,7 @@ TEST_F(WebRtcSessionTest, SetLocalNonCryptoAnswer) {
// SetRemoteDescription and SetLocalDescription will take the ownership of // SetRemoteDescription and SetLocalDescription will take the ownership of
// the offer. // the offer.
SetRemoteDescriptionWithoutError(offer); SetRemoteDescriptionWithoutError(offer);
SetLocalDescriptionExpectError(kSdpWithoutCrypto, answer); SetLocalDescriptionAnswerExpectError(kSdpWithoutCrypto, answer);
} }
// Test we will return fail when apply an answer that doesn't have // Test we will return fail when apply an answer that doesn't have
@@ -1150,7 +1204,7 @@ TEST_F(WebRtcSessionTest, SetRemoteNonCryptoAnswer) {
// SetRemoteDescription and SetLocalDescription will take the ownership of // SetRemoteDescription and SetLocalDescription will take the ownership of
// the offer. // the offer.
SetLocalDescriptionWithoutError(offer); SetLocalDescriptionWithoutError(offer);
SetRemoteDescriptionExpectError(kSdpWithoutCrypto, answer); SetRemoteDescriptionAnswerExpectError(kSdpWithoutCrypto, answer);
} }
// Test that we can create and set an offer with a DTLS fingerprint. // Test that we can create and set an offer with a DTLS fingerprint.
@@ -1245,9 +1299,8 @@ TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteOffer) {
SessionDescriptionInterface* offer = CreateOffer(NULL); SessionDescriptionInterface* offer = CreateOffer(NULL);
SetLocalDescriptionWithoutError(offer); SetLocalDescriptionWithoutError(offer);
offer = CreateOffer(NULL); offer = CreateOffer(NULL);
SetRemoteDescriptionExpectError( SetRemoteDescriptionOfferExpectError(
"Called with type in wrong state, type: offer state: STATE_SENTINITIATE", "Called in wrong state: STATE_SENTINITIATE", offer);
offer);
} }
TEST_F(WebRtcSessionTest, TestSetRemoteAndLocalOffer) { TEST_F(WebRtcSessionTest, TestSetRemoteAndLocalOffer) {
@@ -1256,10 +1309,8 @@ TEST_F(WebRtcSessionTest, TestSetRemoteAndLocalOffer) {
SessionDescriptionInterface* offer = CreateOffer(NULL); SessionDescriptionInterface* offer = CreateOffer(NULL);
SetRemoteDescriptionWithoutError(offer); SetRemoteDescriptionWithoutError(offer);
offer = CreateOffer(NULL); offer = CreateOffer(NULL);
SetLocalDescriptionExpectError( SetLocalDescriptionOfferExpectError(
"Called with type in wrong state, type: " "Called in wrong state: STATE_RECEIVEDINITIATE", offer);
"offer state: STATE_RECEIVEDINITIATE",
offer);
} }
TEST_F(WebRtcSessionTest, TestSetLocalPrAnswer) { TEST_F(WebRtcSessionTest, TestSetLocalPrAnswer) {
@@ -1319,8 +1370,7 @@ TEST_F(WebRtcSessionTest, TestSetLocalAnswerWithoutOffer) {
CreateOffer(NULL)); CreateOffer(NULL));
SessionDescriptionInterface* answer = SessionDescriptionInterface* answer =
CreateRemoteAnswer(offer.get()); CreateRemoteAnswer(offer.get());
SetLocalDescriptionExpectError( SetLocalDescriptionAnswerExpectError("Called in wrong state: STATE_INIT",
"Called with type in wrong state, type: answer state: STATE_INIT",
answer); answer);
} }
@@ -1331,9 +1381,8 @@ TEST_F(WebRtcSessionTest, TestSetRemoteAnswerWithoutOffer) {
CreateOffer(NULL)); CreateOffer(NULL));
SessionDescriptionInterface* answer = SessionDescriptionInterface* answer =
CreateRemoteAnswer(offer.get()); CreateRemoteAnswer(offer.get());
SetRemoteDescriptionExpectError( SetRemoteDescriptionAnswerExpectError(
"Called with type in wrong state, type: answer state: STATE_INIT", "Called in wrong state: STATE_INIT", answer);
answer);
} }
TEST_F(WebRtcSessionTest, TestAddRemoteCandidate) { TEST_F(WebRtcSessionTest, TestAddRemoteCandidate) {
@@ -1979,7 +2028,7 @@ TEST_F(WebRtcSessionTest, TestSetLocalDescriptionWithoutIce) {
RemoveIceUfragPwdLines(offer.get(), &sdp); RemoveIceUfragPwdLines(offer.get(), &sdp);
SessionDescriptionInterface* modified_offer = SessionDescriptionInterface* modified_offer =
CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL); CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
SetLocalDescriptionExpectError(kSdpWithoutIceUfragPwd, modified_offer); SetLocalDescriptionOfferExpectError(kSdpWithoutIceUfragPwd, modified_offer);
} }
// This test verifies that setRemoteDescription fails if // This test verifies that setRemoteDescription fails if
@@ -1991,7 +2040,7 @@ TEST_F(WebRtcSessionTest, TestSetRemoteDescriptionWithoutIce) {
RemoveIceUfragPwdLines(offer.get(), &sdp); RemoveIceUfragPwdLines(offer.get(), &sdp);
SessionDescriptionInterface* modified_offer = SessionDescriptionInterface* modified_offer =
CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL); CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
SetRemoteDescriptionExpectError(kSdpWithoutIceUfragPwd, modified_offer); SetRemoteDescriptionOfferExpectError(kSdpWithoutIceUfragPwd, modified_offer);
} }
TEST_F(WebRtcSessionTest, VerifyBundleFlagInPA) { TEST_F(WebRtcSessionTest, VerifyBundleFlagInPA) {
@@ -2071,11 +2120,11 @@ TEST_F(WebRtcSessionTest, TestDisabledRtcpMuxWithBundleEnabled) {
JsepSessionDescription *local_offer = JsepSessionDescription *local_offer =
new JsepSessionDescription(JsepSessionDescription::kOffer); new JsepSessionDescription(JsepSessionDescription::kOffer);
EXPECT_TRUE((local_offer)->Initialize(offer_str, NULL)); EXPECT_TRUE((local_offer)->Initialize(offer_str, NULL));
SetLocalDescriptionExpectError(kBundleWithoutRtcpMux, local_offer); SetLocalDescriptionOfferExpectError(kBundleWithoutRtcpMux, local_offer);
JsepSessionDescription *remote_offer = JsepSessionDescription *remote_offer =
new JsepSessionDescription(JsepSessionDescription::kOffer); new JsepSessionDescription(JsepSessionDescription::kOffer);
EXPECT_TRUE((remote_offer)->Initialize(offer_str, NULL)); EXPECT_TRUE((remote_offer)->Initialize(offer_str, NULL));
SetRemoteDescriptionExpectError(kBundleWithoutRtcpMux, remote_offer); SetRemoteDescriptionOfferExpectError(kBundleWithoutRtcpMux, remote_offer);
// Trying unmodified SDP. // Trying unmodified SDP.
SetLocalDescriptionWithoutError(offer); SetLocalDescriptionWithoutError(offer);
} }
@@ -2319,12 +2368,12 @@ TEST_F(WebRtcSessionTest, TestIceOfferGIceOnlyAnswer) {
SessionDescriptionInterface* pranswer_with_gice = SessionDescriptionInterface* pranswer_with_gice =
CreateSessionDescription(JsepSessionDescription::kPrAnswer, CreateSessionDescription(JsepSessionDescription::kPrAnswer,
original_offer_sdp, NULL); original_offer_sdp, NULL);
SetRemoteDescriptionExpectError(kPushDownPranswerTDFailed, SetRemoteDescriptionPranswerExpectError(kPushDownTDFailed,
pranswer_with_gice); pranswer_with_gice);
SessionDescriptionInterface* answer_with_gice = SessionDescriptionInterface* answer_with_gice =
CreateSessionDescription(JsepSessionDescription::kAnswer, CreateSessionDescription(JsepSessionDescription::kAnswer,
original_offer_sdp, NULL); original_offer_sdp, NULL);
SetRemoteDescriptionExpectError(kPushDownAnswerTDFailed, SetRemoteDescriptionAnswerExpectError(kPushDownTDFailed,
answer_with_gice); answer_with_gice);
} }
@@ -2345,7 +2394,7 @@ TEST_F(WebRtcSessionTest, TestIncorrectMLinesInRemoteAnswer) {
EXPECT_TRUE(modified_answer->Initialize(answer_copy, EXPECT_TRUE(modified_answer->Initialize(answer_copy,
answer->session_id(), answer->session_id(),
answer->session_version())); answer->session_version()));
SetRemoteDescriptionExpectError(kMlineMismatch, modified_answer); SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer);
// Modifying content names. // Modifying content names.
std::string sdp; std::string sdp;
@@ -2361,7 +2410,7 @@ TEST_F(WebRtcSessionTest, TestIncorrectMLinesInRemoteAnswer) {
SessionDescriptionInterface* modified_answer1 = SessionDescriptionInterface* modified_answer1 =
CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL); CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
SetRemoteDescriptionExpectError(kMlineMismatch, modified_answer1); SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer1);
SetRemoteDescriptionWithoutError(answer.release()); SetRemoteDescriptionWithoutError(answer.release());
} }
@@ -2383,7 +2432,7 @@ TEST_F(WebRtcSessionTest, TestIncorrectMLinesInLocalAnswer) {
EXPECT_TRUE(modified_answer->Initialize(answer_copy, EXPECT_TRUE(modified_answer->Initialize(answer_copy,
answer->session_id(), answer->session_id(),
answer->session_version())); answer->session_version()));
SetLocalDescriptionExpectError(kMlineMismatch, modified_answer); SetLocalDescriptionAnswerExpectError(kMlineMismatch, modified_answer);
SetLocalDescriptionWithoutError(answer); SetLocalDescriptionWithoutError(answer);
} }
@@ -2537,7 +2586,7 @@ TEST_F(WebRtcSessionTest, TestSessionContentError) {
mediastream_signaling_.SendAudioVideoStream2(); mediastream_signaling_.SendAudioVideoStream2();
SessionDescriptionInterface* answer = SessionDescriptionInterface* answer =
CreateRemoteAnswer(session_->local_description()); CreateRemoteAnswer(session_->local_description());
SetRemoteDescriptionExpectError("ERROR_CONTENT", answer); SetRemoteDescriptionAnswerExpectError("ERROR_CONTENT", answer);
} }
// Runs the loopback call test with BUNDLE and STUN disabled. // Runs the loopback call test with BUNDLE and STUN disabled.
@@ -2550,20 +2599,27 @@ TEST_F(WebRtcSessionTest, TestIceStatesBasic) {
TestLoopbackCall(); TestLoopbackCall();
} }
// Regression-test for a crash which should have been an error. TEST_F(WebRtcSessionTest, SetSdpFailedOnSessionError) {
TEST_F(WebRtcSessionTest, TestNoStateTransitionPendingError) {
Init(NULL); Init(NULL);
cricket::MediaSessionOptions options; cricket::MediaSessionOptions options;
options.has_audio = true; options.has_audio = true;
options.has_video = true; options.has_video = true;
session_->SetError(cricket::BaseSession::ERROR_CONTENT); cricket::BaseSession::Error error_code = cricket::BaseSession::ERROR_CONTENT;
std::string error_code_str = "ERROR_CONTENT";
std::string error_desc = "Fake session error description.";
session_->SetError(error_code, error_desc);
SessionDescriptionInterface* offer = CreateRemoteOffer(options); SessionDescriptionInterface* offer = CreateRemoteOffer(options);
SessionDescriptionInterface* answer = SessionDescriptionInterface* answer =
CreateRemoteAnswer(offer, options); CreateRemoteAnswer(offer, options);
SetRemoteDescriptionExpectError(kSessionError, offer);
SetLocalDescriptionExpectError(kSessionError, answer); std::string action;
// Not crashing is our success. std::ostringstream session_error_msg;
session_error_msg << kSessionError << error_code_str << ". ";
session_error_msg << kSessionErrorDesc << error_desc << ".";
SetRemoteDescriptionExpectError(action, session_error_msg.str(), offer);
SetLocalDescriptionExpectError(action, session_error_msg.str(), answer);
} }
TEST_F(WebRtcSessionTest, TestRtpDataChannel) { TEST_F(WebRtcSessionTest, TestRtpDataChannel) {
@@ -2803,7 +2859,7 @@ TEST_F(WebRtcSessionTest, TestSetRemoteOfferFailIfDtlsDisabledAndNoCrypto) {
audio->description.identity_fingerprint.reset( audio->description.identity_fingerprint.reset(
talk_base::SSLFingerprint::CreateFromRfc4572( talk_base::SSLFingerprint::CreateFromRfc4572(
talk_base::DIGEST_SHA_256, kFakeDtlsFingerprint)); talk_base::DIGEST_SHA_256, kFakeDtlsFingerprint));
SetRemoteDescriptionExpectError(kSdpWithoutSdesAndDtlsDisabled, SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesAndDtlsDisabled,
offer); offer);
} }

114
talk/base/sslfingerprint.cc Normal file
View File

@@ -0,0 +1,114 @@
/*
* libjingle
* Copyright 2012, Google Inc.
* Copyright 2012, RTFM Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "talk/base/sslfingerprint.h"
#include <ctype.h>
#include <string>
#include "talk/base/helpers.h"
#include "talk/base/messagedigest.h"
#include "talk/base/stringencode.h"
namespace talk_base {
SSLFingerprint* SSLFingerprint::Create(
const std::string& algorithm, const talk_base::SSLIdentity* identity) {
if (!identity) {
return NULL;
}
return Create(algorithm, &(identity->certificate()));
}
SSLFingerprint* SSLFingerprint::Create(
const std::string& algorithm, const talk_base::SSLCertificate* cert) {
uint8 digest_val[64];
size_t digest_len;
bool ret = cert->ComputeDigest(
algorithm, digest_val, sizeof(digest_val), &digest_len);
if (!ret) {
return NULL;
}
return new SSLFingerprint(algorithm, digest_val, digest_len);
}
SSLFingerprint* SSLFingerprint::CreateFromRfc4572(
const std::string& algorithm, const std::string& fingerprint) {
if (algorithm.empty() || !talk_base::IsFips180DigestAlgorithm(algorithm))
return NULL;
if (fingerprint.empty())
return NULL;
size_t value_len;
char value[talk_base::MessageDigest::kMaxSize];
value_len = talk_base::hex_decode_with_delimiter(value, sizeof(value),
fingerprint.c_str(),
fingerprint.length(),
':');
if (!value_len)
return NULL;
return new SSLFingerprint(algorithm,
reinterpret_cast<uint8*>(value),
value_len);
}
SSLFingerprint::SSLFingerprint(
const std::string& algorithm, const uint8* digest_in, size_t digest_len)
: algorithm(algorithm) {
digest.SetData(digest_in, digest_len);
}
SSLFingerprint::SSLFingerprint(const SSLFingerprint& from)
: algorithm(from.algorithm), digest(from.digest) {}
bool SSLFingerprint::operator==(const SSLFingerprint& other) const {
return algorithm == other.algorithm &&
digest == other.digest;
}
std::string SSLFingerprint::GetRfc4572Fingerprint() const {
std::string fingerprint =
talk_base::hex_encode_with_delimiter(
digest.data(), digest.length(), ':');
std::transform(fingerprint.begin(), fingerprint.end(),
fingerprint.begin(), ::toupper);
return fingerprint;
}
std::string SSLFingerprint::ToString() {
std::string fp_str = algorithm;
fp_str.append(" ");
fp_str.append(GetRfc4572Fingerprint());
return fp_str;
}
} // namespace talk_base

View File

@@ -29,81 +29,35 @@
#ifndef TALK_BASE_SSLFINGERPRINT_H_ #ifndef TALK_BASE_SSLFINGERPRINT_H_
#define TALK_BASE_SSLFINGERPRINT_H_ #define TALK_BASE_SSLFINGERPRINT_H_
#include <ctype.h>
#include <string> #include <string>
#include "talk/base/buffer.h" #include "talk/base/buffer.h"
#include "talk/base/helpers.h"
#include "talk/base/messagedigest.h"
#include "talk/base/sslidentity.h" #include "talk/base/sslidentity.h"
#include "talk/base/stringencode.h"
namespace talk_base { namespace talk_base {
class SSLCertificate;
struct SSLFingerprint { struct SSLFingerprint {
static SSLFingerprint* Create(const std::string& algorithm, static SSLFingerprint* Create(const std::string& algorithm,
const talk_base::SSLIdentity* identity) { const talk_base::SSLIdentity* identity);
if (!identity) {
return NULL;
}
return Create(algorithm, &(identity->certificate()));
}
static SSLFingerprint* Create(const std::string& algorithm, static SSLFingerprint* Create(const std::string& algorithm,
const talk_base::SSLCertificate* cert) { const talk_base::SSLCertificate* cert);
uint8 digest_val[64];
size_t digest_len;
bool ret = cert->ComputeDigest(
algorithm, digest_val, sizeof(digest_val), &digest_len);
if (!ret) {
return NULL;
}
return new SSLFingerprint(algorithm, digest_val, digest_len);
}
static SSLFingerprint* CreateFromRfc4572(const std::string& algorithm, static SSLFingerprint* CreateFromRfc4572(const std::string& algorithm,
const std::string& fingerprint) { const std::string& fingerprint);
if (algorithm.empty() || !talk_base::IsFips180DigestAlgorithm(algorithm))
return NULL;
if (fingerprint.empty())
return NULL;
size_t value_len;
char value[talk_base::MessageDigest::kMaxSize];
value_len = talk_base::hex_decode_with_delimiter(value, sizeof(value),
fingerprint.c_str(),
fingerprint.length(),
':');
if (!value_len)
return NULL;
return new SSLFingerprint(algorithm,
reinterpret_cast<uint8*>(value),
value_len);
}
SSLFingerprint(const std::string& algorithm, const uint8* digest_in, SSLFingerprint(const std::string& algorithm, const uint8* digest_in,
size_t digest_len) : algorithm(algorithm) { size_t digest_len);
digest.SetData(digest_in, digest_len);
}
SSLFingerprint(const SSLFingerprint& from)
: algorithm(from.algorithm), digest(from.digest) {}
bool operator==(const SSLFingerprint& other) const {
return algorithm == other.algorithm &&
digest == other.digest;
}
std::string GetRfc4572Fingerprint() const { SSLFingerprint(const SSLFingerprint& from);
std::string fingerprint =
talk_base::hex_encode_with_delimiter( bool operator==(const SSLFingerprint& other) const;
digest.data(), digest.length(), ':');
std::transform(fingerprint.begin(), fingerprint.end(), std::string GetRfc4572Fingerprint() const;
fingerprint.begin(), ::toupper);
return fingerprint; std::string ToString();
}
std::string algorithm; std::string algorithm;
talk_base::Buffer digest; talk_base::Buffer digest;

View File

@@ -26,6 +26,7 @@
*/ */
#include "talk/examples/chat/chatapp.h" #include "talk/examples/chat/chatapp.h"
#include "talk/base/stringencode.h"
#include "talk/examples/chat/consoletask.h" #include "talk/examples/chat/consoletask.h"
#include "talk/examples/chat/textchatsendtask.h" #include "talk/examples/chat/textchatsendtask.h"
#include "talk/examples/chat/textchatreceivetask.h" #include "talk/examples/chat/textchatreceivetask.h"

View File

@@ -410,6 +410,7 @@
'base/ssladapter.cc', 'base/ssladapter.cc',
'base/ssladapter.h', 'base/ssladapter.h',
'base/sslconfig.h', 'base/sslconfig.h',
'base/sslfingerprint.cc',
'base/sslfingerprint.h', 'base/sslfingerprint.h',
'base/sslidentity.cc', 'base/sslidentity.cc',
'base/sslidentity.h', 'base/sslidentity.h',

View File

@@ -281,7 +281,8 @@ class FakeVoiceMediaChannel : public RtpHelper<VoiceMediaChannel> {
} }
return set_sending(flag != SEND_NOTHING); return set_sending(flag != SEND_NOTHING);
} }
virtual bool SetSendBandwidth(bool autobw, int bps) { return true; } virtual bool SetStartSendBandwidth(int bps) { return true; }
virtual bool SetMaxSendBandwidth(int bps) { return true; }
virtual bool AddRecvStream(const StreamParams& sp) { virtual bool AddRecvStream(const StreamParams& sp) {
if (!RtpHelper<VoiceMediaChannel>::AddRecvStream(sp)) if (!RtpHelper<VoiceMediaChannel>::AddRecvStream(sp))
return false; return false;
@@ -446,7 +447,9 @@ class FakeVideoMediaChannel : public RtpHelper<VideoMediaChannel> {
explicit FakeVideoMediaChannel(FakeVideoEngine* engine) explicit FakeVideoMediaChannel(FakeVideoEngine* engine)
: engine_(engine), : engine_(engine),
sent_intra_frame_(false), sent_intra_frame_(false),
requested_intra_frame_(false) {} requested_intra_frame_(false),
start_bps_(-1),
max_bps_(-1) {}
~FakeVideoMediaChannel(); ~FakeVideoMediaChannel();
const std::vector<VideoCodec>& recv_codecs() const { return recv_codecs_; } const std::vector<VideoCodec>& recv_codecs() const { return recv_codecs_; }
@@ -457,6 +460,8 @@ class FakeVideoMediaChannel : public RtpHelper<VideoMediaChannel> {
const std::map<uint32, VideoRenderer*>& renderers() const { const std::map<uint32, VideoRenderer*>& renderers() const {
return renderers_; return renderers_;
} }
int start_bps() const { return start_bps_; }
int max_bps() const { return max_bps_; }
bool GetSendStreamFormat(uint32 ssrc, VideoFormat* format) { bool GetSendStreamFormat(uint32 ssrc, VideoFormat* format) {
if (send_formats_.find(ssrc) == send_formats_.end()) { if (send_formats_.find(ssrc) == send_formats_.end()) {
return false; return false;
@@ -534,7 +539,14 @@ class FakeVideoMediaChannel : public RtpHelper<VideoMediaChannel> {
bool HasCapturer(uint32 ssrc) const { bool HasCapturer(uint32 ssrc) const {
return capturers_.find(ssrc) != capturers_.end(); return capturers_.find(ssrc) != capturers_.end();
} }
virtual bool SetSendBandwidth(bool autobw, int bps) { return true; } virtual bool SetStartSendBandwidth(int bps) {
start_bps_ = bps;
return true;
}
virtual bool SetMaxSendBandwidth(int bps) {
max_bps_ = bps;
return true;
}
virtual bool AddRecvStream(const StreamParams& sp) { virtual bool AddRecvStream(const StreamParams& sp) {
if (!RtpHelper<VideoMediaChannel>::AddRecvStream(sp)) if (!RtpHelper<VideoMediaChannel>::AddRecvStream(sp))
return false; return false;
@@ -591,6 +603,8 @@ class FakeVideoMediaChannel : public RtpHelper<VideoMediaChannel> {
bool sent_intra_frame_; bool sent_intra_frame_;
bool requested_intra_frame_; bool requested_intra_frame_;
VideoOptions options_; VideoOptions options_;
int start_bps_;
int max_bps_;
}; };
class FakeSoundclipMedia : public SoundclipMedia { class FakeSoundclipMedia : public SoundclipMedia {
@@ -601,12 +615,11 @@ class FakeSoundclipMedia : public SoundclipMedia {
class FakeDataMediaChannel : public RtpHelper<DataMediaChannel> { class FakeDataMediaChannel : public RtpHelper<DataMediaChannel> {
public: public:
explicit FakeDataMediaChannel(void* unused) explicit FakeDataMediaChannel(void* unused)
: auto_bandwidth_(false), send_blocked_(false), max_bps_(-1) {} : send_blocked_(false), max_bps_(-1) {}
~FakeDataMediaChannel() {} ~FakeDataMediaChannel() {}
const std::vector<DataCodec>& recv_codecs() const { return recv_codecs_; } const std::vector<DataCodec>& recv_codecs() const { return recv_codecs_; }
const std::vector<DataCodec>& send_codecs() const { return send_codecs_; } const std::vector<DataCodec>& send_codecs() const { return send_codecs_; }
const std::vector<DataCodec>& codecs() const { return send_codecs(); } const std::vector<DataCodec>& codecs() const { return send_codecs(); }
bool auto_bandwidth() const { return auto_bandwidth_; }
int max_bps() const { return max_bps_; } int max_bps() const { return max_bps_; }
virtual bool SetRecvCodecs(const std::vector<DataCodec>& codecs) { virtual bool SetRecvCodecs(const std::vector<DataCodec>& codecs) {
@@ -630,8 +643,8 @@ class FakeDataMediaChannel : public RtpHelper<DataMediaChannel> {
set_playout(receive); set_playout(receive);
return true; return true;
} }
virtual bool SetSendBandwidth(bool autobw, int bps) { virtual bool SetStartSendBandwidth(int bps) { return true; }
auto_bandwidth_ = autobw; virtual bool SetMaxSendBandwidth(int bps) {
max_bps_ = bps; max_bps_ = bps;
return true; return true;
} }
@@ -669,7 +682,6 @@ class FakeDataMediaChannel : public RtpHelper<DataMediaChannel> {
std::vector<DataCodec> send_codecs_; std::vector<DataCodec> send_codecs_;
SendDataParams last_sent_data_params_; SendDataParams last_sent_data_params_;
std::string last_sent_data_; std::string last_sent_data_;
bool auto_bandwidth_;
bool send_blocked_; bool send_blocked_;
int max_bps_; int max_bps_;
}; };

View File

@@ -243,7 +243,8 @@ class FileVoiceChannel : public VoiceMediaChannel {
virtual bool AddRecvStream(const StreamParams& sp) { return true; } virtual bool AddRecvStream(const StreamParams& sp) { return true; }
virtual bool RemoveRecvStream(uint32 ssrc) { return true; } virtual bool RemoveRecvStream(uint32 ssrc) { return true; }
virtual bool MuteStream(uint32 ssrc, bool on) { return false; } virtual bool MuteStream(uint32 ssrc, bool on) { return false; }
virtual bool SetSendBandwidth(bool autobw, int bps) { return true; } virtual bool SetStartSendBandwidth(int bps) { return true; }
virtual bool SetMaxSendBandwidth(int bps) { return true; }
virtual bool SetOptions(const AudioOptions& options) { virtual bool SetOptions(const AudioOptions& options) {
options_ = options; options_ = options;
return true; return true;
@@ -311,7 +312,8 @@ class FileVideoChannel : public VideoMediaChannel {
virtual bool AddRecvStream(const StreamParams& sp) { return true; } virtual bool AddRecvStream(const StreamParams& sp) { return true; }
virtual bool RemoveRecvStream(uint32 ssrc) { return true; } virtual bool RemoveRecvStream(uint32 ssrc) { return true; }
virtual bool MuteStream(uint32 ssrc, bool on) { return false; } virtual bool MuteStream(uint32 ssrc, bool on) { return false; }
virtual bool SetSendBandwidth(bool autobw, int bps) { return true; } virtual bool SetStartSendBandwidth(int bps) { return true; }
virtual bool SetMaxSendBandwidth(int bps) { return true; }
virtual bool SetOptions(const VideoOptions& options) { virtual bool SetOptions(const VideoOptions& options) {
options_ = options; options_ = options;
return true; return true;

View File

@@ -183,9 +183,12 @@ bool HybridVideoMediaChannel::SetSendRtpHeaderExtensions(
active_channel_->SetSendRtpHeaderExtensions(extensions); active_channel_->SetSendRtpHeaderExtensions(extensions);
} }
bool HybridVideoMediaChannel::SetSendBandwidth(bool autobw, int bps) { bool HybridVideoMediaChannel::SetStartSendBandwidth(int bps) {
return active_channel_ && return active_channel_ && active_channel_->SetStartSendBandwidth(bps);
active_channel_->SetSendBandwidth(autobw, bps); }
bool HybridVideoMediaChannel::SetMaxSendBandwidth(int bps) {
return active_channel_ && active_channel_->SetMaxSendBandwidth(bps);
} }
bool HybridVideoMediaChannel::SetSend(bool send) { bool HybridVideoMediaChannel::SetSend(bool send) {

View File

@@ -75,7 +75,8 @@ class HybridVideoMediaChannel : public VideoMediaChannel {
virtual bool SetSendStreamFormat(uint32 ssrc, const VideoFormat& format); virtual bool SetSendStreamFormat(uint32 ssrc, const VideoFormat& format);
virtual bool SetSendRtpHeaderExtensions( virtual bool SetSendRtpHeaderExtensions(
const std::vector<RtpHeaderExtension>& extensions); const std::vector<RtpHeaderExtension>& extensions);
virtual bool SetSendBandwidth(bool autobw, int bps); virtual bool SetStartSendBandwidth(int bps);
virtual bool SetMaxSendBandwidth(int bps);
virtual bool SetSend(bool send); virtual bool SetSend(bool send);
virtual bool AddRecvStream(const StreamParams& sp); virtual bool AddRecvStream(const StreamParams& sp);

View File

@@ -535,8 +535,10 @@ class MediaChannel : public sigslot::has_slots<> {
const std::vector<RtpHeaderExtension>& extensions) = 0; const std::vector<RtpHeaderExtension>& extensions) = 0;
virtual bool SetSendRtpHeaderExtensions( virtual bool SetSendRtpHeaderExtensions(
const std::vector<RtpHeaderExtension>& extensions) = 0; const std::vector<RtpHeaderExtension>& extensions) = 0;
// Sets the rate control to use when sending data. // Sets the initial bandwidth to use when sending starts.
virtual bool SetSendBandwidth(bool autobw, int bps) = 0; virtual bool SetStartSendBandwidth(int bps) = 0;
// Sets the maximum allowed bandwidth to use when sending data.
virtual bool SetMaxSendBandwidth(int bps) = 0;
// Base method to send packet using NetworkInterface. // Base method to send packet using NetworkInterface.
bool SendPacket(talk_base::Buffer* packet) { bool SendPacket(talk_base::Buffer* packet) {

View File

@@ -290,8 +290,8 @@ void RtpDataMediaChannel::OnPacketReceived(
SignalDataReceived(params, data, data_len); SignalDataReceived(params, data, data_len);
} }
bool RtpDataMediaChannel::SetSendBandwidth(bool autobw, int bps) { bool RtpDataMediaChannel::SetMaxSendBandwidth(int bps) {
if (autobw || bps <= 0) { if (bps <= 0) {
bps = kDataMaxBandwidth; bps = kDataMaxBandwidth;
} }
send_limiter_.reset(new talk_base::RateLimiter(bps / 8, 1.0)); send_limiter_.reset(new talk_base::RateLimiter(bps / 8, 1.0));

View File

@@ -96,7 +96,8 @@ class RtpDataMediaChannel : public DataMediaChannel {
timing_ = timing; timing_ = timing;
} }
virtual bool SetSendBandwidth(bool autobw, int bps); virtual bool SetStartSendBandwidth(int bps) { return true; }
virtual bool SetMaxSendBandwidth(int bps);
virtual bool SetRecvRtpHeaderExtensions( virtual bool SetRecvRtpHeaderExtensions(
const std::vector<RtpHeaderExtension>& extensions) { return true; } const std::vector<RtpHeaderExtension>& extensions) { return true; }
virtual bool SetSendRtpHeaderExtensions( virtual bool SetSendRtpHeaderExtensions(

View File

@@ -387,7 +387,7 @@ TEST_F(RtpDataMediaChannelTest, SendDataRate) {
// With rtp overhead of 32 bytes, each one of our packets is 36 // With rtp overhead of 32 bytes, each one of our packets is 36
// bytes, or 288 bits. So, a limit of 872bps will allow 3 packets, // bytes, or 288 bits. So, a limit of 872bps will allow 3 packets,
// but not four. // but not four.
dmc->SetSendBandwidth(false, 872); dmc->SetMaxSendBandwidth(872);
EXPECT_TRUE(dmc->SendData(params, payload, &result)); EXPECT_TRUE(dmc->SendData(params, payload, &result));
EXPECT_TRUE(dmc->SendData(params, payload, &result)); EXPECT_TRUE(dmc->SendData(params, payload, &result));

View File

@@ -165,8 +165,8 @@ VideoAdapter::VideoAdapter()
frames_(0), frames_(0),
adapted_frames_(0), adapted_frames_(0),
adaption_changes_(0), adaption_changes_(0),
previous_width_(0), previous_width(0),
previous_height_(0), previous_height(0),
black_output_(false), black_output_(false),
is_black_(false), is_black_(false),
interval_next_frame_(0) { interval_next_frame_(0) {
@@ -240,11 +240,11 @@ int VideoAdapter::GetOutputNumPixels() const {
// TODO(fbarchard): Add AdaptFrameRate function that only drops frames but // TODO(fbarchard): Add AdaptFrameRate function that only drops frames but
// not resolution. // not resolution.
bool VideoAdapter::AdaptFrame(const VideoFrame* in_frame, bool VideoAdapter::AdaptFrame(const VideoFrame* in_frame,
VideoFrame** out_frame) { const VideoFrame** out_frame) {
talk_base::CritScope cs(&critical_section_);
if (!in_frame || !out_frame) { if (!in_frame || !out_frame) {
return false; return false;
} }
talk_base::CritScope cs(&critical_section_);
++frames_; ++frames_;
// Update input to actual frame dimensions. // Update input to actual frame dimensions.
@@ -306,8 +306,8 @@ bool VideoAdapter::AdaptFrame(const VideoFrame* in_frame,
// resolution changes as well. Consider dropping the statistics into their // resolution changes as well. Consider dropping the statistics into their
// own class which could be queried publically. // own class which could be queried publically.
bool changed = false; bool changed = false;
if (previous_width_ && (previous_width_ != (*out_frame)->GetWidth() || if (previous_width && (previous_width != (*out_frame)->GetWidth() ||
previous_height_ != (*out_frame)->GetHeight())) { previous_height != (*out_frame)->GetHeight())) {
show = true; show = true;
++adaption_changes_; ++adaption_changes_;
changed = true; changed = true;
@@ -325,8 +325,8 @@ bool VideoAdapter::AdaptFrame(const VideoFrame* in_frame,
<< "x" << (*out_frame)->GetHeight() << "x" << (*out_frame)->GetHeight()
<< " Changed: " << (changed ? "true" : "false"); << " Changed: " << (changed ? "true" : "false");
} }
previous_width_ = (*out_frame)->GetWidth(); previous_width = (*out_frame)->GetWidth();
previous_height_ = (*out_frame)->GetHeight(); previous_height = (*out_frame)->GetHeight();
return true; return true;
} }

View File

@@ -62,7 +62,7 @@ class VideoAdapter {
// successfully. Return false otherwise. // successfully. Return false otherwise.
// output_frame_ is owned by the VideoAdapter that has the best knowledge on // output_frame_ is owned by the VideoAdapter that has the best knowledge on
// the output frame. // the output frame.
bool AdaptFrame(const VideoFrame* in_frame, VideoFrame** out_frame); bool AdaptFrame(const VideoFrame* in_frame, const VideoFrame** out_frame);
void set_scale_third(bool enable) { void set_scale_third(bool enable) {
LOG(LS_INFO) << "Video Adapter third scaling is now " LOG(LS_INFO) << "Video Adapter third scaling is now "
@@ -90,8 +90,8 @@ class VideoAdapter {
int frames_; // Number of input frames. int frames_; // Number of input frames.
int adapted_frames_; // Number of frames scaled. int adapted_frames_; // Number of frames scaled.
int adaption_changes_; // Number of changes in scale factor. int adaption_changes_; // Number of changes in scale factor.
size_t previous_width_; // Previous adapter output width. size_t previous_width; // Previous adapter output width.
size_t previous_height_; // Previous adapter output height. size_t previous_height; // Previous adapter output height.
bool black_output_; // Flag to tell if we need to black output_frame_. bool black_output_; // Flag to tell if we need to black output_frame_.
bool is_black_; // Flag to tell if output_frame_ is currently black. bool is_black_; // Flag to tell if output_frame_ is currently black.
int64 interval_next_frame_; int64 interval_next_frame_;

View File

@@ -257,7 +257,7 @@ bool VideoCapturer::GetBestCaptureFormat(const VideoFormat& format,
best_format->width = best->width; best_format->width = best->width;
best_format->height = best->height; best_format->height = best->height;
best_format->fourcc = best->fourcc; best_format->fourcc = best->fourcc;
best_format->interval = talk_base::_max(format.interval, best->interval); best_format->interval = best->interval;
LOG(LS_INFO) << " Best " << best_format->ToString() << " Interval " LOG(LS_INFO) << " Best " << best_format->ToString() << " Interval "
<< best_format->interval << " distance " << best_distance; << best_format->interval << " distance " << best_distance;
} }
@@ -301,7 +301,7 @@ std::string VideoCapturer::ToString(const CapturedFrame* captured_frame) const {
std::ostringstream ss; std::ostringstream ss;
ss << fourcc_name << captured_frame->width << "x" << captured_frame->height ss << fourcc_name << captured_frame->width << "x" << captured_frame->height
<< "x" << VideoFormat::IntervalToFps(captured_frame->elapsed_time); << "x" << VideoFormat::IntervalToFpsFloat(captured_frame->elapsed_time);
return ss.str(); return ss.str();
} }
@@ -475,25 +475,14 @@ void VideoCapturer::OnFrameCaptured(VideoCapturer*,
<< desired_width << " x " << desired_height; << desired_width << " x " << desired_height;
return; return;
} }
if (!muted_ && !ApplyProcessors(&i420_frame)) {
VideoFrame* adapted_frame = &i420_frame;
if (!SignalAdaptFrame.is_empty() && !IsScreencast()) {
VideoFrame* out_frame = NULL;
SignalAdaptFrame(this, adapted_frame, &out_frame);
if (!out_frame) {
return; // VideoAdapter dropped the frame.
}
adapted_frame = out_frame;
}
if (!muted_ && !ApplyProcessors(adapted_frame)) {
// Processor dropped the frame. // Processor dropped the frame.
return; return;
} }
if (muted_) { if (muted_) {
adapted_frame->SetToBlack(); i420_frame.SetToBlack();
} }
SignalVideoFrame(this, adapted_frame); SignalVideoFrame(this, &i420_frame);
#endif // VIDEO_FRAME_NAME #endif // VIDEO_FRAME_NAME
} }
@@ -577,9 +566,9 @@ int64 VideoCapturer::GetFormatDistance(const VideoFormat& desired,
int desired_width = desired.width; int desired_width = desired.width;
int desired_height = desired.height; int desired_height = desired.height;
int64 delta_w = supported.width - desired_width; int64 delta_w = supported.width - desired_width;
int64 supported_fps = VideoFormat::IntervalToFps(supported.interval); float supported_fps = VideoFormat::IntervalToFpsFloat(supported.interval);
int64 delta_fps = float delta_fps =
supported_fps - VideoFormat::IntervalToFps(desired.interval); supported_fps - VideoFormat::IntervalToFpsFloat(desired.interval);
// Check height of supported height compared to height we would like it to be. // Check height of supported height compared to height we would like it to be.
int64 aspect_h = int64 aspect_h =
desired_width ? supported.width * desired_height / desired_width desired_width ? supported.width * desired_height / desired_width
@@ -606,9 +595,9 @@ int64 VideoCapturer::GetFormatDistance(const VideoFormat& desired,
// Require camera fps to be at least 96% of what is requested, or higher, // Require camera fps to be at least 96% of what is requested, or higher,
// if resolution differs. 96% allows for slight variations in fps. e.g. 29.97 // if resolution differs. 96% allows for slight variations in fps. e.g. 29.97
if (delta_fps < 0) { if (delta_fps < 0) {
int64 min_desirable_fps = delta_w ? float min_desirable_fps = delta_w ?
VideoFormat::IntervalToFps(desired.interval) * 29 / 30 : VideoFormat::IntervalToFpsFloat(desired.interval) * 28.f / 30.f :
VideoFormat::IntervalToFps(desired.interval) * 24 / 30; VideoFormat::IntervalToFpsFloat(desired.interval) * 23.f / 30.f;
delta_fps = -delta_fps; delta_fps = -delta_fps;
if (supported_fps < min_desirable_fps) { if (supported_fps < min_desirable_fps) {
distance |= static_cast<int64>(1) << 62; distance |= static_cast<int64>(1) << 62;
@@ -616,10 +605,11 @@ int64 VideoCapturer::GetFormatDistance(const VideoFormat& desired,
distance |= static_cast<int64>(1) << 15; distance |= static_cast<int64>(1) << 15;
} }
} }
int64 idelta_fps = static_cast<int>(delta_fps);
// 12 bits for width and height and 8 bits for fps and fourcc. // 12 bits for width and height and 8 bits for fps and fourcc.
distance |= distance |=
(delta_w << 28) | (delta_h << 16) | (delta_fps << 8) | delta_fourcc; (delta_w << 28) | (delta_h << 16) | (idelta_fps << 8) | delta_fourcc;
return distance; return distance;
} }

View File

@@ -255,11 +255,6 @@ class VideoCapturer
// Signal the captured frame to downstream. // Signal the captured frame to downstream.
sigslot::signal2<VideoCapturer*, const CapturedFrame*, sigslot::signal2<VideoCapturer*, const CapturedFrame*,
sigslot::multi_threaded_local> SignalFrameCaptured; sigslot::multi_threaded_local> SignalFrameCaptured;
// If slots are connected to SignalAdaptFrame, this signals with parameters
// of this capturer instance, the input video frame and output frame
// pointer, respectively.
sigslot::signal3<VideoCapturer*, const VideoFrame*, VideoFrame**,
sigslot::multi_threaded_local> SignalAdaptFrame;
// Signal the captured frame converted to I420 to downstream. // Signal the captured frame converted to I420 to downstream.
sigslot::signal2<VideoCapturer*, const VideoFrame*, sigslot::signal2<VideoCapturer*, const VideoFrame*,
sigslot::multi_threaded_local> SignalVideoFrame; sigslot::multi_threaded_local> SignalVideoFrame;

View File

@@ -507,23 +507,23 @@ TEST_F(VideoCapturerTest, TestFpsFormats) {
cricket::VideoFormat::FpsToInterval(10), cricket::FOURCC_ANY)); cricket::VideoFormat::FpsToInterval(10), cricket::FOURCC_ANY));
cricket::VideoFormat best; cricket::VideoFormat best;
// expect 30 fps to choose 30 fps format // Expect 30 fps to choose 30 fps format.
EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[0], &best)); EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[0], &best));
EXPECT_EQ(640, best.width); EXPECT_EQ(640, best.width);
EXPECT_EQ(400, best.height); EXPECT_EQ(400, best.height);
EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval); EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
// expect 20 fps to choose 20 fps format // Expect 20 fps to choose 30 fps format.
EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[1], &best)); EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[1], &best));
EXPECT_EQ(640, best.width); EXPECT_EQ(640, best.width);
EXPECT_EQ(400, best.height); EXPECT_EQ(400, best.height);
EXPECT_EQ(cricket::VideoFormat::FpsToInterval(20), best.interval); EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
// expect 10 fps to choose 15 fps format but set fps to 10 // Expect 10 fps to choose 15 fps format and set fps to 15.
EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[2], &best)); EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[2], &best));
EXPECT_EQ(640, best.width); EXPECT_EQ(640, best.width);
EXPECT_EQ(480, best.height); EXPECT_EQ(480, best.height);
EXPECT_EQ(cricket::VideoFormat::FpsToInterval(10), best.interval); EXPECT_EQ(cricket::VideoFormat::FpsToInterval(15), best.interval);
// We have VGA 60 fps and 15 fps. Choose best fps. // We have VGA 60 fps and 15 fps. Choose best fps.
supported_formats.clear(); supported_formats.clear();
@@ -539,23 +539,23 @@ TEST_F(VideoCapturerTest, TestFpsFormats) {
cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
capturer_.ResetSupportedFormats(supported_formats); capturer_.ResetSupportedFormats(supported_formats);
// expect 30 fps to choose 60 fps format, but will set best fps to 30 // Expect 30 fps to choose 60 fps format and will set best fps to 60.
EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[0], &best)); EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[0], &best));
EXPECT_EQ(640, best.width); EXPECT_EQ(640, best.width);
EXPECT_EQ(480, best.height); EXPECT_EQ(480, best.height);
EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval); EXPECT_EQ(cricket::VideoFormat::FpsToInterval(60), best.interval);
// expect 20 fps to choose 60 fps format, but will set best fps to 20 // Expect 20 fps to choose 60 fps format, and will set best fps to 60.
EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[1], &best)); EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[1], &best));
EXPECT_EQ(640, best.width); EXPECT_EQ(640, best.width);
EXPECT_EQ(480, best.height); EXPECT_EQ(480, best.height);
EXPECT_EQ(cricket::VideoFormat::FpsToInterval(20), best.interval); EXPECT_EQ(cricket::VideoFormat::FpsToInterval(60), best.interval);
// expect 10 fps to choose 10 fps // Expect 10 fps to choose 15 fps.
EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[2], &best)); EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[2], &best));
EXPECT_EQ(640, best.width); EXPECT_EQ(640, best.width);
EXPECT_EQ(480, best.height); EXPECT_EQ(480, best.height);
EXPECT_EQ(cricket::VideoFormat::FpsToInterval(10), best.interval); EXPECT_EQ(cricket::VideoFormat::FpsToInterval(15), best.interval);
} }
TEST_F(VideoCapturerTest, TestRequest16x10_9) { TEST_F(VideoCapturerTest, TestRequest16x10_9) {

View File

@@ -236,7 +236,8 @@ std::string VideoFormat::ToString() const {
} }
std::ostringstream ss; std::ostringstream ss;
ss << fourcc_name << width << "x" << height << "x" << IntervalToFps(interval); ss << fourcc_name << width << "x" << height << "x"
<< IntervalToFpsFloat(interval);
return ss.str(); return ss.str();
} }

View File

@@ -212,11 +212,17 @@ struct VideoFormat : VideoFormatPod {
} }
static int IntervalToFps(int64 interval) { static int IntervalToFps(int64 interval) {
// Normalize the interval first.
interval = talk_base::_max(interval, kMinimumInterval);
return static_cast<int>(talk_base::kNumNanosecsPerSec / interval); return static_cast<int>(talk_base::kNumNanosecsPerSec / interval);
} }
static float IntervalToFpsFloat(int64 interval) {
if (!interval) {
return 0.f;
}
return static_cast<float>(talk_base::kNumNanosecsPerSec) /
static_cast<float>(interval);
}
bool operator==(const VideoFormat& format) const { bool operator==(const VideoFormat& format) const {
return width == format.width && height == format.height && return width == format.width && height == format.height &&
interval == format.interval && fourcc == format.fourcc; interval == format.interval && fourcc == format.fourcc;

View File

@@ -70,7 +70,7 @@ TEST(VideoCommonTest, TestVideoFormatIsSize0x0) {
// Test ToString: print fourcc when it is printable. // Test ToString: print fourcc when it is printable.
TEST(VideoCommonTest, TestVideoFormatToString) { TEST(VideoCommonTest, TestVideoFormatToString) {
VideoFormat format; VideoFormat format;
EXPECT_EQ("0x0x10000", format.ToString()); EXPECT_EQ("0x0x0", format.ToString());
format.fourcc = FOURCC_I420; format.fourcc = FOURCC_I420;
format.width = 640; format.width = 640;

View File

@@ -928,12 +928,11 @@ class VideoMediaChannelTest : public testing::Test,
EXPECT_TRUE(channel_->SetCapturer(5678, NULL)); EXPECT_TRUE(channel_->SetCapturer(5678, NULL));
} }
// Test that we can set the bandwidth to auto or a specific value. // Test that we can set the bandwidth.
void SetSendBandwidth() { void SetSendBandwidth() {
EXPECT_TRUE(channel_->SetSendBandwidth(true, -1)); EXPECT_TRUE(channel_->SetStartSendBandwidth(64 * 1024));
EXPECT_TRUE(channel_->SetSendBandwidth(true, 128 * 1024)); EXPECT_TRUE(channel_->SetMaxSendBandwidth(-1)); // <= 0 means unlimited.
EXPECT_TRUE(channel_->SetSendBandwidth(false, -1)); EXPECT_TRUE(channel_->SetMaxSendBandwidth(128 * 1024));
EXPECT_TRUE(channel_->SetSendBandwidth(false, 128 * 1024));
} }
// Test that we can set the SSRC for the default send source. // Test that we can set the SSRC for the default send source.
void SetSendSsrc() { void SetSendSsrc() {

View File

@@ -145,7 +145,8 @@ class LinphoneVoiceChannel : public VoiceMediaChannel {
virtual void SetSendSsrc(uint32 id) {} // TODO: change RTP packet? virtual void SetSendSsrc(uint32 id) {} // TODO: change RTP packet?
virtual bool SetRtcpCName(const std::string& cname) { return true; } virtual bool SetRtcpCName(const std::string& cname) { return true; }
virtual bool Mute(bool on) { return mute_; } virtual bool Mute(bool on) { return mute_; }
virtual bool SetSendBandwidth(bool autobw, int bps) { return true; } virtual bool SetStartSendBandwidth(int bps) { return true; }
virtual bool SetMaxSendBandwidth(int bps) { return true; }
virtual bool SetOptions(int options) { return true; } virtual bool SetOptions(int options) { return true; }
virtual bool SetRecvRtpHeaderExtensions( virtual bool SetRecvRtpHeaderExtensions(
const std::vector<RtpHeaderExtension>& extensions) { return true; } const std::vector<RtpHeaderExtension>& extensions) { return true; }

View File

@@ -30,7 +30,7 @@
#include <errno.h> #include <errno.h>
#include <string> #include <string>
#include <set> #include <vector>
namespace cricket { namespace cricket {
// Some ERRNO values get re-#defined to WSA* equivalents in some talk/ // Some ERRNO values get re-#defined to WSA* equivalents in some talk/
@@ -166,7 +166,8 @@ class SctpDataMediaChannel : public DataMediaChannel,
// TODO(pthatcher): Cleanup MediaChannel interface, or at least // TODO(pthatcher): Cleanup MediaChannel interface, or at least
// don't try calling these and return false. Right now, things // don't try calling these and return false. Right now, things
// don't work if we return false. // don't work if we return false.
virtual bool SetSendBandwidth(bool autobw, int bps) { return true; } virtual bool SetStartSendBandwidth(int bps) { return true; }
virtual bool SetMaxSendBandwidth(int bps) { return true; }
virtual bool SetRecvRtpHeaderExtensions( virtual bool SetRecvRtpHeaderExtensions(
const std::vector<RtpHeaderExtension>& extensions) { return true; } const std::vector<RtpHeaderExtension>& extensions) { return true; }
virtual bool SetSendRtpHeaderExtensions( virtual bool SetSendRtpHeaderExtensions(
@@ -216,6 +217,7 @@ class SctpDataMediaChannel : public DataMediaChannel,
talk_base::Buffer* buffer); talk_base::Buffer* buffer);
void OnNotificationFromSctp(talk_base::Buffer* buffer); void OnNotificationFromSctp(talk_base::Buffer* buffer);
void OnNotificationAssocChange(const sctp_assoc_change& change); void OnNotificationAssocChange(const sctp_assoc_change& change);
void OnStreamResetEvent(const struct sctp_stream_reset_event* evt); void OnStreamResetEvent(const struct sctp_stream_reset_event* evt);
// Responsible for marshalling incoming data to the channels listeners, and // Responsible for marshalling incoming data to the channels listeners, and

View File

@@ -632,6 +632,10 @@ class WebRtcVideoChannelSendInfo : public sigslot::has_slots<> {
} }
} }
bool AdaptFrame(const VideoFrame* in_frame, const VideoFrame** out_frame) {
*out_frame = NULL;
return video_adapter_->AdaptFrame(in_frame, out_frame);
}
int CurrentAdaptReason() const { int CurrentAdaptReason() const {
return video_adapter_->adapt_reason(); return video_adapter_->adapt_reason();
} }
@@ -672,18 +676,9 @@ class WebRtcVideoChannelSendInfo : public sigslot::has_slots<> {
// video capturer. // video capturer.
video_adapter_->SetInputFormat(*capture_format); video_adapter_->SetInputFormat(*capture_format);
} }
// TODO(thorcarpenter): When the adapter supports "only frame dropping"
// mode, also hook it up to screencast capturers.
video_capturer->SignalAdaptFrame.connect(
this, &WebRtcVideoChannelSendInfo::AdaptFrame);
} }
} }
void AdaptFrame(VideoCapturer* capturer, const VideoFrame* input,
VideoFrame** adapted) {
video_adapter_->AdaptFrame(input, adapted);
}
void ApplyCpuOptions(const VideoOptions& options) { void ApplyCpuOptions(const VideoOptions& options) {
bool cpu_adapt, cpu_smoothing, adapt_third; bool cpu_adapt, cpu_smoothing, adapt_third;
float low, med, high; float low, med, high;
@@ -2470,7 +2465,9 @@ bool WebRtcVideoMediaChannel::SetCapturer(uint32 ssrc,
MaybeDisconnectCapturer(old_capturer); MaybeDisconnectCapturer(old_capturer);
send_channel->set_video_capturer(capturer); send_channel->set_video_capturer(capturer);
MaybeConnectCapturer(capturer); capturer->SignalVideoFrame.connect(
this,
&WebRtcVideoMediaChannel::SendFrame);
if (!capturer->IsScreencast() && ratio_w_ != 0 && ratio_h_ != 0) { if (!capturer->IsScreencast() && ratio_w_ != 0 && ratio_h_ != 0) {
capturer->UpdateAspectRatio(ratio_w_, ratio_h_); capturer->UpdateAspectRatio(ratio_w_, ratio_h_);
} }
@@ -2624,11 +2621,27 @@ bool WebRtcVideoMediaChannel::SetSendRtpHeaderExtensions(
return true; return true;
} }
bool WebRtcVideoMediaChannel::SetSendBandwidth(bool autobw, int bps) { bool WebRtcVideoMediaChannel::SetStartSendBandwidth(int bps) {
LOG(LS_INFO) << "WebRtcVideoMediaChanne::SetSendBandwidth"; LOG(LS_INFO) << "WebRtcVideoMediaChannel::SetStartSendBandwidth";
if (!send_codec_) {
LOG(LS_INFO) << "The send codec has not been set up yet";
return true;
}
// On success, SetSendCodec() will reset |send_start_bitrate_| to |bps/1000|,
// by calling MaybeChangeStartBitrate. That method will also clamp the
// start bitrate between min and max, consistent with the override behavior
// in SetMaxSendBandwidth.
return SetSendCodec(*send_codec_,
send_min_bitrate_, bps / 1000, send_max_bitrate_);
}
bool WebRtcVideoMediaChannel::SetMaxSendBandwidth(int bps) {
LOG(LS_INFO) << "WebRtcVideoMediaChannel::SetMaxSendBandwidth";
if (InConferenceMode()) { if (InConferenceMode()) {
LOG(LS_INFO) << "Conference mode ignores SetSendBandWidth"; LOG(LS_INFO) << "Conference mode ignores SetMaxSendBandwidth";
return true; return true;
} }
@@ -2637,28 +2650,17 @@ bool WebRtcVideoMediaChannel::SetSendBandwidth(bool autobw, int bps) {
return true; return true;
} }
int min_bitrate;
int start_bitrate;
int max_bitrate;
if (autobw) {
// Use the default values for min bitrate.
min_bitrate = send_min_bitrate_;
// Use the default value or the bps for the max // Use the default value or the bps for the max
max_bitrate = (bps <= 0) ? send_max_bitrate_ : (bps / 1000); int max_bitrate = (bps <= 0) ? send_max_bitrate_ : (bps / 1000);
// Maximum start bitrate can be kStartVideoBitrate.
start_bitrate = talk_base::_min(kStartVideoBitrate, max_bitrate); // Reduce the current minimum and start bitrates if necessary.
} else { int min_bitrate = talk_base::_min(send_min_bitrate_, max_bitrate);
// Use the default start or the bps as the target bitrate. int start_bitrate = talk_base::_min(send_start_bitrate_, max_bitrate);
int target_bitrate = (bps <= 0) ? kStartVideoBitrate : (bps / 1000);
min_bitrate = target_bitrate;
start_bitrate = target_bitrate;
max_bitrate = target_bitrate;
}
if (!SetSendCodec(*send_codec_, min_bitrate, start_bitrate, max_bitrate)) { if (!SetSendCodec(*send_codec_, min_bitrate, start_bitrate, max_bitrate)) {
return false; return false;
} }
LogSendCodecChange("SetSendBandwidth()"); LogSendCodecChange("SetMaxSendBandwidth()");
return true; return true;
} }
@@ -2860,6 +2862,7 @@ bool WebRtcVideoMediaChannel::GetRenderer(uint32 ssrc,
return true; return true;
} }
// TODO(zhurunz): Add unittests to test this function.
void WebRtcVideoMediaChannel::SendFrame(VideoCapturer* capturer, void WebRtcVideoMediaChannel::SendFrame(VideoCapturer* capturer,
const VideoFrame* frame) { const VideoFrame* frame) {
// If the |capturer| is registered to any send channel, then send the frame // If the |capturer| is registered to any send channel, then send the frame

View File

@@ -276,7 +276,8 @@ class WebRtcVideoMediaChannel : public talk_base::MessageHandler,
const std::vector<RtpHeaderExtension>& extensions); const std::vector<RtpHeaderExtension>& extensions);
virtual bool SetSendRtpHeaderExtensions( virtual bool SetSendRtpHeaderExtensions(
const std::vector<RtpHeaderExtension>& extensions); const std::vector<RtpHeaderExtension>& extensions);
virtual bool SetSendBandwidth(bool autobw, int bps); virtual bool SetStartSendBandwidth(int bps);
virtual bool SetMaxSendBandwidth(int bps);
virtual bool SetOptions(const VideoOptions &options); virtual bool SetOptions(const VideoOptions &options);
virtual bool GetOptions(VideoOptions *options) const { virtual bool GetOptions(VideoOptions *options) const {
*options = options_; *options = options_;
@@ -292,6 +293,8 @@ class WebRtcVideoMediaChannel : public talk_base::MessageHandler,
bool SendFrame(WebRtcVideoChannelSendInfo* channel_info, bool SendFrame(WebRtcVideoChannelSendInfo* channel_info,
const VideoFrame* frame, bool is_screencast); const VideoFrame* frame, bool is_screencast);
void AdaptAndSendFrame(VideoCapturer* capturer, const VideoFrame* frame);
// Thunk functions for use with HybridVideoEngine // Thunk functions for use with HybridVideoEngine
void OnLocalFrame(VideoCapturer* capturer, const VideoFrame* frame) { void OnLocalFrame(VideoCapturer* capturer, const VideoFrame* frame) {
SendFrame(0u, frame, capturer->IsScreencast()); SendFrame(0u, frame, capturer->IsScreencast());

View File

@@ -1100,30 +1100,62 @@ TEST_F(WebRtcVideoEngineTestFake, SetBandwidthAuto) {
EXPECT_TRUE(SetupEngine()); EXPECT_TRUE(SetupEngine());
int channel_num = vie_.GetLastChannel(); int channel_num = vie_.GetLastChannel();
EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs())); EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs()));
EXPECT_TRUE(channel_->SetSendBandwidth(true, cricket::kAutoBandwidth)); EXPECT_TRUE(channel_->SetMaxSendBandwidth(cricket::kAutoBandwidth));
VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height); VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height);
} }
// Test that we set bandwidth properly when using auto with upper bound. // Test that we set bandwidth properly when using auto with upper bound.
TEST_F(WebRtcVideoEngineTestFake, SetBandwidthAutoCapped) { TEST_F(WebRtcVideoEngineTestFake, SetBandwidthCapped) {
EXPECT_TRUE(SetupEngine()); EXPECT_TRUE(SetupEngine());
int channel_num = vie_.GetLastChannel(); int channel_num = vie_.GetLastChannel();
EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs())); EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs()));
EXPECT_TRUE(channel_->SetSendBandwidth(true, 768000)); EXPECT_TRUE(channel_->SetMaxSendBandwidth(768000));
VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height, 0, 768U); VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height, 0, 768U);
} }
// Test that we set bandwidth properly when using a fixed bandwidth. // Test that we reduce the start bandwidth when the requested max is less than
TEST_F(WebRtcVideoEngineTestFake, SetBandwidthFixed) { // the default start bandwidth.
TEST_F(WebRtcVideoEngineTestFake, SetMaxBandwidthBelowDefaultStart) {
EXPECT_TRUE(SetupEngine()); EXPECT_TRUE(SetupEngine());
int channel_num = vie_.GetLastChannel(); int channel_num = vie_.GetLastChannel();
EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs())); EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs()));
EXPECT_TRUE(channel_->SetSendBandwidth(false, 768000)); int max_bandwidth_kbps = (kMinBandwidthKbps + kStartBandwidthKbps) / 2;
EXPECT_TRUE(channel_->SetMaxSendBandwidth(max_bandwidth_kbps * 1000));
VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height, 0, VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height, 0,
768U, 768U, 768U); max_bandwidth_kbps, kMinBandwidthKbps, max_bandwidth_kbps);
} }
// Test that SetSendBandwidth is ignored in conference mode. // Test that we reduce the min bandwidth when the requested max is less than
// the min bandwidth.
TEST_F(WebRtcVideoEngineTestFake, SetMaxBandwidthBelowMin) {
EXPECT_TRUE(SetupEngine());
int channel_num = vie_.GetLastChannel();
EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs()));
int max_bandwidth_kbps = kMinBandwidthKbps / 2;
EXPECT_TRUE(channel_->SetMaxSendBandwidth(max_bandwidth_kbps * 1000));
VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height, 0,
max_bandwidth_kbps, max_bandwidth_kbps, max_bandwidth_kbps);
}
// Test that the start bandwidth can be controlled separately from the max
// bandwidth.
TEST_F(WebRtcVideoEngineTestFake, SetStartBandwidth) {
EXPECT_TRUE(SetupEngine());
int channel_num = vie_.GetLastChannel();
EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs()));
int start_bandwidth_kbps = kStartBandwidthKbps + 1;
EXPECT_TRUE(channel_->SetStartSendBandwidth(start_bandwidth_kbps * 1000));
VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height, 0,
kMaxBandwidthKbps, kMinBandwidthKbps, start_bandwidth_kbps);
// Check that SetMaxSendBandwidth doesn't overwrite the start bandwidth.
int max_bandwidth_kbps = kMaxBandwidthKbps + 1;
EXPECT_TRUE(channel_->SetMaxSendBandwidth(max_bandwidth_kbps * 1000));
VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height, 0,
max_bandwidth_kbps, kMinBandwidthKbps, start_bandwidth_kbps);
}
// Test that SetMaxSendBandwidth is ignored in conference mode.
TEST_F(WebRtcVideoEngineTestFake, SetBandwidthInConference) { TEST_F(WebRtcVideoEngineTestFake, SetBandwidthInConference) {
EXPECT_TRUE(SetupEngine()); EXPECT_TRUE(SetupEngine());
int channel_num = vie_.GetLastChannel(); int channel_num = vie_.GetLastChannel();
@@ -1134,7 +1166,7 @@ TEST_F(WebRtcVideoEngineTestFake, SetBandwidthInConference) {
VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height); VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height);
// Set send bandwidth. // Set send bandwidth.
EXPECT_TRUE(channel_->SetSendBandwidth(false, 768000)); EXPECT_TRUE(channel_->SetMaxSendBandwidth(768000));
// Verify bitrate not changed. // Verify bitrate not changed.
webrtc::VideoCodec gcodec; webrtc::VideoCodec gcodec;
@@ -1159,12 +1191,11 @@ TEST_F(WebRtcVideoEngineTestFake, SetBandwidthScreencast) {
EXPECT_TRUE(channel_->AddSendStream( EXPECT_TRUE(channel_->AddSendStream(
cricket::StreamParams::CreateLegacy(123))); cricket::StreamParams::CreateLegacy(123)));
EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); EXPECT_TRUE(channel_->SetSendCodecs(codec_list));
EXPECT_TRUE(channel_->SetSendBandwidth(false, 111000)); EXPECT_TRUE(channel_->SetMaxSendBandwidth(111000));
EXPECT_TRUE(channel_->SetSend(true)); EXPECT_TRUE(channel_->SetSend(true));
SendI420ScreencastFrame(kVP8Codec.width, kVP8Codec.height); SendI420ScreencastFrame(kVP8Codec.width, kVP8Codec.height);
VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height, 0, VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height, 0, 111);
111, 111, 111);
} }
@@ -1243,7 +1274,11 @@ TEST_F(WebRtcVideoEngineTestFake, SetOptionsWithDenoising) {
EXPECT_FALSE(vie_.GetCaptureDenoising(capture_id)); EXPECT_FALSE(vie_.GetCaptureDenoising(capture_id));
} }
TEST_F(WebRtcVideoEngineTestFake, MultipleSendStreamsWithOneCapturer) { // Test disabled because it drops frames when adapt-before-effects is turned
// off (turned off because it was exposing a crash - see bug 12250150). This is
// safe for now because this test exercises an unused feature.
// TODO(tpsiaki) reenable once adapt-before-effects is turned back on.
TEST_F(WebRtcVideoEngineTestFake, DISABLED_MultipleSendStreamsWithOneCapturer) {
EXPECT_TRUE(SetupEngine()); EXPECT_TRUE(SetupEngine());
// Start the capturer // Start the capturer

View File

@@ -1655,7 +1655,6 @@ WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel(WebRtcVoiceEngine *engine)
engine, engine,
engine->CreateMediaVoiceChannel()), engine->CreateMediaVoiceChannel()),
send_bw_setting_(false), send_bw_setting_(false),
send_autobw_(false),
send_bw_bps_(0), send_bw_bps_(0),
options_(), options_(),
dtmf_allowed_(false), dtmf_allowed_(false),
@@ -2023,7 +2022,7 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
send_codec_.reset(new webrtc::CodecInst(send_codec)); send_codec_.reset(new webrtc::CodecInst(send_codec));
if (send_bw_setting_) { if (send_bw_setting_) {
SetSendBandwidthInternal(send_autobw_, send_bw_bps_); SetSendBandwidthInternal(send_bw_bps_);
} }
return true; return true;
@@ -2928,18 +2927,23 @@ bool WebRtcVoiceMediaChannel::MuteStream(uint32 ssrc, bool muted) {
return true; return true;
} }
bool WebRtcVoiceMediaChannel::SetSendBandwidth(bool autobw, int bps) { bool WebRtcVoiceMediaChannel::SetStartSendBandwidth(int bps) {
LOG(LS_INFO) << "WebRtcVoiceMediaChanne::SetSendBandwidth."; // TODO(andresp): Add support for setting an independent start bandwidth when
// bandwidth estimation is enabled for voice engine.
send_bw_setting_ = true; return false;
send_autobw_ = autobw;
send_bw_bps_ = bps;
return SetSendBandwidthInternal(send_autobw_, send_bw_bps_);
} }
bool WebRtcVoiceMediaChannel::SetSendBandwidthInternal(bool autobw, int bps) { bool WebRtcVoiceMediaChannel::SetMaxSendBandwidth(int bps) {
LOG(LS_INFO) << "WebRtcVoiceMediaChanne::SetSendBandwidthInternal."; LOG(LS_INFO) << "WebRtcVoiceMediaChanne::SetSendBandwidth.";
return SetSendBandwidthInternal(bps);
}
bool WebRtcVoiceMediaChannel::SetSendBandwidthInternal(int bps) {
LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetSendBandwidthInternal.";
send_bw_setting_ = true;
send_bw_bps_ = bps;
if (!send_codec_) { if (!send_codec_) {
LOG(LS_INFO) << "The send codec has not been set up yet. " LOG(LS_INFO) << "The send codec has not been set up yet. "
@@ -2948,7 +2952,9 @@ bool WebRtcVoiceMediaChannel::SetSendBandwidthInternal(bool autobw, int bps) {
} }
// Bandwidth is auto by default. // Bandwidth is auto by default.
if (autobw || bps <= 0) // TODO(bemasc): Fix this so that if SetMaxSendBandwidth(50) is followed by
// SetMaxSendBandwith(0), the second call removes the previous limit.
if (bps <= 0)
return true; return true;
webrtc::CodecInst codec = *send_codec_; webrtc::CodecInst codec = *send_codec_;

View File

@@ -365,7 +365,8 @@ class WebRtcVoiceMediaChannel
const talk_base::PacketTime& packet_time); const talk_base::PacketTime& packet_time);
virtual void OnReadyToSend(bool ready) {} virtual void OnReadyToSend(bool ready) {}
virtual bool MuteStream(uint32 ssrc, bool on); virtual bool MuteStream(uint32 ssrc, bool on);
virtual bool SetSendBandwidth(bool autobw, int bps); virtual bool SetStartSendBandwidth(int bps);
virtual bool SetMaxSendBandwidth(int bps);
virtual bool GetStats(VoiceMediaInfo* info); virtual bool GetStats(VoiceMediaInfo* info);
// Gets last reported error from WebRtc voice engine. This should be only // Gets last reported error from WebRtc voice engine. This should be only
// called in response a failure. // called in response a failure.
@@ -411,7 +412,7 @@ class WebRtcVoiceMediaChannel
return channel_id == voe_channel(); return channel_id == voe_channel();
} }
bool SetSendCodecs(int channel, const std::vector<AudioCodec>& codecs); bool SetSendCodecs(int channel, const std::vector<AudioCodec>& codecs);
bool SetSendBandwidthInternal(bool autobw, int bps); bool SetSendBandwidthInternal(int bps);
talk_base::scoped_ptr<WebRtcSoundclipStream> ringback_tone_; talk_base::scoped_ptr<WebRtcSoundclipStream> ringback_tone_;
std::set<int> ringback_channels_; // channels playing ringback std::set<int> ringback_channels_; // channels playing ringback
@@ -419,7 +420,6 @@ class WebRtcVoiceMediaChannel
std::vector<AudioCodec> send_codecs_; std::vector<AudioCodec> send_codecs_;
talk_base::scoped_ptr<webrtc::CodecInst> send_codec_; talk_base::scoped_ptr<webrtc::CodecInst> send_codec_;
bool send_bw_setting_; bool send_bw_setting_;
bool send_autobw_;
int send_bw_bps_; int send_bw_bps_;
AudioOptions options_; AudioOptions options_;
bool dtmf_allowed_; bool dtmf_allowed_;

View File

@@ -201,39 +201,26 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
// Test that send bandwidth is set correctly. // Test that send bandwidth is set correctly.
// |codec| is the codec under test. // |codec| is the codec under test.
// |default_bitrate| is the default bitrate for the codec. // |max_bitrate| is a parameter to set to SetMaxSendBandwidth().
// |auto_bitrate| is a parameter to set to SetSendBandwidth(). // |expected_result| is the expected result from SetMaxSendBandwidth().
// |desired_bitrate| is a parameter to set to SetSendBandwidth(). // |expected_bitrate| is the expected audio bitrate afterward.
// |expected_result| is expected results from SetSendBandwidth().
void TestSendBandwidth(const cricket::AudioCodec& codec, void TestSendBandwidth(const cricket::AudioCodec& codec,
int default_bitrate, int max_bitrate,
bool auto_bitrate, bool expected_result,
int desired_bitrate, int expected_bitrate) {
bool expected_result) {
int channel_num = voe_.GetLastChannel(); int channel_num = voe_.GetLastChannel();
std::vector<cricket::AudioCodec> codecs; std::vector<cricket::AudioCodec> codecs;
codecs.push_back(codec); codecs.push_back(codec);
EXPECT_TRUE(channel_->SetSendCodecs(codecs)); EXPECT_TRUE(channel_->SetSendCodecs(codecs));
bool result = channel_->SetSendBandwidth(auto_bitrate, desired_bitrate); bool result = channel_->SetMaxSendBandwidth(max_bitrate);
EXPECT_EQ(expected_result, result); EXPECT_EQ(expected_result, result);
webrtc::CodecInst temp_codec; webrtc::CodecInst temp_codec;
EXPECT_FALSE(voe_.GetSendCodec(channel_num, temp_codec)); EXPECT_FALSE(voe_.GetSendCodec(channel_num, temp_codec));
if (result) { EXPECT_EQ(expected_bitrate, temp_codec.rate);
// If SetSendBandwidth() returns true then bitrate is set correctly.
if (auto_bitrate) {
EXPECT_EQ(default_bitrate, temp_codec.rate);
} else {
EXPECT_EQ(desired_bitrate, temp_codec.rate);
}
} else {
// If SetSendBandwidth() returns false then bitrate is set to the
// default value.
EXPECT_EQ(default_bitrate, temp_codec.rate);
}
} }
@@ -575,47 +562,67 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendBandwidthAuto) {
EXPECT_TRUE(SetupEngine()); EXPECT_TRUE(SetupEngine());
EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs())); EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs()));
// Test that when autobw is true, bitrate is kept as the default // Test that when autobw is enabled, bitrate is kept as the default
// value. autobw is true for the following tests. // value. autobw is enabled for the following tests because the target
// bitrate is <= 0.
// ISAC, default bitrate == 32000. // ISAC, default bitrate == 32000.
TestSendBandwidth(kIsacCodec, 32000, true, 96000, true); TestSendBandwidth(kIsacCodec, 0, true, 32000);
// PCMU, default bitrate == 64000. // PCMU, default bitrate == 64000.
TestSendBandwidth(kPcmuCodec, 64000, true, 96000, true); TestSendBandwidth(kPcmuCodec, -1, true, 64000);
// CELT, default bitrate == 64000. // CELT, default bitrate == 64000.
TestSendBandwidth(kCeltCodec, 64000, true, 96000, true); TestSendBandwidth(kCeltCodec, 0, true, 64000);
// opus, default bitrate == 64000. // opus, default bitrate == 64000.
TestSendBandwidth(kOpusCodec, 64000, true, 96000, true); TestSendBandwidth(kOpusCodec, -1, true, 64000);
} }
TEST_F(WebRtcVoiceEngineTestFake, SetSendBandwidthFixedMultiRateAsCaller) { TEST_F(WebRtcVoiceEngineTestFake, SetMaxSendBandwidthMultiRateAsCaller) {
EXPECT_TRUE(SetupEngine()); EXPECT_TRUE(SetupEngine());
EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs())); EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs()));
// Test that we can set bitrate if a multi-rate codec is used. // Test that the bitrate of a multi-rate codec is always the maximum.
// autobw is false for the following tests.
// ISAC, default bitrate == 32000. // ISAC, default bitrate == 32000.
TestSendBandwidth(kIsacCodec, 32000, false, 128000, true); TestSendBandwidth(kIsacCodec, 128000, true, 128000);
TestSendBandwidth(kIsacCodec, 16000, true, 16000);
// CELT, default bitrate == 64000. // CELT, default bitrate == 64000.
TestSendBandwidth(kCeltCodec, 64000, false, 96000, true); TestSendBandwidth(kCeltCodec, 96000, true, 96000);
TestSendBandwidth(kCeltCodec, 32000, true, 32000);
// opus, default bitrate == 64000. // opus, default bitrate == 64000.
TestSendBandwidth(kOpusCodec, 64000, false, 96000, true); TestSendBandwidth(kOpusCodec, 96000, true, 96000);
TestSendBandwidth(kOpusCodec, 48000, true, 48000);
} }
TEST_F(WebRtcVoiceEngineTestFake, SetSendBandwidthFixedMultiRateAsCallee) { TEST_F(WebRtcVoiceEngineTestFake, SetMaxSendBandwidthFixedRateAsCaller) {
EXPECT_TRUE(SetupEngine());
EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs()));
// Test that we can only set a maximum bitrate for a fixed-rate codec
// if it's bigger than the fixed rate.
// PCMU, fixed bitrate == 64000.
TestSendBandwidth(kPcmuCodec, 0, true, 64000);
TestSendBandwidth(kPcmuCodec, 1, false, 64000);
TestSendBandwidth(kPcmuCodec, 128000, true, 64000);
TestSendBandwidth(kPcmuCodec, 32000, false, 64000);
TestSendBandwidth(kPcmuCodec, 64000, true, 64000);
TestSendBandwidth(kPcmuCodec, 63999, false, 64000);
TestSendBandwidth(kPcmuCodec, 64001, true, 64000);
}
TEST_F(WebRtcVoiceEngineTestFake, SetMaxSendBandwidthMultiRateAsCallee) {
EXPECT_TRUE(engine_.Init(talk_base::Thread::Current())); EXPECT_TRUE(engine_.Init(talk_base::Thread::Current()));
channel_ = engine_.CreateChannel(); channel_ = engine_.CreateChannel();
EXPECT_TRUE(channel_ != NULL); EXPECT_TRUE(channel_ != NULL);
EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs())); EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs()));
int desired_bitrate = 128000; int desired_bitrate = 128000;
EXPECT_TRUE(channel_->SetSendBandwidth(false, desired_bitrate)); EXPECT_TRUE(channel_->SetMaxSendBandwidth(desired_bitrate));
EXPECT_TRUE(channel_->AddSendStream( EXPECT_TRUE(channel_->AddSendStream(
cricket::StreamParams::CreateLegacy(kSsrc1))); cricket::StreamParams::CreateLegacy(kSsrc1)));
@@ -629,7 +636,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendBandwidthFixedMultiRateAsCallee) {
// Test that bitrate cannot be set for CBR codecs. // Test that bitrate cannot be set for CBR codecs.
// Bitrate is ignored if it is higher than the fixed bitrate. // Bitrate is ignored if it is higher than the fixed bitrate.
// Bitrate less then the fixed bitrate is an error. // Bitrate less then the fixed bitrate is an error.
TEST_F(WebRtcVoiceEngineTestFake, SetSendBandwidthFixedCbr) { TEST_F(WebRtcVoiceEngineTestFake, SetMaxSendBandwidthCbr) {
EXPECT_TRUE(SetupEngine()); EXPECT_TRUE(SetupEngine());
EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs())); EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs()));
@@ -642,10 +649,10 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendBandwidthFixedCbr) {
EXPECT_TRUE(channel_->SetSendCodecs(codecs)); EXPECT_TRUE(channel_->SetSendCodecs(codecs));
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, codec)); EXPECT_EQ(0, voe_.GetSendCodec(channel_num, codec));
EXPECT_EQ(64000, codec.rate); EXPECT_EQ(64000, codec.rate);
EXPECT_TRUE(channel_->SetSendBandwidth(false, 128000)); EXPECT_TRUE(channel_->SetMaxSendBandwidth(128000));
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, codec)); EXPECT_EQ(0, voe_.GetSendCodec(channel_num, codec));
EXPECT_EQ(64000, codec.rate); EXPECT_EQ(64000, codec.rate);
EXPECT_FALSE(channel_->SetSendBandwidth(false, 128)); EXPECT_FALSE(channel_->SetMaxSendBandwidth(128));
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, codec)); EXPECT_EQ(0, voe_.GetSendCodec(channel_num, codec));
EXPECT_EQ(64000, codec.rate); EXPECT_EQ(64000, codec.rate);
} }

View File

@@ -66,8 +66,8 @@ class DtlsTransport : public Base {
return true; return true;
} }
virtual bool ApplyLocalTransportDescription_w(TransportChannelImpl* virtual bool ApplyLocalTransportDescription_w(TransportChannelImpl* channel,
channel) { std::string* error_desc) {
talk_base::SSLFingerprint* local_fp = talk_base::SSLFingerprint* local_fp =
Base::local_description()->identity_fingerprint.get(); Base::local_description()->identity_fingerprint.get();
@@ -79,30 +79,36 @@ class DtlsTransport : public Base {
identity_)); identity_));
ASSERT(local_fp_tmp.get() != NULL); ASSERT(local_fp_tmp.get() != NULL);
if (!(*local_fp_tmp == *local_fp)) { if (!(*local_fp_tmp == *local_fp)) {
LOG(LS_WARNING) << "Local fingerprint does not match identity"; std::ostringstream desc;
return false; desc << "Local fingerprint does not match identity. Expected: ";
desc << local_fp_tmp->ToString();
desc << " Got: " << local_fp->ToString();
return BadTransportDescription(desc.str(), error_desc);
} }
} else { } else {
LOG(LS_WARNING) return BadTransportDescription(
<< "Local fingerprint provided but no identity available"; "Local fingerprint provided but no identity available.",
return false; error_desc);
} }
} else { } else {
identity_ = NULL; identity_ = NULL;
} }
if (!channel->SetLocalIdentity(identity_)) if (!channel->SetLocalIdentity(identity_)) {
return false; return BadTransportDescription("Failed to set local identity.",
error_desc);
// Apply the description in the base class.
return Base::ApplyLocalTransportDescription_w(channel);
} }
virtual bool NegotiateTransportDescription_w(ContentAction local_role) { // Apply the description in the base class.
return Base::ApplyLocalTransportDescription_w(channel, error_desc);
}
virtual bool NegotiateTransportDescription_w(ContentAction local_role,
std::string* error_desc) {
if (!Base::local_description() || !Base::remote_description()) { if (!Base::local_description() || !Base::remote_description()) {
LOG(LS_INFO) << "Local and Remote description must be set before " const std::string msg = "Local and Remote description must be set before "
<< "transport descriptions are negotiated"; "transport descriptions are negotiated";
return false; return BadTransportDescription(msg, error_desc);
} }
talk_base::SSLFingerprint* local_fp = talk_base::SSLFingerprint* local_fp =
@@ -144,8 +150,9 @@ class DtlsTransport : public Base {
bool is_remote_server = false; bool is_remote_server = false;
if (local_role == CA_OFFER) { if (local_role == CA_OFFER) {
if (local_connection_role != CONNECTIONROLE_ACTPASS) { if (local_connection_role != CONNECTIONROLE_ACTPASS) {
LOG(LS_ERROR) << "Offerer must use actpass value for setup attribute"; return BadTransportDescription(
return false; "Offerer must use actpass value for setup attribute.",
error_desc);
} }
if (remote_connection_role == CONNECTIONROLE_ACTIVE || if (remote_connection_role == CONNECTIONROLE_ACTIVE ||
@@ -153,25 +160,28 @@ class DtlsTransport : public Base {
remote_connection_role == CONNECTIONROLE_NONE) { remote_connection_role == CONNECTIONROLE_NONE) {
is_remote_server = (remote_connection_role == CONNECTIONROLE_PASSIVE); is_remote_server = (remote_connection_role == CONNECTIONROLE_PASSIVE);
} else { } else {
LOG(LS_ERROR) << "Answerer must use either active or passive value " const std::string msg =
<< "for setup attribute"; "Answerer must use either active or passive value "
return false; "for setup attribute.";
return BadTransportDescription(msg, error_desc);
} }
// If remote is NONE or ACTIVE it will act as client. // If remote is NONE or ACTIVE it will act as client.
} else { } else {
if (remote_connection_role != CONNECTIONROLE_ACTPASS && if (remote_connection_role != CONNECTIONROLE_ACTPASS &&
remote_connection_role != CONNECTIONROLE_NONE) { remote_connection_role != CONNECTIONROLE_NONE) {
LOG(LS_ERROR) << "Offerer must use actpass value for setup attribute"; return BadTransportDescription(
return false; "Offerer must use actpass value for setup attribute.",
error_desc);
} }
if (local_connection_role == CONNECTIONROLE_ACTIVE || if (local_connection_role == CONNECTIONROLE_ACTIVE ||
local_connection_role == CONNECTIONROLE_PASSIVE) { local_connection_role == CONNECTIONROLE_PASSIVE) {
is_remote_server = (local_connection_role == CONNECTIONROLE_ACTIVE); is_remote_server = (local_connection_role == CONNECTIONROLE_ACTIVE);
} else { } else {
LOG(LS_ERROR) << "Answerer must use either active or passive value " const std::string msg =
<< "for setup attribute"; "Answerer must use either active or passive value "
return false; "for setup attribute.";
return BadTransportDescription(msg, error_desc);
} }
// If local is passive, local will act as server. // If local is passive, local will act as server.
@@ -181,9 +191,9 @@ class DtlsTransport : public Base {
talk_base::SSL_SERVER; talk_base::SSL_SERVER;
} else if (local_fp && (local_role == CA_ANSWER)) { } else if (local_fp && (local_role == CA_ANSWER)) {
LOG(LS_ERROR) return BadTransportDescription(
<< "Local fingerprint supplied when caller didn't offer DTLS"; "Local fingerprint supplied when caller didn't offer DTLS.",
return false; error_desc);
} else { } else {
// We are not doing DTLS // We are not doing DTLS
remote_fingerprint_.reset(new talk_base::SSLFingerprint( remote_fingerprint_.reset(new talk_base::SSLFingerprint(
@@ -191,7 +201,7 @@ class DtlsTransport : public Base {
} }
// Now run the negotiation for the base class. // Now run the negotiation for the base class.
return Base::NegotiateTransportDescription_w(local_role); return Base::NegotiateTransportDescription_w(local_role, error_desc);
} }
virtual DtlsTransportChannelWrapper* CreateTransportChannel(int component) { virtual DtlsTransportChannelWrapper* CreateTransportChannel(int component) {
@@ -216,12 +226,13 @@ class DtlsTransport : public Base {
private: private:
virtual bool ApplyNegotiatedTransportDescription_w( virtual bool ApplyNegotiatedTransportDescription_w(
TransportChannelImpl* channel) { TransportChannelImpl* channel,
std::string* error_desc) {
// Set ssl role. Role must be set before fingerprint is applied, which // Set ssl role. Role must be set before fingerprint is applied, which
// initiates DTLS setup. // initiates DTLS setup.
if (!channel->SetSslRole(secure_role_)) { if (!channel->SetSslRole(secure_role_)) {
LOG(LS_INFO) << "Failed to set ssl role for the channel."; return BadTransportDescription("Failed to set ssl role for the channel.",
return false; error_desc);
} }
// Apply remote fingerprint. // Apply remote fingerprint.
if (!channel->SetRemoteFingerprint( if (!channel->SetRemoteFingerprint(
@@ -229,9 +240,10 @@ class DtlsTransport : public Base {
reinterpret_cast<const uint8 *>(remote_fingerprint_-> reinterpret_cast<const uint8 *>(remote_fingerprint_->
digest.data()), digest.data()),
remote_fingerprint_->digest.length())) { remote_fingerprint_->digest.length())) {
return false; return BadTransportDescription("Failed to apply remote fingerprint.",
error_desc);
} }
return Base::ApplyNegotiatedTransportDescription_w(channel); return Base::ApplyNegotiatedTransportDescription_w(channel, error_desc);
} }
talk_base::SSLIdentity* identity_; talk_base::SSLIdentity* identity_;

View File

@@ -185,14 +185,14 @@ class DtlsTestClient : public sigslot::has_slots<> {
// content action is CA_ANSWER. // content action is CA_ANSWER.
if (action == cricket::CA_OFFER) { if (action == cricket::CA_OFFER) {
ASSERT_TRUE(transport_->SetLocalTransportDescription( ASSERT_TRUE(transport_->SetLocalTransportDescription(
local_desc, cricket::CA_OFFER)); local_desc, cricket::CA_OFFER, NULL));
ASSERT_EQ(expect_success, transport_->SetRemoteTransportDescription( ASSERT_EQ(expect_success, transport_->SetRemoteTransportDescription(
remote_desc, cricket::CA_ANSWER)); remote_desc, cricket::CA_ANSWER, NULL));
} else { } else {
ASSERT_TRUE(transport_->SetRemoteTransportDescription( ASSERT_TRUE(transport_->SetRemoteTransportDescription(
remote_desc, cricket::CA_OFFER)); remote_desc, cricket::CA_OFFER, NULL));
ASSERT_EQ(expect_success, transport_->SetLocalTransportDescription( ASSERT_EQ(expect_success, transport_->SetLocalTransportDescription(
local_desc, cricket::CA_ANSWER)); local_desc, cricket::CA_ANSWER, NULL));
} }
negotiated_dtls_ = (local_identity && remote_identity); negotiated_dtls_ = (local_identity && remote_identity);
} }

View File

@@ -277,21 +277,29 @@ void TransportProxy::SetIceRole(IceRole role) {
} }
bool TransportProxy::SetLocalTransportDescription( bool TransportProxy::SetLocalTransportDescription(
const TransportDescription& description, ContentAction action) { const TransportDescription& description,
ContentAction action,
std::string* error_desc) {
// If this is an answer, finalize the negotiation. // If this is an answer, finalize the negotiation.
if (action == CA_ANSWER) { if (action == CA_ANSWER) {
CompleteNegotiation(); CompleteNegotiation();
} }
return transport_->get()->SetLocalTransportDescription(description, action); return transport_->get()->SetLocalTransportDescription(description,
action,
error_desc);
} }
bool TransportProxy::SetRemoteTransportDescription( bool TransportProxy::SetRemoteTransportDescription(
const TransportDescription& description, ContentAction action) { const TransportDescription& description,
ContentAction action,
std::string* error_desc) {
// If this is an answer, finalize the negotiation. // If this is an answer, finalize the negotiation.
if (action == CA_ANSWER) { if (action == CA_ANSWER) {
CompleteNegotiation(); CompleteNegotiation();
} }
return transport_->get()->SetRemoteTransportDescription(description, action); return transport_->get()->SetRemoteTransportDescription(description,
action,
error_desc);
} }
void TransportProxy::OnSignalingReady() { void TransportProxy::OnSignalingReady() {
@@ -418,16 +426,22 @@ bool BaseSession::SetIdentity(talk_base::SSLIdentity* identity) {
} }
bool BaseSession::PushdownTransportDescription(ContentSource source, bool BaseSession::PushdownTransportDescription(ContentSource source,
ContentAction action) { ContentAction action,
std::string* error_desc) {
if (source == CS_LOCAL) { if (source == CS_LOCAL) {
return PushdownLocalTransportDescription(local_description_, action); return PushdownLocalTransportDescription(local_description_,
action,
error_desc);
} }
return PushdownRemoteTransportDescription(remote_description_, action); return PushdownRemoteTransportDescription(remote_description_,
action,
error_desc);
} }
bool BaseSession::PushdownLocalTransportDescription( bool BaseSession::PushdownLocalTransportDescription(
const SessionDescription* sdesc, const SessionDescription* sdesc,
ContentAction action) { ContentAction action,
std::string* error_desc) {
// Update the Transports with the right information, and trigger them to // Update the Transports with the right information, and trigger them to
// start connecting. // start connecting.
for (TransportMap::iterator iter = transports_.begin(); for (TransportMap::iterator iter = transports_.begin();
@@ -438,7 +452,8 @@ bool BaseSession::PushdownLocalTransportDescription(
bool ret = GetTransportDescription( bool ret = GetTransportDescription(
sdesc, iter->second->content_name(), &tdesc); sdesc, iter->second->content_name(), &tdesc);
if (ret) { if (ret) {
if (!iter->second->SetLocalTransportDescription(tdesc, action)) { if (!iter->second->SetLocalTransportDescription(tdesc, action,
error_desc)) {
return false; return false;
} }
@@ -451,7 +466,8 @@ bool BaseSession::PushdownLocalTransportDescription(
bool BaseSession::PushdownRemoteTransportDescription( bool BaseSession::PushdownRemoteTransportDescription(
const SessionDescription* sdesc, const SessionDescription* sdesc,
ContentAction action) { ContentAction action,
std::string* error_desc) {
// Update the Transports with the right information. // Update the Transports with the right information.
for (TransportMap::iterator iter = transports_.begin(); for (TransportMap::iterator iter = transports_.begin();
iter != transports_.end(); ++iter) { iter != transports_.end(); ++iter) {
@@ -462,7 +478,8 @@ bool BaseSession::PushdownRemoteTransportDescription(
bool ret = GetTransportDescription( bool ret = GetTransportDescription(
sdesc, iter->second->content_name(), &tdesc); sdesc, iter->second->content_name(), &tdesc);
if (ret) { if (ret) {
if (!iter->second->SetRemoteTransportDescription(tdesc, action)) { if (!iter->second->SetRemoteTransportDescription(tdesc, action,
error_desc)) {
return false; return false;
} }
} }
@@ -611,10 +628,11 @@ void BaseSession::SetState(State state) {
SignalNewDescription(); SignalNewDescription();
} }
void BaseSession::SetError(Error error) { void BaseSession::SetError(Error error, const std::string& error_desc) {
ASSERT(signaling_thread_->IsCurrent()); ASSERT(signaling_thread_->IsCurrent());
if (error != error_) { if (error != error_) {
error_ = error; error_ = error;
error_desc_ = error_desc;
SignalError(this, error); SignalError(this, error);
} }
} }
@@ -856,7 +874,7 @@ void BaseSession::OnMessage(talk_base::Message *pmsg) {
switch (pmsg->message_id) { switch (pmsg->message_id) {
case MSG_TIMEOUT: case MSG_TIMEOUT:
// Session timeout has occured. // Session timeout has occured.
SetError(ERROR_TIME); SetError(ERROR_TIME, "Session timeout has occured.");
break; break;
case MSG_STATE: case MSG_STATE:
@@ -925,7 +943,7 @@ bool Session::Initiate(const std::string &to,
// the TransportDescriptions. // the TransportDescriptions.
SpeculativelyConnectAllTransportChannels(); SpeculativelyConnectAllTransportChannels();
PushdownTransportDescription(CS_LOCAL, CA_OFFER); PushdownTransportDescription(CS_LOCAL, CA_OFFER, NULL);
SetState(Session::STATE_SENTINITIATE); SetState(Session::STATE_SENTINITIATE);
return true; return true;
} }
@@ -946,7 +964,7 @@ bool Session::Accept(const SessionDescription* sdesc) {
return false; return false;
} }
// TODO(juberti): Add BUNDLE support to transport-info messages. // TODO(juberti): Add BUNDLE support to transport-info messages.
PushdownTransportDescription(CS_LOCAL, CA_ANSWER); PushdownTransportDescription(CS_LOCAL, CA_ANSWER, NULL);
MaybeEnableMuxingSupport(); // Enable transport channel mux if supported. MaybeEnableMuxingSupport(); // Enable transport channel mux if supported.
SetState(Session::STATE_SENTACCEPT); SetState(Session::STATE_SENTACCEPT);
return true; return true;
@@ -1261,8 +1279,10 @@ void Session::OnFailedSend(const buzz::XmlElement* orig_stanza,
if (!OnRedirectError(redirect, &error)) { if (!OnRedirectError(redirect, &error)) {
// TODO: Should we send a message back? The standard // TODO: Should we send a message back? The standard
// says nothing about it. // says nothing about it.
LOG(LS_ERROR) << "Failed to redirect: " << error.text; std::ostringstream desc;
SetError(ERROR_RESPONSE); desc << "Failed to redirect: " << error.text;
LOG(LS_ERROR) << desc.str();
SetError(ERROR_RESPONSE, desc.str());
} }
return; return;
} }
@@ -1290,7 +1310,7 @@ void Session::OnFailedSend(const buzz::XmlElement* orig_stanza,
} else if ((error_type != "continue") && (error_type != "wait")) { } else if ((error_type != "continue") && (error_type != "wait")) {
// We do not set an error if the other side said it is okay to continue // We do not set an error if the other side said it is okay to continue
// (possibly after waiting). These errors can be ignored. // (possibly after waiting). These errors can be ignored.
SetError(ERROR_RESPONSE); SetError(ERROR_RESPONSE, "");
} }
} }
@@ -1318,7 +1338,7 @@ bool Session::OnInitiateMessage(const SessionMessage& msg,
init.transports, init.transports,
init.groups)); init.groups));
// Updating transport with TransportDescription. // Updating transport with TransportDescription.
PushdownTransportDescription(CS_REMOTE, CA_OFFER); PushdownTransportDescription(CS_REMOTE, CA_OFFER, NULL);
SetState(STATE_RECEIVEDINITIATE); SetState(STATE_RECEIVEDINITIATE);
// Users of Session may listen to state change and call Reject(). // Users of Session may listen to state change and call Reject().
@@ -1352,7 +1372,7 @@ bool Session::OnAcceptMessage(const SessionMessage& msg, MessageError* error) {
accept.transports, accept.transports,
accept.groups)); accept.groups));
// Updating transport with TransportDescription. // Updating transport with TransportDescription.
PushdownTransportDescription(CS_REMOTE, CA_ANSWER); PushdownTransportDescription(CS_REMOTE, CA_ANSWER, NULL);
MaybeEnableMuxingSupport(); // Enable transport channel mux if supported. MaybeEnableMuxingSupport(); // Enable transport channel mux if supported.
SetState(STATE_RECEIVEDACCEPT); SetState(STATE_RECEIVEDACCEPT);
@@ -1496,8 +1516,8 @@ bool Session::CheckState(State expected, MessageError* error) {
return true; return true;
} }
void Session::SetError(Error error) { void Session::SetError(Error error, const std::string& error_desc) {
BaseSession::SetError(error); BaseSession::SetError(error, error_desc);
if (error != ERROR_NONE) if (error != ERROR_NONE)
signaling_thread()->Post(this, MSG_ERROR); signaling_thread()->Post(this, MSG_ERROR);
} }

View File

@@ -145,9 +145,11 @@ class TransportProxy : public sigslot::has_slots<>,
void SetIceRole(IceRole role); void SetIceRole(IceRole role);
void SetIdentity(talk_base::SSLIdentity* identity); void SetIdentity(talk_base::SSLIdentity* identity);
bool SetLocalTransportDescription(const TransportDescription& description, bool SetLocalTransportDescription(const TransportDescription& description,
ContentAction action); ContentAction action,
std::string* error_desc);
bool SetRemoteTransportDescription(const TransportDescription& description, bool SetRemoteTransportDescription(const TransportDescription& description,
ContentAction action); ContentAction action,
std::string* error_desc);
void OnSignalingReady(); void OnSignalingReady();
bool OnRemoteCandidates(const Candidates& candidates, std::string* error); bool OnRemoteCandidates(const Candidates& candidates, std::string* error);
@@ -327,13 +329,15 @@ class BaseSession : public sigslot::has_slots<>,
// Returns the last error in the session. See the enum above for details. // Returns the last error in the session. See the enum above for details.
// Each time the an error occurs, we will fire this signal. // Each time the an error occurs, we will fire this signal.
Error error() const { return error_; } Error error() const { return error_; }
const std::string& error_desc() const { return error_desc_; }
sigslot::signal2<BaseSession* , Error> SignalError; sigslot::signal2<BaseSession* , Error> SignalError;
// Updates the state, signaling if necessary. // Updates the state, signaling if necessary.
virtual void SetState(State state); virtual void SetState(State state);
// Updates the error state, signaling if necessary. // Updates the error state, signaling if necessary.
virtual void SetError(Error error); // TODO(ronghuawu): remove the SetError method that doesn't take |error_desc|.
virtual void SetError(Error error, const std::string& error_desc);
// Fired when the remote description is updated, with the updated // Fired when the remote description is updated, with the updated
// contents. // contents.
@@ -384,7 +388,8 @@ class BaseSession : public sigslot::has_slots<>,
bool SetIdentity(talk_base::SSLIdentity* identity); bool SetIdentity(talk_base::SSLIdentity* identity);
bool PushdownTransportDescription(ContentSource source, bool PushdownTransportDescription(ContentSource source,
ContentAction action); ContentAction action,
std::string* error_desc);
void set_initiator(bool initiator) { initiator_ = initiator; } void set_initiator(bool initiator) { initiator_ = initiator; }
const TransportMap& transport_proxies() const { return transports_; } const TransportMap& transport_proxies() const { return transports_; }
@@ -466,13 +471,16 @@ class BaseSession : public sigslot::has_slots<>,
protected: protected:
State state_; State state_;
Error error_; Error error_;
std::string error_desc_;
private: private:
// Helper methods to push local and remote transport descriptions. // Helper methods to push local and remote transport descriptions.
bool PushdownLocalTransportDescription( bool PushdownLocalTransportDescription(
const SessionDescription* sdesc, ContentAction action); const SessionDescription* sdesc, ContentAction action,
std::string* error_desc);
bool PushdownRemoteTransportDescription( bool PushdownRemoteTransportDescription(
const SessionDescription* sdesc, ContentAction action); const SessionDescription* sdesc, ContentAction action,
std::string* error_desc);
bool IsCandidateAllocationDone() const; bool IsCandidateAllocationDone() const;
void MaybeCandidateAllocationDone(); void MaybeCandidateAllocationDone();
@@ -553,7 +561,7 @@ class Session : public BaseSession {
} }
// Updates the error state, signaling if necessary. // Updates the error state, signaling if necessary.
virtual void SetError(Error error); virtual void SetError(Error error, const std::string& error_desc);
// When the session needs to send signaling messages, it beings by requesting // When the session needs to send signaling messages, it beings by requesting
// signaling. The client should handle this by calling OnSignalingReady once // signaling. The client should handle this by calling OnSignalingReady once

View File

@@ -73,6 +73,33 @@ struct ChannelParams : public talk_base::MessageData {
Candidate* candidate; Candidate* candidate;
}; };
static std::string IceProtoToString(TransportProtocol proto) {
std::string proto_str;
switch (proto) {
case ICEPROTO_GOOGLE:
proto_str = "gice";
break;
case ICEPROTO_HYBRID:
proto_str = "hybrid";
break;
case ICEPROTO_RFC5245:
proto_str = "ice";
break;
default:
ASSERT(false);
break;
}
return proto_str;
}
bool BadTransportDescription(const std::string& desc, std::string* err_desc) {
if (err_desc) {
*err_desc = desc;
}
LOG(LS_ERROR) << desc;
return false;
}
Transport::Transport(talk_base::Thread* signaling_thread, Transport::Transport(talk_base::Thread* signaling_thread,
talk_base::Thread* worker_thread, talk_base::Thread* worker_thread,
const std::string& content_name, const std::string& content_name,
@@ -131,15 +158,21 @@ bool Transport::GetRemoteCertificate_w(talk_base::SSLCertificate** cert) {
} }
bool Transport::SetLocalTransportDescription( bool Transport::SetLocalTransportDescription(
const TransportDescription& description, ContentAction action) { const TransportDescription& description,
ContentAction action,
std::string* error_desc) {
return worker_thread_->Invoke<bool>(Bind( return worker_thread_->Invoke<bool>(Bind(
&Transport::SetLocalTransportDescription_w, this, description, action)); &Transport::SetLocalTransportDescription_w, this,
description, action, error_desc));
} }
bool Transport::SetRemoteTransportDescription( bool Transport::SetRemoteTransportDescription(
const TransportDescription& description, ContentAction action) { const TransportDescription& description,
ContentAction action,
std::string* error_desc) {
return worker_thread_->Invoke<bool>(Bind( return worker_thread_->Invoke<bool>(Bind(
&Transport::SetRemoteTransportDescription_w, this, description, action)); &Transport::SetRemoteTransportDescription_w, this,
description, action, error_desc));
} }
TransportChannelImpl* Transport::CreateChannel(int component) { TransportChannelImpl* Transport::CreateChannel(int component) {
@@ -176,10 +209,12 @@ TransportChannelImpl* Transport::CreateChannel_w(int component) {
impl->SetIceRole(ice_role_); impl->SetIceRole(ice_role_);
impl->SetIceTiebreaker(tiebreaker_); impl->SetIceTiebreaker(tiebreaker_);
if (local_description_) { if (local_description_) {
ApplyLocalTransportDescription_w(impl); // TODO(ronghuawu): Change CreateChannel_w to be able to return error since
// below Apply**Description_w calls can fail.
ApplyLocalTransportDescription_w(impl, NULL);
if (remote_description_) { if (remote_description_) {
ApplyRemoteTransportDescription_w(impl); ApplyRemoteTransportDescription_w(impl, NULL);
ApplyNegotiatedTransportDescription_w(impl); ApplyNegotiatedTransportDescription_w(impl, NULL);
} }
} }
@@ -276,7 +311,7 @@ void Transport::ConnectChannels_w() {
talk_base::CreateRandomString(ICE_PWD_LENGTH), talk_base::CreateRandomString(ICE_PWD_LENGTH),
ICEMODE_FULL, CONNECTIONROLE_NONE, NULL, ICEMODE_FULL, CONNECTIONROLE_NONE, NULL,
Candidates()); Candidates());
SetLocalTransportDescription_w(desc, CA_OFFER); SetLocalTransportDescription_w(desc, CA_OFFER, NULL);
} }
CallChannels_w(&TransportChannelImpl::Connect); CallChannels_w(&TransportChannelImpl::Connect);
@@ -606,63 +641,70 @@ void Transport::SetRemoteIceMode_w(IceMode mode) {
} }
bool Transport::SetLocalTransportDescription_w( bool Transport::SetLocalTransportDescription_w(
const TransportDescription& desc, ContentAction action) { const TransportDescription& desc,
ContentAction action,
std::string* error_desc) {
bool ret = true; bool ret = true;
talk_base::CritScope cs(&crit_); talk_base::CritScope cs(&crit_);
local_description_.reset(new TransportDescription(desc)); local_description_.reset(new TransportDescription(desc));
for (ChannelMap::iterator iter = channels_.begin(); for (ChannelMap::iterator iter = channels_.begin();
iter != channels_.end(); ++iter) { iter != channels_.end(); ++iter) {
ret &= ApplyLocalTransportDescription_w(iter->second.get()); ret &= ApplyLocalTransportDescription_w(iter->second.get(), error_desc);
} }
if (!ret) if (!ret)
return false; return false;
// If PRANSWER/ANSWER is set, we should decide transport protocol type. // If PRANSWER/ANSWER is set, we should decide transport protocol type.
if (action == CA_PRANSWER || action == CA_ANSWER) { if (action == CA_PRANSWER || action == CA_ANSWER) {
ret &= NegotiateTransportDescription_w(action); ret &= NegotiateTransportDescription_w(action, error_desc);
} }
return ret; return ret;
} }
bool Transport::SetRemoteTransportDescription_w( bool Transport::SetRemoteTransportDescription_w(
const TransportDescription& desc, ContentAction action) { const TransportDescription& desc,
ContentAction action,
std::string* error_desc) {
bool ret = true; bool ret = true;
talk_base::CritScope cs(&crit_); talk_base::CritScope cs(&crit_);
remote_description_.reset(new TransportDescription(desc)); remote_description_.reset(new TransportDescription(desc));
for (ChannelMap::iterator iter = channels_.begin(); for (ChannelMap::iterator iter = channels_.begin();
iter != channels_.end(); ++iter) { iter != channels_.end(); ++iter) {
ret &= ApplyRemoteTransportDescription_w(iter->second.get()); ret &= ApplyRemoteTransportDescription_w(iter->second.get(), error_desc);
} }
// If PRANSWER/ANSWER is set, we should decide transport protocol type. // If PRANSWER/ANSWER is set, we should decide transport protocol type.
if (action == CA_PRANSWER || action == CA_ANSWER) { if (action == CA_PRANSWER || action == CA_ANSWER) {
ret = NegotiateTransportDescription_w(CA_OFFER); ret = NegotiateTransportDescription_w(CA_OFFER, error_desc);
} }
return ret; return ret;
} }
bool Transport::ApplyLocalTransportDescription_w(TransportChannelImpl* ch) { bool Transport::ApplyLocalTransportDescription_w(TransportChannelImpl* ch,
std::string* error_desc) {
ch->SetIceCredentials(local_description_->ice_ufrag, ch->SetIceCredentials(local_description_->ice_ufrag,
local_description_->ice_pwd); local_description_->ice_pwd);
return true; return true;
} }
bool Transport::ApplyRemoteTransportDescription_w(TransportChannelImpl* ch) { bool Transport::ApplyRemoteTransportDescription_w(TransportChannelImpl* ch,
std::string* error_desc) {
ch->SetRemoteIceCredentials(remote_description_->ice_ufrag, ch->SetRemoteIceCredentials(remote_description_->ice_ufrag,
remote_description_->ice_pwd); remote_description_->ice_pwd);
return true; return true;
} }
bool Transport::ApplyNegotiatedTransportDescription_w( bool Transport::ApplyNegotiatedTransportDescription_w(
TransportChannelImpl* channel) { TransportChannelImpl* channel, std::string* error_desc) {
channel->SetIceProtocolType(protocol_); channel->SetIceProtocolType(protocol_);
channel->SetRemoteIceMode(remote_ice_mode_); channel->SetRemoteIceMode(remote_ice_mode_);
return true; return true;
} }
bool Transport::NegotiateTransportDescription_w(ContentAction local_role) { bool Transport::NegotiateTransportDescription_w(ContentAction local_role,
std::string* error_desc) {
// TODO(ekr@rtfm.com): This is ICE-specific stuff. Refactor into // TODO(ekr@rtfm.com): This is ICE-specific stuff. Refactor into
// P2PTransport. // P2PTransport.
const TransportDescription* offer; const TransportDescription* offer;
@@ -690,7 +732,12 @@ bool Transport::NegotiateTransportDescription_w(ContentAction local_role) {
// answer must be treated as error. // answer must be treated as error.
if ((offer_proto == ICEPROTO_GOOGLE || offer_proto == ICEPROTO_RFC5245) && if ((offer_proto == ICEPROTO_GOOGLE || offer_proto == ICEPROTO_RFC5245) &&
(offer_proto != answer_proto)) { (offer_proto != answer_proto)) {
return false; std::ostringstream desc;
desc << "Offer and answer protocol mismatch: "
<< IceProtoToString(offer_proto)
<< " vs "
<< IceProtoToString(answer_proto);
return BadTransportDescription(desc.str(), error_desc);
} }
protocol_ = answer_proto == ICEPROTO_HYBRID ? ICEPROTO_GOOGLE : answer_proto; protocol_ = answer_proto == ICEPROTO_HYBRID ? ICEPROTO_GOOGLE : answer_proto;
@@ -712,7 +759,7 @@ bool Transport::NegotiateTransportDescription_w(ContentAction local_role) {
for (ChannelMap::iterator iter = channels_.begin(); for (ChannelMap::iterator iter = channels_.begin();
iter != channels_.end(); iter != channels_.end();
++iter) { ++iter) {
if (!ApplyNegotiatedTransportDescription_w(iter->second.get())) if (!ApplyNegotiatedTransportDescription_w(iter->second.get(), error_desc))
return false; return false;
} }
return true; return true;

View File

@@ -187,6 +187,8 @@ struct TransportStats {
TransportChannelStatsList channel_stats; TransportChannelStatsList channel_stats;
}; };
bool BadTransportDescription(const std::string& desc, std::string* err_desc);
class Transport : public talk_base::MessageHandler, class Transport : public talk_base::MessageHandler,
public sigslot::has_slots<> { public sigslot::has_slots<> {
public: public:
@@ -270,11 +272,13 @@ class Transport : public talk_base::MessageHandler,
// Set the local TransportDescription to be used by TransportChannels. // Set the local TransportDescription to be used by TransportChannels.
// This should be called before ConnectChannels(). // This should be called before ConnectChannels().
bool SetLocalTransportDescription(const TransportDescription& description, bool SetLocalTransportDescription(const TransportDescription& description,
ContentAction action); ContentAction action,
std::string* error_desc);
// Set the remote TransportDescription to be used by TransportChannels. // Set the remote TransportDescription to be used by TransportChannels.
bool SetRemoteTransportDescription(const TransportDescription& description, bool SetRemoteTransportDescription(const TransportDescription& description,
ContentAction action); ContentAction action,
std::string* error_desc);
// Tells all current and future channels to start connecting. When the first // Tells all current and future channels to start connecting. When the first
// channel begins connecting, the following signal is raised. // channel begins connecting, the following signal is raised.
@@ -362,25 +366,27 @@ class Transport : public talk_base::MessageHandler,
// Pushes down the transport parameters from the local description, such // Pushes down the transport parameters from the local description, such
// as the ICE ufrag and pwd. // as the ICE ufrag and pwd.
// Derived classes can override, but must call the base as well. // Derived classes can override, but must call the base as well.
virtual bool ApplyLocalTransportDescription_w(TransportChannelImpl* virtual bool ApplyLocalTransportDescription_w(TransportChannelImpl* channel,
channel); std::string* error_desc);
// Pushes down remote ice credentials from the remote description to the // Pushes down remote ice credentials from the remote description to the
// transport channel. // transport channel.
virtual bool ApplyRemoteTransportDescription_w(TransportChannelImpl* ch); virtual bool ApplyRemoteTransportDescription_w(TransportChannelImpl* ch,
std::string* error_desc);
// Negotiates the transport parameters based on the current local and remote // Negotiates the transport parameters based on the current local and remote
// transport description, such at the version of ICE to use, and whether DTLS // transport description, such at the version of ICE to use, and whether DTLS
// should be activated. // should be activated.
// Derived classes can negotiate their specific parameters here, but must call // Derived classes can negotiate their specific parameters here, but must call
// the base as well. // the base as well.
virtual bool NegotiateTransportDescription_w(ContentAction local_role); virtual bool NegotiateTransportDescription_w(ContentAction local_role,
std::string* error_desc);
// Pushes down the transport parameters obtained via negotiation. // Pushes down the transport parameters obtained via negotiation.
// Derived classes can set their specific parameters here, but must call the // Derived classes can set their specific parameters here, but must call the
// base as well. // base as well.
virtual bool ApplyNegotiatedTransportDescription_w( virtual bool ApplyNegotiatedTransportDescription_w(
TransportChannelImpl* channel); TransportChannelImpl* channel, std::string* error_desc);
virtual bool GetSslRole_w(talk_base::SSLRole* ssl_role) const { virtual bool GetSslRole_w(talk_base::SSLRole* ssl_role) const {
return false; return false;
@@ -468,9 +474,11 @@ class Transport : public talk_base::MessageHandler,
void SetIceRole_w(IceRole role); void SetIceRole_w(IceRole role);
void SetRemoteIceMode_w(IceMode mode); void SetRemoteIceMode_w(IceMode mode);
bool SetLocalTransportDescription_w(const TransportDescription& desc, bool SetLocalTransportDescription_w(const TransportDescription& desc,
ContentAction action); ContentAction action,
std::string* error_desc);
bool SetRemoteTransportDescription_w(const TransportDescription& desc, bool SetRemoteTransportDescription_w(const TransportDescription& desc,
ContentAction action); ContentAction action,
std::string* error_desc);
bool GetStats_w(TransportStats* infos); bool GetStats_w(TransportStats* infos);
bool GetRemoteCertificate_w(talk_base::SSLCertificate** cert); bool GetRemoteCertificate_w(talk_base::SSLCertificate** cert);

View File

@@ -147,7 +147,8 @@ TEST_F(TransportTest, TestChannelIceParameters) {
cricket::TransportDescription local_desc( cricket::TransportDescription local_desc(
cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1); cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1);
ASSERT_TRUE(transport_->SetLocalTransportDescription(local_desc, ASSERT_TRUE(transport_->SetLocalTransportDescription(local_desc,
cricket::CA_OFFER)); cricket::CA_OFFER,
NULL));
EXPECT_EQ(cricket::ICEROLE_CONTROLLING, transport_->ice_role()); EXPECT_EQ(cricket::ICEROLE_CONTROLLING, transport_->ice_role());
EXPECT_TRUE(SetupChannel()); EXPECT_TRUE(SetupChannel());
EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole()); EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole());
@@ -158,7 +159,8 @@ TEST_F(TransportTest, TestChannelIceParameters) {
cricket::TransportDescription remote_desc( cricket::TransportDescription remote_desc(
cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1); cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1);
ASSERT_TRUE(transport_->SetRemoteTransportDescription(remote_desc, ASSERT_TRUE(transport_->SetRemoteTransportDescription(remote_desc,
cricket::CA_ANSWER)); cricket::CA_ANSWER,
NULL));
EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole()); EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole());
EXPECT_EQ(99U, channel_->IceTiebreaker()); EXPECT_EQ(99U, channel_->IceTiebreaker());
EXPECT_EQ(cricket::ICEMODE_FULL, channel_->remote_ice_mode()); EXPECT_EQ(cricket::ICEMODE_FULL, channel_->remote_ice_mode());
@@ -178,11 +180,13 @@ TEST_F(TransportTest, TestSetRemoteIceLiteInOffer) {
kIceUfrag1, kIcePwd1, cricket::ICEMODE_LITE, kIceUfrag1, kIcePwd1, cricket::ICEMODE_LITE,
cricket::CONNECTIONROLE_ACTPASS, NULL, cricket::Candidates()); cricket::CONNECTIONROLE_ACTPASS, NULL, cricket::Candidates());
ASSERT_TRUE(transport_->SetRemoteTransportDescription(remote_desc, ASSERT_TRUE(transport_->SetRemoteTransportDescription(remote_desc,
cricket::CA_OFFER)); cricket::CA_OFFER,
NULL));
cricket::TransportDescription local_desc( cricket::TransportDescription local_desc(
cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1); cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1);
ASSERT_TRUE(transport_->SetLocalTransportDescription(local_desc, ASSERT_TRUE(transport_->SetLocalTransportDescription(local_desc,
cricket::CA_ANSWER)); cricket::CA_ANSWER,
NULL));
EXPECT_EQ(cricket::ICEROLE_CONTROLLING, transport_->ice_role()); EXPECT_EQ(cricket::ICEROLE_CONTROLLING, transport_->ice_role());
EXPECT_TRUE(SetupChannel()); EXPECT_TRUE(SetupChannel());
EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole()); EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole());
@@ -195,7 +199,8 @@ TEST_F(TransportTest, TestSetRemoteIceLiteInAnswer) {
cricket::TransportDescription local_desc( cricket::TransportDescription local_desc(
cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1); cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1);
ASSERT_TRUE(transport_->SetLocalTransportDescription(local_desc, ASSERT_TRUE(transport_->SetLocalTransportDescription(local_desc,
cricket::CA_OFFER)); cricket::CA_OFFER,
NULL));
EXPECT_EQ(cricket::ICEROLE_CONTROLLING, transport_->ice_role()); EXPECT_EQ(cricket::ICEROLE_CONTROLLING, transport_->ice_role());
EXPECT_TRUE(SetupChannel()); EXPECT_TRUE(SetupChannel());
EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole()); EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole());
@@ -206,7 +211,8 @@ TEST_F(TransportTest, TestSetRemoteIceLiteInAnswer) {
kIceUfrag1, kIcePwd1, cricket::ICEMODE_LITE, kIceUfrag1, kIcePwd1, cricket::ICEMODE_LITE,
cricket::CONNECTIONROLE_NONE, NULL, cricket::Candidates()); cricket::CONNECTIONROLE_NONE, NULL, cricket::Candidates());
ASSERT_TRUE(transport_->SetRemoteTransportDescription(remote_desc, ASSERT_TRUE(transport_->SetRemoteTransportDescription(remote_desc,
cricket::CA_ANSWER)); cricket::CA_ANSWER,
NULL));
EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole()); EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole());
// After receiving remote description with ICEMODE_LITE, channel should // After receiving remote description with ICEMODE_LITE, channel should
// have mode set to ICEMODE_LITE. // have mode set to ICEMODE_LITE.

View File

@@ -195,6 +195,9 @@ TurnPort::~TurnPort() {
while (!entries_.empty()) { while (!entries_.empty()) {
DestroyEntry(entries_.front()->address()); DestroyEntry(entries_.front()->address());
} }
if (resolver_) {
resolver_->Destroy(false);
}
} }
void TurnPort::PrepareAddress() { void TurnPort::PrepareAddress() {

View File

@@ -523,7 +523,7 @@ bool Call::StartScreencast(Session* session,
VideoContentDescription* video = CreateVideoStreamUpdate(stream); VideoContentDescription* video = CreateVideoStreamUpdate(stream);
// TODO(pthatcher): Wait until view request before sending video. // TODO(pthatcher): Wait until view request before sending video.
video_channel->SetLocalContent(video, CA_UPDATE); video_channel->SetLocalContent(video, CA_UPDATE, NULL);
SendVideoStreamUpdate(session, video); SendVideoStreamUpdate(session, video);
return true; return true;
} }
@@ -546,7 +546,7 @@ bool Call::StopScreencast(Session* session,
// No ssrcs // No ssrcs
VideoContentDescription* video = CreateVideoStreamUpdate(stream); VideoContentDescription* video = CreateVideoStreamUpdate(stream);
video_channel->SetLocalContent(video, CA_UPDATE); video_channel->SetLocalContent(video, CA_UPDATE, NULL);
SendVideoStreamUpdate(session, video); SendVideoStreamUpdate(session, video);
return true; return true;
} }
@@ -870,9 +870,11 @@ void Call::OnRemoteDescriptionUpdate(BaseSession* base_session,
bool Call::UpdateVoiceChannelRemoteContent( bool Call::UpdateVoiceChannelRemoteContent(
Session* session, const AudioContentDescription* audio) { Session* session, const AudioContentDescription* audio) {
VoiceChannel* voice_channel = GetVoiceChannel(session); VoiceChannel* voice_channel = GetVoiceChannel(session);
if (!voice_channel->SetRemoteContent(audio, CA_UPDATE)) { if (!voice_channel->SetRemoteContent(audio, CA_UPDATE, NULL)) {
LOG(LS_ERROR) << "Failure in audio SetRemoteContent with CA_UPDATE"; const std::string error_desc =
session->SetError(BaseSession::ERROR_CONTENT); "Failure in audio SetRemoteContent with CA_UPDATE";
LOG(LS_ERROR) << error_desc;
session->SetError(BaseSession::ERROR_CONTENT, error_desc);
return false; return false;
} }
return true; return true;
@@ -881,9 +883,11 @@ bool Call::UpdateVoiceChannelRemoteContent(
bool Call::UpdateVideoChannelRemoteContent( bool Call::UpdateVideoChannelRemoteContent(
Session* session, const VideoContentDescription* video) { Session* session, const VideoContentDescription* video) {
VideoChannel* video_channel = GetVideoChannel(session); VideoChannel* video_channel = GetVideoChannel(session);
if (!video_channel->SetRemoteContent(video, CA_UPDATE)) { if (!video_channel->SetRemoteContent(video, CA_UPDATE, NULL)) {
LOG(LS_ERROR) << "Failure in video SetRemoteContent with CA_UPDATE"; const std::string error_desc =
session->SetError(BaseSession::ERROR_CONTENT); "Failure in video SetRemoteContent with CA_UPDATE";
LOG(LS_ERROR) << error_desc;
session->SetError(BaseSession::ERROR_CONTENT, error_desc);
return false; return false;
} }
return true; return true;
@@ -892,9 +896,11 @@ bool Call::UpdateVideoChannelRemoteContent(
bool Call::UpdateDataChannelRemoteContent( bool Call::UpdateDataChannelRemoteContent(
Session* session, const DataContentDescription* data) { Session* session, const DataContentDescription* data) {
DataChannel* data_channel = GetDataChannel(session); DataChannel* data_channel = GetDataChannel(session);
if (!data_channel->SetRemoteContent(data, CA_UPDATE)) { if (!data_channel->SetRemoteContent(data, CA_UPDATE, NULL)) {
LOG(LS_ERROR) << "Failure in data SetRemoteContent with CA_UPDATE"; const std::string error_desc =
session->SetError(BaseSession::ERROR_CONTENT); "Failure in data SetRemoteContent with CA_UPDATE";
LOG(LS_ERROR) << error_desc;
session->SetError(BaseSession::ERROR_CONTENT, error_desc);
return false; return false;
} }
return true; return true;

View File

@@ -60,7 +60,6 @@ enum {
MSG_REMOVESENDSTREAM, MSG_REMOVESENDSTREAM,
MSG_SETRINGBACKTONE, MSG_SETRINGBACKTONE,
MSG_PLAYRINGBACKTONE, MSG_PLAYRINGBACKTONE,
MSG_SETMAXSENDBANDWIDTH,
MSG_ADDSCREENCAST, MSG_ADDSCREENCAST,
MSG_REMOVESCREENCAST, MSG_REMOVESCREENCAST,
MSG_SENDINTRAFRAME, MSG_SENDINTRAFRAME,
@@ -88,6 +87,17 @@ static const char kDtlsSrtpExporterLabel[] = "EXTRACTOR-dtls_srtp";
static const int kAgcMinus10db = -10; static const int kAgcMinus10db = -10;
static void SetSessionError(BaseSession* session, BaseSession::Error error,
const std::string& error_desc) {
session->SetError(error, error_desc);
}
static void SafeSetError(const std::string& message, std::string* error_desc) {
if (error_desc) {
*error_desc = message;
}
}
// TODO(hellner): use the device manager for creation of screen capturers when // TODO(hellner): use the device manager for creation of screen capturers when
// the cl enabling it has landed. // the cl enabling it has landed.
class NullScreenCapturerFactory : public VideoChannel::ScreenCapturerFactory { class NullScreenCapturerFactory : public VideoChannel::ScreenCapturerFactory {
@@ -103,13 +113,17 @@ VideoChannel::ScreenCapturerFactory* CreateScreenCapturerFactory() {
} }
struct SetContentData : public talk_base::MessageData { struct SetContentData : public talk_base::MessageData {
SetContentData(const MediaContentDescription* content, ContentAction action) SetContentData(const MediaContentDescription* content,
ContentAction action,
std::string* error_desc)
: content(content), : content(content),
action(action), action(action),
error_desc(error_desc),
result(false) { result(false) {
} }
const MediaContentDescription* content; const MediaContentDescription* content;
ContentAction action; ContentAction action;
std::string* error_desc;
bool result; bool result;
}; };
@@ -273,10 +287,13 @@ struct DataChannelErrorMessageData : public talk_base::MessageData {
}; };
struct SessionErrorMessageData : public talk_base::MessageData { struct SessionErrorMessageData : public talk_base::MessageData {
explicit SessionErrorMessageData(cricket::BaseSession::Error error) SessionErrorMessageData(cricket::BaseSession::Error error,
: error_(error) {} const std::string& error_desc)
: error_(error),
error_desc_(error_desc) {}
BaseSession::Error error_; BaseSession::Error error_;
std::string error_desc_;
}; };
struct SsrcMessageData : public talk_base::MessageData { struct SsrcMessageData : public talk_base::MessageData {
@@ -505,25 +522,21 @@ bool BaseChannel::RemoveSendStream(uint32 ssrc) {
} }
bool BaseChannel::SetLocalContent(const MediaContentDescription* content, bool BaseChannel::SetLocalContent(const MediaContentDescription* content,
ContentAction action) { ContentAction action,
SetContentData data(content, action); std::string* error_desc) {
SetContentData data(content, action, error_desc);
Send(MSG_SETLOCALCONTENT, &data); Send(MSG_SETLOCALCONTENT, &data);
return data.result; return data.result;
} }
bool BaseChannel::SetRemoteContent(const MediaContentDescription* content, bool BaseChannel::SetRemoteContent(const MediaContentDescription* content,
ContentAction action) { ContentAction action,
SetContentData data(content, action); std::string* error_desc) {
SetContentData data(content, action, error_desc);
Send(MSG_SETREMOTECONTENT, &data); Send(MSG_SETREMOTECONTENT, &data);
return data.result; return data.result;
} }
bool BaseChannel::SetMaxSendBandwidth(int max_bandwidth) {
SetBandwidthData data(max_bandwidth);
Send(MSG_SETMAXSENDBANDWIDTH, &data);
return data.result;
}
void BaseChannel::StartConnectionMonitor(int cms) { void BaseChannel::StartConnectionMonitor(int cms) {
socket_monitor_.reset(new SocketMonitor(transport_channel_, socket_monitor_.reset(new SocketMonitor(transport_channel_,
worker_thread(), worker_thread(),
@@ -857,10 +870,11 @@ void BaseChannel::OnNewLocalDescription(
GetFirstContent(session->local_description()); GetFirstContent(session->local_description());
const MediaContentDescription* content_desc = const MediaContentDescription* content_desc =
GetContentDescription(content_info); GetContentDescription(content_info);
std::string error_desc;
if (content_desc && content_info && !content_info->rejected && if (content_desc && content_info && !content_info->rejected &&
!SetLocalContent(content_desc, action)) { !SetLocalContent(content_desc, action, &error_desc)) {
SetSessionError(session_, BaseSession::ERROR_CONTENT, error_desc);
LOG(LS_ERROR) << "Failure in SetLocalContent with action " << action; LOG(LS_ERROR) << "Failure in SetLocalContent with action " << action;
session->SetError(BaseSession::ERROR_CONTENT);
} }
} }
@@ -870,10 +884,11 @@ void BaseChannel::OnNewRemoteDescription(
GetFirstContent(session->remote_description()); GetFirstContent(session->remote_description());
const MediaContentDescription* content_desc = const MediaContentDescription* content_desc =
GetContentDescription(content_info); GetContentDescription(content_info);
std::string error_desc;
if (content_desc && content_info && !content_info->rejected && if (content_desc && content_info && !content_info->rejected &&
!SetRemoteContent(content_desc, action)) { !SetRemoteContent(content_desc, action, &error_desc)) {
SetSessionError(session_, BaseSession::ERROR_CONTENT, error_desc);
LOG(LS_ERROR) << "Failure in SetRemoteContent with action " << action; LOG(LS_ERROR) << "Failure in SetRemoteContent with action " << action;
session->SetError(BaseSession::ERROR_CONTENT);
} }
} }
@@ -938,8 +953,9 @@ void BaseChannel::ChannelWritable_w() {
// If we're doing DTLS-SRTP, now is the time. // If we're doing DTLS-SRTP, now is the time.
if (!was_ever_writable_ && ShouldSetupDtlsSrtp()) { if (!was_ever_writable_ && ShouldSetupDtlsSrtp()) {
if (!SetupDtlsSrtp(false)) { if (!SetupDtlsSrtp(false)) {
LOG(LS_ERROR) << "Couldn't finish DTLS-SRTP on RTP channel"; const std::string error_desc =
SessionErrorMessageData data(BaseSession::ERROR_TRANSPORT); "Couldn't set up DTLS-SRTP on RTP channel.";
SessionErrorMessageData data(BaseSession::ERROR_TRANSPORT, error_desc);
// Sent synchronously. // Sent synchronously.
signaling_thread()->Send(this, MSG_SESSION_ERROR, &data); signaling_thread()->Send(this, MSG_SESSION_ERROR, &data);
return; return;
@@ -947,8 +963,9 @@ void BaseChannel::ChannelWritable_w() {
if (rtcp_transport_channel_) { if (rtcp_transport_channel_) {
if (!SetupDtlsSrtp(true)) { if (!SetupDtlsSrtp(true)) {
LOG(LS_ERROR) << "Couldn't finish DTLS-SRTP on RTCP channel"; const std::string error_desc =
SessionErrorMessageData data(BaseSession::ERROR_TRANSPORT); "Couldn't set up DTLS-SRTP on RTCP channel";
SessionErrorMessageData data(BaseSession::ERROR_TRANSPORT, error_desc);
// Sent synchronously. // Sent synchronously.
signaling_thread()->Send(this, MSG_SESSION_ERROR, &data); signaling_thread()->Send(this, MSG_SESSION_ERROR, &data);
return; return;
@@ -1085,62 +1102,69 @@ void BaseChannel::ChannelNotWritable_w() {
ChangeState(); ChangeState();
} }
// Sets the maximum video bandwidth for automatic bandwidth adjustment.
bool BaseChannel::SetMaxSendBandwidth_w(int max_bandwidth) {
return media_channel()->SetSendBandwidth(true, max_bandwidth);
}
// |dtls| will be set to true if DTLS is active for transport channel and // |dtls| will be set to true if DTLS is active for transport channel and
// crypto is empty. // crypto is empty.
bool BaseChannel::CheckSrtpConfig(const std::vector<CryptoParams>& cryptos, bool BaseChannel::CheckSrtpConfig(const std::vector<CryptoParams>& cryptos,
bool* dtls) { bool* dtls,
std::string* error_desc) {
*dtls = transport_channel_->IsDtlsActive(); *dtls = transport_channel_->IsDtlsActive();
if (*dtls && !cryptos.empty()) { if (*dtls && !cryptos.empty()) {
LOG(LS_WARNING) << "Cryptos must be empty when DTLS is active."; SafeSetError("Cryptos must be empty when DTLS is active.",
error_desc);
return false; return false;
} }
return true; return true;
} }
bool BaseChannel::SetSrtp_w(const std::vector<CryptoParams>& cryptos, bool BaseChannel::SetSrtp_w(const std::vector<CryptoParams>& cryptos,
ContentAction action, ContentSource src) { ContentAction action,
ContentSource src,
std::string* error_desc) {
if (action == CA_UPDATE) {
// no crypto params.
return true;
}
bool ret = false; bool ret = false;
bool dtls = false; bool dtls = false;
ret = CheckSrtpConfig(cryptos, &dtls); ret = CheckSrtpConfig(cryptos, &dtls, error_desc);
if (!ret) {
return false;
}
switch (action) { switch (action) {
case CA_OFFER: case CA_OFFER:
// If DTLS is already active on the channel, we could be renegotiating // If DTLS is already active on the channel, we could be renegotiating
// here. We don't update the srtp filter. // here. We don't update the srtp filter.
if (ret && !dtls) { if (!dtls) {
ret = srtp_filter_.SetOffer(cryptos, src); ret = srtp_filter_.SetOffer(cryptos, src);
} }
break; break;
case CA_PRANSWER: case CA_PRANSWER:
// If we're doing DTLS-SRTP, we don't want to update the filter // If we're doing DTLS-SRTP, we don't want to update the filter
// with an answer, because we already have SRTP parameters. // with an answer, because we already have SRTP parameters.
if (ret && !dtls) { if (!dtls) {
ret = srtp_filter_.SetProvisionalAnswer(cryptos, src); ret = srtp_filter_.SetProvisionalAnswer(cryptos, src);
} }
break; break;
case CA_ANSWER: case CA_ANSWER:
// If we're doing DTLS-SRTP, we don't want to update the filter // If we're doing DTLS-SRTP, we don't want to update the filter
// with an answer, because we already have SRTP parameters. // with an answer, because we already have SRTP parameters.
if (ret && !dtls) { if (!dtls) {
ret = srtp_filter_.SetAnswer(cryptos, src); ret = srtp_filter_.SetAnswer(cryptos, src);
} }
break; break;
case CA_UPDATE:
// no crypto params.
ret = true;
break;
default: default:
break; break;
} }
return ret; if (!ret) {
SafeSetError("Failed to setup SRTP filter.", error_desc);
return false;
}
return true;
} }
bool BaseChannel::SetRtcpMux_w(bool enable, ContentAction action, bool BaseChannel::SetRtcpMux_w(bool enable, ContentAction action,
ContentSource src) { ContentSource src,
std::string* error_desc) {
bool ret = false; bool ret = false;
switch (action) { switch (action) {
case CA_OFFER: case CA_OFFER:
@@ -1162,17 +1186,21 @@ bool BaseChannel::SetRtcpMux_w(bool enable, ContentAction action,
default: default:
break; break;
} }
if (!ret) {
SafeSetError("Failed to setup RTCP mux filter.", error_desc);
return false;
}
// |rtcp_mux_filter_| can be active if |action| is CA_PRANSWER or // |rtcp_mux_filter_| can be active if |action| is CA_PRANSWER or
// CA_ANSWER, but we only want to tear down the RTCP transport channel if we // CA_ANSWER, but we only want to tear down the RTCP transport channel if we
// received a final answer. // received a final answer.
if (ret && rtcp_mux_filter_.IsActive()) { if (rtcp_mux_filter_.IsActive()) {
// If the RTP transport is already writable, then so are we. // If the RTP transport is already writable, then so are we.
if (transport_channel_->writable()) { if (transport_channel_->writable()) {
ChannelWritable_w(); ChannelWritable_w();
} }
} }
return ret; return true;
} }
bool BaseChannel::AddRecvStream_w(const StreamParams& sp) { bool BaseChannel::AddRecvStream_w(const StreamParams& sp) {
@@ -1200,7 +1228,8 @@ bool BaseChannel::RemoveSendStream_w(uint32 ssrc) {
} }
bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams, bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams,
ContentAction action) { ContentAction action,
std::string* error_desc) {
if (!VERIFY(action == CA_OFFER || action == CA_ANSWER || if (!VERIFY(action == CA_OFFER || action == CA_ANSWER ||
action == CA_PRANSWER || action == CA_UPDATE)) action == CA_PRANSWER || action == CA_UPDATE))
return false; return false;
@@ -1217,14 +1246,17 @@ bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams,
local_streams_.push_back(*it); local_streams_.push_back(*it);
LOG(LS_INFO) << "Add send stream ssrc: " << it->first_ssrc(); LOG(LS_INFO) << "Add send stream ssrc: " << it->first_ssrc();
} else { } else {
LOG(LS_INFO) << "Failed to add send stream ssrc: " std::ostringstream desc;
<< it->first_ssrc(); desc << "Failed to add send stream ssrc: " << it->first_ssrc();
SafeSetError(desc.str(), error_desc);
return false; return false;
} }
} else if (stream_exist && !it->has_ssrcs()) { } else if (stream_exist && !it->has_ssrcs()) {
if (!media_channel()->RemoveSendStream(existing_stream.first_ssrc())) { if (!media_channel()->RemoveSendStream(existing_stream.first_ssrc())) {
LOG(LS_ERROR) << "Failed to remove send stream with ssrc " std::ostringstream desc;
desc << "Failed to remove send stream with ssrc "
<< it->first_ssrc() << "."; << it->first_ssrc() << ".";
SafeSetError(desc.str(), error_desc);
return false; return false;
} }
RemoveStreamBySsrc(&local_streams_, existing_stream.first_ssrc()); RemoveStreamBySsrc(&local_streams_, existing_stream.first_ssrc());
@@ -1242,8 +1274,10 @@ bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams,
it != local_streams_.end(); ++it) { it != local_streams_.end(); ++it) {
if (!GetStreamBySsrc(streams, it->first_ssrc(), NULL)) { if (!GetStreamBySsrc(streams, it->first_ssrc(), NULL)) {
if (!media_channel()->RemoveSendStream(it->first_ssrc())) { if (!media_channel()->RemoveSendStream(it->first_ssrc())) {
LOG(LS_ERROR) << "Failed to remove send stream with ssrc " std::ostringstream desc;
desc << "Failed to remove send stream with ssrc "
<< it->first_ssrc() << "."; << it->first_ssrc() << ".";
SafeSetError(desc.str(), error_desc);
ret = false; ret = false;
} }
} }
@@ -1255,7 +1289,9 @@ bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams,
if (media_channel()->AddSendStream(*it)) { if (media_channel()->AddSendStream(*it)) {
LOG(LS_INFO) << "Add send ssrc: " << it->ssrcs[0]; LOG(LS_INFO) << "Add send ssrc: " << it->ssrcs[0];
} else { } else {
LOG(LS_INFO) << "Failed to add send stream ssrc: " << it->first_ssrc(); std::ostringstream desc;
desc << "Failed to add send stream ssrc: " << it->first_ssrc();
SafeSetError(desc.str(), error_desc);
ret = false; ret = false;
} }
} }
@@ -1266,7 +1302,8 @@ bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams,
bool BaseChannel::UpdateRemoteStreams_w( bool BaseChannel::UpdateRemoteStreams_w(
const std::vector<StreamParams>& streams, const std::vector<StreamParams>& streams,
ContentAction action) { ContentAction action,
std::string* error_desc) {
if (!VERIFY(action == CA_OFFER || action == CA_ANSWER || if (!VERIFY(action == CA_OFFER || action == CA_ANSWER ||
action == CA_PRANSWER || action == CA_UPDATE)) action == CA_PRANSWER || action == CA_UPDATE))
return false; return false;
@@ -1283,14 +1320,17 @@ bool BaseChannel::UpdateRemoteStreams_w(
remote_streams_.push_back(*it); remote_streams_.push_back(*it);
LOG(LS_INFO) << "Add remote stream ssrc: " << it->first_ssrc(); LOG(LS_INFO) << "Add remote stream ssrc: " << it->first_ssrc();
} else { } else {
LOG(LS_INFO) << "Failed to add remote stream ssrc: " std::ostringstream desc;
<< it->first_ssrc(); desc << "Failed to add remote stream ssrc: " << it->first_ssrc();
SafeSetError(desc.str(), error_desc);
return false; return false;
} }
} else if (stream_exists && !it->has_ssrcs()) { } else if (stream_exists && !it->has_ssrcs()) {
if (!RemoveRecvStream_w(existing_stream.first_ssrc())) { if (!RemoveRecvStream_w(existing_stream.first_ssrc())) {
LOG(LS_ERROR) << "Failed to remove remote stream with ssrc " std::ostringstream desc;
desc << "Failed to remove remote stream with ssrc "
<< it->first_ssrc() << "."; << it->first_ssrc() << ".";
SafeSetError(desc.str(), error_desc);
return false; return false;
} }
RemoveStreamBySsrc(&remote_streams_, existing_stream.first_ssrc()); RemoveStreamBySsrc(&remote_streams_, existing_stream.first_ssrc());
@@ -1311,8 +1351,10 @@ bool BaseChannel::UpdateRemoteStreams_w(
it != remote_streams_.end(); ++it) { it != remote_streams_.end(); ++it) {
if (!GetStreamBySsrc(streams, it->first_ssrc(), NULL)) { if (!GetStreamBySsrc(streams, it->first_ssrc(), NULL)) {
if (!RemoveRecvStream_w(it->first_ssrc())) { if (!RemoveRecvStream_w(it->first_ssrc())) {
LOG(LS_ERROR) << "Failed to remove remote stream with ssrc " std::ostringstream desc;
desc << "Failed to remove remote stream with ssrc "
<< it->first_ssrc() << "."; << it->first_ssrc() << ".";
SafeSetError(desc.str(), error_desc);
ret = false; ret = false;
} }
} }
@@ -1324,8 +1366,9 @@ bool BaseChannel::UpdateRemoteStreams_w(
if (AddRecvStream_w(*it)) { if (AddRecvStream_w(*it)) {
LOG(LS_INFO) << "Add remote ssrc: " << it->ssrcs[0]; LOG(LS_INFO) << "Add remote ssrc: " << it->ssrcs[0];
} else { } else {
LOG(LS_INFO) << "Failed to add remote stream ssrc: " std::ostringstream desc;
<< it->first_ssrc(); desc << "Failed to add remote stream ssrc: " << it->first_ssrc();
SafeSetError(desc.str(), error_desc);
ret = false; ret = false;
} }
} }
@@ -1335,37 +1378,56 @@ bool BaseChannel::UpdateRemoteStreams_w(
} }
bool BaseChannel::SetBaseLocalContent_w(const MediaContentDescription* content, bool BaseChannel::SetBaseLocalContent_w(const MediaContentDescription* content,
ContentAction action) { ContentAction action,
std::string* error_desc) {
// Cache secure_required_ for belt and suspenders check on SendPacket // Cache secure_required_ for belt and suspenders check on SendPacket
secure_required_ = content->crypto_required(); secure_required_ = content->crypto_required();
bool ret = UpdateLocalStreams_w(content->streams(), action); bool ret = UpdateLocalStreams_w(content->streams(), action, error_desc);
// Set local SRTP parameters (what we will encrypt with). // Set local SRTP parameters (what we will encrypt with).
ret &= SetSrtp_w(content->cryptos(), action, CS_LOCAL); ret &= SetSrtp_w(content->cryptos(), action, CS_LOCAL, error_desc);
// Set local RTCP mux parameters. // Set local RTCP mux parameters.
ret &= SetRtcpMux_w(content->rtcp_mux(), action, CS_LOCAL); ret &= SetRtcpMux_w(content->rtcp_mux(), action, CS_LOCAL, error_desc);
// Set local RTP header extensions. // Set local RTP header extensions.
if (content->rtp_header_extensions_set()) { if (content->rtp_header_extensions_set()) {
ret &= media_channel()->SetRecvRtpHeaderExtensions( if (!media_channel()->SetRecvRtpHeaderExtensions(
content->rtp_header_extensions()); content->rtp_header_extensions())) {
std::ostringstream desc;
desc << "Failed to set receive rtp header extensions for "
<< MediaTypeToString(content->type()) << " content.";
SafeSetError(desc.str(), error_desc);
ret = false;
}
} }
set_local_content_direction(content->direction()); set_local_content_direction(content->direction());
return ret; return ret;
} }
bool BaseChannel::SetBaseRemoteContent_w(const MediaContentDescription* content, bool BaseChannel::SetBaseRemoteContent_w(const MediaContentDescription* content,
ContentAction action) { ContentAction action,
bool ret = UpdateRemoteStreams_w(content->streams(), action); std::string* error_desc) {
bool ret = UpdateRemoteStreams_w(content->streams(), action, error_desc);
// Set remote SRTP parameters (what the other side will encrypt with). // Set remote SRTP parameters (what the other side will encrypt with).
ret &= SetSrtp_w(content->cryptos(), action, CS_REMOTE); ret &= SetSrtp_w(content->cryptos(), action, CS_REMOTE, error_desc);
// Set remote RTCP mux parameters. // Set remote RTCP mux parameters.
ret &= SetRtcpMux_w(content->rtcp_mux(), action, CS_REMOTE); ret &= SetRtcpMux_w(content->rtcp_mux(), action, CS_REMOTE, error_desc);
// Set remote RTP header extensions. // Set remote RTP header extensions.
if (content->rtp_header_extensions_set()) { if (content->rtp_header_extensions_set()) {
ret &= media_channel()->SetSendRtpHeaderExtensions( if (!media_channel()->SetSendRtpHeaderExtensions(
content->rtp_header_extensions()); content->rtp_header_extensions())) {
std::ostringstream desc;
desc << "Failed to set send rtp header extensions for "
<< MediaTypeToString(content->type()) << " content.";
SafeSetError(desc.str(), error_desc);
ret = false;
} }
if (content->bandwidth() != kAutoBandwidth) { }
ret &= media_channel()->SetSendBandwidth(false, content->bandwidth());
if (!media_channel()->SetMaxSendBandwidth(content->bandwidth())) {
std::ostringstream desc;
desc << "Failed to set max send bandwidth for "
<< MediaTypeToString(content->type()) << " content.";
SafeSetError(desc.str(), error_desc);
ret = false;
} }
set_remote_content_direction(content->direction()); set_remote_content_direction(content->direction());
return ret; return ret;
@@ -1391,12 +1453,16 @@ void BaseChannel::OnMessage(talk_base::Message *pmsg) {
} }
case MSG_SETLOCALCONTENT: { case MSG_SETLOCALCONTENT: {
SetContentData* data = static_cast<SetContentData*>(pmsg->pdata); SetContentData* data = static_cast<SetContentData*>(pmsg->pdata);
data->result = SetLocalContent_w(data->content, data->action); data->result = SetLocalContent_w(data->content,
data->action,
data->error_desc);
break; break;
} }
case MSG_SETREMOTECONTENT: { case MSG_SETREMOTECONTENT: {
SetContentData* data = static_cast<SetContentData*>(pmsg->pdata); SetContentData* data = static_cast<SetContentData*>(pmsg->pdata);
data->result = SetRemoteContent_w(data->content, data->action); data->result = SetRemoteContent_w(data->content,
data->action,
data->error_desc);
break; break;
} }
case MSG_ADDRECVSTREAM: { case MSG_ADDRECVSTREAM: {
@@ -1419,11 +1485,6 @@ void BaseChannel::OnMessage(talk_base::Message *pmsg) {
data->result = RemoveSendStream_w(data->ssrc); data->result = RemoveSendStream_w(data->ssrc);
break; break;
} }
case MSG_SETMAXSENDBANDWIDTH: {
SetBandwidthData* data = static_cast<SetBandwidthData*>(pmsg->pdata);
data->result = SetMaxSendBandwidth_w(data->value);
break;
}
case MSG_RTPPACKET: case MSG_RTPPACKET:
case MSG_RTCPPACKET: { case MSG_RTCPPACKET: {
@@ -1439,7 +1500,7 @@ void BaseChannel::OnMessage(talk_base::Message *pmsg) {
case MSG_SESSION_ERROR: { case MSG_SESSION_ERROR: {
SessionErrorMessageData* data = static_cast<SessionErrorMessageData*> SessionErrorMessageData* data = static_cast<SessionErrorMessageData*>
(pmsg->pdata); (pmsg->pdata);
session_->SetError(data->error_); SetSessionError(session_, data->error_, data->error_desc_);
break; break;
} }
} }
@@ -1685,21 +1746,28 @@ const ContentInfo* VoiceChannel::GetFirstContent(
} }
bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content, bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content,
ContentAction action) { ContentAction action,
std::string* error_desc) {
ASSERT(worker_thread() == talk_base::Thread::Current()); ASSERT(worker_thread() == talk_base::Thread::Current());
LOG(LS_INFO) << "Setting local voice description"; LOG(LS_INFO) << "Setting local voice description";
const AudioContentDescription* audio = const AudioContentDescription* audio =
static_cast<const AudioContentDescription*>(content); static_cast<const AudioContentDescription*>(content);
ASSERT(audio != NULL); ASSERT(audio != NULL);
if (!audio) return false; if (!audio) {
SafeSetError("Can't find audio content in local description.", error_desc);
return false;
}
bool ret = SetBaseLocalContent_w(content, action); bool ret = SetBaseLocalContent_w(content, action, error_desc);
// Set local audio codecs (what we want to receive). // Set local audio codecs (what we want to receive).
// TODO(whyuan): Change action != CA_UPDATE to !audio->partial() when partial // TODO(whyuan): Change action != CA_UPDATE to !audio->partial() when partial
// is set properly. // is set properly.
if (action != CA_UPDATE || audio->has_codecs()) { if (action != CA_UPDATE || audio->has_codecs()) {
ret &= media_channel()->SetRecvCodecs(audio->codecs()); if (!media_channel()->SetRecvCodecs(audio->codecs())) {
SafeSetError("Failed to set audio receive codecs.", error_desc);
ret = false;
}
} }
// If everything worked, see if we can start receiving. // If everything worked, see if we can start receiving.
@@ -1712,22 +1780,29 @@ bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content,
} }
bool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content, bool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content,
ContentAction action) { ContentAction action,
std::string* error_desc) {
ASSERT(worker_thread() == talk_base::Thread::Current()); ASSERT(worker_thread() == talk_base::Thread::Current());
LOG(LS_INFO) << "Setting remote voice description"; LOG(LS_INFO) << "Setting remote voice description";
const AudioContentDescription* audio = const AudioContentDescription* audio =
static_cast<const AudioContentDescription*>(content); static_cast<const AudioContentDescription*>(content);
ASSERT(audio != NULL); ASSERT(audio != NULL);
if (!audio) return false; if (!audio) {
SafeSetError("Can't find audio content in remote description.", error_desc);
return false;
}
bool ret = true; bool ret = true;
// Set remote video codecs (what the other side wants to receive). // Set remote video codecs (what the other side wants to receive).
if (action != CA_UPDATE || audio->has_codecs()) { if (action != CA_UPDATE || audio->has_codecs()) {
ret &= media_channel()->SetSendCodecs(audio->codecs()); if (!media_channel()->SetSendCodecs(audio->codecs())) {
SafeSetError("Failed to set audio send codecs.", error_desc);
ret = false;
}
} }
ret &= SetBaseRemoteContent_w(content, action); ret &= SetBaseRemoteContent_w(content, action, error_desc);
if (action != CA_UPDATE) { if (action != CA_UPDATE) {
// Tweak our audio processing settings, if needed. // Tweak our audio processing settings, if needed.
@@ -2104,19 +2179,26 @@ const ContentInfo* VideoChannel::GetFirstContent(
} }
bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content, bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
ContentAction action) { ContentAction action,
std::string* error_desc) {
ASSERT(worker_thread() == talk_base::Thread::Current()); ASSERT(worker_thread() == talk_base::Thread::Current());
LOG(LS_INFO) << "Setting local video description"; LOG(LS_INFO) << "Setting local video description";
const VideoContentDescription* video = const VideoContentDescription* video =
static_cast<const VideoContentDescription*>(content); static_cast<const VideoContentDescription*>(content);
ASSERT(video != NULL); ASSERT(video != NULL);
if (!video) return false; if (!video) {
SafeSetError("Can't find video content in local description.", error_desc);
return false;
}
bool ret = SetBaseLocalContent_w(content, action); bool ret = SetBaseLocalContent_w(content, action, error_desc);
// Set local video codecs (what we want to receive). // Set local video codecs (what we want to receive).
if (action != CA_UPDATE || video->has_codecs()) { if (action != CA_UPDATE || video->has_codecs()) {
ret &= media_channel()->SetRecvCodecs(video->codecs()); if (!media_channel()->SetRecvCodecs(video->codecs())) {
SafeSetError("Failed to set video receive codecs.", error_desc);
ret = false;
}
} }
if (action != CA_UPDATE) { if (action != CA_UPDATE) {
@@ -2140,22 +2222,29 @@ bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
} }
bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content, bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content,
ContentAction action) { ContentAction action,
std::string* error_desc) {
ASSERT(worker_thread() == talk_base::Thread::Current()); ASSERT(worker_thread() == talk_base::Thread::Current());
LOG(LS_INFO) << "Setting remote video description"; LOG(LS_INFO) << "Setting remote video description";
const VideoContentDescription* video = const VideoContentDescription* video =
static_cast<const VideoContentDescription*>(content); static_cast<const VideoContentDescription*>(content);
ASSERT(video != NULL); ASSERT(video != NULL);
if (!video) return false; if (!video) {
SafeSetError("Can't find video content in remote description.", error_desc);
return false;
}
bool ret = true; bool ret = true;
// Set remote video codecs (what the other side wants to receive). // Set remote video codecs (what the other side wants to receive).
if (action != CA_UPDATE || video->has_codecs()) { if (action != CA_UPDATE || video->has_codecs()) {
ret &= media_channel()->SetSendCodecs(video->codecs()); if (!media_channel()->SetSendCodecs(video->codecs())) {
SafeSetError("Failed to set video send codecs.", error_desc);
ret = false;
}
} }
ret &= SetBaseRemoteContent_w(content, action); ret &= SetBaseRemoteContent_w(content, action, error_desc);
if (action != CA_UPDATE) { if (action != CA_UPDATE) {
// Tweak our video processing settings, if needed. // Tweak our video processing settings, if needed.
@@ -2553,13 +2642,8 @@ bool DataChannel::WantsPacket(bool rtcp, talk_base::Buffer* packet) {
return false; return false;
} }
// Sets the maximum bandwidth. Anything over this will be dropped. bool DataChannel::SetDataChannelType(DataChannelType new_data_channel_type,
bool DataChannel::SetMaxSendBandwidth_w(int max_bps) { std::string* error_desc) {
LOG(LS_INFO) << "DataChannel: Setting max bandwidth to " << max_bps;
return media_channel()->SetSendBandwidth(false, max_bps);
}
bool DataChannel::SetDataChannelType(DataChannelType new_data_channel_type) {
// It hasn't been set before, so set it now. // It hasn't been set before, so set it now.
if (data_channel_type_ == DCT_NONE) { if (data_channel_type_ == DCT_NONE) {
data_channel_type_ = new_data_channel_type; data_channel_type_ = new_data_channel_type;
@@ -2568,9 +2652,11 @@ bool DataChannel::SetDataChannelType(DataChannelType new_data_channel_type) {
// It's been set before, but doesn't match. That's bad. // It's been set before, but doesn't match. That's bad.
if (data_channel_type_ != new_data_channel_type) { if (data_channel_type_ != new_data_channel_type) {
LOG(LS_WARNING) << "Data channel type mismatch." std::ostringstream desc;
desc << "Data channel type mismatch."
<< " Expected " << data_channel_type_ << " Expected " << data_channel_type_
<< " Got " << new_data_channel_type; << " Got " << new_data_channel_type;
SafeSetError(desc.str(), error_desc);
return false; return false;
} }
@@ -2579,42 +2665,53 @@ bool DataChannel::SetDataChannelType(DataChannelType new_data_channel_type) {
} }
bool DataChannel::SetDataChannelTypeFromContent( bool DataChannel::SetDataChannelTypeFromContent(
const DataContentDescription* content) { const DataContentDescription* content,
std::string* error_desc) {
bool is_sctp = ((content->protocol() == kMediaProtocolSctp) || bool is_sctp = ((content->protocol() == kMediaProtocolSctp) ||
(content->protocol() == kMediaProtocolDtlsSctp)); (content->protocol() == kMediaProtocolDtlsSctp));
DataChannelType data_channel_type = is_sctp ? DCT_SCTP : DCT_RTP; DataChannelType data_channel_type = is_sctp ? DCT_SCTP : DCT_RTP;
return SetDataChannelType(data_channel_type); return SetDataChannelType(data_channel_type, error_desc);
} }
bool DataChannel::SetLocalContent_w(const MediaContentDescription* content, bool DataChannel::SetLocalContent_w(const MediaContentDescription* content,
ContentAction action) { ContentAction action,
std::string* error_desc) {
ASSERT(worker_thread() == talk_base::Thread::Current()); ASSERT(worker_thread() == talk_base::Thread::Current());
LOG(LS_INFO) << "Setting local data description"; LOG(LS_INFO) << "Setting local data description";
const DataContentDescription* data = const DataContentDescription* data =
static_cast<const DataContentDescription*>(content); static_cast<const DataContentDescription*>(content);
ASSERT(data != NULL); ASSERT(data != NULL);
if (!data) return false; if (!data) {
SafeSetError("Can't find data content in local description.", error_desc);
return false;
}
bool ret = false; bool ret = false;
if (!SetDataChannelTypeFromContent(data)) { if (!SetDataChannelTypeFromContent(data, error_desc)) {
return false; return false;
} }
if (data_channel_type_ == DCT_SCTP) { if (data_channel_type_ == DCT_SCTP) {
// SCTP data channels don't need the rest of the stuff. // SCTP data channels don't need the rest of the stuff.
ret = UpdateLocalStreams_w(data->streams(), action); ret = UpdateLocalStreams_w(data->streams(), action, error_desc);
if (ret) { if (ret) {
set_local_content_direction(content->direction()); set_local_content_direction(content->direction());
// As in SetRemoteContent_w, make sure we set the local SCTP port // As in SetRemoteContent_w, make sure we set the local SCTP port
// number as specified in our DataContentDescription. // number as specified in our DataContentDescription.
ret = media_channel()->SetRecvCodecs(data->codecs()); if (!media_channel()->SetRecvCodecs(data->codecs())) {
SafeSetError("Failed to set data receive codecs.", error_desc);
ret = false;
}
} }
} else { } else {
ret = SetBaseLocalContent_w(content, action); ret = SetBaseLocalContent_w(content, action, error_desc);
if (action != CA_UPDATE || data->has_codecs()) { if (action != CA_UPDATE || data->has_codecs()) {
ret &= media_channel()->SetRecvCodecs(data->codecs()); if (!media_channel()->SetRecvCodecs(data->codecs())) {
SafeSetError("Failed to set data receive codecs.", error_desc);
ret = false;
}
} }
} }
@@ -2628,28 +2725,35 @@ bool DataChannel::SetLocalContent_w(const MediaContentDescription* content,
} }
bool DataChannel::SetRemoteContent_w(const MediaContentDescription* content, bool DataChannel::SetRemoteContent_w(const MediaContentDescription* content,
ContentAction action) { ContentAction action,
std::string* error_desc) {
ASSERT(worker_thread() == talk_base::Thread::Current()); ASSERT(worker_thread() == talk_base::Thread::Current());
const DataContentDescription* data = const DataContentDescription* data =
static_cast<const DataContentDescription*>(content); static_cast<const DataContentDescription*>(content);
ASSERT(data != NULL); ASSERT(data != NULL);
if (!data) return false; if (!data) {
SafeSetError("Can't find data content in remote description.", error_desc);
return false;
}
bool ret = true; bool ret = true;
if (!SetDataChannelTypeFromContent(data)) { if (!SetDataChannelTypeFromContent(data, error_desc)) {
return false; return false;
} }
if (data_channel_type_ == DCT_SCTP) { if (data_channel_type_ == DCT_SCTP) {
LOG(LS_INFO) << "Setting SCTP remote data description"; LOG(LS_INFO) << "Setting SCTP remote data description";
// SCTP data channels don't need the rest of the stuff. // SCTP data channels don't need the rest of the stuff.
ret = UpdateRemoteStreams_w(content->streams(), action); ret = UpdateRemoteStreams_w(content->streams(), action, error_desc);
if (ret) { if (ret) {
set_remote_content_direction(content->direction()); set_remote_content_direction(content->direction());
// We send the SCTP port number (not to be confused with the underlying // We send the SCTP port number (not to be confused with the underlying
// UDP port number) as a codec parameter. Make sure it gets there. // UDP port number) as a codec parameter. Make sure it gets there.
ret = media_channel()->SetSendCodecs(data->codecs()); if (!media_channel()->SetSendCodecs(data->codecs())) {
SafeSetError("Failed to set data send codecs.", error_desc);
ret = false;
}
} }
} else { } else {
// If the remote data doesn't have codecs and isn't an update, it // If the remote data doesn't have codecs and isn't an update, it
@@ -2661,17 +2765,24 @@ bool DataChannel::SetRemoteContent_w(const MediaContentDescription* content,
// Set remote video codecs (what the other side wants to receive). // Set remote video codecs (what the other side wants to receive).
if (action != CA_UPDATE || data->has_codecs()) { if (action != CA_UPDATE || data->has_codecs()) {
ret &= media_channel()->SetSendCodecs(data->codecs()); if (!media_channel()->SetSendCodecs(data->codecs())) {
SafeSetError("Failed to set data send codecs.", error_desc);
ret = false;
}
} }
if (ret) { if (ret) {
ret &= SetBaseRemoteContent_w(content, action); ret &= SetBaseRemoteContent_w(content, action, error_desc);
} }
if (action != CA_UPDATE) { if (action != CA_UPDATE) {
int bandwidth_bps = data->bandwidth(); int bandwidth_bps = data->bandwidth();
bool auto_bandwidth = (bandwidth_bps == kAutoBandwidth); if (!media_channel()->SetMaxSendBandwidth(bandwidth_bps)) {
ret &= media_channel()->SetSendBandwidth(auto_bandwidth, bandwidth_bps); std::ostringstream desc;
desc << "Failed to set max send bandwidth for data content.";
SafeSetError(desc.str(), error_desc);
ret = false;
}
} }
} }

View File

@@ -111,10 +111,11 @@ class BaseChannel
// Channel control // Channel control
bool SetLocalContent(const MediaContentDescription* content, bool SetLocalContent(const MediaContentDescription* content,
ContentAction action); ContentAction action,
std::string* error_desc);
bool SetRemoteContent(const MediaContentDescription* content, bool SetRemoteContent(const MediaContentDescription* content,
ContentAction action); ContentAction action,
bool SetMaxSendBandwidth(int max_bandwidth); std::string* error_desc);
bool Enable(bool enable); bool Enable(bool enable);
// Mute sending media on the stream with SSRC |ssrc| // Mute sending media on the stream with SSRC |ssrc|
@@ -306,24 +307,35 @@ class BaseChannel
virtual const ContentInfo* GetFirstContent( virtual const ContentInfo* GetFirstContent(
const SessionDescription* sdesc) = 0; const SessionDescription* sdesc) = 0;
bool UpdateLocalStreams_w(const std::vector<StreamParams>& streams, bool UpdateLocalStreams_w(const std::vector<StreamParams>& streams,
ContentAction action); ContentAction action,
std::string* error_desc);
bool UpdateRemoteStreams_w(const std::vector<StreamParams>& streams, bool UpdateRemoteStreams_w(const std::vector<StreamParams>& streams,
ContentAction action); ContentAction action,
std::string* error_desc);
bool SetBaseLocalContent_w(const MediaContentDescription* content, bool SetBaseLocalContent_w(const MediaContentDescription* content,
ContentAction action); ContentAction action,
std::string* error_desc);
virtual bool SetLocalContent_w(const MediaContentDescription* content, virtual bool SetLocalContent_w(const MediaContentDescription* content,
ContentAction action) = 0; ContentAction action,
std::string* error_desc) = 0;
bool SetBaseRemoteContent_w(const MediaContentDescription* content, bool SetBaseRemoteContent_w(const MediaContentDescription* content,
ContentAction action); ContentAction action,
std::string* error_desc);
virtual bool SetRemoteContent_w(const MediaContentDescription* content, virtual bool SetRemoteContent_w(const MediaContentDescription* content,
ContentAction action) = 0; ContentAction action,
std::string* error_desc) = 0;
bool CheckSrtpConfig(const std::vector<CryptoParams>& cryptos, bool* dtls); bool CheckSrtpConfig(const std::vector<CryptoParams>& cryptos,
bool SetSrtp_w(const std::vector<CryptoParams>& params, ContentAction action, bool* dtls,
ContentSource src); std::string* error_desc);
bool SetRtcpMux_w(bool enable, ContentAction action, ContentSource src); bool SetSrtp_w(const std::vector<CryptoParams>& params,
ContentAction action,
virtual bool SetMaxSendBandwidth_w(int max_bandwidth); ContentSource src,
std::string* error_desc);
bool SetRtcpMux_w(bool enable,
ContentAction action,
ContentSource src,
std::string* error_desc);
// From MessageHandler // From MessageHandler
virtual void OnMessage(talk_base::Message* pmsg); virtual void OnMessage(talk_base::Message* pmsg);
@@ -450,9 +462,11 @@ class VoiceChannel : public BaseChannel {
virtual void ChangeState(); virtual void ChangeState();
virtual const ContentInfo* GetFirstContent(const SessionDescription* sdesc); virtual const ContentInfo* GetFirstContent(const SessionDescription* sdesc);
virtual bool SetLocalContent_w(const MediaContentDescription* content, virtual bool SetLocalContent_w(const MediaContentDescription* content,
ContentAction action); ContentAction action,
std::string* error_desc);
virtual bool SetRemoteContent_w(const MediaContentDescription* content, virtual bool SetRemoteContent_w(const MediaContentDescription* content,
ContentAction action); ContentAction action,
std::string* error_desc);
bool SetRingbackTone_w(const void* buf, int len); bool SetRingbackTone_w(const void* buf, int len);
bool PlayRingbackTone_w(uint32 ssrc, bool play, bool loop); bool PlayRingbackTone_w(uint32 ssrc, bool play, bool loop);
void HandleEarlyMediaTimeout(); void HandleEarlyMediaTimeout();
@@ -549,9 +563,11 @@ class VideoChannel : public BaseChannel {
virtual void ChangeState(); virtual void ChangeState();
virtual const ContentInfo* GetFirstContent(const SessionDescription* sdesc); virtual const ContentInfo* GetFirstContent(const SessionDescription* sdesc);
virtual bool SetLocalContent_w(const MediaContentDescription* content, virtual bool SetLocalContent_w(const MediaContentDescription* content,
ContentAction action); ContentAction action,
std::string* error_desc);
virtual bool SetRemoteContent_w(const MediaContentDescription* content, virtual bool SetRemoteContent_w(const MediaContentDescription* content,
ContentAction action); ContentAction action,
std::string* error_desc);
void SendIntraFrame_w() { void SendIntraFrame_w() {
media_channel()->SendIntraFrame(); media_channel()->SendIntraFrame();
} }
@@ -677,15 +693,18 @@ class DataChannel : public BaseChannel {
// If data_channel_type_ is DCT_NONE, set it. Otherwise, check that // If data_channel_type_ is DCT_NONE, set it. Otherwise, check that
// it's the same as what was set previously. Returns false if it's // it's the same as what was set previously. Returns false if it's
// set to one type one type and changed to another type later. // set to one type one type and changed to another type later.
bool SetDataChannelType(DataChannelType new_data_channel_type); bool SetDataChannelType(DataChannelType new_data_channel_type,
std::string* error_desc);
// Same as SetDataChannelType, but extracts the type from the // Same as SetDataChannelType, but extracts the type from the
// DataContentDescription. // DataContentDescription.
bool SetDataChannelTypeFromContent(const DataContentDescription* content); bool SetDataChannelTypeFromContent(const DataContentDescription* content,
virtual bool SetMaxSendBandwidth_w(int max_bandwidth); std::string* error_desc);
virtual bool SetLocalContent_w(const MediaContentDescription* content, virtual bool SetLocalContent_w(const MediaContentDescription* content,
ContentAction action); ContentAction action,
std::string* error_desc);
virtual bool SetRemoteContent_w(const MediaContentDescription* content, virtual bool SetRemoteContent_w(const MediaContentDescription* content,
ContentAction action); ContentAction action,
std::string* error_desc);
virtual void ChangeState(); virtual void ChangeState();
virtual bool WantsPacket(bool rtcp, talk_base::Buffer* packet); virtual bool WantsPacket(bool rtcp, talk_base::Buffer* packet);

View File

@@ -318,14 +318,17 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
} }
bool SendInitiate() { bool SendInitiate() {
bool result = channel1_->SetLocalContent(&local_media_content1_, CA_OFFER); bool result = channel1_->SetLocalContent(&local_media_content1_,
CA_OFFER, NULL);
if (result) { if (result) {
channel1_->Enable(true); channel1_->Enable(true);
result = channel2_->SetRemoteContent(&remote_media_content1_, CA_OFFER); result = channel2_->SetRemoteContent(&remote_media_content1_,
CA_OFFER, NULL);
if (result) { if (result) {
session1_.Connect(&session2_); session1_.Connect(&session2_);
result = channel2_->SetLocalContent(&local_media_content2_, CA_ANSWER); result = channel2_->SetLocalContent(&local_media_content2_,
CA_ANSWER, NULL);
} }
} }
return result; return result;
@@ -333,34 +336,39 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
bool SendAccept() { bool SendAccept() {
channel2_->Enable(true); channel2_->Enable(true);
return channel1_->SetRemoteContent(&remote_media_content2_, CA_ANSWER); return channel1_->SetRemoteContent(&remote_media_content2_,
CA_ANSWER, NULL);
} }
bool SendOffer() { bool SendOffer() {
bool result = channel1_->SetLocalContent(&local_media_content1_, CA_OFFER); bool result = channel1_->SetLocalContent(&local_media_content1_,
CA_OFFER, NULL);
if (result) { if (result) {
channel1_->Enable(true); channel1_->Enable(true);
result = channel2_->SetRemoteContent(&remote_media_content1_, CA_OFFER); result = channel2_->SetRemoteContent(&remote_media_content1_,
CA_OFFER, NULL);
} }
return result; return result;
} }
bool SendProvisionalAnswer() { bool SendProvisionalAnswer() {
bool result = channel2_->SetLocalContent(&local_media_content2_, bool result = channel2_->SetLocalContent(&local_media_content2_,
CA_PRANSWER); CA_PRANSWER, NULL);
if (result) { if (result) {
channel2_->Enable(true); channel2_->Enable(true);
result = channel1_->SetRemoteContent(&remote_media_content2_, result = channel1_->SetRemoteContent(&remote_media_content2_,
CA_PRANSWER); CA_PRANSWER, NULL);
session1_.Connect(&session2_); session1_.Connect(&session2_);
} }
return result; return result;
} }
bool SendFinalAnswer() { bool SendFinalAnswer() {
bool result = channel2_->SetLocalContent(&local_media_content2_, CA_ANSWER); bool result = channel2_->SetLocalContent(&local_media_content2_,
CA_ANSWER, NULL);
if (result) if (result)
result = channel1_->SetRemoteContent(&remote_media_content2_, CA_ANSWER); result = channel1_->SetRemoteContent(&remote_media_content2_,
CA_ANSWER, NULL);
return result; return result;
} }
@@ -591,9 +599,9 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
CreateChannels(0, 0); CreateChannels(0, 0);
typename T::Content content; typename T::Content content;
CreateContent(0, kPcmuCodec, kH264Codec, &content); CreateContent(0, kPcmuCodec, kH264Codec, &content);
EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER)); EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER, NULL));
EXPECT_EQ(0U, media_channel1_->codecs().size()); EXPECT_EQ(0U, media_channel1_->codecs().size());
EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER)); EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER, NULL));
ASSERT_EQ(1U, media_channel1_->codecs().size()); ASSERT_EQ(1U, media_channel1_->codecs().size());
EXPECT_TRUE(CodecMatches(content.codecs()[0], EXPECT_TRUE(CodecMatches(content.codecs()[0],
media_channel1_->codecs()[0])); media_channel1_->codecs()[0]));
@@ -604,10 +612,10 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
void TestSetContentsNullOffer() { void TestSetContentsNullOffer() {
CreateChannels(0, 0); CreateChannels(0, 0);
typename T::Content content; typename T::Content content;
EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER)); EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER, NULL));
CreateContent(0, kPcmuCodec, kH264Codec, &content); CreateContent(0, kPcmuCodec, kH264Codec, &content);
EXPECT_EQ(0U, media_channel1_->codecs().size()); EXPECT_EQ(0U, media_channel1_->codecs().size());
EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER)); EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER, NULL));
ASSERT_EQ(1U, media_channel1_->codecs().size()); ASSERT_EQ(1U, media_channel1_->codecs().size());
EXPECT_TRUE(CodecMatches(content.codecs()[0], EXPECT_TRUE(CodecMatches(content.codecs()[0],
media_channel1_->codecs()[0])); media_channel1_->codecs()[0]));
@@ -623,13 +631,13 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
CreateContent(0, kPcmuCodec, kH264Codec, &content); CreateContent(0, kPcmuCodec, kH264Codec, &content);
// Both sides agree on mux. Should no longer be a separate RTCP channel. // Both sides agree on mux. Should no longer be a separate RTCP channel.
content.set_rtcp_mux(true); content.set_rtcp_mux(true);
EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER)); EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER, NULL));
EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER)); EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER, NULL));
EXPECT_TRUE(channel1_->rtcp_transport_channel() == NULL); EXPECT_TRUE(channel1_->rtcp_transport_channel() == NULL);
// Only initiator supports mux. Should still have a separate RTCP channel. // Only initiator supports mux. Should still have a separate RTCP channel.
EXPECT_TRUE(channel2_->SetLocalContent(&content, CA_OFFER)); EXPECT_TRUE(channel2_->SetLocalContent(&content, CA_OFFER, NULL));
content.set_rtcp_mux(false); content.set_rtcp_mux(false);
EXPECT_TRUE(channel2_->SetRemoteContent(&content, CA_ANSWER)); EXPECT_TRUE(channel2_->SetRemoteContent(&content, CA_ANSWER, NULL));
EXPECT_TRUE(channel2_->rtcp_transport_channel() != NULL); EXPECT_TRUE(channel2_->rtcp_transport_channel() != NULL);
} }
@@ -642,17 +650,17 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
typename T::Content content; typename T::Content content;
CreateContent(0, kPcmuCodec, kH264Codec, &content); CreateContent(0, kPcmuCodec, kH264Codec, &content);
content.set_rtcp_mux(true); content.set_rtcp_mux(true);
EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER)); EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER, NULL));
EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_PRANSWER)); EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_PRANSWER, NULL));
EXPECT_TRUE(channel1_->rtcp_transport_channel() != NULL); EXPECT_TRUE(channel1_->rtcp_transport_channel() != NULL);
EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER)); EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER, NULL));
// Both sides agree on mux. Should no longer be a separate RTCP channel. // Both sides agree on mux. Should no longer be a separate RTCP channel.
EXPECT_TRUE(channel1_->rtcp_transport_channel() == NULL); EXPECT_TRUE(channel1_->rtcp_transport_channel() == NULL);
// Only initiator supports mux. Should still have a separate RTCP channel. // Only initiator supports mux. Should still have a separate RTCP channel.
EXPECT_TRUE(channel2_->SetLocalContent(&content, CA_OFFER)); EXPECT_TRUE(channel2_->SetLocalContent(&content, CA_OFFER, NULL));
content.set_rtcp_mux(false); content.set_rtcp_mux(false);
EXPECT_TRUE(channel2_->SetRemoteContent(&content, CA_PRANSWER)); EXPECT_TRUE(channel2_->SetRemoteContent(&content, CA_PRANSWER, NULL));
EXPECT_TRUE(channel2_->SetRemoteContent(&content, CA_ANSWER)); EXPECT_TRUE(channel2_->SetRemoteContent(&content, CA_ANSWER, NULL));
EXPECT_TRUE(channel2_->rtcp_transport_channel() != NULL); EXPECT_TRUE(channel2_->rtcp_transport_channel() != NULL);
} }
@@ -663,7 +671,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
typename T::Content content; typename T::Content content;
CreateContent(0, kPcmuCodec, kH264Codec, &content); CreateContent(0, kPcmuCodec, kH264Codec, &content);
content.set_buffered_mode_latency(101); content.set_buffered_mode_latency(101);
EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER)); EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER, NULL));
EXPECT_EQ(0U, media_channel1_->codecs().size()); EXPECT_EQ(0U, media_channel1_->codecs().size());
cricket::VideoOptions options; cricket::VideoOptions options;
ASSERT_TRUE(media_channel1_->GetOptions(&options)); ASSERT_TRUE(media_channel1_->GetOptions(&options));
@@ -671,7 +679,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
EXPECT_TRUE(options.buffered_mode_latency.Get(&latency)); EXPECT_TRUE(options.buffered_mode_latency.Get(&latency));
EXPECT_EQ(101, latency); EXPECT_EQ(101, latency);
content.set_buffered_mode_latency(102); content.set_buffered_mode_latency(102);
EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER)); EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER, NULL));
ASSERT_EQ(1U, media_channel1_->codecs().size()); ASSERT_EQ(1U, media_channel1_->codecs().size());
EXPECT_TRUE(CodecMatches(content.codecs()[0], EXPECT_TRUE(CodecMatches(content.codecs()[0],
media_channel1_->codecs()[0])); media_channel1_->codecs()[0]));
@@ -688,8 +696,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
kPcmuCodec, kH264Codec, kPcmuCodec, kH264Codec,
&content); &content);
EXPECT_EQ(0U, media_channel1_->codecs().size()); EXPECT_EQ(0U, media_channel1_->codecs().size());
EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER)); EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER, NULL));
EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER)); EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER, NULL));
ASSERT_EQ(1U, media_channel1_->codecs().size()); ASSERT_EQ(1U, media_channel1_->codecs().size());
EXPECT_TRUE(CodecMatches(content.codecs()[0], EXPECT_TRUE(CodecMatches(content.codecs()[0],
media_channel1_->codecs()[0])); media_channel1_->codecs()[0]));
@@ -698,14 +706,14 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
update_content.set_partial(true); update_content.set_partial(true);
CreateContent(0, kIsacCodec, kH264SvcCodec, CreateContent(0, kIsacCodec, kH264SvcCodec,
&update_content); &update_content);
EXPECT_TRUE(channel1_->SetRemoteContent(&update_content, CA_UPDATE)); EXPECT_TRUE(channel1_->SetRemoteContent(&update_content, CA_UPDATE, NULL));
ASSERT_EQ(1U, media_channel1_->codecs().size()); ASSERT_EQ(1U, media_channel1_->codecs().size());
EXPECT_TRUE(CodecMatches(update_content.codecs()[0], EXPECT_TRUE(CodecMatches(update_content.codecs()[0],
media_channel1_->codecs()[0])); media_channel1_->codecs()[0]));
// Now update without any codecs. This is ignored. // Now update without any codecs. This is ignored.
typename T::Content empty_content; typename T::Content empty_content;
empty_content.set_partial(true); empty_content.set_partial(true);
EXPECT_TRUE(channel1_->SetRemoteContent(&empty_content, CA_UPDATE)); EXPECT_TRUE(channel1_->SetRemoteContent(&empty_content, CA_UPDATE, NULL));
ASSERT_EQ(1U, media_channel1_->codecs().size()); ASSERT_EQ(1U, media_channel1_->codecs().size());
EXPECT_TRUE(CodecMatches(update_content.codecs()[0], EXPECT_TRUE(CodecMatches(update_content.codecs()[0],
media_channel1_->codecs()[0])); media_channel1_->codecs()[0]));
@@ -751,7 +759,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
CreateContent(0, kPcmuCodec, kH264Codec, &content1); CreateContent(0, kPcmuCodec, kH264Codec, &content1);
content1.AddStream(stream1); content1.AddStream(stream1);
EXPECT_EQ(0u, media_channel1_->send_streams().size()); EXPECT_EQ(0u, media_channel1_->send_streams().size());
EXPECT_TRUE(channel1_->SetLocalContent(&content1, CA_OFFER)); EXPECT_TRUE(channel1_->SetLocalContent(&content1, CA_OFFER, NULL));
ASSERT_EQ(1u, media_channel1_->send_streams().size()); ASSERT_EQ(1u, media_channel1_->send_streams().size());
EXPECT_EQ(stream1, media_channel1_->send_streams()[0]); EXPECT_EQ(stream1, media_channel1_->send_streams()[0]);
@@ -762,7 +770,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
content2.AddStream(stream2); content2.AddStream(stream2);
content2.AddStream(stream3); content2.AddStream(stream3);
content2.set_partial(true); content2.set_partial(true);
EXPECT_TRUE(channel1_->SetLocalContent(&content2, CA_UPDATE)); EXPECT_TRUE(channel1_->SetLocalContent(&content2, CA_UPDATE, NULL));
ASSERT_EQ(3u, media_channel1_->send_streams().size()); ASSERT_EQ(3u, media_channel1_->send_streams().size());
EXPECT_EQ(stream1, media_channel1_->send_streams()[0]); EXPECT_EQ(stream1, media_channel1_->send_streams()[0]);
EXPECT_EQ(stream2, media_channel1_->send_streams()[1]); EXPECT_EQ(stream2, media_channel1_->send_streams()[1]);
@@ -774,7 +782,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
stream1.ssrcs.clear(); stream1.ssrcs.clear();
content3.AddStream(stream1); content3.AddStream(stream1);
content3.set_partial(true); content3.set_partial(true);
EXPECT_TRUE(channel1_->SetLocalContent(&content3, CA_UPDATE)); EXPECT_TRUE(channel1_->SetLocalContent(&content3, CA_UPDATE, NULL));
ASSERT_EQ(2u, media_channel1_->send_streams().size()); ASSERT_EQ(2u, media_channel1_->send_streams().size());
EXPECT_EQ(stream2, media_channel1_->send_streams()[0]); EXPECT_EQ(stream2, media_channel1_->send_streams()[0]);
EXPECT_EQ(stream3, media_channel1_->send_streams()[1]); EXPECT_EQ(stream3, media_channel1_->send_streams()[1]);
@@ -784,7 +792,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
typename T::Content content4; typename T::Content content4;
content4.AddStream(stream2); content4.AddStream(stream2);
content4.set_partial(true); content4.set_partial(true);
EXPECT_TRUE(channel1_->SetLocalContent(&content4, CA_UPDATE)); EXPECT_TRUE(channel1_->SetLocalContent(&content4, CA_UPDATE, NULL));
ASSERT_EQ(2u, media_channel1_->send_streams().size()); ASSERT_EQ(2u, media_channel1_->send_streams().size());
EXPECT_EQ(stream2, media_channel1_->send_streams()[0]); EXPECT_EQ(stream2, media_channel1_->send_streams()[0]);
EXPECT_EQ(stream3, media_channel1_->send_streams()[1]); EXPECT_EQ(stream3, media_channel1_->send_streams()[1]);
@@ -818,7 +826,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
CreateContent(0, kPcmuCodec, kH264Codec, &content1); CreateContent(0, kPcmuCodec, kH264Codec, &content1);
content1.AddStream(stream1); content1.AddStream(stream1);
EXPECT_EQ(0u, media_channel1_->recv_streams().size()); EXPECT_EQ(0u, media_channel1_->recv_streams().size());
EXPECT_TRUE(channel1_->SetRemoteContent(&content1, CA_OFFER)); EXPECT_TRUE(channel1_->SetRemoteContent(&content1, CA_OFFER, NULL));
ASSERT_EQ(1u, media_channel1_->codecs().size()); ASSERT_EQ(1u, media_channel1_->codecs().size());
ASSERT_EQ(1u, media_channel1_->recv_streams().size()); ASSERT_EQ(1u, media_channel1_->recv_streams().size());
@@ -830,7 +838,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
content2.AddStream(stream2); content2.AddStream(stream2);
content2.AddStream(stream3); content2.AddStream(stream3);
content2.set_partial(true); content2.set_partial(true);
EXPECT_TRUE(channel1_->SetRemoteContent(&content2, CA_UPDATE)); EXPECT_TRUE(channel1_->SetRemoteContent(&content2, CA_UPDATE, NULL));
ASSERT_EQ(3u, media_channel1_->recv_streams().size()); ASSERT_EQ(3u, media_channel1_->recv_streams().size());
EXPECT_EQ(stream1, media_channel1_->recv_streams()[0]); EXPECT_EQ(stream1, media_channel1_->recv_streams()[0]);
EXPECT_EQ(stream2, media_channel1_->recv_streams()[1]); EXPECT_EQ(stream2, media_channel1_->recv_streams()[1]);
@@ -842,7 +850,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
stream1.ssrcs.clear(); stream1.ssrcs.clear();
content3.AddStream(stream1); content3.AddStream(stream1);
content3.set_partial(true); content3.set_partial(true);
EXPECT_TRUE(channel1_->SetRemoteContent(&content3, CA_UPDATE)); EXPECT_TRUE(channel1_->SetRemoteContent(&content3, CA_UPDATE, NULL));
ASSERT_EQ(2u, media_channel1_->recv_streams().size()); ASSERT_EQ(2u, media_channel1_->recv_streams().size());
EXPECT_EQ(stream2, media_channel1_->recv_streams()[0]); EXPECT_EQ(stream2, media_channel1_->recv_streams()[0]);
EXPECT_EQ(stream3, media_channel1_->recv_streams()[1]); EXPECT_EQ(stream3, media_channel1_->recv_streams()[1]);
@@ -852,7 +860,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
typename T::Content content4; typename T::Content content4;
content4.AddStream(stream2); content4.AddStream(stream2);
content4.set_partial(true); content4.set_partial(true);
EXPECT_TRUE(channel1_->SetRemoteContent(&content4, CA_UPDATE)); EXPECT_TRUE(channel1_->SetRemoteContent(&content4, CA_UPDATE, NULL));
ASSERT_EQ(2u, media_channel1_->recv_streams().size()); ASSERT_EQ(2u, media_channel1_->recv_streams().size());
EXPECT_EQ(stream2, media_channel1_->recv_streams()[0]); EXPECT_EQ(stream2, media_channel1_->recv_streams()[0]);
EXPECT_EQ(stream3, media_channel1_->recv_streams()[1]); EXPECT_EQ(stream3, media_channel1_->recv_streams()[1]);
@@ -879,20 +887,20 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
typename T::Content content1; typename T::Content content1;
CreateContent(0, kPcmuCodec, kH264Codec, &content1); CreateContent(0, kPcmuCodec, kH264Codec, &content1);
content1.AddStream(stream1); content1.AddStream(stream1);
EXPECT_TRUE(channel1_->SetLocalContent(&content1, CA_OFFER)); EXPECT_TRUE(channel1_->SetLocalContent(&content1, CA_OFFER, NULL));
EXPECT_TRUE(channel1_->Enable(true)); EXPECT_TRUE(channel1_->Enable(true));
EXPECT_EQ(1u, media_channel1_->send_streams().size()); EXPECT_EQ(1u, media_channel1_->send_streams().size());
EXPECT_TRUE(channel2_->SetRemoteContent(&content1, CA_OFFER)); EXPECT_TRUE(channel2_->SetRemoteContent(&content1, CA_OFFER, NULL));
EXPECT_EQ(1u, media_channel2_->recv_streams().size()); EXPECT_EQ(1u, media_channel2_->recv_streams().size());
session1_.Connect(&session2_); session1_.Connect(&session2_);
// Channel 2 do not send anything. // Channel 2 do not send anything.
typename T::Content content2; typename T::Content content2;
CreateContent(0, kPcmuCodec, kH264Codec, &content2); CreateContent(0, kPcmuCodec, kH264Codec, &content2);
EXPECT_TRUE(channel1_->SetRemoteContent(&content2, CA_ANSWER)); EXPECT_TRUE(channel1_->SetRemoteContent(&content2, CA_ANSWER, NULL));
EXPECT_EQ(0u, media_channel1_->recv_streams().size()); EXPECT_EQ(0u, media_channel1_->recv_streams().size());
EXPECT_TRUE(channel2_->SetLocalContent(&content2, CA_ANSWER)); EXPECT_TRUE(channel2_->SetLocalContent(&content2, CA_ANSWER, NULL));
EXPECT_TRUE(channel2_->Enable(true)); EXPECT_TRUE(channel2_->Enable(true));
EXPECT_EQ(0u, media_channel2_->send_streams().size()); EXPECT_EQ(0u, media_channel2_->send_streams().size());
@@ -903,21 +911,21 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
typename T::Content content3; typename T::Content content3;
CreateContent(SECURE, kPcmuCodec, kH264Codec, &content3); CreateContent(SECURE, kPcmuCodec, kH264Codec, &content3);
content3.AddStream(stream2); content3.AddStream(stream2);
EXPECT_TRUE(channel2_->SetLocalContent(&content3, CA_OFFER)); EXPECT_TRUE(channel2_->SetLocalContent(&content3, CA_OFFER, NULL));
ASSERT_EQ(1u, media_channel2_->send_streams().size()); ASSERT_EQ(1u, media_channel2_->send_streams().size());
EXPECT_EQ(stream2, media_channel2_->send_streams()[0]); EXPECT_EQ(stream2, media_channel2_->send_streams()[0]);
EXPECT_TRUE(channel1_->SetRemoteContent(&content3, CA_OFFER)); EXPECT_TRUE(channel1_->SetRemoteContent(&content3, CA_OFFER, NULL));
ASSERT_EQ(1u, media_channel1_->recv_streams().size()); ASSERT_EQ(1u, media_channel1_->recv_streams().size());
EXPECT_EQ(stream2, media_channel1_->recv_streams()[0]); EXPECT_EQ(stream2, media_channel1_->recv_streams()[0]);
// Channel 1 replies but stop sending stream1. // Channel 1 replies but stop sending stream1.
typename T::Content content4; typename T::Content content4;
CreateContent(SECURE, kPcmuCodec, kH264Codec, &content4); CreateContent(SECURE, kPcmuCodec, kH264Codec, &content4);
EXPECT_TRUE(channel1_->SetLocalContent(&content4, CA_ANSWER)); EXPECT_TRUE(channel1_->SetLocalContent(&content4, CA_ANSWER, NULL));
EXPECT_EQ(0u, media_channel1_->send_streams().size()); EXPECT_EQ(0u, media_channel1_->send_streams().size());
EXPECT_TRUE(channel2_->SetRemoteContent(&content4, CA_ANSWER)); EXPECT_TRUE(channel2_->SetRemoteContent(&content4, CA_ANSWER, NULL));
EXPECT_EQ(0u, media_channel2_->recv_streams().size()); EXPECT_EQ(0u, media_channel2_->recv_streams().size());
EXPECT_TRUE(channel1_->secure()); EXPECT_TRUE(channel1_->secure());
@@ -936,13 +944,16 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
EXPECT_TRUE(channel1_->Enable(true)); EXPECT_TRUE(channel1_->Enable(true));
EXPECT_FALSE(media_channel1_->playout()); EXPECT_FALSE(media_channel1_->playout());
EXPECT_FALSE(media_channel1_->sending()); EXPECT_FALSE(media_channel1_->sending());
EXPECT_TRUE(channel1_->SetLocalContent(&local_media_content1_, CA_OFFER)); EXPECT_TRUE(channel1_->SetLocalContent(&local_media_content1_,
CA_OFFER, NULL));
EXPECT_TRUE(media_channel1_->playout()); EXPECT_TRUE(media_channel1_->playout());
EXPECT_FALSE(media_channel1_->sending()); EXPECT_FALSE(media_channel1_->sending());
EXPECT_TRUE(channel2_->SetRemoteContent(&local_media_content1_, CA_OFFER)); EXPECT_TRUE(channel2_->SetRemoteContent(&local_media_content1_,
CA_OFFER, NULL));
EXPECT_FALSE(media_channel2_->playout()); EXPECT_FALSE(media_channel2_->playout());
EXPECT_FALSE(media_channel2_->sending()); EXPECT_FALSE(media_channel2_->sending());
EXPECT_TRUE(channel2_->SetLocalContent(&local_media_content2_, CA_ANSWER)); EXPECT_TRUE(channel2_->SetLocalContent(&local_media_content2_,
CA_ANSWER, NULL));
EXPECT_FALSE(media_channel2_->playout()); EXPECT_FALSE(media_channel2_->playout());
EXPECT_FALSE(media_channel2_->sending()); EXPECT_FALSE(media_channel2_->sending());
session1_.Connect(&session2_); session1_.Connect(&session2_);
@@ -953,7 +964,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
EXPECT_TRUE(channel2_->Enable(true)); EXPECT_TRUE(channel2_->Enable(true));
EXPECT_TRUE(media_channel2_->playout()); EXPECT_TRUE(media_channel2_->playout());
EXPECT_TRUE(media_channel2_->sending()); EXPECT_TRUE(media_channel2_->sending());
EXPECT_TRUE(channel1_->SetRemoteContent(&local_media_content2_, CA_ANSWER)); EXPECT_TRUE(channel1_->SetRemoteContent(&local_media_content2_,
CA_ANSWER, NULL));
EXPECT_TRUE(media_channel1_->playout()); EXPECT_TRUE(media_channel1_->playout());
EXPECT_TRUE(media_channel1_->sending()); EXPECT_TRUE(media_channel1_->sending());
} }
@@ -998,10 +1010,10 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
EXPECT_FALSE(media_channel2_->playout()); EXPECT_FALSE(media_channel2_->playout());
EXPECT_FALSE(media_channel2_->sending()); EXPECT_FALSE(media_channel2_->sending());
EXPECT_TRUE(channel1_->SetLocalContent(&content1, CA_OFFER)); EXPECT_TRUE(channel1_->SetLocalContent(&content1, CA_OFFER, NULL));
EXPECT_TRUE(channel2_->SetRemoteContent(&content1, CA_OFFER)); EXPECT_TRUE(channel2_->SetRemoteContent(&content1, CA_OFFER, NULL));
EXPECT_TRUE(channel2_->SetLocalContent(&content2, CA_PRANSWER)); EXPECT_TRUE(channel2_->SetLocalContent(&content2, CA_PRANSWER, NULL));
EXPECT_TRUE(channel1_->SetRemoteContent(&content2, CA_PRANSWER)); EXPECT_TRUE(channel1_->SetRemoteContent(&content2, CA_PRANSWER, NULL));
session1_.Connect(&session2_); session1_.Connect(&session2_);
EXPECT_TRUE(media_channel1_->playout()); EXPECT_TRUE(media_channel1_->playout());
@@ -1011,8 +1023,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
// Update |content2| to be RecvOnly. // Update |content2| to be RecvOnly.
content2.set_direction(cricket::MD_RECVONLY); content2.set_direction(cricket::MD_RECVONLY);
EXPECT_TRUE(channel2_->SetLocalContent(&content2, CA_PRANSWER)); EXPECT_TRUE(channel2_->SetLocalContent(&content2, CA_PRANSWER, NULL));
EXPECT_TRUE(channel1_->SetRemoteContent(&content2, CA_PRANSWER)); EXPECT_TRUE(channel1_->SetRemoteContent(&content2, CA_PRANSWER, NULL));
EXPECT_TRUE(media_channel1_->playout()); EXPECT_TRUE(media_channel1_->playout());
EXPECT_TRUE(media_channel1_->sending()); EXPECT_TRUE(media_channel1_->sending());
@@ -1021,8 +1033,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
// Update |content2| to be SendRecv. // Update |content2| to be SendRecv.
content2.set_direction(cricket::MD_SENDRECV); content2.set_direction(cricket::MD_SENDRECV);
EXPECT_TRUE(channel2_->SetLocalContent(&content2, CA_ANSWER)); EXPECT_TRUE(channel2_->SetLocalContent(&content2, CA_ANSWER, NULL));
EXPECT_TRUE(channel1_->SetRemoteContent(&content2, CA_ANSWER)); EXPECT_TRUE(channel1_->SetRemoteContent(&content2, CA_ANSWER, NULL));
EXPECT_TRUE(media_channel1_->playout()); EXPECT_TRUE(media_channel1_->playout());
EXPECT_TRUE(media_channel1_->sending()); EXPECT_TRUE(media_channel1_->sending());
@@ -1587,21 +1599,21 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
// Test failures in SetLocalContent. // Test failures in SetLocalContent.
media_channel1_->set_fail_set_recv_codecs(true); media_channel1_->set_fail_set_recv_codecs(true);
session1_.SetError(cricket::BaseSession::ERROR_NONE); session1_.SetError(cricket::BaseSession::ERROR_NONE, "");
session1_.SetState(cricket::Session::STATE_SENTINITIATE); session1_.SetState(cricket::Session::STATE_SENTINITIATE);
EXPECT_EQ(cricket::BaseSession::ERROR_CONTENT, session1_.error()); EXPECT_EQ(cricket::BaseSession::ERROR_CONTENT, session1_.error());
media_channel1_->set_fail_set_recv_codecs(true); media_channel1_->set_fail_set_recv_codecs(true);
session1_.SetError(cricket::BaseSession::ERROR_NONE); session1_.SetError(cricket::BaseSession::ERROR_NONE, "");
session1_.SetState(cricket::Session::STATE_SENTACCEPT); session1_.SetState(cricket::Session::STATE_SENTACCEPT);
EXPECT_EQ(cricket::BaseSession::ERROR_CONTENT, session1_.error()); EXPECT_EQ(cricket::BaseSession::ERROR_CONTENT, session1_.error());
// Test failures in SetRemoteContent. // Test failures in SetRemoteContent.
media_channel1_->set_fail_set_send_codecs(true); media_channel1_->set_fail_set_send_codecs(true);
session1_.SetError(cricket::BaseSession::ERROR_NONE); session1_.SetError(cricket::BaseSession::ERROR_NONE, "");
session1_.SetState(cricket::Session::STATE_RECEIVEDINITIATE); session1_.SetState(cricket::Session::STATE_RECEIVEDINITIATE);
EXPECT_EQ(cricket::BaseSession::ERROR_CONTENT, session1_.error()); EXPECT_EQ(cricket::BaseSession::ERROR_CONTENT, session1_.error());
media_channel1_->set_fail_set_send_codecs(true); media_channel1_->set_fail_set_send_codecs(true);
session1_.SetError(cricket::BaseSession::ERROR_NONE); session1_.SetError(cricket::BaseSession::ERROR_NONE, "");
session1_.SetState(cricket::Session::STATE_RECEIVEDACCEPT); session1_.SetState(cricket::Session::STATE_RECEIVEDACCEPT);
EXPECT_EQ(cricket::BaseSession::ERROR_CONTENT, session1_.error()); EXPECT_EQ(cricket::BaseSession::ERROR_CONTENT, session1_.error());
} }
@@ -1613,7 +1625,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
cricket::SessionDescription* sdesc = CreateSessionDescriptionWithStream(1); cricket::SessionDescription* sdesc = CreateSessionDescriptionWithStream(1);
EXPECT_TRUE(session1_.set_local_description(sdesc)); EXPECT_TRUE(session1_.set_local_description(sdesc));
session1_.SetError(cricket::BaseSession::ERROR_NONE); session1_.SetError(cricket::BaseSession::ERROR_NONE, "");
session1_.SetState(cricket::Session::STATE_SENTINITIATE); session1_.SetState(cricket::Session::STATE_SENTINITIATE);
EXPECT_EQ(cricket::BaseSession::ERROR_NONE, session1_.error()); EXPECT_EQ(cricket::BaseSession::ERROR_NONE, session1_.error());
EXPECT_TRUE(media_channel1_->HasSendStream(1)); EXPECT_TRUE(media_channel1_->HasSendStream(1));
@@ -1635,7 +1647,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
cricket::SessionDescription* sdesc = CreateSessionDescriptionWithStream(1); cricket::SessionDescription* sdesc = CreateSessionDescriptionWithStream(1);
EXPECT_TRUE(session1_.set_remote_description(sdesc)); EXPECT_TRUE(session1_.set_remote_description(sdesc));
session1_.SetError(cricket::BaseSession::ERROR_NONE); session1_.SetError(cricket::BaseSession::ERROR_NONE, "");
session1_.SetState(cricket::Session::STATE_RECEIVEDINITIATE); session1_.SetState(cricket::Session::STATE_RECEIVEDINITIATE);
EXPECT_EQ(cricket::BaseSession::ERROR_NONE, session1_.error()); EXPECT_EQ(cricket::BaseSession::ERROR_NONE, session1_.error());
EXPECT_TRUE(media_channel1_->HasRecvStream(1)); EXPECT_TRUE(media_channel1_->HasRecvStream(1));
@@ -1655,7 +1667,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
cricket::SessionDescription* sdesc = CreateSessionDescriptionWithStream(1); cricket::SessionDescription* sdesc = CreateSessionDescriptionWithStream(1);
EXPECT_TRUE(session1_.set_remote_description(sdesc)); EXPECT_TRUE(session1_.set_remote_description(sdesc));
session1_.SetError(cricket::BaseSession::ERROR_NONE); session1_.SetError(cricket::BaseSession::ERROR_NONE, "");
session1_.SetState(cricket::Session::STATE_RECEIVEDINITIATE); session1_.SetState(cricket::Session::STATE_RECEIVEDINITIATE);
EXPECT_EQ(cricket::BaseSession::ERROR_NONE, session1_.error()); EXPECT_EQ(cricket::BaseSession::ERROR_NONE, session1_.error());
EXPECT_TRUE(media_channel1_->HasRecvStream(1)); EXPECT_TRUE(media_channel1_->HasRecvStream(1));
@@ -1687,7 +1699,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
cricket::SessionDescription* sdesc = CreateSessionDescriptionWithStream(1); cricket::SessionDescription* sdesc = CreateSessionDescriptionWithStream(1);
EXPECT_TRUE(session1_.set_local_description(sdesc)); EXPECT_TRUE(session1_.set_local_description(sdesc));
session1_.SetError(cricket::BaseSession::ERROR_NONE); session1_.SetError(cricket::BaseSession::ERROR_NONE, "");
session1_.SetState(cricket::Session::STATE_SENTINITIATE); session1_.SetState(cricket::Session::STATE_SENTINITIATE);
EXPECT_EQ(cricket::BaseSession::ERROR_NONE, session1_.error()); EXPECT_EQ(cricket::BaseSession::ERROR_NONE, session1_.error());
EXPECT_TRUE(media_channel1_->HasSendStream(1)); EXPECT_TRUE(media_channel1_->HasSendStream(1));
@@ -1810,8 +1822,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
CreateContent(0, kPcmuCodec, kH264Codec, &content); CreateContent(0, kPcmuCodec, kH264Codec, &content);
// Both sides agree on mux. Should no longer be a separate RTCP channel. // Both sides agree on mux. Should no longer be a separate RTCP channel.
content.set_rtcp_mux(true); content.set_rtcp_mux(true);
EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER)); EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER, NULL));
EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER)); EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER, NULL));
EXPECT_TRUE(channel1_->rtcp_transport_channel() == NULL); EXPECT_TRUE(channel1_->rtcp_transport_channel() == NULL);
TransportChannel* rtp = channel1_->transport_channel(); TransportChannel* rtp = channel1_->transport_channel();
EXPECT_FALSE(media_channel1_->ready_to_send()); EXPECT_FALSE(media_channel1_->ready_to_send());

View File

@@ -1024,6 +1024,25 @@ static bool IsDtlsActive(
return current_tdesc->secure(); return current_tdesc->secure();
} }
std::string MediaTypeToString(MediaType type) {
std::string type_str;
switch (type) {
case MEDIA_TYPE_AUDIO:
type_str = "audio";
break;
case MEDIA_TYPE_VIDEO:
type_str = "video";
break;
case MEDIA_TYPE_DATA:
type_str = "data";
break;
default:
ASSERT(false);
break;
}
return type_str;
}
void MediaSessionOptions::AddStream(MediaType type, void MediaSessionOptions::AddStream(MediaType type,
const std::string& id, const std::string& id,
const std::string& sync_label) { const std::string& sync_label) {

View File

@@ -63,6 +63,8 @@ enum MediaType {
MEDIA_TYPE_DATA MEDIA_TYPE_DATA
}; };
std::string MediaTypeToString(MediaType type);
enum MediaContentDirection { enum MediaContentDirection {
MD_INACTIVE, MD_INACTIVE,
MD_SENDONLY, MD_SENDONLY,