diff options
author | attilamolnar <attilamolnar@hush.com> | 2013-07-15 13:40:22 +0200 |
---|---|---|
committer | attilamolnar <attilamolnar@hush.com> | 2013-08-18 15:11:02 +0200 |
commit | b14ebbccf08ec34a73e1ba271e67da80d9fe805c (patch) | |
tree | 012640699b3960940af3756ef1e881747b0aa8d1 /src | |
parent | 153179b574dccd6df9c5c5f3e68f3c1725e26843 (diff) |
m_spanningtree Move all server-to-server command handlers into handler classes
These commands are not registered in or called by the core. When looking for the handler of a command a new command table is searched first which contains all server-to-server commands. If a handler cannot be found in there, the core command table is consulted.
Diffstat (limited to 'src')
34 files changed, 583 insertions, 501 deletions
diff --git a/src/modules/m_spanningtree/addline.cpp b/src/modules/m_spanningtree/addline.cpp index 2ef76a351..2ee8401fa 100644 --- a/src/modules/m_spanningtree/addline.cpp +++ b/src/modules/m_spanningtree/addline.cpp @@ -20,36 +20,19 @@ #include "inspircd.h" #include "xline.h" -#include "treesocket.h" #include "treeserver.h" #include "utils.h" +#include "commands.h" -bool TreeSocket::AddLine(const std::string &prefix, parameterlist ¶ms) +CmdResult CommandAddLine::Handle(User* usr, std::vector<std::string>& params) { - if (params.size() < 6) - { - const std::string& servername = MyRoot->GetName(); - ServerInstance->SNO->WriteToSnoMask('d', "%s sent me a malformed ADDLINE", servername.c_str()); - return true; - } - XLineFactory* xlf = ServerInstance->XLines->GetFactory(params[0]); - - std::string setter = "<unknown>"; - User* usr = ServerInstance->FindNick(prefix); - if (usr) - setter = usr->nick; - else - { - TreeServer* t = Utils->FindServer(prefix); - if (t) - setter = t->GetName(); - } + const std::string& setter = usr->nick; if (!xlf) { ServerInstance->SNO->WriteToSnoMask('d',"%s sent me an unknown ADDLINE type (%s).",setter.c_str(),params[0].c_str()); - return true; + return CMD_FAILURE; } XLine* xl = NULL; @@ -60,7 +43,7 @@ bool TreeSocket::AddLine(const std::string &prefix, parameterlist ¶ms) catch (ModuleException &e) { ServerInstance->SNO->WriteToSnoMask('d',"Unable to ADDLINE type %s from %s: %s", params[0].c_str(), setter.c_str(), e.GetReason()); - return true; + return CMD_FAILURE; } xl->SetCreateTime(ConvToInt(params[3])); if (ServerInstance->XLines->AddLine(xl, NULL)) @@ -76,20 +59,19 @@ bool TreeSocket::AddLine(const std::string &prefix, parameterlist ¶ms) ServerInstance->SNO->WriteToSnoMask('X',"%s added permanent %s%s on %s: %s",setter.c_str(),params[0].c_str(),params[0].length() == 1 ? "-line" : "", params[1].c_str(),params[5].c_str()); } - params[5] = ":" + params[5]; - User* u = ServerInstance->FindNick(prefix); - Utils->DoOneToAllButSender(prefix, "ADDLINE", params, u ? u->server : prefix); - TreeServer *remoteserver = Utils->FindServer(u ? u->server : prefix); + TreeServer* remoteserver = Utils->FindServer(usr->server); if (!remoteserver->bursting) { ServerInstance->XLines->ApplyLines(); } + return CMD_SUCCESS; } else + { delete xl; - - return true; + return CMD_FAILURE; + } } diff --git a/src/modules/m_spanningtree/away.cpp b/src/modules/m_spanningtree/away.cpp index ae60633bf..cf0c87ce4 100644 --- a/src/modules/m_spanningtree/away.cpp +++ b/src/modules/m_spanningtree/away.cpp @@ -21,13 +21,12 @@ #include "main.h" #include "utils.h" -#include "treesocket.h" +#include "commands.h" -bool TreeSocket::Away(const std::string &prefix, parameterlist ¶ms) +CmdResult CommandAway::Handle(User* u, std::vector<std::string>& params) { - User* u = ServerInstance->FindNick(prefix); - if ((!u) || (IS_SERVER(u))) - return true; + if (IS_SERVER(u)) + return CMD_INVALID; if (params.size()) { FOREACH_MOD(OnSetAway, (u, params[params.size() - 1])); @@ -38,14 +37,11 @@ bool TreeSocket::Away(const std::string &prefix, parameterlist ¶ms) u->awaytime = ServerInstance->Time(); u->awaymsg = params[params.size() - 1]; - - params[params.size() - 1] = ":" + params[params.size() - 1]; } else { FOREACH_MOD(OnSetAway, (u, "")); u->awaymsg.clear(); } - Utils->DoOneToAllButSender(prefix,"AWAY",params,u->server); - return true; + return CMD_SUCCESS; } diff --git a/src/modules/m_spanningtree/commands.h b/src/modules/m_spanningtree/commands.h index 44f26ae6c..a895c569b 100644 --- a/src/modules/m_spanningtree/commands.h +++ b/src/modules/m_spanningtree/commands.h @@ -39,50 +39,53 @@ class CommandRSQuit : public Command RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters); }; -class CommandSVSJoin : public Command +class CommandSVSJoin : public ServerCommand { public: - CommandSVSJoin(Module* Creator) : Command(Creator, "SVSJOIN", 2) { flags_needed = FLAG_SERVERONLY; } - CmdResult Handle (const std::vector<std::string>& parameters, User *user); + CommandSVSJoin(Module* Creator) : ServerCommand(Creator, "SVSJOIN", 2) { } + CmdResult Handle(User* user, std::vector<std::string>& params); RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters); }; -class CommandSVSPart : public Command + +class CommandSVSPart : public ServerCommand { public: - CommandSVSPart(Module* Creator) : Command(Creator, "SVSPART", 2) { flags_needed = FLAG_SERVERONLY; } - CmdResult Handle (const std::vector<std::string>& parameters, User *user); + CommandSVSPart(Module* Creator) : ServerCommand(Creator, "SVSPART", 2) { } + CmdResult Handle(User* user, std::vector<std::string>& params); RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters); }; -class CommandSVSNick : public Command + +class CommandSVSNick : public ServerCommand { public: - CommandSVSNick(Module* Creator) : Command(Creator, "SVSNICK", 3) { flags_needed = FLAG_SERVERONLY; } - CmdResult Handle (const std::vector<std::string>& parameters, User *user); + CommandSVSNick(Module* Creator) : ServerCommand(Creator, "SVSNICK", 3) { } + CmdResult Handle(User* user, std::vector<std::string>& params); RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters); }; -class CommandMetadata : public Command + +class CommandMetadata : public ServerCommand { public: - CommandMetadata(Module* Creator) : Command(Creator, "METADATA", 2) { flags_needed = FLAG_SERVERONLY; } - CmdResult Handle (const std::vector<std::string>& parameters, User *user); - RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters) { return ROUTE_BROADCAST; } + CommandMetadata(Module* Creator) : ServerCommand(Creator, "METADATA", 2) { } + CmdResult Handle(User* user, std::vector<std::string>& params); }; -class CommandUID : public Command + +class CommandUID : public ServerCommand { public: - CommandUID(Module* Creator) : Command(Creator, "UID", 10) { flags_needed = FLAG_SERVERONLY; } - CmdResult Handle (const std::vector<std::string>& parameters, User *user); - RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters) { return ROUTE_BROADCAST; } + CommandUID(Module* Creator) : ServerCommand(Creator, "UID", 10) { } + CmdResult Handle(User* user, std::vector<std::string>& params); }; -class CommandOpertype : public Command + +class CommandOpertype : public ServerCommand { public: - CommandOpertype(Module* Creator) : Command(Creator, "OPERTYPE", 1) { flags_needed = FLAG_SERVERONLY; } - CmdResult Handle (const std::vector<std::string>& parameters, User *user); - RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters) { return ROUTE_BROADCAST; } + CommandOpertype(Module* Creator) : ServerCommand(Creator, "OPERTYPE", 1) { } + CmdResult Handle(User* user, std::vector<std::string>& params); }; + class TreeSocket; -class CommandFJoin : public Command +class CommandFJoin : public ServerCommand { /** Remove all modes from a channel, including statusmodes (+qaovh etc), simplemodes, parameter modes. * This does not update the timestamp of the target channel, this must be done seperately. @@ -91,59 +94,174 @@ class CommandFJoin : public Command static void ApplyModeStack(User* srcuser, Channel* c, irc::modestacker& stack); bool ProcessModeUUIDPair(const std::string& item, TreeSocket* src_socket, Channel* chan, irc::modestacker* modestack); public: - CommandFJoin(Module* Creator) : Command(Creator, "FJOIN", 3) { flags_needed = FLAG_SERVERONLY; } - CmdResult Handle (const std::vector<std::string>& parameters, User *user); - RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters) { return ROUTE_BROADCAST; } + CommandFJoin(Module* Creator) : ServerCommand(Creator, "FJOIN", 3) { } + CmdResult Handle(User* user, std::vector<std::string>& params); +}; + +class CommandFMode : public ServerCommand +{ + public: + CommandFMode(Module* Creator) : ServerCommand(Creator, "FMODE", 3) { } + CmdResult Handle(User* user, std::vector<std::string>& params); +}; + +class CommandFTopic : public ServerCommand +{ + public: + CommandFTopic(Module* Creator) : ServerCommand(Creator, "FTOPIC", 5) { } + CmdResult Handle(User* user, std::vector<std::string>& params); +}; + +class CommandFHost : public ServerCommand +{ + public: + CommandFHost(Module* Creator) : ServerCommand(Creator, "FHOST", 1) { } + CmdResult Handle(User* user, std::vector<std::string>& params); +}; + +class CommandFIdent : public ServerCommand +{ + public: + CommandFIdent(Module* Creator) : ServerCommand(Creator, "FIDENT", 1) { } + CmdResult Handle(User* user, std::vector<std::string>& params); +}; + +class CommandFName : public ServerCommand +{ + public: + CommandFName(Module* Creator) : ServerCommand(Creator, "FNAME", 1) { } + CmdResult Handle(User* user, std::vector<std::string>& params); +}; + +class CommandIJoin : public ServerCommand +{ + public: + CommandIJoin(Module* Creator) : ServerCommand(Creator, "IJOIN", 1) { } + CmdResult Handle(User* user, std::vector<std::string>& params); +}; + +class CommandResync : public ServerCommand +{ + public: + CommandResync(Module* Creator) : ServerCommand(Creator, "RESYNC", 1) { } + CmdResult Handle(User* user, std::vector<std::string>& parameters); +}; + +class CommandAway : public ServerCommand +{ + public: + CommandAway(Module* Creator) : ServerCommand(Creator, "AWAY", 0, 2) { } + CmdResult Handle(User* user, std::vector<std::string>& parameters); }; -class CommandFMode : public Command + +class CommandAddLine : public ServerCommand +{ + public: + CommandAddLine(Module* Creator) : ServerCommand(Creator, "ADDLINE", 6, 6) { } + CmdResult Handle(User* user, std::vector<std::string>& parameters); +}; + +class CommandDelLine : public ServerCommand +{ + public: + CommandDelLine(Module* Creator) : ServerCommand(Creator, "DELLINE", 2, 2) { } + CmdResult Handle(User* user, std::vector<std::string>& parameters); +}; + +class CommandEncap : public ServerCommand +{ + public: + CommandEncap(Module* Creator) : ServerCommand(Creator, "ENCAP", 2) { } + CmdResult Handle(User* user, std::vector<std::string>& parameters); + RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters); +}; + +class CommandIdle : public ServerCommand +{ + public: + CommandIdle(Module* Creator) : ServerCommand(Creator, "IDLE", 1) { } + CmdResult Handle(User* user, std::vector<std::string>& parameters); + RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters) { return ROUTE_UNICAST(parameters[0]); } +}; + +class CommandNick : public ServerCommand +{ + public: + CommandNick(Module* Creator) : ServerCommand(Creator, "NICK", 2) { } + CmdResult Handle(User* user, std::vector<std::string>& parameters); +}; + +class CommandPing : public ServerCommand +{ + public: + CommandPing(Module* Creator) : ServerCommand(Creator, "PING", 1) { } + CmdResult Handle(User* user, std::vector<std::string>& parameters); + RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters) { return ROUTE_UNICAST(parameters[0]); } +}; + +class CommandPong : public ServerCommand { public: - CommandFMode(Module* Creator) : Command(Creator, "FMODE", 3) { flags_needed = FLAG_SERVERONLY; } - CmdResult Handle (const std::vector<std::string>& parameters, User *user); - RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters) { return ROUTE_BROADCAST; } + CommandPong(Module* Creator) : ServerCommand(Creator, "PONG", 1) { } + CmdResult Handle(User* user, std::vector<std::string>& parameters); + RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters) { return ROUTE_UNICAST(parameters[0]); } }; -class CommandFTopic : public Command + +class CommandPush : public ServerCommand { public: - CommandFTopic(Module* Creator) : Command(Creator, "FTOPIC", 5) { flags_needed = FLAG_SERVERONLY; } - CmdResult Handle (const std::vector<std::string>& parameters, User *user); - RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters) { return ROUTE_BROADCAST; } + CommandPush(Module* Creator) : ServerCommand(Creator, "PUSH", 2) { } + CmdResult Handle(User* user, std::vector<std::string>& parameters); + RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters) { return ROUTE_UNICAST(parameters[0]); } }; -class CommandFHost : public Command + +class CommandSave : public ServerCommand { public: - CommandFHost(Module* Creator) : Command(Creator, "FHOST", 1) { flags_needed = FLAG_SERVERONLY; } - CmdResult Handle (const std::vector<std::string>& parameters, User *user); - RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters) { return ROUTE_BROADCAST; } + CommandSave(Module* Creator) : ServerCommand(Creator, "SAVE", 2) { } + CmdResult Handle(User* user, std::vector<std::string>& parameters); }; -class CommandFIdent : public Command + +class CommandServer : public ServerCommand { public: - CommandFIdent(Module* Creator) : Command(Creator, "FIDENT", 1) { flags_needed = FLAG_SERVERONLY; } - CmdResult Handle (const std::vector<std::string>& parameters, User *user); - RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters) { return ROUTE_BROADCAST; } + CommandServer(Module* Creator) : ServerCommand(Creator, "SERVER", 5) { } + CmdResult Handle(User* user, std::vector<std::string>& parameters); }; -class CommandFName : public Command + +class CommandSQuit : public ServerCommand +{ + public: + CommandSQuit(Module* Creator) : ServerCommand(Creator, "SQUIT", 2) { } + CmdResult Handle(User* user, std::vector<std::string>& parameters); +}; + +class CommandSNONotice : public ServerCommand +{ + public: + CommandSNONotice(Module* Creator) : ServerCommand(Creator, "SNONOTICE", 2) { } + CmdResult Handle(User* user, std::vector<std::string>& parameters); +}; + +class CommandVersion : public ServerCommand { public: - CommandFName(Module* Creator) : Command(Creator, "FNAME", 1) { flags_needed = FLAG_SERVERONLY; } - CmdResult Handle (const std::vector<std::string>& parameters, User *user); - RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters) { return ROUTE_BROADCAST; } + CommandVersion(Module* Creator) : ServerCommand(Creator, "VERSION", 1) { } + CmdResult Handle(User* user, std::vector<std::string>& parameters); }; -class CommandIJoin : public SplitCommand +class CommandBurst : public ServerCommand { public: - CommandIJoin(Module* Creator) : SplitCommand(Creator, "IJOIN", 1) { flags_needed = FLAG_SERVERONLY; } - CmdResult HandleRemote(const std::vector<std::string>& parameters, RemoteUser* user); - RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters) { return ROUTE_BROADCAST; } + CommandBurst(Module* Creator) : ServerCommand(Creator, "BURST") { } + CmdResult Handle(User* user, std::vector<std::string>& parameters); }; -class CommandResync : public SplitCommand +class CommandEndBurst : public ServerCommand { public: - CommandResync(Module* Creator) : SplitCommand(Creator, "RESYNC", 1) { flags_needed = FLAG_SERVERONLY; } - CmdResult HandleServer(const std::vector<std::string>& parameters, FakeUser* user); + CommandEndBurst(Module* Creator) : ServerCommand(Creator, "ENDBURST") { } + CmdResult Handle(User* user, std::vector<std::string>& parameters); }; class SpanningTreeCommands @@ -165,5 +283,21 @@ class SpanningTreeCommands CommandFHost fhost; CommandFIdent fident; CommandFName fname; + CommandAway away; + CommandAddLine addline; + CommandDelLine delline; + CommandEncap encap; + CommandIdle idle; + CommandNick nick; + CommandPing ping; + CommandPong pong; + CommandPush push; + CommandSave save; + CommandServer server; + CommandSQuit squit; + CommandSNONotice snonotice; + CommandVersion version; + CommandBurst burst; + CommandEndBurst endburst; SpanningTreeCommands(ModuleSpanningTree* module); }; diff --git a/src/modules/m_spanningtree/delline.cpp b/src/modules/m_spanningtree/delline.cpp index 6ac70283c..c4ed1691b 100644 --- a/src/modules/m_spanningtree/delline.cpp +++ b/src/modules/m_spanningtree/delline.cpp @@ -20,35 +20,19 @@ #include "inspircd.h" #include "xline.h" -#include "treesocket.h" -#include "treeserver.h" -#include "utils.h" +#include "commands.h" -bool TreeSocket::DelLine(const std::string &prefix, parameterlist ¶ms) +CmdResult CommandDelLine::Handle(User* user, std::vector<std::string>& params) { - if (params.size() < 2) - return true; - - std::string setter = "<unknown>"; - - User* user = ServerInstance->FindNick(prefix); - if (user) - setter = user->nick; - else - { - TreeServer* t = Utils->FindServer(prefix); - if (t) - setter = t->GetName(); - } - + const std::string& setter = user->nick; /* NOTE: No check needed on 'user', this function safely handles NULL */ if (ServerInstance->XLines->DelLine(params[1].c_str(), params[0], user)) { ServerInstance->SNO->WriteToSnoMask('X',"%s removed %s%s on %s", setter.c_str(), params[0].c_str(), params[0].length() == 1 ? "-line" : "", params[1].c_str()); - Utils->DoOneToAllButSender(prefix,"DELLINE", params, prefix); + return CMD_SUCCESS; } - return true; + return CMD_FAILURE; } diff --git a/src/modules/m_spanningtree/encap.cpp b/src/modules/m_spanningtree/encap.cpp index fedadedb5..12ab2b664 100644 --- a/src/modules/m_spanningtree/encap.cpp +++ b/src/modules/m_spanningtree/encap.cpp @@ -18,31 +18,24 @@ #include "inspircd.h" -#include "xline.h" -#include "treesocket.h" -#include "utils.h" +#include "commands.h" /** ENCAP */ -void TreeSocket::Encap(User* who, parameterlist ¶ms) +CmdResult CommandEncap::Handle(User* user, std::vector<std::string>& params) { - if (params.size() > 1) + if (ServerInstance->Config->GetSID() == params[0] || InspIRCd::Match(ServerInstance->Config->ServerName, params[0])) { - if (ServerInstance->Config->GetSID() == params[0] || InspIRCd::Match(ServerInstance->Config->ServerName, params[0])) - { - parameterlist plist(params.begin() + 2, params.end()); - ServerInstance->Parser->CallHandler(params[1], plist, who); - // discard return value, ENCAP shall succeed even if the command does not exist - } - - params[params.size() - 1] = ":" + params[params.size() - 1]; - - if (params[0].find_first_of("*?") != std::string::npos) - { - Utils->DoOneToAllButSender(who->uuid, "ENCAP", params, who->server); - } - else - Utils->DoOneToOne(who->uuid, "ENCAP", params, params[0]); + parameterlist plist(params.begin() + 2, params.end()); + ServerInstance->Parser->CallHandler(params[1], plist, user); + // Discard return value, ENCAP shall succeed even if the command does not exist } + return CMD_SUCCESS; } +RouteDescriptor CommandEncap::GetRouting(User* user, const std::vector<std::string>& params) +{ + if (params[0].find_first_of("*?") != std::string::npos) + return ROUTE_BROADCAST; + return ROUTE_UNICAST(params[0]); +} diff --git a/src/modules/m_spanningtree/fjoin.cpp b/src/modules/m_spanningtree/fjoin.cpp index 21327581a..831d52c1d 100644 --- a/src/modules/m_spanningtree/fjoin.cpp +++ b/src/modules/m_spanningtree/fjoin.cpp @@ -26,7 +26,7 @@ #include "treesocket.h" /** FJOIN, almost identical to TS6 SJOIN, except for nicklist handling. */ -CmdResult CommandFJoin::Handle(const std::vector<std::string>& params, User *srcuser) +CmdResult CommandFJoin::Handle(User* srcuser, std::vector<std::string>& params) { /* 1.1+ FJOIN works as follows: * diff --git a/src/modules/m_spanningtree/fmode.cpp b/src/modules/m_spanningtree/fmode.cpp index 7e02df6a7..16af5ccc0 100644 --- a/src/modules/m_spanningtree/fmode.cpp +++ b/src/modules/m_spanningtree/fmode.cpp @@ -22,7 +22,7 @@ #include "commands.h" /** FMODE command - server mode with timestamp checks */ -CmdResult CommandFMode::Handle(const std::vector<std::string>& params, User *who) +CmdResult CommandFMode::Handle(User* who, std::vector<std::string>& params) { time_t TS = ConvToInt(params[1]); if (!TS) diff --git a/src/modules/m_spanningtree/ftopic.cpp b/src/modules/m_spanningtree/ftopic.cpp index 69d3af565..0a4a95f9e 100644 --- a/src/modules/m_spanningtree/ftopic.cpp +++ b/src/modules/m_spanningtree/ftopic.cpp @@ -22,7 +22,7 @@ #include "commands.h" /** FTOPIC command */ -CmdResult CommandFTopic::Handle(const std::vector<std::string>& params, User *user) +CmdResult CommandFTopic::Handle(User* user, std::vector<std::string>& params) { Channel* c = ServerInstance->FindChan(params[0]); if (!c) diff --git a/src/modules/m_spanningtree/idle.cpp b/src/modules/m_spanningtree/idle.cpp index 2c95eaad1..57692ddf5 100644 --- a/src/modules/m_spanningtree/idle.cpp +++ b/src/modules/m_spanningtree/idle.cpp @@ -19,33 +19,28 @@ #include "inspircd.h" #include "utils.h" -#include "treesocket.h" +#include "commands.h" -bool TreeSocket::Whois(const std::string &prefix, parameterlist ¶ms) +CmdResult CommandIdle::Handle(User* issuer, std::vector<std::string>& params) { - if (params.size() < 1) - return true; - /* If this is a request, this user did the /whois * If this is a reply, this user's information is in params[1] and params[2] */ - User* issuer = ServerInstance->FindUUID(prefix); - if ((!issuer) || (IS_SERVER(issuer))) - return true; + if (IS_SERVER(issuer)) + return CMD_FAILURE; /* If this is a request, this is the user whose idle information was requested * If this is a reply, this user did the /whois */ User* target = ServerInstance->FindUUID(params[0]); if ((!target) || (IS_SERVER(target))) - return true; + return CMD_FAILURE; LocalUser* localtarget = IS_LOCAL(target); if (!localtarget) { // Forward to target's server - Utils->DoOneToOne(prefix, "IDLE", params, target->server); - return true; + return CMD_SUCCESS; } if (params.size() >= 2) @@ -63,11 +58,11 @@ bool TreeSocket::Whois(const std::string &prefix, parameterlist ¶ms) idle = ((unsigned int) (ServerInstance->Time() - localtarget->idle_lastmsg)); parameterlist reply; - reply.push_back(prefix); + reply.push_back(issuer->uuid); reply.push_back(ConvToStr(target->signon)); reply.push_back(ConvToStr(idle)); Utils->DoOneToOne(params[0], "IDLE", reply, issuer->server); } - return true; + return CMD_SUCCESS; } diff --git a/src/modules/m_spanningtree/ijoin.cpp b/src/modules/m_spanningtree/ijoin.cpp index 8185216d3..8342e9d24 100644 --- a/src/modules/m_spanningtree/ijoin.cpp +++ b/src/modules/m_spanningtree/ijoin.cpp @@ -23,7 +23,7 @@ #include "treeserver.h" #include "treesocket.h" -CmdResult CommandIJoin::HandleRemote(const std::vector<std::string>& params, RemoteUser* user) +CmdResult CommandIJoin::Handle(User* user, std::vector<std::string>& params) { Channel* chan = ServerInstance->FindChan(params[0]); if (!chan) @@ -63,7 +63,7 @@ CmdResult CommandIJoin::HandleRemote(const std::vector<std::string>& params, Rem return CMD_SUCCESS; } -CmdResult CommandResync::HandleServer(const std::vector<std::string>& params, FakeUser* user) +CmdResult CommandResync::Handle(User* user, std::vector<std::string>& params) { ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Resyncing " + params[0]); Channel* chan = ServerInstance->FindChan(params[0]); diff --git a/src/modules/m_spanningtree/main.cpp b/src/modules/m_spanningtree/main.cpp index 7bbe5fbad..8f17129a3 100644 --- a/src/modules/m_spanningtree/main.cpp +++ b/src/modules/m_spanningtree/main.cpp @@ -44,7 +44,11 @@ SpanningTreeCommands::SpanningTreeCommands(ModuleSpanningTree* module) : rconnect(module), rsquit(module), svsjoin(module), svspart(module), svsnick(module), metadata(module), uid(module), opertype(module), fjoin(module), ijoin(module), resync(module), - fmode(module), ftopic(module), fhost(module), fident(module), fname(module) + fmode(module), ftopic(module), fhost(module), fident(module), fname(module), + away(module), addline(module), delline(module), encap(module), idle(module), + nick(module), ping(module), pong(module), push(module), save(module), + server(module), squit(module), snonotice(module), version(module), + burst(module), endburst(module) { } @@ -57,20 +61,6 @@ void ModuleSpanningTree::init() commands = new SpanningTreeCommands(this); ServerInstance->Modules->AddService(commands->rconnect); ServerInstance->Modules->AddService(commands->rsquit); - ServerInstance->Modules->AddService(commands->svsjoin); - ServerInstance->Modules->AddService(commands->svspart); - ServerInstance->Modules->AddService(commands->svsnick); - ServerInstance->Modules->AddService(commands->metadata); - ServerInstance->Modules->AddService(commands->uid); - ServerInstance->Modules->AddService(commands->opertype); - ServerInstance->Modules->AddService(commands->fjoin); - ServerInstance->Modules->AddService(commands->ijoin); - ServerInstance->Modules->AddService(commands->resync); - ServerInstance->Modules->AddService(commands->fmode); - ServerInstance->Modules->AddService(commands->ftopic); - ServerInstance->Modules->AddService(commands->fhost); - ServerInstance->Modules->AddService(commands->fident); - ServerInstance->Modules->AddService(commands->fname); delete ServerInstance->PI; ServerInstance->PI = new SpanningTreeProtocolInterface(Utils); diff --git a/src/modules/m_spanningtree/main.h b/src/modules/m_spanningtree/main.h index 07b0762e5..8b1f8e72f 100644 --- a/src/modules/m_spanningtree/main.h +++ b/src/modules/m_spanningtree/main.h @@ -24,8 +24,9 @@ #pragma once #include "inspircd.h" - #include "modules/dns.h" +#include "servercommand.h" + /** If you make a change which breaks the protocol, increment this. * If you completely change the protocol, completely change the number. * @@ -57,6 +58,8 @@ class ModuleSpanningTree : public Module public: dynamic_reference<DNS::Manager> DNS; + ServerCommandManager CmdManager; + /** Set to true if inside a spanningtree call, to prevent sending * xlines and other things back to their source */ diff --git a/src/modules/m_spanningtree/metadata.cpp b/src/modules/m_spanningtree/metadata.cpp index 8ce41d87f..cf386cf21 100644 --- a/src/modules/m_spanningtree/metadata.cpp +++ b/src/modules/m_spanningtree/metadata.cpp @@ -21,7 +21,7 @@ #include "inspircd.h" #include "commands.h" -CmdResult CommandMetadata::Handle(const std::vector<std::string>& params, User *srcuser) +CmdResult CommandMetadata::Handle(User* srcuser, std::vector<std::string>& params) { if (params[0] == "*") { diff --git a/src/modules/m_spanningtree/misccommands.cpp b/src/modules/m_spanningtree/misccommands.cpp new file mode 100644 index 000000000..6e66c68a7 --- /dev/null +++ b/src/modules/m_spanningtree/misccommands.cpp @@ -0,0 +1,56 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2013 Attila Molnar <attilamolnar@hush.com> + * Copyright (C) 2007-2008, 2012 Robin Burchell <robin+git@viroteck.net> + * Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org> + * Copyright (C) 2007-2008 Craig Edwards <craigedwards@brainbox.cc> + * Copyright (C) 2008 Pippijn van Steenhoven <pip88nl@gmail.com> + * Copyright (C) 2008 Thomas Stagner <aquanight@inspircd.org> + * Copyright (C) 2007 Dennis Friis <peavey@inspircd.org> + * + * This file is part of InspIRCd. InspIRCd 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, version 2. + * + * 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, see <http://www.gnu.org/licenses/>. + */ + + +#include "inspircd.h" + +#include "main.h" +#include "commands.h" +#include "treeserver.h" + +CmdResult CommandSNONotice::Handle(User* user, std::vector<std::string>& params) +{ + ServerInstance->SNO->WriteToSnoMask(params[0][0], "From " + user->nick + ": " + params[1]); + return CMD_SUCCESS; +} + +CmdResult CommandBurst::Handle(User* user, std::vector<std::string>& params) +{ + if (!IS_SERVER(user)) + return CMD_INVALID; + + TreeServer* server = Utils->FindServer(user->server); + server->bursting = true; + return CMD_SUCCESS; +} + +CmdResult CommandEndBurst::Handle(User* user, std::vector<std::string>& params) +{ + if (!IS_SERVER(user)) + return CMD_INVALID; + + TreeServer* server = Utils->FindServer(user->server); + server->FinishBurst(); + return CMD_SUCCESS; +} diff --git a/src/modules/m_spanningtree/nick.cpp b/src/modules/m_spanningtree/nick.cpp new file mode 100644 index 000000000..5de12b51b --- /dev/null +++ b/src/modules/m_spanningtree/nick.cpp @@ -0,0 +1,64 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2013 Attila Molnar <attilamolnar@hush.com> + * Copyright (C) 2007-2008, 2012 Robin Burchell <robin+git@viroteck.net> + * Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org> + * Copyright (C) 2007-2008 Craig Edwards <craigedwards@brainbox.cc> + * Copyright (C) 2008 Pippijn van Steenhoven <pip88nl@gmail.com> + * Copyright (C) 2008 Thomas Stagner <aquanight@inspircd.org> + * Copyright (C) 2007 Dennis Friis <peavey@inspircd.org> + * + * This file is part of InspIRCd. InspIRCd 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, version 2. + * + * 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, see <http://www.gnu.org/licenses/>. + */ + + +#include "inspircd.h" + +#include "main.h" +#include "utils.h" +#include "commands.h" + +CmdResult CommandNick::Handle(User* user, std::vector<std::string>& params) +{ + if (IS_SERVER(user)) + return CMD_INVALID; + + if ((isdigit(params[0][0])) && (params[0] != user->uuid)) + return CMD_INVALID; + + /* Update timestamp on user when they change nicks */ + user->age = ConvToInt(params[1]); + + /* + * On nick messages, check that the nick doesn't already exist here. + * If it does, perform collision logic. + */ + User* x = ServerInstance->FindNickOnly(params[0]); + if ((x) && (x != user)) + { + /* x is local, who is remote */ + int collideret = Utils->DoCollision(x, Utils->FindServer(user->server), user->age, user->ident, user->GetIPString(), user->uuid); + if (collideret != 1) + { + /* + * Remote client lost, or both lost, parsing or passing on this + * nickchange would be pointless, as the incoming client's server will + * soon receive SAVE to change its nick to its UID. :) -- w00t + */ + return CMD_FAILURE; + } + } + user->ForceNickChange(params[0]); + return CMD_SUCCESS; +} diff --git a/src/modules/m_spanningtree/nickcollide.cpp b/src/modules/m_spanningtree/nickcollide.cpp index 3d29e402a..39490e953 100644 --- a/src/modules/m_spanningtree/nickcollide.cpp +++ b/src/modules/m_spanningtree/nickcollide.cpp @@ -21,6 +21,7 @@ #include "inspircd.h" #include "treesocket.h" +#include "treeserver.h" #include "utils.h" /* @@ -29,7 +30,7 @@ * Returns 1 if colliding local client, 2 if colliding remote, 3 if colliding both. * Sends SAVEs as appropriate and forces nickchanges too. */ -int TreeSocket::DoCollision(User *u, time_t remotets, const std::string &remoteident, const std::string &remoteip, const std::string &remoteuid) +int SpanningTreeUtilities::DoCollision(User* u, TreeServer* server, time_t remotets, const std::string& remoteident, const std::string& remoteip, const std::string& remoteuid) { /* * Under old protocol rules, we would have had to kill both clients. @@ -107,7 +108,7 @@ int TreeSocket::DoCollision(User *u, time_t remotets, const std::string &remotei parameterlist params; params.push_back(u->uuid); params.push_back(ConvToStr(u->age)); - Utils->DoOneToMany(ServerInstance->Config->GetSID(),"SAVE",params); + this->DoOneToMany(ServerInstance->Config->GetSID(),"SAVE",params); u->ForceNickChange(u->uuid); @@ -122,7 +123,8 @@ int TreeSocket::DoCollision(User *u, time_t remotets, const std::string &remotei * the UID or halt the propagation of the nick change command, * so other servers don't need to see the SAVE */ - WriteLine(":"+ServerInstance->Config->GetSID()+" SAVE "+remoteuid+" "+ ConvToStr(remotets)); + TreeSocket* sock = server->GetRoute()->GetSocket(); + sock->WriteLine(":"+ServerInstance->Config->GetSID()+" SAVE "+remoteuid+" "+ ConvToStr(remotets)); if (remote) { diff --git a/src/modules/m_spanningtree/opertype.cpp b/src/modules/m_spanningtree/opertype.cpp index 835448503..c3f9b633c 100644 --- a/src/modules/m_spanningtree/opertype.cpp +++ b/src/modules/m_spanningtree/opertype.cpp @@ -26,7 +26,7 @@ /** Because the core won't let users or even SERVERS set +o, * we use the OPERTYPE command to do this. */ -CmdResult CommandOpertype::Handle(const std::vector<std::string>& params, User *u) +CmdResult CommandOpertype::Handle(User* u, std::vector<std::string>& params) { const std::string& opertype = params[0]; if (!u->IsOper()) diff --git a/src/modules/m_spanningtree/ping.cpp b/src/modules/m_spanningtree/ping.cpp index 92eee2666..537efe964 100644 --- a/src/modules/m_spanningtree/ping.cpp +++ b/src/modules/m_spanningtree/ping.cpp @@ -20,30 +20,24 @@ #include "inspircd.h" #include "utils.h" -#include "treesocket.h" +#include "treeserver.h" +#include "commands.h" +#include "utils.h" -bool TreeSocket::LocalPing(const std::string &prefix, parameterlist ¶ms) +CmdResult CommandPing::Handle(User* user, std::vector<std::string>& params) { - if (params.size() < 1) - return true; - - const std::string& forwardto = params[0]; - if (forwardto == ServerInstance->Config->GetSID()) + if (params[0] == ServerInstance->Config->GetSID()) { // PING for us, reply with a PONG - std::string reply = ":" + forwardto + " PONG " + prefix; + parameterlist reply; + reply.push_back(user->uuid); if (params.size() >= 2) // If there is a second parameter, append it - reply.append(" :").append(params[1]); + reply.push_back(params[1]); - this->WriteLine(reply); - } - else - { - // not for us, pass it on :) - Utils->DoOneToOne(prefix,"PING",params,forwardto); + Utils->DoOneToOne(params[0], "PONG", reply, user->server); } - return true; + return CMD_SUCCESS; } diff --git a/src/modules/m_spanningtree/pong.cpp b/src/modules/m_spanningtree/pong.cpp index 034f1f891..006d51a10 100644 --- a/src/modules/m_spanningtree/pong.cpp +++ b/src/modules/m_spanningtree/pong.cpp @@ -21,30 +21,25 @@ #include "utils.h" #include "treeserver.h" -#include "treesocket.h" +#include "commands.h" +#include "utils.h" -bool TreeSocket::LocalPong(const std::string &prefix, parameterlist ¶ms) +CmdResult CommandPong::Handle(User* user, std::vector<std::string>& params) { - if (params.size() < 1) - return true; - - const std::string& forwardto = params[0]; - if (forwardto == ServerInstance->Config->GetSID()) + TreeServer* server = Utils->FindServer(user->server); + if (server->bursting) { - // PONG for us - TreeServer* ServerSource = Utils->FindServer(prefix); - if (ServerSource) - { - long ts = ServerInstance->Time() * 1000 + (ServerInstance->Time_ns() / 1000000); - ServerSource->rtt = ts - ServerSource->LastPingMsec; - ServerSource->SetPingFlag(); - } + ServerInstance->SNO->WriteGlobalSno('l', "Server \002%s\002 has not finished burst, forcing end of burst (send ENDBURST!)", server->GetName().c_str()); + server->FinishBurst(); } - else + + if (params[0] == ServerInstance->Config->GetSID()) { - // not for us, pass it on :) - Utils->DoOneToOne(prefix,"PONG",params,forwardto); + // PONG for us + long ts = ServerInstance->Time() * 1000 + (ServerInstance->Time_ns() / 1000000); + server->rtt = ts - server->LastPingMsec; + server->SetPingFlag(); } - return true; + return CMD_SUCCESS; } diff --git a/src/modules/m_spanningtree/postcommand.cpp b/src/modules/m_spanningtree/postcommand.cpp index 7a681856a..3fb3d5b07 100644 --- a/src/modules/m_spanningtree/postcommand.cpp +++ b/src/modules/m_spanningtree/postcommand.cpp @@ -29,7 +29,7 @@ void ModuleSpanningTree::OnPostCommand(Command* command, const std::vector<std:: Utils->RouteCommand(NULL, command, parameters, user); } -void SpanningTreeUtilities::RouteCommand(TreeServer* origin, Command* thiscmd, const parameterlist& parameters, User* user) +void SpanningTreeUtilities::RouteCommand(TreeServer* origin, CommandBase* thiscmd, const parameterlist& parameters, User* user) { const std::string& command = thiscmd->name; RouteDescriptor routing = thiscmd->GetRouting(user, parameters); diff --git a/src/modules/m_spanningtree/push.cpp b/src/modules/m_spanningtree/push.cpp index 05b5d68de..a265e0d2e 100644 --- a/src/modules/m_spanningtree/push.cpp +++ b/src/modules/m_spanningtree/push.cpp @@ -20,25 +20,17 @@ #include "inspircd.h" #include "utils.h" -#include "treesocket.h" +#include "commands.h" -bool TreeSocket::Push(const std::string &prefix, parameterlist ¶ms) +CmdResult CommandPush::Handle(User* user, std::vector<std::string>& params) { - if (params.size() < 2) - return true; User* u = ServerInstance->FindNick(params[0]); if (!u) - return true; + return CMD_FAILURE; if (IS_LOCAL(u)) { u->Write(params[1]); } - else - { - // continue the raw onwards - params[1] = ":" + params[1]; - Utils->DoOneToOne(prefix,"PUSH",params,u->server); - } - return true; + return CMD_SUCCESS; } diff --git a/src/modules/m_spanningtree/save.cpp b/src/modules/m_spanningtree/save.cpp index 42d909be7..8f0eced73 100644 --- a/src/modules/m_spanningtree/save.cpp +++ b/src/modules/m_spanningtree/save.cpp @@ -21,28 +21,27 @@ #include "utils.h" #include "treesocket.h" +#include "commands.h" /** * SAVE command - force nick change to UID on timestamp match */ -bool TreeSocket::ForceNick(const std::string &prefix, parameterlist ¶ms) +CmdResult CommandSave::Handle(User* user, std::vector<std::string>& params) { - if (params.size() < 2) - return true; - User* u = ServerInstance->FindNick(params[0]); + if ((!u) || (IS_SERVER(u))) + return CMD_FAILURE; + time_t ts = atol(params[1].c_str()); - if ((u) && (!IS_SERVER(u)) && (u->age == ts)) + if (u->age == ts) { - Utils->DoOneToAllButSender(prefix,"SAVE",params,prefix); - if (!u->ForceNickChange(u->uuid)) { ServerInstance->Users->QuitUser(u, "Nickname collision"); } } - return true; + return CMD_SUCCESS; } diff --git a/src/modules/m_spanningtree/server.cpp b/src/modules/m_spanningtree/server.cpp index aebc16568..fcd326974 100644 --- a/src/modules/m_spanningtree/server.cpp +++ b/src/modules/m_spanningtree/server.cpp @@ -20,53 +20,48 @@ #include "inspircd.h" +#include "main.h" #include "utils.h" #include "link.h" #include "treeserver.h" #include "treesocket.h" +#include "commands.h" /* * Some server somewhere in the network introducing another server. * -- w */ -bool TreeSocket::RemoteServer(const std::string &prefix, parameterlist ¶ms) +CmdResult CommandServer::Handle(User* user, std::vector<std::string>& params) { - if (params.size() < 5) - { - SendError("Protocol error - Not enough parameters for SERVER command"); - return false; - } - std::string servername = params[0]; // password is not used for a remote server // hopcount is not used (ever) std::string sid = params[3]; std::string description = params[4]; - TreeServer* ParentOfThis = Utils->FindServer(prefix); + TreeServer* ParentOfThis = Utils->FindServer(user->server); + TreeSocket* socket = ParentOfThis->GetRoute()->GetSocket(); + + if (!IS_SERVER(user)) + return CMD_FAILURE; - if (!ParentOfThis) - { - this->SendError("Protocol error - Introduced remote server from unknown server "+prefix); - return false; - } if (!InspIRCd::IsSID(sid)) { - this->SendError("Invalid format server ID: "+sid+"!"); - return false; + socket->SendError("Invalid format server ID: "+sid+"!"); + return CMD_FAILURE; } TreeServer* CheckDupe = Utils->FindServer(servername); if (CheckDupe) { - this->SendError("Server "+servername+" already exists!"); + socket->SendError("Server "+servername+" already exists!"); ServerInstance->SNO->WriteToSnoMask('L', "Server \2"+CheckDupe->GetName()+"\2 being introduced from \2" + ParentOfThis->GetName() + "\2 denied, already exists. Closing link with " + ParentOfThis->GetName()); - return false; + return CMD_FAILURE; } CheckDupe = Utils->FindServer(sid); if (CheckDupe) { - this->SendError("Server ID "+sid+" already exists! You may want to specify the server ID for the server manually with <server:id> so they do not conflict."); + socket->SendError("Server ID "+sid+" already exists! You may want to specify the server ID for the server manually with <server:id> so they do not conflict."); ServerInstance->SNO->WriteToSnoMask('L', "Server \2"+servername+"\2 being introduced from \2" + ParentOfThis->GetName() + "\2 denied, server ID already exists on the network. Closing link with " + ParentOfThis->GetName()); - return false; + return CMD_FAILURE; } @@ -75,10 +70,8 @@ bool TreeSocket::RemoteServer(const std::string &prefix, parameterlist ¶ms) TreeServer *Node = new TreeServer(servername, description, sid, ParentOfThis,NULL, lnk ? lnk->Hidden : false); ParentOfThis->AddChild(Node); - params[4] = ":" + params[4]; - Utils->DoOneToAllButSender(prefix,"SERVER",params,prefix); ServerInstance->SNO->WriteToSnoMask('L', "Server \002"+ParentOfThis->GetName()+"\002 introduced server \002"+servername+"\002 ("+description+")"); - return true; + return CMD_SUCCESS; } diff --git a/src/modules/m_spanningtree/servercommand.cpp b/src/modules/m_spanningtree/servercommand.cpp new file mode 100644 index 000000000..fe5a38a9e --- /dev/null +++ b/src/modules/m_spanningtree/servercommand.cpp @@ -0,0 +1,48 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2013 Attila Molnar <attilamolnar@hush.com> + * + * This file is part of InspIRCd. InspIRCd 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, version 2. + * + * 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, see <http://www.gnu.org/licenses/>. + */ + + +#include "inspircd.h" +#include "main.h" +#include "servercommand.h" + +ServerCommand::ServerCommand(Module* Creator, const std::string& Name, unsigned int MinParams, unsigned int MaxParams) + : CommandBase(Creator, Name, MinParams, MaxParams) +{ + ModuleSpanningTree* st = static_cast<ModuleSpanningTree*>(Creator); + st->CmdManager.AddCommand(this); +} + +RouteDescriptor ServerCommand::GetRouting(User* user, const std::vector<std::string>& parameters) +{ + // Broadcast server-to-server commands unless overridden + return ROUTE_BROADCAST; +} + +ServerCommand* ServerCommandManager::GetHandler(const std::string& command) const +{ + ServerCommandMap::const_iterator it = commands.find(command); + if (it != commands.end()) + return it->second; + return NULL; +} + +bool ServerCommandManager::AddCommand(ServerCommand* cmd) +{ + return commands.insert(std::make_pair(cmd->name, cmd)).second; +} diff --git a/src/modules/m_spanningtree/servercommand.h b/src/modules/m_spanningtree/servercommand.h new file mode 100644 index 000000000..4311dd7b7 --- /dev/null +++ b/src/modules/m_spanningtree/servercommand.h @@ -0,0 +1,39 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2013 Attila Molnar <attilamolnar@hush.com> + * + * This file is part of InspIRCd. InspIRCd 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, version 2. + * + * 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, see <http://www.gnu.org/licenses/>. + */ + + +#pragma once + +class ServerCommand : public CommandBase +{ + public: + ServerCommand(Module* Creator, const std::string& Name, unsigned int MinPara = 0, unsigned int MaxPara = 0); + + virtual CmdResult Handle(User* user, std::vector<std::string>& parameters) = 0; + virtual RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters); +}; + +class ServerCommandManager +{ + typedef TR1NS::unordered_map<std::string, ServerCommand*> ServerCommandMap; + ServerCommandMap commands; + + public: + ServerCommand* GetHandler(const std::string& command) const; + bool AddCommand(ServerCommand* cmd); +}; diff --git a/src/modules/m_spanningtree/svsjoin.cpp b/src/modules/m_spanningtree/svsjoin.cpp index 032633416..552e08dd3 100644 --- a/src/modules/m_spanningtree/svsjoin.cpp +++ b/src/modules/m_spanningtree/svsjoin.cpp @@ -22,7 +22,7 @@ #include "commands.h" -CmdResult CommandSVSJoin::Handle(const std::vector<std::string>& parameters, User *user) +CmdResult CommandSVSJoin::Handle(User* user, std::vector<std::string>& parameters) { // Check for valid channel name if (!ServerInstance->IsChannel(parameters[1])) diff --git a/src/modules/m_spanningtree/svsnick.cpp b/src/modules/m_spanningtree/svsnick.cpp index 6490626af..a504afbd7 100644 --- a/src/modules/m_spanningtree/svsnick.cpp +++ b/src/modules/m_spanningtree/svsnick.cpp @@ -22,7 +22,7 @@ #include "commands.h" -CmdResult CommandSVSNick::Handle(const std::vector<std::string>& parameters, User *user) +CmdResult CommandSVSNick::Handle(User* user, std::vector<std::string>& parameters) { User* u = ServerInstance->FindNick(parameters[0]); diff --git a/src/modules/m_spanningtree/svspart.cpp b/src/modules/m_spanningtree/svspart.cpp index b966da282..f86afa367 100644 --- a/src/modules/m_spanningtree/svspart.cpp +++ b/src/modules/m_spanningtree/svspart.cpp @@ -22,7 +22,7 @@ #include "commands.h" -CmdResult CommandSVSPart::Handle(const std::vector<std::string>& parameters, User *user) +CmdResult CommandSVSPart::Handle(User* user, std::vector<std::string>& parameters) { User* u = ServerInstance->FindUUID(parameters[0]); if (!u) diff --git a/src/modules/m_spanningtree/treesocket.h b/src/modules/m_spanningtree/treesocket.h index 88204319c..47bdef884 100644 --- a/src/modules/m_spanningtree/treesocket.h +++ b/src/modules/m_spanningtree/treesocket.h @@ -208,9 +208,6 @@ class TreeSocket : public BufferedSocket */ void Squit(TreeServer* Current, const std::string &reason); - /* Used on nick collision ... XXX ugly function HACK */ - int DoCollision(User *u, time_t remotets, const std::string &remoteident, const std::string &remoteip, const std::string &remoteuid); - /** Send one or more FJOINs for a channel of users. * If the length of a single line is more than 480-NICKMAX * in length, it is split over multiple lines. @@ -245,48 +242,6 @@ class TreeSocket : public BufferedSocket /** Handle ERROR command */ void Error(parameterlist ¶ms); - /** Remote AWAY */ - bool Away(const std::string &prefix, parameterlist ¶ms); - - /** SAVE to resolve nick collisions without killing */ - bool ForceNick(const std::string &prefix, parameterlist ¶ms); - - /** ENCAP command - */ - void Encap(User* who, parameterlist ¶ms); - - /** PONG - */ - bool LocalPong(const std::string &prefix, parameterlist ¶ms); - - /** VERSION - */ - bool ServerVersion(const std::string &prefix, parameterlist ¶ms); - - /** ADDLINE - */ - bool AddLine(const std::string &prefix, parameterlist ¶ms); - - /** DELLINE - */ - bool DelLine(const std::string &prefix, parameterlist ¶ms); - - /** WHOIS - */ - bool Whois(const std::string &prefix, parameterlist ¶ms); - - /** PUSH - */ - bool Push(const std::string &prefix, parameterlist ¶ms); - - /** PING - */ - bool LocalPing(const std::string &prefix, parameterlist ¶ms); - - /** <- (remote) <- SERVER - */ - bool RemoteServer(const std::string &prefix, parameterlist ¶ms); - /** (local) -> SERVER */ bool Outbound_Reply_Server(parameterlist ¶ms); diff --git a/src/modules/m_spanningtree/treesocket1.cpp b/src/modules/m_spanningtree/treesocket1.cpp index e2afe6421..8dbdb3839 100644 --- a/src/modules/m_spanningtree/treesocket1.cpp +++ b/src/modules/m_spanningtree/treesocket1.cpp @@ -29,6 +29,7 @@ #include "treeserver.h" #include "link.h" #include "treesocket.h" +#include "commands.h" /** Because most of the I/O gubbins are encapsulated within * BufferedSocket, we just call the superclass constructor for @@ -167,22 +168,21 @@ void TreeSocket::Squit(TreeServer* Current, const std::string &reason) { bool LocalSquit = false; - if ((Current) && (Current != Utils->TreeRoot)) + if (Current != Utils->TreeRoot) { DelServerEvent(Utils->Creator, Current->GetName()); - if (!Current->GetSocket() || Current->GetSocket()->Introduced()) - { - parameterlist params; - params.push_back(Current->GetID()); - params.push_back(":"+reason); - Utils->DoOneToAllButSender(Current->GetParent()->GetID(),"SQUIT",params,Current->GetName()); - } - if (Current->GetParent() == Utils->TreeRoot) { ServerInstance->SNO->WriteGlobalSno('l', "Server \002"+Current->GetName()+"\002 split: "+reason); LocalSquit = true; + if (Current->GetSocket()->Introduced()) + { + parameterlist params; + params.push_back(Current->GetID()); + params.push_back(":"+reason); + Utils->DoOneToMany(Utils->TreeRoot->GetID(), "SQUIT", params); + } } else { @@ -204,8 +204,20 @@ void TreeSocket::Squit(TreeServer* Current, const std::string &reason) Close(); } } - else +} + +CmdResult CommandSQuit::Handle(User* user, std::vector<std::string>& params) +{ + TreeServer* quitting = Utils->FindServer(params[0]); + if (!quitting) + { ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Squit from unknown server"); + return CMD_FAILURE; + } + + TreeSocket* sock = Utils->FindServer(user->server)->GetRoute()->GetSocket(); + sock->Squit(quitting, params[1]); + return CMD_SUCCESS; } /** This function is called when we receive data from a remote diff --git a/src/modules/m_spanningtree/treesocket2.cpp b/src/modules/m_spanningtree/treesocket2.cpp index 4995f6cb7..66826ff3b 100644 --- a/src/modules/m_spanningtree/treesocket2.cpp +++ b/src/modules/m_spanningtree/treesocket2.cpp @@ -310,156 +310,13 @@ void TreeSocket::ProcessConnectedLine(std::string& prefix, std::string& command, return; } - // TODO move all this into Commands - if (command == "MAP") + ServerCommand* scmd = Utils->Creator->CmdManager.GetHandler(command); + CommandBase* cmdbase = scmd; + Command* cmd; + if (!scmd) { - Utils->Creator->HandleMap(params, who); - } - else if (command == "SERVER") - { - this->RemoteServer(prefix,params); - } - else if (command == "ERROR") - { - this->Error(params); - } - else if (command == "AWAY") - { - this->Away(prefix,params); - } - else if (command == "PING") - { - this->LocalPing(prefix,params); - } - else if (command == "PONG") - { - TreeServer *s = Utils->FindServer(prefix); - if (s && s->bursting) - { - ServerInstance->SNO->WriteGlobalSno('l',"Server \002%s\002 has not finished burst, forcing end of burst (send ENDBURST!)", prefix.c_str()); - s->FinishBurst(); - } - this->LocalPong(prefix,params); - } - else if (command == "VERSION") - { - this->ServerVersion(prefix,params); - } - else if (command == "ADDLINE") - { - this->AddLine(prefix,params); - } - else if (command == "DELLINE") - { - this->DelLine(prefix,params); - } - else if (command == "SAVE") - { - this->ForceNick(prefix,params); - } - else if (command == "IDLE") - { - this->Whois(prefix,params); - } - else if (command == "PUSH") - { - this->Push(prefix,params); - } - else if (command == "SQUIT") - { - if (params.size() == 2) - { - this->Squit(Utils->FindServer(params[0]),params[1]); - } - } - else if (command == "SNONOTICE") - { - if (params.size() >= 2) - { - ServerInstance->SNO->WriteToSnoMask(params[0][0], "From " + who->nick + ": "+ params[1]); - params[1] = ":" + params[1]; - Utils->DoOneToAllButSender(prefix, command, params, prefix); - } - } - else if (command == "BURST") - { - // Set prefix server as bursting - TreeServer* ServerSource = Utils->FindServer(prefix); - if (!ServerSource) - { - ServerInstance->SNO->WriteGlobalSno('l', "WTF: Got BURST from a non-server(?): %s", prefix.c_str()); - return; - } - - ServerSource->bursting = true; - Utils->DoOneToAllButSender(prefix, command, params, prefix); - } - else if (command == "ENDBURST") - { - TreeServer* ServerSource = Utils->FindServer(prefix); - if (!ServerSource) - { - ServerInstance->SNO->WriteGlobalSno('l', "WTF: Got ENDBURST from a non-server(?): %s", prefix.c_str()); - return; - } - - ServerSource->FinishBurst(); - Utils->DoOneToAllButSender(prefix, command, params, prefix); - } - else if (command == "ENCAP") - { - this->Encap(who, params); - } - else if (command == "NICK") - { - if (params.size() != 2) - { - SendError("Protocol violation: Wrong number of parameters for NICK message"); - return; - } - - if (IS_SERVER(who)) - { - SendError("Protocol violation: Server changing nick"); - return; - } - - if ((isdigit(params[0][0])) && (params[0] != who->uuid)) - { - SendError("Protocol violation: User changing nick to an invalid UID - " + params[0]); - return; - } - - /* Update timestamp on user when they change nicks */ - who->age = ConvToInt(params[1]); - - /* - * On nick messages, check that the nick doesnt already exist here. - * If it does, perform collision logic. - */ - User* x = ServerInstance->FindNickOnly(params[0]); - if ((x) && (x != who)) - { - int collideret = 0; - /* x is local, who is remote */ - collideret = this->DoCollision(x, who->age, who->ident, who->GetIPString(), who->uuid); - if (collideret != 1) - { - /* - * Remote client lost, or both lost, parsing or passing on this - * nickchange would be pointless, as the incoming client's server will - * soon recieve SVSNICK to change its nick to its UID. :) -- w00t - */ - return; - } - } - who->ForceNickChange(params[0]); - Utils->DoOneToAllButSender(prefix, command, params, prefix); - } - else - { - Command* cmd = ServerInstance->Parser->GetHandler(command); - + // Not a special server-to-server command + cmd = ServerInstance->Parser->GetHandler(command); if (!cmd) { irc::stringjoiner pmlist(params); @@ -468,36 +325,41 @@ void TreeSocket::ProcessConnectedLine(std::string& prefix, std::string& command, SendError("Unrecognised command '" + command + "' -- possibly loaded mismatched modules"); return; } + cmdbase = cmd; + } - if (params.size() < cmd->min_params) - { - irc::stringjoiner pmlist(params); - ServerInstance->Logs->Log(MODNAME, LOG_SPARSE, "Insufficient parameters for S2S command :%s %s %s", - who->uuid.c_str(), command.c_str(), pmlist.GetJoined().c_str()); - SendError("Insufficient parameters for command '" + command + "'"); - return; - } + if (params.size() < cmdbase->min_params) + { + irc::stringjoiner pmlist(params); + ServerInstance->Logs->Log(MODNAME, LOG_SPARSE, "Insufficient parameters for S2S command :%s %s %s", + who->uuid.c_str(), command.c_str(), pmlist.GetJoined().c_str()); + SendError("Insufficient parameters for command '" + command + "'"); + return; + } - if ((!params.empty()) && (params.back().empty()) && (!cmd->allow_empty_last_param)) - { - // the last param is empty and the command handler doesn't allow that, check if there will be enough params if we drop the last - if (params.size()-1 < cmd->min_params) - return; - params.pop_back(); - } + if ((!params.empty()) && (params.back().empty()) && (!cmdbase->allow_empty_last_param)) + { + // the last param is empty and the command handler doesn't allow that, check if there will be enough params if we drop the last + if (params.size()-1 < cmdbase->min_params) + return; + params.pop_back(); + } - CmdResult res = cmd->Handle(params, who); + CmdResult res; + if (scmd) + res = scmd->Handle(who, params); + else + res = cmd->Handle(params, who); - if (res == CMD_INVALID) - { - irc::stringjoiner pmlist(params); - ServerInstance->Logs->Log(MODNAME, LOG_SPARSE, "Error handling S2S command :%s %s %s", - who->uuid.c_str(), command.c_str(), pmlist.GetJoined().c_str()); - SendError("Error handling '" + command + "' -- possibly loaded mismatched modules"); - } - else if (res == CMD_SUCCESS) - Utils->RouteCommand(route_back_again, cmd, params, who); + if (res == CMD_INVALID) + { + irc::stringjoiner pmlist(params); + ServerInstance->Logs->Log(MODNAME, LOG_SPARSE, "Error handling S2S command :%s %s %s", + who->uuid.c_str(), command.c_str(), pmlist.GetJoined().c_str()); + SendError("Error handling '" + command + "' -- possibly loaded mismatched modules"); } + else if (res == CMD_SUCCESS) + Utils->RouteCommand(route_back_again, cmdbase, params, who); } void TreeSocket::OnTimeout() diff --git a/src/modules/m_spanningtree/uid.cpp b/src/modules/m_spanningtree/uid.cpp index a24d44e53..da75eebec 100644 --- a/src/modules/m_spanningtree/uid.cpp +++ b/src/modules/m_spanningtree/uid.cpp @@ -25,7 +25,7 @@ #include "utils.h" #include "treeserver.h" -CmdResult CommandUID::Handle(const parameterlist ¶ms, User* serversrc) +CmdResult CommandUID::Handle(User* serversrc, std::vector<std::string>& params) { /** Do we have enough parameters: * 0 1 2 3 4 5 6 7 8 9 (n-1) @@ -50,7 +50,6 @@ CmdResult CommandUID::Handle(const parameterlist ¶ms, User* serversrc) return CMD_INVALID; if (modestr[0] != '+') return CMD_INVALID; - TreeSocket* sock = remoteserver->GetRoute()->GetSocket(); /* check for collision */ user_hash::iterator iter = ServerInstance->Users->clientlist->find(params[2]); @@ -60,17 +59,13 @@ CmdResult CommandUID::Handle(const parameterlist ¶ms, User* serversrc) /* * Nick collision. */ - int collide = sock->DoCollision(iter->second, age_t, params[5], params[6], params[0]); + int collide = Utils->DoCollision(iter->second, remoteserver, age_t, params[5], params[6], params[0]); ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "*** Collision on %s, collide=%d", params[2].c_str(), collide); if (collide != 1) { - /* remote client lost, make sure we change their nick for the hash too - * - * This alters the line that will be sent to other servers, which - * commands normally shouldn't do; hence the required const_cast. - */ - const_cast<parameterlist&>(params)[2] = params[0]; + // Remote client lost, make sure we change their nick for the hash too + params[2] = params[0]; } } @@ -152,7 +147,7 @@ CmdResult CommandUID::Handle(const parameterlist ¶ms, User* serversrc) return CMD_SUCCESS; } -CmdResult CommandFHost::Handle(const parameterlist ¶ms, User* src) +CmdResult CommandFHost::Handle(User* src, std::vector<std::string>& params) { if (IS_SERVER(src)) return CMD_FAILURE; @@ -160,7 +155,7 @@ CmdResult CommandFHost::Handle(const parameterlist ¶ms, User* src) return CMD_SUCCESS; } -CmdResult CommandFIdent::Handle(const parameterlist ¶ms, User* src) +CmdResult CommandFIdent::Handle(User* src, std::vector<std::string>& params) { if (IS_SERVER(src)) return CMD_FAILURE; @@ -168,7 +163,7 @@ CmdResult CommandFIdent::Handle(const parameterlist ¶ms, User* src) return CMD_SUCCESS; } -CmdResult CommandFName::Handle(const parameterlist ¶ms, User* src) +CmdResult CommandFName::Handle(User* src, std::vector<std::string>& params) { if (IS_SERVER(src)) return CMD_FAILURE; diff --git a/src/modules/m_spanningtree/utils.h b/src/modules/m_spanningtree/utils.h index bf81ef47f..f65b07c43 100644 --- a/src/modules/m_spanningtree/utils.h +++ b/src/modules/m_spanningtree/utils.h @@ -126,7 +126,7 @@ class SpanningTreeUtilities : public classbase */ ~SpanningTreeUtilities(); - void RouteCommand(TreeServer*, Command*, const parameterlist&, User*); + void RouteCommand(TreeServer* origin, CommandBase* cmd, const parameterlist& parameters, User* user); /** Send a message from this server to one other local or remote */ @@ -144,6 +144,10 @@ class SpanningTreeUtilities : public classbase */ void ReadConfiguration(); + /** Handle nick collision + */ + int DoCollision(User* u, TreeServer* server, time_t remotets, const std::string& remoteident, const std::string& remoteip, const std::string& remoteuid); + /** Compile a list of servers which contain members of channel c */ void GetListOfServersForChannel(Channel* c, TreeServerList &list, char status, const CUList &exempt_list); diff --git a/src/modules/m_spanningtree/version.cpp b/src/modules/m_spanningtree/version.cpp index 63bf6c419..9a0710359 100644 --- a/src/modules/m_spanningtree/version.cpp +++ b/src/modules/m_spanningtree/version.cpp @@ -22,21 +22,16 @@ #include "main.h" #include "utils.h" #include "treeserver.h" -#include "treesocket.h" +#include "commands.h" -bool TreeSocket::ServerVersion(const std::string &prefix, parameterlist ¶ms) +CmdResult CommandVersion::Handle(User* user, std::vector<std::string>& params) { - if (params.size() < 1) - return true; - - TreeServer* ServerSource = Utils->FindServer(prefix); + TreeServer* ServerSource = Utils->FindServer(user->server); if (ServerSource) { ServerSource->SetVersion(params[0]); } - params[0] = ":" + params[0]; - Utils->DoOneToAllButSender(prefix,"VERSION",params,prefix); - return true; + return CMD_SUCCESS; } |