mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7108ee1ba0 | ||
|
|
cf8e68f7a0 | ||
|
|
a9510c2209 | ||
|
|
b2be5943a8 | ||
|
|
8f19fe292e | ||
|
|
d3e7668d0a | ||
|
|
88e67a74e5 | ||
|
|
7fecda1a23 | ||
|
|
56b6fa88f9 | ||
|
|
e847cfe4bc | ||
|
|
1a854ae3ba | ||
|
|
c75180bf95 | ||
|
|
d496450b84 | ||
|
|
d2636ed133 | ||
|
|
59de0c2085 | ||
|
|
4b7df29bd1 | ||
|
|
b099ba6a29 | ||
|
|
164069e194 | ||
|
|
b3e4ff8613 | ||
|
|
3eb5ec3543 | ||
|
|
c3c698a615 | ||
|
|
ac6d2f3e83 | ||
|
|
d1f1b8a43a | ||
|
|
85586a621c | ||
|
|
1a384a334f | ||
|
|
8901afded5 | ||
|
|
ab12703a11 | ||
|
|
9992b4c964 | ||
|
|
9a2dbd08cd | ||
|
|
5f92a00b71 | ||
|
|
7bd9d51217 | ||
|
|
80c649aa40 | ||
|
|
6c8fe2cc53 | ||
|
|
dcc7167d75 | ||
|
|
e3a52e4039 | ||
|
|
498f6162f7 | ||
|
|
33d85d3670 | ||
|
|
afbf5b9633 | ||
|
|
a8505be6c0 | ||
|
|
4a07632569 | ||
|
|
d4f0589c39 | ||
|
|
a9989d46fc | ||
|
|
99cf598c0c | ||
|
|
a6af22b8f0 | ||
|
|
0961d61a88 | ||
|
|
7b76a2d749 | ||
|
|
b516f1d3ec | ||
|
|
8fdef7a1f9 | ||
|
|
10258db4ae | ||
|
|
621c9523cf | ||
|
|
c415adab28 | ||
|
|
7fef1048b3 | ||
|
|
1e7aaeeeed | ||
|
|
c5b4564001 | ||
|
|
a9127c8d79 | ||
|
|
a0f7a5c70f | ||
|
|
ecf3cae35b | ||
|
|
d553bc8014 | ||
|
|
a1553d3632 | ||
|
|
bb42ae1b4a | ||
|
|
61ac2efe0e | ||
|
|
1c0a3ec413 | ||
|
|
8b7e93385b | ||
|
|
c742624054 | ||
|
|
8011f0615d | ||
|
|
8096b2198f | ||
|
|
3556bd5283 | ||
|
|
26710694af | ||
|
|
0f397eeb55 | ||
|
|
bf929398a9 | ||
|
|
4f8a0f753e | ||
|
|
7db5da9566 | ||
|
|
4d1389805c | ||
|
|
ee87e2b946 | ||
|
|
6356d78768 | ||
|
|
afdf7e740e | ||
|
|
51ce3ddf78 | ||
|
|
192186056e | ||
|
|
336a7febd7 | ||
|
|
63e73d1b73 | ||
|
|
a02ab9a723 | ||
|
|
95f15ab9dd | ||
|
|
5d0ea0066a | ||
|
|
9ff6b2da9b | ||
|
|
6ac7e27847 | ||
|
|
4ed1c5e747 | ||
|
|
bae3bc096f | ||
|
|
9d73683de2 | ||
|
|
f5fec0ab71 | ||
|
|
9909ab10c4 | ||
|
|
65cff01fee | ||
|
|
10190a3012 | ||
|
|
79ab696f4e |
@@ -1,58 +0,0 @@
|
||||
d3850b52334a91d005b0fe45e1e38ba0997a1fb8 no_server mode
|
||||
2d8a617299153ed2efa6ecee7920e9d36c29e0f5 0.9.5beta1
|
||||
04722a2d0121080d14a64df097c278860db5ce8a 0.9.5rc1
|
||||
820cc64ab296dc4589ef72a33a6b804c22a0430c 0.9.5rc2
|
||||
b0db39cfad5ac6d4f00bbb3f9c57cf73206e2afb 0.9.5
|
||||
9f8b98ad1dfa51b86b13fa624c65f73523075fc4 0.9.5.1
|
||||
a83e7a482e65befcfbb0e24af8cd5d15190acdd7 0.9.6-rc1
|
||||
b8f67c6cd0d62f864db9b2b265b4e260ad7d873c 0.9.6-rc2
|
||||
35918dd4b3771158b2b57410613ef029e08bbd60 0.9.6
|
||||
5f25d1f97f9dde3e391a668c1c610a52a5db8244 0.9.6.1
|
||||
ef31fc61ac48018c464f28ebfdf865b96bf83f18 0.9.6.2
|
||||
9e100c1f085034396cec586f0c76ad3f9800d1a5 0.9.7-beta1
|
||||
ff4111eb8f55b958ec91c70163e10f3372a9b94d 0.9.7-rc1
|
||||
eb8aff2926230bb114fb90f67203440a2c534bf1 0.9.7-rc2
|
||||
311eef929ec8fd0a5dc8c16531afb7bb42d36d01 0.9.7-rc3
|
||||
4b50c04e414f1d9ab8b0b5910aba83d09ac21abb 0.9.7
|
||||
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
|
||||
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
|
||||
0000000000000000000000000000000000000000 0.9.7.1
|
||||
0000000000000000000000000000000000000000 0.9.7.1
|
||||
486e7760bcbc2191ddb9b4aee6c98dbd5fc4c754 0.9.7.1
|
||||
a5f13497b39269621f8f1e56e14d2cc141452e79 0.9.7.2
|
||||
d1e57707f6317f134fea7d12f6588d8690f74f3f 0.9.8-rc1
|
||||
e91bc724325e14c13b8f548c0b6a315c48a1c32a 0.9.8-rc2
|
||||
4fb424d52f226a0a087fea89709f5eb540e03f25 0.9.8-rc3
|
||||
0f1f3924ee5309a9990d9af1ffc68846e3dfb31b 0.9.8-rc4
|
||||
42efe1f329005618c8b44f901979ebcecd5216fb 0.9.8
|
||||
fd8477b6348faf16588106055ca59df1c488f76a 0.9.8.1
|
||||
7169ef1d68d3dab4737bcc3f9e082839e5a06cc1 0.9.8.2
|
||||
f4d3c4dcd7a63e21fcc9d8d567374c69935178bd 0.9.8.3
|
||||
6945ee03c7ea95eb19217ef1e1fb17d9ae26adbc 0.9.9-beta1
|
||||
fb168b0b86169219aa9b8e40f0caa6297cf34dbc 0.9.9-rc1
|
||||
6aa667612019fcff8e68af9469f73aff6fa378a8 0.9.9-rc2
|
||||
376ffd8f190623e5e2521fe9fa64bf03c31e71be 0.9.9
|
||||
7048ae11cfc8453c6bb599af3c0dfacd7ebae43c 1.0-rc1
|
||||
7a4e021ea7ba2953e474326612c3bb82d6817f0e 1.0-rc2
|
||||
4e4e781ef89ac33e71a7e92741d54549240ed156 1.0-rc3
|
||||
24f7e260ea345c2cd73e2fd8191dddbd1b039062 1.0-rc4
|
||||
043ba93dd69cf6924e98db3cb9a8759cce997367 1.0-rc5
|
||||
a2b8f25fd17ed7424d1470a287d0b3144d2a12c8 1.0-rc6
|
||||
a3ca2e8e27c5c12c44ba0cacb4de4cb51377f184 1.0-rc7
|
||||
365e2514cc19f0366365318f12a1d63113b02924 1.0-rc8
|
||||
5da6fe43a8c29056bc9442c684615e11a3699795 1.0-rc9
|
||||
af490b8c30f83bc5fb6f3837a760981474647755 1.0-rc10
|
||||
3c70927335856883283fe4db448e092cecc0ccdb 1.0
|
||||
8fe7bb792399cb6e6a24e20551f4149409660363 1.0.1
|
||||
1d1702789710ec1c20613d2490b14f70756e67ec 1.1-rc1
|
||||
901f0cb5de36ea907b26d64ac9ce54605ec531d2 1.1-rc2
|
||||
ede5c664978bb40e476e8d4a5789562928f28507 1.1-rc3
|
||||
ef99144291f06822d026e981d5d856cbec14d867 1.1-rc4
|
||||
e1568fd16b7b586cc72deb4dfccbbe64ae0b84df 1.1
|
||||
24c8fe5a26e557db41cf1cee45b8964d5885e484 1.2-rc1
|
||||
29de0fb320bc0a1ce84972f9f249360e315d3c10 1.2-rc2
|
||||
c3cdecbf2bac591336baddd14f9ac22e18d6e200 1.2
|
||||
14524da00a8b382dffb1d16a0e70cdf4a946f369 1.3-rc2
|
||||
883b946db9038372cb1d76cb1d328a3093140e7b 1.3-rc3
|
||||
aeea5a5d2e8b62ad55e23d539e1be02f2b6962af 1.3-rc4
|
||||
620e0cb6ccdb0ce27561b4240cb3a0ef4c3527fd 1.3
|
||||
+1
-1
@@ -16,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, spooler, cheaper_busyness, symcall, transformation_tofile, transformation_gzip, transformation_chunked
|
||||
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, transformation_chunked, transformation_offload, router_memcached, router_redis, router_hash
|
||||
as_shared_library = false
|
||||
|
||||
locking = auto
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = psgi,coroae
|
||||
inherit = base
|
||||
@@ -1,3 +1,4 @@
|
||||
[uwsgi]
|
||||
main_plugin = python,gevent
|
||||
inherit = base
|
||||
debug = false
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
"""
|
||||
Greenlets support
|
||||
|
||||
simply --pypy-exec this file to enable PyPy's greenlet mode
|
||||
|
||||
Example:
|
||||
|
||||
uwsgi --http-socket :9090 --pypy-home /opt/pypy --pypy-wsgi werkzeug.testapp:test_app --pypy-exec contrib/pypy/uwsgi_pypy_greenlets.py --async 8
|
||||
"""
|
||||
|
||||
import greenlet
|
||||
|
||||
uwsgi_pypy_greenlets = {}
|
||||
|
||||
def uwsgi_pypy_greenlet_wrapper():
|
||||
lib.async_schedule_to_req_green()
|
||||
|
||||
@ffi.callback("void()")
|
||||
def uwsgi_pypy_greenlet_schedule():
|
||||
id = lib.uwsgi.wsgi_req.async_id
|
||||
modifier1 = lib.uwsgi.wsgi_req.uh.modifier1;
|
||||
|
||||
# generate a new greenlet
|
||||
if not lib.uwsgi.wsgi_req.suspended:
|
||||
uwsgi_pypy_greenlets[id] = greenlet.greenlet(uwsgi_pypy_greenlet_wrapper)
|
||||
lib.uwsgi.wsgi_req.suspended = 1
|
||||
|
||||
# this is called in the main stack
|
||||
if lib.uwsgi.p[modifier1].suspend:
|
||||
lib.uwsgi.p[modifier1].suspend(ffi.NULL)
|
||||
|
||||
# let's switch
|
||||
uwsgi_pypy_greenlets[id].switch()
|
||||
|
||||
# back to the main stack
|
||||
if lib.uwsgi.p[modifier1].resume:
|
||||
lib.uwsgi.p[modifier1].resume(ffi.NULL)
|
||||
|
||||
@ffi.callback("void(struct wsgi_request *)")
|
||||
def uwsgi_pypy_greenlet_switch(wsgi_req):
|
||||
id = wsgi_req.async_id
|
||||
modifier1 = wsgi_req.uh.modifier1;
|
||||
|
||||
# this is called in the current greenlet
|
||||
if lib.uwsgi.p[modifier1].suspend:
|
||||
lib.uwsgi.p[modifier1].suspend(wsgi_req)
|
||||
|
||||
uwsgi_pypy_main_greenlet.switch()
|
||||
|
||||
# back to the greenlet
|
||||
if lib.uwsgi.p[modifier1].resume:
|
||||
lib.uwsgi.p[modifier1].resume(wsgi_req)
|
||||
|
||||
# update current running greenlet
|
||||
lib.uwsgi.wsgi_req = wsgi_req
|
||||
|
||||
if lib.uwsgi.async <= 1:
|
||||
raise Exception("pypy greenlets require async mode !!!")
|
||||
lib.uwsgi.schedule_to_main = uwsgi_pypy_greenlet_switch
|
||||
lib.uwsgi.schedule_to_req = uwsgi_pypy_greenlet_schedule
|
||||
uwsgi_pypy_main_greenlet = greenlet.getcurrent()
|
||||
@@ -0,0 +1,15 @@
|
||||
# uWSGI - Emperor
|
||||
#
|
||||
|
||||
description "uWSGI Emperor"
|
||||
|
||||
start on runlevel [2345]
|
||||
stop on runlevel [!2345]
|
||||
|
||||
respawn
|
||||
|
||||
env LOGTO=/tmp/uwsgi.log
|
||||
env BINPATH=/home/foo/uwsgi/uwsgi
|
||||
env VASSALS=/etc/uwsgi
|
||||
|
||||
exec $BINPATH --emperor $VASSALS --logto $LOGTO
|
||||
@@ -11,7 +11,6 @@ respawn
|
||||
env LOGTO=/tmp/uwsgi.log
|
||||
env BINPATH=/home/foo/uwsgi/uwsgi
|
||||
|
||||
# --no-orphans avoid workers without master
|
||||
# --die-on-term could be a good idea
|
||||
exec $BINPATH --no-orphans --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -w simple_app --logto $LOGTO -M -p 4
|
||||
# --die-on-term is upstart friendly
|
||||
exec $BINPATH --die-on-term --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -w simple_app --logto $LOGTO -M -p 4
|
||||
|
||||
|
||||
@@ -206,7 +206,11 @@ int async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
|
||||
}
|
||||
|
||||
static int async_wait_fd_read(int fd, int timeout) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
wsgi_req->async_ready_fd = 0;
|
||||
|
||||
if (async_add_fd_read(wsgi_req, fd, timeout)) {
|
||||
return -1;
|
||||
}
|
||||
@@ -222,6 +226,8 @@ static int async_wait_fd_read(int fd, int timeout) {
|
||||
|
||||
void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
|
||||
|
||||
wsgi_req->async_ready_fd = 0;
|
||||
|
||||
if (timeout > 0 && wsgi_req->async_timeout == NULL) {
|
||||
wsgi_req->async_timeout = uwsgi_add_rb_timer(uwsgi.rb_async_timeouts, uwsgi_now() + timeout, wsgi_req);
|
||||
}
|
||||
@@ -265,6 +271,9 @@ int async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
|
||||
|
||||
static int async_wait_fd_write(int fd, int timeout) {
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
wsgi_req->async_ready_fd = 0;
|
||||
|
||||
if (async_add_fd_write(wsgi_req, fd, timeout)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -171,6 +171,41 @@ static void cache_sync_hook(char *k, uint16_t kl, char *v, uint16_t vl, void *da
|
||||
}
|
||||
}
|
||||
|
||||
static void uwsgi_cache_add_items(struct uwsgi_cache *uc) {
|
||||
struct uwsgi_string_list *usl = uwsgi.add_cache_item;
|
||||
while(usl) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
char *key = usl->value;
|
||||
uint16_t key_len = usl->len;
|
||||
if (space) {
|
||||
// need to skip ?
|
||||
if (uwsgi_strncmp(uc->name, uc->name_len, usl->value, space-usl->value)) {
|
||||
goto next;
|
||||
}
|
||||
key = space+1;
|
||||
key_len = usl->len - ((space-usl->value)+1);
|
||||
}
|
||||
char *value = strchr(key, '=');
|
||||
if (!value) {
|
||||
uwsgi_log("[cache] unable to store item %s\n", usl->value);
|
||||
goto next;
|
||||
}
|
||||
key_len = value - key;
|
||||
value++;
|
||||
uint64_t len = (usl->value + usl->len) - value;
|
||||
uwsgi_wlock(uc->lock);
|
||||
if (!uwsgi_cache_set2(uc, key, key_len, value, len, 0, 0)) {
|
||||
uwsgi_log("[cache] stored \"%.*s\" in \"%s\"\n", key_len, key, uc->name);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[cache-error] unable to store \"%.*s\" in \"%s\"\n", key_len, key, uc->name);
|
||||
}
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
next:
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void uwsgi_cache_load_files(struct uwsgi_cache *uc) {
|
||||
|
||||
struct uwsgi_string_list *usl = uwsgi.load_file_in_cache;
|
||||
@@ -341,6 +376,8 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
|
||||
|
||||
uwsgi_cache_load_files(uc);
|
||||
|
||||
uwsgi_cache_add_items(uc);
|
||||
|
||||
}
|
||||
|
||||
static uint64_t uwsgi_cache_get_index(struct uwsgi_cache *uc, char *key, uint16_t keylen) {
|
||||
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
Chunked input implementation
|
||||
|
||||
--chunked-input-limit <bytes> (default 1MB)
|
||||
|
||||
--chunked-input-timeout <s> (default --socket-timeout)
|
||||
|
||||
chunk = uwsgi.chunked_read([timeout])
|
||||
|
||||
timeout = -1 (wait forever)
|
||||
timeout = 0 (default)
|
||||
|
||||
*/
|
||||
|
||||
static ssize_t uwsgi_chunked_input_recv(struct wsgi_request *wsgi_req, int timeout, int nb) {
|
||||
|
||||
if (timeout == 0) timeout = uwsgi.chunked_input_timeout;
|
||||
if (timeout == 0) timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
|
||||
|
||||
int ret = -1;
|
||||
|
||||
for(;;) {
|
||||
ssize_t rlen = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->chunked_input_buf->buf + wsgi_req->chunked_input_buf->pos, wsgi_req->chunked_input_buf->len - wsgi_req->chunked_input_buf->pos);
|
||||
if (rlen > 0) return rlen;
|
||||
if (rlen == 0) return -1;
|
||||
if (rlen < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
if (nb) return -1;
|
||||
goto wait;
|
||||
}
|
||||
uwsgi_error("uwsgi_chunked_input_recv()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
wait:
|
||||
ret = uwsgi.wait_read_hook(wsgi_req->fd, timeout);
|
||||
if (ret > 0) {
|
||||
rlen = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->chunked_input_buf->buf + wsgi_req->chunked_input_buf->pos, wsgi_req->chunked_input_buf->len - wsgi_req->chunked_input_buf->pos);
|
||||
if (rlen > 0) return rlen;
|
||||
if (rlen <= 0) return -1;
|
||||
}
|
||||
if (ret < 0) {
|
||||
uwsgi_error("uwsgi_chunked_input_recv()");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_chunked_readline(struct wsgi_request *wsgi_req) {
|
||||
size_t i;
|
||||
int found = 0;
|
||||
for(i=0;i<wsgi_req->chunked_input_buf->pos;i++) {
|
||||
if (found) {
|
||||
if (wsgi_req->chunked_input_buf->buf[i] == '\n') {
|
||||
// strtoul will stop at \r
|
||||
size_t num = strtoul(wsgi_req->chunked_input_buf->buf, NULL, 16);
|
||||
if (uwsgi_buffer_decapitate(wsgi_req->chunked_input_buf, i+1)) return -1;
|
||||
return num;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if ((wsgi_req->chunked_input_buf->buf[i] >= '0' && wsgi_req->chunked_input_buf->buf[i] <= '9') ||
|
||||
(wsgi_req->chunked_input_buf->buf[i] >= 'a' && wsgi_req->chunked_input_buf->buf[i] <= 'z') ||
|
||||
(wsgi_req->chunked_input_buf->buf[i] >= 'A' && wsgi_req->chunked_input_buf->buf[i] <= 'Z')) continue;
|
||||
if (wsgi_req->chunked_input_buf->buf[i] == '\r') { found = 1; continue; }
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
0 -> waiting for \r\n
|
||||
1 -> waiting for whole body
|
||||
|
||||
*/
|
||||
|
||||
char *uwsgi_chunked_read(struct wsgi_request *wsgi_req, size_t *len, int timeout, int nb) {
|
||||
char *ret;
|
||||
if (!wsgi_req->chunked_input_buf) {
|
||||
wsgi_req->chunked_input_buf = uwsgi_buffer_new(uwsgi.page_size);
|
||||
wsgi_req->chunked_input_buf->limit = uwsgi.chunked_input_limit;
|
||||
}
|
||||
|
||||
// the whole chunk stream has been consumed
|
||||
if (wsgi_req->chunked_input_complete) {
|
||||
*len = 0;
|
||||
return wsgi_req->chunked_input_buf->buf;
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
if (wsgi_req->chunked_input_need > 0 || wsgi_req->chunked_input_buf->pos == 0) {
|
||||
if (uwsgi_buffer_fix(wsgi_req->chunked_input_buf, uwsgi.page_size)) return NULL;
|
||||
ssize_t rlen = uwsgi_chunked_input_recv(wsgi_req, timeout, nb);
|
||||
if (rlen <= 0) return NULL;
|
||||
// update buffer position
|
||||
wsgi_req->chunked_input_buf->pos += rlen;
|
||||
|
||||
if (wsgi_req->chunked_input_need > 0) {
|
||||
if ((size_t)rlen > wsgi_req->chunked_input_need) {
|
||||
wsgi_req->chunked_input_need = 0;
|
||||
}
|
||||
else {
|
||||
wsgi_req->chunked_input_need -= rlen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wsgi_req->chunked_input_need > 0) continue;
|
||||
|
||||
// ok we have a frame, let's parse it
|
||||
if (wsgi_req->chunked_input_buf->pos > 0) {
|
||||
switch(wsgi_req->chunked_input_parser_status) {
|
||||
case 0:
|
||||
wsgi_req->chunked_input_chunk_len = uwsgi_chunked_readline(wsgi_req);
|
||||
if (wsgi_req->chunked_input_chunk_len == -2) {
|
||||
break;
|
||||
}
|
||||
else if (wsgi_req->chunked_input_chunk_len < 0) {
|
||||
return NULL;
|
||||
}
|
||||
else if (wsgi_req->chunked_input_chunk_len == 0) {
|
||||
*len = 0;
|
||||
wsgi_req->chunked_input_complete = 1;
|
||||
return wsgi_req->chunked_input_buf->buf;
|
||||
}
|
||||
// if here the buffer has been already decapitated
|
||||
if ((size_t)(wsgi_req->chunked_input_chunk_len+2) > wsgi_req->chunked_input_buf->pos) {
|
||||
wsgi_req->chunked_input_need = (wsgi_req->chunked_input_chunk_len+2) - wsgi_req->chunked_input_buf->pos;
|
||||
wsgi_req->chunked_input_parser_status = 1;
|
||||
break;
|
||||
}
|
||||
*len = wsgi_req->chunked_input_chunk_len;
|
||||
ret = wsgi_req->chunked_input_buf->buf;
|
||||
if (uwsgi_buffer_decapitate(wsgi_req->chunked_input_buf, wsgi_req->chunked_input_chunk_len+2)) return NULL;
|
||||
return ret;
|
||||
case 1:
|
||||
if ((size_t)(wsgi_req->chunked_input_chunk_len+2) > wsgi_req->chunked_input_buf->pos) {
|
||||
wsgi_req->chunked_input_need = (wsgi_req->chunked_input_chunk_len+2) - wsgi_req->chunked_input_buf->pos;
|
||||
break;
|
||||
}
|
||||
*len = wsgi_req->chunked_input_chunk_len;
|
||||
ret = wsgi_req->chunked_input_buf->buf;
|
||||
if (uwsgi_buffer_decapitate(wsgi_req->chunked_input_buf, wsgi_req->chunked_input_chunk_len+2)) return NULL;
|
||||
wsgi_req->chunked_input_parser_status = 0;
|
||||
return ret;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
int main() {}
|
||||
@@ -169,6 +169,9 @@ void uwsgi_init_default() {
|
||||
uwsgi.wait_write_hook = uwsgi_simple_wait_write_hook;
|
||||
|
||||
uwsgi_websockets_init();
|
||||
|
||||
// 1 MB default limit
|
||||
uwsgi.chunked_input_limit = 1024*1024;
|
||||
}
|
||||
|
||||
void uwsgi_setup_reload() {
|
||||
|
||||
@@ -1078,3 +1078,22 @@ void uwsgi_add_safe_fd(int fd) {
|
||||
uwsgi.safe_fds[uwsgi.safe_fds_cnt] = fd;
|
||||
uwsgi.safe_fds_cnt++;
|
||||
}
|
||||
|
||||
int uwsgi_is_again() {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_disconnect(struct wsgi_request *wsgi_req) {
|
||||
if (wsgi_req->socket) {
|
||||
wsgi_req->socket->proto_close(wsgi_req);
|
||||
}
|
||||
wsgi_req->fd_closed = 1;
|
||||
}
|
||||
|
||||
int uwsgi_ready_fd(struct wsgi_request *wsgi_req) {
|
||||
if (wsgi_req->async_ready_fd) return wsgi_req->async_last_ready_fd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -485,6 +485,18 @@ int master_loop(char **argv, char **environ) {
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_check_touches(uwsgi.touch_exec);
|
||||
// update signal touches
|
||||
usl = uwsgi.touch_signal;
|
||||
while(usl) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
usl->len = strlen(usl->value);
|
||||
usl->custom_ptr = space + 1;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_check_touches(uwsgi.touch_signal);
|
||||
|
||||
// setup cheaper algos (can be stacked)
|
||||
uwsgi.cheaper_algo = uwsgi_cheaper_algo_spare;
|
||||
@@ -769,6 +781,12 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi_log_verbose("[uwsgi-touch-exec] running %s\n", touched);
|
||||
}
|
||||
}
|
||||
touched = uwsgi_check_touches(uwsgi.touch_signal);
|
||||
if (touched) {
|
||||
uint8_t signum = atoi(touched);
|
||||
uwsgi_route_signal(signum);
|
||||
uwsgi_log_verbose("[uwsgi-touch-signal] raising %u\n", signum);
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
|
||||
@@ -197,6 +197,14 @@ void uwsgi_master_check_mules_deadline() {
|
||||
uwsgi.mules[i].harakiri = 0;
|
||||
}
|
||||
}
|
||||
// user harakiri
|
||||
if (uwsgi.mules[i].user_harakiri > 0) {
|
||||
if (uwsgi.mules[i].user_harakiri < (time_t) uwsgi.current_time) {
|
||||
uwsgi_log("*** HARAKIRI ON MULE %d (pid: %d) ***\n", i + 1, uwsgi.mules[i].pid);
|
||||
kill(uwsgi.mules[i].pid, SIGKILL);
|
||||
uwsgi.mules[i].user_harakiri = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,6 +216,11 @@ void uwsgi_master_check_spoolers_deadline() {
|
||||
kill(uspool->pid, SIGKILL);
|
||||
uspool->harakiri = 0;
|
||||
}
|
||||
if (uspool->user_harakiri > 0 && uspool->user_harakiri < (time_t) uwsgi.current_time) {
|
||||
uwsgi_log("*** HARAKIRI ON THE SPOOLER (pid: %d) ***\n", uspool->pid);
|
||||
kill(uspool->pid, SIGKILL);
|
||||
uspool->user_harakiri = 0;
|
||||
}
|
||||
uspool = uspool->next;
|
||||
}
|
||||
}
|
||||
|
||||
+16
-2
@@ -696,8 +696,17 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
while (ud) {
|
||||
if (uwsgi_stats_object_open(us))
|
||||
goto end;
|
||||
if (uwsgi_stats_keyval_comma(us, "cmd", ud->command))
|
||||
|
||||
// allocate 2x the size of original command
|
||||
// in case we need to escape all chars
|
||||
char *cmd = uwsgi_malloc(strlen(ud->command)*2);
|
||||
escape_json(ud->command, strlen(ud->command), cmd);
|
||||
if (uwsgi_stats_keyval_comma(us, "cmd", cmd)) {
|
||||
free(cmd);
|
||||
goto end;
|
||||
}
|
||||
free(cmd);
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) (ud->pid < 0) ? 0 : ud->pid))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong(us, "respawns", (unsigned long long) ud->respawns ? 0 : ud->respawns))
|
||||
@@ -1106,8 +1115,13 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
if (uwsgi_stats_keyslong_comma(us, "week", (long long) ucron->week))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keyval_comma(us, "command", ucron->command))
|
||||
char *cmd = uwsgi_malloc(strlen(ucron->command)*2);
|
||||
escape_json(ucron->command, strlen(ucron->command), cmd);
|
||||
if (uwsgi_stats_keyval_comma(us, "command", cmd)) {
|
||||
free(cmd);
|
||||
goto end;
|
||||
}
|
||||
free(cmd);
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "unique", (unsigned long long) ucron->unique))
|
||||
goto end;
|
||||
|
||||
+92
-2
@@ -58,6 +58,22 @@ static int uwsgi_offload_enqueue(struct wsgi_request *wsgi_req, struct uwsgi_off
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
pipe offload engine:
|
||||
fd -> the file descriptor to read from
|
||||
len -> amount of data to transfer
|
||||
|
||||
*/
|
||||
|
||||
static int u_offload_pipe_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
|
||||
|
||||
if (uor->fd < 0 || !uor->len) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
memory offload engine:
|
||||
@@ -66,7 +82,7 @@ static int uwsgi_offload_enqueue(struct wsgi_request *wsgi_req, struct uwsgi_off
|
||||
|
||||
*/
|
||||
|
||||
int u_offload_memory_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
|
||||
static int u_offload_memory_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
|
||||
|
||||
if (!uor->buf || !uor->len) {
|
||||
return -1;
|
||||
@@ -83,7 +99,7 @@ int u_offload_memory_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload
|
||||
|
||||
*/
|
||||
|
||||
int u_offload_transfer_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
|
||||
static int u_offload_transfer_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
|
||||
|
||||
if (!uor->name) {
|
||||
return -1;
|
||||
@@ -343,6 +359,71 @@ static int u_offload_sendfile_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
pipe offloading
|
||||
status:
|
||||
0 -> waiting for data on fd
|
||||
1 -> waiting for write to s
|
||||
*/
|
||||
|
||||
static int u_offload_pipe_do(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor, int fd) {
|
||||
|
||||
ssize_t rlen;
|
||||
|
||||
// setup
|
||||
if (fd == -1) {
|
||||
event_queue_add_fd_read(ut->queue, uor->fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(uor->status) {
|
||||
// read event from fd
|
||||
case 0:
|
||||
if (!uor->buf) {
|
||||
uor->buf = uwsgi_malloc(4096);
|
||||
}
|
||||
rlen = read(uor->fd, uor->buf, 4096);
|
||||
if (rlen > 0) {
|
||||
uor->to_write = rlen;
|
||||
uor->pos = 0;
|
||||
if (event_queue_del_fd(ut->queue, uor->fd, event_queue_read())) return -1;
|
||||
if (event_queue_add_fd_write(ut->queue, uor->s)) return -1;
|
||||
uor->status = 1;
|
||||
return 0;
|
||||
}
|
||||
if (rlen < 0) {
|
||||
uwsgi_offload_retry
|
||||
uwsgi_error("u_offload_pipe_do() -> read()");
|
||||
}
|
||||
return -1;
|
||||
// write event on s
|
||||
case 1:
|
||||
rlen = write(uor->s, uor->buf + uor->pos, uor->to_write);
|
||||
if (rlen > 0) {
|
||||
uor->to_write -= rlen;
|
||||
uor->pos += rlen;
|
||||
if (uor->to_write == 0) {
|
||||
if (event_queue_del_fd(ut->queue, uor->s, event_queue_write())) return -1;
|
||||
if (event_queue_add_fd_read(ut->queue, uor->fd)) return -1;
|
||||
uor->status = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (rlen < 0) {
|
||||
uwsgi_offload_retry
|
||||
uwsgi_error("u_offload_pipe_do() -> write()");
|
||||
}
|
||||
return -1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
the offload task starts soon after the call to connect()
|
||||
|
||||
@@ -541,6 +622,7 @@ void uwsgi_offload_engines_register_all() {
|
||||
uwsgi.offload_engine_sendfile = uwsgi_offload_register_engine("sendfile", u_offload_sendfile_prepare, u_offload_sendfile_do);
|
||||
uwsgi.offload_engine_transfer = uwsgi_offload_register_engine("transfer", u_offload_transfer_prepare, u_offload_transfer_do);
|
||||
uwsgi.offload_engine_memory = uwsgi_offload_register_engine("memory", u_offload_memory_prepare, u_offload_memory_do);
|
||||
uwsgi.offload_engine_pipe = uwsgi_offload_register_engine("pipe", u_offload_pipe_prepare, u_offload_pipe_do);
|
||||
}
|
||||
|
||||
int uwsgi_offload_request_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t len) {
|
||||
@@ -566,3 +648,11 @@ int uwsgi_offload_request_memory_do(struct wsgi_request *wsgi_req, char *buf, si
|
||||
uor.len = len;
|
||||
return uwsgi_offload_run(wsgi_req, &uor, NULL);
|
||||
}
|
||||
|
||||
int uwsgi_offload_request_pipe_do(struct wsgi_request *wsgi_req, int fd, size_t len) {
|
||||
struct uwsgi_offload_request uor;
|
||||
uwsgi_offload_setup(uwsgi.offload_engine_pipe, &uor, wsgi_req, 1);
|
||||
uor.fd = fd;
|
||||
uor.len = len;
|
||||
return uwsgi_offload_run(wsgi_req, &uor, NULL);
|
||||
}
|
||||
|
||||
+2
-2
@@ -478,9 +478,9 @@ int uwsgi_postbuffer_do_in_disk(struct wsgi_request *wsgi_req) {
|
||||
int upload_progress_fd = -1;
|
||||
char *upload_progress_filename = NULL;
|
||||
|
||||
wsgi_req->post_file = tmpfile();
|
||||
wsgi_req->post_file = uwsgi_tmpfile();
|
||||
if (!wsgi_req->post_file) {
|
||||
uwsgi_error("uwsgi_postbuffer_do_in_disk()/tmpfile()");
|
||||
uwsgi_error("uwsgi_postbuffer_do_in_disk()/uwsgi_tmpfile()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
+80
-1
@@ -564,7 +564,7 @@ static int uwsgi_router_harakiri_func(struct wsgi_request *wsgi_req, struct uwsg
|
||||
if (route->custom > 0) {
|
||||
set_user_harakiri(route->custom);
|
||||
}
|
||||
return UWSGI_ROUTE_CONTINUE;
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
|
||||
static int uwsgi_router_harakiri(struct uwsgi_route *ur, char *arg) {
|
||||
@@ -889,6 +889,77 @@ static int uwsgi_router_setscriptname(struct uwsgi_route *ur, char *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// setmethod route
|
||||
static int uwsgi_router_setmethod_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, "REQUEST_METHOD", 14, ub->buf, ub->pos);
|
||||
if (!ptr) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
wsgi_req->method = ptr;
|
||||
wsgi_req->method_len = ub->pos;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_setmethod(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_setmethod_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// seturi route
|
||||
static int uwsgi_router_seturi_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, "REQUEST_URI", 11, ub->buf, ub->pos);
|
||||
if (!ptr) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
wsgi_req->uri = ptr;
|
||||
wsgi_req->uri_len = ub->pos;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_seturi(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_seturi_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// setpathinfo route
|
||||
static int uwsgi_router_setpathinfo_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, "PATH_INFO", 9, ub->buf, ub->pos);
|
||||
if (!ptr) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
wsgi_req->path_info = ptr;
|
||||
wsgi_req->path_info_len = ub->pos;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_setpathinfo(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_setpathinfo_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// setuser route
|
||||
static int uwsgi_router_setuser_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
@@ -1389,6 +1460,11 @@ static char *uwsgi_route_var_uwsgi(struct wsgi_request *wsgi_req, char *key, uin
|
||||
*vallen = strlen(ret);
|
||||
}
|
||||
|
||||
else if (!uwsgi_strncmp(key, keylen, "lq", 2)) {
|
||||
ret = uwsgi_num2str(uwsgi.shared->load);
|
||||
*vallen = strlen(ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1514,6 +1590,9 @@ void uwsgi_register_embedded_routers() {
|
||||
uwsgi_register_router("sethome", uwsgi_router_sethome);
|
||||
uwsgi_register_router("setfile", uwsgi_router_setfile);
|
||||
uwsgi_register_router("setscriptname", uwsgi_router_setscriptname);
|
||||
uwsgi_register_router("setmethod", uwsgi_router_setmethod);
|
||||
uwsgi_register_router("seturi", uwsgi_router_seturi);
|
||||
uwsgi_register_router("setpathinfo", uwsgi_router_setpathinfo);
|
||||
uwsgi_register_router("setprocname", uwsgi_router_setprocname);
|
||||
uwsgi_register_router("alarm", uwsgi_router_alarm);
|
||||
|
||||
|
||||
@@ -37,3 +37,39 @@ ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
simple non blocking sendfile implementation
|
||||
(generally used as fallback)
|
||||
*/
|
||||
|
||||
int uwsgi_simple_sendfile(struct wsgi_request *wsgi_req, int fd, size_t pos, size_t len) {
|
||||
|
||||
wsgi_req->write_pos = 0;
|
||||
|
||||
for(;;) {
|
||||
int ret = wsgi_req->socket->proto_sendfile(wsgi_req, fd, pos, len);
|
||||
if (ret < 0) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_error("uwsgi_simple_sendfile()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
if (ret == UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
ret = uwsgi_wait_write_req(wsgi_req);
|
||||
if (ret < 0) {
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
if (ret == 0) {
|
||||
uwsgi_log("uwsgi_simple_sendfile() TIMEOUT !!!\n");
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
+10
-5
@@ -82,6 +82,8 @@ int uwsgi_apply_final_transformations(struct wsgi_request *wsgi_req) {
|
||||
found_nostream = 1;
|
||||
}
|
||||
else {
|
||||
// stop the chain if no chunk is available
|
||||
if (!ut->chunk) return 0;
|
||||
t_buf = ut->chunk->buf;
|
||||
t_len = ut->chunk->pos;
|
||||
goto next;
|
||||
@@ -132,6 +134,12 @@ void uwsgi_free_transformations(struct wsgi_request *wsgi_req) {
|
||||
if (current_ut->chunk) {
|
||||
uwsgi_buffer_destroy(current_ut->chunk);
|
||||
}
|
||||
if (current_ut->ub) {
|
||||
uwsgi_buffer_destroy(current_ut->ub);
|
||||
}
|
||||
if (current_ut->fd > -1) {
|
||||
close(current_ut->fd);
|
||||
}
|
||||
ut = ut->next;
|
||||
free(current_ut);
|
||||
}
|
||||
@@ -144,12 +152,9 @@ struct uwsgi_transformation *uwsgi_add_transformation(struct wsgi_request *wsgi_
|
||||
ut = ut->next;
|
||||
}
|
||||
|
||||
ut = uwsgi_malloc(sizeof(struct uwsgi_transformation));
|
||||
ut = uwsgi_calloc(sizeof(struct uwsgi_transformation));
|
||||
ut->func = func;
|
||||
ut->is_final = 0;
|
||||
ut->next = NULL;
|
||||
ut->chunk = NULL;
|
||||
ut->can_stream = 0;
|
||||
ut->fd = -1;
|
||||
ut->data = data;
|
||||
|
||||
if (old_ut) {
|
||||
|
||||
+83
-22
@@ -71,11 +71,30 @@ void set_user_harakiri(int sec) {
|
||||
uwsgi_log("!!! unable to set user harakiri without the master process !!!\n");
|
||||
return;
|
||||
}
|
||||
// a 0 seconds value, reset the timer
|
||||
if (sec == 0) {
|
||||
uwsgi.workers[uwsgi.mywid].user_harakiri = 0;
|
||||
if (uwsgi.muleid > 0) {
|
||||
uwsgi.mules[uwsgi.muleid-1].user_harakiri = 0;
|
||||
}
|
||||
else if (uwsgi.i_am_a_spooler) {
|
||||
struct uwsgi_spooler *uspool = uwsgi.i_am_a_spooler;
|
||||
uspool->user_harakiri = 0;
|
||||
}
|
||||
else {
|
||||
uwsgi.workers[uwsgi.mywid].user_harakiri = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi.workers[uwsgi.mywid].user_harakiri = uwsgi_now() + sec;
|
||||
if (uwsgi.muleid > 0) {
|
||||
uwsgi.mules[uwsgi.muleid-1].user_harakiri = uwsgi_now() + sec;
|
||||
}
|
||||
else if (uwsgi.i_am_a_spooler) {
|
||||
struct uwsgi_spooler *uspool = uwsgi.i_am_a_spooler;
|
||||
uspool->user_harakiri = uwsgi_now() + sec;
|
||||
}
|
||||
else {
|
||||
uwsgi.workers[uwsgi.mywid].user_harakiri = uwsgi_now() + sec;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -708,6 +727,11 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
// free chunked input
|
||||
if (wsgi_req->chunked_input_buf) {
|
||||
uwsgi_buffer_destroy(wsgi_req->chunked_input_buf);
|
||||
}
|
||||
|
||||
// free websocket engine
|
||||
if (wsgi_req->websocket_buf) {
|
||||
uwsgi_buffer_destroy(wsgi_req->websocket_buf);
|
||||
@@ -1147,7 +1171,6 @@ int uwsgi_get_app_id(struct wsgi_request *wsgi_req, char *key, uint16_t key_len,
|
||||
int i;
|
||||
struct stat st;
|
||||
int found;
|
||||
int free_appname = 0;
|
||||
|
||||
char *app_name = key;
|
||||
uint16_t app_name_len = key_len;
|
||||
@@ -1162,13 +1185,20 @@ int uwsgi_get_app_id(struct wsgi_request *wsgi_req, char *key, uint16_t key_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);
|
||||
char *vhost_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;
|
||||
app_name = uwsgi_req_append(wsgi_req, "UWSGI_APPID", 11, vhost_name, app_name_len);
|
||||
free(vhost_name);
|
||||
if (!app_name) {
|
||||
uwsgi_log("unable to add UWSGI_APPID to the uwsgi buffer, consider increasing it\n");
|
||||
return -1;
|
||||
}
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("VirtualHost KEY=%.*s\n", wsgi_req->appid_len, wsgi_req->appid);
|
||||
uwsgi_debug("VirtualHost KEY=%.*s\n", app_name_len, app_name);
|
||||
#endif
|
||||
free_appname = 1;
|
||||
}
|
||||
wsgi_req->appid = app_name;
|
||||
wsgi_req->appid_len = app_name_len;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1203,18 +1233,11 @@ int uwsgi_get_app_id(struct wsgi_request *wsgi_req, char *key, uint16_t key_len,
|
||||
}
|
||||
}
|
||||
}
|
||||
if (modifier1 == -1) {
|
||||
if (free_appname) free(app_name);
|
||||
return i;
|
||||
}
|
||||
if (modifier1 == uwsgi_apps[i].modifier1) {
|
||||
if (free_appname) free(app_name);
|
||||
return i;
|
||||
}
|
||||
if (modifier1 == -1) return i;
|
||||
if (modifier1 == uwsgi_apps[i].modifier1) return i;
|
||||
}
|
||||
}
|
||||
|
||||
if (free_appname) free(app_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1952,7 +1975,7 @@ int uwsgi_list_has_str(char *list, char *str) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char hex2num(char *str) {
|
||||
static char hex2num(char *str) {
|
||||
|
||||
char val = 0;
|
||||
|
||||
@@ -3065,6 +3088,36 @@ void escape_shell_arg(char *src, size_t len, char *dst) {
|
||||
*ptr++ = 0;
|
||||
}
|
||||
|
||||
void escape_json(char *src, size_t len, char *dst) {
|
||||
|
||||
size_t i;
|
||||
char *ptr = dst;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (src[i] == '\t') {
|
||||
*ptr++ = '\\';
|
||||
*ptr++ = 't';
|
||||
}
|
||||
else if (src[i] == '\n') {
|
||||
*ptr++ = '\\';
|
||||
*ptr++ = 'n';
|
||||
}
|
||||
else if (src[i] == '\r') {
|
||||
*ptr++ = '\\';
|
||||
*ptr++ = 'r';
|
||||
}
|
||||
else if (src[i] == '"') {
|
||||
*ptr++ = '\\';
|
||||
*ptr++ = '"';
|
||||
}
|
||||
else {
|
||||
*ptr++ = src[i];
|
||||
}
|
||||
}
|
||||
|
||||
*ptr++ = 0;
|
||||
}
|
||||
|
||||
void http_url_decode(char *buf, uint16_t * len, char *dst) {
|
||||
|
||||
uint16_t i;
|
||||
@@ -3221,14 +3274,22 @@ char *uwsgi_chomp(char *str) {
|
||||
return str;
|
||||
}
|
||||
|
||||
char *uwsgi_tmpname(char *base, char *id) {
|
||||
char *template = uwsgi_concat3(base, "/", id);
|
||||
if (mkstemp(template) < 0) {
|
||||
free(template);
|
||||
return NULL;
|
||||
int uwsgi_tmpfd() {
|
||||
char *tmpdir = getenv("TMPDIR");
|
||||
if (!tmpdir) {
|
||||
tmpdir = "/tmp";
|
||||
}
|
||||
char *template = uwsgi_concat2(tmpdir, "/uwsgiXXXXXX");
|
||||
int fd = mkstemp(template);
|
||||
unlink(template);
|
||||
free(template);
|
||||
return fd;
|
||||
}
|
||||
|
||||
return template;
|
||||
FILE *uwsgi_tmpfile() {
|
||||
int fd = uwsgi_tmpfd();
|
||||
if (fd < 0) return NULL;
|
||||
return fdopen(fd, "w+");
|
||||
}
|
||||
|
||||
int uwsgi_file_to_string_list(char *filename, struct uwsgi_string_list **list) {
|
||||
|
||||
+70
-14
@@ -236,6 +236,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"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},
|
||||
|
||||
{"add-cache-item", required_argument, 0, "add an item in the cache", uwsgi_opt_add_string_list, &uwsgi.add_cache_item, 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},
|
||||
@@ -349,6 +350,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"touch-logrotate", required_argument, 0, "trigger logrotation if the specified file is modified/touched", uwsgi_opt_add_string_list, &uwsgi.touch_logrotate, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
{"touch-logreopen", required_argument, 0, "trigger log reopen if the specified file is modified/touched", uwsgi_opt_add_string_list, &uwsgi.touch_logreopen, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
{"touch-exec", required_argument, 0, "run command when the specified file is modified/touched (syntax: file command)", uwsgi_opt_add_string_list, &uwsgi.touch_exec, UWSGI_OPT_MASTER},
|
||||
{"touch-signal", required_argument, 0, "signal when the specified file is modified/touched (syntax: file signal)", uwsgi_opt_add_string_list, &uwsgi.touch_signal, UWSGI_OPT_MASTER},
|
||||
{"propagate-touch", no_argument, 0, "over-engineering option for system with flaky signal mamagement", uwsgi_opt_true, &uwsgi.propagate_touch, 0},
|
||||
{"limit-post", required_argument, 0, "limit request body", uwsgi_opt_set_64bit, &uwsgi.limit_post, 0},
|
||||
{"no-orphans", no_argument, 0, "automatically kill workers if master dies (can be dangerous for availability)", uwsgi_opt_true, &uwsgi.no_orphans, 0},
|
||||
@@ -459,6 +461,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"log-route", required_argument, 0, "log to the specified named logger if regexp applied on logline matches", uwsgi_opt_add_regexp_custom_list, &uwsgi.log_route, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
{"log-req-route", required_argument, 0, "log requests to the specified named logger if regexp applied on logline matches", uwsgi_opt_add_regexp_custom_list, &uwsgi.log_req_route, UWSGI_OPT_REQ_LOG_MASTER},
|
||||
#endif
|
||||
|
||||
{"use-abort", no_argument, 0, "call abort() on segfault/fpe, could be useful for generating a core dump", uwsgi_opt_true, &uwsgi.use_abort, 0},
|
||||
|
||||
{"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},
|
||||
@@ -579,6 +584,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"websockets-max-size", required_argument, 0, "set the max allowed size of websocket messages (in Kbytes, default 1024)", uwsgi_opt_set_64bit, &uwsgi.websockets_max_size, 0},
|
||||
{"websocket-max-size", required_argument, 0, "set the max allowed size of websocket messages (in Kbytes, default 1024)", uwsgi_opt_set_64bit, &uwsgi.websockets_max_size, 0},
|
||||
|
||||
{"chunked-input-limit", required_argument, 0, "set the max size of a chunked input part (default 1MB, in bytes)", uwsgi_opt_set_64bit, &uwsgi.chunked_input_limit, 0},
|
||||
{"chunked-input-timeout", required_argument, 0, "set default timeout for chunked input", uwsgi_opt_set_int, &uwsgi.chunked_input_timeout, 0},
|
||||
|
||||
{"clock", required_argument, 0, "set a clock source", uwsgi_opt_set_str, &uwsgi.requested_clock, 0},
|
||||
|
||||
{"clock-list", no_argument, 0, "list enabled clocks", uwsgi_opt_true, &uwsgi.clock_list, 0},
|
||||
@@ -693,6 +701,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"show-config", no_argument, 0, "show the current config reformatted as ini", uwsgi_opt_true, &uwsgi.show_config, 0},
|
||||
{"print", required_argument, 0, "simple print", uwsgi_opt_print, NULL, 0},
|
||||
{"cflags", no_argument, 0, "report uWSGI CFLAGS (useful for building external plugins)", uwsgi_opt_cflags, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"dot-h", no_argument, 0, "dump the uwsgi.h used for building the core (useful for building external plugins)", uwsgi_opt_dot_h, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"version", no_argument, 0, "print uWSGI version", uwsgi_opt_print, UWSGI_VERSION, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
@@ -1527,6 +1536,8 @@ void uwsgi_segfault(int signum) {
|
||||
uwsgi_log("!!! uWSGI process %d got Segmentation Fault !!!\n", (int) getpid());
|
||||
uwsgi_backtrace(uwsgi.backtrace_depth);
|
||||
|
||||
if (uwsgi.use_abort) abort();
|
||||
|
||||
// restore default handler to generate core
|
||||
signal(signum, SIG_DFL);
|
||||
kill(getpid(), signum);
|
||||
@@ -1540,6 +1551,8 @@ void uwsgi_fpe(int signum) {
|
||||
uwsgi_log("!!! uWSGI process %d got Floating Point Exception !!!\n", (int) getpid());
|
||||
uwsgi_backtrace(uwsgi.backtrace_depth);
|
||||
|
||||
if (uwsgi.use_abort) abort();
|
||||
|
||||
// restore default handler to generate core
|
||||
signal(signum, SIG_DFL);
|
||||
kill(getpid(), signum);
|
||||
@@ -3386,7 +3399,9 @@ void uwsgi_opt_set_16bit(char *opt, char *value, void *key) {
|
||||
uint16_t *ptr = (uint16_t *) key;
|
||||
|
||||
if (value) {
|
||||
*ptr = (strtoul(value, NULL, 10));
|
||||
unsigned long n = strtoul(value, NULL, 10);
|
||||
if (n > 65535) n = 65535;
|
||||
*ptr = n;
|
||||
}
|
||||
else {
|
||||
*ptr = 1;
|
||||
@@ -4057,20 +4072,61 @@ void uwsgi_opt_flock_wait(char *opt, char *filename, void *none) {
|
||||
// report CFLAGS used for compiling the server
|
||||
// use that values to build external plugins
|
||||
void uwsgi_opt_cflags(char *opt, char *filename, void *foobar) {
|
||||
size_t len = sizeof(UWSGI_CFLAGS);
|
||||
char *src = UWSGI_CFLAGS;
|
||||
char *ptr = uwsgi_malloc(len / 2);
|
||||
char *base = ptr;
|
||||
size_t i;
|
||||
unsigned int u;
|
||||
for (i = 0; i < len; i += 2) {
|
||||
sscanf(src + i, "%2x", &u);
|
||||
*ptr++ = (char) u;
|
||||
}
|
||||
fprintf(stdout, "%.*s\n", (int) len / 2, base);
|
||||
fprintf(stdout, "%s\n", uwsgi_get_cflags());
|
||||
exit(0);
|
||||
}
|
||||
|
||||
char *uwsgi_get_cflags() {
|
||||
size_t len = sizeof(UWSGI_CFLAGS);
|
||||
char *src = UWSGI_CFLAGS;
|
||||
char *ptr = uwsgi_malloc((len / 2) + 1);
|
||||
char *base = ptr;
|
||||
size_t i;
|
||||
unsigned int u;
|
||||
for (i = 0; i < len; i += 2) {
|
||||
sscanf(src + i, "%2x", &u);
|
||||
*ptr++ = (char) u;
|
||||
}
|
||||
*ptr ++= 0;
|
||||
return base;
|
||||
}
|
||||
|
||||
// report uwsgi.h used for compiling the server
|
||||
// use that values to build external plugins
|
||||
extern char *uwsgi_dot_h;
|
||||
char *uwsgi_get_dot_h() {
|
||||
char *src = uwsgi_dot_h;
|
||||
size_t len = strlen(src);
|
||||
char *ptr = uwsgi_malloc(len / 2);
|
||||
char *base = ptr;
|
||||
size_t i;
|
||||
unsigned int u;
|
||||
for (i = 0; i < len; i += 2) {
|
||||
sscanf(src + i, "%2x", &u);
|
||||
*ptr++ = (char) u;
|
||||
}
|
||||
#ifdef UWSGI_ZLIB
|
||||
struct uwsgi_buffer *ub = uwsgi_zlib_decompress(base, ptr-base);
|
||||
if (!ub) {
|
||||
free(base);
|
||||
return "";
|
||||
}
|
||||
// add final null byte
|
||||
uwsgi_buffer_append(ub, "\0", 1);
|
||||
free(base);
|
||||
// base is the final blob
|
||||
base = ub->buf;
|
||||
ub->buf = NULL;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
#endif
|
||||
return base;
|
||||
}
|
||||
void uwsgi_opt_dot_h(char *opt, char *filename, void *foobar) {
|
||||
fprintf(stdout, "%s\n", uwsgi_get_dot_h());
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_connect_and_read(char *opt, char *address, void *foobar) {
|
||||
|
||||
char buf[8192];
|
||||
@@ -4107,9 +4163,9 @@ void uwsgi_opt_extract(char *opt, char *address, void *foobar) {
|
||||
}
|
||||
|
||||
void uwsgi_print_sym(char *opt, char *symbol, void *foobar) {
|
||||
char *sym = dlsym(RTLD_DEFAULT, symbol);
|
||||
char **sym = dlsym(RTLD_DEFAULT, symbol);
|
||||
if (sym) {
|
||||
uwsgi_log("%s", sym);
|
||||
uwsgi_log("%s", *sym);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -408,3 +408,35 @@ int uwsgi_simple_wait_write_hook(int fd, int timeout) {
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
simplified write to client
|
||||
(generally used as fallback)
|
||||
*/
|
||||
int uwsgi_simple_write(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
|
||||
wsgi_req->write_pos = 0;
|
||||
|
||||
for(;;) {
|
||||
int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
|
||||
if (ret < 0) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_error("uwsgi_simple_write()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
if (ret == UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
ret = uwsgi_wait_write_req(wsgi_req);
|
||||
if (ret < 0) { wsgi_req->write_errors++; return -1;}
|
||||
if (ret == 0) {
|
||||
uwsgi_log("uwsgi_simple_write() TIMEOUT !!!\n");
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+56
@@ -2,6 +2,8 @@
|
||||
|
||||
char gzheader[10] = { 0x1f, 0x8b, Z_DEFLATED, 0, 0, 0, 0, 0, 0, 3 };
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
char *uwsgi_gzip_chunk(z_stream *z, uint32_t *crc32, char *buf, size_t len, size_t *dlen) {
|
||||
uwsgi_crc32(crc32, buf, len);
|
||||
return uwsgi_deflate(z, buf, len, dlen);
|
||||
@@ -38,6 +40,45 @@ end:
|
||||
return ub;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *uwsgi_zlib_decompress(char *buf, size_t len) {
|
||||
z_stream z;
|
||||
|
||||
z.zalloc = Z_NULL;
|
||||
z.zfree = Z_NULL;
|
||||
z.opaque = Z_NULL;
|
||||
if (inflateInit(&z) != Z_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
|
||||
unsigned char out[8192];
|
||||
|
||||
z.next_in = (unsigned char *)buf;
|
||||
z.avail_in = len;
|
||||
z.next_out = out;
|
||||
|
||||
do {
|
||||
z.avail_out = 8192;
|
||||
z.next_out = out;
|
||||
int ret = inflate(&z, Z_NO_FLUSH);
|
||||
if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
ub = NULL;
|
||||
goto end;
|
||||
}
|
||||
if (uwsgi_buffer_append(ub, (char *)out, 8192 - z.avail_out)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
ub = NULL;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
while (z.avail_out == 0);
|
||||
end:
|
||||
inflateEnd(&z);
|
||||
return ub;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_deflate_init(z_stream *z, char *dict, size_t dict_len) {
|
||||
z->zalloc = Z_NULL;
|
||||
z->zfree = Z_NULL;
|
||||
@@ -54,6 +95,21 @@ int uwsgi_deflate_init(z_stream *z, char *dict, size_t dict_len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_inflate_init(z_stream *z, char *dict, size_t dict_len) {
|
||||
z->zalloc = Z_NULL;
|
||||
z->zfree = Z_NULL;
|
||||
z->opaque = Z_NULL;
|
||||
if (inflateInit2(z, 16+MAX_WBITS) != Z_OK) {
|
||||
return -1;
|
||||
}
|
||||
if (dict && dict_len) {
|
||||
if (inflateSetDictionary(z, (Bytef *) dict, dict_len) != Z_OK) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_gzip_prepare(z_stream *z, char *dict, size_t dict_len, uint32_t *crc32) {
|
||||
uwsgi_crc32(crc32, NULL, 0);
|
||||
if (uwsgi_deflate_init(z, NULL, 0)) return -1;
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Livello_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="768px" height="272.667px" viewBox="0 0 768 272.667" enable-background="new 0 0 768 272.667" xml:space="preserve">
|
||||
<g>
|
||||
<path fill="#AEC84D" d="M170.667,41.334"/>
|
||||
<path fill="#AEC84D" d="M46.167,106.667v92.5c0,0-0.667,52.667,48.5,51.5c7.667-0.333,36,1,43-21c0-0.5,0,17,0,17h34l0.062-140h-34
|
||||
l-0.062,86.5c0,0,1,31-28,29.5s-28.5-27-28.5-27l-0.167-89H46.167z"/>
|
||||
<polygon fill="#141215" points="227,250.334 241,250.334 286.667,137.334 332.333,250.001 346.333,250.001 403,41.334
|
||||
368.667,32.667 334.333,161.667 293.667,60.001 279.333,60.001 240,160.667 204.667,32.667 170.667,41.334 "/>
|
||||
<path fill="#141215" d="M402,203c0,0,8.667,26.001,23,35.334s38.666,12.999,50.333,12.666s71.001-1.333,71.667-56.333
|
||||
c5-28-19.333-48.334-26-52.334s-28.334-18-45.667-23s-34.334-16-35.667-24.666s0.001-34,37.334-34.334
|
||||
c26,2.668,27,13.668,31,19.668l7,14.332l28.666-13.332c0,0-11.334-27-14-29.334s-13.333-19-55.333-18.666
|
||||
c-42,0.332-66.666,17.666-68.333,47.666s4.666,44,35.333,62.666c19,10.334,39.001,12.667,59.667,28.334
|
||||
c14.333,11.667,11.334,25.001,11,30.667s-7.334,21.666-36.334,20.333S441,209.668,439,206.334s-9-17-9-17L402,203z"/>
|
||||
<rect x="710.667" y="36.334" fill="#141215" width="35.333" height="211.333"/>
|
||||
<path fill="#141215" d="M636.333,135.001v27.666h27.333v56c0,0-8.334,5.001-26.667,4.334s-47.332,1.666-49.666-81.667
|
||||
s37.334-80.667,42-80.667s28,0.334,40,33.334C669.667,94.334,698,80.667,698,80.667s-12.334-50.333-67-47.666
|
||||
c-54.666,2.666-75.666,30.999-78.666,102c-3,71,21.999,117.334,81.666,115s64-7.334,64-7.334l-0.083-107.583L636.333,135.001z"/>
|
||||
<g>
|
||||
<circle fill="#AEC84D" cx="521.333" cy="71.001" r="11.667"/>
|
||||
<circle fill="#252326" cx="521.333" cy="71.001" r="3.5"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="none" d="M81.147,185.163L81,106.667H46.167v90.88C56.139,192.016,68.027,187.752,81.147,185.163z"/>
|
||||
<path fill="none" d="M171.729,106.667h-34l-0.057,78.023c12.606,2.254,24.141,6.043,34.017,11.019L171.729,106.667z"/>
|
||||
<path opacity="0.1" fill="#FFFFFF" d="M46.167,199.167c0,0-0.667,52.667,48.5,51.5c7.667-0.333,36,1,43-21c0-0.5,0,17,0,17h34
|
||||
l0.023-50.958c-9.876-4.976-21.411-8.765-34.017-11.019l-0.006,8.477c0,0,1,31-28,29.5s-28.5-27-28.5-27l-0.02-10.504
|
||||
c-13.12,2.589-25.008,6.853-34.98,12.384V199.167z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="none" d="M342.89,129.517l-8.557,32.15l-13.896-34.738c-22.89-2.918-44.071-6.524-63.071-10.708L240,160.667
|
||||
l-14.526-52.621c-16.399-4.896-30.286-10.312-41.175-16.132L227,250.334h14l45.667-113l45.667,112.667h14l31.898-117.459
|
||||
C366.127,131.707,354.33,130.695,342.89,129.517z"/>
|
||||
<path opacity="0.1" fill="#FFFFFF" d="M403,41.334l-34.333-8.667l-25.776,96.85c11.44,1.178,23.237,2.19,35.341,3.025L403,41.334z
|
||||
"/>
|
||||
<path opacity="0.1" fill="#FFFFFF" d="M204.667,32.667l-34,8.667l13.633,50.58c10.889,5.82,24.775,11.236,41.175,16.132
|
||||
L204.667,32.667z"/>
|
||||
<path opacity="0.1" fill="#FFFFFF" d="M293.667,60.001h-14.333l-21.967,56.22c19,4.185,40.182,7.79,63.071,10.708L293.667,60.001z
|
||||
"/>
|
||||
</g>
|
||||
<path opacity="0.1" fill="#FFFFFF" d="M474.333,33.001c-42,0.332-66.666,17.666-68.333,47.666
|
||||
c-1.409,25.351,2.897,39.276,22.77,54.247c10.646,0.275,21.452,0.419,32.396,0.419c15.9,0,31.514-0.299,46.756-0.872
|
||||
c-9.466-5.486-21.856-12.032-32.589-15.128c-17.333-5-34.334-16-35.667-24.666s0.001-34,37.334-34.334
|
||||
c26,2.668,27,13.668,31,19.668l7,14.332l28.666-13.332c0,0-11.334-27-14-29.334S516.333,32.667,474.333,33.001z"/>
|
||||
<path opacity="0.1" fill="#FFFFFF" d="M631,33.001c-53.87,2.627-75.047,30.182-78.522,98.93c11.947-0.916,23.576-2.007,34.838-3.26
|
||||
c1.845-70.377,37.603-68.004,42.019-68.004c4.666,0,28,0.334,40,33.334C669.667,94.334,698,80.667,698,80.667
|
||||
S685.666,30.334,631,33.001z"/>
|
||||
<path opacity="0.1" fill="#FFFFFF" d="M710.667,103.59c14.42-5.033,26.342-10.521,35.333-16.36V36.334h-35.333V103.59z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.0 KiB |
@@ -229,6 +229,7 @@ static void uwsgi_airbrake_loop(struct uwsgi_thread *ut) {
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
struct curl_slist *expect = NULL; expect = curl_slist_append(expect, "Expect:");
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, expect);
|
||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||
|
||||
struct uwsgi_airbrake_config *uacc = (struct uwsgi_airbrake_config *) ut->data;
|
||||
char *opts = uwsgi_str(uacc->arg);
|
||||
|
||||
@@ -154,6 +154,7 @@ static void uwsgi_alarm_curl_loop(struct uwsgi_thread *ut) {
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
struct curl_slist *expect = NULL; expect = curl_slist_append(expect, "Expect:");
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, expect);
|
||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||
|
||||
struct uwsgi_alarm_curl_config *uacc = (struct uwsgi_alarm_curl_config *) ut->data;
|
||||
char *opts = uwsgi_str(uacc->arg);
|
||||
|
||||
@@ -23,13 +23,13 @@
|
||||
}\
|
||||
peer->out_pos += len;
|
||||
|
||||
#define cr_write_buf(peer, buf, f) write(peer->fd, buf + buf##_pos, buf->pos - buf##_pos);\
|
||||
#define cr_write_buf(peer, ubuf, f) write(peer->fd, ubuf->buf + ubuf##_pos, ubuf->pos - ubuf##_pos);\
|
||||
if (len < 0) {\
|
||||
cr_try_again;\
|
||||
uwsgi_cr_error(peer, f);\
|
||||
return -1;\
|
||||
}\
|
||||
buf##_pos += len;
|
||||
ubuf##_pos += len;
|
||||
|
||||
#define cr_write_complete(peer) peer->out_pos == peer->out->pos
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ request:
|
||||
#endif
|
||||
|
||||
for(;;) {
|
||||
if (uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req)) {
|
||||
if (uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req) <= UWSGI_OK) {
|
||||
goto end;
|
||||
}
|
||||
wsgi_req->switches++;
|
||||
|
||||
@@ -453,7 +453,8 @@ static int amqp_wait_connection_tune(int fd) {
|
||||
static char *amqp_simple_get_frame(int fd, struct amqp_frame_header *fh) {
|
||||
|
||||
char *ptr = (char *) fh;
|
||||
ssize_t len = 0, rlen;
|
||||
size_t len = 0;
|
||||
ssize_t rlen;
|
||||
|
||||
while(len < 7) {
|
||||
rlen = recv(fd, ptr, 7-len, 0);
|
||||
|
||||
@@ -25,6 +25,7 @@ struct uwsgi_jvm {
|
||||
jclass input_stream_class;
|
||||
jclass file_class;
|
||||
jclass hashmap_class;
|
||||
jclass list_class;
|
||||
jclass set_class;
|
||||
jclass iterator_class;
|
||||
|
||||
@@ -63,6 +64,10 @@ jmethodID uwsgi_jvm_get_static_method_id_quiet(jclass, char *, char *);
|
||||
jobject uwsgi_jvm_str(char *, size_t);
|
||||
jobject uwsgi_jvm_hashmap(void);
|
||||
int uwsgi_jvm_hashmap_put(jobject, jobject, jobject);
|
||||
int uwsgi_jvm_hashmap_has(jobject, jobject);
|
||||
|
||||
jobject uwsgi_jvm_list(void);
|
||||
int uwsgi_jvm_list_add(jobject, jobject);
|
||||
|
||||
jobject uwsgi_jvm_call_object(jobject, jmethodID, ...);
|
||||
jobject uwsgi_jvm_call_object_static(jclass, jmethodID, ...);
|
||||
|
||||
@@ -215,15 +215,42 @@ JNIEXPORT jint JNICALL uwsgi_jvm_request_body_read_bytearray(JNIEnv *env, jobjec
|
||||
return rlen;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL uwsgi_jvm_request_body_readline_bytearray(JNIEnv *env, jobject o, jobject b) {
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
ssize_t rlen = 0;
|
||||
size_t len = uwsgi_jvm_array_len(b);
|
||||
char *chunk = uwsgi_request_body_readline(wsgi_req, len, &rlen);
|
||||
if (!chunk) {
|
||||
uwsgi_jvm_throw_io("error reading request body");
|
||||
return -1;
|
||||
}
|
||||
if (chunk == uwsgi.empty) {
|
||||
return -1;
|
||||
}
|
||||
char *buf = (char *) (*ujvm_env)->GetByteArrayElements(ujvm_env, b, JNI_FALSE);
|
||||
if (!buf) return -1;
|
||||
memcpy(buf, chunk, rlen);
|
||||
(*ujvm_env)->ReleaseByteArrayElements(ujvm_env, b, (jbyte *) buf, 0);
|
||||
return rlen;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint JNICALL uwsgi_jvm_request_body_available(JNIEnv *env, jobject o) {
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
return (jint) (wsgi_req->post_cl - wsgi_req->post_pos);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL uwsgi_jvm_request_body_seek(JNIEnv *env, jobject o, jint pos) {
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
uwsgi_request_body_seek(wsgi_req, pos);
|
||||
}
|
||||
|
||||
static JNINativeMethod uwsgi_jvm_request_body_methods[] = {
|
||||
{"read", "()I", (void *) &uwsgi_jvm_request_body_read},
|
||||
{"read", "([B)I", (void *) &uwsgi_jvm_request_body_read_bytearray},
|
||||
{"readLine", "([B)I", (void *) &uwsgi_jvm_request_body_readline_bytearray},
|
||||
{"available", "()I", (void *) &uwsgi_jvm_request_body_available},
|
||||
{"seek", "(I)V", (void *) &uwsgi_jvm_request_body_seek},
|
||||
};
|
||||
|
||||
static struct uwsgi_option uwsgi_jvm_options[] = {
|
||||
@@ -684,6 +711,23 @@ void uwsgi_jvm_local_unref(jobject obj) {
|
||||
(*ujvm_env)->DeleteLocalRef(ujvm_env, obj);
|
||||
}
|
||||
|
||||
jobject uwsgi_jvm_list() {
|
||||
// optimization
|
||||
static jmethodID mid = 0;
|
||||
|
||||
if (!mid) {
|
||||
mid = uwsgi_jvm_get_method_id(ujvm.list_class, "<init>", "()V");
|
||||
if (!mid) return NULL;
|
||||
}
|
||||
|
||||
jobject ll = (*ujvm_env)->NewObject(ujvm_env, ujvm.list_class, mid);
|
||||
if (uwsgi_jvm_exception()) {
|
||||
return NULL;
|
||||
}
|
||||
return ll;
|
||||
}
|
||||
|
||||
|
||||
jobject uwsgi_jvm_hashmap() {
|
||||
// optimization
|
||||
static jmethodID mid = 0;
|
||||
@@ -712,6 +756,18 @@ int uwsgi_jvm_hashmap_put(jobject hm, jobject key, jobject value) {
|
||||
return uwsgi_jvm_call(hm, mid, key, value);
|
||||
}
|
||||
|
||||
int uwsgi_jvm_list_add(jobject ll, jobject value) {
|
||||
// optimization
|
||||
static jmethodID mid = 0;
|
||||
|
||||
if (!mid) {
|
||||
mid = uwsgi_jvm_get_method_id(ujvm.list_class, "add", "(Ljava/lang/Object;)Z");
|
||||
if (!mid) return -1;
|
||||
}
|
||||
|
||||
return uwsgi_jvm_call(ll, mid, value);
|
||||
}
|
||||
|
||||
jobject uwsgi_jvm_hashmap_get(jobject hm, jobject key) {
|
||||
// optimization
|
||||
static jmethodID mid = 0;
|
||||
@@ -724,6 +780,21 @@ jobject uwsgi_jvm_hashmap_get(jobject hm, jobject key) {
|
||||
return uwsgi_jvm_call_object(hm, mid, key);
|
||||
}
|
||||
|
||||
int uwsgi_jvm_hashmap_has(jobject hm, jobject key) {
|
||||
// optimization
|
||||
static jmethodID mid = 0;
|
||||
|
||||
if (!mid) {
|
||||
mid = uwsgi_jvm_get_method_id(ujvm.hashmap_class, "containsKey", "(Ljava/lang/Object;)Z");
|
||||
if (!mid) return 0;
|
||||
}
|
||||
|
||||
if (uwsgi_jvm_call_bool(hm, mid, key)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
jobject uwsgi_jvm_iterator(jobject set) {
|
||||
// optimization
|
||||
static jmethodID mid = 0;
|
||||
@@ -1010,6 +1081,9 @@ static void uwsgi_jvm_create(void) {
|
||||
ujvm.hashmap_class = uwsgi_jvm_class("java/util/HashMap");
|
||||
if (!ujvm.hashmap_class) exit(1);
|
||||
|
||||
ujvm.list_class = uwsgi_jvm_class("java/util/ArrayList");
|
||||
if (!ujvm.list_class) exit(1);
|
||||
|
||||
ujvm.set_class = uwsgi_jvm_class("java/util/Set");
|
||||
if (!ujvm.set_class) exit(1);
|
||||
|
||||
@@ -1026,6 +1100,52 @@ static void uwsgi_jvm_create(void) {
|
||||
if (!uwsgi_class) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
start filling uwsgi.opt
|
||||
*/
|
||||
jfieldID opt_fid = (*ujvm_env)->GetStaticFieldID(ujvm_env, uwsgi_class, "opt", "Ljava/util/HashMap;");
|
||||
if (uwsgi_jvm_exception()) {
|
||||
exit(1);
|
||||
}
|
||||
jobject opt_hm = uwsgi_jvm_hashmap();
|
||||
int j;
|
||||
for (j = 0; j < uwsgi.exported_opts_cnt; j++) {
|
||||
jstring j_opt_key = uwsgi_jvm_str(uwsgi.exported_opts[j]->key, 0);
|
||||
if (uwsgi_jvm_hashmap_has(opt_hm, (jobject) j_opt_key)) {
|
||||
jobject j_opt_value = uwsgi_jvm_hashmap_get(opt_hm, (jobject) j_opt_key);
|
||||
if (uwsgi_jvm_object_is_instance(j_opt_value, ujvm.list_class)) {
|
||||
if (uwsgi.exported_opts[j]->value == NULL) {
|
||||
uwsgi_jvm_list_add(j_opt_value, (jobject) 1);
|
||||
}
|
||||
else {
|
||||
uwsgi_jvm_list_add(j_opt_value, uwsgi_jvm_str(uwsgi.exported_opts[j]->value, 0));
|
||||
}
|
||||
}
|
||||
else {
|
||||
jobject ll = uwsgi_jvm_list();
|
||||
uwsgi_jvm_list_add(ll, j_opt_value);
|
||||
if (uwsgi.exported_opts[j]->value == NULL) {
|
||||
uwsgi_jvm_list_add(ll, (jobject) 1);
|
||||
}
|
||||
else {
|
||||
uwsgi_jvm_list_add(ll, uwsgi_jvm_str(uwsgi.exported_opts[j]->value, 0));
|
||||
}
|
||||
uwsgi_jvm_hashmap_put(opt_hm, j_opt_key, ll);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uwsgi.exported_opts[j]->value == NULL) {
|
||||
uwsgi_jvm_hashmap_put(opt_hm, j_opt_key, (jobject) 1);
|
||||
}
|
||||
else {
|
||||
uwsgi_jvm_hashmap_put(opt_hm, j_opt_key, uwsgi_jvm_str(uwsgi.exported_opts[j]->value, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
(*ujvm_env)->SetStaticObjectField(ujvm_env, uwsgi_class, opt_fid, opt_hm);
|
||||
|
||||
|
||||
(*ujvm_env)->RegisterNatives(ujvm_env, uwsgi_class, uwsgi_jvm_api_methods, sizeof(uwsgi_jvm_api_methods)/sizeof(uwsgi_jvm_api_methods[0]));
|
||||
if (uwsgi_jvm_exception()) {
|
||||
exit(1);
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
public class uwsgi {
|
||||
|
||||
static HashMap<String,Object> opt;
|
||||
|
||||
public static class RequestBody extends InputStream {
|
||||
public native int read();
|
||||
public native int read(byte[] b);
|
||||
public native int readLine(byte[] b);
|
||||
public native int available();
|
||||
public native void seek(int pos);
|
||||
}
|
||||
|
||||
public interface SignalHandler {
|
||||
|
||||
@@ -9,6 +9,7 @@ struct uwsgi_jwsgi {
|
||||
char *app;
|
||||
jmethodID app_mid;
|
||||
jclass app_class;
|
||||
jobject app_instance;
|
||||
} ujwsgi;
|
||||
|
||||
static struct uwsgi_option uwsgi_jwsgi_options[] = {
|
||||
@@ -20,7 +21,16 @@ static int uwsgi_jwsgi_add_request_item(jobject hm, char *key, uint16_t key_len,
|
||||
jobject j_key = uwsgi_jvm_str(key, key_len);
|
||||
if (!j_key) return -1;
|
||||
|
||||
jobject j_value = uwsgi_jvm_str(value, value_len);
|
||||
jobject j_value = NULL;
|
||||
// avoid clobbering vars
|
||||
if (value_len > 0) {
|
||||
j_value = uwsgi_jvm_str(value, value_len);
|
||||
}
|
||||
else {
|
||||
char *tmp = uwsgi_str("");
|
||||
j_value = uwsgi_jvm_str(tmp, 0);
|
||||
free(tmp);
|
||||
}
|
||||
if (!j_value) {
|
||||
uwsgi_jvm_local_unref(j_value);
|
||||
return -1;
|
||||
@@ -72,7 +82,12 @@ static int uwsgi_jwsgi_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (uwsgi_jwsgi_add_request_input(hm, "jwsgi.input", 11)) goto end;
|
||||
|
||||
response = uwsgi_jvm_call_object_static(ujwsgi.app_class, ujwsgi.app_mid, hm);
|
||||
if (!ujwsgi.app_instance) {
|
||||
response = uwsgi_jvm_call_object_static(ujwsgi.app_class, ujwsgi.app_mid, hm);
|
||||
}
|
||||
else {
|
||||
response = uwsgi_jvm_call_object(ujwsgi.app_instance, ujwsgi.app_mid, hm);
|
||||
}
|
||||
if (!response) goto end;
|
||||
|
||||
if (uwsgi_jvm_array_len(response) != 3) {
|
||||
@@ -135,23 +150,31 @@ static int uwsgi_jwsgi_setup() {
|
||||
|
||||
char *app = uwsgi_str(ujwsgi.app);
|
||||
|
||||
char *method = "application";
|
||||
char *colon = strchr(app, ':');
|
||||
|
||||
if (!colon) {
|
||||
uwsgi_log("invalid JWSGI app definition, must be class:method\n");
|
||||
exit(1);
|
||||
if (colon) {
|
||||
*colon = 0;
|
||||
method = colon + 1;
|
||||
}
|
||||
|
||||
*colon = 0;
|
||||
|
||||
ujwsgi.app_class = uwsgi_jvm_class(app);
|
||||
if (!ujwsgi.app_class) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ujwsgi.app_mid = uwsgi_jvm_get_static_method_id(ujwsgi.app_class, colon+1, "(Ljava/util/HashMap;)[Ljava/lang/Object;");
|
||||
if (!ujwsgi.app_mid) {
|
||||
exit(1);
|
||||
ujwsgi.app_mid = uwsgi_jvm_get_static_method_id_quiet(ujwsgi.app_class, method, "(Ljava/util/HashMap;)[Ljava/lang/Object;");
|
||||
if (uwsgi_jvm_exception() || !ujwsgi.app_mid) {
|
||||
jmethodID mid = uwsgi_jvm_get_method_id(ujwsgi.app_class, "<init>", "()V");
|
||||
if (uwsgi_jvm_exception() || !mid) exit(1);
|
||||
ujwsgi.app_instance = (*ujvm_env)->NewObject(ujvm_env, ujwsgi.app_class, mid);
|
||||
if (uwsgi_jvm_exception() || !ujwsgi.app_instance) {
|
||||
exit(1);
|
||||
}
|
||||
ujwsgi.app_mid = uwsgi_jvm_get_method_id(ujwsgi.app_class, method, "(Ljava/util/HashMap;)[Ljava/lang/Object;");
|
||||
if (uwsgi_jvm_exception() || !ujwsgi.app_mid) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("JWSGI app \"%s\" loaded\n", ujwsgi.app);
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
struct uwsgi_plugin objc_gc_plugin = {
|
||||
.name = "objc_gc",
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
NAME="objc_gc"
|
||||
CFLAGS=["-fobjc-gc"]
|
||||
LDFLAGS=[]
|
||||
LIBS=[]
|
||||
GCC_LIST=['objc_gc.m']
|
||||
@@ -81,6 +81,16 @@ XS(XS_signal) {
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
|
||||
XS(XS_set_user_harakiri) {
|
||||
dXSARGS;
|
||||
|
||||
psgi_check_args(1);
|
||||
|
||||
set_user_harakiri( SvIV(ST(0)) );
|
||||
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
|
||||
XS(XS_reload) {
|
||||
dXSARGS;
|
||||
|
||||
@@ -549,5 +559,7 @@ void init_perl_embedded_module() {
|
||||
|
||||
psgi_xs(add_timer);
|
||||
psgi_xs(add_rb_timer);
|
||||
|
||||
psgi_xs(set_user_harakiri);
|
||||
}
|
||||
|
||||
|
||||
+15
-41
@@ -41,47 +41,6 @@ void (*uwsgi_pypy_post_fork_hook)(void);
|
||||
extern struct uwsgi_server uwsgi;
|
||||
struct uwsgi_plugin pypy_plugin;
|
||||
|
||||
int uwsgi_pypy_helper_masterpid() {
|
||||
if (uwsgi.master_process) {
|
||||
return uwsgi.workers[0].pid;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_pypy_helper_worker_id() {
|
||||
return uwsgi.mywid;
|
||||
}
|
||||
|
||||
int uwsgi_pypy_helper_mule_id() {
|
||||
return uwsgi.muleid;
|
||||
}
|
||||
|
||||
void uwsgi_pypy_helper_signal(int signum) {
|
||||
uwsgi_signal_send(uwsgi.signal_socket, signum);
|
||||
}
|
||||
|
||||
struct uwsgi_opt **uwsgi_pypy_helper_opts(int *n) {
|
||||
*n = uwsgi.exported_opts_cnt;
|
||||
return uwsgi.exported_opts;
|
||||
}
|
||||
|
||||
char *uwsgi_pypy_helper_version() {
|
||||
return UWSGI_VERSION;
|
||||
}
|
||||
|
||||
int uwsgi_pypy_helper_register_signal(int signum, char *kind, void *handler) {
|
||||
return uwsgi_register_signal(signum, kind, handler, pypy_plugin.modifier1);
|
||||
}
|
||||
|
||||
int uwsgi_pypy_helper_register_rpc(char *name, int argc, void *func) {
|
||||
return uwsgi_register_rpc(name, &pypy_plugin, argc, func);
|
||||
}
|
||||
|
||||
struct iovec *uwsgi_pypy_helper_environ(struct wsgi_request *wsgi_req, uint16_t *len) {
|
||||
*len = wsgi_req->var_cnt;
|
||||
return wsgi_req->hvec;
|
||||
}
|
||||
|
||||
static int uwsgi_pypy_init() {
|
||||
|
||||
size_t rlen = 0;
|
||||
@@ -342,6 +301,20 @@ static void uwsgi_pypy_onload() {
|
||||
#endif
|
||||
}
|
||||
|
||||
static int uwsgi_pypy_mule(char *opt) {
|
||||
|
||||
if (uwsgi_endswith(opt, ".py")) {
|
||||
size_t rlen = 0;
|
||||
char *buffer = uwsgi_open_and_read(opt, &rlen, 1, NULL);
|
||||
pypy_execute_source(buffer);
|
||||
free(buffer);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_plugin pypy_plugin = {
|
||||
.name = "pypy",
|
||||
.modifier1 = 0,
|
||||
@@ -357,4 +330,5 @@ struct uwsgi_plugin pypy_plugin = {
|
||||
.enable_threads = uwsgi_pypy_enable_threads,
|
||||
.rpc = uwsgi_pypy_rpc,
|
||||
.post_fork = uwsgi_pypy_post_fork,
|
||||
.mule = uwsgi_pypy_mule,
|
||||
};
|
||||
|
||||
+508
-72
@@ -14,69 +14,230 @@ import cffi
|
||||
|
||||
# this is a list holding object we do not want to be freed (like callback and handlers)
|
||||
uwsgi_gc = []
|
||||
# the main ffi
|
||||
ffi = cffi.FFI()
|
||||
|
||||
defines = '''
|
||||
# the hooks we need to patch
|
||||
hooks = '''
|
||||
void free(void *);
|
||||
ssize_t read(int, void *, size_t);
|
||||
ssize_t write(int, const void *, size_t);
|
||||
int close(int);
|
||||
|
||||
void (*uwsgi_pypy_hook_loader)(char *);
|
||||
void (*uwsgi_pypy_hook_file_loader)(char *);
|
||||
void (*uwsgi_pypy_hook_pythonpath)(char *);
|
||||
void (*uwsgi_pypy_hook_request)(void *, int);
|
||||
void (*uwsgi_pypy_hook_request)(struct wsgi_request *);
|
||||
void (*uwsgi_pypy_post_fork_hook)(void);
|
||||
'''
|
||||
|
||||
# here we load CFLAGS and uwsgi.h from the binary
|
||||
defines0 = '''
|
||||
char *uwsgi_get_cflags();
|
||||
char *uwsgi_get_dot_h();
|
||||
'''
|
||||
ffi.cdef(defines0)
|
||||
lib0 = ffi.verify(defines0)
|
||||
|
||||
|
||||
# this is ugly, we should find a better approach
|
||||
# basically it build a list of #define from binary CFLAGS
|
||||
uwsgi_cdef = []
|
||||
uwsgi_defines = []
|
||||
uwsgi_cflags = ffi.string(lib0.uwsgi_get_cflags()).split()
|
||||
for cflag in uwsgi_cflags:
|
||||
if cflag.startswith('-D'):
|
||||
line = cflag[2:]
|
||||
if '=' in line:
|
||||
(key, value) = line.split('=', 1)
|
||||
uwsgi_cdef.append('#define %s ...' % key)
|
||||
uwsgi_defines.append('#define %s %s' % (key, value.replace('\\"','"').replace('""','"')))
|
||||
else:
|
||||
uwsgi_cdef.append('#define %s ...' % line)
|
||||
uwsgi_defines.append('#define %s 1' % line)
|
||||
uwsgi_dot_h = ffi.string(lib0.uwsgi_get_dot_h())
|
||||
|
||||
# uwsgi definitions
|
||||
cdefines = '''
|
||||
%s
|
||||
|
||||
struct iovec {
|
||||
char *iov_base;
|
||||
uint64_t iov_len;
|
||||
void *iov_base;
|
||||
size_t iov_len;
|
||||
...;
|
||||
};
|
||||
|
||||
struct uwsgi_header {
|
||||
uint8_t modifier1;
|
||||
...;
|
||||
};
|
||||
|
||||
struct wsgi_request {
|
||||
int fd;
|
||||
int async_id;
|
||||
uint16_t var_cnt;
|
||||
struct iovec *hvec;
|
||||
|
||||
int async_ready_fd;
|
||||
int async_last_ready_fd;
|
||||
|
||||
int suspended;
|
||||
|
||||
struct uwsgi_header *uh;
|
||||
...;
|
||||
};
|
||||
|
||||
struct uwsgi_opt {
|
||||
char *key;
|
||||
char *value;
|
||||
int configured;
|
||||
char *key;
|
||||
char *value;
|
||||
...;
|
||||
};
|
||||
|
||||
struct uwsgi_worker {
|
||||
int id;
|
||||
int pid;
|
||||
uint64_t requests;
|
||||
uint64_t delta_requests;
|
||||
uint64_t signals;
|
||||
|
||||
int cheaped;
|
||||
int suspended;
|
||||
int sig;
|
||||
uint8_t signum;
|
||||
|
||||
uint64_t running_time;
|
||||
uint64_t avg_response_time;
|
||||
uint64_t tx;
|
||||
...;
|
||||
};
|
||||
|
||||
struct uwsgi_plugin {
|
||||
uint8_t modifier1;
|
||||
|
||||
void (*suspend) (struct wsgi_request *);
|
||||
void (*resume) (struct wsgi_request *);
|
||||
...;
|
||||
};
|
||||
|
||||
struct uwsgi_buffer {
|
||||
char *buf;
|
||||
size_t pos;
|
||||
...;
|
||||
};
|
||||
|
||||
struct uwsgi_server {
|
||||
char hostname[];
|
||||
int mywid;
|
||||
int muleid;
|
||||
int master_process;
|
||||
|
||||
struct uwsgi_opt **exported_opts;
|
||||
int exported_opts_cnt;
|
||||
|
||||
struct uwsgi_worker *workers;
|
||||
|
||||
int signal_socket;
|
||||
int numproc;
|
||||
int async;
|
||||
|
||||
void (*schedule_to_main) (struct wsgi_request *);
|
||||
void (*schedule_to_req) (void);
|
||||
|
||||
struct wsgi_request *(*current_wsgi_req) (void);
|
||||
|
||||
struct wsgi_request *wsgi_req;
|
||||
|
||||
struct uwsgi_plugin *p[];
|
||||
...;
|
||||
};
|
||||
struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_plugin *pypy_plugin;
|
||||
|
||||
const char *uwsgi_pypy_version;
|
||||
|
||||
char *uwsgi_binary_path();
|
||||
void uwsgi_set_processname(char *);
|
||||
void uwsgi_alarm_trigger(char *, char *, uint64_t);
|
||||
int uwsgi_signal_registered(uint8_t);
|
||||
|
||||
int uwsgi_response_write_body_do(void *, char *, uint64_t);
|
||||
int uwsgi_response_sendfile_do_can_close(void *, int, uint64_t, uint64_t, int);
|
||||
int uwsgi_response_prepare_headers(void *, char *, uint16_t);
|
||||
int uwsgi_response_add_header(void *, char *, uint16_t, char *, uint16_t);
|
||||
char *uwsgi_request_body_read(void *, uint64_t, int64_t *);
|
||||
char *uwsgi_request_body_readline(void *, uint64_t, int64_t *);
|
||||
int uwsgi_response_prepare_headers(struct wsgi_request *, char *, size_t);
|
||||
int uwsgi_response_add_header(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
|
||||
int uwsgi_response_write_body_do(struct wsgi_request *, char *, size_t);
|
||||
int uwsgi_response_sendfile_do_can_close(struct wsgi_request *, int, size_t, size_t, int);
|
||||
|
||||
struct iovec *uwsgi_pypy_helper_environ(void *, uint16_t *);
|
||||
char *uwsgi_request_body_read(struct wsgi_request *, ssize_t , ssize_t *);
|
||||
char *uwsgi_request_body_readline(struct wsgi_request *, ssize_t, ssize_t *);
|
||||
|
||||
char *uwsgi_pypy_helper_version();
|
||||
int uwsgi_pypy_helper_register_signal(int, char *, void *);
|
||||
int uwsgi_pypy_helper_register_rpc(char *, int, void *);
|
||||
void uwsgi_pypy_helper_signal(int);
|
||||
struct uwsgi_opt** uwsgi_pypy_helper_opts(int *);
|
||||
int uwsgi_pypy_helper_masterpid();
|
||||
int uwsgi_pypy_helper_worker_id();
|
||||
int uwsgi_pypy_helper_mule_id();
|
||||
void uwsgi_buffer_destroy(struct uwsgi_buffer *);
|
||||
int uwsgi_is_again();
|
||||
|
||||
int uwsgi_register_rpc(char *, struct uwsgi_plugin *, uint8_t, void *);
|
||||
int uwsgi_register_signal(uint8_t, char *, void *, uint8_t);
|
||||
|
||||
char *uwsgi_cache_magic_get(char *, uint64_t, uint64_t *, uint64_t *, char *);
|
||||
int uwsgi_cache_magic_set(char *, uint64_t, char *, uint64_t, uint64_t, uint64_t, char *);
|
||||
int uwsgi_cache_magic_del(char *, uint64_t, char *);
|
||||
int uwsgi_add_timer(uint8_t, int);
|
||||
int uwsgi_add_rb_timer(uint8_t, int, int);
|
||||
int uwsgi_add_file_monitor(uint8_t, char *);
|
||||
char *uwsgi_do_rpc(char *, char *, uint8_t, char **, uint16_t *, uint16_t *);
|
||||
int uwsgi_signal_add_cron(uint8_t, int, int, int, int, int);
|
||||
|
||||
void uwsgi_set_processname(char *);
|
||||
int uwsgi_signal_send(int, uint8_t);
|
||||
uint64_t uwsgi_worker_exceptions(int);
|
||||
int uwsgi_worker_is_busy(int);
|
||||
|
||||
char *uwsgi_cache_magic_get(char *, uint16_t, uint64_t *, uint64_t *, char *);
|
||||
int uwsgi_cache_magic_set(char *, uint16_t, char *, uint64_t, uint64_t, uint64_t, char *);
|
||||
int uwsgi_cache_magic_del(char *, uint16_t, char *);
|
||||
int uwsgi_cache_magic_exists(char *, uint16_t, char *);
|
||||
int uwsgi_cache_magic_clear(char *);
|
||||
|
||||
int uwsgi_add_file_monitor(uint8_t, char *);
|
||||
int uwsgi_add_timer(uint8_t, int);
|
||||
int uwsgi_signal_add_rb_timer(uint8_t, int, int);
|
||||
|
||||
int uwsgi_user_lock(int);
|
||||
int uwsgi_user_unlock(int);
|
||||
|
||||
'''
|
||||
int uwsgi_signal_registered(uint8_t);
|
||||
|
||||
ffi = cffi.FFI()
|
||||
ffi.cdef(defines)
|
||||
lib = ffi.verify(defines)
|
||||
int uwsgi_signal_add_cron(uint8_t, int, int, int, int, int);
|
||||
void uwsgi_alarm_trigger(char *, char *, size_t);
|
||||
|
||||
void async_schedule_to_req_green(void);
|
||||
void async_add_timeout(struct wsgi_request *, int);
|
||||
int async_add_fd_write(struct wsgi_request *, int, int);
|
||||
int async_add_fd_read(struct wsgi_request *, int, int);
|
||||
int uwsgi_connect(char *, int, int);
|
||||
|
||||
int uwsgi_websocket_handshake(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
|
||||
int uwsgi_websocket_send(struct wsgi_request *, char *, size_t);
|
||||
struct uwsgi_buffer *uwsgi_websocket_recv(struct wsgi_request *);
|
||||
struct uwsgi_buffer *uwsgi_websocket_recv_nb(struct wsgi_request *);
|
||||
|
||||
char *uwsgi_chunked_read(struct wsgi_request *, size_t *, int, int);
|
||||
|
||||
void uwsgi_disconnect(struct wsgi_request *);
|
||||
|
||||
int uwsgi_ready_fd(struct wsgi_request *);
|
||||
|
||||
void set_user_harakiri(int);
|
||||
|
||||
%s
|
||||
|
||||
''' % ('\n'.join(uwsgi_cdef), hooks)
|
||||
|
||||
cverify = '''
|
||||
%s
|
||||
|
||||
const char *uwsgi_pypy_version = UWSGI_VERSION;
|
||||
|
||||
%s
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_plugin *pypy_plugin;
|
||||
%s
|
||||
''' % ('\n'.join(uwsgi_defines), uwsgi_dot_h, hooks)
|
||||
|
||||
ffi.cdef(cdefines)
|
||||
lib = ffi.verify(cverify)
|
||||
libc = ffi.dlopen(None)
|
||||
|
||||
|
||||
|
||||
"""
|
||||
this is a global object point the the WSGI callable
|
||||
it sucks, i will fix it in the near future...
|
||||
@@ -115,7 +276,7 @@ def uwsgi_pypy_file_loader(filename):
|
||||
wsgi_application = getattr(mod, c)
|
||||
|
||||
"""
|
||||
.post_fork_hokk
|
||||
.post_fork_hook
|
||||
"""
|
||||
@ffi.callback("void()")
|
||||
def uwsgi_pypy_post_fork_hook():
|
||||
@@ -180,7 +341,7 @@ class WSGIinput(object):
|
||||
raise IOError("error waiting for wsgi.input")
|
||||
|
||||
def getline(self, hint=0):
|
||||
rlen = ffi.new('int64_t*')
|
||||
rlen = ffi.new('ssize_t*')
|
||||
chunk = lib.uwsgi_request_body_readline(self.wsgi_req, hint, rlen)
|
||||
if chunk != ffi.NULL:
|
||||
return ffi.string(chunk, rlen[0])
|
||||
@@ -213,8 +374,9 @@ class WSGIinput(object):
|
||||
"""
|
||||
the WSGI request handler
|
||||
"""
|
||||
@ffi.callback("void(void *, int)")
|
||||
def uwsgi_pypy_wsgi_handler(wsgi_req, core):
|
||||
@ffi.callback("void(struct wsgi_request *)")
|
||||
def uwsgi_pypy_wsgi_handler(wsgi_req):
|
||||
import uwsgi
|
||||
global wsgi_application
|
||||
|
||||
def writer(data):
|
||||
@@ -229,10 +391,9 @@ def uwsgi_pypy_wsgi_handler(wsgi_req, core):
|
||||
return writer
|
||||
|
||||
environ = {}
|
||||
nv = ffi.new("uint16_t*")
|
||||
iov = lib.uwsgi_pypy_helper_environ(wsgi_req, nv)
|
||||
for i in range(0, nv[0], 2):
|
||||
environ[ffi.string(iov[i].iov_base, iov[i].iov_len)] = ffi.string(iov[i+1].iov_base, iov[i+1].iov_len)
|
||||
iov = wsgi_req.hvec
|
||||
for i in range(0, wsgi_req.var_cnt, 2):
|
||||
environ[ffi.string(ffi.cast("char*", iov[i].iov_base), iov[i].iov_len)] = ffi.string(ffi.cast("char*", iov[i+1].iov_base), iov[i+1].iov_len)
|
||||
|
||||
environ['wsgi.version'] = (1, 0)
|
||||
scheme = 'http'
|
||||
@@ -247,7 +408,8 @@ def uwsgi_pypy_wsgi_handler(wsgi_req, core):
|
||||
environ['wsgi.multithread'] = True
|
||||
environ['wsgi.multiprocess'] = True
|
||||
|
||||
environ['uwsgi.core'] = core
|
||||
environ['uwsgi.core'] = wsgi_req.async_id
|
||||
environ['uwsgi.node'] = uwsgi.hostname
|
||||
|
||||
response = wsgi_application(environ, start_response)
|
||||
if type(response) is str:
|
||||
@@ -281,13 +443,13 @@ Here we define the "uwsgi" virtual module
|
||||
|
||||
uwsgi = imp.new_module('uwsgi')
|
||||
sys.modules['uwsgi'] = uwsgi
|
||||
uwsgi.version = ffi.string(lib.uwsgi_pypy_helper_version())
|
||||
|
||||
uwsgi.version = ffi.string(lib.uwsgi_pypy_version)
|
||||
uwsgi.hostname = ffi.string(lib.uwsgi.hostname)
|
||||
|
||||
def uwsgi_pypy_uwsgi_register_signal(signum, kind, handler):
|
||||
cb = ffi.callback('void(int)', handler)
|
||||
uwsgi_gc.append(cb)
|
||||
if lib.uwsgi_pypy_helper_register_signal(signum, ffi.new("char[]", kind), cb) < 0:
|
||||
if lib.uwsgi_register_signal(signum, ffi.new("char[]", kind), cb, lib.pypy_plugin.modifier1) < 0:
|
||||
raise Exception("unable to register signal %d" % signum)
|
||||
uwsgi.register_signal = uwsgi_pypy_uwsgi_register_signal
|
||||
|
||||
@@ -311,7 +473,7 @@ def uwsgi_pypy_uwsgi_register_rpc(name, func, argc=0):
|
||||
rpc_func = uwsgi_pypy_RPC(func)
|
||||
cb = ffi.callback("int(int, char*[], int[], char*)", rpc_func)
|
||||
uwsgi_gc.append(cb)
|
||||
if lib.uwsgi_pypy_helper_register_rpc(ffi.new("char[]", name), argc, cb) < 0:
|
||||
if lib.uwsgi_register_rpc(ffi.new("char[]", name), lib.pypy_plugin, argc, cb) < 0:
|
||||
raise Exception("unable to register rpc func %s" % name)
|
||||
uwsgi.register_rpc = uwsgi_pypy_uwsgi_register_rpc
|
||||
|
||||
@@ -350,9 +512,7 @@ def uwsgi_pypy_call(func, *args):
|
||||
return uwsgi_pypy_rpc(node, func, *args)
|
||||
uwsgi.call = uwsgi_pypy_call
|
||||
|
||||
def uwsgi_pypy_uwsgi_signal(signum):
|
||||
lib.uwsgi_pypy_helper_signal(signum)
|
||||
uwsgi.signal = uwsgi_pypy_uwsgi_signal
|
||||
uwsgi.signal = lambda x: lib.uwsgi_signal_send(lib.uwsgi.signal_socket, x)
|
||||
|
||||
|
||||
def uwsgi_pypy_uwsgi_cache_get(key, cache=ffi.NULL):
|
||||
@@ -387,7 +547,7 @@ def uwsgi_pypy_uwsgi_add_timer(signum, secs):
|
||||
uwsgi.add_timer = uwsgi_pypy_uwsgi_add_timer
|
||||
|
||||
def uwsgi_pypy_uwsgi_add_rb_timer(signum, secs):
|
||||
if lib.uwsgi_add_rb_timer(signum, secs, 0) < 0:
|
||||
if lib.uwsgi_signal_add_rb_timer(signum, secs, 0) < 0:
|
||||
raise Exception("unable to register redblack timer")
|
||||
uwsgi.add_rb_timer = uwsgi_pypy_uwsgi_add_rb_timer
|
||||
|
||||
@@ -397,27 +557,25 @@ def uwsgi_pypy_uwsgi_add_file_monitor(signum, filename):
|
||||
raise Exception("unable to register file monitor")
|
||||
uwsgi.add_file_monitor = uwsgi_pypy_uwsgi_add_file_monitor
|
||||
|
||||
def uwsgi_pypy_lock(num):
|
||||
def uwsgi_pypy_lock(num=0):
|
||||
if lib.uwsgi_user_lock(num) < 0:
|
||||
raise Exception("invalid lock")
|
||||
uwsgi.lock = uwsgi_pypy_lock
|
||||
|
||||
def uwsgi_pypy_unlock(num):
|
||||
def uwsgi_pypy_unlock(num=0):
|
||||
if lib.uwsgi_user_unlock(num) < 0:
|
||||
raise Exception("invalid lock")
|
||||
uwsgi.unlock = uwsgi_pypy_unlock
|
||||
|
||||
def uwsgi_pypy_masterpid():
|
||||
return lib.uwsgi_pypy_helper_masterpid()
|
||||
if lib.uwsgi.master_process:
|
||||
return lib.uwsgi.workers[0].pid
|
||||
return 0
|
||||
uwsgi.masterpid = uwsgi_pypy_masterpid
|
||||
|
||||
def uwsgi_pypy_worker_id():
|
||||
return lib.uwsgi_pypy_helper_worker_id()
|
||||
uwsgi.worker_id = uwsgi_pypy_worker_id
|
||||
uwsgi.worker_id = lambda: lib.uwsgi.mywid
|
||||
|
||||
def uwsgi_pypy_mule_id():
|
||||
return lib.uwsgi_pypy_helper_mule_id()
|
||||
uwsgi.mule_id = uwsgi_pypy_mule_id
|
||||
uwsgi.mule_id = lambda: lib.uwsgi.muleid
|
||||
|
||||
def uwsgi_pypy_signal_registered(signum):
|
||||
if lib.uwsgi_signal_registered(signum) > 0:
|
||||
@@ -429,28 +587,24 @@ def uwsgi_pypy_alarm(alarm, msg):
|
||||
lib.uwsgi_alarm_trigger(ffi.new('char[]', alarm), ffi.new('char[]', msg), len(msg))
|
||||
uwsgi.alarm = uwsgi_pypy_alarm
|
||||
|
||||
def uwsgi_pypy_setprocname(name):
|
||||
lib.uwsgi_set_processname(ffi.new('char[]',name))
|
||||
uwsgi.setprocname = uwsgi_pypy_setprocname
|
||||
uwsgi.setprocname = lambda name: lib.uwsgi_set_processname(ffi.new('char[]', name))
|
||||
|
||||
def uwsgi_pypy_add_cron(signum, minute, hour, day, month, week):
|
||||
if lib.uwsgi_signal_add_cron(signum, minute, hour, day, month, week) < 0:
|
||||
raise Exception("unable to register cron")
|
||||
return True
|
||||
uwsgi.add_cron = uwsgi_pypy_add_cron
|
||||
|
||||
"""
|
||||
populate uwsgi.opt
|
||||
"""
|
||||
uwsgi.opt = {}
|
||||
n_opts = ffi.new('int*')
|
||||
u_opts = lib.uwsgi_pypy_helper_opts(n_opts)
|
||||
for i in range(0, n_opts[0]):
|
||||
k = ffi.string(u_opts[i].key)
|
||||
if u_opts[i].value == ffi.NULL:
|
||||
for i in range(0, lib.uwsgi.exported_opts_cnt):
|
||||
uo = lib.uwsgi.exported_opts[i]
|
||||
k = ffi.string(uo.key)
|
||||
if uo.value == ffi.NULL:
|
||||
v = True
|
||||
else:
|
||||
v = ffi.string(u_opts[i].value)
|
||||
v = ffi.string(uo.value)
|
||||
if k in uwsgi.opt:
|
||||
if type(uwsgi.opt[k]) is list:
|
||||
uwsgi.opt[k].append(v)
|
||||
@@ -459,5 +613,287 @@ for i in range(0, n_opts[0]):
|
||||
else:
|
||||
uwsgi.opt[k] = v
|
||||
|
||||
def uwsgi_pypy_current_wsgi_req():
|
||||
wsgi_req = lib.uwsgi.current_wsgi_req()
|
||||
if wsgi_req == ffi.NULL:
|
||||
raise Exception("unable to get current wsgi_request, check your setup !!!")
|
||||
return wsgi_req
|
||||
|
||||
"""
|
||||
uwsgi.suspend()
|
||||
"""
|
||||
def uwsgi_pypy_suspend():
|
||||
wsgi_req = uwsgi_pypy_current_wsgi_req()
|
||||
if lib.uwsgi.schedule_to_main:
|
||||
lib.uwsgi.schedule_to_main(wsgi_req);
|
||||
uwsgi.suspend = uwsgi_pypy_suspend
|
||||
|
||||
"""
|
||||
uwsgi.workers()
|
||||
"""
|
||||
def uwsgi_pypy_workers():
|
||||
workers = []
|
||||
for i in range(1, lib.uwsgi.numproc+1):
|
||||
worker = {}
|
||||
worker['id'] = lib.uwsgi.workers[i].id
|
||||
worker['pid'] = lib.uwsgi.workers[i].pid
|
||||
worker['requests'] = lib.uwsgi.workers[i].requests
|
||||
worker['delta_requests'] = lib.uwsgi.workers[i].delta_requests
|
||||
worker['signals'] = lib.uwsgi.workers[i].signals
|
||||
worker['exceptions'] = lib.uwsgi_worker_exceptions(i);
|
||||
worker['apps'] = []
|
||||
if lib.uwsgi.workers[i].cheaped:
|
||||
worker['status'] == 'cheap'
|
||||
elif lib.uwsgi.workers[i].suspended and not lib.uwsgi_worker_is_busy(i):
|
||||
worker['status'] == 'pause'
|
||||
else:
|
||||
if lib.uwsgi.workers[i].sig:
|
||||
worker['status'] = 'sig%d' % lib.uwsgi.workers[i].signum
|
||||
elif lib.uwsgi_worker_is_busy(i):
|
||||
worker['status'] = 'busy'
|
||||
else:
|
||||
worker['status'] = 'idle'
|
||||
worker['running_time'] = lib.uwsgi.workers[i].running_time
|
||||
worker['avg_rt'] = lib.uwsgi.workers[i].avg_response_time
|
||||
worker['tx'] = lib.uwsgi.workers[i].tx
|
||||
|
||||
workers.append(worker)
|
||||
return workers
|
||||
|
||||
uwsgi.workers = uwsgi_pypy_workers
|
||||
|
||||
"""
|
||||
uwsgi.async_sleep(timeout)
|
||||
"""
|
||||
def uwsgi_pypy_async_sleep(timeout):
|
||||
if timeout > 0:
|
||||
wsgi_req = uwsgi_pypy_current_wsgi_req();
|
||||
lib.async_add_timeout(wsgi_req, timeout);
|
||||
uwsgi.async_sleep = uwsgi_pypy_async_sleep
|
||||
|
||||
"""
|
||||
uwsgi.async_connect(addr)
|
||||
"""
|
||||
def uwsgi_pypy_async_connect(addr):
|
||||
fd = lib.uwsgi_connect(ffi.new('char[]', addr), 0, 1)
|
||||
if fd < 0:
|
||||
raise Exception("unable to connect to %s" % addr)
|
||||
return fd
|
||||
uwsgi.async_connect = uwsgi_pypy_async_connect
|
||||
|
||||
uwsgi.connection_fd = lambda: uwsgi_pypy_current_wsgi_req().fd
|
||||
|
||||
"""
|
||||
uwsgi.wait_fd_read(fd, timeout=0)
|
||||
"""
|
||||
def uwsgi_pypy_wait_fd_read(fd, timeout=0):
|
||||
wsgi_req = uwsgi_pypy_current_wsgi_req();
|
||||
if lib.async_add_fd_read(wsgi_req, fd, timeout) < 0:
|
||||
raise Exception("unable to add fd %d to the event queue" % fd)
|
||||
uwsgi.wait_fd_read = uwsgi_pypy_wait_fd_read
|
||||
|
||||
"""
|
||||
uwsgi.wait_fd_write(fd, timeout=0)
|
||||
"""
|
||||
def uwsgi_pypy_wait_fd_write(fd, timeout=0):
|
||||
wsgi_req = uwsgi_pypy_current_wsgi_req();
|
||||
if lib.async_add_fd_write(wsgi_req, fd, timeout) < 0:
|
||||
raise Exception("unable to add fd %d to the event queue" % fd)
|
||||
uwsgi.wait_fd_write = uwsgi_pypy_wait_fd_write
|
||||
|
||||
"""
|
||||
uwsgi.ready_fd()
|
||||
"""
|
||||
def uwsgi_pypy_ready_fd():
|
||||
wsgi_req = uwsgi_pypy_current_wsgi_req();
|
||||
return lib.uwsgi_ready_fd(wsgi_req)
|
||||
uwsgi.ready_fd = uwsgi_pypy_ready_fd
|
||||
|
||||
|
||||
"""
|
||||
uwsgi.send(fd=None,data)
|
||||
"""
|
||||
def uwsgi_pypy_send(*args):
|
||||
if len(args) == 0:
|
||||
raise ValueError("uwsgi.send() takes at least 1 argument")
|
||||
elif len(args) == 1:
|
||||
wsgi_req = uwsgi_pypy_current_wsgi_req();
|
||||
fd = wsgi_req.fd
|
||||
data = args[0]
|
||||
else:
|
||||
fd = args[0]
|
||||
data = args[1]
|
||||
rlen = libc.write(fd, data, len(data))
|
||||
if rlen <= 0:
|
||||
raise IOError("unable to send data")
|
||||
return rlen
|
||||
uwsgi.send = uwsgi_pypy_send
|
||||
|
||||
"""
|
||||
uwsgi.recv(fd=None,len)
|
||||
"""
|
||||
def uwsgi_pypy_recv(*args):
|
||||
if len(args) == 0:
|
||||
raise ValueError("uwsgi.recv() takes at least 1 argument")
|
||||
elif len(args) == 1:
|
||||
wsgi_req = uwsgi_pypy_current_wsgi_req();
|
||||
fd = wsgi_req.fd
|
||||
l = args[0]
|
||||
else:
|
||||
fd = args[0]
|
||||
l = args[1]
|
||||
data = ffi.new('char[%d]' % l)
|
||||
rlen = libc.read(fd, data, l)
|
||||
if rlen <= 0:
|
||||
raise IOError("unable to receive data")
|
||||
return ffi.string(data[0:rlen])
|
||||
uwsgi.recv = uwsgi_pypy_recv
|
||||
|
||||
"""
|
||||
uwsgi.close(fd)
|
||||
"""
|
||||
uwsgi.close = lambda fd: lib.close(fd)
|
||||
|
||||
"""
|
||||
uwsgi.disconnect()
|
||||
"""
|
||||
uwsgi.disconnect = lambda: lib.uwsgi_disconnect(uwsgi_pypy_current_wsgi_req())
|
||||
|
||||
"""
|
||||
uwsgi.websocket_recv()
|
||||
"""
|
||||
def uwsgi_pypy_websocket_recv():
|
||||
wsgi_req = uwsgi_pypy_current_wsgi_req();
|
||||
ub = lib.uwsgi_websocket_recv(wsgi_req);
|
||||
if ub == ffi.NULL:
|
||||
raise IOError("unable to receive websocket message")
|
||||
ret = ffi.string(ub.buf, ub.pos)
|
||||
lib.uwsgi_buffer_destroy(ub)
|
||||
return ret
|
||||
uwsgi.websocket_recv = uwsgi_pypy_websocket_recv
|
||||
|
||||
"""
|
||||
uwsgi.websocket_recv_nb()
|
||||
"""
|
||||
def uwsgi_pypy_websocket_recv_nb():
|
||||
wsgi_req = uwsgi_pypy_current_wsgi_req();
|
||||
ub = lib.uwsgi_websocket_recv_nb(wsgi_req);
|
||||
if ub == ffi.NULL:
|
||||
raise IOError("unable to receive websocket message")
|
||||
ret = ffi.string(ub.buf, ub.pos)
|
||||
lib.uwsgi_buffer_destroy(ub)
|
||||
return ret
|
||||
uwsgi.websocket_recv_nb = uwsgi_pypy_websocket_recv_nb
|
||||
|
||||
"""
|
||||
uwsgi.websocket_handshake(key, origin)
|
||||
"""
|
||||
def uwsgi_pypy_websocket_handshake(key, origin=''):
|
||||
wsgi_req = uwsgi_pypy_current_wsgi_req();
|
||||
if lib.uwsgi_websocket_handshake(wsgi_req, ffi.new('char[]', key), len(key), ffi.new('char[]',origin), len(origin)) < 0:
|
||||
raise IOError("unable to complete websocket handshake")
|
||||
uwsgi.websocket_handshake = uwsgi_pypy_websocket_handshake
|
||||
|
||||
"""
|
||||
uwsgi.websocket_send(msg)
|
||||
"""
|
||||
def uwsgi_pypy_websocket_send(msg):
|
||||
wsgi_req = uwsgi_pypy_current_wsgi_req();
|
||||
if lib.uwsgi_websocket_send(wsgi_req, ffi.new('char[]', msg), len(msg)) < 0:
|
||||
raise IOError("unable to send websocket message")
|
||||
uwsgi.websocket_send = uwsgi_pypy_websocket_send
|
||||
|
||||
"""
|
||||
uwsgi.chunked_read(timeout=0)
|
||||
"""
|
||||
def uwsgi_pypy_chunked_read(timeout=0):
|
||||
wsgi_req = uwsgi_pypy_current_wsgi_req();
|
||||
rlen = ffi.new("size_t*")
|
||||
chunk = lib.uwsgi_chunked_read(wsgi_req, rlen, timeout, 0)
|
||||
if chunk == ffi.NULL:
|
||||
raise IOError("unable to receive chunked part")
|
||||
return ffi.string(chunk, rlen[0])
|
||||
uwsgi.chunked_read = uwsgi_pypy_chunked_read
|
||||
|
||||
"""
|
||||
uwsgi.chunked_read_nb()
|
||||
"""
|
||||
def uwsgi_pypy_chunked_read_nb():
|
||||
wsgi_req = uwsgi_pypy_current_wsgi_req();
|
||||
rlen = ffi.new("size_t*")
|
||||
chunk = lib.uwsgi_chunked_read(wsgi_req, rlen, 0, 1)
|
||||
if chunk == ffi.NULL:
|
||||
if lib.uwsgi_is_again() > 0:
|
||||
return None
|
||||
raise IOError("unable to receive chunked part")
|
||||
|
||||
return ffi.string(chunk, rlen[0])
|
||||
uwsgi.chunked_read_nb = uwsgi_pypy_chunked_read_nb
|
||||
|
||||
"""
|
||||
uwsgi.set_user_harakiri(sec)
|
||||
"""
|
||||
uwsgi.set_user_harakiri = lambda x: lib.set_user_harakiri(x)
|
||||
|
||||
|
||||
print "Initialized PyPy with Python", sys.version
|
||||
print "PyPy Home:", sys.prefix
|
||||
|
||||
|
||||
"""
|
||||
Continulets support
|
||||
"""
|
||||
|
||||
# this is the dictionary of continulets (one per-core)
|
||||
uwsgi_pypy_continulets = {}
|
||||
|
||||
|
||||
def uwsgi_pypy_continulet_wrapper(cont):
|
||||
lib.async_schedule_to_req_green()
|
||||
|
||||
@ffi.callback("void()")
|
||||
def uwsgi_pypy_continulet_schedule():
|
||||
id = lib.uwsgi.wsgi_req.async_id
|
||||
modifier1 = lib.uwsgi.wsgi_req.uh.modifier1;
|
||||
|
||||
# generate a new continulet
|
||||
if not lib.uwsgi.wsgi_req.suspended:
|
||||
from _continuation import continulet
|
||||
uwsgi_pypy_continulets[id] = continulet(uwsgi_pypy_continulet_wrapper)
|
||||
lib.uwsgi.wsgi_req.suspended = 1
|
||||
|
||||
# this is called in the main stack
|
||||
if lib.uwsgi.p[modifier1].suspend:
|
||||
lib.uwsgi.p[modifier1].suspend(ffi.NULL)
|
||||
|
||||
# let's switch
|
||||
uwsgi_pypy_continulets[id].switch()
|
||||
|
||||
# back to the main stack
|
||||
if lib.uwsgi.p[modifier1].resume:
|
||||
lib.uwsgi.p[modifier1].resume(ffi.NULL)
|
||||
|
||||
@ffi.callback("void(struct wsgi_request *)")
|
||||
def uwsgi_pypy_continulet_switch(wsgi_req):
|
||||
id = wsgi_req.async_id
|
||||
modifier1 = wsgi_req.uh.modifier1;
|
||||
|
||||
# this is called in the current continulet
|
||||
if lib.uwsgi.p[modifier1].suspend:
|
||||
lib.uwsgi.p[modifier1].suspend(wsgi_req)
|
||||
|
||||
uwsgi_pypy_continulets[id].switch()
|
||||
|
||||
# back to the continulet
|
||||
if lib.uwsgi.p[modifier1].resume:
|
||||
lib.uwsgi.p[modifier1].resume(wsgi_req)
|
||||
|
||||
# update current running continulet
|
||||
lib.uwsgi.wsgi_req = wsgi_req
|
||||
|
||||
def uwsgi_pypy_setup_continulets():
|
||||
if lib.uwsgi.async <= 1:
|
||||
raise Exception("pypy continulets require async mode !!!")
|
||||
lib.uwsgi.schedule_to_main = uwsgi_pypy_continulet_switch
|
||||
lib.uwsgi.schedule_to_req = uwsgi_pypy_continulet_schedule
|
||||
print "*** PyPy Continulets engine loaded ***"
|
||||
|
||||
@@ -1756,7 +1756,12 @@ void uwsgi_python_harakiri(int wid) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
# you can use this logger to offload logging to python
|
||||
# be sure to configure it to not log to stderr otherwise you will generate a loop
|
||||
import logging
|
||||
logging.basicConfig(filename='/tmp/pippo.log')
|
||||
*/
|
||||
ssize_t uwsgi_python_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
if (!Py_IsInitialized()) return -1;
|
||||
|
||||
|
||||
@@ -1063,6 +1063,42 @@ PyObject *py_uwsgi_websocket_send(PyObject * self, PyObject * args) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_chunked_read(PyObject * self, PyObject * args) {
|
||||
int timeout = 0;
|
||||
if (!PyArg_ParseTuple(args, "|i:chunked_read", &timeout)) {
|
||||
return NULL;
|
||||
}
|
||||
size_t len = 0;
|
||||
struct wsgi_request *wsgi_req = py_current_wsgi_req();
|
||||
UWSGI_RELEASE_GIL
|
||||
char *chunk = uwsgi_chunked_read(wsgi_req, &len, timeout, 0);
|
||||
UWSGI_GET_GIL
|
||||
if (!chunk) {
|
||||
return PyErr_Format(PyExc_IOError, "unable to receive chunked part");
|
||||
}
|
||||
|
||||
return PyString_FromStringAndSize(chunk, len);
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_chunked_read_nb(PyObject * self, PyObject * args) {
|
||||
size_t len = 0;
|
||||
struct wsgi_request *wsgi_req = py_current_wsgi_req();
|
||||
UWSGI_RELEASE_GIL
|
||||
char *chunk = uwsgi_chunked_read(wsgi_req, &len, 0, 1);
|
||||
UWSGI_GET_GIL
|
||||
if (!chunk) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
return PyErr_Format(PyExc_IOError, "unable to receive chunked part");
|
||||
}
|
||||
|
||||
return PyString_FromStringAndSize(chunk, len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
PyObject *py_uwsgi_websocket_recv(PyObject * self, PyObject * args) {
|
||||
struct wsgi_request *wsgi_req = py_current_wsgi_req();
|
||||
UWSGI_RELEASE_GIL
|
||||
@@ -2234,17 +2270,15 @@ PyObject *py_uwsgi_disconnect(PyObject * self, PyObject * args) {
|
||||
|
||||
struct wsgi_request *wsgi_req = py_current_wsgi_req();
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("disconnecting worker %d (pid :%d) from session...\n", uwsgi.mywid, uwsgi.mypid);
|
||||
#endif
|
||||
uwsgi_disconnect(wsgi_req);
|
||||
|
||||
if (wsgi_req->socket) {
|
||||
wsgi_req->socket->proto_close(wsgi_req);
|
||||
}
|
||||
wsgi_req->fd_closed = 1;
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
PyObject *py_uwsgi_ready_fd(PyObject * self, PyObject * args) {
|
||||
struct wsgi_request *wsgi_req = py_current_wsgi_req();
|
||||
return PyInt_FromLong(uwsgi_ready_fd(wsgi_req));
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_parse_file(PyObject * self, PyObject * args) {
|
||||
@@ -2484,6 +2518,11 @@ static PyMethodDef uwsgi_advanced_methods[] = {
|
||||
{"websocket_send", py_uwsgi_websocket_send, METH_VARARGS, ""},
|
||||
{"websocket_handshake", py_uwsgi_websocket_handshake, METH_VARARGS, ""},
|
||||
|
||||
{"chunked_read", py_uwsgi_chunked_read, METH_VARARGS, ""},
|
||||
{"chunked_read_nb", py_uwsgi_chunked_read_nb, METH_VARARGS, ""},
|
||||
|
||||
{"ready_fd", py_uwsgi_ready_fd, METH_VARARGS, ""},
|
||||
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
|
||||
+60
-51
@@ -7,7 +7,7 @@ extern struct uwsgi_plugin rack_plugin;
|
||||
|
||||
#define uwsgi_rack_api(x, y, z) rb_define_module_function(rb_uwsgi_embedded, x, y, z)
|
||||
|
||||
VALUE rack_uwsgi_warning(VALUE *class, VALUE rbmessage) {
|
||||
static VALUE rack_uwsgi_warning(VALUE *class, VALUE rbmessage) {
|
||||
|
||||
Check_Type(rbmessage, T_STRING);
|
||||
char *message = RSTRING_PTR(rbmessage);
|
||||
@@ -26,7 +26,14 @@ VALUE rack_uwsgi_warning(VALUE *class, VALUE rbmessage) {
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_log(VALUE *class, VALUE msg) {
|
||||
static VALUE rack_uwsgi_user_harakiri(VALUE *class, VALUE sec) {
|
||||
Check_Type(sec, T_FIXNUM);
|
||||
set_user_harakiri(NUM2INT(sec));
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
|
||||
static VALUE rack_uwsgi_log(VALUE *class, VALUE msg) {
|
||||
|
||||
Check_Type(msg, T_STRING);
|
||||
|
||||
@@ -35,7 +42,7 @@ VALUE rack_uwsgi_log(VALUE *class, VALUE msg) {
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_i_am_the_spooler(VALUE *class) {
|
||||
static VALUE rack_uwsgi_i_am_the_spooler(VALUE *class) {
|
||||
if (uwsgi.i_am_a_spooler) {
|
||||
return Qtrue;
|
||||
}
|
||||
@@ -43,7 +50,7 @@ VALUE rack_uwsgi_i_am_the_spooler(VALUE *class) {
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
VALUE rack_uwsgi_i_am_the_lord(VALUE *class, VALUE legion_name) {
|
||||
static VALUE rack_uwsgi_i_am_the_lord(VALUE *class, VALUE legion_name) {
|
||||
Check_Type(legion_name, T_STRING);
|
||||
if (uwsgi_legion_i_am_the_lord(RSTRING_PTR(legion_name))) {
|
||||
return Qtrue;
|
||||
@@ -54,7 +61,7 @@ VALUE rack_uwsgi_i_am_the_lord(VALUE *class, VALUE legion_name) {
|
||||
|
||||
|
||||
|
||||
VALUE rack_uwsgi_setprocname(VALUE *class, VALUE rbname) {
|
||||
static VALUE rack_uwsgi_setprocname(VALUE *class, VALUE rbname) {
|
||||
|
||||
Check_Type(rbname, T_STRING);
|
||||
char *name = RSTRING_PTR(rbname);
|
||||
@@ -63,7 +70,7 @@ VALUE rack_uwsgi_setprocname(VALUE *class, VALUE rbname) {
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_mem(VALUE *class) {
|
||||
static VALUE rack_uwsgi_mem(VALUE *class) {
|
||||
|
||||
uint64_t rss=0, vsz = 0;
|
||||
VALUE ml = rb_ary_new2(2);
|
||||
@@ -77,23 +84,23 @@ VALUE rack_uwsgi_mem(VALUE *class) {
|
||||
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_request_id(VALUE *class) {
|
||||
static VALUE rack_uwsgi_request_id(VALUE *class) {
|
||||
return ULONG2NUM(uwsgi.workers[uwsgi.mywid].requests);
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_worker_id(VALUE *class) {
|
||||
static VALUE rack_uwsgi_worker_id(VALUE *class) {
|
||||
return INT2NUM(uwsgi.mywid);
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_mule_id(VALUE *class) {
|
||||
static VALUE rack_uwsgi_mule_id(VALUE *class) {
|
||||
return INT2NUM(uwsgi.muleid);
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_logsize(VALUE *class) {
|
||||
static VALUE rack_uwsgi_logsize(VALUE *class) {
|
||||
return ULONG2NUM(uwsgi.shared->logsize);
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_mule_msg(int argc, VALUE *argv, VALUE *class) {
|
||||
static VALUE rack_uwsgi_mule_msg(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
int fd = -1;
|
||||
int mule_id = -1;
|
||||
@@ -151,7 +158,7 @@ VALUE rack_uwsgi_mule_msg(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
|
||||
|
||||
int uwsgi_ruby_hash_mule_callback(VALUE key, VALUE val, VALUE arg_array) {
|
||||
static int uwsgi_ruby_hash_mule_callback(VALUE key, VALUE val, VALUE arg_array) {
|
||||
Check_Type(key, T_SYMBOL);
|
||||
ID key_id = SYM2ID(key);
|
||||
const char *key_name = rb_id2name(key_id);
|
||||
@@ -172,7 +179,7 @@ int uwsgi_ruby_hash_mule_callback(VALUE key, VALUE val, VALUE arg_array) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_mule_get_msg(int argc, VALUE *argv, VALUE *class) {
|
||||
static VALUE rack_uwsgi_mule_get_msg(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
int manage_signals = 1;
|
||||
int manage_farms = 1;
|
||||
@@ -228,7 +235,7 @@ VALUE rack_uwsgi_mule_get_msg(int argc, VALUE *argv, VALUE *class) {
|
||||
}
|
||||
|
||||
|
||||
VALUE rack_uwsgi_lock(int argc, VALUE *argv, VALUE *class) {
|
||||
static VALUE rack_uwsgi_lock(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
int lock_num = 0;
|
||||
|
||||
@@ -246,7 +253,7 @@ VALUE rack_uwsgi_lock(int argc, VALUE *argv, VALUE *class) {
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_unlock(int argc, VALUE *argv, VALUE *class) {
|
||||
static VALUE rack_uwsgi_unlock(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
int lock_num = 0;
|
||||
|
||||
@@ -268,7 +275,7 @@ VALUE rack_uwsgi_unlock(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
|
||||
|
||||
VALUE rack_uwsgi_cache_set(int argc, VALUE *argv, VALUE *class) {
|
||||
static VALUE rack_uwsgi_cache_set(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
if (argc < 2) goto error;
|
||||
|
||||
@@ -304,7 +311,7 @@ error:
|
||||
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_cache_update(int argc, VALUE *argv, VALUE *class) {
|
||||
static VALUE rack_uwsgi_cache_update(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
if (argc < 2) goto error;
|
||||
|
||||
@@ -341,7 +348,7 @@ error:
|
||||
}
|
||||
|
||||
|
||||
VALUE rack_uwsgi_cache_set_exc(int argc, VALUE *argv, VALUE *class) {
|
||||
static VALUE rack_uwsgi_cache_set_exc(int argc, VALUE *argv, VALUE *class) {
|
||||
VALUE ret = rack_uwsgi_cache_set(argc, argv, class);
|
||||
if (ret == Qnil) {
|
||||
rb_raise(rb_eRuntimeError, "unable to set value in uWSGI cache");
|
||||
@@ -349,7 +356,7 @@ VALUE rack_uwsgi_cache_set_exc(int argc, VALUE *argv, VALUE *class) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_cache_update_exc(int argc, VALUE *argv, VALUE *class) {
|
||||
static VALUE rack_uwsgi_cache_update_exc(int argc, VALUE *argv, VALUE *class) {
|
||||
VALUE ret = rack_uwsgi_cache_update(argc, argv, class);
|
||||
if (ret == Qnil) {
|
||||
rb_raise(rb_eRuntimeError, "unable to update value in uWSGI cache");
|
||||
@@ -357,7 +364,7 @@ VALUE rack_uwsgi_cache_update_exc(int argc, VALUE *argv, VALUE *class) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_cache_del(int argc, VALUE *argv, VALUE *class) {
|
||||
static VALUE rack_uwsgi_cache_del(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
if (argc == 0) goto error;
|
||||
|
||||
@@ -383,7 +390,7 @@ error:
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_cache_del_exc(int argc, VALUE *argv, VALUE *class) {
|
||||
static VALUE rack_uwsgi_cache_del_exc(int argc, VALUE *argv, VALUE *class) {
|
||||
VALUE ret = rack_uwsgi_cache_del(argc, argv, class);
|
||||
if (ret == Qnil) {
|
||||
rb_raise(rb_eRuntimeError, "unable to delete object from uWSGI cache");
|
||||
@@ -393,7 +400,7 @@ VALUE rack_uwsgi_cache_del_exc(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
|
||||
|
||||
VALUE rack_uwsgi_cache_exists(int argc, VALUE *argv, VALUE *class) {
|
||||
static VALUE rack_uwsgi_cache_exists(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
if (argc == 0) goto error;
|
||||
|
||||
@@ -421,7 +428,7 @@ error:
|
||||
|
||||
|
||||
|
||||
VALUE rack_uwsgi_cache_clear(int argc, VALUE *argv, VALUE *class) {
|
||||
static VALUE rack_uwsgi_cache_clear(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
char *cache = NULL;
|
||||
|
||||
@@ -437,7 +444,7 @@ VALUE rack_uwsgi_cache_clear(int argc, VALUE *argv, VALUE *class) {
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_cache_clear_exc(int argc, VALUE *argv, VALUE *class) {
|
||||
static VALUE rack_uwsgi_cache_clear_exc(int argc, VALUE *argv, VALUE *class) {
|
||||
VALUE ret = rack_uwsgi_cache_clear(argc, argv, class);
|
||||
if (ret == Qnil) {
|
||||
rb_raise(rb_eRuntimeError, "unable to clear the uWSGI cache");
|
||||
@@ -447,7 +454,7 @@ VALUE rack_uwsgi_cache_clear_exc(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
|
||||
|
||||
VALUE rack_uwsgi_cache_get(int argc, VALUE *argv, VALUE *class) {
|
||||
static VALUE rack_uwsgi_cache_get(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
if (argc == 0) goto error;
|
||||
|
||||
@@ -477,7 +484,7 @@ error:
|
||||
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_cache_get_exc(int argc, VALUE *argv, VALUE *class) {
|
||||
static VALUE rack_uwsgi_cache_get_exc(int argc, VALUE *argv, VALUE *class) {
|
||||
VALUE ret = rack_uwsgi_cache_get(argc, argv, class);
|
||||
if (ret == Qnil) {
|
||||
rb_raise(rb_eRuntimeError, "unable to get value from uWSGI cache");
|
||||
@@ -488,7 +495,7 @@ VALUE rack_uwsgi_cache_get_exc(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
|
||||
|
||||
VALUE rack_uwsgi_add_cron(VALUE *class, VALUE rbsignum, VALUE rbmin, VALUE rbhour, VALUE rbday, VALUE rbmon, VALUE rbweek) {
|
||||
static VALUE rack_uwsgi_add_cron(VALUE *class, VALUE rbsignum, VALUE rbmin, VALUE rbhour, VALUE rbday, VALUE rbmon, VALUE rbweek) {
|
||||
|
||||
Check_Type(rbsignum, T_FIXNUM);
|
||||
Check_Type(rbmin, T_FIXNUM);
|
||||
@@ -514,7 +521,7 @@ VALUE rack_uwsgi_add_cron(VALUE *class, VALUE rbsignum, VALUE rbmin, VALUE rbhou
|
||||
|
||||
|
||||
|
||||
VALUE rack_uwsgi_add_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
|
||||
static VALUE rack_uwsgi_add_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
|
||||
|
||||
Check_Type(rbsignum, T_FIXNUM);
|
||||
Check_Type(secs, T_FIXNUM);
|
||||
@@ -532,7 +539,7 @@ VALUE rack_uwsgi_add_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
|
||||
|
||||
|
||||
|
||||
VALUE rack_uwsgi_add_rb_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
|
||||
static VALUE rack_uwsgi_add_rb_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
|
||||
|
||||
Check_Type(rbsignum, T_FIXNUM);
|
||||
Check_Type(secs, T_FIXNUM);
|
||||
@@ -550,7 +557,7 @@ VALUE rack_uwsgi_add_rb_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
|
||||
}
|
||||
|
||||
|
||||
VALUE rack_uwsgi_alarm(VALUE *class, VALUE alarm, VALUE msg) {
|
||||
static VALUE rack_uwsgi_alarm(VALUE *class, VALUE alarm, VALUE msg) {
|
||||
|
||||
Check_Type(alarm, T_STRING);
|
||||
Check_Type(msg, T_STRING);
|
||||
@@ -560,7 +567,7 @@ VALUE rack_uwsgi_alarm(VALUE *class, VALUE alarm, VALUE msg) {
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_add_file_monitor(VALUE *class, VALUE rbsignum, VALUE rbfilename) {
|
||||
static VALUE rack_uwsgi_add_file_monitor(VALUE *class, VALUE rbsignum, VALUE rbfilename) {
|
||||
|
||||
Check_Type(rbsignum, T_FIXNUM);
|
||||
Check_Type(rbfilename, T_STRING);
|
||||
@@ -577,7 +584,7 @@ VALUE rack_uwsgi_add_file_monitor(VALUE *class, VALUE rbsignum, VALUE rbfilename
|
||||
}
|
||||
|
||||
|
||||
VALUE uwsgi_ruby_wait_fd_read(VALUE *class, VALUE arg1, VALUE arg2) {
|
||||
static VALUE uwsgi_ruby_wait_fd_read(VALUE *class, VALUE arg1, VALUE arg2) {
|
||||
|
||||
Check_Type(arg1, T_FIXNUM);
|
||||
Check_Type(arg2, T_FIXNUM);
|
||||
@@ -595,7 +602,7 @@ VALUE uwsgi_ruby_wait_fd_read(VALUE *class, VALUE arg1, VALUE arg2) {
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_wait_fd_write(VALUE *class, VALUE arg1, VALUE arg2) {
|
||||
static VALUE uwsgi_ruby_wait_fd_write(VALUE *class, VALUE arg1, VALUE arg2) {
|
||||
|
||||
Check_Type(arg1, T_FIXNUM);
|
||||
Check_Type(arg2, T_FIXNUM);
|
||||
@@ -612,7 +619,7 @@ VALUE uwsgi_ruby_wait_fd_write(VALUE *class, VALUE arg1, VALUE arg2) {
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_async_connect(VALUE *class, VALUE arg) {
|
||||
static VALUE uwsgi_ruby_async_connect(VALUE *class, VALUE arg) {
|
||||
|
||||
Check_Type(arg, T_STRING);
|
||||
|
||||
@@ -622,7 +629,7 @@ VALUE uwsgi_ruby_async_connect(VALUE *class, VALUE arg) {
|
||||
}
|
||||
|
||||
|
||||
VALUE uwsgi_ruby_async_sleep(VALUE *class, VALUE arg) {
|
||||
static VALUE uwsgi_ruby_async_sleep(VALUE *class, VALUE arg) {
|
||||
|
||||
Check_Type(arg, T_FIXNUM);
|
||||
|
||||
@@ -636,7 +643,7 @@ VALUE uwsgi_ruby_async_sleep(VALUE *class, VALUE arg) {
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_masterpid(VALUE *class) {
|
||||
static VALUE uwsgi_ruby_masterpid(VALUE *class) {
|
||||
|
||||
if (uwsgi.master_process) {
|
||||
return INT2NUM(uwsgi.workers[0].pid);
|
||||
@@ -644,7 +651,7 @@ VALUE uwsgi_ruby_masterpid(VALUE *class) {
|
||||
return INT2NUM(0);
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_suspend(VALUE *class) {
|
||||
static VALUE uwsgi_ruby_suspend(VALUE *class) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
@@ -655,7 +662,7 @@ VALUE uwsgi_ruby_suspend(VALUE *class) {
|
||||
}
|
||||
|
||||
|
||||
VALUE uwsgi_ruby_signal_wait(int argc, VALUE *argv, VALUE *class) {
|
||||
static VALUE uwsgi_ruby_signal_wait(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
int wait_for_specific_signal = 0;
|
||||
@@ -687,7 +694,7 @@ VALUE uwsgi_ruby_signal_wait(int argc, VALUE *argv, VALUE *class) {
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_signal_received(VALUE *class) {
|
||||
static VALUE uwsgi_ruby_signal_received(VALUE *class) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
@@ -695,7 +702,7 @@ VALUE uwsgi_ruby_signal_received(VALUE *class) {
|
||||
}
|
||||
|
||||
|
||||
VALUE uwsgi_ruby_signal_registered(VALUE *class, VALUE signum) {
|
||||
static VALUE uwsgi_ruby_signal_registered(VALUE *class, VALUE signum) {
|
||||
|
||||
Check_Type(signum, T_FIXNUM);
|
||||
|
||||
@@ -708,7 +715,7 @@ VALUE uwsgi_ruby_signal_registered(VALUE *class, VALUE signum) {
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_do_rpc(int argc, VALUE *rpc_argv, VALUE *class) {
|
||||
static VALUE uwsgi_ruby_do_rpc(int argc, VALUE *rpc_argv, VALUE *class) {
|
||||
|
||||
char *node = NULL, *func;
|
||||
uint16_t size = 0;
|
||||
@@ -759,7 +766,7 @@ clear:
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_register_rpc(int argc, VALUE *argv, VALUE *class) {
|
||||
static VALUE uwsgi_ruby_register_rpc(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
int rb_argc = 0;
|
||||
|
||||
@@ -785,7 +792,7 @@ clear:
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_register_signal(VALUE *class, VALUE signum, VALUE sigkind, VALUE rbhandler) {
|
||||
static VALUE uwsgi_ruby_register_signal(VALUE *class, VALUE signum, VALUE sigkind, VALUE rbhandler) {
|
||||
|
||||
Check_Type(signum, T_FIXNUM);
|
||||
Check_Type(sigkind, T_STRING);
|
||||
@@ -805,7 +812,7 @@ VALUE uwsgi_ruby_register_signal(VALUE *class, VALUE signum, VALUE sigkind, VALU
|
||||
}
|
||||
|
||||
|
||||
VALUE uwsgi_ruby_signal(int argc, VALUE *argv, VALUE *class) {
|
||||
static VALUE uwsgi_ruby_signal(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
if (argc < 1) {
|
||||
rb_raise(rb_eRuntimeError, "you have to specify a signum");
|
||||
@@ -872,7 +879,7 @@ int rack_uwsgi_build_spool(VALUE rbkey, VALUE rbval, VALUE argv) {
|
||||
}
|
||||
|
||||
|
||||
VALUE rack_uwsgi_send_spool(VALUE *class, VALUE args) {
|
||||
static VALUE rack_uwsgi_send_spool(VALUE *class, VALUE args) {
|
||||
|
||||
char spool_filename[1024];
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
@@ -926,10 +933,10 @@ VALUE rack_uwsgi_send_spool(VALUE *class, VALUE args) {
|
||||
rb_hash_foreach(args, rack_uwsgi_build_spool, (VALUE) argv);
|
||||
|
||||
if (numprio) {
|
||||
priority = uwsgi_num2str(numprio);
|
||||
priority = uwsgi_num2str((int)numprio);
|
||||
}
|
||||
|
||||
int ret = spool_request(uwsgi.spoolers, spool_filename, uwsgi.workers[0].requests + 1, wsgi_req->async_id, spool_buffer, argv[0] - spool_buffer, priority, at, body, body_len);
|
||||
int ret = spool_request(uwsgi.spoolers, spool_filename, (int)(uwsgi.workers[0].requests + 1), wsgi_req->async_id, spool_buffer, (int)(argv[0] - spool_buffer), priority, at, body, body_len);
|
||||
|
||||
if (priority) {
|
||||
free(priority);
|
||||
@@ -950,7 +957,7 @@ VALUE rack_uwsgi_send_spool(VALUE *class, VALUE args) {
|
||||
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_websocket_handshake(int argc, VALUE *argv, VALUE *class) {
|
||||
static VALUE uwsgi_ruby_websocket_handshake(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
@@ -978,7 +985,7 @@ VALUE uwsgi_ruby_websocket_handshake(int argc, VALUE *argv, VALUE *class) {
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_websocket_send(VALUE *class, VALUE *msg) {
|
||||
static VALUE uwsgi_ruby_websocket_send(VALUE *class, VALUE *msg) {
|
||||
Check_Type(msg, T_STRING);
|
||||
char *message = RSTRING_PTR(msg);
|
||||
size_t message_len = RSTRING_LEN(msg);
|
||||
@@ -989,7 +996,7 @@ VALUE uwsgi_ruby_websocket_send(VALUE *class, VALUE *msg) {
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_websocket_recv(VALUE *class) {
|
||||
static VALUE uwsgi_ruby_websocket_recv(VALUE *class) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
struct uwsgi_buffer *ub = uwsgi_websocket_recv(wsgi_req);
|
||||
@@ -1003,7 +1010,7 @@ VALUE uwsgi_ruby_websocket_recv(VALUE *class) {
|
||||
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_websocket_recv_nb(VALUE *class) {
|
||||
static VALUE uwsgi_ruby_websocket_recv_nb(VALUE *class) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
struct uwsgi_buffer *ub = uwsgi_websocket_recv_nb(wsgi_req);
|
||||
@@ -1069,6 +1076,8 @@ void uwsgi_rack_init_api() {
|
||||
|
||||
uwsgi_rack_api("set_warning_message", rack_uwsgi_warning, 1);
|
||||
|
||||
uwsgi_rack_api("set_user_harakiri", rack_uwsgi_user_harakiri, 1);
|
||||
|
||||
uwsgi_rack_api("rpc", uwsgi_ruby_do_rpc, -1);
|
||||
|
||||
|
||||
|
||||
@@ -141,13 +141,13 @@ static struct uwsgi_buffer *uwsgi_ruby_backtrace(struct wsgi_request *wsgi_req)
|
||||
// ok let's start the C dance to parse the backtrace
|
||||
char *colon = strchr(bt, ':');
|
||||
if (!colon) continue;
|
||||
filename = uwsgi_concat2n(bt, colon-bt, "", 0);
|
||||
filename = uwsgi_concat2n(bt, (int) (colon-bt), "", 0);
|
||||
uint16_t filename_len = colon-bt;
|
||||
colon++; if (*colon == 0) goto error;
|
||||
char *lineno_ptr = colon;
|
||||
colon = strchr(lineno_ptr, ':');
|
||||
if (!colon) goto error;
|
||||
int64_t lineno = uwsgi_str_num(lineno_ptr, colon-lineno_ptr);
|
||||
int64_t lineno = uwsgi_str_num(lineno_ptr, (int) (colon-lineno_ptr));
|
||||
colon++; if (*colon == 0) goto error;
|
||||
colon = strchr(lineno_ptr, '`');
|
||||
if (!colon) goto error;
|
||||
@@ -155,7 +155,7 @@ static struct uwsgi_buffer *uwsgi_ruby_backtrace(struct wsgi_request *wsgi_req)
|
||||
char *function_ptr = colon;
|
||||
char *function_end = strchr(function_ptr, '\'');
|
||||
if (!function_end) goto error;
|
||||
function = uwsgi_concat2n(function_ptr, function_end-function_ptr, "", 0);
|
||||
function = uwsgi_concat2n(function_ptr, (int) (function_end-function_ptr), "", 0);
|
||||
uint16_t function_len = function_end-function_ptr;
|
||||
|
||||
if (uwsgi_buffer_u16le(ub, filename_len)) goto error;
|
||||
@@ -312,7 +312,7 @@ VALUE init_rack_app(VALUE);
|
||||
|
||||
VALUE rack_call_rpc_handler(VALUE args) {
|
||||
VALUE rpc_args = rb_ary_entry(args, 1);
|
||||
return rb_funcall2(rb_ary_entry(args, 0), rb_intern("call"), RARRAY_LEN(rpc_args), RARRAY_PTR(rpc_args));
|
||||
return rb_funcall2(rb_ary_entry(args, 0), rb_intern("call"), (int) RARRAY_LEN(rpc_args), RARRAY_PTR(rpc_args));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -112,13 +112,15 @@ static ssize_t rr_xclient_write(struct corerouter_peer *peer) {
|
||||
if (!len) return 0;
|
||||
|
||||
if (cr_write_complete_buf(peer, rr->xclient)) {
|
||||
if (peer->session->main_peer->out) {
|
||||
if (peer->session->main_peer->out_pos > 0) {
|
||||
// (eventually) send previous data
|
||||
peer->last_hook_read = rr_instance_read;
|
||||
cr_write_to_main(peer, rr_write);
|
||||
}
|
||||
else {
|
||||
// reset to standard behaviour
|
||||
cr_reset_hooks(peer);
|
||||
peer->in->pos = 0;
|
||||
cr_reset_hooks_and_read(peer, rr_instance_read);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,10 +142,10 @@ static ssize_t rr_xclient_read(struct corerouter_peer *peer) {
|
||||
return -1;
|
||||
}
|
||||
// banner received (skip it, will be sent later)
|
||||
size_t remains = peer->in->pos - (len - (i+1));
|
||||
size_t remains = len - (i+1);
|
||||
if (remains > 0) {
|
||||
peer->session->main_peer->out = peer->in;
|
||||
peer->session->main_peer->out_pos = remains;
|
||||
peer->session->main_peer->out_pos = (peer->in->pos - remains) ;
|
||||
}
|
||||
cr_write_to_backend(peer, rr_xclient_write);
|
||||
return len;
|
||||
|
||||
@@ -193,7 +193,6 @@ static int uwsgi_routing_func_cache(struct wsgi_request *wsgi_req, struct uwsgi_
|
||||
if (wsgi_req->socket->can_offload && !ur->custom && !urcc->no_offload) {
|
||||
if (!uwsgi_offload_request_memory_do(wsgi_req, value, valsize)) {
|
||||
wsgi_req->via = UWSGI_VIA_OFFLOAD;
|
||||
wsgi_req->status = 202;
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
by Unbit
|
||||
|
||||
syntax:
|
||||
|
||||
route = /^foobar1(.*)/ hash:key=foo$1poo,algo=murmur2,var=MYHASH,items=node1;node2;node3
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_router_hash_conf {
|
||||
|
||||
char *key;
|
||||
size_t key_len;
|
||||
|
||||
char *var;
|
||||
size_t var_len;
|
||||
|
||||
char *algo;
|
||||
char *items;
|
||||
size_t items_len;
|
||||
};
|
||||
|
||||
static int uwsgi_routing_func_hash(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
|
||||
|
||||
struct uwsgi_router_hash_conf *urhc = (struct uwsgi_router_hash_conf *) ur->data2;
|
||||
|
||||
struct uwsgi_hash_algo *uha = uwsgi_hash_algo_get(urhc->algo);
|
||||
if (!uha) {
|
||||
uwsgi_log("[uwsgi-hash-router] unable to find hash algo \"%s\"\n", urhc->algo);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
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, urhc->key, urhc->key_len);
|
||||
if (!ub) return UWSGI_ROUTE_BREAK;
|
||||
|
||||
uint32_t h = uha->func(ub->buf, ub->pos);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
|
||||
// now count the number of items
|
||||
uint32_t items = 1;
|
||||
size_t i, ilen = urhc->items_len;
|
||||
for(i=0;i<ilen;i++) {
|
||||
if (urhc->items[i] == ';') items++;
|
||||
}
|
||||
|
||||
// skip last semicolon
|
||||
if (urhc->items[ilen-1] == ';') items--;
|
||||
|
||||
uint32_t hashed_result = h % items;
|
||||
uint32_t found = 0;
|
||||
char *value = urhc->items;
|
||||
uint16_t vallen = 0;
|
||||
for(i=0;i<ilen;i++) {
|
||||
if (!value) {
|
||||
value = urhc->items + i;
|
||||
}
|
||||
if (urhc->items[i] == ';') {
|
||||
if (found == hashed_result) {
|
||||
vallen = (urhc->items+i) - value;
|
||||
break;
|
||||
}
|
||||
value = NULL;
|
||||
found++;
|
||||
}
|
||||
}
|
||||
|
||||
if (vallen == 0) {
|
||||
// first item
|
||||
if (hashed_result == 0) {
|
||||
value = urhc->items;
|
||||
vallen = urhc->items_len;
|
||||
}
|
||||
// last item
|
||||
else {
|
||||
vallen = (urhc->items + urhc->items_len) - value;
|
||||
}
|
||||
}
|
||||
|
||||
if (!vallen) {
|
||||
uwsgi_log("[uwsgi-hash-router] BUG !!! unable to hash items\n");
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
if (!uwsgi_req_append(wsgi_req, urhc->var, urhc->var_len, value, vallen)) {
|
||||
uwsgi_log("[uwsgi-hash-router] unable to append hash var to the request\n");
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
|
||||
static int uwsgi_router_hash(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_hash;
|
||||
ur->data = args;
|
||||
ur->data_len = strlen(args);
|
||||
struct uwsgi_router_hash_conf *urhc = uwsgi_calloc(sizeof(struct uwsgi_router_hash_conf));
|
||||
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
|
||||
"key", &urhc->key,
|
||||
"var", &urhc->var,
|
||||
"algo", &urhc->algo,
|
||||
"items", &urhc->items,
|
||||
NULL)) {
|
||||
uwsgi_log("invalid route syntax: %s\n", args);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!urhc->key || !urhc->var || !urhc->items) {
|
||||
uwsgi_log("invalid route syntax: you need to specify a hash key, a var and a set of items\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
urhc->key_len = strlen(urhc->key);
|
||||
urhc->var_len = strlen(urhc->var);
|
||||
urhc->items_len = strlen(urhc->items);
|
||||
|
||||
|
||||
if (!urhc->algo) urhc->algo = "djb33x";
|
||||
|
||||
ur->data2 = urhc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void router_hash_register() {
|
||||
uwsgi_register_router("hash", uwsgi_router_hash);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin router_hash_plugin = {
|
||||
.name = "router_hash",
|
||||
.on_load = router_hash_register,
|
||||
};
|
||||
|
||||
#else
|
||||
struct uwsgi_plugin router_hash_plugin = {
|
||||
.name = "router_hash",
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='router_hash'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
GCC_LIST = ['router_hash']
|
||||
@@ -1,20 +1,24 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
|
||||
#define MEMCACHED_BUFSIZE 8192
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
memcached internal router
|
||||
memcached internal router and transformation
|
||||
|
||||
route = /^foobar1(.*)/ memcached:addr=127.0.0.1:11211,key=foo$1poo,type=body
|
||||
route = /^foobar1(.*)/ memcached:addr=127.0.0.1:11211,key=foo$1poo
|
||||
route = /^foobar1(.*)/ memcachedstore:addr=127.0.0.1:11211,key=foo$1poo
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_router_memcached_conf {
|
||||
|
||||
char *addr;
|
||||
size_t addr_len;
|
||||
|
||||
char *key;
|
||||
size_t key_len;
|
||||
@@ -22,12 +26,19 @@ struct uwsgi_router_memcached_conf {
|
||||
char *content_type;
|
||||
size_t content_type_len;
|
||||
|
||||
// 0 -> full, 1 -> body
|
||||
char *type;
|
||||
int type_num;
|
||||
char *no_offload;
|
||||
char *expires;
|
||||
|
||||
};
|
||||
|
||||
// this is allocated for each transformation
|
||||
struct uwsgi_transformation_memcached_conf {
|
||||
struct uwsgi_buffer *addr;
|
||||
struct uwsgi_buffer *key;
|
||||
char *expires;
|
||||
};
|
||||
|
||||
|
||||
static size_t memcached_firstline_parse(char *buf, size_t len) {
|
||||
// check for "VALUE x 0 0"
|
||||
if (len < 11) return 0;
|
||||
@@ -48,6 +59,86 @@ static size_t memcached_firstline_parse(char *buf, size_t len) {
|
||||
}
|
||||
}
|
||||
|
||||
// store an item in memcached
|
||||
static void memcached_store(char *addr, struct uwsgi_buffer *key, struct uwsgi_buffer *value, char *expires) {
|
||||
|
||||
int timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
|
||||
|
||||
int fd = uwsgi_connect(addr, 0, 1);
|
||||
if (fd < 0) return;
|
||||
|
||||
// wait for connection
|
||||
int ret = uwsgi.wait_write_hook(fd, timeout);
|
||||
if (ret <= 0) goto end;
|
||||
|
||||
// build the request
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
|
||||
if (uwsgi_buffer_append(ub, "set ", 4)) goto end2;
|
||||
if (uwsgi_buffer_append(ub, key->buf, key->pos)) goto end2;
|
||||
if (uwsgi_buffer_append(ub, " 0 " , 3)) goto end2;
|
||||
if (uwsgi_buffer_append(ub, expires, strlen(expires))) goto end2;
|
||||
if (uwsgi_buffer_append(ub, " " , 1)) goto end2;
|
||||
if (uwsgi_buffer_num64(ub, value->pos)) goto end2;
|
||||
if (uwsgi_buffer_append(ub, "\r\n" , 2)) goto end2;
|
||||
|
||||
if (uwsgi_write_true_nb(fd, ub->buf, ub->pos, timeout)) goto end2;
|
||||
if (uwsgi_write_true_nb(fd, value->buf, value->pos, timeout)) goto end2;
|
||||
if (uwsgi_write_true_nb(fd, "\r\n", 2, timeout)) goto end2;
|
||||
|
||||
// we are not interested in command result... (ugly but it works)
|
||||
end2:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
end:
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static int transform_memcached(struct wsgi_request *wsgi_req, struct uwsgi_transformation *ut) {
|
||||
struct uwsgi_transformation_memcached_conf *utmc = (struct uwsgi_transformation_memcached_conf *) ut->data;
|
||||
struct uwsgi_buffer *ub = ut->chunk;
|
||||
|
||||
// store only successfull response
|
||||
if (wsgi_req->write_errors == 0 && wsgi_req->status == 200 && ub->pos > 0) {
|
||||
memcached_store(utmc->addr->buf, utmc->key, ub, utmc->expires);
|
||||
}
|
||||
|
||||
// free resources
|
||||
uwsgi_buffer_destroy(utmc->key);
|
||||
uwsgi_buffer_destroy(utmc->addr);
|
||||
free(utmc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// be tolerant on errors
|
||||
static int uwsgi_routing_func_memcached_store(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
|
||||
struct uwsgi_router_memcached_conf *urmc = (struct uwsgi_router_memcached_conf *) ur->data2;
|
||||
|
||||
struct uwsgi_transformation_memcached_conf *utmc = uwsgi_calloc(sizeof(struct uwsgi_transformation_memcached_conf));
|
||||
|
||||
// build key and name
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
utmc->key = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urmc->key, urmc->key_len);
|
||||
if (!utmc->key) goto error;
|
||||
|
||||
utmc->addr = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urmc->addr, urmc->addr_len);
|
||||
if (!utmc->addr) goto error;
|
||||
|
||||
utmc->expires = urmc->expires;
|
||||
|
||||
uwsgi_add_transformation(wsgi_req, transform_memcached, utmc);
|
||||
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
|
||||
error:
|
||||
if (utmc->key) uwsgi_buffer_destroy(utmc->key);
|
||||
if (utmc->addr) uwsgi_buffer_destroy(utmc->addr);
|
||||
free(utmc);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_routing_func_memcached(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
|
||||
// this is the buffer for the memcached response
|
||||
char buf[MEMCACHED_BUFSIZE];
|
||||
@@ -62,13 +153,24 @@ static int uwsgi_routing_func_memcached(struct wsgi_request *wsgi_req, struct uw
|
||||
struct uwsgi_buffer *ub_key = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urmc->key, urmc->key_len);
|
||||
if (!ub_key) return UWSGI_ROUTE_BREAK;
|
||||
|
||||
int fd = uwsgi_connect(urmc->addr, 0, 1);
|
||||
if (fd < 0) { uwsgi_buffer_destroy(ub_key) ; goto end; }
|
||||
struct uwsgi_buffer *ub_addr = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urmc->addr, urmc->addr_len);
|
||||
if (!ub_addr) {
|
||||
uwsgi_buffer_destroy(ub_key);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
int fd = uwsgi_connect(ub_addr->buf, 0, 1);
|
||||
if (fd < 0) {
|
||||
uwsgi_buffer_destroy(ub_key);
|
||||
uwsgi_buffer_destroy(ub_addr);
|
||||
goto end;
|
||||
}
|
||||
|
||||
// wait for connection;
|
||||
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
if (ret <= 0) {
|
||||
uwsgi_buffer_destroy(ub_key) ;
|
||||
uwsgi_buffer_destroy(ub_addr);
|
||||
close(fd);
|
||||
goto end;
|
||||
}
|
||||
@@ -77,11 +179,13 @@ static int uwsgi_routing_func_memcached(struct wsgi_request *wsgi_req, struct uw
|
||||
char *cmd = uwsgi_concat3n("get ", 4, ub_key->buf, ub_key->pos, "\r\n", 2);
|
||||
if (uwsgi_write_true_nb(fd, cmd, 6+ub_key->pos, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uwsgi_buffer_destroy(ub_key);
|
||||
uwsgi_buffer_destroy(ub_addr);
|
||||
free(cmd);
|
||||
close(fd);
|
||||
goto end;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub_key);
|
||||
uwsgi_buffer_destroy(ub_addr);
|
||||
free(cmd);
|
||||
|
||||
// ok, start reading the response...
|
||||
@@ -130,26 +234,34 @@ read:
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (urmc->type_num == 1) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) { close(fd); goto end; }
|
||||
if (uwsgi_response_add_content_type(wsgi_req, urmc->content_type, urmc->content_type_len)) { close(fd); goto end; }
|
||||
if (uwsgi_response_add_content_length(wsgi_req, response_size)) { close(fd); goto end; }
|
||||
}
|
||||
// from now on, every error will trigger a BREAK...
|
||||
|
||||
// send headers
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto error;
|
||||
if (uwsgi_response_add_content_type(wsgi_req, urmc->content_type, urmc->content_type_len)) goto error;
|
||||
if (uwsgi_response_add_content_length(wsgi_req, response_size)) goto error;
|
||||
|
||||
// the first chunk could already contains part of the body
|
||||
size_t remains = pos-(found+2);
|
||||
if (remains >= response_size) {
|
||||
uwsgi_response_write_body_do(wsgi_req, buf+found+2, response_size);
|
||||
close(fd);
|
||||
goto end;
|
||||
goto done;
|
||||
}
|
||||
|
||||
// send what we have
|
||||
if (uwsgi_response_write_body_do(wsgi_req, buf+found+2, remains)) {
|
||||
close(fd);
|
||||
goto end;
|
||||
}
|
||||
if (uwsgi_response_write_body_do(wsgi_req, buf+found+2, remains)) goto error;
|
||||
|
||||
// and now start reading til the output is consumed
|
||||
response_size -= remains;
|
||||
|
||||
// try to offload via the pipe engine
|
||||
if (wsgi_req->socket->can_offload && !ur->custom && !urmc->no_offload) {
|
||||
if (!uwsgi_offload_request_pipe_do(wsgi_req, fd, response_size)) {
|
||||
wsgi_req->via = UWSGI_VIA_OFFLOAD;
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
}
|
||||
|
||||
while(response_size > 0) {
|
||||
ssize_t len = read(fd, buf, UMIN(MEMCACHED_BUFSIZE, response_size));
|
||||
if (len > 0) goto write;
|
||||
@@ -165,23 +277,22 @@ wait2:
|
||||
}
|
||||
goto error;
|
||||
write:
|
||||
if (uwsgi_response_write_body_do(wsgi_req, buf, len)) {
|
||||
goto error;
|
||||
}
|
||||
if (uwsgi_response_write_body_do(wsgi_req, buf, len)) goto error;
|
||||
response_size -= len;
|
||||
}
|
||||
|
||||
done:
|
||||
close(fd);
|
||||
if (ur->custom)
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
|
||||
error:
|
||||
close(fd);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
|
||||
end:
|
||||
if (ur->custom)
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
|
||||
static int uwsgi_router_memcached(struct uwsgi_route *ur, char *args) {
|
||||
@@ -193,27 +304,23 @@ static int uwsgi_router_memcached(struct uwsgi_route *ur, char *args) {
|
||||
"addr", &urmc->addr,
|
||||
"key", &urmc->key,
|
||||
"content_type", &urmc->content_type,
|
||||
"type", &urmc->type, NULL)) {
|
||||
"no_offload", &urmc->no_offload,
|
||||
NULL)) {
|
||||
uwsgi_log("invalid route syntax: %s\n", args);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!urmc->key || !urmc->addr) {
|
||||
uwsgi_log("invalid route syntax: you need to specify a memcached address and key pattern\n");
|
||||
exit(1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
urmc->key_len = strlen(urmc->key);
|
||||
urmc->addr_len = strlen(urmc->addr);
|
||||
|
||||
if (!urmc->type) urmc->type = "full";
|
||||
if (!urmc->content_type) urmc->content_type = "text/html";
|
||||
|
||||
urmc->content_type_len = strlen(urmc->content_type);
|
||||
|
||||
if (!strcmp(urmc->type, "body")) {
|
||||
urmc->type_num = 1;
|
||||
}
|
||||
|
||||
ur->data2 = urmc;
|
||||
return 0;
|
||||
}
|
||||
@@ -224,12 +331,46 @@ static int uwsgi_router_memcached_continue(struct uwsgi_route *ur, char *args) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_router_memcached_store(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_memcached_store;
|
||||
ur->data = args;
|
||||
ur->data_len = strlen(args);
|
||||
struct uwsgi_router_memcached_conf *urmc = uwsgi_calloc(sizeof(struct uwsgi_router_memcached_conf));
|
||||
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
|
||||
"addr", &urmc->addr,
|
||||
"key", &urmc->key,
|
||||
"expires", &urmc->expires, NULL)) {
|
||||
uwsgi_log("invalid memcachedstore route syntax: %s\n", args);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!urmc->key || !urmc->addr) {
|
||||
uwsgi_log("invalid memcachedstore route syntax: you need to specify an address and a key\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
urmc->key_len = strlen(urmc->key);
|
||||
urmc->addr_len = strlen(urmc->addr);
|
||||
|
||||
if (!urmc->expires) urmc->expires = "0";
|
||||
|
||||
ur->data2 = urmc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void router_memcached_register() {
|
||||
uwsgi_register_router("memcached", uwsgi_router_memcached);
|
||||
uwsgi_register_router("memcached-continue", uwsgi_router_memcached_continue);
|
||||
uwsgi_register_router("memcachedstore", uwsgi_router_memcached_store);
|
||||
uwsgi_register_router("memcached-store", uwsgi_router_memcached_store);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
struct uwsgi_plugin router_memcached_plugin = {
|
||||
.name = "router_memcached",
|
||||
#ifdef UWSGI_ROUTING
|
||||
.on_load = router_memcached_register,
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -0,0 +1,374 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
|
||||
#define REDIS_BUFSIZE 8192
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
redis internal router and transformation
|
||||
|
||||
route = /^foobar1(.*)/ redis:addr=127.0.0.1:11211,key=foo$1poo
|
||||
route = /^foobar1(.*)/ redisstore:addr=127.0.0.1:11211,key=foo$1poo
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_router_redis_conf {
|
||||
|
||||
char *addr;
|
||||
size_t addr_len;
|
||||
|
||||
char *key;
|
||||
size_t key_len;
|
||||
|
||||
char *content_type;
|
||||
size_t content_type_len;
|
||||
|
||||
char *no_offload;
|
||||
char *expires;
|
||||
|
||||
};
|
||||
|
||||
// this is allocated for each transformation
|
||||
struct uwsgi_transformation_redis_conf {
|
||||
struct uwsgi_buffer *addr;
|
||||
struct uwsgi_buffer *key;
|
||||
char *expires;
|
||||
};
|
||||
|
||||
|
||||
static size_t redis_firstline_parse(char *buf, size_t len) {
|
||||
// check for "$0"
|
||||
if (len < 2) return 0;
|
||||
if (buf[0] != '$') return 0;
|
||||
if (buf[1] == '-') return 0;
|
||||
return uwsgi_str_num(buf + 1, len - 1);
|
||||
}
|
||||
|
||||
// store an item in redis
|
||||
static void redis_store(char *addr, struct uwsgi_buffer *key, struct uwsgi_buffer *value, char *expires) {
|
||||
|
||||
int timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
|
||||
|
||||
int fd = uwsgi_connect(addr, 0, 1);
|
||||
if (fd < 0) return;
|
||||
|
||||
// wait for connection
|
||||
int ret = uwsgi.wait_write_hook(fd, timeout);
|
||||
if (ret <= 0) goto end;
|
||||
|
||||
// build the request
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
|
||||
if (uwsgi_buffer_append(ub, "*3\r\n$3\r\nSET\r\n$", 14)) goto end2;
|
||||
if (uwsgi_buffer_num64(ub, key->pos)) goto end2;
|
||||
if (uwsgi_buffer_append(ub, "\r\n" , 2)) goto end2;
|
||||
if (uwsgi_buffer_append(ub, key->buf, key->pos)) goto end2;
|
||||
if (uwsgi_buffer_append(ub, "\r\n$" , 3)) goto end2;
|
||||
if (uwsgi_buffer_num64(ub, value->pos)) goto end2;
|
||||
if (uwsgi_buffer_append(ub, "\r\n" , 2)) goto end2;
|
||||
if (uwsgi_write_true_nb(fd, ub->buf, ub->pos, timeout)) goto end2;
|
||||
if (uwsgi_write_true_nb(fd, value->buf, value->pos, timeout)) goto end2;
|
||||
ub->pos = 0;
|
||||
if (strcmp(expires, "0")) {
|
||||
if (uwsgi_buffer_append(ub, "\r\n*3\r\n$6\r\nEXPIRE\r\n$" , 19)) goto end2;
|
||||
if (uwsgi_buffer_num64(ub, key->pos)) goto end2;
|
||||
if (uwsgi_buffer_append(ub, "\r\n" , 2)) goto end2;
|
||||
if (uwsgi_buffer_append(ub, key->buf, key->pos)) goto end2;
|
||||
if (uwsgi_buffer_append(ub, "\r\n$" , 3)) goto end2;
|
||||
if (uwsgi_buffer_num64(ub, strlen(expires))) goto end2;
|
||||
if (uwsgi_buffer_append(ub, "\r\n" , 2)) goto end2;
|
||||
if (uwsgi_buffer_append(ub, expires, strlen(expires))) goto end2;
|
||||
}
|
||||
if (uwsgi_buffer_append(ub, "\r\n" , 2)) goto end2;
|
||||
if (uwsgi_write_true_nb(fd, ub->buf, ub->pos, timeout)) goto end2;
|
||||
|
||||
// we are not interested in command result... (ugly but it works)
|
||||
end2:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
end:
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static int transform_redis(struct wsgi_request *wsgi_req, struct uwsgi_transformation *ut) {
|
||||
struct uwsgi_transformation_redis_conf *utrc = (struct uwsgi_transformation_redis_conf *) ut->data;
|
||||
struct uwsgi_buffer *ub = ut->chunk;
|
||||
|
||||
// store only successfull response
|
||||
if (wsgi_req->write_errors == 0 && wsgi_req->status == 200 && ub->pos > 0) {
|
||||
redis_store(utrc->addr->buf, utrc->key, ub, utrc->expires);
|
||||
}
|
||||
|
||||
// free resources
|
||||
uwsgi_buffer_destroy(utrc->key);
|
||||
uwsgi_buffer_destroy(utrc->addr);
|
||||
free(utrc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// be tolerant on errors
|
||||
static int uwsgi_routing_func_redis_store(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
|
||||
struct uwsgi_router_redis_conf *urrc = (struct uwsgi_router_redis_conf *) ur->data2;
|
||||
|
||||
struct uwsgi_transformation_redis_conf *utrc = uwsgi_calloc(sizeof(struct uwsgi_transformation_redis_conf));
|
||||
|
||||
// build key and name
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
utrc->key = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urrc->key, urrc->key_len);
|
||||
if (!utrc->key) goto error;
|
||||
|
||||
utrc->addr = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urrc->addr, urrc->addr_len);
|
||||
if (!utrc->addr) goto error;
|
||||
|
||||
utrc->expires = urrc->expires;
|
||||
|
||||
uwsgi_add_transformation(wsgi_req, transform_redis, utrc);
|
||||
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
|
||||
error:
|
||||
if (utrc->key) uwsgi_buffer_destroy(utrc->key);
|
||||
if (utrc->addr) uwsgi_buffer_destroy(utrc->addr);
|
||||
free(utrc);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_routing_func_redis(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
|
||||
// this is the buffer for the redis response
|
||||
char buf[REDIS_BUFSIZE];
|
||||
size_t i;
|
||||
char last_char = 0;
|
||||
|
||||
struct uwsgi_router_redis_conf *urrc = (struct uwsgi_router_redis_conf *) 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_key = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urrc->key, urrc->key_len);
|
||||
if (!ub_key) return UWSGI_ROUTE_BREAK;
|
||||
|
||||
struct uwsgi_buffer *ub_addr = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urrc->addr, urrc->addr_len);
|
||||
if (!ub_addr) {
|
||||
uwsgi_buffer_destroy(ub_key);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
int fd = uwsgi_connect(ub_addr->buf, 0, 1);
|
||||
if (fd < 0) {
|
||||
uwsgi_buffer_destroy(ub_key);
|
||||
uwsgi_buffer_destroy(ub_addr);
|
||||
goto end;
|
||||
}
|
||||
|
||||
// wait for connection;
|
||||
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
if (ret <= 0) {
|
||||
uwsgi_buffer_destroy(ub_key) ;
|
||||
uwsgi_buffer_destroy(ub_addr);
|
||||
close(fd);
|
||||
goto end;
|
||||
}
|
||||
|
||||
// build the request and send it
|
||||
char *cmd = uwsgi_concat3n("get ", 4, ub_key->buf, ub_key->pos, "\r\n", 2);
|
||||
if (uwsgi_write_true_nb(fd, cmd, 6+ub_key->pos, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uwsgi_buffer_destroy(ub_key);
|
||||
uwsgi_buffer_destroy(ub_addr);
|
||||
free(cmd);
|
||||
close(fd);
|
||||
goto end;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub_key);
|
||||
uwsgi_buffer_destroy(ub_addr);
|
||||
free(cmd);
|
||||
|
||||
// ok, start reading the response...
|
||||
// first we need to get a full line;
|
||||
size_t found = 0;
|
||||
size_t pos = 0;
|
||||
for(;;) {
|
||||
ssize_t len = read(fd, buf + pos, REDIS_BUFSIZE - pos);
|
||||
if (len > 0) {
|
||||
pos += len;
|
||||
goto read;
|
||||
}
|
||||
if (len < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait;
|
||||
}
|
||||
close(fd);
|
||||
goto end;
|
||||
wait:
|
||||
ret = uwsgi.wait_read_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
// when we have a chunk try to read the first line
|
||||
if (ret > 0) {
|
||||
len = read(fd, buf + pos, REDIS_BUFSIZE - pos);
|
||||
if (len > 0) {
|
||||
pos += len;
|
||||
goto read;
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
goto end;
|
||||
read:
|
||||
for(i=0;i<pos;i++) {
|
||||
if (last_char == '\r' && buf[i] == '\n') {
|
||||
found = i-1;
|
||||
break;
|
||||
}
|
||||
last_char = buf[i];
|
||||
}
|
||||
if (found) break;
|
||||
}
|
||||
|
||||
// ok parse the first line
|
||||
size_t response_size = redis_firstline_parse(buf, found);
|
||||
if (response_size == 0) {
|
||||
close(fd);
|
||||
goto end;
|
||||
}
|
||||
|
||||
// from now on, every error will trigger a BREAK...
|
||||
|
||||
// send headers
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto error;
|
||||
if (uwsgi_response_add_content_type(wsgi_req, urrc->content_type, urrc->content_type_len)) goto error;
|
||||
if (uwsgi_response_add_content_length(wsgi_req, response_size)) goto error;
|
||||
|
||||
// the first chunk could already contains part of the body
|
||||
size_t remains = pos-(found+2);
|
||||
if (remains >= response_size) {
|
||||
uwsgi_response_write_body_do(wsgi_req, buf+found+2, response_size);
|
||||
goto done;
|
||||
}
|
||||
|
||||
// send what we have
|
||||
if (uwsgi_response_write_body_do(wsgi_req, buf+found+2, remains)) goto error;
|
||||
|
||||
// and now start reading til the output is consumed
|
||||
response_size -= remains;
|
||||
|
||||
// try to offload via the pipe engine
|
||||
if (wsgi_req->socket->can_offload && !ur->custom && !urrc->no_offload) {
|
||||
if (!uwsgi_offload_request_pipe_do(wsgi_req, fd, response_size)) {
|
||||
wsgi_req->via = UWSGI_VIA_OFFLOAD;
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
}
|
||||
|
||||
while(response_size > 0) {
|
||||
ssize_t len = read(fd, buf, UMIN(REDIS_BUFSIZE, response_size));
|
||||
if (len > 0) goto write;
|
||||
if (len < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait2;
|
||||
}
|
||||
goto error;
|
||||
wait2:
|
||||
ret = uwsgi.wait_read_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
if (ret > 0) {
|
||||
len = read(fd, buf, UMIN(REDIS_BUFSIZE, response_size));
|
||||
if (len > 0) goto write;
|
||||
}
|
||||
goto error;
|
||||
write:
|
||||
if (uwsgi_response_write_body_do(wsgi_req, buf, len)) goto error;
|
||||
response_size -= len;
|
||||
}
|
||||
|
||||
done:
|
||||
close(fd);
|
||||
if (ur->custom)
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
|
||||
error:
|
||||
close(fd);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
|
||||
end:
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
|
||||
static int uwsgi_router_redis(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_redis;
|
||||
ur->data = args;
|
||||
ur->data_len = strlen(args);
|
||||
struct uwsgi_router_redis_conf *urrc = uwsgi_calloc(sizeof(struct uwsgi_router_redis_conf));
|
||||
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
|
||||
"addr", &urrc->addr,
|
||||
"key", &urrc->key,
|
||||
"content_type", &urrc->content_type,
|
||||
"no_offload", &urrc->no_offload,
|
||||
NULL)) {
|
||||
uwsgi_log("invalid route syntax: %s\n", args);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!urrc->key || !urrc->addr) {
|
||||
uwsgi_log("invalid route syntax: you need to specify a redis address and key pattern\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
urrc->key_len = strlen(urrc->key);
|
||||
urrc->addr_len = strlen(urrc->addr);
|
||||
|
||||
if (!urrc->content_type) urrc->content_type = "text/html";
|
||||
urrc->content_type_len = strlen(urrc->content_type);
|
||||
|
||||
ur->data2 = urrc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_router_redis_continue(struct uwsgi_route *ur, char *args) {
|
||||
uwsgi_router_redis(ur, args);
|
||||
ur->custom = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_router_redis_store(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_redis_store;
|
||||
ur->data = args;
|
||||
ur->data_len = strlen(args);
|
||||
struct uwsgi_router_redis_conf *urrc = uwsgi_calloc(sizeof(struct uwsgi_router_redis_conf));
|
||||
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
|
||||
"addr", &urrc->addr,
|
||||
"key", &urrc->key,
|
||||
"expires", &urrc->expires, NULL)) {
|
||||
uwsgi_log("invalid redisstore route syntax: %s\n", args);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!urrc->key || !urrc->addr) {
|
||||
uwsgi_log("invalid redisstore route syntax: you need to specify an address and a key\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
urrc->key_len = strlen(urrc->key);
|
||||
urrc->addr_len = strlen(urrc->addr);
|
||||
|
||||
if (!urrc->expires) urrc->expires = "0";
|
||||
|
||||
ur->data2 = urrc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void router_redis_register() {
|
||||
uwsgi_register_router("redis", uwsgi_router_redis);
|
||||
uwsgi_register_router("redis-continue", uwsgi_router_redis_continue);
|
||||
uwsgi_register_router("redisstore", uwsgi_router_redis_store);
|
||||
uwsgi_register_router("redis-store", uwsgi_router_redis_store);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
struct uwsgi_plugin router_redis_plugin = {
|
||||
.name = "router_redis",
|
||||
#ifdef UWSGI_ROUTING
|
||||
.on_load = router_redis_register,
|
||||
#endif
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='router_redis'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
GCC_LIST = ['router_redis']
|
||||
@@ -0,0 +1,75 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
#ifndef UWSGI_XML_LIBXML2
|
||||
#error you need a libxml2-enabled build of uWSGI to use the router_xmldir plugin
|
||||
#endif
|
||||
|
||||
#include <libxml/tree.h>
|
||||
|
||||
static int uwsgi_routing_func_xmldir(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;
|
||||
|
||||
struct dirent **tasklist;
|
||||
int n = scandir(ub->buf, &tasklist, 0, versionsort);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
if (n < 0) return UWSGI_ROUTE_BREAK;
|
||||
int i;
|
||||
xmlDoc *rdoc = xmlNewDoc(BAD_CAST "1.0");
|
||||
xmlNode *rtree = xmlNewNode(NULL, BAD_CAST "tree");
|
||||
xmlDocSetRootElement(rdoc, rtree);
|
||||
|
||||
for(i=0;i<n;i++) {
|
||||
if (tasklist[i]->d_name[0] == '.') goto next;
|
||||
switch (tasklist[i]->d_type) {
|
||||
case DT_DIR:
|
||||
xmlNewTextChild(rtree, NULL, BAD_CAST "directory", BAD_CAST tasklist[i]->d_name);
|
||||
break;
|
||||
case DT_LNK:
|
||||
xmlNewTextChild(rtree, NULL, BAD_CAST "link", BAD_CAST tasklist[i]->d_name);
|
||||
break;
|
||||
case DT_REG:
|
||||
xmlNewTextChild(rtree, NULL, BAD_CAST "file", BAD_CAST tasklist[i]->d_name);
|
||||
break;
|
||||
default:
|
||||
xmlNewTextChild(rtree, NULL, BAD_CAST "unknown", BAD_CAST tasklist[i]->d_name);
|
||||
break;
|
||||
}
|
||||
next:
|
||||
free(tasklist[i]);
|
||||
}
|
||||
|
||||
free(tasklist);
|
||||
|
||||
xmlChar *xmlbuf;
|
||||
int xlen = 0;
|
||||
xmlDocDumpFormatMemory(rdoc, &xmlbuf, &xlen, 1);
|
||||
|
||||
uwsgi_response_prepare_headers(wsgi_req,"200 OK", 6);
|
||||
uwsgi_response_write_body_do(wsgi_req, (char *) xmlbuf, xlen);
|
||||
|
||||
xmlFreeDoc(rdoc);
|
||||
xmlFree(xmlbuf);
|
||||
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_router_xmldir(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_xmldir;
|
||||
ur->data = args;
|
||||
ur->data_len = strlen(args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void router_xmldir_register() {
|
||||
uwsgi_register_router("xmldir", uwsgi_router_xmldir);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin router_xmldir_plugin = {
|
||||
.name = "router_xmldir",
|
||||
.on_load = router_xmldir_register,
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
NAME='router_xmldir'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
GCC_LIST = ['router_xmldir']
|
||||
@@ -0,0 +1,138 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
#if defined(UWSGI_ROUTING)
|
||||
|
||||
/*
|
||||
|
||||
offload transformation
|
||||
|
||||
each chunk is buffered to the transformation custom buffer
|
||||
|
||||
if the buffer grows higher than the specified limit, the response will be buffered to disk
|
||||
|
||||
on final the memory (or the tmpfile) will be offloaded
|
||||
|
||||
even if we are talking about buffering, this is a streaming transformation
|
||||
as we need to hold control on memory usage
|
||||
|
||||
"offload" MUST BE the last transformation in the chain. Hellish things will happen otherwise...
|
||||
|
||||
*/
|
||||
|
||||
static int transform_offload(struct wsgi_request *wsgi_req, struct uwsgi_transformation *ut) {
|
||||
|
||||
if (ut->is_final) {
|
||||
struct uwsgi_transformation *orig_ut = (struct uwsgi_transformation *) ut->data;
|
||||
// sendfile offload
|
||||
if (orig_ut->fd > -1) {
|
||||
if (!uwsgi_offload_request_sendfile_do(wsgi_req, orig_ut->fd, orig_ut->len)) {
|
||||
// the fd will be closed by the offload engine
|
||||
orig_ut->fd = -1;
|
||||
wsgi_req->via = UWSGI_VIA_OFFLOAD;
|
||||
wsgi_req->response_size += orig_ut->len;
|
||||
return 0;
|
||||
}
|
||||
// fallback to non-offloaded write
|
||||
if (uwsgi_simple_sendfile(wsgi_req, orig_ut->fd, 0, orig_ut->len)) {
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->response_size += orig_ut->len;
|
||||
return 0;
|
||||
}
|
||||
// memory offload
|
||||
if (orig_ut->ub) {
|
||||
if (!uwsgi_offload_request_memory_do(wsgi_req, orig_ut->ub->buf, orig_ut->ub->pos)) {
|
||||
// memory will be freed by the offload engine
|
||||
orig_ut->ub->buf = NULL;
|
||||
wsgi_req->via = UWSGI_VIA_OFFLOAD;
|
||||
wsgi_req->response_size += orig_ut->ub->pos;
|
||||
return 0;
|
||||
}
|
||||
// fallback to non-offloaded write
|
||||
if (uwsgi_simple_write(wsgi_req, orig_ut->ub->buf, orig_ut->ub->pos)) {
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->response_size += orig_ut->ub->pos;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// check if we need to start buffering to disk
|
||||
if (ut->fd == -1 && ut->len + ut->chunk->pos > ut->custom64) {
|
||||
ut->fd = uwsgi_tmpfd();
|
||||
if (ut->fd < 0) return -1;
|
||||
// save already buffered data
|
||||
if (ut->ub) {
|
||||
ssize_t wlen = write(ut->fd, ut->ub->buf, ut->ub->pos);
|
||||
if (wlen != (ssize_t) ut->ub->pos) {
|
||||
uwsgi_error("transform_offload/write()");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if fd > -1, append to file
|
||||
if (ut->fd > -1) {
|
||||
ssize_t wlen = write(ut->fd, ut->chunk->buf, ut->chunk->pos);
|
||||
if (wlen != (ssize_t) ut->chunk->pos) {
|
||||
uwsgi_error("transform_offload/write()");
|
||||
return -1;
|
||||
}
|
||||
ut->len += wlen;
|
||||
goto done;
|
||||
}
|
||||
|
||||
// buffer to memory
|
||||
if (!ut->ub) {
|
||||
ut->ub = uwsgi_buffer_new(ut->chunk->pos);
|
||||
}
|
||||
|
||||
// append the chunk to the custom buffer
|
||||
if (uwsgi_buffer_append(ut->ub, ut->chunk->buf, ut->chunk->pos)) return -1;
|
||||
ut->len += ut->chunk->pos;
|
||||
done:
|
||||
// reset the chunk !!!
|
||||
ut->chunk->pos = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_routing_func_offload(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
if (!wsgi_req->socket->can_offload) {
|
||||
uwsgi_log("unable to use the offload transformation without offload threads !!!\n");
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
struct uwsgi_transformation *ut = uwsgi_add_transformation(wsgi_req, transform_offload, NULL);
|
||||
ut->can_stream = 1;
|
||||
ut->custom64 = ur->custom;
|
||||
// add a "final" transformation to add the trailing chunk
|
||||
ut = uwsgi_add_transformation(wsgi_req, transform_offload, ut);
|
||||
ut->is_final = 1;
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
|
||||
static int uwsgi_router_offload(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_offload;
|
||||
if (args[0] == 0) {
|
||||
// 1 MB limit
|
||||
ur->custom = 1024 * 1024;
|
||||
}
|
||||
else {
|
||||
ur->custom = strtoul(args, NULL, 10);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void router_offload_register(void) {
|
||||
uwsgi_register_router("offload", uwsgi_router_offload);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin transformation_offload_plugin = {
|
||||
.name = "transformation_offload",
|
||||
.on_load = router_offload_register,
|
||||
};
|
||||
#else
|
||||
struct uwsgi_plugin transformation_offload_plugin = {
|
||||
.name = "transformation_offload",
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='transformation_offload'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
GCC_LIST = ['offload']
|
||||
+18
-2
@@ -150,11 +150,17 @@ parse:
|
||||
|
||||
|
||||
ssize_t uwsgi_proto_fastcgi_read_body(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
int has_read = 0;
|
||||
if (wsgi_req->proto_parser_remains > 0) {
|
||||
size_t remains = UMIN(wsgi_req->proto_parser_remains, len);
|
||||
memcpy(buf, wsgi_req->proto_parser_remains_buf, remains);
|
||||
wsgi_req->proto_parser_remains -= remains;
|
||||
wsgi_req->proto_parser_remains_buf += remains;
|
||||
// we consumed all of the body, we can safely move the memory
|
||||
if (wsgi_req->proto_parser_remains == 0 && wsgi_req->proto_parser_move) {
|
||||
memmove(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_buf + wsgi_req->proto_parser_move, wsgi_req->proto_parser_pos);
|
||||
wsgi_req->proto_parser_move = 0;
|
||||
}
|
||||
return remains;
|
||||
}
|
||||
|
||||
@@ -176,7 +182,14 @@ ssize_t uwsgi_proto_fastcgi_read_body(struct wsgi_request *wsgi_req, char *buf,
|
||||
// copy remaining
|
||||
wsgi_req->proto_parser_remains = fcgi_len - remains;
|
||||
wsgi_req->proto_parser_remains_buf = wsgi_req->proto_parser_buf + sizeof(struct fcgi_record) + remains;
|
||||
memmove(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_buf + fcgi_all_len, wsgi_req->proto_parser_pos - fcgi_all_len);
|
||||
// we consumed all of the body, we can safely move the memory
|
||||
if (wsgi_req->proto_parser_remains == 0) {
|
||||
memmove(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_buf + fcgi_all_len, wsgi_req->proto_parser_pos - fcgi_all_len);
|
||||
}
|
||||
else {
|
||||
// postpone memory move
|
||||
wsgi_req->proto_parser_move = fcgi_all_len;
|
||||
}
|
||||
wsgi_req->proto_parser_pos -= fcgi_all_len;
|
||||
return remains;
|
||||
}
|
||||
@@ -192,12 +205,15 @@ ssize_t uwsgi_proto_fastcgi_read_body(struct wsgi_request *wsgi_req, char *buf,
|
||||
wsgi_req->proto_parser_buf = tmp_buf;
|
||||
wsgi_req->proto_parser_buf_size += fcgi_all_len - (wsgi_req->proto_parser_buf_size - wsgi_req->proto_parser_pos);
|
||||
}
|
||||
goto gather;
|
||||
if (!has_read) goto gather;
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
gather:
|
||||
rlen = read(wsgi_req->fd, wsgi_req->proto_parser_buf + wsgi_req->proto_parser_pos, wsgi_req->proto_parser_buf_size - wsgi_req->proto_parser_pos);
|
||||
if (rlen > 0) {
|
||||
has_read = 1;
|
||||
wsgi_req->proto_parser_pos += rlen;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
"""
|
||||
simplified test for continulet without checking for partial writes
|
||||
|
||||
to enable continulets you only need to call uwsgi_pypy_setup_continulets() soon after startup:
|
||||
|
||||
uwsgi --pypy-wsgi-file t/pypy/t_continulet1.py --http-socket :9090 --pypy-home /opt/pypy --pypy-eval "uwsgi_pypy_setup_continulets()" --async 8
|
||||
|
||||
"""
|
||||
import uwsgi
|
||||
def application(e, sr):
|
||||
sr('200 OK', [('Content-Type','text/plain')])
|
||||
|
||||
# call suspend 10 times and yield some value
|
||||
for i in range(0,10):
|
||||
print i
|
||||
uwsgi.suspend()
|
||||
yield str(i)
|
||||
|
||||
# connect to a memcached server
|
||||
fd = uwsgi.async_connect('127.0.0.1:11211')
|
||||
try:
|
||||
# start waiting for socket availability (4 seconds max)
|
||||
uwsgi.wait_fd_write(fd, 4)
|
||||
# suspend execution 'til event
|
||||
uwsgi.suspend()
|
||||
uwsgi.send(fd, "get /foobar\r\n")
|
||||
# now wait for memcached response
|
||||
uwsgi.wait_fd_read(fd, 4)
|
||||
uwsgi.suspend()
|
||||
# read the response
|
||||
data = uwsgi.recv(fd, 4096)
|
||||
# return to the client
|
||||
yield data
|
||||
finally:
|
||||
uwsgi.close(fd)
|
||||
|
||||
print "sleeping for 3 seconds..."
|
||||
uwsgi.async_sleep(3)
|
||||
uwsgi.suspend()
|
||||
yield "done"
|
||||
@@ -0,0 +1,47 @@
|
||||
"""
|
||||
safer test for continulet with partial writes check
|
||||
|
||||
to enable continulets you only need to call uwsgi_pypy_setup_continulets() soon after startup:
|
||||
|
||||
uwsgi --pypy-wsgi-file t/pypy/t_continulet2.py --http-socket :9090 --pypy-home /opt/pypy --pypy-eval "uwsgi_pypy_setup_continulets()" --async 8
|
||||
|
||||
"""
|
||||
import uwsgi
|
||||
def application(e, sr):
|
||||
sr('200 OK', [('Content-Type','text/plain')])
|
||||
|
||||
# suspend 10 times and yield a value
|
||||
for i in range(1,10):
|
||||
print i
|
||||
uwsgi.suspend()
|
||||
yield str(i)
|
||||
|
||||
# connect to a memcached server
|
||||
fd = uwsgi.async_connect('127.0.0.1:11211')
|
||||
try:
|
||||
command = "get /foobar\r\n"
|
||||
remains = len(command)
|
||||
while remains > 0:
|
||||
# start waiting for socket availability (4 seconds max)
|
||||
uwsgi.wait_fd_write(fd, 4)
|
||||
# suspend execution 'til event
|
||||
uwsgi.suspend()
|
||||
pos = len(command) - remains
|
||||
written = uwsgi.send(fd, command[pos:])
|
||||
remains -= written
|
||||
|
||||
# now wait for memcached response
|
||||
uwsgi.wait_fd_read(fd, 4)
|
||||
uwsgi.suspend()
|
||||
# read a chunk of data
|
||||
data = uwsgi.recv(fd, 4096)
|
||||
# .. and yield it
|
||||
yield data
|
||||
finally:
|
||||
# always ensure sockets are closed
|
||||
uwsgi.close(fd)
|
||||
|
||||
print "sleeping for 3 seconds..."
|
||||
uwsgi.async_sleep(3)
|
||||
uwsgi.suspend()
|
||||
yield "done"
|
||||
@@ -0,0 +1,14 @@
|
||||
import socket
|
||||
import sys
|
||||
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
|
||||
(addr, port) = sys.argv[1].split(':')
|
||||
s.connect((addr, int(port)))
|
||||
|
||||
s.send("POST /send HTTP/1.1\r\n")
|
||||
s.send("Transfer-Encoding: chunked\r\n\r\n")
|
||||
|
||||
while True:
|
||||
msg = raw_input("msg >> ")
|
||||
s.send("%X\r\n%s\r\n" % (len(msg), msg))
|
||||
@@ -0,0 +1,81 @@
|
||||
#!./uwsgi --http-socket :9090 --async 100 ...
|
||||
# same chat example but using uwsgi async api
|
||||
# for pypy + continulets just run:
|
||||
# uwsgi --http-socket :9090 --pypy-home /opt/pypy --pypy-wsgi-file tests/websockets_chat_async.py --pypy-eval "uwsgi_pypy_setup_continulets()" --async 100
|
||||
import uwsgi
|
||||
import time
|
||||
import redis
|
||||
|
||||
def application(env, sr):
|
||||
|
||||
ws_scheme = 'ws'
|
||||
if 'HTTPS' in env or env['wsgi.url_scheme'] == 'https':
|
||||
ws_scheme = 'wss'
|
||||
|
||||
if env['PATH_INFO'] == '/':
|
||||
sr('200 OK', [('Content-Type','text/html')])
|
||||
return """
|
||||
<html>
|
||||
<head>
|
||||
<script language="Javascript">
|
||||
var s = new WebSocket("%s://%s/foobar/");
|
||||
s.onopen = function() {
|
||||
alert("connected !!!");
|
||||
s.send("ciao");
|
||||
};
|
||||
s.onmessage = function(e) {
|
||||
var bb = document.getElementById('blackboard')
|
||||
var html = bb.innerHTML;
|
||||
bb.innerHTML = html + '<br/>' + e.data;
|
||||
};
|
||||
|
||||
s.onerror = function(e) {
|
||||
alert(e);
|
||||
}
|
||||
|
||||
s.onclose = function(e) {
|
||||
alert("connection closed");
|
||||
}
|
||||
|
||||
function invia() {
|
||||
var value = document.getElementById('testo').value;
|
||||
s.send(value);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>WebSocket</h1>
|
||||
<input type="text" id="testo"/>
|
||||
<input type="button" value="invia" onClick="invia();"/>
|
||||
<div id="blackboard" style="width:640px;height:480px;background-color:black;color:white;border: solid 2px red;overflow:auto">
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
""" % (ws_scheme, env['HTTP_HOST'])
|
||||
elif env['PATH_INFO'] == '/favicon.ico':
|
||||
return ""
|
||||
elif env['PATH_INFO'] == '/foobar/':
|
||||
uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', ''))
|
||||
print "websockets..."
|
||||
r = redis.StrictRedis(host='localhost', port=6379, db=0)
|
||||
channel = r.pubsub()
|
||||
channel.subscribe('foobar')
|
||||
|
||||
websocket_fd = uwsgi.connection_fd()
|
||||
redis_fd = channel.connection._sock.fileno()
|
||||
|
||||
while True:
|
||||
uwsgi.wait_fd_read(websocket_fd)
|
||||
uwsgi.wait_fd_read(redis_fd)
|
||||
uwsgi.suspend()
|
||||
fd = uwsgi.ready_fd()
|
||||
if fd > -1:
|
||||
if fd == websocket_fd:
|
||||
msg = uwsgi.websocket_recv_nb()
|
||||
if msg:
|
||||
r.publish('foobar', msg)
|
||||
elif fd == redis_fd:
|
||||
msg = channel.parse_response()
|
||||
# only interested in user messages
|
||||
if msg[0] == 'message':
|
||||
uwsgi.websocket_send("[%s] %s" % (time.time(), msg))
|
||||
+1
-1
@@ -2,7 +2,7 @@ Gem::Specification.new do |s|
|
||||
s.name = 'uwsgi'
|
||||
s.license = 'GPL-2'
|
||||
s.version = `python -c "import uwsgiconfig as uc; print uc.uwsgi_version"`.sub(/-dev-.*/,'')
|
||||
s.date = '2013-05-26'
|
||||
s.date = '2013-06-05'
|
||||
s.summary = "uWSGI"
|
||||
s.description = "The uWSGI server for Ruby/Rack"
|
||||
s.authors = ["Unbit"]
|
||||
|
||||
@@ -218,11 +218,6 @@ extern "C" {
|
||||
#include <sys/prctl.h>
|
||||
#include <linux/limits.h>
|
||||
#include <sys/mount.h>
|
||||
#ifdef UWSGI_PTRACE
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/reg.h>
|
||||
#endif
|
||||
extern int pivot_root(const char *new_root, const char *put_old);
|
||||
#endif
|
||||
|
||||
@@ -278,7 +273,9 @@ extern int pivot_root(const char *new_root, const char *put_old);
|
||||
#endif
|
||||
|
||||
#if defined(__HAIKU__) || defined(__CYGWIN__)
|
||||
#ifndef WAIT_ANY
|
||||
#define WAIT_ANY (-1)
|
||||
#endif
|
||||
#define PRIO_MAX 20
|
||||
#endif
|
||||
|
||||
@@ -1048,6 +1045,7 @@ struct uwsgi_spooler {
|
||||
uint64_t tasks;
|
||||
struct uwsgi_lock_item *lock;
|
||||
time_t harakiri;
|
||||
time_t user_harakiri;
|
||||
|
||||
int mode;
|
||||
|
||||
@@ -1220,6 +1218,10 @@ struct uwsgi_transformation {
|
||||
uint8_t flushed;
|
||||
void *data;
|
||||
uint64_t round;
|
||||
int fd;
|
||||
struct uwsgi_buffer *ub;
|
||||
uint64_t len;
|
||||
uint64_t custom64;
|
||||
struct uwsgi_transformation *next;
|
||||
};
|
||||
|
||||
@@ -1398,6 +1400,7 @@ struct wsgi_request {
|
||||
int headers_hvec;
|
||||
|
||||
uint64_t proto_parser_pos;
|
||||
uint64_t proto_parser_move;
|
||||
int64_t proto_parser_status;
|
||||
void *proto_parser_buf;
|
||||
uint64_t proto_parser_buf_size;
|
||||
@@ -1426,6 +1429,12 @@ struct wsgi_request {
|
||||
time_t websocket_last_pong;
|
||||
int websocket_closed;
|
||||
|
||||
struct uwsgi_buffer *chunked_input_buf;
|
||||
uint8_t chunked_input_parser_status;
|
||||
ssize_t chunked_input_chunk_len;
|
||||
size_t chunked_input_need;
|
||||
uint8_t chunked_input_complete;
|
||||
|
||||
uint64_t stream_id;
|
||||
|
||||
// avoid routing loops
|
||||
@@ -1870,6 +1879,8 @@ struct uwsgi_server {
|
||||
struct uwsgi_regexp_list *log_req_route;
|
||||
#endif
|
||||
|
||||
int use_abort;
|
||||
|
||||
int alarm_freq;
|
||||
uint64_t alarm_msg_size;
|
||||
struct uwsgi_string_list *alarm_list;
|
||||
@@ -1945,6 +1956,7 @@ struct uwsgi_server {
|
||||
struct uwsgi_offload_engine *offload_engine_sendfile;
|
||||
struct uwsgi_offload_engine *offload_engine_transfer;
|
||||
struct uwsgi_offload_engine *offload_engine_memory;
|
||||
struct uwsgi_offload_engine *offload_engine_pipe;
|
||||
int offload_threads;
|
||||
int offload_threads_events;
|
||||
struct uwsgi_thread **offload_thread;
|
||||
@@ -1995,6 +2007,7 @@ struct uwsgi_server {
|
||||
struct uwsgi_string_list *touch_logrotate;
|
||||
struct uwsgi_string_list *touch_logreopen;
|
||||
struct uwsgi_string_list *touch_exec;
|
||||
struct uwsgi_string_list *touch_signal;
|
||||
|
||||
int propagate_touch;
|
||||
|
||||
@@ -2237,6 +2250,7 @@ struct uwsgi_server {
|
||||
size_t lock_size;
|
||||
size_t rwlock_size;
|
||||
|
||||
struct uwsgi_string_list *add_cache_item;
|
||||
struct uwsgi_string_list *load_file_in_cache;
|
||||
#ifdef UWSGI_ZLIB
|
||||
struct uwsgi_string_list *load_file_in_cache_gzip;
|
||||
@@ -2339,6 +2353,9 @@ struct uwsgi_server {
|
||||
int websockets_pong_tolerance;
|
||||
uint64_t websockets_max_size;
|
||||
|
||||
int chunked_input_timeout;
|
||||
uint64_t chunked_input_limit;
|
||||
|
||||
int (*wait_write_hook) (int, int);
|
||||
int (*wait_read_hook) (int, int);
|
||||
|
||||
@@ -2568,6 +2585,7 @@ struct uwsgi_mule {
|
||||
uint8_t signum;
|
||||
|
||||
time_t harakiri;
|
||||
time_t user_harakiri;
|
||||
|
||||
char name[0xff];
|
||||
};
|
||||
@@ -3227,6 +3245,7 @@ struct uwsgi_gateway_socket *uwsgi_new_gateway_socket(char *, char *);
|
||||
struct uwsgi_gateway_socket *uwsgi_new_gateway_socket_from_fd(int, char *);
|
||||
|
||||
void escape_shell_arg(char *, size_t, char *);
|
||||
void escape_json(char *, size_t, char *);
|
||||
|
||||
void *uwsgi_malloc_shared(size_t);
|
||||
void *uwsgi_calloc_shared(size_t);
|
||||
@@ -3355,7 +3374,8 @@ void uwsgi_opt_set_cap(char *, char *, void *);
|
||||
void uwsgi_opt_set_unshare(char *, char *, void *);
|
||||
#endif
|
||||
|
||||
char *uwsgi_tmpname(char *, char *);
|
||||
int uwsgi_tmpfd();
|
||||
FILE *uwsgi_tmpfile();
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
struct uwsgi_router *uwsgi_register_router(char *, int (*)(struct uwsgi_route *, char *));
|
||||
@@ -3490,9 +3510,13 @@ char *uwsgi_substitute(char *, char *, char *);
|
||||
|
||||
void uwsgi_opt_add_custom_option(char *, char *, void *);
|
||||
void uwsgi_opt_cflags(char *, char *, void *);
|
||||
void uwsgi_opt_dot_h(char *, char *, void *);
|
||||
void uwsgi_opt_connect_and_read(char *, char *, void *);
|
||||
void uwsgi_opt_extract(char *, char *, void *);
|
||||
|
||||
char *uwsgi_get_dot_h();
|
||||
char *uwsgi_get_cflags();
|
||||
|
||||
struct uwsgi_string_list *uwsgi_string_list_has_item(struct uwsgi_string_list *, char *, size_t);
|
||||
|
||||
void trigger_harakiri(int);
|
||||
@@ -3770,6 +3794,10 @@ struct uwsgi_thread *uwsgi_offload_thread_start(void);
|
||||
int uwsgi_offload_request_sendfile_do(struct wsgi_request *, int, size_t);
|
||||
int uwsgi_offload_request_net_do(struct wsgi_request *, char *, struct uwsgi_buffer *);
|
||||
int uwsgi_offload_request_memory_do(struct wsgi_request *, char *, size_t);
|
||||
int uwsgi_offload_request_pipe_do(struct wsgi_request *, int, size_t);
|
||||
|
||||
int uwsgi_simple_sendfile(struct wsgi_request *, int, size_t, size_t);
|
||||
int uwsgi_simple_write(struct wsgi_request *, char *, size_t);
|
||||
|
||||
|
||||
void uwsgi_subscription_set_algo(char *);
|
||||
@@ -3852,6 +3880,8 @@ int uwsgi_websocket_send(struct wsgi_request *, char *, size_t);
|
||||
struct uwsgi_buffer *uwsgi_websocket_recv(struct wsgi_request *);
|
||||
struct uwsgi_buffer *uwsgi_websocket_recv_nb(struct wsgi_request *);
|
||||
|
||||
char *uwsgi_chunked_read(struct wsgi_request *, size_t *, int, int);
|
||||
|
||||
uint16_t uwsgi_be16(char *);
|
||||
uint32_t uwsgi_be32(char *);
|
||||
uint64_t uwsgi_be64(char *);
|
||||
@@ -3995,9 +4025,11 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *);
|
||||
#ifdef UWSGI_ZLIB
|
||||
#include <zlib.h>
|
||||
int uwsgi_deflate_init(z_stream *, char *, size_t);
|
||||
int uwsgi_inflate_init(z_stream *, char *, size_t);
|
||||
char *uwsgi_deflate(z_stream *, char *, size_t, size_t *);
|
||||
void uwsgi_crc32(uint32_t *, char *, size_t);
|
||||
struct uwsgi_buffer *uwsgi_gzip(char *, size_t);
|
||||
struct uwsgi_buffer *uwsgi_zlib_decompress(char *, size_t);
|
||||
int uwsgi_gzip_fix(z_stream *, uint32_t, struct uwsgi_buffer *, size_t);
|
||||
char *uwsgi_gzip_chunk(z_stream *, uint32_t *, char *, size_t, size_t *);
|
||||
int uwsgi_gzip_prepare(z_stream *, char *, size_t, uint32_t *);
|
||||
@@ -4040,6 +4072,10 @@ void uwsgi_takeover(void);
|
||||
|
||||
char *uwsgi_binary_path(void);
|
||||
|
||||
int uwsgi_is_again();
|
||||
void uwsgi_disconnect(struct wsgi_request *);
|
||||
int uwsgi_ready_fd(struct wsgi_request *);
|
||||
|
||||
void uwsgi_check_emperor(void);
|
||||
#ifdef UWSGI_AS_SHARED_LIBRARY
|
||||
int uwsgi_init(int, char **, char **);
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
send_message()
|
||||
send_multi_message()
|
||||
reload()
|
||||
workers()
|
||||
masterpid()
|
||||
total_requests()
|
||||
getoption(id)
|
||||
get_option(id)
|
||||
setoption(id, value)
|
||||
set_option(id, value)
|
||||
sorry_i_need_to_block()
|
||||
request_id()
|
||||
worker_id()
|
||||
log(message)
|
||||
disconnect()
|
||||
grunt()
|
||||
load_plugin()
|
||||
lock()
|
||||
unlock()
|
||||
send()
|
||||
cl()
|
||||
req_fd()
|
||||
signal(num)
|
||||
sendfile()
|
||||
set_warning_message()
|
||||
mem()
|
||||
has_hook()
|
||||
logsize()
|
||||
send_multicast_message
|
||||
cluster_nodes
|
||||
cluster_best_node
|
||||
async_sleep
|
||||
async_connect
|
||||
async_send_message
|
||||
green_schedule
|
||||
suspend
|
||||
wait_fd_read(fd, [timeout])
|
||||
wait_fd_write(fd, timeout)
|
||||
is_connected()
|
||||
send
|
||||
recv()
|
||||
recv_block
|
||||
recv_frame
|
||||
close
|
||||
parsefile
|
||||
sharedarea_read
|
||||
sharedarea_write
|
||||
sharedarea_readbyte
|
||||
sharedarea_writebyte
|
||||
sharedarea_readlong
|
||||
sharedarea_writelong
|
||||
sharedarea_inclong
|
||||
register_signal(num, targer, handler)
|
||||
register_rpc(name, func[,args])
|
||||
rpc(node, name[,args,...])
|
||||
+61
-12
@@ -1,6 +1,6 @@
|
||||
# uWSGI build system
|
||||
|
||||
uwsgi_version = '1.9.11'
|
||||
uwsgi_version = '1.9.13'
|
||||
|
||||
import os
|
||||
import re
|
||||
@@ -25,13 +25,17 @@ try:
|
||||
import ConfigParser
|
||||
except:
|
||||
import configparser as ConfigParser
|
||||
from imp import reload
|
||||
|
||||
GCC = os.environ.get('CC', sysconfig.get_config_var('CC'))
|
||||
if not GCC:
|
||||
GCC = 'gcc'
|
||||
|
||||
CPP = os.environ.get('CPP', 'cpp')
|
||||
def get_preprocessor():
|
||||
if 'clang' in GCC:
|
||||
return 'clang -xc core/clang_fake.c'
|
||||
return 'cpp'
|
||||
|
||||
CPP = os.environ.get('CPP', get_preprocessor())
|
||||
|
||||
try:
|
||||
CPUCOUNT = int(os.environ.get('CPUCOUNT', -1))
|
||||
@@ -245,11 +249,11 @@ def build_uwsgi(uc, print_only=False):
|
||||
print("detected CPU cores: %d" % CPUCOUNT)
|
||||
print("configured CFLAGS: %s" % ' '.join(cflags))
|
||||
|
||||
try:
|
||||
uwsgi_cflags = ' '.join(cflags).encode('hex')
|
||||
except:
|
||||
if sys.version_info[0] >= 3:
|
||||
import binascii
|
||||
uwsgi_cflags = binascii.b2a_hex(' '.join(cflags).encode('ascii')).decode('ascii')
|
||||
else:
|
||||
uwsgi_cflags = ' '.join(cflags).encode('hex')
|
||||
|
||||
last_cflags_ts = 0
|
||||
|
||||
@@ -267,6 +271,27 @@ def build_uwsgi(uc, print_only=False):
|
||||
ulc.write(uwsgi_cflags)
|
||||
ulc.close()
|
||||
|
||||
|
||||
# embed uwsgi.h in the server binary. It increases the binary size, but will be very useful
|
||||
# for various tricks (like cffi integration)
|
||||
# if possibile, the blob is compressed
|
||||
if sys.version_info[0] >= 3:
|
||||
uwsgi_dot_h_content = open('uwsgi.h', 'rb').read()
|
||||
else:
|
||||
uwsgi_dot_h_content = open('uwsgi.h').read()
|
||||
if report['zlib']:
|
||||
import zlib
|
||||
# maximum level of compression
|
||||
uwsgi_dot_h_content = zlib.compress(uwsgi_dot_h_content, 9)
|
||||
if sys.version_info[0] >= 3:
|
||||
import binascii
|
||||
uwsgi_dot_h = binascii.b2a_hex(uwsgi_dot_h_content).decode('ascii')
|
||||
else:
|
||||
uwsgi_dot_h = uwsgi_dot_h_content.encode('hex')
|
||||
open('core/dot_h.c', 'w').write('char *uwsgi_dot_h = "%s";\n' % uwsgi_dot_h);
|
||||
gcc_list.append('core/dot_h')
|
||||
|
||||
|
||||
cflags.append('-DUWSGI_CFLAGS=\\"%s\\"' % uwsgi_cflags)
|
||||
cflags.append('-DUWSGI_BUILD_DATE="\\"%s\\""' % time.strftime("%d %B %Y %H:%M:%S"))
|
||||
|
||||
@@ -317,6 +342,13 @@ def build_uwsgi(uc, print_only=False):
|
||||
except:
|
||||
pass
|
||||
|
||||
if GCC in ('clang',):
|
||||
try:
|
||||
p_cflags.remove('-fno-fast-math')
|
||||
p_cflags.remove('-ggdb3')
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
p_cflags.remove('-Wdeclaration-after-statement')
|
||||
except:
|
||||
@@ -456,6 +488,8 @@ def open_profile(filename):
|
||||
class uConf(object):
|
||||
|
||||
def __init__(self, filename, mute=False):
|
||||
global GCC
|
||||
|
||||
self.config = ConfigParser.ConfigParser()
|
||||
if not mute:
|
||||
print("using profile: %s" % filename)
|
||||
@@ -476,7 +510,7 @@ class uConf(object):
|
||||
'core/notify', 'core/mule', 'core/subscription', 'core/stats', 'core/sendfile', 'core/async', 'core/master_checks',
|
||||
'core/offload', 'core/io', 'core/static', 'core/websockets', 'core/spooler', 'core/snmp', 'core/exceptions', 'core/config',
|
||||
'core/setup_utils', 'core/clock', 'core/init', 'core/buffer', 'core/reader', 'core/writer', 'core/alarm', 'core/cron',
|
||||
'core/plugins', 'core/lock', 'core/cache', 'core/daemons', 'core/errors', 'core/hash', 'core/master_events',
|
||||
'core/plugins', 'core/lock', 'core/cache', 'core/daemons', 'core/errors', 'core/hash', 'core/master_events', 'core/chunked',
|
||||
'core/queue', 'core/event', 'core/signal', 'core/strings', 'core/progress', 'core/timebomb', 'core/ini',
|
||||
'core/rpc', 'core/gateway', 'core/loop', 'core/cookie', 'core/querystring', 'core/rb_timers', 'core/transformations', 'core/uwsgi']
|
||||
# add protocols
|
||||
@@ -487,6 +521,10 @@ class uConf(object):
|
||||
self.gcc_list.append('proto/scgi')
|
||||
self.include_path = []
|
||||
|
||||
if 'UWSGI_INCLUDES' in os.environ:
|
||||
self.include_path += os.environ['UWSGI_INCLUDES'].split(',')
|
||||
|
||||
|
||||
self.cflags = ['-O2', '-I.', '-Wall', '-Werror', '-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64'] + os.environ.get("CFLAGS", "").split() + self.get('cflags','').split()
|
||||
|
||||
report['kernel'] = uwsgi_os
|
||||
@@ -504,11 +542,13 @@ class uConf(object):
|
||||
if uwsgi_os == 'GNU':
|
||||
self.cflags.append('-D__HURD__')
|
||||
|
||||
try:
|
||||
gcc_version = str(spcall("%s -dumpversion" % GCC))
|
||||
except:
|
||||
print("*** you need a c compiler to build uWSGI ***")
|
||||
sys.exit(1)
|
||||
gcc_version = spcall("%s -dumpversion" % GCC)
|
||||
if not gcc_version and GCC.startswith('gcc'):
|
||||
if uwsgi_os == 'Darwin':
|
||||
GCC = 'llvm-' + GCC
|
||||
else:
|
||||
GCC = 'gcc'
|
||||
gcc_version = spcall("%s -dumpversion" % GCC)
|
||||
|
||||
try:
|
||||
add_it = False
|
||||
@@ -655,6 +695,8 @@ class uConf(object):
|
||||
|
||||
if uwsgi_os == 'Darwin':
|
||||
self.cflags.append('-mmacosx-version-min=10.5')
|
||||
if GCC in ('clang',):
|
||||
self.libs.remove('-rdynamic')
|
||||
|
||||
# compile extras
|
||||
extras = self.get('extras', None)
|
||||
@@ -1197,6 +1239,13 @@ def build_plugin(path, uc, cflags, ldflags, libs, name = None):
|
||||
except:
|
||||
pass
|
||||
|
||||
if GCC in ('clang',):
|
||||
try:
|
||||
p_cflags.remove('-fno-fast-math')
|
||||
p_cflags.remove('-ggdb3')
|
||||
except:
|
||||
pass
|
||||
|
||||
if uwsgi_os.startswith('CYGWIN'):
|
||||
try:
|
||||
p_cflags.remove('-fstack-protector')
|
||||
|
||||
+19
-24
@@ -1,4 +1,3 @@
|
||||
import uwsgi
|
||||
import sys
|
||||
from threading import Thread
|
||||
|
||||
@@ -7,6 +6,7 @@ try:
|
||||
except:
|
||||
import pickle
|
||||
|
||||
import uwsgi
|
||||
|
||||
if uwsgi.masterpid() == 0:
|
||||
raise Exception(
|
||||
@@ -45,48 +45,43 @@ class postfork(object):
|
||||
postfork_chain.append(f)
|
||||
|
||||
|
||||
class spool(object):
|
||||
class spoolraw(object):
|
||||
|
||||
def spool(self, *args, **kwargs):
|
||||
def __call__(self, *args, **kwargs):
|
||||
arguments = self.base_dict
|
||||
arguments['ud_spool_ret'] = str(uwsgi.SPOOL_OK)
|
||||
if len(args) > 0:
|
||||
arguments.update(args[0])
|
||||
if kwargs:
|
||||
arguments.update(kwargs)
|
||||
return uwsgi.spool(arguments)
|
||||
|
||||
# For backward compatibility (uWSGI < 1.9.13)
|
||||
def spool(self, *args, **kwargs):
|
||||
return self.__class__.__call__(self, *args, **kwargs)
|
||||
|
||||
def __init__(self, f):
|
||||
if not 'spooler' in uwsgi.opt:
|
||||
raise Exception(
|
||||
"you have to enable the uWSGI spooler to use @spool decorator")
|
||||
"you have to enable the uWSGI spooler to use @%s decorator" % self.__class__.__name__)
|
||||
self.f = f
|
||||
spooler_functions[f.__name__] = self.f
|
||||
self.f.spool = self.spool
|
||||
spooler_functions[self.f.__name__] = self.f
|
||||
# For backward compatibility (uWSGI < 1.9.13)
|
||||
self.f.spool = self.__call__
|
||||
self.base_dict = {'ud_spool_func': self.f.__name__}
|
||||
|
||||
|
||||
class spoolforever(spool):
|
||||
class spool(spoolraw):
|
||||
|
||||
def spool(self, *args, **kwargs):
|
||||
arguments = self.base_dict
|
||||
arguments['ud_spool_ret'] = str(uwsgi.SPOOL_RETRY)
|
||||
if len(args) > 0:
|
||||
arguments.update(args[0])
|
||||
if kwargs:
|
||||
arguments.update(kwargs)
|
||||
return uwsgi.spool(arguments)
|
||||
def __call__(self, *args, **kwargs):
|
||||
self.base_dict['ud_spool_ret'] = str(uwsgi.SPOOL_OK)
|
||||
return spoolraw.__call__(self, *args, **kwargs)
|
||||
|
||||
|
||||
class spoolraw(spool):
|
||||
class spoolforever(spoolraw):
|
||||
|
||||
def spool(self, *args, **kwargs):
|
||||
arguments = self.base_dict
|
||||
if len(args) > 0:
|
||||
arguments.update(args[0])
|
||||
if kwargs:
|
||||
arguments.update(kwargs)
|
||||
return uwsgi.spool(arguments)
|
||||
def __call__(self, *args, **kwargs):
|
||||
self.base_dict['ud_spool_ret'] = str(uwsgi.SPOOL_RETRY)
|
||||
return spoolraw.__call__(self, *args, **kwargs)
|
||||
|
||||
|
||||
class mulefunc(object):
|
||||
|
||||
Reference in New Issue
Block a user