Merging BaseSession code into WebRtcSession.
After the TransportController CL, BaseSession does little more than hold a state and an error, and act as an intermediary for the TransportController. So it doesn't make sense for it to be its own class. Review URL: https://codereview.webrtc.org/1397973002 Cr-Commit-Position: refs/heads/master@{#10281}
This commit is contained in:
parent
83210409e0
commit
d59daf8023
@ -1163,32 +1163,31 @@ void PeerConnection::Close() {
|
||||
// streams before the channels are closed.
|
||||
stats_->UpdateStats(kStatsOutputLevelStandard);
|
||||
|
||||
session_->Terminate();
|
||||
session_->Close();
|
||||
}
|
||||
|
||||
void PeerConnection::OnSessionStateChange(cricket::BaseSession* /*session*/,
|
||||
cricket::BaseSession::State state) {
|
||||
void PeerConnection::OnSessionStateChange(WebRtcSession* /*session*/,
|
||||
WebRtcSession::State state) {
|
||||
switch (state) {
|
||||
case cricket::BaseSession::STATE_INIT:
|
||||
case WebRtcSession::STATE_INIT:
|
||||
ChangeSignalingState(PeerConnectionInterface::kStable);
|
||||
break;
|
||||
case cricket::BaseSession::STATE_SENTINITIATE:
|
||||
case WebRtcSession::STATE_SENTOFFER:
|
||||
ChangeSignalingState(PeerConnectionInterface::kHaveLocalOffer);
|
||||
break;
|
||||
case cricket::BaseSession::STATE_SENTPRACCEPT:
|
||||
case WebRtcSession::STATE_SENTPRANSWER:
|
||||
ChangeSignalingState(PeerConnectionInterface::kHaveLocalPrAnswer);
|
||||
break;
|
||||
case cricket::BaseSession::STATE_RECEIVEDINITIATE:
|
||||
case WebRtcSession::STATE_RECEIVEDOFFER:
|
||||
ChangeSignalingState(PeerConnectionInterface::kHaveRemoteOffer);
|
||||
break;
|
||||
case cricket::BaseSession::STATE_RECEIVEDPRACCEPT:
|
||||
case WebRtcSession::STATE_RECEIVEDPRANSWER:
|
||||
ChangeSignalingState(PeerConnectionInterface::kHaveRemotePrAnswer);
|
||||
break;
|
||||
case cricket::BaseSession::STATE_SENTACCEPT:
|
||||
case cricket::BaseSession::STATE_RECEIVEDACCEPT:
|
||||
case WebRtcSession::STATE_INPROGRESS:
|
||||
ChangeSignalingState(PeerConnectionInterface::kStable);
|
||||
break;
|
||||
case cricket::BaseSession::STATE_RECEIVEDTERMINATE:
|
||||
case WebRtcSession::STATE_CLOSED:
|
||||
ChangeSignalingState(PeerConnectionInterface::kClosed);
|
||||
break;
|
||||
default:
|
||||
|
||||
@ -209,8 +209,7 @@ class PeerConnection : public PeerConnectionInterface,
|
||||
void OnIceConnectionReceivingChange(bool receiving) override;
|
||||
|
||||
// Signals from WebRtcSession.
|
||||
void OnSessionStateChange(cricket::BaseSession* session,
|
||||
cricket::BaseSession::State state);
|
||||
void OnSessionStateChange(WebRtcSession* session, WebRtcSession::State state);
|
||||
void ChangeSignalingState(SignalingState signaling_state);
|
||||
|
||||
rtc::Thread* signaling_thread() const {
|
||||
|
||||
@ -70,12 +70,13 @@ typedef TypeForAdd<float> FloatForAdd;
|
||||
typedef TypeForAdd<int64_t> Int64ForAdd;
|
||||
typedef TypeForAdd<int> IntForAdd;
|
||||
|
||||
StatsReport::Id GetTransportIdFromProxy(const cricket::ProxyTransportMap& map,
|
||||
StatsReport::Id GetTransportIdFromProxy(const ProxyTransportMap& map,
|
||||
const std::string& proxy) {
|
||||
RTC_DCHECK(!proxy.empty());
|
||||
cricket::ProxyTransportMap::const_iterator found = map.find(proxy);
|
||||
if (found == map.end())
|
||||
auto found = map.find(proxy);
|
||||
if (found == map.end()) {
|
||||
return StatsReport::Id();
|
||||
}
|
||||
|
||||
return StatsReport::NewComponentId(
|
||||
found->second, cricket::ICE_CANDIDATE_COMPONENT_RTP);
|
||||
@ -677,9 +678,9 @@ void StatsCollector::ExtractSessionInfo() {
|
||||
StatsReport* report = reports_.ReplaceOrAddNew(id);
|
||||
report->set_timestamp(stats_gathering_started_);
|
||||
report->AddBoolean(StatsReport::kStatsValueNameInitiator,
|
||||
pc_->session()->initiator());
|
||||
pc_->session()->initial_offerer());
|
||||
|
||||
cricket::SessionStats stats;
|
||||
SessionStats stats;
|
||||
if (!pc_->session()->GetTransportStats(&stats)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -156,7 +156,7 @@ class StatsCollector {
|
||||
// Raw pointer to the peer connection the statistics are gathered from.
|
||||
PeerConnection* const pc_;
|
||||
double stats_gathering_started_;
|
||||
cricket::ProxyTransportMap proxy_to_transport_;
|
||||
ProxyTransportMap proxy_to_transport_;
|
||||
|
||||
// TODO(tommi): We appear to be holding on to raw pointers to reference
|
||||
// counted objects? We should be using scoped_refptr here.
|
||||
|
||||
@ -95,7 +95,7 @@ class MockWebRtcSession : public webrtc::WebRtcSession {
|
||||
// track.
|
||||
MOCK_METHOD2(GetLocalTrackIdBySsrc, bool(uint32_t, std::string*));
|
||||
MOCK_METHOD2(GetRemoteTrackIdBySsrc, bool(uint32_t, std::string*));
|
||||
MOCK_METHOD1(GetTransportStats, bool(cricket::SessionStats*));
|
||||
MOCK_METHOD1(GetTransportStats, bool(SessionStats*));
|
||||
MOCK_METHOD2(GetLocalCertificate,
|
||||
bool(const std::string& transport_name,
|
||||
rtc::scoped_refptr<rtc::RTCCertificate>* certificate));
|
||||
@ -687,7 +687,7 @@ class StatsCollectorTest : public testing::Test {
|
||||
transport_stats.transport_name = "audio";
|
||||
transport_stats.channel_stats.push_back(channel_stats);
|
||||
|
||||
cricket::SessionStats session_stats;
|
||||
SessionStats session_stats;
|
||||
session_stats.transport_stats[transport_stats.transport_name] =
|
||||
transport_stats;
|
||||
|
||||
@ -763,7 +763,7 @@ class StatsCollectorTest : public testing::Test {
|
||||
MockWebRtcSession session_;
|
||||
MockPeerConnection pc_;
|
||||
FakeDataChannelProvider data_channel_provider_;
|
||||
cricket::SessionStats session_stats_;
|
||||
SessionStats session_stats_;
|
||||
rtc::scoped_refptr<webrtc::MediaStream> stream_;
|
||||
rtc::scoped_refptr<webrtc::VideoTrack> track_;
|
||||
rtc::scoped_refptr<FakeAudioTrack> audio_track_;
|
||||
@ -1376,7 +1376,7 @@ TEST_F(StatsCollectorTest, NoTransport) {
|
||||
transport_stats.transport_name = "audio";
|
||||
transport_stats.channel_stats.push_back(channel_stats);
|
||||
|
||||
cricket::SessionStats session_stats;
|
||||
SessionStats session_stats;
|
||||
session_stats.transport_stats[transport_stats.transport_name] =
|
||||
transport_stats;
|
||||
|
||||
@ -1435,7 +1435,7 @@ TEST_F(StatsCollectorTest, NoCertificates) {
|
||||
transport_stats.transport_name = "audio";
|
||||
transport_stats.channel_stats.push_back(channel_stats);
|
||||
|
||||
cricket::SessionStats session_stats;
|
||||
SessionStats session_stats;
|
||||
session_stats.transport_stats[transport_stats.transport_name] =
|
||||
transport_stats;
|
||||
|
||||
|
||||
@ -331,7 +331,11 @@ static bool BadSdp(const std::string& source,
|
||||
const std::string& reason,
|
||||
std::string* err_desc) {
|
||||
std::ostringstream desc;
|
||||
desc << "Failed to set " << source << " " << type << " sdp: " << reason;
|
||||
desc << "Failed to set " << source;
|
||||
if (!type.empty()) {
|
||||
desc << " " << type;
|
||||
}
|
||||
desc << " sdp: " << reason;
|
||||
|
||||
if (err_desc) {
|
||||
*err_desc = desc.str();
|
||||
@ -382,30 +386,21 @@ static bool BadAnswerSdp(cricket::ContentSource source,
|
||||
return BadSdp(source, SessionDescriptionInterface::kAnswer, reason, err_desc);
|
||||
}
|
||||
|
||||
#define GET_STRING_OF_STATE(state) \
|
||||
case cricket::BaseSession::state: \
|
||||
result = #state; \
|
||||
#define GET_STRING_OF_STATE(state) \
|
||||
case webrtc::WebRtcSession::state: \
|
||||
result = #state; \
|
||||
break;
|
||||
|
||||
static std::string GetStateString(cricket::BaseSession::State state) {
|
||||
static std::string GetStateString(webrtc::WebRtcSession::State state) {
|
||||
std::string result;
|
||||
switch (state) {
|
||||
GET_STRING_OF_STATE(STATE_INIT)
|
||||
GET_STRING_OF_STATE(STATE_SENTINITIATE)
|
||||
GET_STRING_OF_STATE(STATE_RECEIVEDINITIATE)
|
||||
GET_STRING_OF_STATE(STATE_SENTPRACCEPT)
|
||||
GET_STRING_OF_STATE(STATE_SENTACCEPT)
|
||||
GET_STRING_OF_STATE(STATE_RECEIVEDPRACCEPT)
|
||||
GET_STRING_OF_STATE(STATE_RECEIVEDACCEPT)
|
||||
GET_STRING_OF_STATE(STATE_SENTMODIFY)
|
||||
GET_STRING_OF_STATE(STATE_RECEIVEDMODIFY)
|
||||
GET_STRING_OF_STATE(STATE_SENTREJECT)
|
||||
GET_STRING_OF_STATE(STATE_RECEIVEDREJECT)
|
||||
GET_STRING_OF_STATE(STATE_SENTREDIRECT)
|
||||
GET_STRING_OF_STATE(STATE_SENTTERMINATE)
|
||||
GET_STRING_OF_STATE(STATE_RECEIVEDTERMINATE)
|
||||
GET_STRING_OF_STATE(STATE_SENTOFFER)
|
||||
GET_STRING_OF_STATE(STATE_RECEIVEDOFFER)
|
||||
GET_STRING_OF_STATE(STATE_SENTPRANSWER)
|
||||
GET_STRING_OF_STATE(STATE_RECEIVEDPRANSWER)
|
||||
GET_STRING_OF_STATE(STATE_INPROGRESS)
|
||||
GET_STRING_OF_STATE(STATE_DEINIT)
|
||||
GET_STRING_OF_STATE(STATE_CLOSED)
|
||||
default:
|
||||
ASSERT(false);
|
||||
break;
|
||||
@ -413,22 +408,19 @@ static std::string GetStateString(cricket::BaseSession::State state) {
|
||||
return result;
|
||||
}
|
||||
|
||||
#define GET_STRING_OF_ERROR_CODE(err) \
|
||||
case cricket::BaseSession::err: \
|
||||
result = #err; \
|
||||
#define GET_STRING_OF_ERROR_CODE(err) \
|
||||
case webrtc::WebRtcSession::err: \
|
||||
result = #err; \
|
||||
break;
|
||||
|
||||
static std::string GetErrorCodeString(cricket::BaseSession::Error err) {
|
||||
static std::string GetErrorCodeString(webrtc::WebRtcSession::Error err) {
|
||||
std::string result;
|
||||
switch (err) {
|
||||
GET_STRING_OF_ERROR_CODE(ERROR_NONE)
|
||||
GET_STRING_OF_ERROR_CODE(ERROR_TIME)
|
||||
GET_STRING_OF_ERROR_CODE(ERROR_RESPONSE)
|
||||
GET_STRING_OF_ERROR_CODE(ERROR_NETWORK)
|
||||
GET_STRING_OF_ERROR_CODE(ERROR_CONTENT)
|
||||
GET_STRING_OF_ERROR_CODE(ERROR_TRANSPORT)
|
||||
default:
|
||||
ASSERT(false);
|
||||
RTC_DCHECK(false);
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
@ -541,14 +533,16 @@ WebRtcSession::WebRtcSession(cricket::ChannelManager* channel_manager,
|
||||
rtc::Thread* signaling_thread,
|
||||
rtc::Thread* worker_thread,
|
||||
cricket::PortAllocator* port_allocator)
|
||||
: cricket::BaseSession(signaling_thread,
|
||||
worker_thread,
|
||||
port_allocator,
|
||||
rtc::ToString(rtc::CreateRandomId64() & LLONG_MAX),
|
||||
false),
|
||||
: signaling_thread_(signaling_thread),
|
||||
worker_thread_(worker_thread),
|
||||
port_allocator_(port_allocator),
|
||||
// RFC 3264: The numeric value of the session id and version in the
|
||||
// o line MUST be representable with a "64 bit signed integer".
|
||||
// Due to this constraint session id |sid_| is max limited to LLONG_MAX.
|
||||
sid_(rtc::ToString(rtc::CreateRandomId64() & LLONG_MAX)),
|
||||
transport_controller_(new cricket::TransportController(signaling_thread,
|
||||
worker_thread,
|
||||
port_allocator)),
|
||||
channel_manager_(channel_manager),
|
||||
ice_observer_(NULL),
|
||||
ice_connection_state_(PeerConnectionInterface::kIceConnectionNew),
|
||||
@ -558,13 +552,14 @@ WebRtcSession::WebRtcSession(cricket::ChannelManager* channel_manager,
|
||||
data_channel_type_(cricket::DCT_NONE),
|
||||
ice_restart_latch_(new IceRestartAnswerLatch),
|
||||
metrics_observer_(NULL) {
|
||||
transport_controller()->SignalConnectionState.connect(
|
||||
transport_controller_->SetIceRole(cricket::ICEROLE_CONTROLLED);
|
||||
transport_controller_->SignalConnectionState.connect(
|
||||
this, &WebRtcSession::OnTransportControllerConnectionState);
|
||||
transport_controller()->SignalReceiving.connect(
|
||||
transport_controller_->SignalReceiving.connect(
|
||||
this, &WebRtcSession::OnTransportControllerReceiving);
|
||||
transport_controller()->SignalGatheringState.connect(
|
||||
transport_controller_->SignalGatheringState.connect(
|
||||
this, &WebRtcSession::OnTransportControllerGatheringState);
|
||||
transport_controller()->SignalCandidatesGathered.connect(
|
||||
transport_controller_->SignalCandidatesGathered.connect(
|
||||
this, &WebRtcSession::OnTransportControllerCandidatesGathered);
|
||||
}
|
||||
|
||||
@ -584,9 +579,8 @@ WebRtcSession::~WebRtcSession() {
|
||||
SignalDataChannelDestroyed();
|
||||
channel_manager_->DestroyDataChannel(data_channel_.release());
|
||||
}
|
||||
for (size_t i = 0; i < saved_candidates_.size(); ++i) {
|
||||
delete saved_candidates_[i];
|
||||
}
|
||||
|
||||
LOG(LS_INFO) << "Session: " << id() << " is destroyed.";
|
||||
}
|
||||
|
||||
bool WebRtcSession::Initialize(
|
||||
@ -596,7 +590,7 @@ bool WebRtcSession::Initialize(
|
||||
const PeerConnectionInterface::RTCConfiguration& rtc_configuration) {
|
||||
bundle_policy_ = rtc_configuration.bundle_policy;
|
||||
rtcp_mux_policy_ = rtc_configuration.rtcp_mux_policy;
|
||||
transport_controller()->SetSslMaxProtocolVersion(options.ssl_max_version);
|
||||
transport_controller_->SetSslMaxProtocolVersion(options.ssl_max_version);
|
||||
|
||||
// Obtain a certificate from RTCConfiguration if any were provided (optional).
|
||||
rtc::scoped_refptr<rtc::RTCCertificate> certificate;
|
||||
@ -775,18 +769,9 @@ bool WebRtcSession::Initialize(
|
||||
return true;
|
||||
}
|
||||
|
||||
cricket::IceConfig WebRtcSession::ParseIceConfig(
|
||||
const PeerConnectionInterface::RTCConfiguration& config) const {
|
||||
cricket::IceConfig ice_config;
|
||||
ice_config.receiving_timeout_ms = config.ice_connection_receiving_timeout;
|
||||
ice_config.gather_continually = (config.continual_gathering_policy ==
|
||||
PeerConnectionInterface::GATHER_CONTINUALLY);
|
||||
return ice_config;
|
||||
}
|
||||
|
||||
void WebRtcSession::Terminate() {
|
||||
SetState(STATE_RECEIVEDTERMINATE);
|
||||
RemoveUnusedChannels(NULL);
|
||||
void WebRtcSession::Close() {
|
||||
SetState(STATE_CLOSED);
|
||||
RemoveUnusedChannels(nullptr);
|
||||
ASSERT(!voice_channel_);
|
||||
ASSERT(!video_channel_);
|
||||
ASSERT(!data_channel_);
|
||||
@ -801,13 +786,13 @@ cricket::SecurePolicy WebRtcSession::SdesPolicy() const {
|
||||
}
|
||||
|
||||
bool WebRtcSession::GetSslRole(rtc::SSLRole* role) {
|
||||
if (local_description() == NULL || remote_description() == NULL) {
|
||||
if (!local_desc_ || !remote_desc_) {
|
||||
LOG(LS_INFO) << "Local and Remote descriptions must be applied to get "
|
||||
<< "SSL Role of the session.";
|
||||
return false;
|
||||
}
|
||||
|
||||
return transport_controller()->GetSslRole(role);
|
||||
return transport_controller_->GetSslRole(role);
|
||||
}
|
||||
|
||||
void WebRtcSession::CreateOffer(
|
||||
@ -837,10 +822,11 @@ bool WebRtcSession::SetLocalDescription(SessionDescriptionInterface* desc,
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update the initiator flag if this session is the initiator.
|
||||
// Update the initial_offerer flag if this session is the initial_offerer.
|
||||
Action action = GetAction(desc->type());
|
||||
if (state() == STATE_INIT && action == kOffer) {
|
||||
set_initiator(true);
|
||||
initial_offerer_ = true;
|
||||
transport_controller_->SetIceRole(cricket::ICEROLE_CONTROLLING);
|
||||
}
|
||||
|
||||
cricket::SecurePolicy sdes_policy =
|
||||
@ -851,7 +837,6 @@ bool WebRtcSession::SetLocalDescription(SessionDescriptionInterface* desc,
|
||||
// Update the MediaContentDescription crypto settings as per the policy set.
|
||||
UpdateSessionDescriptionSecurePolicy(crypto_required, desc->description());
|
||||
|
||||
set_local_description(desc->description()->Copy());
|
||||
local_desc_.reset(desc_temp.release());
|
||||
|
||||
// Transport and Media channels will be created only when offer is set.
|
||||
@ -868,19 +853,12 @@ bool WebRtcSession::SetLocalDescription(SessionDescriptionInterface* desc,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (remote_description()) {
|
||||
// Now that we have a local description, we can push down remote candidates
|
||||
// that we stored, and those from the remote description.
|
||||
if (!saved_candidates_.empty()) {
|
||||
// If there are saved candidates which arrived before the local
|
||||
// description was set, copy those to the remote description.
|
||||
CopySavedCandidates(remote_desc_.get());
|
||||
}
|
||||
// Push remote candidates in remote description to transport channels.
|
||||
if (remote_desc_) {
|
||||
// Now that we have a local description, we can push down remote candidates.
|
||||
UseCandidatesInSessionDescription(remote_desc_.get());
|
||||
}
|
||||
|
||||
if (error() != cricket::BaseSession::ERROR_NONE) {
|
||||
if (error() != ERROR_NONE) {
|
||||
return BadLocalSdp(desc->type(), GetSessionErrorMsg(), err_desc);
|
||||
}
|
||||
return true;
|
||||
@ -898,6 +876,10 @@ bool WebRtcSession::SetRemoteDescription(SessionDescriptionInterface* desc,
|
||||
return false;
|
||||
}
|
||||
|
||||
rtc::scoped_ptr<SessionDescriptionInterface> old_remote_desc(
|
||||
remote_desc_.release());
|
||||
remote_desc_.reset(desc_temp.release());
|
||||
|
||||
// Transport and Media channels will be created only when offer is set.
|
||||
Action action = GetAction(desc->type());
|
||||
if (action == kOffer && !CreateChannels(desc->description())) {
|
||||
@ -911,33 +893,31 @@ bool WebRtcSession::SetRemoteDescription(SessionDescriptionInterface* desc,
|
||||
|
||||
// NOTE: Candidates allocation will be initiated only when SetLocalDescription
|
||||
// is called.
|
||||
set_remote_description(desc->description()->Copy());
|
||||
if (!UpdateSessionState(action, cricket::CS_REMOTE, err_desc)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (local_description() && !UseCandidatesInSessionDescription(desc)) {
|
||||
if (local_desc_ && !UseCandidatesInSessionDescription(desc)) {
|
||||
return BadRemoteSdp(desc->type(), kInvalidCandidates, err_desc);
|
||||
}
|
||||
|
||||
// Copy all saved candidates.
|
||||
CopySavedCandidates(desc);
|
||||
|
||||
// Check if this new SessionDescription contains new ice ufrag and password
|
||||
// that indicates the remote peer requests ice restart.
|
||||
bool ice_restart =
|
||||
ice_restart_latch_->CheckForRemoteIceRestart(remote_desc_.get(), desc);
|
||||
ice_restart_latch_->CheckForRemoteIceRestart(old_remote_desc.get(), desc);
|
||||
// We retain all received candidates only if ICE is not restarted.
|
||||
// When ICE is restarted, all previous candidates belong to an old generation
|
||||
// and should not be kept.
|
||||
// TODO(deadbeef): This goes against the W3C spec which says the remote
|
||||
// description should only contain candidates from the last set remote
|
||||
// description plus any candidates added since then. We should remove this
|
||||
// once we're sure it won't break anything.
|
||||
if (!ice_restart) {
|
||||
WebRtcSessionDescriptionFactory::CopyCandidatesFromSessionDescription(
|
||||
remote_desc_.get(), desc);
|
||||
old_remote_desc.get(), desc);
|
||||
}
|
||||
|
||||
remote_desc_.reset(desc_temp.release());
|
||||
|
||||
if (error() != cricket::BaseSession::ERROR_NONE) {
|
||||
if (error() != ERROR_NONE) {
|
||||
return BadRemoteSdp(desc->type(), GetSessionErrorMsg(), err_desc);
|
||||
}
|
||||
|
||||
@ -956,6 +936,29 @@ bool WebRtcSession::SetRemoteDescription(SessionDescriptionInterface* desc,
|
||||
return true;
|
||||
}
|
||||
|
||||
void WebRtcSession::LogState(State old_state, State new_state) {
|
||||
LOG(LS_INFO) << "Session:" << id()
|
||||
<< " Old state:" << GetStateString(old_state)
|
||||
<< " New state:" << GetStateString(new_state);
|
||||
}
|
||||
|
||||
void WebRtcSession::SetState(State state) {
|
||||
ASSERT(signaling_thread_->IsCurrent());
|
||||
if (state != state_) {
|
||||
LogState(state_, state);
|
||||
state_ = state;
|
||||
SignalState(this, state_);
|
||||
}
|
||||
}
|
||||
|
||||
void WebRtcSession::SetError(Error error, const std::string& error_desc) {
|
||||
ASSERT(signaling_thread_->IsCurrent());
|
||||
if (error != error_) {
|
||||
error_ = error;
|
||||
error_desc_ = error_desc;
|
||||
}
|
||||
}
|
||||
|
||||
bool WebRtcSession::UpdateSessionState(
|
||||
Action action, cricket::ContentSource source,
|
||||
std::string* err_desc) {
|
||||
@ -963,18 +966,18 @@ bool WebRtcSession::UpdateSessionState(
|
||||
|
||||
// If there's already a pending error then no state transition should happen.
|
||||
// But all call-sites should be verifying this before calling us!
|
||||
ASSERT(error() == cricket::BaseSession::ERROR_NONE);
|
||||
ASSERT(error() == ERROR_NONE);
|
||||
std::string td_err;
|
||||
if (action == kOffer) {
|
||||
if (!PushdownTransportDescription(source, cricket::CA_OFFER, &td_err)) {
|
||||
return BadOfferSdp(source, MakeTdErrorString(td_err), err_desc);
|
||||
}
|
||||
SetState(source == cricket::CS_LOCAL ?
|
||||
STATE_SENTINITIATE : STATE_RECEIVEDINITIATE);
|
||||
SetState(source == cricket::CS_LOCAL ? STATE_SENTOFFER
|
||||
: STATE_RECEIVEDOFFER);
|
||||
if (!PushdownMediaDescription(cricket::CA_OFFER, source, err_desc)) {
|
||||
SetError(BaseSession::ERROR_CONTENT, *err_desc);
|
||||
SetError(ERROR_CONTENT, *err_desc);
|
||||
}
|
||||
if (error() != cricket::BaseSession::ERROR_NONE) {
|
||||
if (error() != ERROR_NONE) {
|
||||
return BadOfferSdp(source, GetSessionErrorMsg(), err_desc);
|
||||
}
|
||||
} else if (action == kPrAnswer) {
|
||||
@ -982,12 +985,12 @@ bool WebRtcSession::UpdateSessionState(
|
||||
return BadPranswerSdp(source, MakeTdErrorString(td_err), err_desc);
|
||||
}
|
||||
EnableChannels();
|
||||
SetState(source == cricket::CS_LOCAL ?
|
||||
STATE_SENTPRACCEPT : STATE_RECEIVEDPRACCEPT);
|
||||
SetState(source == cricket::CS_LOCAL ? STATE_SENTPRANSWER
|
||||
: STATE_RECEIVEDPRANSWER);
|
||||
if (!PushdownMediaDescription(cricket::CA_PRANSWER, source, err_desc)) {
|
||||
SetError(BaseSession::ERROR_CONTENT, *err_desc);
|
||||
SetError(ERROR_CONTENT, *err_desc);
|
||||
}
|
||||
if (error() != cricket::BaseSession::ERROR_NONE) {
|
||||
if (error() != ERROR_NONE) {
|
||||
return BadPranswerSdp(source, GetSessionErrorMsg(), err_desc);
|
||||
}
|
||||
} else if (action == kAnswer) {
|
||||
@ -995,11 +998,9 @@ bool WebRtcSession::UpdateSessionState(
|
||||
return BadAnswerSdp(source, MakeTdErrorString(td_err), err_desc);
|
||||
}
|
||||
const cricket::ContentGroup* local_bundle =
|
||||
BaseSession::local_description()->GetGroupByName(
|
||||
cricket::GROUP_TYPE_BUNDLE);
|
||||
local_desc_->description()->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
|
||||
const cricket::ContentGroup* remote_bundle =
|
||||
BaseSession::remote_description()->GetGroupByName(
|
||||
cricket::GROUP_TYPE_BUNDLE);
|
||||
remote_desc_->description()->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
|
||||
if (local_bundle && remote_bundle) {
|
||||
// The answerer decides the transport to bundle on
|
||||
const cricket::ContentGroup* answer_bundle =
|
||||
@ -1010,39 +1011,17 @@ bool WebRtcSession::UpdateSessionState(
|
||||
}
|
||||
}
|
||||
EnableChannels();
|
||||
SetState(source == cricket::CS_LOCAL ?
|
||||
STATE_SENTACCEPT : STATE_RECEIVEDACCEPT);
|
||||
SetState(STATE_INPROGRESS);
|
||||
if (!PushdownMediaDescription(cricket::CA_ANSWER, source, err_desc)) {
|
||||
SetError(BaseSession::ERROR_CONTENT, *err_desc);
|
||||
SetError(ERROR_CONTENT, *err_desc);
|
||||
}
|
||||
if (error() != cricket::BaseSession::ERROR_NONE) {
|
||||
if (error() != ERROR_NONE) {
|
||||
return BadAnswerSdp(source, GetSessionErrorMsg(), err_desc);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebRtcSession::PushdownMediaDescription(
|
||||
cricket::ContentAction action,
|
||||
cricket::ContentSource source,
|
||||
std::string* err) {
|
||||
auto set_content = [this, action, source, err](cricket::BaseChannel* ch) {
|
||||
if (!ch) {
|
||||
return true;
|
||||
} else if (source == cricket::CS_LOCAL) {
|
||||
return ch->PushdownLocalDescription(
|
||||
base_local_description(), action, err);
|
||||
} else {
|
||||
return ch->PushdownRemoteDescription(
|
||||
base_remote_description(), action, err);
|
||||
}
|
||||
};
|
||||
|
||||
return (set_content(voice_channel()) &&
|
||||
set_content(video_channel()) &&
|
||||
set_content(data_channel()));
|
||||
}
|
||||
|
||||
WebRtcSession::Action WebRtcSession::GetAction(const std::string& type) {
|
||||
if (type == SessionDescriptionInterface::kOffer) {
|
||||
return WebRtcSession::kOffer;
|
||||
@ -1055,7 +1034,97 @@ WebRtcSession::Action WebRtcSession::GetAction(const std::string& type) {
|
||||
return WebRtcSession::kOffer;
|
||||
}
|
||||
|
||||
bool WebRtcSession::GetTransportStats(cricket::SessionStats* stats) {
|
||||
bool WebRtcSession::PushdownMediaDescription(
|
||||
cricket::ContentAction action,
|
||||
cricket::ContentSource source,
|
||||
std::string* err) {
|
||||
auto set_content = [this, action, source, err](cricket::BaseChannel* ch) {
|
||||
if (!ch) {
|
||||
return true;
|
||||
} else if (source == cricket::CS_LOCAL) {
|
||||
return ch->PushdownLocalDescription(local_desc_->description(), action,
|
||||
err);
|
||||
} else {
|
||||
return ch->PushdownRemoteDescription(remote_desc_->description(), action,
|
||||
err);
|
||||
}
|
||||
};
|
||||
|
||||
return (set_content(voice_channel()) &&
|
||||
set_content(video_channel()) &&
|
||||
set_content(data_channel()));
|
||||
}
|
||||
|
||||
bool WebRtcSession::PushdownTransportDescription(cricket::ContentSource source,
|
||||
cricket::ContentAction action,
|
||||
std::string* error_desc) {
|
||||
RTC_DCHECK(signaling_thread()->IsCurrent());
|
||||
|
||||
if (source == cricket::CS_LOCAL) {
|
||||
return PushdownLocalTransportDescription(local_desc_->description(), action,
|
||||
error_desc);
|
||||
}
|
||||
return PushdownRemoteTransportDescription(remote_desc_->description(), action,
|
||||
error_desc);
|
||||
}
|
||||
|
||||
bool WebRtcSession::PushdownLocalTransportDescription(
|
||||
const SessionDescription* sdesc,
|
||||
cricket::ContentAction action,
|
||||
std::string* err) {
|
||||
RTC_DCHECK(signaling_thread()->IsCurrent());
|
||||
|
||||
if (!sdesc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const TransportInfo& tinfo : sdesc->transport_infos()) {
|
||||
if (!transport_controller_->SetLocalTransportDescription(
|
||||
tinfo.content_name, tinfo.description, action, err)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebRtcSession::PushdownRemoteTransportDescription(
|
||||
const SessionDescription* sdesc,
|
||||
cricket::ContentAction action,
|
||||
std::string* err) {
|
||||
RTC_DCHECK(signaling_thread()->IsCurrent());
|
||||
|
||||
if (!sdesc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const TransportInfo& tinfo : sdesc->transport_infos()) {
|
||||
if (!transport_controller_->SetRemoteTransportDescription(
|
||||
tinfo.content_name, tinfo.description, action, err)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebRtcSession::GetTransportDescription(
|
||||
const SessionDescription* description,
|
||||
const std::string& content_name,
|
||||
cricket::TransportDescription* tdesc) {
|
||||
if (!description || !tdesc) {
|
||||
return false;
|
||||
}
|
||||
const TransportInfo* transport_info =
|
||||
description->GetTransportInfoByName(content_name);
|
||||
if (!transport_info) {
|
||||
return false;
|
||||
}
|
||||
*tdesc = transport_info->description;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebRtcSession::GetTransportStats(SessionStats* stats) {
|
||||
ASSERT(signaling_thread()->IsCurrent());
|
||||
return (GetChannelTransportStats(voice_channel(), stats) &&
|
||||
GetChannelTransportStats(video_channel(), stats) &&
|
||||
@ -1063,7 +1132,7 @@ bool WebRtcSession::GetTransportStats(cricket::SessionStats* stats) {
|
||||
}
|
||||
|
||||
bool WebRtcSession::GetChannelTransportStats(cricket::BaseChannel* ch,
|
||||
cricket::SessionStats* stats) {
|
||||
SessionStats* stats) {
|
||||
ASSERT(signaling_thread()->IsCurrent());
|
||||
if (!ch) {
|
||||
// Not using this channel.
|
||||
@ -1080,7 +1149,7 @@ bool WebRtcSession::GetChannelTransportStats(cricket::BaseChannel* ch,
|
||||
}
|
||||
|
||||
cricket::TransportStats tstats;
|
||||
if (!transport_controller()->GetStats(transport_name, &tstats)) {
|
||||
if (!transport_controller_->GetStats(transport_name, &tstats)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1092,14 +1161,14 @@ bool WebRtcSession::GetLocalCertificate(
|
||||
const std::string& transport_name,
|
||||
rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
|
||||
ASSERT(signaling_thread()->IsCurrent());
|
||||
return transport_controller()->GetLocalCertificate(transport_name,
|
||||
certificate);
|
||||
return transport_controller_->GetLocalCertificate(transport_name,
|
||||
certificate);
|
||||
}
|
||||
|
||||
bool WebRtcSession::GetRemoteSSLCertificate(const std::string& transport_name,
|
||||
rtc::SSLCertificate** cert) {
|
||||
ASSERT(signaling_thread()->IsCurrent());
|
||||
return transport_controller()->GetRemoteSSLCertificate(transport_name, cert);
|
||||
return transport_controller_->GetRemoteSSLCertificate(transport_name, cert);
|
||||
}
|
||||
|
||||
cricket::BaseChannel* WebRtcSession::GetChannel(
|
||||
@ -1156,37 +1225,35 @@ bool WebRtcSession::EnableBundle(const cricket::ContentGroup& bundle) {
|
||||
}
|
||||
|
||||
bool WebRtcSession::ProcessIceMessage(const IceCandidateInterface* candidate) {
|
||||
if (state() == STATE_INIT) {
|
||||
LOG(LS_ERROR) << "ProcessIceMessage: ICE candidates can't be added "
|
||||
<< "without any offer (local or remote) "
|
||||
<< "session description.";
|
||||
if (!remote_desc_) {
|
||||
LOG(LS_ERROR) << "ProcessIceMessage: ICE candidates can't be added "
|
||||
<< "without any remote session description.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!candidate) {
|
||||
LOG(LS_ERROR) << "ProcessIceMessage: Candidate is NULL";
|
||||
LOG(LS_ERROR) << "ProcessIceMessage: Candidate is NULL.";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool valid = false;
|
||||
if (!ReadyToUseRemoteCandidate(candidate, NULL, &valid)) {
|
||||
if (valid) {
|
||||
LOG(LS_INFO) << "ProcessIceMessage: Candidate saved";
|
||||
saved_candidates_.push_back(
|
||||
new JsepIceCandidate(candidate->sdp_mid(),
|
||||
candidate->sdp_mline_index(),
|
||||
candidate->candidate()));
|
||||
}
|
||||
return valid;
|
||||
bool ready = ReadyToUseRemoteCandidate(candidate, NULL, &valid);
|
||||
if (!valid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add this candidate to the remote session description.
|
||||
if (!remote_desc_->AddCandidate(candidate)) {
|
||||
LOG(LS_ERROR) << "ProcessIceMessage: Candidate cannot be used";
|
||||
LOG(LS_ERROR) << "ProcessIceMessage: Candidate cannot be used.";
|
||||
return false;
|
||||
}
|
||||
|
||||
return UseCandidate(candidate);
|
||||
if (ready) {
|
||||
return UseCandidate(candidate);
|
||||
} else {
|
||||
LOG(LS_INFO) << "ProcessIceMessage: Not ready to use candidate.";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool WebRtcSession::SetIceTransports(
|
||||
@ -1195,18 +1262,37 @@ bool WebRtcSession::SetIceTransports(
|
||||
ConvertIceTransportTypeToCandidateFilter(type));
|
||||
}
|
||||
|
||||
cricket::IceConfig WebRtcSession::ParseIceConfig(
|
||||
const PeerConnectionInterface::RTCConfiguration& config) const {
|
||||
cricket::IceConfig ice_config;
|
||||
ice_config.receiving_timeout_ms = config.ice_connection_receiving_timeout;
|
||||
ice_config.gather_continually = (config.continual_gathering_policy ==
|
||||
PeerConnectionInterface::GATHER_CONTINUALLY);
|
||||
return ice_config;
|
||||
}
|
||||
|
||||
void WebRtcSession::SetIceConfig(const cricket::IceConfig& config) {
|
||||
transport_controller_->SetIceConfig(config);
|
||||
}
|
||||
|
||||
void WebRtcSession::MaybeStartGathering() {
|
||||
transport_controller_->MaybeStartGathering();
|
||||
}
|
||||
|
||||
bool WebRtcSession::GetLocalTrackIdBySsrc(uint32_t ssrc,
|
||||
std::string* track_id) {
|
||||
if (!base_local_description())
|
||||
if (!local_desc_) {
|
||||
return false;
|
||||
return webrtc::GetTrackIdBySsrc(base_local_description(), ssrc, track_id);
|
||||
}
|
||||
return webrtc::GetTrackIdBySsrc(local_desc_->description(), ssrc, track_id);
|
||||
}
|
||||
|
||||
bool WebRtcSession::GetRemoteTrackIdBySsrc(uint32_t ssrc,
|
||||
std::string* track_id) {
|
||||
if (!base_remote_description())
|
||||
if (!remote_desc_) {
|
||||
return false;
|
||||
return webrtc::GetTrackIdBySsrc(base_remote_description(), ssrc, track_id);
|
||||
}
|
||||
return webrtc::GetTrackIdBySsrc(remote_desc_->description(), ssrc, track_id);
|
||||
}
|
||||
|
||||
std::string WebRtcSession::BadStateErrMsg(State state) {
|
||||
@ -1317,7 +1403,8 @@ bool WebRtcSession::CanInsertDtmf(const std::string& track_id) {
|
||||
uint32_t send_ssrc = 0;
|
||||
// The Dtmf is negotiated per channel not ssrc, so we only check if the ssrc
|
||||
// exists.
|
||||
if (!GetAudioSsrcByTrackId(base_local_description(), track_id,
|
||||
if (!local_desc_ ||
|
||||
!GetAudioSsrcByTrackId(local_desc_->description(), track_id,
|
||||
&send_ssrc)) {
|
||||
LOG(LS_ERROR) << "CanInsertDtmf: Track does not exist: " << track_id;
|
||||
return false;
|
||||
@ -1333,8 +1420,8 @@ bool WebRtcSession::InsertDtmf(const std::string& track_id,
|
||||
return false;
|
||||
}
|
||||
uint32_t send_ssrc = 0;
|
||||
if (!VERIFY(GetAudioSsrcByTrackId(base_local_description(),
|
||||
track_id, &send_ssrc))) {
|
||||
if (!VERIFY(local_desc_ && GetAudioSsrcByTrackId(local_desc_->description(),
|
||||
track_id, &send_ssrc))) {
|
||||
LOG(LS_ERROR) << "InsertDtmf: Track does not exist: " << track_id;
|
||||
return false;
|
||||
}
|
||||
@ -1421,7 +1508,7 @@ void WebRtcSession::ResetIceRestartLatch() {
|
||||
|
||||
void WebRtcSession::OnCertificateReady(
|
||||
const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
|
||||
transport_controller()->SetLocalCertificate(certificate);
|
||||
transport_controller_->SetLocalCertificate(certificate);
|
||||
}
|
||||
|
||||
bool WebRtcSession::waiting_for_certificate_for_testing() const {
|
||||
@ -1430,7 +1517,7 @@ bool WebRtcSession::waiting_for_certificate_for_testing() const {
|
||||
|
||||
const rtc::scoped_refptr<rtc::RTCCertificate>&
|
||||
WebRtcSession::certificate_for_testing() {
|
||||
return transport_controller()->certificate_for_testing();
|
||||
return transport_controller_->certificate_for_testing();
|
||||
}
|
||||
|
||||
void WebRtcSession::SetIceConnectionState(
|
||||
@ -1583,11 +1670,12 @@ void WebRtcSession::EnableChannels() {
|
||||
// Returns the media index for a local ice candidate given the content name.
|
||||
bool WebRtcSession::GetLocalCandidateMediaIndex(const std::string& content_name,
|
||||
int* sdp_mline_index) {
|
||||
if (!base_local_description() || !sdp_mline_index)
|
||||
if (!local_desc_ || !sdp_mline_index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool content_found = false;
|
||||
const ContentInfos& contents = base_local_description()->contents();
|
||||
const ContentInfos& contents = local_desc_->description()->contents();
|
||||
for (size_t index = 0; index < contents.size(); ++index) {
|
||||
if (contents[index].name == content_name) {
|
||||
*sdp_mline_index = static_cast<int>(index);
|
||||
@ -1600,28 +1688,27 @@ bool WebRtcSession::GetLocalCandidateMediaIndex(const std::string& content_name,
|
||||
|
||||
bool WebRtcSession::UseCandidatesInSessionDescription(
|
||||
const SessionDescriptionInterface* remote_desc) {
|
||||
if (!remote_desc)
|
||||
if (!remote_desc) {
|
||||
return true;
|
||||
}
|
||||
bool ret = true;
|
||||
|
||||
for (size_t m = 0; m < remote_desc->number_of_mediasections(); ++m) {
|
||||
const IceCandidateCollection* candidates = remote_desc->candidates(m);
|
||||
for (size_t n = 0; n < candidates->count(); ++n) {
|
||||
for (size_t n = 0; n < candidates->count(); ++n) {
|
||||
const IceCandidateInterface* candidate = candidates->at(n);
|
||||
bool valid = false;
|
||||
if (!ReadyToUseRemoteCandidate(candidate, remote_desc, &valid)) {
|
||||
if (valid) {
|
||||
LOG(LS_INFO) << "UseCandidatesInSessionDescription: Candidate saved.";
|
||||
saved_candidates_.push_back(
|
||||
new JsepIceCandidate(candidate->sdp_mid(),
|
||||
candidate->sdp_mline_index(),
|
||||
candidate->candidate()));
|
||||
LOG(LS_INFO) << "UseCandidatesInSessionDescription: Not ready to use "
|
||||
<< "candidate.";
|
||||
}
|
||||
continue;
|
||||
}
|
||||
ret = UseCandidate(candidate);
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
@ -1631,7 +1718,7 @@ bool WebRtcSession::UseCandidate(
|
||||
const IceCandidateInterface* candidate) {
|
||||
|
||||
size_t mediacontent_index = static_cast<size_t>(candidate->sdp_mline_index());
|
||||
size_t remote_content_size = base_remote_description()->contents().size();
|
||||
size_t remote_content_size = remote_desc_->description()->contents().size();
|
||||
if (mediacontent_index >= remote_content_size) {
|
||||
LOG(LS_ERROR)
|
||||
<< "UseRemoteCandidateInSession: Invalid candidate media index.";
|
||||
@ -1639,13 +1726,13 @@ bool WebRtcSession::UseCandidate(
|
||||
}
|
||||
|
||||
cricket::ContentInfo content =
|
||||
base_remote_description()->contents()[mediacontent_index];
|
||||
remote_desc_->description()->contents()[mediacontent_index];
|
||||
std::vector<cricket::Candidate> candidates;
|
||||
candidates.push_back(candidate->candidate());
|
||||
// Invoking BaseSession method to handle remote candidates.
|
||||
std::string error;
|
||||
if (transport_controller()->AddRemoteCandidates(content.name, candidates,
|
||||
&error)) {
|
||||
if (transport_controller_->AddRemoteCandidates(content.name, candidates,
|
||||
&error)) {
|
||||
// Candidates successfully submitted for checking.
|
||||
if (ice_connection_state_ == PeerConnectionInterface::kIceConnectionNew ||
|
||||
ice_connection_state_ ==
|
||||
@ -1757,7 +1844,7 @@ bool WebRtcSession::CreateChannels(const SessionDescription* desc) {
|
||||
|
||||
bool WebRtcSession::CreateVoiceChannel(const cricket::ContentInfo* content) {
|
||||
voice_channel_.reset(channel_manager_->CreateVoiceChannel(
|
||||
media_controller_.get(), transport_controller(), content->name, true,
|
||||
media_controller_.get(), transport_controller_.get(), content->name, true,
|
||||
audio_options_));
|
||||
if (!voice_channel_) {
|
||||
return false;
|
||||
@ -1772,7 +1859,7 @@ bool WebRtcSession::CreateVoiceChannel(const cricket::ContentInfo* content) {
|
||||
|
||||
bool WebRtcSession::CreateVideoChannel(const cricket::ContentInfo* content) {
|
||||
video_channel_.reset(channel_manager_->CreateVideoChannel(
|
||||
media_controller_.get(), transport_controller(), content->name, true,
|
||||
media_controller_.get(), transport_controller_.get(), content->name, true,
|
||||
video_options_));
|
||||
if (!video_channel_) {
|
||||
return false;
|
||||
@ -1788,7 +1875,7 @@ bool WebRtcSession::CreateVideoChannel(const cricket::ContentInfo* content) {
|
||||
bool WebRtcSession::CreateDataChannel(const cricket::ContentInfo* content) {
|
||||
bool sctp = (data_channel_type_ == cricket::DCT_SCTP);
|
||||
data_channel_.reset(channel_manager_->CreateDataChannel(
|
||||
transport_controller(), content->name, !sctp, data_channel_type_));
|
||||
transport_controller_.get(), content->name, !sctp, data_channel_type_));
|
||||
if (!data_channel_) {
|
||||
return false;
|
||||
}
|
||||
@ -1806,21 +1893,8 @@ bool WebRtcSession::CreateDataChannel(const cricket::ContentInfo* content) {
|
||||
}
|
||||
|
||||
void WebRtcSession::OnDtlsSetupFailure(cricket::BaseChannel*, bool rtcp) {
|
||||
SetError(BaseSession::ERROR_TRANSPORT, rtcp ? kDtlsSetupFailureRtcp :
|
||||
kDtlsSetupFailureRtp);
|
||||
}
|
||||
|
||||
void WebRtcSession::CopySavedCandidates(
|
||||
SessionDescriptionInterface* dest_desc) {
|
||||
if (!dest_desc) {
|
||||
ASSERT(false);
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i < saved_candidates_.size(); ++i) {
|
||||
dest_desc->AddCandidate(saved_candidates_[i]);
|
||||
delete saved_candidates_[i];
|
||||
}
|
||||
saved_candidates_.clear();
|
||||
SetError(ERROR_TRANSPORT,
|
||||
rtcp ? kDtlsSetupFailureRtcp : kDtlsSetupFailureRtp);
|
||||
}
|
||||
|
||||
void WebRtcSession::OnDataChannelMessageReceived(
|
||||
@ -1881,7 +1955,7 @@ bool WebRtcSession::ValidateSessionDescription(
|
||||
const SessionDescriptionInterface* sdesc,
|
||||
cricket::ContentSource source, std::string* err_desc) {
|
||||
std::string type;
|
||||
if (error() != cricket::BaseSession::ERROR_NONE) {
|
||||
if (error() != ERROR_NONE) {
|
||||
return BadSdp(source, type, GetSessionErrorMsg(), err_desc);
|
||||
}
|
||||
|
||||
@ -1919,8 +1993,8 @@ bool WebRtcSession::ValidateSessionDescription(
|
||||
// Verify m-lines in Answer when compared against Offer.
|
||||
if (action == kAnswer) {
|
||||
const cricket::SessionDescription* offer_desc =
|
||||
(source == cricket::CS_LOCAL) ? remote_description()->description() :
|
||||
local_description()->description();
|
||||
(source == cricket::CS_LOCAL) ? remote_desc_->description()
|
||||
: local_desc_->description();
|
||||
if (!VerifyMediaDescriptions(sdesc->description(), offer_desc)) {
|
||||
return BadAnswerSdp(source, kMlineMismatch, err_desc);
|
||||
}
|
||||
@ -1932,31 +2006,27 @@ bool WebRtcSession::ValidateSessionDescription(
|
||||
bool WebRtcSession::ExpectSetLocalDescription(Action action) {
|
||||
return ((action == kOffer && state() == STATE_INIT) ||
|
||||
// update local offer
|
||||
(action == kOffer && state() == STATE_SENTINITIATE) ||
|
||||
(action == kOffer && state() == STATE_SENTOFFER) ||
|
||||
// update the current ongoing session.
|
||||
(action == kOffer && state() == STATE_RECEIVEDACCEPT) ||
|
||||
(action == kOffer && state() == STATE_SENTACCEPT) ||
|
||||
(action == kOffer && state() == STATE_INPROGRESS) ||
|
||||
// accept remote offer
|
||||
(action == kAnswer && state() == STATE_RECEIVEDINITIATE) ||
|
||||
(action == kAnswer && state() == STATE_SENTPRACCEPT) ||
|
||||
(action == kPrAnswer && state() == STATE_RECEIVEDINITIATE) ||
|
||||
(action == kPrAnswer && state() == STATE_SENTPRACCEPT));
|
||||
(action == kAnswer && state() == STATE_RECEIVEDOFFER) ||
|
||||
(action == kAnswer && state() == STATE_SENTPRANSWER) ||
|
||||
(action == kPrAnswer && state() == STATE_RECEIVEDOFFER) ||
|
||||
(action == kPrAnswer && state() == STATE_SENTPRANSWER));
|
||||
}
|
||||
|
||||
bool WebRtcSession::ExpectSetRemoteDescription(Action action) {
|
||||
return ((action == kOffer && state() == STATE_INIT) ||
|
||||
// update remote offer
|
||||
(action == kOffer && state() == STATE_RECEIVEDINITIATE) ||
|
||||
(action == kOffer && state() == STATE_RECEIVEDOFFER) ||
|
||||
// update the current ongoing session
|
||||
(action == kOffer && state() == STATE_RECEIVEDACCEPT) ||
|
||||
(action == kOffer && state() == STATE_SENTACCEPT) ||
|
||||
(action == kOffer && state() == STATE_INPROGRESS) ||
|
||||
// accept local offer
|
||||
(action == kAnswer && state() == STATE_SENTINITIATE) ||
|
||||
(action == kAnswer && state() == STATE_RECEIVEDPRACCEPT) ||
|
||||
(action == kPrAnswer && state() == STATE_SENTINITIATE) ||
|
||||
(action == kPrAnswer && state() == STATE_RECEIVEDPRACCEPT));
|
||||
(action == kAnswer && state() == STATE_SENTOFFER) ||
|
||||
(action == kAnswer && state() == STATE_RECEIVEDPRANSWER) ||
|
||||
(action == kPrAnswer && state() == STATE_SENTOFFER) ||
|
||||
(action == kPrAnswer && state() == STATE_RECEIVEDPRANSWER));
|
||||
}
|
||||
|
||||
std::string WebRtcSession::GetSessionErrorMsg() {
|
||||
@ -1978,10 +2048,11 @@ bool WebRtcSession::ReadyToUseRemoteCandidate(
|
||||
*valid = true;;
|
||||
|
||||
const SessionDescriptionInterface* current_remote_desc =
|
||||
remote_desc ? remote_desc : remote_description();
|
||||
remote_desc ? remote_desc : remote_desc_.get();
|
||||
|
||||
if (!current_remote_desc)
|
||||
if (!current_remote_desc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t mediacontent_index =
|
||||
static_cast<size_t>(candidate->sdp_mline_index());
|
||||
@ -2002,7 +2073,7 @@ bool WebRtcSession::ReadyToUseRemoteCandidate(
|
||||
return false;
|
||||
}
|
||||
|
||||
return transport_controller()->ReadyForRemoteCandidates(
|
||||
return transport_controller_->ReadyForRemoteCandidates(
|
||||
channel->transport_name());
|
||||
}
|
||||
|
||||
@ -2038,7 +2109,7 @@ void WebRtcSession::ReportTransportStats() {
|
||||
}
|
||||
for (const auto& name : transport_names) {
|
||||
cricket::TransportStats stats;
|
||||
if (transport_controller()->GetStats(name, &stats)) {
|
||||
if (transport_controller_->GetStats(name, &stats)) {
|
||||
ReportBestConnectionState(stats);
|
||||
ReportNegotiatedCiphers(stats);
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
#include "talk/app/webrtc/peerconnectioninterface.h"
|
||||
#include "talk/app/webrtc/statstypes.h"
|
||||
#include "talk/media/base/mediachannel.h"
|
||||
#include "webrtc/p2p/base/session.h"
|
||||
#include "webrtc/p2p/base/transportcontroller.h"
|
||||
#include "talk/session/media/mediasession.h"
|
||||
#include "webrtc/base/sigslot.h"
|
||||
#include "webrtc/base/sslidentity.h"
|
||||
@ -46,7 +46,6 @@
|
||||
|
||||
namespace cricket {
|
||||
|
||||
class BaseChannel;
|
||||
class ChannelManager;
|
||||
class DataChannel;
|
||||
class StatsReport;
|
||||
@ -112,26 +111,80 @@ class IceObserver {
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(IceObserver);
|
||||
};
|
||||
|
||||
class WebRtcSession : public cricket::BaseSession,
|
||||
public AudioProviderInterface,
|
||||
// Statistics for all the transports of the session.
|
||||
typedef std::map<std::string, cricket::TransportStats> TransportStatsMap;
|
||||
typedef std::map<std::string, std::string> ProxyTransportMap;
|
||||
|
||||
// TODO(pthatcher): Think of a better name for this. We already have
|
||||
// a TransportStats in transport.h. Perhaps TransportsStats?
|
||||
struct SessionStats {
|
||||
ProxyTransportMap proxy_to_transport;
|
||||
TransportStatsMap transport_stats;
|
||||
};
|
||||
|
||||
// A WebRtcSession manages general session state. This includes negotiation
|
||||
// of both the application-level and network-level protocols: the former
|
||||
// defines what will be sent and the latter defines how it will be sent. Each
|
||||
// network-level protocol is represented by a Transport object. Each Transport
|
||||
// participates in the network-level negotiation. The individual streams of
|
||||
// packets are represented by TransportChannels. The application-level protocol
|
||||
// is represented by SessionDecription objects.
|
||||
class WebRtcSession : public AudioProviderInterface,
|
||||
public VideoProviderInterface,
|
||||
public DtmfProviderInterface,
|
||||
public DataChannelProviderInterface {
|
||||
public DataChannelProviderInterface,
|
||||
public sigslot::has_slots<> {
|
||||
public:
|
||||
enum State {
|
||||
STATE_INIT = 0,
|
||||
STATE_SENTOFFER, // Sent offer, waiting for answer.
|
||||
STATE_RECEIVEDOFFER, // Received an offer. Need to send answer.
|
||||
STATE_SENTPRANSWER, // Sent provisional answer. Need to send answer.
|
||||
STATE_RECEIVEDPRANSWER, // Received provisional answer, waiting for answer.
|
||||
STATE_INPROGRESS, // Offer/answer exchange completed.
|
||||
STATE_CLOSED, // Close() was called.
|
||||
};
|
||||
|
||||
enum Error {
|
||||
ERROR_NONE = 0, // no error
|
||||
ERROR_CONTENT = 1, // channel errors in SetLocalContent/SetRemoteContent
|
||||
ERROR_TRANSPORT = 2, // transport error of some kind
|
||||
};
|
||||
|
||||
WebRtcSession(cricket::ChannelManager* channel_manager,
|
||||
rtc::Thread* signaling_thread,
|
||||
rtc::Thread* worker_thread,
|
||||
cricket::PortAllocator* port_allocator);
|
||||
virtual ~WebRtcSession();
|
||||
|
||||
// These are const to allow them to be called from const methods.
|
||||
rtc::Thread* signaling_thread() const { return signaling_thread_; }
|
||||
rtc::Thread* worker_thread() const { return worker_thread_; }
|
||||
cricket::PortAllocator* port_allocator() const { return port_allocator_; }
|
||||
|
||||
// The ID of this session.
|
||||
const std::string& id() const { return sid_; }
|
||||
|
||||
bool Initialize(
|
||||
const PeerConnectionFactoryInterface::Options& options,
|
||||
const MediaConstraintsInterface* constraints,
|
||||
rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store,
|
||||
const PeerConnectionInterface::RTCConfiguration& rtc_configuration);
|
||||
// Deletes the voice, video and data channel and changes the session state
|
||||
// to STATE_RECEIVEDTERMINATE.
|
||||
void Terminate();
|
||||
// to STATE_CLOSED.
|
||||
void Close();
|
||||
|
||||
// Returns true if we were the initial offerer.
|
||||
bool initial_offerer() const { return initial_offerer_; }
|
||||
|
||||
// Returns the current state of the session. See the enum above for details.
|
||||
// Each time the state changes, we will fire this signal.
|
||||
State state() const { return state_; }
|
||||
sigslot::signal2<WebRtcSession*, State> SignalState;
|
||||
|
||||
// Returns the last error in the session. See the enum above for details.
|
||||
Error error() const { return error_; }
|
||||
const std::string& error_desc() const { return error_desc_; }
|
||||
|
||||
void RegisterIceObserver(IceObserver* observer) {
|
||||
ice_observer_ = observer;
|
||||
@ -153,10 +206,6 @@ class WebRtcSession : public cricket::BaseSession,
|
||||
// Get current ssl role from transport.
|
||||
bool GetSslRole(rtc::SSLRole* role);
|
||||
|
||||
// Generic error message callback from WebRtcSession.
|
||||
// TODO - It may be necessary to supply error code as well.
|
||||
sigslot::signal0<> SignalError;
|
||||
|
||||
void CreateOffer(
|
||||
CreateSessionDescriptionObserver* observer,
|
||||
const PeerConnectionInterface::RTCOfferAnswerOptions& options,
|
||||
@ -177,21 +226,18 @@ class WebRtcSession : public cricket::BaseSession,
|
||||
cricket::IceConfig ParseIceConfig(
|
||||
const PeerConnectionInterface::RTCConfiguration& config) const;
|
||||
|
||||
void SetIceConfig(const cricket::IceConfig& ice_config);
|
||||
|
||||
// Start gathering candidates for any new transports, or transports doing an
|
||||
// ICE restart.
|
||||
void MaybeStartGathering();
|
||||
|
||||
const SessionDescriptionInterface* local_description() const {
|
||||
return local_desc_.get();
|
||||
}
|
||||
const SessionDescriptionInterface* remote_description() const {
|
||||
return remote_desc_.get();
|
||||
}
|
||||
// TODO(pthatcher): Cleanup the distinction between
|
||||
// SessionDescription and SessionDescriptionInterface and remove
|
||||
// these if possible.
|
||||
const cricket::SessionDescription* base_local_description() const {
|
||||
return BaseSession::local_description();
|
||||
}
|
||||
const cricket::SessionDescription* base_remote_description() const {
|
||||
return BaseSession::remote_description();
|
||||
}
|
||||
|
||||
// Get the id used as a media stream track's "id" field from ssrc.
|
||||
virtual bool GetLocalTrackIdBySsrc(uint32_t ssrc, std::string* track_id);
|
||||
@ -232,11 +278,10 @@ class WebRtcSession : public cricket::BaseSession,
|
||||
|
||||
// Returns stats for all channels of all transports.
|
||||
// This avoids exposing the internal structures used to track them.
|
||||
virtual bool GetTransportStats(cricket::SessionStats* stats);
|
||||
virtual bool GetTransportStats(SessionStats* stats);
|
||||
|
||||
// Get stats for a specific channel
|
||||
bool GetChannelTransportStats(cricket::BaseChannel* ch,
|
||||
cricket::SessionStats* stats);
|
||||
bool GetChannelTransportStats(cricket::BaseChannel* ch, SessionStats* stats);
|
||||
|
||||
// virtual so it can be mocked in unit tests
|
||||
virtual bool GetLocalCertificate(
|
||||
@ -291,6 +336,16 @@ class WebRtcSession : public cricket::BaseSession,
|
||||
kAnswer,
|
||||
};
|
||||
|
||||
// Log session state.
|
||||
void LogState(State old_state, State new_state);
|
||||
|
||||
// Updates the state, signaling if necessary.
|
||||
virtual void SetState(State state);
|
||||
|
||||
// Updates the error state, signaling if necessary.
|
||||
// TODO(ronghuawu): remove the SetError method that doesn't take |error_desc|.
|
||||
virtual void SetError(Error error, const std::string& error_desc);
|
||||
|
||||
bool UpdateSessionState(Action action, cricket::ContentSource source,
|
||||
std::string* err_desc);
|
||||
static Action GetAction(const std::string& type);
|
||||
@ -300,6 +355,27 @@ class WebRtcSession : public cricket::BaseSession,
|
||||
cricket::ContentSource source,
|
||||
std::string* error_desc);
|
||||
|
||||
bool PushdownTransportDescription(cricket::ContentSource source,
|
||||
cricket::ContentAction action,
|
||||
std::string* error_desc);
|
||||
|
||||
// Helper methods to push local and remote transport descriptions.
|
||||
bool PushdownLocalTransportDescription(
|
||||
const cricket::SessionDescription* sdesc,
|
||||
cricket::ContentAction action,
|
||||
std::string* error_desc);
|
||||
bool PushdownRemoteTransportDescription(
|
||||
const cricket::SessionDescription* sdesc,
|
||||
cricket::ContentAction action,
|
||||
std::string* error_desc);
|
||||
|
||||
// Returns true and the TransportInfo of the given |content_name|
|
||||
// from |description|. Returns false if it's not available.
|
||||
static bool GetTransportDescription(
|
||||
const cricket::SessionDescription* description,
|
||||
const std::string& content_name,
|
||||
cricket::TransportDescription* info);
|
||||
|
||||
cricket::BaseChannel* GetChannel(const std::string& content_name);
|
||||
// Cause all the BaseChannels in the bundle group to have the same
|
||||
// transport channel.
|
||||
@ -331,10 +407,6 @@ class WebRtcSession : public cricket::BaseSession,
|
||||
bool CreateVideoChannel(const cricket::ContentInfo* content);
|
||||
bool CreateDataChannel(const cricket::ContentInfo* content);
|
||||
|
||||
// Copy the candidates from |saved_candidates_| to |dest_desc|.
|
||||
// The |saved_candidates_| will be cleared after this function call.
|
||||
void CopySavedCandidates(SessionDescriptionInterface* dest_desc);
|
||||
|
||||
// Listens to SCTP CONTROL messages on unused SIDs and process them as OPEN
|
||||
// messages.
|
||||
void OnDataChannelMessageReceived(cricket::DataChannel* channel,
|
||||
@ -386,6 +458,18 @@ class WebRtcSession : public cricket::BaseSession,
|
||||
|
||||
void ReportNegotiatedCiphers(const cricket::TransportStats& stats);
|
||||
|
||||
rtc::Thread* const signaling_thread_;
|
||||
rtc::Thread* const worker_thread_;
|
||||
cricket::PortAllocator* const port_allocator_;
|
||||
|
||||
State state_ = STATE_INIT;
|
||||
Error error_ = ERROR_NONE;
|
||||
std::string error_desc_;
|
||||
|
||||
const std::string sid_;
|
||||
bool initial_offerer_ = false;
|
||||
|
||||
rtc::scoped_ptr<cricket::TransportController> transport_controller_;
|
||||
rtc::scoped_ptr<MediaControllerInterface> media_controller_;
|
||||
rtc::scoped_ptr<cricket::VoiceChannel> voice_channel_;
|
||||
rtc::scoped_ptr<cricket::VideoChannel> video_channel_;
|
||||
@ -396,8 +480,6 @@ class WebRtcSession : public cricket::BaseSession,
|
||||
bool ice_connection_receiving_;
|
||||
rtc::scoped_ptr<SessionDescriptionInterface> local_desc_;
|
||||
rtc::scoped_ptr<SessionDescriptionInterface> remote_desc_;
|
||||
// Candidates that arrived before the remote description was set.
|
||||
std::vector<IceCandidateInterface*> saved_candidates_;
|
||||
// If the remote peer is using a older version of implementation.
|
||||
bool older_version_remote_peer_;
|
||||
bool dtls_enabled_;
|
||||
|
||||
@ -70,7 +70,6 @@
|
||||
return; \
|
||||
}
|
||||
|
||||
using cricket::BaseSession;
|
||||
using cricket::DF_PLAY;
|
||||
using cricket::DF_SEND;
|
||||
using cricket::FakeVoiceMediaChannel;
|
||||
@ -92,6 +91,7 @@ using webrtc::JsepSessionDescription;
|
||||
using webrtc::PeerConnectionFactoryInterface;
|
||||
using webrtc::PeerConnectionInterface;
|
||||
using webrtc::SessionDescriptionInterface;
|
||||
using webrtc::SessionStats;
|
||||
using webrtc::StreamCollection;
|
||||
using webrtc::WebRtcSession;
|
||||
using webrtc::kBundleWithoutRtcpMux;
|
||||
@ -857,7 +857,7 @@ class WebRtcSessionTest
|
||||
session_->MaybeStartGathering();
|
||||
}
|
||||
void SetLocalDescriptionExpectState(SessionDescriptionInterface* desc,
|
||||
BaseSession::State expected_state) {
|
||||
WebRtcSession::State expected_state) {
|
||||
SetLocalDescriptionWithoutError(desc);
|
||||
EXPECT_EQ(expected_state, session_->state());
|
||||
}
|
||||
@ -885,7 +885,7 @@ class WebRtcSessionTest
|
||||
EXPECT_TRUE(session_->SetRemoteDescription(desc, NULL));
|
||||
}
|
||||
void SetRemoteDescriptionExpectState(SessionDescriptionInterface* desc,
|
||||
BaseSession::State expected_state) {
|
||||
WebRtcSession::State expected_state) {
|
||||
SetRemoteDescriptionWithoutError(desc);
|
||||
EXPECT_EQ(expected_state, session_->state());
|
||||
}
|
||||
@ -1946,8 +1946,8 @@ TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteOffer) {
|
||||
SessionDescriptionInterface* offer = CreateOffer();
|
||||
SetLocalDescriptionWithoutError(offer);
|
||||
offer = CreateOffer();
|
||||
SetRemoteDescriptionOfferExpectError(
|
||||
"Called in wrong state: STATE_SENTINITIATE", offer);
|
||||
SetRemoteDescriptionOfferExpectError("Called in wrong state: STATE_SENTOFFER",
|
||||
offer);
|
||||
}
|
||||
|
||||
TEST_F(WebRtcSessionTest, TestSetRemoteAndLocalOffer) {
|
||||
@ -1957,44 +1957,44 @@ TEST_F(WebRtcSessionTest, TestSetRemoteAndLocalOffer) {
|
||||
SetRemoteDescriptionWithoutError(offer);
|
||||
offer = CreateOffer();
|
||||
SetLocalDescriptionOfferExpectError(
|
||||
"Called in wrong state: STATE_RECEIVEDINITIATE", offer);
|
||||
"Called in wrong state: STATE_RECEIVEDOFFER", offer);
|
||||
}
|
||||
|
||||
TEST_F(WebRtcSessionTest, TestSetLocalPrAnswer) {
|
||||
Init();
|
||||
SendNothing();
|
||||
SessionDescriptionInterface* offer = CreateRemoteOffer();
|
||||
SetRemoteDescriptionExpectState(offer, BaseSession::STATE_RECEIVEDINITIATE);
|
||||
SetRemoteDescriptionExpectState(offer, WebRtcSession::STATE_RECEIVEDOFFER);
|
||||
|
||||
JsepSessionDescription* pranswer = static_cast<JsepSessionDescription*>(
|
||||
CreateAnswer(NULL));
|
||||
pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
|
||||
SetLocalDescriptionExpectState(pranswer, BaseSession::STATE_SENTPRACCEPT);
|
||||
SetLocalDescriptionExpectState(pranswer, WebRtcSession::STATE_SENTPRANSWER);
|
||||
|
||||
SendAudioVideoStream1();
|
||||
JsepSessionDescription* pranswer2 = static_cast<JsepSessionDescription*>(
|
||||
CreateAnswer(NULL));
|
||||
pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
|
||||
|
||||
SetLocalDescriptionExpectState(pranswer2, BaseSession::STATE_SENTPRACCEPT);
|
||||
SetLocalDescriptionExpectState(pranswer2, WebRtcSession::STATE_SENTPRANSWER);
|
||||
|
||||
SendAudioVideoStream2();
|
||||
SessionDescriptionInterface* answer = CreateAnswer(NULL);
|
||||
SetLocalDescriptionExpectState(answer, BaseSession::STATE_SENTACCEPT);
|
||||
SetLocalDescriptionExpectState(answer, WebRtcSession::STATE_INPROGRESS);
|
||||
}
|
||||
|
||||
TEST_F(WebRtcSessionTest, TestSetRemotePrAnswer) {
|
||||
Init();
|
||||
SendNothing();
|
||||
SessionDescriptionInterface* offer = CreateOffer();
|
||||
SetLocalDescriptionExpectState(offer, BaseSession::STATE_SENTINITIATE);
|
||||
SetLocalDescriptionExpectState(offer, WebRtcSession::STATE_SENTOFFER);
|
||||
|
||||
JsepSessionDescription* pranswer =
|
||||
CreateRemoteAnswer(session_->local_description());
|
||||
pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
|
||||
|
||||
SetRemoteDescriptionExpectState(pranswer,
|
||||
BaseSession::STATE_RECEIVEDPRACCEPT);
|
||||
WebRtcSession::STATE_RECEIVEDPRANSWER);
|
||||
|
||||
SendAudioVideoStream1();
|
||||
JsepSessionDescription* pranswer2 =
|
||||
@ -2002,12 +2002,12 @@ TEST_F(WebRtcSessionTest, TestSetRemotePrAnswer) {
|
||||
pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
|
||||
|
||||
SetRemoteDescriptionExpectState(pranswer2,
|
||||
BaseSession::STATE_RECEIVEDPRACCEPT);
|
||||
WebRtcSession::STATE_RECEIVEDPRANSWER);
|
||||
|
||||
SendAudioVideoStream2();
|
||||
SessionDescriptionInterface* answer =
|
||||
CreateRemoteAnswer(session_->local_description());
|
||||
SetRemoteDescriptionExpectState(answer, BaseSession::STATE_RECEIVEDACCEPT);
|
||||
SetRemoteDescriptionExpectState(answer, WebRtcSession::STATE_INPROGRESS);
|
||||
}
|
||||
|
||||
TEST_F(WebRtcSessionTest, TestSetLocalAnswerWithoutOffer) {
|
||||
@ -2040,21 +2040,24 @@ TEST_F(WebRtcSessionTest, TestAddRemoteCandidate) {
|
||||
candidate.set_component(1);
|
||||
JsepIceCandidate ice_candidate1(kMediaContentName0, 0, candidate);
|
||||
|
||||
// Fail since we have not set a offer description.
|
||||
// Fail since we have not set a remote description.
|
||||
EXPECT_FALSE(session_->ProcessIceMessage(&ice_candidate1));
|
||||
|
||||
SessionDescriptionInterface* offer = CreateOffer();
|
||||
SetLocalDescriptionWithoutError(offer);
|
||||
// Candidate should be allowed to add before remote description.
|
||||
EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
|
||||
candidate.set_component(2);
|
||||
JsepIceCandidate ice_candidate2(kMediaContentName0, 0, candidate);
|
||||
EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
|
||||
|
||||
// Fail since we have not set a remote description.
|
||||
EXPECT_FALSE(session_->ProcessIceMessage(&ice_candidate1));
|
||||
|
||||
SessionDescriptionInterface* answer = CreateRemoteAnswer(
|
||||
session_->local_description());
|
||||
SetRemoteDescriptionWithoutError(answer);
|
||||
|
||||
EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
|
||||
candidate.set_component(2);
|
||||
JsepIceCandidate ice_candidate2(kMediaContentName0, 0, candidate);
|
||||
EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
|
||||
|
||||
// Verifying the candidates are copied properly from internal vector.
|
||||
const SessionDescriptionInterface* remote_desc =
|
||||
session_->remote_description();
|
||||
@ -2231,8 +2234,9 @@ TEST_F(WebRtcSessionTest, TestChannelCreationsWithContentNames) {
|
||||
rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
|
||||
|
||||
// CreateOffer creates session description with the content names "audio" and
|
||||
// "video". Goal is to modify these content names and verify transport channel
|
||||
// proxy in the BaseSession, as proxies are created with the content names
|
||||
// "video". Goal is to modify these content names and verify transport
|
||||
// channels
|
||||
// in the WebRtcSession, as channels are created with the content names
|
||||
// present in SDP.
|
||||
std::string sdp;
|
||||
EXPECT_TRUE(offer->ToString(&sdp));
|
||||
@ -2812,7 +2816,7 @@ TEST_F(WebRtcSessionTest, TestSetRemoteDescriptionWithIceRestart) {
|
||||
}
|
||||
|
||||
// Test that candidates sent to the "video" transport do not get pushed down to
|
||||
// the "audio" transport channel when bundling using TransportProxy.
|
||||
// the "audio" transport channel when bundling.
|
||||
TEST_F(WebRtcSessionTest, TestIgnoreCandidatesForUnusedTransportWhenBundling) {
|
||||
AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
|
||||
|
||||
@ -2837,7 +2841,7 @@ TEST_F(WebRtcSessionTest, TestIgnoreCandidatesForUnusedTransportWhenBundling) {
|
||||
// Checks if one of the transport channels contains a connection using a given
|
||||
// port.
|
||||
auto connection_with_remote_port = [this, voice_channel](int port) {
|
||||
cricket::SessionStats stats;
|
||||
SessionStats stats;
|
||||
session_->GetChannelTransportStats(voice_channel, &stats);
|
||||
for (auto& kv : stats.transport_stats) {
|
||||
for (auto& chan_stat : kv.second.channel_stats) {
|
||||
@ -2996,14 +3000,14 @@ TEST_F(WebRtcSessionTest, TestMaxBundleRejectAudio) {
|
||||
CreateRemoteAnswer(session_->local_description(), recv_options);
|
||||
SetRemoteDescriptionWithoutError(answer);
|
||||
|
||||
EXPECT_TRUE(NULL == session_->voice_channel());
|
||||
EXPECT_TRUE(NULL != session_->video_rtp_transport_channel());
|
||||
EXPECT_TRUE(nullptr == session_->voice_channel());
|
||||
EXPECT_TRUE(nullptr != session_->video_rtp_transport_channel());
|
||||
|
||||
session_->Terminate();
|
||||
EXPECT_TRUE(NULL == session_->voice_rtp_transport_channel());
|
||||
EXPECT_TRUE(NULL == session_->voice_rtcp_transport_channel());
|
||||
EXPECT_TRUE(NULL == session_->video_rtp_transport_channel());
|
||||
EXPECT_TRUE(NULL == session_->video_rtcp_transport_channel());
|
||||
session_->Close();
|
||||
EXPECT_TRUE(nullptr == session_->voice_rtp_transport_channel());
|
||||
EXPECT_TRUE(nullptr == session_->voice_rtcp_transport_channel());
|
||||
EXPECT_TRUE(nullptr == session_->video_rtp_transport_channel());
|
||||
EXPECT_TRUE(nullptr == session_->video_rtcp_transport_channel());
|
||||
}
|
||||
|
||||
// kBundlePolicyMaxBundle policy but no BUNDLE in the answer.
|
||||
@ -3349,29 +3353,30 @@ TEST_F(WebRtcSessionTest, InsertDtmf) {
|
||||
expected_duration, expected_flags));
|
||||
}
|
||||
|
||||
// This test verifies the |initiator| flag when session initiates the call.
|
||||
// This test verifies the |initial_offerer| flag when session initiates the
|
||||
// call.
|
||||
TEST_F(WebRtcSessionTest, TestInitiatorFlagAsOriginator) {
|
||||
Init();
|
||||
EXPECT_FALSE(session_->initiator());
|
||||
EXPECT_FALSE(session_->initial_offerer());
|
||||
SessionDescriptionInterface* offer = CreateOffer();
|
||||
SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
|
||||
SetLocalDescriptionWithoutError(offer);
|
||||
EXPECT_TRUE(session_->initiator());
|
||||
EXPECT_TRUE(session_->initial_offerer());
|
||||
SetRemoteDescriptionWithoutError(answer);
|
||||
EXPECT_TRUE(session_->initiator());
|
||||
EXPECT_TRUE(session_->initial_offerer());
|
||||
}
|
||||
|
||||
// This test verifies the |initiator| flag when session receives the call.
|
||||
// This test verifies the |initial_offerer| flag when session receives the call.
|
||||
TEST_F(WebRtcSessionTest, TestInitiatorFlagAsReceiver) {
|
||||
Init();
|
||||
EXPECT_FALSE(session_->initiator());
|
||||
EXPECT_FALSE(session_->initial_offerer());
|
||||
SessionDescriptionInterface* offer = CreateRemoteOffer();
|
||||
SetRemoteDescriptionWithoutError(offer);
|
||||
SessionDescriptionInterface* answer = CreateAnswer(NULL);
|
||||
|
||||
EXPECT_FALSE(session_->initiator());
|
||||
EXPECT_FALSE(session_->initial_offerer());
|
||||
SetLocalDescriptionWithoutError(answer);
|
||||
EXPECT_FALSE(session_->initiator());
|
||||
EXPECT_FALSE(session_->initial_offerer());
|
||||
}
|
||||
|
||||
// Verifing local offer and remote answer have matching m-lines as per RFC 3264.
|
||||
@ -3583,10 +3588,17 @@ TEST_F(WebRtcSessionTest, TestSessionContentError) {
|
||||
video_channel_ = media_engine_->GetVideoChannel(0);
|
||||
video_channel_->set_fail_set_send_codecs(true);
|
||||
|
||||
SendAudioVideoStream2();
|
||||
SessionDescriptionInterface* answer =
|
||||
CreateRemoteAnswer(session_->local_description());
|
||||
SetRemoteDescriptionAnswerExpectError("ERROR_CONTENT", answer);
|
||||
|
||||
// Test that after a content error, setting any description will
|
||||
// result in an error.
|
||||
video_channel_->set_fail_set_send_codecs(false);
|
||||
answer = CreateRemoteAnswer(session_->local_description());
|
||||
SetRemoteDescriptionExpectError("", "ERROR_CONTENT", answer);
|
||||
offer = CreateRemoteOffer();
|
||||
SetLocalDescriptionExpectError("", "ERROR_CONTENT", offer);
|
||||
}
|
||||
|
||||
// Runs the loopback call test with BUNDLE and STUN disabled.
|
||||
@ -3620,28 +3632,6 @@ TEST_F(WebRtcSessionTest, TestIceStatesBundle) {
|
||||
TestLoopbackCall();
|
||||
}
|
||||
|
||||
TEST_F(WebRtcSessionTest, SetSdpFailedOnSessionError) {
|
||||
Init();
|
||||
cricket::MediaSessionOptions options;
|
||||
options.recv_video = true;
|
||||
|
||||
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* answer =
|
||||
CreateRemoteAnswer(offer, options);
|
||||
|
||||
std::string action;
|
||||
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) {
|
||||
constraints_.reset(new FakeConstraints());
|
||||
constraints_->AddOptional(
|
||||
|
||||
@ -366,10 +366,10 @@ void WebRtcSessionDescriptionFactory::OnMessage(rtc::Message* msg) {
|
||||
|
||||
void WebRtcSessionDescriptionFactory::InternalCreateOffer(
|
||||
CreateSessionDescriptionRequest request) {
|
||||
cricket::SessionDescription* desc(
|
||||
session_desc_factory_.CreateOffer(
|
||||
request.options,
|
||||
static_cast<cricket::BaseSession*>(session_)->local_description()));
|
||||
cricket::SessionDescription* desc(session_desc_factory_.CreateOffer(
|
||||
request.options, session_->local_description()
|
||||
? session_->local_description()->description()
|
||||
: nullptr));
|
||||
// RFC 3264
|
||||
// When issuing an offer that modifies the session,
|
||||
// the "o=" line of the new SDP MUST be identical to that in the
|
||||
@ -413,9 +413,12 @@ void WebRtcSessionDescriptionFactory::InternalCreateAnswer(
|
||||
}
|
||||
|
||||
cricket::SessionDescription* desc(session_desc_factory_.CreateAnswer(
|
||||
static_cast<cricket::BaseSession*>(session_)->remote_description(),
|
||||
request.options,
|
||||
static_cast<cricket::BaseSession*>(session_)->local_description()));
|
||||
session_->remote_description()
|
||||
? session_->remote_description()->description()
|
||||
: nullptr,
|
||||
request.options, session_->local_description()
|
||||
? session_->local_description()->description()
|
||||
: nullptr));
|
||||
// RFC 3264
|
||||
// If the answer is different from the offer in any way (different IP
|
||||
// addresses, ports, etc.), the origin line MUST be different in the answer.
|
||||
|
||||
@ -33,7 +33,6 @@
|
||||
|
||||
#include "talk/media/base/capturemanager.h"
|
||||
#include "talk/media/base/mediaengine.h"
|
||||
#include "webrtc/p2p/base/session.h"
|
||||
#include "talk/session/media/voicechannel.h"
|
||||
#include "webrtc/base/criticalsection.h"
|
||||
#include "webrtc/base/fileutils.h"
|
||||
|
||||
@ -41,14 +41,12 @@ const int kDefaultMinTimeBetweenSwitches = 1000;
|
||||
}
|
||||
|
||||
CurrentSpeakerMonitor::CurrentSpeakerMonitor(
|
||||
AudioSourceContext* audio_source_context, BaseSession* session)
|
||||
AudioSourceContext* audio_source_context)
|
||||
: started_(false),
|
||||
audio_source_context_(audio_source_context),
|
||||
session_(session),
|
||||
current_speaker_ssrc_(0),
|
||||
earliest_permitted_switch_time_(0),
|
||||
min_time_between_switches_(kDefaultMinTimeBetweenSwitches) {
|
||||
}
|
||||
min_time_between_switches_(kDefaultMinTimeBetweenSwitches) {}
|
||||
|
||||
CurrentSpeakerMonitor::~CurrentSpeakerMonitor() {
|
||||
Stop();
|
||||
@ -193,10 +191,10 @@ void CurrentSpeakerMonitor::OnAudioMonitor(
|
||||
}
|
||||
|
||||
void CurrentSpeakerMonitor::OnMediaStreamsUpdate(
|
||||
AudioSourceContext* audio_source_context, BaseSession* session,
|
||||
const MediaStreams& added, const MediaStreams& removed) {
|
||||
|
||||
if (audio_source_context == audio_source_context_ && session == session_) {
|
||||
AudioSourceContext* audio_source_context,
|
||||
const MediaStreams& added,
|
||||
const MediaStreams& removed) {
|
||||
if (audio_source_context == audio_source_context_) {
|
||||
// Update the speaking state map based on added and removed streams.
|
||||
for (std::vector<cricket::StreamParams>::const_iterator
|
||||
it = removed.audio().begin(); it != removed.audio().end(); ++it) {
|
||||
@ -211,8 +209,8 @@ void CurrentSpeakerMonitor::OnMediaStreamsUpdate(
|
||||
}
|
||||
|
||||
void CurrentSpeakerMonitor::OnMediaStreamsReset(
|
||||
AudioSourceContext* audio_source_context, BaseSession* session) {
|
||||
if (audio_source_context == audio_source_context_ && session == session_) {
|
||||
AudioSourceContext* audio_source_context) {
|
||||
if (audio_source_context == audio_source_context_) {
|
||||
ssrc_to_speaking_state_map_.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,7 +38,6 @@
|
||||
|
||||
namespace cricket {
|
||||
|
||||
class BaseSession;
|
||||
struct AudioInfo;
|
||||
struct MediaStreams;
|
||||
|
||||
@ -46,11 +45,10 @@ class AudioSourceContext {
|
||||
public:
|
||||
sigslot::signal2<AudioSourceContext*, const cricket::AudioInfo&>
|
||||
SignalAudioMonitor;
|
||||
sigslot::signal2<AudioSourceContext*, cricket::BaseSession*>
|
||||
SignalMediaStreamsReset;
|
||||
sigslot::signal4<AudioSourceContext*, cricket::BaseSession*,
|
||||
const cricket::MediaStreams&, const cricket::MediaStreams&>
|
||||
SignalMediaStreamsUpdate;
|
||||
sigslot::signal1<AudioSourceContext*> SignalMediaStreamsReset;
|
||||
sigslot::signal3<AudioSourceContext*,
|
||||
const cricket::MediaStreams&,
|
||||
const cricket::MediaStreams&> SignalMediaStreamsUpdate;
|
||||
};
|
||||
|
||||
// CurrentSpeakerMonitor can be used to monitor the audio-levels from
|
||||
@ -64,12 +62,9 @@ class AudioSourceContext {
|
||||
// It's recommended that the audio monitor be started with a 100 ms period.
|
||||
class CurrentSpeakerMonitor : public sigslot::has_slots<> {
|
||||
public:
|
||||
CurrentSpeakerMonitor(AudioSourceContext* audio_source_context,
|
||||
BaseSession* session);
|
||||
CurrentSpeakerMonitor(AudioSourceContext* audio_source_context);
|
||||
~CurrentSpeakerMonitor();
|
||||
|
||||
BaseSession* session() const { return session_; }
|
||||
|
||||
void Start();
|
||||
void Stop();
|
||||
|
||||
@ -87,11 +82,9 @@ class CurrentSpeakerMonitor : public sigslot::has_slots<> {
|
||||
void OnAudioMonitor(AudioSourceContext* audio_source_context,
|
||||
const AudioInfo& info);
|
||||
void OnMediaStreamsUpdate(AudioSourceContext* audio_source_context,
|
||||
BaseSession* session,
|
||||
const MediaStreams& added,
|
||||
const MediaStreams& removed);
|
||||
void OnMediaStreamsReset(AudioSourceContext* audio_source_context,
|
||||
BaseSession* session);
|
||||
void OnMediaStreamsReset(AudioSourceContext* audio_source_context);
|
||||
|
||||
// These are states that a participant will pass through so that we gradually
|
||||
// recognize that they have started and stopped speaking. This avoids
|
||||
@ -106,7 +99,6 @@ class CurrentSpeakerMonitor : public sigslot::has_slots<> {
|
||||
|
||||
bool started_;
|
||||
AudioSourceContext* audio_source_context_;
|
||||
BaseSession* session_;
|
||||
std::map<uint32_t, SpeakingState> ssrc_to_speaking_state_map_;
|
||||
uint32_t current_speaker_ssrc_;
|
||||
// To prevent overswitching, switching is disabled for some time after a
|
||||
|
||||
@ -46,7 +46,7 @@ class CurrentSpeakerMonitorTest : public testing::Test,
|
||||
public sigslot::has_slots<> {
|
||||
public:
|
||||
CurrentSpeakerMonitorTest() {
|
||||
monitor_ = new CurrentSpeakerMonitor(&source_, NULL);
|
||||
monitor_ = new CurrentSpeakerMonitor(&source_);
|
||||
// Shrink the minimum time betweeen switches to 10 ms so we don't have to
|
||||
// slow down our tests.
|
||||
monitor_->set_min_time_between_switches(kMinTimeBetweenSwitches);
|
||||
|
||||
@ -8,254 +8,5 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/p2p/base/session.h"
|
||||
|
||||
#include "webrtc/base/bind.h"
|
||||
#include "webrtc/base/common.h"
|
||||
#include "webrtc/base/helpers.h"
|
||||
#include "webrtc/base/logging.h"
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/base/stringencode.h"
|
||||
#include "webrtc/base/sslstreamadapter.h"
|
||||
#include "webrtc/p2p/base/transport.h"
|
||||
#include "webrtc/p2p/base/transportinfo.h"
|
||||
#include "webrtc/p2p/base/transportcontroller.h"
|
||||
#include "webrtc/p2p/base/constants.h"
|
||||
|
||||
namespace cricket {
|
||||
|
||||
using rtc::Bind;
|
||||
|
||||
std::string BaseSession::StateToString(State state) {
|
||||
switch (state) {
|
||||
case STATE_INIT:
|
||||
return "STATE_INIT";
|
||||
case STATE_SENTINITIATE:
|
||||
return "STATE_SENTINITIATE";
|
||||
case STATE_RECEIVEDINITIATE:
|
||||
return "STATE_RECEIVEDINITIATE";
|
||||
case STATE_SENTPRACCEPT:
|
||||
return "STATE_SENTPRACCEPT";
|
||||
case STATE_SENTACCEPT:
|
||||
return "STATE_SENTACCEPT";
|
||||
case STATE_RECEIVEDPRACCEPT:
|
||||
return "STATE_RECEIVEDPRACCEPT";
|
||||
case STATE_RECEIVEDACCEPT:
|
||||
return "STATE_RECEIVEDACCEPT";
|
||||
case STATE_SENTMODIFY:
|
||||
return "STATE_SENTMODIFY";
|
||||
case STATE_RECEIVEDMODIFY:
|
||||
return "STATE_RECEIVEDMODIFY";
|
||||
case STATE_SENTREJECT:
|
||||
return "STATE_SENTREJECT";
|
||||
case STATE_RECEIVEDREJECT:
|
||||
return "STATE_RECEIVEDREJECT";
|
||||
case STATE_SENTREDIRECT:
|
||||
return "STATE_SENTREDIRECT";
|
||||
case STATE_SENTTERMINATE:
|
||||
return "STATE_SENTTERMINATE";
|
||||
case STATE_RECEIVEDTERMINATE:
|
||||
return "STATE_RECEIVEDTERMINATE";
|
||||
case STATE_INPROGRESS:
|
||||
return "STATE_INPROGRESS";
|
||||
case STATE_DEINIT:
|
||||
return "STATE_DEINIT";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "STATE_" + rtc::ToString(state);
|
||||
}
|
||||
|
||||
BaseSession::BaseSession(rtc::Thread* signaling_thread,
|
||||
rtc::Thread* worker_thread,
|
||||
PortAllocator* port_allocator,
|
||||
const std::string& sid,
|
||||
bool initiator)
|
||||
: state_(STATE_INIT),
|
||||
error_(ERROR_NONE),
|
||||
signaling_thread_(signaling_thread),
|
||||
worker_thread_(worker_thread),
|
||||
port_allocator_(port_allocator),
|
||||
sid_(sid),
|
||||
transport_controller_(new TransportController(signaling_thread,
|
||||
worker_thread,
|
||||
port_allocator)) {
|
||||
ASSERT(signaling_thread->IsCurrent());
|
||||
set_initiator(initiator);
|
||||
}
|
||||
|
||||
BaseSession::~BaseSession() {
|
||||
ASSERT(signaling_thread()->IsCurrent());
|
||||
|
||||
ASSERT(state_ != STATE_DEINIT);
|
||||
LogState(state_, STATE_DEINIT);
|
||||
state_ = STATE_DEINIT;
|
||||
SignalState(this, state_);
|
||||
}
|
||||
|
||||
const SessionDescription* BaseSession::local_description() const {
|
||||
// TODO(tommi): Assert on thread correctness.
|
||||
return local_description_.get();
|
||||
}
|
||||
|
||||
const SessionDescription* BaseSession::remote_description() const {
|
||||
// TODO(tommi): Assert on thread correctness.
|
||||
return remote_description_.get();
|
||||
}
|
||||
|
||||
SessionDescription* BaseSession::remote_description() {
|
||||
// TODO(tommi): Assert on thread correctness.
|
||||
return remote_description_.get();
|
||||
}
|
||||
|
||||
void BaseSession::set_local_description(const SessionDescription* sdesc) {
|
||||
// TODO(tommi): Assert on thread correctness.
|
||||
if (sdesc != local_description_.get())
|
||||
local_description_.reset(sdesc);
|
||||
}
|
||||
|
||||
void BaseSession::set_remote_description(SessionDescription* sdesc) {
|
||||
// TODO(tommi): Assert on thread correctness.
|
||||
if (sdesc != remote_description_)
|
||||
remote_description_.reset(sdesc);
|
||||
}
|
||||
|
||||
void BaseSession::set_initiator(bool initiator) {
|
||||
initiator_ = initiator;
|
||||
|
||||
IceRole ice_role = initiator ? ICEROLE_CONTROLLING : ICEROLE_CONTROLLED;
|
||||
transport_controller_->SetIceRole(ice_role);
|
||||
}
|
||||
|
||||
const SessionDescription* BaseSession::initiator_description() const {
|
||||
// TODO(tommi): Assert on thread correctness.
|
||||
return initiator_ ? local_description_.get() : remote_description_.get();
|
||||
}
|
||||
|
||||
bool BaseSession::PushdownTransportDescription(ContentSource source,
|
||||
ContentAction action,
|
||||
std::string* error_desc) {
|
||||
ASSERT(signaling_thread()->IsCurrent());
|
||||
|
||||
if (source == CS_LOCAL) {
|
||||
return PushdownLocalTransportDescription(local_description(),
|
||||
action,
|
||||
error_desc);
|
||||
}
|
||||
return PushdownRemoteTransportDescription(remote_description(),
|
||||
action,
|
||||
error_desc);
|
||||
}
|
||||
|
||||
bool BaseSession::PushdownLocalTransportDescription(
|
||||
const SessionDescription* sdesc,
|
||||
ContentAction action,
|
||||
std::string* err) {
|
||||
ASSERT(signaling_thread()->IsCurrent());
|
||||
|
||||
if (!sdesc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const TransportInfo& tinfo : sdesc->transport_infos()) {
|
||||
if (!transport_controller_->SetLocalTransportDescription(
|
||||
tinfo.content_name, tinfo.description, action, err)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BaseSession::PushdownRemoteTransportDescription(
|
||||
const SessionDescription* sdesc,
|
||||
ContentAction action,
|
||||
std::string* err) {
|
||||
ASSERT(signaling_thread()->IsCurrent());
|
||||
|
||||
if (!sdesc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const TransportInfo& tinfo : sdesc->transport_infos()) {
|
||||
if (!transport_controller_->SetRemoteTransportDescription(
|
||||
tinfo.content_name, tinfo.description, action, err)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BaseSession::SetState(State state) {
|
||||
ASSERT(signaling_thread_->IsCurrent());
|
||||
if (state != state_) {
|
||||
LogState(state_, state);
|
||||
state_ = state;
|
||||
SignalState(this, state_);
|
||||
signaling_thread_->Post(this, MSG_STATE);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseSession::SetError(Error error, const std::string& error_desc) {
|
||||
ASSERT(signaling_thread_->IsCurrent());
|
||||
if (error != error_) {
|
||||
error_ = error;
|
||||
error_desc_ = error_desc;
|
||||
SignalError(this, error);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseSession::SetIceConfig(const IceConfig& config) {
|
||||
transport_controller_->SetIceConfig(config);
|
||||
}
|
||||
|
||||
void BaseSession::MaybeStartGathering() {
|
||||
transport_controller_->MaybeStartGathering();
|
||||
}
|
||||
|
||||
void BaseSession::LogState(State old_state, State new_state) {
|
||||
LOG(LS_INFO) << "Session:" << id()
|
||||
<< " Old state:" << StateToString(old_state)
|
||||
<< " New state:" << StateToString(new_state);
|
||||
}
|
||||
|
||||
// static
|
||||
bool BaseSession::GetTransportDescription(const SessionDescription* description,
|
||||
const std::string& content_name,
|
||||
TransportDescription* tdesc) {
|
||||
if (!description || !tdesc) {
|
||||
return false;
|
||||
}
|
||||
const TransportInfo* transport_info =
|
||||
description->GetTransportInfoByName(content_name);
|
||||
if (!transport_info) {
|
||||
return false;
|
||||
}
|
||||
*tdesc = transport_info->description;
|
||||
return true;
|
||||
}
|
||||
|
||||
void BaseSession::OnMessage(rtc::Message *pmsg) {
|
||||
switch (pmsg->message_id) {
|
||||
case MSG_TIMEOUT:
|
||||
// Session timeout has occured.
|
||||
SetError(ERROR_TIME, "Session timeout has occured.");
|
||||
break;
|
||||
|
||||
case MSG_STATE:
|
||||
switch (state_) {
|
||||
case STATE_SENTACCEPT:
|
||||
case STATE_RECEIVEDACCEPT:
|
||||
SetState(STATE_INPROGRESS);
|
||||
break;
|
||||
|
||||
default:
|
||||
// Explicitly ignoring some states here.
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace cricket
|
||||
// TODO(deadbeef): Remove this file when Chrome build files no longer reference
|
||||
// it.
|
||||
|
||||
@ -8,195 +8,6 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_P2P_BASE_SESSION_H_
|
||||
#define WEBRTC_P2P_BASE_SESSION_H_
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/base/refcount.h"
|
||||
#include "webrtc/base/rtccertificate.h"
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/base/scoped_ref_ptr.h"
|
||||
#include "webrtc/base/socketaddress.h"
|
||||
#include "webrtc/p2p/base/candidate.h"
|
||||
#include "webrtc/p2p/base/port.h"
|
||||
#include "webrtc/p2p/base/transport.h"
|
||||
|
||||
namespace cricket {
|
||||
|
||||
class BaseSession;
|
||||
class P2PTransportChannel;
|
||||
class Transport;
|
||||
class TransportChannel;
|
||||
class TransportChannelImpl;
|
||||
class TransportController;
|
||||
|
||||
// Statistics for all the transports of this session.
|
||||
typedef std::map<std::string, TransportStats> TransportStatsMap;
|
||||
typedef std::map<std::string, std::string> ProxyTransportMap;
|
||||
|
||||
// TODO(pthatcher): Think of a better name for this. We already have
|
||||
// a TransportStats in transport.h. Perhaps TransportsStats?
|
||||
struct SessionStats {
|
||||
ProxyTransportMap proxy_to_transport;
|
||||
TransportStatsMap transport_stats;
|
||||
};
|
||||
|
||||
// A BaseSession manages general session state. This includes negotiation
|
||||
// of both the application-level and network-level protocols: the former
|
||||
// defines what will be sent and the latter defines how it will be sent. Each
|
||||
// network-level protocol is represented by a Transport object. Each Transport
|
||||
// participates in the network-level negotiation. The individual streams of
|
||||
// packets are represented by TransportChannels. The application-level protocol
|
||||
// is represented by SessionDecription objects.
|
||||
class BaseSession : public sigslot::has_slots<>,
|
||||
public rtc::MessageHandler {
|
||||
public:
|
||||
enum {
|
||||
MSG_TIMEOUT = 0,
|
||||
MSG_ERROR,
|
||||
MSG_STATE,
|
||||
};
|
||||
|
||||
enum State {
|
||||
STATE_INIT = 0,
|
||||
STATE_SENTINITIATE, // sent initiate, waiting for Accept or Reject
|
||||
STATE_RECEIVEDINITIATE, // received an initiate. Call Accept or Reject
|
||||
STATE_SENTPRACCEPT, // sent provisional Accept
|
||||
STATE_SENTACCEPT, // sent accept. begin connecting transport
|
||||
STATE_RECEIVEDPRACCEPT, // received provisional Accept, waiting for Accept
|
||||
STATE_RECEIVEDACCEPT, // received accept. begin connecting transport
|
||||
STATE_SENTMODIFY, // sent modify, waiting for Accept or Reject
|
||||
STATE_RECEIVEDMODIFY, // received modify, call Accept or Reject
|
||||
STATE_SENTREJECT, // sent reject after receiving initiate
|
||||
STATE_RECEIVEDREJECT, // received reject after sending initiate
|
||||
STATE_SENTREDIRECT, // sent direct after receiving initiate
|
||||
STATE_SENTTERMINATE, // sent terminate (any time / either side)
|
||||
STATE_RECEIVEDTERMINATE, // received terminate (any time / either side)
|
||||
STATE_INPROGRESS, // session accepted and in progress
|
||||
STATE_DEINIT, // session is being destroyed
|
||||
};
|
||||
|
||||
enum Error {
|
||||
ERROR_NONE = 0, // no error
|
||||
ERROR_TIME = 1, // no response to signaling
|
||||
ERROR_RESPONSE = 2, // error during signaling
|
||||
ERROR_NETWORK = 3, // network error, could not allocate network resources
|
||||
ERROR_CONTENT = 4, // channel errors in SetLocalContent/SetRemoteContent
|
||||
ERROR_TRANSPORT = 5, // transport error of some kind
|
||||
};
|
||||
|
||||
// Convert State to a readable string.
|
||||
static std::string StateToString(State state);
|
||||
|
||||
BaseSession(rtc::Thread* signaling_thread,
|
||||
rtc::Thread* worker_thread,
|
||||
PortAllocator* port_allocator,
|
||||
const std::string& sid,
|
||||
bool initiator);
|
||||
virtual ~BaseSession();
|
||||
|
||||
// These are const to allow them to be called from const methods.
|
||||
rtc::Thread* signaling_thread() const { return signaling_thread_; }
|
||||
rtc::Thread* worker_thread() const { return worker_thread_; }
|
||||
PortAllocator* port_allocator() const { return port_allocator_; }
|
||||
|
||||
// The ID of this session.
|
||||
const std::string& id() const { return sid_; }
|
||||
|
||||
// Returns the application-level description given by our client.
|
||||
// If we are the recipient, this will be NULL until we send an accept.
|
||||
const SessionDescription* local_description() const;
|
||||
|
||||
// Returns the application-level description given by the other client.
|
||||
// If we are the initiator, this will be NULL until we receive an accept.
|
||||
const SessionDescription* remote_description() const;
|
||||
|
||||
SessionDescription* remote_description();
|
||||
|
||||
// Takes ownership of SessionDescription*
|
||||
void set_local_description(const SessionDescription* sdesc);
|
||||
|
||||
// Takes ownership of SessionDescription*
|
||||
void set_remote_description(SessionDescription* sdesc);
|
||||
|
||||
void set_initiator(bool initiator);
|
||||
bool initiator() const { return initiator_; }
|
||||
|
||||
const SessionDescription* initiator_description() const;
|
||||
|
||||
// Returns the current state of the session. See the enum above for details.
|
||||
// Each time the state changes, we will fire this signal.
|
||||
State state() const { return state_; }
|
||||
sigslot::signal2<BaseSession* , State> SignalState;
|
||||
|
||||
// Returns the last error in the session. See the enum above for details.
|
||||
// Each time the an error occurs, we will fire this signal.
|
||||
Error error() const { return error_; }
|
||||
const std::string& error_desc() const { return error_desc_; }
|
||||
sigslot::signal2<BaseSession* , Error> SignalError;
|
||||
|
||||
// Updates the state, signaling if necessary.
|
||||
virtual void SetState(State state);
|
||||
|
||||
// Updates the error state, signaling if necessary.
|
||||
// TODO(ronghuawu): remove the SetError method that doesn't take |error_desc|.
|
||||
virtual void SetError(Error error, const std::string& error_desc);
|
||||
|
||||
void SetIceConfig(const IceConfig& ice_config);
|
||||
|
||||
// Start gathering candidates for any new transports, or transports doing an
|
||||
// ICE restart.
|
||||
void MaybeStartGathering();
|
||||
|
||||
protected:
|
||||
bool PushdownTransportDescription(ContentSource source,
|
||||
ContentAction action,
|
||||
std::string* error_desc);
|
||||
|
||||
// Handles messages posted to us.
|
||||
virtual void OnMessage(rtc::Message *pmsg);
|
||||
|
||||
TransportController* transport_controller() {
|
||||
return transport_controller_.get();
|
||||
}
|
||||
|
||||
protected:
|
||||
State state_;
|
||||
Error error_;
|
||||
std::string error_desc_;
|
||||
|
||||
private:
|
||||
// Helper methods to push local and remote transport descriptions.
|
||||
bool PushdownLocalTransportDescription(
|
||||
const SessionDescription* sdesc, ContentAction action,
|
||||
std::string* error_desc);
|
||||
bool PushdownRemoteTransportDescription(
|
||||
const SessionDescription* sdesc, ContentAction action,
|
||||
std::string* error_desc);
|
||||
|
||||
// Log session state.
|
||||
void LogState(State old_state, State new_state);
|
||||
|
||||
// Returns true and the TransportInfo of the given |content_name|
|
||||
// from |description|. Returns false if it's not available.
|
||||
static bool GetTransportDescription(const SessionDescription* description,
|
||||
const std::string& content_name,
|
||||
TransportDescription* info);
|
||||
|
||||
rtc::Thread* const signaling_thread_;
|
||||
rtc::Thread* const worker_thread_;
|
||||
PortAllocator* const port_allocator_;
|
||||
const std::string sid_;
|
||||
bool initiator_;
|
||||
rtc::scoped_ptr<TransportController> transport_controller_;
|
||||
rtc::scoped_ptr<const SessionDescription> local_description_;
|
||||
rtc::scoped_ptr<SessionDescription> remote_description_;
|
||||
};
|
||||
|
||||
} // namespace cricket
|
||||
|
||||
#endif // WEBRTC_P2P_BASE_SESSION_H_
|
||||
// TODO(deadbeef): Remove this file when Chrome build files no longer reference
|
||||
// it.
|
||||
#error "DONT INCLUDE THIS"
|
||||
|
||||
@ -46,8 +46,6 @@
|
||||
'base/relayport.h',
|
||||
'base/relayserver.cc',
|
||||
'base/relayserver.h',
|
||||
'base/session.cc',
|
||||
'base/session.h',
|
||||
'base/sessiondescription.cc',
|
||||
'base/sessiondescription.h',
|
||||
'base/sessionid.h',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user