summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorent Le Coz <louiz@louiz.org>2015-02-21 06:39:20 +0100
committerFlorent Le Coz <louiz@louiz.org>2015-02-21 06:45:11 +0100
commita50ca30e769a628f609f8cc0eedf5bc10b3f1b5a (patch)
tree9119399eefe68d086e80eeaa3fc35e673257cdc7
parent3032dc3580e2d6c3fab57b587945fbb213271557 (diff)
downloadbiboumi-a50ca30e769a628f609f8cc0eedf5bc10b3f1b5a.tar.gz
biboumi-a50ca30e769a628f609f8cc0eedf5bc10b3f1b5a.tar.bz2
biboumi-a50ca30e769a628f609f8cc0eedf5bc10b3f1b5a.tar.xz
biboumi-a50ca30e769a628f609f8cc0eedf5bc10b3f1b5a.zip
Use a timer to try reconnecting to the XMPP server only each 2 seconds
When the connection is lost, immediately try to reconnect, then try to reconnect every 2 seconds. This is much better than the previous “Try to re-connect as fast as possible”.
-rw-r--r--CHANGELOG2
-rw-r--r--src/main.cpp23
-rw-r--r--src/network/poller.cpp3
-rw-r--r--src/network/tcp_socket_handler.cpp5
-rw-r--r--src/xmpp/xmpp_component.cpp3
-rw-r--r--src/xmpp/xmpp_component.hpp6
6 files changed, 38 insertions, 4 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 9e907b0..872eb4d 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -7,6 +7,8 @@ Version 2.0
- Setting a participant's role/affiliation now results in a change of IRC
mode, instead of being ignored. Setting Toto's affiliation to admin is
now equivalent to “/mode +o Toto”
+ - Fix the reconnection to the XMPP server to try every 2 seconds
+ instead of immediately. This avoid hogging resources for nothing
Version 1.1 2014-16-07
diff --git a/src/main.cpp b/src/main.cpp
index 393bf05..a67baf9 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -108,6 +108,8 @@ int main(int ac, char** av)
exiting = true;
stop.store(false);
xmpp_component->shutdown();
+ // Cancel the timer for an potential reconnection
+ TimedEventsManager::instance().cancel("XMPP reconnection");
}
if (reload)
{
@@ -127,17 +129,34 @@ int main(int ac, char** av)
if (!exiting && xmpp_component->ever_auth &&
!xmpp_component->is_connected() &&
!xmpp_component->is_connecting())
- {
+ {
+ if (xmpp_component->first_connection_try == true)
+ { // immediately re-try to connect
xmpp_component->reset();
xmpp_component->start();
}
+ else
+ { // Re-connecting failed, we now try only each few seconds
+ auto reconnect_later = [xmpp_component]()
+ {
+ xmpp_component->reset();
+ xmpp_component->start();
+ };
+ TimedEvent event(std::chrono::steady_clock::now() + 2s,
+ reconnect_later, "XMPP reconnection");
+ TimedEventsManager::instance().add_event(std::move(event));
+ }
+ }
// If the only existing connection is the one to the XMPP component:
// close the XMPP stream.
if (exiting && xmpp_component->is_connecting())
xmpp_component->close();
if (exiting && p->size() == 1 && xmpp_component->is_document_open())
xmpp_component->close_document();
- timeout = TimedEventsManager::instance().get_timeout();
+ if (exiting) // If we are exiting, do not wait for any timed event
+ timeout = utils::no_timeout;
+ else
+ timeout = TimedEventsManager::instance().get_timeout();
}
log_info("All connections cleanly closed, have a nice day.");
return 0;
diff --git a/src/network/poller.cpp b/src/network/poller.cpp
index 29c4bce..ffc4f2d 100644
--- a/src/network/poller.cpp
+++ b/src/network/poller.cpp
@@ -1,5 +1,6 @@
#include <network/poller.hpp>
#include <logger/logger.hpp>
+#include <utils/timed_events.hpp>
#include <assert.h>
#include <errno.h>
@@ -133,7 +134,7 @@ void Poller::stop_watching_send_events(SocketHandler* socket_handler)
int Poller::poll(const std::chrono::milliseconds& timeout)
{
- if (this->socket_handlers.empty())
+ if (this->socket_handlers.empty() && timeout == utils::no_timeout)
return -1;
#if POLLER == POLL
int nb_events = ::poll(this->fds, this->nfds, timeout.count());
diff --git a/src/network/tcp_socket_handler.cpp b/src/network/tcp_socket_handler.cpp
index c5d254e..1d1eaa7 100644
--- a/src/network/tcp_socket_handler.cpp
+++ b/src/network/tcp_socket_handler.cpp
@@ -213,8 +213,11 @@ ssize_t TCPSocketHandler::do_recv(void* recv_buf, const size_t buf_size)
else if (-1 == size)
{
log_warning("Error while reading from socket: " << strerror(errno));
+ // Remember if we were connecting, or already connected when this
+ // happened, because close() sets this->connecting to false
+ const auto were_connecting = this->connecting;
this->close();
- if (this->connecting)
+ if (were_connecting)
this->on_connection_failed(strerror(errno));
else
this->on_connection_close(strerror(errno));
diff --git a/src/xmpp/xmpp_component.cpp b/src/xmpp/xmpp_component.cpp
index 1335326..841ead4 100644
--- a/src/xmpp/xmpp_component.cpp
+++ b/src/xmpp/xmpp_component.cpp
@@ -39,6 +39,7 @@ static std::set<std::string> kickable_errors{
XmppComponent::XmppComponent(std::shared_ptr<Poller> poller, const std::string& hostname, const std::string& secret):
TCPSocketHandler(poller),
ever_auth(false),
+ first_connection_try(true),
served_hostname(hostname),
secret(secret),
authenticated(false),
@@ -86,6 +87,7 @@ void XmppComponent::send_stanza(const Stanza& stanza)
void XmppComponent::on_connection_failed(const std::string& reason)
{
+ this->first_connection_try = false;
log_error("Failed to connect to the XMPP server: " << reason);
#ifdef SYSTEMDDAEMON_FOUND
sd_notifyf(0, "STATUS=Failed to connect to the XMPP server: %s", reason.data());
@@ -95,6 +97,7 @@ void XmppComponent::on_connection_failed(const std::string& reason)
void XmppComponent::on_connected()
{
log_info("connected to XMPP server");
+ this->first_connection_try = true;
XmlNode node("", nullptr);
node.set_name("stream:stream");
node["xmlns"] = COMPONENT_NS;
diff --git a/src/xmpp/xmpp_component.hpp b/src/xmpp/xmpp_component.hpp
index 64b2ff7..951d5a3 100644
--- a/src/xmpp/xmpp_component.hpp
+++ b/src/xmpp/xmpp_component.hpp
@@ -241,6 +241,12 @@ public:
* Whether or not we ever succeeded our authentication to the XMPP server
*/
bool ever_auth;
+ /**
+ * Whether or not this is the first consecutive try on connecting to the
+ * XMPP server. We use this to delay the connection attempt for a few
+ * seconds, if it is not the first try.
+ */
+ bool first_connection_try;
private:
/**