The InspIRCd Project
Home | Developers | Wiki | Forums | Bug Tracker | SVN | Download
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

modules.cpp

Go to the documentation of this file.
00001 /*       +------------------------------------+
00002  *       | Inspire Internet Relay Chat Daemon |
00003  *       +------------------------------------+
00004  *
00005  *  InspIRCd: (C) 2002-2008 InspIRCd Development Team
00006  * See: http://www.inspircd.org/wiki/index.php/Credits
00007  *
00008  * This program is free but copyrighted software; see
00009  *            the file COPYING for details.
00010  *
00011  * ---------------------------------------------------
00012  */
00013 
00014 /* $Core */
00015 
00016 #include "inspircd.h"
00017 #include "xline.h"
00018 #include "socket.h"
00019 #include "socketengine.h"
00020 #include "command_parse.h"
00021 #include "dns.h"
00022 #include "exitcodes.h"
00023 
00024 #ifndef WIN32
00025         #include <dirent.h>
00026 #endif
00027 
00028 // version is a simple class for holding a modules version number
00029 Version::Version(const std::string &sversion, int flags, int api_ver)
00030 : version(sversion), Flags(flags), API(api_ver)
00031 {
00032 }
00033 
00034 Request::Request(char* anydata, Module* src, Module* dst)
00035 : data(anydata), source(src), dest(dst)
00036 {
00037         /* Ensure that because this module doesnt support ID strings, it doesnt break modules that do
00038          * by passing them uninitialized pointers (could happen)
00039          */
00040         id = '\0';
00041 }
00042 
00043 Request::Request(Module* src, Module* dst, const char* idstr)
00044 : id(idstr), source(src), dest(dst)
00045 {
00046 }
00047 
00048 char* Request::GetData()
00049 {
00050         return this->data;
00051 }
00052 
00053 const char* Request::GetId()
00054 {
00055         return this->id;
00056 }
00057 
00058 Module* Request::GetSource()
00059 {
00060         return this->source;
00061 }
00062 
00063 Module* Request::GetDest()
00064 {
00065         return this->dest;
00066 }
00067 
00068 const char* Request::Send()
00069 {
00070         if (this->dest)
00071         {
00072                 return dest->OnRequest(this);
00073         }
00074         else
00075         {
00076                 return NULL;
00077         }
00078 }
00079 
00080 Event::Event(char* anydata, Module* src, const std::string &eventid) : data(anydata), source(src), id(eventid) { }
00081 
00082 char* Event::GetData()
00083 {
00084         return (char*)this->data;
00085 }
00086 
00087 Module* Event::GetSource()
00088 {
00089         return this->source;
00090 }
00091 
00092 char* Event::Send(InspIRCd* ServerInstance)
00093 {
00094         FOREACH_MOD(I_OnEvent,OnEvent(this));
00095         return NULL;
00096 }
00097 
00098 std::string Event::GetEventID()
00099 {
00100         return this->id;
00101 }
00102 
00103 
00104 // These declarations define the behavours of the base class Module (which does nothing at all)
00105 
00106 Module::Module(InspIRCd* Me) : ServerInstance(Me) { }
00107 Module::~Module() { }
00108 
00109 int             Module::OnSendSnotice(char &snomask, std::string &type, const std::string &message) { return 0; }
00110 void            Module::OnUserConnect(User*) { }
00111 void            Module::OnUserQuit(User*, const std::string&, const std::string&) { }
00112 void            Module::OnUserDisconnect(User*) { }
00113 void            Module::OnUserJoin(User*, Channel*, bool, bool&) { }
00114 void            Module::OnPostJoin(User*, Channel*) { }
00115 void            Module::OnUserPart(User*, Channel*, std::string&, bool&) { }
00116 void            Module::OnRehash(User*, const std::string&) { }
00117 void            Module::OnServerRaw(std::string&, bool, User*) { }
00118 int             Module::OnUserPreJoin(User*, Channel*, const char*, std::string&, const std::string&) { return 0; }
00119 void            Module::OnMode(User*, void*, int, const std::string&) { }
00120 Version         Module::GetVersion() { return Version("Misconfigured", VF_VENDOR, -1); }
00121 void            Module::OnOper(User*, const std::string&) { }
00122 void            Module::OnPostOper(User*, const std::string&, const std::string &) { }
00123 void            Module::OnInfo(User*) { }
00124 void            Module::OnWhois(User*, User*) { }
00125 int             Module::OnUserPreInvite(User*, User*, Channel*, time_t) { return 0; }
00126 int             Module::OnUserPreMessage(User*, void*, int, std::string&, char, CUList&) { return 0; }
00127 int             Module::OnUserPreNotice(User*, void*, int, std::string&, char, CUList&) { return 0; }
00128 int             Module::OnUserPreNick(User*, const std::string&) { return 0; }
00129 void            Module::OnUserPostNick(User*, const std::string&) { }
00130 int             Module::OnAccessCheck(User*, User*, Channel*, int) { return ACR_DEFAULT; }
00131 void            Module::On005Numeric(std::string&) { }
00132 int             Module::OnKill(User*, User*, const std::string&) { return 0; }
00133 void            Module::OnLoadModule(Module*, const std::string&) { }
00134 void            Module::OnUnloadModule(Module*, const std::string&) { }
00135 void            Module::OnBackgroundTimer(time_t) { }
00136 int             Module::OnPreCommand(std::string&, std::vector<std::string>&, User *, bool, const std::string&) { return 0; }
00137 void            Module::OnPostCommand(const std::string&, const std::vector<std::string>&, User *, CmdResult, const std::string&) { }
00138 bool            Module::OnCheckReady(User*) { return true; }
00139 int             Module::OnUserRegister(User*) { return 0; }
00140 int             Module::OnUserPreKick(User*, User*, Channel*, const std::string&) { return 0; }
00141 void            Module::OnUserKick(User*, User*, Channel*, const std::string&, bool&) { }
00142 int             Module::OnRawMode(User*, Channel*, const char, const std::string &, bool, int, bool) { return 0; }
00143 int             Module::OnCheckInvite(User*, Channel*) { return 0; }
00144 int             Module::OnCheckKey(User*, Channel*, const std::string&) { return 0; }
00145 int             Module::OnCheckLimit(User*, Channel*) { return 0; }
00146 int             Module::OnCheckBan(User*, Channel*) { return 0; }
00147 int             Module::OnCheckExtBan(User *, Channel *, char) { return 0; }
00148 int             Module::OnCheckStringExtBan(const std::string &s, Channel *c, char type) { return 0; }
00149 int             Module::OnStats(char, User*, string_list&) { return 0; }
00150 int             Module::OnChangeLocalUserHost(User*, const std::string&) { return 0; }
00151 int             Module::OnChangeLocalUserGECOS(User*, const std::string&) { return 0; }
00152 int             Module::OnLocalTopicChange(User*, Channel*, const std::string&) { return 0; }
00153 void            Module::OnEvent(Event*) { return; }
00154 const char*             Module::OnRequest(Request*) { return NULL; }
00155 int             Module::OnPassCompare(Extensible* ex, const std::string &password, const std::string &input, const std::string& hashtype) { return 0; }
00156 void            Module::OnGlobalOper(User*) { }
00157 void            Module::OnPostConnect(User*) { }
00158 int             Module::OnAddBan(User*, Channel*, const std::string &) { return 0; }
00159 int             Module::OnDelBan(User*, Channel*, const std::string &) { return 0; }
00160 void            Module::OnRawSocketAccept(int, const std::string&, int) { }
00161 int             Module::OnRawSocketWrite(int, const char*, int) { return 0; }
00162 void            Module::OnRawSocketClose(int) { }
00163 void            Module::OnRawSocketConnect(int) { }
00164 int             Module::OnRawSocketRead(int, char*, unsigned int, int&) { return 0; }
00165 void            Module::OnUserMessage(User*, void*, int, const std::string&, char, const CUList&) { }
00166 void            Module::OnUserNotice(User*, void*, int, const std::string&, char, const CUList&) { }
00167 void            Module::OnRemoteKill(User*, User*, const std::string&, const std::string&) { }
00168 void            Module::OnUserInvite(User*, User*, Channel*, time_t) { }
00169 void            Module::OnPostLocalTopicChange(User*, Channel*, const std::string&) { }
00170 void            Module::OnGetServerDescription(const std::string&, std::string&) { }
00171 void            Module::OnSyncUser(User*, Module*, void*) { }
00172 void            Module::OnSyncChannel(Channel*, Module*, void*) { }
00173 void            Module::ProtoSendMode(void*, int, void*, const std::string&) { }
00174 void            Module::OnSyncChannelMetaData(Channel*, Module*, void*, const std::string&, bool) { }
00175 void            Module::OnSyncUserMetaData(User*, Module*, void*, const std::string&, bool) { }
00176 void            Module::OnSyncOtherMetaData(Module*, void*, bool) { }
00177 void            Module::OnDecodeMetaData(int, void*, const std::string&, const std::string&) { }
00178 void            Module::ProtoSendMetaData(void*, int, void*, const std::string&, const std::string&) { }
00179 void            Module::OnWallops(User*, const std::string&) { }
00180 void            Module::OnChangeHost(User*, const std::string&) { }
00181 void            Module::OnChangeName(User*, const std::string&) { }
00182 void            Module::OnAddLine(User*, XLine*) { }
00183 void            Module::OnDelLine(User*, XLine*) { }
00184 void            Module::OnExpireLine(XLine*) { }
00185 void            Module::OnCleanup(int, void*) { }
00186 int             Module::OnChannelPreDelete(Channel*) { return 0; }
00187 void            Module::OnChannelDelete(Channel*) { }
00188 int             Module::OnSetAway(User*, const std::string &) { return 0; }
00189 int             Module::OnUserList(User*, Channel*, CUList*&) { return 0; }
00190 int             Module::OnWhoisLine(User*, User*, int&, std::string&) { return 0; }
00191 void            Module::OnBuildExemptList(MessageType, Channel*, User*, char, CUList&, const std::string&) { }
00192 void            Module::OnGarbageCollect() { }
00193 void            Module::OnBufferFlushed(User*) { }
00194 void            Module::OnText(User*, void*, int, const std::string&, char, CUList&) { }
00195 void            Module::OnRunTestSuite() { }
00196 void            Module::OnNamesListItem(User*, User*, Channel*, std::string&, std::string&) { }
00197 int             Module::OnNumeric(User*, unsigned int, const std::string&) { return 0; }
00198 void            Module::OnHookUserIO(User*, const std::string&) { }
00199 bool            Module::OnHostCycle(User* user) { return false; }
00200 
00201 ModuleManager::ModuleManager(InspIRCd* Ins) : ModCount(0), Instance(Ins)
00202 {
00203 }
00204 
00205 ModuleManager::~ModuleManager()
00206 {
00207 }
00208 
00209 bool ModuleManager::Attach(Implementation i, Module* mod)
00210 {
00211         if (std::find(EventHandlers[i].begin(), EventHandlers[i].end(), mod) != EventHandlers[i].end())
00212                 return false;
00213 
00214         EventHandlers[i].push_back(mod);
00215         return true;
00216 }
00217 
00218 bool ModuleManager::Detach(Implementation i, Module* mod)
00219 {
00220         EventHandlerIter x = std::find(EventHandlers[i].begin(), EventHandlers[i].end(), mod);
00221 
00222         if (x == EventHandlers[i].end())
00223                 return false;
00224 
00225         EventHandlers[i].erase(x);
00226         return true;
00227 }
00228 
00229 void ModuleManager::Attach(Implementation* i, Module* mod, size_t sz)
00230 {
00231         for (size_t n = 0; n < sz; ++n)
00232                 Attach(i[n], mod);
00233 }
00234 
00235 void ModuleManager::DetachAll(Module* mod)
00236 {
00237         for (size_t n = I_BEGIN + 1; n != I_END; ++n)
00238                 Detach((Implementation)n, mod);
00239 }
00240 
00241 bool ModuleManager::SetPriority(Module* mod, PriorityState s)
00242 {
00243         for (size_t n = I_BEGIN + 1; n != I_END; ++n)
00244                 SetPriority(mod, (Implementation)n, s);
00245 
00246         return true;
00247 }
00248 
00249 bool ModuleManager::SetPriority(Module* mod, Implementation i, PriorityState s, Module** modules, size_t sz)
00250 {
00257         size_t swap_pos = 0;
00258         size_t source = 0;
00259         bool swap = true;
00260         bool found = false;
00261 
00262         /* Locate our module. This is O(n) but it only occurs on module load so we're
00263          * not too bothered about it
00264          */
00265         for (size_t x = 0; x != EventHandlers[i].size(); ++x)
00266         {
00267                 if (EventHandlers[i][x] == mod)
00268                 {
00269                         source = x;
00270                         found = true;
00271                         break;
00272                 }
00273         }
00274 
00275         /* Eh? this module doesnt exist, probably trying to set priority on an event
00276          * theyre not attached to.
00277          */
00278         if (!found)
00279                 return false;
00280 
00281         switch (s)
00282         {
00283                 /* Dummy value */
00284                 case PRIO_DONTCARE:
00285                         swap = false;
00286                 break;
00287                 /* Module wants to be first, sod everything else */
00288                 case PRIO_FIRST:
00289                         swap_pos = 0;
00290                 break;
00291                 /* Module is submissive and wants to be last... awww. */
00292                 case PRIO_LAST:
00293                         if (EventHandlers[i].empty())
00294                                 swap_pos = 0;
00295                         else
00296                                 swap_pos = EventHandlers[i].size() - 1;
00297                 break;
00298                 /* Place this module after a set of other modules */
00299                 case PRIO_AFTER:
00300                 {
00301                         /* Find the latest possible position */
00302                         swap_pos = 0;
00303                         swap = false;
00304                         for (size_t x = 0; x != EventHandlers[i].size(); ++x)
00305                         {
00306                                 for (size_t n = 0; n < sz; ++n)
00307                                 {
00308                                         if ((modules[n]) && (EventHandlers[i][x] == modules[n]) && (x >= swap_pos) && (source <= swap_pos))
00309                                         {
00310                                                 swap_pos = x;
00311                                                 swap = true;
00312                                         }
00313                                 }
00314                         }
00315                 }
00316                 break;
00317                 /* Place this module before a set of other modules */
00318                 case PRIO_BEFORE:
00319                 {
00320                         swap_pos = EventHandlers[i].size() - 1;
00321                         swap = false;
00322                         for (size_t x = 0; x != EventHandlers[i].size(); ++x)
00323                         {
00324                                 for (size_t n = 0; n < sz; ++n)
00325                                 {
00326                                         if ((modules[n]) && (EventHandlers[i][x] == modules[n]) && (x <= swap_pos) && (source >= swap_pos))
00327                                         {
00328                                                 swap = true;
00329                                                 swap_pos = x;
00330                                         }
00331                                 }
00332                         }
00333                 }
00334                 break;
00335         }
00336 
00337         /* Do we need to swap? */
00338         if (swap && (swap_pos != source))
00339         {
00340                 /* Suggestion from Phoenix, "shuffle" the modules to better retain call order */
00341                 int incrmnt = 1;
00342 
00343                 if (source > swap_pos)
00344                         incrmnt = -1;
00345 
00346                 for (unsigned int j = source; j != swap_pos; j += incrmnt)
00347                 {
00348                         if (( j + incrmnt > EventHandlers[i].size() - 1) || (j + incrmnt < 0))
00349                                 continue;
00350 
00351                         std::swap(EventHandlers[i][j], EventHandlers[i][j+incrmnt]);
00352                 }
00353         }
00354 
00355         return true;
00356 }
00357 
00358 std::string& ModuleManager::LastError()
00359 {
00360         return LastModuleError;
00361 }
00362 
00363 bool ModuleManager::Load(const char* filename)
00364 {
00365         /* Do we have a glob pattern in the filename?
00366          * The user wants to load multiple modules which
00367          * match the pattern.
00368          */
00369         if (strchr(filename,'*') || (strchr(filename,'?')))
00370         {
00371                 int n_match = 0;
00372                 DIR* library = opendir(Instance->Config->ModPath);
00373                 if (library)
00374                 {
00375                         /* Try and locate and load all modules matching the pattern */
00376                         dirent* entry = NULL;
00377                         while (0 != (entry = readdir(library)))
00378                         {
00379                                 if (InspIRCd::Match(entry->d_name, filename, NULL))
00380                                 {
00381                                         if (!this->Load(entry->d_name))
00382                                                 n_match++;
00383                                 }
00384                         }
00385                         closedir(library);
00386                 }
00387                 /* Loadmodule will now return false if any one of the modules failed
00388                  * to load (but wont abort when it encounters a bad one) and when 1 or
00389                  * more modules were actually loaded.
00390                  */
00391                 return (n_match > 0);
00392         }
00393 
00394         char modfile[MAXBUF];
00395         snprintf(modfile,MAXBUF,"%s/%s",Instance->Config->ModPath,filename);
00396         std::string filename_str = filename;
00397 
00398         if (!ServerConfig::DirValid(modfile))
00399         {
00400                 LastModuleError = "Module " + std::string(filename) + " is not in the module directory that i am configured to look in (is "+Instance->Config->ModPath+" really a symlink?)";
00401                 Instance->Logs->Log("MODULE", DEFAULT, LastModuleError);
00402                 return false;
00403         }
00404         
00405         if (!ServerConfig::FileExists(modfile))
00406         {
00407                 LastModuleError = "Module file could not be found: " + filename_str;
00408                 Instance->Logs->Log("MODULE", DEFAULT, LastModuleError);
00409                 return false;
00410         }
00411         
00412         if (Modules.find(filename_str) != Modules.end())
00413         {       
00414                 LastModuleError = "Module " + filename_str + " is already loaded, cannot load a module twice!";
00415                 Instance->Logs->Log("MODULE", DEFAULT, LastModuleError);
00416                 return false;
00417         }
00418                 
00419         Module* newmod = NULL;
00420         ircd_module* newhandle = NULL;
00421 
00422         try
00423         {
00424                 /* This will throw a CoreException if there's a problem loading
00425                  * the module file or getting a pointer to the init_module symbol.
00426                  */
00427                 newhandle = new ircd_module(Instance, modfile, "init_module");
00428                 newmod = newhandle->CallInit();
00429 
00430                 if (newmod)
00431                 {
00432                         Version v = newmod->GetVersion();
00433 
00434                         if (v.API != API_VERSION)
00435                         {
00436                                 DetachAll(newmod);
00437                                 delete newmod;
00438                                 delete newhandle;
00439                                 LastModuleError = "Unable to load " + filename_str + ": Incorrect module API version: " + ConvToStr(v.API) + " (our version: " + ConvToStr(API_VERSION) + ")";
00440                                 Instance->Logs->Log("MODULE", DEFAULT, LastModuleError);
00441                                 return false;
00442                         }
00443                         else
00444                         {
00445                                 Instance->Logs->Log("MODULE", DEFAULT,"New module introduced: %s (API version %d, Module version %s)%s", filename, v.API, v.version.c_str(), (!(v.Flags & VF_VENDOR) ? " [3rd Party]" : " [Vendor]"));
00446                         }
00447 
00448                         Modules[filename_str] = std::make_pair(newhandle, newmod);
00449                 }
00450                 else
00451                 {
00452                         delete newhandle;
00453                         LastModuleError = "Unable to load " + filename_str + ": Probably missing init_module() entrypoint, but dlsym() didn't notice a problem";
00454                         Instance->Logs->Log("MODULE", DEFAULT, LastModuleError);
00455                         return false;
00456                 }
00457         }
00459         catch (LoadModuleException& modexcept)
00460         {
00461                 DetachAll(newmod);
00462                 if (newmod)
00463                         delete newmod;
00464                 if (newhandle)
00465                         delete newhandle;
00466                 LastModuleError = "Unable to load " + filename_str + ": Error when loading: " + modexcept.GetReason();
00467                 Instance->Logs->Log("MODULE", DEFAULT, LastModuleError);
00468                 return false;
00469         }
00470         catch (FindSymbolException& modexcept)
00471         {
00472                 DetachAll(newmod);
00473                 if (newmod)
00474                         delete newmod;
00475                 if (newhandle)
00476                         delete newhandle;
00477                 LastModuleError = "Unable to load " + filename_str + ": Error finding symbol: " + modexcept.GetReason();
00478                 Instance->Logs->Log("MODULE", DEFAULT, LastModuleError);
00479                 return false;
00480         }
00481         catch (CoreException& modexcept)
00482         {
00483                 DetachAll(newmod);
00484                 if (newmod)
00485                         delete newmod;
00486                 if (newhandle)
00487                         delete newhandle;
00488                 LastModuleError = "Unable to load " + filename_str + ": " + modexcept.GetReason();
00489                 Instance->Logs->Log("MODULE", DEFAULT, LastModuleError);
00490                 return false;
00491         }
00492 
00493         this->ModCount++;
00494         FOREACH_MOD_I(Instance,I_OnLoadModule,OnLoadModule(newmod, filename_str));
00495 
00496         /* We give every module a chance to re-prioritize when we introduce a new one,
00497          * not just the one thats loading, as the new module could affect the preference
00498          * of others
00499          */
00500         for (std::map<std::string, std::pair<ircd_module*, Module*> >::iterator n = Modules.begin(); n != Modules.end(); ++n)
00501                 n->second.second->Prioritize();
00502 
00503         Instance->BuildISupport();
00504         return true;
00505 }
00506 
00507 bool ModuleManager::Unload(const char* filename)
00508 {
00509         std::string filename_str(filename);
00510         std::map<std::string, std::pair<ircd_module*, Module*> >::iterator modfind = Modules.find(filename);
00511 
00512         if (modfind != Modules.end())
00513         {
00514                 if (modfind->second.second->GetVersion().Flags & VF_STATIC)
00515                 {
00516                         LastModuleError = "Module " + filename_str + " not unloadable (marked static)";
00517                         Instance->Logs->Log("MODULE", DEFAULT, LastModuleError);
00518                         return false;
00519                 }
00520                 std::pair<int,std::string> intercount = GetInterfaceInstanceCount(modfind->second.second);
00521                 if (intercount.first > 0)
00522                 {
00523                         LastModuleError = "Failed to unload module " + filename_str + ", being used by " + ConvToStr(intercount.first) + " other(s) via interface '" + intercount.second + "'";
00524                         Instance->Logs->Log("MODULE", DEFAULT, LastModuleError);
00525                         return false;
00526                 }
00527 
00528                 /* Give the module a chance to tidy out all its metadata */
00529                 for (chan_hash::iterator c = Instance->chanlist->begin(); c != Instance->chanlist->end(); c++)
00530                 {
00531                         modfind->second.second->OnCleanup(TYPE_CHANNEL,c->second);
00532                 }
00533                 for (user_hash::iterator u = Instance->Users->clientlist->begin(); u != Instance->Users->clientlist->end(); u++)
00534                 {
00535                         modfind->second.second->OnCleanup(TYPE_USER,u->second);
00536                 }
00537 
00538                 /* Tidy up any dangling resolvers */
00539                 Instance->Res->CleanResolvers(modfind->second.second);
00540 
00541 
00542                 FOREACH_MOD_I(Instance,I_OnUnloadModule,OnUnloadModule(modfind->second.second, modfind->first));
00543 
00544                 this->DetachAll(modfind->second.second);
00545 
00546                 Instance->Parser->RemoveCommands(filename);
00547 
00548                 delete modfind->second.second;
00549                 delete modfind->second.first;
00550                 Modules.erase(modfind);
00551 
00552                 Instance->Logs->Log("MODULE", DEFAULT,"Module %s unloaded",filename);
00553                 this->ModCount--;
00554                 Instance->BuildISupport();
00555                 return true;
00556         }
00557 
00558         LastModuleError = "Module " + filename_str + " is not loaded, cannot unload it!";
00559         Instance->Logs->Log("MODULE", DEFAULT, LastModuleError);
00560         return false;
00561 }
00562 
00563 /* We must load the modules AFTER initializing the socket engine, now */
00564 void ModuleManager::LoadAll()
00565 {
00566         char configToken[MAXBUF];
00567         ModCount = -1;
00568 
00569         for(int count = 0; count < Instance->Config->ConfValueEnum(Instance->Config->config_data, "module"); count++)
00570         {
00571                 Instance->Config->ConfValue(Instance->Config->config_data, "module", "name", count, configToken, MAXBUF);
00572                 printf_c("[\033[1;32m*\033[0m] Loading module:\t\033[1;32m%s\033[0m\n",configToken);
00573                 
00574                 if (!this->Load(configToken))           
00575                 {
00576                         Instance->Logs->Log("MODULE", DEFAULT, this->LastError());
00577                         printf_c("\n[\033[1;31m*\033[0m] %s\n\n", this->LastError().c_str());
00578                         Instance->Exit(EXIT_STATUS_MODULE);
00579                 }
00580         }
00581 }
00582 
00583 bool ModuleManager::PublishFeature(const std::string &FeatureName, Module* Mod)
00584 {
00585         if (Features.find(FeatureName) == Features.end())
00586         {
00587                 Features[FeatureName] = Mod;
00588                 return true;
00589         }
00590         return false;
00591 }
00592 
00593 bool ModuleManager::UnpublishFeature(const std::string &FeatureName)
00594 {
00595         featurelist::iterator iter = Features.find(FeatureName);
00596         
00597         if (iter == Features.end())
00598                 return false;
00599 
00600         Features.erase(iter);
00601         return true;
00602 }
00603 
00604 Module* ModuleManager::FindFeature(const std::string &FeatureName)
00605 {
00606         featurelist::iterator iter = Features.find(FeatureName);
00607 
00608         if (iter == Features.end())
00609                 return NULL;
00610 
00611         return iter->second;
00612 }
00613 
00614 bool ModuleManager::PublishInterface(const std::string &InterfaceName, Module* Mod)
00615 {
00616         interfacelist::iterator iter = Interfaces.find(InterfaceName);
00617 
00618         if (iter == Interfaces.end())
00619         {
00620                 modulelist ml;
00621                 ml.push_back(Mod);
00622                 Interfaces[InterfaceName] = std::make_pair(0, ml);
00623         }
00624         else
00625         {
00626                 iter->second.second.push_back(Mod);
00627         }
00628         return true;
00629 }
00630 
00631 bool ModuleManager::UnpublishInterface(const std::string &InterfaceName, Module* Mod)
00632 {
00633         interfacelist::iterator iter = Interfaces.find(InterfaceName);
00634 
00635         if (iter == Interfaces.end())
00636                 return false;
00637 
00638         for (modulelist::iterator x = iter->second.second.begin(); x != iter->second.second.end(); x++)
00639         {
00640                 if (*x == Mod)
00641                 {
00642                         iter->second.second.erase(x);
00643                         if (iter->second.second.empty())
00644                                 Interfaces.erase(InterfaceName);
00645                         return true;
00646                 }
00647         }
00648         return false;
00649 }
00650 
00651 modulelist* ModuleManager::FindInterface(const std::string &InterfaceName)
00652 {
00653         interfacelist::iterator iter = Interfaces.find(InterfaceName);
00654         if (iter == Interfaces.end())
00655                 return NULL;
00656         else
00657                 return &(iter->second.second);
00658 }
00659 
00660 bool ModuleManager::ModuleHasInterface(Module* mod, const std::string& InterfaceName)
00661 {
00662         interfacelist::iterator iter = Interfaces.find(InterfaceName);
00663         if (iter == Interfaces.end())
00664                 return false;
00665         else
00666         {
00667                 modulelist& ml = iter->second.second;
00668                 modulelist::iterator mi = std::find(ml.begin(), ml.end(), mod);
00669                 return (mi != ml.end());
00670         }
00671 }
00672 
00673 void ModuleManager::UseInterface(const std::string &InterfaceName)
00674 {
00675         interfacelist::iterator iter = Interfaces.find(InterfaceName);
00676         if (iter != Interfaces.end())
00677                 iter->second.first++;
00678 
00679 }
00680 
00681 void ModuleManager::DoneWithInterface(const std::string &InterfaceName)
00682 {
00683         interfacelist::iterator iter = Interfaces.find(InterfaceName);
00684         if (iter != Interfaces.end())
00685                 iter->second.first--;
00686 }
00687 
00688 std::pair<int,std::string> ModuleManager::GetInterfaceInstanceCount(Module* m)
00689 {
00690         for (interfacelist::iterator iter = Interfaces.begin(); iter != Interfaces.end(); iter++)
00691         {
00692                 for (modulelist::iterator x = iter->second.second.begin(); x != iter->second.second.end(); x++)
00693                 {
00694                         if (*x == m)
00695                         {
00696                                 return std::make_pair(iter->