mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-08-26 16:28:00 +00:00
201 lines
6.3 KiB
C
201 lines
6.3 KiB
C
#include <uwsgi.h>
|
|
|
|
extern struct uwsgi_server uwsgi;
|
|
|
|
struct uwsgi_symcall {
|
|
struct uwsgi_string_list *symcall_function_name;
|
|
int (*symcall_function)(struct wsgi_request *);
|
|
struct uwsgi_string_list *rpc;
|
|
struct uwsgi_string_list *post_fork;
|
|
int use_rtld_next;
|
|
void *dlsym_handle;
|
|
} usym;
|
|
|
|
struct uwsgi_plugin symcall_plugin;
|
|
|
|
static struct uwsgi_option uwsgi_symcall_options[] = {
|
|
{"symcall", required_argument, 0, "load the specified C symbol as the symcall request handler (supports <mountpoint=func> too)", uwsgi_opt_add_string_list, &usym.symcall_function_name, 0},
|
|
#ifdef RTLD_NEXT
|
|
{"symcall-use-next", no_argument, 0, "use RTLD_NEXT when searching for symbols", uwsgi_opt_true, &usym.use_rtld_next, 0},
|
|
#endif
|
|
{"symcall-register-rpc", required_argument, 0, "load the specified C symbol as an RPC function (syntax: name function)", uwsgi_opt_add_string_list, &usym.rpc, 0},
|
|
{"symcall-post-fork", required_argument, 0, "call the specified C symbol after each fork()", uwsgi_opt_add_string_list, &usym.post_fork, 0},
|
|
{0, 0, 0, 0},
|
|
};
|
|
|
|
static void uwsgi_symcall_init(){
|
|
#ifdef RTLD_NEXT
|
|
if (usym.use_rtld_next) {
|
|
usym.dlsym_handle = RTLD_NEXT;
|
|
}
|
|
#endif
|
|
struct uwsgi_string_list *usl = NULL;
|
|
int has_mountpoints = 0;
|
|
uwsgi_foreach(usl, usym.symcall_function_name) {
|
|
char *func = usl->value, *mountpoint = "";
|
|
char *equal = strchr(usl->value, '=');
|
|
if (equal) {
|
|
*equal = 0;
|
|
func = equal+1;
|
|
mountpoint = usl->value;
|
|
has_mountpoints = 1;
|
|
}
|
|
usl->custom_ptr = dlsym(usym.dlsym_handle, func);
|
|
if (!usl->custom_ptr) {
|
|
uwsgi_log("unable to find symbol \"%s\" in process address space\n", func);
|
|
exit(1);
|
|
}
|
|
int id = uwsgi_apps_cnt;
|
|
struct uwsgi_app *ua = uwsgi_add_app(id, symcall_plugin.modifier1, mountpoint, strlen(mountpoint), usl->custom_ptr, NULL);
|
|
uwsgi_log("symcall app %d (mountpoint: \"%.*s\") mapped to function ptr: %p\n", id, ua->mountpoint_len, ua->mountpoint, usl->custom_ptr);
|
|
if (equal) *equal = '=';
|
|
}
|
|
|
|
if (!has_mountpoints && usym.symcall_function_name) {
|
|
usym.symcall_function = usym.symcall_function_name->custom_ptr;
|
|
}
|
|
|
|
uwsgi_foreach(usl, usym.rpc) {
|
|
char *space = strchr(usl->value, ' ');
|
|
if (!space) {
|
|
uwsgi_log("invalid symcall RPC syntax, must be: rpcname symbol\n");
|
|
exit(1);
|
|
}
|
|
*space = 0;
|
|
void *func = dlsym(usym.dlsym_handle, space+1);
|
|
if (!func) {
|
|
uwsgi_log("unable to find symbol \"%s\" in process address space\n", space+1);
|
|
exit(1);
|
|
}
|
|
if (uwsgi_register_rpc(usl->value, &symcall_plugin, 0, func)) {
|
|
uwsgi_log("unable to register rpc function");
|
|
exit(1);
|
|
}
|
|
*space = ' ';
|
|
}
|
|
}
|
|
|
|
static int uwsgi_symcall_request(struct wsgi_request *wsgi_req) {
|
|
if (usym.symcall_function) {
|
|
return usym.symcall_function(wsgi_req);
|
|
}
|
|
|
|
if (uwsgi_parse_vars(wsgi_req)) return -1;
|
|
|
|
wsgi_req->app_id = uwsgi_get_app_id(wsgi_req, wsgi_req->appid, wsgi_req->appid_len, symcall_plugin.modifier1);
|
|
if (wsgi_req->app_id == -1 && !uwsgi.no_default_app && uwsgi.default_app > -1) {
|
|
if (uwsgi_apps[uwsgi.default_app].modifier1 == symcall_plugin.modifier1) {
|
|
wsgi_req->app_id = uwsgi.default_app;
|
|
}
|
|
}
|
|
|
|
if (wsgi_req->app_id == -1) {
|
|
uwsgi_404(wsgi_req);
|
|
return UWSGI_OK;
|
|
}
|
|
|
|
struct uwsgi_app *ua = &uwsgi_apps[wsgi_req->app_id];
|
|
if (ua->interpreter) {
|
|
int (*func)(struct wsgi_request *) = (int (*)(struct wsgi_request *)) ua->interpreter;
|
|
return func(wsgi_req);
|
|
}
|
|
return UWSGI_OK;
|
|
}
|
|
|
|
|
|
static void uwsgi_symcall_after_request(struct wsgi_request *wsgi_req) {
|
|
log_request(wsgi_req);
|
|
}
|
|
|
|
static uint64_t uwsgi_symcall_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char **buffer) {
|
|
uint64_t (*casted_func)(uint8_t, char **, uint16_t *, char **) = (uint64_t (*)(uint8_t, char **, uint16_t *, char **)) func;
|
|
return casted_func(argc, argv, argvs, buffer);
|
|
}
|
|
|
|
static void uwsgi_symcall_post_fork() {
|
|
void (*func)(void);
|
|
struct uwsgi_string_list *usl = usym.post_fork;
|
|
while(usl) {
|
|
func = dlsym(usym.dlsym_handle, usl->value);
|
|
if (!func) {
|
|
uwsgi_log("unable to find symbol \"%s\" in process address space\n", usl->value);
|
|
exit(1);
|
|
}
|
|
func();
|
|
usl = usl->next;
|
|
}
|
|
}
|
|
|
|
static int uwsgi_symcall_mule(char *opt) {
|
|
if (uwsgi_endswith(opt, "()")) {
|
|
char *func_name = uwsgi_concat2n(opt, strlen(opt)-2, "", 0);
|
|
void (*func)() = dlsym(usym.dlsym_handle, func_name);
|
|
if (!func) {
|
|
uwsgi_log("unable to find symbol \"%s\" in process address space\n", func_name);
|
|
exit(1);
|
|
}
|
|
free(func_name);
|
|
func();
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#ifdef UWSGI_ROUTING
|
|
static int symcall_route(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
|
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
|
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
|
|
|
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
|
if (!ub) return UWSGI_ROUTE_BREAK;
|
|
|
|
int (*func)(struct wsgi_request *) = (int (*)(struct wsgi_request *)) dlsym(usym.dlsym_handle, ub->buf);
|
|
uwsgi_buffer_destroy(ub);
|
|
|
|
if (func) {
|
|
wsgi_req->async_status = func(wsgi_req);
|
|
}
|
|
else {
|
|
if (ur->custom) return UWSGI_ROUTE_NEXT;
|
|
uwsgi_404(wsgi_req);
|
|
}
|
|
|
|
return UWSGI_ROUTE_BREAK;
|
|
}
|
|
|
|
static int uwsgi_router_symcall(struct uwsgi_route *ur, char *args) {
|
|
ur->func = symcall_route;
|
|
ur->data = args;
|
|
ur->data_len = strlen(args);
|
|
return 0;
|
|
}
|
|
|
|
static int uwsgi_router_symcall_next(struct uwsgi_route *ur, char *args) {
|
|
ur->custom = 1;
|
|
return uwsgi_router_symcall(ur, args);
|
|
}
|
|
#endif
|
|
|
|
static void uwsgi_symcall_register() {
|
|
usym.dlsym_handle = RTLD_DEFAULT;
|
|
#ifdef UWSGI_ROUTING
|
|
uwsgi_register_router("symcall", uwsgi_router_symcall);
|
|
uwsgi_register_router("symcall-next", uwsgi_router_symcall_next);
|
|
#endif
|
|
}
|
|
|
|
struct uwsgi_plugin symcall_plugin = {
|
|
|
|
.name = "symcall",
|
|
.modifier1 = 18,
|
|
.options = uwsgi_symcall_options,
|
|
.init_apps = uwsgi_symcall_init,
|
|
.request = uwsgi_symcall_request,
|
|
.after_request = uwsgi_symcall_after_request,
|
|
.rpc = uwsgi_symcall_rpc,
|
|
.post_fork = uwsgi_symcall_post_fork,
|
|
.mule = uwsgi_symcall_mule,
|
|
.on_load = uwsgi_symcall_register,
|
|
};
|
|
|