diff options
Diffstat (limited to 'talk/session')
-rwxr-xr-x | talk/session/media/bundlefilter.cc | 65 | ||||
-rwxr-xr-x | talk/session/media/bundlefilter.h | 25 | ||||
-rwxr-xr-x | talk/session/media/bundlefilter_unittest.cc | 148 | ||||
-rw-r--r-- | talk/session/media/channel.cc | 302 | ||||
-rw-r--r-- | talk/session/media/channel.h | 43 | ||||
-rw-r--r-- | talk/session/media/channel_unittest.cc | 78 | ||||
-rw-r--r-- | talk/session/media/channelmanager.cc | 93 | ||||
-rw-r--r-- | talk/session/media/channelmanager.h | 14 | ||||
-rw-r--r-- | talk/session/media/channelmanager_unittest.cc | 59 | ||||
-rw-r--r-- | talk/session/media/mediasession.cc | 161 | ||||
-rw-r--r-- | talk/session/media/mediasession.h | 61 | ||||
-rw-r--r-- | talk/session/media/mediasession_unittest.cc | 37 | ||||
-rw-r--r-- | talk/session/media/srtpfilter.cc | 37 | ||||
-rw-r--r-- | talk/session/media/srtpfilter.h | 17 | ||||
-rw-r--r-- | talk/session/media/srtpfilter_unittest.cc | 102 |
15 files changed, 509 insertions, 733 deletions
diff --git a/talk/session/media/bundlefilter.cc b/talk/session/media/bundlefilter.cc index b47d47fb27..670befeb7d 100755 --- a/talk/session/media/bundlefilter.cc +++ b/talk/session/media/bundlefilter.cc @@ -32,78 +32,29 @@ namespace cricket { -static const uint32_t kSsrc01 = 0x01; - BundleFilter::BundleFilter() { } BundleFilter::~BundleFilter() { } -bool BundleFilter::DemuxPacket(const char* data, size_t len, bool rtcp) { - // For rtp packets, we check whether the payload type can be found. - // For rtcp packets, we check whether the ssrc can be found or is the special - // value 1 except for SDES packets which always pass through. Plus, if - // |streams_| is empty, we will allow all rtcp packets pass through provided - // that they are valid rtcp packets in case that they are for early media. - if (!rtcp) { - // It may not be a RTP packet (e.g. SCTP). - if (!IsRtpPacket(data, len)) - return false; - - int payload_type = 0; - if (!GetRtpPayloadType(data, len, &payload_type)) { - return false; - } - return FindPayloadType(payload_type); +bool BundleFilter::DemuxPacket(const uint8_t* data, size_t len) { + // For RTP packets, we check whether the payload type can be found. + if (!IsRtpPacket(data, len)) { + return false; } - // Rtcp packets using ssrc filter. - int pl_type = 0; - uint32_t ssrc = 0; - if (!GetRtcpType(data, len, &pl_type)) return false; - if (pl_type == kRtcpTypeSDES) { - // SDES packet parsing not supported. - LOG(LS_INFO) << "SDES packet received for demux."; - return true; - } else { - if (!GetRtcpSsrc(data, len, &ssrc)) return false; - if (ssrc == kSsrc01) { - // SSRC 1 has a special meaning and indicates generic feedback on - // some systems and should never be dropped. If it is forwarded - // incorrectly it will be ignored by lower layers anyway. - return true; - } + int payload_type = 0; + if (!GetRtpPayloadType(data, len, &payload_type)) { + return false; } - // Pass through if |streams_| is empty to allow early rtcp packets in. - return !HasStreams() || FindStream(ssrc); + return FindPayloadType(payload_type); } void BundleFilter::AddPayloadType(int payload_type) { payload_types_.insert(payload_type); } -bool BundleFilter::AddStream(const StreamParams& stream) { - if (GetStreamBySsrc(streams_, stream.first_ssrc())) { - LOG(LS_WARNING) << "Stream already added to filter"; - return false; - } - streams_.push_back(stream); - return true; -} - -bool BundleFilter::RemoveStream(uint32_t ssrc) { - return RemoveStreamBySsrc(&streams_, ssrc); -} - -bool BundleFilter::HasStreams() const { - return !streams_.empty(); -} - -bool BundleFilter::FindStream(uint32_t ssrc) const { - return ssrc == 0 ? false : GetStreamBySsrc(streams_, ssrc) != nullptr; -} - bool BundleFilter::FindPayloadType(int pl_type) const { return payload_types_.find(pl_type) != payload_types_.end(); } diff --git a/talk/session/media/bundlefilter.h b/talk/session/media/bundlefilter.h index 3717376668..d9d952f4ee 100755 --- a/talk/session/media/bundlefilter.h +++ b/talk/session/media/bundlefilter.h @@ -28,6 +28,8 @@ #ifndef TALK_SESSION_MEDIA_BUNDLEFILTER_H_ #define TALK_SESSION_MEDIA_BUNDLEFILTER_H_ +#include <stdint.h> + #include <set> #include <vector> @@ -37,42 +39,31 @@ namespace cricket { // In case of single RTP session and single transport channel, all session -// ( or media) channels share a common transport channel. Hence they all get +// (or media) channels share a common transport channel. Hence they all get // SignalReadPacket when packet received on transport channel. This requires // cricket::BaseChannel to know all the valid sources, else media channel // will decode invalid packets. // // This class determines whether a packet is destined for cricket::BaseChannel. -// For rtp packets, this is decided based on the payload type. For rtcp packets, -// this is decided based on the sender ssrc values. +// This is only to be used for RTP packets as RTCP packets are not filtered. +// For RTP packets, this is decided based on the payload type. class BundleFilter { public: BundleFilter(); ~BundleFilter(); - // Determines packet belongs to valid cricket::BaseChannel. - bool DemuxPacket(const char* data, size_t len, bool rtcp); + // Determines if a RTP packet belongs to valid cricket::BaseChannel. + bool DemuxPacket(const uint8_t* data, size_t len); // Adds the supported payload type. void AddPayloadType(int payload_type); - // Adding a valid source to the filter. - bool AddStream(const StreamParams& stream); - - // Removes source from the filter. - bool RemoveStream(uint32_t ssrc); - - // Utility methods added for unitest. - // True if |streams_| is not empty. - bool HasStreams() const; - bool FindStream(uint32_t ssrc) const; + // Public for unittests. bool FindPayloadType(int pl_type) const; void ClearAllPayloadTypes(); - private: std::set<int> payload_types_; - std::vector<StreamParams> streams_; }; } // namespace cricket diff --git a/talk/session/media/bundlefilter_unittest.cc b/talk/session/media/bundlefilter_unittest.cc index 806d6bab09..f2c35fc1d8 100755 --- a/talk/session/media/bundlefilter_unittest.cc +++ b/talk/session/media/bundlefilter_unittest.cc @@ -30,9 +30,6 @@ using cricket::StreamParams; -static const int kSsrc1 = 0x1111; -static const int kSsrc2 = 0x2222; -static const int kSsrc3 = 0x3333; static const int kPayloadType1 = 0x11; static const int kPayloadType2 = 0x22; static const int kPayloadType3 = 0x33; @@ -55,56 +52,6 @@ static const unsigned char kRtpPacketPt3Ssrc2[] = { 0x22, }; -// PT = 200 = SR, len = 28, SSRC of sender = 0x0001 -// NTP TS = 0, RTP TS = 0, packet count = 0 -static const unsigned char kRtcpPacketSrSsrc01[] = { - 0x80, 0xC8, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, -}; - -// PT = 200 = SR, len = 28, SSRC of sender = 0x2222 -// NTP TS = 0, RTP TS = 0, packet count = 0 -static const unsigned char kRtcpPacketSrSsrc2[] = { - 0x80, 0xC8, 0x00, 0x1B, 0x00, 0x00, 0x22, 0x22, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, -}; - -// First packet - SR = PT = 200, len = 0, SSRC of sender = 0x1111 -// NTP TS = 0, RTP TS = 0, packet count = 0 -// second packet - SDES = PT = 202, count = 0, SSRC = 0x1111, cname len = 0 -static const unsigned char kRtcpPacketCompoundSrSdesSsrc1[] = { - 0x80, 0xC8, 0x00, 0x01, 0x00, 0x00, 0x11, 0x11, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x81, 0xCA, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x01, 0x00, -}; - -// SDES = PT = 202, count = 0, SSRC = 0x2222, cname len = 0 -static const unsigned char kRtcpPacketSdesSsrc2[] = { - 0x81, 0xCA, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x01, 0x00, -}; - -// Packet has only mandatory fixed RTCP header -static const unsigned char kRtcpPacketFixedHeaderOnly[] = { - 0x80, 0xC8, 0x00, 0x00, -}; - -// Small packet for SSRC demux. -static const unsigned char kRtcpPacketTooSmall[] = { - 0x80, 0xC8, 0x00, 0x00, 0x00, 0x00, -}; - -// PT = 206, FMT = 1, Sender SSRC = 0x1111, Media SSRC = 0x1111 -// No FCI information is needed for PLI. -static const unsigned char kRtcpPacketNonCompoundRtcpPliFeedback[] = { - 0x81, 0xCE, 0x00, 0x0C, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x11, 0x11, -}; - // An SCTP packet. static const unsigned char kSctpPacket[] = { 0x00, 0x01, 0x00, 0x01, @@ -114,100 +61,29 @@ static const unsigned char kSctpPacket[] = { 0x00, 0x00, 0x00, 0x00, }; -TEST(BundleFilterTest, AddRemoveStreamTest) { - cricket::BundleFilter bundle_filter; - EXPECT_FALSE(bundle_filter.HasStreams()); - EXPECT_TRUE(bundle_filter.AddStream(StreamParams::CreateLegacy(kSsrc1))); - StreamParams stream2; - stream2.ssrcs.push_back(kSsrc2); - stream2.ssrcs.push_back(kSsrc3); - EXPECT_TRUE(bundle_filter.AddStream(stream2)); - - EXPECT_TRUE(bundle_filter.HasStreams()); - EXPECT_TRUE(bundle_filter.FindStream(kSsrc1)); - EXPECT_TRUE(bundle_filter.FindStream(kSsrc2)); - EXPECT_TRUE(bundle_filter.FindStream(kSsrc3)); - EXPECT_TRUE(bundle_filter.RemoveStream(kSsrc1)); - EXPECT_FALSE(bundle_filter.FindStream(kSsrc1)); - EXPECT_TRUE(bundle_filter.RemoveStream(kSsrc3)); - EXPECT_FALSE(bundle_filter.RemoveStream(kSsrc2)); // Already removed. - EXPECT_FALSE(bundle_filter.HasStreams()); -} - TEST(BundleFilterTest, RtpPacketTest) { cricket::BundleFilter bundle_filter; bundle_filter.AddPayloadType(kPayloadType1); - EXPECT_TRUE(bundle_filter.DemuxPacket( - reinterpret_cast<const char*>(kRtpPacketPt1Ssrc1), - sizeof(kRtpPacketPt1Ssrc1), false)); + EXPECT_TRUE(bundle_filter.DemuxPacket(kRtpPacketPt1Ssrc1, + sizeof(kRtpPacketPt1Ssrc1))); bundle_filter.AddPayloadType(kPayloadType2); - EXPECT_TRUE(bundle_filter.DemuxPacket( - reinterpret_cast<const char*>(kRtpPacketPt2Ssrc2), - sizeof(kRtpPacketPt2Ssrc2), false)); + EXPECT_TRUE(bundle_filter.DemuxPacket(kRtpPacketPt2Ssrc2, + sizeof(kRtpPacketPt2Ssrc2))); // Payload type 0x33 is not added. - EXPECT_FALSE(bundle_filter.DemuxPacket( - reinterpret_cast<const char*>(kRtpPacketPt3Ssrc2), - sizeof(kRtpPacketPt3Ssrc2), false)); + EXPECT_FALSE(bundle_filter.DemuxPacket(kRtpPacketPt3Ssrc2, + sizeof(kRtpPacketPt3Ssrc2))); // Size is too small. - EXPECT_FALSE(bundle_filter.DemuxPacket( - reinterpret_cast<const char*>(kRtpPacketPt1Ssrc1), 11, false)); + EXPECT_FALSE(bundle_filter.DemuxPacket(kRtpPacketPt1Ssrc1, 11)); bundle_filter.ClearAllPayloadTypes(); - EXPECT_FALSE(bundle_filter.DemuxPacket( - reinterpret_cast<const char*>(kRtpPacketPt1Ssrc1), - sizeof(kRtpPacketPt1Ssrc1), false)); - EXPECT_FALSE(bundle_filter.DemuxPacket( - reinterpret_cast<const char*>(kRtpPacketPt2Ssrc2), - sizeof(kRtpPacketPt2Ssrc2), false)); -} - -TEST(BundleFilterTest, RtcpPacketTest) { - cricket::BundleFilter bundle_filter; - EXPECT_TRUE(bundle_filter.AddStream(StreamParams::CreateLegacy(kSsrc1))); - EXPECT_TRUE(bundle_filter.DemuxPacket( - reinterpret_cast<const char*>(kRtcpPacketCompoundSrSdesSsrc1), - sizeof(kRtcpPacketCompoundSrSdesSsrc1), true)); - EXPECT_TRUE(bundle_filter.AddStream(StreamParams::CreateLegacy(kSsrc2))); - EXPECT_TRUE(bundle_filter.DemuxPacket( - reinterpret_cast<const char*>(kRtcpPacketSrSsrc2), - sizeof(kRtcpPacketSrSsrc2), true)); - EXPECT_TRUE(bundle_filter.DemuxPacket( - reinterpret_cast<const char*>(kRtcpPacketSdesSsrc2), - sizeof(kRtcpPacketSdesSsrc2), true)); - EXPECT_TRUE(bundle_filter.RemoveStream(kSsrc2)); - // RTCP Packets other than SR and RR are demuxed regardless of SSRC. - EXPECT_TRUE(bundle_filter.DemuxPacket( - reinterpret_cast<const char*>(kRtcpPacketSdesSsrc2), - sizeof(kRtcpPacketSdesSsrc2), true)); - // RTCP Packets with 'special' SSRC 0x01 are demuxed also - EXPECT_TRUE(bundle_filter.DemuxPacket( - reinterpret_cast<const char*>(kRtcpPacketSrSsrc01), - sizeof(kRtcpPacketSrSsrc01), true)); - EXPECT_FALSE(bundle_filter.DemuxPacket( - reinterpret_cast<const char*>(kRtcpPacketSrSsrc2), - sizeof(kRtcpPacketSrSsrc2), true)); - EXPECT_FALSE(bundle_filter.DemuxPacket( - reinterpret_cast<const char*>(kRtcpPacketFixedHeaderOnly), - sizeof(kRtcpPacketFixedHeaderOnly), true)); - EXPECT_FALSE(bundle_filter.DemuxPacket( - reinterpret_cast<const char*>(kRtcpPacketTooSmall), - sizeof(kRtcpPacketTooSmall), true)); - EXPECT_TRUE(bundle_filter.DemuxPacket( - reinterpret_cast<const char*>(kRtcpPacketNonCompoundRtcpPliFeedback), - sizeof(kRtcpPacketNonCompoundRtcpPliFeedback), true)); - // If the streams_ is empty, rtcp packet passes through - EXPECT_TRUE(bundle_filter.RemoveStream(kSsrc1)); - EXPECT_FALSE(bundle_filter.HasStreams()); - EXPECT_TRUE(bundle_filter.DemuxPacket( - reinterpret_cast<const char*>(kRtcpPacketSrSsrc2), - sizeof(kRtcpPacketSrSsrc2), true)); + EXPECT_FALSE(bundle_filter.DemuxPacket(kRtpPacketPt1Ssrc1, + sizeof(kRtpPacketPt1Ssrc1))); + EXPECT_FALSE(bundle_filter.DemuxPacket(kRtpPacketPt2Ssrc2, + sizeof(kRtpPacketPt2Ssrc2))); } TEST(BundleFilterTest, InvalidRtpPacket) { cricket::BundleFilter bundle_filter; - EXPECT_TRUE(bundle_filter.AddStream(StreamParams::CreateLegacy(kSsrc1))); - EXPECT_FALSE(bundle_filter.DemuxPacket( - reinterpret_cast<const char*>(kSctpPacket), - sizeof(kSctpPacket), false)); + EXPECT_FALSE(bundle_filter.DemuxPacket(kSctpPacket, sizeof(kSctpPacket))); } diff --git a/talk/session/media/channel.cc b/talk/session/media/channel.cc index 91a6d8cb5a..a59c3f82b7 100644 --- a/talk/session/media/channel.cc +++ b/talk/session/media/channel.cc @@ -25,23 +25,36 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include <utility> + #include "talk/session/media/channel.h" #include "talk/media/base/constants.h" #include "talk/media/base/rtputils.h" -#include "webrtc/p2p/base/transportchannel.h" #include "talk/session/media/channelmanager.h" +#include "webrtc/audio/audio_sink.h" #include "webrtc/base/bind.h" #include "webrtc/base/buffer.h" #include "webrtc/base/byteorder.h" #include "webrtc/base/common.h" #include "webrtc/base/dscp.h" #include "webrtc/base/logging.h" +#include "webrtc/base/trace_event.h" +#include "webrtc/p2p/base/transportchannel.h" namespace cricket { - using rtc::Bind; +namespace { +// See comment below for why we need to use a pointer to a scoped_ptr. +bool SetRawAudioSink_w(VoiceMediaChannel* channel, + uint32_t ssrc, + rtc::scoped_ptr<webrtc::AudioSinkInterface>* sink) { + channel->SetRawAudioSink(ssrc, std::move(*sink)); + return true; +} +} // namespace + enum { MSG_EARLYMEDIATIMEOUT = 1, MSG_SCREENCASTWINDOWEVENT, @@ -101,15 +114,6 @@ struct DataChannelErrorMessageData : public rtc::MessageData { DataMediaChannel::Error error; }; - -struct VideoChannel::ScreencastDetailsData { - explicit ScreencastDetailsData(uint32_t s) - : ssrc(s), fps(0), screencast_max_pixels(0) {} - uint32_t ssrc; - int fps; - int screencast_max_pixels; -}; - static const char* PacketType(bool rtcp) { return (!rtcp) ? "RTP" : "RTCP"; } @@ -151,6 +155,7 @@ void RtpParametersFromMediaDescription( if (desc->rtp_header_extensions_set()) { params->extensions = desc->rtp_header_extensions(); } + params->rtcp.reduced_size = desc->rtcp_reduced_size(); } template <class Codec, class Options> @@ -218,11 +223,11 @@ bool BaseChannel::Init() { return false; } - if (!SetDtlsSrtpCiphers(transport_channel(), false)) { + if (!SetDtlsSrtpCryptoSuites(transport_channel(), false)) { return false; } if (rtcp_transport_enabled() && - !SetDtlsSrtpCiphers(rtcp_transport_channel(), true)) { + !SetDtlsSrtpCryptoSuites(rtcp_transport_channel(), true)) { return false; } @@ -249,21 +254,43 @@ bool BaseChannel::SetTransport_w(const std::string& transport_name) { return true; } - set_transport_channel(transport_controller_->CreateTransportChannel_w( - transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP)); - if (!transport_channel()) { - return false; + // When using DTLS-SRTP, we must reset the SrtpFilter every time the transport + // changes and wait until the DTLS handshake is complete to set the newly + // negotiated parameters. + if (ShouldSetupDtlsSrtp()) { + // Set |writable_| to false such that UpdateWritableState_w can set up + // DTLS-SRTP when the writable_ becomes true again. + writable_ = false; + srtp_filter_.ResetParams(); } + + // TODO(guoweis): Remove this grossness when we remove non-muxed 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)); + set_rtcp_transport_channel( + transport_controller_->CreateTransportChannel_w( + transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP), + false /* update_writablity */); if (!rtcp_transport_channel()) { return false; } } + // We're not updating the writablity during the transition state. + set_transport_channel(transport_controller_->CreateTransportChannel_w( + transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP)); + if (!transport_channel()) { + return false; + } + + // TODO(guoweis): Remove this grossness when we remove non-muxed RTCP. + if (rtcp_transport_enabled()) { + // We can only update the RTCP ready to send after set_transport_channel has + // handled channel writability. + SetReadyToSend( + true, rtcp_transport_channel() && rtcp_transport_channel()->writable()); + } transport_name_ = transport_name; return true; } @@ -299,7 +326,8 @@ void BaseChannel::set_transport_channel(TransportChannel* new_tc) { SetReadyToSend(false, new_tc && new_tc->writable()); } -void BaseChannel::set_rtcp_transport_channel(TransportChannel* new_tc) { +void BaseChannel::set_rtcp_transport_channel(TransportChannel* new_tc, + bool update_writablity) { ASSERT(worker_thread_ == rtc::Thread::Current()); TransportChannel* old_tc = rtcp_transport_channel_; @@ -318,16 +346,21 @@ void BaseChannel::set_rtcp_transport_channel(TransportChannel* new_tc) { rtcp_transport_channel_ = new_tc; if (new_tc) { + RTC_CHECK(!(ShouldSetupDtlsSrtp() && srtp_filter_.IsActive())) + << "Setting RTCP for DTLS/SRTP after SrtpFilter is active " + << "should never happen."; 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()); + if (update_writablity) { + // 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) { @@ -336,6 +369,7 @@ void BaseChannel::ConnectToTransportChannel(TransportChannel* tc) { tc->SignalWritableState.connect(this, &BaseChannel::OnWritableState); tc->SignalReadPacket.connect(this, &BaseChannel::OnChannelRead); tc->SignalReadyToSend.connect(this, &BaseChannel::OnReadyToSend); + tc->SignalDtlsState.connect(this, &BaseChannel::OnDtlsState); } void BaseChannel::DisconnectFromTransportChannel(TransportChannel* tc) { @@ -344,6 +378,7 @@ void BaseChannel::DisconnectFromTransportChannel(TransportChannel* tc) { tc->SignalWritableState.disconnect(this); tc->SignalReadPacket.disconnect(this); tc->SignalReadyToSend.disconnect(this); + tc->SignalDtlsState.disconnect(this); } bool BaseChannel::Enable(bool enable) { @@ -374,6 +409,7 @@ bool BaseChannel::RemoveSendStream(uint32_t ssrc) { bool BaseChannel::SetLocalContent(const MediaContentDescription* content, ContentAction action, std::string* error_desc) { + TRACE_EVENT0("webrtc", "BaseChannel::SetLocalContent"); return InvokeOnWorker(Bind(&BaseChannel::SetLocalContent_w, this, content, action, error_desc)); } @@ -381,6 +417,7 @@ bool BaseChannel::SetLocalContent(const MediaContentDescription* content, bool BaseChannel::SetRemoteContent(const MediaContentDescription* content, ContentAction action, std::string* error_desc) { + TRACE_EVENT0("webrtc", "BaseChannel::SetRemoteContent"); return InvokeOnWorker(Bind(&BaseChannel::SetRemoteContent_w, this, content, action, error_desc)); } @@ -416,10 +453,10 @@ bool BaseChannel::IsReadyToReceive() const { bool BaseChannel::IsReadyToSend() const { // Send outgoing data if we are enabled, have local and remote content, // and we have had some form of connectivity. - return enabled() && - IsReceiveContentDirection(remote_content_direction_) && + return enabled() && IsReceiveContentDirection(remote_content_direction_) && IsSendContentDirection(local_content_direction_) && - was_ever_writable(); + was_ever_writable() && + (srtp_filter_.IsActive() || !ShouldSetupDtlsSrtp()); } bool BaseChannel::SendPacket(rtc::Buffer* packet, @@ -459,6 +496,7 @@ void BaseChannel::OnChannelRead(TransportChannel* channel, const char* data, size_t len, const rtc::PacketTime& packet_time, int flags) { + TRACE_EVENT0("webrtc", "BaseChannel::OnChannelRead"); // OnChannelRead gets called from P2PSocket; now pass data to MediaEngine ASSERT(worker_thread_ == rtc::Thread::Current()); @@ -474,6 +512,22 @@ void BaseChannel::OnReadyToSend(TransportChannel* channel) { SetReadyToSend(channel == rtcp_transport_channel_, true); } +void BaseChannel::OnDtlsState(TransportChannel* channel, + DtlsTransportState state) { + if (!ShouldSetupDtlsSrtp()) { + return; + } + + // Reset the srtp filter if it's not the CONNECTED state. For the CONNECTED + // state, setting up DTLS-SRTP context is deferred to ChannelWritable_w to + // cover other scenarios like the whole channel is writable (not just this + // TransportChannel) or when TransportChannel is attached after DTLS is + // negotiated. + if (state != DTLS_TRANSPORT_CONNECTED) { + srtp_filter_.ResetParams(); + } +} + void BaseChannel::SetReadyToSend(bool rtcp, bool ready) { if (rtcp) { rtcp_ready_to_send_ = ready; @@ -512,7 +566,7 @@ bool BaseChannel::SendPacket(bool rtcp, // Avoid a copy by transferring the ownership of the packet data. int message_id = (!rtcp) ? MSG_RTPPACKET : MSG_RTCPPACKET; PacketMessageData* data = new PacketMessageData; - data->packet = packet->Pass(); + data->packet = std::move(*packet); data->options = options; worker_thread_->Post(this, message_id, data); return true; @@ -628,9 +682,12 @@ bool BaseChannel::WantsPacket(bool rtcp, rtc::Buffer* packet) { << " packet: wrong size=" << packet->size(); return false; } - - // Bundle filter handles both rtp and rtcp packets. - return bundle_filter_.DemuxPacket(packet->data<char>(), packet->size(), rtcp); + if (rtcp) { + // Permit all (seemingly valid) RTCP packets. + return true; + } + // Check whether we handle this payload. + return bundle_filter_.DemuxPacket(packet->data<uint8_t>(), packet->size()); } void BaseChannel::HandlePacket(bool rtcp, rtc::Buffer* packet, @@ -758,8 +815,9 @@ void BaseChannel::UpdateWritableState_w() { void BaseChannel::ChannelWritable_w() { ASSERT(worker_thread_ == rtc::Thread::Current()); - if (writable_) + if (writable_) { return; + } LOG(LS_INFO) << "Channel writable (" << content_name_ << ")" << (was_ever_writable_ ? "" : " for the first time"); @@ -775,22 +833,8 @@ void BaseChannel::ChannelWritable_w() { } } - // If we're doing DTLS-SRTP, now is the time. - if (!was_ever_writable_ && ShouldSetupDtlsSrtp()) { - if (!SetupDtlsSrtp(false)) { - SignalDtlsSetupFailure_w(false); - return; - } - - if (rtcp_transport_channel_) { - if (!SetupDtlsSrtp(true)) { - SignalDtlsSetupFailure_w(true); - return; - } - } - } - was_ever_writable_ = true; + MaybeSetupDtlsSrtp_w(); writable_ = true; ChangeState(); } @@ -806,20 +850,21 @@ void BaseChannel::SignalDtlsSetupFailure_s(bool rtcp) { SignalDtlsSetupFailure(this, rtcp); } -bool BaseChannel::SetDtlsSrtpCiphers(TransportChannel *tc, bool rtcp) { - std::vector<std::string> ciphers; - // We always use the default SRTP ciphers for RTCP, but we may use different - // ciphers for RTP depending on the media type. +bool BaseChannel::SetDtlsSrtpCryptoSuites(TransportChannel* tc, bool rtcp) { + std::vector<int> crypto_suites; + // We always use the default SRTP crypto suites for RTCP, but we may use + // different crypto suites for RTP depending on the media type. if (!rtcp) { - GetSrtpCryptoSuiteNames(&ciphers); + GetSrtpCryptoSuites(&crypto_suites); } else { - GetDefaultSrtpCryptoSuiteNames(&ciphers); + GetDefaultSrtpCryptoSuites(&crypto_suites); } - return tc->SetSrtpCiphers(ciphers); + return tc->SetSrtpCryptoSuites(crypto_suites); } bool BaseChannel::ShouldSetupDtlsSrtp() const { - return true; + // Since DTLS is applied to all channels, checking RTP should be enough. + return transport_channel_ && transport_channel_->IsDtlsActive(); } // This function returns true if either DTLS-SRTP is not in use @@ -830,14 +875,12 @@ bool BaseChannel::SetupDtlsSrtp(bool rtcp_channel) { TransportChannel* channel = rtcp_channel ? rtcp_transport_channel_ : transport_channel_; - // No DTLS - if (!channel->IsDtlsActive()) - return true; + RTC_DCHECK(channel->IsDtlsActive()); - std::string selected_cipher; + int selected_crypto_suite; - if (!channel->GetSrtpCryptoSuite(&selected_cipher)) { - LOG(LS_ERROR) << "No DTLS-SRTP selected cipher"; + if (!channel->GetSrtpCryptoSuite(&selected_crypto_suite)) { + LOG(LS_ERROR) << "No DTLS-SRTP selected crypto suite"; return false; } @@ -893,21 +936,15 @@ bool BaseChannel::SetupDtlsSrtp(bool rtcp_channel) { } if (rtcp_channel) { - ret = srtp_filter_.SetRtcpParams( - selected_cipher, - &(*send_key)[0], - static_cast<int>(send_key->size()), - selected_cipher, - &(*recv_key)[0], - static_cast<int>(recv_key->size())); + 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())); } else { - ret = srtp_filter_.SetRtpParams( - selected_cipher, - &(*send_key)[0], - static_cast<int>(send_key->size()), - selected_cipher, - &(*recv_key)[0], - static_cast<int>(recv_key->size())); + 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())); } if (!ret) @@ -918,6 +955,28 @@ bool BaseChannel::SetupDtlsSrtp(bool rtcp_channel) { return ret; } +void BaseChannel::MaybeSetupDtlsSrtp_w() { + if (srtp_filter_.IsActive()) { + return; + } + + if (!ShouldSetupDtlsSrtp()) { + return; + } + + if (!SetupDtlsSrtp(false)) { + SignalDtlsSetupFailure_w(false); + return; + } + + if (rtcp_transport_channel_) { + if (!SetupDtlsSrtp(true)) { + SignalDtlsSetupFailure_w(true); + return; + } + } +} + void BaseChannel::ChannelNotWritable_w() { ASSERT(worker_thread_ == rtc::Thread::Current()); if (!writable_) @@ -1022,7 +1081,7 @@ void BaseChannel::ActivateRtcpMux() { void BaseChannel::ActivateRtcpMux_w() { if (!rtcp_mux_filter_.IsActive()) { rtcp_mux_filter_.SetActive(); - set_rtcp_transport_channel(nullptr); + set_rtcp_transport_channel(nullptr, true); rtcp_transport_enabled_ = false; } } @@ -1045,7 +1104,7 @@ bool BaseChannel::SetRtcpMux_w(bool enable, ContentAction action, LOG(LS_INFO) << "Enabling rtcp-mux for " << content_name() << " by destroying RTCP transport channel for " << transport_name(); - set_rtcp_transport_channel(nullptr); + set_rtcp_transport_channel(nullptr, true); rtcp_transport_enabled_ = false; } break; @@ -1075,15 +1134,11 @@ bool BaseChannel::SetRtcpMux_w(bool enable, ContentAction action, bool BaseChannel::AddRecvStream_w(const StreamParams& sp) { ASSERT(worker_thread() == rtc::Thread::Current()); - if (!media_channel()->AddRecvStream(sp)) - return false; - - return bundle_filter_.AddStream(sp); + return media_channel()->AddRecvStream(sp); } bool BaseChannel::RemoveRecvStream_w(uint32_t ssrc) { ASSERT(worker_thread() == rtc::Thread::Current()); - bundle_filter_.RemoveStream(ssrc); return media_channel()->RemoveRecvStream(ssrc); } @@ -1243,6 +1298,7 @@ void BaseChannel::MaybeCacheRtpAbsSendTimeHeaderExtension( } void BaseChannel::OnMessage(rtc::Message *pmsg) { + TRACE_EVENT0("webrtc", "BaseChannel::OnMessage"); switch (pmsg->message_id) { case MSG_RTPPACKET: case MSG_RTCPPACKET: { @@ -1324,15 +1380,6 @@ void VoiceChannel::SetEarlyMedia(bool enable) { } } -bool VoiceChannel::PressDTMF(int digit, bool playout) { - int flags = DF_SEND; - if (playout) { - flags |= DF_PLAY; - } - int duration_ms = 160; - return InsertDtmf(0, digit, duration_ms, flags); -} - bool VoiceChannel::CanInsertDtmf() { return InvokeOnWorker(Bind(&VoiceMediaChannel::CanInsertDtmf, media_channel())); @@ -1340,10 +1387,9 @@ bool VoiceChannel::CanInsertDtmf() { bool VoiceChannel::InsertDtmf(uint32_t ssrc, int event_code, - int duration, - int flags) { + int duration) { return InvokeOnWorker(Bind(&VoiceChannel::InsertDtmf_w, this, - ssrc, event_code, duration, flags)); + ssrc, event_code, duration)); } bool VoiceChannel::SetOutputVolume(uint32_t ssrc, double volume) { @@ -1351,6 +1397,15 @@ bool VoiceChannel::SetOutputVolume(uint32_t ssrc, double volume) { media_channel(), ssrc, volume)); } +void VoiceChannel::SetRawAudioSink( + uint32_t ssrc, + rtc::scoped_ptr<webrtc::AudioSinkInterface> sink) { + // We need to work around Bind's lack of support for scoped_ptr and ownership + // passing. So we invoke to our own little routine that gets a pointer to + // our local variable. This is OK since we're synchronously invoking. + InvokeOnWorker(Bind(&SetRawAudioSink_w, media_channel(), ssrc, &sink)); +} + bool VoiceChannel::GetStats(VoiceMediaInfo* stats) { return InvokeOnWorker(Bind(&VoiceMediaChannel::GetStats, media_channel(), stats)); @@ -1440,6 +1495,7 @@ const ContentInfo* VoiceChannel::GetFirstContent( bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content, ContentAction action, std::string* error_desc) { + TRACE_EVENT0("webrtc", "VoiceChannel::SetLocalContent_w"); ASSERT(worker_thread() == rtc::Thread::Current()); LOG(LS_INFO) << "Setting local voice description"; @@ -1484,6 +1540,7 @@ bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content, bool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content, ContentAction action, std::string* error_desc) { + TRACE_EVENT0("webrtc", "VoiceChannel::SetRemoteContent_w"); ASSERT(worker_thread() == rtc::Thread::Current()); LOG(LS_INFO) << "Setting remote voice description"; @@ -1502,7 +1559,7 @@ bool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content, AudioSendParameters send_params = last_send_params_; RtpSendParametersFromMediaDescription(audio, &send_params); if (audio->agc_minus_10db()) { - send_params.options.adjust_agc_delta.Set(kAgcMinus10db); + send_params.options.adjust_agc_delta = rtc::Optional<int>(kAgcMinus10db); } if (!media_channel()->SetSendParameters(send_params)) { SafeSetError("Failed to set remote audio description send parameters.", @@ -1539,13 +1596,11 @@ void VoiceChannel::HandleEarlyMediaTimeout() { bool VoiceChannel::InsertDtmf_w(uint32_t ssrc, int event, - int duration, - int flags) { + int duration) { if (!enabled()) { return false; } - - return media_channel()->InsertDtmf(ssrc, event, duration, flags); + return media_channel()->InsertDtmf(ssrc, event, duration); } void VoiceChannel::OnMessage(rtc::Message *pmsg) { @@ -1581,9 +1636,8 @@ void VoiceChannel::OnAudioMonitorUpdate(AudioMonitor* monitor, SignalAudioMonitor(this, info); } -void VoiceChannel::GetSrtpCryptoSuiteNames( - std::vector<std::string>* ciphers) const { - GetSupportedAudioCryptoSuites(ciphers); +void VoiceChannel::GetSrtpCryptoSuites(std::vector<int>* crypto_suites) const { + GetSupportedAudioCryptoSuites(crypto_suites); } VideoChannel::VideoChannel(rtc::Thread* thread, @@ -1653,20 +1707,6 @@ bool VideoChannel::IsScreencasting() { return InvokeOnWorker(Bind(&VideoChannel::IsScreencasting_w, this)); } -int VideoChannel::GetScreencastFps(uint32_t ssrc) { - ScreencastDetailsData data(ssrc); - worker_thread()->Invoke<void>(Bind( - &VideoChannel::GetScreencastDetails_w, this, &data)); - return data.fps; -} - -int VideoChannel::GetScreencastMaxPixels(uint32_t ssrc) { - ScreencastDetailsData data(ssrc); - worker_thread()->Invoke<void>(Bind( - &VideoChannel::GetScreencastDetails_w, this, &data)); - return data.screencast_max_pixels; -} - bool VideoChannel::SendIntraFrame() { worker_thread()->Invoke<void>(Bind( &VideoMediaChannel::SendIntraFrame, media_channel())); @@ -1726,6 +1766,7 @@ const ContentInfo* VideoChannel::GetFirstContent( bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content, ContentAction action, std::string* error_desc) { + TRACE_EVENT0("webrtc", "VideoChannel::SetLocalContent_w"); ASSERT(worker_thread() == rtc::Thread::Current()); LOG(LS_INFO) << "Setting local video description"; @@ -1770,6 +1811,7 @@ bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content, bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content, ContentAction action, std::string* error_desc) { + TRACE_EVENT0("webrtc", "VideoChannel::SetRemoteContent_w"); ASSERT(worker_thread() == rtc::Thread::Current()); LOG(LS_INFO) << "Setting remote video description"; @@ -1789,7 +1831,7 @@ bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content, VideoSendParameters send_params = last_send_params_; RtpSendParametersFromMediaDescription(video, &send_params); if (video->conference_mode()) { - send_params.options.conference_mode.Set(true); + send_params.options.conference_mode = rtc::Optional<bool>(true); } if (!media_channel()->SetSendParameters(send_params)) { SafeSetError("Failed to set remote video description send parameters.", @@ -1877,18 +1919,6 @@ bool VideoChannel::IsScreencasting_w() const { return !screencast_capturers_.empty(); } -void VideoChannel::GetScreencastDetails_w( - ScreencastDetailsData* data) const { - ScreencastMap::const_iterator iter = screencast_capturers_.find(data->ssrc); - if (iter == screencast_capturers_.end()) { - return; - } - VideoCapturer* capturer = iter->second; - const VideoFormat* video_format = capturer->GetCaptureFormat(); - data->fps = VideoFormat::IntervalToFps(video_format->interval); - data->screencast_max_pixels = capturer->screencast_max_pixels(); -} - void VideoChannel::OnScreencastWindowEvent_s(uint32_t ssrc, rtc::WindowEvent we) { ASSERT(signaling_thread() == rtc::Thread::Current()); @@ -1971,9 +2001,8 @@ bool VideoChannel::GetLocalSsrc(const VideoCapturer* capturer, uint32_t* ssrc) { return false; } -void VideoChannel::GetSrtpCryptoSuiteNames( - std::vector<std::string>* ciphers) const { - GetSupportedVideoCryptoSuites(ciphers); +void VideoChannel::GetSrtpCryptoSuites(std::vector<int>* crypto_suites) const { + GetSupportedVideoCryptoSuites(crypto_suites); } DataChannel::DataChannel(rtc::Thread* thread, @@ -2067,6 +2096,7 @@ bool DataChannel::SetDataChannelTypeFromContent( bool DataChannel::SetLocalContent_w(const MediaContentDescription* content, ContentAction action, std::string* error_desc) { + TRACE_EVENT0("webrtc", "DataChannel::SetLocalContent_w"); ASSERT(worker_thread() == rtc::Thread::Current()); LOG(LS_INFO) << "Setting local data description"; @@ -2122,6 +2152,7 @@ bool DataChannel::SetLocalContent_w(const MediaContentDescription* content, bool DataChannel::SetRemoteContent_w(const MediaContentDescription* content, ContentAction action, std::string* error_desc) { + TRACE_EVENT0("webrtc", "DataChannel::SetRemoteContent_w"); ASSERT(worker_thread() == rtc::Thread::Current()); const DataContentDescription* data = @@ -2279,13 +2310,12 @@ void DataChannel::OnDataChannelReadyToSend(bool writable) { new DataChannelReadyToSendMessageData(writable)); } -void DataChannel::GetSrtpCryptoSuiteNames( - std::vector<std::string>* ciphers) const { - GetSupportedDataCryptoSuites(ciphers); +void DataChannel::GetSrtpCryptoSuites(std::vector<int>* crypto_suites) const { + GetSupportedDataCryptoSuites(crypto_suites); } bool DataChannel::ShouldSetupDtlsSrtp() const { - return (data_channel_type_ == DCT_RTP); + return (data_channel_type_ == DCT_RTP) && BaseChannel::ShouldSetupDtlsSrtp(); } void DataChannel::OnStreamClosedRemotely(uint32_t sid) { diff --git a/talk/session/media/channel.h b/talk/session/media/channel.h index 603115cee7..d8fde670a0 100644 --- a/talk/session/media/channel.h +++ b/talk/session/media/channel.h @@ -38,19 +38,24 @@ #include "talk/media/base/mediaengine.h" #include "talk/media/base/streamparams.h" #include "talk/media/base/videocapturer.h" -#include "webrtc/p2p/base/transportcontroller.h" -#include "webrtc/p2p/client/socketmonitor.h" #include "talk/session/media/audiomonitor.h" #include "talk/session/media/bundlefilter.h" #include "talk/session/media/mediamonitor.h" #include "talk/session/media/mediasession.h" #include "talk/session/media/rtcpmuxfilter.h" #include "talk/session/media/srtpfilter.h" +#include "webrtc/audio/audio_sink.h" #include "webrtc/base/asyncudpsocket.h" #include "webrtc/base/criticalsection.h" #include "webrtc/base/network.h" #include "webrtc/base/sigslot.h" #include "webrtc/base/window.h" +#include "webrtc/p2p/base/transportcontroller.h" +#include "webrtc/p2p/client/socketmonitor.h" + +namespace webrtc { +class AudioSinkInterface; +} // namespace webrtc namespace cricket { @@ -174,8 +179,11 @@ class BaseChannel // Sets the |transport_channel_| (and |rtcp_transport_channel_|, if |rtcp_| is // true). Gets the transport channels from |transport_controller_|. bool SetTransport_w(const std::string& transport_name); + void set_transport_channel(TransportChannel* transport); - void set_rtcp_transport_channel(TransportChannel* transport); + void set_rtcp_transport_channel(TransportChannel* transport, + bool update_writablity); + bool was_ever_writable() const { return was_ever_writable_; } void set_local_content_direction(MediaContentDirection direction) { local_content_direction_ = direction; @@ -213,6 +221,8 @@ class BaseChannel int flags); void OnReadyToSend(TransportChannel* channel); + void OnDtlsState(TransportChannel* channel, DtlsTransportState state); + bool PacketIsRtcp(const TransportChannel* channel, const char* data, size_t len); bool SendPacket(bool rtcp, @@ -235,8 +245,9 @@ class BaseChannel // Do the DTLS key expansion and impose it on the SRTP/SRTCP filters. // |rtcp_channel| indicates whether to set up the RTP or RTCP filter. bool SetupDtlsSrtp(bool rtcp_channel); + void MaybeSetupDtlsSrtp_w(); // Set the DTLS-SRTP cipher policy on this channel as appropriate. - bool SetDtlsSrtpCiphers(TransportChannel *tc, bool rtcp); + bool SetDtlsSrtpCryptoSuites(TransportChannel* tc, bool rtcp); virtual void ChangeState() = 0; @@ -282,9 +293,8 @@ class BaseChannel void OnMessage(rtc::Message* pmsg) override; // Handled in derived classes - // Get the SRTP ciphers to use for RTP media - virtual void GetSrtpCryptoSuiteNames( - std::vector<std::string>* ciphers) const = 0; + // Get the SRTP crypto suites to use for RTP media + virtual void GetSrtpCryptoSuites(std::vector<int>* crypto_suites) const = 0; virtual void OnConnectionMonitorUpdate(ConnectionMonitor* monitor, const std::vector<ConnectionInfo>& infos) = 0; @@ -356,8 +366,6 @@ class VoiceChannel : public BaseChannel { // own ringing sound sigslot::signal1<VoiceChannel*> SignalEarlyMediaTimeout; - // TODO(ronghuawu): Replace PressDTMF with InsertDtmf. - bool PressDTMF(int digit, bool playout); // Returns if the telephone-event has been negotiated. bool CanInsertDtmf(); // Send and/or play a DTMF |event| according to the |flags|. @@ -365,8 +373,11 @@ class VoiceChannel : public BaseChannel { // The |ssrc| should be either 0 or a valid send stream ssrc. // The valid value for the |event| are 0 which corresponding to DTMF // event 0-9, *, #, A-D. - bool InsertDtmf(uint32_t ssrc, int event_code, int duration, int flags); + bool InsertDtmf(uint32_t ssrc, int event_code, int duration); bool SetOutputVolume(uint32_t ssrc, double volume); + void SetRawAudioSink(uint32_t ssrc, + rtc::scoped_ptr<webrtc::AudioSinkInterface> sink); + // Get statistics about the current media session. bool GetStats(VoiceMediaInfo* stats); @@ -402,12 +413,12 @@ class VoiceChannel : public BaseChannel { ContentAction action, std::string* error_desc); void HandleEarlyMediaTimeout(); - bool InsertDtmf_w(uint32_t ssrc, int event, int duration, int flags); + bool InsertDtmf_w(uint32_t ssrc, int event, int duration); bool SetOutputVolume_w(uint32_t ssrc, double volume); bool GetStats_w(VoiceMediaInfo* stats); virtual void OnMessage(rtc::Message* pmsg); - virtual void GetSrtpCryptoSuiteNames(std::vector<std::string>* ciphers) const; + virtual void GetSrtpCryptoSuites(std::vector<int>* crypto_suites) const; virtual void OnConnectionMonitorUpdate( ConnectionMonitor* monitor, const std::vector<ConnectionInfo>& infos); virtual void OnMediaMonitorUpdate( @@ -456,8 +467,6 @@ class VideoChannel : public BaseChannel { // True if we've added a screencast. Doesn't matter if the capturer // has been started or not. bool IsScreencasting(); - int GetScreencastFps(uint32_t ssrc); - int GetScreencastMaxPixels(uint32_t ssrc); // Get statistics about the current media session. bool GetStats(VideoMediaInfo* stats); @@ -476,7 +485,6 @@ class VideoChannel : public BaseChannel { private: typedef std::map<uint32_t, VideoCapturer*> ScreencastMap; - struct ScreencastDetailsData; // overrides from BaseChannel virtual void ChangeState(); @@ -493,11 +501,10 @@ class VideoChannel : public BaseChannel { bool RemoveScreencast_w(uint32_t ssrc); void OnScreencastWindowEvent_s(uint32_t ssrc, rtc::WindowEvent we); bool IsScreencasting_w() const; - void GetScreencastDetails_w(ScreencastDetailsData* d) const; bool GetStats_w(VideoMediaInfo* stats); virtual void OnMessage(rtc::Message* pmsg); - virtual void GetSrtpCryptoSuiteNames(std::vector<std::string>* ciphers) const; + virtual void GetSrtpCryptoSuites(std::vector<int>* crypto_suites) const; virtual void OnConnectionMonitorUpdate( ConnectionMonitor* monitor, const std::vector<ConnectionInfo>& infos); virtual void OnMediaMonitorUpdate( @@ -614,7 +621,7 @@ class DataChannel : public BaseChannel { virtual bool WantsPacket(bool rtcp, rtc::Buffer* packet); virtual void OnMessage(rtc::Message* pmsg); - virtual void GetSrtpCryptoSuiteNames(std::vector<std::string>* ciphers) const; + virtual void GetSrtpCryptoSuites(std::vector<int>* crypto_suites) const; virtual void OnConnectionMonitorUpdate( ConnectionMonitor* monitor, const std::vector<ConnectionInfo>& infos); virtual void OnMediaMonitorUpdate( diff --git a/talk/session/media/channel_unittest.cc b/talk/session/media/channel_unittest.cc index 18233202b6..6b1d66fe39 100644 --- a/talk/session/media/channel_unittest.cc +++ b/talk/session/media/channel_unittest.cc @@ -33,8 +33,8 @@ #include "talk/media/base/rtpdump.h" #include "talk/media/base/screencastid.h" #include "talk/media/base/testutils.h" -#include "webrtc/p2p/base/faketransportcontroller.h" #include "talk/session/media/channel.h" +#include "webrtc/base/arraysize.h" #include "webrtc/base/fileutils.h" #include "webrtc/base/gunit.h" #include "webrtc/base/helpers.h" @@ -44,6 +44,7 @@ #include "webrtc/base/ssladapter.h" #include "webrtc/base/sslidentity.h" #include "webrtc/base/window.h" +#include "webrtc/p2p/base/faketransportcontroller.h" #define MAYBE_SKIP_TEST(feature) \ if (!(rtc::SSLStreamAdapter::feature())) { \ @@ -174,17 +175,15 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> { if (flags1 & DTLS) { // Confirmed to work with KT_RSA and KT_ECDSA. - transport_controller1_.SetLocalCertificate(rtc::RTCCertificate::Create( - rtc::scoped_ptr<rtc::SSLIdentity>( - rtc::SSLIdentity::Generate("session1", rtc::KT_DEFAULT)) - .Pass())); + transport_controller1_.SetLocalCertificate( + rtc::RTCCertificate::Create(rtc::scoped_ptr<rtc::SSLIdentity>( + rtc::SSLIdentity::Generate("session1", rtc::KT_DEFAULT)))); } if (flags2 & DTLS) { // Confirmed to work with KT_RSA and KT_ECDSA. - transport_controller2_.SetLocalCertificate(rtc::RTCCertificate::Create( - rtc::scoped_ptr<rtc::SSLIdentity>( - rtc::SSLIdentity::Generate("session2", rtc::KT_DEFAULT)) - .Pass())); + transport_controller2_.SetLocalCertificate( + rtc::RTCCertificate::Create(rtc::scoped_ptr<rtc::SSLIdentity>( + rtc::SSLIdentity::Generate("session2", rtc::KT_DEFAULT)))); } // Add stream information (SSRC) to the local content but not to the remote @@ -1473,12 +1472,6 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> { EXPECT_TRUE(channel2_->bundle_filter()->FindPayloadType(pl_type1)); EXPECT_FALSE(channel1_->bundle_filter()->FindPayloadType(pl_type2)); EXPECT_FALSE(channel2_->bundle_filter()->FindPayloadType(pl_type2)); - // channel1 - should only have media_content2 as remote. i.e. kSsrc2 - EXPECT_TRUE(channel1_->bundle_filter()->FindStream(kSsrc2)); - EXPECT_FALSE(channel1_->bundle_filter()->FindStream(kSsrc1)); - // channel2 - should only have media_content1 as remote. i.e. kSsrc1 - EXPECT_TRUE(channel2_->bundle_filter()->FindStream(kSsrc1)); - EXPECT_FALSE(channel2_->bundle_filter()->FindStream(kSsrc2)); // Both channels can receive pl_type1 only. EXPECT_TRUE(SendCustomRtp1(kSsrc1, ++sequence_number1_1, pl_type1)); @@ -1503,8 +1496,9 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> { EXPECT_TRUE(SendCustomRtcp1(kSsrc2)); EXPECT_TRUE(SendCustomRtcp2(kSsrc1)); - EXPECT_FALSE(CheckCustomRtcp1(kSsrc1)); - EXPECT_FALSE(CheckCustomRtcp2(kSsrc2)); + // Bundle filter shouldn't filter out any RTCP. + EXPECT_TRUE(CheckCustomRtcp1(kSsrc1)); + EXPECT_TRUE(CheckCustomRtcp2(kSsrc2)); } // Test that the media monitor can be run and gives timely callbacks. @@ -2116,23 +2110,6 @@ TEST_F(VoiceChannelTest, TestMediaMonitor) { Base::TestMediaMonitor(); } -// Test that PressDTMF properly forwards to the media channel. -TEST_F(VoiceChannelTest, TestDtmf) { - CreateChannels(0, 0); - EXPECT_TRUE(SendInitiate()); - EXPECT_TRUE(SendAccept()); - EXPECT_EQ(0U, media_channel1_->dtmf_info_queue().size()); - - EXPECT_TRUE(channel1_->PressDTMF(1, true)); - EXPECT_TRUE(channel1_->PressDTMF(8, false)); - - ASSERT_EQ(2U, media_channel1_->dtmf_info_queue().size()); - EXPECT_TRUE(CompareDtmfInfo(media_channel1_->dtmf_info_queue()[0], - 0, 1, 160, cricket::DF_PLAY | cricket::DF_SEND)); - EXPECT_TRUE(CompareDtmfInfo(media_channel1_->dtmf_info_queue()[1], - 0, 8, 160, cricket::DF_SEND)); -} - // Test that InsertDtmf properly forwards to the media channel. TEST_F(VoiceChannelTest, TestInsertDtmf) { CreateChannels(0, 0); @@ -2140,18 +2117,17 @@ TEST_F(VoiceChannelTest, TestInsertDtmf) { EXPECT_TRUE(SendAccept()); EXPECT_EQ(0U, media_channel1_->dtmf_info_queue().size()); - EXPECT_TRUE(channel1_->InsertDtmf(1, 3, 100, cricket::DF_SEND)); - EXPECT_TRUE(channel1_->InsertDtmf(2, 5, 110, cricket::DF_PLAY)); - EXPECT_TRUE(channel1_->InsertDtmf(3, 7, 120, - cricket::DF_PLAY | cricket::DF_SEND)); + EXPECT_TRUE(channel1_->InsertDtmf(1, 3, 100)); + EXPECT_TRUE(channel1_->InsertDtmf(2, 5, 110)); + EXPECT_TRUE(channel1_->InsertDtmf(3, 7, 120)); ASSERT_EQ(3U, media_channel1_->dtmf_info_queue().size()); EXPECT_TRUE(CompareDtmfInfo(media_channel1_->dtmf_info_queue()[0], - 1, 3, 100, cricket::DF_SEND)); + 1, 3, 100)); EXPECT_TRUE(CompareDtmfInfo(media_channel1_->dtmf_info_queue()[1], - 2, 5, 110, cricket::DF_PLAY)); + 2, 5, 110)); EXPECT_TRUE(CompareDtmfInfo(media_channel1_->dtmf_info_queue()[2], - 3, 7, 120, cricket::DF_PLAY | cricket::DF_SEND)); + 3, 7, 120)); } TEST_F(VoiceChannelTest, TestSetContentFailure) { @@ -2253,21 +2229,19 @@ TEST_F(VoiceChannelTest, TestScaleVolumeMultiwayCall) { } TEST_F(VoiceChannelTest, SendBundleToBundle) { - Base::SendBundleToBundle(kAudioPts, ARRAY_SIZE(kAudioPts), false, false); + Base::SendBundleToBundle(kAudioPts, arraysize(kAudioPts), false, false); } TEST_F(VoiceChannelTest, SendBundleToBundleSecure) { - Base::SendBundleToBundle(kAudioPts, ARRAY_SIZE(kAudioPts), false, true); + Base::SendBundleToBundle(kAudioPts, arraysize(kAudioPts), false, true); } TEST_F(VoiceChannelTest, SendBundleToBundleWithRtcpMux) { - Base::SendBundleToBundle( - kAudioPts, ARRAY_SIZE(kAudioPts), true, false); + Base::SendBundleToBundle(kAudioPts, arraysize(kAudioPts), true, false); } TEST_F(VoiceChannelTest, SendBundleToBundleWithRtcpMuxSecure) { - Base::SendBundleToBundle( - kAudioPts, ARRAY_SIZE(kAudioPts), true, true); + Base::SendBundleToBundle(kAudioPts, arraysize(kAudioPts), true, true); } // VideoChannelTest @@ -2501,21 +2475,19 @@ TEST_F(VideoChannelTest, TestFlushRtcp) { } TEST_F(VideoChannelTest, SendBundleToBundle) { - Base::SendBundleToBundle(kVideoPts, ARRAY_SIZE(kVideoPts), false, false); + Base::SendBundleToBundle(kVideoPts, arraysize(kVideoPts), false, false); } TEST_F(VideoChannelTest, SendBundleToBundleSecure) { - Base::SendBundleToBundle(kVideoPts, ARRAY_SIZE(kVideoPts), false, true); + Base::SendBundleToBundle(kVideoPts, arraysize(kVideoPts), false, true); } TEST_F(VideoChannelTest, SendBundleToBundleWithRtcpMux) { - Base::SendBundleToBundle( - kVideoPts, ARRAY_SIZE(kVideoPts), true, false); + Base::SendBundleToBundle(kVideoPts, arraysize(kVideoPts), true, false); } TEST_F(VideoChannelTest, SendBundleToBundleWithRtcpMuxSecure) { - Base::SendBundleToBundle( - kVideoPts, ARRAY_SIZE(kVideoPts), true, true); + Base::SendBundleToBundle(kVideoPts, arraysize(kVideoPts), true, true); } TEST_F(VideoChannelTest, TestSrtpError) { diff --git a/talk/session/media/channelmanager.cc b/talk/session/media/channelmanager.cc index e7e1cd44a2..e7a4b8bddb 100644 --- a/talk/session/media/channelmanager.cc +++ b/talk/session/media/channelmanager.cc @@ -49,6 +49,7 @@ #include "webrtc/base/sigslotrepeater.h" #include "webrtc/base/stringencode.h" #include "webrtc/base/stringutils.h" +#include "webrtc/base/trace_event.h" namespace cricket { @@ -101,8 +102,6 @@ void ChannelManager::Construct(MediaEngineInterface* me, initialized_ = false; main_thread_ = rtc::Thread::Current(); worker_thread_ = worker_thread; - // Get the default audio options from the media engine. - audio_options_ = media_engine_->GetAudioOptions(); audio_output_volume_ = kNotSetOutputVolume; local_renderer_ = NULL; capturing_ = false; @@ -156,7 +155,7 @@ void ChannelManager::GetSupportedAudioCodecs( void ChannelManager::GetSupportedAudioRtpHeaderExtensions( RtpHeaderExtensions* ext) const { - *ext = media_engine_->audio_rtp_header_extensions(); + *ext = media_engine_->GetAudioCapabilities().header_extensions; } void ChannelManager::GetSupportedVideoCodecs( @@ -175,7 +174,7 @@ void ChannelManager::GetSupportedVideoCodecs( void ChannelManager::GetSupportedVideoRtpHeaderExtensions( RtpHeaderExtensions* ext) const { - *ext = media_engine_->video_rtp_header_extensions(); + *ext = media_engine_->GetVideoCapabilities().header_extensions; } void ChannelManager::GetSupportedDataCodecs( @@ -205,11 +204,6 @@ bool ChannelManager::Init() { return false; } - if (!SetAudioOptions(audio_options_)) { - LOG(LS_WARNING) << "Failed to SetAudioOptions with options: " - << audio_options_.ToString(); - } - // If audio_output_volume_ has been set via SetOutputVolume(), set the // audio output volume of the engine. if (kNotSetOutputVolume != audio_output_volume_ && @@ -218,11 +212,6 @@ bool ChannelManager::Init() { << audio_output_volume_; } - // Now apply the default video codec that has been set earlier. - if (default_video_encoder_config_.max_codec.id != 0) { - SetDefaultVideoEncoderConfig(default_video_encoder_config_); - } - return initialized_; } @@ -295,6 +284,7 @@ VoiceChannel* ChannelManager::CreateVoiceChannel_w( } void ChannelManager::DestroyVoiceChannel(VoiceChannel* voice_channel) { + TRACE_EVENT0("webrtc", "ChannelManager::DestroyVoiceChannel"); if (voice_channel) { worker_thread_->Invoke<void>( Bind(&ChannelManager::DestroyVoiceChannel_w, this, voice_channel)); @@ -302,6 +292,7 @@ void ChannelManager::DestroyVoiceChannel(VoiceChannel* voice_channel) { } void ChannelManager::DestroyVoiceChannel_w(VoiceChannel* voice_channel) { + TRACE_EVENT0("webrtc", "ChannelManager::DestroyVoiceChannel_w"); // Destroy voice channel. ASSERT(initialized_); ASSERT(worker_thread_ == rtc::Thread::Current()); @@ -351,6 +342,7 @@ VideoChannel* ChannelManager::CreateVideoChannel_w( } void ChannelManager::DestroyVideoChannel(VideoChannel* video_channel) { + TRACE_EVENT0("webrtc", "ChannelManager::DestroyVideoChannel"); if (video_channel) { worker_thread_->Invoke<void>( Bind(&ChannelManager::DestroyVideoChannel_w, this, video_channel)); @@ -358,6 +350,7 @@ void ChannelManager::DestroyVideoChannel(VideoChannel* video_channel) { } void ChannelManager::DestroyVideoChannel_w(VideoChannel* video_channel) { + TRACE_EVENT0("webrtc", "ChannelManager::DestroyVideoChannel_w"); // Destroy video channel. ASSERT(initialized_); ASSERT(worker_thread_ == rtc::Thread::Current()); @@ -408,6 +401,7 @@ DataChannel* ChannelManager::CreateDataChannel_w( } void ChannelManager::DestroyDataChannel(DataChannel* data_channel) { + TRACE_EVENT0("webrtc", "ChannelManager::DestroyDataChannel"); if (data_channel) { worker_thread_->Invoke<void>( Bind(&ChannelManager::DestroyDataChannel_w, this, data_channel)); @@ -415,6 +409,7 @@ void ChannelManager::DestroyDataChannel(DataChannel* data_channel) { } void ChannelManager::DestroyDataChannel_w(DataChannel* data_channel) { + TRACE_EVENT0("webrtc", "ChannelManager::DestroyDataChannel_w"); // Destroy data channel. ASSERT(initialized_); DataChannels::iterator it = std::find(data_channels_.begin(), @@ -427,43 +422,6 @@ void ChannelManager::DestroyDataChannel_w(DataChannel* data_channel) { delete data_channel; } -bool ChannelManager::SetAudioOptions(const AudioOptions& options) { - // "Get device ids from DeviceManager" - these are the defaults returned. - Device in_dev("", -1); - Device out_dev("", -1); - - // If we're initialized, pass the settings to the media engine. - bool ret = true; - if (initialized_) { - ret = worker_thread_->Invoke<bool>( - Bind(&ChannelManager::SetAudioOptions_w, this, - options, &in_dev, &out_dev)); - } - - // If all worked well, save the values for use in GetAudioOptions. - if (ret) { - audio_options_ = options; - } - return ret; -} - -bool ChannelManager::SetAudioOptions_w( - const AudioOptions& options, - const Device* in_dev, const Device* out_dev) { - ASSERT(worker_thread_ == rtc::Thread::Current()); - ASSERT(initialized_); - - // Set audio options - bool ret = media_engine_->SetAudioOptions(options); - - // Set the audio devices - if (ret) { - ret = media_engine_->SetSoundDevices(in_dev, out_dev); - } - - return ret; -} - bool ChannelManager::GetOutputVolume(int* level) { if (!initialized_) { return false; @@ -487,39 +445,6 @@ bool ChannelManager::SetOutputVolume(int level) { return ret; } -bool ChannelManager::SetDefaultVideoEncoderConfig(const VideoEncoderConfig& c) { - bool ret = true; - if (initialized_) { - ret = worker_thread_->Invoke<bool>( - Bind(&MediaEngineInterface::SetDefaultVideoEncoderConfig, - media_engine_.get(), c)); - } - if (ret) { - default_video_encoder_config_ = c; - } - return ret; -} - -void ChannelManager::SetVoiceLogging(int level, const char* filter) { - if (initialized_) { - worker_thread_->Invoke<void>( - Bind(&MediaEngineInterface::SetVoiceLogging, - media_engine_.get(), level, filter)); - } else { - media_engine_->SetVoiceLogging(level, filter); - } -} - -void ChannelManager::SetVideoLogging(int level, const char* filter) { - if (initialized_) { - worker_thread_->Invoke<void>( - Bind(&MediaEngineInterface::SetVideoLogging, - media_engine_.get(), level, filter)); - } else { - media_engine_->SetVideoLogging(level, filter); - } -} - std::vector<cricket::VideoFormat> ChannelManager::GetSupportedFormats( VideoCapturer* capturer) const { ASSERT(capturer != NULL); diff --git a/talk/session/media/channelmanager.h b/talk/session/media/channelmanager.h index 6312e61e06..2bc516bfaa 100644 --- a/talk/session/media/channelmanager.h +++ b/talk/session/media/channelmanager.h @@ -129,7 +129,6 @@ class ChannelManager : public rtc::MessageHandler, bool GetOutputVolume(int* level); bool SetOutputVolume(int level); - bool SetDefaultVideoEncoderConfig(const VideoEncoderConfig& config); // RTX will be enabled/disabled in engines that support it. The supporting // engines will start offering an RTX codec. Must be called before Init(). bool SetVideoRtxEnabled(bool enable); @@ -137,10 +136,6 @@ class ChannelManager : public rtc::MessageHandler, // Starts/stops the local microphone and enables polling of the input level. bool capturing() const { return capturing_; } - // Configures the logging output of the mediaengine(s). - void SetVoiceLogging(int level, const char* filter); - void SetVideoLogging(int level, const char* filter); - // Gets capturer's supported formats in a thread safe manner std::vector<cricket::VideoFormat> GetSupportedFormats( VideoCapturer* capturer) const; @@ -181,11 +176,6 @@ class ChannelManager : public rtc::MessageHandler, sigslot::signal2<VideoCapturer*, CaptureState> SignalVideoCaptureStateChange; - protected: - // Adds non-transient parameters which can only be changed through the - // options store. - bool SetAudioOptions(const AudioOptions& options); - private: typedef std::vector<VoiceChannel*> VoiceChannels; typedef std::vector<VideoChannel*> VideoChannels; @@ -217,8 +207,6 @@ class ChannelManager : public rtc::MessageHandler, bool rtcp, DataChannelType data_channel_type); void DestroyDataChannel_w(DataChannel* data_channel); - bool SetAudioOptions_w(const AudioOptions& options, - const Device* in_dev, const Device* out_dev); void OnVideoCaptureStateChange(VideoCapturer* capturer, CaptureState result); void GetSupportedFormats_w( @@ -238,9 +226,7 @@ class ChannelManager : public rtc::MessageHandler, VideoChannels video_channels_; DataChannels data_channels_; - AudioOptions audio_options_; int audio_output_volume_; - VideoEncoderConfig default_video_encoder_config_; VideoRenderer* local_renderer_; bool enable_rtx_; diff --git a/talk/session/media/channelmanager_unittest.cc b/talk/session/media/channelmanager_unittest.cc index fa6aa2cab6..4740f0f37d 100644 --- a/talk/session/media/channelmanager_unittest.cc +++ b/talk/session/media/channelmanager_unittest.cc @@ -183,38 +183,6 @@ TEST_F(ChannelManagerTest, NoTransportChannelTest) { cm_->Terminate(); } -// Test that SetDefaultVideoCodec passes through the right values. -TEST_F(ChannelManagerTest, SetDefaultVideoEncoderConfig) { - cricket::VideoCodec codec(96, "G264", 1280, 720, 60, 0); - cricket::VideoEncoderConfig config(codec, 1, 2); - EXPECT_TRUE(cm_->Init()); - EXPECT_TRUE(cm_->SetDefaultVideoEncoderConfig(config)); - EXPECT_EQ(config, fme_->default_video_encoder_config()); -} - -struct GetCapturerFrameSize : public sigslot::has_slots<> { - void OnVideoFrame(VideoCapturer* capturer, const VideoFrame* frame) { - width = frame->GetWidth(); - height = frame->GetHeight(); - } - GetCapturerFrameSize(VideoCapturer* capturer) : width(0), height(0) { - capturer->SignalVideoFrame.connect(this, - &GetCapturerFrameSize::OnVideoFrame); - static_cast<FakeVideoCapturer*>(capturer)->CaptureFrame(); - } - size_t width; - size_t height; -}; - -// Test that SetDefaultVideoCodec passes through the right values. -TEST_F(ChannelManagerTest, SetDefaultVideoCodecBeforeInit) { - cricket::VideoCodec codec(96, "G264", 1280, 720, 60, 0); - cricket::VideoEncoderConfig config(codec, 1, 2); - EXPECT_TRUE(cm_->SetDefaultVideoEncoderConfig(config)); - EXPECT_TRUE(cm_->Init()); - EXPECT_EQ(config, fme_->default_video_encoder_config()); -} - TEST_F(ChannelManagerTest, GetSetOutputVolumeBeforeInit) { int level; // Before init, SetOutputVolume() remembers the volume but does not change the @@ -250,33 +218,6 @@ TEST_F(ChannelManagerTest, GetSetOutputVolume) { EXPECT_EQ(60, level); } -// Test that logging options set before Init are applied properly, -// and retained even after Init. -TEST_F(ChannelManagerTest, SetLoggingBeforeInit) { - cm_->SetVoiceLogging(rtc::LS_INFO, "test-voice"); - cm_->SetVideoLogging(rtc::LS_VERBOSE, "test-video"); - EXPECT_EQ(rtc::LS_INFO, fme_->voice_loglevel()); - EXPECT_STREQ("test-voice", fme_->voice_logfilter().c_str()); - EXPECT_EQ(rtc::LS_VERBOSE, fme_->video_loglevel()); - EXPECT_STREQ("test-video", fme_->video_logfilter().c_str()); - EXPECT_TRUE(cm_->Init()); - EXPECT_EQ(rtc::LS_INFO, fme_->voice_loglevel()); - EXPECT_STREQ("test-voice", fme_->voice_logfilter().c_str()); - EXPECT_EQ(rtc::LS_VERBOSE, fme_->video_loglevel()); - EXPECT_STREQ("test-video", fme_->video_logfilter().c_str()); -} - -// Test that logging options set after Init are applied properly. -TEST_F(ChannelManagerTest, SetLogging) { - EXPECT_TRUE(cm_->Init()); - cm_->SetVoiceLogging(rtc::LS_INFO, "test-voice"); - cm_->SetVideoLogging(rtc::LS_VERBOSE, "test-video"); - EXPECT_EQ(rtc::LS_INFO, fme_->voice_loglevel()); - EXPECT_STREQ("test-voice", fme_->voice_logfilter().c_str()); - EXPECT_EQ(rtc::LS_VERBOSE, fme_->video_loglevel()); - EXPECT_STREQ("test-video", fme_->video_logfilter().c_str()); -} - TEST_F(ChannelManagerTest, SetVideoRtxEnabled) { std::vector<VideoCodec> codecs; const VideoCodec rtx_codec(96, "rtx", 0, 0, 0, 0); diff --git a/talk/session/media/mediasession.cc b/talk/session/media/mediasession.cc index 7413026092..24f01b4463 100644 --- a/talk/session/media/mediasession.cc +++ b/talk/session/media/mediasession.cc @@ -50,6 +50,17 @@ static const uint32_t kMaxSctpSid = 1023; namespace { const char kInline[] = "inline:"; + +void GetSupportedCryptoSuiteNames(void (*func)(std::vector<int>*), + std::vector<std::string>* names) { +#ifdef HAVE_SRTP + std::vector<int> crypto_suites; + func(&crypto_suites); + for (const auto crypto : crypto_suites) { + names->push_back(rtc::SrtpCryptoSuiteToName(crypto)); + } +#endif +} } namespace cricket { @@ -152,30 +163,50 @@ bool FindMatchingCrypto(const CryptoParamsVec& cryptos, } // For audio, HMAC 32 is prefered because of the low overhead. -void GetSupportedAudioCryptoSuites( - std::vector<std::string>* crypto_suites) { +void GetSupportedAudioCryptoSuites(std::vector<int>* crypto_suites) { #ifdef HAVE_SRTP - crypto_suites->push_back(rtc::CS_AES_CM_128_HMAC_SHA1_32); - crypto_suites->push_back(rtc::CS_AES_CM_128_HMAC_SHA1_80); + crypto_suites->push_back(rtc::SRTP_AES128_CM_SHA1_32); + crypto_suites->push_back(rtc::SRTP_AES128_CM_SHA1_80); #endif } -void GetSupportedVideoCryptoSuites( - std::vector<std::string>* crypto_suites) { - GetDefaultSrtpCryptoSuiteNames(crypto_suites); +void GetSupportedAudioCryptoSuiteNames( + std::vector<std::string>* crypto_suite_names) { + GetSupportedCryptoSuiteNames(GetSupportedAudioCryptoSuites, + crypto_suite_names); +} + +void GetSupportedVideoCryptoSuites(std::vector<int>* crypto_suites) { + GetDefaultSrtpCryptoSuites(crypto_suites); +} + +void GetSupportedVideoCryptoSuiteNames( + std::vector<std::string>* crypto_suite_names) { + GetSupportedCryptoSuiteNames(GetSupportedVideoCryptoSuites, + crypto_suite_names); } -void GetSupportedDataCryptoSuites( - std::vector<std::string>* crypto_suites) { - GetDefaultSrtpCryptoSuiteNames(crypto_suites); +void GetSupportedDataCryptoSuites(std::vector<int>* crypto_suites) { + GetDefaultSrtpCryptoSuites(crypto_suites); } -void GetDefaultSrtpCryptoSuiteNames(std::vector<std::string>* crypto_suites) { +void GetSupportedDataCryptoSuiteNames( + std::vector<std::string>* crypto_suite_names) { + GetSupportedCryptoSuiteNames(GetSupportedDataCryptoSuites, + crypto_suite_names); +} + +void GetDefaultSrtpCryptoSuites(std::vector<int>* crypto_suites) { #ifdef HAVE_SRTP - crypto_suites->push_back(rtc::CS_AES_CM_128_HMAC_SHA1_80); + crypto_suites->push_back(rtc::SRTP_AES128_CM_SHA1_80); #endif } +void GetDefaultSrtpCryptoSuiteNames( + std::vector<std::string>* crypto_suite_names) { + GetSupportedCryptoSuiteNames(GetDefaultSrtpCryptoSuites, crypto_suite_names); +} + // For video support only 80-bit SHA1 HMAC. For audio 32-bit HMAC is // tolerated unless bundle is enabled because it is low overhead. Pick the // crypto in the list that is supported. @@ -518,8 +549,8 @@ static bool AddStreamParams( // Updates the transport infos of the |sdesc| according to the given // |bundle_group|. The transport infos of the content names within the -// |bundle_group| should be updated to use the ufrag and pwd of the first -// content within the |bundle_group|. +// |bundle_group| should be updated to use the ufrag, pwd and DTLS role of the +// first content within the |bundle_group|. static bool UpdateTransportInfoForBundle(const ContentGroup& bundle_group, SessionDescription* sdesc) { // The bundle should not be empty. @@ -540,6 +571,8 @@ static bool UpdateTransportInfoForBundle(const ContentGroup& bundle_group, selected_transport_info->description.ice_ufrag; const std::string& selected_pwd = selected_transport_info->description.ice_pwd; + ConnectionRole selected_connection_role = + selected_transport_info->description.connection_role; for (TransportInfos::iterator it = sdesc->transport_infos().begin(); it != sdesc->transport_infos().end(); ++it) { @@ -547,6 +580,7 @@ static bool UpdateTransportInfoForBundle(const ContentGroup& bundle_group, it->content_name != selected_content_name) { it->description.ice_ufrag = selected_ufrag; it->description.ice_pwd = selected_pwd; + it->description.connection_role = selected_connection_role; } } return true; @@ -602,6 +636,11 @@ static void PruneCryptos(const CryptoParamsVec& filter, target_cryptos->end()); } +static bool IsRtpProtocol(const std::string& protocol) { + return protocol.empty() || + (protocol.find(cricket::kMediaProtocolRtpPrefix) != std::string::npos); +} + static bool IsRtpContent(SessionDescription* sdesc, const std::string& content_name) { bool is_rtp = false; @@ -612,9 +651,7 @@ static bool IsRtpContent(SessionDescription* sdesc, if (!media_desc) { return false; } - is_rtp = media_desc->protocol().empty() || - (media_desc->protocol().find(cricket::kMediaProtocolRtpPrefix) != - std::string::npos); + is_rtp = IsRtpProtocol(media_desc->protocol()); } return is_rtp; } @@ -726,6 +763,11 @@ static bool CreateMediaContentOffer( offer->set_crypto_required(CT_SDES); } offer->set_rtcp_mux(options.rtcp_mux_enabled); + // TODO(deadbeef): Once we're sure this works correctly, enable it in + // CreateOffer. + // if (offer->type() == cricket::MEDIA_TYPE_VIDEO) { + // offer->set_rtcp_reduced_size(true); + // } offer->set_multistream(options.is_muc); offer->set_rtp_header_extensions(rtp_extensions); @@ -1004,6 +1046,11 @@ static bool CreateMediaContentAnswer( answer->set_rtp_header_extensions(negotiated_rtp_extensions); answer->set_rtcp_mux(options.rtcp_mux_enabled && offer->rtcp_mux()); + // TODO(deadbeef): Once we're sure this works correctly, enable it in + // CreateAnswer. + // if (answer->type() == cricket::MEDIA_TYPE_VIDEO) { + // answer->set_rtcp_reduced_size(offer->rtcp_reduced_size()); + // } if (sdes_policy != SEC_DISABLED) { CryptoParams crypto; @@ -1036,12 +1083,16 @@ static bool CreateMediaContentAnswer( answer->set_direction(MD_RECVONLY); break; case MD_RECVONLY: - answer->set_direction(answer->streams().empty() ? MD_INACTIVE - : MD_SENDONLY); + answer->set_direction(IsRtpProtocol(answer->protocol()) && + answer->streams().empty() + ? MD_INACTIVE + : MD_SENDONLY); break; case MD_SENDRECV: - answer->set_direction(answer->streams().empty() ? MD_RECVONLY - : MD_SENDRECV); + answer->set_direction(IsRtpProtocol(answer->protocol()) && + answer->streams().empty() + ? MD_RECVONLY + : MD_SENDRECV); break; default: RTC_DCHECK(false && "MediaContentDescription has unexpected direction."); @@ -1508,13 +1559,18 @@ bool MediaSessionDescriptionFactory::AddAudioContentForOffer( const AudioCodecs& audio_codecs, StreamParamsVec* current_streams, SessionDescription* desc) const { + const ContentInfo* current_audio_content = + GetFirstAudioContent(current_description); + std::string content_name = + current_audio_content ? current_audio_content->name : CN_AUDIO; + cricket::SecurePolicy sdes_policy = - IsDtlsActive(CN_AUDIO, current_description) ? - cricket::SEC_DISABLED : secure(); + IsDtlsActive(content_name, current_description) ? cricket::SEC_DISABLED + : secure(); scoped_ptr<AudioContentDescription> audio(new AudioContentDescription()); std::vector<std::string> crypto_suites; - GetSupportedAudioCryptoSuites(&crypto_suites); + GetSupportedAudioCryptoSuiteNames(&crypto_suites); if (!CreateMediaContentOffer( options, audio_codecs, @@ -1546,8 +1602,8 @@ bool MediaSessionDescriptionFactory::AddAudioContentForOffer( } } - desc->AddContent(CN_AUDIO, NS_JINGLE_RTP, audio.release()); - if (!AddTransportOffer(CN_AUDIO, options.transport_options, + desc->AddContent(content_name, NS_JINGLE_RTP, audio.release()); + if (!AddTransportOffer(content_name, options.audio_transport_options, current_description, desc)) { return false; } @@ -1562,13 +1618,18 @@ bool MediaSessionDescriptionFactory::AddVideoContentForOffer( const VideoCodecs& video_codecs, StreamParamsVec* current_streams, SessionDescription* desc) const { + const ContentInfo* current_video_content = + GetFirstVideoContent(current_description); + std::string content_name = + current_video_content ? current_video_content->name : CN_VIDEO; + cricket::SecurePolicy sdes_policy = - IsDtlsActive(CN_VIDEO, current_description) ? - cricket::SEC_DISABLED : secure(); + IsDtlsActive(content_name, current_description) ? cricket::SEC_DISABLED + : secure(); scoped_ptr<VideoContentDescription> video(new VideoContentDescription()); std::vector<std::string> crypto_suites; - GetSupportedVideoCryptoSuites(&crypto_suites); + GetSupportedVideoCryptoSuiteNames(&crypto_suites); if (!CreateMediaContentOffer( options, video_codecs, @@ -1601,8 +1662,8 @@ bool MediaSessionDescriptionFactory::AddVideoContentForOffer( } } - desc->AddContent(CN_VIDEO, NS_JINGLE_RTP, video.release()); - if (!AddTransportOffer(CN_VIDEO, options.transport_options, + desc->AddContent(content_name, NS_JINGLE_RTP, video.release()); + if (!AddTransportOffer(content_name, options.video_transport_options, current_description, desc)) { return false; } @@ -1623,9 +1684,14 @@ bool MediaSessionDescriptionFactory::AddDataContentForOffer( FilterDataCodecs(data_codecs, is_sctp); + const ContentInfo* current_data_content = + GetFirstDataContent(current_description); + std::string content_name = + current_data_content ? current_data_content->name : CN_DATA; + cricket::SecurePolicy sdes_policy = - IsDtlsActive(CN_DATA, current_description) ? - cricket::SEC_DISABLED : secure(); + IsDtlsActive(content_name, current_description) ? cricket::SEC_DISABLED + : secure(); std::vector<std::string> crypto_suites; if (is_sctp) { // SDES doesn't make sense for SCTP, so we disable it, and we only @@ -1638,7 +1704,7 @@ bool MediaSessionDescriptionFactory::AddDataContentForOffer( data->set_protocol( secure_transport ? kMediaProtocolDtlsSctp : kMediaProtocolSctp); } else { - GetSupportedDataCryptoSuites(&crypto_suites); + GetSupportedDataCryptoSuiteNames(&crypto_suites); } if (!CreateMediaContentOffer( @@ -1655,13 +1721,13 @@ bool MediaSessionDescriptionFactory::AddDataContentForOffer( } if (is_sctp) { - desc->AddContent(CN_DATA, NS_JINGLE_DRAFT_SCTP, data.release()); + desc->AddContent(content_name, NS_JINGLE_DRAFT_SCTP, data.release()); } else { data->set_bandwidth(options.data_bandwidth); SetMediaProtocol(secure_transport, data.get()); - desc->AddContent(CN_DATA, NS_JINGLE_RTP, data.release()); + desc->AddContent(content_name, NS_JINGLE_RTP, data.release()); } - if (!AddTransportOffer(CN_DATA, options.transport_options, + if (!AddTransportOffer(content_name, options.data_transport_options, current_description, desc)) { return false; } @@ -1676,10 +1742,9 @@ bool MediaSessionDescriptionFactory::AddAudioContentForAnswer( SessionDescription* answer) const { const ContentInfo* audio_content = GetFirstAudioContent(offer); - scoped_ptr<TransportDescription> audio_transport( - CreateTransportAnswer(audio_content->name, offer, - options.transport_options, - current_description)); + scoped_ptr<TransportDescription> audio_transport(CreateTransportAnswer( + audio_content->name, offer, options.audio_transport_options, + current_description)); if (!audio_transport) { return false; } @@ -1735,10 +1800,9 @@ bool MediaSessionDescriptionFactory::AddVideoContentForAnswer( StreamParamsVec* current_streams, SessionDescription* answer) const { const ContentInfo* video_content = GetFirstVideoContent(offer); - scoped_ptr<TransportDescription> video_transport( - CreateTransportAnswer(video_content->name, offer, - options.transport_options, - current_description)); + scoped_ptr<TransportDescription> video_transport(CreateTransportAnswer( + video_content->name, offer, options.video_transport_options, + current_description)); if (!video_transport) { return false; } @@ -1791,10 +1855,9 @@ bool MediaSessionDescriptionFactory::AddDataContentForAnswer( StreamParamsVec* current_streams, SessionDescription* answer) const { const ContentInfo* data_content = GetFirstDataContent(offer); - scoped_ptr<TransportDescription> data_transport( - CreateTransportAnswer(data_content->name, offer, - options.transport_options, - current_description)); + scoped_ptr<TransportDescription> data_transport(CreateTransportAnswer( + data_content->name, offer, options.data_transport_options, + current_description)); if (!data_transport) { return false; } diff --git a/talk/session/media/mediasession.h b/talk/session/media/mediasession.h index e92628e711..1540274665 100644 --- a/talk/session/media/mediasession.h +++ b/talk/session/media/mediasession.h @@ -134,6 +134,10 @@ struct MediaSessionOptions { bool HasSendMediaStream(MediaType type) const; + // TODO(deadbeef): Put all the audio/video/data-specific options into a map + // structure (content name -> options). + // MediaSessionDescriptionFactory assumes there will never be more than one + // audio/video/data content, but this will change with unified plan. bool recv_audio; bool recv_video; DataChannelType data_channel_type; @@ -144,7 +148,9 @@ struct MediaSessionOptions { // bps. -1 == auto. int video_bandwidth; int data_bandwidth; - TransportOptions transport_options; + TransportOptions audio_transport_options; + TransportOptions video_transport_options; + TransportOptions data_transport_options; struct Stream { Stream(MediaType type, @@ -167,17 +173,7 @@ struct MediaSessionOptions { // "content" (as used in XEP-0166) descriptions for voice and video. class MediaContentDescription : public ContentDescription { public: - MediaContentDescription() - : rtcp_mux_(false), - bandwidth_(kAutoBandwidth), - crypto_required_(CT_NONE), - rtp_header_extensions_set_(false), - multistream_(false), - conference_mode_(false), - partial_(false), - buffered_mode_latency_(kBufferedModeDisabled), - direction_(MD_SENDRECV) { - } + MediaContentDescription() {} virtual MediaType type() const = 0; virtual bool has_codecs() const = 0; @@ -195,6 +191,11 @@ class MediaContentDescription : public ContentDescription { bool rtcp_mux() const { return rtcp_mux_; } void set_rtcp_mux(bool mux) { rtcp_mux_ = mux; } + bool rtcp_reduced_size() const { return rtcp_reduced_size_; } + void set_rtcp_reduced_size(bool reduced_size) { + rtcp_reduced_size_ = reduced_size; + } + int bandwidth() const { return bandwidth_; } void set_bandwidth(int bandwidth) { bandwidth_ = bandwidth; } @@ -291,19 +292,20 @@ class MediaContentDescription : public ContentDescription { int buffered_mode_latency() const { return buffered_mode_latency_; } protected: - bool rtcp_mux_; - int bandwidth_; + bool rtcp_mux_ = false; + bool rtcp_reduced_size_ = false; + int bandwidth_ = kAutoBandwidth; std::string protocol_; std::vector<CryptoParams> cryptos_; - CryptoType crypto_required_; + CryptoType crypto_required_ = CT_NONE; std::vector<RtpHeaderExtension> rtp_header_extensions_; - bool rtp_header_extensions_set_; - bool multistream_; + bool rtp_header_extensions_set_ = false; + bool multistream_ = false; StreamParamsVec streams_; - bool conference_mode_; - bool partial_; - int buffered_mode_latency_; - MediaContentDirection direction_; + bool conference_mode_ = false; + bool partial_ = false; + int buffered_mode_latency_ = kBufferedModeDisabled; + MediaContentDirection direction_ = MD_SENDRECV; }; template <class C> @@ -547,10 +549,19 @@ const VideoContentDescription* GetFirstVideoContentDescription( const DataContentDescription* GetFirstDataContentDescription( const SessionDescription* sdesc); -void GetSupportedAudioCryptoSuites(std::vector<std::string>* crypto_suites); -void GetSupportedVideoCryptoSuites(std::vector<std::string>* crypto_suites); -void GetSupportedDataCryptoSuites(std::vector<std::string>* crypto_suites); -void GetDefaultSrtpCryptoSuiteNames(std::vector<std::string>* crypto_suites); +void GetSupportedAudioCryptoSuites(std::vector<int>* crypto_suites); +void GetSupportedVideoCryptoSuites(std::vector<int>* crypto_suites); +void GetSupportedDataCryptoSuites(std::vector<int>* crypto_suites); +void GetDefaultSrtpCryptoSuites(std::vector<int>* crypto_suites); +void GetSupportedAudioCryptoSuiteNames( + std::vector<std::string>* crypto_suite_names); +void GetSupportedVideoCryptoSuiteNames( + std::vector<std::string>* crypto_suite_names); +void GetSupportedDataCryptoSuiteNames( + std::vector<std::string>* crypto_suite_names); +void GetDefaultSrtpCryptoSuiteNames( + std::vector<std::string>* crypto_suite_names); + } // namespace cricket #endif // TALK_SESSION_MEDIA_MEDIASESSION_H_ diff --git a/talk/session/media/mediasession_unittest.cc b/talk/session/media/mediasession_unittest.cc index 72aefc884c..20b72e9394 100644 --- a/talk/session/media/mediasession_unittest.cc +++ b/talk/session/media/mediasession_unittest.cc @@ -69,6 +69,9 @@ using cricket::CryptoParamsVec; using cricket::AudioContentDescription; using cricket::VideoContentDescription; using cricket::DataContentDescription; +using cricket::GetFirstAudioContent; +using cricket::GetFirstVideoContent; +using cricket::GetFirstDataContent; using cricket::GetFirstAudioContentDescription; using cricket::GetFirstVideoContentDescription; using cricket::GetFirstDataContentDescription; @@ -235,11 +238,9 @@ class MediaSessionDescriptionFactoryTest : public testing::Test { f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2)); f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2)); tdf1_.set_certificate(rtc::RTCCertificate::Create( - rtc::scoped_ptr<rtc::SSLIdentity>( - new rtc::FakeSSLIdentity("id1")).Pass())); + rtc::scoped_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1")))); tdf2_.set_certificate(rtc::RTCCertificate::Create( - rtc::scoped_ptr<rtc::SSLIdentity>( - new rtc::FakeSSLIdentity("id2")).Pass())); + rtc::scoped_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id2")))); } // Create a video StreamParamsVec object with: @@ -607,6 +608,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80); EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol()); } + // Create a RTP data offer, and ensure it matches what we expect. TEST_F(MediaSessionDescriptionFactoryTest, TestCreateRtpDataOffer) { MediaSessionOptions opts; @@ -2313,3 +2315,30 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestVADEnableOption) { audio_content = answer->GetContentByName("audio"); EXPECT_TRUE(VerifyNoCNCodecs(audio_content)); } + +// Test that the content name ("mid" in SDP) is unchanged when creating a +// new offer. +TEST_F(MediaSessionDescriptionFactoryTest, + TestContentNameNotChangedInSubsequentOffers) { + MediaSessionOptions opts; + opts.recv_audio = true; + opts.recv_video = true; + opts.data_channel_type = cricket::DCT_SCTP; + // Create offer and modify the default content names. + rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr)); + for (ContentInfo& content : offer->contents()) { + content.name.append("_modified"); + } + + rtc::scoped_ptr<SessionDescription> updated_offer( + f1_.CreateOffer(opts, offer.get())); + const ContentInfo* audio_content = GetFirstAudioContent(updated_offer.get()); + const ContentInfo* video_content = GetFirstVideoContent(updated_offer.get()); + const ContentInfo* data_content = GetFirstDataContent(updated_offer.get()); + ASSERT_TRUE(audio_content != nullptr); + ASSERT_TRUE(video_content != nullptr); + ASSERT_TRUE(data_content != nullptr); + EXPECT_EQ("audio_modified", audio_content->name); + EXPECT_EQ("video_modified", video_content->name); + EXPECT_EQ("data_modified", data_content->name); +} diff --git a/talk/session/media/srtpfilter.cc b/talk/session/media/srtpfilter.cc index 079ddfb57e..a200a3c4c2 100644 --- a/talk/session/media/srtpfilter.cc +++ b/talk/session/media/srtpfilter.cc @@ -146,10 +146,10 @@ bool SrtpFilter::SetProvisionalAnswer( return DoSetAnswer(answer_params, source, false); } -bool SrtpFilter::SetRtpParams(const std::string& send_cs, +bool SrtpFilter::SetRtpParams(int send_cs, const uint8_t* send_key, int send_key_len, - const std::string& recv_cs, + int recv_cs, const uint8_t* recv_key, int recv_key_len) { if (IsActive()) { @@ -179,10 +179,10 @@ bool SrtpFilter::SetRtpParams(const std::string& send_cs, // SrtpSession. // - In the muxed case, they are keyed with the same keys, so // this function is not needed -bool SrtpFilter::SetRtcpParams(const std::string& send_cs, +bool SrtpFilter::SetRtcpParams(int send_cs, const uint8_t* send_key, int send_key_len, - const std::string& recv_cs, + int recv_cs, const uint8_t* recv_key, int recv_key_len) { // This can only be called once, but can be safely called after @@ -428,10 +428,12 @@ bool SrtpFilter::ApplyParams(const CryptoParams& send_params, ParseKeyParams(recv_params.key_params, recv_key, sizeof(recv_key))); if (ret) { CreateSrtpSessions(); - ret = (send_session_->SetSend(send_params.cipher_suite, - send_key, sizeof(send_key)) && - recv_session_->SetRecv(recv_params.cipher_suite, - recv_key, sizeof(recv_key))); + ret = (send_session_->SetSend( + rtc::SrtpCryptoSuiteFromName(send_params.cipher_suite), send_key, + sizeof(send_key)) && + recv_session_->SetRecv( + rtc::SrtpCryptoSuiteFromName(recv_params.cipher_suite), recv_key, + sizeof(recv_key))); } if (ret) { LOG(LS_INFO) << "SRTP activated with negotiated parameters:" @@ -448,6 +450,10 @@ bool SrtpFilter::ApplyParams(const CryptoParams& send_params, bool SrtpFilter::ResetParams() { offer_params_.clear(); state_ = ST_INIT; + send_session_ = nullptr; + recv_session_ = nullptr; + send_rtcp_session_ = nullptr; + recv_rtcp_session_ = nullptr; LOG(LS_INFO) << "SRTP reset to init state"; return true; } @@ -507,11 +513,11 @@ SrtpSession::~SrtpSession() { } } -bool SrtpSession::SetSend(const std::string& cs, const uint8_t* key, int len) { +bool SrtpSession::SetSend(int cs, const uint8_t* key, int len) { return SetKey(ssrc_any_outbound, cs, key, len); } -bool SrtpSession::SetRecv(const std::string& cs, const uint8_t* key, int len) { +bool SrtpSession::SetRecv(int cs, const uint8_t* key, int len) { return SetKey(ssrc_any_inbound, cs, key, len); } @@ -658,10 +664,7 @@ void SrtpSession::set_signal_silent_time(uint32_t signal_silent_time_in_ms) { srtp_stat_->set_signal_silent_time(signal_silent_time_in_ms); } -bool SrtpSession::SetKey(int type, - const std::string& cs, - const uint8_t* key, - int len) { +bool SrtpSession::SetKey(int type, int cs, const uint8_t* key, int len) { if (session_) { LOG(LS_ERROR) << "Failed to create SRTP session: " << "SRTP session already created"; @@ -675,15 +678,15 @@ bool SrtpSession::SetKey(int type, srtp_policy_t policy; memset(&policy, 0, sizeof(policy)); - if (cs == rtc::CS_AES_CM_128_HMAC_SHA1_80) { + if (cs == rtc::SRTP_AES128_CM_SHA1_80) { crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp); crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp); - } else if (cs == rtc::CS_AES_CM_128_HMAC_SHA1_32) { + } else if (cs == rtc::SRTP_AES128_CM_SHA1_32) { crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtp); // rtp is 32, crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp); // rtcp still 80 } else { LOG(LS_WARNING) << "Failed to create SRTP session: unsupported" - << " cipher_suite " << cs.c_str(); + << " cipher_suite " << cs; return false; } diff --git a/talk/session/media/srtpfilter.h b/talk/session/media/srtpfilter.h index 3c3a8e848b..6b941f32fd 100644 --- a/talk/session/media/srtpfilter.h +++ b/talk/session/media/srtpfilter.h @@ -104,16 +104,16 @@ class SrtpFilter { // Just set up both sets of keys directly. // Used with DTLS-SRTP. - bool SetRtpParams(const std::string& send_cs, + bool SetRtpParams(int send_cs, const uint8_t* send_key, int send_key_len, - const std::string& recv_cs, + int recv_cs, const uint8_t* recv_key, int recv_key_len); - bool SetRtcpParams(const std::string& send_cs, + bool SetRtcpParams(int send_cs, const uint8_t* send_key, int send_key_len, - const std::string& recv_cs, + int recv_cs, const uint8_t* recv_key, int recv_key_len); @@ -138,6 +138,8 @@ class SrtpFilter { // Update the silent threshold (in ms) for signaling errors. void set_signal_silent_time(uint32_t signal_silent_time_in_ms); + bool ResetParams(); + sigslot::repeater3<uint32_t, Mode, Error> SignalSrtpError; protected: @@ -153,7 +155,6 @@ class SrtpFilter { CryptoParams* selected_params); bool ApplyParams(const CryptoParams& send_params, const CryptoParams& recv_params); - bool ResetParams(); static bool ParseKeyParams(const std::string& params, uint8_t* key, int len); private: @@ -199,10 +200,10 @@ class SrtpSession { // Configures the session for sending data using the specified // cipher-suite and key. Receiving must be done by a separate session. - bool SetSend(const std::string& cs, const uint8_t* key, int len); + bool SetSend(int cs, const uint8_t* key, int len); // Configures the session for receiving data using the specified // cipher-suite and key. Sending must be done by a separate session. - bool SetRecv(const std::string& cs, const uint8_t* key, int len); + bool SetRecv(int cs, const uint8_t* key, int len); // Encrypts/signs an individual RTP/RTCP packet, in-place. // If an HMAC is used, this will increase the packet size. @@ -232,7 +233,7 @@ class SrtpSession { SignalSrtpError; private: - bool SetKey(int type, const std::string& cs, const uint8_t* key, int len); + bool SetKey(int type, int cs, const uint8_t* key, int len); // Returns send stream current packet index from srtp db. bool GetSendStreamPacketIndex(void* data, int in_len, int64_t* index); diff --git a/talk/session/media/srtpfilter_unittest.cc b/talk/session/media/srtpfilter_unittest.cc index 8122455205..11874380e2 100644 --- a/talk/session/media/srtpfilter_unittest.cc +++ b/talk/session/media/srtpfilter_unittest.cc @@ -508,21 +508,17 @@ TEST_F(SrtpFilterTest, TestDisableEncryption) { // Test directly setting the params with AES_CM_128_HMAC_SHA1_80 TEST_F(SrtpFilterTest, TestProtect_SetParamsDirect_AES_CM_128_HMAC_SHA1_80) { - EXPECT_TRUE(f1_.SetRtpParams(CS_AES_CM_128_HMAC_SHA1_80, - kTestKey1, kTestKeyLen, - CS_AES_CM_128_HMAC_SHA1_80, + EXPECT_TRUE(f1_.SetRtpParams(rtc::SRTP_AES128_CM_SHA1_80, kTestKey1, + kTestKeyLen, rtc::SRTP_AES128_CM_SHA1_80, kTestKey2, kTestKeyLen)); - EXPECT_TRUE(f2_.SetRtpParams(CS_AES_CM_128_HMAC_SHA1_80, - kTestKey2, kTestKeyLen, - CS_AES_CM_128_HMAC_SHA1_80, + EXPECT_TRUE(f2_.SetRtpParams(rtc::SRTP_AES128_CM_SHA1_80, kTestKey2, + kTestKeyLen, rtc::SRTP_AES128_CM_SHA1_80, kTestKey1, kTestKeyLen)); - EXPECT_TRUE(f1_.SetRtcpParams(CS_AES_CM_128_HMAC_SHA1_80, - kTestKey1, kTestKeyLen, - CS_AES_CM_128_HMAC_SHA1_80, + EXPECT_TRUE(f1_.SetRtcpParams(rtc::SRTP_AES128_CM_SHA1_80, kTestKey1, + kTestKeyLen, rtc::SRTP_AES128_CM_SHA1_80, kTestKey2, kTestKeyLen)); - EXPECT_TRUE(f2_.SetRtcpParams(CS_AES_CM_128_HMAC_SHA1_80, - kTestKey2, kTestKeyLen, - CS_AES_CM_128_HMAC_SHA1_80, + EXPECT_TRUE(f2_.SetRtcpParams(rtc::SRTP_AES128_CM_SHA1_80, kTestKey2, + kTestKeyLen, rtc::SRTP_AES128_CM_SHA1_80, kTestKey1, kTestKeyLen)); EXPECT_TRUE(f1_.IsActive()); EXPECT_TRUE(f2_.IsActive()); @@ -531,21 +527,17 @@ TEST_F(SrtpFilterTest, TestProtect_SetParamsDirect_AES_CM_128_HMAC_SHA1_80) { // Test directly setting the params with AES_CM_128_HMAC_SHA1_32 TEST_F(SrtpFilterTest, TestProtect_SetParamsDirect_AES_CM_128_HMAC_SHA1_32) { - EXPECT_TRUE(f1_.SetRtpParams(CS_AES_CM_128_HMAC_SHA1_32, - kTestKey1, kTestKeyLen, - CS_AES_CM_128_HMAC_SHA1_32, + EXPECT_TRUE(f1_.SetRtpParams(rtc::SRTP_AES128_CM_SHA1_32, kTestKey1, + kTestKeyLen, rtc::SRTP_AES128_CM_SHA1_32, kTestKey2, kTestKeyLen)); - EXPECT_TRUE(f2_.SetRtpParams(CS_AES_CM_128_HMAC_SHA1_32, - kTestKey2, kTestKeyLen, - CS_AES_CM_128_HMAC_SHA1_32, + EXPECT_TRUE(f2_.SetRtpParams(rtc::SRTP_AES128_CM_SHA1_32, kTestKey2, + kTestKeyLen, rtc::SRTP_AES128_CM_SHA1_32, kTestKey1, kTestKeyLen)); - EXPECT_TRUE(f1_.SetRtcpParams(CS_AES_CM_128_HMAC_SHA1_32, - kTestKey1, kTestKeyLen, - CS_AES_CM_128_HMAC_SHA1_32, + EXPECT_TRUE(f1_.SetRtcpParams(rtc::SRTP_AES128_CM_SHA1_32, kTestKey1, + kTestKeyLen, rtc::SRTP_AES128_CM_SHA1_32, kTestKey2, kTestKeyLen)); - EXPECT_TRUE(f2_.SetRtcpParams(CS_AES_CM_128_HMAC_SHA1_32, - kTestKey2, kTestKeyLen, - CS_AES_CM_128_HMAC_SHA1_32, + EXPECT_TRUE(f2_.SetRtcpParams(rtc::SRTP_AES128_CM_SHA1_32, kTestKey2, + kTestKeyLen, rtc::SRTP_AES128_CM_SHA1_32, kTestKey1, kTestKeyLen)); EXPECT_TRUE(f1_.IsActive()); EXPECT_TRUE(f2_.IsActive()); @@ -554,25 +546,21 @@ TEST_F(SrtpFilterTest, TestProtect_SetParamsDirect_AES_CM_128_HMAC_SHA1_32) { // Test directly setting the params with bogus keys TEST_F(SrtpFilterTest, TestSetParamsKeyTooShort) { - EXPECT_FALSE(f1_.SetRtpParams(CS_AES_CM_128_HMAC_SHA1_80, - kTestKey1, kTestKeyLen - 1, - CS_AES_CM_128_HMAC_SHA1_80, + EXPECT_FALSE(f1_.SetRtpParams(rtc::SRTP_AES128_CM_SHA1_80, kTestKey1, + kTestKeyLen - 1, rtc::SRTP_AES128_CM_SHA1_80, kTestKey1, kTestKeyLen - 1)); - EXPECT_FALSE(f1_.SetRtcpParams(CS_AES_CM_128_HMAC_SHA1_80, - kTestKey1, kTestKeyLen - 1, - CS_AES_CM_128_HMAC_SHA1_80, + EXPECT_FALSE(f1_.SetRtcpParams(rtc::SRTP_AES128_CM_SHA1_80, kTestKey1, + kTestKeyLen - 1, rtc::SRTP_AES128_CM_SHA1_80, kTestKey1, kTestKeyLen - 1)); } #if defined(ENABLE_EXTERNAL_AUTH) TEST_F(SrtpFilterTest, TestGetSendAuthParams) { - EXPECT_TRUE(f1_.SetRtpParams(CS_AES_CM_128_HMAC_SHA1_32, - kTestKey1, kTestKeyLen, - CS_AES_CM_128_HMAC_SHA1_32, + EXPECT_TRUE(f1_.SetRtpParams(rtc::SRTP_AES128_CM_SHA1_32, kTestKey1, + kTestKeyLen, rtc::SRTP_AES128_CM_SHA1_32, kTestKey2, kTestKeyLen)); - EXPECT_TRUE(f1_.SetRtcpParams(CS_AES_CM_128_HMAC_SHA1_32, - kTestKey1, kTestKeyLen, - CS_AES_CM_128_HMAC_SHA1_32, + EXPECT_TRUE(f1_.SetRtcpParams(rtc::SRTP_AES128_CM_SHA1_32, kTestKey1, + kTestKeyLen, rtc::SRTP_AES128_CM_SHA1_32, kTestKey2, kTestKeyLen)); uint8_t* auth_key = NULL; int auth_key_len = 0, auth_tag_len = 0; @@ -629,28 +617,30 @@ class SrtpSessionTest : public testing::Test { // Test that we can set up the session and keys properly. TEST_F(SrtpSessionTest, TestGoodSetup) { - EXPECT_TRUE(s1_.SetSend(CS_AES_CM_128_HMAC_SHA1_80, kTestKey1, kTestKeyLen)); - EXPECT_TRUE(s2_.SetRecv(CS_AES_CM_128_HMAC_SHA1_80, kTestKey1, kTestKeyLen)); + EXPECT_TRUE(s1_.SetSend(rtc::SRTP_AES128_CM_SHA1_80, kTestKey1, kTestKeyLen)); + EXPECT_TRUE(s2_.SetRecv(rtc::SRTP_AES128_CM_SHA1_80, kTestKey1, kTestKeyLen)); } // Test that we can't change the keys once set. TEST_F(SrtpSessionTest, TestBadSetup) { - EXPECT_TRUE(s1_.SetSend(CS_AES_CM_128_HMAC_SHA1_80, kTestKey1, kTestKeyLen)); - EXPECT_TRUE(s2_.SetRecv(CS_AES_CM_128_HMAC_SHA1_80, kTestKey1, kTestKeyLen)); - EXPECT_FALSE(s1_.SetSend(CS_AES_CM_128_HMAC_SHA1_80, kTestKey2, kTestKeyLen)); - EXPECT_FALSE(s2_.SetRecv(CS_AES_CM_128_HMAC_SHA1_80, kTestKey2, kTestKeyLen)); + EXPECT_TRUE(s1_.SetSend(rtc::SRTP_AES128_CM_SHA1_80, kTestKey1, kTestKeyLen)); + EXPECT_TRUE(s2_.SetRecv(rtc::SRTP_AES128_CM_SHA1_80, kTestKey1, kTestKeyLen)); + EXPECT_FALSE( + s1_.SetSend(rtc::SRTP_AES128_CM_SHA1_80, kTestKey2, kTestKeyLen)); + EXPECT_FALSE( + s2_.SetRecv(rtc::SRTP_AES128_CM_SHA1_80, kTestKey2, kTestKeyLen)); } // Test that we fail keys of the wrong length. TEST_F(SrtpSessionTest, TestKeysTooShort) { - EXPECT_FALSE(s1_.SetSend(CS_AES_CM_128_HMAC_SHA1_80, kTestKey1, 1)); - EXPECT_FALSE(s2_.SetRecv(CS_AES_CM_128_HMAC_SHA1_80, kTestKey1, 1)); + EXPECT_FALSE(s1_.SetSend(rtc::SRTP_AES128_CM_SHA1_80, kTestKey1, 1)); + EXPECT_FALSE(s2_.SetRecv(rtc::SRTP_AES128_CM_SHA1_80, kTestKey1, 1)); } // Test that we can encrypt and decrypt RTP/RTCP using AES_CM_128_HMAC_SHA1_80. TEST_F(SrtpSessionTest, TestProtect_AES_CM_128_HMAC_SHA1_80) { - EXPECT_TRUE(s1_.SetSend(CS_AES_CM_128_HMAC_SHA1_80, kTestKey1, kTestKeyLen)); - EXPECT_TRUE(s2_.SetRecv(CS_AES_CM_128_HMAC_SHA1_80, kTestKey1, kTestKeyLen)); + EXPECT_TRUE(s1_.SetSend(rtc::SRTP_AES128_CM_SHA1_80, kTestKey1, kTestKeyLen)); + EXPECT_TRUE(s2_.SetRecv(rtc::SRTP_AES128_CM_SHA1_80, kTestKey1, kTestKeyLen)); TestProtectRtp(CS_AES_CM_128_HMAC_SHA1_80); TestProtectRtcp(CS_AES_CM_128_HMAC_SHA1_80); TestUnprotectRtp(CS_AES_CM_128_HMAC_SHA1_80); @@ -659,8 +649,8 @@ TEST_F(SrtpSessionTest, TestProtect_AES_CM_128_HMAC_SHA1_80) { // Test that we can encrypt and decrypt RTP/RTCP using AES_CM_128_HMAC_SHA1_32. TEST_F(SrtpSessionTest, TestProtect_AES_CM_128_HMAC_SHA1_32) { - EXPECT_TRUE(s1_.SetSend(CS_AES_CM_128_HMAC_SHA1_32, kTestKey1, kTestKeyLen)); - EXPECT_TRUE(s2_.SetRecv(CS_AES_CM_128_HMAC_SHA1_32, kTestKey1, kTestKeyLen)); + EXPECT_TRUE(s1_.SetSend(rtc::SRTP_AES128_CM_SHA1_32, kTestKey1, kTestKeyLen)); + EXPECT_TRUE(s2_.SetRecv(rtc::SRTP_AES128_CM_SHA1_32, kTestKey1, kTestKeyLen)); TestProtectRtp(CS_AES_CM_128_HMAC_SHA1_32); TestProtectRtcp(CS_AES_CM_128_HMAC_SHA1_32); TestUnprotectRtp(CS_AES_CM_128_HMAC_SHA1_32); @@ -668,7 +658,7 @@ TEST_F(SrtpSessionTest, TestProtect_AES_CM_128_HMAC_SHA1_32) { } TEST_F(SrtpSessionTest, TestGetSendStreamPacketIndex) { - EXPECT_TRUE(s1_.SetSend(CS_AES_CM_128_HMAC_SHA1_32, kTestKey1, kTestKeyLen)); + EXPECT_TRUE(s1_.SetSend(rtc::SRTP_AES128_CM_SHA1_32, kTestKey1, kTestKeyLen)); int64_t index; int out_len = 0; EXPECT_TRUE(s1_.ProtectRtp(rtp_packet_, rtp_len_, @@ -681,8 +671,8 @@ TEST_F(SrtpSessionTest, TestGetSendStreamPacketIndex) { // Test that we fail to unprotect if someone tampers with the RTP/RTCP paylaods. TEST_F(SrtpSessionTest, TestTamperReject) { int out_len; - EXPECT_TRUE(s1_.SetSend(CS_AES_CM_128_HMAC_SHA1_80, kTestKey1, kTestKeyLen)); - EXPECT_TRUE(s2_.SetRecv(CS_AES_CM_128_HMAC_SHA1_80, kTestKey1, kTestKeyLen)); + EXPECT_TRUE(s1_.SetSend(rtc::SRTP_AES128_CM_SHA1_80, kTestKey1, kTestKeyLen)); + EXPECT_TRUE(s2_.SetRecv(rtc::SRTP_AES128_CM_SHA1_80, kTestKey1, kTestKeyLen)); TestProtectRtp(CS_AES_CM_128_HMAC_SHA1_80); TestProtectRtcp(CS_AES_CM_128_HMAC_SHA1_80); rtp_packet_[0] = 0x12; @@ -694,8 +684,8 @@ TEST_F(SrtpSessionTest, TestTamperReject) { // Test that we fail to unprotect if the payloads are not authenticated. TEST_F(SrtpSessionTest, TestUnencryptReject) { int out_len; - EXPECT_TRUE(s1_.SetSend(CS_AES_CM_128_HMAC_SHA1_80, kTestKey1, kTestKeyLen)); - EXPECT_TRUE(s2_.SetRecv(CS_AES_CM_128_HMAC_SHA1_80, kTestKey1, kTestKeyLen)); + EXPECT_TRUE(s1_.SetSend(rtc::SRTP_AES128_CM_SHA1_80, kTestKey1, kTestKeyLen)); + EXPECT_TRUE(s2_.SetRecv(rtc::SRTP_AES128_CM_SHA1_80, kTestKey1, kTestKeyLen)); EXPECT_FALSE(s2_.UnprotectRtp(rtp_packet_, rtp_len_, &out_len)); EXPECT_FALSE(s2_.UnprotectRtcp(rtcp_packet_, rtcp_len_, &out_len)); } @@ -703,7 +693,7 @@ TEST_F(SrtpSessionTest, TestUnencryptReject) { // Test that we fail when using buffers that are too small. TEST_F(SrtpSessionTest, TestBuffersTooSmall) { int out_len; - EXPECT_TRUE(s1_.SetSend(CS_AES_CM_128_HMAC_SHA1_80, kTestKey1, kTestKeyLen)); + EXPECT_TRUE(s1_.SetSend(rtc::SRTP_AES128_CM_SHA1_80, kTestKey1, kTestKeyLen)); EXPECT_FALSE(s1_.ProtectRtp(rtp_packet_, rtp_len_, sizeof(rtp_packet_) - 10, &out_len)); EXPECT_FALSE(s1_.ProtectRtcp(rtcp_packet_, rtcp_len_, @@ -717,8 +707,8 @@ TEST_F(SrtpSessionTest, TestReplay) { static const uint16_t replay_window = 1024; int out_len; - EXPECT_TRUE(s1_.SetSend(CS_AES_CM_128_HMAC_SHA1_80, kTestKey1, kTestKeyLen)); - EXPECT_TRUE(s2_.SetRecv(CS_AES_CM_128_HMAC_SHA1_80, kTestKey1, kTestKeyLen)); + EXPECT_TRUE(s1_.SetSend(rtc::SRTP_AES128_CM_SHA1_80, kTestKey1, kTestKeyLen)); + EXPECT_TRUE(s2_.SetRecv(rtc::SRTP_AES128_CM_SHA1_80, kTestKey1, kTestKeyLen)); // Initial sequence number. rtc::SetBE16(reinterpret_cast<uint8_t*>(rtp_packet_) + 2, seqnum_big); |