1 /*
2  *  Copyright 2018 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 PC_TEST_FAKE_PEER_CONNECTION_FOR_STATS_H_
12 #define PC_TEST_FAKE_PEER_CONNECTION_FOR_STATS_H_
13 
14 #include <map>
15 #include <memory>
16 #include <set>
17 #include <string>
18 #include <utility>
19 #include <vector>
20 
21 #include "media/base/fake_media_engine.h"
22 #include "pc/stream_collection.h"
23 #include "pc/test/fake_data_channel_provider.h"
24 #include "pc/test/fake_peer_connection_base.h"
25 
26 namespace webrtc {
27 
28 // Fake VoiceMediaChannel where the result of GetStats can be configured.
29 class FakeVoiceMediaChannelForStats : public cricket::FakeVoiceMediaChannel {
30  public:
FakeVoiceMediaChannelForStats()31   FakeVoiceMediaChannelForStats()
32       : cricket::FakeVoiceMediaChannel(nullptr, cricket::AudioOptions()) {}
33 
SetStats(const cricket::VoiceMediaInfo & voice_info)34   void SetStats(const cricket::VoiceMediaInfo& voice_info) {
35     stats_ = voice_info;
36   }
37 
38   // VoiceMediaChannel overrides.
GetStats(cricket::VoiceMediaInfo * info)39   bool GetStats(cricket::VoiceMediaInfo* info) override {
40     if (stats_) {
41       *info = *stats_;
42       return true;
43     }
44     return false;
45   }
46 
47  private:
48   absl::optional<cricket::VoiceMediaInfo> stats_;
49 };
50 
51 // Fake VideoMediaChannel where the result of GetStats can be configured.
52 class FakeVideoMediaChannelForStats : public cricket::FakeVideoMediaChannel {
53  public:
FakeVideoMediaChannelForStats()54   FakeVideoMediaChannelForStats()
55       : cricket::FakeVideoMediaChannel(nullptr, cricket::VideoOptions()) {}
56 
SetStats(const cricket::VideoMediaInfo & video_info)57   void SetStats(const cricket::VideoMediaInfo& video_info) {
58     stats_ = video_info;
59   }
60 
61   // VideoMediaChannel overrides.
GetStats(cricket::VideoMediaInfo * info)62   bool GetStats(cricket::VideoMediaInfo* info) override {
63     if (stats_) {
64       *info = *stats_;
65       return true;
66     }
67     return false;
68   }
69 
70  private:
71   absl::optional<cricket::VideoMediaInfo> stats_;
72 };
73 
74 constexpr bool kDefaultRtcpMuxRequired = true;
75 constexpr bool kDefaultSrtpRequired = true;
76 
77 // This class is intended to be fed into the StatsCollector and
78 // RTCStatsCollector so that the stats functionality can be unit tested.
79 // Individual tests can configure this fake as needed to simulate scenarios
80 // under which to test the stats collectors.
81 class FakePeerConnectionForStats : public FakePeerConnectionBase {
82  public:
83   // TODO(steveanton): Add support for specifying separate threads to test
84   // multi-threading correctness.
FakePeerConnectionForStats()85   FakePeerConnectionForStats()
86       : network_thread_(rtc::Thread::Current()),
87         worker_thread_(rtc::Thread::Current()),
88         signaling_thread_(rtc::Thread::Current()),
89         local_streams_(StreamCollection::Create()),
90         remote_streams_(StreamCollection::Create()) {}
91 
mutable_local_streams()92   rtc::scoped_refptr<StreamCollection> mutable_local_streams() {
93     return local_streams_;
94   }
95 
mutable_remote_streams()96   rtc::scoped_refptr<StreamCollection> mutable_remote_streams() {
97     return remote_streams_;
98   }
99 
AddSender(rtc::scoped_refptr<RtpSenderInternal> sender)100   rtc::scoped_refptr<RtpSenderInterface> AddSender(
101       rtc::scoped_refptr<RtpSenderInternal> sender) {
102     // TODO(steveanton): Switch tests to use RtpTransceivers directly.
103     auto sender_proxy = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
104         signaling_thread_, sender);
105     GetOrCreateFirstTransceiverOfType(sender->media_type())
106         ->internal()
107         ->AddSender(sender_proxy);
108     return sender_proxy;
109   }
110 
RemoveSender(rtc::scoped_refptr<RtpSenderInterface> sender)111   void RemoveSender(rtc::scoped_refptr<RtpSenderInterface> sender) {
112     GetOrCreateFirstTransceiverOfType(sender->media_type())
113         ->internal()
114         ->RemoveSender(sender);
115   }
116 
AddReceiver(rtc::scoped_refptr<RtpReceiverInternal> receiver)117   rtc::scoped_refptr<RtpReceiverInterface> AddReceiver(
118       rtc::scoped_refptr<RtpReceiverInternal> receiver) {
119     // TODO(steveanton): Switch tests to use RtpTransceivers directly.
120     auto receiver_proxy =
121         RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
122             signaling_thread_, receiver);
123     GetOrCreateFirstTransceiverOfType(receiver->media_type())
124         ->internal()
125         ->AddReceiver(receiver_proxy);
126     return receiver_proxy;
127   }
128 
RemoveReceiver(rtc::scoped_refptr<RtpReceiverInterface> receiver)129   void RemoveReceiver(rtc::scoped_refptr<RtpReceiverInterface> receiver) {
130     GetOrCreateFirstTransceiverOfType(receiver->media_type())
131         ->internal()
132         ->RemoveReceiver(receiver);
133   }
134 
AddVoiceChannel(const std::string & mid,const std::string & transport_name)135   FakeVoiceMediaChannelForStats* AddVoiceChannel(
136       const std::string& mid,
137       const std::string& transport_name) {
138     RTC_DCHECK(!voice_channel_);
139     auto voice_media_channel =
140         std::make_unique<FakeVoiceMediaChannelForStats>();
141     auto* voice_media_channel_ptr = voice_media_channel.get();
142     voice_channel_ = std::make_unique<cricket::VoiceChannel>(
143         worker_thread_, network_thread_, signaling_thread_,
144         std::move(voice_media_channel), mid, kDefaultSrtpRequired,
145         webrtc::CryptoOptions(), &ssrc_generator_);
146     voice_channel_->set_transport_name_for_testing(transport_name);
147     GetOrCreateFirstTransceiverOfType(cricket::MEDIA_TYPE_AUDIO)
148         ->internal()
149         ->SetChannel(voice_channel_.get());
150     return voice_media_channel_ptr;
151   }
152 
AddVideoChannel(const std::string & mid,const std::string & transport_name)153   FakeVideoMediaChannelForStats* AddVideoChannel(
154       const std::string& mid,
155       const std::string& transport_name) {
156     RTC_DCHECK(!video_channel_);
157     auto video_media_channel =
158         std::make_unique<FakeVideoMediaChannelForStats>();
159     auto video_media_channel_ptr = video_media_channel.get();
160     video_channel_ = std::make_unique<cricket::VideoChannel>(
161         worker_thread_, network_thread_, signaling_thread_,
162         std::move(video_media_channel), mid, kDefaultSrtpRequired,
163         webrtc::CryptoOptions(), &ssrc_generator_);
164     video_channel_->set_transport_name_for_testing(transport_name);
165     GetOrCreateFirstTransceiverOfType(cricket::MEDIA_TYPE_VIDEO)
166         ->internal()
167         ->SetChannel(video_channel_.get());
168     return video_media_channel_ptr;
169   }
170 
AddSctpDataChannel(const std::string & label)171   void AddSctpDataChannel(const std::string& label) {
172     AddSctpDataChannel(label, InternalDataChannelInit());
173   }
174 
AddSctpDataChannel(const std::string & label,const InternalDataChannelInit & init)175   void AddSctpDataChannel(const std::string& label,
176                           const InternalDataChannelInit& init) {
177     // TODO(bugs.webrtc.org/11547): Supply a separate network thread.
178     AddSctpDataChannel(SctpDataChannel::Create(&data_channel_provider_, label,
179                                                init, rtc::Thread::Current(),
180                                                rtc::Thread::Current()));
181   }
182 
AddSctpDataChannel(rtc::scoped_refptr<SctpDataChannel> data_channel)183   void AddSctpDataChannel(rtc::scoped_refptr<SctpDataChannel> data_channel) {
184     sctp_data_channels_.push_back(data_channel);
185   }
186 
SetTransportStats(const std::string & transport_name,const cricket::TransportChannelStats & channel_stats)187   void SetTransportStats(const std::string& transport_name,
188                          const cricket::TransportChannelStats& channel_stats) {
189     SetTransportStats(
190         transport_name,
191         std::vector<cricket::TransportChannelStats>{channel_stats});
192   }
193 
SetTransportStats(const std::string & transport_name,const std::vector<cricket::TransportChannelStats> & channel_stats_list)194   void SetTransportStats(
195       const std::string& transport_name,
196       const std::vector<cricket::TransportChannelStats>& channel_stats_list) {
197     cricket::TransportStats transport_stats;
198     transport_stats.transport_name = transport_name;
199     transport_stats.channel_stats = channel_stats_list;
200     transport_stats_by_name_[transport_name] = transport_stats;
201   }
202 
SetCallStats(const Call::Stats & call_stats)203   void SetCallStats(const Call::Stats& call_stats) { call_stats_ = call_stats; }
204 
SetLocalCertificate(const std::string & transport_name,rtc::scoped_refptr<rtc::RTCCertificate> certificate)205   void SetLocalCertificate(
206       const std::string& transport_name,
207       rtc::scoped_refptr<rtc::RTCCertificate> certificate) {
208     local_certificates_by_transport_[transport_name] = certificate;
209   }
210 
SetRemoteCertChain(const std::string & transport_name,std::unique_ptr<rtc::SSLCertChain> chain)211   void SetRemoteCertChain(const std::string& transport_name,
212                           std::unique_ptr<rtc::SSLCertChain> chain) {
213     remote_cert_chains_by_transport_[transport_name] = std::move(chain);
214   }
215 
216   // PeerConnectionInterface overrides.
217 
local_streams()218   rtc::scoped_refptr<StreamCollectionInterface> local_streams() override {
219     return local_streams_;
220   }
221 
remote_streams()222   rtc::scoped_refptr<StreamCollectionInterface> remote_streams() override {
223     return remote_streams_;
224   }
225 
GetSenders()226   std::vector<rtc::scoped_refptr<RtpSenderInterface>> GetSenders()
227       const override {
228     std::vector<rtc::scoped_refptr<RtpSenderInterface>> senders;
229     for (auto transceiver : transceivers_) {
230       for (auto sender : transceiver->internal()->senders()) {
231         senders.push_back(sender);
232       }
233     }
234     return senders;
235   }
236 
GetReceivers()237   std::vector<rtc::scoped_refptr<RtpReceiverInterface>> GetReceivers()
238       const override {
239     std::vector<rtc::scoped_refptr<RtpReceiverInterface>> receivers;
240     for (auto transceiver : transceivers_) {
241       for (auto receiver : transceiver->internal()->receivers()) {
242         receivers.push_back(receiver);
243       }
244     }
245     return receivers;
246   }
247 
248   // PeerConnectionInternal overrides.
249 
network_thread()250   rtc::Thread* network_thread() const override { return network_thread_; }
251 
worker_thread()252   rtc::Thread* worker_thread() const override { return worker_thread_; }
253 
signaling_thread()254   rtc::Thread* signaling_thread() const override { return signaling_thread_; }
255 
256   std::vector<
257       rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
GetTransceiversInternal()258   GetTransceiversInternal() const override {
259     return transceivers_;
260   }
261 
GetDataChannelStats()262   std::vector<DataChannelStats> GetDataChannelStats() const override {
263     RTC_DCHECK_RUN_ON(signaling_thread());
264     std::vector<DataChannelStats> stats;
265     for (const auto& channel : sctp_data_channels_)
266       stats.push_back(channel->GetStats());
267     return stats;
268   }
269 
GetPooledCandidateStats()270   cricket::CandidateStatsList GetPooledCandidateStats() const override {
271     return {};
272   }
273 
GetTransportNamesByMid()274   std::map<std::string, std::string> GetTransportNamesByMid() const override {
275     std::map<std::string, std::string> transport_names_by_mid;
276     if (voice_channel_) {
277       transport_names_by_mid[voice_channel_->content_name()] =
278           voice_channel_->transport_name();
279     }
280     if (video_channel_) {
281       transport_names_by_mid[video_channel_->content_name()] =
282           video_channel_->transport_name();
283     }
284     return transport_names_by_mid;
285   }
286 
GetTransportStatsByNames(const std::set<std::string> & transport_names)287   std::map<std::string, cricket::TransportStats> GetTransportStatsByNames(
288       const std::set<std::string>& transport_names) override {
289     std::map<std::string, cricket::TransportStats> transport_stats_by_name;
290     for (const std::string& transport_name : transport_names) {
291       transport_stats_by_name[transport_name] =
292           GetTransportStatsByName(transport_name);
293     }
294     return transport_stats_by_name;
295   }
296 
GetCallStats()297   Call::Stats GetCallStats() override { return call_stats_; }
298 
GetLocalCertificate(const std::string & transport_name,rtc::scoped_refptr<rtc::RTCCertificate> * certificate)299   bool GetLocalCertificate(
300       const std::string& transport_name,
301       rtc::scoped_refptr<rtc::RTCCertificate>* certificate) override {
302     auto it = local_certificates_by_transport_.find(transport_name);
303     if (it != local_certificates_by_transport_.end()) {
304       *certificate = it->second;
305       return true;
306     } else {
307       return false;
308     }
309   }
310 
GetRemoteSSLCertChain(const std::string & transport_name)311   std::unique_ptr<rtc::SSLCertChain> GetRemoteSSLCertChain(
312       const std::string& transport_name) override {
313     auto it = remote_cert_chains_by_transport_.find(transport_name);
314     if (it != remote_cert_chains_by_transport_.end()) {
315       return it->second->Clone();
316     } else {
317       return nullptr;
318     }
319   }
320 
321  private:
GetTransportStatsByName(const std::string & transport_name)322   cricket::TransportStats GetTransportStatsByName(
323       const std::string& transport_name) {
324     auto it = transport_stats_by_name_.find(transport_name);
325     if (it != transport_stats_by_name_.end()) {
326       // If specific transport stats have been specified, return those.
327       return it->second;
328     }
329     // Otherwise, generate some dummy stats.
330     cricket::TransportChannelStats channel_stats;
331     channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
332     cricket::TransportStats transport_stats;
333     transport_stats.transport_name = transport_name;
334     transport_stats.channel_stats.push_back(channel_stats);
335     return transport_stats;
336   }
337 
338   rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
GetOrCreateFirstTransceiverOfType(cricket::MediaType media_type)339   GetOrCreateFirstTransceiverOfType(cricket::MediaType media_type) {
340     for (auto transceiver : transceivers_) {
341       if (transceiver->internal()->media_type() == media_type) {
342         return transceiver;
343       }
344     }
345     auto transceiver = RtpTransceiverProxyWithInternal<RtpTransceiver>::Create(
346         signaling_thread_, new RtpTransceiver(media_type));
347     transceivers_.push_back(transceiver);
348     return transceiver;
349   }
350 
351   rtc::Thread* const network_thread_;
352   rtc::Thread* const worker_thread_;
353   rtc::Thread* const signaling_thread_;
354 
355   rtc::scoped_refptr<StreamCollection> local_streams_;
356   rtc::scoped_refptr<StreamCollection> remote_streams_;
357 
358   std::vector<
359       rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
360       transceivers_;
361 
362   FakeDataChannelProvider data_channel_provider_;
363 
364   std::unique_ptr<cricket::VoiceChannel> voice_channel_;
365   std::unique_ptr<cricket::VideoChannel> video_channel_;
366 
367   std::vector<rtc::scoped_refptr<SctpDataChannel>> sctp_data_channels_;
368 
369   std::map<std::string, cricket::TransportStats> transport_stats_by_name_;
370 
371   Call::Stats call_stats_;
372 
373   std::map<std::string, rtc::scoped_refptr<rtc::RTCCertificate>>
374       local_certificates_by_transport_;
375   std::map<std::string, std::unique_ptr<rtc::SSLCertChain>>
376       remote_cert_chains_by_transport_;
377 
378   rtc::UniqueRandomIdGenerator ssrc_generator_;
379 };
380 
381 }  // namespace webrtc
382 
383 #endif  // PC_TEST_FAKE_PEER_CONNECTION_FOR_STATS_H_
384