Compare commits

..
67 Commits
Author SHA1 Message Date
Unbit fe8ee7c7b3 uWSGI 1.9.4 2013-03-30 16:29:51 +01:00
Unbit cd382c6bc0 added rpcblob/rpcnext 2013-03-30 16:06:47 +01:00
Unbit e68296c293 a bit of cosmetic for uwsgi.h 2013-03-30 09:28:06 +01:00
Unbit cc189feae5 added uwsgi_register_signal to v8 2013-03-30 09:25:50 +01:00
unbit 18e19027a1 Merge pull request #207 from prymitive/legion_api
refactored legion opt functions to be more plugin friendly
2013-03-30 00:58:46 -07:00
Łukasz Mierzwa 2d2e0e4757 refactored legion opt functions to be more plugin friendly 2013-03-29 23:33:33 +01:00
Unbit a9f50d79f9 start 1.9.4 2013-03-29 21:24:56 +01:00
Unbit 0ccd31bee0 fixed reloading when in Go mode 2013-03-29 21:24:41 +01:00
Unbit 3ea82b2bcd do not differentiate reload when uWSGI is build as shared library 2013-03-29 21:21:46 +01:00
Unbit 6dad7b3ced ported the cplusplus plugin to the new api 2013-03-29 19:43:03 +01:00
Unbit f96ebd2b07 Merge branch 'master' of github.com:unbit/uwsgi 2013-03-29 19:37:53 +01:00
Unbit b8d0e7a3ac beta quality v8 plugin 2013-03-29 19:37:33 +01:00
unbit 14cca3d497 Merge pull request #204 from prymitive/legion_join_hook
legion join hook
2013-03-29 06:02:42 -07:00
Łukasz Mierzwa c343ca0cc3 legion join hook 2013-03-29 14:01:02 +01:00
Unbit 527d371bda fixed multiple mules event handling 2013-03-29 13:34:48 +01:00
Unbit b87a800a9a avoid resetting uwsgi.mywid in the master 2013-03-29 13:24:33 +01:00
Unbit e406993ed1 fixed typo 2013-03-29 12:51:52 +01:00
Unbit eeff935fc9 fixed signal handling in non-workers 2013-03-29 12:50:56 +01:00
Unbit 0791394f1a official support for SmartOS 2013-03-29 08:12:58 +00:00
unbit 082a407b06 Merge pull request #201 from prymitive/cache_restore_items_count
update cache items count after restore
2013-03-28 15:23:22 -07:00
Łukasz Mierzwa 8a89b49df1 update cache items count after restore 2013-03-28 23:20:17 +01:00
unbit 2314b9cbab Merge pull request #200 from jbert/master
Fix segfault in psgi plugin
2013-03-28 15:02:26 -07:00
John Berthels d0cca85c83 fix segfault in psgi handler after taking early-exit error path in coroae_accept_request 2013-03-28 17:29:00 +00:00
unbit 6a7a5cbcba Merge pull request #199 from prymitive/cache_stats_missin_list_close
missing list close in cache stats
2013-03-28 09:28:02 -07:00
Łukasz Mierzwa ecccc82cc8 missing list close 2013-03-28 16:56:31 +01:00
Unbit 02693489fe fixed php headers generation 2013-03-28 12:13:23 +01:00
Unbit 0f5dba5828 apache 2.4 support in mod_proxy_uwsgi 2013-03-28 11:19:13 +01:00
Unbit e528d4c4b7 implemented --emperor-tyrant-nofollow 2013-03-28 10:18:01 +01:00
Unbit 52a3af6acf prepare for uWSGI 1.9.3 2013-03-28 10:05:24 +01:00
Unbit dcefea9958 added rpcret routing action 2013-03-28 10:03:33 +01:00
Unbit 59121ff834 added --lua-load, fixed lua rpc memory leak 2013-03-28 09:21:47 +01:00
Unbit 7f5bb6d472 allows usage of configurators in the emperor 2013-03-28 09:07:15 +01:00
Unbit 639c1a508c support for lua ordered arrays in configurations 2013-03-28 09:00:10 +01:00
Unbit 417a26fc64 added config.lua example 2013-03-28 08:02:32 +01:00
Unbit 210ccd0063 allows configuration via lua 2013-03-28 08:02:07 +01:00
unbit 1bf0162d38 Merge pull request #196 from ryankask/jvm-plugin-import
Fix imports for the JVM plugin
2013-03-27 02:53:03 -07:00
Ryan Kaskel e93027fd7e Fix imports for JVM plugin. 2013-03-27 09:48:14 +00:00
Unbit 807060706f prepare for 1.9.2 2013-03-26 20:05:33 +01:00
Unbit a317f88d3c added the cache command to the ssi plugin 2013-03-26 20:03:37 +01:00
Unbit e17a7f0701 fixed a typo 2013-03-26 19:53:32 +01:00
Unbit db325eb9fe fixed readline() + post_buffering 2013-03-26 17:54:42 +01:00
Unbit b41a4c8c3b fixed python3 headers management 2013-03-26 16:45:57 +01:00
Unbit 73b4d11d18 added ssi router 2013-03-26 15:38:45 +01:00
Unbit 8162b87287 beta quality ssi plugin 2013-03-26 15:19:23 +01:00
Unbit 70e9e4f3ee added printenv 2013-03-26 12:24:17 +01:00
Unbit e61ae376b3 other improvements in the ssi plugin 2013-03-26 11:48:51 +01:00
Unbit 2d57b0e926 added preliminary ssi support 2013-03-26 11:33:00 +01:00
Unbit ae683af07a completed the geoip plugin [2] 2013-03-26 07:11:27 +01:00
Unbit 3c4f6a9171 completed the geoip plugin 2013-03-26 07:05:02 +01:00
Unbit 39986e546c fixed GeoIP plugin 2013-03-26 06:47:18 +01:00
Unbit 2e81a80f7b added preliminary geoip plugin 2013-03-25 19:11:20 +01:00
Unbit fcb3aa38c8 allows freeing route vars 2013-03-25 18:15:29 +01:00
Unbit 00a38d8ec5 fixed routing vars management 2013-03-25 18:10:41 +01:00
Unbit 07a0ab4227 pluggable routing vars 2013-03-25 18:05:57 +01:00
Unbit d4a9a2c543 fixed exceptions in the fiber plugin 2013-03-25 17:46:29 +01:00
Unbit 2b523fc60d added query string management functions 2013-03-25 10:21:20 +01:00
Unbit 0c26928236 added cookie management and --route-run 2013-03-25 09:56:53 +01:00
Unbit 8401e56a22 added 'empty' internal routing condition 2013-03-25 09:04:30 +01:00
Unbit 5109f9ae0b back to libxml2 default 2013-03-25 08:47:22 +01:00
Unbit c9bc06669a .ini file can backreference themselves 2013-03-25 08:47:00 +01:00
unbit a83fb2672c Merge pull request #189 from xtfxme/enhance/189-dashful-endif-endfor
Routing table appear to go nuts when used within a FOR loop
2013-03-24 23:18:50 -07:00
C Anthony Risinger 8f9ecb44d9 [#189] endfor/endif => end-for/end-if ...i know i'm not alone 2013-03-24 15:45:04 -05:00
Unbit bfcc09a8de prepare for cookie management in internal routing 2013-03-24 21:05:21 +01:00
Unbit f8a8c997db removed cache type in routing instruction 2013-03-24 20:30:56 +01:00
Unbit 132b996f30 added cachestore routing instruction 2013-03-24 19:43:41 +01:00
Unbit 12f970cdfb prepare for routing-governed caching 2013-03-24 19:24:13 +01:00
Unbit 9afa963225 prepare for gem 1.9.1 2013-03-24 11:39:44 +01:00
44 changed files with 2109 additions and 169 deletions
+43
View File
@@ -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] != '/') {
+26
View File
@@ -328,3 +328,29 @@ int uwsgi_buffer_set_uh(struct uwsgi_buffer *ub, uint8_t modifier1, uint8_t modi
ub->buf[3] = modifier2;
return 0;
}
struct uwsgi_buffer *uwsgi_buffer_from_file(char *filename) {
struct stat st;
int fd = open(filename, O_RDONLY);
if (fd < 0) {
return NULL;
}
if (fstat(fd, &st)) {
close(fd);
return NULL;
}
struct uwsgi_buffer *ub = uwsgi_buffer_new(st.st_size);
ssize_t len = read(fd, ub->buf, st.st_size);
close(fd);
if (len != st.st_size) {
uwsgi_buffer_destroy(ub);
return NULL;
}
ub->pos = len;
return ub;
}
+2 -1
View File
@@ -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) {
+33
View File
@@ -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;
}
+81
View File
@@ -0,0 +1,81 @@
#include <uwsgi.h>
/*
cookie management functions (mainly used by the internal routing subsystem)
*/
static char *check_cookie(char *cookie, uint16_t cookie_len, char *key, uint16_t keylen, uint16_t *vallen) {
uint16_t orig_cookie_len = cookie_len-1;
// first lstrip white spaces
char *ptr = cookie;
uint16_t i;
for(i=0;i<cookie_len;i++) {
if (isspace((int)ptr[i])) {
cookie++;
cookie_len--;
}
else {
break;
}
}
// then rstrip (skipping the first char...)
for(i=orig_cookie_len;i>0;i--) {
if (isspace((int)ptr[i])) {
cookie_len--;
}
else {
break;
}
}
// now search for the first equal sign
char *equal = memchr(cookie, '=', cookie_len);
if (!equal) return NULL;
if (uwsgi_strncmp(key, keylen, cookie, equal-cookie)) {
return NULL;
}
cookie_len -= (equal-cookie)+1;
if (cookie_len == 0) return NULL;
*vallen = cookie_len;
return equal+1;
}
char *uwsgi_get_cookie(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
uint16_t i;
char *cookie = wsgi_req->cookie;
uint16_t cookie_len = 0;
char *ptr = wsgi_req->cookie;
//start splitting by ;
for(i=0;i<wsgi_req->cookie_len;i++) {
if (!cookie) {
cookie = ptr + i;
}
if (ptr[i] == ';') {
char *value = check_cookie(cookie, cookie_len, key, keylen, vallen);
if (value) {
return value;
}
cookie_len = 0;
cookie = NULL;
}
else {
cookie_len++;
}
}
if (cookie_len > 0) {
char *value = check_cookie(cookie, cookie_len, key, keylen, vallen);
if (value) {
return value;
}
}
return NULL;
}
+60 -6
View File
@@ -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);
}
@@ -882,6 +927,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
View File
@@ -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");
}
}
+13 -1
View File
@@ -7,6 +7,8 @@ extern struct uwsgi_server uwsgi;
This memory must not be freed for all the server lifecycle
*/
static char *last_file = NULL;
void ini_rstrip(char *line) {
off_t i;
@@ -104,13 +106,23 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
if (colon[1] != 0) {
section_asked = colon + 1;
}
if (colon == file) {
file = last_file;
}
}
if (file[0] != 0) {
if (file[0] != 0 && file != last_file) {
uwsgi_log_initial("[uWSGI] getting INI configuration from %s\n", file);
}
ini = uwsgi_open_and_read(file, &len, 1, magic_table);
if (file != last_file) {
if (last_file) {
free(last_file);
}
last_file = uwsgi_str(file);
}
while (len) {
ini_line = ini_get_line(ini, len);
+64 -24
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+7
View File
@@ -354,6 +354,13 @@ static int uwsgi_proto_check_11(struct wsgi_request *wsgi_req, char *key, char *
return 0;
}
if (!uwsgi_proto_key("HTTP_COOKIE", 11)) {
wsgi_req->cookie = buf;
wsgi_req->cookie_len = len;
return 0;
}
if (!uwsgi_proto_key("UWSGI_APPID", 11)) {
wsgi_req->appid = buf;
wsgi_req->appid_len = len;
+57
View File
@@ -0,0 +1,57 @@
#include <uwsgi.h>
/*
QUERY_STRING management functions (mainly used by the internal routing subsystem)
*/
static char *check_qs(char *qs, uint16_t qs_len, char *key, uint16_t keylen, uint16_t *vallen) {
// search for the equal sign
char *equal = memchr(qs, '=', qs_len);
if (!equal) return NULL;
if (uwsgi_strncmp(key, keylen, qs, equal-qs)) {
return NULL;
}
qs_len -= (equal-qs)+1;
if (qs_len == 0) return NULL;
*vallen = qs_len;
return equal+1;
}
char *uwsgi_get_qs(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
uint16_t i;
char *qs = wsgi_req->query_string;
uint16_t qs_len = 0;
char *ptr = wsgi_req->query_string;
//start splitting by ;
for(i=0;i<wsgi_req->query_string_len;i++) {
if (!qs) {
qs = ptr + i;
}
if (ptr[i] == '&') {
char *value = check_qs(qs, qs_len, key, keylen, vallen);
if (value) {
return value;
}
qs_len = 0;
qs = NULL;
}
else {
qs_len++;
}
}
if (qs_len > 0) {
char *value = check_qs(qs, qs_len, key, keylen, vallen);
if (value) {
return value;
}
}
return NULL;
}
+14 -14
View File
@@ -108,64 +108,65 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
}
}
remains = UMIN(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark, wsgi_req->post_cl - wsgi_req->post_pos);
// read from a file
if (wsgi_req->post_file) {
size_t ret = fread(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, wsgi_req->post_readline_size - wsgi_req->post_readline_watermark, 1, wsgi_req->post_file);
size_t ret = fread(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, remains, 1, wsgi_req->post_file);
if (ret == 0) {
uwsgi_error("consume_body_for_readline()/fread()");
return -1;
}
wsgi_req->post_pos += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
wsgi_req->post_readline_watermark += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
wsgi_req->post_pos += remains;
wsgi_req->post_readline_watermark += remains;
return 0;
}
// read from post_buffering memory
if (uwsgi.post_buffering) {
wsgi_req->post_pos += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
memcpy(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, wsgi_req->post_buffering_buf + wsgi_req->post_pos, wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
wsgi_req->post_readline_watermark += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
memcpy(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, wsgi_req->post_buffering_buf + wsgi_req->post_pos, remains);
wsgi_req->post_pos += remains;
wsgi_req->post_readline_watermark += remains;
return 0;
}
// read from socket
ssize_t len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
ssize_t len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , remains);
if (len > 0) {
wsgi_req->post_pos += len;
wsgi_req->post_readline_watermark += len;
return 0;
}
if (len == 0) {
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
uwsgi_read_error(remains);
return -1;
}
if (len < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
goto wait;
}
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
uwsgi_read_error(remains);
return -1;
}
wait:
ret = uwsgi_wait_read_req(wsgi_req);
if (ret > 0) {
len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , remains);
if (len > 0) {
wsgi_req->post_pos += len;
wsgi_req->post_readline_watermark += len;
return 0;
}
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
uwsgi_read_error(remains);
return -1;
}
// 0 means timeout
else if (ret == 0) {
uwsgi_read_timeout(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
uwsgi_read_timeout(remains);
return -1;
}
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
uwsgi_read_error(remains);
return -1;
}
@@ -347,7 +348,6 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
if (wsgi_req->post_file) {
if (fread(wsgi_req->post_read_buf + *rlen, remains, 1, wsgi_req->post_file) != 1) {
*rlen = -1;
uwsgi_log("%llu\n", remains);
uwsgi_error("uwsgi_request_body_read()/fread()");
return NULL;
}
+102 -4
View File
@@ -3,6 +3,43 @@
extern struct uwsgi_server uwsgi;
struct uwsgi_route_var *uwsgi_register_route_var(char *name, char *(*func)(struct wsgi_request *, char *, uint16_t, uint16_t *)) {
struct uwsgi_route_var *old_urv = NULL,*urv = uwsgi.route_vars;
while(urv) {
if (!strcmp(urv->name, name)) {
return urv;
}
old_urv = urv;
urv = urv->next;
}
urv = uwsgi_calloc(sizeof(struct uwsgi_route_var));
urv->name = name;
urv->name_len = strlen(name);
urv->func = func;
if (old_urv) {
old_urv->next = urv;
}
else {
uwsgi.route_vars = urv;
}
return urv;
}
struct uwsgi_route_var *uwsgi_get_route_var(char *name, uint16_t name_len) {
struct uwsgi_route_var *urv = uwsgi.route_vars;
while(urv) {
if (!uwsgi_strncmp(urv->name, urv->name_len, name, name_len)) {
return urv;
}
urv = urv->next;
}
return NULL;
}
struct uwsgi_buffer *uwsgi_routing_translate(struct wsgi_request *wsgi_req, struct uwsgi_route *ur, char *subject, uint16_t subject_len, char *data, size_t data_len) {
char *pass1 = data;
@@ -44,9 +81,32 @@ struct uwsgi_buffer *uwsgi_routing_translate(struct wsgi_request *wsgi_req, stru
case 2:
if (pass1[i] == '}') {
uint16_t vallen = 0;
char *value = uwsgi_get_var(wsgi_req, key, keylen, &vallen);
int need_free = 0;
char *value = NULL;
char *bracket = memchr(key, '[', keylen);
if (bracket && keylen > 0 && key[keylen-1] == ']') {
struct uwsgi_route_var *urv = uwsgi_get_route_var(key, bracket - key);
if (urv) {
need_free = urv->need_free;
value = urv->func(wsgi_req, bracket + 1, keylen - (urv->name_len+2), &vallen);
}
else {
value = uwsgi_get_var(wsgi_req, key, keylen, &vallen);
}
}
else {
value = uwsgi_get_var(wsgi_req, key, keylen, &vallen);
}
if (value) {
if (uwsgi_buffer_append(ub, value, vallen)) goto error;
if (uwsgi_buffer_append(ub, value, vallen)) {
if (need_free) {
free(value);
}
goto error;
}
if (need_free) {
free(value);
}
}
status = 0;
key = NULL;
@@ -97,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;
}
@@ -108,6 +170,11 @@ int uwsgi_apply_routes_do(struct wsgi_request *wsgi_req, char *subject, uint16_t
wsgi_req->route_goto = 0;
if (!routes->if_func) {
// could be a "run"
if (!routes->subject) {
n = 0;
goto run;
}
if (!subject) {
char **subject2 = (char **) (((char *) (wsgi_req)) + routes->subject);
uint16_t *subject_len2 = (uint16_t *) (((char *) (wsgi_req)) + routes->subject_len);
@@ -137,6 +204,7 @@ int uwsgi_apply_routes_do(struct wsgi_request *wsgi_req, char *subject, uint16_t
}
}
run:
if (n >= 0) {
wsgi_req->is_routing = 1;
int ret = routes->func(wsgi_req, routes);
@@ -197,6 +265,8 @@ static void *uwsgi_route_get_condition_func(char *name) {
void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
char *space = NULL;
char *command = NULL;
struct uwsgi_route *old_ur = NULL,*ur = uwsgi.routes;
uint64_t pos = 0;
while(ur) {
@@ -223,7 +293,12 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
char *route = uwsgi_str(value);
char *space = strchr(route, ' ');
if (!strcmp(foobar, "run")) {
command = route;
goto done;
}
space = strchr(route, ' ');
if (!space) {
uwsgi_log("invalid route syntax\n");
exit(1);
@@ -299,7 +374,8 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
}
}
char *command = space + 1;
command = space + 1;
done:
ur->action = uwsgi_str(command);
char *colon = strchr(command, ':');
@@ -666,6 +742,20 @@ static int uwsgi_route_condition_regexp(struct wsgi_request *wsgi_req, struct uw
return 0;
}
static int uwsgi_route_condition_empty(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, ur->subject_str_len);
if (!ub) return -1;
if (ub->pos == 0) {
uwsgi_buffer_destroy(ub);
return 1;
}
uwsgi_buffer_destroy(ub);
return 0;
}
static int uwsgi_route_condition_equal(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
@@ -806,6 +896,11 @@ void uwsgi_register_embedded_routers() {
uwsgi_register_route_condition("endswith", uwsgi_route_condition_endswith);
uwsgi_register_route_condition("regexp", uwsgi_route_condition_regexp);
uwsgi_register_route_condition("re", uwsgi_route_condition_regexp);
uwsgi_register_route_condition("empty", uwsgi_route_condition_empty);
uwsgi_register_route_var("cookie", uwsgi_get_cookie);
uwsgi_register_route_var("qs", uwsgi_get_qs);
}
struct uwsgi_router *uwsgi_register_router(char *name, int (*func) (struct uwsgi_route *, char *)) {
@@ -864,6 +959,9 @@ void uwsgi_routing_dump() {
if (routes->label) {
uwsgi_log("[rule: %llu] label: %s\n", (unsigned long long ) routes->pos, routes->label);
}
else if (!routes->subject_str && !routes->if_func) {
uwsgi_log("[rule: %llu] action: %s\n", (unsigned long long ) routes->pos, routes->action);
}
else {
uwsgi_log("[rule: %llu] subject: %s %s: %s%s action: %s\n", (unsigned long long ) routes->pos, routes->subject_str, routes->if_func ? "func" : "regexp", routes->if_negate ? "!" : "", routes->regexp, routes->action);
}
+3 -1
View File
@@ -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;
}
-1
View File
@@ -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 !!!
+19
View File
@@ -622,6 +622,25 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
free(wsgi_req->proto_parser_buf);
}
// do we need to store the response in the cache
if (wsgi_req->cache_it) {
// only response with a body and a status code of 200 can be cached (TODO allows it to be configurable)
if (wsgi_req->cached_response && wsgi_req->status == 200 && wsgi_req->response_size > 0) {
uwsgi_cache_magic_set(wsgi_req->cache_it->buf, wsgi_req->cache_it->pos,
wsgi_req->cached_response->buf, wsgi_req->cached_response->pos, wsgi_req->cache_it_expires, UWSGI_CACHE_FLAG_UPDATE, wsgi_req->cache_it_to ? wsgi_req->cache_it_to->buf : NULL);
}
uwsgi_buffer_destroy(wsgi_req->cache_it);
}
if (wsgi_req->cache_it_to) {
uwsgi_buffer_destroy(wsgi_req->cache_it_to);
}
if (wsgi_req->cached_response) {
uwsgi_buffer_destroy(wsgi_req->cached_response);
}
if (!wsgi_req->do_not_account) {
uwsgi.workers[0].requests++;
uwsgi.workers[uwsgi.mywid].requests++;
+86 -1
View File
@@ -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},
@@ -80,6 +81,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"for", required_argument, 0, "(opt logic) for cycle", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for, UWSGI_OPT_IMMEDIATE},
{"for-glob", required_argument, 0, "(opt logic) for cycle (expand glob)", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for_glob, UWSGI_OPT_IMMEDIATE},
{"endfor", optional_argument, 0, "(opt logic) end for cycle", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
{"end-for", optional_argument, 0, "(opt logic) end for cycle", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
{"if-opt", required_argument, 0, "(opt logic) check for option", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_opt, UWSGI_OPT_IMMEDIATE},
{"if-not-opt", required_argument, 0, "(opt logic) check for option", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_not_opt, UWSGI_OPT_IMMEDIATE},
@@ -108,6 +110,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"if-directory", required_argument, 0, "(opt logic) check for directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_dir, UWSGI_OPT_IMMEDIATE},
{"endif", optional_argument, 0, "(opt logic) end if", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
{"end-if", optional_argument, 0, "(opt logic) end if", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
{"blacklist", required_argument, 0, "set options blacklist context", uwsgi_opt_set_str, &uwsgi.blacklist_context, UWSGI_OPT_IMMEDIATE},
{"end-blacklist", no_argument, 0, "clear options blacklist context", uwsgi_opt_set_null, &uwsgi.blacklist_context, UWSGI_OPT_IMMEDIATE},
@@ -169,6 +172,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"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},
@@ -181,6 +185,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},
@@ -261,6 +267,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},
@@ -375,9 +383,9 @@ 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", 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},
{"legion-scroll-list-max-size", required_argument, 0, "set max size of legion scroll list buffer", uwsgi_opt_set_64bit, &uwsgi.legion_scroll_list_max_size, 0},
{"subscriptions-sign-check", required_argument, 0, "set digest algorithm and certificate directory for secured subscription system", uwsgi_opt_scd, NULL, UWSGI_OPT_MASTER},
@@ -511,6 +519,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"route-label", required_argument, 0, "add a routing label (for use with goto)", uwsgi_opt_add_route, NULL, 0},
{"route-if", required_argument, 0, "add a route based on condition", uwsgi_opt_add_route, "if", 0},
{"route-if-not", required_argument, 0, "add a route based on condition (negate version)", uwsgi_opt_add_route, "if-not", 0},
{"route-run", required_argument, 0, "always run the specified route action", uwsgi_opt_add_route, "run", 0},
{"router-list", no_argument, 0, "list enabled routers", uwsgi_opt_true, &uwsgi.router_list, 0},
{"routers-list", no_argument, 0, "list enabled routers", uwsgi_opt_true, &uwsgi.router_list, 0},
#endif
@@ -784,8 +793,12 @@ void config_magic_table_fill(char *filename, char **magic_table) {
char *section = uwsgi_get_last_char(filename, ':');
if (section) {
*section = 0;
if (section == filename) {
goto reuse;
}
}
// we have a special case for symlinks
if (uwsgi_is_link(filename)) {
if (filename[0] != '/') {
@@ -839,6 +852,7 @@ void config_magic_table_fill(char *filename, char **magic_table) {
if (uwsgi_get_last_char(magic_table['s'], '.'))
magic_table['n'] = uwsgi_concat2n(magic_table['s'], uwsgi_get_last_char(magic_table['s'], '.') - magic_table['s'], "", 0);
reuse:
if (section) {
magic_table['x'] = section+1;
*section = ':';
@@ -3178,6 +3192,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) {
@@ -3757,6 +3824,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) {
@@ -3783,6 +3853,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);
+13
View File
@@ -141,6 +141,7 @@ int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
return UWSGI_OK;
}
// this is the function called by all request plugins to send chunks to the client
int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_t len) {
if (wsgi_req->write_errors) return -1;
@@ -182,6 +183,18 @@ sendbody:
// reset for the next write
wsgi_req->write_pos = 0;
// now we need to check if the chunk must be stored
if (wsgi_req->cache_it) {
if (!wsgi_req->cached_response) {
wsgi_req->cached_response = uwsgi_buffer_new(len);
}
// if we are unable to append the buffer, we just stop caching it
if (uwsgi_buffer_append(wsgi_req->cached_response, buf, len)) {
uwsgi_buffer_destroy(wsgi_req->cache_it);
wsgi_req->cache_it = NULL;
}
}
return UWSGI_OK;
}
+9
View File
@@ -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
+8
View File
@@ -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
+6 -4
View File
@@ -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 -1
View File
@@ -1,4 +1,4 @@
#include "../../uwsgi.h"
#include <uwsgi.h>
int uwsgi_cplusplus_init(void);
+2 -1
View File
@@ -2,6 +2,7 @@
extern struct uwsgi_server uwsgi;
extern struct uwsgi_rack ur;
extern struct uwsgi_plugin rack_plugin;
struct ufib {
int enabled;
@@ -45,7 +46,7 @@ static void fiber_schedule_to_req() {
int error = 0;
rb_protect(rb_fiber_schedule_to_req, 0, &error);
if (error) {
uwsgi_ruby_exception();
rack_plugin.exception_log(NULL);
rb_gc_unregister_address(&ufiber.fib[id]);
uwsgi.wsgi_req->async_status = UWSGI_OK;
}
+141
View File
@@ -0,0 +1,141 @@
#include <uwsgi.h>
#include <GeoIP.h>
#include <GeoIPCity.h>
struct uwsgi_geoip {
char *country_db;
char *city_db;
GeoIP *country;
GeoIP *city;
} ugeoip;
struct uwsgi_option uwsgi_geoip_options[] = {
{"geoip-country", required_argument, 0, "load the specified geoip country database", uwsgi_opt_set_str, &ugeoip.country_db, 0},
{"geoip-city", required_argument, 0, "load the specified geoip city database", uwsgi_opt_set_str, &ugeoip.city_db, 0},
{ 0, 0, 0, 0, 0, 0, 0 }
};
static int uwsgi_geoip_init() {
if (ugeoip.country_db) {
ugeoip.country = GeoIP_open(ugeoip.country_db, GEOIP_MEMORY_CACHE);
if (!ugeoip.country) {
uwsgi_log("unable to open GeoIP country database: %s\n", ugeoip.country_db);
exit(1);
}
}
if (ugeoip.city_db) {
ugeoip.city = GeoIP_open(ugeoip.city_db, GEOIP_MEMORY_CACHE);
if (!ugeoip.city) {
uwsgi_log("unable to open GeoIP city database: %s\n", ugeoip.city_db);
exit(1);
}
}
return 0;
}
static char *uwsgi_route_var_geoip(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
uint32_t ip;
char ip_str[16];
// should be enough for geo coords
char lonlat[64];
memset(ip_str, 0, 16);
memcpy(ip_str, wsgi_req->remote_addr, wsgi_req->remote_addr_len);
if (inet_pton(AF_INET, ip_str, &ip) <= 0) {
return NULL;
}
ip = htonl(ip);
char *value = NULL;
// always prefer the city database;
GeoIP *g = ugeoip.city;
if (!g) {
g = ugeoip.country;
if (g) {
if (!uwsgi_strncmp(key, keylen, "country_code", 12)) {
value = (char *) GeoIP_country_code_by_ipnum(g, ip);
}
else if (!uwsgi_strncmp(key, keylen, "country_code3", 13)) {
value = (char *) GeoIP_country_code3_by_ipnum(g, ip);
}
else if (!uwsgi_strncmp(key, keylen, "country_name", 12)) {
value = (char *) GeoIP_country_name_by_ipnum(g, ip);
}
if (value) {
*vallen = strlen(value);
return uwsgi_str(value);
}
}
return NULL;
}
GeoIPRecord *gr = GeoIP_record_by_ipnum(g, ip);
if (!gr) return NULL;
// ok let's generate the output
if (!uwsgi_strncmp(key, keylen, "continent", 9)) {
value = gr->continent_code;
}
else if (!uwsgi_strncmp(key, keylen, "country_code", 12)) {
value = gr->country_code;
}
else if (!uwsgi_strncmp(key, keylen, "country_code3", 13)) {
value = gr->country_code3;
}
else if (!uwsgi_strncmp(key, keylen, "country_name", 12)) {
value = gr->country_name;
}
else if (!uwsgi_strncmp(key, keylen, "region", 6)) {
value = gr->region;
}
else if (!uwsgi_strncmp(key, keylen, "region_name", 11)) {
value = (char *) GeoIP_region_name_by_code(gr->country_code, gr->region);
}
else if (!uwsgi_strncmp(key, keylen, "city", 4)) {
value = gr->city;
}
else if (!uwsgi_strncmp(key, keylen, "postal_code", 11)) {
value = gr->postal_code;
}
else if (!uwsgi_strncmp(key, keylen, "latitude", 8) || !uwsgi_strncmp(key, keylen, "lat", 3)) {
snprintf(lonlat, 64, "%f", gr->latitude);
value = lonlat;
}
else if (!uwsgi_strncmp(key, keylen, "longitude", 9) || !uwsgi_strncmp(key, keylen, "lon", 3)) {
snprintf(lonlat, 64, "%f", gr->longitude);
value = lonlat;
}
else if (!uwsgi_strncmp(key, keylen, "dma", 3)) {
snprintf(lonlat, 64, "%d", gr->dma_code);
value = lonlat;
}
else if (!uwsgi_strncmp(key, keylen, "area", 4)) {
snprintf(lonlat, 64, "%d", gr->area_code);
value = lonlat;
}
if (value) {
*vallen = strlen(value);
char *ret = uwsgi_str(value);
GeoIPRecord_delete(gr);
return ret;
}
GeoIPRecord_delete(gr);
return NULL;
}
static void register_route_vars_geoip() {
struct uwsgi_route_var *urv = uwsgi_register_route_var("geoip", uwsgi_route_var_geoip);
urv->need_free = 1;
}
struct uwsgi_plugin geoip_plugin = {
.name = "geoip",
.options = uwsgi_geoip_options,
.init = uwsgi_geoip_init,
.on_load = register_route_vars_geoip,
};
+8
View File
@@ -0,0 +1,8 @@
NAME='geoip'
CFLAGS = []
LDFLAGS = []
LIBS = ['-lGeoIP']
GCC_LIST = ['geoip']
+2 -1
View File
@@ -1,4 +1,5 @@
import os,sys
import os
import shutil
NAME='jvm'
+116 -22
View File
@@ -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 -1
View File
@@ -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);
+5 -1
View File
@@ -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)
+1 -1
View File
@@ -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)
+22 -8
View File
@@ -58,11 +58,12 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
char *status_line = NULL;
size_t status_line_len = 0;
#ifdef PYTHREE
PyObject *zero = NULL;
PyObject *zero2 = NULL;
if (self != Py_None) {
PyObject *zero = PyUnicode_AsASCIIString(head);
zero = PyUnicode_AsASCIIString(head);
status_line = PyBytes_AsString(zero);
status_line_len = PyBytes_Size(zero);
Py_DECREF(zero);
}
else {
status_line = PyBytes_AsString(head);
@@ -73,9 +74,15 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
status_line_len = PyString_Size(head);
#endif
if (uwsgi_response_prepare_headers(wsgi_req, status_line, status_line_len)) {
#ifdef PYTHREE
Py_DECREF(zero);
#endif
return PyErr_Format(PyExc_TypeError, "unable to set HTTP status line");
}
#ifdef PYTHREE
Py_DECREF(zero);
#endif
headers = PyTuple_GetItem(args, 1);
if (!headers) {
@@ -125,10 +132,9 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
#ifdef PYTHREE
if (self != Py_None) {
PyObject *zero = PyUnicode_AsASCIIString(h_key);
zero = PyUnicode_AsASCIIString(h_key);
k = PyBytes_AsString(zero);
kl = PyBytes_Size(zero);
Py_DECREF(zero);
}
else {
k = PyBytes_AsString(h_key);
@@ -141,10 +147,9 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
#ifdef PYTHREE
if (self != Py_None) {
PyObject *zero = PyUnicode_AsASCIIString(h_value);
v = PyBytes_AsString(zero);
vl = PyBytes_Size(zero);
Py_DECREF(zero);
zero2 = PyUnicode_AsASCIIString(h_value);
v = PyBytes_AsString(zero2);
vl = PyBytes_Size(zero2);
}
else {
v = PyBytes_AsString(h_value);
@@ -156,9 +161,18 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
#endif
if (uwsgi_response_add_header(wsgi_req, k, kl, v, vl)) {
#ifdef PYTHREE
Py_DECREF(zero);
Py_DECREF(zero2);
#endif
return PyErr_Format(PyExc_TypeError, "unable to add header to the response");
}
#ifdef PYTHREE
Py_DECREF(zero);
Py_DECREF(zero2);
#endif
}
if (up.start_response_nodelay) {
+86 -17
View File
@@ -10,7 +10,7 @@ extern struct uwsgi_server uwsgi;
syntax:
route = /^foobar1(.*)/ cache:key=foo$1poo,type=body,content_type=text/html,name=foobar
route = /^foobar1(.*)/ cache:key=foo$1poo,content_type=text/html,name=foobar
*/
@@ -18,21 +18,57 @@ struct uwsgi_router_cache_conf {
// the name of the cache
char *name;
size_t name_len;
char *key;
size_t key_len;
char *type;
char *content_type;
size_t content_type_len;
// 0 -> full, 1 -> body
int type_num;
struct uwsgi_cache *cache;
char *expires_str;
uint64_t expires;
};
// be tolerant on errors
static int uwsgi_routing_func_cache_store(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
struct uwsgi_router_cache_conf *urcc = (struct uwsgi_router_cache_conf *) ur->data2;
// overwrite previous run
if (wsgi_req->cache_it) {
uwsgi_buffer_destroy(wsgi_req->cache_it);
wsgi_req->cache_it = NULL;
}
if (wsgi_req->cache_it_to) {
uwsgi_buffer_destroy(wsgi_req->cache_it_to);
wsgi_req->cache_it_to = NULL;
}
// build key and name
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
wsgi_req->cache_it = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urcc->key, urcc->key_len);
if (!wsgi_req->cache_it) return UWSGI_ROUTE_NEXT;
if (urcc->name) {
wsgi_req->cache_it_to = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urcc->name, urcc->name_len);
if (!wsgi_req->cache_it_to) {
uwsgi_buffer_destroy(wsgi_req->cache_it);
wsgi_req->cache_it = NULL;
}
}
wsgi_req->cache_it_expires = urcc->expires;
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_routing_func_cache(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
struct uwsgi_router_cache_conf *urcc = (struct uwsgi_router_cache_conf *) ur->data2;
@@ -46,12 +82,9 @@ static int uwsgi_routing_func_cache(struct wsgi_request *wsgi_req, struct uwsgi_
char *value = uwsgi_cache_magic_get(ub->buf, ub->pos, &valsize, urcc->name);
uwsgi_buffer_destroy(ub);
if (value) {
if (urcc->type_num == 1) {
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto error;
if (uwsgi_response_add_content_type(wsgi_req, urcc->content_type, urcc->content_type_len)) goto error;
if (uwsgi_response_add_content_length(wsgi_req, valsize)) goto error;
}
// body only
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto error;
if (uwsgi_response_add_content_type(wsgi_req, urcc->content_type, urcc->content_type_len)) goto error;
if (uwsgi_response_add_content_length(wsgi_req, valsize)) goto error;
uwsgi_response_write_body_do(wsgi_req, value, valsize);
free(value);
if (ur->custom)
@@ -65,6 +98,45 @@ error:
return UWSGI_ROUTE_BREAK;
}
static int uwsgi_router_cache_store(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_cache_store;
ur->data = args;
ur->data_len = strlen(args);
struct uwsgi_router_cache_conf *urcc = uwsgi_calloc(sizeof(struct uwsgi_router_cache_conf));
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
"key", &urcc->key,
"name", &urcc->name,
"expires", &urcc->expires_str, NULL)) {
uwsgi_log("invalid cachestore route syntax: %s\n", args);
goto error;
}
if (urcc->key) {
urcc->key_len = strlen(urcc->key);
}
if (urcc->name) {
urcc->name_len = strlen(urcc->name);
}
if (!urcc->key) {
uwsgi_log("invalid cachestore route syntax: you need to specify a cache key\n");
goto error;
}
if (urcc->expires_str) {
urcc->expires = strtoul(urcc->expires_str, NULL, 10);
}
ur->data2 = urcc;
return 0;
error:
if (urcc->key) free(urcc->key);
if (urcc->name) free(urcc->name);
if (urcc->expires_str) free(urcc->expires_str);
return -1;
}
static int uwsgi_router_cache(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_cache;
ur->data = args;
@@ -74,7 +146,7 @@ static int uwsgi_router_cache(struct uwsgi_route *ur, char *args) {
"key", &urcc->key,
"content_type", &urcc->content_type,
"name", &urcc->name,
"type", &urcc->type, NULL)) {
NULL)) {
uwsgi_log("invalid route syntax: %s\n", args);
exit(1);
}
@@ -88,15 +160,10 @@ static int uwsgi_router_cache(struct uwsgi_route *ur, char *args) {
exit(1);
}
if (!urcc->type) urcc->type = "full";
if (!urcc->content_type) urcc->content_type = "text/html";
urcc->content_type_len = strlen(urcc->content_type);
if (!strcmp(urcc->type, "body")) {
urcc->type_num = 1;
}
ur->data2 = urcc;
return 0;
}
@@ -110,6 +177,8 @@ static int uwsgi_router_cache_continue(struct uwsgi_route *ur, char *args) {
static void router_cache_register() {
uwsgi_register_router("cache", uwsgi_router_cache);
uwsgi_register_router("cache-continue", uwsgi_router_cache_continue);
uwsgi_register_router("cachestore", uwsgi_router_cache_store);
uwsgi_register_router("cache-store", uwsgi_router_cache_store);
}
struct uwsgi_plugin router_cache_plugin = {
+171 -2
View File
@@ -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
+526
View File
@@ -0,0 +1,526 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
#define UWSGI_SSI_MAX_ARGS 8
/*
uWSGI server side includes implementation
*/
struct uwsgi_ssi_arg {
char *key;
size_t key_len;
char *value;
size_t val_len;
};
struct uwsgi_ssi_cmd {
char *name;
size_t name_len;
struct uwsgi_buffer *(*func)(struct wsgi_request *, struct uwsgi_ssi_arg *, int);
struct uwsgi_ssi_cmd *next;
};
struct uwsgi_ssi_cmd *uwsgi_ssi_commands = NULL;
static struct uwsgi_ssi_cmd* uwsgi_ssi_get_cmd(char *name, size_t name_len) {
struct uwsgi_ssi_cmd *usc = uwsgi_ssi_commands;
while(usc) {
if (!uwsgi_strncmp(usc->name, usc->name_len, name, name_len)) {
return usc;
}
usc = usc->next;
}
return NULL;
}
static struct uwsgi_ssi_cmd *uwsgi_register_ssi_command(char *name, struct uwsgi_buffer *(*func)(struct wsgi_request *, struct uwsgi_ssi_arg *, int)) {
struct uwsgi_ssi_cmd *old_usc = NULL,*usc = uwsgi_ssi_commands;
while(usc) {
if (!strcmp(usc->name, name)) {
return usc;
}
old_usc = usc;
usc = usc->next;
}
usc = uwsgi_calloc(sizeof(struct uwsgi_ssi_cmd));
usc->name = name;
usc->name_len = strlen(name);
usc->func = func;
if (old_usc) {
old_usc->next = usc;
}
else {
uwsgi_ssi_commands = usc;
}
return usc;
}
static int uwsgi_ssi_parse_args(struct wsgi_request *wsgi_req, char *buf, size_t len, struct uwsgi_ssi_arg *argv, int *argc) {
// status [0]null/= [1]" [2]" [3]\s
size_t i;
uint8_t status = 0;
char *key = buf;
size_t key_len = 0;
char *value = NULL;
size_t val_len = 0;
for(i=0;i<len;i++) {
switch(status) {
case 0:
if (buf[i] == '=') {
status = 1;
}
else {
key_len++;
}
break;
case 1:
if (buf[i] == '"') {
status = 2;
}
else {
return -1;
}
break;
case 2:
if (buf[i] == '"') {
status = 3;
argv[*argc].key = key; argv[*argc].key_len = key_len;
argv[*argc].value = value; argv[*argc].val_len = val_len;
*argc = *argc+1;
if (*argc >= UWSGI_SSI_MAX_ARGS) {
return -1;
}
key = NULL;
key_len = 0;
value = NULL;
val_len = 0;
}
else {
if (!value) {
value = buf + i;
}
val_len++;
}
break;
case 3:
if (!isspace((int)buf[i])) {
key = buf + i;
key_len = 1;
status = 0;
}
break;
default:
return -1;
}
}
return 0;
}
static struct uwsgi_buffer *uwsgi_ssi_parse_command(struct wsgi_request *wsgi_req, char *buf, size_t len) {
// storage for arguments
struct uwsgi_ssi_arg argv[UWSGI_SSI_MAX_ARGS];
int argc = 0;
// first remove white spaces from the begin and the end
char *cmd = buf;
size_t cmd_len = len;
size_t i;
for(i=0;i<len;i++) {
if (isspace((int)buf[i])) {
cmd++;
cmd_len--;
}
else {
break;
}
}
// then rstrip (skipping the first char...)
for(i=(len-1);i>0;i--) {
if (isspace((int)buf[i])) {
cmd_len--;
}
else {
break;
}
}
// now get the command
char *ssi_cmd = cmd;
size_t ssi_cmd_len = 0;
int found = 0;
for(i=0;i<cmd_len;i++) {
if (isspace(cmd[i])) {
found = 1;
break;
}
ssi_cmd_len++;
}
struct uwsgi_ssi_cmd *usc = uwsgi_ssi_get_cmd(ssi_cmd, ssi_cmd_len);
if (!usc) return NULL ;
if (!found) goto run;
// now split the args
char *cmd_args = cmd + ssi_cmd_len + 1;
size_t cmd_args_len = cmd_len - (ssi_cmd_len + 1);
for(i=(ssi_cmd_len + 1);i<cmd_len;i++) {
if (isspace((int)cmd[i])) {
cmd_args++;
cmd_args_len--;
}
else {
break;
}
}
if (uwsgi_ssi_parse_args(wsgi_req, cmd_args, cmd_args_len, argv, &argc)) {
return NULL;
}
run:
return usc->func(wsgi_req, argv, argc);
}
static struct uwsgi_buffer *uwsgi_ssi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len) {
size_t i;
uint8_t status = 0;
char *cmd = NULL;
size_t cmd_len = 0;
struct uwsgi_buffer *ub = uwsgi_buffer_new(len);
// parsing status 0[null] 1[<] 2[!] 3[-] 4[-] 5[#/-] 6[-] 7[>]
// on status 6-7-8 the reset action come back to 5 instead of 0
for(i=0;i<len;i++) {
switch(status) {
case 0:
if (buf[i] == '<') {
status = 1;
}
else {
if (uwsgi_buffer_append(ub, &buf[i], 1)) goto error;
}
break;
case 1:
status = 0;
if (buf[i] == '!') {
status = 2;
}
else {
if (uwsgi_buffer_append(ub, "<", 1)) goto error;
if (uwsgi_buffer_append(ub, &buf[i], 1)) goto error;
}
break;
case 2:
status = 0;
if (buf[i] == '-') {
status = 3;
}
else {
if (uwsgi_buffer_append(ub, "<!", 2)) goto error;
if (uwsgi_buffer_append(ub, &buf[i], 1)) goto error;
}
break;
case 3:
status = 0;
if (buf[i] == '-') {
status = 4;
}
else {
if (uwsgi_buffer_append(ub, "<!-", 3)) goto error;
if (uwsgi_buffer_append(ub, &buf[i], 1)) goto error;
}
break;
case 4:
status = 0;
if (buf[i] == '#') {
status = 5;
}
else {
if (uwsgi_buffer_append(ub, "<!--", 4)) goto error;
if (uwsgi_buffer_append(ub, &buf[i], 1)) goto error;
}
break;
case 5:
if (buf[i] == '-') {
status = 6;
break;
}
if (!cmd) {
cmd = buf+i;
}
cmd_len++;
break;
case 6:
status = 5;
if (buf[i] == '-') {
status = 7;
}
else {
cmd_len+=2;
}
break;
case 7:
status = 5;
if (buf[i] == '>') {
status = 0;
struct uwsgi_buffer *ub_cmd = uwsgi_ssi_parse_command(wsgi_req, cmd, cmd_len);
if (ub_cmd) {
if (uwsgi_buffer_append(ub, ub_cmd->buf, ub_cmd->pos)) {
uwsgi_buffer_destroy(ub_cmd);
goto error;
}
uwsgi_buffer_destroy(ub_cmd);
}
cmd = NULL;
cmd_len = 0;
}
else {
cmd_len+=3;
}
break;
default:
goto error;
}
}
return ub;
error:
uwsgi_buffer_destroy(ub);
return NULL;
}
static int uwsgi_ssi_request(struct wsgi_request *wsgi_req) {
struct uwsgi_buffer *ub = NULL;
if (uwsgi_parse_vars(wsgi_req)) {
return -1;
}
if (!wsgi_req->document_root_len || !wsgi_req->path_info_len) {
uwsgi_log("[uwsgi-ssi] DOCUMENT_ROOT and PATH_INFO must be defined !!!\n");
uwsgi_500(wsgi_req);
return UWSGI_OK;
}
char *filename = uwsgi_concat3n(wsgi_req->document_root, wsgi_req->document_root_len, "/", 1, wsgi_req->path_info, wsgi_req->path_info_len);
size_t filename_len = wsgi_req->document_root_len + 1 + wsgi_req->path_info_len;
// we expand the path for future security implementations
char *real_filename = uwsgi_expand_path(filename, filename_len, NULL);
free(filename);
if (!real_filename) {
uwsgi_404(wsgi_req);
return UWSGI_OK;
}
struct uwsgi_buffer *ub_ssi = uwsgi_buffer_from_file(real_filename);
free(real_filename);
if (!ub_ssi) {
uwsgi_500(wsgi_req);
return UWSGI_OK;
}
ub = uwsgi_ssi_parse(wsgi_req, ub_ssi->buf, ub_ssi->pos);
uwsgi_buffer_destroy(ub_ssi);
if (!ub) {
uwsgi_500(wsgi_req);
return UWSGI_OK;
}
// prepare headers
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) {
uwsgi_500(wsgi_req);
goto end;
}
// content_length
if (uwsgi_response_add_content_length(wsgi_req, ub->pos)) {
uwsgi_500(wsgi_req);
goto end;
}
// content_type
if (uwsgi_response_add_content_type(wsgi_req, "text/html", 9)) {
uwsgi_500(wsgi_req);
goto end;
}
uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
end:
if (ub) {
uwsgi_buffer_destroy(ub);
}
return UWSGI_OK;
}
static char *uwsgi_ssi_get_arg(struct uwsgi_ssi_arg *argv, int argc, char *key, size_t key_len, size_t *val_len) {
int i;
for(i=0;i<argc;i++) {
struct uwsgi_ssi_arg *arg = &argv[i];
if (!uwsgi_strncmp(arg->key, arg->key_len, key, key_len)) {
*val_len = arg->val_len;
return arg->value;
}
}
return NULL;
}
// echo command
static struct uwsgi_buffer *ssi_cmd_echo(struct wsgi_request *wsgi_req, struct uwsgi_ssi_arg *argv, int argc) {
size_t var_len = 0;
char *var = uwsgi_ssi_get_arg(argv, argc, "var", 3, &var_len);
if (!var || var_len == 0) return NULL;
uint16_t rlen = 0;
char *value = uwsgi_get_var(wsgi_req, var, var_len, &rlen);
if (!value) return NULL;
if (rlen == 0) return NULL;
struct uwsgi_buffer *ub = uwsgi_buffer_new(rlen);
if (uwsgi_buffer_append(ub, value, rlen)) {
uwsgi_buffer_destroy(ub);
return NULL;
}
return ub;
};
// printenv command
static struct uwsgi_buffer *ssi_cmd_printenv(struct wsgi_request *wsgi_req, struct uwsgi_ssi_arg *argv, int argc) {
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
int i;
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
if (uwsgi_buffer_append(ub, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len)) goto error;
if (uwsgi_buffer_append(ub, "=", 1)) goto error;
if (uwsgi_buffer_append(ub, wsgi_req->hvec[i+1].iov_base, wsgi_req->hvec[i+1].iov_len)) goto error;
if (uwsgi_buffer_append(ub, "\n", 1)) goto error;
}
return ub;
error:
uwsgi_buffer_destroy(ub);
return NULL;
};
// include command
static struct uwsgi_buffer *ssi_cmd_include(struct wsgi_request *wsgi_req, struct uwsgi_ssi_arg *argv, int argc) {
size_t var_len = 0;
char *var = uwsgi_ssi_get_arg(argv, argc, "file", 4, &var_len);
if (!var || var_len == 0) return NULL;
char *filename = uwsgi_concat2n(var, var_len, "", 0);
struct uwsgi_buffer *ub = uwsgi_buffer_from_file(filename);
free(filename);
return ub;
}
// cache command (uWSGI specific)
static struct uwsgi_buffer *ssi_cmd_cache(struct wsgi_request *wsgi_req, struct uwsgi_ssi_arg *argv, int argc) {
size_t var_len = 0;
char *var = uwsgi_ssi_get_arg(argv, argc, "key", 3, &var_len);
if (!var || var_len == 0) return NULL;
size_t cache_len = 0;
char *cache = uwsgi_ssi_get_arg(argv, argc, "name", 4, &cache_len);
char *cache_name = NULL;
if (cache && cache_len) {
cache_name = uwsgi_concat2n(cache, cache_len, "", 0);
}
uint64_t rlen = 0;
char *value = uwsgi_cache_magic_get(var, var_len, &rlen, cache_name);
if (cache_name) free(cache_name);
struct uwsgi_buffer *ub = NULL;
if (value) {
ub = uwsgi_buffer_new(rlen);
if (uwsgi_buffer_append(ub, value, rlen)) {
free(value);
uwsgi_buffer_destroy(ub);
return NULL;
}
free(value);
}
return ub;
}
static int uwsgi_routing_func_ssi(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
struct uwsgi_buffer *ub = NULL;
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub_filename = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub_filename) goto end;
struct uwsgi_buffer *ub_ssi = uwsgi_buffer_from_file(ub_filename->buf);
uwsgi_buffer_destroy(ub_filename);
if (!ub_ssi) goto end;
ub = uwsgi_ssi_parse(wsgi_req, ub_ssi->buf, ub_ssi->pos);
uwsgi_buffer_destroy(ub_ssi);
if (!ub) goto end;
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto end;
if (uwsgi_response_add_content_length(wsgi_req, ub->pos)) goto end;
if (uwsgi_response_add_content_type(wsgi_req, "text/html", 9)) goto end;
uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
end:
if (ub) uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
static int uwsgi_router_ssi(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_ssi;
ur->data = args;
ur->data_len = strlen(args);
return 0;
}
static int uwsgi_ssi_init() {
uwsgi_register_ssi_command("echo", ssi_cmd_echo);
uwsgi_register_ssi_command("printenv", ssi_cmd_printenv);
uwsgi_register_ssi_command("include", ssi_cmd_include);
uwsgi_register_ssi_command("cache", ssi_cmd_cache);
return 0;
}
static void uwsgi_ssi_register_router() {
uwsgi_register_router("ssi", uwsgi_router_ssi);
}
static void uwsgi_ssi_log(struct wsgi_request *wsgi_req) {
log_request(wsgi_req);
}
struct uwsgi_plugin ssi_plugin = {
.name = "ssi",
.modifier1 = 19,
.init = uwsgi_ssi_init,
.request = uwsgi_ssi_request,
.after_request = uwsgi_ssi_log,
.on_load = uwsgi_ssi_register_router,
};
+6
View File
@@ -0,0 +1,6 @@
NAME='ssi'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['ssi']
+29
View File
@@ -0,0 +1,29 @@
#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 *);
static void uwsgi_v8_register(void) {
uwsgi_register_configurator(".js", uwsgi_v8_configurator);
}
extern struct uwsgi_option uwsgi_v8_options[];
static int uwsgi_v8_request(struct wsgi_request *wsgi_req) {
return UWSGI_OK;
}
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,
.signal_handler = uwsgi_v8_signal_handler,
};
+6
View File
@@ -0,0 +1,6 @@
NAME='v8'
CFLAGS = []
LDFLAGS = []
LIBS = ['-lv8']
GCC_LIST = ['plugin', 'v8_uwsgi.cc']
+237
View File
@@ -0,0 +1,237 @@
#include <uwsgi.h>
#include <v8.h>
struct uwsgi_v8 {
v8::Persistent<v8::Context> *contexts;
struct uwsgi_string_list *load;
} 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},
{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]));
if (uwsgi_register_signal(uwsgi_signal, *signal_kind, *func, v8_plugin.modifier1)) {
uwsgi_log("[uwsgi-v8] unable to register signal %d\n", uwsgi_signal);
return v8::Undefined();
}
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]));
if (uwsgi_register_rpc(*name, v8_plugin.modifier1, j_argc, *func)) {
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(v8::Persistent<v8::Context> context, char *filename) {
v8::HandleScope handle_scope;
v8::Context::Scope context_scope(context);
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);
}
}
extern "C" int uwsgi_v8_init(){
uwsgi_log("Initializing V8 %s environment... (%d Isolates)\n", v8::V8::GetVersion(), uwsgi.cores);
uv8.contexts = (v8::Persistent<v8::Context> *) uwsgi_malloc( sizeof(v8::Persistent<v8::Context>*) * uwsgi.cores );
return 0;
}
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();
}
static v8::Persistent<v8::Context> uwsgi_v8_new_isolate(int core) {
v8::HandleScope handle_scope;
if (core > 0) {
// create a new isolate
v8::Isolate *isolate = v8::Isolate::New();
// set as the current isolate
v8::Isolate::Scope iscope(isolate);
}
v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
// print alias is always handy
global->Set(v8::String::New("uwsgi_log"), v8::FunctionTemplate::New(uwsgi_v8_api_log));
global->Set(v8::String::New("uwsgi_register_rpc"), v8::FunctionTemplate::New(uwsgi_v8_api_register_rpc));
global->Set(v8::String::New("uwsgi_register_signal"), v8::FunctionTemplate::New(uwsgi_v8_api_register_signal));
// create a new context
v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);
return context;
}
extern "C" void uwsgi_v8_apps() {
if (!uv8.load) return;
int i;
for(i=0;i<uwsgi.cores;i++) {
uv8.contexts[i] = uwsgi_v8_new_isolate(i);
struct uwsgi_string_list *usl = uv8.load;
while(usl) {
uwsgi_v8_load_file(uv8.contexts[i], usl->value);
usl = usl->next;
}
}
}
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) {
v8::HandleScope handle_scope;
v8::Handle<v8::Value> argj[256];
struct wsgi_request *wsgi_req = current_wsgi_req();
v8::Context::Scope context_scope(uv8.contexts[wsgi_req->async_id]);
v8::Persistent<v8::Function> l_func = static_cast<v8::Function*> (func);
uint8_t i;
for(i=0;i<argc;i++) {
argj[i] = v8::String::New(argv[i], argvs[i]);
}
v8::Handle<v8::Value> result = l_func->Call(l_func, 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" int uwsgi_v8_signal_handler(uint8_t sig, void *handler) {
int ret = 0;
v8::HandleScope handle_scope;
struct wsgi_request *wsgi_req = current_wsgi_req();
v8::Context::Scope context_scope(uv8.contexts[wsgi_req->async_id]);
v8::Persistent<v8::Function> l_func = static_cast<v8::Function*> (handler);
v8::Handle<v8::Value> argj[1];
argj[0] = v8::Number::New(sig);
v8::Handle<v8::Value> result = l_func->Call(l_func, 1, argj);
if (result.IsEmpty()) ret = -1;
while(!v8::V8::IdleNotification()) {};
return ret;
}
+1 -1
View File
@@ -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-02'
s.date = '2013-03-30'
s.summary = "uWSGI"
s.description = "The uWSGI server for Ruby/Rack"
s.authors = ["Unbit"]
+57 -14
View File
@@ -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 **);
@@ -1106,6 +1109,14 @@ struct uwsgi_route_condition {
struct uwsgi_route_condition *next;
};
struct uwsgi_route_var {
char *name;
uint16_t name_len;
char *(*func)(struct wsgi_request *, char *, uint16_t, uint16_t *);
int need_free;
struct uwsgi_route_var *next;
};
struct uwsgi_router {
char *name;
int (*func) (struct uwsgi_route *, char *);
@@ -1236,6 +1247,9 @@ struct uwsgi_router {
char *referer;
uint16_t referer_len;
char *cookie;
uint16_t cookie_len;
char *path_info;
uint16_t path_info_len;
int path_info_pos;
@@ -1383,6 +1397,11 @@ struct uwsgi_router {
// internal routing goto instruction
uint32_t route_goto;
struct uwsgi_buffer *cache_it;
struct uwsgi_buffer *cache_it_to;
uint64_t cache_it_expires;
struct uwsgi_buffer *cached_response;
struct msghdr msg;
union {
struct cmsghdr cmsg;
@@ -1490,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)
@@ -1501,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;
@@ -1612,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;
@@ -1619,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
@@ -2068,6 +2098,7 @@ struct uwsgi_server {
struct uwsgi_router *routers;
struct uwsgi_route *routes;
struct uwsgi_route_condition *route_conditions;
struct uwsgi_route_var *route_vars;
#endif
int single_interpreter;
@@ -3225,6 +3256,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 *);
@@ -3585,6 +3618,7 @@ int uwsgi_buffer_insert_chunked(struct uwsgi_buffer *, size_t, size_t);
int uwsgi_buffer_append_chunked(struct uwsgi_buffer *, size_t);
int uwsgi_buffer_append_json(struct uwsgi_buffer *, char *, size_t);
int uwsgi_buffer_set_uh(struct uwsgi_buffer *, uint8_t, uint8_t);
struct uwsgi_buffer *uwsgi_buffer_from_file(char *);
ssize_t uwsgi_buffer_write_simple(struct wsgi_request *, struct uwsgi_buffer *);
@@ -3725,9 +3759,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);
@@ -3867,8 +3904,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 *);
@@ -3904,6 +3941,12 @@ char *uwsgi_deflate(z_stream *, char *, size_t, size_t *);
void uwsgi_crc32(uint32_t *, char *, size_t);
#endif
char *uwsgi_get_cookie(struct wsgi_request *, char *, uint16_t, uint16_t *);
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 *));
void uwsgi_check_emperor(void);
#ifdef UWSGI_AS_SHARED_LIBRARY
int uwsgi_init(int, char **, char **);
+3 -3
View File
@@ -1,6 +1,6 @@
# uWSGI build system
uwsgi_version = '1.9.1'
uwsgi_version = '1.9.4'
import os
import re
@@ -457,11 +457,11 @@ 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',
'core/rpc', 'core/gateway', 'core/loop', 'core/rb_timers', 'core/uwsgi']
'core/rpc', 'core/gateway', 'core/loop', 'core/cookie', 'core/querystring', 'core/rb_timers', 'core/uwsgi']
# add protocols
self.gcc_list.append('proto/base')
self.gcc_list.append('proto/uwsgi')