summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordanieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7>2009-10-06 16:50:48 +0000
committerdanieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7>2009-10-06 16:50:48 +0000
commitf9717e35cab505cfca95e708b53336bd7bf78f56 (patch)
tree04c1fd9c4d34b224f9816fd501b18809cc01152e
parent2fabf1ccd1897c55b58757d8ed722a025f93554f (diff)
Take advantage of link errors to check API_VERSION at module load time
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@11805 e03df62e-2008-0410-955e-edbf42e46eb7
-rw-r--r--include/modules.h26
-rw-r--r--src/modules.cpp25
2 files changed, 23 insertions, 28 deletions
diff --git a/include/modules.h b/include/modules.h
index ca345dbc1..d59bdf05b 100644
--- a/include/modules.h
+++ b/include/modules.h
@@ -104,8 +104,8 @@ struct ModResult {
}
};
-/** If you change the module API, change this value. */
-#define API_VERSION 13000
+/** If you change the module API in any way, increment this value. */
+#define API_VERSION 131
class ServerConfig;
@@ -226,13 +226,14 @@ do { \
#define IS_AWAY(x) (!x->awaymsg.empty())
/** Holds a module's Version information.
- * The four members (set by the constructor only) indicate details as to the version number
- * of a module. A class of type Version is returned by the GetVersion method of the Module class.
- * The flags and API values represent the module flags and API version of the module.
- * The API version of a module must match the API version of the core exactly for the module to
- * load successfully.
+ * The members (set by the constructor only) indicate details as to the version number
+ * of a module. A class of type Version is returned by the GetVersion method of the Module class.
+ *
+ * The core provides only one implementation of the template, causing a run-time linking
+ * error when attempting to load a module compiled against a different API_VERSION.
*/
-class CoreExport Version : public classbase
+template<int api>
+class CoreExport VersionBase : public classbase
{
public:
/** Module description
@@ -242,16 +243,17 @@ class CoreExport Version : public classbase
*/
const std::string version;
- /** Flags and API version
+ /** Flags
*/
- const int Flags, API;
+ const int Flags;
/** Initialize version class
*/
- Version(const std::string &desc, int flags,
- int api_ver = API_VERSION, const std::string& src_rev = VERSION " r" REVISION);
+ VersionBase(const std::string &desc, int flags = VF_NONE, int dummy = 0, const std::string& src_rev = VERSION " r" REVISION);
};
+typedef VersionBase<API_VERSION> Version;
+
/** The ModuleMessage class is the base class of Request and Event
* This class is used to represent a basic data structure which is passed
* between modules for safe inter-module communications.
diff --git a/src/modules.cpp b/src/modules.cpp
index f7904d07b..36a885ea9 100644
--- a/src/modules.cpp
+++ b/src/modules.cpp
@@ -27,9 +27,12 @@
// version is a simple class for holding a modules version number
-Version::Version(const std::string &modv, int flags, int api_ver, const std::string& rev)
-: description(modv), version(rev), Flags(flags), API(api_ver)
+template<>
+VersionBase<API_VERSION>::VersionBase(const std::string &modv, int flags, int api_ver, const std::string& rev)
+: description(modv), version(rev), Flags(flags)
{
+ if (api_ver != API_VERSION)
+ abort();
}
Request::Request(char* anydata, Module* src, Module* dst)
@@ -439,19 +442,7 @@ bool ModuleManager::Load(const char* filename)
newmod->ModuleDLLFactory = newhandle;
Version v = newmod->GetVersion();
- if (v.API != API_VERSION)
- {
- DetachAll(newmod);
- delete newmod;
- delete newhandle;
- LastModuleError = "Unable to load " + filename_str + ": Incorrect module API version: " + ConvToStr(v.API) + " (our version: " + ConvToStr(API_VERSION) + ")";
- ServerInstance->Logs->Log("MODULE", DEFAULT, LastModuleError);
- return false;
- }
- else
- {
- ServerInstance->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]"));
- }
+ ServerInstance->Logs->Log("MODULE", DEFAULT,"New module introduced: %s (Module version %s)%s", filename, v.version.c_str(), (!(v.Flags & VF_VENDOR) ? " [3rd Party]" : " [Vendor]"));
Modules[filename_str] = newmod;
}
@@ -463,7 +454,9 @@ bool ModuleManager::Load(const char* filename)
return false;
}
}
- /** XXX: Is there anything we can do about this mess? -- Brain */
+ /** XXX: Is there anything we can do about this mess? -- Brain
+ * Yeah, don't use exceptions without RAII. -- Daniel
+ */
catch (LoadModuleException& modexcept)
{
DetachAll(newmod);