Add DTLSTransport info into sender/receiver state.

This is in preparation for letting Chrome extract DTLSTransport
information after SLD/SRD instead of doing it on-demand.

Bug: chromium:907849
Change-Id: Iac6b174c98d3d14136e1fd25bce4a9292f6c8b41
Reviewed-on: https://webrtc-review.googlesource.com/c/116984
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Björn Terelius <terelius@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Fredrik Solenberg <solenberg@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26289}
This commit is contained in:
Harald Alvestrand 2019-01-17 10:39:40 +01:00 committed by Commit Bot
parent ad8719442b
commit 4a7b3acfcf
17 changed files with 203 additions and 19 deletions

View file

@ -23,7 +23,9 @@ enum class DtlsTransportState {
kConnecting, // In the process of negotiating a secure connection.
kConnected, // Completed negotiation and verified fingerprints.
kClosed, // Intentionally closed.
kFailed // Failure due to an error or failing to verify a remote fingerprint.
kFailed, // Failure due to an error or failing to verify a remote
// fingerprint.
kNumValues
};
// This object gives snapshot information about the changeable state of a

View file

@ -53,4 +53,9 @@ RtpReceiverInterface::GetFrameDecryptor() const {
return nullptr;
}
rtc::scoped_refptr<DtlsTransportInterface>
RtpReceiverInterface::dtls_transport() const {
return nullptr;
}
} // namespace webrtc

View file

