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