diff options
| author | littleblack111 <littleblack11111@gmail.com> | 2025-06-12 21:41:41 +0800 |
|---|---|---|
| committer | littleblack111 <littleblack11111@gmail.com> | 2025-06-13 20:22:51 +0800 |
| commit | 6f7b994684032060f0a2d7af82f4f3572293b8d6 (patch) | |
| tree | 793d328cbcd6761365267550b55db45aee9b21fc /src/session.cpp | |
| parent | 6a51ab4525c59e9fe2bdbd92493019b0a98c6b94 (diff) | |
internal!: organized internal structure, using cmake now
Diffstat (limited to 'src/session.cpp')
| -rw-r--r-- | src/session.cpp | 273 |
1 files changed, 0 insertions, 273 deletions
diff --git a/src/session.cpp b/src/session.cpp deleted file mode 100644 index 126d547..0000000 --- a/src/session.cpp +++ /dev/null @@ -1,273 +0,0 @@ -#include "session.hpp" -#include "chatManager.hpp" -#include "commandHandler.hpp" -#include "format.hpp" -#include "log.hpp" -#include "server.hpp" -#include "sessionManager.hpp" -#include <algorithm> -#include <arpa/inet.h> -#include <cerrno> -#include <cstring> -#include <memory> -#include <optional> -#include <sys/socket.h> - -CSession::CSession() { - m_sockfd = std::make_shared<CFileDescriptor>(accept(g_pServer->getSocket()->get(), reinterpret_cast<sockaddr *>(&m_addr), &m_addrLen)); // if this is in the init list, it will run before m_addrLen, so it won't work :/ - - if (!m_sockfd->isValid()) - throw std::runtime_error("session: Failed to create socket"); - - m_ip.resize(INET_ADDRSTRLEN); - inet_ntop(AF_INET, &m_addr.sin_addr, &m_ip[0], INET_ADDRSTRLEN); - m_ip.resize(strlen(m_ip.c_str())); - m_port = ntohs(m_addr.sin_port); - m_isAdmin = std::ranges::any_of(m_adminIps, [this](const char *ip) { return m_ip == ip; }); - - log(LOG, "Client {} connected on port {}", m_ip, m_port); - - log(TRACE, "session: initialized"); -} - -CSession::~CSession() { -#ifdef DEBUG - onDisconnect(); -#endif - m_sockfd.reset(); - - log(LOG, "Client {}@{} disconnected", m_name, m_ip); - - log(TRACE, "session({}@{}): bye", m_name, m_ip); -} - -#ifdef DEBUG -void CSession::onConnect() { - log(TRACE, "Client {}@{} connected", m_name, m_ip); -} - -void CSession::onDisconnect() { - log(TRACE, "Client {}@{} disconnected", m_name, m_ip); -} -#endif - -void CSession::onErrno(eEventType eventType) { - char errbuf[256]; - const char *err = strerror_r(errno, errbuf, sizeof(errbuf)); - - switch (eventType) { - case READ: - log(WARN, "Error while reading: {}", err); - break; - case WRITE: - log(WARN, "Error while writing: {}", err); - break; - } -} - -#ifdef DEBUG -void CSession::onRecv(const SRecvData &data) { - log(TRACE, "Received: {}", data.data); -} - -void CSession::onSend(const std::string &msg) { - log(LOG, "Sent: {}", msg); -} -#endif - -void CSession::recvLoop() { - while (true) { - auto recvData = read(NFormatter::fmt(NONEWLINE, "{}: ", m_name)); - if (!recvData->good) - break; - - recvData->sanitize(); - if (recvData->isEmpty()) { - log(TRACE, "Empty message from {}", m_name); - continue; - } - - const auto isCommand = g_pCommandHandler->isCommand(recvData->data); - if (isCommand) - g_pCommandHandler->handleCommand(recvData->data, self.lock()); - - g_pChatManager->newMessage({.msg = recvData->data, .username = m_name, .sender = self, .admin = isCommand}); - } -} - -bool CSession::SRecvData::isEmpty() const { - return data.empty() || std::ranges::all_of(data, [](char c) { return std::isspace(c); }); -} - -void CSession::SRecvData::sanitize() { - if (!data.empty() && data.back() == '\n') - data.pop_back(); - - data.erase(std::remove(data.begin(), data.end(), asciiEscape), data.end()); // don't accept ASCII code, might mess up terminal // NOLINT - - if (const auto start = data.find_first_not_of(" \t\r\n"); start != std::string::npos) { - const auto end = data.find_last_not_of(" \t\r\n"); - data = data.substr(start, end - start + 1); - } else - data.clear(); -} - -std::unique_ptr<CSession::SRecvData> CSession::read() { - auto recvData = std::make_unique<SRecvData>(); - - recvData->data.resize(recvData->size); - ssize_t size = recv(m_sockfd->get(), &recvData->data[0], recvData->size, 0); - - if (size < 0) { - recvData->good = false; - onErrno(READ); - } else if (size == 0) - recvData->good = false; - else { - recvData->data.resize(size); - recvData->good = true; - } - -#ifdef DEBUG - onRecv(*recvData); -#endif - m_szReading.reset(); - return recvData; -} - -std::unique_ptr<CSession::SRecvData> CSession::read(const std::string &msg, bool bypassDeaf) { - if (bypassDeaf && m_bDeaf) - m_bDeaf = false; - write(NONEWLINE, "{}", msg); - if (bypassDeaf && !m_bDeaf) - m_bDeaf = true; - m_szReading = msg; - return read(); -} - -void CSession::run() { -#ifdef DEBUG - onConnect(); -#endif - if (registerSession()) { - for (const auto &chat : g_pChatManager->getChat()) - writeChat(chat); - recvLoop(); - } else - log(LOG, "Client {} exited without even registering", m_ip); - - g_pSessionManager->kick(self); -} - -bool CSession::isMuted() const { - return m_bMuted; -} - -void CSession::setMuted(bool mute) { - m_bMuted = mute; -} - -bool CSession::isDeaf() const { - return m_bDeaf; -} - -void CSession::setDeaf(bool deaf) { - m_bDeaf = deaf; -} - -bool CSession::registerSession() { - auto recvData = read("Name: ", true); - if (!recvData->good) - return false; - - recvData->sanitize(); - if (recvData->isEmpty()) { - m_bDeaf = false; - write("Name cannot be empty"); - m_bDeaf = true; - return registerSession(); - } - - if (g_pSessionManager->nameExists(recvData->data)) { - m_bDeaf = false; - write("Name already exists"); - m_bDeaf = true; - return registerSession(); - } - - this->m_name = recvData->data; - - log(LOG, "Client {} registered as: {}", m_ip, m_name); - - g_pSessionManager->broadcast(NFormatter::fmt(NONEWLINE, "{} has joined the chat", m_name), self); - - m_bDeaf = false; - return true; -} - -bool CSession::isValid() { - if (!m_sockfd->isValid() || m_name.empty()) - return false; - - int err = 0; - socklen_t size = sizeof(err); - return getsockopt(m_sockfd->get(), SOL_SOCKET, SO_ERROR, &err, &size) >= 0 && err == 0; -} - -bool CSession::write(const std::string &msg) { - return write("{}", msg); -} - -bool CSession::writeChat(const CChatManager::SMessage &msg) { - const auto sender = msg.sender ? msg.sender->lock() : nullptr; - if (sender ? sender != self.lock() : msg.username != m_name) { - if (msg.admin && !m_isAdmin) - return false; - - return write(g_pChatManager->fmtBroadcastMessage(msg)); - } - return false; -} - -const std::string &CSession::getName() const { - return m_name; -} - -const std::string &CSession::getIp() const { - return m_ip; -} - -bool CSession::isAdmin() const { - return m_isAdmin; -} - -template <typename... Args> -bool CSession::write(std::format_string<Args...> fmt, Args &&...args) { - if (m_bDeaf) - return false; - return write(NONE, fmt, std::forward<Args>(args)...); -} - -template <typename... Args> -bool CSession::write(eFormatType type, std::format_string<Args...> fmt, Args &&...args) { - if (m_bDeaf) - return false; - - std::string msg = NFormatter::fmt(type, fmt, std::forward<Args>(args)...); - if (m_szReading) { - msg.insert(0, "\r"); - msg.append(*m_szReading); - } - - if (send(m_sockfd->get(), msg.c_str(), msg.size(), 0) < 0) { - onErrno(WRITE); - return false; - } -#ifdef DEBUG - onSend(msg); -#endif - return true; -} - -template bool CSession::write<const std::string &>(std::format_string<const std::string &>, const std::string &); -template bool CSession::write<const std::string &>(eFormatType, std::format_string<const std::string &>, const std::string &); |
