Deprecate core logger
[MonkeyD.git] / src / plugin.c
blobf08014245b0c041745294e3261db0b9524ba216e
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"
47 void *mk_plugin_load(char *path)
49 void *handle;
51 handle = dlopen(path, RTLD_LAZY);
52 if (!handle) {
53 fprintf(stderr, "Error during dlopen(): %s\n", dlerror());
54 exit(1);
56 return handle;
59 void *mk_plugin_load_symbol(void *handler, const char *symbol)
61 char *err;
62 void *s;
64 dlerror();
65 s = dlsym(handler, symbol);
66 if ((err = dlerror()) != NULL) {
67 return NULL;
70 return s;
73 void mk_plugin_register_stagemap_add(struct plugin_stagem **stm, struct plugin *p)
75 struct plugin_stagem *list, *new;
77 new = mk_mem_malloc_z(sizeof(struct plugin_stagem));
78 new->p = p;
79 new->next = NULL;
81 if (!*stm) {
82 *stm = new;
83 return;
86 list = *stm;
88 while (list->next) {
89 list = list->next;
92 list->next = new;
95 void mk_plugin_register_stagemap(struct plugin *p)
97 /* Plugin to stages */
98 if (*p->hooks & MK_PLUGIN_STAGE_10) {
99 mk_plugin_register_stagemap_add(&plg_stagemap->stage_10, p);
102 if (*p->hooks & MK_PLUGIN_STAGE_20) {
103 mk_plugin_register_stagemap_add(&plg_stagemap->stage_20, p);
106 if (*p->hooks & MK_PLUGIN_STAGE_30) {
107 mk_plugin_register_stagemap_add(&plg_stagemap->stage_30, p);
110 if (*p->hooks & MK_PLUGIN_STAGE_40) {
111 mk_plugin_register_stagemap_add(&plg_stagemap->stage_40, p);
114 if (*p->hooks & MK_PLUGIN_STAGE_50) {
115 mk_plugin_register_stagemap_add(&plg_stagemap->stage_50, p);
119 struct plugin *mk_plugin_alloc(void *handler, char *path)
121 struct plugin *p;
123 p = mk_mem_malloc_z(sizeof(struct plugin));
124 p->shortname = mk_plugin_load_symbol(handler, "_shortname");
125 p->name = mk_plugin_load_symbol(handler, "_name");
126 p->version = mk_plugin_load_symbol(handler, "_version");
127 p->path = mk_string_dup(path);
128 p->handler = handler;
129 p->hooks = (mk_plugin_hook_t *) mk_plugin_load_symbol(handler, "_hooks");
131 /* Mandatory functions */
132 p->init = (int (*)()) mk_plugin_load_symbol(handler, "_mkp_init");
133 p->exit = (int (*)()) mk_plugin_load_symbol(handler, "_mkp_exit");
135 /* Core hooks */
136 p->core.prctx = (int (*)()) mk_plugin_load_symbol(handler,
137 "_mkp_core_prctx");
138 p->core.thctx = (int (*)()) mk_plugin_load_symbol(handler,
139 "_mkp_core_thctx");
141 /* Stage hooks */
142 p->stage.s10 = (int (*)())
143 mk_plugin_load_symbol(handler, "_mkp_stage_10");
145 p->stage.s20 = (int (*)())
146 mk_plugin_load_symbol(handler, "_mkp_stage_20");
148 p->stage.s30 = (int (*)())
149 mk_plugin_load_symbol(handler, "_mkp_stage_30");
151 p->stage.s40 = (int (*)())
152 mk_plugin_load_symbol(handler, "_mkp_stage_40");
154 p->stage.s50 = (int (*)())
155 mk_plugin_load_symbol(handler, "_mkp_stage_50");
157 /* Network I/O hooks */
158 p->net_io.accept = (int (*)())
159 mk_plugin_load_symbol(handler, "_mkp_network_io_accept");
161 p->net_io.read = (int (*)())
162 mk_plugin_load_symbol(handler, "_mkp_network_io_read");
164 p->net_io.write = (int (*)())
165 mk_plugin_load_symbol(handler, "_mkp_network_io_write");
167 p->net_io.writev = (int (*)())
168 mk_plugin_load_symbol(handler, "_mkp_network_io_writev");
170 p->net_io.close = (int (*)())
171 mk_plugin_load_symbol(handler, "_mkp_network_io_close");
173 p->net_io.connect = (int (*)())
174 mk_plugin_load_symbol(handler, "_mkp_network_io_connect");
176 p->net_io.send_file = (int (*)())
177 mk_plugin_load_symbol(handler, "_mkp_network_io_send_file");
179 p->net_io.create_socket = (int (*)())
180 mk_plugin_load_symbol(handler, "_mkp_network_io_create_socket");
182 p->net_io.bind = (int (*)())
183 mk_plugin_load_symbol(handler, "_mkp_network_io_bind");
185 p->net_io.server = (int (*)())
186 mk_plugin_load_symbol(handler, "_mkp_network_io_server");
189 /* Network IP hooks */
190 p->net_ip.addr = (int (*)())
191 mk_plugin_load_symbol(handler, "_mkp_network_ip_addr");
193 p->net_ip.maxlen = (int (*)())
194 mk_plugin_load_symbol(handler, "_mkp_network_ip_maxlen");
196 /* Thread key */
197 p->thread_key = (pthread_key_t) mk_plugin_load_symbol(handler,
198 "_mkp_data");
200 /* Event handlers hooks */
201 p->event_read = (int (*)())
202 mk_plugin_load_symbol(handler, "_mkp_event_read");
204 p->event_write = (int (*)())
205 mk_plugin_load_symbol(handler, "_mkp_event_write");
207 p->event_error = (int (*)())
208 mk_plugin_load_symbol(handler, "_mkp_event_error");
210 p->event_close = (int (*)())
211 mk_plugin_load_symbol(handler, "_mkp_event_close");
213 p->event_timeout = (int (*)())
214 mk_plugin_load_symbol(handler, "_mkp_event_timeout");
216 /* Next ! */
217 p->next = NULL;
219 return p;
222 /* Load the plugins and set the library symbols to the
223 * local struct plugin *p node
225 struct plugin *mk_plugin_register(struct plugin *p)
227 if (!p->name || !p->version || !p->hooks) {
228 #ifdef TRACE
229 MK_TRACE("Plugin must define name, version and hooks. Check: %s", p->path);
230 #endif
231 mk_plugin_free(p);
232 return NULL;
235 if (!p->init || !p->exit) {
236 #ifdef TRACE
237 MK_TRACE("Plugin must define hooks 'init' and 'exit'");
238 #endif
239 mk_plugin_free(p);
240 return NULL;
243 /* NETWORK_IO Plugin */
244 if (*p->hooks & MK_PLUGIN_NETWORK_IO) {
245 /* Validate mandatory calls */
246 if (!p->net_io.accept || !p->net_io.read || !p->net_io.write ||
247 !p->net_io.writev || !p->net_io.close || !p->net_io.connect ||
248 !p->net_io.send_file || !p->net_io.create_socket || !p->net_io.bind ||
249 !p->net_io.server ) {
250 #ifdef TRACE
251 MK_TRACE("Networking IO plugin incomplete: %s", p->path);
252 MK_TRACE("Mapped Functions\naccept : %p\nread : %p\n\
253 write : %p\nwritev: %p\nclose : %p\nconnect : %p\nsendfile : %p\n\
254 create socket : %p\nbind : %p\nserver : %p",
255 p->net_io.accept,
256 p->net_io.read,
257 p->net_io.write,
258 p->net_io.writev,
259 p->net_io.close,
260 p->net_io.connect,
261 p->net_io.send_file,
262 p->net_io.create_socket,
263 p->net_io.bind,
264 p->net_io.server);
265 #endif
266 mk_plugin_free(p);
267 return NULL;
270 /* Restrict to one NETWORK_IO plugin */
271 if (!plg_netiomap) {
272 plg_netiomap = &p->net_io;
274 else {
275 fprintf(stderr,
276 "\nError: Loading more than one Network IO Plugin: %s",
277 p->path);
278 exit(1);
282 /* NETWORK_IP Plugin */
283 if (*p->hooks & MK_PLUGIN_NETWORK_IP) {
284 /* Validate mandatory calls */
285 if (!p->net_ip.addr || !p->net_ip.maxlen) {
286 #ifdef TRACE
287 MK_TRACE("Networking IP plugin incomplete: %s", p->path);
288 MK_TRACE("Mapped Functions\naddr :%p\nmaxlen :%p",
289 p->net_ip.addr,
290 p->net_ip.maxlen);
291 #endif
292 mk_plugin_free(p);
293 return NULL;
296 /* Restrict to one NETWORK_IP plugin */
297 if (!plg_netipmap) {
298 plg_netipmap = &p->net_ip;
300 else {
301 fprintf(stderr,
302 "\nError: Loading more than one Network IP Plugin: %s",
303 p->path);
304 exit(1);
308 /* Add Plugin to the end of the list */
309 if (!config->plugins) {
310 config->plugins = p;
312 else {
313 struct plugin *plg = config->plugins;
314 while(plg->next){
315 plg = plg->next;
317 plg->next = p;
320 mk_plugin_register_stagemap(p);
321 return p;
324 void mk_plugin_unregister(struct plugin *p)
326 struct plugin *node, *prev;
328 node = config->plugins;
330 if (!node) {
331 return;
334 if (node == p) {
335 config->plugins = p->next;
336 mk_plugin_free(p);
337 return;
340 prev = node;
341 while (node->next != p) {
342 prev = node;
343 node = node->next;
346 if (node) {
347 prev->next = p->next;
348 mk_plugin_free(p);
349 return;
353 void mk_plugin_free(struct plugin *p)
355 mk_mem_free(p->path);
356 mk_mem_free(p);
357 p = NULL;
360 void mk_plugin_init()
362 int ret;
363 char *path;
364 char *plugin_confdir = 0;
365 void *handle;
366 unsigned long len;
367 struct plugin *p;
368 struct plugin_api *api;
369 struct mk_config *cnf;
370 struct mk_config_section *section;
371 struct mk_config_entry *entry;
373 api = mk_mem_malloc_z(sizeof(struct plugin_api));
374 plg_stagemap = mk_mem_malloc_z(sizeof(struct plugin_stagemap));
375 plg_netiomap = NULL;
376 plg_netipmap = NULL;
378 /* Setup and connections list */
379 api->config = config;
380 api->sched_list = &sched_list;
382 /* API plugins funcions */
384 /* HTTP callbacks */
385 api->http_request_end = (void *) mk_plugin_http_request_end;
387 /* Memory callbacks */
388 api->pointer_set = (void *) mk_pointer_set;
389 api->pointer_print = (void *) mk_pointer_print;
390 api->plugin_load_symbol = (void *) mk_plugin_load_symbol;
391 api->mem_alloc = (void *) mk_mem_malloc;
392 api->mem_alloc_z = (void *) mk_mem_malloc_z;
393 api->mem_free = (void *) mk_mem_free;
395 /* String Callbacks */
396 api->str_build = (void *) mk_string_build;
397 api->str_dup = (void *) mk_string_dup;
398 api->str_search = (void *) mk_string_search;
399 api->str_search_n = (void *) mk_string_search_n;
400 api->str_copy_substr = (void *) mk_string_copy_substr;
401 api->str_split_line = (void *) mk_string_split_line;
403 /* File Callbacks */
404 api->file_to_buffer = (void *) mk_file_to_buffer;
405 api->file_get_info = (void *) mk_file_get_info;
407 /* HTTP Callbacks */
408 api->header_send = (void *) mk_header_send;
410 /* IOV callbacks */
411 api->iov_create = (void *) mk_iov_create;
412 api->iov_free = (void *) mk_iov_free;
413 api->iov_add_entry = (void *) mk_iov_add_entry;
414 api->iov_set_entry = (void *) mk_iov_set_entry;
415 api->iov_send = (void *) mk_iov_send;
416 api->iov_print = (void *) mk_iov_print;
418 /* EPoll callbacks */
419 api->epoll_create = (void *) mk_epoll_create;
420 api->epoll_init = (void *) mk_epoll_init;
421 api->epoll_add = (void *) mk_epoll_add;
422 api->epoll_del = (void *) mk_epoll_del;
423 api->epoll_change_mode = (void *) mk_epoll_change_mode;
425 /* Socket callbacks */
426 api->socket_cork_flag = (void *) mk_socket_set_cork_flag;
427 api->socket_connect = (void *) mk_socket_connect;
428 api->socket_reset = (void *) mk_socket_reset;
429 api->socket_set_tcp_nodelay = (void *) mk_socket_set_tcp_nodelay;
430 api->socket_set_nonblocking = (void *) mk_socket_set_nonblocking;
431 api->socket_create = (void *) mk_socket_create;
432 api->socket_close = (void *) mk_socket_close;
433 api->socket_sendv = (void *) mk_socket_sendv;
434 api->socket_send = (void *) mk_socket_send;
435 api->socket_read = (void *) mk_socket_read;
436 api->socket_send_file = (void *) mk_socket_send_file;
438 /* Config Callbacks */
439 api->config_create = (void *) mk_config_create;
440 api->config_free = (void *) mk_config_free;
441 api->config_section_get = (void *) mk_config_section_get;
442 api->config_section_getval = (void *) mk_config_section_getval;
444 /* Scheduler and Event callbacks */
445 api->sched_get_connection = (void *) mk_sched_get_connection;
446 api->event_add = (void *) mk_plugin_event_add;
447 api->event_socket_change_mode = (void *) mk_plugin_event_socket_change_mode;
449 /* Worker functions */
450 api->worker_spawn = (void *) mk_worker_spawn;
452 /* Some useful functions =) */
453 api->sys_get_somaxconn = (void *) mk_utils_get_somaxconn;
454 #ifdef TRACE
455 api->trace = (void *) mk_utils_trace;
456 #endif
458 /* Read configuration file */
459 path = mk_mem_malloc_z(1024);
460 snprintf(path, 1024, "%s/%s", config->serverconf, MK_PLUGIN_LOAD);
461 cnf = mk_config_create(path);
463 if (!cnf) {
464 puts("Error: Plugins configuration file could not be readed");
465 exit(1);
468 /* Read section 'PLUGINS' */
469 section = mk_config_section_get(cnf, "PLUGINS");
471 /* Read key entries */
472 entry = section->entry;
473 while (entry) {
474 if (strcasecmp(entry->key, "Load") == 0) {
475 handle = mk_plugin_load(entry->val);
477 p = mk_plugin_alloc(handle, entry->val);
478 if (!p) {
479 fprintf(stderr, "Plugin error: %s\n", entry->val);
480 dlclose(handle);
483 /* Build plugin configuration path */
484 mk_string_build(&plugin_confdir,
485 &len,
486 "%s/plugins/%s/",
487 config->serverconf, p->shortname);
489 #ifdef TRACE
490 MK_TRACE("Load Plugin '%s@%s'", p->shortname, p->path);
491 #endif
492 /* Init plugin */
493 ret = p->init(&api, plugin_confdir);
494 if (ret < 0) {
495 /* Free plugin, do not register */
496 #ifdef TRACE
497 MK_TRACE("Unregister plugin '%s'", p->shortname);
498 #endif
499 mk_plugin_free(p);
500 entry = entry->next;
501 continue;
504 /* If everything worked, register plugin */
505 mk_plugin_register(p);
507 entry = entry->next;
510 if (!plg_netiomap) {
511 fprintf(stderr, "\nError: no Network plugin loaded >:|\n\n");
512 exit(1);
515 api->plugins = config->plugins;
516 mk_mem_free(path);
519 int mk_plugin_stage_run(mk_plugin_hook_t hook,
520 unsigned int socket,
521 struct sched_connection *conx,
522 struct client_request *cr, struct request *sr)
524 int ret;
525 struct plugin_stagem *stm;
527 /* Connection just accept(ed) not assigned to worker thread */
528 if (hook & MK_PLUGIN_STAGE_10) {
529 stm = plg_stagemap->stage_10;
530 while (stm) {
531 #ifdef TRACE
532 MK_TRACE("[%s] STAGE 10", stm->p->shortname);
533 #endif
534 ret = stm->p->stage.s10(socket, conx);
535 switch (ret) {
536 case MK_PLUGIN_RET_CLOSE_CONX:
537 #ifdef TRACE
538 MK_TRACE("return MK_PLUGIN_RET_CLOSE_CONX");
539 #endif
540 return MK_PLUGIN_RET_CLOSE_CONX;
543 stm = stm->next;
547 /* The HTTP Request stream has been just received */
548 if (hook & MK_PLUGIN_STAGE_20) {
549 stm = plg_stagemap->stage_20;
550 while (stm) {
551 #ifdef TRACE
552 MK_TRACE("[%s] STAGE 20", stm->p->shortname);
553 #endif
554 ret = stm->p->stage.s20(cr, sr);
555 switch (ret) {
556 case MK_PLUGIN_RET_CLOSE_CONX:
557 #ifdef TRACE
558 MK_TRACE("return MK_PLUGIN_RET_CLOSE_CONX");
559 #endif
560 return MK_PLUGIN_RET_CLOSE_CONX;
563 stm = stm->next;
567 /* The plugin acts like an Object handler, it will take care of the
568 * request, it decides what to do with the request
570 if (hook & MK_PLUGIN_STAGE_30) {
571 /* The request just arrived and is required to check who can
572 * handle it */
573 if (!sr->handled_by){
574 stm = plg_stagemap->stage_30;
575 while (stm) {
576 /* Call stage */
577 #ifdef TRACE
578 MK_TRACE("[%s] STAGE 30", stm->p->shortname);
579 #endif
580 ret = stm->p->stage.s30(stm->p, cr, sr);
582 switch (ret) {
583 case MK_PLUGIN_RET_NOT_ME:
584 break;
585 case MK_PLUGIN_RET_CONTINUE:
586 return MK_PLUGIN_RET_CONTINUE;
587 case MK_PLUGIN_RET_END:
588 return MK_PLUGIN_RET_END;
591 stm = stm->next;
596 /* The request has ended, the content has been served */
597 if (hook & MK_PLUGIN_STAGE_40) {
598 stm = plg_stagemap->stage_40;
599 while (stm) {
600 #ifdef TRACE
601 MK_TRACE("[%s] STAGE 40", stm->p->shortname);
602 #endif
603 ret = stm->p->stage.s40(cr, sr);
604 switch (ret) {
605 case MK_PLUGIN_RET_NOT_ME:
606 break;
607 case MK_PLUGIN_RET_CONTINUE:
608 return MK_PLUGIN_RET_CONTINUE;
610 stm = stm->next;
614 /* The request has ended, the content has been served */
615 if (hook & MK_PLUGIN_STAGE_50) {
616 stm = plg_stagemap->stage_50;
617 while (stm) {
618 #ifdef TRACE
619 MK_TRACE("[%s] STAGE 50", stm->p->shortname);
620 #endif
621 ret = stm->p->stage.s50(socket);
622 switch (ret) {
623 case MK_PLUGIN_RET_NOT_ME:
624 break;
625 case MK_PLUGIN_RET_CONTINUE:
626 return MK_PLUGIN_RET_CONTINUE;
628 stm = stm->next;
632 return -1;
635 void mk_plugin_request_handler_add(struct request *sr, struct plugin *p)
637 if (!sr->handled_by) {
638 sr->handled_by = p;
639 return;
643 void mk_plugin_request_handler_del(struct request *sr, struct plugin *p)
645 if (!sr->handled_by) {
646 return;
649 mk_mem_free(sr->handled_by);
652 /* This function is called by every created worker
653 * for plugins which need to set some data under a thread
654 * context
656 void mk_plugin_core_process()
658 struct plugin *p;
660 p = config->plugins;
662 while (p) {
663 /* Init plugin */
664 if (p->core.prctx) {
665 p->core.prctx(config);
668 p = p->next;
672 /* This function is called by every created worker
673 * for plugins which need to set some data under a thread
674 * context
676 void mk_plugin_core_thread()
678 struct plugin *p;
680 p = config->plugins;
682 while (p) {
683 /* Init plugin */
684 if (p->core.thctx) {
685 p->core.thctx();
688 p = p->next;
692 /* This function is called by Monkey *outside* of the
693 * thread context for plugins, so here's the right
694 * place to set pthread keys or similar
696 void mk_plugin_preworker_calls()
698 int ret;
699 struct plugin *p;
701 p = config->plugins;
703 while (p) {
704 /* Init pthread keys */
705 if (p->thread_key) {
706 ret = pthread_key_create(&p->thread_key, NULL);
707 if (ret != 0) {
708 printf("\nPlugin Error: could not create key for %s",
709 p->shortname);
710 fflush(stdout);
711 exit(1);
714 p = p->next;
718 int mk_plugin_event_add(int socket, int mode,
719 struct plugin *handler,
720 struct client_request *cr,
721 struct request *sr)
723 struct sched_list_node *sched;
724 struct plugin_event *list;
725 struct plugin_event *aux;
726 struct plugin_event *event;
728 sched = mk_sched_get_thread_conf();
730 if (!sched || !handler || !cr || !sr) {
731 return -1;
734 /* Event node (this list exist at thread level */
735 event = mk_mem_malloc(sizeof(struct plugin_event));
736 event->socket = socket;
737 event->handler = handler;
738 event->cr = cr;
739 event->sr = sr;
740 event->next = NULL;
742 /* Get thread event list */
743 list = mk_plugin_event_get_list();
744 if (!list) {
745 mk_plugin_event_set_list(event);
747 else {
748 aux = list;
749 while (aux->next) {
750 aux = aux->next;
753 aux->next = event;
754 mk_plugin_event_set_list(aux);
757 /* The thread event info has been registered, now we need
758 to register the socket involved to the thread epoll array */
759 mk_epoll_add(sched->epoll_fd, event->socket,
760 mode, MK_EPOLL_BEHAVIOR_DEFAULT);
761 return 0;
764 int mk_plugin_http_request_end(int socket)
766 int ret;
768 ret = mk_http_request_end(socket);
769 if (ret < 0) {
770 return mk_conn_close(socket);
773 return 0;
776 int mk_plugin_event_socket_change_mode(int socket, int mode)
778 struct sched_list_node *sched;
780 sched = mk_sched_get_thread_conf();
782 if (!sched) {
783 return -1;
786 return mk_epoll_change_mode(sched->epoll_fd, socket, mode);
789 struct plugin_event *mk_plugin_event_get(int socket)
791 struct plugin_event *event;
793 event = mk_plugin_event_get_list();
795 while (event){
796 if (event->socket == socket) {
797 return event;
800 event = event->next;
803 return NULL;
806 int mk_plugin_event_set_list(struct plugin_event *event)
808 return pthread_setspecific(mk_plugin_event_k, (void *) event);
811 struct plugin_event *mk_plugin_event_get_list()
813 return (struct plugin_event *) pthread_getspecific(mk_plugin_event_k);
817 /* Plugin epoll event handlers
818 * ---------------------------
819 * this functions are called by connection.c functions as mk_conn_read(),
820 * mk_conn_write(),mk_conn_error(), mk_conn_close() and mk_conn_timeout
822 * Return Values:
823 * -------------
824 * MK_PLUGIN_RET_EVENT_NOT_ME: There's no plugin hook associated
827 int mk_plugin_event_read(int socket)
829 struct plugin_event *event;
831 #ifdef TRACE
832 MK_TRACE("Plugin, event read FD %i", socket);
833 #endif
835 event = mk_plugin_event_get(socket);
836 if (!event) {
837 return MK_PLUGIN_RET_EVENT_NOT_ME;
840 if (event->handler->event_read) {
841 return event->handler->event_read(socket);
844 return MK_PLUGIN_RET_CONTINUE;
847 int mk_plugin_event_write(int socket)
849 struct plugin_event *event;
851 #ifdef TRACE
852 MK_TRACE("Plugin, event write FD %i", socket);
853 #endif
855 event = mk_plugin_event_get(socket);
856 if (!event) {
857 return MK_PLUGIN_RET_EVENT_NOT_ME;
860 if (event->handler->event_write) {
861 return event->handler->event_write(socket);
864 return MK_PLUGIN_RET_CONTINUE;
867 int mk_plugin_event_error(int socket)
869 struct plugin_event *event;
871 #ifdef TRACE
872 MK_TRACE("Plugin, event error FD %i", socket);
873 #endif
875 event = mk_plugin_event_get(socket);
876 if (!event) {
877 return MK_PLUGIN_RET_EVENT_NOT_ME;
880 if (event->handler->event_error) {
881 return event->handler->event_error(socket);
884 return MK_PLUGIN_RET_CONTINUE;
887 int mk_plugin_event_close(int socket)
889 struct plugin_event *event;
891 #ifdef TRACE
892 MK_TRACE("Plugin, event close FD %i", socket);
893 #endif
895 event = mk_plugin_event_get(socket);
896 if (!event) {
897 return MK_PLUGIN_RET_EVENT_NOT_ME;
900 if (event->handler->event_close) {
901 return event->handler->event_close(socket);
904 return 0;
907 int mk_plugin_event_timeout(int socket)
909 struct plugin_event *event;
911 #ifdef TRACE
912 MK_TRACE("Plugin, event timeout FD %i", socket);
913 #endif
915 event = mk_plugin_event_get(socket);
916 if (!event) {
917 return MK_PLUGIN_RET_EVENT_NOT_ME;
920 if (event->handler->event_timeout) {
921 return event->handler->event_timeout(socket);
924 return 0;