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:
deadbeef 2015-10-14 15:02:44 -07:00 committed by Commit bot
parent 83210409e0
commit d59daf8023
16 changed files with 486 additions and 792 deletions

View File

@ -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:

View File

@ -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 {

View File

@ -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;
}

View File

@ -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.

View File

@ -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;

View File

@ -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);
}

View File

@ -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_;

View File

@ -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(

View File

@ -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.

View File

@ -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"

View File

@ -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();
}
}

View File

@ -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

View File

@ -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);

View File

@ -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.

View File

@ -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"

View File

@ -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',