blob: e6129b5983596fb8ae1ee64a0f532c6601433e9f [file] [log] [blame]
zsteind48dbda2017-04-04 19:45:57 -07001/*
2 * Copyright 2017 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Steve Anton10542f22019-01-11 09:11:00 -080011#include "pc/rtp_transport.h"
zsteind48dbda2017-04-04 19:45:57 -070012
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <errno.h>
14#include <string>
Zhi Huang365381f2018-04-13 16:44:34 -070015#include <utility>
16
Yves Gerey3e707812018-11-28 16:47:49 +010017#include "api/rtp_headers.h"
Steve Anton10542f22019-01-11 09:11:00 -080018#include "api/rtp_parameters.h"
19#include "media/base/rtp_utils.h"
Zhi Huang365381f2018-04-13 16:44:34 -070020#include "modules/rtp_rtcp/source/rtp_packet_received.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "rtc_base/checks.h"
Steve Anton10542f22019-01-11 09:11:00 -080022#include "rtc_base/copy_on_write_buffer.h"
Yves Gerey3e707812018-11-28 16:47:49 +010023#include "rtc_base/logging.h"
24#include "rtc_base/third_party/sigslot/sigslot.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020025#include "rtc_base/trace_event.h"
zsteind48dbda2017-04-04 19:45:57 -070026
27namespace webrtc {
28
zstein56162b92017-04-24 16:54:35 -070029void RtpTransport::SetRtcpMuxEnabled(bool enable) {
30 rtcp_mux_enabled_ = enable;
31 MaybeSignalReadyToSend();
zsteind9ce7642017-04-10 16:17:57 -070032}
33
zstein56162b92017-04-24 16:54:35 -070034void RtpTransport::SetRtpPacketTransport(
35 rtc::PacketTransportInternal* new_packet_transport) {
36 if (new_packet_transport == rtp_packet_transport_) {
37 return;
38 }
39 if (rtp_packet_transport_) {
40 rtp_packet_transport_->SignalReadyToSend.disconnect(this);
zstein3dcf0e92017-06-01 13:22:42 -070041 rtp_packet_transport_->SignalReadPacket.disconnect(this);
Zhi Huang942bc2e2017-11-13 13:26:07 -080042 rtp_packet_transport_->SignalNetworkRouteChanged.disconnect(this);
Zhi Huangcd3fc5d2017-11-29 10:41:57 -080043 rtp_packet_transport_->SignalWritableState.disconnect(this);
44 rtp_packet_transport_->SignalSentPacket.disconnect(this);
Zhi Huang942bc2e2017-11-13 13:26:07 -080045 // Reset the network route of the old transport.
Danil Chapovalov66cadcc2018-06-19 16:47:43 +020046 SignalNetworkRouteChanged(absl::optional<rtc::NetworkRoute>());
zstein56162b92017-04-24 16:54:35 -070047 }
48 if (new_packet_transport) {
49 new_packet_transport->SignalReadyToSend.connect(
50 this, &RtpTransport::OnReadyToSend);
zstein3dcf0e92017-06-01 13:22:42 -070051 new_packet_transport->SignalReadPacket.connect(this,
52 &RtpTransport::OnReadPacket);
Zhi Huang942bc2e2017-11-13 13:26:07 -080053 new_packet_transport->SignalNetworkRouteChanged.connect(
Zhi Huang365381f2018-04-13 16:44:34 -070054 this, &RtpTransport::OnNetworkRouteChanged);
Zhi Huangcd3fc5d2017-11-29 10:41:57 -080055 new_packet_transport->SignalWritableState.connect(
56 this, &RtpTransport::OnWritableState);
57 new_packet_transport->SignalSentPacket.connect(this,
58 &RtpTransport::OnSentPacket);
Zhi Huang942bc2e2017-11-13 13:26:07 -080059 // Set the network route for the new transport.
60 SignalNetworkRouteChanged(new_packet_transport->network_route());
zstein56162b92017-04-24 16:54:35 -070061 }
Zhi Huang8c316c12017-11-13 21:13:45 +000062
Zhi Huang942bc2e2017-11-13 13:26:07 -080063 rtp_packet_transport_ = new_packet_transport;
zstein56162b92017-04-24 16:54:35 -070064 // Assumes the transport is ready to send if it is writable. If we are wrong,
65 // ready to send will be updated the next time we try to send.
66 SetReadyToSend(false,
67 rtp_packet_transport_ && rtp_packet_transport_->writable());
68}
69
70void RtpTransport::SetRtcpPacketTransport(
71 rtc::PacketTransportInternal* new_packet_transport) {
72 if (new_packet_transport == rtcp_packet_transport_) {
73 return;
74 }
75 if (rtcp_packet_transport_) {
76 rtcp_packet_transport_->SignalReadyToSend.disconnect(this);
zstein3dcf0e92017-06-01 13:22:42 -070077 rtcp_packet_transport_->SignalReadPacket.disconnect(this);
Zhi Huang942bc2e2017-11-13 13:26:07 -080078 rtcp_packet_transport_->SignalNetworkRouteChanged.disconnect(this);
Zhi Huangcd3fc5d2017-11-29 10:41:57 -080079 rtcp_packet_transport_->SignalWritableState.disconnect(this);
80 rtcp_packet_transport_->SignalSentPacket.disconnect(this);
Zhi Huang942bc2e2017-11-13 13:26:07 -080081 // Reset the network route of the old transport.
Danil Chapovalov66cadcc2018-06-19 16:47:43 +020082 SignalNetworkRouteChanged(absl::optional<rtc::NetworkRoute>());
zstein56162b92017-04-24 16:54:35 -070083 }
84 if (new_packet_transport) {
85 new_packet_transport->SignalReadyToSend.connect(
86 this, &RtpTransport::OnReadyToSend);
zstein3dcf0e92017-06-01 13:22:42 -070087 new_packet_transport->SignalReadPacket.connect(this,
88 &RtpTransport::OnReadPacket);
Zhi Huang942bc2e2017-11-13 13:26:07 -080089 new_packet_transport->SignalNetworkRouteChanged.connect(
Zhi Huang365381f2018-04-13 16:44:34 -070090 this, &RtpTransport::OnNetworkRouteChanged);
Zhi Huangcd3fc5d2017-11-29 10:41:57 -080091 new_packet_transport->SignalWritableState.connect(
92 this, &RtpTransport::OnWritableState);
93 new_packet_transport->SignalSentPacket.connect(this,
94 &RtpTransport::OnSentPacket);
Zhi Huang942bc2e2017-11-13 13:26:07 -080095 // Set the network route for the new transport.
96 SignalNetworkRouteChanged(new_packet_transport->network_route());
zstein56162b92017-04-24 16:54:35 -070097 }
98 rtcp_packet_transport_ = new_packet_transport;
99
100 // Assumes the transport is ready to send if it is writable. If we are wrong,
101 // ready to send will be updated the next time we try to send.
102 SetReadyToSend(true,
103 rtcp_packet_transport_ && rtcp_packet_transport_->writable());
104}
105
106bool RtpTransport::IsWritable(bool rtcp) const {
107 rtc::PacketTransportInternal* transport = rtcp && !rtcp_mux_enabled_
108 ? rtcp_packet_transport_
109 : rtp_packet_transport_;
110 return transport && transport->writable();
111}
112
Zhi Huangcf990f52017-09-22 12:12:30 -0700113bool RtpTransport::SendRtpPacket(rtc::CopyOnWriteBuffer* packet,
114 const rtc::PacketOptions& options,
115 int flags) {
116 return SendPacket(false, packet, options, flags);
117}
118
119bool RtpTransport::SendRtcpPacket(rtc::CopyOnWriteBuffer* packet,
120 const rtc::PacketOptions& options,
121 int flags) {
122 return SendPacket(true, packet, options, flags);
123}
124
zstein56162b92017-04-24 16:54:35 -0700125bool RtpTransport::SendPacket(bool rtcp,
zstein398c3fd2017-07-19 13:38:02 -0700126 rtc::CopyOnWriteBuffer* packet,
zstein56162b92017-04-24 16:54:35 -0700127 const rtc::PacketOptions& options,
128 int flags) {
129 rtc::PacketTransportInternal* transport = rtcp && !rtcp_mux_enabled_
130 ? rtcp_packet_transport_
131 : rtp_packet_transport_;
Amit Hilbuche7a5f7b2019-03-12 11:10:27 -0700132 int ret = transport->SendPacket(packet->cdata<char>(), packet->size(),
133 options, flags);
zstein56162b92017-04-24 16:54:35 -0700134 if (ret != static_cast<int>(packet->size())) {
135 if (transport->GetError() == ENOTCONN) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100136 RTC_LOG(LS_WARNING) << "Got ENOTCONN from transport.";
zstein56162b92017-04-24 16:54:35 -0700137 SetReadyToSend(rtcp, false);
138 }
139 return false;
140 }
141 return true;
zsteind48dbda2017-04-04 19:45:57 -0700142}
143
Zhi Huang365381f2018-04-13 16:44:34 -0700144void RtpTransport::UpdateRtpHeaderExtensionMap(
145 const cricket::RtpHeaderExtensions& header_extensions) {
146 header_extension_map_ = RtpHeaderExtensionMap(header_extensions);
147}
148
149bool RtpTransport::RegisterRtpDemuxerSink(const RtpDemuxerCriteria& criteria,
150 RtpPacketSinkInterface* sink) {
151 rtp_demuxer_.RemoveSink(sink);
152 if (!rtp_demuxer_.AddSink(criteria, sink)) {
153 RTC_LOG(LS_ERROR) << "Failed to register the sink for RTP demuxer.";
154 return false;
155 }
156 return true;
157}
158
159bool RtpTransport::UnregisterRtpDemuxerSink(RtpPacketSinkInterface* sink) {
160 if (!rtp_demuxer_.RemoveSink(sink)) {
161 RTC_LOG(LS_ERROR) << "Failed to unregister the sink for RTP demuxer.";
162 return false;
163 }
164 return true;
165}
166
sprangdb2a9fc2017-08-09 06:42:32 -0700167RTCError RtpTransport::SetParameters(const RtpTransportParameters& parameters) {
168 if (parameters_.rtcp.mux && !parameters.rtcp.mux) {
zsteind9ce7642017-04-10 16:17:57 -0700169 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
170 "Disabling RTCP muxing is not allowed.");
171 }
zsteind9ce7642017-04-10 16:17:57 -0700172
sprangdb2a9fc2017-08-09 06:42:32 -0700173 RtpTransportParameters new_parameters = parameters;
174
175 if (new_parameters.rtcp.cname.empty()) {
176 new_parameters.rtcp.cname = parameters_.rtcp.cname;
177 }
178
179 parameters_ = new_parameters;
zsteind9ce7642017-04-10 16:17:57 -0700180 return RTCError::OK();
181}
182
sprangdb2a9fc2017-08-09 06:42:32 -0700183RtpTransportParameters RtpTransport::GetParameters() const {
184 return parameters_;
zsteind9ce7642017-04-10 16:17:57 -0700185}
186
Amit Hilbuchedd20542019-03-18 12:33:43 -0700187void RtpTransport::DemuxPacket(rtc::CopyOnWriteBuffer packet,
Niels Möllere6933812018-11-05 13:01:41 +0100188 int64_t packet_time_us) {
Zhi Huang365381f2018-04-13 16:44:34 -0700189 webrtc::RtpPacketReceived parsed_packet(&header_extension_map_);
Amit Hilbuchedd20542019-03-18 12:33:43 -0700190 if (!parsed_packet.Parse(std::move(packet))) {
Zhi Huang365381f2018-04-13 16:44:34 -0700191 RTC_LOG(LS_ERROR)
192 << "Failed to parse the incoming RTP packet before demuxing. Drop it.";
193 return;
194 }
195
Niels Möllere6933812018-11-05 13:01:41 +0100196 if (packet_time_us != -1) {
197 parsed_packet.set_arrival_time_ms((packet_time_us + 500) / 1000);
Zhi Huang365381f2018-04-13 16:44:34 -0700198 }
Steve Anton884adca2019-04-15 16:52:27 -0700199 if (!rtp_demuxer_.OnRtpPacket(parsed_packet)) {
200 RTC_LOG(LS_WARNING) << "Failed to demux RTP packet: "
201 << RtpDemuxer::DescribePacket(parsed_packet);
202 }
Zhi Huang365381f2018-04-13 16:44:34 -0700203}
204
Zhi Huang365381f2018-04-13 16:44:34 -0700205bool RtpTransport::IsTransportWritable() {
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800206 auto rtcp_packet_transport =
207 rtcp_mux_enabled_ ? nullptr : rtcp_packet_transport_;
208 return rtp_packet_transport_ && rtp_packet_transport_->writable() &&
209 (!rtcp_packet_transport || rtcp_packet_transport->writable());
210}
211
zstein56162b92017-04-24 16:54:35 -0700212void RtpTransport::OnReadyToSend(rtc::PacketTransportInternal* transport) {
213 SetReadyToSend(transport == rtcp_packet_transport_, true);
214}
215
Zhi Huang365381f2018-04-13 16:44:34 -0700216void RtpTransport::OnNetworkRouteChanged(
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200217 absl::optional<rtc::NetworkRoute> network_route) {
Zhi Huang942bc2e2017-11-13 13:26:07 -0800218 SignalNetworkRouteChanged(network_route);
219}
220
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800221void RtpTransport::OnWritableState(
222 rtc::PacketTransportInternal* packet_transport) {
223 RTC_DCHECK(packet_transport == rtp_packet_transport_ ||
224 packet_transport == rtcp_packet_transport_);
Zhi Huang365381f2018-04-13 16:44:34 -0700225 SignalWritableState(IsTransportWritable());
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800226}
227
228void RtpTransport::OnSentPacket(rtc::PacketTransportInternal* packet_transport,
229 const rtc::SentPacket& sent_packet) {
230 RTC_DCHECK(packet_transport == rtp_packet_transport_ ||
231 packet_transport == rtcp_packet_transport_);
232 SignalSentPacket(sent_packet);
233}
234
Amit Hilbuchedd20542019-03-18 12:33:43 -0700235void RtpTransport::OnRtpPacketReceived(rtc::CopyOnWriteBuffer packet,
Niels Möllere6933812018-11-05 13:01:41 +0100236 int64_t packet_time_us) {
237 DemuxPacket(packet, packet_time_us);
Zhi Huang365381f2018-04-13 16:44:34 -0700238}
239
Amit Hilbuchedd20542019-03-18 12:33:43 -0700240void RtpTransport::OnRtcpPacketReceived(rtc::CopyOnWriteBuffer packet,
Niels Möllere6933812018-11-05 13:01:41 +0100241 int64_t packet_time_us) {
Amit Hilbuchedd20542019-03-18 12:33:43 -0700242 SignalRtcpPacketReceived(&packet, packet_time_us);
Zhi Huang365381f2018-04-13 16:44:34 -0700243}
244
245void RtpTransport::OnReadPacket(rtc::PacketTransportInternal* transport,
246 const char* data,
247 size_t len,
Niels Möllere6933812018-11-05 13:01:41 +0100248 const int64_t& packet_time_us,
Zhi Huang365381f2018-04-13 16:44:34 -0700249 int flags) {
250 TRACE_EVENT0("webrtc", "RtpTransport::OnReadPacket");
251
252 // When using RTCP multiplexing we might get RTCP packets on the RTP
253 // transport. We check the RTP payload type to determine if it is RTCP.
Amit Hilbuchedd20542019-03-18 12:33:43 -0700254 auto array_view = rtc::MakeArrayView(data, len);
255 cricket::RtpPacketType packet_type = cricket::InferRtpPacketType(array_view);
Zhi Huang365381f2018-04-13 16:44:34 -0700256 // Filter out the packet that is neither RTP nor RTCP.
Amit Hilbuchedd20542019-03-18 12:33:43 -0700257 if (packet_type == cricket::RtpPacketType::kUnknown) {
258 return;
259 }
260
261 // Protect ourselves against crazy data.
262 if (!cricket::IsValidRtpPacketSize(packet_type, len)) {
263 RTC_LOG(LS_ERROR) << "Dropping incoming "
264 << cricket::RtpPacketTypeToString(packet_type)
265 << " packet: wrong size=" << len;
Zhi Huang365381f2018-04-13 16:44:34 -0700266 return;
267 }
268
269 rtc::CopyOnWriteBuffer packet(data, len);
Amit Hilbuchedd20542019-03-18 12:33:43 -0700270 if (packet_type == cricket::RtpPacketType::kRtcp) {
271 OnRtcpPacketReceived(std::move(packet), packet_time_us);
Zhi Huang365381f2018-04-13 16:44:34 -0700272 } else {
Amit Hilbuchedd20542019-03-18 12:33:43 -0700273 OnRtpPacketReceived(std::move(packet), packet_time_us);
Zhi Huang365381f2018-04-13 16:44:34 -0700274 }
275}
276
zstein56162b92017-04-24 16:54:35 -0700277void RtpTransport::SetReadyToSend(bool rtcp, bool ready) {
278 if (rtcp) {
279 rtcp_ready_to_send_ = ready;
280 } else {
281 rtp_ready_to_send_ = ready;
282 }
283
284 MaybeSignalReadyToSend();
285}
286
287void RtpTransport::MaybeSignalReadyToSend() {
288 bool ready_to_send =
289 rtp_ready_to_send_ && (rtcp_ready_to_send_ || rtcp_mux_enabled_);
290 if (ready_to_send != ready_to_send_) {
291 ready_to_send_ = ready_to_send;
292 SignalReadyToSend(ready_to_send);
293 }
294}
295
zsteind48dbda2017-04-04 19:45:57 -0700296} // namespace webrtc