diff options
| author | littleblack111 <littleblack11111@gmail.com> | 2025-03-10 18:36:00 +0800 |
|---|---|---|
| committer | littleblack111 <littleblack11111@gmail.com> | 2025-03-20 23:44:58 +0800 |
| commit | 131dc244e67e3b6e9304e7076c397c761860044c (patch) | |
| tree | 56f634c1a16c4e5b6eb2224ba876ca97f68e4dee /src | |
| parent | 4e8644b8ab3b259a91387c93a3295092bd9757a0 (diff) | |
fix(registerName): no longer allow same name
the previous behaviour was it wouldn't broadcast the message to the same
name
debug: more logging, maybe we should disable TRACE by default in the
future?
WIP: partial impl of signal handling(SIGINT(keyboardinterrupt) etc)
Diffstat (limited to 'src')
| -rw-r--r-- | src/chatManager.cpp | 7 | ||||
| -rw-r--r-- | src/chatManager.hpp | 2 | ||||
| -rw-r--r-- | src/chatServer.cpp | 17 | ||||
| -rw-r--r-- | src/format.hpp | 1 | ||||
| -rw-r--r-- | src/main.cpp | 24 | ||||
| -rw-r--r-- | src/server.cpp | 4 | ||||
| -rw-r--r-- | src/session.cpp | 26 | ||||
| -rw-r--r-- | src/session.hpp | 2 | ||||
| -rw-r--r-- | src/sessionManager.cpp | 29 | ||||
| -rw-r--r-- | src/sessionManager.hpp | 5 |
10 files changed, 94 insertions, 23 deletions
diff --git a/src/chatManager.cpp b/src/chatManager.cpp index 9711841..0ed3b60 100644 --- a/src/chatManager.cpp +++ b/src/chatManager.cpp @@ -1,11 +1,18 @@ #include "chatManager.hpp" #include "sessionManager.hpp" +#include "log.hpp" + +CChatManager::CChatManager() { + log(LOG, "ChatManager: initialized"); +} CChatManager::~CChatManager() { m_vMessages.clear(); + log(SYS, "ChatManager: bye"); } void CChatManager::newMessage(const SMessage &msg) { + log(LOG, "New message from {}: {}", msg.username, msg.msg); broadcastMessage(msg); m_vMessages.push_back(msg); } diff --git a/src/chatManager.hpp b/src/chatManager.hpp index d56a886..253ab6a 100644 --- a/src/chatManager.hpp +++ b/src/chatManager.hpp @@ -4,7 +4,7 @@ class CChatManager { public: - CChatManager() = default; + CChatManager(); ~CChatManager(); struct SMessage { std::string msg; diff --git a/src/chatServer.cpp b/src/chatServer.cpp index 2f6ddf5..70504f9 100644 --- a/src/chatServer.cpp +++ b/src/chatServer.cpp @@ -2,25 +2,32 @@ #include "server.hpp" #include "sessionManager.hpp" #include "chatManager.hpp" +#include "log.hpp" -CChatServer::CChatServer() = default; +CChatServer::CChatServer() { + log(LOG, "ChatServer: initialized"); +}; CChatServer::~CChatServer() { cleanup(); + log(SYS, "ChatServer: bye"); } void CChatServer::cleanup() { g_pChatManager.reset(); + // if (m_sessionThread.joinable()) + // m_sessionThread.join(); g_pSessionManager.reset(); g_pServer.reset(); - - if (m_sessionThread.joinable()) - m_sessionThread.join(); } void CChatServer::initManagers() { + log(LOG, "ChatServer: initializing managers"); + log(LOG, "Creating Server"); g_pServer = std::make_unique<CServer>(8080); + log(LOG, "Creating SessionManager"); g_pSessionManager = std::make_shared<CSessionManager>(); + log(LOG, "Creating ChatManager"); g_pChatManager = std::make_unique<CChatManager>(); } @@ -28,7 +35,7 @@ void CChatServer::start() { initManagers(); // will await while waiting for accept() to return a new client - m_sessionThread = std::jthread(&CSessionManager::enterLoop, g_pSessionManager); + m_sessionThread = std::jthread(&CSessionManager::run, g_pSessionManager.get()); m_sessionThread.detach(); while (true) { diff --git a/src/format.hpp b/src/format.hpp index cb9ca17..6e41e04 100644 --- a/src/format.hpp +++ b/src/format.hpp @@ -4,6 +4,7 @@ enum eFormatType : int8_t { NONE, + TRACE, LOG, WARN, ERR, diff --git a/src/main.cpp b/src/main.cpp index 8b800dd..463d44d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,31 @@ #include "chatServer.hpp" +#include <csignal> +#include "log.hpp" + +static void handleSignal(int sig) { + signal(sig, SIG_DFL); + + log(SYS, "Caught signal: {}", sig); + + switch (sig) { + default: + std::exit(0); + break; + } +} + +static void registerSignals() { + signal(SIGINT, handleSignal); + signal(SIGTERM, handleSignal); + + // client may not finish reading hence the server will receive SIGPIPE, we don't want that to just crash the server + signal(SIGPIPE, SIG_IGN); +} // TODO: ARGC, ARGV. the CServer ctor should take a port number int main() { + registerSignals(); + g_pChatServer = std::make_unique<CChatServer>(); g_pChatServer->start(); diff --git a/src/server.cpp b/src/server.cpp index cfe13c5..dbf48a7 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -2,6 +2,7 @@ #include <cstring> #include <print> #include <sys/socket.h> +#include "log.hpp" CServer::CServer(uint16_t port) : m_sockfd(Hyprutils::OS::CFileDescriptor{socket(AF_INET, SOCK_STREAM, 0)}) { @@ -20,10 +21,13 @@ CServer::CServer(uint16_t port) listen(m_sockfd.get(), 5) ? throw std::runtime_error("Failed to bind or listen") : std::println("Server started on port: {}", port); + + log(LOG, "Server: initialized"); }; CServer::~CServer() { m_sockfd.reset(); + log(SYS, "Server: bye"); } Hyprutils::OS::CFileDescriptor *CServer::getSocket() { diff --git a/src/session.cpp b/src/session.cpp index b944f5d..f8506c2 100644 --- a/src/session.cpp +++ b/src/session.cpp @@ -1,5 +1,4 @@ #include "session.hpp" -#include "format.hpp" #include "log.hpp" #include "sessionManager.hpp" #include <cerrno> @@ -7,15 +6,21 @@ #include <sys/socket.h> #include "chatManager.hpp" + CSession::CSession(Hyprutils::OS::CFileDescriptor sockfd) : m_sockfd(std::move(sockfd)) { if (!m_sockfd.isValid()) - throw std::runtime_error("Failed to create socket"); + throw std::runtime_error("session: Failed to create socket"); + + log(TRACE, "session: initialized"); } CSession::~CSession() { onDisconnect(); m_sockfd.reset(); + + self->second.reset(); + log(TRACE, "session({}): bye", m_name); } void CSession::onConnect() { @@ -49,6 +54,7 @@ void CSession::recvLoop() { SRecvData recvData = read(); if (!recvData.good) break; + g_pChatManager->newMessage({.msg=recvData.data, .username=m_name}); } } @@ -82,21 +88,27 @@ void CSession::run() { g_pSessionManager->removeSession(self); } -bool CSession::registerSession() { +void CSession::registerSession() { SRecvData recvData = read("Name: "); if (!recvData.good) - return false; + return; if (recvData.data[0] == '\n' || recvData.data[0] == ' ') { write("Name cannot be empty", eFormatType::ERR); registerSession(); - } + return; + } + *std::remove(recvData.data, recvData.data+strlen(recvData.data), '\n') = '\0'; + if (g_pSessionManager->nameExists(recvData.data)) { + write("Name already exists", eFormatType::ERR); + registerSession(); + return; + } + this->m_name = recvData.data; log(LOG, "Client registered as: {}", m_name); - - return true; } bool CSession::isValid() { diff --git a/src/session.hpp b/src/session.hpp index d81faf8..d32fd96 100644 --- a/src/session.hpp +++ b/src/session.hpp @@ -36,7 +36,7 @@ class CSession { Hyprutils::OS::CFileDescriptor m_sockfd; std::string m_name; void recvLoop(); - bool registerSession(); + void registerSession(); void onConnect(); void onDisconnect(); void onErrno(eEventType); diff --git a/src/sessionManager.cpp b/src/sessionManager.cpp index 84c3709..f4573e1 100644 --- a/src/sessionManager.cpp +++ b/src/sessionManager.cpp @@ -4,24 +4,30 @@ #include <algorithm> #include <unistd.h> #include <utility> +#include "log.hpp" -CSessionManager::CSessionManager() = default; +CSessionManager::CSessionManager() { + log(LOG, "SessionManager: initialized"); +}; CSessionManager::~CSessionManager() { for (auto &[thread, session] : m_vSessions) - thread.join(); + if (thread.joinable()) + thread.join(); + + log(SYS, "SessionManager: bye"); } std::pair<std::jthread, std::shared_ptr<CSession>> *CSessionManager::newSession(Hyprutils::OS::CFileDescriptor sockfd) { - std::shared_ptr session = std::make_unique<CSession>(std::move(sockfd)); + std::shared_ptr session = std::make_shared<CSession>(std::move(sockfd)); const auto instance = &m_vSessions.emplace_back(std::jthread(&CSession::run, session), std::move(session)); instance->second->setSelf(instance); return instance; } -void CSessionManager::enterLoop() { - while (true) - newSession(Hyprutils::OS::CFileDescriptor{accept(g_pServer->getSocket()->get(), nullptr, nullptr) /* awaits new client/session */}); +void CSessionManager::run() { + while (true) + newSession(Hyprutils::OS::CFileDescriptor{accept(g_pServer->getSocket()->get(), nullptr, nullptr) /* awaits new client/session */}); } void CSessionManager::broadcast(const std::string &msg, eFormatType type) const { @@ -30,9 +36,16 @@ void CSessionManager::broadcast(const std::string &msg, eFormatType type) const } void CSessionManager::broadcastChat(const std::string &msg, const std::string &username) const { - for (const auto &[thread, session] : m_vSessions) - if (session->getName() != username) + for (const auto &[thread, session] : m_vSessions) { + if (!session) continue; + auto name = session->getName(); + if (name != username) session->write(msg, NONE); + } +} + +bool CSessionManager::nameExists(const std::string &name) { + return std::ranges::any_of(m_vSessions, [&name](const auto &s) { return s.second->getName() == name; }); } void CSessionManager::removeSession(std::pair<std::jthread, std::shared_ptr<CSession>> *session) { diff --git a/src/sessionManager.hpp b/src/sessionManager.hpp index ea5fce9..08ba541 100644 --- a/src/sessionManager.hpp +++ b/src/sessionManager.hpp @@ -13,14 +13,17 @@ class CSessionManager { std::pair<std::jthread, std::shared_ptr<CSession>> *newSession(Hyprutils::OS::CFileDescriptor sockfd); - void enterLoop(); + void run(); void broadcast(const std::string &msg, eFormatType type = NONE) const; void kick(const CSession *session) const; void addSession(const CSession &session); void removeSession(std::pair<std::jthread, std::shared_ptr<CSession>> *session); + bool nameExists(const std::string &name); + private: void broadcastChat(const std::string &msg, const std::string &username) const; + std::vector<std::pair<std::jthread, std::shared_ptr<CSession>>> m_vSessions; friend class CChatManager; }; |
