| Index: talk/session/media/channel.cc
|
| diff --git a/talk/session/media/channel.cc b/talk/session/media/channel.cc
|
| index 294681ef1449aa94033112e8e5315cec5048a0f7..7b5809855f632f4db59876a6d6e05142548254eb 100644
|
| --- a/talk/session/media/channel.cc
|
| +++ b/talk/session/media/channel.cc
|
| @@ -170,15 +170,17 @@ void RtpSendParametersFromMediaDescription(
|
| }
|
|
|
| BaseChannel::BaseChannel(rtc::Thread* thread,
|
| - MediaChannel* media_channel, BaseSession* session,
|
| - const std::string& content_name, bool rtcp)
|
| + MediaChannel* media_channel,
|
| + TransportController* transport_controller,
|
| + const std::string& content_name,
|
| + bool rtcp)
|
| : worker_thread_(thread),
|
| - session_(session),
|
| + transport_controller_(transport_controller),
|
| media_channel_(media_channel),
|
| content_name_(content_name),
|
| - rtcp_(rtcp),
|
| - transport_channel_(NULL),
|
| - rtcp_transport_channel_(NULL),
|
| + rtcp_transport_enabled_(rtcp),
|
| + transport_channel_(nullptr),
|
| + rtcp_transport_channel_(nullptr),
|
| enabled_(false),
|
| writable_(false),
|
| rtp_ready_to_send_(false),
|
| @@ -204,20 +206,31 @@ BaseChannel::~BaseChannel() {
|
| // the media channel may try to send on the dead transport channel. NULLing
|
| // is not an effective strategy since the sends will come on another thread.
|
| delete media_channel_;
|
| - set_transport_channel(nullptr);
|
| - set_rtcp_transport_channel(nullptr);
|
| + // Note that we don't just call set_transport_channel(nullptr) because that
|
| + // would call a pure virtual method which we can't do from a destructor.
|
| + if (transport_channel_) {
|
| + DisconnectFromTransportChannel(transport_channel_);
|
| + transport_controller_->DestroyTransportChannel_w(
|
| + transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTP);
|
| + }
|
| + if (rtcp_transport_channel_) {
|
| + DisconnectFromTransportChannel(rtcp_transport_channel_);
|
| + transport_controller_->DestroyTransportChannel_w(
|
| + transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
|
| + }
|
| LOG(LS_INFO) << "Destroyed channel";
|
| }
|
|
|
| bool BaseChannel::Init() {
|
| - if (!SetTransportChannels(session(), rtcp())) {
|
| + if (!SetTransport(content_name())) {
|
| return false;
|
| }
|
|
|
| if (!SetDtlsSrtpCiphers(transport_channel(), false)) {
|
| return false;
|
| }
|
| - if (rtcp() && !SetDtlsSrtpCiphers(rtcp_transport_channel(), true)) {
|
| + if (rtcp_transport_enabled() &&
|
| + !SetDtlsSrtpCiphers(rtcp_transport_channel(), true)) {
|
| return false;
|
| }
|
|
|
| @@ -231,29 +244,35 @@ void BaseChannel::Deinit() {
|
| media_channel_->SetInterface(NULL);
|
| }
|
|
|
| -bool BaseChannel::SetTransportChannels(BaseSession* session, bool rtcp) {
|
| - return worker_thread_->Invoke<bool>(Bind(
|
| - &BaseChannel::SetTransportChannels_w, this, session, rtcp));
|
| +bool BaseChannel::SetTransport(const std::string& transport_name) {
|
| + return worker_thread_->Invoke<bool>(
|
| + Bind(&BaseChannel::SetTransport_w, this, transport_name));
|
| }
|
|
|
| -bool BaseChannel::SetTransportChannels_w(BaseSession* session, bool rtcp) {
|
| +bool BaseChannel::SetTransport_w(const std::string& transport_name) {
|
| ASSERT(worker_thread_ == rtc::Thread::Current());
|
|
|
| - set_transport_channel(session->CreateChannel(
|
| - content_name(), cricket::ICE_CANDIDATE_COMPONENT_RTP));
|
| + if (transport_name == transport_name_) {
|
| + // Nothing to do if transport name isn't changing
|
| + return true;
|
| + }
|
| +
|
| + set_transport_channel(transport_controller_->CreateTransportChannel_w(
|
| + transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP));
|
| if (!transport_channel()) {
|
| return false;
|
| }
|
| - if (rtcp) {
|
| - set_rtcp_transport_channel(session->CreateChannel(
|
| - content_name(), cricket::ICE_CANDIDATE_COMPONENT_RTCP));
|
| + if (rtcp_transport_enabled()) {
|
| + LOG(LS_INFO) << "Create RTCP TransportChannel for " << content_name()
|
| + << " on " << transport_name << " transport ";
|
| + set_rtcp_transport_channel(transport_controller_->CreateTransportChannel_w(
|
| + transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP));
|
| if (!rtcp_transport_channel()) {
|
| return false;
|
| }
|
| - } else {
|
| - set_rtcp_transport_channel(nullptr);
|
| }
|
|
|
| + transport_name_ = transport_name;
|
| return true;
|
| }
|
|
|
| @@ -261,42 +280,62 @@ void BaseChannel::set_transport_channel(TransportChannel* new_tc) {
|
| ASSERT(worker_thread_ == rtc::Thread::Current());
|
|
|
| TransportChannel* old_tc = transport_channel_;
|
| -
|
| - if (old_tc == new_tc) {
|
| + if (!old_tc && !new_tc) {
|
| + // Nothing to do
|
| return;
|
| }
|
| + ASSERT(old_tc != new_tc);
|
| +
|
| if (old_tc) {
|
| DisconnectFromTransportChannel(old_tc);
|
| - session()->DestroyChannel(
|
| - content_name(), cricket::ICE_CANDIDATE_COMPONENT_RTP);
|
| + transport_controller_->DestroyTransportChannel_w(
|
| + transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTP);
|
| }
|
|
|
| transport_channel_ = new_tc;
|
|
|
| if (new_tc) {
|
| ConnectToTransportChannel(new_tc);
|
| + for (const auto& pair : socket_options_) {
|
| + new_tc->SetOption(pair.first, pair.second);
|
| + }
|
| }
|
| +
|
| + // Update aggregate writable/ready-to-send state between RTP and RTCP upon
|
| + // setting new channel
|
| + UpdateWritableState_w();
|
| + SetReadyToSend(false, new_tc && new_tc->writable());
|
| }
|
|
|
| void BaseChannel::set_rtcp_transport_channel(TransportChannel* new_tc) {
|
| ASSERT(worker_thread_ == rtc::Thread::Current());
|
|
|
| TransportChannel* old_tc = rtcp_transport_channel_;
|
| -
|
| - if (old_tc == new_tc) {
|
| + if (!old_tc && !new_tc) {
|
| + // Nothing to do
|
| return;
|
| }
|
| + ASSERT(old_tc != new_tc);
|
| +
|
| if (old_tc) {
|
| DisconnectFromTransportChannel(old_tc);
|
| - session()->DestroyChannel(
|
| - content_name(), cricket::ICE_CANDIDATE_COMPONENT_RTCP);
|
| + transport_controller_->DestroyTransportChannel_w(
|
| + transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
|
| }
|
|
|
| rtcp_transport_channel_ = new_tc;
|
|
|
| if (new_tc) {
|
| ConnectToTransportChannel(new_tc);
|
| + for (const auto& pair : rtcp_socket_options_) {
|
| + new_tc->SetOption(pair.first, pair.second);
|
| + }
|
| }
|
| +
|
| + // Update aggregate writable/ready-to-send state between RTP and RTCP upon
|
| + // setting new channel
|
| + UpdateWritableState_w();
|
| + SetReadyToSend(true, new_tc && new_tc->writable());
|
| }
|
|
|
| void BaseChannel::ConnectToTransportChannel(TransportChannel* tc) {
|
| @@ -407,9 +446,13 @@ int BaseChannel::SetOption(SocketType type, rtc::Socket::Option opt,
|
| switch (type) {
|
| case ST_RTP:
|
| channel = transport_channel_;
|
| + socket_options_.push_back(
|
| + std::pair<rtc::Socket::Option, int>(opt, value));
|
| break;
|
| case ST_RTCP:
|
| channel = rtcp_transport_channel_;
|
| + rtcp_socket_options_.push_back(
|
| + std::pair<rtc::Socket::Option, int>(opt, value));
|
| break;
|
| }
|
| return channel ? channel->SetOption(opt, value) : -1;
|
| @@ -417,12 +460,7 @@ int BaseChannel::SetOption(SocketType type, rtc::Socket::Option opt,
|
|
|
| void BaseChannel::OnWritableState(TransportChannel* channel) {
|
| ASSERT(channel == transport_channel_ || channel == rtcp_transport_channel_);
|
| - if (transport_channel_->writable()
|
| - && (!rtcp_transport_channel_ || rtcp_transport_channel_->writable())) {
|
| - ChannelWritable_w();
|
| - } else {
|
| - ChannelNotWritable_w();
|
| - }
|
| + UpdateWritableState_w();
|
| }
|
|
|
| void BaseChannel::OnChannelRead(TransportChannel* channel,
|
| @@ -440,26 +478,25 @@ void BaseChannel::OnChannelRead(TransportChannel* channel,
|
| }
|
|
|
| void BaseChannel::OnReadyToSend(TransportChannel* channel) {
|
| - SetReadyToSend(channel, true);
|
| + ASSERT(channel == transport_channel_ || channel == rtcp_transport_channel_);
|
| + SetReadyToSend(channel == rtcp_transport_channel_, true);
|
| }
|
|
|
| -void BaseChannel::SetReadyToSend(TransportChannel* channel, bool ready) {
|
| - ASSERT(channel == transport_channel_ || channel == rtcp_transport_channel_);
|
| - if (channel == transport_channel_) {
|
| - rtp_ready_to_send_ = ready;
|
| - }
|
| - if (channel == rtcp_transport_channel_) {
|
| +void BaseChannel::SetReadyToSend(bool rtcp, bool ready) {
|
| + if (rtcp) {
|
| rtcp_ready_to_send_ = ready;
|
| + } else {
|
| + rtp_ready_to_send_ = ready;
|
| }
|
|
|
| - if (!ready) {
|
| - // Notify the MediaChannel when either rtp or rtcp channel can't send.
|
| - media_channel_->OnReadyToSend(false);
|
| - } else if (rtp_ready_to_send_ &&
|
| - // In the case of rtcp mux |rtcp_transport_channel_| will be null.
|
| - (rtcp_ready_to_send_ || !rtcp_transport_channel_)) {
|
| + if (rtp_ready_to_send_ &&
|
| + // In the case of rtcp mux |rtcp_transport_channel_| will be null.
|
| + (rtcp_ready_to_send_ || !rtcp_transport_channel_)) {
|
| // Notify the MediaChannel when both rtp and rtcp channel can send.
|
| media_channel_->OnReadyToSend(true);
|
| + } else {
|
| + // Notify the MediaChannel when either rtp or rtcp channel can't send.
|
| + media_channel_->OnReadyToSend(false);
|
| }
|
| }
|
|
|
| @@ -581,7 +618,7 @@ bool BaseChannel::SendPacket(bool rtcp, rtc::Buffer* packet,
|
| if (ret != static_cast<int>(packet->size())) {
|
| if (channel->GetError() == EWOULDBLOCK) {
|
| LOG(LS_WARNING) << "Got EWOULDBLOCK from socket.";
|
| - SetReadyToSend(channel, false);
|
| + SetReadyToSend(rtcp, false);
|
| }
|
| return false;
|
| }
|
| @@ -715,14 +752,21 @@ void BaseChannel::DisableMedia_w() {
|
| ChangeState();
|
| }
|
|
|
| +void BaseChannel::UpdateWritableState_w() {
|
| + if (transport_channel_ && transport_channel_->writable() &&
|
| + (!rtcp_transport_channel_ || rtcp_transport_channel_->writable())) {
|
| + ChannelWritable_w();
|
| + } else {
|
| + ChannelNotWritable_w();
|
| + }
|
| +}
|
| +
|
| void BaseChannel::ChannelWritable_w() {
|
| ASSERT(worker_thread_ == rtc::Thread::Current());
|
| if (writable_)
|
| return;
|
|
|
| - LOG(LS_INFO) << "Channel socket writable ("
|
| - << transport_channel_->content_name() << ", "
|
| - << transport_channel_->component() << ")"
|
| + LOG(LS_INFO) << "Channel writable (" << content_name_ << ")"
|
| << (was_ever_writable_ ? "" : " for the first time");
|
|
|
| std::vector<ConnectionInfo> infos;
|
| @@ -739,13 +783,13 @@ void BaseChannel::ChannelWritable_w() {
|
| // If we're doing DTLS-SRTP, now is the time.
|
| if (!was_ever_writable_ && ShouldSetupDtlsSrtp()) {
|
| if (!SetupDtlsSrtp(false)) {
|
| - SignalDtlsSetupFailure(this, false);
|
| + SignalDtlsSetupFailure_w(false);
|
| return;
|
| }
|
|
|
| if (rtcp_transport_channel_) {
|
| if (!SetupDtlsSrtp(true)) {
|
| - SignalDtlsSetupFailure(this, true);
|
| + SignalDtlsSetupFailure_w(true);
|
| return;
|
| }
|
| }
|
| @@ -788,8 +832,8 @@ bool BaseChannel::ShouldSetupDtlsSrtp() const {
|
| bool BaseChannel::SetupDtlsSrtp(bool rtcp_channel) {
|
| bool ret = false;
|
|
|
| - TransportChannel *channel = rtcp_channel ?
|
| - rtcp_transport_channel_ : transport_channel_;
|
| + TransportChannel* channel =
|
| + rtcp_channel ? rtcp_transport_channel_ : transport_channel_;
|
|
|
| // No DTLS
|
| if (!channel->IsDtlsActive())
|
| @@ -884,9 +928,7 @@ void BaseChannel::ChannelNotWritable_w() {
|
| if (!writable_)
|
| return;
|
|
|
| - LOG(LS_INFO) << "Channel socket not writable ("
|
| - << transport_channel_->content_name() << ", "
|
| - << transport_channel_->component() << ")";
|
| + LOG(LS_INFO) << "Channel not writable (" << content_name_ << ")";
|
| writable_ = false;
|
| ChangeState();
|
| }
|
| @@ -985,7 +1027,8 @@ void BaseChannel::ActivateRtcpMux() {
|
| void BaseChannel::ActivateRtcpMux_w() {
|
| if (!rtcp_mux_filter_.IsActive()) {
|
| rtcp_mux_filter_.SetActive();
|
| - set_rtcp_transport_channel(NULL);
|
| + set_rtcp_transport_channel(nullptr);
|
| + rtcp_transport_enabled_ = false;
|
| }
|
| }
|
|
|
| @@ -1004,7 +1047,11 @@ bool BaseChannel::SetRtcpMux_w(bool enable, ContentAction action,
|
| ret = rtcp_mux_filter_.SetAnswer(enable, src);
|
| if (ret && rtcp_mux_filter_.IsActive()) {
|
| // We activated RTCP mux, close down the RTCP transport.
|
| - set_rtcp_transport_channel(NULL);
|
| + LOG(LS_INFO) << "Enabling rtcp-mux for " << content_name()
|
| + << " by destroying RTCP transport channel for "
|
| + << transport_name();
|
| + set_rtcp_transport_channel(nullptr);
|
| + rtcp_transport_enabled_ = false;
|
| }
|
| break;
|
| case CA_UPDATE:
|
| @@ -1231,14 +1278,16 @@ void BaseChannel::FlushRtcpMessages() {
|
| VoiceChannel::VoiceChannel(rtc::Thread* thread,
|
| MediaEngineInterface* media_engine,
|
| VoiceMediaChannel* media_channel,
|
| - BaseSession* session,
|
| + TransportController* transport_controller,
|
| const std::string& content_name,
|
| bool rtcp)
|
| - : BaseChannel(thread, media_channel, session, content_name,
|
| + : BaseChannel(thread,
|
| + media_channel,
|
| + transport_controller,
|
| + content_name,
|
| rtcp),
|
| media_engine_(media_engine),
|
| - received_media_(false) {
|
| -}
|
| + received_media_(false) {}
|
|
|
| VoiceChannel::~VoiceChannel() {
|
| StopAudioMonitor();
|
| @@ -1264,11 +1313,12 @@ bool VoiceChannel::SetRemoteRenderer(uint32 ssrc, AudioRenderer* renderer) {
|
| media_channel(), ssrc, renderer));
|
| }
|
|
|
| -bool VoiceChannel::SetAudioSend(uint32 ssrc, bool mute,
|
| +bool VoiceChannel::SetAudioSend(uint32 ssrc,
|
| + bool mute,
|
| const AudioOptions* options,
|
| AudioRenderer* renderer) {
|
| - return InvokeOnWorker(Bind(&VoiceMediaChannel::SetAudioSend,
|
| - media_channel(), ssrc, mute, options, renderer));
|
| + return InvokeOnWorker(Bind(&VoiceMediaChannel::SetAudioSend, media_channel(),
|
| + ssrc, mute, options, renderer));
|
| }
|
|
|
| bool VoiceChannel::SetRingbackTone(const void* buf, int len) {
|
| @@ -1607,14 +1657,16 @@ void VoiceChannel::GetSrtpCiphers(std::vector<std::string>* ciphers) const {
|
|
|
| VideoChannel::VideoChannel(rtc::Thread* thread,
|
| VideoMediaChannel* media_channel,
|
| - BaseSession* session,
|
| + TransportController* transport_controller,
|
| const std::string& content_name,
|
| bool rtcp)
|
| - : BaseChannel(thread, media_channel, session, content_name,
|
| + : BaseChannel(thread,
|
| + media_channel,
|
| + transport_controller,
|
| + content_name,
|
| rtcp),
|
| renderer_(NULL),
|
| - previous_we_(rtc::WE_CLOSE) {
|
| -}
|
| + previous_we_(rtc::WE_CLOSE) {}
|
|
|
| bool VideoChannel::Init() {
|
| if (!BaseChannel::Init()) {
|
| @@ -1707,10 +1759,11 @@ bool VideoChannel::RequestIntraFrame() {
|
| return true;
|
| }
|
|
|
| -bool VideoChannel::SetVideoSend(uint32 ssrc, bool mute,
|
| +bool VideoChannel::SetVideoSend(uint32 ssrc,
|
| + bool mute,
|
| const VideoOptions* options) {
|
| - return InvokeOnWorker(Bind(&VideoMediaChannel::SetVideoSend,
|
| - media_channel(), ssrc, mute, options));
|
| + return InvokeOnWorker(Bind(&VideoMediaChannel::SetVideoSend, media_channel(),
|
| + ssrc, mute, options));
|
| }
|
|
|
| void VideoChannel::ChangeState() {
|
| @@ -2045,13 +2098,16 @@ void VideoChannel::GetSrtpCiphers(std::vector<std::string>* ciphers) const {
|
|
|
| DataChannel::DataChannel(rtc::Thread* thread,
|
| DataMediaChannel* media_channel,
|
| - BaseSession* session,
|
| + TransportController* transport_controller,
|
| const std::string& content_name,
|
| bool rtcp)
|
| - : BaseChannel(thread, media_channel, session, content_name, rtcp),
|
| + : BaseChannel(thread,
|
| + media_channel,
|
| + transport_controller,
|
| + content_name,
|
| + rtcp),
|
| data_channel_type_(cricket::DCT_NONE),
|
| - ready_to_send_data_(false) {
|
| -}
|
| + ready_to_send_data_(false) {}
|
|
|
| DataChannel::~DataChannel() {
|
| StopMediaMonitor();
|
|
|