diff options
| -rw-r--r-- | include/libsock/server/client.hpp | 7 | ||||
| -rw-r--r-- | include/libsock/server/clients.hpp | 11 | ||||
| -rw-r--r-- | include/libsock/server/server.hpp | 7 | ||||
| -rw-r--r-- | src/server/client.cpp | 18 | ||||
| -rw-r--r-- | src/server/clients.cpp | 37 | ||||
| -rw-r--r-- | src/server/server.cpp | 21 |
6 files changed, 56 insertions, 45 deletions
diff --git a/include/libsock/server/client.hpp b/include/libsock/server/client.hpp index 2549ef5..591bc2a 100644 --- a/include/libsock/server/client.hpp +++ b/include/libsock/server/client.hpp @@ -48,9 +48,12 @@ class Client { bool isValid(); private: - Client(SP<Server> server = pServer, SP<Clients> clients = pClients, bool track = false, bool oneShot = true); + Client(SP<Server> server, SP<Clients> clients, bool track = false, bool oneShot = true); + + WP<Client> m_self; + WP<Server> m_wpServer; + WP<Clients> m_wpClients; - WP<Client> self; SP<LibSock::CFileDescriptor> m_sockfd; sockaddr_in m_addr; socklen_t m_addrLen = sizeof(m_addr); diff --git a/include/libsock/server/clients.hpp b/include/libsock/server/clients.hpp index d8c1921..b18c043 100644 --- a/include/libsock/server/clients.hpp +++ b/include/libsock/server/clients.hpp @@ -21,10 +21,10 @@ struct SData { class Clients : public std::enable_shared_from_this<Clients> { public: - static SP<Clients> create(); + static SP<Clients> create(WP<Server> server); ~Clients(); - WP<Client> newClient(std::function<void(const WP<Client> &)> loopFunc = [](const WP<Client> &) { ; }, SP<Server> server = pServer); + SP<Client> newClient(std::function<void(const WP<Client> &)> loopFunc = [](const WP<Client> &) { ; }); void broadcast(const std::string &msg, std::optional<WP<Client>> self = std::nullopt); // second param only specified when we // want to exclude the sender @@ -44,10 +44,13 @@ class Clients : public std::enable_shared_from_this<Clients> { std::vector<std::pair<std::jthread, SP<Client>>> m_vClients; std::vector<SData> m_vDatas; - SP<Clients> get(); + WP<Clients> get(); + + WP<Clients> m_self; + WP<Server> m_wpServer; friend class Client; }; -inline SP<Clients> pClients; +inline std::vector<WP<Clients>> vpClients; } // namespace Server } // namespace LibSock diff --git a/include/libsock/server/server.hpp b/include/libsock/server/server.hpp index 225bdb0..f980c97 100644 --- a/include/libsock/server/server.hpp +++ b/include/libsock/server/server.hpp @@ -4,6 +4,7 @@ #include <memory> #include <mutex> #include <netinet/in.h> +#include <vector> namespace LibSock { namespace Server { @@ -20,10 +21,12 @@ class Server : public std::enable_shared_from_this<Server> { sockaddr_in m_addr; uint16_t m_port; - SP<Server> get(); + WP<Server> get(); + + WP<Server> m_self; mutable std::mutex m_mutex; }; -inline SP<Server> pServer; +inline std::vector<SP<Server>> vpServer; } // namespace Server } // namespace LibSock diff --git a/src/server/client.cpp b/src/server/client.cpp index 6e42b69..e84a654 100644 --- a/src/server/client.cpp +++ b/src/server/client.cpp @@ -16,16 +16,16 @@ using namespace LibSock::Server; Client::Client(SP<Server> server, SP<Clients> clients, bool track, bool oneShot) : m_track(track) , m_oneShot(oneShot) { - pServer = std::move(server); - pClients = std::move(clients); + m_wpServer = std::move(server); + m_wpClients = std::move(clients); - if (!pClients) + if (m_wpClients.expired()) throw std::runtime_error("server:client: ClientManager doesn't exist"); - if (!pServer) + if (m_wpServer.expired()) throw std::runtime_error("server:client: Server doesn't exist"); - m_sockfd = std::make_shared<LibSock::CFileDescriptor>(accept(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 :/ + m_sockfd = std::make_shared<LibSock::CFileDescriptor>(accept(m_wpServer.lock()->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("server:client: Failed to create socket"); @@ -91,7 +91,7 @@ UP<SRecvData> Client::read(std::optional<std::function<bool(const SRecvData &)>> } if (m_track) - pClients->m_vDatas.push_back({recvData->data, self}); + m_wpClients.lock()->m_vDatas.push_back({recvData->data, m_self}); return recvData; } @@ -108,11 +108,11 @@ void Client::runLoop(bool resumeHist, std::optional<std::function<bool(const SRe recvLoop(cb); - pClients->kick(self); + m_wpClients.lock()->kick(m_self); } void Client::resumeHistory() { - for (const auto &chat : pClients->getDatas()) + for (const auto &chat : m_wpClients.lock()->getDatas()) write(chat.msg); } diff --git a/src/server/clients.cpp b/src/server/clients.cpp index e1dd161..a274224 100644 --- a/src/server/clients.cpp +++ b/src/server/clients.cpp @@ -2,7 +2,6 @@ #include "libsock/server/client.hpp" #include <algorithm> #include <ranges> -#include <stdexcept> #include <unistd.h> #include <utility> @@ -29,24 +28,25 @@ void Clients::shutdownClients(std::optional<std::function<bool(const std::vector Clients::Clients() { if (std::atexit([]() { - if (pClients) - pClients->shutdownClients(); + for (auto c : vpClients) + if (const auto p = c.lock()) + p->shutdownClients(); })) void(); // failed to register exit handler... } -SP<Clients> Clients::create() { - if (pClients) - throw std::runtime_error("server:clients ClientManager already exist"); - - pClients = SP<Clients>(new Clients()); - return pClients; +SP<Clients> Clients::create(WP<Server> server) { + auto c = SP<Clients>(new Clients()); + vpClients.emplace_back(c); + c->m_self = c; + c->m_wpServer = server; + return c; } -SP<Clients> Clients::get() { - if (!pClients) - pClients = shared_from_this(); - return pClients; +WP<Clients> Clients::get() { + if (m_self.expired()) + m_self = shared_from_this(); + return m_self; } Clients::~Clients() { @@ -55,13 +55,14 @@ Clients::~Clients() { thread.detach(); kick(WP<Client>(client)); } + vpClients.erase(std::remove_if(vpClients.begin(), vpClients.end(), [this](const WP<Clients> &wptr) { return !wptr.owner_before(m_self) && !m_self.owner_before(wptr); }), vpClients.end()); } -WP<Client> Clients::newClient(std::function<void(const WP<Client> &)> loopFunc, SP<Server> server) { - SP client = SP<Client>(new Client(server, shared_from_this())); - auto &instance = m_vClients.emplace_back(std::jthread([&client, &loopFunc]() { loopFunc(client); }), client); - instance.second->self = std::weak_ptr<Client>(instance.second); - return instance.second; +SP<Client> Clients::newClient(std::function<void(const WP<Client> &)> loopFunc) { + SP client = SP<Client>(new Client(m_wpServer.lock(), shared_from_this())); + auto &instance = m_vClients.emplace_back(std::jthread([&client, &loopFunc]() { loopFunc(client); }), client); + instance.second->m_self = std::weak_ptr<Client>(instance.second); + return client; } void Clients::broadcast(const std::string &msg, std::optional<std::weak_ptr<Client>> self) { diff --git a/src/server/server.cpp b/src/server/server.cpp index c14a39e..aabbb50 100644 --- a/src/server/server.cpp +++ b/src/server/server.cpp @@ -1,6 +1,7 @@ #include "libsock/server/server.hpp" #include "libsock/types.hpp" #include "misc/FileDescriptor.hpp" +#include <algorithm> #include <cstring> #include <mutex> #include <stdexcept> @@ -14,8 +15,6 @@ namespace Server { Server::Server(uint16_t port, bool reuseaddr, bool keepalive) : m_sockfd(std::make_shared<LibSock::CFileDescriptor>(socket(AF_INET, SOCK_STREAM, 0))) , m_port(port) { - if (pServer) - throw std::runtime_error("server:server Server already exist"); std::lock_guard<std::mutex> lk(m_mutex); if (!m_sockfd->isValid() || m_sockfd->get() < 0) throw std::runtime_error("server:server Failed to create socket"); @@ -37,20 +36,22 @@ Server::Server(uint16_t port, bool reuseaddr, bool keepalive) } SP<Server> Server::create(uint16_t port, bool reuseaddr, bool keepalive) { - if (pServer) - throw std::runtime_error("server:server Server already exist"); - pServer = SP<Server>(new Server(port, reuseaddr, keepalive)); - return pServer; + auto c = SP<Server>(new Server(port, reuseaddr, keepalive)); + vpServer.emplace_back(c); + c->m_self = c; + return c; } -SP<Server> Server::get() { - if (!pServer) - pServer = shared_from_this(); - return pServer; +WP<Server> Server::get() { + std::lock_guard<std::mutex> lk(m_mutex); + if (m_self.expired()) + m_self = shared_from_this(); + return m_self; } Server::~Server() { m_sockfd.reset(); + vpServer.erase(std::remove_if(vpServer.begin(), vpServer.end(), [this](const SP<Server> &sptr) { return sptr.get() == this; }), vpServer.end()); } SP<LibSock::CFileDescriptor> Server::getSocket() const { |
