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