minor delayed clean-ups
[sip-router] / sr_module.c
1 /* $Id$
2  */
3
4 #include "sr_module.h"
5 #include "dprint.h"
6 #include "error.h"
7
8 #include <dlfcn.h>
9 #include <strings.h>
10 #include <stdlib.h>
11 #include <string.h>
12
13
14 struct sr_module* modules=0;
15
16 #ifdef STATIC_EXEC
17         extern struct module_exports* exec_exports();
18 #endif
19 #ifdef STATIC_TM
20         extern struct module_exports* tm_exports();
21 #endif
22
23 #ifdef STATIC_MAXFWD
24         extern struct module_exports* maxfwd_exports();
25 #endif
26
27 #ifdef STATIC_AUTH
28         extern struct module_exports* auth_exports();
29 #endif
30
31 #ifdef STATIC_RR
32         extern struct module_exports* rr_exports();
33 #endif
34
35 #ifdef STATIC_USRLOC
36         extern struct module_exports* usrloc_exports();
37 #endif
38
39
40 /* initializes statically built (compiled in) modules*/
41 int register_builtin_modules()
42 {
43         int ret;
44
45         ret=0;
46 #ifdef STATIC_TM
47         ret=register_module(tm_exports,"built-in", 0); 
48         if (ret<0) return ret;
49 #endif
50
51 #ifdef EXEC_TM
52         ret=register_module(exec_exports,"built-in", 0); 
53         if (ret<0) return ret;
54 #endif
55
56 #ifdef STATIC_MAXFWD
57         ret=register_module(maxfwd_exports, "built-in", 0);
58         if (ret<0) return ret;
59 #endif
60
61 #ifdef STATIC_AUTH
62         ret=register_module(auth_exports, "built-in", 0); 
63         if (ret<0) return ret;
64 #endif
65         
66 #ifdef STATIC_RR
67         ret=register_module(rr_exports, "built-in", 0);
68         if (ret<0) return ret;
69 #endif
70         
71 #ifdef STATIC_USRLOC
72         ret=register_module(usrloc_exports, "built-in", 0);
73         if (ret<0) return ret;
74 #endif
75         
76         return ret;
77 }
78
79
80
81 /* registers a module,  register_f= module register  functions
82  * returns <0 on error, 0 on success */
83 int register_module(struct module_exports* e, char* path, void* handle)
84 {
85         int ret;
86         struct sr_module* mod;
87         
88         ret=-1;
89
90         /* add module to the list */
91         if ((mod=malloc(sizeof(struct sr_module)))==0){
92                 LOG(L_ERR, "load_module: memory allocation failure\n");
93                 ret=E_OUT_OF_MEM;
94                 goto error;
95         }
96         memset(mod,0, sizeof(struct sr_module));
97         mod->path=path;
98         mod->handle=handle;
99         mod->exports=e;
100         mod->next=modules;
101         modules=mod;
102         return 0;
103 error:
104         return ret;
105 }
106
107 /*
108  * per-child initialization
109  */
110 int init_child(int rank)
111 {
112         struct sr_module* t;
113
114         for(t = modules; t; t = t->next) {
115                 if (t->exports->init_child_f) {
116                         if ((t->exports->init_child_f(rank)) < 0) {
117                                 LOG(L_ERR, "init_child(): Initialization of child %d failed\n",
118                                                 rank);
119                                 return -1;
120                         }
121                 }
122         }
123         return 0;
124 }
125
126
127
128 /* returns 0 on success , <0 on error */
129 int load_module(char* path)
130 {
131         void* handle;
132         char* error;
133         struct module_exports* exp;
134         struct sr_module* t;
135         
136         handle=dlopen(path, RTLD_NOW | RTLD_GLOBAL); /* resolve all symbols now */
137         if (handle==0){
138                 LOG(L_ERR, "ERROR: load_module: could not open module <%s>: %s\n",
139                                         path, dlerror() );
140                 goto error;
141         }
142         
143         for(t=modules;t; t=t->next){
144                 if (t->handle==handle){
145                         LOG(L_WARN, "WARNING: load_module: attempting to load the same"
146                                                 " module twice (%s)\n", path);
147                         goto skip;
148                 }
149         }
150         /* launch register */
151         exp = (struct module_exports*)dlsym(handle, "exports");
152         if ( (error =(char*)dlerror())!=0 ){
153                 LOG(L_ERR, "ERROR: load_module: %s\n", error);
154                 goto error1;
155         }
156         if (register_module(exp, path, handle)<0) goto error1;
157         return 0;
158
159 error1:
160         dlclose(handle);
161 error:
162 skip:
163         return -1;
164 }
165
166
167
168 /* searches the module list and returns a pointer to the "name" function or
169  * 0 if not found */
170 cmd_function find_export(char* name, int param_no)
171 {
172         struct sr_module* t;
173         int r;
174
175         for(t=modules;t;t=t->next){
176                 for(r=0;r<t->exports->cmd_no;r++){
177                         if((strcmp(name, t->exports->cmd_names[r])==0)&&
178                                 (t->exports->param_no[r]==param_no) ){
179                                 DBG("find_export: found <%s> in module %s [%s]\n",
180                                                 name, t->exports->name, t->path);
181                                 return t->exports->cmd_pointers[r];
182                         }
183                 }
184         }
185         DBG("find_export: <%s> not found \n", name);
186         return 0;
187 }
188
189
190 void* find_param_export(char* mod, char* name, modparam_t type)
191 {
192         struct sr_module* t;
193         int r;
194
195         for(t = modules; t; t = t->next) {
196                 if (strcmp(mod, t->exports->name) == 0) {
197                         for(r = 0; r < t->exports->par_no; r++) {
198                                 if ((strcmp(name, t->exports->param_names[r]) == 0) &&
199                                     (t->exports->param_types[r] == type)) {
200                                         DBG("find_param_export: found <%s> in module %s [%s]\n",
201                                             name, t->exports->name, t->path);
202                                         return t->exports->param_pointers[r];
203                                 }
204                         }
205                 }
206         }
207         DBG("find_param_export: parameter <%s> or module <%s> not found\n", name, mod);
208         return 0;
209 }
210
211
212
213 /* finds a module, given a pointer to a module function *
214  * returns pointer to module, & if i i!=0, *i=the function index */
215 struct sr_module* find_module(void* f, int *i)
216 {
217         struct sr_module* t;
218         int r;
219         for (t=modules;t;t=t->next){
220                 for(r=0;r<t->exports->cmd_no;r++) 
221                         if (f==(void*)t->exports->cmd_pointers[r]) {
222                                 if (i) *i=r;
223                                 return t;
224                         }
225         }
226         return 0;
227 }
228
229
230
231 void destroy_modules()
232 {
233         struct sr_module* t;
234
235         for(t=modules;t;t=t->next)
236                 if  ((t->exports)&&(t->exports->destroy_f)) t->exports->destroy_f();
237 }
238
239
240 /*
241  * Initialize all loaded modules, the initialization
242  * is done *AFTER* the configuration file is parsed
243  */
244 int init_modules(void)
245 {
246         struct sr_module* t;
247         
248         for(t = modules; t; t = t->next) {
249                 if ((t->exports) && (t->exports->init_f))
250                         if (t->exports->init_f() != 0) {
251                                 LOG(L_ERR, "init_modules(): Error while initializing module %s\n", t->exports->name);
252                                 return -1;
253                         }
254         }
255         return 0;
256 }