#include "socket.h"
#include "socketengine.h"
#include "command_parse.h"
-#include "dns.h"
#include "exitcodes.h"
#ifndef _WIN32
#endif
static std::vector<dynamic_reference_base*>* dynrefs = NULL;
+static bool dynref_init_complete = false;
void dynamic_reference_base::reset_all()
{
+ dynref_init_complete = true;
if (!dynrefs)
return;
for(unsigned int i = 0; i < dynrefs->size(); i++)
- (*dynrefs)[i]->ClearCache();
+ (*dynrefs)[i]->resolve();
}
// Version is a simple class for holding a modules version number
void Module::OnPreRehash(User*, const std::string&) { }
void Module::OnModuleRehash(User*, const std::string&) { }
void Module::OnRehash(User*) { }
-ModResult Module::OnUserPreJoin(User*, Channel*, const std::string&, std::string&, const std::string&) { return MOD_RES_PASSTHRU; }
+ModResult Module::OnUserPreJoin(LocalUser*, Channel*, const std::string&, std::string&, const std::string&) { return MOD_RES_PASSTHRU; }
void Module::OnMode(User*, void*, int, const std::vector<std::string>&, const std::vector<TranslateType>&) { }
void Module::OnOper(User*, const std::string&) { }
void Module::OnPostOper(User*, const std::string&, const std::string &) { }
ModResult Module::OnUserPreNick(User*, const std::string&) { return MOD_RES_PASSTHRU; }
void Module::OnUserPostNick(User*, const std::string&) { }
ModResult Module::OnPreMode(User*, User*, Channel*, const std::vector<std::string>&) { return MOD_RES_PASSTHRU; }
-void Module::On005Numeric(std::string&) { }
+void Module::On005Numeric(std::map<std::string, std::string>&) { }
ModResult Module::OnKill(User*, User*, const std::string&) { return MOD_RES_PASSTHRU; }
void Module::OnLoadModule(Module*) { }
void Module::OnUnloadModule(Module*) { }
ModResult Module::OnPassCompare(Extensible* ex, const std::string &password, const std::string &input, const std::string& hashtype) { return MOD_RES_PASSTHRU; }
void Module::OnGlobalOper(User*) { }
void Module::OnPostConnect(User*) { }
-ModResult Module::OnAddBan(User*, Channel*, const std::string &) { return MOD_RES_PASSTHRU; }
-ModResult Module::OnDelBan(User*, Channel*, const std::string &) { return MOD_RES_PASSTHRU; }
void Module::OnStreamSocketAccept(StreamSocket*, irc::sockets::sockaddrs*, irc::sockets::sockaddrs*) { }
int Module::OnStreamSocketWrite(StreamSocket*, std::string&) { return -1; }
void Module::OnStreamSocketClose(StreamSocket*) { }
{
std::map<std::string, Module*>::iterator modfind = Modules.find(mod->ModuleSourceFile);
- if (modfind == Modules.end() || modfind->second != mod)
+ if ((modfind == Modules.end()) || (modfind->second != mod) || (mod->dying))
{
LastModuleError = "Module " + mod->ModuleSourceFile + " is not loaded, cannot unload it!";
- ServerInstance->Logs->Log("MODULE", DEFAULT, LastModuleError);
+ ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, LastModuleError);
return false;
}
if (mod->GetVersion().Flags & VF_STATIC)
{
LastModuleError = "Module " + mod->ModuleSourceFile + " not unloadable (marked static)";
- ServerInstance->Logs->Log("MODULE", DEFAULT, LastModuleError);
+ ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, LastModuleError);
return false;
}
+
+ mod->dying = true;
return true;
}
void ModuleManager::DoSafeUnload(Module* mod)
{
+ // First, notify all modules that a module is about to be unloaded, so in case
+ // they pass execution to the soon to be unloaded module, it will happen now,
+ // i.e. before we unregister the services of the module being unloaded
+ FOREACH_MOD(I_OnUnloadModule,OnUnloadModule(mod));
+
std::map<std::string, Module*>::iterator modfind = Modules.find(mod->ModuleSourceFile);
std::vector<reference<ExtensionItem> > items;
ModeHandler* mh;
mh = ServerInstance->Modes->FindMode(m, MODETYPE_USER);
if (mh && mh->creator == mod)
- ServerInstance->Modes->DelMode(mh);
+ this->DelService(*mh);
mh = ServerInstance->Modes->FindMode(m, MODETYPE_CHANNEL);
if (mh && mh->creator == mod)
- ServerInstance->Modes->DelMode(mh);
+ this->DelService(*mh);
}
for(std::multimap<std::string, ServiceProvider*>::iterator i = DataProviders.begin(); i != DataProviders.end(); )
{
dynamic_reference_base::reset_all();
- /* Tidy up any dangling resolvers */
- ServerInstance->Res->CleanResolvers(mod);
-
- FOREACH_MOD(I_OnUnloadModule,OnUnloadModule(mod));
-
DetachAll(mod);
Modules.erase(modfind);
ServerInstance->GlobalCulls.AddItem(mod);
- ServerInstance->Logs->Log("MODULE", DEFAULT,"Module %s unloaded",mod->ModuleSourceFile.c_str());
+ ServerInstance->Logs->Log("MODULE", LOG_DEFAULT,"Module %s unloaded",mod->ModuleSourceFile.c_str());
this->ModCount--;
- ServerInstance->BuildISupport();
+ ServerInstance->ISupport.Build();
}
void ModuleManager::UnloadAll()
case SERVICE_MODE:
if (!ServerInstance->Modes->AddMode(static_cast<ModeHandler*>(&item)))
throw ModuleException("Mode "+std::string(item.name)+" already exists.");
+ DataProviders.insert(std::make_pair("mode/" + item.name, &item));
+ dynamic_reference_base::reset_all();
return;
case SERVICE_METADATA:
if (!ServerInstance->Extensions.Register(static_cast<ExtensionItem*>(&item)))
case SERVICE_DATA:
case SERVICE_IOHOOK:
{
+ if (item.name.substr(0, 5) == "mode/")
+ throw ModuleException("The \"mode/\" service name prefix is reserved.");
+
DataProviders.insert(std::make_pair(item.name, &item));
std::string::size_type slash = item.name.find('/');
if (slash != std::string::npos)
DataProviders.insert(std::make_pair(item.name.substr(0, slash), &item));
DataProviders.insert(std::make_pair(item.name.substr(slash + 1), &item));
}
+ dynamic_reference_base::reset_all();
return;
}
default:
case SERVICE_MODE:
if (!ServerInstance->Modes->DelMode(static_cast<ModeHandler*>(&item)))
throw ModuleException("Mode "+std::string(item.name)+" does not exist.");
- return;
+ // Fall through
case SERVICE_DATA:
case SERVICE_IOHOOK:
{
if (!dynrefs)
dynrefs = new std::vector<dynamic_reference_base*>;
dynrefs->push_back(this);
+ if (dynref_init_complete)
+ resolve();
}
dynamic_reference_base::~dynamic_reference_base()
void dynamic_reference_base::SetProvider(const std::string& newname)
{
name = newname;
- ClearCache();
-}
-
-void dynamic_reference_base::lookup()
-{
- if (!*this)
- throw ModuleException("Dynamic reference to '" + name + "' failed to resolve");
+ resolve();
}
-dynamic_reference_base::operator bool()
+void dynamic_reference_base::resolve()
{
- if (!value)
- {
- std::multimap<std::string, ServiceProvider*>::iterator i = ServerInstance->Modules->DataProviders.find(name);
- if (i != ServerInstance->Modules->DataProviders.end())
- value = static_cast<DataProvider*>(i->second);
- }
- return (value != NULL);
+ std::multimap<std::string, ServiceProvider*>::iterator i = ServerInstance->Modules->DataProviders.find(name);
+ if (i != ServerInstance->Modules->DataProviders.end())
+ value = static_cast<DataProvider*>(i->second);
+ else
+ value = NULL;
}
void InspIRCd::SendMode(const std::vector<std::string>& parameters, User *user)
this->PI->SendMode(parameters[0], Modes->GetLastParseParams(), Modes->GetLastParseTranslate());
}
-bool InspIRCd::AddResolver(Resolver* r, bool cached)
-{
- if (!cached)
- return this->Res->AddResolverClass(r);
- else
- {
- r->TriggerCachedResult();
- delete r;
- return true;
- }
-}
-
Module* ModuleManager::Find(const std::string &name)
{
std::map<std::string, Module*>::iterator modfind = Modules.find(name);