Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(483)

Side by Side Diff: chrome/browser/net/network_stats.cc

Issue 7246021: Prevent DOS attack on UDP echo servers by distinguishing between an echo request (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/net/network_stats.h ('k') | net/tools/testserver/echo_message.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
40 // <version> in "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 = kVersionStart + kVersionLength;
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 = kVersionEnd;
50 static const uint32 kChecksumLength = 10;
51 static const uint32 kChecksumEnd = 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 = kChecksumEnd;
57 static const uint32 kPayloadSizeLength = 7;
58 static const uint32 kPayloadSizeEnd = kPayloadSizeStart + kPayloadSizeLength;
59
60 // This specifies the starting position of the <key> and length of the <key> in
61 // "echo response".
62 static const uint32 kKeyStart = kPayloadSizeEnd;
63 static const uint32 kKeyLength = 6;
64 static const uint32 kKeyEnd = kKeyStart + kKeyLength;
65 static const int32 kKeyMinValue = 0;
66 static const int32 kKeyMaxValue = 999999;
67
68 // This specifies the starting position of the <payload> in "echo request".
69 static const uint32 kPayloadStart = kPayloadSizeEnd;
70
71 // This specifies the starting position of the <encoded_payload> and length of
72 // the <encoded_payload> in "echo response".
73 static const uint32 kEncodedPayloadStart = kKeyEnd;
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 encoded_message_(""),
40 ALLOW_THIS_IN_INITIALIZER_LIST( 81 ALLOW_THIS_IN_INITIALIZER_LIST(
41 read_callback_(this, &NetworkStats::OnReadComplete)), 82 read_callback_(this, &NetworkStats::OnReadComplete)),
42 ALLOW_THIS_IN_INITIALIZER_LIST( 83 ALLOW_THIS_IN_INITIALIZER_LIST(
43 write_callback_(this, &NetworkStats::OnWriteComplete)), 84 write_callback_(this, &NetworkStats::OnWriteComplete)),
44 finished_callback_(NULL), 85 finished_callback_(NULL),
45 start_time_(base::TimeTicks::Now()) { 86 start_time_(base::TimeTicks::Now()),
87 ALLOW_THIS_IN_INITIALIZER_LIST(timers_factory_(this)) {
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_ = kVersionLength + kChecksumLength + kPayloadSizeLength +
58 bytes_to_read_ = bytes_to_send; 100 load_size_;
101 bytes_to_read_ = kVersionLength + kChecksumLength + kPayloadSizeLength +
102 kKeyLength + load_size_;
59 finished_callback_ = finished_callback; 103 finished_callback_ = finished_callback;
60 } 104 }
61 105
62 bool NetworkStats::DoStart(int result) { 106 bool NetworkStats::DoStart(int result) {
63 if (result < 0) { 107 if (result < 0) {
64 Finish(CONNECT_FAILED, result); 108 Finish(CONNECT_FAILED, result);
65 return false; 109 return false;
66 } 110 }
67 111
68 DCHECK(bytes_to_send_); // We should have data to send. 112 DCHECK(bytes_to_send_); // We should have data to send.
69 113
70 start_time_ = base::TimeTicks::Now(); 114 start_time_ = base::TimeTicks::Now();
71 115
72 int rv = SendData(); 116 int rv = SendData();
73 if (rv < 0) { 117 if (rv < 0) {
74 if (rv != net::ERR_IO_PENDING) { 118 if (rv != net::ERR_IO_PENDING) {
75 Finish(WRITE_FAILED, rv); 119 Finish(WRITE_FAILED, rv);
76 return false; 120 return false;
77 } 121 }
78 } 122 }
79 123
80 stream_.Reset(); 124 stream_.Reset();
125
126 // Timeout if we don't get response back from echo servers in 60 secs.
127 const int kReadDataTimeoutMs = 60000;
128 StartReadDataTimer(kReadDataTimeoutMs);
129
81 ReadData(); 130 ReadData();
82 131
83 return true; 132 return true;
84 } 133 }
85 134
86 void NetworkStats::DoFinishCallback(int result) { 135 void NetworkStats::DoFinishCallback(int result) {
87 if (finished_callback_ != NULL) { 136 if (finished_callback_ != NULL) {
88 net::CompletionCallback* callback = finished_callback_; 137 net::CompletionCallback* callback = finished_callback_;
89 finished_callback_ = NULL; 138 finished_callback_ = NULL;
90 callback->Run(result); 139 callback->Run(result);
91 } 140 }
92 } 141 }
93 142
94 void NetworkStats::set_socket(net::Socket* socket) { 143 void NetworkStats::set_socket(net::Socket* socket) {
95 DCHECK(socket); 144 DCHECK(socket);
96 DCHECK(!socket_.get()); 145 DCHECK(!socket_.get());
97 socket_.reset(socket); 146 socket_.reset(socket);
98 } 147 }
99 148
100 bool NetworkStats::ReadComplete(int result) { 149 bool NetworkStats::ReadComplete(int result) {
101 DCHECK(socket_.get()); 150 DCHECK(socket_.get());
102 DCHECK_NE(net::ERR_IO_PENDING, result); 151 DCHECK_NE(net::ERR_IO_PENDING, result);
103 if (result < 0) { 152 if (result < 0) {
104 Finish(READ_FAILED, result); 153 Finish(READ_FAILED, result);
105 return true; 154 return true;
106 } 155 }
107 156
108 if (!stream_.VerifyBytes(read_buffer_->data(), result)) { 157 encoded_message_.append(read_buffer_->data(), result);
109 Finish(READ_VERIFY_FAILED, net::ERR_INVALID_RESPONSE);
110 return true;
111 }
112 158
113 read_buffer_ = NULL; 159 read_buffer_ = NULL;
114 bytes_to_read_ -= result; 160 bytes_to_read_ -= result;
115 161
116 // No more data to read. 162 // No more data to read.
117 if (!bytes_to_read_) { 163 if (!bytes_to_read_ || result == 0) {
118 Finish(SUCCESS, net::OK); 164 if (VerifyBytes())
165 Finish(SUCCESS, net::OK);
166 else
167 Finish(READ_VERIFY_FAILED, net::ERR_INVALID_RESPONSE);
119 return true; 168 return true;
120 } 169 }
121 ReadData();
122 return false; 170 return false;
123 } 171 }
124 172
125 void NetworkStats::OnReadComplete(int result) { 173 void NetworkStats::OnReadComplete(int result) {
126 ReadComplete(result); 174 if (!ReadComplete(result)) {
175 // Called ReadData() via PostDelayedTask() to avoid recursion. Added a delay
176 // of 1ms so that the time-out will fire before we have time to really hog
177 // the CPU too extensively (waiting for the time-out) in case of an infinite
178 // loop.
179 const int kReadDataDelayMs = 1;
180 MessageLoop::current()->PostDelayedTask(
181 FROM_HERE,
182 timers_factory_.NewRunnableMethod(&NetworkStats::ReadData),
183 kReadDataDelayMs);
184 }
127 } 185 }
128 186
129 void NetworkStats::OnWriteComplete(int result) { 187 void NetworkStats::OnWriteComplete(int result) {
130 DCHECK(socket_.get()); 188 DCHECK(socket_.get());
131 DCHECK_NE(net::ERR_IO_PENDING, result); 189 DCHECK_NE(net::ERR_IO_PENDING, result);
132 if (result < 0) { 190 if (result < 0) {
133 Finish(WRITE_FAILED, result); 191 Finish(WRITE_FAILED, result);
134 return; 192 return;
135 } 193 }
136 194
137 write_buffer_->DidConsume(result); 195 write_buffer_->DidConsume(result);
138 bytes_to_send_ -= result; 196 bytes_to_send_ -= result;
139 if (!write_buffer_->BytesRemaining()) 197 if (!write_buffer_->BytesRemaining())
140 write_buffer_ = NULL; 198 write_buffer_ = NULL;
141 199
142 if (bytes_to_send_) { 200 if (bytes_to_send_) {
143 int rv = SendData(); 201 int rv = SendData();
144 if (rv < 0) { 202 if (rv < 0) {
145 if (rv != net::ERR_IO_PENDING) { 203 if (rv != net::ERR_IO_PENDING) {
146 Finish(WRITE_FAILED, rv); 204 Finish(WRITE_FAILED, rv);
147 return; 205 return;
148 } 206 }
149 } 207 }
150 } 208 }
151 } 209 }
152 210
153 void NetworkStats::ReadData() { 211 void NetworkStats::ReadData() {
154 DCHECK(!read_buffer_.get());
155 int kMaxMessage = 2048;
156
157 // We release the read_buffer_ in the destructor if there is an error.
158 read_buffer_ = new net::IOBuffer(kMaxMessage);
159
160 int rv; 212 int rv;
161 do { 213 do {
162 DCHECK(socket_.get()); 214 if (!socket_.get())
215 return;
216
217 DCHECK(!read_buffer_.get());
218
219 // We release the read_buffer_ in the destructor if there is an error.
220 read_buffer_ = new net::IOBuffer(kMaxMessage);
221
163 rv = socket_->Read(read_buffer_, kMaxMessage, &read_callback_); 222 rv = socket_->Read(read_buffer_, kMaxMessage, &read_callback_);
164 if (rv == net::ERR_IO_PENDING) 223 if (rv == net::ERR_IO_PENDING)
165 return; 224 return;
166 if (ReadComplete(rv)) // Complete the read manually. 225 // If we have read all the data then return.
226 if (ReadComplete(rv))
167 return; 227 return;
168 } while (rv > 0); 228 } while (rv > 0);
169 } 229 }
170 230
171 int NetworkStats::SendData() { 231 int NetworkStats::SendData() {
172 DCHECK(bytes_to_send_); // We should have data to send. 232 DCHECK(bytes_to_send_); // We should have data to send.
173 do { 233 do {
174 if (!write_buffer_.get()) { 234 if (!write_buffer_.get()) {
175 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(bytes_to_send_)); 235 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(bytes_to_send_));
176 stream_.GetBytes(buffer->data(), bytes_to_send_); 236 GetEchoRequest(buffer);
177 write_buffer_ = new net::DrainableIOBuffer(buffer, bytes_to_send_); 237 write_buffer_ = new net::DrainableIOBuffer(buffer, bytes_to_send_);
178 } 238 }
179 239
180 DCHECK(socket_.get()); 240 if (!socket_.get())
241 return net::ERR_UNEXPECTED;
181 int rv = socket_->Write(write_buffer_, 242 int rv = socket_->Write(write_buffer_,
182 write_buffer_->BytesRemaining(), 243 write_buffer_->BytesRemaining(),
183 &write_callback_); 244 &write_callback_);
184 if (rv < 0) 245 if (rv < 0)
185 return rv; 246 return rv;
186 write_buffer_->DidConsume(rv); 247 write_buffer_->DidConsume(rv);
187 bytes_to_send_ -= rv; 248 bytes_to_send_ -= rv;
188 if (!write_buffer_->BytesRemaining()) 249 if (!write_buffer_->BytesRemaining())
189 write_buffer_ = NULL; 250 write_buffer_ = NULL;
190 } while (bytes_to_send_); 251 } while (bytes_to_send_);
191 return net::OK; 252 return net::OK;
192 } 253 }
193 254
255 void NetworkStats::StartReadDataTimer(int milliseconds) {
256 MessageLoop::current()->PostDelayedTask(
257 FROM_HERE,
258 timers_factory_.NewRunnableMethod(&NetworkStats::OnReadDataTimeout),
259 milliseconds);
260 }
261
262 void NetworkStats::OnReadDataTimeout() {
263 Finish(READ_TIMED_OUT, net::ERR_INVALID_ARGUMENT);
264 }
265
266 void NetworkStats::GetEchoRequest(net::IOBuffer* io_buffer) {
267 // Copy the <version> into the io_buffer starting from the kVersionStart
268 // position.
269 std::string version = base::StringPrintf("%02d", kVersionNumber);
270 char* buffer = io_buffer->data() + kVersionStart;
271 DCHECK(kVersionLength == version.length());
272 memcpy(buffer, version.c_str(), kVersionLength);
273
274 // Get the <payload> from the |stream_| and copy it into io_buffer starting
275 // from the kPayloadStart position.
276 buffer = io_buffer->data() + kPayloadStart;
277 stream_.GetBytes(buffer, load_size_);
278
279 // Calculate the <checksum> of the <payload>.
280 uint32 sum = 0;
281 for (uint32 i = 0; i < load_size_; ++i)
282 sum += buffer[i];
283
284 // Copy the <checksum> into the io_buffer starting from the kChecksumStart
285 // position.
286 std::string checksum = base::StringPrintf("%010d", sum);
287 buffer = io_buffer->data() + kChecksumStart;
288 DCHECK(kChecksumLength == checksum.length());
289 memcpy(buffer, checksum.c_str(), kChecksumLength);
290
291 // Copy the size of the <payload> into the io_buffer starting from the
292 // kPayloadSizeStart position.
293 buffer = io_buffer->data() + kPayloadSizeStart;
294 std::string payload_size = base::StringPrintf("%07d", load_size_);
295 DCHECK(kPayloadSizeLength == payload_size.length());
296 memcpy(buffer, payload_size.c_str(), kPayloadSizeLength);
297 }
298
299 bool NetworkStats::VerifyBytes() {
300 // If the "echo response" doesn't have enough bytes, then return false.
301 if (encoded_message_.length() < kEncodedPayloadStart)
302 return false;
303
304 // Extract the |key| from the "echo response".
305 std::string key_string = encoded_message_.substr(kKeyStart, kKeyLength);
306 const char* key = key_string.c_str();
307 int key_value = atoi(key);
308 if (key_value < kKeyMinValue || key_value > kKeyMaxValue)
309 return false;
310
311 std::string encoded_payload =
312 encoded_message_.substr(kEncodedPayloadStart);
313 const char* encoded_data = encoded_payload.c_str();
314 uint32 message_length = encoded_payload.length();
315 message_length = std::min(message_length, kMaxMessage);
316 // We should get back all the data we had sent.
317 if (message_length != load_size_)
318 return false;
319
320 // Decrypt the data by looping through the |encoded_data| and XOR each byte
321 // with the |key| to get the decoded byte. Append the decoded byte to the
322 // |decoded_data|.
323 char decoded_data[kMaxMessage + 1];
324 for (uint32 data_index = 0, key_index = 0;
325 data_index < message_length;
326 ++data_index) {
327 char encoded_byte = encoded_data[data_index];
328 char key_byte = key[key_index];
329 char decoded_byte = encoded_byte ^ key_byte;
330 decoded_data[data_index] = decoded_byte;
331 key_index = (key_index + 1) % kKeyLength;
332 }
333
334 return stream_.VerifyBytes(decoded_data, message_length);
335 }
336
194 // UDPStatsClient methods and members. 337 // UDPStatsClient methods and members.
195 UDPStatsClient::UDPStatsClient() 338 UDPStatsClient::UDPStatsClient()
196 : NetworkStats() { 339 : NetworkStats() {
197 } 340 }
198 341
199 UDPStatsClient::~UDPStatsClient() { 342 UDPStatsClient::~UDPStatsClient() {
200 } 343 }
201 344
202 bool UDPStatsClient::Start(const std::string& ip_str, 345 bool UDPStatsClient::Start(const std::string& ip_str,
203 int port, 346 int port,
204 int bytes_to_send, 347 uint32 bytes_to_send,
205 net::CompletionCallback* finished_callback) { 348 net::CompletionCallback* finished_callback) {
206 DCHECK(port); 349 DCHECK(port);
207 DCHECK(bytes_to_send); // We should have data to send. 350 DCHECK(bytes_to_send); // We should have data to send.
208 351
209 Initialize(bytes_to_send, finished_callback); 352 Initialize(bytes_to_send, finished_callback);
210 353
211 net::IPAddressNumber ip_number; 354 net::IPAddressNumber ip_number;
212 if (!net::ParseIPLiteralToNumber(ip_str, &ip_number)) { 355 if (!net::ParseIPLiteralToNumber(ip_str, &ip_number)) {
213 Finish(IP_STRING_PARSE_FAILED, net::ERR_INVALID_ARGUMENT); 356 Finish(IP_STRING_PARSE_FAILED, net::ERR_INVALID_ARGUMENT);
214 return false; 357 return false;
215 } 358 }
216 net::IPEndPoint server_address = net::IPEndPoint(ip_number, port); 359 net::IPEndPoint server_address = net::IPEndPoint(ip_number, port);
217 360
218 net::UDPClientSocket* udp_socket = 361 net::UDPClientSocket* udp_socket =
219 new net::UDPClientSocket(net::DatagramSocket::DEFAULT_BIND, 362 new net::UDPClientSocket(net::DatagramSocket::DEFAULT_BIND,
220 net::RandIntCallback(), 363 net::RandIntCallback(),
221 NULL, 364 NULL,
222 net::NetLog::Source()); 365 net::NetLog::Source());
223 DCHECK(udp_socket); 366 if (!udp_socket) {
367 Finish(SOCKET_CREATE_FAILED, net::ERR_INVALID_ARGUMENT);
368 return false;
369 }
224 set_socket(udp_socket); 370 set_socket(udp_socket);
225 371
226 int rv = udp_socket->Connect(server_address); 372 int rv = udp_socket->Connect(server_address);
227 return DoStart(rv); 373 return DoStart(rv);
228 } 374 }
229 375
376 bool UDPStatsClient::ReadComplete(int result) {
377 DCHECK_NE(net::ERR_IO_PENDING, result);
378 if (result <= 0) {
379 Finish(READ_FAILED, result);
380 return true;
381 }
382 return NetworkStats::ReadComplete(result);
383 }
384
230 void UDPStatsClient::Finish(Status status, int result) { 385 void UDPStatsClient::Finish(Status status, int result) {
231 base::TimeDelta duration = base::TimeTicks::Now() - start_time(); 386 base::TimeDelta duration = base::TimeTicks::Now() - start_time();
232 if (load_size() == kSmallTestBytesToSend) { 387 if (load_size() == kSmallTestBytesToSend) {
233 if (result == net::OK) 388 if (result == net::OK)
234 UMA_HISTOGRAM_TIMES("NetConnectivity.UDP.Success.100B.RTT", duration); 389 UMA_HISTOGRAM_TIMES("NetConnectivity.UDP.Success.100B.RTT", duration);
235 else 390 else
236 UMA_HISTOGRAM_TIMES("NetConnectivity.UDP.Fail.100B.RTT", duration); 391 UMA_HISTOGRAM_TIMES("NetConnectivity.UDP.Fail.100B.RTT", duration);
237 392
238 UMA_HISTOGRAM_ENUMERATION( 393 UMA_HISTOGRAM_ENUMERATION(
239 "NetConnectivity.UDP.Status.100B", status, STATUS_MAX); 394 "NetConnectivity.UDP.Status.100B", status, STATUS_MAX);
(...skipping 25 matching lines...) Expand all
265 resolve_callback_(this, &TCPStatsClient::OnResolveComplete)), 420 resolve_callback_(this, &TCPStatsClient::OnResolveComplete)),
266 ALLOW_THIS_IN_INITIALIZER_LIST( 421 ALLOW_THIS_IN_INITIALIZER_LIST(
267 connect_callback_(this, &TCPStatsClient::OnConnectComplete)) { 422 connect_callback_(this, &TCPStatsClient::OnConnectComplete)) {
268 } 423 }
269 424
270 TCPStatsClient::~TCPStatsClient() { 425 TCPStatsClient::~TCPStatsClient() {
271 } 426 }
272 427
273 bool TCPStatsClient::Start(net::HostResolver* host_resolver, 428 bool TCPStatsClient::Start(net::HostResolver* host_resolver,
274 const net::HostPortPair& server_host_port_pair, 429 const net::HostPortPair& server_host_port_pair,
275 int bytes_to_send, 430 uint32 bytes_to_send,
276 net::CompletionCallback* finished_callback) { 431 net::CompletionCallback* finished_callback) {
277 DCHECK(bytes_to_send); // We should have data to send. 432 DCHECK(bytes_to_send); // We should have data to send.
278 433
279 Initialize(bytes_to_send, finished_callback); 434 Initialize(bytes_to_send, finished_callback);
280 435
281 net::HostResolver::RequestInfo request(server_host_port_pair); 436 net::HostResolver::RequestInfo request(server_host_port_pair);
282 int rv = host_resolver->Resolve(request, 437 int rv = host_resolver->Resolve(request,
283 &addresses_, 438 &addresses_,
284 &resolve_callback_, 439 &resolve_callback_,
285 NULL, 440 NULL,
286 net::BoundNetLog()); 441 net::BoundNetLog());
287 if (rv == net::ERR_IO_PENDING) 442 if (rv == net::ERR_IO_PENDING)
288 return true; 443 return true;
289 return DoConnect(rv); 444 return DoConnect(rv);
290 } 445 }
291 446
292 void TCPStatsClient::OnResolveComplete(int result) { 447 void TCPStatsClient::OnResolveComplete(int result) {
293 DoConnect(result); 448 DoConnect(result);
294 } 449 }
295 450
296 bool TCPStatsClient::DoConnect(int result) { 451 bool TCPStatsClient::DoConnect(int result) {
297 if (result != net::OK) { 452 if (result != net::OK) {
298 Finish(RESOLVE_FAILED, result); 453 Finish(RESOLVE_FAILED, result);
299 return false; 454 return false;
300 } 455 }
301 456
302 net::TCPClientSocket* tcp_socket = 457 net::TCPClientSocket* tcp_socket =
303 new net::TCPClientSocket(addresses_, NULL, net::NetLog::Source()); 458 new net::TCPClientSocket(addresses_, NULL, net::NetLog::Source());
304 DCHECK(tcp_socket); 459 if (!tcp_socket) {
460 Finish(SOCKET_CREATE_FAILED, net::ERR_INVALID_ARGUMENT);
461 return false;
462 }
305 set_socket(tcp_socket); 463 set_socket(tcp_socket);
306 464
307 int rv = tcp_socket->Connect(&connect_callback_); 465 int rv = tcp_socket->Connect(&connect_callback_);
308 if (rv == net::ERR_IO_PENDING) 466 if (rv == net::ERR_IO_PENDING)
309 return true; 467 return true;
310 468
311 return DoStart(rv); 469 return DoStart(rv);
312 } 470 }
313 471
314 void TCPStatsClient::OnConnectComplete(int result) { 472 void TCPStatsClient::OnConnectComplete(int result) {
315 DoStart(result); 473 DoStart(result);
316 } 474 }
317 475
476 bool TCPStatsClient::ReadComplete(int result) {
477 DCHECK_NE(net::ERR_IO_PENDING, result);
478 if (result < 0) {
479 Finish(READ_FAILED, result);
480 return true;
481 }
482 return NetworkStats::ReadComplete(result);
483 }
484
318 void TCPStatsClient::Finish(Status status, int result) { 485 void TCPStatsClient::Finish(Status status, int result) {
319 base::TimeDelta duration = base::TimeTicks::Now() - start_time(); 486 base::TimeDelta duration = base::TimeTicks::Now() - start_time();
320 if (load_size() == kSmallTestBytesToSend) { 487 if (load_size() == kSmallTestBytesToSend) {
321 if (result == net::OK) 488 if (result == net::OK)
322 UMA_HISTOGRAM_TIMES("NetConnectivity.TCP.Success.100B.RTT", duration); 489 UMA_HISTOGRAM_TIMES("NetConnectivity.TCP.Success.100B.RTT", duration);
323 else 490 else
324 UMA_HISTOGRAM_TIMES("NetConnectivity.TCP.Fail.100B.RTT", duration); 491 UMA_HISTOGRAM_TIMES("NetConnectivity.TCP.Fail.100B.RTT", duration);
325 492
326 UMA_HISTOGRAM_ENUMERATION( 493 UMA_HISTOGRAM_ENUMERATION(
327 "NetConnectivity.TCP.Status.100B", status, STATUS_MAX); 494 "NetConnectivity.TCP.Status.100B", status, STATUS_MAX);
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 TCPStatsClient* small_tcp_client = new TCPStatsClient(); 591 TCPStatsClient* small_tcp_client = new TCPStatsClient();
425 small_tcp_client->Start(host_resolver, server_address, kSmallTestBytesToSend, 592 small_tcp_client->Start(host_resolver, server_address, kSmallTestBytesToSend,
426 NULL); 593 NULL);
427 594
428 TCPStatsClient* large_tcp_client = new TCPStatsClient(); 595 TCPStatsClient* large_tcp_client = new TCPStatsClient();
429 large_tcp_client->Start(host_resolver, server_address, kLargeTestBytesToSend, 596 large_tcp_client->Start(host_resolver, server_address, kLargeTestBytesToSend,
430 NULL); 597 NULL);
431 } 598 }
432 599
433 } // namespace chrome_browser_net 600 } // namespace chrome_browser_net
OLDNEW
« no previous file with comments | « chrome/browser/net/network_stats.h ('k') | net/tools/testserver/echo_message.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698