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