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