This is an automated email from the ASF dual-hosted git repository.

wwbmmm pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brpc.git


The following commit(s) were added to refs/heads/master by this push:
     new ec11bb39 Support TCP heartbeat of client (#2098)
ec11bb39 is described below

commit ec11bb39400c2c48455c5f1647a8e651efbe1676
Author: Bright Chen <[email protected]>
AuthorDate: Wed Apr 26 15:45:56 2023 +0800

    Support TCP heartbeat of client (#2098)
    
    * support TCP heartbeat of client
    
    * optimize keepalive code & add UT
    
    * optimize keepalive code
    
    * fix keepalive UT
    
    * use PLOG instead of LOG
---
 src/brpc/input_messenger.cpp  |  40 +++++
 src/brpc/socket.cpp           | 131 +++++++++++++-
 src/brpc/socket.h             |  25 +++
 test/brpc_socket_unittest.cpp | 387 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 575 insertions(+), 8 deletions(-)

diff --git a/src/brpc/input_messenger.cpp b/src/brpc/input_messenger.cpp
index f33e626c..699f080c 100644
--- a/src/brpc/input_messenger.cpp
+++ b/src/brpc/input_messenger.cpp
@@ -53,6 +53,18 @@ DEFINE_bool(log_connection_close, false,
             "Print log when remote side closes the connection");
 BRPC_VALIDATE_GFLAG(log_connection_close, PassValidate);
 
+DEFINE_bool(socket_keepalive, false,
+            "Enable keepalive of sockets if this value is true");
+
+DEFINE_int32(socket_keepalive_idle_s, -1,
+             "Set idle time of sockets before keepalive if this value is 
positive");
+
+DEFINE_int32(socket_keepalive_interval_s, -1,
+             "Set interval of sockets between keepalives if this value is 
positive");
+
+DEFINE_int32(socket_keepalive_count, -1,
+             "Set number of keepalives of sockets before close if this value 
is positive");
+
 DECLARE_bool(usercode_in_pthread);
 DECLARE_uint64(max_body_size);
 
@@ -474,6 +486,15 @@ int InputMessenger::Create(const butil::EndPoint& 
remote_side,
     options.user = this;
     options.on_edge_triggered_events = OnNewMessages;
     options.health_check_interval_s = health_check_interval_s;
+    if (FLAGS_socket_keepalive) {
+        options.keepalive_options = std::make_shared<SocketKeepaliveOptions>();
+        options.keepalive_options->keepalive_idle_s
+            = FLAGS_socket_keepalive_idle_s;
+        options.keepalive_options->keepalive_interval_s
+            = FLAGS_socket_keepalive_interval_s;
+        options.keepalive_options->keepalive_count
+            = FLAGS_socket_keepalive_count;
+    }
     return Socket::Create(options, id);
 }
 
@@ -489,6 +510,25 @@ int InputMessenger::Create(SocketOptions options, 
SocketId* id) {
 #endif
         options.on_edge_triggered_events = OnNewMessages;
     }
+    // Enable keepalive by options or Gflag.
+    // Priority: options > Gflag.
+    if (options.keepalive_options || FLAGS_socket_keepalive) {
+        if (!options.keepalive_options) {
+            options.keepalive_options = 
std::make_shared<SocketKeepaliveOptions>();
+        }
+        if (options.keepalive_options->keepalive_idle_s <= 0) {
+            options.keepalive_options->keepalive_idle_s
+                = FLAGS_socket_keepalive_idle_s;
+        }
+        if (options.keepalive_options->keepalive_interval_s <= 0) {
+            options.keepalive_options->keepalive_interval_s
+                = FLAGS_socket_keepalive_interval_s;
+        }
+        if (options.keepalive_options->keepalive_count <= 0) {
+            options.keepalive_options->keepalive_count
+                = FLAGS_socket_keepalive_count;
+        }
+    }
     return Socket::Create(options, id);
 }
 
diff --git a/src/brpc/socket.cpp b/src/brpc/socket.cpp
index c603b0ec..259e09ca 100644
--- a/src/brpc/socket.cpp
+++ b/src/brpc/socket.cpp
@@ -557,28 +557,28 @@ int Socket::ResetFileDescriptor(int fd) {
     // OK to fail, namely unix domain socket does not support this.
     butil::make_no_delay(fd);
     if (_tos > 0 &&
-        setsockopt(fd, IPPROTO_IP, IP_TOS, &_tos, sizeof(_tos)) < 0) {
-        PLOG(FATAL) << "Fail to set tos of fd=" << fd << " to " << _tos;
+        setsockopt(fd, IPPROTO_IP, IP_TOS, &_tos, sizeof(_tos)) != 0) {
+        PLOG(ERROR) << "Fail to set tos of fd=" << fd << " to " << _tos;
     }
 
     if (FLAGS_socket_send_buffer_size > 0) {
         int buff_size = FLAGS_socket_send_buffer_size;
-        socklen_t size = sizeof(buff_size);
-        if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buff_size, size) != 0) {
-            PLOG(FATAL) << "Fail to set sndbuf of fd=" << fd << " to " 
+        if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buff_size, 
sizeof(buff_size)) != 0) {
+            PLOG(ERROR) << "Fail to set sndbuf of fd=" << fd << " to "
                         << buff_size;
         }
     }
 
     if (FLAGS_socket_recv_buffer_size > 0) {
         int buff_size = FLAGS_socket_recv_buffer_size;
-        socklen_t size = sizeof(buff_size);
-        if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buff_size, size) != 0) {
-            PLOG(FATAL) << "Fail to set rcvbuf of fd=" << fd << " to " 
+        if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buff_size, 
sizeof(buff_size)) != 0) {
+            PLOG(ERROR) << "Fail to set rcvbuf of fd=" << fd << " to "
                         << buff_size;
         }
     }
 
