mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6adbc37a31 | ||
|
|
688d3fff8c | ||
|
|
c0b079deb0 | ||
|
|
9b30c8683b | ||
|
|
9113812b0d | ||
|
|
1abe9f2d12 | ||
|
|
9a37b3653f | ||
|
|
65ad341a31 | ||
|
|
bd31548903 | ||
|
|
dd536cf7ea | ||
|
|
efa27dfc6c | ||
|
|
91b14e0b34 | ||
|
|
74b3d25bcf | ||
|
|
3857e26e4c | ||
|
|
c7d3a27225 | ||
|
|
4f50b4aafc | ||
|
|
d172fb4909 | ||
|
|
c842bb4917 | ||
|
|
d6da6848be | ||
|
|
b1caf56f49 | ||
|
|
00c243bcce | ||
|
|
575dd6beee | ||
|
|
645d021d73 | ||
|
|
0ca320e5fd | ||
|
|
7879a010e8 | ||
|
|
43dd1029ad | ||
|
|
ce7d84b865 | ||
|
|
7ab1795075 | ||
|
|
e1ce4e1011 | ||
|
|
0c02a5104a | ||
|
|
0e244fc59c | ||
|
|
5d6086c84a | ||
|
|
a45be4f7a9 | ||
|
|
dd63bef92e | ||
|
|
621a05d879 | ||
|
|
b857690caf | ||
|
|
edb0a72dfd | ||
|
|
da4af442ad | ||
|
|
04ff580075 | ||
|
|
5925db13cf | ||
|
|
d283fd1aae | ||
|
|
345b22d8f0 | ||
|
|
b8fc89166d | ||
|
|
50ffb9d258 | ||
|
|
9ae1b26d52 | ||
|
|
f281d21a1b | ||
|
|
b9a2b92005 | ||
|
|
92a26d4ff6 | ||
|
|
51360416a7 | ||
|
|
c7bc98a50c | ||
|
|
b4b5c0175a | ||
|
|
7ed3eb36ee | ||
|
|
05c475f597 | ||
|
|
c750dfc1e3 | ||
|
|
01b14f4395 | ||
|
|
46d7d4bf1d | ||
|
|
02d76f12e0 | ||
|
|
719860a349 | ||
|
|
5cce0935fd | ||
|
|
24ef2a838f | ||
|
|
8aa739b4b2 | ||
|
|
9221e1953e | ||
|
|
18592fb2bd | ||
|
|
fc80eeb581 | ||
|
|
bc19b58681 | ||
|
|
8f2202eab5 | ||
|
|
aa2ecf14df | ||
|
|
43f5792826 | ||
|
|
36ff37e12c | ||
|
|
6dd6f961e8 | ||
|
|
5dd5d92ffb | ||
|
|
64f1b844bd | ||
|
|
e562c4691d | ||
|
|
1cbab74f0e | ||
|
|
3053fdb25a | ||
|
|
f11f542242 | ||
|
|
32ddf10cfa | ||
|
|
1b54be396c | ||
|
|
f81a4f9736 | ||
|
|
048b339593 | ||
|
|
081a6b90bf | ||
|
|
97f1b6d649 | ||
|
|
593aba2b19 | ||
|
|
47c9e5e3f0 | ||
|
|
bca8bc0c4d | ||
|
|
a67dfdd542 | ||
|
|
d1bbe7e3f9 | ||
|
|
442c982aff | ||
|
|
a2f50ccf2e | ||
|
|
b1c5fef0dc | ||
|
|
f6d8ac52f4 | ||
|
|
94e4fcbfe1 | ||
|
|
c9e7b0f48e | ||
|
|
2f932d8ca0 | ||
|
|
c517320f7a | ||
|
|
b0dae66264 | ||
|
|
0d87ed7298 | ||
|
|
fd3291b11f | ||
|
|
e5ac5d6352 | ||
|
|
403bd604e2 | ||
|
|
045d8947ae | ||
|
|
a9f2c71863 | ||
|
|
b504a1ebe8 | ||
|
|
f05ce0d2fc | ||
|
|
a2f3c716b1 | ||
|
|
2d7ca36f60 | ||
|
|
5370e535dd | ||
|
|
092767c29f | ||
|
|
4e119e6838 | ||
|
|
87ef444ea6 | ||
|
|
714be76f9b | ||
|
|
af0f0da8c2 | ||
|
|
8407372801 | ||
|
|
d19c4e84fc | ||
|
|
3342852a9a | ||
|
|
586a02d849 | ||
|
|
188dad744a | ||
|
|
6cf3bbea69 | ||
|
|
04736d371e | ||
|
|
cc9151f89e |
@@ -1,9 +1,5 @@
|
||||
*.o
|
||||
*.py[co]
|
||||
*.class
|
||||
*.jar
|
||||
|
||||
/uwsgi
|
||||
/uwsgibuild.*
|
||||
|
||||
/t/ring/target
|
||||
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
language: c
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
|
||||
script:
|
||||
- echo -e "\n\n>>> Building uWSGI binary"
|
||||
- /usr/bin/python uwsgiconfig.py --build travis
|
||||
- echo -e "\n\n>>> Building python26 plugin"
|
||||
- /usr/bin/python2.6 -V
|
||||
- /usr/bin/python2.6 uwsgiconfig.py --plugin plugins/python base python26
|
||||
- echo -e "\n\n>>> Building python27 plugin"
|
||||
- /usr/bin/python2.7 -V
|
||||
- /usr/bin/python2.7 uwsgiconfig.py --plugin plugins/python base python27
|
||||
- echo -e "\n\n>>> Building python31 plugin"
|
||||
- /usr/bin/python3.1 -V
|
||||
- /usr/bin/python3.1 uwsgiconfig.py --plugin plugins/python base python31
|
||||
- echo -e "\n\n>>> Building python32 plugin"
|
||||
- /usr/bin/python3.2 -V
|
||||
- /usr/bin/python3.2 uwsgiconfig.py --plugin plugins/python base python32
|
||||
- echo -e "\n\n>>> Building python33 plugin"
|
||||
- /usr/bin/python3.3 -V
|
||||
- /usr/bin/python3.3 uwsgiconfig.py --plugin plugins/python base python33
|
||||
- echo -e "\n\n>>> Building rack 1.8.7 plugin"
|
||||
- /usr/bin/ruby1.8 -v
|
||||
- UWSGICONFIG_RUBYPATH=/usr/bin/ruby1.8 /usr/bin/python uwsgiconfig.py --plugin plugins/rack base rack187
|
||||
- echo -e "\n\n>>> Building rack 1.9.1 plugin"
|
||||
- /usr/bin/ruby1.9.1 -v
|
||||
- UWSGICONFIG_RUBYPATH=/usr/bin/ruby1.9.1 /usr/bin/python uwsgiconfig.py --plugin plugins/rack base rack191
|
||||
- echo -e "\n\n>>> Building cgi plugin"
|
||||
- /usr/bin/python uwsgiconfig.py --plugin plugins/cgi base
|
||||
- echo -e "\n\n>>> Building dummy plugin"
|
||||
- /usr/bin/python uwsgiconfig.py --plugin plugins/dummy base
|
||||
- echo -e "\n\n>>> Building done, starting tests"
|
||||
- ./tests/travis.sh
|
||||
|
||||
before_install:
|
||||
- sudo add-apt-repository -y ppa:fkrull/deadsnakes
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -qqyf python2.6-dev python2.7-dev python3.1-dev python3.2-dev python3.3-dev rubygems1.8 ruby1.8-dev ruby1.9.1-dev
|
||||
- sudo apt-get install -qqyf libxml2-dev libpcre3-dev libcap2-dev
|
||||
- sudo apt-get install -qqyf curl
|
||||
|
||||
@@ -21,4 +21,3 @@ Roy Marples
|
||||
Aarni Koskela
|
||||
C Anthony Risinger
|
||||
Stephen Pierce
|
||||
Mingli Yuan
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
surprise i am empty !
|
||||
|
||||
Look in the online documentation on https://uwsgi-docs.readthedocs.org/en/latest/
|
||||
Look in the online documentation on http://projects.unbit.it/uwsgi/
|
||||
|
||||
+43
-40
@@ -1,36 +1,6 @@
|
||||
/*
|
||||
|
||||
*** mod_proxy_uwsgi ***
|
||||
|
||||
Copyright 2009-2013 Unbit S.a.s. <info@unbit.it>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
|
||||
To build:
|
||||
|
||||
apxs2 -i -c mod_proxy_uwsgi.c
|
||||
|
||||
To use:
|
||||
|
||||
LoadModule proxy_uwsgi_module /usr/lib/apache2/modules/mod_proxy_uwsgi.so
|
||||
ProxyPass / uwsgi://127.0.0.1:3031/
|
||||
|
||||
Docs:
|
||||
|
||||
http://uwsgi-docs.readthedocs.org/en/latest/Apache.html#mod-proxy-uwsgi
|
||||
apxs2 -i -c mod_proxy_uwsgi.c
|
||||
|
||||
*/
|
||||
#define APR_WANT_MEMFUNC
|
||||
@@ -217,6 +187,28 @@ static int uwsgi_send_body(request_rec *r, proxy_conn_rec *conn)
|
||||
return OK;
|
||||
}
|
||||
|
||||
static
|
||||
apr_status_t ap_proxygetline(apr_bucket_brigade *bb, char *s, int n, request_rec *r,
|
||||
int fold, int *writen)
|
||||
{
|
||||
char *tmp_s = s;
|
||||
apr_status_t rv;
|
||||
apr_size_t len;
|
||||
|
||||
rv = ap_rgetline(&tmp_s, n, &len, r, fold, bb);
|
||||
apr_brigade_cleanup(bb);
|
||||
|
||||
if (rv == APR_SUCCESS) {
|
||||
*writen = (int) len;
|
||||
} else if (rv == APR_ENOSPC) {
|
||||
*writen = n;
|
||||
} else {
|
||||
*writen = -1;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_conf *conf)
|
||||
{
|
||||
|
||||
@@ -236,7 +228,11 @@ static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_
|
||||
|
||||
apr_bucket_brigade *bb = apr_brigade_create(r->pool, c->bucket_alloc);
|
||||
|
||||
len = ap_getline(buffer, sizeof(buffer), rp, 1);
|
||||
|
||||
rc = ap_proxygetline(bb, buffer, sizeof(buffer), rp, 0, &len);
|
||||
if (len == 0) {
|
||||
rc = ap_proxygetline(bb, buffer, sizeof(buffer), rp, 0, &len);
|
||||
}
|
||||
|
||||
if (len <= 0) {
|
||||
// oops
|
||||
@@ -245,11 +241,25 @@ static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_
|
||||
|
||||
backend->worker->s->read += len;
|
||||
|
||||
if (!apr_date_checkmask(buffer, "HTTP/#.# ###*") || len >= sizeof(buffer)-1) {
|
||||
if (!apr_date_checkmask(buffer, "HTTP/#.# ###*")) {
|
||||
// oops
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
int major, minor;
|
||||
|
||||
major = buffer[5] - '0';
|
||||
minor = buffer[7] - '0';
|
||||
|
||||
/* If not an HTTP/1 message or
|
||||
* if the status line was > 8192 bytes
|
||||
*/
|
||||
if ((major != 1) || (len >= sizeof(buffer)-1)) {
|
||||
return ap_proxyerror(r, HTTP_BAD_GATEWAY,
|
||||
apr_pstrcat(r->pool, "Corrupt status line returned by remote "
|
||||
"server: ", buffer, NULL));
|
||||
}
|
||||
|
||||
char keepchar = buffer[12];
|
||||
buffer[12] = '\0';
|
||||
r->status = atoi(&buffer[9]);
|
||||
@@ -343,13 +353,6 @@ static int uwsgi_handler(request_rec *r, proxy_worker *worker,
|
||||
if (u_path_info[0] != '/') {
|
||||
delta = 1;
|
||||
}
|
||||
int decode_status = ap_unescape_url(url+w_len-delta);
|
||||
if (decode_status) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||
"unable to decode uri: %s",
|
||||
url+w_len-delta);
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
apr_table_add(r->subprocess_env, "PATH_INFO", url+w_len-delta);
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
*** uWSGI/mod_uwsgi ***
|
||||
|
||||
Copyright 2009-2013 Unbit S.a.s. <info@unbit.it>
|
||||
Copyright 2009-2012 Unbit S.a.s. <info@unbit.it>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
object file for embedded files will be put here
|
||||
+7
-1
@@ -6,7 +6,13 @@ json = auto
|
||||
sqlite3 = auto
|
||||
zeromq = auto
|
||||
snmp = true
|
||||
spooler = true
|
||||
embedded = true
|
||||
ssl = auto
|
||||
udp = true
|
||||
multicast = true
|
||||
threading = true
|
||||
minterpreters = true
|
||||
async = true
|
||||
ldap = auto
|
||||
pcre = auto
|
||||
@@ -23,7 +29,7 @@ plugins =
|
||||
bin_name = uwsgi
|
||||
append_version =
|
||||
plugin_dir = .
|
||||
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http, logfile, router_cache, rawrouter, router_static, sslrouter
|
||||
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http, logfile, router_cache, rawrouter
|
||||
as_shared_library = false
|
||||
|
||||
locking = auto
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
[uwsgi]
|
||||
# pypy,jvm,ring,jwsgi
|
||||
main_plugin = erlang,psgi,rack,lua,python,gevent,php,cgi,mono,pyerl,go
|
||||
inherit = base
|
||||
@@ -1,3 +0,0 @@
|
||||
[uwsgi]
|
||||
main_plugin = jvm,jwsgi
|
||||
inherit = base
|
||||
@@ -1,3 +0,0 @@
|
||||
[uwsgi]
|
||||
main_plugin = mono
|
||||
inherit = base
|
||||
@@ -1,3 +0,0 @@
|
||||
[uwsgi]
|
||||
main_plugin = jvm,ring
|
||||
inherit = base
|
||||
@@ -1,3 +0,0 @@
|
||||
[uwsgi]
|
||||
main_plugin =
|
||||
inherit = base
|
||||
@@ -5,6 +5,14 @@ yaml = true
|
||||
json = false
|
||||
sqlite3 = false
|
||||
zeromq = false
|
||||
snmp = false
|
||||
spooler = true
|
||||
embedded = true
|
||||
udp = true
|
||||
multicast = false
|
||||
threading = true
|
||||
minterpreters = true
|
||||
async = true
|
||||
ldap = true
|
||||
pcre = true
|
||||
routing = true
|
||||
|
||||
+1
-4
@@ -1,15 +1,12 @@
|
||||
use POSIX;
|
||||
use IO::Socket::INET;
|
||||
use IO::Socket::INET6;
|
||||
use IO::Socket::UNIX;
|
||||
|
||||
my $s = IO::Socket::INET->new(LocalAddr => '127.0.0.1', LocalPort => 1717, Proto => 'tcp', Reuse => 1);
|
||||
my $s2 = IO::Socket::INET->new(LocalAddr => '127.0.0.1', LocalPort => 3022, Proto => 'tcp', Reuse => 1);
|
||||
my $s3 = IO::Socket::INET6->new(LocalAddr => '::', LocalPort => 3017, Proto => 'tcp', Reuse => 1);
|
||||
my $s4 = IO::Socket::UNIX->new(Local => '/tmp/u.sock', Listen => 1);
|
||||
|
||||
dup2($s->fileno, 17);
|
||||
dup2($s2->fileno, 22);
|
||||
dup2($s3->fileno, 30);
|
||||
dup2($s4->fileno, 0);
|
||||
exec './uwsgi','-M', '--socket','fd://17', '--http-socket','fd://22', '--socket','fd://30','--stats',':5001';
|
||||
exec './uwsgi','-M', '--socket','fd://17', '--http-socket','fd://22', '--socket','fd://30';
|
||||
|
||||
+1
-68
@@ -136,7 +136,6 @@ static struct uwsgi_alarm_instance *uwsgi_alarm_get_instance(char *name) {
|
||||
}
|
||||
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
|
||||
|
||||
struct uwsgi_alarm_log *old_ual = NULL, *ual = uwsgi.alarm_logs;
|
||||
@@ -163,10 +162,8 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
|
||||
char *p = strtok(list, ",");
|
||||
while (p) {
|
||||
struct uwsgi_alarm_instance *uai = uwsgi_alarm_get_instance(p);
|
||||
if (!uai) {
|
||||
free(list);
|
||||
if (!uai)
|
||||
return -1;
|
||||
}
|
||||
struct uwsgi_alarm_ll *old_uall = NULL, *uall = ual->alarms;
|
||||
while (uall) {
|
||||
old_uall = uall;
|
||||
@@ -183,38 +180,12 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
|
||||
}
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
free(list);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void uwsgi_alarm_thread_loop(struct uwsgi_thread *ut) {
|
||||
char *buf = uwsgi_malloc(uwsgi.alarm_msg_size + sizeof(long));
|
||||
for (;;) {
|
||||
int interesting_fd = -1;
|
||||
int ret = event_queue_wait(ut->queue, -1, &interesting_fd);
|
||||
if (ret > 0) {
|
||||
ssize_t len = read(ut->pipe[1], buf, uwsgi.alarm_msg_size + sizeof(long));
|
||||
if (len > (ssize_t)(sizeof(long) + 1)) {
|
||||
size_t msg_size = len - sizeof(long);
|
||||
char *msg = buf + sizeof(long);
|
||||
long ptr = 0;
|
||||
memcpy(&ptr, buf, sizeof(long));
|
||||
struct uwsgi_alarm_instance *uai = (struct uwsgi_alarm_instance *) ptr;
|
||||
if (!uai)
|
||||
break;
|
||||
uwsgi_alarm_run(uai, msg, msg_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
|
||||
// initialize alarms, instances and log regexps
|
||||
void uwsgi_alarms_init() {
|
||||
|
||||
if (!uwsgi.master_process) return;
|
||||
|
||||
// first of all, create instance of alarms
|
||||
struct uwsgi_string_list *usl = uwsgi.alarm_list;
|
||||
while (usl) {
|
||||
@@ -241,9 +212,6 @@ void uwsgi_alarms_init() {
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
if (!uwsgi.alarm_instances) return;
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
// then map log-alarm
|
||||
usl = uwsgi.alarm_logs_list;
|
||||
while (usl) {
|
||||
@@ -263,20 +231,8 @@ void uwsgi_alarms_init() {
|
||||
|
||||
usl = usl->next;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void uwsgi_alarm_thread_start() {
|
||||
if (!uwsgi.alarm_instances) return;
|
||||
// start the alarm_thread
|
||||
uwsgi.alarm_thread = uwsgi_thread_new(uwsgi_alarm_thread_loop);
|
||||
if (!uwsgi.alarm_thread) {
|
||||
uwsgi_log("unable to spawn alarm thread\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
// check if a log should raise an alarm
|
||||
void uwsgi_alarm_log_check(char *msg, size_t len) {
|
||||
if (!uwsgi_strncmp(msg, len, "[uwsgi-alarm", 12))
|
||||
@@ -294,7 +250,6 @@ void uwsgi_alarm_log_check(char *msg, size_t len) {
|
||||
ual = ual->next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// call the alarm func
|
||||
void uwsgi_alarm_run(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
|
||||
@@ -310,7 +265,6 @@ void uwsgi_alarm_run(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
|
||||
uai->last_msg_size = len;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
// call the alarms mapped to a log line
|
||||
void uwsgi_alarm_log_run(struct uwsgi_alarm_log *ual, char *msg, size_t len) {
|
||||
struct uwsgi_alarm_ll *uall = ual->alarms;
|
||||
@@ -319,24 +273,3 @@ void uwsgi_alarm_log_run(struct uwsgi_alarm_log *ual, char *msg, size_t len) {
|
||||
uall = uall->next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// this is the api function workers,mules and whatever you want can call from code
|
||||
void uwsgi_alarm_trigger(char *alarm_instance_name, char *msg, size_t len) {
|
||||
if (!uwsgi.alarm_thread) return;
|
||||
if (len > uwsgi.alarm_msg_size) return;
|
||||
struct uwsgi_alarm_instance *uai = uwsgi_alarm_get_instance(alarm_instance_name);
|
||||
if (!uai) return;
|
||||
|
||||
struct iovec iov[2];
|
||||
iov[0].iov_base = &uai;
|
||||
iov[0].iov_len = sizeof(long);
|
||||
iov[1].iov_base = msg;
|
||||
iov[1].iov_len = len;
|
||||
|
||||
// now send the message to the alarm thread
|
||||
if (writev(uwsgi.alarm_thread->pipe[0], iov, 2) != (ssize_t) (len+sizeof(long))) {
|
||||
uwsgi_error("[uwsgi-alarm-error] uwsgi_alarm_trigger()/writev()");
|
||||
}
|
||||
}
|
||||
|
||||
+37
-64
@@ -1,14 +1,7 @@
|
||||
#include <uwsgi.h>
|
||||
#include "uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
void uwsgi_async_queue_is_full(time_t now) {
|
||||
if (now > uwsgi.async_queue_is_full) {
|
||||
uwsgi_log_verbose("[DANGER] async queue is full !!!\n");
|
||||
uwsgi.async_queue_is_full = now;
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_async_init() {
|
||||
int i;
|
||||
|
||||
@@ -40,7 +33,7 @@ struct wsgi_request *find_wsgi_req_by_fd(int fd) {
|
||||
return uwsgi.async_waiting_fd_table[fd];
|
||||
}
|
||||
|
||||
static void runqueue_remove(struct uwsgi_async_request *u_request) {
|
||||
void runqueue_remove(struct uwsgi_async_request *u_request) {
|
||||
|
||||
struct uwsgi_async_request *parent = u_request->prev;
|
||||
struct uwsgi_async_request *child = u_request->next;
|
||||
@@ -65,7 +58,7 @@ static void runqueue_remove(struct uwsgi_async_request *u_request) {
|
||||
uwsgi.async_runqueue_cnt--;
|
||||
}
|
||||
|
||||
static void runqueue_push(struct wsgi_request *wsgi_req) {
|
||||
void runqueue_push(struct wsgi_request *wsgi_req) {
|
||||
|
||||
struct uwsgi_async_request *uar;
|
||||
|
||||
@@ -103,9 +96,10 @@ struct wsgi_request *find_first_available_wsgi_req() {
|
||||
return wsgi_req;
|
||||
}
|
||||
|
||||
static void async_expire_timeouts(uint64_t now) {
|
||||
void async_expire_timeouts() {
|
||||
|
||||
struct wsgi_request *wsgi_req;
|
||||
uint64_t current_time = (uint64_t) uwsgi_now();
|
||||
struct uwsgi_async_fd *uaf = NULL, *current_uaf;
|
||||
|
||||
struct uwsgi_rb_timer *urbt;
|
||||
@@ -117,7 +111,7 @@ static void async_expire_timeouts(uint64_t now) {
|
||||
if (urbt == NULL)
|
||||
return;
|
||||
|
||||
if (urbt->value <= now) {
|
||||
if (urbt->value <= current_time) {
|
||||
wsgi_req = (struct wsgi_request *) urbt->data;
|
||||
// timeout expired
|
||||
wsgi_req->async_timed_out = 1;
|
||||
@@ -144,12 +138,12 @@ static void async_expire_timeouts(uint64_t now) {
|
||||
|
||||
}
|
||||
|
||||
int async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
|
||||
void async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
|
||||
|
||||
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
|
||||
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
return;
|
||||
|
||||
// find first slot
|
||||
while (uad) {
|
||||
@@ -174,23 +168,8 @@ int async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
|
||||
async_add_timeout(wsgi_req, timeout);
|
||||
}
|
||||
uwsgi.async_waiting_fd_table[fd] = wsgi_req;
|
||||
wsgi_req->async_force_again = 1;
|
||||
return event_queue_add_fd_read(uwsgi.async_queue, fd);
|
||||
}
|
||||
event_queue_add_fd_read(uwsgi.async_queue, fd);
|
||||
|
||||
static int async_wait_fd_read(int fd, int timeout) {
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
if (async_add_fd_read(wsgi_req, fd, timeout)) {
|
||||
return -1;
|
||||
}
|
||||
if (uwsgi.schedule_to_main) {
|
||||
uwsgi.schedule_to_main(wsgi_req);
|
||||
}
|
||||
if (wsgi_req->async_timed_out) {
|
||||
wsgi_req->async_timed_out = 0;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
|
||||
@@ -201,12 +180,12 @@ void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
|
||||
|
||||
}
|
||||
|
||||
int async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
|
||||
void async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
|
||||
|
||||
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
|
||||
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
return;
|
||||
|
||||
// find first slot
|
||||
while (uad) {
|
||||
@@ -232,27 +211,12 @@ int async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
|
||||
}
|
||||
|
||||
uwsgi.async_waiting_fd_table[fd] = wsgi_req;
|
||||
wsgi_req->async_force_again = 1;
|
||||
return event_queue_add_fd_write(uwsgi.async_queue, fd);
|
||||
}
|
||||
event_queue_add_fd_write(uwsgi.async_queue, fd);
|
||||
|
||||
static int async_wait_fd_write(int fd, int timeout) {
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
if (async_add_fd_write(wsgi_req, fd, timeout)) {
|
||||
return -1;
|
||||
}
|
||||
if (uwsgi.schedule_to_main) {
|
||||
uwsgi.schedule_to_main(wsgi_req);
|
||||
}
|
||||
if (wsgi_req->async_timed_out) {
|
||||
wsgi_req->async_timed_out = 0;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void async_schedule_to_req(void) {
|
||||
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh->modifier1]->request(uwsgi.wsgi_req);
|
||||
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->request(uwsgi.wsgi_req);
|
||||
}
|
||||
|
||||
void async_loop() {
|
||||
@@ -269,7 +233,7 @@ void async_loop() {
|
||||
int is_a_new_connection;
|
||||
int proto_parser_status;
|
||||
|
||||
uint64_t now;
|
||||
time_t now, last_now = 0;
|
||||
|
||||
static struct uwsgi_async_request *current_request = NULL, *next_async_request = NULL;
|
||||
|
||||
@@ -279,9 +243,6 @@ void async_loop() {
|
||||
uwsgi.async_runqueue = NULL;
|
||||
uwsgi.async_runqueue_cnt = 0;
|
||||
|
||||
uwsgi.wait_write_hook = async_wait_fd_write;
|
||||
uwsgi.wait_read_hook = async_wait_fd_read;
|
||||
|
||||
if (uwsgi.signal_socket > -1) {
|
||||
event_queue_add_fd_read(uwsgi.async_queue, uwsgi.signal_socket);
|
||||
event_queue_add_fd_read(uwsgi.async_queue, uwsgi.my_signal_socket);
|
||||
@@ -291,22 +252,20 @@ void async_loop() {
|
||||
if (!uwsgi.schedule_to_req)
|
||||
uwsgi.schedule_to_req = async_schedule_to_req;
|
||||
|
||||
if (!uwsgi.schedule_to_main) {
|
||||
uwsgi_log("*** WARNING *** async mode without coroutine/greenthread engine loaded !!!\n");
|
||||
}
|
||||
|
||||
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
|
||||
|
||||
now = (uint64_t) uwsgi_now();
|
||||
if (uwsgi.async_runqueue_cnt) {
|
||||
timeout = 0;
|
||||
}
|
||||
else {
|
||||
min_timeout = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts, NULL);
|
||||
if (uwsgi.async_runqueue_cnt) {
|
||||
timeout = 0;
|
||||
}
|
||||
if (min_timeout) {
|
||||
timeout = min_timeout->value - now;
|
||||
timeout = min_timeout->value - uwsgi_now();
|
||||
if (timeout <= 0) {
|
||||
async_expire_timeouts(now);
|
||||
async_expire_timeouts();
|
||||
timeout = 0;
|
||||
}
|
||||
}
|
||||
@@ -317,10 +276,9 @@ void async_loop() {
|
||||
|
||||
uwsgi.async_nevents = event_queue_wait_multi(uwsgi.async_queue, timeout, events, 64);
|
||||
|
||||
now = (uint64_t) uwsgi_now();
|
||||
// timeout ???
|
||||
if (uwsgi.async_nevents == 0) {
|
||||
async_expire_timeouts(now);
|
||||
async_expire_timeouts();
|
||||
}
|
||||
|
||||
|
||||
@@ -347,7 +305,11 @@ void async_loop() {
|
||||
|
||||
uwsgi.wsgi_req = find_first_available_wsgi_req();
|
||||
if (uwsgi.wsgi_req == NULL) {
|
||||
uwsgi_async_queue_is_full((time_t)now);
|
||||
now = uwsgi_now();
|
||||
if (now > last_now) {
|
||||
uwsgi_log("async queue is full !!!\n");
|
||||
last_now = now;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -357,6 +319,18 @@ void async_loop() {
|
||||
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
|
||||
break;
|
||||
}
|
||||
// on linux we do not need to reset the socket to blocking state
|
||||
#ifndef __linux__
|
||||
/* re-set blocking socket */
|
||||
int arg = uwsgi_sock->arg;
|
||||
arg &= (~O_NONBLOCK);
|
||||
if (fcntl(uwsgi.wsgi_req->poll.fd, F_SETFL, arg) < 0) {
|
||||
uwsgi_error("fcntl()");
|
||||
uwsgi.async_queue_unused_ptr++;
|
||||
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (wsgi_req_async_recv(uwsgi.wsgi_req)) {
|
||||
uwsgi.async_queue_unused_ptr++;
|
||||
@@ -432,7 +406,6 @@ void async_loop() {
|
||||
|
||||
// put the request in the runqueue again
|
||||
runqueue_push(uwsgi.wsgi_req);
|
||||
// avoid managing other enqueued events...
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+8
-212
@@ -48,50 +48,6 @@ int uwsgi_buffer_ensure(struct uwsgi_buffer *ub, size_t len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_buffer_insert(struct uwsgi_buffer *ub, size_t pos, char *buf, size_t len) {
|
||||
size_t to_move = (ub->pos-pos);
|
||||
if (uwsgi_buffer_ensure(ub, len)) return -1;
|
||||
memmove(ub->buf+pos+len, ub->buf+pos, to_move);
|
||||
memcpy(ub->buf+pos, buf, len);
|
||||
ub->pos += len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_buffer_insert_chunked(struct uwsgi_buffer *ub, size_t pos, size_t len) {
|
||||
// 0xFFFFFFFFFFFFFFFF\r\n\0
|
||||
char chunked[19];
|
||||
int ret = snprintf(chunked, 19, "%X\r\n", (unsigned int) len);
|
||||
if (ret <= 0 || ret > 19) {
|
||||
return -1;
|
||||
}
|
||||
return uwsgi_buffer_insert(ub, pos, chunked, ret);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_append_chunked(struct uwsgi_buffer *ub, size_t len) {
|
||||
// 0xFFFFFFFFFFFFFFFF\r\n\0
|
||||
char chunked[19];
|
||||
int ret = snprintf(chunked, 19, "%X\r\n", (unsigned int) len);
|
||||
if (ret <= 0 || ret > 19) {
|
||||
return -1;
|
||||
}
|
||||
return uwsgi_buffer_append(ub, chunked, ret);
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_buffer_decapitate(struct uwsgi_buffer *ub, size_t len) {
|
||||
if (len > ub->pos) return -1;
|
||||
memmove(ub->buf, ub->buf + len, ub->pos-len);
|
||||
ub->pos = ub->pos-len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_buffer_byte(struct uwsgi_buffer *ub, char byte) {
|
||||
return uwsgi_buffer_append(ub, &byte, 1);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_u8(struct uwsgi_buffer *ub, uint8_t u8) {
|
||||
return uwsgi_buffer_append(ub, (char *) &u8, 1);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_append(struct uwsgi_buffer *ub, char *buf, size_t len) {
|
||||
|
||||
@@ -121,173 +77,12 @@ int uwsgi_buffer_append(struct uwsgi_buffer *ub, char *buf, size_t len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_buffer_append_json(struct uwsgi_buffer *ub, char *buf, size_t len) {
|
||||
// need to escape \ and "
|
||||
size_t i;
|
||||
for(i=0;i<len;i++) {
|
||||
if (buf[i] == '"') {
|
||||
if (uwsgi_buffer_append(ub, "\\\"", 2)) return -1;
|
||||
}
|
||||
else if (buf[i] == '\\') {
|
||||
if (uwsgi_buffer_append(ub, "\\\\", 2)) return -1;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_buffer_append(ub, buf+i, 1)) return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_buffer_u16le(struct uwsgi_buffer *ub, uint16_t num) {
|
||||
uint8_t buf[2];
|
||||
buf[0] = (uint8_t) (num & 0xff);
|
||||
buf[1] = (uint8_t) ((num >> 8) & 0xff);
|
||||
return uwsgi_buffer_append(ub, (char *) buf, 2);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_u16be(struct uwsgi_buffer *ub, uint16_t num) {
|
||||
uint8_t buf[2];
|
||||
buf[1] = (uint8_t) (num & 0xff);
|
||||
buf[0] = (uint8_t) ((num >> 8) & 0xff);
|
||||
return uwsgi_buffer_append(ub, (char *) buf, 2);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_u24be(struct uwsgi_buffer *ub, uint32_t num) {
|
||||
uint8_t buf[3];
|
||||
buf[2] = (uint8_t) (num & 0xff);
|
||||
buf[1] = (uint8_t) ((num >> 8) & 0xff);
|
||||
buf[0] = (uint8_t) ((num >> 16) & 0xff);
|
||||
return uwsgi_buffer_append(ub, (char *) buf, 3);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_u32be(struct uwsgi_buffer *ub, uint32_t num) {
|
||||
uint8_t buf[4];
|
||||
buf[3] = (uint8_t) (num & 0xff);
|
||||
buf[2] = (uint8_t) ((num >> 8) & 0xff);
|
||||
buf[1] = (uint8_t) ((num >> 16) & 0xff);
|
||||
buf[0] = (uint8_t) ((num >> 24) & 0xff);
|
||||
return uwsgi_buffer_append(ub, (char *) buf, 4);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_u32le(struct uwsgi_buffer *ub, uint32_t num) {
|
||||
uint8_t buf[4];
|
||||
buf[0] = (uint8_t) (num & 0xff);
|
||||
buf[1] = (uint8_t) ((num >> 8) & 0xff);
|
||||
buf[2] = (uint8_t) ((num >> 16) & 0xff);
|
||||
buf[3] = (uint8_t) ((num >> 24) & 0xff);
|
||||
return uwsgi_buffer_append(ub, (char *) buf, 4);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_u64be(struct uwsgi_buffer *ub, uint64_t num) {
|
||||
uint8_t buf[8];
|
||||
buf[7] = (uint8_t) (num & 0xff);
|
||||
buf[6] = (uint8_t) ((num >> 8) & 0xff);
|
||||
buf[5] = (uint8_t) ((num >> 16) & 0xff);
|
||||
buf[4] = (uint8_t) ((num >> 24) & 0xff);
|
||||
buf[3] = (uint8_t) ((num >> 32) & 0xff);
|
||||
buf[2] = (uint8_t) ((num >> 40) & 0xff);
|
||||
buf[1] = (uint8_t) ((num >> 48) & 0xff);
|
||||
buf[0] = (uint8_t) ((num >> 56) & 0xff);
|
||||
return uwsgi_buffer_append(ub, (char *) buf, 8);
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_buffer_append_ipv4(struct uwsgi_buffer *ub, void *addr) {
|
||||
char ip[INET_ADDRSTRLEN];
|
||||
if (!inet_ntop(AF_INET, addr, ip, INET_ADDRSTRLEN)) {
|
||||
uwsgi_error("uwsgi_buffer_append_ipv4() -> inet_ntop()");
|
||||
return -1;
|
||||
}
|
||||
return uwsgi_buffer_append(ub, ip, strlen(ip));
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_buffer_num64(struct uwsgi_buffer *ub, int64_t num) {
|
||||
char buf[sizeof(UMAX64_STR)+1];
|
||||
int ret = snprintf(buf, sizeof(UMAX64_STR)+1, "%lld", (long long) num);
|
||||
if (ret <= 0 || ret > (int) (sizeof(UMAX64_STR)+1)) {
|
||||
return -1;
|
||||
}
|
||||
return uwsgi_buffer_append(ub, buf, ret);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_append_keyval(struct uwsgi_buffer *ub, char *key, uint16_t keylen, char *val, uint16_t vallen) {
|
||||
if (uwsgi_buffer_u16le(ub, keylen)) return -1;
|
||||
if (uwsgi_buffer_append(ub, key, keylen)) return -1;
|
||||
if (uwsgi_buffer_u16le(ub, vallen)) return -1;
|
||||
return uwsgi_buffer_append(ub, val, vallen);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_append_keyval32(struct uwsgi_buffer *ub, char *key, uint32_t keylen, char *val, uint32_t vallen) {
|
||||
if (uwsgi_buffer_u32be(ub, keylen)) return -1;
|
||||
if (uwsgi_buffer_append(ub, key, keylen)) return -1;
|
||||
if (uwsgi_buffer_u32be(ub, vallen)) return -1;
|
||||
return uwsgi_buffer_append(ub, val, vallen);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_append_keynum(struct uwsgi_buffer *ub, char *key, uint16_t keylen, int64_t num) {
|
||||
char buf[sizeof(UMAX64_STR)+1];
|
||||
int ret = snprintf(buf, (sizeof(UMAX64_STR)+1), "%lld", (long long) num);
|
||||
if (ret <= 0 || ret > (int) (sizeof(UMAX64_STR)+1)) {
|
||||
return -1;
|
||||
}
|
||||
if (uwsgi_buffer_u16le(ub, keylen)) return -1;
|
||||
if (uwsgi_buffer_append(ub, key, keylen)) return -1;
|
||||
if (uwsgi_buffer_u16le(ub, ret)) return -1;
|
||||
return uwsgi_buffer_append(ub, buf, ret);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_append_valnum(struct uwsgi_buffer *ub, int64_t num) {
|
||||
char buf[sizeof(UMAX64_STR)+1];
|
||||
int ret = snprintf(buf, (sizeof(UMAX64_STR)+1), "%lld", (long long) num);
|
||||
if (ret <= 0 || ret > (int) (sizeof(UMAX64_STR)+1)) {
|
||||
return -1;
|
||||
}
|
||||
if (uwsgi_buffer_u16le(ub, ret)) return -1;
|
||||
return uwsgi_buffer_append(ub, buf, ret);
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_buffer_append_keyipv4(struct uwsgi_buffer *ub, char *key, uint16_t keylen, void *addr) {
|
||||
if (uwsgi_buffer_u16le(ub, keylen)) return -1;
|
||||
if (uwsgi_buffer_append(ub, key, keylen)) return -1;
|
||||
if (uwsgi_buffer_u16le(ub, 15)) return -1;
|
||||
char *ptr = ub->buf + (ub->pos - 2);
|
||||
if (uwsgi_buffer_append_ipv4(ub, addr)) return -1;
|
||||
// fix the size
|
||||
*ptr = ((ub->buf+ub->pos) - (ptr+2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_buffer_append_base64(struct uwsgi_buffer *ub, char *s, size_t len) {
|
||||
size_t b64_len = 0;
|
||||
char *b64 = uwsgi_base64_encode(s, len, &b64_len);
|
||||
if (!b64) return -1;
|
||||
int ret = uwsgi_buffer_append(ub, b64, b64_len);
|
||||
free(b64);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_buffer_destroy(struct uwsgi_buffer *ub) {
|
||||
if (ub->buf)
|
||||
free(ub->buf);
|
||||
free(ub);
|
||||
}
|
||||
|
||||
ssize_t uwsgi_buffer_write_simple(struct wsgi_request *wsgi_req, struct uwsgi_buffer *ub) {
|
||||
size_t remains = ub->pos;
|
||||
while(remains) {
|
||||
ssize_t len = write(wsgi_req->fd, ub->buf + (ub->pos - remains), remains);
|
||||
if (len <= 0) {
|
||||
return len;
|
||||
}
|
||||
remains -= len;
|
||||
}
|
||||
|
||||
return ub->pos;
|
||||
}
|
||||
|
||||
int uwsgi_buffer_send(struct uwsgi_buffer *ub, int fd) {
|
||||
size_t remains = ub->pos;
|
||||
char *ptr = ub->buf;
|
||||
@@ -320,11 +115,12 @@ int uwsgi_buffer_send(struct uwsgi_buffer *ub, int fd) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_buffer_set_uh(struct uwsgi_buffer *ub, uint8_t modifier1, uint8_t modifier2) {
|
||||
if (ub->pos < 4) return -1;
|
||||
ub->buf[0] = modifier1;
|
||||
ub->buf[1] = (uint8_t) ((ub->pos - 4) & 0xff);
|
||||
ub->buf[2] = (uint8_t) (((ub->pos - 4) >> 8) & 0xff);
|
||||
ub->buf[3] = modifier2;
|
||||
return 0;
|
||||
int uwsgi_buffer_num64(struct uwsgi_buffer *ub, int64_t num) {
|
||||
char buf[sizeof(UMAX64_STR)+1];
|
||||
int ret = snprintf(buf, sizeof(UMAX64_STR)+1, "%lld", (long long) num);
|
||||
if (ret <= 0 || ret > (int) (sizeof(UMAX64_STR)+1)) {
|
||||
return -1;
|
||||
}
|
||||
return uwsgi_buffer_append(ub, buf, ret);
|
||||
}
|
||||
|
||||
|
||||
+227
-1456
File diff suppressed because it is too large
Load Diff
+464
@@ -0,0 +1,464 @@
|
||||
#include "uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
|
||||
#ifdef UWSGI_UDP
|
||||
|
||||
static void cluster_manage_opt(char *key, uint16_t keylen, char *value, uint16_t vallen, void *foobar) {
|
||||
|
||||
add_exported_option(uwsgi_concat2n(key, keylen, "", 0), uwsgi_concat2n(value, vallen, "", 0), 0);
|
||||
|
||||
}
|
||||
|
||||
void cluster_setup() {
|
||||
|
||||
int rlen;
|
||||
// get cluster configuration
|
||||
if (uwsgi.cluster != NULL) {
|
||||
// get multicast socket
|
||||
|
||||
uwsgi.cluster_fd = uwsgi_cluster_join(uwsgi.cluster);
|
||||
|
||||
uwsgi_log("JOINED CLUSTER: %s\n", uwsgi.cluster);
|
||||
|
||||
// ask for cluster options only if bot pre-existent options are set
|
||||
if (uwsgi.exported_opts_cnt == 1 && !uwsgi.cluster_nodes) {
|
||||
// now wait max 60 seconds and resend multicast request every 10 seconds
|
||||
for (;;) {
|
||||
uwsgi_log("asking \"%s\" uWSGI cluster for configuration data:\n", uwsgi.cluster);
|
||||
if (uwsgi_send_empty_pkt(uwsgi.cluster_fd, uwsgi.cluster, 99, 0) < 0) {
|
||||
uwsgi_log("unable to send multicast message to %s\n", uwsgi.cluster);
|
||||
continue;
|
||||
}
|
||||
waitfd:
|
||||
rlen = uwsgi_waitfd(uwsgi.cluster_fd, 10);
|
||||
if (rlen < 0) {
|
||||
break;
|
||||
}
|
||||
else if (rlen > 0) {
|
||||
// receive the packet
|
||||
char clusterbuf[4096];
|
||||
if (!uwsgi_hooked_parse_dict_dgram(uwsgi.cluster_fd, clusterbuf, 4096, 99, 1, cluster_manage_opt, NULL)) {
|
||||
uwsgi_configure();
|
||||
goto options_parsed;
|
||||
}
|
||||
else {
|
||||
goto waitfd;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
options_parsed:
|
||||
|
||||
if (!uwsgi.cluster_nodes)
|
||||
uwsgi_cluster_add_me();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void uwsgi_cluster_add_node(struct uwsgi_cluster_node *nucn, int type) {
|
||||
|
||||
int i;
|
||||
struct uwsgi_cluster_node *ucn;
|
||||
char *tcp_port;
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("adding node\n");
|
||||
#endif
|
||||
|
||||
tcp_port = strchr(nucn->name, ':');
|
||||
#ifndef UWSGI_ZEROMQ
|
||||
if (tcp_port == NULL) {
|
||||
#else
|
||||
char *zmq_dash = strchr(nucn->name, '-');
|
||||
if (tcp_port == NULL && zmq_dash == NULL) {
|
||||
#endif
|
||||
|
||||
fprintf(stdout, "invalid cluster node name %s\n", nucn->name);
|
||||
return;
|
||||
}
|
||||
|
||||
// first check for already present node
|
||||
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
|
||||
ucn = &uwsgi.shared->nodes[i];
|
||||
if (ucn->name[0] != 0) {
|
||||
if (!strcmp(ucn->name, nucn->name)) {
|
||||
ucn->status = UWSGI_NODE_OK;
|
||||
ucn->last_seen = uwsgi_now();
|
||||
// update requests
|
||||
ucn->requests = nucn->requests;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
|
||||
ucn = &uwsgi.shared->nodes[i];
|
||||
|
||||
if (ucn->name[0] == 0) {
|
||||
memcpy(ucn->name, nucn->name, strlen(nucn->name) + 1);
|
||||
memcpy(ucn->nodename, nucn->nodename, strlen(nucn->nodename) + 1);
|
||||
ucn->workers = nucn->workers;
|
||||
ucn->ucn_addr.sin_family = AF_INET;
|
||||
if (tcp_port) {
|
||||
ucn->ucn_addr.sin_port = htons(atoi(tcp_port + 1));
|
||||
tcp_port[0] = 0;
|
||||
}
|
||||
if (nucn->name[0] == 0) {
|
||||
ucn->ucn_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
}
|
||||
else {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s\n", nucn->name);
|
||||
#endif
|
||||
ucn->ucn_addr.sin_addr.s_addr = inet_addr(nucn->name);
|
||||
}
|
||||
|
||||
ucn->type = type;
|
||||
// here memory can be freed, as it is allocated by uwsgi_concat2n
|
||||
if (type != CLUSTER_NODE_DYNAMIC && tcp_port) {
|
||||
tcp_port[0] = ':';
|
||||
}
|
||||
ucn->last_seen = uwsgi_now();
|
||||
ucn->requests = nucn->requests;
|
||||
uwsgi_log("[uWSGI cluster] added node %s\n", ucn->name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("unable to add node %s\n", nucn->name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int uwsgi_cluster_add_me() {
|
||||
|
||||
const char *key1 = "hostname";
|
||||
const char *key2 = "address";
|
||||
const char *key3 = "workers";
|
||||
const char *key4 = "requests";
|
||||
|
||||
char *ptrbuf;
|
||||
uint16_t ustrlen;
|
||||
char numproc[6];
|
||||
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
char uuid_zmq_str[37];
|
||||
uuid_t uuid_zmq;
|
||||
if (!uwsgi.sockets && !uwsgi.zeromq) {
|
||||
#else
|
||||
if (!uwsgi.sockets) {
|
||||
#endif
|
||||
uwsgi_log("you need to specify at least a socket to start a uWSGI cluster\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
snprintf(numproc, 6, "%d", uwsgi.numproc);
|
||||
|
||||
size_t len;
|
||||
|
||||
if (uwsgi.sockets) {
|
||||
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key2) + 2 + strlen(uwsgi.sockets->name) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
|
||||
}
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
else if (uwsgi.zeromq) {
|
||||
uuid_generate(uuid_zmq);
|
||||
uuid_unparse(uuid_zmq, uuid_zmq_str);
|
||||
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key2) + 2 + strlen(uuid_zmq_str) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
|
||||
}
|
||||
char *buf = uwsgi_malloc(len);
|
||||
|
||||
ptrbuf = buf;
|
||||
|
||||
ustrlen = strlen(key1);
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, key1, strlen(key1));
|
||||
ptrbuf += strlen(key1);
|
||||
|
||||
ustrlen = strlen(uwsgi.hostname);
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, uwsgi.hostname, strlen(uwsgi.hostname));
|
||||
ptrbuf += strlen(uwsgi.hostname);
|
||||
|
||||
|
||||
if (uwsgi.sockets && uwsgi.sockets->name) {
|
||||
ustrlen = strlen(key2);
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, key2, strlen(key2));
|
||||
ptrbuf += strlen(key2);
|
||||
|
||||
ustrlen = strlen(uwsgi.sockets->name);
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, uwsgi.sockets->name, strlen(uwsgi.sockets->name));
|
||||
ptrbuf += strlen(uwsgi.sockets->name);
|
||||
}
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
else if (uwsgi.zeromq) {
|
||||
ustrlen = strlen(key2);
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, key2, strlen(key2));
|
||||
ptrbuf += strlen(key2);
|
||||
|
||||
ustrlen = strlen(uuid_zmq_str);
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, uuid_zmq_str, strlen(uuid_zmq_str));
|
||||
ptrbuf += strlen(uuid_zmq_str);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
ustrlen = strlen(key3);
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, key3, strlen(key3));
|
||||
ptrbuf += strlen(key3);
|
||||
|
||||
ustrlen = strlen(numproc);
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, numproc, strlen(numproc));
|
||||
ptrbuf += strlen(numproc);
|
||||
|
||||
ustrlen = strlen(key4);
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, key4, strlen(key4));
|
||||
ptrbuf += strlen(key4);
|
||||
|
||||
ustrlen = 1;
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, "0", 1);
|
||||
ptrbuf += 1;
|
||||
|
||||
|
||||
uwsgi_string_sendto(uwsgi.cluster_fd, 95, 0, (struct sockaddr *) &uwsgi.mc_cluster_addr, sizeof(uwsgi.mc_cluster_addr), buf, len);
|
||||
|
||||
free(buf);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("add_me() successfull\n");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_cluster_join(char *name) {
|
||||
|
||||
int fd;
|
||||
char *cp;
|
||||
int broadcast = 0;
|
||||
|
||||
|
||||
|
||||
if (name[0] == ':') {
|
||||
fd = bind_to_udp(name, 0, 1);
|
||||
broadcast = 1;
|
||||
}
|
||||
else {
|
||||
fd = bind_to_udp(name, 1, 0);
|
||||
}
|
||||
|
||||
if (fd >= 0) {
|
||||
cp = strchr(name, ':');
|
||||
cp[0] = 0;
|
||||
uwsgi.mc_cluster_addr.sin_family = AF_INET;
|
||||
if (broadcast) {
|
||||
uwsgi.mc_cluster_addr.sin_addr.s_addr = INADDR_BROADCAST;
|
||||
}
|
||||
else {
|
||||
uwsgi.mc_cluster_addr.sin_addr.s_addr = inet_addr(name);
|
||||
}
|
||||
uwsgi.mc_cluster_addr.sin_port = htons(atoi(cp + 1));
|
||||
cp[0] = ':';
|
||||
|
||||
|
||||
// announce my presence to all the nodes
|
||||
uwsgi_string_sendto(fd, 73, 0, (struct sockaddr *) &uwsgi.mc_cluster_addr, sizeof(uwsgi.mc_cluster_addr), uwsgi.hostname, strlen(uwsgi.hostname));
|
||||
}
|
||||
else {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
return fd;
|
||||
|
||||
}
|
||||
|
||||
|
||||
char *uwsgi_cluster_best_node() {
|
||||
|
||||
int i;
|
||||
int best_node = -1;
|
||||
struct uwsgi_cluster_node *ucn;
|
||||
|
||||
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
|
||||
ucn = &uwsgi.shared->nodes[i];
|
||||
if (ucn->name[0] != 0 && ucn->status == UWSGI_NODE_OK) {
|
||||
if (best_node == -1) {
|
||||
best_node = i;
|
||||
}
|
||||
else {
|
||||
if (ucn->last_choosen < uwsgi.shared->nodes[best_node].last_choosen) {
|
||||
best_node = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (best_node == -1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uwsgi.shared->nodes[best_node].last_choosen = uwsgi_now();
|
||||
return uwsgi.shared->nodes[best_node].name;
|
||||
}
|
||||
|
||||
|
||||
void manage_cluster_announce(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
|
||||
|
||||
char *tmpstr;
|
||||
struct uwsgi_cluster_node *ucn = (struct uwsgi_cluster_node *) data;
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%.*s = %.*s\n", keylen, key, vallen, val);
|
||||
#endif
|
||||
|
||||
if (!uwsgi_strncmp("hostname", 8, key, keylen)) {
|
||||
strncpy(ucn->nodename, val, UMIN(vallen, 255));
|
||||
}
|
||||
|
||||
if (!uwsgi_strncmp("address", 7, key, keylen)) {
|
||||
strncpy(ucn->name, val, UMIN(vallen, 100));
|
||||
}
|
||||
|
||||
if (!uwsgi_strncmp("workers", 7, key, keylen)) {
|
||||
tmpstr = uwsgi_concat2n(val, vallen, "", 0);
|
||||
ucn->workers = atoi(tmpstr);
|
||||
free(tmpstr);
|
||||
}
|
||||
|
||||
if (!uwsgi_strncmp("requests", 8, key, keylen)) {
|
||||
tmpstr = uwsgi_concat2n(val, vallen, "", 0);
|
||||
ucn->requests = strtoul(tmpstr, NULL, 0);
|
||||
free(tmpstr);
|
||||
}
|
||||
}
|
||||
|
||||
void manage_cluster_message(char *cluster_opt_buf, int cluster_opt_size) {
|
||||
|
||||
struct uwsgi_cluster_node nucn;
|
||||
|
||||
switch (uwsgi.workers[0].cores[0].req.uh.modifier1) {
|
||||
case 95:
|
||||
memset(&nucn, 0, sizeof(struct uwsgi_cluster_node));
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
uwsgi.workers[0].cores[0].req.uh.pktsize = uwsgi_swap16(uwsgi.workers[0].cores[0].req.uh.pktsize);
|
||||
#endif
|
||||
uwsgi_hooked_parse(uwsgi.workers[0].cores[0].req.buffer, uwsgi.workers[0].cores[0].req.uh.pktsize, manage_cluster_announce, &nucn);
|
||||
if (nucn.name[0] != 0) {
|
||||
uwsgi_cluster_add_node(&nucn, CLUSTER_NODE_DYNAMIC);
|
||||
}
|
||||
break;
|
||||
case 96:
|
||||
#ifdef __BIG_ENDIAN__
|
||||
uwsgi.workers[0].cores[0].req.uh.pktsize = uwsgi_swap16(uwsgi.workers[0].cores[0].req.uh.pktsize);
|
||||
#endif
|
||||
uwsgi_log_verbose("%.*s\n", uwsgi.workers[0].cores[0].req.uh.pktsize, uwsgi.workers[0].cores[0].req.buffer);
|
||||
break;
|
||||
case 98:
|
||||
if (kill(getpid(), SIGHUP)) {
|
||||
uwsgi_error("kill()");
|
||||
}
|
||||
break;
|
||||
case 99:
|
||||
if (uwsgi.cluster_nodes)
|
||||
break;
|
||||
if (uwsgi.workers[0].cores[0].req.uh.modifier2 == 0) {
|
||||
uwsgi_log("requested configuration data, sending %d bytes\n", cluster_opt_size);
|
||||
sendto(uwsgi.cluster_fd, cluster_opt_buf, cluster_opt_size, 0, (struct sockaddr *) &uwsgi.mc_cluster_addr, sizeof(uwsgi.mc_cluster_addr));
|
||||
}
|
||||
break;
|
||||
case 73:
|
||||
#ifdef __BIG_ENDIAN__
|
||||
uwsgi.workers[0].cores[0].req.uh.pktsize = uwsgi_swap16(uwsgi.workers[0].cores[0].req.uh.pktsize);
|
||||
#endif
|
||||
uwsgi_log_verbose("[uWSGI cluster %s] new node available: %.*s\n", uwsgi.cluster, uwsgi.workers[0].cores[0].req.uh.pktsize, uwsgi.workers[0].cores[0].req.buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
char *uwsgi_setup_clusterbuf(size_t * size) {
|
||||
|
||||
size_t cluster_opt_size = 4;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
|
||||
//uwsgi_log("%s\n", uwsgi.exported_opts[i]->key);
|
||||
cluster_opt_size += 2 + strlen(uwsgi.exported_opts[i]->key);
|
||||
if (uwsgi.exported_opts[i]->value) {
|
||||
cluster_opt_size += 2 + strlen(uwsgi.exported_opts[i]->value);
|
||||
}
|
||||
else {
|
||||
cluster_opt_size += 2 + 1;
|
||||
}
|
||||
}
|
||||
|
||||
//uwsgi_log("cluster opts size: %d\n", cluster_opt_size);
|
||||
char *cluster_opt_buf = uwsgi_malloc(cluster_opt_size);
|
||||
|
||||
struct uwsgi_header *uh = (struct uwsgi_header *) cluster_opt_buf;
|
||||
|
||||
uh->modifier1 = 99;
|
||||
uh->pktsize = cluster_opt_size - 4;
|
||||
uh->modifier2 = 1;
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
uh->pktsize = uwsgi_swap16(uh->pktsize);
|
||||
#endif
|
||||
|
||||
char *cptrbuf = cluster_opt_buf + 4;
|
||||
|
||||
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
|
||||
//uwsgi_log("%s\n", uwsgi.exported_opts[i]->key);
|
||||
uint16_t ustrlen = strlen(uwsgi.exported_opts[i]->key);
|
||||
*cptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*cptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(cptrbuf, uwsgi.exported_opts[i]->key, ustrlen);
|
||||
cptrbuf += ustrlen;
|
||||
|
||||
if (uwsgi.exported_opts[i]->value) {
|
||||
ustrlen = strlen(uwsgi.exported_opts[i]->value);
|
||||
*cptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*cptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(cptrbuf, uwsgi.exported_opts[i]->value, ustrlen);
|
||||
}
|
||||
else {
|
||||
ustrlen = 1;
|
||||
*cptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*cptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
*cptrbuf = '1';
|
||||
}
|
||||
cptrbuf += ustrlen;
|
||||
}
|
||||
|
||||
return cluster_opt_buf;
|
||||
}
|
||||
+24
-52
@@ -87,7 +87,7 @@ void uwsgi_emperor_blacklist_add(char *id) {
|
||||
}
|
||||
}
|
||||
|
||||
strncpy(uebi->id, id, 0xff);
|
||||
strcpy(uebi->id, id);
|
||||
gettimeofday(&uebi->first_attempt, NULL);
|
||||
memcpy(&uebi->last_attempt, &uebi->first_attempt, sizeof(struct timeval));
|
||||
uebi->throttle_level = uwsgi.emperor_throttle;
|
||||
@@ -356,7 +356,7 @@ static void emperor_stats() {
|
||||
|
||||
while (c_ui) {
|
||||
|
||||
uwsgi_log("vassal instance %s (last modified %lld) status %d loyal %d zerg %d\n", c_ui->name, (long long) c_ui->last_mod, c_ui->status, c_ui->loyal, c_ui->zerg);
|
||||
uwsgi_log("vassal instance %s (last modified %d) status %d loyal %d zerg %d\n", c_ui->name, c_ui->last_mod, c_ui->status, c_ui->loyal, c_ui->zerg);
|
||||
|
||||
c_ui = c_ui->ui_next;
|
||||
}
|
||||
@@ -448,28 +448,17 @@ void emperor_stop(struct uwsgi_instance *c_ui) {
|
||||
|
||||
void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
|
||||
|
||||
struct uwsgi_header uh;
|
||||
|
||||
// reload the uWSGI instance
|
||||
if (write(c_ui->pipe[0], "\1", 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
|
||||
// push the config to the config pipe (if needed)
|
||||
if (c_ui->use_config) {
|
||||
uh.modifier1 = 115;
|
||||
uh.pktsize = c_ui->config_len;
|
||||
uh.modifier2 = 0;
|
||||
if (write(c_ui->pipe_config[0], &uh, 4) != 4) {
|
||||
uwsgi_error("[uwsgi-emperor] write() header config");
|
||||
if (write(c_ui->pipe[0], "\0", 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
else {
|
||||
if (write(c_ui->pipe_config[0], c_ui->config, c_ui->config_len) != (long) c_ui->config_len) {
|
||||
uwsgi_error("[uwsgi-emperor] write() config");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (write(c_ui->pipe[0], "\1", 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
c_ui->respawns++;
|
||||
c_ui->last_mod = mod;
|
||||
@@ -496,7 +485,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
#endif
|
||||
|
||||
if (strlen(name) > (0xff - 1)) {
|
||||
uwsgi_log("[emperor] invalid vassal name: %s\n", name);
|
||||
uwsgi_log("[emperor] invalid vassal name\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -611,19 +600,10 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
}
|
||||
|
||||
if (n_ui->use_config) {
|
||||
struct uwsgi_header uh;
|
||||
uh.modifier1 = 115;
|
||||
uh.pktsize = n_ui->config_len;
|
||||
uh.modifier2 = 0;
|
||||
if (write(n_ui->pipe_config[0], &uh, 4) != 4) {
|
||||
uwsgi_error("[uwsgi-emperor] write() header config");
|
||||
}
|
||||
else {
|
||||
if (write(n_ui->pipe_config[0], n_ui->config, n_ui->config_len) != (long) n_ui->config_len) {
|
||||
uwsgi_error("[uwsgi-emperor] write() config");
|
||||
}
|
||||
}
|
||||
|
||||
if (write(n_ui->pipe_config[0], n_ui->config, n_ui->config_len) <= 0) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
close(n_ui->pipe_config[0]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -683,7 +663,6 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
char *oe = uwsgi_concat2n(*uenvs, strchr(*uenvs, '=') - *uenvs, "", 0);
|
||||
if (unsetenv(oe)) {
|
||||
uwsgi_error("unsetenv()");
|
||||
free(oe);
|
||||
break;
|
||||
}
|
||||
free(oe);
|
||||
@@ -1056,9 +1035,9 @@ void emperor_loop() {
|
||||
}
|
||||
|
||||
// check if a monitor is mapped to that file descriptor
|
||||
if (uwsgi_emperor_scanner_event(interesting_fd)) {
|
||||
if (uwsgi_emperor_scanner_event(interesting_fd))
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
ui_current = emperor_get_by_fd(interesting_fd);
|
||||
if (ui_current) {
|
||||
@@ -1066,7 +1045,9 @@ void emperor_loop() {
|
||||
ssize_t rlen = read(interesting_fd, &byte, 1);
|
||||
if (rlen <= 0) {
|
||||
// SAFE
|
||||
emperor_del(ui_current);
|
||||
if (!ui_current->config_len) {
|
||||
emperor_del(ui_current);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (byte == 17) {
|
||||
@@ -1454,25 +1435,16 @@ void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char
|
||||
}
|
||||
// check if mtime is changed and the uWSGI instance must be reloaded
|
||||
if (ts > ui_current->last_mod) {
|
||||
// make a new config (free the old one) if needed
|
||||
if (config) {
|
||||
if (ui_current->config)
|
||||
free(ui_current->config);
|
||||
ui_current->config = uwsgi_str(config);
|
||||
ui_current->config_len = strlen(ui_current->config);
|
||||
}
|
||||
// reload the instance
|
||||
// make a new config (free the old one)
|
||||
free(ui_current->config);
|
||||
ui_current->config = config;
|
||||
ui_current->config_len = strlen(config);
|
||||
// always respawn (no need for amqp-style rules)
|
||||
emperor_respawn(ui_current, ts);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// make a copy of the config as it will be freed
|
||||
char *new_config = NULL;
|
||||
size_t new_config_len = 0;
|
||||
if (config) {
|
||||
new_config = uwsgi_str(config);
|
||||
new_config_len = strlen(new_config);
|
||||
}
|
||||
emperor_add(ues, name, ts, new_config, new_config_len, uid, gid);
|
||||
emperor_add(ues, name, ts, uwsgi_str(config), strlen((const char *) config), uid, gid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
// generate internal server error message
|
||||
void uwsgi_500(struct wsgi_request *wsgi_req) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "500 Internal Server Error", 25)) return;
|
||||
if (uwsgi_response_add_connection_close(wsgi_req)) return;
|
||||
uwsgi_response_write_body_do(wsgi_req, "Internal Server Error", 21);
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_404(struct wsgi_request *wsgi_req) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "404 Not Found", 13)) return;
|
||||
if (uwsgi_response_add_connection_close(wsgi_req)) return;
|
||||
if (uwsgi_response_add_header(wsgi_req, "Content-Type", 12, "text/plain", 10)) return;
|
||||
uwsgi_response_write_body_do(wsgi_req, "Not Found", 9);
|
||||
}
|
||||
|
||||
void uwsgi_403(struct wsgi_request *wsgi_req) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "403 Forbidden", 13)) return;
|
||||
if (uwsgi_response_add_connection_close(wsgi_req)) return;
|
||||
if (uwsgi_response_add_content_type(wsgi_req, "text/plain", 10)) return;
|
||||
uwsgi_response_write_body_do(wsgi_req, "Forbidden", 9);
|
||||
}
|
||||
|
||||
void uwsgi_redirect_to_slash(struct wsgi_request *wsgi_req) {
|
||||
|
||||
char *redirect = NULL;
|
||||
size_t redirect_len = 0;
|
||||
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "301 Moved Permanently", 21)) return;
|
||||
if (uwsgi_response_add_connection_close(wsgi_req)) return;
|
||||
|
||||
if (wsgi_req->query_string_len == 0) {
|
||||
redirect = uwsgi_concat2n(wsgi_req->path_info, wsgi_req->path_info_len, "/", 1);
|
||||
redirect_len = wsgi_req->path_info_len + 1;
|
||||
}
|
||||
else {
|
||||
redirect = uwsgi_concat3n(wsgi_req->path_info, wsgi_req->path_info_len, "/?", 2, wsgi_req->query_string, wsgi_req->query_string_len);
|
||||
redirect_len = wsgi_req->path_info_len + 2 + wsgi_req->query_string_len;
|
||||
}
|
||||
uwsgi_response_add_header(wsgi_req, "Location", 8, redirect, redirect_len);
|
||||
free(redirect);
|
||||
return;
|
||||
}
|
||||
|
||||
+2
-242
@@ -2,233 +2,6 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#ifdef UWSGI_EVENT_USE_POLL
|
||||
#define UWSGI_EVENT_IN POLLIN
|
||||
#define UWSGI_EVENT_OUT POLLOUT
|
||||
|
||||
int uwsgi_poll_event_queue_max = 0;
|
||||
struct uwsgi_poll_event {
|
||||
int nevents;
|
||||
int max_events;
|
||||
pthread_mutex_t lock;
|
||||
struct pollfd *poll;
|
||||
};
|
||||
|
||||
struct uwsgi_poll_event **uwsgi_poll_event_queue;
|
||||
|
||||
// all of the public functions must be heavy locked
|
||||
|
||||
static int uwsgi_poll_fd_is_registered(struct uwsgi_poll_event *upe, int fd) {
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (upe->poll[i].fd == fd) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_poll_fd_add(struct uwsgi_poll_event *upe, int fd, int event) {
|
||||
int pos = upe->nevents;
|
||||
if (pos > upe->max_events) return -1;
|
||||
upe->poll[pos].fd = fd;
|
||||
upe->poll[pos].events = event;
|
||||
upe->nevents++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_poll_fd_del(struct uwsgi_poll_event *upe, int fd) {
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (upe->poll[i].fd == fd) {
|
||||
if (i < upe->nevents-1) {
|
||||
memcpy(&upe->poll[i], &upe->poll[i+1], sizeof(struct uwsgi_poll_event) * (upe->nevents - (i+1)));
|
||||
}
|
||||
upe->nevents--;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void uwsgi_poll_queue_rebuild(struct uwsgi_poll_event *upe) {
|
||||
// we need to check if some file descriptor is no more valid
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (!uwsgi_valid_fd(upe->poll[i].fd)) {
|
||||
uwsgi_poll_fd_del(upe, upe->poll[i].fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int event_queue_wait(int eq, int timeout, int *interesting_fd) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
uwsgi_poll_queue_rebuild(upe);
|
||||
int ret = poll(upe->poll, upe->nevents, timeout * 1000);
|
||||
if (ret > 0) {
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (upe->poll[i].revents) {
|
||||
*interesting_fd = upe->poll[i].fd;
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int event_queue_init() {
|
||||
if (!uwsgi_poll_event_queue) {
|
||||
uwsgi_poll_event_queue = uwsgi_calloc(sizeof(struct uwsgi_poll_event *) * uwsgi.max_fd);
|
||||
}
|
||||
int eq = uwsgi_poll_event_queue_max;
|
||||
uwsgi_poll_event_queue[eq] = uwsgi_calloc(sizeof(struct uwsgi_poll_event));
|
||||
uwsgi_poll_event_queue_max++;
|
||||
uwsgi_poll_event_queue[eq]->poll = uwsgi_malloc(sizeof(struct pollfd) * uwsgi.max_fd);
|
||||
uwsgi_poll_event_queue[eq]->max_events = uwsgi.max_fd;
|
||||
pthread_mutex_init(&uwsgi_poll_event_queue[eq]->lock, NULL);
|
||||
return eq;
|
||||
}
|
||||
|
||||
void *event_queue_alloc(int nevents) {
|
||||
return uwsgi_calloc(sizeof(struct pollfd) * nevents);
|
||||
}
|
||||
|
||||
int event_queue_interesting_fd_is_read(void *events, int id) {
|
||||
struct pollfd *pevents = (struct pollfd *)events;
|
||||
struct pollfd *upoll = &pevents[id];
|
||||
if (upoll->revents & POLLIN) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_queue_fd_write_to_readwrite(int eq, int fd) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (upe->poll[i].fd == fd) {
|
||||
upe->poll[i].events = POLLIN|POLLOUT;
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int event_queue_fd_read_to_readwrite(int eq, int fd) {
|
||||
return event_queue_fd_write_to_readwrite(eq, fd);
|
||||
}
|
||||
|
||||
int event_queue_interesting_fd_is_write(void *events, int id) {
|
||||
struct pollfd *pevents = (struct pollfd *)events;
|
||||
struct pollfd *upoll = &pevents[id];
|
||||
if (upoll->revents & POLLOUT) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_queue_add_fd_read(int eq, int fd) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
if (uwsgi_poll_fd_is_registered(upe, fd)) {
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return 0;
|
||||
}
|
||||
int ret = uwsgi_poll_fd_add(upe, fd, POLLIN);
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return ret;
|
||||
}
|
||||
int event_queue_add_fd_write(int eq, int fd) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
if (uwsgi_poll_fd_is_registered(upe, fd)) {
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return 0;
|
||||
}
|
||||
int ret = uwsgi_poll_fd_add(upe, fd, POLLOUT);
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return ret;
|
||||
}
|
||||
int event_queue_del_fd(int eq, int fd, int event) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
int ret = uwsgi_poll_fd_del(upe, fd);
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return ret;
|
||||
}
|
||||
int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
uwsgi_poll_queue_rebuild(upe);
|
||||
int ret = poll(upe->poll, upe->nevents, timeout * 1000);
|
||||
int cnt = 0;
|
||||
if (ret > 0) {
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (upe->poll[i].revents) {
|
||||
struct pollfd *pevents = (struct pollfd *)events;
|
||||
struct pollfd *upoll = &pevents[cnt];
|
||||
upoll->fd = upe->poll[i].fd;
|
||||
upoll->revents = upe->poll[i].revents;
|
||||
upoll->events = upe->poll[i].events;
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
if (ret <= 0) return ret;
|
||||
return cnt;
|
||||
}
|
||||
int event_queue_interesting_fd_has_error(void *events, int id) {
|
||||
struct pollfd *pevents = (struct pollfd *)events;
|
||||
struct pollfd *upoll = &pevents[id];
|
||||
if (upoll->revents & POLLERR || upoll->revents & POLLHUP || upoll->revents & POLLNVAL) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int event_queue_interesting_fd(void *events, int id) {
|
||||
struct pollfd *pevents = (struct pollfd *)events;
|
||||
struct pollfd *upoll = &pevents[id];
|
||||
return upoll->fd;
|
||||
}
|
||||
int event_queue_fd_write_to_read(int eq, int fd) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (upe->poll[i].fd == fd) {
|
||||
upe->poll[i].events = POLLIN;
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return -1;
|
||||
}
|
||||
int event_queue_fd_read_to_write(int eq, int fd) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (upe->poll[i].fd == fd) {
|
||||
upe->poll[i].events = POLLOUT;
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
|
||||
#include <port.h>
|
||||
@@ -335,7 +108,7 @@ int event_queue_interesting_fd_has_error(void *events, int id) {
|
||||
|
||||
int event_queue_interesting_fd_is_read(void *events, int id) {
|
||||
port_event_t *pe = (port_event_t *) events;
|
||||
if (pe[id].portev_events == POLLIN) {
|
||||
if (pe[id].portev_events = POLLIN) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -351,7 +124,7 @@ int event_queue_interesting_fd_is_write(void *events, int id) {
|
||||
|
||||
int event_queue_add_fd_read(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *) eq)) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -398,7 +171,6 @@ int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
|
||||
int ret;
|
||||
uint_t nget = 1;
|
||||
timespec_t ts;
|
||||
|
||||
|
||||
if (timeout >= 0) {
|
||||
ts.tv_sec = timeout;
|
||||
@@ -417,18 +189,6 @@ int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint_t i;
|
||||
port_event_t *pe = (port_event_t *) events;
|
||||
for(i=0;i<nget;i++) {
|
||||
port_event_t *pe_i = &pe[i];
|
||||
if (pe_i->portev_source == PORT_SOURCE_FD) {
|
||||
// event must be readded (damn Oracle/Sun why the fu*k you made such a horrible choice ???? why not adding a ONESHOT flag ???)
|
||||
if (port_associate(eq, pe_i->portev_source, pe_i->portev_object, pe_i->portev_events, NULL)) {
|
||||
uwsgi_error("port_associate");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nget;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,499 +0,0 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
Exceptions management
|
||||
|
||||
generally exceptions are printed in the logs, but if you enable
|
||||
an exception manager they will be stored in a (relatively big) uwsgi packet
|
||||
with the following structure.
|
||||
|
||||
"vars" -> keyval of request vars
|
||||
"backtrace" -> list of backtrace lines. Each line is a list of 5 elements filename,line,function,text,custom
|
||||
"unix" -> seconds since the epoch
|
||||
"class" -> the exception class
|
||||
"msg" -> a text message mapped to the extension
|
||||
"repr" -> a text message mapped to the extension in language-specific gergo
|
||||
"wid" -> worker id
|
||||
"core" -> the core generating the exception
|
||||
"pid" -> pid of the worker
|
||||
"node" -> hostname
|
||||
|
||||
Other vars can be added, but you cannot be sure they will be used by exceptions handler.
|
||||
|
||||
The exception-uwsgi packet is passed "as is" to the exception handler
|
||||
|
||||
Exceptions hooks:
|
||||
|
||||
a request plugin can export that hooks:
|
||||
|
||||
struct uwsgi_buffer *backtrace(struct wsgi_request *);
|
||||
struct uwsgi_buffer *exception_class(struct wsgi_request *);
|
||||
struct uwsgi_buffer *exception_msg(struct wsgi_request *);
|
||||
struct uwsgi_buffer *exception_repr(struct wsgi_request *);
|
||||
void exception_log(struct wsgi_request *);
|
||||
|
||||
Remember to reset the exception status (if possibile) after each call
|
||||
|
||||
Exceptions catcher:
|
||||
|
||||
This is a special development-mode in which exceptions are printed
|
||||
to the HTTP client.
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_buffer *uwsgi_exception_handler_object(struct wsgi_request *wsgi_req) {
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(4096);
|
||||
if (uwsgi_buffer_append_keyval(ub, "vars", 4, wsgi_req->buffer,wsgi_req->uh->pktsize)) goto error;
|
||||
if (uwsgi.p[wsgi_req->uh->modifier1]->backtrace) {
|
||||
struct uwsgi_buffer *bt = uwsgi.p[wsgi_req->uh->modifier1]->backtrace(wsgi_req);
|
||||
if (bt) {
|
||||
if (uwsgi_buffer_append_keyval(ub, "backtrace", 9, bt->buf, bt->pos)) {
|
||||
uwsgi_buffer_destroy(bt);
|
||||
goto error;
|
||||
}
|
||||
uwsgi_buffer_destroy(bt);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.p[wsgi_req->uh->modifier1]->exception_class) {
|
||||
struct uwsgi_buffer *ec = uwsgi.p[wsgi_req->uh->modifier1]->exception_class(wsgi_req);
|
||||
if (ec) {
|
||||
if (uwsgi_buffer_append_keyval(ub, "class", 5, ec->buf, ec->pos)) {
|
||||
uwsgi_buffer_destroy(ec);
|
||||
goto error;
|
||||
}
|
||||
uwsgi_buffer_destroy(ec);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.p[wsgi_req->uh->modifier1]->exception_msg) {
|
||||
struct uwsgi_buffer *em = uwsgi.p[wsgi_req->uh->modifier1]->exception_msg(wsgi_req);
|
||||
if (em) {
|
||||
if (uwsgi_buffer_append_keyval(ub, "msg", 3, em->buf, em->pos)) {
|
||||
uwsgi_buffer_destroy(em);
|
||||
goto error;
|
||||
}
|
||||
uwsgi_buffer_destroy(em);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.p[wsgi_req->uh->modifier1]->exception_repr) {
|
||||
struct uwsgi_buffer *er = uwsgi.p[wsgi_req->uh->modifier1]->exception_repr(wsgi_req);
|
||||
if (er) {
|
||||
if (uwsgi_buffer_append_keyval(ub, "repr", 4, er->buf, er->pos)) {
|
||||
uwsgi_buffer_destroy(er);
|
||||
goto error;
|
||||
}
|
||||
uwsgi_buffer_destroy(er);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi_buffer_append_keynum(ub, "unix", 4, uwsgi_now())) goto error;
|
||||
if (uwsgi_buffer_append_keynum(ub, "wid", 3, uwsgi.mywid)) goto error;
|
||||
if (uwsgi_buffer_append_keynum(ub, "pid", 3, uwsgi.mypid)) goto error;
|
||||
if (uwsgi_buffer_append_keynum(ub, "core", 4, wsgi_req->async_id)) goto error;
|
||||
if (uwsgi_buffer_append_keyval(ub, "node", 4, uwsgi.hostname, uwsgi.hostname_len)) goto error;
|
||||
|
||||
return ub;
|
||||
|
||||
error:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void append_vars_to_ubuf(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
|
||||
struct uwsgi_buffer *ub = (struct uwsgi_buffer *) data;
|
||||
|
||||
if (uwsgi_buffer_append(ub, key, keylen)) return;
|
||||
if (uwsgi_buffer_append(ub, " = ", 3)) return;
|
||||
if (uwsgi_buffer_append(ub, val, vallen)) return;
|
||||
if (uwsgi_buffer_append(ub, "\n", 1)) return;
|
||||
}
|
||||
|
||||
static void append_backtrace_to_ubuf(uint16_t pos, char *value, uint16_t len, void *data) {
|
||||
struct uwsgi_buffer *ub = (struct uwsgi_buffer *) data;
|
||||
|
||||
uint16_t item = 0;
|
||||
if (pos > 0) {
|
||||
item = pos % 5;
|
||||
}
|
||||
|
||||
switch(item) {
|
||||
// filename
|
||||
case 0:
|
||||
if (uwsgi_buffer_append(ub, "filename: \"", 11)) return;
|
||||
if (uwsgi_buffer_append(ub, value, len)) return;
|
||||
if (uwsgi_buffer_append(ub, "\" ", 2)) return;
|
||||
break;
|
||||
// lineno
|
||||
case 1:
|
||||
if (uwsgi_buffer_append(ub, "line: ", 6)) return;
|
||||
if (uwsgi_buffer_append(ub, value, len)) return;
|
||||
if (uwsgi_buffer_append(ub, " ", 1)) return;
|
||||
break;
|
||||
// function
|
||||
case 2:
|
||||
if (uwsgi_buffer_append(ub, "function: \"", 11)) return;
|
||||
if (uwsgi_buffer_append(ub, value, len)) return;
|
||||
if (uwsgi_buffer_append(ub, "\" ", 2)) return;
|
||||
break;
|
||||
// text
|
||||
case 3:
|
||||
if (len > 0) {
|
||||
if (uwsgi_buffer_append(ub, "text/code: \"", 12)) return;
|
||||
if (uwsgi_buffer_append(ub, value, len)) return;
|
||||
if (uwsgi_buffer_append(ub, "\" ", 2)) return;
|
||||
}
|
||||
break;
|
||||
// custom
|
||||
case 4:
|
||||
if (len > 0) {
|
||||
if (uwsgi_buffer_append(ub, "custom: \"", 9)) return;
|
||||
if (uwsgi_buffer_append(ub, value, len)) return;
|
||||
if (uwsgi_buffer_append(ub, "\" ", 2)) return;
|
||||
}
|
||||
if (uwsgi_buffer_append(ub, "\n", 1)) return;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_exceptions_catch(struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "500 Internal Server Error", 25)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uwsgi_response_add_content_type(wsgi_req, "text/plain", 10)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(4096);
|
||||
if (uwsgi_buffer_append(ub, "uWSGI exceptions catcher for \"", 30)) goto error;
|
||||
if (uwsgi_buffer_append(ub, wsgi_req->method, wsgi_req->method_len)) goto error;
|
||||
if (uwsgi_buffer_append(ub, " ", 1)) goto error;
|
||||
if (uwsgi_buffer_append(ub, wsgi_req->uri, wsgi_req->uri_len)) goto error;
|
||||
if (uwsgi_buffer_append(ub, "\" (request plugin: \"", 20)) goto error;
|
||||
if (uwsgi_buffer_append(ub, (char *) uwsgi.p[wsgi_req->uh->modifier1]->name, strlen(uwsgi.p[wsgi_req->uh->modifier1]->name))) goto error;
|
||||
if (uwsgi_buffer_append(ub, "\", modifier1: ", 14 )) goto error;
|
||||
if (uwsgi_buffer_num64(ub, wsgi_req->uh->modifier1)) goto error;
|
||||
if (uwsgi_buffer_append(ub, ")\n\n", 3)) goto error;
|
||||
|
||||
if (uwsgi_buffer_append(ub, "Exception: ", 11)) goto error;
|
||||
|
||||
if (uwsgi.p[wsgi_req->uh->modifier1]->exception_repr) {
|
||||
struct uwsgi_buffer *ub_exc_repr = uwsgi.p[wsgi_req->uh->modifier1]->exception_repr(wsgi_req);
|
||||
if (ub_exc_repr) {
|
||||
if (uwsgi_buffer_append(ub, ub_exc_repr->buf, ub_exc_repr->pos)) {
|
||||
uwsgi_buffer_destroy(ub_exc_repr);
|
||||
goto error;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub_exc_repr);
|
||||
}
|
||||
else {
|
||||
goto notavail3;
|
||||
}
|
||||
}
|
||||
else {
|
||||
notavail3:
|
||||
if (uwsgi_buffer_append(ub, "-Not available-", 15)) goto error;
|
||||
}
|
||||
|
||||
if (uwsgi_buffer_append(ub, "\n\n", 2)) goto error;
|
||||
|
||||
if (uwsgi_buffer_append(ub, "Exception class: ", 17)) goto error;
|
||||
|
||||
if (uwsgi.p[wsgi_req->uh->modifier1]->exception_class) {
|
||||
struct uwsgi_buffer *ub_exc_class = uwsgi.p[wsgi_req->uh->modifier1]->exception_class(wsgi_req);
|
||||
if (ub_exc_class) {
|
||||
if (uwsgi_buffer_append(ub, ub_exc_class->buf, ub_exc_class->pos)) {
|
||||
uwsgi_buffer_destroy(ub_exc_class);
|
||||
goto error;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub_exc_class);
|
||||
}
|
||||
else {
|
||||
goto notavail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
notavail:
|
||||
if (uwsgi_buffer_append(ub, "-Not available-", 15)) goto error;
|
||||
}
|
||||
|
||||
if (uwsgi_buffer_append(ub, "\n\n", 2)) goto error;
|
||||
|
||||
if (uwsgi_buffer_append(ub, "Exception message: ", 19)) goto error;
|
||||
|
||||
if (uwsgi.p[wsgi_req->uh->modifier1]->exception_msg) {
|
||||
struct uwsgi_buffer *ub_exc_msg = uwsgi.p[wsgi_req->uh->modifier1]->exception_msg(wsgi_req);
|
||||
if (ub_exc_msg) {
|
||||
if (uwsgi_buffer_append(ub, ub_exc_msg->buf, ub_exc_msg->pos)) {
|
||||
uwsgi_buffer_destroy(ub_exc_msg);
|
||||
goto error;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub_exc_msg);
|
||||
}
|
||||
else {
|
||||
goto notavail2;
|
||||
}
|
||||
}
|
||||
else {
|
||||
notavail2:
|
||||
if (uwsgi_buffer_append(ub, "-Not available-", 15)) goto error;
|
||||
}
|
||||
|
||||
if (uwsgi_buffer_append(ub, "\n\n", 2)) goto error;
|
||||
|
||||
if (uwsgi_buffer_append(ub, "Backtrace:\n", 11)) goto error;
|
||||
|
||||
if (uwsgi.p[wsgi_req->uh->modifier1]->backtrace) {
|
||||
struct uwsgi_buffer *ub_exc_bt = uwsgi.p[wsgi_req->uh->modifier1]->backtrace(wsgi_req);
|
||||
if (ub_exc_bt) {
|
||||
struct uwsgi_buffer *parsed_bt = uwsgi_buffer_new(4096);
|
||||
if (uwsgi_hooked_parse_array(ub_exc_bt->buf, ub_exc_bt->pos, append_backtrace_to_ubuf, parsed_bt)) {
|
||||
uwsgi_buffer_destroy(ub_exc_bt);
|
||||
uwsgi_buffer_destroy(parsed_bt);
|
||||
goto error;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub_exc_bt);
|
||||
if (uwsgi_buffer_append(ub, parsed_bt->buf, parsed_bt->pos)) {
|
||||
uwsgi_buffer_destroy(parsed_bt);
|
||||
goto error;
|
||||
}
|
||||
uwsgi_buffer_destroy(parsed_bt);
|
||||
}
|
||||
else {
|
||||
goto notavail4;
|
||||
}
|
||||
}
|
||||
else {
|
||||
notavail4:
|
||||
if (uwsgi_buffer_append(ub, "-Not available-", 15)) goto error;
|
||||
}
|
||||
|
||||
if (uwsgi_buffer_append(ub, "\n\n", 2)) goto error;
|
||||
|
||||
if (uwsgi_hooked_parse(wsgi_req->buffer, wsgi_req->uh->pktsize, append_vars_to_ubuf, ub)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
static void uwsgi_exception_run_handlers(struct uwsgi_buffer *ub) {
|
||||
struct uwsgi_string_list *usl = uwsgi.exception_handlers_instance;
|
||||
struct iovec iov[2];
|
||||
iov[1].iov_base = ub->buf;
|
||||
iov[1].iov_len = ub->pos;
|
||||
while(usl) {
|
||||
struct uwsgi_exception_handler_instance *uehi = (struct uwsgi_exception_handler_instance *) usl->custom_ptr;
|
||||
iov[0].iov_base = &uehi;
|
||||
iov[0].iov_len = sizeof(long);
|
||||
// now send the message to the exception handler thread
|
||||
if (writev(uwsgi.exception_handler_thread->pipe[0], iov, 2) != (ssize_t) (ub->pos+sizeof(long))) {
|
||||
uwsgi_error("[uwsgi-exception-handler-error] uwsgi_exception_run_handlers()/writev()");
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_manage_exception(struct wsgi_request *wsgi_req,int catch) {
|
||||
|
||||
int do_exit = uwsgi.reload_on_exception;
|
||||
|
||||
if (!wsgi_req) goto log2;
|
||||
|
||||
if (do_exit) goto check_catch;
|
||||
|
||||
if (wsgi_req && uwsgi.exception_handlers_instance) {
|
||||
struct uwsgi_buffer *ehi = uwsgi_exception_handler_object(wsgi_req);
|
||||
if (ehi) {
|
||||
uwsgi_exception_run_handlers(ehi);
|
||||
uwsgi_buffer_destroy(ehi);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].exceptions++;
|
||||
uwsgi_apps[wsgi_req->app_id].exceptions++;
|
||||
|
||||
if (uwsgi.reload_on_exception_type && uwsgi.p[wsgi_req->uh->modifier1]->exception_class) {
|
||||
struct uwsgi_buffer *ub = uwsgi.p[wsgi_req->uh->modifier1]->exception_msg(wsgi_req);
|
||||
if (ub) {
|
||||
struct uwsgi_string_list *usl = uwsgi.reload_on_exception_type;
|
||||
while (usl) {
|
||||
if (!uwsgi_strncmp(usl->value, usl->len, ub->buf, ub->len)) {
|
||||
do_exit = 1;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
goto check_catch;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.reload_on_exception_value && uwsgi.p[wsgi_req->uh->modifier1]->exception_msg) {
|
||||
struct uwsgi_buffer *ub = uwsgi.p[wsgi_req->uh->modifier1]->exception_msg(wsgi_req);
|
||||
if (ub) {
|
||||
struct uwsgi_string_list *usl = uwsgi.reload_on_exception_value;
|
||||
while (usl) {
|
||||
if (!uwsgi_strncmp(usl->value, usl->len, ub->buf, ub->len)) {
|
||||
do_exit = 1;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
goto check_catch;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.reload_on_exception_repr && uwsgi.p[wsgi_req->uh->modifier1]->exception_repr) {
|
||||
struct uwsgi_buffer *ub = uwsgi.p[wsgi_req->uh->modifier1]->exception_msg(wsgi_req);
|
||||
if (ub) {
|
||||
struct uwsgi_string_list *usl = uwsgi.reload_on_exception_repr;
|
||||
while (usl) {
|
||||
if (!uwsgi_strncmp(usl->value, usl->len, ub->buf, ub->len)) {
|
||||
do_exit = 1;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
goto check_catch;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub);
|
||||
}
|
||||
}
|
||||
|
||||
check_catch:
|
||||
if (catch && wsgi_req) {
|
||||
if (uwsgi_exceptions_catch(wsgi_req)) {
|
||||
// for now, just goto, new features could be added
|
||||
goto log;
|
||||
}
|
||||
}
|
||||
|
||||
log:
|
||||
if (uwsgi.p[wsgi_req->uh->modifier1]->exception_log) {
|
||||
uwsgi.p[wsgi_req->uh->modifier1]->exception_log(wsgi_req);
|
||||
}
|
||||
|
||||
log2:
|
||||
if (do_exit) {
|
||||
exit(UWSGI_EXCEPTION_CODE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_exception_handler *uwsgi_register_exception_handler(char *name, int (*func)(struct uwsgi_exception_handler_instance *, char *, size_t)) {
|
||||
struct uwsgi_exception_handler *old_ueh = NULL, *ueh = uwsgi.exception_handlers;
|
||||
while(ueh) {
|
||||
if (!strcmp(name, ueh->name)) {
|
||||
return NULL;
|
||||
}
|
||||
old_ueh = ueh;
|
||||
ueh = ueh->next;
|
||||
}
|
||||
|
||||
ueh = uwsgi_calloc(sizeof(struct uwsgi_exception_handler));
|
||||
ueh->name = name;
|
||||
ueh->func = func;
|
||||
|
||||
if (old_ueh) {
|
||||
old_ueh->next = ueh;
|
||||
}
|
||||
else {
|
||||
uwsgi.exception_handlers = ueh;
|
||||
}
|
||||
|
||||
return ueh;
|
||||
}
|
||||
|
||||
struct uwsgi_exception_handler *uwsgi_exception_handler_by_name(char *name) {
|
||||
struct uwsgi_exception_handler *ueh = uwsgi.exception_handlers;
|
||||
while(ueh) {
|
||||
if (!strcmp(name, ueh->name)) {
|
||||
return ueh;
|
||||
}
|
||||
ueh = ueh->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void uwsgi_exception_handler_thread_loop(struct uwsgi_thread *ut) {
|
||||
char *buf = uwsgi_malloc(uwsgi.exception_handler_msg_size + sizeof(long));
|
||||
for (;;) {
|
||||
int interesting_fd = -1;
|
||||
int ret = event_queue_wait(ut->queue, -1, &interesting_fd);
|
||||
if (ret > 0) {
|
||||
ssize_t len = read(ut->pipe[1], buf, uwsgi.alarm_msg_size + sizeof(long));
|
||||
if (len > (ssize_t)(sizeof(long) + 1)) {
|
||||
size_t msg_size = len - sizeof(long);
|
||||
char *msg = buf + sizeof(long);
|
||||
long ptr = 0;
|
||||
memcpy(&ptr, buf, sizeof(long));
|
||||
struct uwsgi_exception_handler_instance *uehi = (struct uwsgi_exception_handler_instance *) ptr;
|
||||
if (!uehi)
|
||||
break;
|
||||
if (uehi->handler->func(uehi, msg, msg_size)) {
|
||||
uwsgi_log("[uwsgi-exception] error running the handler \"%s\" args: \"%s\"\n", uehi->handler->name, uehi->arg ? uehi->arg : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
|
||||
void uwsgi_exception_setup_handlers() {
|
||||
|
||||
struct uwsgi_string_list *usl = uwsgi.exception_handlers_instance;
|
||||
while(usl) {
|
||||
char *handler = uwsgi_str(usl->value);
|
||||
char *colon = strchr(handler, ':');
|
||||
if (colon) {
|
||||
*colon = 0;
|
||||
}
|
||||
struct uwsgi_exception_handler *ueh = uwsgi_exception_handler_by_name(handler);
|
||||
if (!ueh) {
|
||||
uwsgi_log("unable to find exception handler: %s\n", handler);
|
||||
free(handler);
|
||||
exit(1);
|
||||
}
|
||||
free(handler);
|
||||
|
||||
struct uwsgi_exception_handler_instance *uehi = uwsgi_calloc(sizeof(struct uwsgi_exception_handler_instance));
|
||||
uehi->handler = ueh;
|
||||
if (colon) {
|
||||
uehi->arg = colon+1;
|
||||
}
|
||||
usl->custom_ptr = uehi;
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_exceptions_handler_thread_start() {
|
||||
|
||||
// start the exception_handler_thread
|
||||
uwsgi.exception_handler_thread = uwsgi_thread_new(uwsgi_exception_handler_thread_loop);
|
||||
if (!uwsgi.exception_handler_thread) {
|
||||
uwsgi_log("unable to spawn exception handler thread\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -42,7 +42,7 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop) (int, void *), v
|
||||
}
|
||||
|
||||
static void gateway_brutal_end() {
|
||||
_exit(UWSGI_END_CODE);
|
||||
_exit(UWSGI_END_CODE);
|
||||
}
|
||||
|
||||
void gateway_respawn(int id) {
|
||||
@@ -82,7 +82,7 @@ void gateway_respawn(int id) {
|
||||
|
||||
ug->loop(id, ug->data);
|
||||
// never here !!! (i hope)
|
||||
exit(1);
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
ug->pid = gw_pid;
|
||||
|
||||
-93
@@ -1,93 +0,0 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
// Bernstein classic hash (this is not static as it is used by other areas)
|
||||
uint32_t djb33x_hash(char *key, uint64_t keylen) {
|
||||
|
||||
register uint32_t hash = 5381;
|
||||
uint64_t i;
|
||||
|
||||
for (i = 0; i < keylen; i++) {
|
||||
hash = ((hash << 5) + hash) ^ key[i];
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
// Murmur2 hash Copyright (C) Austin Appleby
|
||||
// adapted from nginx
|
||||
uint32_t murmur2_hash(char *key, uint64_t keylen) {
|
||||
|
||||
uint32_t h, k;
|
||||
uint8_t *ukey = (uint8_t *) key;
|
||||
h = 0 ^ keylen;
|
||||
while (keylen >= 4) {
|
||||
k = ukey[0];
|
||||
k |= ukey[1] << 8;
|
||||
k |= ukey[2] << 16;
|
||||
k |= ukey[3] << 24;
|
||||
|
||||
k *= 0x5bd1e995;
|
||||
k ^= k >> 24;
|
||||
k *= 0x5bd1e995;
|
||||
|
||||
h *= 0x5bd1e995;
|
||||
h ^= k;
|
||||
|
||||
ukey += 4;
|
||||
keylen -= 4;
|
||||
}
|
||||
|
||||
switch (keylen) {
|
||||
case 3:
|
||||
h ^= key[2] << 16;
|
||||
case 2:
|
||||
h ^= key[1] << 8;
|
||||
case 1:
|
||||
h ^= key[0];
|
||||
h *= 0x5bd1e995;
|
||||
}
|
||||
|
||||
h ^= h >> 13;
|
||||
h *= 0x5bd1e995;
|
||||
h ^= h >> 15;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_hash_algo *uwsgi_hash_algo_get(char *name) {
|
||||
struct uwsgi_hash_algo *uha = uwsgi.hash_algos;
|
||||
while(uha) {
|
||||
if (!strcmp(name, uha->name)) {
|
||||
return uha;
|
||||
}
|
||||
uha = uha->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
void uwsgi_hash_algo_register(char *name, uint32_t (*func)(char *, uint64_t)) {
|
||||
|
||||
struct uwsgi_hash_algo *old_uha = NULL, *uha = uwsgi.hash_algos;
|
||||
while(uha) {
|
||||
if (!strcmp(uha->name, name)) return;
|
||||
old_uha = uha;
|
||||
uha = uha->next;
|
||||
}
|
||||
|
||||
uha = uwsgi_calloc(sizeof(struct uwsgi_hash_algo));
|
||||
uha->name = name;
|
||||
uha->func = func;
|
||||
if (old_uha) {
|
||||
old_uha->next = uha;
|
||||
}
|
||||
else {
|
||||
uwsgi.hash_algos = uha;
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_hash_algo_register_all() {
|
||||
uwsgi_hash_algo_register("djb33x", djb33x_hash);
|
||||
uwsgi_hash_algo_register("murmur2", murmur2_hash);
|
||||
}
|
||||
+4
-4
@@ -54,9 +54,9 @@ char *ini_get_key(char *key) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
char *ini_get_line(char *ini, size_t size) {
|
||||
char *ini_get_line(char *ini, off_t size) {
|
||||
|
||||
size_t i;
|
||||
off_t i;
|
||||
char *ptr = ini;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
@@ -78,7 +78,7 @@ char *ini_get_line(char *ini, size_t size) {
|
||||
|
||||
void uwsgi_ini_config(char *file, char *magic_table[]) {
|
||||
|
||||
size_t len = 0;
|
||||
int len = 0;
|
||||
char *ini;
|
||||
|
||||
char *ini_line;
|
||||
@@ -109,7 +109,7 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
|
||||
}
|
||||
|
||||
if (file[0] != 0) {
|
||||
uwsgi_log_initial("[uWSGI] getting INI configuration from %s\n", file);
|
||||
uwsgi_log("[uWSGI] getting INI configuration from %s\n", file);
|
||||
}
|
||||
|
||||
ini = uwsgi_open_and_read(file, &len, 1, magic_table);
|
||||
|
||||
+13
-168
@@ -2,61 +2,6 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct http_status_codes {
|
||||
const char key[3];
|
||||
const char *message;
|
||||
int message_size;
|
||||
};
|
||||
|
||||
/* statistically ordered */
|
||||
struct http_status_codes hsc[] = {
|
||||
{"200", "OK"},
|
||||
{"302", "Found"},
|
||||
{"404", "Not Found"},
|
||||
{"500", "Internal Server Error"},
|
||||
{"301", "Moved Permanently"},
|
||||
{"304", "Not Modified"},
|
||||
{"303", "See Other"},
|
||||
{"403", "Forbidden"},
|
||||
{"307", "Temporary Redirect"},
|
||||
{"401", "Unauthorized"},
|
||||
{"400", "Bad Request"},
|
||||
{"405", "Method Not Allowed"},
|
||||
{"408", "Request Timeout"},
|
||||
|
||||
{"100", "Continue"},
|
||||
{"101", "Switching Protocols"},
|
||||
{"201", "Created"},
|
||||
{"202", "Accepted"},
|
||||
{"203", "Non-Authoritative Information"},
|
||||
{"204", "No Content"},
|
||||
{"205", "Reset Content"},
|
||||
{"206", "Partial Content"},
|
||||
{"300", "Multiple Choices"},
|
||||
{"305", "Use Proxy"},
|
||||
{"402", "Payment Required"},
|
||||
{"406", "Not Acceptable"},
|
||||
{"407", "Proxy Authentication Required"},
|
||||
{"409", "Conflict"},
|
||||
{"410", "Gone"},
|
||||
{"411", "Length Required"},
|
||||
{"412", "Precondition Failed"},
|
||||
{"413", "Request Entity Too Large"},
|
||||
{"414", "Request-URI Too Long"},
|
||||
{"415", "Unsupported Media Type"},
|
||||
{"416", "Requested Range Not Satisfiable"},
|
||||
{"417", "Expectation Failed"},
|
||||
{"501", "Not Implemented"},
|
||||
{"502", "Bad Gateway"},
|
||||
{"503", "Service Unavailable"},
|
||||
{"504", "Gateway Timeout"},
|
||||
{"505", "HTTP Version Not Supported"},
|
||||
{"", NULL},
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
void uwsgi_init_default() {
|
||||
|
||||
uwsgi.cpus = 1;
|
||||
@@ -68,6 +13,7 @@ void uwsgi_init_default() {
|
||||
|
||||
uwsgi.signal_socket = -1;
|
||||
uwsgi.my_signal_socket = -1;
|
||||
uwsgi.cache_server_fd = -1;
|
||||
uwsgi.stats_fd = -1;
|
||||
|
||||
uwsgi.stats_pusher_default_freq = 3;
|
||||
@@ -86,18 +32,15 @@ void uwsgi_init_default() {
|
||||
uwsgi.subscribe_freq = 10;
|
||||
uwsgi.subscription_tolerance = 17;
|
||||
|
||||
uwsgi.cluster_fd = -1;
|
||||
uwsgi.cores = 1;
|
||||
uwsgi.threads = 1;
|
||||
|
||||
// default max number of rpc slot
|
||||
uwsgi.rpc_max = 64;
|
||||
|
||||
uwsgi.offload_threads_events = 64;
|
||||
|
||||
uwsgi.default_app = -1;
|
||||
|
||||
uwsgi.buffer_size = 4096;
|
||||
uwsgi.body_read_warning = 8;
|
||||
uwsgi.numproc = 1;
|
||||
|
||||
uwsgi.forkbomb_delay = 2;
|
||||
@@ -109,22 +52,18 @@ void uwsgi_init_default() {
|
||||
|
||||
uwsgi.log_master_bufsize = 8192;
|
||||
|
||||
uwsgi.worker_reload_mercy = 60;
|
||||
|
||||
uwsgi.max_vars = MAX_VARS;
|
||||
uwsgi.vec_size = 4 + 1 + (4 * MAX_VARS);
|
||||
|
||||
uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] = 4;
|
||||
uwsgi.shared->options[UWSGI_OPTION_LOGGING] = 1;
|
||||
|
||||
// a workers hould be running for at least 10 seconds
|
||||
uwsgi.shared->options[UWSGI_OPTION_MIN_WORKER_LIFETIME] = 10;
|
||||
|
||||
#ifdef UWSGI_SPOOLER
|
||||
uwsgi.shared->spooler_frequency = 30;
|
||||
|
||||
uwsgi.shared->spooler_signal_pipe[0] = -1;
|
||||
uwsgi.shared->spooler_signal_pipe[1] = -1;
|
||||
|
||||
#endif
|
||||
uwsgi.shared->mule_signal_pipe[0] = -1;
|
||||
uwsgi.shared->mule_signal_pipe[1] = -1;
|
||||
|
||||
@@ -134,37 +73,20 @@ void uwsgi_init_default() {
|
||||
uwsgi.shared->worker_log_pipe[0] = -1;
|
||||
uwsgi.shared->worker_log_pipe[1] = -1;
|
||||
|
||||
uwsgi.shared->worker_req_log_pipe[0] = -1;
|
||||
uwsgi.shared->worker_req_log_pipe[1] = -1;
|
||||
|
||||
uwsgi.req_log_fd = 2;
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
// 1 day of tolerance
|
||||
uwsgi.subscriptions_sign_check_tolerance = 3600 * 24;
|
||||
uwsgi.ssl_sessions_timeout = 300;
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_ALARM
|
||||
uwsgi.alarm_freq = 3;
|
||||
uwsgi.alarm_msg_size = 8192;
|
||||
#endif
|
||||
|
||||
uwsgi.exception_handler_msg_size = 65536;
|
||||
|
||||
#ifdef UWSGI_MULTICAST
|
||||
uwsgi.multicast_ttl = 1;
|
||||
uwsgi.multicast_loop = 1;
|
||||
#endif
|
||||
|
||||
// filling http status codes
|
||||
struct http_status_codes *http_sc;
|
||||
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
|
||||
http_sc->message_size = strlen(http_sc->message);
|
||||
}
|
||||
|
||||
uwsgi.empty = "";
|
||||
|
||||
uwsgi.wait_read_hook = uwsgi_simple_wait_read_hook;
|
||||
uwsgi.wait_write_hook = uwsgi_simple_wait_write_hook;
|
||||
|
||||
uwsgi_websockets_init();
|
||||
}
|
||||
|
||||
void uwsgi_setup_reload() {
|
||||
@@ -296,7 +218,7 @@ void uwsgi_commandline_config() {
|
||||
void uwsgi_setup_workers() {
|
||||
int i, j;
|
||||
// allocate shared memory for workers + master
|
||||
uwsgi.workers = (struct uwsgi_worker *) uwsgi_calloc_shared(sizeof(struct uwsgi_worker) * (uwsgi.numproc + 1));
|
||||
uwsgi.workers = (struct uwsgi_worker *) uwsgi_calloc_shared(sizeof(struct uwsgi_worker) * (uwsgi.numproc + 1 + uwsgi.grunt));
|
||||
|
||||
for (i = 0; i <= uwsgi.numproc; i++) {
|
||||
// allocate memory for apps
|
||||
@@ -307,8 +229,7 @@ void uwsgi_setup_workers() {
|
||||
|
||||
// this is a trick for avoiding too much memory areas
|
||||
void *ts = uwsgi_calloc_shared(sizeof(void *) * uwsgi.max_apps * uwsgi.cores);
|
||||
// add 4 bytes for uwsgi header
|
||||
void *buffers = uwsgi_malloc_shared((uwsgi.buffer_size+4) * uwsgi.cores);
|
||||
void *buffers = uwsgi_malloc_shared(uwsgi.buffer_size * uwsgi.cores);
|
||||
void *hvec = uwsgi_malloc_shared(sizeof(struct iovec) * uwsgi.vec_size * uwsgi.cores);
|
||||
void *post_buf = NULL;
|
||||
if (uwsgi.post_buffering > 0)
|
||||
@@ -318,8 +239,8 @@ void uwsgi_setup_workers() {
|
||||
for (j = 0; j < uwsgi.cores; j++) {
|
||||
// allocate shared memory for thread states (required for some language, like python)
|
||||
uwsgi.workers[i].cores[j].ts = ts + ((sizeof(void *) * uwsgi.max_apps) * j);
|
||||
// raw per-request buffer (+4 bytes for uwsgi header)
|
||||
uwsgi.workers[i].cores[j].buffer = buffers + ((uwsgi.buffer_size+4) * j);
|
||||
// raw per-request buffer
|
||||
uwsgi.workers[i].cores[j].buffer = buffers + (uwsgi.buffer_size * j);
|
||||
// iovec for uwsgi vars
|
||||
uwsgi.workers[i].cores[j].hvec = hvec + ((sizeof(struct iovec) * uwsgi.vec_size) * j);
|
||||
if (post_buf)
|
||||
@@ -341,11 +262,7 @@ void uwsgi_setup_workers() {
|
||||
}
|
||||
|
||||
total_memory *= (uwsgi.numproc + uwsgi.master_process);
|
||||
if (uwsgi.numproc > 0)
|
||||
uwsgi_log("mapped %llu bytes (%llu KB) for %d cores\n", (unsigned long long) total_memory, (unsigned long long) (total_memory / 1024), uwsgi.cores * uwsgi.numproc);
|
||||
|
||||
// allocate signal table
|
||||
uwsgi.shared->signal_table = uwsgi_calloc_shared(sizeof(struct uwsgi_signal_entry) * 256 * (uwsgi.numproc + 1));
|
||||
uwsgi_log("mapped %llu bytes (%llu KB) for %d cores\n", total_memory, total_memory / 1024, uwsgi.cores * uwsgi.numproc);
|
||||
|
||||
}
|
||||
|
||||
@@ -376,75 +293,3 @@ pid_t uwsgi_daemonize2() {
|
||||
|
||||
return uwsgi.mypid;
|
||||
}
|
||||
|
||||
// fix/check related options
|
||||
void sanitize_args() {
|
||||
|
||||
if (uwsgi.async > 1) {
|
||||
uwsgi.cores = uwsgi.async;
|
||||
}
|
||||
|
||||
if (uwsgi.threads > 1) {
|
||||
uwsgi.has_threads = 1;
|
||||
uwsgi.cores = uwsgi.threads;
|
||||
}
|
||||
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
|
||||
if (!uwsgi.post_buffering) {
|
||||
uwsgi_log(" *** WARNING: you have enabled harakiri without post buffering. Slow upload could be rejected on post-unbuffered webservers *** \n");
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.write_errors_exception_only) {
|
||||
uwsgi.ignore_sigpipe = 1;
|
||||
uwsgi.ignore_write_errors = 1;
|
||||
}
|
||||
|
||||
if (uwsgi.cheaper_count == 0) uwsgi.cheaper = 0;
|
||||
|
||||
if (uwsgi.cheaper_count > 0 && uwsgi.cheaper_count >= uwsgi.numproc) {
|
||||
uwsgi_log("invalid cheaper value: must be lower than processes\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (uwsgi.cheaper && uwsgi.cheaper_count) {
|
||||
if (uwsgi.cheaper_initial) {
|
||||
if (uwsgi.cheaper_initial < uwsgi.cheaper_count) {
|
||||
uwsgi_log("warning: invalid cheaper-initial value (%d), must be equal or higher than cheaper (%d), using %d as initial number of workers\n",
|
||||
uwsgi.cheaper_initial, uwsgi.cheaper_count, uwsgi.cheaper_count);
|
||||
uwsgi.cheaper_initial = uwsgi.cheaper_count;
|
||||
}
|
||||
else if (uwsgi.cheaper_initial > uwsgi.numproc) {
|
||||
uwsgi_log("warning: invalid cheaper-initial value (%d), must be lower or equal than worker count (%d), using %d as initial number of workers\n",
|
||||
uwsgi.cheaper_initial, uwsgi.numproc, uwsgi.numproc);
|
||||
uwsgi.cheaper_initial = uwsgi.numproc;
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi.cheaper_initial = uwsgi.cheaper_count;
|
||||
}
|
||||
}
|
||||
|
||||
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]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const char *uwsgi_http_status_msg(char *status, uint16_t *len) {
|
||||
struct http_status_codes *http_sc;
|
||||
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
|
||||
if (!strncmp(http_sc->key, status, 3)) {
|
||||
*len = http_sc->message_size;
|
||||
return http_sc->message;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+2
-2
@@ -13,7 +13,7 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
void uwsgi_json_config(char *file, char *magic_table[]) {
|
||||
|
||||
size_t len = 0;
|
||||
int len = 0;
|
||||
char *json_data;
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log_initial("[uWSGI] getting JSON configuration from %s\n", file);
|
||||
uwsgi_log("[uWSGI] getting JSON configuration from %s\n", file);
|
||||
|
||||
json_data = uwsgi_open_and_read(file, &len, 1, magic_table);
|
||||
|
||||
|
||||
-1022
File diff suppressed because it is too large
Load Diff
+6
-71
@@ -91,6 +91,7 @@ retry:
|
||||
}
|
||||
|
||||
#ifdef EOWNERDEAD
|
||||
|
||||
#ifndef PTHREAD_MUTEX_ROBUST
|
||||
#define PTHREAD_MUTEX_ROBUST PTHREAD_MUTEX_ROBUST_NP
|
||||
#endif
|
||||
@@ -401,60 +402,6 @@ void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
|
||||
uwsgi_unlock_fast(uli);
|
||||
}
|
||||
|
||||
#elif defined(UWSGI_LOCK_USE_WINDOWS_MUTEX)
|
||||
|
||||
#define UWSGI_LOCK_ENGINE_NAME "windows mutexes"
|
||||
#define UWSGI_LOCK_SIZE sizeof(HANDLE)
|
||||
#define UWSGI_RWLOCK_SIZE sizeof(HANDLE)
|
||||
|
||||
|
||||
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
|
||||
|
||||
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
|
||||
struct _SECURITY_ATTRIBUTES sa;
|
||||
memset(&sa, 0, sizeof(struct _SECURITY_ATTRIBUTES));
|
||||
sa.bInheritHandle = 1;
|
||||
uli->lock_ptr = CreateMutex(&sa, FALSE, NULL);
|
||||
return uli;
|
||||
}
|
||||
|
||||
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
|
||||
WaitForSingleObject(uli->lock_ptr, INFINITE);
|
||||
uli->pid = uwsgi.mypid;
|
||||
}
|
||||
|
||||
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
|
||||
ReleaseMutex(uli->lock_ptr);
|
||||
uli->pid = 0;
|
||||
}
|
||||
|
||||
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
|
||||
if (WaitForSingleObject(uli->lock_ptr, 0) == WAIT_TIMEOUT) {
|
||||
return 0;
|
||||
}
|
||||
return uli->pid;
|
||||
}
|
||||
|
||||
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
|
||||
return uwsgi_lock_fast_init(id);
|
||||
}
|
||||
|
||||
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) {
|
||||
uwsgi_lock_fast(uli);
|
||||
}
|
||||
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) {
|
||||
uwsgi_lock_fast(uli);
|
||||
}
|
||||
|
||||
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) {
|
||||
return uwsgi_lock_fast_check(uli);
|
||||
}
|
||||
|
||||
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
|
||||
uwsgi_unlock_fast(uli);
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#define uwsgi_lock_fast_init uwsgi_lock_ipcsem_init
|
||||
@@ -533,7 +480,7 @@ void uwsgi_lock_ipcsem(struct uwsgi_lock_item *uli) {
|
||||
|
||||
retry:
|
||||
if (semop(semid, &sb, 1)) {
|
||||
if (errno == EINTR) goto retry;
|
||||
if (errno == EINTR) goto retry;
|
||||
uwsgi_error("semop()");
|
||||
}
|
||||
}
|
||||
@@ -550,7 +497,7 @@ void uwsgi_unlock_ipcsem(struct uwsgi_lock_item *uli) {
|
||||
|
||||
retry:
|
||||
if (semop(semid, &sb, 1)) {
|
||||
if (errno == EINTR) goto retry;
|
||||
if (errno == EINTR) goto retry;
|
||||
uwsgi_error("semop()");
|
||||
}
|
||||
|
||||
@@ -615,10 +562,6 @@ pid_t uwsgi_rwlock_ipcsem_check(struct uwsgi_lock_item *uli) {
|
||||
|
||||
void uwsgi_setup_locking() {
|
||||
|
||||
int i;
|
||||
|
||||
if (uwsgi.locking_setup) return;
|
||||
|
||||
// use the fastest available locking
|
||||
if (uwsgi.lock_engine) {
|
||||
if (!strcmp(uwsgi.lock_engine, "ipcsem")) {
|
||||
@@ -657,8 +600,9 @@ void uwsgi_setup_locking() {
|
||||
uwsgi.lock_size = UWSGI_LOCK_SIZE;
|
||||
uwsgi.rwlock_size = UWSGI_RWLOCK_SIZE;
|
||||
|
||||
ready:
|
||||
// application generic lock
|
||||
int i;
|
||||
ready:
|
||||
uwsgi.user_lock = uwsgi_malloc(sizeof(void *) * (uwsgi.locks + 1));
|
||||
for (i = 0; i < uwsgi.locks + 1; i++) {
|
||||
uwsgi.user_lock[i] = uwsgi_lock_init(uwsgi_concat2("user ", uwsgi_num2str(i)));
|
||||
@@ -691,20 +635,11 @@ ready:
|
||||
|
||||
if (uwsgi.use_thunder_lock) {
|
||||
// process shared thunder lock
|
||||
uwsgi.the_thunder_lock = uwsgi_lock_init("thunder");
|
||||
uwsgi.the_thunder_lock = uwsgi_lock_init("thunder");
|
||||
}
|
||||
|
||||
uwsgi.rpc_table_lock = uwsgi_lock_init("rpc");
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
// register locking for legions
|
||||
struct uwsgi_legion *ul = uwsgi.legions;
|
||||
while(ul) {
|
||||
ul->lock = uwsgi_lock_init(uwsgi_concat2("legion_", ul->legion));
|
||||
ul = ul->next;
|
||||
}
|
||||
#endif
|
||||
uwsgi.locking_setup = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+130
-367
@@ -1,9 +1,9 @@
|
||||
#ifndef __DragonFly__
|
||||
#include <uwsgi.h>
|
||||
#endif
|
||||
#define _NO_UWSGI_RB
|
||||
#include "uwsgi.h"
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
|
||||
#include <sys/user.h>
|
||||
#include <kvm.h>
|
||||
#include <sys/user.h>
|
||||
#elif defined(__sun__)
|
||||
/* Terrible Hack !!! */
|
||||
#ifndef _LP64
|
||||
@@ -17,10 +17,6 @@
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
#ifdef __DragonFly__
|
||||
#include <uwsgi.h>
|
||||
#endif
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
//use this instead of fprintf to avoid buffering mess with udp logging
|
||||
@@ -148,21 +144,6 @@ void create_logpipe(void) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (uwsgi.req_log_master) {
|
||||
#if defined(SOCK_SEQPACKET) && defined(__linux__)
|
||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, uwsgi.shared->worker_req_log_pipe)) {
|
||||
#else
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, uwsgi.shared->worker_req_log_pipe)) {
|
||||
#endif
|
||||
uwsgi_error("socketpair()\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_socket_nb(uwsgi.shared->worker_req_log_pipe[0]);
|
||||
uwsgi_socket_nb(uwsgi.shared->worker_req_log_pipe[1]);
|
||||
uwsgi.req_log_fd = uwsgi.shared->worker_req_log_pipe[1];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
@@ -213,6 +194,7 @@ void logto(char *logfile) {
|
||||
|
||||
int fd;
|
||||
|
||||
#ifdef UWSGI_UDP
|
||||
char *udp_port;
|
||||
struct sockaddr_in udp_addr;
|
||||
|
||||
@@ -248,6 +230,7 @@ void logto(char *logfile) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
if (uwsgi.log_truncate) {
|
||||
fd = open(logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
}
|
||||
@@ -265,7 +248,9 @@ void logto(char *logfile) {
|
||||
uwsgi_error("chmod()");
|
||||
}
|
||||
}
|
||||
#ifdef UWSGI_UDP
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* stdout */
|
||||
@@ -309,70 +294,61 @@ void uwsgi_setup_log() {
|
||||
|
||||
}
|
||||
|
||||
static struct uwsgi_logger *setup_choosen_logger(struct uwsgi_string_list *usl) {
|
||||
char *id = NULL;
|
||||
char *name = usl->value;
|
||||
|
||||
char *space = strchr(name, ' ');
|
||||
if (space) {
|
||||
int is_id = 1;
|
||||
int i;
|
||||
for (i = 0; i < (space - name); i++) {
|
||||
if (!isalnum((int)name[i])) {
|
||||
is_id = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (is_id) {
|
||||
id = uwsgi_concat2n(name, space - name, "", 0);
|
||||
name = space + 1;
|
||||
}
|
||||
}
|
||||
|
||||
char *colon = strchr(name, ':');
|
||||
if (colon) {
|
||||
*colon = 0;
|
||||
}
|
||||
|
||||
struct uwsgi_logger *choosen_logger = uwsgi_get_logger(name);
|
||||
if (!choosen_logger) {
|
||||
uwsgi_log("unable to find logger %s\n", name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// make a copy of the logger
|
||||
struct uwsgi_logger *copy_of_choosen_logger = uwsgi_malloc(sizeof(struct uwsgi_logger));
|
||||
memcpy(copy_of_choosen_logger, choosen_logger, sizeof(struct uwsgi_logger));
|
||||
choosen_logger = copy_of_choosen_logger;
|
||||
choosen_logger->id = id;
|
||||
choosen_logger->next = NULL;
|
||||
|
||||
if (colon) {
|
||||
choosen_logger->arg = colon + 1;
|
||||
// check for empty string
|
||||
if (*choosen_logger->arg == 0) {
|
||||
choosen_logger->arg = NULL;
|
||||
}
|
||||
*colon = ':';
|
||||
}
|
||||
return choosen_logger;
|
||||
}
|
||||
|
||||
void uwsgi_setup_log_master(void) {
|
||||
|
||||
struct uwsgi_string_list *usl = uwsgi.requested_logger;
|
||||
while (usl) {
|
||||
struct uwsgi_logger *choosen_logger = setup_choosen_logger(usl);
|
||||
uwsgi_append_logger(choosen_logger);
|
||||
usl = usl->next;
|
||||
}
|
||||
char *id = NULL;
|
||||
char *name = usl->value;
|
||||
|
||||
usl = uwsgi.requested_req_logger;
|
||||
while (usl) {
|
||||
struct uwsgi_logger *choosen_logger = setup_choosen_logger(usl);
|
||||
uwsgi_append_req_logger(choosen_logger);
|
||||
usl = usl->next;
|
||||
}
|
||||
char *space = strchr(name, ' ');
|
||||
if (space) {
|
||||
int is_id = 1;
|
||||
int i;
|
||||
for (i = 0; i < (space - name); i++) {
|
||||
if (!isalnum(name[i])) {
|
||||
is_id = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (is_id) {
|
||||
id = uwsgi_concat2n(name, space - name, "", 0);
|
||||
name = space + 1;
|
||||
}
|
||||
}
|
||||
|
||||
char *colon = strchr(name, ':');
|
||||
if (colon) {
|
||||
*colon = 0;
|
||||
}
|
||||
|
||||
struct uwsgi_logger *choosen_logger = uwsgi_get_logger(name);
|
||||
if (!choosen_logger) {
|
||||
uwsgi_log("unable to find logger %s\n", name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// make a copy of the logger
|
||||
struct uwsgi_logger *copy_of_choosen_logger = uwsgi_malloc(sizeof(struct uwsgi_logger));
|
||||
memcpy(copy_of_choosen_logger, choosen_logger, sizeof(struct uwsgi_logger));
|
||||
choosen_logger = copy_of_choosen_logger;
|
||||
choosen_logger->id = id;
|
||||
choosen_logger->next = NULL;
|
||||
|
||||
if (colon) {
|
||||
choosen_logger->arg = colon + 1;
|
||||
// check for empty string
|
||||
if (*choosen_logger->arg == 0) {
|
||||
choosen_logger->arg = NULL;
|
||||
}
|
||||
*colon = ':';
|
||||
}
|
||||
|
||||
uwsgi_append_logger(choosen_logger);
|
||||
|
||||
usl = usl->next;
|
||||
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
// set logger by its id
|
||||
@@ -381,11 +357,6 @@ void uwsgi_setup_log_master(void) {
|
||||
url->custom_ptr = uwsgi_get_logger_from_id(url->custom_str);
|
||||
url = url->next;
|
||||
}
|
||||
url = uwsgi.log_req_route;
|
||||
while (url) {
|
||||
url->custom_ptr = uwsgi_get_logger_from_id(url->custom_str);
|
||||
url = url->next;
|
||||
}
|
||||
#endif
|
||||
|
||||
uwsgi.original_log_fd = dup(1);
|
||||
@@ -487,13 +458,13 @@ void uwsgi_check_logrotate(void) {
|
||||
uwsgi_error_open(uwsgi.logfile);
|
||||
grace_them_all(0);
|
||||
}
|
||||
else {
|
||||
if (dup2(fd, uwsgi.original_log_fd) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
grace_them_all(0);
|
||||
}
|
||||
close(fd);
|
||||
if (dup2(fd, uwsgi.original_log_fd) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
grace_them_all(0);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
}
|
||||
else {
|
||||
uwsgi_error("unable to rotate log: rename()");
|
||||
@@ -556,7 +527,7 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_LOG_BIG] && (wsgi_req->response_size >= uwsgi.shared->options[UWSGI_OPTION_LOG_BIG])) {
|
||||
goto logit;
|
||||
}
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_LOG_SENDFILE] && wsgi_req->via == UWSGI_VIA_SENDFILE) {
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_LOG_SENDFILE] && (wsgi_req->sendfile_fd > -1 && wsgi_req->sendfile_obj == wsgi_req->async_result)) {
|
||||
goto logit;
|
||||
}
|
||||
|
||||
@@ -601,19 +572,16 @@ void uwsgi_logit_simple(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
}
|
||||
|
||||
// mark requests via (sendfile, route, offload...)
|
||||
switch(wsgi_req->via) {
|
||||
case UWSGI_VIA_SENDFILE:
|
||||
via = msg1;
|
||||
break;
|
||||
case UWSGI_VIA_ROUTE:
|
||||
via = msg3;
|
||||
break;
|
||||
case UWSGI_VIA_OFFLOAD:
|
||||
via = msg4;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if (wsgi_req->sendfile_fd > -1 && wsgi_req->sendfile_obj == wsgi_req->async_result) { //wsgi_req->sendfile_fd_size > 0 ) {
|
||||
via = msg1;
|
||||
}
|
||||
|
||||
// mark route() requests
|
||||
if (wsgi_req->status == -17) {
|
||||
via = msg3;
|
||||
}
|
||||
else if (wsgi_req->status == -30) {
|
||||
via = msg4;
|
||||
}
|
||||
|
||||
#ifdef __sun__
|
||||
@@ -654,13 +622,11 @@ void uwsgi_logit_simple(struct wsgi_request *wsgi_req) {
|
||||
|
||||
}
|
||||
|
||||
rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %llu bytes in %llu %s%s(%.*s %d) %d headers in %llu bytes (%d switches on core %d)\n", (int) uwsgi.mypid, wsgi_req->app_id, app_req, (unsigned long long) uwsgi.workers[0].requests, wsgi_req->remote_addr_len, wsgi_req->remote_addr, wsgi_req->remote_user_len, wsgi_req->remote_user, wsgi_req->var_cnt, wsgi_req->uh->pktsize,
|
||||
24, time_request, wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri, (unsigned long long) wsgi_req->response_size, (unsigned long long) rt, tsize, via, wsgi_req->protocol_len, wsgi_req->protocol, wsgi_req->status, wsgi_req->header_cnt, (unsigned long long) wsgi_req->headers_size, wsgi_req->switches, wsgi_req->async_id);
|
||||
rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %llu bytes in %llu %s%s(%.*s %d) %d headers in %llu bytes (%d switches on core %d)\n", (int) uwsgi.mypid, wsgi_req->app_id, app_req, (unsigned long long) uwsgi.workers[0].requests, wsgi_req->remote_addr_len, wsgi_req->remote_addr, wsgi_req->remote_user_len, wsgi_req->remote_user, wsgi_req->var_cnt, wsgi_req->uh.pktsize, 24, time_request, wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri, (unsigned long long) wsgi_req->response_size, (unsigned long long) rt, tsize, via, wsgi_req->protocol_len, wsgi_req->protocol, wsgi_req->status, wsgi_req->header_cnt, (unsigned long long) wsgi_req->headers_size, wsgi_req->switches, wsgi_req->async_id);
|
||||
|
||||
// not enough space for logging the request, just log a (safe) minimal message
|
||||
if (rlen > 4096) {
|
||||
rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] 0.0.0.0 () {%d vars in %d bytes} [%.*s] - - => generated %llu bytes in %llu %s%s(- %d) %d headers in %llu bytes (%d switches on core %d)\n", (int) uwsgi.mypid, wsgi_req->app_id, app_req, (unsigned long long) uwsgi.workers[0].requests, wsgi_req->var_cnt, wsgi_req->uh->pktsize,
|
||||
24, time_request, (unsigned long long) wsgi_req->response_size, (unsigned long long) rt, tsize, via, wsgi_req->status, wsgi_req->header_cnt, (unsigned long long) wsgi_req->headers_size, wsgi_req->switches, wsgi_req->async_id);
|
||||
rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] 0.0.0.0 () {%d vars in %d bytes} [%.*s] - - => generated %llu bytes in %llu %s%s(- %d) %d headers in %llu bytes (%d switches on core %d)\n", (int) uwsgi.mypid, wsgi_req->app_id, app_req, (unsigned long long) uwsgi.workers[0].requests, wsgi_req->var_cnt, wsgi_req->uh.pktsize, 24, time_request, (unsigned long long) wsgi_req->response_size, (unsigned long long) rt, tsize, via, wsgi_req->status, wsgi_req->header_cnt, (unsigned long long) wsgi_req->headers_size, wsgi_req->switches, wsgi_req->async_id);
|
||||
// argh, last resort, truncate it
|
||||
if (rlen > 4096) {
|
||||
rlen = 4096;
|
||||
@@ -671,7 +637,7 @@ void uwsgi_logit_simple(struct wsgi_request *wsgi_req) {
|
||||
logvec[logvecpos].iov_len = rlen;
|
||||
|
||||
// do not check for errors
|
||||
rlen = writev(uwsgi.req_log_fd, logvec, logvecpos + 1);
|
||||
rlen = writev(2, logvec, logvecpos + 1);
|
||||
}
|
||||
|
||||
void get_memusage(uint64_t * rss, uint64_t * vsz) {
|
||||
@@ -690,18 +656,6 @@ void get_memusage(uint64_t * rss, uint64_t * vsz) {
|
||||
fclose(procfile);
|
||||
}
|
||||
*rss = *rss * uwsgi.page_size;
|
||||
#elif defined(__CYGWIN__)
|
||||
// same as Linux but rss is not in pages...
|
||||
FILE *procfile;
|
||||
int i;
|
||||
procfile = fopen("/proc/self/stat", "r");
|
||||
if (procfile) {
|
||||
i = fscanf(procfile, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %llu %lld", (unsigned long long *) vsz, (unsigned long long *) rss);
|
||||
if (i != 2) {
|
||||
uwsgi_log("warning: invalid record in /proc/self/stat\n");
|
||||
}
|
||||
fclose(procfile);
|
||||
}
|
||||
#elif defined (__sun__)
|
||||
psinfo_t info;
|
||||
int procfd;
|
||||
@@ -741,13 +695,8 @@ void get_memusage(uint64_t * rss, uint64_t * vsz) {
|
||||
struct kinfo_proc *kproc;
|
||||
kproc = kvm_getprocs(kv, KERN_PROC_PID, uwsgi.mypid, &cnt);
|
||||
if (kproc && cnt > 0) {
|
||||
#if defined(__FreeBSD__)
|
||||
*vsz = kproc->ki_size;
|
||||
*rss = kproc->ki_rssize * uwsgi.page_size;
|
||||
#elif defined(__DragonFly__)
|
||||
*vsz = kproc->kp_vm_map_size;
|
||||
*rss = kproc->kp_vm_rssize * uwsgi.page_size;
|
||||
#endif
|
||||
}
|
||||
#elif defined(UWSGI_NEW_OPENBSD)
|
||||
struct kinfo_proc *kproc;
|
||||
@@ -812,7 +761,6 @@ void uwsgi_register_logger(char *name, ssize_t(*func) (struct uwsgi_logger *, ch
|
||||
ul->configured = 0;
|
||||
ul->fd = -1;
|
||||
ul->data = NULL;
|
||||
ul->buf = NULL;
|
||||
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
@@ -837,24 +785,6 @@ void uwsgi_append_logger(struct uwsgi_logger *ul) {
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_append_req_logger(struct uwsgi_logger *ul) {
|
||||
|
||||
if (!uwsgi.choosen_req_logger) {
|
||||
uwsgi.choosen_req_logger = ul;
|
||||
return;
|
||||
}
|
||||
|
||||
struct uwsgi_logger *ucl = uwsgi.choosen_req_logger;
|
||||
while (ucl) {
|
||||
if (!ucl->next) {
|
||||
ucl->next = ul;
|
||||
return;
|
||||
}
|
||||
ucl = ucl->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_logger *uwsgi_get_logger(char *name) {
|
||||
struct uwsgi_logger *ul = uwsgi.loggers;
|
||||
|
||||
@@ -925,13 +855,13 @@ void uwsgi_logit_lf(struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (uwsgi.logvectors[wsgi_req->async_id][pos].iov_len == 0 && logchunk->type != 0) {
|
||||
uwsgi.logvectors[wsgi_req->async_id][pos].iov_base = (char *) empty_var;
|
||||
uwsgi.logvectors[wsgi_req->async_id][pos].iov_len = 1;
|
||||
uwsgi.logvectors[wsgi_req->async_id][pos].iov_len = 1;
|
||||
}
|
||||
logchunk = logchunk->next;
|
||||
}
|
||||
|
||||
// do not check for errors
|
||||
rlen = writev(uwsgi.req_log_fd, uwsgi.logvectors[wsgi_req->async_id], uwsgi.logformat_vectors);
|
||||
rlen = writev(2, uwsgi.logvectors[wsgi_req->async_id], uwsgi.logformat_vectors);
|
||||
|
||||
// free allocated memory
|
||||
logchunk = uwsgi.logchunks;
|
||||
@@ -1006,25 +936,24 @@ static ssize_t uwsgi_lf_status(struct wsgi_request *wsgi_req, char **buf) {
|
||||
return strlen(*buf);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t uwsgi_lf_rsize(struct wsgi_request *wsgi_req, char **buf) {
|
||||
*buf = uwsgi_num2str(wsgi_req->response_size);
|
||||
return strlen(*buf);
|
||||
*buf = uwsgi_num2str(wsgi_req->response_size);
|
||||
return strlen(*buf);
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_lf_hsize(struct wsgi_request *wsgi_req, char **buf) {
|
||||
*buf = uwsgi_num2str(wsgi_req->headers_size);
|
||||
return strlen(*buf);
|
||||
*buf = uwsgi_num2str(wsgi_req->headers_size);
|
||||
return strlen(*buf);
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_lf_size(struct wsgi_request *wsgi_req, char **buf) {
|
||||
*buf = uwsgi_num2str(wsgi_req->headers_size+wsgi_req->response_size);
|
||||
return strlen(*buf);
|
||||
*buf = uwsgi_num2str(wsgi_req->headers_size+wsgi_req->response_size);
|
||||
return strlen(*buf);
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_lf_cl(struct wsgi_request *wsgi_req, char **buf) {
|
||||
*buf = uwsgi_num2str(wsgi_req->post_cl);
|
||||
return strlen(*buf);
|
||||
*buf = uwsgi_num2str(wsgi_req->post_cl);
|
||||
return strlen(*buf);
|
||||
}
|
||||
|
||||
|
||||
@@ -1048,19 +977,19 @@ static ssize_t uwsgi_lf_time(struct wsgi_request * wsgi_req, char **buf) {
|
||||
return strlen(*buf);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t uwsgi_lf_ltime(struct wsgi_request * wsgi_req, char **buf) {
|
||||
*buf = uwsgi_malloc(64);
|
||||
time_t now = wsgi_req->start_of_request / 1000000;
|
||||
size_t ret = strftime(*buf, 64, "%d/%b/%Y:%H:%M:%S %z", localtime(&now));
|
||||
if (ret == 0) {
|
||||
*buf[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
return ret;
|
||||
*buf = uwsgi_malloc(64);
|
||||
time_t now = wsgi_req->start_of_request / 1000000;
|
||||
size_t ret = strftime(*buf, 64, "%d/%b/%Y:%H:%M:%S %z", localtime(&now));
|
||||
if (ret == 0) {
|
||||
*buf[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static ssize_t uwsgi_lf_micros(struct wsgi_request * wsgi_req, char **buf) {
|
||||
*buf = uwsgi_num2str(wsgi_req->end_of_request - wsgi_req->start_of_request);
|
||||
return strlen(*buf);
|
||||
@@ -1117,17 +1046,17 @@ static ssize_t uwsgi_lf_rssM(struct wsgi_request * wsgi_req, char **buf) {
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_lf_pktsize(struct wsgi_request * wsgi_req, char **buf) {
|
||||
*buf = uwsgi_num2str(wsgi_req->uh->pktsize);
|
||||
*buf = uwsgi_num2str(wsgi_req->uh.pktsize);
|
||||
return strlen(*buf);
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_lf_modifier1(struct wsgi_request * wsgi_req, char **buf) {
|
||||
*buf = uwsgi_num2str(wsgi_req->uh->modifier1);
|
||||
*buf = uwsgi_num2str(wsgi_req->uh.modifier1);
|
||||
return strlen(*buf);
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_lf_modifier2(struct wsgi_request * wsgi_req, char **buf) {
|
||||
*buf = uwsgi_num2str(wsgi_req->uh->modifier2);
|
||||
*buf = uwsgi_num2str(wsgi_req->uh.modifier2);
|
||||
return strlen(*buf);
|
||||
}
|
||||
|
||||
@@ -1194,38 +1123,38 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
|
||||
logchunk->pos_len = offsetof(struct wsgi_request, protocol_len);
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "uagent", 6)) {
|
||||
logchunk->pos = offsetof(struct wsgi_request, user_agent);
|
||||
logchunk->pos_len = offsetof(struct wsgi_request, user_agent_len);
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "referer", 7)) {
|
||||
logchunk->pos = offsetof(struct wsgi_request, referer);
|
||||
logchunk->pos_len = offsetof(struct wsgi_request, referer_len);
|
||||
}
|
||||
logchunk->pos = offsetof(struct wsgi_request, user_agent);
|
||||
logchunk->pos_len = offsetof(struct wsgi_request, user_agent_len);
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "referer", 7)) {
|
||||
logchunk->pos = offsetof(struct wsgi_request, referer);
|
||||
logchunk->pos_len = offsetof(struct wsgi_request, referer_len);
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "status", 6)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_status;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "rsize", 5)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_rsize;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "hsize", 5)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_hsize;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "size", 4)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_size;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "cl", 2)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_cl;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_rsize;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "hsize", 5)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_hsize;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "size", 4)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_size;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "cl", 2)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_cl;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "micros", 6)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_micros;
|
||||
@@ -1242,10 +1171,10 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "ltime", 5)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_ltime;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_ltime;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "ctime", 5)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_ctime;
|
||||
@@ -1327,169 +1256,3 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int uwsgi_master_log(void) {
|
||||
|
||||
ssize_t rlen = read(uwsgi.shared->worker_log_pipe[0], uwsgi.log_master_buf, uwsgi.log_master_bufsize);
|
||||
if (rlen > 0) {
|
||||
#ifdef UWSGI_PCRE
|
||||
uwsgi_alarm_log_check(uwsgi.log_master_buf, rlen);
|
||||
struct uwsgi_regexp_list *url = uwsgi.log_drain_rules;
|
||||
while (url) {
|
||||
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, uwsgi.log_master_buf, rlen) >= 0) {
|
||||
return 0;
|
||||
}
|
||||
url = url->next;
|
||||
}
|
||||
if (uwsgi.log_filter_rules) {
|
||||
int show = 0;
|
||||
url = uwsgi.log_filter_rules;
|
||||
while (url) {
|
||||
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, uwsgi.log_master_buf, rlen) >= 0) {
|
||||
show = 1;
|
||||
break;
|
||||
}
|
||||
url = url->next;
|
||||
}
|
||||
if (!show)
|
||||
return 0;
|
||||
}
|
||||
|
||||
url = uwsgi.log_route;
|
||||
int finish = 0;
|
||||
while (url) {
|
||||
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, uwsgi.log_master_buf, rlen) >= 0) {
|
||||
struct uwsgi_logger *ul_route = (struct uwsgi_logger *) url->custom_ptr;
|
||||
if (ul_route) {
|
||||
ul_route->func(ul_route, uwsgi.log_master_buf, rlen);
|
||||
finish = 1;
|
||||
}
|
||||
}
|
||||
url = url->next;
|
||||
}
|
||||
if (finish)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
int raw_log = 1;
|
||||
|
||||
struct uwsgi_logger *ul = uwsgi.choosen_logger;
|
||||
while (ul) {
|
||||
// check for named logger
|
||||
if (ul->id) {
|
||||
goto next;
|
||||
}
|
||||
ul->func(ul, uwsgi.log_master_buf, rlen);
|
||||
raw_log = 0;
|
||||
next:
|
||||
ul = ul->next;
|
||||
}
|
||||
|
||||
if (raw_log) {
|
||||
rlen = write(uwsgi.original_log_fd, uwsgi.log_master_buf, rlen);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int uwsgi_master_req_log(void) {
|
||||
|
||||
ssize_t rlen = read(uwsgi.shared->worker_req_log_pipe[0], uwsgi.log_master_buf, uwsgi.log_master_bufsize);
|
||||
if (rlen > 0) {
|
||||
#ifdef UWSGI_PCRE
|
||||
struct uwsgi_regexp_list *url = uwsgi.log_req_route;
|
||||
int finish = 0;
|
||||
while (url) {
|
||||
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, uwsgi.log_master_buf, rlen) >= 0) {
|
||||
struct uwsgi_logger *ul_route = (struct uwsgi_logger *) url->custom_ptr;
|
||||
if (ul_route) {
|
||||
ul_route->func(ul_route, uwsgi.log_master_buf, rlen);
|
||||
finish = 1;
|
||||
}
|
||||
}
|
||||
url = url->next;
|
||||
}
|
||||
if (finish)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
int raw_log = 1;
|
||||
|
||||
struct uwsgi_logger *ul = uwsgi.choosen_req_logger;
|
||||
while (ul) {
|
||||
// check for named logger
|
||||
if (ul->id) {
|
||||
goto next;
|
||||
}
|
||||
ul->func(ul, uwsgi.log_master_buf, rlen);
|
||||
raw_log = 0;
|
||||
next:
|
||||
ul = ul->next;
|
||||
}
|
||||
|
||||
if (raw_log) {
|
||||
rlen = write(uwsgi.original_log_fd, uwsgi.log_master_buf, rlen);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void *logger_thread_loop(void *noarg) {
|
||||
struct pollfd logpoll[2];
|
||||
|
||||
// block all signals
|
||||
sigset_t smask;
|
||||
sigfillset(&smask);
|
||||
pthread_sigmask(SIG_BLOCK, &smask, NULL);
|
||||
|
||||
logpoll[0].events = POLLIN;
|
||||
logpoll[0].fd = uwsgi.shared->worker_log_pipe[0];
|
||||
|
||||
int logpolls = 1;
|
||||
|
||||
if (uwsgi.req_log_master) {
|
||||
logpoll[1].events = POLLIN;
|
||||
logpoll[1].fd = uwsgi.shared->worker_req_log_pipe[0];
|
||||
}
|
||||
|
||||
|
||||
for (;;) {
|
||||
int ret = poll(logpoll, logpolls, -1);
|
||||
if (ret > 0) {
|
||||
if (logpoll[0].revents & POLLIN) {
|
||||
pthread_mutex_lock(&uwsgi.threaded_logger_lock);
|
||||
uwsgi_master_log();
|
||||
pthread_mutex_unlock(&uwsgi.threaded_logger_lock);
|
||||
}
|
||||
else if (logpolls > 1 && logpoll[1].revents & POLLIN) {
|
||||
pthread_mutex_lock(&uwsgi.threaded_logger_lock);
|
||||
uwsgi_master_req_log();
|
||||
pthread_mutex_unlock(&uwsgi.threaded_logger_lock);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void uwsgi_threaded_logger_spawn() {
|
||||
pthread_t logger_thread;
|
||||
|
||||
if (pthread_create(&logger_thread, NULL, logger_thread_loop, NULL)) {
|
||||
uwsgi_error("pthread_create()");
|
||||
uwsgi_log("falling back to non-threaded logger...\n");
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->worker_log_pipe[0]);
|
||||
if (uwsgi.req_log_master) {
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->worker_req_log_pipe[0]);
|
||||
}
|
||||
uwsgi.threaded_logger = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-1
@@ -64,10 +64,12 @@ void simple_loop() {
|
||||
|
||||
void uwsgi_loop_cores_run(void *(*func) (void *)) {
|
||||
int i;
|
||||
#ifdef UWSGI_THREADING
|
||||
for (i = 1; i < uwsgi.threads; i++) {
|
||||
long j = i;
|
||||
pthread_create(&uwsgi.workers[uwsgi.mywid].cores[i].thread_id, &uwsgi.threads_attr, func, (void *) j);
|
||||
}
|
||||
#endif
|
||||
long y = 0;
|
||||
func((void *) y);
|
||||
}
|
||||
@@ -118,9 +120,12 @@ void *simple_loop_run(void *arg1) {
|
||||
|
||||
struct wsgi_request *wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[core_id].req;
|
||||
|
||||
#ifdef UWSGI_THREADING
|
||||
if (uwsgi.threads > 1) {
|
||||
uwsgi_setup_thread_req(core_id, wsgi_req);
|
||||
}
|
||||
#endif
|
||||
|
||||
// initialize the main event queue to monitor sockets
|
||||
int main_queue = event_queue_init();
|
||||
|
||||
@@ -141,7 +146,7 @@ void *simple_loop_run(void *arg1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (wsgi_req_recv(main_queue, wsgi_req)) {
|
||||
if (wsgi_req_recv(wsgi_req)) {
|
||||
uwsgi_destroy_request(wsgi_req);
|
||||
continue;
|
||||
}
|
||||
|
||||
+872
-156
File diff suppressed because it is too large
Load Diff
@@ -1,278 +0,0 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
// check if all of the workers are dead and exit uWSGI
|
||||
void uwsgi_master_check_death() {
|
||||
if (uwsgi_instance_is_dying) {
|
||||
int i;
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (uwsgi.workers[i].pid > 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
uwsgi_log("goodbye to uWSGI.\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
// check if all of the workers are dead, and trigger a reload
|
||||
int uwsgi_master_check_reload(char **argv) {
|
||||
if (uwsgi_instance_is_reloading) {
|
||||
int i;
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (uwsgi.workers[i].pid > 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
uwsgi_reload(argv);
|
||||
// never here (unless in shared library mode)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// check for chain reload
|
||||
void uwsgi_master_check_chain() {
|
||||
if (!uwsgi.status.chain_reloading) return;
|
||||
if (uwsgi.status.chain_reloading > uwsgi.numproc) {
|
||||
uwsgi.status.chain_reloading = 0;
|
||||
uwsgi_log_verbose("chain reloading complete\n");
|
||||
}
|
||||
int i;
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].cursed_at == 0 && i == uwsgi.status.chain_reloading) {
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
break;
|
||||
}
|
||||
}
|
||||
uwsgi_unblock_signal(SIGHUP);
|
||||
}
|
||||
|
||||
|
||||
// special function for assuming all of the workers are dead
|
||||
void uwsgi_master_commit_status() {
|
||||
int i;
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
uwsgi.workers[i].pid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_master_check_idle() {
|
||||
|
||||
static time_t last_request_timecheck = 0;
|
||||
static uint64_t last_request_count = 0;
|
||||
int i;
|
||||
int waitpid_status;
|
||||
|
||||
if (!uwsgi.idle || uwsgi.status.is_cheap)
|
||||
return;
|
||||
|
||||
uwsgi.current_time = uwsgi_now();
|
||||
if (!last_request_timecheck)
|
||||
last_request_timecheck = uwsgi.current_time;
|
||||
|
||||
// security check, stop the check if there are busy workers
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
|
||||
if (uwsgi_worker_is_busy(i)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (last_request_count != uwsgi.workers[0].requests) {
|
||||
last_request_timecheck = uwsgi.current_time;
|
||||
last_request_count = uwsgi.workers[0].requests;
|
||||
}
|
||||
// a bit of over-engeneering to avoid clock skews
|
||||
else if (last_request_timecheck < uwsgi.current_time && (uwsgi.current_time - last_request_timecheck > uwsgi.idle)) {
|
||||
uwsgi_log("workers have been inactive for more than %d seconds (%llu-%llu)\n", uwsgi.idle, (unsigned long long) uwsgi.current_time, (unsigned long long) last_request_timecheck);
|
||||
uwsgi.status.is_cheap = 1;
|
||||
if (uwsgi.die_on_idle) {
|
||||
if (uwsgi.has_emperor) {
|
||||
char byte = 22;
|
||||
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
kill_them_all(0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
kill_them_all(0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
uwsgi.workers[i].cheaped = 1;
|
||||
if (uwsgi.workers[i].pid == 0)
|
||||
continue;
|
||||
kill(uwsgi.workers[i].pid, SIGKILL);
|
||||
if (waitpid(uwsgi.workers[i].pid, &waitpid_status, 0) < 0) {
|
||||
if (errno != ECHILD)
|
||||
uwsgi_error("uwsgi_master_check_idle()/waitpid()");
|
||||
}
|
||||
}
|
||||
uwsgi_add_sockets_to_queue(uwsgi.master_queue, -1);
|
||||
uwsgi_log("cheap mode enabled: waiting for socket connection...\n");
|
||||
last_request_timecheck = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_master_check_workers_deadline() {
|
||||
int i;
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
/* first check for harakiri */
|
||||
if (uwsgi.workers[i].harakiri > 0) {
|
||||
if (uwsgi.workers[i].harakiri < (time_t) uwsgi.current_time) {
|
||||
trigger_harakiri(i);
|
||||
}
|
||||
}
|
||||
/* then user-defined harakiri */
|
||||
if (uwsgi.workers[i].user_harakiri > 0) {
|
||||
if (uwsgi.workers[i].user_harakiri < (time_t) uwsgi.current_time) {
|
||||
trigger_harakiri(i);
|
||||
}
|
||||
}
|
||||
// then for evil memory checkers
|
||||
if (uwsgi.evil_reload_on_as) {
|
||||
if ((rlim_t) uwsgi.workers[i].vsz_size >= uwsgi.evil_reload_on_as) {
|
||||
uwsgi_log("*** EVIL RELOAD ON WORKER %d ADDRESS SPACE: %lld (pid: %d) ***\n", i, (long long) uwsgi.workers[i].vsz_size, uwsgi.workers[i].pid);
|
||||
kill(uwsgi.workers[i].pid, SIGKILL);
|
||||
uwsgi.workers[i].vsz_size = 0;
|
||||
}
|
||||
}
|
||||
if (uwsgi.evil_reload_on_rss) {
|
||||
if ((rlim_t) uwsgi.workers[i].rss_size >= uwsgi.evil_reload_on_rss) {
|
||||
uwsgi_log("*** EVIL RELOAD ON WORKER %d RSS: %lld (pid: %d) ***\n", i, (long long) uwsgi.workers[i].rss_size, uwsgi.workers[i].pid);
|
||||
kill(uwsgi.workers[i].pid, SIGKILL);
|
||||
uwsgi.workers[i].rss_size = 0;
|
||||
}
|
||||
}
|
||||
// check if worker was running longer than allowed lifetime
|
||||
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0 && uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME] > 0) {
|
||||
uint64_t lifetime = uwsgi_now() - uwsgi.workers[i].last_spawn;
|
||||
if (lifetime > uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME] && uwsgi.workers[i].manage_next_request == 1) {
|
||||
uwsgi_log("worker %d lifetime reached, it was running for %llu second(s)\n", i, (unsigned long long) lifetime);
|
||||
uwsgi.workers[i].manage_next_request = 0;
|
||||
kill(uwsgi.workers[i].pid, SIGWINCH);
|
||||
}
|
||||
}
|
||||
|
||||
// need to find a better way
|
||||
//uwsgi.workers[i].last_running_time = uwsgi.workers[i].running_time;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_master_check_gateways_deadline() {
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ushared->gateways_cnt; i++) {
|
||||
if (ushared->gateways_harakiri[i] > 0) {
|
||||
if (ushared->gateways_harakiri[i] < (time_t) uwsgi.current_time) {
|
||||
if (ushared->gateways[i].pid > 0) {
|
||||
kill(ushared->gateways[i].pid, SIGKILL);
|
||||
}
|
||||
ushared->gateways_harakiri[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_master_check_mules_deadline() {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].harakiri > 0) {
|
||||
if (uwsgi.mules[i].harakiri < (time_t) uwsgi.current_time) {
|
||||
uwsgi_log("*** HARAKIRI ON MULE %d HANDLING SIGNAL %d (pid: %d) ***\n", i + 1, uwsgi.mules[i].signum, uwsgi.mules[i].pid);
|
||||
kill(uwsgi.mules[i].pid, SIGKILL);
|
||||
uwsgi.mules[i].harakiri = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_master_check_spoolers_deadline() {
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
while (uspool) {
|
||||
if (uspool->harakiri > 0 && uspool->harakiri < (time_t) uwsgi.current_time) {
|
||||
uwsgi_log("*** HARAKIRI ON THE SPOOLER (pid: %d) ***\n", uspool->pid);
|
||||
kill(uspool->pid, SIGKILL);
|
||||
uspool->harakiri = 0;
|
||||
}
|
||||
uspool = uspool->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_master_check_spoolers_death(int diedpid) {
|
||||
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
while (uspool) {
|
||||
if (uspool->pid > 0 && diedpid == uspool->pid) {
|
||||
uwsgi_log("OOOPS the spooler is no more...trying respawn...\n");
|
||||
uspool->respawned++;
|
||||
uspool->pid = spooler_start(uspool);
|
||||
return -1;
|
||||
}
|
||||
uspool = uspool->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_master_check_emperor_death(int diedpid) {
|
||||
if (uwsgi.emperor_pid >= 0 && diedpid == uwsgi.emperor_pid) {
|
||||
uwsgi_log_verbose("!!! Emperor died !!!\n");
|
||||
uwsgi_emperor_start();
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_master_check_mules_death(int diedpid) {
|
||||
int i;
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].pid == diedpid) {
|
||||
uwsgi_log("OOOPS mule %d (pid: %d) crippled...trying respawn...\n", i + 1, uwsgi.mules[i].pid);
|
||||
uwsgi_mule(i + 1);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_master_check_gateways_death(int diedpid) {
|
||||
int i;
|
||||
for (i = 0; i < ushared->gateways_cnt; i++) {
|
||||
if (ushared->gateways[i].pid == diedpid) {
|
||||
gateway_respawn(i);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_master_check_daemons_death(int diedpid) {
|
||||
/* reload the daemons */
|
||||
if (uwsgi_daemon_check_pid_reload(diedpid)) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_worker_is_busy(int wid) {
|
||||
int i;
|
||||
for(i=0;i<uwsgi.cores;i++) {
|
||||
if (uwsgi.workers[wid].cores[i].in_request) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1,174 +0,0 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int uwsgi_master_manage_events(int interesting_fd) {
|
||||
|
||||
// is a logline ?
|
||||
if (uwsgi.log_master && !uwsgi.threaded_logger) {
|
||||
// stderr log ?
|
||||
if (interesting_fd == uwsgi.shared->worker_log_pipe[0]) {
|
||||
uwsgi_master_log();
|
||||
return 0;
|
||||
}
|
||||
// req log ?
|
||||
if (uwsgi.req_log_master && interesting_fd == uwsgi.shared->worker_req_log_pipe[0]) {
|
||||
uwsgi_master_req_log();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// stats server ?
|
||||
if (uwsgi.stats && uwsgi.stats_fd > -1) {
|
||||
if (interesting_fd == uwsgi.stats_fd) {
|
||||
uwsgi_send_stats(uwsgi.stats_fd, uwsgi_master_generate_stats);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// a zerg connection ?
|
||||
if (uwsgi.zerg_server) {
|
||||
if (interesting_fd == uwsgi.zerg_server_fd) {
|
||||
uwsgi_manage_zerg(uwsgi.zerg_server_fd, 0, NULL);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// emperor event ?
|
||||
if (uwsgi.has_emperor) {
|
||||
if (interesting_fd == uwsgi.emperor_fd) {
|
||||
uwsgi_master_manage_emperor();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// wakeup from cheap mode ?
|
||||
if (uwsgi.status.is_cheap) {
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
if (interesting_fd == uwsgi_sock->fd) {
|
||||
uwsgi.status.is_cheap = 0;
|
||||
uwsgi_del_sockets_from_queue(uwsgi.master_queue);
|
||||
// how many worker we need to respawn ?
|
||||
int needed = uwsgi.numproc;
|
||||
// if in cheaper mode, just respawn the minimal amount
|
||||
if (uwsgi.cheaper) {
|
||||
needed = uwsgi.cheaper_count;
|
||||
}
|
||||
int i;
|
||||
for (i = 1; i <= needed; i++) {
|
||||
if (uwsgi_respawn_worker(i))
|
||||
return -1;
|
||||
}
|
||||
// here we continue instead of returning
|
||||
break;
|
||||
}
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// an SNMP request ?
|
||||
if (uwsgi.snmp_addr && interesting_fd == uwsgi.snmp_fd) {
|
||||
uwsgi_master_manage_snmp(uwsgi.snmp_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// a UDP request ?
|
||||
if (uwsgi.udp_socket && interesting_fd == uwsgi.udp_fd) {
|
||||
uwsgi_master_manage_udp(uwsgi.udp_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// check if some file monitor is ready
|
||||
// no need to lock as we are only getting registered items (and only the master can register them)
|
||||
int i;
|
||||
for (i = 0; i < ushared->files_monitored_cnt; i++) {
|
||||
if (ushared->files_monitored[i].registered) {
|
||||
if (interesting_fd == ushared->files_monitored[i].fd) {
|
||||
struct uwsgi_fmon *uf = event_queue_ack_file_monitor(uwsgi.master_queue, interesting_fd);
|
||||
// now call the file_monitor handler
|
||||
if (uf)
|
||||
uwsgi_route_signal(uf->sig);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check if some timer elapsed
|
||||
// no need to lock again
|
||||
for (i = 0; i < ushared->timers_cnt; i++) {
|
||||
if (ushared->timers[i].registered) {
|
||||
if (interesting_fd == ushared->timers[i].fd) {
|
||||
struct uwsgi_timer *ut = event_queue_ack_timer(interesting_fd);
|
||||
// now call the timer handler
|
||||
if (ut)
|
||||
uwsgi_route_signal(ut->sig);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t uwsgi_signal;
|
||||
// check for worker signal
|
||||
if (interesting_fd == uwsgi.shared->worker_signal_pipe[0]) {
|
||||
ssize_t rlen = read(interesting_fd, &uwsgi_signal, 1);
|
||||
if (rlen < 0) {
|
||||
uwsgi_error("uwsgi_master_manage_events()/read()");
|
||||
}
|
||||
else if (rlen > 0) {
|
||||
uwsgi_route_signal(uwsgi_signal);
|
||||
}
|
||||
else {
|
||||
// TODO restart workers here
|
||||
uwsgi_log_verbose("lost connection with workers !!!\n");
|
||||
close(interesting_fd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// check for spooler signal
|
||||
if (uwsgi.spoolers) {
|
||||
if (interesting_fd == uwsgi.shared->spooler_signal_pipe[0]) {
|
||||
ssize_t rlen = read(interesting_fd, &uwsgi_signal, 1);
|
||||
if (rlen < 0) {
|
||||
uwsgi_error("uwsgi_master_manage_events()/read()");
|
||||
}
|
||||
else if (rlen > 0) {
|
||||
uwsgi_route_signal(uwsgi_signal);
|
||||
}
|
||||
else {
|
||||
// TODO restart spoolers here
|
||||
uwsgi_log_verbose("lost connection with spoolers\n");
|
||||
close(interesting_fd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// check for mules signal
|
||||
if (uwsgi.mules_cnt > 0) {
|
||||
if (interesting_fd == uwsgi.shared->mule_signal_pipe[0]) {
|
||||
ssize_t rlen = read(interesting_fd, &uwsgi_signal, 1);
|
||||
if (rlen < 0) {
|
||||
uwsgi_error("uwsgi_master_manage_events()/read()");
|
||||
}
|
||||
else if (rlen > 0) {
|
||||
uwsgi_route_signal(uwsgi_signal);
|
||||
}
|
||||
else {
|
||||
// TODO respawn mules here
|
||||
uwsgi_log_verbose("lost connection with mules\n");
|
||||
close(interesting_fd);
|
||||
}
|
||||
// return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
+66
-325
@@ -5,82 +5,15 @@ extern struct uwsgi_server uwsgi;
|
||||
void worker_wakeup() {
|
||||
}
|
||||
|
||||
uint64_t uwsgi_worker_exceptions(int wid) {
|
||||
uint64_t total = 0;
|
||||
int i;
|
||||
for(i=0;i<uwsgi.cores;i++) {
|
||||
total += uwsgi.workers[wid].cores[i].exceptions;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
void uwsgi_curse(int wid, int sig) {
|
||||
uwsgi.workers[wid].cursed_at = uwsgi_now();
|
||||
uwsgi.workers[wid].no_mercy_at = uwsgi.workers[wid].cursed_at + uwsgi.worker_reload_mercy;
|
||||
|
||||
if (sig) {
|
||||
(void) kill(uwsgi.workers[wid].pid, sig);
|
||||
}
|
||||
}
|
||||
|
||||
static void uwsgi_signal_spoolers(int signum) {
|
||||
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
while (uspool) {
|
||||
if (uspool->pid > 0) {
|
||||
kill(uspool->pid, signum);
|
||||
uwsgi_log("killing the spooler with pid %d\n", uspool->pid);
|
||||
}
|
||||
uspool = uspool->next;
|
||||
}
|
||||
|
||||
}
|
||||
void uwsgi_destroy_processes() {
|
||||
|
||||
int i;
|
||||
int waitpid_status;
|
||||
|
||||
uwsgi_signal_spoolers(SIGKILL);
|
||||
|
||||
if (uwsgi.emperor_pid >= 0) {
|
||||
kill(uwsgi.emperor_pid, SIGKILL);
|
||||
waitpid(uwsgi.emperor_pid, &waitpid_status, 0);
|
||||
uwsgi_log("The Emperor has been buried (pid: %d)\n", (int) uwsgi.emperor_pid);
|
||||
}
|
||||
|
||||
|
||||
uwsgi_detach_daemons();
|
||||
|
||||
for (i = 0; i < ushared->gateways_cnt; i++) {
|
||||
if (ushared->gateways[i].pid > 0) {
|
||||
kill(ushared->gateways[i].pid, SIGKILL);
|
||||
waitpid(ushared->gateways[i].pid, &waitpid_status, 0);
|
||||
uwsgi_log("gateway \"%s %d\" has been buried (pid: %d)\n", ushared->gateways[i].name, ushared->gateways[i].num, (int) ushared->gateways[i].pid);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO mules can be programmed to be gracefully reloaded
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].pid > 0) {
|
||||
kill(uwsgi.mules[i].pid, SIGKILL);
|
||||
waitpid(uwsgi.mules[i].pid, &waitpid_status, 0);
|
||||
uwsgi_log("mule %d has been buried (pid: %d)\n", i, (int) uwsgi.mules[i].pid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void uwsgi_master_cleanup_hooks(void) {
|
||||
|
||||
int j;
|
||||
|
||||
// could be an inherited atexit hook
|
||||
if (uwsgi.mypid != uwsgi.workers[0].pid)
|
||||
if (uwsgi.mywid > 0)
|
||||
return;
|
||||
|
||||
uwsgi.status.is_cleaning = 1;
|
||||
uwsgi.cleaning = 1;
|
||||
|
||||
for (j = 0; j < uwsgi.gp_cnt; j++) {
|
||||
if (uwsgi.gp[j]->master_cleanup) {
|
||||
@@ -145,7 +78,8 @@ int uwsgi_calc_cheaper(void) {
|
||||
#endif
|
||||
uwsgi.workers[oldest_worker].cheaped = 1;
|
||||
uwsgi.workers[oldest_worker].manage_next_request = 0;
|
||||
uwsgi_curse(oldest_worker, SIGWINCH);
|
||||
// wakeup task in case of wait
|
||||
(void) kill(uwsgi.workers[oldest_worker].pid, SIGWINCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,7 +131,7 @@ int uwsgi_cheaper_algo_spare(void) {
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
|
||||
// if a non-busy worker is found, the overload_count is decremented and stop the cycle
|
||||
if (uwsgi_worker_is_busy(i) == 0) {
|
||||
if (uwsgi.workers[i].busy == 0) {
|
||||
if (overload_count > 0)
|
||||
overload_count--;
|
||||
goto healthy;
|
||||
@@ -240,7 +174,7 @@ healthy:
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
|
||||
active_workers++;
|
||||
if (uwsgi_worker_is_busy(i) == 1)
|
||||
if (uwsgi.workers[i].busy == 1)
|
||||
busy_workers++;
|
||||
}
|
||||
}
|
||||
@@ -373,44 +307,43 @@ void uwsgi_reload(char **argv) {
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
if (found) continue;
|
||||
|
||||
if (uwsgi.has_emperor) {
|
||||
if (i == uwsgi.emperor_fd) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i == uwsgi.emperor_fd_config) {
|
||||
continue;
|
||||
if (!found) {
|
||||
if (uwsgi.has_emperor) {
|
||||
if (i == uwsgi.emperor_fd) {
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.log_master) {
|
||||
if (uwsgi.original_log_fd > -1) {
|
||||
if (i == uwsgi.original_log_fd) {
|
||||
continue;
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.shared->worker_log_pipe[0] > -1) {
|
||||
if (i == uwsgi.shared->worker_log_pipe[0]) {
|
||||
continue;
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.shared->worker_log_pipe[1] > -1) {
|
||||
if (i == uwsgi.shared->worker_log_pipe[1]) {
|
||||
continue;
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
#ifdef __APPLE__
|
||||
fcntl(i, F_SETFD, FD_CLOEXEC);
|
||||
fcntl(i, F_SETFD, FD_CLOEXEC);
|
||||
#else
|
||||
close(i);
|
||||
close(i);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_AS_SHARED_LIBRARY
|
||||
@@ -440,10 +373,44 @@ void uwsgi_reload(char **argv) {
|
||||
|
||||
}
|
||||
|
||||
void master_check_cluster_nodes() {
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
|
||||
struct uwsgi_cluster_node *ucn = &uwsgi.shared->nodes[i];
|
||||
|
||||
if (ucn->name[0] != 0 && ucn->type == CLUSTER_NODE_STATIC && ucn->status == UWSGI_NODE_FAILED) {
|
||||
// should i retry ?
|
||||
if (uwsgi.master_cycles % ucn->errors == 0) {
|
||||
if (!uwsgi_ping_node(i, uwsgi.wsgi_req)) {
|
||||
ucn->status = UWSGI_NODE_OK;
|
||||
uwsgi_log("re-enabled cluster node %d/%s\n", i, ucn->name);
|
||||
}
|
||||
else {
|
||||
ucn->errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ucn->name[0] != 0 && ucn->type == CLUSTER_NODE_DYNAMIC) {
|
||||
// if the last_seen attr is higher than 30 secs ago, mark the node as dead
|
||||
if ((uwsgi.current_time - ucn->last_seen) > 30) {
|
||||
uwsgi_log_verbose("no presence announce in the last 30 seconds by node %s, i assume it is dead.\n", ucn->name);
|
||||
ucn->name[0] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
|
||||
|
||||
int i;
|
||||
|
||||
// close the cache server
|
||||
if (uwsgi.cache_server_fd != -1) {
|
||||
close(uwsgi.cache_server_fd);
|
||||
}
|
||||
|
||||
if (uwsgi.master_process) {
|
||||
if (uwsgi.master_queue > -1)
|
||||
close(uwsgi.master_queue);
|
||||
@@ -476,13 +443,14 @@ void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
|
||||
close(uwsgi.workers[i].signal_pipe[1]);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.i_am_a_spooler && uwsgi.i_am_a_spooler->pid != getpid()) {
|
||||
if (uwsgi.shared->spooler_signal_pipe[0] != -1)
|
||||
close(uwsgi.shared->spooler_signal_pipe[0]);
|
||||
if (uwsgi.shared->spooler_signal_pipe[1] != -1)
|
||||
close(uwsgi.shared->spooler_signal_pipe[1]);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (uwsgi.shared->mule_signal_pipe[0] != -1)
|
||||
close(uwsgi.shared->mule_signal_pipe[0]);
|
||||
@@ -535,13 +503,11 @@ int uwsgi_respawn_worker(int wid) {
|
||||
uwsgi.workers[wid].pending_harakiri = 0;
|
||||
uwsgi.workers[wid].rss_size = 0;
|
||||
uwsgi.workers[wid].vsz_size = 0;
|
||||
// ... reset stopped_at
|
||||
uwsgi.workers[wid].cursed_at = 0;
|
||||
uwsgi.workers[wid].no_mercy_at = 0;
|
||||
|
||||
// internal statuses should be reset too
|
||||
|
||||
uwsgi.workers[wid].cheaped = 0;
|
||||
uwsgi.workers[wid].busy = 0;
|
||||
// SUSPENSION is managed by the user, not the master...
|
||||
//uwsgi.workers[wid].suspended = 0;
|
||||
uwsgi.workers[wid].sig = 0;
|
||||
@@ -582,6 +548,7 @@ int uwsgi_respawn_worker(int wid) {
|
||||
uwsgi.workers[uwsgi.mywid].manage_next_request = 1;
|
||||
/*
|
||||
uwsgi.workers[uwsgi.mywid].cheaped = 0;
|
||||
uwsgi.workers[uwsgi.mywid].busy = 0;
|
||||
uwsgi.workers[uwsgi.mywid].suspended = 0;
|
||||
uwsgi.workers[uwsgi.mywid].sig = 0;
|
||||
*/
|
||||
@@ -590,17 +557,16 @@ int uwsgi_respawn_worker(int wid) {
|
||||
uwsgi.workers[uwsgi.mywid].apps_cnt = uwsgi.workers[0].apps_cnt;
|
||||
|
||||
// reset wsgi_request structures
|
||||
for(i=0;i<uwsgi.cores;i++) {
|
||||
uwsgi.workers[uwsgi.mywid].cores[i].in_request = 0;
|
||||
memset(&uwsgi.workers[uwsgi.mywid].cores[i].req, 0, sizeof(struct wsgi_request));
|
||||
}
|
||||
for(i=0;i<uwsgi.cores;i++) {
|
||||
memset(&uwsgi.workers[uwsgi.mywid].cores[i].req, 0, sizeof(struct wsgi_request));
|
||||
}
|
||||
|
||||
uwsgi_fixup_fds(wid, 0, NULL);
|
||||
|
||||
uwsgi.my_signal_socket = uwsgi.workers[wid].signal_pipe[1];
|
||||
|
||||
if (uwsgi.master_process) {
|
||||
if ((uwsgi.workers[uwsgi.mywid].respawn_count || uwsgi.status.is_cheap)) {
|
||||
if ((uwsgi.workers[uwsgi.mywid].respawn_count || uwsgi.cheap)) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->master_fixup) {
|
||||
uwsgi.p[i]->master_fixup(1);
|
||||
@@ -755,7 +721,7 @@ void uwsgi_manage_command_cron(time_t now) {
|
||||
}
|
||||
}
|
||||
if (current_cron->month < 0) {
|
||||
if ((uwsgi_cron_delta->tm_mon % abs(current_cron->month)) == 0) {
|
||||
if ((uwsgi_cron_delta->tm_hour % abs(current_cron->month)) == 0) {
|
||||
uc_month = uwsgi_cron_delta->tm_mon;
|
||||
}
|
||||
}
|
||||
@@ -901,66 +867,6 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
|
||||
if (uwsgi.caches) {
|
||||
|
||||
|
||||
if (uwsgi_stats_key(us, "caches"))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_list_open(us)) goto end;
|
||||
|
||||
struct uwsgi_cache *uc = uwsgi.caches;
|
||||
while(uc) {
|
||||
if (uwsgi_stats_object_open(us))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keyval_comma(us, "name", uc->name ? uc->name : "default"))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keyval_comma(us, "hash", uc->hash->name))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "hashsize", (unsigned long long) uc->hashsize))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "keysize", (unsigned long long) uc->keysize))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "max_items", (unsigned long long) uc->max_items))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "blocks", (unsigned long long) uc->blocks))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "blocksize", (unsigned long long) uc->blocksize))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "items", (unsigned long long) uc->n_items))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "hits", (unsigned long long) uc->hits))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "miss", (unsigned long long) uc->miss))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong(us, "full", (unsigned long long) uc->full))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_object_close(us))
|
||||
goto end;
|
||||
|
||||
if (uc->next) {
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
}
|
||||
uc = uc->next;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_key(us, "sockets"))
|
||||
goto end;
|
||||
|
||||
@@ -1020,7 +926,7 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "delta_requests", (unsigned long long) uwsgi.workers[i + 1].delta_requests))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "exceptions", (unsigned long long) uwsgi_worker_exceptions(i + 1)))
|
||||
if (uwsgi_stats_keylong_comma(us, "exceptions", (unsigned long long) uwsgi.workers[i + 1].exceptions))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "harakiri_count", (unsigned long long) uwsgi.workers[i + 1].harakiri_count))
|
||||
goto end;
|
||||
@@ -1038,7 +944,7 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
if (uwsgi_stats_keyval_comma(us, "status", "cheap"))
|
||||
goto end;
|
||||
}
|
||||
else if (uwsgi.workers[i + 1].suspended && !uwsgi_worker_is_busy(i+1)) {
|
||||
else if (uwsgi.workers[i + 1].suspended && !uwsgi.workers[i + 1].busy) {
|
||||
if (uwsgi_stats_keyval_comma(us, "status", "pause"))
|
||||
goto end;
|
||||
}
|
||||
@@ -1047,7 +953,7 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
if (uwsgi_stats_keyvalnum_comma(us, "status", "sig", (unsigned long long) uwsgi.workers[i + 1].signum))
|
||||
goto end;
|
||||
}
|
||||
else if (uwsgi_worker_is_busy(i+1)) {
|
||||
else if (uwsgi.workers[i + 1].busy) {
|
||||
if (uwsgi_stats_keyval_comma(us, "status", "busy"))
|
||||
goto end;
|
||||
}
|
||||
@@ -1152,21 +1058,7 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
if (uwsgi_stats_keylong_comma(us, "offloaded_requests", (unsigned long long) uc->offloaded_requests))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "write_errors", (unsigned long long) uc->write_errors))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "in_request", (unsigned long long) uc->in_request))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_key(us, "vars"))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_list_open(us))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_dump_vars(us, uc)) goto end;
|
||||
|
||||
if (uwsgi_stats_list_close(us))
|
||||
if (uwsgi_stats_keylong(us, "in_request", (unsigned long long) uc->in_request))
|
||||
goto end;
|
||||
|
||||
|
||||
@@ -1194,6 +1086,7 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
if (uwsgi_stats_list_close(us))
|
||||
goto end;
|
||||
|
||||
#ifdef UWSGI_SPOOLER
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
if (uspool) {
|
||||
if (uwsgi_stats_comma(us))
|
||||
@@ -1232,147 +1125,12 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
if (uwsgi_stats_list_close(us))
|
||||
goto end;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
struct uwsgi_legion *legion = NULL;
|
||||
if (uwsgi.legions) {
|
||||
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_key(us, "legions"))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_list_open(us))
|
||||
goto end;
|
||||
|
||||
legion = uwsgi.legions;
|
||||
while (legion) {
|
||||
if (uwsgi_stats_object_open(us))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keyval_comma(us, "legion", legion->legion))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keyval_comma(us, "addr", legion->addr))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keyval_comma(us, "uuid", legion->uuid))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "valor", (unsigned long long) legion->valor))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "checksum", (unsigned long long) legion->checksum))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "quorum", (unsigned long long) legion->quorum))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "i_am_the_lord", (unsigned long long) legion->i_am_the_lord))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "lord_valor", (unsigned long long) legion->lord_valor))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keyvaln_comma(us, "lord_uuid", legion->lord_uuid, 36))
|
||||
goto end;
|
||||
|
||||
// legion nodes start
|
||||
if (uwsgi_stats_key(us, "nodes"))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_list_open(us))
|
||||
goto end;
|
||||
|
||||
struct uwsgi_string_list *nodes = legion->nodes;
|
||||
while (nodes) {
|
||||
|
||||
if (uwsgi_stats_str(us, nodes->value))
|
||||
goto end;
|
||||
|
||||
nodes = nodes->next;
|
||||
if (nodes) {
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi_stats_list_close(us))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
|
||||
|
||||
// legion members start
|
||||
if (uwsgi_stats_key(us, "members"))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_list_open(us))
|
||||
goto end;
|
||||
|
||||
uwsgi_rlock(legion->lock);
|
||||
struct uwsgi_legion_node *node = legion->nodes_head;
|
||||
while (node) {
|
||||
if (uwsgi_stats_object_open(us))
|
||||
goto unlock_legion_mutex;
|
||||
|
||||
if (uwsgi_stats_keyvaln_comma(us, "name", node->name, node->name_len))
|
||||
goto unlock_legion_mutex;
|
||||
|
||||
if (uwsgi_stats_keyval_comma(us, "uuid", node->uuid))
|
||||
goto unlock_legion_mutex;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "valor", (unsigned long long) node->valor))
|
||||
goto unlock_legion_mutex;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "checksum", (unsigned long long) node->checksum))
|
||||
goto unlock_legion_mutex;
|
||||
|
||||
if (uwsgi_stats_keylong(us, "last_seen", (unsigned long long) node->last_seen))
|
||||
goto unlock_legion_mutex;
|
||||
|
||||
if (uwsgi_stats_object_close(us))
|
||||
goto unlock_legion_mutex;
|
||||
|
||||
node = node->next;
|
||||
if (node) {
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto unlock_legion_mutex;
|
||||
}
|
||||
}
|
||||
uwsgi_rwunlock(legion->lock);
|
||||
|
||||
if (uwsgi_stats_list_close(us))
|
||||
goto end;
|
||||
// legion nodes end
|
||||
|
||||
if (uwsgi_stats_object_close(us))
|
||||
goto end;
|
||||
|
||||
legion = legion->next;
|
||||
if (legion) {
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi_stats_list_close(us))
|
||||
goto end;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
if (uwsgi_stats_object_close(us))
|
||||
goto end;
|
||||
|
||||
return us;
|
||||
#ifdef UWSGI_SSL
|
||||
unlock_legion_mutex:
|
||||
if (legion)
|
||||
uwsgi_rwunlock(legion->lock);
|
||||
#endif
|
||||
end:
|
||||
free(us->base);
|
||||
free(us);
|
||||
@@ -1469,20 +1227,3 @@ void trigger_harakiri(int i) {
|
||||
// to avoid races
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_master_fix_request_counters() {
|
||||
int i;
|
||||
uint64_t total_counter = 0;
|
||||
for (i = 1; i <= uwsgi.numproc;i++) {
|
||||
uint64_t tmp_counter = 0;
|
||||
int j;
|
||||
for(j=0;j<uwsgi.cores;j++) {
|
||||
tmp_counter += uwsgi.workers[i].cores[j].requests;
|
||||
}
|
||||
uwsgi.workers[i].requests = tmp_counter;
|
||||
total_counter += tmp_counter;
|
||||
}
|
||||
|
||||
uwsgi.workers[0].requests = total_counter;
|
||||
}
|
||||
|
||||
|
||||
+5
-7
@@ -56,7 +56,6 @@ void uwsgi_mule(int id) {
|
||||
// avoid race conditions
|
||||
uwsgi.mules[id - 1].id = id;
|
||||
uwsgi.mules[id - 1].pid = getpid();
|
||||
uwsgi.mypid = uwsgi.mules[id - 1].pid;
|
||||
|
||||
uwsgi_fixup_fds(0, id, NULL);
|
||||
|
||||
@@ -82,7 +81,7 @@ void uwsgi_mule(int id) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->mule) {
|
||||
if (uwsgi.p[i]->mule(uwsgi.mules[id - 1].patch) == 1) {
|
||||
// never here ?
|
||||
// never here
|
||||
end_me(1);
|
||||
}
|
||||
}
|
||||
@@ -210,7 +209,7 @@ void uwsgi_mule_handler() {
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
uwsgi_log("*** mule %d received a %ld bytes message ***\n", uwsgi.muleid, (long) len);
|
||||
uwsgi_log("*** mule %d received a %d bytes message ***\n", uwsgi.muleid, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -406,12 +405,12 @@ void uwsgi_setup_mules_and_farms() {
|
||||
uwsgi.mules = (struct uwsgi_mule *) uwsgi_calloc_shared(sizeof(struct uwsgi_mule) * uwsgi.mules_cnt);
|
||||
|
||||
create_signal_pipe(uwsgi.shared->mule_signal_pipe);
|
||||
create_signal_pipe(uwsgi.shared->mule_queue_pipe);
|
||||
create_msg_pipe(uwsgi.shared->mule_queue_pipe, uwsgi.mule_msg_size);
|
||||
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
// create the socket pipe
|
||||
create_signal_pipe(uwsgi.mules[i].signal_pipe);
|
||||
create_signal_pipe(uwsgi.mules[i].queue_pipe);
|
||||
create_msg_pipe(uwsgi.mules[i].queue_pipe, uwsgi.mule_msg_size);
|
||||
|
||||
uwsgi.mules[i].id = i + 1;
|
||||
|
||||
@@ -437,11 +436,10 @@ void uwsgi_setup_mules_and_farms() {
|
||||
mules_list++;
|
||||
|
||||
strncpy(uwsgi.farms[i].name, farm_value, 0xff);
|
||||
free(farm_value);
|
||||
|
||||
// create the socket pipe
|
||||
create_signal_pipe(uwsgi.farms[i].signal_pipe);
|
||||
create_signal_pipe(uwsgi.farms[i].queue_pipe);
|
||||
create_msg_pipe(uwsgi.farms[i].queue_pipe, uwsgi.mule_msg_size);
|
||||
|
||||
char *p = strtok(mules_list, ",");
|
||||
while (p != NULL) {
|
||||
|
||||
+3
-6
@@ -20,9 +20,7 @@ void uwsgi_systemd_notify(char *message) {
|
||||
|
||||
msghdr->msg_iovlen = 3;
|
||||
|
||||
if (sendmsg(uwsgi.notification_fd, msghdr, 0) < 0) {
|
||||
uwsgi_error("sendmsg()");
|
||||
}
|
||||
sendmsg(uwsgi.notification_fd, msghdr, 0);
|
||||
}
|
||||
|
||||
void uwsgi_systemd_notify_ready(void) {
|
||||
@@ -35,9 +33,8 @@ void uwsgi_systemd_notify_ready(void) {
|
||||
|
||||
msghdr->msg_iovlen = 1;
|
||||
|
||||
if (sendmsg(uwsgi.notification_fd, msghdr, 0) < 0) {
|
||||
uwsgi_error("sendmsg()");
|
||||
}
|
||||
sendmsg(uwsgi.notification_fd, msghdr, 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
+73
-193
@@ -4,17 +4,6 @@
|
||||
|
||||
uWSGI offloading subsystem
|
||||
|
||||
steps to offload a task
|
||||
|
||||
1) allocate a uwsgi_offload_request structure (could be on stack)
|
||||
struct uwsgi_offload_request uor;
|
||||
2) prepare it for a specific engine (last argument is the takeover flag)
|
||||
uwsgi_offload_setup(my_engine, &uor, 1)
|
||||
3) run it (last argument is the waiter)
|
||||
int uwsgi_offload_run(wsgi_req, &uor, NULL);
|
||||
|
||||
between 2 and 3 you can set specific values
|
||||
|
||||
*/
|
||||
|
||||
|
||||
@@ -24,20 +13,19 @@ extern struct uwsgi_server uwsgi;
|
||||
#define uwsgi_offload_0r_1w(x, y) if (event_queue_del_fd(ut->queue, x, event_queue_read())) return -1;\
|
||||
if (event_queue_fd_read_to_write(ut->queue, y)) return -1;
|
||||
|
||||
void uwsgi_offload_setup(struct uwsgi_offload_engine *uoe, struct uwsgi_offload_request *uor, struct wsgi_request *wsgi_req, uint8_t takeover) {
|
||||
static int uwsgi_offload_net_transfer(struct uwsgi_thread *, struct uwsgi_offload_request *, int);
|
||||
static int uwsgi_offload_sendfile_transfer(struct uwsgi_thread *, struct uwsgi_offload_request *, int);
|
||||
|
||||
static void uwsgi_offload_setup(struct uwsgi_offload_request *uor, struct wsgi_request *wsgi_req,
|
||||
int (*func)(struct uwsgi_thread *, struct uwsgi_offload_request *, int)) {
|
||||
|
||||
wsgi_req->fd_closed = 1;
|
||||
memset(uor, 0, sizeof(struct uwsgi_offload_request));
|
||||
|
||||
uor->engine = uoe;
|
||||
|
||||
uor->s = wsgi_req->fd;
|
||||
uor->fd = -1;
|
||||
uor->fd2 = -1;
|
||||
// an engine could changes behaviour based on pipe anf takeover values
|
||||
uor->pipe[0] = -1;
|
||||
uor->pipe[1] = -1;
|
||||
uor->takeover = takeover;
|
||||
|
||||
uor->s = wsgi_req->poll.fd;
|
||||
uor->func = func;
|
||||
// put socket in non-blocking mode
|
||||
uwsgi_socket_nb(uor->s);
|
||||
|
||||
}
|
||||
|
||||
static int uwsgi_offload_enqueue(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
|
||||
@@ -50,92 +38,79 @@ static int uwsgi_offload_enqueue(struct wsgi_request *wsgi_req, struct uwsgi_off
|
||||
struct uwsgi_thread *ut = uwsgi.offload_thread[uc->offload_rr];
|
||||
uc->offload_rr++;
|
||||
if (write(ut->pipe[0], uor, sizeof(struct uwsgi_offload_request)) != sizeof(struct uwsgi_offload_request)) {
|
||||
if (uor->takeover) {
|
||||
wsgi_req->fd_closed = 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
int uwsgi_offload_request_net_do(struct wsgi_request *wsgi_req, char *socket, struct uwsgi_buffer *ubuf) {
|
||||
|
||||
transfer offload engine:
|
||||
name -> socket name
|
||||
ubuf -> data to send
|
||||
// fill offload request
|
||||
struct uwsgi_offload_request uor;
|
||||
uwsgi_offload_setup(&uor, wsgi_req, uwsgi_offload_net_transfer);
|
||||
|
||||
*/
|
||||
|
||||
int u_offload_transfer_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
|
||||
|
||||
if (!uor->name) {
|
||||
return -1;
|
||||
uor.fd = uwsgi_connect(socket, 0, 1);
|
||||
if (uor.fd < 0) {
|
||||
uwsgi_error("uwsgi_offload_request_net_do() -> connect()");
|
||||
goto error;
|
||||
}
|
||||
|
||||
uor->fd = uwsgi_connect(uor->ubuf->buf, 0, 1);
|
||||
if (uor->fd < 0) {
|
||||
uwsgi_error("u_offload_transfer_prepare()/connect()");
|
||||
return -1;
|
||||
uor.ubuf = ubuf;
|
||||
|
||||
if (uwsgi_offload_enqueue(wsgi_req, &uor)) {
|
||||
goto error2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error2:
|
||||
close(uor.fd);
|
||||
error:
|
||||
wsgi_req->fd_closed = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
int uwsgi_offload_request_sendfile_do(struct wsgi_request *wsgi_req, char *filename, size_t len) {
|
||||
|
||||
sendfile offload engine:
|
||||
name -> filename to transfer
|
||||
fd -> file descriptor of file to transfer
|
||||
fd2 -> sendfile destination (default wsgi_req->fd)
|
||||
len -> size of the file or amount of data to transfer
|
||||
pos -> position in the file
|
||||
// fill offload request
|
||||
struct uwsgi_offload_request uor;
|
||||
uwsgi_offload_setup(&uor, wsgi_req, uwsgi_offload_sendfile_transfer);
|
||||
|
||||
*/
|
||||
|
||||
static int u_offload_sendfile_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
|
||||
|
||||
if (!uor->name && uor->fd == -1) return -1;
|
||||
|
||||
if (uor->name) {
|
||||
uor->fd = open(uor->name, O_RDONLY | O_NONBLOCK);
|
||||
if (uor->fd < 0) {
|
||||
uwsgi_error_open(uor->name);
|
||||
return -1;
|
||||
}
|
||||
uor.fd = open(filename, O_RDONLY | O_NONBLOCK);
|
||||
if (uor.fd < 0) {
|
||||
uwsgi_error_open(filename);
|
||||
goto error;
|
||||
}
|
||||
|
||||
// make a fstat to get the file size
|
||||
if (!uor->len) {
|
||||
if (!len) {
|
||||
struct stat st;
|
||||
if (fstat(uor->fd, &st)) {
|
||||
uwsgi_error("u_offload_sendfile_prepare()/fstat()");
|
||||
if (uor->name) {
|
||||
close(uor->fd);
|
||||
}
|
||||
return -1;
|
||||
if (fstat(uor.fd, &st)) {
|
||||
uwsgi_error("fstat()");
|
||||
goto error2;
|
||||
}
|
||||
uor->len = st.st_size;
|
||||
len = st.st_size;
|
||||
}
|
||||
|
||||
if (uor->fd2 == -1) {
|
||||
uor->fd2 = uor->s;
|
||||
uor.len = len;
|
||||
|
||||
if (uwsgi_offload_enqueue(wsgi_req, &uor)) {
|
||||
goto error2;
|
||||
}
|
||||
uor->s = -1;
|
||||
|
||||
return 0;
|
||||
|
||||
error2:
|
||||
close(uor.fd);
|
||||
error:
|
||||
wsgi_req->fd_closed = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void uwsgi_offload_close(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor) {
|
||||
// close the socket and the file descriptor
|
||||
if (uor->takeover && uor->s > -1) {
|
||||
close(uor->s);
|
||||
}
|
||||
if (uor->fd != -1) {
|
||||
close(uor->fd);
|
||||
}
|
||||
if (uor->fd2 != -1) {
|
||||
close(uor->fd2);
|
||||
}
|
||||
close(uor->s);
|
||||
close(uor->fd);
|
||||
// remove the structure from the linked list;
|
||||
struct uwsgi_offload_request *prev = uor->prev;
|
||||
struct uwsgi_offload_request *next = uor->next;
|
||||
@@ -164,11 +139,6 @@ static void uwsgi_offload_close(struct uwsgi_thread *ut, struct uwsgi_offload_re
|
||||
uwsgi_buffer_destroy(uor->ubuf);
|
||||
}
|
||||
|
||||
if (uor->pipe[0] != -1) {
|
||||
close(uor->pipe[1]);
|
||||
close(uor->pipe[0]);
|
||||
}
|
||||
|
||||
free(uor);
|
||||
}
|
||||
|
||||
@@ -189,7 +159,7 @@ static void uwsgi_offload_append(struct uwsgi_thread *ut, struct uwsgi_offload_r
|
||||
static struct uwsgi_offload_request *uwsgi_offload_get_by_fd(struct uwsgi_thread *ut, int s) {
|
||||
struct uwsgi_offload_request *uor = ut->offload_requests_head;
|
||||
while (uor) {
|
||||
if (uor->s == s || uor->fd == s || uor->fd2 == s) {
|
||||
if (uor->s == s || uor->fd == s) {
|
||||
return uor;
|
||||
}
|
||||
uor = uor->next;
|
||||
@@ -215,8 +185,8 @@ static void uwsgi_offload_loop(struct uwsgi_thread *ut) {
|
||||
free(uor);
|
||||
continue;
|
||||
}
|
||||
// cal the event function for the first time
|
||||
if (uor->engine->event_func(ut, uor, -1)) {
|
||||
// start monitoring socket for write
|
||||
if (uor->func(ut, uor, -1)) {
|
||||
uwsgi_offload_close(ut, uor);
|
||||
continue;
|
||||
}
|
||||
@@ -229,7 +199,7 @@ static void uwsgi_offload_loop(struct uwsgi_thread *ut) {
|
||||
if (!uor)
|
||||
continue;
|
||||
// run the hook
|
||||
if (uor->engine->event_func(ut, uor, interesting_fd)) {
|
||||
if (uor->func(ut, uor, interesting_fd)) {
|
||||
uwsgi_offload_close(ut, uor);
|
||||
}
|
||||
}
|
||||
@@ -251,14 +221,14 @@ the offload task starts after having acquired the file fd
|
||||
|
||||
*/
|
||||
|
||||
static int u_offload_sendfile_do(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor, int fd) {
|
||||
static int uwsgi_offload_sendfile_transfer(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor, int fd) {
|
||||
|
||||
if (fd == -1) {
|
||||
if (event_queue_add_fd_write(ut->queue, uor->fd2)) return -1;
|
||||
if (event_queue_add_fd_write(ut->queue, uor->s)) return -1;
|
||||
return 0;
|
||||
}
|
||||
#if defined(__linux__) || defined(__sun__)
|
||||
ssize_t len = sendfile(uor->fd2, uor->fd, &uor->pos, 128 * 1024);
|
||||
ssize_t len = sendfile(uor->s, uor->fd, &uor->pos, 128 * 1024);
|
||||
if (len > 0) {
|
||||
uor->written += len;
|
||||
if (uor->written >= uor->len) {
|
||||
@@ -268,25 +238,25 @@ static int u_offload_sendfile_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
|
||||
}
|
||||
else if (len < 0) {
|
||||
uwsgi_offload_retry
|
||||
uwsgi_error("u_offload_sendfile_do()");
|
||||
uwsgi_error("sendfile()");
|
||||
}
|
||||
#elif defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
off_t sbytes = 0;
|
||||
int ret = sendfile(uor->fd, uor->fd2, uor->pos, 0, NULL, &sbytes, 0);
|
||||
int ret = sendfile(uor->fd, uor->s, uor->pos, 0, NULL, &sbytes, 0);
|
||||
// transfer finished
|
||||
if (ret == -1) {
|
||||
uor->pos += sbytes;
|
||||
uwsgi_offload_retry
|
||||
uwsgi_error("u_offload_sendfile_do()");
|
||||
uwsgi_error("sendfile()");
|
||||
}
|
||||
#elif defined(__APPLE__)
|
||||
off_t len = 0;
|
||||
int ret = sendfile(uor->fd, uor->fd2, uor->pos, &len, NULL, 0);
|
||||
int ret = sendfile(uor->fd, uor->s, uor->pos, &len, NULL, 0);
|
||||
// transfer finished
|
||||
if (ret == -1) {
|
||||
uor->pos += len;
|
||||
uwsgi_offload_retry
|
||||
uwsgi_error("u_offload_sendfile_do()");
|
||||
uwsgi_error("sendfile()");
|
||||
}
|
||||
#endif
|
||||
return -1;
|
||||
@@ -303,7 +273,7 @@ the offload task starts soon after the call to connect()
|
||||
3 -> write to s
|
||||
4 -> write to fd
|
||||
*/
|
||||
static int u_offload_transfer_do(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor, int fd) {
|
||||
static int uwsgi_offload_net_transfer(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor, int fd) {
|
||||
|
||||
ssize_t rlen;
|
||||
|
||||
@@ -319,7 +289,7 @@ static int u_offload_transfer_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
|
||||
if (fd == uor->fd) {
|
||||
uor->status = 1;
|
||||
// ok try to send the request right now...
|
||||
return u_offload_transfer_do(ut, uor, fd);
|
||||
return uwsgi_offload_net_transfer(ut, uor, fd);
|
||||
}
|
||||
return -1;
|
||||
// write event (or just connected)
|
||||
@@ -337,7 +307,7 @@ static int u_offload_transfer_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
|
||||
}
|
||||
else if (rlen < 0) {
|
||||
uwsgi_offload_retry
|
||||
uwsgi_error("u_offload_transfer_do() -> write()");
|
||||
uwsgi_error("uwsgi_offload_net_transfer() -> write()");
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
@@ -357,7 +327,7 @@ static int u_offload_transfer_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
|
||||
}
|
||||
if (rlen < 0) {
|
||||
uwsgi_offload_retry
|
||||
uwsgi_error("u_offload_transfer_do() -> read()/fd");
|
||||
uwsgi_error("uwsgi_offload_net_transfer() -> read()/fd");
|
||||
}
|
||||
}
|
||||
else if (fd == uor->s) {
|
||||
@@ -371,7 +341,7 @@ static int u_offload_transfer_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
|
||||
}
|
||||
if (rlen < 0) {
|
||||
uwsgi_offload_retry
|
||||
uwsgi_error("u_offload_transfer_do() -> read()/s");
|
||||
uwsgi_error("uwsgi_offload_net_transfer() -> read()/s");
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
@@ -390,7 +360,7 @@ static int u_offload_transfer_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
|
||||
}
|
||||
else if (rlen < 0) {
|
||||
uwsgi_offload_retry
|
||||
uwsgi_error("u_offload_transfer_do() -> write()/s");
|
||||
uwsgi_error("uwsgi_offload_net_transfer() -> write()/s");
|
||||
}
|
||||
return -1;
|
||||
// write event on fd
|
||||
@@ -408,7 +378,7 @@ static int u_offload_transfer_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
|
||||
}
|
||||
else if (rlen < 0) {
|
||||
uwsgi_offload_retry
|
||||
uwsgi_error("u_offload_transfer_do() -> write()/fd");
|
||||
uwsgi_error("uwsgi_offload_net_transfer() -> write()/fd");
|
||||
}
|
||||
return -1;
|
||||
default:
|
||||
@@ -417,93 +387,3 @@ static int u_offload_transfer_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int uwsgi_offload_run(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor, int *wait) {
|
||||
|
||||
if (uor->engine->prepare_func(wsgi_req, uor)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (wait) {
|
||||
if (pipe(uor->pipe)) {
|
||||
uwsgi_error("uwsgi_offload_setup()/pipe()");
|
||||
return -1;
|
||||
}
|
||||
*wait = uor->pipe[0];
|
||||
uwsgi_socket_nb(uor->pipe[0]);
|
||||
uwsgi_socket_nb(uor->pipe[1]);
|
||||
}
|
||||
|
||||
if (uor->takeover) {
|
||||
wsgi_req->fd_closed = 1;
|
||||
}
|
||||
|
||||
if (uwsgi_offload_enqueue(wsgi_req, uor)) {
|
||||
close(uor->pipe[0]);
|
||||
close(uor->pipe[1]);
|
||||
if (uor->takeover) {
|
||||
wsgi_req->fd_closed = 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
};
|
||||
|
||||
struct uwsgi_offload_engine *uwsgi_offload_engine_by_name(char *name) {
|
||||
struct uwsgi_offload_engine *uoe = uwsgi.offload_engines;
|
||||
while(uoe) {
|
||||
if (!strcmp(name, uoe->name)) {
|
||||
return uoe;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_offload_engine *uwsgi_offload_register_engine(char *name, int (*prepare_func)(struct wsgi_request *, struct uwsgi_offload_request *), int (*event_func) (struct uwsgi_thread *, struct uwsgi_offload_request *, int)) {
|
||||
|
||||
struct uwsgi_offload_engine *old_engine=NULL,*engine=uwsgi.offload_engines;
|
||||
while(engine) {
|
||||
if (!strcmp(engine->name, name)) {
|
||||
return engine;
|
||||
}
|
||||
old_engine = engine;
|
||||
engine = engine->next;
|
||||
}
|
||||
|
||||
engine = uwsgi_calloc(sizeof(struct uwsgi_offload_engine));
|
||||
engine->name = name;
|
||||
engine->prepare_func = prepare_func;
|
||||
engine->event_func = event_func;
|
||||
|
||||
if (old_engine) {
|
||||
old_engine->next = engine;
|
||||
}
|
||||
else {
|
||||
uwsgi.offload_engines = engine;
|
||||
}
|
||||
|
||||
return engine;
|
||||
}
|
||||
|
||||
void uwsgi_offload_engines_register_all() {
|
||||
uwsgi.offload_engine_sendfile = uwsgi_offload_register_engine("sendfile", u_offload_sendfile_prepare, u_offload_sendfile_do);
|
||||
uwsgi.offload_engine_transfer = uwsgi_offload_register_engine("transfer", u_offload_transfer_prepare, u_offload_transfer_do);
|
||||
}
|
||||
|
||||
int uwsgi_offload_request_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t len) {
|
||||
struct uwsgi_offload_request uor;
|
||||
uwsgi_offload_setup(uwsgi.offload_engine_sendfile, &uor, wsgi_req, 1);
|
||||
uor.fd = fd;
|
||||
uor.len = len;
|
||||
return uwsgi_offload_run(wsgi_req, &uor, NULL);
|
||||
}
|
||||
|
||||
int uwsgi_offload_request_net_do(struct wsgi_request *wsgi_req, char *socketname, struct uwsgi_buffer *ubuf) {
|
||||
struct uwsgi_offload_request uor;
|
||||
uwsgi_offload_setup(uwsgi.offload_engine_transfer, &uor, wsgi_req, 1);
|
||||
uor.name = socketname;
|
||||
uor.ubuf = ubuf;
|
||||
return uwsgi_offload_run(wsgi_req, &uor, NULL);
|
||||
}
|
||||
|
||||
+4
-3
@@ -24,7 +24,7 @@ static void uwsgi_plugin_parse_section(char *filename) {
|
||||
}
|
||||
#endif
|
||||
|
||||
int plugin_already_loaded(const char *plugin) {
|
||||
static int plugin_already_loaded(const char *plugin) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
@@ -76,8 +76,8 @@ void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
|
||||
char *plugin_filename = NULL;
|
||||
|
||||
int need_free = 0;
|
||||
char *plugin_name = uwsgi_strip(uwsgi_str(plugin));
|
||||
char *plugin_symbol_name_start = plugin_name;
|
||||
char *plugin_name = plugin;
|
||||
char *plugin_symbol_name_start = plugin;
|
||||
|
||||
struct uwsgi_plugin *up;
|
||||
char linkpath_buf[1024], linkpath[1024];
|
||||
@@ -165,6 +165,7 @@ success:
|
||||
uwsgi_log("%s\n", linkpath);
|
||||
#endif
|
||||
free(plugin_entry_symbol);
|
||||
up = dlsym(plugin_handle, plugin_entry_symbol);
|
||||
char *slash = uwsgi_get_last_char(linkpath, '/');
|
||||
if (!slash) {
|
||||
slash = linkpath;
|
||||
|
||||
-107
@@ -1,107 +0,0 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
upload progress facilities
|
||||
|
||||
*/
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
char *uwsgi_upload_progress_create(struct wsgi_request *wsgi_req, int *fd) {
|
||||
const char *x_progress_id = "X-Progress-ID=";
|
||||
char *xpi_ptr = (char *) x_progress_id;
|
||||
uint16_t i;
|
||||
char *upload_progress_filename = NULL;
|
||||
|
||||
if (wsgi_req->uri_len <= 51)
|
||||
return NULL;
|
||||
|
||||
|
||||
for (i = 0; i < wsgi_req->uri_len; i++) {
|
||||
if (wsgi_req->uri[i] == xpi_ptr[0]) {
|
||||
if (xpi_ptr[0] == '=') {
|
||||
if (wsgi_req->uri + i + 36 <= wsgi_req->uri + wsgi_req->uri_len) {
|
||||
upload_progress_filename = wsgi_req->uri + i + 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
xpi_ptr++;
|
||||
}
|
||||
else {
|
||||
xpi_ptr = (char *) x_progress_id;
|
||||
}
|
||||
}
|
||||
|
||||
// now check for valid uuid (from spec available at http://en.wikipedia.org/wiki/Universally_unique_identifier)
|
||||
if (!upload_progress_filename)
|
||||
return NULL;
|
||||
|
||||
uwsgi_log("upload progress uuid = %.*s\n", 36, upload_progress_filename);
|
||||
if (!check_hex(upload_progress_filename, 8))
|
||||
return NULL;
|
||||
if (upload_progress_filename[8] != '-')
|
||||
return NULL;
|
||||
|
||||
if (!check_hex(upload_progress_filename + 9, 4))
|
||||
return NULL;
|
||||
if (upload_progress_filename[13] != '-')
|
||||
return NULL;
|
||||
|
||||
if (!check_hex(upload_progress_filename + 14, 4))
|
||||
return NULL;
|
||||
if (upload_progress_filename[18] != '-')
|
||||
return NULL;
|
||||
|
||||
if (!check_hex(upload_progress_filename + 19, 4))
|
||||
return NULL;
|
||||
if (upload_progress_filename[23] != '-')
|
||||
return NULL;
|
||||
|
||||
if (!check_hex(upload_progress_filename + 24, 12))
|
||||
return NULL;
|
||||
|
||||
upload_progress_filename = uwsgi_concat4n(uwsgi.upload_progress, strlen(uwsgi.upload_progress), "/", 1, upload_progress_filename, 36, ".js", 3);
|
||||
// here we use O_EXCL to avoid eventual application bug in uuid generation/using
|
||||
*fd = open(upload_progress_filename, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (*fd < 0) {
|
||||
uwsgi_error_open(upload_progress_filename);
|
||||
free(upload_progress_filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return upload_progress_filename;
|
||||
}
|
||||
|
||||
int uwsgi_upload_progress_update(struct wsgi_request *wsgi_req, int fd, size_t remains) {
|
||||
char buf[4096];
|
||||
|
||||
int ret = snprintf(buf, 4096, "{ \"state\" : \"uploading\", \"received\" : %llu, \"size\" : %llu }\r\n", (unsigned long long) (wsgi_req->post_cl - remains), (unsigned long long) wsgi_req->post_cl);
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (lseek(fd, 0, SEEK_SET)) {
|
||||
uwsgi_error("uwsgi_upload_progress_update()/lseek()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (write(fd, buf, ret) != ret) {
|
||||
uwsgi_error("uwsgi_upload_progress_update()/write()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fsync(fd)) {
|
||||
uwsgi_error("uwsgi_upload_progress_update()/fsync()");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_upload_progress_destroy(char *filename, int fd) {
|
||||
close(fd);
|
||||
if (unlink(filename)) {
|
||||
uwsgi_error("uwsgi_upload_progress_destroy()/unlink()");
|
||||
}
|
||||
free(filename);
|
||||
}
|
||||
+1421
-430
File diff suppressed because it is too large
Load Diff
+1
-2
@@ -47,7 +47,6 @@ void uwsgi_init_queue() {
|
||||
// fix header
|
||||
uwsgi.queue_header = uwsgi.queue;
|
||||
uwsgi.queue += 16;
|
||||
close(queue_fd);
|
||||
}
|
||||
else {
|
||||
uwsgi.queue = mmap(NULL, (uwsgi.queue_blocksize * uwsgi.queue_size) + 16, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
@@ -66,7 +65,7 @@ void uwsgi_init_queue() {
|
||||
|
||||
uwsgi.queue_lock = uwsgi_rwlock_init("queue");
|
||||
|
||||
uwsgi_log("*** Queue subsystem initialized: %luMB preallocated ***\n", (uwsgi.queue_blocksize * uwsgi.queue_size) / (1024 * 1024));
|
||||
uwsgi_log("*** Queue subsystem initialized: %dMB preallocated ***\n", (uwsgi.queue_blocksize * uwsgi.queue_size) / (1024 * 1024));
|
||||
}
|
||||
|
||||
char *uwsgi_queue_get(uint64_t index, uint64_t * size) {
|
||||
|
||||
-572
@@ -1,572 +0,0 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int uwsgi_simple_wait_read_hook(int fd, int timeout) {
|
||||
struct pollfd upoll;
|
||||
timeout = timeout * 1000;
|
||||
|
||||
upoll.fd = fd;
|
||||
upoll.events = POLLIN;
|
||||
upoll.revents = 0;
|
||||
int ret = poll(&upoll, 1, timeout);
|
||||
|
||||
if (ret > 0) {
|
||||
if (upoll.revents & POLLIN) {
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (ret < 0) {
|
||||
uwsgi_error("uwsgi_simple_wait_read_hook()/poll()");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
seek()/rewind() language-independent implementations.
|
||||
*/
|
||||
|
||||
void uwsgi_request_body_seek(struct wsgi_request *wsgi_req, off_t pos) {
|
||||
if (wsgi_req->post_file) {
|
||||
if (pos < 0) {
|
||||
if (fseek(wsgi_req->post_file, pos, SEEK_CUR)) {
|
||||
uwsgi_error("uwsgi_request_body_seek()/fseek()");
|
||||
}
|
||||
wsgi_req->post_pos = ftell(wsgi_req->post_file);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fseek(wsgi_req->post_file, pos, SEEK_SET)) {
|
||||
uwsgi_error("uwsgi_request_body_seek()/fseek()");
|
||||
}
|
||||
wsgi_req->post_pos = ftell(wsgi_req->post_file);
|
||||
return;
|
||||
}
|
||||
|
||||
if (uwsgi.post_buffering) {
|
||||
if (pos < 0) {
|
||||
if (pos > (off_t) wsgi_req->post_pos) {
|
||||
wsgi_req->post_pos = 0;
|
||||
return;
|
||||
}
|
||||
wsgi_req->post_pos -= pos;
|
||||
return;
|
||||
}
|
||||
if (pos >= (off_t) uwsgi.post_buffering) {
|
||||
pos = uwsgi.post_buffering - 1;
|
||||
}
|
||||
wsgi_req->post_pos = pos;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
read() and readline() language-independent implementations.
|
||||
|
||||
*/
|
||||
|
||||
#define uwsgi_read_error0(x) uwsgi_log("[uwsgi-body-read] Error reading %llu bytes. Content-Length: %llu consumed: %llu left: %llu message: Client closed connection\n",\
|
||||
(unsigned long long) x,\
|
||||
(unsigned long long) wsgi_req->post_cl, (unsigned long long) wsgi_req->post_pos, (unsigned long long) wsgi_req->post_cl-wsgi_req->post_pos);
|
||||
|
||||
#define uwsgi_read_error(x) uwsgi_log("[uwsgi-body-read] Error reading %llu bytes. Content-Length: %llu consumed: %llu left: %llu message: %s\n",\
|
||||
(unsigned long long) x,\
|
||||
(unsigned long long) wsgi_req->post_cl, (unsigned long long) wsgi_req->post_pos, (unsigned long long) wsgi_req->post_cl-wsgi_req->post_pos,\
|
||||
strerror(errno));
|
||||
|
||||
#define uwsgi_read_timeout(x) uwsgi_log("[uwsgi-body-read] Timeout reading %llu bytes. Content-Length: %llu consumed: %llu left: %llu\n",\
|
||||
(unsigned long long) x,\
|
||||
(unsigned long long) wsgi_req->post_cl, (unsigned long long) wsgi_req->post_pos, (unsigned long long) wsgi_req->post_cl-wsgi_req->post_pos);
|
||||
|
||||
static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
|
||||
|
||||
size_t remains = UMIN(uwsgi.buffer_size, wsgi_req->post_cl - wsgi_req->post_pos);
|
||||
|
||||
int ret;
|
||||
|
||||
// allocate more memory if needed
|
||||
if (wsgi_req->post_readline_size - wsgi_req->post_readline_watermark == 0) {
|
||||
memcpy(wsgi_req->post_readline_buf, wsgi_req->post_readline_buf + wsgi_req->post_readline_pos, wsgi_req->post_readline_watermark - wsgi_req->post_readline_pos);
|
||||
wsgi_req->post_readline_watermark -= wsgi_req->post_readline_pos;
|
||||
wsgi_req->post_readline_pos = 0;
|
||||
// still something to use ?
|
||||
if (wsgi_req->post_readline_size - wsgi_req->post_readline_watermark < remains) {
|
||||
char *tmp_buf = realloc(wsgi_req->post_readline_buf, wsgi_req->post_readline_size + remains);
|
||||
if (!tmp_buf) {
|
||||
uwsgi_error("consume_body_for_readline()/realloc()");
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->post_readline_buf = tmp_buf;
|
||||
wsgi_req->post_readline_size += remains;
|
||||
// INFORM THE USER HIS readline() USAGE IS FOOLISH
|
||||
if (!wsgi_req->post_warning && wsgi_req->post_readline_size > (uwsgi.body_read_warning * 1024*1024)) {
|
||||
uwsgi_log("[uwsgi-warning] you are using readline() on request body allocating over than %llu MB, that is really bad and can be avoided...\n", (unsigned long long) (wsgi_req->post_readline_size/(1024*1024)));
|
||||
wsgi_req->post_warning = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// read from a file
|
||||
if (wsgi_req->post_file) {
|
||||
size_t ret = fread(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, wsgi_req->post_readline_size - wsgi_req->post_readline_watermark, 1, wsgi_req->post_file);
|
||||
if (ret == 0) {
|
||||
uwsgi_error("consume_body_for_readline()/fread()");
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->post_pos += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
|
||||
wsgi_req->post_readline_watermark += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// read from post_buffering memory
|
||||
if (uwsgi.post_buffering) {
|
||||
wsgi_req->post_pos += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
|
||||
memcpy(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, wsgi_req->post_buffering_buf + wsgi_req->post_pos, wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
wsgi_req->post_readline_watermark += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// read from socket
|
||||
ssize_t len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
if (len > 0) {
|
||||
wsgi_req->post_pos += len;
|
||||
wsgi_req->post_readline_watermark += len;
|
||||
return 0;
|
||||
}
|
||||
if (len == 0) {
|
||||
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
return -1;
|
||||
}
|
||||
if (len < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
goto wait;
|
||||
}
|
||||
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
return -1;
|
||||
}
|
||||
wait:
|
||||
ret = uwsgi_wait_read_req(wsgi_req);
|
||||
if (ret > 0) {
|
||||
len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
if (len > 0) {
|
||||
wsgi_req->post_pos += len;
|
||||
wsgi_req->post_readline_watermark += len;
|
||||
return 0;
|
||||
}
|
||||
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
return -1;
|
||||
}
|
||||
// 0 means timeout
|
||||
else if (ret == 0) {
|
||||
uwsgi_read_timeout(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
return -1;
|
||||
}
|
||||
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// TODO take hint into account
|
||||
// readline_buf is allocated when needed and freed at the end of the request
|
||||
char *uwsgi_request_body_readline(struct wsgi_request *wsgi_req, ssize_t hint, ssize_t *rlen) {
|
||||
|
||||
// return 0 if no post_cl or pos >= post_cl and no residual data
|
||||
if ((!wsgi_req->post_cl || wsgi_req->post_pos >= wsgi_req->post_cl ) && !wsgi_req->post_readline_pos) {
|
||||
return uwsgi.empty;
|
||||
}
|
||||
|
||||
// some residual data ?
|
||||
if (wsgi_req->post_readline_pos > 0) {
|
||||
size_t i;
|
||||
for(i=wsgi_req->post_readline_pos;i<wsgi_req->post_readline_watermark;i++) {
|
||||
// found a newline
|
||||
if (wsgi_req->post_readline_buf[i] == '\n') {
|
||||
*rlen = (i+1)-wsgi_req->post_readline_pos;
|
||||
char *buf = wsgi_req->post_readline_buf + wsgi_req->post_readline_pos;
|
||||
wsgi_req->post_readline_pos += *rlen;
|
||||
// all the readline buffer has been consumed
|
||||
if (wsgi_req->post_readline_pos >= wsgi_req->post_readline_watermark) {
|
||||
wsgi_req->post_readline_pos = 0;
|
||||
wsgi_req->post_readline_watermark = 0;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
// ok, no newline found, continue below
|
||||
}
|
||||
|
||||
// allocate memory on the first round
|
||||
if (!wsgi_req->post_readline_buf) {
|
||||
size_t amount = UMIN(uwsgi.buffer_size, wsgi_req->post_cl);
|
||||
wsgi_req->post_readline_buf = malloc(amount);
|
||||
if (!wsgi_req->post_readline_buf) {
|
||||
uwsgi_error("uwsgi_request_body_readline()/malloc()");
|
||||
*rlen = -1;
|
||||
return NULL;
|
||||
}
|
||||
wsgi_req->post_readline_size = amount;
|
||||
}
|
||||
|
||||
// ok, no newline found, consume a bit more of memory and retry
|
||||
for(;;) {
|
||||
// no more data to consume
|
||||
if (wsgi_req->post_pos >= wsgi_req->post_cl) break;
|
||||
|
||||
if (consume_body_for_readline(wsgi_req)) {
|
||||
*rlen = -1;
|
||||
return NULL;
|
||||
}
|
||||
size_t i;
|
||||
for(i=wsgi_req->post_readline_pos;i<wsgi_req->post_readline_watermark;i++) {
|
||||
if (wsgi_req->post_readline_buf[i] == '\n') {
|
||||
*rlen = (i+1)-wsgi_req->post_readline_pos;
|
||||
char *buf = wsgi_req->post_readline_buf + wsgi_req->post_readline_pos;
|
||||
wsgi_req->post_readline_pos += *rlen;
|
||||
if (wsgi_req->post_readline_pos >= wsgi_req->post_readline_watermark) {
|
||||
wsgi_req->post_readline_pos = 0;
|
||||
wsgi_req->post_readline_watermark = 0;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// no line found, let's return all
|
||||
*rlen = wsgi_req->post_readline_size - wsgi_req->post_readline_pos;
|
||||
char *buf = wsgi_req->post_readline_buf + wsgi_req->post_readline_pos;
|
||||
wsgi_req->post_readline_pos = 0;
|
||||
return buf;
|
||||
|
||||
}
|
||||
|
||||
char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize_t *rlen) {
|
||||
|
||||
int ret = -1;
|
||||
size_t remains = hint;
|
||||
|
||||
// return empty if no post_cl or pos >= post_cl and no residual data
|
||||
if ((!wsgi_req->post_cl || wsgi_req->post_pos >= wsgi_req->post_cl ) && !wsgi_req->post_readline_pos) {
|
||||
return uwsgi.empty;
|
||||
}
|
||||
|
||||
// return the whole input
|
||||
if (remains <= 0) {
|
||||
remains = wsgi_req->post_cl;
|
||||
}
|
||||
|
||||
// some residual data ?
|
||||
if (wsgi_req->post_readline_pos > 0) {
|
||||
if (remains <= (wsgi_req->post_readline_watermark - wsgi_req->post_readline_pos)) {
|
||||
*rlen = remains;
|
||||
char *buf = wsgi_req->post_readline_buf + wsgi_req->post_readline_pos;
|
||||
wsgi_req->post_readline_pos += remains;
|
||||
return buf;
|
||||
}
|
||||
// the hint is higher than residual data, let's copy it to read() memory and go on
|
||||
size_t avail = wsgi_req->post_readline_watermark - wsgi_req->post_readline_pos;
|
||||
// check if we have enough memory...
|
||||
if (avail > wsgi_req->post_read_buf_size) {
|
||||
char *tmp_buf = realloc(wsgi_req->post_read_buf, avail);
|
||||
if (!tmp_buf) {
|
||||
uwsgi_error("uwsgi_request_body_read()/realloc()");
|
||||
*rlen = -1;
|
||||
return NULL;
|
||||
}
|
||||
wsgi_req->post_read_buf = tmp_buf;
|
||||
wsgi_req->post_read_buf_size = avail;
|
||||
if (!wsgi_req->post_warning && wsgi_req->post_read_buf_size > (uwsgi.body_read_warning * 1024*1024)) {
|
||||
uwsgi_log("[uwsgi-warning] you are using read() on request body allocating over than %llu MB, that is really bad and can be avoided...\n", (unsigned long long) (wsgi_req->post_read_buf_size/(1024*1024)));
|
||||
wsgi_req->post_warning = 1;
|
||||
}
|
||||
}
|
||||
// fix remains...
|
||||
if (remains > 0) {
|
||||
remains -= avail;
|
||||
}
|
||||
*rlen += avail;
|
||||
memcpy(wsgi_req->post_read_buf, wsgi_req->post_readline_buf + wsgi_req->post_readline_pos, avail);
|
||||
wsgi_req->post_readline_pos = 0;
|
||||
wsgi_req->post_readline_watermark = 0;
|
||||
}
|
||||
|
||||
if (remains + wsgi_req->post_pos > wsgi_req->post_cl) {
|
||||
remains = wsgi_req->post_cl - wsgi_req->post_pos;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (remains == 0) {
|
||||
if (*rlen > 0) {
|
||||
return wsgi_req->post_read_buf;
|
||||
}
|
||||
else {
|
||||
return uwsgi.empty;
|
||||
}
|
||||
}
|
||||
|
||||
// read from post buffering memory
|
||||
if (uwsgi.post_buffering > 0 && !wsgi_req->post_file) {
|
||||
*rlen += remains;
|
||||
char *buf = wsgi_req->post_buffering_buf+wsgi_req->post_pos;
|
||||
wsgi_req->post_pos += remains;
|
||||
return buf;
|
||||
}
|
||||
|
||||
// ok we need to check if we need to allocate memory
|
||||
if (!wsgi_req->post_read_buf) {
|
||||
wsgi_req->post_read_buf = malloc(remains);
|
||||
if (!wsgi_req->post_read_buf) {
|
||||
uwsgi_error("uwsgi_request_body_read()/malloc()");
|
||||
*rlen = -1;
|
||||
return NULL;
|
||||
}
|
||||
wsgi_req->post_read_buf_size = remains;
|
||||
}
|
||||
// need to realloc ?
|
||||
else {
|
||||
if ((remains+*rlen) > wsgi_req->post_read_buf_size) {
|
||||
char *tmp_buf = realloc(wsgi_req->post_read_buf, (remains+*rlen));
|
||||
if (!tmp_buf) {
|
||||
uwsgi_error("uwsgi_request_body_read()/realloc()");
|
||||
*rlen = -1;
|
||||
return NULL;
|
||||
}
|
||||
wsgi_req->post_read_buf = tmp_buf;
|
||||
wsgi_req->post_read_buf_size = (remains+*rlen);
|
||||
if (!wsgi_req->post_warning && wsgi_req->post_read_buf_size > (uwsgi.body_read_warning * 1024*1024)) {
|
||||
uwsgi_log("[uwsgi-warning] you are using read() on request body allocating over than %llu MB, that is really bad and can be avoided...\n", (unsigned long long) (wsgi_req->post_read_buf_size/(1024*1024)));
|
||||
wsgi_req->post_warning = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check for disk buffered body first (they are all read in one shot)
|
||||
if (wsgi_req->post_file) {
|
||||
if (fread(wsgi_req->post_read_buf + *rlen, remains, 1, wsgi_req->post_file) != 1) {
|
||||
*rlen = -1;
|
||||
uwsgi_log("%llu\n", remains);
|
||||
uwsgi_error("uwsgi_request_body_read()/fread()");
|
||||
return NULL;
|
||||
}
|
||||
*rlen += remains;
|
||||
wsgi_req->post_pos+= remains;
|
||||
return wsgi_req->post_read_buf;
|
||||
}
|
||||
|
||||
// ok read all the required bytes...
|
||||
while(remains > 0) {
|
||||
// here we first try to read (as data could be already available)
|
||||
ssize_t len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_read_buf + *rlen , remains);
|
||||
if (len > 0) {
|
||||
wsgi_req->post_pos+=len;
|
||||
remains -= len;
|
||||
*rlen += len;
|
||||
continue;
|
||||
}
|
||||
// client closed connection...
|
||||
if (len == 0) {
|
||||
*rlen = -1;
|
||||
uwsgi_read_error0(remains);
|
||||
return NULL;
|
||||
}
|
||||
if (len < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
goto wait;
|
||||
}
|
||||
*rlen = -1;
|
||||
uwsgi_read_error(remains);
|
||||
return NULL;
|
||||
}
|
||||
wait:
|
||||
ret = uwsgi_wait_read_req(wsgi_req);
|
||||
if (ret > 0) {
|
||||
len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_read_buf + *rlen, remains);
|
||||
if (len > 0) {
|
||||
wsgi_req->post_pos+=len;
|
||||
remains -= len;
|
||||
*rlen += len;
|
||||
continue;
|
||||
}
|
||||
*rlen = -1;
|
||||
if (len == 0) {
|
||||
uwsgi_read_error0(remains);
|
||||
}
|
||||
else {
|
||||
uwsgi_read_error(remains);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
// 0 means timeout
|
||||
else if (ret == 0) {
|
||||
*rlen = 0;
|
||||
uwsgi_read_timeout(remains);
|
||||
return NULL;
|
||||
}
|
||||
*rlen = -1;
|
||||
uwsgi_read_error(remains);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return wsgi_req->post_read_buf;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
post buffering
|
||||
|
||||
*/
|
||||
|
||||
int uwsgi_postbuffer_do_in_mem(struct wsgi_request *wsgi_req) {
|
||||
|
||||
size_t remains = wsgi_req->post_cl;
|
||||
int ret;
|
||||
char *ptr = wsgi_req->post_buffering_buf;
|
||||
|
||||
while (remains > 0) {
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
|
||||
inc_harakiri(uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
}
|
||||
|
||||
ssize_t rlen = wsgi_req->socket->proto_read_body(wsgi_req, ptr, remains);
|
||||
if (rlen > 0) {
|
||||
remains -= rlen;
|
||||
ptr += rlen;
|
||||
continue;
|
||||
}
|
||||
if (rlen == 0) {
|
||||
uwsgi_read_error0(remains);
|
||||
return -1;
|
||||
}
|
||||
if (rlen < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
goto wait;
|
||||
}
|
||||
uwsgi_read_error(remains);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wait:
|
||||
ret = uwsgi_wait_read_req(wsgi_req);
|
||||
if (ret > 0) {
|
||||
rlen = wsgi_req->socket->proto_read_body(wsgi_req, ptr, remains);
|
||||
if (rlen > 0) {
|
||||
remains -= rlen;
|
||||
ptr += rlen;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (ret < 0) {
|
||||
uwsgi_read_error(remains);
|
||||
return -1;
|
||||
}
|
||||
uwsgi_read_timeout(remains);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_postbuffer_do_in_disk(struct wsgi_request *wsgi_req) {
|
||||
|
||||
size_t post_remains = wsgi_req->post_cl;
|
||||
int ret;
|
||||
int upload_progress_fd = -1;
|
||||
char *upload_progress_filename = NULL;
|
||||
|
||||
wsgi_req->post_file = tmpfile();
|
||||
if (!wsgi_req->post_file) {
|
||||
uwsgi_error("uwsgi_postbuffer_do_in_disk()/tmpfile()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uwsgi.upload_progress) {
|
||||
// first check for X-Progress-ID size
|
||||
// separator + 'X-Progress-ID' + '=' + uuid
|
||||
upload_progress_filename = uwsgi_upload_progress_create(wsgi_req, &upload_progress_fd);
|
||||
if (!upload_progress_filename) {
|
||||
uwsgi_log("invalid X-Progress-ID value: must be a UUID\n");
|
||||
}
|
||||
}
|
||||
|
||||
// manage buffered data and upload progress
|
||||
while (post_remains > 0) {
|
||||
|
||||
// during post buffering we need to constantly reset the harakiri
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
|
||||
inc_harakiri(uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
}
|
||||
|
||||
// we use the already available post buffering buffer to read chunks....
|
||||
size_t remains = UMIN(post_remains, uwsgi.post_buffering);
|
||||
|
||||
// first try to read data (there could be something already available
|
||||
ssize_t rlen = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_buffering_buf, remains);
|
||||
if (rlen > 0) goto write;
|
||||
if (rlen == 0) {
|
||||
uwsgi_read_error0(remains);
|
||||
goto end;
|
||||
}
|
||||
if (rlen < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
goto wait;
|
||||
}
|
||||
uwsgi_read_error(remains);
|
||||
goto end;
|
||||
}
|
||||
|
||||
wait:
|
||||
ret = uwsgi_wait_read_req(wsgi_req);
|
||||
if (ret > 0) {
|
||||
rlen = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_buffering_buf, remains);
|
||||
if (rlen > 0) goto write;
|
||||
if (rlen == 0) {
|
||||
uwsgi_read_error0(remains);
|
||||
}
|
||||
else {
|
||||
uwsgi_read_error(remains);
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
if (ret < 0) {
|
||||
uwsgi_read_error(remains);
|
||||
goto end;
|
||||
}
|
||||
uwsgi_read_timeout(remains);
|
||||
goto end;
|
||||
|
||||
write:
|
||||
if (fwrite(wsgi_req->post_buffering_buf, rlen, 1, wsgi_req->post_file) != 1) {
|
||||
uwsgi_error("uwsgi_postbuffer_do_in_disk()/fwrite()");
|
||||
goto end;
|
||||
}
|
||||
|
||||
post_remains -= rlen;
|
||||
|
||||
if (upload_progress_filename) {
|
||||
// stop updating it on errors
|
||||
if (uwsgi_upload_progress_update(wsgi_req, upload_progress_fd, post_remains)) {
|
||||
uwsgi_upload_progress_destroy(upload_progress_filename, upload_progress_fd);
|
||||
upload_progress_filename = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
rewind(wsgi_req->post_file);
|
||||
|
||||
if (upload_progress_filename) {
|
||||
uwsgi_upload_progress_destroy(upload_progress_filename, upload_progress_fd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
end:
|
||||
if (upload_progress_filename) {
|
||||
uwsgi_upload_progress_destroy(upload_progress_filename, upload_progress_fd);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
+38
-38
@@ -62,49 +62,49 @@ int uwsgi_regexp_ovector(pcre * pattern, pcre_extra * pattern_extra) {
|
||||
|
||||
char *uwsgi_regexp_apply_ovec(char *src, int src_n, char *dst, int dst_n, int *ovector, int n) {
|
||||
|
||||
int i;
|
||||
int dollar = 0;
|
||||
int i;
|
||||
int dollar = 0;
|
||||
|
||||
size_t dollars = n;
|
||||
|
||||
for(i=0;i<dst_n;i++) {
|
||||
if (dst[i] == '$') {
|
||||
dollars++;
|
||||
}
|
||||
}
|
||||
size_t dollars = n;
|
||||
|
||||
char *res = uwsgi_malloc(dst_n + (src_n * dollars) + 1);
|
||||
char *ptr = res;
|
||||
for(i=0;i<dst_n;i++) {
|
||||
if (dst[i] == '$') {
|
||||
dollars++;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < dst_n; i++) {
|
||||
if (dollar) {
|
||||
if (isdigit((int) dst[i])) {
|
||||
int pos = (dst[i] - 48);
|
||||
if (pos <= n) {
|
||||
pos = pos * 2;
|
||||
memcpy(ptr, src + ovector[pos], ovector[pos + 1] - ovector[pos]);
|
||||
ptr += ovector[pos + 1] - ovector[pos];
|
||||
}
|
||||
}
|
||||
else {
|
||||
*ptr++ = '$';
|
||||
*ptr++ = dst[i];
|
||||
}
|
||||
dollar = 0;
|
||||
}
|
||||
else {
|
||||
if (dst[i] == '$') {
|
||||
dollar = 1;
|
||||
}
|
||||
else {
|
||||
*ptr++ = dst[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
char *res = uwsgi_malloc(dst_n + (src_n * dollars) + 1);
|
||||
char *ptr = res;
|
||||
|
||||
*ptr++ = 0;
|
||||
for (i = 0; i < dst_n; i++) {
|
||||
if (dollar) {
|
||||
if (isdigit((int) dst[i])) {
|
||||
int pos = (dst[i] - 48);
|
||||
if (pos <= n) {
|
||||
pos = pos * 2;
|
||||
memcpy(ptr, src + ovector[pos], ovector[pos + 1] - ovector[pos]);
|
||||
ptr += ovector[pos + 1] - ovector[pos];
|
||||
}
|
||||
}
|
||||
else {
|
||||
*ptr++ = '$';
|
||||
*ptr++ = dst[i];
|
||||
}
|
||||
dollar = 0;
|
||||
}
|
||||
else {
|
||||
if (dst[i] == '$') {
|
||||
dollar = 1;
|
||||
}
|
||||
else {
|
||||
*ptr++ = dst[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
*ptr++ = 0;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+63
-644
@@ -1,226 +1,65 @@
|
||||
#ifdef UWSGI_ROUTING
|
||||
#include <uwsgi.h>
|
||||
#include "uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_buffer *uwsgi_routing_translate(struct wsgi_request *wsgi_req, struct uwsgi_route *ur, char *subject, uint16_t subject_len, char *data, size_t data_len) {
|
||||
|
||||
char *pass1 = data;
|
||||
size_t pass1_len = data_len;
|
||||
|
||||
// cannot fail
|
||||
if (subject) {
|
||||
pass1 = uwsgi_regexp_apply_ovec(subject, subject_len, data, data_len, ur->ovector, ur->ovn);
|
||||
pass1_len = strlen(pass1);
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(pass1_len);
|
||||
size_t i;
|
||||
int status = 0;
|
||||
char *key = NULL;
|
||||
size_t keylen = 0;
|
||||
for(i=0;i<pass1_len;i++) {
|
||||
switch(status) {
|
||||
case 0:
|
||||
if (pass1[i] == '$') {
|
||||
status = 1;
|
||||
break;
|
||||
}
|
||||
if (uwsgi_buffer_append(ub, pass1 + i, 1)) goto error;
|
||||
break;
|
||||
case 1:
|
||||
if (pass1[i] == '{') {
|
||||
status = 2;
|
||||
key = pass1+i+1;
|
||||
keylen = 0;
|
||||
break;
|
||||
}
|
||||
status = 0;
|
||||
key = NULL;
|
||||
keylen = 0;
|
||||
if (uwsgi_buffer_append(ub, "$", 1)) goto error;
|
||||
if (uwsgi_buffer_append(ub, pass1 + i, 1)) goto error;
|
||||
break;
|
||||
case 2:
|
||||
if (pass1[i] == '}') {
|
||||
uint16_t vallen = 0;
|
||||
char *value = uwsgi_get_var(wsgi_req, key, keylen, &vallen);
|
||||
if (value) {
|
||||
if (uwsgi_buffer_append(ub, value, vallen)) goto error;
|
||||
}
|
||||
status = 0;
|
||||
key = NULL;
|
||||
keylen = 0;
|
||||
break;
|
||||
}
|
||||
keylen++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// fix the buffer
|
||||
if (status == 1) {
|
||||
if (uwsgi_buffer_append(ub, "$", 1)) goto error;
|
||||
}
|
||||
else if (status == 2) {
|
||||
if (uwsgi_buffer_append(ub, "${", 2)) goto error;
|
||||
if (keylen > 0) {
|
||||
if (uwsgi_buffer_append(ub, key, keylen)) goto error;
|
||||
}
|
||||
}
|
||||
|
||||
// add the final NULL byte (to simplify plugin work)
|
||||
if (uwsgi_buffer_append(ub, "\0", 1)) goto error;
|
||||
// .. but came back of 1 position to avoid accounting it
|
||||
ub->pos--;
|
||||
|
||||
if (pass1 != data) {
|
||||
free(pass1);
|
||||
}
|
||||
return ub;
|
||||
|
||||
error:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int uwsgi_apply_routes_do(struct wsgi_request *wsgi_req, char *subject, uint16_t subject_len) {
|
||||
|
||||
struct uwsgi_route *routes = uwsgi.routes;
|
||||
void *goon_func = NULL;
|
||||
int n = -1;
|
||||
|
||||
char *orig_subject = subject;
|
||||
uint16_t orig_subject_len = subject_len;
|
||||
|
||||
while (routes) {
|
||||
|
||||
if (wsgi_req->route_goto > 0 && wsgi_req->route_pc < wsgi_req->route_goto) {
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (goon_func && goon_func == routes->func) {
|
||||
goto next;
|
||||
}
|
||||
goon_func = NULL;
|
||||
wsgi_req->route_goto = 0;
|
||||
|
||||
if (!routes->if_func) {
|
||||
if (!subject) {
|
||||
char **subject2 = (char **) (((char *) (wsgi_req)) + routes->subject);
|
||||
uint16_t *subject_len2 = (uint16_t *) (((char *) (wsgi_req)) + routes->subject_len);
|
||||
subject = *subject2 ;
|
||||
subject_len = *subject_len2;
|
||||
}
|
||||
n = uwsgi_regexp_match_ovec(routes->pattern, routes->pattern_extra, subject, subject_len, routes->ovector, routes->ovn);
|
||||
}
|
||||
else {
|
||||
int ret = routes->if_func(wsgi_req, routes);
|
||||
// error
|
||||
if (ret < 0) {
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
// true
|
||||
if (!routes->if_negate) {
|
||||
if (ret == 0) {
|
||||
goto next;
|
||||
}
|
||||
n = ret;
|
||||
}
|
||||
else {
|
||||
if (ret > 0) {
|
||||
goto next;
|
||||
}
|
||||
n = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (n >= 0) {
|
||||
wsgi_req->is_routing = 1;
|
||||
int ret = routes->func(wsgi_req, routes);
|
||||
wsgi_req->is_routing = 0;
|
||||
if (ret == UWSGI_ROUTE_BREAK) {
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].routed_requests++;
|
||||
return ret;
|
||||
}
|
||||
if (ret == UWSGI_ROUTE_CONTINUE) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ret == UWSGI_ROUTE_GOON) {
|
||||
goon_func = routes->func;
|
||||
}
|
||||
}
|
||||
next:
|
||||
subject = orig_subject;
|
||||
subject_len = orig_subject_len;
|
||||
routes = routes->next;
|
||||
if (routes) wsgi_req->route_pc++;
|
||||
}
|
||||
|
||||
return UWSGI_ROUTE_CONTINUE;
|
||||
}
|
||||
|
||||
int uwsgi_apply_routes(struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (!uwsgi.routes)
|
||||
return UWSGI_ROUTE_CONTINUE;
|
||||
struct uwsgi_route *routes = uwsgi.routes;
|
||||
|
||||
// avoid loops
|
||||
if (wsgi_req->is_routing)
|
||||
if (!routes)
|
||||
return UWSGI_ROUTE_CONTINUE;
|
||||
|
||||
if (uwsgi_parse_vars(wsgi_req)) {
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
// in case of static files serving previous rules could be applied
|
||||
if (wsgi_req->routes_applied) {
|
||||
return UWSGI_ROUTE_CONTINUE;
|
||||
}
|
||||
|
||||
return uwsgi_apply_routes_do(wsgi_req, NULL, 0);
|
||||
}
|
||||
|
||||
static void *uwsgi_route_get_condition_func(char *name) {
|
||||
struct uwsgi_route_condition *urc = uwsgi.route_conditions;
|
||||
while(urc) {
|
||||
if (!strcmp(urc->name, name)) {
|
||||
return urc->func;
|
||||
while (routes) {
|
||||
char **subject = (char **) (((char *) (wsgi_req)) + routes->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *) (wsgi_req)) + routes->subject_len);
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("route subject = %.*s\n", *subject_len, *subject);
|
||||
#endif
|
||||
int n = uwsgi_regexp_match_ovec(routes->pattern, routes->pattern_extra, *subject, *subject_len, routes->ovector, routes->ovn);
|
||||
if (n >= 0) {
|
||||
int ret = routes->func(wsgi_req, routes);
|
||||
if (ret == UWSGI_ROUTE_BREAK) uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].routed_requests++;
|
||||
if (ret != UWSGI_ROUTE_NEXT) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
urc = urc->next;
|
||||
routes = routes->next;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
return UWSGI_ROUTE_CONTINUE;
|
||||
}
|
||||
|
||||
int uwsgi_apply_routes_fast(struct wsgi_request *wsgi_req, char *uri, int len) {
|
||||
|
||||
struct uwsgi_route *routes = uwsgi.routes;
|
||||
|
||||
if (!routes)
|
||||
return UWSGI_ROUTE_CONTINUE;
|
||||
|
||||
while (routes) {
|
||||
int n = uwsgi_regexp_match_ovec(routes->pattern, routes->pattern_extra, uri, len, routes->ovector, routes->ovn);
|
||||
if (n >= 0) {
|
||||
int ret = routes->func(wsgi_req, routes);
|
||||
if (ret == UWSGI_ROUTE_BREAK) uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].routed_requests++;
|
||||
if (ret != UWSGI_ROUTE_NEXT) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
routes = routes->next;
|
||||
}
|
||||
|
||||
return UWSGI_ROUTE_CONTINUE;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
|
||||
|
||||
struct uwsgi_route *old_ur = NULL,*ur = uwsgi.routes;
|
||||
uint64_t pos = 0;
|
||||
while(ur) {
|
||||
old_ur = ur;
|
||||
ur = ur->next;
|
||||
pos++;
|
||||
}
|
||||
ur = uwsgi_calloc(sizeof(struct uwsgi_route));
|
||||
if (old_ur) {
|
||||
old_ur->next = ur;
|
||||
}
|
||||
else {
|
||||
uwsgi.routes = ur;
|
||||
}
|
||||
|
||||
ur->pos = pos;
|
||||
|
||||
// is it a label ?
|
||||
if (foobar == NULL) {
|
||||
ur->label = value;
|
||||
ur->label_len = strlen(value);
|
||||
return;
|
||||
}
|
||||
|
||||
char *route = uwsgi_str(value);
|
||||
|
||||
char *space = strchr(route, ' ');
|
||||
@@ -231,27 +70,23 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
|
||||
|
||||
*space = 0;
|
||||
|
||||
if (!strcmp(foobar, "if") || !strcmp(foobar, "if-not")) {
|
||||
char *colon = strchr(route, ':');
|
||||
if (!colon) {
|
||||
uwsgi_log("invalid route condition syntax\n");
|
||||
exit(1);
|
||||
}
|
||||
*colon = 0;
|
||||
|
||||
if (!strcmp(foobar, "if-not")) {
|
||||
ur->if_negate = 1;
|
||||
}
|
||||
|
||||
foobar = colon+1;
|
||||
ur->if_func = uwsgi_route_get_condition_func(route);
|
||||
if (!ur->if_func) {
|
||||
uwsgi_log("unable to find \"%s\" route condition\n", route);
|
||||
exit(1);
|
||||
struct uwsgi_route *ur = uwsgi.routes;
|
||||
if (!ur) {
|
||||
uwsgi.routes = uwsgi_calloc(sizeof(struct uwsgi_route));
|
||||
ur = uwsgi.routes;
|
||||
}
|
||||
else {
|
||||
while (ur) {
|
||||
if (!ur->next) {
|
||||
ur->next = uwsgi_calloc(sizeof(struct uwsgi_route));
|
||||
ur = ur->next;
|
||||
break;
|
||||
}
|
||||
ur = ur->next;
|
||||
}
|
||||
}
|
||||
|
||||
else if (!strcmp(foobar, "http_host")) {
|
||||
if (!strcmp(foobar, "http_host")) {
|
||||
ur->subject = offsetof(struct wsgi_request, host);
|
||||
ur->subject_len = offsetof(struct wsgi_request, host_len);
|
||||
}
|
||||
@@ -263,44 +98,21 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
|
||||
ur->subject = offsetof(struct wsgi_request, query_string);
|
||||
ur->subject_len = offsetof(struct wsgi_request, query_string_len);
|
||||
}
|
||||
else if (!strcmp(foobar, "remote_addr")) {
|
||||
ur->subject = offsetof(struct wsgi_request, remote_addr);
|
||||
ur->subject_len = offsetof(struct wsgi_request, remote_addr_len);
|
||||
}
|
||||
else if (!strcmp(foobar, "user_agent")) {
|
||||
ur->subject = offsetof(struct wsgi_request, user_agent);
|
||||
ur->subject_len = offsetof(struct wsgi_request, user_agent_len);
|
||||
}
|
||||
else if (!strcmp(foobar, "referer")) {
|
||||
ur->subject = offsetof(struct wsgi_request, referer);
|
||||
ur->subject_len = offsetof(struct wsgi_request, referer_len);
|
||||
}
|
||||
else if (!strcmp(foobar, "remote_user")) {
|
||||
ur->subject = offsetof(struct wsgi_request, remote_user);
|
||||
ur->subject_len = offsetof(struct wsgi_request, remote_user_len);
|
||||
}
|
||||
else {
|
||||
ur->subject = offsetof(struct wsgi_request, path_info);
|
||||
ur->subject_len = offsetof(struct wsgi_request, path_info_len);
|
||||
}
|
||||
|
||||
ur->subject_str = foobar;
|
||||
ur->subject_str_len = strlen(ur->subject_str);
|
||||
ur->regexp = route;
|
||||
if (uwsgi_regexp_build(route, &ur->pattern, &ur->pattern_extra)) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (ur->subject && ur->subject_len) {
|
||||
if (uwsgi_regexp_build(route, &ur->pattern, &ur->pattern_extra)) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ur->ovn = uwsgi_regexp_ovector(ur->pattern, ur->pattern_extra);
|
||||
if (ur->ovn > 0) {
|
||||
ur->ovector = uwsgi_calloc(sizeof(int) * (3 * (ur->ovn + 1)));
|
||||
}
|
||||
ur->ovn = uwsgi_regexp_ovector(ur->pattern, ur->pattern_extra);
|
||||
if (ur->ovn > 0) {
|
||||
ur->ovector = uwsgi_calloc(sizeof(int) * (3 * (ur->ovn + 1)));
|
||||
}
|
||||
|
||||
char *command = space + 1;
|
||||
ur->action = uwsgi_str(command);
|
||||
|
||||
char *colon = strchr(command, ':');
|
||||
if (!colon) {
|
||||
@@ -326,7 +138,6 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
|
||||
last_ur->is_last = 1;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
r = r->next;
|
||||
}
|
||||
@@ -335,358 +146,6 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int uwsgi_route_api_func(struct wsgi_request *wsgi_req, char *router, char *args) {
|
||||
struct uwsgi_route *ur = NULL;
|
||||
struct uwsgi_router *r = uwsgi.routers;
|
||||
while(r) {
|
||||
if (!strcmp(router, r->name)) {
|
||||
goto found;
|
||||
}
|
||||
r = r->next;
|
||||
}
|
||||
free(args);
|
||||
return -1;
|
||||
found:
|
||||
ur = uwsgi_calloc(sizeof(struct uwsgi_route));
|
||||
// initialize the virtual route
|
||||
if (r->func(ur, args)) {
|
||||
free(ur);
|
||||
free(args);
|
||||
return -1;
|
||||
}
|
||||
// call it
|
||||
int ret = ur->func(wsgi_req, ur);
|
||||
if (ur->free) {
|
||||
ur->free(ur);
|
||||
}
|
||||
free(ur);
|
||||
free(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// continue/last route
|
||||
|
||||
static int uwsgi_router_continue_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
|
||||
return UWSGI_ROUTE_CONTINUE;
|
||||
}
|
||||
|
||||
static int uwsgi_router_continue(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_continue_func;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// break route
|
||||
|
||||
static int uwsgi_router_break_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
|
||||
if (route->data_len >= 3) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, route->data, route->data_len)) goto end;
|
||||
if (uwsgi_response_add_connection_close(wsgi_req)) goto end;
|
||||
if (uwsgi_response_add_content_type(wsgi_req, "text/plain", 10)) goto end;
|
||||
// no need to check for return value
|
||||
uwsgi_response_write_headers_do(wsgi_req);
|
||||
}
|
||||
end:
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
static int uwsgi_router_break(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_break_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// goon route
|
||||
static int uwsgi_router_goon_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
|
||||
return UWSGI_ROUTE_GOON;
|
||||
}
|
||||
static int uwsgi_router_goon(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_goon_func;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// log route
|
||||
static int uwsgi_router_log_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);
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
||||
if (!ub) return UWSGI_ROUTE_BREAK;
|
||||
|
||||
uwsgi_log("%.*s\n", ub->pos, ub->buf);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
|
||||
static int uwsgi_router_log(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_log_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// logvar route
|
||||
static int uwsgi_router_logvar_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);
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data2, ur->data2_len);
|
||||
if (!ub) return UWSGI_ROUTE_BREAK;
|
||||
uwsgi_logvar_add(wsgi_req, ur->data, ur->data_len, ub->buf, ub->pos);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
|
||||
static int uwsgi_router_logvar(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_logvar_func;
|
||||
char *equal = strchr(arg, '=');
|
||||
if (!equal) {
|
||||
uwsgi_log("invalid logvar syntax, must be key=value\n");
|
||||
exit(1);
|
||||
}
|
||||
ur->data = arg;
|
||||
ur->data_len = equal-arg;
|
||||
ur->data2 = equal+1;
|
||||
ur->data2_len = strlen(ur->data2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// goto route
|
||||
|
||||
static int uwsgi_router_goto_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
// build the label (if needed)
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
||||
if (!ub) return UWSGI_ROUTE_BREAK;
|
||||
|
||||
// find the label
|
||||
struct uwsgi_route *routes = uwsgi.routes;
|
||||
while(routes) {
|
||||
if (!routes->label) goto next;
|
||||
if (!uwsgi_strncmp(routes->label, routes->label_len, ub->buf, ub->pos)) {
|
||||
wsgi_req->route_goto = routes->pos;
|
||||
goto found;
|
||||
}
|
||||
next:
|
||||
routes = routes->next;
|
||||
}
|
||||
|
||||
wsgi_req->route_goto = ur->custom;
|
||||
|
||||
found:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
if (wsgi_req->route_goto <= wsgi_req->route_pc) {
|
||||
wsgi_req->route_goto = 0;
|
||||
uwsgi_log("[uwsgi-route] ERROR \"goto\" instruction can only jump forward (check your label !!!)\n");
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
|
||||
static int uwsgi_router_goto(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_goto_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
ur->custom = atoi(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// addvar route
|
||||
static int uwsgi_router_addvar_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);
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data2, ur->data2_len);
|
||||
if (!ub) return UWSGI_ROUTE_BREAK;
|
||||
|
||||
if (!uwsgi_req_append(wsgi_req, ur->data, ur->data_len, ub->buf, ub->pos)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_router_addvar(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_addvar_func;
|
||||
char *equal = strchr(arg, '=');
|
||||
if (!equal) {
|
||||
uwsgi_log("[uwsgi-route] invalid addvar syntax, must be KEY=VAL\n");
|
||||
exit(1);
|
||||
}
|
||||
ur->data = arg;
|
||||
ur->data_len = equal-arg;
|
||||
ur->data2 = equal+1;
|
||||
ur->data2_len = strlen(ur->data2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// addheader route
|
||||
static int uwsgi_router_addheader_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);
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
||||
if (!ub) return UWSGI_ROUTE_BREAK;
|
||||
uwsgi_additional_header_add(wsgi_req, ub->buf, ub->pos);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_router_addheader(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_addheader_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// remheader route
|
||||
static int uwsgi_router_remheader_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);
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
||||
if (!ub) return UWSGI_ROUTE_BREAK;
|
||||
uwsgi_remove_header(wsgi_req, ub->buf, ub->pos);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_router_remheader(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_remheader_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// signal route
|
||||
static int uwsgi_router_signal_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
|
||||
uwsgi_signal_send(uwsgi.signal_socket, route->custom);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_signal(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_signal_func;
|
||||
ur->custom = atoi(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// send route
|
||||
static int uwsgi_router_send_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
|
||||
uwsgi_response_write_body_do(wsgi_req, route->data, route->data_len);
|
||||
if (route->custom) {
|
||||
uwsgi_response_write_body_do(wsgi_req, "\r\n", 2);
|
||||
}
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_send(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_send_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
static int uwsgi_router_send_crnl(struct uwsgi_route *ur, char *arg) {
|
||||
uwsgi_router_send(ur, arg);
|
||||
ur->custom = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_route_condition_exists(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, ur->subject_str_len);
|
||||
if (!ub) return -1;
|
||||
if (uwsgi_file_exists(ub->buf)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return 1;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_route_condition_isfile(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, ur->subject_str_len);
|
||||
if (!ub) return -1;
|
||||
if (uwsgi_is_file(ub->buf)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return 1;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_route_condition_isdir(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, ur->subject_str_len);
|
||||
if (!ub) return -1;
|
||||
if (uwsgi_is_dir(ub->buf)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return 1;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_route_condition_islink(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, ur->subject_str_len);
|
||||
if (!ub) return -1;
|
||||
if (uwsgi_is_link(ub->buf)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return 1;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_route_condition_isexec(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, ur->subject_str_len);
|
||||
if (!ub) return -1;
|
||||
if (!access(ub->buf, X_OK)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return 1;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// register embedded routers
|
||||
void uwsgi_register_embedded_routers() {
|
||||
uwsgi_register_router("continue", uwsgi_router_continue);
|
||||
uwsgi_register_router("last", uwsgi_router_continue);
|
||||
uwsgi_register_router("break", uwsgi_router_break);
|
||||
uwsgi_register_router("goon", uwsgi_router_goon);
|
||||
uwsgi_register_router("log", uwsgi_router_log);
|
||||
uwsgi_register_router("logvar", uwsgi_router_logvar);
|
||||
uwsgi_register_router("goto", uwsgi_router_goto);
|
||||
uwsgi_register_router("addvar", uwsgi_router_addvar);
|
||||
uwsgi_register_router("addheader", uwsgi_router_addheader);
|
||||
uwsgi_register_router("delheader", uwsgi_router_remheader);
|
||||
uwsgi_register_router("remheader", uwsgi_router_remheader);
|
||||
uwsgi_register_router("signal", uwsgi_router_signal);
|
||||
uwsgi_register_router("send", uwsgi_router_send);
|
||||
uwsgi_register_router("send-crnl", uwsgi_router_send_crnl);
|
||||
|
||||
uwsgi_register_route_condition("exists", uwsgi_route_condition_exists);
|
||||
uwsgi_register_route_condition("isfile", uwsgi_route_condition_isfile);
|
||||
uwsgi_register_route_condition("isdir", uwsgi_route_condition_isdir);
|
||||
uwsgi_register_route_condition("islink", uwsgi_route_condition_islink);
|
||||
uwsgi_register_route_condition("isexec", uwsgi_route_condition_isexec);
|
||||
}
|
||||
|
||||
struct uwsgi_router *uwsgi_register_router(char *name, int (*func) (struct uwsgi_route *, char *)) {
|
||||
|
||||
struct uwsgi_router *ur = uwsgi.routers;
|
||||
@@ -710,44 +169,4 @@ struct uwsgi_router *uwsgi_register_router(char *name, int (*func) (struct uwsgi
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_route_condition *uwsgi_register_route_condition(char *name, int (*func) (struct wsgi_request *, struct uwsgi_route *)) {
|
||||
struct uwsgi_route_condition *old_urc = NULL,*urc = uwsgi.route_conditions;
|
||||
while(urc) {
|
||||
if (!strcmp(urc->name, name)) {
|
||||
return urc;
|
||||
}
|
||||
old_urc = urc;
|
||||
urc = urc->next;
|
||||
}
|
||||
|
||||
urc = uwsgi_calloc(sizeof(struct uwsgi_route_condition));
|
||||
urc->name = name;
|
||||
urc->func = func;
|
||||
|
||||
if (old_urc) {
|
||||
old_urc->next = urc;
|
||||
}
|
||||
else {
|
||||
uwsgi.route_conditions = urc;
|
||||
}
|
||||
|
||||
return urc;
|
||||
}
|
||||
|
||||
void uwsgi_routing_dump() {
|
||||
struct uwsgi_route *routes = uwsgi.routes;
|
||||
if (!routes) return;
|
||||
uwsgi_log("*** dumping internal routing table ***\n");
|
||||
while(routes) {
|
||||
if (routes->label) {
|
||||
uwsgi_log("[rule: %llu] label: %s\n", (unsigned long long ) routes->pos, routes->label);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[rule: %llu] subject: %s %s: %s%s action: %s\n", (unsigned long long ) routes->pos, routes->subject_str, routes->if_func ? "func" : "regexp", routes->if_negate ? "!" : "", routes->regexp, routes->action);
|
||||
}
|
||||
routes = routes->next;
|
||||
}
|
||||
uwsgi_log("*** end of the internal routing table ***\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
+42
-78
@@ -7,51 +7,25 @@ int uwsgi_register_rpc(char *name, uint8_t modifier1, uint8_t args, void *func)
|
||||
struct uwsgi_rpc *urpc;
|
||||
int ret = -1;
|
||||
|
||||
if (uwsgi.mywid == 0 && uwsgi.workers[0].pid != uwsgi.mypid) {
|
||||
uwsgi_log("only the master and the workers can register RPC functions\n");
|
||||
if (uwsgi.mywid != 0) {
|
||||
uwsgi_log("you can register RPC functions only in the master\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_lock(uwsgi.rpc_table_lock);
|
||||
|
||||
// first check if a function is already registered
|
||||
size_t i;
|
||||
for(i=0;i<uwsgi.shared->rpc_count[uwsgi.mywid];i++) {
|
||||
int pos = (uwsgi.mywid * uwsgi.rpc_max) + i;
|
||||
urpc = &uwsgi.rpc_table[pos];
|
||||
if (!strcmp(name, urpc->name)) {
|
||||
goto already;
|
||||
}
|
||||
}
|
||||
if (uwsgi.shared->rpc_count < MAX_RPC) {
|
||||
urpc = &uwsgi.shared->rpc_table[uwsgi.shared->rpc_count];
|
||||
|
||||
if (uwsgi.shared->rpc_count[uwsgi.mywid] < uwsgi.rpc_max) {
|
||||
int pos = (uwsgi.mywid * uwsgi.rpc_max) + uwsgi.shared->rpc_count[uwsgi.mywid];
|
||||
urpc = &uwsgi.rpc_table[pos];
|
||||
uwsgi.shared->rpc_count[uwsgi.mywid]++;
|
||||
already:
|
||||
memcpy(urpc->name, name, strlen(name));
|
||||
urpc->modifier1 = modifier1;
|
||||
urpc->args = args;
|
||||
urpc->func = func;
|
||||
urpc->shared = uwsgi.mywid == 0 ? 1 : 0;
|
||||
|
||||
uwsgi.shared->rpc_count++;
|
||||
|
||||
ret = 0;
|
||||
if (uwsgi.mywid == 0) {
|
||||
uwsgi_log("registered shared/inherited RPC function \"%s\"\n", name);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("registered RPC function \"%s\" on worker %d\n", name, uwsgi.mywid);
|
||||
}
|
||||
}
|
||||
|
||||
// implement cow
|
||||
if (uwsgi.mywid == 0) {
|
||||
int i;
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
uwsgi.shared->rpc_count[i] = uwsgi.shared->rpc_count[0];
|
||||
int pos = (i * uwsgi.rpc_max);
|
||||
memcpy(&uwsgi.rpc_table[pos], uwsgi.rpc_table, sizeof(struct uwsgi_rpc) * uwsgi.rpc_max);
|
||||
}
|
||||
uwsgi_log("registered RPC function %s\n", name);
|
||||
}
|
||||
|
||||
uwsgi_unlock(uwsgi.rpc_table_lock);
|
||||
@@ -62,15 +36,13 @@ already:
|
||||
uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], char *output) {
|
||||
|
||||
struct uwsgi_rpc *urpc = NULL;
|
||||
uint64_t i;
|
||||
int i;
|
||||
uint16_t ret = 0;
|
||||
|
||||
int pos = (uwsgi.mywid * uwsgi.rpc_max);
|
||||
|
||||
for (i = 0; i < uwsgi.shared->rpc_count[uwsgi.mywid]; i++) {
|
||||
if (uwsgi.rpc_table[pos + i].name[0] != 0) {
|
||||
if (!strcmp(uwsgi.rpc_table[pos + i].name, name)) {
|
||||
urpc = &uwsgi.rpc_table[pos + i];
|
||||
for (i = 0; i < uwsgi.shared->rpc_count; i++) {
|
||||
if (uwsgi.shared->rpc_table[i].name[0] != 0) {
|
||||
if (!strcmp(uwsgi.shared->rpc_table[i].name, name)) {
|
||||
urpc = &uwsgi.shared->rpc_table[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -90,31 +62,25 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
|
||||
|
||||
uint8_t i;
|
||||
uint16_t ulen;
|
||||
struct uwsgi_header *uh = NULL;
|
||||
struct uwsgi_header uh;
|
||||
char *buffer = NULL;
|
||||
|
||||
*len = 0;
|
||||
|
||||
if (node == NULL || !strcmp(node, "")) {
|
||||
// allocate the whole buffer
|
||||
buffer = uwsgi_malloc(UMAX16);
|
||||
buffer = uwsgi_malloc(65536);
|
||||
*len = uwsgi_rpc(func, argc, argv, argvs, buffer);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
// connect to node (async way)
|
||||
int fd = uwsgi_connect(node, 0, 1);
|
||||
// connect to node
|
||||
int fd = uwsgi_connect(node, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
|
||||
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
|
||||
// wait for connection;
|
||||
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
if (ret <= 0) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// prepare a uwsgi array
|
||||
uint16_t buffer_size = 2 + strlen(func);
|
||||
|
||||
@@ -123,16 +89,14 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
|
||||
}
|
||||
|
||||
// allocate the whole buffer
|
||||
buffer = uwsgi_malloc(4+buffer_size);
|
||||
buffer = uwsgi_malloc(65536);
|
||||
|
||||
// set the uwsgi header
|
||||
uh = (struct uwsgi_header *) buffer;
|
||||
uh->modifier1 = 173;
|
||||
uh->pktsize = buffer_size;
|
||||
uh->modifier2 = 0;
|
||||
uh.modifier1 = 173;
|
||||
uh.pktsize = buffer_size;
|
||||
uh.modifier2 = 0;
|
||||
|
||||
// add func to the array
|
||||
char *bufptr = buffer + 4;
|
||||
char *bufptr = buffer;
|
||||
ulen = strlen(func);
|
||||
*bufptr++ = (uint8_t) (ulen & 0xff);
|
||||
*bufptr++ = (uint8_t) ((ulen >> 8) & 0xff);
|
||||
@@ -147,33 +111,33 @@ 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
|
||||
if (uwsgi_write_true_nb(fd, buffer, buffer_size+4, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
goto error;
|
||||
if (write(fd, &uh, 4) != 4) {
|
||||
uwsgi_error("write()");
|
||||
close(fd);
|
||||
free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// 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])) {
|
||||
goto error;
|
||||
if (write(fd, buffer, buffer_size) != buffer_size) {
|
||||
uwsgi_error("write()");
|
||||
close(fd);
|
||||
free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (uwsgi_read_response(fd, &uh, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &buffer) < 0) {
|
||||
close(fd);
|
||||
free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
*len = rlen;
|
||||
|
||||
*len = uh.pktsize;
|
||||
if (*len == 0) {
|
||||
goto error;
|
||||
free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
return buffer;
|
||||
|
||||
error:
|
||||
close(fd);
|
||||
free(buffer);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_rpc_init() {
|
||||
uwsgi.rpc_table = uwsgi_calloc_shared((sizeof(struct uwsgi_rpc) * uwsgi.rpc_max) * (uwsgi.numproc+1));
|
||||
uwsgi.shared->rpc_count = uwsgi_calloc_shared(sizeof(uint64_t) * (uwsgi.numproc+1));
|
||||
}
|
||||
|
||||
+163
-28
@@ -2,38 +2,173 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
// sendfile() abstraction
|
||||
ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
|
||||
ssize_t uwsgi_sendfile(struct wsgi_request * wsgi_req) {
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
off_t sf_len = len;
|
||||
int sf_ret = sendfile(filefd, sockfd, pos, len, NULL, &sf_len, 0);
|
||||
if (sf_ret == 0 || (sf_ret == -1 && errno == EAGAIN)) return sf_len;
|
||||
return -1;
|
||||
#elif defined(__APPLE__)
|
||||
off_t sf_len = len;
|
||||
int sf_ret = sendfile(filefd, sockfd, pos, &sf_len, NULL, 0);
|
||||
if (sf_ret == 0 || (sf_ret == -1 && errno == EAGAIN)) return sf_len;
|
||||
return -1;
|
||||
#elif defined(__linux__) || defined(__sun__)
|
||||
off_t off = pos;
|
||||
return sendfile(sockfd, filefd, &off, len);
|
||||
#else
|
||||
// for platform not supporting sendfile we need to rely on boring read/write
|
||||
// generally that platforms have very low memory, so use a 8k buffer
|
||||
char buf[8192];
|
||||
if (pos > 0) {
|
||||
if (lseek(filefd, pos, SEEK_SET)) {
|
||||
uwsgi_error("uwsgi_sendfile_do()/seek()");
|
||||
return -1;
|
||||
int fd = wsgi_req->sendfile_fd;
|
||||
int sockfd = wsgi_req->poll.fd;
|
||||
struct stat stat_buf;
|
||||
ssize_t sst = 0;
|
||||
|
||||
if (!wsgi_req->sendfile_fd_size) {
|
||||
|
||||
if (fstat(fd, &stat_buf)) {
|
||||
uwsgi_error("fstat()");
|
||||
goto end;
|
||||
}
|
||||
else {
|
||||
wsgi_req->sendfile_fd_size = stat_buf.st_size;
|
||||
}
|
||||
}
|
||||
ssize_t rlen = read(filefd, buf, UMIN(len, 8192));
|
||||
if (rlen <= 0) {
|
||||
uwsgi_error("uwsgi_sendfile_do()/read()");
|
||||
return -1;
|
||||
|
||||
if (wsgi_req->sendfile_fd_size) {
|
||||
|
||||
if (!wsgi_req->sendfile_fd_chunk)
|
||||
wsgi_req->sendfile_fd_chunk = 4096;
|
||||
|
||||
if (wsgi_req->socket->proto_sendfile) {
|
||||
sst = wsgi_req->socket->proto_sendfile(wsgi_req);
|
||||
}
|
||||
else {
|
||||
sst = uwsgi_do_sendfile(sockfd, wsgi_req->sendfile_fd, wsgi_req->sendfile_fd_size, wsgi_req->sendfile_fd_chunk, &wsgi_req->sendfile_fd_pos, uwsgi.async);
|
||||
}
|
||||
|
||||
}
|
||||
return write(sockfd, buf, rlen);
|
||||
|
||||
end:
|
||||
return sst;
|
||||
}
|
||||
|
||||
ssize_t uwsgi_do_sendfile(int sockfd, int filefd, size_t filesize, size_t chunk, off_t * pos, int async) {
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
|
||||
int sf_ret;
|
||||
|
||||
off_t sf_len = filesize;
|
||||
|
||||
if (async > 1) {
|
||||
sf_len = chunk;
|
||||
sf_ret = sendfile(filefd, sockfd, *pos, 0, NULL, &sf_len, 0);
|
||||
*pos += sf_len;
|
||||
}
|
||||
else {
|
||||
sf_ret = sendfile(filefd, sockfd, 0, 0, NULL, &sf_len, 0);
|
||||
}
|
||||
|
||||
if (sf_ret < 0) {
|
||||
if (errno != EAGAIN) {
|
||||
uwsgi_error("sendfile()");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return sf_len;
|
||||
#elif defined(__APPLE__)
|
||||
int sf_ret;
|
||||
off_t sf_len = filesize;
|
||||
|
||||
if (async > 1) {
|
||||
sf_len = chunk;
|
||||
sf_ret = sendfile(filefd, sockfd, *pos, &sf_len, NULL, 0);
|
||||
*pos += sf_len;
|
||||
}
|
||||
else {
|
||||
sf_ret = sendfile(filefd, sockfd, 0, &sf_len, NULL, 0);
|
||||
}
|
||||
|
||||
if (sf_ret) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("sf_len = %d\n", sf_len);
|
||||
#endif
|
||||
uwsgi_error("sendfile()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return sf_len;
|
||||
|
||||
#elif defined(__linux__) || defined(__sun__)
|
||||
int sf_ret;
|
||||
size_t written = 0;
|
||||
|
||||
if (async > 1) {
|
||||
sf_ret = sendfile(sockfd, filefd, pos, chunk);
|
||||
if (sf_ret < 0) {
|
||||
uwsgi_error("sendfile()");
|
||||
return 0;
|
||||
}
|
||||
return sf_ret;
|
||||
}
|
||||
|
||||
while (written < filesize) {
|
||||
sf_ret = sendfile(sockfd, filefd, pos, filesize - written);
|
||||
if (sf_ret < 0) {
|
||||
uwsgi_error("sendfile()");
|
||||
return 0;
|
||||
}
|
||||
else if (sf_ret == 0) {
|
||||
return 0;
|
||||
}
|
||||
written += sf_ret;
|
||||
}
|
||||
return written;
|
||||
|
||||
#else
|
||||
static size_t nosf_buf_size = 0;
|
||||
static char *nosf_buf;
|
||||
char *nosf_buf2;
|
||||
|
||||
ssize_t jlen = 0;
|
||||
ssize_t rlen = 0;
|
||||
ssize_t i = 0;
|
||||
|
||||
if (!nosf_buf) {
|
||||
nosf_buf = malloc(chunk);
|
||||
}
|
||||
else if (chunk != nosf_buf_size) {
|
||||
nosf_buf2 = realloc(nosf_buf, chunk);
|
||||
if (!nosf_buf2) {
|
||||
free(nosf_buf);
|
||||
}
|
||||
nosf_buf = nosf_buf2;
|
||||
}
|
||||
|
||||
if (!nosf_buf) {
|
||||
uwsgi_error("sendfile malloc()/realloc()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
nosf_buf_size = chunk;
|
||||
|
||||
if (async > 1) {
|
||||
jlen = read(filefd, nosf_buf, chunk);
|
||||
if (jlen <= 0) {
|
||||
uwsgi_error("read()");
|
||||
return 0;
|
||||
}
|
||||
jlen = write(sockfd, nosf_buf, jlen);
|
||||
if (jlen <= 0) {
|
||||
uwsgi_error("write()");
|
||||
return 0;
|
||||
}
|
||||
return jlen;
|
||||
}
|
||||
|
||||
while (i < (int) filesize) {
|
||||
jlen = read(filefd, nosf_buf, chunk);
|
||||
if (jlen <= 0) {
|
||||
uwsgi_error("read()");
|
||||
break;
|
||||
}
|
||||
i += jlen;
|
||||
jlen = write(sockfd, nosf_buf, jlen);
|
||||
if (jlen <= 0) {
|
||||
uwsgi_error("write()");
|
||||
break;
|
||||
}
|
||||
rlen += jlen;
|
||||
}
|
||||
|
||||
return rlen;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
+9
-2
@@ -106,11 +106,13 @@ void uwsgi_setup_inherited_sockets() {
|
||||
//now close all the unbound fd
|
||||
for (j = 3; j < (int) uwsgi.max_fd; j++) {
|
||||
int useless = 1;
|
||||
#ifdef UWSGI_MULTICAST
|
||||
if (j == uwsgi.cluster_fd)
|
||||
continue;
|
||||
#endif
|
||||
if (uwsgi.has_emperor) {
|
||||
if (j == uwsgi.emperor_fd)
|
||||
continue;
|
||||
if (j == uwsgi.emperor_fd_config)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (uwsgi.shared->worker_log_pipe[0] > -1) {
|
||||
@@ -128,6 +130,11 @@ void uwsgi_setup_inherited_sockets() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (uwsgi.cache_server && uwsgi.cache_server_fd != -1) {
|
||||
if (j == uwsgi.cache_server_fd)
|
||||
continue;
|
||||
}
|
||||
|
||||
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
|
||||
int found = 0;
|
||||
while (ugs) {
|
||||
|
||||
+12
-27
@@ -6,9 +6,7 @@ int uwsgi_signal_handler(uint8_t sig) {
|
||||
|
||||
struct uwsgi_signal_entry *use = NULL;
|
||||
|
||||
int pos = (uwsgi.mywid * 256) + sig;
|
||||
|
||||
use = &uwsgi.shared->signal_table[pos];
|
||||
use = &uwsgi.shared->signal_table[sig];
|
||||
|
||||
if (!use->handler)
|
||||
return -1;
|
||||
@@ -57,11 +55,13 @@ int uwsgi_signal_handler(uint8_t sig) {
|
||||
set_mule_harakiri(uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI]);
|
||||
}
|
||||
}
|
||||
#ifdef UWSGI_SPOOLER
|
||||
else if (uwsgi.i_am_a_spooler && (getpid() == uwsgi.i_am_a_spooler->pid)) {
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
|
||||
set_spooler_harakiri(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int ret = uwsgi.p[use->modifier1]->signal_handler(sig, use->handler);
|
||||
|
||||
@@ -77,19 +77,20 @@ int uwsgi_signal_handler(uint8_t sig) {
|
||||
set_mule_harakiri(0);
|
||||
}
|
||||
}
|
||||
#ifdef UWSGI_SPOOLER
|
||||
else if (uwsgi.i_am_a_spooler && (getpid() == uwsgi.i_am_a_spooler->pid)) {
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
|
||||
set_spooler_harakiri(0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int uwsgi_signal_registered(uint8_t sig) {
|
||||
|
||||
int pos = (uwsgi.mywid * 256) + sig;
|
||||
if (uwsgi.shared->signal_table[pos].handler != NULL)
|
||||
if (uwsgi.shared->signal_table[sig].handler != NULL)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
@@ -99,23 +100,15 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
|
||||
|
||||
struct uwsgi_signal_entry *use = NULL;
|
||||
|
||||
if (!uwsgi.master_process) return -1;
|
||||
|
||||
if (uwsgi.mywid == 0 && uwsgi.workers[0].pid != uwsgi.mypid) {
|
||||
uwsgi_log("only the master and the workers can register signal handlers\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strlen(receiver) > 63)
|
||||
return -1;
|
||||
|
||||
uwsgi_lock(uwsgi.signal_table_lock);
|
||||
|
||||
int pos = (uwsgi.mywid * 256) + sig;
|
||||
use = &uwsgi.shared->signal_table[pos];
|
||||
use = &uwsgi.shared->signal_table[sig];
|
||||
|
||||
if (use->handler && uwsgi.mywid == 0) {
|
||||
uwsgi_log("[uwsgi-signal] you cannot re-register a signal as the master !!!\n");
|
||||
if (use->handler) {
|
||||
uwsgi_log("[uwsgi-signal] you cannot re-register a signal !!!\n");
|
||||
uwsgi_unlock(uwsgi.signal_table_lock);
|
||||
return -1;
|
||||
}
|
||||
@@ -132,15 +125,6 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
|
||||
uwsgi_log("[uwsgi-signal] signum %d registered (wid: %d modifier1: %d target: %s)\n", sig, uwsgi.mywid, modifier1, receiver);
|
||||
}
|
||||
|
||||
// check for cow
|
||||
if (uwsgi.mywid == 0) {
|
||||
int i;
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
int pos = (i * 256);
|
||||
memcpy(&uwsgi.shared->signal_table[pos], use, sizeof(struct uwsgi_signal_entry) * 256);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_unlock(uwsgi.signal_table_lock);
|
||||
|
||||
return 0;
|
||||
@@ -442,8 +426,7 @@ int uwsgi_signal_send(int fd, uint8_t sig) {
|
||||
|
||||
void uwsgi_route_signal(uint8_t sig) {
|
||||
|
||||
int pos = (uwsgi.mywid * 256) + sig;
|
||||
struct uwsgi_signal_entry *use = &ushared->signal_table[pos];
|
||||
struct uwsgi_signal_entry *use = &ushared->signal_table[sig];
|
||||
int i;
|
||||
|
||||
// send to first available worker
|
||||
@@ -474,6 +457,7 @@ void uwsgi_route_signal(uint8_t sig) {
|
||||
else if (!strcmp(use->receiver, "subscribed")) {
|
||||
}
|
||||
// route to spooler
|
||||
#ifdef UWSGI_SPOOLER
|
||||
else if (!strcmp(use->receiver, "spooler")) {
|
||||
if (ushared->worker_signal_pipe[0] != -1) {
|
||||
if (uwsgi_signal_send(ushared->spooler_signal_pipe[0], sig)) {
|
||||
@@ -481,6 +465,7 @@ void uwsgi_route_signal(uint8_t sig) {
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else if (!strcmp(use->receiver, "mules")) {
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi_signal_send(uwsgi.mules[i].signal_pipe[0], sig)) {
|
||||
|
||||
+6
-15
@@ -1,4 +1,6 @@
|
||||
#include <uwsgi.h>
|
||||
#ifdef UWSGI_SNMP
|
||||
|
||||
#include "uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
@@ -406,17 +408,6 @@ int uwsgi_setup_snmp(void) {
|
||||
|
||||
return snmp_fd;
|
||||
}
|
||||
|
||||
void uwsgi_master_manage_snmp(int snmp_fd) {
|
||||
struct sockaddr_in udp_client;
|
||||
socklen_t udp_len = sizeof(udp_client);
|
||||
ssize_t rlen = recvfrom(snmp_fd, uwsgi.wsgi_req->buffer, uwsgi.buffer_size, 0, (struct sockaddr *) &udp_client, &udp_len);
|
||||
|
||||
if (rlen < 0) {
|
||||
uwsgi_error("recvfrom()");
|
||||
}
|
||||
else if (rlen > 0) {
|
||||
manage_snmp(snmp_fd, (uint8_t *) uwsgi.wsgi_req->buffer, rlen, &udp_client);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
#warning "*** SNMP support is disabled ***"
|
||||
#endif
|
||||
|
||||
+133
-152
@@ -2,23 +2,6 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
static int uwsgi_socket_strcmp(char *sock1, char *sock2) {
|
||||
size_t sock1_len = strlen(sock1);
|
||||
size_t sock2_len = strlen(sock2);
|
||||
|
||||
if (!uwsgi_starts_with(sock1, sock1_len, "0.0.0.0:", 8)) {
|
||||
sock1 += 7;
|
||||
sock1_len = strlen(sock1);
|
||||
}
|
||||
|
||||
if (!uwsgi_starts_with(sock2, sock2_len, "0.0.0.0:", 8)) {
|
||||
sock2 += 7;
|
||||
sock2_len = strlen(sock2);
|
||||
}
|
||||
|
||||
return uwsgi_strncmp(sock1, sock1_len, sock2, sock2_len);
|
||||
}
|
||||
|
||||
char *uwsgi_getsockname(int fd) {
|
||||
|
||||
socklen_t socket_type_len = sizeof(struct sockaddr_un);
|
||||
@@ -185,6 +168,7 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
return serverfd;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_UDP
|
||||
int bind_to_udp(char *socket_name, int multicast, int broadcast) {
|
||||
int serverfd;
|
||||
struct sockaddr_in uws_addr;
|
||||
@@ -192,7 +176,10 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
|
||||
int bcast = 1;
|
||||
int reuse = 1;
|
||||
|
||||
#ifdef UWSGI_MULTICAST
|
||||
struct ip_mreq mc;
|
||||
uint8_t loop = 1;
|
||||
#endif
|
||||
|
||||
udp_port = strchr(socket_name, ':');
|
||||
if (udp_port == NULL) {
|
||||
@@ -209,6 +196,7 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
|
||||
uws_addr.sin_family = AF_INET;
|
||||
uws_addr.sin_port = htons(atoi(udp_port + 1));
|
||||
|
||||
#ifdef UWSGI_MULTICAST
|
||||
if (!broadcast && !multicast) {
|
||||
char quad[4];
|
||||
char *first_part = strchr(socket_name, '.');
|
||||
@@ -219,6 +207,9 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
|
||||
multicast = 1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (!broadcast) {
|
||||
#endif
|
||||
if (!strcmp(socket_name, "255.255.255.255")) {
|
||||
broadcast = 1;
|
||||
}
|
||||
@@ -245,12 +236,14 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
|
||||
uwsgi_error("setsockopt()");
|
||||
}
|
||||
|
||||
#ifdef UWSGI_MULTICAST
|
||||
if (multicast) {
|
||||
// if multicast is enabled remember to bind to INADDR_ANY
|
||||
uws_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
mc.imr_multiaddr.s_addr = inet_addr(socket_name);
|
||||
mc.imr_interface.s_addr = INADDR_ANY;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (broadcast) {
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_BROADCAST, &bcast, sizeof(bcast))) {
|
||||
@@ -266,9 +259,10 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_MULTICAST
|
||||
if (multicast) {
|
||||
uwsgi_log("[uwsgi-mcast] joining multicast group: %s:%d\n", socket_name, ntohs(uws_addr.sin_port));
|
||||
if (setsockopt(serverfd, IPPROTO_IP, IP_MULTICAST_LOOP, &uwsgi.multicast_loop, sizeof(uwsgi.multicast_loop))) {
|
||||
uwsgi_log("[uWSGI] joining multicast group: %s:%d\n", socket_name, ntohs(uws_addr.sin_port));
|
||||
if (setsockopt(serverfd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop))) {
|
||||
uwsgi_error("setsockopt()");
|
||||
}
|
||||
|
||||
@@ -281,11 +275,13 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
udp_port[0] = ':';
|
||||
return serverfd;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
int uwsgi_connectn(char *socket_name, uint16_t len, int timeout, int async) {
|
||||
|
||||
@@ -478,7 +474,7 @@ char *generate_socket_name(char *socket_name) {
|
||||
|
||||
}
|
||||
|
||||
uwsgi_log("unable to find a valid socket address\n");
|
||||
uwsgi_log("unable to find avalid socket address\n");
|
||||
#endif
|
||||
uwsgi_nuclear_blast();
|
||||
}
|
||||
@@ -551,30 +547,12 @@ socklen_t socket_to_in_addr(char *socket_name, char *port, int portn, struct soc
|
||||
int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
|
||||
int serverfd;
|
||||
#ifdef AF_INET6
|
||||
struct sockaddr_in6 uws_addr;
|
||||
#else
|
||||
struct sockaddr_in uws_addr;
|
||||
#endif
|
||||
int reuse = 1;
|
||||
int family = AF_INET;
|
||||
socklen_t addr_len = sizeof(struct sockaddr_in);
|
||||
|
||||
#ifdef AF_INET6
|
||||
if (socket_name[0] == '[' && tcp_port[-1] == ']') {
|
||||
family = AF_INET6;
|
||||
socket_to_in_addr6(socket_name, tcp_port, 0, &uws_addr);
|
||||
addr_len = sizeof(struct sockaddr_in6);
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
socket_to_in_addr(socket_name, tcp_port, 0, (struct sockaddr_in *) &uws_addr);
|
||||
#ifdef AF_INET6
|
||||
}
|
||||
#endif
|
||||
socket_to_in_addr(socket_name, tcp_port, 0, &uws_addr);
|
||||
|
||||
|
||||
serverfd = socket(family, SOCK_STREAM, 0);
|
||||
serverfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (serverfd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
uwsgi_nuclear_blast();
|
||||
@@ -608,19 +586,6 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
#endif
|
||||
}
|
||||
|
||||
if (uwsgi.tcp_fast_open) {
|
||||
#ifdef TCP_FASTOPEN
|
||||
if (setsockopt(serverfd, SOL_TCP, TCP_FASTOPEN, (const void *) &uwsgi.tcp_fast_open, sizeof(int)) < 0) {
|
||||
uwsgi_error("TCP_FASTOPEN setsockopt()");
|
||||
}
|
||||
else {
|
||||
uwsgi_log("TCP_FASTOPEN enabled on %s\n", socket_name);
|
||||
}
|
||||
#else
|
||||
uwsgi_log("!!! your system does not support TCP_FASTOPEN !!!\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (uwsgi.so_send_timeout) {
|
||||
struct timeval tv;
|
||||
tv.tv_sec = uwsgi.so_send_timeout;
|
||||
@@ -656,7 +621,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
}
|
||||
|
||||
|
||||
if (bind(serverfd, (struct sockaddr *) &uws_addr, addr_len) != 0) {
|
||||
if (bind(serverfd, (struct sockaddr *) &uws_addr, sizeof(uws_addr)) != 0) {
|
||||
if (errno == EADDRINUSE) {
|
||||
uwsgi_log("probably another instance of uWSGI is running on the same address (%s).\n", socket_name);
|
||||
}
|
||||
@@ -667,7 +632,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
#ifdef __linux__
|
||||
long somaxconn = uwsgi_num_from_file("/proc/sys/net/core/somaxconn", 1);
|
||||
if (somaxconn > 0 && uwsgi.listen_queue > somaxconn) {
|
||||
uwsgi_log("Listen queue size is greater than the system max net.core.somaxconn (%li).\n", somaxconn);
|
||||
uwsgi_log("Listen queue size is greater than the system max net.core.somaxconn (%i).\n", somaxconn);
|
||||
uwsgi_nuclear_blast();
|
||||
}
|
||||
#endif
|
||||
@@ -742,16 +707,7 @@ int timed_connect(struct pollfd *fdpoll, const struct sockaddr *addr, int addr_s
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MSG_FASTOPEN
|
||||
if (addr->sa_family == AF_INET && uwsgi.tcp_fast_open_client) {
|
||||
ret = sendto(fdpoll->fd, "", 0, MSG_FASTOPEN, addr, addr_size);
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
ret = connect(fdpoll->fd, addr, addr_size);
|
||||
#ifdef MSG_FASTOPEN
|
||||
}
|
||||
#endif
|
||||
ret = connect(fdpoll->fd, addr, addr_size);
|
||||
|
||||
if (async) {
|
||||
if (ret < 0 && errno != EINPROGRESS) {
|
||||
@@ -967,7 +923,6 @@ struct uwsgi_socket *uwsgi_new_socket(char *name) {
|
||||
char *auto_port = uwsgi_num2str(ntohs(sin.sin_port));
|
||||
char *auto_ip = inet_ntoa(sin.sin_addr);
|
||||
uwsgi_sock->name = uwsgi_concat3n(auto_ip, strlen(auto_ip), ":", 1, auto_port, strlen(auto_port));
|
||||
free(auto_port);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1087,7 +1042,7 @@ void uwsgi_add_socket_from_fd(struct uwsgi_socket *uwsgi_sock, int fd) {
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef AF_INET6
|
||||
#ifdef UWSGI_IPV6
|
||||
else if (gsa.sa->sa_family == AF_INET6) {
|
||||
char *computed_addr;
|
||||
char computed_port[6];
|
||||
@@ -1403,7 +1358,87 @@ nextsock:
|
||||
}
|
||||
|
||||
|
||||
#ifdef AF_INET6
|
||||
#ifdef UWSGI_IPV6
|
||||
int bind_to_tcp6(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
|
||||
int serverfd;
|
||||
struct sockaddr_in6 uws_addr;
|
||||
int reuse = 1;
|
||||
|
||||
socket_to_in_addr6(socket_name, tcp_port, 0, &uws_addr);
|
||||
|
||||
serverfd = socket(AF_INET6, SOCK_STREAM, 0);
|
||||
if (serverfd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
uwsgi_nuclear_blast();
|
||||
}
|
||||
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) {
|
||||
uwsgi_error("setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
#ifdef IP_FREEBIND
|
||||
if (uwsgi.freebind) {
|
||||
if (setsockopt(serverfd, SOL_IP, IP_FREEBIND, (const void *) &uwsgi.freebind, sizeof(int)) < 0) {
|
||||
uwsgi_error("setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (uwsgi.reuse_port) {
|
||||
#ifdef SO_REUSEPORT
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEPORT, (const void *) &uwsgi.reuse_port, sizeof(int)) < 0) {
|
||||
uwsgi_error("setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
}
|
||||
#else
|
||||
uwsgi_log("!!! your system does not support SO_REUSEPORT !!!\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!uwsgi.no_defer_accept) {
|
||||
|
||||
#ifdef __linux__
|
||||
if (setsockopt(serverfd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], sizeof(int))) {
|
||||
uwsgi_error("setsockopt()");
|
||||
}
|
||||
// OSX has no SO_ACCEPTFILTER !!!
|
||||
#elif defined(__freebsd__)
|
||||
struct accept_filter_arg afa;
|
||||
strcpy(afa.af_name, "dataready");
|
||||
afa.af_arg[0] = 0;
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(struct accept_filter_arg))) {
|
||||
uwsgi_error("setsockopt()");
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (bind(serverfd, (struct sockaddr *) &uws_addr, sizeof(uws_addr)) != 0) {
|
||||
if (errno == EADDRINUSE) {
|
||||
uwsgi_log("probably another instance of uWSGI is running on the same address.\n");
|
||||
}
|
||||
uwsgi_error("bind()");
|
||||
uwsgi_nuclear_blast();
|
||||
}
|
||||
|
||||
if (listen(serverfd, listen_queue) != 0) {
|
||||
uwsgi_error("listen()");
|
||||
uwsgi_nuclear_blast();
|
||||
}
|
||||
|
||||
|
||||
if (tcp_port)
|
||||
tcp_port[0] = ':';
|
||||
|
||||
return serverfd;
|
||||
}
|
||||
|
||||
socklen_t socket_to_in_addr6(char *socket_name, char *port, int portn, struct sockaddr_in6 * sin_addr) {
|
||||
|
||||
memset(sin_addr, 0, sizeof(struct sockaddr_in6));
|
||||
@@ -1459,9 +1494,9 @@ void uwsgi_setup_shared_sockets() {
|
||||
uwsgi_log("uwsgi shared socket %d bound to UNIX address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), shared_sock->name, shared_sock->fd);
|
||||
}
|
||||
else {
|
||||
#ifdef AF_INET6
|
||||
#ifdef UWSGI_IPV6
|
||||
if (shared_sock->name[0] == '[' && tcp_port[-1] == ']') {
|
||||
shared_sock->fd = bind_to_tcp(shared_sock->name, uwsgi.listen_queue, tcp_port);
|
||||
shared_sock->fd = bind_to_tcp6(shared_sock->name, uwsgi.listen_queue, tcp_port);
|
||||
shared_sock->family = AF_INET6;
|
||||
// fix socket name
|
||||
shared_sock->name = uwsgi_getsockname(shared_sock->fd);
|
||||
@@ -1474,7 +1509,7 @@ void uwsgi_setup_shared_sockets() {
|
||||
// fix socket name
|
||||
shared_sock->name = uwsgi_getsockname(shared_sock->fd);
|
||||
uwsgi_log("uwsgi shared socket %d bound to TCP address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), shared_sock->name, shared_sock->fd);
|
||||
#ifdef AF_INET6
|
||||
#ifdef UWSGI_IPV6
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1493,7 +1528,7 @@ void uwsgi_setup_shared_sockets() {
|
||||
for (i = 3; i < (int) uwsgi.max_fd; i++) {
|
||||
char *sock = uwsgi_getsockname(i);
|
||||
if (sock) {
|
||||
if (!uwsgi_socket_strcmp(sock, shared_sock->name)) {
|
||||
if (!strcmp(sock, shared_sock->name)) {
|
||||
if (strchr(sock, ':')) {
|
||||
uwsgi_log("uwsgi shared socket %d inherited TCP address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), sock, i);
|
||||
shared_sock->family = AF_INET;
|
||||
@@ -1504,7 +1539,9 @@ void uwsgi_setup_shared_sockets() {
|
||||
}
|
||||
shared_sock->fd = i;
|
||||
}
|
||||
free(sock);
|
||||
else {
|
||||
free(sock);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1618,9 +1655,9 @@ void uwsgi_bind_sockets() {
|
||||
uwsgi_log("uwsgi socket %d bound to UNIX address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
|
||||
}
|
||||
else {
|
||||
#ifdef AF_INET6
|
||||
#ifdef UWSGI_IPV6
|
||||
if (uwsgi_sock->name[0] == '[' && tcp_port[-1] == ']') {
|
||||
uwsgi_sock->fd = bind_to_tcp(uwsgi_sock->name, uwsgi.listen_queue, tcp_port);
|
||||
uwsgi_sock->fd = bind_to_tcp6(uwsgi_sock->name, uwsgi.listen_queue, tcp_port);
|
||||
uwsgi_log("uwsgi socket %d bound to TCP6 address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
|
||||
uwsgi_sock->family = AF_INET6;
|
||||
}
|
||||
@@ -1629,7 +1666,7 @@ void uwsgi_bind_sockets() {
|
||||
uwsgi_sock->fd = bind_to_tcp(uwsgi_sock->name, uwsgi.listen_queue, tcp_port);
|
||||
uwsgi_log("uwsgi socket %d bound to TCP address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
|
||||
uwsgi_sock->family = AF_INET;
|
||||
#ifdef AF_INET6
|
||||
#ifdef UWSGI_IPV6
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1705,14 +1742,14 @@ void uwsgi_bind_sockets() {
|
||||
uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
if (uwsgi_sock->auto_port) {
|
||||
#ifdef AF_INET6
|
||||
#ifdef UWSGI_IPV6
|
||||
if (uwsgi_sock->family == AF_INET6) {
|
||||
uwsgi_log("uwsgi socket %d bound to TCP6 address %s (port auto-assigned) fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
uwsgi_log("uwsgi socket %d bound to TCP address %s (port auto-assigned) fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
|
||||
#ifdef AF_INET6
|
||||
#ifdef UWSGI_IPV6
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1723,7 +1760,6 @@ void uwsgi_bind_sockets() {
|
||||
}
|
||||
|
||||
void uwsgi_set_sockets_protocols() {
|
||||
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
char *requested_protocol = uwsgi_sock->proto_name;
|
||||
@@ -1745,7 +1781,6 @@ void uwsgi_set_sockets_protocols() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
setup_proto:
|
||||
if (!requested_protocol) {
|
||||
requested_protocol = uwsgi.protocol;
|
||||
@@ -1754,70 +1789,28 @@ setup_proto:
|
||||
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_write = uwsgi_proto_uwsgi_write;
|
||||
uwsgi_sock->proto_writev = uwsgi_proto_uwsgi_writev;
|
||||
uwsgi_sock->proto_write_header = uwsgi_proto_uwsgi_write_header;
|
||||
uwsgi_sock->proto_writev_header = uwsgi_proto_uwsgi_writev_header;
|
||||
uwsgi_sock->proto_sendfile = NULL;
|
||||
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))) {
|
||||
if (uwsgi.protocol && (!strcmp(uwsgi.protocol, "fastcgi") || !strcmp(uwsgi.protocol, "fcgi"))) {
|
||||
uwsgi.shared->options[UWSGI_OPTION_CGI_MODE] = 1;
|
||||
}
|
||||
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_write = uwsgi_proto_fastcgi_write;
|
||||
uwsgi_sock->proto_writev = uwsgi_proto_fastcgi_writev;
|
||||
uwsgi_sock->proto_write_header = uwsgi_proto_fastcgi_write_header;
|
||||
uwsgi_sock->proto_writev_header = uwsgi_proto_fastcgi_writev_header;
|
||||
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) || !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) || !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;
|
||||
@@ -1826,13 +1819,11 @@ setup_proto:
|
||||
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_write = uwsgi_proto_uwsgi_write;
|
||||
uwsgi_sock->proto_writev = uwsgi_proto_uwsgi_writev;
|
||||
uwsgi_sock->proto_write_header = uwsgi_proto_uwsgi_write_header;
|
||||
uwsgi_sock->proto_writev_header = uwsgi_proto_uwsgi_writev_header;
|
||||
uwsgi_sock->proto_sendfile = NULL;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_base_close;
|
||||
if (uwsgi.offload_threads > 0)
|
||||
uwsgi_sock->can_offload = 1;
|
||||
@@ -1843,13 +1834,3 @@ nextsock:
|
||||
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_tcp_nodelay(int fd) {
|
||||
#ifdef TCP_NODELAY
|
||||
int flag = 1;
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(int))) {
|
||||
uwsgi_error("uwsgi_tcp_nodelay()/setsockopt()");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
+7
-2
@@ -1,3 +1,4 @@
|
||||
#ifdef UWSGI_SPOOLER
|
||||
#include "uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
@@ -254,7 +255,7 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
|
||||
close(fd);
|
||||
|
||||
if (!uwsgi.spooler_quiet)
|
||||
uwsgi_log("[spooler] written %lu bytes to file %s\n", (unsigned long) size + body_len + 4, filename);
|
||||
uwsgi_log("[spooler] written %d bytes to file %s\n", size + body_len + 4, filename);
|
||||
|
||||
// and here waiting threads can continue
|
||||
uwsgi_unlock(uspool->lock);
|
||||
@@ -547,7 +548,7 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
|
||||
uspool->tasks++;
|
||||
if (ret == -2) {
|
||||
if (!uwsgi.spooler_quiet)
|
||||
uwsgi_log("[spooler %s pid: %d] done with task %s after %lld seconds\n", uspool->dir, (int) uwsgi.mypid, task, (long long) uwsgi_now() - now);
|
||||
uwsgi_log("[spooler %s pid: %d] done with task %s after %d seconds\n", uspool->dir, (int) uwsgi.mypid, task, uwsgi_now() - now);
|
||||
destroy_spool(dir, task);
|
||||
}
|
||||
// re-spool it
|
||||
@@ -583,3 +584,7 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
#warning "*** Spooler support is disabled ***"
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ extern struct uwsgi_server uwsgi;
|
||||
static int uwsgi_sqlite3_config_callback(void *magic_table, int field_count, char **fields, char **col) {
|
||||
// make a copy of the string
|
||||
if (field_count >= 2) {
|
||||
size_t value_len = strlen(fields[1]) + 1;
|
||||
int value_len = strlen(fields[1]) + 1;
|
||||
char *value = magic_sub(fields[1], value_len, &value_len, (char **) magic_table);
|
||||
add_exported_option(uwsgi_strncopy(fields[0], strlen(fields[0])), value, 0);
|
||||
}
|
||||
|
||||
-499
@@ -1,499 +0,0 @@
|
||||
#include "../uwsgi.h"
|
||||
#include <openssl/rand.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
/*
|
||||
|
||||
ssl additional datas are retrieved via indexes.
|
||||
|
||||
You can create an index with SSL_CTX_get_ex_new_index and
|
||||
set data in it with SSL_CTX_set_ex_data
|
||||
|
||||
*/
|
||||
|
||||
void uwsgi_ssl_init(void) {
|
||||
OPENSSL_config(NULL);
|
||||
SSL_library_init();
|
||||
SSL_load_error_strings();
|
||||
OpenSSL_add_all_algorithms();
|
||||
uwsgi.ssl_initialized = 1;
|
||||
}
|
||||
|
||||
void uwsgi_ssl_info_cb(SSL const *ssl, int where, int ret) {
|
||||
if (where & SSL_CB_HANDSHAKE_DONE) {
|
||||
if (ssl->s3) {
|
||||
ssl->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int uwsgi_ssl_verify_callback(int ok, X509_STORE_CTX * x509_store) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int uwsgi_ssl_session_new_cb(SSL *ssl, SSL_SESSION *sess) {
|
||||
char session_blob[4096];
|
||||
int len = i2d_SSL_SESSION(sess, NULL);
|
||||
if (len > 4096) {
|
||||
if (uwsgi.ssl_verbose) {
|
||||
uwsgi_log("[uwsgi-ssl] unable to store session of size %d\n", len);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char *p = (unsigned char *) session_blob;
|
||||
i2d_SSL_SESSION(sess, &p);
|
||||
|
||||
// ok let's write the value to the cache
|
||||
uwsgi_wlock(uwsgi.ssl_sessions_cache->lock);
|
||||
if (uwsgi_cache_set2(uwsgi.ssl_sessions_cache, (char *) sess->session_id, sess->session_id_length, session_blob, len, uwsgi.ssl_sessions_timeout, 0)) {
|
||||
if (uwsgi.ssl_verbose) {
|
||||
uwsgi_log("[uwsgi-ssl] unable to store session of size %d in the cache\n", len);
|
||||
}
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.ssl_sessions_cache->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SSL_SESSION *uwsgi_ssl_session_get_cb(SSL *ssl, unsigned char *key, int keylen, int *copy) {
|
||||
|
||||
uint64_t valsize = 0;
|
||||
|
||||
*copy = 0;
|
||||
uwsgi_rlock(uwsgi.ssl_sessions_cache->lock);
|
||||
char *value = uwsgi_cache_get2(uwsgi.ssl_sessions_cache, (char *)key, keylen, &valsize);
|
||||
if (!value) {
|
||||
uwsgi_rwunlock(uwsgi.ssl_sessions_cache->lock);
|
||||
if (uwsgi.ssl_verbose) {
|
||||
uwsgi_log("[uwsgi-ssl] cache miss\n");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
SSL_SESSION *sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&value, valsize);
|
||||
uwsgi_rwunlock(uwsgi.ssl_sessions_cache->lock);
|
||||
return sess;
|
||||
}
|
||||
|
||||
void uwsgi_ssl_session_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess) {
|
||||
uwsgi_wlock(uwsgi.ssl_sessions_cache->lock);
|
||||
if (uwsgi_cache_del2(uwsgi.ssl_sessions_cache, (char *) sess->session_id, sess->session_id_length, 0, 0)) {
|
||||
if (uwsgi.ssl_verbose) {
|
||||
uwsgi_log("[uwsgi-ssl] error removing cache item\n");
|
||||
}
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.ssl_sessions_cache->lock);
|
||||
}
|
||||
|
||||
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
||||
static int uwsgi_sni_cb(SSL *ssl, int *ad, void *arg) {
|
||||
const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
|
||||
if (!servername) return SSL_TLSEXT_ERR_NOACK;
|
||||
size_t servername_len = strlen(servername);
|
||||
|
||||
struct uwsgi_string_list *usl = uwsgi.sni;
|
||||
while(usl) {
|
||||
if (!uwsgi_strncmp(usl->value, usl->len, (char *)servername, servername_len)) {
|
||||
SSL_set_SSL_CTX(ssl, usl->custom_ptr);
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
struct uwsgi_regexp_list *url = uwsgi.sni_regexp;
|
||||
while(url) {
|
||||
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, (char *)servername, servername_len) >= 0) {
|
||||
SSL_set_SSL_CTX(ssl, url->custom_ptr);
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
url = url->next;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (uwsgi.sni_dir) {
|
||||
size_t sni_dir_len = strlen(uwsgi.sni_dir);
|
||||
char *sni_dir_cert = uwsgi_concat4n(uwsgi.sni_dir, sni_dir_len, "/", 1, (char *) servername, servername_len, ".crt", 4);
|
||||
char *sni_dir_key = uwsgi_concat4n(uwsgi.sni_dir, sni_dir_len, "/", 1, (char *) servername, servername_len, ".key", 4);
|
||||
char *sni_dir_client_ca = uwsgi_concat4n(uwsgi.sni_dir, sni_dir_len, "/", 1, (char *) servername, servername_len, ".ca", 3);
|
||||
if (uwsgi_file_exists(sni_dir_cert) && uwsgi_file_exists(sni_dir_key)) {
|
||||
char *client_ca = NULL;
|
||||
if (uwsgi_file_exists(sni_dir_client_ca)) {
|
||||
client_ca = sni_dir_client_ca;
|
||||
}
|
||||
usl = uwsgi_ssl_add_sni_item(uwsgi_str((char *)servername), sni_dir_cert, sni_dir_key, uwsgi.sni_dir_ciphers, client_ca);
|
||||
if (!usl) goto done;
|
||||
free(sni_dir_cert);
|
||||
free(sni_dir_key);
|
||||
free(sni_dir_client_ca);
|
||||
SSL_set_SSL_CTX(ssl, usl->custom_ptr);
|
||||
uwsgi_log("[uwsgi-sni for pid %d] added context for %s\n", (int) getpid(), servername);
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
done:
|
||||
free(sni_dir_cert);
|
||||
free(sni_dir_key);
|
||||
free(sni_dir_client_ca);
|
||||
}
|
||||
|
||||
return SSL_TLSEXT_ERR_NOACK;
|
||||
}
|
||||
#endif
|
||||
|
||||
SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ciphers, char *client_ca) {
|
||||
|
||||
SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method());
|
||||
if (!ctx) {
|
||||
uwsgi_log("[uwsgi-ssl] unable to initialize context \"%s\"\n", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// this part is taken from nginx and stud, removing unneeded functionality
|
||||
// stud (for me) has made the best choice on choosing DH approach
|
||||
|
||||
long ssloptions = SSL_OP_NO_SSLv2 | SSL_OP_ALL | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
|
||||
// disable compression (if possibile)
|
||||
#ifdef SSL_OP_NO_COMPRESSION
|
||||
ssloptions |= SSL_OP_NO_COMPRESSION;
|
||||
#endif
|
||||
|
||||
// release/reuse buffers as soon as possibile
|
||||
#ifdef SSL_MODE_RELEASE_BUFFERS
|
||||
SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
|
||||
#endif
|
||||
|
||||
if (SSL_CTX_use_certificate_chain_file(ctx, crt) <= 0) {
|
||||
uwsgi_log("[uwsgi-ssl] unable to assign certificate %s for context \"%s\"\n", crt, name);
|
||||
SSL_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// this part is based from stud
|
||||
BIO *bio = BIO_new_file(crt, "r");
|
||||
if (bio) {
|
||||
DH *dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
|
||||
BIO_free(bio);
|
||||
if (dh) {
|
||||
SSL_CTX_set_tmp_dh(ctx, dh);
|
||||
DH_free(dh);
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
|
||||
#ifndef OPENSSL_NO_ECDH
|
||||
#ifdef NID_X9_62_prime256v1
|
||||
EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
|
||||
SSL_CTX_set_tmp_ecdh(ctx, ecdh);
|
||||
EC_KEY_free(ecdh);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM) <= 0) {
|
||||
uwsgi_log("[uwsgi-ssl] unable to assign key %s for context \"%s\"\n", key, name);
|
||||
SSL_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// if ciphers are specified, prefer server ciphers
|
||||
if (ciphers && strlen(ciphers) > 0) {
|
||||
if (SSL_CTX_set_cipher_list(ctx, ciphers) == 0) {
|
||||
uwsgi_log("[uwsgi-ssl] unable to set requested ciphers (%s) for context \"%s\"\n", ciphers, name);
|
||||
SSL_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ssloptions |= SSL_OP_CIPHER_SERVER_PREFERENCE;
|
||||
}
|
||||
|
||||
// set session context (if possibile), this is required for client certificate authentication
|
||||
if (name) {
|
||||
SSL_CTX_set_session_id_context(ctx, (unsigned char *) name, strlen(name));
|
||||
}
|
||||
|
||||
if (client_ca) {
|
||||
if (client_ca[0] == '!') {
|
||||
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, uwsgi_ssl_verify_callback);
|
||||
client_ca++;
|
||||
}
|
||||
else {
|
||||
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, uwsgi_ssl_verify_callback);
|
||||
}
|
||||
// in the future we should allow to set the verify depth
|
||||
SSL_CTX_set_verify_depth(ctx, 1);
|
||||
if (SSL_CTX_load_verify_locations(ctx, client_ca, NULL) == 0) {
|
||||
uwsgi_log("[uwsgi-ssl] unable to set ssl verify locations (%s) for context \"%s\"\n", client_ca, name);
|
||||
SSL_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
STACK_OF(X509_NAME) * list = SSL_load_client_CA_file(client_ca);
|
||||
if (!list) {
|
||||
uwsgi_log("unable to load client CA certificate (%s) for context \"%s\"\n", client_ca, name);
|
||||
SSL_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SSL_CTX_set_client_CA_list(ctx, list);
|
||||
}
|
||||
|
||||
|
||||
SSL_CTX_set_info_callback(ctx, uwsgi_ssl_info_cb);
|
||||
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
||||
SSL_CTX_set_tlsext_servername_callback(ctx, uwsgi_sni_cb);
|
||||
#endif
|
||||
|
||||
// disable session caching by default
|
||||
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
|
||||
|
||||
if (uwsgi.ssl_sessions_use_cache) {
|
||||
|
||||
// we need to early initialize locking and caching
|
||||
uwsgi_setup_locking();
|
||||
uwsgi_cache_create_all();
|
||||
|
||||
uwsgi.ssl_sessions_cache = uwsgi_cache_by_name(uwsgi.ssl_sessions_use_cache);
|
||||
if (!uwsgi.ssl_sessions_cache) {
|
||||
uwsgi_log("unable to find cache \"%s\"\n", uwsgi.ssl_sessions_use_cache ? uwsgi.ssl_sessions_use_cache : "default");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!uwsgi.ssl_sessions_cache->max_items) {
|
||||
uwsgi_log("you have to enable uWSGI cache to use it as SSL session store !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (uwsgi.ssl_sessions_cache->blocksize < 4096) {
|
||||
uwsgi_log("cache blocksize for SSL session store must be at least 4096 bytes\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER|
|
||||
SSL_SESS_CACHE_NO_INTERNAL|
|
||||
SSL_SESS_CACHE_NO_AUTO_CLEAR);
|
||||
|
||||
#ifdef SSL_OP_NO_TICKET
|
||||
ssloptions |= SSL_OP_NO_TICKET;
|
||||
#endif
|
||||
|
||||
// just for fun
|
||||
SSL_CTX_sess_set_cache_size(ctx, 0);
|
||||
|
||||
// set the callback for ssl sessions
|
||||
SSL_CTX_sess_set_new_cb(ctx, uwsgi_ssl_session_new_cb);
|
||||
SSL_CTX_sess_set_get_cb(ctx, uwsgi_ssl_session_get_cb);
|
||||
SSL_CTX_sess_set_remove_cb(ctx, uwsgi_ssl_session_remove_cb);
|
||||
}
|
||||
|
||||
SSL_CTX_set_timeout(ctx, uwsgi.ssl_sessions_timeout);
|
||||
|
||||
SSL_CTX_set_options(ctx, ssloptions);
|
||||
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
char *uwsgi_rsa_sign(char *algo_key, char *message, size_t message_len, unsigned int *s_len) {
|
||||
|
||||
// openssl could not be initialized
|
||||
if (!uwsgi.ssl_initialized) {
|
||||
uwsgi_ssl_init();
|
||||
}
|
||||
|
||||
*s_len = 0;
|
||||
EVP_PKEY *pk = NULL;
|
||||
|
||||
char *algo = uwsgi_str(algo_key);
|
||||
char *colon = strchr(algo, ':');
|
||||
if (!colon) {
|
||||
uwsgi_log("invalid RSA signature syntax, must be: <digest>:<pemfile>\n");
|
||||
free(algo);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*colon = 0;
|
||||
char *keyfile = colon + 1;
|
||||
char *signature = NULL;
|
||||
|
||||
FILE *kf = fopen(keyfile, "r");
|
||||
if (!kf) {
|
||||
uwsgi_error_open(keyfile);
|
||||
free(algo);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (PEM_read_PrivateKey(kf, &pk, NULL, NULL) == 0) {
|
||||
uwsgi_log("unable to load private key: %s\n", keyfile);
|
||||
free(algo);
|
||||
fclose(kf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fclose(kf);
|
||||
|
||||
EVP_MD_CTX *ctx = EVP_MD_CTX_create();
|
||||
if (!ctx) {
|
||||
free(algo);
|
||||
EVP_PKEY_free(pk);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const EVP_MD *md = EVP_get_digestbyname(algo);
|
||||
if (!md) {
|
||||
uwsgi_log("unknown digest algo: %s\n", algo);
|
||||
free(algo);
|
||||
EVP_PKEY_free(pk);
|
||||
EVP_MD_CTX_destroy(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*s_len = EVP_PKEY_size(pk);
|
||||
signature = uwsgi_malloc(*s_len);
|
||||
|
||||
if (EVP_SignInit_ex(ctx, md, NULL) == 0) {
|
||||
ERR_print_errors_fp(stderr);
|
||||
free(signature);
|
||||
signature = NULL;
|
||||
*s_len = 0;
|
||||
goto clear;
|
||||
}
|
||||
|
||||
if (EVP_SignUpdate(ctx, message, message_len) == 0) {
|
||||
ERR_print_errors_fp(stderr);
|
||||
free(signature);
|
||||
signature = NULL;
|
||||
*s_len = 0;
|
||||
goto clear;
|
||||
}
|
||||
|
||||
|
||||
if (EVP_SignFinal(ctx, (unsigned char *) signature, s_len, pk) == 0) {
|
||||
ERR_print_errors_fp(stderr);
|
||||
free(signature);
|
||||
signature = NULL;
|
||||
*s_len = 0;
|
||||
goto clear;
|
||||
}
|
||||
|
||||
clear:
|
||||
free(algo);
|
||||
EVP_PKEY_free(pk);
|
||||
EVP_MD_CTX_destroy(ctx);
|
||||
return signature;
|
||||
|
||||
}
|
||||
|
||||
char *uwsgi_sanitize_cert_filename(char *base, char *key, uint16_t keylen) {
|
||||
uint16_t i;
|
||||
char *filename = uwsgi_concat4n(base, strlen(base), "/", 1, key, keylen, ".pem\0", 5);
|
||||
|
||||
for (i = strlen(base) + 1; i < (strlen(base) + 1) + keylen; i++) {
|
||||
if (filename[i] >= '0' && filename[i] <= '9')
|
||||
continue;
|
||||
if (filename[i] >= 'A' && filename[i] <= 'Z')
|
||||
continue;
|
||||
if (filename[i] >= 'a' && filename[i] <= 'z')
|
||||
continue;
|
||||
if (filename[i] == '.')
|
||||
continue;
|
||||
if (filename[i] == '-')
|
||||
continue;
|
||||
if (filename[i] == '_')
|
||||
continue;
|
||||
filename[i] = '_';
|
||||
}
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
||||
char *uwsgi_ssl_rand(size_t len) {
|
||||
unsigned char *buf = uwsgi_calloc(len+1);
|
||||
if (RAND_bytes(buf, len) <= 0) {
|
||||
return NULL;
|
||||
}
|
||||
return (char *) buf;
|
||||
}
|
||||
|
||||
char *uwsgi_sha1(char *src, size_t len, char *dst) {
|
||||
SHA_CTX sha;
|
||||
SHA1_Init(&sha);
|
||||
SHA1_Update(&sha, src, len);
|
||||
SHA1_Final((unsigned char *)dst, &sha);
|
||||
return dst;
|
||||
}
|
||||
|
||||
char *uwsgi_sha1_2n(char *s1, size_t len1, char *s2, size_t len2, char *dst) {
|
||||
SHA_CTX sha;
|
||||
SHA1_Init(&sha);
|
||||
SHA1_Update(&sha, s1, len1);
|
||||
SHA1_Update(&sha, s2, len2);
|
||||
SHA1_Final((unsigned char *)dst, &sha);
|
||||
return dst;
|
||||
}
|
||||
|
||||
void uwsgi_opt_sni(char *opt, char *value, void *foobar) {
|
||||
char *client_ca = NULL;
|
||||
char *v = uwsgi_str(value);
|
||||
|
||||
char *space = strchr(v, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid %s syntax, must be sni_key<space>crt,key[,ciphers,client_ca]\n", opt);
|
||||
exit(1);
|
||||
}
|
||||
*space = 0;
|
||||
char *crt = space+1;
|
||||
char *key = strchr(crt, ',');
|
||||
if (!key) {
|
||||
uwsgi_log("invalid %s syntax, must be sni_key<space>crt,key[,ciphers,client_ca]\n", opt);
|
||||
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++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!uwsgi.ssl_initialized) {
|
||||
uwsgi_ssl_init();
|
||||
}
|
||||
|
||||
SSL_CTX *ctx = uwsgi_ssl_new_server_context(v, crt, key, ciphers, client_ca);
|
||||
if (!ctx) {
|
||||
uwsgi_log("[uwsgi-ssl] DANGER unable to initialize context for \"%s\"\n", v);
|
||||
free(v);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
if (!strcmp(opt, "sni-regexp")) {
|
||||
struct uwsgi_regexp_list *url = uwsgi_regexp_new_list(&uwsgi.sni_regexp, v);
|
||||
url->custom_ptr = ctx;
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
struct uwsgi_string_list *usl = uwsgi_string_new_list(&uwsgi.sni, v);
|
||||
usl->custom_ptr = ctx;
|
||||
#ifdef UWSGI_PCRE
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *uwsgi_ssl_add_sni_item(char *name, char *crt, char *key, char *ciphers, char *client_ca) {
|
||||
if (!uwsgi.ssl_initialized) {
|
||||
uwsgi_ssl_init();
|
||||
}
|
||||
SSL_CTX *ctx = uwsgi_ssl_new_server_context(name, crt, key, ciphers, client_ca);
|
||||
if (!ctx) {
|
||||
uwsgi_log("[uwsgi-ssl] DANGER unable to initialize context for \"%s\"\n", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *usl = uwsgi_string_new_list(&uwsgi.sni, name);
|
||||
usl->custom_ptr = ctx;
|
||||
return usl;
|
||||
}
|
||||
-623
@@ -1,623 +0,0 @@
|
||||
#include "uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t filename_len, struct stat *st) {
|
||||
// check for filename size
|
||||
if (filename_len + 4 > PATH_MAX) return 0;
|
||||
// check for supported encodings
|
||||
if (!uwsgi_contains_n(wsgi_req->encoding, wsgi_req->encoding_len, "gzip", 4) ) return 0;
|
||||
|
||||
// check for 'all'
|
||||
if (uwsgi.static_gzip_all) goto gzip;
|
||||
|
||||
// check for dirs/prefix
|
||||
struct uwsgi_string_list *usl = uwsgi.static_gzip_dir;
|
||||
while(usl) {
|
||||
if (!uwsgi_starts_with(filename, filename_len, usl->value, usl->len)) {
|
||||
goto gzip;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
// check for ext/suffix
|
||||
usl = uwsgi.static_gzip_ext;
|
||||
while(usl) {
|
||||
if (!uwsgi_strncmp(filename + (filename_len - usl->len), usl->len, usl->value, usl->len)) {
|
||||
goto gzip;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
// check for regexp
|
||||
struct uwsgi_regexp_list *url = uwsgi.static_gzip;
|
||||
while(url) {
|
||||
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, filename, filename_len) >= 0) {
|
||||
goto gzip;
|
||||
}
|
||||
url = url->next;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
gzip:
|
||||
|
||||
memcpy(filename + filename_len, ".gz\0", 4);
|
||||
filename_len += 3;
|
||||
|
||||
if (stat(filename, st)) {
|
||||
filename_len -= 3;
|
||||
filename[filename_len] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int set_http_date(time_t t, char *dst) {
|
||||
|
||||
static char *week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
|
||||
static char *months[] = {
|
||||
"Jan", "Feb", "Mar", "Apr",
|
||||
"May", "Jun", "Jul", "Aug",
|
||||
"Sep", "Oct", "Nov", "Dec"
|
||||
};
|
||||
|
||||
struct tm *hdtm = gmtime(&t);
|
||||
|
||||
int ret = snprintf(dst, 31, "%s, %02d %s %4d %02d:%02d:%02d GMT",
|
||||
week[hdtm->tm_wday], hdtm->tm_mday, months[hdtm->tm_mon], hdtm->tm_year + 1900, hdtm->tm_hour, hdtm->tm_min, hdtm->tm_sec);
|
||||
if (ret <= 0 || ret > 31) {
|
||||
return 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// only RFC 1123 is supported
|
||||
static time_t parse_http_date(char *date, uint16_t len) {
|
||||
|
||||
struct tm hdtm;
|
||||
|
||||
if (len != 29 && date[3] != ',')
|
||||
return 0;
|
||||
|
||||
hdtm.tm_mday = uwsgi_str2_num(date + 5);
|
||||
|
||||
switch (date[8]) {
|
||||
case 'J':
|
||||
if (date[9] == 'a') {
|
||||
hdtm.tm_mon = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (date[9] == 'u') {
|
||||
if (date[10] == 'n') {
|
||||
hdtm.tm_mon = 5;
|
||||
break;
|
||||
}
|
||||
|
||||
if (date[10] == 'l') {
|
||||
hdtm.tm_mon = 6;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
case 'F':
|
||||
hdtm.tm_mon = 1;
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
if (date[9] != 'a')
|
||||
return 0;
|
||||
|
||||
if (date[10] == 'r') {
|
||||
hdtm.tm_mon = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
if (date[10] == 'y') {
|
||||
hdtm.tm_mon = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
case 'A':
|
||||
if (date[10] == 'r') {
|
||||
hdtm.tm_mon = 3;
|
||||
break;
|
||||
}
|
||||
if (date[10] == 'g') {
|
||||
hdtm.tm_mon = 7;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case 'S':
|
||||
hdtm.tm_mon = 8;
|
||||
break;
|
||||
|
||||
case 'O':
|
||||
hdtm.tm_mon = 9;
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
hdtm.tm_mon = 10;
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
hdtm.tm_mon = 11;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
hdtm.tm_year = uwsgi_str4_num(date + 12) - 1900;
|
||||
|
||||
hdtm.tm_hour = uwsgi_str2_num(date + 17);
|
||||
hdtm.tm_min = uwsgi_str2_num(date + 20);
|
||||
hdtm.tm_sec = uwsgi_str2_num(date + 23);
|
||||
|
||||
return timegm(&hdtm);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int uwsgi_add_expires_type(struct wsgi_request *wsgi_req, char *mime_type, int mime_type_len, struct stat *st) {
|
||||
|
||||
struct uwsgi_dyn_dict *udd = uwsgi.static_expires_type;
|
||||
time_t now = wsgi_req->start_of_request / 1000000;
|
||||
// 30+1
|
||||
char expires[31];
|
||||
|
||||
while (udd) {
|
||||
if (!uwsgi_strncmp(udd->key, udd->keylen, mime_type, mime_type_len)) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(now + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
udd = udd->next;
|
||||
}
|
||||
|
||||
udd = uwsgi.static_expires_type_mtime;
|
||||
while (udd) {
|
||||
if (!uwsgi_strncmp(udd->key, udd->keylen, mime_type, mime_type_len)) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(st->st_mtime + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
udd = udd->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
int uwsgi_add_expires(struct wsgi_request *wsgi_req, char *filename, int filename_len, struct stat *st) {
|
||||
|
||||
struct uwsgi_dyn_dict *udd = uwsgi.static_expires;
|
||||
time_t now = wsgi_req->start_of_request / 1000000;
|
||||
// 30+1
|
||||
char expires[31];
|
||||
|
||||
while (udd) {
|
||||
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, filename, filename_len) >= 0) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(now + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
udd = udd->next;
|
||||
}
|
||||
|
||||
udd = uwsgi.static_expires_mtime;
|
||||
while (udd) {
|
||||
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, filename, filename_len) >= 0) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(st->st_mtime + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
udd = udd->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_add_expires_path_info(struct wsgi_request *wsgi_req, struct stat *st) {
|
||||
|
||||
struct uwsgi_dyn_dict *udd = uwsgi.static_expires_path_info;
|
||||
time_t now = wsgi_req->start_of_request / 1000000;
|
||||
// 30+1
|
||||
char expires[31];
|
||||
|
||||
while (udd) {
|
||||
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->path_info, wsgi_req->path_info_len) >= 0) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(now + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
udd = udd->next;
|
||||
}
|
||||
|
||||
udd = uwsgi.static_expires_path_info_mtime;
|
||||
while (udd) {
|
||||
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->path_info, wsgi_req->path_info_len) >= 0) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(st->st_mtime + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
udd = udd->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_add_expires_uri(struct wsgi_request *wsgi_req, struct stat *st) {
|
||||
|
||||
struct uwsgi_dyn_dict *udd = uwsgi.static_expires_uri;
|
||||
time_t now = wsgi_req->start_of_request / 1000000;
|
||||
// 30+1
|
||||
char expires[31];
|
||||
|
||||
while (udd) {
|
||||
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->uri, wsgi_req->uri_len) >= 0) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(now + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
udd = udd->next;
|
||||
}
|
||||
|
||||
udd = uwsgi.static_expires_uri_mtime;
|
||||
while (udd) {
|
||||
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->uri, wsgi_req->uri_len) >= 0) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(st->st_mtime + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
udd = udd->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
char *uwsgi_get_mime_type(char *name, int namelen, int *size) {
|
||||
|
||||
int i;
|
||||
int count = 0;
|
||||
char *ext = NULL;
|
||||
for (i = namelen - 1; i >= 0; i--) {
|
||||
if (!isalnum((int) name[i])) {
|
||||
if (name[i] == '.') {
|
||||
ext = name + (namelen - count);
|
||||
break;
|
||||
}
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
if (!ext)
|
||||
return NULL;
|
||||
|
||||
struct uwsgi_dyn_dict *udd = uwsgi.mimetypes;
|
||||
while (udd) {
|
||||
if (!uwsgi_strncmp(ext, count, udd->key, udd->keylen)) {
|
||||
udd->hits++;
|
||||
// auto optimization
|
||||
if (udd->prev) {
|
||||
if (udd->hits > udd->prev->hits) {
|
||||
struct uwsgi_dyn_dict *udd_parent = udd->prev->prev, *udd_prev = udd->prev;
|
||||
if (udd_parent) {
|
||||
udd_parent->next = udd;
|
||||
}
|
||||
|
||||
if (udd->next) {
|
||||
udd->next->prev = udd_prev;
|
||||
}
|
||||
|
||||
udd_prev->prev = udd;
|
||||
udd_prev->next = udd->next;
|
||||
|
||||
udd->prev = udd_parent;
|
||||
udd->next = udd_prev;
|
||||
|
||||
if (udd->prev == NULL) {
|
||||
uwsgi.mimetypes = udd;
|
||||
}
|
||||
}
|
||||
}
|
||||
*size = udd->vallen;
|
||||
return udd->value;
|
||||
}
|
||||
udd = udd->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ssize_t uwsgi_append_static_path(char *dir, size_t dir_len, char *file, size_t file_len) {
|
||||
|
||||
|
||||
size_t len = dir_len;
|
||||
|
||||
if (len + 1 + file_len > PATH_MAX) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dir[len - 1] == '/') {
|
||||
memcpy(dir + len, file, file_len);
|
||||
dir[len + file_len] = 0;
|
||||
len += file_len;
|
||||
}
|
||||
else {
|
||||
dir[len] = '/';
|
||||
memcpy(dir + len + 1, file, file_len);
|
||||
dir[len + 1 + file_len] = 0;
|
||||
len += 1 + file_len;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int uwsgi_static_stat(struct wsgi_request *wsgi_req, char *filename, size_t *filename_len, struct stat *st, struct uwsgi_string_list **index) {
|
||||
|
||||
int ret = stat(filename, st);
|
||||
// if non-existant return -1
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
if (S_ISREG(st->st_mode))
|
||||
return 0;
|
||||
|
||||
// check for index
|
||||
if (S_ISDIR(st->st_mode)) {
|
||||
struct uwsgi_string_list *usl = uwsgi.static_index;
|
||||
while (usl) {
|
||||
ssize_t new_len = uwsgi_append_static_path(filename, *filename_len, usl->value, usl->len);
|
||||
if (new_len >= 0) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("checking for %s\n", filename);
|
||||
#endif
|
||||
if (uwsgi_is_file2(filename, st)) {
|
||||
*index = usl;
|
||||
*filename_len = new_len;
|
||||
return 0;
|
||||
}
|
||||
// reset to original name
|
||||
filename[*filename_len] = 0;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, size_t real_filename_len, struct stat *st) {
|
||||
|
||||
int mime_type_size = 0;
|
||||
char http_last_modified[49];
|
||||
|
||||
if (uwsgi.threads > 1)
|
||||
pthread_mutex_lock(&uwsgi.lock_static);
|
||||
|
||||
char *mime_type = uwsgi_get_mime_type(real_filename, real_filename_len, &mime_type_size);
|
||||
|
||||
if (uwsgi.threads > 1)
|
||||
pthread_mutex_unlock(&uwsgi.lock_static);
|
||||
|
||||
if (wsgi_req->if_modified_since_len) {
|
||||
time_t ims = parse_http_date(wsgi_req->if_modified_since, wsgi_req->if_modified_since_len);
|
||||
if (st->st_mtime <= ims) {
|
||||
uwsgi_response_prepare_headers(wsgi_req, "304 Not Modified", 16);
|
||||
return uwsgi_response_write_headers_do(wsgi_req);
|
||||
}
|
||||
}
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[uwsgi-fileserve] file %s found\n", real_filename);
|
||||
#endif
|
||||
|
||||
// HTTP status
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return -1;
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
uwsgi_add_expires(wsgi_req, real_filename, real_filename_len, st);
|
||||
uwsgi_add_expires_path_info(wsgi_req, st);
|
||||
uwsgi_add_expires_uri(wsgi_req, st);
|
||||
#endif
|
||||
|
||||
// Content-Type (if available)
|
||||
if (mime_type_size > 0 && mime_type) {
|
||||
if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_size)) return -1;
|
||||
// check for content-type related headers
|
||||
uwsgi_add_expires_type(wsgi_req, mime_type, mime_type_size, st);
|
||||
}
|
||||
|
||||
// increase static requests counter
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].static_requests++;
|
||||
|
||||
// nginx
|
||||
if (uwsgi.file_serve_mode == 1) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "X-Accel-Redirect", 16, real_filename, real_filename_len)) return -1;
|
||||
// this is the final header (\r\n added)
|
||||
int size = set_http_date(st->st_mtime, http_last_modified);
|
||||
if (uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, http_last_modified, size)) return -1;
|
||||
}
|
||||
// apache
|
||||
else if (uwsgi.file_serve_mode == 2) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "X-Sendfile", 10, real_filename, real_filename_len)) return -1;
|
||||
// this is the final header (\r\n added)
|
||||
int size = set_http_date(st->st_mtime, http_last_modified);
|
||||
if (uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, http_last_modified, size)) return -1;
|
||||
}
|
||||
// raw
|
||||
else {
|
||||
// here we need to choose if we want the gzip variant;
|
||||
if (uwsgi_static_want_gzip(wsgi_req, real_filename, real_filename_len, st)) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Content-Encoding", 16, "gzip", 4)) return -1;
|
||||
}
|
||||
// set Content-Length
|
||||
if (uwsgi_response_add_content_length(wsgi_req, st->st_size)) return -1;
|
||||
int size = set_http_date(st->st_mtime, http_last_modified);
|
||||
if (uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, http_last_modified, size)) return -1;
|
||||
|
||||
// if it is a HEAD request just skip transfer
|
||||
if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4)) {
|
||||
wsgi_req->status = 200;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Ok, the file must be transferred from uWSGI
|
||||
// offloading will be automatically managed
|
||||
int fd = open(real_filename, O_RDONLY);
|
||||
if (fd < 0) return -1;
|
||||
// fd will be closed in the following function
|
||||
uwsgi_response_sendfile_do(wsgi_req, fd, 0, st->st_size);
|
||||
}
|
||||
|
||||
wsgi_req->status = 200;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_t document_root_len, char *path_info, uint16_t path_info_len, int is_a_file) {
|
||||
|
||||
struct stat st;
|
||||
char real_filename[PATH_MAX + 1];
|
||||
size_t real_filename_len = 0;
|
||||
char *filename = NULL;
|
||||
size_t filename_len = 0;
|
||||
|
||||
struct uwsgi_string_list *index = NULL;
|
||||
|
||||
if (!is_a_file) {
|
||||
filename = uwsgi_concat3n(document_root, document_root_len, "/", 1, path_info, path_info_len);
|
||||
filename_len = document_root_len + 1 + path_info_len;
|
||||
}
|
||||
else {
|
||||
filename = uwsgi_concat2n(document_root, document_root_len, "", 0);
|
||||
filename_len = document_root_len;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[uwsgi-fileserve] checking for %s\n", filename);
|
||||
#endif
|
||||
|
||||
if (uwsgi.static_cache_paths) {
|
||||
uwsgi_rlock(uwsgi.static_cache_paths->lock);
|
||||
uint64_t item_len;
|
||||
char *item = uwsgi_cache_get2(uwsgi.static_cache_paths, filename, filename_len, &item_len);
|
||||
if (item && item_len > 0 && item_len <= PATH_MAX) {
|
||||
memcpy(real_filename, item, item_len);
|
||||
real_filename_len = item_len;
|
||||
uwsgi_rwunlock(uwsgi.static_cache_paths->lock);
|
||||
goto found;
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.static_cache_paths->lock);
|
||||
}
|
||||
|
||||
if (!realpath(filename, real_filename)) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[uwsgi-fileserve] unable to get realpath() of the static file\n");
|
||||
#endif
|
||||
free(filename);
|
||||
return -1;
|
||||
}
|
||||
real_filename_len = strlen(real_filename);
|
||||
|
||||
if (uwsgi.static_cache_paths) {
|
||||
uwsgi_wlock(uwsgi.static_cache_paths->lock);
|
||||
uwsgi_cache_set2(uwsgi.static_cache_paths, filename, filename_len, real_filename, real_filename_len, uwsgi.use_static_cache_paths, UWSGI_CACHE_FLAG_UPDATE);
|
||||
uwsgi_rwunlock(uwsgi.static_cache_paths->lock);
|
||||
}
|
||||
|
||||
found:
|
||||
free(filename);
|
||||
|
||||
if (uwsgi_starts_with(real_filename, real_filename_len, document_root, document_root_len)) {
|
||||
struct uwsgi_string_list *safe = uwsgi.static_safe;
|
||||
while(safe) {
|
||||
if (!uwsgi_starts_with(real_filename, real_filename_len, safe->value, safe->len)) {
|
||||
goto safe;
|
||||
}
|
||||
safe = safe->next;
|
||||
}
|
||||
uwsgi_log("[uwsgi-fileserve] security error: %s is not under %.*s or a safe path\n", real_filename, document_root_len, document_root);
|
||||
return -1;
|
||||
}
|
||||
|
||||
safe:
|
||||
|
||||
if (!uwsgi_static_stat(wsgi_req, real_filename, &real_filename_len, &st, &index)) {
|
||||
|
||||
if (index) {
|
||||
// if we are here the PATH_INFO need to be changed
|
||||
if (uwsgi_req_append_path_info_with_index(wsgi_req, index->value, index->len)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// skip methods other than GET and HEAD
|
||||
if (uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "GET", 3) && uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// check for skippable ext
|
||||
struct uwsgi_string_list *sse = uwsgi.static_skip_ext;
|
||||
while (sse) {
|
||||
if (real_filename_len >= sse->len) {
|
||||
if (!uwsgi_strncmp(real_filename + (real_filename_len - sse->len), sse->len, sse->value, sse->len)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
sse = sse->next;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
// before sending the file, we need to check if some rule applies
|
||||
if (!wsgi_req->is_routing && uwsgi_apply_routes_do(wsgi_req, NULL, 0) == UWSGI_ROUTE_BREAK) {
|
||||
return 0;
|
||||
}
|
||||
wsgi_req->routes_applied = 1;
|
||||
#endif
|
||||
|
||||
return uwsgi_real_file_serve(wsgi_req, real_filename, real_filename_len, &st);
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
}
|
||||
+3
-55
@@ -13,7 +13,6 @@ struct uwsgi_stats *uwsgi_stats_new(size_t chunk_size) {
|
||||
us->chunk = chunk_size;
|
||||
us->size = chunk_size;
|
||||
us->tabs = 1;
|
||||
us->dirty = 0;
|
||||
us->minified = uwsgi.stats_minified;
|
||||
if (!us->minified) {
|
||||
us->base[1] = '\n';
|
||||
@@ -374,7 +373,7 @@ struct uwsgi_stats_pusher *uwsgi_stats_pusher_get(char *name) {
|
||||
return usp;
|
||||
}
|
||||
|
||||
struct uwsgi_stats_pusher_instance *uwsgi_stats_pusher_add(struct uwsgi_stats_pusher *pusher, char *arg) {
|
||||
struct uwsgi_stats_pusher_instance * uwsgi_stats_pusher_add(struct uwsgi_stats_pusher *pusher, char *arg) {
|
||||
struct uwsgi_stats_pusher_instance *old_uspi = NULL, *uspi = uwsgi.stats_pusher_instances;
|
||||
while (uspi) {
|
||||
old_uspi = uspi;
|
||||
@@ -383,8 +382,7 @@ struct uwsgi_stats_pusher_instance *uwsgi_stats_pusher_add(struct uwsgi_stats_pu
|
||||
|
||||
uspi = uwsgi_calloc(sizeof(struct uwsgi_stats_pusher_instance));
|
||||
uspi->pusher = pusher;
|
||||
uspi->arg = uwsgi_str(arg);
|
||||
uspi->raw = pusher->raw;
|
||||
uspi->arg = arg;
|
||||
if (old_uspi) {
|
||||
old_uspi->next = uspi;
|
||||
}
|
||||
@@ -423,8 +421,7 @@ void uwsgi_stats_pusher_loop(struct uwsgi_thread *ut) {
|
||||
else {
|
||||
if (!us) {
|
||||
us = uwsgi_master_generate_stats();
|
||||
if (!us)
|
||||
goto next;
|
||||
if (!us) goto next;
|
||||
}
|
||||
uspi->pusher->func(uspi, now, us->base, us->pos);
|
||||
}
|
||||
@@ -453,7 +450,6 @@ void uwsgi_stats_pusher_setup() {
|
||||
pusher = uwsgi_stats_pusher_get(ssp);
|
||||
if (!pusher) {
|
||||
uwsgi_log("unable to find \"%s\" stats_pusher\n", ssp);
|
||||
free(ssp);
|
||||
exit(1);
|
||||
}
|
||||
char *arg = NULL;
|
||||
@@ -463,7 +459,6 @@ void uwsgi_stats_pusher_setup() {
|
||||
}
|
||||
uwsgi_stats_pusher_add(pusher, arg);
|
||||
usl = usl->next;
|
||||
free(ssp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -533,50 +528,3 @@ void uwsgi_stats_pusher_file(struct uwsgi_stats_pusher_instance *uspi, time_t no
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static void stats_dump_var(char *k, uint16_t kl, char *v, uint16_t vl, void *data) {
|
||||
struct uwsgi_stats *us = (struct uwsgi_stats *) data;
|
||||
if (us->dirty) return;
|
||||
uint16_t i;
|
||||
// replace " with '
|
||||
for(i=0;i<kl;i++) {
|
||||
if (k[i] == '"') {
|
||||
k[i] = '\'';
|
||||
}
|
||||
}
|
||||
for(i=0;i<vl;i++) {
|
||||
if (v[i] == '"') {
|
||||
v[i] = '\'';
|
||||
}
|
||||
}
|
||||
char *var = uwsgi_concat3n(k, kl, "=", 1, v,vl);
|
||||
if (uwsgi_stats_str(us, var)) {
|
||||
us->dirty = 1;
|
||||
free(var);
|
||||
return;
|
||||
}
|
||||
free(var);
|
||||
if (uwsgi_stats_comma(us)) {
|
||||
us->dirty = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int uwsgi_stats_dump_vars(struct uwsgi_stats *us, struct uwsgi_core *uc) {
|
||||
if (!uc->in_request) return 0;
|
||||
struct uwsgi_header *uh = (struct uwsgi_header *) uwsgi.workers[0].cores[0].buffer;
|
||||
uint16_t pktsize = uh->pktsize;
|
||||
if (!pktsize) return 0;
|
||||
char *dst = uwsgi.workers[0].cores[0].buffer;
|
||||
memcpy(dst, uc->buffer+4, uwsgi.buffer_size);
|
||||
// ok now check if something changed...
|
||||
if (!uc->in_request) return 0;
|
||||
if (uh->pktsize != pktsize) return 0;
|
||||
if (memcmp(dst, uc->buffer+4, uwsgi.buffer_size)) return 0;
|
||||
// nothing changed let's dump vars
|
||||
int ret = uwsgi_hooked_parse(dst, pktsize, stats_dump_var, us);
|
||||
if (ret) return -1;
|
||||
if (us->dirty) return -1;
|
||||
if (uwsgi_stats_str(us, "")) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
#include "../uwsgi.h"
|
||||
|
||||
/*
|
||||
|
||||
Storage subsystem: filesystem-like abstraction
|
||||
|
||||
struct uwsgi_storage_engine {
|
||||
char *name;
|
||||
uint16_t name_len;
|
||||
int64_t (*get)(char *, uint16_t, char *, uint64_t, uint64_t, uint64_t);
|
||||
int64_t (*set)(char *, uint16_t, char *, uint64_t, uint64_t, uint64_t);
|
||||
};
|
||||
|
||||
struct uwsgi_storage {
|
||||
char *name;
|
||||
uint16_t name_len;
|
||||
struct uwsgi_storage_engine *engine;
|
||||
};
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_storage* uwsgi_storage_by_name(char *name, uint16_t name_len) {
|
||||
if (!name_len) {
|
||||
name_len = strlen(name);
|
||||
}
|
||||
struct uwsgi_storage *s = uwsgi.virtualdisks;
|
||||
while(s) {
|
||||
if (!uwsgi_strncmp(s->name, s->name_len, name, name_len)) {
|
||||
return s;
|
||||
}
|
||||
s = s->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int64_t uwsgi_storage_get(struct uwsgi_storage *storage, char *key, uint16_t key_len, char *out_buf, uint64_t pos, uint64_t size, uint64_t flags) {
|
||||
if (!storage->get) return -1;
|
||||
return storage->get(key, key_len, out_buf, pos, size, flags);
|
||||
}
|
||||
|
||||
int64_t uwsgi_storage_set(struct uwsgi_storage *storage, char *key, uint16_t key_len, char *in_buf, uint64_t pos, uint64_t size, uint64_t flags) {
|
||||
if (!storage->set) return -1;
|
||||
return storage->set(key, key_len, out_buf, pos, size, flags);
|
||||
}
|
||||
-340
@@ -1,340 +0,0 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
// check if a string_list contains an item
|
||||
struct uwsgi_string_list *uwsgi_string_list_has_item(struct uwsgi_string_list *list, char *key, size_t keylen) {
|
||||
struct uwsgi_string_list *usl = list;
|
||||
while (usl) {
|
||||
if (keylen == usl->len) {
|
||||
if (!memcmp(key, usl->value, keylen)) {
|
||||
return usl;
|
||||
}
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// lower a string
|
||||
char *uwsgi_lower(char *str, size_t size) {
|
||||
size_t i;
|
||||
for (i = 0; i < size; i++) {
|
||||
str[i] = tolower((int) str[i]);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
// check if a string is contained in another one
|
||||
char *uwsgi_str_contains(char *str, int slen, char what) {
|
||||
|
||||
int i;
|
||||
for (i = 0; i < slen; i++) {
|
||||
if (str[i] == what) {
|
||||
return str + i;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int uwsgi_contains_n(char *s1, size_t s1_len, char *s2, size_t s2_len) {
|
||||
size_t i;
|
||||
char *ptr = s2;
|
||||
for (i = 0; i < s1_len; i++) {
|
||||
if (s1[i] == *ptr) {
|
||||
ptr++;
|
||||
if (ptr == s2 + s2_len) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ptr = s2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// fast compare 2 sized strings
|
||||
int uwsgi_strncmp(char *src, int slen, char *dst, int dlen) {
|
||||
|
||||
if (slen != dlen)
|
||||
return 1;
|
||||
|
||||
return memcmp(src, dst, dlen);
|
||||
|
||||
}
|
||||
|
||||
// fast compare 2 sized strings (case insensitive)
|
||||
int uwsgi_strnicmp(char *src, int slen, char *dst, int dlen) {
|
||||
|
||||
if (slen != dlen)
|
||||
return 1;
|
||||
|
||||
return strncasecmp(src, dst, dlen);
|
||||
|
||||
}
|
||||
|
||||
// fast sized check of initial part of a string
|
||||
int uwsgi_starts_with(char *src, int slen, char *dst, int dlen) {
|
||||
|
||||
if (slen < dlen)
|
||||
return -1;
|
||||
|
||||
return memcmp(src, dst, dlen);
|
||||
}
|
||||
|
||||
|
||||
// unsized check
|
||||
int uwsgi_startswith(char *src, char *what, int wlen) {
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < wlen; i++) {
|
||||
if (src[i] != what[i])
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// concatenate strings
|
||||
char *uwsgi_concatn(int c, ...) {
|
||||
|
||||
va_list s;
|
||||
char *item;
|
||||
int j = c;
|
||||
char *buf;
|
||||
size_t len = 1;
|
||||
size_t tlen = 1;
|
||||
|
||||
va_start(s, c);
|
||||
while (j > 0) {
|
||||
item = va_arg(s, char *);
|
||||
if (item == NULL) {
|
||||
break;
|
||||
}
|
||||
len += va_arg(s, int);
|
||||
j--;
|
||||
}
|
||||
va_end(s);
|
||||
|
||||
|
||||
buf = uwsgi_malloc(len);
|
||||
memset(buf, 0, len);
|
||||
|
||||
j = c;
|
||||
|
||||
len = 0;
|
||||
|
||||
va_start(s, c);
|
||||
while (j > 0) {
|
||||
item = va_arg(s, char *);
|
||||
if (item == NULL) {
|
||||
break;
|
||||
}
|
||||
tlen = va_arg(s, int);
|
||||
memcpy(buf + len, item, tlen);
|
||||
len += tlen;
|
||||
j--;
|
||||
}
|
||||
va_end(s);
|
||||
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
|
||||
char *uwsgi_concat2(char *one, char *two) {
|
||||
|
||||
char *buf;
|
||||
size_t len = strlen(one) + strlen(two) + 1;
|
||||
|
||||
|
||||
buf = uwsgi_malloc(len);
|
||||
buf[len - 1] = 0;
|
||||
|
||||
memcpy(buf, one, strlen(one));
|
||||
memcpy(buf + strlen(one), two, strlen(two));
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
|
||||
char *uwsgi_concat4(char *one, char *two, char *three, char *four) {
|
||||
|
||||
char *buf;
|
||||
size_t len = strlen(one) + strlen(two) + strlen(three) + strlen(four) + 1;
|
||||
|
||||
|
||||
buf = uwsgi_malloc(len);
|
||||
buf[len - 1] = 0;
|
||||
|
||||
memcpy(buf, one, strlen(one));
|
||||
memcpy(buf + strlen(one), two, strlen(two));
|
||||
memcpy(buf + strlen(one) + strlen(two), three, strlen(three));
|
||||
memcpy(buf + strlen(one) + strlen(two) + strlen(three), four, strlen(four));
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
|
||||
|
||||
char *uwsgi_concat3(char *one, char *two, char *three) {
|
||||
|
||||
char *buf;
|
||||
size_t len = strlen(one) + strlen(two) + strlen(three) + 1;
|
||||
|
||||
|
||||
buf = uwsgi_malloc(len);
|
||||
buf[len - 1] = 0;
|
||||
|
||||
memcpy(buf, one, strlen(one));
|
||||
memcpy(buf + strlen(one), two, strlen(two));
|
||||
memcpy(buf + strlen(one) + strlen(two), three, strlen(three));
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
|
||||
char *uwsgi_concat2n(char *one, int s1, char *two, int s2) {
|
||||
|
||||
char *buf;
|
||||
size_t len = s1 + s2 + 1;
|
||||
|
||||
|
||||
buf = uwsgi_malloc(len);
|
||||
buf[len - 1] = 0;
|
||||
|
||||
memcpy(buf, one, s1);
|
||||
memcpy(buf + s1, two, s2);
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
|
||||
char *uwsgi_concat2nn(char *one, int s1, char *two, int s2, int *len) {
|
||||
|
||||
char *buf;
|
||||
*len = s1 + s2 + 1;
|
||||
|
||||
|
||||
buf = uwsgi_malloc(*len);
|
||||
buf[*len - 1] = 0;
|
||||
|
||||
memcpy(buf, one, s1);
|
||||
memcpy(buf + s1, two, s2);
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
|
||||
|
||||
char *uwsgi_concat3n(char *one, int s1, char *two, int s2, char *three, int s3) {
|
||||
|
||||
char *buf;
|
||||
size_t len = s1 + s2 + s3 + 1;
|
||||
|
||||
|
||||
buf = uwsgi_malloc(len);
|
||||
buf[len - 1] = 0;
|
||||
|
||||
memcpy(buf, one, s1);
|
||||
memcpy(buf + s1, two, s2);
|
||||
memcpy(buf + s1 + s2, three, s3);
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
|
||||
char *uwsgi_concat4n(char *one, int s1, char *two, int s2, char *three, int s3, char *four, int s4) {
|
||||
|
||||
char *buf;
|
||||
size_t len = s1 + s2 + s3 + s4 + 1;
|
||||
|
||||
|
||||
buf = uwsgi_malloc(len);
|
||||
buf[len - 1] = 0;
|
||||
|
||||
memcpy(buf, one, s1);
|
||||
memcpy(buf + s1, two, s2);
|
||||
memcpy(buf + s1 + s2, three, s3);
|
||||
memcpy(buf + s1 + s2 + s3, four, s4);
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
|
||||
// concat unsized strings
|
||||
char *uwsgi_concat(int c, ...) {
|
||||
|
||||
va_list s;
|
||||
char *item;
|
||||
size_t len = 1;
|
||||
int j = c;
|
||||
char *buf;
|
||||
|
||||
va_start(s, c);
|
||||
while (j > 0) {
|
||||
item = va_arg(s, char *);
|
||||
if (item == NULL) {
|
||||
break;
|
||||
}
|
||||
len += (int) strlen(item);
|
||||
j--;
|
||||
}
|
||||
va_end(s);
|
||||
|
||||
|
||||
buf = uwsgi_malloc(len);
|
||||
memset(buf, 0, len);
|
||||
|
||||
j = c;
|
||||
|
||||
len = 0;
|
||||
|
||||
va_start(s, c);
|
||||
while (j > 0) {
|
||||
item = va_arg(s, char *);
|
||||
if (item == NULL) {
|
||||
break;
|
||||
}
|
||||
memcpy(buf + len, item, strlen(item));
|
||||
len += strlen(item);
|
||||
j--;
|
||||
}
|
||||
va_end(s);
|
||||
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
|
||||
char *uwsgi_strncopy(char *s, int len) {
|
||||
|
||||
char *buf;
|
||||
|
||||
buf = uwsgi_malloc(len + 1);
|
||||
buf[len] = 0;
|
||||
|
||||
memcpy(buf, s, len);
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
|
||||
// this move a string back of one char and put a 0 at the end (used in uwsgi parsers for buffer reusing)
|
||||
char *uwsgi_cheap_string(char *buf, int len) {
|
||||
|
||||
int i;
|
||||
char *cheap_buf = buf - 1;
|
||||
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
*cheap_buf++ = buf[i];
|
||||
}
|
||||
|
||||
|
||||
buf[len - 1] = 0;
|
||||
|
||||
return buf - 1;
|
||||
}
|
||||
|
||||
+176
-254
@@ -91,7 +91,7 @@ static struct uwsgi_subscribe_node *uwsgi_subscription_algo_lrc(struct uwsgi_sub
|
||||
if (min_rc == 0 || node->reference < min_rc) {
|
||||
min_rc = node->reference;
|
||||
choosen_node = node;
|
||||
if (min_rc == 0 && !(node->next && node->next->reference <= node->reference && node->next->last_requests <= node->last_requests))
|
||||
if (min_rc == 0 && !(node->next && node->next->reference <= node->reference && node->next->requests <= node->requests))
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -125,7 +125,7 @@ static struct uwsgi_subscribe_node *uwsgi_subscription_algo_wlrc(struct uwsgi_su
|
||||
if (min_rc == 0 || ref < min_rc) {
|
||||
min_rc = ref;
|
||||
choosen_node = node;
|
||||
if (min_rc == 0 && !(node->next && next_node_ref <= ref && node->next->last_requests <= node->last_requests))
|
||||
if (min_rc == 0 && !(node->next && next_node_ref <= ref && node->next->requests <= node->requests))
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -376,7 +376,6 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
node->weight = usr->weight;
|
||||
if (!node->weight)
|
||||
node->weight = 1;
|
||||
node->last_requests = 0;
|
||||
return node;
|
||||
}
|
||||
old_node = node;
|
||||
@@ -395,7 +394,6 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
node->modifier1 = usr->modifier1;
|
||||
node->modifier2 = usr->modifier2;
|
||||
node->requests = 0;
|
||||
node->last_requests = 0;
|
||||
node->transferred = 0;
|
||||
node->reference = 0;
|
||||
node->death_mark = 0;
|
||||
@@ -472,7 +470,6 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
current_slot->nodes->len = usr->address_len;
|
||||
current_slot->nodes->reference = 0;
|
||||
current_slot->nodes->requests = 0;
|
||||
current_slot->nodes->last_requests = 0;
|
||||
current_slot->nodes->transferred = 0;
|
||||
current_slot->nodes->death_mark = 0;
|
||||
current_slot->nodes->failcnt = 0;
|
||||
@@ -517,8 +514,31 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
}
|
||||
|
||||
|
||||
// TODO rewrite it using uwsgi buffers
|
||||
void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, uint8_t modifier1, uint8_t modifier2, uint8_t cmd, char *socket_name, char *sign) {
|
||||
|
||||
char value_cores[sizeof(UMAX64_STR) + 1];
|
||||
char value_load[sizeof(UMAX64_STR) + 1];
|
||||
char value_weight[sizeof(UMAX64_STR) + 1];
|
||||
|
||||
|
||||
int value_cores_size = uwsgi_long2str2n(uwsgi.numproc * uwsgi.cores, value_cores, sizeof(UMAX64_STR));
|
||||
int value_load_size = uwsgi_long2str2n(uwsgi.shared->load, value_load, sizeof(UMAX64_STR));
|
||||
|
||||
int value_weight_size = 0;
|
||||
|
||||
if (uwsgi.auto_weight) {
|
||||
value_weight_size = uwsgi_long2str2n(uwsgi.numproc * uwsgi.cores, value_weight, sizeof(UMAX64_STR));
|
||||
}
|
||||
else {
|
||||
value_weight_size = uwsgi_long2str2n(uwsgi.weight, value_weight, sizeof(UMAX64_STR));
|
||||
}
|
||||
|
||||
char value_modifier1[4];
|
||||
char value_modifier2[4];
|
||||
int value_modifier1_size = uwsgi_long2str2n(modifier1, value_modifier1, 3);
|
||||
int value_modifier2_size = uwsgi_long2str2n(modifier2, value_modifier2, 3);
|
||||
|
||||
if (socket_name == NULL && !uwsgi.sockets)
|
||||
return;
|
||||
|
||||
@@ -526,44 +546,173 @@ void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, uint8
|
||||
socket_name = uwsgi.sockets->name;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(4096);
|
||||
size_t ssb_size = 4 + (2 + 3) + (2 + keysize) + (2 + 7) + (2 + strlen(socket_name)) + (2 + 9 + 2 + value_modifier1_size) + (2 + 9 + 2 + value_modifier2_size) + (2 + 5 + 2 + value_cores_size) + (2 + 4 + 2 + value_load_size) + (2 + 6 + 2 + value_weight_size);
|
||||
|
||||
// make space for uwsgi header
|
||||
ub->pos = 4;
|
||||
char *subscrbuf = uwsgi_malloc(ssb_size);
|
||||
// leave space for uwsgi header
|
||||
char *ssb = subscrbuf + 4;
|
||||
|
||||
if (uwsgi_buffer_append_keyval(ub, "key", 3, key, keysize)) goto end;
|
||||
if (uwsgi_buffer_append_keyval(ub, "address", 7, socket_name, strlen(socket_name))) goto end;
|
||||
if (uwsgi_buffer_append_keynum(ub, "modifier1", 9, modifier1)) goto end;
|
||||
if (uwsgi_buffer_append_keynum(ub, "modifier2", 9, modifier2)) goto end;
|
||||
if (uwsgi_buffer_append_keynum(ub, "cores", 5, uwsgi.numproc * uwsgi.cores)) goto end;
|
||||
if (uwsgi_buffer_append_keynum(ub, "load", 4, uwsgi.shared->load)) goto end;
|
||||
if (uwsgi.auto_weight) {
|
||||
if (uwsgi_buffer_append_keynum(ub, "weight", 6, uwsgi.numproc * uwsgi.cores )) goto end;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_buffer_append_keynum(ub, "weight", 6, uwsgi.weight )) goto end;
|
||||
}
|
||||
// key = "domain"
|
||||
uint16_t ustrlen = 3;
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ssb, "key", ustrlen);
|
||||
ssb += ustrlen;
|
||||
|
||||
ustrlen = keysize;
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ssb, key, ustrlen);
|
||||
ssb += ustrlen;
|
||||
|
||||
// address = "first uwsgi socket"
|
||||
ustrlen = 7;
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ssb, "address", ustrlen);
|
||||
ssb += ustrlen;
|
||||
|
||||
ustrlen = strlen(socket_name);
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ssb, socket_name, ustrlen);
|
||||
ssb += ustrlen;
|
||||
|
||||
// modifier1 = "modifier1"
|
||||
ustrlen = 9;
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ssb, "modifier1", ustrlen);
|
||||
ssb += ustrlen;
|
||||
|
||||
ustrlen = value_modifier1_size;
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ssb, value_modifier1, value_modifier1_size);
|
||||
ssb += ustrlen;
|
||||
|
||||
// modifier2 = "modifier2"
|
||||
ustrlen = 9;
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ssb, "modifier2", ustrlen);
|
||||
ssb += ustrlen;
|
||||
|
||||
ustrlen = value_modifier2_size;
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ssb, value_modifier2, value_modifier2_size);
|
||||
ssb += ustrlen;
|
||||
|
||||
// cores = uwsgi.numproc * uwsgi.cores
|
||||
ustrlen = 5;
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ssb, "cores", ustrlen);
|
||||
ssb += ustrlen;
|
||||
|
||||
ustrlen = value_cores_size;
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ssb, value_cores, value_cores_size);
|
||||
ssb += ustrlen;
|
||||
|
||||
// load
|
||||
ustrlen = 4;
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ssb, "load", ustrlen);
|
||||
ssb += ustrlen;
|
||||
|
||||
ustrlen = value_load_size;
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ssb, value_load, value_load_size);
|
||||
ssb += ustrlen;
|
||||
|
||||
// weight
|
||||
ustrlen = 6;
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ssb, "weight", ustrlen);
|
||||
ssb += ustrlen;
|
||||
|
||||
ustrlen = value_weight_size;
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ssb, value_weight, value_weight_size);
|
||||
ssb += ustrlen;
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
if (sign) {
|
||||
if (uwsgi_buffer_append_keynum(ub, "unix", 4, (uwsgi_now() + (time_t) cmd) )) goto end;
|
||||
// add space for "unix" item
|
||||
char unix_dst[sizeof(UMAX64_STR) + 1];
|
||||
if (snprintf(unix_dst, sizeof(UMAX64_STR) + 1, "%lu", (unsigned long) (uwsgi_now() + (time_t) cmd)) < 1) {
|
||||
uwsgi_error("unable to generate unix time for subscription !!!\n");
|
||||
free(subscrbuf);
|
||||
return;
|
||||
}
|
||||
ssb_size += 2 + 4 + 2 + strlen(unix_dst);
|
||||
char *new_buf = realloc(subscrbuf, ssb_size);
|
||||
if (!new_buf) {
|
||||
uwsgi_error("realloc()");
|
||||
free(subscrbuf);
|
||||
return;
|
||||
}
|
||||
|
||||
// fix ssb (new_buf base could be changed)
|
||||
ssb = (new_buf + (ssb - subscrbuf));
|
||||
subscrbuf = new_buf;
|
||||
|
||||
ustrlen = 4;
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ssb, "unix", ustrlen);
|
||||
ssb += ustrlen;
|
||||
|
||||
ustrlen = strlen(unix_dst);
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ssb, unix_dst, strlen(unix_dst));
|
||||
ssb += ustrlen;
|
||||
|
||||
unsigned int signature_len = 0;
|
||||
char *signature = uwsgi_rsa_sign(sign, ub->buf + 4, ub->pos - 4, &signature_len);
|
||||
char *signature = uwsgi_rsa_sign(sign, subscrbuf + 4, ssb_size - 4, &signature_len);
|
||||
if (signature && signature_len > 0) {
|
||||
if (uwsgi_buffer_append_keyval(ub, "sign", 4, signature, signature_len)) {
|
||||
// add space for "sign" item
|
||||
ssb_size += 2 + 4 + 2 + signature_len;
|
||||
char *new_buf = realloc(subscrbuf, ssb_size);
|
||||
if (!new_buf) {
|
||||
uwsgi_error("realloc()");
|
||||
free(signature);
|
||||
goto end;
|
||||
free(subscrbuf);
|
||||
return;
|
||||
}
|
||||
|
||||
// fix ssb (new_buf base could be changed)
|
||||
ssb = (new_buf + (ssb - subscrbuf));
|
||||
subscrbuf = new_buf;
|
||||
|
||||
ustrlen = 4;
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ssb, "sign", ustrlen);
|
||||
ssb += ustrlen;
|
||||
|
||||
ustrlen = signature_len;
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ssb, signature, signature_len);
|
||||
ssb += ustrlen;
|
||||
|
||||
free(signature);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
send_udp_message(224, cmd, udp_address, ub->buf, ub->pos - 4);
|
||||
end:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
send_udp_message(224, cmd, udp_address, subscrbuf, ssb_size - 4);
|
||||
free(subscrbuf);
|
||||
}
|
||||
|
||||
|
||||
@@ -607,230 +756,3 @@ struct uwsgi_subscribe_slot **uwsgi_subscription_init_ht() {
|
||||
}
|
||||
return uwsgi_calloc(sizeof(struct uwsgi_subscription_slot *) * UMAX16);
|
||||
}
|
||||
|
||||
void uwsgi_subscribe(char *subscription, uint8_t cmd) {
|
||||
|
||||
size_t subfile_size;
|
||||
size_t i;
|
||||
char *key = NULL;
|
||||
int keysize = 0;
|
||||
char *modifier1 = NULL;
|
||||
int modifier1_len = 0;
|
||||
char *socket_name = NULL;
|
||||
char *udp_address = subscription;
|
||||
char *udp_port = NULL;
|
||||
char *subscription_key = NULL;
|
||||
char *sign = NULL;
|
||||
|
||||
// check for explicit socket_name
|
||||
char *equal = strchr(subscription, '=');
|
||||
if (equal) {
|
||||
socket_name = subscription;
|
||||
if (socket_name[0] == '=') {
|
||||
equal = strchr(socket_name + 1, '=');
|
||||
if (!equal)
|
||||
return;
|
||||
*equal = '\0';
|
||||
struct uwsgi_socket *us = uwsgi_get_shared_socket_by_num(atoi(socket_name + 1));
|
||||
if (!us)
|
||||
return;
|
||||
socket_name = us->name;
|
||||
}
|
||||
*equal = '\0';
|
||||
udp_address = equal + 1;
|
||||
}
|
||||
|
||||
// check for unix socket
|
||||
if (udp_address[0] != '/') {
|
||||
udp_port = strchr(udp_address, ':');
|
||||
if (!udp_port) {
|
||||
if (equal)
|
||||
*equal = '=';
|
||||
return;
|
||||
}
|
||||
subscription_key = strchr(udp_port + 1, ':');
|
||||
}
|
||||
else {
|
||||
subscription_key = strchr(udp_address + 1, ':');
|
||||
}
|
||||
|
||||
if (!subscription_key) {
|
||||
if (equal)
|
||||
*equal = '=';
|
||||
return;
|
||||
}
|
||||
|
||||
udp_address = uwsgi_concat2n(udp_address, subscription_key - udp_address, "", 0);
|
||||
|
||||
if (subscription_key[1] == '@') {
|
||||
if (!uwsgi_file_exists(subscription_key + 2))
|
||||
goto clear;
|
||||
char *lines = uwsgi_open_and_read(subscription_key + 2, &subfile_size, 1, NULL);
|
||||
if (subfile_size > 0) {
|
||||
key = lines;
|
||||
for (i = 0; i < subfile_size; i++) {
|
||||
if (lines[i] == 0) {
|
||||
if (keysize > 0) {
|
||||
if (key[0] != '#' && key[0] != '\n') {
|
||||
modifier1 = strchr(key, ',');
|
||||
if (modifier1) {
|
||||
modifier1[0] = 0;
|
||||
modifier1++;
|
||||
modifier1_len = strlen(modifier1);
|
||||
keysize = strlen(key);
|
||||
}
|
||||
uwsgi_send_subscription(udp_address, key, keysize, uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign);
|
||||
modifier1 = NULL;
|
||||
modifier1_len = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (lines[i] == '\n') {
|
||||
if (keysize > 0) {
|
||||
if (key[0] != '#' && key[0] != '\n') {
|
||||
lines[i] = 0;
|
||||
modifier1 = strchr(key, ',');
|
||||
if (modifier1) {
|
||||
modifier1[0] = 0;
|
||||
modifier1++;
|
||||
modifier1_len = strlen(modifier1);
|
||||
keysize = strlen(key);
|
||||
}
|
||||
uwsgi_send_subscription(udp_address, key, keysize, uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign);
|
||||
modifier1 = NULL;
|
||||
modifier1_len = 0;
|
||||
lines[i] = '\n';
|
||||
}
|
||||
}
|
||||
key = lines + i + 1;
|
||||
keysize = 0;
|
||||
continue;
|
||||
}
|
||||
keysize++;
|
||||
}
|
||||
|
||||
free(lines);
|
||||
}
|
||||
}
|
||||
else {
|
||||
modifier1 = strchr(subscription_key + 1, ',');
|
||||
if (modifier1) {
|
||||
modifier1[0] = 0;
|
||||
modifier1++;
|
||||
|
||||
sign = strchr(modifier1 + 1, ',');
|
||||
if (sign) {
|
||||
*sign = 0;
|
||||
sign++;
|
||||
}
|
||||
modifier1_len = strlen(modifier1);
|
||||
}
|
||||
|
||||
uwsgi_send_subscription(udp_address, subscription_key + 1, strlen(subscription_key + 1), uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign);
|
||||
if (modifier1)
|
||||
modifier1[-1] = ',';
|
||||
if (sign)
|
||||
sign[-1] = ',';
|
||||
}
|
||||
|
||||
clear:
|
||||
if (equal)
|
||||
*equal = '=';
|
||||
free(udp_address);
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_subscribe2(char *arg, uint8_t cmd) {
|
||||
|
||||
char *s2_server = NULL;
|
||||
char *s2_key = NULL;
|
||||
char *s2_socket = NULL;
|
||||
char *s2_addr = NULL;
|
||||
char *s2_weight = NULL;
|
||||
char *s2_sign = NULL;
|
||||
char *s2_modifier1 = NULL;
|
||||
char *s2_modifier2 = NULL;
|
||||
char *s2_check = NULL;
|
||||
|
||||
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
|
||||
"server", &s2_server,
|
||||
"key", &s2_key,
|
||||
"socket", &s2_socket,
|
||||
"addr", &s2_addr,
|
||||
"weight", &s2_weight,
|
||||
"modifier1", &s2_modifier1,
|
||||
"modifier2", &s2_modifier2,
|
||||
"sign", &s2_sign,
|
||||
"check", &s2_check,
|
||||
NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!s2_server || !s2_key) goto end;
|
||||
|
||||
if (s2_check) {
|
||||
if (uwsgi_file_exists(s2_check)) goto end;
|
||||
}
|
||||
|
||||
if (s2_weight) {
|
||||
uwsgi.weight = atoi(s2_weight);
|
||||
}
|
||||
|
||||
if (s2_socket) {
|
||||
struct uwsgi_socket *us = uwsgi_get_socket_by_num(atoi(s2_socket));
|
||||
if (us) {
|
||||
if (s2_addr) {
|
||||
free(s2_addr);
|
||||
}
|
||||
s2_addr = uwsgi_str(us->name);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t modifier1 = 0;
|
||||
uint8_t modifier2 = 0;
|
||||
|
||||
if (s2_modifier1) {
|
||||
modifier1 = atoi(s2_modifier1);
|
||||
}
|
||||
|
||||
if (s2_modifier2) {
|
||||
modifier2 = atoi(s2_modifier2);
|
||||
}
|
||||
|
||||
uwsgi_send_subscription(s2_server, s2_key, strlen(s2_key), modifier1, modifier2, cmd, s2_addr, s2_sign);
|
||||
end:
|
||||
if (s2_server) free(s2_server);
|
||||
if (s2_key) free(s2_key);
|
||||
if (s2_socket) free(s2_socket);
|
||||
if (s2_addr) free(s2_addr);
|
||||
if (s2_weight) free(s2_weight);
|
||||
if (s2_modifier1) free(s2_modifier1);
|
||||
if (s2_modifier2) free(s2_modifier2);
|
||||
if (s2_sign) free(s2_sign);
|
||||
if (s2_check) free(s2_check);
|
||||
}
|
||||
|
||||
void uwsgi_subscribe_all(uint8_t cmd, int verbose) {
|
||||
// -- subscribe
|
||||
struct uwsgi_string_list *subscriptions = uwsgi.subscriptions;
|
||||
while (subscriptions) {
|
||||
if (verbose) {
|
||||
uwsgi_log("%s %s\n", cmd ? "unsubscribing from" : "subscribing to", subscriptions->value);
|
||||
}
|
||||
uwsgi_subscribe(subscriptions->value, cmd);
|
||||
subscriptions = subscriptions->next;
|
||||
}
|
||||
|
||||
// --subscribe2
|
||||
subscriptions = uwsgi.subscriptions2;
|
||||
while (subscriptions) {
|
||||
if (verbose) {
|
||||
uwsgi_log("%s %s\n", cmd ? "unsubscribing from" : "subscribing to", subscriptions->value);
|
||||
}
|
||||
uwsgi_subscribe2(subscriptions->value, cmd);
|
||||
subscriptions = subscriptions->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
uWSGI timebomb
|
||||
|
||||
this is a simple thread waiting for a timeout and calling exit
|
||||
with the specified value.
|
||||
|
||||
You can use it as a last resort in async apps that could block
|
||||
normal uWSGI behaviours
|
||||
|
||||
*/
|
||||
|
||||
struct time_bomb {
|
||||
int timeout;
|
||||
int exit_code;
|
||||
};
|
||||
|
||||
static void *time_bomb(void *arg) {
|
||||
|
||||
// block all signals
|
||||
sigset_t smask;
|
||||
sigfillset(&smask);
|
||||
pthread_sigmask(SIG_BLOCK, &smask, NULL);
|
||||
|
||||
struct time_bomb *tb = (struct time_bomb *) arg;
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = tb->timeout;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
select(0, NULL, NULL, NULL, &tv);
|
||||
uwsgi_log_verbose("*** BOOOOOOM ***\n");
|
||||
exit(tb->exit_code);
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_time_bomb(int timeout, int exit_code) {
|
||||
|
||||
pthread_t time_bomb_thread;
|
||||
|
||||
struct time_bomb *tb = uwsgi_malloc(sizeof(struct time_bomb));
|
||||
tb->timeout = timeout;
|
||||
tb->exit_code = exit_code;
|
||||
|
||||
if (pthread_create(&time_bomb_thread, NULL, time_bomb, (void *) tb)) {
|
||||
uwsgi_error("pthread_create()");
|
||||
uwsgi_log("unable to setup the time bomb, goodbye\n");
|
||||
exit(exit_code);
|
||||
}
|
||||
else {
|
||||
uwsgi_log_verbose("Fire in the hole !!! (%d seconds to detonation)\n", timeout);
|
||||
}
|
||||
|
||||
}
|
||||
+1848
-465
File diff suppressed because it is too large
Load Diff
+349
-328
File diff suppressed because it is too large
Load Diff
@@ -1,359 +0,0 @@
|
||||
#include "uwsgi.h"
|
||||
|
||||
/*
|
||||
|
||||
uWSGI websockets functions
|
||||
|
||||
sponsored by 20Tab S.r.l. <info@20tab.com>
|
||||
|
||||
*/
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
static struct uwsgi_buffer *uwsgi_websocket_message(char *msg, size_t len) {
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(10 + len);
|
||||
if (uwsgi_buffer_u8(ub, 0x81)) goto error;
|
||||
if (len < 126) {
|
||||
if (uwsgi_buffer_u8(ub, len)) goto error;
|
||||
}
|
||||
else if (len <= (uint16_t) 0xffff) {
|
||||
if (uwsgi_buffer_u8(ub, 126)) goto error;
|
||||
if (uwsgi_buffer_u16be(ub, len)) goto error;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_buffer_u8(ub, 127)) goto error;
|
||||
if (uwsgi_buffer_u64be(ub, len)) goto error;
|
||||
}
|
||||
|
||||
if (uwsgi_buffer_append(ub, msg, len)) goto error;
|
||||
return ub;
|
||||
|
||||
error:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int uwsgi_websockets_ping(struct wsgi_request *wsgi_req) {
|
||||
if (uwsgi_response_write_body_do(wsgi_req, uwsgi.websockets_ping->buf, uwsgi.websockets_ping->pos)) {
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->websocket_last_ping = uwsgi_now();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_websockets_pong(struct wsgi_request *wsgi_req) {
|
||||
return uwsgi_response_write_body_do(wsgi_req, uwsgi.websockets_pong->buf, uwsgi.websockets_pong->pos);
|
||||
}
|
||||
|
||||
static int uwsgi_websockets_check_pingpong(struct wsgi_request *wsgi_req) {
|
||||
time_t now = uwsgi_now();
|
||||
// first round
|
||||
if (wsgi_req->websocket_last_ping == 0) {
|
||||
return uwsgi_websockets_ping(wsgi_req);
|
||||
}
|
||||
// pong not received ?
|
||||
if (wsgi_req->websocket_last_pong < wsgi_req->websocket_last_ping) {
|
||||
if (wsgi_req->websocket_last_ping - wsgi_req->websocket_last_pong > uwsgi.websockets_pong_tolerance) {
|
||||
uwsgi_log("[uwsgi-websocket] no PONG received in %d seconds !!!\n", uwsgi.websockets_pong_tolerance);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
// pong received, send anther ping
|
||||
if (now - wsgi_req->websocket_last_ping >= uwsgi.websockets_ping_freq) {
|
||||
return uwsgi_websockets_ping(wsgi_req);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_websocket_send_do(struct wsgi_request *wsgi_req, char *msg, size_t len) {
|
||||
struct uwsgi_buffer *ub = uwsgi_websocket_message(msg, len);
|
||||
if (!ub) return -1;
|
||||
|
||||
ssize_t ret = uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_websocket_send(struct wsgi_request *wsgi_req, char *msg, size_t len) {
|
||||
if (wsgi_req->websocket_closed) {
|
||||
return -1;
|
||||
}
|
||||
ssize_t ret = uwsgi_websocket_send_do(wsgi_req, msg, len);
|
||||
if (ret < 0) {
|
||||
wsgi_req->websocket_closed = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void uwsgi_websocket_parse_header(struct wsgi_request *wsgi_req) {
|
||||
uint8_t byte1 = wsgi_req->websocket_buf->buf[0];
|
||||
uint8_t byte2 = wsgi_req->websocket_buf->buf[1];
|
||||
wsgi_req->websocket_opcode = byte1 & 0xf;
|
||||
wsgi_req->websocket_has_mask = byte2 >> 7;
|
||||
wsgi_req->websocket_size = byte2 & 0x7f;
|
||||
}
|
||||
|
||||
static struct uwsgi_buffer *uwsgi_websockets_parse(struct wsgi_request *wsgi_req) {
|
||||
// de-mask buffer
|
||||
uint8_t *ptr = (uint8_t *) (wsgi_req->websocket_buf->buf + (wsgi_req->websocket_pktsize - wsgi_req->websocket_size));
|
||||
size_t i;
|
||||
|
||||
if (wsgi_req->websocket_has_mask) {
|
||||
uint8_t *mask = ptr-4;
|
||||
for(i=0;i<wsgi_req->websocket_size;i++) {
|
||||
ptr[i] = ptr[i] ^ mask[i%4];
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(wsgi_req->websocket_size);
|
||||
if (uwsgi_buffer_append(ub, (char *) ptr, wsgi_req->websocket_size)) goto error;
|
||||
if (uwsgi_buffer_decapitate(wsgi_req->websocket_buf, wsgi_req->websocket_pktsize)) goto error;
|
||||
wsgi_req->websocket_phase = 0;
|
||||
wsgi_req->websocket_need = 2;
|
||||
return ub;
|
||||
error:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t uwsgi_websockets_recv_pkt(struct wsgi_request *wsgi_req, int nb) {
|
||||
|
||||
int ret = -1;
|
||||
|
||||
for(;;) {
|
||||
ssize_t rlen = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->websocket_buf->buf + wsgi_req->websocket_buf->pos, wsgi_req->websocket_buf->len - wsgi_req->websocket_buf->pos);
|
||||
if (rlen > 0) return rlen;
|
||||
if (rlen == 0) return -1;
|
||||
if (rlen < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
if (nb) {
|
||||
if (uwsgi_websockets_check_pingpong(wsgi_req)) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
goto wait;
|
||||
}
|
||||
uwsgi_error("uwsgi_websockets_recv_pkt()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
wait:
|
||||
ret = uwsgi.wait_read_hook(wsgi_req->fd, uwsgi.websockets_ping_freq);
|
||||
if (ret > 0) {
|
||||
rlen = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->websocket_buf->buf + wsgi_req->websocket_buf->pos, wsgi_req->websocket_buf->len - wsgi_req->websocket_buf->pos);
|
||||
if (rlen > 0) return rlen;
|
||||
if (rlen <= 0) return -1;
|
||||
}
|
||||
if (ret < 0) {
|
||||
uwsgi_error("uwsgi_websockets_recv_pkt()");
|
||||
return -1;
|
||||
}
|
||||
// send unsolicited pong
|
||||
if (uwsgi_websockets_check_pingpong(wsgi_req)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static struct uwsgi_buffer *uwsgi_websocket_recv_do(struct wsgi_request *wsgi_req, int nb) {
|
||||
if (!wsgi_req->websocket_buf) {
|
||||
// this buffer will be destroyed on connection close
|
||||
wsgi_req->websocket_buf = uwsgi_buffer_new(uwsgi.page_size);
|
||||
// need 2 byte header
|
||||
wsgi_req->websocket_need = 2;
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
size_t remains = wsgi_req->websocket_buf->pos;
|
||||
// i have data;
|
||||
if (remains >= wsgi_req->websocket_need) {
|
||||
switch(wsgi_req->websocket_phase) {
|
||||
// header
|
||||
case 0:
|
||||
uwsgi_websocket_parse_header(wsgi_req);
|
||||
wsgi_req->websocket_pktsize = 2 + (wsgi_req->websocket_has_mask*4);
|
||||
if (wsgi_req->websocket_size == 126) {
|
||||
wsgi_req->websocket_need += 2;
|
||||
wsgi_req->websocket_phase = 1;
|
||||
wsgi_req->websocket_pktsize += 2;
|
||||
}
|
||||
else if (wsgi_req->websocket_size == 127) {
|
||||
wsgi_req->websocket_need += 8;
|
||||
wsgi_req->websocket_phase = 1;
|
||||
wsgi_req->websocket_pktsize += 8;
|
||||
}
|
||||
else {
|
||||
wsgi_req->websocket_phase = 2;
|
||||
}
|
||||
break;
|
||||
// size
|
||||
case 1:
|
||||
if (wsgi_req->websocket_size == 126) {
|
||||
wsgi_req->websocket_size = uwsgi_be16(wsgi_req->websocket_buf->buf+2);
|
||||
}
|
||||
else if (wsgi_req->websocket_size == 127) {
|
||||
wsgi_req->websocket_size = uwsgi_be64(wsgi_req->websocket_buf->buf+2);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[uwsgi-websocket] BUG error in websocket parser\n");
|
||||
return NULL;
|
||||
}
|
||||
if (wsgi_req->websocket_size > (uwsgi.websockets_max_size*1024)) {
|
||||
uwsgi_log("[uwsgi-websocket] invalid packet size received: %llu, max allowed: %llu\n", wsgi_req->websocket_size, uwsgi.websockets_max_size * 1024);
|
||||
return NULL;
|
||||
}
|
||||
wsgi_req->websocket_phase = 2;
|
||||
break;
|
||||
// mask check
|
||||
case 2:
|
||||
if (wsgi_req->websocket_has_mask) {
|
||||
wsgi_req->websocket_need += 4;
|
||||
wsgi_req->websocket_phase = 3;
|
||||
}
|
||||
else {
|
||||
wsgi_req->websocket_need += wsgi_req->websocket_size;
|
||||
wsgi_req->websocket_phase = 4;
|
||||
}
|
||||
break;
|
||||
// mask
|
||||
case 3:
|
||||
wsgi_req->websocket_pktsize += wsgi_req->websocket_size;
|
||||
wsgi_req->websocket_need += wsgi_req->websocket_size;
|
||||
wsgi_req->websocket_phase = 4;
|
||||
break;
|
||||
// message
|
||||
case 4:
|
||||
switch (wsgi_req->websocket_opcode) {
|
||||
// message
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
return uwsgi_websockets_parse(wsgi_req);
|
||||
// close
|
||||
case 0x8:
|
||||
return NULL;
|
||||
// ping
|
||||
case 0x9:
|
||||
if (uwsgi_websockets_pong(wsgi_req)) {
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
// pong
|
||||
case 0xA:
|
||||
wsgi_req->websocket_last_pong = uwsgi_now();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// reset the status
|
||||
wsgi_req->websocket_phase = 0;
|
||||
wsgi_req->websocket_need = 2;
|
||||
// decapitate the buffer
|
||||
if (uwsgi_buffer_decapitate(wsgi_req->websocket_buf, wsgi_req->websocket_pktsize)) return NULL;
|
||||
break;
|
||||
// oops
|
||||
default:
|
||||
uwsgi_log("[uwsgi-websocket] BUG error in websocket parser\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
// need more data
|
||||
else {
|
||||
if (uwsgi_buffer_ensure(wsgi_req->websocket_buf, uwsgi.page_size)) return NULL;
|
||||
ssize_t len = uwsgi_websockets_recv_pkt(wsgi_req, nb);
|
||||
if (len <= 0) {
|
||||
if (nb == 1 && len == 0) {
|
||||
// return an empty buffer to signal blocking event
|
||||
return uwsgi_buffer_new(0);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
// update buffer size
|
||||
wsgi_req->websocket_buf->pos+=len;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *uwsgi_websocket_recv(struct wsgi_request *wsgi_req) {
|
||||
if (wsgi_req->websocket_closed) {
|
||||
return NULL;
|
||||
}
|
||||
struct uwsgi_buffer *ub = uwsgi_websocket_recv_do(wsgi_req, 0);
|
||||
if (!ub) {
|
||||
wsgi_req->websocket_closed = 1;
|
||||
}
|
||||
return ub;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *uwsgi_websocket_recv_nb(struct wsgi_request *wsgi_req) {
|
||||
if (wsgi_req->websocket_closed) {
|
||||
return NULL;
|
||||
}
|
||||
struct uwsgi_buffer *ub = uwsgi_websocket_recv_do(wsgi_req, 1);
|
||||
if (!ub) {
|
||||
wsgi_req->websocket_closed = 1;
|
||||
}
|
||||
return ub;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ssize_t uwsgi_websockets_simple_send(struct wsgi_request *wsgi_req, struct uwsgi_buffer *ub) {
|
||||
ssize_t len = wsgi_req->socket->proto_write(wsgi_req, ub->buf, ub->pos);
|
||||
if (wsgi_req->write_errors > 0) {
|
||||
return -1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int uwsgi_websocket_handshake(struct wsgi_request *wsgi_req, char *key, uint16_t key_len, char *origin, uint16_t origin_len) {
|
||||
#ifdef UWSGI_SSL
|
||||
char sha1[20];
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "101 Web Socket Protocol Handshake", 33)) return -1;
|
||||
if (uwsgi_response_add_header(wsgi_req, "Upgrade", 7, "WebSocket", 9)) return -1;
|
||||
if (uwsgi_response_add_header(wsgi_req, "Connection", 10, "Upgrade", 7)) return -1;
|
||||
if (origin_len > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Sec-WebSocket-Origin", 20, origin, origin_len)) return -1;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Sec-WebSocket-Origin", 20, "*", 1)) return -1;
|
||||
}
|
||||
// generate websockets sha1 and encode it to base64
|
||||
if (!uwsgi_sha1_2n(key, key_len, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", 36, sha1)) return -1;
|
||||
size_t b64_len = 0;
|
||||
char *b64 = uwsgi_base64_encode(sha1, 20, &b64_len);
|
||||
if (!b64) return -1;
|
||||
|
||||
if (uwsgi_response_add_header(wsgi_req, "Sec-WebSocket-Accept", 20, b64, b64_len)) {
|
||||
free(b64);
|
||||
return -1;
|
||||
}
|
||||
free(b64);
|
||||
|
||||
wsgi_req->websocket_last_pong = uwsgi_now();
|
||||
|
||||
return uwsgi_response_write_headers_do(wsgi_req);
|
||||
#else
|
||||
uwsgi_log("you need to build uWSGI with SSL support to use the websocket handshake api function !!!\n");
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void uwsgi_websockets_init() {
|
||||
uwsgi.websockets_pong = uwsgi_buffer_new(2);
|
||||
uwsgi_buffer_append(uwsgi.websockets_pong, "\x8A\0", 2);
|
||||
uwsgi.websockets_ping = uwsgi_buffer_new(2);
|
||||
uwsgi_buffer_append(uwsgi.websockets_ping, "\x89\0", 2);
|
||||
uwsgi.websockets_ping_freq = 30;
|
||||
uwsgi.websockets_pong_tolerance = 3;
|
||||
uwsgi.websockets_max_size = 1024;
|
||||
}
|
||||
-299
@@ -1,299 +0,0 @@
|
||||
#include "uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int uwsgi_response_add_content_length(struct wsgi_request *wsgi_req, uint64_t cl) {
|
||||
char buf[sizeof(UMAX64_STR)+1];
|
||||
int ret = snprintf(buf, sizeof(UMAX64_STR)+1, "%llu", (unsigned long long) cl);
|
||||
if (ret <= 0 || ret > (int) (sizeof(UMAX64_STR)+1)) {
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
return uwsgi_response_add_header(wsgi_req, "Content-Length", 14, buf, ret);
|
||||
}
|
||||
|
||||
// status could be NNN or NNN message
|
||||
int uwsgi_response_prepare_headers(struct wsgi_request *wsgi_req, char *status, uint16_t status_len) {
|
||||
|
||||
if (wsgi_req->headers_sent || wsgi_req->headers_size || wsgi_req->response_size || status_len < 3 || wsgi_req->write_errors) return -1;
|
||||
|
||||
if (!wsgi_req->headers) {
|
||||
wsgi_req->headers = uwsgi_buffer_new(uwsgi.page_size);
|
||||
wsgi_req->headers->limit = UMAX16;
|
||||
}
|
||||
|
||||
// reset the buffer (could be useful for rollbacks...)
|
||||
wsgi_req->headers->pos = 0;
|
||||
struct uwsgi_buffer *hh = NULL;
|
||||
if (status_len <= 4) {
|
||||
char *new_sc = NULL;
|
||||
size_t new_sc_len = 0;
|
||||
uint16_t sc_len = 0;
|
||||
const char *sc = uwsgi_http_status_msg(status, &sc_len);
|
||||
if (sc) {
|
||||
new_sc = uwsgi_concat3n(status, 3, " ", 1, (char *)sc, sc_len);
|
||||
new_sc_len = 4+sc_len;
|
||||
}
|
||||
else {
|
||||
new_sc = uwsgi_concat2n(status, 3, " Unknown", 8);
|
||||
new_sc_len = 11;
|
||||
}
|
||||
hh = wsgi_req->socket->proto_prepare_headers(wsgi_req, new_sc, new_sc_len);
|
||||
free(new_sc);
|
||||
}
|
||||
else {
|
||||
hh = wsgi_req->socket->proto_prepare_headers(wsgi_req, status, status_len);
|
||||
}
|
||||
if (!hh) {wsgi_req->write_errors++; return -1;}
|
||||
if (uwsgi_buffer_append(wsgi_req->headers, hh->buf, hh->pos)) goto error;
|
||||
uwsgi_buffer_destroy(hh);
|
||||
wsgi_req->status = uwsgi_str3_num(status);
|
||||
return 0;
|
||||
error:
|
||||
uwsgi_buffer_destroy(hh);
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//each protocol has its header generator
|
||||
int uwsgi_response_add_header(struct wsgi_request *wsgi_req, char *key, uint16_t key_len, char *value, uint16_t value_len) {
|
||||
|
||||
if (wsgi_req->headers_sent || wsgi_req->headers_size || wsgi_req->response_size || wsgi_req->write_errors) return -1;
|
||||
|
||||
struct uwsgi_string_list *rh = uwsgi.remove_headers;
|
||||
while(rh) {
|
||||
if (!uwsgi_strnicmp(key, key_len, rh->value, rh->len)) {
|
||||
return 0;
|
||||
}
|
||||
rh = rh->next;
|
||||
}
|
||||
rh = wsgi_req->remove_headers;
|
||||
while(rh) {
|
||||
if (!uwsgi_strnicmp(key, key_len, rh->value, rh->len)) {
|
||||
return 0;
|
||||
}
|
||||
rh = rh->next;
|
||||
}
|
||||
|
||||
if (!wsgi_req->headers) {
|
||||
wsgi_req->headers = uwsgi_buffer_new(uwsgi.page_size);
|
||||
wsgi_req->headers->limit = UMAX16;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *hh = wsgi_req->socket->proto_add_header(wsgi_req, key, key_len, value, value_len);
|
||||
if (!hh) { wsgi_req->write_errors++ ; return -1;}
|
||||
if (uwsgi_buffer_append(wsgi_req->headers, hh->buf, hh->pos)) goto error;
|
||||
wsgi_req->header_cnt++;
|
||||
uwsgi_buffer_destroy(hh);
|
||||
return 0;
|
||||
error:
|
||||
uwsgi_buffer_destroy(hh);
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
|
||||
if (wsgi_req->headers_sent || !wsgi_req->headers || wsgi_req->response_size || wsgi_req->write_errors) {
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *ah = uwsgi.additional_headers;
|
||||
while(ah) {
|
||||
if (uwsgi_response_add_header(wsgi_req, NULL, 0, ah->value, ah->len)) return -1;
|
||||
ah = ah->next;
|
||||
}
|
||||
|
||||
ah = wsgi_req->additional_headers;
|
||||
while(ah) {
|
||||
if (uwsgi_response_add_header(wsgi_req, NULL, 0, ah->value, ah->len)) return -1;
|
||||
ah = ah->next;
|
||||
}
|
||||
|
||||
|
||||
if (wsgi_req->socket->proto_fix_headers(wsgi_req)) { wsgi_req->write_errors++ ; return -1;}
|
||||
|
||||
for(;;) {
|
||||
int ret = wsgi_req->socket->proto_write_headers(wsgi_req, wsgi_req->headers->buf, wsgi_req->headers->pos);
|
||||
if (ret < 0) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_error("uwsgi_response_write_headers_do()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
if (ret == UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
ret = uwsgi_wait_write_req(wsgi_req);
|
||||
if (ret < 0) { wsgi_req->write_errors++; return -1;}
|
||||
if (ret == 0) {
|
||||
uwsgi_log("uwsgi_response_write_headers_do() TIMEOUT !!!\n");
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
wsgi_req->headers_size += wsgi_req->write_pos;
|
||||
// reset for the next write
|
||||
wsgi_req->write_pos = 0;
|
||||
wsgi_req->headers_sent = 1;
|
||||
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
|
||||
if (wsgi_req->write_errors) return -1;
|
||||
|
||||
if (!wsgi_req->headers_sent) {
|
||||
int ret = uwsgi_response_write_headers_do(wsgi_req);
|
||||
if (ret == UWSGI_OK) goto sendbody;
|
||||
if (ret == UWSGI_AGAIN) return UWSGI_AGAIN;
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
|
||||
sendbody:
|
||||
|
||||
if (len == 0) return UWSGI_OK;
|
||||
|
||||
for(;;) {
|
||||
int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
|
||||
if (ret < 0) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_error("uwsgi_response_write_body_do()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
if (ret == UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
ret = uwsgi_wait_write_req(wsgi_req);
|
||||
if (ret < 0) { wsgi_req->write_errors++; return -1;}
|
||||
if (ret == 0) {
|
||||
uwsgi_log("uwsgi_response_write_body_do() TIMEOUT !!!\n");
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
wsgi_req->response_size += wsgi_req->write_pos;
|
||||
// reset for the next write
|
||||
wsgi_req->write_pos = 0;
|
||||
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
int uwsgi_response_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t pos, size_t len) {
|
||||
|
||||
int can_close = 1;
|
||||
|
||||
if (fd == wsgi_req->sendfile_fd) can_close = 0;
|
||||
|
||||
if (wsgi_req->write_errors) return -1;
|
||||
|
||||
if (!wsgi_req->headers_sent) {
|
||||
int ret = uwsgi_response_write_headers_do(wsgi_req);
|
||||
if (ret == UWSGI_OK) goto sendfile;
|
||||
if (ret == UWSGI_AGAIN) return UWSGI_AGAIN;
|
||||
wsgi_req->write_errors++;
|
||||
if (can_close) close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sendfile:
|
||||
|
||||
if (len == 0) {
|
||||
struct stat st;
|
||||
if (fstat(fd, &st)) {
|
||||
uwsgi_error("fstat()");
|
||||
wsgi_req->write_errors++;
|
||||
if (can_close) close(fd);
|
||||
return -1;
|
||||
}
|
||||
len = st.st_size;
|
||||
}
|
||||
|
||||
if (wsgi_req->socket->can_offload) {
|
||||
// of we cannot close the socket (before the app will close it later)
|
||||
// let's dup it
|
||||
if (!can_close) {
|
||||
int tmp_fd = dup(fd);
|
||||
if (tmp_fd < 0) {
|
||||
uwsgi_error("uwsgi_response_sendfile_do()/dup()");
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
fd = tmp_fd;
|
||||
can_close = 1;
|
||||
}
|
||||
if (!uwsgi_offload_request_sendfile_do(wsgi_req, fd, len)) {
|
||||
wsgi_req->via = UWSGI_VIA_OFFLOAD;
|
||||
wsgi_req->response_size += len;
|
||||
return 0;
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
if (can_close) close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
wsgi_req->via = UWSGI_VIA_SENDFILE;
|
||||
|
||||
for(;;) {
|
||||
int ret = wsgi_req->socket->proto_sendfile(wsgi_req, fd, pos, len);
|
||||
if (ret < 0) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_error("uwsgi_response_sendfile_do()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
if (can_close) close(fd);
|
||||
return -1;
|
||||
}
|
||||
if (ret == UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
ret = uwsgi_wait_write_req(wsgi_req);
|
||||
if (ret < 0) {
|
||||
wsgi_req->write_errors++;
|
||||
if (can_close) close(fd);
|
||||
return -1;
|
||||
}
|
||||
if (ret == 0) {
|
||||
uwsgi_log("uwsgi_response_sendfile_do() TIMEOUT !!!\n");
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
wsgi_req->response_size += wsgi_req->write_pos;
|
||||
// reset for the next write
|
||||
wsgi_req->write_pos = 0;
|
||||
// close the file descriptor
|
||||
if (can_close) close(fd);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_simple_wait_write_hook(int fd, int timeout) {
|
||||
struct pollfd upoll;
|
||||
timeout = timeout * 1000;
|
||||
|
||||
upoll.fd = fd;
|
||||
upoll.events = POLLOUT;
|
||||
upoll.revents = 0;
|
||||
int ret = poll(&upoll, 1, timeout);
|
||||
|
||||
if (ret > 0) {
|
||||
if (upoll.revents & POLLOUT) {
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (ret < 0) {
|
||||
uwsgi_error("uwsgi_simple_wait_write_hook()/poll()");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
+3
-3
@@ -20,7 +20,7 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic
|
||||
|
||||
char *xml_id;
|
||||
char *xml_content;
|
||||
size_t xml_size = 0;
|
||||
int xml_size = 0;
|
||||
|
||||
if (uwsgi_check_scheme(filename)) {
|
||||
colon = uwsgi_get_last_char(filename, '/');
|
||||
@@ -47,7 +47,7 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_log_initial("[uWSGI] parsing config file %s\n", filename);
|
||||
uwsgi_log("[uWSGI] parsing config file %s\n", filename);
|
||||
|
||||
element = xmlDocGetRootElement(doc);
|
||||
if (element == NULL) {
|
||||
@@ -221,7 +221,7 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic
|
||||
char *colon;
|
||||
|
||||
char *xml_content;
|
||||
size_t xml_size = 0;
|
||||
int xml_size = 0;
|
||||
int done = 0;
|
||||
|
||||
if (uwsgi_check_scheme(filename)) {
|
||||
|
||||
+4
-4
@@ -61,9 +61,9 @@ int yaml_get_depth(char *line) {
|
||||
return depth;
|
||||
}
|
||||
|
||||
char *yaml_get_line(char *yaml, size_t size) {
|
||||
char *yaml_get_line(char *yaml, off_t size) {
|
||||
|
||||
size_t i;
|
||||
off_t i;
|
||||
char *ptr = yaml;
|
||||
int comment = 0;
|
||||
|
||||
@@ -96,7 +96,7 @@ char *yaml_get_line(char *yaml, size_t size) {
|
||||
|
||||
void uwsgi_yaml_config(char *file, char *magic_table[]) {
|
||||
|
||||
size_t len = 0;
|
||||
int len = 0;
|
||||
char *yaml;
|
||||
|
||||
int in_uwsgi_section = 0;
|
||||
@@ -122,7 +122,7 @@ void uwsgi_yaml_config(char *file, char *magic_table[]) {
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log_initial("[uWSGI] getting YAML configuration from %s\n", file);
|
||||
uwsgi_log("[uWSGI] getting YAML configuration from %s\n", file);
|
||||
|
||||
yaml = uwsgi_open_and_read(file, &len, 1, magic_table);
|
||||
|
||||
|
||||
-55
@@ -1,55 +0,0 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
|
||||
int uwsgi_deflate_init(z_stream *z, char *dict, size_t dict_len) {
|
||||
z->zalloc = Z_NULL;
|
||||
z->zfree = Z_NULL;
|
||||
z->opaque = Z_NULL;
|
||||
if (deflateInit2(z, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15, 9, Z_DEFAULT_STRATEGY) != Z_OK) {
|
||||
//if (deflateInit(z, Z_DEFAULT_COMPRESSION)) {
|
||||
return -1;
|
||||
}
|
||||
if (dict && dict_len) {
|
||||
if (deflateSetDictionary(z, (Bytef *) dict, dict_len) != Z_OK) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
char *uwsgi_deflate(z_stream *z, char *buf, size_t len, size_t *dlen) {
|
||||
|
||||
// calculate the amount of bytes needed for output (+30 should be enough)
|
||||
Bytef *dbuf = uwsgi_malloc(len+30);
|
||||
z->avail_in = len;
|
||||
z->next_in = (Bytef *) buf;
|
||||
z->avail_out = len+30;
|
||||
z->next_out = dbuf;
|
||||
|
||||
if (len > 0) {
|
||||
if (deflate(z, Z_SYNC_FLUSH) != Z_OK) {
|
||||
free(dbuf);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (deflate(z, Z_FINISH) != Z_STREAM_END) {
|
||||
free(dbuf);
|
||||
return NULL;
|
||||
}
|
||||
deflateEnd(z);
|
||||
}
|
||||
|
||||
*dlen = (z->next_out - dbuf);
|
||||
return (char *) dbuf;
|
||||
}
|
||||
|
||||
void uwsgi_crc32(uint32_t *ctx, char *buf, size_t len) {
|
||||
if (!buf) {
|
||||
*ctx = crc32(*ctx, Z_NULL, 0);
|
||||
}
|
||||
else {
|
||||
*ctx = crc32(*ctx, (const Bytef *) buf, len);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
{% extends "admin/base_site.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
|
||||
{% block breadcrumbs %}
|
||||
<div class="breadcrumbs">
|
||||
<a href="../">{% trans 'Home' %}</a> ›
|
||||
{% trans 'uWSGI' %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<div id="content-main">
|
||||
<h1>uWSGI status</h1>
|
||||
<b>masterpid:</b> {{masterpid}}<br/>
|
||||
<b>started_on:</b> {{started_on}}<br/>
|
||||
<b>buffer size:</b> {{buffer_size}}<br/>
|
||||
<b>workers:</b> {{numproc}}<br/>
|
||||
<b>total requests:</b> {{total_requests}}<br/>
|
||||
|
||||
<br/>
|
||||
|
||||
<div class="module" style="width:860px">
|
||||
<table>
|
||||
<caption style="width:860px">workers</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="row">id</th>
|
||||
<th scope="row">pid</th>
|
||||
<th scope="row">requests</th>
|
||||
<th scope="row">running time (milliseconds)</th>
|
||||
<th scope="row">load</th>
|
||||
<th scope="row">last spawn</th>
|
||||
<th scope="row">respawn count</th>
|
||||
<th scope="row">address space (vsz)</th>
|
||||
<th scope="row">resident memory (rss)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for w in workers %}
|
||||
<tr>
|
||||
<td align="center">{{w.id}}</td>
|
||||
<td align="center">{{w.pid}}</td>
|
||||
<td align="right">{{w.requests}}</td>
|
||||
<td align="right">{{w.running_time}}</td>
|
||||
<td align="right">{{w.load|floatformat:2}} %</td>
|
||||
<td align="right">{{w.last_spawn_str}}</td>
|
||||
<td align="right">{{w.respawn_count}}</td>
|
||||
<td align="right">{{w.vsz|filesizeformat}}</td>
|
||||
<td align="right">{{w.rss|filesizeformat}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="module" style="width:860px">
|
||||
<table>
|
||||
<caption style="width:860px">spooler jobs</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="row">job filename</th>
|
||||
<th scope="row">environment</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for j in jobs %}
|
||||
<tr>
|
||||
<td align="left">{{j.file}}</td>
|
||||
<td align="left">{{j.env}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{% if masterpid %}
|
||||
<br/>
|
||||
<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="reload/" method="post">
|
||||
{% csrf_token %}
|
||||
<input type="submit" value="gracefully reload uWSGI" name="_reload"/>
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import sys, os
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from django.conf.urls.defaults import *
|
||||
|
||||
urlpatterns = patterns('uwsgi_admin.views',
|
||||
(r'^$', 'index'),
|
||||
(r'^reload/$', 'reload')
|
||||
)
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import uwsgi
|
||||
import time
|
||||
from django.shortcuts import render_to_response
|
||||
from django.template import RequestContext
|
||||
from django.contrib.admin.views.decorators import staff_member_required
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http import HttpResponseRedirect
|
||||
|
||||
|
||||
def index(request):
|
||||
workers = uwsgi.workers()
|
||||
total_load = time.time() - uwsgi.started_on
|
||||
for w in workers:
|
||||
w['load'] = (100 * (w['running_time']/1000))/total_load
|
||||
w['last_spawn_str'] = time.ctime(w['last_spawn'])
|
||||
|
||||
jobs = []
|
||||
if 'spooler' in uwsgi.opt:
|
||||
spooler_jobs = uwsgi.spooler_jobs()
|
||||
for j in spooler_jobs:
|
||||
jobs.append({'file': j, 'env': uwsgi.parsefile(j)})
|
||||
|
||||
return render_to_response('uwsgi.html', {'masterpid': uwsgi.masterpid(),
|
||||
'started_on': time.ctime(uwsgi.started_on),
|
||||
'buffer_size': uwsgi.buffer_size,
|
||||
'total_requests': uwsgi.total_requests(),
|
||||
'numproc': uwsgi.numproc,
|
||||
'workers': workers,
|
||||
'jobs': jobs,
|
||||
}, RequestContext(request, {}))
|
||||
index = staff_member_required(index)
|
||||
|
||||
def reload(request):
|
||||
if uwsgi.masterpid() > 0:
|
||||
uwsgi.reload()
|
||||
request.user.message_set.create(message="uWSGI reloaded")
|
||||
else:
|
||||
request.user.message_set.create(message="The uWSGI master process is not active")
|
||||
|
||||
return HttpResponseRedirect(reverse(index))
|
||||
|
||||
reload = staff_member_required(reload)
|
||||
@@ -0,0 +1,29 @@
|
||||
from django.template.base import TemplateDoesNotExist
|
||||
from django.template.loader import BaseLoader
|
||||
from django.conf import settings
|
||||
|
||||
try:
|
||||
import uwsgi
|
||||
on_uwsgi = True
|
||||
except:
|
||||
on_uwsgi = False
|
||||
|
||||
|
||||
|
||||
|
||||
class Loader(BaseLoader):
|
||||
|
||||
is_usable = on_uwsgi
|
||||
|
||||
def symbolize(self, name):
|
||||
return name.replace('.','_').replace('/','_').replace('-','_')
|
||||
|
||||
def load_template_source(self, template_name, template_dirs=None):
|
||||
filename = 'templates_' + self.symbolize(template_name)
|
||||
for app in settings.INSTALLED_APPS:
|
||||
try:
|
||||
symbol = "%s_%s" % (self.symbolize(app), filename)
|
||||
return (uwsgi.embedded_data(symbol), "sym://%s" % symbol)
|
||||
except:
|
||||
pass
|
||||
raise TemplateDoesNotExist(template_name)
|
||||
@@ -1,77 +0,0 @@
|
||||
# to run the server
|
||||
# uwsgi --plugin psgi,coroae --http-socket :9090 --http-socket-modifier1 5 --coroae 8 --psgi examples/corostream.pl --master
|
||||
# to test it
|
||||
# curl -D /dev/stdout -N --raw http://localhost:9090/
|
||||
|
||||
use Coro::AnyEvent;
|
||||
use AnyEvent::HTTP;
|
||||
|
||||
my $signal_handler = sub {
|
||||
my $signum = shift;
|
||||
print "i am the signal ".$signum."\n" ;
|
||||
};
|
||||
|
||||
my $signal_timer = sub {
|
||||
my $signum = shift;
|
||||
print "2 seconds elapsed\n";
|
||||
};
|
||||
|
||||
uwsgi::register_signal(17, '', $signal_handler);
|
||||
uwsgi::register_signal(30, '', $signal_timer);
|
||||
|
||||
# raise the signal 30 every 2 seconds
|
||||
uwsgi::add_timer(30, 2);
|
||||
|
||||
sub streamer {
|
||||
$responder = shift;
|
||||
# generate the headers and start streaming the response
|
||||
my $writer = $responder->( [200, ['Content-Type' => 'text/plain']]);
|
||||
|
||||
$writer->write("Hello, the streaming is starting...\n");
|
||||
|
||||
for(my $i=0;$i<5;$i++) {
|
||||
Coro::AnyEvent::sleep 1;
|
||||
$writer->write("[".$i."] one seconds elapsed...\n");
|
||||
}
|
||||
|
||||
$writer->write("let me show you the coroae plugin source taken from github\n\n");
|
||||
|
||||
# this condvar will allow us to wait for the github response
|
||||
my $w = AnyEvent->condvar;
|
||||
|
||||
my $uwsgi_coroae_src = '';
|
||||
|
||||
http_get 'https://raw.github.com/unbit/uwsgi/master/plugins/coroae/coroae.c', sub { $uwsgi_coroae_src = $_[0] ; $w->send;};
|
||||
|
||||
$w->recv;
|
||||
|
||||
$writer->write($uwsgi_coroae_src);
|
||||
|
||||
Coro::AnyEvent::sleep 1;
|
||||
|
||||
$writer->write("now let's raise a uwsgi signal...\n");
|
||||
|
||||
uwsgi::signal(17);
|
||||
|
||||
Coro::AnyEvent::sleep 1;
|
||||
|
||||
$writer->write("another one second elapsed, time to finish.\n");
|
||||
|
||||
Coro::AnyEvent::sleep 1;
|
||||
|
||||
$writer->write("Goodbye\n");
|
||||
|
||||
$writer->close;
|
||||
|
||||
print "the request ended, but we are still here\n";
|
||||
|
||||
Coro::AnyEvent::sleep 1;
|
||||
|
||||
print "another second elapsed, time to end (really)\n";
|
||||
}
|
||||
|
||||
# our PSGI app
|
||||
my $app = sub {
|
||||
my $env = shift;
|
||||
return \&streamer;
|
||||
}
|
||||
+1
-2
@@ -15,11 +15,10 @@ rpc result:<br/>
|
||||
|
||||
<?
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
echo uwsgi_cache_update('foobar', $_POST['cache_val']);
|
||||
uwsgi_cache_update('foobar', $_POST['cache_val']);
|
||||
}
|
||||
|
||||
?>
|
||||
cache value: <?= uwsgi_cache_get('foobar') ?><br/>
|
||||
<form method="POST">
|
||||
<input type="text" name="cache_val" value="<?=uwsgi_cache_get('foobar')?>"/>
|
||||
<input type="submit" value="cache set" />
|
||||
|
||||
+2
-14
@@ -132,16 +132,10 @@ void linux_namespace_jail() {
|
||||
|
||||
if (strcmp(uwsgi.ns, "/")) {
|
||||
ns_tmp_mountpoint = uwsgi_concat2(uwsgi.ns, "/.uwsgi_ns_tmp_mountpoint");
|
||||
if (mkdir(ns_tmp_mountpoint, S_IRWXU) < 0) {
|
||||
uwsgi_error("mkdir() ns_tmp_mountpoint");
|
||||
exit(1);
|
||||
}
|
||||
mkdir(ns_tmp_mountpoint, S_IRWXU);
|
||||
|
||||
ns_tmp_mountpoint2 = uwsgi_concat2(ns_tmp_mountpoint, "/.uwsgi_ns_tmp_mountpoint");
|
||||
if (mkdir(ns_tmp_mountpoint2, S_IRWXU) < 0) {
|
||||
uwsgi_error("mkdir() ns_tmp_mountpoint2");
|
||||
exit(1);
|
||||
}
|
||||
mkdir(ns_tmp_mountpoint2, S_IRWXU);
|
||||
|
||||
if (mount(uwsgi.ns, ns_tmp_mountpoint, "none", MS_BIND, NULL)) {
|
||||
uwsgi_error("mount()");
|
||||
@@ -207,16 +201,10 @@ void linux_namespace_jail() {
|
||||
|
||||
unmounted = 0;
|
||||
procmounts = fopen("/proc/self/mounts", "r");
|
||||
if (!procmounts)
|
||||
break;
|
||||
while (fgets(line, 1024, procmounts) != NULL) {
|
||||
delim0 = strchr(line, ' ');
|
||||
if (!delim0)
|
||||
continue;
|
||||
delim0++;
|
||||
delim1 = strchr(delim0, ' ');
|
||||
if (!delim1)
|
||||
continue;
|
||||
*delim1 = 0;
|
||||
// and now check for keep-mounts
|
||||
if (uwsgi_is_a_keep_mount(delim0)) continue;
|
||||
|
||||
@@ -6,30 +6,42 @@ extern struct uwsgi_server uwsgi;
|
||||
int uwsgi_request_admin(struct wsgi_request *wsgi_req) {
|
||||
|
||||
uint32_t opt_value = 0;
|
||||
ssize_t len;
|
||||
|
||||
if (wsgi_req->uh->pktsize != 0 && wsgi_req->uh->pktsize != 4)
|
||||
if (wsgi_req->uh.pktsize != 0 && wsgi_req->uh.pktsize != 4)
|
||||
return UWSGI_OK;
|
||||
|
||||
// write request
|
||||
if (wsgi_req->uh->pktsize == 4) {
|
||||
if (wsgi_req->uh.pktsize == 4) {
|
||||
memcpy(&opt_value, wsgi_req->buffer, 4);
|
||||
uwsgi_log( "setting internal option %d to %d\n", wsgi_req->uh->modifier2, opt_value);
|
||||
uwsgi.shared->options[wsgi_req->uh->modifier2] = opt_value;
|
||||
uwsgi_log( "setting internal option %d to %d\n", wsgi_req->uh.modifier2, opt_value);
|
||||
uwsgi.shared->options[wsgi_req->uh.modifier2] = opt_value;
|
||||
|
||||
// ACK
|
||||
wsgi_req->uh->modifier1 = 255;
|
||||
wsgi_req->uh->pktsize = 0;
|
||||
wsgi_req->uh->modifier2 = 1;
|
||||
uwsgi_response_write_body_do(wsgi_req, (char *)wsgi_req->uh , 4);
|
||||
wsgi_req->uh.modifier1 = 255;
|
||||
wsgi_req->uh.pktsize = 0;
|
||||
wsgi_req->uh.modifier2 = 1;
|
||||
len = write(wsgi_req->poll.fd, wsgi_req, 4);
|
||||
if (len != 4) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
// get request
|
||||
else {
|
||||
uwsgi_log( "internal option %d = %d\n", wsgi_req->uh->modifier2, uwsgi.shared->options[wsgi_req->uh->modifier2]);
|
||||
uwsgi_log( "internal option %d = %d\n", wsgi_req->uh.modifier2, uwsgi.shared->options[wsgi_req->uh.modifier2]);
|
||||
|
||||
wsgi_req->uh->modifier1 = 10;
|
||||
wsgi_req->uh->pktsize = 4;
|
||||
uwsgi_response_write_body_do(wsgi_req, (char *)wsgi_req->uh , 4);
|
||||
uwsgi_response_write_body_do(wsgi_req, (char *) &uwsgi.shared->options[wsgi_req->uh->modifier2], 4);
|
||||
wsgi_req->uh.modifier1 = 10;
|
||||
wsgi_req->uh.pktsize = 4;
|
||||
len = write(wsgi_req->poll.fd, wsgi_req, 4);
|
||||
if (len != 4) {
|
||||
uwsgi_error("write()");
|
||||
return UWSGI_OK;
|
||||
}
|
||||
len = write(wsgi_req->poll.fd, (char *) &uwsgi.shared->options[wsgi_req->uh.modifier2], 4);
|
||||
if (len != 4) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return UWSGI_OK;
|
||||
|
||||
@@ -17,7 +17,6 @@ struct uwsgi_alarm_curl_opt {
|
||||
};
|
||||
|
||||
|
||||
#ifdef CURLOPT_MAIL_RCPT
|
||||
static void uwsgi_alarm_curl_to(CURL *curl, CURLoption option, char *arg, struct uwsgi_alarm_curl_config *uacc) {
|
||||
uacc->to = arg;
|
||||
struct curl_slist *list = NULL;
|
||||
@@ -30,7 +29,6 @@ static void uwsgi_alarm_curl_to(CURL *curl, CURLoption option, char *arg, struct
|
||||
}
|
||||
curl_easy_setopt(curl, option, list);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void uwsgi_alarm_curl_ssl(CURL *curl, CURLoption option, char *arg, struct uwsgi_alarm_curl_config *uacc) {
|
||||
curl_easy_setopt(curl, option, (long)CURLUSESSL_ALL);
|
||||
@@ -46,12 +44,8 @@ static void uwsgi_alarm_curl_set_subject(CURL *curl, CURLoption option, char *ar
|
||||
|
||||
static struct uwsgi_alarm_curl_opt uaco[] = {
|
||||
{"url", CURLOPT_URL, NULL},
|
||||
#ifdef CURLOPT_MAIL_RCPT
|
||||
{"mail_to", CURLOPT_MAIL_RCPT, uwsgi_alarm_curl_to },
|
||||
#endif
|
||||
#ifdef CURLOPT_MAIL_FROM
|
||||
{"mail_from", CURLOPT_MAIL_FROM, NULL},
|
||||
#endif
|
||||
{"subject", 0, uwsgi_alarm_curl_set_subject},
|
||||
{"ssl", CURLOPT_USE_SSL, uwsgi_alarm_curl_ssl},
|
||||
{"auth_user", CURLOPT_USERNAME, NULL},
|
||||
|
||||
@@ -25,8 +25,6 @@ class Jabbo : public ConnectionListener{
|
||||
p = strtok_r(NULL, ",", &ctx);
|
||||
}
|
||||
|
||||
full_jid = jab_username;
|
||||
|
||||
JID jid(jab_username);
|
||||
client = new Client( jid, jab_password );
|
||||
client->registerConnectionListener(this);
|
||||
@@ -54,11 +52,11 @@ class Jabbo : public ConnectionListener{
|
||||
event_queue_add_fd_read(u_thread->queue, fd);
|
||||
event_queue_add_fd_read(u_thread->queue, u_thread->pipe[1]);
|
||||
u_connected = 1;
|
||||
uwsgi_log_alarm("-xmpp] (%s) connected to the XMPP server\n", full_jid);
|
||||
uwsgi_log("[uwsgi-xmpp] connected to the XMPP server\n");
|
||||
}
|
||||
|
||||
virtual void onDisconnect(ConnectionError e) {
|
||||
uwsgi_log_alarm("-xmpp] (%s) trying reconnect to the XMPP server...\n", full_jid);
|
||||
uwsgi_log("[uwsgi-xmpp] trying reconnect to the XMPP server...\n");
|
||||
if (u_connected) {
|
||||
// no need to remove it as it is already closed...
|
||||
//event_queue_del_fd(u_thread->queue, fd, event_queue_read());
|
||||
@@ -71,12 +69,12 @@ class Jabbo : public ConnectionListener{
|
||||
}
|
||||
|
||||
virtual void onResourceBindError(const Error *error) {
|
||||
uwsgi_log_alarm("-xmpp] (%s) onResourceBindError(): %s\n", full_jid, error->text().c_str());
|
||||
uwsgi_log("[uwsgi-xmpp] onResourceBindError(): %s\n", error->text().c_str());
|
||||
client->disconnect();
|
||||
}
|
||||
|
||||
virtual void onSessionCreateError(const Error *error) {
|
||||
uwsgi_log_alarm("-xmpp] (%s) onSessionCreateError(): %s\n", full_jid, error->text().c_str());
|
||||
uwsgi_log("[uwsgi-xmpp] onSessionCreateError(): %s\n", error->text().c_str());
|
||||
client->disconnect();
|
||||
}
|
||||
|
||||
@@ -85,7 +83,6 @@ class Jabbo : public ConnectionListener{
|
||||
}
|
||||
|
||||
Client* client;
|
||||
char *full_jid;
|
||||
int fd;
|
||||
int u_connected;
|
||||
struct uwsgi_thread *u_thread;
|
||||
|
||||
Vendored
+39
-253
@@ -1,195 +1,35 @@
|
||||
#include <uwsgi.h>
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
/*
|
||||
|
||||
Plugin for remote access to the uWSGI cache
|
||||
|
||||
For request generating a response containing cache data, we need to make
|
||||
a copy to avoid holding the lock too much in case of blocking/slow writes
|
||||
|
||||
we use 1.9 cache magic functions to be DRY
|
||||
|
||||
the modifier2 is the command to run. Some command is extremely raw, and generally it is mean
|
||||
for internal uWSGI usage.
|
||||
|
||||
commands:
|
||||
|
||||
0 -> simple cache get for values not bigger than 64k, the request is [111, keysize, 0] + key / response is [111, vallen, 0] + value
|
||||
|
||||
1 -> simple cache set for values not bigger than 64k, the request is [111, pktsize, 1] + (key, value) / response is connection closed
|
||||
|
||||
2 -> simple cache del, the request is [111, keysize, 2] + key / response is connection closed
|
||||
|
||||
3/4 -> simple dict based get command -> [111, pktsize ,3/4] + (key|get) / response is value for "key and get", but if "get" and no key is found an HTTP 404 is returned
|
||||
|
||||
5 -> get and stream -> [111, keysize, 5] + key response is a stream of the value til the whole object is transferred
|
||||
|
||||
6 -> dump the whole cache
|
||||
|
||||
17 -> magic interface for plugins remote access { "cmd": "get|set|update|del|exists", "key": "cache key", "expires": "seconds", "cache": "the cache name"}
|
||||
returns: {"status":"ok|notfound|error", "size": "size of the following body, if present"} + stream
|
||||
|
||||
*/
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
static void cache_simple_command(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
|
||||
void cache_command(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
|
||||
|
||||
struct wsgi_request *wsgi_req = (struct wsgi_request *) data;
|
||||
uint64_t tmp_vallen = 0;
|
||||
|
||||
if (vallen > 0) {
|
||||
if (!uwsgi_strncmp(key, keylen, "key", 3)) {
|
||||
uint64_t vallen = 0;
|
||||
char *value = uwsgi_cache_magic_get(val, vallen, &vallen, NULL);
|
||||
if (value) {
|
||||
uwsgi_response_write_body_do(wsgi_req, value, vallen);
|
||||
free(value);
|
||||
val = uwsgi_cache_get(val, vallen, &tmp_vallen);
|
||||
if (val && tmp_vallen > 0) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("cache value size: %llu\n", tmp_vallen);
|
||||
#endif
|
||||
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, val, tmp_vallen);
|
||||
}
|
||||
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "get", 3)) {
|
||||
uint64_t vallen = 0;
|
||||
char *value = uwsgi_cache_magic_get(val, vallen, &vallen, NULL);
|
||||
if (value) {
|
||||
uwsgi_response_write_body_do(wsgi_req, value, vallen);
|
||||
free(value);
|
||||
val = uwsgi_cache_get(val, vallen, &tmp_vallen);
|
||||
if (val && vallen > 0) {
|
||||
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, val, tmp_vallen);
|
||||
}
|
||||
else {
|
||||
uwsgi_404(wsgi_req);
|
||||
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 404 Not Found\r\n\r\n<h1>Not Found</h1>", 44);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// this function does not use the magic api internally to avoid too much copy
|
||||
static void manage_magic_context(struct wsgi_request *wsgi_req, struct uwsgi_cache_magic_context *ucmc) {
|
||||
|
||||
struct uwsgi_buffer *ub = NULL;
|
||||
struct uwsgi_cache *uc = uwsgi.caches;
|
||||
|
||||
if (ucmc->cache_len > 0) {
|
||||
uc = uwsgi_cache_by_namelen(ucmc->cache, ucmc->cache_len);
|
||||
if (!uc) return;
|
||||
}
|
||||
|
||||
if (!uc) return;
|
||||
|
||||
// cache get
|
||||
if (!uwsgi_strncmp(ucmc->cmd, ucmc->cmd_len, "get", 3)) {
|
||||
uint64_t vallen = 0;
|
||||
uwsgi_rlock(uc->lock);
|
||||
char *value = uwsgi_cache_get2(uc, ucmc->key, ucmc->key_len, &vallen);
|
||||
if (!value) {
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
return;
|
||||
}
|
||||
// we are still locked !!!
|
||||
ub = uwsgi_buffer_new(uwsgi.page_size);
|
||||
ub->pos = 4;
|
||||
if (uwsgi_buffer_append_keyval(ub, "status", 6, "ok", 2)) goto error;
|
||||
if (uwsgi_buffer_append_keynum(ub, "size", 4, vallen)) goto error;
|
||||
if (uwsgi_buffer_set_uh(ub, 111, 17)) goto error;
|
||||
if (uwsgi_buffer_append(ub, value, vallen)) goto error;
|
||||
// unlock !!!
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return;
|
||||
}
|
||||
|
||||
// cache exists
|
||||
if (!uwsgi_strncmp(ucmc->cmd, ucmc->cmd_len, "exists", 6)) {
|
||||
uwsgi_rlock(uc->lock);
|
||||
if (!uwsgi_cache_exists2(uc, ucmc->key, ucmc->key_len)) {
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
return;
|
||||
}
|
||||
// we are still locked !!!
|
||||
ub = uwsgi_buffer_new(uwsgi.page_size);
|
||||
ub->pos = 4;
|
||||
if (uwsgi_buffer_append_keyval(ub, "status", 6, "ok", 2)) goto error;
|
||||
if (uwsgi_buffer_set_uh(ub, 111, 17)) goto error;
|
||||
// unlock !!!
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return;
|
||||
}
|
||||
|
||||
// cache del
|
||||
if (!uwsgi_strncmp(ucmc->cmd, ucmc->cmd_len, "del", 3)) {
|
||||
uwsgi_wlock(uc->lock);
|
||||
if (uwsgi_cache_del2(uc, ucmc->key, ucmc->key_len, 0, 0)) {
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
return;
|
||||
}
|
||||
// we are still locked !!!
|
||||
ub = uwsgi_buffer_new(uwsgi.page_size);
|
||||
ub->pos = 4;
|
||||
if (uwsgi_buffer_append_keyval(ub, "status", 6, "ok", 2)) goto error;
|
||||
if (uwsgi_buffer_set_uh(ub, 111, 17)) goto error;
|
||||
// unlock !!!
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return;
|
||||
}
|
||||
|
||||
// cache clear
|
||||
if (!uwsgi_strncmp(ucmc->cmd, ucmc->cmd_len, "clear", 5)) {
|
||||
uint64_t i;
|
||||
uwsgi_wlock(uc->lock);
|
||||
for (i = 1; i < uwsgi.caches->max_items; i++) {
|
||||
if (uwsgi_cache_del2(uc, NULL, 0, i, 0)) {
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// we are still locked !!!
|
||||
ub = uwsgi_buffer_new(uwsgi.page_size);
|
||||
ub->pos = 4;
|
||||
if (uwsgi_buffer_append_keyval(ub, "status", 6, "ok", 2)) goto error;
|
||||
if (uwsgi_buffer_set_uh(ub, 111, 17)) goto error;
|
||||
// unlock !!!
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return;
|
||||
}
|
||||
|
||||
// cache set
|
||||
if (!uwsgi_strncmp(ucmc->cmd, ucmc->cmd_len, "set", 3) || !uwsgi_strncmp(ucmc->cmd, ucmc->cmd_len, "update", 6)) {
|
||||
if (ucmc->size == 0 || ucmc->size > uc->max_item_size) return;
|
||||
wsgi_req->post_cl = ucmc->size;
|
||||
// read the value
|
||||
ssize_t rlen = 0;
|
||||
char *value = uwsgi_request_body_read(wsgi_req, ucmc->size, &rlen);
|
||||
if (rlen != (ssize_t) ucmc->size) return;
|
||||
// ok let's lock
|
||||
uwsgi_wlock(uc->lock);
|
||||
if (uwsgi_cache_set2(uc, ucmc->key, ucmc->key_len, value, ucmc->size, ucmc->expires, ucmc->cmd_len > 3 ? UWSGI_CACHE_FLAG_UPDATE : 0)) {
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
return;
|
||||
}
|
||||
// we are still locked !!!
|
||||
ub = uwsgi_buffer_new(uwsgi.page_size);
|
||||
ub->pos = 4;
|
||||
if (uwsgi_buffer_append_keyval(ub, "status", 6, "ok", 2)) goto error;
|
||||
if (uwsgi_buffer_set_uh(ub, 111, 17)) goto error;
|
||||
// unlock !!!
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
error:
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
}
|
||||
|
||||
static int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
|
||||
int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
uint64_t vallen = 0;
|
||||
char *value;
|
||||
@@ -197,116 +37,62 @@ static int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
|
||||
uint16_t argvs[3];
|
||||
uint8_t argc = 0;
|
||||
|
||||
// used for modifier2 17
|
||||
struct uwsgi_cache_magic_context ucmc;
|
||||
struct uwsgi_cache *uc = NULL;
|
||||
|
||||
switch(wsgi_req->uh->modifier2) {
|
||||
switch(wsgi_req->uh.modifier2) {
|
||||
case 0:
|
||||
// get
|
||||
if (wsgi_req->uh->pktsize > 0) {
|
||||
value = uwsgi_cache_magic_get(wsgi_req->buffer, wsgi_req->uh->pktsize, &vallen, NULL);
|
||||
if (value) {
|
||||
wsgi_req->uh->pktsize = vallen;
|
||||
if (uwsgi_response_write_body_do(wsgi_req, (char *)&wsgi_req->uh, 4)) { free(value) ; return -1;}
|
||||
uwsgi_response_write_body_do(wsgi_req, value, vallen);
|
||||
free(value);
|
||||
if (wsgi_req->uh.pktsize > 0) {
|
||||
value = uwsgi_cache_get(wsgi_req->buffer, wsgi_req->uh.pktsize, &vallen);
|
||||
if (value && vallen > 0) {
|
||||
wsgi_req->uh.pktsize = vallen;
|
||||
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, (char *)&wsgi_req->uh, 4);
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, value, vallen);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
// set
|
||||
if (wsgi_req->uh->pktsize > 0) {
|
||||
// max 3 items
|
||||
if (wsgi_req->uh.pktsize > 0) {
|
||||
argc = 3;
|
||||
if (!uwsgi_parse_array(wsgi_req->buffer, wsgi_req->uh->pktsize, argv, argvs, &argc)) {
|
||||
if (!uwsgi_parse_array(wsgi_req->buffer, wsgi_req->uh.pktsize, argv, argvs, &argc)) {
|
||||
if (argc > 1) {
|
||||
uwsgi_cache_magic_set(argv[0], argvs[0], argv[1], argvs[1], 0, 0, NULL);
|
||||
uwsgi_cache_set(argv[0], argvs[0], argv[1], argvs[1], 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
// del
|
||||
if (wsgi_req->uh->pktsize > 0) {
|
||||
uwsgi_cache_magic_del(wsgi_req->buffer, wsgi_req->uh->pktsize, NULL);
|
||||
if (wsgi_req->uh.pktsize > 0) {
|
||||
uwsgi_cache_del(wsgi_req->buffer, wsgi_req->uh.pktsize, 0);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
// dict
|
||||
if (wsgi_req->uh->pktsize > 0) {
|
||||
uwsgi_hooked_parse(wsgi_req->buffer, wsgi_req->uh->pktsize, cache_simple_command, (void *) wsgi_req);
|
||||
if (wsgi_req->uh.pktsize > 0) {
|
||||
uwsgi_hooked_parse(wsgi_req->buffer, wsgi_req->uh.pktsize, cache_command, (void *) wsgi_req);
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
// get (uwsgi + stream)
|
||||
if (wsgi_req->uh->pktsize > 0) {
|
||||
value = uwsgi_cache_magic_get(wsgi_req->buffer, wsgi_req->uh->pktsize, &vallen, NULL);
|
||||
if (value) {
|
||||
wsgi_req->uh->pktsize = 0;
|
||||
wsgi_req->uh->modifier2 = 1;
|
||||
if (uwsgi_response_write_body_do(wsgi_req, (char *)&wsgi_req->uh, 4)) { free(value) ;return -1;}
|
||||
uwsgi_response_write_body_do(wsgi_req, value, vallen);
|
||||
free(value);
|
||||
if (wsgi_req->uh.pktsize > 0) {
|
||||
value = uwsgi_cache_get(wsgi_req->buffer, wsgi_req->uh.pktsize, &vallen);
|
||||
if (value && vallen > 0) {
|
||||
wsgi_req->uh.pktsize = 0;
|
||||
wsgi_req->uh.modifier2 = 1;
|
||||
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, (char *)&wsgi_req->uh, 4);
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, value, vallen);
|
||||
}
|
||||
else {
|
||||
wsgi_req->uh->pktsize = 0;
|
||||
wsgi_req->uh->modifier2 = 0;
|
||||
uwsgi_response_write_body_do(wsgi_req, (char *)&wsgi_req->uh, 4);
|
||||
free(value);
|
||||
wsgi_req->uh.pktsize = 0;
|
||||
wsgi_req->uh.modifier2 = 0;
|
||||
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, (char *)&wsgi_req->uh, 4);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
// dump
|
||||
uc = uwsgi.caches;
|
||||
if (wsgi_req->uh->pktsize > 0) {
|
||||
uc = uwsgi_cache_by_namelen(wsgi_req->buffer, wsgi_req->uh->pktsize);
|
||||
}
|
||||
|
||||
if (!uc) break;
|
||||
|
||||
uwsgi_wlock(uc->lock);
|
||||
struct uwsgi_buffer *cache_dump = uwsgi_buffer_new(uwsgi.page_size + uc->filesize);
|
||||
cache_dump->pos = 4;
|
||||
if (uwsgi_buffer_append_keynum(cache_dump, "items", 5, uc->max_items)) {
|
||||
uwsgi_buffer_destroy(cache_dump);
|
||||
break;
|
||||
}
|
||||
if (uwsgi_buffer_append_keynum(cache_dump, "blocksize", 9, uc->blocksize)) {
|
||||
uwsgi_buffer_destroy(cache_dump);
|
||||
break;
|
||||
}
|
||||
|
||||
if (uwsgi_buffer_set_uh(cache_dump, 111, 7)) {
|
||||
uwsgi_buffer_destroy(cache_dump);
|
||||
break;
|
||||
}
|
||||
|
||||
if (uwsgi_buffer_append(cache_dump, (char *)uc->items, uc->filesize)) {
|
||||
uwsgi_buffer_destroy(cache_dump);
|
||||
break;
|
||||
}
|
||||
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
|
||||
uwsgi_response_write_body_do(wsgi_req, cache_dump->buf, cache_dump->pos);
|
||||
uwsgi_buffer_destroy(cache_dump);
|
||||
break;
|
||||
case 17:
|
||||
if (wsgi_req->uh->pktsize == 0) break;
|
||||
memset(&ucmc, 0, sizeof(struct uwsgi_cache_magic_context));
|
||||
if (uwsgi_hooked_parse(wsgi_req->buffer, wsgi_req->uh->pktsize, uwsgi_cache_magic_context_hook, &ucmc)) {
|
||||
break;
|
||||
}
|
||||
manage_magic_context(wsgi_req, &ucmc);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return UWSGI_OK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin cache_plugin = {
|
||||
|
||||
@@ -97,6 +97,7 @@ static void carbon_post_init() {
|
||||
|
||||
if (!u_carbon.last_busyness_values) {
|
||||
u_carbon.last_busyness_values = uwsgi_calloc(sizeof(unsigned long long) * uwsgi.numproc);
|
||||
|
||||
}
|
||||
|
||||
if (!u_carbon.current_busyness_values) {
|
||||
@@ -149,7 +150,7 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
for (i = 0; i < uwsgi.numproc; i++) {
|
||||
u_carbon.current_busyness_values[i] = uwsgi.workers[i+1].running_time - u_carbon.last_busyness_values[i];
|
||||
u_carbon.last_busyness_values[i] = uwsgi.workers[i+1].running_time;
|
||||
u_carbon.was_busy[i-1] += uwsgi_worker_is_busy(i+1);
|
||||
u_carbon.was_busy[i-1] += uwsgi.workers[i+1].busy;
|
||||
}
|
||||
|
||||
u_carbon.need_retry = 0;
|
||||
|
||||
+155
-58
@@ -1,4 +1,4 @@
|
||||
#include <uwsgi.h>
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
@@ -66,6 +66,55 @@ struct uwsgi_option uwsgi_cgi_options[] = {
|
||||
|
||||
};
|
||||
|
||||
void uwsgi_cgi_404(struct wsgi_request *wsgi_req) {
|
||||
|
||||
wsgi_req->status = 404;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 404 Not Found\r\nContent-Type: text/plain\r\n\r\nNot Found", 61);
|
||||
}
|
||||
|
||||
void uwsgi_cgi_403(struct wsgi_request *wsgi_req) {
|
||||
|
||||
wsgi_req->status = 403;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 403 Forbidden\r\nContent-Type: text/plain\r\n\r\nForbidden", 61);
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_cgi_redirect_to_slash(struct wsgi_request *wsgi_req) {
|
||||
|
||||
struct iovec iov[6];
|
||||
|
||||
wsgi_req->status = 301;
|
||||
iov[0].iov_base = wsgi_req->protocol;
|
||||
iov[0].iov_len = wsgi_req->protocol_len;
|
||||
iov[1].iov_base = " 301 Moved Permanently\r\n";
|
||||
iov[1].iov_len = 24;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2);
|
||||
|
||||
iov[0].iov_base = "Location: ";
|
||||
iov[0].iov_len = 10;
|
||||
iov[1].iov_base = wsgi_req->path_info;
|
||||
iov[1].iov_len = wsgi_req->path_info_len;
|
||||
iov[2].iov_base = "/";
|
||||
iov[2].iov_len = 1;
|
||||
|
||||
if (wsgi_req->query_string_len > 0) {
|
||||
iov[3].iov_base = "?";
|
||||
iov[3].iov_len = 1;
|
||||
iov[4].iov_base = wsgi_req->query_string;
|
||||
iov[4].iov_len = wsgi_req->query_string_len;
|
||||
iov[5].iov_base = "\r\n\r\n";
|
||||
iov[5].iov_len = 4;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 6);
|
||||
wsgi_req->header_cnt++;
|
||||
}
|
||||
else {
|
||||
iov[3].iov_base = "\r\n\r\n";
|
||||
iov[3].iov_len = 4;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 4);
|
||||
wsgi_req->header_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_cgi_apps() {
|
||||
|
||||
struct uwsgi_dyn_dict *udd = uc.mountpoint;
|
||||
@@ -186,6 +235,10 @@ int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
size_t header_size = 0;
|
||||
int status_sent = 0;
|
||||
|
||||
struct uwsgi_string_list *ah = uwsgi.additional_headers;
|
||||
|
||||
struct iovec iov[4];
|
||||
|
||||
for(i=0;i<len;i++) {
|
||||
// end of a line
|
||||
if (buf[i] == '\n') {
|
||||
@@ -214,7 +267,16 @@ int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
// "Status: NNN"
|
||||
if (header_size >= 11) {
|
||||
if (!strncasecmp("Status: ", key, 8)) {
|
||||
uwsgi_response_prepare_headers(wsgi_req, key+8, header_size - 8);
|
||||
wsgi_req->status = uwsgi_str3_num(key+8);
|
||||
iov[0].iov_base = wsgi_req->protocol;
|
||||
iov[0].iov_len = wsgi_req->protocol_len;
|
||||
iov[1].iov_base = " ";
|
||||
iov[1].iov_len = 1;
|
||||
iov[2].iov_base = key+8;
|
||||
iov[2].iov_len = header_size - 8;
|
||||
iov[3].iov_base = "\r\n";
|
||||
iov[3].iov_len = 2;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 4);
|
||||
status_sent = 1;
|
||||
key = NULL;
|
||||
value = NULL;
|
||||
@@ -229,18 +291,34 @@ int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
// Location: X
|
||||
if (header_size >= 11) {
|
||||
if (!strncasecmp("Location: ", key, 10)) {
|
||||
uwsgi_response_prepare_headers(wsgi_req, "302 Found", 9);
|
||||
|
||||
wsgi_req->status = 302;
|
||||
iov[0].iov_base = wsgi_req->protocol;
|
||||
iov[0].iov_len = wsgi_req->protocol_len;
|
||||
iov[1].iov_base = " 302 Found\r\n";
|
||||
iov[1].iov_len = 12;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2);
|
||||
status_sent = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (status_sent == 0) {
|
||||
uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6);
|
||||
wsgi_req->status = 200;
|
||||
iov[0].iov_base = wsgi_req->protocol;
|
||||
iov[0].iov_len = wsgi_req->protocol_len;
|
||||
iov[1].iov_base = " 200 OK\r\n";
|
||||
iov[1].iov_len = 9;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2);
|
||||
status_sent = 1;
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_response_add_header(wsgi_req, NULL, 0, key, header_size);
|
||||
iov[0].iov_base = key;
|
||||
iov[0].iov_len = header_size;
|
||||
iov[1].iov_base = "\r\n";
|
||||
iov[1].iov_len = 2;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2);
|
||||
wsgi_req->header_cnt++;
|
||||
|
||||
key = NULL;
|
||||
value = NULL;
|
||||
@@ -259,8 +337,19 @@ int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
|
||||
send_body:
|
||||
|
||||
while(ah) {
|
||||
iov[0].iov_base = ah->value;
|
||||
iov[0].iov_len = ah->len;
|
||||
iov[1].iov_base = "\r\n";
|
||||
iov[1].iov_len = 2;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2);
|
||||
wsgi_req->header_cnt++;
|
||||
ah = ah->next;
|
||||
}
|
||||
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2);
|
||||
if (len-i > 0) {
|
||||
uwsgi_response_write_body_do(wsgi_req, buf+i, len-i);
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, buf+i, len-i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -343,7 +432,7 @@ int uwsgi_cgi_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot
|
||||
*(dst+part_size-1) = 0;
|
||||
|
||||
if (stat(full_path, &st)) {
|
||||
uwsgi_404(wsgi_req);
|
||||
uwsgi_cgi_404(wsgi_req);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -404,8 +493,8 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
char *script_name = NULL;
|
||||
|
||||
/* Standard CGI request */
|
||||
if (!wsgi_req->uh->pktsize) {
|
||||
uwsgi_log("Empty CGI request. skip.\n");
|
||||
if (!wsgi_req->uh.pktsize) {
|
||||
uwsgi_log("Invalid CGI request. skip.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -428,7 +517,7 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
if (docroot == NULL || docroot_len == 0) {
|
||||
uwsgi_404(wsgi_req);
|
||||
uwsgi_cgi_404(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
@@ -448,7 +537,7 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
if (realpath(full_path, tmp_path) == NULL) {
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
uwsgi_404(wsgi_req);
|
||||
uwsgi_cgi_404(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
@@ -470,7 +559,7 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
if (stat(full_path, &cgi_stat)) {
|
||||
uwsgi_404(wsgi_req);
|
||||
uwsgi_cgi_404(wsgi_req);
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
return UWSGI_OK;
|
||||
@@ -480,7 +569,7 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
// add / to directories
|
||||
if (wsgi_req->path_info_len == 0 || (wsgi_req->path_info_len > 0 && wsgi_req->path_info[wsgi_req->path_info_len-1] != '/')) {
|
||||
uwsgi_redirect_to_slash(wsgi_req);
|
||||
uwsgi_cgi_redirect_to_slash(wsgi_req);
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
return UWSGI_OK;
|
||||
@@ -503,7 +592,7 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
uwsgi_404(wsgi_req);
|
||||
uwsgi_cgi_404(wsgi_req);
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
return UWSGI_OK;
|
||||
@@ -527,7 +616,7 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
if (!cgi_allowed) {
|
||||
uwsgi_403(wsgi_req);
|
||||
uwsgi_cgi_403(wsgi_req);
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
return UWSGI_OK;
|
||||
@@ -543,7 +632,7 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
if (helper == NULL) {
|
||||
if (access(full_path, X_OK)) {
|
||||
uwsgi_error("access()");
|
||||
uwsgi_403(wsgi_req);
|
||||
uwsgi_cgi_403(wsgi_req);
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
return UWSGI_OK;
|
||||
@@ -558,13 +647,17 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
if (pipe(post_pipe)) {
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
close(cgi_pipe[0]);
|
||||
close(cgi_pipe[1]);
|
||||
uwsgi_error("pipe()");
|
||||
return UWSGI_OK;
|
||||
int send_post_data = 0;
|
||||
if (uwsgi.post_buffering > 0 && wsgi_req->post_cl && !wsgi_req->async_post) {
|
||||
send_post_data = 1;
|
||||
if (pipe(post_pipe)) {
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
close(cgi_pipe[0]);
|
||||
close(cgi_pipe[1]);
|
||||
uwsgi_error("pipe()");
|
||||
return UWSGI_OK;
|
||||
}
|
||||
}
|
||||
|
||||
cgi_pid = fork();
|
||||
@@ -575,8 +668,10 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
free(docroot);
|
||||
close(cgi_pipe[0]);
|
||||
close(cgi_pipe[1]);
|
||||
close(post_pipe[0]);
|
||||
close(post_pipe[1]);
|
||||
if (send_post_data) {
|
||||
close(post_pipe[0]);
|
||||
close(post_pipe[1]);
|
||||
}
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
@@ -586,34 +681,23 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
free(docroot);
|
||||
|
||||
close(cgi_pipe[1]);
|
||||
close(post_pipe[0]);
|
||||
|
||||
// ok start sending post data...
|
||||
size_t remains = wsgi_req->post_cl;
|
||||
while(remains > 0) {
|
||||
ssize_t rlen = 0;
|
||||
char *buf = uwsgi_request_body_read(wsgi_req, 8192, &rlen);
|
||||
if (!buf) {
|
||||
if (send_post_data) {
|
||||
close(post_pipe[0]);
|
||||
if (write(post_pipe[1], wsgi_req->post_buffering_buf, wsgi_req->post_cl) != (ssize_t) wsgi_req->post_cl) {
|
||||
uwsgi_error("write()");
|
||||
close(post_pipe[1]);
|
||||
goto clear2;
|
||||
}
|
||||
if (buf == uwsgi.empty) break;
|
||||
// write data to the node
|
||||
if (uwsgi_write_true_nb(post_pipe[1], buf, rlen, uc.timeout)) {
|
||||
close(post_pipe[1]);
|
||||
goto clear2;
|
||||
}
|
||||
remains -= rlen;
|
||||
}
|
||||
|
||||
close(post_pipe[1]);
|
||||
goto clear2;
|
||||
}
|
||||
close(post_pipe[1]);
|
||||
}
|
||||
// wait for data
|
||||
char *headers_buf = uwsgi_malloc(uc.buffer_size);
|
||||
char *ptr = headers_buf;
|
||||
remains = uc.buffer_size;
|
||||
size_t remains = uc.buffer_size;
|
||||
int completed = 0;
|
||||
while(remains > 0) {
|
||||
int ret = uwsgi.wait_read_hook(cgi_pipe[0], uc.timeout);
|
||||
int ret = uwsgi_waitfd(cgi_pipe[0], uc.timeout);
|
||||
if (ret > 0) {
|
||||
len = read(cgi_pipe[0], ptr, remains);
|
||||
if (len > 0) {
|
||||
@@ -643,11 +727,11 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
while (!completed) {
|
||||
int ret = uwsgi.wait_read_hook(cgi_pipe[0], uc.timeout);
|
||||
int ret = uwsgi_waitfd(cgi_pipe[0], uc.timeout);
|
||||
if (ret > 0) {
|
||||
len = read(cgi_pipe[0], headers_buf, uc.buffer_size);
|
||||
if (len > 0) {
|
||||
uwsgi_response_write_body_do(wsgi_req, headers_buf, len);
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, headers_buf, len);
|
||||
}
|
||||
// end of output
|
||||
else if (len == 0) {
|
||||
@@ -670,7 +754,6 @@ clear:
|
||||
free(headers_buf);
|
||||
clear2:
|
||||
close(cgi_pipe[0]);
|
||||
close(post_pipe[1]);
|
||||
|
||||
// now wait for process exit/death
|
||||
if (waitpid(cgi_pid, &waitpid_status, 0) < 0) {
|
||||
@@ -683,23 +766,37 @@ clear2:
|
||||
// close all the fd except wsgi_req->poll.fd and 2;
|
||||
|
||||
for(i=0;i< (int)uwsgi.max_fd;i++) {
|
||||
if (post_pipe[0] == i) {
|
||||
continue;
|
||||
}
|
||||
if (wsgi_req->post_file) {
|
||||
if (fileno(wsgi_req->post_file) == i) {
|
||||
if (send_post_data) {
|
||||
if (post_pipe[0] == i) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (i != wsgi_req->fd && i != 2 && i != cgi_pipe[1]) {
|
||||
if (wsgi_req->async_post) {
|
||||
if (fileno((FILE*)wsgi_req->async_post) == i) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (i != wsgi_req->poll.fd && i != 2 && i != cgi_pipe[1]) {
|
||||
close(i);
|
||||
}
|
||||
}
|
||||
|
||||
// now map wsgi_req->poll.fd (or async_post) to 0 & cgi_pipe[1] to 1
|
||||
if (post_pipe[0] != 0) {
|
||||
dup2(post_pipe[0], 0);
|
||||
close(post_pipe[0]);
|
||||
if (send_post_data) {
|
||||
if (post_pipe[0] != 0) {
|
||||
dup2(post_pipe[0], 0);
|
||||
close(post_pipe[0]);
|
||||
}
|
||||
}
|
||||
else if (wsgi_req->async_post) {
|
||||
if (fileno((FILE*)wsgi_req->async_post) != 0) {
|
||||
dup2(fileno((FILE*)wsgi_req->async_post), 0);
|
||||
fclose(wsgi_req->async_post);
|
||||
}
|
||||
}
|
||||
else if (wsgi_req->poll.fd != 0) {
|
||||
dup2(wsgi_req->poll.fd, 0);
|
||||
close(wsgi_req->poll.fd);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <uwsgi.h>
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
/*
|
||||
|
||||
@@ -13,7 +13,6 @@ struct uwsgi_cheaper_busyness_global {
|
||||
uint64_t busyness_max;
|
||||
uint64_t busyness_min;
|
||||
uint64_t *last_values;
|
||||
int *was_busy;
|
||||
uint64_t tcheck;
|
||||
uint64_t last_cheaped; // last time worker was cheaped due to low busyness
|
||||
uint64_t next_cheap; // timestamp, we can cheap worker after it
|
||||
@@ -28,9 +27,6 @@ struct uwsgi_cheaper_busyness_global {
|
||||
int backlog_alert;
|
||||
int backlog_step;
|
||||
uint64_t backlog_multi; // multiplier used to cheap emergency workers
|
||||
uint64_t backlog_nonzero_alert;
|
||||
int backlog_is_nonzero;
|
||||
uint64_t backlog_nonzero_since; // since when backlog is > 0
|
||||
#endif
|
||||
} uwsgi_cheaper_busyness_global;
|
||||
|
||||
@@ -57,7 +53,7 @@ struct uwsgi_option uwsgi_cheaper_busyness_options[] = {
|
||||
|
||||
#ifdef __linux__
|
||||
{"cheaper-busyness-backlog-alert", required_argument, 0,
|
||||
"spawn emergency worker(s) if anytime listen queue is higher than this value (default 33)",
|
||||
"spawn emergency worker if anytime listen queue is higher than this value (default 33)",
|
||||
uwsgi_opt_set_int, &uwsgi_cheaper_busyness_global.backlog_alert, 0},
|
||||
{"cheaper-busyness-backlog-multiplier", required_argument, 0,
|
||||
"set cheaper multiplier used for emergency workers (default 3)",
|
||||
@@ -65,9 +61,6 @@ struct uwsgi_option uwsgi_cheaper_busyness_options[] = {
|
||||
{"cheaper-busyness-backlog-step", required_argument, 0,
|
||||
"number of emergency workers to spawn at a time (default 1)",
|
||||
uwsgi_opt_set_int, &uwsgi_cheaper_busyness_global.backlog_step, 0},
|
||||
{"cheaper-busyness-backlog-nonzero", required_argument, 0,
|
||||
"spawn emergency worker(s) if backlog is > 0 for more then N seconds (default 60)",
|
||||
uwsgi_opt_set_64bit, &uwsgi_cheaper_busyness_global.backlog_nonzero_alert, 0},
|
||||
#endif
|
||||
|
||||
{0, 0, 0, 0, 0, 0 ,0},
|
||||
@@ -125,17 +118,12 @@ int spawn_emergency_worker(int backlog) {
|
||||
}
|
||||
}
|
||||
|
||||
// reset cheap timer, so that we need to start counting idle cycles from zero
|
||||
uwsgi_cheaper_busyness_global.emergency_workers += decheaped;
|
||||
|
||||
set_next_cheap_time();
|
||||
|
||||
if (decheaped > 0) {
|
||||
uwsgi_cheaper_busyness_global.emergency_workers += decheaped;
|
||||
uwsgi_log("[busyness] %d requests in listen queue, spawning %d emergency worker(s) (%d)!\n",
|
||||
backlog, decheaped, uwsgi_cheaper_busyness_global.emergency_workers);
|
||||
} else {
|
||||
uwsgi_log("[busyness] %d requests in listen queue but we are already started maximum number of workers (%d)\n",
|
||||
backlog, uwsgi.numproc);
|
||||
}
|
||||
uwsgi_log("[busyness] %d requests in listen queue, spawning %d emergency worker(s) (%d)!\n",
|
||||
backlog, decheaped, uwsgi_cheaper_busyness_global.emergency_workers);
|
||||
|
||||
return decheaped;
|
||||
}
|
||||
@@ -152,9 +140,6 @@ int cheaper_busyness_algo(void) {
|
||||
if (!uwsgi_cheaper_busyness_global.last_values) {
|
||||
uwsgi_cheaper_busyness_global.last_values = uwsgi_calloc(sizeof(uint64_t) * uwsgi.numproc);
|
||||
}
|
||||
if (!uwsgi_cheaper_busyness_global.was_busy) {
|
||||
uwsgi_cheaper_busyness_global.was_busy = uwsgi_calloc(sizeof(int) * uwsgi.numproc);
|
||||
}
|
||||
|
||||
// set defaults
|
||||
if (!uwsgi_cheaper_busyness_global.busyness_max) uwsgi_cheaper_busyness_global.busyness_max = 50;
|
||||
@@ -166,7 +151,6 @@ int cheaper_busyness_algo(void) {
|
||||
if (!uwsgi_cheaper_busyness_global.backlog_alert) uwsgi_cheaper_busyness_global.backlog_alert = 33;
|
||||
if (!uwsgi_cheaper_busyness_global.backlog_multi) uwsgi_cheaper_busyness_global.backlog_multi = 3;
|
||||
if (!uwsgi_cheaper_busyness_global.backlog_step) uwsgi_cheaper_busyness_global.backlog_step = 1;
|
||||
if (!uwsgi_cheaper_busyness_global.backlog_nonzero_alert) uwsgi_cheaper_busyness_global.backlog_nonzero_alert = 60;
|
||||
#endif
|
||||
|
||||
if (!uwsgi_cheaper_busyness_global.min_multi) {
|
||||
@@ -179,7 +163,6 @@ int cheaper_busyness_algo(void) {
|
||||
#ifdef __linux__
|
||||
uwsgi_log("[busyness] backlog alert is set to %d request(s), step is %d\n",
|
||||
uwsgi_cheaper_busyness_global.backlog_alert, uwsgi_cheaper_busyness_global.backlog_step);
|
||||
uwsgi_log("[busyness] backlog non-zero alert is set to %llu second(s)\n", uwsgi_cheaper_busyness_global.backlog_nonzero_alert);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -193,11 +176,9 @@ int cheaper_busyness_algo(void) {
|
||||
uint64_t avg_busyness = 0;
|
||||
|
||||
for (i = 0; i < uwsgi.numproc; i++) {
|
||||
|
||||
if (uwsgi.workers[i+1].cheaped == 0 && uwsgi.workers[i+1].pid > 0) {
|
||||
active_workers++;
|
||||
uwsgi_cheaper_busyness_global.was_busy[i] += uwsgi_worker_is_busy(i+1);
|
||||
} else {
|
||||
uwsgi_cheaper_busyness_global.was_busy[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,19 +192,7 @@ int cheaper_busyness_algo(void) {
|
||||
for (i = 0; i < uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i+1].cheaped == 0 && uwsgi.workers[i+1].pid > 0) {
|
||||
uint64_t percent = (( (uwsgi.workers[i+1].running_time-uwsgi_cheaper_busyness_global.last_values[i])*100)/t);
|
||||
if (percent > 100) {
|
||||
percent = 100;
|
||||
}
|
||||
else if (uwsgi.workers[i+1].running_time-uwsgi_cheaper_busyness_global.last_values[i] == 0 && percent == 0 && uwsgi_cheaper_busyness_global.was_busy[i] > 0) {
|
||||
// running_time did not change but workers were busy
|
||||
// this means that workers had response times > busyness check interval
|
||||
if (uwsgi_cheaper_busyness_global.verbose) {
|
||||
uwsgi_log("[busyness] worker %d was busy %d time(s) in last cycle but no request was completed during this time, marking as 100%% busy\n",
|
||||
i+1, uwsgi_cheaper_busyness_global.was_busy[i]);
|
||||
}
|
||||
percent = 100;
|
||||
}
|
||||
uwsgi_cheaper_busyness_global.was_busy[i] = 0;
|
||||
if (percent > 100) percent = 100;
|
||||
total_busyness += percent;
|
||||
if (uwsgi_cheaper_busyness_global.verbose && active_workers > 1)
|
||||
uwsgi_log("[busyness] worker nr %d %llus average busyness is at %llu%%\n",
|
||||
@@ -344,36 +313,13 @@ int cheaper_busyness_algo(void) {
|
||||
uwsgi_cheaper_busyness_global.next_cheap += uwsgi.cheaper_overload*1000000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
else if (backlog > uwsgi_cheaper_busyness_global.backlog_alert && active_workers < uwsgi.numproc) {
|
||||
} else if (backlog > uwsgi_cheaper_busyness_global.backlog_alert && active_workers < uwsgi.numproc) {
|
||||
// we check for backlog overload every cycle
|
||||
return spawn_emergency_worker(backlog);
|
||||
}
|
||||
else if (backlog > 0) {
|
||||
if (uwsgi_cheaper_busyness_global.backlog_is_nonzero) {
|
||||
// backlog was > 0 last time, check timestamp and spawn workers if needed
|
||||
if ((now - uwsgi_cheaper_busyness_global.backlog_nonzero_since)/1000000 >= uwsgi_cheaper_busyness_global.backlog_nonzero_alert) {
|
||||
uwsgi_log("[busyness] backlog was non-zero for %llu second(s), spawning new worker(s)\n", (now - uwsgi_cheaper_busyness_global.backlog_nonzero_since)/1000000);
|
||||
uwsgi_cheaper_busyness_global.backlog_nonzero_since = now;
|
||||
return spawn_emergency_worker(backlog);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// this is first > 0 pass, setup timer
|
||||
if (uwsgi_cheaper_busyness_global.verbose)
|
||||
uwsgi_log("[busyness] backlog is starting to fill (%d)\n", backlog);
|
||||
uwsgi_cheaper_busyness_global.backlog_is_nonzero = 1;
|
||||
uwsgi_cheaper_busyness_global.backlog_nonzero_since = now;
|
||||
}
|
||||
}
|
||||
else if (uwsgi_cheaper_busyness_global.backlog_is_nonzero) {
|
||||
if (uwsgi_cheaper_busyness_global.verbose)
|
||||
uwsgi_log("[busyness] backlog is now empty\n");
|
||||
uwsgi_cheaper_busyness_global.backlog_is_nonzero = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+375
-394
@@ -16,104 +16,6 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
#include "cr.h"
|
||||
|
||||
struct corerouter_peer *uwsgi_cr_peer_find_by_sid(struct corerouter_session *cs, uint32_t sid) {
|
||||
|
||||
struct corerouter_peer *peers = cs->peers;
|
||||
while(peers) {
|
||||
if (peers->sid == sid) {
|
||||
return peers;
|
||||
}
|
||||
peers = peers->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// add a new peer to the session
|
||||
struct corerouter_peer *uwsgi_cr_peer_add(struct corerouter_session *cs) {
|
||||
struct corerouter_peer *old_peers = NULL, *peers = cs->peers;
|
||||
|
||||
while(peers) {
|
||||
old_peers = peers;
|
||||
peers = peers->next;
|
||||
}
|
||||
|
||||
peers = uwsgi_calloc(sizeof(struct corerouter_peer));
|
||||
peers->session = cs;
|
||||
peers->fd = -1;
|
||||
// create input buffer
|
||||
peers->in = uwsgi_buffer_new(uwsgi.page_size);
|
||||
// add timeout
|
||||
peers->timeout = cr_add_timeout(cs->corerouter, peers);
|
||||
// check retry
|
||||
if (cs->retry) {
|
||||
peers->can_retry = 1;
|
||||
}
|
||||
peers->prev = old_peers;
|
||||
|
||||
if (old_peers) {
|
||||
old_peers->next = peers;
|
||||
}
|
||||
else {
|
||||
cs->peers = peers;
|
||||
}
|
||||
|
||||
return peers;
|
||||
}
|
||||
|
||||
// reset a peer (allows it to connect to another backend)
|
||||
void uwsgi_cr_peer_reset(struct corerouter_peer *peer) {
|
||||
if (peer->tmp_socket_name) {
|
||||
free(peer->tmp_socket_name);
|
||||
peer->tmp_socket_name = NULL;
|
||||
}
|
||||
cr_del_timeout(peer->session->corerouter, peer);
|
||||
|
||||
if (peer->fd != -1) {
|
||||
close(peer->fd);
|
||||
peer->session->corerouter->cr_table[peer->fd] = NULL;
|
||||
peer->fd = -1;
|
||||
peer->hook_read = NULL;
|
||||
peer->hook_write = NULL;
|
||||
}
|
||||
|
||||
peer->failed = 0;
|
||||
peer->soopt = 0;
|
||||
peer->timed_out = 0;
|
||||
|
||||
peer->un = NULL;
|
||||
peer->static_node = NULL;
|
||||
}
|
||||
|
||||
// destroy a peer
|
||||
void uwsgi_cr_peer_del(struct corerouter_peer *peer) {
|
||||
struct corerouter_peer *prev = peer->prev;
|
||||
struct corerouter_peer *next = peer->next;
|
||||
|
||||
if (prev) {
|
||||
prev->next = peer->next;
|
||||
}
|
||||
|
||||
if (next) {
|
||||
next->prev = peer->prev;
|
||||
}
|
||||
|
||||
if (peer == peer->session->peers) {
|
||||
peer->session->peers = peer->next;
|
||||
}
|
||||
|
||||
uwsgi_cr_peer_reset(peer);
|
||||
|
||||
if (peer->in) {
|
||||
uwsgi_buffer_destroy(peer->in);
|
||||
}
|
||||
|
||||
// main_peer bring the output buffer from backend peers
|
||||
if (peer->out && peer->out_need_free) {
|
||||
uwsgi_buffer_destroy(peer->out);
|
||||
}
|
||||
free(peer);
|
||||
}
|
||||
|
||||
void uwsgi_opt_corerouter(char *opt, char *value, void *cr) {
|
||||
struct uwsgi_corerouter *ucr = (struct uwsgi_corerouter *) cr;
|
||||
uwsgi_new_gateway_socket(value, ucr->name);
|
||||
@@ -256,9 +158,6 @@ void corerouter_manage_subscription(char *key, uint16_t keylen, char *val, uint1
|
||||
else if (!uwsgi_strncmp("modifier1", 9, key, keylen)) {
|
||||
usr->modifier1 = uwsgi_str_num(val, vallen);
|
||||
}
|
||||
else if (!uwsgi_strncmp("modifier2", 9, key, keylen)) {
|
||||
usr->modifier2 = uwsgi_str_num(val, vallen);
|
||||
}
|
||||
else if (!uwsgi_strncmp("cores", 5, key, keylen)) {
|
||||
usr->cores = uwsgi_str_num(val, vallen);
|
||||
}
|
||||
@@ -277,160 +176,160 @@ void corerouter_manage_subscription(char *key, uint16_t keylen, char *val, uint1
|
||||
}
|
||||
}
|
||||
|
||||
void corerouter_close_peer(struct uwsgi_corerouter *ucr, struct corerouter_peer *peer) {
|
||||
struct corerouter_session *cs = peer->session;
|
||||
static struct uwsgi_rb_timer *corerouter_reset_timeout(struct uwsgi_corerouter *, struct corerouter_session *);
|
||||
|
||||
|
||||
// manage subscription reference count
|
||||
if (ucr->subscriptions && peer->un && peer->un->len > 0) {
|
||||
// decrease reference count
|
||||
void corerouter_close_session(struct uwsgi_corerouter *ucr, struct corerouter_session *cr_session) {
|
||||
|
||||
|
||||
if (cr_session->instance_fd != -1) {
|
||||
close(cr_session->instance_fd);
|
||||
ucr->cr_table[cr_session->instance_fd] = NULL;
|
||||
}
|
||||
|
||||
if (ucr->subscriptions && cr_session->un && cr_session->un->len > 0) {
|
||||
// decrease reference count
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[1] node %.*s refcnt: %llu\n", peer->un->len, peer->un->name, peer->un->reference);
|
||||
uwsgi_log("[1] node %.*s refcnt: %llu\n", cr_session->un->len, cr_session->un->name, cr_session->un->reference);
|
||||
#endif
|
||||
peer->un->reference--;
|
||||
cr_session->un->reference--;
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[2] node %.*s refcnt: %llu\n", peer->un->len, peer->un->name, peer->un->reference);
|
||||
uwsgi_log("[2] node %.*s refcnt: %llu\n", cr_session->un->len, cr_session->un->name, cr_session->un->reference);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (peer->failed) {
|
||||
|
||||
if (peer->soopt) {
|
||||
if (!ucr->quiet)
|
||||
uwsgi_log("[uwsgi-%s] unable to connect() to node \"%.*s\": %s\n", ucr->short_name, (int) peer->instance_address_len, peer->instance_address, strerror(peer->soopt));
|
||||
}
|
||||
else if (peer->timed_out) {
|
||||
if (peer->instance_address_len > 0) {
|
||||
if (peer->connecting) {
|
||||
if (!ucr->quiet)
|
||||
uwsgi_log("[uwsgi-%s] unable to connect() to node \"%.*s\": timeout\n", ucr->short_name, (int) peer->instance_address_len, peer->instance_address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now check for dead nodes
|
||||
if (ucr->subscriptions && peer->un && peer->un->len > 0) {
|
||||
if (cr_session->instance_failed) {
|
||||
|
||||
if (peer->un->death_mark == 0)
|
||||
uwsgi_log("[uwsgi-%s] %.*s => marking %.*s as failed\n", ucr->short_name, (int) peer->key_len, peer->key, (int) peer->instance_address_len, peer->instance_address);
|
||||
if (cr_session->soopt) {
|
||||
if (!ucr->quiet)
|
||||
uwsgi_log("[uwsgi-%s] unable to connect() to node \"%.*s\": %s\n", ucr->short_name, (int) cr_session->instance_address_len, cr_session->instance_address, strerror(cr_session->soopt));
|
||||
}
|
||||
else if (cr_session->timed_out) {
|
||||
if (cr_session->instance_address_len > 0) {
|
||||
if (cr_session->connecting) {
|
||||
if (!ucr->quiet)
|
||||
uwsgi_log("[uwsgi-%s] unable to connect() to node \"%.*s\": timeout\n", ucr->short_name, (int) cr_session->instance_address_len, cr_session->instance_address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
peer->un->failcnt++;
|
||||
peer->un->death_mark = 1;
|
||||
// now check for dead nodes
|
||||
if (ucr->subscriptions && cr_session->un && cr_session->un->len > 0) {
|
||||
|
||||
if (cr_session->un->death_mark == 0)
|
||||
uwsgi_log("[uwsgi-%s] %.*s => marking %.*s as failed\n", ucr->short_name, (int) cr_session->hostname_len, cr_session->hostname, (int) cr_session->instance_address_len, cr_session->instance_address);
|
||||
|
||||
cr_session->un->failcnt++;
|
||||
cr_session->un->death_mark = 1;
|
||||
// check if i can remove the node
|
||||
if (peer->un->reference == 0) {
|
||||
uwsgi_remove_subscribe_node(ucr->subscriptions, peer->un);
|
||||
if (cr_session->un->reference == 0) {
|
||||
uwsgi_remove_subscribe_node(ucr->subscriptions, cr_session->un);
|
||||
}
|
||||
if (ucr->cheap && !ucr->i_am_cheap && !ucr->fallback && uwsgi_no_subscriptions(ucr->subscriptions)) {
|
||||
uwsgi_gateway_go_cheap(ucr->name, ucr->queue, &ucr->i_am_cheap);
|
||||
}
|
||||
|
||||
}
|
||||
else if (peer->static_node) {
|
||||
peer->static_node->custom = uwsgi_now();
|
||||
uwsgi_log("[uwsgi-%s] %.*s => marking %.*s as failed\n", ucr->short_name, (int) peer->key_len, peer->key, (int) peer->instance_address_len, peer->instance_address);
|
||||
}
|
||||
else if (cr_session->static_node) {
|
||||
cr_session->static_node->custom = uwsgi_now();
|
||||
uwsgi_log("[uwsgi-%s] %.*s => marking %.*s as failed\n", ucr->short_name, (int) cr_session->hostname_len, cr_session->hostname, (int) cr_session->instance_address_len, cr_session->instance_address);
|
||||
}
|
||||
|
||||
// check if the router supports the retry hook
|
||||
if (!peer->can_retry) goto end;
|
||||
if (peer->retries >= (size_t) ucr->max_retries) goto end;
|
||||
|
||||
peer->retries++;
|
||||
// reset the peer
|
||||
uwsgi_cr_peer_reset(peer);
|
||||
// set new timeout
|
||||
peer->timeout = cr_add_timeout(ucr, peer);
|
||||
if (cr_session->tmp_socket_name) {
|
||||
free(cr_session->tmp_socket_name);
|
||||
cr_session->tmp_socket_name = NULL;
|
||||
}
|
||||
|
||||
if (!cr_session->retry) goto end;
|
||||
// check for max retries
|
||||
if (cr_session->retries >= (size_t) ucr->max_retries) goto end;
|
||||
|
||||
cr_session->retries++;
|
||||
|
||||
// reset error and timeout
|
||||
cr_session->instance_failed = 0;
|
||||
cr_session->timeout = corerouter_reset_timeout(ucr, cr_session);
|
||||
cr_session->timed_out = 0;
|
||||
cr_session->soopt = 0;
|
||||
|
||||
// reset nodes
|
||||
cr_session->un = NULL;
|
||||
cr_session->static_node = NULL;
|
||||
cr_session->instance_fd = -1;
|
||||
|
||||
// reset hooks (safe as fd is closed)
|
||||
cr_session->event_hook_read = NULL;
|
||||
cr_session->event_hook_write = NULL;
|
||||
cr_session->event_hook_instance_read = NULL;
|
||||
cr_session->event_hook_instance_write = NULL;
|
||||
|
||||
if (ucr->fallback) {
|
||||
// ok let's try with the fallback nodes
|
||||
if (!cs->fallback) {
|
||||
cs->fallback = ucr->fallback;
|
||||
}
|
||||
else {
|
||||
cs->fallback = cs->fallback->next;
|
||||
if (!cs->fallback) goto end;
|
||||
}
|
||||
if (!cr_session->fallback) {
|
||||
cr_session->fallback = ucr->fallback;
|
||||
}
|
||||
else {
|
||||
cr_session->fallback = cr_session->fallback->next;
|
||||
if (!cr_session->fallback) goto end;
|
||||
}
|
||||
|
||||
peer->instance_address = cs->fallback->value;
|
||||
peer->instance_address_len = cs->fallback->len;
|
||||
cr_session->instance_address = cr_session->fallback->value;
|
||||
cr_session->instance_address_len = cr_session->fallback->len;
|
||||
|
||||
if (cs->retry(peer)) {
|
||||
if (!peer->failed) goto end;
|
||||
}
|
||||
return;
|
||||
if (cr_session->retry(ucr, cr_session)) {
|
||||
if (!cr_session->instance_failed) goto end;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
cr_session->instance_address = NULL;
|
||||
cr_session->instance_address_len = 0;
|
||||
if (cr_session->retry(ucr, cr_session)) {
|
||||
if (!cr_session->instance_failed) goto end;
|
||||
}
|
||||
|
||||
peer->instance_address = NULL;
|
||||
peer->instance_address_len = 0;
|
||||
if (cs->retry(peer)) {
|
||||
if (!peer->failed) goto end;
|
||||
}
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
end:
|
||||
uwsgi_cr_peer_del(peer);
|
||||
|
||||
if (peer == cs->main_peer) {
|
||||
cs->main_peer = NULL;
|
||||
corerouter_close_session(ucr, cs);
|
||||
if (cr_session->tmp_socket_name) {
|
||||
free(cr_session->tmp_socket_name);
|
||||
}
|
||||
else {
|
||||
if (cs->can_keepalive == 0 && cs->wait_full_write == 0) {
|
||||
corerouter_close_session(ucr, cs);
|
||||
|
||||
if (cr_session->buf_file)
|
||||
fclose(cr_session->buf_file);
|
||||
|
||||
if (cr_session->buf_file_name) {
|
||||
if (unlink(cr_session->buf_file_name)) {
|
||||
uwsgi_error("unlink()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// destroy a session
|
||||
void corerouter_close_session(struct uwsgi_corerouter *ucr, struct corerouter_session *cr_session) {
|
||||
|
||||
struct corerouter_peer *main_peer = cr_session->main_peer;
|
||||
if (main_peer) {
|
||||
uwsgi_cr_peer_del(main_peer);
|
||||
}
|
||||
|
||||
// free peers
|
||||
struct corerouter_peer *peers = cr_session->peers;
|
||||
while(peers) {
|
||||
struct corerouter_peer *tmp_peer = peers;
|
||||
peers = peers->next;
|
||||
// special case here for subscription system
|
||||
if (ucr->subscriptions && tmp_peer->un && tmp_peer->un->len) {
|
||||
tmp_peer->un->reference--;
|
||||
}
|
||||
uwsgi_cr_peer_del(tmp_peer);
|
||||
free(cr_session->buf_file_name);
|
||||
}
|
||||
|
||||
// could be used to free additional resources
|
||||
if (cr_session->close)
|
||||
cr_session->close(cr_session);
|
||||
|
||||
close(cr_session->fd);
|
||||
ucr->cr_table[cr_session->fd] = NULL;
|
||||
|
||||
uwsgi_buffer_destroy(cr_session->buffer);
|
||||
|
||||
cr_del_timeout(ucr, cr_session);
|
||||
free(cr_session);
|
||||
|
||||
if (ucr->active_sessions == 0) {
|
||||
uwsgi_log("[BUG] number of active sessions already 0 !!!\n");
|
||||
return;
|
||||
}
|
||||
ucr->active_sessions--;
|
||||
}
|
||||
|
||||
struct uwsgi_rb_timer *corerouter_reset_timeout(struct uwsgi_corerouter *ucr, struct corerouter_peer *peer) {
|
||||
cr_del_timeout(ucr, peer);
|
||||
return cr_add_timeout(ucr, peer);
|
||||
static struct uwsgi_rb_timer *corerouter_reset_timeout(struct uwsgi_corerouter *ucr, struct corerouter_session *cr_session) {
|
||||
cr_del_timeout(ucr, cr_session);
|
||||
return cr_add_timeout(ucr, cr_session);
|
||||
}
|
||||
|
||||
struct uwsgi_rb_timer *corerouter_reset_timeout_fast(struct uwsgi_corerouter *ucr, struct corerouter_peer *peer, time_t now) {
|
||||
cr_del_timeout(ucr, peer);
|
||||
return cr_add_timeout_fast(ucr, peer, now);
|
||||
}
|
||||
static void corerouter_expire_timeouts(struct uwsgi_corerouter *ucr) {
|
||||
|
||||
|
||||
static void corerouter_expire_timeouts(struct uwsgi_corerouter *ucr, time_t now) {
|
||||
|
||||
uint64_t current = (uint64_t) now;
|
||||
uint64_t current = (uint64_t) uwsgi_now();
|
||||
struct uwsgi_rb_timer *urbt;
|
||||
struct corerouter_peer *peer;
|
||||
struct corerouter_session *cr_session;
|
||||
|
||||
for (;;) {
|
||||
urbt = uwsgi_min_rb_timer(ucr->timeouts, NULL);
|
||||
@@ -438,12 +337,12 @@ static void corerouter_expire_timeouts(struct uwsgi_corerouter *ucr, time_t now)
|
||||
return;
|
||||
|
||||
if (urbt->value <= current) {
|
||||
peer = (struct corerouter_peer *) urbt->data;
|
||||
peer->timed_out = 1;
|
||||
if (peer->connecting) {
|
||||
peer->failed = 1;
|
||||
cr_session = (struct corerouter_session *) urbt->data;
|
||||
cr_session->timed_out = 1;
|
||||
if (cr_session->connecting) {
|
||||
cr_session->instance_failed = 1;
|
||||
}
|
||||
corerouter_close_peer(ucr, peer);
|
||||
corerouter_close_session(ucr, cr_session);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -451,163 +350,237 @@ static void corerouter_expire_timeouts(struct uwsgi_corerouter *ucr, time_t now)
|
||||
}
|
||||
}
|
||||
|
||||
int uwsgi_cr_set_hooks(struct corerouter_peer *peer, ssize_t (*read_hook)(struct corerouter_peer *), ssize_t (*write_hook)(struct corerouter_peer *)) {
|
||||
struct corerouter_session *cs = peer->session;
|
||||
|
||||
int uwsgi_cr_hook_read(struct corerouter_session *cs, ssize_t (*hook)(struct corerouter_session *)) {
|
||||
|
||||
struct uwsgi_corerouter *ucr = cs->corerouter;
|
||||
|
||||
//uwsgi_log("uwsgi_cr_set_hooks(%d, %p, %p)\n", peer->fd, read_hook, write_hook);
|
||||
|
||||
if (read_hook) {
|
||||
peer->last_hook_read = read_hook;
|
||||
}
|
||||
|
||||
if (write_hook) {
|
||||
peer->last_hook_write = write_hook;
|
||||
}
|
||||
|
||||
int read_changed = 1;
|
||||
int write_changed = 1;
|
||||
|
||||
if (read_hook && peer->hook_read) {
|
||||
read_changed = 0;
|
||||
}
|
||||
else if (!read_hook && !peer->hook_read) {
|
||||
read_changed = 0;
|
||||
}
|
||||
|
||||
if (write_hook && peer->hook_write) {
|
||||
write_changed = 0;
|
||||
}
|
||||
else if (!write_hook && !peer->hook_write) {
|
||||
write_changed = 0;
|
||||
}
|
||||
|
||||
if (!read_changed && !write_changed) {
|
||||
goto unchanged;
|
||||
}
|
||||
|
||||
int has_read = 0;
|
||||
int has_write = 0;
|
||||
|
||||
if (peer->hook_read) {
|
||||
has_read = 1;
|
||||
}
|
||||
|
||||
if (peer->hook_write) {
|
||||
has_write = 1;
|
||||
}
|
||||
|
||||
if (!read_hook && !write_hook) {
|
||||
if (has_read) {
|
||||
if (event_queue_del_fd(ucr->queue, peer->fd, event_queue_read())) return -1;
|
||||
// first check the case of event removal
|
||||
if (hook == NULL) {
|
||||
// nothing changed
|
||||
if (!cs->event_hook_read) goto unchanged;
|
||||
// if there is a write event defined, le'ts modify it
|
||||
if (cs->event_hook_write) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_fd_readwrite_to_write() for %d\n", cs->fd);
|
||||
#endif
|
||||
if (event_queue_fd_readwrite_to_write(ucr->queue, cs->fd)) return -1;
|
||||
}
|
||||
if (has_write) {
|
||||
if (event_queue_del_fd(ucr->queue, peer->fd, event_queue_write())) return -1;
|
||||
// simply remove the read event
|
||||
else {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_del_fd() for %d\n", cs->fd);
|
||||
#endif
|
||||
if (event_queue_del_fd(ucr->queue, cs->fd, event_queue_read())) return -1;
|
||||
}
|
||||
}
|
||||
else if (read_hook && write_hook) {
|
||||
if (has_read) {
|
||||
if (event_queue_fd_read_to_readwrite(ucr->queue, peer->fd)) return -1;
|
||||
}
|
||||
else if (has_write) {
|
||||
if (event_queue_fd_write_to_readwrite(ucr->queue, peer->fd)) return -1;
|
||||
}
|
||||
}
|
||||
else if (read_hook) {
|
||||
if (has_write) {
|
||||
if (write_changed) {
|
||||
if (event_queue_fd_write_to_read(ucr->queue, peer->fd)) return -1;
|
||||
}
|
||||
else {
|
||||
if (event_queue_fd_write_to_readwrite(ucr->queue, peer->fd)) return -1;
|
||||
else {
|
||||
// set the hook
|
||||
// if write is not defined, simply add a single monitor
|
||||
if (cs->event_hook_write == NULL) {
|
||||
if (!cs->event_hook_read) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_add_fd_read() for %d\n", cs->fd);
|
||||
#endif
|
||||
if (event_queue_add_fd_read(ucr->queue, cs->fd)) return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (event_queue_add_fd_read(ucr->queue, peer->fd)) return -1;
|
||||
}
|
||||
}
|
||||
else if (write_hook) {
|
||||
if (has_read) {
|
||||
if (read_changed) {
|
||||
if (event_queue_fd_read_to_write(ucr->queue, peer->fd)) return -1;
|
||||
if (!cs->event_hook_read) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_fd_write_to_readwrite() for %d\n", cs->fd);
|
||||
#endif
|
||||
if (event_queue_fd_write_to_readwrite(ucr->queue, cs->fd)) return -1;
|
||||
}
|
||||
else {
|
||||
if (event_queue_fd_read_to_readwrite(ucr->queue, peer->fd)) return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (event_queue_add_fd_write(ucr->queue, peer->fd)) return -1;
|
||||
}
|
||||
}
|
||||
|
||||
unchanged:
|
||||
|
||||
peer->hook_read = read_hook;
|
||||
peer->hook_write = write_hook;
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_hook_read set to %p for %d\n", hook, cs->fd);
|
||||
#endif
|
||||
cs->event_hook_read = hook;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_cr_hook_write(struct corerouter_session *cs, ssize_t (*hook)(struct corerouter_session *)) {
|
||||
|
||||
struct uwsgi_corerouter *ucr = cs->corerouter;
|
||||
|
||||
// first check the case of event removal
|
||||
if (hook == NULL) {
|
||||
// nothing changed
|
||||
if (!cs->event_hook_write) goto unchanged;
|
||||
// if there is a read event defined, le'ts modify it
|
||||
if (cs->event_hook_read) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_fd_readwrite_to_read() for %d\n", cs->fd);
|
||||
#endif
|
||||
if (event_queue_fd_readwrite_to_read(ucr->queue, cs->fd)) return -1;
|
||||
}
|
||||
// simply remove the write event
|
||||
else {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_del_fd() for %d\n", cs->fd);
|
||||
#endif
|
||||
if (event_queue_del_fd(ucr->queue, cs->fd, event_queue_write())) return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// set the hook
|
||||
// if read is not defined, simply add a single monitor
|
||||
if (cs->event_hook_read == NULL) {
|
||||
if (!cs->event_hook_write) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_add_fd_write() for %d\n", cs->fd);
|
||||
#endif
|
||||
if (event_queue_add_fd_write(ucr->queue, cs->fd)) return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!cs->event_hook_write) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_fd_read_to_readwrite() for %d\n", cs->fd);
|
||||
#endif
|
||||
if (event_queue_fd_read_to_readwrite(ucr->queue, cs->fd)) return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unchanged:
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_hook_write set to %p for %d\n", hook, cs->fd);
|
||||
#endif
|
||||
cs->event_hook_write = hook;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_cr_hook_instance_read(struct corerouter_session *cs, ssize_t (*hook)(struct corerouter_session *)) {
|
||||
|
||||
struct uwsgi_corerouter *ucr = cs->corerouter;
|
||||
|
||||
// first check the case of event removal
|
||||
if (hook == NULL) {
|
||||
// nothing changed
|
||||
if (!cs->event_hook_instance_read) goto unchanged;
|
||||
// if there is a write event defined, le'ts modify it
|
||||
if (cs->event_hook_instance_write) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_fd_readwrite_to_write() for %d\n", cs->instance_fd);
|
||||
#endif
|
||||
if (event_queue_fd_readwrite_to_write(ucr->queue, cs->instance_fd)) return -1;
|
||||
}
|
||||
// simply remove the read event
|
||||
else {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_del_fd() for %d\n", cs->instance_fd);
|
||||
#endif
|
||||
if (event_queue_del_fd(ucr->queue, cs->instance_fd, event_queue_read())) return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// set the hook
|
||||
// if write is not defined, simply add a single monitor
|
||||
if (cs->event_hook_instance_write == NULL) {
|
||||
if (!cs->event_hook_instance_read) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_add_fd_read() for %d\n", cs->instance_fd);
|
||||
#endif
|
||||
if (event_queue_add_fd_read(ucr->queue, cs->instance_fd)) return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!cs->event_hook_instance_read) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_fd_write_to_readwrite() for %d\n", cs->instance_fd);
|
||||
#endif
|
||||
if (event_queue_fd_write_to_readwrite(ucr->queue, cs->instance_fd)) return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unchanged:
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_hook_instance_read set to %p for %d\n", hook, cs->instance_fd);
|
||||
#endif
|
||||
cs->event_hook_instance_read = hook;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_cr_hook_instance_write(struct corerouter_session *cs, ssize_t (*hook)(struct corerouter_session *)) {
|
||||
|
||||
struct uwsgi_corerouter *ucr = cs->corerouter;
|
||||
|
||||
// first check the case of event removal
|
||||
if (hook == NULL) {
|
||||
// nothing changed
|
||||
if (!cs->event_hook_instance_write) goto unchanged;
|
||||
// if there is a read event defined, le'ts modify it
|
||||
if (cs->event_hook_instance_read) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_fd_readwrite_to_read() for %d\n", cs->instance_fd);
|
||||
#endif
|
||||
if (event_queue_fd_readwrite_to_read(ucr->queue, cs->instance_fd)) return -1;
|
||||
}
|
||||
// simply remove the write event
|
||||
else {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_del_fd() for %d\n", cs->instance_fd);
|
||||
#endif
|
||||
if (event_queue_del_fd(ucr->queue, cs->instance_fd, event_queue_write())) return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// set the hook
|
||||
// if read is not defined, simply add a single monitor
|
||||
if (cs->event_hook_instance_read == NULL) {
|
||||
if (!cs->event_hook_instance_write) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_add_fd_write() for %d\n", cs->instance_fd);
|
||||
#endif
|
||||
if (event_queue_add_fd_write(ucr->queue, cs->instance_fd)) return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!cs->event_hook_instance_write) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_fd_read_to_readwrite() for %d\n", cs->instance_fd);
|
||||
#endif
|
||||
if (event_queue_fd_read_to_readwrite(ucr->queue, cs->instance_fd)) return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unchanged:
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_hook_instance_write set to %p for %d\n", hook, cs->instance_fd);
|
||||
#endif
|
||||
cs->event_hook_instance_write = hook;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct corerouter_session *corerouter_alloc_session(struct uwsgi_corerouter *ucr, struct uwsgi_gateway_socket *ugs, int new_connection, struct sockaddr *cr_addr, socklen_t cr_addr_len) {
|
||||
|
||||
struct corerouter_session *cs = uwsgi_calloc(ucr->session_size);
|
||||
|
||||
struct corerouter_peer *peer = uwsgi_calloc(sizeof(struct corerouter_peer));
|
||||
// main_peer has only input buffer as output buffer is taken from backend peers
|
||||
peer->in = uwsgi_buffer_new(uwsgi.page_size);
|
||||
|
||||
ucr->cr_table[new_connection] = peer;
|
||||
cs->main_peer = peer;
|
||||
|
||||
peer->fd = new_connection;
|
||||
peer->session = cs;
|
||||
ucr->cr_table[new_connection] = uwsgi_calloc(ucr->session_size);
|
||||
ucr->cr_table[new_connection]->fd = new_connection;
|
||||
ucr->cr_table[new_connection]->instance_fd = -1;
|
||||
|
||||
// map corerouter and socket
|
||||
cs->corerouter = ucr;
|
||||
cs->ugs = ugs;
|
||||
ucr->cr_table[new_connection]->corerouter = ucr;
|
||||
ucr->cr_table[new_connection]->ugs = ugs;
|
||||
|
||||
// set initial timeout
|
||||
peer->timeout = cr_add_timeout(ucr, ucr->cr_table[new_connection]);
|
||||
ucr->cr_table[new_connection]->timeout = cr_add_timeout(ucr, ucr->cr_table[new_connection]);
|
||||
|
||||
ucr->active_sessions++;
|
||||
|
||||
// build the client address
|
||||
memcpy(&cs->client_sockaddr, cr_addr, cr_addr_len);
|
||||
switch(cr_addr->sa_family) {
|
||||
case AF_INET:
|
||||
if (inet_ntop(AF_INET, &cs->client_sockaddr.sa_in.sin_addr, cs->client_address, cr_addr_len) == NULL) {
|
||||
uwsgi_error("corerouter_alloc_session/inet_ntop()");
|
||||
memcpy(cs->client_address, "0.0.0.0", 7);
|
||||
cs->client_port[0] = '0';
|
||||
cs->client_port[1] = 0;
|
||||
}
|
||||
uwsgi_num2str2(cs->client_sockaddr.sa_in.sin_port, cs->client_port);
|
||||
break;
|
||||
#ifdef AF_INET6
|
||||
case AF_INET6:
|
||||
if (inet_ntop(AF_INET6, &cs->client_sockaddr.sa_in6.sin6_addr, cs->client_address, cr_addr_len) == NULL) {
|
||||
uwsgi_error("corerouter_alloc_session/inet_ntop()");
|
||||
memcpy(cs->client_address, "0.0.0.0", 7);
|
||||
cs->client_port[0] = '0';
|
||||
cs->client_port[1] = 0;
|
||||
}
|
||||
uwsgi_num2str2(cs->client_sockaddr.sa_in6.sin6_port, cs->client_port);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
memcpy(cs->client_address, "0.0.0.0", 7);
|
||||
cs->client_port[0] = '0';
|
||||
cs->client_port[1] = 0;
|
||||
break;
|
||||
}
|
||||
// create dynamic buffer
|
||||
ucr->cr_table[new_connection]->buffer = uwsgi_buffer_new(uwsgi.page_size);
|
||||
|
||||
// here we prepare the real session and set the hooks
|
||||
if (ucr->alloc_session(ucr, ugs, cs, cr_addr, cr_addr_len)) {
|
||||
corerouter_close_session(ucr, cs);
|
||||
cs = NULL;
|
||||
}
|
||||
ucr->alloc_session(ucr, ugs, ucr->cr_table[new_connection], cr_addr, cr_addr_len);
|
||||
|
||||
return cs;
|
||||
return ucr->cr_table[new_connection];
|
||||
}
|
||||
|
||||
void uwsgi_corerouter_loop(int id, void *data) {
|
||||
@@ -633,7 +606,7 @@ void uwsgi_corerouter_loop(int id, void *data) {
|
||||
|
||||
|
||||
if (!ucr->socket_timeout)
|
||||
ucr->socket_timeout = 60;
|
||||
ucr->socket_timeout = 30;
|
||||
|
||||
if (!ucr->static_node_gracetime)
|
||||
ucr->static_node_gracetime = 30;
|
||||
@@ -686,6 +659,7 @@ void uwsgi_corerouter_loop(int id, void *data) {
|
||||
|
||||
struct uwsgi_rb_timer *min_timeout;
|
||||
|
||||
int interesting_fd;
|
||||
int new_connection;
|
||||
|
||||
|
||||
@@ -696,13 +670,11 @@ void uwsgi_corerouter_loop(int id, void *data) {
|
||||
union uwsgi_sockaddr cr_addr;
|
||||
socklen_t cr_addr_len = sizeof(struct sockaddr_un);
|
||||
|
||||
struct corerouter_session *cr_session;
|
||||
|
||||
ucr->mapper = uwsgi_cr_map_use_void;
|
||||
|
||||
if (ucr->use_cache) {
|
||||
ucr->cache = uwsgi_cache_by_name(ucr->use_cache);
|
||||
if (!ucr->cache) {
|
||||
uwsgi_log("unable to find cache \"%s\"\n", ucr->use_cache);
|
||||
}
|
||||
ucr->mapper = uwsgi_cr_map_use_cache;
|
||||
}
|
||||
else if (ucr->pattern) {
|
||||
@@ -726,22 +698,24 @@ void uwsgi_corerouter_loop(int id, void *data) {
|
||||
else if (ucr->static_nodes) {
|
||||
ucr->mapper = uwsgi_cr_map_use_static_nodes;
|
||||
}
|
||||
else if (ucr->use_cluster) {
|
||||
ucr->mapper = uwsgi_cr_map_use_cluster;
|
||||
}
|
||||
|
||||
|
||||
ucr->timeouts = uwsgi_init_rb_timer();
|
||||
|
||||
for (;;) {
|
||||
|
||||
time_t now = uwsgi_now();
|
||||
|
||||
// set timeouts and harakiri
|
||||
min_timeout = uwsgi_min_rb_timer(ucr->timeouts, NULL);
|
||||
if (min_timeout == NULL) {
|
||||
delta = -1;
|
||||
}
|
||||
else {
|
||||
delta = min_timeout->value - now;
|
||||
delta = min_timeout->value - uwsgi_now();
|
||||
if (delta <= 0) {
|
||||
corerouter_expire_timeouts(ucr, now);
|
||||
corerouter_expire_timeouts(ucr);
|
||||
delta = 0;
|
||||
}
|
||||
}
|
||||
@@ -753,37 +727,35 @@ void uwsgi_corerouter_loop(int id, void *data) {
|
||||
// wait for events
|
||||
nevents = event_queue_wait_multi(ucr->queue, delta, events, ucr->nevents);
|
||||
|
||||
now = uwsgi_now();
|
||||
|
||||
if (uwsgi.master_process && ucr->harakiri > 0) {
|
||||
ushared->gateways_harakiri[id] = now + ucr->harakiri;
|
||||
ushared->gateways_harakiri[id] = uwsgi_now() + ucr->harakiri;
|
||||
}
|
||||
|
||||
if (nevents == 0) {
|
||||
corerouter_expire_timeouts(ucr, now);
|
||||
corerouter_expire_timeouts(ucr);
|
||||
}
|
||||
|
||||
for (i = 0; i < nevents; i++) {
|
||||
|
||||
// get the interesting fd
|
||||
ucr->interesting_fd = event_queue_interesting_fd(events, i);
|
||||
interesting_fd = event_queue_interesting_fd(events, i);
|
||||
// something bad happened
|
||||
if (ucr->interesting_fd < 0) continue;
|
||||
if (interesting_fd < 0) continue;
|
||||
|
||||
// check if the ucr->interesting_fd matches a gateway socket
|
||||
// check if the interesting_fd matches a gateway socket
|
||||
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
|
||||
int taken = 0;
|
||||
while (ugs) {
|
||||
if (ugs->gateway == &ushared->gateways[id] && ucr->interesting_fd == ugs->fd) {
|
||||
if (ugs->gateway == &ushared->gateways[id] && interesting_fd == ugs->fd) {
|
||||
if (!ugs->subscription) {
|
||||
#if defined(__linux__) && defined(SOCK_NONBLOCK) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
new_connection = accept4(ucr->interesting_fd, (struct sockaddr *) &cr_addr, &cr_addr_len, SOCK_NONBLOCK);
|
||||
new_connection = accept4(interesting_fd, (struct sockaddr *) &cr_addr, &cr_addr_len, SOCK_NONBLOCK);
|
||||
if (new_connection < 0) {
|
||||
taken = 1;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
new_connection = accept(ucr->interesting_fd, (struct sockaddr *) &cr_addr, &cr_addr_len);
|
||||
new_connection = accept(interesting_fd, (struct sockaddr *) &cr_addr, &cr_addr_len);
|
||||
if (new_connection < 0) {
|
||||
taken = 1;
|
||||
break;
|
||||
@@ -793,9 +765,12 @@ void uwsgi_corerouter_loop(int id, void *data) {
|
||||
uwsgi_socket_nb(new_connection);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct corerouter_session *cr = corerouter_alloc_session(ucr, ugs, new_connection, (struct sockaddr *) &cr_addr, cr_addr_len);
|
||||
//something wrong in the allocation
|
||||
if (!cr) break;
|
||||
if (cr->instance_failed) {
|
||||
corerouter_close_session(ucr, cr);
|
||||
}
|
||||
}
|
||||
else if (ugs->subscription) {
|
||||
uwsgi_corerouter_manage_subscription(ucr, id, ugs);
|
||||
@@ -814,55 +789,63 @@ void uwsgi_corerouter_loop(int id, void *data) {
|
||||
}
|
||||
|
||||
// manage internal subscription
|
||||
if (ucr->interesting_fd == ushared->gateways[id].internal_subscription_pipe[1]) {
|
||||
uwsgi_corerouter_manage_internal_subscription(ucr, ucr->interesting_fd);
|
||||
if (interesting_fd == ushared->gateways[id].internal_subscription_pipe[1]) {
|
||||
uwsgi_corerouter_manage_internal_subscription(ucr, interesting_fd);
|
||||
}
|
||||
// manage a stats request
|
||||
else if (ucr->interesting_fd == ucr->cr_stats_server) {
|
||||
else if (interesting_fd == ucr->cr_stats_server) {
|
||||
corerouter_send_stats(ucr);
|
||||
}
|
||||
else {
|
||||
struct corerouter_peer *peer = ucr->cr_table[ucr->interesting_fd];
|
||||
cr_session = ucr->cr_table[interesting_fd];
|
||||
|
||||
// something is going wrong...
|
||||
if (peer == NULL)
|
||||
if (cr_session == NULL)
|
||||
continue;
|
||||
|
||||
// on error, destroy the session
|
||||
if (event_queue_interesting_fd_has_error(events, i)) {
|
||||
peer->failed = 1;
|
||||
corerouter_close_peer(ucr, peer);
|
||||
if (interesting_fd == cr_session->instance_fd) {
|
||||
cr_session->instance_failed = 1;
|
||||
}
|
||||
corerouter_close_session(ucr, cr_session);
|
||||
continue;
|
||||
}
|
||||
|
||||
// set timeout (in main_peer too)
|
||||
peer->timeout = corerouter_reset_timeout_fast(ucr, peer, now);
|
||||
peer->session->main_peer->timeout = corerouter_reset_timeout_fast(ucr, peer->session->main_peer, now);
|
||||
|
||||
ssize_t (*hook)(struct corerouter_peer *) = NULL;
|
||||
|
||||
// set timeout
|
||||
cr_session->timeout = corerouter_reset_timeout(ucr, cr_session);
|
||||
// call event hook
|
||||
if (event_queue_interesting_fd_is_read(events, i)) {
|
||||
hook = peer->hook_read;
|
||||
ssize_t (*hook)(struct corerouter_session *) = NULL;
|
||||
if (interesting_fd == cr_session->fd) {
|
||||
if (event_queue_interesting_fd_is_read(events, i)) {
|
||||
hook = cr_session->event_hook_read;
|
||||
}
|
||||
else if (event_queue_interesting_fd_is_write(events, i)) {
|
||||
hook = cr_session->event_hook_write;
|
||||
}
|
||||
}
|
||||
else if (event_queue_interesting_fd_is_write(events, i)) {
|
||||
hook = peer->hook_write;
|
||||
else if (interesting_fd == cr_session->instance_fd) {
|
||||
if (event_queue_interesting_fd_is_read(events, i)) {
|
||||
hook = cr_session->event_hook_instance_read;
|
||||
}
|
||||
else if (event_queue_interesting_fd_is_write(events, i)) {
|
||||
hook = cr_session->event_hook_instance_write;
|
||||
}
|
||||
}
|
||||
|
||||
// not having a hook could mean a previous event in the loop cleared it...
|
||||
if (!hook) continue;
|
||||
// reset errno (as we use it for internal signalling)
|
||||
errno = 0;
|
||||
ssize_t ret = hook(peer);
|
||||
ssize_t ret = hook(cr_session);
|
||||
// connection closed
|
||||
if (ret == 0) {
|
||||
corerouter_close_peer(ucr, peer);
|
||||
corerouter_close_session(ucr, cr_session);
|
||||
continue;
|
||||
}
|
||||
else if (ret < 0) {
|
||||
if (errno == EINPROGRESS) continue;
|
||||
// remove keepalive on error
|
||||
peer->session->can_keepalive = 0;
|
||||
corerouter_close_peer(ucr, peer);
|
||||
corerouter_close_session(ucr, cr_session);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -883,7 +866,8 @@ int uwsgi_corerouter_has_backends(struct uwsgi_corerouter *ucr) {
|
||||
ucr->base ||
|
||||
(ucr->code_string_code && ucr->code_string_function) ||
|
||||
ucr->to_socket ||
|
||||
ucr->static_nodes
|
||||
ucr->static_nodes ||
|
||||
ucr->use_cluster
|
||||
) {
|
||||
return 1;
|
||||
}
|
||||
@@ -966,8 +950,6 @@ void corerouter_send_stats(struct uwsgi_corerouter *ucr) {
|
||||
char *cwd = uwsgi_get_cwd();
|
||||
if (uwsgi_stats_keyval_comma(us, "cwd", cwd)) goto end0;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "active_sessions", (unsigned long long) ucr->active_sessions)) goto end0;
|
||||
|
||||
if (uwsgi_stats_key(us , ucr->short_name)) goto end0;
|
||||
if (uwsgi_stats_list_open(us)) goto end0;
|
||||
|
||||
@@ -1038,7 +1020,6 @@ void corerouter_send_stats(struct uwsgi_corerouter *ucr) {
|
||||
if (uwsgi_stats_keylong_comma(us, "modifier2", (unsigned long long) s_node->modifier2)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "last_check", (unsigned long long) s_node->last_check)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "requests", (unsigned long long) s_node->requests)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "last_requests", (unsigned long long) s_node->last_requests)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "tx", (unsigned long long) s_node->transferred)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "cores", (unsigned long long) s_node->cores)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "load", (unsigned long long) s_node->load)) goto end0;
|
||||
|
||||
+71
-221
@@ -3,197 +3,28 @@
|
||||
#define COREROUTER_STATUS_RECV_HDR 2
|
||||
#define COREROUTER_STATUS_RESPONSE 3
|
||||
|
||||
#define cr_add_timeout(u, x) uwsgi_add_rb_timer(u->timeouts, uwsgi_now()+u->socket_timeout, x)
|
||||
#define cr_add_timeout_fast(u, x, t) uwsgi_add_rb_timer(u->timeouts, t+u->socket_timeout, x)
|
||||
#define cr_add_timeout(u, x) uwsgi_add_rb_timer(u->timeouts, time(NULL)+u->socket_timeout, x)
|
||||
#define cr_add_fake_timeout(u, x) uwsgi_add_rb_timer(u->timeouts, time(NULL)+1, x)
|
||||
#define cr_add_check_timeout(x) uwsgi_add_rb_timer(timeouts, time(NULL)+x, NULL)
|
||||
#define cr_del_check_timeout(x) uwsgi_del_rb_timer(timeouts, x);
|
||||
#define cr_del_timeout(u, x) uwsgi_del_rb_timer(u->timeouts, x->timeout); free(x->timeout);
|
||||
|
||||
#define uwsgi_cr_error(x, y) uwsgi_log("[uwsgi-%s client_addr: %s client_port: %s] %s: %s [%s line %d]\n", x->session->corerouter->short_name, x->session->client_address, x->session->client_port, y, strerror(errno), __FILE__, __LINE__)
|
||||
#define uwsgi_cr_log(x, y, ...) uwsgi_log("[uwsgi-%s client_addr: %s client_port: %s]" y, x->session->corerouter->short_name, x->session->client_address, x->session->client_port, __VA_ARGS__)
|
||||
|
||||
#define cr_try_again if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {\
|
||||
errno = EINPROGRESS;\
|
||||
return -1;\
|
||||
}
|
||||
|
||||
#define cr_write(peer, f) write(peer->fd, peer->out->buf + peer->out_pos, peer->out->pos - peer->out_pos);\
|
||||
if (len < 0) {\
|
||||
cr_try_again;\
|
||||
uwsgi_cr_error(peer, f);\
|
||||
return -1;\
|
||||
}\
|
||||
peer->out_pos += len;
|
||||
|
||||
#define cr_write_buf(peer, buf, f) write(peer->fd, buf + buf##_pos, buf->pos - buf##_pos);\
|
||||
if (len < 0) {\
|
||||
cr_try_again;\
|
||||
uwsgi_cr_error(peer, f);\
|
||||
return -1;\
|
||||
}\
|
||||
buf##_pos += len;
|
||||
|
||||
#define cr_write_complete(peer) peer->out_pos == peer->out->pos
|
||||
|
||||
#define cr_write_complete_buf(peer, buf) buf##_pos == buf->pos
|
||||
|
||||
#define cr_connect(peer, f) peer->fd = uwsgi_connectn(peer->instance_address, peer->instance_address_len, 0, 1);\
|
||||
if (peer->fd < 0) {\
|
||||
peer->failed = 1;\
|
||||
peer->soopt = errno;\
|
||||
return -1;\
|
||||
}\
|
||||
peer->session->corerouter->cr_table[peer->fd] = peer;\
|
||||
peer->connecting = 1;\
|
||||
cr_write_to_backend(peer, f);
|
||||
|
||||
#define cr_read(peer, f) read(peer->fd, peer->in->buf + peer->in->pos, peer->in->len - peer->in->pos);\
|
||||
if (len < 0) {\
|
||||
cr_try_again;\
|
||||
uwsgi_cr_error(peer, f);\
|
||||
return -1;\
|
||||
}\
|
||||
peer->in->pos += len;\
|
||||
|
||||
#define cr_read_exact(peer, l, f) read(peer->fd, peer->in->buf + peer->in->pos, (l - peer->in->pos));\
|
||||
if (len < 0) {\
|
||||
cr_try_again;\
|
||||
uwsgi_cr_error(peer, f);\
|
||||
return -1;\
|
||||
}\
|
||||
peer->in->pos += len;\
|
||||
|
||||
#define cr_reset_hooks(peer) if(!peer->session->main_peer->disabled) {\
|
||||
if (uwsgi_cr_set_hooks(peer->session->main_peer, peer->session->main_peer->last_hook_read, NULL)) return -1;\
|
||||
}\
|
||||
else {\
|
||||
if (uwsgi_cr_set_hooks(peer->session->main_peer, NULL, NULL)) return -1;\
|
||||
}\
|
||||
struct corerouter_peer *peers = peer->session->peers;\
|
||||
while(peers) {\
|
||||
if (uwsgi_cr_set_hooks(peers, peers->last_hook_read, NULL)) return -1;\
|
||||
peers = peers->next;\
|
||||
}
|
||||
|
||||
#define cr_reset_hooks_and_read(peer, f) if (uwsgi_cr_set_hooks(peer->session->main_peer, peer->session->main_peer->last_hook_read, NULL)) return -1;\
|
||||
peer->last_hook_read = f;\
|
||||
struct corerouter_peer *peers = peer->session->peers;\
|
||||
while(peers) {\
|
||||
if (uwsgi_cr_set_hooks(peers, peers->last_hook_read, NULL)) return -1;\
|
||||
peers = peers->next;\
|
||||
}
|
||||
|
||||
#define cr_write_to_main(peer, f) if (uwsgi_cr_set_hooks(peer->session->main_peer, NULL, f)) return -1;\
|
||||
struct corerouter_peer *peers = peer->session->peers;\
|
||||
while(peers) {\
|
||||
if (uwsgi_cr_set_hooks(peers, NULL, NULL)) return -1;\
|
||||
peers = peers->next;\
|
||||
}
|
||||
|
||||
#define cr_write_to_backend(peer, f) if (uwsgi_cr_set_hooks(peer->session->main_peer, NULL, NULL)) return -1;\
|
||||
if (uwsgi_cr_set_hooks(peer, NULL, f)) return -1;\
|
||||
struct corerouter_peer *peers = peer->session->peers;\
|
||||
while(peers) {\
|
||||
if (peers != peer) {\
|
||||
if (uwsgi_cr_set_hooks(peers, NULL, NULL)) return -1;\
|
||||
}\
|
||||
peers = peers->next;\
|
||||
}
|
||||
|
||||
#define cr_peer_connected(peer, f) socklen_t solen = sizeof(int);\
|
||||
if (getsockopt(peer->fd, SOL_SOCKET, SO_ERROR, (void *) (&peer->soopt), &solen) < 0) {\
|
||||
uwsgi_cr_error(peer, f "/getsockopt()");\
|
||||
peer->failed = 1;\
|
||||
return -1;\
|
||||
}\
|
||||
if (peer->soopt) {\
|
||||
peer->failed = 1;\
|
||||
return -1;\
|
||||
}\
|
||||
peer->connecting = 0;\
|
||||
peer->can_retry = 0;\
|
||||
if (peer->static_node) peer->static_node->custom2++;\
|
||||
if (peer->un) {\
|
||||
peer->un->requests++;\
|
||||
peer->un->last_requests++;\
|
||||
}\
|
||||
|
||||
|
||||
struct corerouter_session;
|
||||
|
||||
// a peer is a connection to a socket (a client or a backend) and can be monitored for events.
|
||||
struct corerouter_peer {
|
||||
// the file descriptor
|
||||
int fd;
|
||||
// the session
|
||||
struct corerouter_session *session;
|
||||
|
||||
// if set do not wait for events
|
||||
int disabled;
|
||||
|
||||
// hook to run on a read event
|
||||
ssize_t (*hook_read)(struct corerouter_peer *);
|
||||
ssize_t (*last_hook_read)(struct corerouter_peer *);
|
||||
// hook to run on a write event
|
||||
ssize_t (*hook_write)(struct corerouter_peer *);
|
||||
ssize_t (*last_hook_write)(struct corerouter_peer *);
|
||||
|
||||
// has the peer failed ?
|
||||
int failed;
|
||||
// is the peer connecting ?
|
||||
int connecting;
|
||||
// is there a connection error ?
|
||||
int soopt;
|
||||
// has the peer timed out ?
|
||||
int timed_out;
|
||||
// the timeout rb_tree
|
||||
struct uwsgi_rb_timer *timeout;
|
||||
|
||||
// each peer can map to a different instance
|
||||
char *tmp_socket_name;
|
||||
char *instance_address;
|
||||
uint64_t instance_address_len;
|
||||
|
||||
// backend info
|
||||
struct uwsgi_subscribe_node *un;
|
||||
struct uwsgi_string_list *static_node;
|
||||
|
||||
// incoming data
|
||||
struct uwsgi_buffer *in;
|
||||
// data to send
|
||||
struct uwsgi_buffer *out;
|
||||
// amount of sent data (partial write management)
|
||||
size_t out_pos;
|
||||
int out_need_free;
|
||||
|
||||
// stream id (could have various use)
|
||||
uint32_t sid;
|
||||
|
||||
// internal parser status
|
||||
int r_parser_status;
|
||||
|
||||
// can retry ?
|
||||
int can_retry;
|
||||
// how many retries ?
|
||||
uint16_t retries;
|
||||
|
||||
// parsed key
|
||||
char *key;
|
||||
uint16_t key_len;
|
||||
|
||||
uint8_t modifier1;
|
||||
uint8_t modifier2;
|
||||
|
||||
struct corerouter_peer *prev;
|
||||
struct corerouter_peer *next;
|
||||
};
|
||||
|
||||
struct uwsgi_corerouter {
|
||||
|
||||
char *name;
|
||||
char *short_name;
|
||||
size_t session_size;
|
||||
|
||||
int (*alloc_session)(struct uwsgi_corerouter *, struct uwsgi_gateway_socket *, struct corerouter_session *, struct sockaddr *, socklen_t);
|
||||
int (*mapper)(struct uwsgi_corerouter *, struct corerouter_peer *);
|
||||
void (*alloc_session)(struct uwsgi_corerouter *, struct uwsgi_gateway_socket *, struct corerouter_session *, struct sockaddr *, socklen_t);
|
||||
int (*mapper)(struct uwsgi_corerouter *, struct corerouter_session *);
|
||||
|
||||
int has_sockets;
|
||||
int has_backends;
|
||||
@@ -204,8 +35,7 @@ struct uwsgi_corerouter {
|
||||
|
||||
struct uwsgi_rbtree *timeouts;
|
||||
|
||||
char *use_cache;
|
||||
struct uwsgi_cache *cache;
|
||||
int use_cache;
|
||||
int nevents;
|
||||
|
||||
int max_retries;
|
||||
@@ -234,6 +64,8 @@ struct uwsgi_corerouter {
|
||||
int socket_num;
|
||||
struct uwsgi_socket *to_socket;
|
||||
|
||||
int use_cluster;
|
||||
|
||||
struct uwsgi_subscribe_slot **subscriptions;
|
||||
|
||||
struct uwsgi_string_list *fallback;
|
||||
@@ -244,6 +76,7 @@ struct uwsgi_corerouter {
|
||||
char *code_string_code;
|
||||
char *code_string_function;
|
||||
|
||||
|
||||
struct uwsgi_rb_timer *subscriptions_check;
|
||||
|
||||
int cheap;
|
||||
@@ -252,54 +85,72 @@ struct uwsgi_corerouter {
|
||||
int tolerance;
|
||||
int harakiri;
|
||||
|
||||
struct corerouter_peer **cr_table;
|
||||
|
||||
int interesting_fd;
|
||||
|
||||
uint64_t active_sessions;
|
||||
struct corerouter_session **cr_table;
|
||||
|
||||
};
|
||||
|
||||
// a session is started when a client connect to the router
|
||||
struct corerouter_session {
|
||||
|
||||
int fd;
|
||||
int instance_fd;
|
||||
|
||||
// corerouter related to this session
|
||||
struct uwsgi_corerouter *corerouter;
|
||||
// gateway socket related to this session
|
||||
struct uwsgi_gateway_socket *ugs;
|
||||
|
||||
// the list of fallback instances
|
||||
// parsed hostname
|
||||
char *hostname;
|
||||
uint16_t hostname_len;
|
||||
|
||||
int has_key;
|
||||
int connecting;
|
||||
|
||||
char *instance_address;
|
||||
uint64_t instance_address_len;
|
||||
|
||||
struct uwsgi_subscribe_node *un;
|
||||
struct uwsgi_string_list *static_node;
|
||||
int soopt;
|
||||
int timed_out;
|
||||
|
||||
struct uwsgi_rb_timer *timeout;
|
||||
int instance_failed;
|
||||
|
||||
// check content_length
|
||||
size_t post_cl;
|
||||
size_t post_remains;
|
||||
|
||||
struct uwsgi_string_list *fallback;
|
||||
|
||||
char *buf_file_name;
|
||||
FILE *buf_file;
|
||||
|
||||
char *tmp_socket_name;
|
||||
|
||||
// store the client address
|
||||
struct sockaddr_un addr;
|
||||
socklen_t addr_len;
|
||||
|
||||
// async hooks:
|
||||
// the session is watiting for this fd
|
||||
ssize_t (*event_hook_read)(struct corerouter_session *);
|
||||
ssize_t (*event_hook_write)(struct corerouter_session *);
|
||||
ssize_t (*event_hook_instance_read)(struct corerouter_session *);
|
||||
ssize_t (*event_hook_instance_write)(struct corerouter_session *);
|
||||
|
||||
void (*close)(struct corerouter_session *);
|
||||
int (*retry)(struct corerouter_peer *);
|
||||
int (*retry)(struct uwsgi_corerouter *, struct corerouter_session *);
|
||||
size_t retries;
|
||||
|
||||
// leave the main peer alive
|
||||
int can_keepalive;
|
||||
// destroy the main peer after the last full write
|
||||
int wait_full_write;
|
||||
struct uwsgi_buffer *buffer;
|
||||
size_t buffer_len;
|
||||
off_t buffer_pos;
|
||||
|
||||
// this is the peer of the client
|
||||
struct corerouter_peer *main_peer;
|
||||
// this is the linked list of backends
|
||||
struct corerouter_peer *peers;
|
||||
|
||||
// connect after the next successfull write
|
||||
struct corerouter_peer *connect_peer_after_write;
|
||||
|
||||
union uwsgi_sockaddr client_sockaddr;
|
||||
#ifdef AF_INET6
|
||||
char client_address[INET6_ADDRSTRLEN];
|
||||
#else
|
||||
char client_address[INET_ADDRLEN];
|
||||
#endif
|
||||
|
||||
// use 11 bytes to be snprintf friendly
|
||||
char client_port[11];
|
||||
struct uwsgi_header uh;
|
||||
|
||||
uint8_t modifier1;
|
||||
uint8_t modifier2;
|
||||
};
|
||||
|
||||
void uwsgi_opt_corerouter(char *, char *, void *);
|
||||
@@ -323,21 +174,20 @@ int uwsgi_corerouter_init(struct uwsgi_corerouter *);
|
||||
struct corerouter_session *corerouter_alloc_session(struct uwsgi_corerouter *, struct uwsgi_gateway_socket *, int, struct sockaddr *, socklen_t);
|
||||
void corerouter_close_session(struct uwsgi_corerouter *, struct corerouter_session *);
|
||||
|
||||
int uwsgi_cr_map_use_void(struct uwsgi_corerouter *, struct corerouter_peer *);
|
||||
int uwsgi_cr_map_use_cache(struct uwsgi_corerouter *, struct corerouter_peer *);
|
||||
int uwsgi_cr_map_use_pattern(struct uwsgi_corerouter *, struct corerouter_peer *);
|
||||
int uwsgi_cr_map_use_cluster(struct uwsgi_corerouter *, struct corerouter_peer *);
|
||||
int uwsgi_cr_map_use_subscription(struct uwsgi_corerouter *, struct corerouter_peer *);
|
||||
int uwsgi_cr_map_use_subscription_dotsplit(struct uwsgi_corerouter *, struct corerouter_peer *);
|
||||
int uwsgi_cr_map_use_base(struct uwsgi_corerouter *, struct corerouter_peer *);
|
||||
int uwsgi_cr_map_use_cs(struct uwsgi_corerouter *, struct corerouter_peer *);
|
||||
int uwsgi_cr_map_use_to(struct uwsgi_corerouter *, struct corerouter_peer *);
|
||||
int uwsgi_cr_map_use_static_nodes(struct uwsgi_corerouter *, struct corerouter_peer *);
|
||||
int uwsgi_cr_map_use_void(struct uwsgi_corerouter *, struct corerouter_session *);
|
||||
int uwsgi_cr_map_use_cache(struct uwsgi_corerouter *, struct corerouter_session *);
|
||||
int uwsgi_cr_map_use_pattern(struct uwsgi_corerouter *, struct corerouter_session *);
|
||||
int uwsgi_cr_map_use_cluster(struct uwsgi_corerouter *, struct corerouter_session *);
|
||||
int uwsgi_cr_map_use_subscription(struct uwsgi_corerouter *, struct corerouter_session *);
|
||||
int uwsgi_cr_map_use_subscription_dotsplit(struct uwsgi_corerouter *, struct corerouter_session *);
|
||||
int uwsgi_cr_map_use_base(struct uwsgi_corerouter *, struct corerouter_session *);
|
||||
int uwsgi_cr_map_use_cs(struct uwsgi_corerouter *, struct corerouter_session *);
|
||||
int uwsgi_cr_map_use_to(struct uwsgi_corerouter *, struct corerouter_session *);
|
||||
int uwsgi_cr_map_use_static_nodes(struct uwsgi_corerouter *, struct corerouter_session *);
|
||||
|
||||
int uwsgi_corerouter_has_backends(struct uwsgi_corerouter *);
|
||||
|
||||
int uwsgi_cr_set_hooks(struct corerouter_peer *, ssize_t (*)(struct corerouter_peer *), ssize_t (*)(struct corerouter_peer *));
|
||||
struct corerouter_peer *uwsgi_cr_peer_add(struct corerouter_session *);
|
||||
struct corerouter_peer *uwsgi_cr_peer_find_by_sid(struct corerouter_session *, uint32_t);
|
||||
void corerouter_close_peer(struct uwsgi_corerouter *, struct corerouter_peer *);
|
||||
struct uwsgi_rb_timer *corerouter_reset_timeout(struct uwsgi_corerouter *, struct corerouter_peer *);
|
||||
int uwsgi_cr_hook_read(struct corerouter_session *, ssize_t (*)(struct corerouter_session *));
|
||||
int uwsgi_cr_hook_write(struct corerouter_session *, ssize_t (*)(struct corerouter_session *));
|
||||
int uwsgi_cr_hook_instance_read(struct corerouter_session *, ssize_t (*)(struct corerouter_session *));
|
||||
int uwsgi_cr_hook_instance_write(struct corerouter_session *, ssize_t (*)(struct corerouter_session *));
|
||||
|
||||
@@ -40,7 +40,7 @@ void uwsgi_corerouter_setup_sockets(struct uwsgi_corerouter *ucr) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
ugs->port = strrchr(ugs->name, ':');
|
||||
ugs->port = strchr(ugs->name, ':');
|
||||
int current_defer_accept = uwsgi.no_defer_accept;
|
||||
if (ugs->no_defer) {
|
||||
uwsgi.no_defer_accept = 1;
|
||||
@@ -59,15 +59,14 @@ void uwsgi_corerouter_setup_sockets(struct uwsgi_corerouter *ucr) {
|
||||
uwsgi.no_defer_accept = current_defer_accept;
|
||||
}
|
||||
}
|
||||
|
||||
// fix SERVER_PORT
|
||||
if (!ugs->port || !ugs->port_len) {
|
||||
ugs->port = strchr(ugs->name, ':');
|
||||
if (ugs->port) {
|
||||
ugs->port++;
|
||||
ugs->port_len = strlen(ugs->port);
|
||||
}
|
||||
}
|
||||
if (!ugs->port || !ugs->port_len) {
|
||||
ugs->port = strchr(ugs->name, ':');
|
||||
if (ugs->port) {
|
||||
ugs->port++;
|
||||
ugs->port_len = strlen(ugs->port);
|
||||
}
|
||||
}
|
||||
// put socket in non-blocking mode
|
||||
uwsgi_socket_nb(ugs->fd);
|
||||
uwsgi_log("%s bound on %s fd %d\n", ucr->name, ugs->name, ugs->fd);
|
||||
@@ -75,7 +74,12 @@ void uwsgi_corerouter_setup_sockets(struct uwsgi_corerouter *ucr) {
|
||||
else if (ugs->subscription) {
|
||||
if (ugs->fd == -1) {
|
||||
if (strchr(ugs->name, ':')) {
|
||||
#ifdef UWSGI_UDP
|
||||
ugs->fd = bind_to_udp(ugs->name, 0, 0);
|
||||
#else
|
||||
uwsgi_log("uWSGI has been built without UDP support !!!\n");
|
||||
exit(1);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
ugs->fd = bind_to_unix_dgram(ugs->name);
|
||||
|
||||
+67
-56
@@ -4,40 +4,38 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int uwsgi_cr_map_use_void(struct uwsgi_corerouter *ucr, struct corerouter_peer *peer) {
|
||||
int uwsgi_cr_map_use_void(struct uwsgi_corerouter *ucr, struct corerouter_session *cr_session) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_cr_map_use_cache(struct uwsgi_corerouter *ucr, struct corerouter_peer *peer) {
|
||||
uwsgi_rlock(ucr->cache->lock);
|
||||
peer->instance_address = uwsgi_cache_get2(ucr->cache, peer->key, peer->key_len, &peer->instance_address_len);
|
||||
char *cs_mod = uwsgi_str_contains(peer->instance_address, peer->instance_address_len, ',');
|
||||
int uwsgi_cr_map_use_cache(struct uwsgi_corerouter *ucr, struct corerouter_session *cr_session) {
|
||||
cr_session->instance_address = uwsgi_cache_get(cr_session->hostname, cr_session->hostname_len, &cr_session->instance_address_len);
|
||||
char *cs_mod = uwsgi_str_contains(cr_session->instance_address, cr_session->instance_address_len, ',');
|
||||
if (cs_mod) {
|
||||
peer->modifier1 = uwsgi_str_num(cs_mod + 1, (peer->instance_address_len - (cs_mod - peer->instance_address)) - 1);
|
||||
peer->instance_address_len = (cs_mod - peer->instance_address);
|
||||
cr_session->modifier1 = uwsgi_str_num(cs_mod + 1, (cr_session->instance_address_len - (cs_mod - cr_session->instance_address)) - 1);
|
||||
cr_session->instance_address_len = (cs_mod - cr_session->instance_address);
|
||||
}
|
||||
uwsgi_rwunlock(ucr->cache->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_cr_map_use_pattern(struct uwsgi_corerouter *ucr, struct corerouter_peer *peer) {
|
||||
size_t tmp_socket_name_len = 0;
|
||||
ucr->magic_table['s'] = uwsgi_concat2n(peer->key, peer->key_len, "", 0);
|
||||
peer->tmp_socket_name = magic_sub(ucr->pattern, ucr->pattern_len, &tmp_socket_name_len, ucr->magic_table);
|
||||
int uwsgi_cr_map_use_pattern(struct uwsgi_corerouter *ucr, struct corerouter_session *cr_session) {
|
||||
int tmp_socket_name_len = 0;
|
||||
ucr->magic_table['s'] = uwsgi_concat2n(cr_session->hostname, cr_session->hostname_len, "", 0);
|
||||
cr_session->tmp_socket_name = magic_sub(ucr->pattern, ucr->pattern_len, &tmp_socket_name_len, ucr->magic_table);
|
||||
free(ucr->magic_table['s']);
|
||||
peer->instance_address_len = tmp_socket_name_len;
|
||||
peer->instance_address = peer->tmp_socket_name;
|
||||
cr_session->instance_address_len = tmp_socket_name_len;
|
||||
cr_session->instance_address = cr_session->tmp_socket_name;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_cr_map_use_subscription(struct uwsgi_corerouter *ucr, struct corerouter_peer *peer) {
|
||||
int uwsgi_cr_map_use_subscription(struct uwsgi_corerouter *ucr, struct corerouter_session *cr_session) {
|
||||
|
||||
peer->un = uwsgi_get_subscribe_node(ucr->subscriptions, peer->key, peer->key_len);
|
||||
if (peer->un && peer->un->len) {
|
||||
peer->instance_address = peer->un->name;
|
||||
peer->instance_address_len = peer->un->len;
|
||||
peer->modifier1 = peer->un->modifier1;
|
||||
cr_session->un = uwsgi_get_subscribe_node(ucr->subscriptions, cr_session->hostname, cr_session->hostname_len);
|
||||
if (cr_session->un && cr_session->un->len) {
|
||||
cr_session->instance_address = cr_session->un->name;
|
||||
cr_session->instance_address_len = cr_session->un->len;
|
||||
cr_session->modifier1 = cr_session->un->modifier1;
|
||||
}
|
||||
else if (ucr->cheap && !ucr->i_am_cheap && uwsgi_no_subscriptions(ucr->subscriptions)) {
|
||||
uwsgi_gateway_go_cheap(ucr->name, ucr->queue, &ucr->i_am_cheap);
|
||||
@@ -46,17 +44,17 @@ int uwsgi_cr_map_use_subscription(struct uwsgi_corerouter *ucr, struct coreroute
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_cr_map_use_subscription_dotsplit(struct uwsgi_corerouter *ucr, struct corerouter_peer *peer) {
|
||||
int uwsgi_cr_map_use_subscription_dotsplit(struct uwsgi_corerouter *ucr, struct corerouter_session *cr_session) {
|
||||
|
||||
char *name = peer->key;
|
||||
uint16_t name_len = peer->key_len;
|
||||
char *name = cr_session->hostname;
|
||||
uint16_t name_len = cr_session->hostname_len;
|
||||
|
||||
split:
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("trying with %.*s\n", name_len, name);
|
||||
#endif
|
||||
peer->un = uwsgi_get_subscribe_node(ucr->subscriptions, name, name_len);
|
||||
if (!peer->un) {
|
||||
cr_session->un = uwsgi_get_subscribe_node(ucr->subscriptions, name, name_len);
|
||||
if (!cr_session->un) {
|
||||
char *next = memchr(name+1, '.', name_len-1);
|
||||
if (next) {
|
||||
name_len -= next - name;
|
||||
@@ -65,10 +63,10 @@ split:
|
||||
}
|
||||
}
|
||||
|
||||
if (peer->un && peer->un->len) {
|
||||
peer->instance_address = peer->un->name;
|
||||
peer->instance_address_len = peer->un->len;
|
||||
peer->modifier1 = peer->un->modifier1;
|
||||
if (cr_session->un && cr_session->un->len) {
|
||||
cr_session->instance_address = cr_session->un->name;
|
||||
cr_session->instance_address_len = cr_session->un->len;
|
||||
cr_session->modifier1 = cr_session->un->modifier1;
|
||||
}
|
||||
else if (ucr->cheap && !ucr->i_am_cheap && uwsgi_no_subscriptions(ucr->subscriptions)) {
|
||||
uwsgi_gateway_go_cheap(ucr->name, ucr->queue, &ucr->i_am_cheap);
|
||||
@@ -78,59 +76,72 @@ split:
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_cr_map_use_base(struct uwsgi_corerouter *ucr, struct corerouter_peer *peer) {
|
||||
int uwsgi_cr_map_use_base(struct uwsgi_corerouter *ucr, struct corerouter_session *cr_session) {
|
||||
|
||||
int tmp_socket_name_len = 0;
|
||||
|
||||
peer->tmp_socket_name = uwsgi_concat2nn(ucr->base, ucr->base_len, peer->key, peer->key_len, &tmp_socket_name_len);
|
||||
peer->instance_address_len = tmp_socket_name_len;
|
||||
peer->instance_address = peer->tmp_socket_name;
|
||||
cr_session->tmp_socket_name = uwsgi_concat2nn(ucr->base, ucr->base_len, cr_session->hostname, cr_session->hostname_len, &tmp_socket_name_len);
|
||||
cr_session->instance_address_len = tmp_socket_name_len;
|
||||
cr_session->instance_address = cr_session->tmp_socket_name;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_cr_map_use_cs(struct uwsgi_corerouter *ucr, struct corerouter_peer *peer) {
|
||||
int uwsgi_cr_map_use_cs(struct uwsgi_corerouter *ucr, struct corerouter_session *cr_session) {
|
||||
if (uwsgi.p[ucr->code_string_modifier1]->code_string) {
|
||||
char *name = uwsgi_concat2("uwsgi_", ucr->short_name);
|
||||
peer->instance_address = uwsgi.p[ucr->code_string_modifier1]->code_string(name, ucr->code_string_code, ucr->code_string_function, peer->key, peer->key_len);
|
||||
cr_session->instance_address = uwsgi.p[ucr->code_string_modifier1]->code_string(name, ucr->code_string_code, ucr->code_string_function, cr_session->hostname, cr_session->hostname_len);
|
||||
free(name);
|
||||
if (peer->instance_address) {
|
||||
peer->instance_address_len = strlen(peer->instance_address);
|
||||
char *cs_mod = uwsgi_str_contains(peer->instance_address, peer->instance_address_len, ',');
|
||||
if (cr_session->instance_address) {
|
||||
cr_session->instance_address_len = strlen(cr_session->instance_address);
|
||||
char *cs_mod = uwsgi_str_contains(cr_session->instance_address, cr_session->instance_address_len, ',');
|
||||
if (cs_mod) {
|
||||
peer->modifier1 = uwsgi_str_num(cs_mod + 1, (peer->instance_address_len - (cs_mod - peer->instance_address)) - 1);
|
||||
peer->instance_address_len = (cs_mod - peer->instance_address);
|
||||
cr_session->modifier1 = uwsgi_str_num(cs_mod + 1, (cr_session->instance_address_len - (cs_mod - cr_session->instance_address)) - 1);
|
||||
cr_session->instance_address_len = (cs_mod - cr_session->instance_address);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_cr_map_use_to(struct uwsgi_corerouter *ucr, struct corerouter_peer *peer) {
|
||||
peer->instance_address = ucr->to_socket->name;
|
||||
peer->instance_address_len = ucr->to_socket->name_len;
|
||||
int uwsgi_cr_map_use_to(struct uwsgi_corerouter *ucr, struct corerouter_session *cr_session) {
|
||||
cr_session->instance_address = ucr->to_socket->name;
|
||||
cr_session->instance_address_len = ucr->to_socket->name_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_cr_map_use_static_nodes(struct uwsgi_corerouter *ucr, struct corerouter_peer *peer) {
|
||||
int uwsgi_cr_map_use_cluster(struct uwsgi_corerouter *ucr, struct corerouter_session *cr_session) {
|
||||
#ifdef UWSGI_MULTICAST
|
||||
cr_session->instance_address = uwsgi_cluster_best_node();
|
||||
if (cr_session->instance_address) {
|
||||
cr_session->instance_address_len = strlen(cr_session->instance_address);
|
||||
}
|
||||
#else
|
||||
uwsgi_log("uWSGI has been built without multicast/clustering support !!!\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_cr_map_use_static_nodes(struct uwsgi_corerouter *ucr, struct corerouter_session *cr_session) {
|
||||
if (!ucr->current_static_node) {
|
||||
ucr->current_static_node = ucr->static_nodes;
|
||||
}
|
||||
|
||||
peer->static_node = ucr->current_static_node;
|
||||
cr_session->static_node = ucr->current_static_node;
|
||||
|
||||
// is it a dead node ?
|
||||
if (peer->static_node->custom > 0) {
|
||||
if (cr_session->static_node->custom > 0) {
|
||||
|
||||
// gracetime passed ?
|
||||
if (peer->static_node->custom + ucr->static_node_gracetime <= (uint64_t) uwsgi_now()) {
|
||||
peer->static_node->custom = 0;
|
||||
if (cr_session->static_node->custom + ucr->static_node_gracetime <= (uint64_t) uwsgi_now()) {
|
||||
cr_session->static_node->custom = 0;
|
||||
}
|
||||
else {
|
||||
struct uwsgi_string_list *tmp_node = peer->static_node;
|
||||
struct uwsgi_string_list *next_node = peer->static_node->next;
|
||||
peer->static_node = NULL;
|
||||
struct uwsgi_string_list *tmp_node = cr_session->static_node;
|
||||
struct uwsgi_string_list *next_node = cr_session->static_node->next;
|
||||
cr_session->static_node = NULL;
|
||||
// needed for 1-node only setups
|
||||
if (!next_node)
|
||||
next_node = ucr->static_nodes;
|
||||
@@ -144,7 +155,7 @@ int uwsgi_cr_map_use_static_nodes(struct uwsgi_corerouter *ucr, struct coreroute
|
||||
break;
|
||||
|
||||
if (next_node->custom == 0) {
|
||||
peer->static_node = next_node;
|
||||
cr_session->static_node = next_node;
|
||||
break;
|
||||
}
|
||||
next_node = next_node->next;
|
||||
@@ -152,12 +163,12 @@ int uwsgi_cr_map_use_static_nodes(struct uwsgi_corerouter *ucr, struct coreroute
|
||||
}
|
||||
}
|
||||
|
||||
if (peer->static_node) {
|
||||
if (cr_session->static_node) {
|
||||
|
||||
peer->instance_address = peer->static_node->value;
|
||||
peer->instance_address_len = peer->static_node->len;
|
||||
cr_session->instance_address = cr_session->static_node->value;
|
||||
cr_session->instance_address_len = cr_session->static_node->len;
|
||||
// set the next one
|
||||
ucr->current_static_node = peer->static_node->next;
|
||||
ucr->current_static_node = cr_session->static_node->next;
|
||||
}
|
||||
else {
|
||||
// set the next one
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user