Skip to content

Commit

Permalink
Add TCP keep-alive options to rtc::Socket
Browse files Browse the repository at this point in the history
Enabling Socket options on keep-alive related function that may enable clients to detect any stale connection early on.

Bug: webrtc:15866
Change-Id: Ib4f15e0c933aeb6cf4fd18ff8cc708d118ea8645
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/342223
Reviewed-by: Harald Alvestrand <[email protected]>
Commit-Queue: Tim Na <[email protected]>
Cr-Commit-Position: refs/heads/main@{#41888}
  • Loading branch information
timna authored and WebRTC LUCI CQ committed Mar 13, 2024
1 parent f3096af commit 4473d75
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 1 deletion.
29 changes: 29 additions & 0 deletions rtc_base/physical_socket_server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,35 @@ int PhysicalSocket::TranslateOption(Option opt, int* slevel, int* sopt) {
#endif
case OPT_RTP_SENDTIME_EXTN_ID:
return -1; // No logging is necessary as this not a OS socket option.
case OPT_KEEPALIVE:
*slevel = SOL_SOCKET;
*sopt = SO_KEEPALIVE;
break;
case OPT_TCP_KEEPCNT:
*slevel = IPPROTO_TCP;
*sopt = TCP_KEEPCNT;
break;
case OPT_TCP_KEEPIDLE:
*slevel = IPPROTO_TCP;
#if !defined(WEBRTC_MAC)
*sopt = TCP_KEEPIDLE;
#else
*sopt = TCP_KEEPALIVE;
#endif
break;
case OPT_TCP_KEEPINTVL:
*slevel = IPPROTO_TCP;
*sopt = TCP_KEEPINTVL;
break;
case OPT_TCP_USER_TIMEOUT:
#if defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID)
*slevel = IPPROTO_TCP;
*sopt = TCP_USER_TIMEOUT;
break;
#else
RTC_LOG(LS_WARNING) << "Socket::OPT_TCP_USER_TIMEOUT not supported.";
return -1;
#endif
default:
RTC_DCHECK_NOTREACHED();
return -1;
Expand Down
7 changes: 6 additions & 1 deletion rtc_base/socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,12 @@ class RTC_EXPORT Socket {
// This is specific to libjingle and will be used
// if SendTime option is needed at socket level.
OPT_SEND_ECN, // 2-bit ECN
OPT_RECV_ECN
OPT_RECV_ECN,
OPT_KEEPALIVE, // Enable socket keep alive
OPT_TCP_KEEPCNT, // Set TCP keep alive count
OPT_TCP_KEEPIDLE, // Set TCP keep alive idle time in seconds
OPT_TCP_KEEPINTVL, // Set TCP keep alive interval in seconds
OPT_TCP_USER_TIMEOUT, // Set TCP user timeout
};
virtual int GetOption(Option opt, int* value) = 0;
virtual int SetOption(Option opt, int value) = 0;
Expand Down
38 changes: 38 additions & 0 deletions rtc_base/socket_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1101,6 +1101,44 @@ void SocketTest::GetSetOptionsInternal(const IPAddress& loopback) {
ASSERT_NE(-1, socket->GetOption(Socket::OPT_RECV_ECN, &current_recv_esn));
ASSERT_EQ(current_recv_esn, desired_recv_esn);
#endif

// Prepare on TCP specific options.
socket.reset(socket_factory_->CreateSocket(loopback.family(), SOCK_STREAM));
socket->Bind(SocketAddress(loopback, 0));

// Check that we can set NODELAY on a TCP socket.
ASSERT_NE(-1, socket->SetOption(Socket::OPT_NODELAY, desired_nd));
ASSERT_NE(-1, socket->GetOption(Socket::OPT_NODELAY, &current_nd));
ASSERT_NE(0, current_nd);

// Check TCP Keep Alive settings.
int current_kl, desired_kl = 1;
ASSERT_NE(-1, socket->SetOption(Socket::OPT_KEEPALIVE, desired_kl));
ASSERT_NE(-1, socket->GetOption(Socket::OPT_KEEPALIVE, &current_kl));
ASSERT_NE(0, current_kl);

int current_kl_cnt, desired_kl_cnt = 3;
ASSERT_NE(-1, socket->SetOption(Socket::OPT_TCP_KEEPCNT, desired_kl_cnt));
ASSERT_NE(-1, socket->GetOption(Socket::OPT_TCP_KEEPCNT, &current_kl_cnt));
ASSERT_EQ(desired_kl_cnt, current_kl_cnt);

int current_kl_idle, desired_kl_idle = 2;
ASSERT_NE(-1, socket->SetOption(Socket::OPT_TCP_KEEPIDLE, desired_kl_idle));
ASSERT_NE(-1, socket->GetOption(Socket::OPT_TCP_KEEPIDLE, &current_kl_idle));
ASSERT_EQ(desired_kl_idle, current_kl_idle);

int current_kl_intvl, desired_kl_intvl = 2;
ASSERT_NE(-1, socket->SetOption(Socket::OPT_TCP_KEEPINTVL, desired_kl_intvl));
ASSERT_NE(-1,
socket->GetOption(Socket::OPT_TCP_KEEPINTVL, &current_kl_intvl));
ASSERT_EQ(desired_kl_intvl, current_kl_intvl);

#if defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID)
int current_ut, desired_ut = 10;
ASSERT_NE(-1, socket->SetOption(Socket::OPT_TCP_USER_TIMEOUT, desired_ut));
ASSERT_NE(-1, socket->GetOption(Socket::OPT_TCP_USER_TIMEOUT, &current_ut));
ASSERT_EQ(desired_ut, current_ut);
#endif
}

void SocketTest::SocketRecvTimestamp(const IPAddress& loopback) {
Expand Down

0 comments on commit 4473d75

Please sign in to comment.