Skip to content
Snippets Groups Projects
Unverified Commit 93f85f37 authored by Sébastien Blin's avatar Sébastien Blin
Browse files

pjproject: fix TCP sockets death detection

TCP_KEEPALIVE are not enough to detect that TCP connections are dead or not.
Some routers doesn't seems to support TCP_KEEPALIVE and moreover, sometimes
the settings is just not enough as described in this article:
https://blog.cloudflare.com/when-tcp-sockets-refuse-to-die/

RFC 5482 describe a new option for sockets: TCP_USER_TIMEOUT which must be used
with keep alives to detect closed connection in a better way.

In this patch we set TCP_USER_TIMEOUT to 30 seconds (like the keep alive). This is
a TCP level socket option used to specify the max time in ms that transmitted data
can be unacknowledged before a force close.

Change-Id: I217616b9b9e08adfa5a044a451fbbc97faf1939e
Gitlab: #243
parent 8473608f
No related branches found
Tags 1.1.0
No related merge requests found
pjlib/include/pj/sock.h | 7 +++++++
pjlib/src/pj/sock_bsd.c | 9 +++++++++
pjlib/src/pj/sock_common.c | 5 +++++
pjlib/src/pj/sock_uwp.cpp | 6 ++++++
pjlib/src/pj/symbols.c | 1 +
5 files changed, 28 insertions(+)
diff --git a/pjlib/include/pj/sock.h b/pjlib/include/pj/sock.h
index 095a38335..e1349c52c 100644
--- a/pjlib/include/pj/sock.h
+++ b/pjlib/include/pj/sock.h
@@ -317,6 +317,7 @@ extern const pj_uint16_t PJ_SO_KEEPALIVE;
extern const pj_uint16_t PJ_TCP_KEEPIDLE;
extern const pj_uint16_t PJ_TCP_KEEPINTVL;
extern const pj_uint16_t PJ_TCP_KEEPCNT;
+extern const pj_uint16_t PJ_TCP_USER_TIMEOUT;
/** Set the protocol-defined priority for all packets to be sent on socket.
*/
@@ -360,6 +361,9 @@ extern const pj_uint16_t PJ_IP_DROP_MEMBERSHIP;
/** Get #PJ_TCP_KEEPINTVL constant */
# define pj_TCP_KEEPINTVL() PJ_TCP_KEEPINTVL(void);
+ /** Get #PJ_TCP_USER_TIMEOUT constant */
+ PJ_DECL(pj_uint16_t) PJ_TCP_USER_TIMEOUT(void);
+
/** Get #PJ_TCP_KEEPCNT constant */
# define pj_TCP_KEEPCNT() PJ_TCP_KEEPCNT(void);
@@ -405,6 +409,9 @@ extern const pj_uint16_t PJ_IP_DROP_MEMBERSHIP;
/** Get #PJ_TCP_KEEPIDLE constant */
# define pj_TCP_KEEPIDLE() PJ_TCP_KEEPIDLE
+ /** Get #PJ_TCP_USER_TIMEOUT constant */
+# define pj_TCP_USER_TIMEOUT() PJ_TCP_USER_TIMEOUT
+
/** Get #PJ_TCP_KEEPINTVL constant */
# define pj_TCP_KEEPINTVL() PJ_TCP_KEEPINTVL
diff --git a/pjlib/src/pj/sock_bsd.c b/pjlib/src/pj/sock_bsd.c
index 0e9bfdbe9..e8bd94bee 100644
--- a/pjlib/src/pj/sock_bsd.c
+++ b/pjlib/src/pj/sock_bsd.c
@@ -162,6 +162,11 @@ const pj_uint16_t PJ_TCP_KEEPIDLE = TCP_KEEPIDLE;
# ifdef TCP_KEEPINTVL
const pj_uint16_t PJ_TCP_KEEPINTVL = TCP_KEEPINTVL;
# endif
+# ifdef TCP_USER_TIMEOUT
+const pj_uint16_t PJ_TCP_USER_TIMEOUT = TCP_USER_TIMEOUT;
+#else
+const pj_uint16_t PJ_TCP_USER_TIMEOUT = 18;
+# endif
# ifdef TCP_KEEPCNT
const pj_uint16_t PJ_TCP_KEEPCNT = TCP_KEEPCNT;
# endif
@@ -592,7 +597,11 @@ PJ_DEF(pj_status_t) pj_sock_socket(int af,
&val, sizeof(val));
pj_sock_setsockopt(*sock, pj_SOL_TCP(), pj_TCP_KEEPINTVL(),
&val, sizeof(val));
+ val = 30000;
+ pj_sock_setsockopt(*sock, pj_SOL_TCP(), pj_TCP_USER_TIMEOUT(),
+ &val, sizeof(val));
val = 1;
+
}
#if defined(PJ_SOCK_HAS_IPV6_V6ONLY) && PJ_SOCK_HAS_IPV6_V6ONLY != 0
if (af == PJ_AF_INET6) {
diff --git a/pjlib/src/pj/sock_common.c b/pjlib/src/pj/sock_common.c
index 6beb28590..1a0a38aee 100644
--- a/pjlib/src/pj/sock_common.c
+++ b/pjlib/src/pj/sock_common.c
@@ -1351,6 +1351,11 @@ PJ_DEF(pj_uint16_t) pj_SO_KEEPALIVE(void)
return PJ_SO_KEEPALIVE;
}
+PJ_DEF(pj_uint16_t) pj_TCP_USER_TIMEOUT(void)
+{
+ return PJ_TCP_USER_TIMEOUT;
+}
+
PJ_DEF(pj_uint16_t) pj_TCP_NODELAY(void)
{
return PJ_TCP_NODELAY;
diff --git a/pjlib/src/pj/sock_uwp.cpp b/pjlib/src/pj/sock_uwp.cpp
index 34baebcee..4ba61cfd1 100644
--- a/pjlib/src/pj/sock_uwp.cpp
+++ b/pjlib/src/pj/sock_uwp.cpp
@@ -97,6 +97,12 @@ const pj_uint16_t PJ_SOL_TCP = IPPROTO_TCP;
const pj_uint16_t PJ_SOL_TCP = 6;
#endif /* SOL_TCP */
+#if defined(TCP_USER_TIMEOUT)
+const pj_uint16_t PJ_TCP_USER_TIMEOUT = TCP_USER_TIMEOUT;
+#else
+const pj_uint16_t PJ_TCP_USER_TIMEOUT = 18;
+#endif
+
#if defined(SOL_KEEPALIVE)
const pj_uint16_t PJ_SOL_KEEPALIVE = SOL_KEEPALIVE;
#else
diff --git a/pjlib/src/pj/symbols.c b/pjlib/src/pj/symbols.c
index 966a9fc43..c71e49da4 100644
--- a/pjlib/src/pj/symbols.c
+++ b/pjlib/src/pj/symbols.c
@@ -262,6 +262,7 @@ PJ_EXPORT_SYMBOL(PJ_SOL_IP)
PJ_EXPORT_SYMBOL(PJ_TCP_KEEPIDLE)
PJ_EXPORT_SYMBOL(PJ_TCP_KEEPINTVL)
PJ_EXPORT_SYMBOL(PJ_TCP_KEEPCNT)
+PJ_EXPORT_SYMBOL(PJ_TCP_USER_TIMEOUT)
PJ_EXPORT_SYMBOL(PJ_SOL_TCP)
PJ_EXPORT_SYMBOL(PJ_SOL_UDP)
PJ_EXPORT_SYMBOL(PJ_SOL_IPV6)
......@@ -15,8 +15,9 @@
"0009-add-config-site.patch",
"0001-win-config.patch",
"0002-win-vs-gnutls.patch",
"0003-win-vs2017-props.patch"
],
"0003-win-vs2017-props.patch",
"0011-fix-tcp-death-detection.patch"
],
"project_paths": [
"pjlib-util/build/pjlib_util.vcxproj",
"pjmedia/build/pjmedia.vcxproj",
......
......@@ -55,6 +55,7 @@ pjproject: pjproject-$(PJPROJECT_VERSION).tar.gz .sum-pjproject
$(APPLY) $(SRC)/pjproject/0008-fix_ioqueue_ipv6_sendto.patch
$(APPLY) $(SRC)/pjproject/0009-add-config-site.patch
$(APPLY) $(SRC)/pjproject/0010-fix-pkgconfig.patch
$(APPLY) $(SRC)/pjproject/0011-fix-tcp-death-detection.patch
ifdef HAVE_ANDROID
$(APPLY) $(SRC)/pjproject/0001-android.patch
endif
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment