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