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. 4 5 #ifndef CHROME_BROWSER_NET_NETWORK_STATS_H_ 6 #define CHROME_BROWSER_NET_NETWORK_STATS_H_ 7 8 #include <bitset> 9 #include <string> 10 #include <vector> 11 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" 22 23 namespace net { 24 class ClientSocketFactory; 25 class DatagramClientSocket; 26 class HostResolver; 27 class SingleRequestHostResolver; 28 } 29 30 namespace chrome_browser_net { 31 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. 37 // 38 // This class collects the following stats from users who have opted in. 39 // a) RTT. 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. 43 // 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 47 // without pacing. 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). 55 56 class NetworkStats { 57 public: 58 enum Status { // Used in 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. 67 }; 68 69 enum ReadState { // Used to track if |socket_| has a pending read. 70 READ_STATE_IDLE, 71 READ_STATE_READ_PENDING, 72 }; 73 74 enum WriteState { // Used to track if |socket_| has a pending write. 75 WRITE_STATE_IDLE, 76 WRITE_STATE_WRITE_PENDING, 77 }; 78 79 // |TestType| specifies the possible tests we may run 80 // (except for the first and the last serving as boundaries). 81 enum TestType { 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 84 // acquire the token. 85 TOKEN_REQUEST, 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. 90 NAT_BIND_TEST, 91 PACKET_SIZE_TEST, 92 TEST_TYPE_MAX, 93 }; 94 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. 98 ~NetworkStats(); 99 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, 110 uint32 probe_bytes, 111 uint32 bytes_for_packet_size_test, 112 const net::CompletionCallback& callback); 113 114 private: 115 friend class NetworkStatsTest; 116 117 // Start the test specified by the current_test_index_. It also resets all 118 // the book keeping data, before starting the new test. 119 void StartOneTest(); 120 121 // Reset all the counters and the collected stats. 122 void ResetData(); 123 124 // Callback that is called when host resolution is completed. 125 void OnResolveComplete(int result); 126 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); 131 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); 136 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 139 // queue. 140 void SendHelloRequest(); 141 142 // Send a ProbeRequest packet which requests the server to send a set 143 // of Probing packets. 144 void SendProbeRequest(); 145 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); 151 152 // Callbacks when an internal IO (Read or Write) is completed. 153 void OnReadComplete(int result); 154 void OnWriteComplete(int result); 155 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_| 158 // is Null. 159 int ReadData(); 160 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); 165 166 // Update the send buffer (telling it that |bytes_sent| has been sent). 167 // And reset |write_buffer_|. 168 void UpdateSendBuffer(int bytes_sent); 169 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); 174 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); 180 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. 185 void TestPhaseComplete(Status status, int result); 186 187 // This method is called from TestPhaseComplete() and calls 188 // |finished_callback_| callback to indicate that the test has finished. 189 void DoFinishCallback(int result); 190 191 // Update counters/metrics for the given |probe_packet|. 192 // Return true if all packets for the current test are received and 193 // false otherwise. 194 bool UpdateReception(const ProbePacket& probe_packet); 195 196 // Record all histograms for current test phase, which is assumed to be 197 // complete (i.e., we are no longer waiting for packets in this phase). 198 // |test_type| is the current test_type to be recorded. |status| is the 199 // status of the current test. 200 void RecordHistograms(TestType test_type); 201 202 // Collect the following network connectivity stats when 203 // kMaximumSequentialPackets (21) packets are sent from the server. 204 // a) Client received at least one packet. 205 // b) Client received the nth packet. 206 // c) The number of packets received for each subsequence of packets 1...n. 207 void RecordPacketsReceivedHistograms(TestType test_type); 208 209 // Collect the following network connectivity stats for the first 210 // kMaximumCorrelationPackets (6) packets in a test. 211 // Success/failure of each packet, to estimate reachability for users, 212 // and to estimate if there is a probabalistic dependency in packet loss when 213 // kMaximumCorrelationPackets packets are sent consecutively. 214 void RecordPacketLossSeriesHistograms(TestType test_type); 215 216 // Collect the average inter-arrival time (scaled up by 20 times because the 217 // minimum time value in a histogram is 1ms) of a sequence of probing packets. 218 void RecordInterArrivalHistograms(TestType test_type); 219 220 // Collect the RTT for the packet specified by the |index| in the current 221 // test. 222 void RecordRTTHistograms(TestType test_type, uint32 index); 223 224 // Collect whether the second packet in the NAT test is received for the 225 // given idle time. 226 void RecordNATTestReceivedHistograms(Status status); 227 228 // Collect whether we have the requested packet size was received or not in 229 // the PACKET_SIZE_TEST test. 230 void RecordPacketSizeTestReceivedHistograms(Status status); 231 232 // Record the time duration between sending the probe request and receiving 233 // the last probe packet excluding the pacing time requested by the client. 234 // This applies to both NAT bind test and paced/non-paced packet test. 235 void RecordSendToLastRecvDelayHistograms(TestType test_type); 236 237 // Return the next test type (internally increment |current_test_index_|) 238 // in |test_sequence_|; 239 TestType GetNextTest(); 240 241 // These static variables are defined so that they can be changed in testing. 242 // Maximum number of tests in one activation of the experiment. 243 static uint32 maximum_tests_; 244 // Maximum number of packets for START/PACED/NON_PACED tests. 245 static uint32 maximum_sequential_packets_; 246 // Maximum number of packets for NAT binding test. 247 static uint32 maximum_NAT_packets_; 248 // Maximum time duration between the two packets for NAT Bind testing. 249 static uint32 maximum_NAT_idle_seconds_; 250 // Whether to start the probe test immediately after connect success. 251 // Used for unittest. 252 static bool start_test_after_connect_; 253 254 // The socket handler for this session. 255 scoped_ptr<net::DatagramClientSocket> socket_; 256 257 net::ClientSocketFactory* socket_factory_; 258 259 // The read buffer used to read data from the socket. 260 scoped_refptr<net::IOBuffer> read_buffer_; 261 262 // The write buffer used to write data to the socket. 263 scoped_refptr<net::DrainableIOBuffer> write_buffer_; 264 265 // Specify the port for which we are testing the network connectivity. 266 uint16 histogram_port_; 267 268 // Specify if there is a proxy server or not. 269 bool has_proxy_server_; 270 271 // HostResolver used to find the IP addresses. 272 scoped_ptr<net::SingleRequestHostResolver> resolver_; 273 274 // Addresses filled out by HostResolver after host resolution is completed. 275 net::AddressList addresses_; 276 277 // Callback to call when test is successefully finished or whenever 278 // there is an error (this will be used by unittests to check the result). 279 net::CompletionCallback finished_callback_; 280 281 // RTTs for each packet. 282 std::vector<base::TimeDelta> packet_rtt_; 283 284 // Time when sending probe_request, used for computing RTT. 285 base::TimeTicks probe_request_time_; 286 287 // Size of the probe packets requested to be sent from servers. We don't use 288 // |probe_packet_bytes_| during PACKET_SIZE_TEST. 289 uint32 probe_packet_bytes_; 290 291 // Size of the packet requested to be sent from servers for PACKET_SIZE_TEST. 292 uint32 bytes_for_packet_size_test_; 293 294 // bitmask indicating which packets are received. 295 std::bitset<21> packets_received_mask_; 296 297 // Arrival time of the first packet in the current test. 298 base::TimeTicks first_arrival_time_; 299 // Arrival time of the most recently received packet in the current test. 300 base::TimeTicks last_arrival_time_; 301 // Average time between two consecutive packets. It is updated when either all 302 // packets are received or timeout happens in the current test. 303 base::TimeDelta inter_arrival_time_; 304 // Target time duration for sending two consecutive packets at the server. 305 // It should be 0 for StartPacket test or NonPacedPacket test. For 306 // PacedPacket test, it is derived from the inter_arrival_time_ in the 307 // previous (StartPacket) test. For NATBind test, it is randomly generated 308 // between 1 second and |maximum_NAT_idle_seconds_| seconds. 309 base::TimeDelta pacing_interval_; 310 // A list of tests that will be performed in sequence. 311 std::vector<TestType> test_sequence_; 312 uint32 current_test_index_; // Index of the current test. 313 314 ProbeMessage probe_message_; 315 316 // Token received from server for authentication. 317 ProbePacket_Token token_; 318 319 // The state variables to track pending reads/writes. 320 ReadState read_state_; 321 WriteState write_state_; 322 323 // We use this factory to create timeout tasks for socket's ReadData. 324 base::WeakPtrFactory<NetworkStats> weak_factory_; 325 326 DISALLOW_COPY_AND_ASSIGN(NetworkStats); 327 }; 328 329 class ProxyDetector { 330 public: 331 // Used for the callback that is called from |OnResolveProxyComplete|. 332 typedef base::Callback<void(bool)> OnResolvedCallback; 333 334 // Construct a ProxyDetector object that finds out if access to 335 // |server_address| goes through a proxy server or not. Calls the |callback| 336 // after proxy resolution is completed by currying the proxy resolution 337 // status. 338 ProxyDetector(net::ProxyService* proxy_service, 339 const net::HostPortPair& server_address, 340 OnResolvedCallback callback); 341 342 // This method uses |proxy_service_| to resolve the proxy for 343 // |server_address_|. 344 void StartResolveProxy(); 345 346 private: 347 // This object is deleted from |OnResolveProxyComplete|. 348 ~ProxyDetector(); 349 350 // Call the |callback_| by currying the proxy resolution status. 351 void OnResolveProxyComplete(int result); 352 353 // |proxy_service_| specifies the proxy service that is to be used to find 354 // if access to |server_address_| goes through proxy server or not. 355 net::ProxyService* proxy_service_; 356 357 // |server_address_| specifies the server host and port pair for which we are 358 // trying to see if access to it, goes through proxy or not. 359 net::HostPortPair server_address_; 360 361 // |callback_| will be called after proxy resolution is completed. 362 OnResolvedCallback callback_; 363 364 // |proxy_info_| holds proxy information returned by ResolveProxy. 365 net::ProxyInfo proxy_info_; 366 367 // Indicate if there is a pending a proxy resolution. We use this to assert 368 // that there is no in-progress proxy resolution request. 369 bool has_pending_proxy_resolution_; 370 DISALLOW_COPY_AND_ASSIGN(ProxyDetector); 371 }; 372 373 // This collects the network connectivity stats for UDP protocol for small 374 // percentage of users who are participating in the experiment (by enabling 375 // "UMA upload"). This method gets called only if UMA upload to the 376 // server has succeeded. 377 void CollectNetworkStats(const std::string& network_stats_server_url, 378 IOThread* io_thread); 379 380 // This starts a series of tests randomly selected among one of the three 381 // choices of probe packet sizes: 100 Bytes, 500 Bytes, 1200 Bytes. 382 void StartNetworkStatsTest(net::HostResolver* host_resolver, 383 const net::HostPortPair& server_address, 384 uint16 histogram_port, 385 bool has_proxy_server); 386 387 } // namespace chrome_browser_net 388 389 #endif // CHROME_BROWSER_NET_NETWORK_STATS_H_ 390