diff --git a/talk/app/webrtc/peerconnection.cc b/talk/app/webrtc/peerconnection.cc index 4df6790a1a..e7b33c43ac 100644 --- a/talk/app/webrtc/peerconnection.cc +++ b/talk/app/webrtc/peerconnection.cc @@ -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: diff --git a/talk/app/webrtc/peerconnection.h b/talk/app/webrtc/peerconnection.h index 0c048988e1..6a66497859 100644 --- a/talk/app/webrtc/peerconnection.h +++ b/talk/app/webrtc/peerconnection.h @@ -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 { diff --git a/talk/app/webrtc/statscollector.cc b/talk/app/webrtc/statscollector.cc index 9ba7da808d..347a84640c 100644 --- a/talk/app/webrtc/statscollector.cc +++ b/talk/app/webrtc/statscollector.cc @@ -70,12 +70,13 @@ typedef TypeForAdd FloatForAdd; typedef TypeForAdd Int64ForAdd; typedef TypeForAdd 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; } diff --git a/talk/app/webrtc/statscollector.h b/talk/app/webrtc/statscollector.h index 714f15a401..18a345d71d 100644 --- a/talk/app/webrtc/statscollector.h +++ b/talk/app/webrtc/statscollector.h @@ -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. diff --git a/talk/app/webrtc/statscollector_unittest.cc b/talk/app/webrtc/statscollector_unittest.cc index 49b992c17f..8b0a9edc1b 100644 --- a/talk/app/webrtc/statscollector_unittest.cc +++ b/talk/app/webrtc/statscollector_unittest.cc @@ -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* 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 stream_; rtc::scoped_refptr track_; rtc::scoped_refptr 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; diff --git a/talk/app/webrtc/webrtcsession.cc b/talk/app/webrtc/webrtcsession.cc index 1a5751a111..f17dd34b75 100644 --- a/talk/app/webrtc/webrtcsession.cc +++ b/talk/app/webrtc/webrtcsession.cc @@ -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 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 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* 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& 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& 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(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(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 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(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); } diff --git a/talk/app/webrtc/webrtcsession.h b/talk/app/webrtc/webrtcsession.h index 8dcc85fabf..f3dd602eba 100644 --- a/talk/app/webrtc/webrtcsession.h +++ b/talk/app/webrtc/webrtcsession.h @@ -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 TransportStatsMap; +typedef std::map 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 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 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 transport_controller_; rtc::scoped_ptr media_controller_; rtc::scoped_ptr voice_channel_; rtc::scoped_ptr video_channel_; @@ -396,8 +480,6 @@ class WebRtcSession : public cricket::BaseSession, bool ice_connection_receiving_; rtc::scoped_ptr local_desc_; rtc::scoped_ptr remote_desc_; - // Candidates that arrived before the remote description was set. - std::vector saved_candidates_; // If the remote peer is using a older version of implementation. bool older_version_remote_peer_; bool dtls_enabled_; diff --git a/talk/app/webrtc/webrtcsession_unittest.cc b/talk/app/webrtc/webrtcsession_unittest.cc index f0558eee3d..f998ca8848 100644 --- a/talk/app/webrtc/webrtcsession_unittest.cc +++ b/talk/app/webrtc/webrtcsession_unittest.cc @@ -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( CreateAnswer(NULL)); pranswer->set_type(SessionDescriptionInterface::kPrAnswer); - SetLocalDescriptionExpectState(pranswer, BaseSession::STATE_SENTPRACCEPT); + SetLocalDescriptionExpectState(pranswer, WebRtcSession::STATE_SENTPRANSWER); SendAudioVideoStream1(); JsepSessionDescription* pranswer2 = static_cast( 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 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( diff --git a/talk/app/webrtc/webrtcsessiondescriptionfactory.cc b/talk/app/webrtc/webrtcsessiondescriptionfactory.cc index d391020cd1..25965af79d 100644 --- a/talk/app/webrtc/webrtcsessiondescriptionfactory.cc +++ b/talk/app/webrtc/webrtcsessiondescriptionfactory.cc @@ -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(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(session_)->remote_description(), - request.options, - static_cast(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. diff --git a/talk/session/media/channelmanager.h b/talk/session/media/channelmanager.h index e0a0fb2a70..c17a60fe01 100644 --- a/talk/session/media/channelmanager.h +++ b/talk/session/media/channelmanager.h @@ -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" diff --git a/talk/session/media/currentspeakermonitor.cc b/talk/session/media/currentspeakermonitor.cc index 5cfab267a0..52a0d0c1d7 100644 --- a/talk/session/media/currentspeakermonitor.cc +++ b/talk/session/media/currentspeakermonitor.cc @@ -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::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(); } } diff --git a/talk/session/media/currentspeakermonitor.h b/talk/session/media/currentspeakermonitor.h index 4dfe6f0997..cef8b733dc 100644 --- a/talk/session/media/currentspeakermonitor.h +++ b/talk/session/media/currentspeakermonitor.h @@ -38,7 +38,6 @@ namespace cricket { -class BaseSession; struct AudioInfo; struct MediaStreams; @@ -46,11 +45,10 @@ class AudioSourceContext { public: sigslot::signal2 SignalAudioMonitor; - sigslot::signal2 - SignalMediaStreamsReset; - sigslot::signal4 - SignalMediaStreamsUpdate; + sigslot::signal1 SignalMediaStreamsReset; + sigslot::signal3 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 ssrc_to_speaking_state_map_; uint32_t current_speaker_ssrc_; // To prevent overswitching, switching is disabled for some time after a diff --git a/talk/session/media/currentspeakermonitor_unittest.cc b/talk/session/media/currentspeakermonitor_unittest.cc index 7970cea18b..fa2a3ce893 100644 --- a/talk/session/media/currentspeakermonitor_unittest.cc +++ b/talk/session/media/currentspeakermonitor_unittest.cc @@ -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); diff --git a/webrtc/p2p/base/session.cc b/webrtc/p2p/base/session.cc index 5e5a88f8d1..1a23f8363f 100644 --- a/webrtc/p2p/base/session.cc +++ b/webrtc/p2p/base/session.cc @@ -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. diff --git a/webrtc/p2p/base/session.h b/webrtc/p2p/base/session.h index 2cf8c8a52f..a98a5efe13 100644 --- a/webrtc/p2p/base/session.h +++ b/webrtc/p2p/base/session.h @@ -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 -#include -#include -#include - -#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 TransportStatsMap; -typedef std::map 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 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 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 transport_controller_; - rtc::scoped_ptr local_description_; - rtc::scoped_ptr 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" diff --git a/webrtc/p2p/p2p.gyp b/webrtc/p2p/p2p.gyp index b5409f4df7..490cfbf087 100644 --- a/webrtc/p2p/p2p.gyp +++ b/webrtc/p2p/p2p.gyp @@ -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',