0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-06-02 10:08:56 +02:00

Replace command system.

This commit is contained in:
Jason Volk 2016-09-05 16:05:16 -07:00
parent 46d992d3a0
commit 9275429ee1
11 changed files with 360 additions and 181 deletions

View file

@ -188,6 +188,7 @@ const char *const interruption_message
void
handle_interruption()
try
{
static bool seen_the_message;
if(!seen_the_message)
@ -206,12 +207,16 @@ handle_interruption()
return;
}
if(line.empty())
return;
if(line == "ABORT")
abort();
if(line == "EXIT")
exit(0);
line += "\r\n";
ircd::execute(ircd::me, line);
}
catch(const std::exception &e)
{
std::cerr << "\033[1;31merror\033[0m: " << e.what() << std::endl;
}

View file

@ -145,10 +145,10 @@ struct client
time_t large_ctcp_sent; /* ctcp to large group sent, relax flood checks */
char *certfp; /* client certificate fingerprint */
client();
client() {}
client(const client &) = delete;
client &operator=(const client &) = delete;
~client() noexcept;
~client() noexcept {}
};
struct ZipStats
@ -517,42 +517,42 @@ inline void
set_reject(client &client)
{
client.status = status::REJECT;
client.handler = UNREGISTERED_HANDLER;
//client.handler = UNREGISTERED_HANDLER;
}
inline void
set_connecting(client &client)
{
client.status = status::CONNECTING;
client.handler = UNREGISTERED_HANDLER;
//client.handler = UNREGISTERED_HANDLER;
}
inline void
set_handshake(client &client)
{
client.status = status::HANDSHAKE;
client.handler = UNREGISTERED_HANDLER;
//client.handler = UNREGISTERED_HANDLER;
}
inline void
set_me(client &client)
{
client.status = status::ME;
client.handler = UNREGISTERED_HANDLER;
//client.handler = UNREGISTERED_HANDLER;
}
inline void
set_unknown(client &client)
{
client.status = status::UNKNOWN;
client.handler = UNREGISTERED_HANDLER;
//client.handler = UNREGISTERED_HANDLER;
}
inline void
set_server(client &client)
{
client.status = status::SERVER;
client.handler = SERVER_HANDLER;
//client.handler = SERVER_HANDLER;
}
bool is_oper(const client &);
@ -561,14 +561,14 @@ inline void
set_client(client &client)
{
client.status = status::CLIENT;
client.handler = is_oper(client)? OPER_HANDLER : CLIENT_HANDLER;
//client.handler = is_oper(client)? OPER_HANDLER : CLIENT_HANDLER;
}
inline void
set_remote_client(client &client)
{
client.status = status::CLIENT;
client.handler = RCLIENT_HANDLER;
//client.handler = RCLIENT_HANDLER;
}
inline bool
@ -690,8 +690,8 @@ inline void
set_oper(client &client)
{
set(client, mode::OPER);
if (my(client))
client.handler = OPER_HANDLER;
// if (my(client))
// client.handler = OPER_HANDLER;
}
inline void
@ -699,8 +699,8 @@ clear_oper(client &client)
{
clear(client, mode::OPER);
clear(client, mode::ADMIN);
if (my(client) && !is_server(client))
client.handler = CLIENT_HANDLER;
// if (my(client) && !is_server(client))
// client.handler = CLIENT_HANDLER;
}
inline void

114
include/ircd/cmd.h Normal file
View file

@ -0,0 +1,114 @@
/*
* Copyright (C) 2016 Charybdis Development Team
* Copyright (C) 2016 Jason Volk <jason@zemos.net>
*
* 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 is present in all copies.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#define HAVE_IRCD_CMD_H
#ifdef __cplusplus
namespace ircd {
struct line
:rfc1459::line
{
using rfc1459::line::line;
auto &operator[](const size_t &pos) const;
auto &operator[](const size_t &pos);
};
inline auto &pfx(const line &line) { return line.pfx; }
inline auto &pfx(line &line) { return line.pfx; }
inline auto &nick(const line &line) { return pfx(line).nick; }
inline auto &nick(line &line) { return pfx(line).nick; }
inline auto &user(const line &line) { return pfx(line).user; }
inline auto &user(line &line) { return pfx(line).user; }
inline auto &host(const line &line) { return pfx(line).host; }
inline auto &host(line &line) { return pfx(line).host; }
inline auto &command(const line &line) { return line.cmd; }
inline auto &command(line &line) { return line.cmd; }
inline auto &parv(const line &line) { return line.parv; }
inline auto &parv(line &line) { return line.parv; }
inline auto parc(const line &line) { return parv(line).size(); }
inline auto &
line::operator[](const size_t &pos)
{
return parv.at(pos);
}
inline auto &
line::operator[](const size_t &pos)
const
{
return parv.at(pos);
}
} // namespace ircd
#endif
#ifdef __cplusplus
namespace ircd {
namespace cmds {
using client::client;
IRCD_EXCEPTION(ircd::error, error)
IRCD_EXCEPTION(error, not_found) // Really should be throwing err::421 directly but..
IRCD_EXCEPTION(error, already_exists)
struct cmd
{
std::string name;
std::set<std::string> aliases;
std::function<void (client &, line)> handler; // Used if not overloaded
private:
void emplace();
public:
virtual void operator()(client &, line);
cmd(const std::string &name);
cmd(const std::string &name, const decltype(handler) &handler);
cmd(cmd &&) = delete;
cmd(const cmd &) = delete;
virtual ~cmd() noexcept;
};
// cmd structs are managed by their module (or wherever the instance resides)
extern std::map<std::string, cmd *, case_insensitive_less> cmds;
bool exists(const std::string &name);
cmd *find(const std::string &name, const std::nothrow_t &);
cmd &find(const std::string &name);
void execute(client &client, line);
void execute(client &client, const std::string &line);
void execute(client &client, const uint8_t *const &line, const size_t &len);
} // namespace cmds
using cmds::execute;
using cmds::cmd;
} // namespace ircd
#endif

View file

@ -31,20 +31,40 @@
#include "stdinc.h"
#endif
#ifdef __cplusplus
// TODO: move
// Allow a reference to an ios to be passed to ircd
#ifdef __cplusplus
namespace boost {
namespace asio {
struct io_service;
}
}
} // namespace asio
} // namespace boost
#endif // __cplusplus
#ifdef __cplusplus
namespace ircd {
extern bool debugmode;
extern boost::asio::io_service *ios;
extern client::client me;
void init(boost::asio::io_service &ios, const std::string &newconf_path);
} // namespace ircd
#endif // __cplusplus
#ifdef __cplusplus
namespace ircd {
struct SetOptions
{
@ -81,7 +101,6 @@ extern bool server_state_foreground;
extern bool opers_see_all_users; /* sno_farconnect.so loaded, operspy without
accountability, etc */
extern client::client me;
extern rb_dlink_list global_client_list;
extern client::client *local[];
extern struct Counter Count;
@ -113,7 +132,5 @@ void restart(const char *) __attribute__((noreturn));
void ircd_shutdown() __attribute__((noreturn));
void server_reboot(void) __attribute__((noreturn));
void init(boost::asio::io_service &ios, const std::string &newconf_path);
} // namespace ircd
#endif // __cplusplus

View file

@ -1,144 +0,0 @@
/*
* ircd-ratbox: A slightly useful ircd.
* msg.h: A header for the message handler structure.
*
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
* Copyright (C) 1996-2002 Hybrid Development Team
* Copyright (C) 2002-2004 ircd-ratbox development team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#pragma once
#define HAVE_IRCD_MSG_H
#ifdef __cplusplus
namespace ircd {
/* MessageHandler */
typedef enum HandlerType
{
UNREGISTERED_HANDLER,
CLIENT_HANDLER,
RCLIENT_HANDLER,
SERVER_HANDLER,
ENCAP_HANDLER,
OPER_HANDLER,
LAST_HANDLER_TYPE
}
HandlerType;
/* struct MsgBuf* msgbuf_p - message buffer (including tags)
* client::client* client_p - connection message originated from
* client::client* source_p - source of message, may be different from client_p
* int parc - parameter count (from msgbuf_p)
* char* parv[] - parameter vector (from msgbuf_p)
*/
using MessageHandler = std::function<void (struct MsgBuf *, client::client &, client::client &, int, const char *[])>;
struct MessageEntry
{
MessageHandler handler;
size_t min_para;
};
/* Message table structure */
struct Message
{
const char *cmd;
unsigned int count; /* number of times command used */
unsigned int rcount; /* number of times command used by server */
unsigned long bytes; /* bytes received for this message */
unsigned int flags;
/* handlers:
* UNREGISTERED, CLIENT, RCLIENT, SERVER, OPER, LAST
*/
struct MessageEntry handlers[LAST_HANDLER_TYPE];
};
/* generic handlers */
extern void m_ignore(struct MsgBuf *, client::client &, client::client &, int, const char **);
extern void m_not_oper(struct MsgBuf *, client::client &, client::client &, int, const char **);
extern void m_registered(struct MsgBuf *, client::client &, client::client &, int, const char **);
extern void m_unregistered(struct MsgBuf *, client::client &, client::client &, int, const char **);
#define mg_ignore { m_ignore, 0 }
#define mg_not_oper { m_not_oper, 0 }
#define mg_reg { m_registered, 0 }
#define mg_unreg { m_unregistered, 0 }
/*
* m_functions execute protocol messages on this server:
* void m_func(struct MsgBuf *, client::client* client_p, client::client* source_p, int parc, char* parv[]);
*
* client_p is always NON-NULL, pointing to a *LOCAL* client
* structure (with an open socket connected!). This
* identifies the physical socket where the message
* originated (or which caused the m_function to be
* executed--some m_functions may call others...).
*
* source_p is the source of the message, defined by the
* prefix part of the message if present. If not
* or prefix not found, then source_p==client_p.
*
* (!is_server(*client_p)) => (client_p == source_p), because
* prefixes are taken *only* from servers...
*
* (is_server(*client_p))
* (source_p == client_p) => the message didn't
* have the prefix.
*
* (source_p != client_p && is_server(*source_p) means
* the prefix specified servername. (?)
*
* (source_p != client_p && !is_server(*source_p) means
* that message originated from a remote
* user (not local).
*
*
* combining
*
* (!is_server(*source_p)) means that, source_p can safely
* taken as defining the target structure of the
* message in this server.
*
* *Always* true (if 'parse' and others are working correct):
*
* 1) source_p->from == client_p (note: client_p->from == client_p)
*
* 2) MyConnect(source_p) <=> source_p == client_p (e.g. source_p
* *cannot* be a local connection, unless it's
* actually client_p!). [MyConnect(x) should probably
* be defined as (x == x->from) --msa ]
*
* parc number of variable parameter strings (if zero,
* parv is allowed to be NULL)
*
* parv a NULL terminated list of parameter pointers,
*
* parv[0], unused for historical reasons (formerly
* sender name)
* parv[1]...parv[parc-1]
* pointers to additional parameters
* parv[parc] == NULL, *always*
*
* note: it is guaranteed that parv[1]..parv[parc-1] are all
* non-NULL pointers.
*/
} // namespace ircd
#endif // __cplusplus

View file

@ -82,7 +82,7 @@ namespace ircd
#include "whowas.h"
#include "tgchange.h"
#include "msgbuf.h"
#include "msg.h"
#include "cmd.h"
#include "client.h"
#include "mask.h"
@ -108,7 +108,6 @@ namespace ircd
#include "monitor.h"
#include "operhash.h"
#include "packet.h"
#include "parse.h"
#include "privilege.h"
#include "ratelimit.h"
#include "reject.h"

View file

@ -40,7 +40,8 @@ libircd_la_SOURCES = \
newconf.cc \
modules.cc \
snomask.cc \
info.cc
info.cc \
cmd.cc
#authproc.cc \
#bandbi.cc \

186
ircd/cmd.cc Normal file
View file

@ -0,0 +1,186 @@
/*
* Copyright (C) 2016 Charybdis Development Team
* Copyright (C) 2016 Jason Volk <jason@zemos.net>
*
* 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 is present in all copies.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
namespace ircd {
namespace cmds {
std::map<std::string, cmd *, case_insensitive_less> cmds;
} // namespace cmds
} // namespace ircd
ircd::cmds::cmd::cmd(const std::string &name)
:name{name}
{
emplace();
}
ircd::cmds::cmd::cmd(const std::string &name,
const decltype(handler) &handler)
:name{name}
,handler{handler}
{
emplace();
}
ircd::cmds::cmd::~cmd()
noexcept
{
cmds.erase(name);
log::info("Removed command \"%s\" by handler @ %p", name.c_str(), this);
}
void
ircd::cmds::cmd::operator()(client &client,
line line)
{
handler(client, std::move(line));
}
void
ircd::cmds::cmd::emplace()
{
const auto iit(cmds.emplace(name, this));
if(!iit.second)
throw already_exists("Command name \"%s\" already registered", name.c_str());
log::info("Registered command \"%s\" to handler @ %p", name.c_str(), this);
}
void
ircd::cmds::execute(client &client,
const uint8_t *const &ptr,
const size_t &len)
{
execute(client, line(ptr, len));
}
void
ircd::cmds::execute(client &client,
const std::string &l)
{
execute(client, line(l));
}
void
ircd::cmds::execute(client &client,
line line)
{
auto &handle(find(command(line)));
handle(client, std::move(line));
}
ircd::cmds::cmd &
ircd::cmds::find(const std::string &name)
try
{
return *cmds.at(name);
}
catch(const std::out_of_range &e)
{
throw not_found("%s", name.c_str());
}
ircd::cmds::cmd *
ircd::cmds::find(const std::string &name,
const std::nothrow_t &)
{
const auto it(cmds.find(name));
return it != end(cmds)? it->second : nullptr;
}
bool
ircd::cmds::exists(const std::string &name)
{
return cmds.count(name);
}
//
// Museum of historical comments
//
// parse.c (1990 - 2016)
//
/* ok, fake prefix happens naturally during a burst on a nick
* collision with TS5, we cant kill them because one client has to
* survive, so we just send an error.
*/
/* meepfoo is a nickname (ignore)
* #XXXXXXXX is a UID (KILL)
* #XX is a SID (SQUIT)
* meep.foo is a server (SQUIT)
*/
/*
* *WARNING*
* Numerics are mostly error reports. If there is something
* wrong with the message, just *DROP* it! Don't even think of
* sending back a neat error message -- big danger of creating
* a ping pong error message...
*/
/*
* Prepare the parameter portion of the message into 'buffer'.
* (Because the buffer is twice as large as the message buffer
* for the socket, no overflow can occur here... ...on current
* assumptions--bets are off, if these are changed --msa)
* Note: if buffer is non-empty, it will begin with SPACE.
*/
/*
* We shouldn't get numerics sent to us,
* any numerics we do get indicate a bug somewhere..
*/
/* ugh. this is here because of nick collisions. when two servers
* relink, they burst each other their nicks, then perform collides.
* if there is a nick collision, BOTH servers will kill their own
* nicks, and BOTH will kill the other servers nick, which wont exist,
* because it will have been already killed by the local server.
*
* unfortunately, as we cant guarantee other servers will do the
* "right thing" on a nick collision, we have to keep both kills.
* ergo we need to ignore ERR_NOSUCHNICK. --fl_
*/
/* quick comment. This _was_ tried. i.e. assume the other servers
* will do the "right thing" and kill a nick that is colliding.
* unfortunately, it did not work. --Dianora
*/
/* note, now we send PING on server connect, we can
* also get ERR_NOSUCHSERVER..
*/
/* This message changed direction (nick collision?)
* ignore it.
*/
/* csircd will send out unknown umode flag for +a (admin), drop it here. */
/* Fake it for server hiding, if its our client */
/* bit of a hack.
* I don't =really= want to waste a bit in a flag
* number_of_nick_changes is only really valid after the client
* is fully registered..
*/

View file

@ -36,8 +36,8 @@ struct ServerStatistics ServerStats;
struct ev_entry *check_splitmode_ev;
int maxconnections;
//client::client me; /* That's me */
struct LocalUser meLocalUser; /* That's also part of me */
client::client me; // That's me
struct LocalUser meLocalUser; // That's also part of me
rb_dlink_list global_client_list;

View file

@ -342,7 +342,7 @@ client_dopacket(client::client *client_p, char *buffer, size_t length)
me.localClient->receiveB &= 0x03ff;
}
parse(client_p, buffer, buffer + length);
//parse(client_p, buffer, buffer + length);
}

View file

@ -42,6 +42,7 @@ static void do_modreload(client::client &, const std::string &);
static void do_modlist(client::client &, const std::string &);
static void do_modrestart(client::client &);
/*
struct Message modload_msgtab = {
"MODLOAD", 0, 0, 0, 0,
{mg_unreg, mg_not_oper, mg_ignore, mg_ignore, {me_modload, 2}, {mo_modload, 2}}
@ -66,17 +67,17 @@ struct Message modrestart_msgtab = {
"MODRESTART", 0, 0, 0, 0,
{mg_unreg, mg_not_oper, mg_ignore, mg_ignore, {me_modrestart, 0}, {mo_modrestart, 0}}
};
*/
mapi::header IRCD_MODULE
{
"Provides module management commands",
mapi::NO_FLAGS,
&modload_msgtab,
&modunload_msgtab,
&modreload_msgtab,
&modlist_msgtab,
&modrestart_msgtab,
mapi::NO_FLAGS
//&modload_msgtab,
//&modunload_msgtab,
//&modreload_msgtab,
//&modlist_msgtab,
//&modrestart_msgtab,
};
// load a module ..