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 socket_options_(0), | |
| 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 rv = SetSocketOptions(); | |
| 256 if (rv < 0) | |
| 257 return rv; | |
| 254 rv = DoBind(address); | 258 rv = DoBind(address); |
| 255 if (rv < 0) | 259 if (rv < 0) |
| 256 return rv; | 260 return rv; |
| 257 local_address_.reset(); | 261 local_address_.reset(); |
| 258 return rv; | 262 return rv; |
| 259 } | 263 } |
| 260 | 264 |
| 261 bool UDPSocketLibevent::SetReceiveBufferSize(int32 size) { | 265 bool UDPSocketLibevent::SetReceiveBufferSize(int32 size) { |
| 262 DCHECK(CalledOnValidThread()); | 266 DCHECK(CalledOnValidThread()); |
| 263 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, | 267 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, |
| 264 reinterpret_cast<const char*>(&size), sizeof(size)); | 268 reinterpret_cast<const char*>(&size), sizeof(size)); |
| 265 DCHECK(!rv) << "Could not set socket receive buffer size: " << errno; | 269 DCHECK(!rv) << "Could not set socket receive buffer size: " << errno; |
| 266 return rv == 0; | 270 return rv == 0; |
| 267 } | 271 } |
| 268 | 272 |
| 269 bool UDPSocketLibevent::SetSendBufferSize(int32 size) { | 273 bool UDPSocketLibevent::SetSendBufferSize(int32 size) { |
| 270 DCHECK(CalledOnValidThread()); | 274 DCHECK(CalledOnValidThread()); |
| 271 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, | 275 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, |
| 272 reinterpret_cast<const char*>(&size), sizeof(size)); | 276 reinterpret_cast<const char*>(&size), sizeof(size)); |
| 273 DCHECK(!rv) << "Could not set socket send buffer size: " << errno; | 277 DCHECK(!rv) << "Could not set socket send buffer size: " << errno; |
| 274 return rv == 0; | 278 return rv == 0; |
| 275 } | 279 } |
| 276 | 280 |
| 281 void UDPSocketLibevent::AllowAddressReuse() { | |
| 282 DCHECK(CalledOnValidThread()); | |
| 283 DCHECK(!is_connected()); | |
| 284 | |
| 285 socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS; | |
| 286 } | |
| 287 | |
| 288 void UDPSocketLibevent::AllowBroadcast() { | |
| 289 DCHECK(CalledOnValidThread()); | |
| 290 DCHECK(!is_connected()); | |
| 291 | |
| 292 socket_options_ |= SOCKET_OPTION_BROADCAST; | |
| 293 } | |
| 294 | |
| 277 void UDPSocketLibevent::DoReadCallback(int rv) { | 295 void UDPSocketLibevent::DoReadCallback(int rv) { |
| 278 DCHECK_NE(rv, ERR_IO_PENDING); | 296 DCHECK_NE(rv, ERR_IO_PENDING); |
| 279 DCHECK(!read_callback_.is_null()); | 297 DCHECK(!read_callback_.is_null()); |
| 280 | 298 |
| 281 // since Run may result in Read being called, clear read_callback_ up front. | 299 // since Run may result in Read being called, clear read_callback_ up front. |
| 282 CompletionCallback c = read_callback_; | 300 CompletionCallback c = read_callback_; |
| 283 read_callback_.Reset(); | 301 read_callback_.Reset(); |
| 284 c.Run(rv); | 302 c.Run(rv); |
| 285 } | 303 } |
| 286 | 304 |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 423 0, | 441 0, |
| 424 addr, | 442 addr, |
| 425 storage.addr_len)); | 443 storage.addr_len)); |
| 426 if (result < 0) | 444 if (result < 0) |
| 427 result = MapSystemError(errno); | 445 result = MapSystemError(errno); |
| 428 if (result != ERR_IO_PENDING) | 446 if (result != ERR_IO_PENDING) |
| 429 LogWrite(result, buf->data(), address); | 447 LogWrite(result, buf->data(), address); |
| 430 return result; | 448 return result; |
| 431 } | 449 } |
| 432 | 450 |
| 451 int UDPSocketLibevent::SetSocketOptions() { | |
| 452 int true_value = 1; | |
| 453 if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) { | |
| 454 int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &true_value, | |
| 455 sizeof(true_value)); | |
| 456 if (rv < 0) | |
| 457 return MapSystemError(errno); | |
| 458 #if defined(SO_REUSEPORT) | |
| 459 rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEPORT, &true_value, | |
|
Sergey Ulanov
2012/09/12 19:13:10
Why do we really need this option here? It seems l
ygorshenin1
2012/09/13 18:29:16
Thanks, Sergey, you're right. SO_REUSEPORT is used
| |
| 460 sizeof(true_value)); | |
| 461 if (rv < 0) | |
| 462 return MapSystemError(errno); | |
| 463 #endif | |
| 464 } | |
| 465 if (socket_options_ & SOCKET_OPTION_BROADCAST) { | |
| 466 int rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &true_value, | |
| 467 sizeof(true_value)); | |
| 468 if (rv < 0) | |
| 469 return MapSystemError(errno); | |
| 470 } | |
| 471 return OK; | |
| 472 } | |
| 473 | |
| 433 int UDPSocketLibevent::DoBind(const IPEndPoint& address) { | 474 int UDPSocketLibevent::DoBind(const IPEndPoint& address) { |
| 434 SockaddrStorage storage; | 475 SockaddrStorage storage; |
| 435 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) | 476 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) |
| 436 return ERR_UNEXPECTED; | 477 return ERR_UNEXPECTED; |
| 437 int rv = bind(socket_, storage.addr, storage.addr_len); | 478 int rv = bind(socket_, storage.addr, storage.addr_len); |
| 438 return rv < 0 ? MapSystemError(errno) : rv; | 479 return rv < 0 ? MapSystemError(errno) : rv; |
| 439 } | 480 } |
| 440 | 481 |
| 441 int UDPSocketLibevent::RandomBind(const IPEndPoint& address) { | 482 int UDPSocketLibevent::RandomBind(const IPEndPoint& address) { |
| 442 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null()); | 483 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null()); |
| 443 | 484 |
| 444 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s. | 485 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s. |
| 445 IPAddressNumber ip(address.address().size()); | 486 IPAddressNumber ip(address.address().size()); |
| 446 | 487 |
| 447 for (int i = 0; i < kBindRetries; ++i) { | 488 for (int i = 0; i < kBindRetries; ++i) { |
| 448 int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd))); | 489 int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd))); |
| 449 if (rv == OK || rv != ERR_ADDRESS_IN_USE) | 490 if (rv == OK || rv != ERR_ADDRESS_IN_USE) |
| 450 return rv; | 491 return rv; |
| 451 } | 492 } |
| 452 return DoBind(IPEndPoint(ip, 0)); | 493 return DoBind(IPEndPoint(ip, 0)); |
| 453 } | 494 } |
| 454 | 495 |
| 455 } // namespace net | 496 } // namespace net |
| OLD | NEW |