Merge branch 'epolletc'
This commit is contained in:
+7
-1
@@ -24,6 +24,12 @@ include_directories(${ICONV_INCLUDE_DIR})
|
|||||||
# coming from these headers.
|
# coming from these headers.
|
||||||
include_directories(SYSTEM ${CRYPTO++_INCLUDE_DIR})
|
include_directories(SYSTEM ${CRYPTO++_INCLUDE_DIR})
|
||||||
|
|
||||||
|
set(POLLER "POLL" CACHE STRING
|
||||||
|
"Choose the poller between POLL and EPOLL (Linux-only)")
|
||||||
|
if((NOT ${POLLER} MATCHES "POLL") AND
|
||||||
|
(NOT ${POLLER} MATCHES "EPOLL"))
|
||||||
|
message(FATAL_ERROR "POLLER must be either POLL or EPOLL")
|
||||||
|
endif()
|
||||||
#
|
#
|
||||||
## utils
|
## utils
|
||||||
#
|
#
|
||||||
@@ -95,4 +101,4 @@ target_link_libraries(test
|
|||||||
utils
|
utils
|
||||||
config)
|
config)
|
||||||
|
|
||||||
CONFIGURE_FILE(config.h.cmake src/config.h @ONLY)
|
configure_file(config.h.cmake src/config.h)
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
#cmakedefine ICONV_SECOND_ARGUMENT_IS_CONST
|
#cmakedefine ICONV_SECOND_ARGUMENT_IS_CONST
|
||||||
|
#cmakedefine POLLER ${POLLER}
|
||||||
|
|||||||
@@ -222,6 +222,27 @@ void IrcClient::on_channel_message(const IrcMessage& message)
|
|||||||
this->bridge->send_message(iid, nick, body, muc);
|
this->bridge->send_message(iid, nick, body, muc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IrcClient::empty_motd(const IrcMessage& message)
|
||||||
|
{
|
||||||
|
(void)message;
|
||||||
|
this->motd.erase();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IrcClient::on_motd_line(const IrcMessage& message)
|
||||||
|
{
|
||||||
|
const std::string body = message.arguments[1];
|
||||||
|
// We could send the MOTD without a line break between each IRC-message,
|
||||||
|
// but sometimes it contains some ASCII art, we use line breaks to keep
|
||||||
|
// them intact.
|
||||||
|
this->motd += body+"\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void IrcClient::send_motd(const IrcMessage& message)
|
||||||
|
{
|
||||||
|
(void)message;
|
||||||
|
this->bridge->send_xmpp_message(this->hostname, "", this->motd);
|
||||||
|
}
|
||||||
|
|
||||||
void IrcClient::on_topic_received(const IrcMessage& message)
|
void IrcClient::on_topic_received(const IrcMessage& message)
|
||||||
{
|
{
|
||||||
const std::string chan_name = message.arguments[1];
|
const std::string chan_name = message.arguments[1];
|
||||||
|
|||||||
+23
-2
@@ -99,6 +99,18 @@ public:
|
|||||||
* Forward the server message received from IRC to the XMPP component
|
* Forward the server message received from IRC to the XMPP component
|
||||||
*/
|
*/
|
||||||
void forward_server_message(const IrcMessage& message);
|
void forward_server_message(const IrcMessage& message);
|
||||||
|
/**
|
||||||
|
* Just empty the motd we kept as a string
|
||||||
|
*/
|
||||||
|
void empty_motd(const IrcMessage& message);
|
||||||
|
/**
|
||||||
|
* Send the MOTD string as one single "big" message
|
||||||
|
*/
|
||||||
|
void send_motd(const IrcMessage& message);
|
||||||
|
/**
|
||||||
|
* Append this line to the MOTD
|
||||||
|
*/
|
||||||
|
void on_motd_line(const IrcMessage& message);
|
||||||
/**
|
/**
|
||||||
* Forward the join of an other user into an IRC channel, and save the
|
* Forward the join of an other user into an IRC channel, and save the
|
||||||
* IrcUsers in the IrcChannel
|
* IrcUsers in the IrcChannel
|
||||||
@@ -172,6 +184,11 @@ private:
|
|||||||
*/
|
*/
|
||||||
std::vector<std::string> channels_to_join;
|
std::vector<std::string> channels_to_join;
|
||||||
bool welcomed;
|
bool welcomed;
|
||||||
|
/**
|
||||||
|
* Each motd line received is appended to this string, which we send when
|
||||||
|
* the motd is completely received
|
||||||
|
*/
|
||||||
|
std::string motd;
|
||||||
IrcClient(const IrcClient&) = delete;
|
IrcClient(const IrcClient&) = delete;
|
||||||
IrcClient(IrcClient&&) = delete;
|
IrcClient(IrcClient&&) = delete;
|
||||||
IrcClient& operator=(const IrcClient&) = delete;
|
IrcClient& operator=(const IrcClient&) = delete;
|
||||||
@@ -186,8 +203,12 @@ typedef void (IrcClient::*irc_callback_t)(const IrcMessage&);
|
|||||||
|
|
||||||
static const std::unordered_map<std::string, irc_callback_t> irc_callbacks = {
|
static const std::unordered_map<std::string, irc_callback_t> irc_callbacks = {
|
||||||
{"NOTICE", &IrcClient::forward_server_message},
|
{"NOTICE", &IrcClient::forward_server_message},
|
||||||
{"375", &IrcClient::forward_server_message},
|
{"RPL_MOTDSTART", &IrcClient::empty_motd},
|
||||||
{"372", &IrcClient::forward_server_message},
|
{"375", &IrcClient::empty_motd},
|
||||||
|
{"RPL_MOTD", &IrcClient::on_motd_line},
|
||||||
|
{"372", &IrcClient::on_motd_line},
|
||||||
|
{"RPL_MOTDEND", &IrcClient::send_motd},
|
||||||
|
{"376", &IrcClient::send_motd},
|
||||||
{"JOIN", &IrcClient::on_channel_join},
|
{"JOIN", &IrcClient::on_channel_join},
|
||||||
{"PRIVMSG", &IrcClient::on_channel_message},
|
{"PRIVMSG", &IrcClient::on_channel_message},
|
||||||
{"353", &IrcClient::set_and_forward_user_list},
|
{"353", &IrcClient::set_and_forward_user_list},
|
||||||
|
|||||||
+69
-4
@@ -12,6 +12,13 @@ Poller::Poller()
|
|||||||
#if POLLER == POLL
|
#if POLLER == POLL
|
||||||
memset(this->fds, 0, sizeof(this->fds));
|
memset(this->fds, 0, sizeof(this->fds));
|
||||||
this->nfds = 0;
|
this->nfds = 0;
|
||||||
|
#elif POLLER == EPOLL
|
||||||
|
this->epfd = ::epoll_create1(0);
|
||||||
|
if (this->epfd == -1)
|
||||||
|
{
|
||||||
|
perror("epoll");
|
||||||
|
throw std::runtime_error("Could not create epoll instance");
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,6 +43,17 @@ void Poller::add_socket_handler(std::shared_ptr<SocketHandler> socket_handler)
|
|||||||
this->fds[this->nfds].events = POLLIN;
|
this->fds[this->nfds].events = POLLIN;
|
||||||
this->nfds++;
|
this->nfds++;
|
||||||
#endif
|
#endif
|
||||||
|
#if POLLER == EPOLL
|
||||||
|
struct epoll_event event;
|
||||||
|
event.data.ptr = socket_handler.get();
|
||||||
|
event.events = EPOLLIN;
|
||||||
|
const int res = ::epoll_ctl(this->epfd, EPOLL_CTL_ADD, socket_handler->get_socket(), &event);
|
||||||
|
if (res == -1)
|
||||||
|
{
|
||||||
|
perror("epoll_ctl");
|
||||||
|
throw std::runtime_error("Could not add socket to epoll");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Poller::remove_socket_handler(const socket_t socket)
|
void Poller::remove_socket_handler(const socket_t socket)
|
||||||
@@ -44,6 +62,8 @@ void Poller::remove_socket_handler(const socket_t socket)
|
|||||||
if (it == this->socket_handlers.end())
|
if (it == this->socket_handlers.end())
|
||||||
throw std::runtime_error("Trying to remove a SocketHandler that is not managed");
|
throw std::runtime_error("Trying to remove a SocketHandler that is not managed");
|
||||||
this->socket_handlers.erase(it);
|
this->socket_handlers.erase(it);
|
||||||
|
|
||||||
|
#if POLLER == POLL
|
||||||
for (size_t i = 0; i < this->nfds; i++)
|
for (size_t i = 0; i < this->nfds; i++)
|
||||||
{
|
{
|
||||||
if (this->fds[i].fd == socket)
|
if (this->fds[i].fd == socket)
|
||||||
@@ -58,9 +78,17 @@ void Poller::remove_socket_handler(const socket_t socket)
|
|||||||
this->nfds--;
|
this->nfds--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#elif POLLER == EPOLL
|
||||||
|
const int res = ::epoll_ctl(this->epfd, EPOLL_CTL_DEL, socket, nullptr);
|
||||||
|
if (res == -1)
|
||||||
|
{
|
||||||
|
perror("epoll_ctl");
|
||||||
|
throw std::runtime_error("Could not remove socket from epoll");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Poller::watch_send_events(const SocketHandler* const socket_handler)
|
void Poller::watch_send_events(SocketHandler* socket_handler)
|
||||||
{
|
{
|
||||||
#if POLLER == POLL
|
#if POLLER == POLL
|
||||||
for (size_t i = 0; i <= this->nfds; ++i)
|
for (size_t i = 0; i <= this->nfds; ++i)
|
||||||
@@ -71,11 +99,21 @@ void Poller::watch_send_events(const SocketHandler* const socket_handler)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
throw std::runtime_error("Cannot watch a non-registered socket for send events");
|
throw std::runtime_error("Cannot watch a non-registered socket for send events");
|
||||||
|
#elif POLLER == EPOLL
|
||||||
|
struct epoll_event event;
|
||||||
|
event.data.ptr = socket_handler;
|
||||||
|
event.events = EPOLLIN|EPOLLOUT;
|
||||||
|
const int res = ::epoll_ctl(this->epfd, EPOLL_CTL_MOD, socket_handler->get_socket(), &event);
|
||||||
|
if (res == -1)
|
||||||
|
{
|
||||||
|
perror("epoll_ctl");
|
||||||
|
throw std::runtime_error("Could not modify socket flags in epoll");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Poller::stop_watching_send_events(const SocketHandler* const socket_handler)
|
void Poller::stop_watching_send_events(SocketHandler* socket_handler)
|
||||||
{
|
{
|
||||||
#if POLLER == POLL
|
#if POLLER == POLL
|
||||||
for (size_t i = 0; i <= this->nfds; ++i)
|
for (size_t i = 0; i <= this->nfds; ++i)
|
||||||
@@ -86,8 +124,18 @@ void Poller::stop_watching_send_events(const SocketHandler* const socket_handler
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
throw std::runtime_error("Cannot watch a non-registered socket for send events");
|
throw std::runtime_error("Cannot watch a non-registered socket for send events");
|
||||||
|
#elif POLLER == EPOLL
|
||||||
|
struct epoll_event event;
|
||||||
|
event.data.ptr = socket_handler;
|
||||||
|
event.events = EPOLLIN;
|
||||||
|
const int res = ::epoll_ctl(this->epfd, EPOLL_CTL_MOD, socket_handler->get_socket(), &event);
|
||||||
|
if (res == -1)
|
||||||
|
{
|
||||||
|
perror("epoll_ctl");
|
||||||
|
throw std::runtime_error("Could not modify socket flags in epoll");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Poller::poll()
|
bool Poller::poll()
|
||||||
@@ -121,6 +169,23 @@ bool Poller::poll()
|
|||||||
res--;
|
res--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#elif POLLER == EPOLL
|
||||||
|
static const size_t max_events = 12;
|
||||||
|
struct epoll_event revents[max_events];
|
||||||
|
const int nb_events = epoll_wait(this->epfd, revents, max_events, -1);
|
||||||
|
if (nb_events == -1)
|
||||||
|
{
|
||||||
|
perror("epoll_wait");
|
||||||
|
throw std::runtime_error("Epoll_wait failed");
|
||||||
|
}
|
||||||
|
for (int i = 0; i < nb_events; ++i)
|
||||||
|
{
|
||||||
|
auto socket_handler = static_cast<SocketHandler*>(revents[i].data.ptr);
|
||||||
|
if (revents[i].events & EPOLLIN)
|
||||||
|
socket_handler->on_recv();
|
||||||
|
if (revents[i].events & EPOLLOUT)
|
||||||
|
socket_handler->on_send();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-10
@@ -9,27 +9,29 @@
|
|||||||
#define POLL 1
|
#define POLL 1
|
||||||
#define EPOLL 2
|
#define EPOLL 2
|
||||||
#define KQUEUE 3
|
#define KQUEUE 3
|
||||||
|
#include <config.h>
|
||||||
#define POLLER POLL
|
#ifndef POLLER
|
||||||
|
#define POLLER POLL
|
||||||
|
#endif
|
||||||
|
|
||||||
#if POLLER == POLL
|
#if POLLER == POLL
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
// TODO, dynamic size, without artificial limit
|
|
||||||
#define MAX_POLL_FD_NUMBER 4096
|
#define MAX_POLL_FD_NUMBER 4096
|
||||||
|
#elif POLLER == EPOLL
|
||||||
|
#include <sys/epoll.h>
|
||||||
|
#else
|
||||||
|
#error Invalid POLLER value
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We pass some SocketHandlers to this the Poller, which uses
|
* We pass some SocketHandlers to this Poller, which uses
|
||||||
* poll/epoll/kqueue/select etc to wait for events on these SocketHandlers,
|
* poll/epoll/kqueue/select etc to wait for events on these SocketHandlers,
|
||||||
* and call the callbacks when event occurs.
|
* and call the callbacks when event occurs.
|
||||||
*
|
*
|
||||||
* TODO: support for all these pollers:
|
* TODO: support these pollers:
|
||||||
* - poll(2) (mandatory)
|
|
||||||
* - epoll(7)
|
|
||||||
* - kqueue(2)
|
* - kqueue(2)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
class Poller
|
class Poller
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -48,12 +50,12 @@ public:
|
|||||||
* Signal the poller that he needs to watch for send events for the given
|
* Signal the poller that he needs to watch for send events for the given
|
||||||
* SocketHandler.
|
* SocketHandler.
|
||||||
*/
|
*/
|
||||||
void watch_send_events(const SocketHandler* const socket_handler);
|
void watch_send_events(SocketHandler* socket_handler);
|
||||||
/**
|
/**
|
||||||
* Signal the poller that he needs to stop watching for send events for
|
* Signal the poller that he needs to stop watching for send events for
|
||||||
* this SocketHandler.
|
* this SocketHandler.
|
||||||
*/
|
*/
|
||||||
void stop_watching_send_events(const SocketHandler* const socket_handler);
|
void stop_watching_send_events(SocketHandler* socket_handler);
|
||||||
/**
|
/**
|
||||||
* Wait for all watched events, and call the SocketHandlers' callbacks
|
* Wait for all watched events, and call the SocketHandlers' callbacks
|
||||||
* when one is ready.
|
* when one is ready.
|
||||||
@@ -72,6 +74,8 @@ private:
|
|||||||
#if POLLER == POLL
|
#if POLLER == POLL
|
||||||
struct pollfd fds[MAX_POLL_FD_NUMBER];
|
struct pollfd fds[MAX_POLL_FD_NUMBER];
|
||||||
nfds_t nfds;
|
nfds_t nfds;
|
||||||
|
#elif POLLER == EPOLL
|
||||||
|
int epfd;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Poller(const Poller&) = delete;
|
Poller(const Poller&) = delete;
|
||||||
|
|||||||
Reference in New Issue
Block a user