blob: b26783260f0436baa1bf68e2f86221a99ef2c18b [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
zhihuange683c682017-08-31 16:00:07 -070079bool RtpTransport::SendRtpPacket(rtc::CopyOnWriteBuffer* packet,
80 const rtc::PacketOptions& options,
81 int flags) {
82 return SendPacket(false, packet, options, flags);
83}
84
85bool RtpTransport::SendRtcpPacket(rtc::CopyOnWriteBuffer* packet,
86 const rtc::PacketOptions& options,
87 int flags) {
88 return SendPacket(true, packet, options, flags);
89}
90
zstein56162b92017-04-24 16:54:35 -070091bool RtpTransport::SendPacket(bool rtcp,
zstein398c3fd2017-07-19 13:38:02 -070092 rtc::CopyOnWriteBuffer* packet,
zstein56162b92017-04-24 16:54:35 -070093 const rtc::PacketOptions& options,
94 int flags) {
95 rtc::PacketTransportInternal* transport = rtcp && !rtcp_mux_enabled_
96 ? rtcp_packet_transport_
97 : rtp_packet_transport_;
98 int ret = transport->SendPacket(packet->data<char>(), packet->size(), options,
99 flags);
100 if (ret != static_cast<int>(packet->size())) {
101 if (transport->GetError() == ENOTCONN) {
102 LOG(LS_WARNING) << "Got ENOTCONN from transport.";
103 SetReadyToSend(rtcp, false);
104 }
105 return false;
106 }
107 return true;
zsteind48dbda2017-04-04 19:45:57 -0700108}
109
zstein3dcf0e92017-06-01 13:22:42 -0700110bool RtpTransport::HandlesPacket(const uint8_t* data, size_t len) {
111 return bundle_filter_.DemuxPacket(data, len);
112}
113
114bool RtpTransport::HandlesPayloadType(int payload_type) const {
115 return bundle_filter_.FindPayloadType(payload_type);
116}
117
118void RtpTransport::AddHandledPayloadType(int payload_type) {
119 bundle_filter_.AddPayloadType(payload_type);
120}
121
zsteind9ce7642017-04-10 16:17:57 -0700122PacketTransportInterface* RtpTransport::GetRtpPacketTransport() const {
123 return rtp_packet_transport_;
124}
125
126PacketTransportInterface* RtpTransport::GetRtcpPacketTransport() const {
127 return rtcp_packet_transport_;
128}
129
sprangdb2a9fc2017-08-09 06:42:32 -0700130RTCError RtpTransport::SetParameters(const RtpTransportParameters& parameters) {
131 if (parameters_.rtcp.mux && !parameters.rtcp.mux) {
zsteind9ce7642017-04-10 16:17:57 -0700132 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
133 "Disabling RTCP muxing is not allowed.");
134 }
sprangdb2a9fc2017-08-09 06:42:32 -0700135 if (parameters.keepalive != parameters_.keepalive) {
136 // TODO(sprang): Wire up support for keep-alive (only ORTC support for now).
137 LOG_AND_RETURN_ERROR(
138 RTCErrorType::INVALID_MODIFICATION,
139 "RTP keep-alive parameters not supported by this channel.");
zsteind9ce7642017-04-10 16:17:57 -0700140 }
141
sprangdb2a9fc2017-08-09 06:42:32 -0700142 RtpTransportParameters new_parameters = parameters;
143
144 if (new_parameters.rtcp.cname.empty()) {
145 new_parameters.rtcp.cname = parameters_.rtcp.cname;
146 }
147
148 parameters_ = new_parameters;
zsteind9ce7642017-04-10 16:17:57 -0700149 return RTCError::OK();
150}
151
sprangdb2a9fc2017-08-09 06:42:32 -0700152RtpTransportParameters RtpTransport::GetParameters() const {
153 return parameters_;
zsteind9ce7642017-04-10 16:17:57 -0700154}
155
156RtpTransportAdapter* RtpTransport::GetInternal() {
157 return nullptr;
158}
159
zstein56162b92017-04-24 16:54:35 -0700160void RtpTransport::OnReadyToSend(rtc::PacketTransportInternal* transport) {
161 SetReadyToSend(transport == rtcp_packet_transport_, true);
162}
163
164void RtpTransport::SetReadyToSend(bool rtcp, bool ready) {
165 if (rtcp) {
166 rtcp_ready_to_send_ = ready;
167 } else {
168 rtp_ready_to_send_ = ready;
169 }
170
171 MaybeSignalReadyToSend();
172}
173
174void RtpTransport::MaybeSignalReadyToSend() {
175 bool ready_to_send =
176 rtp_ready_to_send_ && (rtcp_ready_to_send_ || rtcp_mux_enabled_);
177 if (ready_to_send != ready_to_send_) {
178 ready_to_send_ = ready_to_send;
179 SignalReadyToSend(ready_to_send);
180 }
181}
182
zstein3dcf0e92017-06-01 13:22:42 -0700183// Check the RTP payload type. If 63 < payload type < 96, it's RTCP.
184// For additional details, see http://tools.ietf.org/html/rfc5761.
185bool IsRtcp(const char* data, int len) {
186 if (len < 2) {
187 return false;
188 }
189 char pt = data[1] & 0x7F;
190 return (63 < pt) && (pt < 96);
191}
192
193void RtpTransport::OnReadPacket(rtc::PacketTransportInternal* transport,
194 const char* data,
195 size_t len,
196 const rtc::PacketTime& packet_time,
197 int flags) {
198 TRACE_EVENT0("webrtc", "RtpTransport::OnReadPacket");
199
200 // When using RTCP multiplexing we might get RTCP packets on the RTP
201 // transport. We check the RTP payload type to determine if it is RTCP.
202 bool rtcp = transport == rtcp_packet_transport() ||
203 IsRtcp(data, static_cast<int>(len));
204 rtc::CopyOnWriteBuffer packet(data, len);
205
206 if (!WantsPacket(rtcp, &packet)) {
207 return;
208 }
209
210 // This mutates |packet| if it is protected.
zstein634977b2017-07-14 12:30:04 -0700211 SignalPacketReceived(rtcp, &packet, packet_time);
zstein3dcf0e92017-06-01 13:22:42 -0700212}
213
214bool RtpTransport::WantsPacket(bool rtcp,
215 const rtc::CopyOnWriteBuffer* packet) {
216 // Protect ourselves against crazy data.
217 if (!packet || !cricket::IsValidRtpRtcpPacketSize(rtcp, packet->size())) {
218 LOG(LS_ERROR) << "Dropping incoming " << cricket::RtpRtcpStringLiteral(rtcp)
219 << " packet: wrong size=" << packet->size();
220 return false;
221 }
222 if (rtcp) {
223 // Permit all (seemingly valid) RTCP packets.
224 return true;
225 }
226 // Check whether we handle this payload.
227 return HandlesPacket(packet->data(), packet->size());
228}
229
zsteind48dbda2017-04-04 19:45:57 -0700230} // namespace webrtc