webrtc_m130/pc/jseptransportcontroller.h

349 lines
14 KiB
C
Raw Normal View History

/*
* Copyright 2017 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef PC_JSEPTRANSPORTCONTROLLER_H_
#define PC_JSEPTRANSPORTCONTROLLER_H_
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "api/candidate.h"
Reland "Move CryptoOptions to api/crypto from rtc_base/sslstreamadapter.h" Promotes rtc::CryptoOptions to webrtc::CryptoOptions converting it from class that only handles SRTP configuration to a more generic structure that can be used and extended for all per peer connection CryptoOptions that can be on a given PeerConnection. Now all SRTP related options are under webrtc::CryptoOptions::Srtp and can be accessed as crypto_options.srtp.whatever_option_name. This is more inline with other structures we have in WebRTC such as VideoConfig. As additional features are added over time this will allow the structure to remain compartmentalized and concerned components can only request a subset of the overall configuration structure e.g: void MySrtpFunction(const webrtc::CryptoOptions::Srtp& srtp_config); In addition to this it made little sense for sslstreamadapter.h to hold all Srtp related configuration options. The header has become loo large and takes on too many responsibilities and spilting this up will lead to more maintainable code going forward. This will be used in a future CL to enable configuration options for the newly supported Frame Crypto. Reland Fix: - cryptooptions.h - now has enable_aes128_sha1_32_crypto_cipher as an optional root level configuration. - peerconnectionfactory - If this optional is set will now overwrite the underyling value. This along with the other field will be deprecated once dependent projects are updated. TBR=sakal@webrtc.org,kthelgason@webrtc.org,emadomara@webrtc.org,qingsi@webrtc.org Bug: webrtc:9681 Change-Id: Iaa6b741baafb85d352e42f54226119f19d97151d Reviewed-on: https://webrtc-review.googlesource.com/c/105560 Reviewed-by: Benjamin Wright <benwright@webrtc.org> Reviewed-by: Steve Anton <steveanton@webrtc.org> Reviewed-by: Emad Omara <emadomara@webrtc.org> Commit-Queue: Benjamin Wright <benwright@webrtc.org> Cr-Commit-Position: refs/heads/master@{#25135}
2018-10-11 15:33:17 -07:00
#include "api/crypto/cryptooptions.h"
#include "api/media_transport_interface.h"
#include "api/peerconnectioninterface.h"
#include "logging/rtc_event_log/rtc_event_log.h"
#include "media/sctp/sctptransportinternal.h"
#include "p2p/base/dtlstransport.h"
#include "p2p/base/p2ptransportchannel.h"
#include "p2p/base/transportfactoryinterface.h"
#include "pc/channel.h"
#include "pc/dtlssrtptransport.h"
#include "pc/jseptransport.h"
#include "pc/rtptransport.h"
#include "pc/srtptransport.h"
#include "rtc_base/asyncinvoker.h"
#include "rtc_base/constructormagic.h"
#include "rtc_base/refcountedobject.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
namespace rtc {
class Thread;
class PacketTransportInternal;
} // namespace rtc
namespace webrtc {
class JsepTransportController : public sigslot::has_slots<> {
public:
// Used when the RtpTransport/DtlsTransport of the m= section is changed
// because the section is rejected or BUNDLE is enabled.
class Observer {
public:
virtual ~Observer() {}
// Returns true if media associated with |mid| was successfully set up to be
// demultiplexed on |rtp_transport|. Could return false if two bundled m=
// sections use the same SSRC, for example.
virtual bool OnTransportChanged(
const std::string& mid,
RtpTransportInternal* rtp_transport,
cricket::DtlsTransportInternal* dtls_transport) = 0;
};
struct Config {
// If |redetermine_role_on_ice_restart| is true, ICE role is redetermined
// upon setting a local transport description that indicates an ICE
// restart.
bool redetermine_role_on_ice_restart = true;
rtc::SSLProtocolVersion ssl_max_version = rtc::SSL_PROTOCOL_DTLS_12;
// |crypto_options| is used to determine if created DTLS transports
// negotiate GCM crypto suites or not.
Reland "Move CryptoOptions to api/crypto from rtc_base/sslstreamadapter.h" Promotes rtc::CryptoOptions to webrtc::CryptoOptions converting it from class that only handles SRTP configuration to a more generic structure that can be used and extended for all per peer connection CryptoOptions that can be on a given PeerConnection. Now all SRTP related options are under webrtc::CryptoOptions::Srtp and can be accessed as crypto_options.srtp.whatever_option_name. This is more inline with other structures we have in WebRTC such as VideoConfig. As additional features are added over time this will allow the structure to remain compartmentalized and concerned components can only request a subset of the overall configuration structure e.g: void MySrtpFunction(const webrtc::CryptoOptions::Srtp& srtp_config); In addition to this it made little sense for sslstreamadapter.h to hold all Srtp related configuration options. The header has become loo large and takes on too many responsibilities and spilting this up will lead to more maintainable code going forward. This will be used in a future CL to enable configuration options for the newly supported Frame Crypto. Reland Fix: - cryptooptions.h - now has enable_aes128_sha1_32_crypto_cipher as an optional root level configuration. - peerconnectionfactory - If this optional is set will now overwrite the underyling value. This along with the other field will be deprecated once dependent projects are updated. TBR=sakal@webrtc.org,kthelgason@webrtc.org,emadomara@webrtc.org,qingsi@webrtc.org Bug: webrtc:9681 Change-Id: Iaa6b741baafb85d352e42f54226119f19d97151d Reviewed-on: https://webrtc-review.googlesource.com/c/105560 Reviewed-by: Benjamin Wright <benwright@webrtc.org> Reviewed-by: Steve Anton <steveanton@webrtc.org> Reviewed-by: Emad Omara <emadomara@webrtc.org> Commit-Queue: Benjamin Wright <benwright@webrtc.org> Cr-Commit-Position: refs/heads/master@{#25135}
2018-10-11 15:33:17 -07:00
webrtc::CryptoOptions crypto_options;
PeerConnectionInterface::BundlePolicy bundle_policy =
PeerConnectionInterface::kBundlePolicyBalanced;
PeerConnectionInterface::RtcpMuxPolicy rtcp_mux_policy =
PeerConnectionInterface::kRtcpMuxPolicyRequire;
bool disable_encryption = false;
bool enable_external_auth = false;
// Used to inject the ICE/DTLS transports created externally.
cricket::TransportFactoryInterface* external_transport_factory = nullptr;
Observer* transport_observer = nullptr;
bool active_reset_srtp_params = false;
RtcEventLog* event_log = nullptr;
// Optional media transport factory (experimental). If provided it will be
// used to create media_transport and will be used to send / receive
// audio and video frames instead of RTP. Note that currently
// media_transport co-exists with RTP / RTCP transports and uses the same
// underlying ICE transport.
MediaTransportFactory* media_transport_factory = nullptr;
};
// The ICE related events are signaled on the |signaling_thread|.
// All the transport related methods are called on the |network_thread|.
JsepTransportController(rtc::Thread* signaling_thread,
rtc::Thread* network_thread,
cricket::PortAllocator* port_allocator,
AsyncResolverFactory* async_resolver_factory,
Config config);
virtual ~JsepTransportController();
// The main method to be called; applies a description at the transport
// level, creating/destroying transport objects as needed and updating their
// properties. This includes RTP, DTLS, and ICE (but not SCTP). At least not
// yet? May make sense to in the future.
RTCError SetLocalDescription(SdpType type,
const cricket::SessionDescription* description);
RTCError SetRemoteDescription(SdpType type,
const cricket::SessionDescription* description);
// Get transports to be used for the provided |mid|. If bundling is enabled,
// calling GetRtpTransport for multiple MIDs may yield the same object.
RtpTransportInternal* GetRtpTransport(const std::string& mid) const;
cricket::DtlsTransportInternal* GetDtlsTransport(
const std::string& mid) const;
cricket::DtlsTransportInternal* GetRtcpDtlsTransport(
const std::string& mid) const;
MediaTransportInterface* GetMediaTransport(const std::string& mid) const;
/*********************
* ICE-related methods
********************/
// This method is public to allow PeerConnection to update it from
// SetConfiguration.
void SetIceConfig(const cricket::IceConfig& config);
// Set the "needs-ice-restart" flag as described in JSEP. After the flag is
// set, offers should generate new ufrags/passwords until an ICE restart
// occurs.
void SetNeedsIceRestartFlag();
// Returns true if the ICE restart flag above was set, and no ICE restart has
// occurred yet for this transport (by applying a local description with
// changed ufrag/password). If the transport has been deleted as a result of
// bundling, returns false.
bool NeedsIceRestart(const std::string& mid) const;
// Start gathering candidates for any new transports, or transports doing an
// ICE restart.
void MaybeStartGathering();
RTCError AddRemoteCandidates(
const std::string& mid,
const std::vector<cricket::Candidate>& candidates);
RTCError RemoveRemoteCandidates(
const std::vector<cricket::Candidate>& candidates);
/**********************
* DTLS-related methods
*********************/
// Specifies the identity to use in this session.
// Can only be called once.
bool SetLocalCertificate(
const rtc::scoped_refptr<rtc::RTCCertificate>& certificate);
rtc::scoped_refptr<rtc::RTCCertificate> GetLocalCertificate(
const std::string& mid) const;
// Caller owns returned certificate chain. This method mainly exists for
// stats reporting.
std::unique_ptr<rtc::SSLCertChain> GetRemoteSSLCertChain(
const std::string& mid) const;
// Get negotiated role, if one has been negotiated.
absl::optional<rtc::SSLRole> GetDtlsRole(const std::string& mid) const;
// TODO(deadbeef): GetStats isn't const because all the way down to
// OpenSSLStreamAdapter, GetSslCipherSuite and GetDtlsSrtpCryptoSuite are not
// const. Fix this.
bool GetStats(const std::string& mid, cricket::TransportStats* stats);
bool initial_offerer() const { return initial_offerer_ && *initial_offerer_; }
void SetActiveResetSrtpParams(bool active_reset_srtp_params);
// Allows to overwrite the settings from config. You may set or reset the
// media transport factory on the jsep transport controller, as long as you
// did not call 'GetMediaTransport' or 'MaybeCreateJsepTransport'. Once Jsep
// transport is created, you can't change this setting.
void SetMediaTransportFactory(MediaTransportFactory* media_transport_factory);
// All of these signals are fired on the signaling thread.
// If any transport failed => failed,
// Else if all completed => completed,
// Else if all connected => connected,
// Else => connecting
sigslot::signal1<cricket::IceConnectionState> SignalIceConnectionState;
// If all transports done gathering => complete,
// Else if any are gathering => gathering,
// Else => new
sigslot::signal1<cricket::IceGatheringState> SignalIceGatheringState;
// (mid, candidates)
sigslot::signal2<const std::string&, const std::vector<cricket::Candidate>&>
SignalIceCandidatesGathered;
sigslot::signal1<const std::vector<cricket::Candidate>&>
SignalIceCandidatesRemoved;
sigslot::signal1<rtc::SSLHandshakeError> SignalDtlsHandshakeError;
private:
RTCError ApplyDescription_n(bool local,
SdpType type,
const cricket::SessionDescription* description);
RTCError ValidateAndMaybeUpdateBundleGroup(
bool local,
SdpType type,
const cricket::SessionDescription* description);
RTCError ValidateContent(const cricket::ContentInfo& content_info);
void HandleRejectedContent(const cricket::ContentInfo& content_info,
const cricket::SessionDescription* description);
bool HandleBundledContent(const cricket::ContentInfo& content_info);
bool SetTransportForMid(const std::string& mid,
cricket::JsepTransport* jsep_transport);
void RemoveTransportForMid(const std::string& mid);
cricket::JsepTransportDescription CreateJsepTransportDescription(
cricket::ContentInfo content_info,
cricket::TransportInfo transport_info,
const std::vector<int>& encrypted_extension_ids,
int rtp_abs_sendtime_extn_id);
absl::optional<std::string> bundled_mid() const {
absl::optional<std::string> bundled_mid;
if (bundle_group_ && bundle_group_->FirstContentName()) {
bundled_mid = *(bundle_group_->FirstContentName());
}
return bundled_mid;
}
bool IsBundled(const std::string& mid) const {
return bundle_group_ && bundle_group_->HasContentName(mid);
}
bool ShouldUpdateBundleGroup(SdpType type,
const cricket::SessionDescription* description);
std::vector<int> MergeEncryptedHeaderExtensionIdsForBundle(
const cricket::SessionDescription* description);
std::vector<int> GetEncryptedHeaderExtensionIds(
const cricket::ContentInfo& content_info);
int GetRtpAbsSendTimeHeaderExtensionId(
const cricket::ContentInfo& content_info);
// This method takes the BUNDLE group into account. If the JsepTransport is
// destroyed because of BUNDLE, it would return the transport which other
// transports are bundled on (In current implementation, it is the first
// content in the BUNDLE group).
const cricket::JsepTransport* GetJsepTransportForMid(
const std::string& mid) const;
cricket::JsepTransport* GetJsepTransportForMid(const std::string& mid);
// Get the JsepTransport without considering the BUNDLE group. Return nullptr
// if the JsepTransport is destroyed.
const cricket::JsepTransport* GetJsepTransportByName(
const std::string& transport_name) const;
cricket::JsepTransport* GetJsepTransportByName(
const std::string& transport_name);
// Creates jsep transport. Noop if transport is already created.
// Transport is created either during SetLocalDescription (|local| == true) or
// during SetRemoteDescription (|local| == false). Passing |local| helps to
// differentiate initiator (caller) from answerer (callee).
RTCError MaybeCreateJsepTransport(bool local,
const cricket::ContentInfo& content_info);
void MaybeDestroyJsepTransport(const std::string& mid);
void DestroyAllJsepTransports_n();
void SetIceRole_n(cricket::IceRole ice_role);
cricket::IceRole DetermineIceRole(
cricket::JsepTransport* jsep_transport,
const cricket::TransportInfo& transport_info,
SdpType type,
bool local);
std::unique_ptr<cricket::DtlsTransportInternal> CreateDtlsTransport(
const std::string& transport_name,
bool rtcp);
std::unique_ptr<webrtc::RtpTransport> CreateUnencryptedRtpTransport(
const std::string& transport_name,
rtc::PacketTransportInternal* rtp_packet_transport,
rtc::PacketTransportInternal* rtcp_packet_transport);
std::unique_ptr<webrtc::SrtpTransport> CreateSdesTransport(
const std::string& transport_name,
cricket::DtlsTransportInternal* rtp_dtls_transport,
cricket::DtlsTransportInternal* rtcp_dtls_transport);
std::unique_ptr<webrtc::DtlsSrtpTransport> CreateDtlsSrtpTransport(
const std::string& transport_name,
cricket::DtlsTransportInternal* rtp_dtls_transport,
cricket::DtlsTransportInternal* rtcp_dtls_transport);
// Collect all the DtlsTransports, including RTP and RTCP, from the
// JsepTransports. JsepTransportController can iterate all the DtlsTransports
// and update the aggregate states.
std::vector<cricket::DtlsTransportInternal*> GetDtlsTransports();
// Handlers for signals from Transport.
void OnTransportWritableState_n(rtc::PacketTransportInternal* transport);
void OnTransportReceivingState_n(rtc::PacketTransportInternal* transport);
void OnTransportGatheringState_n(cricket::IceTransportInternal* transport);
void OnTransportCandidateGathered_n(cricket::IceTransportInternal* transport,
const cricket::Candidate& candidate);
void OnTransportCandidatesRemoved_n(cricket::IceTransportInternal* transport,
const cricket::Candidates& candidates);
void OnTransportRoleConflict_n(cricket::IceTransportInternal* transport);
void OnTransportStateChanged_n(cricket::IceTransportInternal* transport);
void UpdateAggregateStates_n();
void OnDtlsHandshakeError(rtc::SSLHandshakeError error);
rtc::Thread* const signaling_thread_ = nullptr;
rtc::Thread* const network_thread_ = nullptr;
cricket::PortAllocator* const port_allocator_ = nullptr;
AsyncResolverFactory* const async_resolver_factory_ = nullptr;
std::map<std::string, std::unique_ptr<cricket::JsepTransport>>
jsep_transports_by_name_;
// This keeps track of the mapping between media section
// (BaseChannel/SctpTransport) and the JsepTransport underneath.
std::map<std::string, cricket::JsepTransport*> mid_to_transport_;
// Aggregate state for Transports.
cricket::IceConnectionState ice_connection_state_ =
cricket::kIceConnectionConnecting;
cricket::IceGatheringState ice_gathering_state_ = cricket::kIceGatheringNew;
Config config_;
const cricket::SessionDescription* local_desc_ = nullptr;
const cricket::SessionDescription* remote_desc_ = nullptr;
absl::optional<bool> initial_offerer_;
absl::optional<cricket::ContentGroup> bundle_group_;
cricket::IceConfig ice_config_;
cricket::IceRole ice_role_ = cricket::ICEROLE_CONTROLLING;
uint64_t ice_tiebreaker_ = rtc::CreateRandomId64();
rtc::scoped_refptr<rtc::RTCCertificate> certificate_;
rtc::AsyncInvoker invoker_;
RTC_DISALLOW_COPY_AND_ASSIGN(JsepTransportController);
};
} // namespace webrtc
#endif // PC_JSEPTRANSPORTCONTROLLER_H_