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 { |
| 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 |
| 44 } // namespace |
| 45 |
26 const char* CandidateTypeToRTCIceCandidateType(const std::string& type) { | 46 const char* CandidateTypeToRTCIceCandidateType(const std::string& type) { |
27 if (type == cricket::LOCAL_PORT_TYPE) | 47 if (type == cricket::LOCAL_PORT_TYPE) |
28 return RTCIceCandidateType::kHost; | 48 return RTCIceCandidateType::kHost; |
29 if (type == cricket::STUN_PORT_TYPE) | 49 if (type == cricket::STUN_PORT_TYPE) |
30 return RTCIceCandidateType::kSrflx; | 50 return RTCIceCandidateType::kSrflx; |
31 if (type == cricket::PRFLX_PORT_TYPE) | 51 if (type == cricket::PRFLX_PORT_TYPE) |
32 return RTCIceCandidateType::kPrflx; | 52 return RTCIceCandidateType::kPrflx; |
33 if (type == cricket::RELAY_PORT_TYPE) | 53 if (type == cricket::RELAY_PORT_TYPE) |
34 return RTCIceCandidateType::kRelay; | 54 return RTCIceCandidateType::kRelay; |
35 RTC_NOTREACHED(); | 55 RTC_NOTREACHED(); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 cached_report_ = nullptr; | 120 cached_report_ = nullptr; |
101 } | 121 } |
102 | 122 |
103 void RTCStatsCollector::ProducePartialResultsOnSignalingThread( | 123 void RTCStatsCollector::ProducePartialResultsOnSignalingThread( |
104 int64_t timestamp_us) { | 124 int64_t timestamp_us) { |
105 RTC_DCHECK(signaling_thread_->IsCurrent()); | 125 RTC_DCHECK(signaling_thread_->IsCurrent()); |
106 rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create(); | 126 rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create(); |
107 | 127 |
108 SessionStats session_stats; | 128 SessionStats session_stats; |
109 if (pc_->session()->GetTransportStats(&session_stats)) { | 129 if (pc_->session()->GetTransportStats(&session_stats)) { |
110 ProduceCertificateStats_s(timestamp_us, session_stats, report.get()); | 130 std::map<std::string, CertificateStatsPair> transport_cert_stats = |
111 ProduceIceCandidateAndPairStats_s(timestamp_us, session_stats, | 131 PrepareTransportCertificateStats_s(session_stats); |
112 report.get()); | 132 |
| 133 ProduceCertificateStats_s( |
| 134 timestamp_us, transport_cert_stats, report.get()); |
| 135 ProduceIceCandidateAndPairStats_s( |
| 136 timestamp_us, session_stats, report.get()); |
| 137 ProduceTransportStats_s( |
| 138 timestamp_us, session_stats, transport_cert_stats, report.get()); |
113 } | 139 } |
114 ProducePeerConnectionStats_s(timestamp_us, report.get()); | 140 ProducePeerConnectionStats_s(timestamp_us, report.get()); |
115 | 141 |
116 AddPartialResults(report); | 142 AddPartialResults(report); |
117 } | 143 } |
118 | 144 |
119 void RTCStatsCollector::ProducePartialResultsOnWorkerThread( | 145 void RTCStatsCollector::ProducePartialResultsOnWorkerThread( |
120 int64_t timestamp_us) { | 146 int64_t timestamp_us) { |
121 RTC_DCHECK(worker_thread_->IsCurrent()); | 147 RTC_DCHECK(worker_thread_->IsCurrent()); |
122 rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create(); | 148 rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create(); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 RTC_DCHECK(!callbacks_.empty()); | 196 RTC_DCHECK(!callbacks_.empty()); |
171 RTC_DCHECK(cached_report_); | 197 RTC_DCHECK(cached_report_); |
172 for (const rtc::scoped_refptr<RTCStatsCollectorCallback>& callback : | 198 for (const rtc::scoped_refptr<RTCStatsCollectorCallback>& callback : |
173 callbacks_) { | 199 callbacks_) { |
174 callback->OnStatsDelivered(cached_report_); | 200 callback->OnStatsDelivered(cached_report_); |
175 } | 201 } |
176 callbacks_.clear(); | 202 callbacks_.clear(); |
177 } | 203 } |
178 | 204 |
179 void RTCStatsCollector::ProduceCertificateStats_s( | 205 void RTCStatsCollector::ProduceCertificateStats_s( |
180 int64_t timestamp_us, const SessionStats& session_stats, | 206 int64_t timestamp_us, |
| 207 const std::map<std::string, CertificateStatsPair>& transport_cert_stats, |
181 RTCStatsReport* report) const { | 208 RTCStatsReport* report) const { |
182 RTC_DCHECK(signaling_thread_->IsCurrent()); | 209 RTC_DCHECK(signaling_thread_->IsCurrent()); |
183 for (const auto& transport_stats : session_stats.transport_stats) { | 210 for (const auto& kvp : transport_cert_stats) { |
184 rtc::scoped_refptr<rtc::RTCCertificate> local_certificate; | 211 if (kvp.second.local) { |
185 if (pc_->session()->GetLocalCertificate( | 212 ProduceCertificateStatsFromSSLCertificateStats_s( |
186 transport_stats.second.transport_name, &local_certificate)) { | 213 timestamp_us, *kvp.second.local.get(), report); |
187 ProduceCertificateStatsFromSSLCertificateAndChain_s( | |
188 timestamp_us, local_certificate->ssl_certificate(), report); | |
189 } | 214 } |
190 std::unique_ptr<rtc::SSLCertificate> remote_certificate = | 215 if (kvp.second.remote) { |
191 pc_->session()->GetRemoteSSLCertificate( | 216 ProduceCertificateStatsFromSSLCertificateStats_s( |
192 transport_stats.second.transport_name); | 217 timestamp_us, *kvp.second.remote.get(), report); |
193 if (remote_certificate) { | |
194 ProduceCertificateStatsFromSSLCertificateAndChain_s( | |
195 timestamp_us, *remote_certificate.get(), report); | |
196 } | 218 } |
197 } | 219 } |
198 } | 220 } |
199 | 221 |
200 void RTCStatsCollector::ProduceCertificateStatsFromSSLCertificateAndChain_s( | 222 void RTCStatsCollector::ProduceCertificateStatsFromSSLCertificateStats_s( |
201 int64_t timestamp_us, const rtc::SSLCertificate& certificate, | 223 int64_t timestamp_us, const rtc::SSLCertificateStats& certificate_stats, |
202 RTCStatsReport* report) const { | 224 RTCStatsReport* report) const { |
203 RTC_DCHECK(signaling_thread_->IsCurrent()); | 225 RTC_DCHECK(signaling_thread_->IsCurrent()); |
204 std::unique_ptr<rtc::SSLCertificateStats> ssl_stats = | 226 RTCCertificateStats* prev_certificate_stats = nullptr; |
205 certificate.GetStats(); | 227 for (const rtc::SSLCertificateStats* s = &certificate_stats; s; |
206 RTCCertificateStats* prev_stats = nullptr; | |
207 for (rtc::SSLCertificateStats* s = ssl_stats.get(); s; | |
208 s = s->issuer.get()) { | 228 s = s->issuer.get()) { |
209 RTCCertificateStats* stats = new RTCCertificateStats( | 229 RTCCertificateStats* certificate_stats = new RTCCertificateStats( |
210 "RTCCertificate_" + s->fingerprint, timestamp_us); | 230 RTCCertificateIDFromFingerprint(s->fingerprint), timestamp_us); |
211 stats->fingerprint = s->fingerprint; | 231 certificate_stats->fingerprint = s->fingerprint; |
212 stats->fingerprint_algorithm = s->fingerprint_algorithm; | 232 certificate_stats->fingerprint_algorithm = s->fingerprint_algorithm; |
213 stats->base64_certificate = s->base64_certificate; | 233 certificate_stats->base64_certificate = s->base64_certificate; |
214 if (prev_stats) | 234 if (prev_certificate_stats) |
215 prev_stats->issuer_certificate_id = stats->id(); | 235 prev_certificate_stats->issuer_certificate_id = certificate_stats->id(); |
216 report->AddStats(std::unique_ptr<RTCCertificateStats>(stats)); | 236 report->AddStats(std::unique_ptr<RTCCertificateStats>(certificate_stats)); |
217 prev_stats = stats; | 237 prev_certificate_stats = certificate_stats; |
218 } | 238 } |
219 } | 239 } |
220 | 240 |
221 void RTCStatsCollector::ProduceIceCandidateAndPairStats_s( | 241 void RTCStatsCollector::ProduceIceCandidateAndPairStats_s( |
222 int64_t timestamp_us, const SessionStats& session_stats, | 242 int64_t timestamp_us, const SessionStats& session_stats, |
223 RTCStatsReport* report) const { | 243 RTCStatsReport* report) const { |
224 RTC_DCHECK(signaling_thread_->IsCurrent()); | 244 RTC_DCHECK(signaling_thread_->IsCurrent()); |
225 for (const auto& transport_stats : session_stats.transport_stats) { | 245 for (const auto& transport_stats : session_stats.transport_stats) { |
226 for (const auto& channel_stats : transport_stats.second.channel_stats) { | 246 for (const auto& channel_stats : transport_stats.second.channel_stats) { |
227 for (const cricket::ConnectionInfo& info : | 247 for (const cricket::ConnectionInfo& info : |
228 channel_stats.connection_infos) { | 248 channel_stats.connection_infos) { |
229 const std::string& id = "RTCIceCandidatePair_" + | |
230 info.local_candidate.id() + "_" + info.remote_candidate.id(); | |
231 std::unique_ptr<RTCIceCandidatePairStats> candidate_pair_stats( | 249 std::unique_ptr<RTCIceCandidatePairStats> candidate_pair_stats( |
232 new RTCIceCandidatePairStats(id, timestamp_us)); | 250 new RTCIceCandidatePairStats( |
| 251 RTCIceCandidatePairStatsIDFromConnectionInfo(info), |
| 252 timestamp_us)); |
233 | 253 |
234 // TODO(hbos): Set all of the |RTCIceCandidatePairStats|'s members, | 254 // TODO(hbos): Set all of the |RTCIceCandidatePairStats|'s members, |
235 // crbug.com/633550. | 255 // crbug.com/633550. |
236 | 256 |
237 // TODO(hbos): Set candidate_pair_stats->transport_id. Should be ID to | 257 // TODO(hbos): Set candidate_pair_stats->transport_id. Should be ID to |
238 // RTCTransportStats which does not exist yet: crbug.com/653873. | 258 // RTCTransportStats which does not exist yet: crbug.com/653873. |
239 | 259 |
240 // TODO(hbos): There could be other candidates that are not paired with | 260 // TODO(hbos): There could be other candidates that are not paired with |
241 // anything. We don't have a complete list. Local candidates come from | 261 // anything. We don't have a complete list. Local candidates come from |
242 // Port objects, and prflx candidates (both local and remote) are only | 262 // Port objects, and prflx candidates (both local and remote) are only |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
330 // There is always just one |RTCPeerConnectionStats| so its |id| can be a | 350 // There is always just one |RTCPeerConnectionStats| so its |id| can be a |
331 // constant. | 351 // constant. |
332 std::unique_ptr<RTCPeerConnectionStats> stats( | 352 std::unique_ptr<RTCPeerConnectionStats> stats( |
333 new RTCPeerConnectionStats("RTCPeerConnection", timestamp_us)); | 353 new RTCPeerConnectionStats("RTCPeerConnection", timestamp_us)); |
334 stats->data_channels_opened = data_channels_opened; | 354 stats->data_channels_opened = data_channels_opened; |
335 stats->data_channels_closed = static_cast<uint32_t>(data_channels.size()) - | 355 stats->data_channels_closed = static_cast<uint32_t>(data_channels.size()) - |
336 data_channels_opened; | 356 data_channels_opened; |
337 report->AddStats(std::move(stats)); | 357 report->AddStats(std::move(stats)); |
338 } | 358 } |
339 | 359 |
| 360 void RTCStatsCollector::ProduceTransportStats_s( |
| 361 int64_t timestamp_us, const SessionStats& session_stats, |
| 362 const std::map<std::string, CertificateStatsPair>& transport_cert_stats, |
| 363 RTCStatsReport* report) const { |
| 364 RTC_DCHECK(signaling_thread_->IsCurrent()); |
| 365 for (const auto& transport : session_stats.transport_stats) { |
| 366 // Get reference to RTCP channel, if it exists. |
| 367 std::string rtcp_transport_stats_id; |
| 368 for (const auto& channel_stats : transport.second.channel_stats) { |
| 369 if (channel_stats.component == |
| 370 cricket::ICE_CANDIDATE_COMPONENT_RTCP) { |
| 371 rtcp_transport_stats_id = RTCTransportStatsIDFromTransportChannel( |
| 372 transport.second.transport_name, channel_stats.component); |
| 373 break; |
| 374 } |
| 375 } |
| 376 |
| 377 // Get reference to local and remote certificates of this transport, if they |
| 378 // exist. |
| 379 const auto& certificate_stats_it = transport_cert_stats.find( |
| 380 transport.second.transport_name); |
| 381 RTC_DCHECK(certificate_stats_it != transport_cert_stats.cend()); |
| 382 std::string local_certificate_id; |
| 383 if (certificate_stats_it->second.local) { |
| 384 local_certificate_id = RTCCertificateIDFromFingerprint( |
| 385 certificate_stats_it->second.local->fingerprint); |
| 386 } |
| 387 std::string remote_certificate_id; |
| 388 if (certificate_stats_it->second.remote) { |
| 389 remote_certificate_id = RTCCertificateIDFromFingerprint( |
| 390 certificate_stats_it->second.remote->fingerprint); |
| 391 } |
| 392 |
| 393 // There is one transport stats for each channel. |
| 394 for (const auto& channel_stats : transport.second.channel_stats) { |
| 395 std::unique_ptr<RTCTransportStats> transport_stats( |
| 396 new RTCTransportStats( |
| 397 RTCTransportStatsIDFromTransportChannel( |
| 398 transport.second.transport_name, channel_stats.component), |
| 399 timestamp_us)); |
| 400 transport_stats->bytes_sent = 0; |
| 401 transport_stats->bytes_received = 0; |
| 402 transport_stats->active_connection = false; |
| 403 for (const cricket::ConnectionInfo& info : |
| 404 channel_stats.connection_infos) { |
| 405 *transport_stats->bytes_sent += info.sent_total_bytes; |
| 406 *transport_stats->bytes_received += info.recv_total_bytes; |
| 407 if (info.best_connection) { |
| 408 transport_stats->active_connection = true; |
| 409 transport_stats->selected_candidate_pair_id = |
| 410 RTCIceCandidatePairStatsIDFromConnectionInfo(info); |
| 411 } |
| 412 } |
| 413 if (channel_stats.component != cricket::ICE_CANDIDATE_COMPONENT_RTCP && |
| 414 !rtcp_transport_stats_id.empty()) { |
| 415 transport_stats->rtcp_transport_stats_id = rtcp_transport_stats_id; |
| 416 } |
| 417 if (!local_certificate_id.empty()) |
| 418 transport_stats->local_certificate_id = local_certificate_id; |
| 419 if (!remote_certificate_id.empty()) |
| 420 transport_stats->remote_certificate_id = remote_certificate_id; |
| 421 report->AddStats(std::move(transport_stats)); |
| 422 } |
| 423 } |
| 424 } |
| 425 |
| 426 std::map<std::string, RTCStatsCollector::CertificateStatsPair> |
| 427 RTCStatsCollector::PrepareTransportCertificateStats_s( |
| 428 const SessionStats& session_stats) const { |
| 429 RTC_DCHECK(signaling_thread_->IsCurrent()); |
| 430 std::map<std::string, CertificateStatsPair> transport_cert_stats; |
| 431 for (const auto& transport_stats : session_stats.transport_stats) { |
| 432 CertificateStatsPair certificate_stats_pair; |
| 433 rtc::scoped_refptr<rtc::RTCCertificate> local_certificate; |
| 434 if (pc_->session()->GetLocalCertificate( |
| 435 transport_stats.second.transport_name, &local_certificate)) { |
| 436 certificate_stats_pair.local = |
| 437 local_certificate->ssl_certificate().GetStats(); |
| 438 } |
| 439 std::unique_ptr<rtc::SSLCertificate> remote_certificate = |
| 440 pc_->session()->GetRemoteSSLCertificate( |
| 441 transport_stats.second.transport_name); |
| 442 if (remote_certificate) { |
| 443 certificate_stats_pair.remote = remote_certificate->GetStats(); |
| 444 } |
| 445 transport_cert_stats.insert( |
| 446 std::make_pair(transport_stats.second.transport_name, |
| 447 std::move(certificate_stats_pair))); |
| 448 } |
| 449 return transport_cert_stats; |
| 450 } |
| 451 |
340 } // namespace webrtc | 452 } // namespace webrtc |
OLD | NEW |