summaryrefslogtreecommitdiff
path: root/src/sessionManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/sessionManager.cpp')
-rw-r--r--src/sessionManager.cpp98
1 files changed, 55 insertions, 43 deletions
diff --git a/src/sessionManager.cpp b/src/sessionManager.cpp
index de55480..7ed1a8e 100644
--- a/src/sessionManager.cpp
+++ b/src/sessionManager.cpp
@@ -13,8 +13,22 @@ void CSessionManager::shutdownSessions() {
if (m_vSessions.empty())
return;
- for (auto &session : m_vSessions)
- kick(&session, false, "Server shutting down");
+ for (auto &[thread, session] : m_vSessions) {
+ if (session) {
+ session->setDeaf(false);
+ session->write("Server shutting down");
+ if (!session->getName().empty())
+ g_pSessionManager->broadcast(NFormatter::fmt(NONEWLINE, "{} has left the chat", session->getName()), std::weak_ptr<CSession>(session));
+ }
+ }
+
+ for (auto &[thread, session] : m_vSessions) {
+ if (thread.joinable())
+ thread.detach();
+ session.reset();
+ }
+
+ m_vSessions.clear();
}
CSessionManager::CSessionManager() {
@@ -31,17 +45,16 @@ CSessionManager::~CSessionManager() {
for (auto &[thread, session] : m_vSessions) {
if (thread.joinable())
thread.detach();
- kick(session.get());
+ kick(std::weak_ptr<CSession>(session));
}
log(SYS, "SessionManager: bye");
}
-std::pair<std::jthread, std::shared_ptr<CSession>> *CSessionManager::newSession() {
+void CSessionManager::newSession() {
std::shared_ptr session = std::make_shared<CSession>();
- const auto instance = &m_vSessions.emplace_back(std::jthread(&CSession::run, session.get()), session);
- instance->second->setSelf(instance);
- return instance;
+ auto &instance = m_vSessions.emplace_back(std::jthread([session]() { session->run(); }), session);
+ instance.second->self = std::weak_ptr<CSession>(instance.second);
}
void CSessionManager::run() {
@@ -49,9 +62,9 @@ void CSessionManager::run() {
newSession();
}
-void CSessionManager::broadcast(const std::string &msg, std::optional<const CSession *const> self) const {
+void CSessionManager::broadcast(const std::string &msg, std::optional<std::weak_ptr<CSession>> self) const {
for (const auto &[thread, session] : m_vSessions)
- if (!self || (self && session.get() != *self))
+ if (!self || (self && session != self->lock()))
session->write(msg);
g_pIOManager->addCustom({"", msg});
@@ -73,7 +86,7 @@ bool CSessionManager::nameExists(const std::string &name) {
if (it != m_vSessions.end()) {
if (!it->second->isValid()) {
- kick(it->second.get(), true, "Connection lost");
+ kick(std::weak_ptr<CSession>(it->second), true, "Connection lost");
return false;
}
return true;
@@ -81,49 +94,48 @@ bool CSessionManager::nameExists(const std::string &name) {
return false;
}
-CSession *CSessionManager::getByName(const std::string &name) const {
+std::shared_ptr<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;
+ return it != m_vSessions.end() ? it->second : nullptr;
}
-CSession *CSessionManager::getByIp(const std::string &ip) const {
- auto it = std::ranges::find_if(m_vSessions, [&ip](const auto &s) { log(LOG, s.second->m_ip); return s.second->m_ip == ip; });
- return it != m_vSessions.end() ? it->second.get() : nullptr;
+std::shared_ptr<CSession> CSessionManager::getByIp(const std::string &ip) const {
+ auto it = std::ranges::find_if(m_vSessions, [&ip](const auto &s) { log(LOG, s.second->getIp()); return s.second->getIp() == ip; });
+ return it != m_vSessions.end() ? it->second : nullptr;
}
std::vector<std::shared_ptr<CSession>> CSessionManager::getSessions() const {
return m_vSessions | std::views::transform([](const auto &s) { return s.second; }) | std::ranges::to<std::vector>();
}
-void CSessionManager::kick(CSession *session, const bool kill, const std::string &reason) {
- for (auto &_session : m_vSessions)
- if (_session.second.get() == session)
- kick(&_session, kill, reason);
-}
-
-void CSessionManager::kick(std::pair<std::jthread, std::shared_ptr<CSession>> *session, const bool kill, const std::string &reason) {
- auto it = std::ranges::find_if(m_vSessions, [session](const auto &s) { return s.second.get() == session->second.get(); });
-
- if (session->second)
- // this only exist when the session is registered
- // not sure why the second is null, but m_name definately is since it's setted during register
- // but we don't need to notify people if the session didn't even "join"/register anyways
- g_pSessionManager->broadcast(NFormatter::fmt(NONEWLINE, "{} has left the chat", session->second->m_name), session->second.get());
+void CSessionManager::kick(std::weak_ptr<CSession> session_weak, const bool kill, const std::string &reason) {
+ auto session = session_weak.lock();
+ if (!session)
+ return;
- if (it != m_vSessions.end()) {
- if (!reason.empty()) {
- it->second->setDeaf(false);
- it->second->write(reason);
+ for (auto it = m_vSessions.begin(); it != m_vSessions.end(); ++it) {
+ if (it->second == session) {
+ if (session)
+ // this only exist when the session is registered
+ // not sure why the second is null, but m_name definately is since it's setted during register
+ // but we don't need to notify people if the session didn't even "join"/register anyways
+ g_pSessionManager->broadcast(NFormatter::fmt(NONEWLINE, "{} has left the chat", session->getName()), session_weak);
+
+ if (!reason.empty()) {
+ session->setDeaf(false);
+ session->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
+ it->second.reset();
+ m_vSessions.erase(it);
+ if (kill && native_handle != 0)
+ // cancel(terminal/kill) the thread if it doesn't exit on its own
+ // pthread_cancel cuz it's the safest https://stackoverflow.com/a/3438576
+ // need a condition because it might crash if the thread is already dead
+ pthread_cancel(native_handle);
+ return;
}
- 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)
- // cancel(terminal/kill) the thread if it doesn't exit on its own
- // pthread_cancel cuz it's the safest https://stackoverflow.com/a/3438576
- // need a condition because it might crash if the thread is already dead
- pthread_cancel(native_handle);
}
}