1*6777b538SAndroid Build Coastguard Worker // Copyright 2016 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "net/socket/socket_options.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <cerrno>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
10*6777b538SAndroid Build Coastguard Worker #include "net/base/net_errors.h"
11*6777b538SAndroid Build Coastguard Worker
12*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
13*6777b538SAndroid Build Coastguard Worker #include <winsock2.h>
14*6777b538SAndroid Build Coastguard Worker #include <ws2tcpip.h>
15*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
16*6777b538SAndroid Build Coastguard Worker #include <netinet/in.h>
17*6777b538SAndroid Build Coastguard Worker #include <netinet/tcp.h>
18*6777b538SAndroid Build Coastguard Worker #include <sys/socket.h>
19*6777b538SAndroid Build Coastguard Worker #endif
20*6777b538SAndroid Build Coastguard Worker
21*6777b538SAndroid Build Coastguard Worker namespace net {
22*6777b538SAndroid Build Coastguard Worker
SetTCPNoDelay(SocketDescriptor fd,bool no_delay)23*6777b538SAndroid Build Coastguard Worker int SetTCPNoDelay(SocketDescriptor fd, bool no_delay) {
24*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
25*6777b538SAndroid Build Coastguard Worker BOOL on = no_delay ? TRUE : FALSE;
26*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
27*6777b538SAndroid Build Coastguard Worker int on = no_delay ? 1 : 0;
28*6777b538SAndroid Build Coastguard Worker #endif
29*6777b538SAndroid Build Coastguard Worker int rv = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
30*6777b538SAndroid Build Coastguard Worker reinterpret_cast<const char*>(&on), sizeof(on));
31*6777b538SAndroid Build Coastguard Worker return rv == -1 ? MapSystemError(errno) : OK;
32*6777b538SAndroid Build Coastguard Worker }
33*6777b538SAndroid Build Coastguard Worker
SetReuseAddr(SocketDescriptor fd,bool reuse)34*6777b538SAndroid Build Coastguard Worker int SetReuseAddr(SocketDescriptor fd, bool reuse) {
35*6777b538SAndroid Build Coastguard Worker // SO_REUSEADDR is useful for server sockets to bind to a recently unbound
36*6777b538SAndroid Build Coastguard Worker // port. When a socket is closed, the end point changes its state to TIME_WAIT
37*6777b538SAndroid Build Coastguard Worker // and wait for 2 MSL (maximum segment lifetime) to ensure the remote peer
38*6777b538SAndroid Build Coastguard Worker // acknowledges its closure. For server sockets, it is usually safe to
39*6777b538SAndroid Build Coastguard Worker // bind to a TIME_WAIT end point immediately, which is a widely adopted
40*6777b538SAndroid Build Coastguard Worker // behavior.
41*6777b538SAndroid Build Coastguard Worker //
42*6777b538SAndroid Build Coastguard Worker // Note that on *nix, SO_REUSEADDR does not enable the socket (which can be
43*6777b538SAndroid Build Coastguard Worker // either TCP or UDP) to bind to an end point that is already bound by another
44*6777b538SAndroid Build Coastguard Worker // socket. To do that one must set SO_REUSEPORT instead. This option is not
45*6777b538SAndroid Build Coastguard Worker // provided on Linux prior to 3.9.
46*6777b538SAndroid Build Coastguard Worker //
47*6777b538SAndroid Build Coastguard Worker // SO_REUSEPORT is provided in MacOS X and iOS.
48*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
49*6777b538SAndroid Build Coastguard Worker BOOL boolean_value = reuse ? TRUE : FALSE;
50*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
51*6777b538SAndroid Build Coastguard Worker int boolean_value = reuse ? 1 : 0;
52*6777b538SAndroid Build Coastguard Worker #endif
53*6777b538SAndroid Build Coastguard Worker int rv = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
54*6777b538SAndroid Build Coastguard Worker reinterpret_cast<const char*>(&boolean_value),
55*6777b538SAndroid Build Coastguard Worker sizeof(boolean_value));
56*6777b538SAndroid Build Coastguard Worker return rv == -1 ? MapSystemError(errno) : OK;
57*6777b538SAndroid Build Coastguard Worker }
58*6777b538SAndroid Build Coastguard Worker
SetSocketReceiveBufferSize(SocketDescriptor fd,int32_t size)59*6777b538SAndroid Build Coastguard Worker int SetSocketReceiveBufferSize(SocketDescriptor fd, int32_t size) {
60*6777b538SAndroid Build Coastguard Worker int rv = setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
61*6777b538SAndroid Build Coastguard Worker reinterpret_cast<const char*>(&size), sizeof(size));
62*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
63*6777b538SAndroid Build Coastguard Worker int os_error = WSAGetLastError();
64*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
65*6777b538SAndroid Build Coastguard Worker int os_error = errno;
66*6777b538SAndroid Build Coastguard Worker #endif
67*6777b538SAndroid Build Coastguard Worker int net_error = (rv == -1) ? MapSystemError(os_error) : OK;
68*6777b538SAndroid Build Coastguard Worker if (net_error != OK) {
69*6777b538SAndroid Build Coastguard Worker DLOG(ERROR) << "Could not set socket receive buffer size: " << net_error;
70*6777b538SAndroid Build Coastguard Worker }
71*6777b538SAndroid Build Coastguard Worker return net_error;
72*6777b538SAndroid Build Coastguard Worker }
73*6777b538SAndroid Build Coastguard Worker
SetSocketSendBufferSize(SocketDescriptor fd,int32_t size)74*6777b538SAndroid Build Coastguard Worker int SetSocketSendBufferSize(SocketDescriptor fd, int32_t size) {
75*6777b538SAndroid Build Coastguard Worker int rv = setsockopt(fd, SOL_SOCKET, SO_SNDBUF,
76*6777b538SAndroid Build Coastguard Worker reinterpret_cast<const char*>(&size), sizeof(size));
77*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
78*6777b538SAndroid Build Coastguard Worker int os_error = WSAGetLastError();
79*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
80*6777b538SAndroid Build Coastguard Worker int os_error = errno;
81*6777b538SAndroid Build Coastguard Worker #endif
82*6777b538SAndroid Build Coastguard Worker int net_error = (rv == -1) ? MapSystemError(os_error) : OK;
83*6777b538SAndroid Build Coastguard Worker if (net_error != OK) {
84*6777b538SAndroid Build Coastguard Worker DLOG(ERROR) << "Could not set socket send buffer size: " << net_error;
85*6777b538SAndroid Build Coastguard Worker }
86*6777b538SAndroid Build Coastguard Worker return net_error;
87*6777b538SAndroid Build Coastguard Worker }
88*6777b538SAndroid Build Coastguard Worker
SetIPv6Only(SocketDescriptor fd,bool ipv6_only)89*6777b538SAndroid Build Coastguard Worker int SetIPv6Only(SocketDescriptor fd, bool ipv6_only) {
90*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
91*6777b538SAndroid Build Coastguard Worker DWORD on = ipv6_only ? 1 : 0;
92*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
93*6777b538SAndroid Build Coastguard Worker int on = ipv6_only ? 1 : 0;
94*6777b538SAndroid Build Coastguard Worker #endif
95*6777b538SAndroid Build Coastguard Worker int rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,
96*6777b538SAndroid Build Coastguard Worker reinterpret_cast<const char*>(&on), sizeof(on));
97*6777b538SAndroid Build Coastguard Worker return rv == -1 ? MapSystemError(errno) : OK;
98*6777b538SAndroid Build Coastguard Worker }
99*6777b538SAndroid Build Coastguard Worker
100*6777b538SAndroid Build Coastguard Worker } // namespace net
101