blob: 26f7e3e4c9b60ca1cf56f18147f7cf60b120bd7b [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020013#include "media/base/rtputils.h"
Zhi Huang942bc2e2017-11-13 13:26:07 -080014#include "p2p/base/p2pconstants.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "p2p/base/packettransportinterface.h"
16#include "rtc_base/checks.h"
17#include "rtc_base/copyonwritebuffer.h"
18#include "rtc_base/trace_event.h"
zsteind48dbda2017-04-04 19:45:57 -070019
20namespace webrtc {
21
zstein56162b92017-04-24 16:54:35 -070022void RtpTransport::SetRtcpMuxEnabled(bool enable) {
23 rtcp_mux_enabled_ = enable;
24 MaybeSignalReadyToSend();
zsteind9ce7642017-04-10 16:17:57 -070025}
26
zstein56162b92017-04-24 16:54:35 -070027void RtpTransport::SetRtpPacketTransport(
28 rtc::PacketTransportInternal* new_packet_transport) {
29 if (new_packet_transport == rtp_packet_transport_) {
30 return;
31 }
32 if (rtp_packet_transport_) {
33 rtp_packet_transport_->SignalReadyToSend.disconnect(this);
zstein3dcf0e92017-06-01 13:22:42 -070034 rtp_packet_transport_->SignalReadPacket.disconnect(this);
Zhi Huang942bc2e2017-11-13 13:26:07 -080035 rtp_packet_transport_->SignalNetworkRouteChanged.disconnect(this);
Zhi Huangcd3fc5d2017-11-29 10:41:57 -080036 rtp_packet_transport_->SignalWritableState.disconnect(this);
37 rtp_packet_transport_->SignalSentPacket.disconnect(this);
Zhi Huang942bc2e2017-11-13 13:26:07 -080038 // Reset the network route of the old transport.
39 SignalNetworkRouteChanged(rtc::Optional<rtc::NetworkRoute>());
zstein56162b92017-04-24 16:54:35 -070040 }
41 if (new_packet_transport) {
42 new_packet_transport->SignalReadyToSend.connect(
43 this, &RtpTransport::OnReadyToSend);
zstein3dcf0e92017-06-01 13:22:42 -070044 new_packet_transport->SignalReadPacket.connect(this,
45 &RtpTransport::OnReadPacket);
Zhi Huang942bc2e2017-11-13 13:26:07 -080046 new_packet_transport->SignalNetworkRouteChanged.connect(
47 this, &RtpTransport::OnNetworkRouteChange);
Zhi Huangcd3fc5d2017-11-29 10:41:57 -080048 new_packet_transport->SignalWritableState.connect(
49 this, &RtpTransport::OnWritableState);
50 new_packet_transport->SignalSentPacket.connect(this,
51 &RtpTransport::OnSentPacket);
Zhi Huang942bc2e2017-11-13 13:26:07 -080052 // Set the network route for the new transport.
53 SignalNetworkRouteChanged(new_packet_transport->network_route());
zstein56162b92017-04-24 16:54:35 -070054 }
Zhi Huang8c316c12017-11-13 21:13:45 +000055
Zhi Huang942bc2e2017-11-13 13:26:07 -080056 rtp_packet_transport_ = new_packet_transport;
zstein56162b92017-04-24 16:54:35 -070057 // Assumes the transport is ready to send if it is writable. If we are wrong,
58 // ready to send will be updated the next time we try to send.
59 SetReadyToSend(false,
60 rtp_packet_transport_ && rtp_packet_transport_->writable());
61}
62
63void RtpTransport::SetRtcpPacketTransport(
64 rtc::PacketTransportInternal* new_packet_transport) {
65 if (new_packet_transport == rtcp_packet_transport_) {
66 return;
67 }
68 if (rtcp_packet_transport_) {
69 rtcp_packet_transport_->SignalReadyToSend.disconnect(this);
zstein3dcf0e92017-06-01 13:22:42 -070070 rtcp_packet_transport_->SignalReadPacket.disconnect(this);
Zhi Huang942bc2e2017-11-13 13:26:07 -080071 rtcp_packet_transport_->SignalNetworkRouteChanged.disconnect(this);
Zhi Huangcd3fc5d2017-11-29 10:41:57 -080072 rtcp_packet_transport_->SignalWritableState.disconnect(this);
73 rtcp_packet_transport_->SignalSentPacket.disconnect(this);
Zhi Huang942bc2e2017-11-13 13:26:07 -080074 // Reset the network route of the old transport.
75 SignalNetworkRouteChanged(rtc::Optional<rtc::NetworkRoute>());
zstein56162b92017-04-24 16:54:35 -070076 }
77 if (new_packet_transport) {
78 new_packet_transport->SignalReadyToSend.connect(
79 this, &RtpTransport::OnReadyToSend);
zstein3dcf0e92017-06-01 13:22:42 -070080 new_packet_transport->SignalReadPacket.connect(this,
81 &RtpTransport::OnReadPacket);
Zhi Huang942bc2e2017-11-13 13:26:07 -080082 new_packet_transport->SignalNetworkRouteChanged.connect(
83 this, &RtpTransport::OnNetworkRouteChange);
Zhi Huangcd3fc5d2017-11-29 10:41:57 -080084 new_packet_transport->SignalWritableState.connect(
85 this, &RtpTransport::OnWritableState);
86 new_packet_transport->SignalSentPacket.connect(this,
87 &RtpTransport::OnSentPacket);
Zhi Huang942bc2e2017-11-13 13:26:07 -080088 // Set the network route for the new transport.
89 SignalNetworkRouteChanged(new_packet_transport->network_route());
zstein56162b92017-04-24 16:54:35 -070090 }
91 rtcp_packet_transport_ = new_packet_transport;
92
93 // Assumes the transport is ready to send if it is writable. If we are wrong,
94 // ready to send will be updated the next time we try to send.
95 SetReadyToSend(true,
96 rtcp_packet_transport_ && rtcp_packet_transport_->writable());
97}
98
99bool RtpTransport::IsWritable(bool rtcp) const {
100 rtc::PacketTransportInternal* transport = rtcp && !rtcp_mux_enabled_
101 ? rtcp_packet_transport_
102 : rtp_packet_transport_;
103 return transport && transport->writable();
104}
105
Zhi Huangcf990f52017-09-22 12:12:30 -0700106bool RtpTransport::SendRtpPacket(rtc::CopyOnWriteBuffer* packet,
107 const rtc::PacketOptions& options,
108 int flags) {
109 return SendPacket(false, packet, options, flags);
110}
111
112bool RtpTransport::SendRtcpPacket(rtc::CopyOnWriteBuffer* packet,
113 const rtc::PacketOptions& options,
114 int flags) {
115 return SendPacket(true, packet, options, flags);
116}
117
zstein56162b92017-04-24 16:54:35 -0700118bool RtpTransport::SendPacket(bool rtcp,
zstein398c3fd2017-07-19 13:38:02 -0700119 rtc::CopyOnWriteBuffer* packet,
zstein56162b92017-04-24 16:54:35 -0700120 const rtc::PacketOptions& options,
121 int flags) {
122 rtc::PacketTransportInternal* transport = rtcp && !rtcp_mux_enabled_
123 ? rtcp_packet_transport_
124 : rtp_packet_transport_;
125 int ret = transport->SendPacket(packet->data<char>(), packet->size(), options,
126 flags);
127 if (ret != static_cast<int>(packet->size())) {
128 if (transport->GetError() == ENOTCONN) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100129 RTC_LOG(LS_WARNING) << "Got ENOTCONN from transport.";
zstein56162b92017-04-24 16:54:35 -0700130 SetReadyToSend(rtcp, false);
131 }
132 return false;
133 }
134 return true;
zsteind48dbda2017-04-04 19:45:57 -0700135}
136
zstein3dcf0e92017-06-01 13:22:42 -0700137bool RtpTransport::HandlesPacket(const uint8_t* data, size_t len) {
138 return bundle_filter_.DemuxPacket(data, len);
139}
140
141bool RtpTransport::HandlesPayloadType(int payload_type) const {
142 return bundle_filter_.FindPayloadType(payload_type);
143}
144
145void RtpTransport::AddHandledPayloadType(int payload_type) {
146 bundle_filter_.AddPayloadType(payload_type);
147}
148
zsteind9ce7642017-04-10 16:17:57 -0700149PacketTransportInterface* RtpTransport::GetRtpPacketTransport() const {
150 return rtp_packet_transport_;
151}
152
153PacketTransportInterface* RtpTransport::GetRtcpPacketTransport() const {
154 return rtcp_packet_transport_;
155}
156
sprangdb2a9fc2017-08-09 06:42:32 -0700157RTCError RtpTransport::SetParameters(const RtpTransportParameters& parameters) {
158 if (parameters_.rtcp.mux && !parameters.rtcp.mux) {
zsteind9ce7642017-04-10 16:17:57 -0700159 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
160 "Disabling RTCP muxing is not allowed.");
161 }
sprangdb2a9fc2017-08-09 06:42:32 -0700162 if (parameters.keepalive != parameters_.keepalive) {
163 // TODO(sprang): Wire up support for keep-alive (only ORTC support for now).
164 LOG_AND_RETURN_ERROR(
165 RTCErrorType::INVALID_MODIFICATION,
166 "RTP keep-alive parameters not supported by this channel.");
zsteind9ce7642017-04-10 16:17:57 -0700167 }
168
sprangdb2a9fc2017-08-09 06:42:32 -0700169 RtpTransportParameters new_parameters = parameters;
170
171 if (new_parameters.rtcp.cname.empty()) {
172 new_parameters.rtcp.cname = parameters_.rtcp.cname;
173 }
174
175 parameters_ = new_parameters;
zsteind9ce7642017-04-10 16:17:57 -0700176 return RTCError::OK();
177}
178
sprangdb2a9fc2017-08-09 06:42:32 -0700179RtpTransportParameters RtpTransport::GetParameters() const {
180 return parameters_;
zsteind9ce7642017-04-10 16:17:57 -0700181}
182
183RtpTransportAdapter* RtpTransport::GetInternal() {
184 return nullptr;
185}
186
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800187bool RtpTransport::IsRtpTransportWritable() {
188 auto rtcp_packet_transport =
189 rtcp_mux_enabled_ ? nullptr : rtcp_packet_transport_;
190 return rtp_packet_transport_ && rtp_packet_transport_->writable() &&
191 (!rtcp_packet_transport || rtcp_packet_transport->writable());
192}
193
zstein56162b92017-04-24 16:54:35 -0700194void RtpTransport::OnReadyToSend(rtc::PacketTransportInternal* transport) {
195 SetReadyToSend(transport == rtcp_packet_transport_, true);
196}
197
Zhi Huang942bc2e2017-11-13 13:26:07 -0800198void RtpTransport::OnNetworkRouteChange(
199 rtc::Optional<rtc::NetworkRoute> network_route) {
200 SignalNetworkRouteChanged(network_route);
201}
202
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800203void RtpTransport::OnWritableState(
204 rtc::PacketTransportInternal* packet_transport) {
205 RTC_DCHECK(packet_transport == rtp_packet_transport_ ||
206 packet_transport == rtcp_packet_transport_);
207 SignalWritableState(IsRtpTransportWritable());
208}
209
210void RtpTransport::OnSentPacket(rtc::PacketTransportInternal* packet_transport,
211 const rtc::SentPacket& sent_packet) {
212 RTC_DCHECK(packet_transport == rtp_packet_transport_ ||
213 packet_transport == rtcp_packet_transport_);
214 SignalSentPacket(sent_packet);
215}
216
zstein56162b92017-04-24 16:54:35 -0700217void RtpTransport::SetReadyToSend(bool rtcp, bool ready) {
218 if (rtcp) {
219 rtcp_ready_to_send_ = ready;
220 } else {
221 rtp_ready_to_send_ = ready;
222 }
223
224 MaybeSignalReadyToSend();
225}
226
227void RtpTransport::MaybeSignalReadyToSend() {
228 bool ready_to_send =
229 rtp_ready_to_send_ && (rtcp_ready_to_send_ || rtcp_mux_enabled_);
230 if (ready_to_send != ready_to_send_) {
231 ready_to_send_ = ready_to_send;
232 SignalReadyToSend(ready_to_send);
233 }
234}
235
zstein3dcf0e92017-06-01 13:22:42 -0700236// Check the RTP payload type. If 63 < payload type < 96, it's RTCP.
237// For additional details, see http://tools.ietf.org/html/rfc5761.
238bool IsRtcp(const char* data, int len) {
239 if (len < 2) {
240 return false;
241 }
242 char pt = data[1] & 0x7F;
243 return (63 < pt) && (pt < 96);
244}
245
246void RtpTransport::OnReadPacket(rtc::PacketTransportInternal* transport,
247 const char* data,
248 size_t len,
249 const rtc::PacketTime& packet_time,
250 int flags) {
251 TRACE_EVENT0("webrtc", "RtpTransport::OnReadPacket");
252
253 // When using RTCP multiplexing we might get RTCP packets on the RTP
254 // transport. We check the RTP payload type to determine if it is RTCP.
255 bool rtcp = transport == rtcp_packet_transport() ||
256 IsRtcp(data, static_cast<int>(len));
257 rtc::CopyOnWriteBuffer packet(data, len);
258
259 if (!WantsPacket(rtcp, &packet)) {
260 return;
261 }
zstein3dcf0e92017-06-01 13:22:42 -0700262 // This mutates |packet| if it is protected.
zstein634977b2017-07-14 12:30:04 -0700263 SignalPacketReceived(rtcp, &packet, packet_time);
zstein3dcf0e92017-06-01 13:22:42 -0700264}
265
266bool RtpTransport::WantsPacket(bool rtcp,
267 const rtc::CopyOnWriteBuffer* packet) {
268 // Protect ourselves against crazy data.
269 if (!packet || !cricket::IsValidRtpRtcpPacketSize(rtcp, packet->size())) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100270 RTC_LOG(LS_ERROR) << "Dropping incoming "
271 << cricket::RtpRtcpStringLiteral(rtcp)
272 << " packet: wrong size=" << packet->size();
zstein3dcf0e92017-06-01 13:22:42 -0700273 return false;
274 }
275 if (rtcp) {
276 // Permit all (seemingly valid) RTCP packets.
277 return true;
278 }
279 // Check whether we handle this payload.
280 return HandlesPacket(packet->data(), packet->size());
281}
282
zsteind48dbda2017-04-04 19:45:57 -0700283} // namespace webrtc