Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(203)

Side by Side Diff: webrtc/p2p/base/faketransportcontroller.h

Issue 1246913005: TransportController refactoring (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
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 */
pthatcher1 2015/09/01 17:05:21 Is there something you can do with git to make thi
Taylor Brandstetter 2015/09/01 23:53:30 In my local history that's how it appears. But at
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
30 namespace cricket {
31
32 class FakeTransport;
33
34 struct PacketMessageData : public rtc::MessageData {
35 PacketMessageData(const char* data, size_t len) : packet(data, len) {}
36 rtc::Buffer packet;
pthatcher1 2015/09/01 17:05:21 Can you use TypedMessageData<rtc::Buffer>?
Taylor Brandstetter 2015/09/01 23:53:30 I don't think that would be ideal, since it would
37 };
38
39 // Fake transport channel class, which can be passed to anything that needs a
40 // transport channel. Can be informed of another FakeTransportChannel via
41 // SetDestination.
42 // TODO(hbos): Move implementation to .cc file, this and other classes in file.
43 class FakeTransportChannel : public TransportChannelImpl,
44 public rtc::MessageHandler {
45 public:
46 explicit FakeTransportChannel(Transport* transport,
47 const std::string& content_name,
48 int component)
49 : TransportChannelImpl(content_name, component),
50 transport_(transport),
51 dtls_fingerprint_("", nullptr, 0) {}
52 ~FakeTransportChannel() { Reset(); }
53
54 uint64 IceTiebreaker() const { return tiebreaker_; }
55 IceMode remote_ice_mode() const { return remote_ice_mode_; }
56 const std::string& ice_ufrag() const { return ice_ufrag_; }
57 const std::string& ice_pwd() const { return ice_pwd_; }
58 const std::string& remote_ice_ufrag() const { return remote_ice_ufrag_; }
59 const std::string& remote_ice_pwd() const { return remote_ice_pwd_; }
60 const rtc::SSLFingerprint& dtls_fingerprint() const {
61 return dtls_fingerprint_;
62 }
63
64 void SetAsync(bool async) { async_ = async; }
65
66 Transport* GetTransport() override { return transport_; }
67
68 TransportChannelState GetState() const override {
69 if (connection_count_ == 0) {
70 return had_connection_ ? TransportChannelState::STATE_FAILED
71 : TransportChannelState::STATE_INIT;
72 }
73
74 if (connection_count_ == 1) {
75 return TransportChannelState::STATE_COMPLETED;
76 }
77
78 return TransportChannelState::STATE_CONNECTING;
79 }
80
81 void SetIceRole(IceRole role) override { role_ = role; }
82 IceRole GetIceRole() const override { return role_; }
83 void SetIceTiebreaker(uint64 tiebreaker) override {
84 tiebreaker_ = tiebreaker;
85 }
86 void SetIceCredentials(const std::string& ice_ufrag,
87 const std::string& ice_pwd) override {
88 ice_ufrag_ = ice_ufrag;
89 ice_pwd_ = ice_pwd;
90 }
91 void SetRemoteIceCredentials(const std::string& ice_ufrag,
92 const std::string& ice_pwd) override {
93 remote_ice_ufrag_ = ice_ufrag;
94 remote_ice_pwd_ = ice_pwd;
95 }
96
97 void SetRemoteIceMode(IceMode mode) override { remote_ice_mode_ = mode; }
98 bool SetRemoteFingerprint(const std::string& alg,
99 const uint8* digest,
100 size_t digest_len) override {
101 dtls_fingerprint_ = rtc::SSLFingerprint(alg, digest, digest_len);
102 return true;
103 }
104 bool SetSslRole(rtc::SSLRole role) override {
105 ssl_role_ = role;
106 return true;
107 }
108 bool GetSslRole(rtc::SSLRole* role) const override {
109 *role = ssl_role_;
110 return true;
111 }
112
113 void Connect() override {
114 if (state_ == STATE_INIT) {
115 state_ = STATE_CONNECTING;
116 // Connect is expected to start candidate gathering
117 if (gathering_state_ != kIceGatheringGathering) {
118 gathering_state_ = kIceGatheringGathering;
119 SignalGatheringState(this);
120 }
121 }
122 }
123
124 IceGatheringState gathering_state() const override {
125 return gathering_state_;
126 }
127
128 void Reset() {
129 if (state_ != STATE_INIT) {
130 state_ = STATE_INIT;
131 if (dest_) {
132 dest_->state_ = STATE_INIT;
133 dest_->dest_ = nullptr;
134 dest_ = nullptr;
135 }
136 }
137 }
138
139 void SetWritable(bool writable) { set_writable(writable); }
140
141 void SetDestination(FakeTransportChannel* dest) {
142 if (state_ == STATE_CONNECTING && dest) {
143 // This simulates the delivery of candidates.
144 dest_ = dest;
145 dest_->dest_ = this;
146 if (identity_ && dest_->identity_) {
147 do_dtls_ = true;
148 dest_->do_dtls_ = true;
149 NegotiateSrtpCiphers();
150 }
151 state_ = STATE_CONNECTED;
152 dest_->state_ = STATE_CONNECTED;
153 set_writable(true);
154 dest_->set_writable(true);
155 } else if (state_ == STATE_CONNECTED && !dest) {
156 // Simulates loss of connectivity, by asymmetrically forgetting dest_.
157 dest_ = nullptr;
158 state_ = STATE_CONNECTING;
159 set_writable(false);
160 }
161 }
162
163 void SetConnectionCount(size_t connection_count) {
164 size_t old_connection_count = connection_count_;
165 connection_count_ = connection_count;
166 if (connection_count)
167 had_connection_ = true;
168 if (connection_count_ < old_connection_count)
169 SignalConnectionRemoved(this);
170 }
171
172 void SetCandidatesGatheringComplete() {
173 if (gathering_state_ != kIceGatheringComplete) {
174 gathering_state_ = kIceGatheringComplete;
175 SignalGatheringState(this);
176 }
177 }
178
179 void SetReceiving(bool receiving) { set_receiving(receiving); }
180
181 void SetReceivingTimeout(int timeout) override {
182 receiving_timeout_ = timeout;
183 }
184
185 int receiving_timeout() const { return receiving_timeout_; }
186
187 int SendPacket(const char* data,
188 size_t len,
189 const rtc::PacketOptions& options,
190 int flags) override {
191 if (state_ != STATE_CONNECTED) {
192 return -1;
193 }
194
195 if (flags != PF_SRTP_BYPASS && flags != 0) {
196 return -1;
197 }
198
199 PacketMessageData* packet = new PacketMessageData(data, len);
200 if (async_) {
201 rtc::Thread::Current()->Post(this, 0, packet);
202 } else {
203 rtc::Thread::Current()->Send(this, 0, packet);
204 }
205 return static_cast<int>(len);
206 }
207 int SetOption(rtc::Socket::Option opt, int value) override { return true; }
208 bool GetOption(rtc::Socket::Option opt, int* value) override { return true; }
209 int GetError() override { return 0; }
210
211 void AddRemoteCandidate(const Candidate& candidate) override {
212 remote_candidates_.push_back(candidate);
213 }
214 const Candidates& remote_candidates() const { return remote_candidates_; }
215
216 void OnMessage(rtc::Message* msg) override {
217 PacketMessageData* data = static_cast<PacketMessageData*>(msg->pdata);
218 dest_->SignalReadPacket(dest_, data->packet.data<char>(),
219 data->packet.size(), rtc::CreatePacketTime(0), 0);
220 delete data;
221 }
222
223 bool SetLocalIdentity(rtc::SSLIdentity* identity) {
224 identity_ = identity;
225 return true;
226 }
227
228 void SetRemoteCertificate(rtc::FakeSSLCertificate* cert) {
229 remote_cert_ = cert;
230 }
231
232 bool IsDtlsActive() const override { return do_dtls_; }
233
234 bool SetSrtpCiphers(const std::vector<std::string>& ciphers) override {
235 srtp_ciphers_ = ciphers;
236 return true;
237 }
238
239 bool GetSrtpCipher(std::string* cipher) override {
240 if (!chosen_srtp_cipher_.empty()) {
241 *cipher = chosen_srtp_cipher_;
242 return true;
243 }
244 return false;
245 }
246
247 bool GetSslCipher(std::string* cipher) override { return false; }
248
249 bool GetLocalIdentity(rtc::SSLIdentity** identity) const override {
250 if (!identity_)
251 return false;
252
253 *identity = identity_->GetReference();
254 return true;
255 }
256
257 bool GetRemoteCertificate(rtc::SSLCertificate** cert) const override {
258 if (!remote_cert_)
259 return false;
260
261 *cert = remote_cert_->GetReference();
262 return true;
263 }
264
265 bool ExportKeyingMaterial(const std::string& label,
266 const uint8* context,
267 size_t context_len,
268 bool use_context,
269 uint8* result,
270 size_t result_len) override {
271 if (!chosen_srtp_cipher_.empty()) {
272 memset(result, 0xff, result_len);
273 return true;
274 }
275
276 return false;
277 }
278
279 void NegotiateSrtpCiphers() {
280 for (std::vector<std::string>::const_iterator it1 = srtp_ciphers_.begin();
281 it1 != srtp_ciphers_.end(); ++it1) {
282 for (std::vector<std::string>::const_iterator it2 =
283 dest_->srtp_ciphers_.begin();
284 it2 != dest_->srtp_ciphers_.end(); ++it2) {
285 if (*it1 == *it2) {
286 chosen_srtp_cipher_ = *it1;
287 dest_->chosen_srtp_cipher_ = *it2;
288 return;
289 }
290 }
291 }
292 }
293
294 bool GetStats(ConnectionInfos* infos) override {
295 ConnectionInfo info;
296 infos->clear();
297 infos->push_back(info);
298 return true;
299 }
300
301 void set_ssl_max_protocol_version(rtc::SSLProtocolVersion version) {
302 ssl_max_version_ = version;
303 }
304 rtc::SSLProtocolVersion ssl_max_protocol_version() const {
305 return ssl_max_version_;
306 }
307
308 private:
309 enum State { STATE_INIT, STATE_CONNECTING, STATE_CONNECTED };
310 Transport* transport_;
311 FakeTransportChannel* dest_ = nullptr;
312 State state_ = STATE_INIT;
313 bool async_ = false;
314 Candidates remote_candidates_;
315 rtc::SSLIdentity* identity_ = nullptr;
316 rtc::FakeSSLCertificate* remote_cert_ = nullptr;
317 bool do_dtls_ = false;
318 std::vector<std::string> srtp_ciphers_;
319 std::string chosen_srtp_cipher_;
320 int receiving_timeout_ = -1;
321 IceRole role_ = ICEROLE_UNKNOWN;
322 uint64 tiebreaker_ = 0;
323 std::string ice_ufrag_;
324 std::string ice_pwd_;
325 std::string remote_ice_ufrag_;
326 std::string remote_ice_pwd_;
327 IceMode remote_ice_mode_ = ICEMODE_FULL;
328 rtc::SSLProtocolVersion ssl_max_version_ = rtc::SSL_PROTOCOL_DTLS_10;
329 rtc::SSLFingerprint dtls_fingerprint_;
330 rtc::SSLRole ssl_role_ = rtc::SSL_CLIENT;
331 size_t connection_count_ = 0;
332 IceGatheringState gathering_state_ = kIceGatheringNew;
333 bool had_connection_ = false;
334 };
335
336 // Fake transport class, which can be passed to anything that needs a Transport.
337 // Can be informed of another FakeTransport via SetDestination (low-tech way
338 // of doing candidates)
339 class FakeTransport : public Transport {
340 public:
341 typedef std::map<int, FakeTransportChannel*> ChannelMap;
342 // Note that the constructor only needs the allocator parameter so it can be
343 // wrapped by a DtlsTransport
344 FakeTransport(const std::string& content_name,
345 PortAllocator* allocator = nullptr)
pthatcher1 2015/09/01 17:05:21 We usually prefer separate methods/constructors ra
Taylor Brandstetter 2015/09/01 23:53:30 Done.
346 : Transport(content_name, nullptr) {}
347
348 ~FakeTransport() { DestroyAllChannels(); }
349
350 const ChannelMap& channels() const { return channels_; }
351
352 void SetAsync(bool async) { async_ = async; }
pthatcher1 2015/09/01 17:05:21 Can you comment what this does?
Taylor Brandstetter 2015/09/01 23:53:30 Done.
353 void SetDestination(FakeTransport* dest) {
354 dest_ = dest;
355 for (const auto& kv : channels_) {
356 // TODO(hbos): SetLocalCertificate
357 kv.second->SetLocalIdentity(certificate_ ? certificate_->identity()
358 : nullptr);
359 SetChannelDestination(kv.first, kv.second);
360 }
361 }
362
363 void SetWritable(bool writable) {
364 for (const auto& kv : channels_) {
365 kv.second->SetWritable(writable);
366 }
367 }
368
369 void SetCertificate(
370 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) override {
371 certificate_ = certificate;
372 }
373 bool GetCertificate(
374 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) override {
375 if (!certificate_)
376 return false;
377
378 *certificate = certificate_;
379 return true;
380 }
381
382 bool GetSslRole(rtc::SSLRole* role) const override {
383 if (channels_.empty()) {
384 return false;
385 }
386 return channels_.cbegin()->second->GetSslRole(role);
387 }
388
389 bool SetSslMaxProtocolVersion(rtc::SSLProtocolVersion version) override {
390 ssl_max_version_ = version;
391 for (const auto& kv : channels_) {
392 kv.second->set_ssl_max_protocol_version(ssl_max_version_);
393 }
394 return true;
395 }
396 rtc::SSLProtocolVersion ssl_max_protocol_version() const {
397 return ssl_max_version_;
398 }
399
400 using Transport::local_description;
401 using Transport::remote_description;
402
403 protected:
404 TransportChannelImpl* CreateTransportChannel(int component) override {
405 if (channels_.find(component) != channels_.end()) {
406 return nullptr;
407 }
408 FakeTransportChannel* channel =
409 new FakeTransportChannel(this, content_name(), component);
410 channel->set_ssl_max_protocol_version(ssl_max_version_);
411 channel->SetAsync(async_);
412 SetChannelDestination(component, channel);
413 channels_[component] = channel;
414 return channel;
415 }
416
417 void DestroyTransportChannel(TransportChannelImpl* channel) override {
418 channels_.erase(channel->component());
419 delete channel;
420 }
421
422 private:
423 FakeTransportChannel* GetFakeChannel(int component) {
424 auto it = channels_.find(component);
425 return (it != channels_.end()) ? it->second : nullptr;
426 }
427
428 void SetChannelDestination(int component, FakeTransportChannel* channel) {
429 FakeTransportChannel* dest_channel = nullptr;
430 if (dest_) {
431 dest_channel = dest_->GetFakeChannel(component);
432 if (dest_channel) {
433 // TODO(hbos): SetLocalCertificate
434 dest_channel->SetLocalIdentity(
435 dest_->certificate_ ? dest_->certificate_->identity() : nullptr);
436 }
437 }
438 channel->SetDestination(dest_channel);
439 }
440
441 // Note, this is distinct from the Channel map owned by Transport.
442 // This map just tracks the FakeTransportChannels created by this class.
443 // It's mainly needed so that we can access a FakeTransportChannel directly,
444 // even if wrapped by a DtlsTransportChannelWrapper.
445 ChannelMap channels_;
446 FakeTransport* dest_ = nullptr;
447 bool async_ = false;
448 rtc::scoped_refptr<rtc::RTCCertificate> certificate_;
449 rtc::SSLProtocolVersion ssl_max_version_ = rtc::SSL_PROTOCOL_DTLS_10;
450 };
451
452 // Fake TransportController class, which can be passed into a BaseChannel object
453 // for test purposes. Can be connected to other FakeTransportControllers via
454 // Connect().
pthatcher1 2015/09/01 17:05:21 This isn't really a FakeTransportController. It's
Taylor Brandstetter 2015/09/01 23:53:30 This is part of why I had that conversation with y
455 class FakeTransportController : public TransportController {
456 public:
457 FakeTransportController()
458 : TransportController(rtc::Thread::Current(),
459 rtc::Thread::Current(),
460 nullptr),
461 fail_create_channel_(false) {}
462
463 explicit FakeTransportController(bool initiator)
464 : TransportController(rtc::Thread::Current(),
465 rtc::Thread::Current(),
466 nullptr),
467 fail_create_channel_(false) {
468 SetIceRole(initiator ? ICEROLE_CONTROLLING : ICEROLE_CONTROLLED);
469 }
pthatcher1 2015/09/01 17:05:21 Can we just pass in the IceRole instead of the ini
Taylor Brandstetter 2015/09/01 23:53:30 Done.
470
471 explicit FakeTransportController(rtc::Thread* worker_thread)
472 : TransportController(rtc::Thread::Current(), worker_thread, nullptr),
473 fail_create_channel_(false) {
474 }
475
476 FakeTransportController(rtc::Thread* worker_thread, bool initiator)
477 : TransportController(rtc::Thread::Current(), worker_thread, nullptr),
478 fail_create_channel_(false) {
479 SetIceRole(initiator ? ICEROLE_CONTROLLING : ICEROLE_CONTROLLED);
480 }
481
482 FakeTransport* GetTransport_w(const std::string& transport_name) {
483 return static_cast<FakeTransport*>(
484 TransportController::GetTransport_w(transport_name));
485 }
486
487 void Connect(FakeTransportController* dest) {
488 worker_thread()->Invoke<void>(
489 rtc::Bind(&FakeTransportController::Connect_w, this, dest));
490 }
491
492 TransportChannel* CreateTransportChannel_w(const std::string& transport_name,
493 int component) override {
494 if (fail_create_channel_) {
495 return nullptr;
496 }
497 return TransportController::CreateTransportChannel_w(transport_name,
498 component);
499 }
500
501 void set_fail_channel_creation(bool fail_channel_creation) {
502 fail_create_channel_ = fail_channel_creation;
503 }
504
505 protected:
506 Transport* CreateTransport_w(const std::string& transport_name) override {
507 return new FakeTransport(transport_name);
508 }
509
510 void Connect_w(FakeTransportController* dest) {
511 // Simulate the exchange of candidates.
512 ConnectChannels_w();
513 dest->ConnectChannels_w();
514 for (auto& kv : transports()) {
515 FakeTransport* transport = static_cast<FakeTransport*>(kv.second);
516 transport->SetDestination(dest->GetTransport_w(kv.first));
517 }
518 }
519
520 void ConnectChannels_w() {
521 for (auto& kv : transports()) {
522 FakeTransport* transport = static_cast<FakeTransport*>(kv.second);
523 transport->ConnectChannels();
524 }
525 }
526
527 private:
528 bool fail_create_channel_;
529 };
530
531 } // namespace cricket
532
533 #endif // WEBRTC_P2P_BASE_FAKETRANSPORTCONTROLLER_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698