Compare commits

..
83 Commits
Author SHA1 Message Date
Unbit ec954b8aa7 fixed v8 RPC 2013-11-17 07:02:21 +01:00
Unbit 95d20e9f48 add rack to gemspec 2013-11-17 06:44:16 +01:00
Unbit 165aad8cd0 Merge branch 'master' of ssh://github.com/unbit/uwsgi 2013-11-17 06:42:04 +01:00
Unbit 29c339a3c3 gemspec for 1.9.20 2013-11-17 06:41:46 +01:00
unbit 12afba035b Merge pull request #460 from Kapishin/master
Fix typos
2013-11-16 09:01:33 -08:00
Pavlo Kapyshin eeb203afd4 Fix typos 2013-11-16 17:41:26 +02:00
Unbit 6a18d10c56 fixed typo in total_tx metric 2013-11-13 21:38:56 +01:00
Unbit d1383d7749 added multiplier and adder collector 2013-11-13 19:53:47 +01:00
Unbit 0abbabbe10 added accumulator metrics collector 2013-11-13 19:51:22 +01:00
Roberto De Ioris ea44525c22 fixed zeromq support 2013-11-15 07:48:49 +01:00
Unbit 2396c7cf31 prepare for 1.9.20 2013-11-13 15:14:51 +01:00
Roberto De Ioris 4805a9c219 added chunked input api to psgi 2013-11-14 07:44:13 +01:00
Roberto De Ioris 882cdcc2b6 added --plshell and Perl uwsgi::rpc 2013-11-14 06:24:56 +01:00
unbit 59c8bb51b4 Merge pull request #454 from xiaost-bytedance/master
fixed master hang when gracefully reloading in lazy mode
2013-11-13 08:50:52 -08:00
xiaost 3c2350f5ad fixed master hang when gracefully reloading in lazy mode 2013-11-14 00:33:49 +08:00
Unbit 422e958fe3 added uwsgi over SSL 2013-11-13 04:46:27 +01:00
Unbit 4d9c7809d6 added support for proxy protocol 2013-11-13 03:20:55 +01:00
Unbit 6b3d8ea146 added avg metrics collector 2013-11-13 02:41:47 +01:00
Unbit b5d8538fe8 added oid metric in stats 2013-11-12 17:48:48 +01:00
Unbit 47796b315e fixed stupid bug in websocket perl example 2013-11-12 12:38:22 +01:00
Unbit 222bcd8fdc another fix for default app 2013-11-12 12:22:54 +01:00
Unbit f92b800a7c fixed default app usage 2013-11-12 12:18:31 +01:00
Unbit dec2b234f8 fixed no default app 2013-11-12 12:14:15 +01:00
Unbit 3dbd7e3115 fixed comments in websockets_chat.pl 2013-11-12 08:50:50 +01:00
Unbit 09d8747918 added tests/websockets_chat.pl 2013-11-12 08:48:49 +01:00
Unbit fa78fd915b force https to on when --https-socket is in place 2013-11-12 05:59:10 +01:00
Unbit db56141485 completed --https-socket 2013-11-12 05:54:47 +01:00
Unbit 7685af4652 pluginized the socket protocols 2013-11-12 05:44:52 +01:00
unbit 21cb62db6c Merge pull request #452 from Kapishin/master
Fix typos
2013-11-11 20:15:07 -08:00
Pavlo Kapyshin c62aa8e7ed Fix typos 2013-11-11 23:05:30 +02:00
unbit 4765965d8e Merge pull request #451 from xrmx/coverity1111
build/coverity: remove broken erlang plugin
2013-11-11 10:14:08 -08:00
Riccardo Magliocchetti 556feaef2c build/coverity: remove broken erlang plugin 2013-11-11 19:11:20 +01:00
Unbit 799b8a22e0 improved content_type detection for rpc-path_info bridge 2013-11-11 15:50:11 +01:00
Unbit 2336580164 more rpc fixes 2013-11-11 15:09:13 +01:00
Unbit ca4f30c003 fixed rpc 64bit networking extension 2013-11-11 14:52:22 +01:00
Unbit d7d0a71d87 completed rpc 64bit network client 2013-11-11 14:42:28 +01:00
Unbit 44b92f1578 implemented 64bit extension for rpc protocol 2013-11-11 14:08:26 +01:00
Unbit abed95362f another series of rpc 64bit fixes 2013-11-11 13:46:00 +01:00
Unbit 72ecc217f7 perl passes the 64bit rpc test 2013-11-11 13:43:21 +01:00
Unbit 1405d01d50 pypy passes 64bit rpc local test 2013-11-11 13:24:08 +01:00
Unbit def65c4793 fixed python, perl and ruby rpc 64bit 2013-11-11 13:06:16 +01:00
Unbit 26386909de first attempt of moving rpc output from 16 to 64 bit 2013-11-11 13:00:20 +01:00
Unbit 2d4e04059a uwsgi.go low-level optimizations and implementation of uwsgi.CacheGet 2013-11-11 12:18:43 +01:00
unbit ac557739c2 allows monolithic gccgo to run on 32bit 2013-11-11 11:00:33 +01:00
Unbit 73bfc20ba1 added connection_fd to rack plugin 2013-11-11 09:12:52 +01:00
Unbit 6d5ae96d50 hack for adding an empty DEBUG section to the uwsgi core binary 2013-11-11 09:04:48 +01:00
Unbit 20b5b7b0dc added support for uwsgi::connection_fd and psgix.io 2013-11-11 08:22:01 +01:00
Unbit 82c5afd0c7 forgot PROFILE in Makefile 2013-11-11 06:12:32 +01:00
Unbit ec14f5b0fe Merge branch 'master' of ssh://github.com/unbit/uwsgi 2013-11-11 05:45:06 +01:00
unbit d93bdcb7b4 Merge pull request #450 from awentzonline/patch-1
Fixed spelling of error message in pyloader.c
2013-11-10 20:55:22 -08:00
Unbit b68ffc842d prepare for gccgo docs 2013-11-11 05:44:51 +01:00
Adam Wentz 0326c1d508 Fixed spelling of error message in pyloader.c 2013-11-10 14:08:41 -06:00
Unbit 42f45bfbf9 erlang plugin is broken 2013-11-10 08:27:44 +01:00
Unbit d018d3af99 pyerl plugin is broken 2013-11-10 08:27:23 +01:00
Unbit 42afc476d7 improved gccgo monolithic build 2013-11-10 08:26:14 +01:00
Unbit b5037d3f0f sanitize gccgo environment 2013-11-10 07:54:13 +01:00
Unbit 065dd7cfff return after grace_them_all 2013-11-10 06:49:02 +01:00
unbit 7909e092b5 Merge pull request #449 from xrmx/coverity0911-2
More coverity fixes
2013-11-09 21:52:49 -08:00
Unbit 9da53f5fd4 improved gccgo signal handling and added --timer and --rbtimer commodity options 2013-11-10 06:42:46 +01:00
Unbit 025cb7744e implemented goroutines timeout 2013-11-10 05:55:54 +01:00
Unbit e48a3ff1b7 added %k magic vars (number of cpu cores) 2013-11-10 04:51:25 +01:00
Unbit 2be371003c added %t and %T magic vars 2013-11-10 04:36:14 +01:00
Unbit 60d940e301 added simple math and concat to placeholders 2013-11-10 04:27:26 +01:00
Unbit 96c56cd8d5 added simple math routing actions 2013-11-10 03:30:33 +01:00
Unbit 4184619f7b removed snapshotting old feature 2013-11-10 02:59:15 +01:00
Unbit 50a8ec8a19 removed matheval flag, added generic matheval plugin and startin 1.9.20 development cycle 2013-11-10 02:53:08 +01:00
Unbit 79c702278a fixed async queue full condition in goroutine mode 2013-11-10 02:42:00 +01:00
Unbit 8fc41a4c85 remove useless gccgo code 2013-11-09 18:45:57 +01:00
Unbit 9c6455252d avoid GC to destroy go request env 2013-11-09 18:22:36 +01:00
Unbit 83e41844f3 first hardcore commit for supporting gccgo coroutines 2013-11-09 17:28:06 +01:00
Riccardo Magliocchetti 2cc17d6b11 core/logging: if we cannot reopen the log exit
This fixes passing negative fds to write and lseek.

Reported by Coverity as CID #1100807.
2013-11-09 16:15:49 +01:00
Riccardo Magliocchetti 14057b72c8 core: fix memory leak
Reported by Coverity as CID #1100813.
2013-11-09 16:08:47 +01:00
Riccardo Magliocchetti faf72b6a77 plugins/corerouter: fix memory leak
While at it reindent the code

Reported by Coverity as CID #1100818.
2013-11-09 16:05:41 +01:00
Riccardo Magliocchetti 963afa5174 core: fix memory leak
Reported by Coverity as CID #1100819
2013-11-09 15:46:05 +01:00
Unbit ce8ff8c45f fixed metric bug discovered by coverity 2013-11-09 15:15:32 +01:00
Riccardo Magliocchetti 5ae742e8e1 plugins/xslt: fail early if content_type is null
Fixes null pointer dereference.

Reported by Coverity as CID #1125161
2013-11-09 15:11:35 +01:00
Riccardo Magliocchetti 60f6572985 plugins/xslt: fix memory leak
Reported by Coverity as CID #1125168
2013-11-09 15:06:46 +01:00
Riccardo Magliocchetti 4ea34c63d2 plugins/servlet: Check uwsgi_jvm_exception return value
Reported vy Coverity as CID #1125169.
2013-11-09 15:04:47 +01:00
Riccardo Magliocchetti 5699d21aa7 metrics: add missing exit on error path
Fixed null pointer dereference.

