mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ccf298a148 | ||
|
|
914b600af4 | ||
|
|
4944994667 | ||
|
|
3a487578a5 | ||
|
|
39eeccb16a | ||
|
|
32acd3b9d1 | ||
|
|
c57baae477 | ||
|
|
4a6ed633b9 | ||
|
|
2ab1845547 | ||
|
|
f4d2e1f20c | ||
|
|
81dca1f690 | ||
|
|
2b331fd68f | ||
|
|
cc77e4dba7 | ||
|
|
620a13a308 | ||
|
|
42d4ba09d7 | ||
|
|
ca071fa52f | ||
|
|
d38e5dec7b | ||
|
|
e5db38f7c0 | ||
|
|
68a29730c0 | ||
|
|
5c33c4d341 | ||
|
|
a1d6270089 | ||
|
|
1968175b00 | ||
|
|
cf1e2aeeba | ||
|
|
199b0b9f57 | ||
|
|
87a0daa465 | ||
|
|
c2af90b58f | ||
|
|
62f01453af | ||
|
|
375d6ee331 | ||
|
|
222ca2915b | ||
|
|
5ca848f9fe | ||
|
|
68d878ff6b | ||
|
|
782a7b418a | ||
|
|
724d7854ad | ||
|
|
f8e64d17e8 | ||
|
|
3b40799000 | ||
|
|
709964ca92 | ||
|
|
d2cdedc610 | ||
|
|
b7d0730343 | ||
|
|
30b4ea7d49 | ||
|
|
546dadbd06 | ||
|
|
76edf902de | ||
|
|
068024134c | ||
|
|
538ab57b6e | ||
|
|
fd6d9148f3 | ||
|
|
f033f59755 | ||
|
|
7168c6dd69 | ||
|
|
f121d41c2f | ||
|
|
e56e774eac | ||
|
|
6d9b0918a3 | ||
|
|
d445418611 | ||
|
|
6d15a51c9a | ||
|
|
42a615efdd | ||
|
|
54cd1f79a6 | ||
|
|
8ed8f46374 | ||
|
|
dd3a2996a4 | ||
|
|
bf1f90a96a | ||
|
|
2d6200231a | ||
|
|
032cd23304 | ||
|
|
de4c0a9e1c | ||
|
|
e33f8e8920 | ||
|
|
22615c7921 | ||
|
|
9d8809c580 | ||
|
|
96b92c98ff | ||
|
|
07939acecd | ||
|
|
30abcb2563 | ||
|
|
35ce8f2b8d | ||
|
|
d6453eab38 | ||
|
|
e0964d07ea | ||
|
|
fc359f1956 | ||
|
|
322261d65d | ||
|
|
bd1163c439 | ||
|
|
e203a8c706 | ||
|
|
6a1ba2af74 | ||
|
|
22569e64df | ||
|
|
dcafe41cde | ||
|
|
dd2adc08a3 | ||
|
|
d7534d2673 | ||
|
|
0a59920025 | ||
|
|
77602a8de4 | ||
|
|
65b3fde97c | ||
|
|
b690148452 | ||
|
|
4c7bc9ada6 | ||
|
|
432651489f | ||
|
|
82aa232a37 | ||
|
|
19b13bf7a7 | ||
|
|
f7e25d807d | ||
|
|
cf05316b95 | ||
|
|
001c4386b5 | ||
|
|
572527f8cb | ||
|
|
b4252beda6 | ||
|
|
d82ee16e0c | ||
|
|
e4d65c07ce | ||
|
|
86fcb78cc3 | ||
|
|
5beb422d75 | ||
|
|
53679879ca | ||
|
|
a8ad766182 | ||
|
|
cbb2d30f79 | ||
|
|
c5e00bcec6 | ||
|
|
51535d374d | ||
|
|
1e057e6c35 | ||
|
|
b23e8ab862 | ||
|
|
0f7f13dfb2 | ||
|
|
aa19ccda1d | ||
|
|
cd0129e780 | ||
|
|
506c9023e6 | ||
|
|
d47c25ea4c | ||
|
|
010651073c | ||
|
|
76364e3799 | ||
|
|
f9fd0a0203 | ||
|
|
8dfbde5d16 | ||
|
|
888991f8c1 | ||
|
|
ece03922d6 | ||
|
|
47bb827e6e | ||
|
|
a56003d847 | ||
|
|
61022c398c | ||
|
|
00bd8cc525 | ||
|
|
cf6a232aef | ||
|
|
59d1a45ef0 | ||
|
|
0b5f9fcb48 | ||
|
|
f713ffd6a1 | ||
|
|
22ba9d81d4 | ||
|
|
309bc98d7f | ||
|
|
9b8646a583 | ||
|
|
48d1b87ab8 | ||
|
|
c5f849d846 | ||
|
|
31fbb6e4f5 | ||
|
|
4d9a88e999 | ||
|
|
252e8484a8 | ||
|
|
1b89203932 | ||
|
|
2263c6a618 | ||
|
|
673cb3ee21 | ||
|
|
b4ecd504e3 | ||
|
|
f226f29428 | ||
|
|
b87a284390 | ||
|
|
f63dcd0d9c | ||
|
|
7f5563d581 | ||
|
|
d8a61a920e | ||
|
|
5a4900da8e | ||
|
|
677c30057a | ||
|
|
26113e091b | ||
|
|
1b5e98f593 | ||
|
|
0aa5201947 | ||
|
|
e3951baa3f | ||
|
|
9f9dbbab9e | ||
|
|
d546bbadbd | ||
|
|
2b7f25054f | ||
|
|
bb3f6bcf7e | ||
|
|
41da7175d1 | ||
|
|
446763b58a | ||
|
|
3e9337a0fc | ||
|
|
028806165b | ||
|
|
e4be42edbb | ||
|
|
230fa1f3bb | ||
|
|
d74653bbad | ||
|
|
38049b0897 | ||
|
|
b4af646929 | ||
|
|
b21ec73a52 | ||
|
|
c595844f0e | ||
|
|
fe8ee7c7b3 | ||
|
|
cd382c6bc0 | ||
|
|
e68296c293 | ||
|
|
cc189feae5 | ||
|
|
18e19027a1 | ||
|
|
2d2e0e4757 | ||
|
|
a9f50d79f9 | ||
|
|
0ccd31bee0 | ||
|
|
3ea82b2bcd | ||
|
|
6dad7b3ced | ||
|
|
f96ebd2b07 | ||
|
|
b8d0e7a3ac | ||
|
|
14cca3d497 | ||
|
|
c343ca0cc3 | ||
|
|
527d371bda | ||
|
|
b87a800a9a | ||
|
|
e406993ed1 | ||
|
|
eeff935fc9 | ||
|
|
0791394f1a | ||
|
|
082a407b06 | ||
|
|
8a89b49df1 | ||
|
|
2314b9cbab | ||
|
|
d0cca85c83 | ||
|
|
6a7a5cbcba | ||
|
|
ecccc82cc8 | ||
|
|
02693489fe | ||
|
|
0f5dba5828 | ||
|
|
e528d4c4b7 | ||
|
|
52a3af6acf | ||
|
|
dcefea9958 | ||
|
|
59121ff834 | ||
|
|
7f5bb6d472 | ||
|
|
639c1a508c | ||
|
|
417a26fc64 | ||
|
|
210ccd0063 | ||
|
|
1bf0162d38 | ||
|
|
e93027fd7e | ||
|
|
807060706f | ||
|
|
a317f88d3c | ||
|
|
e17a7f0701 | ||
|
|
db325eb9fe | ||
|
|
b41a4c8c3b | ||
|
|
73b4d11d18 | ||
|
|
8162b87287 | ||
|
|
70e9e4f3ee | ||
|
|
e61ae376b3 | ||
|
|
2d57b0e926 | ||
|
|
ae683af07a | ||
|
|
3c4f6a9171 | ||
|
|
39986e546c | ||
|
|
2e81a80f7b | ||
|
|
fcb3aa38c8 | ||
|
|
00a38d8ec5 | ||
|
|
07a0ab4227 | ||
|
|
d4a9a2c543 | ||
|
|
2b523fc60d | ||
|
|
0c26928236 | ||
|
|
8401e56a22 | ||
|
|
5109f9ae0b | ||
|
|
c9bc06669a | ||
|
|
a83fb2672c | ||
|
|
8f9ecb44d9 | ||
|
|
bfcc09a8de | ||
|
|
f8a8c997db | ||
|
|
132b996f30 | ||
|
|
12f970cdfb | ||
|
|
9afa963225 |
@@ -217,6 +217,45 @@ static int uwsgi_send_body(request_rec *r, proxy_conn_rec *conn)
|
||||
return OK;
|
||||
}
|
||||
|
||||
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
|
||||
static request_rec *ap_proxy_make_fake_req(conn_rec *c, request_rec *r)
|
||||
{
|
||||
apr_pool_t *pool;
|
||||
request_rec *rp;
|
||||
|
||||
apr_pool_create(&pool, c->pool);
|
||||
|
||||
rp = apr_pcalloc(pool, sizeof(*r));
|
||||
|
||||
rp->pool = pool;
|
||||
rp->status = HTTP_OK;
|
||||
|
||||
rp->headers_in = apr_table_make(pool, 50);
|
||||
rp->subprocess_env = apr_table_make(pool, 50);
|
||||
rp->headers_out = apr_table_make(pool, 12);
|
||||
rp->err_headers_out = apr_table_make(pool, 5);
|
||||
rp->notes = apr_table_make(pool, 5);
|
||||
|
||||
rp->server = r->server;
|
||||
rp->log = r->log;
|
||||
rp->proxyreq = r->proxyreq;
|
||||
rp->request_time = r->request_time;
|
||||
rp->connection = c;
|
||||
rp->output_filters = c->output_filters;
|
||||
rp->input_filters = c->input_filters;
|
||||
rp->proto_output_filters = c->output_filters;
|
||||
rp->proto_input_filters = c->input_filters;
|
||||
rp->useragent_ip = c->client_ip;
|
||||
rp->useragent_addr = c->client_addr;
|
||||
|
||||
rp->request_config = ap_create_request_config(pool);
|
||||
proxy_run_create_req(r, rp);
|
||||
|
||||
return rp;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_conf *conf)
|
||||
{
|
||||
|
||||
@@ -337,7 +376,11 @@ static int uwsgi_handler(request_rec *r, proxy_worker *worker,
|
||||
}
|
||||
|
||||
// ADD PATH_INFO
|
||||
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
|
||||
size_t w_len = strlen(worker->s->name);
|
||||
#else
|
||||
size_t w_len = strlen(worker->name);
|
||||
#endif
|
||||
char *u_path_info = r->filename + 6 + w_len;
|
||||
int delta = 0;
|
||||
if (u_path_info[0] != '/') {
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = python,gevent,psgi,lua,php,rack,jvm,jwsgi,ring,mono,transformation_toupper,coroae,v8,cgi
|
||||
inherit = base
|
||||
+1
-3
@@ -2,10 +2,8 @@
|
||||
xml = auto
|
||||
yaml = true
|
||||
json = auto
|
||||
sqlite3 = auto
|
||||
zeromq = auto
|
||||
ssl = auto
|
||||
ldap = auto
|
||||
pcre = auto
|
||||
routing = auto
|
||||
debug = false
|
||||
@@ -18,7 +16,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, router_static, sslrouter, spooler, cheaper_busyness, symcall, transformation_tofile, transformation_gzip
|
||||
as_shared_library = false
|
||||
|
||||
locking = auto
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = gridfs
|
||||
inherit = base
|
||||
@@ -2,10 +2,8 @@
|
||||
xml = true
|
||||
yaml = true
|
||||
json = true
|
||||
sqlite3 = true
|
||||
zeromq = true
|
||||
ssl = true
|
||||
ldap = true
|
||||
pcre = true
|
||||
routing = true
|
||||
debug = false
|
||||
|
||||
@@ -2,10 +2,8 @@
|
||||
xml = true
|
||||
yaml = true
|
||||
json = false
|
||||
sqlite3 = false
|
||||
zeromq = false
|
||||
ssl = true
|
||||
ldap = false
|
||||
pcre = true
|
||||
routing = true
|
||||
debug = false
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
the uwsgi handler is included in the official Cherokee distribution
|
||||
+139
-10
@@ -11,6 +11,29 @@ void uwsgi_alarm_func_signal(struct uwsgi_alarm_instance *uai, char *msg, size_t
|
||||
uwsgi_route_signal(uai->data8);
|
||||
}
|
||||
|
||||
// simply log an alarm
|
||||
void uwsgi_alarm_init_log(struct uwsgi_alarm_instance *uai) {
|
||||
}
|
||||
|
||||
void uwsgi_alarm_func_log(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
|
||||
if (msg[len-1] != '\n') {
|
||||
if (uai->arg && strlen(uai->arg) > 0) {
|
||||
uwsgi_log_alarm("] %s %.*s\n", uai->arg, len, msg);
|
||||
}
|
||||
else {
|
||||
uwsgi_log_alarm("] %.*s\n", len, msg);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uai->arg && strlen(uai->arg) > 0) {
|
||||
uwsgi_log_alarm("] %s %.*s", uai->arg, len, msg);
|
||||
}
|
||||
else {
|
||||
uwsgi_log_alarm("] %.*s", len, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// run a command on alarm
|
||||
void uwsgi_alarm_init_cmd(struct uwsgi_alarm_instance *uai) {
|
||||
uai->data_ptr = uai->arg;
|
||||
@@ -86,6 +109,7 @@ void uwsgi_register_embedded_alarms() {
|
||||
uwsgi_register_alarm("signal", uwsgi_alarm_init_signal, uwsgi_alarm_func_signal);
|
||||
uwsgi_register_alarm("cmd", uwsgi_alarm_init_cmd, uwsgi_alarm_func_cmd);
|
||||
uwsgi_register_alarm("mule", uwsgi_alarm_init_mule, uwsgi_alarm_func_mule);
|
||||
uwsgi_register_alarm("log", uwsgi_alarm_init_log, uwsgi_alarm_func_log);
|
||||
}
|
||||
|
||||
static int uwsgi_alarm_add(char *name, char *plugin, char *arg) {
|
||||
@@ -189,21 +213,54 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
|
||||
#endif
|
||||
|
||||
static void uwsgi_alarm_thread_loop(struct uwsgi_thread *ut) {
|
||||
// add uwsgi_alarm_fd;
|
||||
struct uwsgi_alarm_fd *uafd = uwsgi.alarm_fds;
|
||||
while(uafd) {
|
||||
event_queue_add_fd_read(ut->queue, uafd->fd);
|
||||
uafd = uafd->next;
|
||||
}
|
||||
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);
|
||||
if (interesting_fd == ut->pipe[1]) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
// check for alarm_fd
|
||||
else {
|
||||
uafd = uwsgi.alarm_fds;
|
||||
int fd_read = 0;
|
||||
while(uafd) {
|
||||
if (interesting_fd == uafd->fd) {
|
||||
if (fd_read) goto raise;
|
||||
size_t remains = uafd->buf_len;
|
||||
while(remains) {
|
||||
ssize_t len = read(uafd->fd, uafd->buf + (uafd->buf_len-remains), remains);
|
||||
if (len <= 0) {
|
||||
uwsgi_error("[uwsgi-alarm-fd]/read()");
|
||||
uwsgi_log("[uwsgi-alarm-fd] i will stop monitoring fd %d\n", uafd->fd);
|
||||
event_queue_del_fd(ut->queue, uafd->fd, event_queue_read());
|
||||
break;
|
||||
}
|
||||
remains-=len;
|
||||
}
|
||||
fd_read = 1;
|
||||
raise:
|
||||
uwsgi_alarm_run(uafd->alarm, uafd->msg, uafd->msg_len);
|
||||
}
|
||||
uafd = uafd->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -243,6 +300,37 @@ void uwsgi_alarms_init() {
|
||||
|
||||
if (!uwsgi.alarm_instances) return;
|
||||
|
||||
// map alarm file descriptors
|
||||
usl = uwsgi.alarm_fd_list;
|
||||
while(usl) {
|
||||
char *space0 = strchr(usl->value, ' ');
|
||||
if (!space0) {
|
||||
uwsgi_log("invalid alarm-fd syntax: %s\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
*space0 = 0;
|
||||
size_t buf_len = 1;
|
||||
char *space1 = strchr(space0+1, ' ');
|
||||
if (!space1) {
|
||||
uwsgi_log("invalid alarm-fd syntax: %s\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *colon = strchr(space0+1, ':');
|
||||
if (colon) {
|
||||
buf_len = strtoul(colon+1, NULL, 10);
|
||||
*colon = 0;
|
||||
}
|
||||
int fd = atoi(space0+1);
|
||||
uwsgi_add_alarm_fd(fd, usl->value, buf_len, space1+1, strlen(space1+1));
|
||||
*space0 = ' ';
|
||||
*space1 = ' ';
|
||||
if (colon) {
|
||||
*colon = ':';
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
// then map log-alarm
|
||||
usl = uwsgi.alarm_logs_list;
|
||||
@@ -340,3 +428,44 @@ void uwsgi_alarm_trigger(char *alarm_instance_name, char *msg, size_t len) {
|
||||
uwsgi_error("[uwsgi-alarm-error] uwsgi_alarm_trigger()/writev()");
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_alarm_fd *uwsgi_add_alarm_fd(int fd, char *alarm, size_t buf_len, char *msg, size_t msg_len) {
|
||||
struct uwsgi_alarm_fd *old_uafd = NULL, *uafd = uwsgi.alarm_fds;
|
||||
struct uwsgi_alarm_instance *uai = uwsgi_alarm_get_instance(alarm);
|
||||
if (!uai) {
|
||||
uwsgi_log("unable to find alarm \"%s\"\n", alarm);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!buf_len) buf_len = 1;
|
||||
|
||||
while(uafd) {
|
||||
// check if an equal alarm has been added
|
||||
if (uafd->fd == fd && uafd->alarm == uai) {
|
||||
return uafd;
|
||||
}
|
||||
old_uafd = uafd;
|
||||
uafd = uafd->next;
|
||||
}
|
||||
|
||||
uafd = uwsgi_calloc(sizeof(struct uwsgi_alarm_fd));
|
||||
uafd->fd = fd;
|
||||
uafd->buf = uwsgi_malloc(buf_len);
|
||||
uafd->buf_len = buf_len;
|
||||
uafd->msg = msg;
|
||||
uafd->msg_len = msg_len;
|
||||
uafd->alarm = uai;
|
||||
|
||||
if (!old_uafd) {
|
||||
uwsgi.alarm_fds = uafd;
|
||||
}
|
||||
else {
|
||||
old_uafd->next = uafd;
|
||||
}
|
||||
|
||||
// avoid the fd to be closed
|
||||
uwsgi_add_safe_fd(fd);
|
||||
uwsgi_log("[uwsgi-alarm] added fd %d\n", fd);
|
||||
|
||||
return uafd;
|
||||
}
|
||||
|
||||
+11
-16
@@ -52,7 +52,7 @@ static void runqueue_remove(struct uwsgi_async_request *u_request) {
|
||||
child->prev = parent;
|
||||
}
|
||||
|
||||
if (parent == NULL) {
|
||||
if (u_request == uwsgi.async_runqueue) {
|
||||
uwsgi.async_runqueue = child;
|
||||
}
|
||||
|
||||
@@ -67,25 +67,22 @@ static void runqueue_remove(struct uwsgi_async_request *u_request) {
|
||||
|
||||
static void runqueue_push(struct wsgi_request *wsgi_req) {
|
||||
|
||||
struct uwsgi_async_request *uar;
|
||||
struct uwsgi_async_request *uar = uwsgi_malloc(sizeof(struct uwsgi_async_request));
|
||||
uar->prev = NULL;
|
||||
uar->next = NULL;
|
||||
uar->wsgi_req = wsgi_req;
|
||||
|
||||
if (uwsgi.async_runqueue == NULL) {
|
||||
// empty runqueue, create a new one
|
||||
uwsgi.async_runqueue = uwsgi_malloc(sizeof(struct uwsgi_async_request));
|
||||
uwsgi.async_runqueue->next = NULL;
|
||||
uwsgi.async_runqueue->prev = NULL;
|
||||
uwsgi.async_runqueue->wsgi_req = wsgi_req;
|
||||
uwsgi.async_runqueue_last = uwsgi.async_runqueue;
|
||||
uwsgi.async_runqueue = uar;
|
||||
}
|
||||
else {
|
||||
uar = uwsgi_malloc(sizeof(struct uwsgi_async_request));
|
||||
uar->prev = uwsgi.async_runqueue_last;
|
||||
uar->next = NULL;
|
||||
uar->wsgi_req = wsgi_req;
|
||||
uwsgi.async_runqueue_last->next = uar;
|
||||
uwsgi.async_runqueue_last = uar;
|
||||
uar->prev = uwsgi.async_runqueue_last;
|
||||
}
|
||||
|
||||
if (uwsgi.async_runqueue_last) {
|
||||
uwsgi.async_runqueue_last->next = uar;
|
||||
}
|
||||
uwsgi.async_runqueue_last = uar;
|
||||
uwsgi.async_runqueue_cnt++;
|
||||
|
||||
}
|
||||
@@ -393,8 +390,6 @@ void async_loop() {
|
||||
continue;
|
||||
}
|
||||
else if (proto_parser_status < 0) {
|
||||
if (proto_parser_status == -1)
|
||||
uwsgi_log("error parsing request\n");
|
||||
uwsgi.async_proto_fd_table[interesting_fd] = NULL;
|
||||
close(interesting_fd);
|
||||
continue;
|
||||
|
||||
@@ -328,3 +328,29 @@ int uwsgi_buffer_set_uh(struct uwsgi_buffer *ub, uint8_t modifier1, uint8_t modi
|
||||
ub->buf[3] = modifier2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *uwsgi_buffer_from_file(char *filename) {
|
||||
struct stat st;
|
||||
int fd = open(filename, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fstat(fd, &st)) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(st.st_size);
|
||||
|
||||
ssize_t len = read(fd, ub->buf, st.st_size);
|
||||
close(fd);
|
||||
if (len != st.st_size) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ub->pos = len;
|
||||
return ub;
|
||||
}
|
||||
|
||||
|
||||
+175
-89
@@ -156,14 +156,14 @@ static void cache_send_udp_command(struct uwsgi_cache *, char *, uint16_t, char
|
||||
static void cache_sync_hook(char *k, uint16_t kl, char *v, uint16_t vl, void *data) {
|
||||
struct uwsgi_cache *uc = (struct uwsgi_cache *) data;
|
||||
if (!uwsgi_strncmp(k, kl, "items", 5)) {
|
||||
size_t num = uwsgi_str_num(v, vl);
|
||||
size_t num = uwsgi_str_num(v, vl);
|
||||
if (num != uc->max_items) {
|
||||
uwsgi_log("[cache-sync] invalid cache size, expected %llu received %llu\n", (unsigned long long) uc->max_items, (unsigned long long) num);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (!uwsgi_strncmp(k, kl, "blocksize", 9)) {
|
||||
size_t num = uwsgi_str_num(v, vl);
|
||||
size_t num = uwsgi_str_num(v, vl);
|
||||
if (num != uc->blocksize) {
|
||||
uwsgi_log("[cache-sync] invalid cache block size, expected %llu received %llu\n", (unsigned long long) uc->blocksize, (unsigned long long) num);
|
||||
exit(1);
|
||||
@@ -200,6 +200,40 @@ static void uwsgi_cache_load_files(struct uwsgi_cache *uc) {
|
||||
next:
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ZLIB
|
||||
usl = uwsgi.load_file_in_cache_gzip;
|
||||
while(usl) {
|
||||
size_t len = 0;
|
||||
char *value = NULL;
|
||||
char *key = usl->value;
|
||||
uint16_t key_len = usl->len;
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (space) {
|
||||
// need to skip ?
|
||||
if (uwsgi_strncmp(uc->name, uc->name_len, usl->value, space-usl->value)) {
|
||||
goto next2;
|
||||
}
|
||||
key = space+1;
|
||||
key_len = usl->len - ((space-usl->value)+1);
|
||||
}
|
||||
value = uwsgi_open_and_read(key, &len, 0, NULL);
|
||||
if (value) {
|
||||
struct uwsgi_buffer *gzipped = uwsgi_gzip(value, len);
|
||||
if (gzipped) {
|
||||
uwsgi_wlock(uc->lock);
|
||||
if (!uwsgi_cache_set2(uc, key, key_len, gzipped->buf, gzipped->len, 0, 0)) {
|
||||
uwsgi_log("[cache-gzip] stored \"%.*s\" in \"%s\"\n", key_len, key, uc->name);
|
||||
}
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
uwsgi_buffer_destroy(gzipped);
|
||||
}
|
||||
free(value);
|
||||
}
|
||||
next2:
|
||||
usl = usl->next;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -288,21 +322,7 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
|
||||
(unsigned long long) ((sizeof(struct uwsgi_cache_item)+uc->keysize) * uc->max_items), (unsigned long long) (uc->blocksize * uc->max_items),
|
||||
(unsigned long long) uc->blocks_bitmap_size);
|
||||
|
||||
|
||||
struct uwsgi_string_list *usl = uc->nodes;
|
||||
while(usl) {
|
||||
char *port = strchr(usl->value, ':');
|
||||
if (!port) {
|
||||
uwsgi_log("[cache-udp-node] invalid udp address: %s\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
// no need to zero the memory, socket_to_in_addr will do that
|
||||
struct sockaddr_in *sin = uwsgi_malloc(sizeof(struct sockaddr_in));
|
||||
usl->custom = socket_to_in_addr(usl->value, port, 0, sin);
|
||||
usl->custom_ptr = sin;
|
||||
uwsgi_log("added udp node %s for cache \"%s\"\n", usl->value, uc->name);
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_cache_setup_nodes(uc);
|
||||
|
||||
uc->udp_node_socket = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (uc->udp_node_socket < 0) {
|
||||
@@ -311,70 +331,10 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
|
||||
}
|
||||
uwsgi_socket_nb(uc->udp_node_socket);
|
||||
|
||||
usl = uc->sync_nodes;
|
||||
while(usl) {
|
||||
uwsgi_log("[cache-sync] getting cache dump from %s ...\n", usl->value);
|
||||
int fd = uwsgi_connect(usl->value, 0, 0);
|
||||
if (fd < 0) {
|
||||
uwsgi_log("[cache-sync] unable to connect to the cache server\n");
|
||||
goto next;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size + uc->filesize);
|
||||
ub->pos = 4;
|
||||
if (uwsgi_buffer_append(ub, uc->name, uc->name_len)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (uwsgi_buffer_set_uh(ub, 111, 6)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (uwsgi_write_nb(fd, ub->buf, ub->pos, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_log("[cache-sync] unable to write to the cache server\n");
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
size_t rlen = ub->pos;
|
||||
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_log("[cache-sync] unable to read from the cache server\n");
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
uwsgi_hooked_parse(ub->buf, ub->pos, cache_sync_hook, uc);
|
||||
|
||||
if (uwsgi_read_nb(fd, (char *) uc->items, uc->filesize, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
uwsgi_log("[cache-sync] unable to read from the cache server\n");
|
||||
goto next;
|
||||
}
|
||||
|
||||
// reset the hashtable
|
||||
memset(uc->hashtable, 0, sizeof(uint64_t) * UMAX16);
|
||||
// re-fill the hashtable
|
||||
uwsgi_cache_fix(uc);
|
||||
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
break;
|
||||
next:
|
||||
if (!usl->next) {
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("[cache-sync] trying with the next sync node...\n");
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_cache_sync_from_nodes(uc);
|
||||
|
||||
uwsgi_cache_load_files(uc);
|
||||
|
||||
}
|
||||
|
||||
static uint64_t uwsgi_cache_get_index(struct uwsgi_cache *uc, char *key, uint16_t keylen) {
|
||||
@@ -456,6 +416,28 @@ char *uwsgi_cache_get2(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint6
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *uwsgi_cache_get3(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint64_t * valsize, uint64_t *expires) {
|
||||
|
||||
uint64_t index = uwsgi_cache_get_index(uc, key, keylen);
|
||||
|
||||
if (index) {
|
||||
struct uwsgi_cache_item *uci = cache_item(index);
|
||||
if (uci->flags & UWSGI_CACHE_FLAG_UNGETTABLE)
|
||||
return NULL;
|
||||
*valsize = uci->valsize;
|
||||
if (expires)
|
||||
*expires = uci->expires;
|
||||
uci->hits++;
|
||||
uc->hits++;
|
||||
return uc->data + (uci->first_block * uc->blocksize);
|
||||
}
|
||||
|
||||
uc->miss++;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_cache_del2(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint64_t index, uint16_t flags) {
|
||||
|
||||
struct uwsgi_cache_item *uci;
|
||||
@@ -501,6 +483,10 @@ int uwsgi_cache_del2(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint64_
|
||||
uci->expires = 0;
|
||||
|
||||
uc->n_items--;
|
||||
|
||||
if (uc->use_last_modified) {
|
||||
uc->last_modified_at = uwsgi_now();
|
||||
}
|
||||
}
|
||||
|
||||
if (uc->nodes && ret == 0 && !(flags & UWSGI_CACHE_FLAG_LOCAL)) {
|
||||
@@ -533,7 +519,8 @@ void uwsgi_cache_fix(struct uwsgi_cache *uc) {
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("[uwsgi-cache] restored %llu items\n", restored);
|
||||
uc->n_items = restored;
|
||||
uwsgi_log("[uwsgi-cache] restored %llu items\n", uc->n_items);
|
||||
}
|
||||
|
||||
int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *val, uint64_t vallen, uint64_t expires, uint64_t flags) {
|
||||
@@ -546,6 +533,7 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
uint8_t rollback_mode = 0;
|
||||
|
||||
int ret = -1;
|
||||
time_t now = 0;
|
||||
|
||||
if (!keylen || !vallen)
|
||||
return -1;
|
||||
@@ -591,13 +579,13 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
uc->unused_blocks_stack_ptr++;
|
||||
}
|
||||
else if (rollback_mode == 2) {
|
||||
uc->first_available_block--;
|
||||
uc->first_available_block--;
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
// mark used blocks;
|
||||
uint64_t needed_blocks = cache_mark_blocks(uc, uci->first_block, vallen);
|
||||
// optimize teh scan
|
||||
uint64_t needed_blocks = cache_mark_blocks(uc, uci->first_block, vallen);
|
||||
// optimize the scan
|
||||
if (uc->blocks_bitmap_pos + (needed_blocks+1) > uc->blocks) {
|
||||
uc->blocks_bitmap_pos = 0;
|
||||
}
|
||||
@@ -605,8 +593,10 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
uc->blocks_bitmap_pos = uci->first_block + needed_blocks + 1;
|
||||
}
|
||||
}
|
||||
if (expires && !(flags & UWSGI_CACHE_FLAG_ABSEXPIRE))
|
||||
expires += uwsgi_now();
|
||||
if (expires && !(flags & UWSGI_CACHE_FLAG_ABSEXPIRE)) {
|
||||
now = uwsgi_now();
|
||||
expires += now;
|
||||
}
|
||||
uci->expires = expires;
|
||||
uci->hash = uc->hash->func(key, keylen);
|
||||
uci->hits = 0;
|
||||
@@ -645,7 +635,8 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
else if (flags & UWSGI_CACHE_FLAG_UPDATE) {
|
||||
uci = cache_item(index);
|
||||
if (expires && !(flags & UWSGI_CACHE_FLAG_ABSEXPIRE)) {
|
||||
expires += uwsgi_now();
|
||||
now = uwsgi_now();
|
||||
expires += now;
|
||||
uci->expires = expires;
|
||||
}
|
||||
if (uc->blocks_bitmap) {
|
||||
@@ -674,7 +665,11 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
uci->valsize = vallen;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
|
||||
if (uc->use_last_modified) {
|
||||
uc->last_modified_at = (now ? now : uwsgi_now());
|
||||
}
|
||||
|
||||
if (uc->nodes && ret == 0 && !(flags & UWSGI_CACHE_FLAG_LOCAL)) {
|
||||
cache_send_udp_command(uc, key, keylen, val, vallen, expires, 10);
|
||||
}
|
||||
@@ -952,6 +947,7 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
uc->nodes = uwsgi.cache_udp_node;
|
||||
uc->udp_servers = uwsgi.cache_udp_server;
|
||||
uc->store_sync = uwsgi.cache_store_sync;
|
||||
uc->use_last_modified = (uint8_t) uwsgi.cache_use_last_modified;
|
||||
|
||||
if (uwsgi.cache_sync) {
|
||||
uwsgi_string_new_list(&uc->sync_nodes, uwsgi.cache_sync);
|
||||
@@ -971,6 +967,7 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
char *c_sync = NULL;
|
||||
char *c_udp_servers = NULL;
|
||||
char *c_bitmap = NULL;
|
||||
char *c_use_last_modified = NULL;
|
||||
|
||||
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
|
||||
"name", &c_name,
|
||||
@@ -996,6 +993,7 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
"udpservers", &c_udp_servers,
|
||||
"udpserver", &c_udp_servers,
|
||||
"bitmap", &c_bitmap,
|
||||
"lastmod", &c_use_last_modified,
|
||||
NULL)) {
|
||||
uwsgi_log("unable to parse cache definition\n");
|
||||
exit(1);
|
||||
@@ -1040,6 +1038,7 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
uc->use_blocks_bitmap = 1;
|
||||
uc->max_item_size = uc->blocksize * uc->blocks;
|
||||
}
|
||||
if (c_use_last_modified) uc->use_last_modified = 1;
|
||||
|
||||
uc->store_sync = uwsgi.cache_store_sync;
|
||||
if (c_store_sync) { uc->store_sync = uwsgi_n64(c_store_sync); }
|
||||
@@ -1306,7 +1305,7 @@ static int cache_magic_send_and_manage(int fd, struct uwsgi_buffer *ub, char *st
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, char *cache) {
|
||||
char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, uint64_t *expires, char *cache) {
|
||||
struct uwsgi_cache_magic_context ucmc;
|
||||
struct uwsgi_cache *uc = NULL;
|
||||
char *cache_server = NULL;
|
||||
@@ -1331,7 +1330,7 @@ char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, char *
|
||||
// we have a local cache !!!
|
||||
if (uc) {
|
||||
uwsgi_rlock(uc->lock);
|
||||
char *value = uwsgi_cache_get2(uc, key, keylen, vallen);
|
||||
char *value = uwsgi_cache_get3(uc, key, keylen, vallen, expires);
|
||||
if (!value) {
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
return NULL;
|
||||
@@ -1401,6 +1400,9 @@ char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, char *
|
||||
ub->buf = NULL;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
*vallen = ucmc.size;
|
||||
if (expires) {
|
||||
*expires = ucmc.expires;
|
||||
}
|
||||
return value;
|
||||
|
||||
}
|
||||
@@ -1695,3 +1697,87 @@ int uwsgi_cache_magic_clear(char *cache) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_cache_sync_from_nodes(struct uwsgi_cache *uc) {
|
||||
struct uwsgi_string_list *usl = uc->sync_nodes;
|
||||
while(usl) {
|
||||
uwsgi_log("[cache-sync] getting cache dump from %s ...\n", usl->value);
|
||||
int fd = uwsgi_connect(usl->value, 0, 0);
|
||||
if (fd < 0) {
|
||||
uwsgi_log("[cache-sync] unable to connect to the cache server\n");
|
||||
goto next;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size + uc->filesize);
|
||||
ub->pos = 4;
|
||||
if (uwsgi_buffer_append(ub, uc->name, uc->name_len)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (uwsgi_buffer_set_uh(ub, 111, 6)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (uwsgi_write_nb(fd, ub->buf, ub->pos, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_log("[cache-sync] unable to write to the cache server\n");
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
size_t rlen = ub->pos;
|
||||
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_log("[cache-sync] unable to read from the cache server\n");
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
uwsgi_hooked_parse(ub->buf, ub->pos, cache_sync_hook, uc);
|
||||
|
||||
if (uwsgi_read_nb(fd, (char *) uc->items, uc->filesize, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
uwsgi_log("[cache-sync] unable to read from the cache server\n");
|
||||
goto next;
|
||||
}
|
||||
|
||||
// reset the hashtable
|
||||
memset(uc->hashtable, 0, sizeof(uint64_t) * UMAX16);
|
||||
// re-fill the hashtable
|
||||
uwsgi_cache_fix(uc);
|
||||
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
break;
|
||||
next:
|
||||
if (!usl->next) {
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("[cache-sync] trying with the next sync node...\n");
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_cache_setup_nodes(struct uwsgi_cache *uc) {
|
||||
struct uwsgi_string_list *usl = uc->nodes;
|
||||
while(usl) {
|
||||
char *port = strchr(usl->value, ':');
|
||||
if (!port) {
|
||||
uwsgi_log("[cache-udp-node] invalid udp address: %s\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
// no need to zero the memory, socket_to_in_addr will do that
|
||||
struct sockaddr_in *sin = uwsgi_malloc(sizeof(struct sockaddr_in));
|
||||
usl->custom = socket_to_in_addr(usl->value, port, 0, sin);
|
||||
usl->custom_ptr = sin;
|
||||
uwsgi_log("added udp node %s for cache \"%s\"\n", usl->value, uc->name);
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
pluggable configuration system
|
||||
|
||||
*/
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_configurator *uwsgi_register_configurator(char *name, void (*func)(char *, char **)) {
|
||||
struct uwsgi_configurator *old_uc = NULL,*uc = uwsgi.configurators;
|
||||
while(uc) {
|
||||
if (!strcmp(uc->name, name)) {
|
||||
return uc;
|
||||
}
|
||||
old_uc = uc;
|
||||
uc = uc->next;
|
||||
}
|
||||
|
||||
uc = uwsgi_calloc(sizeof(struct uwsgi_configurator));
|
||||
uc->name = name;
|
||||
uc->func = func;
|
||||
|
||||
if (old_uc) {
|
||||
old_uc->next = uc;
|
||||
}
|
||||
else {
|
||||
uwsgi.configurators = uc;
|
||||
}
|
||||
|
||||
return uc;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
cookie management functions (mainly used by the internal routing subsystem)
|
||||
|
||||
*/
|
||||
|
||||
static char *check_cookie(char *cookie, uint16_t cookie_len, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
uint16_t orig_cookie_len = cookie_len-1;
|
||||
// first lstrip white spaces
|
||||
char *ptr = cookie;
|
||||
uint16_t i;
|
||||
for(i=0;i<cookie_len;i++) {
|
||||
if (isspace((int)ptr[i])) {
|
||||
cookie++;
|
||||
cookie_len--;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// then rstrip (skipping the first char...)
|
||||
for(i=orig_cookie_len;i>0;i--) {
|
||||
if (isspace((int)ptr[i])) {
|
||||
cookie_len--;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// now search for the first equal sign
|
||||
char *equal = memchr(cookie, '=', cookie_len);
|
||||
if (!equal) return NULL;
|
||||
|
||||
if (uwsgi_strncmp(key, keylen, cookie, equal-cookie)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cookie_len -= (equal-cookie)+1;
|
||||
if (cookie_len == 0) return NULL;
|
||||
|
||||
*vallen = cookie_len;
|
||||
return equal+1;
|
||||
}
|
||||
|
||||
char *uwsgi_get_cookie(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
uint16_t i;
|
||||
|
||||
char *cookie = wsgi_req->cookie;
|
||||
uint16_t cookie_len = 0;
|
||||
char *ptr = wsgi_req->cookie;
|
||||
//start splitting by ;
|
||||
for(i=0;i<wsgi_req->cookie_len;i++) {
|
||||
if (!cookie) {
|
||||
cookie = ptr + i;
|
||||
}
|
||||
if (ptr[i] == ';') {
|
||||
char *value = check_cookie(cookie, cookie_len, key, keylen, vallen);
|
||||
if (value) {
|
||||
return value;
|
||||
}
|
||||
cookie_len = 0;
|
||||
cookie = NULL;
|
||||
}
|
||||
else {
|
||||
cookie_len++;
|
||||
}
|
||||
}
|
||||
|
||||
if (cookie_len > 0) {
|
||||
char *value = check_cookie(cookie, cookie_len, key, keylen, vallen);
|
||||
if (value) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_cron *uwsgi_cron_add(char *crontab) {
|
||||
int i;
|
||||
struct uwsgi_cron *old_uc, *uc = uwsgi.crons;
|
||||
if (!uc) {
|
||||
uc = uwsgi_malloc(sizeof(struct uwsgi_cron));
|
||||
uwsgi.crons = uc;
|
||||
}
|
||||
else {
|
||||
old_uc = uc;
|
||||
while (uc->next) {
|
||||
uc = uc->next;
|
||||
old_uc = uc;
|
||||
}
|
||||
|
||||
old_uc->next = uwsgi_malloc(sizeof(struct uwsgi_cron));
|
||||
uc = old_uc->next;
|
||||
}
|
||||
|
||||
memset(uc, 0, sizeof(struct uwsgi_cron));
|
||||
|
||||
if (sscanf(crontab, "%d %d %d %d %d %n", &uc->minute, &uc->hour, &uc->day, &uc->month, &uc->week, &i) != 5) {
|
||||
uwsgi_log("invalid cron syntax\n");
|
||||
exit(1);
|
||||
}
|
||||
uc->command = crontab + i;
|
||||
return uc;
|
||||
}
|
||||
|
||||
void uwsgi_opt_add_cron(char *opt, char *value, void *foobar) {
|
||||
uwsgi_cron_add(value);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
void uwsgi_opt_add_legion_cron(char *opt, char *value, void *foobar) {
|
||||
char *space = strchr(value, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid %s syntax, must be prefixed with a legion name\n", opt);
|
||||
exit(1);
|
||||
}
|
||||
char *legion = uwsgi_concat2n(value, space-value, "", 0);
|
||||
struct uwsgi_cron *uc = uwsgi_cron_add(space+1);
|
||||
uc->legion = legion;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int uwsgi_signal_add_cron(uint8_t sig, int minute, int hour, int day, int month, int week) {
|
||||
|
||||
if (!uwsgi.master_process)
|
||||
return -1;
|
||||
|
||||
uwsgi_lock(uwsgi.cron_table_lock);
|
||||
|
||||
if (ushared->cron_cnt < MAX_CRONS) {
|
||||
|
||||
ushared->cron[ushared->cron_cnt].sig = sig;
|
||||
ushared->cron[ushared->cron_cnt].minute = minute;
|
||||
ushared->cron[ushared->cron_cnt].hour = hour;
|
||||
ushared->cron[ushared->cron_cnt].day = day;
|
||||
ushared->cron[ushared->cron_cnt].month = month;
|
||||
ushared->cron[ushared->cron_cnt].week = week;
|
||||
ushared->cron_cnt++;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("you can register max %d cron !!!\n", MAX_CRONS);
|
||||
uwsgi_unlock(uwsgi.cron_table_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_unlock(uwsgi.cron_table_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_manage_signal_cron(time_t now) {
|
||||
|
||||
struct tm *uwsgi_cron_delta;
|
||||
int i;
|
||||
|
||||
uwsgi_cron_delta = localtime(&now);
|
||||
|
||||
if (uwsgi_cron_delta) {
|
||||
|
||||
// fix month
|
||||
uwsgi_cron_delta->tm_mon++;
|
||||
|
||||
uwsgi_lock(uwsgi.cron_table_lock);
|
||||
for (i = 0; i < ushared->cron_cnt; i++) {
|
||||
|
||||
struct uwsgi_cron *ucron = &ushared->cron[i];
|
||||
|
||||
int run_task = uwsgi_cron_task_needs_execution(uwsgi_cron_delta, ucron->minute, ucron->hour, ucron->day, ucron->month, ucron->week);
|
||||
|
||||
if (run_task == 1) {
|
||||
// date match, signal it ?
|
||||
if (now - ucron->last_job >= 60) {
|
||||
uwsgi_route_signal(ucron->sig);
|
||||
ucron->last_job = now;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
uwsgi_unlock(uwsgi.cron_table_lock);
|
||||
}
|
||||
else {
|
||||
uwsgi_error("localtime()");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_manage_command_cron(time_t now) {
|
||||
|
||||
struct tm *uwsgi_cron_delta;
|
||||
|
||||
struct uwsgi_cron *current_cron = uwsgi.crons;
|
||||
|
||||
uwsgi_cron_delta = localtime(&now);
|
||||
|
||||
|
||||
if (!uwsgi_cron_delta) {
|
||||
uwsgi_error("uwsgi_manage_command_cron()/localtime()");
|
||||
return;
|
||||
}
|
||||
|
||||
// fix month
|
||||
uwsgi_cron_delta->tm_mon++;
|
||||
|
||||
while (current_cron) {
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
// check for legion cron
|
||||
if (current_cron->legion) {
|
||||
if (!uwsgi_legion_i_am_the_lord(current_cron->legion)) {
|
||||
current_cron = current_cron->next;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int run_task = uwsgi_cron_task_needs_execution(uwsgi_cron_delta, current_cron->minute, current_cron->hour, current_cron->day, current_cron->month, current_cron->week);
|
||||
|
||||
if (run_task == 1) {
|
||||
|
||||
// date match, run command ?
|
||||
if (now - current_cron->last_job >= 60) {
|
||||
//call command
|
||||
if (current_cron->command) {
|
||||
if (current_cron->func) {
|
||||
current_cron->func(current_cron, now);
|
||||
}
|
||||
else {
|
||||
if (uwsgi_run_command(current_cron->command, NULL, -1) >= 0) {
|
||||
uwsgi_log_verbose("[uwsgi-cron] running %s\n", current_cron->command);
|
||||
}
|
||||
}
|
||||
}
|
||||
current_cron->last_job = now;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
current_cron = current_cron->next;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+12
-10
@@ -208,18 +208,20 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
uwsgi_write_pidfile(ud->pidfile);
|
||||
}
|
||||
|
||||
// /dev/null will became stdin
|
||||
devnull = open("/dev/null", O_RDONLY);
|
||||
if (devnull < 0) {
|
||||
uwsgi_error("/dev/null open()");
|
||||
exit(1);
|
||||
}
|
||||
if (devnull != 0) {
|
||||
if (dup2(devnull, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
if (!uwsgi.daemons_honour_stdin) {
|
||||
// /dev/null will became stdin
|
||||
devnull = open("/dev/null", O_RDONLY);
|
||||
if (devnull < 0) {
|
||||
uwsgi_error("/dev/null open()");
|
||||
exit(1);
|
||||
}
|
||||
close(devnull);
|
||||
if (devnull != 0) {
|
||||
if (dup2(devnull, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(devnull);
|
||||
}
|
||||
}
|
||||
|
||||
if (setsid() < 0) {
|
||||
|
||||
+64
-9
@@ -122,16 +122,27 @@ void uwsgi_emperor_blacklist_remove(char *id) {
|
||||
|
||||
struct uwsgi_emperor_scanner *emperor_scanners;
|
||||
|
||||
static int has_extra_extension(char *name) {
|
||||
struct uwsgi_string_list *usl = uwsgi.emperor_extra_extension;
|
||||
while(usl) {
|
||||
if (uwsgi_endswith(name, usl->value)) {
|
||||
return 1;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_emperor_is_valid(char *name) {
|
||||
|
||||
if (uwsgi_endswith(name, ".xml") || uwsgi_endswith(name, ".ini") || uwsgi_endswith(name, ".yml") || uwsgi_endswith(name, ".yaml") || uwsgi_endswith(name, ".js") || uwsgi_endswith(name, ".json")) {
|
||||
|
||||
if (uwsgi_endswith(name, ".xml") || uwsgi_endswith(name, ".ini") || uwsgi_endswith(name, ".yml") || uwsgi_endswith(name, ".yaml") || uwsgi_endswith(name, ".js") || uwsgi_endswith(name, ".json") || has_extra_extension(name)) {
|
||||
|
||||
if (strlen(name) < 0xff) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -231,10 +242,27 @@ void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
|
||||
|
||||
ui_current = emperor_get(de->d_name);
|
||||
|
||||
uid_t t_uid = st.st_uid;
|
||||
gid_t t_gid = st.st_gid;
|
||||
|
||||
if (uwsgi.emperor_tyrant && uwsgi.emperor_tyrant_nofollow) {
|
||||
struct stat lst;
|
||||
if (lstat(de->d_name, &lst)) {
|
||||
uwsgi_error("[emperor-tyrant]/lstat()");
|
||||
if (ui_current) {
|
||||
uwsgi_log("!!! availability of file %s changed. stopping the instance... !!!\n", de->d_name);
|
||||
emperor_stop(ui_current);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
t_uid = lst.st_uid;
|
||||
t_gid = lst.st_gid;
|
||||
}
|
||||
|
||||
if (ui_current) {
|
||||
// check if uid or gid are changed, in such case, stop the instance
|
||||
if (uwsgi.emperor_tyrant) {
|
||||
if (st.st_uid != ui_current->uid || st.st_gid != ui_current->gid) {
|
||||
if (t_uid != ui_current->uid || t_gid != ui_current->gid) {
|
||||
uwsgi_log("!!! permissions of file %s changed. stopping the instance... !!!\n", de->d_name);
|
||||
emperor_stop(ui_current);
|
||||
continue;
|
||||
@@ -247,7 +275,7 @@ void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
|
||||
}
|
||||
else {
|
||||
char *socket_name = emperor_check_on_demand_socket(de->d_name);
|
||||
emperor_add(ues, de->d_name, st.st_mtime, NULL, 0, st.st_uid, st.st_gid, socket_name);
|
||||
emperor_add(ues, de->d_name, st.st_mtime, NULL, 0, t_uid, t_gid, socket_name);
|
||||
if (socket_name) free(socket_name);
|
||||
}
|
||||
}
|
||||
@@ -308,10 +336,27 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
|
||||
|
||||
ui_current = emperor_get(g.gl_pathv[i]);
|
||||
|
||||
uid_t t_uid = st.st_uid;
|
||||
gid_t t_gid = st.st_gid;
|
||||
|
||||
if (uwsgi.emperor_tyrant && uwsgi.emperor_tyrant_nofollow) {
|
||||
struct stat lst;
|
||||
if (lstat(g.gl_pathv[i], &lst)) {
|
||||
uwsgi_error("[emperor-tyrant]/lstat()");
|
||||
if (ui_current) {
|
||||
uwsgi_log("!!! availability of file %s changed. stopping the instance... !!!\n", g.gl_pathv[i]);
|
||||
emperor_stop(ui_current);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
t_uid = lst.st_uid;
|
||||
t_gid = lst.st_gid;
|
||||
}
|
||||
|
||||
if (ui_current) {
|
||||
// check if uid or gid are changed, in such case, stop the instance
|
||||
if (uwsgi.emperor_tyrant) {
|
||||
if (st.st_uid != ui_current->uid || st.st_gid != ui_current->gid) {
|
||||
if (t_uid != ui_current->uid || t_gid != ui_current->gid) {
|
||||
uwsgi_log("!!! permissions of file %s changed. stopping the instance... !!!\n", g.gl_pathv[i]);
|
||||
emperor_stop(ui_current);
|
||||
continue;
|
||||
@@ -324,7 +369,7 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
|
||||
}
|
||||
else {
|
||||
char *socket_name = emperor_check_on_demand_socket(g.gl_pathv[i]);
|
||||
emperor_add(ues, g.gl_pathv[i], st.st_mtime, NULL, 0, st.st_uid, st.st_gid, socket_name);
|
||||
emperor_add(ues, g.gl_pathv[i], st.st_mtime, NULL, 0, t_uid, t_gid, socket_name);
|
||||
if (socket_name) free(socket_name);
|
||||
}
|
||||
|
||||
@@ -820,15 +865,16 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
|
||||
uenvs = environ;
|
||||
while (*uenvs) {
|
||||
if (!strncmp(*uenvs, "UWSGI_VASSAL_", 13)) {
|
||||
char *ne = uwsgi_concat2("UWSGI_", *uenvs + 13);
|
||||
char *oe = uwsgi_concat2n(*uenvs, strchr(*uenvs, '=') - *uenvs, "", 0);
|
||||
if (!strncmp(*uenvs, "UWSGI_VASSAL_", 13) && strchr(*uenvs, '=')) {
|
||||
char *oe = uwsgi_concat2n(*uenvs, strchr(*uenvs, '=') - *uenvs, "", 0), *ne;
|
||||
if (unsetenv(oe)) {
|
||||
uwsgi_error("unsetenv()");
|
||||
free(oe);
|
||||
break;
|
||||
}
|
||||
free(oe);
|
||||
|
||||
ne = uwsgi_concat2("UWSGI_", *uenvs + 13);
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("putenv %s\n", ne);
|
||||
#endif
|
||||
@@ -882,6 +928,15 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
vassal_argv[1] = "--json";
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".json"))
|
||||
vassal_argv[1] = "--json";
|
||||
|
||||
struct uwsgi_string_list *usl = uwsgi.emperor_extra_extension;
|
||||
while(usl) {
|
||||
if (uwsgi_endswith(n_ui->name, usl->value)) {
|
||||
vassal_argv[1] = "--config";
|
||||
break;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
if (colon) {
|
||||
colon[0] = ':';
|
||||
|
||||
+14
-14
@@ -260,7 +260,7 @@ int event_queue_del_fd(int eq, int fd, int event) {
|
||||
|
||||
int event_queue_fd_write_to_read(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -271,7 +271,7 @@ int event_queue_fd_write_to_read(int eq, int fd) {
|
||||
|
||||
int event_queue_fd_read_to_write(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -282,7 +282,7 @@ int event_queue_fd_read_to_write(int eq, int fd) {
|
||||
|
||||
int event_queue_fd_readwrite_to_read(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -293,7 +293,7 @@ int event_queue_fd_readwrite_to_read(int eq, int fd) {
|
||||
|
||||
int event_queue_fd_readwrite_to_write(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -304,7 +304,7 @@ int event_queue_fd_readwrite_to_write(int eq, int fd) {
|
||||
|
||||
int event_queue_fd_write_to_readwrite(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -315,7 +315,7 @@ int event_queue_fd_write_to_readwrite(int eq, int fd) {
|
||||
|
||||
int event_queue_fd_read_to_readwrite(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -351,7 +351,7 @@ int event_queue_interesting_fd_is_write(void *events, int id) {
|
||||
|
||||
int event_queue_add_fd_read(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -361,7 +361,7 @@ int event_queue_add_fd_read(int eq, int fd) {
|
||||
|
||||
int event_queue_add_fd_write(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -381,7 +381,7 @@ int event_queue_interesting_fd(void *events, int id) {
|
||||
}
|
||||
|
||||
int fd = (int) pe[id].portev_object;
|
||||
int eq = (int) pe[id].portev_user;
|
||||
int eq = (long) pe[id].portev_user;
|
||||
|
||||
if (pe[id].portev_events == POLLOUT) {
|
||||
event_queue_add_fd_write(eq, fd);
|
||||
@@ -423,7 +423,7 @@ int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
|
||||
port_event_t *pe_i = &pe[i];
|
||||
if (pe_i->portev_source == PORT_SOURCE_FD) {
|
||||
// event must be readded (damn Oracle/Sun why the fu*k you made such a horrible choice ???? why not adding a ONESHOT flag ???)
|
||||
if (port_associate(eq, pe_i->portev_source, pe_i->portev_object, pe_i->portev_events, NULL)) {
|
||||
if (port_associate(eq, pe_i->portev_source, pe_i->portev_object, pe_i->portev_events, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
}
|
||||
}
|
||||
@@ -449,16 +449,16 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
|
||||
ret = port_get(eq, &pe, NULL);
|
||||
}
|
||||
if (ret < 0) {
|
||||
if (errno != ETIME) {
|
||||
if (errno == ETIME) return 0;
|
||||
if (errno != EINTR) {
|
||||
uwsgi_error("port_get()");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pe.portev_source == PORT_SOURCE_FD) {
|
||||
// event must be readded (damn Oracle/Sun why the fu*k you made such a horrible choice ???? why not adding a ONESHOT flag ???)
|
||||
if (port_associate(eq, pe.portev_source, pe.portev_object, pe.portev_events, NULL)) {
|
||||
if (port_associate(eq, pe.portev_source, pe.portev_object, pe.portev_events, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -322,7 +322,7 @@ void uwsgi_manage_exception(struct wsgi_request *wsgi_req,int catch) {
|
||||
|
||||
if (do_exit) goto check_catch;
|
||||
|
||||
if (wsgi_req && uwsgi.exception_handlers_instance) {
|
||||
if (uwsgi.exception_handlers_instance) {
|
||||
struct uwsgi_buffer *ehi = uwsgi_exception_handler_object(wsgi_req);
|
||||
if (ehi) {
|
||||
uwsgi_exception_run_handlers(ehi);
|
||||
@@ -442,7 +442,7 @@ static void uwsgi_exception_handler_thread_loop(struct uwsgi_thread *ut) {
|
||||
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));
|
||||
ssize_t len = read(ut->pipe[1], buf, uwsgi.exception_handler_msg_size + sizeof(long));
|
||||
if (len > (ssize_t)(sizeof(long) + 1)) {
|
||||
size_t msg_size = len - sizeof(long);
|
||||
char *msg = buf + sizeof(long);
|
||||
@@ -488,7 +488,7 @@ void uwsgi_exception_setup_handlers() {
|
||||
}
|
||||
|
||||
void uwsgi_exceptions_handler_thread_start() {
|
||||
|
||||
if (!uwsgi.exception_handlers_instance) return;
|
||||
// start the exception_handler_thread
|
||||
uwsgi.exception_handler_thread = uwsgi_thread_new(uwsgi_exception_handler_thread_loop);
|
||||
if (!uwsgi.exception_handler_thread) {
|
||||
|
||||
@@ -28,10 +28,17 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop) (int, void *), v
|
||||
ug->fullname = fullname;
|
||||
ug->data = data;
|
||||
|
||||
#if defined(SOCK_SEQPACKET) && defined(__linux__)
|
||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, ug->internal_subscription_pipe)) {
|
||||
#else
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, ug->internal_subscription_pipe)) {
|
||||
#endif
|
||||
uwsgi_error("socketpair()");
|
||||
}
|
||||
|
||||
uwsgi_socket_nb(ug->internal_subscription_pipe[0]);
|
||||
uwsgi_socket_nb(ug->internal_subscription_pipe[1]);
|
||||
|
||||
if (!uwsgi.master_process)
|
||||
gateway_respawn(ushared->gateways_cnt);
|
||||
|
||||
|
||||
+13
-1
@@ -7,6 +7,8 @@ extern struct uwsgi_server uwsgi;
|
||||
This memory must not be freed for all the server lifecycle
|
||||
*/
|
||||
|
||||
static char *last_file = NULL;
|
||||
|
||||
void ini_rstrip(char *line) {
|
||||
|
||||
off_t i;
|
||||
@@ -104,13 +106,23 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
|
||||
if (colon[1] != 0) {
|
||||
section_asked = colon + 1;
|
||||
}
|
||||
|
||||
if (colon == file) {
|
||||
file = last_file;
|
||||
}
|
||||
}
|
||||
|
||||
if (file[0] != 0) {
|
||||
if (file[0] != 0 && file != last_file) {
|
||||
uwsgi_log_initial("[uWSGI] getting INI configuration from %s\n", file);
|
||||
}
|
||||
|
||||
ini = uwsgi_open_and_read(file, &len, 1, magic_table);
|
||||
if (file != last_file) {
|
||||
if (last_file) {
|
||||
free(last_file);
|
||||
}
|
||||
last_file = uwsgi_str(file);
|
||||
}
|
||||
|
||||
while (len) {
|
||||
ini_line = ini_get_line(ini, len);
|
||||
|
||||
@@ -955,6 +955,8 @@ readok2:
|
||||
|
||||
int uwsgi_proxy_nb(struct wsgi_request *wsgi_req, char *addr, struct uwsgi_buffer *ub, size_t remains, int timeout) {
|
||||
|
||||
struct uwsgi_buffer *headers = NULL;
|
||||
|
||||
int fd = uwsgi_connect(addr, 0, 1);
|
||||
if (fd < 0) {
|
||||
return -1;
|
||||
@@ -988,21 +990,91 @@ int uwsgi_proxy_nb(struct wsgi_request *wsgi_req, char *addr, struct uwsgi_buffe
|
||||
}
|
||||
|
||||
// read the response
|
||||
headers = uwsgi_buffer_new(8192);
|
||||
// max 64k headers
|
||||
ub->limit = UMAX16;
|
||||
for(;;) {
|
||||
char buf[8192];
|
||||
ssize_t rlen = uwsgi_read_true_nb(fd, buf, 8192, timeout);
|
||||
if (rlen > 0) {
|
||||
if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) {
|
||||
break;
|
||||
}
|
||||
if (headers) {
|
||||
if (uwsgi_buffer_append(headers, buf, rlen)) {
|
||||
goto end;
|
||||
}
|
||||
// check if we have a full HTTP response
|
||||
if (uwsgi_is_full_http(headers)) {
|
||||
int ret = uwsgi_blob_to_response(wsgi_req, headers->buf, headers->pos);
|
||||
if (ret) continue;
|
||||
uwsgi_buffer_destroy(headers);
|
||||
headers = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (headers) uwsgi_buffer_destroy(headers);
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
end:
|
||||
if (headers) uwsgi_buffer_destroy(headers);
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void uwsgi_file_write_do(struct uwsgi_string_list *usl) {
|
||||
|
||||
struct uwsgi_string_list *fl = usl;
|
||||
while(fl) {
|
||||
char *equal = strchr(fl->value, '=');
|
||||
if (equal) {
|
||||
*equal = 0;
|
||||
FILE *f = fopen(fl->value, "w");
|
||||
if (!f) {
|
||||
uwsgi_error_open("uwsgi_file_write_do()");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("writing \"%s\" to \"%s\" ...\n", equal+1, fl->value);
|
||||
if (fprintf(f, "%s\n", equal+1) <= 0 || ferror(f) || fclose(f)) {
|
||||
uwsgi_error("uwsgi_file_write_do()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("unable to write empty value for \"%s\"\n", fl->value);
|
||||
exit(1);
|
||||
}
|
||||
*equal = '=';
|
||||
fl = fl->next;
|
||||
}
|
||||
}
|
||||
|
||||
int uwsgi_fd_is_safe(int fd) {
|
||||
int i;
|
||||
for(i=0;i<uwsgi.safe_fds_cnt;i++) {
|
||||
if (uwsgi.safe_fds[i] == fd) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void uwsgi_add_safe_fd(int fd) {
|
||||
// check if the fd is already safe
|
||||
if (uwsgi_fd_is_safe(fd)) return;
|
||||
|
||||
size_t len = sizeof(int) * (uwsgi.safe_fds_cnt+1);
|
||||
int *tmp = realloc(uwsgi.safe_fds, len);
|
||||
if (!tmp) {
|
||||
uwsgi_error("uwsgi_add_safe_fd()/realloc()");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi.safe_fds = tmp;
|
||||
uwsgi.safe_fds[uwsgi.safe_fds_cnt] = fd;
|
||||
uwsgi.safe_fds_cnt++;
|
||||
}
|
||||
|
||||
+136
-34
@@ -203,14 +203,22 @@ static void legions_check_nodes() {
|
||||
|
||||
struct uwsgi_legion_node *node = legion->nodes_head;
|
||||
while (node) {
|
||||
|
||||
if (now - node->last_seen > uwsgi.legion_tolerance) {
|
||||
struct uwsgi_legion_node *tmp_node = node;
|
||||
node = node->next;
|
||||
uwsgi_log("[uwsgi-legion] node: %.*s valor: %llu uuid: %.*s left Legion %s\n", tmp_node->name_len, tmp_node->name, tmp_node->valor, 36, tmp_node->uuid, legion->legion);
|
||||
uwsgi_log("[uwsgi-legion] %s: %.*s valor: %llu uuid: %.*s left Legion %s\n", tmp_node->valor > 0 ? "node" : "arbiter", tmp_node->name_len, tmp_node->name, tmp_node->valor, 36, tmp_node->uuid, legion->legion);
|
||||
uwsgi_wlock(legion->lock);
|
||||
uwsgi_legion_remove_node(legion, tmp_node);
|
||||
uwsgi_rwunlock(legion->lock);
|
||||
// trigger node_left hooks
|
||||
struct uwsgi_string_list *usl = legion->node_left_hooks;
|
||||
while (usl) {
|
||||
int ret = uwsgi_legion_action_call("node_left", legion, usl);
|
||||
if (ret) {
|
||||
uwsgi_log("[uwsgi-legion] ERROR, node_left hook returned: %d\n", ret);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
node = node->next;
|
||||
@@ -224,12 +232,12 @@ struct uwsgi_legion_node *uwsgi_legion_get_lord(struct uwsgi_legion *);
|
||||
|
||||
static void legions_report_quorum(struct uwsgi_legion *ul, uint64_t best_valor, char *best_uuid, int votes) {
|
||||
struct uwsgi_legion_node *nodes = ul->nodes_head;
|
||||
uwsgi_log("\n[uwsgi-legion] --- WE HAVE QUORUM FOR LEGION %s !!! (valor: %llu uuid: %.*s checksum: %llu votes: %d) ---\n", ul->legion, best_valor, 36, best_uuid, ul->checksum, votes);
|
||||
uwsgi_log("[uwsgi-legion] --- WE HAVE QUORUM FOR LEGION %s !!! (valor: %llu uuid: %.*s checksum: %llu votes: %d) ---\n", ul->legion, best_valor, 36, best_uuid, ul->checksum, votes);
|
||||
while (nodes) {
|
||||
uwsgi_log("[uwsgi-legion-node] node: %.*s valor: %llu uuid: %.*s last_seen: %d vote_valor: %llu vote_uuid: %.*s\n", nodes->name_len, nodes->name, nodes->valor, 36, nodes->uuid, nodes->last_seen, nodes->lord_valor, 36, nodes->lord_uuid);
|
||||
uwsgi_log("[uwsgi-legion-node] %s: %.*s valor: %llu uuid: %.*s last_seen: %d vote_valor: %llu vote_uuid: %.*s\n", nodes->valor > 0 ? "node" : "arbiter", nodes->name_len, nodes->name, nodes->valor, 36, nodes->uuid, nodes->last_seen, nodes->lord_valor, 36, nodes->lord_uuid);
|
||||
nodes = nodes->next;
|
||||
}
|
||||
uwsgi_log("[uwsgi-legion] --- END OF QUORUM REPORT ---\n\n");
|
||||
uwsgi_log("[uwsgi-legion] --- END OF QUORUM REPORT ---\n");
|
||||
}
|
||||
|
||||
uint64_t uwsgi_legion_checksum(struct uwsgi_legion *ul) {
|
||||
@@ -265,12 +273,17 @@ static void legions_check_nodes_step2() {
|
||||
best_valor = node->valor;
|
||||
memcpy(best_uuid, node->uuid, 36);
|
||||
}
|
||||
else {
|
||||
// go on if i am not an arbiter
|
||||
else if (ul->valor > 0) {
|
||||
// no potential Lord is available, i will propose myself
|
||||
best_valor = ul->valor;
|
||||
memcpy(best_uuid, ul->uuid, 36);
|
||||
i_am_the_best = 1;
|
||||
}
|
||||
else {
|
||||
// empty lord
|
||||
memset(best_uuid, 0, 36);
|
||||
}
|
||||
|
||||
// calculate the checksum
|
||||
uint64_t new_checksum = uwsgi_legion_checksum(ul);
|
||||
@@ -302,6 +315,18 @@ static void legions_check_nodes_step2() {
|
||||
|
||||
// we have quorum !!!
|
||||
if (votes > 0 && votes >= ul->quorum) {
|
||||
if (!ul->joined) {
|
||||
// triggering join hooks
|
||||
struct uwsgi_string_list *usl = ul->join_hooks;
|
||||
while (usl) {
|
||||
int ret = uwsgi_legion_action_call("join", ul, usl);
|
||||
if (ret) {
|
||||
uwsgi_log("[uwsgi-legion] ERROR, join hook returned: %d\n", ret);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
ul->joined = 1;
|
||||
}
|
||||
// something changed ???
|
||||
if (ul->changed) {
|
||||
legions_report_quorum(ul, best_valor, best_uuid, votes);
|
||||
@@ -337,9 +362,9 @@ static void legions_check_nodes_step2() {
|
||||
if (ul->i_am_the_lord) {
|
||||
uwsgi_log("[uwsgi-legion] a new Lord (valor: %llu uuid: %.*s) raised for Legion %s...\n", ul->lord_valor, 36, ul->lord_uuid, ul->legion);
|
||||
if (ul->lord_scroll_len > 0) {
|
||||
uwsgi_log("*********** The New Lord Scroll ***********\n\n");
|
||||
uwsgi_log("*********** The New Lord Scroll ***********\n");
|
||||
uwsgi_log("%.*s\n", ul->lord_scroll_len, ul->lord_scroll);
|
||||
uwsgi_log("\n*********** End of the New Lord Scroll ***********\n\n");
|
||||
uwsgi_log("*********** End of the New Lord Scroll ***********\n");
|
||||
}
|
||||
// no more lord, trigger unlord hooks
|
||||
struct uwsgi_string_list *usl = ul->unlord_hooks;
|
||||
@@ -356,6 +381,20 @@ static void legions_check_nodes_step2() {
|
||||
}
|
||||
else if (votes > 0 && votes < ul->quorum && (uwsgi_now() - ul->last_warning >= 60)) {
|
||||
uwsgi_log("[uwsgi-legion] no quorum: only %d vote(s) for Legion %s, %d needed to elect a Lord\n", votes, ul->legion, ul->quorum);
|
||||
// no more quorum, leave the Lord state
|
||||
if (ul->i_am_the_lord) {
|
||||
uwsgi_log("[uwsgi-legion] i cannot be The Lord of The Legion %s without a quorum ...\n", ul->legion);
|
||||
// no more lord, trigger unlord hooks
|
||||
struct uwsgi_string_list *usl = ul->unlord_hooks;
|
||||
while (usl) {
|
||||
int ret = uwsgi_legion_action_call("unlord", ul, usl);
|
||||
if (ret) {
|
||||
uwsgi_log("[uwsgi-legion] ERROR, unlord hook returned: %d\n", ret);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
ul->i_am_the_lord = 0;
|
||||
}
|
||||
ul->last_warning = uwsgi_now();
|
||||
}
|
||||
|
||||
@@ -375,6 +414,8 @@ struct uwsgi_legion_node *uwsgi_legion_get_lord(struct uwsgi_legion *ul) {
|
||||
|
||||
struct uwsgi_legion_node *nodes = ul->nodes_head;
|
||||
while (nodes) {
|
||||
// skip arbiters
|
||||
if (nodes->valor == 0) goto next;
|
||||
if (nodes->valor > best_valor) {
|
||||
best_node = nodes;
|
||||
best_valor = nodes->valor;
|
||||
@@ -387,11 +428,12 @@ struct uwsgi_legion_node *uwsgi_legion_get_lord(struct uwsgi_legion *ul) {
|
||||
memcpy(best_uuid, nodes->uuid, 36);
|
||||
}
|
||||
}
|
||||
next:
|
||||
nodes = nodes->next;
|
||||
}
|
||||
|
||||
// first round ?
|
||||
if (ul->lord_valor == 0) {
|
||||
// first round ? (skip first round if arbiter)
|
||||
if (ul->valor > 0 && ul->lord_valor == 0) {
|
||||
ul->changed = 1;
|
||||
}
|
||||
else if (best_valor != ul->lord_valor) {
|
||||
@@ -558,7 +600,16 @@ static void *legion_loop(void *foobar) {
|
||||
// we are still locked (and safe), let's rebuild the scrolls list
|
||||
legion_rebuild_scrolls(ul);
|
||||
uwsgi_rwunlock(ul->lock);
|
||||
uwsgi_log("[uwsgi-legion] node: %.*s valor: %llu uuid: %.*s joined Legion %s\n", node->name_len, node->name, node->valor, 36, node->uuid, ul->legion);
|
||||
uwsgi_log("[uwsgi-legion] %s: %.*s valor: %llu uuid: %.*s joined Legion %s\n", node->valor > 0 ? "node" : "arbiter", node->name_len, node->name, node->valor, 36, node->uuid, ul->legion);
|
||||
// trigger node_joined hooks
|
||||
struct uwsgi_string_list *usl = ul->node_joined_hooks;
|
||||
while (usl) {
|
||||
int ret = uwsgi_legion_action_call("node_joined", ul, usl);
|
||||
if (ret) {
|
||||
uwsgi_log("[uwsgi-legion] ERROR, node_joined hook returned: %d\n", ret);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
node->last_seen = uwsgi_now();
|
||||
@@ -746,6 +797,21 @@ err:
|
||||
return -1;
|
||||
}
|
||||
|
||||
void uwsgi_opt_legion_mcast(char *opt, char *value, void *foobar) {
|
||||
uwsgi_opt_legion(opt, value, foobar);
|
||||
char *legion = uwsgi_str(value);
|
||||
char *space = strchr(legion, ' ');
|
||||
// over engineering
|
||||
if (!space) exit(1);
|
||||
*space = 0;
|
||||
struct uwsgi_legion *ul = uwsgi_legion_get_by_name(legion);
|
||||
if (!ul) {
|
||||
uwsgi_log("unknown legion: %s\n", legion);
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_legion_register_node(ul, uwsgi_str(ul->addr));
|
||||
}
|
||||
|
||||
void uwsgi_opt_legion_node(char *opt, char *value, void *foobar) {
|
||||
|
||||
char *legion = uwsgi_str(value);
|
||||
@@ -763,15 +829,20 @@ void uwsgi_opt_legion_node(char *opt, char *value, void *foobar) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *usl = uwsgi_string_new_list(&ul->nodes, space + 1);
|
||||
char *port = strchr(usl->value, ':');
|
||||
uwsgi_legion_register_node(ul, space + 1);
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_legion_register_node(struct uwsgi_legion *ul, char *addr) {
|
||||
struct uwsgi_string_list *usl = uwsgi_string_new_list(&ul->nodes, addr);
|
||||
char *port = strchr(addr, ':');
|
||||
if (!port) {
|
||||
uwsgi_log("[uwsgi-legion] invalid udp address: %s\n", usl->value);
|
||||
uwsgi_log("[uwsgi-legion] invalid udp address: %s\n", addr);
|
||||
exit(1);
|
||||
}
|
||||
// no need to zero the memory, socket_to_in_addr will do that
|
||||
struct sockaddr_in *sin = uwsgi_malloc(sizeof(struct sockaddr_in));
|
||||
usl->custom = socket_to_in_addr(usl->value, port, 0, sin);
|
||||
usl->custom = socket_to_in_addr(addr, port, 0, sin);
|
||||
usl->custom_ptr = sin;
|
||||
}
|
||||
|
||||
@@ -823,51 +894,76 @@ void uwsgi_opt_legion_scroll(char *opt, char *value, void *foobar) {
|
||||
|
||||
void uwsgi_opt_legion_hook(char *opt, char *value, void *foobar) {
|
||||
|
||||
char *event = strchr(opt, '-');
|
||||
if (!event) {
|
||||
uwsgi_log("[uwsgi-legion] invalid option name (%s), this should not happen (possible bug)\n", opt);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *legion = uwsgi_str(value);
|
||||
|
||||
|
||||
char *space = strchr(legion, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid %s syntax, must be <legion> <action>\n", opt);
|
||||
uwsgi_log("[uwsgi-legion] invalid %s syntax, must be <legion> <action>\n", opt);
|
||||
exit(1);
|
||||
}
|
||||
*space = 0;
|
||||
|
||||
struct uwsgi_legion *ul = uwsgi_legion_get_by_name(legion);
|
||||
if (!ul) {
|
||||
uwsgi_log("unknown legion: %s\n", legion);
|
||||
uwsgi_log("[uwsgi-legion] unknown legion: %s\n", legion);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_legion_register_hook(ul, event + 1, space + 1);
|
||||
}
|
||||
|
||||
void uwsgi_legion_register_hook(struct uwsgi_legion *ul, char *event, char *action) {
|
||||
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
|
||||
if (!strcmp(opt, "legion-lord")) {
|
||||
usl = uwsgi_string_new_list(&ul->lord_hooks, space + 1);
|
||||
if (!strcmp(event, "lord")) {
|
||||
usl = uwsgi_string_new_list(&ul->lord_hooks, action);
|
||||
}
|
||||
else if (!strcmp(opt, "legion-unlord")) {
|
||||
usl = uwsgi_string_new_list(&ul->unlord_hooks, space + 1);
|
||||
else if (!strcmp(event, "unlord")) {
|
||||
usl = uwsgi_string_new_list(&ul->unlord_hooks, action);
|
||||
}
|
||||
else if (!strcmp(opt, "legion-setup")) {
|
||||
usl = uwsgi_string_new_list(&ul->setup_hooks, space + 1);
|
||||
else if (!strcmp(event, "setup")) {
|
||||
usl = uwsgi_string_new_list(&ul->setup_hooks, action);
|
||||
}
|
||||
else if (!strcmp(opt, "legion-death")) {
|
||||
usl = uwsgi_string_new_list(&ul->death_hooks, space + 1);
|
||||
else if (!strcmp(event, "death")) {
|
||||
usl = uwsgi_string_new_list(&ul->death_hooks, action);
|
||||
}
|
||||
else if (!strcmp(event, "join")) {
|
||||
usl = uwsgi_string_new_list(&ul->join_hooks, action);
|
||||
}
|
||||
else if (!strcmp(event, "node-joined")) {
|
||||
usl = uwsgi_string_new_list(&ul->node_joined_hooks, action);
|
||||
}
|
||||
else if (!strcmp(event, "node-left")) {
|
||||
usl = uwsgi_string_new_list(&ul->node_left_hooks, action);
|
||||
}
|
||||
|
||||
else {
|
||||
uwsgi_log("[uwsgi-legion] invalid event: %s\n", event);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!usl)
|
||||
return;
|
||||
|
||||
char *port = strchr(usl->value, ':');
|
||||
if (!port) {
|
||||
uwsgi_log("[uwsgi-legion] invalid %s action: %s\n", opt, usl->value);
|
||||
char *hook = strchr(action, ':');
|
||||
if (!hook) {
|
||||
uwsgi_log("[uwsgi-legion] invalid %s action: %s\n", event, action);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// pointer to action plugin
|
||||
usl->custom_ptr = uwsgi_concat2n(usl->value, port - usl->value, "", 0);
|
||||
usl->custom_ptr = uwsgi_concat2n(action, hook - action, "", 0);;
|
||||
// add that to check the plugin value
|
||||
usl->custom = port - usl->value + 1;
|
||||
}
|
||||
usl->custom = hook - action + 1;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
|
||||
|
||||
@@ -905,6 +1001,10 @@ void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
|
||||
*colon = 0;
|
||||
char *secret = colon + 1;
|
||||
|
||||
uwsgi_legion_register(legion, addr, valor, algo_secret, secret);
|
||||
}
|
||||
|
||||
struct uwsgi_legion *uwsgi_legion_register(char *legion, char *addr, char *valor, char *algo, char *secret) {
|
||||
char *iv = strchr(secret, ' ');
|
||||
if (iv) {
|
||||
*iv = 0;
|
||||
@@ -918,9 +1018,9 @@ void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
|
||||
EVP_CIPHER_CTX *ctx = uwsgi_malloc(sizeof(EVP_CIPHER_CTX));
|
||||
EVP_CIPHER_CTX_init(ctx);
|
||||
|
||||
const EVP_CIPHER *cipher = EVP_get_cipherbyname(algo_secret);
|
||||
const EVP_CIPHER *cipher = EVP_get_cipherbyname(algo);
|
||||
if (!cipher) {
|
||||
uwsgi_log("[uwsgi-legion] unable to find algorithm/cipher %s\n", algo_secret);
|
||||
uwsgi_log("[uwsgi-legion] unable to find algorithm/cipher %s\n", algo);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -983,6 +1083,8 @@ void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
|
||||
ul->scrolls = uwsgi_calloc_shared(ul->scrolls_max_size);
|
||||
|
||||
uwsgi_legion_add(ul);
|
||||
|
||||
return ul;
|
||||
}
|
||||
|
||||
struct uwsgi_legion_action *uwsgi_legion_action_get(char *name) {
|
||||
|
||||
@@ -474,8 +474,6 @@ void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
|
||||
|
||||
#define UWSGI_LOCK_ENGINE_NAME "ipcsem"
|
||||
|
||||
#define UWSGI_IPCSEM_ATEXIT 1
|
||||
|
||||
#endif
|
||||
|
||||
struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
|
||||
@@ -679,9 +677,6 @@ ready:
|
||||
// timer table lock
|
||||
uwsgi.timer_table_lock = uwsgi_lock_init("timer");
|
||||
|
||||
// probe table lock
|
||||
uwsgi.probe_table_lock = uwsgi_lock_init("probe");
|
||||
|
||||
// rb_timer table lock
|
||||
uwsgi.rb_timer_table_lock = uwsgi_lock_init("rbtimer");
|
||||
|
||||
|
||||
+19
-35
@@ -638,22 +638,6 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi_manage_command_cron(uwsgi_now());
|
||||
}
|
||||
|
||||
|
||||
// check for probes
|
||||
if (ushared->probes_cnt > 0) {
|
||||
uwsgi_lock(uwsgi.probe_table_lock);
|
||||
for (i = 0; i < ushared->probes_cnt; i++) {
|
||||
if (interesting_fd == -1) {
|
||||
// increment cycles
|
||||
ushared->probes[i].cycles++;
|
||||
}
|
||||
if (ushared->probes[i].func(interesting_fd, &ushared->probes[i])) {
|
||||
uwsgi_route_signal(ushared->probes[i].sig);
|
||||
}
|
||||
}
|
||||
uwsgi_unlock(uwsgi.probe_table_lock);
|
||||
}
|
||||
|
||||
// some event returned
|
||||
if (rlen > 0) {
|
||||
// if the following function returns -1, a new worker has just spawned
|
||||
@@ -798,8 +782,8 @@ int master_loop(char **argv, char **environ) {
|
||||
|
||||
*/
|
||||
|
||||
uwsgi.mywid = find_worker_id(diedpid);
|
||||
if (uwsgi.mywid <= 0) {
|
||||
int thewid = find_worker_id(diedpid);
|
||||
if (thewid <= 0) {
|
||||
// check spooler, mules, gateways and daemons
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
while (uspool) {
|
||||
@@ -842,50 +826,50 @@ next:
|
||||
|
||||
|
||||
// ok a worker died...
|
||||
uwsgi.workers[uwsgi.mywid].pid = 0;
|
||||
uwsgi.workers[thewid].pid = 0;
|
||||
// only to be safe :P
|
||||
uwsgi.workers[uwsgi.mywid].harakiri = 0;
|
||||
uwsgi.workers[thewid].harakiri = 0;
|
||||
|
||||
// ok, if we are reloading or dying, just continue the master loop
|
||||
// as soon as all of the workers have pid == 0, the action (exit, or reload) is triggered
|
||||
if (uwsgi_instance_is_reloading || uwsgi_instance_is_dying) {
|
||||
uwsgi_log("worker %d buried after %d seconds\n", uwsgi.mywid, (int) (uwsgi_now()-uwsgi.workers[uwsgi.mywid].cursed_at));
|
||||
uwsgi.workers[uwsgi.mywid].cursed_at = 0;
|
||||
uwsgi_log("worker %d buried after %d seconds\n", thewid, (int) (uwsgi_now()-uwsgi.workers[thewid].cursed_at));
|
||||
uwsgi.workers[thewid].cursed_at = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
// if we are stopping workers, just end here
|
||||
|
||||
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_FAILED_APP_CODE) {
|
||||
uwsgi_log("OOPS ! failed loading app in worker %d (pid %d) :( trying again...\n", uwsgi.mywid, (int) diedpid);
|
||||
uwsgi_log("OOPS ! failed loading app in worker %d (pid %d) :( trying again...\n", thewid, (int) diedpid);
|
||||
}
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_DE_HIJACKED_CODE) {
|
||||
uwsgi_log("...restoring worker %d (pid: %d)...\n", uwsgi.mywid, (int) diedpid);
|
||||
uwsgi_log("...restoring worker %d (pid: %d)...\n", thewid, (int) diedpid);
|
||||
}
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_EXCEPTION_CODE) {
|
||||
uwsgi_log("... monitored exception detected, respawning worker %d (pid: %d)...\n", uwsgi.mywid, (int) diedpid);
|
||||
uwsgi_log("... monitored exception detected, respawning worker %d (pid: %d)...\n", thewid, (int) diedpid);
|
||||
}
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_QUIET_CODE) {
|
||||
// noop
|
||||
}
|
||||
else if (uwsgi.workers[uwsgi.mywid].manage_next_request) {
|
||||
else if (uwsgi.workers[thewid].manage_next_request) {
|
||||
if (WIFSIGNALED(waitpid_status)) {
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died, killed by signal %d :( trying respawn ...\n", uwsgi.mywid, (int) diedpid, (int) WTERMSIG(waitpid_status));
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died, killed by signal %d :( trying respawn ...\n", thewid, (int) diedpid, (int) WTERMSIG(waitpid_status));
|
||||
}
|
||||
else {
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died :( trying respawn ...\n", uwsgi.mywid, (int) diedpid);
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died :( trying respawn ...\n", thewid, (int) diedpid);
|
||||
}
|
||||
}
|
||||
else if (uwsgi.workers[uwsgi.mywid].cursed_at > 0) {
|
||||
uwsgi_log("worker %d killed successfully (pid: %d)\n", uwsgi.mywid, (int) diedpid);
|
||||
else if (uwsgi.workers[thewid].cursed_at > 0) {
|
||||
uwsgi_log("worker %d killed successfully (pid: %d)\n", thewid, (int) diedpid);
|
||||
}
|
||||
// manage_next_request is zero, but killed by signal...
|
||||
else if (WIFSIGNALED(waitpid_status)) {
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) MISTERIOUSLY killed by signal %d :( trying respawn ...\n", uwsgi.mywid, (int) diedpid, (int) WTERMSIG(waitpid_status));
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) MISTERIOUSLY killed by signal %d :( trying respawn ...\n", thewid, (int) diedpid, (int) WTERMSIG(waitpid_status));
|
||||
}
|
||||
|
||||
if (uwsgi.workers[uwsgi.mywid].cheaped == 1) {
|
||||
uwsgi_log("uWSGI worker %d cheaped.\n", uwsgi.mywid);
|
||||
if (uwsgi.workers[thewid].cheaped == 1) {
|
||||
uwsgi_log("uWSGI worker %d cheaped.\n", thewid);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -909,12 +893,12 @@ next:
|
||||
uwsgi.respawn_delta = last_respawn.tv_sec;
|
||||
|
||||
// are we chain reloading it ?
|
||||
if (uwsgi.status.chain_reloading == uwsgi.mywid) {
|
||||
if (uwsgi.status.chain_reloading == thewid) {
|
||||
uwsgi.status.chain_reloading++;
|
||||
}
|
||||
|
||||
// respawn the worker (if needed)
|
||||
if (uwsgi_respawn_worker(uwsgi.mywid))
|
||||
if (uwsgi_respawn_worker(thewid))
|
||||
return 0;
|
||||
|
||||
// end of the loop
|
||||
|
||||
+72
-177
@@ -351,6 +351,9 @@ void uwsgi_reload(char **argv) {
|
||||
/* check fd table (a module can obviosly open some fd on initialization...) */
|
||||
uwsgi_log("closing all non-uwsgi socket fds > 2 (max_fd = %d)...\n", (int) uwsgi.max_fd);
|
||||
for (i = 3; i < (int) uwsgi.max_fd; i++) {
|
||||
|
||||
if (uwsgi_fd_is_safe(i)) continue;
|
||||
|
||||
int found = 0;
|
||||
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
@@ -413,9 +416,13 @@ void uwsgi_reload(char **argv) {
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef UWSGI_AS_SHARED_LIBRARY
|
||||
return;
|
||||
#else
|
||||
#ifndef UWSGI_IPCSEM_ATEXIT
|
||||
// free ipc semaphores if in use
|
||||
if (uwsgi.lock_engine && !strcmp(uwsgi.lock_engine, "ipcsem")) {
|
||||
uwsgi_ipcsem_clear();
|
||||
}
|
||||
#endif
|
||||
|
||||
uwsgi_log("running %s\n", uwsgi.binary_path);
|
||||
uwsgi_flush_logs();
|
||||
argv[0] = uwsgi.binary_path;
|
||||
@@ -436,7 +443,6 @@ void uwsgi_reload(char **argv) {
|
||||
uwsgi_error("execvp()");
|
||||
// never here
|
||||
exit(1);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -634,178 +640,6 @@ int uwsgi_respawn_worker(int wid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_manage_signal_cron(time_t now) {
|
||||
|
||||
struct tm *uwsgi_cron_delta;
|
||||
int i;
|
||||
|
||||
uwsgi_cron_delta = localtime(&now);
|
||||
|
||||
if (uwsgi_cron_delta) {
|
||||
|
||||
// fix month
|
||||
uwsgi_cron_delta->tm_mon++;
|
||||
|
||||
uwsgi_lock(uwsgi.cron_table_lock);
|
||||
for (i = 0; i < ushared->cron_cnt; i++) {
|
||||
|
||||
struct uwsgi_cron *ucron = &ushared->cron[i];
|
||||
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
|
||||
|
||||
uc_minute = ucron->minute;
|
||||
uc_hour = ucron->hour;
|
||||
uc_day = ucron->day;
|
||||
uc_month = ucron->month;
|
||||
uc_week = ucron->week;
|
||||
|
||||
// negative values as interval -1 = * , -5 = */5
|
||||
if (ucron->minute < 0) {
|
||||
if ((uwsgi_cron_delta->tm_min % abs(ucron->minute)) == 0) {
|
||||
uc_minute = uwsgi_cron_delta->tm_min;
|
||||
}
|
||||
}
|
||||
if (ucron->hour < 0) {
|
||||
if ((uwsgi_cron_delta->tm_hour % abs(ucron->hour)) == 0) {
|
||||
uc_hour = uwsgi_cron_delta->tm_hour;
|
||||
}
|
||||
}
|
||||
if (ucron->month < 0) {
|
||||
if ((uwsgi_cron_delta->tm_mon % abs(ucron->month)) == 0) {
|
||||
uc_month = uwsgi_cron_delta->tm_mon;
|
||||
}
|
||||
}
|
||||
if (ucron->day < 0) {
|
||||
if ((uwsgi_cron_delta->tm_mday % abs(ucron->day)) == 0) {
|
||||
uc_day = uwsgi_cron_delta->tm_mday;
|
||||
}
|
||||
}
|
||||
if (ucron->week < 0) {
|
||||
if ((uwsgi_cron_delta->tm_wday % abs(ucron->week)) == 0) {
|
||||
uc_week = uwsgi_cron_delta->tm_wday;
|
||||
}
|
||||
}
|
||||
|
||||
int run_task = 0;
|
||||
// mday and wday are ORed
|
||||
if (ucron->day >= 0 && ucron->week >= 0) {
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
|
||||
run_task = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
|
||||
run_task = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (run_task == 1) {
|
||||
// date match, signal it ?
|
||||
if (now - ucron->last_job > 60) {
|
||||
uwsgi_route_signal(ucron->sig);
|
||||
ucron->last_job = now;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
uwsgi_unlock(uwsgi.cron_table_lock);
|
||||
}
|
||||
else {
|
||||
uwsgi_error("localtime()");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_manage_command_cron(time_t now) {
|
||||
|
||||
struct tm *uwsgi_cron_delta;
|
||||
|
||||
struct uwsgi_cron *current_cron = uwsgi.crons;
|
||||
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
|
||||
|
||||
uwsgi_cron_delta = localtime(&now);
|
||||
|
||||
|
||||
if (!uwsgi_cron_delta) {
|
||||
uwsgi_error("localtime()");
|
||||
return;
|
||||
}
|
||||
|
||||
// fix month
|
||||
uwsgi_cron_delta->tm_mon++;
|
||||
|
||||
while (current_cron) {
|
||||
|
||||
uc_minute = current_cron->minute;
|
||||
uc_hour = current_cron->hour;
|
||||
uc_day = current_cron->day;
|
||||
uc_month = current_cron->month;
|
||||
uc_week = current_cron->week;
|
||||
|
||||
// negative values as interval -1 = * , -5 = */5
|
||||
if (current_cron->minute < 0) {
|
||||
if ((uwsgi_cron_delta->tm_min % abs(current_cron->minute)) == 0) {
|
||||
uc_minute = uwsgi_cron_delta->tm_min;
|
||||
}
|
||||
}
|
||||
if (current_cron->hour < 0) {
|
||||
if ((uwsgi_cron_delta->tm_hour % abs(current_cron->hour)) == 0) {
|
||||
uc_hour = uwsgi_cron_delta->tm_hour;
|
||||
}
|
||||
}
|
||||
if (current_cron->month < 0) {
|
||||
if ((uwsgi_cron_delta->tm_mon % abs(current_cron->month)) == 0) {
|
||||
uc_month = uwsgi_cron_delta->tm_mon;
|
||||
}
|
||||
}
|
||||
if (current_cron->day < 0) {
|
||||
if ((uwsgi_cron_delta->tm_mday % abs(current_cron->day)) == 0) {
|
||||
uc_day = uwsgi_cron_delta->tm_mday;
|
||||
}
|
||||
}
|
||||
if (current_cron->week < 0) {
|
||||
if ((uwsgi_cron_delta->tm_wday % abs(current_cron->week)) == 0) {
|
||||
uc_week = uwsgi_cron_delta->tm_wday;
|
||||
}
|
||||
}
|
||||
|
||||
int run_task = 0;
|
||||
// mday and wday are ORed
|
||||
if (current_cron->day >= 0 && current_cron->week >= 0) {
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
|
||||
run_task = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
|
||||
run_task = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (run_task == 1) {
|
||||
|
||||
// date match, run command ?
|
||||
if (now - current_cron->last_job > 60) {
|
||||
//call command
|
||||
if (current_cron->command) {
|
||||
if (uwsgi_run_command(current_cron->command, NULL, -1) >= 0) {
|
||||
uwsgi_log_verbose("[uWSGI-cron] running %s\n", current_cron->command);
|
||||
}
|
||||
}
|
||||
current_cron->last_job = now;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
current_cron = current_cron->next;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
|
||||
int i;
|
||||
@@ -944,7 +778,10 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
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))
|
||||
if (uwsgi_stats_keylong_comma(us, "full", (unsigned long long) uc->full))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong(us, "last_modified_at", (unsigned long long) uc->last_modified_at))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_object_close(us))
|
||||
@@ -957,6 +794,9 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
uc = uc->next;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_list_close(us))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
}
|
||||
@@ -1486,3 +1326,58 @@ void uwsgi_master_fix_request_counters() {
|
||||
uwsgi.workers[0].requests = total_counter;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_cron_task_needs_execution(struct tm *uwsgi_cron_delta, int minute, int hour, int day, int month, int week) {
|
||||
|
||||
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
|
||||
|
||||
uc_minute = minute;
|
||||
uc_hour = hour;
|
||||
uc_day = day;
|
||||
uc_month = month;
|
||||
uc_week = week;
|
||||
|
||||
// negative values as interval -1 = * , -5 = */5
|
||||
if (minute < 0) {
|
||||
if ((uwsgi_cron_delta->tm_min % abs(minute)) == 0) {
|
||||
uc_minute = uwsgi_cron_delta->tm_min;
|
||||
}
|
||||
}
|
||||
if (hour < 0) {
|
||||
if ((uwsgi_cron_delta->tm_hour % abs(hour)) == 0) {
|
||||
uc_hour = uwsgi_cron_delta->tm_hour;
|
||||
}
|
||||
}
|
||||
if (month < 0) {
|
||||
if ((uwsgi_cron_delta->tm_mon % abs(month)) == 0) {
|
||||
uc_month = uwsgi_cron_delta->tm_mon;
|
||||
}
|
||||
}
|
||||
if (day < 0) {
|
||||
if ((uwsgi_cron_delta->tm_mday % abs(day)) == 0) {
|
||||
uc_day = uwsgi_cron_delta->tm_mday;
|
||||
}
|
||||
}
|
||||
if (week < 0) {
|
||||
if ((uwsgi_cron_delta->tm_wday % abs(week)) == 0) {
|
||||
uc_week = uwsgi_cron_delta->tm_wday;
|
||||
}
|
||||
}
|
||||
|
||||
int run_task = 0;
|
||||
// mday and wday are ORed
|
||||
if (day >= 0 && week >= 0) {
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
|
||||
run_task = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
|
||||
run_task = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return run_task;
|
||||
|
||||
}
|
||||
|
||||
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
|
||||
uWSGI metrics subsystem
|
||||
|
||||
a metric is a node in a tree reachable via a numeric id (OID, in SNMP way) or a simple string:
|
||||
|
||||
uwsgi.worker.1.requests
|
||||
uwsgi.custom.foo.bar
|
||||
|
||||
the oid representation:
|
||||
|
||||
1.3.6.1.4.1.35156.17 = iso.org.dod.internet.private.enterprise.unbit.uwsgi
|
||||
1.3.6.1.4.1.35156.17.3.1.1 = iso.org.dod.internet.private.enterprise.unbit.uwsgi.worker.1.requests
|
||||
1.3.6.1.4.1.35156.17.3.1.1 = iso.org.dod.internet.private.enterprise.unbit.uwsgi.worker.1.requests
|
||||
1.3.6.1.4.1.35156.17.3.1.2.1.1 = iso.org.dod.internet.private.enterprise.unbit.uwsgi.worker.1.core.1.requests
|
||||
1.3.6.1.4.1.35156.17.4.1 = iso.org.dod.internet.private.enterprise.unbit.uwsgi.system.load_avg
|
||||
...
|
||||
|
||||
each metric is a collected value with a specific frequency (a frequency of zero means the value is re-computed every time)
|
||||
metrics are meant for numeric values signed 64 bit, but they can be exposed as:
|
||||
|
||||
gauge
|
||||
counter
|
||||
absolute
|
||||
|
||||
both 32 and 64bit, both signed and unsigned
|
||||
|
||||
metrics are managed by a dedicated thread (in the master) holding a linked list of all the items. For few metrics it is a good (read: simple) approach,
|
||||
but you can cache lookups in a uWSGI cache for really big list.
|
||||
|
||||
struct uwsgi_metric *um = uwsgi_register_metric("worker.1.requests", "3.1.1", UWSGI_METRIC_COUNTER, UWSGI_METRIC_PTR, &uwsgi.workers[1].requests, 0, NULL);
|
||||
prototype: struct uwsgi_metric *uwsgi_register_metric(char *name, char *oid, uint8_t value_type, uint8_t collect_way, void *ptr, uint32_t freq, void *custom);
|
||||
|
||||
value_type = UWSGI_METRIC_COUNTER/UWSGI_METRIC_GAUGE/UWSGI_METRIC_ABSOLUTE
|
||||
collect_way = UWSGI_METRIC_PTR -> get from a pointer / UWSGI_METRIC_FUNC -> get from a func with the prototype int64_t func(struct uwsgi_metric *); / UWSGI_METRIC_FILE -> get the value from a file, ptr is the filename
|
||||
|
||||
when freq is zero the value is recomputed whenever requested, otherwise the metrics thread compute it every time the frequency is elapsed and caches it
|
||||
|
||||
For some metric (or all ?) you may want to hold a value even after a server reload. For such a reason you can specify a directory on wich the server (on startup/restart) will look for
|
||||
a file named like the metric and will read the initial value from it. It may look an old-fashioned and quite inefficient way, but it is the most versatile for a sysadmin (allowing him/her
|
||||
to even modify the values manually)
|
||||
|
||||
When registering a metric with the same name of an already registered one, the new one will overwrite the previous one. This allows plugins writer to override default behaviours
|
||||
|
||||
Applications are allowed to update metrics (but they cannot register new ones), with simple api funcs:
|
||||
|
||||
uwsgi.metric_set("worker.1.requests", N)
|
||||
uwsgi.metric_inc("worker.1.requests", N=1)
|
||||
uwsgi.metric_dec("worker.1.requests", N=1)
|
||||
uwsgi.metric_mul("worker.1.requests", N=1)
|
||||
uwsgi.metric_div("worker.1.requests", N=1)
|
||||
|
||||
and obviously they can get values:
|
||||
|
||||
uwsgi.metric_get("worker.1.requests", no_cache|force=False)
|
||||
if the second parameter is True, the value is recomputed (but if it is a metric with a cache, the cache value will not be updated accordingly, this is the job of the metric thread)
|
||||
|
||||
Updating metrics from your app MUST BE ATOMIC, for such a reason a uWSGI rwlock is initialized on startup and used for each operation (simple reading from a metric does not require locking)
|
||||
|
||||
Metrics can be updated from the internal routing subsystem too:
|
||||
|
||||
route-if = equal:${REQUEST_URI};/foobar metricinc:foobar.test 2
|
||||
|
||||
and can be accessed as ${metric[foobar.test]}
|
||||
|
||||
The stats server exports the metrics list in the "metrics" attribute (obviously some info could be redundant)
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_metric {
|
||||
char *name;
|
||||
char *oid;
|
||||
|
||||
// pre-computed snmp representation
|
||||
char *asn;
|
||||
size_t asn_size;
|
||||
|
||||
// ABSOLUTE/COUNTER/GAUGE
|
||||
uint8_t type;
|
||||
|
||||
// MANUAL/PTR/FUNC/FILE
|
||||
uint8_t collect_way
|
||||
|
||||
// this could be taken from a file storage and must laways be added to value when reporting (default 0)
|
||||
int64_t initial_value;
|
||||
// the value of the metric (point to a shared memory area)
|
||||
*int64_t value;
|
||||
|
||||
// a custom blob you can attach to a metric
|
||||
void *custom;
|
||||
|
||||
// the collection frequency
|
||||
uint32_t freq;
|
||||
time_t last_update;
|
||||
|
||||
// run this function to collect the value
|
||||
int64_t (*collector)(struct uwsgi_metric *);
|
||||
// take the value from this pointer to a 64bit value
|
||||
int64_t *ptr;
|
||||
// get the initial value from this file, and store each update in it
|
||||
char *filename;
|
||||
|
||||
struct uwsgi_metric *next;
|
||||
};
|
||||
|
||||
struct uwsgi_metric *uwsgi_register_metric(char *name, char *oid, uint8_t value_type, uint8_t collect_way, void *ptr, uint32_t freq, void *custom) {
|
||||
struct uwsgi_metric *old_metric=NULL,*metric=uwsgi.metric;
|
||||
|
||||
while(metric) {
|
||||
metric = metric->next;
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_metric_loop() {
|
||||
// every second scan the whole metrics tree
|
||||
time_t now = uwsgi_now();
|
||||
}
|
||||
|
||||
int64_t uwsgi_metric_get(char *name, char *oid) {
|
||||
struct uwsgi_metric *um = NULL;
|
||||
if (name) {
|
||||
um = uwsgi_metric_find_by_name(name);
|
||||
}
|
||||
else if (oid) {
|
||||
um = uwsgi_metric_find_by_oid(oid);
|
||||
}
|
||||
if (!um) return 0;
|
||||
|
||||
//
|
||||
switch(um->collect_way) {
|
||||
case UWSGI_METRIC_MANUAL:
|
||||
return um->initial_value+*um->value;
|
||||
case UWSGI_METRIC_PTR:
|
||||
return um->initial_value+*um->ptr;
|
||||
case UWSGI_METRIC_FUNC:
|
||||
case UWSGI_METRIC_FILE:
|
||||
}
|
||||
}
|
||||
+6
-2
@@ -184,6 +184,7 @@ void uwsgi_mule_handler() {
|
||||
if (interesting_fd == uwsgi.signal_socket || interesting_fd == uwsgi.my_signal_socket || farm_has_signaled(interesting_fd)) {
|
||||
len = read(interesting_fd, &uwsgi_signal, 1);
|
||||
if (len <= 0) {
|
||||
if (len < 0 && (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)) continue;
|
||||
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
|
||||
end_me(0);
|
||||
}
|
||||
@@ -197,7 +198,9 @@ void uwsgi_mule_handler() {
|
||||
else if (interesting_fd == uwsgi.mules[uwsgi.muleid - 1].queue_pipe[1] || interesting_fd == uwsgi.shared->mule_queue_pipe[1] || farm_has_msg(interesting_fd)) {
|
||||
len = read(interesting_fd, message, 65536);
|
||||
if (len < 0) {
|
||||
uwsgi_error("read()");
|
||||
if (errno != EAGAIN && errno != EINTR && errno != EWOULDBLOCK) {
|
||||
uwsgi_error("uwsgi_mule_handler/read()");
|
||||
}
|
||||
}
|
||||
else {
|
||||
int i, found = 0;
|
||||
@@ -343,6 +346,7 @@ next:
|
||||
if (interesting_fd > -1) {
|
||||
len = read(interesting_fd, &uwsgi_signal, 1);
|
||||
if (len <= 0) {
|
||||
if (len < 0 && (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)) goto clear;
|
||||
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
|
||||
end_me(0);
|
||||
}
|
||||
@@ -350,7 +354,7 @@ next:
|
||||
uwsgi_log_verbose("master sent signal %d to mule %d\n", uwsgi_signal, uwsgi.muleid);
|
||||
#endif
|
||||
if (uwsgi_signal_handler(uwsgi_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.muleid);
|
||||
}
|
||||
// set the error condition
|
||||
len = -1;
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@ int u_offload_transfer_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offlo
|
||||
return -1;
|
||||
}
|
||||
|
||||
uor->fd = uwsgi_connect(uor->ubuf->buf, 0, 1);
|
||||
uor->fd = uwsgi_connect(uor->name, 0, 1);
|
||||
if (uor->fd < 0) {
|
||||
uwsgi_error("u_offload_transfer_prepare()/connect()");
|
||||
return -1;
|
||||
|
||||
+106
-6
@@ -2,7 +2,7 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
// this is line uwsgi_str_num but with security checks
|
||||
// this is like uwsgi_str_num but with security checks
|
||||
static size_t get_content_length(char *buf, uint16_t size) {
|
||||
int i;
|
||||
size_t val = 0;
|
||||
@@ -80,7 +80,7 @@ ssize_t send_udp_message(uint8_t modifier1, uint8_t modifier2, char *host, char
|
||||
ret = sendto(fd, (char *) uh, message_size + 4, 0, (struct sockaddr *) &un_addr, sizeof(un_addr));
|
||||
}
|
||||
if (ret < 0) {
|
||||
uwsgi_error("sendto()");
|
||||
uwsgi_error("send_udp_message()/sendto()");
|
||||
}
|
||||
close(fd);
|
||||
|
||||
@@ -303,8 +303,41 @@ static int uwsgi_proto_check_9(struct wsgi_request *wsgi_req, char *key, char *b
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uwsgi_parse_http_range(char *buf, uint16_t len, size_t *from, size_t *to) {
|
||||
*from = 0;
|
||||
*to = 0;
|
||||
uint16_t rlen = 0;
|
||||
uint16_t i;
|
||||
for(i=0;i<len;i++) {
|
||||
if (buf[i] == ',') break;
|
||||
rlen++;
|
||||
}
|
||||
|
||||
// bytes=X-
|
||||
if (rlen < 8) return;
|
||||
char *equal = memchr(buf, '=', rlen);
|
||||
if (!equal) return;
|
||||
if (equal-buf != 5) return;
|
||||
if (memcmp(buf, "bytes", 5)) return;
|
||||
char *range = equal+1;
|
||||
rlen -= 6;
|
||||
char *dash = memchr(range, '-', rlen);
|
||||
if (!dash) return;
|
||||
*from = uwsgi_str_num(range, dash-range);
|
||||
*to = uwsgi_str_num(dash+1, rlen - ((dash+1)-range));
|
||||
if (*to > 0 && *from > *to) {
|
||||
*from = 0;
|
||||
*to = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int uwsgi_proto_check_10(struct wsgi_request *wsgi_req, char *key, char *buf, uint16_t len) {
|
||||
|
||||
if (uwsgi.honour_range && !uwsgi_proto_key("HTTP_RANGE", 10)) {
|
||||
uwsgi_parse_http_range(buf, len, &wsgi_req->range_from, &wsgi_req->range_to);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!uwsgi_proto_key("UWSGI_FILE", 10)) {
|
||||
wsgi_req->file = buf;
|
||||
wsgi_req->file_len = len;
|
||||
@@ -312,6 +345,12 @@ static int uwsgi_proto_check_10(struct wsgi_request *wsgi_req, char *key, char *
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!uwsgi_proto_key("UWSGI_HOME", 10)) {
|
||||
wsgi_req->home = buf;
|
||||
wsgi_req->home_len = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -354,6 +393,13 @@ static int uwsgi_proto_check_11(struct wsgi_request *wsgi_req, char *key, char *
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!uwsgi_proto_key("HTTP_COOKIE", 11)) {
|
||||
wsgi_req->cookie = buf;
|
||||
wsgi_req->cookie_len = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (!uwsgi_proto_key("UWSGI_APPID", 11)) {
|
||||
wsgi_req->appid = buf;
|
||||
wsgi_req->appid_len = len;
|
||||
@@ -409,8 +455,8 @@ static int uwsgi_proto_check_12(struct wsgi_request *wsgi_req, char *key, char *
|
||||
}
|
||||
|
||||
if (!uwsgi_proto_key("UWSGI_PYHOME", 12)) {
|
||||
wsgi_req->pyhome = buf;
|
||||
wsgi_req->pyhome_len = len;
|
||||
wsgi_req->home = buf;
|
||||
wsgi_req->home_len = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -693,7 +739,7 @@ next:
|
||||
// check if data are available in the local cache
|
||||
if (wsgi_req->cache_get_len > 0) {
|
||||
uint64_t cache_value_size;
|
||||
char *cache_value = uwsgi_cache_magic_get(wsgi_req->cache_get, wsgi_req->cache_get_len, &cache_value_size, NULL);
|
||||
char *cache_value = uwsgi_cache_magic_get(wsgi_req->cache_get, wsgi_req->cache_get_len, &cache_value_size, NULL, NULL);
|
||||
if (cache_value && cache_value_size > 0) {
|
||||
uwsgi_response_write_body_do(wsgi_req, cache_value, cache_value_size);
|
||||
free(cache_value);
|
||||
@@ -704,7 +750,7 @@ next:
|
||||
if (uwsgi.check_cache && wsgi_req->uri_len && wsgi_req->method_len == 3 && wsgi_req->method[0] == 'G' && wsgi_req->method[1] == 'E' && wsgi_req->method[2] == 'T') {
|
||||
|
||||
uint64_t cache_value_size;
|
||||
char *cache_value = uwsgi_cache_magic_get(wsgi_req->uri, wsgi_req->uri_len, &cache_value_size, NULL);
|
||||
char *cache_value = uwsgi_cache_magic_get(wsgi_req->uri, wsgi_req->uri_len, &cache_value_size, NULL, NULL);
|
||||
if (cache_value && cache_value_size > 0) {
|
||||
uwsgi_response_write_body_do(wsgi_req, cache_value, cache_value_size);
|
||||
free(cache_value);
|
||||
@@ -961,6 +1007,60 @@ int uwsgi_hooked_parse_array(char *buffer, size_t len, void (*hook) (uint16_t, c
|
||||
|
||||
}
|
||||
|
||||
|
||||
// this functions transform a raw HTTP response to a uWSGI-managed response
|
||||
int uwsgi_blob_to_response(struct wsgi_request *wsgi_req, char *body, size_t len) {
|
||||
char *line = body;
|
||||
size_t line_len = 0;
|
||||
size_t i;
|
||||
int status_managed = 0;
|
||||
for(i=0;i<len;i++) {
|
||||
if (body[i] == '\n') {
|
||||
// invalid line
|
||||
if (line_len < 1) {
|
||||
return -1;
|
||||
}
|
||||
if (line[line_len-1] != '\r') {
|
||||
return -1;
|
||||
}
|
||||
// end of the headers
|
||||
if (line_len == 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (status_managed) {
|
||||
char *colon = memchr(line, ':', line_len-1);
|
||||
if (!colon) return -1;
|
||||
if (colon[1] != ' ') return -1;
|
||||
if (uwsgi_response_add_header(wsgi_req, line, colon-line, colon+2, (line_len-1) - ((colon+2)-line))) return -1;
|
||||
}
|
||||
else {
|
||||
char *space = memchr(line, ' ', line_len-1);
|
||||
if (!space) return -1;
|
||||
if ((line_len-1) - ((space+1)-line) < 3) return -1;
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, space+1, (line_len-1) - ((space+1)-line))) return -1;
|
||||
status_managed = 1;
|
||||
}
|
||||
line = NULL;
|
||||
line_len = 0;
|
||||
}
|
||||
else {
|
||||
if (!line) {
|
||||
line = body + i;
|
||||
}
|
||||
line_len++;
|
||||
}
|
||||
}
|
||||
|
||||
if ((i+1) < len) {
|
||||
if (uwsgi_response_write_body_do(wsgi_req, body + (i + 1), len-(i+1))) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
the following functions need to take in account that POST data could be already available in wsgi_req->buffer (generally when uwsgi protocol is in use)
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
QUERY_STRING management functions (mainly used by the internal routing subsystem)
|
||||
|
||||
*/
|
||||
|
||||
static char *check_qs(char *qs, uint16_t qs_len, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
// search for the equal sign
|
||||
char *equal = memchr(qs, '=', qs_len);
|
||||
if (!equal) return NULL;
|
||||
|
||||
if (uwsgi_strncmp(key, keylen, qs, equal-qs)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qs_len -= (equal-qs)+1;
|
||||
if (qs_len == 0) return NULL;
|
||||
|
||||
*vallen = qs_len;
|
||||
return equal+1;
|
||||
}
|
||||
|
||||
char *uwsgi_get_qs(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
uint16_t i;
|
||||
|
||||
char *qs = wsgi_req->query_string;
|
||||
uint16_t qs_len = 0;
|
||||
char *ptr = wsgi_req->query_string;
|
||||
//start splitting by ;
|
||||
for(i=0;i<wsgi_req->query_string_len;i++) {
|
||||
if (!qs) {
|
||||
qs = ptr + i;
|
||||
}
|
||||
if (ptr[i] == '&') {
|
||||
char *value = check_qs(qs, qs_len, key, keylen, vallen);
|
||||
if (value) {
|
||||
return value;
|
||||
}
|
||||
qs_len = 0;
|
||||
qs = NULL;
|
||||
}
|
||||
else {
|
||||
qs_len++;
|
||||
}
|
||||
}
|
||||
|
||||
if (qs_len > 0) {
|
||||
char *value = check_qs(qs, qs_len, key, keylen, vallen);
|
||||
if (value) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
+15
-15
@@ -47,7 +47,7 @@ void uwsgi_request_body_seek(struct wsgi_request *wsgi_req, off_t pos) {
|
||||
|
||||
if (uwsgi.post_buffering) {
|
||||
if (pos < 0) {
|
||||
if (pos > (off_t) wsgi_req->post_pos) {
|
||||
if ((off_t) wsgi_req->post_pos - pos < 0) {
|
||||
wsgi_req->post_pos = 0;
|
||||
return;
|
||||
}
|
||||
@@ -108,64 +108,65 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
}
|
||||
|
||||
remains = UMIN(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark, wsgi_req->post_cl - wsgi_req->post_pos);
|
||||
|
||||
// read from a file
|
||||
if (wsgi_req->post_file) {
|
||||
size_t ret = fread(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, wsgi_req->post_readline_size - wsgi_req->post_readline_watermark, 1, wsgi_req->post_file);
|
||||
size_t ret = fread(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, remains, 1, wsgi_req->post_file);
|
||||
if (ret == 0) {
|
||||
uwsgi_error("consume_body_for_readline()/fread()");
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->post_pos += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
|
||||
wsgi_req->post_readline_watermark += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
|
||||
wsgi_req->post_pos += remains;
|
||||
wsgi_req->post_readline_watermark += remains;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// read from post_buffering memory
|
||||
if (uwsgi.post_buffering) {
|
||||
wsgi_req->post_pos += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
|
||||
memcpy(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, wsgi_req->post_buffering_buf + wsgi_req->post_pos, wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
wsgi_req->post_readline_watermark += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
|
||||
memcpy(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, wsgi_req->post_buffering_buf + wsgi_req->post_pos, remains);
|
||||
wsgi_req->post_pos += remains;
|
||||
wsgi_req->post_readline_watermark += remains;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// read from socket
|
||||
ssize_t len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
ssize_t len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , remains);
|
||||
if (len > 0) {
|
||||
wsgi_req->post_pos += len;
|
||||
wsgi_req->post_readline_watermark += len;
|
||||
return 0;
|
||||
}
|
||||
if (len == 0) {
|
||||
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
uwsgi_read_error(remains);
|
||||
return -1;
|
||||
}
|
||||
if (len < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
goto wait;
|
||||
}
|
||||
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
uwsgi_read_error(remains);
|
||||
return -1;
|
||||
}
|
||||
wait:
|
||||
ret = uwsgi_wait_read_req(wsgi_req);
|
||||
if (ret > 0) {
|
||||
len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , remains);
|
||||
if (len > 0) {
|
||||
wsgi_req->post_pos += len;
|
||||
wsgi_req->post_readline_watermark += len;
|
||||
return 0;
|
||||
}
|
||||
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
uwsgi_read_error(remains);
|
||||
return -1;
|
||||
}
|
||||
// 0 means timeout
|
||||
else if (ret == 0) {
|
||||
uwsgi_read_timeout(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
uwsgi_read_timeout(remains);
|
||||
return -1;
|
||||
}
|
||||
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
uwsgi_read_error(remains);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -347,7 +348,6 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
|
||||
if (wsgi_req->post_file) {
|
||||
if (fread(wsgi_req->post_read_buf + *rlen, remains, 1, wsgi_req->post_file) != 1) {
|
||||
*rlen = -1;
|
||||
uwsgi_log("%llu\n", remains);
|
||||
uwsgi_error("uwsgi_request_body_read()/fread()");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+546
-4
@@ -3,6 +3,43 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_route_var *uwsgi_register_route_var(char *name, char *(*func)(struct wsgi_request *, char *, uint16_t, uint16_t *)) {
|
||||
|
||||
struct uwsgi_route_var *old_urv = NULL,*urv = uwsgi.route_vars;
|
||||
while(urv) {
|
||||
if (!strcmp(urv->name, name)) {
|
||||
return urv;
|
||||
}
|
||||
old_urv = urv;
|
||||
urv = urv->next;
|
||||
}
|
||||
|
||||
urv = uwsgi_calloc(sizeof(struct uwsgi_route_var));
|
||||
urv->name = name;
|
||||
urv->name_len = strlen(name);
|
||||
urv->func = func;
|
||||
|
||||
if (old_urv) {
|
||||
old_urv->next = urv;
|
||||
}
|
||||
else {
|
||||
uwsgi.route_vars = urv;
|
||||
}
|
||||
|
||||
return urv;
|
||||
}
|
||||
|
||||
struct uwsgi_route_var *uwsgi_get_route_var(char *name, uint16_t name_len) {
|
||||
struct uwsgi_route_var *urv = uwsgi.route_vars;
|
||||
while(urv) {
|
||||
if (!uwsgi_strncmp(urv->name, urv->name_len, name, name_len)) {
|
||||
return urv;
|
||||
}
|
||||
urv = urv->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *uwsgi_routing_translate(struct wsgi_request *wsgi_req, struct uwsgi_route *ur, char *subject, uint16_t subject_len, char *data, size_t data_len) {
|
||||
|
||||
char *pass1 = data;
|
||||
@@ -44,9 +81,32 @@ struct uwsgi_buffer *uwsgi_routing_translate(struct wsgi_request *wsgi_req, stru
|
||||
case 2:
|
||||
if (pass1[i] == '}') {
|
||||
uint16_t vallen = 0;
|
||||
char *value = uwsgi_get_var(wsgi_req, key, keylen, &vallen);
|
||||
int need_free = 0;
|
||||
char *value = NULL;
|
||||
char *bracket = memchr(key, '[', keylen);
|
||||
if (bracket && keylen > 0 && key[keylen-1] == ']') {
|
||||
struct uwsgi_route_var *urv = uwsgi_get_route_var(key, bracket - key);
|
||||
if (urv) {
|
||||
need_free = urv->need_free;
|
||||
value = urv->func(wsgi_req, bracket + 1, keylen - (urv->name_len+2), &vallen);
|
||||
}
|
||||
else {
|
||||
value = uwsgi_get_var(wsgi_req, key, keylen, &vallen);
|
||||
}
|
||||
}
|
||||
else {
|
||||
value = uwsgi_get_var(wsgi_req, key, keylen, &vallen);
|
||||
}
|
||||
if (value) {
|
||||
if (uwsgi_buffer_append(ub, value, vallen)) goto error;
|
||||
if (uwsgi_buffer_append(ub, value, vallen)) {
|
||||
if (need_free) {
|
||||
free(value);
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
if (need_free) {
|
||||
free(value);
|
||||
}
|
||||
}
|
||||
status = 0;
|
||||
key = NULL;
|
||||
@@ -97,6 +157,8 @@ int uwsgi_apply_routes_do(struct wsgi_request *wsgi_req, char *subject, uint16_t
|
||||
|
||||
while (routes) {
|
||||
|
||||
if (routes->label) goto next;
|
||||
|
||||
if (wsgi_req->route_goto > 0 && wsgi_req->route_pc < wsgi_req->route_goto) {
|
||||
goto next;
|
||||
}
|
||||
@@ -108,6 +170,11 @@ int uwsgi_apply_routes_do(struct wsgi_request *wsgi_req, char *subject, uint16_t
|
||||
wsgi_req->route_goto = 0;
|
||||
|
||||
if (!routes->if_func) {
|
||||
// could be a "run"
|
||||
if (!routes->subject) {
|
||||
n = 0;
|
||||
goto run;
|
||||
}
|
||||
if (!subject) {
|
||||
char **subject2 = (char **) (((char *) (wsgi_req)) + routes->subject);
|
||||
uint16_t *subject_len2 = (uint16_t *) (((char *) (wsgi_req)) + routes->subject_len);
|
||||
@@ -137,6 +204,7 @@ int uwsgi_apply_routes_do(struct wsgi_request *wsgi_req, char *subject, uint16_t
|
||||
}
|
||||
}
|
||||
|
||||
run:
|
||||
if (n >= 0) {
|
||||
wsgi_req->is_routing = 1;
|
||||
int ret = routes->func(wsgi_req, routes);
|
||||
@@ -152,6 +220,10 @@ int uwsgi_apply_routes_do(struct wsgi_request *wsgi_req, char *subject, uint16_t
|
||||
if (ret == UWSGI_ROUTE_GOON) {
|
||||
goon_func = routes->func;
|
||||
}
|
||||
|
||||
if (ret == -1) {
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
}
|
||||
next:
|
||||
subject = orig_subject;
|
||||
@@ -197,6 +269,8 @@ static void *uwsgi_route_get_condition_func(char *name) {
|
||||
|
||||
void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
|
||||
|
||||
char *space = NULL;
|
||||
char *command = NULL;
|
||||
struct uwsgi_route *old_ur = NULL,*ur = uwsgi.routes;
|
||||
uint64_t pos = 0;
|
||||
while(ur) {
|
||||
@@ -223,7 +297,12 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
|
||||
|
||||
char *route = uwsgi_str(value);
|
||||
|
||||
char *space = strchr(route, ' ');
|
||||
if (!strcmp(foobar, "run")) {
|
||||
command = route;
|
||||
goto done;
|
||||
}
|
||||
|
||||
space = strchr(route, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid route syntax\n");
|
||||
exit(1);
|
||||
@@ -299,7 +378,8 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
|
||||
}
|
||||
}
|
||||
|
||||
char *command = space + 1;
|
||||
command = space + 1;
|
||||
done:
|
||||
ur->action = uwsgi_str(command);
|
||||
|
||||
char *colon = strchr(command, ':');
|
||||
@@ -405,6 +485,28 @@ static int uwsgi_router_goon(struct uwsgi_route *ur, char *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// flush response
|
||||
static int transform_flush(struct wsgi_request *wsgi_req, struct uwsgi_buffer *ub, struct uwsgi_buffer **foobar, void *data) {
|
||||
wsgi_req->flush = 1;
|
||||
return uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
|
||||
return 0;
|
||||
}
|
||||
static int uwsgi_router_flush_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
|
||||
// if there are no transformations defined, set the flush right now
|
||||
if (!wsgi_req->transformations) {
|
||||
wsgi_req->flush = 1;
|
||||
}
|
||||
else {
|
||||
// otherwise push it in the chain
|
||||
uwsgi_add_transformation(wsgi_req, transform_flush, NULL);
|
||||
}
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_flush(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_flush_func;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// log route
|
||||
static int uwsgi_router_log_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
|
||||
@@ -585,6 +687,153 @@ static int uwsgi_router_signal(struct uwsgi_route *ur, char *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// chdir route
|
||||
static int uwsgi_router_chdir_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;
|
||||
if (chdir(ub->buf)) {
|
||||
uwsgi_error("uwsgi_router_chdir_func()/chdir()");
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_chdir(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_chdir_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// setapp route
|
||||
static int uwsgi_router_setapp_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;
|
||||
char *ptr = uwsgi_req_append(wsgi_req, "UWSGI_APPID", 11, ub->buf, ub->pos);
|
||||
if (!ptr) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
wsgi_req->appid = ptr;
|
||||
wsgi_req->appid_len = ub->pos;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_setapp(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_setapp_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// sethome route
|
||||
static int uwsgi_router_sethome_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;
|
||||
char *ptr = uwsgi_req_append(wsgi_req, "UWSGI_HOME", 10, ub->buf, ub->pos);
|
||||
if (!ptr) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
wsgi_req->home = ptr;
|
||||
wsgi_req->home_len = ub->pos;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_sethome(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_sethome_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// setfile route
|
||||
static int uwsgi_router_setfile_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;
|
||||
char *ptr = uwsgi_req_append(wsgi_req, "UWSGI_HOME", 10, ub->buf, ub->pos);
|
||||
if (!ptr) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
wsgi_req->file = ptr;
|
||||
wsgi_req->file_len = ub->pos;
|
||||
wsgi_req->dynamic = 1;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_setfile(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_setfile_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// setprocname route
|
||||
static int uwsgi_router_setprocname_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_set_processname(ub->buf);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_setprocname(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_setprocname_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// alarm route
|
||||
static int uwsgi_router_alarm_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_alarm = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
||||
if (!ub_alarm) return UWSGI_ROUTE_BREAK;
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data2, ur->data2_len);
|
||||
if (!ub) {
|
||||
uwsgi_buffer_destroy(ub_alarm);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
uwsgi_alarm_trigger(ub_alarm->buf, ub->buf, ub->pos);
|
||||
uwsgi_buffer_destroy(ub_alarm);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_alarm(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_alarm_func;
|
||||
char *space = strchr(arg, ' ');
|
||||
if (!space) {
|
||||
return -1;
|
||||
}
|
||||
*space = 0;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
ur->data2 = space+1;
|
||||
ur->data2_len = strlen(ur->data2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// send route
|
||||
static int uwsgi_router_send_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
|
||||
@@ -666,6 +915,20 @@ static int uwsgi_route_condition_regexp(struct wsgi_request *wsgi_req, struct uw
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_route_condition_empty(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, ur->subject_str_len);
|
||||
if (!ub) return -1;
|
||||
|
||||
if (ub->pos == 0) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_route_condition_equal(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
|
||||
@@ -690,6 +953,119 @@ static int uwsgi_route_condition_equal(struct wsgi_request *wsgi_req, struct uws
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_route_condition_higher(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
|
||||
if (!semicolon) return 0;
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
|
||||
if (!ub) return -1;
|
||||
|
||||
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
|
||||
if (!ub2) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return -1;
|
||||
}
|
||||
|
||||
long num1 = strtol(ub->buf, NULL, 10);
|
||||
long num2 = strtol(ub2->buf, NULL, 10);
|
||||
if(num1 > num2) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 1;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_route_condition_higherequal(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
|
||||
if (!semicolon) return 0;
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
|
||||
if (!ub) return -1;
|
||||
|
||||
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
|
||||
if (!ub2) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return -1;
|
||||
}
|
||||
|
||||
long num1 = strtol(ub->buf, NULL, 10);
|
||||
long num2 = strtol(ub2->buf, NULL, 10);
|
||||
if(num1 >= num2) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 1;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_route_condition_lower(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
|
||||
if (!semicolon) return 0;
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
|
||||
if (!ub) return -1;
|
||||
|
||||
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
|
||||
if (!ub2) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return -1;
|
||||
}
|
||||
|
||||
long num1 = strtol(ub->buf, NULL, 10);
|
||||
long num2 = strtol(ub2->buf, NULL, 10);
|
||||
if(num1 < num2) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 1;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_route_condition_lowerequal(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
|
||||
if (!semicolon) return 0;
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
|
||||
if (!ub) return -1;
|
||||
|
||||
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
|
||||
if (!ub2) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return -1;
|
||||
}
|
||||
|
||||
long num1 = strtol(ub->buf, NULL, 10);
|
||||
long num2 = strtol(ub2->buf, NULL, 10);
|
||||
if(num1 <= num2) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 1;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
static int uwsgi_route_condition_lord(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;
|
||||
int ret = uwsgi_legion_i_am_the_lord(ub->buf);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static int uwsgi_route_condition_startswith(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
|
||||
if (!semicolon) return 0;
|
||||
@@ -713,6 +1089,29 @@ static int uwsgi_route_condition_startswith(struct wsgi_request *wsgi_req, struc
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_route_condition_contains(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
|
||||
if (!semicolon) return 0;
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
|
||||
if (!ub) return -1;
|
||||
|
||||
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
|
||||
if (!ub2) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(uwsgi_contains_n(ub->buf, ub->pos, ub2->buf, ub2->pos)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 1;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_route_condition_endswith(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
|
||||
if (!semicolon) return 0;
|
||||
@@ -775,6 +1174,106 @@ static int uwsgi_route_condition_isexec(struct wsgi_request *wsgi_req, struct uw
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *uwsgi_route_var_uwsgi(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
char *ret = NULL;
|
||||
if (!uwsgi_strncmp(key, keylen, "wid", 3)) {
|
||||
ret = uwsgi_num2str(uwsgi.mywid);
|
||||
*vallen = strlen(ret);
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "pid", 3)) {
|
||||
ret = uwsgi_num2str(uwsgi.mypid);
|
||||
*vallen = strlen(ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *uwsgi_route_var_mime(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
char *ret = NULL;
|
||||
uint16_t var_vallen = 0;
|
||||
char *var_value = uwsgi_get_var(wsgi_req, key, keylen, &var_vallen);
|
||||
if (var_value) {
|
||||
size_t mime_type_len = 0;
|
||||
char *ret = uwsgi_get_mime_type(key, keylen, &mime_type_len);
|
||||
if (ret) *vallen = mime_type_len;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static char *uwsgi_route_var_time(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
char *ret = NULL;
|
||||
if (!uwsgi_strncmp(key, keylen, "unix", 4)) {
|
||||
ret = uwsgi_num2str(uwsgi_now());
|
||||
*vallen = strlen(ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *uwsgi_route_var_base64(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
char *ret = NULL;
|
||||
uint16_t var_vallen = 0;
|
||||
char *var_value = uwsgi_get_var(wsgi_req, key, keylen, &var_vallen);
|
||||
if (var_value) {
|
||||
size_t b64_len = 0;
|
||||
ret = uwsgi_base64_encode(var_value, var_vallen, &b64_len);
|
||||
*vallen = b64_len;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *uwsgi_route_var_hex(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
char *ret = NULL;
|
||||
uint16_t var_vallen = 0;
|
||||
char *var_value = uwsgi_get_var(wsgi_req, key, keylen, &var_vallen);
|
||||
if (var_value) {
|
||||
ret = uwsgi_str_to_hex(var_value, var_vallen);
|
||||
*vallen = var_vallen*2;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_MATHEVAL
|
||||
static char *uwsgi_route_var_math(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
char *ret = NULL;
|
||||
// avoid crash
|
||||
if (!wsgi_req->var_cnt) return NULL;
|
||||
// we make a bit of fun here, we do a copy of the vars buffer (+1 byte for final zero) and zeor-pad all of the strings
|
||||
char *vars_buf = uwsgi_malloc(wsgi_req->uh->pktsize + keylen + 1);
|
||||
char **names = uwsgi_malloc(sizeof(char *) * (wsgi_req->var_cnt/2));
|
||||
double *values = uwsgi_calloc(sizeof(double) * (wsgi_req->var_cnt/2));
|
||||
int i,j = 0;
|
||||
char *ptr = vars_buf;
|
||||
for (i = wsgi_req->var_cnt-1; i > 0; i -= 2) {
|
||||
memcpy(ptr, wsgi_req->hvec[i-1].iov_base, wsgi_req->hvec[i-1].iov_len);
|
||||
names[j] = ptr;
|
||||
ptr += wsgi_req->hvec[i-1].iov_len;
|
||||
*ptr++=0;
|
||||
char *num = ptr;
|
||||
memcpy(ptr, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
|
||||
ptr += wsgi_req->hvec[i].iov_len;
|
||||
*ptr++=0;
|
||||
values[j] = strtod(num, NULL);
|
||||
j++;
|
||||
}
|
||||
|
||||
char *expr = ptr;
|
||||
memcpy(ptr, key, keylen); ptr += keylen;
|
||||
*ptr++=0;
|
||||
|
||||
void *e = evaluator_create(expr);
|
||||
if (!e) goto end;
|
||||
double n = evaluator_evaluate(e, j, names, values);
|
||||
evaluator_destroy(e);
|
||||
ret = uwsgi_num2str((int)n);
|
||||
*vallen = strlen(ret);
|
||||
end:
|
||||
free(vars_buf);
|
||||
free(names);
|
||||
free(values);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
// register embedded routers
|
||||
void uwsgi_register_embedded_routers() {
|
||||
@@ -792,6 +1291,14 @@ void uwsgi_register_embedded_routers() {
|
||||
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_router("chdir", uwsgi_router_chdir);
|
||||
uwsgi_register_router("setapp", uwsgi_router_setapp);
|
||||
uwsgi_register_router("sethome", uwsgi_router_sethome);
|
||||
uwsgi_register_router("setfile", uwsgi_router_setfile);
|
||||
uwsgi_register_router("setprocname", uwsgi_router_setprocname);
|
||||
uwsgi_register_router("alarm", uwsgi_router_alarm);
|
||||
|
||||
uwsgi_register_router("flush", uwsgi_router_flush);
|
||||
|
||||
uwsgi_register_route_condition("exists", uwsgi_route_condition_exists);
|
||||
uwsgi_register_route_condition("isfile", uwsgi_route_condition_isfile);
|
||||
@@ -806,6 +1313,38 @@ void uwsgi_register_embedded_routers() {
|
||||
uwsgi_register_route_condition("endswith", uwsgi_route_condition_endswith);
|
||||
uwsgi_register_route_condition("regexp", uwsgi_route_condition_regexp);
|
||||
uwsgi_register_route_condition("re", uwsgi_route_condition_regexp);
|
||||
uwsgi_register_route_condition("ishigher", uwsgi_route_condition_higher);
|
||||
uwsgi_register_route_condition(">", uwsgi_route_condition_higher);
|
||||
uwsgi_register_route_condition("islower", uwsgi_route_condition_lower);
|
||||
uwsgi_register_route_condition("<", uwsgi_route_condition_lower);
|
||||
uwsgi_register_route_condition("ishigherequal", uwsgi_route_condition_higherequal);
|
||||
uwsgi_register_route_condition(">=", uwsgi_route_condition_higherequal);
|
||||
uwsgi_register_route_condition("islowerequal", uwsgi_route_condition_lowerequal);
|
||||
uwsgi_register_route_condition("<=", uwsgi_route_condition_lowerequal);
|
||||
uwsgi_register_route_condition("contains", uwsgi_route_condition_contains);
|
||||
uwsgi_register_route_condition("contain", uwsgi_route_condition_contains);
|
||||
#ifdef UWSGI_SSL
|
||||
uwsgi_register_route_condition("lord", uwsgi_route_condition_lord);
|
||||
#endif
|
||||
|
||||
uwsgi_register_route_condition("empty", uwsgi_route_condition_empty);
|
||||
|
||||
uwsgi_register_route_var("cookie", uwsgi_get_cookie);
|
||||
uwsgi_register_route_var("qs", uwsgi_get_qs);
|
||||
uwsgi_register_route_var("mime", uwsgi_route_var_mime);
|
||||
struct uwsgi_route_var *urv = uwsgi_register_route_var("uwsgi", uwsgi_route_var_uwsgi);
|
||||
urv->need_free = 1;
|
||||
urv = uwsgi_register_route_var("time", uwsgi_route_var_time);
|
||||
urv->need_free = 1;
|
||||
#ifdef UWSGI_MATHEVAL
|
||||
urv = uwsgi_register_route_var("math", uwsgi_route_var_math);
|
||||
urv->need_free = 1;
|
||||
#endif
|
||||
urv = uwsgi_register_route_var("base64", uwsgi_route_var_base64);
|
||||
urv->need_free = 1;
|
||||
|
||||
urv = uwsgi_register_route_var("hex", uwsgi_route_var_hex);
|
||||
urv->need_free = 1;
|
||||
}
|
||||
|
||||
struct uwsgi_router *uwsgi_register_router(char *name, int (*func) (struct uwsgi_route *, char *)) {
|
||||
@@ -864,6 +1403,9 @@ void uwsgi_routing_dump() {
|
||||
if (routes->label) {
|
||||
uwsgi_log("[rule: %llu] label: %s\n", (unsigned long long ) routes->pos, routes->label);
|
||||
}
|
||||
else if (!routes->subject_str && !routes->if_func) {
|
||||
uwsgi_log("[rule: %llu] action: %s\n", (unsigned long long ) routes->pos, routes->action);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[rule: %llu] subject: %s %s: %s%s action: %s\n", (unsigned long long ) routes->pos, routes->subject_str, routes->if_func ? "func" : "regexp", routes->if_negate ? "!" : "", routes->regexp, routes->action);
|
||||
}
|
||||
|
||||
+5
-5
@@ -1,8 +1,8 @@
|
||||
#include "uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int uwsgi_register_rpc(char *name, uint8_t modifier1, uint8_t args, void *func) {
|
||||
int uwsgi_register_rpc(char *name, struct uwsgi_plugin *plugin, uint8_t args, void *func) {
|
||||
|
||||
struct uwsgi_rpc *urpc;
|
||||
int ret = -1;
|
||||
@@ -30,7 +30,7 @@ int uwsgi_register_rpc(char *name, uint8_t modifier1, uint8_t args, void *func)
|
||||
uwsgi.shared->rpc_count[uwsgi.mywid]++;
|
||||
already:
|
||||
memcpy(urpc->name, name, strlen(name));
|
||||
urpc->modifier1 = modifier1;
|
||||
urpc->plugin = plugin;
|
||||
urpc->args = args;
|
||||
urpc->func = func;
|
||||
urpc->shared = uwsgi.mywid == 0 ? 1 : 0;
|
||||
@@ -77,8 +77,8 @@ uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], cha
|
||||
}
|
||||
|
||||
if (urpc) {
|
||||
if (uwsgi.p[urpc->modifier1]->rpc) {
|
||||
ret = uwsgi.p[urpc->modifier1]->rpc(urpc->func, argc, argv, argvs, output);
|
||||
if (urpc->plugin->rpc) {
|
||||
ret = urpc->plugin->rpc(urpc->func, argc, argv, argvs, output);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -106,6 +106,9 @@ void uwsgi_setup_inherited_sockets() {
|
||||
//now close all the unbound fd
|
||||
for (j = 3; j < (int) uwsgi.max_fd; j++) {
|
||||
int useless = 1;
|
||||
|
||||
if (uwsgi_fd_is_safe(j)) continue;
|
||||
|
||||
if (uwsgi.has_emperor) {
|
||||
if (j == uwsgi.emperor_fd)
|
||||
continue;
|
||||
|
||||
+3
-139
@@ -177,89 +177,10 @@ int uwsgi_add_file_monitor(uint8_t sig, char *filename) {
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_probe *uwsgi_probe_register(struct uwsgi_probe **up, char *name, int (*func) (int, struct uwsgi_signal_probe *)) {
|
||||
|
||||
struct uwsgi_probe *uwsgi_up = *up, *old_up;
|
||||
|
||||
if (!uwsgi_up) {
|
||||
*up = uwsgi_malloc(sizeof(struct uwsgi_probe));
|
||||
uwsgi_up = *up;
|
||||
}
|
||||
else {
|
||||
while (uwsgi_up) {
|
||||
old_up = uwsgi_up;
|
||||
uwsgi_up = uwsgi_up->next;
|
||||
}
|
||||
|
||||
uwsgi_up = uwsgi_malloc(sizeof(struct uwsgi_probe));
|
||||
old_up->next = uwsgi_up;
|
||||
}
|
||||
|
||||
uwsgi_up->name = name;
|
||||
uwsgi_up->func = func;
|
||||
uwsgi_up->next = NULL;
|
||||
|
||||
uwsgi_log("registered new probe \"%s\" at %p\n", name, uwsgi_up);
|
||||
|
||||
return uwsgi_up;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_add_probe(uint8_t sig, char *kind, char *args, int timeout, int freq) {
|
||||
|
||||
uwsgi_lock(uwsgi.probe_table_lock);
|
||||
|
||||
if (ushared->probes_cnt < MAX_PROBES) {
|
||||
|
||||
struct uwsgi_probe *up = uwsgi.probes;
|
||||
while (up) {
|
||||
if (!strcmp(up->name, kind)) {
|
||||
break;
|
||||
}
|
||||
up = up->next;
|
||||
}
|
||||
|
||||
if (!up) {
|
||||
uwsgi_log("unable to find probe \"%s\" !!!\n", kind);
|
||||
uwsgi_unlock(uwsgi.probe_table_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// fill the probe table
|
||||
ushared->probes[ushared->probes_cnt].func = up->func;
|
||||
strncpy(ushared->probes[ushared->probes_cnt].args, args, 1024 - 1);
|
||||
ushared->probes[ushared->probes_cnt].registered = 0;
|
||||
ushared->probes[ushared->probes_cnt].sig = sig;
|
||||
ushared->probes[ushared->probes_cnt].fd = -1;
|
||||
ushared->probes[ushared->probes_cnt].state = 0;
|
||||
ushared->probes[ushared->probes_cnt].last_event = 0;
|
||||
ushared->probes[ushared->probes_cnt].data = NULL;
|
||||
ushared->probes[ushared->probes_cnt].cycles = 0;
|
||||
ushared->probes[ushared->probes_cnt].bad = 0;
|
||||
|
||||
if (!timeout) {
|
||||
timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
|
||||
}
|
||||
ushared->probes[ushared->probes_cnt].timeout = timeout;
|
||||
if (!freq) {
|
||||
freq = 1;
|
||||
}
|
||||
ushared->probes[ushared->probes_cnt].freq = freq;
|
||||
ushared->probes_cnt++;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("you can register max %d probes !!!\n", MAX_PROBES);
|
||||
uwsgi_unlock(uwsgi.probe_table_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_unlock(uwsgi.probe_table_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_add_timer(uint8_t sig, int secs) {
|
||||
|
||||
if (!uwsgi.master_process) return -1;
|
||||
|
||||
uwsgi_lock(uwsgi.timer_table_lock);
|
||||
|
||||
if (ushared->timers_cnt < 64) {
|
||||
@@ -282,63 +203,6 @@ int uwsgi_add_timer(uint8_t sig, int secs) {
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_opt_add_cron(char *opt, char *value, void *foobar) {
|
||||
|
||||
int i;
|
||||
|
||||
struct uwsgi_cron *old_uc, *uc = uwsgi.crons;
|
||||
if (!uc) {
|
||||
uc = uwsgi_malloc(sizeof(struct uwsgi_cron));
|
||||
uwsgi.crons = uc;
|
||||
}
|
||||
else {
|
||||
old_uc = uc;
|
||||
while (uc->next) {
|
||||
uc = uc->next;
|
||||
old_uc = uc;
|
||||
}
|
||||
|
||||
old_uc->next = uwsgi_malloc(sizeof(struct uwsgi_cron));
|
||||
uc = old_uc->next;
|
||||
}
|
||||
|
||||
memset(uc, 0, sizeof(struct uwsgi_cron));
|
||||
|
||||
if (sscanf(value, "%d %d %d %d %d %n", &uc->minute, &uc->hour, &uc->day, &uc->month, &uc->week, &i) != 5) {
|
||||
uwsgi_log("invalid cron syntax\n");
|
||||
exit(1);
|
||||
}
|
||||
uc->command = value + i;
|
||||
}
|
||||
|
||||
int uwsgi_signal_add_cron(uint8_t sig, int minute, int hour, int day, int month, int week) {
|
||||
|
||||
if (!uwsgi.master_process)
|
||||
return -1;
|
||||
|
||||
uwsgi_lock(uwsgi.cron_table_lock);
|
||||
|
||||
if (ushared->cron_cnt < MAX_CRONS) {
|
||||
|
||||
ushared->cron[ushared->cron_cnt].sig = sig;
|
||||
ushared->cron[ushared->cron_cnt].minute = minute;
|
||||
ushared->cron[ushared->cron_cnt].hour = hour;
|
||||
ushared->cron[ushared->cron_cnt].day = day;
|
||||
ushared->cron[ushared->cron_cnt].month = month;
|
||||
ushared->cron[ushared->cron_cnt].week = week;
|
||||
ushared->cron_cnt++;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("you can register max %d cron !!!\n", MAX_CRONS);
|
||||
uwsgi_unlock(uwsgi.cron_table_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_unlock(uwsgi.cron_table_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_signal_add_rb_timer(uint8_t sig, int secs, int iterations) {
|
||||
|
||||
if (!uwsgi.master_process)
|
||||
@@ -595,7 +459,7 @@ void uwsgi_receive_signal(int fd, char *name, int id) {
|
||||
if (ret == 0) {
|
||||
goto destroy;
|
||||
}
|
||||
else if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
|
||||
else if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) {
|
||||
uwsgi_error("[uwsgi-signal] read()");
|
||||
goto destroy;
|
||||
}
|
||||
|
||||
@@ -136,6 +136,24 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
uwsgi_log("setting abstract socket mode (warning: only Linux supports this)\n");
|
||||
}
|
||||
|
||||
if (uwsgi.so_sndbuf) {
|
||||
socklen_t sndbuf = (socklen_t) uwsgi.so_sndbuf;
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(socklen_t)) < 0) {
|
||||
uwsgi_error("SO_SNDBUF setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.so_rcvbuf) {
|
||||
socklen_t rcvbuf = (socklen_t) uwsgi.so_rcvbuf;
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(socklen_t)) < 0) {
|
||||
uwsgi_error("SO_RCVBUF setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
uws_addr->sun_family = AF_UNIX;
|
||||
if (socket_name[0] == '@') {
|
||||
memcpy(uws_addr->sun_path + abstract_socket, socket_name + 1, UMIN(strlen(socket_name + 1), 101));
|
||||
@@ -587,6 +605,24 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uwsgi.so_sndbuf) {
|
||||
socklen_t sndbuf = (socklen_t) uwsgi.so_sndbuf;
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(socklen_t)) < 0) {
|
||||
uwsgi_error("SO_SNDBUF setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.so_rcvbuf) {
|
||||
socklen_t rcvbuf = (socklen_t) uwsgi.so_rcvbuf;
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(socklen_t)) < 0) {
|
||||
uwsgi_error("SO_RCVBUF setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) {
|
||||
uwsgi_error("SO_REUSEADDR setsockopt()");
|
||||
|
||||
@@ -108,7 +108,6 @@ pid_t spooler_start(struct uwsgi_spooler * uspool) {
|
||||
signal(SIGSTOP, SIG_IGN);
|
||||
signal(SIGTSTP, SIG_IGN);
|
||||
|
||||
uwsgi.mywid = -1;
|
||||
uwsgi.mypid = getpid();
|
||||
uspool->pid = uwsgi.mypid;
|
||||
// avoid race conditions !!!
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
#ifdef UWSGI_SQLITE3
|
||||
|
||||
#include "uwsgi.h"
|
||||
#include <sqlite3.h>
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_sqlite3_config(char *file, char *magic_table[]) {
|
||||
|
||||
sqlite3 *db;
|
||||
char *err = NULL;
|
||||
char *query = "SELECT * FROM uwsgi";
|
||||
|
||||
char *colon = uwsgi_get_last_char(file, ':');
|
||||
|
||||
if (colon) {
|
||||
colon[0] = 0;
|
||||
if (colon[1] != 0) {
|
||||
query = colon + 1;
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("[uWSGI] getting sqlite3 configuration from %s\n", file);
|
||||
|
||||
#ifdef sqlite3_open_v2
|
||||
if (sqlite3_open_v2(file, &db, SQLITE_OPEN_READONLY, NULL)) {
|
||||
#else
|
||||
if (sqlite3_open(file, &db)) {
|
||||
#endif
|
||||
uwsgi_log("unable to open sqlite3 db: %s\n", sqlite3_errmsg(db));
|
||||
sqlite3_close(db);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (sqlite3_exec(db, query, uwsgi_sqlite3_config_callback, (void *) magic_table, &err)) {
|
||||
uwsgi_log("sqlite3 error: %s\n", err);
|
||||
sqlite3_close(db);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sqlite3_close(db);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
+8
-2
@@ -252,8 +252,14 @@ SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ci
|
||||
|
||||
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);
|
||||
// check for default cache
|
||||
if (!strcmp(uwsgi.ssl_sessions_use_cache, "true") && uwsgi.caches) {
|
||||
uwsgi.ssl_sessions_cache = uwsgi.caches;
|
||||
}
|
||||
else {
|
||||
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) {
|
||||
|
||||
+61
-26
@@ -55,7 +55,7 @@ gzip:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int set_http_date(time_t t, char *dst) {
|
||||
int uwsgi_http_date(time_t t, char *dst) {
|
||||
|
||||
static char *week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
|
||||
static char *months[] = {
|
||||
@@ -179,7 +179,7 @@ int uwsgi_add_expires_type(struct wsgi_request *wsgi_req, char *mime_type, int m
|
||||
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);
|
||||
int size = uwsgi_http_date(now + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -192,7 +192,7 @@ int uwsgi_add_expires_type(struct wsgi_request *wsgi_req, char *mime_type, int m
|
||||
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);
|
||||
int size = uwsgi_http_date(st->st_mtime + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -215,7 +215,7 @@ int uwsgi_add_expires(struct wsgi_request *wsgi_req, char *filename, int filenam
|
||||
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);
|
||||
int size = uwsgi_http_date(now + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -228,7 +228,7 @@ int uwsgi_add_expires(struct wsgi_request *wsgi_req, char *filename, int filenam
|
||||
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);
|
||||
int size = uwsgi_http_date(st->st_mtime + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -250,7 +250,7 @@ int uwsgi_add_expires_path_info(struct wsgi_request *wsgi_req, struct stat *st)
|
||||
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);
|
||||
int size = uwsgi_http_date(now + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -263,7 +263,7 @@ int uwsgi_add_expires_path_info(struct wsgi_request *wsgi_req, struct stat *st)
|
||||
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);
|
||||
int size = uwsgi_http_date(st->st_mtime + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -285,7 +285,7 @@ int uwsgi_add_expires_uri(struct wsgi_request *wsgi_req, struct stat *st) {
|
||||
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);
|
||||
int size = uwsgi_http_date(now + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -298,7 +298,7 @@ int uwsgi_add_expires_uri(struct wsgi_request *wsgi_req, struct stat *st) {
|
||||
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);
|
||||
int size = uwsgi_http_date(st->st_mtime + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -315,7 +315,7 @@ int uwsgi_add_expires_uri(struct wsgi_request *wsgi_req, struct stat *st) {
|
||||
#endif
|
||||
|
||||
|
||||
char *uwsgi_get_mime_type(char *name, int namelen, int *size) {
|
||||
char *uwsgi_get_mime_type(char *name, int namelen, size_t *size) {
|
||||
|
||||
int i;
|
||||
int count = 0;
|
||||
@@ -333,6 +333,10 @@ char *uwsgi_get_mime_type(char *name, int namelen, int *size) {
|
||||
if (!ext)
|
||||
return NULL;
|
||||
|
||||
|
||||
if (uwsgi.threads > 1)
|
||||
pthread_mutex_lock(&uwsgi.lock_static);
|
||||
|
||||
struct uwsgi_dyn_dict *udd = uwsgi.mimetypes;
|
||||
while (udd) {
|
||||
if (!uwsgi_strncmp(ext, count, udd->key, udd->keylen)) {
|
||||
@@ -361,11 +365,16 @@ char *uwsgi_get_mime_type(char *name, int namelen, int *size) {
|
||||
}
|
||||
}
|
||||
*size = udd->vallen;
|
||||
if (uwsgi.threads > 1)
|
||||
pthread_mutex_unlock(&uwsgi.lock_static);
|
||||
return udd->value;
|
||||
}
|
||||
udd = udd->next;
|
||||
}
|
||||
|
||||
if (uwsgi.threads > 1)
|
||||
pthread_mutex_unlock(&uwsgi.lock_static);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -429,16 +438,14 @@ static int uwsgi_static_stat(struct wsgi_request *wsgi_req, char *filename, size
|
||||
|
||||
int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, size_t real_filename_len, struct stat *st) {
|
||||
|
||||
int mime_type_size = 0;
|
||||
size_t mime_type_size = 0;
|
||||
char http_last_modified[49];
|
||||
|
||||
if (uwsgi.threads > 1)
|
||||
pthread_mutex_lock(&uwsgi.lock_static);
|
||||
int use_gzip = 0;
|
||||
|
||||
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);
|
||||
// here we need to choose if we want the gzip variant;
|
||||
if (uwsgi_static_want_gzip(wsgi_req, real_filename, real_filename_len, st)) use_gzip = 1;
|
||||
|
||||
if (wsgi_req->if_modified_since_len) {
|
||||
time_t ims = parse_http_date(wsgi_req->if_modified_since, wsgi_req->if_modified_since_len);
|
||||
@@ -451,8 +458,32 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
|
||||
uwsgi_log("[uwsgi-fileserve] file %s found\n", real_filename);
|
||||
#endif
|
||||
|
||||
|
||||
size_t fsize = st->st_size;
|
||||
if (wsgi_req->range_to) {
|
||||
fsize = wsgi_req->range_to - wsgi_req->range_from;
|
||||
if (fsize > (size_t)st->st_size) {
|
||||
fsize = st->st_size;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// reset in case of inconsistent size
|
||||
if (wsgi_req->range_from > fsize) {
|
||||
wsgi_req->range_from = 0;
|
||||
fsize = 0;
|
||||
}
|
||||
else {
|
||||
fsize -= wsgi_req->range_from;
|
||||
}
|
||||
}
|
||||
|
||||
// HTTP status
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return -1;
|
||||
if (fsize > 0 && (wsgi_req->range_from || wsgi_req->range_to)) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "206 Partial Content", 19)) return -1;
|
||||
}
|
||||
else {
|
||||
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);
|
||||
@@ -460,6 +491,10 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
|
||||
uwsgi_add_expires_uri(wsgi_req, st);
|
||||
#endif
|
||||
|
||||
if (use_gzip) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Content-Encoding", 16, "gzip", 4)) return -1;
|
||||
}
|
||||
|
||||
// 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;
|
||||
@@ -474,25 +509,25 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
|
||||
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);
|
||||
int size = uwsgi_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);
|
||||
int size = uwsgi_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 (to fsize NOT st->st_size)
|
||||
if (uwsgi_response_add_content_length(wsgi_req, fsize)) return -1;
|
||||
if (fsize > 0 && (wsgi_req->range_from || wsgi_req->range_to)) {
|
||||
// here use the original size !!!
|
||||
if (uwsgi_response_add_content_range(wsgi_req, wsgi_req->range_from, wsgi_req->range_to, st->st_size)) 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);
|
||||
int size = uwsgi_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
|
||||
@@ -506,7 +541,7 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
|
||||
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);
|
||||
uwsgi_response_sendfile_do(wsgi_req, fd, wsgi_req->range_from, fsize);
|
||||
}
|
||||
|
||||
wsgi_req->status = 200;
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
uWSGI transformations
|
||||
|
||||
responses can be buffered in the wsgi_request structure (instead of being sent to the client)
|
||||
Before closing the request, the transformations are applied in chain to the response buffer
|
||||
|
||||
Finally the resulting buffer is sent to the client
|
||||
|
||||
Transformations (if required) could completely swallow already set headers
|
||||
|
||||
*/
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int uwsgi_apply_transformations(struct wsgi_request *wsgi_req) {
|
||||
int ret = 0;
|
||||
struct uwsgi_transformation *ut = wsgi_req->transformations;
|
||||
while(ut) {
|
||||
struct uwsgi_buffer *new_ub = NULL;
|
||||
if (ut->func(wsgi_req, wsgi_req->response_buffer, &new_ub, ut->data)) {
|
||||
ret = -1;
|
||||
goto end;
|
||||
}
|
||||
if (new_ub) {
|
||||
uwsgi_buffer_destroy(wsgi_req->response_buffer);
|
||||
wsgi_req->response_buffer = new_ub;
|
||||
}
|
||||
ut = ut->next;
|
||||
}
|
||||
|
||||
end:
|
||||
ut = wsgi_req->transformations;
|
||||
while(ut) {
|
||||
struct uwsgi_transformation *current_ut = ut;
|
||||
ut = ut->next;
|
||||
free(current_ut);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct uwsgi_transformation *uwsgi_add_transformation(struct wsgi_request *wsgi_req, int (*func)(struct wsgi_request *, struct uwsgi_buffer *, struct uwsgi_buffer **, void *), void *data) {
|
||||
struct uwsgi_transformation *old_ut = NULL, *ut = wsgi_req->transformations;
|
||||
while(ut) {
|
||||
old_ut = ut;
|
||||
ut = ut->next;
|
||||
}
|
||||
|
||||
ut = uwsgi_malloc(sizeof(struct uwsgi_transformation));
|
||||
ut->func = func;
|
||||
ut->next = NULL;
|
||||
ut->data = data;
|
||||
|
||||
if (old_ut) {
|
||||
old_ut->next = ut;
|
||||
}
|
||||
else {
|
||||
wsgi_req->transformations = ut;
|
||||
}
|
||||
|
||||
// start buffering
|
||||
if (!wsgi_req->response_buffer) {
|
||||
wsgi_req->response_buffer = uwsgi_buffer_new(uwsgi.page_size);
|
||||
}
|
||||
|
||||
return ut;
|
||||
}
|
||||
+113
-15
@@ -222,12 +222,11 @@ void uwsgi_set_cgroup() {
|
||||
uwsgi_error_open(cgroup_taskfile);
|
||||
exit(1);
|
||||
}
|
||||
if (fprintf(cgroup, "%d", (int) getpid()) <= 0) {
|
||||
uwsgi_log("could not set cgroup\n");
|
||||
if (fprintf(cgroup, "%d\n", (int) getpid()) <= 0 || ferror(cgroup) || fclose(cgroup)) {
|
||||
uwsgi_error("could not set cgroup");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("assigned process %d to cgroup %s\n", (int) getpid(), cgroup_taskfile);
|
||||
fclose(cgroup);
|
||||
free(cgroup_taskfile);
|
||||
|
||||
|
||||
@@ -248,11 +247,10 @@ void uwsgi_set_cgroup() {
|
||||
cgroup_taskfile = uwsgi_concat3(usl->value, "/", uslo->value);
|
||||
cgroup = fopen(cgroup_taskfile, "w");
|
||||
if (cgroup) {
|
||||
if (fprintf(cgroup, "%s\n", cgroup_opt) < 0) {
|
||||
if (fprintf(cgroup, "%s\n", cgroup_opt) <= 0 || ferror(cgroup) || fclose(cgroup)) {
|
||||
uwsgi_log("could not set cgroup option %s to %s\n", uslo->value, cgroup_opt);
|
||||
exit(1);
|
||||
}
|
||||
fclose(cgroup);
|
||||
uwsgi_log("set %s to %s\n", cgroup_opt, cgroup_taskfile);
|
||||
}
|
||||
free(cgroup_taskfile);
|
||||
@@ -576,6 +574,25 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
|
||||
int tmp_id;
|
||||
uint64_t tmp_rt, rss = 0, vsz = 0;
|
||||
|
||||
// flush the response buf (if any)
|
||||
if (wsgi_req->response_buffer) {
|
||||
// send the body only if transformations are successfull
|
||||
struct uwsgi_buffer *ub = wsgi_req->response_buffer;
|
||||
if (uwsgi_apply_transformations(wsgi_req) == 0) {
|
||||
// the response_buffer could be changed by translations
|
||||
ub = wsgi_req->response_buffer;
|
||||
// force true write (take flushing into account)
|
||||
wsgi_req->response_buffer = NULL;
|
||||
if (wsgi_req->response_size == 0) {
|
||||
uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
|
||||
}
|
||||
}
|
||||
else {
|
||||
wsgi_req->write_errors++;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub);
|
||||
}
|
||||
|
||||
// check if headers should be sent
|
||||
if (wsgi_req->headers) {
|
||||
if (!wsgi_req->headers_sent && !wsgi_req->headers_size && !wsgi_req->response_size) {
|
||||
@@ -599,7 +616,6 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = rss;
|
||||
}
|
||||
|
||||
|
||||
// close the connection with the client
|
||||
if (!wsgi_req->fd_closed) {
|
||||
// NOTE, if we close the socket before receiving eventually sent data, socket layer will send a RST
|
||||
@@ -1122,11 +1138,36 @@ void parse_sys_envs(char **envs) {
|
||||
}
|
||||
|
||||
// get the application id
|
||||
int uwsgi_get_app_id(char *app_name, int app_name_len, int modifier1) {
|
||||
int uwsgi_get_app_id(struct wsgi_request *wsgi_req, char *key, uint16_t key_len, int modifier1) {
|
||||
|
||||
int i;
|
||||
struct stat st;
|
||||
int found;
|
||||
int free_appname = 0;
|
||||
|
||||
char *app_name = key;
|
||||
uint16_t app_name_len = key_len;
|
||||
|
||||
if (!app_name && wsgi_req) {
|
||||
app_name = wsgi_req->appid;
|
||||
app_name_len = wsgi_req->appid_len;
|
||||
if (app_name_len == 0) {
|
||||
if (!uwsgi.ignore_script_name) {
|
||||
app_name = wsgi_req->script_name;
|
||||
app_name_len = wsgi_req->script_name_len;
|
||||
}
|
||||
|
||||
if (uwsgi.vhost) {
|
||||
app_name = uwsgi_concat3n(wsgi_req->host, wsgi_req->host_len, "|",1, wsgi_req->script_name, wsgi_req->script_name_len);
|
||||
app_name_len = wsgi_req->host_len + 1 + wsgi_req->script_name_len;
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("VirtualHost KEY=%.*s\n", wsgi_req->appid_len, wsgi_req->appid);
|
||||
#endif
|
||||
free_appname = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < uwsgi_apps_cnt; i++) {
|
||||
// reset check
|
||||
@@ -1158,14 +1199,19 @@ int uwsgi_get_app_id(char *app_name, int app_name_len, int modifier1) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (modifier1 == -1)
|
||||
if (modifier1 == -1) {
|
||||
if (free_appname) free(app_name);
|
||||
return i;
|
||||
if (modifier1 == uwsgi_apps[i].modifier1)
|
||||
}
|
||||
if (modifier1 == uwsgi_apps[i].modifier1) {
|
||||
if (free_appname) free(app_name);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!uwsgi.no_default_app) {
|
||||
if (free_appname) free(app_name);
|
||||
return uwsgi.default_app;
|
||||
}
|
||||
|
||||
@@ -1506,6 +1552,25 @@ int uwsgi_logic_opt_for_glob(char *key, char *value) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_for_times(char *key, char *value) {
|
||||
|
||||
int num = atoi(uwsgi.logic_opt_data);
|
||||
int i;
|
||||
char str_num[11];
|
||||
|
||||
for (i = 1; i <= num; i++) {
|
||||
int ret = uwsgi_num2str2(i, str_num);
|
||||
// security check
|
||||
if (ret < 0 || ret > 11) {
|
||||
exit(1);
|
||||
}
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", str_num), 0);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void add_exported_option(char *key, char *value, int configured) {
|
||||
|
||||
@@ -3035,14 +3100,17 @@ void http_url_decode(char *buf, uint16_t * len, char *dst) {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
we scan the table in reverse, as updated values are at the end
|
||||
*/
|
||||
char *uwsgi_get_var(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t * len) {
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
|
||||
if (!uwsgi_strncmp(key, keylen, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len)) {
|
||||
*len = wsgi_req->hvec[i + 1].iov_len;
|
||||
return wsgi_req->hvec[i + 1].iov_base;
|
||||
for (i = wsgi_req->var_cnt-1; i > 0; i -= 2) {
|
||||
if (!uwsgi_strncmp(key, keylen, wsgi_req->hvec[i-1].iov_base, wsgi_req->hvec[i-1].iov_len)) {
|
||||
*len = wsgi_req->hvec[i].iov_len;
|
||||
return wsgi_req->hvec[i].iov_base;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3195,10 +3263,9 @@ void uwsgi_write_pidfile(char *pidfile_name) {
|
||||
uwsgi_error_open(pidfile_name);
|
||||
exit(1);
|
||||
}
|
||||
if (fprintf(pidfile, "%d\n", (int) getpid()) < 0) {
|
||||
if (fprintf(pidfile, "%d\n", (int) getpid()) <= 0 || ferror(pidfile) || fclose(pidfile)) {
|
||||
uwsgi_log("could not write pidfile.\n");
|
||||
}
|
||||
fclose(pidfile);
|
||||
}
|
||||
|
||||
char *uwsgi_expand_path(char *dir, int dir_len, char *ptr) {
|
||||
@@ -3461,6 +3528,7 @@ int uwsgi_kvlist_parse(char *src, size_t len, char list_separator, char kv_separ
|
||||
escaped = 1;
|
||||
}
|
||||
else if (escaped) {
|
||||
*ptr++ = src[i];
|
||||
escaped = 0;
|
||||
}
|
||||
else {
|
||||
@@ -3809,3 +3877,33 @@ char *uwsgi_get_header(struct wsgi_request *wsgi_req, char *hh, uint16_t len, ui
|
||||
return value;
|
||||
|
||||
}
|
||||
|
||||
static char *uwsgi_hex_table[] = {
|
||||
"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F",
|
||||
"10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F",
|
||||
"20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F",
|
||||
"30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F",
|
||||
"40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F",
|
||||
"50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5A", "5B", "5C", "5D", "5E", "5F",
|
||||
"60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6A", "6B", "6C", "6D", "6E", "6F",
|
||||
"70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7A", "7B", "7C", "7D", "7E", "7F",
|
||||
"80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B", "8C", "8D", "8E", "8F",
|
||||
"90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F",
|
||||
"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF",
|
||||
"B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF",
|
||||
"C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF",
|
||||
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF",
|
||||
"E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF",
|
||||
"F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF",
|
||||
};
|
||||
|
||||
char *uwsgi_str_to_hex(char *src, size_t slen) {
|
||||
char *dst = uwsgi_malloc(slen*2);
|
||||
char *ptr = dst;
|
||||
size_t i;
|
||||
for(i=0;i<slen;i++) {
|
||||
memcpy(ptr, uwsgi_hex_table[ (int) src[i] ], 2);
|
||||
ptr+=2;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
+151
-42
@@ -24,6 +24,7 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
struct uwsgi_server uwsgi;
|
||||
pid_t masterpid;
|
||||
|
||||
#if defined(__APPLE__) && defined(UWSGI_AS_SHARED_LIBRARY)
|
||||
#include <crt_externs.h>
|
||||
@@ -70,8 +71,10 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"xmlconfig", required_argument, 'x', "load config from xml file", uwsgi_opt_load_xml, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"xml", required_argument, 'x', "load config from xml file", uwsgi_opt_load_xml, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#endif
|
||||
{"config", required_argument, 0, "load configuration using the pluggable system", uwsgi_opt_load_config, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"skip-zero", no_argument, 0, "skip check of file descriptor 0", uwsgi_opt_true, &uwsgi.skip_zero, 0},
|
||||
{"skip-atexit", no_argument, 0, "skip atexit hooks (ignored by the master)", uwsgi_opt_true, &uwsgi.skip_atexit, 0},
|
||||
|
||||
{"set", required_argument, 'S', "set a custom placeholder", uwsgi_opt_set_placeholder, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"get", required_argument, 0, "print the specified option value and exit", uwsgi_opt_add_string_list, &uwsgi.get_list, UWSGI_OPT_NO_INITIAL},
|
||||
@@ -79,7 +82,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
|
||||
{"for", required_argument, 0, "(opt logic) for cycle", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for, UWSGI_OPT_IMMEDIATE},
|
||||
{"for-glob", required_argument, 0, "(opt logic) for cycle (expand glob)", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for_glob, UWSGI_OPT_IMMEDIATE},
|
||||
{"for-times", required_argument, 0, "(opt logic) for cycle (expand the specified num to a list starting from 1)", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for_times, UWSGI_OPT_IMMEDIATE},
|
||||
{"endfor", optional_argument, 0, "(opt logic) end for cycle", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"end-for", optional_argument, 0, "(opt logic) end for cycle", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"if-opt", required_argument, 0, "(opt logic) check for option", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_opt, UWSGI_OPT_IMMEDIATE},
|
||||
{"if-not-opt", required_argument, 0, "(opt logic) check for option", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_not_opt, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -108,6 +113,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"if-directory", required_argument, 0, "(opt logic) check for directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_dir, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"endif", optional_argument, 0, "(opt logic) end if", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"end-if", optional_argument, 0, "(opt logic) end if", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"blacklist", required_argument, 0, "set options blacklist context", uwsgi_opt_set_str, &uwsgi.blacklist_context, UWSGI_OPT_IMMEDIATE},
|
||||
{"end-blacklist", no_argument, 0, "clear options blacklist context", uwsgi_opt_set_null, &uwsgi.blacklist_context, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -163,12 +169,14 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"single-interpreter", no_argument, 'i', "do not use multiple interpreters (where available)", uwsgi_opt_true, &uwsgi.single_interpreter, 0},
|
||||
{"need-app", no_argument, 0, "exit if no app can be loaded", uwsgi_opt_true, &uwsgi.need_app, 0},
|
||||
{"master", no_argument, 'M', "enable master process", uwsgi_opt_true, &uwsgi.master_process, 0},
|
||||
{"honour-stdin", no_argument, 0, "do not remap stdin to /dev/null", uwsgi_opt_true, &uwsgi.honour_stdin, 0},
|
||||
{"emperor", required_argument, 0, "run the Emperor", uwsgi_opt_add_string_list, &uwsgi.emperor, 0},
|
||||
{"emperor-procname", required_argument, 0, "set the Emperor process name", uwsgi_opt_set_str, &uwsgi.emperor_procname, 0},
|
||||
{"emperor-freq", required_argument, 0, "set the Emperor scan frequency (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.emperor_freq, 0},
|
||||
{"emperor-required-heartbeat", required_argument, 0, "set the Emperor tolerance about heartbeats", uwsgi_opt_set_int, &uwsgi.emperor_heartbeat, 0},
|
||||
{"emperor-pidfile", required_argument, 0, "write the Emperor pid in the specified file", uwsgi_opt_set_str, &uwsgi.emperor_pidfile, 0},
|
||||
{"emperor-tyrant", no_argument, 0, "put the Emperor in Tyrant mode", uwsgi_opt_true, &uwsgi.emperor_tyrant, 0},
|
||||
{"emperor-tyrant-nofollow", no_argument, 0, "do not follow symlinks when checking for uid/gid in Tyrant mode", uwsgi_opt_true, &uwsgi.emperor_tyrant_nofollow, 0},
|
||||
{"emperor-stats", required_argument, 0, "run the Emperor stats server", uwsgi_opt_set_str, &uwsgi.emperor_stats, 0},
|
||||
{"emperor-stats-server", required_argument, 0, "run the Emperor stats server", uwsgi_opt_set_str, &uwsgi.emperor_stats, 0},
|
||||
{"early-emperor", no_argument, 0, "spawn the emperor as soon as possibile", uwsgi_opt_true, &uwsgi.early_emperor, 0},
|
||||
@@ -181,6 +189,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"emperor-on-demand-directory", required_argument, 0, "enable on demand mode binding to the unix socket in the specified directory named like the vassal + .socket", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_directory, 0},
|
||||
{"emperor-on-demand-dir", required_argument, 0, "enable on demand mode binding to the unix socket in the specified directory named like the vassal + .socket", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_directory, 0},
|
||||
{"emperor-on-demand-exec", required_argument, 0, "use the output of the specified command as on demand socket name (the vassal name is passed as the only argument)", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_exec, 0},
|
||||
{"emperor-extra-extension", required_argument, 0, "allows the specified extension in the Emperor (vassal will be called with --config)", uwsgi_opt_add_string_list, &uwsgi.emperor_extra_extension, 0},
|
||||
{"emperor-extra-ext", required_argument, 0, "allows the specified extension in the Emperor (vassal will be called with --config)", uwsgi_opt_add_string_list, &uwsgi.emperor_extra_extension, 0},
|
||||
{"imperial-monitor-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0},
|
||||
{"imperial-monitors-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0},
|
||||
{"vassals-inherit", required_argument, 0, "add config templates to vassals config", uwsgi_opt_add_string_list, &uwsgi.vassals_templates, 0},
|
||||
@@ -208,6 +218,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"ftok", required_argument, 0, "set the ipcsem key via ftok() for avoiding duplicates", uwsgi_opt_set_str, &uwsgi.ftok, 0},
|
||||
{"sharedarea", required_argument, 'A', "create a raw shared memory area of specified pages", uwsgi_opt_set_int, &uwsgi.sharedareasize, 0},
|
||||
|
||||
{"safe-fd", no_argument, 0, "do not close the specified file descriptor", uwsgi_opt_safe_fd, NULL, 0},
|
||||
{"fd-safe", no_argument, 0, "do not close the specified file descriptor", uwsgi_opt_safe_fd, NULL, 0},
|
||||
|
||||
{"cache", required_argument, 0, "create a shared cache containing given elements", uwsgi_opt_set_64bit, &uwsgi.cache_max_items, 0},
|
||||
{"cache-blocksize", required_argument, 0, "set cache blocksize", uwsgi_opt_set_64bit, &uwsgi.cache_blocksize, 0},
|
||||
{"cache-store", required_argument, 0, "enable persistent cache to disk", uwsgi_opt_set_str, &uwsgi.cache_store, UWSGI_OPT_MASTER},
|
||||
@@ -218,8 +231,12 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"cache-udp-server", required_argument, 0, "bind the cache udp server (used only for set/update/delete) to the specified socket", uwsgi_opt_add_string_list, &uwsgi.cache_udp_server, UWSGI_OPT_MASTER},
|
||||
{"cache-udp-node", required_argument, 0, "send cache update/deletion to the specified cache udp server", uwsgi_opt_add_string_list, &uwsgi.cache_udp_node, UWSGI_OPT_MASTER},
|
||||
{"cache-sync", required_argument, 0, "copy the whole content of another uWSGI cache server on server startup", uwsgi_opt_set_str, &uwsgi.cache_sync, 0},
|
||||
{"cache-use-last-modified", no_argument, 0, "update last_modified_at timestamp on every cache item modification (default is disabled)", uwsgi_opt_true, &uwsgi.cache_use_last_modified, 0},
|
||||
|
||||
{"load-file-in-cache", required_argument, 0, "load a static file in the cache", uwsgi_opt_add_string_list, &uwsgi.load_file_in_cache, 0},
|
||||
#ifdef UWSGI_ZLIB
|
||||
{"load-file-in-cache-gzip", required_argument, 0, "load a static file in the cache with gzip compression", uwsgi_opt_add_string_list, &uwsgi.load_file_in_cache_gzip, 0},
|
||||
#endif
|
||||
|
||||
{"cache2", required_argument, 0, "create a new generation shared cache (keyval syntax)", uwsgi_opt_add_string_list, &uwsgi.cache2, 0},
|
||||
|
||||
@@ -261,6 +278,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"chroot", required_argument, 0, "chroot() to the specified directory", uwsgi_opt_set_str, &uwsgi.chroot, 0},
|
||||
{"uid", required_argument, 0, "setuid to the specified user/uid", uwsgi_opt_set_uid, NULL, 0},
|
||||
{"gid", required_argument, 0, "setgid to the specified group/gid", uwsgi_opt_set_gid, NULL, 0},
|
||||
{"immediate-uid", required_argument, 0, "setuid to the specified user/uid IMMEDIATELY", uwsgi_opt_set_immediate_uid, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"immediate-gid", required_argument, 0, "setgid to the specified group/gid IMMEDIATELY", uwsgi_opt_set_immediate_gid, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"no-initgroups", no_argument, 0, "disable additional groups set via initgroups()", uwsgi_opt_true, &uwsgi.no_initgroups, 0},
|
||||
#ifdef UWSGI_CAP
|
||||
{"cap", required_argument, 0, "set process capability", uwsgi_opt_set_cap, NULL, 0},
|
||||
@@ -285,20 +304,11 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"json", required_argument, 'j', "load config from json file", uwsgi_opt_load_json, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"js", required_argument, 'j', "load config from json file", uwsgi_opt_load_json, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#endif
|
||||
#ifdef UWSGI_SQLITE3
|
||||
{"sqlite3", required_argument, 0, "load config from sqlite3 db", uwsgi_opt_load_sqlite3, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"sqlite", required_argument, 0, "load config from sqlite3 db", uwsgi_opt_load_sqlite3, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#endif
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
{"zeromq", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "zmq", 0},
|
||||
{"zmq", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "zmq", 0},
|
||||
{"zeromq-socket", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "zmq", 0},
|
||||
{"zmq-socket", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "zmq", 0},
|
||||
#endif
|
||||
#ifdef UWSGI_LDAP
|
||||
{"ldap", required_argument, 0, "load configuration from ldap server", uwsgi_opt_load_ldap, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"ldap-schema", no_argument, 0, "dump uWSGI ldap schema", uwsgi_opt_ldap_dump, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"ldap-schema-ldif", no_argument, 0, "dump uWSGI ldap schema in ldif format", uwsgi_opt_ldap_dump_ldif, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#endif
|
||||
{"weight", required_argument, 0, "weight of the instance (used by clustering/lb/subscriptions)", uwsgi_opt_set_64bit, &uwsgi.weight, 0},
|
||||
{"auto-weight", required_argument, 0, "set weight of the instance (used by clustering/lb/subscriptions) automatically", uwsgi_opt_true, &uwsgi.auto_weight, 0},
|
||||
@@ -311,6 +321,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"socket-send-timeout", no_argument, 0, "set SO_SNDTIMEO", uwsgi_opt_set_int, &uwsgi.so_send_timeout, 0},
|
||||
{"so-write-timeout", no_argument, 0, "set SO_SNDTIMEO", uwsgi_opt_set_int, &uwsgi.so_send_timeout, 0},
|
||||
{"socket-write-timeout", no_argument, 0, "set SO_SNDTIMEO", uwsgi_opt_set_int, &uwsgi.so_send_timeout, 0},
|
||||
{"socket-sndbuf", required_argument, 0, "set SO_SNDBUF", uwsgi_opt_set_64bit, &uwsgi.so_sndbuf, 0},
|
||||
{"socket-rcvbuf", required_argument, 0, "set SO_RCVBUF", uwsgi_opt_set_64bit, &uwsgi.so_rcvbuf, 0},
|
||||
{"limit-as", required_argument, 0, "limit processes address space/vsz", uwsgi_opt_set_megabytes, &uwsgi.rl.rlim_max, 0},
|
||||
{"limit-nproc", required_argument, 0, "limit the number of spawnable processes", uwsgi_opt_set_int, &uwsgi.rl_nproc.rlim_max, 0},
|
||||
{"reload-on-as", required_argument, 0, "reload if address space is higher than specified megabytes", uwsgi_opt_set_megabytes, &uwsgi.reload_on_as, UWSGI_OPT_MEMORY},
|
||||
@@ -367,6 +379,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
{"legion", required_argument, 0, "became a member of a legion", uwsgi_opt_legion, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-mcast", required_argument, 0, "became a member of a legion (shortcut for multicast)", uwsgi_opt_legion_mcast, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-node", required_argument, 0, "add a node to a legion", uwsgi_opt_legion_node, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-freq", required_argument, 0, "set the frequency of legion packets", uwsgi_opt_set_int, &uwsgi.legion_freq, UWSGI_OPT_MASTER},
|
||||
{"legion-tolerance", required_argument, 0, "set the tolerance of legion subsystem", uwsgi_opt_set_int, &uwsgi.legion_tolerance, UWSGI_OPT_MASTER},
|
||||
@@ -375,9 +388,11 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"legion-unlord", required_argument, 0, "action to call on Lord dismiss", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-setup", required_argument, 0, "action to call on legion setup", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-death", required_argument, 0, "action to call on legion death (shutdown of the instance)", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-join", required_argument, 0, "action to call on legion join (first time quorum is reached)", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-node-joined", required_argument, 0, "action to call on new node joining legion", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-node-left", required_argument, 0, "action to call node leaving legion", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-quorum", required_argument, 0, "set the quorum of a legion", uwsgi_opt_legion_quorum, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-scroll", required_argument, 0, "set the scroll of a legion", uwsgi_opt_legion_scroll, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-scroll", required_argument, 0, "set the scroll of a legion", uwsgi_opt_legion_scroll, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-scroll-max-size", required_argument, 0, "set max size of legion scroll buffer", uwsgi_opt_set_16bit, &uwsgi.legion_scroll_max_size, 0},
|
||||
{"legion-scroll-list-max-size", required_argument, 0, "set max size of legion scroll list buffer", uwsgi_opt_set_64bit, &uwsgi.legion_scroll_list_max_size, 0},
|
||||
{"subscriptions-sign-check", required_argument, 0, "set digest algorithm and certificate directory for secured subscription system", uwsgi_opt_scd, NULL, UWSGI_OPT_MASTER},
|
||||
@@ -441,6 +456,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
#endif
|
||||
{"alarm", required_argument, 0, "create a new alarm, syntax: <alarm> <plugin:args>", uwsgi_opt_add_string_list, &uwsgi.alarm_list, UWSGI_OPT_MASTER},
|
||||
{"alarm-freq", required_argument, 0, "tune the anti-loop alam system (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.alarm_freq, 0},
|
||||
{"alarm-fd", required_argument, 0, "raise the specified alarm when an fd is read for read (by default it reads 1 byte, set 8 for eventfd)", uwsgi_opt_add_string_list, &uwsgi.alarm_fd_list, UWSGI_OPT_MASTER},
|
||||
#ifdef UWSGI_PCRE
|
||||
{"log-alarm", required_argument, 0, "raise the specified alarm when a log line matches the specified regexp, syntax: <alarm>[,alarm...] <regexp>", uwsgi_opt_add_string_list, &uwsgi.alarm_logs_list, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
{"alarm-log", required_argument, 0, "raise the specified alarm when a log line matches the specified regexp, syntax: <alarm>[,alarm...] <regexp>", uwsgi_opt_add_string_list, &uwsgi.alarm_logs_list, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
@@ -511,6 +527,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"route-label", required_argument, 0, "add a routing label (for use with goto)", uwsgi_opt_add_route, NULL, 0},
|
||||
{"route-if", required_argument, 0, "add a route based on condition", uwsgi_opt_add_route, "if", 0},
|
||||
{"route-if-not", required_argument, 0, "add a route based on condition (negate version)", uwsgi_opt_add_route, "if-not", 0},
|
||||
{"route-run", required_argument, 0, "always run the specified route action", uwsgi_opt_add_route, "run", 0},
|
||||
{"router-list", no_argument, 0, "list enabled routers", uwsgi_opt_true, &uwsgi.router_list, 0},
|
||||
{"routers-list", no_argument, 0, "list enabled routers", uwsgi_opt_true, &uwsgi.router_list, 0},
|
||||
#endif
|
||||
@@ -566,6 +583,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"static-gzip-ext", required_argument, 0, "check for a gzip version of all requested static files with the specified ext/suffix", uwsgi_opt_add_string_list, &uwsgi.static_gzip_ext, UWSGI_OPT_MIME},
|
||||
{"static-gzip-suffix", required_argument, 0, "check for a gzip version of all requested static files with the specified ext/suffix", uwsgi_opt_add_string_list, &uwsgi.static_gzip_ext, UWSGI_OPT_MIME},
|
||||
|
||||
{"honour-range", no_argument, 0, "enable support for the HTTP Range header", uwsgi_opt_true, &uwsgi.honour_range, 0},
|
||||
|
||||
{"offload-threads", required_argument, 0, "set the number of offload threads to spawn (per-worker, default 0)", uwsgi_opt_set_int, &uwsgi.offload_threads, 0},
|
||||
{"offload-thread", required_argument, 0, "set the number of offload threads to spawn (per-worker, default 0)", uwsgi_opt_set_int, &uwsgi.offload_threads, 0},
|
||||
|
||||
@@ -578,6 +597,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"env", required_argument, 0, "set environment variable", uwsgi_opt_set_env, NULL, 0},
|
||||
{"unenv", required_argument, 0, "unset environment variable", uwsgi_opt_unset_env, NULL, 0},
|
||||
{"vacuum", no_argument, 0, "try to remove all of the generated file/sockets", uwsgi_opt_true, &uwsgi.vacuum, 0},
|
||||
{"file-write", required_argument, 0, "write the specified content to the specified file (syntax: file=value) before privileges drop", uwsgi_opt_add_string_list, &uwsgi.file_write_list, 0},
|
||||
#ifdef __linux__
|
||||
{"cgroup", required_argument, 0, "put the processes in the specified cgroup", uwsgi_opt_add_string_list, &uwsgi.cgroup, 0},
|
||||
{"cgroup-opt", required_argument, 0, "set value in specified cgroup option", uwsgi_opt_add_string_list, &uwsgi.cgroup_opt, 0},
|
||||
@@ -597,6 +617,10 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"zerg-server", required_argument, 0, "enable the zerg server on the specified UNIX socket", uwsgi_opt_set_str, &uwsgi.zerg_server, UWSGI_OPT_MASTER},
|
||||
|
||||
{"cron", required_argument, 0, "add a cron task", uwsgi_opt_add_cron, NULL, UWSGI_OPT_MASTER},
|
||||
#ifdef UWSGI_SSL
|
||||
{"legion-cron", required_argument, 0, "add a cron task runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron, NULL, UWSGI_OPT_MASTER},
|
||||
{"cron-legion", required_argument, 0, "add a cron task runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron, NULL, UWSGI_OPT_MASTER},
|
||||
#endif
|
||||
{"loop", required_argument, 0, "select the uWSGI loop engine", uwsgi_opt_set_str, &uwsgi.loop, 0},
|
||||
{"loop-list", no_argument, 0, "list enabled loop engines", uwsgi_opt_true, &uwsgi.loop_list, 0},
|
||||
{"loops-list", no_argument, 0, "list enabled loop engines", uwsgi_opt_true, &uwsgi.loop_list, 0},
|
||||
@@ -604,6 +628,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"attach-daemon", required_argument, 0, "attach a command/daemon to the master process (the command has to not go in background)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
{"smart-attach-daemon", required_argument, 0, "attach a command/daemon to the master process managed by a pidfile (the command has to daemonize)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
{"smart-attach-daemon2", required_argument, 0, "attach a command/daemon to the master process managed by a pidfile (the command has to NOT daemonize)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
{"daemons-honour-stdin", no_argument, 0, "do not change the stdin of external daemons to /dev/null", uwsgi_opt_true, &uwsgi.daemons_honour_stdin, UWSGI_OPT_MASTER},
|
||||
{"plugins", required_argument, 0, "load uWSGI plugins", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"plugin", required_argument, 0, "load uWSGI plugins", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"plugins-dir", required_argument, 0, "add a directory to uWSGI plugin search path", uwsgi_opt_add_string_list, &uwsgi.plugins_dir, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -784,8 +809,12 @@ void config_magic_table_fill(char *filename, char **magic_table) {
|
||||
char *section = uwsgi_get_last_char(filename, ':');
|
||||
if (section) {
|
||||
*section = 0;
|
||||
if (section == filename) {
|
||||
goto reuse;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// we have a special case for symlinks
|
||||
if (uwsgi_is_link(filename)) {
|
||||
if (filename[0] != '/') {
|
||||
@@ -839,6 +868,7 @@ void config_magic_table_fill(char *filename, char **magic_table) {
|
||||
if (uwsgi_get_last_char(magic_table['s'], '.'))
|
||||
magic_table['n'] = uwsgi_concat2n(magic_table['s'], uwsgi_get_last_char(magic_table['s'], '.') - magic_table['s'], "", 0);
|
||||
|
||||
reuse:
|
||||
if (section) {
|
||||
magic_table['x'] = section+1;
|
||||
*section = ':';
|
||||
@@ -930,6 +960,10 @@ void gracefully_kill(int signum) {
|
||||
}
|
||||
|
||||
void end_me(int signum) {
|
||||
if (getpid() != masterpid && uwsgi.skip_atexit) {
|
||||
_exit(UWSGI_END_CODE);
|
||||
// never here
|
||||
}
|
||||
exit(UWSGI_END_CODE);
|
||||
}
|
||||
|
||||
@@ -1186,7 +1220,6 @@ void what_i_am_doing() {
|
||||
}
|
||||
|
||||
|
||||
pid_t masterpid;
|
||||
|
||||
int unconfigured_hook(struct wsgi_request *wsgi_req) {
|
||||
uwsgi_log("-- unavailable modifier requested: %d --\n", wsgi_req->uh->modifier1);
|
||||
@@ -1356,7 +1389,7 @@ void fixup_argv_and_environ(int argc, char **argv, char **environ) {
|
||||
env_count++;
|
||||
}
|
||||
|
||||
uwsgi.environ = uwsgi_malloc(sizeof(char *) * env_count);
|
||||
uwsgi.environ = uwsgi_malloc(sizeof(char *) * (env_count+1));
|
||||
for (i = 0; i < env_count; i++) {
|
||||
uwsgi.environ[i] = strdup(environ[i]);
|
||||
#ifdef UWSGI_DEBUG
|
||||
@@ -1364,6 +1397,7 @@ void fixup_argv_and_environ(int argc, char **argv, char **environ) {
|
||||
#endif
|
||||
environ[i] = uwsgi.environ[i];
|
||||
}
|
||||
uwsgi.environ[env_count] = NULL;
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("max space for custom process name = %d\n", uwsgi.max_procname);
|
||||
@@ -2033,6 +2067,8 @@ int uwsgi_start(void *v_argv) {
|
||||
}
|
||||
#endif
|
||||
|
||||
uwsgi_file_write_do(uwsgi.file_write_list);
|
||||
|
||||
if (!uwsgi.master_as_root && !uwsgi.chown_socket) {
|
||||
uwsgi_as_root();
|
||||
}
|
||||
@@ -2113,6 +2149,20 @@ int uwsgi_start(void *v_argv) {
|
||||
// automatically fix options
|
||||
sanitize_args();
|
||||
|
||||
|
||||
if (uwsgi.requested_max_fd) {
|
||||
uwsgi.rl.rlim_cur = uwsgi.requested_max_fd;
|
||||
uwsgi.rl.rlim_max = uwsgi.requested_max_fd;
|
||||
if (setrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
|
||||
uwsgi_error("setrlimit()");
|
||||
}
|
||||
}
|
||||
|
||||
if (!getrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
|
||||
uwsgi.max_fd = uwsgi.rl.rlim_cur;
|
||||
uwsgi_log_initial("detected max file descriptor number: %lu\n", (unsigned long) uwsgi.max_fd);
|
||||
}
|
||||
|
||||
// start the Emperor if needed
|
||||
if (!uwsgi.early_emperor && uwsgi.emperor) {
|
||||
uwsgi_emperor_start();
|
||||
@@ -2137,19 +2187,6 @@ int uwsgi_start(void *v_argv) {
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.requested_max_fd) {
|
||||
uwsgi.rl.rlim_cur = uwsgi.requested_max_fd;
|
||||
uwsgi.rl.rlim_max = uwsgi.requested_max_fd;
|
||||
if (setrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
|
||||
uwsgi_error("setrlimit()");
|
||||
}
|
||||
}
|
||||
|
||||
if (!getrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
|
||||
uwsgi.max_fd = uwsgi.rl.rlim_cur;
|
||||
uwsgi_log_initial("detected max file descriptor number: %lu\n", (unsigned long) uwsgi.max_fd);
|
||||
}
|
||||
|
||||
if (uwsgi.async > 1) {
|
||||
if ((unsigned long) uwsgi.max_fd < (unsigned long) uwsgi.async) {
|
||||
uwsgi_log("- your current max open files limit is %lu, this is lower than requested async cores !!! -\n", (unsigned long) uwsgi.max_fd);
|
||||
@@ -2336,7 +2373,8 @@ int uwsgi_start(void *v_argv) {
|
||||
!uwsgi.udp_socket &&
|
||||
!uwsgi.emperor &&
|
||||
!uwsgi.command_mode &&
|
||||
!uwsgi.daemons_cnt
|
||||
!uwsgi.daemons_cnt &&
|
||||
!uwsgi.crons
|
||||
#ifdef UWSGI_SSL
|
||||
&& !uwsgi.legions
|
||||
#endif
|
||||
@@ -2399,7 +2437,14 @@ unsafe:
|
||||
if (uwsgi.crons) {
|
||||
struct uwsgi_cron *ucron = uwsgi.crons;
|
||||
while (ucron) {
|
||||
uwsgi_log("command \"%s\" registered as uWSGI-cron task\n", ucron->command);
|
||||
#ifdef UWSGI_SSL
|
||||
if (ucron->legion) {
|
||||
uwsgi_log("[uwsgi-cron] command \"%s\" registered as cron task for legion \"%s\"\n", ucron->command, ucron->legion);
|
||||
ucron = ucron->next;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
uwsgi_log("[uwsgi-cron] command \"%s\" registered as cron task\n", ucron->command);
|
||||
ucron = ucron->next;
|
||||
}
|
||||
}
|
||||
@@ -2535,11 +2580,9 @@ next:
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_MINTERPRETERS
|
||||
if (!uwsgi.single_interpreter && uwsgi.numproc > 0) {
|
||||
uwsgi_log("*** uWSGI is running in multiple interpreter mode ***\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
// check for request plugins, and eventually print a warning
|
||||
int rp_available = 0;
|
||||
@@ -3178,6 +3221,67 @@ void uwsgi_opt_true(char *opt, char *value, void *key) {
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_opt_set_immediate_gid(char *opt, char *value, void *none) {
|
||||
gid_t gid = atoi(value);
|
||||
if (gid == 0) {
|
||||
struct group *ugroup = getgrnam(value);
|
||||
if (ugroup)
|
||||
gid = ugroup->gr_gid;
|
||||
}
|
||||
if (gid <= 0) {
|
||||
uwsgi_log("uwsgi_opt_set_immediate_gid(): invalid gid %d\n", (int) gid);
|
||||
exit(1);
|
||||
}
|
||||
if (setgid(gid)) {
|
||||
uwsgi_error("uwsgi_opt_set_immediate_gid()/setgid()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (setgroups(0, NULL)) {
|
||||
uwsgi_error("uwsgi_opt_set_immediate_gid()/setgroups()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
gid = getgid();
|
||||
if (!gid) {
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("immediate gid: %d\n", (int) gid);
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_set_immediate_uid(char *opt, char *value, void *none) {
|
||||
uid_t uid = atoi(value);
|
||||
if (uid == 0) {
|
||||
struct passwd *upasswd = getpwnam(value);
|
||||
if (upasswd)
|
||||
uid = upasswd->pw_uid;
|
||||
}
|
||||
if (uid <= 0) {
|
||||
uwsgi_log("uwsgi_opt_set_immediate_uid(): invalid uid %d\n", uid);
|
||||
exit(1);
|
||||
}
|
||||
if (setuid(uid)) {
|
||||
uwsgi_error("uwsgi_opt_set_immediate_uid()/setuid()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uid = getuid();
|
||||
if (!uid) {
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("immediate uid: %d\n", (int) uid);
|
||||
}
|
||||
|
||||
void uwsgi_opt_safe_fd(char *opt, char *value, void *foobar) {
|
||||
int fd = atoi(value);
|
||||
if (fd < 0) {
|
||||
uwsgi_log("invalid file descriptor: %d\n", fd);
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_add_safe_fd(fd);
|
||||
}
|
||||
|
||||
void uwsgi_opt_set_int(char *opt, char *value, void *key) {
|
||||
int *ptr = (int *) key;
|
||||
if (value) {
|
||||
@@ -3757,6 +3861,9 @@ void uwsgi_opt_load(char *opt, char *filename, void *none) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// fallback to pluggable system
|
||||
uwsgi_opt_load_config(opt, filename, none);
|
||||
}
|
||||
|
||||
void uwsgi_opt_logic(char *opt, char *arg, void *func) {
|
||||
@@ -3783,6 +3890,21 @@ void uwsgi_opt_load_ini(char *opt, char *filename, void *none) {
|
||||
uwsgi_ini_config(filename, uwsgi.magic_table);
|
||||
}
|
||||
|
||||
void uwsgi_opt_load_config(char *opt, char *filename, void *none) {
|
||||
struct uwsgi_configurator *uc = uwsgi.configurators;
|
||||
while(uc) {
|
||||
if (uwsgi_endswith(filename, uc->name)) {
|
||||
config_magic_table_fill(filename, uwsgi.magic_table);
|
||||
uc->func(filename, uwsgi.magic_table);
|
||||
return;
|
||||
}
|
||||
uc = uc->next;
|
||||
}
|
||||
|
||||
uwsgi_log("unable to load configuration from %s\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_XML
|
||||
void uwsgi_opt_load_xml(char *opt, char *filename, void *none) {
|
||||
config_magic_table_fill(filename, uwsgi.magic_table);
|
||||
@@ -3797,13 +3919,6 @@ void uwsgi_opt_load_yml(char *opt, char *filename, void *none) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_SQLITE3
|
||||
void uwsgi_opt_load_sqlite3(char *opt, char *filename, void *none) {
|
||||
config_magic_table_fill(filename, uwsgi.magic_table);
|
||||
uwsgi_sqlite3_config(filename, uwsgi.magic_table);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_JSON
|
||||
void uwsgi_opt_load_json(char *opt, char *filename, void *none) {
|
||||
config_magic_table_fill(filename, uwsgi.magic_table);
|
||||
@@ -3811,12 +3926,6 @@ void uwsgi_opt_load_json(char *opt, char *filename, void *none) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_LDAP
|
||||
void uwsgi_opt_load_ldap(char *opt, char *url, void *none) {
|
||||
uwsgi_ldap_config(url);
|
||||
}
|
||||
#endif
|
||||
|
||||
void uwsgi_opt_add_custom_option(char *opt, char *value, void *none) {
|
||||
|
||||
struct uwsgi_custom_option *uco = uwsgi.custom_options, *old_uco;
|
||||
|
||||
+51
-2
@@ -12,6 +12,36 @@ int uwsgi_response_add_content_length(struct wsgi_request *wsgi_req, uint64_t cl
|
||||
return uwsgi_response_add_header(wsgi_req, "Content-Length", 14, buf, ret);
|
||||
}
|
||||
|
||||
int uwsgi_response_add_expires(struct wsgi_request *wsgi_req, uint64_t t) {
|
||||
// 30+1
|
||||
char expires[31];
|
||||
int len = uwsgi_http_date((time_t) t, expires);
|
||||
if (!len) {
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
return uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, len);
|
||||
}
|
||||
|
||||
int uwsgi_response_add_content_range(struct wsgi_request *wsgi_req, uint64_t start, uint64_t end, uint64_t cl) {
|
||||
char buf[6+(sizeof(UMAX64_STR)*3)+4];
|
||||
if (end == 0) {
|
||||
end = cl-1;
|
||||
}
|
||||
int ret = snprintf(buf, 6+(sizeof(UMAX64_STR)*3)+4, "bytes %llu-%llu/%llu", (unsigned long long) start, (unsigned long long) end, (unsigned long long) cl);
|
||||
if (ret <= 0 || ret > (int) (6+(sizeof(UMAX64_STR)*3)+4)) {
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
return uwsgi_response_add_header(wsgi_req, "Content-Range", 13, buf, ret);
|
||||
}
|
||||
|
||||
int uwsgi_response_prepare_headers_int(struct wsgi_request *wsgi_req, int status) {
|
||||
char status_str[11];
|
||||
uwsgi_num2str2(status, status_str);
|
||||
return uwsgi_response_prepare_headers(wsgi_req, status_str, 3);
|
||||
}
|
||||
|
||||
// status could be NNN or NNN message
|
||||
int uwsgi_response_prepare_headers(struct wsgi_request *wsgi_req, char *status, uint16_t status_len) {
|
||||
|
||||
@@ -141,11 +171,13 @@ int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
// this is the function called by all request plugins to send chunks to the client
|
||||
int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
|
||||
if (wsgi_req->write_errors) return -1;
|
||||
|
||||
if (!wsgi_req->headers_sent) {
|
||||
// do not commit headers until a response_buffer is available (take in account flushing)
|
||||
if ((wsgi_req->flush || !wsgi_req->response_buffer) && !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;
|
||||
@@ -156,6 +188,15 @@ int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_
|
||||
sendbody:
|
||||
|
||||
if (len == 0) return UWSGI_OK;
|
||||
|
||||
if (wsgi_req->response_buffer) {
|
||||
if (uwsgi_buffer_append(wsgi_req->response_buffer, buf, len)) {
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
if (!wsgi_req->flush)
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
|
||||
@@ -191,7 +232,10 @@ int uwsgi_response_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t pos
|
||||
|
||||
if (fd == wsgi_req->sendfile_fd) can_close = 0;
|
||||
|
||||
if (wsgi_req->write_errors) return -1;
|
||||
if (wsgi_req->write_errors) {
|
||||
if (can_close) close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!wsgi_req->headers_sent) {
|
||||
int ret = uwsgi_response_write_headers_do(wsgi_req);
|
||||
@@ -212,6 +256,10 @@ sendfile:
|
||||
if (can_close) close(fd);
|
||||
return -1;
|
||||
}
|
||||
if (pos >= (size_t)st.st_size) {
|
||||
if (can_close) close(fd);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
len = st.st_size;
|
||||
}
|
||||
|
||||
@@ -263,6 +311,7 @@ sendfile:
|
||||
if (ret == 0) {
|
||||
uwsgi_log("uwsgi_response_sendfile_do() TIMEOUT !!!\n");
|
||||
wsgi_req->write_errors++;
|
||||
if (can_close) close(fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
+32
@@ -1,5 +1,37 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
static char gzheader[10] = { 0x1f, 0x8b, Z_DEFLATED, 0, 0, 0, 0, 0, 0, 3 };
|
||||
|
||||
struct uwsgi_buffer *uwsgi_gzip(char *buf, size_t len) {
|
||||
z_stream z;
|
||||
struct uwsgi_buffer *ub = NULL;
|
||||
uint32_t gzip_crc32 = 0;
|
||||
char *gzipped = NULL;
|
||||
char *gzipped0 = NULL;
|
||||
size_t dlen = 0;
|
||||
size_t dlen0 = 0;
|
||||
|
||||
uwsgi_crc32(&gzip_crc32, NULL, 0);
|
||||
if (uwsgi_deflate_init(&z, NULL, 0)) return NULL;
|
||||
uwsgi_crc32(&gzip_crc32, buf, len);
|
||||
|
||||
gzipped = uwsgi_deflate(&z, buf, len, &dlen);
|
||||
if (!gzipped) goto end;
|
||||
gzipped0 = uwsgi_deflate(&z, NULL, 0, &dlen0);
|
||||
if (!gzipped0) goto end;
|
||||
|
||||
ub = uwsgi_buffer_new(10 + dlen + dlen0 + 8);
|
||||
if (uwsgi_buffer_append(ub, gzheader, 10)) goto end;
|
||||
if (uwsgi_buffer_append(ub, gzipped, dlen)) goto end;
|
||||
if (uwsgi_buffer_append(ub, gzipped0, dlen0)) goto end;
|
||||
if (uwsgi_buffer_u32le(ub, gzip_crc32)) goto end;
|
||||
if (uwsgi_buffer_u32le(ub, len)) goto end;
|
||||
end:
|
||||
if (gzipped) free(gzipped);
|
||||
if (gzipped0) free(gzipped0);
|
||||
deflateEnd(&z);
|
||||
return ub;
|
||||
}
|
||||
|
||||
int uwsgi_deflate_init(z_stream *z, char *dict, size_t dict_len) {
|
||||
z->zalloc = Z_NULL;
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
config = {}
|
||||
|
||||
config['immediate-uid'] = 'roberto'
|
||||
config['immediate-gid'] = 'roberto'
|
||||
config['http-socket'] = ':9090'
|
||||
config['env'] = { 'FOO=bar', 'TEST=topogigio' }
|
||||
config['module'] = 'werkzeug.testapp:test_app'
|
||||
|
||||
return config
|
||||
@@ -0,0 +1,8 @@
|
||||
config = {}
|
||||
|
||||
config[1] = { ['http-socket']=':9090' }
|
||||
config[2] = { ['env']='FOO=bar' }
|
||||
config[3] = { ['env']='TEST=topogigio' }
|
||||
config[4] = { ['module']='werkzeug.testapp:test_app' }
|
||||
|
||||
return config
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +0,0 @@
|
||||
ngx_addon_name=ngx_http_uwsgi_module
|
||||
HTTP_MODULES="$HTTP_MODULES ngx_http_uwsgi_module"
|
||||
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_uwsgi_module.c"
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,16 +0,0 @@
|
||||
|
||||
uwsgi_param QUERY_STRING $query_string;
|
||||
uwsgi_param REQUEST_METHOD $request_method;
|
||||
uwsgi_param CONTENT_TYPE $content_type;
|
||||
uwsgi_param CONTENT_LENGTH $content_length;
|
||||
|
||||
uwsgi_param REQUEST_URI $request_uri;
|
||||
uwsgi_param PATH_INFO $document_uri;
|
||||
uwsgi_param DOCUMENT_ROOT $document_root;
|
||||
uwsgi_param SERVER_PROTOCOL $server_protocol;
|
||||
|
||||
uwsgi_param REMOTE_ADDR $remote_addr;
|
||||
uwsgi_param REMOTE_PORT $remote_port;
|
||||
uwsgi_param SERVER_ADDR $server_addr;
|
||||
uwsgi_param SERVER_PORT $server_port;
|
||||
uwsgi_param SERVER_NAME $server_name;
|
||||
Vendored
+9
-5
@@ -40,7 +40,7 @@ static void cache_simple_command(char *key, uint16_t keylen, char *val, uint16_t
|
||||
if (vallen > 0) {
|
||||
if (!uwsgi_strncmp(key, keylen, "key", 3)) {
|
||||
uint64_t vallen = 0;
|
||||
char *value = uwsgi_cache_magic_get(val, vallen, &vallen, NULL);
|
||||
char *value = uwsgi_cache_magic_get(val, vallen, &vallen, NULL, NULL);
|
||||
if (value) {
|
||||
uwsgi_response_write_body_do(wsgi_req, value, vallen);
|
||||
free(value);
|
||||
@@ -49,7 +49,7 @@ static void cache_simple_command(char *key, uint16_t keylen, char *val, uint16_t
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "get", 3)) {
|
||||
uint64_t vallen = 0;
|
||||
char *value = uwsgi_cache_magic_get(val, vallen, &vallen, NULL);
|
||||
char *value = uwsgi_cache_magic_get(val, vallen, &vallen, NULL, NULL);
|
||||
if (value) {
|
||||
uwsgi_response_write_body_do(wsgi_req, value, vallen);
|
||||
free(value);
|
||||
@@ -77,8 +77,9 @@ static void manage_magic_context(struct wsgi_request *wsgi_req, struct uwsgi_cac
|
||||
// cache get
|
||||
if (!uwsgi_strncmp(ucmc->cmd, ucmc->cmd_len, "get", 3)) {
|
||||
uint64_t vallen = 0;
|
||||
uint64_t expires = 0;
|
||||
uwsgi_rlock(uc->lock);
|
||||
char *value = uwsgi_cache_get2(uc, ucmc->key, ucmc->key_len, &vallen);
|
||||
char *value = uwsgi_cache_get3(uc, ucmc->key, ucmc->key_len, &vallen, &expires);
|
||||
if (!value) {
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
return;
|
||||
@@ -88,6 +89,9 @@ static void manage_magic_context(struct wsgi_request *wsgi_req, struct uwsgi_cac
|
||||
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 (expires) {
|
||||
if (uwsgi_buffer_append_keynum(ub, "expires", 7, expires)) goto error;
|
||||
}
|
||||
if (uwsgi_buffer_set_uh(ub, 111, 17)) goto error;
|
||||
if (uwsgi_buffer_append(ub, value, vallen)) goto error;
|
||||
// unlock !!!
|
||||
@@ -205,7 +209,7 @@ static int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
|
||||
case 0:
|
||||
// get
|
||||
if (wsgi_req->uh->pktsize > 0) {
|
||||
value = uwsgi_cache_magic_get(wsgi_req->buffer, wsgi_req->uh->pktsize, &vallen, NULL);
|
||||
value = uwsgi_cache_magic_get(wsgi_req->buffer, wsgi_req->uh->pktsize, &vallen, NULL, 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;}
|
||||
@@ -242,7 +246,7 @@ static int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
|
||||
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);
|
||||
value = uwsgi_cache_magic_get(wsgi_req->buffer, wsgi_req->uh->pktsize, &vallen, NULL, NULL);
|
||||
if (value) {
|
||||
wsgi_req->uh->pktsize = 0;
|
||||
wsgi_req->uh->modifier2 = 1;
|
||||
|
||||
+58
-5
@@ -35,6 +35,10 @@ struct uwsgi_carbon {
|
||||
char *hostname_dot_replacement;
|
||||
char *hostname;
|
||||
int resolve_hostname;
|
||||
char *idle_avg;
|
||||
int push_avg;
|
||||
int zero_avg;
|
||||
uint64_t last_requests;
|
||||
struct uwsgi_stats_pusher *pusher;
|
||||
} u_carbon;
|
||||
|
||||
@@ -50,6 +54,7 @@ static struct uwsgi_option carbon_options[] = {
|
||||
{"carbon-hostname-dots", required_argument, 0, "set char to use as a replacement for dots in hostname (dots are not replaced by default)", uwsgi_opt_set_str, &u_carbon.hostname_dot_replacement, 0},
|
||||
{"carbon-name-resolve", no_argument, 0, "allow using hostname as carbon server address (default disabled)", uwsgi_opt_true, &u_carbon.resolve_hostname, 0},
|
||||
{"carbon-resolve-names", no_argument, 0, "allow using hostname as carbon server address (default disabled)", uwsgi_opt_true, &u_carbon.resolve_hostname, 0},
|
||||
{"carbon-idle-avg", required_argument, 0, "average values source during idle period (no requests), can be \"last\", \"zero\", \"none\" (default is last)", uwsgi_opt_set_str, &u_carbon.idle_avg, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
@@ -74,12 +79,17 @@ static void carbon_post_init() {
|
||||
else if (!u_server->port) {
|
||||
u_server->port = uwsgi_str(p);
|
||||
}
|
||||
else break;
|
||||
else
|
||||
break;
|
||||
p = strtok(NULL, ":");
|
||||
}
|
||||
if (!u_server->hostname || !u_server->port) {
|
||||
uwsgi_log("[carbon] invalid carbon server address (%s)\n", usl->value);
|
||||
usl = usl->next;
|
||||
|
||||
if (u_server->hostname) free(u_server->hostname);
|
||||
if (u_server->port) free(u_server->port);
|
||||
free(u_server);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -116,6 +126,22 @@ static void carbon_post_init() {
|
||||
}
|
||||
}
|
||||
|
||||
u_carbon.push_avg = 1;
|
||||
u_carbon.zero_avg = 0;
|
||||
if (!u_carbon.idle_avg) {
|
||||
u_carbon.idle_avg = "last";
|
||||
}
|
||||
else if (!strcmp(u_carbon.idle_avg, "zero")) {
|
||||
u_carbon.zero_avg = 1;
|
||||
}
|
||||
else if (!strcmp(u_carbon.idle_avg, "none")) {
|
||||
u_carbon.push_avg = 0;
|
||||
}
|
||||
else if (strcmp(u_carbon.idle_avg, "last")) {
|
||||
uwsgi_log("[carbon] invalid value for carbon-idle-avg: \"%s\"\n", u_carbon.idle_avg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!u_carbon.last_busyness_values) {
|
||||
u_carbon.last_busyness_values = uwsgi_calloc(sizeof(unsigned long long) * uwsgi.numproc);
|
||||
}
|
||||
@@ -232,6 +258,8 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
unsigned long long worker_busyness = 0;
|
||||
unsigned long long total_harakiri = 0;
|
||||
|
||||
int do_avg_push;
|
||||
|
||||
wok = carbon_write(fd, "%s%s.%s.requests %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) uwsgi.workers[0].requests, (unsigned long long) now);
|
||||
if (!wok) goto clear;
|
||||
|
||||
@@ -282,8 +310,19 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
if (!wok) goto clear;
|
||||
}
|
||||
|
||||
wok = carbon_write(fd, "%s%s.%s.worker%d.avg_rt %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) avg_rt, (unsigned long long) now);
|
||||
if (!wok) goto clear;
|
||||
do_avg_push = 1;
|
||||
if (!u_carbon.last_requests || u_carbon.last_requests == uwsgi.workers[0].requests) {
|
||||
if (!u_carbon.push_avg) {
|
||||
do_avg_push = 0;
|
||||
}
|
||||
else if (u_carbon.zero_avg) {
|
||||
avg_rt = 0;
|
||||
}
|
||||
}
|
||||
if (do_avg_push) {
|
||||
wok = carbon_write(fd, "%s%s.%s.worker%d.avg_rt %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) avg_rt, (unsigned long long) now);
|
||||
if (!wok) goto clear;
|
||||
}
|
||||
|
||||
wok = carbon_write(fd, "%s%s.%s.worker%d.tx %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].tx, (unsigned long long) now);
|
||||
if (!wok) goto clear;
|
||||
@@ -304,8 +343,20 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
if (!wok) goto clear;
|
||||
}
|
||||
|
||||
wok = carbon_write(fd, "%s%s.%s.avg_rt %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) (active_workers ? total_avg_rt / active_workers : 0), (unsigned long long) now);
|
||||
if (!wok) goto clear;
|
||||
do_avg_push = 1;
|
||||
uint64_t c_total_avg_rt = (active_workers ? total_avg_rt / active_workers : 0);
|
||||
if (!u_carbon.last_requests || u_carbon.last_requests == uwsgi.workers[0].requests) {
|
||||
if (!u_carbon.push_avg) {
|
||||
do_avg_push = 0;
|
||||
}
|
||||
else if (u_carbon.zero_avg) {
|
||||
c_total_avg_rt = 0;
|
||||
}
|
||||
}
|
||||
if (do_avg_push) {
|
||||
wok = carbon_write(fd, "%s%s.%s.avg_rt %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) c_total_avg_rt, (unsigned long long) now);
|
||||
if (!wok) goto clear;
|
||||
}
|
||||
|
||||
wok = carbon_write(fd, "%s%s.%s.tx %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) total_tx, (unsigned long long) now);
|
||||
if (!wok) goto clear;
|
||||
@@ -333,6 +384,8 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
usl->healthy = 1;
|
||||
usl->errors = 0;
|
||||
|
||||
u_carbon.last_requests = uwsgi.workers[0].requests;
|
||||
|
||||
clear:
|
||||
close(fd);
|
||||
nxt:
|
||||
|
||||
+109
-43
@@ -18,7 +18,7 @@ struct uwsgi_cgi {
|
||||
int path_info;
|
||||
} uc ;
|
||||
|
||||
void uwsgi_opt_add_cgi(char *opt, char *value, void *foobar) {
|
||||
static void uwsgi_opt_add_cgi(char *opt, char *value, void *foobar) {
|
||||
|
||||
char *val = strchr(value, '=');
|
||||
if (!val) {
|
||||
@@ -30,7 +30,7 @@ void uwsgi_opt_add_cgi(char *opt, char *value, void *foobar) {
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_opt_add_cgi_maphelper(char *opt, char *value, void *foobar) {
|
||||
static void uwsgi_opt_add_cgi_maphelper(char *opt, char *value, void *foobar) {
|
||||
char *val = strchr(value, '=');
|
||||
if (!val) {
|
||||
uwsgi_log("invalid CGI helper syntax, must be ext=command\n");
|
||||
@@ -66,7 +66,7 @@ struct uwsgi_option uwsgi_cgi_options[] = {
|
||||
|
||||
};
|
||||
|
||||
void uwsgi_cgi_apps() {
|
||||
static void uwsgi_cgi_apps() {
|
||||
|
||||
struct uwsgi_dyn_dict *udd = uc.mountpoint;
|
||||
struct stat st;
|
||||
@@ -123,7 +123,7 @@ void uwsgi_cgi_apps() {
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_cgi_init(){
|
||||
static int uwsgi_cgi_init(){
|
||||
|
||||
void (*cgi_sym)(void);
|
||||
|
||||
@@ -161,7 +161,7 @@ int uwsgi_cgi_init(){
|
||||
|
||||
}
|
||||
|
||||
char *uwsgi_cgi_get_helper(char *filename) {
|
||||
static char *uwsgi_cgi_get_helper(char *filename) {
|
||||
|
||||
struct uwsgi_dyn_dict *helpers = uc.helpers;
|
||||
size_t len = strlen(filename);
|
||||
@@ -179,7 +179,7 @@ char *uwsgi_cgi_get_helper(char *filename) {
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
static int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
|
||||
size_t i;
|
||||
char *key = buf, *value = NULL;
|
||||
@@ -266,7 +266,7 @@ send_body:
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *uwsgi_cgi_get_docroot(char *path_info, uint16_t path_info_len, int *need_free, int *is_a_file, int *discard_base, char **script_name) {
|
||||
static char *uwsgi_cgi_get_docroot(char *path_info, uint16_t path_info_len, int *need_free, int *is_a_file, int *discard_base, char **script_name) {
|
||||
|
||||
struct uwsgi_dyn_dict *udd = uc.mountpoint, *choosen_udd = NULL;
|
||||
int best_found = 0;
|
||||
@@ -323,7 +323,7 @@ char *uwsgi_cgi_get_docroot(char *path_info, uint16_t path_info_len, int *need_f
|
||||
return path;
|
||||
}
|
||||
|
||||
int uwsgi_cgi_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot, size_t docroot_len, int discard_base, char **path_info) {
|
||||
static int uwsgi_cgi_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot, size_t docroot_len, int discard_base, char **path_info) {
|
||||
|
||||
// and now start walking...
|
||||
uint16_t i;
|
||||
@@ -380,18 +380,12 @@ int uwsgi_cgi_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
static int uwsgi_cgi_run(struct wsgi_request *, char *, size_t, char *, char *, char *, char *, int, int);
|
||||
|
||||
static int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
int i;
|
||||
pid_t cgi_pid;
|
||||
int waitpid_status;
|
||||
char **argv;
|
||||
int nargs = 0;
|
||||
char full_path[PATH_MAX];
|
||||
char tmp_path[PATH_MAX];
|
||||
int cgi_pipe[2];
|
||||
int post_pipe[2];
|
||||
ssize_t len;
|
||||
struct stat cgi_stat;
|
||||
int need_free = 0;
|
||||
int is_a_file = 0;
|
||||
@@ -399,7 +393,6 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
size_t docroot_len = 0;
|
||||
size_t full_path_len = 0;
|
||||
char *helper = NULL;
|
||||
char *command = NULL;
|
||||
char *path_info = NULL;
|
||||
char *script_name = NULL;
|
||||
|
||||
@@ -533,11 +526,8 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
if (is_a_file) {
|
||||
command = docroot;
|
||||
}
|
||||
else {
|
||||
command = full_path;
|
||||
// get the helper
|
||||
if (!is_a_file) {
|
||||
helper = uwsgi_cgi_get_helper(full_path);
|
||||
|
||||
if (helper == NULL) {
|
||||
@@ -551,28 +541,43 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
}
|
||||
|
||||
int ret = uwsgi_cgi_run(wsgi_req, docroot, docroot_len, full_path, helper, path_info, script_name, is_a_file, discard_base);
|
||||
if (need_free) free(docroot);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_cgi_run(struct wsgi_request *wsgi_req, char *docroot, size_t docroot_len, char *full_path, char *helper, char *path_info, char *script_name, int is_a_file, int discard_base) {
|
||||
|
||||
int cgi_pipe[2];
|
||||
int post_pipe[2];
|
||||
int nargs = 0;
|
||||
int waitpid_status;
|
||||
ssize_t len;
|
||||
int i;
|
||||
char **argv;
|
||||
|
||||
char *command = full_path;
|
||||
|
||||
if (is_a_file) {
|
||||
command = docroot;
|
||||
}
|
||||
|
||||
if (pipe(cgi_pipe)) {
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
uwsgi_error("pipe()");
|
||||
uwsgi_error("uwsgi_cgi_run()/pipe()");
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
if (pipe(post_pipe)) {
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
close(cgi_pipe[0]);
|
||||
close(cgi_pipe[1]);
|
||||
uwsgi_error("pipe()");
|
||||
uwsgi_error("uwsgi_cgi_run()/pipe()");
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
cgi_pid = fork();
|
||||
pid_t cgi_pid = fork();
|
||||
|
||||
if (cgi_pid < 0) {
|
||||
uwsgi_error("fork()");
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
uwsgi_error("uwsgi_cgi_run()/fork()");
|
||||
close(cgi_pipe[0]);
|
||||
close(cgi_pipe[1]);
|
||||
close(post_pipe[0]);
|
||||
@@ -582,9 +587,6 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (cgi_pid > 0) {
|
||||
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
|
||||
close(cgi_pipe[1]);
|
||||
close(post_pipe[0]);
|
||||
|
||||
@@ -795,7 +797,7 @@ clear2:
|
||||
}
|
||||
*base = '/';
|
||||
}
|
||||
else {
|
||||
else if (docroot_len > 0) {
|
||||
if (chdir(docroot)) {
|
||||
uwsgi_error("chdir()");
|
||||
}
|
||||
@@ -837,9 +839,8 @@ clear2:
|
||||
escape_shell_arg(arg_copy, arg_copy_len, argv[i]);
|
||||
i++;
|
||||
p = strtok(NULL, "+");
|
||||
}
|
||||
}
|
||||
else {
|
||||
}
|
||||
free(qs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -864,7 +865,7 @@ clear2:
|
||||
}
|
||||
|
||||
if (execvp(argv[0], argv)) {
|
||||
uwsgi_error("execvp()");
|
||||
uwsgi_error("uwsgi_cgi_run()/execvp()");
|
||||
}
|
||||
|
||||
// never here
|
||||
@@ -872,11 +873,73 @@ clear2:
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_cgi_after_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
static void uwsgi_cgi_after_request(struct wsgi_request *wsgi_req) {
|
||||
log_request(wsgi_req);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
static int uwsgi_routing_func_cgi(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
|
||||
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
struct uwsgi_buffer *ub_command = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
||||
if (!ub_command) return UWSGI_ROUTE_BREAK;
|
||||
struct uwsgi_buffer *ub_helper = NULL;
|
||||
if (ur->data2_len) {
|
||||
ub_helper = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data2, ur->data2_len);
|
||||
if (!ub_helper) {
|
||||
uwsgi_buffer_destroy(ub_command);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!uwsgi_is_file(ub_command->buf)) {
|
||||
uwsgi_404(wsgi_req);
|
||||
uwsgi_buffer_destroy(ub_command);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
if (access(ub_command->buf, X_OK)) {
|
||||
uwsgi_403(wsgi_req);
|
||||
uwsgi_buffer_destroy(ub_command);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
}
|
||||
// we need a NULL suffix-ed copy of the docroot
|
||||
char *docroot = uwsgi_concat2n(wsgi_req->document_root, wsgi_req->document_root_len, "", 0);
|
||||
uwsgi_cgi_run(wsgi_req, wsgi_req->document_root, wsgi_req->document_root_len, ub_command->buf, ub_helper ? ub_helper->buf : NULL, NULL, NULL, 0, 0 );
|
||||
free(docroot);
|
||||
uwsgi_buffer_destroy(ub_command);
|
||||
if (ub_helper) uwsgi_buffer_destroy(ub_helper);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
static int uwsgi_router_cgi_helper(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_cgi;
|
||||
char *space = strchr(args, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid cgihelper syntax, must be \"cgihelper:helper command\"\n");
|
||||
return -1;
|
||||
}
|
||||
*space = 0;
|
||||
ur->data = space+1;
|
||||
ur->data_len = strlen(space+1);
|
||||
ur->data2 = args;
|
||||
ur->data2_len = strlen(args);
|
||||
return 0;
|
||||
}
|
||||
static int uwsgi_router_cgi(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_cgi;
|
||||
ur->data = args;
|
||||
ur->data_len = strlen(args);
|
||||
return 0;
|
||||
}
|
||||
static void uwsgi_cgi_register_router() {
|
||||
uwsgi_register_router("cgi", uwsgi_router_cgi);
|
||||
uwsgi_register_router("cgihelper", uwsgi_router_cgi_helper);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct uwsgi_plugin cgi_plugin = {
|
||||
|
||||
@@ -887,5 +950,8 @@ struct uwsgi_plugin cgi_plugin = {
|
||||
.options = uwsgi_cgi_options,
|
||||
.request = uwsgi_cgi_request,
|
||||
.after_request = uwsgi_cgi_after_request,
|
||||
#ifdef UWSGI_ROUTING
|
||||
.on_load = uwsgi_cgi_register_router,
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
@@ -701,7 +701,8 @@ void uwsgi_corerouter_loop(int id, void *data) {
|
||||
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);
|
||||
uwsgi_log("!!! unable to find cache \"%s\" !!!\n", ucr->use_cache);
|
||||
exit(1);
|
||||
}
|
||||
ucr->mapper = uwsgi_cr_map_use_cache;
|
||||
}
|
||||
@@ -899,7 +900,7 @@ int uwsgi_corerouter_init(struct uwsgi_corerouter *ucr) {
|
||||
|
||||
if (ucr->has_sockets) {
|
||||
|
||||
if (ucr->use_cache && !uwsgi.cache_max_items) {
|
||||
if (ucr->use_cache && !uwsgi.caches) {
|
||||
uwsgi_log("you need to create a uwsgi cache to use the %s (add --cache <n>)\n", ucr->name);
|
||||
exit(1);
|
||||
}
|
||||
@@ -945,7 +946,7 @@ void corerouter_send_stats(struct uwsgi_corerouter *ucr) {
|
||||
|
||||
int client_fd = accept(ucr->cr_stats_server, (struct sockaddr *) &client_src, &client_src_len);
|
||||
if (client_fd < 0) {
|
||||
uwsgi_error("accept()");
|
||||
uwsgi_error("corerouter_send_stats()/accept()");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ void uwsgi_corerouter_manage_subscription(struct uwsgi_corerouter *ucr, int id,
|
||||
continue;
|
||||
if (!strcmp(ushared->gateways[i].name, ucr->name)) {
|
||||
if (send(ushared->gateways[i].internal_subscription_pipe[0], bbuf, len, 0) != len) {
|
||||
uwsgi_error("send()");
|
||||
uwsgi_error("uwsgi_corerouter_manage_subscription()/send()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ end:
|
||||
}
|
||||
|
||||
XS(XS_coroae_sighandler) {
|
||||
int sigfd = (int) XSANY.any_ptr;
|
||||
int sigfd = (long) XSANY.any_ptr;
|
||||
uwsgi_receive_signal(sigfd, "worker", uwsgi.mywid);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
@@ -13,8 +13,9 @@ class FakeClass {
|
||||
|
||||
void FakeClass::hello_world(struct wsgi_request *wsgi_req) {
|
||||
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, (char *) "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n", 44);
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, foobar, foobar_len);
|
||||
uwsgi_response_prepare_headers(wsgi_req, (char *)"200 OK", 6);
|
||||
uwsgi_response_add_content_type(wsgi_req, (char *)"text/html", 9);
|
||||
uwsgi_response_write_body_do(wsgi_req, foobar, foobar_len);
|
||||
}
|
||||
|
||||
extern "C" int uwsgi_cplusplus_init(){
|
||||
@@ -27,7 +28,7 @@ extern "C" int uwsgi_cplusplus_request(struct wsgi_request *wsgi_req) {
|
||||
FakeClass *fc;
|
||||
|
||||
// empty request ?
|
||||
if (!wsgi_req->uh.pktsize) {
|
||||
if (!wsgi_req->uh->pktsize) {
|
||||
uwsgi_log( "Invalid request. skip.\n");
|
||||
goto clear;
|
||||
}
|
||||
@@ -55,6 +56,7 @@ clear:
|
||||
|
||||
|
||||
extern "C" void uwsgi_cplusplus_after_request(struct wsgi_request *wsgi_req) {
|
||||
// call log_request(wsgi_req) if you want a standard logline
|
||||
uwsgi_log("logging c++ request\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
|
||||
int uwsgi_cplusplus_init(void);
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
#include <uwsgi.h>
|
||||
#include <curl/curl.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
static void curl_cron_func(struct uwsgi_cron *uc, time_t now) {
|
||||
CURL *curl = curl_easy_init();
|
||||
// ARGH !!!
|
||||
if (!curl) return;
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, uc->command);
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
// use 1 minute as the cron resolution
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60);
|
||||
uwsgi_log("[uwsgi-curl-cron] requesting %s\n", uc->command);
|
||||
CURLcode res = curl_easy_perform(curl);
|
||||
if (res != CURLE_OK) {
|
||||
uwsgi_log("[uwsgi-curl-cron] curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
|
||||
static void uwsgi_opt_add_cron_curl(char *opt, char *value, void *foobar) {
|
||||
struct uwsgi_cron *uc = uwsgi_cron_add(value);
|
||||
uc->func = curl_cron_func;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
static void uwsgi_opt_add_legion_cron_curl(char *opt, char *value, void *foobar) {
|
||||
char *space = strchr(value, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid %s syntax, must be prefixed with a legion name\n", opt);
|
||||
exit(1);
|
||||
}
|
||||
char *legion = uwsgi_concat2n(value, space-value, "", 0);
|
||||
struct uwsgi_cron *uc = uwsgi_cron_add(space+1);
|
||||
uc->legion = legion;
|
||||
uc->func = curl_cron_func;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct uwsgi_option curl_cron_options[] = {
|
||||
{"curl-cron", required_argument, 0, "add a cron task invoking the specified url via CURL", uwsgi_opt_add_cron_curl, NULL, UWSGI_OPT_MASTER},
|
||||
{"cron-curl", required_argument, 0, "add a cron task invoking the specified url via CURL", uwsgi_opt_add_cron_curl, NULL, UWSGI_OPT_MASTER},
|
||||
#ifdef UWSGI_SSL
|
||||
{"legion-curl-cron", required_argument, 0, "add a cron task invoking the specified url via CURL runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron_curl, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-cron-curl", required_argument, 0, "add a cron task invoking the specified url via CURL runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron_curl, NULL, UWSGI_OPT_MASTER},
|
||||
{"curl-cron-legion", required_argument, 0, "add a cron task invoking the specified url via CURL runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron_curl, NULL, UWSGI_OPT_MASTER},
|
||||
{"cron-curl-legion", required_argument, 0, "add a cron task invoking the specified url via CURL runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron_curl, NULL, UWSGI_OPT_MASTER},
|
||||
#endif
|
||||
{ 0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
struct uwsgi_plugin curl_cron_plugin = {
|
||||
.name = "curl_cron",
|
||||
.options = curl_cron_options,
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='curl_cron'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lcurl']
|
||||
GCC_LIST = ['curl_cron']
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_rack ur;
|
||||
extern struct uwsgi_plugin rack_plugin;
|
||||
|
||||
struct ufib {
|
||||
int enabled;
|
||||
@@ -45,7 +46,7 @@ static void fiber_schedule_to_req() {
|
||||
int error = 0;
|
||||
rb_protect(rb_fiber_schedule_to_req, 0, &error);
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
rack_plugin.exception_log(NULL);
|
||||
rb_gc_unregister_address(&ufiber.fib[id]);
|
||||
uwsgi.wsgi_req->async_status = UWSGI_OK;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
#include <GeoIP.h>
|
||||
#include <GeoIPCity.h>
|
||||
|
||||
struct uwsgi_geoip {
|
||||
char *country_db;
|
||||
char *city_db;
|
||||
GeoIP *country;
|
||||
GeoIP *city;
|
||||
|
||||
} ugeoip;
|
||||
|
||||
struct uwsgi_option uwsgi_geoip_options[] = {
|
||||
{"geoip-country", required_argument, 0, "load the specified geoip country database", uwsgi_opt_set_str, &ugeoip.country_db, 0},
|
||||
{"geoip-city", required_argument, 0, "load the specified geoip city database", uwsgi_opt_set_str, &ugeoip.city_db, 0},
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static int uwsgi_geoip_init() {
|
||||
if (ugeoip.country_db) {
|
||||
ugeoip.country = GeoIP_open(ugeoip.country_db, GEOIP_MEMORY_CACHE);
|
||||
if (!ugeoip.country) {
|
||||
uwsgi_log("unable to open GeoIP country database: %s\n", ugeoip.country_db);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (ugeoip.city_db) {
|
||||
ugeoip.city = GeoIP_open(ugeoip.city_db, GEOIP_MEMORY_CACHE);
|
||||
if (!ugeoip.city) {
|
||||
uwsgi_log("unable to open GeoIP city database: %s\n", ugeoip.city_db);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *uwsgi_route_var_geoip(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
uint32_t ip;
|
||||
char ip_str[16];
|
||||
// should be enough for geo coords
|
||||
char lonlat[64];
|
||||
memset(ip_str, 0, 16);
|
||||
memcpy(ip_str, wsgi_req->remote_addr, wsgi_req->remote_addr_len);
|
||||
if (inet_pton(AF_INET, ip_str, &ip) <= 0) {
|
||||
return NULL;
|
||||
}
|
||||
ip = htonl(ip);
|
||||
char *value = NULL;
|
||||
// always prefer the city database;
|
||||
GeoIP *g = ugeoip.city;
|
||||
if (!g) {
|
||||
g = ugeoip.country;
|
||||
if (g) {
|
||||
if (!uwsgi_strncmp(key, keylen, "country_code", 12)) {
|
||||
value = (char *) GeoIP_country_code_by_ipnum(g, ip);
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "country_code3", 13)) {
|
||||
value = (char *) GeoIP_country_code3_by_ipnum(g, ip);
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "country_name", 12)) {
|
||||
value = (char *) GeoIP_country_name_by_ipnum(g, ip);
|
||||
}
|
||||
|
||||
if (value) {
|
||||
*vallen = strlen(value);
|
||||
return uwsgi_str(value);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GeoIPRecord *gr = GeoIP_record_by_ipnum(g, ip);
|
||||
if (!gr) return NULL;
|
||||
|
||||
// ok let's generate the output
|
||||
if (!uwsgi_strncmp(key, keylen, "continent", 9)) {
|
||||
value = gr->continent_code;
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "country_code", 12)) {
|
||||
value = gr->country_code;
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "country_code3", 13)) {
|
||||
value = gr->country_code3;
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "country_name", 12)) {
|
||||
value = gr->country_name;
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "region", 6)) {
|
||||
value = gr->region;
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "region_name", 11)) {
|
||||
value = (char *) GeoIP_region_name_by_code(gr->country_code, gr->region);
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "city", 4)) {
|
||||
value = gr->city;
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "postal_code", 11)) {
|
||||
value = gr->postal_code;
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "latitude", 8) || !uwsgi_strncmp(key, keylen, "lat", 3)) {
|
||||
snprintf(lonlat, 64, "%f", gr->latitude);
|
||||
value = lonlat;
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "longitude", 9) || !uwsgi_strncmp(key, keylen, "lon", 3)) {
|
||||
snprintf(lonlat, 64, "%f", gr->longitude);
|
||||
value = lonlat;
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "dma", 3)) {
|
||||
snprintf(lonlat, 64, "%d", gr->dma_code);
|
||||
value = lonlat;
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "area", 4)) {
|
||||
snprintf(lonlat, 64, "%d", gr->area_code);
|
||||
value = lonlat;
|
||||
}
|
||||
|
||||
|
||||
if (value) {
|
||||
*vallen = strlen(value);
|
||||
char *ret = uwsgi_str(value);
|
||||
GeoIPRecord_delete(gr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
GeoIPRecord_delete(gr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void register_route_vars_geoip() {
|
||||
struct uwsgi_route_var *urv = uwsgi_register_route_var("geoip", uwsgi_route_var_geoip);
|
||||
urv->need_free = 1;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin geoip_plugin = {
|
||||
.name = "geoip",
|
||||
.options = uwsgi_geoip_options,
|
||||
.init = uwsgi_geoip_init,
|
||||
.on_load = register_route_vars_geoip,
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
NAME='geoip'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lGeoIP']
|
||||
|
||||
GCC_LIST = ['geoip']
|
||||
|
||||
@@ -150,7 +150,7 @@ func CacheGet(key string, cache string) []byte {
|
||||
|
||||
var p []byte
|
||||
|
||||
c_value := C.uwsgi_cache_magic_get(k, C.uint16_t(kl), &vl, c)
|
||||
c_value := C.uwsgi_cache_magic_get(k, C.uint16_t(kl), &vl, (*C.uint64_t)(nil), c)
|
||||
|
||||
if c_value != nil {
|
||||
p = C.GoBytes((unsafe.Pointer)(c_value), C.int(vl))
|
||||
|
||||
@@ -0,0 +1,281 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
#include <client/dbclient.h>
|
||||
#include <client/gridfs.h>
|
||||
|
||||
struct uwsgi_gridfs_mountpoint {
|
||||
char *mountpoint;
|
||||
uint16_t mountpoint_len;
|
||||
char *server;
|
||||
char *db;
|
||||
char *timeout_str;
|
||||
int timeout;
|
||||
char *no_mime;
|
||||
char *orig_filename;
|
||||
char *md5;
|
||||
char *etag;
|
||||
char *prefix;
|
||||
char *itemname;
|
||||
uint16_t itemname_len;
|
||||
char *skip_slash;
|
||||
uint16_t prefix_len;
|
||||
char *username;
|
||||
char *password;
|
||||
};
|
||||
|
||||
struct uwsgi_gridfs {
|
||||
int debug;
|
||||
struct uwsgi_string_list *mountpoints;
|
||||
} ugridfs;
|
||||
|
||||
struct uwsgi_option uwsgi_gridfs_options[] = {
|
||||
{(char *)"gridfs-mount", required_argument, 0, (char *)"mount a gridfs db on the specified mountpoint", uwsgi_opt_add_string_list, &ugridfs.mountpoints, UWSGI_OPT_MIME},
|
||||
{(char *)"gridfs-debug", no_argument, 0, (char *)"report gridfs mountpoint and itemname for each request (debug)", uwsgi_opt_true, &ugridfs.debug, UWSGI_OPT_MIME},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_plugin gridfs_plugin;
|
||||
|
||||
static void uwsgi_gridfs_do(struct wsgi_request *wsgi_req, struct uwsgi_gridfs_mountpoint *ugm, char *itemname, int need_free) {
|
||||
|
||||
try {
|
||||
mongo::scoped_ptr<mongo::ScopedDbConnection> conn( mongo::ScopedDbConnection::getScopedDbConnection(ugm->server, ugm->timeout) );
|
||||
try {
|
||||
if (ugm->username && ugm->password) {
|
||||
std::string errmsg;
|
||||
if ((*conn).conn().auth(ugm->db, ugm->username, ugm->password, errmsg)) {
|
||||
uwsgi_log("[uwsgi-gridfs]: %s\n", errmsg.c_str());
|
||||
(*conn).done();
|
||||
uwsgi_403(wsgi_req);
|
||||
return;
|
||||
}
|
||||
}
|
||||
mongo::GridFS gridfs((*conn).conn(), ugm->db);
|
||||
mongo::GridFile gfile = gridfs.findFile(itemname);
|
||||
if (need_free) {
|
||||
free(itemname);
|
||||
itemname = NULL;
|
||||
}
|
||||
if (!gfile.exists()) {
|
||||
(*conn).done();
|
||||
uwsgi_404(wsgi_req);
|
||||
return;
|
||||
}
|
||||
uwsgi_response_prepare_headers(wsgi_req, (char *)"200 OK", 6);
|
||||
// first get the content_type (if possibile)
|
||||
std::string filename = gfile.getFilename();
|
||||
if (!ugm->no_mime) {
|
||||
size_t mime_type_len = 0;
|
||||
char *mime_type = uwsgi_get_mime_type((char *)filename.c_str(), filename.length(), &mime_type_len);
|
||||
if (mime_type) {
|
||||
uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_len);
|
||||
}
|
||||
}
|
||||
if (ugm->orig_filename) {
|
||||
char *filename_header = uwsgi_concat3((char *)"inline; filename=\"", (char *)filename.c_str(), (char *)"\"");
|
||||
uwsgi_response_add_header(wsgi_req, (char *)"Content-Disposition", 19, filename_header, 19 + filename.length());
|
||||
free(filename_header);
|
||||
}
|
||||
uwsgi_response_add_content_length(wsgi_req, gfile.getContentLength());
|
||||
|
||||
if (ugm->etag) {
|
||||
std::string g_md5 = gfile.getMD5();
|
||||
if (!g_md5.empty()) {
|
||||
char *etag = uwsgi_concat3((char *)"\"", (char *)g_md5.c_str(), (char *)"\"");
|
||||
uwsgi_response_add_header(wsgi_req, (char *)"ETag", 4, etag, 2+g_md5.length());
|
||||
free(etag);
|
||||
}
|
||||
}
|
||||
|
||||
if (ugm->md5) {
|
||||
std::string g_md5 = gfile.getMD5();
|
||||
size_t base64_len = 0;
|
||||
char *base64 = uwsgi_base64_encode((char *)g_md5.c_str(), g_md5.length(), &base64_len);
|
||||
uwsgi_response_add_header(wsgi_req, (char *) "Content-MD5", 11, base64, base64_len);
|
||||
free(base64);
|
||||
}
|
||||
|
||||
if (uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, (char *)"HEAD", 4)) {
|
||||
int nc = gfile.getNumChunks();
|
||||
int i;
|
||||
for(i=0;i<nc;i++) {
|
||||
mongo::GridFSChunk gchunk = gfile.getChunk(i);
|
||||
int chunk_len = 0;
|
||||
const char *chunk = gchunk.data(chunk_len);
|
||||
uwsgi_response_write_body_do(wsgi_req, (char *) chunk, chunk_len);
|
||||
}
|
||||
}
|
||||
(*conn).done();
|
||||
}
|
||||
catch ( mongo::DBException &e ) {
|
||||
uwsgi_log("[uwsgi-gridfs]: %s\n", e.what());
|
||||
(*conn).done();
|
||||
if (need_free && itemname) {
|
||||
free(itemname);
|
||||
itemname = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( mongo::DBException &e ) {
|
||||
uwsgi_log("[uwsgi-gridfs]: %s\n", e.what());
|
||||
if (need_free && itemname) {
|
||||
free(itemname);
|
||||
itemname = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct uwsgi_gridfs_mountpoint *uwsgi_gridfs_add_mountpoint(char *arg, size_t arg_len) {
|
||||
struct uwsgi_gridfs_mountpoint *ugm = (struct uwsgi_gridfs_mountpoint *) uwsgi_calloc(sizeof(struct uwsgi_gridfs_mountpoint));
|
||||
if (uwsgi_kvlist_parse(arg, arg_len, ',', '=',
|
||||
"mountpoint", &ugm->mountpoint,
|
||||
"server", &ugm->server,
|
||||
"db", &ugm->db,
|
||||
"prefix", &ugm->prefix,
|
||||
"no_mime", &ugm->no_mime,
|
||||
"timeout", &ugm->timeout_str,
|
||||
"orig_filename", &ugm->orig_filename,
|
||||
"skip_slash", &ugm->skip_slash,
|
||||
"md5", &ugm->md5,
|
||||
"etag", &ugm->etag,
|
||||
"itemname", &ugm->itemname,
|
||||
"item", &ugm->itemname,
|
||||
"username", &ugm->username,
|
||||
"password", &ugm->password,
|
||||
NULL)) {
|
||||
uwsgi_log("invalid gridfs mountpoint syntax\n");
|
||||
free(ugm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!ugm->db) {
|
||||
uwsgi_log("you need to specify a \"db\" name for gridfs\n");
|
||||
free(ugm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!ugm->mountpoint) {
|
||||
ugm->mountpoint = (char *)"";
|
||||
}
|
||||
ugm->mountpoint_len = strlen(ugm->mountpoint);
|
||||
|
||||
if (!ugm->server) {
|
||||
ugm->server = (char *)"127.0.0.1:27017";
|
||||
}
|
||||
|
||||
if (ugm->timeout_str) {
|
||||
ugm->timeout = atoi(ugm->timeout_str);
|
||||
}
|
||||
else {
|
||||
ugm->timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
|
||||
}
|
||||
|
||||
if (ugm->prefix) {
|
||||
ugm->prefix_len = strlen(ugm->prefix);
|
||||
}
|
||||
|
||||
if (ugm->itemname) {
|
||||
ugm->itemname_len = strlen(ugm->itemname);
|
||||
}
|
||||
|
||||
return ugm;
|
||||
}
|
||||
|
||||
extern "C" int uwsgi_gridfs_request(struct wsgi_request *wsgi_req) {
|
||||
// this is the gridfs file
|
||||
char *itemname = NULL;
|
||||
|
||||
/* Standard GridFS request */
|
||||
if (!wsgi_req->uh->pktsize) {
|
||||
uwsgi_log( "Empty GridFS request. skip.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uwsgi_parse_vars(wsgi_req)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
wsgi_req->app_id = uwsgi_get_app_id(wsgi_req, wsgi_req->appid, wsgi_req->appid_len, gridfs_plugin.modifier1);
|
||||
if (ugridfs.debug) {
|
||||
uwsgi_log("[uwsgi-gridfs-debug] app_id = %d\n", wsgi_req->app_id);
|
||||
}
|
||||
|
||||
if (wsgi_req->app_id == -1) {
|
||||
uwsgi_404(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
struct uwsgi_app *ua = &uwsgi_apps[wsgi_req->app_id];
|
||||
|
||||
struct uwsgi_gridfs_mountpoint *ugm = (struct uwsgi_gridfs_mountpoint *) ua->interpreter;
|
||||
|
||||
if (ugm->skip_slash && (wsgi_req->path_info_len > 0 && wsgi_req->path_info[0] == '/')) {
|
||||
itemname = uwsgi_concat2n(ugm->prefix, ugm->prefix_len, wsgi_req->path_info+1, wsgi_req->path_info_len-1);
|
||||
}
|
||||
else {
|
||||
itemname = uwsgi_concat2n(ugm->prefix, ugm->prefix_len, wsgi_req->path_info, wsgi_req->path_info_len);
|
||||
}
|
||||
|
||||
if (ugridfs.debug) {
|
||||
uwsgi_log("[uwsgi-gridfs-debug] itemname = %s\n", itemname);
|
||||
}
|
||||
|
||||
// itemname will be freed here
|
||||
uwsgi_gridfs_do(wsgi_req, ugm, itemname, 1);
|
||||
|
||||
return UWSGI_OK;
|
||||
|
||||
}
|
||||
|
||||
|
||||
extern "C" void uwsgi_gridfs_mount() {
|
||||
if (!uwsgi.skip_atexit) {
|
||||
uwsgi_log("*** WARNING libmongoclient could have a bug with atexit() hooks, if you get segfault on end/reload, add --skip-atexit ***\n");
|
||||
}
|
||||
struct uwsgi_string_list *usl = ugridfs.mountpoints;
|
||||
while(usl) {
|
||||
if (uwsgi_apps_cnt >= uwsgi.max_apps) {
|
||||
uwsgi_log("ERROR: you cannot load more than %d apps in a worker\n", uwsgi.max_apps);
|
||||
exit(1);
|
||||
}
|
||||
int id = uwsgi_apps_cnt;
|
||||
struct uwsgi_gridfs_mountpoint *ugm = uwsgi_gridfs_add_mountpoint(uwsgi_str(usl->value), usl->len);
|
||||
if (!ugm) exit(1);
|
||||
uwsgi_add_app(id, gridfs_plugin.modifier1, ugm->mountpoint, ugm->mountpoint_len, ugm, ugm);
|
||||
uwsgi_emulate_cow_for_apps(id);
|
||||
uwsgi_log("GridFS mountpoint \"%.*s\" (%d) added: server=%s db=%s\n", ugm->mountpoint_len, ugm->mountpoint, id, ugm->server, ugm->db);
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
static int uwsgi_routing_func_gridfs(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
|
||||
|
||||
struct uwsgi_gridfs_mountpoint *ugm = (struct uwsgi_gridfs_mountpoint *) ur->data2;
|
||||
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
struct uwsgi_buffer *ub_itemname = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ugm->itemname, ugm->itemname_len);
|
||||
if (!ub_itemname) return UWSGI_ROUTE_BREAK;
|
||||
if (ugridfs.debug) {
|
||||
uwsgi_log("[uwsgi-gridfs-debug] itemname = %s\n", ub_itemname->buf);
|
||||
}
|
||||
uwsgi_gridfs_do(wsgi_req, ugm, ub_itemname->buf, 0);
|
||||
uwsgi_buffer_destroy(ub_itemname);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
extern "C" int uwsgi_router_gridfs(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_gridfs;
|
||||
ur->data = args;
|
||||
ur->data_len = strlen(args);
|
||||
ur->data2 = uwsgi_gridfs_add_mountpoint((char *)ur->data, ur->data_len);
|
||||
if (!ur->data2) {
|
||||
exit(1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,31 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
int uwsgi_gridfs_request(struct wsgi_request *);
|
||||
void uwsgi_gridfs_mount();
|
||||
extern struct uwsgi_option uwsgi_gridfs_options[];
|
||||
|
||||
static void uwsgi_gridfs_log(struct wsgi_request *wsgi_req) {
|
||||
log_request(wsgi_req);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
int uwsgi_router_gridfs(struct uwsgi_route *, char *);
|
||||
static void uwsgi_gridfs_register_router() {
|
||||
uwsgi_register_router("gridfs", uwsgi_router_gridfs);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
struct uwsgi_plugin gridfs_plugin = {
|
||||
|
||||
.name = "gridfs",
|
||||
.modifier1 = 25,
|
||||
|
||||
.init_apps = uwsgi_gridfs_mount,
|
||||
.options = uwsgi_gridfs_options,
|
||||
.request = uwsgi_gridfs_request,
|
||||
.after_request = uwsgi_gridfs_log,
|
||||
#ifdef UWSGI_ROUTING
|
||||
.on_load = uwsgi_gridfs_register_router,
|
||||
#endif
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
import os
|
||||
|
||||
NAME='gridfs'
|
||||
|
||||
CFLAGS = ['-I/usr/include/mongo','-I/usr/local/include/mongo']
|
||||
LDFLAGS = []
|
||||
|
||||
LIBS = []
|
||||
if not 'UWSGI_MONGODB_NOLIB' in os.environ:
|
||||
LIBS.append('-lmongoclient')
|
||||
LIBS.append('-lstdc++')
|
||||
LIBS.append('-lboost_thread')
|
||||
LIBS.append('-lboost_system')
|
||||
LIBS.append('-lboost_filesystem')
|
||||
|
||||
GCC_LIST = ['plugin', 'gridfs.cc']
|
||||
+13
-8
@@ -90,31 +90,35 @@ int http_add_uwsgi_header(struct corerouter_peer *peer, char *hh, uint16_t hhlen
|
||||
if (!keylen)
|
||||
return -1;
|
||||
|
||||
if (!uwsgi_strncmp("HOST", 4, hh, keylen)) {
|
||||
peer->key = val;
|
||||
peer->key_len = vallen;
|
||||
}
|
||||
|
||||
else if (hr->websockets) {
|
||||
if (hr->websockets) {
|
||||
if (!uwsgi_strncmp("UPGRADE", 7, hh, keylen)) {
|
||||
if (!uwsgi_strnicmp(val, vallen, "websocket", 9)) {
|
||||
hr->websockets++;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
else if (!uwsgi_strncmp("CONNECTION", 10, hh, keylen)) {
|
||||
if (!uwsgi_strnicmp(val, vallen, "Upgrade", 7)) {
|
||||
hr->websockets++;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
else if (!uwsgi_strncmp("SEC_WEBSOCKET_VERSION", 21, hh, keylen)) {
|
||||
hr->websockets++;
|
||||
hr->websockets++;
|
||||
goto done;
|
||||
}
|
||||
else if (!uwsgi_strncmp("SEC_WEBSOCKET_KEY", 17, hh, keylen)) {
|
||||
hr->websocket_key = val;
|
||||
hr->websocket_key_len = vallen;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (!uwsgi_strncmp("HOST", 4, hh, keylen)) {
|
||||
peer->key = val;
|
||||
peer->key_len = vallen;
|
||||
}
|
||||
|
||||
else if (!uwsgi_strncmp("CONTENT_LENGTH", 14, hh, keylen)) {
|
||||
hr->content_length = uwsgi_str_num(val, vallen);
|
||||
hr->session.can_keepalive = 0;
|
||||
@@ -139,12 +143,13 @@ int http_add_uwsgi_header(struct corerouter_peer *peer, char *hh, uint16_t hhlen
|
||||
}
|
||||
#endif
|
||||
|
||||
done:
|
||||
|
||||
if (uwsgi_strncmp("CONTENT_TYPE", 12, hh, keylen) && uwsgi_strncmp("CONTENT_LENGTH", 14, hh, keylen)) {
|
||||
keylen += 5;
|
||||
prefix = 1;
|
||||
}
|
||||
|
||||
|
||||
if (uwsgi_buffer_u16le(out, keylen)) return -1;
|
||||
|
||||
if (prefix) {
|
||||
|
||||
@@ -41,7 +41,7 @@ JNIEXPORT void JNICALL uwsgi_jvm_api_register_signal(JNIEnv *env, jclass c, jint
|
||||
JNIEXPORT void JNICALL uwsgi_jvm_api_register_rpc(JNIEnv *env, jclass c, jstring name, jobject func) {
|
||||
// no need to release it
|
||||
char *n = uwsgi_jvm_str2c(name);
|
||||
if (uwsgi_register_rpc(n, jvm_plugin.modifier1, 0, uwsgi_jvm_ref(func))) {
|
||||
if (uwsgi_register_rpc(n, &jvm_plugin, 0, uwsgi_jvm_ref(func))) {
|
||||
uwsgi_jvm_throw("unable to register rpc function");
|
||||
}
|
||||
}
|
||||
@@ -79,7 +79,7 @@ JNIEXPORT jobject JNICALL uwsgi_jvm_api_cache_get(JNIEnv *env, jclass c, jstring
|
||||
size_t keylen = uwsgi_jvm_strlen(jkey);
|
||||
char *key = uwsgi_jvm_str2c(jkey);
|
||||
uint64_t vallen = 0;
|
||||
char *value = uwsgi_cache_magic_get(key, keylen, &vallen, NULL);
|
||||
char *value = uwsgi_cache_magic_get(key, keylen, &vallen, NULL, NULL);
|
||||
uwsgi_jvm_release_chars(jkey, key);
|
||||
if (value) {
|
||||
jobject o = uwsgi_jvm_bytearray(value, vallen);
|
||||
@@ -99,7 +99,7 @@ JNIEXPORT jobject JNICALL uwsgi_jvm_api_cache_get_name(JNIEnv *env, jclass c, js
|
||||
char *key = uwsgi_jvm_str2c(jkey);
|
||||
char *cache = uwsgi_jvm_str2c(jcache);
|
||||
uint64_t vallen = 0;
|
||||
char *value = uwsgi_cache_magic_get(key, keylen, &vallen, cache);
|
||||
char *value = uwsgi_cache_magic_get(key, keylen, &vallen, NULL, cache);
|
||||
uwsgi_jvm_release_chars(jkey, key);
|
||||
uwsgi_jvm_release_chars(jcache, cache);
|
||||
if (value) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import os,sys
|
||||
import os
|
||||
import shutil
|
||||
|
||||
NAME='jvm'
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
#ifdef UWSGI_LDAP
|
||||
|
||||
#include "uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
@@ -14,7 +12,22 @@ extern struct uwsgi_server uwsgi;
|
||||
#define ldap_unbind_ext_s ldap_unbind_ext
|
||||
#endif
|
||||
|
||||
void ldap2uwsgi(char *ldapname, char *uwsginame) {
|
||||
static void uwsgi_opt_ldap_dump(char *, char *, void *);
|
||||
static void uwsgi_opt_ldap_dump_ldif(char *, char *, void *);
|
||||
static void uwsgi_ldap_config(char *);
|
||||
|
||||
static void uwsgi_opt_load_ldap(char *opt, char *url, void *none) {
|
||||
uwsgi_ldap_config(url);
|
||||
}
|
||||
|
||||
static struct uwsgi_option uwsgi_ldap_options[] = {
|
||||
{"ldap", required_argument, 0, "load configuration from ldap server", uwsgi_opt_load_ldap, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"ldap-schema", no_argument, 0, "dump uWSGI ldap schema", uwsgi_opt_ldap_dump, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"ldap-schema-ldif", no_argument, 0, "dump uWSGI ldap schema in ldif format", uwsgi_opt_ldap_dump_ldif, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
static void ldap2uwsgi(char *ldapname, char *uwsginame) {
|
||||
char *ptr = uwsginame;
|
||||
|
||||
int i;
|
||||
@@ -32,7 +45,7 @@ void ldap2uwsgi(char *ldapname, char *uwsginame) {
|
||||
*ptr++ = 0;
|
||||
}
|
||||
|
||||
int calc_ldap_name(char *name) {
|
||||
static int calc_ldap_name(char *name) {
|
||||
int i;
|
||||
int counter = 0;
|
||||
|
||||
@@ -52,7 +65,7 @@ struct uwsgi_ldap_entry {
|
||||
};
|
||||
|
||||
|
||||
void uwsgi_name_to_ldap(char *src, char *dst) {
|
||||
static void uwsgi_name_to_ldap(char *src, char *dst) {
|
||||
|
||||
int i;
|
||||
char *ptr = dst;
|
||||
@@ -77,22 +90,7 @@ void uwsgi_name_to_ldap(char *src, char *dst) {
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_ldap_entry *get_ldap_by_num(struct uwsgi_ldap_entry *root, int num, int count) {
|
||||
|
||||
int i;
|
||||
struct uwsgi_ldap_entry *ule;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
ule = &root[i];
|
||||
if (ule->num == num) {
|
||||
return ule;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *name, int count) {
|
||||
static struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *name, int count) {
|
||||
int i;
|
||||
struct uwsgi_ldap_entry *ule;
|
||||
|
||||
@@ -106,7 +104,7 @@ struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_ldap_entry *get_ldap_names(int *count) {
|
||||
static struct uwsgi_ldap_entry *get_ldap_names(int *count) {
|
||||
|
||||
struct uwsgi_option *op = uwsgi.options;
|
||||
struct uwsgi_ldap_entry *ule, *entry;
|
||||
@@ -139,7 +137,7 @@ next:
|
||||
return ule;
|
||||
}
|
||||
|
||||
void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
|
||||
static void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
|
||||
|
||||
int i;
|
||||
int items;
|
||||
@@ -192,7 +190,7 @@ void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
|
||||
static void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
|
||||
|
||||
int i;
|
||||
int items;
|
||||
@@ -240,7 +238,7 @@ void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void uwsgi_ldap_config(char *url) {
|
||||
static void uwsgi_ldap_config(char *url) {
|
||||
|
||||
LDAP *ldp;
|
||||
LDAPMessage *results, *entry;
|
||||
@@ -367,4 +365,8 @@ void uwsgi_ldap_config(char *url) {
|
||||
ldap_unbind_ext_s(ldp, NULL, NULL);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
struct uwsgi_plugin ldap_plugin = {
|
||||
.name = "ldap",
|
||||
.options = uwsgi_ldap_options,
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
NAME='ldap'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lldap']
|
||||
|
||||
GCC_LIST = ['ldap']
|
||||
@@ -0,0 +1,71 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
|
||||
static int legion_action_cache_fetch_from_legion(struct uwsgi_legion *ul, char *arg) {
|
||||
uwsgi_log("[legion-cache-fetch] getting cache '%s' dump from legion '%s' nodes\n", arg, ul->legion);
|
||||
|
||||
struct uwsgi_cache *uc = uwsgi_cache_by_name(arg);
|
||||
if (!uc) {
|
||||
uwsgi_log("[legion-cache-fetch] cannot sync, cache '%s' not found\n", arg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *dump_from_nodes = NULL;
|
||||
|
||||
uwsgi_rlock(ul->lock);
|
||||
struct uwsgi_legion_node *legion_nodes = ul->nodes_head;
|
||||
while (legion_nodes) {
|
||||
char *dump_socket = NULL;
|
||||
if (uwsgi_kvlist_parse(legion_nodes->scroll, legion_nodes->scroll_len, ',', '=',
|
||||
"dump-socket", &dump_socket,
|
||||
NULL)) {
|
||||
uwsgi_log("[legion-cache-fetch] cannot sync from %.*s, cache socket address not found in legion scroll: %.*s\n",
|
||||
legion_nodes->name_len, legion_nodes->name, legion_nodes->scroll_len, legion_nodes->scroll);
|
||||
}
|
||||
else {
|
||||
if (dump_socket) {
|
||||
uwsgi_string_new_list(&dump_from_nodes, dump_socket);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[legion-cache-fetch] cannot sync from %.*s, cache socket address not found in legion scroll: %.*s\n",
|
||||
legion_nodes->name_len, legion_nodes->name, legion_nodes->scroll_len, legion_nodes->scroll);
|
||||
}
|
||||
}
|
||||
legion_nodes = legion_nodes->next;
|
||||
}
|
||||
|
||||
// update uc->sync_nodes list
|
||||
struct uwsgi_string_list *usl = uc->sync_nodes;
|
||||
struct uwsgi_string_list *next;
|
||||
while (usl) {
|
||||
next = usl->next;
|
||||
free(usl->value);
|
||||
free(usl);
|
||||
usl = next;
|
||||
}
|
||||
uwsgi_rwunlock(ul->lock);
|
||||
|
||||
uwsgi_rlock(uc->lock);
|
||||
uc->sync_nodes = dump_from_nodes;
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
|
||||
// call sync
|
||||
uwsgi_cache_sync_from_nodes(uc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void legion_cache_register() {
|
||||
uwsgi_legion_action_register("legion-cache-fetch", legion_action_cache_fetch_from_legion);
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_plugin legion_cache_fetch_plugin = {
|
||||
.name = "legion_cache_fetch",
|
||||
.on_load = legion_cache_register,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
NAME = 'legion_cache_fetch'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
GCC_LIST = ['legion_cache_fetch']
|
||||
|
||||
+169
-26
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
#include <lua.h>
|
||||
#include <lualib.h>
|
||||
@@ -8,15 +8,33 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_lua {
|
||||
struct lua_State **L;
|
||||
|
||||
char *shell;
|
||||
char *filename;
|
||||
struct uwsgi_string_list *load;
|
||||
} ulua;
|
||||
|
||||
struct uwsgi_plugin lua_plugin;
|
||||
|
||||
#define lca(L, n) ulua_check_args(L, __FUNCTION__, n)
|
||||
|
||||
static void uwsgi_opt_luashell(char *opt, char *value, void *foobar) {
|
||||
|
||||
uwsgi.honour_stdin = 1;
|
||||
if (value) {
|
||||
ulua.shell = value;
|
||||
}
|
||||
else {
|
||||
ulua.shell = "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct uwsgi_option uwsgi_lua_options[] = {
|
||||
|
||||
{"lua", required_argument, 0, "load lua wsapi app", uwsgi_opt_set_str, &ulua.filename, 0},
|
||||
{"lua-load", required_argument, 0, "load a lua file", uwsgi_opt_add_string_list, &ulua.load, 0},
|
||||
{"lua-shell", no_argument, 0, "run the lua interactive shell (debug.debug())", uwsgi_opt_luashell, NULL, 0},
|
||||
{"luashell", no_argument, 0, "run the lua interactive shell (debug.debug())", uwsgi_opt_luashell, NULL, 0},
|
||||
|
||||
{0, 0, 0, 0},
|
||||
|
||||
@@ -69,10 +87,10 @@ static int uwsgi_api_register_rpc(lua_State *L) {
|
||||
lua_pushvalue(L, 2);
|
||||
func = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
|
||||
uwsgi_log("registered function %d in global table\n", func);
|
||||
uwsgi_log("registered function %d in Lua global table\n", func);
|
||||
lfunc = func;
|
||||
|
||||
if (uwsgi_register_rpc((char *)name, 6, 0, (void *) lfunc)) {
|
||||
if (uwsgi_register_rpc((char *)name, &lua_plugin, 0, (void *) lfunc)) {
|
||||
lua_pushnil(L);
|
||||
}
|
||||
else {
|
||||
@@ -260,7 +278,7 @@ static int uwsgi_api_cache_get(lua_State *L) {
|
||||
if (argc > 1) {
|
||||
cache = lua_tolstring(L, 2, NULL);
|
||||
}
|
||||
value = uwsgi_cache_magic_get((char *)key, keylen, &valsize, (char *)cache);
|
||||
value = uwsgi_cache_magic_get((char *)key, keylen, &valsize, NULL, (char *)cache);
|
||||
if (value) {
|
||||
lua_pushlstring(L, value, valsize);
|
||||
free(value);
|
||||
@@ -345,6 +363,7 @@ static const luaL_reg uwsgi_api[] = {
|
||||
|
||||
{"lock", uwsgi_api_lock},
|
||||
{"unlock", uwsgi_api_unlock},
|
||||
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -387,36 +406,51 @@ static int uwsgi_lua_init(){
|
||||
static void uwsgi_lua_app() {
|
||||
int i;
|
||||
|
||||
if (ulua.filename) {
|
||||
if (!ulua.filename && !ulua.load && !ulua.shell) return;
|
||||
|
||||
for(i=0;i<uwsgi.cores;i++) {
|
||||
ulua.L[i] = luaL_newstate();
|
||||
luaL_openlibs(ulua.L[i]);
|
||||
luaL_register(ulua.L[i], "uwsgi", uwsgi_api);
|
||||
if (luaL_loadfile(ulua.L[i], ulua.filename)) {
|
||||
uwsgi_log("unable to load file %s: %s\n", ulua.filename, lua_tostring(ulua.L[i], -1));
|
||||
exit(1);
|
||||
|
||||
lua_pushstring(ulua.L[i], UWSGI_VERSION);
|
||||
lua_setfield(ulua.L[i], -2, "version");
|
||||
|
||||
struct uwsgi_string_list *usl = ulua.load;
|
||||
while(usl) {
|
||||
if (luaL_dofile(ulua.L[i], usl->value)) {
|
||||
uwsgi_log("unable to load Lua file %s: %s\n", usl->value, lua_tostring(ulua.L[i], -1));
|
||||
exit(1);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
if (ulua.filename) {
|
||||
if (luaL_loadfile(ulua.L[i], ulua.filename)) {
|
||||
uwsgi_log("unable to load Lua file %s: %s\n", ulua.filename, lua_tostring(ulua.L[i], -1));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// use a pcall
|
||||
//lua_call(ulua.L[i], 0, 1);
|
||||
if (lua_pcall(ulua.L[i], 0, 1, 0) != 0) {
|
||||
uwsgi_log("%s\n", lua_tostring(ulua.L[i], -1));
|
||||
exit(1);
|
||||
}
|
||||
// use a pcall
|
||||
//lua_call(ulua.L[i], 0, 1);
|
||||
if (lua_pcall(ulua.L[i], 0, 1, 0) != 0) {
|
||||
uwsgi_log("%s\n", lua_tostring(ulua.L[i], -1));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// if the loaded lua app returns as a table, fetch the
|
||||
// run function.
|
||||
if (lua_istable(ulua.L[i], 2)) {
|
||||
lua_pushstring(ulua.L[i], "run" );
|
||||
lua_gettable(ulua.L[i], 2);
|
||||
lua_replace(ulua.L[i], 2);
|
||||
}
|
||||
// if the loaded lua app returns as a table, fetch the
|
||||
// run function.
|
||||
if (lua_istable(ulua.L[i], 2)) {
|
||||
lua_pushstring(ulua.L[i], "run" );
|
||||
lua_gettable(ulua.L[i], 2);
|
||||
lua_replace(ulua.L[i], 2);
|
||||
}
|
||||
|
||||
if (! lua_isfunction(ulua.L[i], 2)) {
|
||||
uwsgi_log("Can't find WSAPI entry point (no function, nor a table with function'run').\n");
|
||||
exit(1);
|
||||
if (! lua_isfunction(ulua.L[i], 2)) {
|
||||
uwsgi_log("Can't find WSAPI entry point (no function, nor a table with function'run').\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -665,13 +699,119 @@ static uint16_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, uint16_t a
|
||||
#endif
|
||||
if (sl <= 0xffff) {
|
||||
memcpy(buffer, sv, sl);
|
||||
lua_pop(L, 1);
|
||||
return sl;
|
||||
}
|
||||
|
||||
lua_pop(L, 1);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static void uwsgi_lua_configurator_array(lua_State *L) {
|
||||
|
||||
int i;
|
||||
int n = luaL_getn(L, -3);
|
||||
|
||||
for(i=1;i<=n;i++) {
|
||||
lua_rawgeti(L, 1, i);
|
||||
if (lua_istable(L, -1)) {
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, -2) != 0) {
|
||||
char *key = uwsgi_str((char *)lua_tostring(L, -2));
|
||||
char *value = uwsgi_str((char *)lua_tostring(L, -1));
|
||||
add_exported_option(key, value, 0);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void uwsgi_lua_configurator(char *filename, char *magic_table[]) {
|
||||
size_t len = 0;
|
||||
uwsgi_log_initial("[uWSGI] getting Lua configuration from %s\n", filename);
|
||||
char *code = uwsgi_open_and_read(filename, &len, 1, magic_table);
|
||||
lua_State *L = luaL_newstate();
|
||||
if (!L) {
|
||||
uwsgi_log("unable to initialize Lua state for configuration\n");
|
||||
exit(1);
|
||||
}
|
||||
luaL_openlibs(L);
|
||||
if (luaL_dostring(L, code) != 0) {
|
||||
uwsgi_log("error running Lua configurator: %s\n", lua_tostring(L, -1));
|
||||
exit(1);
|
||||
}
|
||||
free(code);
|
||||
|
||||
if (!lua_istable(L, -1)) {
|
||||
uwsgi_log("Lua configurator has to return a table !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
lua_pushnil(L);
|
||||
// we always use uwsgi_str to avoid GC destroying our strings
|
||||
// and to be able to call lua_close at the end
|
||||
while (lua_next(L, -2) != 0) {
|
||||
// array ?
|
||||
if (lua_isnumber(L, -2)) {
|
||||
uwsgi_lua_configurator_array(L);
|
||||
break;
|
||||
}
|
||||
// dictionary
|
||||
else {
|
||||
char *key = uwsgi_str((char *)lua_tostring(L, -2));
|
||||
if (lua_istable(L, -1)) {
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, -2) != 0) {
|
||||
char *value = uwsgi_str((char *)lua_tostring(L, -1));
|
||||
add_exported_option(key, value, 0);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
char *value = uwsgi_str((char *)lua_tostring(L, -1));
|
||||
add_exported_option(key, value, 0);
|
||||
}
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
// this will destroy the whole Lua state
|
||||
lua_close(L);
|
||||
}
|
||||
|
||||
static void uwsgi_register_lua_features() {
|
||||
uwsgi_register_configurator(".lua", uwsgi_lua_configurator);
|
||||
}
|
||||
|
||||
static void uwsgi_lua_hijack(void) {
|
||||
if (ulua.shell && uwsgi.mywid == 1) {
|
||||
uwsgi.workers[uwsgi.mywid].hijacked = 1;
|
||||
uwsgi.workers[uwsgi.mywid].hijacked_count++;
|
||||
// re-map stdin to stdout and stderr if we are logging to a file
|
||||
if (uwsgi.logfile) {
|
||||
if (dup2(0, 1) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
}
|
||||
if (dup2(0, 2) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
}
|
||||
}
|
||||
int ret = -1;
|
||||
// run in the first state
|
||||
lua_State *L = ulua.L[0];
|
||||
lua_getglobal(L, "debug");
|
||||
lua_getfield(L, -1, "debug");
|
||||
ret = lua_pcall(L, 0, 0, 0);
|
||||
if (ret == 0) {
|
||||
exit(UWSGI_QUIET_CODE);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_plugin lua_plugin = {
|
||||
|
||||
@@ -685,8 +825,11 @@ struct uwsgi_plugin lua_plugin = {
|
||||
.magic = uwsgi_lua_magic,
|
||||
.signal_handler = uwsgi_lua_signal_handler,
|
||||
|
||||
.hijack_worker = uwsgi_lua_hijack,
|
||||
|
||||
.code_string = uwsgi_lua_code_string,
|
||||
.rpc = uwsgi_lua_rpc,
|
||||
|
||||
.on_load = uwsgi_register_lua_features,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
#include "client/dbclient.h"
|
||||
|
||||
extern "C" int uwsgi_mongodb_version() {
|
||||
// this is only a hack to force the linked to embed libmongoclient.a
|
||||
mongo::DBClientConnection c;
|
||||
return 0;
|
||||
}
|
||||
@@ -6,9 +6,6 @@ a fake plugin used for preloading mongodb library when only available as static.
|
||||
|
||||
*/
|
||||
|
||||
int uwsgi_mongodb_version(void);
|
||||
|
||||
struct uwsgi_plugin mongodb_plugin = {
|
||||
.name = "mongodb",
|
||||
.init = uwsgi_mongodb_version,
|
||||
};
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
NAME='mongodb'
|
||||
|
||||
CFLAGS = ['-I/usr/include/mongo','-I/usr/local/include/mongo']
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lmongoclient', '-lboost_thread','-lboost_filesystem']
|
||||
LIBS = ['-Wl,-whole-archive', '-lmongoclient', '-Wl,-no-whole-archive', '-lboost_thread', '-lboost_system', '-lboost_filesystem']
|
||||
|
||||
GCC_LIST = ['plugin', 'foobar.cc']
|
||||
GCC_LIST = ['plugin']
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
@@ -29,7 +29,7 @@ struct uwsgi_mongodb_state {
|
||||
struct iovec iovec[13];
|
||||
};
|
||||
|
||||
ssize_t uwsgi_mongodb_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
static ssize_t uwsgi_mongodb_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
|
||||
struct uwsgi_mongodb_state *ums = NULL;
|
||||
|
||||
@@ -151,7 +151,7 @@ done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void uwsgi_mongodblog_register() {
|
||||
static void uwsgi_mongodblog_register() {
|
||||
uwsgi_register_logger("mongodblog", uwsgi_mongodb_logger);
|
||||
}
|
||||
|
||||
|
||||
@@ -267,7 +267,7 @@ static MonoArray *uwsgi_mono_method_api_CacheGet(MonoString *key, MonoString *ca
|
||||
c_cache = mono_string_to_utf8(cache);
|
||||
}
|
||||
uint64_t vallen = 0 ;
|
||||
char *value = uwsgi_cache_magic_get(c_key, c_keylen, &vallen, c_cache);
|
||||
char *value = uwsgi_cache_magic_get(c_key, c_keylen, &vallen, NULL, c_cache);
|
||||
if (value) {
|
||||
MonoArray *ret = mono_array_new(mono_domain_get(), umono.byte_class, vallen);
|
||||
char *buf = mono_array_addr(ret, char, 0);
|
||||
@@ -540,7 +540,7 @@ static int uwsgi_mono_request(struct wsgi_request *wsgi_req) {
|
||||
key_len = 0;
|
||||
}
|
||||
|
||||
wsgi_req->app_id = uwsgi_get_app_id(key, key_len, mono_plugin.modifier1);
|
||||
wsgi_req->app_id = uwsgi_get_app_id(NULL, key, key_len, mono_plugin.modifier1);
|
||||
// if it is -1, try to load a dynamic app
|
||||
if (wsgi_req->app_id == -1) {
|
||||
if (uwsgi.threads > 1) {
|
||||
@@ -548,7 +548,7 @@ static int uwsgi_mono_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
// check if the mean time, something changed
|
||||
wsgi_req->app_id = uwsgi_get_app_id(key, key_len, mono_plugin.modifier1);
|
||||
wsgi_req->app_id = uwsgi_get_app_id(NULL, key, key_len, mono_plugin.modifier1);
|
||||
|
||||
if (wsgi_req->app_id == -1) {
|
||||
wsgi_req->app_id = uwsgi_mono_create_app(key, key_len, key, key_len, 0);
|
||||
|
||||
@@ -96,7 +96,7 @@ static int sapi_uwsgi_send_headers(sapi_headers_struct *sapi_headers)
|
||||
}
|
||||
else {
|
||||
char *sl = SG(sapi_headers).http_status_line;
|
||||
uwsgi_response_prepare_headers(wsgi_req, sl, strlen(sl));
|
||||
uwsgi_response_prepare_headers(wsgi_req, sl + 8 , strlen(sl) - 8);
|
||||
}
|
||||
|
||||
h = zend_llist_get_first_ex(&sapi_headers->headers, &pos);
|
||||
@@ -309,7 +309,7 @@ PHP_FUNCTION(uwsgi_cache_get) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
char *value = uwsgi_cache_magic_get(key, keylen, &valsize, cache);
|
||||
char *value = uwsgi_cache_magic_get(key, keylen, &valsize, NULL, cache);
|
||||
if (value) {
|
||||
char *ret = estrndup(value, valsize);
|
||||
free(value);
|
||||
|
||||
@@ -17,7 +17,7 @@ try:
|
||||
except:
|
||||
pass
|
||||
|
||||
CFLAGS = [os.popen(PHPPATH + ' --includes').read().rstrip(), '-Wno-error=sign-compare']
|
||||
CFLAGS = [os.popen(PHPPATH + ' --includes').read().rstrip(), '-Wno-sign-compare']
|
||||
|
||||
LDFLAGS = os.popen(PHPPATH + ' --ldflags').read().rstrip().split()
|
||||
if ld_run_path:
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int connect_prober_callback(int interesting_fd, struct uwsgi_signal_probe *up) {
|
||||
|
||||
// is this a timeout event ?
|
||||
if (interesting_fd == -1) {
|
||||
// am i wating for something ?
|
||||
if (up->fd != -1) {
|
||||
if (up->cycles > (uint64_t) up->timeout) {
|
||||
// reset the cycle
|
||||
up->cycles = 0;
|
||||
close(up->fd);
|
||||
up->fd = -1;
|
||||
// state = NOOP
|
||||
up->state = 0;
|
||||
// avoid duplicated events
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ok register a new event
|
||||
else {
|
||||
if ((up->cycles % up->freq) == 0) {
|
||||
up->fd = uwsgi_connect(up->args, -1, 1);
|
||||
if (up->fd != -1) {
|
||||
// status = CONNECTING
|
||||
up->state = 1;
|
||||
event_queue_add_fd_write(uwsgi.master_queue, up->fd);
|
||||
return 0;
|
||||
}
|
||||
// signal the bad event (if not already bad)
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (up->fd != -1) {
|
||||
// is this event for me ?
|
||||
if (interesting_fd == up->fd) {
|
||||
// uselsess here (we have only one state), only to show a good practice
|
||||
// check the state
|
||||
if (up->state == 1) {
|
||||
if (uwsgi_is_bad_connection(up->fd)) {
|
||||
// signal the bad connection (if needed)
|
||||
up->cycles = 0;
|
||||
close(up->fd);
|
||||
up->fd = -1;
|
||||
// state = NOOP
|
||||
up->state = 0;
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
// this is a good connection
|
||||
up->cycles = 0;
|
||||
close(up->fd);
|
||||
up->fd = -1;
|
||||
// state = NOOP
|
||||
up->state = 0;
|
||||
if (up->bad) {
|
||||
up->bad = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// default action
|
||||
return 0;
|
||||
}
|
||||
|
||||
int probeconnect_init() {
|
||||
|
||||
uwsgi_probe_register(&uwsgi.probes, "connect", connect_prober_callback);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin probeconnect_plugin = {
|
||||
|
||||
.init = probeconnect_init,
|
||||
};
|
||||
@@ -1,7 +0,0 @@
|
||||
|
||||
NAME='probeconnect'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
GCC_LIST = ['connectprobe']
|
||||
@@ -1,132 +0,0 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <libpq-fe.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
int pg_prober_callback(int, struct uwsgi_signal_probe *);
|
||||
int probepg_init(void);
|
||||
|
||||
int pg_prober_callback(int interesting_fd, struct uwsgi_signal_probe *up) {
|
||||
|
||||
// is this a timeout event ?
|
||||
if (interesting_fd == -1) {
|
||||
// am i wating for something ?
|
||||
if (up->fd != -1) {
|
||||
if (up->cycles > (uint64_t) up->timeout) {
|
||||
// reset the cycle
|
||||
up->cycles = 0;
|
||||
PQfinish((PGconn *) up->data);
|
||||
up->fd = -1;
|
||||
// state = NOOP
|
||||
up->state = 0;
|
||||
// avoid duplicated events
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ok register a new event
|
||||
else {
|
||||
if ((up->cycles % up->freq) == 0) {
|
||||
up->last_event = event_queue_write();
|
||||
up->data = (void *) PQconnectStart(up->args);
|
||||
if (up->data) {
|
||||
// status = CONNECTING
|
||||
up->state = PQstatus((PGconn *) up->data);
|
||||
if (up->state == CONNECTION_BAD)
|
||||
goto bad;
|
||||
up->fd = PQsocket((PGconn *) up->data);
|
||||
event_queue_add_fd_write(uwsgi.master_queue, up->fd);
|
||||
return 0;
|
||||
}
|
||||
bad:
|
||||
// signal the bad event (if not already bad)
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (up->fd != -1) {
|
||||
// is this event for me ?
|
||||
if (interesting_fd == up->fd) {
|
||||
// check the state
|
||||
up->state = PQstatus((PGconn *) up->data);
|
||||
if (up->state == CONNECTION_BAD) {
|
||||
// signal the bad connection (if needed)
|
||||
up->cycles = 0;
|
||||
PQfinish((PGconn *) up->data);
|
||||
up->fd = -1;
|
||||
up->state = 0;
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (up->state == CONNECTION_OK) {
|
||||
up->cycles = 0;
|
||||
PQfinish((PGconn *) up->data);
|
||||
up->fd = -1;
|
||||
// state = NOOP
|
||||
up->state = 0;
|
||||
if (up->bad) {
|
||||
up->bad = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// still wait...
|
||||
else {
|
||||
PostgresPollingStatusType wait_type = PQconnectPoll((PGconn *) up->data);
|
||||
// the connection is good
|
||||
if (wait_type == PGRES_POLLING_ACTIVE || wait_type == PGRES_POLLING_FAILED || wait_type == PGRES_POLLING_OK) {
|
||||
if (wait_type == PGRES_POLLING_ACTIVE)
|
||||
wait_type = PQconnectPoll((PGconn *) up->data);
|
||||
up->cycles = 0;
|
||||
up->fd = -1;
|
||||
// state = NOOP
|
||||
up->state = 0;
|
||||
PQfinish((PGconn *) up->data);
|
||||
if (wait_type == PGRES_POLLING_FAILED) {
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (up->bad) {
|
||||
up->bad = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (wait_type == PGRES_POLLING_READING) {
|
||||
event_queue_del_fd(uwsgi.master_queue, up->fd, up->last_event);
|
||||
event_queue_add_fd_read(uwsgi.master_queue, up->fd);
|
||||
up->last_event = event_queue_read();
|
||||
}
|
||||
else if (wait_type == PGRES_POLLING_WRITING) {
|
||||
event_queue_del_fd(uwsgi.master_queue, up->fd, up->last_event);
|
||||
event_queue_add_fd_write(uwsgi.master_queue, up->fd);
|
||||
up->last_event = event_queue_write();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// default action
|
||||
return 0;
|
||||
}
|
||||
|
||||
int probepg_init() {
|
||||
|
||||
uwsgi_probe_register(&uwsgi.probes, "pg", pg_prober_callback);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin probepg_plugin = {
|
||||
|
||||
.init = probepg_init,
|
||||
};
|
||||
@@ -1,9 +0,0 @@
|
||||
import os
|
||||
|
||||
NAME='probepg'
|
||||
CFLAGS = os.popen('pg_config --cflags').read().rstrip().split()
|
||||
CFLAGS.append('-I' + os.popen('pg_config --includedir').read().rstrip())
|
||||
LDFLAGS = os.popen('pg_config --ldflags').read().rstrip().split()
|
||||
LIBS = ['-L' + os.popen('pg_config --libdir').read().rstrip(), '-lpq']
|
||||
|
||||
GCC_LIST = ['pgprobe']
|
||||
@@ -9,8 +9,11 @@ extern struct uwsgi_plugin psgi_plugin;
|
||||
XS(XS_input_seek) {
|
||||
|
||||
dXSARGS;
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
psgi_check_args(1);
|
||||
uwsgi_request_body_seek(wsgi_req, SvIV(ST(0)));
|
||||
|
||||
XSRETURN(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -394,7 +394,7 @@ int uwsgi_perl_request(struct wsgi_request *wsgi_req) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
wsgi_req->app_id = uwsgi_get_app_id(wsgi_req->appid, wsgi_req->appid_len, psgi_plugin.modifier1);
|
||||
wsgi_req->app_id = uwsgi_get_app_id(wsgi_req, wsgi_req->appid, wsgi_req->appid_len, psgi_plugin.modifier1);
|
||||
// if it is -1, try to load a dynamic app
|
||||
if (wsgi_req->app_id == -1) {
|
||||
if (wsgi_req->dynamic) {
|
||||
@@ -513,6 +513,10 @@ void uwsgi_perl_after_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
log_request(wsgi_req);
|
||||
|
||||
// We may be called after an early exit in XS_coroae_accept_request,
|
||||
// before the environ is set up.
|
||||
if (!wsgi_req->async_environ) return;
|
||||
|
||||
// dereference %env
|
||||
SV *env = SvRV((SV *) wsgi_req->async_environ);
|
||||
|
||||
@@ -617,7 +621,7 @@ void uwsgi_perl_enable_threads(void) {
|
||||
#endif
|
||||
}
|
||||
|
||||
int uwsgi_perl_signal_handler(uint8_t sig, void *handler) {
|
||||
static int uwsgi_perl_signal_handler(uint8_t sig, void *handler) {
|
||||
|
||||
int ret = 0;
|
||||
|
||||
@@ -664,7 +668,7 @@ void uwsgi_perl_run_hook(SV *hook) {
|
||||
}
|
||||
|
||||
static void uwsgi_perl_atexit() {
|
||||
if (uwsgi.mywid == -1) goto realstuff;
|
||||
if (uwsgi.mywid == 0) goto realstuff;
|
||||
|
||||
// if hijacked do not run atexit hooks
|
||||
if (uwsgi.workers[uwsgi.mywid].hijacked)
|
||||
@@ -684,6 +688,41 @@ realstuff:
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t uwsgi_perl_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
|
||||
|
||||
int i;
|
||||
uint16_t ret = 0;
|
||||
|
||||
dSP;
|
||||
ENTER;
|
||||
SAVETMPS;
|
||||
PUSHMARK(SP);
|
||||
for(i=0;i<argc;i++) {
|
||||
XPUSHs( sv_2mortal(newSVpv(argv[i], argvs[i])));
|
||||
}
|
||||
PUTBACK;
|
||||
|
||||
call_sv( SvRV((SV*)func), G_SCALAR | G_EVAL);
|
||||
|
||||
SPAGAIN;
|
||||
if(SvTRUE(ERRSV)) {
|
||||
uwsgi_log("[uwsgi-perl error] %s", SvPV_nolen(ERRSV));
|
||||
}
|
||||
else {
|
||||
STRLEN rlen;
|
||||
SV *response = POPs;
|
||||
char *value = SvPV(response, rlen );
|
||||
ret = UMIN(UMAX16, rlen);
|
||||
memcpy(buffer, value, ret);
|
||||
}
|
||||
|
||||
PUTBACK;
|
||||
FREETMPS;
|
||||
LEAVE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin psgi_plugin = {
|
||||
|
||||
.name = "psgi",
|
||||
@@ -696,6 +735,7 @@ struct uwsgi_plugin psgi_plugin = {
|
||||
|
||||
.init_thread = uwsgi_perl_init_thread,
|
||||
.signal_handler = uwsgi_perl_signal_handler,
|
||||
.rpc = uwsgi_perl_rpc,
|
||||
|
||||
.mule = uwsgi_perl_mule,
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@ XS(XS_cache_get) {
|
||||
cache = SvPV_nolen(ST(1));
|
||||
}
|
||||
|
||||
char *value = uwsgi_cache_magic_get(key, (uint16_t) keylen, &vallen, cache);
|
||||
char *value = uwsgi_cache_magic_get(key, (uint16_t) keylen, &vallen, NULL, cache);
|
||||
if (value) {
|
||||
ST(0) = newSVpv(value, vallen);
|
||||
free(value);
|
||||
@@ -233,6 +233,21 @@ XS(XS_register_signal) {
|
||||
|
||||
}
|
||||
|
||||
XS(XS_register_rpc) {
|
||||
dXSARGS;
|
||||
|
||||
psgi_check_args(2);
|
||||
|
||||
char *name = SvPV_nolen(ST(0));
|
||||
|
||||
if (uwsgi_register_rpc(name, &psgi_plugin, 0, (void *) newRV_inc(ST(1)))) {
|
||||
XSRETURN_NO;
|
||||
}
|
||||
|
||||
XSRETURN_YES;
|
||||
}
|
||||
|
||||
|
||||
XS(XS_postfork) {
|
||||
dXSARGS;
|
||||
|
||||
@@ -519,6 +534,7 @@ void init_perl_embedded_module() {
|
||||
psgi_xs(suspend);
|
||||
psgi_xs(signal);
|
||||
psgi_xs(register_signal);
|
||||
psgi_xs(register_rpc);
|
||||
psgi_xs(signal_wait);
|
||||
#ifdef UWSGI_SSL
|
||||
psgi_xs(i_am_the_lord);
|
||||
|
||||
@@ -33,12 +33,12 @@ void set_dyn_pyhome(char *home, uint16_t pyhome_len) {
|
||||
}
|
||||
|
||||
// simulate a pythonhome directive
|
||||
if (uwsgi.wsgi_req->pyhome_len > 0) {
|
||||
if (uwsgi.wsgi_req->home_len > 0) {
|
||||
|
||||
PyObject *venv_path = UWSGI_PYFROMSTRINGSIZE(uwsgi.wsgi_req->pyhome, uwsgi.wsgi_req->pyhome_len);
|
||||
PyObject *venv_path = UWSGI_PYFROMSTRINGSIZE(uwsgi.wsgi_req->home, uwsgi.wsgi_req->home_len);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("setting dynamic virtualenv to %.*s\n", uwsgi.wsgi_req->pyhome_len, uwsgi.wsgi_req->pyhome);
|
||||
uwsgi_debug("setting dynamic virtualenv to %.*s\n", uwsgi.wsgi_req->home_len, uwsgi.wsgi_req->home);
|
||||
#endif
|
||||
|
||||
PyDict_SetItemString(pysys_dict, "prefix", venv_path);
|
||||
@@ -86,7 +86,7 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
|
||||
time_t now = uwsgi_now();
|
||||
|
||||
if (uwsgi_get_app_id(wsgi_req->appid, wsgi_req->appid_len, -1) != -1) {
|
||||
if (uwsgi_get_app_id(NULL, wsgi_req->appid, wsgi_req->appid_len, -1) != -1) {
|
||||
uwsgi_log( "mountpoint %.*s already configured. skip.\n", wsgi_req->appid_len, wsgi_req->appid);
|
||||
return -1;
|
||||
}
|
||||
@@ -177,8 +177,8 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
wi->interpreter = up.main_thread;
|
||||
}
|
||||
|
||||
if (wsgi_req->pyhome_len) {
|
||||
set_dyn_pyhome(wsgi_req->pyhome, wsgi_req->pyhome_len);
|
||||
if (wsgi_req->home_len) {
|
||||
set_dyn_pyhome(wsgi_req->home, wsgi_req->home_len);
|
||||
}
|
||||
|
||||
if (wsgi_req->touch_reload_len > 0 && wsgi_req->touch_reload_len < 0xff) {
|
||||
@@ -196,8 +196,6 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
goto doh;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// the module contains multiple apps
|
||||
if (PyDict_Check((PyObject *)wi->callable)) {
|
||||
applications = wi->callable;
|
||||
|
||||
@@ -25,7 +25,12 @@ void uwsgi_opt_pythonpath(char *opt, char *value, void *foobar) {
|
||||
void uwsgi_opt_pyshell(char *opt, char *value, void *foobar) {
|
||||
|
||||
uwsgi.honour_stdin = 1;
|
||||
up.pyshell = 1;
|
||||
if (value) {
|
||||
up.pyshell = value;
|
||||
}
|
||||
else {
|
||||
up.pyshell = "";
|
||||
}
|
||||
|
||||
if (!strcmp("pyshell-oneshot", opt)) {
|
||||
up.pyshell_oneshot = 1;
|
||||
@@ -127,8 +132,8 @@ struct uwsgi_option uwsgi_python_options[] = {
|
||||
{"no-site", no_argument, 0, "do not import site module", uwsgi_opt_true, &Py_NoSiteFlag, 0},
|
||||
#endif
|
||||
#endif
|
||||
{"pyshell", no_argument, 0, "run an interactive python shell in the uWSGI environment", uwsgi_opt_pyshell, NULL, 0},
|
||||
{"pyshell-oneshot", no_argument, 0, "run an interactive python shell in the uWSGI environment (one-shot variant)", uwsgi_opt_pyshell, NULL, 0},
|
||||
{"pyshell", optional_argument, 0, "run an interactive python shell in the uWSGI environment", uwsgi_opt_pyshell, NULL, 0},
|
||||
{"pyshell-oneshot", optional_argument, 0, "run an interactive python shell in the uWSGI environment (one-shot variant)", uwsgi_opt_pyshell, NULL, 0},
|
||||
|
||||
{"python", required_argument, 0, "run a python script in the uWSGI environment", uwsgi_opt_pyrun, NULL, 0},
|
||||
{"py", required_argument, 0, "run a python script in the uWSGI environment", uwsgi_opt_pyrun, NULL, 0},
|
||||
@@ -290,7 +295,7 @@ void uwsgi_python_reset_random_seed() {
|
||||
|
||||
void uwsgi_python_atexit() {
|
||||
|
||||
if (uwsgi.mywid == -1) goto realstuff;
|
||||
if (uwsgi.mywid == 0) goto realstuff;
|
||||
|
||||
// if hijacked do not run atexit hooks
|
||||
if (uwsgi.workers[uwsgi.mywid].hijacked)
|
||||
@@ -1063,9 +1068,7 @@ void uwsgi_python_init_apps() {
|
||||
#endif
|
||||
|
||||
// setup app loaders
|
||||
#ifdef UWSGI_MINTERPRETERS
|
||||
up.loaders[LOADER_DYN] = uwsgi_dyn_loader;
|
||||
#endif
|
||||
up.loaders[LOADER_UWSGI] = uwsgi_uwsgi_loader;
|
||||
up.loaders[LOADER_FILE] = uwsgi_file_loader;
|
||||
up.loaders[LOADER_PASTE] = uwsgi_paste_loader;
|
||||
@@ -1690,11 +1693,17 @@ void uwsgi_python_hijack(void) {
|
||||
}
|
||||
}
|
||||
UWSGI_GET_GIL;
|
||||
PyImport_ImportModule("readline");
|
||||
int ret = -1;
|
||||
if (up.pyshell[0] != 0) {
|
||||
ret = PyRun_SimpleString(up.pyshell);
|
||||
}
|
||||
else {
|
||||
PyImport_ImportModule("readline");
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
int ret = PyRun_InteractiveLoop(stdin, "uwsgi");
|
||||
|
||||
ret = PyRun_InteractiveLoop(stdin, "uwsgi");
|
||||
#endif
|
||||
}
|
||||
if (up.pyshell_oneshot) {
|
||||
exit(UWSGI_DE_HIJACKED_CODE);
|
||||
}
|
||||
@@ -1702,7 +1711,6 @@ void uwsgi_python_hijack(void) {
|
||||
if (ret == 0) {
|
||||
exit(UWSGI_QUIET_CODE);
|
||||
}
|
||||
#endif
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_python up;
|
||||
extern struct uwsgi_plugin python_plugin;
|
||||
|
||||
PyObject *py_uwsgi_signal_wait(PyObject * self, PyObject * args) {
|
||||
|
||||
@@ -210,26 +211,6 @@ PyObject *py_uwsgi_add_cron(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
|
||||
PyObject *py_uwsgi_add_probe(PyObject * self, PyObject * args) {
|
||||
|
||||
uint8_t uwsgi_signal;
|
||||
int timeout = 0;
|
||||
int freq = 0;
|
||||
char *probe, *probe_args;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "Bss|ii:add_probe", &uwsgi_signal, &probe, &probe_args, &timeout, &freq)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (uwsgi_add_probe(uwsgi_signal, probe, probe_args, timeout, freq))
|
||||
return PyErr_Format(PyExc_ValueError, "unable to add probe");
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PyObject *py_uwsgi_add_timer(PyObject * self, PyObject * args) {
|
||||
|
||||
uint8_t uwsgi_signal;
|
||||
@@ -414,7 +395,7 @@ PyObject *py_uwsgi_register_rpc(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
|
||||
if (uwsgi_register_rpc(name, 0, argc, func)) {
|
||||
if (uwsgi_register_rpc(name, &python_plugin, argc, func)) {
|
||||
return PyErr_Format(PyExc_ValueError, "unable to register rpc function");
|
||||
}
|
||||
|
||||
@@ -2444,7 +2425,6 @@ static PyMethodDef uwsgi_advanced_methods[] = {
|
||||
{"signal_received", py_uwsgi_signal_received, METH_VARARGS, ""},
|
||||
{"add_file_monitor", py_uwsgi_add_file_monitor, METH_VARARGS, ""},
|
||||
{"add_timer", py_uwsgi_add_timer, METH_VARARGS, ""},
|
||||
{"add_probe", py_uwsgi_add_probe, METH_VARARGS, ""},
|
||||
{"add_rb_timer", py_uwsgi_add_rb_timer, METH_VARARGS, ""},
|
||||
{"add_cron", py_uwsgi_add_cron, METH_VARARGS, ""},
|
||||
|
||||
@@ -2946,7 +2926,7 @@ PyObject *py_uwsgi_cache_get(PyObject * self, PyObject * args) {
|
||||
|
||||
uint64_t vallen = 0;
|
||||
UWSGI_RELEASE_GIL
|
||||
char *value = uwsgi_cache_magic_get(key, keylen, &vallen, cache);
|
||||
char *value = uwsgi_cache_magic_get(key, keylen, &vallen, NULL, cache);
|
||||
UWSGI_GET_GIL
|
||||
if (value) {
|
||||
// in python 3.x we return bytes
|
||||
|
||||
@@ -106,7 +106,7 @@ struct uwsgi_python {
|
||||
|
||||
char *test_module;
|
||||
|
||||
int pyshell;
|
||||
char *pyshell;
|
||||
int pyshell_oneshot;
|
||||
|
||||
|
||||
@@ -268,10 +268,6 @@ struct uwsgi_buffer *uwsgi_python_exception_repr(struct wsgi_request *);
|
||||
struct uwsgi_buffer *uwsgi_python_backtrace(struct wsgi_request *);
|
||||
void uwsgi_python_exception_log(struct wsgi_request *);
|
||||
|
||||
#ifdef UWSGI_PYPY
|
||||
#undef UWSGI_MINTERPRETERS
|
||||
#endif
|
||||
|
||||
#define py_current_wsgi_req() current_wsgi_req();\
|
||||
if (!wsgi_req) {\
|
||||
return PyErr_Format(PyExc_SystemError, "you can call uwsgi api function only from the main callable");\
|
||||
|
||||
@@ -42,6 +42,9 @@ if not 'UWSGI_PYTHON_NOLIB' in os.environ:
|
||||
if not os.path.exists(libpath):
|
||||
libpath = '%s/libpython%s.a' % (libdir, version)
|
||||
LIBS.append(libpath)
|
||||
# hack for messy linkers/compilers
|
||||
if '-lutil' in LIBS:
|
||||
LIBS.append('-lutil')
|
||||
else:
|
||||
try:
|
||||
LDFLAGS.append("-L%s" % sysconfig.get_config_var('LIBDIR'))
|
||||
|
||||
@@ -135,11 +135,34 @@ static PyObject *uwsgi_Input_close(uwsgi_Input *self, PyObject *args) {
|
||||
|
||||
static PyObject *uwsgi_Input_seek(uwsgi_Input *self, PyObject *args) {
|
||||
long pos = 0;
|
||||
int whence = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "l:seek", &pos)) {
|
||||
if (!uwsgi.post_buffering) {
|
||||
return PyErr_Format(PyExc_IOError, "seeking wsgi.input without post_buffering is IMPOSSIBLE !!!");
|
||||
}
|
||||
|
||||
if (!PyArg_ParseTuple(args, "l|i:seek", &pos, &whence)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
uwsgi_request_body_seek() uses SEEK_SET for positive value and SEEK_CUR for negative
|
||||
yous hould always try to transform the "pos" value to an absolute position.
|
||||
*/
|
||||
|
||||
// current
|
||||
if (whence == 1) {
|
||||
pos += self->wsgi_req->post_pos;
|
||||
}
|
||||
// end of stream
|
||||
if (whence == 2) {
|
||||
pos += self->wsgi_req->post_cl;
|
||||
}
|
||||
|
||||
if (pos < 0 || pos > (off_t)self->wsgi_req->post_cl) {
|
||||
return PyErr_Format(PyExc_IOError, "invalid seek position for wsgi.input");
|
||||
}
|
||||
|
||||
uwsgi_request_body_seek(self->wsgi_req, pos);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
@@ -151,6 +174,12 @@ static PyObject *uwsgi_Input_fileno(uwsgi_Input *self, PyObject *args) {
|
||||
return PyInt_FromLong(self->wsgi_req->fd);
|
||||
}
|
||||
|
||||
static PyObject *uwsgi_Input_tell(uwsgi_Input *self, PyObject *args) {
|
||||
|
||||
return PyLong_FromLong(self->wsgi_req->post_pos);
|
||||
}
|
||||
|
||||
|
||||
static PyMethodDef uwsgi_Input_methods[] = {
|
||||
{ "read", (PyCFunction)uwsgi_Input_read, METH_VARARGS, 0 },
|
||||
{ "readline", (PyCFunction)uwsgi_Input_readline, METH_VARARGS, 0 },
|
||||
@@ -158,6 +187,7 @@ static PyMethodDef uwsgi_Input_methods[] = {
|
||||
// add close to allow mod_wsgi compatibility
|
||||
{ "close", (PyCFunction)uwsgi_Input_close, METH_VARARGS, 0 },
|
||||
{ "seek", (PyCFunction)uwsgi_Input_seek, METH_VARARGS, 0 },
|
||||
{ "tell", (PyCFunction)uwsgi_Input_tell, METH_VARARGS, 0 },
|
||||
{ "fileno", (PyCFunction)uwsgi_Input_fileno, METH_VARARGS, 0 },
|
||||
{ NULL, NULL}
|
||||
};
|
||||
@@ -263,8 +293,6 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
|
||||
|
||||
struct uwsgi_app *wi;
|
||||
|
||||
int free_appid = 0;
|
||||
|
||||
if (wsgi_req->async_status == UWSGI_AGAIN) {
|
||||
wi = &uwsgi_apps[wsgi_req->app_id];
|
||||
UWSGI_GET_GIL
|
||||
@@ -300,29 +328,7 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (wsgi_req->appid_len == 0) {
|
||||
if (!uwsgi.ignore_script_name) {
|
||||
wsgi_req->appid = wsgi_req->script_name;
|
||||
wsgi_req->appid_len = wsgi_req->script_name_len;
|
||||
}
|
||||
|
||||
if (uwsgi.vhost) {
|
||||
wsgi_req->appid = uwsgi_concat3n(wsgi_req->host, wsgi_req->host_len, "|",1, wsgi_req->script_name, wsgi_req->script_name_len);
|
||||
wsgi_req->appid_len = wsgi_req->host_len + 1 + wsgi_req->script_name_len;
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("VirtualHost KEY=%.*s\n", wsgi_req->appid_len, wsgi_req->appid);
|
||||
#endif
|
||||
free_appid = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( (wsgi_req->app_id = uwsgi_get_app_id(wsgi_req->appid, wsgi_req->appid_len, 0)) == -1) {
|
||||
wsgi_req->app_id = uwsgi.default_app;
|
||||
if (uwsgi.no_default_app) {
|
||||
wsgi_req->app_id = -1;
|
||||
}
|
||||
if ( (wsgi_req->app_id = uwsgi_get_app_id(wsgi_req, wsgi_req->appid, wsgi_req->appid_len, 0)) == -1) {
|
||||
if (wsgi_req->dynamic) {
|
||||
// this part must be heavy locked in threaded modes
|
||||
if (uwsgi.threads > 1) {
|
||||
@@ -343,10 +349,6 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
}
|
||||
|
||||
if (free_appid) {
|
||||
free(wsgi_req->appid);
|
||||
}
|
||||
|
||||
if (wsgi_req->app_id == -1) {
|
||||
uwsgi_500(wsgi_req);
|
||||
uwsgi_log("--- no python application found, check your startup logs for errors ---\n");
|
||||
|
||||
@@ -58,11 +58,15 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
char *status_line = NULL;
|
||||
size_t status_line_len = 0;
|
||||
#ifdef PYTHREE
|
||||
PyObject *zero = NULL;
|
||||
PyObject *zero2 = NULL;
|
||||
if (self != Py_None) {
|
||||
PyObject *zero = PyUnicode_AsASCIIString(head);
|
||||
zero = PyUnicode_AsASCIIString(head);
|
||||
if (!zero) {
|
||||
return PyErr_Format(PyExc_TypeError, "http status string must be encodable in latin1");
|
||||
}
|
||||
status_line = PyBytes_AsString(zero);
|
||||
status_line_len = PyBytes_Size(zero);
|
||||
Py_DECREF(zero);
|
||||
}
|
||||
else {
|
||||
status_line = PyBytes_AsString(head);
|
||||
@@ -73,9 +77,15 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
status_line_len = PyString_Size(head);
|
||||
#endif
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, status_line, status_line_len)) {
|
||||
#ifdef PYTHREE
|
||||
Py_DECREF(zero);
|
||||
#endif
|
||||
return PyErr_Format(PyExc_TypeError, "unable to set HTTP status line");
|
||||
}
|
||||
|
||||
#ifdef PYTHREE
|
||||
Py_DECREF(zero);
|
||||
#endif
|
||||
|
||||
headers = PyTuple_GetItem(args, 1);
|
||||
if (!headers) {
|
||||
@@ -125,10 +135,12 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
|
||||
#ifdef PYTHREE
|
||||
if (self != Py_None) {
|
||||
PyObject *zero = PyUnicode_AsASCIIString(h_key);
|
||||
zero = PyUnicode_AsASCIIString(h_key);
|
||||
if (!zero) {
|
||||
return PyErr_Format(PyExc_TypeError, "http header must be encodable in latin1");
|
||||
}
|
||||
k = PyBytes_AsString(zero);
|
||||
kl = PyBytes_Size(zero);
|
||||
Py_DECREF(zero);
|
||||
}
|
||||
else {
|
||||
k = PyBytes_AsString(h_key);
|
||||
@@ -141,10 +153,12 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
|
||||
#ifdef PYTHREE
|
||||
if (self != Py_None) {
|
||||
PyObject *zero = PyUnicode_AsASCIIString(h_value);
|
||||
v = PyBytes_AsString(zero);
|
||||
vl = PyBytes_Size(zero);
|
||||
Py_DECREF(zero);
|
||||
zero2 = PyUnicode_AsASCIIString(h_value);
|
||||
if (!zero2) {
|
||||
return PyErr_Format(PyExc_TypeError, "http header must be encodable in latin1");
|
||||
}
|
||||
v = PyBytes_AsString(zero2);
|
||||
vl = PyBytes_Size(zero2);
|
||||
}
|
||||
else {
|
||||
v = PyBytes_AsString(h_value);
|
||||
@@ -156,9 +170,18 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
#endif
|
||||
|
||||
if (uwsgi_response_add_header(wsgi_req, k, kl, v, vl)) {
|
||||
#ifdef PYTHREE
|
||||
Py_DECREF(zero);
|
||||
Py_DECREF(zero2);
|
||||
#endif
|
||||
return PyErr_Format(PyExc_TypeError, "unable to add header to the response");
|
||||
}
|
||||
|
||||
#ifdef PYTHREE
|
||||
Py_DECREF(zero);
|
||||
Py_DECREF(zero2);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
if (up.start_response_nodelay) {
|
||||
|
||||
@@ -463,7 +463,7 @@ VALUE rack_uwsgi_cache_get(int argc, VALUE *argv, VALUE *class) {
|
||||
}
|
||||
|
||||
uint64_t vallen = 0;;
|
||||
char *value = uwsgi_cache_magic_get(key, keylen, &vallen, cache);
|
||||
char *value = uwsgi_cache_magic_get(key, keylen, &vallen, NULL, cache);
|
||||
if (value) {
|
||||
VALUE res = rb_str_new(value, vallen);
|
||||
free(value);
|
||||
@@ -774,7 +774,7 @@ VALUE uwsgi_ruby_register_rpc(int argc, VALUE *argv, VALUE *class) {
|
||||
void *func = (void *) argv[1];
|
||||
|
||||
|
||||
if (uwsgi_register_rpc(name, rack_plugin.modifier1, rb_argc, func)) {
|
||||
if (uwsgi_register_rpc(name, &rack_plugin, rb_argc, func)) {
|
||||
clear:
|
||||
rb_raise(rb_eRuntimeError, "unable to register rpc function");
|
||||
return Qnil;
|
||||
|
||||
@@ -5,6 +5,22 @@ extern struct uwsgi_server uwsgi;
|
||||
struct uwsgi_rack ur;
|
||||
struct uwsgi_plugin rack_plugin;
|
||||
|
||||
static void uwsgi_opt_rbshell(char *opt, char *value, void *foobar) {
|
||||
|
||||
uwsgi.honour_stdin = 1;
|
||||
if (value) {
|
||||
ur.rbshell = value;
|
||||
}
|
||||
else {
|
||||
ur.rbshell = "";
|
||||
}
|
||||
|
||||
if (!strcmp("rbshell-oneshot", opt)) {
|
||||
ur.rb_shell_oneshot = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_option uwsgi_rack_options[] = {
|
||||
|
||||
{"rails", required_argument, 0, "load a rails <= 2.x app", uwsgi_opt_set_str, &ur.rails, UWSGI_OPT_POST_BUFFERING},
|
||||
@@ -29,7 +45,8 @@ struct uwsgi_option uwsgi_rack_options[] = {
|
||||
|
||||
{"rvm-path", required_argument, 0, "search for rvm in the specified directory", uwsgi_opt_add_string_list, &ur.rvm_path, 0},
|
||||
|
||||
{"rbshell", optional_argument, 0, "run a ruby/irb shell", uwsgi_opt_true, &ur.rb_shell, 0},
|
||||
{"rbshell", optional_argument, 0, "run a ruby/irb shell", uwsgi_opt_rbshell, NULL, 0},
|
||||
{"rbshell-oneshot", no_argument, 0, "set ruby/irb shell (one shot)", uwsgi_opt_rbshell, NULL, 0},
|
||||
|
||||
#ifdef RUBY19
|
||||
{"rb-threads", required_argument, 0, "set the number of ruby threads to run", uwsgi_opt_set_int, &ur.rb_threads, 0},
|
||||
@@ -1029,7 +1046,51 @@ int uwsgi_rack_mount_app(char *mountpoint, char *app) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
void uwsgi_rack_hijack(void) {
|
||||
VALUE run_irb(VALUE arg) {
|
||||
rb_funcall(rb_cObject, rb_intern("require"), 1, rb_str_new2("irb"));
|
||||
VALUE irb = rb_const_get(rb_cObject, rb_intern("IRB"));
|
||||
return rb_funcall(irb, rb_intern("start"), 0);
|
||||
}
|
||||
|
||||
static void uwsgi_rack_hijack(void) {
|
||||
if (ur.rb_shell_oneshot && uwsgi.workers[uwsgi.mywid].hijacked_count > 0) {
|
||||
uwsgi.workers[uwsgi.mywid].hijacked = 0;
|
||||
return;
|
||||
}
|
||||
if (ur.rbshell && uwsgi.mywid == 1) {
|
||||
uwsgi.workers[uwsgi.mywid].hijacked = 1;
|
||||
uwsgi.workers[uwsgi.mywid].hijacked_count++;
|
||||
// re-map stdin to stdout and stderr if we are logging to a file
|
||||
if (uwsgi.logfile) {
|
||||
if (dup2(0, 1) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
}
|
||||
if (dup2(0, 2) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
}
|
||||
}
|
||||
int ret = -1;
|
||||
int error = 0;
|
||||
if (ur.rbshell[0] != 0) {
|
||||
rb_eval_string(ur.rbshell);
|
||||
}
|
||||
else {
|
||||
rb_protect( run_irb, 0, &error ) ;
|
||||
if (error) {
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (ur.rb_shell_oneshot) {
|
||||
exit(UWSGI_DE_HIJACKED_CODE);
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
exit(UWSGI_QUIET_CODE);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_rack_mule(char *opt) {
|
||||
|
||||
@@ -45,7 +45,8 @@ struct uwsgi_rack {
|
||||
|
||||
pthread_mutex_t gvl;
|
||||
|
||||
int rb_shell;
|
||||
char *rbshell;
|
||||
int rb_shell_oneshot;
|
||||
int app_id;
|
||||
|
||||
int unprotected;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user