summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorlittleblack111 <littleblack11111@gmail.com>2025-03-10 18:36:00 +0800
committerlittleblack111 <littleblack11111@gmail.com>2025-03-20 23:44:58 +0800
commit131dc244e67e3b6e9304e7076c397c761860044c (patch)
tree56f634c1a16c4e5b6eb2224ba876ca97f68e4dee /src
parent4e8644b8ab3b259a91387c93a3295092bd9757a0 (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.cpp7
-rw-r--r--src/chatManager.hpp2
-rw-r--r--src/chatServer.cpp17
-rw-r--r--src/format.hpp1
-rw-r--r--src/main.cpp24
-rw-r--r--src/server.cpp4
-rw-r--r--src/session.cpp26
-rw-r--r--src/session.hpp2
-rw-r--r--src/sessionManager.cpp29
-rw-r--r--src/sessionManager.hpp5
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;
};