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 ce585811 feat:Support for TLSv1.3 (#3319)
ce585811 is described below

commit ce585811885b12a2d905d2a90640689de2efe71f
Author: neilxxxxx <[email protected]>
AuthorDate: Sun Jun 14 11:45:55 2026 +0800

    feat:Support for TLSv1.3 (#3319)
    
    * feat:Support for TLSv1.3
    
    * Align other UTs in this file
    
    ---------
    
    Co-authored-by: lairongzeng <[email protected]>
---
 src/brpc/details/ssl_helper.cpp |  10 +++-
 src/brpc/details/ssl_helper.h   |   1 +
 src/brpc/ssl_options.cpp        |   2 +-
 src/brpc/ssl_options.h          |   4 +-
 test/brpc_ssl_unittest.cpp      | 118 ++++++++++++++++++----------------------
 5 files changed, 67 insertions(+), 68 deletions(-)

diff --git a/src/brpc/details/ssl_helper.cpp b/src/brpc/details/ssl_helper.cpp
index 322b9cc3..0e31f14b 100644
--- a/src/brpc/details/ssl_helper.cpp
+++ b/src/brpc/details/ssl_helper.cpp
@@ -86,6 +86,8 @@ static int ParseSSLProtocols(const std::string& str_protocol) 
{
             protocol_flag |= TLSv1_1;
         } else if (strncasecmp(protocol.data(), "TLSv1.2", protocol.size()) == 
0) {
             protocol_flag |= TLSv1_2;
+        } else if (strncasecmp(protocol.data(), "TLSv1.3", protocol.size()) == 
0) {
+            protocol_flag |= TLSv1_3;
         } else {
             LOG(ERROR) << "Unknown SSL protocol=" << protocol;
             return -1;
@@ -443,6 +445,12 @@ static int SetSSLOptions(SSL_CTX* ctx, const std::string& 
ciphers,
         ssloptions |= SSL_OP_NO_TLSv1_2;
     }
 #endif  // SSL_OP_NO_TLSv1_2
+
+#ifdef SSL_OP_NO_TLSv1_3
+    if (!(protocols & TLSv1_3)) {
+        ssloptions |= SSL_OP_NO_TLSv1_3;
+    }
+#endif  // SSL_OP_NO_TLSv1_3
     SSL_CTX_set_options(ctx, ssloptions);
 
     long sslmode = SSL_MODE_ENABLE_PARTIAL_WRITE
@@ -585,7 +593,7 @@ SSL_CTX* CreateServerSSLContext(const std::string& 
certificate,
         return NULL;
     }
 
-    int protocols = TLSv1 | TLSv1_1 | TLSv1_2;
+    int protocols = TLSv1 | TLSv1_1 | TLSv1_2 | TLSv1_3;
     if (!options.disable_ssl3) {
         protocols |= SSLv3;
     }
diff --git a/src/brpc/details/ssl_helper.h b/src/brpc/details/ssl_helper.h
index da126b39..a9b8736b 100644
--- a/src/brpc/details/ssl_helper.h
+++ b/src/brpc/details/ssl_helper.h
@@ -53,6 +53,7 @@ enum SSLProtocol {
     TLSv1 = 1 << 1,
     TLSv1_1 = 1 << 2,
     TLSv1_2 = 1 << 3,
+    TLSv1_3 = 1 << 4,
 };
 
 struct FreeSSLCTX {
diff --git a/src/brpc/ssl_options.cpp b/src/brpc/ssl_options.cpp
index 748749ae..efeab5c4 100644
--- a/src/brpc/ssl_options.cpp
+++ b/src/brpc/ssl_options.cpp
@@ -27,7 +27,7 @@ VerifyOptions::VerifyOptions()
 
 ChannelSSLOptions::ChannelSSLOptions()
     : ciphers("DEFAULT")
-    , protocols("TLSv1, TLSv1.1, TLSv1.2")
+    , protocols("TLSv1, TLSv1.1, TLSv1.2, TLSv1.3")
 {}
 
 ServerSSLOptions::ServerSSLOptions()
diff --git a/src/brpc/ssl_options.h b/src/brpc/ssl_options.h
index 8ddda248..3fdb1e85 100644
--- a/src/brpc/ssl_options.h
+++ b/src/brpc/ssl_options.h
@@ -79,8 +79,8 @@ struct ChannelSSLOptions {
     std::string ciphers;
 
     // SSL protocols used for SSL handshake, separated by comma.
-    // Available protocols: SSLv3, TLSv1, TLSv1.1, TLSv1.2
-    // Default: TLSv1, TLSv1.1, TLSv1.2
+    // Available protocols: SSLv3, TLSv1, TLSv1.1, TLSv1.2, TLSv1.3
+    // Default: TLSv1, TLSv1.1, TLSv1.2, TLSv1.3
     std::string protocols;
 
     // When set, fill this into the SNI extension field during handshake,
diff --git a/test/brpc_ssl_unittest.cpp b/test/brpc_ssl_unittest.cpp
index e7545a0c..00fe705e 100644
--- a/test/brpc_ssl_unittest.cpp
+++ b/test/brpc_ssl_unittest.cpp
@@ -35,6 +35,7 @@
 #include "brpc/channel.h"
 #include "brpc/socket_map.h"
 #include "brpc/controller.h"
+#include "brpc/details/ssl_helper.h"
 #include "echo.pb.h"
 
 namespace brpc {
@@ -498,78 +499,67 @@ TEST_F(SSLTest, ssl_perf) {
     close(servfd);
 }
 
-struct AbruptCloseArgs { int listenfd; };
-
-static void* abrupt_close_server(void* arg) {
-    AbruptCloseArgs* a = (AbruptCloseArgs*)arg;
-    int connfd = accept(a->listenfd, NULL, NULL);
-    if (connfd < 0) return NULL;
-    SSL_CTX* ctx = brpc::CreateServerSSLContext(
-        "cert1.crt", "cert1.key", brpc::SSLOptions(), NULL, NULL);
-    SSL* ssl = brpc::CreateSSLSession(ctx, 0, connfd, true);
-    if (ssl) { SSL_do_handshake(ssl); SSL_free(ssl); }
-    close(connfd);
+
+#ifdef TLS1_3_VERSION
+
+void* tls13_do_handshake(void* arg) {
+    SSL* ssl = (SSL*)arg;
+    EXPECT_EQ(1, SSL_do_handshake(ssl));
     return NULL;
 }
 
-TEST_F(SSLTest, ssl_unexpected_eof) {
-    // Verify that Socket::DoRead() returns -1 with errno=ESSL when the
-    // remote side closes the TCP connection without sending close_notify.
-    // Without the fix, DoRead() returns 0, causing error_code=0 to
-    // propagate to Controller::SetFailed() which triggers CHECK(false).
-
-    const int port = 5962;
-    butil::EndPoint ep(butil::IP_ANY, port);
+TEST_F(SSLTest, tls13_protocol_string) {
+    // Same style as ssl_perf: direct SSL handshake, no SocketMap / socket 
internals.
+    const butil::EndPoint ep(butil::IP_ANY, 8613);
     butil::fd_guard listenfd(butil::tcp_listen(ep));
     ASSERT_GT(listenfd, 0);
+    int clifd = tcp_connect(ep, NULL);
+    ASSERT_GT(clifd, 0);
+    int servfd = accept(listenfd, NULL, NULL);
+    ASSERT_GT(servfd, 0);
 
-    AbruptCloseArgs server_args = { listenfd };
-    pthread_t server_tid;
-    ASSERT_EQ(0, pthread_create(&server_tid, NULL, abrupt_close_server,
-                                &server_args));
-
-    brpc::Protocol dummy_protocol = {
-        brpc::policy::ParseRpcMessage, brpc::SerializeRequestDefault,
-        brpc::policy::PackRpcRequest, NULL, ProcessResponse,
-        NULL, NULL, NULL, brpc::CONNECTION_TYPE_ALL, "ssl_ut_eof"
-    };
-    ASSERT_EQ(0, RegisterProtocol((brpc::ProtocolType)31, dummy_protocol));
-
-    brpc::InputMessageHandler dummy_handler = {
-        dummy_protocol.parse, dummy_protocol.process_response,
-        NULL, NULL, dummy_protocol.name
-    };
-    brpc::InputMessenger messenger;
-    ASSERT_EQ(0, messenger.AddHandler(dummy_handler));
-
-    brpc::SocketOptions socket_options;
-    butil::EndPoint server_ep(butil::IP_ANY, port);
-    socket_options.remote_side = server_ep;
-    socket_options.connect_on_create = true;
-    // Do NOT set on_edge_triggered_events — we will call DoRead manually.
-    socket_options.user = &messenger;
-
-    brpc::ChannelSSLOptions ssl_options;
-    SSL_CTX* raw_ctx = brpc::CreateClientSSLContext(ssl_options);
-    ASSERT_NE(nullptr, raw_ctx);
-    std::shared_ptr<brpc::SocketSSLContext> ssl_ctx =
-        std::make_shared<brpc::SocketSSLContext>();
-    ssl_ctx->raw_ctx = raw_ctx;
-    socket_options.initial_ssl_ctx = ssl_ctx;
+    brpc::ChannelSSLOptions opt;
+    opt.protocols = "TLSv1.3";
+    SSL_CTX* cli_ctx = brpc::CreateClientSSLContext(opt);
+    ASSERT_NE(nullptr, cli_ctx);
+    SSL_CTX* serv_ctx =
+            brpc::CreateServerSSLContext("cert1.crt", "cert1.key",
+                                         brpc::SSLOptions(), NULL, NULL);
+    ASSERT_NE(nullptr, serv_ctx);
+    SSL* cli_ssl = brpc::CreateSSLSession(cli_ctx, 0, clifd, false);
+#if defined(SSL_CTRL_SET_TLSEXT_HOSTNAME) || defined(USE_MESALINK)
+    SSL_set_tlsext_host_name(cli_ssl, "localhost");
+#endif
+    SSL* serv_ssl = brpc::CreateSSLSession(serv_ctx, 0, servfd, true);
+    ASSERT_NE(nullptr, cli_ssl);
+    ASSERT_NE(nullptr, serv_ssl);
+    pthread_t cpid;
+    pthread_t spid;
+    ASSERT_EQ(0, pthread_create(&cpid, NULL, tls13_do_handshake, cli_ssl));
+    ASSERT_EQ(0, pthread_create(&spid, NULL, tls13_do_handshake, serv_ssl));
+    ASSERT_EQ(0, pthread_join(cpid, NULL));
+    ASSERT_EQ(0, pthread_join(spid, NULL));
 
-    brpc::SocketId socket_id;
-    ASSERT_EQ(0, brpc::Socket::Create(socket_options, &socket_id));
-    brpc::SocketUniquePtr ptr;
-    ASSERT_EQ(0, brpc::Socket::Address(socket_id, &ptr));
+    const char* version = SSL_get_version(cli_ssl);
+    ASSERT_TRUE(version != NULL);
+    EXPECT_STREQ("TLSv1.3", version) << "negotiated protocol=" << version;
 
-    // Wait for server to close the connection without close_notify.
-    pthread_join(server_tid, NULL);
-    usleep(50000);
+    SSL_free(cli_ssl);
+    SSL_free(serv_ssl);
+    SSL_CTX_free(cli_ctx);
+    SSL_CTX_free(serv_ctx);
+    close(clifd);
+    close(servfd);
+}
 
-    // DoRead should detect the unexpected EOF and return -1 with errno=ESSL.
-    ssize_t nr = ptr->DoRead(1024);
-    EXPECT_EQ(-1, nr);
-    EXPECT_EQ(brpc::ESSL, errno);
+#else  // TLS1_3_VERSION
 
-    ptr->SetFailed();
+TEST_F(SSLTest, tls13_protocol_string) {
+    brpc::ChannelSSLOptions opt;
+    opt.protocols = "TLSv1.3";
+    SSL_CTX* ctx = brpc::CreateClientSSLContext(opt);
+    ASSERT_TRUE(ctx != NULL);
+    SSL_CTX_free(ctx);
 }
+
+#endif  // TLS1_3_VERSION


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

Reply via email to