| OLD | NEW |
| (Empty) |
| 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 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. | |
| 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. Returns true if a new test wasn't started and it | |
| 185 // was self destructed. | |
| 186 bool TestPhaseComplete(Status status, int result); | |
| 187 | |
| 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); | |
| 191 | |
| 192 // Update counters/metrics for the given |probe_packet|. | |
| 193 // Return true if all packets for the current test are received and | |
| 194 // false otherwise. | |
| 195 bool UpdateReception(const ProbePacket& probe_packet); | |
| 196 | |
| 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); | |
| 202 | |
| 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); | |
| 209 | |
| 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); | |
| 216 | |
| 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); | |
| 220 | |
| 221 // Collect the RTT for the packet specified by the |index| in the current | |
| 222 // test. | |
| 223 void RecordRTTHistograms(TestType test_type, uint32 index); | |
| 224 | |
| 225 // Collect whether the second packet in the NAT test is received for the | |
| 226 // given idle time. | |
| 227 void RecordNATTestReceivedHistograms(Status status); | |
| 228 | |
| 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); | |
| 232 | |
| 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); | |
| 237 | |
| 238 // Return the next test type (internally increment |current_test_index_|) | |
| 239 // in |test_sequence_|; | |
| 240 TestType GetNextTest(); | |
| 241 | |
| 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_; | |
| 254 | |
| 255 // The socket handler for this session. | |
| 256 scoped_ptr<net::DatagramClientSocket> socket_; | |
| 257 | |
| 258 net::ClientSocketFactory* socket_factory_; | |
| 259 | |
| 260 // The read buffer used to read data from the socket. | |
| 261 scoped_refptr<net::IOBuffer> read_buffer_; | |
| 262 | |
| 263 // The write buffer used to write data to the socket. | |
| 264 scoped_refptr<net::DrainableIOBuffer> write_buffer_; | |
| 265 | |
| 266 // Specify the port for which we are testing the network connectivity. | |
| 267 uint16 histogram_port_; | |
| 268 | |
| 269 // Specify if there is a proxy server or not. | |
| 270 bool has_proxy_server_; | |
| 271 | |
| 272 // HostResolver used to find the IP addresses. | |
| 273 scoped_ptr<net::SingleRequestHostResolver> resolver_; | |
| 274 | |
| 275 // Addresses filled out by HostResolver after host resolution is completed. | |
| 276 net::AddressList addresses_; | |
| 277 | |
| 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_; | |
| 281 | |
| 282 // RTTs for each packet. | |
| 283 std::vector<base::TimeDelta> packet_rtt_; | |
| 284 | |
| 285 // Time when sending probe_request, used for computing RTT. | |
| 286 base::TimeTicks probe_request_time_; | |
| 287 | |
| 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_; | |
| 291 | |
| 292 // Size of the packet requested to be sent from servers for PACKET_SIZE_TEST. | |
| 293 uint32 bytes_for_packet_size_test_; | |
| 294 | |
| 295 // bitmask indicating which packets are received. | |
| 296 std::bitset<21> packets_received_mask_; | |
| 297 | |
| 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. | |
| 314 | |
| 315 ProbeMessage probe_message_; | |
| 316 | |
| 317 // Token received from server for authentication. | |
| 318 ProbePacket_Token token_; | |
| 319 | |
| 320 // The state variables to track pending reads/writes. | |
| 321 ReadState read_state_; | |
| 322 WriteState write_state_; | |
| 323 | |
| 324 // We use this factory to create timeout tasks for socket's ReadData. | |
| 325 base::WeakPtrFactory<NetworkStats> weak_factory_; | |
| 326 | |
| 327 DISALLOW_COPY_AND_ASSIGN(NetworkStats); | |
| 328 }; | |
| 329 | |
| 330 class ProxyDetector { | |
| 331 public: | |
| 332 // Used for the callback that is called from |OnResolveProxyComplete|. | |
| 333 typedef base::Callback<void(bool)> OnResolvedCallback; | |
| 334 | |
| 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 | |
| 338 // status. | |
| 339 ProxyDetector(net::ProxyService* proxy_service, | |
| 340 const net::HostPortPair& server_address, | |
| 341 OnResolvedCallback callback); | |
| 342 | |
| 343 // This method uses |proxy_service_| to resolve the proxy for | |
| 344 // |server_address_|. | |
| 345 void StartResolveProxy(); | |
| 346 | |
| 347 private: | |
| 348 // This object is deleted from |OnResolveProxyComplete|. | |
| 349 ~ProxyDetector(); | |
| 350 | |
| 351 // Call the |callback_| by currying the proxy resolution status. | |
| 352 void OnResolveProxyComplete(int result); | |
| 353 | |
| 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_; | |
| 357 | |
| 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_; | |
| 361 | |
| 362 // |callback_| will be called after proxy resolution is completed. | |
| 363 OnResolvedCallback callback_; | |
| 364 | |
| 365 // |proxy_info_| holds proxy information returned by ResolveProxy. | |
| 366 net::ProxyInfo proxy_info_; | |
| 367 | |
| 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); | |
| 372 }; | |
| 373 | |
| 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); | |
| 380 | |
| 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); | |
| 387 | |
| 388 } // namespace chrome_browser_net | |
| 389 | |
| 390 #endif // CHROME_BROWSER_NET_NETWORK_STATS_H_ | |
| OLD | NEW |