OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2016 The WebRTC Project Authors. All rights reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/api/rtcstatscollector.h" | 11 #include "webrtc/api/rtcstatscollector.h" |
12 | 12 |
13 #include <memory> | 13 #include <memory> |
14 #include <utility> | 14 #include <utility> |
15 #include <vector> | 15 #include <vector> |
16 | 16 |
17 #include "webrtc/api/peerconnection.h" | 17 #include "webrtc/api/peerconnection.h" |
18 #include "webrtc/api/webrtcsession.h" | 18 #include "webrtc/api/webrtcsession.h" |
19 #include "webrtc/base/checks.h" | 19 #include "webrtc/base/checks.h" |
20 #include "webrtc/base/sslidentity.h" | |
21 #include "webrtc/p2p/base/candidate.h" | 20 #include "webrtc/p2p/base/candidate.h" |
| 21 #include "webrtc/p2p/base/p2pconstants.h" |
22 #include "webrtc/p2p/base/port.h" | 22 #include "webrtc/p2p/base/port.h" |
23 | 23 |
24 namespace webrtc { | 24 namespace webrtc { |
25 | 25 |
26 namespace { | 26 namespace { |
27 | 27 |
| 28 std::string RTCCertificateIDFromFingerprint(const std::string& fingerprint) { |
| 29 return "RTCCertificate_" + fingerprint; |
| 30 } |
| 31 |
| 32 std::string RTCIceCandidatePairStatsIDFromConnectionInfo( |
| 33 const cricket::ConnectionInfo& info) { |
| 34 return "RTCIceCandidatePair_" + info.local_candidate.id() + "_" + |
| 35 info.remote_candidate.id(); |
| 36 } |
| 37 |
| 38 std::string RTCTransportStatsIDFromTransportChannel( |
| 39 const std::string& transport_name, int channel_component) { |
| 40 return "RTCTransport_" + transport_name + "_" + |
| 41 rtc::ToString<>(channel_component); |
| 42 } |
| 43 |
28 const char* CandidateTypeToRTCIceCandidateType(const std::string& type) { | 44 const char* CandidateTypeToRTCIceCandidateType(const std::string& type) { |
29 if (type == cricket::LOCAL_PORT_TYPE) | 45 if (type == cricket::LOCAL_PORT_TYPE) |
30 return RTCIceCandidateType::kHost; | 46 return RTCIceCandidateType::kHost; |
31 if (type == cricket::STUN_PORT_TYPE) | 47 if (type == cricket::STUN_PORT_TYPE) |
32 return RTCIceCandidateType::kSrflx; | 48 return RTCIceCandidateType::kSrflx; |
33 if (type == cricket::PRFLX_PORT_TYPE) | 49 if (type == cricket::PRFLX_PORT_TYPE) |
34 return RTCIceCandidateType::kPrflx; | 50 return RTCIceCandidateType::kPrflx; |
35 if (type == cricket::RELAY_PORT_TYPE) | 51 if (type == cricket::RELAY_PORT_TYPE) |
36 return RTCIceCandidateType::kRelay; | 52 return RTCIceCandidateType::kRelay; |
37 RTC_NOTREACHED(); | 53 RTC_NOTREACHED(); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 cached_report_ = nullptr; | 137 cached_report_ = nullptr; |
122 } | 138 } |
123 | 139 |
124 void RTCStatsCollector::ProducePartialResultsOnSignalingThread( | 140 void RTCStatsCollector::ProducePartialResultsOnSignalingThread( |
125 int64_t timestamp_us) { | 141 int64_t timestamp_us) { |
126 RTC_DCHECK(signaling_thread_->IsCurrent()); | 142 RTC_DCHECK(signaling_thread_->IsCurrent()); |
127 rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create(); | 143 rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create(); |
128 | 144 |
129 SessionStats session_stats; | 145 SessionStats session_stats; |
130 if (pc_->session()->GetTransportStats(&session_stats)) { | 146 if (pc_->session()->GetTransportStats(&session_stats)) { |
131 ProduceCertificateStats_s(timestamp_us, session_stats, report.get()); | 147 std::map<std::string, CertificateStatsPair> transport_cert_stats = |
132 ProduceIceCandidateAndPairStats_s(timestamp_us, session_stats, | 148 PrepareTransportCertificateStats_s(session_stats); |
133 report.get()); | 149 |
| 150 ProduceCertificateStats_s( |
| 151 timestamp_us, transport_cert_stats, report.get()); |
| 152 ProduceIceCandidateAndPairStats_s( |
| 153 timestamp_us, session_stats, report.get()); |
| 154 ProduceTransportStats_s( |
| 155 timestamp_us, session_stats, transport_cert_stats, report.get()); |
134 } | 156 } |
135 ProduceDataChannelStats_s(timestamp_us, report.get()); | 157 ProduceDataChannelStats_s(timestamp_us, report.get()); |
136 ProducePeerConnectionStats_s(timestamp_us, report.get()); | 158 ProducePeerConnectionStats_s(timestamp_us, report.get()); |
137 | 159 |
138 AddPartialResults(report); | 160 AddPartialResults(report); |
139 } | 161 } |
140 | 162 |
141 void RTCStatsCollector::ProducePartialResultsOnWorkerThread( | 163 void RTCStatsCollector::ProducePartialResultsOnWorkerThread( |
142 int64_t timestamp_us) { | 164 int64_t timestamp_us) { |
143 RTC_DCHECK(worker_thread_->IsCurrent()); | 165 RTC_DCHECK(worker_thread_->IsCurrent()); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 RTC_DCHECK(!callbacks_.empty()); | 214 RTC_DCHECK(!callbacks_.empty()); |
193 RTC_DCHECK(cached_report_); | 215 RTC_DCHECK(cached_report_); |
194 for (const rtc::scoped_refptr<RTCStatsCollectorCallback>& callback : | 216 for (const rtc::scoped_refptr<RTCStatsCollectorCallback>& callback : |
195 callbacks_) { | 217 callbacks_) { |
196 callback->OnStatsDelivered(cached_report_); | 218 callback->OnStatsDelivered(cached_report_); |
197 } | 219 } |
198 callbacks_.clear(); | 220 callbacks_.clear(); |
199 } | 221 } |
200 | 222 |
201 void RTCStatsCollector::ProduceCertificateStats_s( | 223 void RTCStatsCollector::ProduceCertificateStats_s( |
202 int64_t timestamp_us, const SessionStats& session_stats, | 224 int64_t timestamp_us, |
| 225 const std::map<std::string, CertificateStatsPair>& transport_cert_stats, |
203 RTCStatsReport* report) const { | 226 RTCStatsReport* report) const { |
204 RTC_DCHECK(signaling_thread_->IsCurrent()); | 227 RTC_DCHECK(signaling_thread_->IsCurrent()); |
205 for (const auto& transport_stats : session_stats.transport_stats) { | 228 for (const auto& kvp : transport_cert_stats) { |
206 rtc::scoped_refptr<rtc::RTCCertificate> local_certificate; | 229 if (kvp.second.local) { |
207 if (pc_->session()->GetLocalCertificate( | 230 ProduceCertificateStatsFromSSLCertificateStats_s( |
208 transport_stats.second.transport_name, &local_certificate)) { | 231 timestamp_us, *kvp.second.local.get(), report); |
209 ProduceCertificateStatsFromSSLCertificateAndChain_s( | |
210 timestamp_us, local_certificate->ssl_certificate(), report); | |
211 } | 232 } |
212 std::unique_ptr<rtc::SSLCertificate> remote_certificate = | 233 if (kvp.second.remote) { |
213 pc_->session()->GetRemoteSSLCertificate( | 234 ProduceCertificateStatsFromSSLCertificateStats_s( |
214 transport_stats.second.transport_name); | 235 timestamp_us, *kvp.second.remote.get(), report); |
215 if (remote_certificate) { | |
216 ProduceCertificateStatsFromSSLCertificateAndChain_s( | |
217 timestamp_us, *remote_certificate.get(), report); | |
218 } | 236 } |
219 } | 237 } |
220 } | 238 } |
221 | 239 |
222 void RTCStatsCollector::ProduceCertificateStatsFromSSLCertificateAndChain_s( | 240 void RTCStatsCollector::ProduceCertificateStatsFromSSLCertificateStats_s( |
223 int64_t timestamp_us, const rtc::SSLCertificate& certificate, | 241 int64_t timestamp_us, const rtc::SSLCertificateStats& certificate_stats, |
224 RTCStatsReport* report) const { | 242 RTCStatsReport* report) const { |
225 RTC_DCHECK(signaling_thread_->IsCurrent()); | 243 RTC_DCHECK(signaling_thread_->IsCurrent()); |
226 std::unique_ptr<rtc::SSLCertificateStats> ssl_stats = | 244 RTCCertificateStats* prev_certificate_stats = nullptr; |
227 certificate.GetStats(); | 245 for (const rtc::SSLCertificateStats* s = &certificate_stats; s; |
228 RTCCertificateStats* prev_stats = nullptr; | |
229 for (rtc::SSLCertificateStats* s = ssl_stats.get(); s; | |
230 s = s->issuer.get()) { | 246 s = s->issuer.get()) { |
231 RTCCertificateStats* stats = new RTCCertificateStats( | 247 RTCCertificateStats* certificate_stats = new RTCCertificateStats( |
232 "RTCCertificate_" + s->fingerprint, timestamp_us); | 248 RTCCertificateIDFromFingerprint(s->fingerprint), timestamp_us); |
233 stats->fingerprint = s->fingerprint; | 249 certificate_stats->fingerprint = s->fingerprint; |
234 stats->fingerprint_algorithm = s->fingerprint_algorithm; | 250 certificate_stats->fingerprint_algorithm = s->fingerprint_algorithm; |
235 stats->base64_certificate = s->base64_certificate; | 251 certificate_stats->base64_certificate = s->base64_certificate; |
236 if (prev_stats) | 252 if (prev_certificate_stats) |
237 prev_stats->issuer_certificate_id = stats->id(); | 253 prev_certificate_stats->issuer_certificate_id = certificate_stats->id(); |
238 report->AddStats(std::unique_ptr<RTCCertificateStats>(stats)); | 254 report->AddStats(std::unique_ptr<RTCCertificateStats>(certificate_stats)); |
239 prev_stats = stats; | 255 prev_certificate_stats = certificate_stats; |
240 } | 256 } |
241 } | 257 } |
242 | 258 |
243 void RTCStatsCollector::ProduceDataChannelStats_s( | 259 void RTCStatsCollector::ProduceDataChannelStats_s( |
244 int64_t timestamp_us, RTCStatsReport* report) const { | 260 int64_t timestamp_us, RTCStatsReport* report) const { |
245 RTC_DCHECK(signaling_thread_->IsCurrent()); | 261 RTC_DCHECK(signaling_thread_->IsCurrent()); |
246 for (const rtc::scoped_refptr<DataChannel>& data_channel : | 262 for (const rtc::scoped_refptr<DataChannel>& data_channel : |
247 pc_->sctp_data_channels()) { | 263 pc_->sctp_data_channels()) { |
248 std::unique_ptr<RTCDataChannelStats> data_channel_stats( | 264 std::unique_ptr<RTCDataChannelStats> data_channel_stats( |
249 new RTCDataChannelStats( | 265 new RTCDataChannelStats( |
(...skipping 13 matching lines...) Expand all Loading... |
263 } | 279 } |
264 | 280 |
265 void RTCStatsCollector::ProduceIceCandidateAndPairStats_s( | 281 void RTCStatsCollector::ProduceIceCandidateAndPairStats_s( |
266 int64_t timestamp_us, const SessionStats& session_stats, | 282 int64_t timestamp_us, const SessionStats& session_stats, |
267 RTCStatsReport* report) const { | 283 RTCStatsReport* report) const { |
268 RTC_DCHECK(signaling_thread_->IsCurrent()); | 284 RTC_DCHECK(signaling_thread_->IsCurrent()); |
269 for (const auto& transport_stats : session_stats.transport_stats) { | 285 for (const auto& transport_stats : session_stats.transport_stats) { |
270 for (const auto& channel_stats : transport_stats.second.channel_stats) { | 286 for (const auto& channel_stats : transport_stats.second.channel_stats) { |
271 for (const cricket::ConnectionInfo& info : | 287 for (const cricket::ConnectionInfo& info : |
272 channel_stats.connection_infos) { | 288 channel_stats.connection_infos) { |
273 const std::string& id = "RTCIceCandidatePair_" + | |
274 info.local_candidate.id() + "_" + info.remote_candidate.id(); | |
275 std::unique_ptr<RTCIceCandidatePairStats> candidate_pair_stats( | 289 std::unique_ptr<RTCIceCandidatePairStats> candidate_pair_stats( |
276 new RTCIceCandidatePairStats(id, timestamp_us)); | 290 new RTCIceCandidatePairStats( |
| 291 RTCIceCandidatePairStatsIDFromConnectionInfo(info), |
| 292 timestamp_us)); |
277 | 293 |
278 // TODO(hbos): Set all of the |RTCIceCandidatePairStats|'s members, | 294 // TODO(hbos): Set all of the |RTCIceCandidatePairStats|'s members, |
279 // crbug.com/633550. | 295 // crbug.com/633550. |
280 | 296 |
281 // TODO(hbos): Set candidate_pair_stats->transport_id. Should be ID to | 297 // TODO(hbos): Set candidate_pair_stats->transport_id. Should be ID to |
282 // RTCTransportStats which does not exist yet: crbug.com/653873. | 298 // RTCTransportStats which does not exist yet: crbug.com/653873. |
283 | 299 |
284 // TODO(hbos): There could be other candidates that are not paired with | 300 // TODO(hbos): There could be other candidates that are not paired with |
285 // anything. We don't have a complete list. Local candidates come from | 301 // anything. We don't have a complete list. Local candidates come from |
286 // Port objects, and prflx candidates (both local and remote) are only | 302 // Port objects, and prflx candidates (both local and remote) are only |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
374 // There is always just one |RTCPeerConnectionStats| so its |id| can be a | 390 // There is always just one |RTCPeerConnectionStats| so its |id| can be a |
375 // constant. | 391 // constant. |
376 std::unique_ptr<RTCPeerConnectionStats> stats( | 392 std::unique_ptr<RTCPeerConnectionStats> stats( |
377 new RTCPeerConnectionStats("RTCPeerConnection", timestamp_us)); | 393 new RTCPeerConnectionStats("RTCPeerConnection", timestamp_us)); |
378 stats->data_channels_opened = data_channels_opened; | 394 stats->data_channels_opened = data_channels_opened; |
379 stats->data_channels_closed = static_cast<uint32_t>(data_channels.size()) - | 395 stats->data_channels_closed = static_cast<uint32_t>(data_channels.size()) - |
380 data_channels_opened; | 396 data_channels_opened; |
381 report->AddStats(std::move(stats)); | 397 report->AddStats(std::move(stats)); |
382 } | 398 } |
383 | 399 |
| 400 void RTCStatsCollector::ProduceTransportStats_s( |
| 401 int64_t timestamp_us, const SessionStats& session_stats, |
| 402 const std::map<std::string, CertificateStatsPair>& transport_cert_stats, |
| 403 RTCStatsReport* report) const { |
| 404 RTC_DCHECK(signaling_thread_->IsCurrent()); |
| 405 for (const auto& transport : session_stats.transport_stats) { |
| 406 // Get reference to RTCP channel, if it exists. |
| 407 std::string rtcp_transport_stats_id; |
| 408 for (const auto& channel_stats : transport.second.channel_stats) { |
| 409 if (channel_stats.component == |
| 410 cricket::ICE_CANDIDATE_COMPONENT_RTCP) { |
| 411 rtcp_transport_stats_id = RTCTransportStatsIDFromTransportChannel( |
| 412 transport.second.transport_name, channel_stats.component); |
| 413 break; |
| 414 } |
| 415 } |
| 416 |
| 417 // Get reference to local and remote certificates of this transport, if they |
| 418 // exist. |
| 419 const auto& certificate_stats_it = transport_cert_stats.find( |
| 420 transport.second.transport_name); |
| 421 RTC_DCHECK(certificate_stats_it != transport_cert_stats.cend()); |
| 422 std::string local_certificate_id; |
| 423 if (certificate_stats_it->second.local) { |
| 424 local_certificate_id = RTCCertificateIDFromFingerprint( |
| 425 certificate_stats_it->second.local->fingerprint); |
| 426 } |
| 427 std::string remote_certificate_id; |
| 428 if (certificate_stats_it->second.remote) { |
| 429 remote_certificate_id = RTCCertificateIDFromFingerprint( |
| 430 certificate_stats_it->second.remote->fingerprint); |
| 431 } |
| 432 |
| 433 // There is one transport stats for each channel. |
| 434 for (const auto& channel_stats : transport.second.channel_stats) { |
| 435 std::unique_ptr<RTCTransportStats> transport_stats( |
| 436 new RTCTransportStats( |
| 437 RTCTransportStatsIDFromTransportChannel( |
| 438 transport.second.transport_name, channel_stats.component), |
| 439 timestamp_us)); |
| 440 transport_stats->bytes_sent = 0; |
| 441 transport_stats->bytes_received = 0; |
| 442 transport_stats->active_connection = false; |
| 443 for (const cricket::ConnectionInfo& info : |
| 444 channel_stats.connection_infos) { |
| 445 *transport_stats->bytes_sent += info.sent_total_bytes; |
| 446 *transport_stats->bytes_received += info.recv_total_bytes; |
| 447 if (info.best_connection) { |
| 448 transport_stats->active_connection = true; |
| 449 transport_stats->selected_candidate_pair_id = |
| 450 RTCIceCandidatePairStatsIDFromConnectionInfo(info); |
| 451 } |
| 452 } |
| 453 if (channel_stats.component != cricket::ICE_CANDIDATE_COMPONENT_RTCP && |
| 454 !rtcp_transport_stats_id.empty()) { |
| 455 transport_stats->rtcp_transport_stats_id = rtcp_transport_stats_id; |
| 456 } |
| 457 if (!local_certificate_id.empty()) |
| 458 transport_stats->local_certificate_id = local_certificate_id; |
| 459 if (!remote_certificate_id.empty()) |
| 460 transport_stats->remote_certificate_id = remote_certificate_id; |
| 461 report->AddStats(std::move(transport_stats)); |
| 462 } |
| 463 } |
| 464 } |
| 465 |
| 466 std::map<std::string, RTCStatsCollector::CertificateStatsPair> |
| 467 RTCStatsCollector::PrepareTransportCertificateStats_s( |
| 468 const SessionStats& session_stats) const { |
| 469 RTC_DCHECK(signaling_thread_->IsCurrent()); |
| 470 std::map<std::string, CertificateStatsPair> transport_cert_stats; |
| 471 for (const auto& transport_stats : session_stats.transport_stats) { |
| 472 CertificateStatsPair certificate_stats_pair; |
| 473 rtc::scoped_refptr<rtc::RTCCertificate> local_certificate; |
| 474 if (pc_->session()->GetLocalCertificate( |
| 475 transport_stats.second.transport_name, &local_certificate)) { |
| 476 certificate_stats_pair.local = |
| 477 local_certificate->ssl_certificate().GetStats(); |
| 478 } |
| 479 std::unique_ptr<rtc::SSLCertificate> remote_certificate = |
| 480 pc_->session()->GetRemoteSSLCertificate( |
| 481 transport_stats.second.transport_name); |
| 482 if (remote_certificate) { |
| 483 certificate_stats_pair.remote = remote_certificate->GetStats(); |
| 484 } |
| 485 transport_cert_stats.insert( |
| 486 std::make_pair(transport_stats.second.transport_name, |
| 487 std::move(certificate_stats_pair))); |
| 488 } |
| 489 return transport_cert_stats; |
| 490 } |
| 491 |
384 const char* CandidateTypeToRTCIceCandidateTypeForTesting( | 492 const char* CandidateTypeToRTCIceCandidateTypeForTesting( |
385 const std::string& type) { | 493 const std::string& type) { |
386 return CandidateTypeToRTCIceCandidateType(type); | 494 return CandidateTypeToRTCIceCandidateType(type); |
387 } | 495 } |
388 | 496 |
389 const char* DataStateToRTCDataChannelStateForTesting( | 497 const char* DataStateToRTCDataChannelStateForTesting( |
390 DataChannelInterface::DataState state) { | 498 DataChannelInterface::DataState state) { |
391 return DataStateToRTCDataChannelState(state); | 499 return DataStateToRTCDataChannelState(state); |
392 } | 500 } |
393 | 501 |
394 } // namespace webrtc | 502 } // namespace webrtc |
OLD | NEW |