blob: 8ef597f58ff253217c325e0f7c09417dc6eb09e7 [file] [log] [blame]
zsteind48dbda2017-04-05 02:45:571/*
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 17:11:0011#include "pc/rtp_transport.h"
zsteind48dbda2017-04-05 02:45:5712
Yves Gerey3e707812018-11-28 15:47:4913#include <errno.h>
Harald Alvestrandc24a2182022-02-23 13:44:5914
15#include <cstdint>
Zhi Huang365381f2018-04-13 23:44:3416#include <utility>
17
Harald Alvestrand5761e7b2021-01-29 14:45:0818#include "absl/strings/string_view.h"
19#include "api/array_view.h"
Harald Alvestrandc24a2182022-02-23 13:44:5920#include "api/units/timestamp.h"
Steve Anton10542f22019-01-11 17:11:0021#include "media/base/rtp_utils.h"
Zhi Huang365381f2018-04-13 23:44:3422#include "modules/rtp_rtcp/source/rtp_packet_received.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3123#include "rtc_base/checks.h"
Steve Anton10542f22019-01-11 17:11:0024#include "rtc_base/copy_on_write_buffer.h"
Yves Gerey3e707812018-11-28 15:47:4925#include "rtc_base/logging.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3126#include "rtc_base/trace_event.h"
zsteind48dbda2017-04-05 02:45:5727
28namespace webrtc {
29
zstein56162b92017-04-24 23:54:3530void RtpTransport::SetRtcpMuxEnabled(bool enable) {
31 rtcp_mux_enabled_ = enable;
32 MaybeSignalReadyToSend();
zsteind9ce7642017-04-10 23:17:5733}
34
Bjorn A Mellem3a1b9272019-05-24 23:13:0835const std::string& RtpTransport::transport_name() const {
36 return rtp_packet_transport_->transport_name();
37}
38
39int RtpTransport::SetRtpOption(rtc::Socket::Option opt, int value) {
40 return rtp_packet_transport_->SetOption(opt, value);
41}
42
43int RtpTransport::SetRtcpOption(rtc::Socket::Option opt, int value) {
44 if (rtcp_packet_transport_) {
45 return rtcp_packet_transport_->SetOption(opt, value);
46 }
47 return -1;
48}
49
zstein56162b92017-04-24 23:54:3550void RtpTransport::SetRtpPacketTransport(
51 rtc::PacketTransportInternal* new_packet_transport) {
52 if (new_packet_transport == rtp_packet_transport_) {
53 return;
54 }
55 if (rtp_packet_transport_) {
56 rtp_packet_transport_->SignalReadyToSend.disconnect(this);
zstein3dcf0e92017-06-01 20:22:4257 rtp_packet_transport_->SignalReadPacket.disconnect(this);
Zhi Huang942bc2e2017-11-13 21:26:0758 rtp_packet_transport_->SignalNetworkRouteChanged.disconnect(this);
Zhi Huangcd3fc5d2017-11-29 18:41:5759 rtp_packet_transport_->SignalWritableState.disconnect(this);
60 rtp_packet_transport_->SignalSentPacket.disconnect(this);
Zhi Huang942bc2e2017-11-13 21:26:0761 // Reset the network route of the old transport.
Danil Chapovalov66cadcc2018-06-19 14:47:4362 SignalNetworkRouteChanged(absl::optional<rtc::NetworkRoute>());
zstein56162b92017-04-24 23:54:3563 }
64 if (new_packet_transport) {
65 new_packet_transport->SignalReadyToSend.connect(
66 this, &RtpTransport::OnReadyToSend);
zstein3dcf0e92017-06-01 20:22:4267 new_packet_transport->SignalReadPacket.connect(this,
68 &RtpTransport::OnReadPacket);
Zhi Huang942bc2e2017-11-13 21:26:0769 new_packet_transport->SignalNetworkRouteChanged.connect(
Zhi Huang365381f2018-04-13 23:44:3470 this, &RtpTransport::OnNetworkRouteChanged);
Zhi Huangcd3fc5d2017-11-29 18:41:5771 new_packet_transport->SignalWritableState.connect(
72 this, &RtpTransport::OnWritableState);
73 new_packet_transport->SignalSentPacket.connect(this,
74 &RtpTransport::OnSentPacket);
Zhi Huang942bc2e2017-11-13 21:26:0775 // Set the network route for the new transport.
76 SignalNetworkRouteChanged(new_packet_transport->network_route());
zstein56162b92017-04-24 23:54:3577 }
Zhi Huang8c316c12017-11-13 21:13:4578
Zhi Huang942bc2e2017-11-13 21:26:0779 rtp_packet_transport_ = new_packet_transport;
zstein56162b92017-04-24 23:54:3580 // Assumes the transport is ready to send if it is writable. If we are wrong,
81 // ready to send will be updated the next time we try to send.
82 SetReadyToSend(false,
83 rtp_packet_transport_ && rtp_packet_transport_->writable());
84}
85
86void RtpTransport::SetRtcpPacketTransport(
87 rtc::PacketTransportInternal* new_packet_transport) {
88 if (new_packet_transport == rtcp_packet_transport_) {
89 return;
90 }
91 if (rtcp_packet_transport_) {
92 rtcp_packet_transport_->SignalReadyToSend.disconnect(this);
zstein3dcf0e92017-06-01 20:22:4293 rtcp_packet_transport_->SignalReadPacket.disconnect(this);
Zhi Huang942bc2e2017-11-13 21:26:0794 rtcp_packet_transport_->SignalNetworkRouteChanged.disconnect(this);
Zhi Huangcd3fc5d2017-11-29 18:41:5795 rtcp_packet_transport_->SignalWritableState.disconnect(this);
96 rtcp_packet_transport_->SignalSentPacket.disconnect(this);
Zhi Huang942bc2e2017-11-13 21:26:0797 // Reset the network route of the old transport.
Danil Chapovalov66cadcc2018-06-19 14:47:4398 SignalNetworkRouteChanged(absl::optional<rtc::NetworkRoute>());
zstein56162b92017-04-24 23:54:3599 }
100 if (new_packet_transport) {
101 new_packet_transport->SignalReadyToSend.connect(
102 this, &RtpTransport::OnReadyToSend);
zstein3dcf0e92017-06-01 20:22:42103 new_packet_transport->SignalReadPacket.connect(this,
104 &RtpTransport::OnReadPacket);
Zhi Huang942bc2e2017-11-13 21:26:07105 new_packet_transport->SignalNetworkRouteChanged.connect(
Zhi Huang365381f2018-04-13 23:44:34106 this, &RtpTransport::OnNetworkRouteChanged);
Zhi Huangcd3fc5d2017-11-29 18:41:57107 new_packet_transport->SignalWritableState.connect(
108 this, &RtpTransport::OnWritableState);
109 new_packet_transport->SignalSentPacket.connect(this,
110 &RtpTransport::OnSentPacket);
Zhi Huang942bc2e2017-11-13 21:26:07111 // Set the network route for the new transport.
112 SignalNetworkRouteChanged(new_packet_transport->network_route());
zstein56162b92017-04-24 23:54:35113 }
114 rtcp_packet_transport_ = new_packet_transport;
115
116 // Assumes the transport is ready to send if it is writable. If we are wrong,
117 // ready to send will be updated the next time we try to send.
118 SetReadyToSend(true,
119 rtcp_packet_transport_ && rtcp_packet_transport_->writable());
120}
121
122bool RtpTransport::IsWritable(bool rtcp) const {
123 rtc::PacketTransportInternal* transport = rtcp && !rtcp_mux_enabled_
124 ? rtcp_packet_transport_
125 : rtp_packet_transport_;
126 return transport && transport->writable();
127}
128
Zhi Huangcf990f52017-09-22 19:12:30129bool RtpTransport::SendRtpPacket(rtc::CopyOnWriteBuffer* packet,
130 const rtc::PacketOptions& options,
131 int flags) {
132 return SendPacket(false, packet, options, flags);
133}
134
135bool RtpTransport::SendRtcpPacket(rtc::CopyOnWriteBuffer* packet,
136 const rtc::PacketOptions& options,
137 int flags) {
138 return SendPacket(true, packet, options, flags);
139}
140
zstein56162b92017-04-24 23:54:35141bool RtpTransport::SendPacket(bool rtcp,
zstein398c3fd2017-07-19 20:38:02142 rtc::CopyOnWriteBuffer* packet,
zstein56162b92017-04-24 23:54:35143 const rtc::PacketOptions& options,
144 int flags) {
145 rtc::PacketTransportInternal* transport = rtcp && !rtcp_mux_enabled_
146 ? rtcp_packet_transport_
147 : rtp_packet_transport_;
Amit Hilbuche7a5f7b2019-03-12 18:10:27148 int ret = transport->SendPacket(packet->cdata<char>(), packet->size(),
149 options, flags);
zstein56162b92017-04-24 23:54:35150 if (ret != static_cast<int>(packet->size())) {
151 if (transport->GetError() == ENOTCONN) {
Mirko Bonadei675513b2017-11-09 10:09:25152 RTC_LOG(LS_WARNING) << "Got ENOTCONN from transport.";
zstein56162b92017-04-24 23:54:35153 SetReadyToSend(rtcp, false);
154 }
155 return false;
156 }
157 return true;
zsteind48dbda2017-04-05 02:45:57158}
159
Zhi Huang365381f2018-04-13 23:44:34160void RtpTransport::UpdateRtpHeaderExtensionMap(
161 const cricket::RtpHeaderExtensions& header_extensions) {
162 header_extension_map_ = RtpHeaderExtensionMap(header_extensions);
163}
164
165bool RtpTransport::RegisterRtpDemuxerSink(const RtpDemuxerCriteria& criteria,
166 RtpPacketSinkInterface* sink) {
167 rtp_demuxer_.RemoveSink(sink);
168 if (!rtp_demuxer_.AddSink(criteria, sink)) {
169 RTC_LOG(LS_ERROR) << "Failed to register the sink for RTP demuxer.";
170 return false;
171 }
172 return true;
173}
174
175bool RtpTransport::UnregisterRtpDemuxerSink(RtpPacketSinkInterface* sink) {
176 if (!rtp_demuxer_.RemoveSink(sink)) {
177 RTC_LOG(LS_ERROR) << "Failed to unregister the sink for RTP demuxer.";
178 return false;
179 }
180 return true;
181}
182
Amit Hilbuchedd20542019-03-18 19:33:43183void RtpTransport::DemuxPacket(rtc::CopyOnWriteBuffer packet,
Niels Möllere6933812018-11-05 12:01:41184 int64_t packet_time_us) {
Tommi2497a272021-05-05 10:33:00185 webrtc::RtpPacketReceived parsed_packet(
186 &header_extension_map_, packet_time_us == -1
187 ? Timestamp::MinusInfinity()
188 : Timestamp::Micros(packet_time_us));
Amit Hilbuchedd20542019-03-18 19:33:43189 if (!parsed_packet.Parse(std::move(packet))) {
Zhi Huang365381f2018-04-13 23:44:34190 RTC_LOG(LS_ERROR)
191 << "Failed to parse the incoming RTP packet before demuxing. Drop it.";
192 return;
193 }
194
Steve Anton884adca2019-04-15 23:52:27195 if (!rtp_demuxer_.OnRtpPacket(parsed_packet)) {
Per Ke1e94ad2023-03-30 14:53:59196 RTC_LOG(LS_VERBOSE) << "Failed to demux RTP packet: "
Steve Anton884adca2019-04-15 23:52:27197 << RtpDemuxer::DescribePacket(parsed_packet);
Per Ke1e94ad2023-03-30 14:53:59198 SignalUnDemuxableRtpPacketReceived(parsed_packet);
Steve Anton884adca2019-04-15 23:52:27199 }
Zhi Huang365381f2018-04-13 23:44:34200}
201
Zhi Huang365381f2018-04-13 23:44:34202bool RtpTransport::IsTransportWritable() {
Zhi Huangcd3fc5d2017-11-29 18:41:57203 auto rtcp_packet_transport =
204 rtcp_mux_enabled_ ? nullptr : rtcp_packet_transport_;
205 return rtp_packet_transport_ && rtp_packet_transport_->writable() &&
206 (!rtcp_packet_transport || rtcp_packet_transport->writable());
207}
208
zstein56162b92017-04-24 23:54:35209void RtpTransport::OnReadyToSend(rtc::PacketTransportInternal* transport) {
210 SetReadyToSend(transport == rtcp_packet_transport_, true);
211}
212
Zhi Huang365381f2018-04-13 23:44:34213void RtpTransport::OnNetworkRouteChanged(
Danil Chapovalov66cadcc2018-06-19 14:47:43214 absl::optional<rtc::NetworkRoute> network_route) {
Zhi Huang942bc2e2017-11-13 21:26:07215 SignalNetworkRouteChanged(network_route);
216}
217
Zhi Huangcd3fc5d2017-11-29 18:41:57218void RtpTransport::OnWritableState(
219 rtc::PacketTransportInternal* packet_transport) {
220 RTC_DCHECK(packet_transport == rtp_packet_transport_ ||
221 packet_transport == rtcp_packet_transport_);
Zhi Huang365381f2018-04-13 23:44:34222 SignalWritableState(IsTransportWritable());
Zhi Huangcd3fc5d2017-11-29 18:41:57223}
224
225void RtpTransport::OnSentPacket(rtc::PacketTransportInternal* packet_transport,
226 const rtc::SentPacket& sent_packet) {
227 RTC_DCHECK(packet_transport == rtp_packet_transport_ ||
228 packet_transport == rtcp_packet_transport_);
229 SignalSentPacket(sent_packet);
230}
231
Amit Hilbuchedd20542019-03-18 19:33:43232void RtpTransport::OnRtpPacketReceived(rtc::CopyOnWriteBuffer packet,
Niels Möllere6933812018-11-05 12:01:41233 int64_t packet_time_us) {
234 DemuxPacket(packet, packet_time_us);
Zhi Huang365381f2018-04-13 23:44:34235}
236
Amit Hilbuchedd20542019-03-18 19:33:43237void RtpTransport::OnRtcpPacketReceived(rtc::CopyOnWriteBuffer packet,
Niels Möllere6933812018-11-05 12:01:41238 int64_t packet_time_us) {
Amit Hilbuchedd20542019-03-18 19:33:43239 SignalRtcpPacketReceived(&packet, packet_time_us);
Zhi Huang365381f2018-04-13 23:44:34240}
241
242void RtpTransport::OnReadPacket(rtc::PacketTransportInternal* transport,
243 const char* data,
244 size_t len,
Niels Möllere6933812018-11-05 12:01:41245 const int64_t& packet_time_us,
Zhi Huang365381f2018-04-13 23:44:34246 int flags) {
247 TRACE_EVENT0("webrtc", "RtpTransport::OnReadPacket");
248
249 // When using RTCP multiplexing we might get RTCP packets on the RTP
250 // transport. We check the RTP payload type to determine if it is RTCP.
Amit Hilbuchedd20542019-03-18 19:33:43251 auto array_view = rtc::MakeArrayView(data, len);
252 cricket::RtpPacketType packet_type = cricket::InferRtpPacketType(array_view);
Zhi Huang365381f2018-04-13 23:44:34253 // Filter out the packet that is neither RTP nor RTCP.
Amit Hilbuchedd20542019-03-18 19:33:43254 if (packet_type == cricket::RtpPacketType::kUnknown) {
255 return;
256 }
257
258 // Protect ourselves against crazy data.
259 if (!cricket::IsValidRtpPacketSize(packet_type, len)) {
260 RTC_LOG(LS_ERROR) << "Dropping incoming "
261 << cricket::RtpPacketTypeToString(packet_type)
262 << " packet: wrong size=" << len;
Zhi Huang365381f2018-04-13 23:44:34263 return;
264 }
265
266 rtc::CopyOnWriteBuffer packet(data, len);
Amit Hilbuchedd20542019-03-18 19:33:43267 if (packet_type == cricket::RtpPacketType::kRtcp) {
268 OnRtcpPacketReceived(std::move(packet), packet_time_us);
Zhi Huang365381f2018-04-13 23:44:34269 } else {
Amit Hilbuchedd20542019-03-18 19:33:43270 OnRtpPacketReceived(std::move(packet), packet_time_us);
Zhi Huang365381f2018-04-13 23:44:34271 }
272}
273
zstein56162b92017-04-24 23:54:35274void RtpTransport::SetReadyToSend(bool rtcp, bool ready) {
275 if (rtcp) {
276 rtcp_ready_to_send_ = ready;
277 } else {
278 rtp_ready_to_send_ = ready;
279 }
280
281 MaybeSignalReadyToSend();
282}
283
284void RtpTransport::MaybeSignalReadyToSend() {
285 bool ready_to_send =
286 rtp_ready_to_send_ && (rtcp_ready_to_send_ || rtcp_mux_enabled_);
287 if (ready_to_send != ready_to_send_) {
288 ready_to_send_ = ready_to_send;
289 SignalReadyToSend(ready_to_send);
290 }
291}
292
zsteind48dbda2017-04-05 02:45:57293} // namespace webrtc