summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/p2p/base/fake_dtls_transport.h
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/p2p/base/fake_dtls_transport.h')
-rw-r--r--third_party/libwebrtc/p2p/base/fake_dtls_transport.h319
1 files changed, 319 insertions, 0 deletions
diff --git a/third_party/libwebrtc/p2p/base/fake_dtls_transport.h b/third_party/libwebrtc/p2p/base/fake_dtls_transport.h
new file mode 100644
index 0000000000..5a3db4886b
--- /dev/null
+++ b/third_party/libwebrtc/p2p/base/fake_dtls_transport.h
@@ -0,0 +1,319 @@
+/*
+ * 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 P2P_BASE_FAKE_DTLS_TRANSPORT_H_
+#define P2P_BASE_FAKE_DTLS_TRANSPORT_H_
+
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/crypto/crypto_options.h"
+#include "api/dtls_transport_interface.h"
+#include "p2p/base/dtls_transport_internal.h"
+#include "p2p/base/fake_ice_transport.h"
+#include "rtc_base/fake_ssl_identity.h"
+#include "rtc_base/rtc_certificate.h"
+
+namespace cricket {
+
+// Fake DTLS transport which is implemented by wrapping a fake ICE transport.
+// Doesn't interact directly with fake ICE transport for anything other than
+// sending packets.
+class FakeDtlsTransport : public DtlsTransportInternal {
+ public:
+ explicit FakeDtlsTransport(FakeIceTransport* ice_transport)
+ : ice_transport_(ice_transport),
+ transport_name_(ice_transport->transport_name()),
+ component_(ice_transport->component()),
+ dtls_fingerprint_("", nullptr) {
+ RTC_DCHECK(ice_transport_);
+ ice_transport_->SignalReadPacket.connect(
+ this, &FakeDtlsTransport::OnIceTransportReadPacket);
+ ice_transport_->SignalNetworkRouteChanged.connect(
+ this, &FakeDtlsTransport::OnNetworkRouteChanged);
+ }
+
+ explicit FakeDtlsTransport(std::unique_ptr<FakeIceTransport> ice)
+ : owned_ice_transport_(std::move(ice)),
+ transport_name_(owned_ice_transport_->transport_name()),
+ component_(owned_ice_transport_->component()),
+ dtls_fingerprint_("", rtc::ArrayView<const uint8_t>()) {
+ ice_transport_ = owned_ice_transport_.get();
+ ice_transport_->SignalReadPacket.connect(
+ this, &FakeDtlsTransport::OnIceTransportReadPacket);
+ ice_transport_->SignalNetworkRouteChanged.connect(
+ this, &FakeDtlsTransport::OnNetworkRouteChanged);
+ }
+
+ // If this constructor is called, a new fake ICE transport will be created,
+ // and this FakeDtlsTransport will take the ownership.
+ FakeDtlsTransport(const std::string& name, int component)
+ : FakeDtlsTransport(std::make_unique<FakeIceTransport>(name, component)) {
+ }
+ FakeDtlsTransport(const std::string& name,
+ int component,
+ rtc::Thread* network_thread)
+ : FakeDtlsTransport(std::make_unique<FakeIceTransport>(name,
+ component,
+ network_thread)) {}
+
+ ~FakeDtlsTransport() override {
+ if (dest_ && dest_->dest_ == this) {
+ dest_->dest_ = nullptr;
+ }
+ }
+
+ // Get inner fake ICE transport.
+ FakeIceTransport* fake_ice_transport() { return ice_transport_; }
+
+ // If async, will send packets by "Post"-ing to message queue instead of
+ // synchronously "Send"-ing.
+ void SetAsync(bool async) { ice_transport_->SetAsync(async); }
+ void SetAsyncDelay(int delay_ms) { ice_transport_->SetAsyncDelay(delay_ms); }
+
+ // SetWritable, SetReceiving and SetDestination are the main methods that can
+ // be used for testing, to simulate connectivity or lack thereof.
+ void SetWritable(bool writable) {
+ ice_transport_->SetWritable(writable);
+ set_writable(writable);
+ }
+ void SetReceiving(bool receiving) {
+ ice_transport_->SetReceiving(receiving);
+ set_receiving(receiving);
+ }
+ void SetDtlsState(webrtc::DtlsTransportState state) {
+ dtls_state_ = state;
+ SendDtlsState(this, dtls_state_);
+ }
+
+ // Simulates the two DTLS transports connecting to each other.
+ // If `asymmetric` is true this method only affects this FakeDtlsTransport.
+ // If false, it affects `dest` as well.
+ void SetDestination(FakeDtlsTransport* dest, bool asymmetric = false) {
+ if (dest == dest_) {
+ return;
+ }
+ RTC_DCHECK(!dest || !dest_)
+ << "Changing fake destination from one to another is not supported.";
+ if (dest && !dest_) {
+ // This simulates the DTLS handshake.
+ dest_ = dest;
+ if (local_cert_ && dest_->local_cert_) {
+ do_dtls_ = true;
+ RTC_LOG(LS_INFO) << "FakeDtlsTransport is doing DTLS";
+ } else {
+ do_dtls_ = false;
+ RTC_LOG(LS_INFO) << "FakeDtlsTransport is not doing DTLS";
+ }
+ SetWritable(true);
+ if (!asymmetric) {
+ dest->SetDestination(this, true);
+ }
+ // If the `dtls_role_` is unset, set it to SSL_CLIENT by default.
+ if (!dtls_role_) {
+ dtls_role_ = std::move(rtc::SSL_CLIENT);
+ }
+ SetDtlsState(webrtc::DtlsTransportState::kConnected);
+ ice_transport_->SetDestination(
+ static_cast<FakeIceTransport*>(dest->ice_transport()), asymmetric);
+ } else {
+ // Simulates loss of connectivity, by asymmetrically forgetting dest_.
+ dest_ = nullptr;
+ SetWritable(false);
+ ice_transport_->SetDestination(nullptr, asymmetric);
+ }
+ }
+
+ // Fake DtlsTransportInternal implementation.
+ webrtc::DtlsTransportState dtls_state() const override { return dtls_state_; }
+ const std::string& transport_name() const override { return transport_name_; }
+ int component() const override { return component_; }
+ const rtc::SSLFingerprint& dtls_fingerprint() const {
+ return dtls_fingerprint_;
+ }
+ webrtc::RTCError SetRemoteParameters(absl::string_view alg,
+ const uint8_t* digest,
+ size_t digest_len,
+ absl::optional<rtc::SSLRole> role) {
+ if (role) {
+ SetDtlsRole(*role);
+ }
+ SetRemoteFingerprint(alg, digest, digest_len);
+ return webrtc::RTCError::OK();
+ }
+ bool SetRemoteFingerprint(absl::string_view alg,
+ const uint8_t* digest,
+ size_t digest_len) {
+ dtls_fingerprint_ =
+ rtc::SSLFingerprint(alg, rtc::MakeArrayView(digest, digest_len));
+ return true;
+ }
+ bool SetDtlsRole(rtc::SSLRole role) override {
+ dtls_role_ = std::move(role);
+ return true;
+ }
+ bool GetDtlsRole(rtc::SSLRole* role) const override {
+ if (!dtls_role_) {
+ return false;
+ }
+ *role = *dtls_role_;
+ return true;
+ }
+ bool SetLocalCertificate(
+ const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) override {
+ do_dtls_ = true;
+ local_cert_ = certificate;
+ return true;
+ }
+ void SetRemoteSSLCertificate(rtc::FakeSSLCertificate* cert) {
+ remote_cert_ = cert;
+ }
+ bool IsDtlsActive() const override { return do_dtls_; }
+ bool GetSslVersionBytes(int* version) const override {
+ if (!do_dtls_) {
+ return false;
+ }
+ *version = 0x0102;
+ return true;
+ }
+ bool GetSrtpCryptoSuite(int* crypto_suite) override {
+ if (!do_dtls_) {
+ return false;
+ }
+ *crypto_suite = crypto_suite_;
+ return true;
+ }
+ void SetSrtpCryptoSuite(int crypto_suite) { crypto_suite_ = crypto_suite; }
+
+ bool GetSslCipherSuite(int* cipher_suite) override {
+ if (ssl_cipher_suite_) {
+ *cipher_suite = *ssl_cipher_suite_;
+ return true;
+ }
+ return false;
+ }
+ void SetSslCipherSuite(absl::optional<int> cipher_suite) {
+ ssl_cipher_suite_ = cipher_suite;
+ }
+ uint16_t GetSslPeerSignatureAlgorithm() const override { return 0; }
+ rtc::scoped_refptr<rtc::RTCCertificate> GetLocalCertificate() const override {
+ return local_cert_;
+ }
+ std::unique_ptr<rtc::SSLCertChain> GetRemoteSSLCertChain() const override {
+ if (!remote_cert_) {
+ return nullptr;
+ }
+ return std::make_unique<rtc::SSLCertChain>(remote_cert_->Clone());
+ }
+ bool ExportKeyingMaterial(absl::string_view label,
+ const uint8_t* context,
+ size_t context_len,
+ bool use_context,
+ uint8_t* result,
+ size_t result_len) override {
+ if (!do_dtls_) {
+ return false;
+ }
+ memset(result, 0xff, result_len);
+ return true;
+ }
+ void set_ssl_max_protocol_version(rtc::SSLProtocolVersion version) {
+ ssl_max_version_ = version;
+ }
+ rtc::SSLProtocolVersion ssl_max_protocol_version() const {
+ return ssl_max_version_;
+ }
+
+ IceTransportInternal* ice_transport() override { return ice_transport_; }
+
+ // PacketTransportInternal implementation, which passes through to fake ICE
+ // transport for sending actual packets.
+ bool writable() const override { return writable_; }
+ bool receiving() const override { return receiving_; }
+ int SendPacket(const char* data,
+ size_t len,
+ const rtc::PacketOptions& options,
+ int flags) override {
+ // We expect only SRTP packets to be sent through this interface.
+ if (flags != PF_SRTP_BYPASS && flags != 0) {
+ return -1;
+ }
+ return ice_transport_->SendPacket(data, len, options, flags);
+ }
+ int SetOption(rtc::Socket::Option opt, int value) override {
+ return ice_transport_->SetOption(opt, value);
+ }
+ bool GetOption(rtc::Socket::Option opt, int* value) override {
+ return ice_transport_->GetOption(opt, value);
+ }
+ int GetError() override { return ice_transport_->GetError(); }
+
+ absl::optional<rtc::NetworkRoute> network_route() const override {
+ return ice_transport_->network_route();
+ }
+
+ private:
+ void OnIceTransportReadPacket(PacketTransportInternal* ice_,
+ const char* data,
+ size_t len,
+ const int64_t& packet_time_us,
+ int flags) {
+ SignalReadPacket(this, data, len, packet_time_us, flags);
+ }
+
+ void set_receiving(bool receiving) {
+ if (receiving_ == receiving) {
+ return;
+ }
+ receiving_ = receiving;
+ SignalReceivingState(this);
+ }
+
+ void set_writable(bool writable) {
+ if (writable_ == writable) {
+ return;
+ }
+ writable_ = writable;
+ if (writable_) {
+ SignalReadyToSend(this);
+ }
+ SignalWritableState(this);
+ }
+
+ void OnNetworkRouteChanged(absl::optional<rtc::NetworkRoute> network_route) {
+ SignalNetworkRouteChanged(network_route);
+ }
+
+ FakeIceTransport* ice_transport_;
+ std::unique_ptr<FakeIceTransport> owned_ice_transport_;
+ std::string transport_name_;
+ int component_;
+ FakeDtlsTransport* dest_ = nullptr;
+ rtc::scoped_refptr<rtc::RTCCertificate> local_cert_;
+ rtc::FakeSSLCertificate* remote_cert_ = nullptr;
+ bool do_dtls_ = false;
+ rtc::SSLProtocolVersion ssl_max_version_ = rtc::SSL_PROTOCOL_DTLS_12;
+ rtc::SSLFingerprint dtls_fingerprint_;
+ absl::optional<rtc::SSLRole> dtls_role_;
+ int crypto_suite_ = rtc::kSrtpAes128CmSha1_80;
+ absl::optional<int> ssl_cipher_suite_;
+
+ webrtc::DtlsTransportState dtls_state_ = webrtc::DtlsTransportState::kNew;
+
+ bool receiving_ = false;
+ bool writable_ = false;
+};
+
+} // namespace cricket
+
+#endif // P2P_BASE_FAKE_DTLS_TRANSPORT_H_