blob: ac57eb887bc690c3fadd8bd793c24ba3629245f8 [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
11#include "webrtc/pc/rtptransport.h"
12
zstein3dcf0e92017-06-01 13:22:42 -070013#include "webrtc/media/base/rtputils.h"
zsteind9ce7642017-04-10 16:17:57 -070014#include "webrtc/p2p/base/packettransportinterface.h"
Edward Lemurc20978e2017-07-06 19:44:34 +020015#include "webrtc/rtc_base/checks.h"
16#include "webrtc/rtc_base/copyonwritebuffer.h"
17#include "webrtc/rtc_base/trace_event.h"
zsteind48dbda2017-04-04 19:45:57 -070018
19namespace webrtc {
20
zstein56162b92017-04-24 16:54:35 -070021void RtpTransport::SetRtcpMuxEnabled(bool enable) {
22 rtcp_mux_enabled_ = enable;
23 MaybeSignalReadyToSend();
zsteind9ce7642017-04-10 16:17:57 -070024}
25
zstein56162b92017-04-24 16:54:35 -070026void RtpTransport::SetRtpPacketTransport(
27 rtc::PacketTransportInternal* new_packet_transport) {
28 if (new_packet_transport == rtp_packet_transport_) {
29 return;
30 }
31 if (rtp_packet_transport_) {
32 rtp_packet_transport_->SignalReadyToSend.disconnect(this);
zstein3dcf0e92017-06-01 13:22:42 -070033 rtp_packet_transport_->SignalReadPacket.disconnect(this);
zstein56162b92017-04-24 16:54:35 -070034 }
35 if (new_packet_transport) {
36 new_packet_transport->SignalReadyToSend.connect(
37 this, &RtpTransport::OnReadyToSend);
zstein3dcf0e92017-06-01 13:22:42 -070038 new_packet_transport->SignalReadPacket.connect(this,
39 &RtpTransport::OnReadPacket);
zstein56162b92017-04-24 16:54:35 -070040 }
41 rtp_packet_transport_ = new_packet_transport;
42
43 // Assumes the transport is ready to send if it is writable. If we are wrong,
44 // ready to send will be updated the next time we try to send.
45 SetReadyToSend(false,
46 rtp_packet_transport_ && rtp_packet_transport_->writable());
47}
48
49void RtpTransport::SetRtcpPacketTransport(
50 rtc::PacketTransportInternal* new_packet_transport) {
51 if (new_packet_transport == rtcp_packet_transport_) {
52 return;
53 }
54 if (rtcp_packet_transport_) {
55 rtcp_packet_transport_->SignalReadyToSend.disconnect(this);
zstein3dcf0e92017-06-01 13:22:42 -070056 rtcp_packet_transport_->SignalReadPacket.disconnect(this);
zstein56162b92017-04-24 16:54:35 -070057 }
58 if (new_packet_transport) {
59 new_packet_transport->SignalReadyToSend.connect(
60 this, &RtpTransport::OnReadyToSend);
zstein3dcf0e92017-06-01 13:22:42 -070061 new_packet_transport->SignalReadPacket.connect(this,
62 &RtpTransport::OnReadPacket);
zstein56162b92017-04-24 16:54:35 -070063 }
64 rtcp_packet_transport_ = new_packet_transport;
65
66 // Assumes the transport is ready to send if it is writable. If we are wrong,
67 // ready to send will be updated the next time we try to send.
68 SetReadyToSend(true,
69 rtcp_packet_transport_ && rtcp_packet_transport_->writable());
70}
71
72bool RtpTransport::IsWritable(bool rtcp) const {
73 rtc::PacketTransportInternal* transport = rtcp && !rtcp_mux_enabled_
74 ? rtcp_packet_transport_
75 : rtp_packet_transport_;
76 return transport && transport->writable();
77}
78
79bool RtpTransport::SendPacket(bool rtcp,
zstein398c3fd2017-07-19 13:38:02 -070080 rtc::CopyOnWriteBuffer* packet,
zstein56162b92017-04-24 16:54:35 -070081 const rtc::PacketOptions& options,
82 int flags) {
83 rtc::PacketTransportInternal* transport = rtcp && !rtcp_mux_enabled_
84 ? rtcp_packet_transport_
85 : rtp_packet_transport_;
86 int ret = transport->SendPacket(packet->data<char>(), packet->size(), options,
87 flags);
88 if (ret != static_cast<int>(packet->size())) {
89 if (transport->GetError() == ENOTCONN) {
90 LOG(LS_WARNING) << "Got ENOTCONN from transport.";
91 SetReadyToSend(rtcp, false);
92 }
93 return false;
94 }
95 return true;
zsteind48dbda2017-04-04 19:45:57 -070096}
97
zstein3dcf0e92017-06-01 13:22:42 -070098bool RtpTransport::HandlesPacket(const uint8_t* data, size_t len) {
99 return bundle_filter_.DemuxPacket(data, len);
100}
101
102bool RtpTransport::HandlesPayloadType(int payload_type) const {
103 return bundle_filter_.FindPayloadType(payload_type);
104}
105
106void RtpTransport::AddHandledPayloadType(int payload_type) {
107 bundle_filter_.AddPayloadType(payload_type);
108}
109
zsteind9ce7642017-04-10 16:17:57 -0700110PacketTransportInterface* RtpTransport::GetRtpPacketTransport() const {
111 return rtp_packet_transport_;
112}
113
114PacketTransportInterface* RtpTransport::GetRtcpPacketTransport() const {
115 return rtcp_packet_transport_;
116}
117
sprangdb2a9fc2017-08-09 06:42:32 -0700118RTCError RtpTransport::SetParameters(const RtpTransportParameters& parameters) {
119 if (parameters_.rtcp.mux && !parameters.rtcp.mux) {
zsteind9ce7642017-04-10 16:17:57 -0700120 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
121 "Disabling RTCP muxing is not allowed.");
122 }
sprangdb2a9fc2017-08-09 06:42:32 -0700123 if (parameters.keepalive != parameters_.keepalive) {
124 // TODO(sprang): Wire up support for keep-alive (only ORTC support for now).
125 LOG_AND_RETURN_ERROR(
126 RTCErrorType::INVALID_MODIFICATION,
127 "RTP keep-alive parameters not supported by this channel.");
zsteind9ce7642017-04-10 16:17:57 -0700128 }
129
sprangdb2a9fc2017-08-09 06:42:32 -0700130 RtpTransportParameters new_parameters = parameters;
131
132 if (new_parameters.rtcp.cname.empty()) {
133 new_parameters.rtcp.cname = parameters_.rtcp.cname;
134 }
135
136 parameters_ = new_parameters;
zsteind9ce7642017-04-10 16:17:57 -0700137 return RTCError::OK();
138}
139
sprangdb2a9fc2017-08-09 06:42:32 -0700140RtpTransportParameters RtpTransport::GetParameters() const {
141 return parameters_;
zsteind9ce7642017-04-10 16:17:57 -0700142}
143
144RtpTransportAdapter* RtpTransport::GetInternal() {
145 return nullptr;
146}
147
zstein56162b92017-04-24 16:54:35 -0700148void RtpTransport::OnReadyToSend(rtc::PacketTransportInternal* transport) {
149 SetReadyToSend(transport == rtcp_packet_transport_, true);
150}
151
152void RtpTransport::SetReadyToSend(bool rtcp, bool ready) {
153 if (rtcp) {
154 rtcp_ready_to_send_ = ready;
155 } else {
156 rtp_ready_to_send_ = ready;
157 }
158
159 MaybeSignalReadyToSend();
160}
161
162void RtpTransport::MaybeSignalReadyToSend() {
163 bool ready_to_send =
164 rtp_ready_to_send_ && (rtcp_ready_to_send_ || rtcp_mux_enabled_);
165 if (ready_to_send != ready_to_send_) {
166 ready_to_send_ = ready_to_send;
167 SignalReadyToSend(ready_to_send);
168 }
169}
170
zstein3dcf0e92017-06-01 13:22:42 -0700171// Check the RTP payload type. If 63 < payload type < 96, it's RTCP.
172// For additional details, see http://tools.ietf.org/html/rfc5761.
173bool IsRtcp(const char* data, int len) {
174 if (len < 2) {
175 return false;
176 }
177 char pt = data[1] & 0x7F;
178 return (63 < pt) && (pt < 96);
179}
180
181void RtpTransport::OnReadPacket(rtc::PacketTransportInternal* transport,
182 const char* data,
183 size_t len,
184 const rtc::PacketTime& packet_time,
185 int flags) {
186 TRACE_EVENT0("webrtc", "RtpTransport::OnReadPacket");
187
188 // When using RTCP multiplexing we might get RTCP packets on the RTP
189 // transport. We check the RTP payload type to determine if it is RTCP.
190 bool rtcp = transport == rtcp_packet_transport() ||
191 IsRtcp(data, static_cast<int>(len));
192 rtc::CopyOnWriteBuffer packet(data, len);
193
194 if (!WantsPacket(rtcp, &packet)) {
195 return;
196 }
197
198 // This mutates |packet| if it is protected.
zstein634977b2017-07-14 12:30:04 -0700199 SignalPacketReceived(rtcp, &packet, packet_time);
zstein3dcf0e92017-06-01 13:22:42 -0700200}
201
202bool RtpTransport::WantsPacket(bool rtcp,
203 const rtc::CopyOnWriteBuffer* packet) {
204 // Protect ourselves against crazy data.
205 if (!packet || !cricket::IsValidRtpRtcpPacketSize(rtcp, packet->size())) {
206 LOG(LS_ERROR) << "Dropping incoming " << cricket::RtpRtcpStringLiteral(rtcp)
207 << " packet: wrong size=" << packet->size();
208 return false;
209 }
210 if (rtcp) {
211 // Permit all (seemingly valid) RTCP packets.
212 return true;
213 }
214 // Check whether we handle this payload.
215 return HandlesPacket(packet->data(), packet->size());
216}
217
zsteind48dbda2017-04-04 19:45:57 -0700218} // namespace webrtc