summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorent Le Coz <louiz@louiz.org>2014-05-27 01:01:44 +0200
committerFlorent Le Coz <louiz@louiz.org>2014-05-27 01:01:44 +0200
commit5507adbe9473f4b41e52d16498f14850773e5e45 (patch)
tree34f2960edf6b73828537460cc50e6cdb9252a5e3
parent6b0ffb5fc2eca537e2cfaf24acb8a4d2ca9b99f1 (diff)
downloadbiboumi-5507adbe9473f4b41e52d16498f14850773e5e45.tar.gz
biboumi-5507adbe9473f4b41e52d16498f14850773e5e45.tar.bz2
biboumi-5507adbe9473f4b41e52d16498f14850773e5e45.tar.xz
biboumi-5507adbe9473f4b41e52d16498f14850773e5e45.zip
SocketHandlers own the poller and add themself into it only when the socket is created
We want to call socket() with the parameters provided by getaddrinfo, so we can’t addd the fd into the poller immediately. We need to wait the connection attempt, and then the SocketHandler can call add_socket_handler itself, if the connection succeeds, or is in progress.
-rw-r--r--src/bridge/bridge.cpp5
-rw-r--r--src/bridge/bridge.hpp5
-rw-r--r--src/irc/irc_client.cpp3
-rw-r--r--src/irc/irc_client.hpp3
-rw-r--r--src/main.cpp13
-rw-r--r--src/network/poller.cpp9
-rw-r--r--src/network/poller.hpp4
-rw-r--r--src/network/socket_handler.cpp12
-rw-r--r--src/network/socket_handler.hpp9
-rw-r--r--src/xmpp/xmpp_component.cpp3
-rw-r--r--src/xmpp/xmpp_component.hpp2
11 files changed, 29 insertions, 39 deletions
diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp
index d803e5e..78cd2d2 100644
--- a/src/bridge/bridge.cpp
+++ b/src/bridge/bridge.cpp
@@ -14,7 +14,7 @@ using namespace std::string_literals;
static const char* action_prefix = "\01ACTION ";
-Bridge::Bridge(const std::string& user_jid, XmppComponent* xmpp, Poller* poller):
+Bridge::Bridge(const std::string& user_jid, XmppComponent* xmpp, std::shared_ptr<Poller> poller):
user_jid(user_jid),
xmpp(xmpp),
poller(poller)
@@ -81,9 +81,8 @@ IrcClient* Bridge::get_irc_client(const std::string& hostname, const std::string
}
catch (const std::out_of_range& exception)
{
- this->irc_clients.emplace(hostname, std::make_shared<IrcClient>(hostname, username, this));
+ this->irc_clients.emplace(hostname, std::make_shared<IrcClient>(this->poller, hostname, username, this));
std::shared_ptr<IrcClient> irc = this->irc_clients.at(hostname);
- this->poller->add_socket_handler(irc);
return irc.get();
}
}
diff --git a/src/bridge/bridge.hpp b/src/bridge/bridge.hpp
index f78bade..37f5b05 100644
--- a/src/bridge/bridge.hpp
+++ b/src/bridge/bridge.hpp
@@ -22,7 +22,7 @@ class Poller;
class Bridge
{
public:
- explicit Bridge(const std::string& user_jid, XmppComponent* xmpp, Poller* poller);
+ explicit Bridge(const std::string& user_jid, XmppComponent* xmpp, std::shared_ptr<Poller> poller);
~Bridge();
/**
* QUIT all connected IRC servers.
@@ -146,9 +146,8 @@ private:
/**
* Poller, to give it the IrcClients that we spawn, to make it manage
* their sockets.
- * We don't own it.
*/
- Poller* poller;
+ std::shared_ptr<Poller> poller;
Bridge(const Bridge&) = delete;
Bridge(Bridge&& other) = delete;
diff --git a/src/irc/irc_client.cpp b/src/irc/irc_client.cpp
index c149311..cea08f2 100644
--- a/src/irc/irc_client.cpp
+++ b/src/irc/irc_client.cpp
@@ -13,7 +13,8 @@
#include <string>
using namespace std::string_literals;
-IrcClient::IrcClient(const std::string& hostname, const std::string& username, Bridge* bridge):
+IrcClient::IrcClient(std::shared_ptr<Poller> poller, const std::string& hostname, const std::string& username, Bridge* bridge):
+ SocketHandler(poller),
hostname(hostname),
username(username),
current_nick(username),
diff --git a/src/irc/irc_client.hpp b/src/irc/irc_client.hpp
index a2e2afe..e70ee33 100644
--- a/src/irc/irc_client.hpp
+++ b/src/irc/irc_client.hpp
@@ -8,6 +8,7 @@
#include <network/socket_handler.hpp>
#include <unordered_map>
+#include <memory>
#include <vector>
#include <string>
#include <map>
@@ -23,7 +24,7 @@ class Bridge;
class IrcClient: public SocketHandler
{
public:
- explicit IrcClient(const std::string& hostname, const std::string& username, Bridge* bridge);
+ explicit IrcClient(std::shared_ptr<Poller> poller, const std::string& hostname, const std::string& username, Bridge* bridge);
~IrcClient();
/**
* Connect to the IRC server
diff --git a/src/main.cpp b/src/main.cpp
index 6cba134..40825c9 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -61,11 +61,11 @@ int main(int ac, char** av)
return config_help("password");
if (hostname.empty())
return config_help("hostname");
- std::shared_ptr<XmppComponent> xmpp_component =
- std::make_shared<XmppComponent>(hostname, password);
- Poller p;
- p.add_socket_handler(xmpp_component);
+ auto p = std::make_shared<Poller>();
+ auto xmpp_component = std::make_shared<XmppComponent>(p,
+ hostname,
+ password);
// Install the signals used to exit the process cleanly, or reload the
// config
@@ -91,7 +91,7 @@ int main(int ac, char** av)
xmpp_component->start();
const std::chrono::milliseconds timeout(-1);
- while (p.poll(timeout) != -1)
+ while (p->poll(timeout) != -1)
{
// Check for empty irc_clients (not connected, or with no joined
// channel) and remove them
@@ -123,14 +123,13 @@ int main(int ac, char** av)
!xmpp_component->is_connecting())
{
xmpp_component->reset();
- p.add_socket_handler(xmpp_component);
xmpp_component->start();
}
// 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())
+ if (exiting && p->size() == 1 && xmpp_component->is_document_open())
xmpp_component->close_document();
}
log_info("All connection cleanely closed, have a nice day.");
diff --git a/src/network/poller.cpp b/src/network/poller.cpp
index 708fe23..d89e50f 100644
--- a/src/network/poller.cpp
+++ b/src/network/poller.cpp
@@ -27,15 +27,14 @@ Poller::~Poller()
{
}
-void Poller::add_socket_handler(std::shared_ptr<SocketHandler> socket_handler)
+void Poller::add_socket_handler(SocketHandler* socket_handler)
{
- // Raise an error if that socket is already in the list
+ // 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())
- throw std::runtime_error("Trying to insert SocketHandler already managed");
+ return ;
this->socket_handlers.emplace(socket_handler->get_socket(), socket_handler);
- socket_handler->set_poller(this);
// We always watch all sockets for receive events
#if POLLER == POLL
@@ -44,7 +43,7 @@ void Poller::add_socket_handler(std::shared_ptr<SocketHandler> socket_handler)
this->nfds++;
#endif
#if POLLER == EPOLL
- struct epoll_event event = {EPOLLIN, {socket_handler.get()}};
+ 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)
{
diff --git a/src/network/poller.hpp b/src/network/poller.hpp
index dc087a2..c3edcd7 100644
--- a/src/network/poller.hpp
+++ b/src/network/poller.hpp
@@ -42,7 +42,7 @@ public:
* Add a SocketHandler to be monitored by this Poller. All receive events
* are always automatically watched.
*/
- void add_socket_handler(std::shared_ptr<SocketHandler> socket_handler);
+ void add_socket_handler(SocketHandler* socket_handler);
/**
* Remove (and stop managing) a SocketHandler, designed by the given socket_t.
*/
@@ -77,7 +77,7 @@ private:
* because that's what is returned by select/poll/etc when an event
* occures.
*/
- std::unordered_map<socket_t, std::shared_ptr<SocketHandler>> socket_handlers;
+ std::unordered_map<socket_t, SocketHandler*> socket_handlers;
#if POLLER == POLL
struct pollfd fds[MAX_POLL_FD_NUMBER];
diff --git a/src/network/socket_handler.cpp b/src/network/socket_handler.cpp
index 2348faa..a9e0c5e 100644
--- a/src/network/socket_handler.cpp
+++ b/src/network/socket_handler.cpp
@@ -23,8 +23,8 @@ using namespace std::string_literals;
# define UIO_FASTIOV 8
#endif
-SocketHandler::SocketHandler():
- poller(nullptr),
+SocketHandler::SocketHandler(std::shared_ptr<Poller> poller):
+ poller(poller),
connected(false),
connecting(false)
{
@@ -107,6 +107,7 @@ void SocketHandler::connect(const std::string& address, const std::string& port)
|| errno == EISCONN)
{
log_info("Connection success.");
+ this->poller->add_socket_handler(this);
this->connected = true;
this->connecting = false;
this->on_connected();
@@ -134,11 +135,6 @@ void SocketHandler::connect()
this->connect(this->address, this->port);
}
-void SocketHandler::set_poller(Poller* poller)
-{
- this->poller = poller;
-}
-
void SocketHandler::on_recv()
{
static constexpr size_t buf_size = 4096;
@@ -231,8 +227,6 @@ void SocketHandler::close()
this->port.clear();
this->poller->remove_socket_handler(this->get_socket());
::close(this->socket);
- // recreate the socket for a potential future usage
- this->init_socket();
}
socket_t SocketHandler::get_socket() const
diff --git a/src/network/socket_handler.hpp b/src/network/socket_handler.hpp
index f554350..1e31dcd 100644
--- a/src/network/socket_handler.hpp
+++ b/src/network/socket_handler.hpp
@@ -6,6 +6,7 @@
#include <netdb.h>
#include <utility>
+#include <memory>
#include <string>
#include <list>
@@ -22,7 +23,7 @@ class Poller;
class SocketHandler
{
public:
- explicit SocketHandler();
+ explicit SocketHandler(std::shared_ptr<Poller> poller);
virtual ~SocketHandler() {}
/**
* (re-)Initialize the socket
@@ -34,10 +35,6 @@ public:
void connect(const std::string& address, const std::string& port);
void connect();
/**
- * Set the pointer to the given Poller, to communicate with it.
- */
- void set_poller(Poller* poller);
- /**
* Reads data in our in_buf and the call parse_in_buf, for the implementor
* to handle the data received so far.
*/
@@ -119,7 +116,7 @@ protected:
* And a raw pointer because we are not owning it, it is owning us
* (actually it is sharing our ownership with a Bridge).
*/
- Poller* poller;
+ std::shared_ptr<Poller> poller;
/**
* Hostname we are connected/connecting to
*/
diff --git a/src/xmpp/xmpp_component.cpp b/src/xmpp/xmpp_component.cpp
index 32f5d96..55f0ca4 100644
--- a/src/xmpp/xmpp_component.cpp
+++ b/src/xmpp/xmpp_component.cpp
@@ -47,7 +47,8 @@ static std::set<std::string> kickable_errors{
"malformed-error"
};
-XmppComponent::XmppComponent(const std::string& hostname, const std::string& secret):
+XmppComponent::XmppComponent(std::shared_ptr<Poller> poller, const std::string& hostname, const std::string& secret):
+ SocketHandler(poller),
ever_auth(false),
last_auth(false),
served_hostname(hostname),
diff --git a/src/xmpp/xmpp_component.hpp b/src/xmpp/xmpp_component.hpp
index fdf068b..f081420 100644
--- a/src/xmpp/xmpp_component.hpp
+++ b/src/xmpp/xmpp_component.hpp
@@ -18,7 +18,7 @@
class XmppComponent: public SocketHandler
{
public:
- explicit XmppComponent(const std::string& hostname, const std::string& secret);
+ explicit XmppComponent(std::shared_ptr<Poller> poller, const std::string& hostname, const std::string& secret);
~XmppComponent();
void on_connection_failed(const std::string& reason) override final;