]> git.ipfire.org Git - thirdparty/squid.git/blob - src/comm/Tcp.cc
59769a3233ec57f28ef04c5212a51d9f1901f484
[thirdparty/squid.git] / src / comm / Tcp.cc
1 /*
2 * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 /* DEBUG: section 05 TCP Socket Functions */
10
11 #include "squid.h"
12 #include "comm/Tcp.h"
13 #include "Debug.h"
14
15 #if HAVE_NETINET_TCP_H
16 #include <netinet/tcp.h>
17 #endif
18 #include <type_traits>
19
20 /// setsockopt(2) wrapper
21 template <typename Option>
22 static bool
23 SetSocketOption(const int fd, const int level, const int optName, const Option &optValue)
24 {
25 #if HAVE_STD_IS_TRIVIALLY_COPYABLE
26 static_assert(std::is_trivially_copyable<Option>::value, "setsockopt() expects POD-like options");
27 #endif
28 static_assert(!std::is_same<Option, bool>::value, "setsockopt() uses int to represent boolean options");
29 if (setsockopt(fd, level, optName, &optValue, sizeof(optValue)) < 0) {
30 const auto xerrno = errno;
31 debugs(5, DBG_IMPORTANT, "ERROR: setsockopt(2) failure: " << xstrerr(xerrno));
32 // TODO: Generalize to throw on errors when some callers need that.
33 return false;
34 }
35 return true;
36 }
37
38 /// setsockopt(2) wrapper for setting typical on/off options
39 static bool
40 SetBooleanSocketOption(const int fd, const int level, const int optName, const bool enable)
41 {
42 const int optValue = enable ? 1 : 0;
43 return SetSocketOption(fd, level, optName, optValue);
44 }
45
46 void
47 Comm::ApplyTcpKeepAlive(int fd, const TcpKeepAlive &cfg)
48 {
49 if (!cfg.enabled)
50 return;
51
52 #if defined(TCP_KEEPCNT)
53 if (cfg.timeout && cfg.interval) {
54 const int count = (cfg.timeout + cfg.interval - 1) / cfg.interval; // XXX: unsigned-to-signed conversion
55 (void)SetSocketOption(fd, IPPROTO_TCP, TCP_KEEPCNT, count);
56 }
57 #endif
58 #if defined(TCP_KEEPIDLE)
59 if (cfg.idle) {
60 // XXX: TCP_KEEPIDLE expects an int; cfg.idle is unsigned
61 (void)SetSocketOption(fd, IPPROTO_TCP, TCP_KEEPIDLE, cfg.idle);
62 }
63 #endif
64 #if defined(TCP_KEEPINTVL)
65 if (cfg.interval) {
66 // XXX: TCP_KEEPINTVL expects an int; cfg.interval is unsigned
67 (void)SetSocketOption(fd, IPPROTO_TCP, TCP_KEEPINTVL, cfg.interval);
68 }
69 #endif
70 (void)SetBooleanSocketOption(fd, SOL_SOCKET, SO_KEEPALIVE, true);
71 }