diff options
| author | Adam <Adam@anope.org> | 2014-11-24 14:27:23 -0500 |
|---|---|---|
| committer | Adam <Adam@anope.org> | 2014-11-24 14:27:23 -0500 |
| commit | 42238034490fb5479d787bd1695750387d508200 (patch) | |
| tree | c93c62e0e1c936e656ae5b9ee1b62380ce2a194c /src | |
| parent | d492923610d9c9146b2a2b63de38deab2cfd4ca7 (diff) | |
Rewrite serializable to have field level granularity
Represent serializable objects in a digraph, and as a result made most
object relationships implicitly defined, and use the graph to trace
references between objects to determine relationships. Edges may
also be marked as having a dependency of the object they point to,
which allows for automatic cleanup and deletion of most objects when
no longer needed.
Additionally, this allows not having to require in-memory copies of
everything when using external databases. db_sql has been rewritten
for this and now always requires a database to function. db_sql with
MySQL now requires InnoDB to make use of transactions and foreign
key constraints.
Diffstat (limited to 'src')
| -rw-r--r-- | src/bots.cpp | 210 | ||||
| -rw-r--r-- | src/command.cpp | 16 | ||||
| -rw-r--r-- | src/config.cpp | 103 | ||||
| -rw-r--r-- | src/event.cpp | 6 | ||||
| -rw-r--r-- | src/extensible.cpp | 41 | ||||
| -rw-r--r-- | src/hashcomp.cpp | 4 | ||||
| -rw-r--r-- | src/init.cpp | 29 | ||||
| -rw-r--r-- | src/language.cpp | 4 | ||||
| -rw-r--r-- | src/logger.cpp | 22 | ||||
| -rw-r--r-- | src/mail.cpp | 16 | ||||
| -rw-r--r-- | src/main.cpp | 1 | ||||
| -rw-r--r-- | src/messages.cpp | 20 | ||||
| -rw-r--r-- | src/misc.cpp | 6 | ||||
| -rw-r--r-- | src/modulemanager.cpp | 2 | ||||
| -rw-r--r-- | src/opertype.cpp | 80 | ||||
| -rw-r--r-- | src/pipeengine.cpp | 7 | ||||
| -rw-r--r-- | src/protocol.cpp | 4 | ||||
| -rw-r--r-- | src/serialize.cpp | 318 | ||||
| -rw-r--r-- | src/servers.cpp | 16 | ||||
| -rw-r--r-- | src/uplink.cpp | 6 | ||||
| -rw-r--r-- | src/users.cpp | 108 | ||||
| -rw-r--r-- | src/version.sh | 2 | ||||
| -rw-r--r-- | src/xline.cpp | 332 |
23 files changed, 750 insertions, 603 deletions
diff --git a/src/bots.cpp b/src/bots.cpp index 6f5c66388..697115ea0 100644 --- a/src/bots.cpp +++ b/src/bots.cpp @@ -20,17 +20,12 @@ #include "event.h" #include "modules/chanserv.h" -Serialize::Checker<botinfo_map> BotListByNick("BotInfo"), BotListByUID("BotInfo"); - -BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const Anope::string &nhost, const Anope::string &nreal, const Anope::string &bmodes) : User(nnick, nuser, nhost, "", "", Me, nreal, Anope::CurTime, "", IRCD ? IRCD->UID_Retrieve() : "", NULL), Serializable("BotInfo"), channels("ChannelInfo"), botmodes(bmodes) +ServiceBot::ServiceBot(const Anope::string &nnick, const Anope::string &nuser, const Anope::string &nhost, const Anope::string &nreal, const Anope::string &bmodes) : LocalUser(nnick, nuser, nhost, "", "", Me, nreal, Anope::CurTime, "", IRCD ? IRCD->UID_Retrieve() : "", NULL), botmodes(bmodes) { - this->lastmsg = this->created = Anope::CurTime; + this->type = UserType::BOT; + this->lastmsg = Anope::CurTime; this->introduced = false; - this->oper_only = this->conf = false; - - (*BotListByNick)[this->nick] = this; - if (!this->uid.empty()) - (*BotListByUID)[this->uid] = this; + this->conf = false; Event::OnCreateBot(&Event::CreateBot::OnCreateBot, this); @@ -41,14 +36,15 @@ BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const A if (!tmodes.empty()) this->SetModesInternal(this, tmodes.c_str()); - XLine x(this->nick, "Reserved for services"); - IRCD->SendSQLine(NULL, &x); + //XXX + //XLine x(this->nick, "Reserved for services"); + //IRCD->SendSQLine(NULL, &x); IRCD->SendClientIntroduction(this); this->introduced = true; } } -BotInfo::~BotInfo() +ServiceBot::~ServiceBot() { Event::OnDelBot(&Event::DelBot::OnDelBot, this); @@ -58,73 +54,25 @@ BotInfo::~BotInfo() IRCD->SendQuit(this, ""); Event::OnUserQuit(&Event::UserQuit::OnUserQuit, this, ""); this->introduced = false; - XLine x(this->nick); - IRCD->SendSQLineDel(&x); - } - - for (std::set<ChanServ::Channel *>::iterator it = this->channels->begin(), it_end = this->channels->end(); it != it_end; ++it) - { - ChanServ::Channel *ci = *it; - this->UnAssign(NULL, ci); + // XXX ? + //XLine x(this->nick); + //IRCD->SendSQLineDel(&x); } - - BotListByNick->erase(this->nick); - if (!this->uid.empty()) - BotListByUID->erase(this->uid); } -void BotInfo::Serialize(Serialize::Data &data) const -{ - data["nick"] << this->nick; - data["user"] << this->ident; - data["host"] << this->host; - data["realname"] << this->realname; - data["created"] << this->created; - data["oper_only"] << this->oper_only; - - Extensible::ExtensibleSerialize(this, this, data); -} -Serializable* BotInfo::Unserialize(Serializable *obj, Serialize::Data &data) -{ - Anope::string nick, user, host, realname, flags; - - data["nick"] >> nick; - data["user"] >> user; - data["host"] >> host; - data["realname"] >> realname; - - BotInfo *bi; - if (obj) - bi = anope_dynamic_static_cast<BotInfo *>(obj); - else if (!(bi = BotInfo::Find(nick, true))) - bi = new BotInfo(nick, user, host, realname); - - data["created"] >> bi->created; - data["oper_only"] >> bi->oper_only; - - Extensible::ExtensibleUnserialize(bi, bi, data); - - return bi; -} - -void BotInfo::GenerateUID() +void ServiceBot::GenerateUID() { if (this->introduced) throw CoreException("Changing bot UID when it is introduced?"); if (!this->uid.empty()) - { - BotListByUID->erase(this->uid); UserListByUID.erase(this->uid); - } - this->uid = IRCD->UID_Retrieve(); - (*BotListByUID)[this->uid] = this; UserListByUID[this->uid] = this; } -void BotInfo::OnKill() +void ServiceBot::OnKill() { this->introduced = false; this->GenerateUID(); @@ -135,63 +83,60 @@ void BotInfo::OnKill() IRCD->SendJoin(this, cit->second->chan, &cit->second->status); } -void BotInfo::SetNewNick(const Anope::string &newnick) +void ServiceBot::SetNewNick(const Anope::string &newnick) { UserListByNick.erase(this->nick); - BotListByNick->erase(this->nick); + bi->SetNick(newnick); this->nick = newnick; UserListByNick[this->nick] = this; - (*BotListByNick)[this->nick] = this; } -const std::set<ChanServ::Channel *> &BotInfo::GetChannels() const +std::vector<ChanServ::Channel *> ServiceBot::GetChannels() const { - return this->channels; + return bi->GetRefs<ChanServ::Channel *>(ChanServ::channel); } -void BotInfo::Assign(User *u, ChanServ::Channel *ci) +void ServiceBot::Assign(User *u, ChanServ::Channel *ci) { EventReturn MOD_RESULT; MOD_RESULT = Event::OnPreBotAssign(&Event::PreBotAssign::OnPreBotAssign, u, ci, this); if (MOD_RESULT == EVENT_STOP) return; - if (ci->bi) - ci->bi->UnAssign(u, ci); + if (ci->GetBot()) + ci->GetBot()->UnAssign(u, ci); - ci->bi = this; - this->channels->insert(ci); + ci->SetBot(this); Event::OnBotAssign(&Event::BotAssign::OnBotAssign, u, ci, this); } -void BotInfo::UnAssign(User *u, ChanServ::Channel *ci) +void ServiceBot::UnAssign(User *u, ChanServ::Channel *ci) { EventReturn MOD_RESULT; MOD_RESULT = Event::OnBotUnAssign(&Event::BotUnAssign::OnBotUnAssign, u, ci); if (MOD_RESULT == EVENT_STOP) return; - if (ci->c && ci->c->FindUser(ci->bi)) + if (ci->c && ci->c->FindUser(ci->GetBot())) { if (u) - ci->bi->Part(ci->c, "UNASSIGN from " + u->nick); + ci->GetBot()->Part(ci->c, "UNASSIGN from " + u->nick); else - ci->bi->Part(ci->c); + ci->GetBot()->Part(ci->c); } - ci->bi = NULL; - this->channels->erase(ci); + ci->SetBot(nullptr); } -unsigned BotInfo::GetChannelCount() const +unsigned ServiceBot::GetChannelCount() const { - return this->channels->size(); + return GetChannels().size(); } -void BotInfo::Join(Channel *c, ChannelStatus *status) +void ServiceBot::Join(Channel *c, ChannelStatus *status) { if (c->FindUser(this) != NULL) return; @@ -203,13 +148,13 @@ void BotInfo::Join(Channel *c, ChannelStatus *status) Event::OnJoinChannel(&Event::JoinChannel::OnJoinChannel, this, c); } -void BotInfo::Join(const Anope::string &chname, ChannelStatus *status) +void ServiceBot::Join(const Anope::string &chname, ChannelStatus *status) { bool c; return this->Join(Channel::FindOrCreate(chname, c), status); } -void BotInfo::Part(Channel *c, const Anope::string &reason) +void ServiceBot::Part(Channel *c, const Anope::string &reason) { if (c->FindUser(this) == NULL) return; @@ -226,7 +171,7 @@ void BotInfo::Part(Channel *c, const Anope::string &reason) Event::OnPartChannel(&Event::PartChannel::OnPartChannel, this, cref, cname, reason); } -void BotInfo::OnMessage(User *u, const Anope::string &message) +void ServiceBot::OnMessage(User *u, const Anope::string &message) { if (this->commands.empty()) return; @@ -235,7 +180,7 @@ void BotInfo::OnMessage(User *u, const Anope::string &message) Command::Run(source, message); } -CommandInfo& BotInfo::SetCommand(const Anope::string &cname, const Anope::string &sname, const Anope::string &permission) +CommandInfo& ServiceBot::SetCommand(const Anope::string &cname, const Anope::string &sname, const Anope::string &permission) { CommandInfo ci; ci.name = sname; @@ -245,7 +190,7 @@ CommandInfo& BotInfo::SetCommand(const Anope::string &cname, const Anope::string return this->commands[cname]; } -CommandInfo *BotInfo::GetCommand(const Anope::string &cname) +CommandInfo *ServiceBot::GetCommand(const Anope::string &cname) { CommandInfo::map::iterator it = this->commands.find(cname); if (it != this->commands.end()) @@ -253,7 +198,7 @@ CommandInfo *BotInfo::GetCommand(const Anope::string &cname) return NULL; } -CommandInfo *BotInfo::FindCommand(const Anope::string &service) +CommandInfo *ServiceBot::FindCommand(const Anope::string &service) { for (auto& it : commands) { @@ -266,30 +211,71 @@ CommandInfo *BotInfo::FindCommand(const Anope::string &service) return nullptr; } -BotInfo* BotInfo::Find(const Anope::string &nick, bool nick_only) +ServiceBot* ServiceBot::Find(const Anope::string &nick, bool nick_only) { - if (!nick_only && IRCD != NULL && IRCD->RequiresID) - { - botinfo_map::iterator it = BotListByUID->find(nick); - if (it != BotListByUID->end()) - { - BotInfo *bi = it->second; - bi->QueueUpdate(); - return bi; - } - - if (IRCD->AmbiguousID) - return NULL; - } + User *u = User::Find(nick, nick_only); + if (u && u->type == UserType::BOT) + return anope_dynamic_static_cast<ServiceBot *>(u); + return nullptr; +} - botinfo_map::iterator it = BotListByNick->find(nick); - if (it != BotListByNick->end()) - { - BotInfo *bi = it->second; - bi->QueueUpdate(); - return bi; - } +void BotInfo::SetCreated(const time_t &t) +{ + Set(&BotInfoType::created, t); +} - return NULL; +time_t BotInfo::GetCreated() +{ + return Get(&BotInfoType::created); +} + +void BotInfo::SetOperOnly(const bool &b) +{ + Set(&BotInfoType::operonly, b); +} + +bool BotInfo::GetOperOnly() +{ + return Get(&BotInfoType::operonly); +} + +void BotInfo::SetNick(const Anope::string &nick) +{ + Set(&BotInfoType::nick, nick); +} + +Anope::string BotInfo::GetNick() +{ + return Get(&BotInfoType::nick); +} + +void BotInfo::SetUser(const Anope::string &user) +{ + Set(&BotInfoType::user, user); +} + +Anope::string BotInfo::GetUser() +{ + return Get(&BotInfoType::user); +} + +void BotInfo::SetHost(const Anope::string &host) +{ + Set(&BotInfoType::host, host); +} + +Anope::string BotInfo::GetHost() +{ + return Get(&BotInfoType::host); +} + +void BotInfo::SetRealName(const Anope::string &realname) +{ + Set(&BotInfoType::realname, realname); +} + +Anope::string BotInfo::GetRealName() +{ + return Get(&BotInfoType::realname); } diff --git a/src/command.cpp b/src/command.cpp index 59db22a4b..c387ddaab 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -20,7 +20,7 @@ #include "modules/botserv.h" #include "modules/chanserv.h" -CommandSource::CommandSource(const Anope::string &n, User *user, NickServ::Account *core, CommandReply *r, BotInfo *bi) : nick(n), u(user), nc(core), reply(r), +CommandSource::CommandSource(const Anope::string &n, User *user, NickServ::Account *core, CommandReply *r, ServiceBot *bi) : nick(n), u(user), nc(core), reply(r), c(NULL), service(bi) { } @@ -64,7 +64,7 @@ bool CommandSource::HasCommand(const Anope::string &cmd) if (this->u) return this->u->HasCommand(cmd); else if (this->nc && this->nc->o) - return this->nc->o->ot->HasCommand(cmd); + return this->nc->o->GetType()->HasCommand(cmd); return false; } @@ -73,7 +73,7 @@ bool CommandSource::HasPriv(const Anope::string &cmd) if (this->u) return this->u->HasPriv(cmd); else if (this->nc && this->nc->o) - return this->nc->o->ot->HasPriv(cmd); + return this->nc->o->GetType()->HasPriv(cmd); return false; } @@ -274,13 +274,17 @@ void Command::Run(CommandSource &source, const Anope::string &message) Event::OnPostCommand(&Event::PostCommand::OnPostCommand, source, c, params); } -bool Command::FindCommandFromService(const Anope::string &command_service, BotInfo* &bot, Anope::string &name) +bool Command::FindCommandFromService(const Anope::string &command_service, ServiceBot* &bot, Anope::string &name) { bot = NULL; - for (botinfo_map::iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it) + for (std::pair<Anope::string, User *> p : UserListByNick) { - BotInfo *bi = it->second; + User *u = p.second; + if (u->type != UserType::BOT) + continue; + + ServiceBot *bi = anope_dynamic_static_cast<ServiceBot *>(u); for (CommandInfo::map::const_iterator cit = bi->commands.begin(), cit_end = bi->commands.end(); cit != cit_end; ++cit) { diff --git a/src/config.cpp b/src/config.cpp index d0575a88c..2bdb71f5e 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -17,6 +17,7 @@ #include "hashcomp.h" #include "event.h" #include "bots.h" +#include "modules.h" #include "modules/nickserv.h" using namespace Configuration; @@ -288,18 +289,26 @@ Conf::Conf() : Block("") if (ot == NULL) throw ConfigException("Oper block for " + nname + " has invalid oper type " + type); - Oper *o = new Oper(nname, ot); - o->require_oper = require_oper; - o->password = password; - o->certfp = certfp; - spacesepstream(host).GetTokens(o->hosts); - o->vhost = vhost; - - this->Opers.push_back(o); + Oper *o = operblock.Create(); + o->conf = this; + o->SetName(nname); + o->SetType(ot); + o->SetRequireOper(require_oper); + o->SetPassword(password); + o->SetCertFP(certfp); + o->SetHost(host); + o->SetVhost(vhost); } - for (botinfo_map::const_iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it) - it->second->conf = false; + for (std::pair<Anope::string, User *> p : UserListByNick) + { + User *u = p.second; + if (u->type != UserType::BOT) + continue; + + ServiceBot *bi = anope_dynamic_static_cast<ServiceBot *>(u); + bi->conf = false; + } for (int i = 0; i < this->CountBlock("service"); ++i) { Block *service = this->GetBlock("service", i); @@ -317,9 +326,9 @@ Conf::Conf() : Block("") ValidateNotEmpty("service", "gecos", gecos); ValidateNoSpaces("service", "channels", channels); - BotInfo *bi = BotInfo::Find(nick, true); + ServiceBot *bi = ServiceBot::Find(nick, true); if (!bi) - bi = new BotInfo(nick, user, host, gecos, modes); + bi = new ServiceBot(nick, user, host, gecos, modes); bi->conf = true; std::vector<Anope::string> oldchannels = bi->botchannels; @@ -396,7 +405,7 @@ Conf::Conf() : Block("") LogInfo l(logage, rawio, debug); - l.bot = BotInfo::Find(log->Get<const Anope::string>("bot", "Global"), true); + l.bot = ServiceBot::Find(log->Get<const Anope::string>("bot", "Global"), true); spacesepstream(log->Get<const Anope::string>("target")).GetTokens(l.targets); spacesepstream(log->Get<const Anope::string>("source")).GetTokens(l.sources); spacesepstream(log->Get<const Anope::string>("admin")).GetTokens(l.admin); @@ -410,8 +419,15 @@ Conf::Conf() : Block("") this->LogInfos.push_back(l); } - for (botinfo_map::const_iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it) - it->second->commands.clear(); + for (std::pair<Anope::string, User *> p : UserListByNick) + { + User *u = p.second; + if (u->type != UserType::BOT) + continue; + + ServiceBot *bi = anope_dynamic_static_cast<ServiceBot *>(u); + bi->commands.clear(); + } for (int i = 0; i < this->CountBlock("command"); ++i) { Block *command = this->GetBlock("command", i); @@ -427,7 +443,7 @@ Conf::Conf() : Block("") ValidateNotEmpty("command", "name", nname); ValidateNotEmpty("command", "command", cmd); - BotInfo *bi = this->GetClient(service); + ServiceBot *bi = this->GetClient(service); if (!bi) continue; @@ -475,30 +491,21 @@ Conf::Conf() : Block("") /* Below here can't throw */ + /* Clear existing conf opers */ if (Config) - /* Clear existing conf opers */ - if (NickServ::service) - { - NickServ::nickcore_map& ncmap = NickServ::service->GetAccountList(); - for (auto& it : ncmap) - { - NickServ::Account *nc = it.second; - if (nc->o && std::find(Config->Opers.begin(), Config->Opers.end(), nc->o) != Config->Opers.end()) - nc->o = NULL; - } - } + for (Oper *o : Serialize::GetObjects<Oper *>(operblock)) + if (o->conf == Config) + o->Delete(); /* Apply new opers */ if (NickServ::service) - for (unsigned i = 0; i < this->Opers.size(); ++i) + for (Oper *o : Serialize::GetObjects<Oper *>(operblock)) { - Oper *o = this->Opers[i]; - - NickServ::Nick *na = NickServ::service->FindNick(o->name); + NickServ::Nick *na = NickServ::service->FindNick(o->GetName()); if (!na) continue; - na->nc->o = o; - Log() << "Tied oper " << na->nc->display << " to type " << o->ot->GetName(); + na->GetAccount()->o = o; + Log() << "Tied oper " << na->GetAccount()->GetDisplay() << " to type " << o->GetType()->GetName(); } if (options->Get<const Anope::string>("casemap", "ascii") == "ascii") @@ -549,8 +556,6 @@ Conf::~Conf() { for (unsigned i = 0; i < MyOperTypes.size(); ++i) delete MyOperTypes[i]; - for (unsigned i = 0; i < Opers.size(); ++i) - delete Opers[i]; } void Conf::Post(Conf *old) @@ -564,32 +569,22 @@ void Conf::Post(Conf *old) ModuleManager::LoadModule(this->ModulesAutoLoad[i], NULL); /* Apply opertype changes, as non-conf opers still point to the old oper types */ - for (unsigned i = Oper::opers.size(); i > 0; --i) + for (Oper *o : Serialize::GetObjects<Oper *>(operblock)) { - Oper *o = Oper::opers[i - 1]; - /* Oper's type is in the old config, so update it */ - if (std::find(old->MyOperTypes.begin(), old->MyOperTypes.end(), o->ot) != old->MyOperTypes.end()) + if (std::find(old->MyOperTypes.begin(), old->MyOperTypes.end(), o->GetType()) != old->MyOperTypes.end()) { - OperType *ot = o->ot; - o->ot = NULL; + OperType *ot = o->GetType(); + o->SetType(nullptr); for (unsigned j = 0; j < MyOperTypes.size(); ++j) if (ot->GetName() == MyOperTypes[j]->GetName()) - o->ot = MyOperTypes[j]; + o->SetType(MyOperTypes[j]); - if (o->ot == NULL) + if (o->GetType() == NULL) { /* Oper block has lost type */ - std::vector<Oper *>::iterator it = std::find(old->Opers.begin(), old->Opers.end(), o); - if (it != old->Opers.end()) - old->Opers.erase(it); - - it = std::find(this->Opers.begin(), this->Opers.end(), o); - if (it != this->Opers.end()) - this->Opers.erase(it); - - delete o; + o->Delete(); } } } @@ -626,11 +621,11 @@ Block *Conf::GetModule(const Anope::string &mname) return GetModule(mname); } -BotInfo *Conf::GetClient(const Anope::string &cname) +ServiceBot *Conf::GetClient(const Anope::string &cname) { Anope::map<Anope::string>::iterator it = bots.find(cname); if (it != bots.end()) - return BotInfo::Find(!it->second.empty() ? it->second : cname, true); + return ServiceBot::Find(!it->second.empty() ? it->second : cname, true); Block *block = GetModule(cname.lower()); const Anope::string &client = block->Get<const Anope::string>("client"); diff --git a/src/event.cpp b/src/event.cpp index cba56a314..9a46b4ac2 100644 --- a/src/event.cpp +++ b/src/event.cpp @@ -91,12 +91,8 @@ EventHandlers<LogMessage> Event::OnLogMessage(nullptr, "OnLogMessage"); EventHandlers<CheckModes> Event::OnCheckModes(nullptr, "OnCheckModes"); EventHandlers<ChannelSync> Event::OnChannelSync(nullptr, "OnChannelSync"); EventHandlers<SetCorrectModes> Event::OnSetCorrectModes(nullptr, "OnSetCorrectModes"); -EventHandlers<SerializeCheck> Event::OnSerializeCheck(nullptr, "OnSerializeCheck"); -EventHandlers<SerializableConstruct> Event::OnSerializableConstruct(nullptr, "OnSerializableConstruct"); -EventHandlers<SerializableDestruct> Event::OnSerializableDestruct(nullptr, "OnSerializableDestruct"); -EventHandlers<SerializableUpdate> Event::OnSerializableUpdate(nullptr, "OnSerializableUpdate"); -EventHandlers<SerializeTypeCreate> Event::OnSerializeTypeCreate(nullptr, "OnSerializeTypeCreate"); EventHandlers<Message> Event::OnMessage(nullptr, "OnMessage"); EventHandlers<CanSet> Event::OnCanSet(nullptr, "OnCanSet"); EventHandlers<CheckDelete> Event::OnCheckDelete(nullptr, "OnCheckDelete"); EventHandlers<ExpireTick> Event::OnExpireTick(nullptr, "OnExpireTick"); +EventHandlers<SerializeEvents> Event::OnSerialize(nullptr, "OnSerialize"); diff --git a/src/extensible.cpp b/src/extensible.cpp index 37206f7c1..e0e35e6ea 100644 --- a/src/extensible.cpp +++ b/src/extensible.cpp @@ -10,25 +10,25 @@ #include "extensible.h" -static std::set<ExtensibleBase *> extensible_items; +ExtensibleBase::ExtensibleBase(Module *m, const Anope::string &n) : ExtensibleBase(m, "Extensible", n) +{ +} -ExtensibleBase::ExtensibleBase(Module *m, const Anope::string &n) : Service(m, "Extensible", n) +ExtensibleBase::ExtensibleBase(Module *m, const Anope::string &t, const Anope::string &n) : Service(m, t, n) { - extensible_items.insert(this); } ExtensibleBase::~ExtensibleBase() { - extensible_items.erase(this); } Extensible::~Extensible() { while (!extension_items.empty()) - (*extension_items.begin())->Unset(this); + extension_items[0]->Unset(this); } -bool Extensible::HasExt(const Anope::string &name) const +bool Extensible::HasExtOK(const Anope::string &name) { ExtensibleRef<void *> ref(name); if (ref) @@ -38,32 +38,3 @@ bool Extensible::HasExt(const Anope::string &name) const return false; } -void Extensible::ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) -{ - for (std::set<ExtensibleBase *>::iterator it = e->extension_items.begin(); it != e->extension_items.end(); ++it) - { - ExtensibleBase *eb = *it; - eb->ExtensibleSerialize(e, s, data); - } -} - -void Extensible::ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) -{ - for (std::set<ExtensibleBase *>::iterator it = extensible_items.begin(); it != extensible_items.end(); ++it) - { - ExtensibleBase *eb = *it; - eb->ExtensibleUnserialize(e, s, data); - } -} - -template<> -bool* Extensible::Extend(const Anope::string &name, const bool &what) -{ - ExtensibleRef<bool> ref(name); - if (ref) - return ref->Set(this); - - Log(LOG_DEBUG) << "Extend for nonexistant type " << name << " on " << static_cast<void *>(this); - return NULL; -} - diff --git a/src/hashcomp.cpp b/src/hashcomp.cpp index beaf727ec..62bcc404f 100644 --- a/src/hashcomp.cpp +++ b/src/hashcomp.cpp @@ -64,8 +64,8 @@ int ci::ci_char_traits::compare(const char *str1, const char *str2, size_t n) { for (unsigned i = 0; i < n; ++i) { - register unsigned char c1 = case_map_upper[static_cast<unsigned char>(*str1)], - c2 = case_map_upper[static_cast<unsigned char>(*str2)]; + unsigned char c1 = case_map_upper[static_cast<unsigned char>(*str1)], + c2 = case_map_upper[static_cast<unsigned char>(*str2)]; if (c1 > c2) return 1; diff --git a/src/init.cpp b/src/init.cpp index 04b02cc06..305f7d584 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -20,6 +20,7 @@ #include "servers.h" #include "language.h" #include "event.h" +#include "modules.h" #ifndef _WIN32 #include <sys/wait.h> @@ -289,7 +290,7 @@ void Anope::Init(int ac, char **av) umask(DEFUMASK); #endif - Serialize::RegisterTypes(); + //Serialize::RegisterTypes(); /* Parse command line arguments */ ParseCommandLineArguments(ac, av); @@ -473,6 +474,10 @@ void Anope::Init(int ac, char **av) /* Initialize the socket engine. Note that some engines can not survive a fork(), so this must be here. */ SocketEngine::Init(); + new BotInfoType(); + new XLineType(nullptr, "XLine"); + new OperBlockType(); + /* Read configuration file; exit if there are problems. */ try { @@ -491,9 +496,14 @@ void Anope::Init(int ac, char **av) /* Create me */ Configuration::Block *block = Config->GetBlock("serverinfo"); Me = new Server(NULL, block->Get<const Anope::string>("name"), 0, block->Get<const Anope::string>("description"), block->Get<const Anope::string>("id")); - for (botinfo_map::const_iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it) + for (std::pair<Anope::string, User *> p : UserListByNick) { - it->second->server = Me; + User *u = p.second; + if (u->type != UserType::BOT) + continue; + + ServiceBot *bi = anope_dynamic_static_cast<ServiceBot *>(u); + bi->server = Me; ++Me->users; } @@ -531,8 +541,15 @@ void Anope::Init(int ac, char **av) Anope::string sid = IRCD->SID_Retrieve(); if (Me->GetSID() == Me->GetName()) Me->SetSID(sid); - for (botinfo_map::iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it) - it->second->GenerateUID(); + for (std::pair<Anope::string, User *> p : UserListByNick) + { + User *u = p.second; + if (u->type != UserType::BOT) + continue; + + ServiceBot *bi = anope_dynamic_static_cast<ServiceBot *>(u); + bi->GenerateUID(); + } } /* Load up databases */ @@ -545,6 +562,6 @@ void Anope::Init(int ac, char **av) for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it) it->second->Sync(); - Serialize::CheckTypes(); + //Serialize::CheckTypes(); } diff --git a/src/language.cpp b/src/language.cpp index 675605159..b1b0d77fc 100644 --- a/src/language.cpp +++ b/src/language.cpp @@ -70,9 +70,9 @@ const char *Language::Translate(User *u, const char *string) return Translate("", string); } -const char *Language::Translate(const NickServ::Account *nc, const char *string) +const char *Language::Translate(NickServ::Account *nc, const char *string) { - return Translate(nc ? nc->language.c_str() : "", string); + return Translate(nc ? nc->GetLanguage().c_str() : "", string); } #if GETTEXT_FOUND diff --git a/src/logger.cpp b/src/logger.cpp index 9dad74a67..3a735d48d 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -78,7 +78,7 @@ const Anope::string &LogFile::GetName() const return this->filename; } -Log::Log(LogType t, const Anope::string &cat, BotInfo *b) : bi(b), u(NULL), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(NULL), m(NULL), type(t), category(cat) +Log::Log(LogType t, const Anope::string &cat, ServiceBot *b) : bi(b), u(NULL), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(NULL), m(NULL), type(t), category(cat) { } @@ -93,7 +93,7 @@ Log::Log(LogType t, CommandSource &src, Command *_c, ChanServ::Channel *_ci) : u size_t sl = c->name.find('/'); this->bi = NULL; if (sl != Anope::string::npos) - this->bi = BotInfo::Find(c->name.substr(0, sl), true); + this->bi = ServiceBot::Find(c->name.substr(0, sl), true); this->category = c->name; } @@ -103,23 +103,23 @@ Log::Log(User *_u, Channel *ch, const Anope::string &cat) : bi(NULL), u(_u), nc( throw CoreException("Invalid pointers passed to Log::Log"); } -Log::Log(User *_u, const Anope::string &cat, BotInfo *_bi) : bi(_bi), u(_u), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(NULL), m(NULL), type(LOG_USER), category(cat) +Log::Log(User *_u, const Anope::string &cat, ServiceBot *_bi) : bi(_bi), u(_u), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(NULL), m(NULL), type(LOG_USER), category(cat) { if (!u) throw CoreException("Invalid pointers passed to Log::Log"); } -Log::Log(Server *serv, const Anope::string &cat, BotInfo *_bi) : bi(_bi), u(NULL), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(serv), m(NULL), type(LOG_SERVER), category(cat) +Log::Log(Server *serv, const Anope::string &cat, ServiceBot *_bi) : bi(_bi), u(NULL), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(serv), m(NULL), type(LOG_SERVER), category(cat) { if (!s) throw CoreException("Invalid pointer passed to Log::Log"); } -Log::Log(BotInfo *b, const Anope::string &cat) : bi(b), u(NULL), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(NULL), m(NULL), type(LOG_NORMAL), category(cat) +Log::Log(ServiceBot *b, const Anope::string &cat) : bi(b), u(NULL), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(NULL), m(NULL), type(LOG_NORMAL), category(cat) { } -Log::Log(Module *mod, const Anope::string &cat, BotInfo *_bi) : bi(_bi), u(NULL), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(NULL), m(mod), type(LOG_MODULE), category(cat) +Log::Log(Module *mod, const Anope::string &cat, ServiceBot *_bi) : bi(_bi), u(NULL), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(NULL), m(mod), type(LOG_MODULE), category(cat) { } @@ -144,11 +144,11 @@ Anope::string Log::FormatSource() const { if (u) if (nc) - return this->u->GetMask() + " (" + this->nc->display + ")"; + return this->u->GetMask() + " (" + this->nc->GetDisplay() + ")"; else return this->u->GetMask(); else if (nc) - return nc->display; + return nc->GetDisplay(); return ""; } @@ -156,7 +156,7 @@ Anope::string Log::FormatCommand() const { Anope::string buffer = FormatSource() + " used " + (source != NULL && !source->command.empty() ? source->command : this->c->name) + " "; if (this->ci) - buffer += "on " + this->ci->name + " "; + buffer += "on " + this->ci->GetName() + " "; return buffer; } @@ -333,9 +333,9 @@ void LogInfo::ProcessMessage(const Log *l) log = true; else if (l->u && src == l->u->nick) log = true; - else if (l->nc && src == l->nc->display) + else if (l->nc && src == l->nc->GetDisplay()) log = true; - else if (l->ci && src == l->ci->name) + else if (l->ci && src == l->ci->GetName()) log = true; else if (l->m && src == l->m->name) log = true; diff --git a/src/mail.cpp b/src/mail.cpp index 342a49a24..1812156e9 100644 --- a/src/mail.cpp +++ b/src/mail.cpp @@ -54,7 +54,7 @@ void Mail::Message::Run() SetExitState(); } -bool Mail::Send(User *u, NickServ::Account *nc, BotInfo *service, const Anope::string &subject, const Anope::string &message) +bool Mail::Send(User *u, NickServ::Account *nc, ServiceBot *service, const Anope::string &subject, const Anope::string &message) { if (!nc || !service || subject.empty() || message.empty()) return false; @@ -65,11 +65,11 @@ bool Mail::Send(User *u, NickServ::Account *nc, BotInfo *service, const Anope::s { if (!b->Get<bool>("usemail") || b->Get<const Anope::string>("sendfrom").empty()) return false; - else if (nc->email.empty()) + else if (nc->GetEmail().empty()) return false; nc->lastmail = Anope::CurTime; - Thread *t = new Mail::Message(b->Get<const Anope::string>("sendfrom"), nc->display, nc->email, subject, message); + Thread *t = new Mail::Message(b->Get<const Anope::string>("sendfrom"), nc->GetDisplay(), nc->GetEmail(), subject, message); t->Start(); return true; } @@ -79,12 +79,12 @@ bool Mail::Send(User *u, NickServ::Account *nc, BotInfo *service, const Anope::s u->SendMessage(service, _("Services have been configured to not send mail.")); else if (Anope::CurTime - u->lastmail < b->Get<time_t>("delay")) u->SendMessage(service, _("Please wait \002%d\002 seconds and retry."), b->Get<time_t>("delay") - (Anope::CurTime - u->lastmail)); - else if (nc->email.empty()) - u->SendMessage(service, _("E-mail for \002%s\002 is invalid."), nc->display.c_str()); + else if (nc->GetEmail().empty()) + u->SendMessage(service, _("E-mail for \002%s\002 is invalid."), nc->GetDisplay().c_str()); else { u->lastmail = nc->lastmail = Anope::CurTime; - Thread *t = new Mail::Message(b->Get<const Anope::string>("sendfrom"), nc->display, nc->email, subject, message); + Thread *t = new Mail::Message(b->Get<const Anope::string>("sendfrom"), nc->GetDisplay(), nc->GetEmail(), subject, message); t->Start(); return true; } @@ -96,11 +96,11 @@ bool Mail::Send(User *u, NickServ::Account *nc, BotInfo *service, const Anope::s bool Mail::Send(NickServ::Account *nc, const Anope::string &subject, const Anope::string &message) { Configuration::Block *b = Config->GetBlock("mail"); - if (!b->Get<bool>("usemail") || b->Get<const Anope::string>("sendfrom").empty() || !nc || nc->email.empty() || subject.empty() || message.empty()) + if (!b->Get<bool>("usemail") || b->Get<const Anope::string>("sendfrom").empty() || !nc || nc->GetEmail().empty() || subject.empty() || message.empty()) return false; nc->lastmail = Anope::CurTime; - Thread *t = new Mail::Message(b->Get<const Anope::string>("sendfrom"), nc->display, nc->email, subject, message); + Thread *t = new Mail::Message(b->Get<const Anope::string>("sendfrom"), nc->GetDisplay(), nc->GetEmail(), subject, message); t->Start(); return true; diff --git a/src/main.cpp b/src/main.cpp index 8a61835b0..1f4434f18 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,6 +17,7 @@ #include "socketengine.h" #include "uplink.h" #include "event.h" +#include "modules.h" #ifndef _WIN32 #include <limits.h> diff --git a/src/messages.cpp b/src/messages.cpp index 2501ac047..9cdab67c1 100644 --- a/src/messages.cpp +++ b/src/messages.cpp @@ -184,13 +184,13 @@ void Kick::Run(MessageSource &source, const std::vector<Anope::string> ¶ms) void Kill::Run(MessageSource &source, const std::vector<Anope::string> ¶ms) { User *u = User::Find(params[0]); - BotInfo *bi; + ServiceBot *bi; if (!u) return; /* Recover if someone kills us. */ - if (u->server == Me && (bi = dynamic_cast<BotInfo *>(u))) + if (u->server == Me && (bi = dynamic_cast<ServiceBot *>(u))) { static time_t last_time = 0; @@ -263,7 +263,7 @@ void Notice::Run(MessageSource &source, const std::vector<Anope::string> ¶ms /* ignore channel notices */ if (!IRCD->IsChannelValid(params[0])) { - BotInfo *bi = BotInfo::Find(params[0]); + ServiceBot *bi = ServiceBot::Find(params[0]); if (!bi) return; Event::OnBotNotice(&Event::BotNotice::OnBotNotice, u, bi, message); @@ -330,7 +330,7 @@ void Privmsg::Run(MessageSource &source, const std::vector<Anope::string> ¶m } else if (!IRCD->RequiresID && Config->UseStrictPrivmsg) { - BotInfo *bi = BotInfo::Find(receiver); + ServiceBot *bi = ServiceBot::Find(receiver); if (!bi) return; Log(LOG_DEBUG) << "Ignored PRIVMSG without @ from " << u->nick; @@ -338,7 +338,7 @@ void Privmsg::Run(MessageSource &source, const std::vector<Anope::string> ¶m return; } - BotInfo *bi = BotInfo::Find(botname, nick_only); + ServiceBot *bi = ServiceBot::Find(botname, nick_only); if (bi) { @@ -416,12 +416,8 @@ void Stats::Run(MessageSource &source, const std::vector<Anope::string> ¶ms) IRCD->SendNumeric(219, source.GetSource(), "%c :End of /STATS report.", params[0][0]); else { - for (unsigned i = 0; i < Oper::opers.size(); ++i) - { - Oper *o = Oper::opers[i]; - - IRCD->SendNumeric(243, source.GetSource(), "O * * %s %s 0", o->name.c_str(), o->ot->GetName().c_str()); - } + for (Oper *o : Serialize::GetObjects<Oper *>(operblock)) + IRCD->SendNumeric(243, source.GetSource(), "O * * %s %s 0", o->GetName().c_str(), o->GetType()->GetName().c_str()); IRCD->SendNumeric(219, source.GetSource(), "%c :End of /STATS report.", params[0][0]); } @@ -475,7 +471,7 @@ void Whois::Run(MessageSource &source, const std::vector<Anope::string> ¶ms) if (u && u->server == Me) { - const BotInfo *bi = BotInfo::Find(u->GetUID()); + const ServiceBot *bi = ServiceBot::Find(u->GetUID()); IRCD->SendNumeric(311, source.GetSource(), "%s %s %s * :%s", u->nick.c_str(), u->GetIdent().c_str(), u->host.c_str(), u->realname.c_str()); if (bi) IRCD->SendNumeric(307, source.GetSource(), "%s :is a registered nick", bi->nick.c_str()); diff --git a/src/misc.cpp b/src/misc.cpp index c347b76a4..27be43a96 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -291,7 +291,7 @@ time_t Anope::DoTime(const Anope::string &s) return amount; } -Anope::string Anope::Duration(time_t t, const NickServ::Account *nc) +Anope::string Anope::Duration(time_t t, NickServ::Account *nc) { /* We first calculate everything */ time_t years = t / 31536000; @@ -332,7 +332,7 @@ Anope::string Anope::Duration(time_t t, const NickServ::Account *nc) } } -Anope::string Anope::strftime(time_t t, const NickServ::Account *nc, bool short_output) +Anope::string Anope::strftime(time_t t, NickServ::Account *nc, bool short_output) { tm tm = *localtime(&t); char buf[BUFSIZE]; @@ -347,7 +347,7 @@ Anope::string Anope::strftime(time_t t, const NickServ::Account *nc, bool short_ return Anope::string(buf) + " " + Language::Translate(nc, _("(now)")); } -Anope::string Anope::Expires(time_t expires, const NickServ::Account *nc) +Anope::string Anope::Expires(time_t expires, NickServ::Account *nc) { if (!expires) return Language::Translate(nc, _("does not expire")); diff --git a/src/modulemanager.cpp b/src/modulemanager.cpp index d11585791..b36d8180b 100644 --- a/src/modulemanager.cpp +++ b/src/modulemanager.cpp @@ -327,6 +327,8 @@ ModuleReturn ModuleManager::DeleteModule(Module *m) if (!m || !m->handle) return MOD_ERR_PARAMS; + Serialize::Unregister(m); + void *handle = m->handle; Anope::string filename = m->filename; diff --git a/src/opertype.cpp b/src/opertype.cpp index b75899234..d524c7ded 100644 --- a/src/opertype.cpp +++ b/src/opertype.cpp @@ -12,31 +12,83 @@ #include "opertype.h" #include "config.h" -std::vector<Oper *> Oper::opers; +Anope::string Oper::GetName() +{ + return Get(&OperBlockType::name); +} -Oper::Oper(const Anope::string &n, OperType *o) : name(n), ot(o), require_oper(false) +void Oper::SetName(const Anope::string &n) { - opers.push_back(this); + Set(&OperBlockType::name, n); } -Oper::~Oper() +Anope::string Oper::GetPassword() { - std::vector<Oper *>::iterator it = std::find(opers.begin(), opers.end(), this); - if (it != opers.end()) - opers.erase(it); + return Get(&OperBlockType::password); } -Oper *Oper::Find(const Anope::string &name) +void Oper::SetPassword(const Anope::string &s) { - for (unsigned i = 0; i < opers.size(); ++i) - { - Oper *o = opers[i]; + Set(&OperBlockType::password, s); +} + +Anope::string Oper::GetCertFP() +{ + return Get(&OperBlockType::certfp); +} + +void Oper::SetCertFP(const Anope::string &s) +{ + Set(&OperBlockType::certfp, s); +} + +Anope::string Oper::GetHost() +{ + return Get(&OperBlockType::host); +} + +void Oper::SetHost(const Anope::string &h) +{ + Set(&OperBlockType::host, h); +} + +Anope::string Oper::GetVhost() +{ + return Get(&OperBlockType::vhost); +} - if (o->name.equals_ci(name)) +void Oper::SetVhost(const Anope::string &s) +{ + Set(&OperBlockType::vhost, s); +} + +OperType *Oper::GetType() +{ + return OperType::Find(Get(&OperBlockType::type)); +} + +void Oper::SetType(OperType *type) +{ + Set(&OperBlockType::type, type->GetName()); +} + +bool Oper::GetRequireOper() +{ + return Get(&OperBlockType::require_oper); +} + +void Oper::SetRequireOper(const bool &b) +{ + Set(&OperBlockType::require_oper, b); +} + +Oper *Oper::Find(const Anope::string &name) +{ + for (Oper *o : Serialize::GetObjects<Oper *>(operblock)) + if (o->GetName() == name) return o; - } - return NULL; + return nullptr; } OperType *OperType::Find(const Anope::string &name) diff --git a/src/pipeengine.cpp b/src/pipeengine.cpp index ee12539da..4b19be48f 100644 --- a/src/pipeengine.cpp +++ b/src/pipeengine.cpp @@ -48,10 +48,11 @@ Pipe::~Pipe() bool Pipe::ProcessRead() { + char dummy[512]; + while (read(this->GetFD(), dummy, sizeof(dummy)) == sizeof(dummy)); + this->OnNotify(); - char dummy[512]; - while (read(this->GetFD(), dummy, 512) == 512); return true; } @@ -76,6 +77,6 @@ bool Pipe::SetWriteBlocking(bool state) void Pipe::Notify() { - this->Write("\0", 1); + this->Write("", 1); } diff --git a/src/protocol.cpp b/src/protocol.cpp index ade936594..4baa35c80 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -480,9 +480,9 @@ User *MessageSource::GetUser() const return this->u; } -BotInfo *MessageSource::GetBot() const +ServiceBot *MessageSource::GetBot() const { - return BotInfo::Find(this->GetName(), true); + return ServiceBot::Find(this->GetName(), true); } Server *MessageSource::GetServer() const diff --git a/src/serialize.cpp b/src/serialize.cpp index a24f6d0e3..b11f8232c 100644 --- a/src/serialize.cpp +++ b/src/serialize.cpp @@ -15,153 +15,321 @@ #include "anope.h" #include "serialize.h" #include "modules.h" -#include "bots.h" -#include "xline.h" #include "event.h" using namespace Serialize; -std::vector<Anope::string> Type::TypeOrder; -std::map<Anope::string, Type *> Serialize::Type::Types; -std::list<Serializable *> *Serializable::SerializableItems; +std::map<Anope::string, TypeBase *> Serialize::Types; -void Serialize::RegisterTypes() +std::unordered_map<ID, Object *> Serialize::objects; + +std::vector<FieldBase *> Serialize::serializableFields; + +static ID curid; + +Object *Serialize::GetID(ID id) +{ + auto it = objects.find(id); + if (it != objects.end()) + return it->second; + return nullptr; +} + +void Serialize::Clear() { - static Type bi("BotInfo", BotInfo::Unserialize), - xline("XLine", XLine::Unserialize); + std::unordered_map<ID, Object *> o; + objects.swap(o); + + for (const std::pair<ID, Object *> &p : o) + delete p.second; } -void Serialize::CheckTypes() +void Serialize::Unregister(Module *m) { - for (std::map<Anope::string, Serialize::Type *>::const_iterator it = Serialize::Type::GetTypes().begin(), it_end = Serialize::Type::GetTypes().end(); it != it_end; ++it) + for (FieldBase *field : serializableFields) + if (field->creator == m) + field->Unregister(); + + for (const std::pair<Anope::string, TypeBase *> &p : Types) { - Serialize::Type *t = it->second; - t->Check(); + TypeBase *s = p.second; + + if (s->GetOwner() == m) + s->Unregister(); } } -Serializable::Serializable(const Anope::string &serialize_type) : last_commit(0), last_commit_time(0), id(0), redis_ignore(0) +std::vector<Edge> Object::GetRefs(TypeBase *type) { - if (SerializableItems == NULL) - SerializableItems = new std::list<Serializable *>(); - SerializableItems->push_back(this); + std::vector<Edge> refs; + EventReturn result = Event::OnSerialize(&Event::SerializeEvents::OnSerializeGetRefs, this, type, refs); + if (result == EVENT_ALLOW) + return refs; - this->s_type = Type::Find(serialize_type); - - this->s_iter = SerializableItems->end(); - --this->s_iter; + if (type == nullptr) + { + refs.clear(); + for (const std::pair<TypeBase *, std::vector<Edge>> &p : edges) + { + const std::vector<Edge> &e = p.second; + refs.insert(refs.end(), e.begin(), e.end()); + } + return refs; + } - Event::OnSerializableConstruct(&Event::SerializableConstruct::OnSerializableConstruct, this); + auto it = edges.find(type); + if (it != edges.end()) + return it->second; + return std::vector<Edge>(); } -Serializable::Serializable(const Serializable &other) : last_commit(0), last_commit_time(0), id(0), redis_ignore(0) +Object::Object(TypeBase *type) { - SerializableItems->push_back(this); - this->s_iter = SerializableItems->end(); - --this->s_iter; + ID i; + EventReturn result = Event::OnSerialize(&Event::SerializeEvents::OnSerializableGetId, i); + if (result != EVENT_ALLOW) + { + while (GetID(++curid)); + i = curid; + } - this->s_type = other.s_type; + id = i; + objects[id] = this; - Event::OnSerializableConstruct(&Event::SerializableConstruct::OnSerializableConstruct, this); + this->s_type = type; + + type->objects.insert(this); + + Log(LOG_DEBUG) << "Creating object id #" << id << " type " << type->GetName(); + + Event::OnSerialize(&Event::SerializeEvents::OnSerializableCreate, this); } -Serializable::~Serializable() +Object::Object(TypeBase *type, ID i) { - Event::OnSerializableDestruct(&Event::SerializableDestruct::OnSerializableDestruct, this); + this->id = i; + objects[i] = this; + + this->s_type = type; - SerializableItems->erase(this->s_iter); + type->objects.insert(this); + + Log(LOG_DEBUG) << "Creating object from id #" << id << " type " << type->GetName(); } -Serializable &Serializable::operator=(const Serializable &) +Object::~Object() { - return *this; + Log(LOG_DEBUG) << "Destructing object id #" << id << " type " << s_type->GetName(); + + /* Remove in memory edges */ + cont: + for (const std::pair<TypeBase *, std::vector<Edge>> &p : edges) + for (const Edge &edge : p.second) + { + if (!edge.direction) + { + Log(LOG_DEBUG_2) << "Removing edge from object id #" << edge.other->id << " type " << edge.other->GetSerializableType()->GetName() << " on field " << edge.field->GetName(); + edge.other->RemoveEdge(this, edge.field); + } + else + { + Log(LOG_DEBUG_2) << "Removing edge to object id #" << edge.other->id << " type " << edge.other->GetSerializableType()->GetName() << " on field " << edge.field->GetName(); + this->RemoveEdge(edge.other, edge.field); + } + goto cont; + } + + objects.erase(id); + s_type->objects.erase(this); } -void Serializable::QueueUpdate() +void Object::Delete() { - /* Schedule updater */ - Event::OnSerializableUpdate(&Event::SerializableUpdate::OnSerializableUpdate, this); + Log(LOG_DEBUG) << "Deleting object id #" << id << " type " << s_type->GetName(); - /* Check for modifications now - this can delete this object! */ - Event::OnSerializeCheck(&Event::SerializeCheck::OnSerializeCheck, this->GetSerializableType()); -} + /* Delete dependant objects */ + for (const Edge &edge : GetRefs(nullptr)) + { + Object *other = edge.other; + FieldBase *field = edge.field; + + if (edge.direction) + continue; + + if (field->depends) + { + Log(LOG_DEBUG_2) << "Deleting dependent object #" << other->id << " type " << other->GetSerializableType()->GetName() << " due to edge on " << field->GetName(); + other->Delete(); + } + else + { + Log(LOG_DEBUG_2) << "Unsetting field " << field->GetName() << " on object #" << other->id << " type " << other->GetSerializableType()->GetName(); + field->UnsetS(other); + } + } -bool Serializable::IsCached(Serialize::Data &data) -{ - return this->last_commit == data.Hash(); + Event::OnSerialize(&Event::SerializeEvents::OnSerializableDelete, this); + + delete this; } -void Serializable::UpdateCache(Serialize::Data &data) +void Object::AddEdge(Object *other, FieldBase *field) { - this->last_commit = data.Hash(); + // field = the field on 'this' object + this->edges[other->GetSerializableType()].emplace_back(other, field, true); + // field = the field on the other object + other->edges[this->GetSerializableType()].emplace_back(this, field, false); } -bool Serializable::IsTSCached() +void Object::RemoveEdge(Object *other, FieldBase *field) { - return this->last_commit_time == Anope::CurTime; + std::vector<Edge> &myedges = this->edges[other->GetSerializableType()]; + auto it = std::find(myedges.begin(), myedges.end(), Edge(other, field, true)); + if (it != myedges.end()) + myedges.erase(it); + else + Log(LOG_DEBUG_2) << "Unable to locate edge for removal on #" << this->id << " type " << s_type->GetName() << " -> #" << other->id << " type " << other->GetSerializableType()->GetName(); + + std::vector<Edge> &theiredges = other->edges[this->GetSerializableType()]; + it = std::find(theiredges.begin(), theiredges.end(), Edge(this, field, false)); + if (it != theiredges.end()) + theiredges.erase(it); + else + Log(LOG_DEBUG_2) << "Unable to locate edge for removal on #" << this->id << " type " << s_type->GetName() << " <- #" << other->id << " type " << other->GetSerializableType()->GetName(); } -void Serializable::UpdateTS() +TypeBase::TypeBase(Module *o, const Anope::string &n) : Service(o, "Serialize::Type", n), name(n), owner(o) { - this->last_commit_time = Anope::CurTime; + Types[this->name] = this; } -const std::list<Serializable *> &Serializable::GetItems() +TypeBase::~TypeBase() { - return *SerializableItems; + if (!Serialize::GetObjects<Object *>(this).empty()) + throw CoreException("Type destructing with objects still alive"); + + if (parent) + { + auto it = std::find(parent->children.begin(), parent->children.end(), this); + if (it != parent->children.end()) + parent->children.erase(it); + } + + for (TypeBase *child : children) + child->parent = nullptr; + + Types.erase(this->name); } -Type::Type(const Anope::string &n, unserialize_func f, Module *o) : name(n), unserialize(f), owner(o), timestamp(0) +void TypeBase::Unregister() { - TypeOrder.push_back(this->name); - Types[this->name] = this; + Log(LOG_DEBUG_2) << "Unregistering type " << this->GetName(); + + for (Object *obj : GetObjects<Object *>(this)) + obj->Delete(); - Event::OnSerializeTypeCreate(&Event::SerializeTypeCreate::OnSerializeTypeCreate, this); + cont: + for (FieldBase *field : fields) + { + field->Unregister(); + goto cont; + } } -Type::~Type() +void TypeBase::SetParent(TypeBase *other) { - std::vector<Anope::string>::iterator it = std::find(TypeOrder.begin(), TypeOrder.end(), this->name); - if (it != TypeOrder.end()) - TypeOrder.erase(it); - Types.erase(this->name); + parent = other; + other->children.push_back(this); } -Serializable *Type::Unserialize(Serializable *obj, Serialize::Data &data) +Serialize::FieldBase *TypeBase::GetField(const Anope::string &fname) { - return this->unserialize(obj, data); + for (FieldBase *f : fields) + if (f->GetName() == fname) + return f; + return nullptr; } -void Type::Check() +std::vector<TypeBase *> TypeBase::GetSubTypes() { - Event::OnSerializeCheck(&Event::SerializeCheck::OnSerializeCheck, this); + std::vector<TypeBase *> v; + + v.push_back(this); + + for (TypeBase *b : children) + { + std::vector<TypeBase *> c = b->GetSubTypes(); + v.insert(v.end(), c.begin(), c.end()); + } + + return v; } -time_t Type::GetTimestamp() const +TypeBase *TypeBase::Find(const Anope::string &name) { - return this->timestamp; + std::map<Anope::string, TypeBase *>::iterator it = Types.find(name); + if (it != Types.end()) + return it->second; + return nullptr; } -void Type::UpdateTimestamp() +const std::map<Anope::string, Serialize::TypeBase *>& TypeBase::GetTypes() { - this->timestamp = Anope::CurTime; + return Types; } -Type *Serialize::Type::Find(const Anope::string &name) +void Serialize::FieldBase::Listener::OnAcquire() { - std::map<Anope::string, Type *>::iterator it = Types.find(name); - if (it != Types.end()) - return it->second; - return NULL; + TypeBase *t = *this; + + if (base->unregister) + return; + + Log(LOG_DEBUG_2) << "Acquired type reference to " << t->GetName() << " for field " << base->GetName(); + + auto it = std::find(t->fields.begin(), t->fields.end(), base); + if (it == t->fields.end()) + t->fields.push_back(base); } -const std::vector<Anope::string> &Type::GetTypeOrder() +FieldBase::FieldBase(Module *c, const Anope::string &n, const ServiceReference<TypeBase> &t, bool d) : type(this, t), creator(c), name(n), depends(d) { - return TypeOrder; + serializableFields.push_back(this); + + type.Check(); } -const std::map<Anope::string, Serialize::Type *>& Type::GetTypes() +FieldBase::~FieldBase() { - return Types; + if (std::find(type->fields.begin(), type->fields.end(), this) != type->fields.end()) + Log(LOG_DEBUG) << "Destructing field " << this->GetName() << " on " << type->GetName() << " while still registered!"; + + auto it = std::find(serializableFields.begin(), serializableFields.end(), this); + if (it != serializableFields.end()) + serializableFields.erase(it); } +void FieldBase::Unregister() +{ + unregister = true; + + Log(LOG_DEBUG_2) << "Unregistering field " << this->GetName() << " on " << type->GetName(); + + /* find edges on this field */ + for (Object *s : Serialize::GetObjects<Object *>(type)) + { + for (const std::pair<TypeBase *, std::vector<Edge>> &p : s->edges) + for (const Edge &edge : p.second) + if (edge.direction && edge.field == this) + { + Log(LOG_DEBUG_2) << "Removing edge on #" << s->id << " <-> #" << edge.other->id << " type " << edge.other->GetSerializableType()->GetName(); + s->RemoveEdge(edge.other, edge.field); + goto cont; + } + cont:; + } + + auto it = std::find(type->fields.begin(), type->fields.end(), this); + if (it != type->fields.end()) + type->fields.erase(it); +} diff --git a/src/servers.cpp b/src/servers.cpp index a6998b200..ece923ac5 100644 --- a/src/servers.cpp +++ b/src/servers.cpp @@ -50,9 +50,13 @@ Server::Server(Server *up, const Anope::string &sname, unsigned shops, const Ano if (Me == this->uplink && !juped) { /* Now do mode related stuff as we know what modes exist .. */ - for (botinfo_map::iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it) + for (std::pair<Anope::string, User *> p : UserListByNick) { - BotInfo *bi = it->second; + User *u = p.second; + if (u->type != UserType::BOT) + continue; + + ServiceBot *bi = anope_dynamic_static_cast<ServiceBot *>(u); Anope::string modes = !bi->botmodes.empty() ? ("+" + bi->botmodes) : IRCD->DefaultPseudoclientModes; bi->SetModesInternal(bi, modes.c_str()); @@ -96,11 +100,11 @@ Server::Server(Server *up, const Anope::string &sname, unsigned shops, const Ano { User *u = it->second; - BotInfo *bi = BotInfo::Find(u->GetUID()); + ServiceBot *bi = ServiceBot::Find(u->GetUID()); if (bi) { - XLine x(bi->nick, "Reserved for services"); - IRCD->SendSQLine(NULL, &x); + //XLine x(bi->nick, "Reserved for services"); + //IRCD->SendSQLine(NULL, &x); } IRCD->SendClientIntroduction(u); @@ -327,7 +331,7 @@ bool Server::IsQuitting() const return quitting; } -void Server::Notice(BotInfo *source, const Anope::string &message) +void Server::Notice(ServiceBot *source, const Anope::string &message) { if (Config->UsePrivmsg && Config->DefPrivmsg) IRCD->SendGlobalPrivmsg(source, this, message); diff --git a/src/uplink.cpp b/src/uplink.cpp index 9337692bb..2235da81e 100644 --- a/src/uplink.cpp +++ b/src/uplink.cpp @@ -17,6 +17,8 @@ #include "servers.h" #include "event.h" #include "bots.h" +#include "timers.h" +#include "modules.h" UplinkSocket *UplinkSock = NULL; @@ -90,7 +92,7 @@ UplinkSocket::~UplinkSocket() { /* Don't use quitmsg here, it may contain information you don't want people to see */ IRCD->SendQuit(u, "Shutting down"); - BotInfo* bi = BotInfo::Find(u->GetUID()); + ServiceBot* bi = ServiceBot::Find(u->GetUID()); if (bi != NULL) bi->introduced = false; } @@ -190,7 +192,7 @@ UplinkSocket::Message::~Message() return; } - const BotInfo *bi = this->source.GetBot(); + const ServiceBot *bi = this->source.GetBot(); if (bi != NULL && bi->introduced == false) { Log(LOG_DEBUG) << "Attempted to send \"" << this->buffer.str() << "\" from " << bi->nick << " when not introduced"; diff --git a/src/users.cpp b/src/users.cpp index f6d72383e..ff81a3017 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -56,7 +56,6 @@ User::User(const Anope::string &snick, const Anope::string &sident, const Anope: this->SetModesInternal(sserver, "%s", smodes.c_str()); this->uid = suid; this->super_admin = false; - this->nc = NULL; size_t old = UserListByNick.size(); UserListByNick[snick] = this; @@ -99,7 +98,7 @@ static void CollideKill(User *target, const Anope::string &reason) IRCD->SendQuit(target, "%s", reason.c_str()); // Reintroduce my client - if (BotInfo *bi = dynamic_cast<BotInfo *>(target)) + if (ServiceBot *bi = dynamic_cast<ServiceBot *>(target)) bi->OnKill(); else target->Quit(reason); @@ -159,7 +158,7 @@ void User::ChangeNick(const Anope::string &newnick, time_t ts) { NickServ::Nick *old_na = NickServ::service->FindNick(this->nick); if (old_na && (this->IsIdentified(true) || this->IsRecognized())) - old_na->last_seen = Anope::CurTime; + old_na->SetLastSeen(Anope::CurTime); } UserListByNick.erase(this->nick); @@ -181,11 +180,11 @@ void User::ChangeNick(const Anope::string &newnick, time_t ts) NickServ::Nick *na = NickServ::service->FindNick(this->nick); if (na) { - on_access = na->nc->IsOnAccess(this); + on_access = na->GetAccount()->IsOnAccess(this); - if (na->nc == this->Account()) + if (na->GetAccount() == this->Account()) { - na->last_seen = Anope::CurTime; + na->SetLastSeen(Anope::CurTime); this->UpdateHost(); } } @@ -297,7 +296,7 @@ void User::SetRealname(const Anope::string &srealname) NickServ::Nick *na = NickServ::service->FindNick(this->nick); if (na && (this->IsIdentified(true) || this->IsRecognized())) - na->last_realname = srealname; + na->SetLastRealname(srealname); } Log(this, "realname") << "changed realname to " << srealname; @@ -339,7 +338,7 @@ void User::SendMessage(const MessageSource &source, const Anope::string &msg) * - The user is not registered and NSDefMsg is enabled * - The user is registered and has set /ns set msg on */ - bool send_privmsg = Config->UsePrivmsg && ((!this->nc && Config->DefPrivmsg) || (this->nc && this->nc->HasExt("MSG"))); + bool send_privmsg = Config->UsePrivmsg && ((!this->nc && Config->DefPrivmsg) || (this->nc && this->nc->HasFieldS("MSG"))); sepstream sep(translated_message, '\n', true); for (Anope::string tok; sep.GetToken(tok);) { @@ -376,35 +375,36 @@ void User::SendMessage(const MessageSource &source, const Anope::string &msg) void User::Identify(NickServ::Nick *na) { - if (this->nick.equals_ci(na->nick)) + if (this->nick.equals_ci(na->GetNick())) { - na->last_usermask = this->GetIdent() + "@" + this->GetDisplayedHost(); - na->last_realhost = this->GetIdent() + "@" + this->host; - na->last_realname = this->realname; - na->last_seen = Anope::CurTime; + na->SetLastUsermask(this->GetIdent() + "@" + this->GetDisplayedHost()); + na->SetLastRealhost(this->GetIdent() + "@" + this->host); + na->SetLastRealname(this->realname); + na->SetLastSeen(Anope::CurTime); } IRCD->SendLogin(this, na); - this->Login(na->nc); + this->Login(na->GetAccount()); Event::OnNickIdentify(&Event::NickIdentify::OnNickIdentify, this); if (this->IsServicesOper()) { - if (!this->nc->o->ot->modes.empty()) + Anope::string m = this->nc->o->GetType()->modes; + if (!m.empty()) { - this->SetModes(NULL, "%s", this->nc->o->ot->modes.c_str()); - this->SendMessage(Me, "Changing your usermodes to \002{0}\002", this->nc->o->ot->modes); + this->SetModes(NULL, "%s", m.c_str()); + this->SendMessage(Me, "Changing your usermodes to \002{0}\002", m.c_str()); UserMode *um = ModeManager::FindUserModeByName("OPER"); - if (um && !this->HasMode("OPER") && this->nc->o->ot->modes.find(um->mchar) != Anope::string::npos) + if (um && !this->HasMode("OPER") && m.find(um->mchar) != Anope::string::npos) IRCD->SendOper(this); } - if (IRCD->CanSetVHost && !this->nc->o->vhost.empty()) + if (IRCD->CanSetVHost && !this->nc->o->GetVhost().empty()) { - this->SendMessage(Me, "Changing your vhost to \002{0}\002", this->nc->o->vhost); - this->SetDisplayedHost(this->nc->o->vhost); - IRCD->SendVhost(this, "", this->nc->o->vhost); + this->SendMessage(Me, "Changing your vhost to \002{0}\002", this->nc->o->GetVhost()); + this->SetDisplayedHost(this->nc->o->GetVhost()); + IRCD->SendVhost(this, "", this->nc->o->GetVhost()); } } } @@ -422,7 +422,7 @@ void User::Login(NickServ::Account *core) this->UpdateHost(); if (this->server->IsSynced()) - Log(this, "account") << "is now identified as " << this->nc->display; + Log(this, "account") << "is now identified as " << this->nc->GetDisplay(); Event::OnUserLogin(&Event::UserLogin::OnUserLogin, this); } @@ -432,9 +432,9 @@ void User::Logout() if (!this->nc) return; - Log(this, "account") << "is no longer identified as " << this->nc->display; + Log(this, "account") << "is no longer identified as " << this->nc->GetDisplay(); - std::list<User *>::iterator it = std::find(this->nc->users.begin(), this->nc->users.end(), this); + auto it = std::find(this->nc->users.begin(), this->nc->users.end(), this); if (it != this->nc->users.end()) this->nc->users.erase(it); @@ -450,8 +450,8 @@ bool User::IsIdentified(bool check_nick) const { if (check_nick && this->nc) { - NickServ::Nick *na = NickServ::service ? NickServ::service->FindNick(this->nick) : nullptr; - return na && *na->nc == *this->nc; + NickServ::Nick *na = NickServ::FindNick(nick); + return na && na->GetAccount() == *this->nc; } return this->nc ? true : false; @@ -461,9 +461,9 @@ bool User::IsRecognized(bool check_secure) const { if (check_secure && on_access) { - const NickServ::Nick *na = NickServ::service ? NickServ::service->FindNick(this->nick) : nullptr; + NickServ::Nick *na = NickServ::FindNick(nick); - if (!na || na->nc->HasExt("NS_SECURE")) + if (!na || na->GetAccount()->HasFieldS("NS_SECURE")) return false; } @@ -475,17 +475,20 @@ bool User::IsServicesOper() if (!this->nc || !this->nc->IsServicesOper()) // No opertype. return false; - else if (this->nc->o->require_oper && !this->HasMode("OPER")) + else if (this->nc->o->GetRequireOper() && !this->HasMode("OPER")) return false; - else if (!this->nc->o->certfp.empty() && this->fingerprint != this->nc->o->certfp) + else if (!this->nc->o->GetCertFP().empty() && this->fingerprint != this->nc->o->GetCertFP()) // Certfp mismatch return false; - else if (!this->nc->o->hosts.empty()) + else if (!this->nc->o->GetHost().empty()) { + std::vector<Anope::string> hosts; + spacesepstream(this->nc->o->GetHost()).GetTokens(hosts); + bool match = false; Anope::string match_host = this->GetIdent() + "@" + this->host; - for (unsigned i = 0; i < this->nc->o->hosts.size(); ++i) - if (Anope::Match(match_host, this->nc->o->hosts[i])) + for (Anope::string h : hosts) + if (Anope::Match(match_host, h)) match = true; if (match == false) return false; @@ -502,14 +505,14 @@ bool User::IsServicesOper() bool User::HasCommand(const Anope::string &command) { if (this->IsServicesOper()) - return this->nc->o->ot->HasCommand(command); + return this->nc->o->GetType()->HasCommand(command); return false; } bool User::HasPriv(const Anope::string &priv) { if (this->IsServicesOper()) - return this->nc->o->ot->HasPriv(priv); + return this->nc->o->GetType()->HasPriv(priv); return false; } @@ -522,14 +525,14 @@ void User::UpdateHost() NickServ::Nick *na = NickServ::service ? NickServ::service->FindNick(this->nick) : nullptr; on_access = false; if (na) - on_access = na->nc->IsOnAccess(this); + on_access = na->GetAccount()->IsOnAccess(this); if (na && (this->IsIdentified(true) || this->IsRecognized())) { Anope::string last_usermask = this->GetIdent() + "@" + this->GetDisplayedHost(); Anope::string last_realhost = this->GetIdent() + "@" + this->host; - na->last_usermask = last_usermask; - na->last_realhost = last_realhost; + na->SetLastUsermask(last_usermask); + na->SetLastRealhost(last_realhost); } } @@ -551,19 +554,20 @@ void User::SetModeInternal(const MessageSource &source, UserMode *um, const Anop if (this->IsServicesOper()) { - if (!this->nc->o->ot->modes.empty()) + Anope::string m = this->nc->o->GetType()->modes; + if (!m.empty()) { - this->SetModes(NULL, "%s", this->nc->o->ot->modes.c_str()); - this->SendMessage(Me, "Changing your usermodes to \002%s\002", this->nc->o->ot->modes.c_str()); + this->SetModes(NULL, "%s", m.c_str()); + this->SendMessage(Me, "Changing your usermodes to \002{0}\002", m); UserMode *oper = ModeManager::FindUserModeByName("OPER"); - if (oper && !this->HasMode("OPER") && this->nc->o->ot->modes.find(oper->mchar) != Anope::string::npos) + if (oper && !this->HasMode("OPER") && m.find(oper->mchar) != Anope::string::npos) IRCD->SendOper(this); } - if (IRCD->CanSetVHost && !this->nc->o->vhost.empty()) + if (IRCD->CanSetVHost && !this->nc->o->GetVhost().empty()) { - this->SendMessage(Me, "Changing your vhost to \002%s\002", this->nc->o->vhost.c_str()); - this->SetDisplayedHost(this->nc->o->vhost); - IRCD->SendVhost(this, "", this->nc->o->vhost); + this->SendMessage(Me, "Changing your vhost to \002{0}\002", this->nc->o->GetVhost()); + this->SetDisplayedHost(this->nc->o->GetVhost()); + IRCD->SendVhost(this, "", this->nc->o->GetVhost()); } } } @@ -593,7 +597,7 @@ void User::RemoveModeInternal(const MessageSource &source, UserMode *um) Event::OnUserModeUnset(&Event::UserModeUnset::OnUserModeUnset, source, this, um->name); } -void User::SetMode(BotInfo *bi, UserMode *um, const Anope::string ¶m) +void User::SetMode(ServiceBot *bi, UserMode *um, const Anope::string ¶m) { if (!um || HasMode(um->name)) return; @@ -602,12 +606,12 @@ void User::SetMode(BotInfo *bi, UserMode *um, const Anope::string ¶m) SetModeInternal(bi, um, param); } -void User::SetMode(BotInfo *bi, const Anope::string &uname, const Anope::string ¶m) +void User::SetMode(ServiceBot *bi, const Anope::string &uname, const Anope::string ¶m) { SetMode(bi, ModeManager::FindUserModeByName(uname), param); } -void User::RemoveMode(BotInfo *bi, UserMode *um, const Anope::string ¶m) +void User::RemoveMode(ServiceBot *bi, UserMode *um, const Anope::string ¶m) { if (!um || !HasMode(um->name)) return; @@ -616,12 +620,12 @@ void User::RemoveMode(BotInfo *bi, UserMode *um, const Anope::string ¶m) RemoveModeInternal(bi, um); } -void User::RemoveMode(BotInfo *bi, const Anope::string &name, const Anope::string ¶m) +void User::RemoveMode(ServiceBot *bi, const Anope::string &name, const Anope::string ¶m) { RemoveMode(bi, ModeManager::FindUserModeByName(name), param); } -void User::SetModes(BotInfo *bi, const char *umodes, ...) +void User::SetModes(ServiceBot *bi, const char *umodes, ...) { char buf[BUFSIZE] = ""; va_list args; diff --git a/src/version.sh b/src/version.sh index 1335a950f..d9033df0f 100644 --- a/src/version.sh +++ b/src/version.sh @@ -3,5 +3,5 @@ VERSION_MAJOR="2" VERSION_MINOR="1" VERSION_PATCH="0" -VERSION_EXTRA="-git" +VERSION_EXTRA="-exploding-tacos" diff --git a/src/xline.cpp b/src/xline.cpp index a39d655be..9d518a659 100644 --- a/src/xline.cpp +++ b/src/xline.cpp @@ -20,14 +20,20 @@ #include "servers.h" /* List of XLine managers we check users against in XLineManager::CheckAll */ -std::list<XLineManager *> XLineManager::XLineManagers; -Serialize::Checker<std::multimap<Anope::string, XLine *, ci::less> > XLineManager::XLinesByUID("XLine"); +std::vector<XLineManager *> XLineManager::XLineManagers; -void XLine::Init() +void XLine::Recache() { - if (this->mask.length() >= 2 && this->mask[0] == '/' && this->mask[this->mask.length() - 1] == '/' && Config->regex_flags) + delete regex; + regex = nullptr; + + delete c; + c = nullptr; + + Anope::string mask = GetMask(); + if (mask.length() >= 2 && mask[0] == '/' && mask[mask.length() - 1] == '/' && Config->regex_flags) { - Anope::string stripped_mask = this->mask.substr(1, this->mask.length() - 2); + Anope::string stripped_mask = mask.substr(1, mask.length() - 2); try { @@ -39,37 +45,37 @@ void XLine::Init() } } - size_t nick_t = this->mask.find('!'); + size_t nick_t = mask.find('!'); if (nick_t != Anope::string::npos) - nick = this->mask.substr(0, nick_t); + nick = mask.substr(0, nick_t); - size_t user_t = this->mask.find('!'), host_t = this->mask.find('@'); + size_t user_t = mask.find('!'), host_t = mask.find('@'); if (host_t != Anope::string::npos) { if (user_t != Anope::string::npos && host_t > user_t) - user = this->mask.substr(user_t + 1, host_t - user_t - 1); + user = mask.substr(user_t + 1, host_t - user_t - 1); else - user = this->mask.substr(0, host_t); + user = mask.substr(0, host_t); } - size_t real_t = this->mask.find('#'); + size_t real_t = mask.find('#'); if (host_t != Anope::string::npos) { if (real_t != Anope::string::npos && real_t > host_t) - host = this->mask.substr(host_t + 1, real_t - host_t - 1); + host = mask.substr(host_t + 1, real_t - host_t - 1); else - host = this->mask.substr(host_t + 1); + host = mask.substr(host_t + 1); } else { if (real_t != Anope::string::npos) - host = this->mask.substr(0, real_t); + host = mask.substr(0, real_t); else - host = this->mask; + host = mask; } if (real_t != Anope::string::npos) - real = this->mask.substr(real_t + 1); + real = mask.substr(real_t + 1); if (host.find('/') != Anope::string::npos) { @@ -82,22 +88,19 @@ void XLine::Init() } } -XLine::XLine(const Anope::string &ma, const Anope::string &r, const Anope::string &uid) : Serializable("XLine"), mask(ma), by(Me->GetName()), created(0), expires(0), reason(r), id(uid) +XLine::XLine(const Anope::string &ma, const Anope::string &r, const Anope::string &uid) : Serialize::Object(xline) { - regex = NULL; - manager = NULL; - c = NULL; - - this->Init(); + SetMask(ma); + SetReason(r); + SetID(id); } -XLine::XLine(const Anope::string &ma, const Anope::string &b, const time_t ex, const Anope::string &r, const Anope::string &uid) : Serializable("XLine"), mask(ma), by(b), created(Anope::CurTime), expires(ex), reason(r), id(uid) +XLine::XLine(const Anope::string &ma, const Anope::string &b, const time_t ex, const Anope::string &r, const Anope::string &uid) : Serialize::Object(xline) { - regex = NULL; - manager = NULL; - c = NULL; - - this->Init(); + SetMask(ma); + SetBy(b); + SetReason(r); + SetID(id); } XLine::~XLine() @@ -106,100 +109,104 @@ XLine::~XLine() delete c; } -const Anope::string &XLine::GetNick() const +void XLine::SetMask(const Anope::string &m) { - return nick; + Set(&XLineType::mask, m); + Recache(); } -const Anope::string &XLine::GetUser() const +Anope::string XLine::GetMask() { - return user; + return Get(&XLineType::mask); } -const Anope::string &XLine::GetHost() const +void XLine::SetBy(const Anope::string &b) { - return host; + Set(&XLineType::by, b); } -const Anope::string &XLine::GetReal() const +Anope::string XLine::GetBy() { - return real; + return Get(&XLineType::by); } -Anope::string XLine::GetReason() const +void XLine::SetReason(const Anope::string &r) { - Anope::string r = this->reason; - if (!this->id.empty()) - r += " (ID: " + this->id + ")"; - return r; + Set(&XLineType::reason, r); } -bool XLine::HasNickOrReal() const +Anope::string XLine::GetReason() { - return !this->GetNick().empty() || !this->GetReal().empty(); + return Get(&XLineType::reason); } -bool XLine::IsRegex() const +void XLine::SetID(const Anope::string &id) { - return !this->mask.empty() && this->mask[0] == '/' && this->mask[this->mask.length() - 1] == '/'; + Set(&XLineType::id, id); } -void XLine::Serialize(Serialize::Data &data) const +Anope::string XLine::GetID() { - data["mask"] << this->mask; - data["by"] << this->by; - data["created"] << this->created; - data["expires"] << this->expires; - data["reason"] << this->reason; - data["uid"] << this->id; - if (this->manager) - data["manager"] << this->manager->name; + return Get(&XLineType::id); } -Serializable* XLine::Unserialize(Serializable *obj, Serialize::Data &data) +void XLine::SetCreated(const time_t &t) { - Anope::string smanager; + Set(&XLineType::created, t); +} - data["manager"] >> smanager; +time_t XLine::GetCreated() +{ + return Get(&XLineType::created); +} - ServiceReference<XLineManager> xlm("XLineManager", smanager); - if (!xlm) - return NULL; +void XLine::SetExpires(const time_t &e) +{ + Set(&XLineType::expires, e); +} - XLine *xl; - if (obj) - { - xl = anope_dynamic_static_cast<XLine *>(obj); - data["mask"] >> xl->mask; - data["by"] >> xl->by; - data["reason"] >> xl->reason; - data["uid"] >> xl->id; +time_t XLine::GetExpires() +{ + return Get(&XLineType::created); +} - if (xlm != xl->manager) - { - xl->manager->DelXLine(xl); - xlm->AddXLine(xl); - } - } - else - { - Anope::string smask, sby, sreason, suid; - time_t expires; +const Anope::string &XLine::GetNick() const +{ + return nick; +} - data["mask"] >> smask; - data["by"] >> sby; - data["reason"] >> sreason; - data["uid"] >> suid; - data["expires"] >> expires; +const Anope::string &XLine::GetUser() const +{ + return user; +} - xl = new XLine(smask, sby, expires, sreason, suid); - xlm->AddXLine(xl); - } +const Anope::string &XLine::GetHost() const +{ + return host; +} + +const Anope::string &XLine::GetReal() const +{ + return real; +} + +Anope::string XLine::GetReasonWithID() +{ + Anope::string r = this->GetReason(); + if (!this->GetID().empty()) + r += " (ID: " + this->GetID() + ")"; + return r; +} - data["created"] >> xl->created; - xl->manager = xlm; +bool XLine::HasNickOrReal() const +{ + return !this->GetNick().empty() || !this->GetReal().empty(); +} - return xl; +bool XLine::IsRegex() +{ + Anope::string mask = GetMask(); + return mask.length() > 2 && mask[0] == '/' && mask[mask.length() - 1] == '/'; } void XLineManager::RegisterXLineManager(XLineManager *xlm) @@ -209,21 +216,16 @@ void XLineManager::RegisterXLineManager(XLineManager *xlm) void XLineManager::UnregisterXLineManager(XLineManager *xlm) { - std::list<XLineManager *>::iterator it = std::find(XLineManagers.begin(), XLineManagers.end(), xlm); - + auto it = std::find(XLineManagers.begin(), XLineManagers.end(), xlm); if (it != XLineManagers.end()) XLineManagers.erase(it); } void XLineManager::CheckAll(User *u) { - for (std::list<XLineManager *>::iterator it = XLineManagers.begin(), it_end = XLineManagers.end(); it != it_end; ++it) - { - XLineManager *xlm = *it; - + for (XLineManager *xlm : XLineManagers) if (xlm->CheckAllXLines(u)) break; - } } Anope::string XLineManager::GenerateUID() @@ -249,12 +251,12 @@ Anope::string XLineManager::GenerateUID() id += c; } } - while (XLinesByUID->count(id) > 0); + while (0);//XLinesByUID.count(id) > 0); return id; } -XLineManager::XLineManager(Module *creator, const Anope::string &xname, char t) : Service(creator, "XLineManager", xname), type(t), xlines("XLine") +XLineManager::XLineManager(Module *creator, const Anope::string &xname, char t) : Service(creator, "XLineManager", xname), type(t) { } @@ -263,120 +265,83 @@ XLineManager::~XLineManager() this->Clear(); } -const char &XLineManager::Type() +char XLineManager::Type() { return this->type; } -size_t XLineManager::GetCount() const +std::vector<XLine *> XLineManager::GetXLines() const { - return this->xlines->size(); -} + std::vector<XLine *> xlines; -const std::vector<XLine *> &XLineManager::GetList() const -{ - return this->xlines; + for (XLine *x : Serialize::GetObjects<XLine *>(xline)) + if (x->manager == this) + xlines.push_back(x); + + return xlines; } void XLineManager::AddXLine(XLine *x) { - if (!x->id.empty()) - XLinesByUID->insert(std::make_pair(x->id, x)); - this->xlines->push_back(x); + // XXX this needs to always be set x->manager = this; } -bool XLineManager::DelXLine(XLine *x) -{ - std::vector<XLine *>::iterator it = std::find(this->xlines->begin(), this->xlines->end(), x); - - if (!x->id.empty()) - { - std::multimap<Anope::string, XLine *, ci::less>::iterator it2 = XLinesByUID->find(x->id), it3 = XLinesByUID->upper_bound(x->id); - for (; it2 != XLinesByUID->end() && it2 != it3; ++it2) - if (it2->second == x) - { - XLinesByUID->erase(it2); - break; - } - } - - if (it != this->xlines->end()) - { - this->SendDel(x); - - delete x; - this->xlines->erase(it); - - return true; - } - - return false; -} - XLine* XLineManager::GetEntry(unsigned index) { - if (index >= this->xlines->size()) - return NULL; + std::vector<XLine *> xlines = GetXLines(); + + if (index >= xlines.size()) + return nullptr; - XLine *x = this->xlines->at(index); - x->QueueUpdate(); - return x; + return xlines.at(index); } void XLineManager::Clear() { - for (unsigned i = 0; i < this->xlines->size(); ++i) - { - XLine *x = this->xlines->at(i); - if (!x->id.empty()) - XLinesByUID->erase(x->id); - delete x; - } - this->xlines->clear(); + for (XLine *x : GetXLines()) + x->Delete(); } bool XLineManager::CanAdd(CommandSource &source, const Anope::string &mask, time_t expires, const Anope::string &reason) { - for (unsigned i = this->GetCount(); i > 0; --i) + for (XLine *x : GetXLines()) { - XLine *x = this->GetEntry(i - 1); - - if (x->mask.equals_ci(mask)) + if (x->GetMask().equals_ci(mask)) { - if (!x->expires || x->expires >= expires) + if (!x->GetExpires() || x->GetExpires() >= expires) { - if (x->reason != reason) + if (x->GetReason() != reason) { - x->reason = reason; - source.Reply(_("Reason for %s updated."), x->mask.c_str()); + x->SetReason(reason); + source.Reply(_("Reason for %s updated."), x->GetMask().c_str()); } else source.Reply(_("%s already exists."), mask.c_str()); } else { - x->expires = expires; - if (x->reason != reason) + x->SetExpires(expires); + if (x->GetReason() != reason) { - x->reason = reason; - source.Reply(_("Expiry and reason updated for %s."), x->mask.c_str()); + x->SetReason(reason); + source.Reply(_("Expiry and reason updated for %s."), x->GetMask().c_str()); } else - source.Reply(_("Expiry for %s updated."), x->mask.c_str()); + source.Reply(_("Expiry for %s updated."), x->GetMask().c_str()); } return false; } - else if (Anope::Match(mask, x->mask) && (!x->expires || x->expires >= expires)) + else if (Anope::Match(mask, x->GetMask()) && (!x->GetExpires() || x->GetExpires() >= expires)) { - source.Reply(_("%s is already covered by %s."), mask.c_str(), x->mask.c_str()); + source.Reply(_("%s is already covered by %s."), mask.c_str(), x->GetMask().c_str()); return false; } - else if (Anope::Match(x->mask, mask) && (!expires || x->expires <= expires)) + else if (Anope::Match(x->GetMask(), mask) && (!expires || x->GetExpires() <= expires)) { - source.Reply(_("Removing %s because %s covers it."), x->mask.c_str(), mask.c_str()); - this->DelXLine(x); + source.Reply(_("Removing %s because %s covers it."), x->GetMask().c_str(), mask.c_str()); + x->Delete(); } } @@ -385,38 +350,21 @@ bool XLineManager::CanAdd(CommandSource &source, const Anope::string &mask, time XLine* XLineManager::HasEntry(const Anope::string &mask) { - std::multimap<Anope::string, XLine *, ci::less>::iterator it = XLinesByUID->find(mask); - if (it != XLinesByUID->end()) - for (std::multimap<Anope::string, XLine *, ci::less>::iterator it2 = XLinesByUID->upper_bound(mask); it != it2; ++it) - if (it->second->manager == NULL || it->second->manager == this) - { - it->second->QueueUpdate(); - return it->second; - } - for (unsigned i = 0, end = this->xlines->size(); i < end; ++i) - { - XLine *x = this->xlines->at(i); - - if (x->mask.equals_ci(mask)) - { - x->QueueUpdate(); + for (XLine *x : GetXLines()) + if (x->GetMask().equals_ci(mask)) return x; - } - } - return NULL; + return nullptr; } XLine *XLineManager::CheckAllXLines(User *u) { - for (unsigned i = this->xlines->size(); i > 0; --i) + for (XLine *x : Serialize::GetObjects<XLine *>(xline)) { - XLine *x = this->xlines->at(i - 1); - - if (x->expires && x->expires < Anope::CurTime) + if (x->GetExpires() && x->GetExpires() < Anope::CurTime) { this->OnExpire(x); - this->DelXLine(x); + x->Delete(); continue; } @@ -427,10 +375,10 @@ XLine *XLineManager::CheckAllXLines(User *u) } } - return NULL; + return nullptr; } -void XLineManager::OnExpire(const XLine *x) +void XLineManager::OnExpire(XLine *x) { } |
