diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/chatManager.cpp | 6 | ||||
| -rw-r--r-- | src/chatManager.hpp | 2 | ||||
| -rw-r--r-- | src/commandHandler.cpp | 32 | ||||
| -rw-r--r-- | src/commandHandler.hpp | 2 | ||||
| -rw-r--r-- | src/inputManager.cpp | 26 | ||||
| -rw-r--r-- | src/session.cpp | 22 | ||||
| -rw-r--r-- | src/session.hpp | 5 | ||||
| -rw-r--r-- | src/sessionManager.cpp | 11 | ||||
| -rw-r--r-- | src/sessionManager.hpp | 4 |
9 files changed, 69 insertions, 41 deletions
diff --git a/src/chatManager.cpp b/src/chatManager.cpp index 2f6a556..4392e00 100644 --- a/src/chatManager.cpp +++ b/src/chatManager.cpp @@ -13,7 +13,7 @@ CChatManager::~CChatManager() { void CChatManager::newMessage(const SMessage &msg) { log(LOG, "{}: {}", msg.username, msg.msg); - broadcastMessage(msg); + g_pSessionManager->broadcastChat(msg); m_vMessages.push_back(msg); } @@ -21,10 +21,6 @@ std::string CChatManager::fmtBroadcastMessage(const SMessage &msg) { return NFormatter::fmt(NONE, "{}: {}", msg.username, msg.msg); } -void CChatManager::broadcastMessage(const SMessage &msg) { - g_pSessionManager->broadcastChat(fmtBroadcastMessage(msg), msg.username); -} - const std::vector<CChatManager::SMessage> &CChatManager::getChat() const { return m_vMessages; } diff --git a/src/chatManager.hpp b/src/chatManager.hpp index 0560657..084c002 100644 --- a/src/chatManager.hpp +++ b/src/chatManager.hpp @@ -11,9 +11,9 @@ class CChatManager { struct SMessage { std::string msg; std::string username; + bool admin = false; }; void newMessage(const SMessage &msg); - void broadcastMessage(const SMessage &msg); std::string fmtBroadcastMessage(const SMessage &msg); const std::vector<SMessage> &getChat() const; diff --git a/src/commandHandler.cpp b/src/commandHandler.cpp index 12b51dc..712bbe2 100644 --- a/src/commandHandler.cpp +++ b/src/commandHandler.cpp @@ -1,5 +1,6 @@ #include "commandHandler.hpp" #include "log.hpp" +#include "sessionManager.hpp" #include <algorithm> CCommandHandler::CCommandHandler() { @@ -56,3 +57,34 @@ CCommandHandler::SResult CCommandHandler::newCommand(const std::string &command, return exeCommand(*getCommand(command), args); } + +void CCommandHandler::handleCommand(std::string input, const char ip[INET_ADDRSTRLEN]) const { + input = input.substr(1); + + std::string command; + std::string args; + + size_t spacePos = input.find(' '); + if (spacePos == std::string::npos) { + command = input; + args = ""; + } else { + command = input.substr(0, spacePos); + // skip extra spaces + size_t startPos = input.find_first_not_of(' ', spacePos); + if (startPos != std::string::npos) + args = input.substr(startPos); + } + + args.empty() ? log(LOG, "Spawning Command: {}", command) : log(LOG, "Spawning Command: {}, Args: {}", command, args); + const auto exe = newCommand(command, args); + + std::function<void(eFormatType, const std::string &)> outputter = [](eFormatType type, const std::string &msg) { log(type, "{}", msg); }; + + if (ip != nullptr) + if (auto session = g_pSessionManager->getByIp(ip)) + outputter = [session](eFormatType, const std::string &msg) { session->write(msg); }; + + exe.good ? exe.result.empty() ? outputter(LOG, "Command succeeded") : outputter(LOG, exe.result) : exe.result.empty() ? outputter(ERR, "Command failed") + : outputter(ERR, exe.result); +}; diff --git a/src/commandHandler.hpp b/src/commandHandler.hpp index 78ab2e5..8d97fd5 100644 --- a/src/commandHandler.hpp +++ b/src/commandHandler.hpp @@ -3,6 +3,7 @@ #include <any> #include <functional> #include <memory> +#include <netinet/in.h> #include <string> #include <vector> @@ -32,6 +33,7 @@ class CCommandHandler { // return false if command struct is invalid bool registerCommand(const SCommand &command); SResult newCommand(const std::string &command, const std::string &args) const; + void handleCommand(std::string input, const char ip[INET_ADDRSTRLEN] = {}) const; template <typename T> struct SMakeCommandArgs { diff --git a/src/inputManager.cpp b/src/inputManager.cpp index 57b7b06..8de26bd 100644 --- a/src/inputManager.cpp +++ b/src/inputManager.cpp @@ -16,30 +16,6 @@ void CInputManager::run() { inputLoop(); } -static void handleCommand(std::string &input) { - input = input.substr(1); - - std::string command; - std::string args; - - size_t spacePos = input.find(' '); - if (spacePos == std::string::npos) { - command = input; - args = ""; - } else { - command = input.substr(0, spacePos); - // skip extra spaces - size_t startPos = input.find_first_not_of(' ', spacePos); - if (startPos != std::string::npos) - args = input.substr(startPos); - } - - args.empty() ? log(TRACE, "Spawning Command: {}", command) : log(TRACE, "Spawning Command: {}, Args: {}", command, args); - const auto exe = g_pCommandHandler->newCommand(command, args); - exe.good ? exe.result.empty() ? log(LOG, "Command {} succeeded", command) : log(LOG, "Command {} succeeded: {}", command, exe.result) : exe.result.empty() ? log(ERR, "Command {} failed", command) - : log(ERR, "Command {} failed: {}", command, exe.result); -}; - void CInputManager::inputLoop() { while (true) { std::string input; @@ -49,6 +25,6 @@ void CInputManager::inputLoop() { if (input.empty()) continue; - g_pCommandHandler->isCommand(input) ? handleCommand(input) : g_pChatManager->broadcastMessage({.msg = input, .username = "Server"}); + g_pCommandHandler->isCommand(input) ? g_pCommandHandler->handleCommand(input) : g_pChatManager->newMessage({.msg = input, .username = "Server"}); } } diff --git a/src/session.cpp b/src/session.cpp index 9668cd8..26dc3f8 100644 --- a/src/session.cpp +++ b/src/session.cpp @@ -1,5 +1,6 @@ #include "session.hpp" #include "chatManager.hpp" +#include "commandHandler.hpp" #include "log.hpp" #include "server.hpp" #include "sessionManager.hpp" @@ -17,7 +18,8 @@ CSession::CSession() throw std::runtime_error("session: Failed to create socket"); inet_ntop(AF_INET, &m_addr.sin_addr, m_ip, INET_ADDRSTRLEN); - m_port = ntohs(m_addr.sin_port); + m_port = ntohs(m_addr.sin_port); + m_isAdmin = std::ranges::any_of(m_adminIps, [this](const char *ip) { return strcmp(ip, m_ip) == 0; }); log(LOG, "Client {} connected on port {}", m_ip, m_port); log(TRACE, "session: initialized"); @@ -70,7 +72,12 @@ void CSession::recvLoop() { if (!recvData->good) break; - g_pChatManager->newMessage({.msg = recvData->data, .username = m_name}); + recvData->sanitize(); + const auto isCommand = g_pCommandHandler->isCommand(recvData->data); + if (m_isAdmin && isCommand) + g_pCommandHandler->handleCommand(recvData->data, m_ip); + + g_pChatManager->newMessage({.msg = recvData->data, .username = m_name, .admin = isCommand}); } } @@ -124,7 +131,7 @@ void CSession::run() { #endif if (registerSession()) { for (const auto &chat : g_pChatManager->getChat()) - write(g_pChatManager->fmtBroadcastMessage(chat)); + writeChat(chat); recvLoop(); } else log(LOG, "Client {} exited without even registering", m_ip); @@ -200,6 +207,15 @@ bool CSession::write(const std::string &msg) { return write("{}", msg); } +void CSession::writeChat(const CChatManager::SMessage &msg) { + if (m_name != msg.username) { + if (msg.admin && !m_isAdmin) + return; + + write(g_pChatManager->fmtBroadcastMessage(msg)); + } +} + const std::string &CSession::getName() const { return m_name; } diff --git a/src/session.hpp b/src/session.hpp index 18c587d..1b7b8db 100644 --- a/src/session.hpp +++ b/src/session.hpp @@ -1,6 +1,7 @@ #pragma once #include "FileDescriptor.hpp" +#include "chatManager.hpp" #include "format.hpp" #include <memory> #include <netinet/in.h> @@ -32,12 +33,15 @@ class CSession { bool write(std::format_string<Args...> fmt, Args &&...args); template <typename... Args> bool write(eFormatType type, std::format_string<Args...> fmt, Args &&...args); + void writeChat(const CChatManager::SMessage &msg); void run(); bool isValid(); private: + constexpr static char m_adminIps[1][INET_ADDRSTRLEN] = {"127.0.0.1"}; + enum eEventType : std::uint8_t { READ, WRITE @@ -50,6 +54,7 @@ class CSession { std::string m_name; char m_ip[INET_ADDRSTRLEN]; int m_port; + bool m_isAdmin = false; bool m_isReading = false; diff --git a/src/sessionManager.cpp b/src/sessionManager.cpp index 51bede4..0e27367 100644 --- a/src/sessionManager.cpp +++ b/src/sessionManager.cpp @@ -45,13 +45,12 @@ void CSessionManager::broadcast(const std::string &msg) const { session->write(msg); } -void CSessionManager::broadcastChat(const std::string &msg, const std::string &username) const { +void CSessionManager::broadcastChat(const CChatManager::SMessage &msg) const { for (const auto &[thread, session] : m_vSessions) { if (!session) continue; - auto name = session->getName(); - if (name != username) - session->write(msg); + + session->writeChat(msg); } } @@ -83,8 +82,8 @@ void CSessionManager::kick(std::pair<std::jthread, std::shared_ptr<CSession>> *s auto it = std::ranges::find_if(m_vSessions, [session](const auto &s) { return s.second.get() == session->second.get(); }); if (it != m_vSessions.end()) { - if (!reason.empty()) - it->second->write(reason); + if (!reason.empty()) + it->second->write(reason); const auto native_handle = it->first.native_handle(); if (it->first.joinable()) it->first.detach(); // .detach the thread since it's removing itself diff --git a/src/sessionManager.hpp b/src/sessionManager.hpp index a0f4389..4ca3311 100644 --- a/src/sessionManager.hpp +++ b/src/sessionManager.hpp @@ -1,5 +1,6 @@ #pragma once +#include "chatManager.hpp" #include "format.hpp" #include "session.hpp" #include <memory> @@ -27,9 +28,10 @@ class CSessionManager { std::vector<std::shared_ptr<CSession>> getSessions() const; private: - void broadcastChat(const std::string &msg, const std::string &username) const; + void broadcastChat(const CChatManager::SMessage &msg) const; std::vector<std::pair<std::jthread, std::shared_ptr<CSession>>> m_vSessions; + friend class CChatManager; }; inline std::shared_ptr<CSessionManager> g_pSessionManager; |