@ -18,6 +18,7 @@
#include <vector>
#include "api/crypto/frame_decryptor_interface.h"
#include "api/dtls_transport_interface.h"
#include "api/media_stream_interface.h"
#include "api/media_types.h"
#include "api/proxy.h"
@ -92,6 +93,13 @@ class RtpReceiverObserverInterface {
class RtpReceiverInterface : public rtc::RefCountInterface {
public:
virtual rtc::scoped_refptr<MediaStreamTrackInterface> track() const = 0;
// The dtlsTransport attribute exposes the DTLS transport on which the
// media is received. It may be null.
// https://w3c.github.io/webrtc-pc/#dom-rtcrtpreceiver-transport
// TODO(https://bugs.webrtc.org/907849) remove default implementation
virtual rtc::scoped_refptr<DtlsTransportInterface> dtls_transport() const;
// The list of streams that |track| is associated with. This is the same as
// the [[AssociatedRemoteMediaStreams]] internal slot in the spec.
// https://w3c.github.io/webrtc-pc/#dfn-associatedremotemediastreams
@ -146,6 +154,7 @@ class RtpReceiverInterface : public rtc::RefCountInterface {
BEGIN_SIGNALING_PROXY_MAP(RtpReceiver)
PROXY_SIGNALING_THREAD_DESTRUCTOR()
PROXY_CONSTMETHOD0(rtc::scoped_refptr<MediaStreamTrackInterface>, track)
PROXY_CONSTMETHOD0(rtc::scoped_refptr<DtlsTransportInterface>, dtls_transport)
PROXY_CONSTMETHOD0(std::vector<std::string>, stream_ids)
PROXY_CONSTMETHOD0(std::vector<rtc::scoped_refptr<MediaStreamInterface>>,
streams)

View file

@ -25,4 +25,9 @@ std::vector<RtpEncodingParameters> RtpSenderInterface::init_send_encodings()
return {};
}
rtc::scoped_refptr<DtlsTransportInterface> RtpSenderInterface::dtls_transport()
const {
return nullptr;
}
} // namespace webrtc

View file

@ -18,6 +18,7 @@
#include <vector>
#include "api/crypto/frame_encryptor_interface.h"
#include "api/dtls_transport_interface.h"
#include "api/dtmf_sender_interface.h"
#include "api/media_stream_interface.h"
#include "api/media_types.h"
@ -36,6 +37,12 @@ class RtpSenderInterface : public rtc::RefCountInterface {
virtual bool SetTrack(MediaStreamTrackInterface* track) = 0;
virtual rtc::scoped_refptr<MediaStreamTrackInterface> track() const = 0;
// The dtlsTransport attribute exposes the DTLS transport on which the
// media is sent. It may be null.
// https://w3c.github.io/webrtc-pc/#dom-rtcrtpsender-transport
// TODO(https://bugs.webrtc.org/907849) remove default implementation
virtual rtc::scoped_refptr<DtlsTransportInterface> dtls_transport() const;
// Returns primary SSRC used by this sender for sending media.
// Returns 0 if not yet determined.
// TODO(deadbeef): Change to absl::optional.
@ -91,6 +98,7 @@ BEGIN_SIGNALING_PROXY_MAP(RtpSender)
PROXY_SIGNALING_THREAD_DESTRUCTOR()
PROXY_METHOD1(bool, SetTrack, MediaStreamTrackInterface*)
PROXY_CONSTMETHOD0(rtc::scoped_refptr<MediaStreamTrackInterface>, track)
PROXY_CONSTMETHOD0(rtc::scoped_refptr<DtlsTransportInterface>, dtls_transport)
PROXY_CONSTMETHOD0(uint32_t, ssrc)
PROXY_CONSTMETHOD0(cricket::MediaType, media_type)
PROXY_CONSTMETHOD0(std::string, id)

View file

@ -421,6 +421,7 @@ rtc_source_set("ice_log") {
deps = [
":rtc_event_log_api",
"../api:libjingle_logging_api",
"../api:libjingle_peerconnection_api",
"../rtc_base:rtc_base_approved",
"//third_party/abseil-cpp/absl/memory",
]

View file

@ -13,19 +13,11 @@
#include <memory>
#include "api/dtls_transport_interface.h"
#include "logging/rtc_event_log/events/rtc_event.h"
namespace webrtc {
enum class DtlsTransportState {
kNew,
kConnecting,
kConnected,
kClosed,
kFailed,
kNumValues
};
class RtcEventDtlsTransportState : public RtcEvent {
public:
explicit RtcEventDtlsTransportState(DtlsTransportState state);

View file

@ -189,7 +189,7 @@ class JsepTransport : public sigslot::has_slots<>,
}
}
rtc::scoped_refptr<webrtc::DtlsTransportInterface> RtpDtlsTransport() {
rtc::scoped_refptr<webrtc::DtlsTransport> RtpDtlsTransport() {
return rtp_dtls_transport_;
}

View file

@ -173,7 +173,7 @@ JsepTransportController::GetRtcpDtlsTransport(const std::string& mid) const {
return jsep_transport->rtcp_dtls_transport();
}
rtc::scoped_refptr<webrtc::DtlsTransportInterface>
rtc::scoped_refptr<webrtc::DtlsTransport>
JsepTransportController::LookupDtlsTransportByMid(const std::string& mid) {
auto jsep_transport = GetJsepTransportForMid(mid);
if (!jsep_transport) {

View file

@ -117,7 +117,7 @@ class JsepTransportController : public sigslot::has_slots<> {
const cricket::DtlsTransportInternal* GetRtcpDtlsTransport(
const std::string& mid) const;
// Gets the externally sharable version of the DtlsTransport.
rtc::scoped_refptr<webrtc::DtlsTransportInterface> LookupDtlsTransportByMid(
rtc::scoped_refptr<webrtc::DtlsTransport> LookupDtlsTransportByMid(
const std::string& mid);
MediaTransportInterface* GetMediaTransport(const std::string& mid) const;

View file

@ -2106,6 +2106,18 @@ RTCError PeerConnection::ApplyLocalDescription(
std::vector<rtc::scoped_refptr<RtpTransceiverInterface>> remove_list;
std::vector<rtc::scoped_refptr<MediaStreamInterface>> removed_streams;
for (auto transceiver : transceivers_) {
// 2.2.7.1.1.(6-9): Set sender and receiver's transport slots.
// Note that code paths that don't set MID won't be able to use
// information about DTLS transports.
if (transceiver->mid()) {
auto dtls_transport =
LookupDtlsTransportByMidInternal(*transceiver->mid());
transceiver->internal()->sender_internal()->set_transport(
dtls_transport);
transceiver->internal()->receiver_internal()->set_transport(
dtls_transport);
}
const ContentInfo* content =
FindMediaSectionForTransceiver(transceiver, local_description());
if (!content) {
@ -2548,7 +2560,7 @@ RTCError PeerConnection::ApplyRemoteDescription(
now_receiving_transceivers.push_back(transceiver);
}
}
// 2.2.8.1.7: If direction is "sendonly" or "inactive", and transceiver's
// 2.2.8.1.9: If direction is "sendonly" or "inactive", and transceiver's
// [[FiredDirection]] slot is either "sendrecv" or "recvonly", process the
// removal of a remote track for the media description, given transceiver,
// removeList, and muteTracks.
@ -2558,16 +2570,25 @@ RTCError PeerConnection::ApplyRemoteDescription(
ProcessRemovalOfRemoteTrack(transceiver, &remove_list,
&removed_streams);
}
// 2.2.8.1.8: Set transceiver's [[FiredDirection]] slot to direction.
// 2.2.8.1.10: Set transceiver's [[FiredDirection]] slot to direction.
transceiver->internal()->set_fired_direction(local_direction);
// 2.2.8.1.9: If description is of type "answer" or "pranswer", then run
// 2.2.8.1.11: If description is of type "answer" or "pranswer", then run
// the following steps:
if (type == SdpType::kPrAnswer || type == SdpType::kAnswer) {
// 2.2.8.1.9.1: Set transceiver's [[CurrentDirection]] slot to
// 2.2.8.1.11.1: Set transceiver's [[CurrentDirection]] slot to
// direction.
transceiver->internal()->set_current_direction(local_direction);
// 2.2.8.1.11.[3-6]: Set the transport internal slots.
if (transceiver->mid()) {
auto dtls_transport =
LookupDtlsTransportByMidInternal(*transceiver->mid());
transceiver->internal()->sender_internal()->set_transport(
dtls_transport);
transceiver->internal()->receiver_internal()->set_transport(
dtls_transport);
}
}
// 2.2.8.1.10: If the media description is rejected, and transceiver is
// 2.2.8.1.12: If the media description is rejected, and transceiver is
// not already stopped, stop the RTCRtpTransceiver transceiver.
if (content->rejected && !transceiver->stopped()) {
RTC_LOG(LS_INFO) << "Stopping transceiver for MID=" << content->name
@ -3445,6 +3466,11 @@ PeerConnection::LookupDtlsTransportByMid(const std::string& mid) {
return transport_controller_->LookupDtlsTransportByMid(mid);
}
rtc::scoped_refptr<DtlsTransport>
PeerConnection::LookupDtlsTransportByMidInternal(const std::string& mid) {
return transport_controller_->LookupDtlsTransportByMid(mid);
}
const SessionDescriptionInterface* PeerConnection::local_description() const {
return pending_local_description_ ? pending_local_description_.get()
: current_local_description_.get();

View file

@ -197,6 +197,8 @@ class PeerConnection : public PeerConnectionInternal,
rtc::scoped_refptr<DtlsTransportInterface> LookupDtlsTransportByMid(
const std::string& mid) override;
rtc::scoped_refptr<DtlsTransport> LookupDtlsTransportByMidInternal(
const std::string& mid);
RTC_DEPRECATED bool StartRtcEventLog(rtc::PlatformFile file,
int64_t max_size_bytes) override;

View file

@ -108,6 +108,28 @@ class PeerConnectionSignalingBaseTest : public ::testing::Test {
return wrapper;
}
int NumberOfDtlsTransports(const WrapperPtr& pc_wrapper) {
std::set<DtlsTransportInterface*> transports;
auto transceivers = pc_wrapper->pc()->GetTransceivers();
for (auto& transceiver : transceivers) {
if (transceiver->sender()->dtls_transport()) {
EXPECT_TRUE(transceiver->receiver()->dtls_transport());
EXPECT_EQ(transceiver->sender()->dtls_transport().get(),
transceiver->receiver()->dtls_transport().get());
transports.insert(transceiver->sender()->dtls_transport().get());
} else {
// If one transceiver is missing, they all should be.
EXPECT_EQ(0UL, transports.size());
}
}
return transports.size();
}
bool HasDtlsTransport(const WrapperPtr& pc_wrapper) {
return NumberOfDtlsTransports(pc_wrapper) > 0;
}
std::unique_ptr<rtc::VirtualSocketServer> vss_;
rtc::AutoSocketServerThread main_;
rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_;
@ -505,4 +527,74 @@ INSTANTIATE_TEST_CASE_P(PeerConnectionSignalingTest,
Values(SdpSemantics::kPlanB,
SdpSemantics::kUnifiedPlan));
class PeerConnectionSignalingUnifiedPlanTest
: public PeerConnectionSignalingBaseTest {
protected:
PeerConnectionSignalingUnifiedPlanTest()
: PeerConnectionSignalingBaseTest(SdpSemantics::kUnifiedPlan) {}
};
// Test that transports are shown in the sender/receiver API after offer/answer.
// This only works in Unified Plan.
TEST_F(PeerConnectionSignalingUnifiedPlanTest,
DtlsTransportsInstantiateInOfferAnswer) {
auto caller = CreatePeerConnectionWithAudioVideo();
auto callee = CreatePeerConnection();
EXPECT_FALSE(HasDtlsTransport(caller));
EXPECT_FALSE(HasDtlsTransport(callee));
auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
caller->SetLocalDescription(CloneSessionDescription(offer.get()));
EXPECT_TRUE(HasDtlsTransport(caller));
callee->SetRemoteDescription(std::move(offer));
EXPECT_FALSE(HasDtlsTransport(callee));
auto answer = callee->CreateAnswer(RTCOfferAnswerOptions());
callee->SetLocalDescription(CloneSessionDescription(answer.get()));
EXPECT_TRUE(HasDtlsTransport(callee));
caller->SetRemoteDescription(std::move(answer));
EXPECT_TRUE(HasDtlsTransport(caller));
ASSERT_EQ(SignalingState::kStable, caller->signaling_state());
}
TEST_F(PeerConnectionSignalingUnifiedPlanTest, DtlsTransportsMergeWhenBundled) {
auto caller = CreatePeerConnectionWithAudioVideo();
auto callee = CreatePeerConnection();
EXPECT_FALSE(HasDtlsTransport(caller));
EXPECT_FALSE(HasDtlsTransport(callee));
auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
caller->SetLocalDescription(CloneSessionDescription(offer.get()));
EXPECT_EQ(2, NumberOfDtlsTransports(caller));
callee->SetRemoteDescription(std::move(offer));
auto answer = callee->CreateAnswer(RTCOfferAnswerOptions());
callee->SetLocalDescription(CloneSessionDescription(answer.get()));
caller->SetRemoteDescription(std::move(answer));
EXPECT_EQ(1, NumberOfDtlsTransports(caller));
ASSERT_EQ(SignalingState::kStable, caller->signaling_state());
}
TEST_F(PeerConnectionSignalingUnifiedPlanTest,
DtlsTransportsAreSeparateeWhenUnbundled) {
auto caller = CreatePeerConnectionWithAudioVideo();
auto callee = CreatePeerConnection();
EXPECT_FALSE(HasDtlsTransport(caller));
EXPECT_FALSE(HasDtlsTransport(callee));
RTCOfferAnswerOptions unbundle_options;
unbundle_options.use_rtp_mux = false;
auto offer = caller->CreateOffer(unbundle_options);
caller->SetLocalDescription(CloneSessionDescription(offer.get()));
EXPECT_EQ(2, NumberOfDtlsTransports(caller));
callee->SetRemoteDescription(std::move(offer));
auto answer = callee->CreateAnswer(RTCOfferAnswerOptions());
callee->SetLocalDescription(CloneSessionDescription(answer.get()));
EXPECT_EQ(2, NumberOfDtlsTransports(callee));
caller->SetRemoteDescription(std::move(answer));
EXPECT_EQ(2, NumberOfDtlsTransports(caller));
ASSERT_EQ(SignalingState::kStable, caller->signaling_state());
}
} // namespace webrtc

View file

@ -54,6 +54,8 @@ class RtpReceiverInternal : public RtpReceiverInterface {
// receive packets on unsignaled SSRCs.
virtual void SetupMediaChannel(uint32_t ssrc) = 0;
virtual void set_transport(
rtc::scoped_refptr<DtlsTransportInterface> dtls_transport) = 0;
// This SSRC is used as an identifier for the receiver between the API layer
// and the WebRtcVideoEngine, WebRtcVoiceEngine layer.
virtual uint32_t ssrc() const = 0;
@ -106,6 +108,9 @@ class AudioRtpReceiver : public ObserverInterface,
rtc::scoped_refptr<MediaStreamTrackInterface> track() const override {
return track_.get();
}
rtc::scoped_refptr<DtlsTransportInterface> dtls_transport() const override {
return dtls_transport_;
}
std::vector<std::string> stream_ids() const override;
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams()
const override {
@ -133,6 +138,10 @@ class AudioRtpReceiver : public ObserverInterface,
uint32_t ssrc() const override { return ssrc_.value_or(0); }
void NotifyFirstPacketReceived() override;
void set_stream_ids(std::vector<std::string> stream_ids) override;
void set_transport(
rtc::scoped_refptr<DtlsTransportInterface> dtls_transport) override {
dtls_transport_ = dtls_transport;
}
void SetStreams(const std::vector<rtc::scoped_refptr<MediaStreamInterface>>&
streams) override;
void SetObserver(RtpReceiverObserverInterface* observer) override;
@ -160,6 +169,7 @@ class AudioRtpReceiver : public ObserverInterface,
bool received_first_packet_ = false;
int attachment_id_ = 0;
rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor_;
rtc::scoped_refptr<DtlsTransportInterface> dtls_transport_;
};
class VideoRtpReceiver : public rtc::RefCountedObject<RtpReceiverInternal> {
@ -186,6 +196,9 @@ class VideoRtpReceiver : public rtc::RefCountedObject<RtpReceiverInternal> {
rtc::scoped_refptr<MediaStreamTrackInterface> track() const override {
return track_.get();
}
rtc::scoped_refptr<DtlsTransportInterface> dtls_transport() const override {
return dtls_transport_;
}
std::vector<std::string> stream_ids() const override;
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams()
const override {
@ -213,6 +226,10 @@ class VideoRtpReceiver : public rtc::RefCountedObject<RtpReceiverInternal> {
uint32_t ssrc() const override { return ssrc_.value_or(0); }
void NotifyFirstPacketReceived() override;
void set_stream_ids(std::vector<std::string> stream_ids) override;
void set_transport(
rtc::scoped_refptr<DtlsTransportInterface> dtls_transport) override {
dtls_transport_ = dtls_transport;
}
void SetStreams(const std::vector<rtc::scoped_refptr<MediaStreamInterface>>&
streams) override;
@ -257,6 +274,7 @@ class VideoRtpReceiver : public rtc::RefCountedObject<RtpReceiverInternal> {
bool received_first_packet_ = false;
int attachment_id_ = 0;
rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor_;
rtc::scoped_refptr<DtlsTransportInterface> dtls_transport_;
};
} // namespace webrtc

View file

@ -50,6 +50,8 @@ class RtpSenderInternal : public RtpSenderInterface {
virtual void set_stream_ids(const std::vector<std::string>& stream_ids) = 0;
virtual void set_init_send_encodings(
const std::vector<RtpEncodingParameters>& init_send_encodings) = 0;
virtual void set_transport(
rtc::scoped_refptr<DtlsTransportInterface> dtls_transport) = 0;
virtual void Stop() = 0;
@ -112,6 +114,10 @@ class AudioRtpSender : public DtmfProviderInterface,
return track_;
}
rtc::scoped_refptr<DtlsTransportInterface> dtls_transport() const override {
return dtls_transport_;
}
uint32_t ssrc() const override { return ssrc_; }
cricket::MediaType media_type() const override {
@ -147,7 +153,10 @@ class AudioRtpSender : public DtmfProviderInterface,
std::vector<RtpEncodingParameters> init_send_encodings() const override {
return init_parameters_.encodings;
}
void set_transport(
rtc::scoped_refptr<DtlsTransportInterface> dtls_transport) override {
dtls_transport_ = dtls_transport;
}
void Stop() override;
int AttachmentId() const override { return attachment_id_; }
@ -173,6 +182,7 @@ class AudioRtpSender : public DtmfProviderInterface,
cricket::VoiceMediaChannel* media_channel_ = nullptr;
StatsCollector* stats_ = nullptr;
rtc::scoped_refptr<AudioTrackInterface> track_;
rtc::scoped_refptr<DtlsTransportInterface> dtls_transport_;
rtc::scoped_refptr<DtmfSenderInterface> dtmf_sender_proxy_;
absl::optional<std::string> last_transaction_id_;
uint32_t ssrc_ = 0;
@ -205,6 +215,9 @@ class VideoRtpSender : public ObserverInterface,
}
uint32_t ssrc() const override { return ssrc_; }
rtc::scoped_refptr<DtlsTransportInterface> dtls_transport() const override {
return dtls_transport_;
}
cricket::MediaType media_type() const override {
return cricket::MEDIA_TYPE_VIDEO;
@ -221,6 +234,10 @@ class VideoRtpSender : public ObserverInterface,
std::vector<RtpEncodingParameters> init_send_encodings() const override {
return init_parameters_.encodings;
}
void set_transport(
rtc::scoped_refptr<DtlsTransportInterface> dtls_transport) override {
dtls_transport_ = dtls_transport;
}
RtpParameters GetParameters() override;
RTCError SetParameters(const RtpParameters& parameters) override;
@ -266,6 +283,7 @@ class VideoRtpSender : public ObserverInterface,
bool stopped_ = false;
int attachment_id_ = 0;
rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor_;
rtc::scoped_refptr<DtlsTransportInterface> dtls_transport_;
};
} // namespace webrtc

View file

@ -25,6 +25,8 @@ class MockRtpReceiverInternal : public RtpReceiverInternal {
// RtpReceiverInterface methods.
MOCK_METHOD1(SetTrack, void(MediaStreamTrackInterface*));
MOCK_CONST_METHOD0(track, rtc::scoped_refptr<MediaStreamTrackInterface>());
MOCK_CONST_METHOD0(dtls_transport,
rtc::scoped_refptr<DtlsTransportInterface>());
MOCK_CONST_METHOD0(stream_ids, std::vector<std::string>());
MOCK_CONST_METHOD0(streams,
std::vector<rtc::scoped_refptr<MediaStreamInterface>>());
@ -46,6 +48,7 @@ class MockRtpReceiverInternal : public RtpReceiverInternal {
MOCK_CONST_METHOD0(ssrc, uint32_t());
MOCK_METHOD0(NotifyFirstPacketReceived, void());
MOCK_METHOD1(set_stream_ids, void(std::vector<std::string>));
MOCK_METHOD1(set_transport, void(rtc::scoped_refptr<DtlsTransportInterface>));
MOCK_METHOD1(
SetStreams,
void(const std::vector<rtc::scoped_refptr<MediaStreamInterface>>&));

View file

@ -26,10 +26,13 @@ class MockRtpSenderInternal : public RtpSenderInternal {
MOCK_METHOD1(SetTrack, bool(MediaStreamTrackInterface*));
MOCK_CONST_METHOD0(track, rtc::scoped_refptr<MediaStreamTrackInterface>());
MOCK_CONST_METHOD0(ssrc, uint32_t());
MOCK_CONST_METHOD0(dtls_transport,
rtc::scoped_refptr<DtlsTransportInterface>());
MOCK_CONST_METHOD0(media_type, cricket::MediaType());
MOCK_CONST_METHOD0(id, std::string());
MOCK_CONST_METHOD0(stream_ids, std::vector<std::string>());
MOCK_CONST_METHOD0(init_send_encodings, std::vector<RtpEncodingParameters>());
MOCK_METHOD1(set_transport, void(rtc::scoped_refptr<DtlsTransportInterface>));
MOCK_METHOD0(GetParameters, RtpParameters());
MOCK_METHOD1(SetParameters, RTCError(const RtpParameters&));
MOCK_CONST_METHOD0(GetDtmfSender, rtc::scoped_refptr<DtmfSenderInterface>());