diff --git a/src/netlog/netlog-gperf.gperf b/src/netlog/netlog-gperf.gperf index 374bb3d..e06c4fa 100644 --- a/src/netlog/netlog-gperf.gperf +++ b/src/netlog/netlog-gperf.gperf @@ -25,3 +25,7 @@ Network.UseSysLogStructuredData, config_parse_bool, 0, off Network.UseSysLogMsgId, config_parse_bool, 0, offsetof(Manager, syslog_msgid) Network.ConnectionRetrySec, config_parse_sec, 0, offsetof(Manager, connection_retry_usec) Network.TLSCertificateAuthMode, config_parse_tls_certificate_auth_mode, 0, offsetof(Manager, auth_mode) +Network.KeepAlive, config_parse_bool, 0, offsetof(Manager, keep_alive) +Network.KeepAliveTimeSec, config_parse_sec, 0, offsetof(Manager, keep_alive_time) +Network.KeepAliveIntervalSec, config_parse_sec, 0, offsetof(Manager, keep_alive_interval) +Network.KeepAliveProbes, config_parse_unsigned, 0, offsetof(Manager, keep_alive_cnt) diff --git a/src/netlog/netlog-manager.h b/src/netlog/netlog-manager.h index f0e44e8..6c814b1 100644 --- a/src/netlog/netlog-manager.h +++ b/src/netlog/netlog-manager.h @@ -75,6 +75,13 @@ struct Manager { DTLSManager *dtls; TLSManager *tls; + + bool keep_alive; + + unsigned keep_alive_cnt; + usec_t timeout_usec; + usec_t keep_alive_time; + usec_t keep_alive_interval; }; int manager_new(const char *state_file, const char *cursor, Manager **ret); diff --git a/src/netlog/netlog-network.c b/src/netlog/netlog-network.c index 3700f82..b75dbc9 100644 --- a/src/netlog/netlog-network.c +++ b/src/netlog/netlog-network.c @@ -417,14 +417,33 @@ int manager_open_network_socket(Manager *m) { }} break; case SYSLOG_TRANSMISSION_PROTOCOL_TCP: { - r = setsockopt_int(m->socket, IPPROTO_TCP, TCP_FASTOPEN, 5); /* Everybody appears to pick qlen=5, let's do the same here. */ - if (r < 0) - log_debug_errno(r, "Failed to enable TCP_FASTOPEN on TCP listening socket, ignoring: %m"); - r = setsockopt_int(m->socket, IPPROTO_TCP, TCP_NODELAY, true); if (r < 0) log_debug_errno(r, "Failed to enable TCP_NODELAY mode, ignoring: %m"); - } + + if (m->keep_alive) { + r = setsockopt_int(m->socket, SOL_SOCKET, SO_KEEPALIVE, true); + if (r < 0) + log_debug_errno(r, "Failed to enable SO_KEEPALIVE: %m"); + } + + if (timestamp_is_set(m->keep_alive_time)) { + r = setsockopt_int(m->socket, SOL_TCP, TCP_KEEPIDLE, m->keep_alive_time / USEC_PER_SEC); + if (r < 0) + log_debug_errno(r, "TCP_KEEPIDLE failed: %m"); + } + + if (m->keep_alive_interval > 0) { + r = setsockopt_int(m->socket, SOL_TCP, TCP_KEEPINTVL, m->keep_alive_interval / USEC_PER_SEC); + if (r < 0) + log_debug_errno(r, "TCP_KEEPINTVL failed: %m"); + } + + if (m->keep_alive_cnt > 0) { + r = setsockopt_int(m->socket, SOL_TCP, TCP_KEEPCNT, m->keep_alive_cnt); + if (r < 0) + log_debug_errno(r, "TCP_KEEPCNT failed: %m"); + }} break; default: break; diff --git a/src/share/conf-parser.c b/src/share/conf-parser.c index 520ec6c..8e52bcc 100644 --- a/src/share/conf-parser.c +++ b/src/share/conf-parser.c @@ -411,39 +411,6 @@ int config_parse_many(const char *conf_file, return 0; } -#if 0 -#define DEFINE_PARSER(type, vartype, conv_func) \ - int config_parse_##type( \ - const char *unit, \ - const char *filename, \ - unsigned line, \ - const char *section, \ - unsigned section_line, \ - const char *lvalue, \ - int ltype, \ - const char *rvalue, \ - void *data, \ - void *userdata) { \ - \ - vartype *i = data; \ - int r; \ - \ - assert(filename); \ - assert(lvalue); \ - assert(rvalue); \ - assert(data); \ - \ - r = conv_func(rvalue, i); \ - if (r < 0) \ - log_syntax(unit, LOG_ERR, filename, line, r, \ - "Failed to parse %s value, ignoring: %s", \ - #type, rvalue); \ - \ - return 0; \ - } \ - struct __useless_struct_to_allow_trailing_semicolon__ - -#endif int config_parse_string( const char *unit, const char *filename, @@ -518,3 +485,4 @@ int config_parse_bool( DEFINE_CONFIG_PARSE_PTR(config_parse_##type, conv_func, vartype, "Failed to parse " #type " value") DEFINE_PARSER(sec, usec_t, parse_sec); +DEFINE_PARSER(unsigned, unsigned, safe_atou); diff --git a/src/share/conf-parser.h b/src/share/conf-parser.h index 383f3c6..e9cf6c4 100644 --- a/src/share/conf-parser.h +++ b/src/share/conf-parser.h @@ -250,3 +250,4 @@ int config_parse_many(const char *conf_file, /* possibly NULL */ CONFIG_PARSER_PROTOTYPE(config_parse_string); CONFIG_PARSER_PROTOTYPE(config_parse_bool); CONFIG_PARSER_PROTOTYPE(config_parse_sec); +CONFIG_PARSER_PROTOTYPE(config_parse_unsigned); diff --git a/src/share/time-util.h b/src/share/time-util.h index e74b171..f15ce75 100644 --- a/src/share/time-util.h +++ b/src/share/time-util.h @@ -105,3 +105,7 @@ static inline usec_t usec_sub_signed(usec_t timestamp, int64_t delta) { int parse_sec(const char *t, usec_t *ret); int parse_time(const char *t, usec_t *ret, usec_t default_unit); + +static inline bool timestamp_is_set(usec_t timestamp) { + return timestamp > 0 && timestamp != USEC_INFINITY; +}