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