~singpolyma/biboumi

a50ca30e769a628f609f8cc0eedf5bc10b3f1b5a — Florent Le Coz 9 years ago 3032dc3
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”.
M CHANGELOG => CHANGELOG +2 -0
@@ 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


M src/main.cpp => src/main.cpp +21 -2
@@ 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;

M src/network/poller.cpp => src/network/poller.cpp +2 -1
@@ 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());

M src/network/tcp_socket_handler.cpp => src/network/tcp_socket_handler.cpp +4 -1
@@ 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));

M src/xmpp/xmpp_component.cpp => src/xmpp/xmpp_component.cpp +3 -0
@@ 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;

M src/xmpp/xmpp_component.hpp => src/xmpp/xmpp_component.hpp +6 -0
@@ 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:
  /**