diff options
| -rw-r--r-- | src/session.cpp | 15 | ||||
| -rw-r--r-- | src/session.hpp | 2 | ||||
| -rw-r--r-- | src/sessionManager.cpp | 25 | ||||
| -rw-r--r-- | src/sessionManager.hpp | 7 |
4 files changed, 36 insertions, 13 deletions
diff --git a/src/session.cpp b/src/session.cpp index d561a51..50eaff4 100644 --- a/src/session.cpp +++ b/src/session.cpp @@ -29,7 +29,6 @@ CSession::~CSession() { #endif m_sockfd.reset(); - self->second.reset(); log(LOG, "Client {}@{} disconnected", m_name, m_ip); log(TRACE, "session({}@{}): bye", m_name, m_ip); @@ -158,10 +157,9 @@ bool CSession::isValid() { if (!m_sockfd.isValid() || m_name.empty()) return false; - if (send(m_sockfd.get(), "", 0, MSG_NOSIGNAL) < 0) - return false; - - return true; + int err = 0; + socklen_t size = sizeof(err); + return getsockopt(m_sockfd.get(), SOL_SOCKET, SO_ERROR, &err, &size) >= 0 && err == 0; } template <typename... Args> @@ -208,7 +206,8 @@ void CSession::setSelf(std::pair<std::jthread, std::shared_ptr<CSession>> *self) this->self = self; } -void CSession::onShutdown() { - write("Shutting down, bye"); - g_pSessionManager->removeSession(self); +void CSession::onKick(const std::string &reason, const bool &kill) { + if (!reason.empty()) + write(reason); + g_pSessionManager->removeSession(self, kill); } diff --git a/src/session.hpp b/src/session.hpp index a00168f..390cd71 100644 --- a/src/session.hpp +++ b/src/session.hpp @@ -64,7 +64,7 @@ class CSession { void onRecv(const SRecvData &data); void onSend(const std::string &msg); #endif - void onShutdown(); + void onKick(const std::string &reason = "", const bool &kill = false); friend class CSessionManager; }; diff --git a/src/sessionManager.cpp b/src/sessionManager.cpp index 20f6820..c62402c 100644 --- a/src/sessionManager.cpp +++ b/src/sessionManager.cpp @@ -2,12 +2,13 @@ #include "log.hpp" #include "session.hpp" #include <algorithm> +#include <cstring> #include <unistd.h> #include <utility> void CSessionManager::shutdownSessions() { for (const auto &[thread, session] : m_vSessions) - session->onShutdown(); + session->onKick("Server shutting down"); } CSessionManager::CSessionManager() { @@ -57,13 +58,33 @@ 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) { +const CSession *CSessionManager::getByName(const std::string &name) const { + auto it = std::ranges::find_if(m_vSessions, [&name](const auto &s) { return s.second->getName() == name; }); + return it != m_vSessions.end() ? it->second.get() : nullptr; +} + +const CSession *CSessionManager::getByIp(const char m_ip[INET_ADDRSTRLEN]) const { + auto it = std::ranges::find_if(m_vSessions, [&m_ip](const auto &s) { log(LOG, s.second->m_ip); return strcmp(s.second->m_ip, m_ip) == 0; }); + return it != m_vSessions.end() ? it->second.get() : nullptr; +} + +void CSessionManager::kick(const CSession *session, const std::string &reason) const { + std::ranges::for_each(m_vSessions, [session, reason](const auto &s) { + if (s.second.get() == session) + s.second->onKick(reason, true); + }); +} + +void CSessionManager::removeSession(std::pair<std::jthread, std::shared_ptr<CSession>> *session, const bool &kill) { auto it = std::ranges::find_if(m_vSessions, [session](const auto &s) { return s.second.get() == session->second.get(); }); if (it != m_vSessions.end()) { + const auto native_handle = it->first.native_handle(); if (it->first.joinable()) it->first.detach(); // .detach the thread since it's removing itself it->second.reset(); m_vSessions.erase(it); + if (kill && native_handle != 0) + pthread_cancel(native_handle); } } diff --git a/src/sessionManager.hpp b/src/sessionManager.hpp index 21c47b9..79fa372 100644 --- a/src/sessionManager.hpp +++ b/src/sessionManager.hpp @@ -15,13 +15,16 @@ class CSessionManager { void run(); void broadcast(const std::string &msg) const; - void kick(const CSession *session) const; + void kick(const CSession *session, const std::string &reason = "") const; void addSession(const CSession &session); - void removeSession(std::pair<std::jthread, std::shared_ptr<CSession>> *session); + void removeSession(std::pair<std::jthread, std::shared_ptr<CSession>> *session, const bool &kill = false); bool nameExists(const std::string &name); void shutdownSessions(); + const CSession *getByName(const std::string &name) const; + const CSession *getByIp(const char m_ip[INET_ADDRSTRLEN]) const; + private: void broadcastChat(const std::string &msg, const std::string &username) const; |
