summaryrefslogtreecommitdiff
path: root/src/modules/m_spanningtree
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/m_spanningtree')
-rw-r--r--src/modules/m_spanningtree/addline.cpp4
-rw-r--r--src/modules/m_spanningtree/away.cpp3
-rw-r--r--src/modules/m_spanningtree/cachetimer.cpp41
-rw-r--r--src/modules/m_spanningtree/cachetimer.h10
-rw-r--r--src/modules/m_spanningtree/capab.cpp70
-rw-r--r--src/modules/m_spanningtree/commands.h36
-rw-r--r--src/modules/m_spanningtree/compat.cpp293
-rw-r--r--src/modules/m_spanningtree/encap.cpp3
-rw-r--r--src/modules/m_spanningtree/fjoin.cpp253
-rw-r--r--src/modules/m_spanningtree/fmode.cpp68
-rw-r--r--src/modules/m_spanningtree/ftopic.cpp56
-rw-r--r--src/modules/m_spanningtree/hmac.cpp45
-rw-r--r--src/modules/m_spanningtree/idle.cpp95
-rw-r--r--src/modules/m_spanningtree/ijoin.cpp93
-rw-r--r--src/modules/m_spanningtree/link.h5
-rw-r--r--src/modules/m_spanningtree/main.cpp187
-rw-r--r--src/modules/m_spanningtree/main.h15
-rw-r--r--src/modules/m_spanningtree/metadata.cpp44
-rw-r--r--src/modules/m_spanningtree/netburst.cpp163
-rw-r--r--src/modules/m_spanningtree/nickcollide.cpp4
-rw-r--r--src/modules/m_spanningtree/operquit.cpp3
-rw-r--r--src/modules/m_spanningtree/opertype.cpp4
-rw-r--r--src/modules/m_spanningtree/override_map.cpp21
-rw-r--r--src/modules/m_spanningtree/override_squit.cpp1
-rw-r--r--src/modules/m_spanningtree/override_stats.cpp5
-rw-r--r--src/modules/m_spanningtree/override_whois.cpp9
-rw-r--r--src/modules/m_spanningtree/ping.cpp38
-rw-r--r--src/modules/m_spanningtree/pong.cpp42
-rw-r--r--src/modules/m_spanningtree/postcommand.cpp14
-rw-r--r--src/modules/m_spanningtree/precommand.cpp12
-rw-r--r--src/modules/m_spanningtree/protocolinterface.cpp33
-rw-r--r--src/modules/m_spanningtree/protocolinterface.h6
-rw-r--r--src/modules/m_spanningtree/push.cpp7
-rw-r--r--src/modules/m_spanningtree/rconnect.cpp32
-rw-r--r--src/modules/m_spanningtree/resolvers.cpp77
-rw-r--r--src/modules/m_spanningtree/resolvers.h28
-rw-r--r--src/modules/m_spanningtree/rsquit.cpp25
-rw-r--r--src/modules/m_spanningtree/save.cpp7
-rw-r--r--src/modules/m_spanningtree/server.cpp24
-rw-r--r--src/modules/m_spanningtree/svsjoin.cpp11
-rw-r--r--src/modules/m_spanningtree/svsnick.cpp4
-rw-r--r--src/modules/m_spanningtree/svspart.cpp6
-rw-r--r--src/modules/m_spanningtree/treeserver.cpp31
-rw-r--r--src/modules/m_spanningtree/treeserver.h26
-rw-r--r--src/modules/m_spanningtree/treesocket.h26
-rw-r--r--src/modules/m_spanningtree/treesocket1.cpp14
-rw-r--r--src/modules/m_spanningtree/treesocket2.cpp32
-rw-r--r--src/modules/m_spanningtree/uid.cpp71
-rw-r--r--src/modules/m_spanningtree/utils.cpp107
-rw-r--r--src/modules/m_spanningtree/utils.h40
-rw-r--r--src/modules/m_spanningtree/version.cpp3
51 files changed, 981 insertions, 1266 deletions
diff --git a/src/modules/m_spanningtree/addline.cpp b/src/modules/m_spanningtree/addline.cpp
index 7ee1a7ef1..a43112ce9 100644
--- a/src/modules/m_spanningtree/addline.cpp
+++ b/src/modules/m_spanningtree/addline.cpp
@@ -57,14 +57,14 @@ bool TreeSocket::AddLine(const std::string &prefix, parameterlist &params)
XLine* xl = NULL;
try
{
- xl = xlf->Generate(ServerInstance->Time(), atoi(params[4].c_str()), params[2], params[5], params[1]);
+ xl = xlf->Generate(ServerInstance->Time(), ConvToInt(params[4]), params[2], params[5], params[1]);
}
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;
}
- xl->SetCreateTime(atoi(params[3].c_str()));
+ xl->SetCreateTime(ConvToInt(params[3]));
if (ServerInstance->XLines->AddLine(xl, NULL))
{
if (xl->duration)
diff --git a/src/modules/m_spanningtree/away.cpp b/src/modules/m_spanningtree/away.cpp
index ed97c48cd..f2cabadd5 100644
--- a/src/modules/m_spanningtree/away.cpp
+++ b/src/modules/m_spanningtree/away.cpp
@@ -21,7 +21,6 @@
#include "main.h"
#include "utils.h"
-#include "treeserver.h"
#include "treesocket.h"
bool TreeSocket::Away(const std::string &prefix, parameterlist &params)
@@ -34,7 +33,7 @@ bool TreeSocket::Away(const std::string &prefix, parameterlist &params)
FOREACH_MOD(I_OnSetAway, OnSetAway(u, params[params.size() - 1]));
if (params.size() > 1)
- u->awaytime = atoi(params[0].c_str());
+ u->awaytime = ConvToInt(params[0]);
else
u->awaytime = ServerInstance->Time();
diff --git a/src/modules/m_spanningtree/cachetimer.cpp b/src/modules/m_spanningtree/cachetimer.cpp
deleted file mode 100644
index be438651d..000000000
--- a/src/modules/m_spanningtree/cachetimer.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * InspIRCd -- Internet Relay Chat Daemon
- *
- * Copyright (C) 2008 Craig Edwards <craigedwards@brainbox.cc>
- *
- * 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 "socket.h"
-#include "xline.h"
-
-#include "cachetimer.h"
-#include "main.h"
-#include "utils.h"
-#include "treeserver.h"
-#include "link.h"
-#include "treesocket.h"
-
-/* $ModDep: m_spanningtree/cachetimer.h m_spanningtree/resolvers.h m_spanningtree/main.h m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/link.h m_spanningtree/treesocket.h */
-
-CacheRefreshTimer::CacheRefreshTimer(SpanningTreeUtilities *Util) : Timer(3600, ServerInstance->Time(), true), Utils(Util)
-{
-}
-
-void CacheRefreshTimer::Tick(time_t TIME)
-{
- Utils->RefreshIPCache();
-}
-
diff --git a/src/modules/m_spanningtree/cachetimer.h b/src/modules/m_spanningtree/cachetimer.h
index bad1b7419..5d2278cd6 100644
--- a/src/modules/m_spanningtree/cachetimer.h
+++ b/src/modules/m_spanningtree/cachetimer.h
@@ -17,12 +17,8 @@
*/
-#ifndef M_SPANNINGTREE_CACHETIMER_H
-#define M_SPANNINGTREE_CACHETIMER_H
+#pragma once
-#include "timer.h"
-
-class ModuleSpanningTree;
class SpanningTreeUtilities;
/** Create a timer which recurs every second, we inherit from Timer.
@@ -35,7 +31,5 @@ class CacheRefreshTimer : public Timer
SpanningTreeUtilities *Utils;
public:
CacheRefreshTimer(SpanningTreeUtilities* Util);
- virtual void Tick(time_t TIME);
+ virtual bool Tick(time_t TIME);
};
-
-#endif
diff --git a/src/modules/m_spanningtree/capab.cpp b/src/modules/m_spanningtree/capab.cpp
index 62afe5974..fa10c79fe 100644
--- a/src/modules/m_spanningtree/capab.cpp
+++ b/src/modules/m_spanningtree/capab.cpp
@@ -20,9 +20,7 @@
#include "inspircd.h"
-#include "xline.h"
-#include "treesocket.h"
#include "treeserver.h"
#include "utils.h"
#include "link.h"
@@ -32,25 +30,19 @@ std::string TreeSocket::MyModules(int filter)
{
std::vector<std::string> modlist = ServerInstance->Modules->GetAllModuleNames(filter);
- if (filter == VF_COMMON && proto_version != ProtocolVersion)
- CompatAddModules(modlist);
-
std::string capabilities;
sort(modlist.begin(),modlist.end());
for (std::vector<std::string>::const_iterator i = modlist.begin(); i != modlist.end(); ++i)
{
if (i != modlist.begin())
- capabilities.push_back(proto_version > 1201 ? ' ' : ',');
+ capabilities.push_back(' ');
capabilities.append(*i);
Module* m = ServerInstance->Modules->Find(*i);
- if (m && proto_version > 1201)
+ Version v = m->GetVersion();
+ if (!v.link_data.empty())
{
- Version v = m->GetVersion();
- if (!v.link_data.empty())
- {
- capabilities.push_back('=');
- capabilities.append(v.link_data);
- }
+ capabilities.push_back('=');
+ capabilities.append(v.link_data);
}
}
return capabilities;
@@ -90,7 +82,7 @@ void TreeSocket::SendCapabilities(int phase)
if (phase < 2)
return;
- char sep = proto_version > 1201 ? ' ' : ',';
+ const char sep = ' ';
irc::sepstream modulelist(MyModules(VF_COMMON), sep);
irc::sepstream optmodulelist(MyModules(VF_OPTCOMMON), sep);
/* Send module names, split at 509 length */
@@ -139,8 +131,10 @@ void TreeSocket::SendCapabilities(int phase)
SetOurChallenge(ServerInstance->GenRandomStr(20));
extra = " CHALLENGE=" + this->GetOurChallenge();
}
- if (proto_version < 1202)
- extra += ServerInstance->Modes->FindMode('h', MODETYPE_CHANNEL) ? " HALFOP=1" : " HALFOP=0";
+
+ // 2.0 needs this key
+ if (proto_version == 1202)
+ extra.append(" PROTOCOL="+ConvToStr(ProtocolVersion));
this->WriteLine("CAPAB CAPABILITIES " /* Preprocessor does this one. */
":NICKMAX="+ConvToStr(ServerInstance->Config->Limits.NickMax)+
@@ -152,12 +146,11 @@ void TreeSocket::SendCapabilities(int phase)
" MAXKICK="+ConvToStr(ServerInstance->Config->Limits.MaxKick)+
" MAXGECOS="+ConvToStr(ServerInstance->Config->Limits.MaxGecos)+
" MAXAWAY="+ConvToStr(ServerInstance->Config->Limits.MaxAway)+
- " IP6SUPPORT=1"+
- " PROTOCOL="+ConvToStr(ProtocolVersion)+extra+
+ extra+
" PREFIX="+ServerInstance->Modes->BuildPrefixes()+
" CHANMODES="+ServerInstance->Modes->GiveModeList(MASK_CHANNEL)+
- " USERMODES="+ServerInstance->Modes->GiveModeList(MASK_USER)+
- " SVSPART=1");
+ " USERMODES="+ServerInstance->Modes->GiveModeList(MASK_USER)
+ );
this->WriteLine("CAPAB END");
}
@@ -202,7 +195,23 @@ bool TreeSocket::Capab(const parameterlist &params)
capab->OptModuleList.clear();
capab->CapKeys.clear();
if (params.size() > 1)
- proto_version = atoi(params[1].c_str());
+ proto_version = ConvToInt(params[1]);
+
+ if (proto_version < MinCompatProtocol)
+ {
+ SendError("CAPAB negotiation failed: Server is using protocol version " + (proto_version ? ConvToStr(proto_version) : "1201 or older")
+ + " which is too old to link with this server (version " + ConvToStr(ProtocolVersion)
+ + (ProtocolVersion != MinCompatProtocol ? ", links with " + ConvToStr(MinCompatProtocol) + " and above)" : ")"));
+ return false;
+ }
+
+ // Special case, may be removed in the future
+ if (proto_version == 1203 || proto_version == 1204)
+ {
+ SendError("CAPAB negotiation failed: InspIRCd 2.1 beta is not supported");
+ return false;
+ }
+
SendCapabilities(2);
}
else if (params[0] == "END")
@@ -212,7 +221,7 @@ bool TreeSocket::Capab(const parameterlist &params)
if ((this->capab->ModuleList != this->MyModules(VF_COMMON)) && (this->capab->ModuleList.length()))
{
std::string diffIneed, diffUneed;
- ListDifference(this->capab->ModuleList, this->MyModules(VF_COMMON), proto_version > 1201 ? ' ' : ',', diffIneed, diffUneed);
+ ListDifference(this->capab->ModuleList, this->MyModules(VF_COMMON), ' ', diffIneed, diffUneed);
if (diffIneed.length() || diffUneed.length())
{
reason = "Modules incorrectly matched on these servers.";
@@ -250,21 +259,6 @@ bool TreeSocket::Capab(const parameterlist &params)
}
}
- if (this->capab->CapKeys.find("PROTOCOL") == this->capab->CapKeys.end())
- {
- reason = "Protocol version not specified";
- }
- else
- {
- proto_version = atoi(capab->CapKeys.find("PROTOCOL")->second.c_str());
- if (proto_version < MinCompatProtocol)
- {
- reason = "Server is using protocol version " + ConvToStr(proto_version) +
- " which is too old to link with this server (version " + ConvToStr(ProtocolVersion)
- + (ProtocolVersion != MinCompatProtocol ? ", links with " + ConvToStr(MinCompatProtocol) + " and above)" : ")");
- }
- }
-
if(this->capab->CapKeys.find("PREFIX") != this->capab->CapKeys.end() && this->capab->CapKeys.find("PREFIX")->second != ServerInstance->Modes->BuildPrefixes())
reason = "One or more of the prefixes on the remote server are invalid on this server.";
@@ -348,7 +342,7 @@ bool TreeSocket::Capab(const parameterlist &params)
}
else
{
- capab->ModuleList.push_back(proto_version > 1201 ? ' ' : ',');
+ capab->ModuleList.push_back(' ');
capab->ModuleList.append(params[1]);
}
}
diff --git a/src/modules/m_spanningtree/commands.h b/src/modules/m_spanningtree/commands.h
index 3b5b499c1..dd54b5b6b 100644
--- a/src/modules/m_spanningtree/commands.h
+++ b/src/modules/m_spanningtree/commands.h
@@ -17,8 +17,7 @@
*/
-#ifndef M_SPANNINGTREE_COMMANDS_H
-#define M_SPANNINGTREE_COMMANDS_H
+#pragma once
#include "main.h"
@@ -40,7 +39,6 @@ class CommandRSQuit : public Command
CommandRSQuit(Module* Callback, SpanningTreeUtilities* Util);
CmdResult Handle (const std::vector<std::string>& parameters, User *user);
RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters);
- void NoticeUser(User* user, const std::string &msg);
};
class CommandSVSJoin : public Command
@@ -85,16 +83,19 @@ class CommandOpertype : public Command
CmdResult Handle (const std::vector<std::string>& parameters, User *user);
RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters) { return ROUTE_BROADCAST; }
};
+class TreeSocket;
class CommandFJoin : public Command
{
+ /** 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.
+ */
+ static void RemoveStatus(Channel* c);
+ 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; }
- /** 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.
- */
- void RemoveStatus(User* source, parameterlist &params);
};
class CommandFMode : public Command
{
@@ -106,7 +107,7 @@ class CommandFMode : public Command
class CommandFTopic : public Command
{
public:
- CommandFTopic(Module* Creator) : Command(Creator, "FTOPIC", 4) { flags_needed = FLAG_SERVERONLY; }
+ 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; }
};
@@ -132,6 +133,21 @@ class CommandFName : public Command
RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters) { return ROUTE_BROADCAST; }
};
+class CommandIJoin : public SplitCommand
+{
+ 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; }
+};
+
+class CommandResync : public SplitCommand
+{
+ public:
+ CommandResync(Module* Creator) : SplitCommand(Creator, "RESYNC", 1) { flags_needed = FLAG_SERVERONLY; }
+ CmdResult HandleServer(const std::vector<std::string>& parameters, FakeUser* user);
+};
+
class SpanningTreeCommands
{
public:
@@ -144,6 +160,8 @@ class SpanningTreeCommands
CommandUID uid;
CommandOpertype opertype;
CommandFJoin fjoin;
+ CommandIJoin ijoin;
+ CommandResync resync;
CommandFMode fmode;
CommandFTopic ftopic;
CommandFHost fhost;
@@ -151,5 +169,3 @@ class SpanningTreeCommands
CommandFName fname;
SpanningTreeCommands(ModuleSpanningTree* module);
};
-
-#endif
diff --git a/src/modules/m_spanningtree/compat.cpp b/src/modules/m_spanningtree/compat.cpp
index ec0cdb036..433da9847 100644
--- a/src/modules/m_spanningtree/compat.cpp
+++ b/src/modules/m_spanningtree/compat.cpp
@@ -20,104 +20,17 @@
#include "inspircd.h"
#include "main.h"
#include "treesocket.h"
+#include "treeserver.h"
-static const char* const forge_common_1201[] = {
- "m_allowinvite.so",
- "m_alltime.so",
- "m_auditorium.so",
- "m_banexception.so",
- "m_blockcaps.so",
- "m_blockcolor.so",
- "m_botmode.so",
- "m_censor.so",
- "m_chanfilter.so",
- "m_chanhistory.so",
- "m_channelban.so",
- "m_chanprotect.so",
- "m_chghost.so",
- "m_chgname.so",
- "m_commonchans.so",
- "m_customtitle.so",
- "m_deaf.so",
- "m_delayjoin.so",
- "m_delaymsg.so",
- "m_exemptchanops.so",
- "m_gecosban.so",
- "m_globops.so",
- "m_helpop.so",
- "m_hidechans.so",
- "m_hideoper.so",
- "m_invisible.so",
- "m_inviteexception.so",
- "m_joinflood.so",
- "m_kicknorejoin.so",
- "m_knock.so",
- "m_messageflood.so",
- "m_muteban.so",
- "m_nickflood.so",
- "m_nicklock.so",
- "m_noctcp.so",
- "m_nokicks.so",
- "m_nonicks.so",
- "m_nonotice.so",
- "m_nopartmsg.so",
- "m_ojoin.so",
- "m_operprefix.so",
- "m_permchannels.so",
- "m_redirect.so",
- "m_regex_glob.so",
- "m_regex_pcre.so",
- "m_regex_posix.so",
- "m_regex_tre.so",
- "m_remove.so",
- "m_sajoin.so",
- "m_sakick.so",
- "m_sanick.so",
- "m_sapart.so",
- "m_saquit.so",
- "m_serverban.so",
- "m_services_account.so",
- "m_servprotect.so",
- "m_setident.so",
- "m_showwhois.so",
- "m_silence.so",
- "m_sslmodes.so",
- "m_stripcolor.so",
- "m_swhois.so",
- "m_uninvite.so",
- "m_watch.so"
-};
-
-static std::string wide_newline("\r\n");
static std::string newline("\n");
-void TreeSocket::CompatAddModules(std::vector<std::string>& modlist)
-{
- if (proto_version < 1202)
- {
- // you MUST have chgident loaded in order to be able to translate FIDENT
- modlist.push_back("m_chgident.so");
- for(int i=0; i * sizeof(char*) < sizeof(forge_common_1201); i++)
- {
- if (ServerInstance->Modules->Find(forge_common_1201[i]))
- modlist.push_back(forge_common_1201[i]);
- }
- // module was merged
- if (ServerInstance->Modules->Find("m_operchans.so"))
- {
- modlist.push_back("m_operchans.so");
- modlist.push_back("m_operinvex.so");
- }
- }
-}
-
void TreeSocket::WriteLine(std::string line)
{
if (LinkState == CONNECTED)
{
if (line[0] != ':')
{
- ServerInstance->Logs->Log("m_spanningtree", DEFAULT, "Sending line without server prefix!");
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEFAULT, "Sending line without server prefix!");
line = ":" + ServerInstance->Config->GetSID() + " " + line;
}
if (proto_version != ProtocolVersion)
@@ -127,70 +40,172 @@ void TreeSocket::WriteLine(std::string line)
std::string command = line.substr(a + 1, b-a-1);
// now try to find a translation entry
// TODO a more efficient lookup method will be needed later
- if (proto_version < 1202 && command == "FIDENT")
- {
- ServerInstance->Logs->Log("m_spanningtree",DEBUG,"Rewriting FIDENT for 1201-protocol server");
- line = ":" + ServerInstance->Config->GetSID() + " CHGIDENT " + line.substr(1,a-1) + line.substr(b);
- }
- else if (proto_version < 1202 && command == "SAVE")
- {
- ServerInstance->Logs->Log("m_spanningtree",DEBUG,"Rewriting SAVE for 1201-protocol server");
- std::string::size_type c = line.find(' ', b + 1);
- std::string uid = line.substr(b, c - b);
- line = ":" + ServerInstance->Config->GetSID() + " SVSNICK" + uid + line.substr(b);
- }
- else if (proto_version < 1202 && command == "AWAY")
+ if (proto_version < 1205)
{
- if (b != std::string::npos)
+ if (command == "IJOIN")
{
- ServerInstance->Logs->Log("m_spanningtree",DEBUG,"Stripping AWAY timestamp for 1201-protocol server");
+ // Convert
+ // :<uid> IJOIN <chan> [<ts> [<flags>]]
+ // to
+ // :<sid> FJOIN <chan> <ts> + [<flags>],<uuid>
std::string::size_type c = line.find(' ', b + 1);
- line.erase(b,c-b);
+ if (c == std::string::npos)
+ {
+ // No TS or modes in the command
+ // :22DAAAAAB IJOIN #chan
+ const std::string channame = line.substr(b+1, c-b-1);
+ Channel* chan = ServerInstance->FindChan(channame);
+ if (!chan)
+ return;
+
+ line.push_back(' ');
+ line.append(ConvToStr(chan->age));
+ line.append(" + ,");
+ }
+ else
+ {
+ std::string::size_type d = line.find(' ', c + 1);
+ if (d == std::string::npos)
+ {
+ // TS present, no modes
+ // :22DAAAAAC IJOIN #chan 12345
+ line.append(" + ,");
+ }
+ else
+ {
+ // Both TS and modes are present
+ // :22DAAAAAC IJOIN #chan 12345 ov
+ std::string::size_type e = line.find(' ', d + 1);
+ if (e != std::string::npos)
+ line.erase(e);
+
+ line.insert(d, " +");
+ line.push_back(',');
+ }
+ }
+
+ // Move the uuid to the end and replace the I with an F
+ line.append(line.substr(1, 9));
+ line.erase(4, 6);
+ line[5] = 'F';
}
- }
- else if (proto_version < 1202 && command == "ENCAP")
- {
- // :src ENCAP target command [args...]
- // A B C D
- // Therefore B and C cannot be npos in a valid command
- if (b == std::string::npos)
+ else if (command == "RESYNC")
return;
- std::string::size_type c = line.find(' ', b + 1);
- if (c == std::string::npos)
- return;
- std::string::size_type d = line.find(' ', c + 1);
- std::string subcmd = line.substr(c + 1, d - c - 1);
-
- if (subcmd == "CHGIDENT" && d != std::string::npos)
+ else if (command == "METADATA")
{
- std::string::size_type e = line.find(' ', d + 1);
- if (e == std::string::npos)
- return; // not valid
- std::string target = line.substr(d + 1, e - d - 1);
+ // Drop TS for channel METADATA
+ // :sid METADATA #target TS extname ...
+ // A B C D
+ if (b == std::string::npos)
+ return;
- ServerInstance->Logs->Log("m_spanningtree",DEBUG,"Forging acceptance of CHGIDENT from 1201-protocol server");
- recvq.insert(0, ":" + target + " FIDENT " + line.substr(e) + "\n");
- }
+ std::string::size_type c = line.find(' ', b + 1);
+ if (c == std::string::npos)
+ return;
- Command* thiscmd = ServerInstance->Parser->GetHandler(subcmd);
- if (thiscmd && subcmd != "WHOISNOTICE")
- {
- Version ver = thiscmd->creator->GetVersion();
- if (ver.Flags & VF_OPTCOMMON)
+ if (line[b + 1] == '#')
{
- ServerInstance->Logs->Log("m_spanningtree",DEBUG,"Removing ENCAP on '%s' for 1201-protocol server",
- subcmd.c_str());
- line.erase(a, c-a);
+ // We're sending channel metadata
+ std::string::size_type d = line.find(' ', c + 1);
+ if (d == std::string::npos)
+ return;
+
+ line.erase(c, d-c);
}
}
+ else if (command == "FTOPIC")
+ {
+ // Drop channel TS for FTOPIC
+ // :sid FTOPIC #target TS TopicTS ...
+ // A B C D
+ if (b == std::string::npos)
+ return;
+
+ std::string::size_type c = line.find(' ', b + 1);
+ if (c == std::string::npos)
+ return;
+
+ std::string::size_type d = line.find(' ', c + 1);
+ if (d == std::string::npos)
+ return;
+
+ line.erase(c, d-c);
+ }
+ else if ((command == "PING") || (command == "PONG"))
+ {
+ // :22D PING 20D
+ if (line.length() < 13)
+ return;
+
+ // Insert the source SID (and a space) between the command and the first parameter
+ line.insert(10, line.substr(1, 4));
+ }
}
}
}
- ServerInstance->Logs->Log("m_spanningtree", RAWIO, "S[%d] O %s", this->GetFd(), line.c_str());
+ ServerInstance->Logs->Log("m_spanningtree", LOG_RAWIO, "S[%d] O %s", this->GetFd(), line.c_str());
this->WriteData(line);
- if (proto_version < 1202)
- this->WriteData(wide_newline);
- else
- this->WriteData(newline);
+ this->WriteData(newline);
+}
+
+namespace
+{
+ bool InsertCurrentChannelTS(std::vector<std::string>& params)
+ {
+ Channel* chan = ServerInstance->FindChan(params[0]);
+ if (!chan)
+ return false;
+
+ // Insert the current TS of the channel between the first and the second parameters
+ params.insert(params.begin()+1, ConvToStr(chan->age));
+ return true;
+ }
+}
+
+bool TreeSocket::PreProcessOldProtocolMessage(User*& who, std::string& cmd, std::vector<std::string>& params)
+{
+ if ((cmd == "METADATA") && (params.size() >= 3))
+ {
+ // :20D METADATA #channel extname :extdata
+ return InsertCurrentChannelTS(params);
+ }
+ else if ((cmd == "FTOPIC") && (params.size() >= 4))
+ {
+ // :20D FTOPIC #channel 100 Attila :topic text
+ return InsertCurrentChannelTS(params);
+ }
+ else if ((cmd == "PING") || (cmd == "PONG"))
+ {
+ if (params.size() == 1)
+ {
+ // If it's a PING with 1 parameter, reply with a PONG now, if it's a PONG with 1 parameter (weird), do nothing
+ if (cmd[1] == 'I')
+ this->WriteData(":" + ServerInstance->Config->GetSID() + " PONG " + params[0] + newline);
+
+ // Don't process this message further
+ return false;
+ }
+
+ // :20D PING 20D 22D
+ // :20D PONG 20D 22D
+ // Drop the first parameter
+ params.erase(params.begin());
+
+ // If the target is a server name, translate it to a SID
+ if (!InspIRCd::IsSID(params[0]))
+ {
+ TreeServer* server = Utils->FindServer(params[0]);
+ if (!server)
+ {
+ // We've no idea what this is, log and stop processing
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEFAULT, "Received a " + cmd + " with an unknown target: \"" + params[0] + "\", command dropped");
+ return false;
+ }
+
+ params[0] = server->GetID();
+ }
+ }
+
+ return true; // Passthru
}
diff --git a/src/modules/m_spanningtree/encap.cpp b/src/modules/m_spanningtree/encap.cpp
index dabfc086b..fedadedb5 100644
--- a/src/modules/m_spanningtree/encap.cpp
+++ b/src/modules/m_spanningtree/encap.cpp
@@ -21,7 +21,6 @@
#include "xline.h"
#include "treesocket.h"
-#include "treeserver.h"
#include "utils.h"
/** ENCAP */
@@ -35,7 +34,7 @@ void TreeSocket::Encap(User* who, parameterlist &params)
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)
diff --git a/src/modules/m_spanningtree/fjoin.cpp b/src/modules/m_spanningtree/fjoin.cpp
index c0475613a..5e58a164f 100644
--- a/src/modules/m_spanningtree/fjoin.cpp
+++ b/src/modules/m_spanningtree/fjoin.cpp
@@ -29,7 +29,7 @@
CmdResult CommandFJoin::Handle(const std::vector<std::string>& params, User *srcuser)
{
SpanningTreeUtilities* Utils = ((ModuleSpanningTree*)(Module*)creator)->Utils;
- /* 1.1 FJOIN works as follows:
+ /* 1.1+ FJOIN works as follows:
*
* Each FJOIN is sent along with a timestamp, and the side with the lowest
* timestamp 'wins'. From this point on we will refer to this side as the
@@ -54,184 +54,175 @@ CmdResult CommandFJoin::Handle(const std::vector<std::string>& params, User *src
* The winning side on the other hand will ignore all user modes from the
* losing side, so only its own modes get applied. Life is simple for those
* who succeed at internets. :-)
+ *
+ * Syntax:
+ * :<sid> FJOIN <chan> <TS> <modes> :[[modes,]<uuid> [[modes,]<uuid> ... ]]
+ * The last parameter is a list consisting of zero or more (modelist, uuid)
+ * pairs (permanent channels may have zero users). The mode list for each
+ * user is a concatenation of the mode letters the user has on the channel
+ * (e.g.: "ov" if the user is opped and voiced). The order of the mode letters
+ * are not important but if a server ecounters an unknown mode letter, it will
+ * drop the link to avoid desync.
+ *
+ * InspIRCd 2.0 and older required a comma before the uuid even if the user
+ * had no prefix modes on the channel, InspIRCd 2.2 and later does not require
+ * a comma in this case anymore.
+ *
*/
- irc::modestacker modestack(true); /* Modes to apply from the users in the user list */
- User* who = NULL; /* User we are currently checking */
- std::string channel = params[0]; /* Channel name, as a string */
- time_t TS = atoi(params[1].c_str()); /* Timestamp given to us for remote side */
- irc::tokenstream users((params.size() > 3) ? params[params.size() - 1] : ""); /* users from the user list */
- bool apply_other_sides_modes = true; /* True if we are accepting the other side's modes */
- Channel* chan = ServerInstance->FindChan(channel); /* The channel we're sending joins to */
- bool created = !chan; /* True if the channel doesnt exist here yet */
- std::string item; /* One item in the list of nicks */
-
- TreeSocket* src_socket = Utils->FindServer(srcuser->server)->GetRoute()->GetSocket();
-
+ time_t TS = ConvToInt(params[1]);
if (!TS)
{
- ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"*** BUG? *** TS of 0 sent to FJOIN. Are some services authors smoking craq, or is it 1970 again?. Dropped.");
+ ServerInstance->Logs->Log("m_spanningtree",LOG_DEFAULT,"*** BUG? *** TS of 0 sent to FJOIN. Are some services authors smoking craq, or is it 1970 again?. Dropped.");
ServerInstance->SNO->WriteToSnoMask('d', "WARNING: The server %s is sending FJOIN with a TS of zero. Total craq. Command was dropped.", srcuser->server.c_str());
return CMD_INVALID;
}
- if (created)
+ const std::string& channel = params[0];
+ Channel* chan = ServerInstance->FindChan(channel);
+ bool apply_other_sides_modes = true;
+
+ if (!chan)
{
chan = new Channel(channel, TS);
- ServerInstance->SNO->WriteToSnoMask('d', "Creation FJOIN received for %s, timestamp: %lu", chan->name.c_str(), (unsigned long)TS);
}
else
{
time_t ourTS = chan->age;
-
if (TS != ourTS)
+ {
ServerInstance->SNO->WriteToSnoMask('d', "Merge FJOIN received for %s, ourTS: %lu, TS: %lu, difference: %lu",
chan->name.c_str(), (unsigned long)ourTS, (unsigned long)TS, (unsigned long)(ourTS - TS));
- /* If our TS is less than theirs, we dont accept their modes */
- if (ourTS < TS)
- {
- ServerInstance->SNO->WriteToSnoMask('d', "NOT Applying modes from other side");
- apply_other_sides_modes = false;
- }
- else if (ourTS > TS)
- {
- /* Our TS greater than theirs, clear all our modes from the channel, accept theirs. */
- ServerInstance->SNO->WriteToSnoMask('d', "Removing our modes, accepting remote");
- parameterlist param_list;
- if (Utils->AnnounceTSChange)
- chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :TS for %s changed from %lu to %lu", chan->name.c_str(), channel.c_str(), (unsigned long) ourTS, (unsigned long) TS);
- // while the name is equal in case-insensitive compare, it might differ in case; use the remote version
- chan->name = channel;
- chan->age = TS;
- chan->ClearInvites();
- param_list.push_back(channel);
- this->RemoveStatus(ServerInstance->FakeClient, param_list);
-
- // XXX: If the channel does not exist in the chan hash at this point, create it so the remote modes can be applied on it.
- // This happens to 0-user permanent channels on the losing side, because those are removed (from the chan hash, then
- // deleted later) as soon as the permchan mode is removed from them.
- if (ServerInstance->FindChan(channel) == NULL)
+ /* If our TS is less than theirs, we dont accept their modes */
+ if (ourTS < TS)
{
- chan = new Channel(channel, TS);
+ apply_other_sides_modes = false;
+ }
+ else if (ourTS > TS)
+ {
+ /* Our TS greater than theirs, clear all our modes from the channel, accept theirs. */
+ if (Utils->AnnounceTSChange)
+ chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :TS for %s changed from %lu to %lu", chan->name.c_str(), channel.c_str(), (unsigned long) ourTS, (unsigned long) TS);
+
+ // while the name is equal in case-insensitive compare, it might differ in case; use the remote version
+ chan->name = channel;
+ chan->age = TS;
+ chan->ClearInvites();
+
+ CommandFJoin::RemoveStatus(chan);
+
+ // XXX: If the channel does not exist in the chan hash at this point, create it so the remote modes can be applied on it.
+ // This happens to 0-user permanent channels on the losing side, because those are removed (from the chan hash, then
+ // deleted later) as soon as the permchan mode is removed from them.
+ if (ServerInstance->FindChan(channel) == NULL)
+ {
+ chan = new Channel(channel, TS);
+ }
}
}
- // The silent case here is ourTS == TS, we don't need to remove modes here, just to merge them later on.
}
- /* First up, apply their modes if they won the TS war */
+ /* First up, apply their channel modes if they won the TS war */
if (apply_other_sides_modes)
{
- unsigned int idx = 2;
std::vector<std::string> modelist;
+ modelist.push_back(channel);
- // Mode parser needs to know what channel to act on.
- modelist.push_back(params[0]);
-
- /* Remember, params[params.size() - 1] is nicklist, and we don't want to apply *that* */
- for (idx = 2; idx != (params.size() - 1); idx++)
- {
- modelist.push_back(params[idx]);
- }
-
+ /* Remember, params[params.size() - 1] is userlist, and we don't want to apply *that* */
+ modelist.insert(modelist.end(), params.begin()+2, params.end()-1);
ServerInstance->SendMode(modelist, srcuser);
}
- /* Now, process every 'modes,nick' pair */
+ irc::modestacker modestack(true);
+ TreeSocket* src_socket = Utils->FindServer(srcuser->server)->GetRoute()->GetSocket();
+
+ /* Now, process every 'modes,uuid' pair */
+ irc::tokenstream users(*params.rbegin());
+ std::string item;
+ irc::modestacker* modestackptr = (apply_other_sides_modes ? &modestack : NULL);
while (users.GetToken(item))
{
- const char* usr = item.c_str();
- if (usr && *usr)
- {
- const char* unparsedmodes = usr;
- std::string modes;
-
-
- /* Iterate through all modes for this user and check they are valid. */
- while ((*unparsedmodes) && (*unparsedmodes != ','))
- {
- ModeHandler *mh = ServerInstance->Modes->FindMode(*unparsedmodes, MODETYPE_CHANNEL);
- if (!mh)
- {
- ServerInstance->Logs->Log("m_spanningtree", SPARSE, "Unrecognised mode %c, dropping link", *unparsedmodes);
- return CMD_INVALID;
- }
-
- modes += *unparsedmodes;
- usr++;
- unparsedmodes++;
- }
+ if (!ProcessModeUUIDPair(item, src_socket, chan, modestackptr))
+ return CMD_INVALID;
+ }
- /* Advance past the comma, to the nick */
- usr++;
+ /* Flush mode stacker if we lost the FJOIN or had equal TS */
+ if (apply_other_sides_modes)
+ CommandFJoin::ApplyModeStack(srcuser, chan, modestack);
- /* Check the user actually exists */
- who = ServerInstance->FindUUID(usr);
- if (who)
- {
- /* Check that the user's 'direction' is correct */
- TreeServer* route_back_again = Utils->BestRouteTo(who->server);
- if ((!route_back_again) || (route_back_again->GetSocket() != src_socket))
- continue;
+ return CMD_SUCCESS;
+}
- /* Add any modes this user had to the mode stack */
- for (std::string::iterator x = modes.begin(); x != modes.end(); ++x)
- modestack.Push(*x, who->nick);
+bool CommandFJoin::ProcessModeUUIDPair(const std::string& item, TreeSocket* src_socket, Channel* chan, irc::modestacker* modestack)
+{
+ std::string::size_type comma = item.find(',');
- Channel::JoinUser(who, channel.c_str(), true, "", route_back_again->bursting, TS);
- }
- else
- {
- ServerInstance->Logs->Log("m_spanningtree",SPARSE, "Ignored nonexistant user %s in fjoin to %s (probably quit?)", usr, channel.c_str());
- continue;
- }
- }
+ // Comma not required anymore if the user has no modes
+ std::string uuid = ((comma == std::string::npos) ? item : item.substr(comma+1));
+ User* who = ServerInstance->FindUUID(uuid);
+ if (!who)
+ {
+ // Probably KILLed, ignore
+ return true;
}
- /* Flush mode stacker if we lost the FJOIN or had equal TS */
- if (apply_other_sides_modes)
+ /* Check that the user's 'direction' is correct */
+ SpanningTreeUtilities* Utils = ((ModuleSpanningTree*)(Module*)creator)->Utils;
+ TreeServer* route_back_again = Utils->BestRouteTo(who->server);
+ if ((!route_back_again) || (route_back_again->GetSocket() != src_socket))
{
- parameterlist stackresult;
- stackresult.push_back(channel);
+ return true;
+ }
- while (modestack.GetStackedLine(stackresult))
+ /* Check if the user received at least one mode */
+ if ((modestack) && (comma > 0) && (comma != std::string::npos))
+ {
+ /* Iterate through the modes and see if they are valid here, if so, apply */
+ std::string::const_iterator commait = item.begin()+comma;
+ for (std::string::const_iterator i = item.begin(); i != commait; ++i)
{
- ServerInstance->SendMode(stackresult, srcuser);
- stackresult.erase(stackresult.begin() + 1, stackresult.end());
+ if (!ServerInstance->Modes->FindMode(*i, MODETYPE_CHANNEL))
+ {
+ ServerInstance->SNO->WriteToSnoMask('d', "Unrecognised mode '%c' for a user in FJOIN, dropping link", *i);
+ return false;
+ }
+
+ /* Add any modes this user had to the mode stack */
+ modestack->Push(*i, who->nick);
}
}
- return CMD_SUCCESS;
+
+ chan->ForceJoin(who, NULL, route_back_again->bursting);
+ return true;
}
-void CommandFJoin::RemoveStatus(User* srcuser, parameterlist &params)
+void CommandFJoin::RemoveStatus(Channel* c)
{
- if (params.size() < 1)
- return;
-
- Channel* c = ServerInstance->FindChan(params[0]);
+ irc::modestacker stack(false);
- if (c)
+ for (char modeletter = 'A'; modeletter <= 'z'; ++modeletter)
{
- irc::modestacker stack(false);
- parameterlist stackresult;
- stackresult.push_back(c->name);
+ ModeHandler* mh = ServerInstance->Modes->FindMode(modeletter, MODETYPE_CHANNEL);
+
+ /* Passing a pointer to a modestacker here causes the mode to be put onto the mode stack,
+ * rather than applied immediately. Module unloads require this to be done immediately,
+ * for this function we require tidyness instead. Fixes bug #493
+ */
+ if (mh)
+ mh->RemoveMode(c, &stack);
+ }
- for (char modeletter = 'A'; modeletter <= 'z'; ++modeletter)
- {
- ModeHandler* mh = ServerInstance->Modes->FindMode(modeletter, MODETYPE_CHANNEL);
-
- /* Passing a pointer to a modestacker here causes the mode to be put onto the mode stack,
- * rather than applied immediately. Module unloads require this to be done immediately,
- * for this function we require tidyness instead. Fixes bug #493
- */
- if (mh)
- mh->RemoveMode(c, &stack);
- }
+ ApplyModeStack(ServerInstance->FakeClient, c, stack);
+}
- while (stack.GetStackedLine(stackresult))
- {
- ServerInstance->SendMode(stackresult, srcuser);
- stackresult.erase(stackresult.begin() + 1, stackresult.end());
- }
+void CommandFJoin::ApplyModeStack(User* srcuser, Channel* c, irc::modestacker& stack)
+{
+ parameterlist stackresult;
+ stackresult.push_back(c->name);
+
+ while (stack.GetStackedLine(stackresult))
+ {
+ ServerInstance->SendMode(stackresult, srcuser);
+ stackresult.erase(stackresult.begin() + 1, stackresult.end());
}
}
-
diff --git a/src/modules/m_spanningtree/fmode.cpp b/src/modules/m_spanningtree/fmode.cpp
index c1e452db6..a91803384 100644
--- a/src/modules/m_spanningtree/fmode.cpp
+++ b/src/modules/m_spanningtree/fmode.cpp
@@ -21,66 +21,50 @@
#include "inspircd.h"
#include "commands.h"
-#include "treesocket.h"
-#include "treeserver.h"
-#include "utils.h"
-
/** FMODE command - server mode with timestamp checks */
CmdResult CommandFMode::Handle(const std::vector<std::string>& params, User *who)
{
- std::string sourceserv = who->server;
-
- std::vector<std::string> modelist;
- time_t TS = 0;
- for (unsigned int q = 0; (q < params.size()) && (q < 64); q++)
+ time_t TS = ConvToInt(params[1]);
+ if (!TS)
{
- if (q == 1)
- {
- /* The timestamp is in this position.
- * We don't want to pass that up to the
- * server->client protocol!
- */
- TS = atoi(params[q].c_str());
- }
- else
- {
- /* Everything else is fine to append to the modelist */
- modelist.push_back(params[q]);
- }
-
+ ServerInstance->Logs->Log("m_spanningtree",LOG_DEFAULT,"*** BUG? *** TS of 0 sent to FMODE. Are some services authors smoking craq, or is it 1970 again?. Dropping link.");
+ ServerInstance->SNO->WriteToSnoMask('d', "WARNING: The server %s is sending FMODE with a TS of zero. Total craq, dropping link.", who->server.c_str());
+ return CMD_INVALID;
}
- /* Extract the TS value of the object, either User or Channel */
- User* dst = ServerInstance->FindNick(params[0]);
- Channel* chan = NULL;
- time_t ourTS = 0;
- if (dst)
+ /* Extract the TS value of the object, either User or Channel */
+ time_t ourTS;
+ if (params[0][0] == '#')
{
- ourTS = dst->age;
+ Channel* chan = ServerInstance->FindChan(params[0]);
+ if (!chan)
+ /* Oops, channel doesn't exist! */
+ return CMD_FAILURE;
+
+ ourTS = chan->age;
}
else
{
- chan = ServerInstance->FindChan(params[0]);
- if (chan)
- {
- ourTS = chan->age;
- }
- else
- /* Oops, channel doesnt exist! */
+ User* user = ServerInstance->FindUUID(params[0]);
+ if (!user)
return CMD_FAILURE;
- }
- if (!TS)
- {
- ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"*** BUG? *** TS of 0 sent to FMODE. Are some services authors smoking craq, or is it 1970 again?. Dropped.");
- ServerInstance->SNO->WriteToSnoMask('d', "WARNING: The server %s is sending FMODE with a TS of zero. Total craq. Mode was dropped.", sourceserv.c_str());
- return CMD_INVALID;
+ if (IS_SERVER(user))
+ return CMD_INVALID;
+
+ ourTS = user->age;
}
/* TS is equal or less: Merge the mode changes into ours and pass on.
*/
if (TS <= ourTS)
{
+ std::vector<std::string> modelist;
+ modelist.reserve(params.size()-1);
+ /* Insert everything into modelist except the TS (params[1]) */
+ modelist.push_back(params[0]);
+ modelist.insert(modelist.end(), params.begin()+2, params.end());
+
bool merge = (TS == ourTS) && IS_SERVER(who);
ServerInstance->Modes->Process(modelist, who, merge);
return CMD_SUCCESS;
diff --git a/src/modules/m_spanningtree/ftopic.cpp b/src/modules/m_spanningtree/ftopic.cpp
index d559c6ae5..69d3af565 100644
--- a/src/modules/m_spanningtree/ftopic.cpp
+++ b/src/modules/m_spanningtree/ftopic.cpp
@@ -21,31 +21,49 @@
#include "inspircd.h"
#include "commands.h"
-#include "treesocket.h"
-#include "treeserver.h"
-#include "utils.h"
-
/** FTOPIC command */
CmdResult CommandFTopic::Handle(const std::vector<std::string>& params, User *user)
{
- time_t ts = atoi(params[1].c_str());
Channel* c = ServerInstance->FindChan(params[0]);
- if (c)
+ if (!c)
+ return CMD_FAILURE;
+
+ time_t ChanTS = ConvToInt(params[1]);
+ if (!ChanTS)
+ return CMD_INVALID;
+
+ if (c->age < ChanTS)
+ // Our channel TS is older, nothing to do
+ return CMD_FAILURE;
+
+ time_t ts = ConvToInt(params[2]);
+ if (!ts)
+ return CMD_INVALID;
+
+ // Channel::topicset is initialized to 0 on channel creation, so their ts will always win if we never had a topic
+ if (ts < c->topicset)
+ return CMD_FAILURE;
+
+ /*
+ * If the topics were updated at the exact same second, accept
+ * the remote only when it's "bigger" than ours as defined by
+ * string comparision, so non-empty topics always overridde
+ * empty topics if their timestamps are equal
+ */
+ if ((ts == c->topicset) && (c->topic > params[4]))
+ return CMD_FAILURE; // Topics were set at the exact same time, keep our topic and setter
+
+ if (c->topic != params[4])
{
- if ((ts >= c->topicset) || (c->topic.empty()))
- {
- if (c->topic != params[3])
- {
- // Update topic only when it differs from current topic
- c->topic.assign(params[3], 0, ServerInstance->Config->Limits.MaxTopic);
- c->WriteChannel(user, "TOPIC %s :%s", c->name.c_str(), c->topic.c_str());
- }
-
- // Always update setter and settime.
- c->setby.assign(params[2], 0, 127);
- c->topicset = ts;
- }
+ // Update topic only when it differs from current topic
+ c->topic.assign(params[4], 0, ServerInstance->Config->Limits.MaxTopic);
+ c->WriteChannel(user, "TOPIC %s :%s", c->name.c_str(), c->topic.c_str());
}
+
+ // Update setter and settime
+ c->setby.assign(params[3], 0, 127);
+ c->topicset = ts;
+
return CMD_SUCCESS;
}
diff --git a/src/modules/m_spanningtree/hmac.cpp b/src/modules/m_spanningtree/hmac.cpp
index d990e1fbf..b7c952797 100644
--- a/src/modules/m_spanningtree/hmac.cpp
+++ b/src/modules/m_spanningtree/hmac.cpp
@@ -19,18 +19,12 @@
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "../hash.h"
-#include "../ssl.h"
-#include "socketengine.h"
+#include "modules/hash.h"
+#include "modules/ssl.h"
#include "main.h"
-#include "utils.h"
-#include "treeserver.h"
#include "link.h"
#include "treesocket.h"
-#include "resolvers.h"
const std::string& TreeSocket::GetOurChallenge()
{
@@ -62,39 +56,10 @@ std::string TreeSocket::MakePass(const std::string &password, const std::string
*/
HashProvider* sha256 = ServerInstance->Modules->FindDataService<HashProvider>("hash/sha256");
if (Utils->ChallengeResponse && sha256 && !challenge.empty())
- {
- if (proto_version < 1202)
- {
- /* This is how HMAC is done in InspIRCd 1.2:
- *
- * sha256( (pass xor 0x5c) + sha256((pass xor 0x36) + m) )
- *
- * 5c and 36 were chosen as part of the HMAC standard, because they
- * flip the bits in a way likely to strengthen the function.
- */
- std::string hmac1, hmac2;
-
- for (size_t n = 0; n < password.length(); n++)
- {
- hmac1.push_back(static_cast<char>(password[n] ^ 0x5C));
- hmac2.push_back(static_cast<char>(password[n] ^ 0x36));
- }
-
- hmac2.append(challenge);
- hmac2 = sha256->hexsum(hmac2);
-
- std::string hmac = hmac1 + hmac2;
- hmac = sha256->hexsum(hmac);
+ return "AUTH:" + BinToBase64(sha256->hmac(password, challenge));
- return "HMAC-SHA256:"+ hmac;
- }
- else
- {
- return "AUTH:" + BinToBase64(sha256->hmac(password, challenge));
- }
- }
- else if (!challenge.empty() && !sha256)
- ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Not authenticating to server using SHA256/HMAC because we don't have m_sha256 loaded!");
+ if (!challenge.empty() && !sha256)
+ ServerInstance->Logs->Log("m_spanningtree",LOG_DEFAULT,"Not authenticating to server using SHA256/HMAC because we don't have m_sha256 loaded!");
return password;
}
diff --git a/src/modules/m_spanningtree/idle.cpp b/src/modules/m_spanningtree/idle.cpp
index 8bc0cd2bb..bf074bf7f 100644
--- a/src/modules/m_spanningtree/idle.cpp
+++ b/src/modules/m_spanningtree/idle.cpp
@@ -18,67 +18,56 @@
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "socketengine.h"
-
-#include "main.h"
#include "utils.h"
-#include "treeserver.h"
#include "treesocket.h"
bool TreeSocket::Whois(const std::string &prefix, parameterlist &params)
{
if (params.size() < 1)
return true;
- User* u = ServerInstance->FindNick(prefix);
- if (u)
+
+ /* 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 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;
+
+ LocalUser* localtarget = IS_LOCAL(target);
+ if (!localtarget)
{
- // an incoming request
- if (params.size() == 1)
- {
- User* x = ServerInstance->FindNick(params[0]);
- if ((x) && (IS_LOCAL(x)))
- {
- long idle = abs((long)((x->idle_lastmsg) - ServerInstance->Time()));
- parameterlist par;
- par.push_back(prefix);
- par.push_back(ConvToStr(x->signon));
- par.push_back(ConvToStr(idle));
- // ours, we're done, pass it BACK
- Utils->DoOneToOne(params[0], "IDLE", par, u->server);
- }
- else
- {
- // not ours pass it on
- if (x)
- Utils->DoOneToOne(prefix, "IDLE", params, x->server);
- }
- }
- else if (params.size() == 3)
- {
- std::string who_did_the_whois = params[0];
- User* who_to_send_to = ServerInstance->FindNick(who_did_the_whois);
- if ((who_to_send_to) && (IS_LOCAL(who_to_send_to)))
- {
- // an incoming reply to a whois we sent out
- std::string nick_whoised = prefix;
- unsigned long signon = atoi(params[1].c_str());
- unsigned long idle = atoi(params[2].c_str());
- if ((who_to_send_to) && (IS_LOCAL(who_to_send_to)))
- {
- ServerInstance->DoWhois(who_to_send_to, u, signon, idle, nick_whoised.c_str());
- }
- }
- else
- {
- // not ours, pass it on
- if (who_to_send_to)
- Utils->DoOneToOne(prefix, "IDLE", params, who_to_send_to->server);
- }
- }
+ // Forward to target's server
+ Utils->DoOneToOne(prefix, "IDLE", params, target->server);
+ return true;
}
- return true;
-}
+ if (params.size() >= 2)
+ {
+ ServerInstance->Parser->CallHandler("WHOIS", params, issuer);
+ }
+ else
+ {
+ // A server is asking us the idle time of our user
+ unsigned int idle;
+ if (localtarget->idle_lastmsg >= ServerInstance->Time())
+ // Possible case when our clock ticked backwards
+ idle = 0;
+ else
+ idle = ((unsigned int) (localtarget->idle_lastmsg - ServerInstance->Time()));
+
+ parameterlist reply;
+ reply.push_back(prefix);
+ reply.push_back(ConvToStr(target->signon));
+ reply.push_back(ConvToStr(idle));
+ Utils->DoOneToOne(params[0], "IDLE", reply, issuer->server);
+ }
+ return true;
+}
diff --git a/src/modules/m_spanningtree/ijoin.cpp b/src/modules/m_spanningtree/ijoin.cpp
new file mode 100644
index 000000000..2f71ffe27
--- /dev/null
+++ b/src/modules/m_spanningtree/ijoin.cpp
@@ -0,0 +1,93 @@
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 2012-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 "commands.h"
+#include "utils.h"
+#include "treeserver.h"
+#include "treesocket.h"
+
+CmdResult CommandIJoin::HandleRemote(const std::vector<std::string>& params, RemoteUser* user)
+{
+ Channel* chan = ServerInstance->FindChan(params[0]);
+ if (!chan)
+ {
+ // Desync detected, recover
+ // Ignore the join and send RESYNC, this will result in the remote server sending all channel data to us
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEBUG, "Received IJOIN for non-existant channel: " + params[0]);
+
+ parameterlist p;
+ p.push_back(params[0]);
+ SpanningTreeUtilities* Utils = ((ModuleSpanningTree*)(Module*)creator)->Utils;
+ Utils->DoOneToOne(ServerInstance->Config->GetSID(), "RESYNC", p, user->server);
+
+ return CMD_FAILURE;
+ }
+
+ bool apply_modes;
+ if (params.size() > 1)
+ {
+ time_t RemoteTS = ConvToInt(params[1]);
+ if (!RemoteTS)
+ {
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEFAULT, "Invalid TS in IJOIN: " + params[1]);
+ return CMD_INVALID;
+ }
+
+ if (RemoteTS < chan->age)
+ {
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEFAULT, "Attempted to lower TS via IJOIN. Channel=" + params[0] + " RemoteTS=" + params[1] + " LocalTS=" + ConvToStr(chan->age));
+ return CMD_INVALID;
+ }
+ apply_modes = ((params.size() > 2) && (RemoteTS == chan->age));
+ }
+ else
+ apply_modes = false;
+
+ chan->ForceJoin(user, apply_modes ? &params[2] : NULL);
+ return CMD_SUCCESS;
+}
+
+CmdResult CommandResync::HandleServer(const std::vector<std::string>& params, FakeUser* user)
+{
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEBUG, "Resyncing " + params[0]);
+ Channel* chan = ServerInstance->FindChan(params[0]);
+ if (!chan)
+ {
+ // This can happen for a number of reasons, safe to ignore
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEBUG, "Channel does not exist");
+ return CMD_FAILURE;
+ }
+
+ SpanningTreeUtilities* Utils = ((ModuleSpanningTree*)(Module*)creator)->Utils;
+ TreeServer* server = Utils->FindServer(user->server);
+ if (!server)
+ return CMD_FAILURE;
+
+ TreeSocket* socket = server->GetSocket();
+ if (!socket)
+ {
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEFAULT, "Received RESYNC with a source that is not directly connected: " + user->uuid);
+ return CMD_INVALID;
+ }
+
+ // Send all known information about the channel
+ socket->SyncChannel(chan);
+ return CMD_SUCCESS;
+}
diff --git a/src/modules/m_spanningtree/link.h b/src/modules/m_spanningtree/link.h
index 797f108d8..b318c9bf2 100644
--- a/src/modules/m_spanningtree/link.h
+++ b/src/modules/m_spanningtree/link.h
@@ -18,8 +18,7 @@
*/
-#ifndef M_SPANNINGTREE_LINK_H
-#define M_SPANNINGTREE_LINK_H
+#pragma once
class Link : public refcountbase
{
@@ -51,5 +50,3 @@ class Autoconnect : public refcountbase
int position;
Autoconnect(ConfigTag* Tag) : tag(Tag) {}
};
-
-#endif
diff --git a/src/modules/m_spanningtree/main.cpp b/src/modules/m_spanningtree/main.cpp
index fdb9ef200..1fa7ef76b 100644
--- a/src/modules/m_spanningtree/main.cpp
+++ b/src/modules/m_spanningtree/main.cpp
@@ -27,7 +27,6 @@
#include "socket.h"
#include "xline.h"
-#include "cachetimer.h"
#include "resolvers.h"
#include "main.h"
#include "utils.h"
@@ -38,22 +37,22 @@
#include "protocolinterface.h"
ModuleSpanningTree::ModuleSpanningTree()
+ : commands(NULL), DNS(this, "DNS"), Utils(NULL)
{
- Utils = new SpanningTreeUtilities(this);
- commands = new SpanningTreeCommands(this);
- RefreshTimer = NULL;
}
SpanningTreeCommands::SpanningTreeCommands(ModuleSpanningTree* module)
: rconnect(module, module->Utils), rsquit(module, module->Utils),
svsjoin(module), svspart(module), svsnick(module), metadata(module),
- uid(module), opertype(module), fjoin(module), fmode(module), ftopic(module),
- fhost(module), fident(module), fname(module)
+ uid(module), opertype(module), fjoin(module), ijoin(module), resync(module),
+ fmode(module), ftopic(module), fhost(module), fident(module), fname(module)
{
}
void ModuleSpanningTree::init()
{
+ Utils = new SpanningTreeUtilities(this);
+ commands = new SpanningTreeCommands(this);
ServerInstance->Modules->AddService(commands->rconnect);
ServerInstance->Modules->AddService(commands->rsquit);
ServerInstance->Modules->AddService(commands->svsjoin);
@@ -63,13 +62,13 @@ void ModuleSpanningTree::init()
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);
- RefreshTimer = new CacheRefreshTimer(Utils);
- ServerInstance->Timers->AddTimer(RefreshTimer);
Implementation eventlist[] =
{
@@ -87,7 +86,7 @@ void ModuleSpanningTree::init()
loopCall = false;
// update our local user count
- Utils->TreeRoot->SetUserCount(ServerInstance->Users->local_users.size());
+ Utils->TreeRoot->UserCount = ServerInstance->Users->local_users.size();
}
void ModuleSpanningTree::ShowLinks(TreeServer* Current, User* user, int hops)
@@ -101,7 +100,7 @@ void ModuleSpanningTree::ShowLinks(TreeServer* Current, User* user, int hops)
{
if ((Current->GetChild(q)->Hidden) || ((Utils->HideULines) && (ServerInstance->ULine(Current->GetChild(q)->GetName()))))
{
- if (IS_OPER(user))
+ if (user->IsOper())
{
ShowLinks(Current->GetChild(q),user,hops+1);
}
@@ -112,16 +111,16 @@ void ModuleSpanningTree::ShowLinks(TreeServer* Current, User* user, int hops)
}
}
/* Don't display the line if its a uline, hide ulines is on, and the user isnt an oper */
- if ((Utils->HideULines) && (ServerInstance->ULine(Current->GetName())) && (!IS_OPER(user)))
+ if ((Utils->HideULines) && (ServerInstance->ULine(Current->GetName())) && (!user->IsOper()))
return;
/* Or if the server is hidden and they're not an oper */
- else if ((Current->Hidden) && (!IS_OPER(user)))
+ else if ((Current->Hidden) && (!user->IsOper()))
return;
std::string servername = Current->GetName();
user->WriteNumeric(364, "%s %s %s :%d %s", user->nick.c_str(), servername.c_str(),
- (Utils->FlatLinks && (!IS_OPER(user))) ? ServerInstance->Config->ServerName.c_str() : Parent.c_str(),
- (Utils->FlatLinks && (!IS_OPER(user))) ? 0 : hops,
+ (Utils->FlatLinks && (!user->IsOper())) ? ServerInstance->Config->ServerName.c_str() : Parent.c_str(),
+ (Utils->FlatLinks && (!user->IsOper())) ? 0 : hops,
Current->GetDesc().c_str());
}
@@ -194,8 +193,7 @@ restart:
// ... if we can find a proper route to them
if (tsock)
{
- tsock->WriteLine(":" + ServerInstance->Config->GetSID() + " PING " +
- ServerInstance->Config->GetSID() + " " + s->GetID());
+ tsock->WriteLine(":" + ServerInstance->Config->GetSID() + " PING " + s->GetID());
s->LastPingMsec = ts;
}
}
@@ -271,8 +269,7 @@ void ModuleSpanningTree::ConnectServer(Link* x, Autoconnect* y)
return;
}
- QueryType start_type = DNS_QUERY_A;
- start_type = DNS_QUERY_AAAA;
+ DNS::QueryType start_type = DNS::QUERY_AAAA;
if (strchr(x->IPAddr.c_str(),':'))
{
in6_addr n;
@@ -302,16 +299,20 @@ void ModuleSpanningTree::ConnectServer(Link* x, Autoconnect* y)
ServerInstance->GlobalCulls.AddItem(newsocket);
}
}
+ else if (!DNS)
+ {
+ ServerInstance->SNO->WriteToSnoMask('l', "CONNECT: Error connecting \002%s\002: Hostname given and m_dns.so is not loaded, unable to resolve.", x->Name.c_str());
+ }
else
{
+ ServernameResolver* snr = new ServernameResolver(Utils, *DNS, x->IPAddr, x, start_type, y);
try
{
- bool cached = false;
- ServernameResolver* snr = new ServernameResolver(Utils, x->IPAddr, x, cached, start_type, y);
- ServerInstance->AddResolver(snr, cached);
+ DNS->Process(snr);
}
- catch (ModuleException& e)
+ catch (DNS::Exception& e)
{
+ delete snr;
ServerInstance->SNO->WriteToSnoMask('l', "CONNECT: Error connecting \002%s\002: %s.",x->Name.c_str(), e.GetReason());
ConnectServer(y, false);
}
@@ -360,12 +361,13 @@ ModResult ModuleSpanningTree::HandleVersion(const std::vector<std::string>& para
TreeServer* found = Utils->FindServerMask(parameters[0]);
if (found)
{
- std::string Version = found->GetVersion();
- user->WriteNumeric(351, "%s :%s",user->nick.c_str(),Version.c_str());
if (found == Utils->TreeRoot)
{
- ServerInstance->Config->Send005(user);
+ // Pass to default VERSION handler.
+ return MOD_RES_PASSTHRU;
}
+ std::string Version = found->GetVersion();
+ user->WriteNumeric(351, "%s :%s",user->nick.c_str(),Version.c_str());
}
else
{
@@ -466,108 +468,45 @@ void ModuleSpanningTree::OnWallops(User* user, const std::string &text)
}
}
-void ModuleSpanningTree::OnUserNotice(User* user, void* dest, int target_type, const std::string &text, char status, const CUList &exempt_list)
+void ModuleSpanningTree::LocalMessage(User* user, void* dest, int target_type, const std::string &text, char status, const CUList &exempt_list, const char* message_type)
{
- /* Server origin */
- if (user == NULL)
+ /* Server or remote origin, dest should always be non-null */
+ if ((!user) || (!IS_LOCAL(user)) || (!dest))
return;
if (target_type == TYPE_USER)
{
- User* d = (User*)dest;
- if (!IS_LOCAL(d) && IS_LOCAL(user))
+ User* d = (User*) dest;
+ if (!IS_LOCAL(d))
{
parameterlist params;
params.push_back(d->uuid);
params.push_back(":"+text);
- Utils->DoOneToOne(user->uuid,"NOTICE",params,d->server);
+ Utils->DoOneToOne(user->uuid, message_type, params, d->server);
}
}
else if (target_type == TYPE_CHANNEL)
{
- if (IS_LOCAL(user))
- {
- Channel *c = (Channel*)dest;
- if (c)
- {
- std::string cname = c->name;
- if (status)
- cname = status + cname;
- TreeServerList list;
- Utils->GetListOfServersForChannel(c,list,status,exempt_list);
- for (TreeServerList::iterator i = list.begin(); i != list.end(); i++)
- {
- TreeSocket* Sock = i->second->GetSocket();
- if (Sock)
- Sock->WriteLine(":"+std::string(user->uuid)+" NOTICE "+cname+" :"+text);
- }
- }
- }
+ Utils->SendChannelMessage(user->uuid, (Channel*)dest, text, status, exempt_list, message_type);
}
else if (target_type == TYPE_SERVER)
{
- if (IS_LOCAL(user))
- {
- char* target = (char*)dest;
- parameterlist par;
- par.push_back(target);
- par.push_back(":"+text);
- Utils->DoOneToMany(user->uuid,"NOTICE",par);
- }
+ char* target = (char*) dest;
+ parameterlist par;
+ par.push_back(target);
+ par.push_back(":"+text);
+ Utils->DoOneToMany(user->uuid, message_type, par);
}
}
-void ModuleSpanningTree::OnUserMessage(User* user, void* dest, int target_type, const std::string &text, char status, const CUList &exempt_list)
+void ModuleSpanningTree::OnUserNotice(User* user, void* dest, int target_type, const std::string &text, char status, const CUList &exempt_list)
{
- /* Server origin */
- if (user == NULL)
- return;
+ LocalMessage(user, dest, target_type, text, status, exempt_list, "NOTICE");
+}
- if (target_type == TYPE_USER)
- {
- // route private messages which are targetted at clients only to the server
- // which needs to receive them
- User* d = (User*)dest;
- if (!IS_LOCAL(d) && (IS_LOCAL(user)))
- {
- parameterlist params;
- params.push_back(d->uuid);
- params.push_back(":"+text);
- Utils->DoOneToOne(user->uuid,"PRIVMSG",params,d->server);
- }
- }
- else if (target_type == TYPE_CHANNEL)
- {
- if (IS_LOCAL(user))
- {
- Channel *c = (Channel*)dest;
- if (c)
- {
- std::string cname = c->name;
- if (status)
- cname = status + cname;
- TreeServerList list;
- Utils->GetListOfServersForChannel(c,list,status,exempt_list);
- for (TreeServerList::iterator i = list.begin(); i != list.end(); i++)
- {
- TreeSocket* Sock = i->second->GetSocket();
- if (Sock)
- Sock->WriteLine(":"+std::string(user->uuid)+" PRIVMSG "+cname+" :"+text);
- }
- }
- }
- }
- else if (target_type == TYPE_SERVER)
- {
- if (IS_LOCAL(user))
- {
- char* target = (char*)dest;
- parameterlist par;
- par.push_back(target);
- par.push_back(":"+text);
- Utils->DoOneToMany(user->uuid,"PRIVMSG",par);
- }
- }
+void ModuleSpanningTree::OnUserMessage(User* user, void* dest, int target_type, const std::string &text, char status, const CUList &exempt_list)
+{
+ LocalMessage(user, dest, target_type, text, status, exempt_list, "PRIVMSG");
}
void ModuleSpanningTree::OnBackgroundTimer(time_t curtime)
@@ -595,7 +534,7 @@ void ModuleSpanningTree::OnUserConnect(LocalUser* user)
params.push_back(":"+user->fullname);
Utils->DoOneToMany(ServerInstance->Config->GetSID(), "UID", params);
- if (IS_OPER(user))
+ if (user->IsOper())
{
params.clear();
params.push_back(user->oper->name);
@@ -610,23 +549,32 @@ void ModuleSpanningTree::OnUserConnect(LocalUser* user)
ServerInstance->PI->SendMetaData(user, item->name, value);
}
- Utils->TreeRoot->SetUserCount(1); // increment by 1
+ Utils->TreeRoot->UserCount++;
}
-void ModuleSpanningTree::OnUserJoin(Membership* memb, bool sync, bool created, CUList& excepts)
+void ModuleSpanningTree::OnUserJoin(Membership* memb, bool sync, bool created_by_local, CUList& excepts)
{
// Only do this for local users
if (IS_LOCAL(memb->user))
{
parameterlist params;
- // set up their permissions and the channel TS with FJOIN.
- // All users are FJOINed now, because a module may specify
- // new joining permissions for the user.
params.push_back(memb->chan->name);
- params.push_back(ConvToStr(memb->chan->age));
- params.push_back(std::string("+") + memb->chan->ChanModes(true));
- params.push_back(memb->modes+","+memb->user->uuid);
- Utils->DoOneToMany(ServerInstance->Config->GetSID(),"FJOIN",params);
+ if (created_by_local)
+ {
+ params.push_back(ConvToStr(memb->chan->age));
+ params.push_back(std::string("+") + memb->chan->ChanModes(true));
+ params.push_back(memb->modes+","+memb->user->uuid);
+ Utils->DoOneToMany(ServerInstance->Config->GetSID(),"FJOIN",params);
+ }
+ else
+ {
+ if (!memb->modes.empty())
+ {
+ params.push_back(ConvToStr(memb->chan->age));
+ params.push_back(memb->modes);
+ }
+ Utils->DoOneToMany(memb->user->uuid, "IJOIN", params);
+ }
}
}
@@ -693,7 +641,7 @@ void ModuleSpanningTree::OnUserQuit(User* user, const std::string &reason, const
TreeServer* SourceServer = Utils->FindServer(user->server);
if (SourceServer)
{
- SourceServer->SetUserCount(-1); // decrement by 1
+ SourceServer->UserCount--;
}
}
@@ -757,7 +705,7 @@ void ModuleSpanningTree::OnPreRehash(User* user, const std::string &parameter)
if (loopCall)
return; // Don't generate a REHASH here if we're in the middle of processing a message that generated this one
- ServerInstance->Logs->Log("remoterehash", DEBUG, "called with param %s", parameter.c_str());
+ ServerInstance->Logs->Log("remoterehash", LOG_DEBUG, "called with param %s", parameter.c_str());
// Send out to other servers
if (!parameter.empty() && parameter[0] != '-')
@@ -950,7 +898,7 @@ void ModuleSpanningTree::ProtoSendMetaData(void* opaque, Extensible* target, con
if (u)
s->WriteLine(":"+ServerInstance->Config->GetSID()+" METADATA "+u->uuid+" "+extname+" :"+extdata);
else if (c)
- s->WriteLine(":"+ServerInstance->Config->GetSID()+" METADATA "+c->name+" "+extname+" :"+extdata);
+ s->WriteLine(":"+ServerInstance->Config->GetSID()+" METADATA "+c->name+" "+ConvToStr(c->age)+" "+extname+" :"+extdata);
else if (!target)
s->WriteLine(":"+ServerInstance->Config->GetSID()+" METADATA * "+extname+" :"+extdata);
}
@@ -958,7 +906,6 @@ void ModuleSpanningTree::ProtoSendMetaData(void* opaque, Extensible* target, con
CullResult ModuleSpanningTree::cull()
{
Utils->cull();
- ServerInstance->Timers->DelTimer(RefreshTimer);
return this->Module::cull();
}
diff --git a/src/modules/m_spanningtree/main.h b/src/modules/m_spanningtree/main.h
index ae6e2e602..3ff369ea6 100644
--- a/src/modules/m_spanningtree/main.h
+++ b/src/modules/m_spanningtree/main.h
@@ -21,12 +21,11 @@
*/
-#ifndef M_SPANNINGTREE_MAIN_H
-#define M_SPANNINGTREE_MAIN_H
+#pragma once
#include "inspircd.h"
-#include <stdarg.h>
+#include "modules/dns.h"
/** If you make a change which breaks the protocol, increment this.
* If you completely change the protocol, completely change the number.
*
@@ -36,8 +35,8 @@
* Failure to document your protocol changes will result in a painfully
* painful death by pain. You have been warned.
*/
-const long ProtocolVersion = 1202;
-const long MinCompatProtocol = 1201;
+const long ProtocolVersion = 1205;
+const long MinCompatProtocol = 1202;
/** Forward declarations
*/
@@ -53,11 +52,13 @@ class Autoconnect;
class ModuleSpanningTree : public Module
{
SpanningTreeCommands* commands;
+ void LocalMessage(User* user, void* dest, int target_type, const std::string &text, char status, const CUList &exempt_list, const char* message_type);
public:
+ dynamic_reference<DNS::Manager> DNS;
+
SpanningTreeUtilities* Utils;
- CacheRefreshTimer *RefreshTimer;
/** Set to true if inside a spanningtree call, to prevent sending
* xlines and other things back to their source
*/
@@ -178,5 +179,3 @@ class ModuleSpanningTree : public Module
Version GetVersion();
void Prioritize();
};
-
-#endif
diff --git a/src/modules/m_spanningtree/metadata.cpp b/src/modules/m_spanningtree/metadata.cpp
index a584f8fa8..9709ca54c 100644
--- a/src/modules/m_spanningtree/metadata.cpp
+++ b/src/modules/m_spanningtree/metadata.cpp
@@ -21,33 +21,49 @@
#include "inspircd.h"
#include "commands.h"
-#include "treesocket.h"
-#include "treeserver.h"
-#include "utils.h"
-
CmdResult CommandMetadata::Handle(const std::vector<std::string>& params, User *srcuser)
{
- std::string value = params.size() < 3 ? "" : params[2];
- ExtensionItem* item = ServerInstance->Extensions.GetItem(params[1]);
if (params[0] == "*")
{
+ std::string value = params.size() < 3 ? "" : params[2];
FOREACH_MOD(I_OnDecodeMetaData,OnDecodeMetaData(NULL,params[1],value));
+ return CMD_SUCCESS;
}
- else if (*(params[0].c_str()) == '#')
+
+ if (params[0][0] == '#')
{
+ // Channel METADATA has an additional parameter: the channel TS
+ // :22D METADATA #channel 12345 extname :extdata
+ if (params.size() < 3)
+ return CMD_INVALID;
+
Channel* c = ServerInstance->FindChan(params[0]);
- if (c)
- {
- if (item)
- item->unserialize(FORMAT_NETWORK, c, value);
- FOREACH_MOD(I_OnDecodeMetaData,OnDecodeMetaData(c,params[1],value));
- }
+ if (!c)
+ return CMD_FAILURE;
+
+ time_t ChanTS = ConvToInt(params[1]);
+ if (!ChanTS)
+ return CMD_INVALID;
+
+ if (c->age < ChanTS)
+ // Their TS is newer than ours, discard this command and do not propagate
+ return CMD_FAILURE;
+
+ std::string value = params.size() < 4 ? "" : params[3];
+
+ ExtensionItem* item = ServerInstance->Extensions.GetItem(params[2]);
+ if (item)
+ item->unserialize(FORMAT_NETWORK, c, value);
+ FOREACH_MOD(I_OnDecodeMetaData,OnDecodeMetaData(c,params[2],value));
}
- else if (*(params[0].c_str()) != '#')
+ else
{
User* u = ServerInstance->FindUUID(params[0]);
if ((u) && (!IS_SERVER(u)))
{
+ ExtensionItem* item = ServerInstance->Extensions.GetItem(params[1]);
+ std::string value = params.size() < 3 ? "" : params[2];
+
if (item)
item->unserialize(FORMAT_NETWORK, u, value);
FOREACH_MOD(I_OnDecodeMetaData,OnDecodeMetaData(u,params[1],value));
diff --git a/src/modules/m_spanningtree/netburst.cpp b/src/modules/m_spanningtree/netburst.cpp
index 5248ea897..21404e68e 100644
--- a/src/modules/m_spanningtree/netburst.cpp
+++ b/src/modules/m_spanningtree/netburst.cpp
@@ -21,10 +21,10 @@
#include "inspircd.h"
#include "xline.h"
+#include "listmode.h"
#include "treesocket.h"
#include "treeserver.h"
-#include "utils.h"
#include "main.h"
/** This function is called when we want to send a netburst to a local
@@ -44,27 +44,27 @@ void TreeSocket::DoBurst(TreeServer* s)
/* send our version string */
this->WriteLine(":" + ServerInstance->Config->GetSID() + " VERSION :"+ServerInstance->GetVersionString());
/* Send server tree */
- this->SendServers(Utils->TreeRoot,s,1);
+ this->SendServers(Utils->TreeRoot, s);
/* Send users and their oper status */
this->SendUsers();
- /* Send everything else (channel modes, xlines etc) */
- this->SendChannelModes();
+
+ for (chan_hash::const_iterator i = ServerInstance->chanlist->begin(); i != ServerInstance->chanlist->end(); ++i)
+ SyncChannel(i->second);
+
this->SendXLines();
FOREACH_MOD(I_OnSyncNetwork,OnSyncNetwork(Utils->Creator,(void*)this));
this->WriteLine(":" + ServerInstance->Config->GetSID() + " ENDBURST");
ServerInstance->SNO->WriteToSnoMask('l',"Finished bursting to \2"+ s->GetName()+"\2.");
}
-/** Recursively send the server tree with distances as hops.
+/** Recursively send the server tree.
* This is used during network burst to inform the other server
* (and any of ITS servers too) of what servers we know about.
* If at any point any of these servers already exist on the other
- * end, our connection may be terminated. The hopcounts given
- * by this function are relative, this doesn't matter so long as
- * they are all >1, as all the remote servers re-calculate them
- * to be relative too, with themselves as hop 0.
+ * end, our connection may be terminated.
+ * The hopcount parameter (3rd) is deprecated, and is always 0.
*/
-void TreeSocket::SendServers(TreeServer* Current, TreeServer* s, int hops)
+void TreeSocket::SendServers(TreeServer* Current, TreeServer* s)
{
char command[MAXBUF];
for (unsigned int q = 0; q < Current->ChildCount(); q++)
@@ -73,13 +73,13 @@ void TreeSocket::SendServers(TreeServer* Current, TreeServer* s, int hops)
if (recursive_server != s)
{
std::string recursive_servername = recursive_server->GetName();
- snprintf(command, MAXBUF, ":%s SERVER %s * %d %s :%s", Current->GetID().c_str(), recursive_servername.c_str(), hops,
+ snprintf(command, MAXBUF, ":%s SERVER %s * 0 %s :%s", Current->GetID().c_str(), recursive_servername.c_str(),
recursive_server->GetID().c_str(),
recursive_server->GetDesc().c_str());
this->WriteLine(command);
this->WriteLine(":"+recursive_server->GetID()+" VERSION :"+recursive_server->GetVersion());
/* down to next level */
- this->SendServers(recursive_server, s, hops+1);
+ this->SendServers(recursive_server, s);
}
}
}
@@ -87,101 +87,49 @@ void TreeSocket::SendServers(TreeServer* Current, TreeServer* s, int hops)
/** 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.
+ * Send one or more FMODEs for a channel with the
+ * channel bans, if there's any.
*/
void TreeSocket::SendFJoins(Channel* c)
{
- std::string buffer;
- char list[MAXBUF];
-
- size_t curlen, headlen;
- curlen = headlen = snprintf(list,MAXBUF,":%s FJOIN %s %lu +%s :",
- ServerInstance->Config->GetSID().c_str(), c->name.c_str(), (unsigned long)c->age, c->ChanModes(true));
- int numusers = 0;
- char* ptr = list + curlen;
- bool looped_once = false;
+ std::string line(":");
+ line.append(ServerInstance->Config->GetSID()).append(" FJOIN ").append(c->name).append(1, ' ').append(ConvToStr(c->age)).append(" +");
+ std::string::size_type erase_from = line.length();
+ line.append(c->ChanModes(true)).append(" :");
const UserMembList *ulist = c->GetUsers();
- std::string modes;
- std::string params;
-
- for (UserMembCIter i = ulist->begin(); i != ulist->end(); i++)
- {
- size_t ptrlen = 0;
- std::string modestr = i->second->modes;
-
- if ((curlen + modestr.length() + i->first->uuid.length() + 4) > 480)
- {
- // remove the final space
- if (ptr[-1] == ' ')
- ptr[-1] = '\0';
- buffer.append(list).append("\r\n");
- curlen = headlen;
- ptr = list + headlen;
- numusers = 0;
- }
-
- ptrlen = snprintf(ptr, MAXBUF-curlen, "%s,%s ", modestr.c_str(), i->first->uuid.c_str());
-
- looped_once = true;
-
- curlen += ptrlen;
- ptr += ptrlen;
-
- numusers++;
- }
-
- // Okay, permanent channels will (of course) need this \r\n anyway, numusers check is if there
- // actually were people in the channel (looped_once == true)
- if (!looped_once || numusers > 0)
- {
- // remove the final space
- if (ptr[-1] == ' ')
- ptr[-1] = '\0';
- buffer.append(list).append("\r\n");
- }
- int linesize = 1;
- for (BanList::iterator b = c->bans.begin(); b != c->bans.end(); b++)
+ for (UserMembCIter i = ulist->begin(); i != ulist->end(); ++i)
{
- int size = b->data.length() + 2;
- int currsize = linesize + size;
- if (currsize <= 350)
- {
- modes.append("b");
- params.append(" ").append(b->data);
- linesize += size;
- }
- if ((modes.length() >= ServerInstance->Config->Limits.MaxModes) || (currsize > 350))
+ const std::string& modestr = i->second->modes;
+ if ((line.length() + modestr.length() + UIDGenerator::UUID_LENGTH + 2) > 480)
{
- /* Wrap at MAXMODES */
- buffer.append(":").append(ServerInstance->Config->GetSID()).append(" FMODE ").append(c->name).append(" ").append(ConvToStr(c->age)).append(" +").append(modes).append(params).append("\r\n");
- modes.clear();
- params.clear();
- linesize = 1;
+ this->WriteLine(line);
+ line.erase(erase_from);
+ line.append(" :");
}
+ line.append(modestr).append(1, ',').append(i->first->uuid).push_back(' ');
}
+ this->WriteLine(line);
- /* Only send these if there are any */
- if (!modes.empty())
- buffer.append(":").append(ServerInstance->Config->GetSID()).append(" FMODE ").append(c->name).append(" ").append(ConvToStr(c->age)).append(" +").append(modes).append(params);
-
- this->WriteLine(buffer);
+ ModeReference ban(NULL, "ban");
+ static_cast<ListModeBase*>(*ban)->DoSyncChannel(c, Utils->Creator, this);
}
/** Send all XLines we know about */
void TreeSocket::SendXLines()
{
char data[MAXBUF];
- std::string n = ServerInstance->Config->GetSID();
- const char* sn = n.c_str();
+ const char* sn = ServerInstance->Config->GetSID().c_str();
std::vector<std::string> types = ServerInstance->XLines->GetAllTypes();
- time_t current = ServerInstance->Time();
- for (std::vector<std::string>::iterator it = types.begin(); it != types.end(); ++it)
+ for (std::vector<std::string>::const_iterator it = types.begin(); it != types.end(); ++it)
{
+ /* Expired lines are removed in XLineManager::GetAll() */
XLineLookup* lookup = ServerInstance->XLines->GetAll(*it);
+ /* lookup cannot be NULL in this case but a check won't hurt */
if (lookup)
{
for (LookupIter i = lookup->begin(); i != lookup->end(); ++i)
@@ -192,11 +140,6 @@ void TreeSocket::SendXLines()
if (!i->second->IsBurstable())
break;
- /* If it's expired, don't bother to burst it
- */
- if (i->second->duration && current > i->second->expiry)
- continue;
-
snprintf(data,MAXBUF,":%s ADDLINE %s %s %s %lu %lu :%s",sn, it->c_str(), i->second->Displayable(),
i->second->source.c_str(),
(unsigned long)i->second->set_time,
@@ -209,31 +152,29 @@ void TreeSocket::SendXLines()
}
/** Send channel topic, modes and metadata */
-void TreeSocket::SendChannelModes()
+void TreeSocket::SyncChannel(Channel* chan)
{
char data[MAXBUF];
- std::string n = ServerInstance->Config->GetSID();
- const char* sn = n.c_str();
- for (chan_hash::iterator c = ServerInstance->chanlist->begin(); c != ServerInstance->chanlist->end(); c++)
- {
- SendFJoins(c->second);
- if (!c->second->topic.empty())
- {
- snprintf(data,MAXBUF,":%s FTOPIC %s %lu %s :%s", sn, c->second->name.c_str(), (unsigned long)c->second->topicset, c->second->setby.c_str(), c->second->topic.c_str());
- this->WriteLine(data);
- }
+ SendFJoins(chan);
- for(Extensible::ExtensibleStore::const_iterator i = c->second->GetExtList().begin(); i != c->second->GetExtList().end(); i++)
- {
- ExtensionItem* item = i->first;
- std::string value = item->serialize(FORMAT_NETWORK, c->second, i->second);
- if (!value.empty())
- Utils->Creator->ProtoSendMetaData(this, c->second, item->name, value);
- }
+ // If the topic was ever set, send it, even if it's empty now
+ // because a new empty topic should override an old non-empty topic
+ if (chan->topicset != 0)
+ {
+ snprintf(data,MAXBUF,":%s FTOPIC %s %lu %lu %s :%s", ServerInstance->Config->GetSID().c_str(), chan->name.c_str(), (unsigned long) chan->age, (unsigned long)chan->topicset, chan->setby.c_str(), chan->topic.c_str());
+ this->WriteLine(data);
+ }
- FOREACH_MOD(I_OnSyncChannel,OnSyncChannel(c->second,Utils->Creator,this));
+ for (Extensible::ExtensibleStore::const_iterator i = chan->GetExtList().begin(); i != chan->GetExtList().end(); i++)
+ {
+ ExtensionItem* item = i->first;
+ std::string value = item->serialize(FORMAT_NETWORK, chan, i->second);
+ if (!value.empty())
+ Utils->Creator->ProtoSendMetaData(this, chan, item->name, value);
}
+
+ FOREACH_MOD(I_OnSyncChannel,OnSyncChannel(chan, Utils->Creator, this));
}
/** send all users and their oper state/modes */
@@ -256,17 +197,17 @@ void TreeSocket::SendUsers()
u->second->host.c_str(), /* 3: Displayed Host */
u->second->dhost.c_str(), /* 4: Real host */
u->second->ident.c_str(), /* 5: Ident */
- u->second->GetIPString(), /* 6: IP string */
+ u->second->GetIPString().c_str(), /* 6: IP string */
(unsigned long)u->second->signon, /* 7: Signon time for WHOWAS */
u->second->FormatModes(true), /* 8...n: Modes and params */
u->second->fullname.c_str()); /* size-1: GECOS */
this->WriteLine(data);
- if (IS_OPER(u->second))
+ if (u->second->IsOper())
{
snprintf(data,MAXBUF,":%s OPERTYPE %s", u->second->uuid.c_str(), u->second->oper->name.c_str());
this->WriteLine(data);
}
- if (IS_AWAY(u->second))
+ if (u->second->IsAway())
{
snprintf(data,MAXBUF,":%s AWAY %ld :%s", u->second->uuid.c_str(), (long)u->second->awaytime, u->second->awaymsg.c_str());
this->WriteLine(data);
diff --git a/src/modules/m_spanningtree/nickcollide.cpp b/src/modules/m_spanningtree/nickcollide.cpp
index 38d59affb..6d9aa0ee9 100644
--- a/src/modules/m_spanningtree/nickcollide.cpp
+++ b/src/modules/m_spanningtree/nickcollide.cpp
@@ -19,13 +19,11 @@
#include "inspircd.h"
-#include "xline.h"
#include "treesocket.h"
-#include "treeserver.h"
#include "utils.h"
-/* $ModDep: m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/treesocket.h */
+/* $ModDep: m_spanningtree/utils.h m_spanningtree/treesocket.h */
/*
diff --git a/src/modules/m_spanningtree/operquit.cpp b/src/modules/m_spanningtree/operquit.cpp
index af2e04ebc..634a0845a 100644
--- a/src/modules/m_spanningtree/operquit.cpp
+++ b/src/modules/m_spanningtree/operquit.cpp
@@ -18,10 +18,7 @@
#include "inspircd.h"
-#include "xline.h"
-
#include "treesocket.h"
-#include "treeserver.h"
#include "utils.h"
/* $ModDep: m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/treesocket.h */
diff --git a/src/modules/m_spanningtree/opertype.cpp b/src/modules/m_spanningtree/opertype.cpp
index 97a4de8c2..4772e9222 100644
--- a/src/modules/m_spanningtree/opertype.cpp
+++ b/src/modules/m_spanningtree/opertype.cpp
@@ -29,8 +29,8 @@
CmdResult CommandOpertype::Handle(const std::vector<std::string>& params, User *u)
{
SpanningTreeUtilities* Utils = ((ModuleSpanningTree*)(Module*)creator)->Utils;
- std::string opertype = params[0];
- if (!IS_OPER(u))
+ const std::string& opertype = params[0];
+ if (!u->IsOper())
ServerInstance->Users->all_opers.push_back(u);
u->modes[UM_OPERATOR] = 1;
OperIndex::iterator iter = ServerInstance->Config->oper_blocks.find(" " + opertype);
diff --git a/src/modules/m_spanningtree/override_map.cpp b/src/modules/m_spanningtree/override_map.cpp
index 04fa4bcab..123a83718 100644
--- a/src/modules/m_spanningtree/override_map.cpp
+++ b/src/modules/m_spanningtree/override_map.cpp
@@ -19,16 +19,13 @@
*/
-/* $ModDesc: Provides a spanning tree server link protocol */
-
#include "inspircd.h"
#include "main.h"
#include "utils.h"
#include "treeserver.h"
-#include "treesocket.h"
-/* $ModDep: m_spanningtree/main.h m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/treesocket.h */
+/* $ModDep: m_spanningtree/main.h m_spanningtree/utils.h m_spanningtree/treeserver.h */
const std::string ModuleSpanningTree::MapOperInfo(TreeServer* Current)
{
@@ -38,7 +35,7 @@ const std::string ModuleSpanningTree::MapOperInfo(TreeServer* Current)
void ModuleSpanningTree::ShowMap(TreeServer* Current, User* user, int depth, int &line, char* names, int &maxnamew, char* stats)
{
- ServerInstance->Logs->Log("map",DEBUG,"ShowMap depth %d on line %d", depth, line);
+ ServerInstance->Logs->Log("map",LOG_DEBUG,"ShowMap depth %d on line %d", depth, line);
float percent;
if (ServerInstance->Users->clientlist->size() == 0)
@@ -48,10 +45,10 @@ void ModuleSpanningTree::ShowMap(TreeServer* Current, User* user, int depth, int
}
else
{
- percent = Current->GetUserCount() * 100.0 / ServerInstance->Users->clientlist->size();
+ percent = Current->UserCount * 100.0 / ServerInstance->Users->clientlist->size();
}
- const std::string operdata = IS_OPER(user) ? MapOperInfo(Current) : "";
+ const std::string operdata = user->IsOper() ? MapOperInfo(Current) : "";
char* myname = names + 100 * line;
char* mystat = stats + 50 * line;
@@ -59,7 +56,7 @@ void ModuleSpanningTree::ShowMap(TreeServer* Current, User* user, int depth, int
int w = depth;
std::string servername = Current->GetName();
- if (IS_OPER(user))
+ if (user->IsOper())
{
w += snprintf(myname + depth, 99 - depth, "%s (%s)", servername.c_str(), Current->GetID().c_str());
}
@@ -70,16 +67,16 @@ void ModuleSpanningTree::ShowMap(TreeServer* Current, User* user, int depth, int
memset(myname + w, ' ', 100 - w);
if (w > maxnamew)
maxnamew = w;
- snprintf(mystat, 49, "%5d [%5.2f%%]%s", Current->GetUserCount(), percent, operdata.c_str());
+ snprintf(mystat, 49, "%5d [%5.2f%%]%s", Current->UserCount, percent, operdata.c_str());
line++;
- if (IS_OPER(user) || !Utils->FlatLinks)
+ if (user->IsOper() || !Utils->FlatLinks)
depth = depth + 2;
for (unsigned int q = 0; q < Current->ChildCount(); q++)
{
TreeServer* child = Current->GetChild(q);
- if (!IS_OPER(user)) {
+ if (!user->IsOper()) {
if (child->Hidden)
continue;
if ((Utils->HideULines) && (ServerInstance->ULine(child->GetName())))
@@ -174,7 +171,7 @@ bool ModuleSpanningTree::HandleMap(const std::vector<std::string>& parameters, U
float avg_users = totusers * 1.0 / line;
- ServerInstance->Logs->Log("map",DEBUG,"local");
+ ServerInstance->Logs->Log("map",LOG_DEBUG,"local");
for (int t = 0; t < line; t++)
{
// terminate the string at maxnamew characters
diff --git a/src/modules/m_spanningtree/override_squit.cpp b/src/modules/m_spanningtree/override_squit.cpp
index 7d01c8149..c8151cbdf 100644
--- a/src/modules/m_spanningtree/override_squit.cpp
+++ b/src/modules/m_spanningtree/override_squit.cpp
@@ -21,7 +21,6 @@
#include "inspircd.h"
#include "socket.h"
-#include "xline.h"
#include "main.h"
#include "utils.h"
diff --git a/src/modules/m_spanningtree/override_stats.cpp b/src/modules/m_spanningtree/override_stats.cpp
index 688661b80..9762ecf4e 100644
--- a/src/modules/m_spanningtree/override_stats.cpp
+++ b/src/modules/m_spanningtree/override_stats.cpp
@@ -18,16 +18,11 @@
*/
-/* $ModDesc: Provides a spanning tree server link protocol */
-
#include "inspircd.h"
-#include "socket.h"
#include "main.h"
#include "utils.h"
-#include "treeserver.h"
#include "link.h"
-#include "treesocket.h"
ModResult ModuleSpanningTree::OnStats(char statschar, User* user, string_list &results)
{
diff --git a/src/modules/m_spanningtree/override_whois.cpp b/src/modules/m_spanningtree/override_whois.cpp
index ad8c6a6ef..45a7399bf 100644
--- a/src/modules/m_spanningtree/override_whois.cpp
+++ b/src/modules/m_spanningtree/override_whois.cpp
@@ -16,19 +16,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
-/* $ModDesc: Provides a spanning tree server link protocol */
-
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
#include "main.h"
#include "utils.h"
-#include "treeserver.h"
-#include "treesocket.h"
-/* $ModDep: m_spanningtree/main.h m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/treesocket.h */
+/* $ModDep: m_spanningtree/main.h m_spanningtree/utils.h */
ModResult ModuleSpanningTree::HandleRemoteWhois(const std::vector<std::string>& parameters, User* user)
{
diff --git a/src/modules/m_spanningtree/ping.cpp b/src/modules/m_spanningtree/ping.cpp
index aec680b23..badcc3401 100644
--- a/src/modules/m_spanningtree/ping.cpp
+++ b/src/modules/m_spanningtree/ping.cpp
@@ -18,44 +18,34 @@
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "socketengine.h"
-#include "main.h"
#include "utils.h"
-#include "treeserver.h"
#include "treesocket.h"
-/* $ModDep: m_spanningtree/main.h m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/treesocket.h */
+/* $ModDep: m_spanningtree/utils.h m_spanningtree/treesocket.h */
bool TreeSocket::LocalPing(const std::string &prefix, parameterlist &params)
{
if (params.size() < 1)
return true;
- if (params.size() == 1)
+
+ const std::string& forwardto = params[0];
+ if (forwardto == ServerInstance->Config->GetSID())
{
- std::string stufftobounce = params[0];
- this->WriteLine(":"+ServerInstance->Config->GetSID()+" PONG "+stufftobounce);
- return true;
+ // PING for us, reply with a PONG
+ std::string reply = ":" + forwardto + " PONG " + prefix;
+ if (params.size() >= 2)
+ // If there is a second parameter, append it
+ reply.append(" :").append(params[1]);
+
+ this->WriteLine(reply);
}
else
{
- std::string forwardto = params[1];
- if (forwardto == ServerInstance->Config->ServerName || forwardto == ServerInstance->Config->GetSID())
- {
- // this is a ping for us, send back PONG to the requesting server
- params[1] = params[0];
- params[0] = forwardto;
- Utils->DoOneToOne(ServerInstance->Config->GetSID(),"PONG",params,params[1]);
- }
- else
- {
- // not for us, pass it on :)
- Utils->DoOneToOne(prefix,"PING",params,forwardto);
- }
- return true;
+ // not for us, pass it on :)
+ Utils->DoOneToOne(prefix,"PING",params,forwardto);
}
+ return true;
}
diff --git a/src/modules/m_spanningtree/pong.cpp b/src/modules/m_spanningtree/pong.cpp
index 5966d05d9..daf53096d 100644
--- a/src/modules/m_spanningtree/pong.cpp
+++ b/src/modules/m_spanningtree/pong.cpp
@@ -18,11 +18,7 @@
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "socketengine.h"
-#include "main.h"
#include "utils.h"
#include "treeserver.h"
#include "treesocket.h"
@@ -34,49 +30,23 @@ bool TreeSocket::LocalPong(const std::string &prefix, parameterlist &params)
if (params.size() < 1)
return true;
- if (params.size() == 1)
+ const std::string& forwardto = params[0];
+ if (forwardto == ServerInstance->Config->GetSID())
{
+ // PONG for us
TreeServer* ServerSource = Utils->FindServer(prefix);
if (ServerSource)
{
- ServerSource->SetPingFlag();
long ts = ServerInstance->Time() * 1000 + (ServerInstance->Time_ns() / 1000000);
ServerSource->rtt = ts - ServerSource->LastPingMsec;
+ ServerSource->SetPingFlag();
}
}
else
{
- std::string forwardto = params[1];
- if (forwardto == ServerInstance->Config->GetSID() || forwardto == ServerInstance->Config->ServerName)
- {
- /*
- * this is a PONG for us
- * if the prefix is a user, check theyre local, and if they are,
- * dump the PONG reply back to their fd. If its a server, do nowt.
- * Services might want to send these s->s, but we dont need to yet.
- */
- User* u = ServerInstance->FindNick(prefix);
- if (u)
- {
- u->WriteServ("PONG %s %s",params[0].c_str(),params[1].c_str());
- }
-
- TreeServer *ServerSource = Utils->FindServer(params[0]);
-
- if (ServerSource)
- {
- long ts = ServerInstance->Time() * 1000 + (ServerInstance->Time_ns() / 1000000);
- ServerSource->rtt = ts - ServerSource->LastPingMsec;
- ServerSource->SetPingFlag();
- }
- }
- else
- {
- // not for us, pass it on :)
- Utils->DoOneToOne(prefix,"PONG",params,forwardto);
- }
+ // not for us, pass it on :)
+ Utils->DoOneToOne(prefix,"PONG",params,forwardto);
}
-
return true;
}
diff --git a/src/modules/m_spanningtree/postcommand.cpp b/src/modules/m_spanningtree/postcommand.cpp
index 471bbfcb9..c10bccaf9 100644
--- a/src/modules/m_spanningtree/postcommand.cpp
+++ b/src/modules/m_spanningtree/postcommand.cpp
@@ -17,19 +17,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
-/* $ModDesc: Provides a spanning tree server link protocol */
-
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
#include "main.h"
#include "utils.h"
#include "treeserver.h"
-#include "treesocket.h"
-/* $ModDep: m_spanningtree/main.h m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/treesocket.h */
+/* $ModDep: m_spanningtree/main.h m_spanningtree/utils.h m_spanningtree/treeserver.h */
void ModuleSpanningTree::OnPostCommand(const std::string &command, const std::vector<std::string>& parameters, LocalUser *user, CmdResult result, const std::string &original_line)
{
@@ -73,7 +67,7 @@ void SpanningTreeUtilities::RouteCommand(TreeServer* origin, const std::string &
TreeServer* sdest = FindServer(routing.serverdest);
if (!sdest)
{
- ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Trying to route ENCAP to nonexistant server %s",
+ ServerInstance->Logs->Log("m_spanningtree",LOG_DEFAULT,"Trying to route ENCAP to nonexistant server %s",
routing.serverdest.c_str());
return;
}
@@ -88,7 +82,7 @@ void SpanningTreeUtilities::RouteCommand(TreeServer* origin, const std::string &
if (!(ver.Flags & (VF_COMMON | VF_CORE)) && srcmodule != Creator)
{
- ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Routed command %s from non-VF_COMMON module %s",
+ ServerInstance->Logs->Log("m_spanningtree",LOG_DEFAULT,"Routed command %s from non-VF_COMMON module %s",
command.c_str(), srcmodule->ModuleSourceFile.c_str());
return;
}
@@ -121,7 +115,7 @@ void SpanningTreeUtilities::RouteCommand(TreeServer* origin, const std::string &
data += " " + params[x];
for (TreeServerList::iterator i = list.begin(); i != list.end(); i++)
{
- TreeSocket* Sock = i->second->GetSocket();
+ TreeSocket* Sock = (*i)->GetSocket();
if (origin && origin->GetSocket() == Sock)
continue;
if (Sock)
diff --git a/src/modules/m_spanningtree/precommand.cpp b/src/modules/m_spanningtree/precommand.cpp
index b331571ca..428e6ab28 100644
--- a/src/modules/m_spanningtree/precommand.cpp
+++ b/src/modules/m_spanningtree/precommand.cpp
@@ -18,18 +18,11 @@
*/
-/* $ModDesc: Provides a spanning tree server link protocol */
-
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
#include "main.h"
-#include "utils.h"
-#include "treeserver.h"
-#include "treesocket.h"
-/* $ModDep: m_spanningtree/main.h m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/treesocket.h */
+/* $ModDep: m_spanningtree/main.h */
ModResult ModuleSpanningTree::OnPreCommand(std::string &command, std::vector<std::string>& parameters, LocalUser *user, bool validated, const std::string &original_line)
{
@@ -64,8 +57,7 @@ ModResult ModuleSpanningTree::OnPreCommand(std::string &command, std::vector<std
}
else if ((command == "VERSION") && (parameters.size() > 0))
{
- this->HandleVersion(parameters,user);
- return MOD_RES_DENY;
+ return this->HandleVersion(parameters,user);
}
return MOD_RES_PASSTHRU;
}
diff --git a/src/modules/m_spanningtree/protocolinterface.cpp b/src/modules/m_spanningtree/protocolinterface.cpp
index 3ab5dae9d..93a138758 100644
--- a/src/modules/m_spanningtree/protocolinterface.cpp
+++ b/src/modules/m_spanningtree/protocolinterface.cpp
@@ -19,10 +19,8 @@
#include "inspircd.h"
-#include "main.h"
#include "utils.h"
#include "treeserver.h"
-#include "treesocket.h"
#include "protocolinterface.h"
/*
@@ -38,8 +36,8 @@ void SpanningTreeProtocolInterface::GetServerList(ProtoServerList &sl)
ps.servername = i->second->GetName();
TreeServer* s = i->second->GetParent();
ps.parentname = s ? s->GetName() : "";
- ps.usercount = i->second->GetUserCount();
- ps.opercount = i->second->GetOperCount();
+ ps.usercount = i->second->UserCount;
+ ps.opercount = i->second->OperCount;
ps.gecos = i->second->GetDesc();
ps.latencyms = i->second->rtt;
sl.push_back(ps);
@@ -65,7 +63,10 @@ void SpanningTreeProtocolInterface::SendMetaData(Extensible* target, const std::
if (u)
params.push_back(u->uuid);
else if (c)
+ {
params.push_back(c->name);
+ params.push_back(ConvToStr(c->age));
+ }
else
params.push_back("*");
@@ -80,6 +81,7 @@ void SpanningTreeProtocolInterface::SendTopic(Channel* channel, std::string &top
parameterlist params;
params.push_back(channel->name);
+ params.push_back(ConvToStr(channel->age));
params.push_back(ConvToStr(ServerInstance->Time()));
params.push_back(ServerInstance->Config->ServerName);
params.push_back(":" + topic);
@@ -135,31 +137,16 @@ void SpanningTreeProtocolInterface::PushToClient(User* target, const std::string
Utils->DoOneToOne(ServerInstance->Config->GetSID(), "PUSH", p, target->server);
}
-void SpanningTreeProtocolInterface::SendChannel(Channel* target, char status, const std::string &text)
-{
- std::string cname = target->name;
- if (status)
- cname = status + cname;
- TreeServerList list;
- CUList exempt_list;
- Utils->GetListOfServersForChannel(target,list,status,exempt_list);
- for (TreeServerList::iterator i = list.begin(); i != list.end(); i++)
- {
- TreeSocket* Sock = i->second->GetSocket();
- if (Sock)
- Sock->WriteLine(text);
- }
-}
-
-
void SpanningTreeProtocolInterface::SendChannelPrivmsg(Channel* target, char status, const std::string &text)
{
- SendChannel(target, status, ":" + ServerInstance->Config->GetSID()+" PRIVMSG "+target->name+" :"+text);
+ CUList exempt_list;
+ Utils->SendChannelMessage(ServerInstance->Config->GetSID(), target, text, status, exempt_list, "PRIVMSG");
}
void SpanningTreeProtocolInterface::SendChannelNotice(Channel* target, char status, const std::string &text)
{
- SendChannel(target, status, ":" + ServerInstance->Config->GetSID()+" NOTICE "+target->name+" :"+text);
+ CUList exempt_list;
+ Utils->SendChannelMessage(ServerInstance->Config->GetSID(), target, text, status, exempt_list, "NOTICE");
}
void SpanningTreeProtocolInterface::SendUserPrivmsg(User* target, const std::string &text)
diff --git a/src/modules/m_spanningtree/protocolinterface.h b/src/modules/m_spanningtree/protocolinterface.h
index 297366893..2757db8da 100644
--- a/src/modules/m_spanningtree/protocolinterface.h
+++ b/src/modules/m_spanningtree/protocolinterface.h
@@ -17,8 +17,7 @@
*/
-#ifndef M_SPANNINGTREE_PROTOCOLINTERFACE_H
-#define M_SPANNINGTREE_PROTOCOLINTERFACE_H
+#pragma once
class SpanningTreeUtilities;
class ModuleSpanningTree;
@@ -43,6 +42,3 @@ class SpanningTreeProtocolInterface : public ProtocolInterface
virtual void SendUserNotice(User* target, const std::string &text);
virtual void GetServerList(ProtoServerList &sl);
};
-
-#endif
-
diff --git a/src/modules/m_spanningtree/push.cpp b/src/modules/m_spanningtree/push.cpp
index b791376ea..496a711bf 100644
--- a/src/modules/m_spanningtree/push.cpp
+++ b/src/modules/m_spanningtree/push.cpp
@@ -18,16 +18,11 @@
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "socketengine.h"
-#include "main.h"
#include "utils.h"
-#include "treeserver.h"
#include "treesocket.h"
-/* $ModDep: m_spanningtree/main.h m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/treesocket.h */
+/* $ModDep: m_spanningtree/utils.h m_spanningtree/treesocket.h */
bool TreeSocket::Push(const std::string &prefix, parameterlist &params)
{
diff --git a/src/modules/m_spanningtree/rconnect.cpp b/src/modules/m_spanningtree/rconnect.cpp
index d4254cac6..ec925c0ca 100644
--- a/src/modules/m_spanningtree/rconnect.cpp
+++ b/src/modules/m_spanningtree/rconnect.cpp
@@ -19,15 +19,9 @@
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "resolvers.h"
#include "main.h"
#include "utils.h"
-#include "treeserver.h"
-#include "link.h"
-#include "treesocket.h"
#include "commands.h"
CommandRConnect::CommandRConnect (Module* Creator, SpanningTreeUtilities* Util)
@@ -39,14 +33,11 @@ CommandRConnect::CommandRConnect (Module* Creator, SpanningTreeUtilities* Util)
CmdResult CommandRConnect::Handle (const std::vector<std::string>& parameters, User *user)
{
- if (IS_LOCAL(user))
+ /* First see if the server which is being asked to connect to another server in fact exists */
+ if (!Utils->FindServerMask(parameters[0]))
{
- if (!Utils->FindServerMask(parameters[0]))
- {
- user->WriteServ("NOTICE %s :*** RCONNECT: Server \002%s\002 isn't connected to the network!", user->nick.c_str(), parameters[0].c_str());
- return CMD_FAILURE;
- }
- user->WriteServ("NOTICE %s :*** RCONNECT: Sending remote connect to \002%s\002 to connect server \002%s\002.",user->nick.c_str(),parameters[0].c_str(),parameters[1].c_str());
+ ((ModuleSpanningTree*)(Module*)creator)->RemoteMessage(user, "*** RCONNECT: Server \002%s\002 isn't connected to the network!", parameters[0].c_str());
+ return CMD_FAILURE;
}
/* Is this aimed at our server? */
@@ -58,6 +49,21 @@ CmdResult CommandRConnect::Handle (const std::vector<std::string>& parameters, U
para.push_back(parameters[1]);
((ModuleSpanningTree*)(Module*)creator)->HandleConnect(para, user);
}
+ else
+ {
+ /* It's not aimed at our server, but if the request originates from our user
+ * acknowledge that we sent the request.
+ *
+ * It's possible that we're asking a server for something that makes no sense
+ * (e.g. connect to itself or to an already connected server), but we don't check
+ * for those conditions here, as ModuleSpanningTree::HandleConnect() (which will run
+ * on the target) does all the checking and error reporting.
+ */
+ if (IS_LOCAL(user))
+ {
+ user->WriteServ("NOTICE %s :*** RCONNECT: Sending remote connect to \002%s\002 to connect server \002%s\002.",user->nick.c_str(),parameters[0].c_str(),parameters[1].c_str());
+ }
+ }
return CMD_SUCCESS;
}
diff --git a/src/modules/m_spanningtree/resolvers.cpp b/src/modules/m_spanningtree/resolvers.cpp
index d7c4c5227..b2d14069c 100644
--- a/src/modules/m_spanningtree/resolvers.cpp
+++ b/src/modules/m_spanningtree/resolvers.cpp
@@ -19,9 +19,8 @@
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
+#include "cachetimer.h"
#include "resolvers.h"
#include "main.h"
#include "utils.h"
@@ -37,13 +36,15 @@
* callback to OnLookupComplete or OnError when completed. Once it has completed we
* will have an IP address which we can then use to continue our connection.
*/
-ServernameResolver::ServernameResolver(SpanningTreeUtilities* Util, const std::string &hostname, Link* x, bool &cached, QueryType qt, Autoconnect* myac)
- : Resolver(hostname, qt, cached, Util->Creator), Utils(Util), query(qt), host(hostname), MyLink(x), myautoconnect(myac)
+ServernameResolver::ServernameResolver(SpanningTreeUtilities* Util, DNS::Manager *mgr, const std::string &hostname, Link* x, DNS::QueryType qt, Autoconnect* myac)
+ : DNS::Request(mgr, Util->Creator, hostname, qt), Utils(Util), query(qt), host(hostname), MyLink(x), myautoconnect(myac)
{
}
-void ServernameResolver::OnLookupComplete(const std::string &result, unsigned int ttl, bool cached)
+void ServernameResolver::OnLookupComplete(const DNS::Query *r)
{
+ const DNS::ResourceRecord &ans_record = r->answers[0];
+
/* Initiate the connection, now that we have an IP to use.
* Passing a hostname directly to BufferedSocket causes it to
* just bail and set its FD to -1.
@@ -51,7 +52,7 @@ void ServernameResolver::OnLookupComplete(const std::string &result, unsigned in
TreeServer* CheckDupe = Utils->FindServer(MyLink->Name.c_str());
if (!CheckDupe) /* Check that nobody tried to connect it successfully while we were resolving */
{
- TreeSocket* newsocket = new TreeSocket(Utils, MyLink, myautoconnect, result);
+ TreeSocket* newsocket = new TreeSocket(Utils, MyLink, myautoconnect, ans_record.rdata);
if (newsocket->GetFd() > -1)
{
/* We're all OK */
@@ -66,47 +67,73 @@ void ServernameResolver::OnLookupComplete(const std::string &result, unsigned in
}
}
-void ServernameResolver::OnError(ResolverError e, const std::string &errormessage)
+void ServernameResolver::OnError(const DNS::Query *r)
{
/* Ooops! */
- if (query == DNS_QUERY_AAAA)
+ if (query == DNS::QUERY_AAAA)
{
- bool cached = false;
- ServernameResolver* snr = new ServernameResolver(Utils, host, MyLink, cached, DNS_QUERY_A, myautoconnect);
- ServerInstance->AddResolver(snr, cached);
- return;
+ ServernameResolver* snr = new ServernameResolver(Utils, this->manager, host, MyLink, DNS::QUERY_A, myautoconnect);
+ try
+ {
+ this->manager->Process(snr);
+ return;
+ }
+ catch (DNS::Exception &)
+ {
+ delete snr;
+ }
}
- ServerInstance->SNO->WriteToSnoMask('l', "CONNECT: Error connecting \002%s\002: Unable to resolve hostname - %s", MyLink->Name.c_str(), errormessage.c_str() );
+
+ ServerInstance->SNO->WriteToSnoMask('l', "CONNECT: Error connecting \002%s\002: Unable to resolve hostname - %s", MyLink->Name.c_str(), this->manager->GetErrorStr(r->error).c_str());
Utils->Creator->ConnectServer(myautoconnect, false);
}
-SecurityIPResolver::SecurityIPResolver(Module* me, SpanningTreeUtilities* U, const std::string &hostname, Link* x, bool &cached, QueryType qt)
- : Resolver(hostname, qt, cached, me), MyLink(x), Utils(U), mine(me), host(hostname), query(qt)
+SecurityIPResolver::SecurityIPResolver(Module* me, SpanningTreeUtilities* U, DNS::Manager *mgr, const std::string &hostname, Link* x, DNS::QueryType qt)
+ : DNS::Request(mgr, me, hostname, qt), MyLink(x), Utils(U), mine(me), host(hostname), query(qt)
{
}
-void SecurityIPResolver::OnLookupComplete(const std::string &result, unsigned int ttl, bool cached)
+void SecurityIPResolver::OnLookupComplete(const DNS::Query *r)
{
+ const DNS::ResourceRecord &ans_record = r->answers[0];
+
for (std::vector<reference<Link> >::iterator i = Utils->LinkBlocks.begin(); i != Utils->LinkBlocks.end(); ++i)
{
Link* L = *i;
if (L->IPAddr == host)
{
- Utils->ValidIPs.push_back(result);
+ Utils->ValidIPs.push_back(ans_record.rdata);
break;
}
}
}
-void SecurityIPResolver::OnError(ResolverError e, const std::string &errormessage)
+void SecurityIPResolver::OnError(const DNS::Query *r)
{
- if (query == DNS_QUERY_AAAA)
+ if (query == DNS::QUERY_AAAA)
{
- bool cached = false;
- SecurityIPResolver* res = new SecurityIPResolver(mine, Utils, host, MyLink, cached, DNS_QUERY_A);
- ServerInstance->AddResolver(res, cached);
- return;
+ SecurityIPResolver* res = new SecurityIPResolver(mine, Utils, this->manager, host, MyLink, DNS::QUERY_A);
+ try
+ {
+ this->manager->Process(res);
+ return;
+ }
+ catch (DNS::Exception &)
+ {
+ delete res;
+ }
}
- ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Could not resolve IP associated with Link '%s': %s",
- MyLink->Name.c_str(),errormessage.c_str());
+ ServerInstance->Logs->Log("m_spanningtree",LOG_DEFAULT,"Could not resolve IP associated with Link '%s': %s",
+ MyLink->Name.c_str(), this->manager->GetErrorStr(r->error).c_str());
+}
+
+CacheRefreshTimer::CacheRefreshTimer(SpanningTreeUtilities* Util)
+ : Timer(3, ServerInstance->Time(), true), Utils(Util)
+{
+}
+
+bool CacheRefreshTimer::Tick(time_t TIME)
+{
+ Utils->RefreshIPCache();
+ return true;
}
diff --git a/src/modules/m_spanningtree/resolvers.h b/src/modules/m_spanningtree/resolvers.h
index 65b9e7249..83aaf8db0 100644
--- a/src/modules/m_spanningtree/resolvers.h
+++ b/src/modules/m_spanningtree/resolvers.h
@@ -18,30 +18,28 @@
*/
-#ifndef M_SPANNINGTREE_RESOLVERS_H
-#define M_SPANNINGTREE_RESOLVERS_H
+#pragma once
-#include "socket.h"
#include "inspircd.h"
-#include "xline.h"
+#include "modules/dns.h"
#include "utils.h"
#include "link.h"
/** Handle resolving of server IPs for the cache
*/
-class SecurityIPResolver : public Resolver
+class SecurityIPResolver : public DNS::Request
{
private:
reference<Link> MyLink;
SpanningTreeUtilities* Utils;
Module* mine;
std::string host;
- QueryType query;
+ DNS::QueryType query;
public:
- SecurityIPResolver(Module* me, SpanningTreeUtilities* U, const std::string &hostname, Link* x, bool &cached, QueryType qt);
- void OnLookupComplete(const std::string &result, unsigned int ttl, bool cached);
- void OnError(ResolverError e, const std::string &errormessage);
+ SecurityIPResolver(Module* me, SpanningTreeUtilities* U, DNS::Manager *mgr, const std::string &hostname, Link* x, DNS::QueryType qt);
+ void OnLookupComplete(const DNS::Query *r);
+ void OnError(const DNS::Query *q);
};
/** This class is used to resolve server hostnames during /connect and autoconnect.
@@ -50,18 +48,16 @@ class SecurityIPResolver : public Resolver
* callback to OnLookupComplete or OnError when completed. Once it has completed we
* will have an IP address which we can then use to continue our connection.
*/
-class ServernameResolver : public Resolver
+class ServernameResolver : public DNS::Request
{
private:
SpanningTreeUtilities* Utils;
- QueryType query;
+ DNS::QueryType query;
std::string host;
reference<Link> MyLink;
reference<Autoconnect> myautoconnect;
public:
- ServernameResolver(SpanningTreeUtilities* Util, const std::string &hostname, Link* x, bool &cached, QueryType qt, Autoconnect* myac);
- void OnLookupComplete(const std::string &result, unsigned int ttl, bool cached);
- void OnError(ResolverError e, const std::string &errormessage);
+ ServernameResolver(SpanningTreeUtilities* Util, DNS::Manager *mgr, const std::string &hostname, Link* x, DNS::QueryType qt, Autoconnect* myac);
+ void OnLookupComplete(const DNS::Query *r);
+ void OnError(const DNS::Query *q);
};
-
-#endif
diff --git a/src/modules/m_spanningtree/rsquit.cpp b/src/modules/m_spanningtree/rsquit.cpp
index 027ae02ab..be658120b 100644
--- a/src/modules/m_spanningtree/rsquit.cpp
+++ b/src/modules/m_spanningtree/rsquit.cpp
@@ -19,13 +19,9 @@
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "main.h"
#include "utils.h"
#include "treeserver.h"
-#include "treesocket.h"
#include "commands.h"
CommandRSQuit::CommandRSQuit (Module* Creator, SpanningTreeUtilities* Util)
@@ -43,13 +39,13 @@ CmdResult CommandRSQuit::Handle (const std::vector<std::string>& parameters, Use
server_target = Utils->FindServerMask(parameters[0]);
if (!server_target)
{
- user->WriteServ("NOTICE %s :*** RSQUIT: Server \002%s\002 isn't connected to the network!", user->nick.c_str(), parameters[0].c_str());
+ ((ModuleSpanningTree*)(Module*)creator)->RemoteMessage(user, "*** RSQUIT: Server \002%s\002 isn't connected to the network!", parameters[0].c_str());
return CMD_FAILURE;
}
if (server_target == Utils->TreeRoot)
{
- NoticeUser(user, "*** RSQUIT: Foolish mortal, you cannot make a server SQUIT itself! ("+parameters[0]+" matches local server name)");
+ ((ModuleSpanningTree*)(Module*)creator)->RemoteMessage(user, "*** RSQUIT: Foolish mortal, you cannot make a server SQUIT itself! (%s matches local server name)", parameters[0].c_str());
return CMD_FAILURE;
}
@@ -75,20 +71,3 @@ RouteDescriptor CommandRSQuit::GetRouting(User* user, const std::vector<std::str
{
return ROUTE_UNICAST(parameters[0]);
}
-
-// XXX use protocol interface instead of rolling our own :)
-void CommandRSQuit::NoticeUser(User* user, const std::string &msg)
-{
- if (IS_LOCAL(user))
- {
- user->WriteServ("NOTICE %s :%s",user->nick.c_str(),msg.c_str());
- }
- else
- {
- parameterlist params;
- params.push_back(user->nick);
- params.push_back("NOTICE "+ConvToStr(user->nick)+" :"+msg);
- Utils->DoOneToOne(ServerInstance->Config->GetSID(), "PUSH", params, user->server);
- }
-}
-
diff --git a/src/modules/m_spanningtree/save.cpp b/src/modules/m_spanningtree/save.cpp
index 92999b422..9e2ade8c4 100644
--- a/src/modules/m_spanningtree/save.cpp
+++ b/src/modules/m_spanningtree/save.cpp
@@ -18,16 +18,11 @@
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "socketengine.h"
-#include "main.h"
#include "utils.h"
-#include "treeserver.h"
#include "treesocket.h"
-/* $ModDep: m_spanningtree/main.h m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/treesocket.h */
+/* $ModDep: m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/treesocket.h */
/**
* SAVE command - force nick change to UID on timestamp match
diff --git a/src/modules/m_spanningtree/server.cpp b/src/modules/m_spanningtree/server.cpp
index 05441da0c..85204ccaa 100644
--- a/src/modules/m_spanningtree/server.cpp
+++ b/src/modules/m_spanningtree/server.cpp
@@ -19,11 +19,7 @@
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "socketengine.h"
-#include "main.h"
#include "utils.h"
#include "link.h"
#include "treeserver.h"
@@ -55,7 +51,7 @@ bool TreeSocket::RemoteServer(const std::string &prefix, parameterlist &params)
this->SendError("Protocol error - Introduced remote server from unknown server "+prefix);
return false;
}
- if (!ServerInstance->IsSID(sid))
+ if (!InspIRCd::IsSID(sid))
{
this->SendError("Invalid format server ID: "+sid+"!");
return false;
@@ -105,17 +101,9 @@ bool TreeSocket::Outbound_Reply_Server(parameterlist &params)
std::string password = params[1];
std::string sid = params[3];
std::string description = params[4];
- int hops = atoi(params[2].c_str());
this->SendCapabilities(2);
- if (hops)
- {
- this->SendError("Server too far away for authentication");
- ServerInstance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, server is too far away for authentication");
- return false;
- }
-
if (!ServerInstance->IsSID(sid))
{
this->SendError("Invalid format server ID: "+sid+"!");
@@ -194,7 +182,7 @@ bool TreeSocket::CheckDuplicate(const std::string& sname, const std::string& sid
}
/* Check for fully initialized instances of the server by id */
- ServerInstance->Logs->Log("m_spanningtree",DEBUG,"Looking for dupe SID %s", sid.c_str());
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEBUG, "Looking for dupe SID %s", sid.c_str());
CheckDupe = Utils->FindServerID(sid);
if (CheckDupe)
@@ -225,17 +213,9 @@ bool TreeSocket::Inbound_Server(parameterlist &params)
std::string password = params[1];
std::string sid = params[3];
std::string description = params[4];
- int hops = atoi(params[2].c_str());
this->SendCapabilities(2);
- if (hops)
- {
- this->SendError("Server too far away for authentication");
- ServerInstance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, server is too far away for authentication");
- return false;
- }
-
if (!ServerInstance->IsSID(sid))
{
this->SendError("Invalid format server ID: "+sid+"!");
diff --git a/src/modules/m_spanningtree/svsjoin.cpp b/src/modules/m_spanningtree/svsjoin.cpp
index 416502369..6b1d2835c 100644
--- a/src/modules/m_spanningtree/svsjoin.cpp
+++ b/src/modules/m_spanningtree/svsjoin.cpp
@@ -19,13 +19,7 @@
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "socketengine.h"
-#include "main.h"
-#include "utils.h"
-#include "treeserver.h"
#include "commands.h"
CmdResult CommandSVSJoin::Handle(const std::vector<std::string>& parameters, User *user)
@@ -40,8 +34,9 @@ CmdResult CommandSVSJoin::Handle(const std::vector<std::string>& parameters, Use
return CMD_FAILURE;
/* only join if it's local, otherwise just pass it on! */
- if (IS_LOCAL(u))
- Channel::JoinUser(u, parameters[1].c_str(), false, "", false, ServerInstance->Time());
+ LocalUser* localuser = IS_LOCAL(u);
+ if (localuser)
+ Channel::JoinUser(localuser, parameters[1]);
return CMD_SUCCESS;
}
diff --git a/src/modules/m_spanningtree/svsnick.cpp b/src/modules/m_spanningtree/svsnick.cpp
index 79dc27ea3..916dae0a7 100644
--- a/src/modules/m_spanningtree/svsnick.cpp
+++ b/src/modules/m_spanningtree/svsnick.cpp
@@ -20,8 +20,6 @@
#include "inspircd.h"
-#include "main.h"
-#include "utils.h"
#include "commands.h"
CmdResult CommandSVSNick::Handle(const std::vector<std::string>& parameters, User *user)
@@ -44,7 +42,7 @@ CmdResult CommandSVSNick::Handle(const std::vector<std::string>& parameters, Use
}
}
- u->age = atoi(parameters[2].c_str());
+ u->age = ConvToInt(parameters[2]);
}
return CMD_SUCCESS;
diff --git a/src/modules/m_spanningtree/svspart.cpp b/src/modules/m_spanningtree/svspart.cpp
index 3bdf13b25..b966da282 100644
--- a/src/modules/m_spanningtree/svspart.cpp
+++ b/src/modules/m_spanningtree/svspart.cpp
@@ -19,13 +19,7 @@
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "socketengine.h"
-#include "main.h"
-#include "utils.h"
-#include "treeserver.h"
#include "commands.h"
CmdResult CommandSVSPart::Handle(const std::vector<std::string>& parameters, User *user)
diff --git a/src/modules/m_spanningtree/treeserver.cpp b/src/modules/m_spanningtree/treeserver.cpp
index 493b05ebf..4ce7c49d5 100644
--- a/src/modules/m_spanningtree/treeserver.cpp
+++ b/src/modules/m_spanningtree/treeserver.cpp
@@ -21,10 +21,9 @@
#include "inspircd.h"
-#include "socket.h"
#include "xline.h"
#include "main.h"
-#include "../spanningtree.h"
+#include "modules/spanningtree.h"
#include "utils.h"
#include "treeserver.h"
@@ -42,7 +41,7 @@ TreeServer::TreeServer(SpanningTreeUtilities* Util, std::string Name, std::strin
bursting = false;
Parent = NULL;
VersionString.clear();
- ServerUserCount = ServerOperCount = 0;
+ UserCount = OperCount = 0;
VersionString = ServerInstance->GetVersionString();
Route = NULL;
Socket = NULL; /* Fix by brain */
@@ -62,7 +61,7 @@ TreeServer::TreeServer(SpanningTreeUtilities* Util, std::string Name, std::strin
age = ServerInstance->Time();
bursting = true;
VersionString.clear();
- ServerUserCount = ServerOperCount = 0;
+ UserCount = OperCount = 0;
SetNextPingTime(ServerInstance->Time() + Utils->PingFreq);
SetPingFlag();
Warned = false;
@@ -70,7 +69,7 @@ TreeServer::TreeServer(SpanningTreeUtilities* Util, std::string Name, std::strin
long ts = ServerInstance->Time() * 1000 + (ServerInstance->Time_ns() / 1000000);
this->StartBurst = ts;
- ServerInstance->Logs->Log("m_spanningtree",DEBUG, "Started bursting at time %lu", ts);
+ ServerInstance->Logs->Log("m_spanningtree",LOG_DEBUG, "Started bursting at time %lu", ts);
/* find the 'route' for this server (e.g. the one directly connected
* to the local server, which we can use to reach it)
@@ -158,7 +157,7 @@ void TreeServer::FinishBurst()
void TreeServer::SetID(const std::string &id)
{
- ServerInstance->Logs->Log("m_spanningtree",DEBUG, "Setting SID to " + id);
+ ServerInstance->Logs->Log("m_spanningtree",LOG_DEBUG, "Setting SID to " + id);
sid = id;
Utils->sidlist[sid] = this;
}
@@ -257,26 +256,6 @@ void TreeServer::SetPingFlag()
LastPingWasGood = true;
}
-unsigned int TreeServer::GetUserCount()
-{
- return ServerUserCount;
-}
-
-void TreeServer::SetUserCount(int diff)
-{
- ServerUserCount += diff;
-}
-
-void TreeServer::SetOperCount(int diff)
-{
- ServerOperCount += diff;
-}
-
-unsigned int TreeServer::GetOperCount()
-{
- return ServerOperCount;
-}
-
TreeSocket* TreeServer::GetSocket()
{
return Socket;
diff --git a/src/modules/m_spanningtree/treeserver.h b/src/modules/m_spanningtree/treeserver.h
index 60b6d1def..460231502 100644
--- a/src/modules/m_spanningtree/treeserver.h
+++ b/src/modules/m_spanningtree/treeserver.h
@@ -19,8 +19,7 @@
*/
-#ifndef M_SPANNINGTREE_TREESERVER_H
-#define M_SPANNINGTREE_TREESERVER_H
+#pragma once
#include "treesocket.h"
@@ -46,8 +45,6 @@ class TreeServer : public classbase
irc::string ServerName; /* Server's name */
std::string ServerDesc; /* Server's description */
std::string VersionString; /* Version string or empty string */
- unsigned int ServerUserCount; /* How many users are on this server? [note: doesn't care about +i] */
- unsigned int ServerOperCount; /* How many opers are on this server? */
TreeSocket* Socket; /* For directly connected servers this points at the socket object */
time_t NextPing; /* After this time, the server should be PINGed*/
bool LastPingWasGood; /* True if the server responded to the last PING with a PONG */
@@ -67,6 +64,9 @@ class TreeServer : public classbase
bool Warned; /* True if we've warned opers about high latency on this server */
bool bursting; /* whether or not this server is bursting */
+ unsigned int UserCount; /* How many users are on this server? [note: doesn't care about +i] */
+ unsigned int OperCount; /* How many opers are on this server? */
+
/** We use this constructor only to create the 'root' item, Utils->TreeRoot, which
* represents our own server. Therefore, it has no route, no parent, and
* no socket associated with it. Its version string is our own local version.
@@ -143,22 +143,6 @@ class TreeServer : public classbase
*/
void SetPingFlag();
- /** Get the number of users on this server.
- */
- unsigned int GetUserCount();
-
- /** Increment or decrement the user count by diff.
- */
- void SetUserCount(int diff);
-
- /** Gets the numbers of opers on this server.
- */
- unsigned int GetOperCount();
-
- /** Increment or decrement the oper count by diff.
- */
- void SetOperCount(int diff);
-
/** Get the TreeSocket pointer for local servers.
* For remote servers, this returns NULL.
*/
@@ -210,5 +194,3 @@ class TreeServer : public classbase
*/
~TreeServer();
};
-
-#endif
diff --git a/src/modules/m_spanningtree/treesocket.h b/src/modules/m_spanningtree/treesocket.h
index d8445572b..0a519041c 100644
--- a/src/modules/m_spanningtree/treesocket.h
+++ b/src/modules/m_spanningtree/treesocket.h
@@ -20,12 +20,9 @@
*/
-#ifndef M_SPANNINGTREE_TREESOCKET_H
-#define M_SPANNINGTREE_TREESOCKET_H
+#pragma once
-#include "socket.h"
#include "inspircd.h"
-#include "xline.h"
#include "utils.h"
@@ -180,13 +177,8 @@ class TreeSocket : public BufferedSocket
/** Recursively send the server tree with distances as hops.
* This is used during network burst to inform the other server
* (and any of ITS servers too) of what servers we know about.
- * If at any point any of these servers already exist on the other
- * end, our connection may be terminated. The hopcounts given
- * by this function are relative, this doesn't matter so long as
- * they are all >1, as all the remote servers re-calculate them
- * to be relative too, with themselves as hop 0.
*/
- void SendServers(TreeServer* Current, TreeServer* s, int hops);
+ void SendServers(TreeServer* Current, TreeServer* s);
/** Returns module list as a string, filtered by filter
* @param filter a module version bitmask, such as VF_COMMON or VF_OPTCOMMON
@@ -197,9 +189,6 @@ class TreeSocket : public BufferedSocket
*/
void SendCapabilities(int phase);
- /** Add modules to VF_COMMON list for backwards compatability */
- void CompatAddModules(std::vector<std::string>& modlist);
-
/* Isolate and return the elements that are different between two lists */
void ListDifference(const std::string &one, const std::string &two, char sep,
std::string& mleft, std::string& mright);
@@ -232,8 +221,8 @@ class TreeSocket : public BufferedSocket
/** Send G, Q, Z and E lines */
void SendXLines();
- /** Send channel modes and topics */
- void SendChannelModes();
+ /** Send all known information about a channel */
+ void SyncChannel(Channel* chan);
/** send all users and their oper state/modes */
void SendUsers();
@@ -331,7 +320,8 @@ class TreeSocket : public BufferedSocket
/** Returns true if this server was introduced to the rest of the network
*/
bool Introduced();
-};
-
-#endif
+ /** Fixes messages coming from old servers so the new command handlers understand them
+ */
+ bool PreProcessOldProtocolMessage(User*& who, std::string& cmd, std::vector<std::string>& params);
+};
diff --git a/src/modules/m_spanningtree/treesocket1.cpp b/src/modules/m_spanningtree/treesocket1.cpp
index 6582ba060..9d0002b66 100644
--- a/src/modules/m_spanningtree/treesocket1.cpp
+++ b/src/modules/m_spanningtree/treesocket1.cpp
@@ -21,17 +21,13 @@
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "socketengine.h"
#include "main.h"
-#include "../spanningtree.h"
+#include "modules/spanningtree.h"
#include "utils.h"
#include "treeserver.h"
#include "link.h"
#include "treesocket.h"
-#include "resolvers.h"
/** Because most of the I/O gubbins are encapsulated within
* BufferedSocket, we just call the superclass constructor for
@@ -158,7 +154,7 @@ void TreeSocket::SendError(const std::string &errormessage)
void TreeSocket::SquitServer(std::string &from, TreeServer* Current, int& num_lost_servers, int& num_lost_users)
{
std::string servername = Current->GetName();
- ServerInstance->Logs->Log("m_spanningtree",DEBUG,"SquitServer for %s from %s",
+ ServerInstance->Logs->Log("m_spanningtree",LOG_DEBUG,"SquitServer for %s from %s",
servername.c_str(), from.c_str());
/* recursively squit the servers attached to 'Current'.
* We're going backwards so we don't remove users
@@ -189,9 +185,9 @@ void TreeSocket::Squit(TreeServer* Current, const std::string &reason)
if (!Current->GetSocket() || Current->GetSocket()->Introduced())
{
parameterlist params;
- params.push_back(Current->GetName());
+ params.push_back(Current->GetID());
params.push_back(":"+reason);
- Utils->DoOneToAllButSender(Current->GetParent()->GetName(),"SQUIT",params,Current->GetName());
+ Utils->DoOneToAllButSender(Current->GetParent()->GetID(),"SQUIT",params,Current->GetName());
}
if (Current->GetParent() == Utils->TreeRoot)
@@ -220,7 +216,7 @@ void TreeSocket::Squit(TreeServer* Current, const std::string &reason)
}
}
else
- ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Squit from unknown server");
+ ServerInstance->Logs->Log("m_spanningtree",LOG_DEFAULT,"Squit from unknown server");
}
/** 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 5007fe921..fdd28a734 100644
--- a/src/modules/m_spanningtree/treesocket2.cpp
+++ b/src/modules/m_spanningtree/treesocket2.cpp
@@ -23,14 +23,10 @@
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "socketengine.h"
#include "main.h"
#include "utils.h"
#include "treeserver.h"
-#include "link.h"
#include "treesocket.h"
#include "resolvers.h"
@@ -47,7 +43,7 @@ void TreeSocket::Split(const std::string& line, std::string& prefix, std::string
if (!tokens.GetToken(prefix))
return;
-
+
if (prefix[0] == ':')
{
prefix = prefix.substr(1);
@@ -84,7 +80,7 @@ void TreeSocket::ProcessLine(std::string &line)
std::string command;
parameterlist params;
- ServerInstance->Logs->Log("m_spanningtree", RAWIO, "S[%d] I %s", this->GetFd(), line.c_str());
+ ServerInstance->Logs->Log("m_spanningtree", LOG_RAWIO, "S[%d] I %s", this->GetFd(), line.c_str());
Split(line, prefix, command, params);
@@ -151,7 +147,7 @@ void TreeSocket::ProcessLine(std::string &line)
{
if (params.size())
{
- time_t them = atoi(params[0].c_str());
+ time_t them = ConvToInt(params[0]);
time_t delta = them - ServerInstance->Time();
if ((delta < -600) || (delta > 600))
{
@@ -257,7 +253,7 @@ void TreeSocket::ProcessConnectedLine(std::string& prefix, std::string& command,
* crossing the users QUIT further upstream from the server. Thanks jilles!
*/
- if ((prefix.length() == UUID_LENGTH-1) && (isdigit(prefix[0])) &&
+ if ((prefix.length() == UIDGenerator::UUID_LENGTH) && (isdigit(prefix[0])) &&
((command == "FMODE") || (command == "MODE") || (command == "KICK") || (command == "TOPIC") || (command == "KILL") || (command == "ADDLINE") || (command == "DELLINE")))
{
/* Special case, we cannot drop these commands as they've been committed already on a
@@ -271,7 +267,7 @@ void TreeSocket::ProcessConnectedLine(std::string& prefix, std::string& command,
}
else
{
- ServerInstance->Logs->Log("m_spanningtree", DEBUG, "Command '%s' from unknown prefix '%s'! Dropping entire command.",
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEBUG, "Command '%s' from unknown prefix '%s'! Dropping entire command.",
command.c_str(), prefix.c_str());
return;
}
@@ -302,7 +298,7 @@ void TreeSocket::ProcessConnectedLine(std::string& prefix, std::string& command,
if ((!route_back_again) || (route_back_again->GetSocket() != this))
{
if (route_back_again)
- ServerInstance->Logs->Log("m_spanningtree",DEBUG,"Protocol violation: Fake direction '%s' from connection '%s'",
+ ServerInstance->Logs->Log("m_spanningtree",LOG_DEBUG,"Protocol violation: Fake direction '%s' from connection '%s'",
prefix.c_str(),linkID.c_str());
return;
}
@@ -314,6 +310,12 @@ void TreeSocket::ProcessConnectedLine(std::string& prefix, std::string& command,
if (command == "SVSMODE") // This isn't in an "else if" so we still force FMODE for changes on channels.
command = "MODE";
+ if (proto_version < ProtocolVersion)
+ {
+ if (!PreProcessOldProtocolMessage(who, command, params))
+ return;
+ }
+
// TODO move all this into Commands
if (command == "MAP")
{
@@ -439,7 +441,7 @@ void TreeSocket::ProcessConnectedLine(std::string& prefix, std::string& command,
}
/* Update timestamp on user when they change nicks */
- who->age = atoi(params[1].c_str());
+ who->age = ConvToInt(params[1]);
/*
* On nick messages, check that the nick doesnt already exist here.
@@ -467,11 +469,11 @@ void TreeSocket::ProcessConnectedLine(std::string& prefix, std::string& command,
else
{
Command* cmd = ServerInstance->Parser->GetHandler(command);
-
+
if (!cmd)
{
irc::stringjoiner pmlist(" ", params, 0, params.size() - 1);
- ServerInstance->Logs->Log("m_spanningtree", SPARSE, "Unrecognised S2S command :%s %s %s",
+ ServerInstance->Logs->Log("m_spanningtree", LOG_SPARSE, "Unrecognised S2S command :%s %s %s",
who->uuid.c_str(), command.c_str(), pmlist.GetJoined().c_str());
SendError("Unrecognised command '" + command + "' -- possibly loaded mismatched modules");
return;
@@ -480,7 +482,7 @@ void TreeSocket::ProcessConnectedLine(std::string& prefix, std::string& command,
if (params.size() < cmd->min_params)
{
irc::stringjoiner pmlist(" ", params, 0, params.size() - 1);
- ServerInstance->Logs->Log("m_spanningtree", SPARSE, "Insufficient parameters for S2S command :%s %s %s",
+ ServerInstance->Logs->Log("m_spanningtree", 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;
@@ -499,7 +501,7 @@ void TreeSocket::ProcessConnectedLine(std::string& prefix, std::string& command,
if (res == CMD_INVALID)
{
irc::stringjoiner pmlist(" ", params, 0, params.size() - 1);
- ServerInstance->Logs->Log("m_spanningtree", SPARSE, "Error handling S2S command :%s %s %s",
+ ServerInstance->Logs->Log("m_spanningtree", 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");
}
diff --git a/src/modules/m_spanningtree/uid.cpp b/src/modules/m_spanningtree/uid.cpp
index f33cb038d..f2e394c37 100644
--- a/src/modules/m_spanningtree/uid.cpp
+++ b/src/modules/m_spanningtree/uid.cpp
@@ -23,10 +23,7 @@
#include "commands.h"
#include "utils.h"
-#include "link.h"
-#include "treesocket.h"
#include "treeserver.h"
-#include "resolvers.h"
CmdResult CommandUID::Handle(const parameterlist &params, User* serversrc)
{
@@ -38,7 +35,7 @@ CmdResult CommandUID::Handle(const parameterlist &params, User* serversrc)
time_t age_t = ConvToInt(params[1]);
time_t signon = ConvToInt(params[7]);
std::string empty;
- std::string modestr(params[8]);
+ const std::string& modestr = params[8];
TreeServer* remoteserver = Utils->FindServer(serversrc->server);
@@ -65,7 +62,7 @@ CmdResult CommandUID::Handle(const parameterlist &params, User* serversrc)
* Nick collision.
*/
int collide = sock->DoCollision(iter->second, age_t, params[5], params[6], params[0]);
- ServerInstance->Logs->Log("m_spanningtree",DEBUG,"*** Collision on %s, collide=%d", params[2].c_str(), collide);
+ ServerInstance->Logs->Log("m_spanningtree",LOG_DEBUG,"*** Collision on %s, collide=%d", params[2].c_str(), collide);
if (collide != 1)
{
@@ -88,7 +85,7 @@ CmdResult CommandUID::Handle(const parameterlist &params, User* serversrc)
}
catch (...)
{
- ServerInstance->Logs->Log("m_spanningtree", DEFAULT, "Duplicate UUID %s in client introduction", params[0].c_str());
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEFAULT, "Duplicate UUID %s in client introduction", params[0].c_str());
return CMD_INVALID;
}
(*(ServerInstance->Users->clientlist))[params[2]] = _new;
@@ -101,49 +98,45 @@ CmdResult CommandUID::Handle(const parameterlist &params, User* serversrc)
_new->signon = signon;
_new->age = age_t;
- /* we need to remove the + from the modestring, so we can do our stuff */
- std::string::size_type pos_after_plus = modestr.find_first_not_of('+');
- if (pos_after_plus != std::string::npos)
- modestr = modestr.substr(pos_after_plus);
-
unsigned int paramptr = 9;
- for (std::string::iterator v = modestr.begin(); v != modestr.end(); v++)
+
+ // Accept more '+' chars, for now
+ std::string::size_type pos = modestr.find_first_not_of('+');
+ for (std::string::const_iterator v = modestr.begin()+pos; v != modestr.end(); ++v)
{
- /* For each mode thats set, increase counter */
+ /* For each mode thats set, find the mode handler and set it on the new user */
ModeHandler* mh = ServerInstance->Modes->FindMode(*v, MODETYPE_USER);
+ if (!mh)
+ {
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEFAULT, "Unrecognised mode '%c' for a user in UID, dropping link", *v);
+ return CMD_INVALID;
+ }
- if (mh)
+ if (mh->GetNumParams(true))
{
- if (mh->GetNumParams(true))
- {
- if (paramptr >= params.size() - 1)
- return CMD_INVALID;
- std::string mp = params[paramptr++];
- /* IMPORTANT NOTE:
- * All modes are assumed to succeed here as they are being set by a remote server.
- * Modes CANNOT FAIL here. If they DO fail, then the failure is ignored. This is important
- * to note as all but one modules currently cannot ever fail in this situation, except for
- * m_servprotect which specifically works this way to prevent the mode being set ANYWHERE
- * but here, at client introduction. You may safely assume this behaviour is standard and
- * will not change in future versions if you want to make use of this protective behaviour
- * yourself.
- */
- mh->OnModeChange(_new, _new, NULL, mp, true);
- }
- else
- mh->OnModeChange(_new, _new, NULL, empty, true);
- _new->SetMode(*v, true);
+ if (paramptr >= params.size() - 1)
+ return CMD_INVALID;
+ std::string mp = params[paramptr++];
+ /* IMPORTANT NOTE:
+ * All modes are assumed to succeed here as they are being set by a remote server.
+ * Modes CANNOT FAIL here. If they DO fail, then the failure is ignored. This is important
+ * to note as all but one modules currently cannot ever fail in this situation, except for
+ * m_servprotect which specifically works this way to prevent the mode being set ANYWHERE
+ * but here, at client introduction. You may safely assume this behaviour is standard and
+ * will not change in future versions if you want to make use of this protective behaviour
+ * yourself.
+ */
+ mh->OnModeChange(_new, _new, NULL, mp, true);
}
+ else
+ mh->OnModeChange(_new, _new, NULL, empty, true);
+ _new->SetMode(*v, true);
}
- /* now we've done with modes processing, put the + back for remote servers */
- if (modestr[0] != '+')
- modestr = "+" + modestr;
-
_new->SetClientIP(params[6].c_str());
ServerInstance->Users->AddGlobalClone(_new);
- remoteserver->SetUserCount(1); // increment by 1
+ remoteserver->UserCount++;
bool dosend = true;
@@ -151,7 +144,7 @@ CmdResult CommandUID::Handle(const parameterlist &params, User* serversrc)
dosend = false;
if (dosend)
- ServerInstance->SNO->WriteToSnoMask('C',"Client connecting at %s: %s (%s) [%s]", _new->server.c_str(), _new->GetFullRealHost().c_str(), _new->GetIPString(), _new->fullname.c_str());
+ ServerInstance->SNO->WriteToSnoMask('C',"Client connecting at %s: %s (%s) [%s]", _new->server.c_str(), _new->GetFullRealHost().c_str(), _new->GetIPString().c_str(), _new->fullname.c_str());
FOREACH_MOD(I_OnPostConnect,OnPostConnect(_new));
diff --git a/src/modules/m_spanningtree/utils.cpp b/src/modules/m_spanningtree/utils.cpp
index cc1c400db..428ef7224 100644
--- a/src/modules/m_spanningtree/utils.cpp
+++ b/src/modules/m_spanningtree/utils.cpp
@@ -21,14 +21,10 @@
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "socketengine.h"
#include "main.h"
#include "utils.h"
#include "treeserver.h"
-#include "link.h"
#include "treesocket.h"
#include "resolvers.h"
@@ -61,7 +57,7 @@ ModResult ModuleSpanningTree::OnAcceptConnection(int newsock, ListenSocket* from
*/
TreeServer* SpanningTreeUtilities::FindServer(const std::string &ServerName)
{
- if (ServerInstance->IsSID(ServerName))
+ if (InspIRCd::IsSID(ServerName))
return this->FindServerID(ServerName);
server_hash::iterator iter = serverlist.find(ServerName.c_str());
@@ -130,9 +126,11 @@ TreeServer* SpanningTreeUtilities::FindServerID(const std::string &id)
return NULL;
}
-SpanningTreeUtilities::SpanningTreeUtilities(ModuleSpanningTree* C) : Creator(C)
+SpanningTreeUtilities::SpanningTreeUtilities(ModuleSpanningTree* C)
+ : RefreshTimer(this), Creator(C)
{
- ServerInstance->Logs->Log("m_spanningtree",DEBUG,"***** Using SID for hash: %s *****", ServerInstance->Config->GetSID().c_str());
+ ServerInstance->Timers->AddTimer(&RefreshTimer);
+ ServerInstance->Logs->Log("m_spanningtree",LOG_DEBUG,"***** Using SID for hash: %s *****", ServerInstance->Config->GetSID().c_str());
this->TreeRoot = new TreeServer(this, ServerInstance->Config->ServerName, ServerInstance->Config->ServerDesc, ServerInstance->Config->GetSID());
this->ReadConfiguration();
@@ -165,12 +163,6 @@ SpanningTreeUtilities::~SpanningTreeUtilities()
delete TreeRoot;
}
-void SpanningTreeUtilities::AddThisServer(TreeServer* server, TreeServerList &list)
-{
- if (list.find(server) == list.end())
- list[server] = server;
-}
-
/* returns a list of DIRECT servernames for a specific channel */
void SpanningTreeUtilities::GetListOfServersForChannel(Channel* c, TreeServerList &list, char status, const CUList &exempt_list)
{
@@ -196,21 +188,30 @@ void SpanningTreeUtilities::GetListOfServersForChannel(Channel* c, TreeServerLis
{
TreeServer* best = this->BestRouteTo(i->first->server);
if (best)
- AddThisServer(best,list);
+ list.insert(best);
}
}
return;
}
-bool SpanningTreeUtilities::DoOneToAllButSender(const std::string &prefix, const std::string &command, const parameterlist &params, std::string omit)
+std::string SpanningTreeUtilities::ConstructLine(const std::string& prefix, const std::string& command, const parameterlist& params)
{
- TreeServer* omitroute = this->BestRouteTo(omit);
- std::string FullLine = ":" + prefix + " " + command;
- unsigned int words = params.size();
- for (unsigned int x = 0; x < words; x++)
+ std::string FullLine;
+ FullLine.reserve(MAXBUF);
+ FullLine = ":" + prefix + " " + command;
+ for (parameterlist::const_iterator x = params.begin(); x != params.end(); ++x)
{
- FullLine = FullLine + " " + params[x];
+ FullLine.push_back(' ');
+ FullLine.append(*x);
}
+ return FullLine;
+}
+
+bool SpanningTreeUtilities::DoOneToAllButSender(const std::string& prefix, const std::string& command, const parameterlist& params, const std::string& omit)
+{
+ TreeServer* omitroute = this->BestRouteTo(omit);
+ std::string FullLine = ConstructLine(prefix, command, params);
+
unsigned int items = this->TreeRoot->ChildCount();
for (unsigned int x = 0; x < items; x++)
{
@@ -231,12 +232,8 @@ bool SpanningTreeUtilities::DoOneToAllButSender(const std::string &prefix, const
bool SpanningTreeUtilities::DoOneToMany(const std::string &prefix, const std::string &command, const parameterlist &params)
{
- std::string FullLine = ":" + prefix + " " + command;
- unsigned int words = params.size();
- for (unsigned int x = 0; x < words; x++)
- {
- FullLine = FullLine + " " + params[x];
- }
+ std::string FullLine = ConstructLine(prefix, command, params);
+
unsigned int items = this->TreeRoot->ChildCount();
for (unsigned int x = 0; x < items; x++)
{
@@ -251,36 +248,16 @@ bool SpanningTreeUtilities::DoOneToMany(const std::string &prefix, const std::st
return true;
}
-bool SpanningTreeUtilities::DoOneToMany(const char* prefix, const char* command, const parameterlist &params)
-{
- std::string spfx = prefix;
- std::string scmd = command;
- return this->DoOneToMany(spfx, scmd, params);
-}
-
-bool SpanningTreeUtilities::DoOneToAllButSender(const char* prefix, const char* command, const parameterlist &params, std::string omit)
-{
- std::string spfx = prefix;
- std::string scmd = command;
- return this->DoOneToAllButSender(spfx, scmd, params, omit);
-}
-
-bool SpanningTreeUtilities::DoOneToOne(const std::string &prefix, const std::string &command, const parameterlist &params, std::string target)
+bool SpanningTreeUtilities::DoOneToOne(const std::string& prefix, const std::string& command, const parameterlist& params, const std::string& target)
{
TreeServer* Route = this->BestRouteTo(target);
if (Route)
{
- std::string FullLine = ":" + prefix + " " + command;
- unsigned int words = params.size();
- for (unsigned int x = 0; x < words; x++)
- {
- FullLine = FullLine + " " + params[x];
- }
if (Route && Route->GetSocket())
{
TreeSocket* Sock = Route->GetSocket();
if (Sock)
- Sock->WriteLine(FullLine);
+ Sock->WriteLine(ConstructLine(prefix, command, params));
}
return true;
}
@@ -298,7 +275,7 @@ void SpanningTreeUtilities::RefreshIPCache()
Link* L = *i;
if (!L->Port)
{
- ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"m_spanningtree: Ignoring a link block without a port.");
+ ServerInstance->Logs->Log("m_spanningtree",LOG_DEFAULT,"m_spanningtree: Ignoring a link block without a port.");
/* Invalid link block */
continue;
}
@@ -310,16 +287,16 @@ void SpanningTreeUtilities::RefreshIPCache()
bool ipvalid = irc::sockets::aptosa(L->IPAddr, L->Port, dummy);
if ((L->IPAddr == "*") || (ipvalid))
ValidIPs.push_back(L->IPAddr);
- else
+ else if (this->Creator->DNS)
{
+ SecurityIPResolver* sr = new SecurityIPResolver(Creator, this, *this->Creator->DNS, L->IPAddr, L, DNS::QUERY_AAAA);
try
{
- bool cached = false;
- SecurityIPResolver* sr = new SecurityIPResolver(Creator, this, L->IPAddr, L, cached, DNS_QUERY_AAAA);
- ServerInstance->AddResolver(sr, cached);
+ this->Creator->DNS->Process(sr);
}
- catch (...)
+ catch (DNS::Exception &)
{
+ delete sr;
}
}
}
@@ -389,11 +366,11 @@ void SpanningTreeUtilities::ReadConfiguration()
if (L->IPAddr.empty())
{
L->IPAddr = "*";
- ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Configuration warning: Link block '" + assign(L->Name) + "' has no IP defined! This will allow any IP to connect as this server, and MAY not be what you want.");
+ ServerInstance->Logs->Log("m_spanningtree",LOG_DEFAULT,"Configuration warning: Link block '" + assign(L->Name) + "' has no IP defined! This will allow any IP to connect as this server, and MAY not be what you want.");
}
if (!L->Port)
- ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Configuration warning: Link block '" + assign(L->Name) + "' has no port defined, you will not be able to /connect it.");
+ ServerInstance->Logs->Log("m_spanningtree",LOG_DEFAULT,"Configuration warning: Link block '" + assign(L->Name) + "' has no port defined, you will not be able to /connect it.");
L->Fingerprint.erase(std::remove(L->Fingerprint.begin(), L->Fingerprint.end(), ':'), L->Fingerprint.end());
LinkBlocks.push_back(L);
@@ -442,3 +419,21 @@ Link* SpanningTreeUtilities::FindLink(const std::string& name)
}
return NULL;
}
+
+void SpanningTreeUtilities::SendChannelMessage(const std::string& prefix, Channel* target, const std::string &text, char status, const CUList& exempt_list, const char* message_type)
+{
+ std::string raw(":");
+ raw.append(prefix).append(1, ' ').append(message_type).push_back(' ');
+ if (status)
+ raw.push_back(status);
+ raw.append(target->name).append(" :").append(text);
+
+ TreeServerList list;
+ this->GetListOfServersForChannel(target, list, status, exempt_list);
+ for (TreeServerList::iterator i = list.begin(); i != list.end(); ++i)
+ {
+ TreeSocket* Sock = (*i)->GetSocket();
+ if (Sock)
+ Sock->WriteLine(raw);
+ }
+}
diff --git a/src/modules/m_spanningtree/utils.h b/src/modules/m_spanningtree/utils.h
index 7d5ffa216..a2566c0c8 100644
--- a/src/modules/m_spanningtree/utils.h
+++ b/src/modules/m_spanningtree/utils.h
@@ -20,10 +20,10 @@
*/
-#ifndef M_SPANNINGTREE_UTILS_H
-#define M_SPANNINGTREE_UTILS_H
+#pragma once
#include "inspircd.h"
+#include "cachetimer.h"
/* Foward declarations */
class TreeServer;
@@ -36,19 +36,21 @@ class SpanningTreeUtilities;
/* This hash_map holds the hash equivalent of the server
* tree, used for rapid linear lookups.
*/
-#ifdef HASHMAP_DEPRECATED
- typedef nspace::hash_map<std::string, TreeServer*, nspace::insensitive, irc::StrHashComp> server_hash;
-#else
- typedef nspace::hash_map<std::string, TreeServer*, nspace::hash<std::string>, irc::StrHashComp> server_hash;
-#endif
+typedef TR1NS::unordered_map<std::string, TreeServer*, irc::insensitive, irc::StrHashComp> server_hash;
-typedef std::map<TreeServer*,TreeServer*> TreeServerList;
+typedef std::set<TreeServer*> TreeServerList;
/** Contains helper functions and variables for this module,
* and keeps them out of the global namespace
*/
class SpanningTreeUtilities : public classbase
{
+ /** Creates a line in the :<prefix> <command> [<params>] format
+ */
+ std::string ConstructLine(const std::string& prefix, const std::string& command, const parameterlist& params);
+
+ CacheRefreshTimer RefreshTimer;
+
public:
/** Creator module
*/
@@ -129,32 +131,20 @@ class SpanningTreeUtilities : public classbase
/** Send a message from this server to one other local or remote
*/
- bool DoOneToOne(const std::string &prefix, const std::string &command, const parameterlist &params, std::string target);
+ bool DoOneToOne(const std::string& prefix, const std::string& command, const parameterlist& params, const std::string& target);
/** Send a message from this server to all but one other, local or remote
*/
- bool DoOneToAllButSender(const std::string &prefix, const std::string &command, const parameterlist &params, std::string omit);
-
- /** Send a message from this server to all but one other, local or remote
- */
- bool DoOneToAllButSender(const char* prefix, const char* command, const parameterlist &params, std::string omit);
+ bool DoOneToAllButSender(const std::string &prefix, const std::string &command, const parameterlist& params, const std::string& omit);
/** Send a message from this server to all others
*/
bool DoOneToMany(const std::string &prefix, const std::string &command, const parameterlist &params);
- /** Send a message from this server to all others
- */
- bool DoOneToMany(const char* prefix, const char* command, const parameterlist &params);
-
/** Read the spanningtree module's tags from the config file
*/
void ReadConfiguration();
- /** Add a server to the server list for GetListOfServersForChannel
- */
- void AddThisServer(TreeServer* server, TreeServerList &list);
-
/** Compile a list of servers which contain members of channel c
*/
void GetListOfServersForChannel(Channel* c, TreeServerList &list, char status, const CUList &exempt_list);
@@ -182,6 +172,8 @@ class SpanningTreeUtilities : public classbase
/** Refresh the IP cache used for allowing inbound connections
*/
void RefreshIPCache();
-};
-#endif
+ /** Sends a PRIVMSG or a NOTICE to a channel obeying an exempt list and an optional prefix
+ */
+ void SendChannelMessage(const std::string& prefix, Channel* target, const std::string &text, char status, const CUList& exempt_list, const char* message_type);
+};
diff --git a/src/modules/m_spanningtree/version.cpp b/src/modules/m_spanningtree/version.cpp
index e08d13e6e..9d76dea9a 100644
--- a/src/modules/m_spanningtree/version.cpp
+++ b/src/modules/m_spanningtree/version.cpp
@@ -18,9 +18,6 @@
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "socketengine.h"
#include "main.h"
#include "utils.h"