diff --git a/src/PlayerbotCommandServer.cpp b/src/PlayerbotCommandServer.cpp index 482c2348..c08f1d05 100644 --- a/src/PlayerbotCommandServer.cpp +++ b/src/PlayerbotCommandServer.cpp @@ -9,8 +9,10 @@ #include #include #include +#include #include #include +#include #include "IoContext.h" #include "Playerbots.h" @@ -18,21 +20,39 @@ using boost::asio::ip::tcp; typedef boost::shared_ptr socket_ptr; +std::mutex session_mutex; // Global mutex to protect sessions +boost::asio::thread_pool pool(4); // 4-thread thread pool + bool ReadLine(socket_ptr sock, std::string* buffer, std::string* line) { - // Do the real reading from fd until buffer has '\n'. + // Check if the socket is valid before using it + if (!sock || !sock->is_open()) + { + LOG_ERROR("playerbots", "Invalid or closed socket."); + return false; + } + + // Does the actual reading until the buffer has a '\n' std::string::iterator pos; while ((pos = find(buffer->begin(), buffer->end(), '\n')) == buffer->end()) { char buf[1025]; boost::system::error_code error; - size_t n = sock->read_some(boost::asio::buffer(buf), error); - if (n == -1 || error == boost::asio::error::eof) - return false; - else if (error) - throw boost::system::system_error(error); // Some other error. - buf[n] = 0; + // Read socket data + size_t n = sock->read_some(boost::asio::buffer(buf), error); + if (n == 0 || error == boost::asio::error::eof) + { + LOG_INFO("playerbots", "Connection closed by peer."); + return false; + } + else if (error) + { + LOG_ERROR("playerbots", "Socket read error: {}", error.message()); + return false; // Returns false in case of error. + } + + buf[n] = 0; // Ensures the buffer ends with null *buffer += buf; } @@ -45,6 +65,8 @@ void session(socket_ptr sock) { try { + std::lock_guard guard(session_mutex); // Protect session with mutex + std::string buffer, request; while (ReadLine(sock, &buffer, &request)) { @@ -55,7 +77,19 @@ void session(socket_ptr sock) } catch (std::exception& e) { - LOG_ERROR("playerbots", "{}", e.what()); + LOG_ERROR("playerbots", "Session error: {}", e.what()); + } + + // Make sure to close the socket at the end of the session + if (sock && sock->is_open()) + { + boost::system::error_code ec; + sock->shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec); + sock->close(ec); + if (ec) + { + LOG_ERROR("playerbots", "Error closing socket: {}", ec.message()); + } } } @@ -66,7 +100,7 @@ void server(Acore::Asio::IoContext& io_service, short port) { socket_ptr sock(new tcp::socket(io_service)); a.accept(*sock); - boost::thread t(boost::bind(session, sock)); + boost::asio::post(pool, boost::bind(session, sock)); // Use thread pool instead of creating new threads } }