From 76ab4b7f43a2975d81c63c7ad8674077e997105d Mon Sep 17 00:00:00 2001 From: marsevilspirit Date: Mon, 16 Dec 2024 03:09:28 +0800 Subject: [PATCH 1/8] add hello command and support setname --- src/base_cmd.h | 1 + src/client.h | 22 ++++++------ src/cmd_admin.cc | 74 +++++++++++++++++++++++++++++++++++++++- src/cmd_admin.h | 21 ++++++++++-- src/cmd_table_manager.cc | 3 ++ 5 files changed, 106 insertions(+), 15 deletions(-) diff --git a/src/base_cmd.h b/src/base_cmd.h index 06d0d24..6227b31 100644 --- a/src/base_cmd.h +++ b/src/base_cmd.h @@ -97,6 +97,7 @@ const std::string kCmdNameDebug = "debug"; const std::string kSubCmdNameDebugHelp = "help"; const std::string kSubCmdNameDebugOOM = "oom"; const std::string kSubCmdNameDebugSegfault = "segfault"; +const std::string kCmdNameHello = "hello"; const std::string kCmdNameInfo = "info"; const std::string kCmdNameSort = "sort"; diff --git a/src/client.h b/src/client.h index cc2d2f9..df07c6b 100644 --- a/src/client.h +++ b/src/client.h @@ -131,19 +131,19 @@ class PClient : public std::enable_shared_from_this { void ClearWatch(); // reply - inline void SetRes(CmdRes _ret, const std::string& content = "") { resp_encode_->SetRes(_ret, content); }; - inline void AppendArrayLen(int64_t ori) { resp_encode_->AppendArrayLen(ori); } - inline void AppendArrayLen(uint64_t ori) { resp_encode_->AppendArrayLen(static_cast(ori)); } - inline void AppendInteger(int64_t value) { resp_encode_->AppendInteger(value); } - inline void AppendStringRaw(const std::string& value) { resp_encode_->AppendStringRaw(value); } - inline void AppendSimpleString(const std::string& value) { resp_encode_->AppendSimpleString(value); } - inline void AppendString(const std::string& value) { resp_encode_->AppendString(value); } - inline void AppendStringVector(const std::vector& strArray) { + void SetRes(CmdRes _ret, const std::string& content = "") { resp_encode_->SetRes(_ret, content); }; + void AppendArrayLen(int64_t ori) { resp_encode_->AppendArrayLen(ori); } + void AppendArrayLen(uint64_t ori) { resp_encode_->AppendArrayLen(static_cast(ori)); } + void AppendInteger(int64_t value) { resp_encode_->AppendInteger(value); } + void AppendStringRaw(const std::string& value) { resp_encode_->AppendStringRaw(value); } + void AppendSimpleString(const std::string& value) { resp_encode_->AppendSimpleString(value); } + void AppendString(const std::string& value) { resp_encode_->AppendString(value); } + void AppendStringVector(const std::vector& strArray) { resp_encode_->AppendStringVector(strArray); }; - inline void AppendString(const char* value, int64_t size) { resp_encode_->AppendString(value, size); } - inline void SetLineString(const std::string& value) { resp_encode_->SetLineString(value); } - inline void Reply(std::string& str) { resp_encode_->Reply(str); } + void AppendString(const char* value, int64_t size) { resp_encode_->AppendString(value, size); } + void SetLineString(const std::string& value) { resp_encode_->SetLineString(value); } + void Reply(std::string& str) { resp_encode_->Reply(str); } // reply // pubsub diff --git a/src/cmd_admin.cc b/src/cmd_admin.cc index af1423b..bf54371 100644 --- a/src/cmd_admin.cc +++ b/src/cmd_admin.cc @@ -25,6 +25,7 @@ #include #include #include "cmd_admin.h" +#include "config.h" #include "db.h" #include "braft/raft.h" @@ -36,7 +37,6 @@ #include "pstd/env.h" #include "client_map.h" -#include "cmd_table_manager.h" #include "slow_log.h" #include "store.h" @@ -161,6 +161,78 @@ bool PingCmd::DoInitial(PClient* client) { return true; } void PingCmd::DoCmd(PClient* client) { client->SetRes(CmdRes::kPong, "PONG"); } +HelloCmd::HelloCmd(const std::string& name, int16_t arity) + : BaseCmd(name, arity, kCmdFlagsFast, kAclCategoryFast | kAclCategoryConnection) {} + +bool HelloCmd::DoInitial(PClient* client) { + size_t argc = client->argv_.size(); + int resp_version = 2; + + if (argc > 1) { + if (pstd::String2int(client->argv_[1].data(), client->argv_[1].size(), &resp_version) == 0) { + client->SetRes(CmdRes::kErrOther, "Protocol version is not an integer or out of range"); + return false; + } + } + + if (resp_version != 2) { + client->SetRes(CmdRes::kErrOther, "unsupported protocol version"); + return false; + } + + return true; +} + +void HelloCmd::DoCmd(PClient* client) { + size_t argc = client->argv_.size(); + size_t next_arg = 2; + + for (; next_arg < argc; next_arg++) { + size_t more_args = argc - next_arg; + const std::string& arg = client->argv_[next_arg]; + if ((strcasecmp(arg.data(), "SETNAME") == 0) && more_args) { + client->SetName(client->argv_[next_arg + 1]); + next_arg++; + } else { + client->SetRes(CmdRes::kSyntaxErr, "Syntax error"); + return; + } + } + + Hello(client); +} + +void HelloCmd::Hello(PClient* client) { + client->AppendArrayLen(static_cast(12)); + client->AppendString("server"); + client->AppendString("kiwi"); + client->AppendString("version"); + client->AppendString(Kkiwi_VERSION); + client->AppendString("proto"); + client->AppendInteger(static_cast(2)); + client->AppendString("id"); + client->AppendInteger(static_cast(client->GetConnId())); + client->AppendString("mode"); + + if (!g_config.use_raft) { + client->AppendString("standalone"); + } else { + client->AppendString("cluster"); + } + + client->AppendString("role"); + if (client->GetAuth()) { + client->AppendString("master"); + } else { + client->AppendString("slave"); + } +} + +void HelloCmd::HelloSubCmdSetname(PClient* client) { + Hello(client); + client->SetName(client->argv_[3]); +} + const std::string InfoCmd::kInfoSection = "info"; const std::string InfoCmd::kAllSection = "all"; const std::string InfoCmd::kServerSection = "server"; diff --git a/src/cmd_admin.h b/src/cmd_admin.h index 5097182..4616d7e 100644 --- a/src/cmd_admin.h +++ b/src/cmd_admin.h @@ -9,6 +9,7 @@ #pragma once +#include #include #include #include "base_cmd.h" @@ -135,7 +136,7 @@ class CmdClientId : public BaseCmd { class CmdClientList : public BaseCmd { private: - enum class Type { DEFAULT, IDLE, ADDR, ID } list_type_; + enum class Type : std::int8_t { DEFAULT, IDLE, ADDR, ID } list_type_; std::string info_; public: @@ -150,7 +151,7 @@ class CmdClientList : public BaseCmd { class CmdClientKill : public BaseCmd { private: - enum class Type { ALL, ADDR, ID } kill_type_; + enum class Type : std::int8_t { ALL, ADDR, ID } kill_type_; public: CmdClientKill(const std::string& name, int16_t arity); @@ -195,6 +196,20 @@ class PingCmd : public BaseCmd { void DoCmd(PClient* client) override; }; +class HelloCmd : public BaseCmd { + public: + HelloCmd(const std::string& name, int16_t arity); + + protected: + bool DoInitial(PClient* client) override; + + private: + void DoCmd(PClient* client) override; + + void Hello(PClient* client); + void HelloSubCmdSetname(PClient* client); +}; + class InfoCmd : public BaseCmd { public: InfoCmd(const std::string& name, int16_t arity); @@ -205,7 +220,7 @@ class InfoCmd : public BaseCmd { private: void DoCmd(PClient* client) override; - enum InfoSection { + enum InfoSection : std::uint8_t { kInfoErr = 0x0, kInfoServer, kInfoStats, diff --git a/src/cmd_table_manager.cc b/src/cmd_table_manager.cc index 38c48b0..46a0d1e 100644 --- a/src/cmd_table_manager.cc +++ b/src/cmd_table_manager.cc @@ -76,6 +76,9 @@ void CmdTableManager::InitCmdTable() { ADD_COMMAND(Select, 2); ADD_COMMAND(Shutdown, 1); + // hello + ADD_COMMAND(Hello, -1); + // info ADD_COMMAND(Info, -1); From e5d3dba190fc0b15c46c014e2e1481d0a648b1d7 Mon Sep 17 00:00:00 2001 From: marsevilspirit Date: Mon, 16 Dec 2024 03:12:27 +0800 Subject: [PATCH 2/8] delete sub fuction --- src/cmd_admin.cc | 5 ----- src/cmd_admin.h | 1 - 2 files changed, 6 deletions(-) diff --git a/src/cmd_admin.cc b/src/cmd_admin.cc index bf54371..0c730d7 100644 --- a/src/cmd_admin.cc +++ b/src/cmd_admin.cc @@ -228,11 +228,6 @@ void HelloCmd::Hello(PClient* client) { } } -void HelloCmd::HelloSubCmdSetname(PClient* client) { - Hello(client); - client->SetName(client->argv_[3]); -} - const std::string InfoCmd::kInfoSection = "info"; const std::string InfoCmd::kAllSection = "all"; const std::string InfoCmd::kServerSection = "server"; diff --git a/src/cmd_admin.h b/src/cmd_admin.h index 4616d7e..24bc64c 100644 --- a/src/cmd_admin.h +++ b/src/cmd_admin.h @@ -207,7 +207,6 @@ class HelloCmd : public BaseCmd { void DoCmd(PClient* client) override; void Hello(PClient* client); - void HelloSubCmdSetname(PClient* client); }; class InfoCmd : public BaseCmd { From eaae9c429fdf750b60ea60299c7db0a304d6f7ab Mon Sep 17 00:00:00 2001 From: marsevilspirit Date: Mon, 16 Dec 2024 03:46:13 +0800 Subject: [PATCH 3/8] add todo --- src/cmd_admin.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cmd_admin.cc b/src/cmd_admin.cc index 0c730d7..fe5b748 100644 --- a/src/cmd_admin.cc +++ b/src/cmd_admin.cc @@ -190,6 +190,7 @@ void HelloCmd::DoCmd(PClient* client) { for (; next_arg < argc; next_arg++) { size_t more_args = argc - next_arg; const std::string& arg = client->argv_[next_arg]; + // TODO(marsevilspirit): support auth if ((strcasecmp(arg.data(), "SETNAME") == 0) && more_args) { client->SetName(client->argv_[next_arg + 1]); next_arg++; From 456928ddab2d2aa6be30016c4182834ab8b83172 Mon Sep 17 00:00:00 2001 From: marsevilspirit Date: Tue, 17 Dec 2024 19:38:13 +0800 Subject: [PATCH 4/8] update --- src/cmd_admin.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cmd_admin.cc b/src/cmd_admin.cc index fe5b748..eafd208 100644 --- a/src/cmd_admin.cc +++ b/src/cmd_admin.cc @@ -190,7 +190,8 @@ void HelloCmd::DoCmd(PClient* client) { for (; next_arg < argc; next_arg++) { size_t more_args = argc - next_arg; const std::string& arg = client->argv_[next_arg]; - // TODO(marsevilspirit): support auth + // TODO(marsevilspirit): support auth acl + // like: hello 2 auth username password if ((strcasecmp(arg.data(), "SETNAME") == 0) && more_args) { client->SetName(client->argv_[next_arg + 1]); next_arg++; From 1197fdcb98dc09a6a34c1a93bfe08959afe43cab Mon Sep 17 00:00:00 2001 From: marsevilspirit Date: Tue, 17 Dec 2024 19:39:27 +0800 Subject: [PATCH 5/8] make format --- src/client.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/client.h b/src/client.h index df07c6b..3a0af05 100644 --- a/src/client.h +++ b/src/client.h @@ -138,9 +138,7 @@ class PClient : public std::enable_shared_from_this { void AppendStringRaw(const std::string& value) { resp_encode_->AppendStringRaw(value); } void AppendSimpleString(const std::string& value) { resp_encode_->AppendSimpleString(value); } void AppendString(const std::string& value) { resp_encode_->AppendString(value); } - void AppendStringVector(const std::vector& strArray) { - resp_encode_->AppendStringVector(strArray); - }; + void AppendStringVector(const std::vector& strArray) { resp_encode_->AppendStringVector(strArray); }; void AppendString(const char* value, int64_t size) { resp_encode_->AppendString(value, size); } void SetLineString(const std::string& value) { resp_encode_->SetLineString(value); } void Reply(std::string& str) { resp_encode_->Reply(str); } From 6c7b3c09fda08fc00c0251938fdd5ad5541dc33a Mon Sep 17 00:00:00 2001 From: marsevilspirit Date: Thu, 26 Dec 2024 21:25:53 +0800 Subject: [PATCH 6/8] support auth password --- src/client.cc | 3 ++- src/client_map.h | 2 +- src/cmd_admin.cc | 29 ++++++++++++++++++++++++++++- src/cmd_admin.h | 2 ++ 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/client.cc b/src/client.cc index 6ec8959..dae5c36 100644 --- a/src/client.cc +++ b/src/client.cc @@ -150,7 +150,8 @@ int PClient::HandlePacket(std::string&& data) { } if (!auth_) { - if (params[0][0] == kCmdNameAuth) { + // auth and hello command can be executed without auth + if (params[0][0] == kCmdNameAuth || params[0][0] == kCmdNameHello) { auto now = ::time(nullptr); if (now <= last_auth_ + 1) { // avoid guess password. diff --git a/src/client_map.h b/src/client_map.h index ddbfa23..9f51af1 100644 --- a/src/client_map.h +++ b/src/client_map.h @@ -38,4 +38,4 @@ class ClientMap { bool KillClientByAddrPort(const std::string& addr_port); }; -} // namespace kiwi \ No newline at end of file +} // namespace kiwi diff --git a/src/cmd_admin.cc b/src/cmd_admin.cc index eafd208..c7cf2ec 100644 --- a/src/cmd_admin.cc +++ b/src/cmd_admin.cc @@ -29,6 +29,7 @@ #include "db.h" #include "braft/raft.h" +#include "log.h" #include "pstd_string.h" #include "rocksdb/version.h" @@ -168,6 +169,10 @@ bool HelloCmd::DoInitial(PClient* client) { size_t argc = client->argv_.size(); int resp_version = 2; + if (!client->GetAuth()) { + Authed_ = false; + } + if (argc > 1) { if (pstd::String2int(client->argv_[1].data(), client->argv_[1].size(), &resp_version) == 0) { client->SetRes(CmdRes::kErrOther, "Protocol version is not an integer or out of range"); @@ -192,15 +197,37 @@ void HelloCmd::DoCmd(PClient* client) { const std::string& arg = client->argv_[next_arg]; // TODO(marsevilspirit): support auth acl // like: hello 2 auth username password + // now only support hello auth password + // do not support username (need acl) if ((strcasecmp(arg.data(), "SETNAME") == 0) && more_args) { client->SetName(client->argv_[next_arg + 1]); next_arg++; + } else if (strcasecmp(arg.data(), "AUTH") == 0 && more_args) { + Authed_ = true; + if (client->GetAuth()) { + continue; + } + if (client->argv_[next_arg + 1] != g_config.password) { + client->SetRes(CmdRes::kErrOther, "invalid password"); + return; + } else { + client->SetAuth(); + } + next_arg++; } else { client->SetRes(CmdRes::kSyntaxErr, "Syntax error"); return; } } + if (!Authed_) { + client->SetRes(CmdRes::kErrOther, + "NOAUTH HELLO must be called with the client already authenticated, \ + otherwise the HELLO AUTH option can be used to authenticate the client and \ + select the RESP protocol version at the same time"); + return; + } + Hello(client); } @@ -213,7 +240,7 @@ void HelloCmd::Hello(PClient* client) { client->AppendString("proto"); client->AppendInteger(static_cast(2)); client->AppendString("id"); - client->AppendInteger(static_cast(client->GetConnId())); + client->AppendInteger(static_cast(client->GetUniqueID())); client->AppendString("mode"); if (!g_config.use_raft) { diff --git a/src/cmd_admin.h b/src/cmd_admin.h index 24bc64c..1828c41 100644 --- a/src/cmd_admin.h +++ b/src/cmd_admin.h @@ -204,6 +204,8 @@ class HelloCmd : public BaseCmd { bool DoInitial(PClient* client) override; private: + bool Authed_ = true; + void DoCmd(PClient* client) override; void Hello(PClient* client); From 98ca25686ea4adffb322ed63b5548fd2cf23859a Mon Sep 17 00:00:00 2001 From: marsevilspirit Date: Sun, 29 Dec 2024 18:53:50 +0800 Subject: [PATCH 7/8] update --- src/cmd_admin.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cmd_admin.h b/src/cmd_admin.h index 183b547..c58b816 100644 --- a/src/cmd_admin.h +++ b/src/cmd_admin.h @@ -204,11 +204,12 @@ class HelloCmd : public BaseCmd { bool DoInitial(PClient* client) override; private: - bool Authed_ = true; - void DoCmd(PClient* client) override; void Hello(PClient* client); + + private: + bool authed_ = true; }; class EchoCmd : public BaseCmd { From d05af74f932c4180b05cd366d992421862d4a24d Mon Sep 17 00:00:00 2001 From: marsevilspirit Date: Sun, 29 Dec 2024 19:11:48 +0800 Subject: [PATCH 8/8] fix Authed_ -> authed_ --- src/cmd_admin.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cmd_admin.cc b/src/cmd_admin.cc index d0d0a29..70c3679 100644 --- a/src/cmd_admin.cc +++ b/src/cmd_admin.cc @@ -170,7 +170,7 @@ bool HelloCmd::DoInitial(PClient* client) { int resp_version = 2; if (!client->GetAuth()) { - Authed_ = false; + authed_ = false; } if (argc > 1) { @@ -203,7 +203,7 @@ void HelloCmd::DoCmd(PClient* client) { client->SetName(client->argv_[next_arg + 1]); next_arg++; } else if (strcasecmp(arg.data(), "AUTH") == 0 && more_args) { - Authed_ = true; + authed_ = true; if (client->GetAuth()) { continue; } @@ -220,7 +220,7 @@ void HelloCmd::DoCmd(PClient* client) { } } - if (!Authed_) { + if (!authed_) { client->SetRes(CmdRes::kErrOther, "NOAUTH HELLO must be called with the client already authenticated, \ otherwise the HELLO AUTH option can be used to authenticate the client and \