Mercurial > irccd
changeset 125:ef4bef0bf0f8
Irccd: implement ServerService, #497
author | David Demelier <markand@malikania.fr> |
---|---|
date | Tue, 10 May 2016 22:51:10 +0200 |
parents | 0895acad4072 |
children | 49572a69c41d |
files | irccd/main.cpp lib/irccd/CMakeSources.cmake lib/irccd/cmd-server-cmode.cpp lib/irccd/cmd-server-cnotice.cpp lib/irccd/cmd-server-connect.cpp lib/irccd/cmd-server-disconnect.cpp lib/irccd/cmd-server-info.cpp lib/irccd/cmd-server-invite.cpp lib/irccd/cmd-server-join.cpp lib/irccd/cmd-server-kick.cpp lib/irccd/cmd-server-list.cpp lib/irccd/cmd-server-me.cpp lib/irccd/cmd-server-message.cpp lib/irccd/cmd-server-mode.cpp lib/irccd/cmd-server-nick.cpp lib/irccd/cmd-server-notice.cpp lib/irccd/cmd-server-part.cpp lib/irccd/cmd-server-reconnect.cpp lib/irccd/cmd-server-topic.cpp lib/irccd/irccd.cpp lib/irccd/irccd.hpp lib/irccd/js-server.cpp lib/irccd/service-server.cpp lib/irccd/service-server.hpp |
diffstat | 24 files changed, 882 insertions(+), 753 deletions(-) [+] |
line wrap: on
line diff
--- a/irccd/main.cpp Tue May 10 22:11:36 2016 +0200 +++ b/irccd/main.cpp Tue May 10 22:51:10 2016 +0200 @@ -37,6 +37,7 @@ #include <irccd/logger.hpp> #include <irccd/options.hpp> #include <irccd/path.hpp> +#include <irccd/service-server.hpp> #include <irccd/system.hpp> #include <irccd/config.hpp> #include <irccd/irccd.hpp> @@ -232,7 +233,7 @@ // [server] section. for (const auto &server : config.loadServers()) { - instance->addServer(server); + instance->serverService().addServer(server); } // [rule] section.
--- a/lib/irccd/CMakeSources.cmake Tue May 10 22:11:36 2016 +0200 +++ b/lib/irccd/CMakeSources.cmake Tue May 10 22:51:10 2016 +0200 @@ -64,6 +64,7 @@ ${CMAKE_CURRENT_LIST_DIR}/server-state-disconnected.hpp ${CMAKE_CURRENT_LIST_DIR}/service.hpp ${CMAKE_CURRENT_LIST_DIR}/service-interrupt.hpp + ${CMAKE_CURRENT_LIST_DIR}/service-server.hpp ${CMAKE_CURRENT_LIST_DIR}/sockets.hpp ${CMAKE_CURRENT_LIST_DIR}/system.hpp ${CMAKE_CURRENT_LIST_DIR}/timer.hpp @@ -132,6 +133,7 @@ ${CMAKE_CURRENT_LIST_DIR}/server-state-connecting.cpp ${CMAKE_CURRENT_LIST_DIR}/server-state-disconnected.cpp ${CMAKE_CURRENT_LIST_DIR}/service-interrupt.cpp + ${CMAKE_CURRENT_LIST_DIR}/service-server.cpp ${CMAKE_CURRENT_LIST_DIR}/sockets.cpp ${CMAKE_CURRENT_LIST_DIR}/system.cpp ${CMAKE_CURRENT_LIST_DIR}/timer.cpp
--- a/lib/irccd/cmd-server-cmode.cpp Tue May 10 22:11:36 2016 +0200 +++ b/lib/irccd/cmd-server-cmode.cpp Tue May 10 22:51:10 2016 +0200 @@ -18,6 +18,7 @@ #include "cmd-server-cmode.hpp" #include "irccd.hpp" +#include "service-server.hpp" namespace irccd { @@ -44,7 +45,7 @@ json::Value ServerChannelMode::exec(Irccd &irccd, const json::Value &request) const { - irccd.requireServer(request.at("server").toString())->cmode( + irccd.serverService().requireServer(request.at("server").toString())->cmode( request.at("channel").toString(), request.at("mode").toString() );
--- a/lib/irccd/cmd-server-cnotice.cpp Tue May 10 22:11:36 2016 +0200 +++ b/lib/irccd/cmd-server-cnotice.cpp Tue May 10 22:51:10 2016 +0200 @@ -18,6 +18,7 @@ #include "cmd-server-cnotice.hpp" #include "irccd.hpp" +#include "service-server.hpp" namespace irccd { @@ -44,7 +45,7 @@ json::Value ServerChannelNotice::exec(Irccd &irccd, const json::Value &request) const { - irccd.requireServer(request.at("server").toString())->cnotice( + irccd.serverService().requireServer(request.at("server").toString())->cnotice( request.at("channel").toString(), request.at("message").toString() );
--- a/lib/irccd/cmd-server-connect.cpp Tue May 10 22:11:36 2016 +0200 +++ b/lib/irccd/cmd-server-connect.cpp Tue May 10 22:51:10 2016 +0200 @@ -21,6 +21,7 @@ #include "cmd-server-connect.hpp" #include "irccd.hpp" #include "server.hpp" +#include "service-server.hpp" #include "util.hpp" namespace irccd { @@ -156,11 +157,11 @@ { auto server = std::make_shared<Server>(readInfo(request), readIdentity(request), readSettings(request)); - if (irccd.hasServer(server->info().name)) { + if (irccd.serverService().hasServer(server->info().name)) { throw std::invalid_argument("server '" + server->info().name + "' already exists"); } - irccd.addServer(std::move(server)); + irccd.serverService().addServer(std::move(server)); return RemoteCommand::exec(irccd, request); }
--- a/lib/irccd/cmd-server-disconnect.cpp Tue May 10 22:11:36 2016 +0200 +++ b/lib/irccd/cmd-server-disconnect.cpp Tue May 10 22:51:10 2016 +0200 @@ -18,6 +18,7 @@ #include "cmd-server-disconnect.hpp" #include "irccd.hpp" +#include "service-server.hpp" namespace irccd { @@ -43,9 +44,9 @@ auto it = request.find("server"); if (it == request.end()) { - irccd.clearServers(); + irccd.serverService().clearServers(); } else { - irccd.removeServer(it->toString()); + irccd.serverService().removeServer(it->toString()); } return RemoteCommand::exec(irccd, request);
--- a/lib/irccd/cmd-server-info.cpp Tue May 10 22:11:36 2016 +0200 +++ b/lib/irccd/cmd-server-info.cpp Tue May 10 22:51:10 2016 +0200 @@ -20,6 +20,7 @@ #include "cmd-server-info.hpp" #include "irccd.hpp" +#include "service-server.hpp" namespace irccd { @@ -51,7 +52,7 @@ json::Value ServerInfo::exec(Irccd &irccd, const json::Value &request) const { - auto server = irccd.requireServer(request.at("server").toString()); + auto server = irccd.serverService().requireServer(request.at("server").toString()); auto response = RemoteCommand::exec(irccd, request); /* General stuff */
--- a/lib/irccd/cmd-server-invite.cpp Tue May 10 22:11:36 2016 +0200 +++ b/lib/irccd/cmd-server-invite.cpp Tue May 10 22:51:10 2016 +0200 @@ -18,6 +18,7 @@ #include "cmd-server-invite.hpp" #include "irccd.hpp" +#include "service-server.hpp" namespace irccd { @@ -53,7 +54,7 @@ json::Value ServerInvite::exec(Irccd &irccd, const json::Value &request) const { - irccd.requireServer( + irccd.serverService().requireServer( request.at("server").toString())->invite( request.at("target").toString(), request.at("channel").toString()
--- a/lib/irccd/cmd-server-join.cpp Tue May 10 22:11:36 2016 +0200 +++ b/lib/irccd/cmd-server-join.cpp Tue May 10 22:51:10 2016 +0200 @@ -18,6 +18,7 @@ #include "cmd-server-join.hpp" #include "irccd.hpp" +#include "service-server.hpp" namespace irccd { @@ -58,7 +59,7 @@ json::Value ServerJoin::exec(Irccd &irccd, const json::Value &request) const { - irccd.requireServer( + irccd.serverService().requireServer( request.at("server").toString())->join( request.at("channel").toString(), request.valueOr("password", json::Type::String, "").toString()
--- a/lib/irccd/cmd-server-kick.cpp Tue May 10 22:11:36 2016 +0200 +++ b/lib/irccd/cmd-server-kick.cpp Tue May 10 22:51:10 2016 +0200 @@ -18,6 +18,7 @@ #include "cmd-server-kick.hpp" #include "irccd.hpp" +#include "service-server.hpp" namespace irccd { @@ -60,7 +61,7 @@ json::Value ServerKick::exec(Irccd &irccd, const json::Value &request) const { - irccd.requireServer(request.at("server").toString())->kick( + irccd.serverService().requireServer(request.at("server").toString())->kick( request.at("target").toString(), request.at("channel").toString(), request.valueOr("reason", json::Type::String, "").toString()
--- a/lib/irccd/cmd-server-list.cpp Tue May 10 22:11:36 2016 +0200 +++ b/lib/irccd/cmd-server-list.cpp Tue May 10 22:51:10 2016 +0200 @@ -20,6 +20,7 @@ #include "cmd-server-list.hpp" #include "irccd.hpp" +#include "service-server.hpp" namespace irccd { @@ -40,7 +41,7 @@ auto json = json::object({}); auto list = json::array({}); - for (const auto &server : irccd.servers()) { + for (const auto &server : irccd.serverService().servers()) { list.append(server->info().name); }
--- a/lib/irccd/cmd-server-me.cpp Tue May 10 22:11:36 2016 +0200 +++ b/lib/irccd/cmd-server-me.cpp Tue May 10 22:51:10 2016 +0200 @@ -18,6 +18,7 @@ #include "cmd-server-me.hpp" #include "irccd.hpp" +#include "service-server.hpp" namespace irccd { @@ -53,7 +54,7 @@ json::Value ServerMe::exec(Irccd &irccd, const json::Value &request) const { - irccd.requireServer(request.at("server").toString())->me( + irccd.serverService().requireServer(request.at("server").toString())->me( request.at("target").toString(), request.at("message").toString() );
--- a/lib/irccd/cmd-server-message.cpp Tue May 10 22:11:36 2016 +0200 +++ b/lib/irccd/cmd-server-message.cpp Tue May 10 22:51:10 2016 +0200 @@ -18,6 +18,7 @@ #include "cmd-server-message.hpp" #include "irccd.hpp" +#include "service-server.hpp" namespace irccd { @@ -53,7 +54,7 @@ json::Value ServerMessage::exec(Irccd &irccd, const json::Value &request) const { - irccd.requireServer(request.at("server").toString())->me( + irccd.serverService().requireServer(request.at("server").toString())->me( request.at("target").toString(), request.at("message").toString() );
--- a/lib/irccd/cmd-server-mode.cpp Tue May 10 22:11:36 2016 +0200 +++ b/lib/irccd/cmd-server-mode.cpp Tue May 10 22:51:10 2016 +0200 @@ -18,6 +18,7 @@ #include "cmd-server-mode.hpp" #include "irccd.hpp" +#include "service-server.hpp" namespace irccd { @@ -51,7 +52,7 @@ json::Value ServerMode::exec(Irccd &irccd, const json::Value &request) const { - irccd.requireServer(request.at("server").toString())->mode(request.at("mode").toString()); + irccd.serverService().requireServer(request.at("server").toString())->mode(request.at("mode").toString()); return nullptr; }
--- a/lib/irccd/cmd-server-nick.cpp Tue May 10 22:11:36 2016 +0200 +++ b/lib/irccd/cmd-server-nick.cpp Tue May 10 22:51:10 2016 +0200 @@ -18,6 +18,7 @@ #include "cmd-server-nick.hpp" #include "irccd.hpp" +#include "service-server.hpp" namespace irccd { @@ -51,7 +52,7 @@ json::Value ServerNick::exec(Irccd &irccd, const json::Value &object) const { - irccd.requireServer(object.at("server").toString())->nick(object.at("nickname").toString()); + irccd.serverService().requireServer(object.at("server").toString())->nick(object.at("nickname").toString()); return nullptr; }
--- a/lib/irccd/cmd-server-notice.cpp Tue May 10 22:11:36 2016 +0200 +++ b/lib/irccd/cmd-server-notice.cpp Tue May 10 22:51:10 2016 +0200 @@ -18,6 +18,7 @@ #include "cmd-server-notice.hpp" #include "irccd.hpp" +#include "service-server.hpp" namespace irccd { @@ -53,7 +54,7 @@ json::Value ServerNotice::exec(Irccd &irccd, const json::Value &request) const { - irccd.requireServer(request.at("server").toString())->notice( + irccd.serverService().requireServer(request.at("server").toString())->notice( request.at("target").toString(), request.at("message").toString() );
--- a/lib/irccd/cmd-server-part.cpp Tue May 10 22:11:36 2016 +0200 +++ b/lib/irccd/cmd-server-part.cpp Tue May 10 22:51:10 2016 +0200 @@ -18,6 +18,7 @@ #include "cmd-server-part.hpp" #include "irccd.hpp" +#include "service-server.hpp" namespace irccd { @@ -58,7 +59,7 @@ json::Value ServerPart::exec(Irccd &irccd, const json::Value &request) const { - irccd.requireServer(request.at("server").toString())->part( + irccd.serverService().requireServer(request.at("server").toString())->part( request.at("channel").toString(), request.valueOr("reason", "").toString() );
--- a/lib/irccd/cmd-server-reconnect.cpp Tue May 10 22:11:36 2016 +0200 +++ b/lib/irccd/cmd-server-reconnect.cpp Tue May 10 22:51:10 2016 +0200 @@ -18,6 +18,7 @@ #include "cmd-server-reconnect.hpp" #include "irccd.hpp" +#include "service-server.hpp" namespace irccd { @@ -48,9 +49,9 @@ auto server = request.find("server"); if (server != request.end() && server->isString()) { - irccd.requireServer(server->toString())->reconnect(); + irccd.serverService().requireServer(server->toString())->reconnect(); } else { - for (auto &server : irccd.servers()) { + for (auto &server : irccd.serverService().servers()) { server->reconnect(); } }
--- a/lib/irccd/cmd-server-topic.cpp Tue May 10 22:11:36 2016 +0200 +++ b/lib/irccd/cmd-server-topic.cpp Tue May 10 22:51:10 2016 +0200 @@ -18,6 +18,7 @@ #include "cmd-server-topic.hpp" #include "irccd.hpp" +#include "service-server.hpp" namespace irccd { @@ -53,7 +54,7 @@ json::Value ServerTopic::exec(Irccd &irccd, const json::Value &request) const { - irccd.requireServer(request.at("server").toString())->topic( + irccd.serverService().requireServer(request.at("server").toString())->topic( request.at("channel").toString(), request.at("topic").toString() );
--- a/lib/irccd/irccd.cpp Tue May 10 22:11:36 2016 +0200 +++ b/lib/irccd/irccd.cpp Tue May 10 22:51:10 2016 +0200 @@ -25,8 +25,8 @@ #include "irccd.hpp" #include "logger.hpp" #include "path.hpp" -#include "server-event.hpp" #include "service-interrupt.hpp" +#include "service-server.hpp" #include "util.hpp" using namespace std; @@ -37,533 +37,6 @@ namespace irccd { -void Irccd::handleServerChannelMode(std::weak_ptr<Server> ptr, std::string origin, std::string channel, std::string mode, std::string arg) -{ - std::shared_ptr<Server> server = ptr.lock(); - - if (!server) { - return; - } - - log::debug() << "server " << server->info().name << ": event onChannelMode:\n"; - log::debug() << " origin: " << origin << "\n"; - log::debug() << " channel: " << channel << "\n"; - log::debug() << " mode: " << mode << "\n"; - log::debug() << " argument: " << arg << std::endl; - - broadcast(json::object({ - { "event", "onChannelMode" }, - { "server", server->info().name }, - { "origin", origin }, - { "channel", channel }, - { "mode", mode }, - { "argument", arg } - }).toJson(0)); - -#if defined(WITH_JS) - post(ServerEvent(server->info().name, origin, channel, - [=] (Plugin &) -> std::string { - return "onChannelMode"; - }, - [=] (Plugin &plugin) { - plugin.onChannelMode(std::move(server), std::move(origin), std::move(channel), std::move(mode), std::move(arg)); - } - )); -#endif -} - -void Irccd::handleServerChannelNotice(std::weak_ptr<Server> ptr, std::string origin, std::string channel, std::string message) -{ - std::shared_ptr<Server> server = ptr.lock(); - - if (!server) { - return; - } - - log::debug() << "server " << server->info().name << ": event onChannelNotice:\n"; - log::debug() << " origin: " << origin << "\n"; - log::debug() << " channel: " << channel << "\n"; - log::debug() << " message: " << message << std::endl; - - broadcast(json::object({ - { "event", "onChannelNotice" }, - { "server", server->info().name }, - { "origin", origin }, - { "channel", channel }, - { "message", message } - }).toJson(0)); - -#if defined(WITH_JS) - post(ServerEvent(server->info().name, origin, channel, - [=] (Plugin &) -> std::string { - return "onChannelNotice"; - }, - [=] (Plugin &plugin) { - plugin.onChannelNotice(std::move(server), std::move(origin), std::move(channel), std::move(message)); - } - )); -#endif -} - -void Irccd::handleServerConnect(std::weak_ptr<Server> ptr) -{ - std::shared_ptr<Server> server = ptr.lock(); - - if (!server) { - return; - } - - log::debug() << "server " << server->info().name << ": event onConnect" << std::endl; - - broadcast(json::object({ - { "event", "onConnect" }, - { "server", server->info().name } - }).toJson(0)); - -#if defined(WITH_JS) - post(ServerEvent(server->info().name, /* origin */ "", /* channel */ "", - [=] (Plugin &) -> std::string { - return "onConnect"; - }, - [=] (Plugin &plugin) { - plugin.onConnect(std::move(server)); - } - )); -#endif -} - -void Irccd::handleServerInvite(std::weak_ptr<Server> ptr, std::string origin, std::string channel, std::string target) -{ - std::shared_ptr<Server> server = ptr.lock(); - - if (!server) { - return; - } - - log::debug() << "server " << server->info().name << ": event onInvite:\n"; - log::debug() << " origin: " << origin << "\n"; - log::debug() << " channel: " << channel << "\n"; - log::debug() << " target: " << target << std::endl; - - broadcast(json::object({ - { "event", "onInvite" }, - { "server", server->info().name }, - { "origin", origin }, - { "channel", channel } - }).toJson(0)); - -#if defined(WITH_JS) - post(ServerEvent(server->info().name, origin, channel, - [=] (Plugin &) -> std::string { - return "onInvite"; - }, - [=] (Plugin &plugin) { - plugin.onInvite(std::move(server), std::move(origin), std::move(channel)); - } - )); -#endif -} - -void Irccd::handleServerJoin(std::weak_ptr<Server> ptr, std::string origin, std::string channel) -{ - std::shared_ptr<Server> server = ptr.lock(); - - if (!server) { - return; - } - - log::debug() << "server " << server->info().name << ": event onJoin:\n"; - log::debug() << " origin: " << origin << "\n"; - log::debug() << " channel: " << channel << std::endl; - - broadcast(json::object({ - { "event", "onJoin" }, - { "server", server->info().name }, - { "origin", origin }, - { "channel", channel } - }).toJson(0)); - -#if defined(WITH_JS) - post(ServerEvent(server->info().name, origin, channel, - [=] (Plugin &) -> std::string { - return "onJoin"; - }, - [=] (Plugin &plugin) { - plugin.onJoin(std::move(server), std::move(origin), std::move(channel)); - } - )); -#endif -} - -void Irccd::handleServerKick(std::weak_ptr<Server> ptr, std::string origin, std::string channel, std::string target, std::string reason) -{ - std::shared_ptr<Server> server = ptr.lock(); - - if (!server) { - return; - } - - log::debug() << "server " << server->info().name << ": event onKick:\n"; - log::debug() << " origin: " << origin << "\n"; - log::debug() << " channel: " << channel << "\n"; - log::debug() << " target: " << target << "\n"; - log::debug() << " reason: " << reason << std::endl; - - broadcast(json::object({ - { "event", "onKick" }, - { "server", server->info().name }, - { "origin", origin }, - { "channel", channel }, - { "target", target }, - { "reason", reason } - }).toJson(0)); - -#if defined(WITH_JS) - post(ServerEvent(server->info().name, origin, channel, - [=] (Plugin &) -> std::string { - return "onKick"; - }, - [=] (Plugin &plugin) { - plugin.onKick(std::move(server), std::move(origin), std::move(channel), std::move(target), std::move(reason)); - } - )); -#endif -} - -void Irccd::handleServerMessage(std::weak_ptr<Server> ptr, std::string origin, std::string channel, std::string message) -{ - std::shared_ptr<Server> server = ptr.lock(); - - if (!server) { - return; - } - - log::debug() << "server " << server->info().name << ": event onMessage:\n"; - log::debug() << " origin: " << origin << "\n"; - log::debug() << " channel: " << channel << "\n"; - log::debug() << " message: " << message << std::endl; - - broadcast(json::object({ - { "event", "onMessage" }, - { "server", server->info().name }, - { "origin", origin }, - { "channel", channel }, - { "message", message } - }).toJson(0)); - -#if defined(WITH_JS) - post(ServerEvent(server->info().name, origin, channel, - [=] (Plugin &plugin) -> std::string { - return util::parseMessage(message, server->settings().command, plugin.name()).second == util::MessageType::Command ? "onCommand" : "onMessage"; - }, - [=] (Plugin &plugin) { - util::MessagePair pack = util::parseMessage(message, server->settings().command, plugin.name()); - - if (pack.second == util::MessageType::Command) - plugin.onCommand(std::move(server), std::move(origin), std::move(channel), std::move(pack.first)); - else - plugin.onMessage(std::move(server), std::move(origin), std::move(channel), std::move(pack.first)); - } - )); -#endif -} - -void Irccd::handleServerMe(std::weak_ptr<Server> ptr, std::string origin, std::string target, std::string message) -{ - std::shared_ptr<Server> server = ptr.lock(); - - if (!server) { - return; - } - - log::debug() << "server " << server->info().name << ": event onMe:\n"; - log::debug() << " origin: " << origin << "\n"; - log::debug() << " target: " << target << "\n"; - log::debug() << " message: " << message << std::endl; - - broadcast(json::object({ - { "event", "onMe" }, - { "server", server->info().name }, - { "origin", origin }, - { "target", target }, - { "message", message } - }).toJson(0)); - -#if defined(WITH_JS) - post(ServerEvent(server->info().name, origin, target, - [=] (Plugin &) -> std::string { - return "onMe"; - }, - [=] (Plugin &plugin) { - plugin.onMe(std::move(server), std::move(origin), std::move(target), std::move(message)); - } - )); -#endif -} - -void Irccd::handleServerMode(std::weak_ptr<Server> ptr, std::string origin, std::string mode) -{ - std::shared_ptr<Server> server = ptr.lock(); - - if (!server) { - return; - } - - log::debug() << "server " << server->info().name << ": event onMode\n"; - log::debug() << " origin: " << origin << "\n"; - log::debug() << " mode: " << mode << std::endl; - - broadcast(json::object({ - { "event", "onMode" }, - { "server", server->info().name }, - { "origin", origin }, - { "mode", mode } - }).toJson(0)); - -#if defined(WITH_JS) - post(ServerEvent(server->info().name, origin, /* channel */ "", - [=] (Plugin &) -> std::string { - return "onMode"; - }, - [=] (Plugin &plugin) { - plugin.onMode(std::move(server), std::move(origin), std::move(mode)); - } - )); -#endif -} - -void Irccd::handleServerNames(std::weak_ptr<Server> ptr, std::string channel, std::set<std::string> nicknames) -{ - std::shared_ptr<Server> server = ptr.lock(); - - if (!server) { - return; - } - - log::debug() << "server " << server->info().name << ": event onNames:\n"; - log::debug() << " channel: " << channel << "\n"; - log::debug() << " names: " << util::join(nicknames.begin(), nicknames.end(), ", ") << std::endl; - - json::Value names(std::vector<json::Value>(nicknames.begin(), nicknames.end())); - - broadcast(json::object({ - { "event", "onNames" }, - { "server", server->info().name }, - { "channel", channel }, - { "names", std::move(names) } - }).toJson(0)); - -#if defined(WITH_JS) - post(ServerEvent(server->info().name, /* origin */ "", channel, - [=] (Plugin &) -> std::string { - return "onNames"; - }, - [=] (Plugin &plugin) { - plugin.onNames(std::move(server), std::move(channel), std::vector<std::string>(nicknames.begin(), nicknames.end())); - } - )); -#endif -} - -void Irccd::handleServerNick(std::weak_ptr<Server> ptr, std::string origin, std::string nickname) -{ - std::shared_ptr<Server> server = ptr.lock(); - - if (!server) { - return; - } - - log::debug() << "server " << server->info().name << ": event onNick:\n"; - log::debug() << " origin: " << origin << "\n"; - log::debug() << " nickname: " << nickname << std::endl; - - broadcast(json::object({ - { "event", "onNick" }, - { "server", server->info().name }, - { "origin", origin }, - { "nickname", nickname } - }).toJson(0)); - -#if defined(WITH_JS) - post(ServerEvent(server->info().name, origin, /* channel */ "", - [=] (Plugin &) -> std::string { - return "onNick"; - }, - [=] (Plugin &plugin) { - plugin.onNick(std::move(server), std::move(origin), std::move(nickname)); - } - )); -#endif -} - -void Irccd::handleServerNotice(std::weak_ptr<Server> ptr, std::string origin, std::string message) -{ - std::shared_ptr<Server> server = ptr.lock(); - - if (!server) { - return; - } - - log::debug() << "server " << server->info().name << ": event onNotice:\n"; - log::debug() << " origin: " << origin << "\n"; - log::debug() << " message: " << message << std::endl; - - broadcast(json::object({ - { "event", "onNotice" }, - { "server", server->info().name }, - { "origin", origin }, - { "message", message } - }).toJson(0)); - -#if defined(WITH_JS) - post(ServerEvent(server->info().name, origin, /* channel */ "", - [=] (Plugin &) -> std::string { - return "onNotice"; - }, - [=] (Plugin &plugin) { - plugin.onNotice(std::move(server), std::move(origin), std::move(message)); - } - )); -#endif -} - -void Irccd::handleServerPart(std::weak_ptr<Server> ptr, std::string origin, std::string channel, std::string reason) -{ - std::shared_ptr<Server> server = ptr.lock(); - - if (!server) { - return; - } - - log::debug() << "server " << server->info().name << ": event onPart:\n"; - log::debug() << " origin: " << origin << "\n"; - log::debug() << " channel: " << channel << "\n"; - log::debug() << " reason: " << reason << std::endl; - - broadcast(json::object({ - { "event", "onPart" }, - { "server", server->info().name }, - { "origin", origin }, - { "channel", channel }, - { "reason", reason } - }).toJson(0)); - -#if defined(WITH_JS) - post(ServerEvent(server->info().name, origin, channel, - [=] (Plugin &) -> std::string { - return "onPart"; - }, - [=] (Plugin &plugin) { - plugin.onPart(std::move(server), std::move(origin), std::move(channel), std::move(reason)); - } - )); -#endif -} - -void Irccd::handleServerQuery(std::weak_ptr<Server> ptr, std::string origin, std::string message) -{ - std::shared_ptr<Server> server = ptr.lock(); - - if (!server) { - return; - } - - log::debug() << "server " << server->info().name << ": event onQuery:\n"; - log::debug() << " origin: " << origin << "\n"; - log::debug() << " message: " << message << std::endl; - - broadcast(json::object({ - { "event", "onQuery" }, - { "server", server->info().name }, - { "origin", origin }, - { "message", message } - }).toJson(0)); - -#if defined(WITH_JS) - post(ServerEvent(server->info().name, origin, /* channel */ "", - [=] (Plugin &plugin) -> std::string { - return util::parseMessage(message, server->settings().command, plugin.name()).second == util::MessageType::Command ? "onQueryCommand" : "onQuery"; - }, - [=] (Plugin &plugin) { - util::MessagePair pack = util::parseMessage(message, server->settings().command, plugin.name()); - - if (pack.second == util::MessageType::Command) - plugin.onQueryCommand(std::move(server), std::move(origin), std::move(pack.first)); - else - plugin.onQuery(std::move(server), std::move(origin), std::move(pack.first)); - } - )); -#endif -} - -void Irccd::handleServerTopic(std::weak_ptr<Server> ptr, std::string origin, std::string channel, std::string topic) -{ - std::shared_ptr<Server> server = ptr.lock(); - - if (!server) { - return; - } - - log::debug() << "server " << server->info().name << ": event onTopic:\n"; - log::debug() << " origin: " << origin << "\n"; - log::debug() << " channel: " << channel << "\n"; - log::debug() << " topic: " << topic << std::endl; - - broadcast(json::object({ - { "event", "onTopic" }, - { "server", server->info().name }, - { "origin", origin }, - { "channel", channel }, - { "topic", topic } - }).toJson(0)); - -#if defined(WITH_JS) - post(ServerEvent(server->info().name, origin, channel, - [=] (Plugin &) -> std::string { - return "onTopic"; - }, - [=] (Plugin &plugin) { - plugin.onTopic(std::move(server), std::move(origin), std::move(channel), std::move(topic)); - } - )); -#endif -} - -void Irccd::handleServerWhois(std::weak_ptr<Server> ptr, ServerWhois whois) -{ - std::shared_ptr<Server> server = ptr.lock(); - - if (!server) { - return; - } - - log::debug() << "server " << server->info().name << ": event onWhois\n"; - log::debug() << " nickname: " << whois.nick << "\n"; - log::debug() << " username: " << whois.user << "\n"; - log::debug() << " host: " << whois.host << "\n"; - log::debug() << " realname: " << whois.realname << "\n"; - log::debug() << " channels: " << util::join(whois.channels.begin(), whois.channels.end()) << std::endl; - - broadcast(json::object({ - { "server", server->info().name }, - { "nickname", whois.nick }, - { "username", whois.user }, - { "host", whois.host }, - { "realname", whois.realname } - }).toJson(0)); - -#if defined(WITH_JS) - post(ServerEvent(server->info().name, /* origin */ "", /* channel */ "", - [=] (Plugin &) -> std::string { - return "onWhois"; - }, - [=] (Plugin &plugin) { - plugin.onWhois(std::move(server), std::move(whois)); - } - )); -#endif -} - void Irccd::handleTransportCommand(std::weak_ptr<TransportClient> ptr, const json::Value &object) { assert(object.isObject()); @@ -676,16 +149,9 @@ } } -void Irccd::processServers(fd_set &input, fd_set &output) -{ - for (auto &server : m_servers) { - server->sync(input, output); - } -} - void Irccd::process(fd_set &setinput, fd_set &setoutput) { - // TODO: create services for servers and transports + // TODO: create services for transports for (const auto &service : m_services) { service->sync(setinput, setoutput); } @@ -695,15 +161,14 @@ /* 3. Check for transport servers */ processTransportServers(setinput); - - /* 4. Check for servers */ - processServers(setinput, setoutput); } Irccd::Irccd() : m_interruptService(std::make_shared<InterruptService>()) + , m_serverService(std::make_shared<ServerService>(*this)) { m_services.push_back(m_interruptService); + m_services.push_back(m_serverService); } void Irccd::post(std::function<void (Irccd &)> ev) noexcept @@ -714,89 +179,6 @@ m_interruptService->interrupt(); } -void Irccd::addServer(shared_ptr<Server> server) noexcept -{ -#if 0 - assert(m_servers.count(server->info().name) == 0); -#endif - - std::weak_ptr<Server> ptr(server); - - server->onChannelMode.connect(std::bind(&Irccd::handleServerChannelMode, this, ptr, _1, _2, _3, _4)); - server->onChannelNotice.connect(std::bind(&Irccd::handleServerChannelNotice, this, ptr, _1, _2, _3)); - server->onConnect.connect(std::bind(&Irccd::handleServerConnect, this, ptr)); - server->onInvite.connect(std::bind(&Irccd::handleServerInvite, this, ptr, _1, _2, _3)); - server->onJoin.connect(std::bind(&Irccd::handleServerJoin, this, ptr, _1, _2)); - server->onKick.connect(std::bind(&Irccd::handleServerKick, this, ptr, _1, _2, _3, _4)); - server->onMessage.connect(std::bind(&Irccd::handleServerMessage, this, ptr, _1, _2, _3)); - server->onMe.connect(std::bind(&Irccd::handleServerMe, this, ptr, _1, _2, _3)); - server->onMode.connect(std::bind(&Irccd::handleServerMode, this, ptr, _1, _2)); - server->onNames.connect(std::bind(&Irccd::handleServerNames, this, ptr, _1, _2)); - server->onNick.connect(std::bind(&Irccd::handleServerNick, this, ptr, _1, _2)); - server->onNotice.connect(std::bind(&Irccd::handleServerNotice, this, ptr, _1, _2)); - server->onPart.connect(std::bind(&Irccd::handleServerPart, this, ptr, _1, _2, _3)); - server->onQuery.connect(std::bind(&Irccd::handleServerQuery, this, ptr, _1, _2)); - server->onTopic.connect(std::bind(&Irccd::handleServerTopic, this, ptr, _1, _2, _3)); - server->onWhois.connect(std::bind(&Irccd::handleServerWhois, this, ptr, _1)); - server->onDie.connect([this, ptr] () { - post([=] (Irccd &) { - auto server = ptr.lock(); - - if (server) { - log::info(fmt::format("server {}: removed", server->info().name)); - m_servers.erase(std::find(m_servers.begin(), m_servers.end(), server)); - } - }); - }); - - m_servers.push_back(std::move(server)); -} - -std::shared_ptr<Server> Irccd::getServer(const std::string &name) const noexcept -{ - auto it = std::find_if(m_servers.begin(), m_servers.end(), [&] (const auto &server) { - return server->info().name == name; - }); - - if (it == m_servers.end()) { - return nullptr; - } - - return *it; -} - -std::shared_ptr<Server> Irccd::requireServer(const std::string &name) const -{ - auto server = getServer(name); - - if (!server) { - throw std::invalid_argument("server {} not found"_format(name)); - } - - return server; -} - -void Irccd::removeServer(const std::string &name) -{ - auto it = std::find_if(m_servers.begin(), m_servers.end(), [&] (const auto &server) { - return server->info().name == name; - }); - - if (it != m_servers.end()) { - (*it)->disconnect(); - m_servers.erase(it); - } -} - -void Irccd::clearServers() noexcept -{ - for (auto &server : m_servers) { - server->disconnect(); - } - - m_servers.clear(); -} - void Irccd::addTransport(std::shared_ptr<TransportServer> ts) { m_transportServers.push_back(std::move(ts)); @@ -991,17 +373,11 @@ FD_ZERO(&setinput); FD_ZERO(&setoutput); - // TODO: create services for servers and transports + // TODO: create services for transports for (const auto &service : m_services) { service->prepare(setinput, setoutput, max); } - /* 2. Add servers */ - for (auto &server : m_servers) { - server->update(); - server->prepare(setinput, setoutput, max); - } - /* 3. Add transports clients */ for (auto &client : m_transportClients) { set(setinput, client->handle());
--- a/lib/irccd/irccd.hpp Tue May 10 22:11:36 2016 +0200 +++ b/lib/irccd/irccd.hpp Tue May 10 22:51:10 2016 +0200 @@ -51,6 +51,7 @@ class InterruptService; class Irccd; class Plugin; +class ServerService; class Service; class TransportCommand; @@ -75,9 +76,6 @@ std::mutex m_mutex; std::vector<std::function<void (Irccd &)>> m_events; - // Servers. - std::vector<std::shared_ptr<Server>> m_servers; - // Optional plugins. #if defined(WITH_JS) std::vector<std::shared_ptr<Plugin>> m_plugins; @@ -92,31 +90,10 @@ // Services std::shared_ptr<InterruptService> m_interruptService; + std::shared_ptr<ServerService> m_serverService; std::vector<std::shared_ptr<Service>> m_services; /* - * Server slots - * ---------------------------------------------------------- - */ - - void handleServerChannelMode(std::weak_ptr<Server> server, std::string origin, std::string channel, std::string mode, std::string arg); - void handleServerChannelNotice(std::weak_ptr<Server> server, std::string origin, std::string channel, std::string notice); - void handleServerConnect(std::weak_ptr<Server> server); - void handleServerInvite(std::weak_ptr<Server> server, std::string origin, std::string channel, std::string target); - void handleServerJoin(std::weak_ptr<Server> server, std::string origin, std::string channel); - void handleServerKick(std::weak_ptr<Server> server, std::string origin, std::string channel, std::string target, std::string reason); - void handleServerMessage(std::weak_ptr<Server> server, std::string origin, std::string channel, std::string message); - void handleServerMe(std::weak_ptr<Server> server, std::string origin, std::string target, std::string message); - void handleServerMode(std::weak_ptr<Server> server, std::string origin, std::string mode); - void handleServerNames(std::weak_ptr<Server> server, std::string channel, std::set<std::string> nicknames); - void handleServerNick(std::weak_ptr<Server> server, std::string origin, std::string nickname); - void handleServerNotice(std::weak_ptr<Server> server, std::string origin, std::string message); - void handleServerPart(std::weak_ptr<Server> server, std::string origin, std::string channel, std::string reason); - void handleServerQuery(std::weak_ptr<Server> server, std::string origin, std::string message); - void handleServerTopic(std::weak_ptr<Server> server, std::string origin, std::string channel, std::string topic); - void handleServerWhois(std::weak_ptr<Server> server, ServerWhois whois); - - /* * Transport clients slots * ---------------------------------------------------------- */ @@ -144,9 +121,14 @@ void processTransportClients(fd_set &input, fd_set &output); void processTransportServers(fd_set &input); - void processServers(fd_set &input, fd_set &output); void process(fd_set &setinput, fd_set &setoutput); + Irccd(const Irccd &) = delete; + Irccd(Irccd &&) = delete; + + Irccd &operator=(const Irccd &) = delete; + Irccd &operator=(Irccd &&) = delete; + public: /** * Prepare standard services. @@ -162,6 +144,16 @@ } /** + * Access the server service. + * + * \return the service + */ + inline ServerService &serverService() noexcept + { + return *m_serverService; + } + + /** * Add an event to the queue. This will immediately signals the event loop to interrupt itself to dispatch * the pending events. * @@ -171,79 +163,6 @@ void post(std::function<void (Irccd &)> ev) noexcept; /* - * Server management - * ---------------------------------------------------------- - * - * Functions to get or create new servers. - * - * Servers that are added to this instance are automatically polled when run() is called. - */ - - /** - * Check if a server exists. - * - * \param name the name - * \return true if exists - */ - inline bool hasServer(const std::string &name) const noexcept - { - return std::count_if(m_servers.cbegin(), m_servers.end(), [&] (const auto &sv) { - return sv->info().name == name; - }) > 0; - } - - /** - * Add a new server to the application. - * - * \pre hasServer must return false - * \param sv the server - */ - void addServer(std::shared_ptr<Server> sv) noexcept; - - /** - * Get a server or empty one if not found - * - * \param name the server name - * \return the server or empty one if not found - */ - std::shared_ptr<Server> getServer(const std::string &name) const noexcept; - - /** - * Find a server by name. - * - * \param name the server name - * \return the server - * \throw std::out_of_range if the server does not exist - */ - std::shared_ptr<Server> requireServer(const std::string &name) const; - - /** - * Get the list of servers - * - * \return the servers - */ - inline const std::vector<std::shared_ptr<Server>> &servers() const noexcept - { - return m_servers; - } - - /** - * Remove a server from the irccd instance. - * - * The server if any, will be disconnected. - * - * \param name the server name - */ - void removeServer(const std::string &name); - - /** - * Remove all servers. - * - * All servers will be disconnected. - */ - void clearServers() noexcept; - - /* * Transport management * ---------------------------------------------------------- *
--- a/lib/irccd/js-server.cpp Tue May 10 22:11:36 2016 +0200 +++ b/lib/irccd/js-server.cpp Tue May 10 22:51:10 2016 +0200 @@ -22,6 +22,7 @@ #include "irccd.hpp" #include "js-server.hpp" #include "server.hpp" +#include "service-server.hpp" namespace irccd { @@ -424,7 +425,7 @@ auto server = duk::get<duk::Shared<Server>>(ctx, 0); if (server) { - duk::getGlobal<duk::RawPointer<Irccd>>(ctx, "\xff""\xff""irccd")->addServer(server); + duk::getGlobal<duk::RawPointer<Irccd>>(ctx, "\xff""\xff""irccd")->serverService().addServer(server); } return 0; @@ -447,7 +448,7 @@ const auto irccd = duk::getGlobal<duk::RawPointer<Irccd>>(ctx, "\xff""\xff""irccd"); try { - duk::push(ctx, duk::Shared<Server>{irccd->requireServer(name)}); + duk::push(ctx, duk::Shared<Server>{irccd->serverService().requireServer(name)}); } catch (...) { return 0; } @@ -468,7 +469,7 @@ { duk::push(ctx, duk::Object{}); - for (const auto &server : duk::getGlobal<duk::RawPointer<Irccd>>(ctx, "\xff""\xff""irccd")->servers()) { + for (const auto &server : duk::getGlobal<duk::RawPointer<Irccd>>(ctx, "\xff""\xff""irccd")->serverService().servers()) { duk::putProperty(ctx, -1, server->info().name, duk::Shared<Server>{server}); } @@ -486,7 +487,7 @@ */ duk::Ret remove(duk::ContextPtr ctx) { - duk::getGlobal<duk::RawPointer<Irccd>>(ctx, "\xff""\xff""irccd")->removeServer(duk::require<std::string>(ctx, 0)); + duk::getGlobal<duk::RawPointer<Irccd>>(ctx, "\xff""\xff""irccd")->serverService().removeServer(duk::require<std::string>(ctx, 0)); return 0; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/irccd/service-server.cpp Tue May 10 22:51:10 2016 +0200 @@ -0,0 +1,671 @@ +/* + * service-server.cpp -- manage IRC servers + * + * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <algorithm> + +#include <format.h> + +#include "irccd.hpp" +#include "logger.hpp" +#include "server-event.hpp" +#include "service-server.hpp" +#include "sysconfig.hpp" +#include "util.hpp" + +using namespace fmt::literals; + +namespace irccd { + +void ServerService::handleChannelMode(std::weak_ptr<Server> ptr, std::string origin, std::string channel, std::string mode, std::string arg) +{ + std::shared_ptr<Server> server = ptr.lock(); + + if (!server) { + return; + } + + log::debug() << "server " << server->info().name << ": event onChannelMode:\n"; + log::debug() << " origin: " << origin << "\n"; + log::debug() << " channel: " << channel << "\n"; + log::debug() << " mode: " << mode << "\n"; + log::debug() << " argument: " << arg << std::endl; + + m_irccd.broadcast(json::object({ + { "event", "onChannelMode" }, + { "server", server->info().name }, + { "origin", origin }, + { "channel", channel }, + { "mode", mode }, + { "argument", arg } + }).toJson(0)); + +#if defined(WITH_JS) + m_irccd.post(ServerEvent(server->info().name, origin, channel, + [=] (Plugin &) -> std::string { + return "onChannelMode"; + }, + [=] (Plugin &plugin) { + plugin.onChannelMode(std::move(server), std::move(origin), std::move(channel), std::move(mode), std::move(arg)); + } + )); +#endif +} + +void ServerService::handleChannelNotice(std::weak_ptr<Server> ptr, std::string origin, std::string channel, std::string message) +{ + std::shared_ptr<Server> server = ptr.lock(); + + if (!server) { + return; + } + + log::debug() << "server " << server->info().name << ": event onChannelNotice:\n"; + log::debug() << " origin: " << origin << "\n"; + log::debug() << " channel: " << channel << "\n"; + log::debug() << " message: " << message << std::endl; + + m_irccd.broadcast(json::object({ + { "event", "onChannelNotice" }, + { "server", server->info().name }, + { "origin", origin }, + { "channel", channel }, + { "message", message } + }).toJson(0)); + +#if defined(WITH_JS) + m_irccd.post(ServerEvent(server->info().name, origin, channel, + [=] (Plugin &) -> std::string { + return "onChannelNotice"; + }, + [=] (Plugin &plugin) { + plugin.onChannelNotice(std::move(server), std::move(origin), std::move(channel), std::move(message)); + } + )); +#endif +} + +void ServerService::handleConnect(std::weak_ptr<Server> ptr) +{ + std::shared_ptr<Server> server = ptr.lock(); + + if (!server) { + return; + } + + log::debug() << "server " << server->info().name << ": event onConnect" << std::endl; + + m_irccd.broadcast(json::object({ + { "event", "onConnect" }, + { "server", server->info().name } + }).toJson(0)); + +#if defined(WITH_JS) + m_irccd.post(ServerEvent(server->info().name, /* origin */ "", /* channel */ "", + [=] (Plugin &) -> std::string { + return "onConnect"; + }, + [=] (Plugin &plugin) { + plugin.onConnect(std::move(server)); + } + )); +#endif +} + +void ServerService::handleInvite(std::weak_ptr<Server> ptr, std::string origin, std::string channel, std::string target) +{ + std::shared_ptr<Server> server = ptr.lock(); + + if (!server) { + return; + } + + log::debug() << "server " << server->info().name << ": event onInvite:\n"; + log::debug() << " origin: " << origin << "\n"; + log::debug() << " channel: " << channel << "\n"; + log::debug() << " target: " << target << std::endl; + + m_irccd.broadcast(json::object({ + { "event", "onInvite" }, + { "server", server->info().name }, + { "origin", origin }, + { "channel", channel } + }).toJson(0)); + +#if defined(WITH_JS) + m_irccd.post(ServerEvent(server->info().name, origin, channel, + [=] (Plugin &) -> std::string { + return "onInvite"; + }, + [=] (Plugin &plugin) { + plugin.onInvite(std::move(server), std::move(origin), std::move(channel)); + } + )); +#endif +} + +void ServerService::handleJoin(std::weak_ptr<Server> ptr, std::string origin, std::string channel) +{ + std::shared_ptr<Server> server = ptr.lock(); + + if (!server) { + return; + } + + log::debug() << "server " << server->info().name << ": event onJoin:\n"; + log::debug() << " origin: " << origin << "\n"; + log::debug() << " channel: " << channel << std::endl; + + m_irccd.broadcast(json::object({ + { "event", "onJoin" }, + { "server", server->info().name }, + { "origin", origin }, + { "channel", channel } + }).toJson(0)); + +#if defined(WITH_JS) + m_irccd.post(ServerEvent(server->info().name, origin, channel, + [=] (Plugin &) -> std::string { + return "onJoin"; + }, + [=] (Plugin &plugin) { + plugin.onJoin(std::move(server), std::move(origin), std::move(channel)); + } + )); +#endif +} + +void ServerService::handleKick(std::weak_ptr<Server> ptr, std::string origin, std::string channel, std::string target, std::string reason) +{ + std::shared_ptr<Server> server = ptr.lock(); + + if (!server) { + return; + } + + log::debug() << "server " << server->info().name << ": event onKick:\n"; + log::debug() << " origin: " << origin << "\n"; + log::debug() << " channel: " << channel << "\n"; + log::debug() << " target: " << target << "\n"; + log::debug() << " reason: " << reason << std::endl; + + m_irccd.broadcast(json::object({ + { "event", "onKick" }, + { "server", server->info().name }, + { "origin", origin }, + { "channel", channel }, + { "target", target }, + { "reason", reason } + }).toJson(0)); + +#if defined(WITH_JS) + m_irccd.post(ServerEvent(server->info().name, origin, channel, + [=] (Plugin &) -> std::string { + return "onKick"; + }, + [=] (Plugin &plugin) { + plugin.onKick(std::move(server), std::move(origin), std::move(channel), std::move(target), std::move(reason)); + } + )); +#endif +} + +void ServerService::handleMessage(std::weak_ptr<Server> ptr, std::string origin, std::string channel, std::string message) +{ + std::shared_ptr<Server> server = ptr.lock(); + + if (!server) { + return; + } + + log::debug() << "server " << server->info().name << ": event onMessage:\n"; + log::debug() << " origin: " << origin << "\n"; + log::debug() << " channel: " << channel << "\n"; + log::debug() << " message: " << message << std::endl; + + m_irccd.broadcast(json::object({ + { "event", "onMessage" }, + { "server", server->info().name }, + { "origin", origin }, + { "channel", channel }, + { "message", message } + }).toJson(0)); + +#if defined(WITH_JS) + m_irccd.post(ServerEvent(server->info().name, origin, channel, + [=] (Plugin &plugin) -> std::string { + return util::parseMessage(message, server->settings().command, plugin.name()).second == util::MessageType::Command ? "onCommand" : "onMessage"; + }, + [=] (Plugin &plugin) { + util::MessagePair pack = util::parseMessage(message, server->settings().command, plugin.name()); + + if (pack.second == util::MessageType::Command) + plugin.onCommand(std::move(server), std::move(origin), std::move(channel), std::move(pack.first)); + else + plugin.onMessage(std::move(server), std::move(origin), std::move(channel), std::move(pack.first)); + } + )); +#endif +} + +void ServerService::handleMe(std::weak_ptr<Server> ptr, std::string origin, std::string target, std::string message) +{ + std::shared_ptr<Server> server = ptr.lock(); + + if (!server) { + return; + } + + log::debug() << "server " << server->info().name << ": event onMe:\n"; + log::debug() << " origin: " << origin << "\n"; + log::debug() << " target: " << target << "\n"; + log::debug() << " message: " << message << std::endl; + + m_irccd.broadcast(json::object({ + { "event", "onMe" }, + { "server", server->info().name }, + { "origin", origin }, + { "target", target }, + { "message", message } + }).toJson(0)); + +#if defined(WITH_JS) + m_irccd.post(ServerEvent(server->info().name, origin, target, + [=] (Plugin &) -> std::string { + return "onMe"; + }, + [=] (Plugin &plugin) { + plugin.onMe(std::move(server), std::move(origin), std::move(target), std::move(message)); + } + )); +#endif +} + +void ServerService::handleMode(std::weak_ptr<Server> ptr, std::string origin, std::string mode) +{ + std::shared_ptr<Server> server = ptr.lock(); + + if (!server) { + return; + } + + log::debug() << "server " << server->info().name << ": event onMode\n"; + log::debug() << " origin: " << origin << "\n"; + log::debug() << " mode: " << mode << std::endl; + + m_irccd.broadcast(json::object({ + { "event", "onMode" }, + { "server", server->info().name }, + { "origin", origin }, + { "mode", mode } + }).toJson(0)); + +#if defined(WITH_JS) + m_irccd.post(ServerEvent(server->info().name, origin, /* channel */ "", + [=] (Plugin &) -> std::string { + return "onMode"; + }, + [=] (Plugin &plugin) { + plugin.onMode(std::move(server), std::move(origin), std::move(mode)); + } + )); +#endif +} + +void ServerService::handleNames(std::weak_ptr<Server> ptr, std::string channel, std::set<std::string> nicknames) +{ + std::shared_ptr<Server> server = ptr.lock(); + + if (!server) { + return; + } + + log::debug() << "server " << server->info().name << ": event onNames:\n"; + log::debug() << " channel: " << channel << "\n"; + log::debug() << " names: " << util::join(nicknames.begin(), nicknames.end(), ", ") << std::endl; + + json::Value names(std::vector<json::Value>(nicknames.begin(), nicknames.end())); + + m_irccd.broadcast(json::object({ + { "event", "onNames" }, + { "server", server->info().name }, + { "channel", channel }, + { "names", std::move(names) } + }).toJson(0)); + +#if defined(WITH_JS) + m_irccd.post(ServerEvent(server->info().name, /* origin */ "", channel, + [=] (Plugin &) -> std::string { + return "onNames"; + }, + [=] (Plugin &plugin) { + plugin.onNames(std::move(server), std::move(channel), std::vector<std::string>(nicknames.begin(), nicknames.end())); + } + )); +#endif +} + +void ServerService::handleNick(std::weak_ptr<Server> ptr, std::string origin, std::string nickname) +{ + std::shared_ptr<Server> server = ptr.lock(); + + if (!server) { + return; + } + + log::debug() << "server " << server->info().name << ": event onNick:\n"; + log::debug() << " origin: " << origin << "\n"; + log::debug() << " nickname: " << nickname << std::endl; + + m_irccd.broadcast(json::object({ + { "event", "onNick" }, + { "server", server->info().name }, + { "origin", origin }, + { "nickname", nickname } + }).toJson(0)); + +#if defined(WITH_JS) + m_irccd.post(ServerEvent(server->info().name, origin, /* channel */ "", + [=] (Plugin &) -> std::string { + return "onNick"; + }, + [=] (Plugin &plugin) { + plugin.onNick(std::move(server), std::move(origin), std::move(nickname)); + } + )); +#endif +} + +void ServerService::handleNotice(std::weak_ptr<Server> ptr, std::string origin, std::string message) +{ + std::shared_ptr<Server> server = ptr.lock(); + + if (!server) { + return; + } + + log::debug() << "server " << server->info().name << ": event onNotice:\n"; + log::debug() << " origin: " << origin << "\n"; + log::debug() << " message: " << message << std::endl; + + m_irccd.broadcast(json::object({ + { "event", "onNotice" }, + { "server", server->info().name }, + { "origin", origin }, + { "message", message } + }).toJson(0)); + +#if defined(WITH_JS) + m_irccd.post(ServerEvent(server->info().name, origin, /* channel */ "", + [=] (Plugin &) -> std::string { + return "onNotice"; + }, + [=] (Plugin &plugin) { + plugin.onNotice(std::move(server), std::move(origin), std::move(message)); + } + )); +#endif +} + +void ServerService::handlePart(std::weak_ptr<Server> ptr, std::string origin, std::string channel, std::string reason) +{ + std::shared_ptr<Server> server = ptr.lock(); + + if (!server) { + return; + } + + log::debug() << "server " << server->info().name << ": event onPart:\n"; + log::debug() << " origin: " << origin << "\n"; + log::debug() << " channel: " << channel << "\n"; + log::debug() << " reason: " << reason << std::endl; + + m_irccd.broadcast(json::object({ + { "event", "onPart" }, + { "server", server->info().name }, + { "origin", origin }, + { "channel", channel }, + { "reason", reason } + }).toJson(0)); + +#if defined(WITH_JS) + m_irccd.post(ServerEvent(server->info().name, origin, channel, + [=] (Plugin &) -> std::string { + return "onPart"; + }, + [=] (Plugin &plugin) { + plugin.onPart(std::move(server), std::move(origin), std::move(channel), std::move(reason)); + } + )); +#endif +} + +void ServerService::handleQuery(std::weak_ptr<Server> ptr, std::string origin, std::string message) +{ + std::shared_ptr<Server> server = ptr.lock(); + + if (!server) { + return; + } + + log::debug() << "server " << server->info().name << ": event onQuery:\n"; + log::debug() << " origin: " << origin << "\n"; + log::debug() << " message: " << message << std::endl; + + m_irccd.broadcast(json::object({ + { "event", "onQuery" }, + { "server", server->info().name }, + { "origin", origin }, + { "message", message } + }).toJson(0)); + +#if defined(WITH_JS) + m_irccd.post(ServerEvent(server->info().name, origin, /* channel */ "", + [=] (Plugin &plugin) -> std::string { + return util::parseMessage(message, server->settings().command, plugin.name()).second == util::MessageType::Command ? "onQueryCommand" : "onQuery"; + }, + [=] (Plugin &plugin) { + util::MessagePair pack = util::parseMessage(message, server->settings().command, plugin.name()); + + if (pack.second == util::MessageType::Command) + plugin.onQueryCommand(std::move(server), std::move(origin), std::move(pack.first)); + else + plugin.onQuery(std::move(server), std::move(origin), std::move(pack.first)); + } + )); +#endif +} + +void ServerService::handleTopic(std::weak_ptr<Server> ptr, std::string origin, std::string channel, std::string topic) +{ + std::shared_ptr<Server> server = ptr.lock(); + + if (!server) { + return; + } + + log::debug() << "server " << server->info().name << ": event onTopic:\n"; + log::debug() << " origin: " << origin << "\n"; + log::debug() << " channel: " << channel << "\n"; + log::debug() << " topic: " << topic << std::endl; + + m_irccd.broadcast(json::object({ + { "event", "onTopic" }, + { "server", server->info().name }, + { "origin", origin }, + { "channel", channel }, + { "topic", topic } + }).toJson(0)); + +#if defined(WITH_JS) + m_irccd.post(ServerEvent(server->info().name, origin, channel, + [=] (Plugin &) -> std::string { + return "onTopic"; + }, + [=] (Plugin &plugin) { + plugin.onTopic(std::move(server), std::move(origin), std::move(channel), std::move(topic)); + } + )); +#endif +} + +void ServerService::handleWhois(std::weak_ptr<Server> ptr, ServerWhois whois) +{ + std::shared_ptr<Server> server = ptr.lock(); + + if (!server) { + return; + } + + log::debug() << "server " << server->info().name << ": event onWhois\n"; + log::debug() << " nickname: " << whois.nick << "\n"; + log::debug() << " username: " << whois.user << "\n"; + log::debug() << " host: " << whois.host << "\n"; + log::debug() << " realname: " << whois.realname << "\n"; + log::debug() << " channels: " << util::join(whois.channels.begin(), whois.channels.end()) << std::endl; + + m_irccd.broadcast(json::object({ + { "server", server->info().name }, + { "nickname", whois.nick }, + { "username", whois.user }, + { "host", whois.host }, + { "realname", whois.realname } + }).toJson(0)); + +#if defined(WITH_JS) + m_irccd.post(ServerEvent(server->info().name, /* origin */ "", /* channel */ "", + [=] (Plugin &) -> std::string { + return "onWhois"; + }, + [=] (Plugin &plugin) { + plugin.onWhois(std::move(server), std::move(whois)); + } + )); +#endif +} + +ServerService::ServerService(Irccd &irccd) + : m_irccd(irccd) +{ +} + +void ServerService::prepare(fd_set &in, fd_set &out, net::Handle &max) +{ + for (auto &server : m_servers) { + server->update(); + server->prepare(in, out, max); + } +} + +void ServerService::sync(fd_set &in, fd_set &out) +{ + for (auto &server : m_servers) { + server->sync(in, out); + } +} + +bool ServerService::hasServer(const std::string &name) const noexcept +{ + return std::count_if(m_servers.cbegin(), m_servers.end(), [&] (const auto &sv) { + return sv->info().name == name; + }) > 0; +} + +void ServerService::addServer(std::shared_ptr<Server> server) noexcept +{ + assert(!hasServer(server->info().name)); + + using namespace std::placeholders; + + std::weak_ptr<Server> ptr(server); + + server->onChannelMode.connect(std::bind(&ServerService::handleChannelMode, this, ptr, _1, _2, _3, _4)); + server->onChannelNotice.connect(std::bind(&ServerService::handleChannelNotice, this, ptr, _1, _2, _3)); + server->onConnect.connect(std::bind(&ServerService::handleConnect, this, ptr)); + server->onInvite.connect(std::bind(&ServerService::handleInvite, this, ptr, _1, _2, _3)); + server->onJoin.connect(std::bind(&ServerService::handleJoin, this, ptr, _1, _2)); + server->onKick.connect(std::bind(&ServerService::handleKick, this, ptr, _1, _2, _3, _4)); + server->onMessage.connect(std::bind(&ServerService::handleMessage, this, ptr, _1, _2, _3)); + server->onMe.connect(std::bind(&ServerService::handleMe, this, ptr, _1, _2, _3)); + server->onMode.connect(std::bind(&ServerService::handleMode, this, ptr, _1, _2)); + server->onNames.connect(std::bind(&ServerService::handleNames, this, ptr, _1, _2)); + server->onNick.connect(std::bind(&ServerService::handleNick, this, ptr, _1, _2)); + server->onNotice.connect(std::bind(&ServerService::handleNotice, this, ptr, _1, _2)); + server->onPart.connect(std::bind(&ServerService::handlePart, this, ptr, _1, _2, _3)); + server->onQuery.connect(std::bind(&ServerService::handleQuery, this, ptr, _1, _2)); + server->onTopic.connect(std::bind(&ServerService::handleTopic, this, ptr, _1, _2, _3)); + server->onWhois.connect(std::bind(&ServerService::handleWhois, this, ptr, _1)); + server->onDie.connect([this, ptr] () { + m_irccd.post([=] (Irccd &) { + auto server = ptr.lock(); + + if (server) { + log::info("server {}: removed"_format(server->info().name)); + m_servers.erase(std::find(m_servers.begin(), m_servers.end(), server)); + } + }); + }); + + m_servers.push_back(std::move(server)); +} + +std::shared_ptr<Server> ServerService::getServer(const std::string &name) const noexcept +{ + auto it = std::find_if(m_servers.begin(), m_servers.end(), [&] (const auto &server) { + return server->info().name == name; + }); + + if (it == m_servers.end()) { + return nullptr; + } + + return *it; +} + +std::shared_ptr<Server> ServerService::requireServer(const std::string &name) const +{ + auto server = getServer(name); + + if (!server) { + throw std::invalid_argument("server {} not found"_format(name)); + } + + return server; +} + +void ServerService::removeServer(const std::string &name) +{ + auto it = std::find_if(m_servers.begin(), m_servers.end(), [&] (const auto &server) { + return server->info().name == name; + }); + + if (it != m_servers.end()) { + (*it)->disconnect(); + m_servers.erase(it); + } +} + +void ServerService::clearServers() noexcept +{ + for (auto &server : m_servers) { + server->disconnect(); + } + + m_servers.clear(); +} + +} // !irccd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/irccd/service-server.hpp Tue May 10 22:51:10 2016 +0200 @@ -0,0 +1,142 @@ +/* + * service-server.hpp -- manage IRC servers + * + * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef IRCCD_SERVICE_SERVER_HPP +#define IRCCD_SERVICE_SERVER_HPP + +/** + * \file service-server.hpp + * \brief Manage IRC servers. + */ + +#include <memory> +#include <set> +#include <string> + +#include "service.hpp" + +namespace irccd { + +class Irccd; +class Server; +class ServerWhois; + +/** + * \brief Manage IRC servers. + */ +class ServerService : public Service { +private: + Irccd &m_irccd; + std::vector<std::shared_ptr<Server>> m_servers; + + void handleChannelMode(std::weak_ptr<Server>, std::string, std::string, std::string, std::string); + void handleChannelNotice(std::weak_ptr<Server>, std::string, std::string, std::string); + void handleConnect(std::weak_ptr<Server>); + void handleInvite(std::weak_ptr<Server>, std::string, std::string, std::string); + void handleJoin(std::weak_ptr<Server>, std::string, std::string); + void handleKick(std::weak_ptr<Server>, std::string, std::string, std::string, std::string); + void handleMessage(std::weak_ptr<Server>, std::string, std::string, std::string); + void handleMe(std::weak_ptr<Server>, std::string, std::string, std::string); + void handleMode(std::weak_ptr<Server>, std::string, std::string); + void handleNames(std::weak_ptr<Server>, std::string, std::set<std::string>); + void handleNick(std::weak_ptr<Server>, std::string, std::string); + void handleNotice(std::weak_ptr<Server>, std::string, std::string); + void handlePart(std::weak_ptr<Server>, std::string, std::string, std::string); + void handleQuery(std::weak_ptr<Server>, std::string, std::string); + void handleTopic(std::weak_ptr<Server>, std::string, std::string, std::string); + void handleWhois(std::weak_ptr<Server>, ServerWhois); + +public: + /** + * Create the server service. + */ + ServerService(Irccd &instance); + + /** + * \copydoc Service::prepare + */ + void prepare(fd_set &in, fd_set &out, net::Handle &max) override; + + /** + * \copydoc Service::sync + */ + void sync(fd_set &in, fd_set &out) override; + + /** + * Check if a server exists. + * + * \param name the name + * \return true if exists + */ + bool hasServer(const std::string &name) const noexcept; + + /** + * Add a new server to the application. + * + * \pre hasServer must return false + * \param sv the server + */ + void addServer(std::shared_ptr<Server> sv) noexcept; + + /** + * Get a server or empty one if not found + * + * \param name the server name + * \return the server or empty one if not found + */ + std::shared_ptr<Server> getServer(const std::string &name) const noexcept; + + /** + * Find a server by name. + * + * \param name the server name + * \return the server + * \throw std::out_of_range if the server does not exist + */ + std::shared_ptr<Server> requireServer(const std::string &name) const; + + /** + * Get the list of servers + * + * \return the servers + */ + inline const std::vector<std::shared_ptr<Server>> &servers() const noexcept + { + return m_servers; + } + + /** + * Remove a server from the irccd instance. + * + * The server if any, will be disconnected. + * + * \param name the server name + */ + void removeServer(const std::string &name); + + /** + * Remove all servers. + * + * All servers will be disconnected. + */ + void clearServers() noexcept; +}; + +} // !irccd + +#endif // !IRCCD_SERVICE_SERVER_HPP