Chromium Code Reviews| Index: webrtc/pc/channel.cc | 
| diff --git a/webrtc/pc/channel.cc b/webrtc/pc/channel.cc | 
| index 59f0869431ae59aef1e26b3dbc555b0c897e7e14..cc0c25637926b7369ea9fb1f94189bc9ccb2717d 100644 | 
| --- a/webrtc/pc/channel.cc | 
| +++ b/webrtc/pc/channel.cc | 
| @@ -118,6 +118,10 @@ static const MediaContentDescription* GetContentDescription( | 
| return static_cast<const MediaContentDescription*>(cinfo->description); | 
| } | 
| +static bool IsInsecureRtp(const std::string& protocol) { | 
| + return protocol == "RTP/AVPF" || protocol == "RTP/AVP"; | 
| 
 
Taylor Brandstetter
2017/08/26 02:40:38
Looking elsewhere, it looks like we typically use
 
Zhi Huang
2017/08/29 18:40:34
Removed.
 
 | 
| +} | 
| + | 
| template <class Codec> | 
| void RtpParametersFromMediaDescription( | 
| const MediaContentDescriptionImpl<Codec>* desc, | 
| @@ -158,17 +162,20 @@ BaseChannel::BaseChannel(rtc::Thread* worker_thread, | 
| signaling_thread_(signaling_thread), | 
| content_name_(content_name), | 
| rtcp_mux_required_(rtcp_mux_required), | 
| - rtp_transport_( | 
| - srtp_required | 
| - ? rtc::WrapUnique<webrtc::RtpTransportInternal>( | 
| - new webrtc::SrtpTransport(rtcp_mux_required, content_name)) | 
| - : rtc::MakeUnique<webrtc::RtpTransport>(rtcp_mux_required)), | 
| srtp_required_(srtp_required), | 
| media_channel_(media_channel), | 
| selected_candidate_pair_(nullptr) { | 
| RTC_DCHECK(worker_thread_ == rtc::Thread::Current()); | 
| + // Always create an SrtpTransport for |rtp_transport_|. If insecure protocol | 
| + // is used, |srtp_transport_| will be set to nullptr and |rtp_transport_| will | 
| + // act as a plain RtpTransport. | 
| + // TODO(zhihuang): Move the transport creation to the TransportController. | 
| + auto transport = | 
| + rtc::MakeUnique<webrtc::SrtpTransport>(rtcp_mux_required, content_name); | 
| + srtp_transport_ = transport.get(); | 
| + rtp_transport_ = std::move(transport); | 
| #if defined(ENABLE_EXTERNAL_AUTH) | 
| - srtp_filter_.EnableExternalAuth(); | 
| + srtp_transport_->EnableExternalAuth(); | 
| #endif | 
| rtp_transport_->SignalReadyToSend.connect( | 
| this, &BaseChannel::OnTransportReadyToSend); | 
| @@ -321,7 +328,10 @@ void BaseChannel::SetTransports_n( | 
| // Set |writable_| to false such that UpdateWritableState_w can set up | 
| // DTLS-SRTP when |writable_| becomes true again. | 
| writable_ = false; | 
| - srtp_filter_.ResetParams(); | 
| + dtls_active_ = false; | 
| + if (srtp_transport_) { | 
| + srtp_transport_->ResetParams(); | 
| + } | 
| } | 
| // If this BaseChannel doesn't require RTCP mux and we haven't fully | 
| @@ -377,8 +387,8 @@ void BaseChannel::SetTransport_n( | 
| } | 
| if (rtcp && new_dtls_transport) { | 
| - RTC_CHECK(!(ShouldSetupDtlsSrtp_n() && srtp_filter_.IsActive())) | 
| - << "Setting RTCP for DTLS/SRTP after SrtpFilter is active " | 
| + RTC_CHECK(!(ShouldSetupDtlsSrtp_n() && secure())) | 
| + << "Setting RTCP for DTLS/SRTP after the channel is secure " | 
| << "should never happen."; | 
| } | 
| @@ -529,8 +539,7 @@ bool BaseChannel::IsReadyToSendMedia_n() const { | 
| // and we have had some form of connectivity. | 
| return enabled() && IsReceiveContentDirection(remote_content_direction_) && | 
| IsSendContentDirection(local_content_direction_) && | 
| - was_ever_writable() && | 
| - (srtp_filter_.IsActive() || !ShouldSetupDtlsSrtp_n()); | 
| + was_ever_writable() && (secure() || !ShouldSetupDtlsSrtp_n()); | 
| } | 
| bool BaseChannel::SendPacket(rtc::CopyOnWriteBuffer* packet, | 
| @@ -588,7 +597,10 @@ void BaseChannel::OnDtlsState(DtlsTransportInternal* transport, | 
| // TransportChannel) or when TransportChannel is attached after DTLS is | 
| // negotiated. | 
| if (state != DTLS_TRANSPORT_CONNECTED) { | 
| - srtp_filter_.ResetParams(); | 
| + dtls_active_ = false; | 
| + if (srtp_transport_) { | 
| + srtp_transport_->ResetParams(); | 
| + } | 
| } | 
| } | 
| @@ -662,74 +674,7 @@ bool BaseChannel::SendPacket(bool rtcp, | 
| return false; | 
| } | 
| - rtc::PacketOptions updated_options; | 
| - updated_options = options; | 
| - // Protect if needed. | 
| - if (srtp_filter_.IsActive()) { | 
| - TRACE_EVENT0("webrtc", "SRTP Encode"); | 
| - bool res; | 
| - uint8_t* data = packet->data(); | 
| - int len = static_cast<int>(packet->size()); | 
| - if (!rtcp) { | 
| - // If ENABLE_EXTERNAL_AUTH flag is on then packet authentication is not done | 
| - // inside libsrtp for a RTP packet. A external HMAC module will be writing | 
| - // a fake HMAC value. This is ONLY done for a RTP packet. | 
| - // Socket layer will update rtp sendtime extension header if present in | 
| - // packet with current time before updating the HMAC. | 
| -#if !defined(ENABLE_EXTERNAL_AUTH) | 
| - res = srtp_filter_.ProtectRtp( | 
| - data, len, static_cast<int>(packet->capacity()), &len); | 
| -#else | 
| - if (!srtp_filter_.IsExternalAuthActive()) { | 
| - res = srtp_filter_.ProtectRtp( | 
| - data, len, static_cast<int>(packet->capacity()), &len); | 
| - } else { | 
| - updated_options.packet_time_params.rtp_sendtime_extension_id = | 
| - rtp_abs_sendtime_extn_id_; | 
| - res = srtp_filter_.ProtectRtp( | 
| - data, len, static_cast<int>(packet->capacity()), &len, | 
| - &updated_options.packet_time_params.srtp_packet_index); | 
| - // If protection succeeds, let's get auth params from srtp. | 
| - if (res) { | 
| - uint8_t* auth_key = NULL; | 
| - int key_len; | 
| - res = srtp_filter_.GetRtpAuthParams( | 
| - &auth_key, &key_len, | 
| - &updated_options.packet_time_params.srtp_auth_tag_len); | 
| - if (res) { | 
| - updated_options.packet_time_params.srtp_auth_key.resize(key_len); | 
| - updated_options.packet_time_params.srtp_auth_key.assign( | 
| - auth_key, auth_key + key_len); | 
| - } | 
| - } | 
| - } | 
| -#endif | 
| - if (!res) { | 
| - int seq_num = -1; | 
| - uint32_t ssrc = 0; | 
| - GetRtpSeqNum(data, len, &seq_num); | 
| - GetRtpSsrc(data, len, &ssrc); | 
| - LOG(LS_ERROR) << "Failed to protect " << content_name_ | 
| - << " RTP packet: size=" << len | 
| - << ", seqnum=" << seq_num << ", SSRC=" << ssrc; | 
| - return false; | 
| - } | 
| - } else { | 
| - res = srtp_filter_.ProtectRtcp(data, len, | 
| - static_cast<int>(packet->capacity()), | 
| - &len); | 
| - if (!res) { | 
| - int type = -1; | 
| - GetRtcpType(data, len, &type); | 
| - LOG(LS_ERROR) << "Failed to protect " << content_name_ | 
| - << " RTCP packet: size=" << len << ", type=" << type; | 
| - return false; | 
| - } | 
| - } | 
| - | 
| - // Update the length of the packet now that we've added the auth tag. | 
| - packet->SetSize(len); | 
| - } else if (srtp_required_) { | 
| + if (!secure() && srtp_required_) { | 
| // The audio/video engines may attempt to send RTCP packets as soon as the | 
| // streams are created, so don't treat this as an error for RTCP. | 
| // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=6809 | 
| @@ -744,9 +689,16 @@ bool BaseChannel::SendPacket(bool rtcp, | 
| return false; | 
| } | 
| + if (secure()) { | 
| 
 
pthatcher
2017/08/28 21:42:56
I think making the shorter path the early return w
 
Zhi Huang
2017/08/29 18:40:34
Done.
 
 | 
| + RTC_DCHECK(srtp_transport_); | 
| + RTC_DCHECK(srtp_transport_->IsActive()); | 
| + // Bon voyage. | 
| + int flags = secure_dtls() ? PF_SRTP_BYPASS : PF_NORMAL; | 
| + return srtp_transport_->SendPacket(rtcp, packet, options, flags); | 
| 
 
pthatcher
2017/08/28 21:42:56
I don't think it should be the responsibility of t
 
Zhi Huang
2017/08/29 18:40:34
SrtpTransport doesn't interact with DtlsTransport
 
 | 
| + } | 
| + | 
| // Bon voyage. | 
| - int flags = (secure() && secure_dtls()) ? PF_SRTP_BYPASS : PF_NORMAL; | 
| - return rtp_transport_->SendPacket(rtcp, packet, updated_options, flags); | 
| + return rtp_transport_->SendPacket(rtcp, packet, options, PF_NORMAL); | 
| 
 
pthatcher
2017/08/28 21:42:56
And similarly here, it would make sense to call Se
 
Zhi Huang
2017/08/29 18:40:34
Done.
 
 | 
| } | 
| bool BaseChannel::HandlesPayloadType(int packet_type) const { | 
| @@ -761,37 +713,7 @@ void BaseChannel::OnPacketReceived(bool rtcp, | 
| signaling_thread()->Post(RTC_FROM_HERE, this, MSG_FIRSTPACKETRECEIVED); | 
| } | 
| - // Unprotect the packet, if needed. | 
| - if (srtp_filter_.IsActive()) { | 
| - TRACE_EVENT0("webrtc", "SRTP Decode"); | 
| - char* data = packet->data<char>(); | 
| - int len = static_cast<int>(packet->size()); | 
| - bool res; | 
| - if (!rtcp) { | 
| - res = srtp_filter_.UnprotectRtp(data, len, &len); | 
| - if (!res) { | 
| - int seq_num = -1; | 
| - uint32_t ssrc = 0; | 
| - GetRtpSeqNum(data, len, &seq_num); | 
| - GetRtpSsrc(data, len, &ssrc); | 
| - LOG(LS_ERROR) << "Failed to unprotect " << content_name_ | 
| - << " RTP packet: size=" << len << ", seqnum=" << seq_num | 
| - << ", SSRC=" << ssrc; | 
| - return; | 
| - } | 
| - } else { | 
| - res = srtp_filter_.UnprotectRtcp(data, len, &len); | 
| - if (!res) { | 
| - int type = -1; | 
| - GetRtcpType(data, len, &type); | 
| - LOG(LS_ERROR) << "Failed to unprotect " << content_name_ | 
| - << " RTCP packet: size=" << len << ", type=" << type; | 
| - return; | 
| - } | 
| - } | 
| - | 
| - packet->SetSize(len); | 
| - } else if (srtp_required_) { | 
| + if (!secure() && srtp_required_) { | 
| // Our session description indicates that SRTP is required, but we got a | 
| // packet before our SRTP filter is active. This means either that | 
| // a) we got SRTP packets before we received the SDES keys, in which case | 
| @@ -834,6 +756,10 @@ bool BaseChannel::PushdownLocalDescription( | 
| const ContentInfo* content_info = GetFirstContent(local_desc); | 
| const MediaContentDescription* content_desc = | 
| GetContentDescription(content_info); | 
| + if (IsInsecureRtp(content_desc->protocol())) { | 
| + RTC_DCHECK(!srtp_required_); | 
| 
 
Taylor Brandstetter
2017/08/26 02:40:38
This should be an error rather than a DCHECK since
 
Zhi Huang
2017/08/29 18:40:34
I'll remove these for now.
 
 | 
| + srtp_transport_ = nullptr; | 
| 
 
Taylor Brandstetter
2017/08/26 02:40:39
This unsets the srtp_transport_ pointer, but rtp_t
 
Zhi Huang
2017/08/29 18:40:33
Done.
 
 | 
| + } | 
| if (content_desc && content_info && !content_info->rejected && | 
| !SetLocalContent(content_desc, action, error_desc)) { | 
| LOG(LS_ERROR) << "Failure in SetLocalContent with action " << action; | 
| @@ -848,6 +774,10 @@ bool BaseChannel::PushdownRemoteDescription( | 
| const ContentInfo* content_info = GetFirstContent(remote_desc); | 
| const MediaContentDescription* content_desc = | 
| GetContentDescription(content_info); | 
| + if (IsInsecureRtp(content_desc->protocol())) { | 
| + RTC_DCHECK(!srtp_required_); | 
| + srtp_transport_ = nullptr; | 
| + } | 
| if (content_desc && content_info && !content_info->rejected && | 
| !SetRemoteContent(content_desc, action, error_desc)) { | 
| LOG(LS_ERROR) << "Failure in SetRemoteContent with action " << action; | 
| @@ -995,17 +925,20 @@ bool BaseChannel::SetupDtlsSrtp_n(bool rtcp) { | 
| recv_key = &server_write_key; | 
| } | 
| - if (!srtp_filter_.IsActive()) { | 
| + if (!secure_dtls()) { | 
| if (rtcp) { | 
| - ret = srtp_filter_.SetRtcpParams(selected_crypto_suite, &(*send_key)[0], | 
| - static_cast<int>(send_key->size()), | 
| - selected_crypto_suite, &(*recv_key)[0], | 
| - static_cast<int>(recv_key->size())); | 
| + RTC_DCHECK(srtp_transport_); | 
| + ret = srtp_transport_->SetRtcpParams( | 
| + selected_crypto_suite, &(*send_key)[0], | 
| + static_cast<int>(send_key->size()), selected_crypto_suite, | 
| + &(*recv_key)[0], static_cast<int>(recv_key->size())); | 
| } else { | 
| - ret = srtp_filter_.SetRtpParams(selected_crypto_suite, &(*send_key)[0], | 
| - static_cast<int>(send_key->size()), | 
| - selected_crypto_suite, &(*recv_key)[0], | 
| - static_cast<int>(recv_key->size())); | 
| + RTC_DCHECK(srtp_transport_); | 
| + ret = srtp_transport_->SetRtpParams( | 
| + selected_crypto_suite, &(*send_key)[0], | 
| + static_cast<int>(send_key->size()), selected_crypto_suite, | 
| + &(*recv_key)[0], static_cast<int>(recv_key->size())); | 
| + dtls_active_ = ret; | 
| } | 
| } else { | 
| if (rtcp) { | 
| @@ -1013,10 +946,10 @@ bool BaseChannel::SetupDtlsSrtp_n(bool rtcp) { | 
| // to update the set of encrypted RTP header extension IDs. | 
| ret = true; | 
| } else { | 
| - ret = srtp_filter_.UpdateRtpParams( | 
| - selected_crypto_suite, | 
| - &(*send_key)[0], static_cast<int>(send_key->size()), | 
| - selected_crypto_suite, | 
| + RTC_DCHECK(srtp_transport_); | 
| + ret = srtp_transport_->UpdateRtpParams( | 
| + selected_crypto_suite, &(*send_key)[0], | 
| + static_cast<int>(send_key->size()), selected_crypto_suite, | 
| &(*recv_key)[0], static_cast<int>(recv_key->size())); | 
| } | 
| } | 
| 
 
pthatcher
2017/08/28 21:42:56
If this is only used for changing the header exten
 
Zhi Huang
2017/08/29 18:40:34
SetEncryptedHeaderExtensionIds just stores the upd
 
 | 
| @@ -1024,14 +957,13 @@ bool BaseChannel::SetupDtlsSrtp_n(bool rtcp) { | 
| if (!ret) { | 
| LOG(LS_WARNING) << "DTLS-SRTP key installation failed"; | 
| } else { | 
| - dtls_keyed_ = true; | 
| UpdateTransportOverhead(); | 
| } | 
| return ret; | 
| } | 
| void BaseChannel::MaybeSetupDtlsSrtp_n() { | 
| - if (srtp_filter_.IsActive()) { | 
| + if (secure_dtls()) { | 
| return; | 
| } | 
| @@ -1138,7 +1070,13 @@ bool BaseChannel::SetSrtp_n(const std::vector<CryptoParams>& cryptos, | 
| if (!ret) { | 
| return false; | 
| } | 
| - srtp_filter_.SetEncryptedHeaderExtensionIds(src, encrypted_extension_ids); | 
| + | 
| + if (!srtp_transport_) { | 
| + LOG(LS_WARNING) << "Setting SRTP without an SrtpTransport."; | 
| 
 
Taylor Brandstetter
2017/08/26 02:40:38
It looks like this warning message would be logged
 
Zhi Huang
2017/08/29 18:40:34
Acknowledged.
 
 | 
| + return true; | 
| + } | 
| + | 
| + srtp_transport_->SetEncryptedHeaderExtensionIds(src, encrypted_extension_ids); | 
| switch (action) { | 
| case CA_OFFER: | 
| // If DTLS is already active on the channel, we could be renegotiating | 
| @@ -1164,10 +1102,33 @@ bool BaseChannel::SetSrtp_n(const std::vector<CryptoParams>& cryptos, | 
| default: | 
| break; | 
| } | 
| + | 
| + // If setting an SDES answer succeeded, apply the negotiated parameters | 
| + // to the SRTP transport. | 
| + if ((action == CA_PRANSWER || action == CA_ANSWER) && !dtls && ret) { | 
| + if (srtp_filter_.send_cipher_suite() && srtp_filter_.recv_cipher_suite()) { | 
| + auto send_key = srtp_filter_.send_key(); | 
| + auto recv_key = srtp_filter_.recv_key(); | 
| + ret = srtp_transport_->SetRtpParams( | 
| + *(srtp_filter_.send_cipher_suite()), &(*send_key)[0], | 
| + static_cast<int>(send_key->size()), | 
| + *(srtp_filter_.recv_cipher_suite()), &(*recv_key)[0], | 
| + static_cast<int>(recv_key->size())); | 
| + } else { | 
| + LOG(LS_INFO) << "No crypto keys are provided for SDES."; | 
| 
 
Taylor Brandstetter
2017/08/26 02:40:38
Is it even possible to hit this point? Won't "srtp
 
Zhi Huang
2017/08/29 18:40:34
If we still support upgrading rtp_transport to srt
 
 | 
| + if (action == CA_ANSWER) { | 
| + // Explicitly reset the |srtp_transport_| if no crypto param is | 
| + // provided in the answer. No need to call |ResetParams()| for | 
| + // |srtp_filter_| because it resets the params inside |SetAnswer|. | 
| + srtp_transport_->ResetParams(); | 
| + } | 
| + } | 
| + } | 
| + | 
| // Only update SRTP filter if using DTLS. SDES is handled internally | 
| // by the SRTP filter. | 
| // TODO(jbauch): Only update if encrypted extension ids have changed. | 
| - if (ret && dtls_keyed_ && rtp_dtls_transport_ && | 
| + if (ret && secure_dtls() && rtp_dtls_transport_ && | 
| rtp_dtls_transport_->dtls_state() == DTLS_TRANSPORT_CONNECTED) { | 
| bool rtcp = false; | 
| ret = SetupDtlsSrtp_n(rtcp); | 
| @@ -1211,7 +1172,6 @@ bool BaseChannel::SetRtcpMux_n(bool enable, | 
| transport_name_.empty() | 
| ? rtp_transport_->rtp_packet_transport()->debug_name() | 
| : transport_name_; | 
| - ; | 
| LOG(LS_INFO) << "Enabling rtcp-mux for " << content_name() | 
| << "; no longer need RTCP transport for " << debug_name; | 
| if (rtp_transport_->rtcp_packet_transport()) { | 
| @@ -1440,7 +1400,8 @@ void BaseChannel::MaybeCacheRtpAbsSendTimeHeaderExtension_w( | 
| void BaseChannel::CacheRtpAbsSendTimeHeaderExtension_n( | 
| int rtp_abs_sendtime_extn_id) { | 
| - rtp_abs_sendtime_extn_id_ = rtp_abs_sendtime_extn_id; | 
| + RTC_DCHECK(srtp_transport_); | 
| + srtp_transport_->CacheRtpAbsSendTimeHeaderExtension(rtp_abs_sendtime_extn_id); | 
| } | 
| void BaseChannel::OnMessage(rtc::Message *pmsg) { | 
| @@ -1724,9 +1685,9 @@ int BaseChannel::GetTransportOverheadPerPacket() const { | 
| ? kTcpOverhaed | 
| : kUdpOverhaed; | 
| - if (secure()) { | 
| + if (secure_sdes()) { | 
| int srtp_overhead = 0; | 
| - if (srtp_filter_.GetSrtpOverhead(&srtp_overhead)) | 
| + if (srtp_transport_->GetSrtpOverhead(&srtp_overhead)) | 
| transport_overhead_per_packet += srtp_overhead; | 
| } |