Introduce RtpTransportInternal and SrtpTransport.

SrtpTransport currently just delegates everything to RtpTransport.
Also makes BaseChannel::rtp_transport_ an RtpTransportInternal and constructs an SrtpTransport if srtp is required.

BUG=webrtc:7013

Review-Url: https://codereview.webrtc.org/2981013002
Cr-Commit-Position: refs/heads/master@{#19095}
This commit is contained in:
zstein 2017-07-19 13:38:02 -07:00 committed by Commit Bot
parent f6a861ab6c
commit 398c3fd6c2
11 changed files with 389 additions and 51 deletions

View File

@ -48,10 +48,13 @@ rtc_static_library("rtc_pc_base") {
"rtcpmuxfilter.h",
"rtptransport.cc",
"rtptransport.h",
"rtptransportinternal.h",
"srtpfilter.cc",
"srtpfilter.h",
"srtpsession.cc",
"srtpsession.h",
"srtptransport.cc",
"srtptransport.h",
"voicechannel.h",
]
@ -258,9 +261,11 @@ if (rtc_include_tests) {
"mediasession_unittest.cc",
"rtcpmuxfilter_unittest.cc",
"rtptransport_unittest.cc",
"rtptransporttestutil.h",
"srtpfilter_unittest.cc",
"srtpsession_unittest.cc",
"srtptestutil.h",
"srtptransport_unittest.cc",
]
include_dirs = [ "//third_party/libsrtp/srtp" ]
@ -289,6 +294,7 @@ if (rtc_include_tests) {
"../rtc_base:rtc_base_tests_main",
"../rtc_base:rtc_base_tests_utils",
"../system_wrappers:metrics_default",
"../test:test_support",
]
if (rtc_build_libsrtp) {

View File

@ -31,6 +31,8 @@
#include "webrtc/media/engine/webrtcvoiceengine.h" // nogncheck
#include "webrtc/p2p/base/packettransportinternal.h"
#include "webrtc/pc/channelmanager.h"
#include "webrtc/pc/rtptransport.h"
#include "webrtc/pc/srtptransport.h"
namespace cricket {
using rtc::Bind;
@ -156,7 +158,11 @@ BaseChannel::BaseChannel(rtc::Thread* worker_thread,
signaling_thread_(signaling_thread),
content_name_(content_name),
rtcp_mux_required_(rtcp_mux_required),
rtp_transport_(rtc::MakeUnique<webrtc::RtpTransport>(rtcp_mux_required)),
rtp_transport_(
srtp_required
? rtc::WrapUnique<webrtc::RtpTransportInternal>(
new webrtc::SrtpTransport(rtcp_mux_required, content_name))
: rtc::MakeUnique<webrtc::RtpTransport>(rtcp_mux_required)),
srtp_required_(srtp_required),
media_channel_(media_channel),
selected_candidate_pair_(nullptr) {
@ -170,7 +176,7 @@ BaseChannel::BaseChannel(rtc::Thread* worker_thread,
// with a callback interface later so that the demuxer can select which
// channel to signal.
rtp_transport_->SignalPacketReceived.connect(this,
&BaseChannel::OnPacketReceived);
&BaseChannel::OnPacketReceived);
LOG(LS_INFO) << "Created channel for " << content_name;
}

View File

@ -33,7 +33,7 @@
#include "webrtc/pc/mediamonitor.h"
#include "webrtc/pc/mediasession.h"
#include "webrtc/pc/rtcpmuxfilter.h"
#include "webrtc/pc/rtptransport.h"
#include "webrtc/pc/rtptransportinternal.h"
#include "webrtc/pc/srtpfilter.h"
#include "webrtc/rtc_base/asyncinvoker.h"
#include "webrtc/rtc_base/asyncudpsocket.h"
@ -397,7 +397,7 @@ class BaseChannel
// If non-null, "X_dtls_transport_" will always equal "X_packet_transport_".
DtlsTransportInternal* rtp_dtls_transport_ = nullptr;
DtlsTransportInternal* rtcp_dtls_transport_ = nullptr;
std::unique_ptr<webrtc::RtpTransport> rtp_transport_;
std::unique_ptr<webrtc::RtpTransportInternal> rtp_transport_;
std::vector<std::pair<rtc::Socket::Option, int> > socket_options_;
std::vector<std::pair<rtc::Socket::Option, int> > rtcp_socket_options_;
SrtpFilter srtp_filter_;

View File

@ -77,7 +77,7 @@ bool RtpTransport::IsWritable(bool rtcp) const {
}
bool RtpTransport::SendPacket(bool rtcp,
const rtc::CopyOnWriteBuffer* packet,
rtc::CopyOnWriteBuffer* packet,
const rtc::PacketOptions& options,
int flags) {
rtc::PacketTransportInternal* transport = rtcp && !rtcp_mux_enabled_

View File

@ -11,8 +11,8 @@
#ifndef WEBRTC_PC_RTPTRANSPORT_H_
#define WEBRTC_PC_RTPTRANSPORT_H_
#include "webrtc/api/ortc/rtptransportinterface.h"
#include "webrtc/pc/bundlefilter.h"
#include "webrtc/pc/rtptransportinternal.h"
#include "webrtc/rtc_base/sigslot.h"
namespace rtc {
@ -26,7 +26,7 @@ class PacketTransportInternal;
namespace webrtc {
class RtpTransport : public RtpTransportInterface, public sigslot::has_slots<> {
class RtpTransport : public RtpTransportInternal {
public:
RtpTransport(const RtpTransport&) = delete;
RtpTransport& operator=(const RtpTransport&) = delete;
@ -35,17 +35,17 @@ class RtpTransport : public RtpTransportInterface, public sigslot::has_slots<> {
: rtcp_mux_enabled_(rtcp_mux_enabled) {}
bool rtcp_mux_enabled() const { return rtcp_mux_enabled_; }
void SetRtcpMuxEnabled(bool enable);
void SetRtcpMuxEnabled(bool enable) override;
rtc::PacketTransportInternal* rtp_packet_transport() const {
rtc::PacketTransportInternal* rtp_packet_transport() const override {
return rtp_packet_transport_;
}
void SetRtpPacketTransport(rtc::PacketTransportInternal* rtp);
void SetRtpPacketTransport(rtc::PacketTransportInternal* rtp) override;
rtc::PacketTransportInternal* rtcp_packet_transport() const {
rtc::PacketTransportInternal* rtcp_packet_transport() const override {
return rtcp_packet_transport_;
}
void SetRtcpPacketTransport(rtc::PacketTransportInternal* rtcp);
void SetRtcpPacketTransport(rtc::PacketTransportInternal* rtcp) override;
PacketTransportInterface* GetRtpPacketTransport() const override;
PacketTransportInterface* GetRtcpPacketTransport() const override;
@ -54,27 +54,16 @@ class RtpTransport : public RtpTransportInterface, public sigslot::has_slots<> {
RTCError SetRtcpParameters(const RtcpParameters& parameters) override;
RtcpParameters GetRtcpParameters() const override;
// Called whenever a transport's ready-to-send state changes. The argument
// is true if all used transports are ready to send. This is more specific
// than just "writable"; it means the last send didn't return ENOTCONN.
sigslot::signal1<bool> SignalReadyToSend;
bool IsWritable(bool rtcp) const;
bool IsWritable(bool rtcp) const override;
bool SendPacket(bool rtcp,
const rtc::CopyOnWriteBuffer* packet,
rtc::CopyOnWriteBuffer* packet,
const rtc::PacketOptions& options,
int flags);
int flags) override;
bool HandlesPayloadType(int payload_type) const;
bool HandlesPayloadType(int payload_type) const override;
void AddHandledPayloadType(int payload_type);
// TODO(zstein): Consider having two signals - RtcPacketReceived and
// RtcpPacketReceived.
// The first argument is true for RTCP packets and false for RTP packets.
sigslot::signal3<bool, rtc::CopyOnWriteBuffer*, const rtc::PacketTime&>
SignalPacketReceived;
void AddHandledPayloadType(int payload_type) override;
protected:
// TODO(zstein): Remove this when we remove RtpTransportAdapter.

View File

@ -12,6 +12,7 @@
#include "webrtc/p2p/base/fakepackettransport.h"
#include "webrtc/pc/rtptransport.h"
#include "webrtc/pc/rtptransporttestutil.h"
#include "webrtc/rtc_base/gunit.h"
namespace webrtc {
@ -151,29 +152,6 @@ TEST(RtpTransportTest, ChangingReadyToSendStateOnlySignalsWhenChanged) {
EXPECT_EQ(observer.count(), 2);
}
class SignalPacketReceivedCounter : public sigslot::has_slots<> {
public:
explicit SignalPacketReceivedCounter(RtpTransport* transport) {
transport->SignalPacketReceived.connect(
this, &SignalPacketReceivedCounter::OnPacketReceived);
}
int rtcp_count() const { return rtcp_count_; }
int rtp_count() const { return rtp_count_; }
private:
void OnPacketReceived(bool rtcp,
rtc::CopyOnWriteBuffer*,
const rtc::PacketTime&) {
if (rtcp) {
++rtcp_count_;
} else {
++rtp_count_;
}
}
int rtcp_count_ = 0;
int rtp_count_ = 0;
};
// Test that SignalPacketReceived fires with rtcp=true when a RTCP packet is
// received.
TEST(RtpTransportTest, SignalDemuxedRtcp) {

View File

@ -0,0 +1,69 @@
/*
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_PC_RTPTRANSPORTINTERNAL_H_
#define WEBRTC_PC_RTPTRANSPORTINTERNAL_H_
#include "webrtc/api/ortc/rtptransportinterface.h"
#include "webrtc/rtc_base/sigslot.h"
namespace rtc {
class CopyOnWriteBuffer;
struct PacketOptions;
struct PacketTime;
} // namespace rtc
namespace webrtc {
// This represents the internal interface beneath RtpTransportInterface;
// it is not accessible to API consumers but is accessible to internal classes
// in order to send and receive RTP and RTCP packets belonging to a single RTP
// session. Additional convenience and configuration methods are also provided.
class RtpTransportInternal : public RtpTransportInterface,
public sigslot::has_slots<> {
public:
virtual void SetRtcpMuxEnabled(bool enable) = 0;
// TODO(zstein): Remove PacketTransport setters. Clients should pass these
// in to constructors instead and construct a new RtpTransportInternal instead
// of updating them.
virtual rtc::PacketTransportInternal* rtp_packet_transport() const = 0;
virtual void SetRtpPacketTransport(rtc::PacketTransportInternal* rtp) = 0;
virtual rtc::PacketTransportInternal* rtcp_packet_transport() const = 0;
virtual void SetRtcpPacketTransport(rtc::PacketTransportInternal* rtcp) = 0;
// Called whenever a transport's ready-to-send state changes. The argument
// is true if all used transports are ready to send. This is more specific
// than just "writable"; it means the last send didn't return ENOTCONN.
sigslot::signal1<bool> SignalReadyToSend;
// TODO(zstein): Consider having two signals - RtpPacketReceived and
// RtcpPacketReceived.
// The first argument is true for RTCP packets and false for RTP packets.
sigslot::signal3<bool, rtc::CopyOnWriteBuffer*, const rtc::PacketTime&>
SignalPacketReceived;
virtual bool IsWritable(bool rtcp) const = 0;
virtual bool SendPacket(bool rtcp,
rtc::CopyOnWriteBuffer* packet,
const rtc::PacketOptions& options,
int flags) = 0;
virtual bool HandlesPayloadType(int payload_type) const = 0;
virtual void AddHandledPayloadType(int payload_type) = 0;
};
} // namespace webrtc
#endif // WEBRTC_PC_RTPTRANSPORTINTERNAL_H_

View File

@ -0,0 +1,44 @@
/*
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_PC_RTPTRANSPORTTESTUTIL_H_
#define WEBRTC_PC_RTPTRANSPORTTESTUTIL_H_
#include "webrtc/pc/rtptransportinternal.h"
#include "webrtc/rtc_base/sigslot.h"
namespace webrtc {
class SignalPacketReceivedCounter : public sigslot::has_slots<> {
public:
explicit SignalPacketReceivedCounter(RtpTransportInternal* transport) {
transport->SignalPacketReceived.connect(
this, &SignalPacketReceivedCounter::OnPacketReceived);
}
int rtcp_count() const { return rtcp_count_; }
int rtp_count() const { return rtp_count_; }
private:
void OnPacketReceived(bool rtcp,
rtc::CopyOnWriteBuffer*,
const rtc::PacketTime&) {
if (rtcp) {
++rtcp_count_;
} else {
++rtp_count_;
}
}
int rtcp_count_ = 0;
int rtp_count_ = 0;
};
} // namespace webrtc
#endif // WEBRTC_PC_RTPTRANSPORTTESTUTIL_H_

View File

@ -0,0 +1,62 @@
/*
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/pc/srtptransport.h"
#include <string>
#include "webrtc/media/base/rtputils.h"
#include "webrtc/pc/rtptransport.h"
#include "webrtc/pc/srtpsession.h"
#include "webrtc/rtc_base/asyncpacketsocket.h"
#include "webrtc/rtc_base/copyonwritebuffer.h"
#include "webrtc/rtc_base/ptr_util.h"
#include "webrtc/rtc_base/trace_event.h"
namespace webrtc {
SrtpTransport::SrtpTransport(bool rtcp_mux_enabled,
const std::string& content_name)
: content_name_(content_name),
rtp_transport_(rtc::MakeUnique<RtpTransport>(rtcp_mux_enabled)) {
ConnectToRtpTransport();
}
SrtpTransport::SrtpTransport(std::unique_ptr<RtpTransportInternal> transport,
const std::string& content_name)
: content_name_(content_name), rtp_transport_(std::move(transport)) {
ConnectToRtpTransport();
}
void SrtpTransport::ConnectToRtpTransport() {
rtp_transport_->SignalPacketReceived.connect(
this, &SrtpTransport::OnPacketReceived);
rtp_transport_->SignalReadyToSend.connect(this,
&SrtpTransport::OnReadyToSend);
}
bool SrtpTransport::SendPacket(bool rtcp,
rtc::CopyOnWriteBuffer* packet,
const rtc::PacketOptions& options,
int flags) {
// TODO(zstein): Protect packet.
return rtp_transport_->SendPacket(rtcp, packet, options, flags);
}
void SrtpTransport::OnPacketReceived(bool rtcp,
rtc::CopyOnWriteBuffer* packet,
const rtc::PacketTime& packet_time) {
// TODO(zstein): Unprotect packet.
SignalPacketReceived(rtcp, packet, packet_time);
}
} // namespace webrtc

108
webrtc/pc/srtptransport.h Normal file
View File

@ -0,0 +1,108 @@
/*
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_PC_SRTPTRANSPORT_H_
#define WEBRTC_PC_SRTPTRANSPORT_H_
#include <memory>
#include <string>
#include <utility>
#include "webrtc/pc/rtptransportinternal.h"
#include "webrtc/pc/srtpfilter.h"
#include "webrtc/rtc_base/checks.h"
namespace webrtc {
// This class will eventually be a wrapper around RtpTransportInternal
// that protects and unprotects sent and received RTP packets. This
// functionality is currently implemented by SrtpFilter and BaseChannel, but
// will be moved here in the future.
class SrtpTransport : public RtpTransportInternal {
public:
SrtpTransport(bool rtcp_mux_enabled, const std::string& content_name);
// TODO(zstein): Consider taking an RtpTransport instead of an
// RtpTransportInternal.
SrtpTransport(std::unique_ptr<RtpTransportInternal> transport,
const std::string& content_name);
void SetRtcpMuxEnabled(bool enable) override {
rtp_transport_->SetRtcpMuxEnabled(enable);
}
rtc::PacketTransportInternal* rtp_packet_transport() const override {
return rtp_transport_->rtp_packet_transport();
}
void SetRtpPacketTransport(rtc::PacketTransportInternal* rtp) override {
rtp_transport_->SetRtpPacketTransport(rtp);
}
PacketTransportInterface* GetRtpPacketTransport() const override {
return rtp_transport_->GetRtpPacketTransport();
}
rtc::PacketTransportInternal* rtcp_packet_transport() const override {
return rtp_transport_->rtcp_packet_transport();
}
void SetRtcpPacketTransport(rtc::PacketTransportInternal* rtcp) override {
rtp_transport_->SetRtcpPacketTransport(rtcp);
}
PacketTransportInterface* GetRtcpPacketTransport() const override {
return rtp_transport_->GetRtcpPacketTransport();
}
bool IsWritable(bool rtcp) const override {
return rtp_transport_->IsWritable(rtcp);
}
bool SendPacket(bool rtcp,
rtc::CopyOnWriteBuffer* packet,
const rtc::PacketOptions& options,
int flags) override;
bool HandlesPayloadType(int payload_type) const override {
return rtp_transport_->HandlesPayloadType(payload_type);
}
void AddHandledPayloadType(int payload_type) override {
rtp_transport_->AddHandledPayloadType(payload_type);
}
RtcpParameters GetRtcpParameters() const override {
return rtp_transport_->GetRtcpParameters();
}
RTCError SetRtcpParameters(const RtcpParameters& parameters) override {
return rtp_transport_->SetRtcpParameters(parameters);
}
// TODO(zstein): Remove this when we remove RtpTransportAdapter.
RtpTransportAdapter* GetInternal() override { return nullptr; }
private:
void ConnectToRtpTransport();
void OnPacketReceived(bool rtcp,
rtc::CopyOnWriteBuffer* packet,
const rtc::PacketTime& packet_time);
void OnReadyToSend(bool ready) { SignalReadyToSend(ready); }
const std::string content_name_;
std::unique_ptr<RtpTransportInternal> rtp_transport_;
};
} // namespace webrtc
#endif // WEBRTC_PC_SRTPTRANSPORT_H_

View File

@ -0,0 +1,76 @@
/*
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/pc/srtptransport.h"
#include "webrtc/pc/rtptransport.h"
#include "webrtc/pc/rtptransporttestutil.h"
#include "webrtc/rtc_base/asyncpacketsocket.h"
#include "webrtc/rtc_base/gunit.h"
#include "webrtc/rtc_base/ptr_util.h"
#include "webrtc/test/gmock.h"
namespace webrtc {
using testing::_;
using testing::Return;
class MockRtpTransport : public RtpTransport {
public:
MockRtpTransport() : RtpTransport(true) {}
MOCK_METHOD4(SendPacket,
bool(bool rtcp,
rtc::CopyOnWriteBuffer* packet,
const rtc::PacketOptions& options,
int flags));
void PretendReceivedPacket() {
bool rtcp = false;
rtc::CopyOnWriteBuffer buffer;
rtc::PacketTime time;
SignalPacketReceived(rtcp, &buffer, time);
}
};
TEST(SrtpTransportTest, SendPacket) {
auto rtp_transport = rtc::MakeUnique<MockRtpTransport>();
EXPECT_CALL(*rtp_transport, SendPacket(_, _, _, _)).WillOnce(Return(true));
SrtpTransport srtp_transport(std::move(rtp_transport), "a");
const bool rtcp = false;
rtc::CopyOnWriteBuffer packet;
rtc::PacketOptions options;
int flags = 0;
EXPECT_TRUE(srtp_transport.SendPacket(rtcp, &packet, options, flags));
// TODO(zstein): Also verify that the packet received by RtpTransport has been
// protected once SrtpTransport handles that.
}
// Test that SrtpTransport fires SignalPacketReceived when the underlying
// RtpTransport fires SignalPacketReceived.
TEST(SrtpTransportTest, SignalPacketReceived) {
auto rtp_transport = rtc::MakeUnique<MockRtpTransport>();
MockRtpTransport* rtp_transport_raw = rtp_transport.get();
SrtpTransport srtp_transport(std::move(rtp_transport), "a");
SignalPacketReceivedCounter counter(&srtp_transport);
rtp_transport_raw->PretendReceivedPacket();
EXPECT_EQ(1, counter.rtp_count());
// TODO(zstein): Also verify that the packet is unprotected once SrtpTransport
// handles that.
}
} // namespace webrtc