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

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
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_ =
58 bytes_to_read_ = bytes_to_send; 100 kVersionLength + kChecksumLength + kPayloadSizeLength + load_size_;
101 bytes_to_read_ =
102 kVersionLength + kChecksumLength + kPayloadSizeLength + kKeyLength +
jar (doing other things) 2011/08/15 19:33:50 style nit: (personal?): suggest not wrapping until
ramant (doing other things) 2011/08/16 00:00:03 Done.
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.
69 114
70 start_time_ = base::TimeTicks::Now(); 115 start_time_ = base::TimeTicks::Now();
71 116
72 int rv = SendData(); 117 int rv = SendData();
73 if (rv < 0) { 118 if (rv < 0) {
74 if (rv != net::ERR_IO_PENDING) { 119 if (rv != net::ERR_IO_PENDING) {
75 Finish(WRITE_FAILED, rv); 120 Finish(WRITE_FAILED, rv);
76 return false; 121 return false;
77 } 122 }
78 } 123 }
79 124
80 stream_.Reset(); 125 stream_.Reset();
126
127 // Timeout if we don't get response back from echo servers in 60 secs.
128 const int kReadDataTimeoutMs = 60000;
129 StartReadDataTimer(kReadDataTimeoutMs);
130
81 ReadData(); 131 ReadData();
82 132
83 return true; 133 return true;
84 } 134 }
85 135
86 void NetworkStats::DoFinishCallback(int result) { 136 void NetworkStats::DoFinishCallback(int result) {
87 if (finished_callback_ != NULL) { 137 if (finished_callback_ != NULL) {
88 net::CompletionCallback* callback = finished_callback_; 138 net::CompletionCallback* callback = finished_callback_;
89 finished_callback_ = NULL; 139 finished_callback_ = NULL;
90 callback->Run(result); 140 callback->Run(result);
91 } 141 }
92 } 142 }
93 143
94 void NetworkStats::set_socket(net::Socket* socket) { 144 void NetworkStats::set_socket(net::Socket* socket) {
95 DCHECK(socket); 145 DCHECK(socket);
96 DCHECK(!socket_.get()); 146 DCHECK(!socket_.get());
97 socket_.reset(socket); 147 socket_.reset(socket);
98 } 148 }
99 149
100 bool NetworkStats::ReadComplete(int result) { 150 bool NetworkStats::ReadComplete(int result) {
101 DCHECK(socket_.get()); 151 DCHECK(socket_.get());
102 DCHECK_NE(net::ERR_IO_PENDING, result); 152 DCHECK_NE(net::ERR_IO_PENDING, result);
103 if (result < 0) { 153 if (result < 0) {
104 Finish(READ_FAILED, result); 154 Finish(READ_FAILED, result);
105 return true; 155 return true;
106 } 156 }
107 157
108 if (!stream_.VerifyBytes(read_buffer_->data(), result)) { 158 encoded_message_.append(read_buffer_->data(), result);
109 Finish(READ_VERIFY_FAILED, net::ERR_INVALID_RESPONSE);
110 return true;
111 }
112 159
113 read_buffer_ = NULL; 160 read_buffer_ = NULL;
114 bytes_to_read_ -= result; 161 bytes_to_read_ -= result;
115 162
116 // No more data to read. 163 // No more data to read.
117 if (!bytes_to_read_) { 164 if (!bytes_to_read_ || result == 0) {
118 Finish(SUCCESS, net::OK); 165 if (VerifyBytes())
166 Finish(SUCCESS, net::OK);
167 else
168 Finish(READ_VERIFY_FAILED, net::ERR_INVALID_RESPONSE);
119 return true; 169 return true;
120 } 170 }
121 ReadData();
122 return false; 171 return false;
123 } 172 }
124 173
125 void NetworkStats::OnReadComplete(int result) { 174 void NetworkStats::OnReadComplete(int result) {
126 ReadComplete(result); 175 if (!ReadComplete(result)) {
176 MessageLoop::current()->PostTask(
jar (doing other things) 2011/08/15 19:33:50 This deserves some comment. You mentioned that yo
ramant (doing other things) 2011/08/16 00:00:03 Done.
177 FROM_HERE,
178 timers_factory_.NewRunnableMethod(&NetworkStats::ReadData));
179 }
127 } 180 }
128 181
129 void NetworkStats::OnWriteComplete(int result) { 182 void NetworkStats::OnWriteComplete(int result) {
130 DCHECK(socket_.get()); 183 DCHECK(socket_.get());
131 DCHECK_NE(net::ERR_IO_PENDING, result); 184 DCHECK_NE(net::ERR_IO_PENDING, result);
132 if (result < 0) { 185 if (result < 0) {
133 Finish(WRITE_FAILED, result); 186 Finish(WRITE_FAILED, result);
134 return; 187 return;
135 } 188 }
136 189
137 write_buffer_->DidConsume(result); 190 write_buffer_->DidConsume(result);
138 bytes_to_send_ -= result; 191 bytes_to_send_ -= result;
139 if (!write_buffer_->BytesRemaining()) 192 if (!write_buffer_->BytesRemaining())
140 write_buffer_ = NULL; 193 write_buffer_ = NULL;
141 194
142 if (bytes_to_send_) { 195 if (bytes_to_send_) {
143 int rv = SendData(); 196 int rv = SendData();
144 if (rv < 0) { 197 if (rv < 0) {
145 if (rv != net::ERR_IO_PENDING) { 198 if (rv != net::ERR_IO_PENDING) {
146 Finish(WRITE_FAILED, rv); 199 Finish(WRITE_FAILED, rv);
147 return; 200 return;
148 } 201 }
149 } 202 }
150 } 203 }
151 } 204 }
152 205
153 void NetworkStats::ReadData() { 206 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; 207 int rv;
161 do { 208 do {
162 DCHECK(socket_.get()); 209 if (!socket_.get())
210 return;
211
212 DCHECK(!read_buffer_.get());
213
214 // We release the read_buffer_ in the destructor if there is an error.
215 read_buffer_ = new net::IOBuffer(kMaxMessage);
216
163 rv = socket_->Read(read_buffer_, kMaxMessage, &read_callback_); 217 rv = socket_->Read(read_buffer_, kMaxMessage, &read_callback_);
164 if (rv == net::ERR_IO_PENDING) 218 if (rv == net::ERR_IO_PENDING)
165 return; 219 return;
166 if (ReadComplete(rv)) // Complete the read manually. 220 // If we have read all the data then return.
221 if (ReadComplete(rv))
167 return; 222 return;
168 } while (rv > 0); 223 } while (rv > 0);
169 } 224 }
170 225
171 int NetworkStats::SendData() { 226 int NetworkStats::SendData() {
172 DCHECK(bytes_to_send_); // We should have data to send. 227 DCHECK(bytes_to_send_); // We should have data to send.
173 do { 228 do {
174 if (!write_buffer_.get()) { 229 if (!write_buffer_.get()) {
175 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(bytes_to_send_)); 230 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(bytes_to_send_));
176 stream_.GetBytes(buffer->data(), bytes_to_send_); 231 GetEchoRequest(buffer);
177 write_buffer_ = new net::DrainableIOBuffer(buffer, bytes_to_send_); 232 write_buffer_ = new net::DrainableIOBuffer(buffer, bytes_to_send_);
178 } 233 }
179 234
180 DCHECK(socket_.get()); 235 if (!socket_.get())
236 return net::ERR_UNEXPECTED;
181 int rv = socket_->Write(write_buffer_, 237 int rv = socket_->Write(write_buffer_,
182 write_buffer_->BytesRemaining(), 238 write_buffer_->BytesRemaining(),
183 &write_callback_); 239 &write_callback_);
184 if (rv < 0) 240 if (rv < 0)
185 return rv; 241 return rv;
186 write_buffer_->DidConsume(rv); 242 write_buffer_->DidConsume(rv);
187 bytes_to_send_ -= rv; 243 bytes_to_send_ -= rv;
188 if (!write_buffer_->BytesRemaining()) 244 if (!write_buffer_->BytesRemaining())
189 write_buffer_ = NULL; 245 write_buffer_ = NULL;
190 } while (bytes_to_send_); 246 } while (bytes_to_send_);
191 return net::OK; 247 return net::OK;
192 } 248 }
193 249
250 void NetworkStats::StartReadDataTimer(int milliseconds) {
251 MessageLoop::current()->PostDelayedTask(
252 FROM_HERE,
253 timers_factory_.NewRunnableMethod(&NetworkStats::OnReadDataTimeout),
254 milliseconds);
255 }
256
257 void NetworkStats::OnReadDataTimeout() {
258 Finish(READ_FAILED, net::ERR_INVALID_ARGUMENT);
jar (doing other things) 2011/08/15 19:33:50 Is there any better error code to supply here?
ramant (doing other things) 2011/08/16 00:00:03 Done.
259 }
260
261 void NetworkStats::GetEchoRequest(net::IOBuffer* io_buffer) {
262 // Copy the <version> into the io_buffer starting from the kVersionStart
263 // position.
264 std::string version = base::StringPrintf("%02d", kVersionNumber);
265 char* buffer = io_buffer->data() + kVersionStart;
266 DCHECK(kVersionLength == version.length());
267 memcpy(buffer, version.c_str(), kVersionLength);
268
269 // Get the <payload> from the |stream_| and copy it into io_buffer starting
270 // from the kPayloadStart position.
271 buffer = io_buffer->data() + kPayloadStart;
272 stream_.GetBytes(buffer, load_size_);
273
274 // Calculate the <checksum> of the <payload>.
275 uint32 sum = 0;
276 for (uint32 i = 0; i < load_size_; ++i)
277 sum += buffer[i];
278
279 // Copy the <checksum> into the io_buffer starting from the kChecksumStart
280 // position.
281 std::string checksum = base::StringPrintf("%010d", sum);
282 buffer = io_buffer->data() + kChecksumStart;
283 DCHECK(kChecksumLength == checksum.length());
284 memcpy(buffer, checksum.c_str(), kChecksumLength);
285
286 // Copy the size of the <payload> into the io_buffer starting from the
287 // kPayloadSizeStart position.
288 buffer = io_buffer->data() + kPayloadSizeStart;
289 std::string payload_size = base::StringPrintf("%07d", load_size_);
290 DCHECK(kPayloadSizeLength == payload_size.length());
291 memcpy(buffer, payload_size.c_str(), kPayloadSizeLength);
292 }
293
294 bool NetworkStats::VerifyBytes() {
295 // If the "echo response" doesn't have enough bytes, then return false.
296 if (encoded_message_.length() < kEncodedPayloadStart)
297 return false;
298
299 // Extract the |key| from the "echo response".
300 std::string key_string = encoded_message_.substr(kKeyStart, kKeyLength);
301 const char* key = key_string.c_str();
302 int key_value = atoi(key);
303 if (key_value < kKeyMinValue || key_value > kKeyMaxValue)
304 return false;
305
306 std::string encoded_payload =
307 encoded_message_.substr(kEncodedPayloadStart);
308 const char* encoded_data = encoded_payload.c_str();
309 uint32 message_length = encoded_payload.length();
310 message_length = std::min(message_length, kMaxMessage);
311 // We should get back all the data we had sent.
312 if (message_length != load_size_)
313 return false;
314
315 // Decrypt the data by looping through the |encoded_data| and XOR each byte
316 // with the |key| to get the decoded byte. Append the decoded byte to the
317 // |decoded_data|.
318 char decoded_data[kMaxMessage + 1];
319 for (uint32 data_index = 0, key_index = 0;
320 data_index < message_length;
321 ++data_index) {
322 char encoded_byte = encoded_data[data_index];
323 char key_byte = key[key_index];
324 char decoded_byte = encoded_byte ^ key_byte;
325 decoded_data[data_index] = decoded_byte;
326 key_index = (key_index + 1) % kKeyLength;
327 }
328
329 return stream_.VerifyBytes(decoded_data, message_length);
330 }
331
194 // UDPStatsClient methods and members. 332 // UDPStatsClient methods and members.
195 UDPStatsClient::UDPStatsClient() 333 UDPStatsClient::UDPStatsClient()
196 : NetworkStats() { 334 : NetworkStats() {
197 } 335 }
198 336
199 UDPStatsClient::~UDPStatsClient() { 337 UDPStatsClient::~UDPStatsClient() {
200 } 338 }
201 339
202 bool UDPStatsClient::Start(const std::string& ip_str, 340 bool UDPStatsClient::Start(const std::string& ip_str,
203 int port, 341 int port,
204 int bytes_to_send, 342 uint32 bytes_to_send,
205 net::CompletionCallback* finished_callback) { 343 net::CompletionCallback* finished_callback) {
206 DCHECK(port); 344 DCHECK(port);
207 DCHECK(bytes_to_send); // We should have data to send. 345 DCHECK(bytes_to_send); // We should have data to send.
208 346
209 Initialize(bytes_to_send, finished_callback); 347 Initialize(bytes_to_send, finished_callback);
210 348
211 net::IPAddressNumber ip_number; 349 net::IPAddressNumber ip_number;
212 if (!net::ParseIPLiteralToNumber(ip_str, &ip_number)) { 350 if (!net::ParseIPLiteralToNumber(ip_str, &ip_number)) {
213 Finish(IP_STRING_PARSE_FAILED, net::ERR_INVALID_ARGUMENT); 351 Finish(IP_STRING_PARSE_FAILED, net::ERR_INVALID_ARGUMENT);
214 return false; 352 return false;
215 } 353 }
216 net::IPEndPoint server_address = net::IPEndPoint(ip_number, port); 354 net::IPEndPoint server_address = net::IPEndPoint(ip_number, port);
217 355
218 net::UDPClientSocket* udp_socket = 356 net::UDPClientSocket* udp_socket =
219 new net::UDPClientSocket(net::DatagramSocket::DEFAULT_BIND, 357 new net::UDPClientSocket(net::DatagramSocket::DEFAULT_BIND,
220 net::RandIntCallback(), 358 net::RandIntCallback(),
221 NULL, 359 NULL,
222 net::NetLog::Source()); 360 net::NetLog::Source());
223 DCHECK(udp_socket); 361 if (!udp_socket) {
362 Finish(SOCKET_CREATE_FAILED, net::ERR_INVALID_ARGUMENT);
363 return false;
364 }
224 set_socket(udp_socket); 365 set_socket(udp_socket);
225 366
226 int rv = udp_socket->Connect(server_address); 367 int rv = udp_socket->Connect(server_address);
227 return DoStart(rv); 368 return DoStart(rv);
228 } 369 }
229 370
371 bool UDPStatsClient::ReadComplete(int result) {
372 DCHECK_NE(net::ERR_IO_PENDING, result);
373 if (result <= 0) {
374 Finish(READ_FAILED, result);
375 return true;
376 }
377 return NetworkStats::ReadComplete(result);
378 }
379
230 void UDPStatsClient::Finish(Status status, int result) { 380 void UDPStatsClient::Finish(Status status, int result) {
231 base::TimeDelta duration = base::TimeTicks::Now() - start_time(); 381 base::TimeDelta duration = base::TimeTicks::Now() - start_time();
232 if (load_size() == kSmallTestBytesToSend) { 382 if (load_size() == kSmallTestBytesToSend) {
233 if (result == net::OK) 383 if (result == net::OK)
234 UMA_HISTOGRAM_TIMES("NetConnectivity.UDP.Success.100B.RTT", duration); 384 UMA_HISTOGRAM_TIMES("NetConnectivity.UDP.Success.100B.RTT", duration);
235 else 385 else
236 UMA_HISTOGRAM_TIMES("NetConnectivity.UDP.Fail.100B.RTT", duration); 386 UMA_HISTOGRAM_TIMES("NetConnectivity.UDP.Fail.100B.RTT", duration);
237 387
238 UMA_HISTOGRAM_ENUMERATION( 388 UMA_HISTOGRAM_ENUMERATION(
239 "NetConnectivity.UDP.Status.100B", status, STATUS_MAX); 389 "NetConnectivity.UDP.Status.100B", status, STATUS_MAX);
(...skipping 25 matching lines...) Expand all
265 resolve_callback_(this, &TCPStatsClient::OnResolveComplete)), 415 resolve_callback_(this, &TCPStatsClient::OnResolveComplete)),
266 ALLOW_THIS_IN_INITIALIZER_LIST( 416 ALLOW_THIS_IN_INITIALIZER_LIST(
267 connect_callback_(this, &TCPStatsClient::OnConnectComplete)) { 417 connect_callback_(this, &TCPStatsClient::OnConnectComplete)) {
268 } 418 }
269 419
270 TCPStatsClient::~TCPStatsClient() { 420 TCPStatsClient::~TCPStatsClient() {
271 } 421 }
272 422
273 bool TCPStatsClient::Start(net::HostResolver* host_resolver, 423 bool TCPStatsClient::Start(net::HostResolver* host_resolver,
274 const net::HostPortPair& server_host_port_pair, 424 const net::HostPortPair& server_host_port_pair,
275 int bytes_to_send, 425 uint32 bytes_to_send,
276 net::CompletionCallback* finished_callback) { 426 net::CompletionCallback* finished_callback) {
277 DCHECK(bytes_to_send); // We should have data to send. 427 DCHECK(bytes_to_send); // We should have data to send.
278 428
279 Initialize(bytes_to_send, finished_callback); 429 Initialize(bytes_to_send, finished_callback);
280 430
281 net::HostResolver::RequestInfo request(server_host_port_pair); 431 net::HostResolver::RequestInfo request(server_host_port_pair);
282 int rv = host_resolver->Resolve(request, 432 int rv = host_resolver->Resolve(request,
283 &addresses_, 433 &addresses_,
284 &resolve_callback_, 434 &resolve_callback_,
285 NULL, 435 NULL,
286 net::BoundNetLog()); 436 net::BoundNetLog());
287 if (rv == net::ERR_IO_PENDING) 437 if (rv == net::ERR_IO_PENDING)
288 return true; 438 return true;
289 return DoConnect(rv); 439 return DoConnect(rv);
290 } 440 }
291 441
292 void TCPStatsClient::OnResolveComplete(int result) { 442 void TCPStatsClient::OnResolveComplete(int result) {
293 DoConnect(result); 443 DoConnect(result);
294 } 444 }
295 445
296 bool TCPStatsClient::DoConnect(int result) { 446 bool TCPStatsClient::DoConnect(int result) {
297 if (result != net::OK) { 447 if (result != net::OK) {
298 Finish(RESOLVE_FAILED, result); 448 Finish(RESOLVE_FAILED, result);
299 return false; 449 return false;
300 } 450 }
301 451
302 net::TCPClientSocket* tcp_socket = 452 net::TCPClientSocket* tcp_socket =
303 new net::TCPClientSocket(addresses_, NULL, net::NetLog::Source()); 453 new net::TCPClientSocket(addresses_, NULL, net::NetLog::Source());
304 DCHECK(tcp_socket); 454 if (!tcp_socket) {
455 Finish(SOCKET_CREATE_FAILED, net::ERR_INVALID_ARGUMENT);
456 return false;
457 }
305 set_socket(tcp_socket); 458 set_socket(tcp_socket);
306 459
307 int rv = tcp_socket->Connect(&connect_callback_); 460 int rv = tcp_socket->Connect(&connect_callback_);
308 if (rv == net::ERR_IO_PENDING) 461 if (rv == net::ERR_IO_PENDING)
309 return true; 462 return true;
310 463
311 return DoStart(rv); 464 return DoStart(rv);
312 } 465 }
313 466
314 void TCPStatsClient::OnConnectComplete(int result) { 467 void TCPStatsClient::OnConnectComplete(int result) {
315 DoStart(result); 468 DoStart(result);
316 } 469 }
317 470
471 bool TCPStatsClient::ReadComplete(int result) {
472 DCHECK_NE(net::ERR_IO_PENDING, result);
473 if (result < 0) {
474 Finish(READ_FAILED, result);
475 return true;
476 }
477 return NetworkStats::ReadComplete(result);
478 }
479
318 void TCPStatsClient::Finish(Status status, int result) { 480 void TCPStatsClient::Finish(Status status, int result) {
319 base::TimeDelta duration = base::TimeTicks::Now() - start_time(); 481 base::TimeDelta duration = base::TimeTicks::Now() - start_time();
320 if (load_size() == kSmallTestBytesToSend) { 482 if (load_size() == kSmallTestBytesToSend) {
321 if (result == net::OK) 483 if (result == net::OK)
322 UMA_HISTOGRAM_TIMES("NetConnectivity.TCP.Success.100B.RTT", duration); 484 UMA_HISTOGRAM_TIMES("NetConnectivity.TCP.Success.100B.RTT", duration);
323 else 485 else
324 UMA_HISTOGRAM_TIMES("NetConnectivity.TCP.Fail.100B.RTT", duration); 486 UMA_HISTOGRAM_TIMES("NetConnectivity.TCP.Fail.100B.RTT", duration);
325 487
326 UMA_HISTOGRAM_ENUMERATION( 488 UMA_HISTOGRAM_ENUMERATION(
327 "NetConnectivity.TCP.Status.100B", status, STATUS_MAX); 489 "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(); 586 TCPStatsClient* small_tcp_client = new TCPStatsClient();
425 small_tcp_client->Start(host_resolver, server_address, kSmallTestBytesToSend, 587 small_tcp_client->Start(host_resolver, server_address, kSmallTestBytesToSend,
426 NULL); 588 NULL);
427 589
428 TCPStatsClient* large_tcp_client = new TCPStatsClient(); 590 TCPStatsClient* large_tcp_client = new TCPStatsClient();
429 large_tcp_client->Start(host_resolver, server_address, kLargeTestBytesToSend, 591 large_tcp_client->Start(host_resolver, server_address, kLargeTestBytesToSend,
430 NULL); 592 NULL);
431 } 593 }
432 594
433 } // namespace chrome_browser_net 595 } // namespace chrome_browser_net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698