1 /*
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
11 #include "pc/rtp_transport.h"
12
13 #include <errno.h>
14 #include <string>
15 #include <utility>
16
17 #include "absl/strings/string_view.h"
18 #include "api/array_view.h"
19 #include "media/base/rtp_utils.h"
20 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
21 #include "rtc_base/checks.h"
22 #include "rtc_base/copy_on_write_buffer.h"
23 #include "rtc_base/logging.h"
24 #include "rtc_base/third_party/sigslot/sigslot.h"
25 #include "rtc_base/trace_event.h"
26
27 namespace webrtc {
28
SetRtcpMuxEnabled(bool enable)29 void RtpTransport::SetRtcpMuxEnabled(bool enable) {
30 rtcp_mux_enabled_ = enable;
31 MaybeSignalReadyToSend();
32 }
33
transport_name() const34 const std::string& RtpTransport::transport_name() const {
35 return rtp_packet_transport_->transport_name();
36 }
37
SetRtpOption(rtc::Socket::Option opt,int value)38 int RtpTransport::SetRtpOption(rtc::Socket::Option opt, int value) {
39 return rtp_packet_transport_->SetOption(opt, value);
40 }
41
SetRtcpOption(rtc::Socket::Option opt,int value)42 int RtpTransport::SetRtcpOption(rtc::Socket::Option opt, int value) {
43 if (rtcp_packet_transport_) {
44 return rtcp_packet_transport_->SetOption(opt, value);
45 }
46 return -1;
47 }
48
SetRtpPacketTransport(rtc::PacketTransportInternal * new_packet_transport)49 void RtpTransport::SetRtpPacketTransport(
50 rtc::PacketTransportInternal* new_packet_transport) {
51 if (new_packet_transport == rtp_packet_transport_) {
52 return;
53 }
54 if (rtp_packet_transport_) {
55 rtp_packet_transport_->SignalReadyToSend.disconnect(this);
56 rtp_packet_transport_->SignalReadPacket.disconnect(this);
57 rtp_packet_transport_->SignalNetworkRouteChanged.disconnect(this);
58 rtp_packet_transport_->SignalWritableState.disconnect(this);
59 rtp_packet_transport_->SignalSentPacket.disconnect(this);
60 // Reset the network route of the old transport.
61 SignalNetworkRouteChanged(absl::optional<rtc::NetworkRoute>());
62 }
63 if (new_packet_transport) {
64 new_packet_transport->SignalReadyToSend.connect(
65 this, &RtpTransport::OnReadyToSend);
66 new_packet_transport->SignalReadPacket.connect(this,
67 &RtpTransport::OnReadPacket);
68 new_packet_transport->SignalNetworkRouteChanged.connect(
69 this, &RtpTransport::OnNetworkRouteChanged);
70 new_packet_transport->SignalWritableState.connect(
71 this, &RtpTransport::OnWritableState);
72 new_packet_transport->SignalSentPacket.connect(this,
73 &RtpTransport::OnSentPacket);
74 // Set the network route for the new transport.
75 SignalNetworkRouteChanged(new_packet_transport->network_route());
76 }
77
78 rtp_packet_transport_ = new_packet_transport;
79 // Assumes the transport is ready to send if it is writable. If we are wrong,
80 // ready to send will be updated the next time we try to send.
81 SetReadyToSend(false,
82 rtp_packet_transport_ && rtp_packet_transport_->writable());
83 }
84
SetRtcpPacketTransport(rtc::PacketTransportInternal * new_packet_transport)85 void RtpTransport::SetRtcpPacketTransport(
86 rtc::PacketTransportInternal* new_packet_transport) {
87 if (new_packet_transport == rtcp_packet_transport_) {
88 return;
89 }
90 if (rtcp_packet_transport_) {
91 rtcp_packet_transport_->SignalReadyToSend.disconnect(this);
92 rtcp_packet_transport_->SignalReadPacket.disconnect(this);
93 rtcp_packet_transport_->SignalNetworkRouteChanged.disconnect(this);
94 rtcp_packet_transport_->SignalWritableState.disconnect(this);
95 rtcp_packet_transport_->SignalSentPacket.disconnect(this);
96 // Reset the network route of the old transport.
97 SignalNetworkRouteChanged(absl::optional<rtc::NetworkRoute>());
98 }
99 if (new_packet_transport) {
100 new_packet_transport->SignalReadyToSend.connect(
101 this, &RtpTransport::OnReadyToSend);
102 new_packet_transport->SignalReadPacket.connect(this,
103 &RtpTransport::OnReadPacket);
104 new_packet_transport->SignalNetworkRouteChanged.connect(
105 this, &RtpTransport::OnNetworkRouteChanged);
106 new_packet_transport->SignalWritableState.connect(
107 this, &RtpTransport::OnWritableState);
108 new_packet_transport->SignalSentPacket.connect(this,
109 &RtpTransport::OnSentPacket);
110 // Set the network route for the new transport.
111 SignalNetworkRouteChanged(new_packet_transport->network_route());
112 }
113 rtcp_packet_transport_ = new_packet_transport;
114
115 // Assumes the transport is ready to send if it is writable. If we are wrong,
116 // ready to send will be updated the next time we try to send.
117 SetReadyToSend(true,
118 rtcp_packet_transport_ && rtcp_packet_transport_->writable());
119 }
120
IsWritable(bool rtcp) const121 bool RtpTransport::IsWritable(bool rtcp) const {
122 rtc::PacketTransportInternal* transport = rtcp && !rtcp_mux_enabled_
123 ? rtcp_packet_transport_
124 : rtp_packet_transport_;
125 return transport && transport->writable();
126 }
127
SendRtpPacket(rtc::CopyOnWriteBuffer * packet,const rtc::PacketOptions & options,int flags)128 bool RtpTransport::SendRtpPacket(rtc::CopyOnWriteBuffer* packet,
129 const rtc::PacketOptions& options,
130 int flags) {
131 return SendPacket(false, packet, options, flags);
132 }
133
SendRtcpPacket(rtc::CopyOnWriteBuffer * packet,const rtc::PacketOptions & options,int flags)134 bool RtpTransport::SendRtcpPacket(rtc::CopyOnWriteBuffer* packet,
135 const rtc::PacketOptions& options,
136 int flags) {
137 return SendPacket(true, packet, options, flags);
138 }
139
SendPacket(bool rtcp,rtc::CopyOnWriteBuffer * packet,const rtc::PacketOptions & options,int flags)140 bool RtpTransport::SendPacket(bool rtcp,
141 rtc::CopyOnWriteBuffer* packet,
142 const rtc::PacketOptions& options,
143 int flags) {
144 rtc::PacketTransportInternal* transport = rtcp && !rtcp_mux_enabled_
145 ? rtcp_packet_transport_
146 : rtp_packet_transport_;
147 int ret = transport->SendPacket(packet->cdata<char>(), packet->size(),
148 options, flags);
149 if (ret != static_cast<int>(packet->size())) {
150 if (transport->GetError() == ENOTCONN) {
151 RTC_LOG(LS_WARNING) << "Got ENOTCONN from transport.";
152 SetReadyToSend(rtcp, false);
153 }
154 return false;
155 }
156 return true;
157 }
158
UpdateRtpHeaderExtensionMap(const cricket::RtpHeaderExtensions & header_extensions)159 void RtpTransport::UpdateRtpHeaderExtensionMap(
160 const cricket::RtpHeaderExtensions& header_extensions) {
161 header_extension_map_ = RtpHeaderExtensionMap(header_extensions);
162 }
163
RegisterRtpDemuxerSink(const RtpDemuxerCriteria & criteria,RtpPacketSinkInterface * sink)164 bool RtpTransport::RegisterRtpDemuxerSink(const RtpDemuxerCriteria& criteria,
165 RtpPacketSinkInterface* sink) {
166 rtp_demuxer_.RemoveSink(sink);
167 if (!rtp_demuxer_.AddSink(criteria, sink)) {
168 RTC_LOG(LS_ERROR) << "Failed to register the sink for RTP demuxer.";
169 return false;
170 }
171 return true;
172 }
173
UnregisterRtpDemuxerSink(RtpPacketSinkInterface * sink)174 bool RtpTransport::UnregisterRtpDemuxerSink(RtpPacketSinkInterface* sink) {
175 if (!rtp_demuxer_.RemoveSink(sink)) {
176 RTC_LOG(LS_ERROR) << "Failed to unregister the sink for RTP demuxer.";
177 return false;
178 }
179 return true;
180 }
181
DemuxPacket(rtc::CopyOnWriteBuffer packet,int64_t packet_time_us)182 void RtpTransport::DemuxPacket(rtc::CopyOnWriteBuffer packet,
183 int64_t packet_time_us) {
184 webrtc::RtpPacketReceived parsed_packet(&header_extension_map_);
185 if (!parsed_packet.Parse(packet)) {
186 RTC_LOG(LS_ERROR)
187 << "Failed to parse the incoming RTP packet before demuxing. Drop it.";
188 return;
189 }
190
191 if (packet_time_us != -1) {
192 parsed_packet.set_arrival_time_ms((packet_time_us + 500) / 1000);
193 }
194 if (!rtp_demuxer_.OnRtpPacket(parsed_packet)) {
195 SignalRtpPacketReceived.emit(&packet, packet_time_us, true);
196 RTC_LOG(LS_WARNING) << "Failed to demux RTP packet: "
197 << RtpDemuxer::DescribePacket(parsed_packet);
198 } else {
199 SignalRtpPacketReceived.emit(&packet, packet_time_us, false);
200 }
201 }
202
IsTransportWritable()203 bool RtpTransport::IsTransportWritable() {
204 auto rtcp_packet_transport =
205 rtcp_mux_enabled_ ? nullptr : rtcp_packet_transport_;
206 return rtp_packet_transport_ && rtp_packet_transport_->writable() &&
207 (!rtcp_packet_transport || rtcp_packet_transport->writable());
208 }
209
OnReadyToSend(rtc::PacketTransportInternal * transport)210 void RtpTransport::OnReadyToSend(rtc::PacketTransportInternal* transport) {
211 SetReadyToSend(transport == rtcp_packet_transport_, true);
212 }
213
OnNetworkRouteChanged(absl::optional<rtc::NetworkRoute> network_route)214 void RtpTransport::OnNetworkRouteChanged(
215 absl::optional<rtc::NetworkRoute> network_route) {
216 SignalNetworkRouteChanged(network_route);
217 }
218
OnWritableState(rtc::PacketTransportInternal * packet_transport)219 void RtpTransport::OnWritableState(
220 rtc::PacketTransportInternal* packet_transport) {
221 RTC_DCHECK(packet_transport == rtp_packet_transport_ ||
222 packet_transport == rtcp_packet_transport_);
223 SignalWritableState(IsTransportWritable());
224 }
225
OnSentPacket(rtc::PacketTransportInternal * packet_transport,const rtc::SentPacket & sent_packet)226 void RtpTransport::OnSentPacket(rtc::PacketTransportInternal* packet_transport,
227 const rtc::SentPacket& sent_packet) {
228 RTC_DCHECK(packet_transport == rtp_packet_transport_ ||
229 packet_transport == rtcp_packet_transport_);
230 SignalSentPacket(sent_packet);
231 }
232
OnRtpPacketReceived(rtc::CopyOnWriteBuffer packet,int64_t packet_time_us)233 void RtpTransport::OnRtpPacketReceived(rtc::CopyOnWriteBuffer packet,
234 int64_t packet_time_us) {
235 DemuxPacket(packet, packet_time_us);
236 }
237
OnRtcpPacketReceived(rtc::CopyOnWriteBuffer packet,int64_t packet_time_us)238 void RtpTransport::OnRtcpPacketReceived(rtc::CopyOnWriteBuffer packet,
239 int64_t packet_time_us) {
240 SignalRtcpPacketReceived(&packet, packet_time_us);
241 }
242
OnReadPacket(rtc::PacketTransportInternal * transport,const char * data,size_t len,const int64_t & packet_time_us,int flags)243 void RtpTransport::OnReadPacket(rtc::PacketTransportInternal* transport,
244 const char* data,
245 size_t len,
246 const int64_t& packet_time_us,
247 int flags) {
248 TRACE_EVENT0("webrtc", "RtpTransport::OnReadPacket");
249
250 // When using RTCP multiplexing we might get RTCP packets on the RTP
251 // transport. We check the RTP payload type to determine if it is RTCP.
252 auto array_view = rtc::MakeArrayView(data, len);
253 cricket::RtpPacketType packet_type = cricket::InferRtpPacketType(array_view);
254 // Filter out the packet that is neither RTP nor RTCP.
255 if (packet_type == cricket::RtpPacketType::kUnknown) {
256 return;
257 }
258
259 // Protect ourselves against crazy data.
260 if (!cricket::IsValidRtpPacketSize(packet_type, len)) {
261 RTC_LOG(LS_ERROR) << "Dropping incoming "
262 << cricket::RtpPacketTypeToString(packet_type)
263 << " packet: wrong size=" << len;
264 return;
265 }
266
267 rtc::CopyOnWriteBuffer packet(data, len);
268 if (packet_type == cricket::RtpPacketType::kRtcp) {
269 OnRtcpPacketReceived(std::move(packet), packet_time_us);
270 } else {
271 OnRtpPacketReceived(std::move(packet), packet_time_us);
272 }
273 }
274
SetReadyToSend(bool rtcp,bool ready)275 void RtpTransport::SetReadyToSend(bool rtcp, bool ready) {
276 if (rtcp) {
277 rtcp_ready_to_send_ = ready;
278 } else {
279 rtp_ready_to_send_ = ready;
280 }
281
282 MaybeSignalReadyToSend();
283 }
284
MaybeSignalReadyToSend()285 void RtpTransport::MaybeSignalReadyToSend() {
286 bool ready_to_send =
287 rtp_ready_to_send_ && (rtcp_ready_to_send_ || rtcp_mux_enabled_);
288 if (ready_to_send != ready_to_send_) {
289 ready_to_send_ = ready_to_send;
290 SignalReadyToSend(ready_to_send);
291 }
292 }
293
294 } // namespace webrtc
295