Reported by Coverity as CID #1127337
2013-11-09 15:00:58 +01:00
Unbit dda8d25495 try to address EAGAIn body read problem 2013-11-09 13:17:17 +01:00
Unbit d4f690322c moved go to broken plugins 2013-11-09 13:01:28 +01:00
Unbit 4f2f30d1e5 improved gccgo plugin 2013-11-09 12:55:52 +01:00
Unbit d3b28e7956 more plugins for coveriti, fixed gccgo 2013-11-09 12:20:32 +01:00
77 changed files with 2048 additions and 595 deletions
+6
View File
@@ -8,3 +8,9 @@ clean:
check:
$(PYTHON) uwsgiconfig.py --check
plugin.%:
$(PYTHON) uwsgiconfig.py --plugin plugins/$* $(PROFILE)
%:
$(PYTHON) uwsgiconfig.py --build $@
+1 -1
View File
@@ -1,3 +1,3 @@
[uwsgi]
main_plugin = python,gevent,psgi,lua,php,rack,jvm,jwsgi,ring,mono,transformation_toupper,coroae,v8,cgi,xslt,webdav,ssi,ldap,gccgo,rados
main_plugin = python,gevent,psgi,lua,php,rack,jvm,jwsgi,ring,mono,transformation_toupper,coroae,v8,cgi,xslt,webdav,ssi,ldap,gccgo,rados,pypy
inherit = base
-1
View File
@@ -6,7 +6,6 @@ zeromq = auto
ssl = auto
pcre = auto
routing = auto
matheval = auto
debug = false
unbit = false
xml_implementation = libxml2
+1 -2
View File
@@ -1,4 +1,3 @@
[uwsgi]
# pypy,go
main_plugin = erlang,psgi,rack,lua,python,gevent,php,cgi,pyerl,glusterfs,pty,xslt,msgpack,geoip,v8,pam,ldap,mono,jvm,ring,jwsgi
main_plugin = psgi,rack,lua,python,gevent,php,cgi,glusterfs,pty,xslt,msgpack,geoip,v8,pam,ldap,mono,jvm,ring,jwsgi,servlet,rados,coroae,pypy,gccgo
inherit = base
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = gccgo
inherit = base
-1
View File
@@ -1,4 +1,3 @@
[uwsgi]
main_plugin = glusterfs
inherit = base
matheval = false
-5
View File
@@ -1,5 +0,0 @@
[uwsgi]
main_plugin = go
inherit = base
bin_name = libuwsgi.so
as_shared_library = true
-1
View File
@@ -6,7 +6,6 @@ zeromq = false
ssl = false
pcre = false
routing = false
matheval = false
debug = false
unbit = false
xml_implementation = none
+5 -5
View File
@@ -4,18 +4,18 @@ extern struct uwsgi_server uwsgi;
/*
This is a general purpose async loop engine (it expects a coroutine based approach)
This is a general-purpose async loop engine (it expects a coroutine-based approach)
You can see it as an hub holding the following structures:
1) the runqueue, cores ready to be run are appended in this list
1) the runqueue, cores ready to be run are appended to this list
2) the fd list, this is a list of monitored file descriptors, a core can wait for all the file descriptors it needs
3) the timeout value, if set the current core will timeout aftert he specified number of seconds (unless an event cancel it)
3) the timeout value, if set, the current core will timeout after the specified number of seconds (unless an event cancels it)
IMPORTANT: this is not a callback based engine !!!
IMPORTANT: this is not a callback-based engine !!!
*/
@@ -159,7 +159,7 @@ static void async_expire_timeouts(uint64_t now) {
wsgi_req = (struct wsgi_request *) urbt->data;
// timeout expired
wsgi_req->async_timed_out = 1;
// reset teh request
// reset the request
async_reset_request(wsgi_req);
// push it in the runqueue
runqueue_push(wsgi_req);
+3 -3
View File
@@ -762,7 +762,7 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
}
// mark used blocks;
uint64_t needed_blocks = cache_mark_blocks(uc, uci->first_block, vallen);
// optimize teh scan
// optimize the scan
if (uc->blocks_bitmap_pos + (needed_blocks+1) > uc->blocks) {
uc->blocks_bitmap_pos = 0;
}
@@ -1432,7 +1432,7 @@ static int cache_magic_send_and_manage(int fd, struct uwsgi_buffer *ub, char *st
// ok now wait for the response, using the same buffer of the request
// NOTE: after using a uwsgi_buffer in that way we basically destroy (even if we can safely free it)
size_t rlen = ub->pos;
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, timeout)) return -1;
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, timeout, NULL, NULL)) return -1;
// try to fix the buffer to maintain size info
ub->pos = rlen;
@@ -1867,7 +1867,7 @@ void uwsgi_cache_sync_from_nodes(struct uwsgi_cache *uc) {
}
size_t rlen = ub->pos;
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], NULL, NULL)) {
uwsgi_buffer_destroy(ub);
uwsgi_log("[cache-sync] unable to read from the cache server\n");
close(fd);
+165
View File
@@ -633,3 +633,168 @@ clear:
}
char *uwsgi_get_exported_opt(char *key) {
int i;
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
if (!strcmp(uwsgi.exported_opts[i]->key, key)) {
return uwsgi.exported_opts[i]->value;
}
}
return NULL;
}
char *uwsgi_get_optname_by_index(int index) {
struct uwsgi_option *op = uwsgi.options;
while (op->name) {
if (op->shortcut == index) {
return op->name;
}
op++;
}
return NULL;
}
/*
this works as a pipeline
processes = 2
cpu_cores = 8
foobar = %(processes cpu_cores + 2)
translate as:
step1 = proceses cpu_cores = 2 8 = 28 (string concatenation)
step1 + = step1_apply_func_plus (func token)
step1_apply_func_plus 2 = 28 + 2 = 30 (math)
*/
char *uwsgi_manage_placeholder(char *key) {
enum {
concat = 0,
sum,
sub,
mul,
div,
} state;
state = concat;
char *current_value = NULL;
char *space = strchr(key, ' ');
if (!space) {
return uwsgi_get_exported_opt(key);
}
// let's start the heavy metal here
char *tmp_value = uwsgi_str(key);
char *p, *ctx = NULL;
uwsgi_foreach_token(tmp_value, " ", p, ctx) {
char *value = NULL;
if (is_a_number(p)) {
value = uwsgi_str(p);
}
else if (!strcmp(p, "+")) {
state = sum;
continue;
}
else if (!strcmp(p, "-")) {
state = sub;
continue;
}
else if (!strcmp(p, "*")) {
state = mul;
continue;
}
else if (!strcmp(p, "/")) {
state = div;
continue;
}
else if (!strcmp(p, "++")) {
if (current_value) {
int64_t tmp_value = strtoll(current_value, NULL, 10);
free(current_value);
current_value = uwsgi_64bit2str(tmp_value+1);
}
state = concat;
continue;
}
else if (!strcmp(p, "--")) {
if (current_value) {
int64_t tmp_value = strtoll(current_value, NULL, 10);
free(current_value);
current_value = uwsgi_64bit2str(tmp_value-1);
}
state = concat;
continue;
}
// find the option
else {
char *ov = uwsgi_get_exported_opt(p);
if (!ov) ov = "";
value = uwsgi_str(ov);
}
int64_t arg1n = 0, arg2n = 0;
char *arg1 = "", *arg2 = "";
switch(state) {
case concat:
if (current_value) arg1 = current_value;
if (value) arg2 = value;
char *ret = uwsgi_concat2(arg1, arg2);
if (current_value) free(current_value);
current_value = ret;
break;
case sum:
if (current_value) arg1n = strtoll(current_value, NULL, 10);
if (value) arg2n = strtoll(value, NULL, 10);
if (current_value) free(current_value);
current_value = uwsgi_64bit2str(arg1n + arg2n);
break;
case sub:
if (current_value) arg1n = strtoll(current_value, NULL, 10);
if (value) arg2n = strtoll(value, NULL, 10);
if (current_value) free(current_value);
current_value = uwsgi_64bit2str(arg1n - arg2n);
break;
case mul:
if (current_value) arg1n = strtoll(current_value, NULL, 10);
if (value) arg2n = strtoll(value, NULL, 10);
if (current_value) free(current_value);
current_value = uwsgi_64bit2str(arg1n * arg2n);
break;
case div:
if (current_value) arg1n = strtoll(current_value, NULL, 10);
if (value) arg2n = strtoll(value, NULL, 10);
if (current_value) free(current_value);
// avoid division by zero
if (arg2n == 0) {
current_value = uwsgi_64bit2str(0);
}
else {
current_value = uwsgi_64bit2str(arg1n / arg2n);
}
break;
default:
break;
}
// over engineering
if (value)
free(value);
// reset state to concat
state = concat;
}
return current_value;
}
-6
View File
@@ -346,7 +346,6 @@ void uwsgi_setup_workers() {
uwsgi.workers[i].signal_pipe[0] = -1;
uwsgi.workers[i].signal_pipe[1] = -1;
snprintf(uwsgi.workers[i].name, 0xff, "uWSGI worker %d", i);
snprintf(uwsgi.workers[i].snapshot_name, 0xff, "uWSGI snapshot %d", i);
}
uint64_t total_memory = (sizeof(struct uwsgi_app) * uwsgi.max_apps) + (sizeof(struct uwsgi_core) * uwsgi.cores) + (sizeof(void *) * uwsgi.max_apps * uwsgi.cores) + (uwsgi.buffer_size * uwsgi.cores) + (sizeof(struct iovec) * uwsgi.vec_size * uwsgi.cores);
@@ -448,11 +447,6 @@ void sanitize_args() {
}
}
if (uwsgi.auto_snapshot > 0 && uwsgi.auto_snapshot > uwsgi.numproc) {
uwsgi_log("invalid auto-snapshot value: must be <= than processes\n");
exit(1);
}
if (uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME] > 0 && uwsgi.shared->options[UWSGI_OPTION_MIN_WORKER_LIFETIME] >= uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME]) {
uwsgi_log("invalid min-worker-lifetime value (%d), must be lower than max-worker-lifetime (%d)\n",
uwsgi.shared->options[UWSGI_OPTION_MIN_WORKER_LIFETIME], uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME]);
+6 -2
View File
@@ -943,12 +943,12 @@ int uwsgi_read_whole_true_nb(int fd, char *buf, size_t remains, int timeout) {
}
/*
this is a pretty magic function used for read a full uwsgi response
this is a pretty magic function used for reading a full uwsgi response
it is true non blocking, so you can use it in request plugins
buffer is expected to be at least 4 bytes, rlen is a get/set value
*/
int uwsgi_read_with_realloc(int fd, char **buffer, size_t *rlen, int timeout) {
int uwsgi_read_with_realloc(int fd, char **buffer, size_t *rlen, int timeout, uint8_t *modifier1, uint8_t *modifier2) {
if (*rlen < 4) return -1;
char *buf = *buffer;
int ret;
@@ -979,6 +979,10 @@ readok:
struct uwsgi_header *uh = (struct uwsgi_header *) buf;
uint16_t pktsize = uh->pktsize;
if (modifier1)
*modifier1 = uh->modifier1;
if (modifier2)
*modifier2 = uh->modifier2;
if (pktsize > *rlen) {
char *tmp_buf = realloc(buf, pktsize);
+1
View File
@@ -575,6 +575,7 @@ void uwsgi_log_reopen() {
if (uwsgi.original_log_fd < 0) {
uwsgi_error_open(uwsgi.logfile);
grace_them_all(0);
return;
}
ret = snprintf(message, 1024, "[%d] %s reopened.\n", (int) uwsgi_now(), uwsgi.logfile);
if (ret > 0) {
+22 -54
View File
@@ -28,17 +28,6 @@ void uwsgi_update_load_counters() {
}
void uwsgi_restore_auto_snapshot(int signum) {
if (uwsgi.workers[1].snapshot > 0) {
uwsgi.restore_snapshot = 1;
}
else {
uwsgi_log("[WARNING] no snapshot available\n");
}
}
void uwsgi_block_signal(int signum) {
sigset_t smask;
sigemptyset(&smask);
@@ -104,31 +93,6 @@ void uwsgi_master_manage_udp(int udp_fd) {
}
}
void uwsgi_master_restore_snapshot() {
int i, waitpid_status;
uwsgi_log("[snapshot] restoring workers...\n");
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].pid == 0)
continue;
kill(uwsgi.workers[i].pid, SIGKILL);
if (waitpid(uwsgi.workers[i].pid, &waitpid_status, 0) < 0) {
uwsgi_error("waitpid()");
}
if (uwsgi.auto_snapshot > 0 && i > uwsgi.auto_snapshot) {
uwsgi.workers[i].pid = 0;
uwsgi.workers[i].snapshot = 0;
}
else {
uwsgi.workers[i].pid = uwsgi.workers[i].snapshot;
uwsgi.workers[i].snapshot = 0;
kill(uwsgi.workers[i].pid, SIGURG);
uwsgi_log("Restored uWSGI worker %d (pid: %d)\n", i, (int) uwsgi.workers[i].pid);
}
}
uwsgi.restore_snapshot = 0;
}
void suspend_resume_them_all(int signum) {
int i;
@@ -326,9 +290,6 @@ int master_loop(char **argv, char **environ) {
}
uwsgi_unix_signal(SIGINT, kill_them_all);
uwsgi_unix_signal(SIGUSR1, stats);
if (uwsgi.auto_snapshot) {
uwsgi_unix_signal(SIGURG, uwsgi_restore_auto_snapshot);
}
atexit(uwsgi_master_cleanup_hooks);
@@ -514,6 +475,28 @@ int master_loop(char **argv, char **environ) {
// fsmon
uwsgi_fsmon_setup();
uwsgi_foreach(usl, uwsgi.signal_timers) {
char *space = strchr(usl->value, ' ');
if (!space) {
uwsgi_log("invalid signal timer syntax, must be: <signal> <seconds>\n");
exit(1);
}
*space = 0;
uwsgi_add_timer(atoi(usl->value), atoi(space+1));
*space = ' ';
}
uwsgi_foreach(usl, uwsgi.rb_signal_timers) {
char *space = strchr(usl->value, ' ');
if (!space) {
uwsgi_log("invalid redblack signal timer syntax, must be: <signal> <seconds>\n");
exit(1);
}
*space = 0;
uwsgi_signal_add_rb_timer(atoi(usl->value), atoi(space+1), 0);
*space = ' ';
}
// setup cheaper algos (can be stacked)
uwsgi.cheaper_algo = uwsgi_cheaper_algo_spare;
if (uwsgi.requested_cheaper_algo) {
@@ -567,21 +550,6 @@ int master_loop(char **argv, char **environ) {
// check for daemons (smart and dumb)
uwsgi_daemons_smart_check();
if (uwsgi.respawn_snapshots) {
for (i = 1; i <= uwsgi.respawn_snapshots; i++) {
if (uwsgi_respawn_worker(i))
return 0;
}
uwsgi.respawn_snapshots = 0;
}
if (uwsgi.restore_snapshot) {
uwsgi_master_restore_snapshot();
continue;
}
// cheaper management
if (uwsgi.cheaper && !uwsgi.status.is_cheap && !uwsgi_instance_is_reloading && !uwsgi_instance_is_dying && !uwsgi.workers[0].suspended) {
if (!uwsgi_calc_cheaper())
+1
View File
@@ -118,6 +118,7 @@ int uwsgi_master_manage_events(int interesting_fd) {
reap_them_all(0);
uwsgi_unblock_signal(SIGTERM);
}
if (usl->custom2 > 8) free(tmp);
return 0;
}
usl = usl->next;
+5
View File
@@ -903,6 +903,11 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
goto end;
}
if (uwsgi_stats_keyval_comma(us, "oid", um->oid ? um->oid : "")) {
uwsgi_rwunlock(uwsgi.metrics_lock);
goto end;
}
if (uwsgi_stats_keyslong(us, "value", (long long) um_val)) {
uwsgi_rwunlock(uwsgi.metrics_lock);
goto end;
+59 -2
View File
@@ -225,7 +225,7 @@ struct uwsgi_metric *uwsgi_register_metric_do(char *name, char *oid, uint8_t val
}
metric = uwsgi_calloc(sizeof(struct uwsgi_metric));
// always make a copy of the name (se we can use stack for building strings)
// always make a copy of the name (so we can use stack for building strings)
metric->name = uwsgi_str(name);
metric->name_len = strlen(metric->name);
@@ -752,7 +752,7 @@ void uwsgi_setup_metrics() {
uwsgi_metric_name("worker.%d.avg_response_time", i) ; uwsgi_metric_oid("3.%d.8", i);
uwsgi_register_metric(buf, buf2, UWSGI_METRIC_GAUGE, "ptr", &uwsgi.workers[i].avg_response_time, 0, NULL);
uwsgi_metric_name("worker.%d.total_rx", i) ; uwsgi_metric_oid("3.%d.9", i);
uwsgi_metric_name("worker.%d.total_tx", i) ; uwsgi_metric_oid("3.%d.9", i);
struct uwsgi_metric *tx = uwsgi_register_metric(buf, buf2, UWSGI_METRIC_COUNTER, "ptr", &uwsgi.workers[i].tx, 0, NULL);
uwsgi_metric_add_child(total_tx, tx);
@@ -872,6 +872,7 @@ void uwsgi_setup_metrics() {
struct uwsgi_metric *um = uwsgi_metric_find_by_name(m_key);
if (!um) {
uwsgi_log("unable to find metric %s\n", m_key);
exit(1);
}
struct uwsgi_metric_threshold *umt = uwsgi_calloc(sizeof(struct uwsgi_metric_threshold));
@@ -969,6 +970,58 @@ static int64_t uwsgi_metric_collector_sum(struct uwsgi_metric *um) {
return total;
}
static int64_t uwsgi_metric_collector_accumulator(struct uwsgi_metric *um) {
int64_t total = *um->value;
struct uwsgi_metric_child *umc = um->children;
while(umc) {
struct uwsgi_metric *c = umc->um;
total += *c->value;
umc = umc->next;
}
return total;
}
static int64_t uwsgi_metric_collector_multiplier(struct uwsgi_metric *um) {
int64_t total = 0;
struct uwsgi_metric_child *umc = um->children;
while(umc) {
struct uwsgi_metric *c = umc->um;
total += *c->value;
umc = umc->next;
}
return total * um->arg1n;
}
static int64_t uwsgi_metric_collector_adder(struct uwsgi_metric *um) {
int64_t total = 0;
struct uwsgi_metric_child *umc = um->children;
while(umc) {
struct uwsgi_metric *c = umc->um;
total += *c->value;
umc = umc->next;
}
return total + um->arg1n;
}
static int64_t uwsgi_metric_collector_avg(struct uwsgi_metric *um) {
int64_t total = 0;
int64_t count = 0;
struct uwsgi_metric_child *umc = um->children;
while(umc) {
struct uwsgi_metric *c = umc->um;
total += *c->value;
count++;
umc = umc->next;
}
if (count == 0) return 0;
return total/count;
}
static int64_t uwsgi_metric_collector_func(struct uwsgi_metric *um) {
if (!um->arg1) return 0;
int64_t (*func)(struct uwsgi_metric *) = (int64_t (*)(struct uwsgi_metric *)) um->custom;
@@ -984,5 +1037,9 @@ void uwsgi_metrics_collectors_setup() {
uwsgi_register_metric_collector("ptr", uwsgi_metric_collector_ptr);
uwsgi_register_metric_collector("file", uwsgi_metric_collector_file);
uwsgi_register_metric_collector("sum", uwsgi_metric_collector_sum);
uwsgi_register_metric_collector("accumulator", uwsgi_metric_collector_accumulator);
uwsgi_register_metric_collector("adder", uwsgi_metric_collector_adder);
uwsgi_register_metric_collector("multiplier", uwsgi_metric_collector_multiplier);
uwsgi_register_metric_collector("avg", uwsgi_metric_collector_avg);
uwsgi_register_metric_collector("func", uwsgi_metric_collector_func);
}
+1 -1
View File
@@ -389,7 +389,7 @@ wait:
remains -= len;
*rlen += len;
continue;
}else if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
}else if (len < 0 && (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS)) {
goto wait;
}
*rlen = -1;
+87 -46
View File
@@ -582,6 +582,88 @@ static int uwsgi_router_break(struct uwsgi_route *ur, char *arg) {
return 0;
}
// simple math router
static int uwsgi_router_simple_math_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
uint16_t var_vallen = 0;
char *var_value = uwsgi_get_var(wsgi_req, ur->data, ur->data_len, &var_vallen);
if (!var_value) return UWSGI_ROUTE_BREAK;
int64_t base_value = uwsgi_str_num(var_value, var_vallen);
int64_t value = 1;
if (ur->data2_len) {
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data2, ur->data2_len);
if (!ub) return UWSGI_ROUTE_BREAK;
value = uwsgi_str_num(ub->buf, ub->pos);
uwsgi_buffer_destroy(ub);
}
char out[sizeof(UMAX64_STR)+1];
int64_t total = 0;
switch(ur->custom) {
// -
case 1:
total = base_value - value;
break;
// *
case 2:
total = base_value * value;
break;
// /
case 3:
if (value == 0) total = 0;
else {
total = base_value/value;
}
break;
default:
total = base_value + value;
break;
}
int ret = uwsgi_long2str2n(total, out, sizeof(UMAX64_STR)+1);
if (ret <= 0) return UWSGI_ROUTE_BREAK;
if (!uwsgi_req_append(wsgi_req, ur->data, ur->data_len, out, ret)) {
return UWSGI_ROUTE_BREAK;
}
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_simple_math_plus(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_simple_math_func;
char *comma = strchr(arg, ',');
if (comma) {
ur->data = arg;
ur->data_len = comma - arg;
ur->data2 = comma+1;
ur->data2_len = strlen(ur->data);
}
else {
ur->data = arg;
ur->data_len = strlen(arg);
}
return 0;
}
static int uwsgi_router_simple_math_minus(struct uwsgi_route *ur, char *arg) {
ur->custom = 1;
return uwsgi_router_simple_math_plus(ur, arg);
}
static int uwsgi_router_simple_math_multiply(struct uwsgi_route *ur, char *arg) {
ur->custom = 2;
return uwsgi_router_simple_math_plus(ur, arg);
}
static int uwsgi_router_simple_math_divide(struct uwsgi_route *ur, char *arg) {
ur->custom = 2;
return uwsgi_router_simple_math_plus(ur, arg);
}
// harakiri router
static int uwsgi_router_harakiri_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
@@ -1639,48 +1721,6 @@ static char *uwsgi_route_var_hex(struct wsgi_request *wsgi_req, char *key, uint1
return ret;
}
#ifdef UWSGI_MATHEVAL
static char *uwsgi_route_var_math(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
char *ret = NULL;
// avoid crash
if (!wsgi_req->var_cnt) return NULL;
// we make a bit of fun here, we do a copy of the vars buffer (+1 byte for final zero) and zeor-pad all of the strings
char *vars_buf = uwsgi_malloc(wsgi_req->uh->pktsize + keylen + 1);
char **names = uwsgi_malloc(sizeof(char *) * (wsgi_req->var_cnt/2));
double *values = uwsgi_calloc(sizeof(double) * (wsgi_req->var_cnt/2));
int i,j = 0;
char *ptr = vars_buf;
for (i = wsgi_req->var_cnt-1; i > 0; i -= 2) {
memcpy(ptr, wsgi_req->hvec[i-1].iov_base, wsgi_req->hvec[i-1].iov_len);
names[j] = ptr;
ptr += wsgi_req->hvec[i-1].iov_len;
*ptr++=0;
char *num = ptr;
memcpy(ptr, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
ptr += wsgi_req->hvec[i].iov_len;
*ptr++=0;
values[j] = strtod(num, NULL);
j++;
}
char *expr = ptr;
memcpy(ptr, key, keylen); ptr += keylen;
*ptr++=0;
void *e = evaluator_create(expr);
if (!e) goto end;
double n = evaluator_evaluate(e, j, names, values);
evaluator_destroy(e);
ret = uwsgi_num2str((int)n);
*vallen = strlen(ret);
end:
free(vars_buf);
free(names);
free(values);
return ret;
}
#endif
// register embedded routers
void uwsgi_register_embedded_routers() {
uwsgi_register_router("continue", uwsgi_router_continue);
@@ -1713,6 +1753,11 @@ void uwsgi_register_embedded_routers() {
uwsgi_register_router("setprocname", uwsgi_router_setprocname);
uwsgi_register_router("alarm", uwsgi_router_alarm);
uwsgi_register_router("+", uwsgi_router_simple_math_plus);
uwsgi_register_router("-", uwsgi_router_simple_math_minus);
uwsgi_register_router("*", uwsgi_router_simple_math_multiply);
uwsgi_register_router("/", uwsgi_router_simple_math_divide);
uwsgi_register_router("flush", uwsgi_router_flush);
uwsgi_register_router("fixcl", uwsgi_router_fixcl);
@@ -1756,10 +1801,6 @@ void uwsgi_register_embedded_routers() {
urv->need_free = 1;
urv = uwsgi_register_route_var("httptime", uwsgi_route_var_httptime);
urv->need_free = 1;
#ifdef UWSGI_MATHEVAL
urv = uwsgi_register_route_var("math", uwsgi_route_var_math);
urv->need_free = 1;
#endif
urv = uwsgi_register_route_var("base64", uwsgi_route_var_base64);
urv->need_free = 1;
+36 -8
View File
@@ -59,11 +59,11 @@ already:
return ret;
}
uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], char *output) {
uint64_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], char **output) {
struct uwsgi_rpc *urpc = NULL;
uint64_t i;
uint16_t ret = 0;
uint64_t ret = 0;
int pos = (uwsgi.mywid * uwsgi.rpc_max);
@@ -85,8 +85,15 @@ uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], cha
return ret;
}
static void rpc_context_hook(char *key, uint16_t kl, char *value, uint16_t vl, void *data) {
size_t *r = (size_t *) data;
char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t argvs[], uint16_t * len) {
if (!uwsgi_strncmp(key, kl, "CONTENT_LENGTH", 14)) {
*r = uwsgi_str_num(value, vl);
}
}
char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t argvs[], uint64_t * len) {
uint8_t i;
uint16_t ulen;
@@ -97,9 +104,10 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
if (node == NULL || !strcmp(node, "")) {
// allocate the whole buffer
buffer = uwsgi_malloc(UMAX16);
*len = uwsgi_rpc(func, argc, argv, argvs, buffer);
return buffer;
*len = uwsgi_rpc(func, argc, argv, argvs, &buffer);
if (*buffer)
return buffer;
return NULL;
}
@@ -147,17 +155,37 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
bufptr += ulen;
}
// ok the reuqest is ready, let's send it in non blocking way
// ok the request is ready, let's send it in non blocking way
if (uwsgi_write_true_nb(fd, buffer, buffer_size+4, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
goto error;
}
// ok time to wait for the response in non blocking way
size_t rlen = buffer_size+4;
if (uwsgi_read_with_realloc(fd, &buffer, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
uint8_t modifier2 = 0;
if (uwsgi_read_with_realloc(fd, &buffer, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], NULL, &modifier2)) {
goto error;
}
// 64bit response ?
if (modifier2 == 5) {
size_t content_len = 0;
if (uwsgi_hooked_parse(buffer, rlen, rpc_context_hook, &content_len )) goto error;
if (content_len > rlen) {
char *tmp_buf = realloc(buffer, content_len);
if (!tmp_buf) goto error;
buffer = tmp_buf;
}
rlen = content_len;
// read the raw value from the socket
if (uwsgi_read_whole_true_nb(fd, buffer, rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
goto error;
}
}
close(fd);
*len = rlen;
if (*len == 0) {
+1 -1
View File
@@ -209,7 +209,7 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
oid_part[0] = *ptr;
// old style SNMP metrics
// old-style SNMP metrics
if (oid_part[0] == 1 || oid_part[0] == 2) {
ptr++;
+57 -119
View File
@@ -6,6 +6,22 @@ static int connect_to_unix(char *, int, int);
static int connect_to_tcp(char *, int, int, int);
static int connect_to_udp(char *, int);
void uwsgi_socket_setup_protocol(struct uwsgi_socket *uwsgi_sock, char *protocol) {
if (!protocol) protocol = "uwsgi";
struct uwsgi_protocol *up = uwsgi.protocols;
while(up) {
if (!strcmp(protocol, up->name)) {
up->func(uwsgi_sock);
return;
}
up = up->next;
}
uwsgi_log("unable to find protocol %s\n", protocol);
exit(1);
}
static int uwsgi_socket_strcmp(char *sock1, char *sock2) {
size_t sock1_len = strlen(sock1);
size_t sock2_len = strlen(sock2);
@@ -1853,125 +1869,8 @@ void uwsgi_set_sockets_protocols() {
setup_proto:
if (!requested_protocol) {
requested_protocol = uwsgi.protocol;
}
if (requested_protocol && !strcmp("http", requested_protocol)) {
uwsgi_sock->proto = uwsgi_proto_http_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
uwsgi_sock->proto_write = uwsgi_proto_base_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
if (uwsgi.offload_threads > 0)
uwsgi_sock->can_offload = 1;
}
else if (requested_protocol && !strcmp("raw", requested_protocol)) {
uwsgi_sock->proto = uwsgi_proto_raw_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
uwsgi_sock->proto_write = uwsgi_proto_base_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
if (uwsgi.offload_threads > 0)
uwsgi_sock->can_offload = 1;
}
else if (requested_protocol && (!strcmp("fastcgi", requested_protocol) || !strcmp("fcgi", requested_protocol))) {
uwsgi_sock->proto = uwsgi_proto_fastcgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_cgi_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_fastcgi_read_body;
uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_fastcgi_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close;
}
else if (requested_protocol && (!strcmp("fastcgi-nph", requested_protocol) || !strcmp("fcgi-nph", requested_protocol))) {
uwsgi_sock->proto = uwsgi_proto_fastcgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_fastcgi_read_body;
uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_fastcgi_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close;
}
else if (requested_protocol && !strcmp("scgi", requested_protocol)) {
uwsgi_sock->proto = uwsgi_proto_scgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_cgi_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
uwsgi_sock->proto_write = uwsgi_proto_base_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
}
else if (requested_protocol && !strcmp("scgi-nph", requested_protocol)) {
uwsgi_sock->proto = uwsgi_proto_scgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
uwsgi_sock->proto_write = uwsgi_proto_base_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
}
#ifdef UWSGI_ZEROMQ
else if (requested_protocol && !strcmp("zmq", requested_protocol)) {
uwsgi.zeromq = 1;
}
#endif
else if (requested_protocol && !strcmp("puwsgi", requested_protocol)) {
uwsgi_sock->proto = uwsgi_proto_puwsgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_puwsgi_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_noop_read_body;
uwsgi_sock->proto_write = uwsgi_proto_base_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_puwsgi_close;
uwsgi_sock->fd_threads = uwsgi_malloc(sizeof(int) * uwsgi.cores);
memset(uwsgi_sock->fd_threads, -1, sizeof(int) * uwsgi.cores);
uwsgi_sock->retry = uwsgi_calloc(sizeof(int) * uwsgi.cores);
uwsgi.is_et = 1;
}
else {
uwsgi_sock->proto = uwsgi_proto_uwsgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
uwsgi_sock->proto_write = uwsgi_proto_base_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
if (uwsgi.offload_threads > 0)
uwsgi_sock->can_offload = 1;
}
if (!requested_protocol) requested_protocol = uwsgi.protocol;
uwsgi_socket_setup_protocol(uwsgi_sock, requested_protocol);
nextsock:
uwsgi_sock = uwsgi_sock->next;
}
@@ -2007,3 +1906,42 @@ int uwsgi_accept(int server_fd) {
}
struct uwsgi_protocol *uwsgi_register_protocol(char *name, void (*func)(struct uwsgi_socket *)) {
struct uwsgi_protocol *old_up = NULL, *up = uwsgi.protocols;
while(up) {
if (!strcmp(name, up->name)) {
goto found;
}
old_up = up;
up = up->next;
}
up = uwsgi_calloc(sizeof(struct uwsgi_protocol));
up->name = name;
if (old_up) {
old_up->next = up;
}
else {
uwsgi.protocols = up;
}
found:
up->func = func;
return up;
}
void uwsgi_protocols_register() {
uwsgi_register_protocol("uwsgi", uwsgi_proto_uwsgi_setup);
uwsgi_register_protocol("puwsgi", uwsgi_proto_puwsgi_setup);
uwsgi_register_protocol("http", uwsgi_proto_http_setup);
#ifdef UWSGI_SSL
uwsgi_register_protocol("suwsgi", uwsgi_proto_suwsgi_setup);
uwsgi_register_protocol("https", uwsgi_proto_https_setup);
#endif
uwsgi_register_protocol("fastcgi", uwsgi_proto_fastcgi_setup);
uwsgi_register_protocol("fastcgi-nph", uwsgi_proto_fastcgi_nph_setup);
uwsgi_register_protocol("scgi", uwsgi_proto_scgi_setup);
uwsgi_register_protocol("scgi-nph", uwsgi_proto_scgi_nph_setup);
#ifdef UWSGI_ZEROMQ
uwsgi_register_protocol("zmq", uwsgi_proto_zmq_setup);
#endif
uwsgi_register_protocol("raw", uwsgi_proto_raw_setup);
}
+5 -50
View File
@@ -1290,7 +1290,7 @@ long uwsgi_num_from_file(char *filename, int quiet) {
// setup for a new request
void wsgi_req_setup(struct wsgi_request *wsgi_req, int async_id, struct uwsgi_socket *uwsgi_sock) {
wsgi_req->app_id = uwsgi.default_app;
wsgi_req->app_id = -1;
wsgi_req->async_id = async_id;
wsgi_req->sendfile_fd = -1;
@@ -1901,33 +1901,6 @@ void uwsgi_unix_signal(int signum, void (*func) (int)) {
}
}
char *uwsgi_get_exported_opt(char *key) {
int i;
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
if (!strcmp(uwsgi.exported_opts[i]->key, key)) {
return uwsgi.exported_opts[i]->value;
}
}
return NULL;
}
char *uwsgi_get_optname_by_index(int index) {
struct uwsgi_option *op = uwsgi.options;
while (op->name) {
if (op->shortcut == index) {
return op->name;
}
op++;
}
return NULL;
}
int uwsgi_list_has_num(char *list, int num) {
char *list2 = uwsgi_concat2(list, "");
@@ -3380,8 +3353,10 @@ struct uwsgi_app *uwsgi_add_app(int id, uint8_t modifier1, char *mountpoint, int
}
}
if ((mountpoint_len == 0 || (mountpoint_len = -1 && mountpoint[0] == '/')) && uwsgi.default_app == -1) {
uwsgi.default_app = id;
if (!uwsgi.no_default_app) {
if ((mountpoint_len == 0 || (mountpoint_len = -1 && mountpoint[0] == '/')) && uwsgi.default_app == -1) {
uwsgi.default_app = id;
}
}
return wi;
@@ -3779,26 +3754,6 @@ error:
return NULL;
}
// evaluate a math expression
#ifdef UWSGI_MATHEVAL
double uwsgi_matheval(char *expr) {
#ifdef UWSGI_DEBUG
uwsgi_log("matheval expr = %s\n", expr);
#endif
double ret = 0.0;
void *e = evaluator_create(expr);
if (!e)
return ret;
ret = evaluator_evaluate(e, 0, NULL, NULL);
evaluator_destroy(e);
return ret;
}
char *uwsgi_matheval_str(char *expr) {
double ret = uwsgi_matheval(expr);
return uwsgi_num2str((int) ret);
}
#endif
int uwsgi_kvlist_parse(char *src, size_t len, char list_separator, char kv_separator, ...) {
size_t i;
va_list ap;
+90 -89
View File
@@ -38,11 +38,21 @@ UWSGI_DECLARE_EMBEDDED_PLUGINS;
static struct uwsgi_option uwsgi_base_options[] = {
{"socket", required_argument, 's', "bind to the specified UNIX/TCP socket using default protocol", uwsgi_opt_add_socket, NULL, 0},
{"uwsgi-socket", required_argument, 's', "bind to the specified UNIX/TCP socket using uwsgi protocol", uwsgi_opt_add_socket, "uwsgi", 0},
#ifdef UWSGI_SSL
{"suwsgi-socket", required_argument, 's', "bind to the specified UNIX/TCP socket using uwsgi protocol over SSL", uwsgi_opt_add_ssl_socket, "suwsgi", 0},
{"ssl-socket", required_argument, 's', "bind to the specified UNIX/TCP socket using uwsgi protocol over SSL", uwsgi_opt_add_ssl_socket, "suwsgi", 0},
#endif
{"http-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using HTTP protocol", uwsgi_opt_add_socket, "http", 0},
{"http-socket-modifier1", required_argument, 0, "force the specified modifier1 when using HTTP protocol", uwsgi_opt_set_64bit, &uwsgi.http_modifier1, 0},
{"http-socket-modifier2", required_argument, 0, "force the specified modifier2 when using HTTP protocol", uwsgi_opt_set_64bit, &uwsgi.http_modifier2, 0},
#ifdef UWSGI_SSL
{"https-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using HTTPS protocol", uwsgi_opt_add_ssl_socket, "https", 0},
{"https-socket-modifier1", required_argument, 0, "force the specified modifier1 when using HTTPS protocol", uwsgi_opt_set_64bit, &uwsgi.https_modifier1, 0},
{"https-socket-modifier2", required_argument, 0, "force the specified modifier2 when using HTTPS protocol", uwsgi_opt_set_64bit, &uwsgi.https_modifier2, 0},
#endif
{"fastcgi-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using FastCGI protocol", uwsgi_opt_add_socket, "fastcgi", 0},
{"fastcgi-nph-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using FastCGI protocol (nph mode)", uwsgi_opt_add_socket, "fastcgi-nph", 0},
{"fastcgi-modifier1", required_argument, 0, "force the specified modifier1 when using FastCGI protocol", uwsgi_opt_set_64bit, &uwsgi.fastcgi_modifier1, 0},
@@ -225,14 +235,13 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"vassals-set", required_argument, 0, "automatically set the specified option (via --set) for every vassal", uwsgi_opt_add_string_list, &uwsgi.vassals_set, 0},
{"vassal-set", required_argument, 0, "automatically set the specified option (via --set) for every vassal", uwsgi_opt_add_string_list, &uwsgi.vassals_set, 0},
{"heartbeat", required_argument, 0, "announce healtness to the emperor", uwsgi_opt_set_int, &uwsgi.heartbeat, 0},
{"heartbeat", required_argument, 0, "announce healthiness to the emperor", uwsgi_opt_set_int, &uwsgi.heartbeat, 0},
{"auto-snapshot", optional_argument, 0, "automatically make workers snaphost after reload", uwsgi_opt_set_int, &uwsgi.auto_snapshot, UWSGI_OPT_LAZY},
{"reload-mercy", required_argument, 0, "set the maximum time (in seconds) we wait for workers and other processes to die during reload/shutdown", uwsgi_opt_set_int, &uwsgi.reload_mercy, 0},
{"worker-reload-mercy", required_argument, 0, "set the maximum time (in seconds) a worker can take to reload/shutdown (default is 60)", uwsgi_opt_set_int, &uwsgi.worker_reload_mercy, 0},
{"exit-on-reload", no_argument, 0, "force exit even if a reload is requested", uwsgi_opt_true, &uwsgi.exit_on_reload, 0},
{"die-on-term", no_argument, 0, "exit instead of brutal reload on SIGTERM", uwsgi_opt_true, &uwsgi.die_on_term, 0},
{"force-gateway", no_argument, 0, "force teh spawn of the first registered gateway without a master", uwsgi_opt_true, &uwsgi.force_gateway, 0},
{"force-gateway", no_argument, 0, "force the spawn of the first registered gateway without a master", uwsgi_opt_true, &uwsgi.force_gateway, 0},
{"help", no_argument, 'h', "show this help", uwsgi_help, NULL, UWSGI_OPT_IMMEDIATE},
{"usage", no_argument, 'h', "show this help", uwsgi_help, NULL, UWSGI_OPT_IMMEDIATE},
@@ -299,6 +308,12 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"signal-bufsize", required_argument, 0, "set buffer size for signal queue", uwsgi_opt_set_int, &uwsgi.signal_bufsize, 0},
{"signals-bufsize", required_argument, 0, "set buffer size for signal queue", uwsgi_opt_set_int, &uwsgi.signal_bufsize, 0},
{"signal-timer", required_argument, 0, "add a timer (syntax: <signal> <seconds>)", uwsgi_opt_add_string_list, &uwsgi.signal_timers, UWSGI_OPT_MASTER},
{"timer", required_argument, 0, "add a timer (syntax: <signal> <seconds>)", uwsgi_opt_add_string_list, &uwsgi.signal_timers, UWSGI_OPT_MASTER},
{"signal-rbtimer", required_argument, 0, "add a redblack timer (syntax: <signal> <seconds>)", uwsgi_opt_add_string_list, &uwsgi.rb_signal_timers, UWSGI_OPT_MASTER},
{"rbtimer", required_argument, 0, "add a redblack timer (syntax: <signal> <seconds>)", uwsgi_opt_add_string_list, &uwsgi.rb_signal_timers, UWSGI_OPT_MASTER},
{"rpc-max", required_argument, 0, "maximum number of rpc slots (default: 64)", uwsgi_opt_set_64bit, &uwsgi.rpc_max, 0},
{"disable-logging", no_argument, 'L', "disable request logging", uwsgi_opt_dyn_false, (void *) UWSGI_OPTION_LOGGING, 0},
@@ -514,9 +529,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"metric", required_argument, 0, "add a custom metric", uwsgi_opt_add_string_list, &uwsgi.additional_metrics, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
{"metric-threshold", required_argument, 0, "add a metric threshold/alarm", uwsgi_opt_add_string_list, &uwsgi.metrics_threshold, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
{"metric-alarm", required_argument, 0, "add a metric threshold/alarm", uwsgi_opt_add_string_list, &uwsgi.metrics_threshold, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
{"metrics-dir", required_argument, 0, "exports metrics as text files in the specified directory", uwsgi_opt_set_str, &uwsgi.metrics_dir, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
{"metrics-dir", required_argument, 0, "export metrics as text files to the specified directory", uwsgi_opt_set_str, &uwsgi.metrics_dir, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
{"metrics-dir-restore", no_argument, 0, "restore last value taken from the metrics dir", uwsgi_opt_true, &uwsgi.metrics_dir_restore, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
{"metric-dir", required_argument, 0, "exports metrics as text files in the specified directory", uwsgi_opt_set_str, &uwsgi.metrics_dir, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
{"metric-dir", required_argument, 0, "export metrics as text files to the specified directory", uwsgi_opt_set_str, &uwsgi.metrics_dir, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
{"metric-dir-restore", no_argument, 0, "restore last value taken from the metrics dir", uwsgi_opt_true, &uwsgi.metrics_dir_restore, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
{"udp", required_argument, 0, "run the udp server on the specified address", uwsgi_opt_set_str, &uwsgi.udp_socket, UWSGI_OPT_MASTER},
@@ -845,6 +860,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"namespace-net", required_argument, 0, "add network namespace", uwsgi_opt_set_str, &uwsgi.ns_net, 0},
{"ns-net", required_argument, 0, "add network namespace", uwsgi_opt_set_str, &uwsgi.ns_net, 0},
#endif
{"enable-proxy-protocol", no_argument, 0, "enable PROXY1 protocol support (only for http parsers)", uwsgi_opt_true, &uwsgi.enable_proxy_protocol, 0},
{"reuse-port", no_argument, 0, "enable REUSE_PORT flag on socket (BSD only)", uwsgi_opt_true, &uwsgi.reuse_port, 0},
{"tcp-fast-open", required_argument, 0, "enable TCP_FASTOPEN flag on TCP sockets with the specified qlen value", uwsgi_opt_set_int, &uwsgi.tcp_fast_open, 0},
{"tcp-fastopen", required_argument, 0, "enable TCP_FASTOPEN flag on TCP sockets with the specified qlen value", uwsgi_opt_set_int, &uwsgi.tcp_fast_open, 0},
@@ -870,7 +886,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"worker-exec", required_argument, 0, "run the specified command as worker", uwsgi_opt_set_str, &uwsgi.worker_exec, 0},
{"worker-exec2", required_argument, 0, "run the specified command as worker (after post_fork hook)", uwsgi_opt_set_str, &uwsgi.worker_exec2, 0},
{"attach-daemon", required_argument, 0, "attach a command/daemon to the master process (the command has to not go in background)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
{"attach-control-daemon", required_argument, 0, "attach a command/daemon to the master process (the command has to not go in background), when teh daemon dies, the master dies too", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
{"attach-control-daemon", required_argument, 0, "attach a command/daemon to the master process (the command has to not go in background), when the daemon dies, the master dies too", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
{"smart-attach-daemon", required_argument, 0, "attach a command/daemon to the master process managed by a pidfile (the command has to daemonize)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
{"smart-attach-daemon2", required_argument, 0, "attach a command/daemon to the master process managed by a pidfile (the command has to NOT daemonize)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
#ifdef UWSGI_SSL
@@ -1053,10 +1069,10 @@ void warn_pipe() {
struct wsgi_request *wsgi_req = current_wsgi_req();
if (uwsgi.threads < 2 && wsgi_req->uri_len > 0) {
uwsgi_log("SIGPIPE: writing to a closed pipe/socket/fd (probably the client disconnected) on request %.*s (ip %.*s) !!!\n", wsgi_req->uri_len, wsgi_req->uri, wsgi_req->remote_addr_len, wsgi_req->remote_addr);
uwsgi_log_verbose("SIGPIPE: writing to a closed pipe/socket/fd (probably the client disconnected) on request %.*s (ip %.*s) !!!\n", wsgi_req->uri_len, wsgi_req->uri, wsgi_req->remote_addr_len, wsgi_req->remote_addr);
}
else {
uwsgi_log("SIGPIPE: writing to a closed pipe/socket/fd (probably the client disconnected) !!!\n");
uwsgi_log_verbose("SIGPIPE: writing to a closed pipe/socket/fd (probably the client disconnected) !!!\n");
}
}
@@ -1204,7 +1220,9 @@ void grace_them_all(int signum) {
if (uwsgi.lazy) {
for (i = 1; i <= uwsgi.numproc; i++) {
uwsgi_curse(i, SIGHUP);
if (uwsgi.workers[i].pid > 0) {
uwsgi_curse(i, SIGHUP);
}
}
return;
}
@@ -1212,9 +1230,6 @@ void grace_them_all(int signum) {
uwsgi.status.gracefully_reloading = 1;
int waitpid_status;
uwsgi_destroy_processes();
uwsgi_log("...gracefully killing workers...\n");
@@ -1228,36 +1243,10 @@ void grace_them_all(int signum) {
}
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.auto_snapshot) {
if (uwsgi.workers[i].snapshot > 0) {
kill(uwsgi.workers[i].snapshot, SIGKILL);
if (waitpid(uwsgi.workers[i].snapshot, &waitpid_status, 0) < 0) {
uwsgi_error("waitpid()");
}
}
if (uwsgi.workers[i].pid > 0) {
if (uwsgi.auto_snapshot > 0 && i > uwsgi.auto_snapshot) {
uwsgi.workers[i].snapshot = 0;
uwsgi.workers[i].destroy = 1;
uwsgi_curse(i, SIGHUP);
}
else {
uwsgi.workers[i].snapshot = uwsgi.workers[i].pid;
kill(uwsgi.workers[i].pid, SIGURG);
}
}
}
else if (uwsgi.workers[i].pid > 0) {
if (uwsgi.workers[i].pid > 0) {
uwsgi_curse(i, SIGHUP);
}
}
if (uwsgi.auto_snapshot) {
uwsgi.respawn_snapshots = uwsgi.numproc - uwsgi.auto_snapshot;
if (!uwsgi.respawn_snapshots)
uwsgi.respawn_snapshots = 1;
}
}
void uwsgi_nuclear_blast() {
@@ -1316,23 +1305,6 @@ void harakiri() {
exit(0);
}
void snapshot_me(int signum) {
// wakeup !!!
if (uwsgi.snapshot) {
uwsgi.snapshot = 0;
uwsgi_set_processname(uwsgi.workers[uwsgi.mywid].name);
return;
}
uwsgi.workers[uwsgi.mywid].manage_next_request = 0;
if (uwsgi.threads > 1) {
wait_for_threads();
}
uwsgi.snapshot = 1;
uwsgi_set_processname(uwsgi.workers[uwsgi.mywid].snapshot_name);
uwsgi_log("[snapshot] process %d taken\n", (int) getpid());
}
void stats(int signum) {
//fix this for better logging(this cause races)
struct uwsgi_app *ua = NULL;
@@ -1416,8 +1388,8 @@ void what_i_am_doing() {
int unconfigured_hook(struct wsgi_request *wsgi_req) {
if (wsgi_req->uh->modifier1 == 0 && !uwsgi.no_default_app) {
if (uwsgi_apps_cnt > 0 && wsgi_req->app_id > -1 && wsgi_req->app_id < uwsgi.max_apps) {
struct uwsgi_app *ua = &uwsgi_apps[wsgi_req->app_id];
if (uwsgi_apps_cnt > 0 && uwsgi.default_app > -1) {
struct uwsgi_app *ua = &uwsgi_apps[uwsgi.default_app];
if (uwsgi.p[ua->modifier1]->request != unconfigured_hook) {
wsgi_req->uh->modifier1 = ua->modifier1;
return uwsgi.p[ua->modifier1]->request(wsgi_req);
@@ -1903,7 +1875,6 @@ int main(int argc, char *argv[], char *envp[]) {
signal(SIGTERM, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
//initialize masterpid with a default value
masterpid = getpid();
@@ -1946,6 +1917,12 @@ int main(int argc, char *argv[], char *envp[]) {
// set default values
uwsgi_init_default();
// detect cpu cores
#if defined(_SC_NPROCESSORS_ONLN)
uwsgi.cpus = sysconf(_SC_NPROCESSORS_ONLN);
#elif defined(_SC_NPROCESSORS_CONF)
uwsgi.cpus = sysconf(_SC_NPROCESSORS_CONF);
#endif
// set default logit hook
uwsgi.logit = uwsgi_logit_simple;
@@ -2045,7 +2022,10 @@ int main(int argc, char *argv[], char *envp[]) {
// set a couple of 'static' magic vars
uwsgi.magic_table['v'] = uwsgi.cwd;
uwsgi.magic_table['h'] = uwsgi.hostname;
uwsgi.magic_table['t'] = uwsgi_64bit2str(uwsgi_now());
uwsgi.magic_table['T'] = uwsgi_64bit2str(uwsgi_micros());
uwsgi.magic_table['V'] = UWSGI_VERSION;
uwsgi.magic_table['k'] = uwsgi_num2str(uwsgi.cpus);
uwsgi.magic_table['['] = "\033";
// you can embed a ini file in the uWSGi binary with default options
@@ -2067,12 +2047,7 @@ int main(int argc, char *argv[], char *envp[]) {
uwsgi_apply_config_pass('@', uwsgi_simple_file_read);
// last pass: REFERENCEs
uwsgi_apply_config_pass('%', uwsgi_get_exported_opt);
#ifdef UWSGI_MATHEVAL
// optional pass: MATH
uwsgi_apply_config_pass('=', uwsgi_matheval_str);
#endif
uwsgi_apply_config_pass('%', uwsgi_manage_placeholder);
// ok, the options dictionary is available, lets manage it
uwsgi_configure();
@@ -2253,12 +2228,6 @@ int main(int argc, char *argv[], char *envp[]) {
uwsgi_log_initial("*** big endian arch detected ***\n");
#endif
#if defined(_SC_NPROCESSORS_ONLN)
uwsgi.cpus = sysconf(_SC_NPROCESSORS_ONLN);
#elif defined(_SC_NPROCESSORS_CONF)
uwsgi.cpus = sysconf(_SC_NPROCESSORS_CONF);
#endif
uwsgi_log_initial("detected number of CPU cores: %d\n", uwsgi.cpus);
@@ -2629,6 +2598,9 @@ int uwsgi_start(void *v_argv) {
// initialize the exception handlers
uwsgi_exception_setup_handlers();
// initialize socket protocols (do it after caching !!!)
uwsgi_protocols_register();
/* plugin initialization */
for (i = 0; i < uwsgi.gp_cnt; i++) {
if (uwsgi.gp[i]->init) {
@@ -2867,7 +2839,7 @@ unsafe:
// set a default request structure (for loading apps...)
uwsgi.wsgi_req = &uwsgi.workers[0].cores[0].req;
// ok, let's inizialize the metrics subsystem
// ok, let's initialize the metrics subsystem
uwsgi_setup_metrics();
// cores are allocated, lets allocate logformat (if required)
@@ -3216,11 +3188,6 @@ void uwsgi_worker_run() {
uwsgi_unix_signal(SIGINT, end_me);
uwsgi_unix_signal(SIGTERM, end_me);
if (uwsgi.auto_snapshot) {
uwsgi_unix_signal(SIGURG, snapshot_me);
}
uwsgi_unix_signal(SIGUSR1, stats);
signal(SIGUSR2, (void *) &what_i_am_doing);
if (!uwsgi.ignore_sigpipe) {
@@ -3284,15 +3251,6 @@ void uwsgi_ignition() {
int i;
// snapshot workers do not enter the loop until a specific signal (SIGURG) is raised...
if (uwsgi.snapshot) {
wait_for_call_of_duty:
uwsgi_sig_pause();
if (uwsgi.snapshot)
goto wait_for_call_of_duty;
uwsgi_log("[snapshot] process %d is the new worker %d\n", (int) getpid(), uwsgi.mywid);
}
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->hijack_worker) {
uwsgi.p[i]->hijack_worker();
@@ -3335,9 +3293,6 @@ wait_for_call_of_duty:
}
}
if (uwsgi.snapshot) {
uwsgi_ignition();
}
// end of the process...
end_me(0);
}
@@ -3899,6 +3854,51 @@ void uwsgi_opt_add_socket(char *opt, char *value, void *protocol) {
uwsgi_sock->proto_name = protocol;
}
#ifdef UWSGI_SSL
void uwsgi_opt_add_ssl_socket(char *opt, char *value, void *protocol) {
char *client_ca = NULL;
// build socket, certificate and key file
char *sock = uwsgi_str(value);
char *crt = strchr(sock, ',');
if (!crt) {
uwsgi_log("invalid https-socket syntax must be socket,crt,key\n");
exit(1);
}
*crt = '\0'; crt++;
char *key = strchr(crt, ',');
if (!key) {
uwsgi_log("invalid https-socket syntax must be socket,crt,key\n");
exit(1);
}
*key = '\0'; key++;
char *ciphers = strchr(key, ',');
if (ciphers) {
*ciphers = '\0'; ciphers++;
client_ca = strchr(ciphers, ',');
if (client_ca) {
*client_ca = '\0'; client_ca++;
}
}
struct uwsgi_socket *uwsgi_sock = uwsgi_new_socket(generate_socket_name(sock));
uwsgi_sock->name_len = strlen(uwsgi_sock->name);
uwsgi_sock->proto_name = protocol;
// ok we have the socket, initialize ssl if required
if (!uwsgi.ssl_initialized) {
uwsgi_ssl_init();
}
// initialize ssl context
uwsgi_sock->ssl_ctx = uwsgi_ssl_new_server_context(uwsgi_sock->name, crt, key, ciphers, client_ca);
if (!uwsgi_sock->ssl_ctx) {
exit(1);
}
}
#endif
void uwsgi_opt_add_socket_no_defer(char *opt, char *value, void *protocol) {
struct uwsgi_socket *uwsgi_sock = uwsgi_new_socket(generate_socket_name(value));
uwsgi_sock->name_len = strlen(uwsgi_sock->name);
@@ -4214,6 +4214,7 @@ int uwsgi_zerg_attach(char *value) {
}
pos++;
}
free(zerg);
}
close(zerg_fd);
+1 -1
View File
@@ -53,7 +53,7 @@ static struct uwsgi_option carbon_options[] = {
{"carbon-name-resolve", no_argument, 0, "allow using hostname as carbon server address (default disabled)", uwsgi_opt_true, &u_carbon.resolve_hostname, 0},
{"carbon-resolve-names", no_argument, 0, "allow using hostname as carbon server address (default disabled)", uwsgi_opt_true, &u_carbon.resolve_hostname, 0},
{"carbon-idle-avg", required_argument, 0, "average values source during idle period (no requests), can be \"last\", \"zero\", \"none\" (default is last)", uwsgi_opt_set_str, &u_carbon.idle_avg, 0},
{"carbon-use-metrics", no_argument, 0, "don't compute all statistics, use metrics subsystem data instead (warning! key names will be different", uwsgi_opt_true, &u_carbon.use_metrics, 0},
{"carbon-use-metrics", no_argument, 0, "don't compute all statistics, use metrics subsystem data instead (warning! key names will be different)", uwsgi_opt_true, &u_carbon.use_metrics, 0},
{0, 0, 0, 0, 0, 0, 0},
};
+6 -5
View File
@@ -187,11 +187,12 @@ void uwsgi_opt_corerouter_zerg(char *opt, char *value, void *cr) {
close(zerg_fd);
for(j=0;j<count;j++) {
if (zerg[j] == -1) break;
ugs = uwsgi_new_gateway_socket_from_fd(zerg[j], ucr->name);
ugs->zerg = optarg;
}
for(j=0;j<count;j++) {
if (zerg[j] == -1) break;
ugs = uwsgi_new_gateway_socket_from_fd(zerg[j], ucr->name);
ugs->zerg = optarg;
}
free(zerg);
}
+271 -13
View File
@@ -2,7 +2,7 @@
/*
Soon before official Go 1.1, we understand supporting Go in a fork() heavy
Soon before official Go 1.1, we understood supporting Go in a fork() heavy
environment was not blessed by the Go community.
Instead of completely dropping support for Go, we studied how the gccgo project works and we
@@ -16,8 +16,31 @@
the uwsgi.Run() go function directly calls the uwsgi_takeover() function (it automatically
manages mules, spoolers and workers)
As well as before each core maps to a goroutine mapped to a real pthread. (goroutines called
from your apps are native goroutines)
The plugin implements goroutines too.
On startup a goroutine is created for each socket and signals file descriptors.
For every request a new goroutine is created too.
The wsgi_request * structure is attached to the "closure" field of the goroutine (PAY ATTENTION)
even if the loop engine makes use of the async mode, pthreads could be spawned all over the place.
For such a reason a mutex is created avoiding the global wsgi_req structures to be clobbered
Contrary to the standard way Go apps are deployed, the plugin supports loading shared libraries.
While this is a common approach in other environments, the Go community prefers monolithic binaries.
As always, choose the model that best suite for you. Eventually building a single uWSGI binary with your Go
app embedded is pretty easy:
CFLAGS=-DUWSGI_GCCGO_MONOLITHIC UWSGI_ADDITIONAL_SOURCES=t/go/uploadtest.go UWSGI_PROFILE=gccgo make
or you can add the following two directives in a build profile:
cflags = -DUWSGI_GCCGO_MONOLITHIC
additional_sources = t/go/uploadtest.go
*/
@@ -25,25 +48,29 @@ extern struct uwsgi_server uwsgi;
struct uwsgi_plugin gccgo_plugin;
struct uwsgi_gccgo{
// 1 if a main is loaded
int initialized;
struct uwsgi_string_list *libs;
char *args;
pthread_mutex_t wsgi_req_lock;
} ugccgo;
/*
shortcut for enabling the "goroutines" loop engine
*/
static void uwsgi_opt_setup_goroutines(char *opt, char *value, void *foobar) {
// set async mode
uwsgi_opt_set_int(opt, value, &uwsgi.async);
// set loop engine
uwsgi.loop = "goroutines";
}
*/
struct uwsgi_option uwsgi_gccgo_options[] = {
{"go-load", required_argument, 0, "load a go shared library in the process address space, eventually patching main.main and __go_init_main", uwsgi_opt_add_string_list, &ugccgo.libs, 0},
{"gccgo-load", required_argument, 0, "load a go shared library in the process address space, eventually patching main.main and __go_init_main", uwsgi_opt_add_string_list, &ugccgo.libs, 0},
{"go-args", required_argument, 0, "set go commandline arguments", uwsgi_opt_set_str, &ugccgo.args, 0},
{"gccgo-args", required_argument, 0, "set go commandline arguments", uwsgi_opt_set_str, &ugccgo.args, 0},
// {"goroutines", required_argument, 0, "a shortcut setting optimal options for goroutine-based apps, takes the number of goroutines to spawn as argument", uwsgi_opt_setup_goroutines, NULL, UWSGI_OPT_THREADS},
{"goroutines", required_argument, 0, "a shortcut setting optimal options for goroutine-based apps, takes the number of max goroutines to spawn as argument", uwsgi_opt_setup_goroutines, NULL, UWSGI_OPT_THREADS},
{0, 0, 0, 0, 0, 0, 0},
};
@@ -51,27 +78,46 @@ struct uwsgi_option uwsgi_gccgo_options[] = {
// no_split_stack is the key to avoid crashing !!!
void* runtime_m(void) __attribute__ ((noinline, no_split_stack));
// initialize runtime
void runtime_check(void);
void runtime_args(int, char **);
void runtime_osinit(void);
void runtime_schedinit(void);
void *__go_go(void *, void *);
void runtime_main(void);
void runtime_mstart(void *);
// spawn a goroutine
void *__go_go(void *, void *);
// api functions exposed
extern void uwsgigo_request(void *, void *) __asm__ ("go.uwsgi.RequestHandler");
extern void* uwsgigo_env(void *) __asm__ ("go.uwsgi.Env");
extern void* uwsgigo_env_add(void *, void *, uint16_t, void *, uint16_t) __asm__ ("go.uwsgi.EnvAdd");
extern void uwsgigo_run_core(int) __asm__ ("go.uwsgi.RunCore");
extern void uwsgigo_signal_handler(void *, uint8_t) __asm__ ("go.uwsgi.SignalHandler");
//extern void uwsgigo_loop(void) __asm__ ("go.uwsgi.Loop");
// for goroutines
void runtime_netpollinit(void);
void runtime_starttheworld(void);
void *runtime_pollOpen(int) __asm__ ("net.runtime_pollOpen");
void runtime_pollClose(void *) __asm__ ("net.runtime_pollClose");
void runtime_pollUnblock(void *) __asm__ ("net.runtime_pollUnblock");
int runtime_pollWait(void *, int) __asm__ ("net.runtime_pollWait");
void runtime_pollSetDeadline(void *, int64_t, int) __asm__ ("net.runtime_pollSetDeadline");
void runtime_gosched(void);
// the current goroutine
void *runtime_g(void);
// we use the closure field to store the wsgi_req structure
void __go_set_closure(void *);
void *__go_get_closure(void);
static void mainstart(void *arg __attribute__((unused))) {
runtime_main();
}
#ifndef UWSGI_GCCGO_MONOLITHIC
void uwsgigo_main_main(void) __asm__ ("main.main");
void uwsgigo_main_init(void) __asm__ ("__go_init_main");
#endif
void (*uwsgigo_hook_init)(void);
void (*uwsgigo_hook_main)(void);
@@ -102,6 +148,14 @@ int uwsgi_gccgo_helper_register_signal(uint8_t signum, char *receiver, void *han
}
static void uwsgi_gccgo_initialize() {
if (uwsgi.threads > 1) {
uwsgi_log("!!! the Go runtime cannot work in multithreaded modes !!!\n");
exit(1);
}
#ifdef UWSGI_GCCGO_MONOLITHIC
uwsgigo_hook_init = dlsym(RTLD_DEFAULT, "__go_init_main");
uwsgigo_hook_main = dlsym(RTLD_DEFAULT, "main.main");
#endif
struct uwsgi_string_list *usl = ugccgo.libs;
while(usl) {
void *handle = dlopen(usl->value, RTLD_NOW | RTLD_GLOBAL);
@@ -109,9 +163,16 @@ static void uwsgi_gccgo_initialize() {
uwsgi_log("unable to open go shared library: %s\n", dlerror());
exit(1);
}
uwsgi_log("[uwsgi-gccgo] loaded %s\n", usl->value);
uwsgigo_hook_init = dlsym(handle, "__go_init_main");
uwsgigo_hook_main = dlsym(handle, "main.main");
void *g_init = dlsym(handle, "__go_init_main");
void *g_main = dlsym(handle, "main.main");
if (g_init && g_main) {
uwsgigo_hook_init = g_init;
uwsgigo_hook_main = g_main;
uwsgi_log("[uwsgi-gccgo] loaded %s as main\n", usl->value);
}
else {
uwsgi_log("[uwsgi-gccgo] loaded %s\n", usl->value);
}
usl = usl->next;
}
@@ -119,6 +180,8 @@ static void uwsgi_gccgo_initialize() {
return;
}
ugccgo.initialized = 1;
// Go runtime initialization
int argc = 0;
if (ugccgo.args) {
@@ -131,7 +194,7 @@ static void uwsgi_gccgo_initialize() {
}
runtime_check();
if (argc > 0) {
char **argv = uwsgi_calloc(sizeof(char *) * (argc + 1));
char **argv = uwsgi_calloc(sizeof(char *) * (argc + 2));
char *argv_list = uwsgi_str(ugccgo.args);
char *p, *ctx = NULL;
int n = 0;
@@ -145,6 +208,7 @@ static void uwsgi_gccgo_initialize() {
char *argv[2] = {0,0};
runtime_args(0, argv);
}
runtime_osinit();
runtime_schedinit();
__go_go(mainstart, NULL);
@@ -153,6 +217,10 @@ static void uwsgi_gccgo_initialize() {
}
static int uwsgi_gccgo_request(struct wsgi_request *wsgi_req) {
if (!ugccgo.initialized) {
uwsgi_log("!!! Go runtime not initialized !!!\n");
goto end;
}
/* Standard GO request */
if (!wsgi_req->uh->pktsize) {
uwsgi_log("Empty GO request. skip.\n");
@@ -170,6 +238,7 @@ static int uwsgi_gccgo_request(struct wsgi_request *wsgi_req) {
i++;
}
uwsgigo_request(wsgi_req->async_environ, wsgi_req);
end:
return UWSGI_OK;
}
@@ -178,15 +247,204 @@ static void uwsgi_gccgo_after_request(struct wsgi_request *wsgi_req) {
}
static int uwsgi_gccgo_signal_handler(uint8_t signum, void *handler) {
if (!ugccgo.initialized) return -1;
uwsgigo_signal_handler(handler, signum);
return 0;
}
#define free_req_queue pthread_mutex_lock(&ugccgo.wsgi_req_lock);uwsgi.async_queue_unused_ptr++; uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = wsgi_req; pthread_mutex_unlock(&ugccgo.wsgi_req_lock)
static void uwsgi_gccgo_request_goroutine(void *arg) {
struct wsgi_request *wsgi_req = (struct wsgi_request *) arg;
// map wsgi_req to the goroutine
__go_set_closure(wsgi_req);
int ret,status;
for(;;) {
ret = uwsgi.wait_read_hook(wsgi_req->fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
wsgi_req->switches++;
if (ret <= 0) {
goto end;
}
retry:
status = wsgi_req->socket->proto(wsgi_req);
if (status < 0) {
goto end;
}
else if (status == 0) {
break;
}
if (uwsgi_is_again()) continue;
goto retry;
}
#ifdef UWSGI_ROUTING
if (uwsgi_apply_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
goto end;
}
#endif
for(;;) {
if (uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req) <= UWSGI_OK) {
goto end;
}
wsgi_req->switches++;
// yield
runtime_gosched();
}
end:
uwsgi_close_request(wsgi_req);
free_req_queue;
}
static struct wsgi_request *uwsgi_gccgo_current_wsgi_req(void) {
return (struct wsgi_request *) __go_get_closure();
}
static int uwsgi_gccgo_wait_read_hook(int fd, int timeout) {
void *pdesc = runtime_pollOpen(fd);
int64_t t = (uwsgi_micros() * 1000LL) + (((int64_t)timeout) * 1000LL * 1000LL * 1000LL);
runtime_pollSetDeadline(pdesc, t, 'r');
int ret = runtime_pollWait(pdesc, 'r');
runtime_pollUnblock(pdesc);
runtime_pollClose(pdesc);
if (ret == 0) return 1;
// timeout
if (ret == 2) return 0;
return -1;
}
static int uwsgi_gccgo_wait_write_hook(int fd, int timeout) {
void *pdesc = runtime_pollOpen(fd);
int64_t t = (uwsgi_micros() * 1000LL) + (((int64_t)timeout) * 1000LL * 1000LL * 1000LL);
runtime_pollSetDeadline(pdesc, t, 'w');
int ret = runtime_pollWait(pdesc, 'w');
runtime_pollUnblock(pdesc);
runtime_pollClose(pdesc);
if (ret == 0) return 1;
// timeout
if (ret == 2) return 0;
return -1;
}
/*
this goroutine manages signals
*/
static void uwsgi_gccgo_signal_goroutine(void *arg) {
int *fd = (int *) arg;
void *pdesc = runtime_pollOpen(*fd);
for(;;) {
runtime_pollWait(pdesc, 'r');
retry:
uwsgi_receive_signal(*fd, "worker", uwsgi.mywid);
if (uwsgi_is_again()) continue;
goto retry;
}
}
static void uwsgi_gccgo_socket_goroutine(void *arg) {
struct uwsgi_socket *uwsgi_sock = (struct uwsgi_socket *) arg;
struct wsgi_request *wsgi_req = NULL;
void *pdesc = runtime_pollOpen(uwsgi_sock->fd);
// wait for connection
for(;;) {
runtime_pollWait(pdesc, 'r');
retry:
pthread_mutex_lock(&ugccgo.wsgi_req_lock);
wsgi_req = find_first_available_wsgi_req();
pthread_mutex_unlock(&ugccgo.wsgi_req_lock);
if (wsgi_req == NULL) {
uwsgi_async_queue_is_full(uwsgi_now());
// try rescheduling...
// we do not use runtime_gosched() as we want to call the netpoll loop too
runtime_pollUnblock(pdesc);
runtime_pollClose(pdesc);
pdesc = runtime_pollOpen(uwsgi_sock->fd);
continue;
}
// fill wsgi_request structure
wsgi_req_setup(wsgi_req, wsgi_req->async_id, uwsgi_sock );
// mark core as used
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 1;
// accept the connection (since uWSGI 1.5 all of the sockets are non-blocking)
if (wsgi_req_simple_accept(wsgi_req, uwsgi_sock->fd)) {
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 0;
free_req_queue;
if (uwsgi_is_again()) continue;
goto retry;
}
wsgi_req->start_of_request = uwsgi_micros();
wsgi_req->start_of_request_in_sec = wsgi_req->start_of_request/1000000;
// enter harakiri mode
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
}
// spawn the new goroutine
__go_go(uwsgi_gccgo_request_goroutine, wsgi_req);
goto retry;
}
}
static void uwsgi_gccgo_loop() {
if (!ugccgo.initialized) {
uwsgi_log("no go.main code loaded !!!\n");
exit(1);
}
// initialize the log protecting the wsgi_req structures
pthread_mutex_init(&ugccgo.wsgi_req_lock, NULL);
// hooks
uwsgi.current_wsgi_req = uwsgi_gccgo_current_wsgi_req;
uwsgi.wait_write_hook = uwsgi_gccgo_wait_write_hook;
uwsgi.wait_read_hook = uwsgi_gccgo_wait_read_hook;
// ininitialize Go I/O loop
runtime_netpollinit();
if (uwsgi.signal_socket > -1) {
__go_go(uwsgi_gccgo_signal_goroutine, &uwsgi.signal_socket);
__go_go(uwsgi_gccgo_signal_goroutine, &uwsgi.my_signal_socket);
}
// start a goroutine for each socket
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
if (!uwsgi_sock->next) {
uwsgi_gccgo_socket_goroutine(uwsgi_sock);
}
else {
__go_go(uwsgi_gccgo_socket_goroutine, uwsgi_sock);
}
uwsgi_sock = uwsgi_sock->next;
}
// never here
}
static void uwsgi_gccgo_on_load() {
uwsgi_register_loop( (char *) "go", uwsgi_gccgo_loop);
uwsgi_register_loop( (char *) "goroutine", uwsgi_gccgo_loop);
uwsgi_register_loop( (char *) "goroutines", uwsgi_gccgo_loop);
}
struct uwsgi_plugin gccgo_plugin = {
.name = "gccgo",
.modifier1 = 11,
.options = uwsgi_gccgo_options,
//.on_load = uwsgi_gccgo_on_load,
.on_load = uwsgi_gccgo_on_load,
.request = uwsgi_gccgo_request,
.after_request = uwsgi_gccgo_after_request,
.post_fork = uwsgi_gccgo_initialize,
+45 -2
View File
@@ -1,5 +1,12 @@
package uwsgi
/*
this is a very low-level module, full of performance hacks
do not take it as a good example of go coding...
*/
import (
"strings"
"net/http"
@@ -20,17 +27,27 @@ func uwsgi_response_add_header(*interface{}, *byte, uint16, *byte, uint16) int
func uwsgi_request_body_read(*interface{}, *byte, uint64) int
//extern uwsgi_gccgo_helper_register_signal
func uwsgi_register_signal(uint8, *byte, func(uint8)) int
//extern uwsgi_cache_magic_get
func uwsgi_cache_magic_get(*byte, uint16, *uint64, *uint64, *byte) *byte;
//extern __go_byte_array_to_string
func __go_byte_array_to_string(*byte, int) string
//extern free
func free(* byte)
var uwsgi_signals_gc [256]func(uint8)
var uwsgi_env_gc map[interface{}]interface{}
func Env(wsgi_req *interface{}) *map[string]string {
var env map[string]string
env = make(map[string]string)
uwsgi_env_gc[wsgi_req] = &env
return &env
}
func EnvAdd(env *map[string]string, k *[65536]byte, kl uint16, v *[65536]byte, vl uint16) {
(*env)[ string((*k)[0:kl]) ] = string((*v)[0:vl])
func EnvAdd(env *map[string]string, k *byte, kl uint16, v *byte, vl uint16) {
s_k := __go_byte_array_to_string(k, int(kl))
s_v := __go_byte_array_to_string(v, int(vl))
(*env)[ s_k ] = s_v
}
type ResponseWriter struct {
@@ -98,9 +115,13 @@ func RequestHandler(env *map[string]string, wsgi_req *interface{}) {
w := ResponseWriter{httpReq, wsgi_req,http.Header{},false}
http.DefaultServeMux.ServeHTTP(&w, httpReq)
}
delete(uwsgi_env_gc, wsgi_req)
}
func RegisterSignal(signum uint8, receiver string, handler func(uint8)) bool {
if (receiver == "") {
receiver = "worker"
}
var b []byte = []byte(receiver)
if (uwsgi_register_signal(signum, &b[0], handler) < 0) {
return false
@@ -109,10 +130,32 @@ func RegisterSignal(signum uint8, receiver string, handler func(uint8)) bool {
return true
}
// get an item from the cache
func CacheGet(key string, cache string) string {
var b_key []byte = []byte(key)
var v_len uint64 = 0
var expires uint64 = 0
var value *byte
if (cache == "") {
value = uwsgi_cache_magic_get(&b_key[0], uint16(len(b_key)), &v_len, &expires, nil)
} else {
b_cache := []byte(cache)
value = uwsgi_cache_magic_get(&b_key[0], uint16(len(b_key)), &v_len, &expires, &b_cache[0])
}
ret := __go_byte_array_to_string(value, int(v_len))
free(value)
return ret
}
func SignalHandler(handler func(uint8), signum uint8) {
handler(signum)
}
func Run() {
uwsgi_env_gc = make(map[interface{}]interface{})
uwsgi_takeover()
}
+13
View File
@@ -0,0 +1,13 @@
import os
NAME='gccgo'
CFLAGS = ['-g']
LDFLAGS = []
LIBS = ['-lgo']
GCC_LIST = ['gccgo_plugin', 'uwsgi.go']
def post_build(config):
if os.path.exists('plugins/gccgo/uwsgi.go.o'):
if os.system("objcopy -j .go_export plugins/gccgo/uwsgi.go.o plugins/gccgo/uwsgi.gox") != 0:
os._exit(1)
print("*** uwsgi.gox available in %s/plugins/gccgo ***" % os.getcwd())
-4
View File
@@ -1,10 +1,6 @@
#include <uwsgi.h>
#include <api/glfs.h>
#ifdef UWSGI_MATHEVAL
#error currently the glusterfs plugins is not compatible with uWSGI built with matheval support
#endif
extern struct uwsgi_server uwsgi;
/*
+1 -1
View File
@@ -127,7 +127,7 @@ static void greenlet_init_apps(void) {
// map wsgi_req to greenlet object
uwsgi.current_wsgi_req = uwsgi_greenlet_current_wsgi_req;
// blindy call it as the stackless gil engine is already set
// blindly call it as the stackless gil engine is already set
UWSGI_GET_GIL
+1 -1
View File
@@ -139,7 +139,7 @@ void uwsgi_opt_https2(char *opt, char *value, void *cr) {
#ifdef UWSGI_SPDY
spdyerror:
uwsgi_log("unable to inizialize SPDY settings buffers\n");
uwsgi_log("unable to initialize SPDY settings buffers\n");
exit(1);
#endif
}
+5 -4
View File
@@ -127,7 +127,7 @@ JNIEXPORT jobject JNICALL uwsgi_jvm_api_rpc(JNIEnv *env, jclass c, jobject j_arg
char *argv[256];
uint16_t argvs[256];
jobject argvj[256];
uint16_t size = 0;
uint64_t size = 0;
size_t args = uwsgi_jvm_array_len(j_args);
if (args < 2) return NULL;
@@ -1277,7 +1277,7 @@ void uwsgi_jvm_release_bytearray(jobject o, char *str) {
(*ujvm_env)->ReleaseByteArrayElements(ujvm_env, o, (jbyte *)str, 0);
}
static uint16_t uwsgi_jvm_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
static uint64_t uwsgi_jvm_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char **buffer) {
jvalue args[1];
jobject str_array = (*ujvm_env)->NewObjectArray(ujvm_env, argc, ujvm.str_class, NULL);
if (!str_array) return 0;
@@ -1294,9 +1294,10 @@ static uint16_t uwsgi_jvm_rpc(void *func, uint8_t argc, char **argv, uint16_t ar
return 0;
}
size_t rlen = uwsgi_jvm_strlen(ret);
if (rlen <= 0xffff) {
if (rlen > 0) {
*buffer = uwsgi_malloc(rlen);
char *b = uwsgi_jvm_str2c(ret);
memcpy(buffer, b, rlen);
memcpy(*buffer, b, rlen);
uwsgi_jvm_release_chars(ret, b);
uwsgi_jvm_local_unref(ret);
return rlen;
+4 -3
View File
@@ -670,7 +670,7 @@ static int uwsgi_lua_signal_handler(uint8_t sig, void *handler) {
}
static uint16_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
static uint64_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, uint16_t argvs[], char **buffer) {
uint8_t i;
const char *sv;
@@ -702,8 +702,9 @@ static uint16_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, uint16_t a
#ifdef UWSGI_DEBUG
uwsgi_log("sv = %s sl = %lu\n", sv, (unsigned long) sl);
#endif
if (sl <= 0xffff) {
memcpy(buffer, sv, sl);
if (sl > 0) {
*buffer = uwsgi_malloc(sl);
memcpy(*buffer, sv, sl);
lua_pop(L, 1);
return sl;
}
+52
View File
@@ -0,0 +1,52 @@
#include <uwsgi.h>
#include <matheval.h>
static char *uwsgi_route_var_math(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
char *ret = NULL;
// avoid crash
if (!wsgi_req->var_cnt) return NULL;
// we make a bit of fun here, we do a copy of the vars buffer (+1 byte for final zero) and zeor-pad all of the strings
char *vars_buf = uwsgi_malloc(wsgi_req->uh->pktsize + keylen + 1);
char **names = uwsgi_malloc(sizeof(char *) * (wsgi_req->var_cnt/2));
double *values = uwsgi_calloc(sizeof(double) * (wsgi_req->var_cnt/2));
int i,j = 0;
char *ptr = vars_buf;
for (i = wsgi_req->var_cnt-1; i > 0; i -= 2) {
memcpy(ptr, wsgi_req->hvec[i-1].iov_base, wsgi_req->hvec[i-1].iov_len);
names[j] = ptr;
ptr += wsgi_req->hvec[i-1].iov_len;
*ptr++=0;
char *num = ptr;
memcpy(ptr, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
ptr += wsgi_req->hvec[i].iov_len;
*ptr++=0;
values[j] = strtod(num, NULL);
j++;
}
char *expr = ptr;
memcpy(ptr, key, keylen); ptr += keylen;
*ptr++=0;
void *e = evaluator_create(expr);
if (!e) goto end;
double n = evaluator_evaluate(e, j, names, values);
evaluator_destroy(e);
ret = uwsgi_num2str((int)n);
*vallen = strlen(ret);
end:
free(vars_buf);
free(names);
free(values);
return ret;
}
static void router_matheval_register() {
struct uwsgi_route_var *urv = uwsgi_register_route_var("math", uwsgi_route_var_math);
urv->need_free = 1;
}
struct uwsgi_plugin matheval_plugin = {
.name = "matheval",
.on_load = router_matheval_register,
};
+6
View File
@@ -0,0 +1,6 @@
NAME='matheval'
CFLAGS = []
LDFLAGS = []
LIBS = ['-lmatheval']
GCC_LIST = ['math']
+1 -1
View File
@@ -374,7 +374,7 @@ PHP_FUNCTION(uwsgi_rpc) {
zval *z_current_obj;
char *argv[256];
uint16_t argvs[256];
uint16_t size = 0;
uint64_t size = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &varargs, &num_args) == FAILURE) {
RETURN_NULL();
+5
View File
@@ -58,6 +58,11 @@ struct uwsgi_perl {
time_t last_auto_reload;
struct uwsgi_string_list *auto_reload_ignore;
HV *auto_reload_hash;
int enable_psgix_io;
char *shell;
int shell_oneshot;
};
void init_perl_embedded_module(void);
+2 -1
View File
@@ -349,6 +349,7 @@ int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, Pe
perl_eval_pv("use IO::Handle;", 0);
perl_eval_pv("use IO::File;", 0);
perl_eval_pv("use IO::Socket;", 0);
perl_eval_pv("use Scalar::Util;", 0);
if (!uperl.no_die_catch) {
perl_eval_pv("use Devel::StackTrace;", 0);
@@ -462,7 +463,7 @@ void uwsgi_psgi_app() {
init_psgi_app(NULL, uperl.psgi, strlen(uperl.psgi), uperl.main);
}
// create a perl environment (if needed)
else if (uperl.exec) {
else if (uperl.exec || uperl.shell) {
PERL_SET_CONTEXT(uperl.main[0]);
perl_parse(uperl.main[0], xs_init, 2, uperl.embedding, NULL);
}
+96 -6
View File
@@ -11,9 +11,25 @@ struct uwsgi_perl uperl;
struct uwsgi_plugin psgi_plugin;
static void uwsgi_opt_plshell(char *opt, char *value, void *foobar) {
uwsgi.honour_stdin = 1;
if (value) {
uperl.shell = value;
}
else {
uperl.shell = "";
}
if (!strcmp("plshell-oneshot", opt)) {
uperl.shell_oneshot = 1;
}
}
struct uwsgi_option uwsgi_perl_options[] = {
{"psgi", required_argument, 0, "load a psgi app", uwsgi_opt_set_str, &uperl.psgi, 0},
{"psgi-enable-psgix-io", no_argument, 0, "enable psgix.io support", uwsgi_opt_true, &uperl.enable_psgix_io, 0},
{"perl-no-die-catch", no_argument, 0, "do not catch $SIG{__DIE__}", uwsgi_opt_true, &uperl.no_die_catch, 0},
{"perl-local-lib", required_argument, 0, "set perl locallib path", uwsgi_opt_set_str, &uperl.locallib, 0},
#ifdef PERL_VERSION_STRING
@@ -25,6 +41,9 @@ struct uwsgi_option uwsgi_perl_options[] = {
{"perl-exec-post-fork", required_argument, 0, "exec the specified perl file after fork()", uwsgi_opt_add_string_list, &uperl.exec_post_fork, 0},
{"perl-auto-reload", required_argument, 0, "enable perl auto-reloader with the specified frequency", uwsgi_opt_set_int, &uperl.auto_reload, UWSGI_OPT_MASTER},
{"perl-auto-reload-ignore", required_argument, 0, "ignore the specified files when auto-reload is enabled", uwsgi_opt_add_string_list, &uperl.auto_reload_ignore, UWSGI_OPT_MASTER},
{"plshell", optional_argument, 0, "run a perl interactive shell", uwsgi_opt_plshell, NULL, 0},
{"plshell-oneshot", no_argument, 0, "run a perl interactive shell (one shot)", uwsgi_opt_plshell, NULL, 0},
{0, 0, 0, 0, 0, 0, 0},
};
@@ -102,6 +121,31 @@ SV *uwsgi_perl_obj_new(char *class, size_t class_len) {
}
SV *uwsgi_perl_obj_new_from_fd(char *class, size_t class_len, int fd) {
SV *newobj;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVpv( class, class_len)));
XPUSHs(sv_2mortal(newSViv( fd )));
XPUSHs(sv_2mortal(newSVpv( "w", 1 )));
PUTBACK;
call_method( "new_from_fd", G_SCALAR);
SPAGAIN;
newobj = SvREFCNT_inc(POPs);
PUTBACK;
FREETMPS;
LEAVE;
return newobj;
}
SV *uwsgi_perl_call_stream(SV *func) {
SV *ret = NULL;
@@ -245,7 +289,10 @@ AV *psgi_call(struct wsgi_request *wsgi_req, SV *psgi_func, SV *env) {
uwsgi_log("[uwsgi-perl error] %s", SvPV_nolen(ERRSV));
}
else {
ret = (AV *) SvREFCNT_inc(SvRV(POPs));
SV *r = POPs;
if (SvROK(r)) {
ret = (AV *) SvREFCNT_inc(SvRV(r));
}
}
PUTBACK;
@@ -360,7 +407,12 @@ SV *build_psgi_env(struct wsgi_request *wsgi_req) {
// cleanup handlers array
av = newAV();
if (!hv_store(env, "psgix.cleanup.handlers", 22, newRV_noinc((SV *)av ), 0)) goto clear;
// this call requires a bunch of syscalls, so it hurts performance
if (uperl.enable_psgix_io) {
SV *io = uwsgi_perl_obj_new_from_fd("IO::Socket", 10, wsgi_req->fd);
if (!hv_store(env, "psgix.io", 8, io, 0)) goto clear;
}
SV *pe = uwsgi_perl_obj_new("uwsgi::error", 12);
if (!hv_store(env, "psgi.errors", 11, pe, 0)) goto clear;
@@ -764,10 +816,10 @@ realstuff:
}
}
static uint16_t uwsgi_perl_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
static uint64_t uwsgi_perl_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char **buffer) {
int i;
uint16_t ret = 0;
uint64_t ret = 0;
dSP;
ENTER;
@@ -788,8 +840,11 @@ static uint16_t uwsgi_perl_rpc(void *func, uint8_t argc, char **argv, uint16_t a
STRLEN rlen;
SV *response = POPs;
char *value = SvPV(response, rlen );
ret = UMIN(UMAX16-1, rlen);
memcpy(buffer, value, ret);
if (rlen > 0) {
*buffer = uwsgi_malloc(rlen);
memcpy(*buffer, value, rlen);
ret = rlen;
}
}
PUTBACK;
@@ -799,6 +854,39 @@ static uint16_t uwsgi_perl_rpc(void *func, uint8_t argc, char **argv, uint16_t a
return ret;
}
static void uwsgi_perl_hijack(void) {
if (uperl.shell_oneshot && uwsgi.workers[uwsgi.mywid].hijacked_count > 0) {
uwsgi.workers[uwsgi.mywid].hijacked = 0;
return;
}
if (uperl.shell && uwsgi.mywid == 1) {
uwsgi.workers[uwsgi.mywid].hijacked = 1;
uwsgi.workers[uwsgi.mywid].hijacked_count++;
// re-map stdin to stdout and stderr if we are logging to a file
if (uwsgi.logfile) {
if (dup2(0, 1) < 0) {
uwsgi_error("dup2()");
}
if (dup2(0, 2) < 0) {
uwsgi_error("dup2()");
}
}
if (uperl.shell[0] != 0) {
perl_eval_pv(uperl.shell, 0);
}
else {
perl_eval_pv("use Devel::REPL;my $repl = Devel::REPL->new;$repl->run;", 0);
}
if (uperl.shell_oneshot) {
exit(UWSGI_DE_HIJACKED_CODE);
}
exit(0);
}
}
struct uwsgi_plugin psgi_plugin = {
.name = "psgi",
@@ -815,6 +903,8 @@ struct uwsgi_plugin psgi_plugin = {
.mule = uwsgi_perl_mule,
.hijack_worker = uwsgi_perl_hijack,
.post_fork = uwsgi_perl_post_fork,
.request = uwsgi_perl_request,
.after_request = uwsgi_perl_after_request,
+94 -2
View File
@@ -324,7 +324,7 @@ XS(XS_call) {
dXSARGS;
char *func;
uint16_t size = 0;
uint64_t size = 0;
int i;
char *argv[256];
uint16_t argvs[256];
@@ -351,6 +351,41 @@ XS(XS_call) {
XSRETURN_UNDEF;
}
XS(XS_rpc) {
dXSARGS;
char *node;
char *func;
uint64_t size = 0;
int i;
char *argv[256];
uint16_t argvs[256];
STRLEN arg_len;
psgi_check_args(2);
node = SvPV_nolen(ST(0));
func = SvPV_nolen(ST(1));
for(i=0;i<(items-2);i++) {
argv[i] = SvPV(ST(i+2), arg_len);
argvs[i] = arg_len;
}
// response must be always freed
char *response = uwsgi_do_rpc(node, func, items-2, argv, argvs, &size);
if (response) {
ST(0) = newSVpv(response, size);
sv_2mortal(ST(0));
free(response);
XSRETURN(1);
}
XSRETURN_UNDEF;
}
XS(XS_suspend) {
@@ -404,9 +439,20 @@ XS(XS_i_am_the_lord) {
}
XSRETURN_NO;
}
#endif
XS(XS_connection_fd) {
dXSARGS;
psgi_check_args(0);
struct wsgi_request *wsgi_req = current_wsgi_req();
ST(0) = newSViv(wsgi_req->fd);
sv_2mortal(ST(0));
XSRETURN(1);
}
XS(XS_websocket_handshake) {
dXSARGS;
@@ -622,6 +668,45 @@ XS(XS_metric_get) {
XSRETURN(1);
}
XS(XS_chunked_read) {
dXSARGS;
int timeout = 0;
size_t len = 0;
psgi_check_args(0);
if (items > 0) {
timeout = SvIV(ST(0));
}
struct wsgi_request *wsgi_req = current_wsgi_req();
char *chunk = uwsgi_chunked_read(wsgi_req, &len, timeout, 0);
if (!chunk) {
croak("unable to receive chunked part");
XSRETURN_UNDEF;
}
ST(0) = newSVpv(chunk, len);
sv_2mortal(ST(0));
XSRETURN(1);
}
XS(XS_chunked_read_nb) {
dXSARGS;
size_t len = 0;
psgi_check_args(0);
struct wsgi_request *wsgi_req = current_wsgi_req();
char *chunk = uwsgi_chunked_read(wsgi_req, &len, 0, 1);
if (!chunk) {
if (uwsgi_is_again()) XSRETURN_UNDEF;
croak("unable to receive chunked part");
XSRETURN_UNDEF;
}
ST(0) = newSVpv(chunk, len);
sv_2mortal(ST(0));
XSRETURN(1);
}
void init_perl_embedded_module() {
psgi_xs(reload);
@@ -633,6 +718,7 @@ void init_perl_embedded_module() {
psgi_xs(cache_clear);
psgi_xs(call);
psgi_xs(rpc);
psgi_xs(wait_fd_read);
psgi_xs(wait_fd_write);
psgi_xs(async_sleep);
@@ -646,6 +732,9 @@ void init_perl_embedded_module() {
#ifdef UWSGI_SSL
psgi_xs(i_am_the_lord);
#endif
psgi_xs(connection_fd);
psgi_xs(alarm);
psgi_xs(websocket_handshake);
psgi_xs(websocket_recv);
@@ -665,5 +754,8 @@ void init_perl_embedded_module() {
psgi_xs(metric_div);
psgi_xs(metric_get);
psgi_xs(metric_set);
psgi_xs(chunked_read);
psgi_xs(chunked_read_nb);
}
+2 -2
View File
@@ -274,10 +274,10 @@ static int uwsgi_pypy_signal_handler(uint8_t sig, void *handler) {
return 0;
}
static uint16_t uwsgi_pypy_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
static uint64_t uwsgi_pypy_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char **buffer) {
int iargvs[UMAX8];
int i;
int (*pypy_func)(int, char **, int*, char *) = (int (*)(int, char **, int*, char *)) func;
int (*pypy_func)(int, char **, int*, char **) = (int (*)(int, char **, int*, char **)) func;
// we convert 16bit to int
for(i=0;i<argc;i++) {
iargvs[i] = (int) argvs[i];
+8 -5
View File
@@ -172,6 +172,8 @@ const char *uwsgi_pypy_version;
char *uwsgi_binary_path();
void *uwsgi_malloc(size_t);
int uwsgi_response_prepare_headers(struct wsgi_request *, char *, size_t);
int uwsgi_response_add_header(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
int uwsgi_response_write_body_do(struct wsgi_request *, char *, size_t);
@@ -186,7 +188,7 @@ int uwsgi_is_again();
int uwsgi_register_rpc(char *, struct uwsgi_plugin *, uint8_t, void *);
int uwsgi_register_signal(uint8_t, char *, void *, uint8_t);
char *uwsgi_do_rpc(char *, char *, uint8_t, char **, uint16_t *, uint16_t *);
char *uwsgi_do_rpc(char *, char *, uint8_t, char **, uint16_t *, uint64_t *);
void uwsgi_set_processname(char *);
int uwsgi_signal_send(int, uint8_t);
@@ -490,15 +492,16 @@ class uwsgi_pypy_RPC(object):
for i in range(0, argc):
pargs.append(ffi.string(argv[i], argvs[i]))
response = self.func(*pargs)
if len(response) > 0 and len(response) <= 65535:
dst = ffi.buffer(buf, 65536)
if len(response) > 0:
buf[0] = lib.uwsgi_malloc(len(response))
dst = ffi.buffer(buf[0], len(response))
dst[:len(response)] = response
return len(response)
def uwsgi_pypy_uwsgi_register_rpc(name, func, argc=0):
rpc_func = uwsgi_pypy_RPC(func)
cb = ffi.callback("int(int, char*[], int[], char*)", rpc_func)
cb = ffi.callback("int(int, char*[], int[], char**)", rpc_func)
uwsgi_gc.append(cb)
if lib.uwsgi_register_rpc(ffi.new("char[]", name), ffi.addressof(lib.pypy_plugin), argc, cb) < 0:
raise Exception("unable to register rpc func %s" % name)
@@ -508,7 +511,7 @@ def uwsgi_pypy_rpc(node, func, *args):
argc = 0
argv = ffi.new('char*[256]')
argvs = ffi.new('uint16_t[256]')
rsize = ffi.new('uint16_t*')
rsize = ffi.new('uint64_t*')
for arg in args:
if argc >= 255:
+7 -5
View File
@@ -167,7 +167,7 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
PyThreadState_Swap(wi->interpreter);
init_pyargv();
// we need to inizialize an embedded module for every interpreter
// we need to initialize an embedded module for every interpreter
init_uwsgi_embedded_module();
init_uwsgi_vars();
@@ -205,7 +205,7 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
app_list = PyDict_Keys(applications);
multiapp = PyList_Size(app_list);
if (multiapp < 1) {
uwsgi_log("you have to define at least one app in the apllications dictionary\n");
uwsgi_log("you have to define at least one app in the applications dictionary\n");
goto doh;
}
@@ -340,9 +340,11 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
const char *default_app = "";
if ((wsgi_req->appid_len == 0 || (wsgi_req->appid_len = 1 && wsgi_req->appid[0] == '/')) && uwsgi.default_app == -1) {
default_app = " (default app)" ;
uwsgi.default_app = id;
if (!uwsgi.no_default_app) {
if ((wsgi_req->appid_len == 0 || (wsgi_req->appid_len = 1 && wsgi_req->appid[0] == '/')) && uwsgi.default_app == -1) {
default_app = " (default app)" ;
uwsgi.default_app = id;
}
}
wi->started_at = now;
+4 -3
View File
@@ -1522,7 +1522,7 @@ clear:
return -1;
}
uint16_t uwsgi_python_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
uint64_t uwsgi_python_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char **buffer) {
UWSGI_GET_GIL;
@@ -1546,8 +1546,9 @@ uint16_t uwsgi_python_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[
if (PyString_Check(ret)) {
rv = PyString_AsString(ret);
rl = PyString_Size(ret);
if (rl <= 65536) {
memcpy(buffer, rv, rl);
if (rl > 0) {
*buffer = uwsgi_malloc(rl);
memcpy(*buffer, rv, rl);
Py_DECREF(ret);
UWSGI_RELEASE_GIL;
return rl;
+2 -2
View File
@@ -265,7 +265,7 @@ PyObject *py_uwsgi_add_file_monitor(PyObject * self, PyObject * args) {
PyObject *py_uwsgi_call(PyObject * self, PyObject * args) {
char *func;
uint16_t size = 0;
uint64_t size = 0;
PyObject *py_func;
int argc = PyTuple_Size(args);
int i;
@@ -331,7 +331,7 @@ PyObject *py_uwsgi_rpc_list(PyObject * self, PyObject * args) {
PyObject *py_uwsgi_rpc(PyObject * self, PyObject * args) {
char *node = NULL, *func;
uint16_t size = 0;
uint64_t size = 0;
PyObject *py_node, *py_func;
int argc = PyTuple_Size(args);
+8 -1
View File
@@ -141,6 +141,11 @@ static VALUE rack_uwsgi_i_am_the_lord(VALUE *class, VALUE legion_name) {
}
#endif
static VALUE rack_uwsgi_connection_fd(VALUE *class) {
struct wsgi_request *wsgi_req = current_wsgi_req();
return INT2NUM(wsgi_req->fd);
}
static VALUE rack_uwsgi_setprocname(VALUE *class, VALUE rbname) {
@@ -800,7 +805,7 @@ static VALUE uwsgi_ruby_signal_registered(VALUE *class, VALUE signum) {
static VALUE uwsgi_ruby_do_rpc(int argc, VALUE *rpc_argv, VALUE *class) {
char *node = NULL, *func;
uint16_t size = 0;
uint64_t size = 0;
char *argv[256];
uint16_t argvs[256];
@@ -1166,6 +1171,8 @@ void uwsgi_rack_init_api() {
#ifdef UWSGI_SSL
uwsgi_rack_api("i_am_the_lord", rack_uwsgi_i_am_the_lord, 1);
#endif
uwsgi_rack_api("connection_fd", rack_uwsgi_connection_fd, 0);
uwsgi_rack_api("cache_get", rack_uwsgi_cache_get, -1);
+4 -7
View File
@@ -315,7 +315,7 @@ VALUE rack_call_rpc_handler(VALUE args) {
}
uint16_t uwsgi_ruby_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
uint64_t uwsgi_ruby_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char **buffer) {
uint8_t i;
VALUE rb_args = rb_ary_new2(2);
@@ -343,8 +343,9 @@ uint16_t uwsgi_ruby_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[],
if (TYPE(ret) == T_STRING) {
rv = RSTRING_PTR(ret);
rl = RSTRING_LEN(ret);
if (rl <= 0xffff) {
memcpy(buffer, rv, rl);
if (rl > 0) {
*buffer = uwsgi_malloc(rl);
memcpy(*buffer, rv, rl);
return rl;
}
}
@@ -1106,7 +1107,6 @@ static void uwsgi_rack_hijack(void) {
uwsgi_error("dup2()");
}
}
int ret = -1;
int error = 0;
if (ur.rbshell[0] != 0) {
rb_eval_string(ur.rbshell);
@@ -1122,9 +1122,6 @@ static void uwsgi_rack_hijack(void) {
exit(UWSGI_DE_HIJACKED_CODE);
}
if (ret == 0) {
exit(UWSGI_QUIET_CODE);
}
exit(0);
}
+61 -25
View File
@@ -11,13 +11,14 @@ extern struct uwsgi_server uwsgi;
rpc-HTTP interface.
modifier2 changes the parsser behaviours:
modifier2 changes the parser behaviours:
0 -> return uwsgi header + rpc response
1 -> return raw rpc response
2 -> split PATH_INFO to get func name and args and return as HTTP response with content_type as application/binary or Accept request header (if different from *)
3 -> set xmlrpc wrapper (requires libxml2)
4 -> set jsonrpc wrapper (requires libjansson)
5 -> used in uwsgi response to signal the response is a uwsgi dictionary followed by the body (the dictionary must contains a CONTENT_LENGTH key)
*/
@@ -70,7 +71,7 @@ static int uwsgi_rpc_xmlrpc_args(xmlNode *element, char **argv, uint16_t *argvs,
return 0;
}
static int uwsgi_rpc_xmlrpc(struct wsgi_request *wsgi_req, xmlDoc *doc, char **argv, uint16_t *argvs, uint8_t *argc, char *response_buf) {
static int uwsgi_rpc_xmlrpc(struct wsgi_request *wsgi_req, xmlDoc *doc, char **argv, uint16_t *argvs, uint8_t *argc, char **response_buf) {
char *method = NULL;
xmlNode *element = xmlDocGetRootElement(doc);
if (!element) return -1;
@@ -91,12 +92,14 @@ static int uwsgi_rpc_xmlrpc(struct wsgi_request *wsgi_req, xmlDoc *doc, char **a
}
if (!method) return -1;
wsgi_req->uh->pktsize = uwsgi_rpc(method, *argc, argv+1, argvs+1, response_buf);
uint64_t content_len = uwsgi_rpc(method, *argc, argv+1, argvs+1, response_buf);
if (!wsgi_req->uh->pktsize) return -1;
if (wsgi_req->uh->pktsize == UMAX16-1) return -1;
if (!*response_buf) return -1;
// add final NULL byte
response_buf[wsgi_req->uh->pktsize] = 0;
char *tmp_buf = realloc(*response_buf, content_len + 1);
if (!tmp_buf) return -1;
*response_buf = tmp_buf;
*response_buf[content_len] = 0;
xmlDoc *rdoc = xmlNewDoc(BAD_CAST "1.0");
xmlNode *m_response = xmlNewNode(NULL, BAD_CAST "methodResponse");
@@ -130,7 +133,9 @@ static int uwsgi_rpc_request(struct wsgi_request *wsgi_req) {
// maximum number of supported arguments
uint8_t argc = 0xff;
// response output
char response_buf[UMAX16];
char *response_buf = NULL;
// response size
size_t content_len = 0;
/* Standard RPC request */
if (!wsgi_req->uh->pktsize) {
@@ -173,22 +178,23 @@ static int uwsgi_rpc_request(struct wsgi_request *wsgi_req) {
p = strtok_r(NULL, "/", &ctx);
}
wsgi_req->uh->pktsize = uwsgi_rpc(argv[0], argc, argv+1, argvs+1, response_buf);
content_len = uwsgi_rpc(argv[0], argc, argv+1, argvs+1, &response_buf);
free(args);
if (!wsgi_req->uh->pktsize) {
if (!content_len) {
if (response_buf) free(response_buf);
uwsgi_404(wsgi_req);
return UWSGI_OK;
}
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return 1;
if (uwsgi_response_add_content_length(wsgi_req, wsgi_req->uh->pktsize)) return -1;
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) {if (response_buf) free(response_buf); return -1;}
if (uwsgi_response_add_content_length(wsgi_req, content_len)) {if (response_buf) free(response_buf); return -1;}
uint16_t ctype_len = 0;
char *ctype = uwsgi_get_var(wsgi_req, "HTTP_ACCEPT", 11, &ctype_len);
if (ctype && strcmp(ctype, "*/*") && strcmp(ctype, "*")) {
if (uwsgi_response_add_content_type(wsgi_req, ctype, ctype_len)) return -1;
if (!ctype || !uwsgi_strncmp(ctype, ctype_len, "*/*" ,3) || !uwsgi_strncmp(ctype, ctype_len, "*", 1)) {
if (uwsgi_response_add_content_type(wsgi_req, "application/binary", 18)) {if (response_buf) free(response_buf); return -1;}
}
else {
if (uwsgi_response_add_content_type(wsgi_req, "application/binary", 18)) return -1;
if (uwsgi_response_add_content_type(wsgi_req, ctype, ctype_len)) {if (response_buf) free(response_buf); return -1;}
}
goto sendbody;
}
@@ -206,11 +212,12 @@ static int uwsgi_rpc_request(struct wsgi_request *wsgi_req) {
uwsgi_500(wsgi_req);
return UWSGI_OK;
}
int ret = uwsgi_rpc_xmlrpc(wsgi_req, doc, argv, argvs, &argc, response_buf);
int ret = uwsgi_rpc_xmlrpc(wsgi_req, doc, argv, argvs, &argc, &response_buf);
xmlFreeDoc(doc);
if (ret) {
uwsgi_500(wsgi_req);
}
if (response_buf) free(response_buf);
return UWSGI_OK;
}
#endif
@@ -221,20 +228,49 @@ static int uwsgi_rpc_request(struct wsgi_request *wsgi_req) {
}
// call the function (output will be in wsgi_req->buffer)
wsgi_req->uh->pktsize = uwsgi_rpc(argv[0], argc-1, argv+1, argvs+1, response_buf);
content_len = uwsgi_rpc(argv[0], argc-1, argv+1, argvs+1, &response_buf);
if (!response_buf) return -1;
// using modifier2 we may want a raw output
if (wsgi_req->uh->modifier2 == 0) {
if (uwsgi_response_write_body_do(wsgi_req, (char *) wsgi_req->uh, 4)) {
return -1;
if (content_len > 0xffff) {
// signal dictionary
wsgi_req->uh->modifier2 = 5;
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
if (uwsgi_buffer_append_keynum(ub, "CONTENT_LENGTH", 14 , content_len)) {
uwsgi_buffer_destroy(ub);
free(response_buf);
return -1;
}
// fix uwsgi header
wsgi_req->uh->pktsize = ub->pos;
if (uwsgi_response_write_body_do(wsgi_req, (char *) wsgi_req->uh, 4)) {
uwsgi_buffer_destroy(ub);
free(response_buf);
return -1;
}
if (uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos)) {
uwsgi_buffer_destroy(ub);
free(response_buf);
return -1;
}
uwsgi_buffer_destroy(ub);
}
else {
wsgi_req->uh->pktsize = content_len;
if (uwsgi_response_write_body_do(wsgi_req, (char *) wsgi_req->uh, 4)) {
free(response_buf);
return -1;
}
}
}
sendbody:
// write the response
uwsgi_response_write_body_do(wsgi_req, response_buf, wsgi_req->uh->pktsize);
uwsgi_response_write_body_do(wsgi_req, response_buf, content_len);
free(response_buf);
return UWSGI_OK;
}
@@ -270,7 +306,7 @@ static int uwsgi_routing_func_rpc(struct wsgi_request *wsgi_req, struct uwsgi_ro
*at = 0;
remote = at+1;
}
uint16_t size;
uint64_t size;
char *response = uwsgi_do_rpc(remote, func, ur->custom, argv, argvs, &size);
free(func);
if (!response) goto end;
@@ -322,7 +358,7 @@ static int uwsgi_routing_func_rpc_blob(struct wsgi_request *wsgi_req, struct uws
*at = 0;
remote = at+1;
}
uint16_t size;
uint64_t size;
char *response = uwsgi_do_rpc(remote, func, ur->custom, argv, argvs, &size);
free(func);
if (!response) goto end;
@@ -377,7 +413,7 @@ static int uwsgi_routing_func_rpc_raw(struct wsgi_request *wsgi_req, struct uwsg
*at = 0;
remote = at+1;
}
uint16_t size;
uint64_t size;
char *response = uwsgi_do_rpc(remote, func, ur->custom, argv, argvs, &size);
free(func);
if (!response) goto end;
@@ -431,7 +467,7 @@ static int uwsgi_routing_func_rpc_var(struct wsgi_request *wsgi_req, struct uwsg
*at = 0;
remote = at+1;
}
uint16_t size;
uint64_t size;
char *response = uwsgi_do_rpc(remote, func, ur->custom, argv, argvs, &size);
free(func);
if (!response) goto end;
@@ -488,7 +524,7 @@ static int uwsgi_routing_func_rpc_ret(struct wsgi_request *wsgi_req, struct uwsg
*at = 0;
remote = at+1;
}
uint16_t size;
uint64_t size;
char *response = uwsgi_do_rpc(remote, func, ur->custom, argv, argvs, &size);
free(func);
if (!response) goto end;
+1 -1
View File
@@ -61,7 +61,7 @@ static void rrdtool_post_init() {
if (!u_rrd.create) return;
// do not waste time if no --rrdtool option is defiend
// do not waste time if no --rrdtool option is defined
if (!u_rrd.directory) return;
if (!u_rrd.freq) u_rrd.freq = 300;
+2 -2
View File
@@ -50,11 +50,11 @@ static int uwsgi_servlet_setup() {
uwsgi_log("%p %p\n", uwsgi_request, uwsgi_response);
mid = uwsgi_jvm_get_method_id(uwsgi_request , "<init>", "()V");
uwsgi_jvm_exception();
if (uwsgi_jvm_exception() || !mid) exit(1);
jobject request = (*ujvm_env)->NewObject(ujvm_env, uwsgi_request, mid);
mid = uwsgi_jvm_get_method_id(uwsgi_response , "<init>", "()V");
uwsgi_jvm_exception();
if (uwsgi_jvm_exception() || !mid) exit(1);
jobject response = (*ujvm_env)->NewObject(ujvm_env, uwsgi_response, mid);
uwsgi_log("%p %p\n", request, response);
+1 -1
View File
@@ -94,7 +94,7 @@ static void stackless_init_apps(void) {
up.gil_release = gil_stackless_release;
}
// blindy call it as the stackless gil engine is already set
// blindly call it as the stackless gil engine is already set
UWSGI_GET_GIL
usl.sl = uwsgi_malloc( sizeof(PyTaskletObject *) * uwsgi.async );
+2 -2
View File
@@ -63,8 +63,8 @@ static void uwsgi_symcall_after_request(struct wsgi_request *wsgi_req) {
log_request(wsgi_req);
}
static uint16_t uwsgi_symcall_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
uint16_t (*casted_func)(uint8_t, char **, uint16_t *, char *) = (uint16_t (*)(uint8_t, char **, uint16_t *, char *)) func;
static uint64_t uwsgi_symcall_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char **buffer) {
uint64_t (*casted_func)(uint8_t, char **, uint16_t *, char **) = (uint64_t (*)(uint8_t, char **, uint16_t *, char **)) func;
return casted_func(argc, argv, argvs, buffer);
}
+1 -1
View File
@@ -3,7 +3,7 @@
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 *);
uint64_t uwsgi_v8_rpc(void *, uint8_t, char **, uint16_t *, char **);
int uwsgi_v8_signal_handler(uint8_t, void *);
void uwsgi_v8_init_thread(int);
void uwsgi_v8_enable_threads();
+6 -3
View File
@@ -256,7 +256,7 @@ extern "C" void uwsgi_v8_configurator(char *filename, char *magic_table[]) {
}
extern "C" uint16_t uwsgi_v8_rpc(void * func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
extern "C" uint64_t uwsgi_v8_rpc(void * func, uint8_t argc, char **argv, uint16_t argvs[], char **buffer) {
int core_id = (long) pthread_getspecific(uv8.current_core);
@@ -285,8 +285,11 @@ extern "C" uint16_t uwsgi_v8_rpc(void * func, uint8_t argc, char **argv, uint16_
if (!*robj) {
return 0;
}
uint16_t rlen = robj->Length();
memcpy(buffer, *r_value, rlen);
uint64_t rlen = (uint64_t) robj->Length();
if (rlen > 0) {
*buffer = (char *)uwsgi_malloc(rlen);
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;
+5 -4
View File
@@ -267,6 +267,7 @@ static int uwsgi_request_xslt(struct wsgi_request *wsgi_req) {
if (found) goto apply;
uwsgi_404(wsgi_req);
free(xmlfile);
return UWSGI_OK;
apply:
@@ -398,10 +399,10 @@ static int uwsgi_routing_func_xslt(struct wsgi_request *wsgi_req, struct uwsgi_r
if (!ub_params) goto end;
}
if (urxc->content_type) {
ub_content_type = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urxc->content_type, urxc->content_type_len);
if (!ub_content_type) goto end;
}
if (!urxc->content_type) goto end;
ub_content_type = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urxc->content_type, urxc->content_type_len);
if (!ub_content_type) goto end;
int rlen;
xmlDoc *doc = xmlParseFile(ub_doc->buf) ;
+132
View File
@@ -114,6 +114,26 @@ void uwsgi_proto_base_close(struct wsgi_request *wsgi_req) {
close(wsgi_req->fd);
}
#ifdef UWSGI_SSL
int uwsgi_proto_ssl_accept(struct wsgi_request *wsgi_req, int server_fd) {
int fd = uwsgi_proto_base_accept(wsgi_req, server_fd);
if (fd >= 0) {
wsgi_req->ssl = SSL_new(wsgi_req->socket->ssl_ctx);
SSL_set_fd(wsgi_req->ssl, fd);
SSL_set_accept_state(wsgi_req->ssl);
}
return fd;
}
void uwsgi_proto_ssl_close(struct wsgi_request *wsgi_req) {
uwsgi_proto_base_close(wsgi_req);
// clear the errors (otherwise they could be propagated)
ERR_clear_error();
SSL_free(wsgi_req->ssl);
}
#endif
struct uwsgi_buffer *uwsgi_proto_base_add_header(struct wsgi_request *wsgi_req, char *k, uint16_t kl, char *v, uint16_t vl) {
struct uwsgi_buffer *ub = NULL;
if (kl > 0) {
@@ -188,6 +208,39 @@ int uwsgi_proto_base_write(struct wsgi_request * wsgi_req, char *buf, size_t len
return -1;
}
#ifdef UWSGI_SSL
int uwsgi_proto_ssl_write(struct wsgi_request * wsgi_req, char *buf, size_t len) {
int ret = -1;
retry:
ret = SSL_write(wsgi_req->ssl, buf, len);
if (ret >= 0) {
wsgi_req->write_pos += ret;
if (wsgi_req->write_pos == len) {
return UWSGI_OK;
}
return UWSGI_AGAIN;
}
int err = SSL_get_error(wsgi_req->ssl, ret);
if (err == SSL_ERROR_WANT_WRITE) {
return UWSGI_AGAIN;
}
else if (err == SSL_ERROR_WANT_READ) {
ret = uwsgi_wait_read_req(wsgi_req);
if (ret <= 0) return -1;
goto retry;
}
else if (err == SSL_ERROR_SYSCALL) {
uwsgi_error("uwsgi_proto_ssl_write()/SSL_write()");
}
return -1;
}
#endif
int uwsgi_proto_base_sendfile(struct wsgi_request * wsgi_req, int fd, size_t pos, size_t len) {
ssize_t wlen = uwsgi_sendfile_do(wsgi_req->fd, fd, pos+wsgi_req->write_pos, len-wsgi_req->write_pos);
if (wlen > 0) {
@@ -205,6 +258,34 @@ int uwsgi_proto_base_sendfile(struct wsgi_request * wsgi_req, int fd, size_t pos
return -1;
}
#ifdef UWSGI_SSL
int uwsgi_proto_ssl_sendfile(struct wsgi_request *wsgi_req, int fd, size_t pos, size_t len) {
char buf[32768];
ssize_t rlen = read(fd, buf, UMIN(len, 32768));
if (rlen <= 0) return -1;
for(;;) {
int ret = uwsgi_proto_ssl_write(wsgi_req, buf, rlen);
if (ret == UWSGI_OK) {
if (wsgi_req->write_pos >= len) {
return UWSGI_OK;
}
return UWSGI_AGAIN;
}
if (ret == UWSGI_AGAIN) {
ret = uwsgi_wait_write_req(wsgi_req);
if (ret <= 0 ) return -1;
continue;
}
return -1;
}
return -1;
}
#endif
int uwsgi_proto_base_fix_headers(struct wsgi_request * wsgi_req) {
return uwsgi_buffer_append(wsgi_req->headers, "\r\n", 2);
}
@@ -220,7 +301,58 @@ ssize_t uwsgi_proto_base_read_body(struct wsgi_request *wsgi_req, char *buf, siz
return read(wsgi_req->fd, buf, len);
}
#ifdef UWSGI_SSL
ssize_t uwsgi_proto_ssl_read_body(struct wsgi_request *wsgi_req, char *buf, size_t len) {
int ret = -1;
if (wsgi_req->proto_parser_remains > 0) {
size_t remains = UMIN(wsgi_req->proto_parser_remains, len);
memcpy(buf, wsgi_req->proto_parser_remains_buf, remains);
wsgi_req->proto_parser_remains -= remains;
wsgi_req->proto_parser_remains_buf += remains;
return remains;
}
retry:
ret = SSL_read(wsgi_req->ssl, buf, len);
if (ret >= 0) return ret;
int err = SSL_get_error(wsgi_req->ssl, ret);
if (err == SSL_ERROR_WANT_READ) {
errno = EAGAIN;
return -1;
}
else if (err == SSL_ERROR_WANT_WRITE) {
ret = uwsgi_wait_write_req(wsgi_req);
if (ret <= 0) return -1;
goto retry;
}
else if (err == SSL_ERROR_SYSCALL) {
uwsgi_error("uwsgi_proto_ssl_read_body()/SSL_read()");
}
return -1;
}
#endif
ssize_t uwsgi_proto_noop_read_body(struct wsgi_request *wsgi_req, char *buf, size_t len) {
uwsgi_log_verbose("!!! the current protocol does not support request body !!!\n");
return -1;
}
void uwsgi_proto_raw_setup(struct uwsgi_socket *uwsgi_sock) {
uwsgi_sock->proto = uwsgi_proto_raw_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
uwsgi_sock->proto_write = uwsgi_proto_base_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
if (uwsgi.offload_threads > 0)
uwsgi_sock->can_offload = 1;
}
+26
View File
@@ -319,3 +319,29 @@ int uwsgi_proto_fastcgi_sendfile(struct wsgi_request *wsgi_req, int fd, size_t p
}
return -1;
}
void uwsgi_proto_fastcgi_setup(struct uwsgi_socket *uwsgi_sock) {
uwsgi_sock->proto = uwsgi_proto_fastcgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_cgi_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_fastcgi_read_body;
uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_fastcgi_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close;
}
void uwsgi_proto_fastcgi_nph_setup(struct uwsgi_socket *uwsgi_sock) {
uwsgi_sock->proto = uwsgi_proto_fastcgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_fastcgi_read_body;
uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_fastcgi_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close;
}
+247 -14
View File
@@ -1,6 +1,6 @@
/* async http protocol parser */
#include "../uwsgi.h"
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
@@ -76,6 +76,96 @@ static uint16_t http_add_uwsgi_header(struct wsgi_request *wsgi_req, char *hh, i
return 2 + keylen + 2 + vallen;
}
static char *proxy1_parse(char *ptr, char *watermark, char **src, uint16_t *src_len, char **dst, uint16_t *dst_len, char **src_port, uint16_t *src_port_len, char **dst_port, uint16_t *dst_port_len) {
// check for PROXY header
if (watermark - ptr > 6) {
if (memcmp(ptr, "PROXY ", 6)) return ptr;
}
else {
return ptr;
}
ptr+= 6;
char *base = ptr;
while (ptr < watermark) {
if (*ptr == ' ') {
ptr++;
break;
}
else if (*ptr == '\n') {
return ptr+1;
}
ptr++;
}
// SRC address
base = ptr;
while (ptr < watermark) {
if (*ptr == ' ') {
*src = base;
*src_len = ptr - base;
ptr++;
break;
}
else if (*ptr == '\n') {
return ptr+1;
}
ptr++;
}
// DST address
base = ptr;
while (ptr < watermark) {
if (*ptr == ' ') {
*dst = base;
*dst_len = ptr - base;
ptr++;
break;
}
else if (*ptr == '\n') {
return ptr+1;
}
ptr++;
}
// SRC port
base = ptr;
while (ptr < watermark) {
if (*ptr == ' ') {
*src_port = base;
*src_port_len = ptr - base;
ptr++;
break;
}
else if (*ptr == '\n') {
return ptr+1;
}
ptr++;
}
// DST port
base = ptr;
while (ptr < watermark) {
if (*ptr == '\r') {
*dst_port = base;
*dst_port_len = ptr - base;
ptr++;
break;
}
else if (*ptr == '\n') {
return ptr+1;
}
ptr++;
}
// check for \n
while (ptr < watermark) {
if (*ptr == '\n') return ptr+1;
ptr++;
}
return ptr;
}
static int http_parse(struct wsgi_request *wsgi_req, char *watermark) {
@@ -84,6 +174,19 @@ static int http_parse(struct wsgi_request *wsgi_req, char *watermark) {
char *query_string = NULL;
char ip[INET_ADDRSTRLEN+1];
struct sockaddr_in *http_sin = (struct sockaddr_in *) &wsgi_req->c_addr;
char *proxy_src = NULL;
char *proxy_dst = NULL;
char *proxy_src_port = NULL;
char *proxy_dst_port = NULL;
uint16_t proxy_src_len = 0;
uint16_t proxy_dst_len = 0;
uint16_t proxy_src_port_len = 0;
uint16_t proxy_dst_port_len = 0;
if (uwsgi.enable_proxy_protocol) {
ptr = proxy1_parse(ptr, watermark, &proxy_src, &proxy_src_len, &proxy_dst, &proxy_dst_len, &proxy_src_port, &proxy_src_port_len, &proxy_dst_port, &proxy_dst_port_len);
base = ptr;
}
// REQUEST_METHOD
while (ptr < watermark) {
@@ -162,24 +265,40 @@ static int http_parse(struct wsgi_request *wsgi_req, char *watermark) {
// SERVER_NAME
wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_NAME", 11, uwsgi.hostname, uwsgi.hostname_len);
// SERVER_PORT
char *server_port = strchr(wsgi_req->socket->name, ':');
if (server_port) {
wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, server_port+1, strlen(server_port+1));
// SERVER_PORT / SERVER_ADDR
if (proxy_dst) {
wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_ADDR", 11, proxy_dst, proxy_dst_len);
if (proxy_dst_port) {
wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, proxy_dst_port, proxy_dst_port_len);
}
}
else {
wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, "80", 2);
char *server_port = strchr(wsgi_req->socket->name, ':');
if (server_port) {
wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, server_port+1, strlen(server_port+1));
}
else {
wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, "80", 2);
}
}
// TODO add ipv6 support
// REMOTE_ADDR
memset(ip, 0, INET_ADDRSTRLEN+1);
if (inet_ntop(AF_INET, (void *) &http_sin->sin_addr.s_addr, ip, INET_ADDRSTRLEN)) {
wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, ip, strlen(ip));
if (proxy_src) {
wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, proxy_src, proxy_src_len);
if (proxy_src_port) {
wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_PORT", 11, proxy_src_port, proxy_src_port_len);
}
}
else {
uwsgi_error("inet_ntop()");
return -1;
// TODO add ipv6 support
memset(ip, 0, INET_ADDRSTRLEN+1);
if (inet_ntop(AF_INET, (void *) &http_sin->sin_addr.s_addr, ip, INET_ADDRSTRLEN)) {
wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, ip, strlen(ip));
}
else {
uwsgi_error("inet_ntop()");
return -1;
}
}
//HEADERS
@@ -211,7 +330,7 @@ static int http_parse(struct wsgi_request *wsgi_req, char *watermark) {
int uwsgi_proto_http_parser(struct wsgi_request *wsgi_req) {
static int uwsgi_proto_http_parser(struct wsgi_request *wsgi_req) {
ssize_t j;
char *ptr;
@@ -239,7 +358,7 @@ int uwsgi_proto_http_parser(struct wsgi_request *wsgi_req) {
}
// mute on 0 len...
if (wsgi_req->proto_parser_pos > 0) {
uwsgi_error("uwsgi_proto_http_parser()");
uwsgi_log("uwsgi_proto_http_parser() -> client closed connection");
}
return -1;
@@ -437,3 +556,117 @@ int uwsgi_is_full_http(struct uwsgi_buffer *ub) {
return 0;
}
void uwsgi_proto_http_setup(struct uwsgi_socket *uwsgi_sock) {
uwsgi_sock->proto = uwsgi_proto_http_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
uwsgi_sock->proto_write = uwsgi_proto_base_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
if (uwsgi.offload_threads > 0)
uwsgi_sock->can_offload = 1;
}
#ifdef UWSGI_SSL
static int uwsgi_proto_https_parser(struct wsgi_request *wsgi_req) {
ssize_t j;
char *ptr;
int len = -1;
// first round ? (wsgi_req->proto_parser_buf is freed at the end of the request)
if (!wsgi_req->proto_parser_buf) {
wsgi_req->proto_parser_buf = uwsgi_malloc(uwsgi.buffer_size);
}
if (uwsgi.buffer_size - wsgi_req->proto_parser_pos == 0) {
uwsgi_log("invalid HTTPS request size (max %u)...skip\n", uwsgi.buffer_size);
return -1;
}
retry:
len = SSL_read(wsgi_req->ssl, wsgi_req->proto_parser_buf + wsgi_req->proto_parser_pos, uwsgi.buffer_size - wsgi_req->proto_parser_pos);
if (len > 0) {
goto parse;
}
if (len == 0) goto empty;
int err = SSL_get_error(wsgi_req->ssl, len);
if (err == SSL_ERROR_WANT_READ) {
return UWSGI_AGAIN;
}
else if (err == SSL_ERROR_WANT_WRITE) {
int ret = uwsgi_wait_write_req(wsgi_req);
if (ret <= 0) return -1;
goto retry;
}
else if (err == SSL_ERROR_SYSCALL) {
uwsgi_error("uwsgi_proto_https_parser()/SSL_read()");
}
return -1;
empty:
// mute on 0 len...
if (wsgi_req->proto_parser_pos > 0) {
uwsgi_log("uwsgi_proto_https_parser() -> client closed connection");
}
return -1;
parse:
ptr = wsgi_req->proto_parser_buf + wsgi_req->proto_parser_pos;
wsgi_req->proto_parser_pos += len;
for (j = 0; j < len; j++) {
if (*ptr == '\r' && (wsgi_req->proto_parser_status == 0 || wsgi_req->proto_parser_status == 2)) {
wsgi_req->proto_parser_status++;
}
else if (*ptr == '\r') {
wsgi_req->proto_parser_status = 1;
}
else if (*ptr == '\n' && wsgi_req->proto_parser_status == 1) {
wsgi_req->proto_parser_status = 2;
}
else if (*ptr == '\n' && wsgi_req->proto_parser_status == 3) {
ptr++;
wsgi_req->proto_parser_remains = len - (j + 1);
if (wsgi_req->proto_parser_remains > 0) {
wsgi_req->proto_parser_remains_buf = (wsgi_req->proto_parser_buf + wsgi_req->proto_parser_pos) - wsgi_req->proto_parser_remains;
}
wsgi_req->https = "on";
wsgi_req->https_len = 2;
if (http_parse(wsgi_req, ptr)) return -1;
wsgi_req->uh->modifier1 = uwsgi.https_modifier1;
wsgi_req->uh->modifier2 = uwsgi.https_modifier2;
return UWSGI_OK;
}
else {
wsgi_req->proto_parser_status = 0;
}
ptr++;
}
return UWSGI_AGAIN;
}
void uwsgi_proto_https_setup(struct uwsgi_socket *uwsgi_sock) {
uwsgi_sock->proto = uwsgi_proto_https_parser;
uwsgi_sock->proto_accept = uwsgi_proto_ssl_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_ssl_read_body;
uwsgi_sock->proto_write = uwsgi_proto_ssl_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_ssl_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_ssl_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_ssl_close;
}
#endif
+17
View File
@@ -89,3 +89,20 @@ int uwsgi_proto_puwsgi_accept(struct wsgi_request *wsgi_req, int fd) {
}
return uwsgi_proto_base_accept(wsgi_req, fd);
}
void uwsgi_proto_puwsgi_setup(struct uwsgi_socket *uwsgi_sock) {
uwsgi_sock->proto = uwsgi_proto_puwsgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_puwsgi_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_noop_read_body;
uwsgi_sock->proto_write = uwsgi_proto_base_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_puwsgi_close;
uwsgi_sock->fd_threads = uwsgi_malloc(sizeof(int) * uwsgi.cores);
memset(uwsgi_sock->fd_threads, -1, sizeof(int) * uwsgi.cores);
uwsgi_sock->retry = uwsgi_calloc(sizeof(int) * uwsgi.cores);
uwsgi.is_et = 1;
}
+27
View File
@@ -106,3 +106,30 @@ int uwsgi_proto_scgi_parser(struct wsgi_request *wsgi_req) {
}
return -1;
}
void uwsgi_proto_scgi_setup(struct uwsgi_socket *uwsgi_sock) {
uwsgi_sock->proto = uwsgi_proto_scgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_cgi_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
uwsgi_sock->proto_write = uwsgi_proto_base_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
}
void uwsgi_proto_scgi_nph_setup(struct uwsgi_socket *uwsgi_sock) {
uwsgi_sock->proto = uwsgi_proto_scgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
uwsgi_sock->proto_write = uwsgi_proto_base_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
}
+96 -9
View File
@@ -4,22 +4,22 @@
extern struct uwsgi_server uwsgi;
int uwsgi_proto_uwsgi_parser(struct wsgi_request *wsgi_req) {
static int uwsgi_proto_uwsgi_parser(struct wsgi_request *wsgi_req) {
char *ptr = (char *) wsgi_req->uh;
ssize_t len = read(wsgi_req->fd, ptr + wsgi_req->proto_parser_pos, (uwsgi.buffer_size+4) - wsgi_req->proto_parser_pos);
ssize_t len = read(wsgi_req->fd, ptr + wsgi_req->proto_parser_pos, (uwsgi.buffer_size + 4) - wsgi_req->proto_parser_pos);
if (len > 0) {
wsgi_req->proto_parser_pos += len;
if (wsgi_req->proto_parser_pos >= 4) {
#ifdef __BIG_ENDIAN__
wsgi_req->uh->pktsize = uwsgi_swap16(wsgi_req->uh->pktsize);
#endif
if ((wsgi_req->proto_parser_pos-4) == wsgi_req->uh->pktsize) {
return UWSGI_OK;
if ((wsgi_req->proto_parser_pos - 4) == wsgi_req->uh->pktsize) {
return UWSGI_OK;
}
if ((wsgi_req->proto_parser_pos-4) > wsgi_req->uh->pktsize) {
wsgi_req->proto_parser_remains = wsgi_req->proto_parser_pos-(4+wsgi_req->uh->pktsize);
if ((wsgi_req->proto_parser_pos - 4) > wsgi_req->uh->pktsize) {
wsgi_req->proto_parser_remains = wsgi_req->proto_parser_pos - (4 + wsgi_req->uh->pktsize);
wsgi_req->proto_parser_remains_buf = wsgi_req->buffer + wsgi_req->uh->pktsize;
return UWSGI_OK;
return UWSGI_OK;
}
if (wsgi_req->uh->pktsize > uwsgi.buffer_size) {
uwsgi_log("invalid request block size: %u (max %u)...skip\n", wsgi_req->uh->pktsize, uwsgi.buffer_size);
@@ -32,16 +32,71 @@ int uwsgi_proto_uwsgi_parser(struct wsgi_request *wsgi_req) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
return UWSGI_AGAIN;
}
uwsgi_error("uwsgi_proto_uwsgi_parser()");
uwsgi_error("uwsgi_proto_uwsgi_parser()");
return -1;
}
// 0 len
if (wsgi_req->proto_parser_pos > 0) {
uwsgi_error("uwsgi_proto_uwsgi_parser()");
uwsgi_error("uwsgi_proto_uwsgi_parser()");
}
return -1;
}
#ifdef UWSGI_SSL
static int uwsgi_proto_suwsgi_parser(struct wsgi_request *wsgi_req) {
char *ptr = (char *) wsgi_req->uh;
int len = -1;
retry:
len = SSL_read(wsgi_req->ssl, ptr + wsgi_req->proto_parser_pos, (uwsgi.buffer_size + 4) - wsgi_req->proto_parser_pos);
if (len > 0) {
wsgi_req->proto_parser_pos += len;
if (wsgi_req->proto_parser_pos >= 4) {
#ifdef __BIG_ENDIAN__
wsgi_req->uh->pktsize = uwsgi_swap16(wsgi_req->uh->pktsize);
#endif
if ((wsgi_req->proto_parser_pos - 4) == wsgi_req->uh->pktsize) {
return UWSGI_OK;
}
if ((wsgi_req->proto_parser_pos - 4) > wsgi_req->uh->pktsize) {
wsgi_req->proto_parser_remains = wsgi_req->proto_parser_pos - (4 + wsgi_req->uh->pktsize);
wsgi_req->proto_parser_remains_buf = wsgi_req->buffer + wsgi_req->uh->pktsize;
return UWSGI_OK;
}
if (wsgi_req->uh->pktsize > uwsgi.buffer_size) {
uwsgi_log("invalid request block size: %u (max %u)...skip\n", wsgi_req->uh->pktsize, uwsgi.buffer_size);
return -1;
}
}
return UWSGI_AGAIN;
}
else if (len == 0) goto empty;
int err = SSL_get_error(wsgi_req->ssl, len);
if (err == SSL_ERROR_WANT_READ) {
return UWSGI_AGAIN;
}
else if (err == SSL_ERROR_WANT_WRITE) {
int ret = uwsgi_wait_write_req(wsgi_req);
if (ret <= 0) return -1;
goto retry;
}
else if (err == SSL_ERROR_SYSCALL) {
uwsgi_error("uwsgi_proto_suwsgi_parser()/SSL_read()");
}
return -1;
empty:
// 0 len
if (wsgi_req->proto_parser_pos > 0) {
uwsgi_error("uwsgi_proto_uwsgi_parser()");
}
return -1;
}
#endif
/*
int uwsgi_proto_uwsgi_parser_unix(struct wsgi_request *wsgi_req) {
@@ -155,3 +210,35 @@ int uwsgi_proto_uwsgi_parser_unix(struct wsgi_request *wsgi_req) {
}
*/
void uwsgi_proto_uwsgi_setup(struct uwsgi_socket *uwsgi_sock) {
uwsgi_sock->proto = uwsgi_proto_uwsgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
uwsgi_sock->proto_write = uwsgi_proto_base_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
if (uwsgi.offload_threads > 0)
uwsgi_sock->can_offload = 1;
}
#ifdef UWSGI_SSL
void uwsgi_proto_suwsgi_setup(struct uwsgi_socket *uwsgi_sock) {
uwsgi_sock->proto = uwsgi_proto_suwsgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_ssl_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_ssl_read_body;
uwsgi_sock->proto_write = uwsgi_proto_ssl_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_ssl_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_ssl_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_ssl_close;
if (uwsgi.offload_threads > 0)
uwsgi_sock->can_offload = 1;
}
#endif
+4
View File
@@ -662,3 +662,7 @@ void uwsgi_proto_zeromq_setup(struct uwsgi_socket *uwsgi_sock) {
uwsgi_sock->recv_flag = ZMQ_NOBLOCK;
#endif
}
void uwsgi_proto_zmq_setup(struct uwsgi_socket *uwsgi_sock) {
uwsgi.zeromq = 1;
}
+5
View File
@@ -24,8 +24,13 @@ func postHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, foo + "\n\n" + handler.Filename + "\n\n" + string(bar_data))
}
func signal30(sig uint8) {
fmt.Println("ciao")
}
func main() {
fmt.Println(os.Args)
uwsgi.RegisterSignal(30, "", signal30)
http.HandleFunc("/view/", viewHandler)
http.HandleFunc("/post/", postHandler)
uwsgi.Run()
+129
View File
@@ -0,0 +1,129 @@
#!./uwsgi --http-socket :9090 --coroae 100 --psgi tests/websockets_chat.pl
use Coro::AnyEvent;
use AnyEvent::Redis;
# Coro::AnyEvent uWSGI/PSGI websocket app
# you can build a Coro::AnyEvent-enabled uWSGI binary with 'make coroae'
# note: we need two redis connections, one for publishing and one for subscribing
my $app = sub {
my ($env) = @_;
my $ws_scheme = 'ws';
$ws_scheme = 'wss' if ($env->{'HTTPS'} || $env->{'wsgi.url_scheme'} eq 'https');
if ($env->{'PATH_INFO'} eq '/') {
my $host = $env->{'HTTP_HOST'};
my $html = <<EOF;
<html>
<head>
<script language="Javascript">
var s = new WebSocket("$ws_scheme://$host/foobar/");
s.onopen = function() {
alert("connected !!!");
s.send("ciao");
};
s.onmessage = function(e) {
var bb = document.getElementById('blackboard')
var html = bb.innerHTML;
bb.innerHTML = html + '<br/>' + e.data;
};
s.onerror = function(e) {
alert(e);
}
s.onclose = function(e) {
alert("connection closed");
}
function invia() {
var value = document.getElementById('testo').value;
s.send(value);
}
</script>
</head>
<body>
<h1>WebSocket</h1>
<input type="text" id="testo"/>
<input type="button" value="invia" onClick="invia();"/>
<div id="blackboard" style="width:640px;height:480px;background-color:black;color:white;border: solid 2px red;overflow:auto">
</div>
</body>
</html>
EOF
return [200, ['Content-Type' => 'text/html'], [$html]];
}
elsif ($env->{'PATH_INFO'} eq '/favicon.ico') {
return [404, [], []];
}
elsif ($env->{'PATH_INFO'} eq '/foobar/') {
# when 1 something was wrong and we need to close the connection
my $error = 0;
# when 1 there is something in the websocket
my $websocket_event = 0;
# when defined there is a redis message available
my $redis_message = undef;
# do the hadnshake
uwsgi::websocket_handshake($env->{'HTTP_SEC_WEBSOCKET_KEY'}, $env->{'HTTP_ORIGIN'});
print "websockets...\n" ;
# this condvar will allow us to wait for events
my $w = AnyEvent->condvar;
# connect to redis
my $redis = AnyEvent::Redis->new(
host => '127.0.0.1',
port => 6379,
encoding => 'utf8',
on_error => sub { warn @_; $error = 1; $w->send; },
on_cleanup => sub { warn "Connection closed: @_"; $error = 1; $w->send; },
);
# subscribe to the 'foobar' channel
$redis->subscribe('foobar', sub {
my ($message, $channel) = @_;
$redis_message = $message;
# wakeup !!!
$w->send;
});
# open a second connection to publish messages
my $redis_publisher = AnyEvent::Redis->new(
host => '127.0.0.1',
port => 6379,
encoding => 'utf8',
on_error => sub { warn @_; $error = 1; $w->send; },
on_cleanup => sub { warn "Connection closed: @_"; $error = 1; $w->send; },
);
# start waiting for read events in the websocket
my $ws = AnyEvent->io( fh => uwsgi::connection_fd, poll => 'r', cb => sub {
$websocket_event = 1;
# wakeup !!!
$w->send;
}
);
# the main loop
for(;;) {
# here we block until an event is available
$w->recv;
break if $error;
# any websocket message available ?
if ($websocket_event) {
my $msg = uwsgi::websocket_recv_nb;
$redis_publisher->publish('foobar', $msg) if $msg;
$websocket_event = 0;
}
# any redis message available ?
if ($redis_message) {
uwsgi::websocket_send('['.time().'] '.$redis_message);
$redis_message = undef;
}
$w = AnyEvent->condvar;
}
}
}
+2 -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-11-09'
s.date = '2013-11-17'
s.summary = "uWSGI"
s.description = "The uWSGI server for Ruby/Rack"
s.authors = ["Unbit"]
@@ -12,4 +12,5 @@ Gem::Specification.new do |s|
s.require_paths = ['.']
s.executables << 'uwsgi'
s.homepage = 'http://projects.unbit.it/uwsgi'
s.add_runtime_dependency 'rack'
end
+65 -45
View File
@@ -438,10 +438,6 @@ struct uwsgi_lock_ops {
#include <pcre.h>
#endif
#ifdef UWSGI_MATHEVAL
#include <matheval.h>
#endif
struct uwsgi_dyn_dict {
char *key;
@@ -962,10 +958,20 @@ struct uwsgi_socket {
int shared;
int from_shared;
#ifdef UWSGI_SSL
SSL_CTX *ssl_ctx;
#endif
// used for avoiding vacuum mess
ino_t inode;
};
struct uwsgi_protocol {
char *name;
void (*func)(struct uwsgi_socket *);
struct uwsgi_protocol *next;
};
struct uwsgi_server;
struct uwsgi_plugin {
@@ -1009,7 +1015,7 @@ struct uwsgi_plugin {
int (*spooler) (char *, char *, uint16_t, char *, size_t);
uint16_t(*rpc) (void *, uint8_t, char **, uint16_t *, char *);
uint64_t(*rpc) (void *, uint8_t, char **, uint16_t *, char **);
void (*jail) (int (*)(void *), char **);
void (*post_jail) (void);
@@ -1525,6 +1531,10 @@ struct wsgi_request {
int is_raw;
#ifdef UWSGI_SSL
SSL *ssl;
#endif
struct msghdr msg;
union {
struct cmsghdr cmsg;
@@ -1682,14 +1692,6 @@ struct uwsgi_server {
char *blacklist_context;
char *whitelist_context;
int snapshot;
int respawn_snapshots;
// enable auto-snapshotting
int auto_snapshot;
pid_t restore_snapshot;
unsigned int reloads;
// leave master running as root
@@ -1723,10 +1725,14 @@ struct uwsgi_server {
int tcp_fast_open;
int tcp_fast_open_client;
int enable_proxy_protocol;
uint64_t fastcgi_modifier1;
uint64_t fastcgi_modifier2;
uint64_t http_modifier1;
uint64_t http_modifier2;
uint64_t https_modifier1;
uint64_t https_modifier2;
uint64_t scgi_modifier1;
uint64_t scgi_modifier2;
uint64_t raw_modifier1;
@@ -2216,6 +2222,9 @@ struct uwsgi_server {
struct uwsgi_string_list *fs_brutal_reload;
struct uwsgi_string_list *fs_signal;
struct uwsgi_string_list *signal_timers;
struct uwsgi_string_list *rb_signal_timers;
struct uwsgi_string_list *mountpoints_check;
int propagate_touch;
@@ -2405,6 +2414,7 @@ struct uwsgi_server {
int zeromq;
void *zmq_context;
#endif
struct uwsgi_protocol *protocols;
struct uwsgi_socket *sockets;
struct uwsgi_socket *shared_sockets;
int is_et;
@@ -2741,17 +2751,10 @@ struct uwsgi_core {
struct wsgi_request req;
};
struct uwsgi_snapshot {
char *name;
pid_t pid;
time_t timestamp;
};
struct uwsgi_worker {
int id;
pid_t pid;
pid_t snapshot;
uint64_t status;
time_t last_spawn;
@@ -2800,7 +2803,6 @@ struct uwsgi_worker {
struct uwsgi_core *cores;
char name[0xff];
char snapshot_name[0xff];
};
@@ -3094,8 +3096,8 @@ void uwsgi_route_signal(uint8_t);
int uwsgi_start(void *);
int uwsgi_register_rpc(char *, struct uwsgi_plugin *, uint8_t, void *);
uint16_t uwsgi_rpc(char *, uint8_t, char **, uint16_t *, char *);
char *uwsgi_do_rpc(char *, char *, uint8_t, char **, uint16_t *, uint16_t *);
uint64_t uwsgi_rpc(char *, uint8_t, char **, uint16_t *, char **);
char *uwsgi_do_rpc(char *, char *, uint8_t, char **, uint16_t *, uint64_t *);
void uwsgi_rpc_init(void);
char *uwsgi_cheap_string(char *, int);
@@ -3167,6 +3169,7 @@ void uwsgi_nuclear_blast();
void uwsgi_unix_signal(int, void (*)(int));
char *uwsgi_get_exported_opt(char *);
char *uwsgi_manage_placeholder(char *);
int uwsgi_signal_add_cron(uint8_t, int, int, int, int, int);
int uwsgi_cron_task_needs_execution(struct tm *, int, int, int, int, int);
@@ -3225,30 +3228,24 @@ time_t timegm(struct tm *);
size_t uwsgi_str_num(char *, int);
size_t uwsgi_str_occurence(char *, size_t, char);
int uwsgi_proto_uwsgi_parser(struct wsgi_request *);
int uwsgi_proto_puwsgi_parser(struct wsgi_request *);
int uwsgi_proto_base_write(struct wsgi_request *, char *, size_t);
#ifdef UWSGI_SSL
int uwsgi_proto_ssl_write(struct wsgi_request *, char *, size_t);
#endif
int uwsgi_proto_base_write_header(struct wsgi_request *, char *, size_t);
ssize_t uwsgi_proto_base_read_body(struct wsgi_request *, char *, size_t);
ssize_t uwsgi_proto_noop_read_body(struct wsgi_request *, char *, size_t);
int uwsgi_proto_http_parser(struct wsgi_request *);
int uwsgi_proto_fastcgi_parser(struct wsgi_request *);
int uwsgi_proto_fastcgi_write(struct wsgi_request *, char *, size_t);
int uwsgi_proto_fastcgi_write_header(struct wsgi_request *, char *, size_t);
int uwsgi_proto_fastcgi_sendfile(struct wsgi_request *, int, size_t, size_t);
void uwsgi_proto_fastcgi_close(struct wsgi_request *);
ssize_t uwsgi_proto_fastcgi_read_body(struct wsgi_request *, char *, size_t);
int uwsgi_proto_scgi_parser(struct wsgi_request *);
#ifdef UWSGI_SSL
ssize_t uwsgi_proto_ssl_read_body(struct wsgi_request *, char *, size_t);
#endif
int uwsgi_proto_base_accept(struct wsgi_request *, int);
int uwsgi_proto_puwsgi_accept(struct wsgi_request *, int);
int uwsgi_proto_raw_parser(struct wsgi_request *);
void uwsgi_proto_base_close(struct wsgi_request *);
void uwsgi_proto_puwsgi_close(struct wsgi_request *);
#ifdef UWSGI_SSL
int uwsgi_proto_ssl_accept(struct wsgi_request *, int);
void uwsgi_proto_ssl_close(struct wsgi_request *);
#endif
uint16_t proto_base_add_uwsgi_header(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
uint16_t proto_base_add_uwsgi_var(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
@@ -3259,6 +3256,24 @@ void *uwsgi_zeromq_init(void);
void uwsgi_zeromq_init_sockets(void);
#endif
// protocols
void uwsgi_proto_uwsgi_setup(struct uwsgi_socket *);
void uwsgi_proto_puwsgi_setup(struct uwsgi_socket *);
void uwsgi_proto_raw_setup(struct uwsgi_socket *);
void uwsgi_proto_http_setup(struct uwsgi_socket *);
#ifdef UWSGI_SSL
void uwsgi_proto_https_setup(struct uwsgi_socket *);
void uwsgi_proto_suwsgi_setup(struct uwsgi_socket *);
#endif
#ifdef UWSGI_ZEROMQ
void uwsgi_proto_zmq_setup(struct uwsgi_socket *);
#endif
void uwsgi_proto_fastcgi_setup(struct uwsgi_socket *);
void uwsgi_proto_fastcgi_nph_setup(struct uwsgi_socket *);
void uwsgi_proto_scgi_setup(struct uwsgi_socket *);
void uwsgi_proto_scgi_nph_setup(struct uwsgi_socket *);
int uwsgi_num2str2(int, char *);
@@ -3297,7 +3312,7 @@ int uwsgi_read_whole_true_nb(int, char *, size_t, int);
int uwsgi_read_uh(int fd, struct uwsgi_header *, int);
int uwsgi_proxy_nb(struct wsgi_request *, char *, struct uwsgi_buffer *, size_t, int);
int uwsgi_read_with_realloc(int, char **, size_t *, int);
int uwsgi_read_with_realloc(int, char **, size_t *, int, uint8_t *, uint8_t *);
int uwsgi_write_true_nb(int, char *, size_t, int);
void uwsgi_destroy_request(struct wsgi_request *);
@@ -3539,6 +3554,9 @@ void uwsgi_opt_dyn_false(char *, char *, void *);
void uwsgi_opt_set_placeholder(char *, char *, void *);
void uwsgi_opt_add_shared_socket(char *, char *, void *);
void uwsgi_opt_add_socket(char *, char *, void *);
#ifdef UWSGI_SSL
void uwsgi_opt_add_ssl_socket(char *, char *, void *);
#endif
void uwsgi_opt_add_socket_no_defer(char *, char *, void *);
void uwsgi_opt_add_lazy_socket(char *, char *, void *);
void uwsgi_opt_add_cron(char *, char *, void *);
@@ -4082,11 +4100,6 @@ void uwsgi_daemons_smart_check();
void uwsgi_setup_thread_req(long, struct wsgi_request *);
void uwsgi_loop_cores_run(void *(*)(void *));
#ifdef UWSGI_MATHEVAL
double uwsgi_matheval(char *);
char *uwsgi_matheval_str(char *);
#endif
int uwsgi_kvlist_parse(char *, size_t, char, char, ...);
int uwsgi_send_http_stats(int);
@@ -4181,6 +4194,9 @@ struct uwsgi_buffer *uwsgi_proto_base_cgi_prepare_headers(struct wsgi_request *,
int uwsgi_response_write_body_do(struct wsgi_request *, char *, size_t);
int uwsgi_proto_base_sendfile(struct wsgi_request *, int, size_t, size_t);
#ifdef UWSGI_SSL
int uwsgi_proto_ssl_sendfile(struct wsgi_request *, int, size_t, size_t);
#endif
ssize_t uwsgi_sendfile_do(int, int, size_t, size_t);
int uwsgi_proto_base_fix_headers(struct wsgi_request *);
@@ -4533,6 +4549,10 @@ int uwsgi_base128(struct uwsgi_buffer *, uint64_t, int);
struct wsgi_request *find_wsgi_req_proto_by_fd(int);
struct uwsgi_protocol *uwsgi_register_protocol(char *, void (*)(struct uwsgi_socket *));
void uwsgi_protocols_register(void);
#ifdef __cplusplus
}
#endif
+26 -21
View File
@@ -1,6 +1,6 @@
# uWSGI build system
uwsgi_version = '1.9.19'
uwsgi_version = '1.9.20'
import os
import re
@@ -66,7 +66,6 @@ report = {
'timer': False,
'filemonitor': False,
'pcre': False,
'matheval': False,
'routing': False,
'capabilities': False,
'yaml': False,
@@ -308,16 +307,6 @@ def build_uwsgi(uc, print_only=False, gcll=None):
open('core/dot_h.c', 'w').write('char *uwsgi_dot_h = "%s";\n' % uwsgi_dot_h);
gcc_list.append('core/dot_h')
additional_sources = os.environ.get('UWSGI_ADDITIONAL_SOURCES')
if not additional_sources:
additional_sources = uc.get('additional_sources')
if additional_sources:
for item in additional_sources.split(','):
if item.endswith('.c'):
gcc_list.append(item[:-2])
else:
gcc_list.append(item)
cflags.append('-DUWSGI_CFLAGS=\\"%s\\"' % uwsgi_cflags)
cflags.append('-DUWSGI_BUILD_DATE="\\"%s\\""' % time.strftime("%d %B %Y %H:%M:%S"))
@@ -329,7 +318,18 @@ def build_uwsgi(uc, print_only=False, gcll=None):
if objfile == 'uwsgi':
objfile = 'main'
if not objfile.endswith('.a') and not objfile.endswith('.o'):
compile(' '.join(cflags), last_cflags_ts, objfile + '.o', file + '.c')
if objfile.endswith('.c') or objfile.endswith('.cc') or objfile.endswith('.m') or objfile.endswith('.go'):
if objfile.endswith('.go'):
cflags.append('-Wno-error')
compile(' '.join(cflags), last_cflags_ts, objfile + '.o', file)
if objfile.endswith('.go'):
cflags.pop()
else:
if objfile == 'core/dot_h':
cflags.append('-g')
compile(' '.join(cflags), last_cflags_ts, objfile + '.o', file + '.c')
if objfile == 'core/dot_h':
cflags.pop()
if uc.get('embedded_plugins'):
ep = uc.get('embedded_plugins').split(',')
@@ -406,11 +406,13 @@ def build_uwsgi(uc, print_only=False, gcll=None):
gcc_list.append(cfile)
elif cfile.endswith('.o'):
gcc_list.append('%s/%s' % (path, cfile))
elif not cfile.endswith('.c') and not cfile.endswith('.cc') and not cfile.endswith('.m'):
elif not cfile.endswith('.c') and not cfile.endswith('.cc') and not cfile.endswith('.go') and not cfile.endswith('.m'):
compile(' '.join(uniq_warnings(p_cflags)), last_cflags_ts,
path + '/' + cfile + '.o', path + '/' + cfile + '.c')
gcc_list.append('%s/%s' % (path, cfile))
else:
if cfile.endswith('.go'):
p_cflags.append('-Wno-error')
compile(' '.join(uniq_warnings(p_cflags)), last_cflags_ts,
path + '/' + cfile + '.o', path + '/' + cfile)
gcc_list.append('%s/%s' % (path, cfile))
@@ -464,6 +466,13 @@ def build_uwsgi(uc, print_only=False, gcll=None):
for ef in binary_list:
gcc_list.append("build/%s" % ef)
additional_sources = os.environ.get('UWSGI_ADDITIONAL_SOURCES')
if not additional_sources:
additional_sources = uc.get('additional_sources')
if additional_sources:
for item in additional_sources.split(','):
gcc_list.append(item)
if compile_queue:
for t in thread_compilers:
compile_queue.put((None, None))
@@ -972,12 +981,6 @@ class uConf(object):
self.libs.append('-lcap')
report['capabilities'] = True
if self.get('matheval'):
if (self.get('matheval') == 'auto' and self.has_include('matheval.h')) or self.get('matheval') == 'true':
self.cflags.append("-DUWSGI_MATHEVAL")
self.libs.append('-lmatheval')
report['matheval'] = True
has_json = False
has_uuid = False
@@ -1253,9 +1256,11 @@ def build_plugin(path, uc, cflags, ldflags, libs, name = None):
for cfile in up['GCC_LIST']:
if cfile.endswith('.a'):
gcc_list.append(cfile)
elif not cfile.endswith('.c') and not cfile.endswith('.cc') and not cfile.endswith('.m') and not cfile.endswith('.o'):
elif not cfile.endswith('.c') and not cfile.endswith('.cc') and not cfile.endswith('.m') and not cfile.endswith('.go') and not cfile.endswith('.o'):
gcc_list.append(path + '/' + cfile + '.c')
else:
if cfile.endswith('.go'):
p_cflags.append('-Wno-error')
gcc_list.append(path + '/' + cfile)
for bfile in up.get('BINARY_LIST', []):
try: