blob: 3ed7f5f433b7a6250b345ed96086fe2f383d30c2 [file] [log] [blame]
Zhi Huange818b6e2018-02-22 15:26:27 -08001/*
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#ifndef PC_JSEPTRANSPORTCONTROLLER_H_
12#define PC_JSEPTRANSPORTCONTROLLER_H_
13
14#include <map>
15#include <memory>
16#include <string>
17#include <utility>
18#include <vector>
19
20#include "api/candidate.h"
Benjamin Wrighta54daf12018-10-11 15:33:17 -070021#include "api/crypto/cryptooptions.h"
Anton Sukhanov7940da02018-10-10 10:34:49 -070022#include "api/media_transport_interface.h"
Zhi Huange818b6e2018-02-22 15:26:27 -080023#include "api/peerconnectioninterface.h"
Qingsi Wang7685e862018-06-11 20:15:46 -070024#include "logging/rtc_event_log/rtc_event_log.h"
Zhi Huange818b6e2018-02-22 15:26:27 -080025#include "media/sctp/sctptransportinternal.h"
26#include "p2p/base/dtlstransport.h"
27#include "p2p/base/p2ptransportchannel.h"
28#include "p2p/base/transportfactoryinterface.h"
29#include "pc/channel.h"
30#include "pc/dtlssrtptransport.h"
Zhi Huang365381f2018-04-13 16:44:34 -070031#include "pc/jseptransport.h"
Zhi Huange818b6e2018-02-22 15:26:27 -080032#include "pc/rtptransport.h"
33#include "pc/srtptransport.h"
34#include "rtc_base/asyncinvoker.h"
35#include "rtc_base/constructormagic.h"
36#include "rtc_base/refcountedobject.h"
Artem Titove41c4332018-07-25 15:04:28 +020037#include "rtc_base/third_party/sigslot/sigslot.h"
Zhi Huange818b6e2018-02-22 15:26:27 -080038
39namespace rtc {
40class Thread;
41class PacketTransportInternal;
42} // namespace rtc
43
44namespace webrtc {
45
Steve Antond25828a2018-08-31 13:06:05 -070046class JsepTransportController : public sigslot::has_slots<> {
Zhi Huange818b6e2018-02-22 15:26:27 -080047 public:
Zhi Huang365381f2018-04-13 16:44:34 -070048 // Used when the RtpTransport/DtlsTransport of the m= section is changed
49 // because the section is rejected or BUNDLE is enabled.
50 class Observer {
51 public:
52 virtual ~Observer() {}
53
54 // Returns true if media associated with |mid| was successfully set up to be
55 // demultiplexed on |rtp_transport|. Could return false if two bundled m=
56 // sections use the same SSRC, for example.
Taylor Brandstettercbaa2542018-04-16 16:42:14 -070057 virtual bool OnTransportChanged(
Zhi Huang365381f2018-04-13 16:44:34 -070058 const std::string& mid,
Taylor Brandstettercbaa2542018-04-16 16:42:14 -070059 RtpTransportInternal* rtp_transport,
Piotr (Peter) Slatalacc8e8bb2018-11-15 08:26:19 -080060 cricket::DtlsTransportInternal* dtls_transport,
61 MediaTransportInterface* media_transport) = 0;
Zhi Huang365381f2018-04-13 16:44:34 -070062 };
63
Zhi Huange818b6e2018-02-22 15:26:27 -080064 struct Config {
65 // If |redetermine_role_on_ice_restart| is true, ICE role is redetermined
66 // upon setting a local transport description that indicates an ICE
67 // restart.
68 bool redetermine_role_on_ice_restart = true;
69 rtc::SSLProtocolVersion ssl_max_version = rtc::SSL_PROTOCOL_DTLS_12;
70 // |crypto_options| is used to determine if created DTLS transports
71 // negotiate GCM crypto suites or not.
Benjamin Wrighta54daf12018-10-11 15:33:17 -070072 webrtc::CryptoOptions crypto_options;
Zhi Huange818b6e2018-02-22 15:26:27 -080073 PeerConnectionInterface::BundlePolicy bundle_policy =
74 PeerConnectionInterface::kBundlePolicyBalanced;
75 PeerConnectionInterface::RtcpMuxPolicy rtcp_mux_policy =
76 PeerConnectionInterface::kRtcpMuxPolicyRequire;
77 bool disable_encryption = false;
78 bool enable_external_auth = false;
79 // Used to inject the ICE/DTLS transports created externally.
80 cricket::TransportFactoryInterface* external_transport_factory = nullptr;
Zhi Huang365381f2018-04-13 16:44:34 -070081 Observer* transport_observer = nullptr;
Zhi Huangb57e1692018-06-12 11:41:11 -070082 bool active_reset_srtp_params = false;
Qingsi Wang7685e862018-06-11 20:15:46 -070083 RtcEventLog* event_log = nullptr;
Anton Sukhanov7940da02018-10-10 10:34:49 -070084
85 // Optional media transport factory (experimental). If provided it will be
86 // used to create media_transport and will be used to send / receive
87 // audio and video frames instead of RTP. Note that currently
88 // media_transport co-exists with RTP / RTCP transports and uses the same
89 // underlying ICE transport.
90 MediaTransportFactory* media_transport_factory = nullptr;
Zhi Huange818b6e2018-02-22 15:26:27 -080091 };
92
93 // The ICE related events are signaled on the |signaling_thread|.
94 // All the transport related methods are called on the |network_thread|.
95 JsepTransportController(rtc::Thread* signaling_thread,
96 rtc::Thread* network_thread,
97 cricket::PortAllocator* port_allocator,
Zach Steine20867f2018-08-02 13:20:15 -070098 AsyncResolverFactory* async_resolver_factory,
Zhi Huange818b6e2018-02-22 15:26:27 -080099 Config config);
100 virtual ~JsepTransportController();
101
102 // The main method to be called; applies a description at the transport
103 // level, creating/destroying transport objects as needed and updating their
104 // properties. This includes RTP, DTLS, and ICE (but not SCTP). At least not
105 // yet? May make sense to in the future.
106 RTCError SetLocalDescription(SdpType type,
107 const cricket::SessionDescription* description);
108
109 RTCError SetRemoteDescription(SdpType type,
110 const cricket::SessionDescription* description);
111
112 // Get transports to be used for the provided |mid|. If bundling is enabled,
113 // calling GetRtpTransport for multiple MIDs may yield the same object.
114 RtpTransportInternal* GetRtpTransport(const std::string& mid) const;
115 cricket::DtlsTransportInternal* GetDtlsTransport(
116 const std::string& mid) const;
117 cricket::DtlsTransportInternal* GetRtcpDtlsTransport(
118 const std::string& mid) const;
119
Anton Sukhanov7940da02018-10-10 10:34:49 -0700120 MediaTransportInterface* GetMediaTransport(const std::string& mid) const;
Bjorn Mellem175aa2e2018-11-08 11:23:22 -0800121 MediaTransportState GetMediaTransportState(const std::string& mid) const;
Anton Sukhanov7940da02018-10-10 10:34:49 -0700122
Zhi Huange818b6e2018-02-22 15:26:27 -0800123 /*********************
124 * ICE-related methods
125 ********************/
126 // This method is public to allow PeerConnection to update it from
127 // SetConfiguration.
128 void SetIceConfig(const cricket::IceConfig& config);
129 // Set the "needs-ice-restart" flag as described in JSEP. After the flag is
130 // set, offers should generate new ufrags/passwords until an ICE restart
131 // occurs.
132 void SetNeedsIceRestartFlag();
133 // Returns true if the ICE restart flag above was set, and no ICE restart has
134 // occurred yet for this transport (by applying a local description with
135 // changed ufrag/password). If the transport has been deleted as a result of
136 // bundling, returns false.
137 bool NeedsIceRestart(const std::string& mid) const;
138 // Start gathering candidates for any new transports, or transports doing an
139 // ICE restart.
140 void MaybeStartGathering();
141 RTCError AddRemoteCandidates(
142 const std::string& mid,
143 const std::vector<cricket::Candidate>& candidates);
144 RTCError RemoveRemoteCandidates(
145 const std::vector<cricket::Candidate>& candidates);
146
147 /**********************
148 * DTLS-related methods
149 *********************/
150 // Specifies the identity to use in this session.
151 // Can only be called once.
152 bool SetLocalCertificate(
153 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate);
154 rtc::scoped_refptr<rtc::RTCCertificate> GetLocalCertificate(
155 const std::string& mid) const;
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800156 // Caller owns returned certificate chain. This method mainly exists for
157 // stats reporting.
158 std::unique_ptr<rtc::SSLCertChain> GetRemoteSSLCertChain(
Zhi Huange818b6e2018-02-22 15:26:27 -0800159 const std::string& mid) const;
160 // Get negotiated role, if one has been negotiated.
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200161 absl::optional<rtc::SSLRole> GetDtlsRole(const std::string& mid) const;
Zhi Huange818b6e2018-02-22 15:26:27 -0800162
163 // TODO(deadbeef): GetStats isn't const because all the way down to
164 // OpenSSLStreamAdapter, GetSslCipherSuite and GetDtlsSrtpCryptoSuite are not
165 // const. Fix this.
166 bool GetStats(const std::string& mid, cricket::TransportStats* stats);
Zhi Huange818b6e2018-02-22 15:26:27 -0800167
Zhi Huange830e682018-03-30 10:48:35 -0700168 bool initial_offerer() const { return initial_offerer_ && *initial_offerer_; }
Zhi Huang365381f2018-04-13 16:44:34 -0700169
Zhi Huangb57e1692018-06-12 11:41:11 -0700170 void SetActiveResetSrtpParams(bool active_reset_srtp_params);
171
Piotr (Peter) Slatala97fc11f2018-10-18 12:57:59 -0700172 // Allows to overwrite the settings from config. You may set or reset the
173 // media transport factory on the jsep transport controller, as long as you
174 // did not call 'GetMediaTransport' or 'MaybeCreateJsepTransport'. Once Jsep
175 // transport is created, you can't change this setting.
176 void SetMediaTransportFactory(MediaTransportFactory* media_transport_factory);
177
Zhi Huange818b6e2018-02-22 15:26:27 -0800178 // All of these signals are fired on the signaling thread.
179
180 // If any transport failed => failed,
181 // Else if all completed => completed,
182 // Else if all connected => connected,
183 // Else => connecting
184 sigslot::signal1<cricket::IceConnectionState> SignalIceConnectionState;
185
Jonas Olsson635474e2018-10-18 15:58:17 +0200186 sigslot::signal1<PeerConnectionInterface::PeerConnectionState>
187 SignalConnectionState;
188 sigslot::signal1<PeerConnectionInterface::IceConnectionState>
189 SignalStandardizedIceConnectionState;
190
Zhi Huange818b6e2018-02-22 15:26:27 -0800191 // If all transports done gathering => complete,
192 // Else if any are gathering => gathering,
193 // Else => new
194 sigslot::signal1<cricket::IceGatheringState> SignalIceGatheringState;
195
196 // (mid, candidates)
197 sigslot::signal2<const std::string&, const std::vector<cricket::Candidate>&>
198 SignalIceCandidatesGathered;
199
200 sigslot::signal1<const std::vector<cricket::Candidate>&>
201 SignalIceCandidatesRemoved;
202
203 sigslot::signal1<rtc::SSLHandshakeError> SignalDtlsHandshakeError;
204
Bjorn Mellem175aa2e2018-11-08 11:23:22 -0800205 sigslot::signal<> SignalMediaTransportStateChanged;
206
Zhi Huange818b6e2018-02-22 15:26:27 -0800207 private:
Zhi Huange818b6e2018-02-22 15:26:27 -0800208 RTCError ApplyDescription_n(bool local,
209 SdpType type,
210 const cricket::SessionDescription* description);
Zhi Huangd2248f82018-04-10 14:41:03 -0700211 RTCError ValidateAndMaybeUpdateBundleGroup(
212 bool local,
213 SdpType type,
214 const cricket::SessionDescription* description);
Zhi Huange830e682018-03-30 10:48:35 -0700215 RTCError ValidateContent(const cricket::ContentInfo& content_info);
Zhi Huange818b6e2018-02-22 15:26:27 -0800216
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700217 void HandleRejectedContent(const cricket::ContentInfo& content_info,
Zhi Huangd2248f82018-04-10 14:41:03 -0700218 const cricket::SessionDescription* description);
Zhi Huang365381f2018-04-13 16:44:34 -0700219 bool HandleBundledContent(const cricket::ContentInfo& content_info);
Zhi Huange818b6e2018-02-22 15:26:27 -0800220
Zhi Huang365381f2018-04-13 16:44:34 -0700221 bool SetTransportForMid(const std::string& mid,
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700222 cricket::JsepTransport* jsep_transport);
223 void RemoveTransportForMid(const std::string& mid);
Zhi Huangd2248f82018-04-10 14:41:03 -0700224
Zhi Huange818b6e2018-02-22 15:26:27 -0800225 cricket::JsepTransportDescription CreateJsepTransportDescription(
226 cricket::ContentInfo content_info,
227 cricket::TransportInfo transport_info,
Zhi Huange830e682018-03-30 10:48:35 -0700228 const std::vector<int>& encrypted_extension_ids,
229 int rtp_abs_sendtime_extn_id);
Zhi Huange818b6e2018-02-22 15:26:27 -0800230
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200231 absl::optional<std::string> bundled_mid() const {
232 absl::optional<std::string> bundled_mid;
Taylor Brandstetter0ab56512018-04-12 10:30:48 -0700233 if (bundle_group_ && bundle_group_->FirstContentName()) {
234 bundled_mid = *(bundle_group_->FirstContentName());
Zhi Huange818b6e2018-02-22 15:26:27 -0800235 }
236 return bundled_mid;
237 }
238
239 bool IsBundled(const std::string& mid) const {
240 return bundle_group_ && bundle_group_->HasContentName(mid);
241 }
242
243 bool ShouldUpdateBundleGroup(SdpType type,
244 const cricket::SessionDescription* description);
245
246 std::vector<int> MergeEncryptedHeaderExtensionIdsForBundle(
247 const cricket::SessionDescription* description);
Zhi Huange818b6e2018-02-22 15:26:27 -0800248 std::vector<int> GetEncryptedHeaderExtensionIds(
249 const cricket::ContentInfo& content_info);
250
Zhi Huange830e682018-03-30 10:48:35 -0700251 int GetRtpAbsSendTimeHeaderExtensionId(
252 const cricket::ContentInfo& content_info);
Zhi Huange818b6e2018-02-22 15:26:27 -0800253
Zhi Huange830e682018-03-30 10:48:35 -0700254 // This method takes the BUNDLE group into account. If the JsepTransport is
255 // destroyed because of BUNDLE, it would return the transport which other
256 // transports are bundled on (In current implementation, it is the first
257 // content in the BUNDLE group).
Zhi Huang365381f2018-04-13 16:44:34 -0700258 const cricket::JsepTransport* GetJsepTransportForMid(
Zhi Huange830e682018-03-30 10:48:35 -0700259 const std::string& mid) const;
Zhi Huang365381f2018-04-13 16:44:34 -0700260 cricket::JsepTransport* GetJsepTransportForMid(const std::string& mid);
Zhi Huange830e682018-03-30 10:48:35 -0700261
262 // Get the JsepTransport without considering the BUNDLE group. Return nullptr
263 // if the JsepTransport is destroyed.
Zhi Huang365381f2018-04-13 16:44:34 -0700264 const cricket::JsepTransport* GetJsepTransportByName(
Zhi Huange830e682018-03-30 10:48:35 -0700265 const std::string& transport_name) const;
Zhi Huang365381f2018-04-13 16:44:34 -0700266 cricket::JsepTransport* GetJsepTransportByName(
Zhi Huange830e682018-03-30 10:48:35 -0700267 const std::string& transport_name);
268
Anton Sukhanov7940da02018-10-10 10:34:49 -0700269 // Creates jsep transport. Noop if transport is already created.
270 // Transport is created either during SetLocalDescription (|local| == true) or
271 // during SetRemoteDescription (|local| == false). Passing |local| helps to
272 // differentiate initiator (caller) from answerer (callee).
273 RTCError MaybeCreateJsepTransport(bool local,
274 const cricket::ContentInfo& content_info);
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -0800275
276 // Creates media transport if config wants to use it, and pre-shared key is
277 // provided in content info. It modifies the config to disable media transport
278 // if pre-shared key is not provided.
279 std::unique_ptr<webrtc::MediaTransportInterface> MaybeCreateMediaTransport(
280 const cricket::ContentInfo& content_info,
281 bool local,
282 cricket::IceTransportInternal* ice_transport);
Zhi Huange818b6e2018-02-22 15:26:27 -0800283 void MaybeDestroyJsepTransport(const std::string& mid);
284 void DestroyAllJsepTransports_n();
285
286 void SetIceRole_n(cricket::IceRole ice_role);
287
288 cricket::IceRole DetermineIceRole(
Zhi Huang365381f2018-04-13 16:44:34 -0700289 cricket::JsepTransport* jsep_transport,
Zhi Huange818b6e2018-02-22 15:26:27 -0800290 const cricket::TransportInfo& transport_info,
291 SdpType type,
292 bool local);
293
294 std::unique_ptr<cricket::DtlsTransportInternal> CreateDtlsTransport(
295 const std::string& transport_name,
296 bool rtcp);
297
298 std::unique_ptr<webrtc::RtpTransport> CreateUnencryptedRtpTransport(
299 const std::string& transport_name,
300 rtc::PacketTransportInternal* rtp_packet_transport,
301 rtc::PacketTransportInternal* rtcp_packet_transport);
302 std::unique_ptr<webrtc::SrtpTransport> CreateSdesTransport(
303 const std::string& transport_name,
Zhi Huange830e682018-03-30 10:48:35 -0700304 cricket::DtlsTransportInternal* rtp_dtls_transport,
305 cricket::DtlsTransportInternal* rtcp_dtls_transport);
Zhi Huange818b6e2018-02-22 15:26:27 -0800306 std::unique_ptr<webrtc::DtlsSrtpTransport> CreateDtlsSrtpTransport(
307 const std::string& transport_name,
308 cricket::DtlsTransportInternal* rtp_dtls_transport,
309 cricket::DtlsTransportInternal* rtcp_dtls_transport);
310
311 // Collect all the DtlsTransports, including RTP and RTCP, from the
312 // JsepTransports. JsepTransportController can iterate all the DtlsTransports
313 // and update the aggregate states.
314 std::vector<cricket::DtlsTransportInternal*> GetDtlsTransports();
315
316 // Handlers for signals from Transport.
317 void OnTransportWritableState_n(rtc::PacketTransportInternal* transport);
318 void OnTransportReceivingState_n(rtc::PacketTransportInternal* transport);
319 void OnTransportGatheringState_n(cricket::IceTransportInternal* transport);
320 void OnTransportCandidateGathered_n(cricket::IceTransportInternal* transport,
321 const cricket::Candidate& candidate);
Zhi Huange818b6e2018-02-22 15:26:27 -0800322 void OnTransportCandidatesRemoved_n(cricket::IceTransportInternal* transport,
323 const cricket::Candidates& candidates);
324 void OnTransportRoleConflict_n(cricket::IceTransportInternal* transport);
325 void OnTransportStateChanged_n(cricket::IceTransportInternal* transport);
Bjorn Mellem175aa2e2018-11-08 11:23:22 -0800326 void OnMediaTransportStateChanged_n();
Zhi Huange818b6e2018-02-22 15:26:27 -0800327
328 void UpdateAggregateStates_n();
329
330 void OnDtlsHandshakeError(rtc::SSLHandshakeError error);
331
332 rtc::Thread* const signaling_thread_ = nullptr;
333 rtc::Thread* const network_thread_ = nullptr;
334 cricket::PortAllocator* const port_allocator_ = nullptr;
Zach Steine20867f2018-08-02 13:20:15 -0700335 AsyncResolverFactory* const async_resolver_factory_ = nullptr;
Zhi Huange818b6e2018-02-22 15:26:27 -0800336
Zhi Huang365381f2018-04-13 16:44:34 -0700337 std::map<std::string, std::unique_ptr<cricket::JsepTransport>>
Zhi Huange830e682018-03-30 10:48:35 -0700338 jsep_transports_by_name_;
Zhi Huangd2248f82018-04-10 14:41:03 -0700339 // This keeps track of the mapping between media section
Zhi Huang365381f2018-04-13 16:44:34 -0700340 // (BaseChannel/SctpTransport) and the JsepTransport underneath.
341 std::map<std::string, cricket::JsepTransport*> mid_to_transport_;
Zhi Huange818b6e2018-02-22 15:26:27 -0800342
Jonas Olsson635474e2018-10-18 15:58:17 +0200343 // Aggregate states for Transports.
344 // standardized_ice_connection_state_ is intended to replace
345 // ice_connection_state, see bugs.webrtc.org/9308
Zhi Huange818b6e2018-02-22 15:26:27 -0800346 cricket::IceConnectionState ice_connection_state_ =
347 cricket::kIceConnectionConnecting;
Jonas Olsson635474e2018-10-18 15:58:17 +0200348 PeerConnectionInterface::IceConnectionState
349 standardized_ice_connection_state_ =
350 PeerConnectionInterface::kIceConnectionNew;
351 PeerConnectionInterface::PeerConnectionState combined_connection_state_ =
352 PeerConnectionInterface::PeerConnectionState::kNew;
Zhi Huange818b6e2018-02-22 15:26:27 -0800353 cricket::IceGatheringState ice_gathering_state_ = cricket::kIceGatheringNew;
354
355 Config config_;
356 const cricket::SessionDescription* local_desc_ = nullptr;
357 const cricket::SessionDescription* remote_desc_ = nullptr;
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200358 absl::optional<bool> initial_offerer_;
Zhi Huange818b6e2018-02-22 15:26:27 -0800359
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200360 absl::optional<cricket::ContentGroup> bundle_group_;
Zhi Huange818b6e2018-02-22 15:26:27 -0800361
362 cricket::IceConfig ice_config_;
363 cricket::IceRole ice_role_ = cricket::ICEROLE_CONTROLLING;
364 uint64_t ice_tiebreaker_ = rtc::CreateRandomId64();
365 rtc::scoped_refptr<rtc::RTCCertificate> certificate_;
366 rtc::AsyncInvoker invoker_;
367
Zhi Huange818b6e2018-02-22 15:26:27 -0800368 RTC_DISALLOW_COPY_AND_ASSIGN(JsepTransportController);
369};
370
371} // namespace webrtc
372
373#endif // PC_JSEPTRANSPORTCONTROLLER_H_