deadbeef | f534659 | 2017-01-24 21:51:21 -0800 | [diff] [blame] | 1 | /* |
| 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 WEBRTC_P2P_BASE_FAKEDTLSTRANSPORT_H_ |
| 12 | #define WEBRTC_P2P_BASE_FAKEDTLSTRANSPORT_H_ |
| 13 | |
| 14 | #include <memory> |
| 15 | #include <string> |
| 16 | #include <vector> |
| 17 | |
deadbeef | f534659 | 2017-01-24 21:51:21 -0800 | [diff] [blame] | 18 | #include "webrtc/p2p/base/dtlstransportinternal.h" |
| 19 | #include "webrtc/p2p/base/fakeicetransport.h" |
Edward Lemur | c20978e | 2017-07-06 19:44:34 +0200 | [diff] [blame] | 20 | #include "webrtc/rtc_base/fakesslidentity.h" |
deadbeef | f534659 | 2017-01-24 21:51:21 -0800 | [diff] [blame] | 21 | |
| 22 | namespace cricket { |
| 23 | |
| 24 | // Fake DTLS transport which is implemented by wrapping a fake ICE transport. |
| 25 | // Doesn't interact directly with fake ICE transport for anything other than |
| 26 | // sending packets. |
| 27 | class FakeDtlsTransport : public DtlsTransportInternal { |
| 28 | public: |
| 29 | explicit FakeDtlsTransport(FakeIceTransport* ice_transport) |
| 30 | : ice_transport_(ice_transport), |
| 31 | transport_name_(ice_transport->transport_name()), |
| 32 | component_(ice_transport->component()), |
| 33 | dtls_fingerprint_("", nullptr, 0) { |
| 34 | ice_transport_->SignalReadPacket.connect( |
| 35 | this, &FakeDtlsTransport::OnIceTransportReadPacket); |
| 36 | } |
| 37 | |
| 38 | // If this constructor is called, a new fake ICE transport will be created, |
| 39 | // and this FakeDtlsTransport will take the ownership. |
| 40 | explicit FakeDtlsTransport(const std::string& name, int component) |
| 41 | : owned_ice_transport_(new FakeIceTransport(name, component)), |
| 42 | transport_name_(owned_ice_transport_->transport_name()), |
| 43 | component_(owned_ice_transport_->component()), |
| 44 | dtls_fingerprint_("", nullptr, 0) { |
| 45 | ice_transport_ = owned_ice_transport_.get(); |
| 46 | ice_transport_->SignalReadPacket.connect( |
| 47 | this, &FakeDtlsTransport::OnIceTransportReadPacket); |
| 48 | } |
| 49 | |
| 50 | ~FakeDtlsTransport() override { |
| 51 | if (dest_ && dest_->dest_ == this) { |
| 52 | dest_->dest_ = nullptr; |
| 53 | } |
| 54 | } |
| 55 | |
| 56 | // Get inner fake ICE transport. |
| 57 | FakeIceTransport* fake_ice_transport() { return ice_transport_; } |
| 58 | |
| 59 | // If async, will send packets by "Post"-ing to message queue instead of |
| 60 | // synchronously "Send"-ing. |
| 61 | void SetAsync(bool async) { ice_transport_->SetAsync(async); } |
| 62 | void SetAsyncDelay(int delay_ms) { ice_transport_->SetAsyncDelay(delay_ms); } |
| 63 | |
| 64 | // SetWritable, SetReceiving and SetDestination are the main methods that can |
| 65 | // be used for testing, to simulate connectivity or lack thereof. |
| 66 | void SetWritable(bool writable) { |
| 67 | ice_transport_->SetWritable(writable); |
| 68 | set_writable(writable); |
| 69 | } |
| 70 | void SetReceiving(bool receiving) { |
| 71 | ice_transport_->SetReceiving(receiving); |
| 72 | set_receiving(receiving); |
| 73 | } |
| 74 | |
| 75 | // Simulates the two DTLS transports connecting to each other. |
| 76 | // If |asymmetric| is true this method only affects this FakeDtlsTransport. |
| 77 | // If false, it affects |dest| as well. |
| 78 | void SetDestination(FakeDtlsTransport* dest, bool asymmetric = false) { |
| 79 | if (dest == dest_) { |
| 80 | return; |
| 81 | } |
| 82 | RTC_DCHECK(!dest || !dest_) |
| 83 | << "Changing fake destination from one to another is not supported."; |
| 84 | if (dest && !dest_) { |
| 85 | // This simulates the DTLS handshake. |
| 86 | dest_ = dest; |
| 87 | if (local_cert_ && dest_->local_cert_) { |
| 88 | do_dtls_ = true; |
deadbeef | f534659 | 2017-01-24 21:51:21 -0800 | [diff] [blame] | 89 | } |
| 90 | SetWritable(true); |
| 91 | if (!asymmetric) { |
| 92 | dest->SetDestination(this, true); |
| 93 | } |
jbauch | 5869f50 | 2017-06-29 12:31:36 -0700 | [diff] [blame] | 94 | dtls_state_ = DTLS_TRANSPORT_CONNECTED; |
deadbeef | f534659 | 2017-01-24 21:51:21 -0800 | [diff] [blame] | 95 | ice_transport_->SetDestination( |
| 96 | static_cast<FakeIceTransport*>(dest->ice_transport()), asymmetric); |
| 97 | } else { |
| 98 | // Simulates loss of connectivity, by asymmetrically forgetting dest_. |
| 99 | dest_ = nullptr; |
| 100 | SetWritable(false); |
| 101 | ice_transport_->SetDestination(nullptr, asymmetric); |
| 102 | } |
| 103 | } |
| 104 | |
| 105 | // Fake DtlsTransportInternal implementation. |
| 106 | DtlsTransportState dtls_state() const override { return dtls_state_; } |
| 107 | const std::string& transport_name() const override { return transport_name_; } |
| 108 | int component() const override { return component_; } |
| 109 | const rtc::SSLFingerprint& dtls_fingerprint() const { |
| 110 | return dtls_fingerprint_; |
| 111 | } |
| 112 | bool SetRemoteFingerprint(const std::string& alg, |
| 113 | const uint8_t* digest, |
| 114 | size_t digest_len) override { |
| 115 | dtls_fingerprint_ = rtc::SSLFingerprint(alg, digest, digest_len); |
| 116 | return true; |
| 117 | } |
| 118 | bool SetSslRole(rtc::SSLRole role) override { |
| 119 | ssl_role_ = role; |
| 120 | return true; |
| 121 | } |
| 122 | bool GetSslRole(rtc::SSLRole* role) const override { |
| 123 | *role = ssl_role_; |
| 124 | return true; |
| 125 | } |
jbauch | 5869f50 | 2017-06-29 12:31:36 -0700 | [diff] [blame] | 126 | const rtc::CryptoOptions& crypto_options() const override { |
| 127 | return crypto_options_; |
| 128 | } |
| 129 | void SetCryptoOptions(const rtc::CryptoOptions& crypto_options) { |
| 130 | crypto_options_ = crypto_options; |
| 131 | } |
deadbeef | f534659 | 2017-01-24 21:51:21 -0800 | [diff] [blame] | 132 | bool SetLocalCertificate( |
| 133 | const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) override { |
| 134 | local_cert_ = certificate; |
| 135 | return true; |
| 136 | } |
| 137 | void SetRemoteSSLCertificate(rtc::FakeSSLCertificate* cert) { |
| 138 | remote_cert_ = cert; |
| 139 | } |
| 140 | bool IsDtlsActive() const override { return do_dtls_; } |
deadbeef | f534659 | 2017-01-24 21:51:21 -0800 | [diff] [blame] | 141 | bool GetSrtpCryptoSuite(int* crypto_suite) override { |
deadbeef | 7914b8c | 2017-04-21 03:23:33 -0700 | [diff] [blame] | 142 | if (!do_dtls_) { |
| 143 | return false; |
deadbeef | f534659 | 2017-01-24 21:51:21 -0800 | [diff] [blame] | 144 | } |
jbauch | 5869f50 | 2017-06-29 12:31:36 -0700 | [diff] [blame] | 145 | *crypto_suite = crypto_suite_; |
deadbeef | 7914b8c | 2017-04-21 03:23:33 -0700 | [diff] [blame] | 146 | return true; |
deadbeef | f534659 | 2017-01-24 21:51:21 -0800 | [diff] [blame] | 147 | } |
jbauch | 5869f50 | 2017-06-29 12:31:36 -0700 | [diff] [blame] | 148 | void SetSrtpCryptoSuite(int crypto_suite) { |
| 149 | crypto_suite_ = crypto_suite; |
| 150 | } |
deadbeef | f534659 | 2017-01-24 21:51:21 -0800 | [diff] [blame] | 151 | bool GetSslCipherSuite(int* cipher_suite) override { return false; } |
| 152 | rtc::scoped_refptr<rtc::RTCCertificate> GetLocalCertificate() const override { |
| 153 | return local_cert_; |
| 154 | } |
| 155 | std::unique_ptr<rtc::SSLCertificate> GetRemoteSSLCertificate() |
| 156 | const override { |
| 157 | return remote_cert_ ? std::unique_ptr<rtc::SSLCertificate>( |
| 158 | remote_cert_->GetReference()) |
| 159 | : nullptr; |
| 160 | } |
| 161 | bool ExportKeyingMaterial(const std::string& label, |
| 162 | const uint8_t* context, |
| 163 | size_t context_len, |
| 164 | bool use_context, |
| 165 | uint8_t* result, |
| 166 | size_t result_len) override { |
deadbeef | 7914b8c | 2017-04-21 03:23:33 -0700 | [diff] [blame] | 167 | if (!do_dtls_) { |
| 168 | return false; |
deadbeef | f534659 | 2017-01-24 21:51:21 -0800 | [diff] [blame] | 169 | } |
deadbeef | 7914b8c | 2017-04-21 03:23:33 -0700 | [diff] [blame] | 170 | memset(result, 0xff, result_len); |
| 171 | return true; |
deadbeef | f534659 | 2017-01-24 21:51:21 -0800 | [diff] [blame] | 172 | } |
| 173 | void set_ssl_max_protocol_version(rtc::SSLProtocolVersion version) { |
| 174 | ssl_max_version_ = version; |
| 175 | } |
| 176 | rtc::SSLProtocolVersion ssl_max_protocol_version() const { |
| 177 | return ssl_max_version_; |
| 178 | } |
deadbeef | f534659 | 2017-01-24 21:51:21 -0800 | [diff] [blame] | 179 | |
| 180 | IceTransportInternal* ice_transport() override { return ice_transport_; } |
| 181 | |
deadbeef | 5bd5ca3 | 2017-02-10 11:31:50 -0800 | [diff] [blame] | 182 | // PacketTransportInternal implementation, which passes through to fake ICE |
deadbeef | f534659 | 2017-01-24 21:51:21 -0800 | [diff] [blame] | 183 | // transport for sending actual packets. |
| 184 | bool writable() const override { return writable_; } |
| 185 | bool receiving() const override { return receiving_; } |
| 186 | int SendPacket(const char* data, |
| 187 | size_t len, |
| 188 | const rtc::PacketOptions& options, |
| 189 | int flags) override { |
| 190 | // We expect only SRTP packets to be sent through this interface. |
| 191 | if (flags != PF_SRTP_BYPASS && flags != 0) { |
| 192 | return -1; |
| 193 | } |
| 194 | return ice_transport_->SendPacket(data, len, options, flags); |
| 195 | } |
| 196 | int SetOption(rtc::Socket::Option opt, int value) override { |
| 197 | return ice_transport_->SetOption(opt, value); |
| 198 | } |
| 199 | bool GetOption(rtc::Socket::Option opt, int* value) override { |
| 200 | return ice_transport_->GetOption(opt, value); |
| 201 | } |
| 202 | int GetError() override { return ice_transport_->GetError(); } |
| 203 | |
| 204 | private: |
deadbeef | 5bd5ca3 | 2017-02-10 11:31:50 -0800 | [diff] [blame] | 205 | void OnIceTransportReadPacket(PacketTransportInternal* ice_, |
deadbeef | f534659 | 2017-01-24 21:51:21 -0800 | [diff] [blame] | 206 | const char* data, |
| 207 | size_t len, |
| 208 | const rtc::PacketTime& time, |
| 209 | int flags) { |
| 210 | SignalReadPacket(this, data, len, time, flags); |
| 211 | } |
| 212 | |
deadbeef | f534659 | 2017-01-24 21:51:21 -0800 | [diff] [blame] | 213 | void set_receiving(bool receiving) { |
| 214 | if (receiving_ == receiving) { |
| 215 | return; |
| 216 | } |
| 217 | receiving_ = receiving; |
| 218 | SignalReceivingState(this); |
| 219 | } |
| 220 | |
| 221 | void set_writable(bool writable) { |
| 222 | if (writable_ == writable) { |
| 223 | return; |
| 224 | } |
| 225 | writable_ = writable; |
| 226 | if (writable_) { |
| 227 | SignalReadyToSend(this); |
| 228 | } |
| 229 | SignalWritableState(this); |
| 230 | } |
| 231 | |
| 232 | FakeIceTransport* ice_transport_; |
| 233 | std::unique_ptr<FakeIceTransport> owned_ice_transport_; |
| 234 | std::string transport_name_; |
| 235 | int component_; |
| 236 | FakeDtlsTransport* dest_ = nullptr; |
| 237 | rtc::scoped_refptr<rtc::RTCCertificate> local_cert_; |
| 238 | rtc::FakeSSLCertificate* remote_cert_ = nullptr; |
| 239 | bool do_dtls_ = false; |
deadbeef | f534659 | 2017-01-24 21:51:21 -0800 | [diff] [blame] | 240 | rtc::SSLProtocolVersion ssl_max_version_ = rtc::SSL_PROTOCOL_DTLS_12; |
| 241 | rtc::SSLFingerprint dtls_fingerprint_; |
| 242 | rtc::SSLRole ssl_role_ = rtc::SSL_CLIENT; |
jbauch | 5869f50 | 2017-06-29 12:31:36 -0700 | [diff] [blame] | 243 | int crypto_suite_ = rtc::SRTP_AES128_CM_SHA1_80; |
| 244 | rtc::CryptoOptions crypto_options_; |
deadbeef | f534659 | 2017-01-24 21:51:21 -0800 | [diff] [blame] | 245 | |
| 246 | DtlsTransportState dtls_state_ = DTLS_TRANSPORT_NEW; |
| 247 | |
| 248 | bool receiving_ = false; |
| 249 | bool writable_ = false; |
| 250 | }; |
| 251 | |
| 252 | } // namespace cricket |
| 253 | |
| 254 | #endif // WEBRTC_P2P_BASE_FAKEDTLSTRANSPORT_H_ |