From 0ec82c104ded01a44ed36d20e25220fa41887fd0 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Fri, 27 Feb 2015 12:18:34 +0100 Subject: Add louloulibs as a submodule --- louloulibs | 1 + 1 file changed, 1 insertion(+) create mode 160000 louloulibs (limited to 'louloulibs/network/poller.cpp') diff --git a/louloulibs b/louloulibs new file mode 160000 index 0000000..b6af145 --- /dev/null +++ b/louloulibs @@ -0,0 +1 @@ +Subproject commit b6af145bfb9561a1bb1ecb940f50163c5ce4dbbb -- cgit v1.2.3 From e6569a1090be063f34624474f0d4578f37a169ae Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Fri, 27 Feb 2015 12:40:50 +0100 Subject: Only use include_directory() if the directory path is defined --- louloulibs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'louloulibs/network/poller.cpp') diff --git a/louloulibs b/louloulibs index b6af145..d6a3724 160000 --- a/louloulibs +++ b/louloulibs @@ -1 +1 @@ -Subproject commit b6af145bfb9561a1bb1ecb940f50163c5ce4dbbb +Subproject commit d6a3724c6a0127a49a9e7adb1090bb7438c8d0f2 -- cgit v1.2.3 From e4c696861d86b62305ca0ec8136e79f147837b94 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 2 Mar 2015 11:06:40 +0100 Subject: Update louloulibs to last revision --- louloulibs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'louloulibs/network/poller.cpp') diff --git a/louloulibs b/louloulibs index d6a3724..5f3a1bb 160000 --- a/louloulibs +++ b/louloulibs @@ -1 +1 @@ -Subproject commit d6a3724c6a0127a49a9e7adb1090bb7438c8d0f2 +Subproject commit 5f3a1bb54df4de5f332282bbdf791bdce07c71c4 -- cgit v1.2.3 From d88ec5fdf10ecb168355bc38dc81d83ff59a0234 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 2 Mar 2015 11:32:18 +0100 Subject: Update to latest louloulibs revision --- louloulibs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'louloulibs/network/poller.cpp') diff --git a/louloulibs b/louloulibs index 5f3a1bb..d0b8695 160000 --- a/louloulibs +++ b/louloulibs @@ -1 +1 @@ -Subproject commit 5f3a1bb54df4de5f332282bbdf791bdce07c71c4 +Subproject commit d0b8695ceb13e0c6d72821fe605de36e494afcdf -- cgit v1.2.3 From c243fea660723eba00b65e639b76d0783cb59064 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 4 Mar 2015 05:56:44 +0100 Subject: Update to latest louloulibs revision --- louloulibs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'louloulibs/network/poller.cpp') diff --git a/louloulibs b/louloulibs index d0b8695..99757a4 160000 --- a/louloulibs +++ b/louloulibs @@ -1 +1 @@ -Subproject commit d0b8695ceb13e0c6d72821fe605de36e494afcdf +Subproject commit 99757a44b49619ff59cae9e6d983a3b7c20c56bf -- cgit v1.2.3 From ad0465b32051e224f6a234f3ed36494905e59cbf Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 20 Apr 2015 20:33:02 +0200 Subject: Decode incoming JIDs local part according to xep 0106 This let users send message to nicks such as Q@CServe.quakenet.org fix #3047 --- louloulibs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'louloulibs/network/poller.cpp') diff --git a/louloulibs b/louloulibs index 99757a4..88d2b13 160000 --- a/louloulibs +++ b/louloulibs @@ -1 +1 @@ -Subproject commit 99757a44b49619ff59cae9e6d983a3b7c20c56bf +Subproject commit 88d2b136e5f133f0d0dc01f59449284f663d53ea -- cgit v1.2.3 From 0d706741c6b3a8bdf6b4f8ca0b1ac00cb27bd8b8 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 20 Apr 2015 20:35:32 +0200 Subject: Update louloulibs submodule to the correct revision --- louloulibs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'louloulibs/network/poller.cpp') diff --git a/louloulibs b/louloulibs index 88d2b13..b53ae92 160000 --- a/louloulibs +++ b/louloulibs @@ -1 +1 @@ -Subproject commit 88d2b136e5f133f0d0dc01f59449284f663d53ea +Subproject commit b53ae922f48f1465a7fa61136f65ec39e38a452e -- cgit v1.2.3 From a8225dc54c019788722bda3bda8d55151c1ccdef Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 21 Apr 2015 15:35:10 +0200 Subject: Properly check for connecting or connected status before reconnecting Note, in our context, is_connecting() includes the resolving part as well as the actual connection (if we are using c-ares) fix #3048 --- louloulibs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'louloulibs/network/poller.cpp') diff --git a/louloulibs b/louloulibs index b53ae92..6c812cd 160000 --- a/louloulibs +++ b/louloulibs @@ -1 +1 @@ -Subproject commit b53ae922f48f1465a7fa61136f65ec39e38a452e +Subproject commit 6c812cd86e31569db61cac4e30f77e296d207191 -- cgit v1.2.3 From 71fec776c4d7b99b76a44deae6f333d9cffa1496 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Thu, 7 May 2015 17:42:37 +0200 Subject: Update to latest louloulibs fix #3042 --- louloulibs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'louloulibs/network/poller.cpp') diff --git a/louloulibs b/louloulibs index 6c812cd..eaa4fbb 160000 --- a/louloulibs +++ b/louloulibs @@ -1 +1 @@ -Subproject commit 6c812cd86e31569db61cac4e30f77e296d207191 +Subproject commit eaa4fbba814b56b4fe7ffb62984fddfbb9280291 -- cgit v1.2.3 From fbeb5af364db54c8a82f5ea30b83df441988ea4b Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 13 May 2015 20:17:43 +0200 Subject: Update to latest louloulibs revision, and add test for hostname validity fix #2694 --- louloulibs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'louloulibs/network/poller.cpp') diff --git a/louloulibs b/louloulibs index eaa4fbb..89398b5 160000 --- a/louloulibs +++ b/louloulibs @@ -1 +1 @@ -Subproject commit eaa4fbba814b56b4fe7ffb62984fddfbb9280291 +Subproject commit 89398b5d886744c3812b65195308cae57eca2b53 -- cgit v1.2.3 From 897b281e67dc82700db9fd9c2dedc5e01e5871ee Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 27 May 2015 23:44:23 +0200 Subject: Avoid some potential race conditions by blocking the signals we manage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit They are atomically unblocked in the ppoll/epoll_pwait calls, avoiding any race condition on the check of the “stop” or “reload” booleans. --- louloulibs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'louloulibs/network/poller.cpp') diff --git a/louloulibs b/louloulibs index 89398b5..0f3c118 160000 --- a/louloulibs +++ b/louloulibs @@ -1 +1 @@ -Subproject commit 89398b5d886744c3812b65195308cae57eca2b53 +Subproject commit 0f3c1183e2bf0941ae2bffd3f31577bce4f3001c -- cgit v1.2.3 From e1a7114c8daa10589c830ce972cf461c3540111b Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Thu, 28 May 2015 23:42:52 +0200 Subject: louloulibs is directly included, instead of being a submodule Because this is a nightmare to manage --- louloulibs | 1 - louloulibs/network/poller.cpp | 225 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 225 insertions(+), 1 deletion(-) delete mode 160000 louloulibs create mode 100644 louloulibs/network/poller.cpp (limited to 'louloulibs/network/poller.cpp') diff --git a/louloulibs b/louloulibs deleted file mode 160000 index 0f3c118..0000000 --- a/louloulibs +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0f3c1183e2bf0941ae2bffd3f31577bce4f3001c diff --git a/louloulibs/network/poller.cpp b/louloulibs/network/poller.cpp new file mode 100644 index 0000000..329e1c8 --- /dev/null +++ b/louloulibs/network/poller.cpp @@ -0,0 +1,225 @@ +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +Poller::Poller() +{ +#if POLLER == POLL + this->nfds = 0; +#elif POLLER == EPOLL + this->epfd = ::epoll_create1(0); + if (this->epfd == -1) + { + log_error("epoll failed: " << strerror(errno)); + throw std::runtime_error("Could not create epoll instance"); + } +#endif +} + +Poller::~Poller() +{ +} + +void Poller::add_socket_handler(SocketHandler* socket_handler) +{ + // Don't do anything if the socket is already managed + const auto it = this->socket_handlers.find(socket_handler->get_socket()); + if (it != this->socket_handlers.end()) + return ; + + this->socket_handlers.emplace(socket_handler->get_socket(), socket_handler); + + // We always watch all sockets for receive events +#if POLLER == POLL + this->fds[this->nfds].fd = socket_handler->get_socket(); + this->fds[this->nfds].events = POLLIN; + this->nfds++; +#endif +#if POLLER == EPOLL + struct epoll_event event = {EPOLLIN, {socket_handler}}; + const int res = ::epoll_ctl(this->epfd, EPOLL_CTL_ADD, socket_handler->get_socket(), &event); + if (res == -1) + { + log_error("epoll_ctl failed: " << strerror(errno)); + throw std::runtime_error("Could not add socket to epoll"); + } +#endif +} + +void Poller::remove_socket_handler(const socket_t socket) +{ + const auto it = this->socket_handlers.find(socket); + if (it == this->socket_handlers.end()) + throw std::runtime_error("Trying to remove a SocketHandler that is not managed"); + this->socket_handlers.erase(it); + +#if POLLER == POLL + for (size_t i = 0; i < this->nfds; i++) + { + if (this->fds[i].fd == socket) + { + // Move all subsequent pollfd by one on the left, erasing the + // value of the one we remove + for (size_t j = i; j < this->nfds - 1; ++j) + { + this->fds[j].fd = this->fds[j+1].fd; + this->fds[j].events= this->fds[j+1].events; + } + this->nfds--; + } + } +#elif POLLER == EPOLL + const int res = ::epoll_ctl(this->epfd, EPOLL_CTL_DEL, socket, nullptr); + if (res == -1) + { + log_error("epoll_ctl failed: " << strerror(errno)); + throw std::runtime_error("Could not remove socket from epoll"); + } +#endif +} + +void Poller::watch_send_events(SocketHandler* socket_handler) +{ +#if POLLER == POLL + for (size_t i = 0; i <= this->nfds; ++i) + { + if (this->fds[i].fd == socket_handler->get_socket()) + { + this->fds[i].events = POLLIN|POLLOUT; + return; + } + } + throw std::runtime_error("Cannot watch a non-registered socket for send events"); +#elif POLLER == EPOLL + struct epoll_event event = {EPOLLIN|EPOLLOUT, {socket_handler}}; + const int res = ::epoll_ctl(this->epfd, EPOLL_CTL_MOD, socket_handler->get_socket(), &event); + if (res == -1) + { + log_error("epoll_ctl failed: " << strerror(errno)); + throw std::runtime_error("Could not modify socket flags in epoll"); + } +#endif +} + +void Poller::stop_watching_send_events(SocketHandler* socket_handler) +{ +#if POLLER == POLL + for (size_t i = 0; i <= this->nfds; ++i) + { + if (this->fds[i].fd == socket_handler->get_socket()) + { + this->fds[i].events = POLLIN; + return; + } + } + throw std::runtime_error("Cannot watch a non-registered socket for send events"); +#elif POLLER == EPOLL + struct epoll_event event = {EPOLLIN, {socket_handler}}; + const int res = ::epoll_ctl(this->epfd, EPOLL_CTL_MOD, socket_handler->get_socket(), &event); + if (res == -1) + { + log_error("epoll_ctl failed: " << strerror(errno)); + throw std::runtime_error("Could not modify socket flags in epoll"); + } +#endif +} + +int Poller::poll(const std::chrono::milliseconds& timeout) +{ + if (this->socket_handlers.empty() && timeout == utils::no_timeout) + return -1; +#if POLLER == POLL + // Convert our nice timeout into this ugly struct + struct timespec timeout_ts; + struct timespec* timeout_tsp; + if (timeout > 0s) + { + auto seconds = std::chrono::duration_cast(timeout); + timeout_ts.tv_sec = seconds.count(); + timeout_ts.tv_nsec = std::chrono::duration_cast(timeout - seconds).count(); + timeout_tsp = &timeout_ts; + } + else + timeout_tsp = nullptr; + + // Unblock all signals, only during the ppoll call + sigset_t empty_signal_set; + sigemptyset(&empty_signal_set); + int nb_events = ::ppoll(this->fds, this->nfds, timeout_tsp, + &empty_signal_set); + if (nb_events < 0) + { + if (errno == EINTR) + return true; + log_error("poll failed: " << strerror(errno)); + throw std::runtime_error("Poll failed"); + } + // We cannot possibly have more ready events than the number of fds we are + // watching + assert(static_cast(nb_events) <= this->nfds); + for (size_t i = 0; i <= this->nfds && nb_events != 0; ++i) + { + if (this->fds[i].revents == 0) + continue; + else if (this->fds[i].revents & POLLIN) + { + auto socket_handler = this->socket_handlers.at(this->fds[i].fd); + socket_handler->on_recv(); + nb_events--; + } + else if (this->fds[i].revents & POLLOUT) + { + auto socket_handler = this->socket_handlers.at(this->fds[i].fd); + if (socket_handler->is_connected()) + socket_handler->on_send(); + else + socket_handler->connect(); + nb_events--; + } + } + return 1; +#elif POLLER == EPOLL + static const size_t max_events = 12; + struct epoll_event revents[max_events]; + // Unblock all signals, only during the epoll_pwait call + sigset_t empty_signal_set; + sigemptyset(&empty_signal_set); + const int nb_events = ::epoll_pwait(this->epfd, revents, max_events, timeout.count(), + &empty_signal_set); + if (nb_events == -1) + { + if (errno == EINTR) + return 0; + log_error("epoll wait: " << strerror(errno)); + throw std::runtime_error("Epoll_wait failed"); + } + for (int i = 0; i < nb_events; ++i) + { + auto socket_handler = static_cast(revents[i].data.ptr); + if (revents[i].events & EPOLLIN) + socket_handler->on_recv(); + else if (revents[i].events & EPOLLOUT) + { + if (socket_handler->is_connected()) + socket_handler->on_send(); + else + socket_handler->connect(); + } + } + return nb_events; +#endif +} + +size_t Poller::size() const +{ + return this->socket_handlers.size(); +} -- cgit v1.2.3 From 6ee80ad26858eeee9a99b448320025ca439eee55 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 22 Feb 2016 16:56:13 +0100 Subject: Fix the ordering of poll callbacks (recv, connect, send) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Because if we have a send event to signal the connection sucess + a recv event to signal something to read on the socket, we need to first finish the connect process before reading the available data. That’s what we do now. --- louloulibs/network/poller.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'louloulibs/network/poller.cpp') diff --git a/louloulibs/network/poller.cpp b/louloulibs/network/poller.cpp index 329e1c8..50e9806 100644 --- a/louloulibs/network/poller.cpp +++ b/louloulibs/network/poller.cpp @@ -205,15 +205,12 @@ int Poller::poll(const std::chrono::milliseconds& timeout) for (int i = 0; i < nb_events; ++i) { auto socket_handler = static_cast(revents[i].data.ptr); - if (revents[i].events & EPOLLIN) + if (revents[i].events & EPOLLIN && socket_handler->is_connected()) socket_handler->on_recv(); + else if (revents[i].events & EPOLLOUT && socket_handler->is_connected()) + socket_handler->on_send(); else if (revents[i].events & EPOLLOUT) - { - if (socket_handler->is_connected()) - socket_handler->on_send(); - else - socket_handler->connect(); - } + socket_handler->connect(); } return nb_events; #endif -- cgit v1.2.3 From b29d94444d176604f0847985f3ecf57091d4a47b Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 24 Feb 2016 09:28:59 +0100 Subject: Close the epoll fd --- louloulibs/network/poller.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'louloulibs/network/poller.cpp') diff --git a/louloulibs/network/poller.cpp b/louloulibs/network/poller.cpp index 50e9806..0559644 100644 --- a/louloulibs/network/poller.cpp +++ b/louloulibs/network/poller.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -27,6 +28,8 @@ Poller::Poller() Poller::~Poller() { + if (this->epfd > 0) + ::close(this->epfd); } void Poller::add_socket_handler(SocketHandler* socket_handler) -- cgit v1.2.3 From b47179f1256f2a3fe6ce0d8f30eceb0f91b33b2e Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 24 Feb 2016 09:29:28 +0100 Subject: Fix the ordering of poll callbacks, with ppoll too --- louloulibs/network/poller.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'louloulibs/network/poller.cpp') diff --git a/louloulibs/network/poller.cpp b/louloulibs/network/poller.cpp index 0559644..26e5a8f 100644 --- a/louloulibs/network/poller.cpp +++ b/louloulibs/network/poller.cpp @@ -171,21 +171,22 @@ int Poller::poll(const std::chrono::milliseconds& timeout) assert(static_cast(nb_events) <= this->nfds); for (size_t i = 0; i <= this->nfds && nb_events != 0; ++i) { + auto socket_handler = this->socket_handlers.at(this->fds[i].fd); if (this->fds[i].revents == 0) continue; - else if (this->fds[i].revents & POLLIN) + else if (this->fds[i].revents & POLLIN && socket_handler->is_connected()) { - auto socket_handler = this->socket_handlers.at(this->fds[i].fd); socket_handler->on_recv(); nb_events--; } - else if (this->fds[i].revents & POLLOUT) + else if (this->fds[i].revents & POLLOUT && socket_handler->is_connected()) { - auto socket_handler = this->socket_handlers.at(this->fds[i].fd); - if (socket_handler->is_connected()) socket_handler->on_send(); - else - socket_handler->connect(); + nb_events--; + } + else if (this->fds[i].revents & POLLOUT) + { + socket_handler->connect(); nb_events--; } } -- cgit v1.2.3 From ce798b1e8cfce7df69e0e91400c96090447a5ea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 10 May 2016 12:48:39 +0200 Subject: Fix build with POLLER=POLL --- louloulibs/network/poller.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'louloulibs/network/poller.cpp') diff --git a/louloulibs/network/poller.cpp b/louloulibs/network/poller.cpp index 26e5a8f..959567e 100644 --- a/louloulibs/network/poller.cpp +++ b/louloulibs/network/poller.cpp @@ -28,8 +28,10 @@ Poller::Poller() Poller::~Poller() { +#if POLLER == EPOLL if (this->epfd > 0) ::close(this->epfd); +#endif } void Poller::add_socket_handler(SocketHandler* socket_handler) -- cgit v1.2.3 From 5a2e61161792cf51209f240e40e28036195f35be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Mon, 13 Jun 2016 19:59:17 +0200 Subject: Show off, with some variadic templates, for the logger module --- louloulibs/network/poller.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'louloulibs/network/poller.cpp') diff --git a/louloulibs/network/poller.cpp b/louloulibs/network/poller.cpp index 959567e..8a6fd97 100644 --- a/louloulibs/network/poller.cpp +++ b/louloulibs/network/poller.cpp @@ -20,7 +20,7 @@ Poller::Poller() this->epfd = ::epoll_create1(0); if (this->epfd == -1) { - log_error("epoll failed: " << strerror(errno)); + log_error("epoll failed: ", strerror(errno)); throw std::runtime_error("Could not create epoll instance"); } #endif @@ -54,7 +54,7 @@ void Poller::add_socket_handler(SocketHandler* socket_handler) const int res = ::epoll_ctl(this->epfd, EPOLL_CTL_ADD, socket_handler->get_socket(), &event); if (res == -1) { - log_error("epoll_ctl failed: " << strerror(errno)); + log_error("epoll_ctl failed: ", strerror(errno)); throw std::runtime_error("Could not add socket to epoll"); } #endif @@ -86,7 +86,7 @@ void Poller::remove_socket_handler(const socket_t socket) const int res = ::epoll_ctl(this->epfd, EPOLL_CTL_DEL, socket, nullptr); if (res == -1) { - log_error("epoll_ctl failed: " << strerror(errno)); + log_error("epoll_ctl failed: ", strerror(errno)); throw std::runtime_error("Could not remove socket from epoll"); } #endif @@ -109,7 +109,7 @@ void Poller::watch_send_events(SocketHandler* socket_handler) const int res = ::epoll_ctl(this->epfd, EPOLL_CTL_MOD, socket_handler->get_socket(), &event); if (res == -1) { - log_error("epoll_ctl failed: " << strerror(errno)); + log_error("epoll_ctl failed: ", strerror(errno)); throw std::runtime_error("Could not modify socket flags in epoll"); } #endif @@ -132,7 +132,7 @@ void Poller::stop_watching_send_events(SocketHandler* socket_handler) const int res = ::epoll_ctl(this->epfd, EPOLL_CTL_MOD, socket_handler->get_socket(), &event); if (res == -1) { - log_error("epoll_ctl failed: " << strerror(errno)); + log_error("epoll_ctl failed: ", strerror(errno)); throw std::runtime_error("Could not modify socket flags in epoll"); } #endif @@ -165,7 +165,7 @@ int Poller::poll(const std::chrono::milliseconds& timeout) { if (errno == EINTR) return true; - log_error("poll failed: " << strerror(errno)); + log_error("poll failed: ", strerror(errno)); throw std::runtime_error("Poll failed"); } // We cannot possibly have more ready events than the number of fds we are @@ -205,7 +205,7 @@ int Poller::poll(const std::chrono::milliseconds& timeout) { if (errno == EINTR) return 0; - log_error("epoll wait: " << strerror(errno)); + log_error("epoll wait: ", strerror(errno)); throw std::runtime_error("Epoll_wait failed"); } for (int i = 0; i < nb_events; ++i) -- cgit v1.2.3