Security Plugin: set http status for URL rule match
[MonkeyD.git] / src / plugin.c
blob357080da3f7c61f7a4423d4afe1fd89ef4c74cff
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 /* Monkey HTTP Daemon
4 * ------------------
5 * Copyright (C) 2001-2010, Eduardo Silva P. <edsiper@gmail.com>
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.
22 #include <string.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <unistd.h>
28 #include <dlfcn.h>
29 #include <err.h>
31 #include "config.h"
32 #include "connection.h"
33 #include "plugin.h"
34 #include "monkey.h"
35 #include "request.h"
36 #include "scheduler.h"
37 #include "utils.h"
38 #include "str.h"
39 #include "file.h"
40 #include "header.h"
41 #include "http.h"
42 #include "memory.h"
43 #include "iov.h"
44 #include "epoll.h"
45 #include "worker.h"
46 #include "clock.h"
48 void *mk_plugin_load(char *path)
50 void *handle;
52 handle = dlopen(path, RTLD_LAZY);
53 if (!handle) {
54 fprintf(stderr, "Error during dlopen(): %s\n", dlerror());
55 exit(1);
57 return handle;
60 void *mk_plugin_load_symbol(void *handler, const char *symbol)
62 char *err;
63 void *s;
65 dlerror();
66 s = dlsym(handler, symbol);
67 if ((err = dlerror()) != NULL) {
68 return NULL;
71 return s;
74 void mk_plugin_register_stagemap_add(struct plugin_stagem **stm, struct plugin *p)
76 struct plugin_stagem *list, *new;
78 new = mk_mem_malloc_z(sizeof(struct plugin_stagem));
79 new->p = p;
80 new->next = NULL;
82 if (!*stm) {
83 *stm = new;
84 return;
87 list = *stm;
89 while (list->next) {
90 list = list->next;
93 list->next = new;
96 void mk_plugin_register_stagemap(struct plugin *p)
98 /* Plugin to stages */
99 if (*p->hooks & MK_PLUGIN_STAGE_10) {
100 mk_plugin_register_stagemap_add(&plg_stagemap->stage_10, p);
103 if (*p->hooks & MK_PLUGIN_STAGE_20) {
104 mk_plugin_register_stagemap_add(&plg_stagemap->stage_20, p);
107 if (*p->hooks & MK_PLUGIN_STAGE_30) {
108 mk_plugin_register_stagemap_add(&plg_stagemap->stage_30, p);
111 if (*p->hooks & MK_PLUGIN_STAGE_40) {
112 mk_plugin_register_stagemap_add(&plg_stagemap->stage_40, p);
115 if (*p->hooks & MK_PLUGIN_STAGE_50) {
116 mk_plugin_register_stagemap_add(&plg_stagemap->stage_50, p);
120 struct plugin *mk_plugin_alloc(void *handler, char *path)
122 struct plugin *p;
124 p = mk_mem_malloc_z(sizeof(struct plugin));
125 p->shortname = mk_plugin_load_symbol(handler, "_shortname");
126 p->name = mk_plugin_load_symbol(handler, "_name");
127 p->version = mk_plugin_load_symbol(handler, "_version");
128 p->path = mk_string_dup(path);
129 p->handler = handler;
130 p->hooks = (mk_plugin_hook_t *) mk_plugin_load_symbol(handler, "_hooks");
132 /* Mandatory functions */
133 p->init = (int (*)()) mk_plugin_load_symbol(handler, "_mkp_init");
134 p->exit = (int (*)()) mk_plugin_load_symbol(handler, "_mkp_exit");
136 /* Core hooks */
137 p->core.prctx = (int (*)()) mk_plugin_load_symbol(handler,
138 "_mkp_core_prctx");
139 p->core.thctx = (int (*)()) mk_plugin_load_symbol(handler,
140 "_mkp_core_thctx");
142 /* Stage hooks */
143 p->stage.s10 = (int (*)())
144 mk_plugin_load_symbol(handler, "_mkp_stage_10");
146 p->stage.s20 = (int (*)())
147 mk_plugin_load_symbol(handler, "_mkp_stage_20");
149 p->stage.s30 = (int (*)())
150 mk_plugin_load_symbol(handler, "_mkp_stage_30");
152 p->stage.s40 = (int (*)())
153 mk_plugin_load_symbol(handler, "_mkp_stage_40");
155 p->stage.s50 = (int (*)())
156 mk_plugin_load_symbol(handler, "_mkp_stage_50");
158 /* Network I/O hooks */
159 p->net_io.accept = (int (*)())
160 mk_plugin_load_symbol(handler, "_mkp_network_io_accept");
162 p->net_io.read = (int (*)())
163 mk_plugin_load_symbol(handler, "_mkp_network_io_read");
165 p->net_io.write = (int (*)())
166 mk_plugin_load_symbol(handler, "_mkp_network_io_write");
168 p->net_io.writev = (int (*)())
169 mk_plugin_load_symbol(handler, "_mkp_network_io_writev");
171 p->net_io.close = (int (*)())
172 mk_plugin_load_symbol(handler, "_mkp_network_io_close");
174 p->net_io.connect = (int (*)())
175 mk_plugin_load_symbol(handler, "_mkp_network_io_connect");
177 p->net_io.send_file = (int (*)())
178 mk_plugin_load_symbol(handler, "_mkp_network_io_send_file");
180 p->net_io.create_socket = (int (*)())
181 mk_plugin_load_symbol(handler, "_mkp_network_io_create_socket");
183 p->net_io.bind = (int (*)())
184 mk_plugin_load_symbol(handler, "_mkp_network_io_bind");
186 p->net_io.server = (int (*)())
187 mk_plugin_load_symbol(handler, "_mkp_network_io_server");
190 /* Network IP hooks */
191 p->net_ip.addr = (int (*)())
192 mk_plugin_load_symbol(handler, "_mkp_network_ip_addr");
194 p->net_ip.maxlen = (int (*)())
195 mk_plugin_load_symbol(handler, "_mkp_network_ip_maxlen");
197 /* Thread key */
198 p->thread_key = (pthread_key_t *) mk_plugin_load_symbol(handler,
199 "_mkp_data");
201 /* Event handlers hooks */
202 p->event_read = (int (*)())
203 mk_plugin_load_symbol(handler, "_mkp_event_read");
205 p->event_write = (int (*)())
206 mk_plugin_load_symbol(handler, "_mkp_event_write");
208 p->event_error = (int (*)())
209 mk_plugin_load_symbol(handler, "_mkp_event_error");
211 p->event_close = (int (*)())
212 mk_plugin_load_symbol(handler, "_mkp_event_close");
214 p->event_timeout = (int (*)())
215 mk_plugin_load_symbol(handler, "_mkp_event_timeout");
217 /* Next ! */
218 p->next = NULL;
220 return p;
223 /* Load the plugins and set the library symbols to the
224 * local struct plugin *p node
226 struct plugin *mk_plugin_register(struct plugin *p)
228 if (!p->name || !p->version || !p->hooks) {
229 #ifdef TRACE
230 MK_TRACE("Plugin must define name, version and hooks. Check: %s", p->path);
231 #endif
232 mk_plugin_free(p);
233 return NULL;
236 if (!p->init || !p->exit) {
237 #ifdef TRACE
238 MK_TRACE("Plugin must define hooks 'init' and 'exit'");
239 #endif
240 mk_plugin_free(p);
241 return NULL;
244 /* NETWORK_IO Plugin */
245 if (*p->hooks & MK_PLUGIN_NETWORK_IO) {
246 /* Validate mandatory calls */
247 if (!p->net_io.accept || !p->net_io.read || !p->net_io.write ||
248 !p->net_io.writev || !p->net_io.close || !p->net_io.connect ||
249 !p->net_io.send_file || !p->net_io.create_socket || !p->net_io.bind ||
250 !p->net_io.server ) {
251 #ifdef TRACE
252 MK_TRACE("Networking IO plugin incomplete: %s", p->path);
253 MK_TRACE("Mapped Functions\naccept : %p\nread : %p\n\
254 write : %p\nwritev: %p\nclose : %p\nconnect : %p\nsendfile : %p\n\
255 create socket : %p\nbind : %p\nserver : %p",
256 p->net_io.accept,
257 p->net_io.read,
258 p->net_io.write,
259 p->net_io.writev,
260 p->net_io.close,
261 p->net_io.connect,
262 p->net_io.send_file,
263 p->net_io.create_socket,
264 p->net_io.bind,
265 p->net_io.server);
266 #endif
267 mk_plugin_free(p);
268 return NULL;
271 /* Restrict to one NETWORK_IO plugin */
272 if (!plg_netiomap) {
273 plg_netiomap = &p->net_io;
275 else {
276 fprintf(stderr,
277 "\nError: Loading more than one Network IO Plugin: %s",
278 p->path);
279 exit(1);
283 /* NETWORK_IP Plugin */
284 if (*p->hooks & MK_PLUGIN_NETWORK_IP) {
285 /* Validate mandatory calls */
286 if (!p->net_ip.addr || !p->net_ip.maxlen) {
287 #ifdef TRACE
288 MK_TRACE("Networking IP plugin incomplete: %s", p->path);
289 MK_TRACE("Mapped Functions\naddr :%p\nmaxlen :%p",
290 p->net_ip.addr,
291 p->net_ip.maxlen);
292 #endif
293 mk_plugin_free(p);
294 return NULL;
297 /* Restrict to one NETWORK_IP plugin */
298 if (!plg_netipmap) {
299 plg_netipmap = &p->net_ip;
301 else {
302 fprintf(stderr,
303 "\nError: Loading more than one Network IP Plugin: %s",
304 p->path);
305 exit(1);
309 /* Add Plugin to the end of the list */
310 if (!config->plugins) {
311 config->plugins = p;
313 else {
314 struct plugin *plg = config->plugins;
315 while(plg->next){
316 plg = plg->next;
318 plg->next = p;
321 mk_plugin_register_stagemap(p);
322 return p;
325 void mk_plugin_unregister(struct plugin *p)
327 struct plugin *node, *prev;
329 node = config->plugins;
331 if (!node) {
332 return;
335 if (node == p) {
336 config->plugins = p->next;
337 mk_plugin_free(p);
338 return;
341 prev = node;
342 while (node->next != p) {
343 prev = node;
344 node = node->next;
347 if (node) {
348 prev->next = p->next;
349 mk_plugin_free(p);
350 return;
354 void mk_plugin_free(struct plugin *p)
356 mk_mem_free(p->path);
357 mk_mem_free(p);
358 p = NULL;
361 void mk_plugin_init()
363 int ret;
364 char *path;
365 char *plugin_confdir = 0;
366 void *handle;
367 unsigned long len;
368 struct plugin *p;
369 struct plugin_api *api;
370 struct mk_config *cnf;
371 struct mk_config_section *section;
372 struct mk_config_entry *entry;
374 api = mk_mem_malloc_z(sizeof(struct plugin_api));
375 plg_stagemap = mk_mem_malloc_z(sizeof(struct plugin_stagemap));
376 plg_netiomap = NULL;
377 plg_netipmap = NULL;
379 /* Setup and connections list */
380 api->config = config;
381 api->sched_list = &sched_list;
383 /* API plugins funcions */
385 /* HTTP callbacks */
386 api->http_request_end = (void *) mk_plugin_http_request_end;
388 /* Memory callbacks */
389 api->pointer_set = (void *) mk_pointer_set;
390 api->pointer_print = (void *) mk_pointer_print;
391 api->plugin_load_symbol = (void *) mk_plugin_load_symbol;
392 api->mem_alloc = (void *) mk_mem_malloc;
393 api->mem_alloc_z = (void *) mk_mem_malloc_z;
394 api->mem_free = (void *) mk_mem_free;
396 /* String Callbacks */
397 api->str_build = (void *) mk_string_build;
398 api->str_dup = (void *) mk_string_dup;
399 api->str_search = (void *) mk_string_search;
400 api->str_search_n = (void *) mk_string_search_n;
401 api->str_copy_substr = (void *) mk_string_copy_substr;
402 api->str_itop = (void *) mk_string_itop;
403 api->str_split_line = (void *) mk_string_split_line;
405 /* File Callbacks */
406 api->file_to_buffer = (void *) mk_file_to_buffer;
407 api->file_get_info = (void *) mk_file_get_info;
409 /* HTTP Callbacks */
410 api->header_send = (void *) mk_header_send;
411 api->header_set_http_status = (void *) mk_header_set_http_status;
413 /* IOV callbacks */
414 api->iov_create = (void *) mk_iov_create;
415 api->iov_free = (void *) mk_iov_free;
416 api->iov_add_entry = (void *) mk_iov_add_entry;
417 api->iov_set_entry = (void *) mk_iov_set_entry;
418 api->iov_send = (void *) mk_iov_send;
419 api->iov_print = (void *) mk_iov_print;
421 /* EPoll callbacks */
422 api->epoll_create = (void *) mk_epoll_create;
423 api->epoll_init = (void *) mk_epoll_init;
424 api->epoll_add = (void *) mk_epoll_add;
425 api->epoll_del = (void *) mk_epoll_del;
426 api->epoll_change_mode = (void *) mk_epoll_change_mode;
428 /* Socket callbacks */
429 api->socket_cork_flag = (void *) mk_socket_set_cork_flag;
430 api->socket_connect = (void *) mk_socket_connect;
431 api->socket_reset = (void *) mk_socket_reset;
432 api->socket_set_tcp_nodelay = (void *) mk_socket_set_tcp_nodelay;
433 api->socket_set_nonblocking = (void *) mk_socket_set_nonblocking;
434 api->socket_create = (void *) mk_socket_create;
435 api->socket_close = (void *) mk_socket_close;
436 api->socket_sendv = (void *) mk_socket_sendv;
437 api->socket_send = (void *) mk_socket_send;
438 api->socket_read = (void *) mk_socket_read;
439 api->socket_send_file = (void *) mk_socket_send_file;
441 /* Config Callbacks */
442 api->config_create = (void *) mk_config_create;
443 api->config_free = (void *) mk_config_free;
444 api->config_section_get = (void *) mk_config_section_get;
445 api->config_section_getval = (void *) mk_config_section_getval;
447 /* Scheduler and Event callbacks */
448 api->sched_get_connection = (void *) mk_sched_get_connection;
449 api->event_add = (void *) mk_plugin_event_add;
450 api->event_del = (void *) mk_plugin_event_del;
451 api->event_socket_change_mode = (void *) mk_plugin_event_socket_change_mode;
453 /* Worker functions */
454 api->worker_spawn = (void *) mk_worker_spawn;
456 /* Some useful functions =) */
457 api->sys_get_somaxconn = (void *) mk_utils_get_somaxconn;
459 /* Time functions */
460 api->time_unix = (void *) mk_plugin_time_now_unix;
461 api->time_human = (void *) mk_plugin_time_now_human;
463 #ifdef TRACE
464 api->trace = (void *) mk_utils_trace;
465 #endif
467 /* Read configuration file */
468 path = mk_mem_malloc_z(1024);
469 snprintf(path, 1024, "%s/%s", config->serverconf, MK_PLUGIN_LOAD);
470 cnf = mk_config_create(path);
472 if (!cnf) {
473 puts("Error: Plugins configuration file could not be readed");
474 exit(1);
477 /* Read section 'PLUGINS' */
478 section = mk_config_section_get(cnf, "PLUGINS");
480 /* Read key entries */
481 entry = section->entry;
482 while (entry) {
483 if (strcasecmp(entry->key, "Load") == 0) {
484 handle = mk_plugin_load(entry->val);
486 p = mk_plugin_alloc(handle, entry->val);
487 if (!p) {
488 fprintf(stderr, "Plugin error: %s\n", entry->val);
489 dlclose(handle);
492 /* Build plugin configuration path */
493 mk_string_build(&plugin_confdir,
494 &len,
495 "%s/plugins/%s/",
496 config->serverconf, p->shortname);
498 #ifdef TRACE
499 MK_TRACE("Load Plugin '%s@%s'", p->shortname, p->path);
500 #endif
501 /* Init plugin */
502 ret = p->init(&api, plugin_confdir);
503 if (ret < 0) {
504 /* Free plugin, do not register */
505 #ifdef TRACE
506 MK_TRACE("Unregister plugin '%s'", p->shortname);
507 #endif
508 mk_plugin_free(p);
509 entry = entry->next;
510 continue;
513 /* If everything worked, register plugin */
514 mk_plugin_register(p);
516 entry = entry->next;
519 if (!plg_netiomap) {
520 fprintf(stderr, "\nError: no Network plugin loaded >:|\n\n");
521 exit(1);
524 api->plugins = config->plugins;
525 /* Look for plugins thread key data */
526 mk_plugin_preworker_calls();
527 mk_mem_free(path);
530 int mk_plugin_stage_run(mk_plugin_hook_t hook,
531 unsigned int socket,
532 struct sched_connection *conx,
533 struct client_request *cr, struct request *sr)
535 int ret;
536 struct plugin_stagem *stm;
538 /* Connection just accept(ed) not assigned to worker thread */
539 if (hook & MK_PLUGIN_STAGE_10) {
540 stm = plg_stagemap->stage_10;
541 while (stm) {
542 #ifdef TRACE
543 MK_TRACE("[%s] STAGE 10", stm->p->shortname);
544 #endif
545 ret = stm->p->stage.s10(socket, conx);
546 switch (ret) {
547 case MK_PLUGIN_RET_CLOSE_CONX:
548 #ifdef TRACE
549 MK_TRACE("return MK_PLUGIN_RET_CLOSE_CONX");
550 #endif
551 return MK_PLUGIN_RET_CLOSE_CONX;
554 stm = stm->next;
558 /* The HTTP Request stream has been just received */
559 if (hook & MK_PLUGIN_STAGE_20) {
560 stm = plg_stagemap->stage_20;
561 while (stm) {
562 #ifdef TRACE
563 MK_TRACE("[%s] STAGE 20", stm->p->shortname);
564 #endif
565 ret = stm->p->stage.s20(cr, sr);
566 switch (ret) {
567 case MK_PLUGIN_RET_CLOSE_CONX:
568 #ifdef TRACE
569 MK_TRACE("return MK_PLUGIN_RET_CLOSE_CONX");
570 #endif
571 return MK_PLUGIN_RET_CLOSE_CONX;
574 stm = stm->next;
578 /* The plugin acts like an Object handler, it will take care of the
579 * request, it decides what to do with the request
581 if (hook & MK_PLUGIN_STAGE_30) {
582 /* The request just arrived and is required to check who can
583 * handle it */
584 if (!sr->handled_by){
585 stm = plg_stagemap->stage_30;
586 while (stm) {
587 /* Call stage */
588 #ifdef TRACE
589 MK_TRACE("[%s] STAGE 30", stm->p->shortname);
590 #endif
591 ret = stm->p->stage.s30(stm->p, cr, sr);
593 switch (ret) {
594 case MK_PLUGIN_RET_NOT_ME:
595 break;
596 case MK_PLUGIN_RET_CONTINUE:
597 return MK_PLUGIN_RET_CONTINUE;
598 case MK_PLUGIN_RET_END:
599 return MK_PLUGIN_RET_END;
602 stm = stm->next;
607 /* The request has ended, the content has been served */
608 if (hook & MK_PLUGIN_STAGE_40) {
609 stm = plg_stagemap->stage_40;
610 while (stm) {
611 #ifdef TRACE
612 MK_TRACE("[%s] STAGE 40", stm->p->shortname);
613 #endif
614 ret = stm->p->stage.s40(cr, sr);
615 stm = stm->next;
619 /* The request has ended, the content has been served */
620 if (hook & MK_PLUGIN_STAGE_50) {
621 stm = plg_stagemap->stage_50;
622 while (stm) {
623 #ifdef TRACE
624 MK_TRACE("[%s] STAGE 50", stm->p->shortname);
625 #endif
626 ret = stm->p->stage.s50(socket);
627 switch (ret) {
628 case MK_PLUGIN_RET_NOT_ME:
629 break;
630 case MK_PLUGIN_RET_CONTINUE:
631 return MK_PLUGIN_RET_CONTINUE;
633 stm = stm->next;
637 return -1;
640 void mk_plugin_request_handler_add(struct request *sr, struct plugin *p)
642 if (!sr->handled_by) {
643 sr->handled_by = p;
644 return;
648 void mk_plugin_request_handler_del(struct request *sr, struct plugin *p)
650 if (!sr->handled_by) {
651 return;
654 mk_mem_free(sr->handled_by);
657 /* This function is called by every created worker
658 * for plugins which need to set some data under a thread
659 * context
661 void mk_plugin_core_process()
663 struct plugin *p;
665 p = config->plugins;
667 while (p) {
668 /* Init plugin */
669 if (p->core.prctx) {
670 p->core.prctx(config);
673 p = p->next;
677 /* This function is called by every created worker
678 * for plugins which need to set some data under a thread
679 * context
681 void mk_plugin_core_thread()
683 struct plugin *p;
685 p = config->plugins;
687 while (p) {
688 /* Init plugin thread context */
689 if (p->core.thctx) {
690 p->core.thctx();
693 p = p->next;
697 /* This function is called by Monkey *outside* of the
698 * thread context for plugins, so here's the right
699 * place to set pthread keys or similar
701 void mk_plugin_preworker_calls()
703 int ret;
704 struct plugin *p;
706 p = config->plugins;
708 while (p) {
709 /* Init pthread keys */
710 if (p->thread_key) {
711 #ifdef TRACE
712 MK_TRACE("[%s] Set thread key", p->shortname);
713 #endif
714 ret = pthread_key_create(p->thread_key, NULL);
715 if (ret != 0) {
716 printf("\nPlugin Error: could not create key for %s",
717 p->shortname);
718 fflush(stdout);
719 exit(1);
722 p = p->next;
726 int mk_plugin_event_del(int socket)
728 struct plugin_event *list, *aux, *prev;
730 #ifdef TRACE
731 MK_TRACE("[FD %i] Plugin delete event", socket);
732 #endif
734 if (socket <= 0) {
735 return -1;
738 list = mk_plugin_event_get_list();
740 aux = list;
741 while (aux) {
742 if (aux->socket == socket) {
743 if (aux == list) {
744 list = aux->next;
746 else {
747 prev = list;
748 while (prev->next != aux) {
749 prev = prev->next;
752 prev->next = aux->next;
754 mk_mem_free(aux);
755 mk_plugin_event_set_list(list);
756 return 0;
758 aux = aux->next;
761 #ifdef TRACE
762 MK_TRACE("[FD %i] not found :/");
763 exit(1);
764 #endif
766 return -1;
769 int mk_plugin_event_add(int socket, int mode,
770 struct plugin *handler,
771 struct client_request *cr,
772 struct request *sr)
774 struct sched_list_node *sched;
775 struct plugin_event *list;
776 struct plugin_event *aux;
777 struct plugin_event *event;
779 sched = mk_sched_get_thread_conf();
781 if (!sched || !handler || !cr || !sr) {
782 return -1;
785 /* Event node (this list exist at thread level */
786 event = mk_mem_malloc(sizeof(struct plugin_event));
787 event->socket = socket;
788 event->handler = handler;
789 event->cr = cr;
790 event->sr = sr;
791 event->next = NULL;
793 /* Get thread event list */
794 list = mk_plugin_event_get_list();
795 if (!list) {
796 mk_plugin_event_set_list(event);
798 else {
799 aux = list;
800 while (aux->next) {
801 aux = aux->next;
804 aux->next = event;
805 mk_plugin_event_set_list(list);
808 /* The thread event info has been registered, now we need
809 to register the socket involved to the thread epoll array */
810 mk_epoll_add(sched->epoll_fd, event->socket,
811 mode, MK_EPOLL_BEHAVIOR_DEFAULT);
812 return 0;
815 int mk_plugin_http_request_end(int socket)
817 int ret;
819 ret = mk_http_request_end(socket);
821 #ifdef TRACE
822 MK_TRACE("PLUGIN HTTP REQUEST END [FD=%i] = ret %i", socket, ret);
823 #endif
825 if (ret < 0) {
826 return mk_conn_close(socket);
829 return 0;
832 int mk_plugin_event_socket_change_mode(int socket, int mode)
834 struct sched_list_node *sched;
836 sched = mk_sched_get_thread_conf();
838 if (!sched) {
839 return -1;
842 return mk_epoll_change_mode(sched->epoll_fd, socket, mode);
845 struct plugin_event *mk_plugin_event_get(int socket)
847 struct plugin_event *event;
849 event = mk_plugin_event_get_list();
851 while (event){
852 if (event->socket == socket) {
853 return event;
856 event = event->next;
859 return NULL;
862 int mk_plugin_event_set_list(struct plugin_event *event)
864 return pthread_setspecific(mk_plugin_event_k, event);
867 struct plugin_event *mk_plugin_event_get_list()
869 return pthread_getspecific(mk_plugin_event_k);
873 /* Plugin epoll event handlers
874 * ---------------------------
875 * this functions are called by connection.c functions as mk_conn_read(),
876 * mk_conn_write(),mk_conn_error(), mk_conn_close() and mk_conn_timeout().
878 * Return Values:
879 * -------------
880 * MK_PLUGIN_RET_EVENT_NOT_ME: There's no plugin hook associated
883 int mk_plugin_event_read(int socket)
885 struct plugin_event *event;
887 #ifdef TRACE
888 MK_TRACE("[FD %i] Plugin event read", socket);
889 #endif
891 event = mk_plugin_event_get(socket);
892 if (!event) {
893 #ifdef TRACE
894 MK_TRACE(" not handled by plugin");
895 #endif
896 return MK_PLUGIN_RET_EVENT_NOT_ME;
899 if (event->handler->event_read) {
900 #ifdef TRACE
901 MK_TRACE(" handled by plugin");
902 #endif
903 return event->handler->event_read(socket);
906 return MK_PLUGIN_RET_CONTINUE;
909 int mk_plugin_event_write(int socket)
911 struct plugin_event *event;
913 #ifdef TRACE
914 MK_TRACE("[FD %i] Plugin event write", socket);
915 #endif
917 event = mk_plugin_event_get(socket);
918 if (!event) {
919 return MK_PLUGIN_RET_EVENT_NOT_ME;
922 if (event->handler->event_write) {
923 return event->handler->event_write(socket);
926 return MK_PLUGIN_RET_CONTINUE;
929 int mk_plugin_event_error(int socket)
931 struct plugin_event *event;
933 #ifdef TRACE
934 MK_TRACE("[FD %i] Plugin event error", socket);
935 #endif
937 event = mk_plugin_event_get(socket);
938 if (!event) {
939 return MK_PLUGIN_RET_EVENT_NOT_ME;
942 if (event->handler->event_error) {
943 return event->handler->event_error(socket);
946 return MK_PLUGIN_RET_CONTINUE;
949 int mk_plugin_event_close(int socket)
951 struct plugin_event *event;
953 #ifdef TRACE
954 MK_TRACE("[FD %i] Plugin event close", socket);
955 #endif
957 event = mk_plugin_event_get(socket);
958 if (!event) {
959 return MK_PLUGIN_RET_EVENT_NOT_ME;
962 if (event->handler->event_close) {
963 return event->handler->event_close(socket);
966 return 0;
969 int mk_plugin_event_timeout(int socket)
971 struct plugin_event *event;
973 #ifdef TRACE
974 MK_TRACE("[FD %i] Plugin event timeout", socket);
975 #endif
977 event = mk_plugin_event_get(socket);
978 if (!event) {
979 return MK_PLUGIN_RET_EVENT_NOT_ME;
982 if (event->handler->event_timeout) {
983 return event->handler->event_timeout(socket);
986 return 0;
989 int mk_plugin_time_now_unix()
991 return log_current_utime;
994 mk_pointer *mk_plugin_time_now_human()
996 return &log_current_time;