OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2017 The WebRTC project authors. All Rights Reserved. | 2 * Copyright 2017 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/pc/rtptransport.h" | 11 #include "webrtc/pc/rtptransport.h" |
12 | 12 |
13 #include "webrtc/base/checks.h" | 13 #include "webrtc/base/checks.h" |
14 #include "webrtc/base/copyonwritebuffer.h" | 14 #include "webrtc/base/copyonwritebuffer.h" |
15 #include "webrtc/base/trace_event.h" | |
16 #include "webrtc/media/base/rtputils.h" | |
15 #include "webrtc/p2p/base/packettransportinterface.h" | 17 #include "webrtc/p2p/base/packettransportinterface.h" |
16 | 18 |
17 namespace webrtc { | 19 namespace webrtc { |
18 | 20 |
19 void RtpTransport::SetRtcpMuxEnabled(bool enable) { | 21 void RtpTransport::SetRtcpMuxEnabled(bool enable) { |
20 rtcp_mux_enabled_ = enable; | 22 rtcp_mux_enabled_ = enable; |
21 MaybeSignalReadyToSend(); | 23 MaybeSignalReadyToSend(); |
22 } | 24 } |
23 | 25 |
24 void RtpTransport::SetRtpPacketTransport( | 26 void RtpTransport::SetRtpPacketTransport( |
25 rtc::PacketTransportInternal* new_packet_transport) { | 27 rtc::PacketTransportInternal* new_packet_transport) { |
26 if (new_packet_transport == rtp_packet_transport_) { | 28 if (new_packet_transport == rtp_packet_transport_) { |
27 return; | 29 return; |
28 } | 30 } |
29 if (rtp_packet_transport_) { | 31 if (rtp_packet_transport_) { |
30 rtp_packet_transport_->SignalReadyToSend.disconnect(this); | 32 rtp_packet_transport_->SignalReadyToSend.disconnect(this); |
33 rtp_packet_transport_->SignalReadPacket.disconnect(this); | |
31 } | 34 } |
32 if (new_packet_transport) { | 35 if (new_packet_transport) { |
33 new_packet_transport->SignalReadyToSend.connect( | 36 new_packet_transport->SignalReadyToSend.connect( |
34 this, &RtpTransport::OnReadyToSend); | 37 this, &RtpTransport::OnReadyToSend); |
38 new_packet_transport->SignalReadPacket.connect(this, | |
39 &RtpTransport::OnReadPacket); | |
35 } | 40 } |
36 rtp_packet_transport_ = new_packet_transport; | 41 rtp_packet_transport_ = new_packet_transport; |
37 | 42 |
38 // Assumes the transport is ready to send if it is writable. If we are wrong, | 43 // Assumes the transport is ready to send if it is writable. If we are wrong, |
39 // ready to send will be updated the next time we try to send. | 44 // ready to send will be updated the next time we try to send. |
40 SetReadyToSend(false, | 45 SetReadyToSend(false, |
41 rtp_packet_transport_ && rtp_packet_transport_->writable()); | 46 rtp_packet_transport_ && rtp_packet_transport_->writable()); |
42 } | 47 } |
43 | 48 |
44 void RtpTransport::SetRtcpPacketTransport( | 49 void RtpTransport::SetRtcpPacketTransport( |
45 rtc::PacketTransportInternal* new_packet_transport) { | 50 rtc::PacketTransportInternal* new_packet_transport) { |
46 if (new_packet_transport == rtcp_packet_transport_) { | 51 if (new_packet_transport == rtcp_packet_transport_) { |
47 return; | 52 return; |
48 } | 53 } |
49 if (rtcp_packet_transport_) { | 54 if (rtcp_packet_transport_) { |
50 rtcp_packet_transport_->SignalReadyToSend.disconnect(this); | 55 rtcp_packet_transport_->SignalReadyToSend.disconnect(this); |
56 rtcp_packet_transport_->SignalReadPacket.disconnect(this); | |
51 } | 57 } |
52 if (new_packet_transport) { | 58 if (new_packet_transport) { |
53 new_packet_transport->SignalReadyToSend.connect( | 59 new_packet_transport->SignalReadyToSend.connect( |
54 this, &RtpTransport::OnReadyToSend); | 60 this, &RtpTransport::OnReadyToSend); |
61 new_packet_transport->SignalReadPacket.connect(this, | |
62 &RtpTransport::OnReadPacket); | |
55 } | 63 } |
56 rtcp_packet_transport_ = new_packet_transport; | 64 rtcp_packet_transport_ = new_packet_transport; |
57 | 65 |
58 // Assumes the transport is ready to send if it is writable. If we are wrong, | 66 // Assumes the transport is ready to send if it is writable. If we are wrong, |
59 // ready to send will be updated the next time we try to send. | 67 // ready to send will be updated the next time we try to send. |
60 SetReadyToSend(true, | 68 SetReadyToSend(true, |
61 rtcp_packet_transport_ && rtcp_packet_transport_->writable()); | 69 rtcp_packet_transport_ && rtcp_packet_transport_->writable()); |
62 } | 70 } |
63 | 71 |
64 bool RtpTransport::IsWritable(bool rtcp) const { | 72 bool RtpTransport::IsWritable(bool rtcp) const { |
(...skipping 15 matching lines...) Expand all Loading... | |
80 if (ret != static_cast<int>(packet->size())) { | 88 if (ret != static_cast<int>(packet->size())) { |
81 if (transport->GetError() == ENOTCONN) { | 89 if (transport->GetError() == ENOTCONN) { |
82 LOG(LS_WARNING) << "Got ENOTCONN from transport."; | 90 LOG(LS_WARNING) << "Got ENOTCONN from transport."; |
83 SetReadyToSend(rtcp, false); | 91 SetReadyToSend(rtcp, false); |
84 } | 92 } |
85 return false; | 93 return false; |
86 } | 94 } |
87 return true; | 95 return true; |
88 } | 96 } |
89 | 97 |
98 bool RtpTransport::HandlesPacket(const uint8_t* data, size_t len) { | |
99 return bundle_filter_.DemuxPacket(data, len); | |
100 } | |
101 | |
102 bool RtpTransport::HandlesPayloadType(int payload_type) const { | |
103 return bundle_filter_.FindPayloadType(payload_type); | |
104 } | |
105 | |
106 void RtpTransport::AddHandledPayloadType(int payload_type) { | |
107 bundle_filter_.AddPayloadType(payload_type); | |
108 } | |
109 | |
90 PacketTransportInterface* RtpTransport::GetRtpPacketTransport() const { | 110 PacketTransportInterface* RtpTransport::GetRtpPacketTransport() const { |
91 return rtp_packet_transport_; | 111 return rtp_packet_transport_; |
92 } | 112 } |
93 | 113 |
94 PacketTransportInterface* RtpTransport::GetRtcpPacketTransport() const { | 114 PacketTransportInterface* RtpTransport::GetRtcpPacketTransport() const { |
95 return rtcp_packet_transport_; | 115 return rtcp_packet_transport_; |
96 } | 116 } |
97 | 117 |
98 RTCError RtpTransport::SetRtcpParameters(const RtcpParameters& parameters) { | 118 RTCError RtpTransport::SetRtcpParameters(const RtcpParameters& parameters) { |
99 if (rtcp_parameters_.mux && !parameters.mux) { | 119 if (rtcp_parameters_.mux && !parameters.mux) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
135 | 155 |
136 void RtpTransport::MaybeSignalReadyToSend() { | 156 void RtpTransport::MaybeSignalReadyToSend() { |
137 bool ready_to_send = | 157 bool ready_to_send = |
138 rtp_ready_to_send_ && (rtcp_ready_to_send_ || rtcp_mux_enabled_); | 158 rtp_ready_to_send_ && (rtcp_ready_to_send_ || rtcp_mux_enabled_); |
139 if (ready_to_send != ready_to_send_) { | 159 if (ready_to_send != ready_to_send_) { |
140 ready_to_send_ = ready_to_send; | 160 ready_to_send_ = ready_to_send; |
141 SignalReadyToSend(ready_to_send); | 161 SignalReadyToSend(ready_to_send); |
142 } | 162 } |
143 } | 163 } |
144 | 164 |
165 void RtpTransport::OnReadPacket(rtc::PacketTransportInternal* transport, | |
166 const char* data, | |
167 size_t len, | |
168 const rtc::PacketTime& packet_time, | |
169 int flags) { | |
170 TRACE_EVENT0("webrtc", "RtpTransport::OnReadPacket"); | |
171 | |
172 // When using RTCP multiplexing we might get RTCP packets on the RTP | |
173 // transport. We feed RTP traffic into the demuxer to determine if it is RTCP. | |
174 bool rtcp = PacketIsRtcp(transport, data, len); | |
175 rtc::CopyOnWriteBuffer packet(data, len); | |
176 | |
177 if (!WantsPacket(rtcp, &packet)) { | |
178 return; | |
179 } | |
180 | |
181 if (!has_received_packet_ && !rtcp) { | |
182 has_received_packet_ = true; | |
183 SignalFirstPacketReceived(); | |
Taylor Brandstetter
2017/05/25 16:14:25
nit: Since ultimately "SignalFirstPacketReceived"
Zach Stein
2017/05/30 21:50:55
Done.
| |
184 } | |
185 | |
186 // This mutates packet if it is protected. | |
187 SignalPacketReceived(rtcp, packet, packet_time); | |
188 | |
189 // Supports early media timeout in VoiceChannel. | |
190 // TODO(zstein): See if this can be combined with has_received_packet_. | |
191 if (!received_media_ && !rtcp) { | |
192 received_media_ = true; | |
Taylor Brandstetter
2017/05/25 16:14:25
Same sort of situation here. VoiceChannel already
Zach Stein
2017/05/30 21:50:55
Done.
| |
193 } | |
194 } | |
195 | |
196 // Check the RTP payload type. If 63 < payload type < 96, it's RTCP. | |
197 // For additional details, see http://tools.ietf.org/html/rfc5761. | |
198 bool IsRtcp(const char* data, int len) { | |
Taylor Brandstetter
2017/05/25 16:14:25
If we're moving things to rtputils.h, this would b
Zach Stein
2017/05/30 21:50:55
I was only moving methods that are called from mul
| |
199 if (len < 2) { | |
200 return false; | |
201 } | |
202 char pt = data[1] & 0x7F; | |
203 return (63 < pt) && (pt < 96); | |
204 } | |
205 | |
206 | |
207 bool RtpTransport::PacketIsRtcp(const rtc::PacketTransportInternal* transport, | |
208 const char* data, | |
209 size_t len) { | |
210 // TODO(zstein): Can't check if we offered mux from here and we fail | |
211 // SendEarlyRtcpMuxToRtcpMux if we only check rtcp_mux_enabled. RtcpMuxFilter | |
212 // had: | |
213 | |
214 // If we're muxing RTP/RTCP, we must inspect each packet delivered | |
215 // and determine whether it is RTP or RTCP. We do so by looking at | |
216 // the RTP payload type (see IsRtcp). Note that if we offer RTCP | |
217 // mux, we may receive muxed RTCP before we receive the answer, so | |
218 // we operate in that state too. | |
219 // bool offered_mux = ((state_ == ST_SENTOFFER) && offer_enable_); | |
220 // return (IsActive() || offered_mux) && IsRtcp(data, len); | |
221 | |
222 // TODO(zstein): We could give RtpTransport a reference to the mux filter | |
223 // instead of using rtcp_mux_enabled_ here (and some yet to be implemented | |
224 // logic to know if mux is provisionally enabled). Or can we just always | |
225 // rely on IsRtcp (and not bother checking rtcp_mux_enabled)? | |
Taylor Brandstetter
2017/05/25 16:14:25
Let's just do this. The only way we could *not off
Zach Stein
2017/05/30 21:50:55
Done.
Am I understanding correctly that the exist
Taylor Brandstetter
2017/05/31 08:25:03
Even then, the remote client should only use paylo
Zach Stein
2017/06/01 03:45:58
Acknowledged.
| |
226 | |
227 return transport == rtcp_packet_transport() || | |
228 (/*rtcp_mux_enabled_ &&*/ IsRtcp(data, len)); | |
229 } | |
230 | |
231 bool RtpTransport::WantsPacket(bool rtcp, | |
232 const rtc::CopyOnWriteBuffer* packet) { | |
233 // Protect ourselves against crazy data. | |
234 if (!packet || !cricket::IsValidRtpRtcpPacketSize(rtcp, packet->size())) { | |
235 LOG(LS_ERROR) << "Dropping incoming " | |
236 << cricket::PacketType(rtcp) | |
237 << " packet: wrong size=" << packet->size(); | |
238 return false; | |
239 } | |
240 if (rtcp) { | |
241 // Permit all (seemingly valid) RTCP packets. | |
242 return true; | |
243 } | |
244 // Check whether we handle this payload. | |
245 return HandlesPacket(packet->data(), packet->size()); | |
246 } | |
247 | |
145 } // namespace webrtc | 248 } // namespace webrtc |
OLD | NEW |