diff --git a/talk/app/webrtc/jsepsessiondescription_unittest.cc b/talk/app/webrtc/jsepsessiondescription_unittest.cc index cf992c07fe..1c24c1ab2d 100644 --- a/talk/app/webrtc/jsepsessiondescription_unittest.cc +++ b/talk/app/webrtc/jsepsessiondescription_unittest.cc @@ -101,8 +101,7 @@ class JsepSessionDescriptionTest : public testing::Test { int port = 1234; rtc::SocketAddress address("127.0.0.1", port++); cricket::Candidate candidate("rtp", cricket::ICE_CANDIDATE_COMPONENT_RTP, - "udp", address, 1, "", - "", "local", "eth0", 0, "1"); + "udp", address, 1, "", "", "local", 0, "1"); candidate_ = candidate; const std::string session_id = rtc::ToString(rtc::CreateRandomId64()); diff --git a/talk/app/webrtc/statscollector.cc b/talk/app/webrtc/statscollector.cc index f1c91b1c25..47458b9baa 100644 --- a/talk/app/webrtc/statscollector.cc +++ b/talk/app/webrtc/statscollector.cc @@ -619,6 +619,37 @@ std::string StatsCollector::AddCertificateReports( return AddOneCertificateReport(cert, issuer_id); } +std::string StatsCollector::AddCandidateReport( + const cricket::Candidate& candidate, + const std::string& report_type) { + std::ostringstream ost; + ost << "Cand-" << candidate.id(); + StatsReport* report = reports_.Find(ost.str()); + if (!report) { + report = reports_.InsertNew(ost.str()); + DCHECK(StatsReport::kStatsReportTypeIceLocalCandidate == report_type || + StatsReport::kStatsReportTypeIceRemoteCandidate == report_type); + report->type = report_type; + if (report_type == StatsReport::kStatsReportTypeIceLocalCandidate) { + report->AddValue(StatsReport::kStatsValueNameCandidateNetworkType, + rtc::AdapterTypeToStatsType(candidate.network_type())); + } + report->timestamp = stats_gathering_started_; + report->AddValue(StatsReport::kStatsValueNameCandidateIPAddress, + candidate.address().ipaddr().ToString()); + report->AddValue(StatsReport::kStatsValueNameCandidatePortNumber, + candidate.address().PortAsString()); + report->AddValue(StatsReport::kStatsValueNameCandidatePriority, + candidate.priority()); + report->AddValue(StatsReport::kStatsValueNameCandidateType, + cricket::IceCandidateTypeToStatsType(candidate.type())); + report->AddValue(StatsReport::kStatsValueNameCandidateTransportType, + candidate.protocol()); + } + + return ost.str(); +} + void StatsCollector::ExtractSessionInfo() { ASSERT(session_->signaling_thread()->IsCurrent()); // Extract information from the base session. @@ -711,6 +742,15 @@ void StatsCollector::ExtractSessionInfo() { info.readable); report->AddBoolean(StatsReport::kStatsValueNameActiveConnection, info.best_connection); + report->AddValue(StatsReport::kStatsValueNameLocalCandidateId, + AddCandidateReport( + info.local_candidate, + StatsReport::kStatsReportTypeIceLocalCandidate)); + report->AddValue( + StatsReport::kStatsValueNameRemoteCandidateId, + AddCandidateReport( + info.remote_candidate, + StatsReport::kStatsReportTypeIceRemoteCandidate)); report->AddValue(StatsReport::kStatsValueNameLocalAddress, info.local_candidate.address().ToString()); report->AddValue(StatsReport::kStatsValueNameRemoteAddress, diff --git a/talk/app/webrtc/statscollector.h b/talk/app/webrtc/statscollector.h index 5b944f91fb..867e7886a1 100644 --- a/talk/app/webrtc/statscollector.h +++ b/talk/app/webrtc/statscollector.h @@ -93,12 +93,19 @@ class StatsCollector { void ClearUpdateStatsCacheForTest(); private: + friend class StatsCollectorTest; + bool CopySelectedReports(const std::string& selector, StatsReports* reports); // Helper method for AddCertificateReports. std::string AddOneCertificateReport( const rtc::SSLCertificate* cert, const std::string& issuer_id); + // Helper method for creating IceCandidate report. |is_local| indicates + // whether this candidate is local or remote. + std::string AddCandidateReport(const cricket::Candidate& candidate, + const std::string& report_type); + // Adds a report for this certificate and every certificate in its chain, and // returns the leaf certificate's report's ID. std::string AddCertificateReports(const rtc::SSLCertificate* cert); diff --git a/talk/app/webrtc/statscollector_unittest.cc b/talk/app/webrtc/statscollector_unittest.cc index 924b7de002..34b5bba3fd 100644 --- a/talk/app/webrtc/statscollector_unittest.cc +++ b/talk/app/webrtc/statscollector_unittest.cc @@ -42,6 +42,7 @@ #include "webrtc/base/base64.h" #include "webrtc/base/fakesslidentity.h" #include "webrtc/base/gunit.h" +#include "webrtc/base/network.h" using cricket::StatsOptions; using testing::_; @@ -61,7 +62,7 @@ class FakeDeviceManager; } // namespace cricket -namespace { +namespace webrtc { // Error return values const char kNotFound[] = "NOT FOUND"; @@ -501,6 +502,12 @@ class StatsCollectorTest : public testing::Test { .WillOnce(DoAll(SetArgPointee<1>(kRemoteTrackId), Return(true))); } + std::string AddCandidateReport(StatsCollector* collector, + const cricket::Candidate& candidate, + const std::string& report_type) { + return collector->AddCandidateReport(candidate, report_type); + } + void SetupAndVerifyAudioTrackStats( FakeAudioTrack* audio_track, webrtc::MediaStream* stream, @@ -1016,6 +1023,97 @@ TEST_F(StatsCollectorTest, ReportsFromRemoteTrack) { EXPECT_EQ(kRemoteTrackId, track_id); } +// This test verifies the Ice Candidate report should contain the correct +// information from local/remote candidates. +TEST_F(StatsCollectorTest, IceCandidateReport) { + webrtc::StatsCollector stats(&session_); // Implementation under test. + StatsReports reports; // returned values. + + const int local_port = 2000; + const char local_ip[] = "192.168.0.1"; + const int remote_port = 2001; + const char remote_ip[] = "192.168.0.2"; + + rtc::SocketAddress local_address(local_ip, local_port); + rtc::SocketAddress remote_address(remote_ip, remote_port); + rtc::AdapterType network_type = rtc::ADAPTER_TYPE_ETHERNET; + uint32 priority = 1000; + + cricket::Candidate c; + const std::string& local_id = rtc::CreateRandomString(8); + c.set_id(local_id); + c.set_type(cricket::LOCAL_PORT_TYPE); + c.set_protocol(cricket::UDP_PROTOCOL_NAME); + c.set_address(local_address); + c.set_priority(priority); + c.set_network_type(network_type); + std::string report_id = AddCandidateReport( + &stats, c, StatsReport::kStatsReportTypeIceLocalCandidate); + EXPECT_EQ("Cand-" + local_id, report_id); + + const std::string& remote_id = rtc::CreateRandomString(8); + c.set_id(remote_id); + c.set_type(cricket::PRFLX_PORT_TYPE); + c.set_address(remote_address); + report_id = AddCandidateReport( + &stats, c, StatsReport::kStatsReportTypeIceRemoteCandidate); + EXPECT_EQ("Cand-" + remote_id, report_id); + + stats.GetStats(NULL, &reports); + + // Verify the local candidate report is populated correctly. + EXPECT_EQ( + local_ip, + ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, + StatsReport::kStatsValueNameCandidateIPAddress)); + EXPECT_EQ( + rtc::ToString(local_port), + ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, + StatsReport::kStatsValueNameCandidatePortNumber)); + EXPECT_EQ( + cricket::UDP_PROTOCOL_NAME, + ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, + StatsReport::kStatsValueNameCandidateTransportType)); + EXPECT_EQ( + rtc::ToString(priority), + ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, + StatsReport::kStatsValueNameCandidatePriority)); + EXPECT_EQ( + cricket::IceCandidateTypeToStatsType(cricket::LOCAL_PORT_TYPE), + ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, + StatsReport::kStatsValueNameCandidateType)); + EXPECT_EQ( + rtc::AdapterTypeToStatsType(network_type), + ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, + StatsReport::kStatsValueNameCandidateNetworkType)); + + // Verify the remote candidate report is populated correctly. + EXPECT_EQ(remote_ip, + ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate, + reports, + StatsReport::kStatsValueNameCandidateIPAddress)); + EXPECT_EQ(rtc::ToString(remote_port), + ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate, + reports, + StatsReport::kStatsValueNameCandidatePortNumber)); + EXPECT_EQ(cricket::UDP_PROTOCOL_NAME, + ExtractStatsValue( + StatsReport::kStatsReportTypeIceRemoteCandidate, reports, + StatsReport::kStatsValueNameCandidateTransportType)); + EXPECT_EQ(rtc::ToString(priority), + ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate, + reports, + StatsReport::kStatsValueNameCandidatePriority)); + EXPECT_EQ( + cricket::IceCandidateTypeToStatsType(cricket::PRFLX_PORT_TYPE), + ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate, + reports, StatsReport::kStatsValueNameCandidateType)); + EXPECT_EQ(kNotFound, + ExtractStatsValue( + StatsReport::kStatsReportTypeIceRemoteCandidate, reports, + StatsReport::kStatsValueNameCandidateNetworkType)); +} + // This test verifies that all chained certificates are correctly // reported TEST_F(StatsCollectorTest, ChainedCertificateReportsCreated) { @@ -1461,4 +1559,4 @@ TEST_F(StatsCollectorTest, TwoLocalTracksWithSameSsrc) { media_channel, &new_voice_sender_info, NULL, &new_stats_read, &reports); } -} // namespace +} // namespace webrtc diff --git a/talk/app/webrtc/statstypes.cc b/talk/app/webrtc/statstypes.cc index 8547520069..fd96b1070c 100644 --- a/talk/app/webrtc/statstypes.cc +++ b/talk/app/webrtc/statstypes.cc @@ -34,7 +34,9 @@ const char StatsReport::kStatsReportTypeBwe[] = "VideoBwe"; const char StatsReport::kStatsReportTypeRemoteSsrc[] = "remoteSsrc"; const char StatsReport::kStatsReportTypeSsrc[] = "ssrc"; const char StatsReport::kStatsReportTypeTrack[] = "googTrack"; -const char StatsReport::kStatsReportTypeIceCandidate[] = "iceCandidate"; +const char StatsReport::kStatsReportTypeIceLocalCandidate[] = "localcandidate"; +const char StatsReport::kStatsReportTypeIceRemoteCandidate[] = + "remotecandidate"; const char StatsReport::kStatsReportTypeTransport[] = "googTransport"; const char StatsReport::kStatsReportTypeComponent[] = "googComponent"; const char StatsReport::kStatsReportTypeCandidatePair[] = "googCandidatePair"; @@ -135,6 +137,22 @@ const char* StatsReport::Value::display_name() const { return "googCaptureJitterMs"; case kStatsValueNameCaptureQueueDelayMsPerS: return "googCaptureQueueDelayMsPerS"; + + // Candidate related attributes. Values are taken from + // http://w3c.github.io/webrtc-stats/#rtcstatstype-enum*. + case kStatsValueNameCandidateIPAddress: + return "ipAddress"; + case kStatsValueNameCandidateNetworkType: + return "networkType"; + case kStatsValueNameCandidatePortNumber: + return "portNumber"; + case kStatsValueNameCandidatePriority: + return "priority"; + case kStatsValueNameCandidateTransportType: + return "transport"; + case kStatsValueNameCandidateType: + return "candidateType"; + case kStatsValueNameChannelId: return "googChannelId"; case kStatsValueNameCodecName: @@ -227,6 +245,8 @@ const char* StatsReport::Value::display_name() const { return "googJitterReceived"; case kStatsValueNameLocalAddress: return "googLocalAddress"; + case kStatsValueNameLocalCandidateId: + return "localCandidateId"; case kStatsValueNameLocalCandidateType: return "googLocalCandidateType"; case kStatsValueNameLocalCertificateId: @@ -253,6 +273,8 @@ const char* StatsReport::Value::display_name() const { return "googReceivedPacketGroupPropagationDeltaSumDebug"; case kStatsValueNameRemoteAddress: return "googRemoteAddress"; + case kStatsValueNameRemoteCandidateId: + return "remoteCandidateId"; case kStatsValueNameRemoteCandidateType: return "googRemoteCandidateType"; case kStatsValueNameRemoteCertificateId: diff --git a/talk/app/webrtc/statstypes.h b/talk/app/webrtc/statstypes.h index d47dc18534..bca771c378 100644 --- a/talk/app/webrtc/statstypes.h +++ b/talk/app/webrtc/statstypes.h @@ -97,6 +97,12 @@ class StatsReport { kStatsValueNameCaptureJitterMs, kStatsValueNameCaptureQueueDelayMsPerS, kStatsValueNameCaptureStartNtpTimeMs, + kStatsValueNameCandidateIPAddress, + kStatsValueNameCandidateNetworkType, + kStatsValueNameCandidatePortNumber, + kStatsValueNameCandidatePriority, + kStatsValueNameCandidateTransportType, + kStatsValueNameCandidateType, kStatsValueNameChannelId, kStatsValueNameCodecName, kStatsValueNameComponent, @@ -138,6 +144,7 @@ class StatsReport { kStatsValueNameJitterBufferMs, kStatsValueNameJitterReceived, kStatsValueNameLocalAddress, + kStatsValueNameLocalCandidateId, kStatsValueNameLocalCandidateType, kStatsValueNameLocalCertificateId, kStatsValueNameMaxDecodeMs, @@ -151,6 +158,7 @@ class StatsReport { kStatsValueNameRecvPacketGroupPropagationDeltaDebug, kStatsValueNameRecvPacketGroupPropagationDeltaSumDebug, kStatsValueNameRemoteAddress, + kStatsValueNameRemoteCandidateId, kStatsValueNameRemoteCandidateType, kStatsValueNameRemoteCertificateId, kStatsValueNameRenderDelayMs, @@ -237,9 +245,12 @@ class StatsReport { // track. The |id| field is the track id. static const char kStatsReportTypeTrack[]; - // StatsReport of |type| = "iceCandidate" is statistics on a specific - // ICE Candidate. It links to its transport. - static const char kStatsReportTypeIceCandidate[]; + // StatsReport of |type| = "localcandidate" or "remotecandidate" is attributes + // on a specific ICE Candidate. It links to its connection pair by candidate + // id. The string value is taken from + // http://w3c.github.io/webrtc-stats/#rtcstatstype-enum*. + static const char kStatsReportTypeIceLocalCandidate[]; + static const char kStatsReportTypeIceRemoteCandidate[]; // A StatsReport of |type| = "googCertificate" contains an SSL certificate // transmitted by one of the endpoints of this connection. The |id| is diff --git a/talk/app/webrtc/webrtcsdp.cc b/talk/app/webrtc/webrtcsdp.cc index c7b34c4845..226b8b0f49 100644 --- a/talk/app/webrtc/webrtcsdp.cc +++ b/talk/app/webrtc/webrtcsdp.cc @@ -1089,12 +1089,10 @@ bool ParseCandidate(const std::string& message, Candidate* candidate, } } - // Empty string as the candidate id and network name. const std::string id; - const std::string network_name; *candidate = Candidate(id, component_id, cricket::ProtoToString(protocol), - address, priority, username, password, candidate_type, network_name, - generation, foundation); + address, priority, username, password, candidate_type, + generation, foundation); candidate->set_related_address(related_address); candidate->set_tcptype(tcptype); return true; diff --git a/talk/app/webrtc/webrtcsdp_unittest.cc b/talk/app/webrtc/webrtcsdp_unittest.cc index 8655487432..cc684d2ce5 100644 --- a/talk/app/webrtc/webrtcsdp_unittest.cc +++ b/talk/app/webrtc/webrtcsdp_unittest.cc @@ -588,88 +588,74 @@ class WebRtcSdpTest : public testing::Test { // v4 host int port = 1234; rtc::SocketAddress address("192.168.1.5", port++); - Candidate candidate1( - "", ICE_CANDIDATE_COMPONENT_RTP, "udp", address, kCandidatePriority, - "", "", LOCAL_PORT_TYPE, - "", kCandidateGeneration, kCandidateFoundation1); + Candidate candidate1("", ICE_CANDIDATE_COMPONENT_RTP, "udp", address, + kCandidatePriority, "", "", LOCAL_PORT_TYPE, + kCandidateGeneration, kCandidateFoundation1); address.SetPort(port++); - Candidate candidate2( - "", ICE_CANDIDATE_COMPONENT_RTCP, "udp", address, kCandidatePriority, - "", "", LOCAL_PORT_TYPE, - "", kCandidateGeneration, kCandidateFoundation1); + Candidate candidate2("", ICE_CANDIDATE_COMPONENT_RTCP, "udp", address, + kCandidatePriority, "", "", LOCAL_PORT_TYPE, + kCandidateGeneration, kCandidateFoundation1); address.SetPort(port++); - Candidate candidate3( - "", ICE_CANDIDATE_COMPONENT_RTCP, "udp", address, kCandidatePriority, - "", "", LOCAL_PORT_TYPE, - "", kCandidateGeneration, kCandidateFoundation1); + Candidate candidate3("", ICE_CANDIDATE_COMPONENT_RTCP, "udp", address, + kCandidatePriority, "", "", LOCAL_PORT_TYPE, + kCandidateGeneration, kCandidateFoundation1); address.SetPort(port++); - Candidate candidate4( - "", ICE_CANDIDATE_COMPONENT_RTP, "udp", address, kCandidatePriority, - "", "", LOCAL_PORT_TYPE, - "", kCandidateGeneration, kCandidateFoundation1); + Candidate candidate4("", ICE_CANDIDATE_COMPONENT_RTP, "udp", address, + kCandidatePriority, "", "", LOCAL_PORT_TYPE, + kCandidateGeneration, kCandidateFoundation1); // v6 host rtc::SocketAddress v6_address("::1", port++); - cricket::Candidate candidate5( - "", cricket::ICE_CANDIDATE_COMPONENT_RTP, - "udp", v6_address, kCandidatePriority, - "", "", cricket::LOCAL_PORT_TYPE, - "", kCandidateGeneration, kCandidateFoundation2); + cricket::Candidate candidate5("", cricket::ICE_CANDIDATE_COMPONENT_RTP, + "udp", v6_address, kCandidatePriority, "", "", + cricket::LOCAL_PORT_TYPE, + kCandidateGeneration, kCandidateFoundation2); v6_address.SetPort(port++); - cricket::Candidate candidate6( - "", cricket::ICE_CANDIDATE_COMPONENT_RTCP, - "udp", v6_address, kCandidatePriority, - "", "", cricket::LOCAL_PORT_TYPE, - "", kCandidateGeneration, kCandidateFoundation2); + cricket::Candidate candidate6("", cricket::ICE_CANDIDATE_COMPONENT_RTCP, + "udp", v6_address, kCandidatePriority, "", "", + cricket::LOCAL_PORT_TYPE, + kCandidateGeneration, kCandidateFoundation2); v6_address.SetPort(port++); - cricket::Candidate candidate7( - "", cricket::ICE_CANDIDATE_COMPONENT_RTCP, - "udp", v6_address, kCandidatePriority, - "", "", cricket::LOCAL_PORT_TYPE, - "", kCandidateGeneration, kCandidateFoundation2); + cricket::Candidate candidate7("", cricket::ICE_CANDIDATE_COMPONENT_RTCP, + "udp", v6_address, kCandidatePriority, "", "", + cricket::LOCAL_PORT_TYPE, + kCandidateGeneration, kCandidateFoundation2); v6_address.SetPort(port++); - cricket::Candidate candidate8( - "", cricket::ICE_CANDIDATE_COMPONENT_RTP, - "udp", v6_address, kCandidatePriority, - "", "", cricket::LOCAL_PORT_TYPE, - "", kCandidateGeneration, kCandidateFoundation2); + cricket::Candidate candidate8("", cricket::ICE_CANDIDATE_COMPONENT_RTP, + "udp", v6_address, kCandidatePriority, "", "", + cricket::LOCAL_PORT_TYPE, + kCandidateGeneration, kCandidateFoundation2); // stun int port_stun = 2345; rtc::SocketAddress address_stun("74.125.127.126", port_stun++); rtc::SocketAddress rel_address_stun("192.168.1.5", port_stun++); - cricket::Candidate candidate9 - ("", cricket::ICE_CANDIDATE_COMPONENT_RTP, - "udp", address_stun, kCandidatePriority, - "", "", STUN_PORT_TYPE, - "", kCandidateGeneration, kCandidateFoundation3); + cricket::Candidate candidate9("", cricket::ICE_CANDIDATE_COMPONENT_RTP, + "udp", address_stun, kCandidatePriority, "", + "", STUN_PORT_TYPE, kCandidateGeneration, + kCandidateFoundation3); candidate9.set_related_address(rel_address_stun); address_stun.SetPort(port_stun++); rel_address_stun.SetPort(port_stun++); - cricket::Candidate candidate10( - "", cricket::ICE_CANDIDATE_COMPONENT_RTCP, - "udp", address_stun, kCandidatePriority, - "", "", STUN_PORT_TYPE, - "", kCandidateGeneration, kCandidateFoundation3); + cricket::Candidate candidate10("", cricket::ICE_CANDIDATE_COMPONENT_RTCP, + "udp", address_stun, kCandidatePriority, "", + "", STUN_PORT_TYPE, kCandidateGeneration, + kCandidateFoundation3); candidate10.set_related_address(rel_address_stun); // relay int port_relay = 3456; rtc::SocketAddress address_relay("74.125.224.39", port_relay++); - cricket::Candidate candidate11( - "", cricket::ICE_CANDIDATE_COMPONENT_RTCP, - "udp", address_relay, kCandidatePriority, - "", "", - cricket::RELAY_PORT_TYPE, "", - kCandidateGeneration, kCandidateFoundation4); + cricket::Candidate candidate11("", cricket::ICE_CANDIDATE_COMPONENT_RTCP, + "udp", address_relay, kCandidatePriority, "", + "", cricket::RELAY_PORT_TYPE, + kCandidateGeneration, kCandidateFoundation4); address_relay.SetPort(port_relay++); - cricket::Candidate candidate12( - "", cricket::ICE_CANDIDATE_COMPONENT_RTP, - "udp", address_relay, kCandidatePriority, - "", "", - RELAY_PORT_TYPE, "", - kCandidateGeneration, kCandidateFoundation4); + cricket::Candidate candidate12("", cricket::ICE_CANDIDATE_COMPONENT_RTP, + "udp", address_relay, kCandidatePriority, "", + "", RELAY_PORT_TYPE, kCandidateGeneration, + kCandidateFoundation4); // voice candidates_.push_back(candidate1); @@ -1642,11 +1628,10 @@ TEST_F(WebRtcSdpTest, SerializeCandidates) { // TODO(mallinath) : Enable this test once WebRTCSdp capable of parsing // RFC 6544. TEST_F(WebRtcSdpTest, SerializeTcpCandidates) { - Candidate candidate( - "", ICE_CANDIDATE_COMPONENT_RTP, "tcp", - rtc::SocketAddress("192.168.1.5", 9), kCandidatePriority, - "", "", LOCAL_PORT_TYPE, - "", kCandidateGeneration, kCandidateFoundation1); + Candidate candidate("", ICE_CANDIDATE_COMPONENT_RTP, "tcp", + rtc::SocketAddress("192.168.1.5", 9), kCandidatePriority, + "", "", LOCAL_PORT_TYPE, kCandidateGeneration, + kCandidateFoundation1); candidate.set_tcptype(cricket::TCPTYPE_ACTIVE_STR); rtc::scoped_ptr jcandidate( new JsepIceCandidate(std::string("audio_content_name"), 0, candidate)); @@ -1936,11 +1921,10 @@ TEST_F(WebRtcSdpTest, DeserializeCandidate) { sdp = kSdpTcpActiveCandidate; EXPECT_TRUE(SdpDeserializeCandidate(sdp, &jcandidate)); // Make a cricket::Candidate equivalent to kSdpTcpCandidate string. - Candidate candidate( - "", ICE_CANDIDATE_COMPONENT_RTP, "tcp", - rtc::SocketAddress("192.168.1.5", 9), kCandidatePriority, - "", "", LOCAL_PORT_TYPE, - "", kCandidateGeneration, kCandidateFoundation1); + Candidate candidate("", ICE_CANDIDATE_COMPONENT_RTP, "tcp", + rtc::SocketAddress("192.168.1.5", 9), kCandidatePriority, + "", "", LOCAL_PORT_TYPE, kCandidateGeneration, + kCandidateFoundation1); rtc::scoped_ptr jcandidate_template( new JsepIceCandidate(std::string("audio_content_name"), 0, candidate)); EXPECT_TRUE(jcandidate.candidate().IsEquivalent( diff --git a/webrtc/base/network.cc b/webrtc/base/network.cc index 4cc3ab9f97..57d6d98e1b 100644 --- a/webrtc/base/network.cc +++ b/webrtc/base/network.cc @@ -65,6 +65,14 @@ const int kNetworksUpdateIntervalMs = 2000; const int kHighestNetworkPreference = 127; +// Strings used by the stats collector to report adapter types. This fits the +// general stype of http://w3c.github.io/webrtc-stats than what +// AdapterTypeToString does. +const char* STATSREPORT_ADAPTER_TYPE_ETHERNET = "lan"; +const char* STATSREPORT_ADAPTER_TYPE_WIFI = "wlan"; +const char* STATSREPORT_ADAPTER_TYPE_WWAN = "wwan"; +const char* STATSREPORT_ADAPTER_TYPE_VPN = "vpn"; + typedef struct { Network* net; std::vector ips; @@ -123,6 +131,24 @@ std::string AdapterTypeToString(AdapterType type) { } // namespace +const char* AdapterTypeToStatsType(rtc::AdapterType type) { + switch (type) { + case ADAPTER_TYPE_UNKNOWN: + return "unknown"; + case ADAPTER_TYPE_ETHERNET: + return STATSREPORT_ADAPTER_TYPE_ETHERNET; + case ADAPTER_TYPE_WIFI: + return STATSREPORT_ADAPTER_TYPE_WIFI; + case ADAPTER_TYPE_CELLULAR: + return STATSREPORT_ADAPTER_TYPE_WWAN; + case ADAPTER_TYPE_VPN: + return STATSREPORT_ADAPTER_TYPE_VPN; + default: + ASSERT(false); + return ""; + } +} + std::string MakeNetworkKey(const std::string& name, const IPAddress& prefix, int prefix_length) { std::ostringstream ost; diff --git a/webrtc/base/network.h b/webrtc/base/network.h index 6f9d08e707..f81c62fc3f 100644 --- a/webrtc/base/network.h +++ b/webrtc/base/network.h @@ -39,6 +39,11 @@ enum AdapterType { ADAPTER_TYPE_VPN = 4 }; +// Conversion function to convert adapter type to report string which are more +// fitting to the general style of http://w3c.github.io/webrtc-stats. This is +// only used by stats collector. +const char* AdapterTypeToStatsType(rtc::AdapterType type); + // Makes a string key for this network. Used in the network manager's maps. // Network objects are keyed on interface name, network prefix and the // length of that prefix. diff --git a/webrtc/p2p/base/candidate.h b/webrtc/p2p/base/candidate.h index 72bc69ef27..44b9b989c2 100644 --- a/webrtc/p2p/base/candidate.h +++ b/webrtc/p2p/base/candidate.h @@ -20,6 +20,7 @@ #include "webrtc/p2p/base/constants.h" #include "webrtc/base/basictypes.h" +#include "webrtc/base/network.h" #include "webrtc/base/socketaddress.h" namespace cricket { @@ -30,17 +31,33 @@ class Candidate { public: // TODO: Match the ordering and param list as per RFC 5245 // candidate-attribute syntax. http://tools.ietf.org/html/rfc5245#section-15.1 - Candidate() : component_(0), priority_(0), generation_(0) {} - Candidate(const std::string& id, int component, const std::string& protocol, - const rtc::SocketAddress& address, uint32 priority, - const std::string& username, const std::string& password, - const std::string& type, const std::string& network_name, - uint32 generation, const std::string& foundation) - : id_(id), component_(component), protocol_(protocol), address_(address), - priority_(priority), username_(username), password_(password), - type_(type), network_name_(network_name), generation_(generation), - foundation_(foundation) { - } + Candidate() + : component_(0), + priority_(0), + network_type_(rtc::ADAPTER_TYPE_UNKNOWN), + generation_(0) {} + + Candidate(const std::string& id, + int component, + const std::string& protocol, + const rtc::SocketAddress& address, + uint32 priority, + const std::string& username, + const std::string& password, + const std::string& type, + uint32 generation, + const std::string& foundation) + : id_(id), + component_(component), + protocol_(protocol), + address_(address), + priority_(priority), + username_(username), + password_(password), + type_(type), + network_type_(rtc::ADAPTER_TYPE_UNKNOWN), + generation_(generation), + foundation_(foundation) {} const std::string & id() const { return id_; } void set_id(const std::string & id) { id_ = id; } @@ -94,6 +111,11 @@ class Candidate { network_name_ = network_name; } + rtc::AdapterType network_type() const { return network_type_; } + void set_network_type(rtc::AdapterType network_type) { + network_type_ = network_type; + } + // Candidates in a new generation replace those in the old generation. uint32 generation() const { return generation_; } void set_generation(uint32 generation) { generation_ = generation; } @@ -201,6 +223,7 @@ class Candidate { std::string password_; std::string type_; std::string network_name_; + rtc::AdapterType network_type_; uint32 generation_; std::string foundation_; rtc::SocketAddress related_address_; diff --git a/webrtc/p2p/base/p2ptransportchannel.cc b/webrtc/p2p/base/p2ptransportchannel.cc index 6ecdf569e0..8073f59871 100644 --- a/webrtc/p2p/base/p2ptransportchannel.cc +++ b/webrtc/p2p/base/p2ptransportchannel.cc @@ -506,11 +506,10 @@ void P2PTransportChannel::OnUnknownAddress( } std::string id = rtc::CreateRandomString(8); - new_remote_candidate = Candidate( - id, component(), ProtoToString(proto), address, - 0, remote_username, remote_password, type, - port->Network()->name(), 0U, - rtc::ToString(rtc::ComputeCrc32(id))); + new_remote_candidate = + Candidate(id, component(), ProtoToString(proto), address, 0, + remote_username, remote_password, type, 0U, + rtc::ToString(rtc::ComputeCrc32(id))); new_remote_candidate.set_priority( new_remote_candidate.GetPriority(ICE_TYPE_PREFERENCE_SRFLX, port->Network()->preference(), 0)); diff --git a/webrtc/p2p/base/port.cc b/webrtc/p2p/base/port.cc index 59344547d6..ad193c8ec4 100644 --- a/webrtc/p2p/base/port.cc +++ b/webrtc/p2p/base/port.cc @@ -26,6 +26,14 @@ namespace { +// The following is the enum RTCStatsIceCandidateType from +// http://w3c.github.io/webrtc-stats/#rtcstatsicecandidatetype-enum such that +// our stats report for ice candidate type could conform to that. +const char STATSREPORT_LOCAL_PORT_TYPE[] = "host"; +const char STATSREPORT_STUN_PORT_TYPE[] = "serverreflexive"; +const char STATSREPORT_PRFLX_PORT_TYPE[] = "peerreflexive"; +const char STATSREPORT_RELAY_PORT_TYPE[] = "relayed"; + // Determines whether we have seen at least the given maximum number of // pings fail to have a response. inline bool TooManyFailures( @@ -131,6 +139,23 @@ bool StringToProto(const char* value, ProtocolType* proto) { return false; } +const char* IceCandidateTypeToStatsType(const std::string& candidate_type) { + if (candidate_type == LOCAL_PORT_TYPE) { + return STATSREPORT_LOCAL_PORT_TYPE; + } + if (candidate_type == STUN_PORT_TYPE) { + return STATSREPORT_STUN_PORT_TYPE; + } + if (candidate_type == PRFLX_PORT_TYPE) { + return STATSREPORT_PRFLX_PORT_TYPE; + } + if (candidate_type == RELAY_PORT_TYPE) { + return STATSREPORT_RELAY_PORT_TYPE; + } + ASSERT(false); + return "unknown"; +} + // RFC 6544, TCP candidate encoding rules. const int DISCARD_PORT = 9; const char TCPTYPE_ACTIVE_STR[] = "active"; @@ -270,6 +295,7 @@ void Port::AddAddress(const rtc::SocketAddress& address, c.set_username(username_fragment()); c.set_password(password_); c.set_network_name(network_->name()); + c.set_network_type(network_->type()); c.set_generation(generation_); c.set_related_address(related_address); c.set_foundation(ComputeFoundation(type, protocol, base_address)); @@ -1430,6 +1456,7 @@ void Connection::MaybeAddPrflxCandidate(ConnectionRequest* request, new_local_candidate.set_username(local_candidate().username()); new_local_candidate.set_password(local_candidate().password()); new_local_candidate.set_network_name(local_candidate().network_name()); + new_local_candidate.set_network_type(local_candidate().network_type()); new_local_candidate.set_related_address(local_candidate().address()); new_local_candidate.set_foundation( ComputeFoundation(PRFLX_PORT_TYPE, local_candidate().protocol(), diff --git a/webrtc/p2p/base/port.h b/webrtc/p2p/base/port.h index b78c2c5544..fa16fa14d5 100644 --- a/webrtc/p2p/base/port.h +++ b/webrtc/p2p/base/port.h @@ -88,6 +88,10 @@ enum IcePriorityValue { const char* ProtoToString(ProtocolType proto); bool StringToProto(const char* value, ProtocolType* proto); +// Conversion function to convert candidate type string to the corresponding one +// from enum RTCStatsIceCandidateType. +const char* IceCandidateTypeToStatsType(const std::string& candidate_type); + struct ProtocolAddress { rtc::SocketAddress address; ProtocolType proto; diff --git a/webrtc/p2p/base/transport_unittest.cc b/webrtc/p2p/base/transport_unittest.cc index abcf32ceb3..e5d7acafa2 100644 --- a/webrtc/p2p/base/transport_unittest.cc +++ b/webrtc/p2p/base/transport_unittest.cc @@ -18,6 +18,7 @@ #include "webrtc/libjingle/xmpp/constants.h" #include "webrtc/base/fakesslidentity.h" #include "webrtc/base/gunit.h" +#include "webrtc/base/network.h" #include "webrtc/base/thread.h" using cricket::Candidate; @@ -346,19 +347,19 @@ TEST_F(TransportTest, TestSetRemoteIceLiteInAnswer) { // Tests that we can properly serialize/deserialize candidates. TEST_F(TransportTest, TestP2PTransportWriteAndParseCandidate) { - Candidate test_candidate( - "", 1, "udp", - rtc::SocketAddress("2001:db8:fefe::1", 9999), - 738197504, "abcdef", "ghijkl", "foo", "testnet", 50, ""); - Candidate test_candidate2( - "", 2, "tcp", - rtc::SocketAddress("192.168.7.1", 9999), - 1107296256, "mnopqr", "stuvwx", "bar", "testnet2", 100, ""); + Candidate test_candidate("", 1, "udp", + rtc::SocketAddress("2001:db8:fefe::1", 9999), + 738197504, "abcdef", "ghijkl", "foo", 50, ""); + test_candidate.set_network_name("testnet"); + Candidate test_candidate2("", 2, "tcp", + rtc::SocketAddress("192.168.7.1", 9999), 1107296256, + "mnopqr", "stuvwx", "bar", 100, ""); + test_candidate2.set_network_name("testnet2"); rtc::SocketAddress host_address("www.google.com", 24601); host_address.SetResolvedIP(rtc::IPAddress(0x0A000001)); - Candidate test_candidate3( - "", 3, "spdy", host_address, 1476395008, "yzabcd", - "efghij", "baz", "testnet3", 150, ""); + Candidate test_candidate3("", 3, "spdy", host_address, 1476395008, "yzabcd", + "efghij", "baz", 150, ""); + test_candidate3.set_network_name("testnet3"); WriteError write_error; ParseError parse_error; rtc::scoped_ptr elem;