+    EnableKeepaliveIfNeeded(fd);
+
     if (_on_edge_triggered_events) {
         if (GetGlobalEventDispatcher(fd).AddConsumer(id(), fd) != 0) {
             PLOG(ERROR) << "Fail to add SocketId=" << id() 
@@ -590,6 +590,69 @@ int Socket::ResetFileDescriptor(int fd) {
     return 0;
 }
 
+void Socket::EnableKeepaliveIfNeeded(int fd) {
+    if (!_keepalive_options) {
+        return;
+    }
+
+    int keepalive = 1;
+    if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keepalive,
+                   sizeof(keepalive)) != 0) {
+        PLOG(ERROR) << "Fail to set keepalive of fd=" << fd;
+        return;
+    }
+
+#if defined(OS_LINUX)
+    if (_keepalive_options->keepalive_idle_s > 0) {
+        if (setsockopt(fd, SOL_TCP, TCP_KEEPIDLE,
+                       &_keepalive_options->keepalive_idle_s,
+                       sizeof(_keepalive_options->keepalive_idle_s)) != 0) {
+            PLOG(ERROR) << "Fail to set keepidle of fd=" << fd;
+        }
+    }
+
+    if (_keepalive_options->keepalive_interval_s > 0) {
+        if (setsockopt(fd, SOL_TCP, TCP_KEEPINTVL,
+                       &_keepalive_options->keepalive_interval_s,
+                       sizeof(_keepalive_options->keepalive_interval_s)) != 0) 
{
+            PLOG(ERROR) << "Fail to set keepintvl of fd=" << fd;
+        }
+    }
+
+    if (_keepalive_options->keepalive_count > 0) {
+        if (setsockopt(fd, SOL_TCP, TCP_KEEPCNT,
+                       &_keepalive_options->keepalive_count,
+                       sizeof(_keepalive_options->keepalive_count)) != 0) {
+            PLOG(ERROR) << "Fail to set keepcnt of fd=" << fd;
+        }
+    }
+#elif defined(OS_MACOSX)
+    if (_keepalive_options->keepalive_idle_s > 0) {
+        if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE,
+                       &_keepalive_options->keepalive_idle_s,
+                       sizeof(_keepalive_options->keepalive_idle_s)) != 0) {
+            PLOG(ERROR) << "Fail to set keepidle of fd=" << fd;
+        }
+    }
+
+    if (_keepalive_options->keepalive_interval_s > 0) {
+        if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL,
+                       &_keepalive_options->keepalive_interval_s,
+                       sizeof(_keepalive_options->keepalive_interval_s)) != 0) 
{
+            PLOG(ERROR) << "Fail to set keepintvl of fd=" << fd;
+        }
+    }
+
+    if (_keepalive_options->keepalive_count > 0) {
+        if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT,
+                       &_keepalive_options->keepalive_count,
+                       sizeof(_keepalive_options->keepalive_count)) != 0) {
+            PLOG(ERROR) << "Fail to set keepcnt of fd=" << fd;
+        }
+    }
+#endif
+}
+
 // SocketId = 32-bit version + 32-bit slot.
 //   version: from version part of _versioned_nref, must be an EVEN number.
 //   slot: designated by ResourcePool.
@@ -676,6 +739,7 @@ int Socket::Create(const SocketOptions& options, SocketId* 
id) {
     }
     m->_last_writetime_us.store(cpuwide_now, butil::memory_order_relaxed);
     m->_unwritten_bytes.store(0, butil::memory_order_relaxed);
+    m->_keepalive_options = options.keepalive_options;
     CHECK(NULL == m->_write_head.load(butil::memory_order_relaxed));
     // Must be last one! Internal fields of this Socket may be access
     // just after calling ResetFileDescriptor.
@@ -2268,6 +2332,57 @@ void Socket::DebugSocket(std::ostream& os, SocketId id) {
         Print(os, ptr->_ssl_session, "\n  ");
         os << "\n}";
     }
+
+    {
+        int keepalive = 0;
+        socklen_t len = sizeof(keepalive);
+        if (getsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keepalive, &len) == 0) {
+            os << "\nkeepalive=" << keepalive;
+        }
+    }
+
+    {
+        int keepidle = 0;
+        socklen_t len = sizeof(keepidle);
+#if defined(OS_MACOSX)
+        if (getsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &keepidle, &len) == 0) {
+            os << "\ntcp_keepalive_time=" << keepidle;
+        }
+#elif defined(OS_LINUX)
+        if (getsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &keepidle, &len) == 0) {
+            os << "\ntcp_keepalive_time=" << keepidle;
+        }
+#endif
+    }
+
+    {
+        int keepintvl = 0;
+        socklen_t len = sizeof(keepintvl);
+#if defined(OS_MACOSX)
+        if (getsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &keepintvl, &len) == 0) 
{
+            os << "\ntcp_keepalive_intvl=" << keepintvl;
+        }
+#elif defined(OS_LINUX)
+        if (getsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &keepintvl, &len) == 0) {
+            os << "\ntcp_keepalive_intvl=" << keepintvl;
+        }
+#endif
+    }
+
+    {
+        int keepcnt = 0;
+        socklen_t len = sizeof(keepcnt);
+#if defined(OS_MACOSX)
+        if (getsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &keepcnt, &len) == 0) {
+            os << "\ntcp_keepalive_probes=" << keepcnt;
+        }
+#elif defined(OS_LINUX)
+        if (getsockopt(fd, SOL_TCP, TCP_KEEPCNT, &keepcnt, &len) == 0) {
+            os << "\ntcp_keepalive_probes=" << keepcnt;
+        }
+#endif
+    }
+
 #if defined(OS_MACOSX)
     struct tcp_connection_info ti;
     socklen_t len = sizeof(ti);
