| // Copyright 2016 The Chromium Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "net/socket/socket_options.h" | |
| #include <cerrno> | |
| #include "build/build_config.h" | |
| #include "net/base/net_errors.h" | |
| #if BUILDFLAG(IS_WIN) | |
| #include <winsock2.h> | |
| #include <ws2tcpip.h> | |
| #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) | |
| #include <netinet/in.h> | |
| #include <netinet/tcp.h> | |
| #include <sys/socket.h> | |
| #endif | |
| namespace net { | |
| int SetTCPNoDelay(SocketDescriptor fd, bool no_delay) { | |
| #if BUILDFLAG(IS_WIN) | |
| BOOL on = no_delay ? TRUE : FALSE; | |
| #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) | |
| int on = no_delay ? 1 : 0; | |
| #endif | |
| int rv = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, | |
| reinterpret_cast<const char*>(&on), sizeof(on)); | |
| return rv == -1 ? MapSystemError(errno) : OK; | |
| } | |
| int SetReuseAddr(SocketDescriptor fd, bool reuse) { | |
| // SO_REUSEADDR is useful for server sockets to bind to a recently unbound | |
| // port. When a socket is closed, the end point changes its state to TIME_WAIT | |
| // and wait for 2 MSL (maximum segment lifetime) to ensure the remote peer | |
| // acknowledges its closure. For server sockets, it is usually safe to | |
| // bind to a TIME_WAIT end point immediately, which is a widely adopted | |
| // behavior. | |
| // | |
| // Note that on *nix, SO_REUSEADDR does not enable the socket (which can be | |
| // either TCP or UDP) to bind to an end point that is already bound by another | |
| // socket. To do that one must set SO_REUSEPORT instead. This option is not | |
| // provided on Linux prior to 3.9. | |
| // | |
| // SO_REUSEPORT is provided in MacOS X and iOS. | |
| #if BUILDFLAG(IS_WIN) | |
| BOOL boolean_value = reuse ? TRUE : FALSE; | |
| #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) | |
| int boolean_value = reuse ? 1 : 0; | |
| #endif | |
| int rv = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, | |
| reinterpret_cast<const char*>(&boolean_value), | |
| sizeof(boolean_value)); | |
| return rv == -1 ? MapSystemError(errno) : OK; | |
| } | |
| int SetSocketReceiveBufferSize(SocketDescriptor fd, int32_t size) { | |
| int rv = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, | |
| reinterpret_cast<const char*>(&size), sizeof(size)); | |
| #if BUILDFLAG(IS_WIN) | |
| int os_error = WSAGetLastError(); | |
| #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) | |
| int os_error = errno; | |
| #endif | |
| int net_error = (rv == -1) ? MapSystemError(os_error) : OK; | |
| if (net_error != OK) { | |
| DLOG(ERROR) << "Could not set socket receive buffer size: " << net_error; | |
| } | |
| return net_error; | |
| } | |
| int SetSocketSendBufferSize(SocketDescriptor fd, int32_t size) { | |
| int rv = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, | |
| reinterpret_cast<const char*>(&size), sizeof(size)); | |
| #if BUILDFLAG(IS_WIN) | |
| int os_error = WSAGetLastError(); | |
| #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) | |
| int os_error = errno; | |
| #endif | |
| int net_error = (rv == -1) ? MapSystemError(os_error) : OK; | |
| if (net_error != OK) { | |
| DLOG(ERROR) << "Could not set socket send buffer size: " << net_error; | |
| } | |
| return net_error; | |
| } | |
| int SetIPv6Only(SocketDescriptor fd, bool ipv6_only) { | |
| #if BUILDFLAG(IS_WIN) | |
| DWORD on = ipv6_only ? 1 : 0; | |
| #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) | |
| int on = ipv6_only ? 1 : 0; | |
| #endif | |
| int rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, | |
| reinterpret_cast<const char*>(&on), sizeof(on)); | |
| return rv == -1 ? MapSystemError(errno) : OK; | |
| } | |
| } // namespace net |