1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3 /* Monkey HTTP Server
4 * ==================
5 * Copyright 2001-2017 Eduardo Silva <eduardo@monkey.io>
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 #include <monkey/monkey.h>
21 #include <monkey/mk_utils.h>
22 #include <monkey/mk_http.h>
23 #include <monkey/mk_clock.h>
24 #include <monkey/mk_plugin.h>
25 #include <monkey/mk_mimetype.h>
26 #include <monkey/mk_vhost.h>
27 #include <monkey/mk_static_plugins.h>
28 #include <monkey/mk_plugin_stage.h>
29 #include <monkey/mk_core.h>
30 #include <monkey/mk_net.h>
31
32 #ifndef _WIN32
33 #include <dlfcn.h>
34 #include <err.h>
35 #endif
36
37 enum {
38 bufsize = 256
39 };
40
41 static struct plugin_stagemap *plg_stagemap;
42 struct plugin_network_io *plg_netiomap;
43 struct plugin_api *api;
44
mk_plugin_lookup(char * shortname,struct mk_server * server)45 struct mk_plugin *mk_plugin_lookup(char *shortname, struct mk_server *server)
46 {
47 struct mk_list *head;
48 struct mk_plugin *p = NULL;
49
50 mk_list_foreach(head, &server->plugins) {
51 p = mk_list_entry(head, struct mk_plugin, _head);
52 if (strcmp(p->shortname, shortname) == 0){
53 return p;
54 }
55 }
56
57 return NULL;
58 }
59
mk_plugin_load_dynamic(const char * path)60 void *mk_plugin_load_dynamic(const char *path)
61 {
62 void *handle;
63
64 #ifdef _WIN32
65 handle = (void *) LoadLibraryA(path);
66 #else
67 handle = dlopen(path, RTLD_LAZY);
68
69 if (!handle) {
70 mk_warn("dlopen() %s", dlerror());
71 }
72 #endif
73
74 return handle;
75 }
76
mk_plugin_load_symbol(void * handler,const char * symbol)77 void *mk_plugin_load_symbol(void *handler, const char *symbol)
78 {
79 void *s;
80
81 #ifdef _WIN32
82 s = GetProcAddress((HMODULE)handler, symbol);
83 #else
84 dlerror();
85 s = dlsym(handler, symbol);
86 if (dlerror() != NULL) {
87 return NULL;
88 }
89 #endif
90
91 return s;
92 }
93
94 /* Initialize a plugin, trigger the init_plugin callback */
mk_plugin_init(struct plugin_api * api,struct mk_plugin * plugin,struct mk_server * server)95 static int mk_plugin_init(struct plugin_api *api, struct mk_plugin *plugin,
96 struct mk_server *server)
97 {
98 int ret;
99 unsigned long len;
100 char path[1024];
101 char *conf_dir = NULL;
102 struct file_info f_info;
103
104 MK_TRACE("Load Plugin: '%s'", plugin->shortname);
105
106 snprintf(path, 1024, "%s/%s",
107 server->path_conf_root, server->conf_plugins);
108 ret = mk_file_get_info(path, &f_info, MK_FILE_READ);
109 if (ret == -1 || f_info.is_directory == MK_FALSE) {
110 snprintf(path, 1024, "%s", server->conf_plugins);
111 }
112
113 /* Build plugin configuration path */
114 mk_string_build(&conf_dir,
115 &len,
116 "%s/%s/",
117 path, plugin->shortname);
118
119 /* Init plugin */
120 plugin->server_ctx = server;
121 ret = plugin->init_plugin(&api, conf_dir);
122 mk_mem_free(conf_dir);
123
124 return ret;
125 }
126
127
128 /*
129 * Load a plugin into Monkey core, 'type' defines if it's a MK_PLUGIN_STATIC or
130 * a MK_PLUGIN_DYNAMIC. 'shortname' is mandatory and 'path' is only used when
131 * MK_PLUGIN_DYNAMIC is set and represents the absolute path of the shared
132 * library.
133 */
mk_plugin_load(int type,const char * shortname,void * data,struct mk_server * server)134 struct mk_plugin *mk_plugin_load(int type, const char *shortname,
135 void *data, struct mk_server *server)
136 {
137 char *path;
138 char symbol[64];
139 void *handler;
140 struct mk_list *head;
141 struct mk_plugin *tmp;
142 struct mk_plugin *plugin = NULL;
143 struct mk_plugin_stage *stage;
144
145 /* Set main struct name to reference */
146 if (type == MK_PLUGIN_DYNAMIC) {
147 path = (char *) data;
148 handler = mk_plugin_load_dynamic(path);
149 if (!handler) {
150 return NULL;
151 }
152
153 snprintf(symbol, sizeof(symbol) - 1, "mk_plugin_%s", shortname);
154 plugin = mk_plugin_load_symbol(handler, symbol);
155 if (!plugin) {
156 mk_warn("Plugin '%s' is not registering properly", path);
157 #ifdef _WIN32
158 FreeLibrary((HMODULE)handler);
159 #else
160 dlclose(handler);
161 #endif
162 return NULL;
163 }
164
165 /* Make sure this is not loaded twice (ref #218) */
166 mk_list_foreach(head, &server->plugins) {
167 tmp = mk_list_entry(head, struct mk_plugin, _head);
168 if (tmp->load_type == MK_PLUGIN_STATIC &&
169 strcmp(tmp->name, plugin->name) == 0){
170 mk_warn("Plugin '%s' have been built-in.",
171 tmp->shortname);
172 #ifdef _WIN32
173 FreeLibrary((HMODULE)handler);
174 #else
175 dlclose(handler);
176 #endif
177 return NULL;
178 }
179 }
180
181 plugin->load_type = MK_PLUGIN_DYNAMIC;
182 plugin->handler = handler;
183 plugin->path = mk_string_dup(path);
184 }
185 else if (type == MK_PLUGIN_STATIC) {
186 plugin = (struct mk_plugin *) data;
187 plugin->load_type = MK_PLUGIN_STATIC;
188 }
189
190 if (!plugin) {
191 return NULL;
192 }
193
194 /* Validate all callbacks are set */
195 if (!plugin->shortname || !plugin->name || !plugin->version ||
196 !plugin->init_plugin || !plugin->exit_plugin) {
197 mk_warn("Plugin '%s' is not registering all fields properly",
198 shortname);
199 return NULL;
200 }
201
202 if (plugin->hooks & MK_PLUGIN_NETWORK_LAYER) {
203 mk_bug(!plugin->network);
204 }
205
206 mk_list_init(&plugin->stage_list);
207 if (plugin->hooks & MK_PLUGIN_STAGE) {
208 struct mk_plugin_stage *st;
209
210 stage = plugin->stage;
211 if (stage->stage10) {
212 st = mk_mem_alloc(sizeof(struct mk_plugin_stage));
213 st->stage10 = stage->stage10;
214 st->plugin = plugin;
215 mk_list_add(&st->_head, &server->stage10_handler);
216 mk_list_add(&st->_parent_head, &plugin->stage_list);
217 }
218 if (stage->stage20) {
219 st = mk_mem_alloc(sizeof(struct mk_plugin_stage));
220 st->stage20 = stage->stage20;
221 st->plugin = plugin;
222 mk_list_add(&st->_head, &server->stage20_handler);
223 mk_list_add(&st->_parent_head, &plugin->stage_list);
224 }
225 if (stage->stage30) {
226 st = mk_mem_alloc(sizeof(struct mk_plugin_stage));
227 st->stage30 = stage->stage30;
228 st->plugin = plugin;
229 mk_list_add(&st->_head, &server->stage30_handler);
230 mk_list_add(&st->_parent_head, &plugin->stage_list);
231 }
232 if (stage->stage40) {
233 st = mk_mem_alloc(sizeof(struct mk_plugin_stage));
234 st->stage40 = stage->stage40;
235 st->plugin = plugin;
236 mk_list_add(&st->_head, &server->stage40_handler);
237 mk_list_add(&st->_parent_head, &plugin->stage_list);
238 }
239 if (stage->stage50) {
240 st = mk_mem_alloc(sizeof(struct mk_plugin_stage));
241 st->stage50 = stage->stage50;
242 st->plugin = plugin;
243 mk_list_add(&st->_head, &server->stage50_handler);
244 mk_list_add(&st->_parent_head, &plugin->stage_list);
245 }
246 }
247
248 if (type == MK_PLUGIN_DYNAMIC) {
249 /* Add Plugin to the end of the list */
250 mk_list_add(&plugin->_head, &server->plugins);
251 }
252
253 return plugin;
254 }
255
mk_plugin_unregister(struct mk_plugin * p)256 void mk_plugin_unregister(struct mk_plugin *p)
257 {
258 mk_mem_free(p->path);
259 mk_list_del(&p->_head);
260 if (p->load_type == MK_PLUGIN_DYNAMIC) {
261 #ifdef _WIN32
262 FreeLibrary((HMODULE)p->handler);
263 #else
264 dlclose(p->handler);
265 #endif
266 }
267
268 }
269
mk_plugin_api_init(struct mk_server * server)270 void mk_plugin_api_init(struct mk_server *server)
271 {
272 /* Create an instance of the API */
273 api = mk_mem_alloc_z(sizeof(struct plugin_api));
274
275 #ifndef _WIN32
276 __builtin_prefetch(api);
277 #endif
278
279 /* Setup and connections list */
280 /* FIXME: api->config = server; */
281
282 /* API plugins funcions */
283
284 /* Error helper */
285 api->_error = mk_print;
286
287 /* HTTP callbacks */
288 api->http_request_end = mk_plugin_http_request_end;
289 api->http_request_error = mk_plugin_http_error;
290
291 /* Memory callbacks */
292 api->pointer_set = mk_ptr_set;
293 api->pointer_print = mk_ptr_print;
294 api->pointer_to_buf = mk_ptr_to_buf;
295 api->plugin_load_symbol = mk_plugin_load_symbol;
296 api->mem_alloc = mk_mem_alloc;
297 api->mem_alloc_z = mk_mem_alloc_z;
298 api->mem_realloc = mk_mem_realloc;
299 api->mem_free = mk_mem_free;
300
301 /* String Callbacks */
302 api->str_build = mk_string_build;
303 api->str_dup = mk_string_dup;
304 api->str_search = mk_string_search;
305 api->str_search_n = mk_string_search_n;
306 api->str_char_search = mk_string_char_search;
307 api->str_copy_substr = mk_string_copy_substr;
308 api->str_itop = mk_string_itop;
309 api->str_split_line = mk_string_split_line;
310 api->str_split_free = mk_string_split_free;
311
312 /* File Callbacks */
313 api->file_to_buffer = mk_file_to_buffer;
314 api->file_get_info = mk_file_get_info;
315
316 /* HTTP Callbacks */
317 api->header_prepare = mk_plugin_header_prepare;
318 api->header_add = mk_plugin_header_add;
319 api->header_get = mk_http_header_get;
320 api->header_set_http_status = mk_header_set_http_status;
321
322 /* Channels / Streams */
323 api->channel_new = mk_channel_new;
324 api->channel_flush = mk_channel_flush;
325 api->channel_write = mk_channel_write;
326 api->channel_append_stream = mk_channel_append_stream;
327
328 /* IOV callbacks */
329 api->iov_create = mk_iov_create;
330 api->iov_realloc = mk_iov_realloc;
331 api->iov_free = mk_iov_free;
332 api->iov_free_marked = mk_iov_free_marked;
333 api->iov_add = mk_iov_add;
334 api->iov_set_entry = mk_iov_set_entry;
335 api->iov_send = mk_iov_send;
336 api->iov_print = mk_iov_print;
337
338 /* events mechanism */
339 api->ev_loop_create = mk_event_loop_create;
340 api->ev_add = mk_event_add;
341 api->ev_del = mk_event_del;
342 api->ev_timeout_create = mk_event_timeout_create;
343 api->ev_channel_create = mk_event_channel_create;
344 api->ev_wait = mk_event_wait;
345 api->ev_backend = mk_event_backend;
346
347 /* Mimetype */
348 api->mimetype_lookup = mk_mimetype_lookup;
349
350 /* Socket callbacks */
351 api->socket_cork_flag = mk_socket_set_cork_flag;
352 api->socket_connect = mk_socket_connect;
353 api->socket_open = mk_socket_open;
354 api->socket_reset = mk_socket_reset;
355 api->socket_set_tcp_fastopen = mk_socket_set_tcp_fastopen;
356 api->socket_set_tcp_reuseport = mk_socket_set_tcp_reuseport;
357 api->socket_set_tcp_nodelay = mk_socket_set_tcp_nodelay;
358 api->socket_set_nonblocking = mk_socket_set_nonblocking;
359 api->socket_create = mk_socket_create;
360 api->socket_ip_str = mk_socket_ip_str;
361
362 /* Async network */
363 api->net_conn_create = mk_net_conn_create;
364
365 /* Config Callbacks */
366 api->config_create = mk_rconf_create;
367 api->config_open = mk_rconf_open;
368 api->config_free = mk_rconf_free;
369 api->config_section_get = mk_rconf_section_get;
370 api->config_section_get_key = mk_rconf_section_get_key;
371
372 /* Scheduler and Event callbacks */
373 api->sched_loop = mk_sched_loop;
374 api->sched_get_connection = mk_sched_get_connection;
375 api->sched_event_free = mk_sched_event_free;
376 api->sched_remove_client = mk_plugin_sched_remove_client;
377 api->sched_worker_info = mk_plugin_sched_get_thread_conf;
378
379 /* Worker functions */
380 api->worker_spawn = mk_utils_worker_spawn;
381 api->worker_rename = mk_utils_worker_rename;
382
383 /* Time functions */
384 api->time_unix = mk_plugin_time_now_unix;
385 api->time_to_gmt = mk_utils_utime2gmt;
386 api->time_human = mk_plugin_time_now_human;
387
388 api->stacktrace = (void *) mk_utils_stacktrace;
389 api->kernel_version = mk_kernel_version;
390 api->kernel_features_print = mk_kernel_features_print;
391 api->plugins = &server->plugins;
392
393 /* handler */
394 api->handler_param_get = mk_handler_param_get;
395 }
396
mk_plugin_load_static(struct mk_server * server)397 void mk_plugin_load_static(struct mk_server *server)
398 {
399 /* Load static plugins */
400 mk_list_init(&server->plugins);
401 mk_static_plugins(&server->plugins);
402 }
403
mk_plugin_load_all(struct mk_server * server)404 void mk_plugin_load_all(struct mk_server *server)
405 {
406 int ret;
407 char *tmp;
408 char *path;
409 char shortname[64];
410 struct mk_plugin *p;
411 struct mk_rconf *cnf;
412 struct mk_rconf_section *section;
413 struct mk_rconf_entry *entry;
414 struct mk_list *head;
415 struct mk_list *htmp;
416 struct file_info f_info;
417
418 mk_plugin_load_static(server);
419 mk_list_foreach_safe(head, htmp, &server->plugins) {
420 p = mk_list_entry(head, struct mk_plugin, _head);
421
422 /* Load the static plugin */
423 p = mk_plugin_load(MK_PLUGIN_STATIC,
424 p->shortname,
425 (void *) p,
426 server);
427 if (!p) {
428 continue;
429 }
430 ret = mk_plugin_init(api, p, server);
431 if (ret == -1) {
432 /* Free plugin, do not register, error initializing */
433 mk_warn("Plugin initialization failed: %s", p->shortname);
434 mk_plugin_unregister(p);
435 continue;
436 }
437 else if (ret == -2) {
438 /* Do not register, just skip it */
439 mk_plugin_unregister(p);
440 continue;
441 }
442 }
443
444 /* In case there are not dynamic plugins */
445 if (!server->conf_plugin_load) {
446 return;
447 }
448
449 /* Read configuration file */
450 path = mk_mem_alloc_z(1024);
451 snprintf(path, 1024, "%s/%s", server->path_conf_root,
452 server->conf_plugin_load);
453 ret = mk_file_get_info(path, &f_info, MK_FILE_READ);
454 if (ret == -1 || f_info.is_file == MK_FALSE) {
455 snprintf(path, 1024, "%s", server->conf_plugin_load);
456 }
457
458 cnf = mk_rconf_open(path);
459 if (!cnf) {
460 mk_warn("No dynamic plugins loaded.");
461 mk_mem_free(path);
462 return;
463 }
464
465 /* Read section 'PLUGINS' */
466 section = mk_rconf_section_get(cnf, "PLUGINS");
467 if (!section) {
468 exit(EXIT_FAILURE);
469 }
470
471 /* Read key entries */
472 mk_list_foreach_safe(head, htmp, §ion->entries) {
473 entry = mk_list_entry(head, struct mk_rconf_entry, _head);
474 if (strcasecmp(entry->key, "Load") == 0) {
475
476 /* Get plugin 'shortname' */
477 tmp = memrchr(entry->val, '-', strlen(entry->val));
478 ++tmp;
479 memset(shortname, '\0', sizeof(shortname) - 1);
480 strncpy(shortname, tmp, strlen(tmp) - 3);
481
482 /* Load the dynamic plugin */
483 p = mk_plugin_load(MK_PLUGIN_DYNAMIC,
484 shortname,
485 entry->val,
486 server);
487 if (!p) {
488 mk_warn("Invalid plugin '%s'", entry->val);
489 continue;
490 }
491
492 ret = mk_plugin_init(api, p, server);
493 if (ret < 0) {
494 /* Free plugin, do not register */
495 MK_TRACE("Unregister plugin '%s'", p->shortname);
496 mk_plugin_unregister(p);
497 continue;
498 }
499 }
500 }
501
502 /* Look for plugins thread key data */
503 mk_plugin_preworker_calls(server);
504 mk_vhost_map_handlers(server);
505 mk_mem_free(path);
506 mk_rconf_free(cnf);
507 }
508
mk_plugin_exit_stages(struct mk_plugin * p)509 static void mk_plugin_exit_stages(struct mk_plugin *p)
510 {
511 struct mk_list *tmp;
512 struct mk_list *head;
513 struct mk_plugin_stage *st;
514
515 mk_list_foreach_safe(head, tmp, &p->stage_list) {
516 st = mk_list_entry(head, struct mk_plugin_stage, _parent_head);
517
518 /* remove from direct config->stageN head list */
519 mk_list_del(&st->_head);
520
521 /* remove from plugin->stage_lists */
522 mk_list_del(&st->_parent_head);
523 mk_mem_free(st);
524 }
525 }
526
527 /* Invoke all plugins 'exit' hook and free resources by the plugin interface */
mk_plugin_exit_all(struct mk_server * server)528 void mk_plugin_exit_all(struct mk_server *server)
529 {
530 struct mk_plugin *plugin;
531 struct mk_list *head, *tmp;
532
533 /* Plugins */
534 mk_list_foreach(head, &server->plugins) {
535 plugin = mk_list_entry(head, struct mk_plugin, _head);
536 plugin->exit_plugin();
537 }
538
539 /* Plugin interface it self */
540 mk_list_foreach_safe(head, tmp, &server->plugins) {
541 plugin = mk_list_entry(head, struct mk_plugin, _head);
542 mk_list_del(&plugin->_head);
543 mk_plugin_exit_stages(plugin);
544
545 if (plugin->load_type == MK_PLUGIN_DYNAMIC) {
546 mk_mem_free(plugin->path);
547 #ifdef _WIN32
548 FreeLibrary((HMODULE)plugin->handler);
549 #else
550 dlclose(plugin ->handler);
551 #endif
552 }
553 }
554 mk_mem_free(api);
555 mk_mem_free(plg_stagemap);
556 }
557
558 /*
559 * When a worker is exiting, it invokes this function to release any plugin
560 * associated data.
561 */
mk_plugin_exit_worker()562 void mk_plugin_exit_worker()
563 {
564 }
565
566 /* This function is called by every created worker
567 * for plugins which need to set some data under a thread
568 * context
569 */
mk_plugin_core_process(struct mk_server * server)570 void mk_plugin_core_process(struct mk_server *server)
571 {
572 struct mk_plugin *node;
573 struct mk_list *head;
574
575 mk_list_foreach(head, &server->plugins) {
576 node = mk_list_entry(head, struct mk_plugin, _head);
577
578 /* Init plugin */
579 if (node->master_init) {
580 node->master_init(server);
581 }
582 }
583 }
584
585 /* This function is called by every created worker
586 * for plugins which need to set some data under a thread
587 * context
588 */
mk_plugin_core_thread(struct mk_server * server)589 void mk_plugin_core_thread(struct mk_server *server)
590 {
591
592 struct mk_plugin *node;
593 struct mk_list *head;
594
595 mk_list_foreach(head, &server->plugins) {
596 node = mk_list_entry(head, struct mk_plugin, _head);
597
598 /* Init plugin thread context */
599 if (node->worker_init) {
600 node->worker_init(server);
601 }
602 }
603 }
604
605 /* This function is called by Monkey *outside* of the
606 * thread context for plugins, so here's the right
607 * place to set pthread keys or similar
608 */
mk_plugin_preworker_calls(struct mk_server * server)609 void mk_plugin_preworker_calls(struct mk_server *server)
610 {
611 int ret;
612 struct mk_plugin *node;
613 struct mk_list *head;
614
615 mk_list_foreach(head, &server->plugins) {
616 node = mk_list_entry(head, struct mk_plugin, _head);
617
618 /* Init pthread keys */
619 if (node->thread_key) {
620 MK_TRACE("[%s] Set thread key", node->shortname);
621
622 ret = pthread_key_create(node->thread_key, NULL);
623 if (ret != 0) {
624 mk_err("Plugin Error: could not create key for %s",
625 node->shortname);
626 }
627 }
628 }
629 }
630
mk_plugin_http_error(int http_status,struct mk_http_session * cs,struct mk_http_request * sr,struct mk_plugin * plugin)631 int mk_plugin_http_error(int http_status, struct mk_http_session *cs,
632 struct mk_http_request *sr,
633 struct mk_plugin *plugin)
634 {
635 return mk_http_error(http_status, cs, sr, plugin->server_ctx);
636 }
637
638
mk_plugin_http_request_end(struct mk_plugin * plugin,struct mk_http_session * cs,int close)639 int mk_plugin_http_request_end(struct mk_plugin *plugin,
640 struct mk_http_session *cs, int close)
641 {
642 int ret;
643 int con;
644 struct mk_http_request *sr;
645 struct mk_server *server = plugin->server_ctx;
646
647 MK_TRACE("[FD %i] PLUGIN HTTP REQUEST END", cs->socket);
648
649 cs->status = MK_REQUEST_STATUS_INCOMPLETE;
650 if (mk_list_is_empty(&cs->request_list) == 0) {
651 MK_TRACE("[FD %i] Tried to end non-existing request.", cs->socket);
652 return -1;
653 }
654
655 sr = mk_list_entry_last(&cs->request_list, struct mk_http_request, _head);
656 mk_plugin_stage_run_40(cs, sr, server);
657
658 if (close == MK_TRUE) {
659 cs->close_now = MK_TRUE;
660 }
661
662 /* Let's check if we should ask to finalize the connection or not */
663 ret = mk_http_request_end(cs, server);
664 MK_TRACE("[FD %i] HTTP session end = %i", cs->socket, ret);
665 if (ret < 0) {
666 con = mk_sched_event_close(cs->conn, mk_sched_get_thread_conf(),
667 MK_EP_SOCKET_DONE, server);
668 if (con != 0) {
669 return con;
670 }
671 else {
672 return -1;
673 }
674 }
675
676 return ret;
677 }
678
679 /* Plugin epoll event handlers
680 * ---------------------------
681 * this functions are called by connection.c functions as mk_conn_read(),
682 * mk_conn_write(),mk_conn_error(), mk_conn_close() and mk_conn_timeout().
683 *
684 * Return Values:
685 * -------------
686 * MK_PLUGIN_RET_EVENT_NOT_ME: There's no plugin hook associated
687 */
688
mk_plugin_event_bad_return(const char * hook,int ret)689 void mk_plugin_event_bad_return(const char *hook, int ret)
690 {
691 mk_err("[%s] Not allowed return value %i", hook, ret);
692 }
693
mk_plugin_time_now_unix()694 int mk_plugin_time_now_unix()
695 {
696 return log_current_utime;
697 }
698
mk_plugin_time_now_human()699 mk_ptr_t *mk_plugin_time_now_human()
700 {
701 return &log_current_time;
702 }
703
mk_plugin_sched_remove_client(int socket,struct mk_server * server)704 int mk_plugin_sched_remove_client(int socket, struct mk_server *server)
705 {
706 struct mk_sched_conn *conn;
707 struct mk_sched_worker *sched;
708
709 MK_TRACE("[FD %i] remove client", socket);
710
711 sched = mk_sched_get_thread_conf();
712 conn = mk_sched_get_connection(sched, socket);
713 if (!conn) {
714 return -1;
715 }
716
717 return mk_sched_remove_client(conn, sched, server);
718 }
719
mk_plugin_header_prepare(struct mk_plugin * plugin,struct mk_http_session * cs,struct mk_http_request * sr)720 int mk_plugin_header_prepare(struct mk_plugin *plugin,
721 struct mk_http_session *cs,
722 struct mk_http_request *sr)
723 {
724 return mk_header_prepare(cs, sr, plugin->server_ctx);
725 }
726
727
mk_plugin_header_add(struct mk_http_request * sr,char * row,int len)728 int mk_plugin_header_add(struct mk_http_request *sr, char *row, int len)
729 {
730 mk_bug(!sr);
731
732 if (!sr->headers._extra_rows) {
733 /*
734 * We allocate space for a fixed number of IOV entries:
735 *
736 * MK_PLUGIN_HEADER_EXTRA_ROWS = X
737 *
738 * we use (MK_PLUGIN_HEADER_EXTRA_ROWS * 2) thinking in an ending CRLF
739 */
740 sr->headers._extra_rows = mk_iov_create(MK_PLUGIN_HEADER_EXTRA_ROWS * 2, 0);
741 mk_bug(!sr->headers._extra_rows);
742 }
743
744 mk_iov_add(sr->headers._extra_rows, row, len,
745 MK_FALSE);
746 mk_iov_add(sr->headers._extra_rows,
747 mk_iov_crlf.data, mk_iov_crlf.len,
748 MK_FALSE);
749 return 0;
750 }
751
mk_plugin_sched_get_thread_conf()752 struct mk_sched_worker *mk_plugin_sched_get_thread_conf()
753 {
754 return MK_TLS_GET(mk_tls_sched_worker_node);
755 }
756
mk_plugin_cap(char cap,struct mk_server * server)757 struct mk_plugin *mk_plugin_cap(char cap, struct mk_server *server)
758 {
759 struct mk_list *head;
760 struct mk_plugin *plugin;
761
762 mk_list_foreach(head, &server->plugins) {
763 plugin = mk_list_entry(head, struct mk_plugin, _head);
764 if (plugin->capabilities & cap) {
765 return plugin;
766 }
767 }
768
769 return NULL;
770 }
771
mk_handler_param_get(int id,struct mk_list * params)772 struct mk_vhost_handler_param *mk_handler_param_get(int id,
773 struct mk_list *params)
774 {
775 int i = 0;
776 struct mk_list *head;
777
778 mk_list_foreach(head, params) {
779 if (i == id) {
780 return mk_list_entry(head, struct mk_vhost_handler_param, _head);
781 }
782 i++;
783 }
784
785 return NULL;
786 }
787