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