diff --git a/core/manager/manager.cpp b/core/manager/manager.cpp index 8344f98..d91d14c 100644 --- a/core/manager/manager.cpp +++ b/core/manager/manager.cpp @@ -35,12 +35,22 @@ void Manager::run() noexcept { void Manager::read() noexcept { auto self(shared_from_this()); - boost::asio::async_read_until(socket_, boost::asio::dynamic_buffer(data_), "\r\n", - [this, self](boost::system::error_code ec, std::size_t length) { + socket_.async_read_some( + boost::asio::buffer(buffer_), + [this, self](const boost::system::error_code& ec, std::size_t length) { if (ec) return; - data_.erase(0, data_.find_first_not_of("\r\n")); - if (!data_.empty()) invokeAction(); - data_.clear(); + data_.append(buffer_.data(), length); + + std::size_t start = 0; + std::size_t pos; + + while ((pos = data_.find("\r\n", start)) != std::string::npos) { + std::string line = data_.substr(start, pos - start); + invokeAction(line); + start = pos + 2; + } + + data_.erase(0, start); read(); } ); @@ -51,50 +61,51 @@ void Manager::result(std::string value) noexcept { [this](boost::system::error_code ec, std::size_t){}); } -void Manager::invokeAction() noexcept { - std::istringstream request(data_); +void Manager::invokeAction(const std::string& line) noexcept { std::vector args; std::string command; - request >> command; - boost::algorithm::to_upper(command); - - if (std::find(commands.all.begin(), commands.all.end(), command) == commands.all.end()) return; + const char* ptr = line.c_str(); + const char* end = ptr + line.size(); - char quote = '\0'; - - std::string value; + while (ptr != end && !std::isspace(*ptr)) { + command.push_back(std::toupper(*ptr)); + ++ptr; + } - while (request) { - char peekStream = request.peek(); + if (commands.all.find(command) == commands.all.end()) return result("ERROR: incorrect command"); - if (peekStream == '"' || peekStream == '\'') { - quote = request.get(); - value.clear(); - char c; - bool escape = false; + while (ptr != end && std::isspace(*ptr)) ++ptr; - while (request.get(c)) { - if (escape) { - value.push_back(c); - escape = false; - } - else if (c == '\\') escape = true; - else if (c == quote) break; - else value.push_back(c); - } - } else if (std::isspace(peekStream)) { - request.ignore(); - if (!value.empty()) { + std::string value; + char quote = '\0'; + bool escape = false; + + while (ptr != end) { + char c = *ptr++; + + if (quote) { + if (escape) { + value.push_back(c); + escape = false; + } else if (c == '\\') { + escape = true; + } else if (c == quote) { + quote = '\0'; args.push_back(std::move(value)); value.clear(); + } else { + value.push_back(c); } - } else { - request >> value; - if (request) { + } else if (c == '"' || c == '\'') { + quote = c; + } else if (std::isspace(c)) { + if (!value.empty()) { args.push_back(std::move(value)); value.clear(); } + } else { + value.push_back(c); } } @@ -110,8 +121,6 @@ void Manager::invokeAction() noexcept { if (commands.set == command) return invokeSet(args); if (commands.del == command) return invokeDel(args); if (commands.keys == command) return invokeKeys(args); - - return result("ERROR: incorrect command"); } void Manager::invokeDel(std::vector args) noexcept { diff --git a/core/manager/manager.h b/core/manager/manager.h index 075f617..538d6c5 100644 --- a/core/manager/manager.h +++ b/core/manager/manager.h @@ -31,6 +31,7 @@ #include #include #include + #include #include #include #include @@ -44,7 +45,7 @@ std::string auth = "AUTH"; std::string use = "USE"; std::string keys = "KEYS"; - std::vector all = {"SET", "DEL", "GET", "AUTH", "USE", "KEYS"}; + std::unordered_set all = {"AUTH", "USE", "GET", "SET", "DEL", "KEYS"}; }; @@ -58,7 +59,7 @@ private: void read() noexcept; void result(std::string value) noexcept; - void invokeAction() noexcept; + void invokeAction(const std::string& line) noexcept; void invokeDel(std::vector args) noexcept; void invokeSet(std::vector args); void invokeGet(std::vector args) noexcept; @@ -74,5 +75,6 @@ std::function onDisconnect_; boost::asio::ip::tcp::socket socket_; ConfigConnect& ConfigConn_; + std::array buffer_; }; #endif \ No newline at end of file diff --git a/core/socket/socket.cpp b/core/socket/socket.cpp index 22dfcca..72c8664 100644 --- a/core/socket/socket.cpp +++ b/core/socket/socket.cpp @@ -22,10 +22,16 @@ #include "socket.h" CoreSocket::CoreSocket(boost::asio::io_context& io_context, std::string ip, short port, Cache& cache_) - : acceptor_(io_context, boost::asio::ip::tcp::endpoint(boost::asio::ip::make_address(ip), port)), - cache_(cache_), client_(0), socket_(io_context) { - acceptor_.set_option(boost::asio::socket_base::reuse_address(true)); + : acceptor_(io_context), cache_(cache_), client_(0), socket_(io_context) { + boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::make_address_v4(ip), port); + acceptor_.open(endpoint.protocol()); + + acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); acceptor_.set_option(boost::asio::ip::tcp::no_delay(true)); + + acceptor_.bind(endpoint); + acceptor_.listen(boost::asio::socket_base::max_listen_connections); + accept(); ping(); } diff --git a/main.cpp b/main.cpp index 368bfe7..2c48ac7 100644 --- a/main.cpp +++ b/main.cpp @@ -29,7 +29,15 @@ int main(){ boost::asio::io_context io_context; ConfigHosting ConfigHost = Config::getConfigHost(); CoreSocket server(io_context, ConfigHost.address, ConfigHost.port, cache_); - io_context.run(); + + std::vector threads; + for (std::size_t i = 0; i < std::thread::hardware_concurrency(); ++i) { + threads.emplace_back([&io_context]() { io_context.run(); }); + } + + for (auto& thread : threads) { + thread.join(); + } } catch (std::exception& e) { std::cerr << "Exception: " << e.what() << "\n";