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 6f0a54a9 Allow enabled_protocols to name http, h2 and rdma_handshake 
(#3518)
6f0a54a9 is described below

commit 6f0a54a97e3979ff35fa65ebd7cbf07c236f08b3
Author: Bright Chen <[email protected]>
AuthorDate: Sat Sep 5 15:21:08 2026 +0800

    Allow enabled_protocols to name http, h2 and rdma_handshake (#3518)
---
 src/brpc/server.cpp           | 17 +++++++-----
 src/brpc/server.h             |  4 +++
 test/brpc_server_unittest.cpp | 61 ++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 74 insertions(+), 8 deletions(-)

diff --git a/src/brpc/server.cpp b/src/brpc/server.cpp
index 0852cfc1..baf8b8fa 100644
--- a/src/brpc/server.cpp
+++ b/src/brpc/server.cpp
@@ -17,6 +17,7 @@
 
 
 #include <iomanip>
+#include <unordered_set>
 #include <arpa/inet.h>                              // inet_aton
 #include <fcntl.h>                                  // O_CREAT
 #include <sys/stat.h>                               // mkdir
@@ -619,7 +620,7 @@ BUTIL_FORCE_INLINE bool is_rdma_handshake_protocol(const 
char* name) {
 }
 
 Acceptor* Server::BuildAcceptor() {
-    std::set<std::string> whitelist;
+    std::unordered_set<std::string> whitelist;
     for (butil::StringSplitter sp(_options.enabled_protocols.c_str(), ' ');
          sp; ++sp) {
         std::string protocol(sp.field(), sp.length());
@@ -635,10 +636,13 @@ Acceptor* Server::BuildAcceptor() {
             // The protocol does not support server-side.
             continue;
         }
-        if (has_whitelist &&
+        // Erase whatever the exemptions below say. http, h2 and
+        // rdma_handshake are always served, but they are still
+        // valid names for the whitelist.
+        bool in_whitelist = (whitelist.erase(protocols[i].name) != 0);
+        if (has_whitelist && !in_whitelist &&
             !is_http_protocol(protocols[i].name) &&
-            !is_rdma_handshake_protocol(protocols[i].name) &&
-            !whitelist.erase(protocols[i].name)) {
+            !is_rdma_handshake_protocol(protocols[i].name)) {
             // the protocol is not allowed to serve.
             RPC_VLOG << "Skip protocol=" << protocols[i].name;
             continue;
@@ -659,9 +663,8 @@ Acceptor* Server::BuildAcceptor() {
     if (!whitelist.empty()) {
         std::ostringstream err;
         err << "ServerOptions.enabled_protocols has unknown protocols=`";
-        for (std::set<std::string>::const_iterator it = whitelist.begin();
-             it != whitelist.end(); ++it) {
-            err << *it << ' ';
+        for (const auto& protocol : whitelist) {
+            err << protocol << ' ';
         }
         err << '\'';
         delete acceptor;
diff --git a/src/brpc/server.h b/src/brpc/server.h
index 30846f75..276e8795 100644
--- a/src/brpc/server.h
+++ b/src/brpc/server.h
@@ -260,6 +260,10 @@ struct ServerOptions {
 
     // Only enable these protocols, separated by spaces.
     // All names inside must be valid, check protocols name in global.cpp
+    // http/h2 and rdma_handshake are served whatever this field says:
+    // the builtin services are only reachable over http/h2, and
+    // rdma_handshake is a transport level handshake dispatching no request.
+    // Naming them here is allowed and changes nothing.
     // Default: empty (all protocols)
     std::string enabled_protocols;
 
diff --git a/test/brpc_server_unittest.cpp b/test/brpc_server_unittest.cpp
index 4e64a851..19e2f9a7 100644
--- a/test/brpc_server_unittest.cpp
+++ b/test/brpc_server_unittest.cpp
@@ -460,11 +460,70 @@ TEST_F(ServerTest, 
only_allow_protocols_in_enabled_protocols) {
     stub.Echo(&cntl, &req, &res, nullptr);
     ASSERT_TRUE(cntl.Failed());
     ASSERT_TRUE(cntl.ErrorText().find("Got EOF of ") != std::string::npos);
-    
+
     ASSERT_EQ(0, server.Stop(0));
     ASSERT_EQ(0, server.Join());
 }
 
+// http, h2 and rdma_handshake are served whatever enabled_protocols says, but
+// naming them in it used to make Start() fail: the exemption was tested
+// before whitelist.erase() and `&&' short-circuited it, so the names survived
+// into the leftover check and came back as "unknown protocols=`http '".
+TEST_F(ServerTest, enabled_protocols_can_name_always_enabled_protocols) {
+    std::string cases[] = {
+        "baidu_std http",
+        "baidu_std h2",
+        "baidu_std rdma_handshake",
+        "baidu_std http h2 rdma_handshake",
+    };
+    for (size_t i = 0; i < arraysize(cases); ++i) {
+        brpc::Server server;
+        EchoServiceImpl echo_svc;
+        ASSERT_EQ(0, server.AddService(
+                      &echo_svc, brpc::SERVER_DOESNT_OWN_SERVICE));
+        brpc::ServerOptions opt;
+        opt.enabled_protocols = cases[i];
+        ASSERT_EQ(0, server.Start("127.0.0.1:0", &opt)) << cases[i];
+        butil::EndPoint ep = server.listen_address();
+
+        brpc::ChannelOptions copt;
+        brpc::Controller cntl;
+        test::EchoRequest req;
+        test::EchoResponse res;
+        req.set_message(EXP_REQUEST);
+
+        // The protocol that actually needed whitelisting still serves.
+        copt.protocol = "baidu_std";
+        brpc::Channel chan;
+        ASSERT_EQ(0, chan.Init(ep, &copt));
+        test::EchoService_Stub stub(&chan);
+        stub.Echo(&cntl, &req, &res, nullptr);
+        ASSERT_FALSE(cntl.Failed()) << cases[i] << ": " << cntl.ErrorText();
+
+        // And so does http, as it does for any whitelist.
+        copt.protocol = "http";
+        brpc::Channel http_channel;
+        ASSERT_EQ(0, http_channel.Init(ep, &copt));
+        cntl.Reset();
+        cntl.http_request().uri() = "/version";
+        http_channel.CallMethod(nullptr, &cntl, nullptr, nullptr, nullptr);
+        ASSERT_FALSE(cntl.Failed()) << cases[i] << ": " << cntl.ErrorText();
+
+        // A protocol left out of the whitelist is still refused.
+        copt.protocol = "hulu_pbrpc";
+        brpc::Channel hulu_channel;
+        ASSERT_EQ(0, hulu_channel.Init(ep, &copt));
+        cntl.Reset();
+        test::EchoService_Stub hulu_stub(&hulu_channel);
+        hulu_stub.Echo(&cntl, &req, &res, nullptr);
+        ASSERT_TRUE(cntl.Failed()) << cases[i];
+        LOG(INFO) << "Expected error: " << cntl.ErrorText();
+
+        ASSERT_EQ(0, server.Stop(0));
+        ASSERT_EQ(0, server.Join());
+    }
+}
+
 TEST_F(ServerTest, services_in_different_ns) {
     const int port = 9200;
     brpc::Server server1;


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

Reply via email to