diff options
Diffstat (limited to 'chrome/browser/net/network_stats.cc')
-rw-r--r-- | chrome/browser/net/network_stats.cc | 594 |
1 files changed, 351 insertions, 243 deletions
diff --git a/chrome/browser/net/network_stats.cc b/chrome/browser/net/network_stats.cc index af7f299..c134f09 100644 --- a/chrome/browser/net/network_stats.cc +++ b/chrome/browser/net/network_stats.cc @@ -22,7 +22,6 @@ #include "net/base/network_change_notifier.h" #include "net/base/test_completion_callback.h" #include "net/proxy/proxy_service.h" -#include "net/socket/tcp_client_socket.h" #include "net/udp/udp_client_socket.h" #include "net/udp/udp_server_socket.h" @@ -30,21 +29,18 @@ using content::BrowserThread; namespace chrome_browser_net { -// This specifies the number of bytes to be sent to the TCP/UDP servers as part +// This specifies the number of bytes to be sent to the UDP echo servers as part // of small packet size test. static const uint32 kSmallTestBytesToSend = 100; -// This specifies the number of bytes to be sent to the TCP/UDP servers as part +// This specifies the number of bytes to be sent to the UDP echo servers as part // of medium packet size test. static const uint32 kMediumTestBytesToSend = 500; -// This specifies the number of bytes to be sent to the TCP/UDP servers as part +// This specifies the number of bytes to be sent to the UDP echo servers as part // of large packet size test. static const uint32 kLargeTestBytesToSend = 1200; -// This specifies the maximum message (payload) size. -static const uint32 kMaxMessage = 2048; - // This specifies starting position of the <version> and length of the // <version> in "echo request" and "echo response". static const uint32 kVersionNumber = 1; @@ -84,11 +80,9 @@ static const uint32 kPacketNumberLength = 10; // "echo response". static const uint32 kEncodedPayloadStart = kKeyEnd; -// HistogramPortSelector and kPorts should be kept in sync. -static const int32 kPorts[] = {53, 80, 587, 6121, 8080, 999999}; - -// The packet number that is to be sent to the server. -static uint32 g_packet_number_ = 0; +// HistogramPortSelector and kPorts should be kept in sync. Port 999999 is +// used by the unit tests. +static const int32 kPorts[] = {6121, 999999}; // Maximum number of packets that can be sent to the server for packet loss // correlation test. @@ -97,16 +91,26 @@ static const uint32 kMaximumCorrelationPackets = 6; // Maximum number of packets that can be sent to the server. static const uint32 kMaximumSequentialPackets = 21; +// This specifies the maximum message (payload) size. +static const uint32 kMaxMessage = kMaximumSequentialPackets * 2048; + // NetworkStats methods and members. NetworkStats::NetworkStats() - : load_size_(0), + : read_buffer_(NULL), + write_buffer_(NULL), + load_size_(0), bytes_to_read_(0), bytes_to_send_(0), has_proxy_server_(false), packets_to_send_(0), packets_sent_(0), - base_packet_number_(0), + packets_received_(0), packets_received_mask_(0), + packet_number_(0), + base_packet_number_(0), + sending_complete_(false), + current_test_(START_PACKET_TEST), + next_test_(TEST_TYPE_MAX), ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { } @@ -142,6 +146,17 @@ bool NetworkStats::Start(net::HostResolver* host_resolver, return DoConnect(rv); } +void NetworkStats::RestartPacketTest() { + ResetData(); + current_test_ = next_test_; + next_test_ = TEST_TYPE_MAX; + if (!bytes_to_read_) { + read_buffer_ = NULL; + ReadData(); + } + SendPacket(); +} + void NetworkStats::Initialize( uint32 bytes_to_send, HistogramPortSelector histogram_port, @@ -151,13 +166,65 @@ void NetworkStats::Initialize( DCHECK(bytes_to_send); // We should have data to send. DCHECK(packets_to_send); // We should send at least 1 packet. DCHECK_LE(bytes_to_send, kLargeTestBytesToSend); + DCHECK_LE(packets_to_send, 8 * sizeof(packets_received_mask_)); load_size_ = bytes_to_send; packets_to_send_ = packets_to_send; - histogram_port_ = histogram_port; has_proxy_server_ = has_proxy_server; finished_callback_ = finished_callback; + ResetData(); + packet_number_ = base::RandInt(1 << 28, INT_MAX); +} + +void NetworkStats::ResetData() { + write_buffer_ = NULL; + bytes_to_send_ = 0; + packet_status_.clear(); + packet_status_.resize(packets_to_send_); + packets_sent_ = 0; + packets_received_ = 0; + packets_received_mask_ = 0; + sending_complete_ = false; +} + +void NetworkStats::OnResolveComplete(int result) { + DoConnect(result); +} + +bool NetworkStats::DoConnect(int result) { + if (result != net::OK) { + Finish(RESOLVE_FAILED, result); + return false; + } + + net::UDPClientSocket* udp_socket = + new net::UDPClientSocket(net::DatagramSocket::DEFAULT_BIND, + net::RandIntCallback(), + NULL, + net::NetLog::Source()); + if (!udp_socket) { + Finish(SOCKET_CREATE_FAILED, net::ERR_INVALID_ARGUMENT); + return false; + } + set_socket(udp_socket); + + if (addresses().empty()) { + Finish(RESOLVE_FAILED, net::ERR_INVALID_ARGUMENT); + return false; + } + + const net::IPEndPoint& endpoint = addresses().front(); + int rv = udp_socket->Connect(endpoint); + if (rv < 0) { + Finish(CONNECT_FAILED, rv); + return false; + } + + const int kSocketBufferSize = 2 * packets_to_send_ * 2048; + udp_socket->SetSendBufferSize(kSocketBufferSize); + udp_socket->SetReceiveBufferSize(kSocketBufferSize); + return ConnectComplete(rv); } bool NetworkStats::ConnectComplete(int result) { @@ -166,24 +233,52 @@ bool NetworkStats::ConnectComplete(int result) { return false; } - base_packet_number_ = g_packet_number_; - start_time_ = base::TimeTicks::Now(); + ReadData(); SendPacket(); return true; } -void NetworkStats::DoFinishCallback(int result) { - if (!finished_callback_.is_null()) { - net::CompletionCallback callback = finished_callback_; - finished_callback_.Reset(); - callback.Run(result); - } +void NetworkStats::SendPacket() { + while (true) { + if (bytes_to_send_ == 0u) { + if (packets_sent_ >= packets_to_send_) { + // Timeout if we don't get response back from echo servers in 30 secs. + sending_complete_ = true; + const int kReadDataTimeoutMs = 30000; + StartReadDataTimer(kReadDataTimeoutMs); + break; + } + + ++packet_number_; + if (packets_sent_ == 0) + base_packet_number_ = packet_number_; + bytes_to_send_ = SendingPacketSize(); + SendNextPacketAfterDelay(); + break; + } + + int rv = SendData(); + if (rv < 0) { + if (rv != net::ERR_IO_PENDING) + Finish(WRITE_FAILED, rv); + break; + } + DCHECK_EQ(bytes_to_send_, 0u); + }; } -void NetworkStats::set_socket(net::Socket* socket) { - DCHECK(socket); - DCHECK(!socket_.get()); - socket_.reset(socket); +void NetworkStats::SendNextPacketAfterDelay() { + if (current_test_ == PACED_PACKET_TEST) { + MessageLoop::current()->PostDelayedTask( + FROM_HERE, + base::Bind(&NetworkStats::SendPacket, weak_factory_.GetWeakPtr()), + average_time_); + return; + } + + MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(&NetworkStats::SendPacket, weak_factory_.GetWeakPtr())); } bool NetworkStats::ReadComplete(int result) { @@ -194,13 +289,29 @@ bool NetworkStats::ReadComplete(int result) { return true; } - encoded_message_.append(read_buffer_->data(), result); + if (result > 0) { + std::string encoded_message; + encoded_message.append(read_buffer_->data(), result); + if (VerifyBytes(encoded_message) == SUCCESS) { + base::TimeTicks now = base::TimeTicks::Now(); + if (packets_received_ == 0) + packet_1st_byte_read_time_ = now; + packet_last_byte_read_time_ = now; + + DCHECK_GE(bytes_to_read_, static_cast<uint32>(result)); + if (bytes_to_read_ >= static_cast<uint32>(result)) + bytes_to_read_ -= result; + ++packets_received_; + } + } read_buffer_ = NULL; - bytes_to_read_ -= result; // No more data to read. if (!bytes_to_read_ || result == 0) { + if (!sending_complete_) + return false; + Status status = VerifyPackets(); if (status == SUCCESS) Finish(status, net::OK); @@ -211,35 +322,6 @@ bool NetworkStats::ReadComplete(int result) { return false; } -void NetworkStats::OnResolveComplete(int result) { - DoConnect(result); -} - -void NetworkStats::SendPacket() { - DCHECK_EQ(bytes_to_send_, 0u); - uint32 sending_packet_size = SendingPacketSize(); - - while (packets_to_send_ > packets_sent_) { - ++g_packet_number_; - - bytes_to_send_ = sending_packet_size; - int rv = SendData(); - if (rv < 0) { - if (rv != net::ERR_IO_PENDING) - Finish(WRITE_FAILED, rv); - return; - } - DCHECK_EQ(bytes_to_send_, 0u); - } - - // Timeout if we don't get response back from echo servers in 60 secs. - const int kReadDataTimeoutMs = 60000; - StartReadDataTimer(kReadDataTimeoutMs); - - bytes_to_read_ = packets_sent_ * ReceivingPacketSize(); - ReadData(); -} - void NetworkStats::OnReadComplete(int result) { if (!ReadComplete(result)) { // Called ReadData() via PostDelayedTask() to avoid recursion. Added a delay @@ -282,7 +364,7 @@ void NetworkStats::ReadData() { int rv; do { if (!socket_.get()) - return; + break; DCHECK(!read_buffer_.get()); @@ -293,10 +375,11 @@ void NetworkStats::ReadData() { base::Bind(&NetworkStats::OnReadComplete, base::Unretained(this))); if (rv == net::ERR_IO_PENDING) - return; + break; + // If we have read all the data then return. if (ReadComplete(rv)) - return; + break; } while (rv > 0); } @@ -304,10 +387,23 @@ int NetworkStats::SendData() { DCHECK(bytes_to_send_); // We should have data to send. do { if (!write_buffer_.get()) { + // Send a new packet. scoped_refptr<net::IOBufferWithSize> buffer( new net::IOBufferWithSize(bytes_to_send_)); GetEchoRequest(buffer); write_buffer_ = new net::DrainableIOBuffer(buffer, bytes_to_send_); + + // As soon as we write, a read could happen. Thus update all the book + // keeping data. + bytes_to_read_ += ReceivingPacketSize(); + ++packets_sent_; + if (packets_sent_ >= packets_to_send_) + sending_complete_ = true; + + uint32 packet_index = packet_number_ - base_packet_number_; + DCHECK_GE(packet_index, 0u); + DCHECK_LT(packet_index, packet_status_.size()); + packet_status_[packet_index].start_time_ = base::TimeTicks::Now(); } if (!socket_.get()) @@ -337,18 +433,21 @@ void NetworkStats::DidSendData(int bytes_sent) { if (!write_buffer_->BytesRemaining()) write_buffer_ = NULL; bytes_to_send_ -= bytes_sent; - if (bytes_to_send_ == 0) - ++packets_sent_; } void NetworkStats::StartReadDataTimer(int milliseconds) { MessageLoop::current()->PostDelayedTask( FROM_HERE, - base::Bind(&NetworkStats::OnReadDataTimeout, weak_factory_.GetWeakPtr()), + base::Bind(&NetworkStats::OnReadDataTimeout, + weak_factory_.GetWeakPtr(), + base_packet_number_), base::TimeDelta::FromMilliseconds(milliseconds)); } -void NetworkStats::OnReadDataTimeout() { +void NetworkStats::OnReadDataTimeout(uint32 test_base_packet_number) { + if (test_base_packet_number != base_packet_number_) + return; + Status status = VerifyPackets(); if (status == SUCCESS) Finish(status, net::OK); @@ -395,7 +494,7 @@ void NetworkStats::GetEchoRequest(net::IOBufferWithSize* io_buffer) { memcpy(buffer + kVersionStart, version.c_str(), kVersionLength); // Copy the packet_number into the payload. - std::string packet_number = base::StringPrintf("%010d", g_packet_number_); + std::string packet_number = base::StringPrintf("%010d", packet_number_); DCHECK(kPacketNumberLength == packet_number.length()); DCHECK_GE(buffer_size, kPayloadStart + kPacketNumberLength); memcpy(buffer + kPayloadStart, packet_number.c_str(), kPacketNumberLength); @@ -426,24 +525,48 @@ void NetworkStats::GetEchoRequest(net::IOBufferWithSize* io_buffer) { } NetworkStats::Status NetworkStats::VerifyPackets() { - uint32 packet_start = 0; - size_t message_length = encoded_message_.length(); - uint32 receiving_packet_size = ReceivingPacketSize(); Status status = SUCCESS; - for (uint32 i = 0; i < packets_to_send_; i++) { - if (message_length <= packet_start) { - status = ZERO_LENGTH_ERROR; - break; - } - std::string response = - encoded_message_.substr(packet_start, receiving_packet_size); - Status packet_status = VerifyBytes(response); - if (packet_status != SUCCESS) - status = packet_status; - packet_start += receiving_packet_size; + uint32 successful_packets = 0; + + for (uint32 i = 0; i < packet_status_.size(); i++) { + if (packets_received_mask_ & (1 << i)) + ++successful_packets; } - if (message_length > packet_start) + + if (packets_received_ > packets_to_send_) status = TOO_MANY_PACKETS; + + if (packets_to_send_ > successful_packets) + status = SOME_PACKETS_NOT_VERIFIED; + + if (current_test_ == START_PACKET_TEST && + packets_to_send_ == kMaximumSequentialPackets && + successful_packets > 1) { + base::TimeDelta total_time; + if (packet_last_byte_read_time_ > packet_1st_byte_read_time_) { + total_time = + packet_last_byte_read_time_ - packet_1st_byte_read_time_; + } + average_time_ = total_time / (successful_packets - 1); + std::string histogram_name = base::StringPrintf( + "NetConnectivity3.%s.Sent%02d.%d.%dB.PacketDelay", + TestName(), + kMaximumSequentialPackets, + kPorts[histogram_port_], + load_size_); + base::Histogram* histogram = base::Histogram::FactoryTimeGet( + histogram_name, base::TimeDelta::FromMilliseconds(1), + base::TimeDelta::FromSeconds(30), 50, + base::Histogram::kUmaTargetedHistogramFlag); + histogram->AddTime(total_time); + + int experiment_to_run = base::RandInt(1, 2); + if (experiment_to_run == 1) + next_test_ = NON_PACED_PACKET_TEST; + else + next_test_ = PACED_PACKET_TEST; + } + return status; } @@ -496,9 +619,11 @@ NetworkStats::Status NetworkStats::VerifyBytes(const std::string& response) { char packet_number_data[kPacketNumberLength + 1]; memset(packet_number_data, 0, kPacketNumberLength + 1); memcpy(packet_number_data, decoded_data, kPacketNumberLength); - uint32 packet_number = atoi(packet_number_data); - uint32 packet_index = packet_number - base_packet_number_; - if (packet_index > packets_to_send_) + uint32 packet_number_received = atoi(packet_number_data); + if (packet_number_received < base_packet_number_) + return PREVIOUS_PACKET_NUMBER; + uint32 packet_index = packet_number_received - base_packet_number_; + if (packet_index >= packets_to_send_) return INVALID_PACKET_NUMBER; stream_.Reset(); @@ -507,26 +632,100 @@ NetworkStats::Status NetworkStats::VerifyBytes(const std::string& response) { return PATTERN_CHANGED; } - packets_received_mask_ |= 1 << (packet_index - 1); + if (packets_received_mask_ & (1 << packet_index)) + return DUPLICATE_PACKET; + + packets_received_mask_ |= 1 << packet_index; + DCHECK_GE(packet_index, 0u); + DCHECK_LT(packet_index, packet_status_.size()); + packet_status_[packet_index].end_time_ = base::TimeTicks::Now(); return SUCCESS; } -void NetworkStats::RecordAcksReceivedHistograms(const char* load_size_string) { +void NetworkStats::Finish(Status status, int result) { + // Set the base_packet_number_ for the start of next test. Changing the + // |base_packet_number_| indicates to OnReadDataTimeout that the Finish has + // already been called for the test and that it doesn't need to call Finish + // again. + base_packet_number_ = packet_number_ + 1; + RecordHistograms(PROTOCOL_UDP, status, result); + + if (next_test() == NON_PACED_PACKET_TEST || + next_test() == PACED_PACKET_TEST) { + MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(&NetworkStats::RestartPacketTest, + weak_factory_.GetWeakPtr())); + return; + } + + DoFinishCallback(result); + + // Close the socket so that there are no more IO operations. + net::UDPClientSocket* udp_socket = + static_cast<net::UDPClientSocket*>(socket()); + if (udp_socket) + udp_socket->Close(); + + delete this; +} + +void NetworkStats::DoFinishCallback(int result) { + if (!finished_callback_.is_null()) { + net::CompletionCallback callback = finished_callback_; + finished_callback_.Reset(); + callback.Run(result); + } +} + +void NetworkStats::RecordHistograms(const ProtocolValue& protocol, + const Status& status, + int result) { + if (packets_to_send_ != kMaximumSequentialPackets && + packets_to_send_ != kMaximumCorrelationPackets) { + return; + } + + std::string load_size_string = base::StringPrintf("%dB", load_size_); + + if (packets_to_send_ == kMaximumCorrelationPackets) { + RecordPacketLossSeriesHistograms( + protocol, load_size_string, status, result); + return; + } + + for (uint32 i = 0; i < 3; i++) + RecordRTTHistograms(protocol, load_size_string, i); + + RecordRTTHistograms(protocol, load_size_string, 9); + RecordRTTHistograms(protocol, load_size_string, 19); + + RecordAcksReceivedHistograms(load_size_string); +} + +void NetworkStats::RecordAcksReceivedHistograms( + const std::string& load_size_string) { + DCHECK_EQ(packets_to_send_, kMaximumSequentialPackets); + + const char* test_name = TestName(); bool received_atleast_one_packet = packets_received_mask_ > 0; + std::string histogram_name = base::StringPrintf( - "NetConnectivity2.Sent%d.GotAnAck.%d.%s", + "NetConnectivity3.%s.Sent%02d.GotAnAck.%d.%s", + test_name, kMaximumSequentialPackets, kPorts[histogram_port_], - load_size_string); + load_size_string.c_str()); base::Histogram* got_an_ack_histogram = base::BooleanHistogram::FactoryGet( histogram_name, base::Histogram::kUmaTargetedHistogramFlag); got_an_ack_histogram->AddBoolean(received_atleast_one_packet); histogram_name = base::StringPrintf( - "NetConnectivity2.Sent%d.PacketsSent.%d.%s", + "NetConnectivity3.%s.Sent%02d.PacketsSent.%d.%s", + test_name, kMaximumSequentialPackets, kPorts[histogram_port_], - load_size_string); + load_size_string.c_str()); base::Histogram* packets_sent_histogram = base::Histogram::FactoryGet( histogram_name, @@ -538,14 +737,15 @@ void NetworkStats::RecordAcksReceivedHistograms(const char* load_size_string) { return; histogram_name = base::StringPrintf( - "NetConnectivity2.Sent%d.AckReceivedForNthPacket.%d.%s", + "NetConnectivity3.%s.Sent%02d.AckReceivedForNthPacket.%02d.%s", + test_name, kMaximumSequentialPackets, kPorts[histogram_port_], - load_size_string); + load_size_string.c_str()); base::Histogram* ack_received_for_nth_packet_histogram = base::Histogram::FactoryGet( histogram_name, - 1, kMaximumSequentialPackets, kMaximumSequentialPackets + 1, + 1, kMaximumSequentialPackets + 1, kMaximumSequentialPackets + 2, base::Histogram::kUmaTargetedHistogramFlag); int count = 0; @@ -558,11 +758,12 @@ void NetworkStats::RecordAcksReceivedHistograms(const char* load_size_string) { if (packet_number < 2) continue; histogram_name = base::StringPrintf( - "NetConnectivity2.Sent%d.AcksReceivedFromFirst%dPackets.%d.%s", + "NetConnectivity3.%s.Sent%02d.AcksReceivedFromFirst%02dPackets.%d.%s", + test_name, kMaximumSequentialPackets, packet_number, kPorts[histogram_port_], - load_size_string); + load_size_string.c_str()); base::Histogram* acks_received_count_histogram = base::Histogram::FactoryGet( histogram_name, 1, packet_number, packet_number + 1, @@ -573,24 +774,27 @@ void NetworkStats::RecordAcksReceivedHistograms(const char* load_size_string) { void NetworkStats::RecordPacketLossSeriesHistograms( const ProtocolValue& protocol, + const std::string& load_size_string, const Status& status, - const char* load_size_string, int result) { - if (packets_to_send_ < 2 || protocol != PROTOCOL_UDP) - return; + DCHECK_EQ(packets_to_send_, kMaximumCorrelationPackets); - // Build "NetConnectivity2.Send6.SeriesAcked.<port>.<load_size>" histogram + const char* test_name = TestName(); + + // Build "NetConnectivity3.Send6.SeriesAcked.<port>.<load_size>" histogram // name. Total number of histograms are 5*2. std::string series_acked_histogram_name = base::StringPrintf( - "NetConnectivity2.Send6.SeriesAcked.%d.%s", + "NetConnectivity3.%s.Send6.SeriesAcked.%d.%s", + test_name, kPorts[histogram_port_], - load_size_string); - // Build "NetConnectivity2.Send6.PacketsSent.<port>.<load_size>" histogram + load_size_string.c_str()); + // Build "NetConnectivity3.Send6.PacketsSent.<port>.<load_size>" histogram // name. Total number of histograms are 5*2. std::string packets_sent_histogram_name = base::StringPrintf( - "NetConnectivity2.Send6.PacketsSent.%d.%s", + "NetConnectivity3.%s.Send6.PacketsSent.%d.%s", + test_name, kPorts[histogram_port_], - load_size_string); + load_size_string.c_str()); // If we are running without a proxy, we'll generate 2 distinct histograms in // each case, one will have the ".NoProxy" suffix. @@ -616,144 +820,48 @@ void NetworkStats::RecordPacketLossSeriesHistograms( } } -void NetworkStats::RecordHistograms(const ProtocolValue& protocol, - const Status& status, - int result) { - // Build <load_size> string. - const char* kSmallLoadString = "100B"; - const char* kMediumLoadString = "500B"; - const char* kLargeLoadString = "1K"; - const char* load_size_string; - if (load_size_ == kSmallTestBytesToSend) - load_size_string = kSmallLoadString; - else if (load_size_ == kMediumTestBytesToSend) - load_size_string = kMediumLoadString; - else - load_size_string = kLargeLoadString; - - if (packets_to_send_ == kMaximumSequentialPackets) { - RecordAcksReceivedHistograms(load_size_string); - return; - } - RecordPacketLossSeriesHistograms(protocol, status, load_size_string, result); -} - -// UDPStatsClient methods and members. -UDPStatsClient::UDPStatsClient() - : NetworkStats() { -} - -UDPStatsClient::~UDPStatsClient() { -} - -bool UDPStatsClient::DoConnect(int result) { - if (result != net::OK) { - Finish(RESOLVE_FAILED, result); - return false; - } - - net::UDPClientSocket* udp_socket = - new net::UDPClientSocket(net::DatagramSocket::DEFAULT_BIND, - net::RandIntCallback(), - NULL, - net::NetLog::Source()); - if (!udp_socket) { - Finish(SOCKET_CREATE_FAILED, net::ERR_INVALID_ARGUMENT); - return false; - } - set_socket(udp_socket); - - if (addresses().empty()) { - Finish(RESOLVE_FAILED, net::ERR_INVALID_ARGUMENT); - return false; - } - - const net::IPEndPoint& endpoint = addresses().front(); - int rv = udp_socket->Connect(endpoint); - if (rv < 0) { - Finish(CONNECT_FAILED, rv); - return false; - } - return NetworkStats::ConnectComplete(rv); -} - -bool UDPStatsClient::ReadComplete(int result) { - DCHECK_NE(net::ERR_IO_PENDING, result); - if (result <= 0) { - Finish(READ_FAILED, result); - return true; - } - return NetworkStats::ReadComplete(result); -} - -void UDPStatsClient::Finish(Status status, int result) { - RecordHistograms(PROTOCOL_UDP, status, result); - - DoFinishCallback(result); - - // Close the socket so that there are no more IO operations. - net::UDPClientSocket* udp_socket = - static_cast<net::UDPClientSocket*>(socket()); - if (udp_socket) - udp_socket->Close(); - - delete this; -} - -// TCPStatsClient methods and members. -TCPStatsClient::TCPStatsClient() { -} - -TCPStatsClient::~TCPStatsClient() { -} - -bool TCPStatsClient::DoConnect(int result) { - if (result != net::OK) { - Finish(RESOLVE_FAILED, result); - return false; - } - - net::TCPClientSocket* tcp_socket = - new net::TCPClientSocket(addresses(), NULL, net::NetLog::Source()); - if (!tcp_socket) { - Finish(SOCKET_CREATE_FAILED, net::ERR_INVALID_ARGUMENT); - return false; - } - set_socket(tcp_socket); - - int rv = tcp_socket->Connect(base::Bind(&TCPStatsClient::OnConnectComplete, - base::Unretained(this))); - if (rv == net::ERR_IO_PENDING) - return true; - - return NetworkStats::ConnectComplete(rv); -} - -void TCPStatsClient::OnConnectComplete(int result) { - NetworkStats::ConnectComplete(result); +void NetworkStats::RecordRTTHistograms(const ProtocolValue& protocol, + const std::string& load_size_string, + uint32 index) { + DCHECK_GE(index, 0u); + DCHECK_LT(index, packet_status_.size()); + + const char* test_name = TestName(); + std::string rtt_histogram_name = base::StringPrintf( + "NetConnectivity3.%s.Sent%02d.Success.RTT.Packet%02d.%d.%s", + test_name, + packets_to_send_, + index + 1, + kPorts[histogram_port_], + load_size_string.c_str()); + base::Histogram* rtt_histogram = base::Histogram::FactoryTimeGet( + rtt_histogram_name, + base::TimeDelta::FromMilliseconds(10), + base::TimeDelta::FromSeconds(30), 50, + base::Histogram::kUmaTargetedHistogramFlag); + base::TimeDelta duration = + packet_status_[index].end_time_ - packet_status_[index].start_time_; + rtt_histogram->AddTime(duration); } -bool TCPStatsClient::ReadComplete(int result) { - DCHECK_NE(net::ERR_IO_PENDING, result); - if (result < 0) { - Finish(READ_FAILED, result); - return true; +const char* NetworkStats::TestName() { + switch (current_test_) { + case START_PACKET_TEST: + return "StartPacket"; + case NON_PACED_PACKET_TEST: + return "NonPacedPacket"; + case PACED_PACKET_TEST: + return "PacedPacket"; + default: + NOTREACHED(); + return "None"; } - return NetworkStats::ReadComplete(result); } -void TCPStatsClient::Finish(Status status, int result) { - RecordHistograms(PROTOCOL_TCP, status, result); - - DoFinishCallback(result); - - // Disconnect the socket so that there are no more IO operations. - net::TCPClientSocket* tcp_socket = - static_cast<net::TCPClientSocket*>(socket()); - if (tcp_socket) - tcp_socket->Disconnect(); - - delete this; +void NetworkStats::set_socket(net::Socket* socket) { + DCHECK(socket); + DCHECK(!socket_.get()); + socket_.reset(socket); } // ProxyDetector methods and members. @@ -834,7 +942,7 @@ void CollectNetworkStats(const std::string& network_stats_server, NetworkStats::PORT_6121; if (!trial.get()) { - // Set up a field trial to collect network stats for UDP and TCP. + // Set up a field trial to collect network stats for UDP. const base::FieldTrial::Probability kDivisor = 1000; // Enable the connectivity testing for 0.5% of the users in stable channel. @@ -902,16 +1010,16 @@ void StartNetworkStatsTest(net::HostResolver* host_resolver, switch (experiment_to_run) { case 1: { - UDPStatsClient* udp_stats_client = new UDPStatsClient(); + NetworkStats* udp_stats_client = new NetworkStats(); udp_stats_client->Start( host_resolver, server_address, histogram_port, has_proxy_server, - kSmallTestBytesToSend, kMaximumCorrelationPackets, + kLargeTestBytesToSend, kMaximumCorrelationPackets, net::CompletionCallback()); } break; case 2: { - UDPStatsClient* udp_stats_client = new UDPStatsClient(); + NetworkStats* udp_stats_client = new NetworkStats(); udp_stats_client->Start( host_resolver, server_address, histogram_port, has_proxy_server, kSmallTestBytesToSend, kMaximumSequentialPackets, @@ -920,7 +1028,7 @@ void StartNetworkStatsTest(net::HostResolver* host_resolver, break; case 3: { - UDPStatsClient* udp_stats_client = new UDPStatsClient(); + NetworkStats* udp_stats_client = new NetworkStats(); udp_stats_client->Start( host_resolver, server_address, histogram_port, has_proxy_server, kMediumTestBytesToSend, kMaximumSequentialPackets, @@ -929,7 +1037,7 @@ void StartNetworkStatsTest(net::HostResolver* host_resolver, break; case 4: { - UDPStatsClient* udp_stats_client = new UDPStatsClient(); + NetworkStats* udp_stats_client = new NetworkStats(); udp_stats_client->Start( host_resolver, server_address, histogram_port, has_proxy_server, kLargeTestBytesToSend, kMaximumSequentialPackets, |