mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec954b8aa7 | ||
|
|
95d20e9f48 | ||
|
|
165aad8cd0 | ||
|
|
29c339a3c3 | ||
|
|
12afba035b | ||
|
|
eeb203afd4 | ||
|
|
6a18d10c56 | ||
|
|
d1383d7749 | ||
|
|
0abbabbe10 | ||
|
|
ea44525c22 | ||
|
|
2396c7cf31 | ||
|
|
4805a9c219 | ||
|
|
882cdcc2b6 | ||
|
|
59c8bb51b4 | ||
|
|
3c2350f5ad | ||
|
|
422e958fe3 | ||
|
|
4d9c7809d6 | ||
|
|
6b3d8ea146 | ||
|
|
b5d8538fe8 | ||
|
|
47796b315e | ||
|
|
222bcd8fdc | ||
|
|
f92b800a7c | ||
|
|
dec2b234f8 | ||
|
|
3dbd7e3115 | ||
|
|
09d8747918 | ||
|
|
fa78fd915b | ||
|
|
db56141485 | ||
|
|
7685af4652 | ||
|
|
21cb62db6c | ||
|
|
c62aa8e7ed | ||
|
|
4765965d8e | ||
|
|
556feaef2c | ||
|
|
799b8a22e0 | ||
|
|
2336580164 | ||
|
|
ca4f30c003 | ||
|
|
d7d0a71d87 | ||
|
|
44b92f1578 | ||
|
|
abed95362f | ||
|
|
72ecc217f7 | ||
|
|
1405d01d50 | ||
|
|
def65c4793 | ||
|
|
26386909de | ||
|
|
2d4e04059a | ||
|
|
ac557739c2 | ||
|
|
73bfc20ba1 | ||
|
|
6d5ae96d50 | ||
|
|
20b5b7b0dc | ||
|
|
82c5afd0c7 | ||
|
|
ec14f5b0fe | ||
|
|
d93bdcb7b4 | ||
|
|
b68ffc842d | ||
|
|
0326c1d508 | ||
|
|
42f45bfbf9 | ||
|
|
d018d3af99 | ||
|
|
42afc476d7 | ||
|
|
b5037d3f0f | ||
|
|
065dd7cfff | ||
|
|
7909e092b5 | ||
|
|
9da53f5fd4 | ||
|
|
025cb7744e | ||
|
|
e48a3ff1b7 | ||
|
|
2be371003c | ||
|
|
60d940e301 | ||
|
|
96c56cd8d5 | ||
|
|
4184619f7b | ||
|
|
50a8ec8a19 | ||
|
|
79c702278a | ||
|
|
8fc41a4c85 | ||
|
|
9c6455252d | ||
|
|
83e41844f3 | ||
|
|
2cc17d6b11 | ||
|
|
14057b72c8 | ||
|
|
faf72b6a77 | ||
|
|
963afa5174 | ||
|
|
ce8ff8c45f | ||
|
|
5ae742e8e1 | ||
|
|
60f6572985 | ||
|
|
4ea34c63d2 | ||
|
|
5699d21aa7 | ||
|
|
dda8d25495 | ||
|
|
d4f690322c | ||
|
|
4f2f30d1e5 | ||
|
|
d3b28e7956 |
@@ -8,3 +8,9 @@ clean:
|
||||
|
||||
check:
|
||||
$(PYTHON) uwsgiconfig.py --check
|
||||
|
||||
plugin.%:
|
||||
$(PYTHON) uwsgiconfig.py --plugin plugins/$* $(PROFILE)
|
||||
|
||||
%:
|
||||
$(PYTHON) uwsgiconfig.py --build $@
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
@@ -6,7 +6,6 @@ zeromq = auto
|
||||
ssl = auto
|
||||
pcre = auto
|
||||
routing = auto
|
||||
matheval = auto
|
||||
debug = false
|
||||
unbit = false
|
||||
xml_implementation = libxml2
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = gccgo
|
||||
inherit = base
|
||||
@@ -1,4 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = glusterfs
|
||||
inherit = base
|
||||
matheval = false
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
[uwsgi]
|
||||
main_plugin = go
|
||||
inherit = base
|
||||
bin_name = libuwsgi.so
|
||||
as_shared_library = true
|
||||
@@ -6,7 +6,6 @@ zeromq = false
|
||||
ssl = false
|
||||
pcre = false
|
||||
routing = false
|
||||
matheval = false
|
||||
debug = false
|
||||
unbit = false
|
||||
xml_implementation = none
|
||||
|
||||
+5
-5
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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())
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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},
|
||||
|
||||
};
|
||||
|
||||
@@ -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
@@ -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
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
@@ -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;
|
||||
|
||||
/*
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='matheval'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lmatheval']
|
||||
GCC_LIST = ['math']
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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
@@ -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();
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user