Avoid one condition variable in msg-thread impl
[yazproxy-moved-to-github.git] / src / modules.cpp
1 /* $Id: modules.cpp,v 1.4 2005-06-25 15:58:33 adam Exp $
2    Copyright (c) 1998-2005, Index Data.
3
4 This file is part of the yaz-proxy.
5
6 YAZ proxy is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2, or (at your option) any later
9 version.
10
11 YAZ proxy is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with YAZ proxy; see the file LICENSE.  If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA.
20  */
21
22 #include <string.h>
23 #if HAVE_DLFCN_H
24 #include <dlfcn.h>
25 #endif
26
27 #include <yaz/nmem.h>
28 #include <yaz/log.h>
29 #include <yazproxy/module.h>
30
31 class Yaz_ProxyModule {
32     friend class Proxy_Msg;
33 private:
34     void *m_dl_handle;                /* dlopen/close handle */
35     Yaz_ProxyModule_entry *m_entry;
36     Yaz_ProxyModule *m_next; 
37     void *m_user_handle;              /* user handle */
38 public:
39     Yaz_ProxyModule(void *dl_handle, Yaz_ProxyModule_entry *ent,
40                     Yaz_ProxyModule *next);
41     ~Yaz_ProxyModule();
42     
43     Yaz_ProxyModule *get_next() { return m_next; };
44     int is_module(const char *name);
45     int authenticate(const char *target_name, void *element_ptr,
46                      const char *user, const char *group, const char *password,
47                      const char *peer_IP);
48 };
49
50 int Yaz_ProxyModule::is_module(const char *name)
51 {
52     if (!name || !strcmp(m_entry->module_name, name))
53         return 1;
54     return 0;
55 }
56
57 Yaz_ProxyModule::Yaz_ProxyModule(void *dl_handle, Yaz_ProxyModule_entry *ent,
58                                  Yaz_ProxyModule *next)
59 {
60     m_dl_handle = dl_handle;
61     m_entry = ent;
62     m_next = next;
63     m_user_handle = 0;
64     if (m_entry->int_version == 0)
65     {
66         struct Yaz_ProxyModule_int0 *int0 =
67             reinterpret_cast<Yaz_ProxyModule_int0 *>(m_entry->fl);
68         if (int0->init)
69             m_user_handle = (*int0->init)();
70     }
71 }
72
73 Yaz_ProxyModule::~Yaz_ProxyModule()
74 {
75     if (m_entry->int_version == 0)
76     {
77         struct Yaz_ProxyModule_int0 *int0 =
78             reinterpret_cast<Yaz_ProxyModule_int0 *>(m_entry->fl);
79         if (int0->destroy)
80             (*int0->destroy)(m_user_handle);
81     }
82 #if HAVE_DLFCN_H
83     dlclose(m_dl_handle);
84 #endif
85 }
86
87 int Yaz_ProxyModule::authenticate(const char *name,
88                                   void *element_ptr,
89                                   const char *user, const char *group,
90                                   const char *password,
91                                   const char *peer_IP)
92 {
93     if (m_entry->int_version == 0)
94     {
95         struct Yaz_ProxyModule_int0 *int0 =
96             reinterpret_cast<Yaz_ProxyModule_int0 *>(m_entry->fl);
97         
98         if (!int0->authenticate)
99             return YAZPROXY_RET_NOT_ME;
100         return (*int0->authenticate)(m_user_handle, name, element_ptr,
101                                      user, group, password, peer_IP);
102     }
103     return YAZPROXY_RET_NOT_ME;
104 }
105
106 Yaz_ProxyModules::Yaz_ProxyModules()
107 {
108     m_list = 0;
109     m_no_open = 0;
110 }
111
112
113 Yaz_ProxyModules::~Yaz_ProxyModules()
114 {
115     unload_modules();
116 }
117
118 void Yaz_ProxyModules::unload_modules()
119 {
120     Yaz_ProxyModule *m = m_list;
121     while (m)
122     {
123         Yaz_ProxyModule *m_next = m->get_next();
124         delete m;
125         m_no_open--;
126         m = m_next;
127     }
128     m_list = 0;
129 }
130
131
132 int Yaz_ProxyModules::authenticate(const char *module_name,
133                                    const char *target_name, void *element_ptr,
134                                    const char *user,
135                                    const char *group,
136                                    const char *password,
137                                    const char *peer_IP)
138 {
139     int ret = YAZPROXY_RET_NOT_ME;
140     Yaz_ProxyModule *m = m_list;
141     for (; m; m = m->get_next())
142     {
143         if (m->is_module(module_name))
144         {
145             ret = m->authenticate(target_name, element_ptr,
146                                   user, group, password,
147                                   peer_IP);
148             if (ret != YAZPROXY_RET_NOT_ME)
149                 break;
150         }
151     }
152     return ret;
153 }
154
155 int Yaz_ProxyModules::add_module(const char *fname)
156 {
157 #if HAVE_DLFCN_H
158     void *dl_handle = dlopen(fname, RTLD_NOW|RTLD_GLOBAL);
159     if (dl_handle)
160     {
161         Yaz_ProxyModule_entry *fl_ptr = 0;
162         fl_ptr = reinterpret_cast<Yaz_ProxyModule_entry *> 
163             (dlsym(dl_handle, "yazproxy_module"));
164         if (fl_ptr)
165         {
166             Yaz_ProxyModule *m = new Yaz_ProxyModule(dl_handle,
167                                                      fl_ptr,
168                                                      m_list);
169             m_list = m;
170
171             m_no_open++;
172             yaz_log(YLOG_LOG, "Loaded module no_open=%d", m_no_open);
173             return 0;
174         }
175         else
176         {
177             return -1;
178             dlclose(dl_handle);
179         }
180     }
181     else
182         return -1;
183 #else
184     return -1;
185 #endif
186 }
187
188 /*
189  * Local variables:
190  * c-basic-offset: 4
191  * indent-tabs-mode: nil
192  * End:
193  * vim: shiftwidth=4 tabstop=8 expandtab
194  */
195