Replace BundleFilter with RtpDemuxer in RtpTransport.
BundleFilter is replaced by RtpDemuxer in RtpTransport for payload type-based demuxing. RtpTransport will support MID-based demuxing later. Each BaseChannel has its own RTP demuxing criteria and when connecting to the RtpTransport, BaseChannel will register itself as a demuxer sink. The inheritance model is changed. New inheritance chain: DtlsSrtpTransport->SrtpTransport->RtpTranpsort The JsepTransport2 is renamed to JsepTransport. NOTE: When RTCP packets are received, Call::DeliverRtcp will be called for multiple times (webrtc:9035) which is an existing issue. With this CL, it will become more of a problem and should be fixed. Bug: webrtc:8587 Change-Id: Ibd880e7b744bd912336a691309950bc18e42cf62 Reviewed-on: https://webrtc-review.googlesource.com/65786 Commit-Queue: Zhi Huang <zhihuang@webrtc.org> Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org> Reviewed-by: Benjamin Wright <benwright@webrtc.org> Cr-Commit-Position: refs/heads/master@{#22867}
This commit is contained in:
parent
c6416fbe16
commit
365381fdf1
@ -275,6 +275,16 @@ bool IsRtpPacket(const void* data, size_t len) {
|
||||
return (static_cast<const uint8_t*>(data)[0] >> 6) == kRtpVersion;
|
||||
}
|
||||
|
||||
// Check the RTP payload type. If 63 < payload type < 96, it's RTCP.
|
||||
// For additional details, see http://tools.ietf.org/html/rfc5761.
|
||||
bool IsRtcpPacket(const char* data, size_t len) {
|
||||
if (len < 2) {
|
||||
return false;
|
||||
}
|
||||
char pt = data[1] & 0x7F;
|
||||
return (63 < pt) && (pt < 96);
|
||||
}
|
||||
|
||||
bool IsValidRtpPayloadType(int payload_type) {
|
||||
return payload_type >= 0 && payload_type <= 127;
|
||||
}
|
||||
|
||||
@ -55,6 +55,7 @@ bool SetRtpHeader(void* data, size_t len, const RtpHeader& header);
|
||||
|
||||
bool IsRtpPacket(const void* data, size_t len);
|
||||
|
||||
bool IsRtcpPacket(const char* data, size_t len);
|
||||
// True if |payload type| is 0-127.
|
||||
bool IsValidRtpPayloadType(int payload_type);
|
||||
|
||||
|
||||
@ -171,8 +171,8 @@ RtpTransportAdapter::RtpTransportAdapter(
|
||||
|
||||
transport_->SignalReadyToSend.connect(this,
|
||||
&RtpTransportAdapter::OnReadyToSend);
|
||||
transport_->SignalPacketReceived.connect(
|
||||
this, &RtpTransportAdapter::OnPacketReceived);
|
||||
transport_->SignalRtcpPacketReceived.connect(
|
||||
this, &RtpTransportAdapter::OnRtcpPacketReceived);
|
||||
transport_->SignalWritableState.connect(
|
||||
this, &RtpTransportAdapter::OnWritableState);
|
||||
}
|
||||
|
||||
@ -14,13 +14,11 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "api/ortc/srtptransportinterface.h"
|
||||
#include "api/rtcerror.h"
|
||||
#include "media/base/streamparams.h"
|
||||
#include "ortc/rtptransportcontrolleradapter.h"
|
||||
#include "pc/channel.h"
|
||||
#include "pc/rtptransport.h"
|
||||
#include "pc/rtptransportinternal.h"
|
||||
#include "pc/rtptransportinternaladapter.h"
|
||||
#include "pc/srtptransport.h"
|
||||
#include "rtc_base/constructormagic.h"
|
||||
#include "rtc_base/sigslot.h"
|
||||
@ -82,8 +80,6 @@ class RtpTransportAdapter : public RtpTransportInternalAdapter {
|
||||
|
||||
bool IsSrtpActive() const override { return transport_->IsSrtpActive(); }
|
||||
|
||||
bool IsSrtpTransport() const { return srtp_transport_ != nullptr; }
|
||||
|
||||
protected:
|
||||
RtpTransportAdapter* GetInternal() override { return this; }
|
||||
|
||||
@ -96,10 +92,9 @@ class RtpTransportAdapter : public RtpTransportInternalAdapter {
|
||||
|
||||
void OnReadyToSend(bool ready) { SignalReadyToSend(ready); }
|
||||
|
||||
void OnPacketReceived(bool rtcp,
|
||||
rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketTime& time) {
|
||||
SignalPacketReceived(rtcp, packet, time);
|
||||
void OnRtcpPacketReceived(rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketTime& time) {
|
||||
SignalRtcpPacketReceived(packet, time);
|
||||
}
|
||||
|
||||
void OnWritableState(bool writable) { SignalWritableState(writable); }
|
||||
|
||||
@ -869,8 +869,6 @@ void RtpTransportControllerAdapter::CreateVoiceChannel() {
|
||||
cricket::AudioOptions());
|
||||
RTC_DCHECK(voice_channel_);
|
||||
voice_channel_->Enable(true);
|
||||
voice_channel_->DisableEncryption(
|
||||
!inner_audio_transport_->GetInternal()->IsSrtpTransport());
|
||||
}
|
||||
|
||||
void RtpTransportControllerAdapter::CreateVideoChannel() {
|
||||
@ -880,8 +878,6 @@ void RtpTransportControllerAdapter::CreateVideoChannel() {
|
||||
cricket::VideoOptions());
|
||||
RTC_DCHECK(video_channel_);
|
||||
video_channel_->Enable(true);
|
||||
video_channel_->DisableEncryption(
|
||||
!inner_video_transport_->GetInternal()->IsSrtpTransport());
|
||||
}
|
||||
|
||||
void RtpTransportControllerAdapter::DestroyVoiceChannel() {
|
||||
|
||||
14
pc/BUILD.gn
14
pc/BUILD.gn
@ -30,8 +30,6 @@ rtc_static_library("rtc_pc_base") {
|
||||
defines = []
|
||||
sources = [
|
||||
"audiomonitor.h",
|
||||
"bundlefilter.cc",
|
||||
"bundlefilter.h",
|
||||
"channel.cc",
|
||||
"channel.h",
|
||||
"channelmanager.cc",
|
||||
@ -42,8 +40,8 @@ rtc_static_library("rtc_pc_base") {
|
||||
"dtlssrtptransport.h",
|
||||
"externalhmac.cc",
|
||||
"externalhmac.h",
|
||||
"jseptransport2.cc",
|
||||
"jseptransport2.h",
|
||||
"jseptransport.cc",
|
||||
"jseptransport.h",
|
||||
"jseptransportcontroller.cc",
|
||||
"jseptransportcontroller.h",
|
||||
"mediasession.cc",
|
||||
@ -76,10 +74,13 @@ rtc_static_library("rtc_pc_base") {
|
||||
"../api:optional",
|
||||
"../api:ortc_api",
|
||||
"../api:video_frame_api",
|
||||
"../call:rtp_interfaces",
|
||||
"../call:rtp_receiver",
|
||||
"../common_video:common_video",
|
||||
"../media:rtc_data",
|
||||
"../media:rtc_h264_profile_id",
|
||||
"../media:rtc_media_base",
|
||||
"../modules/rtp_rtcp:rtp_rtcp_format",
|
||||
"../p2p:rtc_p2p",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base:rtc_base",
|
||||
@ -270,12 +271,11 @@ if (rtc_include_tests) {
|
||||
testonly = true
|
||||
|
||||
sources = [
|
||||
"bundlefilter_unittest.cc",
|
||||
"channel_unittest.cc",
|
||||
"channelmanager_unittest.cc",
|
||||
"currentspeakermonitor_unittest.cc",
|
||||
"dtlssrtptransport_unittest.cc",
|
||||
"jseptransport2_unittest.cc",
|
||||
"jseptransport_unittest.cc",
|
||||
"jseptransportcontroller_unittest.cc",
|
||||
"mediasession_unittest.cc",
|
||||
"rtcpmuxfilter_unittest.cc",
|
||||
@ -308,9 +308,11 @@ if (rtc_include_tests) {
|
||||
"../api:array_view",
|
||||
"../api:fakemetricsobserver",
|
||||
"../api:libjingle_peerconnection_api",
|
||||
"../call:rtp_interfaces",
|
||||
"../logging:rtc_event_log_api",
|
||||
"../media:rtc_media_base",
|
||||
"../media:rtc_media_tests_utils",
|
||||
"../modules/rtp_rtcp:rtp_rtcp_format",
|
||||
"../p2p:p2p_test_utils",
|
||||
"../p2p:rtc_p2p",
|
||||
"../rtc_base:checks",
|
||||
|
||||
133
pc/channel.cc
133
pc/channel.cc
@ -17,6 +17,7 @@
|
||||
#include "api/call/audio_sink.h"
|
||||
#include "media/base/mediaconstants.h"
|
||||
#include "media/base/rtputils.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
|
||||
#include "rtc_base/bind.h"
|
||||
#include "rtc_base/byteorder.h"
|
||||
#include "rtc_base/checks.h"
|
||||
@ -108,13 +109,13 @@ BaseChannel::BaseChannel(rtc::Thread* worker_thread,
|
||||
crypto_options_(crypto_options),
|
||||
media_channel_(std::move(media_channel)) {
|
||||
RTC_DCHECK_RUN_ON(worker_thread_);
|
||||
demuxer_criteria_.mid = content_name;
|
||||
RTC_LOG(LS_INFO) << "Created channel for " << content_name;
|
||||
}
|
||||
|
||||
BaseChannel::~BaseChannel() {
|
||||
TRACE_EVENT0("webrtc", "BaseChannel::~BaseChannel");
|
||||
RTC_DCHECK_RUN_ON(worker_thread_);
|
||||
Deinit();
|
||||
// Eats any outstanding messages or packets.
|
||||
worker_thread_->Clear(&invoker_);
|
||||
worker_thread_->Clear(this);
|
||||
@ -125,15 +126,15 @@ BaseChannel::~BaseChannel() {
|
||||
RTC_LOG(LS_INFO) << "Destroyed channel: " << content_name_;
|
||||
}
|
||||
|
||||
void BaseChannel::ConnectToRtpTransport() {
|
||||
bool BaseChannel::ConnectToRtpTransport() {
|
||||
RTC_DCHECK(rtp_transport_);
|
||||
if (!RegisterRtpDemuxerSink()) {
|
||||
return false;
|
||||
}
|
||||
rtp_transport_->SignalReadyToSend.connect(
|
||||
this, &BaseChannel::OnTransportReadyToSend);
|
||||
// TODO(zstein): RtpTransport::SignalPacketReceived will probably be replaced
|
||||
// with a callback interface later so that the demuxer can select which
|
||||
// channel to signal.
|
||||
rtp_transport_->SignalPacketReceived.connect(this,
|
||||
&BaseChannel::OnPacketReceived);
|
||||
rtp_transport_->SignalRtcpPacketReceived.connect(
|
||||
this, &BaseChannel::OnRtcpPacketReceived);
|
||||
rtp_transport_->SignalNetworkRouteChanged.connect(
|
||||
this, &BaseChannel::OnNetworkRouteChanged);
|
||||
rtp_transport_->SignalWritableState.connect(this,
|
||||
@ -146,12 +147,14 @@ void BaseChannel::ConnectToRtpTransport() {
|
||||
if (metrics_observer_) {
|
||||
rtp_transport_->SetMetricsObserver(metrics_observer_);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void BaseChannel::DisconnectFromRtpTransport() {
|
||||
RTC_DCHECK(rtp_transport_);
|
||||
rtp_transport_->UnregisterRtpDemuxerSink(this);
|
||||
rtp_transport_->SignalReadyToSend.disconnect(this);
|
||||
rtp_transport_->SignalPacketReceived.disconnect(this);
|
||||
rtp_transport_->SignalRtcpPacketReceived.disconnect(this);
|
||||
rtp_transport_->SignalNetworkRouteChanged.disconnect(this);
|
||||
rtp_transport_->SignalWritableState.disconnect(this);
|
||||
rtp_transport_->SignalSentPacket.disconnect(this);
|
||||
@ -160,9 +163,8 @@ void BaseChannel::DisconnectFromRtpTransport() {
|
||||
|
||||
void BaseChannel::Init_w(webrtc::RtpTransportInternal* rtp_transport) {
|
||||
RTC_DCHECK_RUN_ON(worker_thread_);
|
||||
network_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
|
||||
SetRtpTransport(rtp_transport);
|
||||
});
|
||||
network_thread_->Invoke<void>(
|
||||
RTC_FROM_HERE, [this, rtp_transport] { SetRtpTransport(rtp_transport); });
|
||||
|
||||
// Both RTP and RTCP channels should be set, we can call SetInterface on
|
||||
// the media channel and it can set network options.
|
||||
@ -187,12 +189,15 @@ void BaseChannel::Deinit() {
|
||||
});
|
||||
}
|
||||
|
||||
void BaseChannel::SetRtpTransport(webrtc::RtpTransportInternal* rtp_transport) {
|
||||
bool BaseChannel::SetRtpTransport(webrtc::RtpTransportInternal* rtp_transport) {
|
||||
if (rtp_transport == rtp_transport_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!network_thread_->IsCurrent()) {
|
||||
network_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
|
||||
SetRtpTransport(rtp_transport);
|
||||
return network_thread_->Invoke<bool>(RTC_FROM_HERE, [this, rtp_transport] {
|
||||
return SetRtpTransport(rtp_transport);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (rtp_transport_) {
|
||||
@ -204,7 +209,10 @@ void BaseChannel::SetRtpTransport(webrtc::RtpTransportInternal* rtp_transport) {
|
||||
RTC_DCHECK(rtp_transport_->rtp_packet_transport());
|
||||
transport_name_ = rtp_transport_->rtp_packet_transport()->transport_name();
|
||||
|
||||
ConnectToRtpTransport();
|
||||
if (!ConnectToRtpTransport()) {
|
||||
RTC_LOG(LS_ERROR) << "Failed to connect to the new RtpTransport.";
|
||||
return false;
|
||||
}
|
||||
OnTransportReadyToSend(rtp_transport_->IsReadyToSend());
|
||||
UpdateWritableState_n();
|
||||
|
||||
@ -220,6 +228,7 @@ void BaseChannel::SetRtpTransport(webrtc::RtpTransportInternal* rtp_transport) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void BaseChannel::SetMetricsObserver(
|
||||
@ -239,11 +248,19 @@ bool BaseChannel::Enable(bool enable) {
|
||||
}
|
||||
|
||||
bool BaseChannel::AddRecvStream(const StreamParams& sp) {
|
||||
demuxer_criteria_.ssrcs.insert(sp.first_ssrc());
|
||||
if (!RegisterRtpDemuxerSink()) {
|
||||
return false;
|
||||
}
|
||||
return InvokeOnWorker<bool>(RTC_FROM_HERE,
|
||||
Bind(&BaseChannel::AddRecvStream_w, this, sp));
|
||||
}
|
||||
|
||||
bool BaseChannel::RemoveRecvStream(uint32_t ssrc) {
|
||||
demuxer_criteria_.ssrcs.erase(ssrc);
|
||||
if (!RegisterRtpDemuxerSink()) {
|
||||
return false;
|
||||
}
|
||||
return InvokeOnWorker<bool>(
|
||||
RTC_FROM_HERE, Bind(&BaseChannel::RemoveRecvStream_w, this, ssrc));
|
||||
}
|
||||
@ -295,7 +312,7 @@ bool BaseChannel::IsReadyToSendMedia_n() const {
|
||||
return enabled() &&
|
||||
webrtc::RtpTransceiverDirectionHasRecv(remote_content_direction_) &&
|
||||
webrtc::RtpTransceiverDirectionHasSend(local_content_direction_) &&
|
||||
was_ever_writable() && (srtp_active() || encryption_disabled_);
|
||||
was_ever_writable();
|
||||
}
|
||||
|
||||
bool BaseChannel::SendPacket(rtc::CopyOnWriteBuffer* packet,
|
||||
@ -430,23 +447,56 @@ bool BaseChannel::SendPacket(bool rtcp,
|
||||
: rtp_transport_->SendRtpPacket(packet, options, PF_SRTP_BYPASS);
|
||||
}
|
||||
|
||||
bool BaseChannel::HandlesPayloadType(int packet_type) const {
|
||||
return bundle_filter_.FindPayloadType(packet_type);
|
||||
void BaseChannel::OnRtpPacket(const webrtc::RtpPacketReceived& parsed_packet) {
|
||||
// Reconstruct the PacketTime from the |parsed_packet|.
|
||||
// RtpPacketReceived.arrival_time_ms = (PacketTime + 500) / 1000;
|
||||
// Note: The |not_before| field is always 0 here. This field is not currently
|
||||
// used, so it should be fine.
|
||||
int64_t timestamp = -1;
|
||||
if (parsed_packet.arrival_time_ms() > 0) {
|
||||
timestamp = parsed_packet.arrival_time_ms() * 1000;
|
||||
}
|
||||
rtc::PacketTime packet_time(timestamp, /*not_before=*/0);
|
||||
|
||||
OnPacketReceived(/*rtcp=*/false, parsed_packet.Buffer(), packet_time);
|
||||
}
|
||||
|
||||
void BaseChannel::UpdateRtpHeaderExtensionMap(
|
||||
const RtpHeaderExtensions& header_extensions) {
|
||||
RTC_DCHECK(rtp_transport_);
|
||||
// Update the header extension map on network thread in case there is data
|
||||
// race.
|
||||
// TODO(zhihuang): Add an rtc::ThreadChecker make sure to RtpTransport won't
|
||||
// be accessed from different threads.
|
||||
//
|
||||
// NOTE: This doesn't take the BUNDLE case in account meaning the RTP header
|
||||
// extension maps are not merged when BUNDLE is enabled. This is fine because
|
||||
// the ID for MID should be consistent among all the RTP transports.
|
||||
network_thread_->Invoke<void>(RTC_FROM_HERE, [this, &header_extensions] {
|
||||
rtp_transport_->UpdateRtpHeaderExtensionMap(header_extensions);
|
||||
});
|
||||
}
|
||||
|
||||
bool BaseChannel::RegisterRtpDemuxerSink() {
|
||||
RTC_DCHECK(rtp_transport_);
|
||||
return network_thread_->Invoke<bool>(RTC_FROM_HERE, [this] {
|
||||
return rtp_transport_->RegisterRtpDemuxerSink(demuxer_criteria_, this);
|
||||
});
|
||||
}
|
||||
|
||||
void BaseChannel::OnRtcpPacketReceived(rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketTime& packet_time) {
|
||||
OnPacketReceived(/*rtcp=*/true, *packet, packet_time);
|
||||
}
|
||||
|
||||
void BaseChannel::OnPacketReceived(bool rtcp,
|
||||
rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::CopyOnWriteBuffer& packet,
|
||||
const rtc::PacketTime& packet_time) {
|
||||
if (!has_received_packet_ && !rtcp) {
|
||||
has_received_packet_ = true;
|
||||
signaling_thread()->Post(RTC_FROM_HERE, this, MSG_FIRSTPACKETRECEIVED);
|
||||
}
|
||||
|
||||
// Filter out the packet this channel cannot handle.
|
||||
if (!rtcp && !bundle_filter_.DemuxPacket(packet->data(), packet->size())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!srtp_active() && srtp_required_) {
|
||||
// Our session description indicates that SRTP is required, but we got a
|
||||
// packet before our SRTP filter is active. This means either that
|
||||
@ -467,7 +517,7 @@ void BaseChannel::OnPacketReceived(bool rtcp,
|
||||
|
||||
invoker_.AsyncInvoke<void>(
|
||||
RTC_FROM_HERE, worker_thread_,
|
||||
Bind(&BaseChannel::ProcessPacket, this, rtcp, *packet, packet_time));
|
||||
Bind(&BaseChannel::ProcessPacket, this, rtcp, packet, packet_time));
|
||||
}
|
||||
|
||||
void BaseChannel::ProcessPacket(bool rtcp,
|
||||
@ -595,7 +645,9 @@ bool BaseChannel::UpdateRemoteStreams_w(
|
||||
// the unsignaled stream params that are cached.
|
||||
if ((!it->has_ssrcs() && !HasStreamWithNoSsrcs(streams)) ||
|
||||
!GetStreamBySsrc(streams, it->first_ssrc())) {
|
||||
if (!RemoveRecvStream_w(it->first_ssrc())) {
|
||||
if (RemoveRecvStream_w(it->first_ssrc())) {
|
||||
RTC_LOG(LS_INFO) << "Remove remote ssrc: " << it->first_ssrc();
|
||||
} else {
|
||||
std::ostringstream desc;
|
||||
desc << "Failed to remove remote stream with ssrc "
|
||||
<< it->first_ssrc() << ".";
|
||||
@ -604,6 +656,7 @@ bool BaseChannel::UpdateRemoteStreams_w(
|
||||
}
|
||||
}
|
||||
}
|
||||
demuxer_criteria_.ssrcs.clear();
|
||||
// Check for new streams.
|
||||
for (StreamParamsVec::const_iterator it = streams.begin();
|
||||
it != streams.end(); ++it) {
|
||||
@ -621,7 +674,11 @@ bool BaseChannel::UpdateRemoteStreams_w(
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
// Update the receiving SSRCs.
|
||||
demuxer_criteria_.ssrcs.insert(it->ssrcs.begin(), it->ssrcs.end());
|
||||
}
|
||||
// Re-register the sink to update the receiving ssrcs.
|
||||
RegisterRtpDemuxerSink();
|
||||
remote_streams_ = streams;
|
||||
return ret;
|
||||
}
|
||||
@ -663,7 +720,7 @@ void BaseChannel::OnMessage(rtc::Message *pmsg) {
|
||||
}
|
||||
|
||||
void BaseChannel::AddHandledPayloadType(int payload_type) {
|
||||
bundle_filter_.AddPayloadType(payload_type);
|
||||
demuxer_criteria_.payload_types.insert(static_cast<uint8_t>(payload_type));
|
||||
}
|
||||
|
||||
void BaseChannel::FlushRtcpMessages_n() {
|
||||
@ -752,6 +809,7 @@ bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content,
|
||||
|
||||
RtpHeaderExtensions rtp_header_extensions =
|
||||
GetFilteredRtpHeaderExtensions(audio->rtp_header_extensions());
|
||||
UpdateRtpHeaderExtensionMap(rtp_header_extensions);
|
||||
|
||||
AudioRecvParameters recv_params = last_recv_params_;
|
||||
RtpParametersFromMediaDescription(audio, rtp_header_extensions, &recv_params);
|
||||
@ -763,6 +821,12 @@ bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content,
|
||||
for (const AudioCodec& codec : audio->codecs()) {
|
||||
AddHandledPayloadType(codec.id);
|
||||
}
|
||||
// Need to re-register the sink to update the handled payload.
|
||||
if (!RegisterRtpDemuxerSink()) {
|
||||
RTC_LOG(LS_ERROR) << "Failed to set up audio demuxing.";
|
||||
return false;
|
||||
}
|
||||
|
||||
last_recv_params_ = recv_params;
|
||||
|
||||
// TODO(pthatcher): Move local streams into AudioSendParameters, and
|
||||
@ -880,6 +944,7 @@ bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
|
||||
|
||||
RtpHeaderExtensions rtp_header_extensions =
|
||||
GetFilteredRtpHeaderExtensions(video->rtp_header_extensions());
|
||||
UpdateRtpHeaderExtensionMap(rtp_header_extensions);
|
||||
|
||||
VideoRecvParameters recv_params = last_recv_params_;
|
||||
RtpParametersFromMediaDescription(video, rtp_header_extensions, &recv_params);
|
||||
@ -891,6 +956,12 @@ bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
|
||||
for (const VideoCodec& codec : video->codecs()) {
|
||||
AddHandledPayloadType(codec.id);
|
||||
}
|
||||
// Need to re-register the sink to update the handled payload.
|
||||
if (!RegisterRtpDemuxerSink()) {
|
||||
RTC_LOG(LS_ERROR) << "Failed to set up video demuxing.";
|
||||
return false;
|
||||
}
|
||||
|
||||
last_recv_params_ = recv_params;
|
||||
|
||||
// TODO(pthatcher): Move local streams into VideoSendParameters, and
|
||||
@ -1039,6 +1110,12 @@ bool RtpDataChannel::SetLocalContent_w(const MediaContentDescription* content,
|
||||
for (const DataCodec& codec : data->codecs()) {
|
||||
AddHandledPayloadType(codec.id);
|
||||
}
|
||||
// Need to re-register the sink to update the handled payload.
|
||||
if (!RegisterRtpDemuxerSink()) {
|
||||
RTC_LOG(LS_ERROR) << "Failed to set up data demuxing.";
|
||||
return false;
|
||||
}
|
||||
|
||||
last_recv_params_ = recv_params;
|
||||
|
||||
// TODO(pthatcher): Move local streams into DataSendParameters, and
|
||||
|
||||
56
pc/channel.h
56
pc/channel.h
@ -23,13 +23,13 @@
|
||||
#include "api/rtpreceiverinterface.h"
|
||||
#include "api/videosinkinterface.h"
|
||||
#include "api/videosourceinterface.h"
|
||||
#include "call/rtp_packet_sink_interface.h"
|
||||
#include "media/base/mediachannel.h"
|
||||
#include "media/base/mediaengine.h"
|
||||
#include "media/base/streamparams.h"
|
||||
#include "p2p/base/dtlstransportinternal.h"
|
||||
#include "p2p/base/packettransportinternal.h"
|
||||
#include "pc/audiomonitor.h"
|
||||
#include "pc/bundlefilter.h"
|
||||
#include "pc/dtlssrtptransport.h"
|
||||
#include "pc/mediasession.h"
|
||||
#include "pc/rtptransport.h"
|
||||
@ -68,9 +68,10 @@ class MediaContentDescription;
|
||||
// vtable, and the media channel's thread using BaseChannel as the
|
||||
// NetworkInterface.
|
||||
|
||||
class BaseChannel
|
||||
: public rtc::MessageHandler, public sigslot::has_slots<>,
|
||||
public MediaChannel::NetworkInterface {
|
||||
class BaseChannel : public rtc::MessageHandler,
|
||||
public sigslot::has_slots<>,
|
||||
public MediaChannel::NetworkInterface,
|
||||
public webrtc::RtpPacketSinkInterface {
|
||||
public:
|
||||
// If |srtp_required| is true, the channel will not send or receive any
|
||||
// RTP/RTCP packets without using SRTP (either using SDES or DTLS-SRTP).
|
||||
@ -108,7 +109,7 @@ class BaseChannel
|
||||
// encryption, an SrtpTransport for SDES or a DtlsSrtpTransport for DTLS-SRTP.
|
||||
// This can be called from any thread and it hops to the network thread
|
||||
// internally. It would replace the |SetTransports| and its variants.
|
||||
void SetRtpTransport(webrtc::RtpTransportInternal* rtp_transport);
|
||||
bool SetRtpTransport(webrtc::RtpTransportInternal* rtp_transport);
|
||||
|
||||
// Channel control
|
||||
bool SetLocalContent(const MediaContentDescription* content,
|
||||
@ -120,7 +121,7 @@ class BaseChannel
|
||||
|
||||
bool Enable(bool enable);
|
||||
|
||||
// Multiplexing
|
||||
// TODO(zhihuang): These methods are used for testing and can be removed.
|
||||
bool AddRecvStream(const StreamParams& sp);
|
||||
bool RemoveRecvStream(uint32_t ssrc);
|
||||
bool AddSendStream(const StreamParams& sp);
|
||||
@ -172,10 +173,8 @@ class BaseChannel
|
||||
|
||||
virtual cricket::MediaType media_type() = 0;
|
||||
|
||||
// Public for testing.
|
||||
// TODO(zstein): Remove this once channels register themselves with
|
||||
// an RtpTransport in a more explicit way.
|
||||
bool HandlesPayloadType(int payload_type) const;
|
||||
// RtpPacketSinkInterface overrides.
|
||||
void OnRtpPacket(const webrtc::RtpPacketReceived& packet) override;
|
||||
|
||||
// Used by the RTCStatsCollector tests to set the transport name without
|
||||
// creating RtpTransports.
|
||||
@ -186,8 +185,6 @@ class BaseChannel
|
||||
void SetMetricsObserver(
|
||||
rtc::scoped_refptr<webrtc::MetricsObserverInterface> metrics_observer);
|
||||
|
||||
void DisableEncryption(bool disabled) { encryption_disabled_ = disabled; }
|
||||
|
||||
protected:
|
||||
virtual MediaChannel* media_channel() const { return media_channel_.get(); }
|
||||
|
||||
@ -232,12 +229,11 @@ class BaseChannel
|
||||
rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketOptions& options);
|
||||
|
||||
bool WantsPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet);
|
||||
void HandlePacket(bool rtcp, rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketTime& packet_time);
|
||||
// TODO(zstein): packet can be const once the RtpTransport handles protection.
|
||||
void OnRtcpPacketReceived(rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketTime& packet_time);
|
||||
|
||||
void OnPacketReceived(bool rtcp,
|
||||
rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::CopyOnWriteBuffer& packet,
|
||||
const rtc::PacketTime& packet_time);
|
||||
void ProcessPacket(bool rtcp,
|
||||
const rtc::CopyOnWriteBuffer& packet,
|
||||
@ -282,11 +278,6 @@ class BaseChannel
|
||||
RtpHeaderExtensions GetFilteredRtpHeaderExtensions(
|
||||
const RtpHeaderExtensions& extensions);
|
||||
|
||||
// Helper method to get RTP Absoulute SendTime extension header id if
|
||||
// present in remote supported extensions list.
|
||||
void MaybeCacheRtpAbsSendTimeHeaderExtension_w(
|
||||
const std::vector<webrtc::RtpExtension>& extensions);
|
||||
|
||||
// From MessageHandler
|
||||
void OnMessage(rtc::Message* pmsg) override;
|
||||
|
||||
@ -298,8 +289,13 @@ class BaseChannel
|
||||
|
||||
void AddHandledPayloadType(int payload_type);
|
||||
|
||||
void UpdateRtpHeaderExtensionMap(
|
||||
const RtpHeaderExtensions& header_extensions);
|
||||
|
||||
bool RegisterRtpDemuxerSink();
|
||||
|
||||
private:
|
||||
void ConnectToRtpTransport();
|
||||
bool ConnectToRtpTransport();
|
||||
void DisconnectFromRtpTransport();
|
||||
void SignalSentPacket_n(const rtc::SentPacket& sent_packet);
|
||||
void SignalSentPacket_w(const rtc::SentPacket& sent_packet);
|
||||
@ -317,11 +313,6 @@ class BaseChannel
|
||||
rtc::scoped_refptr<webrtc::MetricsObserverInterface> metrics_observer_;
|
||||
|
||||
webrtc::RtpTransportInternal* rtp_transport_ = nullptr;
|
||||
// Only one of these transports is non-null at a time. One for DTLS-SRTP, one
|
||||
// for SDES and one for unencrypted RTP.
|
||||
std::unique_ptr<webrtc::SrtpTransport> sdes_transport_;
|
||||
std::unique_ptr<webrtc::DtlsSrtpTransport> dtls_srtp_transport_;
|
||||
std::unique_ptr<webrtc::RtpTransport> unencrypted_rtp_transport_;
|
||||
|
||||
std::vector<std::pair<rtc::Socket::Option, int> > socket_options_;
|
||||
std::vector<std::pair<rtc::Socket::Option, int> > rtcp_socket_options_;
|
||||
@ -345,14 +336,7 @@ class BaseChannel
|
||||
webrtc::RtpTransceiverDirection remote_content_direction_ =
|
||||
webrtc::RtpTransceiverDirection::kInactive;
|
||||
|
||||
// The cached encrypted header extension IDs.
|
||||
rtc::Optional<std::vector<int>> cached_send_extension_ids_;
|
||||
rtc::Optional<std::vector<int>> cached_recv_extension_ids_;
|
||||
|
||||
// TODO(zhihuang): These two variables can be removed once switching to
|
||||
// RtpDemuxer.
|
||||
BundleFilter bundle_filter_;
|
||||
bool encryption_disabled_ = false;
|
||||
webrtc::RtpDemuxerCriteria demuxer_criteria_;
|
||||
};
|
||||
|
||||
// VoiceChannel is a specialization that adds support for early media, DTMF,
|
||||
|
||||
@ -42,6 +42,8 @@ const cricket::VideoCodec kH264SvcCodec(99, "H264-SVC");
|
||||
const cricket::DataCodec kGoogleDataCodec(101, "google-data");
|
||||
const uint32_t kSsrc1 = 0x1111;
|
||||
const uint32_t kSsrc2 = 0x2222;
|
||||
const uint32_t kSsrc3 = 0x3333;
|
||||
const uint32_t kSsrc4 = 0x4444;
|
||||
const int kAudioPts[] = {0, 8};
|
||||
const int kVideoPts[] = {97, 99};
|
||||
enum class NetworkIsWorker { Yes, No };
|
||||
@ -239,13 +241,6 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
if (flags2 & SSRC_MUX) {
|
||||
AddLegacyStreamInContent(kSsrc2, flags2, &remote_media_content2_);
|
||||
}
|
||||
|
||||
if (!(flags1 & DTLS)) {
|
||||
channel1_->DisableEncryption(true);
|
||||
}
|
||||
if (!(flags2 & DTLS)) {
|
||||
channel2_->DisableEncryption(true);
|
||||
}
|
||||
}
|
||||
std::unique_ptr<typename T::Channel> CreateChannel(
|
||||
rtc::Thread* worker_thread,
|
||||
@ -289,9 +284,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
std::unique_ptr<webrtc::RtpTransport> CreateUnencryptedTransport(
|
||||
rtc::PacketTransportInternal* rtp_packet_transport,
|
||||
rtc::PacketTransportInternal* rtcp_packet_transport) {
|
||||
bool rtcp_mux_enabled = (rtcp_packet_transport == nullptr);
|
||||
auto rtp_transport =
|
||||
rtc::MakeUnique<webrtc::RtpTransport>(rtcp_mux_enabled);
|
||||
rtc::MakeUnique<webrtc::RtpTransport>(rtcp_packet_transport == nullptr);
|
||||
|
||||
rtp_transport->SetRtpPacketTransport(rtp_packet_transport);
|
||||
if (rtcp_packet_transport) {
|
||||
@ -303,11 +297,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
std::unique_ptr<webrtc::DtlsSrtpTransport> CreateDtlsSrtpTransport(
|
||||
cricket::DtlsTransportInternal* rtp_dtls_transport,
|
||||
cricket::DtlsTransportInternal* rtcp_dtls_transport) {
|
||||
bool rtcp_mux_enabled = (rtcp_dtls_transport == nullptr);
|
||||
auto srtp_transport =
|
||||
rtc::MakeUnique<webrtc::SrtpTransport>(rtcp_mux_enabled);
|
||||
auto dtls_srtp_transport =
|
||||
rtc::MakeUnique<webrtc::DtlsSrtpTransport>(std::move(srtp_transport));
|
||||
auto dtls_srtp_transport = rtc::MakeUnique<webrtc::DtlsSrtpTransport>(
|
||||
rtcp_dtls_transport == nullptr);
|
||||
|
||||
dtls_srtp_transport->SetDtlsTransports(rtp_dtls_transport,
|
||||
rtcp_dtls_transport);
|
||||
@ -1177,10 +1168,6 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
CreateChannels(flags, flags);
|
||||
EXPECT_TRUE(SendInitiate());
|
||||
EXPECT_TRUE(SendAccept());
|
||||
EXPECT_TRUE(channel1_->HandlesPayloadType(pl_type1));
|
||||
EXPECT_TRUE(channel2_->HandlesPayloadType(pl_type1));
|
||||
EXPECT_FALSE(channel1_->HandlesPayloadType(pl_type2));
|
||||
EXPECT_FALSE(channel2_->HandlesPayloadType(pl_type2));
|
||||
|
||||
// Both channels can receive pl_type1 only.
|
||||
SendCustomRtp1(kSsrc1, ++sequence_number1_1, pl_type1);
|
||||
@ -1191,11 +1178,11 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
EXPECT_TRUE(CheckNoRtp1());
|
||||
EXPECT_TRUE(CheckNoRtp2());
|
||||
|
||||
SendCustomRtp1(kSsrc1, ++sequence_number1_1, pl_type2);
|
||||
SendCustomRtp2(kSsrc2, ++sequence_number2_2, pl_type2);
|
||||
SendCustomRtp1(kSsrc3, ++sequence_number1_1, pl_type2);
|
||||
SendCustomRtp2(kSsrc4, ++sequence_number2_2, pl_type2);
|
||||
WaitForThreads();
|
||||
EXPECT_FALSE(CheckCustomRtp2(kSsrc1, sequence_number1_1, pl_type2));
|
||||
EXPECT_FALSE(CheckCustomRtp1(kSsrc2, sequence_number2_2, pl_type2));
|
||||
EXPECT_FALSE(CheckCustomRtp2(kSsrc3, sequence_number1_1, pl_type2));
|
||||
EXPECT_FALSE(CheckCustomRtp1(kSsrc4, sequence_number2_2, pl_type2));
|
||||
|
||||
// RTCP test
|
||||
SendCustomRtcp1(kSsrc1);
|
||||
|
||||
@ -55,12 +55,8 @@ class ChannelManagerTest : public testing::Test {
|
||||
std::unique_ptr<webrtc::RtpTransportInternal> CreateDtlsSrtpTransport() {
|
||||
rtp_dtls_transport_ = rtc::MakeUnique<FakeDtlsTransport>(
|
||||
"fake_dtls_transport", cricket::ICE_CANDIDATE_COMPONENT_RTP);
|
||||
auto rtp_transport =
|
||||
rtc::MakeUnique<webrtc::RtpTransport>(/*rtcp_mux_required=*/true);
|
||||
auto srtp_transport =
|
||||
rtc::MakeUnique<webrtc::SrtpTransport>(std::move(rtp_transport));
|
||||
auto dtls_srtp_transport =
|
||||
rtc::MakeUnique<webrtc::DtlsSrtpTransport>(std::move(srtp_transport));
|
||||
rtc::MakeUnique<webrtc::DtlsSrtpTransport>(/*rtcp_mux_required=*/true);
|
||||
dtls_srtp_transport->SetDtlsTransports(rtp_dtls_transport_.get(),
|
||||
/*rtcp_dtls_transport=*/nullptr);
|
||||
return dtls_srtp_transport;
|
||||
|
||||
@ -24,22 +24,8 @@ static const char kDtlsSrtpExporterLabel[] = "EXTRACTOR-dtls_srtp";
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
DtlsSrtpTransport::DtlsSrtpTransport(
|
||||
std::unique_ptr<webrtc::SrtpTransport> srtp_transport)
|
||||
: RtpTransportInternalAdapter(srtp_transport.get()) {
|
||||
srtp_transport_ = std::move(srtp_transport);
|
||||
RTC_DCHECK(srtp_transport_);
|
||||
srtp_transport_->SignalPacketReceived.connect(
|
||||
this, &DtlsSrtpTransport::OnPacketReceived);
|
||||
srtp_transport_->SignalReadyToSend.connect(this,
|
||||
&DtlsSrtpTransport::OnReadyToSend);
|
||||
srtp_transport_->SignalNetworkRouteChanged.connect(
|
||||
this, &DtlsSrtpTransport::OnNetworkRouteChanged);
|
||||
srtp_transport_->SignalWritableState.connect(
|
||||
this, &DtlsSrtpTransport::OnWritableState);
|
||||
srtp_transport_->SignalSentPacket.connect(this,
|
||||
&DtlsSrtpTransport::OnSentPacket);
|
||||
}
|
||||
DtlsSrtpTransport::DtlsSrtpTransport(bool rtcp_mux_enabled)
|
||||
: SrtpTransport(rtcp_mux_enabled) {}
|
||||
|
||||
void DtlsSrtpTransport::SetDtlsTransports(
|
||||
cricket::DtlsTransportInternal* rtp_dtls_transport,
|
||||
@ -54,7 +40,7 @@ void DtlsSrtpTransport::SetDtlsTransports(
|
||||
// DtlsTransport changes and wait until the DTLS handshake is complete to set
|
||||
// the newly negotiated parameters.
|
||||
if (IsSrtpActive()) {
|
||||
srtp_transport_->ResetParams();
|
||||
ResetParams();
|
||||
}
|
||||
|
||||
const std::string transport_name =
|
||||
@ -76,13 +62,13 @@ void DtlsSrtpTransport::SetDtlsTransports(
|
||||
SetRtpDtlsTransport(rtp_dtls_transport);
|
||||
SetRtpPacketTransport(rtp_dtls_transport);
|
||||
|
||||
UpdateWritableStateAndMaybeSetupDtlsSrtp();
|
||||
MaybeSetupDtlsSrtp();
|
||||
}
|
||||
|
||||
void DtlsSrtpTransport::SetRtcpMuxEnabled(bool enable) {
|
||||
srtp_transport_->SetRtcpMuxEnabled(enable);
|
||||
SrtpTransport::SetRtcpMuxEnabled(enable);
|
||||
if (enable) {
|
||||
UpdateWritableStateAndMaybeSetupDtlsSrtp();
|
||||
MaybeSetupDtlsSrtp();
|
||||
}
|
||||
}
|
||||
|
||||
@ -128,10 +114,9 @@ bool DtlsSrtpTransport::IsDtlsConnected() {
|
||||
}
|
||||
|
||||
bool DtlsSrtpTransport::IsDtlsWritable() {
|
||||
auto rtp_packet_transport = srtp_transport_->rtp_packet_transport();
|
||||
auto rtcp_packet_transport =
|
||||
rtcp_mux_enabled() ? nullptr : srtp_transport_->rtcp_packet_transport();
|
||||
return rtp_packet_transport && rtp_packet_transport->writable() &&
|
||||
rtcp_mux_enabled() ? nullptr : rtcp_dtls_transport_;
|
||||
return rtp_dtls_transport_ && rtp_dtls_transport_->writable() &&
|
||||
(!rtcp_packet_transport || rtcp_packet_transport->writable());
|
||||
}
|
||||
|
||||
@ -140,7 +125,7 @@ bool DtlsSrtpTransport::DtlsHandshakeCompleted() {
|
||||
}
|
||||
|
||||
void DtlsSrtpTransport::MaybeSetupDtlsSrtp() {
|
||||
if (IsSrtpActive() || !DtlsHandshakeCompleted()) {
|
||||
if (IsSrtpActive() || !IsDtlsWritable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -170,11 +155,10 @@ void DtlsSrtpTransport::SetupRtpDtlsSrtp() {
|
||||
|
||||
if (!ExtractParams(rtp_dtls_transport_, &selected_crypto_suite, &send_key,
|
||||
&recv_key) ||
|
||||
!srtp_transport_->SetRtpParams(
|
||||
selected_crypto_suite, &send_key[0],
|
||||
static_cast<int>(send_key.size()), send_extension_ids,
|
||||
selected_crypto_suite, &recv_key[0],
|
||||
static_cast<int>(recv_key.size()), recv_extension_ids)) {
|
||||
!SetRtpParams(selected_crypto_suite, &send_key[0],
|
||||
static_cast<int>(send_key.size()), send_extension_ids,
|
||||
selected_crypto_suite, &recv_key[0],
|
||||
static_cast<int>(recv_key.size()), recv_extension_ids)) {
|
||||
SignalDtlsSrtpSetupFailure(this, /*rtcp=*/false);
|
||||
RTC_LOG(LS_WARNING) << "DTLS-SRTP key installation for RTP failed";
|
||||
}
|
||||
@ -202,11 +186,11 @@ void DtlsSrtpTransport::SetupRtcpDtlsSrtp() {
|
||||
rtc::ZeroOnFreeBuffer<unsigned char> rtcp_recv_key;
|
||||
if (!ExtractParams(rtcp_dtls_transport_, &selected_crypto_suite,
|
||||
&rtcp_send_key, &rtcp_recv_key) ||
|
||||
!srtp_transport_->SetRtcpParams(
|
||||
selected_crypto_suite, &rtcp_send_key[0],
|
||||
static_cast<int>(rtcp_send_key.size()), send_extension_ids,
|
||||
selected_crypto_suite, &rtcp_recv_key[0],
|
||||
static_cast<int>(rtcp_recv_key.size()), recv_extension_ids)) {
|
||||
!SetRtcpParams(selected_crypto_suite, &rtcp_send_key[0],
|
||||
static_cast<int>(rtcp_send_key.size()), send_extension_ids,
|
||||
selected_crypto_suite, &rtcp_recv_key[0],
|
||||
static_cast<int>(rtcp_recv_key.size()),
|
||||
recv_extension_ids)) {
|
||||
SignalDtlsSrtpSetupFailure(this, /*rtcp=*/true);
|
||||
RTC_LOG(LS_WARNING) << "DTLS-SRTP key installation for RTCP failed";
|
||||
}
|
||||
@ -307,59 +291,22 @@ void DtlsSrtpTransport::SetRtcpDtlsTransport(
|
||||
SetDtlsTransport(rtcp_dtls_transport, &rtcp_dtls_transport_);
|
||||
}
|
||||
|
||||
void DtlsSrtpTransport::UpdateWritableStateAndMaybeSetupDtlsSrtp() {
|
||||
bool writable = IsDtlsWritable();
|
||||
SetWritable(writable);
|
||||
if (writable) {
|
||||
MaybeSetupDtlsSrtp();
|
||||
}
|
||||
}
|
||||
|
||||
void DtlsSrtpTransport::SetWritable(bool writable) {
|
||||
// Only fire the signal if the writable state changes.
|
||||
if (writable_ != writable) {
|
||||
writable_ = writable;
|
||||
SignalWritableState(writable_);
|
||||
}
|
||||
}
|
||||
|
||||
void DtlsSrtpTransport::OnDtlsState(cricket::DtlsTransportInternal* transport,
|
||||
cricket::DtlsTransportState state) {
|
||||
RTC_DCHECK(transport == rtp_dtls_transport_ ||
|
||||
transport == rtcp_dtls_transport_);
|
||||
|
||||
if (state != cricket::DTLS_TRANSPORT_CONNECTED) {
|
||||
srtp_transport_->ResetParams();
|
||||
ResetParams();
|
||||
return;
|
||||
}
|
||||
|
||||
MaybeSetupDtlsSrtp();
|
||||
}
|
||||
|
||||
void DtlsSrtpTransport::OnWritableState(bool writable) {
|
||||
SetWritable(writable);
|
||||
if (writable) {
|
||||
MaybeSetupDtlsSrtp();
|
||||
}
|
||||
}
|
||||
|
||||
void DtlsSrtpTransport::OnSentPacket(const rtc::SentPacket& sent_packet) {
|
||||
SignalSentPacket(sent_packet);
|
||||
}
|
||||
|
||||
void DtlsSrtpTransport::OnPacketReceived(bool rtcp,
|
||||
rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketTime& packet_time) {
|
||||
SignalPacketReceived(rtcp, packet, packet_time);
|
||||
}
|
||||
|
||||
void DtlsSrtpTransport::OnReadyToSend(bool ready) {
|
||||
SignalReadyToSend(ready);
|
||||
}
|
||||
|
||||
void DtlsSrtpTransport::OnNetworkRouteChanged(
|
||||
rtc::Optional<rtc::NetworkRoute> network_route) {
|
||||
SignalNetworkRouteChanged(network_route);
|
||||
void DtlsSrtpTransport::OnWritableState(
|
||||
rtc::PacketTransportInternal* packet_transport) {
|
||||
MaybeSetupDtlsSrtp();
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -16,20 +16,17 @@
|
||||
#include <vector>
|
||||
|
||||
#include "p2p/base/dtlstransportinternal.h"
|
||||
#include "pc/rtptransportinternaladapter.h"
|
||||
#include "pc/srtptransport.h"
|
||||
#include "rtc_base/buffer.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// This class is intended to be used as an RtpTransport and it wraps both an
|
||||
// SrtpTransport and DtlsTransports(RTP/RTCP). When the DTLS handshake is
|
||||
// finished, it extracts the keying materials from DtlsTransport and sets them
|
||||
// to SrtpTransport.
|
||||
class DtlsSrtpTransport : public RtpTransportInternalAdapter {
|
||||
// The subclass of SrtpTransport is used for DTLS-SRTP. When the DTLS handshake
|
||||
// is finished, it extracts the keying materials from DtlsTransport and
|
||||
// configures the SrtpSessions in the base class.
|
||||
class DtlsSrtpTransport : public SrtpTransport {
|
||||
public:
|
||||
explicit DtlsSrtpTransport(
|
||||
std::unique_ptr<webrtc::SrtpTransport> srtp_transport);
|
||||
explicit DtlsSrtpTransport(bool rtcp_mux_enabled);
|
||||
|
||||
// Set P2P layer RTP/RTCP DtlsTransports. When using RTCP-muxing,
|
||||
// |rtcp_dtls_transport| is null.
|
||||
@ -45,15 +42,6 @@ class DtlsSrtpTransport : public RtpTransportInternalAdapter {
|
||||
void UpdateRecvEncryptedHeaderExtensionIds(
|
||||
const std::vector<int>& recv_extension_ids);
|
||||
|
||||
bool IsSrtpActive() const override { return srtp_transport_->IsSrtpActive(); }
|
||||
|
||||
// Cache RTP Absoulute SendTime extension header ID. This is only used when
|
||||
// external authentication is enabled.
|
||||
void CacheRtpAbsSendTimeHeaderExtension(int rtp_abs_sendtime_extn_id) {
|
||||
srtp_transport_->CacheRtpAbsSendTimeHeaderExtension(
|
||||
rtp_abs_sendtime_extn_id);
|
||||
}
|
||||
|
||||
sigslot::signal2<DtlsSrtpTransport*, bool> SignalDtlsSrtpSetupFailure;
|
||||
|
||||
RTCError SetSrtpSendKey(const cricket::CryptoParams& params) override {
|
||||
@ -82,23 +70,13 @@ class DtlsSrtpTransport : public RtpTransportInternalAdapter {
|
||||
void SetRtpDtlsTransport(cricket::DtlsTransportInternal* rtp_dtls_transport);
|
||||
void SetRtcpDtlsTransport(
|
||||
cricket::DtlsTransportInternal* rtcp_dtls_transport);
|
||||
void UpdateWritableStateAndMaybeSetupDtlsSrtp();
|
||||
// Set the writability and fire the SignalWritableState if the writability
|
||||
// changes.
|
||||
void SetWritable(bool writable);
|
||||
|
||||
void OnDtlsState(cricket::DtlsTransportInternal* dtls_transport,
|
||||
cricket::DtlsTransportState state);
|
||||
void OnWritableState(bool writable);
|
||||
void OnSentPacket(const rtc::SentPacket& sent_packet);
|
||||
void OnPacketReceived(bool rtcp,
|
||||
rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketTime& packet_time);
|
||||
void OnReadyToSend(bool ready);
|
||||
void OnNetworkRouteChanged(rtc::Optional<rtc::NetworkRoute> network_route);
|
||||
|
||||
bool writable_ = false;
|
||||
std::unique_ptr<SrtpTransport> srtp_transport_;
|
||||
// Override the SrtpTransport::OnWritableState.
|
||||
void OnWritableState(rtc::PacketTransportInternal* packet_transport) override;
|
||||
|
||||
// Owned by the TransportController.
|
||||
cricket::DtlsTransportInternal* rtp_dtls_transport_ = nullptr;
|
||||
cricket::DtlsTransportInternal* rtcp_dtls_transport_ = nullptr;
|
||||
|
||||
@ -33,47 +33,26 @@ using webrtc::RtpTransport;
|
||||
|
||||
const int kRtpAuthTagLen = 10;
|
||||
|
||||
class TransportObserver : public sigslot::has_slots<> {
|
||||
public:
|
||||
void OnPacketReceived(bool rtcp,
|
||||
rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketTime& packet_time) {
|
||||
rtcp ? last_recv_rtcp_packet_ = *packet : last_recv_rtp_packet_ = *packet;
|
||||
}
|
||||
|
||||
void OnReadyToSend(bool ready) { ready_to_send_ = ready; }
|
||||
|
||||
rtc::CopyOnWriteBuffer last_recv_rtp_packet() {
|
||||
return last_recv_rtp_packet_;
|
||||
}
|
||||
|
||||
rtc::CopyOnWriteBuffer last_recv_rtcp_packet() {
|
||||
return last_recv_rtcp_packet_;
|
||||
}
|
||||
|
||||
bool ready_to_send() { return ready_to_send_; }
|
||||
|
||||
private:
|
||||
rtc::CopyOnWriteBuffer last_recv_rtp_packet_;
|
||||
rtc::CopyOnWriteBuffer last_recv_rtcp_packet_;
|
||||
bool ready_to_send_ = false;
|
||||
};
|
||||
|
||||
class DtlsSrtpTransportTest : public testing::Test,
|
||||
public sigslot::has_slots<> {
|
||||
protected:
|
||||
DtlsSrtpTransportTest() {}
|
||||
|
||||
~DtlsSrtpTransportTest() {
|
||||
if (dtls_srtp_transport1_) {
|
||||
dtls_srtp_transport1_->UnregisterRtpDemuxerSink(&transport_observer1_);
|
||||
}
|
||||
if (dtls_srtp_transport2_) {
|
||||
dtls_srtp_transport2_->UnregisterRtpDemuxerSink(&transport_observer2_);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<DtlsSrtpTransport> MakeDtlsSrtpTransport(
|
||||
FakeDtlsTransport* rtp_dtls,
|
||||
FakeDtlsTransport* rtcp_dtls,
|
||||
bool rtcp_mux_enabled) {
|
||||
auto rtp_transport = rtc::MakeUnique<RtpTransport>(rtcp_mux_enabled);
|
||||
|
||||
auto srtp_transport =
|
||||
rtc::MakeUnique<SrtpTransport>(std::move(rtp_transport));
|
||||
auto dtls_srtp_transport =
|
||||
rtc::MakeUnique<DtlsSrtpTransport>(std::move(srtp_transport));
|
||||
rtc::MakeUnique<DtlsSrtpTransport>(rtcp_mux_enabled);
|
||||
|
||||
dtls_srtp_transport->SetDtlsTransports(rtp_dtls, rtcp_dtls);
|
||||
|
||||
@ -90,15 +69,24 @@ class DtlsSrtpTransportTest : public testing::Test,
|
||||
dtls_srtp_transport2_ =
|
||||
MakeDtlsSrtpTransport(rtp_dtls2, rtcp_dtls2, rtcp_mux_enabled);
|
||||
|
||||
dtls_srtp_transport1_->SignalPacketReceived.connect(
|
||||
&transport_observer1_, &TransportObserver::OnPacketReceived);
|
||||
dtls_srtp_transport1_->SignalRtcpPacketReceived.connect(
|
||||
&transport_observer1_,
|
||||
&webrtc::TransportObserver::OnRtcpPacketReceived);
|
||||
dtls_srtp_transport1_->SignalReadyToSend.connect(
|
||||
&transport_observer1_, &TransportObserver::OnReadyToSend);
|
||||
&transport_observer1_, &webrtc::TransportObserver::OnReadyToSend);
|
||||
|
||||
dtls_srtp_transport2_->SignalPacketReceived.connect(
|
||||
&transport_observer2_, &TransportObserver::OnPacketReceived);
|
||||
dtls_srtp_transport2_->SignalRtcpPacketReceived.connect(
|
||||
&transport_observer2_,
|
||||
&webrtc::TransportObserver::OnRtcpPacketReceived);
|
||||
dtls_srtp_transport2_->SignalReadyToSend.connect(
|
||||
&transport_observer2_, &TransportObserver::OnReadyToSend);
|
||||
&transport_observer2_, &webrtc::TransportObserver::OnReadyToSend);
|
||||
webrtc::RtpDemuxerCriteria demuxer_criteria;
|
||||
// 0x00 is the payload type used in kPcmuFrame.
|
||||
demuxer_criteria.payload_types = {0x00};
|
||||
dtls_srtp_transport1_->RegisterRtpDemuxerSink(demuxer_criteria,
|
||||
&transport_observer1_);
|
||||
dtls_srtp_transport2_->RegisterRtpDemuxerSink(demuxer_criteria,
|
||||
&transport_observer2_);
|
||||
}
|
||||
|
||||
void CompleteDtlsHandshake(FakeDtlsTransport* fake_dtls1,
|
||||
@ -248,8 +236,8 @@ class DtlsSrtpTransportTest : public testing::Test,
|
||||
|
||||
std::unique_ptr<DtlsSrtpTransport> dtls_srtp_transport1_;
|
||||
std::unique_ptr<DtlsSrtpTransport> dtls_srtp_transport2_;
|
||||
TransportObserver transport_observer1_;
|
||||
TransportObserver transport_observer2_;
|
||||
webrtc::TransportObserver transport_observer1_;
|
||||
webrtc::TransportObserver transport_observer2_;
|
||||
|
||||
int sequence_number_ = 0;
|
||||
};
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "pc/jseptransport2.h"
|
||||
#include "pc/jseptransport.h"
|
||||
|
||||
#include <memory>
|
||||
#include <utility> // for std::pair
|
||||
@ -21,6 +21,7 @@
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/ptr_util.h"
|
||||
#include "rtc_base/strings/string_builder.h"
|
||||
|
||||
using webrtc::SdpType;
|
||||
|
||||
@ -86,7 +87,7 @@ JsepTransportDescription& JsepTransportDescription::operator=(
|
||||
return *this;
|
||||
}
|
||||
|
||||
JsepTransport2::JsepTransport2(
|
||||
JsepTransport::JsepTransport(
|
||||
const std::string& mid,
|
||||
const rtc::scoped_refptr<rtc::RTCCertificate>& local_certificate,
|
||||
std::unique_ptr<webrtc::RtpTransport> unencrypted_rtp_transport,
|
||||
@ -115,9 +116,9 @@ JsepTransport2::JsepTransport2(
|
||||
}
|
||||
}
|
||||
|
||||
JsepTransport2::~JsepTransport2() {}
|
||||
JsepTransport::~JsepTransport() {}
|
||||
|
||||
webrtc::RTCError JsepTransport2::SetLocalJsepTransportDescription(
|
||||
webrtc::RTCError JsepTransport::SetLocalJsepTransportDescription(
|
||||
const JsepTransportDescription& jsep_description,
|
||||
SdpType type) {
|
||||
webrtc::RTCError error;
|
||||
@ -195,7 +196,7 @@ webrtc::RTCError JsepTransport2::SetLocalJsepTransportDescription(
|
||||
return webrtc::RTCError::OK();
|
||||
}
|
||||
|
||||
webrtc::RTCError JsepTransport2::SetRemoteJsepTransportDescription(
|
||||
webrtc::RTCError JsepTransport::SetRemoteJsepTransportDescription(
|
||||
const JsepTransportDescription& jsep_description,
|
||||
webrtc::SdpType type) {
|
||||
webrtc::RTCError error;
|
||||
@ -251,7 +252,7 @@ webrtc::RTCError JsepTransport2::SetRemoteJsepTransportDescription(
|
||||
return webrtc::RTCError::OK();
|
||||
}
|
||||
|
||||
webrtc::RTCError JsepTransport2::AddRemoteCandidates(
|
||||
webrtc::RTCError JsepTransport::AddRemoteCandidates(
|
||||
const Candidates& candidates) {
|
||||
if (!local_description_ || !remote_description_) {
|
||||
return webrtc::RTCError(webrtc::RTCErrorType::INVALID_STATE,
|
||||
@ -276,14 +277,14 @@ webrtc::RTCError JsepTransport2::AddRemoteCandidates(
|
||||
return webrtc::RTCError::OK();
|
||||
}
|
||||
|
||||
void JsepTransport2::SetNeedsIceRestartFlag() {
|
||||
void JsepTransport::SetNeedsIceRestartFlag() {
|
||||
if (!needs_ice_restart_) {
|
||||
needs_ice_restart_ = true;
|
||||
RTC_LOG(LS_VERBOSE) << "needs-ice-restart flag set for transport " << mid();
|
||||
}
|
||||
}
|
||||
|
||||
rtc::Optional<rtc::SSLRole> JsepTransport2::GetDtlsRole() const {
|
||||
rtc::Optional<rtc::SSLRole> JsepTransport::GetDtlsRole() const {
|
||||
RTC_DCHECK(rtp_dtls_transport_);
|
||||
rtc::SSLRole dtls_role;
|
||||
if (!rtp_dtls_transport_->GetDtlsRole(&dtls_role)) {
|
||||
@ -293,7 +294,7 @@ rtc::Optional<rtc::SSLRole> JsepTransport2::GetDtlsRole() const {
|
||||
return rtc::Optional<rtc::SSLRole>(dtls_role);
|
||||
}
|
||||
|
||||
bool JsepTransport2::GetStats(TransportStats* stats) {
|
||||
bool JsepTransport::GetStats(TransportStats* stats) {
|
||||
stats->transport_name = mid();
|
||||
stats->channel_stats.clear();
|
||||
bool ret = GetTransportStats(rtp_dtls_transport_.get(), stats);
|
||||
@ -303,7 +304,7 @@ bool JsepTransport2::GetStats(TransportStats* stats) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
webrtc::RTCError JsepTransport2::VerifyCertificateFingerprint(
|
||||
webrtc::RTCError JsepTransport::VerifyCertificateFingerprint(
|
||||
const rtc::RTCCertificate* certificate,
|
||||
const rtc::SSLFingerprint* fingerprint) const {
|
||||
if (!fingerprint) {
|
||||
@ -320,22 +321,23 @@ webrtc::RTCError JsepTransport2::VerifyCertificateFingerprint(
|
||||
if (*fp_tmp == *fingerprint) {
|
||||
return webrtc::RTCError::OK();
|
||||
}
|
||||
std::ostringstream desc;
|
||||
char ss_buf[1024];
|
||||
rtc::SimpleStringBuilder desc(ss_buf);
|
||||
desc << "Local fingerprint does not match identity. Expected: ";
|
||||
desc << fp_tmp->ToString();
|
||||
desc << " Got: " << fingerprint->ToString();
|
||||
return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER, desc.str());
|
||||
return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
|
||||
std::string(desc.str()));
|
||||
}
|
||||
|
||||
void JsepTransport2::SetLocalIceParameters(
|
||||
IceTransportInternal* ice_transport) {
|
||||
void JsepTransport::SetLocalIceParameters(IceTransportInternal* ice_transport) {
|
||||
RTC_DCHECK(ice_transport);
|
||||
RTC_DCHECK(local_description_);
|
||||
ice_transport->SetIceParameters(
|
||||
local_description_->transport_desc.GetIceParameters());
|
||||
}
|
||||
|
||||
void JsepTransport2::SetRemoteIceParameters(
|
||||
void JsepTransport::SetRemoteIceParameters(
|
||||
IceTransportInternal* ice_transport) {
|
||||
RTC_DCHECK(ice_transport);
|
||||
RTC_DCHECK(remote_description_);
|
||||
@ -344,7 +346,7 @@ void JsepTransport2::SetRemoteIceParameters(
|
||||
ice_transport->SetRemoteIceMode(remote_description_->transport_desc.ice_mode);
|
||||
}
|
||||
|
||||
webrtc::RTCError JsepTransport2::SetNegotiatedDtlsParameters(
|
||||
webrtc::RTCError JsepTransport::SetNegotiatedDtlsParameters(
|
||||
DtlsTransportInternal* dtls_transport,
|
||||
rtc::Optional<rtc::SSLRole> dtls_role,
|
||||
rtc::SSLFingerprint* remote_fingerprint) {
|
||||
@ -367,9 +369,9 @@ webrtc::RTCError JsepTransport2::SetNegotiatedDtlsParameters(
|
||||
return webrtc::RTCError::OK();
|
||||
}
|
||||
|
||||
bool JsepTransport2::SetRtcpMux(bool enable,
|
||||
webrtc::SdpType type,
|
||||
ContentSource source) {
|
||||
bool JsepTransport::SetRtcpMux(bool enable,
|
||||
webrtc::SdpType type,
|
||||
ContentSource source) {
|
||||
bool ret = false;
|
||||
switch (type) {
|
||||
case SdpType::kOffer:
|
||||
@ -399,7 +401,7 @@ bool JsepTransport2::SetRtcpMux(bool enable,
|
||||
return ret;
|
||||
}
|
||||
|
||||
void JsepTransport2::ActivateRtcpMux() {
|
||||
void JsepTransport::ActivateRtcpMux() {
|
||||
if (unencrypted_rtp_transport_) {
|
||||
RTC_DCHECK(!sdes_transport_);
|
||||
RTC_DCHECK(!dtls_srtp_transport_);
|
||||
@ -420,10 +422,10 @@ void JsepTransport2::ActivateRtcpMux() {
|
||||
SignalRtcpMuxActive();
|
||||
}
|
||||
|
||||
bool JsepTransport2::SetSdes(const std::vector<CryptoParams>& cryptos,
|
||||
const std::vector<int>& encrypted_extension_ids,
|
||||
webrtc::SdpType type,
|
||||
ContentSource source) {
|
||||
bool JsepTransport::SetSdes(const std::vector<CryptoParams>& cryptos,
|
||||
const std::vector<int>& encrypted_extension_ids,
|
||||
webrtc::SdpType type,
|
||||
ContentSource source) {
|
||||
bool ret = false;
|
||||
ret = sdes_negotiator_.Process(cryptos, type, source);
|
||||
if (!ret) {
|
||||
@ -464,7 +466,7 @@ bool JsepTransport2::SetSdes(const std::vector<CryptoParams>& cryptos,
|
||||
return ret;
|
||||
}
|
||||
|
||||
webrtc::RTCError JsepTransport2::NegotiateAndSetDtlsParameters(
|
||||
webrtc::RTCError JsepTransport::NegotiateAndSetDtlsParameters(
|
||||
SdpType local_description_type) {
|
||||
if (!local_description_ || !remote_description_) {
|
||||
return webrtc::RTCError(webrtc::RTCErrorType::INVALID_STATE,
|
||||
@ -516,7 +518,7 @@ webrtc::RTCError JsepTransport2::NegotiateAndSetDtlsParameters(
|
||||
return error;
|
||||
}
|
||||
|
||||
webrtc::RTCError JsepTransport2::NegotiateDtlsRole(
|
||||
webrtc::RTCError JsepTransport::NegotiateDtlsRole(
|
||||
SdpType local_description_type,
|
||||
ConnectionRole local_connection_role,
|
||||
ConnectionRole remote_connection_role,
|
||||
@ -604,8 +606,8 @@ webrtc::RTCError JsepTransport2::NegotiateDtlsRole(
|
||||
return webrtc::RTCError::OK();
|
||||
}
|
||||
|
||||
bool JsepTransport2::GetTransportStats(DtlsTransportInternal* dtls_transport,
|
||||
TransportStats* stats) {
|
||||
bool JsepTransport::GetTransportStats(DtlsTransportInternal* dtls_transport,
|
||||
TransportStats* stats) {
|
||||
RTC_DCHECK(dtls_transport);
|
||||
TransportChannelStats substats;
|
||||
substats.component = dtls_transport == rtcp_dtls_transport_.get()
|
||||
@ -8,8 +8,8 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef PC_JSEPTRANSPORT2_H_
|
||||
#define PC_JSEPTRANSPORT2_H_
|
||||
#ifndef PC_JSEPTRANSPORT_H_
|
||||
#define PC_JSEPTRANSPORT_H_
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
@ -68,14 +68,14 @@ struct JsepTransportDescription {
|
||||
// JSEP. Each transport consists of DTLS and ICE transport channels for RTP
|
||||
// (and possibly RTCP, if rtcp-mux isn't used).
|
||||
//
|
||||
// On Threading: JsepTransport performs work solely on the network thread, and
|
||||
// On Threading: JsepTransport performs work solely on the network thread, and
|
||||
// so its methods should only be called on the network thread.
|
||||
class JsepTransport2 : public sigslot::has_slots<> {
|
||||
class JsepTransport : public sigslot::has_slots<> {
|
||||
public:
|
||||
// |mid| is just used for log statements in order to identify the Transport.
|
||||
// Note that |local_certificate| is allowed to be null since a remote
|
||||
// description may be set before a local certificate is generated.
|
||||
JsepTransport2(
|
||||
JsepTransport(
|
||||
const std::string& mid,
|
||||
const rtc::scoped_refptr<rtc::RTCCertificate>& local_certificate,
|
||||
std::unique_ptr<webrtc::RtpTransport> unencrypted_rtp_transport,
|
||||
@ -84,7 +84,7 @@ class JsepTransport2 : public sigslot::has_slots<> {
|
||||
std::unique_ptr<DtlsTransportInternal> rtp_dtls_transport,
|
||||
std::unique_ptr<DtlsTransportInternal> rtcp_dtls_transport);
|
||||
|
||||
~JsepTransport2() override;
|
||||
~JsepTransport() override;
|
||||
|
||||
// Returns the MID of this transport. This is only used for logging.
|
||||
const std::string& mid() const { return mid_; }
|
||||
@ -239,9 +239,9 @@ class JsepTransport2 : public sigslot::has_slots<> {
|
||||
rtc::Optional<std::vector<int>> send_extension_ids_;
|
||||
rtc::Optional<std::vector<int>> recv_extension_ids_;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(JsepTransport2);
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(JsepTransport);
|
||||
};
|
||||
|
||||
} // namespace cricket
|
||||
|
||||
#endif // PC_JSEPTRANSPORT2_H_
|
||||
#endif // PC_JSEPTRANSPORT_H_
|
||||
@ -15,7 +15,7 @@
|
||||
#include "media/base/fakertp.h"
|
||||
#include "p2p/base/fakedtlstransport.h"
|
||||
#include "p2p/base/fakeicetransport.h"
|
||||
#include "pc/jseptransport2.h"
|
||||
#include "pc/jseptransport.h"
|
||||
#include "rtc_base/gunit.h"
|
||||
|
||||
namespace cricket {
|
||||
@ -44,9 +44,8 @@ class JsepTransport2Test : public testing::Test, public sigslot::has_slots<> {
|
||||
std::unique_ptr<webrtc::SrtpTransport> CreateSdesTransport(
|
||||
rtc::PacketTransportInternal* rtp_packet_transport,
|
||||
rtc::PacketTransportInternal* rtcp_packet_transport) {
|
||||
bool rtcp_mux_enabled = (rtcp_packet_transport == nullptr);
|
||||
auto srtp_transport =
|
||||
rtc::MakeUnique<webrtc::SrtpTransport>(rtcp_mux_enabled);
|
||||
auto srtp_transport = rtc::MakeUnique<webrtc::SrtpTransport>(
|
||||
rtcp_packet_transport == nullptr);
|
||||
|
||||
srtp_transport->SetRtpPacketTransport(rtp_packet_transport);
|
||||
if (rtcp_packet_transport) {
|
||||
@ -58,21 +57,17 @@ class JsepTransport2Test : public testing::Test, public sigslot::has_slots<> {
|
||||
std::unique_ptr<webrtc::DtlsSrtpTransport> CreateDtlsSrtpTransport(
|
||||
cricket::DtlsTransportInternal* rtp_dtls_transport,
|
||||
cricket::DtlsTransportInternal* rtcp_dtls_transport) {
|
||||
bool rtcp_mux_enabled = (rtcp_dtls_transport == nullptr);
|
||||
auto srtp_transport =
|
||||
rtc::MakeUnique<webrtc::SrtpTransport>(rtcp_mux_enabled);
|
||||
auto dtls_srtp_transport =
|
||||
rtc::MakeUnique<webrtc::DtlsSrtpTransport>(std::move(srtp_transport));
|
||||
|
||||
auto dtls_srtp_transport = rtc::MakeUnique<webrtc::DtlsSrtpTransport>(
|
||||
rtcp_dtls_transport == nullptr);
|
||||
dtls_srtp_transport->SetDtlsTransports(rtp_dtls_transport,
|
||||
rtcp_dtls_transport);
|
||||
return dtls_srtp_transport;
|
||||
}
|
||||
|
||||
// Create a new JsepTransport2 with a FakeDtlsTransport and a
|
||||
// Create a new JsepTransport with a FakeDtlsTransport and a
|
||||
// FakeIceTransport.
|
||||
std::unique_ptr<JsepTransport2> CreateJsepTransport2(bool rtcp_mux_enabled,
|
||||
SrtpMode srtp_mode) {
|
||||
std::unique_ptr<JsepTransport> CreateJsepTransport2(bool rtcp_mux_enabled,
|
||||
SrtpMode srtp_mode) {
|
||||
auto ice = rtc::MakeUnique<FakeIceTransport>(kTransportName,
|
||||
ICE_CANDIDATE_COMPONENT_RTP);
|
||||
auto rtp_dtls_transport =
|
||||
@ -102,7 +97,7 @@ class JsepTransport2Test : public testing::Test, public sigslot::has_slots<> {
|
||||
RTC_NOTREACHED();
|
||||
}
|
||||
|
||||
auto jsep_transport = rtc::MakeUnique<JsepTransport2>(
|
||||
auto jsep_transport = rtc::MakeUnique<JsepTransport>(
|
||||
kTransportName, /*local_certificate=*/nullptr,
|
||||
std::move(unencrypted_rtp_transport), std::move(sdes_transport),
|
||||
std::move(dtls_srtp_transport), std::move(rtp_dtls_transport),
|
||||
@ -144,7 +139,7 @@ class JsepTransport2Test : public testing::Test, public sigslot::has_slots<> {
|
||||
|
||||
void OnRtcpMuxActive() { signal_rtcp_mux_active_received_ = true; }
|
||||
|
||||
std::unique_ptr<JsepTransport2> jsep_transport_;
|
||||
std::unique_ptr<JsepTransport> jsep_transport_;
|
||||
bool signal_rtcp_mux_active_received_ = false;
|
||||
// The SrtpTransport is owned by |jsep_transport_|. Keep a raw pointer here
|
||||
// for testing.
|
||||
@ -1096,7 +1091,7 @@ class JsepTransport2HeaderExtensionTest
|
||||
}
|
||||
|
||||
void TestOneWaySendRecvPacketWithEncryptedHeaderExtension(
|
||||
JsepTransport2* sender_transport) {
|
||||
JsepTransport* sender_transport) {
|
||||
size_t rtp_len = sizeof(kPcmuFrameWithExtensions);
|
||||
size_t packet_size = rtp_len + GetRtpAuthLen();
|
||||
rtc::Buffer rtp_packet_buffer(packet_size);
|
||||
@ -1119,8 +1114,8 @@ class JsepTransport2HeaderExtensionTest
|
||||
|
||||
int sequence_number_ = 0;
|
||||
int received_packet_count_ = 0;
|
||||
std::unique_ptr<JsepTransport2> jsep_transport1_;
|
||||
std::unique_ptr<JsepTransport2> jsep_transport2_;
|
||||
std::unique_ptr<JsepTransport> jsep_transport1_;
|
||||
std::unique_ptr<JsepTransport> jsep_transport2_;
|
||||
std::vector<int> recv_encrypted_headers1_;
|
||||
std::vector<int> recv_encrypted_headers2_;
|
||||
};
|
||||
@ -94,7 +94,10 @@ JsepTransportController::JsepTransportController(
|
||||
: signaling_thread_(signaling_thread),
|
||||
network_thread_(network_thread),
|
||||
port_allocator_(port_allocator),
|
||||
config_(config) {}
|
||||
config_(config) {
|
||||
// The |transport_observer| is assumed to be non-null.
|
||||
RTC_DCHECK(config_.transport_observer);
|
||||
}
|
||||
|
||||
JsepTransportController::~JsepTransportController() {
|
||||
// Channel destructors may try to send packets, so this needs to happen on
|
||||
@ -181,7 +184,7 @@ void JsepTransportController::SetNeedsIceRestartFlag() {
|
||||
|
||||
bool JsepTransportController::NeedsIceRestart(
|
||||
const std::string& transport_name) const {
|
||||
const cricket::JsepTransport2* transport =
|
||||
const cricket::JsepTransport* transport =
|
||||
GetJsepTransportByName(transport_name);
|
||||
if (!transport) {
|
||||
return false;
|
||||
@ -196,7 +199,7 @@ rtc::Optional<rtc::SSLRole> JsepTransportController::GetDtlsRole(
|
||||
RTC_FROM_HERE, [&] { return GetDtlsRole(mid); });
|
||||
}
|
||||
|
||||
const cricket::JsepTransport2* t = GetJsepTransportForMid(mid);
|
||||
const cricket::JsepTransport* t = GetJsepTransportForMid(mid);
|
||||
if (!t) {
|
||||
return rtc::Optional<rtc::SSLRole>();
|
||||
}
|
||||
@ -237,7 +240,7 @@ JsepTransportController::GetLocalCertificate(
|
||||
RTC_FROM_HERE, [&] { return GetLocalCertificate(transport_name); });
|
||||
}
|
||||
|
||||
const cricket::JsepTransport2* t = GetJsepTransportByName(transport_name);
|
||||
const cricket::JsepTransport* t = GetJsepTransportByName(transport_name);
|
||||
if (!t) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -329,7 +332,7 @@ RTCError JsepTransportController::RemoveRemoteCandidates(
|
||||
for (const auto& kv : candidates_by_transport_name) {
|
||||
const std::string& transport_name = kv.first;
|
||||
const cricket::Candidates& candidates = kv.second;
|
||||
cricket::JsepTransport2* jsep_transport =
|
||||
cricket::JsepTransport* jsep_transport =
|
||||
GetJsepTransportByName(transport_name);
|
||||
if (!jsep_transport) {
|
||||
RTC_LOG(LS_WARNING)
|
||||
@ -355,7 +358,7 @@ bool JsepTransportController::GetStats(const std::string& transport_name,
|
||||
RTC_FROM_HERE, [=] { return GetStats(transport_name, stats); });
|
||||
}
|
||||
|
||||
cricket::JsepTransport2* transport = GetJsepTransportByName(transport_name);
|
||||
cricket::JsepTransport* transport = GetJsepTransportByName(transport_name);
|
||||
if (!transport) {
|
||||
return false;
|
||||
}
|
||||
@ -467,15 +470,12 @@ JsepTransportController::CreateDtlsSrtpTransport(
|
||||
cricket::DtlsTransportInternal* rtp_dtls_transport,
|
||||
cricket::DtlsTransportInternal* rtcp_dtls_transport) {
|
||||
RTC_DCHECK(network_thread_->IsCurrent());
|
||||
auto srtp_transport =
|
||||
rtc::MakeUnique<webrtc::SrtpTransport>(rtcp_dtls_transport == nullptr);
|
||||
auto dtls_srtp_transport = rtc::MakeUnique<webrtc::DtlsSrtpTransport>(
|
||||
rtcp_dtls_transport == nullptr);
|
||||
if (config_.enable_external_auth) {
|
||||
srtp_transport->EnableExternalAuth();
|
||||
dtls_srtp_transport->EnableExternalAuth();
|
||||
}
|
||||
|
||||
auto dtls_srtp_transport =
|
||||
rtc::MakeUnique<webrtc::DtlsSrtpTransport>(std::move(srtp_transport));
|
||||
|
||||
dtls_srtp_transport->SetDtlsTransports(rtp_dtls_transport,
|
||||
rtcp_dtls_transport);
|
||||
return dtls_srtp_transport;
|
||||
@ -574,12 +574,18 @@ RTCError JsepTransportController::ApplyDescription_n(
|
||||
const cricket::TransportInfo& transport_info =
|
||||
description->transport_infos()[i];
|
||||
if (content_info.rejected) {
|
||||
HandleRejectedContent(content_info, description);
|
||||
if (!HandleRejectedContent(content_info, description)) {
|
||||
return RTCError(RTCErrorType::INVALID_PARAMETER,
|
||||
"Failed to process the rejected m= section.");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IsBundled(content_info.name) && content_info.name != *bundled_mid()) {
|
||||
HandleBundledContent(content_info);
|
||||
if (!HandleBundledContent(content_info)) {
|
||||
return RTCError(RTCErrorType::INVALID_PARAMETER,
|
||||
"Failed to process the bundled m= section.");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -598,7 +604,7 @@ RTCError JsepTransportController::ApplyDescription_n(
|
||||
int rtp_abs_sendtime_extn_id =
|
||||
GetRtpAbsSendTimeHeaderExtensionId(content_info);
|
||||
|
||||
cricket::JsepTransport2* transport =
|
||||
cricket::JsepTransport* transport =
|
||||
GetJsepTransportForMid(content_info.name);
|
||||
RTC_DCHECK(transport);
|
||||
|
||||
@ -736,21 +742,20 @@ RTCError JsepTransportController::ValidateContent(
|
||||
return RTCError::OK();
|
||||
}
|
||||
|
||||
void JsepTransportController::HandleRejectedContent(
|
||||
bool JsepTransportController::HandleRejectedContent(
|
||||
const cricket::ContentInfo& content_info,
|
||||
const cricket::SessionDescription* description) {
|
||||
bool ret = true;
|
||||
// If the content is rejected, let the
|
||||
// BaseChannel/SctpTransport change the RtpTransport/DtlsTransport first,
|
||||
// then destroy the cricket::JsepTransport2.
|
||||
RemoveTransportForMid(content_info.name, content_info.type);
|
||||
// If the answerer rejects the first content, which other contents are bundled
|
||||
// on, all the other contents in the bundle group will be rejected.
|
||||
// then destroy the cricket::JsepTransport.
|
||||
ret = RemoveTransportForMid(content_info.name, content_info.type);
|
||||
if (content_info.name == bundled_mid()) {
|
||||
for (auto content_name : bundle_group_->content_names()) {
|
||||
const cricket::ContentInfo* content_in_group =
|
||||
description->GetContentByName(content_name);
|
||||
RTC_DCHECK(content_in_group);
|
||||
RemoveTransportForMid(content_name, content_in_group->type);
|
||||
ret = ret && RemoveTransportForMid(content_name, content_in_group->type);
|
||||
}
|
||||
bundle_group_.reset();
|
||||
} else if (IsBundled(content_info.name)) {
|
||||
@ -761,45 +766,60 @@ void JsepTransportController::HandleRejectedContent(
|
||||
bundle_group_.reset();
|
||||
}
|
||||
}
|
||||
MaybeDestroyJsepTransport(content_info.name);
|
||||
if (ret) {
|
||||
MaybeDestroyJsepTransport(content_info.name);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void JsepTransportController::HandleBundledContent(
|
||||
bool JsepTransportController::HandleBundledContent(
|
||||
const cricket::ContentInfo& content_info) {
|
||||
auto jsep_transport = GetJsepTransportByName(*bundled_mid());
|
||||
RTC_DCHECK(jsep_transport);
|
||||
// If the content is bundled, let the
|
||||
// BaseChannel/SctpTransport change the RtpTransport/DtlsTransport first,
|
||||
// then destroy the cricket::JsepTransport2.
|
||||
SetTransportForMid(content_info.name, jsep_transport, content_info.type);
|
||||
MaybeDestroyJsepTransport(content_info.name);
|
||||
// then destroy the cricket::JsepTransport.
|
||||
if (SetTransportForMid(content_info.name, jsep_transport,
|
||||
content_info.type)) {
|
||||
MaybeDestroyJsepTransport(content_info.name);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void JsepTransportController::SetTransportForMid(
|
||||
bool JsepTransportController::SetTransportForMid(
|
||||
const std::string& mid,
|
||||
cricket::JsepTransport2* jsep_transport,
|
||||
cricket::JsepTransport* jsep_transport,
|
||||
cricket::MediaProtocolType protocol_type) {
|
||||
RTC_DCHECK(jsep_transport);
|
||||
if (mid_to_transport_[mid] == jsep_transport) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ret = true;
|
||||
mid_to_transport_[mid] = jsep_transport;
|
||||
if (protocol_type == cricket::MediaProtocolType::kRtp) {
|
||||
SignalRtpTransportChanged(mid, jsep_transport->rtp_transport());
|
||||
ret = config_.transport_observer->OnRtpTransportChanged(
|
||||
mid, jsep_transport->rtp_transport());
|
||||
} else {
|
||||
SignalDtlsTransportChanged(mid, jsep_transport->rtp_dtls_transport());
|
||||
config_.transport_observer->OnDtlsTransportChanged(
|
||||
mid, jsep_transport->rtp_dtls_transport());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void JsepTransportController::RemoveTransportForMid(
|
||||
bool JsepTransportController::RemoveTransportForMid(
|
||||
const std::string& mid,
|
||||
cricket::MediaProtocolType protocol_type) {
|
||||
bool ret = true;
|
||||
if (protocol_type == cricket::MediaProtocolType::kRtp) {
|
||||
SignalRtpTransportChanged(mid, nullptr);
|
||||
ret = config_.transport_observer->OnRtpTransportChanged(mid, nullptr);
|
||||
RTC_DCHECK(ret);
|
||||
} else {
|
||||
SignalDtlsTransportChanged(mid, nullptr);
|
||||
config_.transport_observer->OnDtlsTransportChanged(mid, nullptr);
|
||||
}
|
||||
mid_to_transport_.erase(mid);
|
||||
return ret;
|
||||
}
|
||||
|
||||
cricket::JsepTransportDescription
|
||||
@ -905,25 +925,25 @@ int JsepTransportController::GetRtpAbsSendTimeHeaderExtensionId(
|
||||
return send_time_extension ? send_time_extension->id : -1;
|
||||
}
|
||||
|
||||
const cricket::JsepTransport2* JsepTransportController::GetJsepTransportForMid(
|
||||
const cricket::JsepTransport* JsepTransportController::GetJsepTransportForMid(
|
||||
const std::string& mid) const {
|
||||
auto it = mid_to_transport_.find(mid);
|
||||
return it == mid_to_transport_.end() ? nullptr : it->second;
|
||||
}
|
||||
|
||||
cricket::JsepTransport2* JsepTransportController::GetJsepTransportForMid(
|
||||
cricket::JsepTransport* JsepTransportController::GetJsepTransportForMid(
|
||||
const std::string& mid) {
|
||||
auto it = mid_to_transport_.find(mid);
|
||||
return it == mid_to_transport_.end() ? nullptr : it->second;
|
||||
}
|
||||
|
||||
const cricket::JsepTransport2* JsepTransportController::GetJsepTransportByName(
|
||||
const cricket::JsepTransport* JsepTransportController::GetJsepTransportByName(
|
||||
const std::string& transport_name) const {
|
||||
auto it = jsep_transports_by_name_.find(transport_name);
|
||||
return (it == jsep_transports_by_name_.end()) ? nullptr : it->second.get();
|
||||
}
|
||||
|
||||
cricket::JsepTransport2* JsepTransportController::GetJsepTransportByName(
|
||||
cricket::JsepTransport* JsepTransportController::GetJsepTransportByName(
|
||||
const std::string& transport_name) {
|
||||
auto it = jsep_transports_by_name_.find(transport_name);
|
||||
return (it == jsep_transports_by_name_.end()) ? nullptr : it->second.get();
|
||||
@ -932,8 +952,7 @@ cricket::JsepTransport2* JsepTransportController::GetJsepTransportByName(
|
||||
RTCError JsepTransportController::MaybeCreateJsepTransport(
|
||||
const cricket::ContentInfo& content_info) {
|
||||
RTC_DCHECK(network_thread_->IsCurrent());
|
||||
cricket::JsepTransport2* transport =
|
||||
GetJsepTransportByName(content_info.name);
|
||||
cricket::JsepTransport* transport = GetJsepTransportByName(content_info.name);
|
||||
if (transport) {
|
||||
return RTCError::OK();
|
||||
}
|
||||
@ -970,8 +989,8 @@ RTCError JsepTransportController::MaybeCreateJsepTransport(
|
||||
content_info.name, rtp_dtls_transport.get(), rtcp_dtls_transport.get());
|
||||
}
|
||||
|
||||
std::unique_ptr<cricket::JsepTransport2> jsep_transport =
|
||||
rtc::MakeUnique<cricket::JsepTransport2>(
|
||||
std::unique_ptr<cricket::JsepTransport> jsep_transport =
|
||||
rtc::MakeUnique<cricket::JsepTransport>(
|
||||
content_info.name, certificate_, std::move(unencrypted_rtp_transport),
|
||||
std::move(sdes_transport), std::move(dtls_srtp_transport),
|
||||
std::move(rtp_dtls_transport), std::move(rtcp_dtls_transport));
|
||||
@ -1018,7 +1037,7 @@ void JsepTransportController::SetIceRole_n(cricket::IceRole ice_role) {
|
||||
}
|
||||
|
||||
cricket::IceRole JsepTransportController::DetermineIceRole(
|
||||
cricket::JsepTransport2* jsep_transport,
|
||||
cricket::JsepTransport* jsep_transport,
|
||||
const cricket::TransportInfo& transport_info,
|
||||
SdpType type,
|
||||
bool local) {
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
#include "p2p/base/transportfactoryinterface.h"
|
||||
#include "pc/channel.h"
|
||||
#include "pc/dtlssrtptransport.h"
|
||||
#include "pc/jseptransport2.h"
|
||||
#include "pc/jseptransport.h"
|
||||
#include "pc/rtptransport.h"
|
||||
#include "pc/srtptransport.h"
|
||||
#include "rtc_base/asyncinvoker.h"
|
||||
@ -44,6 +44,23 @@ namespace webrtc {
|
||||
class JsepTransportController : public sigslot::has_slots<>,
|
||||
public rtc::MessageHandler {
|
||||
public:
|
||||
// Used when the RtpTransport/DtlsTransport of the m= section is changed
|
||||
// because the section is rejected or BUNDLE is enabled.
|
||||
class Observer {
|
||||
public:
|
||||
virtual ~Observer() {}
|
||||
|
||||
// Returns true if media associated with |mid| was successfully set up to be
|
||||
// demultiplexed on |rtp_transport|. Could return false if two bundled m=
|
||||
// sections use the same SSRC, for example.
|
||||
virtual bool OnRtpTransportChanged(const std::string& mid,
|
||||
RtpTransportInternal* rtp_transport) = 0;
|
||||
|
||||
virtual void OnDtlsTransportChanged(
|
||||
const std::string& mid,
|
||||
cricket::DtlsTransportInternal* dtls_transport) = 0;
|
||||
};
|
||||
|
||||
struct Config {
|
||||
// If |redetermine_role_on_ice_restart| is true, ICE role is redetermined
|
||||
// upon setting a local transport description that indicates an ICE
|
||||
@ -61,6 +78,7 @@ class JsepTransportController : public sigslot::has_slots<>,
|
||||
bool enable_external_auth = false;
|
||||
// Used to inject the ICE/DTLS transports created externally.
|
||||
cricket::TransportFactoryInterface* external_transport_factory = nullptr;
|
||||
Observer* transport_observer = nullptr;
|
||||
};
|
||||
|
||||
// The ICE related events are signaled on the |signaling_thread|.
|
||||
@ -136,6 +154,7 @@ class JsepTransportController : public sigslot::has_slots<>,
|
||||
void SetMetricsObserver(webrtc::MetricsObserverInterface* metrics_observer);
|
||||
|
||||
bool initial_offerer() const { return initial_offerer_ && *initial_offerer_; }
|
||||
|
||||
// All of these signals are fired on the signaling thread.
|
||||
|
||||
// If any transport failed => failed,
|
||||
@ -158,19 +177,6 @@ class JsepTransportController : public sigslot::has_slots<>,
|
||||
|
||||
sigslot::signal1<rtc::SSLHandshakeError> SignalDtlsHandshakeError;
|
||||
|
||||
// This will be fired when BUNDLE is enabled, the PeerConnection will handle
|
||||
// the signal and set the RtpTransport for the BaseChannel.
|
||||
// The first argument is the MID and the second is the new RtpTransport.
|
||||
// Before firing this signal, the previous RtpTransport must no longer be
|
||||
// referenced.
|
||||
sigslot::signal2<const std::string&, RtpTransportInternal*>
|
||||
SignalRtpTransportChanged;
|
||||
|
||||
// SCTP version of the signal above. PeerConnection will set a new
|
||||
// DtlsTransport for the SctpTransport.
|
||||
sigslot::signal2<const std::string&, cricket::DtlsTransportInternal*>
|
||||
SignalDtlsTransportChanged;
|
||||
|
||||
private:
|
||||
void OnMessage(rtc::Message* pmsg) override;
|
||||
|
||||
@ -183,14 +189,14 @@ class JsepTransportController : public sigslot::has_slots<>,
|
||||
const cricket::SessionDescription* description);
|
||||
RTCError ValidateContent(const cricket::ContentInfo& content_info);
|
||||
|
||||
void HandleRejectedContent(const cricket::ContentInfo& content_info,
|
||||
bool HandleRejectedContent(const cricket::ContentInfo& content_info,
|
||||
const cricket::SessionDescription* description);
|
||||
void HandleBundledContent(const cricket::ContentInfo& content_info);
|
||||
bool HandleBundledContent(const cricket::ContentInfo& content_info);
|
||||
|
||||
void SetTransportForMid(const std::string& mid,
|
||||
cricket::JsepTransport2* jsep_transport,
|
||||
bool SetTransportForMid(const std::string& mid,
|
||||
cricket::JsepTransport* jsep_transport,
|
||||
cricket::MediaProtocolType protocol_type);
|
||||
void RemoveTransportForMid(const std::string& mid,
|
||||
bool RemoveTransportForMid(const std::string& mid,
|
||||
cricket::MediaProtocolType protocol_type);
|
||||
|
||||
cricket::JsepTransportDescription CreateJsepTransportDescription(
|
||||
@ -226,15 +232,15 @@ class JsepTransportController : public sigslot::has_slots<>,
|
||||
// destroyed because of BUNDLE, it would return the transport which other
|
||||
// transports are bundled on (In current implementation, it is the first
|
||||
// content in the BUNDLE group).
|
||||
const cricket::JsepTransport2* GetJsepTransportForMid(
|
||||
const cricket::JsepTransport* GetJsepTransportForMid(
|
||||
const std::string& mid) const;
|
||||
cricket::JsepTransport2* GetJsepTransportForMid(const std::string& mid);
|
||||
cricket::JsepTransport* GetJsepTransportForMid(const std::string& mid);
|
||||
|
||||
// Get the JsepTransport without considering the BUNDLE group. Return nullptr
|
||||
// if the JsepTransport is destroyed.
|
||||
const cricket::JsepTransport2* GetJsepTransportByName(
|
||||
const cricket::JsepTransport* GetJsepTransportByName(
|
||||
const std::string& transport_name) const;
|
||||
cricket::JsepTransport2* GetJsepTransportByName(
|
||||
cricket::JsepTransport* GetJsepTransportByName(
|
||||
const std::string& transport_name);
|
||||
|
||||
RTCError MaybeCreateJsepTransport(const cricket::ContentInfo& content_info);
|
||||
@ -244,7 +250,7 @@ class JsepTransportController : public sigslot::has_slots<>,
|
||||
void SetIceRole_n(cricket::IceRole ice_role);
|
||||
|
||||
cricket::IceRole DetermineIceRole(
|
||||
cricket::JsepTransport2* jsep_transport,
|
||||
cricket::JsepTransport* jsep_transport,
|
||||
const cricket::TransportInfo& transport_info,
|
||||
SdpType type,
|
||||
bool local);
|
||||
@ -291,11 +297,11 @@ class JsepTransportController : public sigslot::has_slots<>,
|
||||
rtc::Thread* const network_thread_ = nullptr;
|
||||
cricket::PortAllocator* const port_allocator_ = nullptr;
|
||||
|
||||
std::map<std::string, std::unique_ptr<cricket::JsepTransport2>>
|
||||
std::map<std::string, std::unique_ptr<cricket::JsepTransport>>
|
||||
jsep_transports_by_name_;
|
||||
// This keeps track of the mapping between media section
|
||||
// (BaseChannel/SctpTransport) and the JsepTransport2 underneath.
|
||||
std::map<std::string, cricket::JsepTransport2*> mid_to_transport_;
|
||||
// (BaseChannel/SctpTransport) and the JsepTransport underneath.
|
||||
std::map<std::string, cricket::JsepTransport*> mid_to_transport_;
|
||||
|
||||
// Aggregate state for Transports.
|
||||
cricket::IceConnectionState ice_connection_state_ =
|
||||
|
||||
@ -59,7 +59,8 @@ class FakeTransportFactory : public cricket::TransportFactoryInterface {
|
||||
}
|
||||
};
|
||||
|
||||
class JsepTransportControllerTest : public testing::Test,
|
||||
class JsepTransportControllerTest : public JsepTransportController::Observer,
|
||||
public testing::Test,
|
||||
public sigslot::has_slots<> {
|
||||
public:
|
||||
JsepTransportControllerTest() : signaling_thread_(rtc::Thread::Current()) {
|
||||
@ -71,6 +72,7 @@ class JsepTransportControllerTest : public testing::Test,
|
||||
rtc::Thread* signaling_thread = rtc::Thread::Current(),
|
||||
rtc::Thread* network_thread = rtc::Thread::Current(),
|
||||
cricket::PortAllocator* port_allocator = nullptr) {
|
||||
config.transport_observer = this;
|
||||
// The tests only works with |fake_transport_factory|;
|
||||
config.external_transport_factory = fake_transport_factory_.get();
|
||||
transport_controller_ = rtc::MakeUnique<JsepTransportController>(
|
||||
@ -85,10 +87,6 @@ class JsepTransportControllerTest : public testing::Test,
|
||||
this, &JsepTransportControllerTest::OnGatheringState);
|
||||
transport_controller_->SignalIceCandidatesGathered.connect(
|
||||
this, &JsepTransportControllerTest::OnCandidatesGathered);
|
||||
transport_controller_->SignalRtpTransportChanged.connect(
|
||||
this, &JsepTransportControllerTest::OnRtpTransportChanged);
|
||||
transport_controller_->SignalDtlsTransportChanged.connect(
|
||||
this, &JsepTransportControllerTest::OnDtlsTransportChanged);
|
||||
}
|
||||
|
||||
std::unique_ptr<cricket::SessionDescription>
|
||||
@ -262,13 +260,16 @@ class JsepTransportControllerTest : public testing::Test,
|
||||
++candidates_signal_count_;
|
||||
}
|
||||
|
||||
void OnRtpTransportChanged(const std::string& mid,
|
||||
RtpTransportInternal* rtp_transport) {
|
||||
// JsepTransportController::Observer overrides.
|
||||
bool OnRtpTransportChanged(const std::string& mid,
|
||||
RtpTransportInternal* rtp_transport) override {
|
||||
changed_rtp_transport_by_mid_[mid] = rtp_transport;
|
||||
return true;
|
||||
}
|
||||
|
||||
void OnDtlsTransportChanged(const std::string& mid,
|
||||
cricket::DtlsTransportInternal* dtls_transport) {
|
||||
void OnDtlsTransportChanged(
|
||||
const std::string& mid,
|
||||
cricket::DtlsTransportInternal* dtls_transport) override {
|
||||
changed_dtls_transport_by_mid_[mid] = dtls_transport;
|
||||
}
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
#include "media/base/mediaconstants.h"
|
||||
#include "media/base/mediaengine.h" // For DataChannelType
|
||||
#include "p2p/base/transportdescriptionfactory.h"
|
||||
#include "pc/jseptransport2.h"
|
||||
#include "pc/jseptransport.h"
|
||||
#include "pc/sessiondescription.h"
|
||||
|
||||
namespace cricket {
|
||||
|
||||
@ -932,6 +932,7 @@ bool PeerConnection::Initialize(
|
||||
config.bundle_policy = configuration.bundle_policy;
|
||||
config.rtcp_mux_policy = configuration.rtcp_mux_policy;
|
||||
config.crypto_options = options.crypto_options;
|
||||
config.transport_observer = this;
|
||||
#if defined(ENABLE_EXTERNAL_AUTH)
|
||||
config.enable_external_auth = true;
|
||||
#endif
|
||||
@ -947,10 +948,6 @@ bool PeerConnection::Initialize(
|
||||
this, &PeerConnection::OnTransportControllerCandidatesRemoved);
|
||||
transport_controller_->SignalDtlsHandshakeError.connect(
|
||||
this, &PeerConnection::OnTransportControllerDtlsHandshakeError);
|
||||
transport_controller_->SignalRtpTransportChanged.connect(
|
||||
this, &PeerConnection::OnRtpTransportChanged);
|
||||
transport_controller_->SignalDtlsTransportChanged.connect(
|
||||
this, &PeerConnection::OnDtlsTransportChanged);
|
||||
|
||||
sctp_factory_ = factory_->CreateSctpTransportInternalFactory();
|
||||
|
||||
@ -5430,9 +5427,6 @@ cricket::VoiceChannel* PeerConnection::CreateVoiceChannel(
|
||||
voice_channel->SignalSentPacket.connect(this,
|
||||
&PeerConnection::OnSentPacket_w);
|
||||
voice_channel->SetRtpTransport(rtp_transport);
|
||||
if (factory_->options().disable_encryption) {
|
||||
voice_channel->DisableEncryption(true);
|
||||
}
|
||||
if (uma_observer_) {
|
||||
voice_channel->SetMetricsObserver(uma_observer_);
|
||||
}
|
||||
@ -5458,9 +5452,6 @@ cricket::VideoChannel* PeerConnection::CreateVideoChannel(
|
||||
video_channel->SignalSentPacket.connect(this,
|
||||
&PeerConnection::OnSentPacket_w);
|
||||
video_channel->SetRtpTransport(rtp_transport);
|
||||
if (factory_->options().disable_encryption) {
|
||||
video_channel->DisableEncryption(true);
|
||||
}
|
||||
if (uma_observer_) {
|
||||
video_channel->SetMetricsObserver(uma_observer_);
|
||||
}
|
||||
@ -5500,9 +5491,6 @@ bool PeerConnection::CreateDataChannel(const std::string& mid) {
|
||||
rtp_data_channel_->SignalSentPacket.connect(
|
||||
this, &PeerConnection::OnSentPacket_w);
|
||||
rtp_data_channel_->SetRtpTransport(rtp_transport);
|
||||
if (factory_->options().disable_encryption) {
|
||||
rtp_data_channel_->DisableEncryption(true);
|
||||
}
|
||||
if (uma_observer_) {
|
||||
rtp_data_channel_->SetMetricsObserver(uma_observer_);
|
||||
}
|
||||
@ -6100,7 +6088,6 @@ void PeerConnection::DestroyDataChannel() {
|
||||
|
||||
void PeerConnection::DestroyBaseChannel(cricket::BaseChannel* channel) {
|
||||
RTC_DCHECK(channel);
|
||||
|
||||
switch (channel->media_type()) {
|
||||
case cricket::MEDIA_TYPE_AUDIO:
|
||||
channel_manager()->DestroyVoiceChannel(
|
||||
@ -6120,13 +6107,14 @@ void PeerConnection::DestroyBaseChannel(cricket::BaseChannel* channel) {
|
||||
}
|
||||
}
|
||||
|
||||
void PeerConnection::OnRtpTransportChanged(
|
||||
bool PeerConnection::OnRtpTransportChanged(
|
||||
const std::string& mid,
|
||||
RtpTransportInternal* rtp_transport) {
|
||||
auto base_channel = GetChannel(mid);
|
||||
if (base_channel) {
|
||||
base_channel->SetRtpTransport(rtp_transport);
|
||||
return base_channel->SetRtpTransport(rtp_transport);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PeerConnection::OnDtlsTransportChanged(
|
||||
|
||||
@ -51,6 +51,7 @@ class RtcEventLog;
|
||||
// - Generating stats.
|
||||
class PeerConnection : public PeerConnectionInternal,
|
||||
public DataChannelProviderInterface,
|
||||
public JsepTransportController::Observer,
|
||||
public rtc::MessageHandler,
|
||||
public sigslot::has_slots<> {
|
||||
public:
|
||||
@ -877,11 +878,13 @@ class PeerConnection : public PeerConnectionInternal,
|
||||
// method is called.
|
||||
void DestroyBaseChannel(cricket::BaseChannel* channel);
|
||||
|
||||
void OnRtpTransportChanged(const std::string& mid,
|
||||
RtpTransportInternal* rtp_transport);
|
||||
// JsepTransportController::Observer override.
|
||||
bool OnRtpTransportChanged(const std::string& mid,
|
||||
RtpTransportInternal* rtp_transport) override;
|
||||
|
||||
void OnDtlsTransportChanged(const std::string& mid,
|
||||
cricket::DtlsTransportInternal* dtls_transport);
|
||||
void OnDtlsTransportChanged(
|
||||
const std::string& mid,
|
||||
cricket::DtlsTransportInternal* dtls_transport) override;
|
||||
|
||||
sigslot::signal1<DataChannel*> SignalDataChannelCreated_;
|
||||
|
||||
|
||||
@ -666,6 +666,42 @@ TEST_P(PeerConnectionBundleTest, BundleOnFirstMidInAnswer) {
|
||||
EXPECT_EQ(caller->voice_rtp_transport(), caller->video_rtp_transport());
|
||||
}
|
||||
|
||||
// This tests that applying description with conflicted RTP demuxing criteria
|
||||
// will fail.
|
||||
TEST_P(PeerConnectionBundleTest,
|
||||
ApplyDescriptionWithConflictedDemuxCriteriaFail) {
|
||||
auto caller = CreatePeerConnectionWithAudioVideo();
|
||||
auto callee = CreatePeerConnectionWithAudioVideo();
|
||||
|
||||
RTCOfferAnswerOptions options;
|
||||
options.use_rtp_mux = false;
|
||||
auto offer = caller->CreateOffer(options);
|
||||
// Modified the SDP to make two m= sections have the same SSRC.
|
||||
ASSERT_GE(offer->description()->contents().size(), 2U);
|
||||
offer->description()
|
||||
->contents()[0]
|
||||
.description->mutable_streams()[0]
|
||||
.ssrcs[0] = 1111222;
|
||||
offer->description()
|
||||
->contents()[1]
|
||||
.description->mutable_streams()[0]
|
||||
.ssrcs[0] = 1111222;
|
||||
EXPECT_TRUE(
|
||||
caller->SetLocalDescription(CloneSessionDescription(offer.get())));
|
||||
EXPECT_TRUE(callee->SetRemoteDescription(std::move(offer)));
|
||||
EXPECT_TRUE(callee->CreateAnswerAndSetAsLocal(options));
|
||||
|
||||
// Enable BUNDLE in subsequent offer/answer exchange and two m= sections are
|
||||
// expectd to use one RtpTransport underneath.
|
||||
options.use_rtp_mux = true;
|
||||
EXPECT_TRUE(
|
||||
callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal(options)));
|
||||
auto answer = callee->CreateAnswer(options);
|
||||
// When BUNDLE is enabled, applying the description is expected to fail
|
||||
// because the demuxing criteria is conflicted.
|
||||
EXPECT_FALSE(callee->SetLocalDescription(std::move(answer)));
|
||||
}
|
||||
|
||||
// This tests that changing the pre-negotiated BUNDLE tag is not supported.
|
||||
TEST_P(PeerConnectionBundleTest, RejectDescriptionChangingBundleTag) {
|
||||
RTCConfiguration config;
|
||||
|
||||
@ -2273,6 +2273,8 @@ TEST_F(PeerConnectionIntegrationTestUnifiedPlan,
|
||||
|
||||
// Test that if two video tracks are sent (from caller to callee, in this test),
|
||||
// they're transmitted correctly end-to-end.
|
||||
// TODO(zhihuang): Enable this test in Unified Plan mode once the MID-based
|
||||
// demuxing is ready.
|
||||
TEST_P(PeerConnectionIntegrationTest, EndToEndCallWithTwoVideoTracks) {
|
||||
ASSERT_TRUE(CreatePeerConnectionWrappers());
|
||||
ConnectFakeSignaling();
|
||||
@ -2395,7 +2397,6 @@ TEST_P(PeerConnectionIntegrationTest, GetBytesReceivedStatsWithOldStatsApi) {
|
||||
TEST_P(PeerConnectionIntegrationTest, GetBytesSentStatsWithOldStatsApi) {
|
||||
ASSERT_TRUE(CreatePeerConnectionWrappers());
|
||||
ConnectFakeSignaling();
|
||||
caller()->AddAudioVideoTracks();
|
||||
auto audio_track = caller()->CreateLocalAudioTrack();
|
||||
auto video_track = caller()->CreateLocalVideoTrack();
|
||||
caller()->AddTrack(audio_track);
|
||||
|
||||
@ -967,8 +967,8 @@ void RenameContent(cricket::SessionDescription* desc,
|
||||
|
||||
// Tests that an answer responds with the same MIDs as the offer.
|
||||
TEST_P(PeerConnectionMediaTest, AnswerHasSameMidsAsOffer) {
|
||||
const std::string kAudioMid = "not default1";
|
||||
const std::string kVideoMid = "not default2";
|
||||
const std::string kAudioMid = "notdefault1";
|
||||
const std::string kVideoMid = "notdefault2";
|
||||
|
||||
auto caller = CreatePeerConnectionWithAudioVideo();
|
||||
auto callee = CreatePeerConnectionWithAudioVideo();
|
||||
@ -988,8 +988,8 @@ TEST_P(PeerConnectionMediaTest, AnswerHasSameMidsAsOffer) {
|
||||
// Test that if the callee creates a re-offer, the MIDs are the same as the
|
||||
// original offer.
|
||||
TEST_P(PeerConnectionMediaTest, ReOfferHasSameMidsAsFirstOffer) {
|
||||
const std::string kAudioMid = "not default1";
|
||||
const std::string kVideoMid = "not default2";
|
||||
const std::string kAudioMid = "notdefault1";
|
||||
const std::string kVideoMid = "notdefault2";
|
||||
|
||||
auto caller = CreatePeerConnectionWithAudioVideo();
|
||||
auto callee = CreatePeerConnectionWithAudioVideo();
|
||||
|
||||
@ -113,12 +113,8 @@ class RtpSenderReceiverTest : public testing::Test,
|
||||
}
|
||||
|
||||
std::unique_ptr<webrtc::RtpTransportInternal> CreateDtlsSrtpTransport() {
|
||||
auto rtp_transport =
|
||||
rtc::MakeUnique<webrtc::RtpTransport>(/*rtcp_mux_required=*/true);
|
||||
auto srtp_transport =
|
||||
rtc::MakeUnique<webrtc::SrtpTransport>(std::move(rtp_transport));
|
||||
auto dtls_srtp_transport =
|
||||
rtc::MakeUnique<webrtc::DtlsSrtpTransport>(std::move(srtp_transport));
|
||||
rtc::MakeUnique<webrtc::DtlsSrtpTransport>(/*rtcp_mux_required=*/true);
|
||||
dtls_srtp_transport->SetDtlsTransports(rtp_dtls_transport_.get(),
|
||||
/*rtcp_dtls_transport=*/nullptr);
|
||||
return dtls_srtp_transport;
|
||||
|
||||
@ -10,7 +10,10 @@
|
||||
|
||||
#include "pc/rtptransport.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "media/base/rtputils.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
|
||||
#include "p2p/base/p2pconstants.h"
|
||||
#include "p2p/base/packettransportinterface.h"
|
||||
#include "rtc_base/checks.h"
|
||||
@ -44,7 +47,7 @@ void RtpTransport::SetRtpPacketTransport(
|
||||
new_packet_transport->SignalReadPacket.connect(this,
|
||||
&RtpTransport::OnReadPacket);
|
||||
new_packet_transport->SignalNetworkRouteChanged.connect(
|
||||
this, &RtpTransport::OnNetworkRouteChange);
|
||||
this, &RtpTransport::OnNetworkRouteChanged);
|
||||
new_packet_transport->SignalWritableState.connect(
|
||||
this, &RtpTransport::OnWritableState);
|
||||
new_packet_transport->SignalSentPacket.connect(this,
|
||||
@ -80,7 +83,7 @@ void RtpTransport::SetRtcpPacketTransport(
|
||||
new_packet_transport->SignalReadPacket.connect(this,
|
||||
&RtpTransport::OnReadPacket);
|
||||
new_packet_transport->SignalNetworkRouteChanged.connect(
|
||||
this, &RtpTransport::OnNetworkRouteChange);
|
||||
this, &RtpTransport::OnNetworkRouteChanged);
|
||||
new_packet_transport->SignalWritableState.connect(
|
||||
this, &RtpTransport::OnWritableState);
|
||||
new_packet_transport->SignalSentPacket.connect(this,
|
||||
@ -134,6 +137,29 @@ bool RtpTransport::SendPacket(bool rtcp,
|
||||
return true;
|
||||
}
|
||||
|
||||
void RtpTransport::UpdateRtpHeaderExtensionMap(
|
||||
const cricket::RtpHeaderExtensions& header_extensions) {
|
||||
header_extension_map_ = RtpHeaderExtensionMap(header_extensions);
|
||||
}
|
||||
|
||||
bool RtpTransport::RegisterRtpDemuxerSink(const RtpDemuxerCriteria& criteria,
|
||||
RtpPacketSinkInterface* sink) {
|
||||
rtp_demuxer_.RemoveSink(sink);
|
||||
if (!rtp_demuxer_.AddSink(criteria, sink)) {
|
||||
RTC_LOG(LS_ERROR) << "Failed to register the sink for RTP demuxer.";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RtpTransport::UnregisterRtpDemuxerSink(RtpPacketSinkInterface* sink) {
|
||||
if (!rtp_demuxer_.RemoveSink(sink)) {
|
||||
RTC_LOG(LS_ERROR) << "Failed to unregister the sink for RTP demuxer.";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
RTCError RtpTransport::SetParameters(const RtpTransportParameters& parameters) {
|
||||
if (parameters_.rtcp.mux && !parameters.rtcp.mux) {
|
||||
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
|
||||
@ -160,11 +186,26 @@ RtpTransportParameters RtpTransport::GetParameters() const {
|
||||
return parameters_;
|
||||
}
|
||||
|
||||
void RtpTransport::DemuxPacket(rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketTime& time) {
|
||||
webrtc::RtpPacketReceived parsed_packet(&header_extension_map_);
|
||||
if (!parsed_packet.Parse(std::move(*packet))) {
|
||||
RTC_LOG(LS_ERROR)
|
||||
<< "Failed to parse the incoming RTP packet before demuxing. Drop it.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (time.timestamp != -1) {
|
||||
parsed_packet.set_arrival_time_ms((time.timestamp + 500) / 1000);
|
||||
}
|
||||
rtp_demuxer_.OnRtpPacket(parsed_packet);
|
||||
}
|
||||
|
||||
RtpTransportAdapter* RtpTransport::GetInternal() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool RtpTransport::IsRtpTransportWritable() {
|
||||
bool RtpTransport::IsTransportWritable() {
|
||||
auto rtcp_packet_transport =
|
||||
rtcp_mux_enabled_ ? nullptr : rtcp_packet_transport_;
|
||||
return rtp_packet_transport_ && rtp_packet_transport_->writable() &&
|
||||
@ -175,7 +216,7 @@ void RtpTransport::OnReadyToSend(rtc::PacketTransportInternal* transport) {
|
||||
SetReadyToSend(transport == rtcp_packet_transport_, true);
|
||||
}
|
||||
|
||||
void RtpTransport::OnNetworkRouteChange(
|
||||
void RtpTransport::OnNetworkRouteChanged(
|
||||
rtc::Optional<rtc::NetworkRoute> network_route) {
|
||||
SignalNetworkRouteChanged(network_route);
|
||||
}
|
||||
@ -184,7 +225,7 @@ void RtpTransport::OnWritableState(
|
||||
rtc::PacketTransportInternal* packet_transport) {
|
||||
RTC_DCHECK(packet_transport == rtp_packet_transport_ ||
|
||||
packet_transport == rtcp_packet_transport_);
|
||||
SignalWritableState(IsRtpTransportWritable());
|
||||
SignalWritableState(IsTransportWritable());
|
||||
}
|
||||
|
||||
void RtpTransport::OnSentPacket(rtc::PacketTransportInternal* packet_transport,
|
||||
@ -194,6 +235,49 @@ void RtpTransport::OnSentPacket(rtc::PacketTransportInternal* packet_transport,
|
||||
SignalSentPacket(sent_packet);
|
||||
}
|
||||
|
||||
void RtpTransport::OnRtpPacketReceived(rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketTime& packet_time) {
|
||||
DemuxPacket(packet, packet_time);
|
||||
}
|
||||
|
||||
void RtpTransport::OnRtcpPacketReceived(rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketTime& packet_time) {
|
||||
SignalRtcpPacketReceived(packet, packet_time);
|
||||
}
|
||||
|
||||
void RtpTransport::OnReadPacket(rtc::PacketTransportInternal* transport,
|
||||
const char* data,
|
||||
size_t len,
|
||||
const rtc::PacketTime& packet_time,
|
||||
int flags) {
|
||||
TRACE_EVENT0("webrtc", "RtpTransport::OnReadPacket");
|
||||
|
||||
// When using RTCP multiplexing we might get RTCP packets on the RTP
|
||||
// transport. We check the RTP payload type to determine if it is RTCP.
|
||||
bool rtcp =
|
||||
transport == rtcp_packet_transport() || cricket::IsRtcpPacket(data, len);
|
||||
|
||||
// Filter out the packet that is neither RTP nor RTCP.
|
||||
if (!rtcp && !cricket::IsRtpPacket(data, len)) {
|
||||
return;
|
||||
}
|
||||
|
||||
rtc::CopyOnWriteBuffer packet(data, len);
|
||||
// Protect ourselves against crazy data.
|
||||
if (!cricket::IsValidRtpRtcpPacketSize(rtcp, packet.size())) {
|
||||
RTC_LOG(LS_ERROR) << "Dropping incoming "
|
||||
<< cricket::RtpRtcpStringLiteral(rtcp)
|
||||
<< " packet: wrong size=" << packet.size();
|
||||
return;
|
||||
}
|
||||
|
||||
if (rtcp) {
|
||||
OnRtcpPacketReceived(&packet, packet_time);
|
||||
} else {
|
||||
OnRtpPacketReceived(&packet, packet_time);
|
||||
}
|
||||
}
|
||||
|
||||
void RtpTransport::SetReadyToSend(bool rtcp, bool ready) {
|
||||
if (rtcp) {
|
||||
rtcp_ready_to_send_ = ready;
|
||||
@ -213,52 +297,4 @@ void RtpTransport::MaybeSignalReadyToSend() {
|
||||
}
|
||||
}
|
||||
|
||||
// Check the RTP payload type. If 63 < payload type < 96, it's RTCP.
|
||||
// For additional details, see http://tools.ietf.org/html/rfc5761.
|
||||
bool IsRtcp(const char* data, int len) {
|
||||
if (len < 2) {
|
||||
return false;
|
||||
}
|
||||
char pt = data[1] & 0x7F;
|
||||
return (63 < pt) && (pt < 96);
|
||||
}
|
||||
|
||||
void RtpTransport::OnReadPacket(rtc::PacketTransportInternal* transport,
|
||||
const char* data,
|
||||
size_t len,
|
||||
const rtc::PacketTime& packet_time,
|
||||
int flags) {
|
||||
TRACE_EVENT0("webrtc", "RtpTransport::OnReadPacket");
|
||||
|
||||
if (!cricket::IsRtpPacket(data, len) &&
|
||||
!IsRtcp(data, static_cast<int>(len))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// When using RTCP multiplexing we might get RTCP packets on the RTP
|
||||
// transport. We check the RTP payload type to determine if it is RTCP.
|
||||
bool rtcp = transport == rtcp_packet_transport() ||
|
||||
IsRtcp(data, static_cast<int>(len));
|
||||
rtc::CopyOnWriteBuffer packet(data, len);
|
||||
|
||||
if (!WantsPacket(rtcp, &packet)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// This mutates |packet| if it is protected.
|
||||
SignalPacketReceived(rtcp, &packet, packet_time);
|
||||
}
|
||||
|
||||
bool RtpTransport::WantsPacket(bool rtcp,
|
||||
const rtc::CopyOnWriteBuffer* packet) {
|
||||
// Protect ourselves against crazy data.
|
||||
if (!packet || !cricket::IsValidRtpRtcpPacketSize(rtcp, packet->size())) {
|
||||
RTC_LOG(LS_ERROR) << "Dropping incoming "
|
||||
<< cricket::RtpRtcpStringLiteral(rtcp)
|
||||
<< " packet: wrong size=" << packet->size();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -13,7 +13,8 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "api/ortc/rtptransportinterface.h"
|
||||
#include "call/rtp_demuxer.h"
|
||||
#include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
|
||||
#include "pc/rtptransportinternal.h"
|
||||
#include "rtc_base/sigslot.h"
|
||||
|
||||
@ -74,6 +75,14 @@ class RtpTransport : public RtpTransportInternal {
|
||||
|
||||
bool IsSrtpActive() const override { return false; }
|
||||
|
||||
void UpdateRtpHeaderExtensionMap(
|
||||
const cricket::RtpHeaderExtensions& header_extensions) override;
|
||||
|
||||
bool RegisterRtpDemuxerSink(const RtpDemuxerCriteria& criteria,
|
||||
RtpPacketSinkInterface* sink) override;
|
||||
|
||||
bool UnregisterRtpDemuxerSink(RtpPacketSinkInterface* sink) override;
|
||||
|
||||
void SetMetricsObserver(
|
||||
rtc::scoped_refptr<MetricsObserverInterface> metrics_observer) override {}
|
||||
|
||||
@ -81,15 +90,33 @@ class RtpTransport : public RtpTransportInternal {
|
||||
// TODO(zstein): Remove this when we remove RtpTransportAdapter.
|
||||
RtpTransportAdapter* GetInternal() override;
|
||||
|
||||
private:
|
||||
bool IsRtpTransportWritable();
|
||||
bool HandlesPacket(const uint8_t* data, size_t len);
|
||||
// These methods will be used in the subclasses.
|
||||
void DemuxPacket(rtc::CopyOnWriteBuffer* packet, const rtc::PacketTime& time);
|
||||
|
||||
bool SendPacket(bool rtcp,
|
||||
rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketOptions& options,
|
||||
int flags);
|
||||
|
||||
// Overridden by SrtpTransport.
|
||||
virtual void OnNetworkRouteChanged(
|
||||
rtc::Optional<rtc::NetworkRoute> network_route);
|
||||
virtual void OnRtpPacketReceived(rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketTime& packet_time);
|
||||
virtual void OnRtcpPacketReceived(rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketTime& packet_time);
|
||||
// Overridden by SrtpTransport and DtlsSrtpTransport.
|
||||
virtual void OnWritableState(rtc::PacketTransportInternal* packet_transport);
|
||||
|
||||
private:
|
||||
void OnReadyToSend(rtc::PacketTransportInternal* transport);
|
||||
void OnNetworkRouteChange(rtc::Optional<rtc::NetworkRoute> network_route);
|
||||
void OnWritableState(rtc::PacketTransportInternal* packet_transport);
|
||||
void OnSentPacket(rtc::PacketTransportInternal* packet_transport,
|
||||
const rtc::SentPacket& sent_packet);
|
||||
void OnReadPacket(rtc::PacketTransportInternal* transport,
|
||||
const char* data,
|
||||
size_t len,
|
||||
const rtc::PacketTime& packet_time,
|
||||
int flags);
|
||||
|
||||
// Updates "ready to send" for an individual channel and fires
|
||||
// SignalReadyToSend.
|
||||
@ -97,19 +124,11 @@ class RtpTransport : public RtpTransportInternal {
|
||||
|
||||
void MaybeSignalReadyToSend();
|
||||
|
||||
bool SendPacket(bool rtcp,
|
||||
rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketOptions& options,
|
||||
int flags);
|
||||
|
||||
void OnReadPacket(rtc::PacketTransportInternal* transport,
|
||||
const char* data,
|
||||
size_t len,
|
||||
const rtc::PacketTime& packet_time,
|
||||
int flags);
|
||||
|
||||
bool WantsPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet);
|
||||
bool IsTransportWritable();
|
||||
|
||||
// SRTP specific methods.
|
||||
// TODO(zhihuang): Improve the inheritance model so that the RtpTransport
|
||||
// doesn't need to implement SRTP specfic methods.
|
||||
RTCError SetSrtpSendKey(const cricket::CryptoParams& params) override {
|
||||
RTC_NOTREACHED();
|
||||
return RTCError::OK();
|
||||
@ -129,6 +148,10 @@ class RtpTransport : public RtpTransportInternal {
|
||||
bool rtcp_ready_to_send_ = false;
|
||||
|
||||
RtpTransportParameters parameters_;
|
||||
RtpDemuxer rtp_demuxer_;
|
||||
|
||||
// Used for identifying the MID for RtpDemuxer.
|
||||
RtpHeaderExtensionMap header_extension_map_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -250,49 +250,37 @@ TEST(RtpTransportTest, RtcpPacketSentOverCorrectTransport) {
|
||||
EXPECT_EQ(1, observer.rtp_transport_sent_count());
|
||||
}
|
||||
|
||||
class SignalCounter : public sigslot::has_slots<> {
|
||||
public:
|
||||
explicit SignalCounter(RtpTransport* transport) {
|
||||
transport->SignalReadyToSend.connect(this, &SignalCounter::OnReadyToSend);
|
||||
}
|
||||
int count() const { return count_; }
|
||||
void OnReadyToSend(bool ready) { ++count_; }
|
||||
|
||||
private:
|
||||
int count_ = 0;
|
||||
};
|
||||
|
||||
TEST(RtpTransportTest, ChangingReadyToSendStateOnlySignalsWhenChanged) {
|
||||
RtpTransport transport(kMuxEnabled);
|
||||
SignalCounter observer(&transport);
|
||||
TransportObserver observer(&transport);
|
||||
rtc::FakePacketTransport fake_rtp("fake_rtp");
|
||||
fake_rtp.SetWritable(true);
|
||||
|
||||
// State changes, so we should signal.
|
||||
transport.SetRtpPacketTransport(&fake_rtp);
|
||||
EXPECT_EQ(observer.count(), 1);
|
||||
EXPECT_EQ(observer.ready_to_send_signal_count(), 1);
|
||||
|
||||
// State does not change, so we should not signal.
|
||||
transport.SetRtpPacketTransport(&fake_rtp);
|
||||
EXPECT_EQ(observer.count(), 1);
|
||||
EXPECT_EQ(observer.ready_to_send_signal_count(), 1);
|
||||
|
||||
// State does not change, so we should not signal.
|
||||
transport.SetRtcpMuxEnabled(true);
|
||||
EXPECT_EQ(observer.count(), 1);
|
||||
EXPECT_EQ(observer.ready_to_send_signal_count(), 1);
|
||||
|
||||
// State changes, so we should signal.
|
||||
transport.SetRtcpMuxEnabled(false);
|
||||
EXPECT_EQ(observer.count(), 2);
|
||||
EXPECT_EQ(observer.ready_to_send_signal_count(), 2);
|
||||
}
|
||||
|
||||
// Test that SignalPacketReceived fires with rtcp=true when a RTCP packet is
|
||||
// received.
|
||||
TEST(RtpTransportTest, SignalDemuxedRtcp) {
|
||||
RtpTransport transport(kMuxDisabled);
|
||||
SignalPacketReceivedCounter observer(&transport);
|
||||
rtc::FakePacketTransport fake_rtp("fake_rtp");
|
||||
fake_rtp.SetDestination(&fake_rtp, true);
|
||||
transport.SetRtpPacketTransport(&fake_rtp);
|
||||
TransportObserver observer(&transport);
|
||||
|
||||
// An rtcp packet.
|
||||
const char data[] = {0, 73, 0, 0};
|
||||
@ -312,10 +300,14 @@ static const int kRtpLen = 12;
|
||||
// handled payload type is received.
|
||||
TEST(RtpTransportTest, SignalHandledRtpPayloadType) {
|
||||
RtpTransport transport(kMuxDisabled);
|
||||
SignalPacketReceivedCounter observer(&transport);
|
||||
rtc::FakePacketTransport fake_rtp("fake_rtp");
|
||||
fake_rtp.SetDestination(&fake_rtp, true);
|
||||
transport.SetRtpPacketTransport(&fake_rtp);
|
||||
TransportObserver observer(&transport);
|
||||
RtpDemuxerCriteria demuxer_criteria;
|
||||
// Add a handled payload type.
|
||||
demuxer_criteria.payload_types = {0x11};
|
||||
transport.RegisterRtpDemuxerSink(demuxer_criteria, &observer);
|
||||
|
||||
// An rtp packet.
|
||||
const rtc::PacketOptions options;
|
||||
@ -324,6 +316,31 @@ TEST(RtpTransportTest, SignalHandledRtpPayloadType) {
|
||||
fake_rtp.SendPacket(rtp_data.data<char>(), kRtpLen, options, flags);
|
||||
EXPECT_EQ(1, observer.rtp_count());
|
||||
EXPECT_EQ(0, observer.rtcp_count());
|
||||
// Remove the sink before destroying the transport.
|
||||
transport.UnregisterRtpDemuxerSink(&observer);
|
||||
}
|
||||
|
||||
// Test that SignalPacketReceived does not fire when a RTP packet with an
|
||||
// unhandled payload type is received.
|
||||
TEST(RtpTransportTest, DontSignalUnhandledRtpPayloadType) {
|
||||
RtpTransport transport(kMuxDisabled);
|
||||
rtc::FakePacketTransport fake_rtp("fake_rtp");
|
||||
fake_rtp.SetDestination(&fake_rtp, true);
|
||||
transport.SetRtpPacketTransport(&fake_rtp);
|
||||
TransportObserver observer(&transport);
|
||||
RtpDemuxerCriteria demuxer_criteria;
|
||||
// Add an unhandled payload type.
|
||||
demuxer_criteria.payload_types = {0x12};
|
||||
transport.RegisterRtpDemuxerSink(demuxer_criteria, &observer);
|
||||
|
||||
const rtc::PacketOptions options;
|
||||
const int flags = 0;
|
||||
rtc::Buffer rtp_data(kRtpData, kRtpLen);
|
||||
fake_rtp.SendPacket(rtp_data.data<char>(), kRtpLen, options, flags);
|
||||
EXPECT_EQ(0, observer.rtp_count());
|
||||
EXPECT_EQ(0, observer.rtcp_count());
|
||||
// Remove the sink before destroying the transport.
|
||||
transport.UnregisterRtpDemuxerSink(&observer);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -15,7 +15,9 @@
|
||||
|
||||
#include "api/ortc/srtptransportinterface.h"
|
||||
#include "api/umametrics.h"
|
||||
#include "call/rtp_demuxer.h"
|
||||
#include "p2p/base/icetransportinternal.h"
|
||||
#include "pc/sessiondescription.h"
|
||||
#include "rtc_base/networkroute.h"
|
||||
#include "rtc_base/sigslot.h"
|
||||
#include "rtc_base/sslstreamadapter.h"
|
||||
@ -55,11 +57,11 @@ class RtpTransportInternal : public SrtpTransportInterface,
|
||||
// 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;
|
||||
// Called whenever an RTCP packet is received. There is no equivalent signal
|
||||
// for RTP packets because they would be forwarded to the BaseChannel through
|
||||
// the RtpDemuxer callback.
|
||||
sigslot::signal2<rtc::CopyOnWriteBuffer*, const rtc::PacketTime&>
|
||||
SignalRtcpPacketReceived;
|
||||
|
||||
// Called whenever the network route of the P2P layer transport changes.
|
||||
// The argument is an optional network route.
|
||||
@ -83,10 +85,28 @@ class RtpTransportInternal : public SrtpTransportInterface,
|
||||
const rtc::PacketOptions& options,
|
||||
int flags) = 0;
|
||||
|
||||
// This method updates the RTP header extension map so that the RTP transport
|
||||
// can parse the received packets and identify the MID. This is called by the
|
||||
// BaseChannel when setting the content description.
|
||||
//
|
||||
// TODO(zhihuang): Merging and replacing following methods handling header
|
||||
// extensions with SetParameters:
|
||||
// UpdateRtpHeaderExtensionMap,
|
||||
// UpdateSendEncryptedHeaderExtensionIds,
|
||||
// UpdateRecvEncryptedHeaderExtensionIds,
|
||||
// CacheRtpAbsSendTimeHeaderExtension,
|
||||
virtual void UpdateRtpHeaderExtensionMap(
|
||||
const cricket::RtpHeaderExtensions& header_extensions) = 0;
|
||||
|
||||
virtual bool IsSrtpActive() const = 0;
|
||||
|
||||
virtual void SetMetricsObserver(
|
||||
rtc::scoped_refptr<MetricsObserverInterface> metrics_observer) = 0;
|
||||
|
||||
virtual bool RegisterRtpDemuxerSink(const RtpDemuxerCriteria& criteria,
|
||||
RtpPacketSinkInterface* sink) = 0;
|
||||
|
||||
virtual bool UnregisterRtpDemuxerSink(RtpPacketSinkInterface* sink) = 0;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -71,6 +71,20 @@ class RtpTransportInternalAdapter : public RtpTransportInternal {
|
||||
return transport_->SendRtcpPacket(packet, options, flags);
|
||||
}
|
||||
|
||||
void UpdateRtpHeaderExtensionMap(
|
||||
const cricket::RtpHeaderExtensions& header_extensions) override {
|
||||
transport_->UpdateRtpHeaderExtensionMap(header_extensions);
|
||||
}
|
||||
|
||||
bool RegisterRtpDemuxerSink(const RtpDemuxerCriteria& criteria,
|
||||
RtpPacketSinkInterface* sink) override {
|
||||
return transport_->RegisterRtpDemuxerSink(criteria, sink);
|
||||
}
|
||||
|
||||
bool UnregisterRtpDemuxerSink(RtpPacketSinkInterface* sink) override {
|
||||
return transport_->UnregisterRtpDemuxerSink(sink);
|
||||
}
|
||||
|
||||
// RtpTransportInterface overrides.
|
||||
PacketTransportInterface* GetRtpPacketTransport() const override {
|
||||
return transport_->GetRtpPacketTransport();
|
||||
|
||||
@ -11,32 +11,66 @@
|
||||
#ifndef PC_RTPTRANSPORTTESTUTIL_H_
|
||||
#define PC_RTPTRANSPORTTESTUTIL_H_
|
||||
|
||||
#include "call/rtp_packet_sink_interface.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
|
||||
#include "pc/rtptransportinternal.h"
|
||||
#include "rtc_base/sigslot.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class SignalPacketReceivedCounter : public sigslot::has_slots<> {
|
||||
// Used to handle the signals when the RtpTransport receives an RTP/RTCP packet.
|
||||
// Used in Rtp/Srtp/DtlsTransport unit tests.
|
||||
class TransportObserver : public RtpPacketSinkInterface,
|
||||
public sigslot::has_slots<> {
|
||||
public:
|
||||
explicit SignalPacketReceivedCounter(RtpTransportInternal* transport) {
|
||||
transport->SignalPacketReceived.connect(
|
||||
this, &SignalPacketReceivedCounter::OnPacketReceived);
|
||||
TransportObserver() {}
|
||||
|
||||
explicit TransportObserver(RtpTransportInternal* rtp_transport) {
|
||||
rtp_transport->SignalRtcpPacketReceived.connect(
|
||||
this, &TransportObserver::OnRtcpPacketReceived);
|
||||
rtp_transport->SignalReadyToSend.connect(this,
|
||||
&TransportObserver::OnReadyToSend);
|
||||
}
|
||||
int rtcp_count() const { return rtcp_count_; }
|
||||
|
||||
// RtpPacketInterface override.
|
||||
void OnRtpPacket(const RtpPacketReceived& packet) override {
|
||||
rtp_count_++;
|
||||
last_recv_rtp_packet_ = packet.Buffer();
|
||||
}
|
||||
|
||||
void OnRtcpPacketReceived(rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketTime& packet_time) {
|
||||
rtcp_count_++;
|
||||
last_recv_rtcp_packet_ = *packet;
|
||||
}
|
||||
|
||||
int rtp_count() const { return rtp_count_; }
|
||||
int rtcp_count() const { return rtcp_count_; }
|
||||
|
||||
rtc::CopyOnWriteBuffer last_recv_rtp_packet() {
|
||||
return last_recv_rtp_packet_;
|
||||
}
|
||||
|
||||
rtc::CopyOnWriteBuffer last_recv_rtcp_packet() {
|
||||
return last_recv_rtcp_packet_;
|
||||
}
|
||||
|
||||
void OnReadyToSend(bool ready) {
|
||||
ready_to_send_signal_count_++;
|
||||
ready_to_send_ = ready;
|
||||
}
|
||||
|
||||
bool ready_to_send() { return ready_to_send_; }
|
||||
|
||||
int ready_to_send_signal_count() { return ready_to_send_signal_count_; }
|
||||
|
||||
private:
|
||||
void OnPacketReceived(bool rtcp,
|
||||
rtc::CopyOnWriteBuffer*,
|
||||
const rtc::PacketTime&) {
|
||||
if (rtcp) {
|
||||
++rtcp_count_;
|
||||
} else {
|
||||
++rtp_count_;
|
||||
}
|
||||
}
|
||||
int rtcp_count_ = 0;
|
||||
bool ready_to_send_ = false;
|
||||
int rtp_count_ = 0;
|
||||
int rtcp_count_ = 0;
|
||||
int ready_to_send_signal_count_ = 0;
|
||||
rtc::CopyOnWriteBuffer last_recv_rtp_packet_;
|
||||
rtc::CopyOnWriteBuffer last_recv_rtcp_packet_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
#include "rtc_base/asyncpacketsocket.h"
|
||||
#include "rtc_base/base64.h"
|
||||
#include "rtc_base/copyonwritebuffer.h"
|
||||
#include "rtc_base/numerics/safe_conversions.h"
|
||||
#include "rtc_base/ptr_util.h"
|
||||
#include "rtc_base/trace_event.h"
|
||||
#include "rtc_base/zero_memory.h"
|
||||
@ -26,31 +27,7 @@
|
||||
namespace webrtc {
|
||||
|
||||
SrtpTransport::SrtpTransport(bool rtcp_mux_enabled)
|
||||
: RtpTransportInternalAdapter(new RtpTransport(rtcp_mux_enabled)) {
|
||||
// Own the raw pointer |transport| from the base class.
|
||||
rtp_transport_.reset(static_cast<RtpTransport*>(transport_));
|
||||
RTC_DCHECK(rtp_transport_);
|
||||
ConnectToRtpTransport();
|
||||
}
|
||||
|
||||
SrtpTransport::SrtpTransport(std::unique_ptr<RtpTransport> rtp_transport)
|
||||
: RtpTransportInternalAdapter(rtp_transport.get()),
|
||||
rtp_transport_(std::move(rtp_transport)) {
|
||||
RTC_DCHECK(rtp_transport_);
|
||||
ConnectToRtpTransport();
|
||||
}
|
||||
|
||||
void SrtpTransport::ConnectToRtpTransport() {
|
||||
rtp_transport_->SignalPacketReceived.connect(
|
||||
this, &SrtpTransport::OnPacketReceived);
|
||||
rtp_transport_->SignalReadyToSend.connect(this,
|
||||
&SrtpTransport::OnReadyToSend);
|
||||
rtp_transport_->SignalNetworkRouteChanged.connect(
|
||||
this, &SrtpTransport::OnNetworkRouteChanged);
|
||||
rtp_transport_->SignalWritableState.connect(this,
|
||||
&SrtpTransport::OnWritableState);
|
||||
rtp_transport_->SignalSentPacket.connect(this, &SrtpTransport::OnSentPacket);
|
||||
}
|
||||
: RtpTransport(rtcp_mux_enabled) {}
|
||||
|
||||
RTCError SrtpTransport::SetSrtpSendKey(const cricket::CryptoParams& params) {
|
||||
if (send_params_) {
|
||||
@ -135,125 +112,128 @@ RTCError SrtpTransport::SetSrtpReceiveKey(const cricket::CryptoParams& params) {
|
||||
bool SrtpTransport::SendRtpPacket(rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketOptions& options,
|
||||
int flags) {
|
||||
return SendPacket(false, packet, options, flags);
|
||||
}
|
||||
|
||||
bool SrtpTransport::SendRtcpPacket(rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketOptions& options,
|
||||
int flags) {
|
||||
return SendPacket(true, packet, options, flags);
|
||||
}
|
||||
|
||||
bool SrtpTransport::SendPacket(bool rtcp,
|
||||
rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketOptions& options,
|
||||
int flags) {
|
||||
if (!IsSrtpActive()) {
|
||||
RTC_LOG(LS_ERROR)
|
||||
<< "Failed to send the packet because SRTP transport is inactive.";
|
||||
return false;
|
||||
}
|
||||
|
||||
rtc::PacketOptions updated_options = options;
|
||||
rtc::CopyOnWriteBuffer cp = *packet;
|
||||
TRACE_EVENT0("webrtc", "SRTP Encode");
|
||||
bool res;
|
||||
uint8_t* data = packet->data();
|
||||
int len = static_cast<int>(packet->size());
|
||||
if (!rtcp) {
|
||||
int len = rtc::checked_cast<int>(packet->size());
|
||||
// If ENABLE_EXTERNAL_AUTH flag is on then packet authentication is not done
|
||||
// inside libsrtp for a RTP packet. A external HMAC module will be writing
|
||||
// a fake HMAC value. This is ONLY done for a RTP packet.
|
||||
// Socket layer will update rtp sendtime extension header if present in
|
||||
// packet with current time before updating the HMAC.
|
||||
#if !defined(ENABLE_EXTERNAL_AUTH)
|
||||
res = ProtectRtp(data, len, static_cast<int>(packet->capacity()), &len);
|
||||
res = ProtectRtp(data, len, static_cast<int>(packet->capacity()), &len);
|
||||
#else
|
||||
if (!IsExternalAuthActive()) {
|
||||
res = ProtectRtp(data, len, static_cast<int>(packet->capacity()), &len);
|
||||
} else {
|
||||
updated_options.packet_time_params.rtp_sendtime_extension_id =
|
||||
rtp_abs_sendtime_extn_id_;
|
||||
res = ProtectRtp(data, len, static_cast<int>(packet->capacity()), &len,
|
||||
&updated_options.packet_time_params.srtp_packet_index);
|
||||
// If protection succeeds, let's get auth params from srtp.
|
||||
if (!IsExternalAuthActive()) {
|
||||
res = ProtectRtp(data, len, static_cast<int>(packet->capacity()), &len);
|
||||
} else {
|
||||
updated_options.packet_time_params.rtp_sendtime_extension_id =
|
||||
rtp_abs_sendtime_extn_id_;
|
||||
res = ProtectRtp(data, len, static_cast<int>(packet->capacity()), &len,
|
||||
&updated_options.packet_time_params.srtp_packet_index);
|
||||
// If protection succeeds, let's get auth params from srtp.
|
||||
if (res) {
|
||||
uint8_t* auth_key = nullptr;
|
||||
int key_len = 0;
|
||||
res = GetRtpAuthParams(
|
||||
&auth_key, &key_len,
|
||||
&updated_options.packet_time_params.srtp_auth_tag_len);
|
||||
if (res) {
|
||||
uint8_t* auth_key = NULL;
|
||||
int key_len;
|
||||
res = GetRtpAuthParams(
|
||||
&auth_key, &key_len,
|
||||
&updated_options.packet_time_params.srtp_auth_tag_len);
|
||||
if (res) {
|
||||
updated_options.packet_time_params.srtp_auth_key.resize(key_len);
|
||||
updated_options.packet_time_params.srtp_auth_key.assign(
|
||||
auth_key, auth_key + key_len);
|
||||
}
|
||||
updated_options.packet_time_params.srtp_auth_key.resize(key_len);
|
||||
updated_options.packet_time_params.srtp_auth_key.assign(
|
||||
auth_key, auth_key + key_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!res) {
|
||||
int seq_num = -1;
|
||||
uint32_t ssrc = 0;
|
||||
cricket::GetRtpSeqNum(data, len, &seq_num);
|
||||
cricket::GetRtpSsrc(data, len, &ssrc);
|
||||
RTC_LOG(LS_ERROR) << "Failed to protect RTP packet: size=" << len
|
||||
<< ", seqnum=" << seq_num << ", SSRC=" << ssrc;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
res = ProtectRtcp(data, len, static_cast<int>(packet->capacity()), &len);
|
||||
if (!res) {
|
||||
int type = -1;
|
||||
cricket::GetRtcpType(data, len, &type);
|
||||
RTC_LOG(LS_ERROR) << "Failed to protect RTCP packet: size=" << len
|
||||
<< ", type=" << type;
|
||||
return false;
|
||||
}
|
||||
if (!res) {
|
||||
int seq_num = -1;
|
||||
uint32_t ssrc = 0;
|
||||
cricket::GetRtpSeqNum(data, len, &seq_num);
|
||||
cricket::GetRtpSsrc(data, len, &ssrc);
|
||||
RTC_LOG(LS_ERROR) << "Failed to protect RTP packet: size=" << len
|
||||
<< ", seqnum=" << seq_num << ", SSRC=" << ssrc;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update the length of the packet now that we've added the auth tag.
|
||||
packet->SetSize(len);
|
||||
return rtcp ? rtp_transport_->SendRtcpPacket(packet, updated_options, flags)
|
||||
: rtp_transport_->SendRtpPacket(packet, updated_options, flags);
|
||||
return SendPacket(/*rtcp=*/false, packet, updated_options, flags);
|
||||
}
|
||||
|
||||
void SrtpTransport::OnPacketReceived(bool rtcp,
|
||||
rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketTime& packet_time) {
|
||||
bool SrtpTransport::SendRtcpPacket(rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketOptions& options,
|
||||
int flags) {
|
||||
if (!IsSrtpActive()) {
|
||||
RTC_LOG(LS_ERROR)
|
||||
<< "Failed to send the packet because SRTP transport is inactive.";
|
||||
return false;
|
||||
}
|
||||
|
||||
TRACE_EVENT0("webrtc", "SRTP Encode");
|
||||
uint8_t* data = packet->data();
|
||||
int len = rtc::checked_cast<int>(packet->size());
|
||||
if (!ProtectRtcp(data, len, static_cast<int>(packet->capacity()), &len)) {
|
||||
int type = -1;
|
||||
cricket::GetRtcpType(data, len, &type);
|
||||
RTC_LOG(LS_ERROR) << "Failed to protect RTCP packet: size=" << len
|
||||
<< ", type=" << type;
|
||||
return false;
|
||||
}
|
||||
// Update the length of the packet now that we've added the auth tag.
|
||||
packet->SetSize(len);
|
||||
|
||||
return SendPacket(/*rtcp=*/true, packet, options, flags);
|
||||
}
|
||||
|
||||
void SrtpTransport::OnRtpPacketReceived(rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketTime& packet_time) {
|
||||
if (!IsSrtpActive()) {
|
||||
RTC_LOG(LS_WARNING)
|
||||
<< "Inactive SRTP transport received a packet. Drop it.";
|
||||
<< "Inactive SRTP transport received an RTP packet. Drop it.";
|
||||
return;
|
||||
}
|
||||
|
||||
TRACE_EVENT0("webrtc", "SRTP Decode");
|
||||
char* data = packet->data<char>();
|
||||
int len = static_cast<int>(packet->size());
|
||||
bool res;
|
||||
if (!rtcp) {
|
||||
res = UnprotectRtp(data, len, &len);
|
||||
if (!res) {
|
||||
int seq_num = -1;
|
||||
uint32_t ssrc = 0;
|
||||
cricket::GetRtpSeqNum(data, len, &seq_num);
|
||||
cricket::GetRtpSsrc(data, len, &ssrc);
|
||||
RTC_LOG(LS_ERROR) << "Failed to unprotect RTP packet: size=" << len
|
||||
<< ", seqnum=" << seq_num << ", SSRC=" << ssrc;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
res = UnprotectRtcp(data, len, &len);
|
||||
if (!res) {
|
||||
int type = -1;
|
||||
cricket::GetRtcpType(data, len, &type);
|
||||
RTC_LOG(LS_ERROR) << "Failed to unprotect RTCP packet: size=" << len
|
||||
<< ", type=" << type;
|
||||
return;
|
||||
}
|
||||
int len = rtc::checked_cast<int>(packet->size());
|
||||
if (!UnprotectRtp(data, len, &len)) {
|
||||
int seq_num = -1;
|
||||
uint32_t ssrc = 0;
|
||||
cricket::GetRtpSeqNum(data, len, &seq_num);
|
||||
cricket::GetRtpSsrc(data, len, &ssrc);
|
||||
RTC_LOG(LS_ERROR) << "Failed to unprotect RTP packet: size=" << len
|
||||
<< ", seqnum=" << seq_num << ", SSRC=" << ssrc;
|
||||
return;
|
||||
}
|
||||
|
||||
packet->SetSize(len);
|
||||
SignalPacketReceived(rtcp, packet, packet_time);
|
||||
DemuxPacket(packet, packet_time);
|
||||
}
|
||||
|
||||
void SrtpTransport::OnRtcpPacketReceived(rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketTime& packet_time) {
|
||||
if (!IsSrtpActive()) {
|
||||
RTC_LOG(LS_WARNING)
|
||||
<< "Inactive SRTP transport received an RTCP packet. Drop it.";
|
||||
return;
|
||||
}
|
||||
TRACE_EVENT0("webrtc", "SRTP Decode");
|
||||
char* data = packet->data<char>();
|
||||
int len = rtc::checked_cast<int>(packet->size());
|
||||
if (!UnprotectRtcp(data, len, &len)) {
|
||||
int type = -1;
|
||||
cricket::GetRtcpType(data, len, &type);
|
||||
RTC_LOG(LS_ERROR) << "Failed to unprotect RTCP packet: size=" << len
|
||||
<< ", type=" << type;
|
||||
return;
|
||||
}
|
||||
packet->SetSize(len);
|
||||
SignalRtcpPacketReceived(packet, packet_time);
|
||||
}
|
||||
|
||||
void SrtpTransport::OnNetworkRouteChanged(
|
||||
@ -269,6 +249,11 @@ void SrtpTransport::OnNetworkRouteChanged(
|
||||
SignalNetworkRouteChanged(network_route);
|
||||
}
|
||||
|
||||
void SrtpTransport::OnWritableState(
|
||||
rtc::PacketTransportInternal* packet_transport) {
|
||||
SignalWritableState(IsWritable(/*rtcp=*/true) && IsWritable(/*rtcp=*/true));
|
||||
}
|
||||
|
||||
bool SrtpTransport::SetRtpParams(int send_cs,
|
||||
const uint8_t* send_key,
|
||||
int send_key_len,
|
||||
@ -309,6 +294,7 @@ bool SrtpTransport::SetRtpParams(int send_cs,
|
||||
RTC_LOG(LS_INFO) << "SRTP " << (new_sessions ? "activated" : "updated")
|
||||
<< " with negotiated parameters: send cipher_suite "
|
||||
<< send_cs << " recv cipher_suite " << recv_cs;
|
||||
MaybeUpdateWritableState();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -347,7 +333,7 @@ bool SrtpTransport::SetRtcpParams(int send_cs,
|
||||
RTC_LOG(LS_INFO) << "SRTCP activated with negotiated parameters:"
|
||||
" send cipher_suite "
|
||||
<< send_cs << " recv cipher_suite " << recv_cs;
|
||||
|
||||
MaybeUpdateWritableState();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -355,11 +341,16 @@ bool SrtpTransport::IsSrtpActive() const {
|
||||
return send_session_ && recv_session_;
|
||||
}
|
||||
|
||||
bool SrtpTransport::IsWritable(bool rtcp) const {
|
||||
return IsSrtpActive() && RtpTransport::IsWritable(rtcp);
|
||||
}
|
||||
|
||||
void SrtpTransport::ResetParams() {
|
||||
send_session_ = nullptr;
|
||||
recv_session_ = nullptr;
|
||||
send_rtcp_session_ = nullptr;
|
||||
recv_rtcp_session_ = nullptr;
|
||||
MaybeUpdateWritableState();
|
||||
RTC_LOG(LS_INFO) << "The params in SRTP transport are reset.";
|
||||
}
|
||||
|
||||
@ -530,7 +521,15 @@ void SrtpTransport::SetMetricsObserver(
|
||||
if (recv_rtcp_session_) {
|
||||
recv_rtcp_session_->SetMetricsObserver(metrics_observer_);
|
||||
}
|
||||
rtp_transport_->SetMetricsObserver(metrics_observer);
|
||||
}
|
||||
|
||||
void SrtpTransport::MaybeUpdateWritableState() {
|
||||
bool writable = IsWritable(/*rtcp=*/true) && IsWritable(/*rtcp=*/false);
|
||||
// Only fire the signal if the writable state changes.
|
||||
if (writable_ != writable) {
|
||||
writable_ = writable;
|
||||
SignalWritableState(writable_);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -20,38 +20,20 @@
|
||||
#include "p2p/base/dtlstransportinternal.h"
|
||||
#include "p2p/base/icetransportinternal.h"
|
||||
#include "pc/rtptransport.h"
|
||||
#include "pc/rtptransportinternaladapter.h"
|
||||
#include "pc/srtpsession.h"
|
||||
#include "rtc_base/buffer.h"
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// This class will eventually be a wrapper around RtpTransportInternal
|
||||
// that protects and unprotects sent and received RTP packets.
|
||||
class SrtpTransport : public RtpTransportInternalAdapter {
|
||||
// This subclass of the RtpTransport is used for SRTP which is reponsible for
|
||||
// protecting/unprotecting the packets. It provides interfaces to set the crypto
|
||||
// parameters for the SrtpSession underneath.
|
||||
class SrtpTransport : public RtpTransport {
|
||||
public:
|
||||
explicit SrtpTransport(bool rtcp_mux_enabled);
|
||||
|
||||
explicit SrtpTransport(std::unique_ptr<RtpTransport> rtp_transport);
|
||||
|
||||
virtual ~SrtpTransport() {}
|
||||
|
||||
// SrtpTransportInterface overrides.
|
||||
PacketTransportInterface* GetRtpPacketTransport() const override {
|
||||
return rtp_transport_->GetRtpPacketTransport();
|
||||
}
|
||||
PacketTransportInterface* GetRtcpPacketTransport() const override {
|
||||
return rtp_transport_->GetRtcpPacketTransport();
|
||||
}
|
||||
|
||||
// TODO(zstein): Use these RtcpParameters for configuration elsewhere.
|
||||
RTCError SetParameters(const RtpTransportParameters& parameters) override {
|
||||
return rtp_transport_->SetParameters(parameters);
|
||||
}
|
||||
RtpTransportParameters GetParameters() const override {
|
||||
return rtp_transport_->GetParameters();
|
||||
}
|
||||
virtual ~SrtpTransport() = default;
|
||||
|
||||
// SrtpTransportInterface specific implementation.
|
||||
RTCError SetSrtpSendKey(const cricket::CryptoParams& params) override;
|
||||
@ -69,6 +51,8 @@ class SrtpTransport : public RtpTransportInternalAdapter {
|
||||
// created.
|
||||
bool IsSrtpActive() const override;
|
||||
|
||||
bool IsWritable(bool rtcp) const override;
|
||||
|
||||
// Create new send/recv sessions and set the negotiated crypto keys for RTP
|
||||
// packet encryption. The keys can either come from SDES negotiation or DTLS
|
||||
// handshake.
|
||||
@ -120,29 +104,23 @@ class SrtpTransport : public RtpTransportInternalAdapter {
|
||||
rtp_abs_sendtime_extn_id_ = rtp_abs_sendtime_extn_id;
|
||||
}
|
||||
|
||||
void SetMetricsObserver(
|
||||
rtc::scoped_refptr<MetricsObserverInterface> metrics_observer) override;
|
||||
protected:
|
||||
// If the writable state changed, fire the SignalWritableState.
|
||||
void MaybeUpdateWritableState();
|
||||
|
||||
private:
|
||||
void ConnectToRtpTransport();
|
||||
void CreateSrtpSessions();
|
||||
|
||||
bool SendPacket(bool rtcp,
|
||||
rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketOptions& options,
|
||||
int flags);
|
||||
void OnRtpPacketReceived(rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketTime& packet_time) override;
|
||||
void OnRtcpPacketReceived(rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketTime& packet_time) override;
|
||||
void OnNetworkRouteChanged(
|
||||
rtc::Optional<rtc::NetworkRoute> network_route) override;
|
||||
|
||||
void OnPacketReceived(bool rtcp,
|
||||
rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketTime& packet_time);
|
||||
void OnReadyToSend(bool ready) { SignalReadyToSend(ready); }
|
||||
void OnNetworkRouteChanged(rtc::Optional<rtc::NetworkRoute> network_route);
|
||||
|
||||
void OnWritableState(bool writable) { SignalWritableState(writable); }
|
||||
|
||||
void OnSentPacket(const rtc::SentPacket& sent_packet) {
|
||||
SignalSentPacket(sent_packet);
|
||||
}
|
||||
// Override the RtpTransport::OnWritableState.
|
||||
void OnWritableState(rtc::PacketTransportInternal* packet_transport) override;
|
||||
|
||||
bool ProtectRtp(void* data, int in_len, int max_len, int* out_len);
|
||||
|
||||
@ -163,8 +141,10 @@ class SrtpTransport : public RtpTransportInternalAdapter {
|
||||
bool MaybeSetKeyParams();
|
||||
bool ParseKeyParams(const std::string& key_params, uint8_t* key, size_t len);
|
||||
|
||||
void SetMetricsObserver(
|
||||
rtc::scoped_refptr<MetricsObserverInterface> metrics_observer) override;
|
||||
|
||||
const std::string content_name_;
|
||||
std::unique_ptr<RtpTransport> rtp_transport_;
|
||||
|
||||
std::unique_ptr<cricket::SrtpSession> send_session_;
|
||||
std::unique_ptr<cricket::SrtpSession> recv_session_;
|
||||
@ -178,6 +158,8 @@ class SrtpTransport : public RtpTransportInternalAdapter {
|
||||
rtc::ZeroOnFreeBuffer<uint8_t> send_key_;
|
||||
rtc::ZeroOnFreeBuffer<uint8_t> recv_key_;
|
||||
|
||||
bool writable_ = false;
|
||||
|
||||
bool external_auth_enabled_ = false;
|
||||
|
||||
int rtp_abs_sendtime_extn_id_ = -1;
|
||||
|
||||
@ -42,8 +42,6 @@ class SrtpTransportTest : public testing::Test, public sigslot::has_slots<> {
|
||||
protected:
|
||||
SrtpTransportTest() {
|
||||
bool rtcp_mux_enabled = true;
|
||||
auto rtp_transport1 = rtc::MakeUnique<RtpTransport>(rtcp_mux_enabled);
|
||||
auto rtp_transport2 = rtc::MakeUnique<RtpTransport>(rtcp_mux_enabled);
|
||||
|
||||
rtp_packet_transport1_ =
|
||||
rtc::MakeUnique<rtc::FakePacketTransport>("fake_packet_transport1");
|
||||
@ -54,32 +52,32 @@ class SrtpTransportTest : public testing::Test, public sigslot::has_slots<> {
|
||||
rtp_packet_transport1_->SetDestination(rtp_packet_transport2_.get(),
|
||||
asymmetric);
|
||||
|
||||
rtp_transport1->SetRtpPacketTransport(rtp_packet_transport1_.get());
|
||||
rtp_transport2->SetRtpPacketTransport(rtp_packet_transport2_.get());
|
||||
srtp_transport1_ = rtc::MakeUnique<SrtpTransport>(rtcp_mux_enabled);
|
||||
srtp_transport2_ = rtc::MakeUnique<SrtpTransport>(rtcp_mux_enabled);
|
||||
|
||||
srtp_transport1_ =
|
||||
rtc::MakeUnique<SrtpTransport>(std::move(rtp_transport1));
|
||||
srtp_transport2_ =
|
||||
rtc::MakeUnique<SrtpTransport>(std::move(rtp_transport2));
|
||||
srtp_transport1_->SetRtpPacketTransport(rtp_packet_transport1_.get());
|
||||
srtp_transport2_->SetRtpPacketTransport(rtp_packet_transport2_.get());
|
||||
|
||||
srtp_transport1_->SignalPacketReceived.connect(
|
||||
this, &SrtpTransportTest::OnPacketReceived1);
|
||||
srtp_transport2_->SignalPacketReceived.connect(
|
||||
this, &SrtpTransportTest::OnPacketReceived2);
|
||||
srtp_transport1_->SignalRtcpPacketReceived.connect(
|
||||
&rtp_sink1_, &TransportObserver::OnRtcpPacketReceived);
|
||||
srtp_transport2_->SignalRtcpPacketReceived.connect(
|
||||
&rtp_sink2_, &TransportObserver::OnRtcpPacketReceived);
|
||||
|
||||
RtpDemuxerCriteria demuxer_criteria;
|
||||
// 0x00 is the payload type used in kPcmuFrame.
|
||||
demuxer_criteria.payload_types = {0x00};
|
||||
|
||||
srtp_transport1_->RegisterRtpDemuxerSink(demuxer_criteria, &rtp_sink1_);
|
||||
srtp_transport2_->RegisterRtpDemuxerSink(demuxer_criteria, &rtp_sink2_);
|
||||
}
|
||||
|
||||
void OnPacketReceived1(bool rtcp,
|
||||
rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketTime& packet_time) {
|
||||
RTC_LOG(LS_INFO) << "SrtpTransport1 Received a packet.";
|
||||
last_recv_packet1_ = *packet;
|
||||
}
|
||||
|
||||
void OnPacketReceived2(bool rtcp,
|
||||
rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketTime& packet_time) {
|
||||
RTC_LOG(LS_INFO) << "SrtpTransport2 Received a packet.";
|
||||
last_recv_packet2_ = *packet;
|
||||
~SrtpTransportTest() {
|
||||
if (srtp_transport1_) {
|
||||
srtp_transport1_->UnregisterRtpDemuxerSink(&rtp_sink1_);
|
||||
}
|
||||
if (srtp_transport2_) {
|
||||
srtp_transport2_->UnregisterRtpDemuxerSink(&rtp_sink2_);
|
||||
}
|
||||
}
|
||||
|
||||
// With external auth enabled, SRTP doesn't write the auth tag and
|
||||
@ -136,9 +134,9 @@ class SrtpTransportTest : public testing::Test, public sigslot::has_slots<> {
|
||||
if (srtp_transport1_->IsExternalAuthActive()) {
|
||||
TestRtpAuthParams(srtp_transport1_.get(), cipher_suite_name);
|
||||
} else {
|
||||
ASSERT_TRUE(last_recv_packet2_.data());
|
||||
EXPECT_EQ(0,
|
||||
memcmp(last_recv_packet2_.data(), original_rtp_data, rtp_len));
|
||||
ASSERT_TRUE(rtp_sink2_.last_recv_rtp_packet().data());
|
||||
EXPECT_EQ(0, memcmp(rtp_sink2_.last_recv_rtp_packet().data(),
|
||||
original_rtp_data, rtp_len));
|
||||
// Get the encrypted packet from underneath packet transport and verify
|
||||
// the data is actually encrypted.
|
||||
auto fake_rtp_packet_transport = static_cast<rtc::FakePacketTransport*>(
|
||||
@ -153,9 +151,9 @@ class SrtpTransportTest : public testing::Test, public sigslot::has_slots<> {
|
||||
if (srtp_transport2_->IsExternalAuthActive()) {
|
||||
TestRtpAuthParams(srtp_transport2_.get(), cipher_suite_name);
|
||||
} else {
|
||||
ASSERT_TRUE(last_recv_packet1_.data());
|
||||
EXPECT_EQ(0,
|
||||
memcmp(last_recv_packet1_.data(), original_rtp_data, rtp_len));
|
||||
ASSERT_TRUE(rtp_sink1_.last_recv_rtp_packet().data());
|
||||
EXPECT_EQ(0, memcmp(rtp_sink1_.last_recv_rtp_packet().data(),
|
||||
original_rtp_data, rtp_len));
|
||||
auto fake_rtp_packet_transport = static_cast<rtc::FakePacketTransport*>(
|
||||
srtp_transport2_->rtp_packet_transport());
|
||||
EXPECT_NE(0, memcmp(fake_rtp_packet_transport->last_sent_packet()->data(),
|
||||
@ -164,12 +162,12 @@ class SrtpTransportTest : public testing::Test, public sigslot::has_slots<> {
|
||||
}
|
||||
|
||||
void TestSendRecvRtcpPacket(const std::string& cipher_suite_name) {
|
||||
size_t rtcp_len = sizeof(kRtcpReport);
|
||||
size_t rtcp_len = sizeof(::kRtcpReport);
|
||||
size_t packet_size =
|
||||
rtcp_len + 4 + rtc::rtcp_auth_tag_len(cipher_suite_name);
|
||||
rtc::Buffer rtcp_packet_buffer(packet_size);
|
||||
char* rtcp_packet_data = rtcp_packet_buffer.data<char>();
|
||||
memcpy(rtcp_packet_data, kRtcpReport, rtcp_len);
|
||||
memcpy(rtcp_packet_data, ::kRtcpReport, rtcp_len);
|
||||
|
||||
rtc::CopyOnWriteBuffer rtcp_packet1to2(rtcp_packet_data, rtcp_len,
|
||||
packet_size);
|
||||
@ -181,8 +179,9 @@ class SrtpTransportTest : public testing::Test, public sigslot::has_slots<> {
|
||||
// that the packet can be successfully received and decrypted.
|
||||
ASSERT_TRUE(srtp_transport1_->SendRtcpPacket(&rtcp_packet1to2, options,
|
||||
cricket::PF_SRTP_BYPASS));
|
||||
ASSERT_TRUE(last_recv_packet2_.data());
|
||||
EXPECT_EQ(0, memcmp(last_recv_packet2_.data(), rtcp_packet_data, rtcp_len));
|
||||
ASSERT_TRUE(rtp_sink2_.last_recv_rtcp_packet().data());
|
||||
EXPECT_EQ(0, memcmp(rtp_sink2_.last_recv_rtcp_packet().data(),
|
||||
rtcp_packet_data, rtcp_len));
|
||||
// Get the encrypted packet from underneath packet transport and verify the
|
||||
// data is actually encrypted.
|
||||
auto fake_rtp_packet_transport = static_cast<rtc::FakePacketTransport*>(
|
||||
@ -193,8 +192,9 @@ class SrtpTransportTest : public testing::Test, public sigslot::has_slots<> {
|
||||
// Do the same thing in the opposite direction;
|
||||
ASSERT_TRUE(srtp_transport2_->SendRtcpPacket(&rtcp_packet2to1, options,
|
||||
cricket::PF_SRTP_BYPASS));
|
||||
ASSERT_TRUE(last_recv_packet1_.data());
|
||||
EXPECT_EQ(0, memcmp(last_recv_packet1_.data(), rtcp_packet_data, rtcp_len));
|
||||
ASSERT_TRUE(rtp_sink1_.last_recv_rtcp_packet().data());
|
||||
EXPECT_EQ(0, memcmp(rtp_sink1_.last_recv_rtcp_packet().data(),
|
||||
rtcp_packet_data, rtcp_len));
|
||||
fake_rtp_packet_transport = static_cast<rtc::FakePacketTransport*>(
|
||||
srtp_transport2_->rtp_packet_transport());
|
||||
EXPECT_NE(0, memcmp(fake_rtp_packet_transport->last_sent_packet()->data(),
|
||||
@ -261,8 +261,9 @@ class SrtpTransportTest : public testing::Test, public sigslot::has_slots<> {
|
||||
// that the packet can be successfully received and decrypted.
|
||||
ASSERT_TRUE(srtp_transport1_->SendRtpPacket(&rtp_packet1to2, options,
|
||||
cricket::PF_SRTP_BYPASS));
|
||||
ASSERT_TRUE(last_recv_packet2_.data());
|
||||
EXPECT_EQ(0, memcmp(last_recv_packet2_.data(), original_rtp_data, rtp_len));
|
||||
ASSERT_TRUE(rtp_sink2_.last_recv_rtp_packet().data());
|
||||
EXPECT_EQ(0, memcmp(rtp_sink2_.last_recv_rtp_packet().data(),
|
||||
original_rtp_data, rtp_len));
|
||||
// Get the encrypted packet from underneath packet transport and verify the
|
||||
// data and header extension are actually encrypted.
|
||||
auto fake_rtp_packet_transport = static_cast<rtc::FakePacketTransport*>(
|
||||
@ -278,8 +279,9 @@ class SrtpTransportTest : public testing::Test, public sigslot::has_slots<> {
|
||||
// Do the same thing in the opposite direction;
|
||||
ASSERT_TRUE(srtp_transport2_->SendRtpPacket(&rtp_packet2to1, options,
|
||||
cricket::PF_SRTP_BYPASS));
|
||||
ASSERT_TRUE(last_recv_packet1_.data());
|
||||
EXPECT_EQ(0, memcmp(last_recv_packet1_.data(), original_rtp_data, rtp_len));
|
||||
ASSERT_TRUE(rtp_sink1_.last_recv_rtp_packet().data());
|
||||
EXPECT_EQ(0, memcmp(rtp_sink1_.last_recv_rtp_packet().data(),
|
||||
original_rtp_data, rtp_len));
|
||||
fake_rtp_packet_transport = static_cast<rtc::FakePacketTransport*>(
|
||||
srtp_transport2_->rtp_packet_transport());
|
||||
EXPECT_NE(0, memcmp(fake_rtp_packet_transport->last_sent_packet()->data(),
|
||||
@ -322,8 +324,9 @@ class SrtpTransportTest : public testing::Test, public sigslot::has_slots<> {
|
||||
std::unique_ptr<rtc::FakePacketTransport> rtp_packet_transport1_;
|
||||
std::unique_ptr<rtc::FakePacketTransport> rtp_packet_transport2_;
|
||||
|
||||
rtc::CopyOnWriteBuffer last_recv_packet1_;
|
||||
rtc::CopyOnWriteBuffer last_recv_packet2_;
|
||||
TransportObserver rtp_sink1_;
|
||||
TransportObserver rtp_sink2_;
|
||||
|
||||
int sequence_number_ = 0;
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user