diff --git a/src/brpc/socket.h b/src/brpc/socket.h
index 6f710ee2..cc77168f 100644
--- a/src/brpc/socket.h
+++ b/src/brpc/socket.h
@@ -173,6 +173,20 @@ struct SocketSSLContext {
     std::string sni_name;       // useful for clients
 };
 
+struct SocketKeepaliveOptions {
+    SocketKeepaliveOptions()
+        : keepalive_idle_s(-1)
+        , keepalive_interval_s(-1)
+        , keepalive_count(-1)
+        {}
+    // Start keeplives after this period.
+    int keepalive_idle_s;
+    // Interval between keepalives.
+    int keepalive_interval_s;
+    // Number of keepalives before death.
+    int keepalive_count;
+};
+
 // TODO: Comment fields
 struct SocketOptions {
     SocketOptions();
@@ -198,6 +212,10 @@ struct SocketOptions {
     std::shared_ptr<AppConnect> app_connect;
     // The created socket will set parsing_context with this value.
     Destroyable* initial_parsing_context;
+
+    // Socket keepalive related options.
+    // Refer to `SocketKeepaliveOptions' for details.
+    std::shared_ptr<SocketKeepaliveOptions> keepalive_options;
 };
 
 // Abstractions on reading from and writing into file descriptors.
@@ -612,6 +630,8 @@ friend void DereferenceSocket(Socket*);
 
     int ResetFileDescriptor(int fd);
 
+    void EnableKeepaliveIfNeeded(int fd);
+
     // Wait until nref hits `expected_nref' and reset some internal resources.
     int WaitAndReset(int32_t expected_nref);
 
@@ -873,6 +893,11 @@ private:
     butil::atomic<int64_t> _total_streams_unconsumed_size;
 
     butil::atomic<int64_t> _ninflight_app_health_check;
+
+    // Socket keepalive related options.
+    // Refer to `SocketKeepaliveOptions' for details.
+    // non-NULL means that keepalive is on.
+    std::shared_ptr<SocketKeepaliveOptions> _keepalive_options;
 };
 
 } // namespace brpc
diff --git a/test/brpc_socket_unittest.cpp b/test/brpc_socket_unittest.cpp
index 1011c397..10ee988c 100644
--- a/test/brpc_socket_unittest.cpp
+++ b/test/brpc_socket_unittest.cpp
@@ -28,6 +28,7 @@
 #include "butil/time.h"
 #include "butil/macros.h"
 #include "butil/fd_utility.h"
+#include <butil/fd_guard.h>
 #include "bthread/unstable.h"
 #include "bthread/task_control.h"
 #include "brpc/socket.h"
@@ -44,6 +45,7 @@
 #if defined(OS_MACOSX)
 #include <sys/event.h>
 #endif
+#include <netinet/tcp.h>
 
 #define CONNECT_IN_KEEPWRITE 1;
 
@@ -53,6 +55,10 @@ extern TaskControl* g_task_control;
 
 namespace brpc {
 DECLARE_int32(health_check_interval);
+DECLARE_bool(socket_keepalive);
+DECLARE_int32(socket_keepalive_idle_s);
+DECLARE_int32(socket_keepalive_interval_s);
+DECLARE_int32(socket_keepalive_count);
 }
 
 void EchoProcessHuluRequest(brpc::InputMessageBase* msg_base);
@@ -1016,3 +1022,384 @@ TEST_F(SocketTest, multi_threaded_write_perf) {
     ASSERT_EQ((brpc::Socket*)NULL, global_sock);
     close(fds[0]);
 }
