| 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 <net/if.h> | 10 #include <net/if.h> |
| 11 #include <netinet/in.h> | 11 #include <netinet/in.h> |
| 12 #include <sys/ioctl.h> | 12 #include <sys/ioctl.h> |
| 13 #include <sys/socket.h> | 13 #include <sys/socket.h> |
| 14 | 14 |
| 15 #include "base/callback.h" | 15 #include "base/callback.h" |
| 16 #include "base/logging.h" | 16 #include "base/logging.h" |
| 17 #include "base/message_loop/message_loop.h" | 17 #include "base/message_loop/message_loop.h" |
| 18 #include "base/metrics/sparse_histogram.h" | 18 #include "base/metrics/sparse_histogram.h" |
| 19 #include "base/metrics/stats_counters.h" | 19 #include "base/metrics/stats_counters.h" |
| 20 #include "base/posix/eintr_wrapper.h" | 20 #include "base/posix/eintr_wrapper.h" |
| 21 #include "base/rand_util.h" | 21 #include "base/rand_util.h" |
| 22 #include "net/base/io_buffer.h" | 22 #include "net/base/io_buffer.h" |
| 23 #include "net/base/ip_endpoint.h" | 23 #include "net/base/ip_endpoint.h" |
| 24 #include "net/base/net_errors.h" | 24 #include "net/base/net_errors.h" |
| 25 #include "net/base/net_log.h" | 25 #include "net/base/net_log.h" |
| 26 #include "net/base/net_util.h" | 26 #include "net/base/net_util.h" |
| 27 #include "net/socket/socket_descriptor.h" | 27 #include "net/socket/socket_descriptor.h" |
| 28 #include "net/udp/udp_net_log_parameters.h" | 28 #include "net/udp/udp_net_log_parameters.h" |
| 29 | 29 |
| 30 | |
| 31 namespace net { | 30 namespace net { |
| 32 | 31 |
| 33 namespace { | 32 namespace { |
| 34 | 33 |
| 35 const int kBindRetries = 10; | 34 const int kBindRetries = 10; |
| 36 const int kPortStart = 1024; | 35 const int kPortStart = 1024; |
| 37 const int kPortEnd = 65535; | 36 const int kPortEnd = 65535; |
| 38 | 37 |
| 39 #if defined(OS_MACOSX) | 38 #if defined(OS_MACOSX) |
| 40 | 39 |
| 41 // Returns IPv4 address in network order. | 40 // Returns IPv4 address in network order. |
| 42 int GetIPv4AddressFromIndex(int socket, uint32 index, uint32* address){ | 41 int GetIPv4AddressFromIndex(int socket, uint32 index, uint32* address) { |
| 43 if (!index) { | 42 if (!index) { |
| 44 *address = htonl(INADDR_ANY); | 43 *address = htonl(INADDR_ANY); |
| 45 return OK; | 44 return OK; |
| 46 } | 45 } |
| 47 ifreq ifr; | 46 ifreq ifr; |
| 48 ifr.ifr_addr.sa_family = AF_INET; | 47 ifr.ifr_addr.sa_family = AF_INET; |
| 49 if (!if_indextoname(index, ifr.ifr_name)) | 48 if (!if_indextoname(index, ifr.ifr_name)) |
| 50 return MapSystemError(errno); | 49 return MapSystemError(errno); |
| 51 int rv = ioctl(socket, SIOCGIFADDR, &ifr); | 50 int rv = ioctl(socket, SIOCGIFADDR, &ifr); |
| 52 if (rv == -1) | 51 if (rv == -1) |
| 53 return MapSystemError(errno); | 52 return MapSystemError(errno); |
| 54 *address = reinterpret_cast<sockaddr_in*>(&ifr.ifr_addr)->sin_addr.s_addr; | 53 *address = reinterpret_cast<sockaddr_in*>(&ifr.ifr_addr)->sin_addr.s_addr; |
| 55 return OK; | 54 return OK; |
| 56 } | 55 } |
| 57 | 56 |
| 58 #endif // OS_MACOSX | 57 #endif // OS_MACOSX |
| 59 | 58 |
| 60 } // namespace | 59 } // namespace |
| 61 | 60 |
| 62 UDPSocketLibevent::UDPSocketLibevent( | 61 UDPSocketLibevent::UDPSocketLibevent(DatagramSocket::BindType bind_type, |
| 63 DatagramSocket::BindType bind_type, | 62 const RandIntCallback& rand_int_cb, |
| 64 const RandIntCallback& rand_int_cb, | 63 net::NetLog* net_log, |
| 65 net::NetLog* net_log, | 64 const net::NetLog::Source& source) |
| 66 const net::NetLog::Source& source) | 65 : socket_(kInvalidSocket), |
| 67 : socket_(kInvalidSocket), | 66 addr_family_(0), |
| 68 addr_family_(0), | 67 socket_options_(SOCKET_OPTION_MULTICAST_LOOP), |
| 69 socket_options_(SOCKET_OPTION_MULTICAST_LOOP), | 68 multicast_interface_(0), |
| 70 multicast_interface_(0), | 69 multicast_time_to_live_(1), |
| 71 multicast_time_to_live_(1), | 70 bind_type_(bind_type), |
| 72 bind_type_(bind_type), | 71 rand_int_cb_(rand_int_cb), |
| 73 rand_int_cb_(rand_int_cb), | 72 read_watcher_(this), |
| 74 read_watcher_(this), | 73 write_watcher_(this), |
| 75 write_watcher_(this), | 74 read_buf_len_(0), |
| 76 read_buf_len_(0), | 75 recv_from_address_(NULL), |
| 77 recv_from_address_(NULL), | 76 write_buf_len_(0), |
| 78 write_buf_len_(0), | 77 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) { |
| 79 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) { | |
| 80 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, | 78 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, |
| 81 source.ToEventParametersCallback()); | 79 source.ToEventParametersCallback()); |
| 82 if (bind_type == DatagramSocket::RANDOM_BIND) | 80 if (bind_type == DatagramSocket::RANDOM_BIND) |
| 83 DCHECK(!rand_int_cb.is_null()); | 81 DCHECK(!rand_int_cb.is_null()); |
| 84 } | 82 } |
| 85 | 83 |
| 86 UDPSocketLibevent::~UDPSocketLibevent() { | 84 UDPSocketLibevent::~UDPSocketLibevent() { |
| 87 Close(); | 85 Close(); |
| 88 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); | 86 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); |
| 89 } | 87 } |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 DCHECK(read_callback_.is_null()); | 171 DCHECK(read_callback_.is_null()); |
| 174 DCHECK(!recv_from_address_); | 172 DCHECK(!recv_from_address_); |
| 175 DCHECK(!callback.is_null()); // Synchronous operation not supported | 173 DCHECK(!callback.is_null()); // Synchronous operation not supported |
| 176 DCHECK_GT(buf_len, 0); | 174 DCHECK_GT(buf_len, 0); |
| 177 | 175 |
| 178 int nread = InternalRecvFrom(buf, buf_len, address); | 176 int nread = InternalRecvFrom(buf, buf_len, address); |
| 179 if (nread != ERR_IO_PENDING) | 177 if (nread != ERR_IO_PENDING) |
| 180 return nread; | 178 return nread; |
| 181 | 179 |
| 182 if (!base::MessageLoopForIO::current()->WatchFileDescriptor( | 180 if (!base::MessageLoopForIO::current()->WatchFileDescriptor( |
| 183 socket_, true, base::MessageLoopForIO::WATCH_READ, | 181 socket_, |
| 184 &read_socket_watcher_, &read_watcher_)) { | 182 true, |
| 183 base::MessageLoopForIO::WATCH_READ, |
| 184 &read_socket_watcher_, |
| 185 &read_watcher_)) { |
| 185 PLOG(ERROR) << "WatchFileDescriptor failed on read"; | 186 PLOG(ERROR) << "WatchFileDescriptor failed on read"; |
| 186 int result = MapSystemError(errno); | 187 int result = MapSystemError(errno); |
| 187 LogRead(result, NULL, 0, NULL); | 188 LogRead(result, NULL, 0, NULL); |
| 188 return result; | 189 return result; |
| 189 } | 190 } |
| 190 | 191 |
| 191 read_buf_ = buf; | 192 read_buf_ = buf; |
| 192 read_buf_len_ = buf_len; | 193 read_buf_len_ = buf_len; |
| 193 recv_from_address_ = address; | 194 recv_from_address_ = address; |
| 194 read_callback_ = callback; | 195 read_callback_ = callback; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 216 DCHECK_NE(kInvalidSocket, socket_); | 217 DCHECK_NE(kInvalidSocket, socket_); |
| 217 DCHECK(write_callback_.is_null()); | 218 DCHECK(write_callback_.is_null()); |
| 218 DCHECK(!callback.is_null()); // Synchronous operation not supported | 219 DCHECK(!callback.is_null()); // Synchronous operation not supported |
| 219 DCHECK_GT(buf_len, 0); | 220 DCHECK_GT(buf_len, 0); |
| 220 | 221 |
| 221 int result = InternalSendTo(buf, buf_len, address); | 222 int result = InternalSendTo(buf, buf_len, address); |
| 222 if (result != ERR_IO_PENDING) | 223 if (result != ERR_IO_PENDING) |
| 223 return result; | 224 return result; |
| 224 | 225 |
| 225 if (!base::MessageLoopForIO::current()->WatchFileDescriptor( | 226 if (!base::MessageLoopForIO::current()->WatchFileDescriptor( |
| 226 socket_, true, base::MessageLoopForIO::WATCH_WRITE, | 227 socket_, |
| 227 &write_socket_watcher_, &write_watcher_)) { | 228 true, |
| 229 base::MessageLoopForIO::WATCH_WRITE, |
| 230 &write_socket_watcher_, |
| 231 &write_watcher_)) { |
| 228 DVLOG(1) << "WatchFileDescriptor failed on write, errno " << errno; | 232 DVLOG(1) << "WatchFileDescriptor failed on write, errno " << errno; |
| 229 int result = MapSystemError(errno); | 233 int result = MapSystemError(errno); |
| 230 LogWrite(result, NULL, NULL); | 234 LogWrite(result, NULL, NULL); |
| 231 return result; | 235 return result; |
| 232 } | 236 } |
| 233 | 237 |
| 234 write_buf_ = buf; | 238 write_buf_ = buf; |
| 235 write_buf_len_ = buf_len; | 239 write_buf_len_ = buf_len; |
| 236 DCHECK(!send_to_address_.get()); | 240 DCHECK(!send_to_address_.get()); |
| 237 if (address) { | 241 if (address) { |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 if (rv < 0) { | 314 if (rv < 0) { |
| 311 Close(); | 315 Close(); |
| 312 return rv; | 316 return rv; |
| 313 } | 317 } |
| 314 local_address_.reset(); | 318 local_address_.reset(); |
| 315 return rv; | 319 return rv; |
| 316 } | 320 } |
| 317 | 321 |
| 318 int UDPSocketLibevent::SetReceiveBufferSize(int32 size) { | 322 int UDPSocketLibevent::SetReceiveBufferSize(int32 size) { |
| 319 DCHECK(CalledOnValidThread()); | 323 DCHECK(CalledOnValidThread()); |
| 320 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, | 324 int rv = setsockopt(socket_, |
| 321 reinterpret_cast<const char*>(&size), sizeof(size)); | 325 SOL_SOCKET, |
| 326 SO_RCVBUF, |
| 327 reinterpret_cast<const char*>(&size), |
| 328 sizeof(size)); |
| 322 int last_error = errno; | 329 int last_error = errno; |
| 323 DCHECK(!rv) << "Could not set socket receive buffer size: " << last_error; | 330 DCHECK(!rv) << "Could not set socket receive buffer size: " << last_error; |
| 324 return rv == 0 ? OK : MapSystemError(last_error); | 331 return rv == 0 ? OK : MapSystemError(last_error); |
| 325 } | 332 } |
| 326 | 333 |
| 327 int UDPSocketLibevent::SetSendBufferSize(int32 size) { | 334 int UDPSocketLibevent::SetSendBufferSize(int32 size) { |
| 328 DCHECK(CalledOnValidThread()); | 335 DCHECK(CalledOnValidThread()); |
| 329 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, | 336 int rv = setsockopt(socket_, |
| 330 reinterpret_cast<const char*>(&size), sizeof(size)); | 337 SOL_SOCKET, |
| 338 SO_SNDBUF, |
| 339 reinterpret_cast<const char*>(&size), |
| 340 sizeof(size)); |
| 331 int last_error = errno; | 341 int last_error = errno; |
| 332 DCHECK(!rv) << "Could not set socket send buffer size: " << last_error; | 342 DCHECK(!rv) << "Could not set socket send buffer size: " << last_error; |
| 333 return rv == 0 ? OK : MapSystemError(last_error); | 343 return rv == 0 ? OK : MapSystemError(last_error); |
| 334 } | 344 } |
| 335 | 345 |
| 336 void UDPSocketLibevent::AllowAddressReuse() { | 346 void UDPSocketLibevent::AllowAddressReuse() { |
| 337 DCHECK(CalledOnValidThread()); | 347 DCHECK(CalledOnValidThread()); |
| 338 DCHECK(!is_connected()); | 348 DCHECK(!is_connected()); |
| 339 | 349 |
| 340 socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS; | 350 socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR, result); | 408 net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR, result); |
| 399 return; | 409 return; |
| 400 } | 410 } |
| 401 | 411 |
| 402 if (net_log_.IsLogging()) { | 412 if (net_log_.IsLogging()) { |
| 403 DCHECK(addr_len > 0); | 413 DCHECK(addr_len > 0); |
| 404 DCHECK(addr); | 414 DCHECK(addr); |
| 405 | 415 |
| 406 IPEndPoint address; | 416 IPEndPoint address; |
| 407 bool is_address_valid = address.FromSockAddr(addr, addr_len); | 417 bool is_address_valid = address.FromSockAddr(addr, addr_len); |
| 408 net_log_.AddEvent( | 418 net_log_.AddEvent(NetLog::TYPE_UDP_BYTES_RECEIVED, |
| 409 NetLog::TYPE_UDP_BYTES_RECEIVED, | 419 CreateNetLogUDPDataTranferCallback( |
| 410 CreateNetLogUDPDataTranferCallback( | 420 result, bytes, is_address_valid ? &address : NULL)); |
| 411 result, bytes, | |
| 412 is_address_valid ? &address : NULL)); | |
| 413 } | 421 } |
| 414 | 422 |
| 415 base::StatsCounter read_bytes("udp.read_bytes"); | 423 base::StatsCounter read_bytes("udp.read_bytes"); |
| 416 read_bytes.Add(result); | 424 read_bytes.Add(result); |
| 417 } | 425 } |
| 418 | 426 |
| 419 int UDPSocketLibevent::CreateSocket(int addr_family) { | 427 int UDPSocketLibevent::CreateSocket(int addr_family) { |
| 420 addr_family_ = addr_family; | 428 addr_family_ = addr_family; |
| 421 socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, 0); | 429 socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, 0); |
| 422 if (socket_ == kInvalidSocket) | 430 if (socket_ == kInvalidSocket) |
| (...skipping 30 matching lines...) Expand all Loading... |
| 453 if (net_log_.IsLogging()) { | 461 if (net_log_.IsLogging()) { |
| 454 net_log_.AddEvent( | 462 net_log_.AddEvent( |
| 455 NetLog::TYPE_UDP_BYTES_SENT, | 463 NetLog::TYPE_UDP_BYTES_SENT, |
| 456 CreateNetLogUDPDataTranferCallback(result, bytes, address)); | 464 CreateNetLogUDPDataTranferCallback(result, bytes, address)); |
| 457 } | 465 } |
| 458 | 466 |
| 459 base::StatsCounter write_bytes("udp.write_bytes"); | 467 base::StatsCounter write_bytes("udp.write_bytes"); |
| 460 write_bytes.Add(result); | 468 write_bytes.Add(result); |
| 461 } | 469 } |
| 462 | 470 |
| 463 int UDPSocketLibevent::InternalRecvFrom(IOBuffer* buf, int buf_len, | 471 int UDPSocketLibevent::InternalRecvFrom(IOBuffer* buf, |
| 472 int buf_len, |
| 464 IPEndPoint* address) { | 473 IPEndPoint* address) { |
| 465 int bytes_transferred; | 474 int bytes_transferred; |
| 466 int flags = 0; | 475 int flags = 0; |
| 467 | 476 |
| 468 SockaddrStorage storage; | 477 SockaddrStorage storage; |
| 469 | 478 |
| 470 bytes_transferred = | 479 bytes_transferred = HANDLE_EINTR(recvfrom( |
| 471 HANDLE_EINTR(recvfrom(socket_, | 480 socket_, buf->data(), buf_len, flags, storage.addr, &storage.addr_len)); |
| 472 buf->data(), | |
| 473 buf_len, | |
| 474 flags, | |
| 475 storage.addr, | |
| 476 &storage.addr_len)); | |
| 477 int result; | 481 int result; |
| 478 if (bytes_transferred >= 0) { | 482 if (bytes_transferred >= 0) { |
| 479 result = bytes_transferred; | 483 result = bytes_transferred; |
| 480 if (address && !address->FromSockAddr(storage.addr, storage.addr_len)) | 484 if (address && !address->FromSockAddr(storage.addr, storage.addr_len)) |
| 481 result = ERR_ADDRESS_INVALID; | 485 result = ERR_ADDRESS_INVALID; |
| 482 } else { | 486 } else { |
| 483 result = MapSystemError(errno); | 487 result = MapSystemError(errno); |
| 484 } | 488 } |
| 485 if (result != ERR_IO_PENDING) | 489 if (result != ERR_IO_PENDING) |
| 486 LogRead(result, buf->data(), storage.addr_len, storage.addr); | 490 LogRead(result, buf->data(), storage.addr_len, storage.addr); |
| 487 return result; | 491 return result; |
| 488 } | 492 } |
| 489 | 493 |
| 490 int UDPSocketLibevent::InternalSendTo(IOBuffer* buf, int buf_len, | 494 int UDPSocketLibevent::InternalSendTo(IOBuffer* buf, |
| 495 int buf_len, |
| 491 const IPEndPoint* address) { | 496 const IPEndPoint* address) { |
| 492 SockaddrStorage storage; | 497 SockaddrStorage storage; |
| 493 struct sockaddr* addr = storage.addr; | 498 struct sockaddr* addr = storage.addr; |
| 494 if (!address) { | 499 if (!address) { |
| 495 addr = NULL; | 500 addr = NULL; |
| 496 storage.addr_len = 0; | 501 storage.addr_len = 0; |
| 497 } else { | 502 } else { |
| 498 if (!address->ToSockAddr(storage.addr, &storage.addr_len)) { | 503 if (!address->ToSockAddr(storage.addr, &storage.addr_len)) { |
| 499 int result = ERR_ADDRESS_INVALID; | 504 int result = ERR_ADDRESS_INVALID; |
| 500 LogWrite(result, NULL, NULL); | 505 LogWrite(result, NULL, NULL); |
| 501 return result; | 506 return result; |
| 502 } | 507 } |
| 503 } | 508 } |
| 504 | 509 |
| 505 int result = HANDLE_EINTR(sendto(socket_, | 510 int result = HANDLE_EINTR( |
| 506 buf->data(), | 511 sendto(socket_, buf->data(), buf_len, 0, addr, storage.addr_len)); |
| 507 buf_len, | |
| 508 0, | |
| 509 addr, | |
| 510 storage.addr_len)); | |
| 511 if (result < 0) | 512 if (result < 0) |
| 512 result = MapSystemError(errno); | 513 result = MapSystemError(errno); |
| 513 if (result != ERR_IO_PENDING) | 514 if (result != ERR_IO_PENDING) |
| 514 LogWrite(result, buf->data(), address); | 515 LogWrite(result, buf->data(), address); |
| 515 return result; | 516 return result; |
| 516 } | 517 } |
| 517 | 518 |
| 518 int UDPSocketLibevent::SetSocketOptions() { | 519 int UDPSocketLibevent::SetSocketOptions() { |
| 519 int true_value = 1; | 520 int true_value = 1; |
| 520 if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) { | 521 if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) { |
| 521 int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &true_value, | 522 int rv = setsockopt( |
| 522 sizeof(true_value)); | 523 socket_, SOL_SOCKET, SO_REUSEADDR, &true_value, sizeof(true_value)); |
| 523 if (rv < 0) | 524 if (rv < 0) |
| 524 return MapSystemError(errno); | 525 return MapSystemError(errno); |
| 525 } | 526 } |
| 526 if (socket_options_ & SOCKET_OPTION_BROADCAST) { | 527 if (socket_options_ & SOCKET_OPTION_BROADCAST) { |
| 527 int rv; | 528 int rv; |
| 528 #if defined(OS_MACOSX) | 529 #if defined(OS_MACOSX) |
| 529 // SO_REUSEPORT on OSX permits multiple processes to each receive | 530 // SO_REUSEPORT on OSX permits multiple processes to each receive |
| 530 // UDP multicast or broadcast datagrams destined for the bound | 531 // UDP multicast or broadcast datagrams destined for the bound |
| 531 // port. | 532 // port. |
| 532 rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEPORT, &true_value, | 533 rv = setsockopt( |
| 533 sizeof(true_value)); | 534 socket_, SOL_SOCKET, SO_REUSEPORT, &true_value, sizeof(true_value)); |
| 534 #else | 535 #else |
| 535 rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &true_value, | 536 rv = setsockopt( |
| 536 sizeof(true_value)); | 537 socket_, SOL_SOCKET, SO_BROADCAST, &true_value, sizeof(true_value)); |
| 537 #endif // defined(OS_MACOSX) | 538 #endif // defined(OS_MACOSX) |
| 538 if (rv < 0) | 539 if (rv < 0) |
| 539 return MapSystemError(errno); | 540 return MapSystemError(errno); |
| 540 } | 541 } |
| 541 | 542 |
| 542 if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) { | 543 if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) { |
| 543 int rv; | 544 int rv; |
| 544 if (addr_family_ == AF_INET) { | 545 if (addr_family_ == AF_INET) { |
| 545 u_char loop = 0; | 546 u_char loop = 0; |
| 546 rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_LOOP, | 547 rv = setsockopt( |
| 547 &loop, sizeof(loop)); | 548 socket_, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)); |
| 548 } else { | 549 } else { |
| 549 u_int loop = 0; | 550 u_int loop = 0; |
| 550 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, | 551 rv = setsockopt( |
| 551 &loop, sizeof(loop)); | 552 socket_, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &loop, sizeof(loop)); |
| 552 } | 553 } |
| 553 if (rv < 0) | 554 if (rv < 0) |
| 554 return MapSystemError(errno); | 555 return MapSystemError(errno); |
| 555 } | 556 } |
| 556 if (multicast_time_to_live_ != IP_DEFAULT_MULTICAST_TTL) { | 557 if (multicast_time_to_live_ != IP_DEFAULT_MULTICAST_TTL) { |
| 557 int rv; | 558 int rv; |
| 558 if (addr_family_ == AF_INET) { | 559 if (addr_family_ == AF_INET) { |
| 559 u_char ttl = multicast_time_to_live_; | 560 u_char ttl = multicast_time_to_live_; |
| 560 rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_TTL, | 561 rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)); |
| 561 &ttl, sizeof(ttl)); | |
| 562 } else { | 562 } else { |
| 563 // Signed integer. -1 to use route default. | 563 // Signed integer. -1 to use route default. |
| 564 int ttl = multicast_time_to_live_; | 564 int ttl = multicast_time_to_live_; |
| 565 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, | 565 rv = setsockopt( |
| 566 &ttl, sizeof(ttl)); | 566 socket_, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)); |
| 567 } | 567 } |
| 568 if (rv < 0) | 568 if (rv < 0) |
| 569 return MapSystemError(errno); | 569 return MapSystemError(errno); |
| 570 } | 570 } |
| 571 if (multicast_interface_ != 0) { | 571 if (multicast_interface_ != 0) { |
| 572 switch (addr_family_) { | 572 switch (addr_family_) { |
| 573 case AF_INET: { | 573 case AF_INET: { |
| 574 #if !defined(OS_MACOSX) | 574 #if !defined(OS_MACOSX) |
| 575 ip_mreqn mreq; | 575 ip_mreqn mreq; |
| 576 mreq.imr_ifindex = multicast_interface_; | 576 mreq.imr_ifindex = multicast_interface_; |
| 577 mreq.imr_address.s_addr = htonl(INADDR_ANY); | 577 mreq.imr_address.s_addr = htonl(INADDR_ANY); |
| 578 #else | 578 #else |
| 579 ip_mreq mreq; | 579 ip_mreq mreq; |
| 580 int error = GetIPv4AddressFromIndex(socket_, multicast_interface_, | 580 int error = GetIPv4AddressFromIndex( |
| 581 &mreq.imr_interface.s_addr); | 581 socket_, multicast_interface_, &mreq.imr_interface.s_addr); |
| 582 if (error != OK) | 582 if (error != OK) |
| 583 return error; | 583 return error; |
| 584 #endif | 584 #endif |
| 585 int rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_IF, | 585 int rv = setsockopt(socket_, |
| 586 reinterpret_cast<const char*>(&mreq), sizeof(mreq)); | 586 IPPROTO_IP, |
| 587 IP_MULTICAST_IF, |
| 588 reinterpret_cast<const char*>(&mreq), |
| 589 sizeof(mreq)); |
| 587 if (rv) | 590 if (rv) |
| 588 return MapSystemError(errno); | 591 return MapSystemError(errno); |
| 589 break; | 592 break; |
| 590 } | 593 } |
| 591 case AF_INET6: { | 594 case AF_INET6: { |
| 592 uint32 interface_index = multicast_interface_; | 595 uint32 interface_index = multicast_interface_; |
| 593 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_IF, | 596 int rv = setsockopt(socket_, |
| 597 IPPROTO_IPV6, |
| 598 IPV6_MULTICAST_IF, |
| 594 reinterpret_cast<const char*>(&interface_index), | 599 reinterpret_cast<const char*>(&interface_index), |
| 595 sizeof(interface_index)); | 600 sizeof(interface_index)); |
| 596 if (rv) | 601 if (rv) |
| 597 return MapSystemError(errno); | 602 return MapSystemError(errno); |
| 598 break; | 603 break; |
| 599 } | 604 } |
| 600 default: | 605 default: |
| 601 NOTREACHED() << "Invalid address family"; | 606 NOTREACHED() << "Invalid address family"; |
| 602 return ERR_ADDRESS_INVALID; | 607 return ERR_ADDRESS_INVALID; |
| 603 } | 608 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 621 if (last_error == EADDRNOTAVAIL) | 626 if (last_error == EADDRNOTAVAIL) |
| 622 return ERR_ADDRESS_IN_USE; | 627 return ERR_ADDRESS_IN_USE; |
| 623 #endif | 628 #endif |
| 624 return MapSystemError(last_error); | 629 return MapSystemError(last_error); |
| 625 } | 630 } |
| 626 | 631 |
| 627 int UDPSocketLibevent::RandomBind(const IPAddressNumber& address) { | 632 int UDPSocketLibevent::RandomBind(const IPAddressNumber& address) { |
| 628 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null()); | 633 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null()); |
| 629 | 634 |
| 630 for (int i = 0; i < kBindRetries; ++i) { | 635 for (int i = 0; i < kBindRetries; ++i) { |
| 631 int rv = DoBind(IPEndPoint(address, | 636 int rv = |
| 632 rand_int_cb_.Run(kPortStart, kPortEnd))); | 637 DoBind(IPEndPoint(address, rand_int_cb_.Run(kPortStart, kPortEnd))); |
| 633 if (rv == OK || rv != ERR_ADDRESS_IN_USE) | 638 if (rv == OK || rv != ERR_ADDRESS_IN_USE) |
| 634 return rv; | 639 return rv; |
| 635 } | 640 } |
| 636 return DoBind(IPEndPoint(address, 0)); | 641 return DoBind(IPEndPoint(address, 0)); |
| 637 } | 642 } |
| 638 | 643 |
| 639 int UDPSocketLibevent::JoinGroup(const IPAddressNumber& group_address) const { | 644 int UDPSocketLibevent::JoinGroup(const IPAddressNumber& group_address) const { |
| 640 DCHECK(CalledOnValidThread()); | 645 DCHECK(CalledOnValidThread()); |
| 641 if (!is_connected()) | 646 if (!is_connected()) |
| 642 return ERR_SOCKET_NOT_CONNECTED; | 647 return ERR_SOCKET_NOT_CONNECTED; |
| 643 | 648 |
| 644 switch (group_address.size()) { | 649 switch (group_address.size()) { |
| 645 case kIPv4AddressSize: { | 650 case kIPv4AddressSize: { |
| 646 if (addr_family_ != AF_INET) | 651 if (addr_family_ != AF_INET) |
| 647 return ERR_ADDRESS_INVALID; | 652 return ERR_ADDRESS_INVALID; |
| 648 | 653 |
| 649 #if !defined(OS_MACOSX) | 654 #if !defined(OS_MACOSX) |
| 650 ip_mreqn mreq; | 655 ip_mreqn mreq; |
| 651 mreq.imr_ifindex = multicast_interface_; | 656 mreq.imr_ifindex = multicast_interface_; |
| 652 mreq.imr_address.s_addr = htonl(INADDR_ANY); | 657 mreq.imr_address.s_addr = htonl(INADDR_ANY); |
| 653 #else | 658 #else |
| 654 ip_mreq mreq; | 659 ip_mreq mreq; |
| 655 int error = GetIPv4AddressFromIndex(socket_, multicast_interface_, | 660 int error = GetIPv4AddressFromIndex( |
| 656 &mreq.imr_interface.s_addr); | 661 socket_, multicast_interface_, &mreq.imr_interface.s_addr); |
| 657 if (error != OK) | 662 if (error != OK) |
| 658 return error; | 663 return error; |
| 659 #endif | 664 #endif |
| 660 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize); | 665 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize); |
| 661 int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP, | 666 int rv = setsockopt( |
| 662 &mreq, sizeof(mreq)); | 667 socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); |
| 663 if (rv < 0) | 668 if (rv < 0) |
| 664 return MapSystemError(errno); | 669 return MapSystemError(errno); |
| 665 return OK; | 670 return OK; |
| 666 } | 671 } |
| 667 case kIPv6AddressSize: { | 672 case kIPv6AddressSize: { |
| 668 if (addr_family_ != AF_INET6) | 673 if (addr_family_ != AF_INET6) |
| 669 return ERR_ADDRESS_INVALID; | 674 return ERR_ADDRESS_INVALID; |
| 670 ipv6_mreq mreq; | 675 ipv6_mreq mreq; |
| 671 mreq.ipv6mr_interface = multicast_interface_; | 676 mreq.ipv6mr_interface = multicast_interface_; |
| 672 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize); | 677 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize); |
| 673 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_JOIN_GROUP, | 678 int rv = setsockopt( |
| 674 &mreq, sizeof(mreq)); | 679 socket_, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)); |
| 675 if (rv < 0) | 680 if (rv < 0) |
| 676 return MapSystemError(errno); | 681 return MapSystemError(errno); |
| 677 return OK; | 682 return OK; |
| 678 } | 683 } |
| 679 default: | 684 default: |
| 680 NOTREACHED() << "Invalid address family"; | 685 NOTREACHED() << "Invalid address family"; |
| 681 return ERR_ADDRESS_INVALID; | 686 return ERR_ADDRESS_INVALID; |
| 682 } | 687 } |
| 683 } | 688 } |
| 684 | 689 |
| 685 int UDPSocketLibevent::LeaveGroup(const IPAddressNumber& group_address) const { | 690 int UDPSocketLibevent::LeaveGroup(const IPAddressNumber& group_address) const { |
| 686 DCHECK(CalledOnValidThread()); | 691 DCHECK(CalledOnValidThread()); |
| 687 | 692 |
| 688 if (!is_connected()) | 693 if (!is_connected()) |
| 689 return ERR_SOCKET_NOT_CONNECTED; | 694 return ERR_SOCKET_NOT_CONNECTED; |
| 690 | 695 |
| 691 switch (group_address.size()) { | 696 switch (group_address.size()) { |
| 692 case kIPv4AddressSize: { | 697 case kIPv4AddressSize: { |
| 693 if (addr_family_ != AF_INET) | 698 if (addr_family_ != AF_INET) |
| 694 return ERR_ADDRESS_INVALID; | 699 return ERR_ADDRESS_INVALID; |
| 695 ip_mreq mreq; | 700 ip_mreq mreq; |
| 696 mreq.imr_interface.s_addr = INADDR_ANY; | 701 mreq.imr_interface.s_addr = INADDR_ANY; |
| 697 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize); | 702 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize); |
| 698 int rv = setsockopt(socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP, | 703 int rv = setsockopt( |
| 699 &mreq, sizeof(mreq)); | 704 socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)); |
| 700 if (rv < 0) | 705 if (rv < 0) |
| 701 return MapSystemError(errno); | 706 return MapSystemError(errno); |
| 702 return OK; | 707 return OK; |
| 703 } | 708 } |
| 704 case kIPv6AddressSize: { | 709 case kIPv6AddressSize: { |
| 705 if (addr_family_ != AF_INET6) | 710 if (addr_family_ != AF_INET6) |
| 706 return ERR_ADDRESS_INVALID; | 711 return ERR_ADDRESS_INVALID; |
| 707 ipv6_mreq mreq; | 712 ipv6_mreq mreq; |
| 708 mreq.ipv6mr_interface = 0; // 0 indicates default multicast interface. | 713 mreq.ipv6mr_interface = 0; // 0 indicates default multicast interface. |
| 709 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize); | 714 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize); |
| 710 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_LEAVE_GROUP, | 715 int rv = setsockopt( |
| 711 &mreq, sizeof(mreq)); | 716 socket_, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &mreq, sizeof(mreq)); |
| 712 if (rv < 0) | 717 if (rv < 0) |
| 713 return MapSystemError(errno); | 718 return MapSystemError(errno); |
| 714 return OK; | 719 return OK; |
| 715 } | 720 } |
| 716 default: | 721 default: |
| 717 NOTREACHED() << "Invalid address family"; | 722 NOTREACHED() << "Invalid address family"; |
| 718 return ERR_ADDRESS_INVALID; | 723 return ERR_ADDRESS_INVALID; |
| 719 } | 724 } |
| 720 } | 725 } |
| 721 | 726 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 750 return OK; | 755 return OK; |
| 751 } | 756 } |
| 752 | 757 |
| 753 int UDPSocketLibevent::SetDiffServCodePoint(DiffServCodePoint dscp) { | 758 int UDPSocketLibevent::SetDiffServCodePoint(DiffServCodePoint dscp) { |
| 754 if (dscp == DSCP_NO_CHANGE) { | 759 if (dscp == DSCP_NO_CHANGE) { |
| 755 return OK; | 760 return OK; |
| 756 } | 761 } |
| 757 int rv; | 762 int rv; |
| 758 int dscp_and_ecn = dscp << 2; | 763 int dscp_and_ecn = dscp << 2; |
| 759 if (addr_family_ == AF_INET) { | 764 if (addr_family_ == AF_INET) { |
| 760 rv = setsockopt(socket_, IPPROTO_IP, IP_TOS, | 765 rv = setsockopt( |
| 761 &dscp_and_ecn, sizeof(dscp_and_ecn)); | 766 socket_, IPPROTO_IP, IP_TOS, &dscp_and_ecn, sizeof(dscp_and_ecn)); |
| 762 } else { | 767 } else { |
| 763 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_TCLASS, | 768 rv = setsockopt(socket_, |
| 764 &dscp_and_ecn, sizeof(dscp_and_ecn)); | 769 IPPROTO_IPV6, |
| 770 IPV6_TCLASS, |
| 771 &dscp_and_ecn, |
| 772 sizeof(dscp_and_ecn)); |
| 765 } | 773 } |
| 766 if (rv < 0) | 774 if (rv < 0) |
| 767 return MapSystemError(errno); | 775 return MapSystemError(errno); |
| 768 | 776 |
| 769 return OK; | 777 return OK; |
| 770 } | 778 } |
| 771 | 779 |
| 772 void UDPSocketLibevent::DetachFromThread() { | 780 void UDPSocketLibevent::DetachFromThread() { |
| 773 base::NonThreadSafe::DetachFromThread(); | 781 base::NonThreadSafe::DetachFromThread(); |
| 774 } | 782 } |
| 775 | 783 |
| 776 } // namespace net | 784 } // namespace net |
| OLD | NEW |