blob: 366d6e2fc855f20792fe993c25ddf37082c21c02 [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "pc/rtptransport.h"
zsteind48dbda2017-04-04 19:45:57 -070012
Zhi Huang365381f2018-04-13 16:44:34 -070013#include <utility>
14
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "media/base/rtputils.h"
Zhi Huang365381f2018-04-13 16:44:34 -070016#include "modules/rtp_rtcp/source/rtp_packet_received.h"
Zhi Huang942bc2e2017-11-13 13:26:07 -080017#include "p2p/base/p2pconstants.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "p2p/base/packettransportinterface.h"
19#include "rtc_base/checks.h"
20#include "rtc_base/copyonwritebuffer.h"
21#include "rtc_base/trace_event.h"
zsteind48dbda2017-04-04 19:45:57 -070022
23namespace webrtc {
24
zstein56162b92017-04-24 16:54:35 -070025void RtpTransport::SetRtcpMuxEnabled(bool enable) {
26 rtcp_mux_enabled_ = enable;
27 MaybeSignalReadyToSend();
zsteind9ce7642017-04-10 16:17:57 -070028}
29
zstein56162b92017-04-24 16:54:35 -070030void RtpTransport::SetRtpPacketTransport(
31 rtc::PacketTransportInternal* new_packet_transport) {
32 if (new_packet_transport == rtp_packet_transport_) {
33 return;
34 }
35 if (rtp_packet_transport_) {
36 rtp_packet_transport_->SignalReadyToSend.disconnect(this);
zstein3dcf0e92017-06-01 13:22:42 -070037 rtp_packet_transport_->SignalReadPacket.disconnect(this);
Zhi Huang942bc2e2017-11-13 13:26:07 -080038 rtp_packet_transport_->SignalNetworkRouteChanged.disconnect(this);
Zhi Huangcd3fc5d2017-11-29 10:41:57 -080039 rtp_packet_transport_->SignalWritableState.disconnect(this);
40 rtp_packet_transport_->SignalSentPacket.disconnect(this);
Zhi Huang942bc2e2017-11-13 13:26:07 -080041 // Reset the network route of the old transport.
42 SignalNetworkRouteChanged(rtc::Optional<rtc::NetworkRoute>());
zstein56162b92017-04-24 16:54:35 -070043 }
44 if (new_packet_transport) {
45 new_packet_transport->SignalReadyToSend.connect(
46 this, &RtpTransport::OnReadyToSend);
zstein3dcf0e92017-06-01 13:22:42 -070047 new_packet_transport->SignalReadPacket.connect(this,
48 &RtpTransport::OnReadPacket);
Zhi Huang942bc2e2017-11-13 13:26:07 -080049 new_packet_transport->SignalNetworkRouteChanged.connect(
Zhi Huang365381f2018-04-13 16:44:34 -070050 this, &RtpTransport::OnNetworkRouteChanged);
Zhi Huangcd3fc5d2017-11-29 10:41:57 -080051 new_packet_transport->SignalWritableState.connect(
52 this, &RtpTransport::OnWritableState);
53 new_packet_transport->SignalSentPacket.connect(this,
54 &RtpTransport::OnSentPacket);
Zhi Huang942bc2e2017-11-13 13:26:07 -080055 // Set the network route for the new transport.
56 SignalNetworkRouteChanged(new_packet_transport->network_route());
zstein56162b92017-04-24 16:54:35 -070057 }
Zhi Huang8c316c12017-11-13 21:13:45 +000058
Zhi Huang942bc2e2017-11-13 13:26:07 -080059 rtp_packet_transport_ = new_packet_transport;
zstein56162b92017-04-24 16:54:35 -070060 // Assumes the transport is ready to send if it is writable. If we are wrong,
61 // ready to send will be updated the next time we try to send.
62 SetReadyToSend(false,
63 rtp_packet_transport_ && rtp_packet_transport_->writable());
64}
65
66void RtpTransport::SetRtcpPacketTransport(
67 rtc::PacketTransportInternal* new_packet_transport) {
68 if (new_packet_transport == rtcp_packet_transport_) {
69 return;
70 }
71 if (rtcp_packet_transport_) {
72 rtcp_packet_transport_->SignalReadyToSend.disconnect(this);
zstein3dcf0e92017-06-01 13:22:42 -070073 rtcp_packet_transport_->SignalReadPacket.disconnect(this);
Zhi Huang942bc2e2017-11-13 13:26:07 -080074 rtcp_packet_transport_->SignalNetworkRouteChanged.disconnect(this);
Zhi Huangcd3fc5d2017-11-29 10:41:57 -080075 rtcp_packet_transport_->SignalWritableState.disconnect(this);
76 rtcp_packet_transport_->SignalSentPacket.disconnect(this);
Zhi Huang942bc2e2017-11-13 13:26:07 -080077 // Reset the network route of the old transport.
78 SignalNetworkRouteChanged(rtc::Optional<rtc::NetworkRoute>());
zstein56162b92017-04-24 16:54:35 -070079 }
80 if (new_packet_transport) {
81 new_packet_transport->SignalReadyToSend.connect(
82 this, &RtpTransport::OnReadyToSend);
zstein3dcf0e92017-06-01 13:22:42 -070083 new_packet_transport->SignalReadPacket.connect(this,
84 &RtpTransport::OnReadPacket);
Zhi Huang942bc2e2017-11-13 13:26:07 -080085 new_packet_transport->SignalNetworkRouteChanged.connect(
Zhi Huang365381f2018-04-13 16:44:34 -070086 this, &RtpTransport::OnNetworkRouteChanged);
Zhi Huangcd3fc5d2017-11-29 10:41:57 -080087 new_packet_transport->SignalWritableState.connect(
88 this, &RtpTransport::OnWritableState);
89 new_packet_transport->SignalSentPacket.connect(this,
90 &RtpTransport::OnSentPacket);
Zhi Huang942bc2e2017-11-13 13:26:07 -080091 // Set the network route for the new transport.
92 SignalNetworkRouteChanged(new_packet_transport->network_route());
zstein56162b92017-04-24 16:54:35 -070093 }
94 rtcp_packet_transport_ = new_packet_transport;
95
96 // Assumes the transport is ready to send if it is writable. If we are wrong,
97 // ready to send will be updated the next time we try to send.
98 SetReadyToSend(true,
99 rtcp_packet_transport_ && rtcp_packet_transport_->writable());
100}
101
102bool RtpTransport::IsWritable(bool rtcp) const {
103 rtc::PacketTransportInternal* transport = rtcp && !rtcp_mux_enabled_
104 ? rtcp_packet_transport_
105 : rtp_packet_transport_;
106 return transport && transport->writable();
107}
108
Zhi Huangcf990f52017-09-22 12:12:30 -0700109bool RtpTransport::SendRtpPacket(rtc::CopyOnWriteBuffer* packet,
110 const rtc::PacketOptions& options,
111 int flags) {
112 return SendPacket(false, packet, options, flags);
113}
114
115bool RtpTransport::SendRtcpPacket(rtc::CopyOnWriteBuffer* packet,
116 const rtc::PacketOptions& options,
117 int flags) {
118 return SendPacket(true, packet, options, flags);
119}
120
zstein56162b92017-04-24 16:54:35 -0700121bool RtpTransport::SendPacket(bool rtcp,
zstein398c3fd2017-07-19 13:38:02 -0700122 rtc::CopyOnWriteBuffer* packet,
zstein56162b92017-04-24 16:54:35 -0700123 const rtc::PacketOptions& options,
124 int flags) {
125 rtc::PacketTransportInternal* transport = rtcp && !rtcp_mux_enabled_
126 ? rtcp_packet_transport_
127 : rtp_packet_transport_;
128 int ret = transport->SendPacket(packet->data<char>(), packet->size(), options,
129 flags);
130 if (ret != static_cast<int>(packet->size())) {
131 if (transport->GetError() == ENOTCONN) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100132 RTC_LOG(LS_WARNING) << "Got ENOTCONN from transport.";
zstein56162b92017-04-24 16:54:35 -0700133 SetReadyToSend(rtcp, false);
134 }
135 return false;
136 }
137 return true;
zsteind48dbda2017-04-04 19:45:57 -0700138}
139
Zhi Huang365381f2018-04-13 16:44:34 -0700140void RtpTransport::UpdateRtpHeaderExtensionMap(
141 const cricket::RtpHeaderExtensions& header_extensions) {
142 header_extension_map_ = RtpHeaderExtensionMap(header_extensions);
143}
144
145bool RtpTransport::RegisterRtpDemuxerSink(const RtpDemuxerCriteria& criteria,
146 RtpPacketSinkInterface* sink) {
147 rtp_demuxer_.RemoveSink(sink);
148 if (!rtp_demuxer_.AddSink(criteria, sink)) {
149 RTC_LOG(LS_ERROR) << "Failed to register the sink for RTP demuxer.";
150 return false;
151 }
152 return true;
153}
154
155bool RtpTransport::UnregisterRtpDemuxerSink(RtpPacketSinkInterface* sink) {
156 if (!rtp_demuxer_.RemoveSink(sink)) {
157 RTC_LOG(LS_ERROR) << "Failed to unregister the sink for RTP demuxer.";
158 return false;
159 }
160 return true;
161}
162
sprangdb2a9fc2017-08-09 06:42:32 -0700163RTCError RtpTransport::SetParameters(const RtpTransportParameters& parameters) {
164 if (parameters_.rtcp.mux && !parameters.rtcp.mux) {
zsteind9ce7642017-04-10 16:17:57 -0700165 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
166 "Disabling RTCP muxing is not allowed.");
167 }
sprangdb2a9fc2017-08-09 06:42:32 -0700168 if (parameters.keepalive != parameters_.keepalive) {
169 // TODO(sprang): Wire up support for keep-alive (only ORTC support for now).
170 LOG_AND_RETURN_ERROR(
171 RTCErrorType::INVALID_MODIFICATION,
172 "RTP keep-alive parameters not supported by this channel.");
zsteind9ce7642017-04-10 16:17:57 -0700173 }
174
sprangdb2a9fc2017-08-09 06:42:32 -0700175 RtpTransportParameters new_parameters = parameters;
176
177 if (new_parameters.rtcp.cname.empty()) {
178 new_parameters.rtcp.cname = parameters_.rtcp.cname;
179 }
180
181 parameters_ = new_parameters;
zsteind9ce7642017-04-10 16:17:57 -0700182 return RTCError::OK();
183}
184
sprangdb2a9fc2017-08-09 06:42:32 -0700185RtpTransportParameters RtpTransport::GetParameters() const {
186 return parameters_;
zsteind9ce7642017-04-10 16:17:57 -0700187}
188
Zhi Huang365381f2018-04-13 16:44:34 -0700189void RtpTransport::DemuxPacket(rtc::CopyOnWriteBuffer* packet,
190 const rtc::PacketTime& time) {
191 webrtc::RtpPacketReceived parsed_packet(&header_extension_map_);
192 if (!parsed_packet.Parse(std::move(*packet))) {
193 RTC_LOG(LS_ERROR)
194 << "Failed to parse the incoming RTP packet before demuxing. Drop it.";
195 return;
196 }
197
198 if (time.timestamp != -1) {
199 parsed_packet.set_arrival_time_ms((time.timestamp + 500) / 1000);
200 }
201 rtp_demuxer_.OnRtpPacket(parsed_packet);
202}
203
zsteind9ce7642017-04-10 16:17:57 -0700204RtpTransportAdapter* RtpTransport::GetInternal() {
205 return nullptr;
206}
207
Zhi Huang365381f2018-04-13 16:44:34 -0700208bool RtpTransport::IsTransportWritable() {
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800209 auto rtcp_packet_transport =
210 rtcp_mux_enabled_ ? nullptr : rtcp_packet_transport_;
211 return rtp_packet_transport_ && rtp_packet_transport_->writable() &&
212 (!rtcp_packet_transport || rtcp_packet_transport->writable());
213}
214
zstein56162b92017-04-24 16:54:35 -0700215void RtpTransport::OnReadyToSend(rtc::PacketTransportInternal* transport) {
216 SetReadyToSend(transport == rtcp_packet_transport_, true);
217}
218
Zhi Huang365381f2018-04-13 16:44:34 -0700219void RtpTransport::OnNetworkRouteChanged(
Zhi Huang942bc2e2017-11-13 13:26:07 -0800220 rtc::Optional<rtc::NetworkRoute> network_route) {
221 SignalNetworkRouteChanged(network_route);
222}
223
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800224void RtpTransport::OnWritableState(
225 rtc::PacketTransportInternal* packet_transport) {
226 RTC_DCHECK(packet_transport == rtp_packet_transport_ ||
227 packet_transport == rtcp_packet_transport_);
Zhi Huang365381f2018-04-13 16:44:34 -0700228 SignalWritableState(IsTransportWritable());
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800229}
230
231void RtpTransport::OnSentPacket(rtc::PacketTransportInternal* packet_transport,
232 const rtc::SentPacket& sent_packet) {
233 RTC_DCHECK(packet_transport == rtp_packet_transport_ ||
234 packet_transport == rtcp_packet_transport_);
235 SignalSentPacket(sent_packet);
236}
237
Zhi Huang365381f2018-04-13 16:44:34 -0700238void RtpTransport::OnRtpPacketReceived(rtc::CopyOnWriteBuffer* packet,
239 const rtc::PacketTime& packet_time) {
240 DemuxPacket(packet, packet_time);
241}
242
243void RtpTransport::OnRtcpPacketReceived(rtc::CopyOnWriteBuffer* packet,
244 const rtc::PacketTime& packet_time) {
245 SignalRtcpPacketReceived(packet, packet_time);
246}
247
248void RtpTransport::OnReadPacket(rtc::PacketTransportInternal* transport,
249 const char* data,
250 size_t len,
251 const rtc::PacketTime& packet_time,
252 int flags) {
253 TRACE_EVENT0("webrtc", "RtpTransport::OnReadPacket");
254
255 // When using RTCP multiplexing we might get RTCP packets on the RTP
256 // transport. We check the RTP payload type to determine if it is RTCP.
257 bool rtcp =
258 transport == rtcp_packet_transport() || cricket::IsRtcpPacket(data, len);
259
260 // Filter out the packet that is neither RTP nor RTCP.
261 if (!rtcp && !cricket::IsRtpPacket(data, len)) {
262 return;
263 }
264
265 rtc::CopyOnWriteBuffer packet(data, len);
266 // Protect ourselves against crazy data.
267 if (!cricket::IsValidRtpRtcpPacketSize(rtcp, packet.size())) {
268 RTC_LOG(LS_ERROR) << "Dropping incoming "
269 << cricket::RtpRtcpStringLiteral(rtcp)
270 << " packet: wrong size=" << packet.size();
271 return;
272 }
273
274 if (rtcp) {
275 OnRtcpPacketReceived(&packet, packet_time);
276 } else {
277 OnRtpPacketReceived(&packet, packet_time);
278 }
279}
280
zstein56162b92017-04-24 16:54:35 -0700281void RtpTransport::SetReadyToSend(bool rtcp, bool ready) {
282 if (rtcp) {
283 rtcp_ready_to_send_ = ready;
284 } else {
285 rtp_ready_to_send_ = ready;
286 }
287
288 MaybeSignalReadyToSend();
289}
290
291void RtpTransport::MaybeSignalReadyToSend() {
292 bool ready_to_send =
293 rtp_ready_to_send_ && (rtcp_ready_to_send_ || rtcp_mux_enabled_);
294 if (ready_to_send != ready_to_send_) {
295 ready_to_send_ = ready_to_send;
296 SignalReadyToSend(ready_to_send);
297 }
298}
299
zsteind48dbda2017-04-04 19:45:57 -0700300} // namespace webrtc