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 |