OLD | NEW |
| (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 */ | |
10 | |
11 #ifndef WEBRTC_P2P_BASE_FAKESESSION_H_ | |
12 #define WEBRTC_P2P_BASE_FAKESESSION_H_ | |
13 | |
14 #include <map> | |
15 #include <string> | |
16 #include <vector> | |
17 | |
18 #include "webrtc/p2p/base/session.h" | |
19 #include "webrtc/p2p/base/transport.h" | |
20 #include "webrtc/p2p/base/transportchannel.h" | |
21 #include "webrtc/p2p/base/transportchannelimpl.h" | |
22 #include "webrtc/base/buffer.h" | |
23 #include "webrtc/base/fakesslidentity.h" | |
24 #include "webrtc/base/messagequeue.h" | |
25 #include "webrtc/base/sigslot.h" | |
26 #include "webrtc/base/sslfingerprint.h" | |
27 | |
28 namespace cricket { | |
29 | |
30 class FakeTransport; | |
31 | |
32 struct PacketMessageData : public rtc::MessageData { | |
33 PacketMessageData(const char* data, size_t len) : packet(data, len) { | |
34 } | |
35 rtc::Buffer packet; | |
36 }; | |
37 | |
38 // Fake transport channel class, which can be passed to anything that needs a | |
39 // transport channel. Can be informed of another FakeTransportChannel via | |
40 // SetDestination. | |
41 class FakeTransportChannel : public TransportChannelImpl, | |
42 public rtc::MessageHandler { | |
43 public: | |
44 explicit FakeTransportChannel(Transport* transport, | |
45 const std::string& content_name, | |
46 int component) | |
47 : TransportChannelImpl(content_name, component), | |
48 transport_(transport), | |
49 dest_(NULL), | |
50 state_(STATE_INIT), | |
51 async_(false), | |
52 identity_(NULL), | |
53 do_dtls_(false), | |
54 role_(ICEROLE_UNKNOWN), | |
55 tiebreaker_(0), | |
56 ice_proto_(ICEPROTO_HYBRID), | |
57 remote_ice_mode_(ICEMODE_FULL), | |
58 dtls_fingerprint_("", NULL, 0), | |
59 ssl_role_(rtc::SSL_CLIENT), | |
60 connection_count_(0) { | |
61 } | |
62 ~FakeTransportChannel() { | |
63 Reset(); | |
64 } | |
65 | |
66 uint64 IceTiebreaker() const { return tiebreaker_; } | |
67 TransportProtocol protocol() const { return ice_proto_; } | |
68 IceMode remote_ice_mode() const { return remote_ice_mode_; } | |
69 const std::string& ice_ufrag() const { return ice_ufrag_; } | |
70 const std::string& ice_pwd() const { return ice_pwd_; } | |
71 const std::string& remote_ice_ufrag() const { return remote_ice_ufrag_; } | |
72 const std::string& remote_ice_pwd() const { return remote_ice_pwd_; } | |
73 const rtc::SSLFingerprint& dtls_fingerprint() const { | |
74 return dtls_fingerprint_; | |
75 } | |
76 | |
77 void SetAsync(bool async) { | |
78 async_ = async; | |
79 } | |
80 | |
81 virtual Transport* GetTransport() { | |
82 return transport_; | |
83 } | |
84 | |
85 virtual TransportChannelState GetState() const { | |
86 if (connection_count_ == 0) { | |
87 return TransportChannelState::STATE_FAILED; | |
88 } | |
89 | |
90 if (connection_count_ == 1) { | |
91 return TransportChannelState::STATE_COMPLETED; | |
92 } | |
93 | |
94 return TransportChannelState::STATE_FAILED; | |
95 } | |
96 | |
97 virtual void SetIceRole(IceRole role) { role_ = role; } | |
98 virtual IceRole GetIceRole() const { return role_; } | |
99 virtual void SetIceTiebreaker(uint64 tiebreaker) { tiebreaker_ = tiebreaker; } | |
100 virtual bool GetIceProtocolType(IceProtocolType* type) const { | |
101 *type = ice_proto_; | |
102 return true; | |
103 } | |
104 virtual void SetIceProtocolType(IceProtocolType type) { ice_proto_ = type; } | |
105 virtual void SetIceCredentials(const std::string& ice_ufrag, | |
106 const std::string& ice_pwd) { | |
107 ice_ufrag_ = ice_ufrag; | |
108 ice_pwd_ = ice_pwd; | |
109 } | |
110 virtual void SetRemoteIceCredentials(const std::string& ice_ufrag, | |
111 const std::string& ice_pwd) { | |
112 remote_ice_ufrag_ = ice_ufrag; | |
113 remote_ice_pwd_ = ice_pwd; | |
114 } | |
115 | |
116 virtual void SetRemoteIceMode(IceMode mode) { remote_ice_mode_ = mode; } | |
117 virtual bool SetRemoteFingerprint(const std::string& alg, const uint8* digest, | |
118 size_t digest_len) { | |
119 dtls_fingerprint_ = rtc::SSLFingerprint(alg, digest, digest_len); | |
120 return true; | |
121 } | |
122 virtual bool SetSslRole(rtc::SSLRole role) { | |
123 ssl_role_ = role; | |
124 return true; | |
125 } | |
126 virtual bool GetSslRole(rtc::SSLRole* role) const { | |
127 *role = ssl_role_; | |
128 return true; | |
129 } | |
130 | |
131 virtual void Connect() { | |
132 if (state_ == STATE_INIT) { | |
133 state_ = STATE_CONNECTING; | |
134 } | |
135 } | |
136 virtual void Reset() { | |
137 if (state_ != STATE_INIT) { | |
138 state_ = STATE_INIT; | |
139 if (dest_) { | |
140 dest_->state_ = STATE_INIT; | |
141 dest_->dest_ = NULL; | |
142 dest_ = NULL; | |
143 } | |
144 } | |
145 } | |
146 | |
147 void SetWritable(bool writable) { | |
148 set_writable(writable); | |
149 } | |
150 | |
151 void SetDestination(FakeTransportChannel* dest) { | |
152 if (state_ == STATE_CONNECTING && dest) { | |
153 // This simulates the delivery of candidates. | |
154 dest_ = dest; | |
155 dest_->dest_ = this; | |
156 if (identity_ && dest_->identity_) { | |
157 do_dtls_ = true; | |
158 dest_->do_dtls_ = true; | |
159 NegotiateSrtpCiphers(); | |
160 } | |
161 state_ = STATE_CONNECTED; | |
162 dest_->state_ = STATE_CONNECTED; | |
163 set_writable(true); | |
164 dest_->set_writable(true); | |
165 } else if (state_ == STATE_CONNECTED && !dest) { | |
166 // Simulates loss of connectivity, by asymmetrically forgetting dest_. | |
167 dest_ = NULL; | |
168 state_ = STATE_CONNECTING; | |
169 set_writable(false); | |
170 } | |
171 } | |
172 | |
173 void SetConnectionCount(size_t connection_count) { | |
174 size_t old_connection_count = connection_count_; | |
175 connection_count_ = connection_count; | |
176 if (connection_count_ < old_connection_count) | |
177 SignalConnectionRemoved(this); | |
178 } | |
179 | |
180 void SetReceiving(bool receiving) { | |
181 set_receiving(receiving); | |
182 } | |
183 | |
184 void SetReceivingTimeout(int timeout) override {} | |
185 | |
186 virtual int SendPacket(const char* data, size_t len, | |
187 const rtc::PacketOptions& options, int flags) { | |
188 if (state_ != STATE_CONNECTED) { | |
189 return -1; | |
190 } | |
191 | |
192 if (flags != PF_SRTP_BYPASS && flags != 0) { | |
193 return -1; | |
194 } | |
195 | |
196 PacketMessageData* packet = new PacketMessageData(data, len); | |
197 if (async_) { | |
198 rtc::Thread::Current()->Post(this, 0, packet); | |
199 } else { | |
200 rtc::Thread::Current()->Send(this, 0, packet); | |
201 } | |
202 return static_cast<int>(len); | |
203 } | |
204 virtual int SetOption(rtc::Socket::Option opt, int value) { | |
205 return true; | |
206 } | |
207 virtual bool GetOption(rtc::Socket::Option opt, int* value) { | |
208 return true; | |
209 } | |
210 virtual int GetError() { | |
211 return 0; | |
212 } | |
213 | |
214 virtual void OnSignalingReady() { | |
215 } | |
216 virtual void OnCandidate(const Candidate& candidate) { | |
217 } | |
218 | |
219 virtual void OnMessage(rtc::Message* msg) { | |
220 PacketMessageData* data = static_cast<PacketMessageData*>( | |
221 msg->pdata); | |
222 dest_->SignalReadPacket(dest_, data->packet.data<char>(), | |
223 data->packet.size(), rtc::CreatePacketTime(0), 0); | |
224 delete data; | |
225 } | |
226 | |
227 bool SetLocalIdentity(rtc::SSLIdentity* identity) { | |
228 identity_ = identity; | |
229 return true; | |
230 } | |
231 | |
232 | |
233 void SetRemoteCertificate(rtc::FakeSSLCertificate* cert) { | |
234 remote_cert_ = cert; | |
235 } | |
236 | |
237 virtual bool IsDtlsActive() const { | |
238 return do_dtls_; | |
239 } | |
240 | |
241 virtual bool SetSrtpCiphers(const std::vector<std::string>& ciphers) { | |
242 srtp_ciphers_ = ciphers; | |
243 return true; | |
244 } | |
245 | |
246 virtual bool GetSrtpCipher(std::string* cipher) { | |
247 if (!chosen_srtp_cipher_.empty()) { | |
248 *cipher = chosen_srtp_cipher_; | |
249 return true; | |
250 } | |
251 return false; | |
252 } | |
253 | |
254 virtual bool GetSslCipher(std::string* cipher) { | |
255 return false; | |
256 } | |
257 | |
258 virtual bool GetLocalIdentity(rtc::SSLIdentity** identity) const { | |
259 if (!identity_) | |
260 return false; | |
261 | |
262 *identity = identity_->GetReference(); | |
263 return true; | |
264 } | |
265 | |
266 virtual bool GetRemoteCertificate(rtc::SSLCertificate** cert) const { | |
267 if (!remote_cert_) | |
268 return false; | |
269 | |
270 *cert = remote_cert_->GetReference(); | |
271 return true; | |
272 } | |
273 | |
274 virtual bool ExportKeyingMaterial(const std::string& label, | |
275 const uint8* context, | |
276 size_t context_len, | |
277 bool use_context, | |
278 uint8* result, | |
279 size_t result_len) { | |
280 if (!chosen_srtp_cipher_.empty()) { | |
281 memset(result, 0xff, result_len); | |
282 return true; | |
283 } | |
284 | |
285 return false; | |
286 } | |
287 | |
288 virtual void NegotiateSrtpCiphers() { | |
289 for (std::vector<std::string>::const_iterator it1 = srtp_ciphers_.begin(); | |
290 it1 != srtp_ciphers_.end(); ++it1) { | |
291 for (std::vector<std::string>::const_iterator it2 = | |
292 dest_->srtp_ciphers_.begin(); | |
293 it2 != dest_->srtp_ciphers_.end(); ++it2) { | |
294 if (*it1 == *it2) { | |
295 chosen_srtp_cipher_ = *it1; | |
296 dest_->chosen_srtp_cipher_ = *it2; | |
297 return; | |
298 } | |
299 } | |
300 } | |
301 } | |
302 | |
303 bool GetStats(ConnectionInfos* infos) override { | |
304 ConnectionInfo info; | |
305 infos->clear(); | |
306 infos->push_back(info); | |
307 return true; | |
308 } | |
309 | |
310 private: | |
311 enum State { STATE_INIT, STATE_CONNECTING, STATE_CONNECTED }; | |
312 Transport* transport_; | |
313 FakeTransportChannel* dest_; | |
314 State state_; | |
315 bool async_; | |
316 rtc::SSLIdentity* identity_; | |
317 rtc::FakeSSLCertificate* remote_cert_; | |
318 bool do_dtls_; | |
319 std::vector<std::string> srtp_ciphers_; | |
320 std::string chosen_srtp_cipher_; | |
321 IceRole role_; | |
322 uint64 tiebreaker_; | |
323 IceProtocolType ice_proto_; | |
324 std::string ice_ufrag_; | |
325 std::string ice_pwd_; | |
326 std::string remote_ice_ufrag_; | |
327 std::string remote_ice_pwd_; | |
328 IceMode remote_ice_mode_; | |
329 rtc::SSLFingerprint dtls_fingerprint_; | |
330 rtc::SSLRole ssl_role_; | |
331 size_t connection_count_; | |
332 }; | |
333 | |
334 // Fake transport class, which can be passed to anything that needs a Transport. | |
335 // Can be informed of another FakeTransport via SetDestination (low-tech way | |
336 // of doing candidates) | |
337 class FakeTransport : public Transport { | |
338 public: | |
339 typedef std::map<int, FakeTransportChannel*> ChannelMap; | |
340 FakeTransport(rtc::Thread* signaling_thread, | |
341 rtc::Thread* worker_thread, | |
342 const std::string& content_name, | |
343 PortAllocator* alllocator = NULL) | |
344 : Transport(signaling_thread, worker_thread, | |
345 content_name, "test_type", NULL), | |
346 dest_(NULL), | |
347 async_(false), | |
348 identity_(NULL) { | |
349 } | |
350 ~FakeTransport() { | |
351 DestroyAllChannels(); | |
352 } | |
353 | |
354 const ChannelMap& channels() const { return channels_; } | |
355 | |
356 void SetAsync(bool async) { async_ = async; } | |
357 void SetDestination(FakeTransport* dest) { | |
358 dest_ = dest; | |
359 for (ChannelMap::iterator it = channels_.begin(); it != channels_.end(); | |
360 ++it) { | |
361 it->second->SetLocalIdentity(identity_); | |
362 SetChannelDestination(it->first, it->second); | |
363 } | |
364 } | |
365 | |
366 void SetWritable(bool writable) { | |
367 for (ChannelMap::iterator it = channels_.begin(); it != channels_.end(); | |
368 ++it) { | |
369 it->second->SetWritable(writable); | |
370 } | |
371 } | |
372 | |
373 void set_identity(rtc::SSLIdentity* identity) { | |
374 identity_ = identity; | |
375 } | |
376 | |
377 using Transport::local_description; | |
378 using Transport::remote_description; | |
379 | |
380 protected: | |
381 virtual TransportChannelImpl* CreateTransportChannel(int component) { | |
382 if (channels_.find(component) != channels_.end()) { | |
383 return NULL; | |
384 } | |
385 FakeTransportChannel* channel = | |
386 new FakeTransportChannel(this, content_name(), component); | |
387 channel->SetAsync(async_); | |
388 SetChannelDestination(component, channel); | |
389 channels_[component] = channel; | |
390 return channel; | |
391 } | |
392 virtual void DestroyTransportChannel(TransportChannelImpl* channel) { | |
393 channels_.erase(channel->component()); | |
394 delete channel; | |
395 } | |
396 virtual void SetIdentity_w(rtc::SSLIdentity* identity) { | |
397 identity_ = identity; | |
398 } | |
399 virtual bool GetIdentity_w(rtc::SSLIdentity** identity) { | |
400 if (!identity_) | |
401 return false; | |
402 | |
403 *identity = identity_->GetReference(); | |
404 return true; | |
405 } | |
406 | |
407 private: | |
408 FakeTransportChannel* GetFakeChannel(int component) { | |
409 ChannelMap::iterator it = channels_.find(component); | |
410 return (it != channels_.end()) ? it->second : NULL; | |
411 } | |
412 void SetChannelDestination(int component, | |
413 FakeTransportChannel* channel) { | |
414 FakeTransportChannel* dest_channel = NULL; | |
415 if (dest_) { | |
416 dest_channel = dest_->GetFakeChannel(component); | |
417 if (dest_channel) { | |
418 dest_channel->SetLocalIdentity(dest_->identity_); | |
419 } | |
420 } | |
421 channel->SetDestination(dest_channel); | |
422 } | |
423 | |
424 // Note, this is distinct from the Channel map owned by Transport. | |
425 // This map just tracks the FakeTransportChannels created by this class. | |
426 ChannelMap channels_; | |
427 FakeTransport* dest_; | |
428 bool async_; | |
429 rtc::SSLIdentity* identity_; | |
430 }; | |
431 | |
432 // Fake session class, which can be passed into a BaseChannel object for | |
433 // test purposes. Can be connected to other FakeSessions via Connect(). | |
434 class FakeSession : public BaseSession { | |
435 public: | |
436 explicit FakeSession() | |
437 : BaseSession(rtc::Thread::Current(), | |
438 rtc::Thread::Current(), | |
439 NULL, "", "", true), | |
440 fail_create_channel_(false) { | |
441 } | |
442 explicit FakeSession(bool initiator) | |
443 : BaseSession(rtc::Thread::Current(), | |
444 rtc::Thread::Current(), | |
445 NULL, "", "", initiator), | |
446 fail_create_channel_(false) { | |
447 } | |
448 FakeSession(rtc::Thread* worker_thread, bool initiator) | |
449 : BaseSession(rtc::Thread::Current(), | |
450 worker_thread, | |
451 NULL, "", "", initiator), | |
452 fail_create_channel_(false) { | |
453 } | |
454 | |
455 FakeTransport* GetTransport(const std::string& content_name) { | |
456 return static_cast<FakeTransport*>( | |
457 BaseSession::GetTransport(content_name)); | |
458 } | |
459 | |
460 void Connect(FakeSession* dest) { | |
461 // Simulate the exchange of candidates. | |
462 CompleteNegotiation(); | |
463 dest->CompleteNegotiation(); | |
464 for (TransportMap::const_iterator it = transport_proxies().begin(); | |
465 it != transport_proxies().end(); ++it) { | |
466 static_cast<FakeTransport*>(it->second->impl())->SetDestination( | |
467 dest->GetTransport(it->first)); | |
468 } | |
469 } | |
470 | |
471 virtual TransportChannel* CreateChannel( | |
472 const std::string& content_name, | |
473 int component) { | |
474 if (fail_create_channel_) { | |
475 return NULL; | |
476 } | |
477 return BaseSession::CreateChannel(content_name, component); | |
478 } | |
479 | |
480 void set_fail_channel_creation(bool fail_channel_creation) { | |
481 fail_create_channel_ = fail_channel_creation; | |
482 } | |
483 | |
484 // TODO: Hoist this into Session when we re-work the Session code. | |
485 void set_ssl_identity(rtc::SSLIdentity* identity) { | |
486 for (TransportMap::const_iterator it = transport_proxies().begin(); | |
487 it != transport_proxies().end(); ++it) { | |
488 // We know that we have a FakeTransport* | |
489 | |
490 static_cast<FakeTransport*>(it->second->impl())->set_identity | |
491 (identity); | |
492 } | |
493 } | |
494 | |
495 protected: | |
496 virtual Transport* CreateTransport(const std::string& content_name) { | |
497 return new FakeTransport(signaling_thread(), worker_thread(), content_name); | |
498 } | |
499 | |
500 void CompleteNegotiation() { | |
501 for (TransportMap::const_iterator it = transport_proxies().begin(); | |
502 it != transport_proxies().end(); ++it) { | |
503 it->second->CompleteNegotiation(); | |
504 it->second->ConnectChannels(); | |
505 } | |
506 } | |
507 | |
508 private: | |
509 bool fail_create_channel_; | |
510 }; | |
511 | |
512 } // namespace cricket | |
513 | |
514 #endif // WEBRTC_P2P_BASE_FAKESESSION_H_ | |
OLD | NEW |