[$squid_cv_have_std_underlying_type],
[Define if stdlibc support std::underlying_type for enums])
])
+
+## SQUID_CXX_STD_IS_TRIVIALLY_COPYABLE
+## checks whether the std::is_trivially_copyable<> trait exists
+## (known to be missing in GCC until version 5.1)
+AC_DEFUN([SQUID_CXX_STD_IS_TRIVIALLY_COPYABLE],[
+ AC_CACHE_CHECK([whether compiler supports std::is_trivially_copyable],
+ [squid_cv_have_std_is_trivially_copyable],[
+ AC_REQUIRE([AC_PROG_CXX])
+ AC_LANG_PUSH([C++])
+ AC_TRY_COMPILE([#include <type_traits>],
+ [return std::is_trivially_copyable<int>::value ? 1 : 0;],
+ [squid_cv_have_std_is_trivially_copyable=yes],
+ [squid_cv_have_std_is_trivially_copyable=no])
+ AC_LANG_POP
+ ])
+ SQUID_DEFINE_BOOL([HAVE_STD_IS_TRIVIALLY_COPYABLE],
+ [$squid_cv_have_std_is_trivially_copyable],
+ [Define if stdlibc support std::is_trivially_copyable])
+])
dnl Some C++11 types we try to use
AX_CXX_TYPE_UNIFORM_DISTRIBUTIONS
SQUID_CXX_STD_UNDERLYING_TYPE
+SQUID_CXX_STD_IS_TRIVIALLY_COPYABLE
dnl On Solaris 9 x86, gcc may includes a "fixed" set of old system include files
dnl that is incompatible with the updated Solaris header files.
workerQueues(false),
listenConn()
{
- memset(&tcp_keepalive, 0, sizeof(tcp_keepalive));
}
AnyP::PortCfg::~PortCfg()
#include "anyp/TrafficMode.h"
#include "base/CodeContext.h"
#include "comm/Connection.h"
+#include "comm/Tcp.h"
#include "sbuf/SBuf.h"
#include "security/ServerOptions.h"
int disable_pmtu_discovery;
bool workerQueues; ///< whether listening queues should be worker-specific
- struct {
- unsigned int idle;
- unsigned int interval;
- unsigned int timeout;
- bool enabled;
- } tcp_keepalive;
+ Comm::TcpKeepAlive tcp_keepalive;
/**
* The listening socket details.
debugs(33, 4, params.conn << ": accepted");
fd_note(params.conn->fd, "client http connect");
- if (s->tcp_keepalive.enabled)
- commSetTcpKeepalive(params.conn->fd, s->tcp_keepalive.idle, s->tcp_keepalive.interval, s->tcp_keepalive.timeout);
-
// Socket is ready, setup the connection manager to start using it
auto *srv = Http::NewServer(xact);
AsyncJob::Start(srv); // usually async-calls readSomeData()
debugs(33, 4, HERE << params.conn << " accepted, starting SSL negotiation.");
fd_note(params.conn->fd, "client https connect");
- if (s->tcp_keepalive.enabled) {
- commSetTcpKeepalive(params.conn->fd, s->tcp_keepalive.idle, s->tcp_keepalive.interval, s->tcp_keepalive.timeout);
- }
-
// Socket is ready, setup the connection manager to start using it
auto *srv = Https::NewServer(xact);
AsyncJob::Start(srv); // usually async-calls postHttpsAccept()
#endif
-void
-commSetTcpKeepalive(int fd, int idle, int interval, int timeout)
-{
- int on = 1;
-#ifdef TCP_KEEPCNT
- if (timeout && interval) {
- int count = (timeout + interval - 1) / interval;
- if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &count, sizeof(on)) < 0) {
- int xerrno = errno;
- debugs(5, DBG_IMPORTANT, MYNAME << "FD " << fd << ": " << xstrerr(xerrno));
- }
- }
-#endif
-#ifdef TCP_KEEPIDLE
- if (idle) {
- if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(on)) < 0) {
- int xerrno = errno;
- debugs(5, DBG_IMPORTANT, MYNAME << "FD " << fd << ": " << xstrerr(xerrno));
- }
- }
-#endif
-#ifdef TCP_KEEPINTVL
- if (interval) {
- if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &interval, sizeof(on)) < 0) {
- int xerrno = errno;
- debugs(5, DBG_IMPORTANT, MYNAME << "FD " << fd << ": " << xstrerr(xerrno));
- }
- }
-#endif
- if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, sizeof(on)) < 0) {
- int xerrno = errno;
- debugs(5, DBG_IMPORTANT, MYNAME << "FD " << fd << ": " << xstrerr(xerrno));
- }
-}
-
void
comm_init(void)
{
int commSetNonBlocking(int fd);
int commUnsetNonBlocking(int fd);
void commSetCloseOnExec(int fd);
-void commSetTcpKeepalive(int fd, int idle, int interval, int timeout);
void _comm_close(int fd, char const *file, int line);
#define comm_close(x) (_comm_close((x), __FILE__, __LINE__))
void old_comm_reset_close(int fd);
ModSelectWin32.cc \
Read.cc \
Read.h \
+ Tcp.cc \
+ Tcp.h \
TcpAcceptor.cc \
TcpAcceptor.h \
UdpOpenDialer.h \
--- /dev/null
+/*
+ * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+/* DEBUG: section 05 TCP Socket Functions */
+
+#include "squid.h"
+#include "comm/Tcp.h"
+#include "Debug.h"
+
+#if HAVE_NETINET_TCP_H
+#include <netinet/tcp.h>
+#endif
+#include <type_traits>
+
+/// setsockopt(2) wrapper
+template <typename Option>
+static bool
+SetSocketOption(const int fd, const int level, const int optName, const Option &optValue)
+{
+#if HAVE_STD_IS_TRIVIALLY_COPYABLE
+ static_assert(std::is_trivially_copyable<Option>::value, "setsockopt() expects POD-like options");
+#endif
+ static_assert(!std::is_same<Option, bool>::value, "setsockopt() uses int to represent boolean options");
+ if (setsockopt(fd, level, optName, &optValue, sizeof(optValue)) < 0) {
+ const auto xerrno = errno;
+ debugs(5, DBG_IMPORTANT, "ERROR: setsockopt(2) failure: " << xstrerr(xerrno));
+ // TODO: Generalize to throw on errors when some callers need that.
+ return false;
+ }
+ return true;
+}
+
+/// setsockopt(2) wrapper for setting typical on/off options
+static bool
+SetBooleanSocketOption(const int fd, const int level, const int optName, const bool enable)
+{
+ const int optValue = enable ? 1 : 0;
+ return SetSocketOption(fd, level, optName, optValue);
+}
+
+void
+Comm::ApplyTcpKeepAlive(int fd, const TcpKeepAlive &cfg)
+{
+ if (!cfg.enabled)
+ return;
+
+#if defined(TCP_KEEPCNT)
+ if (cfg.timeout && cfg.interval) {
+ const int count = (cfg.timeout + cfg.interval - 1) / cfg.interval; // XXX: unsigned-to-signed conversion
+ (void)SetSocketOption(fd, IPPROTO_TCP, TCP_KEEPCNT, count);
+ }
+#endif
+#if defined(TCP_KEEPIDLE)
+ if (cfg.idle) {
+ // XXX: TCP_KEEPIDLE expects an int; cfg.idle is unsigned
+ (void)SetSocketOption(fd, IPPROTO_TCP, TCP_KEEPIDLE, cfg.idle);
+ }
+#endif
+#if defined(TCP_KEEPINTVL)
+ if (cfg.interval) {
+ // XXX: TCP_KEEPINTVL expects an int; cfg.interval is unsigned
+ (void)SetSocketOption(fd, IPPROTO_TCP, TCP_KEEPINTVL, cfg.interval);
+ }
+#endif
+ (void)SetBooleanSocketOption(fd, SOL_SOCKET, SO_KEEPALIVE, true);
+}
--- /dev/null
+/*
+ * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#ifndef SQUID__SRC_COMM_TCP_H
+#define SQUID__SRC_COMM_TCP_H
+
+namespace Comm
+{
+
+/// Configuration settings for the TCP keep-alive feature
+class TcpKeepAlive
+{
+public:
+ unsigned int idle = 0;
+ unsigned int interval = 0;
+ unsigned int timeout = 0;
+ bool enabled = false;
+};
+
+/// apply configured TCP keep-alive settings to the given FD socket
+void ApplyTcpKeepAlive(int fd, const TcpKeepAlive &);
+
+} // namespace Comm
+
+#endif /* SQUID__SRC_COMM_TCP_H */
// set socket flags
commSetCloseOnExec(sock);
commSetNonBlocking(sock);
+ Comm::ApplyTcpKeepAlive(sock, listenPort_->tcp_keepalive);
/* IFF the socket is (tproxy) transparent, pass the flag down to allow spoofing */
F->flags.transparent = fd_table[conn->fd].flags.transparent; // XXX: can we remove this line yet?
class Connection;
class ConnOpener;
+class TcpKeepAlive;
typedef RefCount<Comm::Connection> ConnectionPointer;
void
Ipc::TypedMsgHdr::getPod(Pod &pod) const
{
+#if HAVE_STD_IS_TRIVIALLY_COPYABLE
// TODO: Enable after fixing Ipc::SharedListenRequest::SharedListenRequest()
//static_assert(std::is_trivially_copyable<Pod>::value, "getPod() used for a POD");
+#endif
getFixed(&pod, sizeof(pod));
}
void
Ipc::TypedMsgHdr::putPod(const Pod &pod)
{
+#if HAVE_STD_IS_TRIVIALLY_COPYABLE
// TODO: Enable after fixing Ipc::SharedListenRequest::pack()
//static_assert(std::is_trivially_copyable<Pod>::value, "putPod() used for a POD");
+#endif
putFixed(&pod, sizeof(pod));
}
debugs(33, 4, params.conn << ": accepted");
fd_note(params.conn->fd, "client ftp connect");
- if (s->tcp_keepalive.enabled)
- commSetTcpKeepalive(params.conn->fd, s->tcp_keepalive.idle, s->tcp_keepalive.interval, s->tcp_keepalive.timeout);
-
AsyncJob::Start(new Server(xact));
}
int commSetNonBlocking(int fd) STUB_RETVAL(Comm::COMM_ERROR)
int commUnsetNonBlocking(int fd) STUB_RETVAL(-1)
void commSetCloseOnExec(int fd) STUB_NOP
-void commSetTcpKeepalive(int fd, int idle, int interval, int timeout) STUB
void _comm_close(int fd, char const *file, int line) STUB
void old_comm_reset_close(int fd) STUB
void comm_reset_close(const Comm::ConnectionPointer &conn) STUB
void Comm::TcpAcceptor::acceptNext() STUB
void Comm::TcpAcceptor::notify(const Comm::Flag flag, const Comm::ConnectionPointer &) const STUB
+#include "comm/Tcp.h"
+void Comm::ApplyTcpKeepAlive(int, const TcpKeepAlive &) STUB
+
#include "comm/Write.h"
void Comm::Write(const Comm::ConnectionPointer &, const char *, int, AsyncCall::Pointer &, FREE *) STUB
void Comm::Write(const Comm::ConnectionPointer &conn, MemBuf *mb, AsyncCall::Pointer &callback) STUB