Commit a50ca30e authored by louiz’'s avatar louiz’

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”.
parent 3032dc35
...@@ -7,6 +7,8 @@ Version 2.0 ...@@ -7,6 +7,8 @@ Version 2.0
- Setting a participant's role/affiliation now results in a change of IRC - 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 mode, instead of being ignored. Setting Toto's affiliation to admin is
now equivalent to “/mode +o Toto” 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 Version 1.1 2014-16-07
......
...@@ -108,6 +108,8 @@ int main(int ac, char** av) ...@@ -108,6 +108,8 @@ int main(int ac, char** av)
exiting = true; exiting = true;
stop.store(false); stop.store(false);
xmpp_component->shutdown(); xmpp_component->shutdown();
// Cancel the timer for an potential reconnection
TimedEventsManager::instance().cancel("XMPP reconnection");
} }
if (reload) if (reload)
{ {
...@@ -127,17 +129,34 @@ int main(int ac, char** av) ...@@ -127,17 +129,34 @@ int main(int ac, char** av)
if (!exiting && xmpp_component->ever_auth && if (!exiting && xmpp_component->ever_auth &&
!xmpp_component->is_connected() && !xmpp_component->is_connected() &&
!xmpp_component->is_connecting()) !xmpp_component->is_connecting())
{ {
if (xmpp_component->first_connection_try == true)
{ // immediately re-try to connect
xmpp_component->reset(); xmpp_component->reset();
xmpp_component->start(); 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: // If the only existing connection is the one to the XMPP component:
// close the XMPP stream. // close the XMPP stream.
if (exiting && xmpp_component->is_connecting()) if (exiting && xmpp_component->is_connecting())
xmpp_component->close(); xmpp_component->close();
if (exiting && p->size() == 1 && xmpp_component->is_document_open()) if (exiting && p->size() == 1 && xmpp_component->is_document_open())
xmpp_component->close_document(); 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."); log_info("All connections cleanly closed, have a nice day.");
return 0; return 0;
......
#include <network/poller.hpp> #include <network/poller.hpp>
#include <logger/logger.hpp> #include <logger/logger.hpp>
#include <utils/timed_events.hpp>
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
...@@ -133,7 +134,7 @@ void Poller::stop_watching_send_events(SocketHandler* socket_handler) ...@@ -133,7 +134,7 @@ void Poller::stop_watching_send_events(SocketHandler* socket_handler)
int Poller::poll(const std::chrono::milliseconds& timeout) int Poller::poll(const std::chrono::milliseconds& timeout)
{ {
if (this->socket_handlers.empty()) if (this->socket_handlers.empty() && timeout == utils::no_timeout)
return -1; return -1;
#if POLLER == POLL #if POLLER == POLL
int nb_events = ::poll(this->fds, this->nfds, timeout.count()); int nb_events = ::poll(this->fds, this->nfds, timeout.count());
......
...@@ -213,8 +213,11 @@ ssize_t TCPSocketHandler::do_recv(void* recv_buf, const size_t buf_size) ...@@ -213,8 +213,11 @@ ssize_t TCPSocketHandler::do_recv(void* recv_buf, const size_t buf_size)
else if (-1 == size) else if (-1 == size)
{ {
log_warning("Error while reading from socket: " << strerror(errno)); 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(); this->close();
if (this->connecting) if (were_connecting)
this->on_connection_failed(strerror(errno)); this->on_connection_failed(strerror(errno));
else else
this->on_connection_close(strerror(errno)); this->on_connection_close(strerror(errno));
......
...@@ -39,6 +39,7 @@ static std::set<std::string> kickable_errors{ ...@@ -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): XmppComponent::XmppComponent(std::shared_ptr<Poller> poller, const std::string& hostname, const std::string& secret):
TCPSocketHandler(poller), TCPSocketHandler(poller),
ever_auth(false), ever_auth(false),
first_connection_try(true),
served_hostname(hostname), served_hostname(hostname),
secret(secret), secret(secret),
authenticated(false), authenticated(false),
...@@ -86,6 +87,7 @@ void XmppComponent::send_stanza(const Stanza& stanza) ...@@ -86,6 +87,7 @@ void XmppComponent::send_stanza(const Stanza& stanza)
void XmppComponent::on_connection_failed(const std::string& reason) void XmppComponent::on_connection_failed(const std::string& reason)
{ {
this->first_connection_try = false;
log_error("Failed to connect to the XMPP server: " << reason); log_error("Failed to connect to the XMPP server: " << reason);
#ifdef SYSTEMDDAEMON_FOUND #ifdef SYSTEMDDAEMON_FOUND
sd_notifyf(0, "STATUS=Failed to connect to the XMPP server: %s", reason.data()); 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) ...@@ -95,6 +97,7 @@ void XmppComponent::on_connection_failed(const std::string& reason)
void XmppComponent::on_connected() void XmppComponent::on_connected()
{ {
log_info("connected to XMPP server"); log_info("connected to XMPP server");
this->first_connection_try = true;
XmlNode node("", nullptr); XmlNode node("", nullptr);
node.set_name("stream:stream"); node.set_name("stream:stream");
node["xmlns"] = COMPONENT_NS; node["xmlns"] = COMPONENT_NS;
......
...@@ -241,6 +241,12 @@ public: ...@@ -241,6 +241,12 @@ public:
* Whether or not we ever succeeded our authentication to the XMPP server * Whether or not we ever succeeded our authentication to the XMPP server
*/ */
bool ever_auth; 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: private:
/** /**
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment