From 6c1c2a86f85316333fd7766b35660e13a96dd4f7 Mon Sep 17 00:00:00 2001 From: "Andrey (Stanson) Kozin" Date: Mon, 8 Feb 2016 08:28:41 +0300 Subject: [PATCH] TCP keepalive setting support --- src/conn.c | 20 ++++++++++++++++++++ src/sock.c | 38 ++++++++++++++++++++++++++++++++++++++ src/sock.h | 1 + strophe.h | 1 + 4 files changed, 60 insertions(+) diff --git a/src/conn.c b/src/conn.c index 1765a49..72536c1 100644 --- a/src/conn.c +++ b/src/conn.c @@ -175,6 +175,26 @@ xmpp_conn_t *xmpp_conn_clone(xmpp_conn_t * const conn) return conn; } +/** Set TCP keepalive parameters + * Turn on TCP keepalive and set timeout and interval. Zero timeout + * disables TCP keepalives. + * + * @param conn a Strophe connection object + * @param timeout TCP keepalive timeout in seconds + * @param interval TCP keepalive interval in seconds + * + * @ingroup Connections + */ +void xmpp_conn_set_keepalive(xmpp_conn_t * const conn, int timeout, int interval) +{ + int ret; + ret = sock_set_keepalive(conn->sock, timeout, interval); + if (ret < 0) { + xmpp_error(conn->ctx, "xmpp", "Setting TCP keepalive (%d,%d) error: %d", + timeout, interval, sock_error()); + } +} + /** Release a Strophe connection object. * Decrement the reference count by one for a connection, freeing the * connection object if the count reaches 0. diff --git a/src/sock.c b/src/sock.c index 49ef205..fb6241d 100644 --- a/src/sock.c +++ b/src/sock.c @@ -22,11 +22,13 @@ #include #include #include +#include /* tcp_keepalive */ #else #include #include #include #include +#include #include #include #endif @@ -108,6 +110,42 @@ sock_t sock_connect(const char * const host, const unsigned short port) return sock; } +int sock_set_keepalive(const sock_t sock, int timeout, int interval) +{ + int ret; + int optval = (timeout && interval) ? 1 : 0; + +#ifdef _WIN32 + struct tcp_keepalive ka; + DWORD dw = 0; + + ka.onoff = optval; + ka.keepalivetime = timeout * 1000; + ka.keepaliveinterval = interval * 1000; + ret = WSAIoctl(sock, SIO_KEEPALIVE_VALS, &ka, sizeof(ka), NULL, 0, &dw, NULL, NULL); +#else + ret = setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval)); + if (ret < 0) + return ret; + + if (optval) { + /* it's not possible to set keepalive count in Windows, so just use some + * acceptable value for UNIX to keep things work the same */ + optval = 5; + ret = setsockopt(sock, SOL_TCP, TCP_KEEPCNT, &optval, sizeof(optval)); + if (ret < 0) + return ret; + ret = setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, &timeout, sizeof(timeout)); + if (ret < 0) + return ret; + ret = setsockopt(sock, SOL_TCP, TCP_KEEPINTVL, &interval, sizeof(interval)); + if (ret < 0) + return ret; + } +#endif + return ret; +} + int sock_close(const sock_t sock) { #ifdef _WIN32 diff --git a/src/sock.h b/src/sock.h index 753d60c..e612bea 100644 --- a/src/sock.h +++ b/src/sock.h @@ -40,5 +40,6 @@ int sock_write(const sock_t sock, const void * const buff, const size_t len); int sock_is_recoverable(const int error); /* checks for an error after connect, return 0 if connect successful */ int sock_connect_error(const sock_t sock); +int sock_set_keepalive(const sock_t sock, int timeout, int interval); #endif /* __LIBSTROPHE_SOCK_H__ */ diff --git a/strophe.h b/strophe.h index 91b0669..737b0a2 100644 --- a/strophe.h +++ b/strophe.h @@ -222,6 +222,7 @@ void xmpp_conn_set_pass(xmpp_conn_t * const conn, const char * const pass); xmpp_ctx_t* xmpp_conn_get_context(xmpp_conn_t * const conn); void xmpp_conn_disable_tls(xmpp_conn_t * const conn); int xmpp_conn_is_secured(xmpp_conn_t * const conn); +void xmpp_conn_set_keepalive(xmpp_conn_t * const conn, int timeout, int interval); int xmpp_connect_client(xmpp_conn_t * const conn, const char * const altdomain,