Hi This is the big one, bringing all lib functionality over.
If you want this split up, please mention in which way ;) Please apply the cheetah patch before this one. - Lauri
>From 11305663f1e331b1dfd4a68d159dcb4795172a2c Mon Sep 17 00:00:00 2001 From: Lauri Kasanen <[email protected]> Date: Tue, 7 Aug 2012 16:35:09 +0300 Subject: [PATCH] lib: Bring the bulk of lib over Some mime functions get exported, config init & reading is separated, and some functions are moved around so that they can be ifdef'd out, to create a smaller library. Signed-off-by: Lauri Kasanen <[email protected]> --- configure | 118 +++++++-- src/include/mk_lib.h | 45 +++ src/include/mk_mimetype.h | 10 +- src/include/mk_plugin.h | 2 + src/include/mk_scheduler.h | 9 +- src/include/public/monkey.h | 191 +++++++++++++ src/mk_clock.c | 2 +- src/mk_config.c | 70 +++--- src/mk_lib.c | 624 +++++++++++++++++++++++++++++++++++++++++++ src/mk_mimetype.c | 34 ++-- src/mk_plugin.c | 121 ++++++++- src/mk_scheduler.c | 14 +- src/mk_server.c | 6 +- src/mk_signals.c | 5 + src/mk_user.c | 4 + src/mk_utils.c | 70 +++--- src/monkey.c | 3 + 17 files changed, 1209 insertions(+), 119 deletions(-) create mode 100644 src/include/mk_lib.h create mode 100644 src/include/public/monkey.h create mode 100644 src/mk_lib.c diff --git a/configure b/configure index e1ea409..04a0556 100755 --- a/configure +++ b/configure @@ -23,6 +23,7 @@ __MONKEY_MINOR__="1" __MONKEY_PATCHLEVEL__="0" VERSION="$__MONKEY__.$__MONKEY_MINOR__.$__MONKEY_PATCHLEVEL__" +SONAME="libmonkey.so.$__MONKEY__.$__MONKEY_MINOR__" SYSNAME=`uname -s` SYSINFO=`uname -sr` INCDIR="src/include/" @@ -160,8 +161,8 @@ main() echo echo -e "\033[1m=== Monkey Configuration ===\033[0m" - echo -e "PLATFORM\t= $platform" - echo -e "COMPILER\t= $CC" + echo -e "Platform\t= $platform" + echo -e "Compiler\t= $CC" echo -e "CFLAGS\t\t= $CFLAGS" echo -e "LDFLAGS\t\t= $LDFLAGS" @@ -169,16 +170,26 @@ main() echo -e "DEFS\t\t= $DEFS" fi + echo + + echo -en "Shared library\t= " + [ -n "$sharedlib" ] && echo "enabled" || echo "disabled" + + echo -en "Relaxed plugins\t= " + [ -n "$relaxed_plugins" ] && echo "enabled" || echo "disabled" + echo - echo -e "PREFIX\t\t= $prefix" - echo -e "BINDIR\t\t= $bindir" - echo -e "SYSCONFDIR\t= $sysconfdir" - echo -e "DATADIR\t\t= $datadir" - echo -e "MANDIR\t\t= $mandir" - echo -e "LOGDIR\t\t= $logdir" + echo -e "Prefix\t\t= $prefix" + echo -e "Bindir\t\t= $bindir" + echo -e "Libdir\t\t= $libdir" + echo -e "Incdir\t\t= $incdir" + echo -e "Sysconfdir\t= $sysconfdir" + echo -e "Datadir\t\t= $datadir" + echo -e "Mandir\t\t= $mandir" + echo -e "Logdir\t\t= $logdir" if [ "$plugdir" != "" ]; then - echo -e "PLUGDIR\t\t= $plugdir" + echo -e "Plugdir\t\t= $plugdir" fi echo @@ -323,19 +334,26 @@ done; plgconf=`cat plugins.conf` rm -rf plugins.conf +if [ -n "$sharedlib" ]; then + incinstall=" install -m 644 src/include/public/* \$(INCDIR)" +fi + cat > Makefile <<EOF # Monkey HTTP Daemon: Makefile # ============================ export monkey_root=\$(CURDIR) PREFIX=\$(DESTDIR)${prefix} BINDIR=\$(DESTDIR)${bindir} +LIBDIR=\$(DESTDIR)${libdir} +INCDIR=\$(DESTDIR)${incdir} MANDIR=\$(DESTDIR)${mandir} SYSCONFDIR=\$(DESTDIR)${sysconfdir} DATADIR=\$(DESTDIR)${datadir} LOGDIR=\$(DESTDIR)${logdir} PLUGINDIR=\$(DESTDIR)${plugdir} +VERSION=$VERSION -all: +all: monkey.pc @\$(MAKE) -s -C src all @\$(MAKE) -s -C plugins all @echo " DONE" @@ -343,6 +361,7 @@ all: clean: @(cd src; \$(MAKE) clean) @(cd plugins; \$(MAKE) clean) + @rm -f monkey.pc distclean: @(cd src; \$(MAKE) distclean) @@ -350,6 +369,8 @@ distclean: install: \$(MAKE) -C src all install -d \$(BINDIR) + install -d \$(LIBDIR)/pkgconfig + install -d \$(INCDIR) install -d \$(MANDIR)/man1 install -d \$(MANDIR)/man3 install -d \$(SYSCONFDIR) @@ -370,8 +391,13 @@ $plglist install -m 644 ./man/*.3 \$(MANDIR)/man3 install -m 644 ./htdocs/*.* \$(DATADIR) install -m 644 ./htdocs/imgs/*.* \${DATADIR}/imgs - $STRIP \$(BINDIR)/monkey - $STRIP \${PLUGINDIR}/* +$incinstall + -install -m 644 src/$SONAME \$(LIBDIR) + -install -m 644 monkey.pc \$(LIBDIR)/pkgconfig + -ln -sf $SONAME \$(LIBDIR)/libmonkey.so + -$STRIP --strip-unneeded \$(LIBDIR)/$SONAME + -$STRIP --strip-unneeded \$(BINDIR)/monkey + -$STRIP --strip-unneeded \${PLUGINDIR}/* @echo @echo " Running Monkey :" @echo " ----------------" @@ -381,6 +407,10 @@ $plglist @echo " For more help use '-h' option" @echo +monkey.pc: + @sed -e "s@PREFIX@$prefix@" -e "s@LIBDIR@$libdir@" -e "s@INCDIR@$incdir@" \ + -e "s@VERSION@$VERSION@" monkey.pc.in > monkey.pc + EOF } @@ -394,12 +424,19 @@ elif [ $platform == "android" ]; then libs="" fi +if [ -n "$sharedlib" ]; then + alltarget="../bin/monkey lib" +else + alltarget="../bin/monkey" +fi + cat > src/Makefile<<EOF _PATH = \$(patsubst \$(monkey_root)/%, %, \$(CURDIR)) CC = @echo " CC \$(_PATH)/\$@"; $CC CC_QUIET= @echo -n; $CC CFLAGS = $CFLAGS -DEFS = $DEFS +DEFS += $DEFS +LIBDEFS = -DSHAREDLIB -fPIC \$(DEFS) INCDIR = ./include LDFLAGS = $LDFLAGS DESTDIR = ../bin/monkey @@ -409,17 +446,25 @@ OBJ = monkey.o mk_method.o mk_mimetype.o mk_request.o \\ mk_user.o mk_utils.o mk_epoll.o mk_scheduler.o \\ mk_string.o mk_memory.o mk_connection.o mk_iov.o mk_http.o \\ mk_file.o mk_socket.o mk_clock.o mk_cache.o \\ - mk_server.o mk_plugin.o + mk_server.o mk_plugin.o mk_lib.o +LIBOBJ = \$(OBJ:.o=.lo) + +.PHONY: clean distclean lib -all: ../bin/monkey +all: $alltarget + +lib: $SONAME -include \$(OBJ:.o=.d) ../bin/monkey: \$(OBJ) \$(CC_QUIET) \$(CFLAGS) \$(DEFS) \$(LDFLAGS) -o \$@ \$(OBJ) $mod_obj \$(LIBS) +$SONAME: \$(LIBOBJ) + \$(CC_QUIET) \$(CFLAGS) \$(LIBDEFS) \$(LDFLAGS) -Wl,-soname,$SONAME -shared -o \$@ \$(LIBOBJ) $mod_obj \$(LIBS) + clean: - rm -rf *.[od] + rm -rf *.[od] $SONAME *.lo rm -rf ../bin/monkey distclean: @@ -431,6 +476,10 @@ distclean: .c.o: \$(CC) -c \$(CFLAGS) \$(DEFS) -I\$(INCDIR) \$< \$(CC_QUIET) -MM -MP \$(CFLAGS) \$(DEFS) -I\$(INCDIR) \$*.c -o \$*.d > /dev/null &2>&1 + +%.lo : %.c + \$(CC) -c -o \$@ \$(CFLAGS) \$(LIBDEFS) -I\$(INCDIR) \$< + EOF } @@ -589,9 +638,15 @@ cat > $INCDIR/mk_info.h <<EOF __MONKEY_PATCHLEVEL__) #define VERSION "$__MONKEY__.$__MONKEY_MINOR__.$__MONKEY_PATCHLEVEL__" #define MONKEY_PATH_CONF "$sysconfdir" +#define PLUGDIR "$plugdir" #endif EOF + +sed -i -e "s@#define MONKEY__.*@#define MONKEY__ $__MONKEY__@" \ +-e "s@#define MONKEY_MINOR__.*@#define MONKEY_MINOR__ $__MONKEY_MINOR__@" \ +-e "s@#define MONKEY_PATCHLEVEL__.*@#define MONKEY_PATCHLEVEL__ $__MONKEY_PATCHLEVEL__@" \ +$INCDIR/public/monkey.h } create_conf() @@ -600,6 +655,8 @@ cat > $INCDIR/config.path <<EOF #!/bin/sh prefix=$prefix bindir=$bindir +libdir=$libdir +incdir=$incdir sysconfdir=$sysconfdir datadir=$datadir logdir=$logdir @@ -729,6 +786,8 @@ aux=`pwd` prefix="$aux" bindir="$aux/bin" +libdir="$aux/lib" +incdir="" mandir="$aux/man" sysconfdir="$aux/conf" datadir="$aux/htdocs" @@ -756,6 +815,8 @@ for arg in $*; do --prefix*) prefix=$optarg bindir="$optarg/bin" + libdir="$optarg/lib" + incdir="$optarg/include" mandir="$optarg/man" sysconfdir="$optarg/conf" datadir="$optarg/htdocs" @@ -774,6 +835,12 @@ for arg in $*; do --datadir*) datadir=$optarg ;; + --libdir*) + libdir=$optarg + ;; + --incdir*) + incdir=$optarg + ;; --logdir*) logdir=$optarg ;; @@ -786,6 +853,12 @@ for arg in $*; do --trace*) trace=1 ;; + --enable-shared*) + sharedlib=1 + ;; + --enable-relaxed-plugins*) + relaxed_plugins=1 + ;; --enable-plugins*) enabled_plugins=$optarg ;; @@ -831,9 +904,16 @@ for arg in $*; do echo " --trace Enable trace messages (don't use in production)" echo " --platform=PLATFORM Target platform: 'generic' or 'android' (default: generic)" echo + echo "Shared library options:" + echo " --enable-shared Build Monkey as a shared library in addition to a stand-alone server" + echo " --enable-relaxed-plugins Allow the application to make the library load arbitrary plugins." + echo " WARNING security risk, do not enable in distro packages!" + echo echo "Installation Directories:" echo " --prefix=PREFIX Root prefix directory" echo " --bindir=BINDIR Binary files (executables)" + echo " --libdir=LIBDIR Libraries" + echo " --incdir=INCDIR Header install path" echo " --sysconfdir=SYSCONFDIR Configuration files" echo " --datadir=DATADIR Specific Monkey data files" echo " --mandir=MANDIR Manpages - documentation" @@ -889,11 +969,13 @@ if test -z "$STRIP" ; then STRIP="strip" fi +[ -n "$relaxed_plugins" ] && DEFS="$DEFS -DRELAXED_PLUGINS" + if test -z "$debug" ; then - CFLAGS="$CFLAGS -O2 -Wall" + CFLAGS="$CFLAGS -O2 -Wall -Wextra" else DEFS="-DDEBUG -DSAFE_FREE" - CFLAGS="$CFLAGS -g -Wall" + CFLAGS="$CFLAGS -g -Wall -Wextra" fi CFLAGS="$CFLAGS -fvisibility=hidden" diff --git a/src/include/mk_lib.h b/src/include/mk_lib.h new file mode 100644 index 0000000..f57ec45 --- /dev/null +++ b/src/include/mk_lib.h @@ -0,0 +1,45 @@ +/* Monkey HTTP Daemon + * ------------------ + * Copyright (C) 2001-2012, Eduardo Silva P. <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef MK_LIB_H +#define MK_LIB_H + +#include "mk_macros.h" +#include "public/monkey.h" + +/* Data */ + +struct mklib_ctx_t { + pthread_t tid; + pthread_t clock; + pthread_t *workers; + + cb_ipcheck ipf; + cb_urlcheck urlf; + cb_data dataf; + cb_close closef; + + struct mklib_worker_info **worker_info; + + const char *plugdir; + + int lib_running; +}; + +#endif diff --git a/src/include/mk_mimetype.h b/src/include/mk_mimetype.h index 1d02159..a81e922 100644 --- a/src/include/mk_mimetype.h +++ b/src/include/mk_mimetype.h @@ -34,9 +34,17 @@ struct mimetype mk_pointer type; }; -struct mimetype *mimetype_default; +/* amount of the top used mime types */ +enum { + MIME_COMMON=10 +}; + +extern struct mimetype *mimetype_default; +int mk_mimetype_add(const char *name, const char *type, const int common); void mk_mimetype_read_config(void); struct mimetype *mk_mimetype_find(mk_pointer * filename); +inline struct mimetype *mk_mimetype_lookup(const char *name); +void mk_mimearr_sort(); #endif diff --git a/src/include/mk_plugin.h b/src/include/mk_plugin.h index 2ad7a5a..d6816ae 100644 --- a/src/include/mk_plugin.h +++ b/src/include/mk_plugin.h @@ -308,6 +308,7 @@ struct plugin_info { }; void mk_plugin_init(); +void mk_plugin_read_config(); void mk_plugin_exit_all(); void mk_plugin_event_init_list(); @@ -337,6 +338,7 @@ int mk_plugin_event_error(int socket); int mk_plugin_event_close(int socket); int mk_plugin_event_timeout(int socket); +void *mk_plugin_load(const char *path); void mk_plugin_register_to(struct plugin **st, struct plugin *p); void *mk_plugin_load_symbol(void *handler, const char *symbol); int mk_plugin_http_request_end(int socket); diff --git a/src/include/mk_scheduler.h b/src/include/mk_scheduler.h index b3a25f1..9a687e8 100644 --- a/src/include/mk_scheduler.h +++ b/src/include/mk_scheduler.h @@ -25,6 +25,7 @@ #include <arpa/inet.h> #include "mk_list.h" +#include "mk_lib.h" #ifndef MK_SCHEDULER_H #define MK_SCHEDULER_H @@ -59,6 +60,9 @@ struct sched_list_node unsigned char initialized; struct client_session *request_handler; +#ifdef SHAREDLIB + mklib_ctx ctx; +#endif }; extern struct sched_list_node *sched_list; @@ -69,6 +73,9 @@ typedef struct int epoll_fd; int epoll_max_events; int max_events; +#ifdef SHAREDLIB + mklib_ctx ctx; +#endif } sched_thread_conf; extern pthread_key_t worker_sched_node; @@ -76,7 +83,7 @@ extern pthread_key_t worker_sched_node; extern pthread_mutex_t mutex_worker_init; void mk_sched_init(); -int mk_sched_launch_thread(int max_events, pthread_t *tout); +int mk_sched_launch_thread(int max_events, pthread_t *tout, mklib_ctx ctx); void *mk_sched_launch_epoll_loop(void *thread_conf); struct sched_list_node *mk_sched_get_handler_owner(void); diff --git a/src/include/public/monkey.h b/src/include/public/monkey.h new file mode 100644 index 0000000..b1526aa --- /dev/null +++ b/src/include/public/monkey.h @@ -0,0 +1,191 @@ +/* Monkey HTTP Daemon + * ------------------ + * Copyright (C) 2001-2012, Eduardo Silva P. <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef MK_MONKEYLIB_H +#define MK_MONKEYLIB_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <pthread.h> + +#if __GNUC__ >= 4 + #define NULL_TERMINATED __attribute__ ((sentinel)) +#else + #define NULL_TERMINATED +#endif + +/* For the internal build */ +#ifdef SHAREDLIB + #include <mk_macros.h> +#else + #ifndef MK_EXPORT + #define MK_EXPORT + #endif +#endif + +#define MONKEY__ +#define MONKEY_MINOR__ +#define MONKEY_PATCHLEVEL__ + +/* --------------------------------- + * Data + * --------------------------------- */ + +/* Opaque pointer, not for use for the apps */ +typedef struct mklib_ctx_t* mklib_ctx; + +enum { + MKLIB_FALSE = 0, + MKLIB_TRUE = 1 +}; + +struct mklib_vhost { + const char *name; + const char *document_root; + const char *server_names; +}; + +struct mklib_worker_info { + unsigned long long active_connections; + int pid; +}; + +struct mklib_mime { + const char *name; + const char *type; +}; + +/* Supported plugins, OR'ed in the init call */ +enum { + MKLIB_LIANA = 0x1, + MKLIB_LIANA_SSL = 0x2 +}; + +/* Config options for the main config call */ +enum mklib_mkc { + MKC_WORKERS = 1, + MKC_TIMEOUT, + MKC_USERDIR, + MKC_INDEXFILE, + MKC_HIDEVERSION, + MKC_RESUME, + MKC_KEEPALIVE, + MKC_KEEPALIVETIMEOUT, + MKC_MAXKEEPALIVEREQUEST, + MKC_MAXREQUESTSIZE, + MKC_SYMLINK, + MKC_DEFAULTMIMETYPE +}; + +/* Config options for the vhost config call */ +enum mklib_mkv { + MKV_SERVERNAME = 1, + MKV_DOCUMENTROOT +}; + +/* Callbacks */ +enum mklib_cb { + MKCB_IPCHECK = 1, + MKCB_URLCHECK, + MKCB_DATA, + MKCB_CLOSE +}; + +/* struct session_request need not be exposed */ +typedef void mklib_session; + +/* Called when a new connection arrives. Return MKLIB_FALSE to reject this connection. */ +typedef int (*cb_ipcheck)(const char *ip); + +/* Called when the URL is known. Return MKLIB_FALSE to reject this connection. */ +typedef int (*cb_urlcheck)(const char *url); + +/* The data callback. Return MKLIB_FALSE if you don't want to handle this URL + * (it will be checked against real files at this vhost's DocumentRoot). + * + * Set *content to point to the content memory. It must + * stay available until the close callback is called. + * + * *header has static storage of 256 bytes for any custom headers. */ +typedef int (*cb_data)(const mklib_session *, const char *vhost, const char *url, + const char *get, unsigned long get_len, const char *post, unsigned long post_len, + unsigned int *status, const char **content, unsigned long *clen, + char *header); + +/* This will be called after the content has been served. If you allocated + * any memory, you can match that memory to the mklib_session pointer and free + * it in this callback. */ +typedef void (*cb_close)(const mklib_session *); + + +/* --------------------------------- + * API + * --------------------------------- */ + +/* Returns NULL on error. All pointer arguments may be NULL and the port/plugins + * may be 0 for the defaults in each case. + * + * With no address, bind to all. + * With no port, use 2001. + * With no plugins, default to MKLIB_LIANA only. + * With no documentroot, the default vhost won't access files. + */ +mklib_ctx MK_EXPORT mklib_init(const char *address, const unsigned int port, + const unsigned int plugins, const char *documentroot); + +/* Set the callbacks. */ +int MK_EXPORT mklib_callback_set(mklib_ctx, const enum mklib_cb, void *); + +/* NULL-terminated config call, consisting of pairs of config item and argument. + * Returns MKLIB_FALSE on failure. */ +int MK_EXPORT mklib_config(mklib_ctx, ...) NULL_TERMINATED; + +/* NULL-terminated config call creating a vhost with *name. Returns MKLIB_FALSE + * on failure. */ +int MK_EXPORT mklib_vhost_config(mklib_ctx, const char *name, ...) NULL_TERMINATED; + +/* Start the server. */ +int MK_EXPORT mklib_start(mklib_ctx); + +/* Stop the server and free mklib_ctx. */ +int MK_EXPORT mklib_stop(mklib_ctx); + +/* Return a list of existing vhosts */ +struct mklib_vhost MK_EXPORT **mklib_vhost_list(mklib_ctx); + +/* Return a list of the workers */ +struct mklib_worker_info MK_EXPORT **mklib_scheduler_worker_info(mklib_ctx); + +/* Return a list of all mimetypes */ +struct mklib_mime MK_EXPORT **mklib_mimetype_list(mklib_ctx); + +/* Add a new mimetype */ +int MK_EXPORT mklib_mimetype_add(mklib_ctx, const char *, const char *); + +#define mklib_vhost_foreach(cur, list) for(cur = *list++; cur; cur = *list++) +#define mklib_worker_info_foreach(cur, list) mklib_vhost_foreach(cur, list) +#define mklib_mimetype_foreach(cur, list) mklib_vhost_foreach(cur, list) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/mk_clock.c b/src/mk_clock.c index 7016864..b048a8a 100644 --- a/src/mk_clock.c +++ b/src/mk_clock.c @@ -81,7 +81,7 @@ static void mk_clock_header_set_time(time_t utime) header_current_time.data = time_string; } -void *mk_clock_worker_init(void *args) +void *mk_clock_worker_init(void *args UNUSED_PARAM) { time_t cur_time; diff --git a/src/mk_config.c b/src/mk_config.c index 16c2c34..79d230f 100644 --- a/src/mk_config.c +++ b/src/mk_config.c @@ -45,14 +45,6 @@ #include "mk_plugin.h" #include "mk_macros.h" -/* Print a specific error */ -static void mk_config_print_error_msg(char *variable, char *path) -{ - mk_err("Error in %s variable under %s, has an invalid value", - variable, path); - exit(EXIT_FAILURE); -} - struct server_config *config; /* Raise a configuration schema error */ @@ -363,6 +355,16 @@ void *mk_config_section_getval(struct mk_config_section *section, char *key, int return NULL; } +#ifndef SHAREDLIB + +/* Print a specific error */ +static void mk_config_print_error_msg(char *variable, char *path) +{ + mk_err("Error in %s variable under %s, has an invalid value", + variable, path); + exit(EXIT_FAILURE); +} + /* Read configuration files */ static void mk_config_read_files(char *path_conf, char *file_conf) { @@ -710,6 +712,33 @@ struct host *mk_config_get_host(char *path) return host; } +/* read main configuration from monkey.conf */ +void mk_config_start_configure(void) +{ + unsigned long len; + + mk_config_set_init_values(); + mk_config_read_files(config->file_config, M_DEFAULT_CONFIG_FILE); + + /* Load mimes */ + mk_mimetype_read_config(); + + mk_pointer_reset(&config->server_software); + + /* Basic server information */ + if (config->hideversion == MK_FALSE) { + mk_string_build(&config->server_software.data, + &len, "Monkey/%s (%s)", VERSION, OS); + config->server_software.len = len; + } + else { + mk_string_build(&config->server_software.data, &len, "Monkey Server"); + config->server_software.len = len; + } +} + +#endif // !SHAREDLIB + void mk_config_set_init_values(void) { /* Init values */ @@ -758,31 +787,6 @@ void mk_config_set_init_values(void) mk_list_init(config->plugins); } -/* read main configuration from monkey.conf */ -void mk_config_start_configure(void) -{ - unsigned long len; - - mk_config_set_init_values(); - mk_config_read_files(config->file_config, M_DEFAULT_CONFIG_FILE); - - /* Load mimes */ - mk_mimetype_read_config(); - - mk_pointer_reset(&config->server_software); - - /* Basic server information */ - if (config->hideversion == MK_FALSE) { - mk_string_build(&config->server_software.data, - &len, "Monkey/%s (%s)", VERSION, OS); - config->server_software.len = len; - } - else { - mk_string_build(&config->server_software.data, &len, "Monkey Server"); - config->server_software.len = len; - } -} - int mk_config_host_find(mk_pointer host, struct host **vhost, struct host_alias **alias) { struct host *entry_host; diff --git a/src/mk_lib.c b/src/mk_lib.c new file mode 100644 index 0000000..274fc73 --- /dev/null +++ b/src/mk_lib.c @@ -0,0 +1,624 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Monkey HTTP Daemon + * ------------------ + * Copyright (C) 2012, Lauri Kasanen <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* Only built for the library */ +#ifdef SHAREDLIB + +#include <stdio.h> +#include <mk_lib.h> +#include <mk_utils.h> +#include <mk_memory.h> +#include <mk_config.h> +#include <mk_info.h> +#include <mk_string.h> +#include <mk_plugin.h> +#include <dlfcn.h> +#include <mk_clock.h> +#include <mk_mimetype.h> +#include <mk_server.h> +#include <stdarg.h> +#include <limits.h> + +/* These are only needed here, not public for all of monkey */ +extern int mime_nitem; +extern struct mimetype *mimecommon, *mimearr; + +static struct host *mklib_host_find(const char *name) +{ + struct host *entry_host; + const struct mk_list *head_vhost; + + mk_list_foreach(head_vhost, &config->hosts) { + entry_host = mk_list_entry(head_vhost, struct host, _head); + + if (strcmp(name, entry_host->file) == 0) return entry_host; + } + + return NULL; +} + + +static void mklib_run(void *p) +{ + int remote_fd, ret; + const mklib_ctx ctx = p; + + mk_utils_worker_rename("libmonkey"); + mk_socket_set_tcp_defer_accept(config->server_fd); + + while (1) { + + if (!ctx->lib_running) { + sleep(1); + continue; + } + + remote_fd = mk_socket_accept(config->server_fd); + if (remote_fd == -1) continue; + + ret = mk_sched_add_client(remote_fd); + if (ret == -1) close(remote_fd); + } +} + +static int load_networking(const char *path) +{ + void *handle; + struct plugin *p; + int ret; + + handle = mk_plugin_load(path); + if (!handle) return MKLIB_FALSE; + + p = mk_plugin_alloc(handle, path); + if (!p) { + dlclose(handle); + return MKLIB_FALSE; + } + + ret = p->init(&api, ""); + if (ret < 0) { + mk_plugin_free(p); + dlclose(handle); + return MKLIB_FALSE; + } + + mk_plugin_register(p); + return MKLIB_TRUE; +} + +int mklib_callback_set(mklib_ctx ctx, const enum mklib_cb cb, void *func) +{ + /* Function is allowed to be NULL, to reset it) */ + if (!ctx || !cb || ctx->lib_running) return MKLIB_FALSE; + + switch(cb) { + case MKCB_IPCHECK: + ctx->ipf = func; + break; + case MKCB_URLCHECK: + ctx->urlf = func; + break; + case MKCB_DATA: + ctx->dataf = func; + break; + case MKCB_CLOSE: + ctx->closef = func; + break; + default: + return MKLIB_FALSE; + break; + } + + return MKLIB_TRUE; +} + +/* Returns NULL on error. All pointer arguments may be NULL and the port/plugins + * may be 0 for the defaults in each case. + * + * With no address, bind to all. + * With no port, use 2001. + * With no plugins, default to MKLIB_LIANA only. + * With no documentroot, the default vhost won't access files. + */ +mklib_ctx mklib_init(const char *address, const unsigned int port, + const unsigned int plugins, const char *documentroot) +{ + mklib_ctx a = mk_mem_malloc_z(sizeof(struct mklib_ctx_t)); + if (!a) return NULL; + + config = mk_mem_malloc_z(sizeof(struct server_config)); + if (!config) goto out; + + config->serverconf = strdup(MONKEY_PATH_CONF); + mk_config_set_init_values(); + mk_sched_init(); + mk_plugin_init(); + + a->plugdir = PLUGDIR; + + char tmppath[PATH_MAX]; + + if (plugins & MKLIB_LIANA_SSL) { + config->transport_layer = strdup("liana_ssl"); + snprintf(tmppath, PATH_MAX, "%s/monkey-liana_ssl.so", a->plugdir); + if (!load_networking(tmppath)) goto out_config; + } + else { + config->transport_layer = strdup("liana"); + snprintf(tmppath, PATH_MAX, "%s/monkey-liana.so", a->plugdir); + if (!load_networking(tmppath)) goto out_config; + } + + if (!plg_netiomap) goto out_config; + mk_plugin_preworker_calls(); + + if (port) config->serverport = port; + if (address) config->listen_addr = strdup(address); + else config->listen_addr = strdup(config->listen_addr); + + unsigned long len; + struct host *host = mk_mem_malloc_z(sizeof(struct host)); + /* We hijack this field for the vhost name */ + host->file = strdup("default"); + mk_list_init(&host->error_pages); + mk_list_init(&host->server_names); + mk_string_build(&host->host_signature, &len, "libmonkey"); + mk_string_build(&host->header_host_signature.data, + &host->header_host_signature.len, + "Server: %s", host->host_signature); + + struct host_alias *alias = mk_mem_malloc_z(sizeof(struct host_alias)); + alias->name = strdup(config->listen_addr); + alias->len = strlen(config->listen_addr); + mk_list_add(&alias->_head, &host->server_names); + + mk_list_add(&host->_head, &config->hosts); + config->nhosts++; + + if (documentroot) { + host->documentroot.data = strdup(documentroot); + host->documentroot.len = strlen(documentroot); + } + else { + host->documentroot.data = strdup("/dev/null"); + host->documentroot.len = sizeof("/dev/null") - 1; + } + + config->server_software.data = ""; + config->server_software.len = 0; + config->default_mimetype = mk_string_dup(MIMETYPE_DEFAULT_TYPE); + mk_mimetype_read_config(); + + config->worker_capacity = mk_server_worker_capacity(config->workers); + config->max_load = (config->worker_capacity * config->workers); + + /* Server listening socket */ + config->server_fd = mk_socket_server(config->serverport, config->listen_addr); + + /* Clock thread */ + mk_clock_sequential_init(); + a->clock = mk_utils_worker_spawn((void *) mk_clock_worker_init, NULL); + + mk_mem_pointers_init(); + mk_thread_keys_init(); + + return a; + + out_config: + free(config); + + out: + free(a); + + return NULL; +} + +/* NULL-terminated config call, consisting of pairs of config item and argument. + * Returns MKLIB_FALSE on failure. */ +int mklib_config(mklib_ctx ctx, ...) +{ + if (!ctx || ctx->lib_running) return MKLIB_FALSE; + + unsigned long len; + int i; + char *s; + va_list va; + + va_start(va, ctx); + + i = va_arg(va, int); + while (i) { + const enum mklib_mkc e = i; + + switch(e) { + case MKC_WORKERS: + i = va_arg(va, int); + config->workers = i; + config->worker_capacity = mk_server_worker_capacity(config->workers); + config->max_load = (config->worker_capacity * config->workers); + + free(sched_list); + mk_sched_init(); + break; + case MKC_TIMEOUT: + i = va_arg(va, int); + config->timeout = i; + break; + case MKC_USERDIR: + s = va_arg(va, char *); + if (config->user_dir) free(config->user_dir); + config->user_dir = strdup(s); + break; + case MKC_INDEXFILE: + s = va_arg(va, char *); + if (config->index_files) mk_string_split_free(config->index_files); + config->index_files = mk_string_split_line(s); + break; + case MKC_HIDEVERSION: + i = va_arg(va, int); + config->server_software.data = NULL; + + /* Basic server information */ + if (!i) { + mk_string_build(&config->server_software.data, + &len, "libmonkey/%s (%s)", VERSION, OS); + } + else { + mk_string_build(&config->server_software.data, &len, "libmonkey"); + } + config->server_software.len = len; + + /* Mark it so for the default vhost */ + struct mk_list *hosts = &config->hosts; + struct host *def = mk_list_entry_first(hosts, struct host, _head); + free(def->host_signature); + free(def->header_host_signature.data); + def->header_host_signature.data = NULL; + + def->host_signature = strdup(config->server_software.data); + mk_string_build(&def->header_host_signature.data, + &def->header_host_signature.len, + "Server: %s", def->host_signature); + break; + case MKC_RESUME: + i = va_arg(va, int); + config->resume = i ? MK_TRUE : MK_FALSE; + break; + case MKC_KEEPALIVE: + i = va_arg(va, int); + config->keep_alive = i ? MK_TRUE : MK_FALSE; + break; + case MKC_KEEPALIVETIMEOUT: + i = va_arg(va, int); + config->keep_alive_timeout = i; + break; + case MKC_MAXKEEPALIVEREQUEST: + i = va_arg(va, int); + config->max_keep_alive_request = i; + break; + case MKC_MAXREQUESTSIZE: + i = va_arg(va, int); + config->max_request_size = i; + break; + case MKC_SYMLINK: + i = va_arg(va, int); + config->symlink = i ? MK_TRUE : MK_FALSE; + break; + case MKC_DEFAULTMIMETYPE: + s = va_arg(va, char *); + free(config->default_mimetype); + config->default_mimetype = NULL; + mk_string_build(&config->default_mimetype, &len, "%s\r\n", s); + mk_pointer_set(&mimetype_default->type, config->default_mimetype); + break; + default: + mk_warn("Unknown config option"); + break; + } + + i = va_arg(va, int); + } + + va_end(va); + return MKLIB_TRUE; +} + +/* NULL-terminated config call creating a vhost with *name. Returns MKLIB_FALSE + * on failure. */ +int mklib_vhost_config(mklib_ctx ctx, const char *name, ...) +{ + if (!ctx) return MKLIB_FALSE; + + /* Does it exist already? */ + struct host *h = mklib_host_find(name); + if (h) return MKLIB_FALSE; + + const struct host *defaulth = mklib_host_find("default"); + if (!defaulth) return MKLIB_FALSE; + + + h = mk_mem_malloc_z(sizeof(struct host)); + h->file = strdup(name); + + h->documentroot.data = strdup("/dev/null"); + h->documentroot.len = sizeof("/dev/null") - 1; + + mk_list_init(&h->error_pages); + mk_list_init(&h->server_names); + + char *s; + int i; + va_list va; + + va_start(va, name); + + i = va_arg(va, int); + while (i) { + const enum mklib_mkv e = i; + + switch(e) { + case MKV_SERVERNAME: + s = va_arg(va, char *); + + struct mk_list *head, *list = mk_string_split_line(s); + + mk_list_foreach(head, list) { + struct mk_string_line *entry = mk_list_entry(head, + struct mk_string_line, + _head); + if (entry->len > MK_HOSTNAME_LEN - 1) { + continue; + } + + struct host_alias *alias = mk_mem_malloc_z(sizeof(struct host_alias)); + alias->name = mk_string_tolower(entry->val); + alias->len = entry->len; + mk_list_add(&alias->_head, &h->server_names); + } + + mk_string_split_free(list); + break; + case MKV_DOCUMENTROOT: + s = va_arg(va, char *); + free(h->documentroot.data); + h->documentroot.data = strdup(s); + h->documentroot.len = strlen(s); + break; + default: + mk_warn("Unknown config option"); + break; + } + + i = va_arg(va, int); + } + + h->host_signature = strdup(defaulth->host_signature); + h->header_host_signature.data = strdup(defaulth->header_host_signature.data); + h->header_host_signature.len = defaulth->header_host_signature.len; + + mk_list_add(&h->_head, &config->hosts); + config->nhosts++; + + va_end(va); + return MKLIB_TRUE; +} + +/* Start the server. */ +int mklib_start(mklib_ctx ctx) +{ + if (!ctx || ctx->lib_running) return MKLIB_FALSE; + + mk_plugin_core_process(); + + ctx->workers = mk_mem_malloc_z(sizeof(pthread_t) * config->workers); + + unsigned int i; + const unsigned int workers = config->workers; + for (i = 0; i < workers; i++) { + mk_sched_launch_thread(config->worker_capacity, &ctx->workers[i], ctx); + } + + /* Wait until all workers report as ready */ + while (1) { + unsigned int ready = 0; + + pthread_mutex_lock(&mutex_worker_init); + for (i = 0; i < workers; i++) { + if (sched_list[i].initialized) + ready++; + } + pthread_mutex_unlock(&mutex_worker_init); + + if (ready == workers) break; + usleep(10000); + } + + ctx->worker_info = mk_mem_malloc_z(sizeof(struct mklib_worker_info *) * (workers + 1)); + for(i = 0; i < workers; i++) { + ctx->worker_info[i] = mk_mem_malloc_z(sizeof(struct mklib_worker_info)); + ctx->worker_info[i]->pid = sched_list[i].pid; + } + + ctx->lib_running = 1; + ctx->tid = mk_utils_worker_spawn(mklib_run, ctx); + + return MKLIB_TRUE; +} + +/* Stop the server and free mklib_ctx. */ +int mklib_stop(mklib_ctx ctx) +{ + if (!ctx || !ctx->lib_running) return MKLIB_FALSE; + + ctx->lib_running = 0; + pthread_cancel(ctx->tid); + + int i; + for (i = 0; i < config->workers; i++) { + pthread_cancel(ctx->workers[i]); + free(ctx->worker_info[i]); + } + free(ctx->worker_info); + + mk_plugin_exit_all(); + +#ifdef SAFE_FREE + mk_config_free_all(); +#else + free(config); +#endif + + free(ctx); + + return MKLIB_TRUE; +} + +struct mklib_vhost **mklib_vhost_list(mklib_ctx ctx) +{ + static struct mklib_vhost **lst = NULL; + struct host *entry_host; + struct host_alias *alias; + struct mk_list *head_vhost, *head_aliases; + unsigned int i, total = 0, namecount; + const char *names[50]; + + if (!ctx) return NULL; + + /* Free it if it exists */ + if (lst) { + for (i = 0; lst[i]; i++) { + free((char *) lst[i]->server_names); + free(lst[i]); + } + + free(lst); + } + + /* How many are there? */ + mk_list_foreach(head_vhost, &config->hosts) { + total++; + } + total++; + + lst = mk_mem_malloc_z(sizeof(struct mklib_vhost *) * total); + + total = 0; + + /* Set up the list to return */ + mk_list_foreach(head_vhost, &config->hosts) { + entry_host = mk_list_entry(head_vhost, struct host, _head); + + lst[total] = mk_mem_malloc_z(sizeof(struct mklib_vhost)); + + lst[total]->name = entry_host->file; + lst[total]->document_root = entry_host->documentroot.data; + + namecount = 0; + unsigned int total_len = 1; + mk_list_foreach(head_aliases, &entry_host->server_names) { + alias = mk_list_entry(head_aliases, struct host_alias, _head); + names[namecount] = alias->name; + namecount++; + total_len += alias->len + 1; + } + + char *servernames = mk_mem_malloc_z(total_len); + for (i = 0; i < namecount; i++) { + strcat(servernames, names[i]); + strcat(servernames, " "); + } + + lst[total]->server_names = servernames; + + total++; + } + + return lst; +} + +struct mklib_worker_info **mklib_scheduler_worker_info(mklib_ctx ctx) +{ + unsigned int i; + const unsigned int workers = config->workers; + + if (!ctx || !ctx->lib_running) return NULL; + + + for (i = 0; i < workers; i++) { + ctx->worker_info[i]->active_connections = sched_list[i].accepted_connections - + sched_list[i].closed_connections; + } + + return ctx->worker_info; +} + +/* Return a list of all mimetypes */ +struct mklib_mime **mklib_mimetype_list(mklib_ctx ctx) +{ + if (!ctx) return NULL; + + static struct mklib_mime **lst = NULL; + unsigned int i; + const unsigned int total = mime_nitem + MIME_COMMON; + + if (lst) { + for (i = 0; i < total; i++) { + free(lst[i]); + } + + free(lst); + } + + lst = mk_mem_malloc_z((total + 1) * sizeof(struct mklib_mime *)); + + for (i = 0; i < total; i++) { + lst[i] = mk_mem_malloc_z(sizeof(struct mklib_mime)); + + if (i < MIME_COMMON) { + lst[i]->name = mimecommon[i].name; + lst[i]->type = mimecommon[i].type.data; + } + else { + const unsigned int m = i - MIME_COMMON; + lst[i]->name = mimearr[m].name; + lst[i]->type = mimearr[m].type.data; + } + } + + return lst; +} + +/* Add a new mimetype */ +int mklib_mimetype_add(mklib_ctx ctx, const char *name, const char *type) +{ + if (!ctx || !name || !type) return MKLIB_FALSE; + + /* Is it added already? */ + if (mk_mimetype_lookup(name)) return MKLIB_FALSE; + + mk_mimetype_add(name, type, 0); + mk_mimearr_sort(); + + return MKLIB_TRUE; +} + +#endif diff --git a/src/mk_mimetype.c b/src/mk_mimetype.c index c5f574c..94cea47 100644 --- a/src/mk_mimetype.c +++ b/src/mk_mimetype.c @@ -36,18 +36,16 @@ #include "mk_list.h" #include "mk_macros.h" -/* amount of the top used mime types */ -#define MIME_COMMON 10 - -static struct mimetype *mimecommon = NULL; /* old top used mime types */ -static struct mimetype *mimearr = NULL; /* old the rest of the mime types */ -static int nitem = 0; /* amount of available mime types */ +struct mimetype *mimetype_default; +struct mimetype *mimecommon = NULL; /* old top used mime types */ +struct mimetype *mimearr = NULL; /* old the rest of the mime types */ +int mime_nitem = 0; /* amount of available mime types */ /* add an item to the mimecommon or mimearr variables */ #define add_mime(item, m) ({ \ - m = (nitem==0) ? mk_mem_malloc(sizeof(struct mimetype)) : \ - mk_mem_realloc(m, (nitem + 1) * (sizeof(struct mimetype))); \ - m[nitem++] = item; \ + m = (mime_nitem==0) ? mk_mem_malloc(sizeof(struct mimetype)) : \ + mk_mem_realloc(m, (mime_nitem + 1) * (sizeof(struct mimetype))); \ + m[mime_nitem++] = item; \ }) static int mime_cmp(const void *m1, const void *m2) @@ -59,7 +57,7 @@ static int mime_cmp(const void *m1, const void *m2) } /* Match mime type for requested resource */ -static inline struct mimetype *mk_mimetype_lookup(char *name) +inline struct mimetype *mk_mimetype_lookup(const char *name) { int i; struct mimetype tmp; @@ -79,10 +77,10 @@ static inline struct mimetype *mk_mimetype_lookup(char *name) } tmp.name = name; - return bsearch(&tmp, mimearr, nitem, sizeof(struct mimetype), mime_cmp); + return bsearch(&tmp, mimearr, mime_nitem, sizeof(struct mimetype), mime_cmp); } -static int mk_mimetype_add(char *name, char *type, int common) +int mk_mimetype_add(const char *name, const char *type, const int common) { int len = strlen(type) + 3; struct mimetype new_mime; @@ -131,7 +129,7 @@ void mk_mimetype_read_config() } else { if (i == MIME_COMMON) { - nitem = 0; /* reset counter */ + mime_nitem = 0; /* reset counter */ } if (mk_mimetype_add(entry->key, entry->val, 0) != 0) { mk_err("Error loading Mime Types"); @@ -140,9 +138,7 @@ void mk_mimetype_read_config() i++; } - - /* sort ascendingly for later binary search */ - qsort(mimearr, nitem, sizeof(struct mimetype), mime_cmp); + mk_mimearr_sort(); /* Set default mime type */ mimetype_default = mk_mem_malloc_z(sizeof(struct mimetype)); @@ -152,6 +148,12 @@ void mk_mimetype_read_config() mk_config_free(cnf); } +void mk_mimearr_sort() +{ + /* sort ascendingly for later binary search */ + qsort(mimearr, mime_nitem, sizeof(struct mimetype), mime_cmp); +} + struct mimetype *mk_mimetype_find(mk_pointer * filename) { int j, len; diff --git a/src/mk_plugin.c b/src/mk_plugin.c index f165dd8..4ab9f8c 100644 --- a/src/mk_plugin.c +++ b/src/mk_plugin.c @@ -34,6 +34,10 @@ #include "mk_plugin.h" #include "mk_macros.h" +enum { + bufsize = 256 +}; + pthread_key_t mk_plugin_event_k; static struct plugin_stagemap *plg_stagemap; @@ -299,17 +303,6 @@ void mk_plugin_free(struct plugin *p) void mk_plugin_init() { - int ret; - char *path; - char *plugin_confdir = 0; - void *handle; - unsigned long len; - struct plugin *p; - struct mk_config *cnf; - struct mk_config_section *section; - struct mk_config_entry *entry; - struct mk_list *head; - api = mk_mem_malloc_z(sizeof(struct plugin_api)); __builtin_prefetch(api); @@ -421,6 +414,24 @@ void mk_plugin_init() api->stacktrace = (void *) mk_utils_stacktrace; #endif + api->plugins = config->plugins; +} + +#ifndef SHAREDLIB + +void mk_plugin_read_config() +{ + int ret; + char *path; + char *plugin_confdir = 0; + void *handle; + unsigned long len; + struct plugin *p; + struct mk_config *cnf; + struct mk_config_section *section; + struct mk_config_entry *entry; + struct mk_list *head; + /* Read configuration file */ path = mk_mem_malloc_z(1024); snprintf(path, 1024, "%s/%s", config->serverconf, MK_PLUGIN_LOAD); @@ -491,14 +502,14 @@ void mk_plugin_init() exit(EXIT_FAILURE); } - api->plugins = config->plugins; - /* Look for plugins thread key data */ mk_plugin_preworker_calls(); mk_mem_free(path); mk_config_free(cnf); } +#endif //!SHAREDLIB + /* Invoke all plugins 'exit' hook and free resources by the plugin interface */ void mk_plugin_exit_all() { @@ -530,6 +541,30 @@ int mk_plugin_stage_run(unsigned int hook, int ret; struct plugin_stagem *stm; +#ifdef SHAREDLIB + struct sched_list_node *thconf = mk_sched_get_thread_conf(); + mklib_ctx ctx = thconf->ctx; + char buf[bufsize], *ptr = buf; + unsigned long len; + + if (hook & MK_PLUGIN_STAGE_10 && ctx->ipf) { + mk_socket_ip_str(socket, &ptr, bufsize, &len); + ret = ctx->ipf(buf); + if (ret == MKLIB_FALSE) return MK_PLUGIN_RET_CLOSE_CONX; + } + + if (hook & MK_PLUGIN_STAGE_20 && ctx->urlf) { + len = sr->uri.len; + if (len >= bufsize) len = bufsize - 1; + strncpy(buf, sr->uri.data, len); + buf[len] = '\0'; + + ret = ctx->urlf(buf); + if (ret == MKLIB_FALSE) return MK_PLUGIN_RET_CLOSE_CONX; + } + +#endif + /* Connection just accept(ed) not assigned to worker thread */ if (hook & MK_PLUGIN_STAGE_10) { stm = plg_stagemap->stage_10; @@ -623,6 +658,66 @@ int mk_plugin_stage_run(unsigned int hook, } } +#ifdef SHAREDLIB + + if (hook & MK_PLUGIN_STAGE_30 && ctx->dataf) { + unsigned int status = 200; + unsigned long clen, get_len = 0, post_len = 0; + const char *content; + char *get = NULL, *post = NULL; + char header[bufsize] = ""; + + if (sr->query_string.data) { + get = mk_mem_malloc_z(sr->query_string.len + 1); + memcpy(get, sr->query_string.data, sr->query_string.len); + get_len = sr->query_string.len; + } + if (sr->data.data) { + post = mk_mem_malloc_z(sr->data.len + 1); + memcpy(post, sr->data.data, sr->data.len); + post_len = sr->data.len; + } + + len = sr->uri.len; + if (len >= bufsize) len = bufsize - 1; + strncpy(buf, sr->uri.data, len); + buf[len] = '\0'; + + ret = ctx->dataf(sr, sr->host_conf->file, buf, + get, get_len, post, post_len, + &status, &content, &clen, header); + mk_mem_free(get); + mk_mem_free(post); + + if (ret == MKLIB_FALSE) return -1; + + /* Status */ + api->header_set_http_status(sr, status); + + /* Headers */ + sr->headers.content_length = clen; + len = strlen(header); + if (len) api->header_add(sr, header, len); + api->header_send(socket, cs, sr); + + /* Data */ + while (clen > 0) { + int remaining = api->socket_send(socket, content, clen); + if (remaining < 0) return -1; + + clen -= remaining; + } + mk_socket_set_cork_flag(socket, TCP_CORK_OFF); + + if (ret == MKLIB_TRUE) return MK_PLUGIN_RET_END; + } + + if (hook & MK_PLUGIN_STAGE_40 && ctx->closef) { + ctx->closef(sr); + } + +#endif + return -1; } diff --git a/src/mk_scheduler.c b/src/mk_scheduler.c index ec52132..2569dc7 100644 --- a/src/mk_scheduler.c +++ b/src/mk_scheduler.c @@ -222,8 +222,10 @@ static void *mk_sched_launch_worker_loop(void *thread_conf) struct sched_list_node *thinfo = NULL; mk_epoll_handlers *handler; +#ifndef SHAREDLIB /* Avoid SIGPIPE signals */ mk_signal_thread_sigpipe_safe(); +#endif /* Init specific thread cache */ mk_sched_thread_lists_init(); @@ -231,7 +233,6 @@ static void *mk_sched_launch_worker_loop(void *thread_conf) /* Register working thread */ wid = mk_sched_register_thread(thconf->epoll_fd); - mk_mem_free(thread_conf); /* Plugin thread context calls */ mk_epoll_state_init(); @@ -247,6 +248,12 @@ static void *mk_sched_launch_worker_loop(void *thread_conf) thinfo = &sched_list[wid]; +#ifdef SHAREDLIB + thinfo->ctx = thconf->ctx; +#endif + + mk_mem_free(thread_conf); + /* Rename worker */ mk_string_build(&thread_name, &len, "monkey: wrk/%i", thinfo->idx); mk_utils_worker_rename(thread_name); @@ -268,7 +275,7 @@ static void *mk_sched_launch_worker_loop(void *thread_conf) * Create thread which will be listening * for incomings file descriptors */ -int mk_sched_launch_thread(int max_events, pthread_t *tout) +int mk_sched_launch_thread(int max_events, pthread_t *tout, mklib_ctx ctx UNUSED_PARAM) { int efd; pthread_t tid; @@ -285,6 +292,9 @@ int mk_sched_launch_thread(int max_events, pthread_t *tout) thconf->epoll_fd = efd; thconf->epoll_max_events = max_events*2; thconf->max_events = max_events; +#ifdef SHAREDLIB + thconf->ctx = ctx; +#endif pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); diff --git a/src/mk_server.c b/src/mk_server.c index a27a2db..88b3ffd 100644 --- a/src/mk_server.c +++ b/src/mk_server.c @@ -66,6 +66,8 @@ unsigned int mk_server_worker_capacity(unsigned short nworkers) return ((avl / 2) / nworkers); } +#ifndef SHAREDLIB + /* Here we launch the worker threads to attend clients */ void mk_server_launch_workers() { @@ -74,7 +76,7 @@ void mk_server_launch_workers() /* Launch workers */ for (i = 0; i < config->workers; i++) { - mk_sched_launch_thread(config->worker_capacity, &skip); + mk_sched_launch_thread(config->worker_capacity, &skip, NULL); } } @@ -119,3 +121,5 @@ void mk_server_loop(int server_fd) } } } + +#endif // !SHAREDLIB diff --git a/src/mk_signals.c b/src/mk_signals.c index 9a02edd..7955935 100644 --- a/src/mk_signals.c +++ b/src/mk_signals.c @@ -20,6 +20,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +/* If a library, do not interfere with the app's signals */ +#ifndef SHAREDLIB + #include <pthread.h> #include <stdio.h> #include <stdlib.h> @@ -111,3 +114,5 @@ void mk_signal_init() sigaction(SIGINT, &act, NULL); sigaction(SIGTERM, &act, NULL); } + +#endif // !SHAREDLIB diff --git a/src/mk_user.c b/src/mk_user.c index 7c78f95..01bcbaa 100644 --- a/src/mk_user.c +++ b/src/mk_user.c @@ -96,6 +96,8 @@ int mk_user_init(struct client_session *cs, struct session_request *sr) return 0; } +#ifndef SHAREDLIB + /* Change process user */ int mk_user_set_uidgid() { @@ -153,3 +155,5 @@ int mk_user_undo_uidgid() } return 0; } + +#endif // !SHAREDLIB diff --git a/src/mk_utils.c b/src/mk_utils.c index ea59c18..8ad5b76 100644 --- a/src/mk_utils.c +++ b/src/mk_utils.c @@ -213,39 +213,6 @@ int mk_buffer_cat(mk_pointer *p, char *buf1, int len1, char *buf2, int len2) return 0; } -/* Run current process in background mode (daemon, evil Monkey >:) */ -int mk_utils_set_daemon() -{ - pid_t pid; - - if ((pid = fork()) < 0){ - mk_err("Error: Failed creating to switch to daemon mode(fork failed)"); - exit(EXIT_FAILURE); - } - - if (pid > 0) /* parent */ - exit(EXIT_SUCCESS); - - /* set files mask */ - umask(0); - - /* Create new session */ - setsid(); - - if (chdir("/") < 0) { /* make sure we can unmount the inherited filesystem */ - mk_err("Error: Unable to unmount the inherited filesystem in the daemon process"); - exit(EXIT_FAILURE); - } - - /* Our last STDOUT message */ - mk_info("Background mode ON"); - - fclose(stderr); - fclose(stdout); - - return 0; -} - /* Convert hexadecimal to int */ int mk_utils_hex2int(char *hex, int len) { @@ -466,6 +433,41 @@ int mk_utils_print_errno(int n) #endif +#ifndef SHAREDLIB + +/* Run current process in background mode (daemon, evil Monkey >:) */ +int mk_utils_set_daemon() +{ + pid_t pid; + + if ((pid = fork()) < 0){ + mk_err("Error: Failed creating to switch to daemon mode(fork failed)"); + exit(EXIT_FAILURE); + } + + if (pid > 0) /* parent */ + exit(EXIT_SUCCESS); + + /* set files mask */ + umask(0); + + /* Create new session */ + setsid(); + + if (chdir("/") < 0) { /* make sure we can unmount the inherited filesystem */ + mk_err("Error: Unable to unmount the inherited filesystem in the daemon process"); + exit(EXIT_FAILURE); + } + + /* Our last STDOUT message */ + mk_info("Background mode ON"); + + fclose(stderr); + fclose(stdout); + + return 0; +} + /* Write Monkey's PID */ int mk_utils_register_pid() { @@ -532,6 +534,8 @@ int mk_utils_remove_pid() return 0; } +#endif // !SHAREDLIB + void mk_print(int type, const char *format, ...) { time_t now; diff --git a/src/monkey.c b/src/monkey.c index a940733..bba62c8 100644 --- a/src/monkey.c +++ b/src/monkey.c @@ -63,6 +63,7 @@ void mk_thread_keys_init(void) pthread_key_create(&mk_plugin_event_k, NULL); } +#ifndef SHAREDLIB static void mk_details(void) { printf("* Process ID is %i", getpid()); @@ -158,6 +159,7 @@ int main(int argc, char **argv) mk_config_start_configure(); mk_sched_init(); mk_plugin_init(); + mk_plugin_read_config(); /* Server listening socket */ config->server_fd = mk_socket_server(config->serverport, config->listen_addr); @@ -218,3 +220,4 @@ int main(int argc, char **argv) mk_mem_free(config); return 0; } +#endif -- 1.7.2.1
_______________________________________________ Monkey mailing list [email protected] http://lists.monkey-project.com/listinfo/monkey