+
+void GetKeepaliveValue(int fd,
+                       int& keepalive,
+                       int& keepalive_idle,
+                       int& keepalive_interval,
+                       int& keepalive_count) {
+    {
+        socklen_t len = sizeof(keepalive);
+        ASSERT_EQ(0, getsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keepalive, 
&len));
+
+    }
+
+    {
+        socklen_t len = sizeof(keepalive_idle);
+#if defined(OS_MACOSX)
+        ASSERT_EQ(0, getsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, 
&keepalive_idle, &len));
+#elif defined(OS_LINUX)
+        ASSERT_EQ(0, getsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &keepalive_idle, 
&len));
+#endif
+    }
+
+    {
+        socklen_t len = sizeof(keepalive_interval);
+#if defined(OS_MACOSX)
+        ASSERT_EQ(0, getsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, 
&keepalive_interval, &len));
+#elif defined(OS_LINUX)
+        ASSERT_EQ(0, getsockopt(fd, SOL_TCP, TCP_KEEPINTVL, 
&keepalive_interval, &len));
+#endif
+    }
+
+    {
+        socklen_t len = sizeof(keepalive_count);
+#if defined(OS_MACOSX)
+        ASSERT_EQ(0, getsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, 
&keepalive_count, &len));
+#elif defined(OS_LINUX)
+        ASSERT_EQ(0, getsockopt(fd, SOL_TCP, TCP_KEEPCNT, &keepalive_count, 
&len));
+#endif
+    }
+}
+
+void CheckNoKeepalive(int fd) {
+    int keepalive = -1;
+    socklen_t len = sizeof(keepalive);
+    ASSERT_EQ(0, getsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keepalive, &len));
+    ASSERT_EQ(0, keepalive);
+}
+
+void CheckKeepalive(int fd,
+                    bool expected_keepalive,
+                    int expected_keepalive_idle,
+                    int expected_keepalive_interval,
+                    int expected_keepalive_count) {
+
+    int keepalive = -1;
+    int keepalive_idle = -1;
+    int keepalive_interval = -1;
+    int keepalive_count = -1;
+    GetKeepaliveValue(fd, keepalive, keepalive_idle,
+                      keepalive_interval, keepalive_count);
+    if (expected_keepalive) {
+        ASSERT_LT(0, keepalive);
+    } else {
+        ASSERT_EQ(0, keepalive);
+        return;
+    }
+    ASSERT_EQ(expected_keepalive_idle, keepalive_idle);
+    ASSERT_EQ(expected_keepalive_interval, keepalive_interval);
+    ASSERT_EQ(expected_keepalive_count, keepalive_count);
+}
+
+TEST_F(SocketTest, keepalive) {
+    int default_keepalive = 0;
+    int default_keepalive_idle = 0;
+    int default_keepalive_interval = 0;
+    int default_keepalive_count = 0;
+    {
+        butil::fd_guard sockfd(socket(AF_INET, SOCK_STREAM, 0));
+        GetKeepaliveValue(sockfd,
+                          default_keepalive,
+                          default_keepalive_idle,
+                          default_keepalive_interval,
+                          default_keepalive_count);
+    }
+
+    // Disable keepalive.
+    {
+        butil::fd_guard sockfd(socket(AF_INET, SOCK_STREAM, 0));
+        brpc::SocketOptions options;
+        options.fd = sockfd;
+        brpc::SocketId id;
+        ASSERT_EQ(0, brpc::Socket::Create(options, &id));
+        brpc::SocketUniquePtr ptr;
+        ASSERT_EQ(0, brpc::Socket::Address(id, &ptr));
+        CheckNoKeepalive(ptr->fd());
+    }
+
+    int keepalive_idle = 1;
+    int keepalive_interval = 2;
+    int keepalive_count = 2;
+    // Enable keepalive.
+    {
+        butil::fd_guard sockfd(socket(AF_INET, SOCK_STREAM, 0));
+        brpc::SocketOptions options;
+        options.fd = sockfd;
+        options.keepalive_options = 
std::make_shared<brpc::SocketKeepaliveOptions>();
+        brpc::SocketId id;
+        ASSERT_EQ(0, brpc::Socket::Create(options, &id));
+        brpc::SocketUniquePtr ptr;
+        ASSERT_EQ(0, brpc::Socket::Address(id, &ptr));
+        CheckKeepalive(ptr->fd(),
+                       true,
+                       default_keepalive_idle,
+                       default_keepalive_interval,
+                       default_keepalive_count);
+    }
+
+    // Enable keepalive and set keepalive idle.
+    {
+        butil::fd_guard sockfd(socket(AF_INET, SOCK_STREAM, 0));
+        brpc::SocketOptions options;
+        options.fd = sockfd;
+        options.keepalive_options = 
std::make_shared<brpc::SocketKeepaliveOptions>();
+        options.keepalive_options->keepalive_idle_s
+            = keepalive_idle;
+        brpc::SocketId id;
+        ASSERT_EQ(0, brpc::Socket::Create(options, &id));
+        brpc::SocketUniquePtr ptr;
+        ASSERT_EQ(0, brpc::Socket::Address(id, &ptr));
+        CheckKeepalive(ptr->fd(),
+                       true,
+                       keepalive_idle,
+                       default_keepalive_interval,
+                       default_keepalive_count);
+    }
+
+    // Enable keepalive and set keepalive interval.
+    {
+        butil::fd_guard sockfd(socket(AF_INET, SOCK_STREAM, 0));
+        brpc::SocketOptions options;
+        options.fd = sockfd;
+        options.keepalive_options = 
std::make_shared<brpc::SocketKeepaliveOptions>();
+        options.keepalive_options->keepalive_interval_s
+            = keepalive_interval;
+        brpc::SocketId id;
+        ASSERT_EQ(0, brpc::Socket::Create(options, &id));
+        brpc::SocketUniquePtr ptr;
+        ASSERT_EQ(0, brpc::Socket::Address(id, &ptr));
+        CheckKeepalive(ptr->fd(),
+                       true,
+                       default_keepalive_idle,
+                       keepalive_interval,
+                       default_keepalive_count);
+    }
+
+    // Enable keepalive and set keepalive count.
+    {
+        butil::fd_guard sockfd(socket(AF_INET, SOCK_STREAM, 0));
+        brpc::SocketOptions options;
+        options.fd = sockfd;
+        options.keepalive_options = 
std::make_shared<brpc::SocketKeepaliveOptions>();
+        options.keepalive_options->keepalive_count
+            = keepalive_count;
+        brpc::SocketId id;
+        ASSERT_EQ(0, brpc::Socket::Create(options, &id));
+        brpc::SocketUniquePtr ptr;
+        ASSERT_EQ(0, brpc::Socket::Address(id, &ptr));
+        CheckKeepalive(ptr->fd(),
+                       true,
+                       default_keepalive_idle,
+                       default_keepalive_interval,
+                       keepalive_count);
+    }
+
+    // Enable keepalive and set keepalive idle, interval, count.
+    {
+        butil::fd_guard sockfd(socket(AF_INET, SOCK_STREAM, 0));
+        brpc::SocketOptions options;
+        options.fd = sockfd;
+        options.keepalive_options = 
std::make_shared<brpc::SocketKeepaliveOptions>();
+        options.keepalive_options->keepalive_idle_s
+            = keepalive_idle;
+        options.keepalive_options->keepalive_interval_s
+            = keepalive_interval;
+        options.keepalive_options->keepalive_count
+            = keepalive_count;
+        brpc::SocketId id;
+        ASSERT_EQ(0, brpc::Socket::Create(options, &id));
+        brpc::SocketUniquePtr ptr;
+        ASSERT_EQ(0, brpc::Socket::Address(id, &ptr));
+        CheckKeepalive(ptr->fd(),
+                       true,
+                       keepalive_idle,
+                       keepalive_interval,
+                       keepalive_count);
+    }
+}
+
+
+TEST_F(SocketTest, keepalive_input_message) {
+    int default_keepalive = 0;
+    int default_keepalive_idle = 0;
+    int default_keepalive_interval = 0;
+    int default_keepalive_count = 0;
+    {
+        butil::fd_guard sockfd(socket(AF_INET, SOCK_STREAM, 0));
+        GetKeepaliveValue(sockfd,
+                          default_keepalive,
+                          default_keepalive_idle,
+                          default_keepalive_interval,
+                          default_keepalive_count);
+    }
+
+    // Disable keepalive.
+    {
+        butil::fd_guard sockfd(socket(AF_INET, SOCK_STREAM, 0));
+        brpc::SocketOptions options;
+        options.fd = sockfd;
+        brpc::SocketId id;
+        ASSERT_EQ(0, brpc::get_or_new_client_side_messenger()
+            ->Create(options, &id));
+        brpc::SocketUniquePtr ptr;
+        ASSERT_EQ(0, brpc::Socket::Address(id, &ptr));
+        CheckNoKeepalive(ptr->fd());
+    }
+
+    // Enable keepalive.
+    brpc::FLAGS_socket_keepalive = true;
+    {
+        butil::fd_guard sockfd(socket(AF_INET, SOCK_STREAM, 0));
+        brpc::SocketOptions options;
+        options.fd = sockfd;
+        brpc::SocketId id;
+        ASSERT_EQ(0, brpc::get_or_new_client_side_messenger()
+            ->Create(options, &id));
+        brpc::SocketUniquePtr ptr;
+        ASSERT_EQ(0, brpc::Socket::Address(id, &ptr));
+        CheckKeepalive(ptr->fd(),
+                       true,
+                       default_keepalive_idle,
+                       default_keepalive_interval,
+                       default_keepalive_count);
+    }
+
+    // Enable keepalive and set keepalive idle.
+    brpc::FLAGS_socket_keepalive_idle_s = 10;
+    {
+        butil::fd_guard sockfd(socket(AF_INET, SOCK_STREAM, 0));
+        brpc::SocketOptions options;
+        options.fd = sockfd;
+        brpc::SocketId id;
+        ASSERT_EQ(0, brpc::get_or_new_client_side_messenger()
+            ->Create(options, &id));
+        brpc::SocketUniquePtr ptr;
+        ASSERT_EQ(0, brpc::Socket::Address(id, &ptr));
+        CheckKeepalive(ptr->fd(),
+                       true,
+                       brpc::FLAGS_socket_keepalive_idle_s,
+                       default_keepalive_interval,
+                       default_keepalive_count);
+    }
+
+    // Enable keepalive and set keepalive idle, interval.
+    brpc::FLAGS_socket_keepalive_interval_s = 10;
+    {
+        butil::fd_guard sockfd(socket(AF_INET, SOCK_STREAM, 0));
+        brpc::SocketOptions options;
+        options.fd = sockfd;
+        brpc::SocketId id;
+        ASSERT_EQ(0, brpc::get_or_new_client_side_messenger()
+            ->Create(options, &id));
+        brpc::SocketUniquePtr ptr;
+        ASSERT_EQ(0, brpc::Socket::Address(id, &ptr));
+        CheckKeepalive(ptr->fd(),
+                       true,
+                       brpc::FLAGS_socket_keepalive_idle_s,
+                       brpc::FLAGS_socket_keepalive_interval_s,
+                       default_keepalive_count);
+    }
+
+    // Enable keepalive and set keepalive idle, interval, count.
+    brpc::FLAGS_socket_keepalive_count = 10;
+    {
+        butil::fd_guard sockfd(socket(AF_INET, SOCK_STREAM, 0));
+        brpc::SocketOptions options;
+        options.fd = sockfd;
+        brpc::SocketId id;
+        ASSERT_EQ(0, brpc::get_or_new_client_side_messenger()
+            ->Create(options, &id));
+        brpc::SocketUniquePtr ptr;
+        ASSERT_EQ(0, brpc::Socket::Address(id, &ptr));
+        CheckKeepalive(ptr->fd(),
+                       true,
+                       brpc::FLAGS_socket_keepalive_idle_s,
+                       brpc::FLAGS_socket_keepalive_interval_s,
+                       brpc::FLAGS_socket_keepalive_count);
+    }
+
+    // Options of keepalive set by user have priority over Gflags.
+    int keepalive_idle = 2;
+    int keepalive_interval = 2;
+    int keepalive_count = 2;
+    {
+        butil::fd_guard sockfd(socket(AF_INET, SOCK_STREAM, 0));
+        brpc::SocketOptions options;
+        options.fd = sockfd;
+        options.keepalive_options = 
std::make_shared<brpc::SocketKeepaliveOptions>();
+        options.keepalive_options->keepalive_idle_s
+            = keepalive_idle;
+        brpc::SocketId id;
+        ASSERT_EQ(0, brpc::get_or_new_client_side_messenger()
+            ->Create(options, &id));
+        brpc::SocketUniquePtr ptr;
+        ASSERT_EQ(0, brpc::Socket::Address(id, &ptr));
+        CheckKeepalive(ptr->fd(),
+                       true,
+                       keepalive_idle,
+                       brpc::FLAGS_socket_keepalive_interval_s,
+                       brpc::FLAGS_socket_keepalive_count);
+    }
+
+    {
+        butil::fd_guard sockfd(socket(AF_INET, SOCK_STREAM, 0));
+        brpc::SocketOptions options;
+        options.fd = sockfd;
+        options.keepalive_options = 
std::make_shared<brpc::SocketKeepaliveOptions>();
+        options.keepalive_options->keepalive_interval_s
+            = keepalive_interval;
+        brpc::SocketId id;
+        ASSERT_EQ(0, brpc::get_or_new_client_side_messenger()
+            ->Create(options, &id));
+        brpc::SocketUniquePtr ptr;
+        ASSERT_EQ(0, brpc::Socket::Address(id, &ptr));
+        CheckKeepalive(ptr->fd(),
+                       true,
+                       brpc::FLAGS_socket_keepalive_idle_s,
+                       keepalive_interval,
+                       brpc::FLAGS_socket_keepalive_count);
+    }
+
+    {
+        butil::fd_guard sockfd(socket(AF_INET, SOCK_STREAM, 0));
+        brpc::SocketOptions options;
+        options.fd = sockfd;
+        options.keepalive_options = 
std::make_shared<brpc::SocketKeepaliveOptions>();
+        options.keepalive_options->keepalive_count
+            = keepalive_count;
+        brpc::SocketId id;
+        ASSERT_EQ(0, brpc::get_or_new_client_side_messenger()
+            ->Create(options, &id));
+        brpc::SocketUniquePtr ptr;
+        ASSERT_EQ(0, brpc::Socket::Address(id, &ptr));
+        CheckKeepalive(ptr->fd(),
+                       true,
+                       brpc::FLAGS_socket_keepalive_idle_s,
+                       brpc::FLAGS_socket_keepalive_interval_s,
+                       keepalive_count);
+    }
+
+    {
+        butil::fd_guard sockfd(socket(AF_INET, SOCK_STREAM, 0));
+        brpc::SocketOptions options;
+        options.fd = sockfd;
+        options.keepalive_options = 
std::make_shared<brpc::SocketKeepaliveOptions>();
+        options.keepalive_options->keepalive_idle_s
+            = keepalive_idle;
+        options.keepalive_options->keepalive_interval_s
+            = keepalive_interval;
+        options.keepalive_options->keepalive_count
+            = keepalive_count;
+        brpc::SocketId id;
+        ASSERT_EQ(0, brpc::get_or_new_client_side_messenger()
+            ->Create(options, &id));
+        brpc::SocketUniquePtr ptr;
+        ASSERT_EQ(0, brpc::Socket::Address(id, &ptr));
+        CheckKeepalive(ptr->fd(),
+                       true,
+                       keepalive_idle,
+                       keepalive_interval,
+                       keepalive_count);
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to