blob: d2604f9eae800d17abfcc7e1ba60107c71018932 [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);
36 // Reset the network route of the old transport.
37 SignalNetworkRouteChanged(rtc::Optional<rtc::NetworkRoute>());
zstein56162b92017-04-24 16:54:35 -070038 }
39 if (new_packet_transport) {
40 new_packet_transport->SignalReadyToSend.connect(
41 this, &RtpTransport::OnReadyToSend);
zstein3dcf0e92017-06-01 13:22:42 -070042 new_packet_transport->SignalReadPacket.connect(this,
43 &RtpTransport::OnReadPacket);
Zhi Huang942bc2e2017-11-13 13:26:07 -080044 new_packet_transport->SignalNetworkRouteChanged.connect(
45 this, &RtpTransport::OnNetworkRouteChange);
46 // Set the network route for the new transport.
47 SignalNetworkRouteChanged(new_packet_transport->network_route());
zstein56162b92017-04-24 16:54:35 -070048 }
Zhi Huang8c316c12017-11-13 21:13:45 +000049
Zhi Huang942bc2e2017-11-13 13:26:07 -080050 rtp_packet_transport_ = new_packet_transport;
zstein56162b92017-04-24 16:54:35 -070051 // Assumes the transport is ready to send if it is writable. If we are wrong,
52 // ready to send will be updated the next time we try to send.
53 SetReadyToSend(false,
54 rtp_packet_transport_ && rtp_packet_transport_->writable());
55}
56
57void RtpTransport::SetRtcpPacketTransport(
58 rtc::PacketTransportInternal* new_packet_transport) {
59 if (new_packet_transport == rtcp_packet_transport_) {
60 return;
61 }
62 if (rtcp_packet_transport_) {
63 rtcp_packet_transport_->SignalReadyToSend.disconnect(this);
zstein3dcf0e92017-06-01 13:22:42 -070064 rtcp_packet_transport_->SignalReadPacket.disconnect(this);
Zhi Huang942bc2e2017-11-13 13:26:07 -080065 rtcp_packet_transport_->SignalNetworkRouteChanged.disconnect(this);
66 // Reset the network route of the old transport.
67 SignalNetworkRouteChanged(rtc::Optional<rtc::NetworkRoute>());
zstein56162b92017-04-24 16:54:35 -070068 }
69 if (new_packet_transport) {
70 new_packet_transport->SignalReadyToSend.connect(
71 this, &RtpTransport::OnReadyToSend);
zstein3dcf0e92017-06-01 13:22:42 -070072 new_packet_transport->SignalReadPacket.connect(this,
73 &RtpTransport::OnReadPacket);
Zhi Huang942bc2e2017-11-13 13:26:07 -080074 new_packet_transport->SignalNetworkRouteChanged.connect(
75 this, &RtpTransport::OnNetworkRouteChange);
76 // Set the network route for the new transport.
77 SignalNetworkRouteChanged(new_packet_transport->network_route());
zstein56162b92017-04-24 16:54:35 -070078 }
79 rtcp_packet_transport_ = new_packet_transport;
80
81 // Assumes the transport is ready to send if it is writable. If we are wrong,
82 // ready to send will be updated the next time we try to send.
83 SetReadyToSend(true,
84 rtcp_packet_transport_ && rtcp_packet_transport_->writable());
85}
86
87bool RtpTransport::IsWritable(bool rtcp) const {
88 rtc::PacketTransportInternal* transport = rtcp && !rtcp_mux_enabled_
89 ? rtcp_packet_transport_
90 : rtp_packet_transport_;
91 return transport && transport->writable();
92}
93
Zhi Huangcf990f52017-09-22 12:12:30 -070094bool RtpTransport::SendRtpPacket(rtc::CopyOnWriteBuffer* packet,
95 const rtc::PacketOptions& options,
96 int flags) {
97 return SendPacket(false, packet, options, flags);
98}
99
100bool RtpTransport::SendRtcpPacket(rtc::CopyOnWriteBuffer* packet,
101 const rtc::PacketOptions& options,
102 int flags) {
103 return SendPacket(true, packet, options, flags);
104}
105
zstein56162b92017-04-24 16:54:35 -0700106bool RtpTransport::SendPacket(bool rtcp,
zstein398c3fd2017-07-19 13:38:02 -0700107 rtc::CopyOnWriteBuffer* packet,
zstein56162b92017-04-24 16:54:35 -0700108 const rtc::PacketOptions& options,
109 int flags) {
110 rtc::PacketTransportInternal* transport = rtcp && !rtcp_mux_enabled_
111 ? rtcp_packet_transport_
112 : rtp_packet_transport_;
113 int ret = transport->SendPacket(packet->data<char>(), packet->size(), options,
114 flags);
115 if (ret != static_cast<int>(packet->size())) {
116 if (transport->GetError() == ENOTCONN) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100117 RTC_LOG(LS_WARNING) << "Got ENOTCONN from transport.";
zstein56162b92017-04-24 16:54:35 -0700118 SetReadyToSend(rtcp, false);
119 }
120 return false;
121 }
122 return true;
zsteind48dbda2017-04-04 19:45:57 -0700123}
124
zstein3dcf0e92017-06-01 13:22:42 -0700125bool RtpTransport::HandlesPacket(const uint8_t* data, size_t len) {
126 return bundle_filter_.DemuxPacket(data, len);
127}
128
129bool RtpTransport::HandlesPayloadType(int payload_type) const {
130 return bundle_filter_.FindPayloadType(payload_type);
131}
132
133void RtpTransport::AddHandledPayloadType(int payload_type) {
134 bundle_filter_.AddPayloadType(payload_type);
135}
136
zsteind9ce7642017-04-10 16:17:57 -0700137PacketTransportInterface* RtpTransport::GetRtpPacketTransport() const {
138 return rtp_packet_transport_;
139}
140
141PacketTransportInterface* RtpTransport::GetRtcpPacketTransport() const {
142 return rtcp_packet_transport_;
143}
144
sprangdb2a9fc2017-08-09 06:42:32 -0700145RTCError RtpTransport::SetParameters(const RtpTransportParameters& parameters) {
146 if (parameters_.rtcp.mux && !parameters.rtcp.mux) {
zsteind9ce7642017-04-10 16:17:57 -0700147 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
148 "Disabling RTCP muxing is not allowed.");
149 }
sprangdb2a9fc2017-08-09 06:42:32 -0700150 if (parameters.keepalive != parameters_.keepalive) {
151 // TODO(sprang): Wire up support for keep-alive (only ORTC support for now).
152 LOG_AND_RETURN_ERROR(
153 RTCErrorType::INVALID_MODIFICATION,
154 "RTP keep-alive parameters not supported by this channel.");
zsteind9ce7642017-04-10 16:17:57 -0700155 }
156
sprangdb2a9fc2017-08-09 06:42:32 -0700157 RtpTransportParameters new_parameters = parameters;
158
159 if (new_parameters.rtcp.cname.empty()) {
160 new_parameters.rtcp.cname = parameters_.rtcp.cname;
161 }
162
163 parameters_ = new_parameters;
zsteind9ce7642017-04-10 16:17:57 -0700164 return RTCError::OK();
165}
166
sprangdb2a9fc2017-08-09 06:42:32 -0700167RtpTransportParameters RtpTransport::GetParameters() const {
168 return parameters_;
zsteind9ce7642017-04-10 16:17:57 -0700169}
170
171RtpTransportAdapter* RtpTransport::GetInternal() {
172 return nullptr;
173}
174
zstein56162b92017-04-24 16:54:35 -0700175void RtpTransport::OnReadyToSend(rtc::PacketTransportInternal* transport) {
176 SetReadyToSend(transport == rtcp_packet_transport_, true);
177}
178
Zhi Huang942bc2e2017-11-13 13:26:07 -0800179void RtpTransport::OnNetworkRouteChange(
180 rtc::Optional<rtc::NetworkRoute> network_route) {
181 SignalNetworkRouteChanged(network_route);
182}
183
zstein56162b92017-04-24 16:54:35 -0700184void RtpTransport::SetReadyToSend(bool rtcp, bool ready) {
185 if (rtcp) {
186 rtcp_ready_to_send_ = ready;
187 } else {
188 rtp_ready_to_send_ = ready;
189 }
190
191 MaybeSignalReadyToSend();
192}
193
194void RtpTransport::MaybeSignalReadyToSend() {
195 bool ready_to_send =
196 rtp_ready_to_send_ && (rtcp_ready_to_send_ || rtcp_mux_enabled_);
197 if (ready_to_send != ready_to_send_) {
198 ready_to_send_ = ready_to_send;
199 SignalReadyToSend(ready_to_send);
200 }
201}
202
zstein3dcf0e92017-06-01 13:22:42 -0700203// Check the RTP payload type. If 63 < payload type < 96, it's RTCP.
204// For additional details, see http://tools.ietf.org/html/rfc5761.
205bool IsRtcp(const char* data, int len) {
206 if (len < 2) {
207 return false;
208 }
209 char pt = data[1] & 0x7F;
210 return (63 < pt) && (pt < 96);
211}
212
213void RtpTransport::OnReadPacket(rtc::PacketTransportInternal* transport,
214 const char* data,
215 size_t len,
216 const rtc::PacketTime& packet_time,
217 int flags) {
218 TRACE_EVENT0("webrtc", "RtpTransport::OnReadPacket");
219
220 // When using RTCP multiplexing we might get RTCP packets on the RTP
221 // transport. We check the RTP payload type to determine if it is RTCP.
222 bool rtcp = transport == rtcp_packet_transport() ||
223 IsRtcp(data, static_cast<int>(len));
224 rtc::CopyOnWriteBuffer packet(data, len);
225
226 if (!WantsPacket(rtcp, &packet)) {
227 return;
228 }
229
230 // This mutates |packet| if it is protected.
zstein634977b2017-07-14 12:30:04 -0700231 SignalPacketReceived(rtcp, &packet, packet_time);
zstein3dcf0e92017-06-01 13:22:42 -0700232}
233
234bool RtpTransport::WantsPacket(bool rtcp,
235 const rtc::CopyOnWriteBuffer* packet) {
236 // Protect ourselves against crazy data.
237 if (!packet || !cricket::IsValidRtpRtcpPacketSize(rtcp, packet->size())) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100238 RTC_LOG(LS_ERROR) << "Dropping incoming "
239 << cricket::RtpRtcpStringLiteral(rtcp)
240 << " packet: wrong size=" << packet->size();
zstein3dcf0e92017-06-01 13:22:42 -0700241 return false;
242 }
243 if (rtcp) {
244 // Permit all (seemingly valid) RTCP packets.
245 return true;
246 }
247 // Check whether we handle this payload.
248 return HandlesPacket(packet->data(), packet->size());
249}
250
zsteind48dbda2017-04-04 19:45:57 -0700251} // namespace webrtc