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

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

Issue 721273002: Remove timing limitation to set Broadcast, ReceiveBuffer, and SendBuffer options from UDPSocket. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years 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
« 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 <net/if.h> 10 #include <net/if.h>
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 60
61 } // namespace 61 } // namespace
62 62
63 UDPSocketLibevent::UDPSocketLibevent( 63 UDPSocketLibevent::UDPSocketLibevent(
64 DatagramSocket::BindType bind_type, 64 DatagramSocket::BindType bind_type,
65 const RandIntCallback& rand_int_cb, 65 const RandIntCallback& rand_int_cb,
66 net::NetLog* net_log, 66 net::NetLog* net_log,
67 const net::NetLog::Source& source) 67 const net::NetLog::Source& source)
68 : socket_(kInvalidSocket), 68 : socket_(kInvalidSocket),
69 addr_family_(0), 69 addr_family_(0),
70 is_connected_(false),
70 socket_options_(SOCKET_OPTION_MULTICAST_LOOP), 71 socket_options_(SOCKET_OPTION_MULTICAST_LOOP),
71 multicast_interface_(0), 72 multicast_interface_(0),
72 multicast_time_to_live_(1), 73 multicast_time_to_live_(1),
73 bind_type_(bind_type), 74 bind_type_(bind_type),
74 rand_int_cb_(rand_int_cb), 75 rand_int_cb_(rand_int_cb),
75 read_watcher_(this), 76 read_watcher_(this),
76 write_watcher_(this), 77 write_watcher_(this),
77 read_buf_len_(0), 78 read_buf_len_(0),
78 recv_from_address_(NULL), 79 recv_from_address_(NULL),
79 write_buf_len_(0), 80 write_buf_len_(0),
80 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) { 81 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) {
81 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, 82 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE,
82 source.ToEventParametersCallback()); 83 source.ToEventParametersCallback());
83 if (bind_type == DatagramSocket::RANDOM_BIND) 84 if (bind_type == DatagramSocket::RANDOM_BIND)
84 DCHECK(!rand_int_cb.is_null()); 85 DCHECK(!rand_int_cb.is_null());
85 } 86 }
86 87
87 UDPSocketLibevent::~UDPSocketLibevent() { 88 UDPSocketLibevent::~UDPSocketLibevent() {
88 Close(); 89 Close();
89 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); 90 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE);
90 } 91 }
91 92
93 int UDPSocketLibevent::Open(AddressFamily address_family) {
94 DCHECK(CalledOnValidThread());
95 DCHECK_EQ(socket_, kInvalidSocket);
96
97 addr_family_ = ConvertAddressFamily(address_family);
98 socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, 0);
99 if (socket_ == kInvalidSocket)
100 return MapSystemError(errno);
101 if (SetNonBlocking(socket_)) {
102 const int err = MapSystemError(errno);
103 Close();
104 return err;
105 }
106 return OK;
107 }
108
92 void UDPSocketLibevent::Close() { 109 void UDPSocketLibevent::Close() {
93 DCHECK(CalledOnValidThread()); 110 DCHECK(CalledOnValidThread());
94 111
95 if (!is_connected()) 112 if (socket_ == kInvalidSocket)
96 return; 113 return;
97 114
98 // Zero out any pending read/write callback state. 115 // Zero out any pending read/write callback state.
99 read_buf_ = NULL; 116 read_buf_ = NULL;
100 read_buf_len_ = 0; 117 read_buf_len_ = 0;
101 read_callback_.Reset(); 118 read_callback_.Reset();
102 recv_from_address_ = NULL; 119 recv_from_address_ = NULL;
103 write_buf_ = NULL; 120 write_buf_ = NULL;
104 write_buf_len_ = 0; 121 write_buf_len_ = 0;
105 write_callback_.Reset(); 122 write_callback_.Reset();
106 send_to_address_.reset(); 123 send_to_address_.reset();
107 124
108 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); 125 bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
109 DCHECK(ok); 126 DCHECK(ok);
110 ok = write_socket_watcher_.StopWatchingFileDescriptor(); 127 ok = write_socket_watcher_.StopWatchingFileDescriptor();
111 DCHECK(ok); 128 DCHECK(ok);
112 129
113 if (IGNORE_EINTR(close(socket_)) < 0) 130 if (IGNORE_EINTR(close(socket_)) < 0)
114 PLOG(ERROR) << "close"; 131 PLOG(ERROR) << "close";
115 132
116 socket_ = kInvalidSocket; 133 socket_ = kInvalidSocket;
117 addr_family_ = 0; 134 addr_family_ = 0;
135 is_connected_ = false;
118 } 136 }
119 137
120 int UDPSocketLibevent::GetPeerAddress(IPEndPoint* address) const { 138 int UDPSocketLibevent::GetPeerAddress(IPEndPoint* address) const {
121 DCHECK(CalledOnValidThread()); 139 DCHECK(CalledOnValidThread());
122 DCHECK(address); 140 DCHECK(address);
123 if (!is_connected()) 141 if (!is_connected())
124 return ERR_SOCKET_NOT_CONNECTED; 142 return ERR_SOCKET_NOT_CONNECTED;
125 143
126 if (!remote_address_.get()) { 144 if (!remote_address_.get()) {
127 SockaddrStorage storage; 145 SockaddrStorage storage;
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 write_buf_len_ = buf_len; 254 write_buf_len_ = buf_len;
237 DCHECK(!send_to_address_.get()); 255 DCHECK(!send_to_address_.get());
238 if (address) { 256 if (address) {
239 send_to_address_.reset(new IPEndPoint(*address)); 257 send_to_address_.reset(new IPEndPoint(*address));
240 } 258 }
241 write_callback_ = callback; 259 write_callback_ = callback;
242 return ERR_IO_PENDING; 260 return ERR_IO_PENDING;
243 } 261 }
244 262
245 int UDPSocketLibevent::Connect(const IPEndPoint& address) { 263 int UDPSocketLibevent::Connect(const IPEndPoint& address) {
264 DCHECK_NE(socket_, kInvalidSocket);
246 net_log_.BeginEvent(NetLog::TYPE_UDP_CONNECT, 265 net_log_.BeginEvent(NetLog::TYPE_UDP_CONNECT,
247 CreateNetLogUDPConnectCallback(&address)); 266 CreateNetLogUDPConnectCallback(&address));
248 int rv = InternalConnect(address); 267 int rv = InternalConnect(address);
249 if (rv != OK)
250 Close();
251 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT, rv); 268 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT, rv);
269 is_connected_ = (rv == OK);
252 return rv; 270 return rv;
253 } 271 }
254 272
255 int UDPSocketLibevent::InternalConnect(const IPEndPoint& address) { 273 int UDPSocketLibevent::InternalConnect(const IPEndPoint& address) {
256 DCHECK(CalledOnValidThread()); 274 DCHECK(CalledOnValidThread());
257 DCHECK(!is_connected()); 275 DCHECK(!is_connected());
258 DCHECK(!remote_address_.get()); 276 DCHECK(!remote_address_.get());
259 int addr_family = address.GetSockAddrFamily();
260 int rv = CreateSocket(addr_family);
261 if (rv < 0)
262 return rv;
263 277
278 int rv = 0;
264 if (bind_type_ == DatagramSocket::RANDOM_BIND) { 279 if (bind_type_ == DatagramSocket::RANDOM_BIND) {
265 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s, 280 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s,
266 // representing INADDR_ANY or in6addr_any. 281 // representing INADDR_ANY or in6addr_any.
267 size_t addr_size = 282 size_t addr_size = address.GetSockAddrFamily() == AF_INET ?
268 addr_family == AF_INET ? kIPv4AddressSize : kIPv6AddressSize; 283 kIPv4AddressSize : kIPv6AddressSize;
269 IPAddressNumber addr_any(addr_size); 284 IPAddressNumber addr_any(addr_size);
270 rv = RandomBind(addr_any); 285 rv = RandomBind(addr_any);
271 } 286 }
272 // else connect() does the DatagramSocket::DEFAULT_BIND 287 // else connect() does the DatagramSocket::DEFAULT_BIND
273 288
274 if (rv < 0) { 289 if (rv < 0) {
275 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketRandomBindErrorCode", -rv); 290 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketRandomBindErrorCode", -rv);
276 Close();
277 return rv; 291 return rv;
278 } 292 }
279 293
280 SockaddrStorage storage; 294 SockaddrStorage storage;
281 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) { 295 if (!address.ToSockAddr(storage.addr, &storage.addr_len))
282 Close();
283 return ERR_ADDRESS_INVALID; 296 return ERR_ADDRESS_INVALID;
284 }
285 297
286 rv = HANDLE_EINTR(connect(socket_, storage.addr, storage.addr_len)); 298 rv = HANDLE_EINTR(connect(socket_, storage.addr, storage.addr_len));
287 if (rv < 0) { 299 if (rv < 0)
288 // Close() may change the current errno. Map errno beforehand. 300 return MapSystemError(errno);
289 int result = MapSystemError(errno);
290 Close();
291 return result;
292 }
293 301
294 remote_address_.reset(new IPEndPoint(address)); 302 remote_address_.reset(new IPEndPoint(address));
295 return rv; 303 return rv;
296 } 304 }
297 305
298 int UDPSocketLibevent::Bind(const IPEndPoint& address) { 306 int UDPSocketLibevent::Bind(const IPEndPoint& address) {
307 DCHECK_NE(socket_, kInvalidSocket);
299 DCHECK(CalledOnValidThread()); 308 DCHECK(CalledOnValidThread());
300 DCHECK(!is_connected()); 309 DCHECK(!is_connected());
301 int rv = CreateSocket(address.GetSockAddrFamily()); 310
311 int rv = SetMulticastOptions();
302 if (rv < 0) 312 if (rv < 0)
303 return rv; 313 return rv;
304 314
305 rv = SetSocketOptions(); 315 rv = DoBind(address);
306 if (rv < 0) { 316 if (rv < 0)
307 Close();
308 return rv; 317 return rv;
309 } 318
310 rv = DoBind(address); 319 is_connected_ = true;
311 if (rv < 0) {
312 Close();
313 return rv;
314 }
315 local_address_.reset(); 320 local_address_.reset();
316 return rv; 321 return rv;
317 } 322 }
318 323
319 int UDPSocketLibevent::SetReceiveBufferSize(int32 size) { 324 int UDPSocketLibevent::SetReceiveBufferSize(int32 size) {
325 DCHECK_NE(socket_, kInvalidSocket);
320 DCHECK(CalledOnValidThread()); 326 DCHECK(CalledOnValidThread());
321 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, 327 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF,
322 reinterpret_cast<const char*>(&size), sizeof(size)); 328 reinterpret_cast<const char*>(&size), sizeof(size));
323 int last_error = errno; 329 return rv == 0 ? OK : MapSystemError(errno);
324 DCHECK(!rv) << "Could not set socket receive buffer size: " << last_error;
325 return rv == 0 ? OK : MapSystemError(last_error);
326 } 330 }
327 331
328 int UDPSocketLibevent::SetSendBufferSize(int32 size) { 332 int UDPSocketLibevent::SetSendBufferSize(int32 size) {
333 DCHECK_NE(socket_, kInvalidSocket);
329 DCHECK(CalledOnValidThread()); 334 DCHECK(CalledOnValidThread());
330 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, 335 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF,
331 reinterpret_cast<const char*>(&size), sizeof(size)); 336 reinterpret_cast<const char*>(&size), sizeof(size));
332 int last_error = errno; 337 return rv == 0 ? OK : MapSystemError(errno);
333 DCHECK(!rv) << "Could not set socket send buffer size: " << last_error;
334 return rv == 0 ? OK : MapSystemError(last_error);
335 } 338 }
336 339
337 void UDPSocketLibevent::AllowAddressReuse() { 340 int UDPSocketLibevent::AllowAddressReuse() {
341 DCHECK_NE(socket_, kInvalidSocket);
338 DCHECK(CalledOnValidThread()); 342 DCHECK(CalledOnValidThread());
339 DCHECK(!is_connected()); 343 DCHECK(!is_connected());
340 344 int true_value = 1;
341 socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS; 345 int rv = setsockopt(
346 socket_, SOL_SOCKET, SO_REUSEADDR, &true_value, sizeof(true_value));
347 return rv == 0 ? OK : MapSystemError(errno);
342 } 348 }
343 349
344 void UDPSocketLibevent::AllowBroadcast() { 350 int UDPSocketLibevent::SetBroadcast(bool broadcast) {
351 DCHECK_NE(socket_, kInvalidSocket);
345 DCHECK(CalledOnValidThread()); 352 DCHECK(CalledOnValidThread());
346 DCHECK(!is_connected()); 353 int value = broadcast ? 1 : 0;
347 354 int rv;
348 socket_options_ |= SOCKET_OPTION_BROADCAST; 355 #if defined(OS_MACOSX)
356 // SO_REUSEPORT on OSX permits multiple processes to each receive
357 // UDP multicast or broadcast datagrams destined for the bound
358 // port.
359 rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(value));
360 #else
361 rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &value, sizeof(value));
362 #endif // defined(OS_MACOSX)
363 return rv == 0 ? OK : MapSystemError(errno);
349 } 364 }
350 365
351 void UDPSocketLibevent::ReadWatcher::OnFileCanReadWithoutBlocking(int) { 366 void UDPSocketLibevent::ReadWatcher::OnFileCanReadWithoutBlocking(int) {
352 if (!socket_->read_callback_.is_null()) 367 if (!socket_->read_callback_.is_null())
353 socket_->DidCompleteRead(); 368 socket_->DidCompleteRead();
354 } 369 }
355 370
356 void UDPSocketLibevent::WriteWatcher::OnFileCanWriteWithoutBlocking(int) { 371 void UDPSocketLibevent::WriteWatcher::OnFileCanWriteWithoutBlocking(int) {
357 if (!socket_->write_callback_.is_null()) 372 if (!socket_->write_callback_.is_null())
358 socket_->DidCompleteWrite(); 373 socket_->DidCompleteWrite();
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 CreateNetLogUDPDataTranferCallback( 426 CreateNetLogUDPDataTranferCallback(
412 result, bytes, 427 result, bytes,
413 is_address_valid ? &address : NULL)); 428 is_address_valid ? &address : NULL));
414 } 429 }
415 430
416 base::StatsCounter read_bytes("udp.read_bytes"); 431 base::StatsCounter read_bytes("udp.read_bytes");
417 read_bytes.Add(result); 432 read_bytes.Add(result);
418 NetworkActivityMonitor::GetInstance()->IncrementBytesReceived(result); 433 NetworkActivityMonitor::GetInstance()->IncrementBytesReceived(result);
419 } 434 }
420 435
421 int UDPSocketLibevent::CreateSocket(int addr_family) {
422 addr_family_ = addr_family;
423 socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, 0);
424 if (socket_ == kInvalidSocket)
425 return MapSystemError(errno);
426 if (SetNonBlocking(socket_)) {
427 const int err = MapSystemError(errno);
428 Close();
429 return err;
430 }
431 return OK;
432 }
433
434 void UDPSocketLibevent::DidCompleteWrite() { 436 void UDPSocketLibevent::DidCompleteWrite() {
435 int result = 437 int result =
436 InternalSendTo(write_buf_.get(), write_buf_len_, send_to_address_.get()); 438 InternalSendTo(write_buf_.get(), write_buf_len_, send_to_address_.get());
437 439
438 if (result != ERR_IO_PENDING) { 440 if (result != ERR_IO_PENDING) {
439 write_buf_ = NULL; 441 write_buf_ = NULL;
440 write_buf_len_ = 0; 442 write_buf_len_ = 0;
441 send_to_address_.reset(); 443 send_to_address_.reset();
442 write_socket_watcher_.StopWatchingFileDescriptor(); 444 write_socket_watcher_.StopWatchingFileDescriptor();
443 DoWriteCallback(result); 445 DoWriteCallback(result);
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
511 0, 513 0,
512 addr, 514 addr,
513 storage.addr_len)); 515 storage.addr_len));
514 if (result < 0) 516 if (result < 0)
515 result = MapSystemError(errno); 517 result = MapSystemError(errno);
516 if (result != ERR_IO_PENDING) 518 if (result != ERR_IO_PENDING)
517 LogWrite(result, buf->data(), address); 519 LogWrite(result, buf->data(), address);
518 return result; 520 return result;
519 } 521 }
520 522
521 int UDPSocketLibevent::SetSocketOptions() { 523 int UDPSocketLibevent::SetMulticastOptions() {
522 int true_value = 1;
523 if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) {
524 int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &true_value,
525 sizeof(true_value));
526 if (rv < 0)
527 return MapSystemError(errno);
528 }
529 if (socket_options_ & SOCKET_OPTION_BROADCAST) {
530 int rv;
531 #if defined(OS_MACOSX)
532 // SO_REUSEPORT on OSX permits multiple processes to each receive
533 // UDP multicast or broadcast datagrams destined for the bound
534 // port.
535 rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEPORT, &true_value,
536 sizeof(true_value));
537 #else
538 rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &true_value,
539 sizeof(true_value));
540 #endif // defined(OS_MACOSX)
541 if (rv < 0)
542 return MapSystemError(errno);
543 }
544
545 if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) { 524 if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) {
546 int rv; 525 int rv;
547 if (addr_family_ == AF_INET) { 526 if (addr_family_ == AF_INET) {
548 u_char loop = 0; 527 u_char loop = 0;
549 rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_LOOP, 528 rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_LOOP,
550 &loop, sizeof(loop)); 529 &loop, sizeof(loop));
551 } else { 530 } else {
552 u_int loop = 0; 531 u_int loop = 0;
553 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, 532 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
554 &loop, sizeof(loop)); 533 &loop, sizeof(loop));
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
770 return MapSystemError(errno); 749 return MapSystemError(errno);
771 750
772 return OK; 751 return OK;
773 } 752 }
774 753
775 void UDPSocketLibevent::DetachFromThread() { 754 void UDPSocketLibevent::DetachFromThread() {
776 base::NonThreadSafe::DetachFromThread(); 755 base::NonThreadSafe::DetachFromThread();
777 } 756 }
778 757
779 } // namespace net 758 } // 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