]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Added generic support for loadable Squid modules or plugins.
authorAlex Rousskov <rousskov@measurement-factory.com>
Mon, 31 Mar 2008 04:31:48 +0000 (22:31 -0600)
committerAlex Rousskov <rousskov@measurement-factory.com>
Mon, 31 Mar 2008 04:31:48 +0000 (22:31 -0600)
The "loadable_modules" squid.conf option specifies what shared libraries to
load dynamically. The support is based on libtool's ltdl library, which has
been integrated with Squid prior to this commit, along with the
--enable-loadable-modules ./configure option.

Loaded modules are currently never unloaded, but that may change.

Loadable modules are needed for eCAP, but loadable_modules code deals with
generic module manipulation, independent from eCAP support.

TODO: support cachemgr reporting and reconfiguration.

src/LoadableModule.cc [new file with mode: 0644]
src/LoadableModule.h [new file with mode: 0644]
src/LoadableModules.cc [new file with mode: 0644]
src/LoadableModules.h [new file with mode: 0644]
src/Makefile.am
src/cf.data.pre
src/main.cc
src/structs.h

diff --git a/src/LoadableModule.cc b/src/LoadableModule.cc
new file mode 100644 (file)
index 0000000..e35e170
--- /dev/null
@@ -0,0 +1,86 @@
+#include "squid.h"
+
+/* The original code has this constant ./configure-able.
+ * The "#else" branches use raw dlopen interface and have not been tested.
+ * We can remove that code if we are going to rely on libtool's ltdl in 
+ * all environments. */
+#define XSTD_USE_LIBLTDL 1
+
+#if XSTD_USE_LIBLTDL
+       #include "libLtdl/ltdl.h" /* generated file */
+#else
+       #include <dlfcn.h>
+#endif
+
+#include "TextException.h"
+#include "LoadableModule.h"
+
+// Note: We must use preprocessor instead of C ifs because if dlopen()
+// is seen by the static linker, the linker will complain.
+
+LoadableModule::LoadableModule(const String &aName): theName(aName), theHandle(0) {
+#      if XSTD_USE_LIBLTDL
+               // Initialise preloaded symbol lookup table.
+               LTDL_SET_PRELOADED_SYMBOLS();
+               if (lt_dlinit() != 0)
+                       throw TexcHere("internal error: cannot initialize libtool module loader");
+#      endif
+}
+
+LoadableModule::~LoadableModule() {
+       if (loaded())
+               unload();
+#      if XSTD_USE_LIBLTDL
+               assert(lt_dlexit() == 0); // XXX: replace with a warning
+#      endif
+}
+
+bool LoadableModule::loaded() const {
+       return theHandle != 0;
+}
+
+void LoadableModule::load(int mode) {
+       if (loaded())
+               throw TexcHere("internal error: reusing LoadableModule object");
+
+       theHandle = openModule(mode);
+
+       if (!loaded())
+               throw TexcHere(errorMsg());
+}
+
+void LoadableModule::unload() {
+       if (!loaded())
+               throw TexcHere("internal error: unloading not loaded module");
+
+       if (!closeModule())
+               throw TexcHere(errorMsg());
+
+       theHandle = 0;
+}
+
+void *LoadableModule::openModule(int mode) {
+#      if XSTD_USE_LIBLTDL
+               return lt_dlopen(theName.buf());
+#      else
+               return dlopen(theName.c_str(),
+                       mode == lmNow ? RTLD_NOW : RTLD_LAZY);
+#      endif
+}
+
+bool LoadableModule::closeModule() {
+#      if XSTD_USE_LIBLTDL
+               // we cast to avoid including ltdl.h in LoadableModule.h
+               return lt_dlclose(static_cast<lt_dlhandle>(theHandle)) == 0;
+#      else
+               return dlclose(theHandle) == 0;
+#      endif
+}
+
+const char *LoadableModule::errorMsg() {
+#      if XSTD_USE_LIBLTDL
+               return lt_dlerror();
+#      else
+               return dlerror();
+#      endif
+}
diff --git a/src/LoadableModule.h b/src/LoadableModule.h
new file mode 100644 (file)
index 0000000..5d9f17f
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef SQUID_LOADABLE_MODULE_H
+#define SQUID_LOADABLE_MODULE_H
+
+#include "SquidString.h"
+
+// wrapper for dlopen(3), libltdl, and friends
+class LoadableModule {
+public:
+    enum LoadMode { lmNow, lmLazy };
+
+public:
+    LoadableModule(const String &aName);
+    ~LoadableModule();           // unloads if loaded
+
+    bool loaded() const;
+    const String &name() const { return theName; }
+    const String &error() const { return theError; }
+
+    void load(int mode = lmNow); // throws Texc
+    void unload(); // throws Texc
+
+protected:
+    String theName;
+    String theError;
+    void *theHandle;
+
+private:
+    void *openModule(int mode);
+    bool closeModule();
+    const char *errorMsg();
+};
+
+#endif
diff --git a/src/LoadableModules.cc b/src/LoadableModules.cc
new file mode 100644 (file)
index 0000000..c9b2725
--- /dev/null
@@ -0,0 +1,25 @@
+#include "squid.h"
+#include "wordlist.h"
+#include "LoadableModule.h"
+#include "LoadableModules.h"
+
+static void
+LoadModule(const char *fname)
+{
+    debugs(1, 1, "loading Squid module from '" << fname << "'");
+
+    LoadableModule *m = new LoadableModule(fname);
+    m->load();
+    debugs(1, 2, "loaded Squid module from '" << fname << "'");
+
+    //TODO: TheModules.push_back(m);
+}
+
+void
+LoadableModulesConfigure(const wordlist *names)
+{
+    int count = 0;
+    for (const wordlist *i = names; i; i = i->next, ++count)
+        LoadModule(i->key);
+    debugs(1, 1, "loaded " << count << " Squid modules");
+}
diff --git a/src/LoadableModules.h b/src/LoadableModules.h
new file mode 100644 (file)
index 0000000..92d622e
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef SQUID_LOADABLE_MODULES_H
+#define SQUID_LOADABLE_MODULES_H
+
+// TODO: add reporting for cachemgr
+// TODO: add reconfiguration support
+
+class wordlist;
+extern void LoadableModulesConfigure(const wordlist *names);
+
+#endif /* SQUID_LOADABLE_MODULES_H */
index ae3e772816e5d01171671a5c4da3fb699ded7e18..c92cbc3a1b47f3d8418f6500258eb3b5b7699377 100644 (file)
@@ -25,6 +25,12 @@ else
 SNMP_SOURCE = 
 endif
 
