1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
5 * Copyright (C) 2001-2010, Eduardo Silva P.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Library General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 #include <sys/types.h>
35 #include "scheduler.h"
43 void *mk_plugin_load(char *path
)
47 handle
= dlopen(path
, RTLD_LAZY
);
49 fprintf(stderr
, "Error during dlopen(): %s\n", dlerror());
55 void *mk_plugin_load_symbol(void *handler
, const char *symbol
)
61 s
= dlsym(handler
, symbol
);
62 if ((err
= dlerror()) != NULL
) {
69 void mk_plugin_register_add_to_stage(struct plugin
**st
, struct plugin
*p
)
87 void mk_plugin_register_stages(struct plugin
*p
)
89 struct plugin_list
*new, *list
;
91 /* Main plugin list */
92 new = mk_mem_malloc(sizeof(struct plugin_list
));
107 /* Assign plugin to stages */
108 if (*p
->stages
& MK_PLUGIN_STAGE_00
) {
109 mk_plugin_register_add_to_stage(&config
->plugins
->stage_00
, p
);
112 if (*p
->stages
& MK_PLUGIN_STAGE_10
) {
113 mk_plugin_register_add_to_stage(&config
->plugins
->stage_10
, p
);
116 if (*p
->stages
& MK_PLUGIN_STAGE_20
) {
117 mk_plugin_register_add_to_stage(&config
->plugins
->stage_20
, p
);
120 if (*p
->stages
& MK_PLUGIN_STAGE_30
) {
121 mk_plugin_register_add_to_stage(&config
->plugins
->stage_30
, p
);
124 if (*p
->stages
& MK_PLUGIN_STAGE_40
) {
125 mk_plugin_register_add_to_stage(&config
->plugins
->stage_40
, p
);
128 if (*p
->stages
& MK_PLUGIN_STAGE_50
) {
129 mk_plugin_register_add_to_stage(&config
->plugins
->stage_50
, p
);
132 if (*p
->stages
& MK_PLUGIN_STAGE_60
) {
133 mk_plugin_register_add_to_stage(&config
->plugins
->stage_60
, p
);
137 void *mk_plugin_register(void *handler
, char *path
)
141 p
= mk_mem_malloc_z(sizeof(struct plugin
));
142 p
->shortname
= mk_plugin_load_symbol(handler
, "_shortname");
143 p
->name
= mk_plugin_load_symbol(handler
, "_name");
144 p
->version
= mk_plugin_load_symbol(handler
, "_version");
145 p
->path
= mk_string_dup(path
);
146 p
->handler
= handler
;
148 (mk_plugin_stage_t
*) mk_plugin_load_symbol(handler
, "_stages");
150 /* Plugin external function */
151 p
->call_init
= (int (*)()) mk_plugin_load_symbol(handler
,
154 p
->call_worker_init
= (int (*)()) mk_plugin_load_symbol(handler
,
155 "_mk_plugin_worker_init");
157 p
->call_stage_10
= (int (*)())
158 mk_plugin_load_symbol(handler
, "_mk_plugin_stage_00");
160 p
->call_stage_10
= (int (*)())
161 mk_plugin_load_symbol(handler
, "_mk_plugin_stage_10");
163 p
->call_stage_20
= (int (*)())
164 mk_plugin_load_symbol(handler
, "_mk_plugin_stage_20");
166 p
->call_stage_30
= (int (*)())
167 mk_plugin_load_symbol(handler
, "_mk_plugin_stage_30");
169 p
->call_stage_40
= (int (*)())
170 mk_plugin_load_symbol(handler
, "_mk_plugin_stage_40");
172 p
->call_stage_40_loop
= (int (*)())
173 mk_plugin_load_symbol(handler
, "_mk_plugin_stage_40_loop");
175 p
->thread_key
= (pthread_key_t
) mk_plugin_load_symbol(handler
, "_mk_plugin_data");
179 if (!p
->name
|| !p
->version
|| !p
->stages
) {
184 mk_plugin_register_stages(p
);
188 void mk_plugin_init()
193 struct plugin_api
*api
;
194 struct plugin_list
*plist
;
195 struct mk_config
*cnf
;
197 api
= mk_mem_malloc_z(sizeof(struct plugin_api
));
199 /* Setup and connections list */
200 api
->config
= config
;
201 api
->sched_list
= &sched_list
;
203 /* API plugins funcions */
204 api
->mem_alloc
= (void *) mk_mem_malloc
;
205 api
->mem_alloc_z
= (void *) mk_mem_malloc_z
;
206 api
->mem_free
= (void *) mk_mem_free
;
207 api
->str_build
= (void *) m_build_buffer
;
208 api
->str_dup
= (void *) mk_string_dup
;
209 api
->str_search
= (void *) mk_string_search
;
210 api
->str_search_n
= (void *) mk_string_search_n
;
211 api
->str_copy_substr
= (void *) mk_string_copy_substr
;
212 api
->str_split_line
= (void *) mk_string_split_line
;
213 api
->file_to_buffer
= (void *) mk_file_to_buffer
;
214 api
->file_get_info
= (void *) mk_file_get_info
;
215 api
->header_send
= (void *) mk_header_send
;
216 api
->iov_create
= (void *) mk_iov_create
;
217 api
->iov_free
= (void *) mk_iov_free
;
218 api
->iov_add_entry
= (void *) mk_iov_add_entry
;
219 api
->iov_set_entry
= (void *) mk_iov_set_entry
;
220 api
->iov_send
= (void *) mk_iov_send
;
221 api
->iov_print
= (void *) mk_iov_print
;
222 api
->pointer_set
= (void *) mk_pointer_set
;
223 api
->pointer_print
= (void *) mk_pointer_print
;
224 api
->plugin_load_symbol
= (void *) mk_plugin_load_symbol
;
225 api
->socket_cork_flag
= (void *) mk_socket_set_cork_flag
;
226 api
->socket_connect
= (void *) mk_socket_connect
;
227 api
->socket_set_tcp_nodelay
= (void *) mk_socket_set_tcp_nodelay
;
228 api
->socket_create
= (void *) mk_socket_create
;
229 api
->config_create
= (void *) mk_config_create
;
230 api
->config_free
= (void *) mk_config_free
;
231 api
->config_getval
= (void *) mk_config_getval
;
232 api
->sched_get_connection
= (void *) mk_sched_get_connection
;
234 path
= mk_mem_malloc_z(1024);
235 snprintf(path
, 1024, "%s/%s", config
->serverconf
, MK_PLUGIN_LOAD
);
237 /* Read configuration file */
238 cnf
= mk_config_create(path
);
241 if (strcasecmp(cnf
->key
, "LoadPlugin") == 0) {
242 handle
= mk_plugin_load(cnf
->val
);
243 p
= mk_plugin_register(handle
, cnf
->val
);
245 fprintf(stderr
, "Plugin error: %s", cnf
->val
);
249 char *plugin_confdir
= 0;
252 m_build_buffer(&plugin_confdir
,
255 config
->serverconf
, p
->shortname
);
257 p
->call_init(&api
, plugin_confdir
);
263 api
->plugins
= plg_list
;
268 int mk_plugin_stage_run(mk_plugin_stage_t stage
,
270 struct sched_connection
*conx
,
271 struct client_request
*cr
, struct request
*sr
)
274 short int assigned
= FALSE
;
278 if (stage
& MK_PLUGIN_STAGE_10
) {
279 p
= config
->plugins
->stage_10
;
285 if (stage
& MK_PLUGIN_STAGE_20
) {
286 p
= config
->plugins
->stage_20
;
288 ret
= p
->call_stage_20(socket
, conx
, cr
);
290 case MK_PLUGIN_RET_CLOSE_CONX
:
291 return MK_PLUGIN_RET_CLOSE_CONX
;
298 if (stage
& MK_PLUGIN_STAGE_30
) {
299 p
= config
->plugins
->stage_30
;
301 ret
= p
->call_stage_30(cr
, sr
);
303 case MK_PLUGIN_RET_CLOSE_CONX
:
304 return MK_PLUGIN_RET_CLOSE_CONX
;
312 if (stage
& MK_PLUGIN_STAGE_40
) {
313 /* Request has been assigned to a Plugin Loop */
319 ret
= p
->call_stage_40_loop(cr
, sr
);
321 if (ret
== MK_PLUGIN_RET_END
) {
322 mk_plugin_request_handler_del(sr
, p
);
329 /* The request just arrived and is required to check who can
331 if (!sr
->handled_by
){
332 p
= config
->plugins
->stage_40
;
335 ret
= p
->call_stage_40(cr
, sr
);
338 case MK_PLUGIN_RET_NOT_ME
:
340 case MK_PLUGIN_RET_END
:
342 case MK_PLUGIN_RET_CONTINUE
:
343 /* Register plugin for next loops */
344 mk_plugin_request_handler_add(sr
, p
);
345 p
->call_stage_40_loop(cr
, sr
);
360 void mk_plugin_request_handler_add(struct request
*sr
, struct plugin
*p
)
362 struct handler
*new, *aux
;
364 new = mk_mem_malloc(sizeof(struct handler
));
368 if (!sr
->handled_by
) {
369 sr
->handled_by
= new;
373 aux
= sr
->handled_by
;
382 printf("\nMK_REQUEST_REGISTER_HANDLER: NEVER ASSIGNED");
386 void mk_plugin_request_handler_del(struct request
*sr
, struct plugin
*p
)
388 struct handler
*prev
= 0, *aux
;
390 if (!sr
->handled_by
) {
394 while (sr
->handled_by
) {
395 aux
= sr
->handled_by
;
414 /* This function is called by every created worker
415 * for plugins which need to set some data under a thread
418 void mk_plugin_worker_startup()
420 struct plugin_list
*plg
;
425 if (plg
->p
->call_worker_init
) {
426 plg
->p
->call_worker_init();