blob: ea07dfe83f625e1cf0f8608934933d3526917bfd [file] [log] [blame]
/*
* Copyright 2015 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_TRANSPORTCONTROLLER_H_
#define PC_TRANSPORTCONTROLLER_H_
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "api/candidate.h"
#include "p2p/base/dtlstransport.h"
#include "p2p/base/p2ptransportchannel.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/sigslot.h"
#include "rtc_base/sslstreamadapter.h"
namespace rtc {
class Thread;
class PacketTransportInternal;
} // namespace rtc
namespace webrtc {
class MetricsObserverInterface;
class RtcEventLog;
} // namespace webrtc
namespace cricket {
class TransportController : public sigslot::has_slots<>,
public rtc::MessageHandler {
public:
// If |redetermine_role_on_ice_restart| is true, ICE role is redetermined
// upon setting a local transport description that indicates an ICE restart.
// For the constructor that doesn't take this parameter, it defaults to true.
//
// |crypto_options| is used to determine if created DTLS transports negotiate
// GCM crypto suites or not.
TransportController(rtc::Thread* signaling_thread,
rtc::Thread* network_thread,
PortAllocator* port_allocator,
bool redetermine_role_on_ice_restart,
const rtc::CryptoOptions& crypto_options,
webrtc::RtcEventLog* event_log = nullptr);
virtual ~TransportController();
rtc::Thread* signaling_thread() const { return signaling_thread_; }
rtc::Thread* network_thread() const { return network_thread_; }
PortAllocator* port_allocator() const { return port_allocator_; }
// Can only be set before transports are created.
// TODO(deadbeef): Make this an argument to the constructor once BaseSession
// and WebRtcSession are combined
bool SetSslMaxProtocolVersion(rtc::SSLProtocolVersion version);
void SetIceConfig(const IceConfig& config);
void SetIceRole(IceRole ice_role);
// 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& transport_name) const;
bool GetSslRole(const std::string& transport_name, rtc::SSLRole* role) const;
// Specifies the identity to use in this session.
// Can only be called once.
bool SetLocalCertificate(
const rtc::scoped_refptr<rtc::RTCCertificate>& certificate);
bool GetLocalCertificate(
const std::string& transport_name,
rtc::scoped_refptr<rtc::RTCCertificate>* certificate) const;
// Caller owns returned certificate chain. This method mainly exists for
// stats reporting.
std::unique_ptr<rtc::SSLCertChain> GetRemoteSSLCertChain(
const std::string& transport_name) const;
bool SetLocalTransportDescription(const std::string& transport_name,
const TransportDescription& tdesc,
webrtc::SdpType type,
std::string* err);
bool SetRemoteTransportDescription(const std::string& transport_name,
const TransportDescription& tdesc,
webrtc::SdpType type,
std::string* err);
// Start gathering candidates for any new transports, or transports doing an
// ICE restart.
void MaybeStartGathering();
bool AddRemoteCandidates(const std::string& transport_name,
const Candidates& candidates,
std::string* err);
bool RemoveRemoteCandidates(const Candidates& candidates, std::string* err);
bool ReadyForRemoteCandidates(const std::string& transport_name) 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& transport_name, TransportStats* stats);
void SetMetricsObserver(webrtc::MetricsObserverInterface* metrics_observer);
// Creates a channel if it doesn't exist. Otherwise, increments a reference
// count and returns an existing channel.
DtlsTransportInternal* CreateDtlsTransport(const std::string& transport_name,
int component);
virtual DtlsTransportInternal* CreateDtlsTransport_n(
const std::string& transport_name,
int component);
// Decrements a channel's reference count, and destroys the channel if
// nothing is referencing it.
virtual void DestroyDtlsTransport(const std::string& transport_name,
int component);
virtual void DestroyDtlsTransport_n(const std::string& transport_name,
int component);
// Create an SrtpTransport/DtlsSrtpTransport if it doesn't exist.
// Otherwise, increments a reference count and returns the existing one.
// These methods are not currently used but the plan is to transition
// PeerConnection and BaseChannel to use them instead of CreateDtlsTransport.
webrtc::SrtpTransport* CreateSdesTransport(const std::string& transport_name,
bool rtcp_mux_enabled);
webrtc::DtlsSrtpTransport* CreateDtlsSrtpTransport(
const std::string& transport_name,
bool rtcp_mux_enabled);
// Destroy an RTP level transport which can be an RtpTransport, an
// SrtpTransport or a DtlsSrtpTransport.
void DestroyTransport(const std::string& transport_name);
// TODO(deadbeef): Remove all for_testing methods!
const rtc::scoped_refptr<rtc::RTCCertificate>& certificate_for_testing()
const {
return certificate_;
}
std::vector<std::string> transport_names_for_testing();
std::vector<DtlsTransportInternal*> channels_for_testing();
DtlsTransportInternal* get_channel_for_testing(
const std::string& transport_name,
int component);
// All of these signals are fired on the signalling thread.
// If any transport failed => failed,
// Else if all completed => completed,
// Else if all connected => connected,
// Else => connecting
sigslot::signal1<IceConnectionState> SignalConnectionState;
// Receiving if any transport is receiving
sigslot::signal1<bool> SignalReceiving;
// If all transports done gathering => complete,
// Else if any are gathering => gathering,
// Else => new
sigslot::signal1<IceGatheringState> SignalGatheringState;
// (transport_name, candidates)
sigslot::signal2<const std::string&, const Candidates&>
SignalCandidatesGathered;
sigslot::signal1<const Candidates&> SignalCandidatesRemoved;
sigslot::signal1<rtc::SSLHandshakeError> SignalDtlsHandshakeError;
protected:
// TODO(deadbeef): Get rid of these virtual methods. Used by
// FakeTransportController currently, but FakeTransportController shouldn't
// even be functioning by subclassing TransportController.
virtual IceTransportInternal* CreateIceTransportChannel_n(
const std::string& transport_name,
int component);
virtual DtlsTransportInternal* CreateDtlsTransportChannel_n(
const std::string& transport_name,
int component,
IceTransportInternal* ice);
private:
void OnMessage(rtc::Message* pmsg) override;
class ChannelPair;
typedef rtc::RefCountedObject<ChannelPair> RefCountedChannel;
// Wrapper for RtpTransport that keeps a reference count.
// When using SDES, |srtp_transport| is non-null, |dtls_srtp_transport| is
// null and |rtp_transport.get()| == |srtp_transport|,
// When using DTLS-SRTP, |dtls_srtp_transport| is non-null, |srtp_transport|
// is null and |rtp_transport.get()| == |dtls_srtp_transport|,
// When using unencrypted RTP, only |rtp_transport| is non-null.
struct RtpTransportWrapper {
// |rtp_transport| is always non-null.
std::unique_ptr<webrtc::RtpTransportInternal> rtp_transport;
webrtc::SrtpTransport* srtp_transport = nullptr;
webrtc::DtlsSrtpTransport* dtls_srtp_transport = nullptr;
};
typedef rtc::RefCountedObject<RtpTransportWrapper> RefCountedRtpTransport;
const RefCountedRtpTransport* FindRtpTransport(
const std::string& transport_name);
// Helper functions to get a channel or transport, or iterator to it (in case
// it needs to be erased).
std::vector<RefCountedChannel*>::iterator GetChannelIterator_n(
const std::string& transport_name,
int component);
std::vector<RefCountedChannel*>::const_iterator GetChannelIterator_n(
const std::string& transport_name,
int component) const;
const JsepTransport* GetJsepTransport(
const std::string& transport_name) const;
JsepTransport* GetJsepTransport(const std::string& transport_name);
const RefCountedChannel* GetChannel_n(const std::string& transport_name,
int component) const;
RefCountedChannel* GetChannel_n(const std::string& transport_name,
int component);
JsepTransport* GetOrCreateJsepTransport(const std::string& transport_name);
void DestroyAllChannels_n();
bool SetSslMaxProtocolVersion_n(rtc::SSLProtocolVersion version);
void SetIceConfig_n(const IceConfig& config);
void SetIceRole_n(IceRole ice_role);
bool GetSslRole_n(const std::string& transport_name,
rtc::SSLRole* role) const;
bool SetLocalCertificate_n(
const rtc::scoped_refptr<rtc::RTCCertificate>& certificate);
bool GetLocalCertificate_n(
const std::string& transport_name,
rtc::scoped_refptr<rtc::RTCCertificate>* certificate) const;
bool SetLocalTransportDescription_n(const std::string& transport_name,
const TransportDescription& tdesc,
webrtc::SdpType type,
std::string* err);
bool SetRemoteTransportDescription_n(const std::string& transport_name,
const TransportDescription& tdesc,
webrtc::SdpType type,
std::string* err);
void MaybeStartGathering_n();
bool AddRemoteCandidates_n(const std::string& transport_name,
const Candidates& candidates,
std::string* err);
bool RemoveRemoteCandidates_n(const Candidates& candidates, std::string* err);
bool ReadyForRemoteCandidates_n(const std::string& transport_name) const;
bool GetStats_n(const std::string& transport_name, TransportStats* stats);
void SetMetricsObserver_n(webrtc::MetricsObserverInterface* metrics_observer);
// Handlers for signals from Transport.
void OnChannelWritableState_n(rtc::PacketTransportInternal* transport);
void OnChannelReceivingState_n(rtc::PacketTransportInternal* transport);
void OnChannelGatheringState_n(IceTransportInternal* channel);
void OnChannelCandidateGathered_n(IceTransportInternal* channel,
const Candidate& candidate);
void OnChannelCandidatesRemoved(const Candidates& candidates);
void OnChannelCandidatesRemoved_n(IceTransportInternal* channel,
const Candidates& candidates);
void OnChannelRoleConflict_n(IceTransportInternal* channel);
void OnChannelStateChanged_n(IceTransportInternal* channel);
void UpdateAggregateStates_n();
void OnDtlsHandshakeError(rtc::SSLHandshakeError error);
rtc::Thread* const signaling_thread_ = nullptr;
rtc::Thread* const network_thread_ = nullptr;
PortAllocator* const port_allocator_ = nullptr;
std::map<std::string, std::unique_ptr<JsepTransport>> transports_;
std::vector<RefCountedChannel*> channels_;
std::map<std::string, RefCountedRtpTransport*> rtp_transports_;
// Aggregate state for TransportChannelImpls.
IceConnectionState connection_state_ = kIceConnectionConnecting;
bool receiving_ = false;
IceGatheringState gathering_state_ = kIceGatheringNew;
IceConfig ice_config_;
IceRole ice_role_ = ICEROLE_CONTROLLING;
bool redetermine_role_on_ice_restart_;
uint64_t ice_tiebreaker_ = rtc::CreateRandomId64();
rtc::CryptoOptions crypto_options_;
rtc::SSLProtocolVersion ssl_max_version_ = rtc::SSL_PROTOCOL_DTLS_12;
rtc::scoped_refptr<rtc::RTCCertificate> certificate_;
rtc::AsyncInvoker invoker_;
webrtc::MetricsObserverInterface* metrics_observer_ = nullptr;
webrtc::RtcEventLog* event_log_;
RTC_DISALLOW_COPY_AND_ASSIGN(TransportController);
};
} // namespace cricket
#endif // PC_TRANSPORTCONTROLLER_H_