X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Fm_spanningtree.cpp;h=20c81bd95af8d3086f682bc479394b82d2e3d638;hb=69c3a32784b8c638ea10c269c3f63ede86b8aaa0;hp=ae9df6161948b92859d43d772dc0542512017394;hpb=f5ab16c85455ba88b08a669227f394dda96a55f9;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/modules/m_spanningtree.cpp b/src/modules/m_spanningtree.cpp index ae9df6161..20c81bd95 100644 --- a/src/modules/m_spanningtree.cpp +++ b/src/modules/m_spanningtree.cpp @@ -100,6 +100,7 @@ class Link : public classbase std::string EncryptionKey; bool HiddenFromStats; std::string FailOver; + int Timeout; }; /** Contains helper functions and variables for this module, @@ -124,6 +125,9 @@ class SpanningTreeUtilities /** Announce TS changes to channels on merge */ bool AnnounceTSChange; + /** Synchronize timestamps between servers + */ + bool EnableTimeSync; /** Socket bindings for listening sockets */ std::vector Bindings; @@ -247,7 +251,8 @@ class TreeServer : public classbase { Parent = NULL; VersionString = ""; - UserCount = OperCount = 0; + UserCount = ServerInstance->UserCount(); + OperCount = ServerInstance->OperCount(); VersionString = ServerInstance->GetVersionString(); Route = NULL; Socket = NULL; /* Fix by brain */ @@ -438,7 +443,7 @@ class TreeServer : public classbase return Parent; } - void SetVersion(std::string Version) + void SetVersion(const std::string &Version) { VersionString = Version; } @@ -1056,6 +1061,9 @@ class TreeSocket : public InspSocket { if ((Current) && (Current != Utils->TreeRoot)) { + Event rmode((char*)Current->GetName().c_str(), (Module*)Utils->Creator, "lost_server"); + rmode.Send(Instance); + std::deque params; params.push_back(Current->GetName()); params.push_back(":"+reason); @@ -1587,7 +1595,7 @@ class TreeSocket : public InspSocket /* default TS is a high value, which if we dont have this * channel will let the other side apply their modes. */ - time_t ourTS = time(NULL)+600; + time_t ourTS = Instance->Time(true)+600; /* Does this channel exist? if it does, get its REAL timestamp */ if (chan) @@ -1609,7 +1617,7 @@ class TreeSocket : public InspSocket /* Lower the TS here */ if (Utils->AnnounceTSChange && chan) chan->WriteChannelWithServ(Instance->Config->ServerName, - "TS for %s changed from %lu to %lu", chan->name, ourTS, TS); + "NOTICE %s :TS for %s changed from %lu to %lu", chan->name, chan->name, ourTS, TS); ourTS = TS; param_list.push_back(channel); @@ -1874,6 +1882,8 @@ class TreeSocket : public InspSocket */ void SendFJoins(TreeServer* Current, chanrec* c) { + std::string buffer; + Instance->Log(DEBUG,"Sending FJOINs to other server for %s",c->name); char list[MAXBUF]; std::string individual_halfops = std::string(":")+this->Instance->Config->ServerName+" FMODE "+c->name+" "+ConvToStr(c->age); @@ -1899,7 +1909,8 @@ class TreeSocket : public InspSocket if (curlen > (480-NICKMAX)) { - this->WriteLine(list); + buffer.append(list).append("\r\n"); + dlen = curlen = snprintf(list,MAXBUF,":%s FJOIN %s %lu",this->Instance->Config->ServerName,c->name,(unsigned long)c->age); ptr = list + dlen; ptrlen = 0; @@ -1908,64 +1919,83 @@ class TreeSocket : public InspSocket } if (numusers) - this->WriteLine(list); + buffer.append(list).append("\r\n"); - for (BanList::iterator b = c->bans.begin(); b != c->bans.end(); b++) - { + for (BanList::iterator b = c->bans.begin(); b != c->bans.end(); b++) + { modes.append("b"); - params.append(b->data).append(" "); - } - this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" FMODE "+c->name+" "+ConvToStr(c->age)+" +"+c->ChanModes(true)+modes+" "+params); + params.append(" ").append(b->data); + + if (params.length() >= MAXMODES) + { + /* Wrap at MAXMODES */ + buffer.append(":").append(this->Instance->Config->ServerName).append(" FMODE ").append(c->name).append(" ").append(ConvToStr(c->age)).append(" +").append(modes).append(params).append("\r\n"); + modes = ""; + params = ""; + } + } + + buffer.append(":").append(this->Instance->Config->ServerName).append(" FMODE ").append(c->name).append(" ").append(ConvToStr(c->age)).append(" +").append(c->ChanModes(true)); + + /* Only send these if there are any */ + if (!modes.empty()) + buffer.append("\r\n").append(":").append(this->Instance->Config->ServerName).append(" FMODE ").append(c->name).append(" ").append(ConvToStr(c->age)).append(" +").append(modes).append(params); + + this->WriteLine(buffer); } /** Send G, Q, Z and E lines */ void SendXLines(TreeServer* Current) { char data[MAXBUF]; + std::string buffer; std::string n = this->Instance->Config->ServerName; const char* sn = n.c_str(); int iterations = 0; /* Yes, these arent too nice looking, but they get the job done */ for (std::vector::iterator i = Instance->XLines->zlines.begin(); i != Instance->XLines->zlines.end(); i++, iterations++) { - snprintf(data,MAXBUF,":%s ADDLINE Z %s %s %lu %lu :%s",sn,(*i)->ipaddr,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason); - this->WriteLine(data); + snprintf(data,MAXBUF,":%s ADDLINE Z %s %s %lu %lu :%s\r\n",sn,(*i)->ipaddr,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason); + buffer.append(data); } for (std::vector::iterator i = Instance->XLines->qlines.begin(); i != Instance->XLines->qlines.end(); i++, iterations++) { - snprintf(data,MAXBUF,":%s ADDLINE Q %s %s %lu %lu :%s",sn,(*i)->nick,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason); - this->WriteLine(data); + snprintf(data,MAXBUF,":%s ADDLINE Q %s %s %lu %lu :%s\r\n",sn,(*i)->nick,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason); + buffer.append(data); } for (std::vector::iterator i = Instance->XLines->glines.begin(); i != Instance->XLines->glines.end(); i++, iterations++) { - snprintf(data,MAXBUF,":%s ADDLINE G %s %s %lu %lu :%s",sn,(*i)->hostmask,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason); - this->WriteLine(data); + snprintf(data,MAXBUF,":%s ADDLINE G %s@%s %s %lu %lu :%s\r\n",sn,(*i)->identmask,(*i)->hostmask,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason); + buffer.append(data); } for (std::vector::iterator i = Instance->XLines->elines.begin(); i != Instance->XLines->elines.end(); i++, iterations++) { - snprintf(data,MAXBUF,":%s ADDLINE E %s %s %lu %lu :%s",sn,(*i)->hostmask,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason); - this->WriteLine(data); + snprintf(data,MAXBUF,":%s ADDLINE E %s@%s %s %lu %lu :%s\r\n",sn,(*i)->identmask,(*i)->hostmask,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason); + buffer.append(data); } for (std::vector::iterator i = Instance->XLines->pzlines.begin(); i != Instance->XLines->pzlines.end(); i++, iterations++) { - snprintf(data,MAXBUF,":%s ADDLINE Z %s %s %lu %lu :%s",sn,(*i)->ipaddr,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason); - this->WriteLine(data); + snprintf(data,MAXBUF,":%s ADDLINE Z %s %s %lu %lu :%s\r\n",sn,(*i)->ipaddr,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason); + buffer.append(data); } for (std::vector::iterator i = Instance->XLines->pqlines.begin(); i != Instance->XLines->pqlines.end(); i++, iterations++) { - snprintf(data,MAXBUF,":%s ADDLINE Q %s %s %lu %lu :%s",sn,(*i)->nick,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason); - this->WriteLine(data); + snprintf(data,MAXBUF,":%s ADDLINE Q %s %s %lu %lu :%s\r\n",sn,(*i)->nick,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason); + buffer.append(data); } for (std::vector::iterator i = Instance->XLines->pglines.begin(); i != Instance->XLines->pglines.end(); i++, iterations++) { - snprintf(data,MAXBUF,":%s ADDLINE G %s %s %lu %lu :%s",sn,(*i)->hostmask,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason); - this->WriteLine(data); + snprintf(data,MAXBUF,":%s ADDLINE G %s@%s %s %lu %lu :%s\r\n",sn,(*i)->identmask,(*i)->hostmask,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason); + buffer.append(data); } for (std::vector::iterator i = Instance->XLines->pelines.begin(); i != Instance->XLines->pelines.end(); i++, iterations++) { - snprintf(data,MAXBUF,":%s ADDLINE E %s %s %lu %lu :%s",sn,(*i)->hostmask,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason); - this->WriteLine(data); + snprintf(data,MAXBUF,":%s ADDLINE E %s@%s %s %lu %lu :%s\r\n",sn,(*i)->identmask,(*i)->hostmask,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason); + buffer.append(data); } + + if (!buffer.empty()) + this->WriteLine(buffer); } /** Send channel modes and topics */ @@ -1999,6 +2029,7 @@ class TreeSocket : public InspSocket { char data[MAXBUF]; std::deque list; + std::string dataline; int iterations = 0; for (user_hash::iterator u = this->Instance->clientlist.begin(); u != this->Instance->clientlist.end(); u++, iterations++) { @@ -2008,11 +2039,13 @@ class TreeSocket : public InspSocket this->WriteLine(data); if (*u->second->oper) { - this->WriteLine(":"+std::string(u->second->nick)+" OPERTYPE "+std::string(u->second->oper)); + snprintf(data,MAXBUF,":%s OPERTYPE %s", u->second->nick, u->second->oper); + this->WriteLine(data); } if (*u->second->awaymsg) { - this->WriteLine(":"+std::string(u->second->nick)+" AWAY :"+std::string(u->second->awaymsg)); + snprintf(data,MAXBUF,":%s AWAY :%s", u->second->nick, u->second->awaymsg); + this->WriteLine(data); } FOREACH_MOD_I(this->Instance,I_OnSyncUser,OnSyncUser(u->second,(Module*)Utils->Creator,(void*)this)); list.clear(); @@ -2032,7 +2065,7 @@ class TreeSocket : public InspSocket */ void DoBurst(TreeServer* s) { - std::string burst = "BURST "+ConvToStr(time(NULL)); + std::string burst = "BURST "+ConvToStr(Instance->Time(true)); std::string endburst = "ENDBURST"; // Because by the end of the netburst, it could be gone! std::string name = s->GetName(); @@ -2078,8 +2111,8 @@ class TreeSocket : public InspSocket * chance of the \r being near the end of the * string, not the start. */ - if (ret.rfind("\r") != std::string::npos) - ret = in_buffer.substr(0,in_buffer.rfind("\r")-1); + if (ret.find("\r") != std::string::npos) + ret = in_buffer.substr(0,in_buffer.find("\r")-1); /* Process this one, abort if it * didnt return true. */ @@ -2111,7 +2144,10 @@ class TreeSocket : public InspSocket } } } - return this->ProcessLine(ret); + if (!this->ProcessLine(ret)) + { + return false; + } } return true; } @@ -2598,7 +2634,7 @@ class TreeSocket : public InspSocket char idle[MAXBUF]; snprintf(signon,MAXBUF,"%lu",(unsigned long)x->signon); - snprintf(idle,MAXBUF,"%lu",(unsigned long)abs((x->idle_lastmsg)-time(NULL))); + snprintf(idle,MAXBUF,"%lu",(unsigned long)abs((x->idle_lastmsg)-Instance->Time(true))); std::deque par; par.push_back(prefix); par.push_back(signon); @@ -2658,6 +2694,45 @@ class TreeSocket : public InspSocket return true; } + bool HandleSetTime(const std::string &prefix, std::deque ¶ms) + { + if (!params.size() || !Utils->EnableTimeSync) + return true; + + bool force = false; + + if ((params.size() == 2) && (params[1] == "FORCE")) + force = true; + + time_t rts = atoi(params[0].c_str()); + time_t us = Instance->Time(true); + + if (rts == us) + { + Instance->Log(DEBUG, "Timestamp from %s is equal", prefix.c_str()); + + Utils->DoOneToAllButSender(prefix, "TIMESET", params, prefix); + } + else if (force || (rts < us)) + { + int old = Instance->SetTimeDelta(rts - us); + Instance->Log(DEBUG, "%s TS (diff %d) from %s applied (old delta was %d)", (force) ? "Forced" : "Lower", rts - us, prefix.c_str(), old); + + Utils->DoOneToAllButSender(prefix, "TIMESET", params, prefix); + } + else + { + Instance->Log(DEBUG, "Higher TS (diff %d) from %s overridden", us - rts, prefix.c_str()); + + std::deque oparams; + oparams.push_back(ConvToStr(us)); + + Utils->DoOneToMany(prefix, "TIMESET", oparams); + } + + return true; + } + bool Time(const std::string &prefix, std::deque ¶ms) { // :source.server TIME remote.server sendernick @@ -2670,9 +2745,7 @@ class TreeSocket : public InspSocket userrec* u = this->Instance->FindNick(params[1]); if (u) { - char curtime[256]; - snprintf(curtime,256,"%lu",(unsigned long)time(NULL)); - params.push_back(curtime); + params.push_back(ConvToStr(Instance->Time(false))); params[0] = prefix; Utils->DoOneToOne(this->Instance->Config->ServerName,"TIME",params,params[0]); } @@ -3043,20 +3116,40 @@ class TreeSocket : public InspSocket } else if (command == "BURST") { - if (params.size()) + if (params.size() && Utils->EnableTimeSync) { - /* If a time stamp is provided, try and check syncronization */ - time_t THEM = atoi(params[0].c_str()); - long delta = THEM-time(NULL); + /* If a time stamp is provided, apply synchronization */ + bool force = false; + time_t them = atoi(params[0].c_str()); + time_t us = Instance->Time(true); + int delta = them - us; + + if ((params.size() == 2) && (params[1] == "FORCE")) + force = true; + if ((delta < -600) || (delta > 600)) { this->Instance->SNO->WriteToSnoMask('l',"\2ERROR\2: Your clocks are out by %d seconds (this is more than ten minutes). Link aborted, \2PLEASE SYNC YOUR CLOCKS!\2",abs(delta)); this->WriteLine("ERROR :Your clocks are out by "+ConvToStr(abs(delta))+" seconds (this is more than ten minutes). Link aborted, PLEASE SYNC YOUR CLOCKS!"); return false; } - else if ((delta < -60) || (delta > 60)) + + if (us == them) { - this->Instance->SNO->WriteToSnoMask('l',"\2WARNING\2: Your clocks are out by %d seconds, please consider synching your clocks.",abs(delta)); + this->Instance->Log(DEBUG, "Timestamps are equal; pat yourself on the back"); + } + else if (force || (us > them)) + { + this->Instance->Log(DEBUG, "Remote server has lower TS (%d seconds)", them - us); + this->Instance->SetTimeDelta(them - us); + // Send this new timestamp to any other servers + Utils->DoOneToMany(Utils->TreeRoot->GetName(), "TIMESET", params); + } + else + { + // Override the timestamp + this->Instance->Log(DEBUG, "We have a higher timestamp (by %d seconds), not updating delta", us - them); + this->WriteLine(":" + Utils->TreeRoot->GetName() + " TIMESET " + ConvToStr(us)); } } this->LinkState = CONNECTED; @@ -3265,6 +3358,10 @@ class TreeSocket : public InspSocket { return this->Push(prefix,params); } + else if (command == "TIMESET") + { + return this->HandleSetTime(prefix, params); + } else if (command == "TIME") { return this->Time(prefix,params); @@ -3315,6 +3412,10 @@ class TreeSocket : public InspSocket sourceserv = this->InboundServerName; } this->Instance->SNO->WriteToSnoMask('l',"Received end of netburst from \2%s\2",sourceserv.c_str()); + + Event rmode((char*)sourceserv.c_str(), (Module*)Utils->Creator, "new_server"); + rmode.Send(Instance); + return true; } else @@ -3435,7 +3536,9 @@ class TreeSocket : public InspSocket { Squit(s,"Remote host closed the connection"); } - this->Instance->SNO->WriteToSnoMask('l',"Connection to '\2%s\2' failed.",quitserver.c_str()); + + if (quitserver != "") + this->Instance->SNO->WriteToSnoMask('l',"Connection to '\2%s\2' failed.",quitserver.c_str()); } virtual int OnIncomingConnection(int newsock, char* ip) @@ -3482,7 +3585,7 @@ class ServernameResolver : public Resolver Link MyLink; SpanningTreeUtilities* Utils; public: - ServernameResolver(SpanningTreeUtilities* Util, InspIRCd* Instance, const std::string &hostname, Link x) : Resolver(Instance, hostname, DNS_QUERY_FORWARD), MyLink(x), Utils(Util) + ServernameResolver(Module* me, SpanningTreeUtilities* Util, InspIRCd* Instance, const std::string &hostname, Link x) : Resolver(Instance, hostname, DNS_QUERY_FORWARD, me), MyLink(x), Utils(Util) { /* Nothing in here, folks */ } @@ -3496,7 +3599,7 @@ class ServernameResolver : public Resolver 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(this->Utils, ServerInstance, result,MyLink.Port,false,10,MyLink.Name.c_str()); + TreeSocket* newsocket = new TreeSocket(this->Utils, ServerInstance, result,MyLink.Port,false,MyLink.Timeout ? MyLink.Timeout : 10,MyLink.Name.c_str()); if (newsocket->GetFd() > -1) { /* We're all OK */ @@ -3527,7 +3630,7 @@ class SecurityIPResolver : public Resolver Link MyLink; SpanningTreeUtilities* Utils; public: - SecurityIPResolver(SpanningTreeUtilities* U, InspIRCd* Instance, const std::string &hostname, Link x) : Resolver(Instance, hostname, DNS_QUERY_FORWARD), MyLink(x), Utils(U) + SecurityIPResolver(Module* me, SpanningTreeUtilities* U, InspIRCd* Instance, const std::string &hostname, Link x) : Resolver(Instance, hostname, DNS_QUERY_FORWARD, me), MyLink(x), Utils(U) { } @@ -3768,33 +3871,38 @@ void SpanningTreeUtilities::ReadConfiguration(bool rebind) { std::string Type = Conf->ReadValue("bind","type",j); std::string IP = Conf->ReadValue("bind","address",j); - int Port = Conf->ReadInteger("bind","port",j,true); + std::string Port = Conf->ReadValue("bind","port",j); if (Type == "servers") { - ServerInstance->Log(DEBUG,"m_spanningtree: Binding server port %s:%d", IP.c_str(), Port); - if (IP == "*") - { - IP = ""; - } - TreeSocket* listener = new TreeSocket(this, ServerInstance, IP.c_str(),Port,true,10); - if (listener->GetState() == I_LISTENING) - { - ServerInstance->Log(DEFAULT,"m_spanningtree: Binding server port %s:%d successful!", IP.c_str(), Port); - Bindings.push_back(listener); - } - else + irc::portparser portrange(Port); + int portno = -1; + while ((portno = portrange.GetToken())) { - ServerInstance->Log(DEFAULT,"m_spanningtree: Warning: Failed to bind server port %d",Port); - listener->Close(); - DELETE(listener); + ServerInstance->Log(DEBUG,"m_spanningtree: Binding server port %s:%d", IP.c_str(), portno); + if (IP == "*") + IP = ""; + + TreeSocket* listener = new TreeSocket(this, ServerInstance, IP.c_str(), portno, true, 10); + if (listener->GetState() == I_LISTENING) + { + ServerInstance->Log(DEFAULT,"m_spanningtree: Binding server port %s:%d successful!", IP.c_str(), portno); + Bindings.push_back(listener); + } + else + { + ServerInstance->Log(DEFAULT,"m_spanningtree: Warning: Failed to bind server port %s:%d",IP.c_str(), portno); + listener->Close(); + DELETE(listener); + } + ServerInstance->Log(DEBUG,"Done with this binding"); } - ServerInstance->Log(DEBUG,"Done with this binding"); } } } FlatLinks = Conf->ReadFlag("options","flatlinks",0); HideULines = Conf->ReadFlag("options","hideulines",0); AnnounceTSChange = Conf->ReadFlag("options","announcets",0); + EnableTimeSync = !(Conf->ReadFlag("options","notimesync",0)); LinkBlocks.clear(); ValidIPs.clear(); for (int j =0; j < Conf->Enumerate("link"); j++) @@ -3810,6 +3918,7 @@ void SpanningTreeUtilities::ReadConfiguration(bool rebind) L.AutoConnect = Conf->ReadInteger("link","autoconnect",j,true); L.EncryptionKey = Conf->ReadValue("link","encryptionkey",j); L.HiddenFromStats = Conf->ReadFlag("link","hidden",j); + L.Timeout = Conf->ReadInteger("link","timeout",j,true); L.NextConnectTime = time(NULL) + L.AutoConnect; /* Bugfix by brain, do not allow people to enter bad configurations */ if (L.Name != ServerInstance->Config->ServerName) @@ -3827,7 +3936,7 @@ void SpanningTreeUtilities::ReadConfiguration(bool rebind) { try { - SecurityIPResolver* sr = new SecurityIPResolver(this, ServerInstance, L.IPAddr, L); + SecurityIPResolver* sr = new SecurityIPResolver((Module*)this->Creator, this, ServerInstance, L.IPAddr, L); ServerInstance->AddResolver(sr); } catch (ModuleException& e) @@ -3871,7 +3980,19 @@ void SpanningTreeUtilities::ReadConfiguration(bool rebind) DELETE(Conf); } - +/** To create a timer which recurs every second, we inherit from InspTimer. + * InspTimer is only one-shot however, so at the end of each Tick() we simply + * insert another of ourselves into the pending queue :) + */ +class TimeSyncTimer : public InspTimer +{ + private: + InspIRCd *Instance; + ModuleSpanningTree *Module; + public: + TimeSyncTimer(InspIRCd *Instance, ModuleSpanningTree *Mod); + virtual void Tick(time_t TIME); +}; class ModuleSpanningTree : public Module { @@ -3883,6 +4004,7 @@ class ModuleSpanningTree : public Module SpanningTreeUtilities* Utils; public: + TimeSyncTimer *SyncTimer; ModuleSpanningTree(InspIRCd* Me) : Module::Module(Me), max_local(0), max_global(0) @@ -3891,6 +4013,14 @@ class ModuleSpanningTree : public Module command_rconnect = new cmd_rconnect(ServerInstance, this, Utils); ServerInstance->AddCommand(command_rconnect); + + if (Utils->EnableTimeSync) + { + SyncTimer = new TimeSyncTimer(ServerInstance, this); + ServerInstance->Timers->AddTimer(SyncTimer); + } + else + SyncTimer = NULL; } void ShowLinks(TreeServer* Current, userrec* user, int hops) @@ -4266,7 +4396,7 @@ class ModuleSpanningTree : public Module /* Do we already have an IP? If so, no need to resolve it. */ if (insp_aton(x->IPAddr.c_str(), &binip) > 0) { - TreeSocket* newsocket = new TreeSocket(Utils, ServerInstance, x->IPAddr,x->Port,false,10,x->Name.c_str()); + TreeSocket* newsocket = new TreeSocket(Utils, ServerInstance, x->IPAddr,x->Port,false,x->Timeout ? x->Timeout : 10,x->Name.c_str()); if (newsocket->GetFd() > -1) { /* Handled automatically on success */ @@ -4282,7 +4412,7 @@ class ModuleSpanningTree : public Module { try { - ServernameResolver* snr = new ServernameResolver(Utils, ServerInstance,x->IPAddr, *x); + ServernameResolver* snr = new ServernameResolver((Module*)this, Utils, ServerInstance,x->IPAddr, *x); ServerInstance->AddResolver(snr); } catch (ModuleException& e) @@ -4385,6 +4515,13 @@ class ModuleSpanningTree : public Module return 1; } + void BroadcastTimeSync() + { + std::deque params; + params.push_back(ConvToStr(ServerInstance->Time(true))); + Utils->DoOneToMany(Utils->TreeRoot->GetName(), "TIMESET", params); + } + virtual int OnStats(char statschar, userrec* user, string_list &results) { if (statschar == 'c') @@ -4799,26 +4936,38 @@ class ModuleSpanningTree : public Module void OnLine(userrec* source, const std::string &host, bool adding, char linetype, long duration, const std::string &reason) { - if (IS_LOCAL(source)) + if (!source) { - char type[8]; - snprintf(type,8,"%cLINE",linetype); - std::string stype = type; - if (adding) - { - char sduration[MAXBUF]; - snprintf(sduration,MAXBUF,"%ld",duration); - std::deque params; - params.push_back(host); - params.push_back(sduration); - params.push_back(":"+reason); - Utils->DoOneToMany(source->nick,stype,params); - } - else + /* Server-set lines */ + char data[MAXBUF]; + snprintf(data,MAXBUF,"%c %s %s %lu %lu :%s", linetype, host.c_str(), ServerInstance->Config->ServerName, ServerInstance->Time(false), duration, reason.c_str()); + std::deque params; + params.push_back(data); + Utils->DoOneToMany(ServerInstance->Config->ServerName, "ADDLINE", params); + } + else + { + if (IS_LOCAL(source)) { - std::deque params; - params.push_back(host); - Utils->DoOneToMany(source->nick,stype,params); + char type[8]; + snprintf(type,8,"%cLINE",linetype); + std::string stype = type; + if (adding) + { + char sduration[MAXBUF]; + snprintf(sduration,MAXBUF,"%ld",duration); + std::deque params; + params.push_back(host); + params.push_back(sduration); + params.push_back(":"+reason); + Utils->DoOneToMany(source->nick,stype,params); + } + else + { + std::deque params; + params.push_back(host); + Utils->DoOneToMany(source->nick,stype,params); + } } } } @@ -4963,7 +5112,7 @@ class ModuleSpanningTree : public Module return; (*params)[1] = ":" + (*params)[1]; params->insert(params->begin() + 1,ServerInstance->Config->ServerName); - params->insert(params->begin() + 1,ConvToStr(ServerInstance->Time())); + params->insert(params->begin() + 1,ConvToStr(ServerInstance->Time(true))); Utils->DoOneToMany(ServerInstance->Config->ServerName,"FTOPIC",*params); } else if (event->GetEventID() == "send_mode") @@ -4988,6 +5137,19 @@ class ModuleSpanningTree : public Module params->insert(params->begin() + 1,ConvToStr(ourTS)); Utils->DoOneToMany(ServerInstance->Config->ServerName,"FMODE",*params); } + else if (event->GetEventID() == "send_push") + { + if (params->size() < 2) + return; + + userrec *a = ServerInstance->FindNick((*params)[0]); + + if (!a) + return; + + (*params)[1] = ":" + (*params)[1]; + Utils->DoOneToOne(ServerInstance->Config->ServerName, "PUSH", *params, a->server); + } } virtual ~ModuleSpanningTree() @@ -4995,6 +5157,8 @@ class ModuleSpanningTree : public Module ServerInstance->Log(DEBUG,"Performing unload of spanningtree!"); /* This will also free the listeners */ delete Utils; + if (SyncTimer) + ServerInstance->Timers->DelTimer(SyncTimer); } virtual Version GetVersion() @@ -5026,6 +5190,17 @@ class ModuleSpanningTree : public Module } }; +TimeSyncTimer::TimeSyncTimer(InspIRCd *Inst, ModuleSpanningTree *Mod) : InspTimer(43200, Inst->Time()), Instance(Inst), Module(Mod) +{ +} + +void TimeSyncTimer::Tick(time_t TIME) +{ + Module->BroadcastTimeSync(); + Module->SyncTimer = new TimeSyncTimer(Instance, Module); + Instance->Timers->AddTimer(Module->SyncTimer); +} + void SpanningTreeUtilities::DoFailOver(Link* x) { if (x->FailOver.length()) @@ -5060,7 +5235,6 @@ Link* SpanningTreeUtilities::FindLink(const std::string& name) return NULL; } - class ModuleSpanningTreeFactory : public ModuleFactory { public: