mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2263c6a618 | ||
|
|
b4ecd504e3 | ||
|
|
f226f29428 | ||
|
|
b87a284390 | ||
|
|
f63dcd0d9c | ||
|
|
7f5563d581 | ||
|
|
d8a61a920e | ||
|
|
5a4900da8e | ||
|
|
677c30057a | ||
|
|
26113e091b | ||
|
|
1b5e98f593 | ||
|
|
0aa5201947 | ||
|
|
e3951baa3f | ||
|
|
9f9dbbab9e | ||
|
|
d546bbadbd | ||
|
|
2b7f25054f | ||
|
|
bb3f6bcf7e | ||
|
|
41da7175d1 | ||
|
|
446763b58a | ||
|
|
3e9337a0fc | ||
|
|
028806165b | ||
|
|
e4be42edbb | ||
|
|
230fa1f3bb | ||
|
|
d74653bbad | ||
|
|
38049b0897 | ||
|
|
b4af646929 | ||
|
|
b21ec73a52 | ||
|
|
c595844f0e | ||
|
|
fe8ee7c7b3 | ||
|
|
cd382c6bc0 | ||
|
|
e68296c293 | ||
|
|
cc189feae5 | ||
|
|
18e19027a1 | ||
|
|
2d2e0e4757 | ||
|
|
a9f50d79f9 | ||
|
|
0ccd31bee0 | ||
|
|
3ea82b2bcd | ||
|
|
6dad7b3ced | ||
|
|
f96ebd2b07 | ||
|
|
b8d0e7a3ac | ||
|
|
14cca3d497 | ||
|
|
c343ca0cc3 | ||
|
|
527d371bda | ||
|
|
b87a800a9a | ||
|
|
e406993ed1 | ||
|
|
eeff935fc9 | ||
|
|
0791394f1a | ||
|
|
082a407b06 | ||
|
|
8a89b49df1 | ||
|
|
2314b9cbab | ||
|
|
d0cca85c83 | ||
|
|
6a7a5cbcba | ||
|
|
ecccc82cc8 | ||
|
|
02693489fe | ||
|
|
0f5dba5828 | ||
|
|
e528d4c4b7 | ||
|
|
52a3af6acf | ||
|
|
dcefea9958 | ||
|
|
59121ff834 | ||
|
|
7f5bb6d472 | ||
|
|
639c1a508c | ||
|
|
417a26fc64 | ||
|
|
210ccd0063 | ||
|
|
1bf0162d38 | ||
|
|
e93027fd7e |
@@ -217,6 +217,45 @@ static int uwsgi_send_body(request_rec *r, proxy_conn_rec *conn)
|
||||
return OK;
|
||||
}
|
||||
|
||||
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
|
||||
static request_rec *ap_proxy_make_fake_req(conn_rec *c, request_rec *r)
|
||||
{
|
||||
apr_pool_t *pool;
|
||||
request_rec *rp;
|
||||
|
||||
apr_pool_create(&pool, c->pool);
|
||||
|
||||
rp = apr_pcalloc(pool, sizeof(*r));
|
||||
|
||||
rp->pool = pool;
|
||||
rp->status = HTTP_OK;
|
||||
|
||||
rp->headers_in = apr_table_make(pool, 50);
|
||||
rp->subprocess_env = apr_table_make(pool, 50);
|
||||
rp->headers_out = apr_table_make(pool, 12);
|
||||
rp->err_headers_out = apr_table_make(pool, 5);
|
||||
rp->notes = apr_table_make(pool, 5);
|
||||
|
||||
rp->server = r->server;
|
||||
rp->log = r->log;
|
||||
rp->proxyreq = r->proxyreq;
|
||||
rp->request_time = r->request_time;
|
||||
rp->connection = c;
|
||||
rp->output_filters = c->output_filters;
|
||||
rp->input_filters = c->input_filters;
|
||||
rp->proto_output_filters = c->output_filters;
|
||||
rp->proto_input_filters = c->input_filters;
|
||||
rp->useragent_ip = c->client_ip;
|
||||
rp->useragent_addr = c->client_addr;
|
||||
|
||||
rp->request_config = ap_create_request_config(pool);
|
||||
proxy_run_create_req(r, rp);
|
||||
|
||||
return rp;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_conf *conf)
|
||||
{
|
||||
|
||||
@@ -337,7 +376,11 @@ static int uwsgi_handler(request_rec *r, proxy_worker *worker,
|
||||
}
|
||||
|
||||
// ADD PATH_INFO
|
||||
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
|
||||
size_t w_len = strlen(worker->s->name);
|
||||
#else
|
||||
size_t w_len = strlen(worker->name);
|
||||
#endif
|
||||
char *u_path_info = r->filename + 6 + w_len;
|
||||
int delta = 0;
|
||||
if (u_path_info[0] != '/') {
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = gridfs
|
||||
inherit = base
|
||||
+2
-1
@@ -533,7 +533,8 @@ void uwsgi_cache_fix(struct uwsgi_cache *uc) {
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("[uwsgi-cache] restored %llu items\n", restored);
|
||||
uc->n_items = restored;
|
||||
uwsgi_log("[uwsgi-cache] restored %llu items\n", uc->n_items);
|
||||
}
|
||||
|
||||
int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *val, uint64_t vallen, uint64_t expires, uint64_t flags) {
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
pluggable configuration system
|
||||
|
||||
*/
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_configurator *uwsgi_register_configurator(char *name, void (*func)(char *, char **)) {
|
||||
struct uwsgi_configurator *old_uc = NULL,*uc = uwsgi.configurators;
|
||||
while(uc) {
|
||||
if (!strcmp(uc->name, name)) {
|
||||
return uc;
|
||||
}
|
||||
old_uc = uc;
|
||||
uc = uc->next;
|
||||
}
|
||||
|
||||
uc = uwsgi_calloc(sizeof(struct uwsgi_configurator));
|
||||
uc->name = name;
|
||||
uc->func = func;
|
||||
|
||||
if (old_uc) {
|
||||
old_uc->next = uc;
|
||||
}
|
||||
else {
|
||||
uwsgi.configurators = uc;
|
||||
}
|
||||
|
||||
return uc;
|
||||
}
|
||||
+12
-10
@@ -208,18 +208,20 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
uwsgi_write_pidfile(ud->pidfile);
|
||||
}
|
||||
|
||||
// /dev/null will became stdin
|
||||
devnull = open("/dev/null", O_RDONLY);
|
||||
if (devnull < 0) {
|
||||
uwsgi_error("/dev/null open()");
|
||||
exit(1);
|
||||
}
|
||||
if (devnull != 0) {
|
||||
if (dup2(devnull, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
if (!uwsgi.daemons_honour_stdin) {
|
||||
// /dev/null will became stdin
|
||||
devnull = open("/dev/null", O_RDONLY);
|
||||
if (devnull < 0) {
|
||||
uwsgi_error("/dev/null open()");
|
||||
exit(1);
|
||||
}
|
||||
close(devnull);
|
||||
if (devnull != 0) {
|
||||
if (dup2(devnull, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(devnull);
|
||||
}
|
||||
}
|
||||
|
||||
if (setsid() < 0) {
|
||||
|
||||
+64
-9
@@ -122,16 +122,27 @@ void uwsgi_emperor_blacklist_remove(char *id) {
|
||||
|
||||
struct uwsgi_emperor_scanner *emperor_scanners;
|
||||
|
||||
static int has_extra_extension(char *name) {
|
||||
struct uwsgi_string_list *usl = uwsgi.emperor_extra_extension;
|
||||
while(usl) {
|
||||
if (uwsgi_endswith(name, usl->value)) {
|
||||
return 1;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_emperor_is_valid(char *name) {
|
||||
|
||||
if (uwsgi_endswith(name, ".xml") || uwsgi_endswith(name, ".ini") || uwsgi_endswith(name, ".yml") || uwsgi_endswith(name, ".yaml") || uwsgi_endswith(name, ".js") || uwsgi_endswith(name, ".json")) {
|
||||
|
||||
if (uwsgi_endswith(name, ".xml") || uwsgi_endswith(name, ".ini") || uwsgi_endswith(name, ".yml") || uwsgi_endswith(name, ".yaml") || uwsgi_endswith(name, ".js") || uwsgi_endswith(name, ".json") || has_extra_extension(name)) {
|
||||
|
||||
if (strlen(name) < 0xff) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -231,10 +242,27 @@ void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
|
||||
|
||||
ui_current = emperor_get(de->d_name);
|
||||
|
||||
uid_t t_uid = st.st_uid;
|
||||
gid_t t_gid = st.st_gid;
|
||||
|
||||
if (uwsgi.emperor_tyrant && uwsgi.emperor_tyrant_nofollow) {
|
||||
struct stat lst;
|
||||
if (lstat(de->d_name, &lst)) {
|
||||
uwsgi_error("[emperor-tyrant]/lstat()");
|
||||
if (ui_current) {
|
||||
uwsgi_log("!!! availability of file %s changed. stopping the instance... !!!\n", de->d_name);
|
||||
emperor_stop(ui_current);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
t_uid = lst.st_uid;
|
||||
t_gid = lst.st_gid;
|
||||
}
|
||||
|
||||
if (ui_current) {
|
||||
// check if uid or gid are changed, in such case, stop the instance
|
||||
if (uwsgi.emperor_tyrant) {
|
||||
if (st.st_uid != ui_current->uid || st.st_gid != ui_current->gid) {
|
||||
if (t_uid != ui_current->uid || t_gid != ui_current->gid) {
|
||||
uwsgi_log("!!! permissions of file %s changed. stopping the instance... !!!\n", de->d_name);
|
||||
emperor_stop(ui_current);
|
||||
continue;
|
||||
@@ -247,7 +275,7 @@ void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
|
||||
}
|
||||
else {
|
||||
char *socket_name = emperor_check_on_demand_socket(de->d_name);
|
||||
emperor_add(ues, de->d_name, st.st_mtime, NULL, 0, st.st_uid, st.st_gid, socket_name);
|
||||
emperor_add(ues, de->d_name, st.st_mtime, NULL, 0, t_uid, t_gid, socket_name);
|
||||
if (socket_name) free(socket_name);
|
||||
}
|
||||
}
|
||||
@@ -308,10 +336,27 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
|
||||
|
||||
ui_current = emperor_get(g.gl_pathv[i]);
|
||||
|
||||
uid_t t_uid = st.st_uid;
|
||||
gid_t t_gid = st.st_gid;
|
||||
|
||||
if (uwsgi.emperor_tyrant && uwsgi.emperor_tyrant_nofollow) {
|
||||
struct stat lst;
|
||||
if (lstat(g.gl_pathv[i], &lst)) {
|
||||
uwsgi_error("[emperor-tyrant]/lstat()");
|
||||
if (ui_current) {
|
||||
uwsgi_log("!!! availability of file %s changed. stopping the instance... !!!\n", g.gl_pathv[i]);
|
||||
emperor_stop(ui_current);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
t_uid = lst.st_uid;
|
||||
t_gid = lst.st_gid;
|
||||
}
|
||||
|
||||
if (ui_current) {
|
||||
// check if uid or gid are changed, in such case, stop the instance
|
||||
if (uwsgi.emperor_tyrant) {
|
||||
if (st.st_uid != ui_current->uid || st.st_gid != ui_current->gid) {
|
||||
if (t_uid != ui_current->uid || t_gid != ui_current->gid) {
|
||||
uwsgi_log("!!! permissions of file %s changed. stopping the instance... !!!\n", g.gl_pathv[i]);
|
||||
emperor_stop(ui_current);
|
||||
continue;
|
||||
@@ -324,7 +369,7 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
|
||||
}
|
||||
else {
|
||||
char *socket_name = emperor_check_on_demand_socket(g.gl_pathv[i]);
|
||||
emperor_add(ues, g.gl_pathv[i], st.st_mtime, NULL, 0, st.st_uid, st.st_gid, socket_name);
|
||||
emperor_add(ues, g.gl_pathv[i], st.st_mtime, NULL, 0, t_uid, t_gid, socket_name);
|
||||
if (socket_name) free(socket_name);
|
||||
}
|
||||
|
||||
@@ -820,15 +865,16 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
|
||||
uenvs = environ;
|
||||
while (*uenvs) {
|
||||
if (!strncmp(*uenvs, "UWSGI_VASSAL_", 13)) {
|
||||
char *ne = uwsgi_concat2("UWSGI_", *uenvs + 13);
|
||||
char *oe = uwsgi_concat2n(*uenvs, strchr(*uenvs, '=') - *uenvs, "", 0);
|
||||
if (!strncmp(*uenvs, "UWSGI_VASSAL_", 13) && strchr(*uenvs, '=')) {
|
||||
char *oe = uwsgi_concat2n(*uenvs, strchr(*uenvs, '=') - *uenvs, "", 0), *ne;
|
||||
if (unsetenv(oe)) {
|
||||
uwsgi_error("unsetenv()");
|
||||
free(oe);
|
||||
break;
|
||||
}
|
||||
free(oe);
|
||||
|
||||
ne = uwsgi_concat2("UWSGI_", *uenvs + 13);
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("putenv %s\n", ne);
|
||||
#endif
|
||||
@@ -882,6 +928,15 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
vassal_argv[1] = "--json";
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".json"))
|
||||
vassal_argv[1] = "--json";
|
||||
|
||||
struct uwsgi_string_list *usl = uwsgi.emperor_extra_extension;
|
||||
while(usl) {
|
||||
if (uwsgi_endswith(n_ui->name, usl->value)) {
|
||||
vassal_argv[1] = "--config";
|
||||
break;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
if (colon) {
|
||||
colon[0] = ':';
|
||||
|
||||
+14
-14
@@ -260,7 +260,7 @@ int event_queue_del_fd(int eq, int fd, int event) {
|
||||
|
||||
int event_queue_fd_write_to_read(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -271,7 +271,7 @@ int event_queue_fd_write_to_read(int eq, int fd) {
|
||||
|
||||
int event_queue_fd_read_to_write(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -282,7 +282,7 @@ int event_queue_fd_read_to_write(int eq, int fd) {
|
||||
|
||||
int event_queue_fd_readwrite_to_read(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -293,7 +293,7 @@ int event_queue_fd_readwrite_to_read(int eq, int fd) {
|
||||
|
||||
int event_queue_fd_readwrite_to_write(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -304,7 +304,7 @@ int event_queue_fd_readwrite_to_write(int eq, int fd) {
|
||||
|
||||
int event_queue_fd_write_to_readwrite(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -315,7 +315,7 @@ int event_queue_fd_write_to_readwrite(int eq, int fd) {
|
||||
|
||||
int event_queue_fd_read_to_readwrite(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -351,7 +351,7 @@ int event_queue_interesting_fd_is_write(void *events, int id) {
|
||||
|
||||
int event_queue_add_fd_read(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -361,7 +361,7 @@ int event_queue_add_fd_read(int eq, int fd) {
|
||||
|
||||
int event_queue_add_fd_write(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -381,7 +381,7 @@ int event_queue_interesting_fd(void *events, int id) {
|
||||
}
|
||||
|
||||
int fd = (int) pe[id].portev_object;
|
||||
int eq = (int) pe[id].portev_user;
|
||||
int eq = (long) pe[id].portev_user;
|
||||
|
||||
if (pe[id].portev_events == POLLOUT) {
|
||||
event_queue_add_fd_write(eq, fd);
|
||||
@@ -423,7 +423,7 @@ int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
|
||||
port_event_t *pe_i = &pe[i];
|
||||
if (pe_i->portev_source == PORT_SOURCE_FD) {
|
||||
// event must be readded (damn Oracle/Sun why the fu*k you made such a horrible choice ???? why not adding a ONESHOT flag ???)
|
||||
if (port_associate(eq, pe_i->portev_source, pe_i->portev_object, pe_i->portev_events, NULL)) {
|
||||
if (port_associate(eq, pe_i->portev_source, pe_i->portev_object, pe_i->portev_events, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
}
|
||||
}
|
||||
@@ -449,16 +449,16 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
|
||||
ret = port_get(eq, &pe, NULL);
|
||||
}
|
||||
if (ret < 0) {
|
||||
if (errno != ETIME) {
|
||||
if (errno == ETIME) return 0;
|
||||
if (errno != EINTR) {
|
||||
uwsgi_error("port_get()");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pe.portev_source == PORT_SOURCE_FD) {
|
||||
// event must be readded (damn Oracle/Sun why the fu*k you made such a horrible choice ???? why not adding a ONESHOT flag ???)
|
||||
if (port_associate(eq, pe.portev_source, pe.portev_object, pe.portev_events, NULL)) {
|
||||
if (port_associate(eq, pe.portev_source, pe.portev_object, pe.portev_events, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
}
|
||||
}
|
||||
|
||||
+64
-24
@@ -203,7 +203,6 @@ static void legions_check_nodes() {
|
||||
|
||||
struct uwsgi_legion_node *node = legion->nodes_head;
|
||||
while (node) {
|
||||
|
||||
if (now - node->last_seen > uwsgi.legion_tolerance) {
|
||||
struct uwsgi_legion_node *tmp_node = node;
|
||||
node = node->next;
|
||||
@@ -302,6 +301,18 @@ static void legions_check_nodes_step2() {
|
||||
|
||||
// we have quorum !!!
|
||||
if (votes > 0 && votes >= ul->quorum) {
|
||||
if (!ul->joined) {
|
||||
// triggering join hooks
|
||||
struct uwsgi_string_list *usl = ul->join_hooks;
|
||||
while (usl) {
|
||||
int ret = uwsgi_legion_action_call("join", ul, usl);
|
||||
if (ret) {
|
||||
uwsgi_log("[uwsgi-legion] ERROR, join hook returned: %d\n", ret);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
ul->joined = 1;
|
||||
}
|
||||
// something changed ???
|
||||
if (ul->changed) {
|
||||
legions_report_quorum(ul, best_valor, best_uuid, votes);
|
||||
@@ -763,15 +774,20 @@ void uwsgi_opt_legion_node(char *opt, char *value, void *foobar) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *usl = uwsgi_string_new_list(&ul->nodes, space + 1);
|
||||
char *port = strchr(usl->value, ':');
|
||||
uwsgi_legion_register_node(ul, space + 1);
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_legion_register_node(struct uwsgi_legion *ul, char *addr) {
|
||||
struct uwsgi_string_list *usl = uwsgi_string_new_list(&ul->nodes, addr);
|
||||
char *port = strchr(addr, ':');
|
||||
if (!port) {
|
||||
uwsgi_log("[uwsgi-legion] invalid udp address: %s\n", usl->value);
|
||||
uwsgi_log("[uwsgi-legion] invalid udp address: %s\n", addr);
|
||||
exit(1);
|
||||
}
|
||||
// no need to zero the memory, socket_to_in_addr will do that
|
||||
struct sockaddr_in *sin = uwsgi_malloc(sizeof(struct sockaddr_in));
|
||||
usl->custom = socket_to_in_addr(usl->value, port, 0, sin);
|
||||
usl->custom = socket_to_in_addr(addr, port, 0, sin);
|
||||
usl->custom_ptr = sin;
|
||||
}
|
||||
|
||||
@@ -823,51 +839,69 @@ void uwsgi_opt_legion_scroll(char *opt, char *value, void *foobar) {
|
||||
|
||||
void uwsgi_opt_legion_hook(char *opt, char *value, void *foobar) {
|
||||
|
||||
char *event = strchr(opt, '-');
|
||||
if (!event) {
|
||||
uwsgi_log("[uwsgi-legion] invalid option name (%s), this should not happen (possible bug)\n", opt);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *legion = uwsgi_str(value);
|
||||
|
||||
|
||||
char *space = strchr(legion, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid %s syntax, must be <legion> <action>\n", opt);
|
||||
uwsgi_log("[uwsgi-legion] invalid %s syntax, must be <legion> <action>\n", opt);
|
||||
exit(1);
|
||||
}
|
||||
*space = 0;
|
||||
|
||||
struct uwsgi_legion *ul = uwsgi_legion_get_by_name(legion);
|
||||
if (!ul) {
|
||||
uwsgi_log("unknown legion: %s\n", legion);
|
||||
uwsgi_log("[uwsgi-legion] unknown legion: %s\n", legion);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_legion_register_hook(ul, event + 1, space + 1);
|
||||
}
|
||||
|
||||
void uwsgi_legion_register_hook(struct uwsgi_legion *ul, char *event, char *action) {
|
||||
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
|
||||
if (!strcmp(opt, "legion-lord")) {
|
||||
usl = uwsgi_string_new_list(&ul->lord_hooks, space + 1);
|
||||
if (!strcmp(event, "lord")) {
|
||||
usl = uwsgi_string_new_list(&ul->lord_hooks, action);
|
||||
}
|
||||
else if (!strcmp(opt, "legion-unlord")) {
|
||||
usl = uwsgi_string_new_list(&ul->unlord_hooks, space + 1);
|
||||
else if (!strcmp(event, "unlord")) {
|
||||
usl = uwsgi_string_new_list(&ul->unlord_hooks, action);
|
||||
}
|
||||
else if (!strcmp(opt, "legion-setup")) {
|
||||
usl = uwsgi_string_new_list(&ul->setup_hooks, space + 1);
|
||||
else if (!strcmp(event, "setup")) {
|
||||
usl = uwsgi_string_new_list(&ul->setup_hooks, action);
|
||||
}
|
||||
else if (!strcmp(opt, "legion-death")) {
|
||||
usl = uwsgi_string_new_list(&ul->death_hooks, space + 1);
|
||||
else if (!strcmp(event, "death")) {
|
||||
usl = uwsgi_string_new_list(&ul->death_hooks, action);
|
||||
}
|
||||
else if (!strcmp(event, "join")) {
|
||||
usl = uwsgi_string_new_list(&ul->join_hooks, action);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[uwsgi-legion] invalid event: %s\n", event);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!usl)
|
||||
return;
|
||||
|
||||
char *port = strchr(usl->value, ':');
|
||||
if (!port) {
|
||||
uwsgi_log("[uwsgi-legion] invalid %s action: %s\n", opt, usl->value);
|
||||
char *hook = strchr(action, ':');
|
||||
if (!hook) {
|
||||
uwsgi_log("[uwsgi-legion] invalid %s action: %s\n", event, action);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// pointer to action plugin
|
||||
usl->custom_ptr = uwsgi_concat2n(usl->value, port - usl->value, "", 0);
|
||||
usl->custom_ptr = uwsgi_concat2n(action, hook - action, "", 0);;
|
||||
// add that to check the plugin value
|
||||
usl->custom = port - usl->value + 1;
|
||||
}
|
||||
usl->custom = hook - action + 1;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
|
||||
|
||||
@@ -905,6 +939,10 @@ void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
|
||||
*colon = 0;
|
||||
char *secret = colon + 1;
|
||||
|
||||
uwsgi_legion_register(legion, addr, valor, algo_secret, secret);
|
||||
}
|
||||
|
||||
struct uwsgi_legion *uwsgi_legion_register(char *legion, char *addr, char *valor, char *algo, char *secret) {
|
||||
char *iv = strchr(secret, ' ');
|
||||
if (iv) {
|
||||
*iv = 0;
|
||||
@@ -918,9 +956,9 @@ void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
|
||||
EVP_CIPHER_CTX *ctx = uwsgi_malloc(sizeof(EVP_CIPHER_CTX));
|
||||
EVP_CIPHER_CTX_init(ctx);
|
||||
|
||||
const EVP_CIPHER *cipher = EVP_get_cipherbyname(algo_secret);
|
||||
const EVP_CIPHER *cipher = EVP_get_cipherbyname(algo);
|
||||
if (!cipher) {
|
||||
uwsgi_log("[uwsgi-legion] unable to find algorithm/cipher %s\n", algo_secret);
|
||||
uwsgi_log("[uwsgi-legion] unable to find algorithm/cipher %s\n", algo);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -983,6 +1021,8 @@ void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
|
||||
ul->scrolls = uwsgi_calloc_shared(ul->scrolls_max_size);
|
||||
|
||||
uwsgi_legion_add(ul);
|
||||
|
||||
return ul;
|
||||
}
|
||||
|
||||
struct uwsgi_legion_action *uwsgi_legion_action_get(char *name) {
|
||||
|
||||
+19
-19
@@ -798,8 +798,8 @@ int master_loop(char **argv, char **environ) {
|
||||
|
||||
*/
|
||||
|
||||
uwsgi.mywid = find_worker_id(diedpid);
|
||||
if (uwsgi.mywid <= 0) {
|
||||
int thewid = find_worker_id(diedpid);
|
||||
if (thewid <= 0) {
|
||||
// check spooler, mules, gateways and daemons
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
while (uspool) {
|
||||
@@ -842,50 +842,50 @@ next:
|
||||
|
||||
|
||||
// ok a worker died...
|
||||
uwsgi.workers[uwsgi.mywid].pid = 0;
|
||||
uwsgi.workers[thewid].pid = 0;
|
||||
// only to be safe :P
|
||||
uwsgi.workers[uwsgi.mywid].harakiri = 0;
|
||||
uwsgi.workers[thewid].harakiri = 0;
|
||||
|
||||
// ok, if we are reloading or dying, just continue the master loop
|
||||
// as soon as all of the workers have pid == 0, the action (exit, or reload) is triggered
|
||||
if (uwsgi_instance_is_reloading || uwsgi_instance_is_dying) {
|
||||
uwsgi_log("worker %d buried after %d seconds\n", uwsgi.mywid, (int) (uwsgi_now()-uwsgi.workers[uwsgi.mywid].cursed_at));
|
||||
uwsgi.workers[uwsgi.mywid].cursed_at = 0;
|
||||
uwsgi_log("worker %d buried after %d seconds\n", thewid, (int) (uwsgi_now()-uwsgi.workers[thewid].cursed_at));
|
||||
uwsgi.workers[thewid].cursed_at = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
// if we are stopping workers, just end here
|
||||
|
||||
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_FAILED_APP_CODE) {
|
||||
uwsgi_log("OOPS ! failed loading app in worker %d (pid %d) :( trying again...\n", uwsgi.mywid, (int) diedpid);
|
||||
uwsgi_log("OOPS ! failed loading app in worker %d (pid %d) :( trying again...\n", thewid, (int) diedpid);
|
||||
}
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_DE_HIJACKED_CODE) {
|
||||
uwsgi_log("...restoring worker %d (pid: %d)...\n", uwsgi.mywid, (int) diedpid);
|
||||
uwsgi_log("...restoring worker %d (pid: %d)...\n", thewid, (int) diedpid);
|
||||
}
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_EXCEPTION_CODE) {
|
||||
uwsgi_log("... monitored exception detected, respawning worker %d (pid: %d)...\n", uwsgi.mywid, (int) diedpid);
|
||||
uwsgi_log("... monitored exception detected, respawning worker %d (pid: %d)...\n", thewid, (int) diedpid);
|
||||
}
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_QUIET_CODE) {
|
||||
// noop
|
||||
}
|
||||
else if (uwsgi.workers[uwsgi.mywid].manage_next_request) {
|
||||
else if (uwsgi.workers[thewid].manage_next_request) {
|
||||
if (WIFSIGNALED(waitpid_status)) {
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died, killed by signal %d :( trying respawn ...\n", uwsgi.mywid, (int) diedpid, (int) WTERMSIG(waitpid_status));
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died, killed by signal %d :( trying respawn ...\n", thewid, (int) diedpid, (int) WTERMSIG(waitpid_status));
|
||||
}
|
||||
else {
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died :( trying respawn ...\n", uwsgi.mywid, (int) diedpid);
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died :( trying respawn ...\n", thewid, (int) diedpid);
|
||||
}
|
||||
}
|
||||
else if (uwsgi.workers[uwsgi.mywid].cursed_at > 0) {
|
||||
uwsgi_log("worker %d killed successfully (pid: %d)\n", uwsgi.mywid, (int) diedpid);
|
||||
else if (uwsgi.workers[thewid].cursed_at > 0) {
|
||||
uwsgi_log("worker %d killed successfully (pid: %d)\n", thewid, (int) diedpid);
|
||||
}
|
||||
// manage_next_request is zero, but killed by signal...
|
||||
else if (WIFSIGNALED(waitpid_status)) {
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) MISTERIOUSLY killed by signal %d :( trying respawn ...\n", uwsgi.mywid, (int) diedpid, (int) WTERMSIG(waitpid_status));
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) MISTERIOUSLY killed by signal %d :( trying respawn ...\n", thewid, (int) diedpid, (int) WTERMSIG(waitpid_status));
|
||||
}
|
||||
|
||||
if (uwsgi.workers[uwsgi.mywid].cheaped == 1) {
|
||||
uwsgi_log("uWSGI worker %d cheaped.\n", uwsgi.mywid);
|
||||
if (uwsgi.workers[thewid].cheaped == 1) {
|
||||
uwsgi_log("uWSGI worker %d cheaped.\n", thewid);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -909,12 +909,12 @@ next:
|
||||
uwsgi.respawn_delta = last_respawn.tv_sec;
|
||||
|
||||
// are we chain reloading it ?
|
||||
if (uwsgi.status.chain_reloading == uwsgi.mywid) {
|
||||
if (uwsgi.status.chain_reloading == thewid) {
|
||||
uwsgi.status.chain_reloading++;
|
||||
}
|
||||
|
||||
// respawn the worker (if needed)
|
||||
if (uwsgi_respawn_worker(uwsgi.mywid))
|
||||
if (uwsgi_respawn_worker(thewid))
|
||||
return 0;
|
||||
|
||||
// end of the loop
|
||||
|
||||
+3
-4
@@ -413,9 +413,6 @@ void uwsgi_reload(char **argv) {
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef UWSGI_AS_SHARED_LIBRARY
|
||||
return;
|
||||
#else
|
||||
uwsgi_log("running %s\n", uwsgi.binary_path);
|
||||
uwsgi_flush_logs();
|
||||
argv[0] = uwsgi.binary_path;
|
||||
@@ -436,7 +433,6 @@ void uwsgi_reload(char **argv) {
|
||||
uwsgi_error("execvp()");
|
||||
// never here
|
||||
exit(1);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -957,6 +953,9 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
uc = uc->next;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_list_close(us))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
}
|
||||
|
||||
+6
-2
@@ -184,6 +184,7 @@ void uwsgi_mule_handler() {
|
||||
if (interesting_fd == uwsgi.signal_socket || interesting_fd == uwsgi.my_signal_socket || farm_has_signaled(interesting_fd)) {
|
||||
len = read(interesting_fd, &uwsgi_signal, 1);
|
||||
if (len <= 0) {
|
||||
if (len < 0 && (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)) continue;
|
||||
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
|
||||
end_me(0);
|
||||
}
|
||||
@@ -197,7 +198,9 @@ void uwsgi_mule_handler() {
|
||||
else if (interesting_fd == uwsgi.mules[uwsgi.muleid - 1].queue_pipe[1] || interesting_fd == uwsgi.shared->mule_queue_pipe[1] || farm_has_msg(interesting_fd)) {
|
||||
len = read(interesting_fd, message, 65536);
|
||||
if (len < 0) {
|
||||
uwsgi_error("read()");
|
||||
if (errno != EAGAIN && errno != EINTR && errno != EWOULDBLOCK) {
|
||||
uwsgi_error("uwsgi_mule_handler/read()");
|
||||
}
|
||||
}
|
||||
else {
|
||||
int i, found = 0;
|
||||
@@ -343,6 +346,7 @@ next:
|
||||
if (interesting_fd > -1) {
|
||||
len = read(interesting_fd, &uwsgi_signal, 1);
|
||||
if (len <= 0) {
|
||||
if (len < 0 && (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)) goto clear;
|
||||
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
|
||||
end_me(0);
|
||||
}
|
||||
@@ -350,7 +354,7 @@ next:
|
||||
uwsgi_log_verbose("master sent signal %d to mule %d\n", uwsgi_signal, uwsgi.muleid);
|
||||
#endif
|
||||
if (uwsgi_signal_handler(uwsgi_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.muleid);
|
||||
}
|
||||
// set the error condition
|
||||
len = -1;
|
||||
|
||||
@@ -157,6 +157,8 @@ int uwsgi_apply_routes_do(struct wsgi_request *wsgi_req, char *subject, uint16_t
|
||||
|
||||
while (routes) {
|
||||
|
||||
if (routes->label) goto next;
|
||||
|
||||
if (wsgi_req->route_goto > 0 && wsgi_req->route_pc < wsgi_req->route_goto) {
|
||||
goto next;
|
||||
}
|
||||
|
||||
+3
-1
@@ -260,6 +260,8 @@ int uwsgi_add_probe(uint8_t sig, char *kind, char *args, int timeout, int freq)
|
||||
|
||||
int uwsgi_add_timer(uint8_t sig, int secs) {
|
||||
|
||||
if (!uwsgi.master_process) return -1;
|
||||
|
||||
uwsgi_lock(uwsgi.timer_table_lock);
|
||||
|
||||
if (ushared->timers_cnt < 64) {
|
||||
@@ -595,7 +597,7 @@ void uwsgi_receive_signal(int fd, char *name, int id) {
|
||||
if (ret == 0) {
|
||||
goto destroy;
|
||||
}
|
||||
else if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
|
||||
else if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) {
|
||||
uwsgi_error("[uwsgi-signal] read()");
|
||||
goto destroy;
|
||||
}
|
||||
|
||||
@@ -108,7 +108,6 @@ pid_t spooler_start(struct uwsgi_spooler * uspool) {
|
||||
signal(SIGSTOP, SIG_IGN);
|
||||
signal(SIGTSTP, SIG_IGN);
|
||||
|
||||
uwsgi.mywid = -1;
|
||||
uwsgi.mypid = getpid();
|
||||
uspool->pid = uwsgi.mypid;
|
||||
// avoid race conditions !!!
|
||||
|
||||
+2
-2
@@ -315,7 +315,7 @@ int uwsgi_add_expires_uri(struct wsgi_request *wsgi_req, struct stat *st) {
|
||||
#endif
|
||||
|
||||
|
||||
char *uwsgi_get_mime_type(char *name, int namelen, int *size) {
|
||||
char *uwsgi_get_mime_type(char *name, int namelen, size_t *size) {
|
||||
|
||||
int i;
|
||||
int count = 0;
|
||||
@@ -429,7 +429,7 @@ static int uwsgi_static_stat(struct wsgi_request *wsgi_req, char *filename, size
|
||||
|
||||
int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, size_t real_filename_len, struct stat *st) {
|
||||
|
||||
int mime_type_size = 0;
|
||||
size_t mime_type_size = 0;
|
||||
char http_last_modified[49];
|
||||
|
||||
if (uwsgi.threads > 1)
|
||||
|
||||
@@ -3480,6 +3480,7 @@ int uwsgi_kvlist_parse(char *src, size_t len, char list_separator, char kv_separ
|
||||
escaped = 1;
|
||||
}
|
||||
else if (escaped) {
|
||||
*ptr++ = src[i];
|
||||
escaped = 0;
|
||||
}
|
||||
else {
|
||||
|
||||
+94
-15
@@ -70,6 +70,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"xmlconfig", required_argument, 'x', "load config from xml file", uwsgi_opt_load_xml, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"xml", required_argument, 'x', "load config from xml file", uwsgi_opt_load_xml, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#endif
|
||||
{"config", required_argument, 0, "load configuration using the pluggable system", uwsgi_opt_load_config, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"skip-zero", no_argument, 0, "skip check of file descriptor 0", uwsgi_opt_true, &uwsgi.skip_zero, 0},
|
||||
|
||||
@@ -165,12 +166,14 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"single-interpreter", no_argument, 'i', "do not use multiple interpreters (where available)", uwsgi_opt_true, &uwsgi.single_interpreter, 0},
|
||||
{"need-app", no_argument, 0, "exit if no app can be loaded", uwsgi_opt_true, &uwsgi.need_app, 0},
|
||||
{"master", no_argument, 'M', "enable master process", uwsgi_opt_true, &uwsgi.master_process, 0},
|
||||
{"honour-stdin", no_argument, 0, "do not remap stdin to /dev/null", uwsgi_opt_true, &uwsgi.honour_stdin, 0},
|
||||
{"emperor", required_argument, 0, "run the Emperor", uwsgi_opt_add_string_list, &uwsgi.emperor, 0},
|
||||
{"emperor-procname", required_argument, 0, "set the Emperor process name", uwsgi_opt_set_str, &uwsgi.emperor_procname, 0},
|
||||
{"emperor-freq", required_argument, 0, "set the Emperor scan frequency (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.emperor_freq, 0},
|
||||
{"emperor-required-heartbeat", required_argument, 0, "set the Emperor tolerance about heartbeats", uwsgi_opt_set_int, &uwsgi.emperor_heartbeat, 0},
|
||||
{"emperor-pidfile", required_argument, 0, "write the Emperor pid in the specified file", uwsgi_opt_set_str, &uwsgi.emperor_pidfile, 0},
|
||||
{"emperor-tyrant", no_argument, 0, "put the Emperor in Tyrant mode", uwsgi_opt_true, &uwsgi.emperor_tyrant, 0},
|
||||
{"emperor-tyrant-nofollow", no_argument, 0, "do not follow symlinks when checking for uid/gid in Tyrant mode", uwsgi_opt_true, &uwsgi.emperor_tyrant_nofollow, 0},
|
||||
{"emperor-stats", required_argument, 0, "run the Emperor stats server", uwsgi_opt_set_str, &uwsgi.emperor_stats, 0},
|
||||
{"emperor-stats-server", required_argument, 0, "run the Emperor stats server", uwsgi_opt_set_str, &uwsgi.emperor_stats, 0},
|
||||
{"early-emperor", no_argument, 0, "spawn the emperor as soon as possibile", uwsgi_opt_true, &uwsgi.early_emperor, 0},
|
||||
@@ -183,6 +186,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"emperor-on-demand-directory", required_argument, 0, "enable on demand mode binding to the unix socket in the specified directory named like the vassal + .socket", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_directory, 0},
|
||||
{"emperor-on-demand-dir", required_argument, 0, "enable on demand mode binding to the unix socket in the specified directory named like the vassal + .socket", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_directory, 0},
|
||||
{"emperor-on-demand-exec", required_argument, 0, "use the output of the specified command as on demand socket name (the vassal name is passed as the only argument)", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_exec, 0},
|
||||
{"emperor-extra-extension", required_argument, 0, "allows the specified extension in the Emperor (vassal will be called with --config)", uwsgi_opt_add_string_list, &uwsgi.emperor_extra_extension, 0},
|
||||
{"emperor-extra-ext", required_argument, 0, "allows the specified extension in the Emperor (vassal will be called with --config)", uwsgi_opt_add_string_list, &uwsgi.emperor_extra_extension, 0},
|
||||
{"imperial-monitor-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0},
|
||||
{"imperial-monitors-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0},
|
||||
{"vassals-inherit", required_argument, 0, "add config templates to vassals config", uwsgi_opt_add_string_list, &uwsgi.vassals_templates, 0},
|
||||
@@ -263,6 +268,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"chroot", required_argument, 0, "chroot() to the specified directory", uwsgi_opt_set_str, &uwsgi.chroot, 0},
|
||||
{"uid", required_argument, 0, "setuid to the specified user/uid", uwsgi_opt_set_uid, NULL, 0},
|
||||
{"gid", required_argument, 0, "setgid to the specified group/gid", uwsgi_opt_set_gid, NULL, 0},
|
||||
{"immediate-uid", required_argument, 0, "setuid to the specified user/uid IMMEDIATELY", uwsgi_opt_set_immediate_uid, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"immediate-gid", required_argument, 0, "setgid to the specified group/gid IMMEDIATELY", uwsgi_opt_set_immediate_gid, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"no-initgroups", no_argument, 0, "disable additional groups set via initgroups()", uwsgi_opt_true, &uwsgi.no_initgroups, 0},
|
||||
#ifdef UWSGI_CAP
|
||||
{"cap", required_argument, 0, "set process capability", uwsgi_opt_set_cap, NULL, 0},
|
||||
@@ -377,6 +384,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"legion-unlord", required_argument, 0, "action to call on Lord dismiss", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-setup", required_argument, 0, "action to call on legion setup", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-death", required_argument, 0, "action to call on legion death (shutdown of the instance)", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-join", required_argument, 0, "action to call on legion join (first time quorum is reached)", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-quorum", required_argument, 0, "set the quorum of a legion", uwsgi_opt_legion_quorum, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-scroll", required_argument, 0, "set the scroll of a legion", uwsgi_opt_legion_scroll, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-scroll-max-size", required_argument, 0, "set max size of legion scroll buffer", uwsgi_opt_set_16bit, &uwsgi.legion_scroll_max_size, 0},
|
||||
@@ -606,6 +614,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"attach-daemon", required_argument, 0, "attach a command/daemon to the master process (the command has to not go in background)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
{"smart-attach-daemon", required_argument, 0, "attach a command/daemon to the master process managed by a pidfile (the command has to daemonize)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
{"smart-attach-daemon2", required_argument, 0, "attach a command/daemon to the master process managed by a pidfile (the command has to NOT daemonize)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
{"daemons-honour-stdin", no_argument, 0, "do not change the stdin of external daemons to /dev/null", uwsgi_opt_true, &uwsgi.daemons_honour_stdin, UWSGI_OPT_MASTER},
|
||||
{"plugins", required_argument, 0, "load uWSGI plugins", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"plugin", required_argument, 0, "load uWSGI plugins", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"plugins-dir", required_argument, 0, "add a directory to uWSGI plugin search path", uwsgi_opt_add_string_list, &uwsgi.plugins_dir, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -2120,6 +2129,20 @@ int uwsgi_start(void *v_argv) {
|
||||
// automatically fix options
|
||||
sanitize_args();
|
||||
|
||||
|
||||
if (uwsgi.requested_max_fd) {
|
||||
uwsgi.rl.rlim_cur = uwsgi.requested_max_fd;
|
||||
uwsgi.rl.rlim_max = uwsgi.requested_max_fd;
|
||||
if (setrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
|
||||
uwsgi_error("setrlimit()");
|
||||
}
|
||||
}
|
||||
|
||||
if (!getrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
|
||||
uwsgi.max_fd = uwsgi.rl.rlim_cur;
|
||||
uwsgi_log_initial("detected max file descriptor number: %lu\n", (unsigned long) uwsgi.max_fd);
|
||||
}
|
||||
|
||||
// start the Emperor if needed
|
||||
if (!uwsgi.early_emperor && uwsgi.emperor) {
|
||||
uwsgi_emperor_start();
|
||||
@@ -2144,19 +2167,6 @@ int uwsgi_start(void *v_argv) {
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.requested_max_fd) {
|
||||
uwsgi.rl.rlim_cur = uwsgi.requested_max_fd;
|
||||
uwsgi.rl.rlim_max = uwsgi.requested_max_fd;
|
||||
if (setrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
|
||||
uwsgi_error("setrlimit()");
|
||||
}
|
||||
}
|
||||
|
||||
if (!getrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
|
||||
uwsgi.max_fd = uwsgi.rl.rlim_cur;
|
||||
uwsgi_log_initial("detected max file descriptor number: %lu\n", (unsigned long) uwsgi.max_fd);
|
||||
}
|
||||
|
||||
if (uwsgi.async > 1) {
|
||||
if ((unsigned long) uwsgi.max_fd < (unsigned long) uwsgi.async) {
|
||||
uwsgi_log("- your current max open files limit is %lu, this is lower than requested async cores !!! -\n", (unsigned long) uwsgi.max_fd);
|
||||
@@ -2542,11 +2552,9 @@ next:
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_MINTERPRETERS
|
||||
if (!uwsgi.single_interpreter && uwsgi.numproc > 0) {
|
||||
uwsgi_log("*** uWSGI is running in multiple interpreter mode ***\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
// check for request plugins, and eventually print a warning
|
||||
int rp_available = 0;
|
||||
@@ -3185,6 +3193,59 @@ void uwsgi_opt_true(char *opt, char *value, void *key) {
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_opt_set_immediate_gid(char *opt, char *value, void *none) {
|
||||
gid_t gid = atoi(value);
|
||||
if (gid == 0) {
|
||||
struct group *ugroup = getgrnam(value);
|
||||
if (ugroup)
|
||||
gid = ugroup->gr_gid;
|
||||
}
|
||||
if (gid <= 0) {
|
||||
uwsgi_log("uwsgi_opt_set_immediate_gid(): invalid gid %d\n", (int) gid);
|
||||
exit(1);
|
||||
}
|
||||
if (setgid(gid)) {
|
||||
uwsgi_error("uwsgi_opt_set_immediate_gid()/setgid()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (setgroups(0, NULL)) {
|
||||
uwsgi_error("uwsgi_opt_set_immediate_gid()/setgroups()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
gid = getgid();
|
||||
if (!gid) {
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("immediate gid: %d\n", (int) gid);
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_set_immediate_uid(char *opt, char *value, void *none) {
|
||||
uid_t uid = atoi(value);
|
||||
if (uid == 0) {
|
||||
struct passwd *upasswd = getpwnam(value);
|
||||
if (upasswd)
|
||||
uid = upasswd->pw_uid;
|
||||
}
|
||||
if (uid <= 0) {
|
||||
uwsgi_log("uwsgi_opt_set_immediate_uid(): invalid uid %d\n", uid);
|
||||
exit(1);
|
||||
}
|
||||
if (setuid(uid)) {
|
||||
uwsgi_error("uwsgi_opt_set_immediate_uid()/setuid()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uid = getuid();
|
||||
if (!uid) {
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("immediate uid: %d\n", (int) uid);
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_set_int(char *opt, char *value, void *key) {
|
||||
int *ptr = (int *) key;
|
||||
if (value) {
|
||||
@@ -3764,6 +3825,9 @@ void uwsgi_opt_load(char *opt, char *filename, void *none) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// fallback to pluggable system
|
||||
uwsgi_opt_load_config(opt, filename, none);
|
||||
}
|
||||
|
||||
void uwsgi_opt_logic(char *opt, char *arg, void *func) {
|
||||
@@ -3790,6 +3854,21 @@ void uwsgi_opt_load_ini(char *opt, char *filename, void *none) {
|
||||
uwsgi_ini_config(filename, uwsgi.magic_table);
|
||||
}
|
||||
|
||||
void uwsgi_opt_load_config(char *opt, char *filename, void *none) {
|
||||
struct uwsgi_configurator *uc = uwsgi.configurators;
|
||||
while(uc) {
|
||||
if (uwsgi_endswith(filename, uc->name)) {
|
||||
config_magic_table_fill(filename, uwsgi.magic_table);
|
||||
uc->func(filename, uwsgi.magic_table);
|
||||
return;
|
||||
}
|
||||
uc = uc->next;
|
||||
}
|
||||
|
||||
uwsgi_log("unable to load configuration from %s\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_XML
|
||||
void uwsgi_opt_load_xml(char *opt, char *filename, void *none) {
|
||||
config_magic_table_fill(filename, uwsgi.magic_table);
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
config = {}
|
||||
|
||||
config['immediate-uid'] = 'roberto'
|
||||
config['immediate-gid'] = 'roberto'
|
||||
config['http-socket'] = ':9090'
|
||||
config['env'] = { 'FOO=bar', 'TEST=topogigio' }
|
||||
config['module'] = 'werkzeug.testapp:test_app'
|
||||
|
||||
return config
|
||||
@@ -0,0 +1,8 @@
|
||||
config = {}
|
||||
|
||||
config[1] = { ['http-socket']=':9090' }
|
||||
config[2] = { ['env']='FOO=bar' }
|
||||
config[3] = { ['env']='TEST=topogigio' }
|
||||
config[4] = { ['module']='werkzeug.testapp:test_app' }
|
||||
|
||||
return config
|
||||
@@ -74,12 +74,17 @@ static void carbon_post_init() {
|
||||
else if (!u_server->port) {
|
||||
u_server->port = uwsgi_str(p);
|
||||
}
|
||||
else break;
|
||||
else
|
||||
break;
|
||||
p = strtok(NULL, ":");
|
||||
}
|
||||
if (!u_server->hostname || !u_server->port) {
|
||||
uwsgi_log("[carbon] invalid carbon server address (%s)\n", usl->value);
|
||||
usl = usl->next;
|
||||
|
||||
if (u_server->hostname) free(u_server->hostname);
|
||||
if (u_server->port) free(u_server->port);
|
||||
free(u_server);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
+109
-43
@@ -18,7 +18,7 @@ struct uwsgi_cgi {
|
||||
int path_info;
|
||||
} uc ;
|
||||
|
||||
void uwsgi_opt_add_cgi(char *opt, char *value, void *foobar) {
|
||||
static void uwsgi_opt_add_cgi(char *opt, char *value, void *foobar) {
|
||||
|
||||
char *val = strchr(value, '=');
|
||||
if (!val) {
|
||||
@@ -30,7 +30,7 @@ void uwsgi_opt_add_cgi(char *opt, char *value, void *foobar) {
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_opt_add_cgi_maphelper(char *opt, char *value, void *foobar) {
|
||||
static void uwsgi_opt_add_cgi_maphelper(char *opt, char *value, void *foobar) {
|
||||
char *val = strchr(value, '=');
|
||||
if (!val) {
|
||||
uwsgi_log("invalid CGI helper syntax, must be ext=command\n");
|
||||
@@ -66,7 +66,7 @@ struct uwsgi_option uwsgi_cgi_options[] = {
|
||||
|
||||
};
|
||||
|
||||
void uwsgi_cgi_apps() {
|
||||
static void uwsgi_cgi_apps() {
|
||||
|
||||
struct uwsgi_dyn_dict *udd = uc.mountpoint;
|
||||
struct stat st;
|
||||
@@ -123,7 +123,7 @@ void uwsgi_cgi_apps() {
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_cgi_init(){
|
||||
static int uwsgi_cgi_init(){
|
||||
|
||||
void (*cgi_sym)(void);
|
||||
|
||||
@@ -161,7 +161,7 @@ int uwsgi_cgi_init(){
|
||||
|
||||
}
|
||||
|
||||
char *uwsgi_cgi_get_helper(char *filename) {
|
||||
static char *uwsgi_cgi_get_helper(char *filename) {
|
||||
|
||||
struct uwsgi_dyn_dict *helpers = uc.helpers;
|
||||
size_t len = strlen(filename);
|
||||
@@ -179,7 +179,7 @@ char *uwsgi_cgi_get_helper(char *filename) {
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
static int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
|
||||
size_t i;
|
||||
char *key = buf, *value = NULL;
|
||||
@@ -266,7 +266,7 @@ send_body:
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *uwsgi_cgi_get_docroot(char *path_info, uint16_t path_info_len, int *need_free, int *is_a_file, int *discard_base, char **script_name) {
|
||||
static char *uwsgi_cgi_get_docroot(char *path_info, uint16_t path_info_len, int *need_free, int *is_a_file, int *discard_base, char **script_name) {
|
||||
|
||||
struct uwsgi_dyn_dict *udd = uc.mountpoint, *choosen_udd = NULL;
|
||||
int best_found = 0;
|
||||
@@ -323,7 +323,7 @@ char *uwsgi_cgi_get_docroot(char *path_info, uint16_t path_info_len, int *need_f
|
||||
return path;
|
||||
}
|
||||
|
||||
int uwsgi_cgi_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot, size_t docroot_len, int discard_base, char **path_info) {
|
||||
static int uwsgi_cgi_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot, size_t docroot_len, int discard_base, char **path_info) {
|
||||
|
||||
// and now start walking...
|
||||
uint16_t i;
|
||||
@@ -380,18 +380,12 @@ int uwsgi_cgi_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
static int uwsgi_cgi_run(struct wsgi_request *, char *, size_t, char *, char *, char *, char *, int, int);
|
||||
|
||||
static int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
int i;
|
||||
pid_t cgi_pid;
|
||||
int waitpid_status;
|
||||
char **argv;
|
||||
int nargs = 0;
|
||||
char full_path[PATH_MAX];
|
||||
char tmp_path[PATH_MAX];
|
||||
int cgi_pipe[2];
|
||||
int post_pipe[2];
|
||||
ssize_t len;
|
||||
struct stat cgi_stat;
|
||||
int need_free = 0;
|
||||
int is_a_file = 0;
|
||||
@@ -399,7 +393,6 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
size_t docroot_len = 0;
|
||||
size_t full_path_len = 0;
|
||||
char *helper = NULL;
|
||||
char *command = NULL;
|
||||
char *path_info = NULL;
|
||||
char *script_name = NULL;
|
||||
|
||||
@@ -533,11 +526,8 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
if (is_a_file) {
|
||||
command = docroot;
|
||||
}
|
||||
else {
|
||||
command = full_path;
|
||||
// get the helper
|
||||
if (!is_a_file) {
|
||||
helper = uwsgi_cgi_get_helper(full_path);
|
||||
|
||||
if (helper == NULL) {
|
||||
@@ -551,28 +541,43 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
}
|
||||
|
||||
int ret = uwsgi_cgi_run(wsgi_req, docroot, docroot_len, full_path, helper, path_info, script_name, is_a_file, discard_base);
|
||||
if (need_free) free(docroot);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_cgi_run(struct wsgi_request *wsgi_req, char *docroot, size_t docroot_len, char *full_path, char *helper, char *path_info, char *script_name, int is_a_file, int discard_base) {
|
||||
|
||||
int cgi_pipe[2];
|
||||
int post_pipe[2];
|
||||
int nargs = 0;
|
||||
int waitpid_status;
|
||||
ssize_t len;
|
||||
int i;
|
||||
char **argv;
|
||||
|
||||
char *command = full_path;
|
||||
|
||||
if (is_a_file) {
|
||||
command = docroot;
|
||||
}
|
||||
|
||||
if (pipe(cgi_pipe)) {
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
uwsgi_error("pipe()");
|
||||
uwsgi_error("uwsgi_cgi_run()/pipe()");
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
if (pipe(post_pipe)) {
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
close(cgi_pipe[0]);
|
||||
close(cgi_pipe[1]);
|
||||
uwsgi_error("pipe()");
|
||||
uwsgi_error("uwsgi_cgi_run()/pipe()");
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
cgi_pid = fork();
|
||||
pid_t cgi_pid = fork();
|
||||
|
||||
if (cgi_pid < 0) {
|
||||
uwsgi_error("fork()");
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
uwsgi_error("uwsgi_cgi_run()/fork()");
|
||||
close(cgi_pipe[0]);
|
||||
close(cgi_pipe[1]);
|
||||
close(post_pipe[0]);
|
||||
@@ -582,9 +587,6 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (cgi_pid > 0) {
|
||||
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
|
||||
close(cgi_pipe[1]);
|
||||
close(post_pipe[0]);
|
||||
|
||||
@@ -795,7 +797,7 @@ clear2:
|
||||
}
|
||||
*base = '/';
|
||||
}
|
||||
else {
|
||||
else if (docroot_len > 0) {
|
||||
if (chdir(docroot)) {
|
||||
uwsgi_error("chdir()");
|
||||
}
|
||||
@@ -837,9 +839,8 @@ clear2:
|
||||
escape_shell_arg(arg_copy, arg_copy_len, argv[i]);
|
||||
i++;
|
||||
p = strtok(NULL, "+");
|
||||
}
|
||||
}
|
||||
else {
|
||||
}
|
||||
free(qs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -864,7 +865,7 @@ clear2:
|
||||
}
|
||||
|
||||
if (execvp(argv[0], argv)) {
|
||||
uwsgi_error("execvp()");
|
||||
uwsgi_error("uwsgi_cgi_run()/execvp()");
|
||||
}
|
||||
|
||||
// never here
|
||||
@@ -872,11 +873,73 @@ clear2:
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_cgi_after_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
static void uwsgi_cgi_after_request(struct wsgi_request *wsgi_req) {
|
||||
log_request(wsgi_req);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
static int uwsgi_routing_func_cgi(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_command = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
||||
if (!ub_command) return UWSGI_ROUTE_BREAK;
|
||||
struct uwsgi_buffer *ub_helper = NULL;
|
||||
if (ur->data2_len) {
|
||||
ub_helper = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data2, ur->data2_len);
|
||||
if (!ub_helper) {
|
||||
uwsgi_buffer_destroy(ub_command);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!uwsgi_is_file(ub_command->buf)) {
|
||||
uwsgi_404(wsgi_req);
|
||||
uwsgi_buffer_destroy(ub_command);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
if (access(ub_command->buf, X_OK)) {
|
||||
uwsgi_403(wsgi_req);
|
||||
uwsgi_buffer_destroy(ub_command);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
}
|
||||
// we need a NULL suffix-ed copy of the docroot
|
||||
char *docroot = uwsgi_concat2n(wsgi_req->document_root, wsgi_req->document_root_len, "", 0);
|
||||
uwsgi_cgi_run(wsgi_req, wsgi_req->document_root, wsgi_req->document_root_len, ub_command->buf, ub_helper ? ub_helper->buf : NULL, NULL, NULL, 0, 0 );
|
||||
free(docroot);
|
||||
uwsgi_buffer_destroy(ub_command);
|
||||
if (ub_helper) uwsgi_buffer_destroy(ub_helper);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
static int uwsgi_router_cgi_helper(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_cgi;
|
||||
char *space = strchr(args, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid cgihelper syntax, must be \"cgihelper:helper command\"\n");
|
||||
return -1;
|
||||
}
|
||||
*space = 0;
|
||||
ur->data = space+1;
|
||||
ur->data_len = strlen(space+1);
|
||||
ur->data2 = args;
|
||||
ur->data2_len = strlen(args);
|
||||
return 0;
|
||||
}
|
||||
static int uwsgi_router_cgi(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_cgi;
|
||||
ur->data = args;
|
||||
ur->data_len = strlen(args);
|
||||
return 0;
|
||||
}
|
||||
static void uwsgi_cgi_register_router() {
|
||||
uwsgi_register_router("cgi", uwsgi_router_cgi);
|
||||
uwsgi_register_router("cgihelper", uwsgi_router_cgi_helper);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct uwsgi_plugin cgi_plugin = {
|
||||
|
||||
@@ -887,5 +950,8 @@ struct uwsgi_plugin cgi_plugin = {
|
||||
.options = uwsgi_cgi_options,
|
||||
.request = uwsgi_cgi_request,
|
||||
.after_request = uwsgi_cgi_after_request,
|
||||
#ifdef UWSGI_ROUTING
|
||||
.on_load = uwsgi_cgi_register_router,
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
@@ -13,8 +13,9 @@ class FakeClass {
|
||||
|
||||
void FakeClass::hello_world(struct wsgi_request *wsgi_req) {
|
||||
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, (char *) "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n", 44);
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, foobar, foobar_len);
|
||||
uwsgi_response_prepare_headers(wsgi_req, (char *)"200 OK", 6);
|
||||
uwsgi_response_add_content_type(wsgi_req, (char *)"text/html", 9);
|
||||
uwsgi_response_write_body_do(wsgi_req, foobar, foobar_len);
|
||||
}
|
||||
|
||||
extern "C" int uwsgi_cplusplus_init(){
|
||||
@@ -27,7 +28,7 @@ extern "C" int uwsgi_cplusplus_request(struct wsgi_request *wsgi_req) {
|
||||
FakeClass *fc;
|
||||
|
||||
// empty request ?
|
||||
if (!wsgi_req->uh.pktsize) {
|
||||
if (!wsgi_req->uh->pktsize) {
|
||||
uwsgi_log( "Invalid request. skip.\n");
|
||||
goto clear;
|
||||
}
|
||||
@@ -55,6 +56,7 @@ clear:
|
||||
|
||||
|
||||
extern "C" void uwsgi_cplusplus_after_request(struct wsgi_request *wsgi_req) {
|
||||
// call log_request(wsgi_req) if you want a standard logline
|
||||
uwsgi_log("logging c++ request\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
|
||||
int uwsgi_cplusplus_init(void);
|
||||
|
||||
@@ -0,0 +1,272 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
#include <client/dbclient.h>
|
||||
#include <client/gridfs.h>
|
||||
|
||||
struct uwsgi_gridfs_mountpoint {
|
||||
char *mountpoint;
|
||||
uint16_t mountpoint_len;
|
||||
char *server;
|
||||
char *db;
|
||||
char *timeout_str;
|
||||
int timeout;
|
||||
char *no_mime;
|
||||
char *orig_filename;
|
||||
char *md5;
|
||||
char *etag;
|
||||
char *prefix;
|
||||
char *itemname;
|
||||
uint16_t itemname_len;
|
||||
char *skip_slash;
|
||||
uint16_t prefix_len;
|
||||
};
|
||||
|
||||
struct uwsgi_gridfs {
|
||||
int debug;
|
||||
struct uwsgi_string_list *mountpoints;
|
||||
} ugridfs;
|
||||
|
||||
struct uwsgi_option uwsgi_gridfs_options[] = {
|
||||
{(char *)"gridfs-mount", required_argument, 0, (char *)"mount a gridfs db on the specified mountpoint", uwsgi_opt_add_string_list, &ugridfs.mountpoints, UWSGI_OPT_MIME},
|
||||
{(char *)"gridfs-debug", no_argument, 0, (char *)"report gridfs mountpoint and itemname for each request (debug)", uwsgi_opt_true, &ugridfs.debug, UWSGI_OPT_MIME},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_plugin gridfs_plugin;
|
||||
|
||||
static void uwsgi_gridfs_do(struct wsgi_request *wsgi_req, struct uwsgi_gridfs_mountpoint *ugm, char *itemname, int need_free) {
|
||||
|
||||
try {
|
||||
mongo::scoped_ptr<mongo::ScopedDbConnection> conn( mongo::ScopedDbConnection::getScopedDbConnection(ugm->server, ugm->timeout) );
|
||||
try {
|
||||
mongo::GridFS gridfs((*conn).conn(), ugm->db);
|
||||
mongo::GridFile gfile = gridfs.findFile(itemname);
|
||||
if (need_free) {
|
||||
free(itemname);
|
||||
itemname = NULL;
|
||||
}
|
||||
if (!gfile.exists()) {
|
||||
(*conn).done();
|
||||
uwsgi_404(wsgi_req);
|
||||
return;
|
||||
}
|
||||
uwsgi_response_prepare_headers(wsgi_req, (char *)"200 OK", 6);
|
||||
// first get the content_type (if possibile)
|
||||
std::string filename = gfile.getFilename();
|
||||
if (!ugm->no_mime) {
|
||||
size_t mime_type_len = 0;
|
||||
char *mime_type = uwsgi_get_mime_type((char *)filename.c_str(), filename.length(), &mime_type_len);
|
||||
if (mime_type) {
|
||||
uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_len);
|
||||
}
|
||||
}
|
||||
if (ugm->orig_filename) {
|
||||
char *filename_header = uwsgi_concat3((char *)"inline; filename=\"", (char *)filename.c_str(), (char *)"\"");
|
||||
uwsgi_response_add_header(wsgi_req, (char *)"Content-Disposition", 19, filename_header, 19 + filename.length());
|
||||
free(filename_header);
|
||||
}
|
||||
uwsgi_response_add_content_length(wsgi_req, gfile.getContentLength());
|
||||
|
||||
if (ugm->etag) {
|
||||
std::string g_md5 = gfile.getMD5();
|
||||
if (!g_md5.empty()) {
|
||||
char *etag = uwsgi_concat3((char *)"\"", (char *)g_md5.c_str(), (char *)"\"");
|
||||
uwsgi_response_add_header(wsgi_req, (char *)"ETag", 4, etag, 2+g_md5.length());
|
||||
free(etag);
|
||||
}
|
||||
}
|
||||
|
||||
if (ugm->md5) {
|
||||
std::string g_md5 = gfile.getMD5();
|
||||
size_t base64_len = 0;
|
||||
char *base64 = uwsgi_base64_encode((char *)g_md5.c_str(), g_md5.length(), &base64_len);
|
||||
uwsgi_response_add_header(wsgi_req, (char *) "Content-MD5", 11, base64, base64_len);
|
||||
free(base64);
|
||||
}
|
||||
|
||||
if (uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, (char *)"HEAD", 4)) {
|
||||
int nc = gfile.getNumChunks();
|
||||
int i;
|
||||
for(i=0;i<nc;i++) {
|
||||
mongo::GridFSChunk gchunk = gfile.getChunk(i);
|
||||
int chunk_len = 0;
|
||||
const char *chunk = gchunk.data(chunk_len);
|
||||
uwsgi_response_write_body_do(wsgi_req, (char *) chunk, chunk_len);
|
||||
}
|
||||
}
|
||||
(*conn).done();
|
||||
}
|
||||
catch ( mongo::DBException &e ) {
|
||||
uwsgi_log("[uwsgi-gridfs]: %s\n", e.what());
|
||||
(*conn).done();
|
||||
if (need_free && itemname) {
|
||||
free(itemname);
|
||||
itemname = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( mongo::DBException &e ) {
|
||||
uwsgi_log("[uwsgi-gridfs]: %s\n", e.what());
|
||||
if (need_free && itemname) {
|
||||
free(itemname);
|
||||
itemname = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct uwsgi_gridfs_mountpoint *uwsgi_gridfs_add_mountpoint(char *arg, size_t arg_len) {
|
||||
struct uwsgi_gridfs_mountpoint *ugm = (struct uwsgi_gridfs_mountpoint *) uwsgi_calloc(sizeof(struct uwsgi_gridfs_mountpoint));
|
||||
if (uwsgi_kvlist_parse(arg, arg_len, ',', '=',
|
||||
"mountpoint", &ugm->mountpoint,
|
||||
"server", &ugm->server,
|
||||
"db", &ugm->db,
|
||||
"prefix", &ugm->prefix,
|
||||
"no_mime", &ugm->no_mime,
|
||||
"timeout", &ugm->timeout_str,
|
||||
"orig_filename", &ugm->orig_filename,
|
||||
"skip_slash", &ugm->skip_slash,
|
||||
"md5", &ugm->md5,
|
||||
"etag", &ugm->etag,
|
||||
"itemname", &ugm->itemname,
|
||||
"item", &ugm->itemname,
|
||||
NULL)) {
|
||||
uwsgi_log("invalid gridfs mountpoint syntax\n");
|
||||
free(ugm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!ugm->db) {
|
||||
uwsgi_log("you need to specify a \"db\" name for gridfs\n");
|
||||
free(ugm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!ugm->mountpoint) {
|
||||
ugm->mountpoint = (char *)"";
|
||||
}
|
||||
ugm->mountpoint_len = strlen(ugm->mountpoint);
|
||||
|
||||
if (!ugm->server) {
|
||||
ugm->server = (char *)"127.0.0.1:27017";
|
||||
}
|
||||
|
||||
if (ugm->timeout_str) {
|
||||
ugm->timeout = atoi(ugm->timeout_str);
|
||||
}
|
||||
else {
|
||||
ugm->timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
|
||||
}
|
||||
|
||||
if (ugm->prefix) {
|
||||
ugm->prefix_len = strlen(ugm->prefix);
|
||||
}
|
||||
|
||||
if (ugm->itemname) {
|
||||
ugm->itemname_len = strlen(ugm->itemname);
|
||||
}
|
||||
|
||||
return ugm;
|
||||
}
|
||||
|
||||
extern "C" int uwsgi_gridfs_request(struct wsgi_request *wsgi_req) {
|
||||
// this is the gridfs file
|
||||
char *itemname = NULL;
|
||||
|
||||
/* Standard GridFS request */
|
||||
if (!wsgi_req->uh->pktsize) {
|
||||
uwsgi_log( "Empty GridFS request. skip.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uwsgi_parse_vars(wsgi_req)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (wsgi_req->appid_len == 0) {
|
||||
if (!uwsgi.ignore_script_name) {
|
||||
wsgi_req->appid = wsgi_req->script_name;
|
||||
wsgi_req->appid_len = wsgi_req->script_name_len;
|
||||
}
|
||||
}
|
||||
|
||||
wsgi_req->app_id = uwsgi_get_app_id(wsgi_req->appid, wsgi_req->appid_len, gridfs_plugin.modifier1);
|
||||
if (ugridfs.debug) {
|
||||
uwsgi_log("[uwsgi-gridfs-debug] app_id = %d\n", wsgi_req->app_id);
|
||||
}
|
||||
|
||||
if (wsgi_req->app_id == -1) {
|
||||
uwsgi_404(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
struct uwsgi_app *ua = &uwsgi_apps[wsgi_req->app_id];
|
||||
|
||||
struct uwsgi_gridfs_mountpoint *ugm = (struct uwsgi_gridfs_mountpoint *) ua->interpreter;
|
||||
|
||||
if (ugm->skip_slash && (wsgi_req->path_info_len > 0 && wsgi_req->path_info[0] == '/')) {
|
||||
itemname = uwsgi_concat2n(ugm->prefix, ugm->prefix_len, wsgi_req->path_info+1, wsgi_req->path_info_len-1);
|
||||
}
|
||||
else {
|
||||
itemname = uwsgi_concat2n(ugm->prefix, ugm->prefix_len, wsgi_req->path_info, wsgi_req->path_info_len);
|
||||
}
|
||||
|
||||
if (ugridfs.debug) {
|
||||
uwsgi_log("[uwsgi-gridfs-debug] itemname = %s\n", itemname);
|
||||
}
|
||||
|
||||
// itemname will be freed here
|
||||
uwsgi_gridfs_do(wsgi_req, ugm, itemname, 1);
|
||||
|
||||
return UWSGI_OK;
|
||||
|
||||
}
|
||||
|
||||
|
||||
extern "C" void uwsgi_gridfs_mount() {
|
||||
struct uwsgi_string_list *usl = ugridfs.mountpoints;
|
||||
while(usl) {
|
||||
if (uwsgi_apps_cnt >= uwsgi.max_apps) {
|
||||
uwsgi_log("ERROR: you cannot load more than %d apps in a worker\n", uwsgi.max_apps);
|
||||
exit(1);
|
||||
}
|
||||
int id = uwsgi_apps_cnt;
|
||||
struct uwsgi_gridfs_mountpoint *ugm = uwsgi_gridfs_add_mountpoint(uwsgi_str(usl->value), usl->len);
|
||||
if (!ugm) exit(1);
|
||||
uwsgi_add_app(id, gridfs_plugin.modifier1, ugm->mountpoint, ugm->mountpoint_len, ugm, ugm);
|
||||
uwsgi_emulate_cow_for_apps(id);
|
||||
uwsgi_log("GridFS mountpoint \"%.*s\" (%d) added: server=%s db=%s\n", ugm->mountpoint_len, ugm->mountpoint, id, ugm->server, ugm->db);
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
static int uwsgi_routing_func_gridfs(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
|
||||
|
||||
struct uwsgi_gridfs_mountpoint *ugm = (struct uwsgi_gridfs_mountpoint *) ur->data2;
|
||||
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
struct uwsgi_buffer *ub_itemname = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ugm->itemname, ugm->itemname_len);
|
||||
if (!ub_itemname) return UWSGI_ROUTE_BREAK;
|
||||
if (ugridfs.debug) {
|
||||
uwsgi_log("[uwsgi-gridfs-debug] itemname = %s\n", ub_itemname->buf);
|
||||
}
|
||||
uwsgi_gridfs_do(wsgi_req, ugm, ub_itemname->buf, 0);
|
||||
uwsgi_buffer_destroy(ub_itemname);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
extern "C" int uwsgi_router_gridfs(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_gridfs;
|
||||
ur->data = args;
|
||||
ur->data_len = strlen(args);
|
||||
ur->data2 = uwsgi_gridfs_add_mountpoint((char *)ur->data, ur->data_len);
|
||||
if (!ur->data2) {
|
||||
exit(1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,31 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
int uwsgi_gridfs_request(struct wsgi_request *);
|
||||
void uwsgi_gridfs_mount();
|
||||
extern struct uwsgi_option uwsgi_gridfs_options[];
|
||||
|
||||
static void uwsgi_gridfs_log(struct wsgi_request *wsgi_req) {
|
||||
log_request(wsgi_req);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
int uwsgi_router_gridfs(struct uwsgi_route *, char *);
|
||||
static void uwsgi_gridfs_register_router() {
|
||||
uwsgi_register_router("gridfs", uwsgi_router_gridfs);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
struct uwsgi_plugin gridfs_plugin = {
|
||||
|
||||
.name = "gridfs",
|
||||
.modifier1 = 25,
|
||||
|
||||
.init_apps = uwsgi_gridfs_mount,
|
||||
.options = uwsgi_gridfs_options,
|
||||
.request = uwsgi_gridfs_request,
|
||||
.after_request = uwsgi_gridfs_log,
|
||||
#ifdef UWSGI_ROUTING
|
||||
.on_load = uwsgi_gridfs_register_router,
|
||||
#endif
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
import os
|
||||
|
||||
NAME='gridfs'
|
||||
|
||||
CFLAGS = ['-I/usr/include/mongo','-I/usr/local/include/mongo']
|
||||
LDFLAGS = []
|
||||
|
||||
LIBS = []
|
||||
if not 'UWSGI_MONGODB_NOLIB' in os.environ:
|
||||
LIBS.append('-lmongoclient')
|
||||
LIBS.append('-lstdc++')
|
||||
LIBS.append('-lboost_thread')
|
||||
LIBS.append('-lboost_system')
|
||||
LIBS.append('-lboost_filesystem')
|
||||
|
||||
GCC_LIST = ['plugin', 'gridfs.cc']
|
||||
@@ -1,4 +1,5 @@
|
||||
import os,sys
|
||||
import os
|
||||
import shutil
|
||||
|
||||
NAME='jvm'
|
||||
|
||||
|
||||
+116
-22
@@ -10,6 +10,7 @@ struct uwsgi_lua {
|
||||
struct lua_State **L;
|
||||
|
||||
char *filename;
|
||||
struct uwsgi_string_list *load;
|
||||
} ulua;
|
||||
|
||||
#define lca(L, n) ulua_check_args(L, __FUNCTION__, n)
|
||||
@@ -17,6 +18,7 @@ struct uwsgi_lua {
|
||||
static struct uwsgi_option uwsgi_lua_options[] = {
|
||||
|
||||
{"lua", required_argument, 0, "load lua wsapi app", uwsgi_opt_set_str, &ulua.filename, 0},
|
||||
{"lua-load", required_argument, 0, "load a lua file", uwsgi_opt_add_string_list, &ulua.load, 0},
|
||||
|
||||
{0, 0, 0, 0},
|
||||
|
||||
@@ -69,7 +71,7 @@ static int uwsgi_api_register_rpc(lua_State *L) {
|
||||
lua_pushvalue(L, 2);
|
||||
func = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
|
||||
uwsgi_log("registered function %d in global table\n", func);
|
||||
uwsgi_log("registered function %d in Lua global table\n", func);
|
||||
lfunc = func;
|
||||
|
||||
if (uwsgi_register_rpc((char *)name, 6, 0, (void *) lfunc)) {
|
||||
@@ -387,36 +389,48 @@ static int uwsgi_lua_init(){
|
||||
static void uwsgi_lua_app() {
|
||||
int i;
|
||||
|
||||
if (ulua.filename) {
|
||||
if (!ulua.filename && !ulua.load) return;
|
||||
|
||||
for(i=0;i<uwsgi.cores;i++) {
|
||||
ulua.L[i] = luaL_newstate();
|
||||
luaL_openlibs(ulua.L[i]);
|
||||
luaL_register(ulua.L[i], "uwsgi", uwsgi_api);
|
||||
if (luaL_loadfile(ulua.L[i], ulua.filename)) {
|
||||
uwsgi_log("unable to load file %s: %s\n", ulua.filename, lua_tostring(ulua.L[i], -1));
|
||||
exit(1);
|
||||
|
||||
struct uwsgi_string_list *usl = ulua.load;
|
||||
while(usl) {
|
||||
if (luaL_dofile(ulua.L[i], usl->value)) {
|
||||
uwsgi_log("unable to load Lua file %s: %s\n", usl->value, lua_tostring(ulua.L[i], -1));
|
||||
exit(1);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
if (ulua.filename) {
|
||||
if (luaL_loadfile(ulua.L[i], ulua.filename)) {
|
||||
uwsgi_log("unable to load Lua file %s: %s\n", ulua.filename, lua_tostring(ulua.L[i], -1));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// use a pcall
|
||||
//lua_call(ulua.L[i], 0, 1);
|
||||
if (lua_pcall(ulua.L[i], 0, 1, 0) != 0) {
|
||||
uwsgi_log("%s\n", lua_tostring(ulua.L[i], -1));
|
||||
exit(1);
|
||||
}
|
||||
// use a pcall
|
||||
//lua_call(ulua.L[i], 0, 1);
|
||||
if (lua_pcall(ulua.L[i], 0, 1, 0) != 0) {
|
||||
uwsgi_log("%s\n", lua_tostring(ulua.L[i], -1));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// if the loaded lua app returns as a table, fetch the
|
||||
// run function.
|
||||
if (lua_istable(ulua.L[i], 2)) {
|
||||
lua_pushstring(ulua.L[i], "run" );
|
||||
lua_gettable(ulua.L[i], 2);
|
||||
lua_replace(ulua.L[i], 2);
|
||||
}
|
||||
// if the loaded lua app returns as a table, fetch the
|
||||
// run function.
|
||||
if (lua_istable(ulua.L[i], 2)) {
|
||||
lua_pushstring(ulua.L[i], "run" );
|
||||
lua_gettable(ulua.L[i], 2);
|
||||
lua_replace(ulua.L[i], 2);
|
||||
}
|
||||
|
||||
if (! lua_isfunction(ulua.L[i], 2)) {
|
||||
uwsgi_log("Can't find WSAPI entry point (no function, nor a table with function'run').\n");
|
||||
exit(1);
|
||||
if (! lua_isfunction(ulua.L[i], 2)) {
|
||||
uwsgi_log("Can't find WSAPI entry point (no function, nor a table with function'run').\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -665,13 +679,92 @@ static uint16_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, uint16_t a
|
||||
#endif
|
||||
if (sl <= 0xffff) {
|
||||
memcpy(buffer, sv, sl);
|
||||
lua_pop(L, 1);
|
||||
return sl;
|
||||
}
|
||||
|
||||
lua_pop(L, 1);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static void uwsgi_lua_configurator_array(lua_State *L) {
|
||||
|
||||
int i;
|
||||
int n = luaL_getn(L, -3);
|
||||
|
||||
for(i=1;i<=n;i++) {
|
||||
lua_rawgeti(L, 1, i);
|
||||
if (lua_istable(L, -1)) {
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, -2) != 0) {
|
||||
char *key = uwsgi_str((char *)lua_tostring(L, -2));
|
||||
char *value = uwsgi_str((char *)lua_tostring(L, -1));
|
||||
add_exported_option(key, value, 0);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void uwsgi_lua_configurator(char *filename, char *magic_table[]) {
|
||||
size_t len = 0;
|
||||
uwsgi_log_initial("[uWSGI] getting Lua configuration from %s\n", filename);
|
||||
char *code = uwsgi_open_and_read(filename, &len, 1, magic_table);
|
||||
lua_State *L = luaL_newstate();
|
||||
if (!L) {
|
||||
uwsgi_log("unable to initialize Lua state for configuration\n");
|
||||
exit(1);
|
||||
}
|
||||
luaL_openlibs(L);
|
||||
if (luaL_dostring(L, code) != 0) {
|
||||
uwsgi_log("error running Lua configurator: %s\n", lua_tostring(L, -1));
|
||||
exit(1);
|
||||
}
|
||||
free(code);
|
||||
|
||||
if (!lua_istable(L, -1)) {
|
||||
uwsgi_log("Lua configurator has to return a table !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
lua_pushnil(L);
|
||||
// we always use uwsgi_str to avoid GC destroying our strings
|
||||
// and to be able to call lua_close at the end
|
||||
while (lua_next(L, -2) != 0) {
|
||||
// array ?
|
||||
if (lua_isnumber(L, -2)) {
|
||||
uwsgi_lua_configurator_array(L);
|
||||
break;
|
||||
}
|
||||
// dictionary
|
||||
else {
|
||||
char *key = uwsgi_str((char *)lua_tostring(L, -2));
|
||||
if (lua_istable(L, -1)) {
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, -2) != 0) {
|
||||
char *value = uwsgi_str((char *)lua_tostring(L, -1));
|
||||
add_exported_option(key, value, 0);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
char *value = uwsgi_str((char *)lua_tostring(L, -1));
|
||||
add_exported_option(key, value, 0);
|
||||
}
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
// this will destroy the whole Lua state
|
||||
lua_close(L);
|
||||
}
|
||||
|
||||
static void uwsgi_register_lua_features() {
|
||||
uwsgi_register_configurator(".lua", uwsgi_lua_configurator);
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_plugin lua_plugin = {
|
||||
|
||||
@@ -688,5 +781,6 @@ struct uwsgi_plugin lua_plugin = {
|
||||
.code_string = uwsgi_lua_code_string,
|
||||
.rpc = uwsgi_lua_rpc,
|
||||
|
||||
.on_load = uwsgi_register_lua_features,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
@@ -29,7 +29,7 @@ struct uwsgi_mongodb_state {
|
||||
struct iovec iovec[13];
|
||||
};
|
||||
|
||||
ssize_t uwsgi_mongodb_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
static ssize_t uwsgi_mongodb_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
|
||||
struct uwsgi_mongodb_state *ums = NULL;
|
||||
|
||||
@@ -151,7 +151,7 @@ done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void uwsgi_mongodblog_register() {
|
||||
static void uwsgi_mongodblog_register() {
|
||||
uwsgi_register_logger("mongodblog", uwsgi_mongodb_logger);
|
||||
}
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ static int sapi_uwsgi_send_headers(sapi_headers_struct *sapi_headers)
|
||||
}
|
||||
else {
|
||||
char *sl = SG(sapi_headers).http_status_line;
|
||||
uwsgi_response_prepare_headers(wsgi_req, sl, strlen(sl));
|
||||
uwsgi_response_prepare_headers(wsgi_req, sl + 8 , strlen(sl) - 8);
|
||||
}
|
||||
|
||||
h = zend_llist_get_first_ex(&sapi_headers->headers, &pos);
|
||||
|
||||
@@ -9,8 +9,11 @@ extern struct uwsgi_plugin psgi_plugin;
|
||||
XS(XS_input_seek) {
|
||||
|
||||
dXSARGS;
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
psgi_check_args(1);
|
||||
uwsgi_request_body_seek(wsgi_req, SvIV(ST(0)));
|
||||
|
||||
XSRETURN(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -513,6 +513,10 @@ void uwsgi_perl_after_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
log_request(wsgi_req);
|
||||
|
||||
// We may be called after an early exit in XS_coroae_accept_request,
|
||||
// before the environ is set up.
|
||||
if (!wsgi_req->async_environ) return;
|
||||
|
||||
// dereference %env
|
||||
SV *env = SvRV((SV *) wsgi_req->async_environ);
|
||||
|
||||
@@ -664,7 +668,7 @@ void uwsgi_perl_run_hook(SV *hook) {
|
||||
}
|
||||
|
||||
static void uwsgi_perl_atexit() {
|
||||
if (uwsgi.mywid == -1) goto realstuff;
|
||||
if (uwsgi.mywid == 0) goto realstuff;
|
||||
|
||||
// if hijacked do not run atexit hooks
|
||||
if (uwsgi.workers[uwsgi.mywid].hijacked)
|
||||
|
||||
@@ -196,8 +196,6 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
goto doh;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// the module contains multiple apps
|
||||
if (PyDict_Check((PyObject *)wi->callable)) {
|
||||
applications = wi->callable;
|
||||
|
||||
@@ -290,7 +290,7 @@ void uwsgi_python_reset_random_seed() {
|
||||
|
||||
void uwsgi_python_atexit() {
|
||||
|
||||
if (uwsgi.mywid == -1) goto realstuff;
|
||||
if (uwsgi.mywid == 0) goto realstuff;
|
||||
|
||||
// if hijacked do not run atexit hooks
|
||||
if (uwsgi.workers[uwsgi.mywid].hijacked)
|
||||
@@ -1063,9 +1063,7 @@ void uwsgi_python_init_apps() {
|
||||
#endif
|
||||
|
||||
// setup app loaders
|
||||
#ifdef UWSGI_MINTERPRETERS
|
||||
up.loaders[LOADER_DYN] = uwsgi_dyn_loader;
|
||||
#endif
|
||||
up.loaders[LOADER_UWSGI] = uwsgi_uwsgi_loader;
|
||||
up.loaders[LOADER_FILE] = uwsgi_file_loader;
|
||||
up.loaders[LOADER_PASTE] = uwsgi_paste_loader;
|
||||
|
||||
@@ -268,10 +268,6 @@ struct uwsgi_buffer *uwsgi_python_exception_repr(struct wsgi_request *);
|
||||
struct uwsgi_buffer *uwsgi_python_backtrace(struct wsgi_request *);
|
||||
void uwsgi_python_exception_log(struct wsgi_request *);
|
||||
|
||||
#ifdef UWSGI_PYPY
|
||||
#undef UWSGI_MINTERPRETERS
|
||||
#endif
|
||||
|
||||
#define py_current_wsgi_req() current_wsgi_req();\
|
||||
if (!wsgi_req) {\
|
||||
return PyErr_Format(PyExc_SystemError, "you can call uwsgi api function only from the main callable");\
|
||||
|
||||
@@ -134,6 +134,7 @@ error:
|
||||
if (urcc->key) free(urcc->key);
|
||||
if (urcc->name) free(urcc->name);
|
||||
if (urcc->expires_str) free(urcc->expires_str);
|
||||
free(urcc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
+171
-2
@@ -93,14 +93,164 @@ end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_routing_func_rpc_blob(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
int ret = -1;
|
||||
// this is the list of args
|
||||
char *argv[UMAX8];
|
||||
// this is the size of each argument
|
||||
uint16_t argvs[UMAX8];
|
||||
// this is a placeholder for tmp uwsgi_buffers
|
||||
struct uwsgi_buffer *ubs[UMAX8];
|
||||
|
||||
char **r_argv = (char **) ur->data2;
|
||||
uint16_t *r_argvs = (uint16_t *) ur->data3;
|
||||
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
uint64_t i;
|
||||
for(i=0;i<ur->custom;i++) {
|
||||
ubs[i] = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, r_argv[i], r_argvs[i]);
|
||||
if (!ubs[i]) goto end;
|
||||
argv[i] = ubs[i]->buf;
|
||||
argvs[i] = ubs[i]->pos;
|
||||
}
|
||||
|
||||
// ok we now need to check it it is a local call or a remote one
|
||||
char *func = uwsgi_str(ur->data);
|
||||
char *remote = NULL;
|
||||
char *at = strchr(func, '@');
|
||||
if (at) {
|
||||
*at = 0;
|
||||
remote = at+1;
|
||||
}
|
||||
uint16_t size;
|
||||
char *response = uwsgi_do_rpc(remote, func, ur->custom, argv, argvs, &size);
|
||||
free(func);
|
||||
if (!response) goto end;
|
||||
|
||||
ret = UWSGI_ROUTE_NEXT;
|
||||
|
||||
// optimization
|
||||
if (!wsgi_req->headers_sent) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) {free(response) ; goto end;}
|
||||
if (uwsgi_response_add_connection_close(wsgi_req)) {free(response) ; goto end;}
|
||||
}
|
||||
uwsgi_response_write_body_do(wsgi_req, response, size);
|
||||
free(response);
|
||||
|
||||
end:
|
||||
for(i=0;i<ur->custom;i++) {
|
||||
if (ubs[i] != NULL) {
|
||||
uwsgi_buffer_destroy(ubs[i]);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// "next" || "continue" || "break(.*)" || "goon" || "goto .+"
|
||||
static int uwsgi_routing_func_rpc_ret(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
int ret = -1;
|
||||
// this is the list of args
|
||||
char *argv[UMAX8];
|
||||
// this is the size of each argument
|
||||
uint16_t argvs[UMAX8];
|
||||
// this is a placeholder for tmp uwsgi_buffers
|
||||
struct uwsgi_buffer *ubs[UMAX8];
|
||||
|
||||
char **r_argv = (char **) ur->data2;
|
||||
uint16_t *r_argvs = (uint16_t *) ur->data3;
|
||||
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
uint64_t i;
|
||||
for(i=0;i<ur->custom;i++) {
|
||||
ubs[i] = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, r_argv[i], r_argvs[i]);
|
||||
if (!ubs[i]) goto end;
|
||||
argv[i] = ubs[i]->buf;
|
||||
argvs[i] = ubs[i]->pos;
|
||||
}
|
||||
|
||||
// ok we now need to check it it is a local call or a remote one
|
||||
char *func = uwsgi_str(ur->data);
|
||||
char *remote = NULL;
|
||||
char *at = strchr(func, '@');
|
||||
if (at) {
|
||||
*at = 0;
|
||||
remote = at+1;
|
||||
}
|
||||
uint16_t size;
|
||||
char *response = uwsgi_do_rpc(remote, func, ur->custom, argv, argvs, &size);
|
||||
free(func);
|
||||
if (!response) goto end;
|
||||
|
||||
ret = UWSGI_ROUTE_CONTINUE;
|
||||
if (!uwsgi_strncmp(response, size, "next", 4 )) {
|
||||
ret = UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
else if (!uwsgi_strncmp(response, size, "continue", 8 )) {
|
||||
ret = UWSGI_ROUTE_CONTINUE;
|
||||
}
|
||||
else if (!uwsgi_strncmp(response, size, "goon", 4 )) {
|
||||
ret = UWSGI_ROUTE_GOON;
|
||||
}
|
||||
else if (!uwsgi_starts_with(response, size, "break", 5 )) {
|
||||
ret = UWSGI_ROUTE_BREAK;
|
||||
if (size > 6) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, response+6, size-6)) goto end0;
|
||||
if (uwsgi_response_add_connection_close(wsgi_req)) goto end0;
|
||||
if (uwsgi_response_add_content_type(wsgi_req, "text/plain", 10)) goto end0;
|
||||
// no need to check for return value
|
||||
uwsgi_response_write_headers_do(wsgi_req);
|
||||
}
|
||||
}
|
||||
else if (!uwsgi_starts_with(response, size, "goto ", 5)) {
|
||||
ret = UWSGI_ROUTE_BREAK;
|
||||
if (size > 5) {
|
||||
// find the label
|
||||
struct uwsgi_route *routes = uwsgi.routes;
|
||||
while(routes) {
|
||||
if (!routes->label) goto next;
|
||||
if (!uwsgi_strncmp(routes->label, routes->label_len, response+5, size-5)) {
|
||||
ret = UWSGI_ROUTE_NEXT;
|
||||
wsgi_req->route_goto = routes->pos;
|
||||
goto found;
|
||||
}
|
||||
next:
|
||||
routes = routes->next;
|
||||
}
|
||||
goto end0;
|
||||
found:
|
||||
if (wsgi_req->route_goto <= wsgi_req->route_pc) {
|
||||
wsgi_req->route_goto = 0;
|
||||
uwsgi_log("[uwsgi-route] ERROR \"goto\" instruction can only jump forward (check your label !!!)\n");
|
||||
ret = UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end0:
|
||||
free(response);
|
||||
|
||||
end:
|
||||
for(i=0;i<ur->custom;i++) {
|
||||
if (ubs[i] != NULL) {
|
||||
uwsgi_buffer_destroy(ubs[i]);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
ur->data = the func name
|
||||
ur->custom = the number of arguments
|
||||
ur->data2 = the pointer to the args
|
||||
ur->data3 = the pointer to the args sizes
|
||||
*/
|
||||
static int uwsgi_router_rpc(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_rpc;
|
||||
static int uwsgi_router_rpc_base(struct uwsgi_route *ur, char *args) {
|
||||
ur->custom = 0;
|
||||
ur->data2 = uwsgi_calloc(sizeof(char *) * UMAX8);
|
||||
ur->data3 = uwsgi_calloc(sizeof(uint16_t) * UMAX8);
|
||||
@@ -134,9 +284,28 @@ static int uwsgi_router_rpc(struct uwsgi_route *ur, char *args) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_router_rpc(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_rpc;
|
||||
return uwsgi_router_rpc_base(ur, args);
|
||||
}
|
||||
|
||||
static int uwsgi_router_rpc_ret(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_rpc_ret;
|
||||
return uwsgi_router_rpc_base(ur, args);
|
||||
}
|
||||
|
||||
static int uwsgi_router_rpc_blob(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_rpc_blob;
|
||||
return uwsgi_router_rpc_base(ur, args);
|
||||
}
|
||||
|
||||
|
||||
static void router_rpc_register() {
|
||||
uwsgi_register_router("call", uwsgi_router_rpc);
|
||||
uwsgi_register_router("rpc", uwsgi_router_rpc);
|
||||
uwsgi_register_router("rpcret", uwsgi_router_rpc_ret);
|
||||
uwsgi_register_router("rpcblob", uwsgi_router_rpc_blob);
|
||||
uwsgi_register_router("rpcnext", uwsgi_router_rpc_blob);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
int uwsgi_v8_init(void);
|
||||
void uwsgi_v8_apps(void);
|
||||
void uwsgi_v8_configurator(char *, char **);
|
||||
uint16_t uwsgi_v8_rpc(void *, uint8_t, char **, uint16_t *, char *);
|
||||
int uwsgi_v8_signal_handler(uint8_t, void *);
|
||||
void uwsgi_v8_init_thread(int);
|
||||
void uwsgi_v8_enable_threads();
|
||||
int uwsgi_v8_mule(char *);
|
||||
|
||||
static void uwsgi_v8_register(void) {
|
||||
uwsgi_register_configurator(".js", uwsgi_v8_configurator);
|
||||
}
|
||||
|
||||
extern struct uwsgi_option uwsgi_v8_options[];
|
||||
|
||||
int uwsgi_v8_request(struct wsgi_request *);
|
||||
|
||||
static void uwsgi_v8_after_request(struct wsgi_request *wsgi_req) {
|
||||
log_request(wsgi_req);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin v8_plugin = {
|
||||
.name = "v8",
|
||||
.modifier1 = 24,
|
||||
.init = uwsgi_v8_init,
|
||||
.init_apps = uwsgi_v8_apps,
|
||||
.options = uwsgi_v8_options,
|
||||
.on_load = uwsgi_v8_register,
|
||||
.rpc = uwsgi_v8_rpc,
|
||||
.request = uwsgi_v8_request,
|
||||
.after_request = uwsgi_v8_after_request,
|
||||
.signal_handler = uwsgi_v8_signal_handler,
|
||||
.enable_threads = uwsgi_v8_enable_threads,
|
||||
.init_thread = uwsgi_v8_init_thread,
|
||||
.mule = uwsgi_v8_mule,
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='v8'
|
||||
|
||||
CFLAGS = ['-Wno-deprecated-declarations']
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lv8']
|
||||
GCC_LIST = ['plugin', 'v8_uwsgi.cc', 'v8_commonjs.cc', 'v8_jsgi.cc']
|
||||
@@ -0,0 +1,75 @@
|
||||
#include "v8_uwsgi.h"
|
||||
|
||||
extern struct uwsgi_v8 uv8;
|
||||
|
||||
static v8::Handle<v8::Value> uwsgi_v8_commonjs_require_do(char *filename) {
|
||||
|
||||
size_t len = 0;
|
||||
char *code = uwsgi_open_and_read(filename, &len, 1, NULL);
|
||||
|
||||
// we re-create every time an "exports" object to emulate a local object
|
||||
v8::Local<v8::Object> exports = v8::Object::New();
|
||||
v8::Context::GetCurrent()->Global()->Set(v8::String::New("exports"), exports);
|
||||
|
||||
// we do not use TryCatch as we directly use stderr and simply exit with error code 1
|
||||
v8::Handle<v8::Script> script = v8::Script::Compile( v8::String::New(code), v8::String::New(filename) );
|
||||
free(code);
|
||||
if (script.IsEmpty()) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
v8::Handle<v8::Value> result = script->Run();
|
||||
if (result.IsEmpty()) {
|
||||
return v8::Undefined();
|
||||
}
|
||||
|
||||
return exports;
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> uwsgi_v8_commonjs_require(const v8::Arguments& args) {
|
||||
if (args.Length() > 0) {
|
||||
v8::String::Utf8Value module_name(args[0]->ToString());
|
||||
// ok lets start searching the module
|
||||
if (uwsgi_is_file(*module_name)) {
|
||||
return uwsgi_v8_commonjs_require_do(*module_name);
|
||||
}
|
||||
|
||||
// try appending .js extension
|
||||
if (!uwsgi_endswith(*module_name, (char *)".js")) {
|
||||
char *tmp_filename = uwsgi_concat2(*module_name, (char *)".js");
|
||||
if (uwsgi_is_file(tmp_filename)) {
|
||||
v8::Handle<v8::Value> ret = uwsgi_v8_commonjs_require_do(tmp_filename);
|
||||
free(tmp_filename);
|
||||
return ret;
|
||||
}
|
||||
free(tmp_filename);
|
||||
}
|
||||
|
||||
// let's start searching in the modules search path
|
||||
struct uwsgi_string_list *usl = uv8.module_paths;
|
||||
while(usl) {
|
||||
char *tmp_filename = uwsgi_concat3(usl->value, (char *)"/", *module_name);
|
||||
if (uwsgi_is_file(tmp_filename)) {
|
||||
v8::Handle<v8::Value> ret = uwsgi_v8_commonjs_require_do(tmp_filename);
|
||||
free(tmp_filename);
|
||||
return ret;
|
||||
}
|
||||
free(tmp_filename);
|
||||
if (!uwsgi_endswith(*module_name, (char *)".js")) {
|
||||
tmp_filename = uwsgi_concat4(usl->value, (char *)"/", *module_name, (char *)".js");
|
||||
if (uwsgi_is_file(tmp_filename)) {
|
||||
v8::Handle<v8::Value> ret = uwsgi_v8_commonjs_require_do(tmp_filename);
|
||||
free(tmp_filename);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
free(tmp_filename);
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
return v8::Undefined();
|
||||
}
|
||||
|
||||
void uwsgi_v8_add_commonjs(v8::Handle<v8::ObjectTemplate> global) {
|
||||
global->Set(v8::String::New("require"), v8::FunctionTemplate::New(uwsgi_v8_commonjs_require));
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
#include "v8_uwsgi.h"
|
||||
|
||||
extern struct uwsgi_v8 uv8;
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
static v8::Handle<v8::Value> uwsgi_v8_jsgi_body_chunk(const v8::Arguments& args) {
|
||||
|
||||
if (args.Length() > 1) {
|
||||
v8::String::Utf8Value chunk(args[0]->ToString());
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
if (uwsgi_response_write_body_do(wsgi_req, *chunk, args[0]->ToString()->Length())) {
|
||||
return v8::ThrowException(v8::Exception::Error(v8::String::New("unable to send JSGI body")));
|
||||
}
|
||||
}
|
||||
|
||||
return v8::Undefined();
|
||||
}
|
||||
|
||||
static void uwsgi_v8_jsgi_fill_request(struct wsgi_request *wsgi_req, v8::Handle<v8::Object> o) {
|
||||
o->Set(v8::String::New("method"), v8::String::New(wsgi_req->method, wsgi_req->method_len));
|
||||
o->Set(v8::String::New("scriptName"), v8::String::New(wsgi_req->script_name, wsgi_req->script_name_len));
|
||||
o->Set(v8::String::New("pathInfo"), v8::String::New(wsgi_req->path_info, wsgi_req->path_info_len));
|
||||
o->Set(v8::String::New("queryString"), v8::String::New(wsgi_req->query_string, wsgi_req->query_string_len));
|
||||
o->Set(v8::String::New("host"), v8::String::New(wsgi_req->host, wsgi_req->host_len));
|
||||
if (wsgi_req->scheme_len) {
|
||||
o->Set(v8::String::New("scheme"), v8::String::New(wsgi_req->scheme, wsgi_req->scheme_len));
|
||||
}
|
||||
else {
|
||||
o->Set(v8::String::New("scheme"), v8::String::New("http"));
|
||||
}
|
||||
o->Set(v8::String::New("remoteAddr"), v8::String::New(wsgi_req->remote_addr, wsgi_req->remote_addr_len));
|
||||
if (wsgi_req->remote_user_len) {
|
||||
o->Set(v8::String::New("remoteUser"), v8::String::New(wsgi_req->remote_user, wsgi_req->remote_user_len));
|
||||
}
|
||||
o->Set(v8::String::New("serverSoftware"), v8::String::New("uWSGI " UWSGI_VERSION));
|
||||
|
||||
v8::Handle<v8::Value> jsgi = v8::Object::New();
|
||||
if (uwsgi.threads > 1) {
|
||||
jsgi->ToObject()->Set(v8::String::New("multithread"), v8::True());
|
||||
}
|
||||
else {
|
||||
jsgi->ToObject()->Set(v8::String::New("multithread"), v8::False());
|
||||
}
|
||||
|
||||
if (uwsgi.numproc > 1) {
|
||||
jsgi->ToObject()->Set(v8::String::New("multiprocess"), v8::True());
|
||||
}
|
||||
else {
|
||||
jsgi->ToObject()->Set(v8::String::New("multiprocess"), v8::False());
|
||||
}
|
||||
o->Set(v8::String::New("jsgi"), jsgi);
|
||||
}
|
||||
|
||||
extern "C" int uwsgi_v8_request(struct wsgi_request *wsgi_req) {
|
||||
char status_str[11];
|
||||
uint32_t i,l;
|
||||
v8::Handle<v8::Value> status, headers, body;
|
||||
v8::Local<v8::Array> props;
|
||||
v8::Local<v8::Value> key, value;
|
||||
v8::Handle<v8::Function> forEach;
|
||||
|
||||
/* Standard JSGI 3.0 request */
|
||||
if (!wsgi_req->uh->pktsize) {
|
||||
uwsgi_log( "Empty JSGI request. skip.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uwsgi_parse_vars(wsgi_req)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int core_id = wsgi_req->async_id;
|
||||
|
||||
uv8.isolates[core_id]->Enter();
|
||||
uv8.contexts[core_id]->Enter();
|
||||
v8::HandleScope handle_scope;
|
||||
v8::Handle<v8::Value> argj[1];
|
||||
argj[0] = v8::Object::New();
|
||||
uwsgi_v8_jsgi_fill_request(wsgi_req, argj[0]->ToObject());
|
||||
v8::Handle<v8::Value> result = uv8.jsgi_func[core_id]->Call(uv8.contexts[core_id]->Global(), 1, argj);
|
||||
if (result.IsEmpty()) goto end;
|
||||
if (!result->IsObject()) goto end;
|
||||
|
||||
status = result->ToObject()->Get(v8::String::New("status"));
|
||||
if (status.IsEmpty() || !status->IsNumber()) {
|
||||
uwsgi_log("invalid JSGI response status\n");
|
||||
exit(1);
|
||||
}
|
||||
headers = result->ToObject()->Get(v8::String::New("headers"));
|
||||
if (headers.IsEmpty() || !headers->IsObject()) {
|
||||
uwsgi_log("invalid JSGI response headers\n");
|
||||
exit(1);
|
||||
}
|
||||
body = result->ToObject()->Get(v8::String::New("body"));
|
||||
if (body.IsEmpty() || !body->IsObject()) {
|
||||
uwsgi_log("invalid JSGI response body\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (uwsgi_num2str2(status->Uint32Value(), status_str) != 3) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, status_str, 3)) goto end;
|
||||
|
||||
props = headers->ToObject()->GetPropertyNames();
|
||||
l = props->Length();
|
||||
|
||||
for(i=0;i<l;i++) {
|
||||
key = props->Get(i);
|
||||
value = headers->ToObject()->Get(key);
|
||||
v8::String::Utf8Value c_key(key->ToString());
|
||||
if (value->IsArray()) {
|
||||
uint32_t opt_l = value->ToObject()->Get(v8::String::New("length"))->ToObject()->Uint32Value();
|
||||
uint32_t j;
|
||||
for(j=0;j<opt_l;j++) {
|
||||
v8::String::Utf8Value c_value(value->ToObject()->Get(j)->ToString());
|
||||
if (uwsgi_response_add_header(wsgi_req, *c_key, strlen(*c_key), *c_value, strlen(*c_value))) goto end;
|
||||
}
|
||||
}
|
||||
else {
|
||||
v8::String::Utf8Value c_value(value->ToString());
|
||||
if (uwsgi_response_add_header(wsgi_req, *c_key, strlen(*c_key), *c_value, strlen(*c_value))) goto end;
|
||||
}
|
||||
}
|
||||
|
||||
// call forEach
|
||||
forEach = v8::Handle<v8::Function>::Cast(body->ToObject()->Get(v8::String::New("forEach")));
|
||||
argj[0] = uv8.jsgi_writer_func[core_id];
|
||||
forEach->Call(body->ToObject(), 1, argj);
|
||||
|
||||
end:
|
||||
while(!v8::V8::IdleNotification()) {};
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
v8::Persistent<v8::Function> uwsgi_v8_load_jsgi(int core_id, char *filename) {
|
||||
|
||||
uv8.isolates[core_id]->Enter();
|
||||
uv8.contexts[core_id]->Enter();
|
||||
v8::HandleScope handle_scope;
|
||||
|
||||
size_t len = 0;
|
||||
char *code = uwsgi_open_and_read(filename, &len, 1, NULL);
|
||||
// we re-create every time an "exports" object to emulate a local object
|
||||
v8::Local<v8::Object> exports = v8::Object::New();
|
||||
v8::Context::GetCurrent()->Global()->Set(v8::String::New("exports"), exports);
|
||||
|
||||
// we do not use TryCatch as we directly use stderr and simply exit with error code 1
|
||||
v8::Handle<v8::Script> script = v8::Script::Compile( v8::String::New(code), v8::String::New(filename) );
|
||||
free(code);
|
||||
if (script.IsEmpty()) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
v8::Handle<v8::Value> result = script->Run();
|
||||
if (result.IsEmpty()) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uv8.jsgi_writer_func[core_id] = v8::Persistent<v8::Function>::New(v8::FunctionTemplate::New(uwsgi_v8_jsgi_body_chunk)->GetFunction());
|
||||
|
||||
v8::Handle<v8::Value> app = exports->Get(v8::String::New("app"));
|
||||
if (!app.IsEmpty() && !app->IsNull() && !app->IsUndefined()) {
|
||||
if (app->ToObject()->IsFunction()) {
|
||||
if (!uv8.jsgi_announced) {
|
||||
uwsgi_log("JSGI 3.0 application loaded from \"exports.app\" in %s\n", filename);
|
||||
uv8.jsgi_announced = -1;
|
||||
}
|
||||
return v8::Persistent<v8::Function>::New(v8::Handle<v8::Function>::Cast(app));
|
||||
}
|
||||
}
|
||||
|
||||
if (!result->IsNull() && !result->IsUndefined() && result->ToObject()->IsFunction()) {
|
||||
if (!uv8.jsgi_announced) {
|
||||
uwsgi_log("JSGI 3.0 application loaded from return value of %s\n", filename);
|
||||
uv8.jsgi_announced = -1;
|
||||
}
|
||||
return v8::Persistent<v8::Function>::New(v8::Handle<v8::Function>::Cast(result));
|
||||
}
|
||||
|
||||
uwsgi_log("unable to find JSGI 3.0 entry point function\n");
|
||||
exit(1);
|
||||
}
|
||||
@@ -0,0 +1,332 @@
|
||||
#include "v8_uwsgi.h"
|
||||
|
||||
struct uwsgi_v8 uv8;
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_plugin v8_plugin;
|
||||
|
||||
struct uwsgi_option uwsgi_v8_options[] = {
|
||||
{(char *)"v8-load", required_argument, 0, (char *)"load a javascript file", uwsgi_opt_add_string_list, &uv8.load, 0},
|
||||
{(char *)"v8-preemptive", required_argument, 0, (char *)"put v8 in preemptive move (single isolate) with the specified frequency", uwsgi_opt_set_int, &uv8.preemptive, 0},
|
||||
{(char *)"v8-gc-freq", required_argument, 0, (char *)"set the v8 garbage collection frequency", uwsgi_opt_set_64bit, &uv8.gc_freq, 0},
|
||||
{(char *)"v8-module-path", required_argument, 0, (char *)"set the v8 modules search path", uwsgi_opt_add_string_list, &uv8.module_paths, 0},
|
||||
{(char *)"v8-jsgi", required_argument, 0, (char *)"load the specified JSGI 3.0 application", uwsgi_opt_set_str, &uv8.jsgi, 0},
|
||||
{0, 0, 0, 0},
|
||||
};
|
||||
|
||||
static v8::Handle<v8::Value> uwsgi_v8_api_register_signal(const v8::Arguments& args) {
|
||||
|
||||
if (args.Length() > 2) {
|
||||
uint8_t uwsgi_signal = args[0]->Uint32Value();
|
||||
v8::String::Utf8Value signal_kind(args[1]->ToString());
|
||||
|
||||
v8::Persistent<v8::Function> func = v8::Persistent<v8::Function>::New(v8::Handle<v8::Function>::Cast(args[2]));
|
||||
|
||||
int core_id = (long) pthread_getspecific(uv8.current_core);
|
||||
struct uwsgi_v8_signal_table *uvst = &uv8.sigtable[uwsgi_signal];
|
||||
|
||||
int need_register = 1;
|
||||
if (uvst->registered == 1) {
|
||||
need_register = 0;
|
||||
}
|
||||
|
||||
uvst->func[core_id] = func;
|
||||
|
||||
if (!need_register) {
|
||||
return v8::True();
|
||||
}
|
||||
|
||||
if (uwsgi_register_signal(uwsgi_signal, *signal_kind, uvst, v8_plugin.modifier1)) {
|
||||
uwsgi_log("[uwsgi-v8] unable to register signal %d\n", uwsgi_signal);
|
||||
return v8::Undefined();
|
||||
}
|
||||
uvst->registered = 1 ;
|
||||
|
||||
return v8::True();
|
||||
}
|
||||
|
||||
return v8::Undefined();
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> uwsgi_v8_api_register_rpc(const v8::Arguments& args) {
|
||||
|
||||
if (args.Length() > 1) {
|
||||
v8::String::Utf8Value name(args[0]->ToString());
|
||||
uint8_t j_argc = 0;
|
||||
if (args.Length() > 2) {
|
||||
j_argc = args[2]->Uint32Value();
|
||||
}
|
||||
|
||||
v8::Persistent<v8::Function> func = v8::Persistent<v8::Function>::New(v8::Handle<v8::Function>::Cast(args[1]));
|
||||
|
||||
int core_id = (long) pthread_getspecific(uv8.current_core);
|
||||
|
||||
// get the rpc slot
|
||||
int i;
|
||||
int found = 0;
|
||||
struct uwsgi_v8_rpc_table *uvrt = NULL;
|
||||
for(i=0;i<(int)uwsgi.rpc_max;i++) {
|
||||
uvrt = &uv8.rpctable[i];
|
||||
if (uvrt->name == NULL) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
// skip already registered funcs
|
||||
else if (!strcmp(uvrt->name, *name)) {
|
||||
uvrt->func[core_id] = func;
|
||||
return v8::True();
|
||||
}
|
||||
}
|
||||
if (!found || !uvrt) {
|
||||
uwsgi_log("[uwsgi-v8] unable to register RPC function \"%s\"\n", *name);
|
||||
return v8::Undefined();
|
||||
}
|
||||
uvrt->name = uwsgi_str(*name);
|
||||
uvrt->func[core_id] = func;
|
||||
|
||||
// we can safely call register_rpc here as it will check for already registered funcs
|
||||
if (uwsgi_register_rpc(*name, v8_plugin.modifier1, j_argc, uvrt)) {
|
||||
uwsgi_log("[uwsgi-v8] unable to register RPC function \"%s\"\n", *name);
|
||||
return v8::Undefined();
|
||||
}
|
||||
|
||||
return v8::True();
|
||||
}
|
||||
|
||||
return v8::Undefined();
|
||||
}
|
||||
|
||||
static void uwsgi_v8_load_file(int core_id, char *filename) {
|
||||
|
||||
uv8.isolates[core_id]->Enter();
|
||||
uv8.contexts[core_id]->Enter();
|
||||
v8::HandleScope handle_scope;
|
||||
|
||||
size_t len = 0;
|
||||
char *code = uwsgi_open_and_read(filename, &len, 1, NULL);
|
||||
|
||||
// we do not use TryCatch as we directly use stderr and simply exit with error code 1
|
||||
v8::Handle<v8::Script> script = v8::Script::Compile( v8::String::New(code), v8::String::New(filename) );
|
||||
free(code);
|
||||
if (script.IsEmpty()) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
v8::Handle<v8::Value> result = script->Run();
|
||||
if (result.IsEmpty()) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> uwsgi_v8_api_log(const v8::Arguments& args) {
|
||||
|
||||
if (args.Length() > 0) {
|
||||
v8::String::Utf8Value str(args[0]->ToString());
|
||||
size_t slen = strlen(*str);
|
||||
if ((*str)[slen-1] == '\n') {
|
||||
uwsgi_log("%s", *str);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("%s\n", *str);
|
||||
}
|
||||
}
|
||||
return v8::Undefined();
|
||||
}
|
||||
|
||||
void uwsgi_v8_add_commonjs(v8::Handle<v8::ObjectTemplate>);
|
||||
|
||||
static v8::Persistent<v8::Context> uwsgi_v8_new_isolate(int core_id) {
|
||||
// create a new isolate
|
||||
v8::Isolate *isolate = v8::Isolate::New();
|
||||
// set as the current isolate
|
||||
isolate->Enter();
|
||||
|
||||
uv8.isolates[core_id] = v8::Isolate::GetCurrent();
|
||||
|
||||
v8::HandleScope handle_scope;
|
||||
|
||||
// uWSGI api
|
||||
v8::Handle<v8::ObjectTemplate> uwsgi_api = v8::ObjectTemplate::New();
|
||||
uwsgi_api->Set(v8::String::New("log"), v8::FunctionTemplate::New(uwsgi_v8_api_log));
|
||||
uwsgi_api->Set(v8::String::New("register_rpc"), v8::FunctionTemplate::New(uwsgi_v8_api_register_rpc));
|
||||
uwsgi_api->Set(v8::String::New("register_signal"), v8::FunctionTemplate::New(uwsgi_v8_api_register_signal));
|
||||
|
||||
v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
|
||||
global->Set(v8::String::New("uwsgi"), uwsgi_api);
|
||||
|
||||
uwsgi_v8_add_commonjs(global);
|
||||
|
||||
// create a new context
|
||||
v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);
|
||||
return context;
|
||||
}
|
||||
|
||||
extern "C" int uwsgi_v8_init(){
|
||||
int i;
|
||||
uwsgi_log("Initializing V8 %s environment... (%d Isolates)\n", v8::V8::GetVersion(), uwsgi.cores);
|
||||
uv8.isolates = (v8::Isolate **) uwsgi_malloc( sizeof(v8::Isolate *) * uwsgi.cores );
|
||||
uv8.contexts = (v8::Persistent<v8::Context> *) uwsgi_malloc( sizeof(v8::Persistent<v8::Context>) * uwsgi.cores );
|
||||
// allocates rpc and signal tables
|
||||
uv8.rpctable = (struct uwsgi_v8_rpc_table *) uwsgi_calloc(sizeof(struct uwsgi_v8_rpc_table) * uwsgi.rpc_max);
|
||||
for(i=0;i<(int)uwsgi.rpc_max;i++) {
|
||||
uv8.rpctable[i].func = (v8::Persistent<v8::Function>*) uwsgi_calloc(sizeof(v8::Persistent<v8::Function>) * uwsgi.cores);
|
||||
}
|
||||
uv8.sigtable = (struct uwsgi_v8_signal_table *) uwsgi_calloc(sizeof(struct uwsgi_v8_signal_table) * 256);
|
||||
for(i=0;i<256;i++) {
|
||||
uv8.sigtable[i].func = (v8::Persistent<v8::Function>*) uwsgi_calloc(sizeof(v8::Persistent<v8::Function>) * uwsgi.cores);
|
||||
}
|
||||
uv8.jsgi_func = (v8::Persistent<v8::Function> *) uwsgi_calloc( sizeof(v8::Persistent<v8::Function>) * uwsgi.cores );
|
||||
uv8.jsgi_writer_func = (v8::Persistent<v8::Function> *) uwsgi_calloc( sizeof(v8::Persistent<v8::Function>) * uwsgi.cores );
|
||||
|
||||
pthread_key_create(&uv8.current_core, NULL);
|
||||
pthread_setspecific(uv8.current_core, (void *) 0);
|
||||
uv8.contexts[0] = uwsgi_v8_new_isolate(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uwsgi_v8_apps_do(int core_id) {
|
||||
struct uwsgi_string_list *usl = uv8.load;
|
||||
while(usl) {
|
||||
uwsgi_v8_load_file(core_id, usl->value);
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
if (uv8.jsgi) {
|
||||
uv8.jsgi_func[core_id] = uwsgi_v8_load_jsgi(core_id, uv8.jsgi);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void uwsgi_v8_apps() {
|
||||
uwsgi_v8_apps_do(0);
|
||||
}
|
||||
|
||||
extern "C" void uwsgi_v8_configurator(char *filename, char *magic_table[]) {
|
||||
|
||||
v8::HandleScope handle_scope;
|
||||
|
||||
uwsgi_log_initial("[uWSGI] getting javascript (V8) configuration from %s\n", filename);
|
||||
|
||||
size_t len = 0;
|
||||
char *code = uwsgi_open_and_read(filename, &len, 1, NULL);
|
||||
|
||||
v8::Handle<v8::Context> context = v8::Context::New();
|
||||
|
||||
v8::Context::Scope context_scope(context);
|
||||
|
||||
// we do not use TryCatch as we directly use stderr and simply exit with error code 1
|
||||
|
||||
v8::Handle<v8::Script> script = v8::Script::Compile( v8::String::New(code), v8::String::New(filename) );
|
||||
if (script.IsEmpty()) {
|
||||
exit(1);
|
||||
}
|
||||
free(code);
|
||||
|
||||
v8::Handle<v8::Value> result = script->Run();
|
||||
if (result.IsEmpty()) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!result->IsArray() && !result->IsObject()) {
|
||||
uwsgi_log("javascript return value must be an object or an array !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uint32_t i;
|
||||
const v8::Local<v8::Array> props = result->ToObject()->GetPropertyNames();
|
||||
const uint32_t l = props->Length();
|
||||
|
||||
for(i=0;i<l;i++) {
|
||||
const v8::Local<v8::Value> key = props->Get(i);
|
||||
const v8::Local<v8::Value> value = result->ToObject()->Get(key);
|
||||
v8::String::Utf8Value c_key(key->ToString());
|
||||
if (value->IsArray()) {
|
||||
uint32_t opt_l = value->ToObject()->Get(v8::String::New("length"))->ToObject()->Uint32Value();
|
||||
uint32_t j;
|
||||
for(j=0;j<opt_l;j++) {
|
||||
v8::String::Utf8Value c_value(value->ToObject()->Get(j)->ToString());
|
||||
add_exported_option(uwsgi_str(*c_key), uwsgi_str(*c_value), 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
v8::String::Utf8Value c_value(value->ToString());
|
||||
add_exported_option(uwsgi_str(*c_key), uwsgi_str(*c_value), 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern "C" uint16_t uwsgi_v8_rpc(void * func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
|
||||
|
||||
int core_id = (long) pthread_getspecific(uv8.current_core);
|
||||
|
||||
uv8.isolates[core_id]->Enter();
|
||||
uv8.contexts[core_id]->Enter();
|
||||
v8::HandleScope handle_scope;
|
||||
v8::Handle<v8::Value> argj[256];
|
||||
|
||||
struct uwsgi_v8_rpc_table *uvrt = (struct uwsgi_v8_rpc_table *) func;
|
||||
|
||||
uint8_t i;
|
||||
for(i=0;i<argc;i++) {
|
||||
argj[i] = v8::String::New(argv[i], argvs[i]);
|
||||
}
|
||||
|
||||
v8::Persistent<v8::Function> l_func = uvrt->func[core_id];
|
||||
|
||||
v8::Handle<v8::Value> result = l_func->Call(uv8.contexts[core_id]->Global(), argc, argj);
|
||||
if (result.IsEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
v8::Handle<v8::String> robj = result->ToString();
|
||||
|
||||
v8::String::Utf8Value r_value(robj);
|
||||
if (!*robj) {
|
||||
return 0;
|
||||
}
|
||||
uint16_t rlen = robj->Length();
|
||||
memcpy(buffer, *r_value, rlen);
|
||||
// call GC every time, could be overkill, we should allow to tune that choice
|
||||
while(!v8::V8::IdleNotification()) {};
|
||||
return rlen;
|
||||
|
||||
}
|
||||
|
||||
extern "C" void uwsgi_v8_init_thread(int core_id) {
|
||||
pthread_setspecific(uv8.current_core, (void *) ((long)core_id));
|
||||
uv8.contexts[core_id] = uwsgi_v8_new_isolate(core_id);
|
||||
uwsgi_v8_apps_do(core_id);
|
||||
}
|
||||
|
||||
extern "C" void uwsgi_v8_enable_threads() {
|
||||
}
|
||||
|
||||
extern "C" int uwsgi_v8_signal_handler(uint8_t sig, void *handler) {
|
||||
int ret = 0;
|
||||
int core_id = (long) pthread_getspecific(uv8.current_core);
|
||||
|
||||
uv8.isolates[core_id]->Enter();
|
||||
uv8.contexts[core_id]->Enter();
|
||||
v8::HandleScope handle_scope;
|
||||
v8::Handle<v8::Value> argj[1];
|
||||
argj[0] = v8::Number::New(sig);
|
||||
struct uwsgi_v8_signal_table *uvst = (struct uwsgi_v8_signal_table *) handler;
|
||||
v8::Persistent<v8::Function> l_func = uvst->func[core_id];
|
||||
v8::Handle<v8::Value> result = l_func->Call(uv8.contexts[core_id]->Global(), 1, argj);
|
||||
if (result.IsEmpty()) ret = -1;
|
||||
while(!v8::V8::IdleNotification()) {};
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern "C" int uwsgi_v8_mule(char *opt) {
|
||||
|
||||
if (uwsgi_endswith(opt, (char *)".js")) {
|
||||
uwsgi_v8_load_file(0, opt);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#include <uwsgi.h>
|
||||
#include <v8.h>
|
||||
|
||||
// as we have isolates in multithread modes, we need to maintain
|
||||
// special tables for the handlers (mules and spooler just run on the core 0)
|
||||
struct uwsgi_v8_signal_table {
|
||||
v8::Persistent<v8::Function> *func;
|
||||
uint8_t registered;
|
||||
};
|
||||
|
||||
struct uwsgi_v8_rpc_table {
|
||||
char *name;
|
||||
v8::Persistent<v8::Function> *func;
|
||||
};
|
||||
|
||||
struct uwsgi_v8 {
|
||||
v8::Persistent<v8::Context> *contexts;
|
||||
v8::Isolate **isolates;
|
||||
char *jsgi;
|
||||
v8::Persistent<v8::Function> *jsgi_func;
|
||||
v8::Persistent<v8::Function> *jsgi_writer_func;
|
||||
int jsgi_announced;
|
||||
struct uwsgi_string_list *load;
|
||||
struct uwsgi_v8_signal_table *sigtable;
|
||||
struct uwsgi_v8_rpc_table *rpctable;
|
||||
pthread_key_t current_core;
|
||||
int preemptive;
|
||||
uint64_t gc_freq;
|
||||
struct uwsgi_string_list *module_paths;
|
||||
};
|
||||
|
||||
v8::Persistent<v8::Function> uwsgi_v8_load_jsgi(int, char *);
|
||||
+1
-1
@@ -2,7 +2,7 @@ Gem::Specification.new do |s|
|
||||
s.name = 'uwsgi'
|
||||
s.license = 'GPL-2'
|
||||
s.version = `python -c "import uwsgiconfig as uc; print uc.uwsgi_version"`.sub(/-dev-.*/,'')
|
||||
s.date = '2013-03-26'
|
||||
s.date = '2013-04-04'
|
||||
s.summary = "uWSGI"
|
||||
s.description = "The uWSGI server for Ruby/Rack"
|
||||
s.authors = ["Unbit"]
|
||||
|
||||
@@ -597,6 +597,9 @@ struct uwsgi_legion_node {
|
||||
int quorum;
|
||||
int changed;
|
||||
|
||||
// set to 1 first time when quorum is reached
|
||||
int joined;
|
||||
|
||||
uint64_t checksum;
|
||||
|
||||
char *scroll;
|
||||
@@ -634,6 +637,7 @@ struct uwsgi_legion_node {
|
||||
struct uwsgi_string_list *unlord_hooks;
|
||||
struct uwsgi_string_list *setup_hooks;
|
||||
struct uwsgi_string_list *death_hooks;
|
||||
struct uwsgi_string_list *join_hooks;
|
||||
struct uwsgi_legion *next;
|
||||
};
|
||||
|
||||
@@ -832,9 +836,9 @@ struct uwsgi_cache {
|
||||
struct uwsgi_loop *next;
|
||||
};
|
||||
|
||||
struct wsgi_request;
|
||||
struct wsgi_request;
|
||||
|
||||
struct uwsgi_socket {
|
||||
struct uwsgi_socket {
|
||||
int fd;
|
||||
char *name;
|
||||
int name_len;
|
||||
@@ -904,11 +908,11 @@ struct uwsgi_cache {
|
||||
int lazy;
|
||||
int shared;
|
||||
int from_shared;
|
||||
};
|
||||
};
|
||||
|
||||
struct uwsgi_server;
|
||||
struct uwsgi_server;
|
||||
|
||||
struct uwsgi_plugin {
|
||||
struct uwsgi_plugin {
|
||||
|
||||
const char *name;
|
||||
const char *alias;
|
||||
@@ -949,7 +953,7 @@ struct uwsgi_cache {
|
||||
|
||||
int (*spooler) (char *, char *, uint16_t, char *, size_t);
|
||||
|
||||
uint16_t(*rpc) (void *, uint8_t, char **, uint16_t *, char *);
|
||||
uint16_t(*rpc) (void *, uint8_t, char **, uint16_t *, char *);
|
||||
|
||||
void (*jail) (int (*)(void *), char **);
|
||||
void (*before_privileges_drop) (void);
|
||||
@@ -959,13 +963,12 @@ struct uwsgi_cache {
|
||||
|
||||
void (*master_cleanup) (void);
|
||||
|
||||
|
||||
struct uwsgi_buffer* (*backtrace)(struct wsgi_request *);
|
||||
struct uwsgi_buffer* (*exception_class)(struct wsgi_request *);
|
||||
struct uwsgi_buffer* (*exception_msg)(struct wsgi_request *);
|
||||
struct uwsgi_buffer* (*exception_repr)(struct wsgi_request *);
|
||||
void (*exception_log)(struct wsgi_request *);
|
||||
};
|
||||
struct uwsgi_buffer* (*exception_class)(struct wsgi_request *);
|
||||
struct uwsgi_buffer* (*exception_msg)(struct wsgi_request *);
|
||||
struct uwsgi_buffer* (*exception_repr)(struct wsgi_request *);
|
||||
void (*exception_log)(struct wsgi_request *);
|
||||
};
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
int uwsgi_regexp_build(char *, pcre **, pcre_extra **);
|
||||
@@ -1506,6 +1509,14 @@ struct uwsgi_instance_status {
|
||||
int is_cleaning;
|
||||
};
|
||||
|
||||
struct uwsgi_configurator {
|
||||
char *name;
|
||||
void (*func)(char *, char **);
|
||||
struct uwsgi_configurator *next;
|
||||
};
|
||||
struct uwsgi_configurator *uwsgi_register_configurator(char *, void (*)(char *, char **));
|
||||
void uwsgi_opt_load_config(char *, char *, void *);
|
||||
|
||||
#define uwsgi_instance_is_dying (uwsgi.status.gracefully_destroying || uwsgi.status.brutally_destroying)
|
||||
#define uwsgi_instance_is_reloading (uwsgi.status.gracefully_reloading || uwsgi.status.brutally_reloading)
|
||||
|
||||
@@ -1517,6 +1528,7 @@ struct uwsgi_server {
|
||||
int hostname_len;
|
||||
|
||||
int (*proto_hooks[UWSGI_PROTO_MAX_CHECK]) (struct wsgi_request *, char *, char *, uint16_t);
|
||||
struct uwsgi_configurator *configurators;
|
||||
|
||||
char **orig_argv;
|
||||
char **argv;
|
||||
@@ -1628,6 +1640,7 @@ struct uwsgi_server {
|
||||
int emperor_fd;
|
||||
int emperor_queue;
|
||||
int emperor_tyrant;
|
||||
int emperor_tyrant_nofollow;
|
||||
int emperor_fd_config;
|
||||
int early_emperor;
|
||||
int emperor_throttle;
|
||||
@@ -1635,6 +1648,7 @@ struct uwsgi_server {
|
||||
int emperor_max_throttle;
|
||||
int emperor_magic_exec;
|
||||
int emperor_heartbeat;
|
||||
struct uwsgi_string_list *emperor_extra_extension;
|
||||
// search for a file with the specified extension at the same level of the vassal file
|
||||
char *emperor_on_demand_extension;
|
||||
// bind to a unix socket on the specified directory named directory/vassal.socket
|
||||
@@ -1849,6 +1863,7 @@ struct uwsgi_server {
|
||||
int threaded_logger;
|
||||
pthread_mutex_t threaded_logger_lock;
|
||||
|
||||
int daemons_honour_stdin;
|
||||
struct uwsgi_daemon *daemons;
|
||||
int daemons_cnt;
|
||||
|
||||
@@ -3242,6 +3257,8 @@ void uwsgi_opt_add_spooler(char *, char *, void *);
|
||||
void uwsgi_opt_add_daemon(char *, char *, void *);
|
||||
void uwsgi_opt_set_uid(char *, char *, void *);
|
||||
void uwsgi_opt_set_gid(char *, char *, void *);
|
||||
void uwsgi_opt_set_immediate_uid(char *, char *, void *);
|
||||
void uwsgi_opt_set_immediate_gid(char *, char *, void *);
|
||||
void uwsgi_opt_set_env(char *, char *, void *);
|
||||
void uwsgi_opt_unset_env(char *, char *, void *);
|
||||
void uwsgi_opt_pidfile_signal(char *, char *, void *);
|
||||
@@ -3743,9 +3760,12 @@ void uwsgi_user_unlock(int);
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
void uwsgi_opt_legion(char *, char *, void *);
|
||||
struct uwsgi_legion *uwsgi_legion_register(char *, char *, char *, char *, char *);
|
||||
void uwsgi_opt_legion_node(char *, char *, void *);
|
||||
void uwsgi_legion_register_node(struct uwsgi_legion *, char *);
|
||||
void uwsgi_opt_legion_quorum(char *, char *, void *);
|
||||
void uwsgi_opt_legion_hook(char *, char *, void *);
|
||||
void uwsgi_legion_register_hook(struct uwsgi_legion *, char *, char *);
|
||||
void uwsgi_opt_legion_scroll(char *, char *, void *);
|
||||
void uwsgi_legion_add(struct uwsgi_legion *);
|
||||
char *uwsgi_ssl_rand(size_t);
|
||||
@@ -3885,8 +3905,8 @@ char *uwsgi_get_header(struct wsgi_request *, char *, uint16_t, uint16_t *);
|
||||
void uwsgi_alarm_thread_start(void);
|
||||
void uwsgi_exceptions_handler_thread_start(void);
|
||||
|
||||
#define uwsgi_response_add_connection_close(x) uwsgi_response_add_header(x, "Connection", 10, "close", 5)
|
||||
#define uwsgi_response_add_content_type(x, y, z) uwsgi_response_add_header(x, "Content-Type", 12, y, z)
|
||||
#define uwsgi_response_add_connection_close(x) uwsgi_response_add_header(x, (char *)"Connection", 10, (char *)"close", 5)
|
||||
#define uwsgi_response_add_content_type(x, y, z) uwsgi_response_add_header(x, (char *)"Content-Type", 12, y, z)
|
||||
|
||||
struct uwsgi_stats_pusher_instance *uwsgi_stats_pusher_add(struct uwsgi_stats_pusher *, char *);
|
||||
|
||||
@@ -3928,6 +3948,8 @@ char *uwsgi_get_qs(struct wsgi_request *, char *, uint16_t, uint16_t *);
|
||||
struct uwsgi_route_var *uwsgi_get_route_var(char *, uint16_t);
|
||||
struct uwsgi_route_var *uwsgi_register_route_var(char *, char *(*)(struct wsgi_request *, char *, uint16_t, uint16_t *));
|
||||
|
||||
char *uwsgi_get_mime_type(char *, int, size_t *);
|
||||
|
||||
void uwsgi_check_emperor(void);
|
||||
#ifdef UWSGI_AS_SHARED_LIBRARY
|
||||
int uwsgi_init(int, char **, char **);
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
# uWSGI build system
|
||||
|
||||
uwsgi_version = '1.9.2'
|
||||
uwsgi_version = '1.9.5'
|
||||
|
||||
import os
|
||||
import re
|
||||
@@ -457,7 +457,7 @@ class uConf(object):
|
||||
self.config.readfp(open_profile(filename))
|
||||
self.gcc_list = ['core/utils', 'core/protocol', 'core/socket', 'core/logging', 'core/master', 'core/master_utils', 'core/emperor',
|
||||
'core/notify', 'core/mule', 'core/subscription', 'core/stats', 'core/sendfile', 'core/async', 'core/master_checks',
|
||||
'core/offload', 'core/io', 'core/static', 'core/websockets', 'core/spooler', 'core/snmp', 'core/exceptions',
|
||||
'core/offload', 'core/io', 'core/static', 'core/websockets', 'core/spooler', 'core/snmp', 'core/exceptions', 'core/config',
|
||||
'core/setup_utils', 'core/clock', 'core/init', 'core/buffer', 'core/reader', 'core/writer', 'core/alarm',
|
||||
'core/plugins', 'core/lock', 'core/cache', 'core/daemons', 'core/errors', 'core/hash', 'core/master_events',
|
||||
'core/queue', 'core/event', 'core/signal', 'core/strings', 'core/progress', 'core/timebomb', 'core/ini',
|
||||
|
||||
Reference in New Issue
Block a user