blob: d5fbec4e39c59abed0353618882584364a2e1b2e [file] [log] [blame]
deadbeefcbecd352015-09-23 11:50:27 -07001/*
2 * Copyright 2009 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_FAKETRANSPORTCONTROLLER_H_
12#define WEBRTC_P2P_BASE_FAKETRANSPORTCONTROLLER_H_
13
14#include <map>
15#include <string>
16#include <vector>
17
18#include "webrtc/p2p/base/transport.h"
19#include "webrtc/p2p/base/transportchannel.h"
20#include "webrtc/p2p/base/transportcontroller.h"
21#include "webrtc/p2p/base/transportchannelimpl.h"
22#include "webrtc/base/bind.h"
23#include "webrtc/base/buffer.h"
24#include "webrtc/base/fakesslidentity.h"
25#include "webrtc/base/messagequeue.h"
26#include "webrtc/base/sigslot.h"
27#include "webrtc/base/sslfingerprint.h"
28#include "webrtc/base/thread.h"
29
30namespace cricket {
31
32class FakeTransport;
33
stefanc1aeaf02015-10-15 07:26:07 -070034namespace {
deadbeefcbecd352015-09-23 11:50:27 -070035struct PacketMessageData : public rtc::MessageData {
36 PacketMessageData(const char* data, size_t len) : packet(data, len) {}
37 rtc::Buffer packet;
38};
stefanc1aeaf02015-10-15 07:26:07 -070039} // namespace
deadbeefcbecd352015-09-23 11:50:27 -070040
41// Fake transport channel class, which can be passed to anything that needs a
42// transport channel. Can be informed of another FakeTransportChannel via
43// SetDestination.
44// TODO(hbos): Move implementation to .cc file, this and other classes in file.
45class FakeTransportChannel : public TransportChannelImpl,
46 public rtc::MessageHandler {
47 public:
mikescarlettb9dd7c52016-02-19 20:43:45 -080048 explicit FakeTransportChannel(const std::string& name, int component)
deadbeefcbecd352015-09-23 11:50:27 -070049 : TransportChannelImpl(name, component),
deadbeefcbecd352015-09-23 11:50:27 -070050 dtls_fingerprint_("", nullptr, 0) {}
51 ~FakeTransportChannel() { Reset(); }
52
Peter Boström0c4e06b2015-10-07 12:23:21 +020053 uint64_t IceTiebreaker() const { return tiebreaker_; }
deadbeefcbecd352015-09-23 11:50:27 -070054 IceMode remote_ice_mode() const { return remote_ice_mode_; }
55 const std::string& ice_ufrag() const { return ice_ufrag_; }
56 const std::string& ice_pwd() const { return ice_pwd_; }
57 const std::string& remote_ice_ufrag() const { return remote_ice_ufrag_; }
58 const std::string& remote_ice_pwd() const { return remote_ice_pwd_; }
59 const rtc::SSLFingerprint& dtls_fingerprint() const {
60 return dtls_fingerprint_;
61 }
62
63 // If async, will send packets by "Post"-ing to message queue instead of
64 // synchronously "Send"-ing.
65 void SetAsync(bool async) { async_ = async; }
66
deadbeefcbecd352015-09-23 11:50:27 -070067 TransportChannelState GetState() const override {
68 if (connection_count_ == 0) {
69 return had_connection_ ? TransportChannelState::STATE_FAILED
70 : TransportChannelState::STATE_INIT;
71 }
72
73 if (connection_count_ == 1) {
74 return TransportChannelState::STATE_COMPLETED;
75 }
76
77 return TransportChannelState::STATE_CONNECTING;
78 }
79
80 void SetIceRole(IceRole role) override { role_ = role; }
81 IceRole GetIceRole() const override { return role_; }
Peter Boström0c4e06b2015-10-07 12:23:21 +020082 void SetIceTiebreaker(uint64_t tiebreaker) override {
deadbeefcbecd352015-09-23 11:50:27 -070083 tiebreaker_ = tiebreaker;
84 }
85 void SetIceCredentials(const std::string& ice_ufrag,
86 const std::string& ice_pwd) override {
87 ice_ufrag_ = ice_ufrag;
88 ice_pwd_ = ice_pwd;
89 }
90 void SetRemoteIceCredentials(const std::string& ice_ufrag,
91 const std::string& ice_pwd) override {
92 remote_ice_ufrag_ = ice_ufrag;
93 remote_ice_pwd_ = ice_pwd;
94 }
95
96 void SetRemoteIceMode(IceMode mode) override { remote_ice_mode_ = mode; }
97 bool SetRemoteFingerprint(const std::string& alg,
Peter Boström0c4e06b2015-10-07 12:23:21 +020098 const uint8_t* digest,
deadbeefcbecd352015-09-23 11:50:27 -070099 size_t digest_len) override {
100 dtls_fingerprint_ = rtc::SSLFingerprint(alg, digest, digest_len);
101 return true;
102 }
103 bool SetSslRole(rtc::SSLRole role) override {
104 ssl_role_ = role;
105 return true;
106 }
107 bool GetSslRole(rtc::SSLRole* role) const override {
108 *role = ssl_role_;
109 return true;
110 }
111
112 void Connect() override {
113 if (state_ == STATE_INIT) {
114 state_ = STATE_CONNECTING;
115 }
116 }
117
118 void MaybeStartGathering() override {
119 if (gathering_state_ == kIceGatheringNew) {
120 gathering_state_ = kIceGatheringGathering;
121 SignalGatheringState(this);
122 }
123 }
124
125 IceGatheringState gathering_state() const override {
126 return gathering_state_;
127 }
128
129 void Reset() {
130 if (state_ != STATE_INIT) {
131 state_ = STATE_INIT;
132 if (dest_) {
133 dest_->state_ = STATE_INIT;
134 dest_->dest_ = nullptr;
135 dest_ = nullptr;
136 }
137 }
138 }
139
140 void SetWritable(bool writable) { set_writable(writable); }
141
142 void SetDestination(FakeTransportChannel* dest) {
143 if (state_ == STATE_CONNECTING && dest) {
144 // This simulates the delivery of candidates.
145 dest_ = dest;
146 dest_->dest_ = this;
147 if (local_cert_ && dest_->local_cert_) {
148 do_dtls_ = true;
149 dest_->do_dtls_ = true;
150 NegotiateSrtpCiphers();
151 }
152 state_ = STATE_CONNECTED;
153 dest_->state_ = STATE_CONNECTED;
154 set_writable(true);
155 dest_->set_writable(true);
156 } else if (state_ == STATE_CONNECTED && !dest) {
157 // Simulates loss of connectivity, by asymmetrically forgetting dest_.
158 dest_ = nullptr;
159 state_ = STATE_CONNECTING;
160 set_writable(false);
161 }
162 }
163
164 void SetConnectionCount(size_t connection_count) {
165 size_t old_connection_count = connection_count_;
166 connection_count_ = connection_count;
167 if (connection_count)
168 had_connection_ = true;
169 if (connection_count_ < old_connection_count)
170 SignalConnectionRemoved(this);
171 }
172
173 void SetCandidatesGatheringComplete() {
174 if (gathering_state_ != kIceGatheringComplete) {
175 gathering_state_ = kIceGatheringComplete;
176 SignalGatheringState(this);
177 }
178 }
179
180 void SetReceiving(bool receiving) { set_receiving(receiving); }
181
honghaiz1f429e32015-09-28 07:57:34 -0700182 void SetIceConfig(const IceConfig& config) override {
Honghai Zhang049fbb12016-03-07 11:13:07 -0800183 receiving_timeout_ = config.receiving_timeout;
honghaiz1f429e32015-09-28 07:57:34 -0700184 gather_continually_ = config.gather_continually;
deadbeefcbecd352015-09-23 11:50:27 -0700185 }
186
187 int receiving_timeout() const { return receiving_timeout_; }
honghaiz1f429e32015-09-28 07:57:34 -0700188 bool gather_continually() const { return gather_continually_; }
deadbeefcbecd352015-09-23 11:50:27 -0700189
190 int SendPacket(const char* data,
191 size_t len,
192 const rtc::PacketOptions& options,
193 int flags) override {
194 if (state_ != STATE_CONNECTED) {
195 return -1;
196 }
197
198 if (flags != PF_SRTP_BYPASS && flags != 0) {
199 return -1;
200 }
201
202 PacketMessageData* packet = new PacketMessageData(data, len);
203 if (async_) {
204 rtc::Thread::Current()->Post(this, 0, packet);
205 } else {
206 rtc::Thread::Current()->Send(this, 0, packet);
207 }
honghaiz34b11eb2016-03-16 08:55:44 -0700208 rtc::SentPacket sent_packet(options.packet_id, rtc::Time64());
stefanc1aeaf02015-10-15 07:26:07 -0700209 SignalSentPacket(this, sent_packet);
deadbeefcbecd352015-09-23 11:50:27 -0700210 return static_cast<int>(len);
211 }
212 int SetOption(rtc::Socket::Option opt, int value) override { return true; }
213 bool GetOption(rtc::Socket::Option opt, int* value) override { return true; }
214 int GetError() override { return 0; }
215
216 void AddRemoteCandidate(const Candidate& candidate) override {
217 remote_candidates_.push_back(candidate);
218 }
Honghai Zhang7fb69db2016-03-14 11:59:18 -0700219
220 void RemoveRemoteCandidate(const Candidate& candidate) override {}
221
deadbeefcbecd352015-09-23 11:50:27 -0700222 const Candidates& remote_candidates() const { return remote_candidates_; }
223
224 void OnMessage(rtc::Message* msg) override {
225 PacketMessageData* data = static_cast<PacketMessageData*>(msg->pdata);
226 dest_->SignalReadPacket(dest_, data->packet.data<char>(),
227 data->packet.size(), rtc::CreatePacketTime(0), 0);
228 delete data;
229 }
230
231 bool SetLocalCertificate(
232 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
233 local_cert_ = certificate;
234 return true;
235 }
236
237 void SetRemoteSSLCertificate(rtc::FakeSSLCertificate* cert) {
238 remote_cert_ = cert;
239 }
240
241 bool IsDtlsActive() const override { return do_dtls_; }
242
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800243 bool SetSrtpCryptoSuites(const std::vector<int>& ciphers) override {
deadbeefcbecd352015-09-23 11:50:27 -0700244 srtp_ciphers_ = ciphers;
245 return true;
246 }
247
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800248 bool GetSrtpCryptoSuite(int* crypto_suite) override {
249 if (chosen_crypto_suite_ != rtc::SRTP_INVALID_CRYPTO_SUITE) {
250 *crypto_suite = chosen_crypto_suite_;
deadbeefcbecd352015-09-23 11:50:27 -0700251 return true;
252 }
253 return false;
254 }
255
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800256 bool GetSslCipherSuite(int* cipher_suite) override { return false; }
deadbeefcbecd352015-09-23 11:50:27 -0700257
258 rtc::scoped_refptr<rtc::RTCCertificate> GetLocalCertificate() const {
259 return local_cert_;
260 }
261
262 bool GetRemoteSSLCertificate(rtc::SSLCertificate** cert) const override {
263 if (!remote_cert_)
264 return false;
265
266 *cert = remote_cert_->GetReference();
267 return true;
268 }
269
270 bool ExportKeyingMaterial(const std::string& label,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200271 const uint8_t* context,
deadbeefcbecd352015-09-23 11:50:27 -0700272 size_t context_len,
273 bool use_context,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200274 uint8_t* result,
deadbeefcbecd352015-09-23 11:50:27 -0700275 size_t result_len) override {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800276 if (chosen_crypto_suite_ != rtc::SRTP_INVALID_CRYPTO_SUITE) {
deadbeefcbecd352015-09-23 11:50:27 -0700277 memset(result, 0xff, result_len);
278 return true;
279 }
280
281 return false;
282 }
283
284 void NegotiateSrtpCiphers() {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800285 for (std::vector<int>::const_iterator it1 = srtp_ciphers_.begin();
deadbeefcbecd352015-09-23 11:50:27 -0700286 it1 != srtp_ciphers_.end(); ++it1) {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800287 for (std::vector<int>::const_iterator it2 = dest_->srtp_ciphers_.begin();
deadbeefcbecd352015-09-23 11:50:27 -0700288 it2 != dest_->srtp_ciphers_.end(); ++it2) {
289 if (*it1 == *it2) {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800290 chosen_crypto_suite_ = *it1;
291 dest_->chosen_crypto_suite_ = *it2;
deadbeefcbecd352015-09-23 11:50:27 -0700292 return;
293 }
294 }
295 }
296 }
297
298 bool GetStats(ConnectionInfos* infos) override {
299 ConnectionInfo info;
300 infos->clear();
301 infos->push_back(info);
302 return true;
303 }
304
305 void set_ssl_max_protocol_version(rtc::SSLProtocolVersion version) {
306 ssl_max_version_ = version;
307 }
308 rtc::SSLProtocolVersion ssl_max_protocol_version() const {
309 return ssl_max_version_;
310 }
311
312 private:
313 enum State { STATE_INIT, STATE_CONNECTING, STATE_CONNECTED };
deadbeefcbecd352015-09-23 11:50:27 -0700314 FakeTransportChannel* dest_ = nullptr;
315 State state_ = STATE_INIT;
316 bool async_ = false;
317 Candidates remote_candidates_;
318 rtc::scoped_refptr<rtc::RTCCertificate> local_cert_;
319 rtc::FakeSSLCertificate* remote_cert_ = nullptr;
320 bool do_dtls_ = false;
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800321 std::vector<int> srtp_ciphers_;
322 int chosen_crypto_suite_ = rtc::SRTP_INVALID_CRYPTO_SUITE;
deadbeefcbecd352015-09-23 11:50:27 -0700323 int receiving_timeout_ = -1;
honghaiz1f429e32015-09-28 07:57:34 -0700324 bool gather_continually_ = false;
deadbeefcbecd352015-09-23 11:50:27 -0700325 IceRole role_ = ICEROLE_UNKNOWN;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200326 uint64_t tiebreaker_ = 0;
deadbeefcbecd352015-09-23 11:50:27 -0700327 std::string ice_ufrag_;
328 std::string ice_pwd_;
329 std::string remote_ice_ufrag_;
330 std::string remote_ice_pwd_;
331 IceMode remote_ice_mode_ = ICEMODE_FULL;
Guo-wei Shieha7446d22016-01-11 15:27:03 -0800332 rtc::SSLProtocolVersion ssl_max_version_ = rtc::SSL_PROTOCOL_DTLS_12;
deadbeefcbecd352015-09-23 11:50:27 -0700333 rtc::SSLFingerprint dtls_fingerprint_;
334 rtc::SSLRole ssl_role_ = rtc::SSL_CLIENT;
335 size_t connection_count_ = 0;
336 IceGatheringState gathering_state_ = kIceGatheringNew;
337 bool had_connection_ = false;
338};
339
340// Fake transport class, which can be passed to anything that needs a Transport.
341// Can be informed of another FakeTransport via SetDestination (low-tech way
342// of doing candidates)
343class FakeTransport : public Transport {
344 public:
345 typedef std::map<int, FakeTransportChannel*> ChannelMap;
346
347 explicit FakeTransport(const std::string& name) : Transport(name, nullptr) {}
348
349 // Note that we only have a constructor with the allocator parameter so it can
350 // be wrapped by a DtlsTransport.
351 FakeTransport(const std::string& name, PortAllocator* allocator)
352 : Transport(name, nullptr) {}
353
354 ~FakeTransport() { DestroyAllChannels(); }
355
356 const ChannelMap& channels() const { return channels_; }
357
358 // If async, will send packets by "Post"-ing to message queue instead of
359 // synchronously "Send"-ing.
360 void SetAsync(bool async) { async_ = async; }
361 void SetDestination(FakeTransport* dest) {
362 dest_ = dest;
363 for (const auto& kv : channels_) {
364 kv.second->SetLocalCertificate(certificate_);
365 SetChannelDestination(kv.first, kv.second);
366 }
367 }
368
369 void SetWritable(bool writable) {
370 for (const auto& kv : channels_) {
371 kv.second->SetWritable(writable);
372 }
373 }
374
375 void SetLocalCertificate(
376 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) override {
377 certificate_ = certificate;
378 }
379 bool GetLocalCertificate(
380 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) override {
381 if (!certificate_)
382 return false;
383
384 *certificate = certificate_;
385 return true;
386 }
387
388 bool GetSslRole(rtc::SSLRole* role) const override {
389 if (channels_.empty()) {
390 return false;
391 }
392 return channels_.begin()->second->GetSslRole(role);
393 }
394
395 bool SetSslMaxProtocolVersion(rtc::SSLProtocolVersion version) override {
396 ssl_max_version_ = version;
397 for (const auto& kv : channels_) {
398 kv.second->set_ssl_max_protocol_version(ssl_max_version_);
399 }
400 return true;
401 }
402 rtc::SSLProtocolVersion ssl_max_protocol_version() const {
403 return ssl_max_version_;
404 }
405
406 using Transport::local_description;
407 using Transport::remote_description;
408
409 protected:
410 TransportChannelImpl* CreateTransportChannel(int component) override {
411 if (channels_.find(component) != channels_.end()) {
412 return nullptr;
413 }
mikescarlettb9dd7c52016-02-19 20:43:45 -0800414 FakeTransportChannel* channel = new FakeTransportChannel(name(), component);
deadbeefcbecd352015-09-23 11:50:27 -0700415 channel->set_ssl_max_protocol_version(ssl_max_version_);
416 channel->SetAsync(async_);
417 SetChannelDestination(component, channel);
418 channels_[component] = channel;
419 return channel;
420 }
421
422 void DestroyTransportChannel(TransportChannelImpl* channel) override {
423 channels_.erase(channel->component());
424 delete channel;
425 }
426
427 private:
428 FakeTransportChannel* GetFakeChannel(int component) {
429 auto it = channels_.find(component);
430 return (it != channels_.end()) ? it->second : nullptr;
431 }
432
433 void SetChannelDestination(int component, FakeTransportChannel* channel) {
434 FakeTransportChannel* dest_channel = nullptr;
435 if (dest_) {
436 dest_channel = dest_->GetFakeChannel(component);
437 if (dest_channel) {
438 dest_channel->SetLocalCertificate(dest_->certificate_);
439 }
440 }
441 channel->SetDestination(dest_channel);
442 }
443
444 // Note, this is distinct from the Channel map owned by Transport.
445 // This map just tracks the FakeTransportChannels created by this class.
446 // It's mainly needed so that we can access a FakeTransportChannel directly,
447 // even if wrapped by a DtlsTransportChannelWrapper.
448 ChannelMap channels_;
449 FakeTransport* dest_ = nullptr;
450 bool async_ = false;
451 rtc::scoped_refptr<rtc::RTCCertificate> certificate_;
Guo-wei Shieha7446d22016-01-11 15:27:03 -0800452 rtc::SSLProtocolVersion ssl_max_version_ = rtc::SSL_PROTOCOL_DTLS_12;
deadbeefcbecd352015-09-23 11:50:27 -0700453};
454
455// Fake TransportController class, which can be passed into a BaseChannel object
456// for test purposes. Can be connected to other FakeTransportControllers via
457// Connect().
458//
459// This fake is unusual in that for the most part, it's implemented with the
460// real TransportController code, but with fake TransportChannels underneath.
461class FakeTransportController : public TransportController {
462 public:
463 FakeTransportController()
464 : TransportController(rtc::Thread::Current(),
465 rtc::Thread::Current(),
466 nullptr),
467 fail_create_channel_(false) {}
468
469 explicit FakeTransportController(IceRole role)
470 : TransportController(rtc::Thread::Current(),
471 rtc::Thread::Current(),
472 nullptr),
473 fail_create_channel_(false) {
474 SetIceRole(role);
475 }
476
477 explicit FakeTransportController(rtc::Thread* worker_thread)
478 : TransportController(rtc::Thread::Current(), worker_thread, nullptr),
479 fail_create_channel_(false) {}
480
481 FakeTransportController(rtc::Thread* worker_thread, IceRole role)
482 : TransportController(rtc::Thread::Current(), worker_thread, nullptr),
483 fail_create_channel_(false) {
484 SetIceRole(role);
485 }
486
487 FakeTransport* GetTransport_w(const std::string& transport_name) {
488 return static_cast<FakeTransport*>(
489 TransportController::GetTransport_w(transport_name));
490 }
491
492 void Connect(FakeTransportController* dest) {
493 worker_thread()->Invoke<void>(
494 rtc::Bind(&FakeTransportController::Connect_w, this, dest));
495 }
496
497 TransportChannel* CreateTransportChannel_w(const std::string& transport_name,
498 int component) override {
499 if (fail_create_channel_) {
500 return nullptr;
501 }
502 return TransportController::CreateTransportChannel_w(transport_name,
503 component);
504 }
505
506 void set_fail_channel_creation(bool fail_channel_creation) {
507 fail_create_channel_ = fail_channel_creation;
508 }
509
510 protected:
511 Transport* CreateTransport_w(const std::string& transport_name) override {
512 return new FakeTransport(transport_name);
513 }
514
515 void Connect_w(FakeTransportController* dest) {
516 // Simulate the exchange of candidates.
517 ConnectChannels_w();
518 dest->ConnectChannels_w();
519 for (auto& kv : transports()) {
520 FakeTransport* transport = static_cast<FakeTransport*>(kv.second);
521 transport->SetDestination(dest->GetTransport_w(kv.first));
522 }
523 }
524
525 void ConnectChannels_w() {
526 for (auto& kv : transports()) {
527 FakeTransport* transport = static_cast<FakeTransport*>(kv.second);
528 transport->ConnectChannels();
529 transport->MaybeStartGathering();
530 }
531 }
532
533 private:
534 bool fail_create_channel_;
535};
536
537} // namespace cricket
538
539#endif // WEBRTC_P2P_BASE_FAKETRANSPORTCONTROLLER_H_