mirror of
https://github.com/inspircd/inspircd.git
synced 2025-03-12 03:59:03 -04:00
Add RESYNC command to allow automatic recovery from a detected desync
This commit is contained in:
parent
48ed1fb39b
commit
4351678065
@ -143,6 +143,11 @@ void TreeSocket::WriteLine(std::string line)
|
||||
line.erase(b,c-b);
|
||||
}
|
||||
}
|
||||
else if (proto_version < 1203 && command == "RESYNC")
|
||||
{
|
||||
// drop the command. 2.0 and earlier cannot automatically recover from desync
|
||||
return;
|
||||
}
|
||||
else if (proto_version < 1202 && command == "ENCAP")
|
||||
{
|
||||
// :src ENCAP target command [args...]
|
||||
|
@ -56,6 +56,7 @@ CmdResult CommandFJoin::Handle(const std::vector<std::string>& params, User *src
|
||||
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 incremental = (params[2] == "*");
|
||||
bool created = !chan; /* True if the channel doesnt exist here yet */
|
||||
std::string item; /* One item in the list of nicks */
|
||||
|
||||
@ -71,7 +72,13 @@ CmdResult CommandFJoin::Handle(const std::vector<std::string>& params, User *src
|
||||
if (created)
|
||||
{
|
||||
chan = new Channel(channel, TS);
|
||||
ServerInstance->SNO->WriteToSnoMask('d', "Creation FJOIN recieved for %s, timestamp: %lu", chan->name.c_str(), (unsigned long)TS);
|
||||
if (incremental)
|
||||
{
|
||||
ServerInstance->SNO->WriteToSnoMask('d', "Incremental creation FJOIN recieved for %s, timestamp: %lu", chan->name.c_str(), (unsigned long)TS);
|
||||
parameterlist resync;
|
||||
resync.push_back(channel);
|
||||
Utils->DoOneToOne(ServerInstance->Config->GetSID().c_str(), "RESYNC", resync, srcuser->uuid);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -97,12 +104,19 @@ CmdResult CommandFJoin::Handle(const std::vector<std::string>& params, User *src
|
||||
chan->age = TS;
|
||||
param_list.push_back(channel);
|
||||
this->RemoveStatus(ServerInstance->FakeClient, param_list);
|
||||
if (incremental)
|
||||
{
|
||||
ServerInstance->SNO->WriteToSnoMask('d', "Incremental merge FJOIN recieved for %s, timestamp: %lu", chan->name.c_str(), (unsigned long)TS);
|
||||
parameterlist resync;
|
||||
resync.push_back(channel);
|
||||
Utils->DoOneToOne(ServerInstance->Config->GetSID().c_str(), "RESYNC", resync, srcuser->uuid);
|
||||
}
|
||||
}
|
||||
// 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 */
|
||||
if (apply_other_sides_modes)
|
||||
if (apply_other_sides_modes && !incremental)
|
||||
{
|
||||
unsigned int idx = 2;
|
||||
std::vector<std::string> modelist;
|
||||
|
@ -611,9 +611,7 @@ void ModuleSpanningTree::OnUserJoin(Membership* memb, bool sync, bool created, C
|
||||
// new joining permissions for the user.
|
||||
params.push_back(memb->chan->name);
|
||||
params.push_back(ConvToStr(memb->chan->age));
|
||||
irc::modestacker ms;
|
||||
memb->chan->ChanModes(ms, MODELIST_SHORT);
|
||||
params.push_back(ms.popModeLine(FORMAT_NETWORK, 400, INT_MAX));
|
||||
params.push_back("*");
|
||||
params.push_back(memb->modes+","+std::string(memb->user->uuid));
|
||||
Utils->DoOneToMany(ServerInstance->Config->GetSID(),"FJOIN",params);
|
||||
}
|
||||
|
@ -26,7 +26,7 @@
|
||||
* 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 ProtocolVersion = 1203;
|
||||
const long MinCompatProtocol = 1201;
|
||||
|
||||
/** Forward declarations
|
||||
|
@ -81,7 +81,7 @@ void TreeSocket::SendServers(TreeServer* Current, TreeServer* s, int hops)
|
||||
* If the length of a single line is more than 480-NICKMAX
|
||||
* in length, it is split over multiple lines.
|
||||
*/
|
||||
void TreeSocket::SendFJoins(TreeServer* Current, Channel* c)
|
||||
void TreeSocket::SendFJoins(Channel* c)
|
||||
{
|
||||
char list[MAXBUF];
|
||||
|
||||
@ -138,6 +138,22 @@ void TreeSocket::SendFJoins(TreeServer* Current, Channel* c)
|
||||
snprintf(list, MAXBUF, ":%s FMODE %s %ld ", ServerInstance->Config->GetSID().c_str(), c->name.c_str(), (unsigned long)c->age);
|
||||
while (!fmodes.empty())
|
||||
WriteLine(list + fmodes.popModeLine(FORMAT_NETWORK));
|
||||
|
||||
if (!c->topic.empty())
|
||||
{
|
||||
snprintf(list,MAXBUF,":%s FTOPIC %s %lu %s :%s", ServerInstance->Config->GetSID().c_str(), c->name.c_str(), (unsigned long)c->topicset, c->setby.c_str(), c->topic.c_str());
|
||||
WriteLine(list);
|
||||
}
|
||||
|
||||
for(Extensible::ExtensibleStore::const_iterator i = c->GetExtList().begin(); i != c->GetExtList().end(); i++)
|
||||
{
|
||||
ExtensionItem* item = i->first;
|
||||
std::string value = item->serialize(FORMAT_NETWORK, c, i->second);
|
||||
if (!value.empty())
|
||||
sync.SendMetaData(c, item->name, value);
|
||||
}
|
||||
|
||||
FOREACH_MOD(I_OnSyncChannel,OnSyncChannel(c, &sync));
|
||||
}
|
||||
|
||||
/** Send G, Q, Z and E lines */
|
||||
@ -183,28 +199,9 @@ void TreeSocket::SendXLines(TreeServer* Current)
|
||||
/** Send channel modes and topics */
|
||||
void TreeSocket::SendChannelModes(TreeServer* Current)
|
||||
{
|
||||
char data[MAXBUF];
|
||||
std::deque<std::string> list;
|
||||
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(Current, 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);
|
||||
}
|
||||
|
||||
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())
|
||||
sync.SendMetaData(c->second, item->name, value);
|
||||
}
|
||||
|
||||
FOREACH_MOD(I_OnSyncChannel,OnSyncChannel(c->second,&sync));
|
||||
SendFJoins(c->second);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -218,7 +218,7 @@ class TreeSocket : public BufferedSocket
|
||||
* If the length of a single line is more than 480-NICKMAX
|
||||
* in length, it is split over multiple lines.
|
||||
*/
|
||||
void SendFJoins(TreeServer* Current, Channel* c);
|
||||
void SendFJoins(Channel* c);
|
||||
|
||||
/** Send G, Q, Z and E lines */
|
||||
void SendXLines(TreeServer* Current);
|
||||
|
@ -289,6 +289,12 @@ void TreeSocket::ProcessConnectedLine(std::string& prefix, std::string& command,
|
||||
{
|
||||
this->Away(prefix,params);
|
||||
}
|
||||
else if (command == "RESYNC" && !params.empty())
|
||||
{
|
||||
Channel* chan = ServerInstance->FindChan(params[0]);
|
||||
if (chan)
|
||||
SendFJoins(chan);
|
||||
}
|
||||
else if (command == "PING")
|
||||
{
|
||||
this->LocalPing(prefix,params);
|
||||
|
Loading…
x
Reference in New Issue
Block a user