Chromium Code Reviews| 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 |