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

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
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(socket_ == kInvalidSocket);
96 return CreateSocket(ConvertAddressFamily(address_family));
97 }
98
92 void UDPSocketLibevent::Close() { 99 void UDPSocketLibevent::Close() {
93 DCHECK(CalledOnValidThread()); 100 DCHECK(CalledOnValidThread());
94 101
95 if (!is_connected()) 102 if (socket_ == kInvalidSocket)
96 return; 103 return;
97 104
98 // Zero out any pending read/write callback state. 105 // Zero out any pending read/write callback state.
99 read_buf_ = NULL; 106 read_buf_ = NULL;
100 read_buf_len_ = 0; 107 read_buf_len_ = 0;
101 read_callback_.Reset(); 108 read_callback_.Reset();
102 recv_from_address_ = NULL; 109 recv_from_address_ = NULL;
103 write_buf_ = NULL; 110 write_buf_ = NULL;
104 write_buf_len_ = 0; 111 write_buf_len_ = 0;
105 write_callback_.Reset(); 112 write_callback_.Reset();
106 send_to_address_.reset(); 113 send_to_address_.reset();
107 114
108 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); 115 bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
109 DCHECK(ok); 116 DCHECK(ok);
110 ok = write_socket_watcher_.StopWatchingFileDescriptor(); 117 ok = write_socket_watcher_.StopWatchingFileDescriptor();
111 DCHECK(ok); 118 DCHECK(ok);
112 119
113 if (IGNORE_EINTR(close(socket_)) < 0) 120 if (IGNORE_EINTR(close(socket_)) < 0)
114 PLOG(ERROR) << "close"; 121 PLOG(ERROR) << "close";
115 122
116 socket_ = kInvalidSocket; 123 socket_ = kInvalidSocket;
117 addr_family_ = 0; 124 addr_family_ = 0;
125 is_connected_ = false;
118 } 126 }
119 127
120 int UDPSocketLibevent::GetPeerAddress(IPEndPoint* address) const { 128 int UDPSocketLibevent::GetPeerAddress(IPEndPoint* address) const {
121 DCHECK(CalledOnValidThread()); 129 DCHECK(CalledOnValidThread());
122 DCHECK(address); 130 DCHECK(address);
123 if (!is_connected()) 131 if (!is_connected())
124 return ERR_SOCKET_NOT_CONNECTED; 132 return ERR_SOCKET_NOT_CONNECTED;
125 133
126 if (!remote_address_.get()) { 134 if (!remote_address_.get()) {
127 SockaddrStorage storage; 135 SockaddrStorage storage;
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 send_to_address_.reset(new IPEndPoint(*address)); 247 send_to_address_.reset(new IPEndPoint(*address));
240 } 248 }
241 write_callback_ = callback; 249 write_callback_ = callback;
242 return ERR_IO_PENDING; 250 return ERR_IO_PENDING;
243 } 251 }
244 252
245 int UDPSocketLibevent::Connect(const IPEndPoint& address) { 253 int UDPSocketLibevent::Connect(const IPEndPoint& address) {
246 net_log_.BeginEvent(NetLog::TYPE_UDP_CONNECT, 254 net_log_.BeginEvent(NetLog::TYPE_UDP_CONNECT,
247 CreateNetLogUDPConnectCallback(&address)); 255 CreateNetLogUDPConnectCallback(&address));
248 int rv = InternalConnect(address); 256 int rv = InternalConnect(address);
249 if (rv != OK)
250 Close();
251 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT, rv); 257 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT, rv);
258 is_connected_ = (rv == OK);
252 return rv; 259 return rv;
253 } 260 }
254 261
255 int UDPSocketLibevent::InternalConnect(const IPEndPoint& address) { 262 int UDPSocketLibevent::InternalConnect(const IPEndPoint& address) {
256 DCHECK(CalledOnValidThread()); 263 DCHECK(CalledOnValidThread());
257 DCHECK(!is_connected()); 264 DCHECK(!is_connected());
258 DCHECK(!remote_address_.get()); 265 DCHECK(!remote_address_.get());
259 int addr_family = address.GetSockAddrFamily();
260 int rv = CreateSocket(addr_family);
261 if (rv < 0)
262 return rv;
263 266
267 int rv = 0;
264 if (bind_type_ == DatagramSocket::RANDOM_BIND) { 268 if (bind_type_ == DatagramSocket::RANDOM_BIND) {
265 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s, 269 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s,
266 // representing INADDR_ANY or in6addr_any. 270 // representing INADDR_ANY or in6addr_any.
267 size_t addr_size = 271 size_t addr_size = address.GetSockAddrFamily() == AF_INET ?
268 addr_family == AF_INET ? kIPv4AddressSize : kIPv6AddressSize; 272 kIPv4AddressSize : kIPv6AddressSize;
269 IPAddressNumber addr_any(addr_size); 273 IPAddressNumber addr_any(addr_size);
270 rv = RandomBind(addr_any); 274 rv = RandomBind(addr_any);
271 } 275 }
272 // else connect() does the DatagramSocket::DEFAULT_BIND 276 // else connect() does the DatagramSocket::DEFAULT_BIND
273 277
274 if (rv < 0) { 278 if (rv < 0) {
275 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketRandomBindErrorCode", -rv); 279 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketRandomBindErrorCode", -rv);
276 Close();
277 return rv; 280 return rv;
278 } 281 }
279 282
280 SockaddrStorage storage; 283 SockaddrStorage storage;
281 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) { 284 if (!address.ToSockAddr(storage.addr, &storage.addr_len))
282 Close();
283 return ERR_ADDRESS_INVALID; 285 return ERR_ADDRESS_INVALID;
284 }
285 286
286 rv = HANDLE_EINTR(connect(socket_, storage.addr, storage.addr_len)); 287 rv = HANDLE_EINTR(connect(socket_, storage.addr, storage.addr_len));
287 if (rv < 0) { 288 if (rv < 0)
288 // Close() may change the current errno. Map errno beforehand. 289 return MapSystemError(errno);
289 int result = MapSystemError(errno);
290 Close();
291 return result;
292 }
293 290
294 remote_address_.reset(new IPEndPoint(address)); 291 remote_address_.reset(new IPEndPoint(address));
295 return rv; 292 return rv;
296 } 293 }
297 294
298 int UDPSocketLibevent::Bind(const IPEndPoint& address) { 295 int UDPSocketLibevent::Bind(const IPEndPoint& address) {
299 DCHECK(CalledOnValidThread()); 296 DCHECK(CalledOnValidThread());
300 DCHECK(!is_connected()); 297 DCHECK(!is_connected());
301 int rv = CreateSocket(address.GetSockAddrFamily()); 298
299 int rv = SetSocketOptions();
302 if (rv < 0) 300 if (rv < 0)
303 return rv; 301 return rv;
304 302
305 rv = SetSocketOptions(); 303 rv = DoBind(address);
306 if (rv < 0) { 304 if (rv < 0)
307 Close();
308 return rv; 305 return rv;
309 } 306
310 rv = DoBind(address); 307 is_connected_ = true;
311 if (rv < 0) {
312 Close();
313 return rv;
314 }
315 local_address_.reset(); 308 local_address_.reset();
316 return rv; 309 return rv;
317 } 310 }
318 311
319 int UDPSocketLibevent::SetReceiveBufferSize(int32 size) { 312 int UDPSocketLibevent::SetReceiveBufferSize(int32 size) {
320 DCHECK(CalledOnValidThread()); 313 DCHECK(CalledOnValidThread());
321 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, 314 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF,
322 reinterpret_cast<const char*>(&size), sizeof(size)); 315 reinterpret_cast<const char*>(&size), sizeof(size));
323 int last_error = errno; 316 int last_error = errno;
324 DCHECK(!rv) << "Could not set socket receive buffer size: " << last_error; 317 DCHECK(!rv) << "Could not set socket receive buffer size: " << last_error;
325 return rv == 0 ? OK : MapSystemError(last_error); 318 return rv == 0 ? OK : MapSystemError(last_error);
326 } 319 }
327 320
328 int UDPSocketLibevent::SetSendBufferSize(int32 size) { 321 int UDPSocketLibevent::SetSendBufferSize(int32 size) {
329 DCHECK(CalledOnValidThread()); 322 DCHECK(CalledOnValidThread());
330 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, 323 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF,
331 reinterpret_cast<const char*>(&size), sizeof(size)); 324 reinterpret_cast<const char*>(&size), sizeof(size));
332 int last_error = errno; 325 int last_error = errno;
333 DCHECK(!rv) << "Could not set socket send buffer size: " << last_error; 326 DCHECK(!rv) << "Could not set socket send buffer size: " << last_error;
334 return rv == 0 ? OK : MapSystemError(last_error); 327 return rv == 0 ? OK : MapSystemError(last_error);
335 } 328 }
336 329
337 void UDPSocketLibevent::AllowAddressReuse() { 330 void UDPSocketLibevent::AllowAddressReuse() {
338 DCHECK(CalledOnValidThread()); 331 DCHECK(CalledOnValidThread());
339 DCHECK(!is_connected()); 332 DCHECK(!is_connected());
340 333
341 socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS; 334 socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS;
342 } 335 }
343 336
344 void UDPSocketLibevent::AllowBroadcast() { 337 int UDPSocketLibevent::SetBroadcast(bool broadcast) {
345 DCHECK(CalledOnValidThread()); 338 DCHECK(CalledOnValidThread());
346 DCHECK(!is_connected()); 339 int value = broadcast ? 1 : 0;
347 340 int rv;
348 socket_options_ |= SOCKET_OPTION_BROADCAST; 341 #if defined(OS_MACOSX)
342 // SO_REUSEPORT on OSX permits multiple processes to each receive
343 // UDP multicast or broadcast datagrams destined for the bound
344 // port.
345 rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(value));
346 #else
347 rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &value, sizeof(value));
348 #endif // defined(OS_MACOSX)
349 int last_error = errno;
350 DCHECK(!rv) << "Could not set socket broadcast option: " << last_error;
rvargas (doing something else) 2014/12/02 23:28:09 Not a good idea to DCHECK the return of an operati
hidehiko 2014/12/03 17:33:27 Done.
351 return rv == 0 ? OK : MapSystemError(last_error);
349 } 352 }
350 353
351 void UDPSocketLibevent::ReadWatcher::OnFileCanReadWithoutBlocking(int) { 354 void UDPSocketLibevent::ReadWatcher::OnFileCanReadWithoutBlocking(int) {
352 if (!socket_->read_callback_.is_null()) 355 if (!socket_->read_callback_.is_null())
353 socket_->DidCompleteRead(); 356 socket_->DidCompleteRead();
354 } 357 }
355 358
356 void UDPSocketLibevent::WriteWatcher::OnFileCanWriteWithoutBlocking(int) { 359 void UDPSocketLibevent::WriteWatcher::OnFileCanWriteWithoutBlocking(int) {
357 if (!socket_->write_callback_.is_null()) 360 if (!socket_->write_callback_.is_null())
358 socket_->DidCompleteWrite(); 361 socket_->DidCompleteWrite();
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
512 addr, 515 addr,
513 storage.addr_len)); 516 storage.addr_len));
514 if (result < 0) 517 if (result < 0)
515 result = MapSystemError(errno); 518 result = MapSystemError(errno);
516 if (result != ERR_IO_PENDING) 519 if (result != ERR_IO_PENDING)
517 LogWrite(result, buf->data(), address); 520 LogWrite(result, buf->data(), address);
518 return result; 521 return result;
519 } 522 }
520 523
521 int UDPSocketLibevent::SetSocketOptions() { 524 int UDPSocketLibevent::SetSocketOptions() {
522 int true_value = 1;
523 if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) { 525 if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) {
524 int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &true_value, 526 int true_value = 1;
525 sizeof(true_value)); 527 int rv = setsockopt(
528 socket_, SOL_SOCKET, SO_REUSEADDR, &true_value, sizeof(true_value));
526 if (rv < 0) 529 if (rv < 0)
527 return MapSystemError(errno); 530 return MapSystemError(errno);
528 } 531 }
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 532
545 if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) { 533 if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) {
546 int rv; 534 int rv;
547 if (addr_family_ == AF_INET) { 535 if (addr_family_ == AF_INET) {
548 u_char loop = 0; 536 u_char loop = 0;
549 rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_LOOP, 537 rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_LOOP,
550 &loop, sizeof(loop)); 538 &loop, sizeof(loop));
551 } else { 539 } else {
552 u_int loop = 0; 540 u_int loop = 0;
553 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, 541 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
770 return MapSystemError(errno); 758 return MapSystemError(errno);
771 759
772 return OK; 760 return OK;
773 } 761 }
774 762
775 void UDPSocketLibevent::DetachFromThread() { 763 void UDPSocketLibevent::DetachFromThread() {
776 base::NonThreadSafe::DetachFromThread(); 764 base::NonThreadSafe::DetachFromThread();
777 } 765 }
778 766
779 } // namespace net 767 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698