+LOADABLE_MODULES_SOURCES = \
+       LoadableModule.h \
+       LoadableModule.cc \
+       LoadableModules.h \
+       LoadableModules.cc
+
 TESTS=$(check_PROGRAMS)
 check_PROGRAMS=
 
@@ -221,6 +227,7 @@ noinst_LIBRARIES = @DISK_LIBS@
 noinst_LTLIBRARIES = libsquid.la libauth.la
 
 INCLUDES        = -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_srcdir)/include -I$(top_srcdir)/lib/libTrie/include
+INCLUDES        += -I$(top_builddir)/lib
 INCLUDES       += @SQUID_CPPUNIT_INC@
 
 EXTRA_PROGRAMS = \
@@ -315,6 +322,7 @@ EXTRA_squid_SOURCES = \
        $(UNLINKDSOURCE) \
        $(SSL_ALL_SOURCE) \
        $(WIN32_ALL_SOURCE) \
+       $(LOADABLE_MODULES_SOURCES) \
        DiskIO/DiskThreads/aiops.cc \
        DiskIO/DiskThreads/aiops_win32.cc
 
@@ -715,6 +723,7 @@ squid_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a \
        ${ADAPTATION_LIBS}
 
 if USE_LOADABLE_MODULES
+squid_SOURCES += $(LOADABLE_MODULES_SOURCES)
 squid_LDADD += \
        @LIBLTDL@
 squid_LDFLAGS = \
index e53a553937039571f17e2de6488d6da6f4d7e2cc..86d01b6b0fd32dca20e4442544ce4e8a049f7480 100644 (file)
@@ -5042,6 +5042,23 @@ Example:
 icap_access class_1 allow all
 DOC_END
 
+COMMENT_START
+ eCAP OPTIONS
+ -----------------------------------------------------------------------------
+COMMENT_END
+
+NAME: loadable_modules
+TYPE: wordlist
+IFDEF: USE_LOADABLE_MODULES
+LOC: Config.loadable_module_names
+DEFAULT: none
+DOC_START
+       Instructs Squid to load the specified dynamic module(s) or activate
+       preloaded module(s).
+Example:
+loadable_modules @DEFAULT_PREFIX@/lib/MinimalAdapter.so
+DOC_END
+
 COMMENT_START
  DNS OPTIONS
  -----------------------------------------------------------------------------
index 796bb92a5b43763e3b136dec418a469d57e353fc..192bc7fe61c5578faa250fe26a896ebc21c443a2 100644 (file)
 #include "MemPool.h"
 #include "ICMPSquid.h"
 
+#if USE_LOADABLE_MODULES
+#include "LoadableModules.h"
+#endif
+
 #if ICAP_CLIENT
 #include "ICAP/ICAPConfig.h"
 #endif
@@ -1085,6 +1089,10 @@ mainInitialize(void)
 
     memCheckInit();
 
+#if USE_LOADABLE_MODULES
+    LoadableModulesConfigure(Config.loadable_module_names);
+#endif
+
 #if ICAP_CLIENT
     TheICAPConfig.finalize(); // must be after we load modules
 #endif
index b65065a9a376beb915af388f21063a4b82c05cf3..ab6eff5d855a15b3b8a4eebc147975950989d838 100644 (file)
@@ -629,6 +629,10 @@ struct SquidConfig
 #endif
 
     char *accept_filter;
+
+#if USE_LOADABLE_MODULES
+    wordlist *loadable_module_names;
+#endif
 };
 
 SQUIDCEXTERN SquidConfig Config;