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 P2P_BASE_FAKE_ICE_TRANSPORT_H_ 12 #define P2P_BASE_FAKE_ICE_TRANSPORT_H_ 13 14 #include <map> 15 #include <memory> 16 #include <string> 17 #include <utility> 18 19 #include "absl/algorithm/container.h" 20 #include "absl/strings/string_view.h" 21 #include "absl/types/optional.h" 22 #include "api/ice_transport_interface.h" 23 #include "api/task_queue/pending_task_safety_flag.h" 24 #include "api/units/time_delta.h" 25 #include "p2p/base/ice_transport_internal.h" 26 #include "rtc_base/copy_on_write_buffer.h" 27 #include "rtc_base/task_queue_for_test.h" 28 29 namespace cricket { 30 using ::webrtc::SafeTask; 31 using ::webrtc::TimeDelta; 32 33 // All methods must be called on the network thread (which is either the thread 34 // calling the constructor, or the separate thread explicitly passed to the 35 // constructor). 36 class FakeIceTransport : public IceTransportInternal { 37 public: 38 explicit FakeIceTransport(absl::string_view name, 39 int component, 40 rtc::Thread* network_thread = nullptr) name_(name)41 : name_(name), 42 component_(component), 43 network_thread_(network_thread ? network_thread 44 : rtc::Thread::Current()) { 45 RTC_DCHECK(network_thread_); 46 } 47 // Must be called either on the network thread, or after the network thread 48 // has been shut down. ~FakeIceTransport()49 ~FakeIceTransport() override { 50 if (dest_ && dest_->dest_ == this) { 51 dest_->dest_ = nullptr; 52 } 53 } 54 55 // If async, will send packets by "Post"-ing to message queue instead of 56 // synchronously "Send"-ing. SetAsync(bool async)57 void SetAsync(bool async) { 58 RTC_DCHECK_RUN_ON(network_thread_); 59 async_ = async; 60 } SetAsyncDelay(int delay_ms)61 void SetAsyncDelay(int delay_ms) { 62 RTC_DCHECK_RUN_ON(network_thread_); 63 async_delay_ms_ = delay_ms; 64 } 65 66 // SetWritable, SetReceiving and SetDestination are the main methods that can 67 // be used for testing, to simulate connectivity or lack thereof. SetWritable(bool writable)68 void SetWritable(bool writable) { 69 RTC_DCHECK_RUN_ON(network_thread_); 70 set_writable(writable); 71 } SetReceiving(bool receiving)72 void SetReceiving(bool receiving) { 73 RTC_DCHECK_RUN_ON(network_thread_); 74 set_receiving(receiving); 75 } 76 77 // Simulates the two transports connecting to each other. 78 // If `asymmetric` is true this method only affects this FakeIceTransport. 79 // If false, it affects `dest` as well. 80 void SetDestination(FakeIceTransport* dest, bool asymmetric = false) { 81 RTC_DCHECK_RUN_ON(network_thread_); 82 if (dest == dest_) { 83 return; 84 } 85 RTC_DCHECK(!dest || !dest_) 86 << "Changing fake destination from one to another is not supported."; 87 if (dest) { 88 // This simulates the delivery of candidates. 89 dest_ = dest; 90 set_writable(true); 91 if (!asymmetric) { 92 dest->SetDestination(this, true); 93 } 94 } else { 95 // Simulates loss of connectivity, by asymmetrically forgetting dest_. 96 dest_ = nullptr; 97 set_writable(false); 98 } 99 } 100 SetTransportState(webrtc::IceTransportState state,IceTransportState legacy_state)101 void SetTransportState(webrtc::IceTransportState state, 102 IceTransportState legacy_state) { 103 RTC_DCHECK_RUN_ON(network_thread_); 104 transport_state_ = state; 105 legacy_transport_state_ = legacy_state; 106 SignalIceTransportStateChanged(this); 107 } 108 SetConnectionCount(size_t connection_count)109 void SetConnectionCount(size_t connection_count) { 110 RTC_DCHECK_RUN_ON(network_thread_); 111 size_t old_connection_count = connection_count_; 112 connection_count_ = connection_count; 113 if (connection_count) { 114 had_connection_ = true; 115 } 116 // In this fake transport channel, `connection_count_` determines the 117 // transport state. 118 if (connection_count_ < old_connection_count) { 119 SignalStateChanged(this); 120 } 121 } 122 SetCandidatesGatheringComplete()123 void SetCandidatesGatheringComplete() { 124 RTC_DCHECK_RUN_ON(network_thread_); 125 if (gathering_state_ != kIceGatheringComplete) { 126 gathering_state_ = kIceGatheringComplete; 127 SignalGatheringState(this); 128 } 129 } 130 131 // Convenience functions for accessing ICE config and other things. receiving_timeout()132 int receiving_timeout() const { 133 RTC_DCHECK_RUN_ON(network_thread_); 134 return ice_config_.receiving_timeout_or_default(); 135 } gather_continually()136 bool gather_continually() const { 137 RTC_DCHECK_RUN_ON(network_thread_); 138 return ice_config_.gather_continually(); 139 } remote_candidates()140 const Candidates& remote_candidates() const { 141 RTC_DCHECK_RUN_ON(network_thread_); 142 return remote_candidates_; 143 } 144 145 // Fake IceTransportInternal implementation. transport_name()146 const std::string& transport_name() const override { return name_; } component()147 int component() const override { return component_; } IceTiebreaker()148 uint64_t IceTiebreaker() const { 149 RTC_DCHECK_RUN_ON(network_thread_); 150 return tiebreaker_; 151 } remote_ice_mode()152 IceMode remote_ice_mode() const { 153 RTC_DCHECK_RUN_ON(network_thread_); 154 return remote_ice_mode_; 155 } ice_ufrag()156 const std::string& ice_ufrag() const { return ice_parameters_.ufrag; } ice_pwd()157 const std::string& ice_pwd() const { return ice_parameters_.pwd; } remote_ice_ufrag()158 const std::string& remote_ice_ufrag() const { 159 return remote_ice_parameters_.ufrag; 160 } remote_ice_pwd()161 const std::string& remote_ice_pwd() const { 162 return remote_ice_parameters_.pwd; 163 } ice_parameters()164 const IceParameters& ice_parameters() const { return ice_parameters_; } remote_ice_parameters()165 const IceParameters& remote_ice_parameters() const { 166 return remote_ice_parameters_; 167 } 168 GetState()169 IceTransportState GetState() const override { 170 RTC_DCHECK_RUN_ON(network_thread_); 171 if (legacy_transport_state_) { 172 return *legacy_transport_state_; 173 } 174 175 if (connection_count_ == 0) { 176 return had_connection_ ? IceTransportState::STATE_FAILED 177 : IceTransportState::STATE_INIT; 178 } 179 180 if (connection_count_ == 1) { 181 return IceTransportState::STATE_COMPLETED; 182 } 183 184 return IceTransportState::STATE_CONNECTING; 185 } 186 GetIceTransportState()187 webrtc::IceTransportState GetIceTransportState() const override { 188 RTC_DCHECK_RUN_ON(network_thread_); 189 if (transport_state_) { 190 return *transport_state_; 191 } 192 193 if (connection_count_ == 0) { 194 return had_connection_ ? webrtc::IceTransportState::kFailed 195 : webrtc::IceTransportState::kNew; 196 } 197 198 if (connection_count_ == 1) { 199 return webrtc::IceTransportState::kCompleted; 200 } 201 202 return webrtc::IceTransportState::kConnected; 203 } 204 SetIceRole(IceRole role)205 void SetIceRole(IceRole role) override { 206 RTC_DCHECK_RUN_ON(network_thread_); 207 role_ = role; 208 } GetIceRole()209 IceRole GetIceRole() const override { 210 RTC_DCHECK_RUN_ON(network_thread_); 211 return role_; 212 } SetIceTiebreaker(uint64_t tiebreaker)213 void SetIceTiebreaker(uint64_t tiebreaker) override { 214 RTC_DCHECK_RUN_ON(network_thread_); 215 tiebreaker_ = tiebreaker; 216 } SetIceParameters(const IceParameters & ice_params)217 void SetIceParameters(const IceParameters& ice_params) override { 218 RTC_DCHECK_RUN_ON(network_thread_); 219 ice_parameters_ = ice_params; 220 } SetRemoteIceParameters(const IceParameters & params)221 void SetRemoteIceParameters(const IceParameters& params) override { 222 RTC_DCHECK_RUN_ON(network_thread_); 223 remote_ice_parameters_ = params; 224 } 225 SetRemoteIceMode(IceMode mode)226 void SetRemoteIceMode(IceMode mode) override { 227 RTC_DCHECK_RUN_ON(network_thread_); 228 remote_ice_mode_ = mode; 229 } 230 MaybeStartGathering()231 void MaybeStartGathering() override { 232 RTC_DCHECK_RUN_ON(network_thread_); 233 if (gathering_state_ == kIceGatheringNew) { 234 gathering_state_ = kIceGatheringGathering; 235 SignalGatheringState(this); 236 } 237 } 238 gathering_state()239 IceGatheringState gathering_state() const override { 240 RTC_DCHECK_RUN_ON(network_thread_); 241 return gathering_state_; 242 } 243 SetIceConfig(const IceConfig & config)244 void SetIceConfig(const IceConfig& config) override { 245 RTC_DCHECK_RUN_ON(network_thread_); 246 ice_config_ = config; 247 } 248 AddRemoteCandidate(const Candidate & candidate)249 void AddRemoteCandidate(const Candidate& candidate) override { 250 RTC_DCHECK_RUN_ON(network_thread_); 251 remote_candidates_.push_back(candidate); 252 } RemoveRemoteCandidate(const Candidate & candidate)253 void RemoveRemoteCandidate(const Candidate& candidate) override { 254 RTC_DCHECK_RUN_ON(network_thread_); 255 auto it = absl::c_find(remote_candidates_, candidate); 256 if (it == remote_candidates_.end()) { 257 RTC_LOG(LS_INFO) << "Trying to remove a candidate which doesn't exist."; 258 return; 259 } 260 261 remote_candidates_.erase(it); 262 } 263 RemoveAllRemoteCandidates()264 void RemoveAllRemoteCandidates() override { 265 RTC_DCHECK_RUN_ON(network_thread_); 266 remote_candidates_.clear(); 267 } 268 GetStats(IceTransportStats * ice_transport_stats)269 bool GetStats(IceTransportStats* ice_transport_stats) override { 270 CandidateStats candidate_stats; 271 ConnectionInfo candidate_pair_stats; 272 ice_transport_stats->candidate_stats_list.clear(); 273 ice_transport_stats->candidate_stats_list.push_back(candidate_stats); 274 ice_transport_stats->connection_infos.clear(); 275 ice_transport_stats->connection_infos.push_back(candidate_pair_stats); 276 return true; 277 } 278 GetRttEstimate()279 absl::optional<int> GetRttEstimate() override { return absl::nullopt; } 280 selected_connection()281 const Connection* selected_connection() const override { return nullptr; } GetSelectedCandidatePair()282 absl::optional<const CandidatePair> GetSelectedCandidatePair() 283 const override { 284 return absl::nullopt; 285 } 286 287 // Fake PacketTransportInternal implementation. writable()288 bool writable() const override { 289 RTC_DCHECK_RUN_ON(network_thread_); 290 return writable_; 291 } receiving()292 bool receiving() const override { 293 RTC_DCHECK_RUN_ON(network_thread_); 294 return receiving_; 295 } 296 // If combine is enabled, every two consecutive packets to be sent with 297 // "SendPacket" will be combined into one outgoing packet. combine_outgoing_packets(bool combine)298 void combine_outgoing_packets(bool combine) { 299 RTC_DCHECK_RUN_ON(network_thread_); 300 combine_outgoing_packets_ = combine; 301 } SendPacket(const char * data,size_t len,const rtc::PacketOptions & options,int flags)302 int SendPacket(const char* data, 303 size_t len, 304 const rtc::PacketOptions& options, 305 int flags) override { 306 RTC_DCHECK_RUN_ON(network_thread_); 307 if (!dest_) { 308 return -1; 309 } 310 311 send_packet_.AppendData(data, len); 312 if (!combine_outgoing_packets_ || send_packet_.size() > len) { 313 rtc::CopyOnWriteBuffer packet(std::move(send_packet_)); 314 if (async_) { 315 network_thread_->PostDelayedTask( 316 SafeTask(task_safety_.flag(), 317 [this, packet] { 318 RTC_DCHECK_RUN_ON(network_thread_); 319 FakeIceTransport::SendPacketInternal(packet); 320 }), 321 TimeDelta::Millis(async_delay_ms_)); 322 } else { 323 SendPacketInternal(packet); 324 } 325 } 326 rtc::SentPacket sent_packet(options.packet_id, rtc::TimeMillis()); 327 SignalSentPacket(this, sent_packet); 328 return static_cast<int>(len); 329 } 330 SetOption(rtc::Socket::Option opt,int value)331 int SetOption(rtc::Socket::Option opt, int value) override { 332 RTC_DCHECK_RUN_ON(network_thread_); 333 socket_options_[opt] = value; 334 return true; 335 } GetOption(rtc::Socket::Option opt,int * value)336 bool GetOption(rtc::Socket::Option opt, int* value) override { 337 RTC_DCHECK_RUN_ON(network_thread_); 338 auto it = socket_options_.find(opt); 339 if (it != socket_options_.end()) { 340 *value = it->second; 341 return true; 342 } else { 343 return false; 344 } 345 } 346 GetError()347 int GetError() override { return 0; } 348 last_sent_packet()349 rtc::CopyOnWriteBuffer last_sent_packet() { 350 RTC_DCHECK_RUN_ON(network_thread_); 351 return last_sent_packet_; 352 } 353 network_route()354 absl::optional<rtc::NetworkRoute> network_route() const override { 355 RTC_DCHECK_RUN_ON(network_thread_); 356 return network_route_; 357 } SetNetworkRoute(absl::optional<rtc::NetworkRoute> network_route)358 void SetNetworkRoute(absl::optional<rtc::NetworkRoute> network_route) { 359 RTC_DCHECK_RUN_ON(network_thread_); 360 network_route_ = network_route; 361 SendTask(network_thread_, [this] { 362 RTC_DCHECK_RUN_ON(network_thread_); 363 SignalNetworkRouteChanged(network_route_); 364 }); 365 } 366 367 private: set_writable(bool writable)368 void set_writable(bool writable) 369 RTC_EXCLUSIVE_LOCKS_REQUIRED(network_thread_) { 370 if (writable_ == writable) { 371 return; 372 } 373 RTC_LOG(LS_INFO) << "Change writable_ to " << writable; 374 writable_ = writable; 375 if (writable_) { 376 SignalReadyToSend(this); 377 } 378 SignalWritableState(this); 379 } 380 set_receiving(bool receiving)381 void set_receiving(bool receiving) 382 RTC_EXCLUSIVE_LOCKS_REQUIRED(network_thread_) { 383 if (receiving_ == receiving) { 384 return; 385 } 386 receiving_ = receiving; 387 SignalReceivingState(this); 388 } 389 SendPacketInternal(const rtc::CopyOnWriteBuffer & packet)390 void SendPacketInternal(const rtc::CopyOnWriteBuffer& packet) 391 RTC_EXCLUSIVE_LOCKS_REQUIRED(network_thread_) { 392 if (dest_) { 393 last_sent_packet_ = packet; 394 dest_->SignalReadPacket(dest_, packet.data<char>(), packet.size(), 395 rtc::TimeMicros(), 0); 396 } 397 } 398 399 const std::string name_; 400 const int component_; 401 FakeIceTransport* dest_ RTC_GUARDED_BY(network_thread_) = nullptr; 402 bool async_ RTC_GUARDED_BY(network_thread_) = false; 403 int async_delay_ms_ RTC_GUARDED_BY(network_thread_) = 0; 404 Candidates remote_candidates_ RTC_GUARDED_BY(network_thread_); 405 IceConfig ice_config_ RTC_GUARDED_BY(network_thread_); 406 IceRole role_ RTC_GUARDED_BY(network_thread_) = ICEROLE_UNKNOWN; 407 uint64_t tiebreaker_ RTC_GUARDED_BY(network_thread_) = 0; 408 IceParameters ice_parameters_ RTC_GUARDED_BY(network_thread_); 409 IceParameters remote_ice_parameters_ RTC_GUARDED_BY(network_thread_); 410 IceMode remote_ice_mode_ RTC_GUARDED_BY(network_thread_) = ICEMODE_FULL; 411 size_t connection_count_ RTC_GUARDED_BY(network_thread_) = 0; 412 absl::optional<webrtc::IceTransportState> transport_state_ 413 RTC_GUARDED_BY(network_thread_); 414 absl::optional<IceTransportState> legacy_transport_state_ 415 RTC_GUARDED_BY(network_thread_); 416 IceGatheringState gathering_state_ RTC_GUARDED_BY(network_thread_) = 417 kIceGatheringNew; 418 bool had_connection_ RTC_GUARDED_BY(network_thread_) = false; 419 bool writable_ RTC_GUARDED_BY(network_thread_) = false; 420 bool receiving_ RTC_GUARDED_BY(network_thread_) = false; 421 bool combine_outgoing_packets_ RTC_GUARDED_BY(network_thread_) = false; 422 rtc::CopyOnWriteBuffer send_packet_ RTC_GUARDED_BY(network_thread_); 423 absl::optional<rtc::NetworkRoute> network_route_ 424 RTC_GUARDED_BY(network_thread_); 425 std::map<rtc::Socket::Option, int> socket_options_ 426 RTC_GUARDED_BY(network_thread_); 427 rtc::CopyOnWriteBuffer last_sent_packet_ RTC_GUARDED_BY(network_thread_); 428 rtc::Thread* const network_thread_; 429 webrtc::ScopedTaskSafetyDetached task_safety_; 430 }; 431 432 class FakeIceTransportWrapper : public webrtc::IceTransportInterface { 433 public: FakeIceTransportWrapper(std::unique_ptr<cricket::FakeIceTransport> internal)434 explicit FakeIceTransportWrapper( 435 std::unique_ptr<cricket::FakeIceTransport> internal) 436 : internal_(std::move(internal)) {} 437 internal()438 cricket::IceTransportInternal* internal() override { return internal_.get(); } 439 440 private: 441 std::unique_ptr<cricket::FakeIceTransport> internal_; 442 }; 443 444 } // namespace cricket 445 446 #endif // P2P_BASE_FAKE_ICE_TRANSPORT_H_ 447