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

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

Issue 10739002: Added broadcasting feature to UDP server sockets. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Added MacOS specific code. Created 8 years, 5 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
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 <sys/socket.h> 10 #include <sys/socket.h>
(...skipping 23 matching lines...) Expand all
34 } // namespace net 34 } // namespace net
35 35
36 namespace net { 36 namespace net {
37 37
38 UDPSocketLibevent::UDPSocketLibevent( 38 UDPSocketLibevent::UDPSocketLibevent(
39 DatagramSocket::BindType bind_type, 39 DatagramSocket::BindType bind_type,
40 const RandIntCallback& rand_int_cb, 40 const RandIntCallback& rand_int_cb,
41 net::NetLog* net_log, 41 net::NetLog* net_log,
42 const net::NetLog::Source& source) 42 const net::NetLog::Source& source)
43 : socket_(kInvalidSocket), 43 : socket_(kInvalidSocket),
44 allow_broadcast_(false),
44 bind_type_(bind_type), 45 bind_type_(bind_type),
45 rand_int_cb_(rand_int_cb), 46 rand_int_cb_(rand_int_cb),
46 read_watcher_(this), 47 read_watcher_(this),
47 write_watcher_(this), 48 write_watcher_(this),
48 read_buf_len_(0), 49 read_buf_len_(0),
49 recv_from_address_(NULL), 50 recv_from_address_(NULL),
50 write_buf_len_(0), 51 write_buf_len_(0),
51 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) { 52 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) {
52 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, 53 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE,
53 source.ToEventParametersCallback()); 54 source.ToEventParametersCallback());
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 remote_address_.reset(new IPEndPoint(address)); 245 remote_address_.reset(new IPEndPoint(address));
245 return rv; 246 return rv;
246 } 247 }
247 248
248 int UDPSocketLibevent::Bind(const IPEndPoint& address) { 249 int UDPSocketLibevent::Bind(const IPEndPoint& address) {
249 DCHECK(CalledOnValidThread()); 250 DCHECK(CalledOnValidThread());
250 DCHECK(!is_connected()); 251 DCHECK(!is_connected());
251 int rv = CreateSocket(address); 252 int rv = CreateSocket(address);
252 if (rv < 0) 253 if (rv < 0)
253 return rv; 254 return rv;
255 if (allow_broadcast_) {
256 rv = DoBroadcast();
257 if (rv < 0)
258 return rv;
259 }
254 rv = DoBind(address); 260 rv = DoBind(address);
255 if (rv < 0) 261 if (rv < 0)
256 return rv; 262 return rv;
257 local_address_.reset(); 263 local_address_.reset();
258 return rv; 264 return rv;
259 } 265 }
260 266
261 bool UDPSocketLibevent::SetReceiveBufferSize(int32 size) { 267 bool UDPSocketLibevent::SetReceiveBufferSize(int32 size) {
262 DCHECK(CalledOnValidThread()); 268 DCHECK(CalledOnValidThread());
263 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, 269 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF,
264 reinterpret_cast<const char*>(&size), sizeof(size)); 270 reinterpret_cast<const char*>(&size), sizeof(size));
265 DCHECK(!rv) << "Could not set socket receive buffer size: " << errno; 271 DCHECK(!rv) << "Could not set socket receive buffer size: " << errno;
266 return rv == 0; 272 return rv == 0;
267 } 273 }
268 274
269 bool UDPSocketLibevent::SetSendBufferSize(int32 size) { 275 bool UDPSocketLibevent::SetSendBufferSize(int32 size) {
270 DCHECK(CalledOnValidThread()); 276 DCHECK(CalledOnValidThread());
271 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, 277 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF,
272 reinterpret_cast<const char*>(&size), sizeof(size)); 278 reinterpret_cast<const char*>(&size), sizeof(size));
273 DCHECK(!rv) << "Could not set socket send buffer size: " << errno; 279 DCHECK(!rv) << "Could not set socket send buffer size: " << errno;
274 return rv == 0; 280 return rv == 0;
275 } 281 }
276 282
283 void UDPSocketLibevent::AllowBroadcast() {
284 DCHECK(CalledOnValidThread());
285 DCHECK(!is_connected());
286
287 allow_broadcast_ = true;
288 }
289
277 void UDPSocketLibevent::DoReadCallback(int rv) { 290 void UDPSocketLibevent::DoReadCallback(int rv) {
278 DCHECK_NE(rv, ERR_IO_PENDING); 291 DCHECK_NE(rv, ERR_IO_PENDING);
279 DCHECK(!read_callback_.is_null()); 292 DCHECK(!read_callback_.is_null());
280 293
281 // since Run may result in Read being called, clear read_callback_ up front. 294 // since Run may result in Read being called, clear read_callback_ up front.
282 CompletionCallback c = read_callback_; 295 CompletionCallback c = read_callback_;
283 read_callback_.Reset(); 296 read_callback_.Reset();
284 c.Run(rv); 297 c.Run(rv);
285 } 298 }
286 299
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 0, 436 0,
424 addr, 437 addr,
425 storage.addr_len)); 438 storage.addr_len));
426 if (result < 0) 439 if (result < 0)
427 result = MapSystemError(errno); 440 result = MapSystemError(errno);
428 if (result != ERR_IO_PENDING) 441 if (result != ERR_IO_PENDING)
429 LogWrite(result, buf->data(), address); 442 LogWrite(result, buf->data(), address);
430 return result; 443 return result;
431 } 444 }
432 445
446 int UDPSocketLibevent::DoBroadcast() {
447 int true_value = 1;
448 int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
449 reinterpret_cast<const char*>(&true_value),
wtc 2012/07/11 18:26:37 Since the fourth argument to setsockopt is a const
ygorshenin1 2012/07/12 09:28:08 Done.
450 sizeof(true_value));
451 if (rv < 0)
452 return MapSystemError(errno);
453 #if defined(OS_MACOSX)
wtc 2012/07/11 18:26:37 If SO_REUSEPORT is defined as a macro (rather than
ygorshenin1 2012/07/12 09:28:08 Done.
454 rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEPORT,
455 reinterpret_cast<const char*>(&true_value),
456 sizeof(true_value));
457 if (rv < 0)
458 return MapSystemError(errno);
459 #endif
460 rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST,
461 reinterpret_cast<const char*>(&true_value),
462 sizeof(true_value));
463 if (rv < 0)
464 return MapSystemError(errno);
465 return OK;
466 }
467
433 int UDPSocketLibevent::DoBind(const IPEndPoint& address) { 468 int UDPSocketLibevent::DoBind(const IPEndPoint& address) {
434 SockaddrStorage storage; 469 SockaddrStorage storage;
435 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) 470 if (!address.ToSockAddr(storage.addr, &storage.addr_len))
436 return ERR_UNEXPECTED; 471 return ERR_UNEXPECTED;
437 int rv = bind(socket_, storage.addr, storage.addr_len); 472 int rv = bind(socket_, storage.addr, storage.addr_len);
438 return rv < 0 ? MapSystemError(errno) : rv; 473 return rv < 0 ? MapSystemError(errno) : rv;
439 } 474 }
440 475
441 int UDPSocketLibevent::RandomBind(const IPEndPoint& address) { 476 int UDPSocketLibevent::RandomBind(const IPEndPoint& address) {
442 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null()); 477 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null());
443 478
444 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s. 479 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s.
445 IPAddressNumber ip(address.address().size()); 480 IPAddressNumber ip(address.address().size());
446 481
447 for (int i = 0; i < kBindRetries; ++i) { 482 for (int i = 0; i < kBindRetries; ++i) {
448 int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd))); 483 int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd)));
449 if (rv == OK || rv != ERR_ADDRESS_IN_USE) 484 if (rv == OK || rv != ERR_ADDRESS_IN_USE)
450 return rv; 485 return rv;
451 } 486 }
452 return DoBind(IPEndPoint(ip, 0)); 487 return DoBind(IPEndPoint(ip, 0));
453 } 488 }
454 489
455 } // namespace net 490 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698