OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/net/network_stats.h" | 5 #include "chrome/browser/net/network_stats.h" |
6 | 6 |
7 #include "base/callback_old.h" | 7 #include "base/callback_old.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
10 #include "base/metrics/field_trial.h" | 10 #include "base/metrics/field_trial.h" |
11 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
12 #include "base/task.h" | 12 #include "base/task.h" |
13 #include "base/threading/platform_thread.h" | 13 #include "base/threading/platform_thread.h" |
14 #include "base/time.h" | 14 #include "base/time.h" |
15 #include "base/tuple.h" | 15 #include "base/tuple.h" |
16 #include "content/browser/browser_thread.h" | 16 #include "content/browser/browser_thread.h" |
17 #include "net/base/net_errors.h" | 17 #include "net/base/net_errors.h" |
18 #include "net/base/net_util.h" | 18 #include "net/base/net_util.h" |
19 #include "net/base/network_change_notifier.h" | 19 #include "net/base/network_change_notifier.h" |
20 #include "net/base/sys_addrinfo.h" | 20 #include "net/base/sys_addrinfo.h" |
21 #include "net/base/test_completion_callback.h" | 21 #include "net/base/test_completion_callback.h" |
22 #include "net/socket/tcp_client_socket.h" | 22 #include "net/socket/tcp_client_socket.h" |
23 #include "net/udp/udp_client_socket.h" | 23 #include "net/udp/udp_client_socket.h" |
24 #include "net/udp/udp_server_socket.h" | 24 #include "net/udp/udp_server_socket.h" |
25 | 25 |
26 namespace chrome_browser_net { | 26 namespace chrome_browser_net { |
27 | 27 |
28 // This specifies the number of bytes to be sent to the TCP/UDP servers as part | 28 // This specifies the number of bytes to be sent to the TCP/UDP servers as part |
29 // of small packet size test. | 29 // of small packet size test. |
30 static const int kSmallTestBytesToSend = 100; | 30 static const uint32 kSmallTestBytesToSend = 100; |
31 | 31 |
32 // This specifies the number of bytes to be sent to the TCP/UDP servers as part | 32 // This specifies the number of bytes to be sent to the TCP/UDP servers as part |
33 // of large packet size test. | 33 // of large packet size test. |
34 static const int kLargeTestBytesToSend = 1200; | 34 static const uint32 kLargeTestBytesToSend = 1200; |
35 | |
36 // This specifies the maximum message (payload) size. | |
37 static const uint32 kMaxMessage = 2048; | |
38 | |
39 // This specifies starting position of the version and length of the version in | |
40 // "echo request" and "echo response". | |
41 static const uint32 kVersionNumber = 1; | |
42 static const uint32 kVersionStart = 0; | |
43 static const uint32 kVersionLength = 2; | |
44 static const uint32 kVersionEnd = 2; // kVersionStart + kVersionLength. | |
jar (doing other things)
2011/08/05 19:37:31
nit: Suggest:
kVersionEnd = kVersionStart + kVers
ramant (doing other things)
2011/08/12 01:05:08
Done.
| |
45 | |
46 // This specifies the starting position of the checksum and length of the | |
47 // checksum in "echo request" and "echo response". Maximum value for the | |
48 // checksum is less than (2 ** 31 - 1). | |
49 static const uint32 kChecksumStart = 2; // kVersionEnd. | |
jar (doing other things)
2011/08/05 19:37:31
nit: assign value rather than comment..
Same belo
ramant (doing other things)
2011/08/12 01:05:08
Done.
| |
50 static const uint32 kChecksumLength = 10; | |
51 static const uint32 kChecksumEnd = 12; // kChecksumStart + kChecksumLength. | |
52 | |
53 // This specifies the starting position of the <payload_size> and length of the | |
54 // <payload_size> in "echo request" and "echo response". Maximum number of bytes | |
55 // that can be sent in the <payload> is 9,999,999. | |
56 static const uint32 kPayloadSizeStart = 12; // kChecksumEnd. | |
57 static const uint32 kPayloadSizeLength = 7; | |
58 // kPayloadSizeEnd = kPayloadSizeStart + kPayloadSizeLength. | |
59 static const uint32 kPayloadSizeEnd = 19; | |
60 | |
61 // This specifies the starting position of the |key_| and length of the |key_| | |
62 // in "echo response". Maximum value for the |key_| is 999,999. | |
63 static const uint32 kKeyStart = 19; // kPayloadSizeEnd. | |
64 static const uint32 kKeyLength = 6; | |
65 static const uint32 kKeyEnd = 25; // kKeyStart + kKeyLength. | |
66 | |
67 // This specifies the starting position of the <payload> in "echo request". | |
68 static const uint32 kPayloadStart = 19; // kPayloadSizeEnd. | |
69 | |
70 // This specifies the starting position of the <encrypted_payload> and length of | |
71 // the <encrypted_payload> in "echo response". | |
72 static const uint32 kEncryptedPayloadStart = 25; // kKeyEnd. | |
73 | |
35 | 74 |
36 // NetworkStats methods and members. | 75 // NetworkStats methods and members. |
37 NetworkStats::NetworkStats() | 76 NetworkStats::NetworkStats() |
38 : bytes_to_read_(0), | 77 : load_size_(0), |
78 bytes_to_read_(0), | |
39 bytes_to_send_(0), | 79 bytes_to_send_(0), |
80 key_(""), | |
81 key_index_(0), | |
40 ALLOW_THIS_IN_INITIALIZER_LIST( | 82 ALLOW_THIS_IN_INITIALIZER_LIST( |
41 read_callback_(this, &NetworkStats::OnReadComplete)), | 83 read_callback_(this, &NetworkStats::OnReadComplete)), |
42 ALLOW_THIS_IN_INITIALIZER_LIST( | 84 ALLOW_THIS_IN_INITIALIZER_LIST( |
43 write_callback_(this, &NetworkStats::OnWriteComplete)), | 85 write_callback_(this, &NetworkStats::OnWriteComplete)), |
44 finished_callback_(NULL), | 86 finished_callback_(NULL), |
45 start_time_(base::TimeTicks::Now()) { | 87 start_time_(base::TimeTicks::Now()) { |
46 } | 88 } |
47 | 89 |
48 NetworkStats::~NetworkStats() { | 90 NetworkStats::~NetworkStats() { |
49 socket_.reset(); | 91 socket_.reset(); |
50 } | 92 } |
51 | 93 |
52 void NetworkStats::Initialize(int bytes_to_send, | 94 void NetworkStats::Initialize(uint32 bytes_to_send, |
53 net::CompletionCallback* finished_callback) { | 95 net::CompletionCallback* finished_callback) { |
54 DCHECK(bytes_to_send); // We should have data to send. | 96 DCHECK(bytes_to_send); // We should have data to send. |
55 | 97 |
56 load_size_ = bytes_to_send; | 98 load_size_ = bytes_to_send; |
57 bytes_to_send_ = bytes_to_send; | 99 bytes_to_send_ = |
58 bytes_to_read_ = bytes_to_send; | 100 kVersionLength + kChecksumLength + kPayloadSizeLength + load_size_; |
101 bytes_to_read_ = | |
102 kVersionLength + kChecksumLength + kPayloadSizeLength + kKeyLength + | |
103 load_size_; | |
59 finished_callback_ = finished_callback; | 104 finished_callback_ = finished_callback; |
60 } | 105 } |
61 | 106 |
62 bool NetworkStats::DoStart(int result) { | 107 bool NetworkStats::DoStart(int result) { |
63 if (result < 0) { | 108 if (result < 0) { |
64 Finish(CONNECT_FAILED, result); | 109 Finish(CONNECT_FAILED, result); |
65 return false; | 110 return false; |
66 } | 111 } |
67 | 112 |
68 DCHECK(bytes_to_send_); // We should have data to send. | 113 DCHECK(bytes_to_send_); // We should have data to send. |
(...skipping 29 matching lines...) Expand all Loading... | |
98 } | 143 } |
99 | 144 |
100 bool NetworkStats::ReadComplete(int result) { | 145 bool NetworkStats::ReadComplete(int result) { |
101 DCHECK(socket_.get()); | 146 DCHECK(socket_.get()); |
102 DCHECK_NE(net::ERR_IO_PENDING, result); | 147 DCHECK_NE(net::ERR_IO_PENDING, result); |
103 if (result < 0) { | 148 if (result < 0) { |
104 Finish(READ_FAILED, result); | 149 Finish(READ_FAILED, result); |
105 return true; | 150 return true; |
106 } | 151 } |
107 | 152 |
108 if (!stream_.VerifyBytes(read_buffer_->data(), result)) { | 153 if (!VerifyBytes(static_cast<uint32>(result))) { |
109 Finish(READ_VERIFY_FAILED, net::ERR_INVALID_RESPONSE); | 154 Finish(READ_VERIFY_FAILED, net::ERR_INVALID_RESPONSE); |
110 return true; | 155 return true; |
111 } | 156 } |
112 | 157 |
113 read_buffer_ = NULL; | 158 read_buffer_ = NULL; |
114 bytes_to_read_ -= result; | 159 bytes_to_read_ -= result; |
115 | 160 |
116 // No more data to read. | 161 // No more data to read. |
117 if (!bytes_to_read_) { | 162 if (!bytes_to_read_) { |
118 Finish(SUCCESS, net::OK); | 163 Finish(SUCCESS, net::OK); |
(...skipping 26 matching lines...) Expand all Loading... | |
145 if (rv != net::ERR_IO_PENDING) { | 190 if (rv != net::ERR_IO_PENDING) { |
146 Finish(WRITE_FAILED, rv); | 191 Finish(WRITE_FAILED, rv); |
147 return; | 192 return; |
148 } | 193 } |
149 } | 194 } |
150 } | 195 } |
151 } | 196 } |
152 | 197 |
153 void NetworkStats::ReadData() { | 198 void NetworkStats::ReadData() { |
154 DCHECK(!read_buffer_.get()); | 199 DCHECK(!read_buffer_.get()); |
155 int kMaxMessage = 2048; | |
156 | 200 |
157 // We release the read_buffer_ in the destructor if there is an error. | 201 // We release the read_buffer_ in the destructor if there is an error. |
158 read_buffer_ = new net::IOBuffer(kMaxMessage); | 202 read_buffer_ = new net::IOBuffer(kMaxMessage); |
159 | 203 |
160 int rv; | 204 int rv; |
161 do { | 205 do { |
162 DCHECK(socket_.get()); | 206 DCHECK(socket_.get()); |
163 rv = socket_->Read(read_buffer_, kMaxMessage, &read_callback_); | 207 rv = socket_->Read(read_buffer_, kMaxMessage, &read_callback_); |
164 if (rv == net::ERR_IO_PENDING) | 208 if (rv == net::ERR_IO_PENDING) |
165 return; | 209 return; |
166 if (ReadComplete(rv)) // Complete the read manually. | 210 if (ReadComplete(rv)) // Complete the read manually. |
167 return; | 211 return; |
168 } while (rv > 0); | 212 } while (rv > 0); |
169 } | 213 } |
170 | 214 |
171 int NetworkStats::SendData() { | 215 int NetworkStats::SendData() { |
172 DCHECK(bytes_to_send_); // We should have data to send. | 216 DCHECK(bytes_to_send_); // We should have data to send. |
173 do { | 217 do { |
174 if (!write_buffer_.get()) { | 218 if (!write_buffer_.get()) { |
175 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(bytes_to_send_)); | 219 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(bytes_to_send_)); |
176 stream_.GetBytes(buffer->data(), bytes_to_send_); | 220 GetEchoRequest(buffer); |
177 write_buffer_ = new net::DrainableIOBuffer(buffer, bytes_to_send_); | 221 write_buffer_ = new net::DrainableIOBuffer(buffer, bytes_to_send_); |
178 } | 222 } |
179 | 223 |
180 DCHECK(socket_.get()); | 224 DCHECK(socket_.get()); |
181 int rv = socket_->Write(write_buffer_, | 225 int rv = socket_->Write(write_buffer_, |
182 write_buffer_->BytesRemaining(), | 226 write_buffer_->BytesRemaining(), |
183 &write_callback_); | 227 &write_callback_); |
184 if (rv < 0) | 228 if (rv < 0) |
185 return rv; | 229 return rv; |
186 write_buffer_->DidConsume(rv); | 230 write_buffer_->DidConsume(rv); |
187 bytes_to_send_ -= rv; | 231 bytes_to_send_ -= rv; |
188 if (!write_buffer_->BytesRemaining()) | 232 if (!write_buffer_->BytesRemaining()) |
189 write_buffer_ = NULL; | 233 write_buffer_ = NULL; |
190 } while (bytes_to_send_); | 234 } while (bytes_to_send_); |
191 return net::OK; | 235 return net::OK; |
192 } | 236 } |
193 | 237 |
238 void NetworkStats::GetEchoRequest(net::IOBuffer* io_buffer) { | |
239 // Copy the <version> into the io_buffer starting from the kVersionStart | |
240 // position. | |
241 std::string version = base::StringPrintf("%02d", kVersionNumber); | |
242 char* buffer = io_buffer->data() + kVersionStart; | |
243 DCHECK(kVersionLength == version.length()); | |
244 memcpy(buffer, version.c_str(), kVersionLength); | |
245 | |
246 // Get the <payload> from the |stream_| and copy it into io_buffer starting | |
247 // from the kPayloadStart position. | |
248 buffer = io_buffer->data() + kPayloadStart; | |
249 stream_.GetBytes(buffer, load_size_); | |
250 | |
251 // Calculate the <checksum> of the <payload>. | |
252 uint32 sum = 0; | |
253 unsigned char* src = reinterpret_cast<unsigned char*>(buffer); | |
254 for (uint32 i = 0; i < load_size_; ++i) | |
255 sum += src[i]; | |
256 | |
257 // Copy the <checksum> into the io_buffer starting from the kChecksumStart | |
258 // position. | |
259 std::string checksum = base::StringPrintf("%010d", sum); | |
260 buffer = io_buffer->data() + kChecksumStart; | |
261 DCHECK(kChecksumLength == checksum.length()); | |
262 memcpy(buffer, checksum.c_str(), kChecksumLength); | |
263 | |
264 // Copy the size of the <payload> into the io_buffer starting from the | |
265 // kPayloadSizeStart position. | |
266 buffer = io_buffer->data() + kPayloadSizeStart; | |
267 std::string payload_size = base::StringPrintf("%07d", load_size_); | |
268 DCHECK(kPayloadSizeLength == payload_size.length()); | |
269 memcpy(buffer, payload_size.c_str(), kPayloadSizeLength); | |
270 } | |
271 | |
272 bool NetworkStats::VerifyBytes(uint32 buffer_length) { | |
jar (doing other things)
2011/08/05 19:37:31
Suggest copying bytes into a local buffer, and the
ramant (doing other things)
2011/08/12 01:05:08
Done.
| |
273 // TODO(rtenneti): Handle the data if it comes out of order. | |
274 uint32 payload_start = 0; | |
275 char* buffer; | |
276 | |
277 if (key_.empty()) { | |
278 // If the "echo response" doesn't have enough bytes, then return false. | |
279 if (buffer_length < kEncryptedPayloadStart) | |
280 return false; | |
281 | |
282 // Extract the |key_| from the "echo response". | |
283 buffer = read_buffer_->data() + kKeyStart; | |
284 char key[kKeyLength + 1]; | |
285 memcpy(key, buffer, kKeyLength); | |
286 key[kKeyLength] = '\0'; | |
287 key_ = key; | |
jar (doing other things)
2011/08/05 19:37:31
nit: avoid memcpy, and just use a special construc
ramant (doing other things)
2011/08/12 01:05:08
Done.
| |
288 | |
289 // Initialize the starting position of the <payload>. | |
290 payload_start = kEncryptedPayloadStart; | |
291 } | |
292 | |
293 // Read the <encrypted_payload> from the "echo response". | |
294 DCHECK_GE(buffer_length, payload_start); | |
295 uint32 message_length = buffer_length - payload_start; | |
296 message_length = std::min(message_length, kMaxMessage); | |
297 buffer = read_buffer_->data() + payload_start; | |
298 char encrypted_data[kMaxMessage + 1]; | |
299 memcpy(encrypted_data, buffer, message_length); | |
300 | |
301 // Decrypt the data. | |
302 char decrypted_data[kMaxMessage + 1]; | |
303 uint32 kIdx = key_index_; | |
304 // Loop through the string and XOR each byte with the |key_| to get the | |
305 // decrypted byte. Append the decrypted byte to the |decrypted_data|. | |
306 for (uint32 idx = 0; idx < message_length; ++idx) { | |
307 int encrypted_byte = static_cast<int>(encrypted_data[idx]); | |
308 int key_byte = static_cast<int>(key_[kIdx]); | |
jar (doing other things)
2011/08/05 19:37:31
suggest using "char" as the types for lines 307 an
ramant (doing other things)
2011/08/12 01:05:08
Done.
| |
309 char decrypted_byte = static_cast<char>(encrypted_byte ^ key_byte); | |
310 decrypted_data[idx] = decrypted_byte; | |
311 kIdx = (kIdx + 1) % kKeyLength; | |
312 } | |
313 // Save the kIdx in case we haven't received the whole "echo response". | |
314 key_index_ = kIdx; | |
315 | |
316 return stream_.VerifyBytes(decrypted_data, message_length); | |
317 } | |
318 | |
194 // UDPStatsClient methods and members. | 319 // UDPStatsClient methods and members. |
195 UDPStatsClient::UDPStatsClient() | 320 UDPStatsClient::UDPStatsClient() |
196 : NetworkStats() { | 321 : NetworkStats() { |
197 } | 322 } |
198 | 323 |
199 UDPStatsClient::~UDPStatsClient() { | 324 UDPStatsClient::~UDPStatsClient() { |
200 } | 325 } |
201 | 326 |
202 bool UDPStatsClient::Start(const std::string& ip_str, | 327 bool UDPStatsClient::Start(const std::string& ip_str, |
203 int port, | 328 int port, |
204 int bytes_to_send, | 329 uint32 bytes_to_send, |
205 net::CompletionCallback* finished_callback) { | 330 net::CompletionCallback* finished_callback) { |
206 DCHECK(port); | 331 DCHECK(port); |
207 DCHECK(bytes_to_send); // We should have data to send. | 332 DCHECK(bytes_to_send); // We should have data to send. |
208 | 333 |
209 Initialize(bytes_to_send, finished_callback); | 334 Initialize(bytes_to_send, finished_callback); |
210 | 335 |
211 net::IPAddressNumber ip_number; | 336 net::IPAddressNumber ip_number; |
212 if (!net::ParseIPLiteralToNumber(ip_str, &ip_number)) { | 337 if (!net::ParseIPLiteralToNumber(ip_str, &ip_number)) { |
213 Finish(IP_STRING_PARSE_FAILED, net::ERR_INVALID_ARGUMENT); | 338 Finish(IP_STRING_PARSE_FAILED, net::ERR_INVALID_ARGUMENT); |
214 return false; | 339 return false; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
265 resolve_callback_(this, &TCPStatsClient::OnResolveComplete)), | 390 resolve_callback_(this, &TCPStatsClient::OnResolveComplete)), |
266 ALLOW_THIS_IN_INITIALIZER_LIST( | 391 ALLOW_THIS_IN_INITIALIZER_LIST( |
267 connect_callback_(this, &TCPStatsClient::OnConnectComplete)) { | 392 connect_callback_(this, &TCPStatsClient::OnConnectComplete)) { |
268 } | 393 } |
269 | 394 |
270 TCPStatsClient::~TCPStatsClient() { | 395 TCPStatsClient::~TCPStatsClient() { |
271 } | 396 } |
272 | 397 |
273 bool TCPStatsClient::Start(net::HostResolver* host_resolver, | 398 bool TCPStatsClient::Start(net::HostResolver* host_resolver, |
274 const net::HostPortPair& server_host_port_pair, | 399 const net::HostPortPair& server_host_port_pair, |
275 int bytes_to_send, | 400 uint32 bytes_to_send, |
276 net::CompletionCallback* finished_callback) { | 401 net::CompletionCallback* finished_callback) { |
277 DCHECK(bytes_to_send); // We should have data to send. | 402 DCHECK(bytes_to_send); // We should have data to send. |
278 | 403 |
279 Initialize(bytes_to_send, finished_callback); | 404 Initialize(bytes_to_send, finished_callback); |
280 | 405 |
281 net::HostResolver::RequestInfo request(server_host_port_pair); | 406 net::HostResolver::RequestInfo request(server_host_port_pair); |
282 int rv = host_resolver->Resolve(request, | 407 int rv = host_resolver->Resolve(request, |
283 &addresses_, | 408 &addresses_, |
284 &resolve_callback_, | 409 &resolve_callback_, |
285 NULL, | 410 NULL, |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
424 TCPStatsClient* small_tcp_client = new TCPStatsClient(); | 549 TCPStatsClient* small_tcp_client = new TCPStatsClient(); |
425 small_tcp_client->Start(host_resolver, server_address, kSmallTestBytesToSend, | 550 small_tcp_client->Start(host_resolver, server_address, kSmallTestBytesToSend, |
426 NULL); | 551 NULL); |
427 | 552 |
428 TCPStatsClient* large_tcp_client = new TCPStatsClient(); | 553 TCPStatsClient* large_tcp_client = new TCPStatsClient(); |
429 large_tcp_client->Start(host_resolver, server_address, kLargeTestBytesToSend, | 554 large_tcp_client->Start(host_resolver, server_address, kLargeTestBytesToSend, |
430 NULL); | 555 NULL); |
431 } | 556 } |
432 | 557 |
433 } // namespace chrome_browser_net | 558 } // namespace chrome_browser_net |
OLD | NEW |