From 3ad8cca9f6fecfb4c1f70f0a8c9d4b860f4c2df3 Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Thu, 12 Jun 2025 21:03:17 +0800 Subject: internal!: refactored to smart pointer --- gdb.txt | 277 ++++++++++++++++++++++++++++++++++++++++++++ src/chatManager.cpp | 2 +- src/chatManager.hpp | 8 +- src/commandHandler.cpp | 35 +++--- src/commandHandler.hpp | 10 +- src/commands.cpp | 4 +- src/core/sessionManager.hpp | 36 ++++++ src/misc/macros.hpp | 4 + src/session.cpp | 13 +-- src/session.hpp | 18 +-- src/sessionManager.cpp | 98 +++++++++------- src/sessionManager.hpp | 15 ++- 12 files changed, 426 insertions(+), 94 deletions(-) create mode 100644 gdb.txt create mode 100644 src/core/sessionManager.hpp create mode 100644 src/misc/macros.hpp diff --git a/gdb.txt b/gdb.txt new file mode 100644 index 0000000..313f5cc --- /dev/null +++ b/gdb.txt @@ -0,0 +1,277 @@ +#0 __pthread_kill_implementation (threadid=, signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44 + tid = + ret = 0 + pd = + old_mask = {__val = {140737488338160}} + ret = +#1 0x00007ffff6aa7813 in __pthread_kill_internal (threadid=, signo=6) at pthread_kill.c:89 +No locals. +#2 0x00007ffff6a4ddc0 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26 + ret = +#3 0x00007ffff6a3557a in __GI_abort () at abort.c:73 + act = {__sigaction_handler = {sa_handler = 0x7fffffffbe00, sa_sigaction = 0x7fffffffbe00}, sa_mask = {__val = {140737488338088, 140737488338160, 93824992426177, 140737488338080, 93824993119967, 93824993119967, 140737488338432, 0, 0, 93824993119967, 93824993119967, 93824993119967, 140737488338432, 140737488338160, 12145864995241784576, 140737488338432}}, sa_flags = -16560, sa_restorer = 0x7fffffffbd10} +#4 0x00007ffff749a421 in std::__glibcxx_assert_fail (file=, line=, function=, condition=) at /usr/src/debug/gcc/gcc/libstdc++-v3/src/c++11/assert_fail.cc:41 +No locals. +#5 0x00005555555bf236 in std::optional::operator-> (this=0x7dfff5be00e8) at /usr/include/c++/15.1.1/optional:1165 + __PRETTY_FUNCTION__ = "constexpr const _Tp* std::optional<_Tp>::operator->() const [with _Tp = CIOManager::SLog]" +#6 0x00005555555bbd75 in operator() (__closure=0x7c7ff5be1260) at /home/system/Code/projects/chat-server/src/io/inputManager.cpp:35 + chat = std::optional [no contained value] + __for_range = std::vector of length 19, capacity 32 = {{msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Creating SessionManager"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "SessionManager: initialized"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Creating ChatManager"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "ChatManager: initialized"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Creating CommandHandler"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "CommandHandler: initialized"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "CommandHandler: registered command: raw"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "CommandHandler: registered command: kick"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "CommandHandler: registered command: list"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "CommandHandler: registered command: mute"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "CommandHandler: registered command: unmute"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Client 127.0.0.1 connected on port 56570"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "session: initialized"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "Client @127.0.0.1 connected"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Sent: Name: "}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "Received: dfa\n"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Client 127.0.0.1 registered as: dfa"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional [no contained value], custom = std::optional containing None = {first = "", second = "dfa has joined the chat"}}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Sent: dfa: "}}, custom = std::optional [no contained value]}} + __for_begin = {msg = std::optional [no contained value], log = std::optional [no contained value], custom = std::optional [no contained value]} + __for_end = {msg = std::optional [no contained value], log = std::optional [no contained value], custom = std::optional [no contained value]} + log = std::optional [no contained value] + custom = std::optional [no contained value] + messages = std::vector of length 0, capacity 0 +#7 0x00005555555be27e in std::__invoke_impl, CInputManager::CInputManager()::&>(std::__invoke_other, struct {...} &) (__f=...) at /usr/include/c++/15.1.1/bits/invoke.h:63 +No locals. +#8 0x00005555555bdbe1 in std::__invoke_r, CInputManager::CInputManager()::&>(struct {...} &) (__fn=...) at /usr/include/c++/15.1.1/bits/invoke.h:118 +No locals. +#9 0x00005555555bd3f3 in std::_Function_handler(), CInputManager::CInputManager():: >::_M_invoke(const std::_Any_data &) (__functor=...) at /usr/include/c++/15.1.1/bits/std_function.h:293 +No locals. +#10 0x00005555555db9d4 in ftxui::Renderer(std::function ()>)::Impl::OnRender() () +No symbol table info available. +#11 0x00005555555cb003 in ftxui::ComponentBase::Render() () +No symbol table info available. +#12 0x00005555555cb366 in ftxui::ComponentBase::OnRender() () +No symbol table info available. +#13 0x00005555555cb259 in ftxui::ComponentBase::Render() () +No symbol table info available. +#14 0x00005555555c4d16 in ftxui::CScrollerBase::OnRender (this=0x7c7ff5be12b0) at /home/system/Code/projects/chat-server/src/io/scroller.cpp:29 + focused = 0x5555556016c0 )> + style = 0x55555560d3c0 )> + background = std::shared_ptr (use count 1207959552, weak count 361840012) = {get() = 0x7ffff6a37769 <__libc_start_main_impl+137>} +#15 0x00005555555cb003 in ftxui::ComponentBase::Render() () +No symbol table info available. +#16 0x00005555555dd8fa in ftxui::(anonymous namespace)::ResizableSplitBase::OnRender() () +No symbol table info available. +#17 0x00005555555cb003 in ftxui::ComponentBase::Render() () +No symbol table info available. +#18 0x00005555555cb366 in ftxui::ComponentBase::OnRender() () +No symbol table info available. +#19 0x00005555555cb003 in ftxui::ComponentBase::Render() () +No symbol table info available. +#20 0x00005555555bc960 in operator() (__closure=0x7c7ff5be1460) at /home/system/Code/projects/chat-server/src/io/inputManager.cpp:67 + this = 0x7caff5be0040 +#21 0x00005555555be44a in std::__invoke_impl, CInputManager::inputLoop()::&>(std::__invoke_other, struct {...} &) (__f=...) at /usr/include/c++/15.1.1/bits/invoke.h:63 +No locals. +#22 0x00005555555bdef4 in std::__invoke_r, CInputManager::inputLoop()::&>(struct {...} &) (__fn=...) at /usr/include/c++/15.1.1/bits/invoke.h:118 +No locals. +#23 0x00005555555bd5f4 in std::_Function_handler(), CInputManager::inputLoop():: >::_M_invoke(const std::_Any_data &) (__functor=...) at /usr/include/c++/15.1.1/bits/std_function.h:293 +No locals. +#24 0x00005555555db9d4 in ftxui::Renderer(std::function ()>)::Impl::OnRender() () +No symbol table info available. +#25 0x00005555555cb003 in ftxui::ComponentBase::Render() () +No symbol table info available. +#26 0x00005555555e6b23 in ftxui::ScreenInteractive::Draw(std::shared_ptr) () +No symbol table info available. +#27 0x00005555555e9d5d in ftxui::ScreenInteractive::RunOnce(std::shared_ptr) () +No symbol table info available. +#28 0x00005555555eaac3 in ftxui::ScreenInteractive::RunOnceBlocking(std::shared_ptr) () +No symbol table info available. +#29 0x00005555555f967f in ftxui::Loop::RunOnceBlocking() () +No symbol table info available. +#30 0x00005555555f9751 in ftxui::Loop::Run() () +No symbol table info available. +#31 0x00005555555e3496 in ftxui::ScreenInteractive::Loop(std::shared_ptr) () +No symbol table info available. +#32 0x00005555555c2759 in CRenderManager::enterLoop (this=0x7d2ff5be0040) at /home/system/Code/projects/chat-server/src/io/renderManager.cpp:33 +No locals. +#33 0x00005555555bcc36 in CInputManager::inputLoop (this=0x7caff5be0040) at /home/system/Code/projects/chat-server/src/io/inputManager.cpp:70 +No locals. +#34 0x00005555555aa3fe in CChatServer::start (this=0x7c2ff5be0100) at /home/system/Code/projects/chat-server/src/core/chatServer.cpp:67 +No locals. +#35 0x00005555555c73b7 in main (argc=2, argv=0x7fffffffd088) at /home/system/Code/projects/chat-server/src/main.cpp:70 + args = std::vector of length 1, capacity 1 = {"8080"} + port = 8080 +#0 __pthread_kill_implementation (threadid=, signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44 + tid = + ret = 0 + pd = + old_mask = {__val = {140737488338160}} + ret = +#1 0x00007ffff6aa7813 in __pthread_kill_internal (threadid=, signo=6) at pthread_kill.c:89 +No locals. +#2 0x00007ffff6a4ddc0 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26 + ret = +#3 0x00007ffff6a3557a in __GI_abort () at abort.c:73 + act = {__sigaction_handler = {sa_handler = 0x7fffffffbe00, sa_sigaction = 0x7fffffffbe00}, sa_mask = {__val = {140737488338088, 140737488338160, 93824992426177, 140737488338112, 93824993119967, 93824993119967, 140737488338432, 0, 0, 93824993119967, 93824993119967, 93824993119967, 140737488338432, 140737488338160, 910566293388473600, 140737488338432}}, sa_flags = -16560, sa_restorer = 0x7fffffffbd10} +#4 0x00007ffff749a421 in std::__glibcxx_assert_fail (file=, line=, function=, condition=) at /usr/src/debug/gcc/gcc/libstdc++-v3/src/c++11/assert_fail.cc:41 +No locals. +#5 0x00005555555bf1c8 in std::optional::operator-> (this=0x7dfff5be0628) at /usr/include/c++/15.1.1/optional:1165 + __PRETTY_FUNCTION__ = "constexpr const _Tp* std::optional<_Tp>::operator->() const [with _Tp = CIOManager::SLog]" +#6 0x00005555555bbd4b in operator() (__closure=0x7c7ff5be1260) at /home/system/Code/projects/chat-server/src/io/inputManager.cpp:35 + chat = std::optional [no contained value] + __for_range = std::vector of length 19, capacity 32 = {{msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Creating SessionManager"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "SessionManager: initialized"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Creating ChatManager"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "ChatManager: initialized"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Creating CommandHandler"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "CommandHandler: initialized"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "CommandHandler: registered command: raw"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "CommandHandler: registered command: kick"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "CommandHandler: registered command: list"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "CommandHandler: registered command: mute"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "CommandHandler: registered command: unmute"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Client 127.0.0.1 connected on port 51028"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "session: initialized"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "Client @127.0.0.1 connected"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Sent: Name: "}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "Received: asdf\n"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Client 127.0.0.1 registered as: asdf"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional [no contained value], custom = std::optional containing None = {first = "", second = "asdf has joined the chat"}}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Sent: asdf: "}}, custom = std::optional [no contained value]}} + __for_begin = {msg = std::optional [no contained value], log = std::optional [no contained value], custom = std::optional [no contained value]} + __for_end = {msg = std::optional [no contained value], log = std::optional [no contained value], custom = std::optional [no contained value]} + log = std::optional [no contained value] + custom = std::optional [no contained value] + messages = std::vector of length 6, capacity 8 = {warning: RTTI symbol not found for class 'std::_Sp_counted_ptr_inplace, (__gnu_cxx::_Lock_policy)2>' +warning: RTTI symbol not found for class 'std::_Sp_counted_ptr_inplace, (__gnu_cxx::_Lock_policy)2>' +std::shared_ptr (use count 1, weak count 0) = {get() = 0x7ccff5be7070}, warning: RTTI symbol not found for class 'std::_Sp_counted_ptr_inplace, (__gnu_cxx::_Lock_policy)2>' +warning: RTTI symbol not found for class 'std::_Sp_counted_ptr_inplace, (__gnu_cxx::_Lock_policy)2>' +std::shared_ptr (use count 1, weak count 0) = {get() = 0x7ccff5be7140}, warning: RTTI symbol not found for class 'std::_Sp_counted_ptr_inplace, (__gnu_cxx::_Lock_policy)2>' +warning: RTTI symbol not found for class 'std::_Sp_counted_ptr_inplace, (__gnu_cxx::_Lock_policy)2>' +std::shared_ptr (use count 1, weak count 0) = {get() = 0x7ccff5be7210}, warning: RTTI symbol not found for class 'std::_Sp_counted_ptr_inplace, (__gnu_cxx::_Lock_policy)2>' +warning: RTTI symbol not found for class 'std::_Sp_counted_ptr_inplace, (__gnu_cxx::_Lock_policy)2>' +std::shared_ptr (use count 1, weak count 0) = {get() = 0x7ccff5be72e0}, warning: RTTI symbol not found for class 'std::_Sp_counted_ptr_inplace, (__gnu_cxx::_Lock_policy)2>' +warning: RTTI symbol not found for class 'std::_Sp_counted_ptr_inplace, (__gnu_cxx::_Lock_policy)2>' +std::shared_ptr (use count 1, weak count 0) = {get() = 0x7ccff5be73b0}, warning: RTTI symbol not found for class 'std::_Sp_counted_ptr_inplace, (__gnu_cxx::_Lock_policy)2>' +warning: RTTI symbol not found for class 'std::_Sp_counted_ptr_inplace, (__gnu_cxx::_Lock_policy)2>' +std::shared_ptr (use count 1, weak count 0) = {get() = 0x7ccff5be7480}} +#7 0x00005555555be22a in std::__invoke_impl, CInputManager::CInputManager()::&>(std::__invoke_other, struct {...} &) (__f=...) at /usr/include/c++/15.1.1/bits/invoke.h:63 +No locals. +#8 0x00005555555bdb8d in std::__invoke_r, CInputManager::CInputManager()::&>(struct {...} &) (__fn=...) at /usr/include/c++/15.1.1/bits/invoke.h:118 +No locals. +#9 0x00005555555bd39f in std::_Function_handler(), CInputManager::CInputManager():: >::_M_invoke(const std::_Any_data &) (__functor=...) at /usr/include/c++/15.1.1/bits/std_function.h:293 +No locals. +#10 0x00005555555db954 in ftxui::Renderer(std::function ()>)::Impl::OnRender() () +No symbol table info available. +#11 0x00005555555caf83 in ftxui::ComponentBase::Render() () +No symbol table info available. +#12 0x00005555555cb2e6 in ftxui::ComponentBase::OnRender() () +No symbol table info available. +#13 0x00005555555cb1d9 in ftxui::ComponentBase::Render() () +No symbol table info available. +#14 0x00005555555c4c8e in ftxui::CScrollerBase::OnRender (this=0x7c7ff5be12b0) at /home/system/Code/projects/chat-server/src/io/scroller.cpp:29 + focused = 0x555555601640 )> + style = 0x55555560d340 )> + background = std::shared_ptr (use count 1207959552, weak count 361840012) = {get() = 0x7ffff6a37769 <__libc_start_main_impl+137>} +#15 0x00005555555caf83 in ftxui::ComponentBase::Render() () +No symbol table info available. +#16 0x00005555555dd87a in ftxui::(anonymous namespace)::ResizableSplitBase::OnRender() () +No symbol table info available. +#17 0x00005555555caf83 in ftxui::ComponentBase::Render() () +No symbol table info available. +#18 0x00005555555cb2e6 in ftxui::ComponentBase::OnRender() () +No symbol table info available. +#19 0x00005555555caf83 in ftxui::ComponentBase::Render() () +No symbol table info available. +#20 0x00005555555bc90c in operator() (__closure=0x7c7ff5be1460) at /home/system/Code/projects/chat-server/src/io/inputManager.cpp:67 + this = 0x7caff5be0040 +#21 0x00005555555be3f6 in std::__invoke_impl, CInputManager::inputLoop()::&>(std::__invoke_other, struct {...} &) (__f=...) at /usr/include/c++/15.1.1/bits/invoke.h:63 +No locals. +#22 0x00005555555bdea0 in std::__invoke_r, CInputManager::inputLoop()::&>(struct {...} &) (__fn=...) at /usr/include/c++/15.1.1/bits/invoke.h:118 +No locals. +#23 0x00005555555bd5a0 in std::_Function_handler(), CInputManager::inputLoop():: >::_M_invoke(const std::_Any_data &) (__functor=...) at /usr/include/c++/15.1.1/bits/std_function.h:293 +No locals. +#24 0x00005555555db954 in ftxui::Renderer(std::function ()>)::Impl::OnRender() () +No symbol table info available. +#25 0x00005555555caf83 in ftxui::ComponentBase::Render() () +No symbol table info available. +#26 0x00005555555e6aa3 in ftxui::ScreenInteractive::Draw(std::shared_ptr) () +No symbol table info available. +#27 0x00005555555e9cdd in ftxui::ScreenInteractive::RunOnce(std::shared_ptr) () +No symbol table info available. +#28 0x00005555555eaa43 in ftxui::ScreenInteractive::RunOnceBlocking(std::shared_ptr) () +No symbol table info available. +#29 0x00005555555f95ff in ftxui::Loop::RunOnceBlocking() () +No symbol table info available. +#30 0x00005555555f96d1 in ftxui::Loop::Run() () +No symbol table info available. +#31 0x00005555555e3416 in ftxui::ScreenInteractive::Loop(std::shared_ptr) () +No symbol table info available. +#32 0x00005555555c26d1 in CRenderManager::enterLoop (this=0x7d2ff5be0040) at /home/system/Code/projects/chat-server/src/io/renderManager.cpp:33 +No locals. +#33 0x00005555555bcbe2 in CInputManager::inputLoop (this=0x7caff5be0040) at /home/system/Code/projects/chat-server/src/io/inputManager.cpp:70 +No locals. +#34 0x00005555555aa3fe in CChatServer::start (this=0x7c2ff5be0100) at /home/system/Code/projects/chat-server/src/core/chatServer.cpp:67 +No locals. +#35 0x00005555555c732f in main (argc=2, argv=0x7fffffffd088) at /home/system/Code/projects/chat-server/src/main.cpp:70 + args = std::vector of length 1, capacity 1 = {"8080"} + port = 8080 +#0 __pthread_kill_implementation (threadid=, signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44 + tid = + ret = 0 + pd = + old_mask = {__val = {140737488338160}} + ret = +#1 0x00007ffff6aa7813 in __pthread_kill_internal (threadid=, signo=6) at pthread_kill.c:89 +No locals. +#2 0x00007ffff6a4ddc0 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26 + ret = +#3 0x00007ffff6a3557a in __GI_abort () at abort.c:73 + act = {__sigaction_handler = {sa_handler = 0x7fffffffbe00, sa_sigaction = 0x7fffffffbe00}, sa_mask = {__val = {140737488338088, 140737488338160, 93824992426177, 137163904475072, 93824993119967, 93824993119967, 140737488338432, 0, 0, 93824993119967, 93824993119967, 93824993119967, 140737488338432, 140737488338160, 1928843476034763008, 140737488338432}}, sa_flags = -16560, sa_restorer = 0x7fffffffbd10} +#4 0x00007ffff749a421 in std::__glibcxx_assert_fail (file=, line=, function=, condition=) at /usr/src/debug/gcc/gcc/libstdc++-v3/src/c++11/assert_fail.cc:41 +No locals. +#5 0x00005555555bf1c6 in std::optional::operator-> (this=0x7e7ff5f705c8) at /usr/include/c++/15.1.1/optional:1165 + __PRETTY_FUNCTION__ = "constexpr const _Tp* std::optional<_Tp>::operator->() const [with _Tp = CIOManager::SLog]" +#6 0x00005555555bbd7d in operator() (__closure=0x7c7ff5be1260) at /home/system/Code/projects/chat-server/src/io/inputManager.cpp:35 + chat = std::optional [no contained value] + __for_range = std::vector of length 65, capacity 128 = {{msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Creating SessionManager"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "SessionManager: initialized"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Creating ChatManager"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "ChatManager: initialized"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Creating CommandHandler"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "CommandHandler: initialized"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "CommandHandler: registered command: raw"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "CommandHandler: registered command: kick"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "CommandHandler: registered command: list"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "CommandHandler: registered command: mute"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "CommandHandler: registered command: unmute"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Server: fdsa"}}, custom = std::optional [no contained value]}, {msg = std::optional = {[contained value] = {msg = "fdsa", username = "Server", sender = std::optional [no contained value], admin = false}}, log = std::optional [no contained value], custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Server: fads"}}, custom = std::optional [no contained value]}, {msg = std::optional = {[contained value] = {msg = "fads", username = "Server", sender = std::optional [no contained value], admin = false}}, log = std::optional [no contained value], custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Server: f"}}, custom = std::optional [no contained value]}, {msg = std::optional = {[contained value] = {msg = "f", username = "Server", sender = std::optional [no contained value], admin = false}}, log = std::optional [no contained value], custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Client 127.0.0.1 connected on port 34678"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "session: initialized"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "Client @127.0.0.1 connected"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Sent: Name: "}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "Received: adsf\n"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Client 127.0.0.1 registered as: adsf"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional [no contained value], custom = std::optional containing None = {first = "", second = "adsf has joined the chat"}}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Sent: Server: fdsa\n"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Sent: Server: fads\n"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Sent: Server: f\n"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Sent: adsf: "}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "Received: asdf\n"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "adsf: asdf"}}, custom = std::optional [no contained value]}, {msg = std::optional = {[contained value] = {msg = "asdf", username = "adsf", sender = std::optional containing std::weak_ptr (expired, weak count 5) = {get() = 0x7cfff5be0050}, admin = false}}, log = std::optional [no contained value], custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Sent: adsf: "}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "Received: adsf\n"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "adsf: adsf"}}, custom = std::optional [no contained value]}, {msg = std::optional = {[contained value] = {msg = "adsf", username = "adsf", sender = std::optional containing std::weak_ptr (expired, weak count 5) = {get() = 0x7cfff5be0050}, admin = false}}, log = std::optional [no contained value], custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Sent: adsf: "}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "Received: \n"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "Empty message from adsf"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Sent: adsf: "}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "Received: adsf\n"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "adsf: adsf"}}, custom = std::optional [no contained value]}, {msg = std::optional = {[contained value] = {msg = "adsf", username = "adsf", sender = std::optional containing std::weak_ptr (expired, weak count 5) = {get() = 0x7cfff5be0050}, admin = false}}, log = std::optional [no contained value], custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Sent: adsf: "}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "Received: fads\n"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "adsf: fads"}}, custom = std::optional [no contained value]}, {msg = std::optional = {[contained value] = {msg = "fads", username = "adsf", sender = std::optional containing std::weak_ptr (expired, weak count 5) = {get() = 0x7cfff5be0050}, admin = false}}, log = std::optional [no contained value], custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Sent: adsf: "}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "Received: asdf\n"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "adsf: asdf"}}, custom = std::optional [no contained value]}, {msg = std::optional = {[contained value] = {msg = "asdf", username = "adsf", sender = std::optional containing std::weak_ptr (expired, weak count 5) = {get() = 0x7cfff5be0050}, admin = false}}, log = std::optional [no contained value], custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Sent: adsf: "}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "Received: ", '\000' ...}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional [no contained value], custom = std::optional containing None = {first = "", second = "adsf has left the chat"}}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "Client adsf@127.0.0.1 disconnected"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Client adsf@127.0.0.1 disconnected"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "session(adsf@127.0.0.1): bye"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Client 127.0.0.1 connected on port 56272"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "session: initialized"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "Client @127.0.0.1 connected"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Sent: Name: "}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "Received: ", '\000' ...}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Client 127.0.0.1 exited without even registering"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "Client @127.0.0.1 disconnected"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = LOG, log = "Client @127.0.0.1 disconnected"}}, custom = std::optional [no contained value]}, {msg = std::optional [no contained value], log = std::optional = {[contained value] = {type = TRACE, log = "session(@127.0.0.1): bye"}}, custom = std::optional [no contained value]}} + __for_begin = {msg = std::optional [no contained value], log = std::optional [no contained value], custom = std::optional [no contained value]} + __for_end = {msg = std::optional [no contained value], log = std::optional [no contained value], custom = std::optional [no contained value]} + log = std::optional [no contained value] + custom = std::optional [no contained value] + messages = std::vector of length 5, capacity 8 = {warning: RTTI symbol not found for class 'std::_Sp_counted_ptr_inplace, (__gnu_cxx::_Lock_policy)2>' +warning: RTTI symbol not found for class 'std::_Sp_counted_ptr_inplace, (__gnu_cxx::_Lock_policy)2>' +std::shared_ptr (use count 1, weak count 0) = {get() = 0x7ccff5d23c00}, warning: RTTI symbol not found for class 'std::_Sp_counted_ptr_inplace, (__gnu_cxx::_Lock_policy)2>' +warning: RTTI symbol not found for class 'std::_Sp_counted_ptr_inplace, (__gnu_cxx::_Lock_policy)2>' +std::shared_ptr (use count 1, weak count 0) = {get() = 0x7ccff5d23cd0}, warning: RTTI symbol not found for class 'std::_Sp_counted_ptr_inplace, (__gnu_cxx::_Lock_policy)2>' +warning: RTTI symbol not found for class 'std::_Sp_counted_ptr_inplace, (__gnu_cxx::_Lock_policy)2>' +std::shared_ptr (use count 1, weak count 0) = {get() = 0x7ccff5d23da0}, warning: RTTI symbol not found for class 'std::_Sp_counted_ptr_inplace, (__gnu_cxx::_Lock_policy)2>' +warning: RTTI symbol not found for class 'std::_Sp_counted_ptr_inplace, (__gnu_cxx::_Lock_policy)2>' +std::shared_ptr (use count 1, weak count 0) = {get() = 0x7ccff5d23e70}, warning: RTTI symbol not found for class 'std::_Sp_counted_ptr_inplace, (__gnu_cxx::_Lock_policy)2>' +warning: RTTI symbol not found for class 'std::_Sp_counted_ptr_inplace, (__gnu_cxx::_Lock_policy)2>' +std::shared_ptr (use count 1, weak count 0) = {get() = 0x7ccff5d23f40}} +#7 0x00005555555be25c in std::__invoke_impl, CInputManager::CInputManager()::&>(std::__invoke_other, struct {...} &) (__f=...) at /usr/include/c++/15.1.1/bits/invoke.h:63 +No locals. +#8 0x00005555555bdbbf in std::__invoke_r, CInputManager::CInputManager()::&>(struct {...} &) (__fn=...) at /usr/include/c++/15.1.1/bits/invoke.h:118 +No locals. +#9 0x00005555555bd3d1 in std::_Function_handler(), CInputManager::CInputManager():: >::_M_invoke(const std::_Any_data &) (__functor=...) at /usr/include/c++/15.1.1/bits/std_function.h:293 +No locals. +#10 0x00005555555db954 in ftxui::Renderer(std::function ()>)::Impl::OnRender() () +No symbol table info available. +#11 0x00005555555caf83 in ftxui::ComponentBase::Render() () +No symbol table info available. +#12 0x00005555555cb2e6 in ftxui::ComponentBase::OnRender() () +No symbol table info available. +#13 0x00005555555cb1d9 in ftxui::ComponentBase::Render() () +No symbol table info available. +#14 0x00005555555c4ca6 in ftxui::CScrollerBase::OnRender (this=0x7c7ff5be12b0) at /home/system/Code/projects/chat-server/src/io/scroller.cpp:29 + focused = 0x555555601640 )> + style = 0x55555560d340 )> + background = std::shared_ptr (use count 1207959552, weak count 361840012) = {get() = 0x7ffff6a37769 <__libc_start_main_impl+137>} +#15 0x00005555555caf83 in ftxui::ComponentBase::Render() () +No symbol table info available. +#16 0x00005555555dd87a in ftxui::(anonymous namespace)::ResizableSplitBase::OnRender() () +No symbol table info available. +#17 0x00005555555caf83 in ftxui::ComponentBase::Render() () +No symbol table info available. +#18 0x00005555555cb2e6 in ftxui::ComponentBase::OnRender() () +No symbol table info available. +#19 0x00005555555caf83 in ftxui::ComponentBase::Render() () +No symbol table info available. +#20 0x00005555555bc93e in operator() (__closure=0x7c7ff5be1460) at /home/system/Code/projects/chat-server/src/io/inputManager.cpp:66 + this = 0x7caff5be0040 +#21 0x00005555555be428 in std::__invoke_impl, CInputManager::inputLoop()::&>(std::__invoke_other, struct {...} &) (__f=...) at /usr/include/c++/15.1.1/bits/invoke.h:63 +No locals. +#22 0x00005555555bded2 in std::__invoke_r, CInputManager::inputLoop()::&>(struct {...} &) (__fn=...) at /usr/include/c++/15.1.1/bits/invoke.h:118 +No locals. +#23 0x00005555555bd5d2 in std::_Function_handler(), CInputManager::inputLoop():: >::_M_invoke(const std::_Any_data &) (__functor=...) at /usr/include/c++/15.1.1/bits/std_function.h:293 +No locals. +#24 0x00005555555db954 in ftxui::Renderer(std::function ()>)::Impl::OnRender() () +No symbol table info available. +#25 0x00005555555caf83 in ftxui::ComponentBase::Render() () +No symbol table info available. +#26 0x00005555555e6aa3 in ftxui::ScreenInteractive::Draw(std::shared_ptr) () +No symbol table info available. +#27 0x00005555555e9cdd in ftxui::ScreenInteractive::RunOnce(std::shared_ptr) () +No symbol table info available. +#28 0x00005555555eaa43 in ftxui::ScreenInteractive::RunOnceBlocking(std::shared_ptr) () +No symbol table info available. +#29 0x00005555555f95ff in ftxui::Loop::RunOnceBlocking() () +No symbol table info available. +#30 0x00005555555f96d1 in ftxui::Loop::Run() () +No symbol table info available. +#31 0x00005555555e3416 in ftxui::ScreenInteractive::Loop(std::shared_ptr) () +No symbol table info available. +#32 0x00005555555c26e9 in CRenderManager::enterLoop (this=0x7d2ff5be0040) at /home/system/Code/projects/chat-server/src/io/renderManager.cpp:33 +No locals. +#33 0x00005555555bcc14 in CInputManager::inputLoop (this=0x7caff5be0040) at /home/system/Code/projects/chat-server/src/io/inputManager.cpp:69 +No locals. +#34 0x00005555555aa3fe in CChatServer::start (this=0x7c2ff5be0100) at /home/system/Code/projects/chat-server/src/core/chatServer.cpp:67 +No locals. +#35 0x00005555555c7347 in main (argc=2, argv=0x7fffffffd088) at /home/system/Code/projects/chat-server/src/main.cpp:70 + args = std::vector of length 1, capacity 1 = {"8080"} + port = 8080 diff --git a/src/chatManager.cpp b/src/chatManager.cpp index e5a6398..8439673 100644 --- a/src/chatManager.cpp +++ b/src/chatManager.cpp @@ -14,7 +14,7 @@ CChatManager::~CChatManager() { void CChatManager::newMessage(const SMessage &msg) { log(LOG, "{}: {}", msg.username, msg.msg); - const auto session = msg.sender ? msg.sender->get() : g_pSessionManager->getByName(msg.username); + const auto session = msg.sender ? msg.sender->lock() : g_pSessionManager->getByName(msg.username); if (session && session->isMuted()) { session->write("You are muted"); return; diff --git a/src/chatManager.hpp b/src/chatManager.hpp index 227ef6c..bd305de 100644 --- a/src/chatManager.hpp +++ b/src/chatManager.hpp @@ -12,10 +12,10 @@ class CChatManager { CChatManager(); ~CChatManager(); struct SMessage { - std::string msg; - std::string username; - std::optional> sender = std::nullopt; - bool admin = false; + std::string msg; + std::string username; + std::optional> sender = std::nullopt; + bool admin = false; }; void newMessage(const SMessage &msg); std::string fmtBroadcastMessage(const SMessage &msg); diff --git a/src/commandHandler.cpp b/src/commandHandler.cpp index 731ea3f..e459ee0 100644 --- a/src/commandHandler.cpp +++ b/src/commandHandler.cpp @@ -1,8 +1,8 @@ #include "commandHandler.hpp" #include "log.hpp" #include "session.hpp" -#include "sessionManager.hpp" #include +#include CCommandHandler::CCommandHandler() { log(LOG, "CommandHandler: initialized"); @@ -18,8 +18,8 @@ bool CCommandHandler::isCommand(const std::string &str) const { }; bool CCommandHandler::validCommand(const std::string &command) const { - return std::ranges::any_of(m_vCommands, [&command](const SCommand &cmd) { - return cmd.name == command; + return std::ranges::any_of(m_vCommands, [&command](const std::shared_ptr &cmd) { + return cmd->name == command; }); } @@ -27,24 +27,24 @@ bool CCommandHandler::registerCommand(const SCommand &command) { if (command.name.empty() || !command.exe || !command.parser) return false; - m_vCommands.push_back(command); + m_vCommands.push_back(std::make_shared(command)); log(TRACE, "CommandHandler: registered command: {}", command.name); return true; } -const CCommandHandler::SCommand *CCommandHandler::getCommand(const std::string &command) const { - auto it = std::ranges::find_if(m_vCommands, [&command](const SCommand &cmd) { return cmd.name == command; }); +std::shared_ptr CCommandHandler::getCommand(const std::string &command) const { + auto it = std::ranges::find_if(m_vCommands, [&command](const std::shared_ptr &cmd) { return cmd->name == command; }); if (it != m_vCommands.end()) - return &*it; + return *it; return nullptr; } -CCommandHandler::SResult CCommandHandler::exeCommand(const SCommand &command, const std::string &args) const { - const auto [parsed, good] = command.parser(args); +CCommandHandler::SResult CCommandHandler::exeCommand(const std::shared_ptr command, const std::string &args) const { + const auto [parsed, good] = command->parser(args); if (!good) try { return {.result = std::any_cast(parsed), .good = false}; @@ -52,22 +52,25 @@ CCommandHandler::SResult CCommandHandler::exeCommand(const SCommand &command, co return {.result = "", .good = false}; } - log(TRACE, "CommandHandler: executing command: {}", command.name); - return command.exe(parsed); + log(TRACE, "CommandHandler: executing command: {}", command->name); + return command->exe(parsed); } -CCommandHandler::SResult CCommandHandler::newCommand(const std::string &command, const std::string &args, CSession *const user) const { +CCommandHandler::SResult CCommandHandler::newCommand(const std::string &command, const std::string &args, std::shared_ptr session) const { if (!validCommand(command)) return {.result = "Invalid command", .good = false}; - const auto cmd = getCommand(command); - if (cmd->requireAdmin && !user->isAdmin()) + auto cmd = getCommand(command); + if (!cmd) + return {.result = "Command not found", .good = false}; + + if (cmd->requireAdmin && !session->isAdmin()) return {.result = "Permission denied", .good = false}; - return exeCommand(*cmd, args); + return exeCommand(cmd, args); } -void CCommandHandler::handleCommand(std::string input, CSession *const user) const { +void CCommandHandler::handleCommand(std::string input, std::shared_ptr user) const { input = input.substr(1); std::string command; diff --git a/src/commandHandler.hpp b/src/commandHandler.hpp index bce93d2..89d19d6 100644 --- a/src/commandHandler.hpp +++ b/src/commandHandler.hpp @@ -34,8 +34,8 @@ class CCommandHandler { bool validCommand(const std::string &command) const; // return false if command struct is invalid bool registerCommand(const SCommand &command); - SResult newCommand(const std::string &command, const std::string &args, CSession *const user) const; - void handleCommand(std::string input, CSession *const user = nullptr) const; + SResult newCommand(const std::string &command, const std::string &args, std::shared_ptr session) const; + void handleCommand(std::string input, std::shared_ptr user = nullptr) const; template struct SMakeCommandArgs { @@ -63,9 +63,9 @@ class CCommandHandler { } private: - const SCommand *getCommand(const std::string &command) const; - SResult exeCommand(const SCommand &command, const std::string &args) const; + std::shared_ptr getCommand(const std::string &command) const; + SResult exeCommand(const std::shared_ptr command, const std::string &args) const; - std::vector m_vCommands; + std::vector> m_vCommands; }; inline std::unique_ptr g_pCommandHandler; diff --git a/src/commands.cpp b/src/commands.cpp index ff20b70..e7894db 100644 --- a/src/commands.cpp +++ b/src/commands.cpp @@ -41,8 +41,8 @@ void registerCommands() { if (!session) return {.result = "User '" + data.target + "' not found", .good = false}; - const auto reason = data.reason ? *data.reason : NOREASON; - g_pSessionManager->kick(session, true, reason); + const auto reason = data.reason ? *data.reason : NOREASON; + g_pSessionManager->kick(session->self, true, reason); return {.result = "Kicked '" + data.target + "': " + reason, .good = true}; }})); g_pCommandHandler->registerCommand({.requireAdmin = false, .name = "list", .parser = [](const std::string &args) -> CCommandHandler::SParseResult { diff --git a/src/core/sessionManager.hpp b/src/core/sessionManager.hpp new file mode 100644 index 0000000..e84226c --- /dev/null +++ b/src/core/sessionManager.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include "../debug/format.hpp" +#include "../misc/memory.hpp" +#include "chatManager.hpp" +#include "session.hpp" +#include +#include + +class CSessionManager { + public: + CSessionManager(); + ~CSessionManager(); + + void newSession(); + + void run(); + void broadcast(const std::string &msg, std::optional> self = std::nullopt) const; // second param only specified when we want to exclude the sender + void kick(WP session, const bool kill = false, const std::string &reason = ""); + void addSession(const CSession &session); + + bool nameExists(const std::string &name); + void shutdownSessions(); + + SP getByName(const std::string &name) const; + SP getByIp(const std::string &ip) const; + std::vector> getSessions() const; + + private: + void broadcast(const CChatManager::SMessage &msg) const; + + std::vector>> m_vSessions; + + friend class CChatManager; +}; +inline SP g_pSessionManager; diff --git a/src/misc/macros.hpp b/src/misc/macros.hpp new file mode 100644 index 0000000..02f5048 --- /dev/null +++ b/src/misc/macros.hpp @@ -0,0 +1,4 @@ +#pragma once + +#define UNLIKELY(expr) (expr) [[unlikely]] +#define LIKELY(expr) (expr) [[likely]] diff --git a/src/session.cpp b/src/session.cpp index 84f1824..126d547 100644 --- a/src/session.cpp +++ b/src/session.cpp @@ -89,9 +89,9 @@ void CSession::recvLoop() { const auto isCommand = g_pCommandHandler->isCommand(recvData->data); if (isCommand) - g_pCommandHandler->handleCommand(recvData->data, this); + g_pCommandHandler->handleCommand(recvData->data, self.lock()); - g_pChatManager->newMessage({.msg = recvData->data, .username = m_name, .sender = self->second, .admin = isCommand}); + g_pChatManager->newMessage({.msg = recvData->data, .username = m_name, .sender = self, .admin = isCommand}); } } @@ -199,7 +199,7 @@ bool CSession::registerSession() { log(LOG, "Client {} registered as: {}", m_ip, m_name); - g_pSessionManager->broadcast(NFormatter::fmt(NONEWLINE, "{} has joined the chat", m_name), this); + g_pSessionManager->broadcast(NFormatter::fmt(NONEWLINE, "{} has joined the chat", m_name), self); m_bDeaf = false; return true; @@ -219,7 +219,8 @@ bool CSession::write(const std::string &msg) { } bool CSession::writeChat(const CChatManager::SMessage &msg) { - if (msg.sender ? this != msg.sender->get() : msg.username != m_name) { + 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; @@ -240,10 +241,6 @@ bool CSession::isAdmin() const { return m_isAdmin; } -void CSession::setSelf(std::pair> *self) { - this->self = self; -} - template bool CSession::write(std::format_string fmt, Args &&...args) { if (m_bDeaf) diff --git a/src/session.hpp b/src/session.hpp index 3ec04a3..2ca274e 100644 --- a/src/session.hpp +++ b/src/session.hpp @@ -30,7 +30,6 @@ class CSession { const std::string &getName() const; const std::string &getIp() const; bool isAdmin() const; - void setSelf(std::pair> *self); std::unique_ptr read(); std::unique_ptr read(const std::string &msg, bool bypassDeaf = false); @@ -58,14 +57,14 @@ class CSession { WRITE }; - std::pair> *self; - std::shared_ptr m_sockfd; - sockaddr_in m_addr; - socklen_t m_addrLen = sizeof(m_addr); - std::string m_name; - std::string m_ip; - int m_port; - bool m_isAdmin = false; + std::weak_ptr self; + std::shared_ptr m_sockfd; + sockaddr_in m_addr; + socklen_t m_addrLen = sizeof(m_addr); + std::string m_name; + std::string m_ip; + int m_port; + bool m_isAdmin = false; std::optional m_szReading = std::nullopt; bool m_bMuted = false; @@ -85,4 +84,5 @@ class CSession { #endif friend class CSessionManager; + friend void registerCommands(); }; 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(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(session)); } log(SYS, "SessionManager: bye"); } -std::pair> *CSessionManager::newSession() { +void CSessionManager::newSession() { std::shared_ptr session = std::make_shared(); - 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(instance.second); } void CSessionManager::run() { @@ -49,9 +62,9 @@ void CSessionManager::run() { newSession(); } -void CSessionManager::broadcast(const std::string &msg, std::optional self) const { +void CSessionManager::broadcast(const std::string &msg, std::optional> 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(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 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 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> CSessionManager::getSessions() const { return m_vSessions | std::views::transform([](const auto &s) { return s.second; }) | std::ranges::to(); } -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> *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 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); } } diff --git a/src/sessionManager.hpp b/src/sessionManager.hpp index eb3705e..179d7d8 100644 --- a/src/sessionManager.hpp +++ b/src/sessionManager.hpp @@ -12,21 +12,24 @@ class CSessionManager { CSessionManager(); ~CSessionManager(); - std::pair> *newSession(); + void newSession(); void run(); - void broadcast(const std::string &msg, std::optional self = std::nullopt) const; // second param only specified when we want to exclude the sender - void kick(CSession *session, const bool kill = false, const std::string &reason = ""); - void kick(std::pair> *session, const bool kill = false, const std::string &reason = ""); + void broadcast(const std::string &msg, std::optional> self = std::nullopt) const; // second param only specified when we want to exclude the sender + void kick(std::weak_ptr session, const bool kill = false, const std::string &reason = ""); void addSession(const CSession &session); bool nameExists(const std::string &name); void shutdownSessions(); - CSession *getByName(const std::string &name) const; - CSession *getByIp(const std::string &ip) const; + std::shared_ptr getByName(const std::string &name) const; + std::shared_ptr getByIp(const std::string &ip) const; std::vector> getSessions() const; + // Safer weak_ptr versions - recommended for most use cases to avoid accidental lifetime extension + std::weak_ptr getByNameWeak(const std::string &name) const; + std::weak_ptr getByIpWeak(const std::string &ip) const; + private: void broadcast(const CChatManager::SMessage &msg) const; -- cgit v1.2.3