OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |