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

Side by Side Diff: net/udp/udp_socket_libevent.cc

Issue 8200011: Add NetLog support to UDP sockets. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: ??? Created 9 years, 2 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 | « net/udp/udp_socket_libevent.h ('k') | net/udp/udp_socket_unittest.cc » ('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 "net/udp/udp_socket_libevent.h" 5 #include "net/udp/udp_socket_libevent.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #include <netdb.h> 9 #include <netdb.h>
10 #include <sys/socket.h> 10 #include <sys/socket.h>
11 11
12 #include "base/eintr_wrapper.h" 12 #include "base/eintr_wrapper.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/message_loop.h" 14 #include "base/message_loop.h"
15 #include "base/metrics/stats_counters.h" 15 #include "base/metrics/stats_counters.h"
16 #include "base/rand_util.h" 16 #include "base/rand_util.h"
17 #include "net/base/io_buffer.h" 17 #include "net/base/io_buffer.h"
18 #include "net/base/ip_endpoint.h" 18 #include "net/base/ip_endpoint.h"
19 #include "net/base/net_errors.h" 19 #include "net/base/net_errors.h"
20 #include "net/base/net_log.h" 20 #include "net/base/net_log.h"
21 #include "net/base/net_util.h" 21 #include "net/base/net_util.h"
22 #include "net/udp/udp_data_transfer_param.h"
22 #if defined(OS_POSIX) 23 #if defined(OS_POSIX)
23 #include <netinet/in.h> 24 #include <netinet/in.h>
24 #endif 25 #endif
25 26
26 namespace { 27 namespace {
27 28
28 static const int kBindRetries = 10; 29 static const int kBindRetries = 10;
29 static const int kPortStart = 1024; 30 static const int kPortStart = 1024;
30 static const int kPortEnd = 65535; 31 static const int kPortEnd = 65535;
31 32
32 } // namespace net 33 } // namespace net
33 34
34 namespace net { 35 namespace net {
35 36
36 UDPSocketLibevent::UDPSocketLibevent( 37 UDPSocketLibevent::UDPSocketLibevent(
37 DatagramSocket::BindType bind_type, 38 DatagramSocket::BindType bind_type,
38 const RandIntCallback& rand_int_cb, 39 const RandIntCallback& rand_int_cb,
39 net::NetLog* net_log, 40 net::NetLog* net_log,
40 const net::NetLog::Source& source) 41 const net::NetLog::Source& source)
41 : socket_(kInvalidSocket), 42 : socket_(kInvalidSocket),
42 bind_type_(bind_type), 43 bind_type_(bind_type),
43 rand_int_cb_(rand_int_cb), 44 rand_int_cb_(rand_int_cb),
44 read_watcher_(this), 45 read_watcher_(this),
45 write_watcher_(this), 46 write_watcher_(this),
46 read_buf_len_(0), 47 read_buf_len_(0),
47 recv_from_address_(NULL), 48 recv_from_address_(NULL),
48 write_buf_len_(0), 49 write_buf_len_(0),
49 read_callback_(NULL), 50 read_callback_(NULL),
50 write_callback_(NULL), 51 write_callback_(NULL),
51 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { 52 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) {
52 scoped_refptr<NetLog::EventParameters> params; 53 scoped_refptr<NetLog::EventParameters> params;
53 if (source.is_valid()) 54 if (source.is_valid())
54 params = new NetLogSourceParameter("source_dependency", source); 55 params = new NetLogSourceParameter("source_dependency", source);
55 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, params); 56 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, params);
56 if (bind_type == DatagramSocket::RANDOM_BIND) 57 if (bind_type == DatagramSocket::RANDOM_BIND)
57 DCHECK(!rand_int_cb.is_null()); 58 DCHECK(!rand_int_cb.is_null());
58 } 59 }
59 60
60 UDPSocketLibevent::~UDPSocketLibevent() { 61 UDPSocketLibevent::~UDPSocketLibevent() {
61 Close(); 62 Close();
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 DCHECK_GT(buf_len, 0); 152 DCHECK_GT(buf_len, 0);
152 153
153 int nread = InternalRecvFrom(buf, buf_len, address); 154 int nread = InternalRecvFrom(buf, buf_len, address);
154 if (nread != ERR_IO_PENDING) 155 if (nread != ERR_IO_PENDING)
155 return nread; 156 return nread;
156 157
157 if (!MessageLoopForIO::current()->WatchFileDescriptor( 158 if (!MessageLoopForIO::current()->WatchFileDescriptor(
158 socket_, true, MessageLoopForIO::WATCH_READ, 159 socket_, true, MessageLoopForIO::WATCH_READ,
159 &read_socket_watcher_, &read_watcher_)) { 160 &read_socket_watcher_, &read_watcher_)) {
160 PLOG(ERROR) << "WatchFileDescriptor failed on read"; 161 PLOG(ERROR) << "WatchFileDescriptor failed on read";
161 return MapSystemError(errno); 162 int result = MapSystemError(errno);
163 LogRead(result, NULL, 0, NULL);
164 return result;
162 } 165 }
163 166
164 read_buf_ = buf; 167 read_buf_ = buf;
165 read_buf_len_ = buf_len; 168 read_buf_len_ = buf_len;
166 recv_from_address_ = address; 169 recv_from_address_ = address;
167 read_callback_ = callback; 170 read_callback_ = callback;
168 return ERR_IO_PENDING; 171 return ERR_IO_PENDING;
169 } 172 }
170 173
171 int UDPSocketLibevent::Write(IOBuffer* buf, 174 int UDPSocketLibevent::Write(IOBuffer* buf,
(...skipping 12 matching lines...) Expand all
184 int UDPSocketLibevent::SendToOrWrite(IOBuffer* buf, 187 int UDPSocketLibevent::SendToOrWrite(IOBuffer* buf,
185 int buf_len, 188 int buf_len,
186 const IPEndPoint* address, 189 const IPEndPoint* address,
187 OldCompletionCallback* callback) { 190 OldCompletionCallback* callback) {
188 DCHECK(CalledOnValidThread()); 191 DCHECK(CalledOnValidThread());
189 DCHECK_NE(kInvalidSocket, socket_); 192 DCHECK_NE(kInvalidSocket, socket_);
190 DCHECK(!write_callback_); 193 DCHECK(!write_callback_);
191 DCHECK(callback); // Synchronous operation not supported 194 DCHECK(callback); // Synchronous operation not supported
192 DCHECK_GT(buf_len, 0); 195 DCHECK_GT(buf_len, 0);
193 196
194 int nwrite = InternalSendTo(buf, buf_len, address); 197 int result = InternalSendTo(buf, buf_len, address);
195 if (nwrite >= 0) { 198 if (result != ERR_IO_PENDING)
196 base::StatsCounter write_bytes("udp.write_bytes"); 199 return result;
197 write_bytes.Add(nwrite);
198 return nwrite;
199 }
200 if (errno != EAGAIN && errno != EWOULDBLOCK)
201 return MapSystemError(errno);
202 200
203 if (!MessageLoopForIO::current()->WatchFileDescriptor( 201 if (!MessageLoopForIO::current()->WatchFileDescriptor(
204 socket_, true, MessageLoopForIO::WATCH_WRITE, 202 socket_, true, MessageLoopForIO::WATCH_WRITE,
205 &write_socket_watcher_, &write_watcher_)) { 203 &write_socket_watcher_, &write_watcher_)) {
206 DVLOG(1) << "WatchFileDescriptor failed on write, errno " << errno; 204 DVLOG(1) << "WatchFileDescriptor failed on write, errno " << errno;
207 return MapSystemError(errno); 205 int result = MapSystemError(errno);
206 LogWrite(result, NULL, NULL);
207 return result;
208 } 208 }
209 209
210 write_buf_ = buf; 210 write_buf_ = buf;
211 write_buf_len_ = buf_len; 211 write_buf_len_ = buf_len;
212 DCHECK(!send_to_address_.get()); 212 DCHECK(!send_to_address_.get());
213 if (address) { 213 if (address) {
214 send_to_address_.reset(new IPEndPoint(*address)); 214 send_to_address_.reset(new IPEndPoint(*address));
215 } 215 }
216 write_callback_ = callback; 216 write_callback_ = callback;
217 return ERR_IO_PENDING; 217 return ERR_IO_PENDING;
218 } 218 }
219 219
220 int UDPSocketLibevent::Connect(const IPEndPoint& address) { 220 int UDPSocketLibevent::Connect(const IPEndPoint& address) {
221 net_log_.BeginEvent(
222 NetLog::TYPE_UDP_CONNECT,
223 make_scoped_refptr(new NetLogStringParameter("address",
224 address.ToString())));
225 int rv = InternalConnect(address);
226 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT, rv);
227 return rv;
228 }
229
230 int UDPSocketLibevent::InternalConnect(const IPEndPoint& address) {
221 DCHECK(CalledOnValidThread()); 231 DCHECK(CalledOnValidThread());
222 DCHECK(!is_connected()); 232 DCHECK(!is_connected());
223 DCHECK(!remote_address_.get()); 233 DCHECK(!remote_address_.get());
224 int rv = CreateSocket(address); 234 int rv = CreateSocket(address);
225 if (rv < 0) 235 if (rv < 0)
226 return rv; 236 return rv;
227 237
228 if (bind_type_ == DatagramSocket::RANDOM_BIND) 238 if (bind_type_ == DatagramSocket::RANDOM_BIND)
229 rv = RandomBind(address); 239 rv = RandomBind(address);
230 // else connect() does the DatagramSocket::DEFAULT_BIND 240 // else connect() does the DatagramSocket::DEFAULT_BIND
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 if (result != ERR_IO_PENDING) { 310 if (result != ERR_IO_PENDING) {
301 read_buf_ = NULL; 311 read_buf_ = NULL;
302 read_buf_len_ = 0; 312 read_buf_len_ = 0;
303 recv_from_address_ = NULL; 313 recv_from_address_ = NULL;
304 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); 314 bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
305 DCHECK(ok); 315 DCHECK(ok);
306 DoReadCallback(result); 316 DoReadCallback(result);
307 } 317 }
308 } 318 }
309 319
320 void UDPSocketLibevent::LogRead(int result,
321 const char* bytes,
322 socklen_t addr_len,
323 const sockaddr* addr) const {
324 if (result < 0) {
325 net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR, result);
326 return;
327 }
328
329 if (net_log_.IsLoggingAllEvents()) {
330 DCHECK(addr_len > 0);
331 DCHECK(addr);
332
333 IPEndPoint address;
334 bool is_address_valid = address.FromSockAddr(addr, addr_len);
335 net_log_.AddEvent(
336 NetLog::TYPE_UDP_BYTES_RECEIVED,
337 make_scoped_refptr(
338 new UDPDataTransferNetLogParam(
339 result, bytes, net_log_.IsLoggingBytes(),
340 is_address_valid ? &address : NULL)));
341 }
342
343 base::StatsCounter read_bytes("udp.read_bytes");
344 read_bytes.Add(result);
345 }
346
310 int UDPSocketLibevent::CreateSocket(const IPEndPoint& address) { 347 int UDPSocketLibevent::CreateSocket(const IPEndPoint& address) {
311 socket_ = socket(address.GetFamily(), SOCK_DGRAM, 0); 348 socket_ = socket(address.GetFamily(), SOCK_DGRAM, 0);
312 if (socket_ == kInvalidSocket) 349 if (socket_ == kInvalidSocket)
313 return MapSystemError(errno); 350 return MapSystemError(errno);
314 if (SetNonBlocking(socket_)) { 351 if (SetNonBlocking(socket_)) {
315 const int err = MapSystemError(errno); 352 const int err = MapSystemError(errno);
316 Close(); 353 Close();
317 return err; 354 return err;
318 } 355 }
319 return OK; 356 return OK;
320 } 357 }
321 358
322 void UDPSocketLibevent::DidCompleteWrite() { 359 void UDPSocketLibevent::DidCompleteWrite() {
323 int result = InternalSendTo(write_buf_, write_buf_len_, 360 int result = InternalSendTo(write_buf_, write_buf_len_,
324 send_to_address_.get()); 361 send_to_address_.get());
325 if (result >= 0) {
326 base::StatsCounter write_bytes("udp.write_bytes");
327 write_bytes.Add(result);
328 } else {
329 result = MapSystemError(errno);
330 }
331 362
332 if (result != ERR_IO_PENDING) { 363 if (result != ERR_IO_PENDING) {
333 write_buf_ = NULL; 364 write_buf_ = NULL;
334 write_buf_len_ = 0; 365 write_buf_len_ = 0;
335 send_to_address_.reset(); 366 send_to_address_.reset();
336 write_socket_watcher_.StopWatchingFileDescriptor(); 367 write_socket_watcher_.StopWatchingFileDescriptor();
337 DoWriteCallback(result); 368 DoWriteCallback(result);
338 } 369 }
339 } 370 }
340 371
372 void UDPSocketLibevent::LogWrite(int result,
373 const char* bytes,
374 const IPEndPoint* address) const {
375 if (result < 0) {
376 net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_SEND_ERROR, result);
377 return;
378 }
379
380 if (net_log_.IsLoggingAllEvents()) {
381 net_log_.AddEvent(
382 NetLog::TYPE_UDP_BYTES_SENT,
383 make_scoped_refptr(
384 new UDPDataTransferNetLogParam(result, bytes,
385 net_log_.IsLoggingBytes(),
386 address)));
387 }
388
389 base::StatsCounter write_bytes("udp.write_bytes");
390 write_bytes.Add(result);
391 }
392
341 int UDPSocketLibevent::InternalRecvFrom(IOBuffer* buf, int buf_len, 393 int UDPSocketLibevent::InternalRecvFrom(IOBuffer* buf, int buf_len,
342 IPEndPoint* address) { 394 IPEndPoint* address) {
343 int bytes_transferred; 395 int bytes_transferred;
344 int flags = 0; 396 int flags = 0;
345 397
346 struct sockaddr_storage addr_storage; 398 struct sockaddr_storage addr_storage;
347 socklen_t addr_len = sizeof(addr_storage); 399 socklen_t addr_len = sizeof(addr_storage);
348 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); 400 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage);
349 401
350 bytes_transferred = 402 bytes_transferred =
351 HANDLE_EINTR(recvfrom(socket_, 403 HANDLE_EINTR(recvfrom(socket_,
352 buf->data(), 404 buf->data(),
353 buf_len, 405 buf_len,
354 flags, 406 flags,
355 addr, 407 addr,
356 &addr_len)); 408 &addr_len));
357 int result; 409 int result;
358 if (bytes_transferred >= 0) { 410 if (bytes_transferred >= 0) {
359 result = bytes_transferred; 411 result = bytes_transferred;
360 base::StatsCounter read_bytes("udp.read_bytes"); 412 if (address && !address->FromSockAddr(addr, addr_len))
361 read_bytes.Add(bytes_transferred); 413 result = ERR_FAILED;
362 if (address) {
363 if (!address->FromSockAddr(addr, addr_len))
364 result = ERR_FAILED;
365 }
366 } else { 414 } else {
367 result = MapSystemError(errno); 415 result = MapSystemError(errno);
368 } 416 }
417 if (result != ERR_IO_PENDING)
418 LogRead(result, buf->data(), addr_len, addr);
369 return result; 419 return result;
370 } 420 }
371 421
372 int UDPSocketLibevent::InternalSendTo(IOBuffer* buf, int buf_len, 422 int UDPSocketLibevent::InternalSendTo(IOBuffer* buf, int buf_len,
373 const IPEndPoint* address) { 423 const IPEndPoint* address) {
374 struct sockaddr_storage addr_storage; 424 struct sockaddr_storage addr_storage;
375 size_t addr_len = sizeof(addr_storage); 425 size_t addr_len = sizeof(addr_storage);
376 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); 426 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage);
377 427
378 if (!address) { 428 if (!address) {
379 addr = NULL; 429 addr = NULL;
380 addr_len = 0; 430 addr_len = 0;
381 } else { 431 } else {
382 if (!address->ToSockAddr(addr, &addr_len)) 432 if (!address->ToSockAddr(addr, &addr_len)) {
383 return ERR_FAILED; 433 int result = ERR_FAILED;
434 LogWrite(result, NULL, NULL);
435 return result;
436 }
384 } 437 }
385 438
386 return HANDLE_EINTR(sendto(socket_, 439 int result = HANDLE_EINTR(sendto(socket_,
387 buf->data(), 440 buf->data(),
388 buf_len, 441 buf_len,
389 0, 442 0,
390 addr, 443 addr,
391 addr_len)); 444 addr_len));
445 if (result < 0)
446 result = MapSystemError(errno);
447 if (result != ERR_IO_PENDING)
448 LogWrite(result, buf->data(), address);
449 return result;
392 } 450 }
393 451
394 int UDPSocketLibevent::DoBind(const IPEndPoint& address) { 452 int UDPSocketLibevent::DoBind(const IPEndPoint& address) {
395 struct sockaddr_storage addr_storage; 453 struct sockaddr_storage addr_storage;
396 size_t addr_len = sizeof(addr_storage); 454 size_t addr_len = sizeof(addr_storage);
397 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); 455 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage);
398 if (!address.ToSockAddr(addr, &addr_len)) 456 if (!address.ToSockAddr(addr, &addr_len))
399 return ERR_UNEXPECTED; 457 return ERR_UNEXPECTED;
400 int rv = bind(socket_, addr, addr_len); 458 int rv = bind(socket_, addr, addr_len);
401 return rv < 0 ? MapSystemError(errno) : rv; 459 return rv < 0 ? MapSystemError(errno) : rv;
402 } 460 }
403 461
404 int UDPSocketLibevent::RandomBind(const IPEndPoint& address) { 462 int UDPSocketLibevent::RandomBind(const IPEndPoint& address) {
405 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null()); 463 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null());
406 464
407 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s. 465 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s.
408 IPAddressNumber ip(address.address().size()); 466 IPAddressNumber ip(address.address().size());
409 467
410 for (int i = 0; i < kBindRetries; ++i) { 468 for (int i = 0; i < kBindRetries; ++i) {
411 int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd))); 469 int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd)));
412 if (rv == OK || rv != ERR_ADDRESS_IN_USE) 470 if (rv == OK || rv != ERR_ADDRESS_IN_USE)
413 return rv; 471 return rv;
414 } 472 }
415 return DoBind(IPEndPoint(ip, 0)); 473 return DoBind(IPEndPoint(ip, 0));
416 } 474 }
417 475
418 } // namespace net 476 } // namespace net
OLDNEW
« no previous file with comments | « net/udp/udp_socket_libevent.h ('k') | net/udp/udp_socket_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698