1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef CHROME_BROWSER_NET_NETWORK_STATS_H_
6 #define CHROME_BROWSER_NET_NETWORK_STATS_H_
12 #include "base/memory/scoped_ptr.h"
13 #include "base/metrics/histogram.h"
14 #include "base/time/time.h"
15 #include "chrome/browser/io_thread.h"
16 #include "chrome/browser/net/probe_message.h"
17 #include "net/base/address_list.h"
18 #include "net/base/completion_callback.h"
19 #include "net/base/host_port_pair.h"
20 #include "net/base/io_buffer.h"
21 #include "net/proxy/proxy_info.h"
24 class ClientSocketFactory
;
25 class DatagramClientSocket
;
27 class SingleRequestHostResolver
;
30 namespace chrome_browser_net
{
32 // This class is used for live experiment of network connectivity (for UDP)
33 // metrics. A small percentage of users participate in this experiment. All
34 // users (who are in the experiment) must have enabled "UMA upload".
35 // In the experiments, clients request the server to send some probing packets,
36 // collect some stats, and send back the results via UMA reports.
38 // This class collects the following stats from users who have opted in.
40 // b) packet inter-arrival time.
41 // c) packet losses for correlation and FEC experiments.
42 // d) packet losses for NAT binding test after idling for a certain period.
44 // There are three tests in one experiment. Right before each test, a
45 // HelloRequest is sent to get an updated token.
46 // 1. |START_PACKET_TEST|: 21 packets are sent from the server to the client
48 // 2. |PACED_PACKET_TEST| or |NON_PACED_PACKET_TEST|: After the first test,
49 // 21 packets are sent from the server to the client with or without pacing.
50 // If pacing, the pacing rate is computed from the first test.
51 // 3. |NAT_BIND_TEST|: 2 packets are sent from the server to the client with
52 // a randomly generated delay of 1~300 seconds.
53 // At the end of these tests, we send another HelloRequest to test whether
54 // the network is still connected and has not changed (e.g. from Wifi to 3g).
58 enum Status
{ // Used in UMA_HISTOGRAM_ENUMERATION.
59 SUCCESS
, // Successfully received bytes from the server.
60 SOCKET_CREATE_FAILED
, // Socket creation failed.
61 RESOLVE_FAILED
, // Host resolution failed.
62 CONNECT_FAILED
, // Connection to the server failed.
63 WRITE_FAILED
, // Sending a message to the server failed.
64 READ_TIMED_OUT
, // Reading the reply from the server timed out.
65 READ_FAILED
, // Reading the reply from the server failed.
66 STATUS_MAX
, // Bounding value.
69 enum ReadState
{ // Used to track if |socket_| has a pending read.
71 READ_STATE_READ_PENDING
,
74 enum WriteState
{ // Used to track if |socket_| has a pending write.
76 WRITE_STATE_WRITE_PENDING
,
79 // |TestType| specifies the possible tests we may run
80 // (except for the first and the last serving as boundaries).
82 // The first one is for requesting token, not a probe test. Put it here
83 // because we use it as a symbol for sending the HelloRequest packet to
86 START_PACKET_TEST
, // First packet loss test (no pacing).
87 NON_PACED_PACKET_TEST
, // Packet loss test with no pacing.
88 PACED_PACKET_TEST
, // Packet loss test with pacing.
89 // Test whether NAT binding expires after some idle period.
95 // Pointer |socket_factory| is NOT deleted by this class.
96 explicit NetworkStats(net::ClientSocketFactory
* socket_factory
);
97 // NetworkStats is deleted in TestPhaseComplete() when all tests are done.
100 // Start the client and connect to |server|.
101 // A client will request a token and then perform several tests.
102 // When the client finishes all tests, or when an error occurs causing the
103 // client to stop, |TestPhaseComplete| will be called with a net status code.
104 // |TestPhaseComplete| will collect histogram stats.
105 // Return true if successful in starting the client.
106 bool Start(net::HostResolver
* host_resolver
,
107 const net::HostPortPair
& server
,
108 uint16 histogram_port
,
109 bool has_proxy_server
,
111 uint32 bytes_for_packet_size_test
,
112 const net::CompletionCallback
& callback
);
115 friend class NetworkStatsTest
;
117 // Start the test specified by the current_test_index_. It also resets all
118 // the book keeping data, before starting the new test.
121 // Reset all the counters and the collected stats.
124 // Callback that is called when host resolution is completed.
125 void OnResolveComplete(int result
);
127 // Called after host is resolved. Creates UDPClientSocket and connects to the
128 // server. If successfully connected, then calls ConnectComplete() to start
129 // the network connectivity tests. Returns |false| if there is any error.
130 bool DoConnect(int result
);
132 // This method is called after socket connection is completed. It will start
133 // the process of sending packets to |server| by calling SendHelloPacket().
134 // Return false if connection is not established (result is less than 0).
135 bool ConnectComplete(int result
);
137 // Send a HelloRequest packet which asks for a token from the server. If
138 // a token is received, it will will add |START_PACKET_TEST| to the test
140 void SendHelloRequest();
142 // Send a ProbeRequest packet which requests the server to send a set
143 // of Probing packets.
144 void SendProbeRequest();
146 // Read and process the data. Called from OnReadComplete() or ReadData().
147 // This function calls TestPhaseComplete() if there is a significant network
148 // error or if all packets in the current test are received.
149 // Return true if TestPhaseComplete() is called otherwise return false.
150 bool ReadComplete(int result
);
152 // Callbacks when an internal IO (Read or Write) is completed.
153 void OnReadComplete(int result
);
154 void OnWriteComplete(int result
);
156 // Read data from server until an error or IO blocking occurs or reading is
157 // complete. Return the result value from socket reading and 0 if |socket_|
161 // Send data contained in |str| to server.
162 // Return a negative value if IO blocking occurs or there is an error.
163 // Otherwise return net::OK.
164 int SendData(const std::string
& str
);
166 // Update the send buffer (telling it that |bytes_sent| has been sent).
167 // And reset |write_buffer_|.
168 void UpdateSendBuffer(int bytes_sent
);
170 // Start a timer (with value |milliseconds|) for responses from the probe
171 // servers. |test_index| is the index of the test at vector |test_sequence_|
172 // and it is used as a parameter of the timer callback.
173 void StartReadDataTimer(uint32 milliseconds
, uint32 test_index
);
175 // Called when the StartReadDataTimer fires. |test_index| specifies
176 // the index of the test. If |current_test_index_| has changed to a
177 // different value, it indicates |test_index| has completed, then
178 // this method is a no-op.
179 void OnReadDataTimeout(uint32 test_index
);
181 // Collect network connectivity stats. This is called when all the data from
182 // server is read or when there is a failure during connect/read/write. It
183 // will either start the next phase of the test, or it will self destruct
184 // at the end of this method. Returns true if a new test wasn't started and it
185 // was self destructed.
186 bool TestPhaseComplete(Status status
, int result
);
188 // This method is called from TestPhaseComplete() and calls
189 // |finished_callback_| callback to indicate that the test has finished.
190 void DoFinishCallback(int result
);
192 // Update counters/metrics for the given |probe_packet|.
193 // Return true if all packets for the current test are received and
195 bool UpdateReception(const ProbePacket
& probe_packet
);
197 // Record all histograms for current test phase, which is assumed to be
198 // complete (i.e., we are no longer waiting for packets in this phase).
199 // |test_type| is the current test_type to be recorded. |status| is the
200 // status of the current test.
201 void RecordHistograms(TestType test_type
);
203 // Collect the following network connectivity stats when
204 // kMaximumSequentialPackets (21) packets are sent from the server.
205 // a) Client received at least one packet.
206 // b) Client received the nth packet.
207 // c) The number of packets received for each subsequence of packets 1...n.
208 void RecordPacketsReceivedHistograms(TestType test_type
);
210 // Collect the following network connectivity stats for the first
211 // kMaximumCorrelationPackets (6) packets in a test.
212 // Success/failure of each packet, to estimate reachability for users,
213 // and to estimate if there is a probabalistic dependency in packet loss when
214 // kMaximumCorrelationPackets packets are sent consecutively.
215 void RecordPacketLossSeriesHistograms(TestType test_type
);
217 // Collect the average inter-arrival time (scaled up by 20 times because the
218 // minimum time value in a histogram is 1ms) of a sequence of probing packets.
219 void RecordInterArrivalHistograms(TestType test_type
);
221 // Collect the RTT for the packet specified by the |index| in the current
223 void RecordRTTHistograms(TestType test_type
, uint32 index
);
225 // Collect whether the second packet in the NAT test is received for the
227 void RecordNATTestReceivedHistograms(Status status
);
229 // Collect whether we have the requested packet size was received or not in
230 // the PACKET_SIZE_TEST test.
231 void RecordPacketSizeTestReceivedHistograms(Status status
);
233 // Record the time duration between sending the probe request and receiving
234 // the last probe packet excluding the pacing time requested by the client.
235 // This applies to both NAT bind test and paced/non-paced packet test.
236 void RecordSendToLastRecvDelayHistograms(TestType test_type
);
238 // Return the next test type (internally increment |current_test_index_|)
239 // in |test_sequence_|;
240 TestType
GetNextTest();
242 // These static variables are defined so that they can be changed in testing.
243 // Maximum number of tests in one activation of the experiment.
244 static uint32 maximum_tests_
;
245 // Maximum number of packets for START/PACED/NON_PACED tests.
246 static uint32 maximum_sequential_packets_
;
247 // Maximum number of packets for NAT binding test.
248 static uint32 maximum_NAT_packets_
;
249 // Maximum time duration between the two packets for NAT Bind testing.
250 static uint32 maximum_NAT_idle_seconds_
;
251 // Whether to start the probe test immediately after connect success.
252 // Used for unittest.
253 static bool start_test_after_connect_
;
255 // The socket handler for this session.
256 scoped_ptr
<net::DatagramClientSocket
> socket_
;
258 net::ClientSocketFactory
* socket_factory_
;
260 // The read buffer used to read data from the socket.
261 scoped_refptr
<net::IOBuffer
> read_buffer_
;
263 // The write buffer used to write data to the socket.
264 scoped_refptr
<net::DrainableIOBuffer
> write_buffer_
;
266 // Specify the port for which we are testing the network connectivity.
267 uint16 histogram_port_
;
269 // Specify if there is a proxy server or not.
270 bool has_proxy_server_
;
272 // HostResolver used to find the IP addresses.
273 scoped_ptr
<net::SingleRequestHostResolver
> resolver_
;
275 // Addresses filled out by HostResolver after host resolution is completed.
276 net::AddressList addresses_
;
278 // Callback to call when test is successefully finished or whenever
279 // there is an error (this will be used by unittests to check the result).
280 net::CompletionCallback finished_callback_
;
282 // RTTs for each packet.
283 std::vector
<base::TimeDelta
> packet_rtt_
;
285 // Time when sending probe_request, used for computing RTT.
286 base::TimeTicks probe_request_time_
;
288 // Size of the probe packets requested to be sent from servers. We don't use
289 // |probe_packet_bytes_| during PACKET_SIZE_TEST.
290 uint32 probe_packet_bytes_
;
292 // Size of the packet requested to be sent from servers for PACKET_SIZE_TEST.
293 uint32 bytes_for_packet_size_test_
;
295 // bitmask indicating which packets are received.
296 std::bitset
<21> packets_received_mask_
;
298 // Arrival time of the first packet in the current test.
299 base::TimeTicks first_arrival_time_
;
300 // Arrival time of the most recently received packet in the current test.
301 base::TimeTicks last_arrival_time_
;
302 // Average time between two consecutive packets. It is updated when either all
303 // packets are received or timeout happens in the current test.
304 base::TimeDelta inter_arrival_time_
;
305 // Target time duration for sending two consecutive packets at the server.
306 // It should be 0 for StartPacket test or NonPacedPacket test. For
307 // PacedPacket test, it is derived from the inter_arrival_time_ in the
308 // previous (StartPacket) test. For NATBind test, it is randomly generated
309 // between 1 second and |maximum_NAT_idle_seconds_| seconds.
310 base::TimeDelta pacing_interval_
;
311 // A list of tests that will be performed in sequence.
312 std::vector
<TestType
> test_sequence_
;
313 uint32 current_test_index_
; // Index of the current test.
315 ProbeMessage probe_message_
;
317 // Token received from server for authentication.
318 ProbePacket_Token token_
;
320 // The state variables to track pending reads/writes.
321 ReadState read_state_
;
322 WriteState write_state_
;
324 // We use this factory to create timeout tasks for socket's ReadData.
325 base::WeakPtrFactory
<NetworkStats
> weak_factory_
;
327 DISALLOW_COPY_AND_ASSIGN(NetworkStats
);
330 class ProxyDetector
{
332 // Used for the callback that is called from |OnResolveProxyComplete|.
333 typedef base::Callback
<void(bool)> OnResolvedCallback
;
335 // Construct a ProxyDetector object that finds out if access to
336 // |server_address| goes through a proxy server or not. Calls the |callback|
337 // after proxy resolution is completed by currying the proxy resolution
339 ProxyDetector(net::ProxyService
* proxy_service
,
340 const net::HostPortPair
& server_address
,
341 OnResolvedCallback callback
);
343 // This method uses |proxy_service_| to resolve the proxy for
344 // |server_address_|.
345 void StartResolveProxy();
348 // This object is deleted from |OnResolveProxyComplete|.
351 // Call the |callback_| by currying the proxy resolution status.
352 void OnResolveProxyComplete(int result
);
354 // |proxy_service_| specifies the proxy service that is to be used to find
355 // if access to |server_address_| goes through proxy server or not.
356 net::ProxyService
* proxy_service_
;
358 // |server_address_| specifies the server host and port pair for which we are
359 // trying to see if access to it, goes through proxy or not.
360 net::HostPortPair server_address_
;
362 // |callback_| will be called after proxy resolution is completed.
363 OnResolvedCallback callback_
;
365 // |proxy_info_| holds proxy information returned by ResolveProxy.
366 net::ProxyInfo proxy_info_
;
368 // Indicate if there is a pending a proxy resolution. We use this to assert
369 // that there is no in-progress proxy resolution request.
370 bool has_pending_proxy_resolution_
;
371 DISALLOW_COPY_AND_ASSIGN(ProxyDetector
);
374 // This collects the network connectivity stats for UDP protocol for small
375 // percentage of users who are participating in the experiment (by enabling
376 // "UMA upload"). This method gets called only if UMA upload to the
377 // server has succeeded.
378 void CollectNetworkStats(const std::string
& network_stats_server_url
,
379 IOThread
* io_thread
);
381 // This starts a series of tests randomly selected among one of the three
382 // choices of probe packet sizes: 100 Bytes, 500 Bytes, 1200 Bytes.
383 void StartNetworkStatsTest(net::HostResolver
* host_resolver
,
384 const net::HostPortPair
& server_address
,
385 uint16 histogram_port
,
386 bool has_proxy_server
);
388 } // namespace chrome_browser_net
390 #endif // CHROME_BROWSER_NET_NETWORK_STATS_H_