2015-09-23 11:50:27 -07:00
|
|
|
/*
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
|
|
|
|
|
2017-09-29 10:51:43 -07:00
|
|
|
#ifndef PC_TRANSPORTCONTROLLER_H_
|
|
|
|
|
#define PC_TRANSPORTCONTROLLER_H_
|
2015-09-23 11:50:27 -07:00
|
|
|
|
|
|
|
|
#include <map>
|
2016-04-26 03:13:22 -07:00
|
|
|
#include <memory>
|
2015-09-23 11:50:27 -07:00
|
|
|
#include <string>
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
2017-10-05 14:53:33 +02:00
|
|
|
#include "api/candidate.h"
|
2017-09-15 06:47:31 +02:00
|
|
|
#include "p2p/base/dtlstransport.h"
|
|
|
|
|
#include "p2p/base/jseptransport.h"
|
|
|
|
|
#include "p2p/base/p2ptransportchannel.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"
|
2015-09-23 11:50:27 -07:00
|
|
|
|
|
|
|
|
namespace rtc {
|
|
|
|
|
class Thread;
|
2017-02-10 11:31:50 -08:00
|
|
|
class PacketTransportInternal;
|
2017-09-29 10:51:43 -07:00
|
|
|
} // namespace rtc
|
|
|
|
|
|
2016-10-05 11:47:22 -07:00
|
|
|
namespace webrtc {
|
|
|
|
|
class MetricsObserverInterface;
|
2017-09-29 10:51:43 -07:00
|
|
|
} // namespace webrtc
|
2015-09-23 11:50:27 -07:00
|
|
|
|
|
|
|
|
namespace cricket {
|
|
|
|
|
|
|
|
|
|
class TransportController : public sigslot::has_slots<>,
|
|
|
|
|
public rtc::MessageHandler {
|
|
|
|
|
public:
|
2016-08-26 20:59:24 -07:00
|
|
|
// 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.
|
Negotiate the same SRTP crypto suites for every DTLS association formed.
Before this CL, we would negotiate:
- No crypto suites for data m= sections.
- A full set for audio m= sections.
- The full set, minus SRTP_AES128_CM_SHA1_32 for video m= sections.
However, this doesn't make sense with BUNDLE, since any DTLS
association could end up being used for any type of media. If
video is "bundled on" the audio transport (which is typical), it
will actually end up using SRTP_AES128_CM_SHA1_32.
So, this CL moves the responsibility of deciding SRTP crypto suites out
of BaseChannel and into DtlsTransport. The only two possibilities are
now "normal set" or "normal set + GCM", if enabled by the PC factory
options.
This fixes an issue (see linked bug) that was occurring when audio/video
were "bundled onto" the data transport. Since the data transport
wasn't negotiating any SRTP crypto suites, none were available to use
for audio/video, so the application would get black video/no audio.
This CL doesn't affect the SDES SRTP crypto suite negotiation;
it only affects the negotiation in the DLTS handshake, through
the use_srtp extension.
BUG=chromium:711243
Review-Url: https://codereview.webrtc.org/2815513012
Cr-Commit-Position: refs/heads/master@{#17810}
2017-04-21 03:23:33 -07:00
|
|
|
//
|
|
|
|
|
// |crypto_options| is used to determine if created DTLS transports negotiate
|
|
|
|
|
// GCM crypto suites or not.
|
2016-08-26 20:59:24 -07:00
|
|
|
TransportController(rtc::Thread* signaling_thread,
|
|
|
|
|
rtc::Thread* network_thread,
|
|
|
|
|
PortAllocator* port_allocator,
|
Negotiate the same SRTP crypto suites for every DTLS association formed.
Before this CL, we would negotiate:
- No crypto suites for data m= sections.
- A full set for audio m= sections.
- The full set, minus SRTP_AES128_CM_SHA1_32 for video m= sections.
However, this doesn't make sense with BUNDLE, since any DTLS
association could end up being used for any type of media. If
video is "bundled on" the audio transport (which is typical), it
will actually end up using SRTP_AES128_CM_SHA1_32.
So, this CL moves the responsibility of deciding SRTP crypto suites out
of BaseChannel and into DtlsTransport. The only two possibilities are
now "normal set" or "normal set + GCM", if enabled by the PC factory
options.
This fixes an issue (see linked bug) that was occurring when audio/video
were "bundled onto" the data transport. Since the data transport
wasn't negotiating any SRTP crypto suites, none were available to use
for audio/video, so the application would get black video/no audio.
This CL doesn't affect the SDES SRTP crypto suite negotiation;
it only affects the negotiation in the DLTS handshake, through
the use_srtp extension.
BUG=chromium:711243
Review-Url: https://codereview.webrtc.org/2815513012
Cr-Commit-Position: refs/heads/master@{#17810}
2017-04-21 03:23:33 -07:00
|
|
|
bool redetermine_role_on_ice_restart,
|
|
|
|
|
const rtc::CryptoOptions& crypto_options);
|
2015-09-23 11:50:27 -07:00
|
|
|
|
|
|
|
|
virtual ~TransportController();
|
|
|
|
|
|
|
|
|
|
rtc::Thread* signaling_thread() const { return signaling_thread_; }
|
2016-05-12 09:20:31 +02:00
|
|
|
rtc::Thread* network_thread() const { return network_thread_; }
|
2015-09-23 11:50:27 -07:00
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
2015-09-28 07:57:34 -07:00
|
|
|
void SetIceConfig(const IceConfig& config);
|
2015-09-23 11:50:27 -07:00
|
|
|
void SetIceRole(IceRole ice_role);
|
|
|
|
|
|
2016-12-10 13:15:33 -08:00
|
|
|
// 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;
|
|
|
|
|
|
2016-12-06 16:22:06 -08:00
|
|
|
bool GetSslRole(const std::string& transport_name, rtc::SSLRole* role) const;
|
2015-09-23 11:50:27 -07:00
|
|
|
|
|
|
|
|
// 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,
|
2016-12-06 16:22:06 -08:00
|
|
|
rtc::scoped_refptr<rtc::RTCCertificate>* certificate) const;
|
|
|
|
|
// Caller owns returned certificate. This method mainly exists for stats
|
|
|
|
|
// reporting.
|
2016-04-26 03:13:22 -07:00
|
|
|
std::unique_ptr<rtc::SSLCertificate> GetRemoteSSLCertificate(
|
2016-12-06 16:22:06 -08:00
|
|
|
const std::string& transport_name) const;
|
2015-09-23 11:50:27 -07:00
|
|
|
bool SetLocalTransportDescription(const std::string& transport_name,
|
|
|
|
|
const TransportDescription& tdesc,
|
|
|
|
|
ContentAction action,
|
|
|
|
|
std::string* err);
|
|
|
|
|
bool SetRemoteTransportDescription(const std::string& transport_name,
|
|
|
|
|
const TransportDescription& tdesc,
|
|
|
|
|
ContentAction action,
|
|
|
|
|
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);
|
2016-03-14 11:59:18 -07:00
|
|
|
bool RemoveRemoteCandidates(const Candidates& candidates, std::string* err);
|
2016-12-06 16:22:06 -08:00
|
|
|
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.
|
2015-09-23 11:50:27 -07:00
|
|
|
bool GetStats(const std::string& transport_name, TransportStats* stats);
|
2016-12-06 16:22:06 -08:00
|
|
|
void SetMetricsObserver(webrtc::MetricsObserverInterface* metrics_observer);
|
2015-09-23 11:50:27 -07:00
|
|
|
|
2015-09-30 10:32:59 -07:00
|
|
|
// Creates a channel if it doesn't exist. Otherwise, increments a reference
|
|
|
|
|
// count and returns an existing channel.
|
2017-01-19 16:54:25 -08:00
|
|
|
DtlsTransportInternal* CreateDtlsTransport(const std::string& transport_name,
|
|
|
|
|
int component);
|
|
|
|
|
virtual DtlsTransportInternal* CreateDtlsTransport_n(
|
2015-09-23 11:50:27 -07:00
|
|
|
const std::string& transport_name,
|
|
|
|
|
int component);
|
2015-09-30 10:32:59 -07:00
|
|
|
|
|
|
|
|
// Decrements a channel's reference count, and destroys the channel if
|
|
|
|
|
// nothing is referencing it.
|
2017-01-19 16:54:25 -08:00
|
|
|
virtual void DestroyDtlsTransport(const std::string& transport_name,
|
|
|
|
|
int component);
|
|
|
|
|
virtual void DestroyDtlsTransport_n(const std::string& transport_name,
|
|
|
|
|
int component);
|
2015-09-23 11:50:27 -07:00
|
|
|
|
2016-12-06 16:22:06 -08:00
|
|
|
// 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();
|
2017-01-19 16:54:25 -08:00
|
|
|
std::vector<DtlsTransportInternal*> channels_for_testing();
|
|
|
|
|
DtlsTransportInternal* get_channel_for_testing(
|
2016-12-06 16:22:06 -08:00
|
|
|
const std::string& transport_name,
|
|
|
|
|
int component);
|
|
|
|
|
|
2015-09-23 11:50:27 -07:00
|
|
|
// 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;
|
|
|
|
|
|
2016-03-14 11:59:18 -07:00
|
|
|
sigslot::signal1<const Candidates&> SignalCandidatesRemoved;
|
|
|
|
|
|
2016-08-26 11:25:05 -07:00
|
|
|
sigslot::signal1<rtc::SSLHandshakeError> SignalDtlsHandshakeError;
|
|
|
|
|
|
2015-09-23 11:50:27 -07:00
|
|
|
protected:
|
2016-12-06 16:22:06 -08:00
|
|
|
// TODO(deadbeef): Get rid of these virtual methods. Used by
|
|
|
|
|
// FakeTransportController currently, but FakeTransportController shouldn't
|
|
|
|
|
// even be functioning by subclassing TransportController.
|
2017-01-12 15:58:31 -08:00
|
|
|
virtual IceTransportInternal* CreateIceTransportChannel_n(
|
2016-12-06 16:22:06 -08:00
|
|
|
const std::string& transport_name,
|
|
|
|
|
int component);
|
2017-01-19 16:54:25 -08:00
|
|
|
virtual DtlsTransportInternal* CreateDtlsTransportChannel_n(
|
2016-12-06 16:22:06 -08:00
|
|
|
const std::string& transport_name,
|
|
|
|
|
int component,
|
2017-01-12 15:58:31 -08:00
|
|
|
IceTransportInternal* ice);
|
2015-09-23 11:50:27 -07:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
void OnMessage(rtc::Message* pmsg) override;
|
|
|
|
|
|
2016-12-13 16:38:36 -08:00
|
|
|
class ChannelPair;
|
|
|
|
|
typedef rtc::RefCountedObject<ChannelPair> RefCountedChannel;
|
2015-09-30 10:32:59 -07:00
|
|
|
|
2016-12-06 16:22:06 -08:00
|
|
|
// Helper functions to get a channel or transport, or iterator to it (in case
|
|
|
|
|
// it needs to be erased).
|
2016-12-13 16:38:36 -08:00
|
|
|
std::vector<RefCountedChannel*>::iterator GetChannelIterator_n(
|
2015-09-30 10:32:59 -07:00
|
|
|
const std::string& transport_name,
|
|
|
|
|
int component);
|
2016-12-13 16:38:36 -08:00
|
|
|
std::vector<RefCountedChannel*>::const_iterator GetChannelIterator_n(
|
2016-12-06 16:22:06 -08:00
|
|
|
const std::string& transport_name,
|
|
|
|
|
int component) const;
|
2016-12-10 13:15:33 -08:00
|
|
|
const JsepTransport* GetJsepTransport(
|
2016-12-06 16:22:06 -08:00
|
|
|
const std::string& transport_name) const;
|
2016-12-10 13:15:33 -08:00
|
|
|
JsepTransport* GetJsepTransport(const std::string& transport_name);
|
2016-12-06 16:22:06 -08:00
|
|
|
const RefCountedChannel* GetChannel_n(const std::string& transport_name,
|
|
|
|
|
int component) const;
|
|
|
|
|
RefCountedChannel* GetChannel_n(const std::string& transport_name,
|
|
|
|
|
int component);
|
|
|
|
|
|
2016-12-10 13:15:33 -08:00
|
|
|
JsepTransport* GetOrCreateJsepTransport(const std::string& transport_name);
|
2016-12-06 16:22:06 -08:00
|
|
|
void DestroyAllChannels_n();
|
2015-09-23 11:50:27 -07:00
|
|
|
|
2016-05-12 09:20:31 +02:00
|
|
|
bool SetSslMaxProtocolVersion_n(rtc::SSLProtocolVersion version);
|
|
|
|
|
void SetIceConfig_n(const IceConfig& config);
|
|
|
|
|
void SetIceRole_n(IceRole ice_role);
|
2016-12-06 16:22:06 -08:00
|
|
|
bool GetSslRole_n(const std::string& transport_name,
|
|
|
|
|
rtc::SSLRole* role) const;
|
2016-05-12 09:20:31 +02:00
|
|
|
bool SetLocalCertificate_n(
|
2015-09-23 11:50:27 -07:00
|
|
|
const rtc::scoped_refptr<rtc::RTCCertificate>& certificate);
|
2016-05-12 09:20:31 +02:00
|
|
|
bool GetLocalCertificate_n(
|
2015-09-23 11:50:27 -07:00
|
|
|
const std::string& transport_name,
|
2016-12-06 16:22:06 -08:00
|
|
|
rtc::scoped_refptr<rtc::RTCCertificate>* certificate) const;
|
2016-05-12 09:20:31 +02:00
|
|
|
std::unique_ptr<rtc::SSLCertificate> GetRemoteSSLCertificate_n(
|
2016-12-06 16:22:06 -08:00
|
|
|
const std::string& transport_name) const;
|
2016-05-12 09:20:31 +02:00
|
|
|
bool SetLocalTransportDescription_n(const std::string& transport_name,
|
2015-09-23 11:50:27 -07:00
|
|
|
const TransportDescription& tdesc,
|
|
|
|
|
ContentAction action,
|
|
|
|
|
std::string* err);
|
2016-05-12 09:20:31 +02:00
|
|
|
bool SetRemoteTransportDescription_n(const std::string& transport_name,
|
2015-09-23 11:50:27 -07:00
|
|
|
const TransportDescription& tdesc,
|
|
|
|
|
ContentAction action,
|
|
|
|
|
std::string* err);
|
2016-05-12 09:20:31 +02:00
|
|
|
void MaybeStartGathering_n();
|
|
|
|
|
bool AddRemoteCandidates_n(const std::string& transport_name,
|
2015-09-23 11:50:27 -07:00
|
|
|
const Candidates& candidates,
|
|
|
|
|
std::string* err);
|
2016-05-12 09:20:31 +02:00
|
|
|
bool RemoveRemoteCandidates_n(const Candidates& candidates, std::string* err);
|
2016-12-06 16:22:06 -08:00
|
|
|
bool ReadyForRemoteCandidates_n(const std::string& transport_name) const;
|
2016-05-12 09:20:31 +02:00
|
|
|
bool GetStats_n(const std::string& transport_name, TransportStats* stats);
|
2016-12-06 16:22:06 -08:00
|
|
|
void SetMetricsObserver_n(webrtc::MetricsObserverInterface* metrics_observer);
|
2015-09-23 11:50:27 -07:00
|
|
|
|
|
|
|
|
// Handlers for signals from Transport.
|
2017-02-10 11:31:50 -08:00
|
|
|
void OnChannelWritableState_n(rtc::PacketTransportInternal* transport);
|
|
|
|
|
void OnChannelReceivingState_n(rtc::PacketTransportInternal* transport);
|
2017-01-19 16:54:25 -08:00
|
|
|
void OnChannelGatheringState_n(IceTransportInternal* channel);
|
|
|
|
|
void OnChannelCandidateGathered_n(IceTransportInternal* channel,
|
2015-09-30 10:32:59 -07:00
|
|
|
const Candidate& candidate);
|
2016-03-14 11:59:18 -07:00
|
|
|
void OnChannelCandidatesRemoved(const Candidates& candidates);
|
2017-01-19 16:54:25 -08:00
|
|
|
void OnChannelCandidatesRemoved_n(IceTransportInternal* channel,
|
2016-03-14 11:59:18 -07:00
|
|
|
const Candidates& candidates);
|
2017-01-19 16:54:25 -08:00
|
|
|
void OnChannelRoleConflict_n(IceTransportInternal* channel);
|
|
|
|
|
void OnChannelStateChanged_n(IceTransportInternal* channel);
|
2015-09-23 11:50:27 -07:00
|
|
|
|
2016-05-12 09:20:31 +02:00
|
|
|
void UpdateAggregateStates_n();
|
2015-09-23 11:50:27 -07:00
|
|
|
|
2016-08-26 11:25:05 -07:00
|
|
|
void OnDtlsHandshakeError(rtc::SSLHandshakeError error);
|
|
|
|
|
|
2015-09-23 11:50:27 -07:00
|
|
|
rtc::Thread* const signaling_thread_ = nullptr;
|
2016-05-12 09:20:31 +02:00
|
|
|
rtc::Thread* const network_thread_ = nullptr;
|
2016-12-06 16:22:06 -08:00
|
|
|
PortAllocator* const port_allocator_ = nullptr;
|
2015-09-23 11:50:27 -07:00
|
|
|
|
2016-12-06 16:22:06 -08:00
|
|
|
std::map<std::string, std::unique_ptr<JsepTransport>> transports_;
|
2016-12-13 16:38:36 -08:00
|
|
|
std::vector<RefCountedChannel*> channels_;
|
2015-09-30 10:32:59 -07:00
|
|
|
|
|
|
|
|
// Aggregate state for TransportChannelImpls.
|
2015-09-23 11:50:27 -07:00
|
|
|
IceConnectionState connection_state_ = kIceConnectionConnecting;
|
|
|
|
|
bool receiving_ = false;
|
|
|
|
|
IceGatheringState gathering_state_ = kIceGatheringNew;
|
|
|
|
|
|
2015-09-28 07:57:34 -07:00
|
|
|
IceConfig ice_config_;
|
2015-09-23 11:50:27 -07:00
|
|
|
IceRole ice_role_ = ICEROLE_CONTROLLING;
|
2016-08-26 20:59:24 -07:00
|
|
|
bool redetermine_role_on_ice_restart_;
|
Use suffixed {uint,int}{8,16,32,64}_t types.
Removes the use of uint8, etc. in favor of uint8_t.
BUG=webrtc:5024
R=henrik.lundin@webrtc.org, henrikg@webrtc.org, perkj@webrtc.org, solenberg@webrtc.org, stefan@webrtc.org, tina.legrand@webrtc.org
Review URL: https://codereview.webrtc.org/1362503003 .
Cr-Commit-Position: refs/heads/master@{#10196}
2015-10-07 12:23:21 +02:00
|
|
|
uint64_t ice_tiebreaker_ = rtc::CreateRandomId64();
|
Negotiate the same SRTP crypto suites for every DTLS association formed.
Before this CL, we would negotiate:
- No crypto suites for data m= sections.
- A full set for audio m= sections.
- The full set, minus SRTP_AES128_CM_SHA1_32 for video m= sections.
However, this doesn't make sense with BUNDLE, since any DTLS
association could end up being used for any type of media. If
video is "bundled on" the audio transport (which is typical), it
will actually end up using SRTP_AES128_CM_SHA1_32.
So, this CL moves the responsibility of deciding SRTP crypto suites out
of BaseChannel and into DtlsTransport. The only two possibilities are
now "normal set" or "normal set + GCM", if enabled by the PC factory
options.
This fixes an issue (see linked bug) that was occurring when audio/video
were "bundled onto" the data transport. Since the data transport
wasn't negotiating any SRTP crypto suites, none were available to use
for audio/video, so the application would get black video/no audio.
This CL doesn't affect the SDES SRTP crypto suite negotiation;
it only affects the negotiation in the DLTS handshake, through
the use_srtp extension.
BUG=chromium:711243
Review-Url: https://codereview.webrtc.org/2815513012
Cr-Commit-Position: refs/heads/master@{#17810}
2017-04-21 03:23:33 -07:00
|
|
|
rtc::CryptoOptions crypto_options_;
|
2016-12-06 16:22:06 -08:00
|
|
|
rtc::SSLProtocolVersion ssl_max_version_ = rtc::SSL_PROTOCOL_DTLS_12;
|
2015-09-23 11:50:27 -07:00
|
|
|
rtc::scoped_refptr<rtc::RTCCertificate> certificate_;
|
2016-03-14 11:59:18 -07:00
|
|
|
rtc::AsyncInvoker invoker_;
|
2016-10-05 11:47:22 -07:00
|
|
|
|
|
|
|
|
webrtc::MetricsObserverInterface* metrics_observer_ = nullptr;
|
2016-12-13 16:38:36 -08:00
|
|
|
|
|
|
|
|
RTC_DISALLOW_COPY_AND_ASSIGN(TransportController);
|
2015-09-23 11:50:27 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
} // namespace cricket
|
|
|
|
|
|
2017-09-29 10:51:43 -07:00
|
|
|
#endif // PC_TRANSPORTCONTROLLER_H_
|