mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d82ee16e0c | ||
|
|
e4d65c07ce | ||
|
|
86fcb78cc3 | ||
|
|
5beb422d75 | ||
|
|
53679879ca | ||
|
|
a8ad766182 | ||
|
|
cbb2d30f79 | ||
|
|
c5e00bcec6 | ||
|
|
51535d374d | ||
|
|
1e057e6c35 | ||
|
|
b23e8ab862 | ||
|
|
0f7f13dfb2 | ||
|
|
aa19ccda1d | ||
|
|
cd0129e780 | ||
|
|
506c9023e6 | ||
|
|
d47c25ea4c | ||
|
|
010651073c | ||
|
|
76364e3799 | ||
|
|
f9fd0a0203 | ||
|
|
8dfbde5d16 | ||
|
|
888991f8c1 | ||
|
|
ece03922d6 | ||
|
|
47bb827e6e | ||
|
|
a56003d847 | ||
|
|
61022c398c | ||
|
|
00bd8cc525 | ||
|
|
cf6a232aef | ||
|
|
59d1a45ef0 | ||
|
|
0b5f9fcb48 | ||
|
|
f713ffd6a1 | ||
|
|
22ba9d81d4 | ||
|
|
309bc98d7f | ||
|
|
9b8646a583 | ||
|
|
48d1b87ab8 | ||
|
|
c5f849d846 | ||
|
|
31fbb6e4f5 | ||
|
|
4d9a88e999 | ||
|
|
252e8484a8 | ||
|
|
1b89203932 | ||
|
|
2263c6a618 | ||
|
|
673cb3ee21 | ||
|
|
b4ecd504e3 | ||
|
|
f226f29428 | ||
|
|
b87a284390 | ||
|
|
f63dcd0d9c | ||
|
|
7f5563d581 | ||
|
|
d8a61a920e | ||
|
|
5a4900da8e | ||
|
|
677c30057a | ||
|
|
26113e091b | ||
|
|
1b5e98f593 | ||
|
|
0aa5201947 | ||
|
|
e3951baa3f | ||
|
|
9f9dbbab9e | ||
|
|
d546bbadbd | ||
|
|
2b7f25054f | ||
|
|
bb3f6bcf7e | ||
|
|
41da7175d1 | ||
|
|
446763b58a | ||
|
|
3e9337a0fc | ||
|
|
028806165b | ||
|
|
e4be42edbb | ||
|
|
230fa1f3bb | ||
|
|
d74653bbad | ||
|
|
38049b0897 | ||
|
|
b4af646929 | ||
|
|
b21ec73a52 | ||
|
|
c595844f0e | ||
|
|
fe8ee7c7b3 | ||
|
|
cd382c6bc0 | ||
|
|
e68296c293 | ||
|
|
cc189feae5 | ||
|
|
18e19027a1 | ||
|
|
2d2e0e4757 | ||
|
|
a9f50d79f9 | ||
|
|
0ccd31bee0 | ||
|
|
3ea82b2bcd | ||
|
|
6dad7b3ced | ||
|
|
f96ebd2b07 | ||
|
|
b8d0e7a3ac | ||
|
|
14cca3d497 | ||
|
|
c343ca0cc3 | ||
|
|
527d371bda | ||
|
|
b87a800a9a | ||
|
|
e406993ed1 | ||
|
|
eeff935fc9 | ||
|
|
0791394f1a | ||
|
|
082a407b06 | ||
|
|
8a89b49df1 | ||
|
|
2314b9cbab | ||
|
|
d0cca85c83 | ||
|
|
6a7a5cbcba | ||
|
|
ecccc82cc8 | ||
|
|
02693489fe | ||
|
|
0f5dba5828 | ||
|
|
e528d4c4b7 | ||
|
|
52a3af6acf | ||
|
|
dcefea9958 | ||
|
|
59121ff834 | ||
|
|
7f5bb6d472 | ||
|
|
639c1a508c | ||
|
|
417a26fc64 | ||
|
|
210ccd0063 | ||
|
|
1bf0162d38 | ||
|
|
e93027fd7e | ||
|
|
807060706f | ||
|
|
a317f88d3c | ||
|
|
e17a7f0701 | ||
|
|
db325eb9fe | ||
|
|
b41a4c8c3b | ||
|
|
73b4d11d18 | ||
|
|
8162b87287 | ||
|
|
70e9e4f3ee | ||
|
|
e61ae376b3 | ||
|
|
2d57b0e926 | ||
|
|
ae683af07a | ||
|
|
3c4f6a9171 | ||
|
|
39986e546c | ||
|
|
2e81a80f7b | ||
|
|
fcb3aa38c8 | ||
|
|
00a38d8ec5 | ||
|
|
07a0ab4227 | ||
|
|
d4a9a2c543 | ||
|
|
2b523fc60d | ||
|
|
0c26928236 | ||
|
|
8401e56a22 | ||
|
|
5109f9ae0b | ||
|
|
c9bc06669a | ||
|
|
a83fb2672c | ||
|
|
8f9ecb44d9 | ||
|
|
bfcc09a8de | ||
|
|
f8a8c997db | ||
|
|
132b996f30 | ||
|
|
12f970cdfb | ||
|
|
9afa963225 | ||
|
|
ed368d0d51 | ||
|
|
21f21d34ba | ||
|
|
f37823c809 | ||
|
|
6eaefcff5e | ||
|
|
79235c1cc3 | ||
|
|
29135f014b | ||
|
|
13c998fb8d | ||
|
|
71bfd0d636 | ||
|
|
51e99e0f5a | ||
|
|
66e7beefc4 | ||
|
|
f2b10c35b7 | ||
|
|
e951eba96c | ||
|
|
9fe18da7a3 | ||
|
|
a14fdead14 | ||
|
|
9a671a4991 | ||
|
|
8f5e7b124a | ||
|
|
5f7464d015 | ||
|
|
238dd6c1d0 | ||
|
|
82e4e54edc | ||
|
|
9946cbb9da | ||
|
|
2474adb23a | ||
|
|
f40757bb67 | ||
|
|
bc29479930 | ||
|
|
4ec78edaa3 | ||
|
|
aa0271158d | ||
|
|
c0aa5bfe17 | ||
|
|
3f8e6a8cc8 | ||
|
|
ef0316fc2e | ||
|
|
7274efab15 | ||
|
|
e44b62b6b2 | ||
|
|
31c041d435 | ||
|
|
35f47371ed | ||
|
|
c5412e1620 | ||
|
|
a9b4c52811 | ||
|
|
5ce40b6ac8 | ||
|
|
b93dcbf46f | ||
|
|
8051a2bc98 | ||
|
|
78d8b221fc | ||
|
|
d51cada284 | ||
|
|
389eef9e88 | ||
|
|
270fb0c50d | ||
|
|
e7e9dfee88 | ||
|
|
3bafae276d | ||
|
|
cfebe2927d | ||
|
|
1d4294a845 | ||
|
|
12cfdd9864 | ||
|
|
add930c517 | ||
|
|
32972978be | ||
|
|
c8bad3550e | ||
|
|
ecc55d789d | ||
|
|
88555e2c20 | ||
|
|
ec2bfcd302 | ||
|
|
f1f81ed4c4 | ||
|
|
87933cca26 | ||
|
|
2dcd8624a2 | ||
|
|
7fcef76bbe | ||
|
|
2a5c4e938d | ||
|
|
274eae27ef | ||
|
|
207220bc50 | ||
|
|
fb8c4439c7 | ||
|
|
894be9c41e | ||
|
|
0a4bff8963 | ||
|
|
d515f3e279 |
@@ -1,5 +1,9 @@
|
||||
*.o
|
||||
*.py[co]
|
||||
*.class
|
||||
*.jar
|
||||
|
||||
/uwsgi
|
||||
/uwsgibuild.*
|
||||
|
||||
/t/ring/target
|
||||
|
||||
@@ -217,6 +217,45 @@ static int uwsgi_send_body(request_rec *r, proxy_conn_rec *conn)
|
||||
return OK;
|
||||
}
|
||||
|
||||
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
|
||||
static request_rec *ap_proxy_make_fake_req(conn_rec *c, request_rec *r)
|
||||
{
|
||||
apr_pool_t *pool;
|
||||
request_rec *rp;
|
||||
|
||||
apr_pool_create(&pool, c->pool);
|
||||
|
||||
rp = apr_pcalloc(pool, sizeof(*r));
|
||||
|
||||
rp->pool = pool;
|
||||
rp->status = HTTP_OK;
|
||||
|
||||
rp->headers_in = apr_table_make(pool, 50);
|
||||
rp->subprocess_env = apr_table_make(pool, 50);
|
||||
rp->headers_out = apr_table_make(pool, 12);
|
||||
rp->err_headers_out = apr_table_make(pool, 5);
|
||||
rp->notes = apr_table_make(pool, 5);
|
||||
|
||||
rp->server = r->server;
|
||||
rp->log = r->log;
|
||||
rp->proxyreq = r->proxyreq;
|
||||
rp->request_time = r->request_time;
|
||||
rp->connection = c;
|
||||
rp->output_filters = c->output_filters;
|
||||
rp->input_filters = c->input_filters;
|
||||
rp->proto_output_filters = c->output_filters;
|
||||
rp->proto_input_filters = c->input_filters;
|
||||
rp->useragent_ip = c->client_ip;
|
||||
rp->useragent_addr = c->client_addr;
|
||||
|
||||
rp->request_config = ap_create_request_config(pool);
|
||||
proxy_run_create_req(r, rp);
|
||||
|
||||
return rp;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_conf *conf)
|
||||
{
|
||||
|
||||
@@ -337,7 +376,11 @@ static int uwsgi_handler(request_rec *r, proxy_worker *worker,
|
||||
}
|
||||
|
||||
// ADD PATH_INFO
|
||||
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
|
||||
size_t w_len = strlen(worker->s->name);
|
||||
#else
|
||||
size_t w_len = strlen(worker->name);
|
||||
#endif
|
||||
char *u_path_info = r->filename + 6 + w_len;
|
||||
int delta = 0;
|
||||
if (u_path_info[0] != '/') {
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
object file for embedded files will be put here
|
||||
@@ -1,18 +1,11 @@
|
||||
[uwsgi]
|
||||
xml = auto
|
||||
ini = true
|
||||
yaml = true
|
||||
json = auto
|
||||
sqlite3 = auto
|
||||
zeromq = auto
|
||||
snmp = true
|
||||
ssl = auto
|
||||
async = true
|
||||
ldap = auto
|
||||
pcre = auto
|
||||
routing = auto
|
||||
alarm = auto
|
||||
ipv6 = false
|
||||
debug = false
|
||||
unbit = false
|
||||
xml_implementation = libxml2
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = gridfs
|
||||
inherit = base
|
||||
@@ -0,0 +1,32 @@
|
||||
[uwsgi]
|
||||
xml = true
|
||||
yaml = true
|
||||
json = true
|
||||
zeromq = true
|
||||
ssl = true
|
||||
pcre = true
|
||||
routing = true
|
||||
debug = false
|
||||
unbit = false
|
||||
xml_implementation = libxml2
|
||||
yaml_implementation = libyaml
|
||||
malloc_implementation = libc
|
||||
extras =
|
||||
plugins =
|
||||
bin_name = /usr/lib/libuwsgi.so
|
||||
append_version = ubuntu
|
||||
plugin_dir = /usr/lib/uwsgi
|
||||
embedded_plugins =
|
||||
as_shared_library = true
|
||||
|
||||
locking = auto
|
||||
event = auto
|
||||
timer = auto
|
||||
filemonitor = auto
|
||||
|
||||
blacklist =
|
||||
whitelist =
|
||||
|
||||
embed_files =
|
||||
|
||||
embed_config =
|
||||
@@ -0,0 +1,6 @@
|
||||
[uwsgi]
|
||||
main_plugin = python,gevent
|
||||
inherit = base
|
||||
plugins = jvm,ring
|
||||
plugin_dir = .
|
||||
|
||||
+12
-6
@@ -1,26 +1,32 @@
|
||||
[uwsgi]
|
||||
xml = true
|
||||
ini = true
|
||||
yaml = true
|
||||
json = false
|
||||
sqlite3 = false
|
||||
zeromq = false
|
||||
ldap = true
|
||||
ssl = true
|
||||
pcre = true
|
||||
routing = true
|
||||
alarm = true
|
||||
debug = false
|
||||
unbit = true
|
||||
xml_implementation = expat
|
||||
yaml_implementation = auto
|
||||
malloc_implementation = libc
|
||||
extras =
|
||||
plugins =
|
||||
bin_name = /opt/unbit/bin/uwsgi
|
||||
bin_name = /opt/unbit/uwsgi19/lib/libuwsgi.so
|
||||
append_version = unbit
|
||||
plugin_dir = /opt/unbit/uwsgi_plugins
|
||||
plugin_dir = /opt/unbit/uwsgi19/plugins
|
||||
embedded_plugins =
|
||||
as_shared_library = true
|
||||
|
||||
locking = auto
|
||||
event = auto
|
||||
timer = auto
|
||||
filemonitor = auto
|
||||
|
||||
blacklist =
|
||||
whitelist =
|
||||
|
||||
embed_files =
|
||||
|
||||
embed_config =
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
[uwsgi]
|
||||
inherit = unbit
|
||||
json = false
|
||||
embedded_plugins = python
|
||||
bin_name = ../bin/uwsgi
|
||||
plugin_dir = ../bin/uwsgi_plugins
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
require 'socket'
|
||||
require 'openssl'
|
||||
|
||||
secret = 'ciaociao'
|
||||
iv = ''
|
||||
address = '127.0.0.1'
|
||||
port = 1717
|
||||
algo = 'bf-cbc'
|
||||
|
||||
s = UDPSocket.new
|
||||
s.bind(address, port)
|
||||
cipher = OpenSSL::Cipher.new(algo)
|
||||
cipher.decrypt
|
||||
cipher.key = secret + ("\0" * (cipher.key_len - secret.length))
|
||||
cipher.iv = iv + ("0" * (cipher.iv_len - iv.length))
|
||||
|
||||
loop do
|
||||
msg, sender = s.recvfrom(8192)
|
||||
cipher.reset
|
||||
begin
|
||||
puts cipher.update(msg) + cipher.final
|
||||
rescue
|
||||
end
|
||||
end
|
||||
@@ -328,3 +328,29 @@ int uwsgi_buffer_set_uh(struct uwsgi_buffer *ub, uint8_t modifier1, uint8_t modi
|
||||
ub->buf[3] = modifier2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *uwsgi_buffer_from_file(char *filename) {
|
||||
struct stat st;
|
||||
int fd = open(filename, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fstat(fd, &st)) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(st.st_size);
|
||||
|
||||
ssize_t len = read(fd, ub->buf, st.st_size);
|
||||
close(fd);
|
||||
if (len != st.st_size) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ub->pos = len;
|
||||
return ub;
|
||||
}
|
||||
|
||||
|
||||
+90
-78
@@ -288,21 +288,7 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
|
||||
(unsigned long long) ((sizeof(struct uwsgi_cache_item)+uc->keysize) * uc->max_items), (unsigned long long) (uc->blocksize * uc->max_items),
|
||||
(unsigned long long) uc->blocks_bitmap_size);
|
||||
|
||||
|
||||
struct uwsgi_string_list *usl = uc->nodes;
|
||||
while(usl) {
|
||||
char *port = strchr(usl->value, ':');
|
||||
if (!port) {
|
||||
uwsgi_log("[cache-udp-node] invalid udp address: %s\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
// no need to zero the memory, socket_to_in_addr will do that
|
||||
struct sockaddr_in *sin = uwsgi_malloc(sizeof(struct sockaddr_in));
|
||||
usl->custom = socket_to_in_addr(usl->value, port, 0, sin);
|
||||
usl->custom_ptr = sin;
|
||||
uwsgi_log("added udp node %s for cache \"%s\"\n", usl->value, uc->name);
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_cache_setup_nodes(uc);
|
||||
|
||||
uc->udp_node_socket = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (uc->udp_node_socket < 0) {
|
||||
@@ -311,70 +297,10 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
|
||||
}
|
||||
uwsgi_socket_nb(uc->udp_node_socket);
|
||||
|
||||
usl = uc->sync_nodes;
|
||||
while(usl) {
|
||||
uwsgi_log("[cache-sync] getting cache dump from %s ...\n", usl->value);
|
||||
int fd = uwsgi_connect(usl->value, 0, 0);
|
||||
if (fd < 0) {
|
||||
uwsgi_log("[cache-sync] unable to connect to the cache server\n");
|
||||
goto next;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size + uc->filesize);
|
||||
ub->pos = 4;
|
||||
if (uwsgi_buffer_append(ub, uc->name, uc->name_len)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (uwsgi_buffer_set_uh(ub, 111, 6)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (uwsgi_write_nb(fd, ub->buf, ub->pos, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_log("[cache-sync] unable to write to the cache server\n");
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
size_t rlen = ub->pos;
|
||||
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_log("[cache-sync] unable to read from the cache server\n");
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
uwsgi_hooked_parse(ub->buf, ub->pos, cache_sync_hook, uc);
|
||||
|
||||
if (uwsgi_read_nb(fd, (char *) uc->items, uc->filesize, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
uwsgi_log("[cache-sync] unable to read from the cache server\n");
|
||||
goto next;
|
||||
}
|
||||
|
||||
// reset the hashtable
|
||||
memset(uc->hashtable, 0, sizeof(uint64_t) * UMAX16);
|
||||
// re-fill the hashtable
|
||||
uwsgi_cache_fix(uc);
|
||||
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
break;
|
||||
next:
|
||||
if (!usl->next) {
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("[cache-sync] trying with the next sync node...\n");
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_cache_sync_from_nodes(uc);
|
||||
|
||||
uwsgi_cache_load_files(uc);
|
||||
|
||||
}
|
||||
|
||||
static uint64_t uwsgi_cache_get_index(struct uwsgi_cache *uc, char *key, uint16_t keylen) {
|
||||
@@ -533,7 +459,8 @@ void uwsgi_cache_fix(struct uwsgi_cache *uc) {
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("[uwsgi-cache] restored %llu items\n", restored);
|
||||
uc->n_items = restored;
|
||||
uwsgi_log("[uwsgi-cache] restored %llu items\n", uc->n_items);
|
||||
}
|
||||
|
||||
int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *val, uint64_t vallen, uint64_t expires, uint64_t flags) {
|
||||
@@ -1695,3 +1622,88 @@ int uwsgi_cache_magic_clear(char *cache) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_cache_sync_from_nodes(struct uwsgi_cache *uc) {
|
||||
struct uwsgi_string_list *usl = uc->sync_nodes;
|
||||
usl = uc->sync_nodes;
|
||||
while(usl) {
|
||||
uwsgi_log("[cache-sync] getting cache dump from %s ...\n", usl->value);
|
||||
int fd = uwsgi_connect(usl->value, 0, 0);
|
||||
if (fd < 0) {
|
||||
uwsgi_log("[cache-sync] unable to connect to the cache server\n");
|
||||
goto next;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size + uc->filesize);
|
||||
ub->pos = 4;
|
||||
if (uwsgi_buffer_append(ub, uc->name, uc->name_len)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (uwsgi_buffer_set_uh(ub, 111, 6)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (uwsgi_write_nb(fd, ub->buf, ub->pos, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_log("[cache-sync] unable to write to the cache server\n");
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
size_t rlen = ub->pos;
|
||||
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_log("[cache-sync] unable to read from the cache server\n");
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
uwsgi_hooked_parse(ub->buf, ub->pos, cache_sync_hook, uc);
|
||||
|
||||
if (uwsgi_read_nb(fd, (char *) uc->items, uc->filesize, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
uwsgi_log("[cache-sync] unable to read from the cache server\n");
|
||||
goto next;
|
||||
}
|
||||
|
||||
// reset the hashtable
|
||||
memset(uc->hashtable, 0, sizeof(uint64_t) * UMAX16);
|
||||
// re-fill the hashtable
|
||||
uwsgi_cache_fix(uc);
|
||||
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
break;
|
||||
next:
|
||||
if (!usl->next) {
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("[cache-sync] trying with the next sync node...\n");
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_cache_setup_nodes(struct uwsgi_cache *uc) {
|
||||
struct uwsgi_string_list *usl = uc->nodes;
|
||||
while(usl) {
|
||||
char *port = strchr(usl->value, ':');
|
||||
if (!port) {
|
||||
uwsgi_log("[cache-udp-node] invalid udp address: %s\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
// no need to zero the memory, socket_to_in_addr will do that
|
||||
struct sockaddr_in *sin = uwsgi_malloc(sizeof(struct sockaddr_in));
|
||||
usl->custom = socket_to_in_addr(usl->value, port, 0, sin);
|
||||
usl->custom_ptr = sin;
|
||||
uwsgi_log("added udp node %s for cache \"%s\"\n", usl->value, uc->name);
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
pluggable configuration system
|
||||
|
||||
*/
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_configurator *uwsgi_register_configurator(char *name, void (*func)(char *, char **)) {
|
||||
struct uwsgi_configurator *old_uc = NULL,*uc = uwsgi.configurators;
|
||||
while(uc) {
|
||||
if (!strcmp(uc->name, name)) {
|
||||
return uc;
|
||||
}
|
||||
old_uc = uc;
|
||||
uc = uc->next;
|
||||
}
|
||||
|
||||
uc = uwsgi_calloc(sizeof(struct uwsgi_configurator));
|
||||
uc->name = name;
|
||||
uc->func = func;
|
||||
|
||||
if (old_uc) {
|
||||
old_uc->next = uc;
|
||||
}
|
||||
else {
|
||||
uwsgi.configurators = uc;
|
||||
}
|
||||
|
||||
return uc;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
cookie management functions (mainly used by the internal routing subsystem)
|
||||
|
||||
*/
|
||||
|
||||
static char *check_cookie(char *cookie, uint16_t cookie_len, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
uint16_t orig_cookie_len = cookie_len-1;
|
||||
// first lstrip white spaces
|
||||
char *ptr = cookie;
|
||||
uint16_t i;
|
||||
for(i=0;i<cookie_len;i++) {
|
||||
if (isspace((int)ptr[i])) {
|
||||
cookie++;
|
||||
cookie_len--;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// then rstrip (skipping the first char...)
|
||||
for(i=orig_cookie_len;i>0;i--) {
|
||||
if (isspace((int)ptr[i])) {
|
||||
cookie_len--;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// now search for the first equal sign
|
||||
char *equal = memchr(cookie, '=', cookie_len);
|
||||
if (!equal) return NULL;
|
||||
|
||||
if (uwsgi_strncmp(key, keylen, cookie, equal-cookie)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cookie_len -= (equal-cookie)+1;
|
||||
if (cookie_len == 0) return NULL;
|
||||
|
||||
*vallen = cookie_len;
|
||||
return equal+1;
|
||||
}
|
||||
|
||||
char *uwsgi_get_cookie(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
uint16_t i;
|
||||
|
||||
char *cookie = wsgi_req->cookie;
|
||||
uint16_t cookie_len = 0;
|
||||
char *ptr = wsgi_req->cookie;
|
||||
//start splitting by ;
|
||||
for(i=0;i<wsgi_req->cookie_len;i++) {
|
||||
if (!cookie) {
|
||||
cookie = ptr + i;
|
||||
}
|
||||
if (ptr[i] == ';') {
|
||||
char *value = check_cookie(cookie, cookie_len, key, keylen, vallen);
|
||||
if (value) {
|
||||
return value;
|
||||
}
|
||||
cookie_len = 0;
|
||||
cookie = NULL;
|
||||
}
|
||||
else {
|
||||
cookie_len++;
|
||||
}
|
||||
}
|
||||
|
||||
if (cookie_len > 0) {
|
||||
char *value = check_cookie(cookie, cookie_len, key, keylen, vallen);
|
||||
if (value) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
+12
-10
@@ -208,18 +208,20 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
uwsgi_write_pidfile(ud->pidfile);
|
||||
}
|
||||
|
||||
// /dev/null will became stdin
|
||||
devnull = open("/dev/null", O_RDONLY);
|
||||
if (devnull < 0) {
|
||||
uwsgi_error("/dev/null open()");
|
||||
exit(1);
|
||||
}
|
||||
if (devnull != 0) {
|
||||
if (dup2(devnull, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
if (!uwsgi.daemons_honour_stdin) {
|
||||
// /dev/null will became stdin
|
||||
devnull = open("/dev/null", O_RDONLY);
|
||||
if (devnull < 0) {
|
||||
uwsgi_error("/dev/null open()");
|
||||
exit(1);
|
||||
}
|
||||
close(devnull);
|
||||
if (devnull != 0) {
|
||||
if (dup2(devnull, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(devnull);
|
||||
}
|
||||
}
|
||||
|
||||
if (setsid() < 0) {
|
||||
|
||||
+280
-58
@@ -122,19 +122,101 @@ void uwsgi_emperor_blacklist_remove(char *id) {
|
||||
|
||||
struct uwsgi_emperor_scanner *emperor_scanners;
|
||||
|
||||
static int has_extra_extension(char *name) {
|
||||
struct uwsgi_string_list *usl = uwsgi.emperor_extra_extension;
|
||||
while(usl) {
|
||||
if (uwsgi_endswith(name, usl->value)) {
|
||||
return 1;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_emperor_is_valid(char *name) {
|
||||
|
||||
if (uwsgi_endswith(name, ".xml") || uwsgi_endswith(name, ".ini") || uwsgi_endswith(name, ".yml") || uwsgi_endswith(name, ".yaml") || uwsgi_endswith(name, ".js") || uwsgi_endswith(name, ".json")) {
|
||||
|
||||
if (uwsgi_endswith(name, ".xml") || uwsgi_endswith(name, ".ini") || uwsgi_endswith(name, ".yml") || uwsgi_endswith(name, ".yaml") || uwsgi_endswith(name, ".js") || uwsgi_endswith(name, ".json") || has_extra_extension(name)) {
|
||||
|
||||
if (strlen(name) < 0xff) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *emperor_check_on_demand_socket(char *filename) {
|
||||
size_t len = 0;
|
||||
if (uwsgi.emperor_on_demand_extension) {
|
||||
char *tmp = uwsgi_concat2(filename, uwsgi.emperor_on_demand_extension);
|
||||
int fd = open(tmp, O_RDONLY);
|
||||
free(tmp);
|
||||
if (fd < 0) return NULL;
|
||||
char *ret = uwsgi_read_fd(fd, &len, 1);
|
||||
close(fd);
|
||||
// change the first non prinabel character to 0
|
||||
size_t i;
|
||||
for(i=0;i<len;i++) {
|
||||
if (ret[i] < 32) {
|
||||
ret[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret[0] == 0) {
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
else if (uwsgi.emperor_on_demand_directory) {
|
||||
// we need to build the socket path automagically
|
||||
char *start_of_vassal_name = uwsgi_get_last_char(filename, '/');
|
||||
if (!start_of_vassal_name) {
|
||||
start_of_vassal_name = filename;
|
||||
}
|
||||
else {
|
||||
start_of_vassal_name++;
|
||||
}
|
||||
char *last_dot = uwsgi_get_last_char(filename, '.');
|
||||
if (!last_dot) return NULL;
|
||||
|
||||
return uwsgi_concat4n(uwsgi.emperor_on_demand_directory, strlen(uwsgi.emperor_on_demand_directory), "/", 1, start_of_vassal_name, last_dot - start_of_vassal_name, ".socket", 7);
|
||||
}
|
||||
else if (uwsgi.emperor_on_demand_exec) {
|
||||
int cpipe[2];
|
||||
if (pipe(cpipe)) {
|
||||
uwsgi_error("emperor_check_on_demand_socket()pipe()");
|
||||
return NULL;
|
||||
}
|
||||
char *cmd = uwsgi_concat4(uwsgi.emperor_on_demand_exec, " \"", filename, "\"");
|
||||
int r = uwsgi_run_command(cmd, NULL, cpipe[1]);
|
||||
free(cmd);
|
||||
if (r < 0) {
|
||||
close(cpipe[0]);
|
||||
close(cpipe[1]);
|
||||
return NULL;
|
||||
}
|
||||
char *ret = uwsgi_read_fd(cpipe[0], &len, 1);
|
||||
close(cpipe[0]);
|
||||
close(cpipe[1]);
|
||||
// change the first non prinabel character to 0
|
||||
size_t i;
|
||||
for(i=0;i<len;i++) {
|
||||
if (ret[i] < 32) {
|
||||
ret[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret[0] == 0) {
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// this is the monitor for non-glob directories
|
||||
void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
|
||||
struct uwsgi_instance *ui_current;
|
||||
@@ -160,10 +242,27 @@ void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
|
||||
|
||||
ui_current = emperor_get(de->d_name);
|
||||
|
||||
uid_t t_uid = st.st_uid;
|
||||
gid_t t_gid = st.st_gid;
|
||||
|
||||
if (uwsgi.emperor_tyrant && uwsgi.emperor_tyrant_nofollow) {
|
||||
struct stat lst;
|
||||
if (lstat(de->d_name, &lst)) {
|
||||
uwsgi_error("[emperor-tyrant]/lstat()");
|
||||
if (ui_current) {
|
||||
uwsgi_log("!!! availability of file %s changed. stopping the instance... !!!\n", de->d_name);
|
||||
emperor_stop(ui_current);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
t_uid = lst.st_uid;
|
||||
t_gid = lst.st_gid;
|
||||
}
|
||||
|
||||
if (ui_current) {
|
||||
// check if uid or gid are changed, in such case, stop the instance
|
||||
if (uwsgi.emperor_tyrant) {
|
||||
if (st.st_uid != ui_current->uid || st.st_gid != ui_current->gid) {
|
||||
if (t_uid != ui_current->uid || t_gid != ui_current->gid) {
|
||||
uwsgi_log("!!! permissions of file %s changed. stopping the instance... !!!\n", de->d_name);
|
||||
emperor_stop(ui_current);
|
||||
continue;
|
||||
@@ -175,7 +274,9 @@ void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
emperor_add(ues, de->d_name, st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
|
||||
char *socket_name = emperor_check_on_demand_socket(de->d_name);
|
||||
emperor_add(ues, de->d_name, st.st_mtime, NULL, 0, t_uid, t_gid, socket_name);
|
||||
if (socket_name) free(socket_name);
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
@@ -235,10 +336,27 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
|
||||
|
||||
ui_current = emperor_get(g.gl_pathv[i]);
|
||||
|
||||
uid_t t_uid = st.st_uid;
|
||||
gid_t t_gid = st.st_gid;
|
||||
|
||||
if (uwsgi.emperor_tyrant && uwsgi.emperor_tyrant_nofollow) {
|
||||
struct stat lst;
|
||||
if (lstat(g.gl_pathv[i], &lst)) {
|
||||
uwsgi_error("[emperor-tyrant]/lstat()");
|
||||
if (ui_current) {
|
||||
uwsgi_log("!!! availability of file %s changed. stopping the instance... !!!\n", g.gl_pathv[i]);
|
||||
emperor_stop(ui_current);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
t_uid = lst.st_uid;
|
||||
t_gid = lst.st_gid;
|
||||
}
|
||||
|
||||
if (ui_current) {
|
||||
// check if uid or gid are changed, in such case, stop the instance
|
||||
if (uwsgi.emperor_tyrant) {
|
||||
if (st.st_uid != ui_current->uid || st.st_gid != ui_current->gid) {
|
||||
if (t_uid != ui_current->uid || t_gid != ui_current->gid) {
|
||||
uwsgi_log("!!! permissions of file %s changed. stopping the instance... !!!\n", g.gl_pathv[i]);
|
||||
emperor_stop(ui_current);
|
||||
continue;
|
||||
@@ -250,7 +368,9 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
emperor_add(ues, g.gl_pathv[i], st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
|
||||
char *socket_name = emperor_check_on_demand_socket(g.gl_pathv[i]);
|
||||
emperor_add(ues, g.gl_pathv[i], st.st_mtime, NULL, 0, t_uid, t_gid, socket_name);
|
||||
if (socket_name) free(socket_name);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -377,6 +497,22 @@ struct uwsgi_instance *emperor_get_by_fd(int fd) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_instance *emperor_get_by_socket_fd(int fd) {
|
||||
|
||||
struct uwsgi_instance *c_ui = ui;
|
||||
|
||||
while (c_ui->ui_next) {
|
||||
c_ui = c_ui->ui_next;
|
||||
|
||||
// over engineering...
|
||||
if (c_ui->on_demand_fd != -1 && c_ui->on_demand_fd == fd) {
|
||||
return c_ui;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct uwsgi_instance *emperor_get(char *name) {
|
||||
|
||||
@@ -430,6 +566,10 @@ void emperor_del(struct uwsgi_instance *c_ui) {
|
||||
uwsgi.emperor_broodlord_count--;
|
||||
}
|
||||
|
||||
if (c_ui->socket_name) {
|
||||
free(c_ui->socket_name);
|
||||
}
|
||||
|
||||
free(c_ui);
|
||||
|
||||
}
|
||||
@@ -478,17 +618,10 @@ void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
|
||||
uwsgi_log("[emperor] reload the uwsgi instance %s\n", c_ui->name);
|
||||
}
|
||||
|
||||
void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, char *config, uint32_t config_size, uid_t uid, gid_t gid) {
|
||||
void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, char *config, uint32_t config_size, uid_t uid, gid_t gid, char *socket_name) {
|
||||
|
||||
struct uwsgi_instance *c_ui = ui;
|
||||
struct uwsgi_instance *n_ui = NULL;
|
||||
pid_t pid;
|
||||
char **vassal_argv;
|
||||
char *uef;
|
||||
char **uenvs;
|
||||
int counter;
|
||||
char *colon = NULL;
|
||||
int i;
|
||||
struct timeval tv;
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
@@ -544,8 +677,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
c_ui = c_ui->ui_next;
|
||||
}
|
||||
|
||||
n_ui = uwsgi_malloc(sizeof(struct uwsgi_instance));
|
||||
memset(n_ui, 0, sizeof(struct uwsgi_instance));
|
||||
n_ui = uwsgi_calloc(sizeof(struct uwsgi_instance));
|
||||
|
||||
if (config) {
|
||||
n_ui->use_config = 1;
|
||||
@@ -576,10 +708,60 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
|
||||
n_ui->first_run = uwsgi_now();
|
||||
n_ui->last_run = n_ui->first_run;
|
||||
n_ui->on_demand_fd = -1;
|
||||
if (socket_name) {
|
||||
n_ui->socket_name = uwsgi_str(socket_name);
|
||||
}
|
||||
|
||||
n_ui->pid = -1;
|
||||
|
||||
// ok here we check if we need to bind to the specified socket or continue with the activation
|
||||
if (socket_name) {
|
||||
char *tcp_port = strchr(socket_name, ':');
|
||||
if (tcp_port) {
|
||||
// disable deferred accept for this socket
|
||||
int current_defer_accept = uwsgi.no_defer_accept;
|
||||
uwsgi.no_defer_accept = 1;
|
||||
n_ui->on_demand_fd = bind_to_tcp(socket_name, uwsgi.listen_queue, tcp_port);
|
||||
uwsgi.no_defer_accept = current_defer_accept;
|
||||
}
|
||||
else {
|
||||
n_ui->on_demand_fd = bind_to_unix(socket_name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
|
||||
}
|
||||
|
||||
if (n_ui->on_demand_fd < 0) {
|
||||
uwsgi_error("emperor_add()/bind()");
|
||||
free(n_ui);
|
||||
c_ui->ui_next = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
event_queue_add_fd_read(uwsgi.emperor_queue, n_ui->on_demand_fd);
|
||||
uwsgi_log("[uwsgi-emperor] %s -> \"on demand\" instance detected, waiting for connections on socket \"%s\" ...\n", name, socket_name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (uwsgi_emperor_vassal_start(n_ui)) {
|
||||
// clear the vassal
|
||||
free(n_ui);
|
||||
c_ui->ui_next = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
|
||||
int i;
|
||||
char *colon = NULL;
|
||||
int counter;
|
||||
char **uenvs;
|
||||
char *uef;
|
||||
char **vassal_argv;
|
||||
pid_t pid;
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe)) {
|
||||
uwsgi_error("socketpair()");
|
||||
goto clear;
|
||||
return -1;
|
||||
}
|
||||
|
||||
event_queue_add_fd_read(uwsgi.emperor_queue, n_ui->pipe[0]);
|
||||
@@ -587,7 +769,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
if (n_ui->use_config) {
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe_config)) {
|
||||
uwsgi_error("socketpair()");
|
||||
goto clear;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -606,6 +788,11 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
n_ui->pid = pid;
|
||||
// close the right side of the pipe
|
||||
close(n_ui->pipe[1]);
|
||||
// close the "on demand" socket
|
||||
if (n_ui->on_demand_fd > -1) {
|
||||
close(n_ui->on_demand_fd);
|
||||
n_ui->on_demand_fd = -1;
|
||||
}
|
||||
if (n_ui->use_config) {
|
||||
close(n_ui->pipe_config[1]);
|
||||
}
|
||||
@@ -625,13 +812,13 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
}
|
||||
|
||||
}
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
|
||||
if (uwsgi.emperor_tyrant) {
|
||||
uwsgi_log("[emperor-tyrant] dropping privileges to %d %d for instance %s\n", (int) uid, (int) gid, name);
|
||||
if (setgid(gid)) {
|
||||
uwsgi_log("[emperor-tyrant] dropping privileges to %d %d for instance %s\n", (int) n_ui->uid, (int) n_ui->gid, n_ui->name);
|
||||
if (setgid(n_ui->gid)) {
|
||||
uwsgi_error("setgid()");
|
||||
exit(1);
|
||||
}
|
||||
@@ -640,7 +827,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (setuid(uid)) {
|
||||
if (setuid(n_ui->uid)) {
|
||||
uwsgi_error("setuid()");
|
||||
exit(1);
|
||||
}
|
||||
@@ -678,15 +865,16 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
|
||||
uenvs = environ;
|
||||
while (*uenvs) {
|
||||
if (!strncmp(*uenvs, "UWSGI_VASSAL_", 13)) {
|
||||
char *ne = uwsgi_concat2("UWSGI_", *uenvs + 13);
|
||||
char *oe = uwsgi_concat2n(*uenvs, strchr(*uenvs, '=') - *uenvs, "", 0);
|
||||
if (!strncmp(*uenvs, "UWSGI_VASSAL_", 13) && strchr(*uenvs, '=')) {
|
||||
char *oe = uwsgi_concat2n(*uenvs, strchr(*uenvs, '=') - *uenvs, "", 0), *ne;
|
||||
if (unsetenv(oe)) {
|
||||
uwsgi_error("unsetenv()");
|
||||
free(oe);
|
||||
break;
|
||||
}
|
||||
free(oe);
|
||||
|
||||
ne = uwsgi_concat2("UWSGI_", *uenvs + 13);
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("putenv %s\n", ne);
|
||||
#endif
|
||||
@@ -720,7 +908,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
vassal_argv[0] = uwsgi.binary_path;
|
||||
|
||||
if (uwsgi.emperor_broodlord) {
|
||||
colon = strchr(name, ':');
|
||||
colon = strchr(n_ui->name, ':');
|
||||
if (colon) {
|
||||
colon[0] = 0;
|
||||
}
|
||||
@@ -728,34 +916,43 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
// initialize to a default value
|
||||
vassal_argv[1] = "--inherit";
|
||||
|
||||
if (!strcmp(name + (strlen(name) - 4), ".xml"))
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".xml"))
|
||||
vassal_argv[1] = "--xml";
|
||||
if (!strcmp(name + (strlen(name) - 4), ".ini"))
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".ini"))
|
||||
vassal_argv[1] = "--ini";
|
||||
if (!strcmp(name + (strlen(name) - 4), ".yml"))
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".yml"))
|
||||
vassal_argv[1] = "--yaml";
|
||||
if (!strcmp(name + (strlen(name) - 5), ".yaml"))
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".yaml"))
|
||||
vassal_argv[1] = "--yaml";
|
||||
if (!strcmp(name + (strlen(name) - 3), ".js"))
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 3), ".js"))
|
||||
vassal_argv[1] = "--json";
|
||||
if (!strcmp(name + (strlen(name) - 5), ".json"))
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".json"))
|
||||
vassal_argv[1] = "--json";
|
||||
|
||||
struct uwsgi_string_list *usl = uwsgi.emperor_extra_extension;
|
||||
while(usl) {
|
||||
if (uwsgi_endswith(n_ui->name, usl->value)) {
|
||||
vassal_argv[1] = "--config";
|
||||
break;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
if (colon) {
|
||||
colon[0] = ':';
|
||||
}
|
||||
|
||||
|
||||
vassal_argv[2] = name;
|
||||
vassal_argv[2] = n_ui->name;
|
||||
if (uwsgi.emperor_magic_exec) {
|
||||
if (!access(name, R_OK | X_OK)) {
|
||||
vassal_argv[2] = uwsgi_concat2("exec://", name);
|
||||
if (!access(n_ui->name, R_OK | X_OK)) {
|
||||
vassal_argv[2] = uwsgi_concat2("exec://", n_ui->name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (n_ui->use_config) {
|
||||
vassal_argv[2] = uwsgi_concat2("emperor://", name);
|
||||
vassal_argv[2] = uwsgi_concat2("emperor://", n_ui->name);
|
||||
}
|
||||
|
||||
counter = 3;
|
||||
@@ -768,18 +965,29 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
}
|
||||
vassal_argv[counter] = NULL;
|
||||
|
||||
// disable stdin
|
||||
int stdin_fd = open("/dev/null", O_RDONLY);
|
||||
if (stdin_fd < 0) {
|
||||
uwsgi_error_open("/dev/null");
|
||||
exit(1);
|
||||
// disable stdin OR map it to the "on demand" socket
|
||||
if (n_ui->on_demand_fd > -1) {
|
||||
if (n_ui->on_demand_fd != 0) {
|
||||
if (dup2(n_ui->on_demand_fd, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(n_ui->on_demand_fd);
|
||||
}
|
||||
}
|
||||
if (stdin_fd != 0) {
|
||||
if (dup2(stdin_fd, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
else {
|
||||
int stdin_fd = open("/dev/null", O_RDONLY);
|
||||
if (stdin_fd < 0) {
|
||||
uwsgi_error_open("/dev/null");
|
||||
exit(1);
|
||||
}
|
||||
close(stdin_fd);
|
||||
if (stdin_fd != 0) {
|
||||
if (dup2(stdin_fd, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(stdin_fd);
|
||||
}
|
||||
}
|
||||
|
||||
// close all of the unneded fd
|
||||
@@ -813,11 +1021,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
exit(UWSGI_EXILE_CODE);
|
||||
}
|
||||
|
||||
clear:
|
||||
|
||||
free(n_ui);
|
||||
c_ui->ui_next = NULL;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void uwsgi_imperial_monitor_glob_init(struct uwsgi_emperor_scanner *ues) {
|
||||
@@ -975,6 +1179,8 @@ void emperor_loop() {
|
||||
char notification_message[64];
|
||||
struct rlimit rl;
|
||||
|
||||
uwsgi.disable_nuclear_blast = 1;
|
||||
|
||||
uwsgi.emperor_stats_fd = -1;
|
||||
|
||||
if (uwsgi.emperor_pidfile) {
|
||||
@@ -1087,14 +1293,24 @@ void emperor_loop() {
|
||||
else if (byte == 30 && uwsgi.emperor_broodlord > 0 && uwsgi.emperor_broodlord_count < uwsgi.emperor_broodlord) {
|
||||
uwsgi_log("[emperor] going in broodlord mode: launching zergs for %s\n", ui_current->name);
|
||||
char *zerg_name = uwsgi_concat3(ui_current->name, ":", "zerg");
|
||||
emperor_add(ui_current->scanner, zerg_name, uwsgi_now(), NULL, 0, ui_current->uid, ui_current->gid);
|
||||
// here we discard socket name as broodlord/zerg cannot be on demand
|
||||
emperor_add(ui_current->scanner, zerg_name, uwsgi_now(), NULL, 0, ui_current->uid, ui_current->gid, NULL);
|
||||
free(zerg_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[emperor] unrecognized vassal event on fd %d\n", interesting_fd);
|
||||
close(interesting_fd);
|
||||
ui_current = emperor_get_by_socket_fd(interesting_fd);
|
||||
if (ui_current) {
|
||||
event_queue_del_fd(uwsgi.emperor_queue, ui_current->on_demand_fd, event_queue_read());
|
||||
if (uwsgi_emperor_vassal_start(ui_current)) {
|
||||
emperor_del(ui_current);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[emperor] unrecognized vassal event on fd %d\n", interesting_fd);
|
||||
close(interesting_fd);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1120,7 +1336,9 @@ void emperor_loop() {
|
||||
has_children = 0;
|
||||
while (ui_current->ui_next) {
|
||||
ui_current = ui_current->ui_next;
|
||||
has_children++;
|
||||
if (ui_current->pid > -1) {
|
||||
has_children++;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.notify) {
|
||||
@@ -1172,7 +1390,7 @@ void emperor_loop() {
|
||||
}
|
||||
else {
|
||||
// UNSAFE
|
||||
emperor_add(ui_current->scanner, ui_current->name, ui_current->last_mod, ui_current->config, ui_current->config_len, ui_current->uid, ui_current->gid);
|
||||
emperor_add(ui_current->scanner, ui_current->name, ui_current->last_mod, ui_current->config, ui_current->config_len, ui_current->uid, ui_current->gid, ui_current->socket_name);
|
||||
emperor_del(ui_current);
|
||||
}
|
||||
break;
|
||||
@@ -1266,7 +1484,7 @@ void emperor_send_stats(int fd) {
|
||||
if (uwsgi_stats_keyval_comma(us, "id", c_ui->name))
|
||||
goto end0;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) c_ui->pid))
|
||||
if (uwsgi_stats_keyslong_comma(us, "pid", (long long) c_ui->pid))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "born", (unsigned long long) c_ui->born))
|
||||
goto end0;
|
||||
@@ -1285,6 +1503,9 @@ void emperor_send_stats(int fd) {
|
||||
if (uwsgi_stats_keylong_comma(us, "zerg", (unsigned long long) c_ui->zerg))
|
||||
goto end0;
|
||||
|
||||
if (uwsgi_stats_keyval_comma(us, "on_demand", c_ui->socket_name ? c_ui->socket_name : ""))
|
||||
goto end0;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "uid", (unsigned long long) c_ui->uid))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "gid", (unsigned long long) c_ui->gid))
|
||||
@@ -1403,6 +1624,7 @@ void uwsgi_emperor_start() {
|
||||
else {
|
||||
uwsgi.emperor_pid = uwsgi_fork("uWSGI Emperor");
|
||||
}
|
||||
|
||||
if (uwsgi.emperor_pid < 0) {
|
||||
uwsgi_error("pid()");
|
||||
exit(1);
|
||||
@@ -1436,7 +1658,7 @@ void uwsgi_check_emperor() {
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char *config, time_t ts, uid_t uid, gid_t gid) {
|
||||
void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char *config, time_t ts, uid_t uid, gid_t gid, char *socket_name) {
|
||||
|
||||
if (!uwsgi_emperor_is_valid(name))
|
||||
return;
|
||||
@@ -1473,6 +1695,6 @@ void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char
|
||||
new_config = uwsgi_str(config);
|
||||
new_config_len = strlen(new_config);
|
||||
}
|
||||
emperor_add(ues, name, ts, new_config, new_config_len, uid, gid);
|
||||
emperor_add(ues, name, ts, new_config, new_config_len, uid, gid, socket_name);
|
||||
}
|
||||
}
|
||||
|
||||
+241
-14
@@ -2,6 +2,233 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#ifdef UWSGI_EVENT_USE_POLL
|
||||
#define UWSGI_EVENT_IN POLLIN
|
||||
#define UWSGI_EVENT_OUT POLLOUT
|
||||
|
||||
int uwsgi_poll_event_queue_max = 0;
|
||||
struct uwsgi_poll_event {
|
||||
int nevents;
|
||||
int max_events;
|
||||
pthread_mutex_t lock;
|
||||
struct pollfd *poll;
|
||||
};
|
||||
|
||||
struct uwsgi_poll_event **uwsgi_poll_event_queue;
|
||||
|
||||
// all of the public functions must be heavy locked
|
||||
|
||||
static int uwsgi_poll_fd_is_registered(struct uwsgi_poll_event *upe, int fd) {
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (upe->poll[i].fd == fd) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_poll_fd_add(struct uwsgi_poll_event *upe, int fd, int event) {
|
||||
int pos = upe->nevents;
|
||||
if (pos > upe->max_events) return -1;
|
||||
upe->poll[pos].fd = fd;
|
||||
upe->poll[pos].events = event;
|
||||
upe->nevents++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_poll_fd_del(struct uwsgi_poll_event *upe, int fd) {
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (upe->poll[i].fd == fd) {
|
||||
if (i < upe->nevents-1) {
|
||||
memcpy(&upe->poll[i], &upe->poll[i+1], sizeof(struct uwsgi_poll_event) * (upe->nevents - (i+1)));
|
||||
}
|
||||
upe->nevents--;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void uwsgi_poll_queue_rebuild(struct uwsgi_poll_event *upe) {
|
||||
// we need to check if some file descriptor is no more valid
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (!uwsgi_valid_fd(upe->poll[i].fd)) {
|
||||
uwsgi_poll_fd_del(upe, upe->poll[i].fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int event_queue_wait(int eq, int timeout, int *interesting_fd) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
uwsgi_poll_queue_rebuild(upe);
|
||||
int ret = poll(upe->poll, upe->nevents, timeout * 1000);
|
||||
if (ret > 0) {
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (upe->poll[i].revents) {
|
||||
*interesting_fd = upe->poll[i].fd;
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int event_queue_init() {
|
||||
if (!uwsgi_poll_event_queue) {
|
||||
uwsgi_poll_event_queue = uwsgi_calloc(sizeof(struct uwsgi_poll_event *) * uwsgi.max_fd);
|
||||
}
|
||||
int eq = uwsgi_poll_event_queue_max;
|
||||
uwsgi_poll_event_queue[eq] = uwsgi_calloc(sizeof(struct uwsgi_poll_event));
|
||||
uwsgi_poll_event_queue_max++;
|
||||
uwsgi_poll_event_queue[eq]->poll = uwsgi_malloc(sizeof(struct pollfd) * uwsgi.max_fd);
|
||||
uwsgi_poll_event_queue[eq]->max_events = uwsgi.max_fd;
|
||||
pthread_mutex_init(&uwsgi_poll_event_queue[eq]->lock, NULL);
|
||||
return eq;
|
||||
}
|
||||
|
||||
void *event_queue_alloc(int nevents) {
|
||||
return uwsgi_calloc(sizeof(struct pollfd) * nevents);
|
||||
}
|
||||
|
||||
int event_queue_interesting_fd_is_read(void *events, int id) {
|
||||
struct pollfd *pevents = (struct pollfd *)events;
|
||||
struct pollfd *upoll = &pevents[id];
|
||||
if (upoll->revents & POLLIN) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_queue_fd_write_to_readwrite(int eq, int fd) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (upe->poll[i].fd == fd) {
|
||||
upe->poll[i].events = POLLIN|POLLOUT;
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int event_queue_fd_read_to_readwrite(int eq, int fd) {
|
||||
return event_queue_fd_write_to_readwrite(eq, fd);
|
||||
}
|
||||
|
||||
int event_queue_interesting_fd_is_write(void *events, int id) {
|
||||
struct pollfd *pevents = (struct pollfd *)events;
|
||||
struct pollfd *upoll = &pevents[id];
|
||||
if (upoll->revents & POLLOUT) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_queue_add_fd_read(int eq, int fd) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
if (uwsgi_poll_fd_is_registered(upe, fd)) {
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return 0;
|
||||
}
|
||||
int ret = uwsgi_poll_fd_add(upe, fd, POLLIN);
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return ret;
|
||||
}
|
||||
int event_queue_add_fd_write(int eq, int fd) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
if (uwsgi_poll_fd_is_registered(upe, fd)) {
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return 0;
|
||||
}
|
||||
int ret = uwsgi_poll_fd_add(upe, fd, POLLOUT);
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return ret;
|
||||
}
|
||||
int event_queue_del_fd(int eq, int fd, int event) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
int ret = uwsgi_poll_fd_del(upe, fd);
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return ret;
|
||||
}
|
||||
int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
uwsgi_poll_queue_rebuild(upe);
|
||||
int ret = poll(upe->poll, upe->nevents, timeout * 1000);
|
||||
int cnt = 0;
|
||||
if (ret > 0) {
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (upe->poll[i].revents) {
|
||||
struct pollfd *pevents = (struct pollfd *)events;
|
||||
struct pollfd *upoll = &pevents[cnt];
|
||||
upoll->fd = upe->poll[i].fd;
|
||||
upoll->revents = upe->poll[i].revents;
|
||||
upoll->events = upe->poll[i].events;
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
if (ret <= 0) return ret;
|
||||
return cnt;
|
||||
}
|
||||
int event_queue_interesting_fd_has_error(void *events, int id) {
|
||||
struct pollfd *pevents = (struct pollfd *)events;
|
||||
struct pollfd *upoll = &pevents[id];
|
||||
if (upoll->revents & POLLERR || upoll->revents & POLLHUP || upoll->revents & POLLNVAL) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int event_queue_interesting_fd(void *events, int id) {
|
||||
struct pollfd *pevents = (struct pollfd *)events;
|
||||
struct pollfd *upoll = &pevents[id];
|
||||
return upoll->fd;
|
||||
}
|
||||
int event_queue_fd_write_to_read(int eq, int fd) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (upe->poll[i].fd == fd) {
|
||||
upe->poll[i].events = POLLIN;
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return -1;
|
||||
}
|
||||
int event_queue_fd_read_to_write(int eq, int fd) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (upe->poll[i].fd == fd) {
|
||||
upe->poll[i].events = POLLOUT;
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
|
||||
#include <port.h>
|
||||
@@ -33,7 +260,7 @@ int event_queue_del_fd(int eq, int fd, int event) {
|
||||
|
||||
int event_queue_fd_write_to_read(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -44,7 +271,7 @@ int event_queue_fd_write_to_read(int eq, int fd) {
|
||||
|
||||
int event_queue_fd_read_to_write(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -55,7 +282,7 @@ int event_queue_fd_read_to_write(int eq, int fd) {
|
||||
|
||||
int event_queue_fd_readwrite_to_read(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -66,7 +293,7 @@ int event_queue_fd_readwrite_to_read(int eq, int fd) {
|
||||
|
||||
int event_queue_fd_readwrite_to_write(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -77,7 +304,7 @@ int event_queue_fd_readwrite_to_write(int eq, int fd) {
|
||||
|
||||
int event_queue_fd_write_to_readwrite(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -88,7 +315,7 @@ int event_queue_fd_write_to_readwrite(int eq, int fd) {
|
||||
|
||||
int event_queue_fd_read_to_readwrite(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -124,7 +351,7 @@ int event_queue_interesting_fd_is_write(void *events, int id) {
|
||||
|
||||
int event_queue_add_fd_read(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -134,7 +361,7 @@ int event_queue_add_fd_read(int eq, int fd) {
|
||||
|
||||
int event_queue_add_fd_write(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -154,7 +381,7 @@ int event_queue_interesting_fd(void *events, int id) {
|
||||
}
|
||||
|
||||
int fd = (int) pe[id].portev_object;
|
||||
int eq = (int) pe[id].portev_user;
|
||||
int eq = (long) pe[id].portev_user;
|
||||
|
||||
if (pe[id].portev_events == POLLOUT) {
|
||||
event_queue_add_fd_write(eq, fd);
|
||||
@@ -196,7 +423,7 @@ int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
|
||||
port_event_t *pe_i = &pe[i];
|
||||
if (pe_i->portev_source == PORT_SOURCE_FD) {
|
||||
// event must be readded (damn Oracle/Sun why the fu*k you made such a horrible choice ???? why not adding a ONESHOT flag ???)
|
||||
if (port_associate(eq, pe_i->portev_source, pe_i->portev_object, pe_i->portev_events, NULL)) {
|
||||
if (port_associate(eq, pe_i->portev_source, pe_i->portev_object, pe_i->portev_events, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
}
|
||||
}
|
||||
@@ -222,16 +449,16 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
|
||||
ret = port_get(eq, &pe, NULL);
|
||||
}
|
||||
if (ret < 0) {
|
||||
if (errno != ETIME) {
|
||||
if (errno == ETIME) return 0;
|
||||
if (errno != EINTR) {
|
||||
uwsgi_error("port_get()");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pe.portev_source == PORT_SOURCE_FD) {
|
||||
// event must be readded (damn Oracle/Sun why the fu*k you made such a horrible choice ???? why not adding a ONESHOT flag ???)
|
||||
if (port_associate(eq, pe.portev_source, pe.portev_object, pe.portev_events, NULL)) {
|
||||
if (port_associate(eq, pe.portev_source, pe.portev_object, pe.portev_events, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
}
|
||||
}
|
||||
|
||||
+14
-6
@@ -1,6 +1,4 @@
|
||||
#ifdef UWSGI_INI
|
||||
|
||||
#include "uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
@@ -9,6 +7,8 @@ extern struct uwsgi_server uwsgi;
|
||||
This memory must not be freed for all the server lifecycle
|
||||
*/
|
||||
|
||||
static char *last_file = NULL;
|
||||
|
||||
void ini_rstrip(char *line) {
|
||||
|
||||
off_t i;
|
||||
@@ -106,13 +106,23 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
|
||||
if (colon[1] != 0) {
|
||||
section_asked = colon + 1;
|
||||
}
|
||||
|
||||
if (colon == file) {
|
||||
file = last_file;
|
||||
}
|
||||
}
|
||||
|
||||
if (file[0] != 0) {
|
||||
if (file[0] != 0 && file != last_file) {
|
||||
uwsgi_log_initial("[uWSGI] getting INI configuration from %s\n", file);
|
||||
}
|
||||
|
||||
ini = uwsgi_open_and_read(file, &len, 1, magic_table);
|
||||
if (file != last_file) {
|
||||
if (last_file) {
|
||||
free(last_file);
|
||||
}
|
||||
last_file = uwsgi_str(file);
|
||||
}
|
||||
|
||||
while (len) {
|
||||
ini_line = ini_get_line(ini, len);
|
||||
@@ -157,5 +167,3 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -770,10 +770,10 @@ timeout:
|
||||
// check if an fd is valid
|
||||
int uwsgi_valid_fd(int fd) {
|
||||
int ret = fcntl(fd, F_GETFL);
|
||||
if (ret == 0) {
|
||||
return 1;
|
||||
if (ret == -1) {
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void uwsgi_close_all_fds(void) {
|
||||
|
||||
+143
-24
@@ -81,6 +81,37 @@ void uwsgi_parse_legion(char *key, uint16_t keylen, char *value, uint16_t vallen
|
||||
}
|
||||
}
|
||||
|
||||
// this function is called when a node is added or removed (heavy locking is needed)
|
||||
static void legion_rebuild_scrolls(struct uwsgi_legion *ul) {
|
||||
uint64_t max_size = ul->scrolls_max_size;
|
||||
|
||||
// first, try to add myself
|
||||
if (ul->scroll_len + (uint64_t) 2 > max_size) {
|
||||
uwsgi_log("[DANGER] you have configured a too much tiny buffer for the scrolls list !!! tune it with --legion-scroll-list-max-size\n");
|
||||
ul->scroll_len = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
char *ptr = ul->scrolls;
|
||||
*ptr ++= (uint8_t) (ul->scroll_len & 0xff);
|
||||
*ptr ++= (uint8_t) ((ul->scroll_len >> 8) &0xff);
|
||||
memcpy(ptr, ul->scroll, ul->scroll_len); ptr += ul->scroll_len;
|
||||
ul->scrolls_len = 2 + ul->scroll_len;
|
||||
// ok start adding nodes;
|
||||
struct uwsgi_legion_node *uln = ul->nodes_head;
|
||||
while(uln) {
|
||||
if (ul->scrolls_len + 2 + uln->scroll_len > max_size) {
|
||||
uwsgi_log("[DANGER] you have configured a too much tiny buffer for the scrolls list !!! tune it with --legion-scroll-list-max-size\n");
|
||||
return;
|
||||
}
|
||||
*ptr ++= (uint8_t) (uln->scroll_len & 0xff);
|
||||
*ptr ++= (uint8_t) ((uln->scroll_len >> 8) &0xff);
|
||||
memcpy(ptr, uln->scroll, uln->scroll_len); ptr += uln->scroll_len;
|
||||
ul->scrolls_len += 2 + uln->scroll_len;
|
||||
uln = uln->next;
|
||||
}
|
||||
}
|
||||
|
||||
// critical section (remember to lock when you use it)
|
||||
struct uwsgi_legion_node *uwsgi_legion_add_node(struct uwsgi_legion *ul, uint16_t valor, char *name, uint16_t name_len, char *uuid) {
|
||||
|
||||
@@ -104,6 +135,7 @@ struct uwsgi_legion_node *uwsgi_legion_add_node(struct uwsgi_legion *ul, uint16_
|
||||
ul->nodes_head = node;
|
||||
}
|
||||
|
||||
|
||||
return node;
|
||||
|
||||
|
||||
@@ -141,6 +173,8 @@ void uwsgi_legion_remove_node(struct uwsgi_legion *ul, struct uwsgi_legion_node
|
||||
}
|
||||
|
||||
free(node);
|
||||
|
||||
legion_rebuild_scrolls(ul);
|
||||
}
|
||||
|
||||
struct uwsgi_legion_node *uwsgi_legion_get_node(struct uwsgi_legion *ul, uint64_t valor, char *name, uint16_t name_len, char *uuid) {
|
||||
@@ -169,7 +203,6 @@ static void legions_check_nodes() {
|
||||
|
||||
struct uwsgi_legion_node *node = legion->nodes_head;
|
||||
while (node) {
|
||||
|
||||
if (now - node->last_seen > uwsgi.legion_tolerance) {
|
||||
struct uwsgi_legion_node *tmp_node = node;
|
||||
node = node->next;
|
||||
@@ -177,6 +210,15 @@ static void legions_check_nodes() {
|
||||
uwsgi_wlock(legion->lock);
|
||||
uwsgi_legion_remove_node(legion, tmp_node);
|
||||
uwsgi_rwunlock(legion->lock);
|
||||
// trigger node_left hooks
|
||||
struct uwsgi_string_list *usl = legion->node_left_hooks;
|
||||
while (usl) {
|
||||
int ret = uwsgi_legion_action_call("node_left", legion, usl);
|
||||
if (ret) {
|
||||
uwsgi_log("[uwsgi-legion] ERROR, node_left hook returned: %d\n", ret);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
node = node->next;
|
||||
@@ -268,6 +310,18 @@ static void legions_check_nodes_step2() {
|
||||
|
||||
// we have quorum !!!
|
||||
if (votes > 0 && votes >= ul->quorum) {
|
||||
if (!ul->joined) {
|
||||
// triggering join hooks
|
||||
struct uwsgi_string_list *usl = ul->join_hooks;
|
||||
while (usl) {
|
||||
int ret = uwsgi_legion_action_call("join", ul, usl);
|
||||
if (ret) {
|
||||
uwsgi_log("[uwsgi-legion] ERROR, join hook returned: %d\n", ret);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
ul->joined = 1;
|
||||
}
|
||||
// something changed ???
|
||||
if (ul->changed) {
|
||||
legions_report_quorum(ul, best_valor, best_uuid, votes);
|
||||
@@ -521,8 +575,19 @@ static void *legion_loop(void *foobar) {
|
||||
node->scroll_len = legion_msg.scroll_len;
|
||||
memcpy(node->scroll, legion_msg.scroll, node->scroll_len);
|
||||
}
|
||||
// we are still locked (and safe), let's rebuild the scrolls list
|
||||
legion_rebuild_scrolls(ul);
|
||||
uwsgi_rwunlock(ul->lock);
|
||||
uwsgi_log("[uwsgi-legion] node: %.*s valor: %llu uuid: %.*s joined Legion %s\n", node->name_len, node->name, node->valor, 36, node->uuid, ul->legion);
|
||||
// trigger node_joined hooks
|
||||
struct uwsgi_string_list *usl = ul->node_joined_hooks;
|
||||
while (usl) {
|
||||
int ret = uwsgi_legion_action_call("node_joined", ul, usl);
|
||||
if (ret) {
|
||||
uwsgi_log("[uwsgi-legion] ERROR, node_joined hook returned: %d\n", ret);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
node->last_seen = uwsgi_now();
|
||||
@@ -727,15 +792,20 @@ void uwsgi_opt_legion_node(char *opt, char *value, void *foobar) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *usl = uwsgi_string_new_list(&ul->nodes, space + 1);
|
||||
char *port = strchr(usl->value, ':');
|
||||
uwsgi_legion_register_node(ul, space + 1);
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_legion_register_node(struct uwsgi_legion *ul, char *addr) {
|
||||
struct uwsgi_string_list *usl = uwsgi_string_new_list(&ul->nodes, addr);
|
||||
char *port = strchr(addr, ':');
|
||||
if (!port) {
|
||||
uwsgi_log("[uwsgi-legion] invalid udp address: %s\n", usl->value);
|
||||
uwsgi_log("[uwsgi-legion] invalid udp address: %s\n", addr);
|
||||
exit(1);
|
||||
}
|
||||
// no need to zero the memory, socket_to_in_addr will do that
|
||||
struct sockaddr_in *sin = uwsgi_malloc(sizeof(struct sockaddr_in));
|
||||
usl->custom = socket_to_in_addr(usl->value, port, 0, sin);
|
||||
usl->custom = socket_to_in_addr(addr, port, 0, sin);
|
||||
usl->custom_ptr = sin;
|
||||
}
|
||||
|
||||
@@ -787,51 +857,76 @@ void uwsgi_opt_legion_scroll(char *opt, char *value, void *foobar) {
|
||||
|
||||
void uwsgi_opt_legion_hook(char *opt, char *value, void *foobar) {
|
||||
|
||||
char *event = strchr(opt, '-');
|
||||
if (!event) {
|
||||
uwsgi_log("[uwsgi-legion] invalid option name (%s), this should not happen (possible bug)\n", opt);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *legion = uwsgi_str(value);
|
||||
|
||||
|
||||
char *space = strchr(legion, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid %s syntax, must be <legion> <action>\n", opt);
|
||||
uwsgi_log("[uwsgi-legion] invalid %s syntax, must be <legion> <action>\n", opt);
|
||||
exit(1);
|
||||
}
|
||||
*space = 0;
|
||||
|
||||
struct uwsgi_legion *ul = uwsgi_legion_get_by_name(legion);
|
||||
if (!ul) {
|
||||
uwsgi_log("unknown legion: %s\n", legion);
|
||||
uwsgi_log("[uwsgi-legion] unknown legion: %s\n", legion);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_legion_register_hook(ul, event + 1, space + 1);
|
||||
}
|
||||
|
||||
void uwsgi_legion_register_hook(struct uwsgi_legion *ul, char *event, char *action) {
|
||||
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
|
||||
if (!strcmp(opt, "legion-lord")) {
|
||||
usl = uwsgi_string_new_list(&ul->lord_hooks, space + 1);
|
||||
if (!strcmp(event, "lord")) {
|
||||
usl = uwsgi_string_new_list(&ul->lord_hooks, action);
|
||||
}
|
||||
else if (!strcmp(opt, "legion-unlord")) {
|
||||
usl = uwsgi_string_new_list(&ul->unlord_hooks, space + 1);
|
||||
else if (!strcmp(event, "unlord")) {
|
||||
usl = uwsgi_string_new_list(&ul->unlord_hooks, action);
|
||||
}
|
||||
else if (!strcmp(opt, "legion-setup")) {
|
||||
usl = uwsgi_string_new_list(&ul->setup_hooks, space + 1);
|
||||
else if (!strcmp(event, "setup")) {
|
||||
usl = uwsgi_string_new_list(&ul->setup_hooks, action);
|
||||
}
|
||||
else if (!strcmp(opt, "legion-death")) {
|
||||
usl = uwsgi_string_new_list(&ul->death_hooks, space + 1);
|
||||
else if (!strcmp(event, "death")) {
|
||||
usl = uwsgi_string_new_list(&ul->death_hooks, action);
|
||||
}
|
||||
else if (!strcmp(event, "join")) {
|
||||
usl = uwsgi_string_new_list(&ul->join_hooks, action);
|
||||
}
|
||||
else if (!strcmp(event, "node-joined")) {
|
||||
usl = uwsgi_string_new_list(&ul->node_joined_hooks, action);
|
||||
}
|
||||
else if (!strcmp(event, "node-left")) {
|
||||
usl = uwsgi_string_new_list(&ul->node_left_hooks, action);
|
||||
}
|
||||
|
||||
else {
|
||||
uwsgi_log("[uwsgi-legion] invalid event: %s\n", event);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!usl)
|
||||
return;
|
||||
|
||||
char *port = strchr(usl->value, ':');
|
||||
if (!port) {
|
||||
uwsgi_log("[uwsgi-legion] invalid %s action: %s\n", opt, usl->value);
|
||||
char *hook = strchr(action, ':');
|
||||
if (!hook) {
|
||||
uwsgi_log("[uwsgi-legion] invalid %s action: %s\n", event, action);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// pointer to action plugin
|
||||
usl->custom_ptr = uwsgi_concat2n(usl->value, port - usl->value, "", 0);
|
||||
usl->custom_ptr = uwsgi_concat2n(action, hook - action, "", 0);;
|
||||
// add that to check the plugin value
|
||||
usl->custom = port - usl->value + 1;
|
||||
}
|
||||
usl->custom = hook - action + 1;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
|
||||
|
||||
@@ -869,6 +964,10 @@ void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
|
||||
*colon = 0;
|
||||
char *secret = colon + 1;
|
||||
|
||||
uwsgi_legion_register(legion, addr, valor, algo_secret, secret);
|
||||
}
|
||||
|
||||
struct uwsgi_legion *uwsgi_legion_register(char *legion, char *addr, char *valor, char *algo, char *secret) {
|
||||
char *iv = strchr(secret, ' ');
|
||||
if (iv) {
|
||||
*iv = 0;
|
||||
@@ -882,9 +981,9 @@ void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
|
||||
EVP_CIPHER_CTX *ctx = uwsgi_malloc(sizeof(EVP_CIPHER_CTX));
|
||||
EVP_CIPHER_CTX_init(ctx);
|
||||
|
||||
const EVP_CIPHER *cipher = EVP_get_cipherbyname(algo_secret);
|
||||
const EVP_CIPHER *cipher = EVP_get_cipherbyname(algo);
|
||||
if (!cipher) {
|
||||
uwsgi_log("[uwsgi-legion] unable to find algorithm/cipher %s\n", algo_secret);
|
||||
uwsgi_log("[uwsgi-legion] unable to find algorithm/cipher %s\n", algo);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -937,10 +1036,18 @@ void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
|
||||
uwsgi.legion_scroll_max_size = 4096;
|
||||
}
|
||||
|
||||
if (!uwsgi.legion_scroll_list_max_size) {
|
||||
uwsgi.legion_scroll_list_max_size = 32768;
|
||||
}
|
||||
|
||||
ul->lord_scroll_size = uwsgi.legion_scroll_max_size;
|
||||
ul->lord_scroll = uwsgi_calloc_shared(ul->lord_scroll_size);
|
||||
ul->scrolls_max_size = uwsgi.legion_scroll_list_max_size;
|
||||
ul->scrolls = uwsgi_calloc_shared(ul->scrolls_max_size);
|
||||
|
||||
uwsgi_legion_add(ul);
|
||||
|
||||
return ul;
|
||||
}
|
||||
|
||||
struct uwsgi_legion_action *uwsgi_legion_action_get(char *name) {
|
||||
@@ -1020,3 +1127,15 @@ char *uwsgi_legion_lord_scroll(char *name, uint16_t *rlen) {
|
||||
uwsgi_rwunlock(legion->lock);
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *uwsgi_legion_scrolls(char *name, uint64_t *rlen) {
|
||||
char *buf = NULL;
|
||||
struct uwsgi_legion *legion = uwsgi_legion_get_by_name(name);
|
||||
if (!legion) return NULL;
|
||||
uwsgi_rlock(legion->lock);
|
||||
buf = uwsgi_malloc(legion->scrolls_len);
|
||||
memcpy(buf, legion->scrolls, legion->scrolls_len);
|
||||
*rlen = legion->scrolls_len;
|
||||
uwsgi_rwunlock(legion->lock);
|
||||
return buf;
|
||||
}
|
||||
|
||||
+54
-3
@@ -401,6 +401,60 @@ void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
|
||||
uwsgi_unlock_fast(uli);
|
||||
}
|
||||
|
||||
#elif defined(UWSGI_LOCK_USE_WINDOWS_MUTEX)
|
||||
|
||||
#define UWSGI_LOCK_ENGINE_NAME "windows mutexes"
|
||||
#define UWSGI_LOCK_SIZE sizeof(HANDLE)
|
||||
#define UWSGI_RWLOCK_SIZE sizeof(HANDLE)
|
||||
|
||||
|
||||
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
|
||||
|
||||
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
|
||||
struct _SECURITY_ATTRIBUTES sa;
|
||||
memset(&sa, 0, sizeof(struct _SECURITY_ATTRIBUTES));
|
||||
sa.bInheritHandle = 1;
|
||||
uli->lock_ptr = CreateMutex(&sa, FALSE, NULL);
|
||||
return uli;
|
||||
}
|
||||
|
||||
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
|
||||
WaitForSingleObject(uli->lock_ptr, INFINITE);
|
||||
uli->pid = uwsgi.mypid;
|
||||
}
|
||||
|
||||
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
|
||||
ReleaseMutex(uli->lock_ptr);
|
||||
uli->pid = 0;
|
||||
}
|
||||
|
||||
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
|
||||
if (WaitForSingleObject(uli->lock_ptr, 0) == WAIT_TIMEOUT) {
|
||||
return 0;
|
||||
}
|
||||
return uli->pid;
|
||||
}
|
||||
|
||||
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
|
||||
return uwsgi_lock_fast_init(id);
|
||||
}
|
||||
|
||||
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) {
|
||||
uwsgi_lock_fast(uli);
|
||||
}
|
||||
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) {
|
||||
uwsgi_lock_fast(uli);
|
||||
}
|
||||
|
||||
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) {
|
||||
return uwsgi_lock_fast_check(uli);
|
||||
}
|
||||
|
||||
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
|
||||
uwsgi_unlock_fast(uli);
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#define uwsgi_lock_fast_init uwsgi_lock_ipcsem_init
|
||||
@@ -625,9 +679,6 @@ ready:
|
||||
// timer table lock
|
||||
uwsgi.timer_table_lock = uwsgi_lock_init("timer");
|
||||
|
||||
// probe table lock
|
||||
uwsgi.probe_table_lock = uwsgi_lock_init("probe");
|
||||
|
||||
// rb_timer table lock
|
||||
uwsgi.rb_timer_table_lock = uwsgi_lock_init("rbtimer");
|
||||
|
||||
|
||||
+33
-12
@@ -1,9 +1,9 @@
|
||||
#define _NO_UWSGI_RB
|
||||
#include "uwsgi.h"
|
||||
|
||||
#ifndef __DragonFly__
|
||||
#include <uwsgi.h>
|
||||
#endif
|
||||
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
|
||||
#include <kvm.h>
|
||||
#include <sys/user.h>
|
||||
#include <kvm.h>
|
||||
#elif defined(__sun__)
|
||||
/* Terrible Hack !!! */
|
||||
#ifndef _LP64
|
||||
@@ -17,6 +17,10 @@
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
#ifdef __DragonFly__
|
||||
#include <uwsgi.h>
|
||||
#endif
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
//use this instead of fprintf to avoid buffering mess with udp logging
|
||||
@@ -314,7 +318,7 @@ static struct uwsgi_logger *setup_choosen_logger(struct uwsgi_string_list *usl)
|
||||
int is_id = 1;
|
||||
int i;
|
||||
for (i = 0; i < (space - name); i++) {
|
||||
if (!isalnum(name[i])) {
|
||||
if (!isalnum((int)name[i])) {
|
||||
is_id = 0;
|
||||
break;
|
||||
}
|
||||
@@ -638,12 +642,8 @@ void uwsgi_logit_simple(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1) {
|
||||
#ifndef UNBIT
|
||||
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} {rss usage: %llu bytes/%lluMB} ", (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024, (unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
|
||||
#else
|
||||
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} ", (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024);
|
||||
#endif
|
||||
|
||||
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} {rss usage: %llu bytes/%lluMB} ", (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024,
|
||||
(unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
|
||||
logvec[logvecpos].iov_base = mempkt;
|
||||
logvec[logvecpos].iov_len = rlen;
|
||||
logvecpos++;
|
||||
@@ -673,7 +673,11 @@ void uwsgi_logit_simple(struct wsgi_request *wsgi_req) {
|
||||
void get_memusage(uint64_t * rss, uint64_t * vsz) {
|
||||
|
||||
#ifdef UNBIT
|
||||
*vsz = syscall(356);
|
||||
uint64_t ret[2];
|
||||
ret[0] = 0; ret[1] = 0;
|
||||
syscall(358, ret);
|
||||
*vsz = ret[0];
|
||||
*rss = ret[1] * uwsgi.page_size;
|
||||
#elif defined(__linux__)
|
||||
FILE *procfile;
|
||||
int i;
|
||||
@@ -686,6 +690,18 @@ void get_memusage(uint64_t * rss, uint64_t * vsz) {
|
||||
fclose(procfile);
|
||||
}
|
||||
*rss = *rss * uwsgi.page_size;
|
||||
#elif defined(__CYGWIN__)
|
||||
// same as Linux but rss is not in pages...
|
||||
FILE *procfile;
|
||||
int i;
|
||||
procfile = fopen("/proc/self/stat", "r");
|
||||
if (procfile) {
|
||||
i = fscanf(procfile, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %llu %lld", (unsigned long long *) vsz, (unsigned long long *) rss);
|
||||
if (i != 2) {
|
||||
uwsgi_log("warning: invalid record in /proc/self/stat\n");
|
||||
}
|
||||
fclose(procfile);
|
||||
}
|
||||
#elif defined (__sun__)
|
||||
psinfo_t info;
|
||||
int procfd;
|
||||
@@ -725,8 +741,13 @@ void get_memusage(uint64_t * rss, uint64_t * vsz) {
|
||||
struct kinfo_proc *kproc;
|
||||
kproc = kvm_getprocs(kv, KERN_PROC_PID, uwsgi.mypid, &cnt);
|
||||
if (kproc && cnt > 0) {
|
||||
#if defined(__FreeBSD__)
|
||||
*vsz = kproc->ki_size;
|
||||
*rss = kproc->ki_rssize * uwsgi.page_size;
|
||||
#elif defined(__DragonFly__)
|
||||
*vsz = kproc->kp_vm_map_size;
|
||||
*rss = kproc->kp_vm_rssize * uwsgi.page_size;
|
||||
#endif
|
||||
}
|
||||
#elif defined(UWSGI_NEW_OPENBSD)
|
||||
struct kinfo_proc *kproc;
|
||||
|
||||
+19
-35
@@ -638,22 +638,6 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi_manage_command_cron(uwsgi_now());
|
||||
}
|
||||
|
||||
|
||||
// check for probes
|
||||
if (ushared->probes_cnt > 0) {
|
||||
uwsgi_lock(uwsgi.probe_table_lock);
|
||||
for (i = 0; i < ushared->probes_cnt; i++) {
|
||||
if (interesting_fd == -1) {
|
||||
// increment cycles
|
||||
ushared->probes[i].cycles++;
|
||||
}
|
||||
if (ushared->probes[i].func(interesting_fd, &ushared->probes[i])) {
|
||||
uwsgi_route_signal(ushared->probes[i].sig);
|
||||
}
|
||||
}
|
||||
uwsgi_unlock(uwsgi.probe_table_lock);
|
||||
}
|
||||
|
||||
// some event returned
|
||||
if (rlen > 0) {
|
||||
// if the following function returns -1, a new worker has just spawned
|
||||
@@ -798,8 +782,8 @@ int master_loop(char **argv, char **environ) {
|
||||
|
||||
*/
|
||||
|
||||
uwsgi.mywid = find_worker_id(diedpid);
|
||||
if (uwsgi.mywid <= 0) {
|
||||
int thewid = find_worker_id(diedpid);
|
||||
if (thewid <= 0) {
|
||||
// check spooler, mules, gateways and daemons
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
while (uspool) {
|
||||
@@ -842,50 +826,50 @@ next:
|
||||
|
||||
|
||||
// ok a worker died...
|
||||
uwsgi.workers[uwsgi.mywid].pid = 0;
|
||||
uwsgi.workers[thewid].pid = 0;
|
||||
// only to be safe :P
|
||||
uwsgi.workers[uwsgi.mywid].harakiri = 0;
|
||||
uwsgi.workers[thewid].harakiri = 0;
|
||||
|
||||
// ok, if we are reloading or dying, just continue the master loop
|
||||
// as soon as all of the workers have pid == 0, the action (exit, or reload) is triggered
|
||||
if (uwsgi_instance_is_reloading || uwsgi_instance_is_dying) {
|
||||
uwsgi_log("worker %d buried after %d seconds\n", uwsgi.mywid, (int) (uwsgi_now()-uwsgi.workers[uwsgi.mywid].cursed_at));
|
||||
uwsgi.workers[uwsgi.mywid].cursed_at = 0;
|
||||
uwsgi_log("worker %d buried after %d seconds\n", thewid, (int) (uwsgi_now()-uwsgi.workers[thewid].cursed_at));
|
||||
uwsgi.workers[thewid].cursed_at = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
// if we are stopping workers, just end here
|
||||
|
||||
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_FAILED_APP_CODE) {
|
||||
uwsgi_log("OOPS ! failed loading app in worker %d (pid %d) :( trying again...\n", uwsgi.mywid, (int) diedpid);
|
||||
uwsgi_log("OOPS ! failed loading app in worker %d (pid %d) :( trying again...\n", thewid, (int) diedpid);
|
||||
}
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_DE_HIJACKED_CODE) {
|
||||
uwsgi_log("...restoring worker %d (pid: %d)...\n", uwsgi.mywid, (int) diedpid);
|
||||
uwsgi_log("...restoring worker %d (pid: %d)...\n", thewid, (int) diedpid);
|
||||
}
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_EXCEPTION_CODE) {
|
||||
uwsgi_log("... monitored exception detected, respawning worker %d (pid: %d)...\n", uwsgi.mywid, (int) diedpid);
|
||||
uwsgi_log("... monitored exception detected, respawning worker %d (pid: %d)...\n", thewid, (int) diedpid);
|
||||
}
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_QUIET_CODE) {
|
||||
// noop
|
||||
}
|
||||
else if (uwsgi.workers[uwsgi.mywid].manage_next_request) {
|
||||
else if (uwsgi.workers[thewid].manage_next_request) {
|
||||
if (WIFSIGNALED(waitpid_status)) {
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died, killed by signal %d :( trying respawn ...\n", uwsgi.mywid, (int) diedpid, (int) WTERMSIG(waitpid_status));
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died, killed by signal %d :( trying respawn ...\n", thewid, (int) diedpid, (int) WTERMSIG(waitpid_status));
|
||||
}
|
||||
else {
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died :( trying respawn ...\n", uwsgi.mywid, (int) diedpid);
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died :( trying respawn ...\n", thewid, (int) diedpid);
|
||||
}
|
||||
}
|
||||
else if (uwsgi.workers[uwsgi.mywid].cursed_at > 0) {
|
||||
uwsgi_log("worker %d killed successfully (pid: %d)\n", uwsgi.mywid, (int) diedpid);
|
||||
else if (uwsgi.workers[thewid].cursed_at > 0) {
|
||||
uwsgi_log("worker %d killed successfully (pid: %d)\n", thewid, (int) diedpid);
|
||||
}
|
||||
// manage_next_request is zero, but killed by signal...
|
||||
else if (WIFSIGNALED(waitpid_status)) {
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) MISTERIOUSLY killed by signal %d :( trying respawn ...\n", uwsgi.mywid, (int) diedpid, (int) WTERMSIG(waitpid_status));
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) MISTERIOUSLY killed by signal %d :( trying respawn ...\n", thewid, (int) diedpid, (int) WTERMSIG(waitpid_status));
|
||||
}
|
||||
|
||||
if (uwsgi.workers[uwsgi.mywid].cheaped == 1) {
|
||||
uwsgi_log("uWSGI worker %d cheaped.\n", uwsgi.mywid);
|
||||
if (uwsgi.workers[thewid].cheaped == 1) {
|
||||
uwsgi_log("uWSGI worker %d cheaped.\n", thewid);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -909,12 +893,12 @@ next:
|
||||
uwsgi.respawn_delta = last_respawn.tv_sec;
|
||||
|
||||
// are we chain reloading it ?
|
||||
if (uwsgi.status.chain_reloading == uwsgi.mywid) {
|
||||
if (uwsgi.status.chain_reloading == thewid) {
|
||||
uwsgi.status.chain_reloading++;
|
||||
}
|
||||
|
||||
// respawn the worker (if needed)
|
||||
if (uwsgi_respawn_worker(uwsgi.mywid))
|
||||
if (uwsgi_respawn_worker(thewid))
|
||||
return 0;
|
||||
|
||||
// end of the loop
|
||||
|
||||
+3
-4
@@ -413,9 +413,6 @@ void uwsgi_reload(char **argv) {
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef UWSGI_AS_SHARED_LIBRARY
|
||||
return;
|
||||
#else
|
||||
uwsgi_log("running %s\n", uwsgi.binary_path);
|
||||
uwsgi_flush_logs();
|
||||
argv[0] = uwsgi.binary_path;
|
||||
@@ -436,7 +433,6 @@ void uwsgi_reload(char **argv) {
|
||||
uwsgi_error("execvp()");
|
||||
// never here
|
||||
exit(1);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -957,6 +953,9 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
uc = uc->next;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_list_close(us))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
}
|
||||
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
|
||||
uWSGI metrics subsystem
|
||||
|
||||
a metric is a node in a tree reachable via a numeric id (OID, in SNMP way) or a simple string:
|
||||
|
||||
uwsgi.worker.1.requests
|
||||
uwsgi.custom.foo.bar
|
||||
|
||||
the oid representation:
|
||||
|
||||
1.3.6.1.4.1.35156.17 = iso.org.dod.internet.private.enterprise.unbit.uwsgi
|
||||
1.3.6.1.4.1.35156.17.3.1.1 = iso.org.dod.internet.private.enterprise.unbit.uwsgi.worker.1.requests
|
||||
1.3.6.1.4.1.35156.17.3.1.1 = iso.org.dod.internet.private.enterprise.unbit.uwsgi.worker.1.requests
|
||||
1.3.6.1.4.1.35156.17.3.1.2.1.1 = iso.org.dod.internet.private.enterprise.unbit.uwsgi.worker.1.core.1.requests
|
||||
1.3.6.1.4.1.35156.17.4.1 = iso.org.dod.internet.private.enterprise.unbit.uwsgi.system.load_avg
|
||||
...
|
||||
|
||||
each metric is a collected value with a specific frequency (a frequency of zero means the value is re-computed every time)
|
||||
metrics are meant for numeric values signed 64 bit, but they can be exposed as:
|
||||
|
||||
gauge
|
||||
counter
|
||||
absolute
|
||||
|
||||
both 32 and 64bit, both signed and unsigned
|
||||
|
||||
metrics are managed by a dedicated thread (in the master) holding a linked list of all the items. For few metrics it is a good (read: simple) approach,
|
||||
but you can cache lookups in a uWSGI cache for really big list.
|
||||
|
||||
struct uwsgi_metric *um = uwsgi_register_metric("worker.1.requests", "3.1.1", UWSGI_METRIC_COUNTER, UWSGI_METRIC_PTR, &uwsgi.workers[1].requests, 0, NULL);
|
||||
prototype: struct uwsgi_metric *uwsgi_register_metric(char *name, char *oid, uint8_t value_type, uint8_t collect_way, void *ptr, uint32_t freq, void *custom);
|
||||
|
||||
value_type = UWSGI_METRIC_COUNTER/UWSGI_METRIC_GAUGE/UWSGI_METRIC_ABSOLUTE
|
||||
collect_way = UWSGI_METRIC_PTR -> get from a pointer / UWSGI_METRIC_FUNC -> get from a func with the prototype int64_t func(struct uwsgi_metric *); / UWSGI_METRIC_FILE -> get the value from a file, ptr is the filename
|
||||
|
||||
when freq is zero the value is recomputed whenever requested, otherwise the metrics thread compute it every time the frequency is elapsed and caches it
|
||||
|
||||
For some metric (or all ?) you may want to hold a value even after a server reload. For such a reason you can specify a directory on wich the server (on startup/restart) will look for
|
||||
a file named like the metric and will read the initial value from it. It may look an old-fashioned and quite inefficient way, but it is the most versatile for a sysadmin (allowing him/her
|
||||
to even modify the values manually)
|
||||
|
||||
When registering a metric with the same name of an already registered one, the new one will overwrite the previous one. This allows plugins writer to override default behaviours
|
||||
|
||||
Applications are allowed to update metrics (but they cannot register new ones), with simple api funcs:
|
||||
|
||||
uwsgi.metric_set("worker.1.requests", N)
|
||||
uwsgi.metric_inc("worker.1.requests", N=1)
|
||||
uwsgi.metric_dec("worker.1.requests", N=1)
|
||||
uwsgi.metric_mul("worker.1.requests", N=1)
|
||||
uwsgi.metric_div("worker.1.requests", N=1)
|
||||
|
||||
and obviously they can get values:
|
||||
|
||||
uwsgi.metric_get("worker.1.requests", no_cache|force=False)
|
||||
if the second parameter is True, the value is recomputed (but if it is a metric with a cache, the cache value will not be updated accordingly, this is the job of the metric thread)
|
||||
|
||||
Updating metrics from your app MUST BE ATOMIC, for such a reason a uWSGI rwlock is initialized on startup and used for each operation (simple reading from a metric does not require locking)
|
||||
|
||||
Metrics can be updated from the internal routing subsystem too:
|
||||
|
||||
route-if = equal:${REQUEST_URI};/foobar metricinc:foobar.test 2
|
||||
|
||||
and can be accessed as ${metric[foobar.test]}
|
||||
|
||||
The stats server exports the metrics list in the "metrics" attribute (obviously some info could be redundant)
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_metric {
|
||||
char *name;
|
||||
char *oid;
|
||||
|
||||
// pre-computed snmp representation
|
||||
char *asn;
|
||||
size_t asn_size;
|
||||
|
||||
// ABSOLUTE/COUNTER/GAUGE
|
||||
uint8_t type;
|
||||
|
||||
// the value of the metric
|
||||
int64_t value;
|
||||
|
||||
// a custom blob you can attach to a metric
|
||||
void *custom;
|
||||
|
||||
// the collection frequency
|
||||
uint32_t freq;
|
||||
time_t last_update;
|
||||
|
||||
// run this function to collect the value
|
||||
int64_t (*collector)(struct uwsgi_metric *);
|
||||
// take the value from this pointer to a 64bit value
|
||||
int64_t *ptr;
|
||||
// get the initial value from this file, and store each update in it
|
||||
char *filename;
|
||||
|
||||
struct uwsgi_metric *next;
|
||||
};
|
||||
|
||||
struct uwsgi_metric *uwsgi_register_metric(char *name, char *oid, uint8_t value_type, uint8_t collect_way, void *ptr, uint32_t freq, void *custom) {
|
||||
struct uwsgi_metric *old_metric=NULL,*metric=uwsgi.metric;
|
||||
|
||||
while(metric) {
|
||||
metric = metric->next;
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_metric_loop() {
|
||||
// every second scan the whole metrics tree
|
||||
time_t now = uwsgi_now();
|
||||
}
|
||||
+6
-2
@@ -184,6 +184,7 @@ void uwsgi_mule_handler() {
|
||||
if (interesting_fd == uwsgi.signal_socket || interesting_fd == uwsgi.my_signal_socket || farm_has_signaled(interesting_fd)) {
|
||||
len = read(interesting_fd, &uwsgi_signal, 1);
|
||||
if (len <= 0) {
|
||||
if (len < 0 && (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)) continue;
|
||||
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
|
||||
end_me(0);
|
||||
}
|
||||
@@ -197,7 +198,9 @@ void uwsgi_mule_handler() {
|
||||
else if (interesting_fd == uwsgi.mules[uwsgi.muleid - 1].queue_pipe[1] || interesting_fd == uwsgi.shared->mule_queue_pipe[1] || farm_has_msg(interesting_fd)) {
|
||||
len = read(interesting_fd, message, 65536);
|
||||
if (len < 0) {
|
||||
uwsgi_error("read()");
|
||||
if (errno != EAGAIN && errno != EINTR && errno != EWOULDBLOCK) {
|
||||
uwsgi_error("uwsgi_mule_handler/read()");
|
||||
}
|
||||
}
|
||||
else {
|
||||
int i, found = 0;
|
||||
@@ -343,6 +346,7 @@ next:
|
||||
if (interesting_fd > -1) {
|
||||
len = read(interesting_fd, &uwsgi_signal, 1);
|
||||
if (len <= 0) {
|
||||
if (len < 0 && (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)) goto clear;
|
||||
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
|
||||
end_me(0);
|
||||
}
|
||||
@@ -350,7 +354,7 @@ next:
|
||||
uwsgi_log_verbose("master sent signal %d to mule %d\n", uwsgi_signal, uwsgi.muleid);
|
||||
#endif
|
||||
if (uwsgi_signal_handler(uwsgi_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.muleid);
|
||||
}
|
||||
// set the error condition
|
||||
len = -1;
|
||||
|
||||
+128
-4
@@ -2,7 +2,7 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
// this is line uwsgi_str_num but with security checks
|
||||
// this is like uwsgi_str_num but with security checks
|
||||
static size_t get_content_length(char *buf, uint16_t size) {
|
||||
int i;
|
||||
size_t val = 0;
|
||||
@@ -80,7 +80,7 @@ ssize_t send_udp_message(uint8_t modifier1, uint8_t modifier2, char *host, char
|
||||
ret = sendto(fd, (char *) uh, message_size + 4, 0, (struct sockaddr *) &un_addr, sizeof(un_addr));
|
||||
}
|
||||
if (ret < 0) {
|
||||
uwsgi_error("sendto()");
|
||||
uwsgi_error("send_udp_message()/sendto()");
|
||||
}
|
||||
close(fd);
|
||||
|
||||
@@ -303,8 +303,41 @@ static int uwsgi_proto_check_9(struct wsgi_request *wsgi_req, char *key, char *b
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uwsgi_parse_http_range(char *buf, uint16_t len, size_t *from, size_t *to) {
|
||||
*from = 0;
|
||||
*to = 0;
|
||||
uint16_t rlen = 0;
|
||||
uint16_t i;
|
||||
for(i=0;i<len;i++) {
|
||||
if (buf[i] == ',') break;
|
||||
rlen++;
|
||||
}
|
||||
|
||||
// bytes=X-
|
||||
if (rlen < 8) return;
|
||||
char *equal = memchr(buf, '=', rlen);
|
||||
if (!equal) return;
|
||||
if (equal-buf != 5) return;
|
||||
if (memcmp(buf, "bytes", 5)) return;
|
||||
char *range = equal+1;
|
||||
rlen -= 6;
|
||||
char *dash = memchr(range, '-', rlen);
|
||||
if (!dash) return;
|
||||
*from = uwsgi_str_num(range, dash-range);
|
||||
*to = uwsgi_str_num(dash+1, rlen - ((dash+1)-range));
|
||||
if (*to > 0 && *from > *to) {
|
||||
*from = 0;
|
||||
*to = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int uwsgi_proto_check_10(struct wsgi_request *wsgi_req, char *key, char *buf, uint16_t len) {
|
||||
|
||||
if (uwsgi.honour_range && !uwsgi_proto_key("HTTP_RANGE", 10)) {
|
||||
uwsgi_parse_http_range(buf, len, &wsgi_req->range_from, &wsgi_req->range_to);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!uwsgi_proto_key("UWSGI_FILE", 10)) {
|
||||
wsgi_req->file = buf;
|
||||
wsgi_req->file_len = len;
|
||||
@@ -312,6 +345,12 @@ static int uwsgi_proto_check_10(struct wsgi_request *wsgi_req, char *key, char *
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!uwsgi_proto_key("UWSGI_HOME", 10)) {
|
||||
wsgi_req->home = buf;
|
||||
wsgi_req->home_len = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -354,6 +393,13 @@ static int uwsgi_proto_check_11(struct wsgi_request *wsgi_req, char *key, char *
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!uwsgi_proto_key("HTTP_COOKIE", 11)) {
|
||||
wsgi_req->cookie = buf;
|
||||
wsgi_req->cookie_len = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (!uwsgi_proto_key("UWSGI_APPID", 11)) {
|
||||
wsgi_req->appid = buf;
|
||||
wsgi_req->appid_len = len;
|
||||
@@ -409,8 +455,8 @@ static int uwsgi_proto_check_12(struct wsgi_request *wsgi_req, char *key, char *
|
||||
}
|
||||
|
||||
if (!uwsgi_proto_key("UWSGI_PYHOME", 12)) {
|
||||
wsgi_req->pyhome = buf;
|
||||
wsgi_req->pyhome_len = len;
|
||||
wsgi_req->home = buf;
|
||||
wsgi_req->home_len = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -962,8 +1008,77 @@ int uwsgi_hooked_parse_array(char *buffer, size_t len, void (*hook) (uint16_t, c
|
||||
}
|
||||
|
||||
|
||||
// this functions transform a raw HTTP response to a uWSGI-managed response
|
||||
int uwsgi_blob_to_response(struct wsgi_request *wsgi_req, char *body, size_t len) {
|
||||
char *line = body;
|
||||
size_t line_len = 0;
|
||||
size_t i;
|
||||
int status_managed = 0;
|
||||
for(i=0;i<len;i++) {
|
||||
if (body[i] == '\n') {
|
||||
// invalid line
|
||||
if (line_len < 1) {
|
||||
return -1;
|
||||
}
|
||||
if (line[line_len-1] != '\r') {
|
||||
return -1;
|
||||
}
|
||||
// end of the headers
|
||||
if (line_len == 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (status_managed) {
|
||||
char *colon = memchr(line, ':', line_len-1);
|
||||
if (!colon) return -1;
|
||||
if (colon[1] != ' ') return -1;
|
||||
if (uwsgi_response_add_header(wsgi_req, line, colon-line, colon+2, (line_len-1) - ((colon+2)-line))) return -1;
|
||||
}
|
||||
else {
|
||||
char *space = memchr(line, ' ', line_len-1);
|
||||
if (!space) return -1;
|
||||
if ((line_len-1) - ((space+1)-line) < 3) return -1;
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, space+1, (line_len-1) - ((space+1)-line))) return -1;
|
||||
status_managed = 1;
|
||||
}
|
||||
line = NULL;
|
||||
line_len = 0;
|
||||
}
|
||||
else {
|
||||
if (!line) {
|
||||
line = body + i;
|
||||
}
|
||||
line_len++;
|
||||
}
|
||||
}
|
||||
|
||||
if ((i+1) < len) {
|
||||
if (uwsgi_response_write_body_do(wsgi_req, body + (i + 1), len-(i+1))) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
the following functions need to take in account that POST data could be already available in wsgi_req->buffer (generally when uwsgi protocol is in use)
|
||||
|
||||
In such a case, allocate a proto_parser_buf and move data there
|
||||
|
||||
*/
|
||||
|
||||
char *uwsgi_req_append(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, char *val, uint16_t vallen) {
|
||||
|
||||
if (!wsgi_req->proto_parser_buf) {
|
||||
if (wsgi_req->proto_parser_remains > 0) {
|
||||
wsgi_req->proto_parser_buf = uwsgi_malloc(wsgi_req->proto_parser_remains);
|
||||
memcpy(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_remains_buf, wsgi_req->proto_parser_remains);
|
||||
wsgi_req->proto_parser_remains_buf = wsgi_req->proto_parser_buf;
|
||||
}
|
||||
}
|
||||
|
||||
if ((wsgi_req->uh->pktsize + (2 + keylen + 2 + vallen)) > uwsgi.buffer_size) {
|
||||
uwsgi_log("not enough buffer space to add %.*s variable, consider increasing it with the --buffer-size option\n", keylen, key);
|
||||
return NULL;
|
||||
@@ -1001,6 +1116,15 @@ char *uwsgi_req_append(struct wsgi_request *wsgi_req, char *key, uint16_t keylen
|
||||
}
|
||||
|
||||
int uwsgi_req_append_path_info_with_index(struct wsgi_request *wsgi_req, char *index, uint16_t index_len) {
|
||||
|
||||
if (!wsgi_req->proto_parser_buf) {
|
||||
if (wsgi_req->proto_parser_remains > 0) {
|
||||
wsgi_req->proto_parser_buf = uwsgi_malloc(wsgi_req->proto_parser_remains);
|
||||
memcpy(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_remains_buf, wsgi_req->proto_parser_remains);
|
||||
wsgi_req->proto_parser_remains_buf = wsgi_req->proto_parser_buf;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t need_slash = 0;
|
||||
if (wsgi_req->path_info_len > 0) {
|
||||
if (wsgi_req->path_info[wsgi_req->path_info_len-1] != '/') {
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
QUERY_STRING management functions (mainly used by the internal routing subsystem)
|
||||
|
||||
*/
|
||||
|
||||
static char *check_qs(char *qs, uint16_t qs_len, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
// search for the equal sign
|
||||
char *equal = memchr(qs, '=', qs_len);
|
||||
if (!equal) return NULL;
|
||||
|
||||
if (uwsgi_strncmp(key, keylen, qs, equal-qs)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qs_len -= (equal-qs)+1;
|
||||
if (qs_len == 0) return NULL;
|
||||
|
||||
*vallen = qs_len;
|
||||
return equal+1;
|
||||
}
|
||||
|
||||
char *uwsgi_get_qs(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
uint16_t i;
|
||||
|
||||
char *qs = wsgi_req->query_string;
|
||||
uint16_t qs_len = 0;
|
||||
char *ptr = wsgi_req->query_string;
|
||||
//start splitting by ;
|
||||
for(i=0;i<wsgi_req->query_string_len;i++) {
|
||||
if (!qs) {
|
||||
qs = ptr + i;
|
||||
}
|
||||
if (ptr[i] == '&') {
|
||||
char *value = check_qs(qs, qs_len, key, keylen, vallen);
|
||||
if (value) {
|
||||
return value;
|
||||
}
|
||||
qs_len = 0;
|
||||
qs = NULL;
|
||||
}
|
||||
else {
|
||||
qs_len++;
|
||||
}
|
||||
}
|
||||
|
||||
if (qs_len > 0) {
|
||||
char *value = check_qs(qs, qs_len, key, keylen, vallen);
|
||||
if (value) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
+15
-15
@@ -47,7 +47,7 @@ void uwsgi_request_body_seek(struct wsgi_request *wsgi_req, off_t pos) {
|
||||
|
||||
if (uwsgi.post_buffering) {
|
||||
if (pos < 0) {
|
||||
if (pos > (off_t) wsgi_req->post_pos) {
|
||||
if ((off_t) wsgi_req->post_pos - pos < 0) {
|
||||
wsgi_req->post_pos = 0;
|
||||
return;
|
||||
}
|
||||
@@ -108,64 +108,65 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
}
|
||||
|
||||
remains = UMIN(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark, wsgi_req->post_cl - wsgi_req->post_pos);
|
||||
|
||||
// read from a file
|
||||
if (wsgi_req->post_file) {
|
||||
size_t ret = fread(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, wsgi_req->post_readline_size - wsgi_req->post_readline_watermark, 1, wsgi_req->post_file);
|
||||
size_t ret = fread(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, remains, 1, wsgi_req->post_file);
|
||||
if (ret == 0) {
|
||||
uwsgi_error("consume_body_for_readline()/fread()");
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->post_pos += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
|
||||
wsgi_req->post_readline_watermark += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
|
||||
wsgi_req->post_pos += remains;
|
||||
wsgi_req->post_readline_watermark += remains;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// read from post_buffering memory
|
||||
if (uwsgi.post_buffering) {
|
||||
wsgi_req->post_pos += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
|
||||
memcpy(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, wsgi_req->post_buffering_buf + wsgi_req->post_pos, wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
wsgi_req->post_readline_watermark += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
|
||||
memcpy(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, wsgi_req->post_buffering_buf + wsgi_req->post_pos, remains);
|
||||
wsgi_req->post_pos += remains;
|
||||
wsgi_req->post_readline_watermark += remains;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// read from socket
|
||||
ssize_t len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
ssize_t len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , remains);
|
||||
if (len > 0) {
|
||||
wsgi_req->post_pos += len;
|
||||
wsgi_req->post_readline_watermark += len;
|
||||
return 0;
|
||||
}
|
||||
if (len == 0) {
|
||||
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
uwsgi_read_error(remains);
|
||||
return -1;
|
||||
}
|
||||
if (len < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
goto wait;
|
||||
}
|
||||
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
uwsgi_read_error(remains);
|
||||
return -1;
|
||||
}
|
||||
wait:
|
||||
ret = uwsgi_wait_read_req(wsgi_req);
|
||||
if (ret > 0) {
|
||||
len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , remains);
|
||||
if (len > 0) {
|
||||
wsgi_req->post_pos += len;
|
||||
wsgi_req->post_readline_watermark += len;
|
||||
return 0;
|
||||
}
|
||||
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
uwsgi_read_error(remains);
|
||||
return -1;
|
||||
}
|
||||
// 0 means timeout
|
||||
else if (ret == 0) {
|
||||
uwsgi_read_timeout(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
uwsgi_read_timeout(remains);
|
||||
return -1;
|
||||
}
|
||||
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
uwsgi_read_error(remains);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -347,7 +348,6 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
|
||||
if (wsgi_req->post_file) {
|
||||
if (fread(wsgi_req->post_read_buf + *rlen, remains, 1, wsgi_req->post_file) != 1) {
|
||||
*rlen = -1;
|
||||
uwsgi_log("%llu\n", remains);
|
||||
uwsgi_error("uwsgi_request_body_read()/fread()");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+577
-5
@@ -3,6 +3,43 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_route_var *uwsgi_register_route_var(char *name, char *(*func)(struct wsgi_request *, char *, uint16_t, uint16_t *)) {
|
||||
|
||||
struct uwsgi_route_var *old_urv = NULL,*urv = uwsgi.route_vars;
|
||||
while(urv) {
|
||||
if (!strcmp(urv->name, name)) {
|
||||
return urv;
|
||||
}
|
||||
old_urv = urv;
|
||||
urv = urv->next;
|
||||
}
|
||||
|
||||
urv = uwsgi_calloc(sizeof(struct uwsgi_route_var));
|
||||
urv->name = name;
|
||||
urv->name_len = strlen(name);
|
||||
urv->func = func;
|
||||
|
||||
if (old_urv) {
|
||||
old_urv->next = urv;
|
||||
}
|
||||
else {
|
||||
uwsgi.route_vars = urv;
|
||||
}
|
||||
|
||||
return urv;
|
||||
}
|
||||
|
||||
struct uwsgi_route_var *uwsgi_get_route_var(char *name, uint16_t name_len) {
|
||||
struct uwsgi_route_var *urv = uwsgi.route_vars;
|
||||
while(urv) {
|
||||
if (!uwsgi_strncmp(urv->name, urv->name_len, name, name_len)) {
|
||||
return urv;
|
||||
}
|
||||
urv = urv->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *uwsgi_routing_translate(struct wsgi_request *wsgi_req, struct uwsgi_route *ur, char *subject, uint16_t subject_len, char *data, size_t data_len) {
|
||||
|
||||
char *pass1 = data;
|
||||
@@ -44,9 +81,32 @@ struct uwsgi_buffer *uwsgi_routing_translate(struct wsgi_request *wsgi_req, stru
|
||||
case 2:
|
||||
if (pass1[i] == '}') {
|
||||
uint16_t vallen = 0;
|
||||
char *value = uwsgi_get_var(wsgi_req, key, keylen, &vallen);
|
||||
int need_free = 0;
|
||||
char *value = NULL;
|
||||
char *bracket = memchr(key, '[', keylen);
|
||||
if (bracket && keylen > 0 && key[keylen-1] == ']') {
|
||||
struct uwsgi_route_var *urv = uwsgi_get_route_var(key, bracket - key);
|
||||
if (urv) {
|
||||
need_free = urv->need_free;
|
||||
value = urv->func(wsgi_req, bracket + 1, keylen - (urv->name_len+2), &vallen);
|
||||
}
|
||||
else {
|
||||
value = uwsgi_get_var(wsgi_req, key, keylen, &vallen);
|
||||
}
|
||||
}
|
||||
else {
|
||||
value = uwsgi_get_var(wsgi_req, key, keylen, &vallen);
|
||||
}
|
||||
if (value) {
|
||||
if (uwsgi_buffer_append(ub, value, vallen)) goto error;
|
||||
if (uwsgi_buffer_append(ub, value, vallen)) {
|
||||
if (need_free) {
|
||||
free(value);
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
if (need_free) {
|
||||
free(value);
|
||||
}
|
||||
}
|
||||
status = 0;
|
||||
key = NULL;
|
||||
@@ -97,6 +157,8 @@ int uwsgi_apply_routes_do(struct wsgi_request *wsgi_req, char *subject, uint16_t
|
||||
|
||||
while (routes) {
|
||||
|
||||
if (routes->label) goto next;
|
||||
|
||||
if (wsgi_req->route_goto > 0 && wsgi_req->route_pc < wsgi_req->route_goto) {
|
||||
goto next;
|
||||
}
|
||||
@@ -108,6 +170,11 @@ int uwsgi_apply_routes_do(struct wsgi_request *wsgi_req, char *subject, uint16_t
|
||||
wsgi_req->route_goto = 0;
|
||||
|
||||
if (!routes->if_func) {
|
||||
// could be a "run"
|
||||
if (!routes->subject) {
|
||||
n = 0;
|
||||
goto run;
|
||||
}
|
||||
if (!subject) {
|
||||
char **subject2 = (char **) (((char *) (wsgi_req)) + routes->subject);
|
||||
uint16_t *subject_len2 = (uint16_t *) (((char *) (wsgi_req)) + routes->subject_len);
|
||||
@@ -137,6 +204,7 @@ int uwsgi_apply_routes_do(struct wsgi_request *wsgi_req, char *subject, uint16_t
|
||||
}
|
||||
}
|
||||
|
||||
run:
|
||||
if (n >= 0) {
|
||||
wsgi_req->is_routing = 1;
|
||||
int ret = routes->func(wsgi_req, routes);
|
||||
@@ -152,6 +220,10 @@ int uwsgi_apply_routes_do(struct wsgi_request *wsgi_req, char *subject, uint16_t
|
||||
if (ret == UWSGI_ROUTE_GOON) {
|
||||
goon_func = routes->func;
|
||||
}
|
||||
|
||||
if (ret == -1) {
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
}
|
||||
next:
|
||||
subject = orig_subject;
|
||||
@@ -176,7 +248,7 @@ int uwsgi_apply_routes(struct wsgi_request *wsgi_req) {
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
// in case ogf static files serving previous rules could be applied
|
||||
// in case of static files serving previous rules could be applied
|
||||
if (wsgi_req->routes_applied) {
|
||||
return UWSGI_ROUTE_CONTINUE;
|
||||
}
|
||||
@@ -197,6 +269,8 @@ static void *uwsgi_route_get_condition_func(char *name) {
|
||||
|
||||
void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
|
||||
|
||||
char *space = NULL;
|
||||
char *command = NULL;
|
||||
struct uwsgi_route *old_ur = NULL,*ur = uwsgi.routes;
|
||||
uint64_t pos = 0;
|
||||
while(ur) {
|
||||
@@ -223,7 +297,12 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
|
||||
|
||||
char *route = uwsgi_str(value);
|
||||
|
||||
char *space = strchr(route, ' ');
|
||||
if (!strcmp(foobar, "run")) {
|
||||
command = route;
|
||||
goto done;
|
||||
}
|
||||
|
||||
space = strchr(route, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid route syntax\n");
|
||||
exit(1);
|
||||
@@ -299,7 +378,8 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
|
||||
}
|
||||
}
|
||||
|
||||
char *command = space + 1;
|
||||
command = space + 1;
|
||||
done:
|
||||
ur->action = uwsgi_str(command);
|
||||
|
||||
char *colon = strchr(command, ':');
|
||||
@@ -585,6 +665,153 @@ static int uwsgi_router_signal(struct uwsgi_route *ur, char *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// chdir route
|
||||
static int uwsgi_router_chdir_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
||||
if (!ub) return UWSGI_ROUTE_BREAK;
|
||||
if (chdir(ub->buf)) {
|
||||
uwsgi_error("uwsgi_router_chdir_func()/chdir()");
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_chdir(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_chdir_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// setapp route
|
||||
static int uwsgi_router_setapp_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
||||
if (!ub) return UWSGI_ROUTE_BREAK;
|
||||
char *ptr = uwsgi_req_append(wsgi_req, "UWSGI_APPID", 11, ub->buf, ub->pos);
|
||||
if (!ptr) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
wsgi_req->appid = ptr;
|
||||
wsgi_req->appid_len = ub->pos;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_setapp(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_setapp_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// sethome route
|
||||
static int uwsgi_router_sethome_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
||||
if (!ub) return UWSGI_ROUTE_BREAK;
|
||||
char *ptr = uwsgi_req_append(wsgi_req, "UWSGI_HOME", 10, ub->buf, ub->pos);
|
||||
if (!ptr) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
wsgi_req->home = ptr;
|
||||
wsgi_req->home_len = ub->pos;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_sethome(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_sethome_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// setfile route
|
||||
static int uwsgi_router_setfile_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
||||
if (!ub) return UWSGI_ROUTE_BREAK;
|
||||
char *ptr = uwsgi_req_append(wsgi_req, "UWSGI_HOME", 10, ub->buf, ub->pos);
|
||||
if (!ptr) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
wsgi_req->file = ptr;
|
||||
wsgi_req->file_len = ub->pos;
|
||||
wsgi_req->dynamic = 1;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_setfile(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_setfile_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// setprocname route
|
||||
static int uwsgi_router_setprocname_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
||||
if (!ub) return UWSGI_ROUTE_BREAK;
|
||||
uwsgi_set_processname(ub->buf);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_setprocname(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_setprocname_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// alarm route
|
||||
static int uwsgi_router_alarm_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
struct uwsgi_buffer *ub_alarm = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
||||
if (!ub_alarm) return UWSGI_ROUTE_BREAK;
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data2, ur->data2_len);
|
||||
if (!ub) {
|
||||
uwsgi_buffer_destroy(ub_alarm);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
uwsgi_alarm_trigger(ub_alarm->buf, ub->buf, ub->pos);
|
||||
uwsgi_buffer_destroy(ub_alarm);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_alarm(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_alarm_func;
|
||||
char *space = strchr(arg, ' ');
|
||||
if (!space) {
|
||||
return -1;
|
||||
}
|
||||
*space = 0;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
ur->data2 = space+1;
|
||||
ur->data2_len = strlen(ur->data2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// send route
|
||||
static int uwsgi_router_send_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
|
||||
@@ -628,6 +855,246 @@ static int uwsgi_route_condition_isfile(struct wsgi_request *wsgi_req, struct uw
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_route_condition_regexp(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
|
||||
if (!semicolon) return 0;
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
|
||||
if (!ub) return -1;
|
||||
|
||||
pcre *pattern;
|
||||
pcre_extra *pattern_extra;
|
||||
char *re = uwsgi_concat2n(semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str), "", 0);
|
||||
if (uwsgi_regexp_build(re, &pattern, &pattern_extra)) {
|
||||
free(re);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return -1;
|
||||
}
|
||||
free(re);
|
||||
|
||||
if (uwsgi_regexp_match(pattern, pattern_extra, ub->buf, ub->pos) >= 0) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
pcre_free(pattern);
|
||||
#ifdef PCRE_STUDY_JIT_COMPILE
|
||||
pcre_free_study(pattern_extra);
|
||||
#else
|
||||
pcre_free(pattern_extra);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
uwsgi_buffer_destroy(ub);
|
||||
pcre_free(pattern);
|
||||
#ifdef PCRE_STUDY_JIT_COMPILE
|
||||
pcre_free_study(pattern_extra);
|
||||
#else
|
||||
pcre_free(pattern_extra);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_route_condition_empty(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, ur->subject_str_len);
|
||||
if (!ub) return -1;
|
||||
|
||||
if (ub->pos == 0) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_route_condition_equal(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
|
||||
if (!semicolon) return 0;
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
|
||||
if (!ub) return -1;
|
||||
|
||||
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
|
||||
if (!ub2) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!uwsgi_strncmp(ub->buf, ub->pos, ub2->buf, ub2->pos)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 1;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_route_condition_higher(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
|
||||
if (!semicolon) return 0;
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
|
||||
if (!ub) return -1;
|
||||
|
||||
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
|
||||
if (!ub2) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return -1;
|
||||
}
|
||||
|
||||
long num1 = strtol(ub->buf, NULL, 10);
|
||||
long num2 = strtol(ub2->buf, NULL, 10);
|
||||
if(num1 > num2) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 1;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_route_condition_higherequal(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
|
||||
if (!semicolon) return 0;
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
|
||||
if (!ub) return -1;
|
||||
|
||||
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
|
||||
if (!ub2) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return -1;
|
||||
}
|
||||
|
||||
long num1 = strtol(ub->buf, NULL, 10);
|
||||
long num2 = strtol(ub2->buf, NULL, 10);
|
||||
if(num1 >= num2) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 1;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_route_condition_lower(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
|
||||
if (!semicolon) return 0;
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
|
||||
if (!ub) return -1;
|
||||
|
||||
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
|
||||
if (!ub2) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return -1;
|
||||
}
|
||||
|
||||
long num1 = strtol(ub->buf, NULL, 10);
|
||||
long num2 = strtol(ub2->buf, NULL, 10);
|
||||
if(num1 < num2) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 1;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_route_condition_lowerequal(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
|
||||
if (!semicolon) return 0;
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
|
||||
if (!ub) return -1;
|
||||
|
||||
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
|
||||
if (!ub2) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return -1;
|
||||
}
|
||||
|
||||
long num1 = strtol(ub->buf, NULL, 10);
|
||||
long num2 = strtol(ub2->buf, NULL, 10);
|
||||
if(num1 <= num2) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 1;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
static int uwsgi_route_condition_lord(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, ur->subject_str_len);
|
||||
if (!ub) return -1;
|
||||
int ret = uwsgi_legion_i_am_the_lord(ub->buf);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static int uwsgi_route_condition_startswith(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
|
||||
if (!semicolon) return 0;
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
|
||||
if (!ub) return -1;
|
||||
|
||||
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
|
||||
if (!ub2) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!uwsgi_starts_with(ub->buf, ub->pos, ub2->buf, ub2->pos)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 1;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_route_condition_endswith(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
|
||||
if (!semicolon) return 0;
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
|
||||
if (!ub) return -1;
|
||||
|
||||
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
|
||||
if (!ub2) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ub2->pos < ub->pos) goto zero;
|
||||
if(!uwsgi_strncmp(ub->buf + (ub->pos - ub2->pos), ub2->pos, ub2->buf, ub2->pos)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
zero:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int uwsgi_route_condition_isdir(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, ur->subject_str_len);
|
||||
if (!ub) return -1;
|
||||
@@ -662,6 +1129,70 @@ static int uwsgi_route_condition_isexec(struct wsgi_request *wsgi_req, struct uw
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *uwsgi_route_var_uwsgi(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
char *ret = NULL;
|
||||
if (!uwsgi_strncmp(key, keylen, "wid", 3)) {
|
||||
ret = uwsgi_num2str(uwsgi.mywid);
|
||||
*vallen = strlen(ret);
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "pid", 3)) {
|
||||
ret = uwsgi_num2str(uwsgi.mypid);
|
||||
*vallen = strlen(ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *uwsgi_route_var_time(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
char *ret = NULL;
|
||||
if (!uwsgi_strncmp(key, keylen, "unix", 4)) {
|
||||
ret = uwsgi_num2str(uwsgi_now());
|
||||
*vallen = strlen(ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_MATHEVAL
|
||||
static char *uwsgi_route_var_math(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
char *ret = NULL;
|
||||
// avoid crash
|
||||
if (!wsgi_req->var_cnt) return NULL;
|
||||
// we make a bit of fun here, we do a copy of the vars buffer (+1 byte for final zero) and zeor-pad all of the strings
|
||||
char *vars_buf = uwsgi_malloc(wsgi_req->uh->pktsize + keylen + 1);
|
||||
char **names = uwsgi_malloc(sizeof(char *) * (wsgi_req->var_cnt/2));
|
||||
double *values = uwsgi_calloc(sizeof(double) * (wsgi_req->var_cnt/2));
|
||||
int i,j = 0;
|
||||
char *ptr = vars_buf;
|
||||
for (i = wsgi_req->var_cnt-1; i > 0; i -= 2) {
|
||||
memcpy(ptr, wsgi_req->hvec[i-1].iov_base, wsgi_req->hvec[i-1].iov_len);
|
||||
names[j] = ptr;
|
||||
ptr += wsgi_req->hvec[i-1].iov_len;
|
||||
*ptr++=0;
|
||||
char *num = ptr;
|
||||
memcpy(ptr, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
|
||||
ptr += wsgi_req->hvec[i].iov_len;
|
||||
*ptr++=0;
|
||||
values[j] = strtod(num, NULL);
|
||||
j++;
|
||||
}
|
||||
|
||||
char *expr = ptr;
|
||||
memcpy(ptr, key, keylen); ptr += keylen;
|
||||
*ptr++=0;
|
||||
|
||||
void *e = evaluator_create(expr);
|
||||
if (!e) goto end;
|
||||
double n = evaluator_evaluate(e, j, names, values);
|
||||
evaluator_destroy(e);
|
||||
ret = uwsgi_num2str((int)n);
|
||||
*vallen = strlen(ret);
|
||||
end:
|
||||
free(vars_buf);
|
||||
free(names);
|
||||
free(values);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
// register embedded routers
|
||||
void uwsgi_register_embedded_routers() {
|
||||
@@ -679,12 +1210,50 @@ void uwsgi_register_embedded_routers() {
|
||||
uwsgi_register_router("signal", uwsgi_router_signal);
|
||||
uwsgi_register_router("send", uwsgi_router_send);
|
||||
uwsgi_register_router("send-crnl", uwsgi_router_send_crnl);
|
||||
uwsgi_register_router("chdir", uwsgi_router_chdir);
|
||||
uwsgi_register_router("setapp", uwsgi_router_setapp);
|
||||
uwsgi_register_router("sethome", uwsgi_router_sethome);
|
||||
uwsgi_register_router("setfile", uwsgi_router_setfile);
|
||||
uwsgi_register_router("setprocname", uwsgi_router_setprocname);
|
||||
uwsgi_register_router("alarm", uwsgi_router_alarm);
|
||||
|
||||
uwsgi_register_route_condition("exists", uwsgi_route_condition_exists);
|
||||
uwsgi_register_route_condition("isfile", uwsgi_route_condition_isfile);
|
||||
uwsgi_register_route_condition("isdir", uwsgi_route_condition_isdir);
|
||||
uwsgi_register_route_condition("islink", uwsgi_route_condition_islink);
|
||||
uwsgi_register_route_condition("isexec", uwsgi_route_condition_isexec);
|
||||
uwsgi_register_route_condition("equal", uwsgi_route_condition_equal);
|
||||
uwsgi_register_route_condition("isequal", uwsgi_route_condition_equal);
|
||||
uwsgi_register_route_condition("eq", uwsgi_route_condition_equal);
|
||||
uwsgi_register_route_condition("==", uwsgi_route_condition_equal);
|
||||
uwsgi_register_route_condition("startswith", uwsgi_route_condition_startswith);
|
||||
uwsgi_register_route_condition("endswith", uwsgi_route_condition_endswith);
|
||||
uwsgi_register_route_condition("regexp", uwsgi_route_condition_regexp);
|
||||
uwsgi_register_route_condition("re", uwsgi_route_condition_regexp);
|
||||
uwsgi_register_route_condition("ishigher", uwsgi_route_condition_higher);
|
||||
uwsgi_register_route_condition(">", uwsgi_route_condition_higher);
|
||||
uwsgi_register_route_condition("islower", uwsgi_route_condition_lower);
|
||||
uwsgi_register_route_condition("<", uwsgi_route_condition_lower);
|
||||
uwsgi_register_route_condition("ishigherequal", uwsgi_route_condition_higherequal);
|
||||
uwsgi_register_route_condition(">=", uwsgi_route_condition_higherequal);
|
||||
uwsgi_register_route_condition("islowerequal", uwsgi_route_condition_lowerequal);
|
||||
uwsgi_register_route_condition("<=", uwsgi_route_condition_lowerequal);
|
||||
#ifdef UWSGI_SSL
|
||||
uwsgi_register_route_condition("lord", uwsgi_route_condition_lord);
|
||||
#endif
|
||||
|
||||
uwsgi_register_route_condition("empty", uwsgi_route_condition_empty);
|
||||
|
||||
uwsgi_register_route_var("cookie", uwsgi_get_cookie);
|
||||
uwsgi_register_route_var("qs", uwsgi_get_qs);
|
||||
struct uwsgi_route_var *urv = uwsgi_register_route_var("uwsgi", uwsgi_route_var_uwsgi);
|
||||
urv->need_free = 1;
|
||||
urv = uwsgi_register_route_var("time", uwsgi_route_var_time);
|
||||
urv->need_free = 1;
|
||||
#ifdef UWSGI_MATHEVAL
|
||||
urv = uwsgi_register_route_var("math", uwsgi_route_var_math);
|
||||
urv->need_free = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
struct uwsgi_router *uwsgi_register_router(char *name, int (*func) (struct uwsgi_route *, char *)) {
|
||||
@@ -743,6 +1312,9 @@ void uwsgi_routing_dump() {
|
||||
if (routes->label) {
|
||||
uwsgi_log("[rule: %llu] label: %s\n", (unsigned long long ) routes->pos, routes->label);
|
||||
}
|
||||
else if (!routes->subject_str && !routes->if_func) {
|
||||
uwsgi_log("[rule: %llu] action: %s\n", (unsigned long long ) routes->pos, routes->action);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[rule: %llu] subject: %s %s: %s%s action: %s\n", (unsigned long long ) routes->pos, routes->subject_str, routes->if_func ? "func" : "regexp", routes->if_negate ? "!" : "", routes->regexp, routes->action);
|
||||
}
|
||||
|
||||
@@ -123,6 +123,16 @@ void uwsgi_setup_inherited_sockets() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (uwsgi.shared->worker_req_log_pipe[0] > -1) {
|
||||
if (j == uwsgi.shared->worker_req_log_pipe[0])
|
||||
continue;
|
||||
}
|
||||
|
||||
if (uwsgi.shared->worker_req_log_pipe[1] > -1) {
|
||||
if (j == uwsgi.shared->worker_req_log_pipe[1])
|
||||
continue;
|
||||
}
|
||||
|
||||
if (uwsgi.original_log_fd > -1) {
|
||||
if (j == uwsgi.original_log_fd)
|
||||
continue;
|
||||
|
||||
+4
-83
@@ -137,7 +137,7 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
|
||||
int i;
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
int pos = (i * 256);
|
||||
memcpy(&uwsgi.shared->signal_table[pos], use, sizeof(struct uwsgi_signal_entry) * 256);
|
||||
memcpy(&uwsgi.shared->signal_table[pos], &uwsgi.shared->signal_table[0], sizeof(struct uwsgi_signal_entry) * 256);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,89 +177,10 @@ int uwsgi_add_file_monitor(uint8_t sig, char *filename) {
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_probe *uwsgi_probe_register(struct uwsgi_probe **up, char *name, int (*func) (int, struct uwsgi_signal_probe *)) {
|
||||
|
||||
struct uwsgi_probe *uwsgi_up = *up, *old_up;
|
||||
|
||||
if (!uwsgi_up) {
|
||||
*up = uwsgi_malloc(sizeof(struct uwsgi_probe));
|
||||
uwsgi_up = *up;
|
||||
}
|
||||
else {
|
||||
while (uwsgi_up) {
|
||||
old_up = uwsgi_up;
|
||||
uwsgi_up = uwsgi_up->next;
|
||||
}
|
||||
|
||||
uwsgi_up = uwsgi_malloc(sizeof(struct uwsgi_probe));
|
||||
old_up->next = uwsgi_up;
|
||||
}
|
||||
|
||||
uwsgi_up->name = name;
|
||||
uwsgi_up->func = func;
|
||||
uwsgi_up->next = NULL;
|
||||
|
||||
uwsgi_log("registered new probe \"%s\" at %p\n", name, uwsgi_up);
|
||||
|
||||
return uwsgi_up;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_add_probe(uint8_t sig, char *kind, char *args, int timeout, int freq) {
|
||||
|
||||
uwsgi_lock(uwsgi.probe_table_lock);
|
||||
|
||||
if (ushared->probes_cnt < MAX_PROBES) {
|
||||
|
||||
struct uwsgi_probe *up = uwsgi.probes;
|
||||
while (up) {
|
||||
if (!strcmp(up->name, kind)) {
|
||||
break;
|
||||
}
|
||||
up = up->next;
|
||||
}
|
||||
|
||||
if (!up) {
|
||||
uwsgi_log("unable to find probe \"%s\" !!!\n", kind);
|
||||
uwsgi_unlock(uwsgi.probe_table_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// fill the probe table
|
||||
ushared->probes[ushared->probes_cnt].func = up->func;
|
||||
strncpy(ushared->probes[ushared->probes_cnt].args, args, 1024 - 1);
|
||||
ushared->probes[ushared->probes_cnt].registered = 0;
|
||||
ushared->probes[ushared->probes_cnt].sig = sig;
|
||||
ushared->probes[ushared->probes_cnt].fd = -1;
|
||||
ushared->probes[ushared->probes_cnt].state = 0;
|
||||
ushared->probes[ushared->probes_cnt].last_event = 0;
|
||||
ushared->probes[ushared->probes_cnt].data = NULL;
|
||||
ushared->probes[ushared->probes_cnt].cycles = 0;
|
||||
ushared->probes[ushared->probes_cnt].bad = 0;
|
||||
|
||||
if (!timeout) {
|
||||
timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
|
||||
}
|
||||
ushared->probes[ushared->probes_cnt].timeout = timeout;
|
||||
if (!freq) {
|
||||
freq = 1;
|
||||
}
|
||||
ushared->probes[ushared->probes_cnt].freq = freq;
|
||||
ushared->probes_cnt++;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("you can register max %d probes !!!\n", MAX_PROBES);
|
||||
uwsgi_unlock(uwsgi.probe_table_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_unlock(uwsgi.probe_table_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_add_timer(uint8_t sig, int secs) {
|
||||
|
||||
if (!uwsgi.master_process) return -1;
|
||||
|
||||
uwsgi_lock(uwsgi.timer_table_lock);
|
||||
|
||||
if (ushared->timers_cnt < 64) {
|
||||
@@ -595,7 +516,7 @@ void uwsgi_receive_signal(int fd, char *name, int id) {
|
||||
if (ret == 0) {
|
||||
goto destroy;
|
||||
}
|
||||
else if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
|
||||
else if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) {
|
||||
uwsgi_error("[uwsgi-signal] read()");
|
||||
goto destroy;
|
||||
}
|
||||
|
||||
+69
-1
@@ -2,6 +2,23 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
static int uwsgi_socket_strcmp(char *sock1, char *sock2) {
|
||||
size_t sock1_len = strlen(sock1);
|
||||
size_t sock2_len = strlen(sock2);
|
||||
|
||||
if (!uwsgi_starts_with(sock1, sock1_len, "0.0.0.0:", 8)) {
|
||||
sock1 += 7;
|
||||
sock1_len = strlen(sock1);
|
||||
}
|
||||
|
||||
if (!uwsgi_starts_with(sock2, sock2_len, "0.0.0.0:", 8)) {
|
||||
sock2 += 7;
|
||||
sock2_len = strlen(sock2);
|
||||
}
|
||||
|
||||
return uwsgi_strncmp(sock1, sock1_len, sock2, sock2_len);
|
||||
}
|
||||
|
||||
char *uwsgi_getsockname(int fd) {
|
||||
|
||||
socklen_t socket_type_len = sizeof(struct sockaddr_un);
|
||||
@@ -49,6 +66,7 @@ int bind_to_unix_dgram(char *socket_name) {
|
||||
if (serverfd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (unlink(socket_name) != 0 && errno != ENOENT) {
|
||||
@@ -68,6 +86,7 @@ int bind_to_unix_dgram(char *socket_name) {
|
||||
#endif
|
||||
uwsgi_error("bind()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return serverfd;
|
||||
@@ -83,6 +102,7 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
if (strlen(socket_name) > 102) {
|
||||
uwsgi_log("invalid socket name\n");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (socket_name[0] == '@') {
|
||||
@@ -96,6 +116,7 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
if (uws_addr == NULL) {
|
||||
uwsgi_error("malloc()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(uws_addr, 0, sizeof(struct sockaddr_un));
|
||||
@@ -103,6 +124,7 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
if (serverfd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
if (abstract_socket == 0) {
|
||||
if (unlink(socket_name) != 0 && errno != ENOENT) {
|
||||
@@ -114,6 +136,24 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
uwsgi_log("setting abstract socket mode (warning: only Linux supports this)\n");
|
||||
}
|
||||
|
||||
if (uwsgi.so_sndbuf) {
|
||||
socklen_t sndbuf = (socklen_t) uwsgi.so_sndbuf;
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(socklen_t)) < 0) {
|
||||
uwsgi_error("SO_SNDBUF setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.so_rcvbuf) {
|
||||
socklen_t rcvbuf = (socklen_t) uwsgi.so_rcvbuf;
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(socklen_t)) < 0) {
|
||||
uwsgi_error("SO_RCVBUF setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
uws_addr->sun_family = AF_UNIX;
|
||||
if (socket_name[0] == '@') {
|
||||
memcpy(uws_addr->sun_path + abstract_socket, socket_name + 1, UMIN(strlen(socket_name + 1), 101));
|
||||
@@ -140,12 +180,14 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
#endif
|
||||
uwsgi_error("bind()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (listen(serverfd, listen_queue) != 0) {
|
||||
uwsgi_error("listen()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// chmod unix socket for lazy users
|
||||
@@ -561,11 +603,31 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
if (serverfd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uwsgi.so_sndbuf) {
|
||||
socklen_t sndbuf = (socklen_t) uwsgi.so_sndbuf;
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(socklen_t)) < 0) {
|
||||
uwsgi_error("SO_SNDBUF setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.so_rcvbuf) {
|
||||
socklen_t rcvbuf = (socklen_t) uwsgi.so_rcvbuf;
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(socklen_t)) < 0) {
|
||||
uwsgi_error("SO_RCVBUF setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) {
|
||||
uwsgi_error("SO_REUSEADDR setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
@@ -576,6 +638,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
if (setsockopt(serverfd, SOL_IP, IP_FREEBIND, (const void *) &uwsgi.freebind, sizeof(int)) < 0) {
|
||||
uwsgi_error("IP_FREEBIND setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -585,6 +648,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEPORT, (const void *) &uwsgi.reuse_port, sizeof(int)) < 0) {
|
||||
uwsgi_error("SO_REUSEPORT setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
uwsgi_log("!!! your system does not support SO_REUSEPORT !!!\n");
|
||||
@@ -611,6 +675,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_SNDTIMEO, (const void *) &tv, sizeof(struct timeval)) < 0) {
|
||||
uwsgi_error("SO_SNDTIMEO setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -645,6 +710,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
}
|
||||
uwsgi_error("bind()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
@@ -652,12 +718,14 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
if (somaxconn > 0 && uwsgi.listen_queue > somaxconn) {
|
||||
uwsgi_log("Listen queue size is greater than the system max net.core.somaxconn (%li).\n", somaxconn);
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (listen(serverfd, listen_queue) != 0) {
|
||||
uwsgi_error("listen()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1476,7 +1544,7 @@ void uwsgi_setup_shared_sockets() {
|
||||
for (i = 3; i < (int) uwsgi.max_fd; i++) {
|
||||
char *sock = uwsgi_getsockname(i);
|
||||
if (sock) {
|
||||
if (!strcmp(sock, shared_sock->name)) {
|
||||
if (!uwsgi_socket_strcmp(sock, shared_sock->name)) {
|
||||
if (strchr(sock, ':')) {
|
||||
uwsgi_log("uwsgi shared socket %d inherited TCP address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), sock, i);
|
||||
shared_sock->family = AF_INET;
|
||||
|
||||
@@ -108,7 +108,6 @@ pid_t spooler_start(struct uwsgi_spooler * uspool) {
|
||||
signal(SIGSTOP, SIG_IGN);
|
||||
signal(SIGTSTP, SIG_IGN);
|
||||
|
||||
uwsgi.mywid = -1;
|
||||
uwsgi.mypid = getpid();
|
||||
uspool->pid = uwsgi.mypid;
|
||||
// avoid race conditions !!!
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
#ifdef UWSGI_SQLITE3
|
||||
|
||||
#include "uwsgi.h"
|
||||
#include <sqlite3.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
static int uwsgi_sqlite3_config_callback(void *magic_table, int field_count, char **fields, char **col) {
|
||||
// make a copy of the string
|
||||
if (field_count >= 2) {
|
||||
size_t value_len = strlen(fields[1]) + 1;
|
||||
char *value = magic_sub(fields[1], value_len, &value_len, (char **) magic_table);
|
||||
add_exported_option(uwsgi_strncopy(fields[0], strlen(fields[0])), value, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_sqlite3_config(char *file, char *magic_table[]) {
|
||||
|
||||
sqlite3 *db;
|
||||
char *err = NULL;
|
||||
char *query = "SELECT * FROM uwsgi";
|
||||
|
||||
char *colon = uwsgi_get_last_char(file, ':');
|
||||
|
||||
if (colon) {
|
||||
colon[0] = 0;
|
||||
if (colon[1] != 0) {
|
||||
query = colon + 1;
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("[uWSGI] getting sqlite3 configuration from %s\n", file);
|
||||
|
||||
#ifdef sqlite3_open_v2
|
||||
if (sqlite3_open_v2(file, &db, SQLITE_OPEN_READONLY, NULL)) {
|
||||
#else
|
||||
if (sqlite3_open(file, &db)) {
|
||||
#endif
|
||||
uwsgi_log("unable to open sqlite3 db: %s\n", sqlite3_errmsg(db));
|
||||
sqlite3_close(db);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (sqlite3_exec(db, query, uwsgi_sqlite3_config_callback, (void *) magic_table, &err)) {
|
||||
uwsgi_log("sqlite3 error: %s\n", err);
|
||||
sqlite3_close(db);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sqlite3_close(db);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
+34
-7
@@ -315,7 +315,7 @@ int uwsgi_add_expires_uri(struct wsgi_request *wsgi_req, struct stat *st) {
|
||||
#endif
|
||||
|
||||
|
||||
char *uwsgi_get_mime_type(char *name, int namelen, int *size) {
|
||||
char *uwsgi_get_mime_type(char *name, int namelen, size_t *size) {
|
||||
|
||||
int i;
|
||||
int count = 0;
|
||||
@@ -429,7 +429,7 @@ static int uwsgi_static_stat(struct wsgi_request *wsgi_req, char *filename, size
|
||||
|
||||
int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, size_t real_filename_len, struct stat *st) {
|
||||
|
||||
int mime_type_size = 0;
|
||||
size_t mime_type_size = 0;
|
||||
char http_last_modified[49];
|
||||
|
||||
if (uwsgi.threads > 1)
|
||||
@@ -451,8 +451,31 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
|
||||
uwsgi_log("[uwsgi-fileserve] file %s found\n", real_filename);
|
||||
#endif
|
||||
|
||||
size_t fsize = st->st_size;
|
||||
if (wsgi_req->range_to) {
|
||||
fsize = wsgi_req->range_to - wsgi_req->range_from;
|
||||
if (fsize > (size_t)st->st_size) {
|
||||
fsize = st->st_size;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// reset in case of inconsistent size
|
||||
if (wsgi_req->range_from > fsize) {
|
||||
wsgi_req->range_from = 0;
|
||||
fsize = 0 ;
|
||||
}
|
||||
else {
|
||||
fsize -= wsgi_req->range_from;
|
||||
}
|
||||
}
|
||||
|
||||
// HTTP status
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return -1;
|
||||
if (fsize > 0 && (wsgi_req->range_from || wsgi_req->range_to)) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "206 Partial Content", 19)) return -1;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return -1;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
uwsgi_add_expires(wsgi_req, real_filename, real_filename_len, st);
|
||||
@@ -490,8 +513,12 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
|
||||
if (uwsgi_static_want_gzip(wsgi_req, real_filename, real_filename_len, st)) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Content-Encoding", 16, "gzip", 4)) return -1;
|
||||
}
|
||||
// set Content-Length
|
||||
if (uwsgi_response_add_content_length(wsgi_req, st->st_size)) return -1;
|
||||
// set Content-Length (to fsize NOT st->st_size)
|
||||
if (uwsgi_response_add_content_length(wsgi_req, fsize)) return -1;
|
||||
if (fsize > 0 && (wsgi_req->range_from || wsgi_req->range_to)) {
|
||||
// here use teh original size !!!
|
||||
if (uwsgi_response_add_content_range(wsgi_req, wsgi_req->range_from, wsgi_req->range_to, st->st_size)) return -1;
|
||||
}
|
||||
int size = set_http_date(st->st_mtime, http_last_modified);
|
||||
if (uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, http_last_modified, size)) return -1;
|
||||
|
||||
@@ -506,7 +533,7 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
|
||||
int fd = open(real_filename, O_RDONLY);
|
||||
if (fd < 0) return -1;
|
||||
// fd will be closed in the following function
|
||||
uwsgi_response_sendfile_do(wsgi_req, fd, 0, st->st_size);
|
||||
uwsgi_response_sendfile_do(wsgi_req, fd, wsgi_req->range_from, fsize);
|
||||
}
|
||||
|
||||
wsgi_req->status = 200;
|
||||
@@ -609,7 +636,7 @@ safe:
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
// before sending the file, we need to check if some rule applies
|
||||
if (uwsgi_apply_routes_do(wsgi_req, NULL, 0) == UWSGI_ROUTE_BREAK) {
|
||||
if (!wsgi_req->is_routing && uwsgi_apply_routes_do(wsgi_req, NULL, 0) == UWSGI_ROUTE_BREAK) {
|
||||
return 0;
|
||||
}
|
||||
wsgi_req->routes_applied = 1;
|
||||
|
||||
+43
-1
@@ -315,6 +315,45 @@ int uwsgi_stats_keylong_comma(struct uwsgi_stats *us, char *key, unsigned long l
|
||||
return uwsgi_stats_comma(us);
|
||||
}
|
||||
|
||||
int uwsgi_stats_keyslong(struct uwsgi_stats *us, char *key, long long num) {
|
||||
|
||||
if (uwsgi_stats_apply_tabs(us))
|
||||
return -1;
|
||||
|
||||
char *ptr = us->base + us->pos;
|
||||
char *watermark = us->base + us->size;
|
||||
size_t available = watermark - ptr;
|
||||
|
||||
int ret = snprintf(ptr, available, "\"%s\":%lld", key, num);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
while (ret >= (int) available) {
|
||||
char *new_base = realloc(us->base, us->size + us->chunk);
|
||||
if (!new_base)
|
||||
return -1;
|
||||
us->base = new_base;
|
||||
us->size += us->chunk;
|
||||
ptr = us->base + us->pos;
|
||||
watermark = us->base + us->size;
|
||||
available = watermark - ptr;
|
||||
ret = snprintf(ptr, available, "\"%s\":%lld", key, num);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
us->pos += ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_stats_keyslong_comma(struct uwsgi_stats *us, char *key, long long num) {
|
||||
int ret = uwsgi_stats_keyslong(us, key, num);
|
||||
if (ret)
|
||||
return -1;
|
||||
return uwsgi_stats_comma(us);
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_send_stats(int fd, struct uwsgi_stats *(*func) (void)) {
|
||||
|
||||
struct sockaddr_un client_src;
|
||||
@@ -383,7 +422,10 @@ struct uwsgi_stats_pusher_instance *uwsgi_stats_pusher_add(struct uwsgi_stats_pu
|
||||
|
||||
uspi = uwsgi_calloc(sizeof(struct uwsgi_stats_pusher_instance));
|
||||
uspi->pusher = pusher;
|
||||
uspi->arg = arg;
|
||||
if (arg) {
|
||||
uspi->arg = uwsgi_str(arg);
|
||||
}
|
||||
uspi->raw = pusher->raw;
|
||||
if (old_uspi) {
|
||||
old_uspi->next = uspi;
|
||||
}
|
||||
|
||||
+55
-5
@@ -622,6 +622,25 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
|
||||
free(wsgi_req->proto_parser_buf);
|
||||
}
|
||||
|
||||
// do we need to store the response in the cache
|
||||
if (wsgi_req->cache_it) {
|
||||
// only response with a body and a status code of 200 can be cached (TODO allows it to be configurable)
|
||||
if (wsgi_req->cached_response && wsgi_req->status == 200 && wsgi_req->response_size > 0) {
|
||||
uwsgi_cache_magic_set(wsgi_req->cache_it->buf, wsgi_req->cache_it->pos,
|
||||
wsgi_req->cached_response->buf, wsgi_req->cached_response->pos, wsgi_req->cache_it_expires, UWSGI_CACHE_FLAG_UPDATE, wsgi_req->cache_it_to ? wsgi_req->cache_it_to->buf : NULL);
|
||||
}
|
||||
uwsgi_buffer_destroy(wsgi_req->cache_it);
|
||||
|
||||
}
|
||||
|
||||
if (wsgi_req->cache_it_to) {
|
||||
uwsgi_buffer_destroy(wsgi_req->cache_it_to);
|
||||
}
|
||||
|
||||
if (wsgi_req->cached_response) {
|
||||
uwsgi_buffer_destroy(wsgi_req->cached_response);
|
||||
}
|
||||
|
||||
if (!wsgi_req->do_not_account) {
|
||||
uwsgi.workers[0].requests++;
|
||||
uwsgi.workers[uwsgi.mywid].requests++;
|
||||
@@ -1506,6 +1525,25 @@ int uwsgi_logic_opt_for_glob(char *key, char *value) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_for_times(char *key, char *value) {
|
||||
|
||||
int num = atoi(uwsgi.logic_opt_data);
|
||||
int i;
|
||||
char str_num[11];
|
||||
|
||||
for (i = 1; i <= num; i++) {
|
||||
int ret = uwsgi_num2str2(i, str_num);
|
||||
// security check
|
||||
if (ret < 0 || ret > 11) {
|
||||
exit(1);
|
||||
}
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", str_num), 0);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void add_exported_option(char *key, char *value, int configured) {
|
||||
|
||||
@@ -2470,13 +2508,19 @@ void uwsgi_chown(char *filename, char *owner) {
|
||||
|
||||
char *uwsgi_get_binary_path(char *argvzero) {
|
||||
|
||||
#if defined(__linux__)
|
||||
#if defined(__linux__) || defined(__CYGWIN__)
|
||||
char *buf = uwsgi_calloc(PATH_MAX + 1);
|
||||
ssize_t len = readlink("/proc/self/exe", buf, PATH_MAX);
|
||||
if (len > 0) {
|
||||
return buf;
|
||||
}
|
||||
free(buf);
|
||||
#elif defined(_WIN32)
|
||||
char *buf = uwsgi_calloc(PATH_MAX + 1);
|
||||
if (GetModuleFileName(NULL, buf, PATH_MAX) > 0) {
|
||||
return buf;
|
||||
}
|
||||
free(buf);
|
||||
#elif defined(__NetBSD__)
|
||||
char *buf = uwsgi_calloc(PATH_MAX + 1);
|
||||
ssize_t len = readlink("/proc/curproc/exe", buf, PATH_MAX);
|
||||
@@ -2941,11 +2985,13 @@ pid_t uwsgi_fork(char *name) {
|
||||
pid_t pid = fork();
|
||||
if (pid == 0) {
|
||||
|
||||
#ifndef __CYGWIN__
|
||||
if (uwsgi.never_swap) {
|
||||
if (mlockall(MCL_CURRENT | MCL_FUTURE)) {
|
||||
uwsgi_error("mlockall()");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) || defined(__sun__)
|
||||
int i;
|
||||
@@ -3027,14 +3073,17 @@ void http_url_decode(char *buf, uint16_t * len, char *dst) {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
we scan the table in reverse, as updated values are at the end
|
||||
*/
|
||||
char *uwsgi_get_var(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t * len) {
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
|
||||
if (!uwsgi_strncmp(key, keylen, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len)) {
|
||||
*len = wsgi_req->hvec[i + 1].iov_len;
|
||||
return wsgi_req->hvec[i + 1].iov_base;
|
||||
for (i = wsgi_req->var_cnt-1; i > 0; i -= 2) {
|
||||
if (!uwsgi_strncmp(key, keylen, wsgi_req->hvec[i-1].iov_base, wsgi_req->hvec[i-1].iov_len)) {
|
||||
*len = wsgi_req->hvec[i].iov_len;
|
||||
return wsgi_req->hvec[i].iov_base;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3453,6 +3502,7 @@ int uwsgi_kvlist_parse(char *src, size_t len, char list_separator, char kv_separ
|
||||
escaped = 1;
|
||||
}
|
||||
else if (escaped) {
|
||||
*ptr++ = src[i];
|
||||
escaped = 0;
|
||||
}
|
||||
else {
|
||||
|
||||
+152
-52
@@ -70,6 +70,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"xmlconfig", required_argument, 'x', "load config from xml file", uwsgi_opt_load_xml, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"xml", required_argument, 'x', "load config from xml file", uwsgi_opt_load_xml, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#endif
|
||||
{"config", required_argument, 0, "load configuration using the pluggable system", uwsgi_opt_load_config, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"skip-zero", no_argument, 0, "skip check of file descriptor 0", uwsgi_opt_true, &uwsgi.skip_zero, 0},
|
||||
|
||||
@@ -79,7 +80,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
|
||||
{"for", required_argument, 0, "(opt logic) for cycle", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for, UWSGI_OPT_IMMEDIATE},
|
||||
{"for-glob", required_argument, 0, "(opt logic) for cycle (expand glob)", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for_glob, UWSGI_OPT_IMMEDIATE},
|
||||
{"for-times", required_argument, 0, "(opt logic) for cycle (expand the specified num to a list starting from 1)", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for_times, UWSGI_OPT_IMMEDIATE},
|
||||
{"endfor", optional_argument, 0, "(opt logic) end for cycle", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"end-for", optional_argument, 0, "(opt logic) end for cycle", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"if-opt", required_argument, 0, "(opt logic) check for option", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_opt, UWSGI_OPT_IMMEDIATE},
|
||||
{"if-not-opt", required_argument, 0, "(opt logic) check for option", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_not_opt, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -108,6 +111,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"if-directory", required_argument, 0, "(opt logic) check for directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_dir, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"endif", optional_argument, 0, "(opt logic) end if", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"end-if", optional_argument, 0, "(opt logic) end if", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"blacklist", required_argument, 0, "set options blacklist context", uwsgi_opt_set_str, &uwsgi.blacklist_context, UWSGI_OPT_IMMEDIATE},
|
||||
{"end-blacklist", no_argument, 0, "clear options blacklist context", uwsgi_opt_set_null, &uwsgi.blacklist_context, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -163,12 +167,14 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"single-interpreter", no_argument, 'i', "do not use multiple interpreters (where available)", uwsgi_opt_true, &uwsgi.single_interpreter, 0},
|
||||
{"need-app", no_argument, 0, "exit if no app can be loaded", uwsgi_opt_true, &uwsgi.need_app, 0},
|
||||
{"master", no_argument, 'M', "enable master process", uwsgi_opt_true, &uwsgi.master_process, 0},
|
||||
{"honour-stdin", no_argument, 0, "do not remap stdin to /dev/null", uwsgi_opt_true, &uwsgi.honour_stdin, 0},
|
||||
{"emperor", required_argument, 0, "run the Emperor", uwsgi_opt_add_string_list, &uwsgi.emperor, 0},
|
||||
{"emperor-procname", required_argument, 0, "set the Emperor process name", uwsgi_opt_set_str, &uwsgi.emperor_procname, 0},
|
||||
{"emperor-freq", required_argument, 0, "set the Emperor scan frequency (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.emperor_freq, 0},
|
||||
{"emperor-required-heartbeat", required_argument, 0, "set the Emperor tolerance about heartbeats", uwsgi_opt_set_int, &uwsgi.emperor_heartbeat, 0},
|
||||
{"emperor-pidfile", required_argument, 0, "write the Emperor pid in the specified file", uwsgi_opt_set_str, &uwsgi.emperor_pidfile, 0},
|
||||
{"emperor-tyrant", no_argument, 0, "put the Emperor in Tyrant mode", uwsgi_opt_true, &uwsgi.emperor_tyrant, 0},
|
||||
{"emperor-tyrant-nofollow", no_argument, 0, "do not follow symlinks when checking for uid/gid in Tyrant mode", uwsgi_opt_true, &uwsgi.emperor_tyrant_nofollow, 0},
|
||||
{"emperor-stats", required_argument, 0, "run the Emperor stats server", uwsgi_opt_set_str, &uwsgi.emperor_stats, 0},
|
||||
{"emperor-stats-server", required_argument, 0, "run the Emperor stats server", uwsgi_opt_set_str, &uwsgi.emperor_stats, 0},
|
||||
{"early-emperor", no_argument, 0, "spawn the emperor as soon as possibile", uwsgi_opt_true, &uwsgi.early_emperor, 0},
|
||||
@@ -176,6 +182,13 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"emperor-throttle", required_argument, 0, "set throttling level (in milliseconds) for bad behaving vassals (default 1000)", uwsgi_opt_set_int, &uwsgi.emperor_throttle, 0},
|
||||
{"emperor-max-throttle", required_argument, 0, "set max throttling level (in milliseconds) for bad behaving vassals (default 3 minutes)", uwsgi_opt_set_int, &uwsgi.emperor_max_throttle, 0},
|
||||
{"emperor-magic-exec", no_argument, 0, "prefix vassals config files with exec:// if they have the executable bit", uwsgi_opt_true, &uwsgi.emperor_magic_exec, 0},
|
||||
{"emperor-on-demand-extension", required_argument, 0, "search for text file (vassal name + extension) containing the on demand socket name", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_extension, 0},
|
||||
{"emperor-on-demand-ext", required_argument, 0, "search for text file (vassal name + extension) containing the on demand socket name", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_extension, 0},
|
||||
{"emperor-on-demand-directory", required_argument, 0, "enable on demand mode binding to the unix socket in the specified directory named like the vassal + .socket", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_directory, 0},
|
||||
{"emperor-on-demand-dir", required_argument, 0, "enable on demand mode binding to the unix socket in the specified directory named like the vassal + .socket", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_directory, 0},
|
||||
{"emperor-on-demand-exec", required_argument, 0, "use the output of the specified command as on demand socket name (the vassal name is passed as the only argument)", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_exec, 0},
|
||||
{"emperor-extra-extension", required_argument, 0, "allows the specified extension in the Emperor (vassal will be called with --config)", uwsgi_opt_add_string_list, &uwsgi.emperor_extra_extension, 0},
|
||||
{"emperor-extra-ext", required_argument, 0, "allows the specified extension in the Emperor (vassal will be called with --config)", uwsgi_opt_add_string_list, &uwsgi.emperor_extra_extension, 0},
|
||||
{"imperial-monitor-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0},
|
||||
{"imperial-monitors-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0},
|
||||
{"vassals-inherit", required_argument, 0, "add config templates to vassals config", uwsgi_opt_add_string_list, &uwsgi.vassals_templates, 0},
|
||||
@@ -256,6 +269,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"chroot", required_argument, 0, "chroot() to the specified directory", uwsgi_opt_set_str, &uwsgi.chroot, 0},
|
||||
{"uid", required_argument, 0, "setuid to the specified user/uid", uwsgi_opt_set_uid, NULL, 0},
|
||||
{"gid", required_argument, 0, "setgid to the specified group/gid", uwsgi_opt_set_gid, NULL, 0},
|
||||
{"immediate-uid", required_argument, 0, "setuid to the specified user/uid IMMEDIATELY", uwsgi_opt_set_immediate_uid, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"immediate-gid", required_argument, 0, "setgid to the specified group/gid IMMEDIATELY", uwsgi_opt_set_immediate_gid, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"no-initgroups", no_argument, 0, "disable additional groups set via initgroups()", uwsgi_opt_true, &uwsgi.no_initgroups, 0},
|
||||
#ifdef UWSGI_CAP
|
||||
{"cap", required_argument, 0, "set process capability", uwsgi_opt_set_cap, NULL, 0},
|
||||
@@ -270,9 +285,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"exec-as-user", required_argument, 0, "run the specified command after privileges drop", uwsgi_opt_add_string_list, &uwsgi.exec_as_user, 0},
|
||||
{"exec-as-user-atexit", required_argument, 0, "run the specified command before app exit and reload", uwsgi_opt_add_string_list, &uwsgi.exec_as_user_atexit, 0},
|
||||
{"exec-pre-app", required_argument, 0, "run the specified command before app loading", uwsgi_opt_add_string_list, &uwsgi.exec_pre_app, 0},
|
||||
#ifdef UWSGI_INI
|
||||
{"exec-post-app", required_argument, 0, "run the specified command after app loading", uwsgi_opt_add_string_list, &uwsgi.exec_post_app, 0},
|
||||
{"ini", required_argument, 0, "load config from ini file", uwsgi_opt_load_ini, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#endif
|
||||
#ifdef UWSGI_YAML
|
||||
{"yaml", required_argument, 'y', "load config from yaml file", uwsgi_opt_load_yml, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"yal", required_argument, 'y', "load config from yaml file", uwsgi_opt_load_yml, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -281,20 +295,11 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"json", required_argument, 'j', "load config from json file", uwsgi_opt_load_json, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"js", required_argument, 'j', "load config from json file", uwsgi_opt_load_json, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#endif
|
||||
#ifdef UWSGI_SQLITE3
|
||||
{"sqlite3", required_argument, 0, "load config from sqlite3 db", uwsgi_opt_load_sqlite3, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"sqlite", required_argument, 0, "load config from sqlite3 db", uwsgi_opt_load_sqlite3, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#endif
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
{"zeromq", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "zmq", 0},
|
||||
{"zmq", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "zmq", 0},
|
||||
{"zeromq-socket", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "zmq", 0},
|
||||
{"zmq-socket", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "zmq", 0},
|
||||
#endif
|
||||
#ifdef UWSGI_LDAP
|
||||
{"ldap", required_argument, 0, "load configuration from ldap server", uwsgi_opt_load_ldap, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"ldap-schema", no_argument, 0, "dump uWSGI ldap schema", uwsgi_opt_ldap_dump, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"ldap-schema-ldif", no_argument, 0, "dump uWSGI ldap schema in ldif format", uwsgi_opt_ldap_dump_ldif, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#endif
|
||||
{"weight", required_argument, 0, "weight of the instance (used by clustering/lb/subscriptions)", uwsgi_opt_set_64bit, &uwsgi.weight, 0},
|
||||
{"auto-weight", required_argument, 0, "set weight of the instance (used by clustering/lb/subscriptions) automatically", uwsgi_opt_true, &uwsgi.auto_weight, 0},
|
||||
@@ -307,6 +312,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"socket-send-timeout", no_argument, 0, "set SO_SNDTIMEO", uwsgi_opt_set_int, &uwsgi.so_send_timeout, 0},
|
||||
{"so-write-timeout", no_argument, 0, "set SO_SNDTIMEO", uwsgi_opt_set_int, &uwsgi.so_send_timeout, 0},
|
||||
{"socket-write-timeout", no_argument, 0, "set SO_SNDTIMEO", uwsgi_opt_set_int, &uwsgi.so_send_timeout, 0},
|
||||
{"socket-sndbuf", required_argument, 0, "set SO_SNDBUF", uwsgi_opt_set_64bit, &uwsgi.so_sndbuf, 0},
|
||||
{"socket-rcvbuf", required_argument, 0, "set SO_RCVBUF", uwsgi_opt_set_64bit, &uwsgi.so_rcvbuf, 0},
|
||||
{"limit-as", required_argument, 0, "limit processes address space/vsz", uwsgi_opt_set_megabytes, &uwsgi.rl.rlim_max, 0},
|
||||
{"limit-nproc", required_argument, 0, "limit the number of spawnable processes", uwsgi_opt_set_int, &uwsgi.rl_nproc.rlim_max, 0},
|
||||
{"reload-on-as", required_argument, 0, "reload if address space is higher than specified megabytes", uwsgi_opt_set_megabytes, &uwsgi.reload_on_as, UWSGI_OPT_MEMORY},
|
||||
@@ -371,10 +378,13 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"legion-unlord", required_argument, 0, "action to call on Lord dismiss", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-setup", required_argument, 0, "action to call on legion setup", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-death", required_argument, 0, "action to call on legion death (shutdown of the instance)", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-join", required_argument, 0, "action to call on legion join (first time quorum is reached)", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-node-joined", required_argument, 0, "action to call on new node joining legion", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-node-left", required_argument, 0, "action to call node leaving legion", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-quorum", required_argument, 0, "set the quorum of a legion", uwsgi_opt_legion_quorum, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-scroll", required_argument, 0, "set the scroll of a legion", uwsgi_opt_legion_scroll, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-scroll", required_argument, 0, "set the scroll of a legion", uwsgi_opt_legion_scroll, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-scroll-max-size", required_argument, 0, "set max size of legion scroll buffer", uwsgi_opt_set_16bit, &uwsgi.legion_scroll_max_size, 0},
|
||||
{"legion-scroll-list-max-size", required_argument, 0, "set max size of legion scroll list buffer", uwsgi_opt_set_64bit, &uwsgi.legion_scroll_list_max_size, 0},
|
||||
{"subscriptions-sign-check", required_argument, 0, "set digest algorithm and certificate directory for secured subscription system", uwsgi_opt_scd, NULL, UWSGI_OPT_MASTER},
|
||||
{"subscriptions-sign-check-tolerance", required_argument, 0, "set the maximum tolerance (in seconds) of clock skew for secured subscription system", uwsgi_opt_set_int, &uwsgi.subscriptions_sign_check_tolerance, UWSGI_OPT_MASTER},
|
||||
#endif
|
||||
@@ -506,6 +516,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"route-label", required_argument, 0, "add a routing label (for use with goto)", uwsgi_opt_add_route, NULL, 0},
|
||||
{"route-if", required_argument, 0, "add a route based on condition", uwsgi_opt_add_route, "if", 0},
|
||||
{"route-if-not", required_argument, 0, "add a route based on condition (negate version)", uwsgi_opt_add_route, "if-not", 0},
|
||||
{"route-run", required_argument, 0, "always run the specified route action", uwsgi_opt_add_route, "run", 0},
|
||||
{"router-list", no_argument, 0, "list enabled routers", uwsgi_opt_true, &uwsgi.router_list, 0},
|
||||
{"routers-list", no_argument, 0, "list enabled routers", uwsgi_opt_true, &uwsgi.router_list, 0},
|
||||
#endif
|
||||
@@ -561,6 +572,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"static-gzip-ext", required_argument, 0, "check for a gzip version of all requested static files with the specified ext/suffix", uwsgi_opt_add_string_list, &uwsgi.static_gzip_ext, UWSGI_OPT_MIME},
|
||||
{"static-gzip-suffix", required_argument, 0, "check for a gzip version of all requested static files with the specified ext/suffix", uwsgi_opt_add_string_list, &uwsgi.static_gzip_ext, UWSGI_OPT_MIME},
|
||||
|
||||
{"honour-range", no_argument, 0, "enable support for the HTTP Range header", uwsgi_opt_true, &uwsgi.honour_range, 0},
|
||||
|
||||
{"offload-threads", required_argument, 0, "set the number of offload threads to spawn (per-worker, default 0)", uwsgi_opt_set_int, &uwsgi.offload_threads, 0},
|
||||
{"offload-thread", required_argument, 0, "set the number of offload threads to spawn (per-worker, default 0)", uwsgi_opt_set_int, &uwsgi.offload_threads, 0},
|
||||
|
||||
@@ -599,6 +612,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"attach-daemon", required_argument, 0, "attach a command/daemon to the master process (the command has to not go in background)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
{"smart-attach-daemon", required_argument, 0, "attach a command/daemon to the master process managed by a pidfile (the command has to daemonize)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
{"smart-attach-daemon2", required_argument, 0, "attach a command/daemon to the master process managed by a pidfile (the command has to NOT daemonize)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
{"daemons-honour-stdin", no_argument, 0, "do not change the stdin of external daemons to /dev/null", uwsgi_opt_true, &uwsgi.daemons_honour_stdin, UWSGI_OPT_MASTER},
|
||||
{"plugins", required_argument, 0, "load uWSGI plugins", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"plugin", required_argument, 0, "load uWSGI plugins", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"plugins-dir", required_argument, 0, "add a directory to uWSGI plugin search path", uwsgi_opt_add_string_list, &uwsgi.plugins_dir, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -779,8 +793,12 @@ void config_magic_table_fill(char *filename, char **magic_table) {
|
||||
char *section = uwsgi_get_last_char(filename, ':');
|
||||
if (section) {
|
||||
*section = 0;
|
||||
if (section == filename) {
|
||||
goto reuse;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// we have a special case for symlinks
|
||||
if (uwsgi_is_link(filename)) {
|
||||
if (filename[0] != '/') {
|
||||
@@ -834,6 +852,7 @@ void config_magic_table_fill(char *filename, char **magic_table) {
|
||||
if (uwsgi_get_last_char(magic_table['s'], '.'))
|
||||
magic_table['n'] = uwsgi_concat2n(magic_table['s'], uwsgi_get_last_char(magic_table['s'], '.') - magic_table['s'], "", 0);
|
||||
|
||||
reuse:
|
||||
if (section) {
|
||||
magic_table['x'] = section+1;
|
||||
*section = ':';
|
||||
@@ -976,9 +995,18 @@ void grace_them_all(int signum) {
|
||||
if (uwsgi_instance_is_reloading || uwsgi_instance_is_dying)
|
||||
return;
|
||||
|
||||
int i;
|
||||
|
||||
if (uwsgi.lazy) {
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
uwsgi.status.gracefully_reloading = 1;
|
||||
|
||||
int i;
|
||||
int waitpid_status;
|
||||
|
||||
|
||||
@@ -1011,8 +1039,6 @@ void grace_them_all(int signum) {
|
||||
}
|
||||
}
|
||||
else if (uwsgi.workers[i].pid > 0) {
|
||||
if (uwsgi.lazy)
|
||||
uwsgi.workers[i].destroy = 1;
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
}
|
||||
}
|
||||
@@ -1027,6 +1053,9 @@ void grace_them_all(int signum) {
|
||||
|
||||
void uwsgi_nuclear_blast() {
|
||||
|
||||
// the Emperor (as an example) cannot nuke itself
|
||||
if (uwsgi.disable_nuclear_blast) return;
|
||||
|
||||
if (!uwsgi.workers) {
|
||||
reap_them_all(0);
|
||||
}
|
||||
@@ -1341,7 +1370,7 @@ void fixup_argv_and_environ(int argc, char **argv, char **environ) {
|
||||
env_count++;
|
||||
}
|
||||
|
||||
uwsgi.environ = uwsgi_malloc(sizeof(char *) * env_count);
|
||||
uwsgi.environ = uwsgi_malloc(sizeof(char *) * (env_count+1));
|
||||
for (i = 0; i < env_count; i++) {
|
||||
uwsgi.environ[i] = strdup(environ[i]);
|
||||
#ifdef UWSGI_DEBUG
|
||||
@@ -1349,6 +1378,7 @@ void fixup_argv_and_environ(int argc, char **argv, char **environ) {
|
||||
#endif
|
||||
environ[i] = uwsgi.environ[i];
|
||||
}
|
||||
uwsgi.environ[env_count] = NULL;
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("max space for custom process name = %d\n", uwsgi.max_procname);
|
||||
@@ -1596,10 +1626,6 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
|
||||
int i;
|
||||
|
||||
#ifdef UNBIT
|
||||
//struct uidsec_struct us;
|
||||
#endif
|
||||
|
||||
struct utsname uuts;
|
||||
|
||||
// signal mask is inherited, and sme process manager could make a real mess...
|
||||
@@ -1701,7 +1727,13 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
// count/set the current reload status
|
||||
uwsgi_setup_reload();
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
SYSTEM_INFO si;
|
||||
GetSystemInfo(&si);
|
||||
uwsgi.page_size = si.dwPageSize;
|
||||
#else
|
||||
uwsgi.page_size = getpagesize();
|
||||
#endif
|
||||
uwsgi.binary_path = uwsgi_get_binary_path(argv[0]);
|
||||
|
||||
// ok we can now safely play with argv and environ
|
||||
@@ -1737,6 +1769,7 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
// set a couple of 'static' magic vars
|
||||
uwsgi.magic_table['v'] = uwsgi.cwd;
|
||||
uwsgi.magic_table['h'] = uwsgi.hostname;
|
||||
uwsgi.magic_table['V'] = UWSGI_VERSION;
|
||||
|
||||
// you can embed a ini file in the uWSGi binary with default options
|
||||
#ifdef UWSGI_EMBED_CONFIG
|
||||
@@ -1785,12 +1818,14 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
// initial log setup (files and daemonization)
|
||||
uwsgi_setup_log();
|
||||
|
||||
#ifndef __CYGWIN__
|
||||
// enable never-swap mode
|
||||
if (uwsgi.never_swap) {
|
||||
if (mlockall(MCL_CURRENT | MCL_FUTURE)) {
|
||||
uwsgi_error("mlockall()");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (uwsgi.flock2)
|
||||
uwsgi_opt_flock(NULL, uwsgi.flock2, NULL);
|
||||
@@ -2093,6 +2128,20 @@ int uwsgi_start(void *v_argv) {
|
||||
// automatically fix options
|
||||
sanitize_args();
|
||||
|
||||
|
||||
if (uwsgi.requested_max_fd) {
|
||||
uwsgi.rl.rlim_cur = uwsgi.requested_max_fd;
|
||||
uwsgi.rl.rlim_max = uwsgi.requested_max_fd;
|
||||
if (setrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
|
||||
uwsgi_error("setrlimit()");
|
||||
}
|
||||
}
|
||||
|
||||
if (!getrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
|
||||
uwsgi.max_fd = uwsgi.rl.rlim_cur;
|
||||
uwsgi_log_initial("detected max file descriptor number: %lu\n", (unsigned long) uwsgi.max_fd);
|
||||
}
|
||||
|
||||
// start the Emperor if needed
|
||||
if (!uwsgi.early_emperor && uwsgi.emperor) {
|
||||
uwsgi_emperor_start();
|
||||
@@ -2117,19 +2166,6 @@ int uwsgi_start(void *v_argv) {
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.requested_max_fd) {
|
||||
uwsgi.rl.rlim_cur = uwsgi.requested_max_fd;
|
||||
uwsgi.rl.rlim_max = uwsgi.requested_max_fd;
|
||||
if (setrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
|
||||
uwsgi_error("setrlimit()");
|
||||
}
|
||||
}
|
||||
|
||||
if (!getrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
|
||||
uwsgi.max_fd = uwsgi.rl.rlim_cur;
|
||||
uwsgi_log_initial("detected max file descriptor number: %lu\n", (unsigned long) uwsgi.max_fd);
|
||||
}
|
||||
|
||||
if (uwsgi.async > 1) {
|
||||
if ((unsigned long) uwsgi.max_fd < (unsigned long) uwsgi.async) {
|
||||
uwsgi_log("- your current max open files limit is %lu, this is lower than requested async cores !!! -\n", (unsigned long) uwsgi.max_fd);
|
||||
@@ -2515,11 +2551,9 @@ next:
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_MINTERPRETERS
|
||||
if (!uwsgi.single_interpreter && uwsgi.numproc > 0) {
|
||||
uwsgi_log("*** uWSGI is running in multiple interpreter mode ***\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
// check for request plugins, and eventually print a warning
|
||||
int rp_available = 0;
|
||||
@@ -3104,6 +3138,18 @@ void uwsgi_init_all_apps() {
|
||||
}
|
||||
}
|
||||
|
||||
usl = uwsgi.exec_post_app;
|
||||
while (usl) {
|
||||
uwsgi_log("running \"%s\" (post app)...\n", usl->value);
|
||||
int ret = uwsgi_run_command_and_wait(NULL, usl->value);
|
||||
if (ret != 0) {
|
||||
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
|
||||
exit(1);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_init_worker_mount_apps() {
|
||||
@@ -3146,6 +3192,59 @@ void uwsgi_opt_true(char *opt, char *value, void *key) {
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_opt_set_immediate_gid(char *opt, char *value, void *none) {
|
||||
gid_t gid = atoi(value);
|
||||
if (gid == 0) {
|
||||
struct group *ugroup = getgrnam(value);
|
||||
if (ugroup)
|
||||
gid = ugroup->gr_gid;
|
||||
}
|
||||
if (gid <= 0) {
|
||||
uwsgi_log("uwsgi_opt_set_immediate_gid(): invalid gid %d\n", (int) gid);
|
||||
exit(1);
|
||||
}
|
||||
if (setgid(gid)) {
|
||||
uwsgi_error("uwsgi_opt_set_immediate_gid()/setgid()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (setgroups(0, NULL)) {
|
||||
uwsgi_error("uwsgi_opt_set_immediate_gid()/setgroups()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
gid = getgid();
|
||||
if (!gid) {
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("immediate gid: %d\n", (int) gid);
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_set_immediate_uid(char *opt, char *value, void *none) {
|
||||
uid_t uid = atoi(value);
|
||||
if (uid == 0) {
|
||||
struct passwd *upasswd = getpwnam(value);
|
||||
if (upasswd)
|
||||
uid = upasswd->pw_uid;
|
||||
}
|
||||
if (uid <= 0) {
|
||||
uwsgi_log("uwsgi_opt_set_immediate_uid(): invalid uid %d\n", uid);
|
||||
exit(1);
|
||||
}
|
||||
if (setuid(uid)) {
|
||||
uwsgi_error("uwsgi_opt_set_immediate_uid()/setuid()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uid = getuid();
|
||||
if (!uid) {
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("immediate uid: %d\n", (int) uid);
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_set_int(char *opt, char *value, void *key) {
|
||||
int *ptr = (int *) key;
|
||||
if (value) {
|
||||
@@ -3695,12 +3794,10 @@ void uwsgi_opt_deprecated(char *opt, char *value, void *message) {
|
||||
|
||||
void uwsgi_opt_load(char *opt, char *filename, void *none) {
|
||||
|
||||
#ifdef UWSGI_INI
|
||||
if (uwsgi_endswith(filename, ".ini")) {
|
||||
uwsgi_opt_load_ini(opt, filename, none);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifdef UWSGI_XML
|
||||
if (uwsgi_endswith(filename, ".xml")) {
|
||||
uwsgi_opt_load_xml(opt, filename, none);
|
||||
@@ -3727,6 +3824,9 @@ void uwsgi_opt_load(char *opt, char *filename, void *none) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// fallback to pluggable system
|
||||
uwsgi_opt_load_config(opt, filename, none);
|
||||
}
|
||||
|
||||
void uwsgi_opt_logic(char *opt, char *arg, void *func) {
|
||||
@@ -3748,12 +3848,25 @@ void uwsgi_opt_logic(char *opt, char *arg, void *func) {
|
||||
void uwsgi_opt_noop(char *opt, char *foo, void *bar) {
|
||||
}
|
||||
|
||||
#ifdef UWSGI_INI
|
||||
void uwsgi_opt_load_ini(char *opt, char *filename, void *none) {
|
||||
config_magic_table_fill(filename, uwsgi.magic_table);
|
||||
uwsgi_ini_config(filename, uwsgi.magic_table);
|
||||
}
|
||||
#endif
|
||||
|
||||
void uwsgi_opt_load_config(char *opt, char *filename, void *none) {
|
||||
struct uwsgi_configurator *uc = uwsgi.configurators;
|
||||
while(uc) {
|
||||
if (uwsgi_endswith(filename, uc->name)) {
|
||||
config_magic_table_fill(filename, uwsgi.magic_table);
|
||||
uc->func(filename, uwsgi.magic_table);
|
||||
return;
|
||||
}
|
||||
uc = uc->next;
|
||||
}
|
||||
|
||||
uwsgi_log("unable to load configuration from %s\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_XML
|
||||
void uwsgi_opt_load_xml(char *opt, char *filename, void *none) {
|
||||
@@ -3769,13 +3882,6 @@ void uwsgi_opt_load_yml(char *opt, char *filename, void *none) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_SQLITE3
|
||||
void uwsgi_opt_load_sqlite3(char *opt, char *filename, void *none) {
|
||||
config_magic_table_fill(filename, uwsgi.magic_table);
|
||||
uwsgi_sqlite3_config(filename, uwsgi.magic_table);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_JSON
|
||||
void uwsgi_opt_load_json(char *opt, char *filename, void *none) {
|
||||
config_magic_table_fill(filename, uwsgi.magic_table);
|
||||
@@ -3783,12 +3889,6 @@ void uwsgi_opt_load_json(char *opt, char *filename, void *none) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_LDAP
|
||||
void uwsgi_opt_load_ldap(char *opt, char *url, void *none) {
|
||||
uwsgi_ldap_config(url);
|
||||
}
|
||||
#endif
|
||||
|
||||
void uwsgi_opt_add_custom_option(char *opt, char *value, void *none) {
|
||||
|
||||
struct uwsgi_custom_option *uco = uwsgi.custom_options, *old_uco;
|
||||
|
||||
@@ -12,6 +12,19 @@ int uwsgi_response_add_content_length(struct wsgi_request *wsgi_req, uint64_t cl
|
||||
return uwsgi_response_add_header(wsgi_req, "Content-Length", 14, buf, ret);
|
||||
}
|
||||
|
||||
int uwsgi_response_add_content_range(struct wsgi_request *wsgi_req, uint64_t start, uint64_t end, uint64_t cl) {
|
||||
char buf[6+(sizeof(UMAX64_STR)*3)+4];
|
||||
if (end == 0) {
|
||||
end = cl-1;
|
||||
}
|
||||
int ret = snprintf(buf, 6+(sizeof(UMAX64_STR)*3)+4, "bytes %llu-%llu/%llu", (unsigned long long) start, (unsigned long long) end, (unsigned long long) cl);
|
||||
if (ret <= 0 || ret > (int) (6+(sizeof(UMAX64_STR)*3)+4)) {
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
return uwsgi_response_add_header(wsgi_req, "Content-Range", 13, buf, ret);
|
||||
}
|
||||
|
||||
// status could be NNN or NNN message
|
||||
int uwsgi_response_prepare_headers(struct wsgi_request *wsgi_req, char *status, uint16_t status_len) {
|
||||
|
||||
@@ -141,6 +154,7 @@ int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
// this is the function called by all request plugins to send chunks to the client
|
||||
int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
|
||||
if (wsgi_req->write_errors) return -1;
|
||||
@@ -182,6 +196,18 @@ sendbody:
|
||||
// reset for the next write
|
||||
wsgi_req->write_pos = 0;
|
||||
|
||||
// now we need to check if the chunk must be stored
|
||||
if (wsgi_req->cache_it) {
|
||||
if (!wsgi_req->cached_response) {
|
||||
wsgi_req->cached_response = uwsgi_buffer_new(len);
|
||||
}
|
||||
// if we are unable to append the buffer, we just stop caching it
|
||||
if (uwsgi_buffer_append(wsgi_req->cached_response, buf, len)) {
|
||||
uwsgi_buffer_destroy(wsgi_req->cache_it);
|
||||
wsgi_req->cache_it = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
@@ -212,6 +238,7 @@ sendfile:
|
||||
if (can_close) close(fd);
|
||||
return -1;
|
||||
}
|
||||
if (pos >= (size_t)st.st_size) return UWSGI_OK;
|
||||
len = st.st_size;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
config = {}
|
||||
|
||||
config['immediate-uid'] = 'roberto'
|
||||
config['immediate-gid'] = 'roberto'
|
||||
config['http-socket'] = ':9090'
|
||||
config['env'] = { 'FOO=bar', 'TEST=topogigio' }
|
||||
config['module'] = 'werkzeug.testapp:test_app'
|
||||
|
||||
return config
|
||||
@@ -0,0 +1,8 @@
|
||||
config = {}
|
||||
|
||||
config[1] = { ['http-socket']=':9090' }
|
||||
config[2] = { ['env']='FOO=bar' }
|
||||
config[3] = { ['env']='TEST=topogigio' }
|
||||
config[4] = { ['module']='werkzeug.testapp:test_app' }
|
||||
|
||||
return config
|
||||
+103
-14
@@ -9,9 +9,10 @@
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct carbon_server_list {
|
||||
char *value; // server address
|
||||
int healthy;
|
||||
int errors;
|
||||
char *hostname;
|
||||
char *port;
|
||||
struct carbon_server_list *next;
|
||||
};
|
||||
|
||||
@@ -33,6 +34,11 @@ struct uwsgi_carbon {
|
||||
char *root_node;
|
||||
char *hostname_dot_replacement;
|
||||
char *hostname;
|
||||
int resolve_hostname;
|
||||
char *idle_avg;
|
||||
int push_avg;
|
||||
int zero_avg;
|
||||
uint64_t last_requests;
|
||||
struct uwsgi_stats_pusher *pusher;
|
||||
} u_carbon;
|
||||
|
||||
@@ -46,6 +52,9 @@ static struct uwsgi_option carbon_options[] = {
|
||||
{"carbon-retry-delay", required_argument, 0, "set connection retry delay in seconds (default 7)", uwsgi_opt_set_int, &u_carbon.retry_delay, 0},
|
||||
{"carbon-root", required_argument, 0, "set carbon metrics root node (default 'uwsgi')", uwsgi_opt_set_str, &u_carbon.root_node, 0},
|
||||
{"carbon-hostname-dots", required_argument, 0, "set char to use as a replacement for dots in hostname (dots are not replaced by default)", uwsgi_opt_set_str, &u_carbon.hostname_dot_replacement, 0},
|
||||
{"carbon-name-resolve", no_argument, 0, "allow using hostname as carbon server address (default disabled)", uwsgi_opt_true, &u_carbon.resolve_hostname, 0},
|
||||
{"carbon-resolve-names", no_argument, 0, "allow using hostname as carbon server address (default disabled)", uwsgi_opt_true, &u_carbon.resolve_hostname, 0},
|
||||
{"carbon-idle-avg", required_argument, 0, "average values source during idle period (no requests), can be \"last\", \"zero\", \"none\" (default is last)", uwsgi_opt_set_str, &u_carbon.idle_avg, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
@@ -59,15 +68,37 @@ static void carbon_post_init() {
|
||||
|
||||
while(usl) {
|
||||
struct carbon_server_list *u_server = uwsgi_calloc(sizeof(struct carbon_server_list));
|
||||
u_server->value = usl->value;
|
||||
u_server->healthy = 1;
|
||||
u_server->errors = 0;
|
||||
|
||||
char *p = strtok(usl->value, ":");
|
||||
while (p) {
|
||||
if (!u_server->hostname) {
|
||||
u_server->hostname = uwsgi_str(p);
|
||||
}
|
||||
else if (!u_server->port) {
|
||||
u_server->port = uwsgi_str(p);
|
||||
}
|
||||
else
|
||||
break;
|
||||
p = strtok(NULL, ":");
|
||||
}
|
||||
if (!u_server->hostname || !u_server->port) {
|
||||
uwsgi_log("[carbon] invalid carbon server address (%s)\n", usl->value);
|
||||
usl = usl->next;
|
||||
|
||||
if (u_server->hostname) free(u_server->hostname);
|
||||
if (u_server->port) free(u_server->port);
|
||||
free(u_server);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (u_carbon.servers_data) {
|
||||
u_server->next = u_carbon.servers_data;
|
||||
}
|
||||
u_carbon.servers_data = u_server;
|
||||
|
||||
uwsgi_log("[carbon] added server %s\n", usl->value);
|
||||
uwsgi_log("[carbon] added server %s:%s\n", u_server->hostname, u_server->port);
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
@@ -80,7 +111,7 @@ static void carbon_post_init() {
|
||||
if (u_carbon.timeout < 1) u_carbon.timeout = 3;
|
||||
if (u_carbon.max_retries <= 0) u_carbon.max_retries = 1;
|
||||
if (u_carbon.retry_delay <= 0) u_carbon.retry_delay = 7;
|
||||
if (!u_carbon.id) {
|
||||
if (!u_carbon.id) {
|
||||
u_carbon.id = uwsgi_str(uwsgi.sockets->name);
|
||||
|
||||
for(i=0;i<(int)strlen(u_carbon.id);i++) {
|
||||
@@ -95,6 +126,22 @@ static void carbon_post_init() {
|
||||
}
|
||||
}
|
||||
|
||||
u_carbon.push_avg = 1;
|
||||
u_carbon.zero_avg = 0;
|
||||
if (!u_carbon.idle_avg) {
|
||||
u_carbon.idle_avg = "last";
|
||||
}
|
||||
else if (!strcmp(u_carbon.idle_avg, "zero")) {
|
||||
u_carbon.zero_avg = 1;
|
||||
}
|
||||
else if (!strcmp(u_carbon.idle_avg, "none")) {
|
||||
u_carbon.push_avg = 0;
|
||||
}
|
||||
else if (strcmp(u_carbon.idle_avg, "last")) {
|
||||
uwsgi_log("[carbon] invalid value for carbon-idle-avg: \"%s\"\n", u_carbon.idle_avg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!u_carbon.last_busyness_values) {
|
||||
u_carbon.last_busyness_values = uwsgi_calloc(sizeof(unsigned long long) * uwsgi.numproc);
|
||||
}
|
||||
@@ -145,6 +192,8 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
int i;
|
||||
int fd;
|
||||
int wok;
|
||||
char *ip;
|
||||
char *carbon_address = NULL;
|
||||
|
||||
for (i = 0; i < uwsgi.numproc; i++) {
|
||||
u_carbon.current_busyness_values[i] = uwsgi.workers[i+1].running_time - u_carbon.last_busyness_values[i];
|
||||
@@ -157,31 +206,44 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
if (retry_cycle && usl->healthy)
|
||||
// skip healthy servers during retry cycle
|
||||
goto nxt;
|
||||
|
||||
|
||||
if (retry_cycle && usl->healthy == 0)
|
||||
uwsgi_log("[carbon] Retrying failed server at %s (%d)\n", usl->value, usl->errors);
|
||||
uwsgi_log("[carbon] Retrying failed server at %s (%d)\n", usl->hostname, usl->errors);
|
||||
|
||||
if (!retry_cycle) {
|
||||
usl->healthy = 1;
|
||||
usl->errors = 0;
|
||||
}
|
||||
|
||||
fd = uwsgi_connect(usl->value, u_carbon.timeout, 0);
|
||||
|
||||
if (u_carbon.resolve_hostname) {
|
||||
ip = uwsgi_resolve_ip(usl->hostname);
|
||||
if (!ip) {
|
||||
uwsgi_log("[carbon] Could not resolve hostname %s\n", usl->hostname);
|
||||
goto nxt;
|
||||
}
|
||||
carbon_address = uwsgi_concat3(ip, ":", usl->port);
|
||||
}
|
||||
else {
|
||||
carbon_address = uwsgi_concat3(usl->hostname, ":", usl->port);
|
||||
}
|
||||
fd = uwsgi_connect(carbon_address, u_carbon.timeout, 0);
|
||||
if (fd < 0) {
|
||||
uwsgi_log("[carbon] Could not connect to carbon server at %s\n", usl->value);
|
||||
uwsgi_log("[carbon] Could not connect to carbon server at %s\n", carbon_address);
|
||||
if (usl->errors < u_carbon.max_retries) {
|
||||
u_carbon.need_retry = 1;
|
||||
u_carbon.next_retry = uwsgi_now() + u_carbon.retry_delay;
|
||||
} else {
|
||||
uwsgi_log("[carbon] Maximum number of retries for %s (%d)\n",
|
||||
usl->value, u_carbon.max_retries);
|
||||
carbon_address, u_carbon.max_retries);
|
||||
usl->healthy = 0;
|
||||
usl->errors = 0;
|
||||
}
|
||||
usl->healthy = 0;
|
||||
usl->errors++;
|
||||
free(carbon_address);
|
||||
goto nxt;
|
||||
}
|
||||
free(carbon_address);
|
||||
// put the socket in non-blocking mode
|
||||
uwsgi_socket_nb(fd);
|
||||
|
||||
@@ -196,6 +258,8 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
unsigned long long worker_busyness = 0;
|
||||
unsigned long long total_harakiri = 0;
|
||||
|
||||
int do_avg_push;
|
||||
|
||||
wok = carbon_write(fd, "%s%s.%s.requests %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) uwsgi.workers[0].requests, (unsigned long long) now);
|
||||
if (!wok) goto clear;
|
||||
|
||||
@@ -246,8 +310,19 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
if (!wok) goto clear;
|
||||
}
|
||||
|
||||
wok = carbon_write(fd, "%s%s.%s.worker%d.avg_rt %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) avg_rt, (unsigned long long) now);
|
||||
if (!wok) goto clear;
|
||||
do_avg_push = 1;
|
||||
if (!u_carbon.last_requests || u_carbon.last_requests == uwsgi.workers[0].requests) {
|
||||
if (!u_carbon.push_avg) {
|
||||
do_avg_push = 0;
|
||||
}
|
||||
else if (u_carbon.zero_avg) {
|
||||
avg_rt = 0;
|
||||
}
|
||||
}
|
||||
if (do_avg_push) {
|
||||
wok = carbon_write(fd, "%s%s.%s.worker%d.avg_rt %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) avg_rt, (unsigned long long) now);
|
||||
if (!wok) goto clear;
|
||||
}
|
||||
|
||||
wok = carbon_write(fd, "%s%s.%s.worker%d.tx %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].tx, (unsigned long long) now);
|
||||
if (!wok) goto clear;
|
||||
@@ -268,8 +343,20 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
if (!wok) goto clear;
|
||||
}
|
||||
|
||||
wok = carbon_write(fd, "%s%s.%s.avg_rt %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) (active_workers ? total_avg_rt / active_workers : 0), (unsigned long long) now);
|
||||
if (!wok) goto clear;
|
||||
do_avg_push = 1;
|
||||
uint64_t c_total_avg_rt = (active_workers ? total_avg_rt / active_workers : 0);
|
||||
if (!u_carbon.last_requests || u_carbon.last_requests == uwsgi.workers[0].requests) {
|
||||
if (!u_carbon.push_avg) {
|
||||
do_avg_push = 0;
|
||||
}
|
||||
else if (u_carbon.zero_avg) {
|
||||
c_total_avg_rt = 0;
|
||||
}
|
||||
}
|
||||
if (do_avg_push) {
|
||||
wok = carbon_write(fd, "%s%s.%s.avg_rt %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) c_total_avg_rt, (unsigned long long) now);
|
||||
if (!wok) goto clear;
|
||||
}
|
||||
|
||||
wok = carbon_write(fd, "%s%s.%s.tx %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) total_tx, (unsigned long long) now);
|
||||
if (!wok) goto clear;
|
||||
@@ -297,6 +384,8 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
usl->healthy = 1;
|
||||
usl->errors = 0;
|
||||
|
||||
u_carbon.last_requests = uwsgi.workers[0].requests;
|
||||
|
||||
clear:
|
||||
close(fd);
|
||||
nxt:
|
||||
|
||||
+109
-43
@@ -18,7 +18,7 @@ struct uwsgi_cgi {
|
||||
int path_info;
|
||||
} uc ;
|
||||
|
||||
void uwsgi_opt_add_cgi(char *opt, char *value, void *foobar) {
|
||||
static void uwsgi_opt_add_cgi(char *opt, char *value, void *foobar) {
|
||||
|
||||
char *val = strchr(value, '=');
|
||||
if (!val) {
|
||||
@@ -30,7 +30,7 @@ void uwsgi_opt_add_cgi(char *opt, char *value, void *foobar) {
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_opt_add_cgi_maphelper(char *opt, char *value, void *foobar) {
|
||||
static void uwsgi_opt_add_cgi_maphelper(char *opt, char *value, void *foobar) {
|
||||
char *val = strchr(value, '=');
|
||||
if (!val) {
|
||||
uwsgi_log("invalid CGI helper syntax, must be ext=command\n");
|
||||
@@ -66,7 +66,7 @@ struct uwsgi_option uwsgi_cgi_options[] = {
|
||||
|
||||
};
|
||||
|
||||
void uwsgi_cgi_apps() {
|
||||
static void uwsgi_cgi_apps() {
|
||||
|
||||
struct uwsgi_dyn_dict *udd = uc.mountpoint;
|
||||
struct stat st;
|
||||
@@ -123,7 +123,7 @@ void uwsgi_cgi_apps() {
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_cgi_init(){
|
||||
static int uwsgi_cgi_init(){
|
||||
|
||||
void (*cgi_sym)(void);
|
||||
|
||||
@@ -161,7 +161,7 @@ int uwsgi_cgi_init(){
|
||||
|
||||
}
|
||||
|
||||
char *uwsgi_cgi_get_helper(char *filename) {
|
||||
static char *uwsgi_cgi_get_helper(char *filename) {
|
||||
|
||||
struct uwsgi_dyn_dict *helpers = uc.helpers;
|
||||
size_t len = strlen(filename);
|
||||
@@ -179,7 +179,7 @@ char *uwsgi_cgi_get_helper(char *filename) {
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
static int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
|
||||
size_t i;
|
||||
char *key = buf, *value = NULL;
|
||||
@@ -266,7 +266,7 @@ send_body:
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *uwsgi_cgi_get_docroot(char *path_info, uint16_t path_info_len, int *need_free, int *is_a_file, int *discard_base, char **script_name) {
|
||||
static char *uwsgi_cgi_get_docroot(char *path_info, uint16_t path_info_len, int *need_free, int *is_a_file, int *discard_base, char **script_name) {
|
||||
|
||||
struct uwsgi_dyn_dict *udd = uc.mountpoint, *choosen_udd = NULL;
|
||||
int best_found = 0;
|
||||
@@ -323,7 +323,7 @@ char *uwsgi_cgi_get_docroot(char *path_info, uint16_t path_info_len, int *need_f
|
||||
return path;
|
||||
}
|
||||
|
||||
int uwsgi_cgi_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot, size_t docroot_len, int discard_base, char **path_info) {
|
||||
static int uwsgi_cgi_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot, size_t docroot_len, int discard_base, char **path_info) {
|
||||
|
||||
// and now start walking...
|
||||
uint16_t i;
|
||||
@@ -380,18 +380,12 @@ int uwsgi_cgi_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
static int uwsgi_cgi_run(struct wsgi_request *, char *, size_t, char *, char *, char *, char *, int, int);
|
||||
|
||||
static int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
int i;
|
||||
pid_t cgi_pid;
|
||||
int waitpid_status;
|
||||
char **argv;
|
||||
int nargs = 0;
|
||||
char full_path[PATH_MAX];
|
||||
char tmp_path[PATH_MAX];
|
||||
int cgi_pipe[2];
|
||||
int post_pipe[2];
|
||||
ssize_t len;
|
||||
struct stat cgi_stat;
|
||||
int need_free = 0;
|
||||
int is_a_file = 0;
|
||||
@@ -399,7 +393,6 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
size_t docroot_len = 0;
|
||||
size_t full_path_len = 0;
|
||||
char *helper = NULL;
|
||||
char *command = NULL;
|
||||
char *path_info = NULL;
|
||||
char *script_name = NULL;
|
||||
|
||||
@@ -533,11 +526,8 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
if (is_a_file) {
|
||||
command = docroot;
|
||||
}
|
||||
else {
|
||||
command = full_path;
|
||||
// get the helper
|
||||
if (!is_a_file) {
|
||||
helper = uwsgi_cgi_get_helper(full_path);
|
||||
|
||||
if (helper == NULL) {
|
||||
@@ -551,28 +541,43 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
}
|
||||
|
||||
int ret = uwsgi_cgi_run(wsgi_req, docroot, docroot_len, full_path, helper, path_info, script_name, is_a_file, discard_base);
|
||||
if (need_free) free(docroot);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_cgi_run(struct wsgi_request *wsgi_req, char *docroot, size_t docroot_len, char *full_path, char *helper, char *path_info, char *script_name, int is_a_file, int discard_base) {
|
||||
|
||||
int cgi_pipe[2];
|
||||
int post_pipe[2];
|
||||
int nargs = 0;
|
||||
int waitpid_status;
|
||||
ssize_t len;
|
||||
int i;
|
||||
char **argv;
|
||||
|
||||
char *command = full_path;
|
||||
|
||||
if (is_a_file) {
|
||||
command = docroot;
|
||||
}
|
||||
|
||||
if (pipe(cgi_pipe)) {
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
uwsgi_error("pipe()");
|
||||
uwsgi_error("uwsgi_cgi_run()/pipe()");
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
if (pipe(post_pipe)) {
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
close(cgi_pipe[0]);
|
||||
close(cgi_pipe[1]);
|
||||
uwsgi_error("pipe()");
|
||||
uwsgi_error("uwsgi_cgi_run()/pipe()");
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
cgi_pid = fork();
|
||||
pid_t cgi_pid = fork();
|
||||
|
||||
if (cgi_pid < 0) {
|
||||
uwsgi_error("fork()");
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
uwsgi_error("uwsgi_cgi_run()/fork()");
|
||||
close(cgi_pipe[0]);
|
||||
close(cgi_pipe[1]);
|
||||
close(post_pipe[0]);
|
||||
@@ -582,9 +587,6 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (cgi_pid > 0) {
|
||||
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
|
||||
close(cgi_pipe[1]);
|
||||
close(post_pipe[0]);
|
||||
|
||||
@@ -795,7 +797,7 @@ clear2:
|
||||
}
|
||||
*base = '/';
|
||||
}
|
||||
else {
|
||||
else if (docroot_len > 0) {
|
||||
if (chdir(docroot)) {
|
||||
uwsgi_error("chdir()");
|
||||
}
|
||||
@@ -837,9 +839,8 @@ clear2:
|
||||
escape_shell_arg(arg_copy, arg_copy_len, argv[i]);
|
||||
i++;
|
||||
p = strtok(NULL, "+");
|
||||
}
|
||||
}
|
||||
else {
|
||||
}
|
||||
free(qs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -864,7 +865,7 @@ clear2:
|
||||
}
|
||||
|
||||
if (execvp(argv[0], argv)) {
|
||||
uwsgi_error("execvp()");
|
||||
uwsgi_error("uwsgi_cgi_run()/execvp()");
|
||||
}
|
||||
|
||||
// never here
|
||||
@@ -872,11 +873,73 @@ clear2:
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_cgi_after_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
static void uwsgi_cgi_after_request(struct wsgi_request *wsgi_req) {
|
||||
log_request(wsgi_req);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
static int uwsgi_routing_func_cgi(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
|
||||
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
struct uwsgi_buffer *ub_command = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
||||
if (!ub_command) return UWSGI_ROUTE_BREAK;
|
||||
struct uwsgi_buffer *ub_helper = NULL;
|
||||
if (ur->data2_len) {
|
||||
ub_helper = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data2, ur->data2_len);
|
||||
if (!ub_helper) {
|
||||
uwsgi_buffer_destroy(ub_command);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!uwsgi_is_file(ub_command->buf)) {
|
||||
uwsgi_404(wsgi_req);
|
||||
uwsgi_buffer_destroy(ub_command);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
if (access(ub_command->buf, X_OK)) {
|
||||
uwsgi_403(wsgi_req);
|
||||
uwsgi_buffer_destroy(ub_command);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
}
|
||||
// we need a NULL suffix-ed copy of the docroot
|
||||
char *docroot = uwsgi_concat2n(wsgi_req->document_root, wsgi_req->document_root_len, "", 0);
|
||||
uwsgi_cgi_run(wsgi_req, wsgi_req->document_root, wsgi_req->document_root_len, ub_command->buf, ub_helper ? ub_helper->buf : NULL, NULL, NULL, 0, 0 );
|
||||
free(docroot);
|
||||
uwsgi_buffer_destroy(ub_command);
|
||||
if (ub_helper) uwsgi_buffer_destroy(ub_helper);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
static int uwsgi_router_cgi_helper(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_cgi;
|
||||
char *space = strchr(args, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid cgihelper syntax, must be \"cgihelper:helper command\"\n");
|
||||
return -1;
|
||||
}
|
||||
*space = 0;
|
||||
ur->data = space+1;
|
||||
ur->data_len = strlen(space+1);
|
||||
ur->data2 = args;
|
||||
ur->data2_len = strlen(args);
|
||||
return 0;
|
||||
}
|
||||
static int uwsgi_router_cgi(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_cgi;
|
||||
ur->data = args;
|
||||
ur->data_len = strlen(args);
|
||||
return 0;
|
||||
}
|
||||
static void uwsgi_cgi_register_router() {
|
||||
uwsgi_register_router("cgi", uwsgi_router_cgi);
|
||||
uwsgi_register_router("cgihelper", uwsgi_router_cgi_helper);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct uwsgi_plugin cgi_plugin = {
|
||||
|
||||
@@ -887,5 +950,8 @@ struct uwsgi_plugin cgi_plugin = {
|
||||
.options = uwsgi_cgi_options,
|
||||
.request = uwsgi_cgi_request,
|
||||
.after_request = uwsgi_cgi_after_request,
|
||||
#ifdef UWSGI_ROUTING
|
||||
.on_load = uwsgi_cgi_register_router,
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
@@ -13,8 +13,9 @@ class FakeClass {
|
||||
|
||||
void FakeClass::hello_world(struct wsgi_request *wsgi_req) {
|
||||
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, (char *) "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n", 44);
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, foobar, foobar_len);
|
||||
uwsgi_response_prepare_headers(wsgi_req, (char *)"200 OK", 6);
|
||||
uwsgi_response_add_content_type(wsgi_req, (char *)"text/html", 9);
|
||||
uwsgi_response_write_body_do(wsgi_req, foobar, foobar_len);
|
||||
}
|
||||
|
||||
extern "C" int uwsgi_cplusplus_init(){
|
||||
@@ -27,7 +28,7 @@ extern "C" int uwsgi_cplusplus_request(struct wsgi_request *wsgi_req) {
|
||||
FakeClass *fc;
|
||||
|
||||
// empty request ?
|
||||
if (!wsgi_req->uh.pktsize) {
|
||||
if (!wsgi_req->uh->pktsize) {
|
||||
uwsgi_log( "Invalid request. skip.\n");
|
||||
goto clear;
|
||||
}
|
||||
@@ -55,6 +56,7 @@ clear:
|
||||
|
||||
|
||||
extern "C" void uwsgi_cplusplus_after_request(struct wsgi_request *wsgi_req) {
|
||||
// call log_request(wsgi_req) if you want a standard logline
|
||||
uwsgi_log("logging c++ request\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
|
||||
int uwsgi_cplusplus_init(void);
|
||||
|
||||
@@ -49,7 +49,7 @@ void uwsgi_imperial_monitor_amqp_event(struct uwsgi_emperor_scanner *ues) {
|
||||
}
|
||||
|
||||
if (msgsize > 0) {
|
||||
emperor_add(ues, amqp_routing_key, uwsgi_now(), config, msgsize, 0, 0);
|
||||
emperor_add(ues, amqp_routing_key, uwsgi_now(), config, msgsize, 0, 0, NULL);
|
||||
}
|
||||
|
||||
end0:
|
||||
@@ -88,7 +88,7 @@ end0:
|
||||
emperor_respawn(ui_current, uwsgi_now());
|
||||
}
|
||||
else {
|
||||
emperor_add(ues, config_file, uwsgi_now(), NULL, 0, 0, 0);
|
||||
emperor_add(ues, config_file, uwsgi_now(), NULL, 0, 0, 0, NULL);
|
||||
}
|
||||
|
||||
free(config_file);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
#include "client/dbclient.h"
|
||||
|
||||
@@ -60,7 +60,9 @@ extern "C" void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *ues
|
||||
vassal_gid = tmp_gid;
|
||||
}
|
||||
|
||||
uwsgi_emperor_simple_do(ues, (char *) name, (char *) config, vassal_ts/1000, vassal_uid, vassal_gid);
|
||||
const char *socket_name = p.getStringField("socket");
|
||||
|
||||
uwsgi_emperor_simple_do(ues, (char *) name, (char *) config, vassal_ts/1000, vassal_uid, vassal_gid, (char *) socket_name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *);
|
||||
void uwsgi_imperial_monitor_mongodb_init(struct uwsgi_emperor_scanner *);
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
import os
|
||||
|
||||
NAME='emperor_mongodb'
|
||||
|
||||
CFLAGS = ['-I/usr/include/mongo','-I/usr/local/include/mongo']
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lmongoclient', '-lboost_thread','-lboost_filesystem']
|
||||
|
||||
LIBS = []
|
||||
if not 'UWSGI_MONGODB_NOLIB' in os.environ:
|
||||
LIBS.append('-lmongoclient')
|
||||
LIBS.append('-lboost_thread')
|
||||
LIBS.append('-lboost_filesystem')
|
||||
|
||||
GCC_LIST = ['plugin', 'emperor_mongodb.cc']
|
||||
|
||||
@@ -68,7 +68,11 @@ void uwsgi_imperial_monitor_pg(struct uwsgi_emperor_scanner *ues) {
|
||||
vassal_uid = uwsgi_str_num(q_uid, strlen(q_uid));
|
||||
vassal_gid = uwsgi_str_num(q_gid, strlen(q_gid));
|
||||
}
|
||||
uwsgi_emperor_simple_do(ues, name, config, uwsgi_str_num(ts, len), vassal_uid, vassal_gid);
|
||||
char *socket_name = NULL;
|
||||
if (PQnfields(res) > 5) {
|
||||
socket_name = PQgetvalue(res, i, 5);
|
||||
}
|
||||
uwsgi_emperor_simple_do(ues, name, config, uwsgi_str_num(ts, len), vassal_uid, vassal_gid, socket_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -64,15 +64,16 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
|
||||
int64_t more = 0;
|
||||
size_t more_size = sizeof(more);
|
||||
int i;
|
||||
zmq_msg_t msg[5];
|
||||
zmq_msg_t msg[6];
|
||||
|
||||
zmq_msg_init(&msg[0]);
|
||||
zmq_msg_init(&msg[1]);
|
||||
zmq_msg_init(&msg[2]);
|
||||
zmq_msg_init(&msg[3]);
|
||||
zmq_msg_init(&msg[4]);
|
||||
zmq_msg_init(&msg[5]);
|
||||
|
||||
for(i=0;i<5;i++) {
|
||||
for(i=0;i<6;i++) {
|
||||
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,0,0)
|
||||
zmq_recvmsg(ues->data, &msg[i], ZMQ_DONTWAIT);
|
||||
#else
|
||||
@@ -105,6 +106,11 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
|
||||
char *ez_gid = NULL;
|
||||
size_t ez_gid_len = 0;
|
||||
|
||||
char *ez_socket_name = NULL;
|
||||
size_t ez_socket_name_len = 0;
|
||||
|
||||
char *socket_name = NULL;
|
||||
|
||||
// config
|
||||
if (i > 1) {
|
||||
ez_config = zmq_msg_data(&msg[2]);
|
||||
@@ -123,6 +129,12 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
|
||||
ez_gid_len = zmq_msg_size(&msg[4]);
|
||||
}
|
||||
|
||||
// gid
|
||||
if (i > 4) {
|
||||
ez_socket_name = zmq_msg_data(&msg[5]);
|
||||
ez_socket_name_len = zmq_msg_size(&msg[5]);
|
||||
}
|
||||
|
||||
char *name = uwsgi_concat2n(ez_name, ez_name_len, "", 0);
|
||||
|
||||
// ok let's start checking commands
|
||||
@@ -142,10 +154,16 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
|
||||
vassal_gid = uwsgi_str_num(ez_gid, ez_gid_len);
|
||||
}
|
||||
|
||||
uwsgi_emperor_simple_do(ues, name, config, uwsgi_now(), vassal_uid, vassal_gid);
|
||||
if (ez_socket_name) {
|
||||
socket_name = uwsgi_concat2n(ez_socket_name, ez_socket_name_len, "", 0);
|
||||
}
|
||||
uwsgi_emperor_simple_do(ues, name, config, uwsgi_now(), vassal_uid, vassal_gid, socket_name);
|
||||
if (config) {
|
||||
free(config);
|
||||
}
|
||||
if (socket_name) {
|
||||
free(socket_name);
|
||||
}
|
||||
}
|
||||
// destroy an instance
|
||||
else if (!uwsgi_strncmp(ez_cmd, ez_cmd_len, "destroy", 6)) {
|
||||
@@ -158,7 +176,7 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[emperor-zeromq] unkonwn command \"%.*s\"\n", (int)ez_cmd_len, ez_cmd);
|
||||
uwsgi_log("[emperor-zeromq] unknown command \"%.*s\"\n", (int)ez_cmd_len, ez_cmd);
|
||||
}
|
||||
|
||||
free(name);
|
||||
@@ -168,6 +186,7 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
|
||||
zmq_msg_close(&msg[2]);
|
||||
zmq_msg_close(&msg[3]);
|
||||
zmq_msg_close(&msg[4]);
|
||||
zmq_msg_close(&msg[5]);
|
||||
}
|
||||
|
||||
// this is the event manager
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_rack ur;
|
||||
extern struct uwsgi_plugin rack_plugin;
|
||||
|
||||
struct ufib {
|
||||
int enabled;
|
||||
@@ -45,7 +46,7 @@ static void fiber_schedule_to_req() {
|
||||
int error = 0;
|
||||
rb_protect(rb_fiber_schedule_to_req, 0, &error);
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
rack_plugin.exception_log(NULL);
|
||||
rb_gc_unregister_address(&ufiber.fib[id]);
|
||||
uwsgi.wsgi_req->async_status = UWSGI_OK;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
#include <GeoIP.h>
|
||||
#include <GeoIPCity.h>
|
||||
|
||||
struct uwsgi_geoip {
|
||||
char *country_db;
|
||||
char *city_db;
|
||||
GeoIP *country;
|
||||
GeoIP *city;
|
||||
|
||||
} ugeoip;
|
||||
|
||||
struct uwsgi_option uwsgi_geoip_options[] = {
|
||||
{"geoip-country", required_argument, 0, "load the specified geoip country database", uwsgi_opt_set_str, &ugeoip.country_db, 0},
|
||||
{"geoip-city", required_argument, 0, "load the specified geoip city database", uwsgi_opt_set_str, &ugeoip.city_db, 0},
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static int uwsgi_geoip_init() {
|
||||
if (ugeoip.country_db) {
|
||||
ugeoip.country = GeoIP_open(ugeoip.country_db, GEOIP_MEMORY_CACHE);
|
||||
if (!ugeoip.country) {
|
||||
uwsgi_log("unable to open GeoIP country database: %s\n", ugeoip.country_db);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (ugeoip.city_db) {
|
||||
ugeoip.city = GeoIP_open(ugeoip.city_db, GEOIP_MEMORY_CACHE);
|
||||
if (!ugeoip.city) {
|
||||
uwsgi_log("unable to open GeoIP city database: %s\n", ugeoip.city_db);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *uwsgi_route_var_geoip(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
uint32_t ip;
|
||||
char ip_str[16];
|
||||
// should be enough for geo coords
|
||||
char lonlat[64];
|
||||
memset(ip_str, 0, 16);
|
||||
memcpy(ip_str, wsgi_req->remote_addr, wsgi_req->remote_addr_len);
|
||||
if (inet_pton(AF_INET, ip_str, &ip) <= 0) {
|
||||
return NULL;
|
||||
}
|
||||
ip = htonl(ip);
|
||||
char *value = NULL;
|
||||
// always prefer the city database;
|
||||
GeoIP *g = ugeoip.city;
|
||||
if (!g) {
|
||||
g = ugeoip.country;
|
||||
if (g) {
|
||||
if (!uwsgi_strncmp(key, keylen, "country_code", 12)) {
|
||||
value = (char *) GeoIP_country_code_by_ipnum(g, ip);
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "country_code3", 13)) {
|
||||
value = (char *) GeoIP_country_code3_by_ipnum(g, ip);
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "country_name", 12)) {
|
||||
value = (char *) GeoIP_country_name_by_ipnum(g, ip);
|
||||
}
|
||||
|
||||
if (value) {
|
||||
*vallen = strlen(value);
|
||||
return uwsgi_str(value);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GeoIPRecord *gr = GeoIP_record_by_ipnum(g, ip);
|
||||
if (!gr) return NULL;
|
||||
|
||||
// ok let's generate the output
|
||||
if (!uwsgi_strncmp(key, keylen, "continent", 9)) {
|
||||
value = gr->continent_code;
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "country_code", 12)) {
|
||||
value = gr->country_code;
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "country_code3", 13)) {
|
||||
value = gr->country_code3;
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "country_name", 12)) {
|
||||
value = gr->country_name;
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "region", 6)) {
|
||||
value = gr->region;
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "region_name", 11)) {
|
||||
value = (char *) GeoIP_region_name_by_code(gr->country_code, gr->region);
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "city", 4)) {
|
||||
value = gr->city;
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "postal_code", 11)) {
|
||||
value = gr->postal_code;
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "latitude", 8) || !uwsgi_strncmp(key, keylen, "lat", 3)) {
|
||||
snprintf(lonlat, 64, "%f", gr->latitude);
|
||||
value = lonlat;
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "longitude", 9) || !uwsgi_strncmp(key, keylen, "lon", 3)) {
|
||||
snprintf(lonlat, 64, "%f", gr->longitude);
|
||||
value = lonlat;
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "dma", 3)) {
|
||||
snprintf(lonlat, 64, "%d", gr->dma_code);
|
||||
value = lonlat;
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "area", 4)) {
|
||||
snprintf(lonlat, 64, "%d", gr->area_code);
|
||||
value = lonlat;
|
||||
}
|
||||
|
||||
|
||||
if (value) {
|
||||
*vallen = strlen(value);
|
||||
char *ret = uwsgi_str(value);
|
||||
GeoIPRecord_delete(gr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
GeoIPRecord_delete(gr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void register_route_vars_geoip() {
|
||||
struct uwsgi_route_var *urv = uwsgi_register_route_var("geoip", uwsgi_route_var_geoip);
|
||||
urv->need_free = 1;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin geoip_plugin = {
|
||||
.name = "geoip",
|
||||
.options = uwsgi_geoip_options,
|
||||
.init = uwsgi_geoip_init,
|
||||
.on_load = register_route_vars_geoip,
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
NAME='geoip'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lGeoIP']
|
||||
|
||||
GCC_LIST = ['geoip']
|
||||
|
||||
+11
-1
@@ -18,6 +18,7 @@ static void uwsgi_opt_setup_gevent(char *opt, char *value, void *null) {
|
||||
|
||||
static struct uwsgi_option gevent_options[] = {
|
||||
{"gevent", required_argument, 0, "a shortcut enabling gevent loop engine with the specified number of async cores and optimal parameters", uwsgi_opt_setup_gevent, NULL, UWSGI_OPT_THREADS},
|
||||
{"gevent-monkey-patch", no_argument, 0, "call gevent.monkey.patch_all() automatically on startup", uwsgi_opt_true, &ugevent.monkey, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
@@ -317,6 +318,16 @@ static void gevent_loop() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// call gevent.monkey.patch_all() if requested
|
||||
if (ugevent.monkey) {
|
||||
PyObject *gevent_monkey_dict = get_uwsgi_pydict("gevent.monkey");
|
||||
if (!gevent_monkey_dict) uwsgi_pyexit;
|
||||
PyObject *gevent_monkey_patch_all = PyDict_GetItemString(gevent_monkey_dict, "patch_all");
|
||||
if (!gevent_monkey_patch_all) uwsgi_pyexit;
|
||||
PyObject *ret = python_call(gevent_monkey_patch_all, PyTuple_New(0), 0, NULL);
|
||||
if (!ret) uwsgi_pyexit;
|
||||
}
|
||||
|
||||
ugevent.spawn = PyDict_GetItemString(gevent_dict, "spawn");
|
||||
if (!ugevent.spawn) uwsgi_pyexit;
|
||||
|
||||
@@ -329,7 +340,6 @@ static void gevent_loop() {
|
||||
ugevent.greenlet_switch_args = PyTuple_New(0);
|
||||
Py_INCREF(ugevent.greenlet_switch_args);
|
||||
|
||||
|
||||
PyObject *gevent_get_hub = PyDict_GetItemString(gevent_dict, "get_hub");
|
||||
|
||||
ugevent.hub = python_call(gevent_get_hub, PyTuple_New(0), 0, NULL);
|
||||
|
||||
@@ -52,5 +52,6 @@ struct uwsgi_gevent {
|
||||
PyObject *signal_watcher;
|
||||
PyObject **watchers;
|
||||
int destroy;
|
||||
int monkey;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,285 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
#include <client/dbclient.h>
|
||||
#include <client/gridfs.h>
|
||||
|
||||
struct uwsgi_gridfs_mountpoint {
|
||||
char *mountpoint;
|
||||
uint16_t mountpoint_len;
|
||||
char *server;
|
||||
char *db;
|
||||
char *timeout_str;
|
||||
int timeout;
|
||||
char *no_mime;
|
||||
char *orig_filename;
|
||||
char *md5;
|
||||
char *etag;
|
||||
char *prefix;
|
||||
char *itemname;
|
||||
uint16_t itemname_len;
|
||||
char *skip_slash;
|
||||
uint16_t prefix_len;
|
||||
char *username;
|
||||
char *password;
|
||||
};
|
||||
|
||||
struct uwsgi_gridfs {
|
||||
int debug;
|
||||
struct uwsgi_string_list *mountpoints;
|
||||
} ugridfs;
|
||||
|
||||
struct uwsgi_option uwsgi_gridfs_options[] = {
|
||||
{(char *)"gridfs-mount", required_argument, 0, (char *)"mount a gridfs db on the specified mountpoint", uwsgi_opt_add_string_list, &ugridfs.mountpoints, UWSGI_OPT_MIME},
|
||||
{(char *)"gridfs-debug", no_argument, 0, (char *)"report gridfs mountpoint and itemname for each request (debug)", uwsgi_opt_true, &ugridfs.debug, UWSGI_OPT_MIME},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_plugin gridfs_plugin;
|
||||
|
||||
static void uwsgi_gridfs_do(struct wsgi_request *wsgi_req, struct uwsgi_gridfs_mountpoint *ugm, char *itemname, int need_free) {
|
||||
|
||||
try {
|
||||
mongo::scoped_ptr<mongo::ScopedDbConnection> conn( mongo::ScopedDbConnection::getScopedDbConnection(ugm->server, ugm->timeout) );
|
||||
try {
|
||||
if (ugm->username && ugm->password) {
|
||||
std::string errmsg;
|
||||
if ((*conn).conn().auth(ugm->db, ugm->username, ugm->password, errmsg)) {
|
||||
uwsgi_log("[uwsgi-gridfs]: %s\n", errmsg.c_str());
|
||||
(*conn).done();
|
||||
uwsgi_403(wsgi_req);
|
||||
return;
|
||||
}
|
||||
}
|
||||
mongo::GridFS gridfs((*conn).conn(), ugm->db);
|
||||
mongo::GridFile gfile = gridfs.findFile(itemname);
|
||||
if (need_free) {
|
||||
free(itemname);
|
||||
itemname = NULL;
|
||||
}
|
||||
if (!gfile.exists()) {
|
||||
(*conn).done();
|
||||
uwsgi_404(wsgi_req);
|
||||
return;
|
||||
}
|
||||
uwsgi_response_prepare_headers(wsgi_req, (char *)"200 OK", 6);
|
||||
// first get the content_type (if possibile)
|
||||
std::string filename = gfile.getFilename();
|
||||
if (!ugm->no_mime) {
|
||||
size_t mime_type_len = 0;
|
||||
char *mime_type = uwsgi_get_mime_type((char *)filename.c_str(), filename.length(), &mime_type_len);
|
||||
if (mime_type) {
|
||||
uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_len);
|
||||
}
|
||||
}
|
||||
if (ugm->orig_filename) {
|
||||
char *filename_header = uwsgi_concat3((char *)"inline; filename=\"", (char *)filename.c_str(), (char *)"\"");
|
||||
uwsgi_response_add_header(wsgi_req, (char *)"Content-Disposition", 19, filename_header, 19 + filename.length());
|
||||
free(filename_header);
|
||||
}
|
||||
uwsgi_response_add_content_length(wsgi_req, gfile.getContentLength());
|
||||
|
||||
if (ugm->etag) {
|
||||
std::string g_md5 = gfile.getMD5();
|
||||
if (!g_md5.empty()) {
|
||||
char *etag = uwsgi_concat3((char *)"\"", (char *)g_md5.c_str(), (char *)"\"");
|
||||
uwsgi_response_add_header(wsgi_req, (char *)"ETag", 4, etag, 2+g_md5.length());
|
||||
free(etag);
|
||||
}
|
||||
}
|
||||
|
||||
if (ugm->md5) {
|
||||
std::string g_md5 = gfile.getMD5();
|
||||
size_t base64_len = 0;
|
||||
char *base64 = uwsgi_base64_encode((char *)g_md5.c_str(), g_md5.length(), &base64_len);
|
||||
uwsgi_response_add_header(wsgi_req, (char *) "Content-MD5", 11, base64, base64_len);
|
||||
free(base64);
|
||||
}
|
||||
|
||||
if (uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, (char *)"HEAD", 4)) {
|
||||
int nc = gfile.getNumChunks();
|
||||
int i;
|
||||
for(i=0;i<nc;i++) {
|
||||
mongo::GridFSChunk gchunk = gfile.getChunk(i);
|
||||
int chunk_len = 0;
|
||||
const char *chunk = gchunk.data(chunk_len);
|
||||
uwsgi_response_write_body_do(wsgi_req, (char *) chunk, chunk_len);
|
||||
}
|
||||
}
|
||||
(*conn).done();
|
||||
}
|
||||
catch ( mongo::DBException &e ) {
|
||||
uwsgi_log("[uwsgi-gridfs]: %s\n", e.what());
|
||||
(*conn).done();
|
||||
if (need_free && itemname) {
|
||||
free(itemname);
|
||||
itemname = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( mongo::DBException &e ) {
|
||||
uwsgi_log("[uwsgi-gridfs]: %s\n", e.what());
|
||||
if (need_free && itemname) {
|
||||
free(itemname);
|
||||
itemname = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct uwsgi_gridfs_mountpoint *uwsgi_gridfs_add_mountpoint(char *arg, size_t arg_len) {
|
||||
struct uwsgi_gridfs_mountpoint *ugm = (struct uwsgi_gridfs_mountpoint *) uwsgi_calloc(sizeof(struct uwsgi_gridfs_mountpoint));
|
||||
if (uwsgi_kvlist_parse(arg, arg_len, ',', '=',
|
||||
"mountpoint", &ugm->mountpoint,
|
||||
"server", &ugm->server,
|
||||
"db", &ugm->db,
|
||||
"prefix", &ugm->prefix,
|
||||
"no_mime", &ugm->no_mime,
|
||||
"timeout", &ugm->timeout_str,
|
||||
"orig_filename", &ugm->orig_filename,
|
||||
"skip_slash", &ugm->skip_slash,
|
||||
"md5", &ugm->md5,
|
||||
"etag", &ugm->etag,
|
||||
"itemname", &ugm->itemname,
|
||||
"item", &ugm->itemname,
|
||||
"username", &ugm->username,
|
||||
"password", &ugm->password,
|
||||
NULL)) {
|
||||
uwsgi_log("invalid gridfs mountpoint syntax\n");
|
||||
free(ugm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!ugm->db) {
|
||||
uwsgi_log("you need to specify a \"db\" name for gridfs\n");
|
||||
free(ugm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!ugm->mountpoint) {
|
||||
ugm->mountpoint = (char *)"";
|
||||
}
|
||||
ugm->mountpoint_len = strlen(ugm->mountpoint);
|
||||
|
||||
if (!ugm->server) {
|
||||
ugm->server = (char *)"127.0.0.1:27017";
|
||||
}
|
||||
|
||||
if (ugm->timeout_str) {
|
||||
ugm->timeout = atoi(ugm->timeout_str);
|
||||
}
|
||||
else {
|
||||
ugm->timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
|
||||
}
|
||||
|
||||
if (ugm->prefix) {
|
||||
ugm->prefix_len = strlen(ugm->prefix);
|
||||
}
|
||||
|
||||
if (ugm->itemname) {
|
||||
ugm->itemname_len = strlen(ugm->itemname);
|
||||
}
|
||||
|
||||
return ugm;
|
||||
}
|
||||
|
||||
extern "C" int uwsgi_gridfs_request(struct wsgi_request *wsgi_req) {
|
||||
// this is the gridfs file
|
||||
char *itemname = NULL;
|
||||
|
||||
/* Standard GridFS request */
|
||||
if (!wsgi_req->uh->pktsize) {
|
||||
uwsgi_log( "Empty GridFS request. skip.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uwsgi_parse_vars(wsgi_req)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (wsgi_req->appid_len == 0) {
|
||||
if (!uwsgi.ignore_script_name) {
|
||||
wsgi_req->appid = wsgi_req->script_name;
|
||||
wsgi_req->appid_len = wsgi_req->script_name_len;
|
||||
}
|
||||
}
|
||||
|
||||
wsgi_req->app_id = uwsgi_get_app_id(wsgi_req->appid, wsgi_req->appid_len, gridfs_plugin.modifier1);
|
||||
if (ugridfs.debug) {
|
||||
uwsgi_log("[uwsgi-gridfs-debug] app_id = %d\n", wsgi_req->app_id);
|
||||
}
|
||||
|
||||
if (wsgi_req->app_id == -1) {
|
||||
uwsgi_404(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
struct uwsgi_app *ua = &uwsgi_apps[wsgi_req->app_id];
|
||||
|
||||
struct uwsgi_gridfs_mountpoint *ugm = (struct uwsgi_gridfs_mountpoint *) ua->interpreter;
|
||||
|
||||
if (ugm->skip_slash && (wsgi_req->path_info_len > 0 && wsgi_req->path_info[0] == '/')) {
|
||||
itemname = uwsgi_concat2n(ugm->prefix, ugm->prefix_len, wsgi_req->path_info+1, wsgi_req->path_info_len-1);
|
||||
}
|
||||
else {
|
||||
itemname = uwsgi_concat2n(ugm->prefix, ugm->prefix_len, wsgi_req->path_info, wsgi_req->path_info_len);
|
||||
}
|
||||
|
||||
if (ugridfs.debug) {
|
||||
uwsgi_log("[uwsgi-gridfs-debug] itemname = %s\n", itemname);
|
||||
}
|
||||
|
||||
// itemname will be freed here
|
||||
uwsgi_gridfs_do(wsgi_req, ugm, itemname, 1);
|
||||
|
||||
return UWSGI_OK;
|
||||
|
||||
}
|
||||
|
||||
|
||||
extern "C" void uwsgi_gridfs_mount() {
|
||||
struct uwsgi_string_list *usl = ugridfs.mountpoints;
|
||||
while(usl) {
|
||||
if (uwsgi_apps_cnt >= uwsgi.max_apps) {
|
||||
uwsgi_log("ERROR: you cannot load more than %d apps in a worker\n", uwsgi.max_apps);
|
||||
exit(1);
|
||||
}
|
||||
int id = uwsgi_apps_cnt;
|
||||
struct uwsgi_gridfs_mountpoint *ugm = uwsgi_gridfs_add_mountpoint(uwsgi_str(usl->value), usl->len);
|
||||
if (!ugm) exit(1);
|
||||
uwsgi_add_app(id, gridfs_plugin.modifier1, ugm->mountpoint, ugm->mountpoint_len, ugm, ugm);
|
||||
uwsgi_emulate_cow_for_apps(id);
|
||||
uwsgi_log("GridFS mountpoint \"%.*s\" (%d) added: server=%s db=%s\n", ugm->mountpoint_len, ugm->mountpoint, id, ugm->server, ugm->db);
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
static int uwsgi_routing_func_gridfs(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
|
||||
|
||||
struct uwsgi_gridfs_mountpoint *ugm = (struct uwsgi_gridfs_mountpoint *) ur->data2;
|
||||
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
struct uwsgi_buffer *ub_itemname = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ugm->itemname, ugm->itemname_len);
|
||||
if (!ub_itemname) return UWSGI_ROUTE_BREAK;
|
||||
if (ugridfs.debug) {
|
||||
uwsgi_log("[uwsgi-gridfs-debug] itemname = %s\n", ub_itemname->buf);
|
||||
}
|
||||
uwsgi_gridfs_do(wsgi_req, ugm, ub_itemname->buf, 0);
|
||||
uwsgi_buffer_destroy(ub_itemname);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
extern "C" int uwsgi_router_gridfs(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_gridfs;
|
||||
ur->data = args;
|
||||
ur->data_len = strlen(args);
|
||||
ur->data2 = uwsgi_gridfs_add_mountpoint((char *)ur->data, ur->data_len);
|
||||
if (!ur->data2) {
|
||||
exit(1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,31 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
int uwsgi_gridfs_request(struct wsgi_request *);
|
||||
void uwsgi_gridfs_mount();
|
||||
extern struct uwsgi_option uwsgi_gridfs_options[];
|
||||
|
||||
static void uwsgi_gridfs_log(struct wsgi_request *wsgi_req) {
|
||||
log_request(wsgi_req);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
int uwsgi_router_gridfs(struct uwsgi_route *, char *);
|
||||
static void uwsgi_gridfs_register_router() {
|
||||
uwsgi_register_router("gridfs", uwsgi_router_gridfs);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
struct uwsgi_plugin gridfs_plugin = {
|
||||
|
||||
.name = "gridfs",
|
||||
.modifier1 = 25,
|
||||
|
||||
.init_apps = uwsgi_gridfs_mount,
|
||||
.options = uwsgi_gridfs_options,
|
||||
.request = uwsgi_gridfs_request,
|
||||
.after_request = uwsgi_gridfs_log,
|
||||
#ifdef UWSGI_ROUTING
|
||||
.on_load = uwsgi_gridfs_register_router,
|
||||
#endif
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
import os
|
||||
|
||||
NAME='gridfs'
|
||||
|
||||
CFLAGS = ['-I/usr/include/mongo','-I/usr/local/include/mongo']
|
||||
LDFLAGS = []
|
||||
|
||||
LIBS = []
|
||||
if not 'UWSGI_MONGODB_NOLIB' in os.environ:
|
||||
LIBS.append('-lmongoclient')
|
||||
LIBS.append('-lstdc++')
|
||||
LIBS.append('-lboost_thread')
|
||||
LIBS.append('-lboost_system')
|
||||
LIBS.append('-lboost_filesystem')
|
||||
|
||||
GCC_LIST = ['plugin', 'gridfs.cc']
|
||||
+2
-2
@@ -587,6 +587,8 @@ ssize_t http_parse(struct corerouter_peer *main_peer) {
|
||||
size_t len = main_peer->in->pos;
|
||||
char *ptr = main_peer->in->buf;
|
||||
|
||||
hr->rnrn = 0;
|
||||
|
||||
for (j = 0; j < len; j++) {
|
||||
if (*ptr == '\r' && (hr->rnrn == 0 || hr->rnrn == 2)) {
|
||||
hr->rnrn++;
|
||||
@@ -770,8 +772,6 @@ int http_alloc_session(struct uwsgi_corerouter *ucr, struct uwsgi_gateway_socket
|
||||
|
||||
}
|
||||
|
||||
hr->rnrn = 0;
|
||||
|
||||
hr->port = ugs->port;
|
||||
hr->port_len = ugs->port_len;
|
||||
switch(ugs->mode) {
|
||||
|
||||
@@ -108,3 +108,5 @@ int uwsgi_jvm_object_to_response_body(struct wsgi_request *, jobject);
|
||||
jobject uwsgi_jvm_bytearray(char *, size_t);
|
||||
char *uwsgi_jvm_bytearray2c(jobject);
|
||||
void uwsgi_jvm_release_bytearray(jobject, char *);
|
||||
|
||||
jobject uwsgi_jvm_to_string(jobject);
|
||||
|
||||
@@ -243,6 +243,15 @@ jobject uwsgi_jvm_entryset(jobject o) {
|
||||
return uwsgi_jvm_call_object(o, mid);
|
||||
}
|
||||
|
||||
jobject uwsgi_jvm_to_string(jobject o) {
|
||||
jclass c = uwsgi_jvm_class_from_object(o);
|
||||
if (!c) return NULL;
|
||||
jmethodID mid = uwsgi_jvm_get_method_id_quiet(c, "toString", "()Ljava/lang/String;");
|
||||
uwsgi_jvm_local_unref(c);
|
||||
if (!mid) return NULL;
|
||||
return uwsgi_jvm_call_object(o, mid);
|
||||
}
|
||||
|
||||
int uwsgi_jvm_object_to_response_body(struct wsgi_request *wsgi_req, jobject body) {
|
||||
|
||||
// check for string
|
||||
@@ -297,20 +306,35 @@ int uwsgi_jvm_object_to_response_body(struct wsgi_request *wsgi_req, jobject bod
|
||||
ret = uwsgi_response_write_body_do(wsgi_req, c_body, c_body_len);
|
||||
uwsgi_jvm_release_chars(chunk, c_body);
|
||||
uwsgi_jvm_local_unref(chunk);
|
||||
if (ret) goto done;
|
||||
continue;
|
||||
}
|
||||
else if (uwsgi_jvm_object_is_instance(chunk, ujvm.bytearray_class)) {
|
||||
|
||||
if (uwsgi_jvm_object_is_instance(chunk, ujvm.bytearray_class)) {
|
||||
char *c_body = uwsgi_jvm_bytearray2c(chunk);
|
||||
size_t c_body_len = uwsgi_jvm_array_len(chunk);
|
||||
ret = uwsgi_response_write_body_do(wsgi_req, c_body, c_body_len);
|
||||
uwsgi_jvm_release_bytearray(chunk, c_body);
|
||||
uwsgi_jvm_local_unref(chunk);
|
||||
if (ret) goto done;
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("body iterable item must be java/lang/String or array of bytes!!!\n");
|
||||
uwsgi_jvm_local_unref(chunk);
|
||||
goto done;
|
||||
|
||||
jobject str_o = uwsgi_jvm_to_string(chunk);
|
||||
if (str_o) {
|
||||
char *c_body = uwsgi_jvm_str2c(str_o);
|
||||
size_t c_body_len = uwsgi_jvm_strlen(str_o);
|
||||
ret = uwsgi_response_write_body_do(wsgi_req, c_body, c_body_len);
|
||||
uwsgi_jvm_release_chars(str_o, c_body);
|
||||
uwsgi_jvm_local_unref(str_o);
|
||||
uwsgi_jvm_local_unref(chunk);
|
||||
if (ret) goto done;
|
||||
continue;
|
||||
}
|
||||
if (ret) goto done;
|
||||
|
||||
uwsgi_log("body iterable item must be java/lang/String or array of bytes!!!\n");
|
||||
uwsgi_jvm_local_unref(chunk);
|
||||
goto done;
|
||||
}
|
||||
done:
|
||||
uwsgi_jvm_local_unref(chunks);
|
||||
@@ -592,11 +616,10 @@ int uwsgi_jvm_consume_input_stream(struct wsgi_request *wsgi_req, size_t chunk,
|
||||
break;
|
||||
}
|
||||
// get the body of the array
|
||||
size_t buf_len = uwsgi_jvm_array_len(byte_buffer);
|
||||
char *buf = (char *) (*ujvm_env)->GetByteArrayElements(ujvm_env, byte_buffer, JNI_FALSE);
|
||||
if (!buf) { ret = -1; break; }
|
||||
//send
|
||||
if (uwsgi_response_write_body_do(wsgi_req, buf, buf_len)) {
|
||||
if (uwsgi_response_write_body_do(wsgi_req, buf, len)) {
|
||||
(*ujvm_env)->ReleaseByteArrayElements(ujvm_env, byte_buffer, (jbyte *) buf, 0);
|
||||
ret = -1; break;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import os,sys
|
||||
import os
|
||||
import shutil
|
||||
|
||||
NAME='jvm'
|
||||
|
||||
@@ -20,6 +21,9 @@ if operating_system == 'darwin':
|
||||
if os.path.exists(jvm):
|
||||
JVM_INCPATH = ["-Wno-deprecated-declarations", "-I%s" % jvm]
|
||||
JVM_LIBPATH = ["-framework JavaVM"]
|
||||
elif operating_system.startswith('cygwin'):
|
||||
JVM_INCPATH = ['-I"/cygdrive/c/Program Files/Java/jdk1.7.0_17/include"', '-I"/cygdrive/c/Program Files/Java/jdk1.7.0_17/include/win32"']
|
||||
JVM_LIBPATH = ['-L"/cygdrive/c/Program Files/Java/jdk1.7.0_17/jre/bin/server"']
|
||||
else:
|
||||
known_jvms = ('/usr/lib/jvm/java-7-openjdk', '/usr/local/openjdk7', '/usr/lib/jvm/java-6-openjdk', '/usr/local/openjdk', '/usr/java', '/usr/lib/jvm/java/')
|
||||
for jvm in known_jvms:
|
||||
@@ -33,15 +37,15 @@ else:
|
||||
JVM_LIBPATH = ["-L%s/jre/lib/%s/server" % (jvm, arch)]
|
||||
break
|
||||
|
||||
try:
|
||||
JVM_INCPATH = os.environ['UWSGICONFIG_JVM_INCPATH']
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
JVM_INCPATH = ['-I"' + os.environ['UWSGICONFIG_JVM_INCPATH'] + '"']
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
JVM_LIBPATH = os.environ['UWSGICONFIG_JVM_LIBPATH']
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
JVM_LIBPATH = ['-L"' + os.environ['UWSGICONFIG_JVM_LIBPATH'] + '"']
|
||||
except:
|
||||
pass
|
||||
|
||||
if not JVM_INCPATH or not JVM_LIBPATH:
|
||||
print("unable to autodetect the JVM path, please specify UWSGICONFIG_JVM_INCPATH and UWSGICONFIG_JVM_LIBPATH environment vars")
|
||||
@@ -66,3 +70,17 @@ def post_build(config):
|
||||
if os.system("cd %s/plugins/jvm ; jar cvf uwsgi.jar *.class" % os.getcwd()) != 0:
|
||||
os._exit(1)
|
||||
print("*** uwsgi.jar available in %s/plugins/jvm/uwsgi.jar ***" % os.getcwd())
|
||||
|
||||
env = os.environ.get('VIRTUAL_ENV')
|
||||
if env:
|
||||
src = "%s/plugins/jvm/uwsgi.jar" % os.getcwd()
|
||||
tgt = "%s/lib/uwsgi.jar" % env
|
||||
shutil.copyfile(src, tgt)
|
||||
print("*** uwsgi.jar had been copied to %s" % tgt)
|
||||
|
||||
plugin = "%s/jvm_plugin.so" % os.getcwd()
|
||||
if os.path.exists(plugin):
|
||||
tgt = "%s/bin/jvm_plugin.so" % env
|
||||
shutil.copyfile(plugin, tgt)
|
||||
print("*** jvm_plugin.so had been copied to %s" % tgt)
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
#ifdef UWSGI_LDAP
|
||||
|
||||
#include "uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
@@ -14,7 +12,22 @@ extern struct uwsgi_server uwsgi;
|
||||
#define ldap_unbind_ext_s ldap_unbind_ext
|
||||
#endif
|
||||
|
||||
void ldap2uwsgi(char *ldapname, char *uwsginame) {
|
||||
static void uwsgi_opt_ldap_dump(char *, char *, void *);
|
||||
static void uwsgi_opt_ldap_dump_ldif(char *, char *, void *);
|
||||
static void uwsgi_ldap_config(char *);
|
||||
|
||||
static void uwsgi_opt_load_ldap(char *opt, char *url, void *none) {
|
||||
uwsgi_ldap_config(url);
|
||||
}
|
||||
|
||||
static struct uwsgi_option uwsgi_ldap_options[] = {
|
||||
{"ldap", required_argument, 0, "load configuration from ldap server", uwsgi_opt_load_ldap, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"ldap-schema", no_argument, 0, "dump uWSGI ldap schema", uwsgi_opt_ldap_dump, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"ldap-schema-ldif", no_argument, 0, "dump uWSGI ldap schema in ldif format", uwsgi_opt_ldap_dump_ldif, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
static void ldap2uwsgi(char *ldapname, char *uwsginame) {
|
||||
char *ptr = uwsginame;
|
||||
|
||||
int i;
|
||||
@@ -32,7 +45,7 @@ void ldap2uwsgi(char *ldapname, char *uwsginame) {
|
||||
*ptr++ = 0;
|
||||
}
|
||||
|
||||
int calc_ldap_name(char *name) {
|
||||
static int calc_ldap_name(char *name) {
|
||||
int i;
|
||||
int counter = 0;
|
||||
|
||||
@@ -52,7 +65,7 @@ struct uwsgi_ldap_entry {
|
||||
};
|
||||
|
||||
|
||||
void uwsgi_name_to_ldap(char *src, char *dst) {
|
||||
static void uwsgi_name_to_ldap(char *src, char *dst) {
|
||||
|
||||
int i;
|
||||
char *ptr = dst;
|
||||
@@ -77,22 +90,7 @@ void uwsgi_name_to_ldap(char *src, char *dst) {
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_ldap_entry *get_ldap_by_num(struct uwsgi_ldap_entry *root, int num, int count) {
|
||||
|
||||
int i;
|
||||
struct uwsgi_ldap_entry *ule;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
ule = &root[i];
|
||||
if (ule->num == num) {
|
||||
return ule;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *name, int count) {
|
||||
static struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *name, int count) {
|
||||
int i;
|
||||
struct uwsgi_ldap_entry *ule;
|
||||
|
||||
@@ -106,7 +104,7 @@ struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_ldap_entry *get_ldap_names(int *count) {
|
||||
static struct uwsgi_ldap_entry *get_ldap_names(int *count) {
|
||||
|
||||
struct uwsgi_option *op = uwsgi.options;
|
||||
struct uwsgi_ldap_entry *ule, *entry;
|
||||
@@ -139,7 +137,7 @@ next:
|
||||
return ule;
|
||||
}
|
||||
|
||||
void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
|
||||
static void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
|
||||
|
||||
int i;
|
||||
int items;
|
||||
@@ -192,7 +190,7 @@ void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
|
||||
static void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
|
||||
|
||||
int i;
|
||||
int items;
|
||||
@@ -240,7 +238,7 @@ void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void uwsgi_ldap_config(char *url) {
|
||||
static void uwsgi_ldap_config(char *url) {
|
||||
|
||||
LDAP *ldp;
|
||||
LDAPMessage *results, *entry;
|
||||
@@ -367,4 +365,8 @@ void uwsgi_ldap_config(char *url) {
|
||||
ldap_unbind_ext_s(ldp, NULL, NULL);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
struct uwsgi_plugin ldap_plugin = {
|
||||
.name = "ldap",
|
||||
.options = uwsgi_ldap_options,
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
NAME='ldap'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lldap']
|
||||
|
||||
GCC_LIST = ['ldap']
|
||||
@@ -0,0 +1,173 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
this is an UDP logger encrypting each packet with the choosen algo, key and iv.
|
||||
|
||||
It is useful in cloud services without persistent storage for which you want to send logs to an external system.
|
||||
|
||||
Syntax: --logger/--req-logger crypto:addr=<udp_address>,algo=<algorithm>,secret=<key>,iv=<iv>,prefix=<prefix>
|
||||
|
||||
example:
|
||||
|
||||
uwsgi --plugin logcrypto --logger crypto:addr=127.0.0.1:1717,algo=bf-cbc,secret=ciaociao -M -p 4 -s :3031
|
||||
|
||||
*/
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_crypto_logger_conf {
|
||||
EVP_CIPHER_CTX *encrypt_ctx;
|
||||
char *addr;
|
||||
char *algo;
|
||||
char *secret;
|
||||
char *iv;
|
||||
char *prefix;
|
||||
size_t prefix_len;
|
||||
};
|
||||
|
||||
static void uwsgi_crypto_logger_setup_encryption(struct uwsgi_crypto_logger_conf *uclc) {
|
||||
|
||||
if (!uwsgi.ssl_initialized) {
|
||||
uwsgi_ssl_init();
|
||||
}
|
||||
|
||||
uclc->encrypt_ctx = uwsgi_malloc(sizeof(EVP_CIPHER_CTX));
|
||||
EVP_CIPHER_CTX_init(uclc->encrypt_ctx);
|
||||
|
||||
const EVP_CIPHER *cipher = EVP_get_cipherbyname(uclc->algo);
|
||||
if (!cipher) {
|
||||
uwsgi_log_safe("[uwsgi-logcrypto] unable to find algorithm/cipher\n");
|
||||
exit(1);
|
||||
}
|
||||
int cipher_len = EVP_CIPHER_key_length(cipher);
|
||||
|
||||
size_t s_len = strlen(uclc->secret);
|
||||
if ((unsigned int) cipher_len > s_len) {
|
||||
char *secret_tmp = uwsgi_malloc(cipher_len);
|
||||
memcpy(secret_tmp, uclc->secret, s_len);
|
||||
memset(secret_tmp + s_len, 0, cipher_len - s_len);
|
||||
uclc->secret = secret_tmp;
|
||||
}
|
||||
|
||||
int iv_len = EVP_CIPHER_iv_length(cipher);
|
||||
size_t s_iv_len = 0;
|
||||
if (uclc->iv) {
|
||||
s_iv_len = strlen(uclc->iv);
|
||||
}
|
||||
if ((unsigned int) iv_len > s_iv_len) {
|
||||
char *secret_tmp = uwsgi_malloc(iv_len);
|
||||
memcpy(secret_tmp, uclc->iv, s_iv_len);
|
||||
memset(secret_tmp + s_iv_len, '0', iv_len - s_iv_len);
|
||||
uclc->iv = secret_tmp;
|
||||
}
|
||||
|
||||
if (EVP_EncryptInit_ex(uclc->encrypt_ctx, cipher, NULL, (const unsigned char *) uclc->secret, (const unsigned char *) uclc->iv) <= 0) {
|
||||
uwsgi_error_safe("uwsgi_crypto_logger_setup_encryption()/EVP_EncryptInit_ex()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_crypto_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
|
||||
struct uwsgi_crypto_logger_conf *uclc = (struct uwsgi_crypto_logger_conf *) ul->data;
|
||||
|
||||
if (!ul->configured) {
|
||||
|
||||
uclc = uwsgi_calloc(sizeof(struct uwsgi_crypto_logger_conf));
|
||||
|
||||
if (uwsgi_kvlist_parse(ul->arg, strlen(ul->arg), ',', '=',
|
||||
"addr", &uclc->addr,
|
||||
"algo", &uclc->algo,
|
||||
"secret", &uclc->secret,
|
||||
"iv", &uclc->iv,
|
||||
"prefix", &uclc->prefix,
|
||||
NULL)) {
|
||||
uwsgi_log_safe("[uwsgi-logcrypto] unable to parse options\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!uclc->addr || !uclc->algo || !uclc->secret) {
|
||||
uwsgi_log_safe("[uwsgi-logcrypto] you have to specify at least addr,algo and secret options\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (uclc->prefix) {
|
||||
uclc->prefix_len = strlen(uclc->prefix);
|
||||
}
|
||||
|
||||
char *colon = strchr(uclc->addr, ':');
|
||||
if (!colon) {
|
||||
uwsgi_log_safe("[uwsgi-logcrypto] invalid UDP address\n");
|
||||
exit(1);
|
||||
}
|
||||
ul->addr_len = socket_to_in_addr(uclc->addr, colon, 0, &ul->addr.sa_in);
|
||||
|
||||
ul->fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (ul->fd < 0) {
|
||||
uwsgi_error_safe("uwsgi_crypto_logger()/socket()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_crypto_logger_setup_encryption(uclc);
|
||||
|
||||
ul->data = uclc;
|
||||
ul->configured = 1;
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
|
||||
if (uwsgi_buffer_num64(ub, uwsgi_micros())) goto error;
|
||||
if (uwsgi_buffer_append(ub, " ", 1)) goto error;
|
||||
if (uclc->prefix) {
|
||||
if (uwsgi_buffer_append(ub, uclc->prefix, uclc->prefix_len)) goto error;
|
||||
if (uwsgi_buffer_append(ub, " ", 1)) goto error;
|
||||
}
|
||||
if (uwsgi_buffer_append(ub, message, len)) goto error;
|
||||
|
||||
// let's encrypt the message
|
||||
unsigned char *encrypted = uwsgi_malloc(ub->pos + EVP_MAX_BLOCK_LENGTH);
|
||||
if (EVP_EncryptInit_ex(uclc->encrypt_ctx, NULL, NULL, NULL, NULL) <= 0) {
|
||||
uwsgi_error_safe("[uwsgi-logcrypto] EVP_EncryptInit_ex()");
|
||||
free(encrypted);
|
||||
goto error;
|
||||
}
|
||||
|
||||
int e_len = 0;
|
||||
if (EVP_EncryptUpdate(uclc->encrypt_ctx, encrypted, &e_len, (unsigned char *) ub->buf, ub->pos) <= 0) {
|
||||
uwsgi_error("[uwsgi-logcrypto] EVP_EncryptUpdate()");
|
||||
free(encrypted);
|
||||
goto error;
|
||||
}
|
||||
|
||||
int tmplen = 0;
|
||||
if (EVP_EncryptFinal_ex(uclc->encrypt_ctx, encrypted + e_len, &tmplen) <= 0) {
|
||||
uwsgi_error("[uwsgi-logcrypto] EVP_EncryptFinal_ex()");
|
||||
free(encrypted);
|
||||
goto error;
|
||||
}
|
||||
|
||||
uwsgi_buffer_destroy(ub);
|
||||
|
||||
ssize_t rlen = sendto(ul->fd, encrypted, e_len + tmplen, 0, (struct sockaddr *) &ul->addr.sa_in, ul->addr_len);
|
||||
free(encrypted);
|
||||
return rlen;
|
||||
|
||||
error:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
static void uwsgi_logcrypto_register() {
|
||||
uwsgi_register_logger("crypto", uwsgi_crypto_logger);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin logcrypto_plugin = {
|
||||
|
||||
.name = "logcrypto",
|
||||
.on_load = uwsgi_logcrypto_register,
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='logcrypto'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
GCC_LIST = ['logcrypto']
|
||||
+164
-23
@@ -8,15 +8,31 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_lua {
|
||||
struct lua_State **L;
|
||||
|
||||
char *shell;
|
||||
char *filename;
|
||||
struct uwsgi_string_list *load;
|
||||
} ulua;
|
||||
|
||||
#define lca(L, n) ulua_check_args(L, __FUNCTION__, n)
|
||||
|
||||
static void uwsgi_opt_luashell(char *opt, char *value, void *foobar) {
|
||||
|
||||
uwsgi.honour_stdin = 1;
|
||||
if (value) {
|
||||
ulua.shell = value;
|
||||
}
|
||||
else {
|
||||
ulua.shell = "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct uwsgi_option uwsgi_lua_options[] = {
|
||||
|
||||
{"lua", required_argument, 0, "load lua wsapi app", uwsgi_opt_set_str, &ulua.filename, 0},
|
||||
{"lua-load", required_argument, 0, "load a lua file", uwsgi_opt_add_string_list, &ulua.load, 0},
|
||||
{"lua-shell", no_argument, 0, "run the lua interactive shell (debug.debug())", uwsgi_opt_luashell, NULL, 0},
|
||||
{"luashell", no_argument, 0, "run the lua interactive shell (debug.debug())", uwsgi_opt_luashell, NULL, 0},
|
||||
|
||||
{0, 0, 0, 0},
|
||||
|
||||
@@ -69,7 +85,7 @@ static int uwsgi_api_register_rpc(lua_State *L) {
|
||||
lua_pushvalue(L, 2);
|
||||
func = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
|
||||
uwsgi_log("registered function %d in global table\n", func);
|
||||
uwsgi_log("registered function %d in Lua global table\n", func);
|
||||
lfunc = func;
|
||||
|
||||
if (uwsgi_register_rpc((char *)name, 6, 0, (void *) lfunc)) {
|
||||
@@ -345,6 +361,7 @@ static const luaL_reg uwsgi_api[] = {
|
||||
|
||||
{"lock", uwsgi_api_lock},
|
||||
{"unlock", uwsgi_api_unlock},
|
||||
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -387,36 +404,51 @@ static int uwsgi_lua_init(){
|
||||
static void uwsgi_lua_app() {
|
||||
int i;
|
||||
|
||||
if (ulua.filename) {
|
||||
if (!ulua.filename && !ulua.load && !ulua.shell) return;
|
||||
|
||||
for(i=0;i<uwsgi.cores;i++) {
|
||||
ulua.L[i] = luaL_newstate();
|
||||
luaL_openlibs(ulua.L[i]);
|
||||
luaL_register(ulua.L[i], "uwsgi", uwsgi_api);
|
||||
if (luaL_loadfile(ulua.L[i], ulua.filename)) {
|
||||
uwsgi_log("unable to load file %s: %s\n", ulua.filename, lua_tostring(ulua.L[i], -1));
|
||||
exit(1);
|
||||
|
||||
lua_pushstring(ulua.L[i], UWSGI_VERSION);
|
||||
lua_setfield(ulua.L[i], -2, "version");
|
||||
|
||||
struct uwsgi_string_list *usl = ulua.load;
|
||||
while(usl) {
|
||||
if (luaL_dofile(ulua.L[i], usl->value)) {
|
||||
uwsgi_log("unable to load Lua file %s: %s\n", usl->value, lua_tostring(ulua.L[i], -1));
|
||||
exit(1);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
if (ulua.filename) {
|
||||
if (luaL_loadfile(ulua.L[i], ulua.filename)) {
|
||||
uwsgi_log("unable to load Lua file %s: %s\n", ulua.filename, lua_tostring(ulua.L[i], -1));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// use a pcall
|
||||
//lua_call(ulua.L[i], 0, 1);
|
||||
if (lua_pcall(ulua.L[i], 0, 1, 0) != 0) {
|
||||
uwsgi_log("%s\n", lua_tostring(ulua.L[i], -1));
|
||||
exit(1);
|
||||
}
|
||||
// use a pcall
|
||||
//lua_call(ulua.L[i], 0, 1);
|
||||
if (lua_pcall(ulua.L[i], 0, 1, 0) != 0) {
|
||||
uwsgi_log("%s\n", lua_tostring(ulua.L[i], -1));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// if the loaded lua app returns as a table, fetch the
|
||||
// run function.
|
||||
if (lua_istable(ulua.L[i], 2)) {
|
||||
lua_pushstring(ulua.L[i], "run" );
|
||||
lua_gettable(ulua.L[i], 2);
|
||||
lua_replace(ulua.L[i], 2);
|
||||
}
|
||||
// if the loaded lua app returns as a table, fetch the
|
||||
// run function.
|
||||
if (lua_istable(ulua.L[i], 2)) {
|
||||
lua_pushstring(ulua.L[i], "run" );
|
||||
lua_gettable(ulua.L[i], 2);
|
||||
lua_replace(ulua.L[i], 2);
|
||||
}
|
||||
|
||||
if (! lua_isfunction(ulua.L[i], 2)) {
|
||||
uwsgi_log("Can't find WSAPI entry point (no function, nor a table with function'run').\n");
|
||||
exit(1);
|
||||
if (! lua_isfunction(ulua.L[i], 2)) {
|
||||
uwsgi_log("Can't find WSAPI entry point (no function, nor a table with function'run').\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -665,13 +697,119 @@ static uint16_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, uint16_t a
|
||||
#endif
|
||||
if (sl <= 0xffff) {
|
||||
memcpy(buffer, sv, sl);
|
||||
lua_pop(L, 1);
|
||||
return sl;
|
||||
}
|
||||
|
||||
lua_pop(L, 1);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static void uwsgi_lua_configurator_array(lua_State *L) {
|
||||
|
||||
int i;
|
||||
int n = luaL_getn(L, -3);
|
||||
|
||||
for(i=1;i<=n;i++) {
|
||||
lua_rawgeti(L, 1, i);
|
||||
if (lua_istable(L, -1)) {
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, -2) != 0) {
|
||||
char *key = uwsgi_str((char *)lua_tostring(L, -2));
|
||||
char *value = uwsgi_str((char *)lua_tostring(L, -1));
|
||||
add_exported_option(key, value, 0);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void uwsgi_lua_configurator(char *filename, char *magic_table[]) {
|
||||
size_t len = 0;
|
||||
uwsgi_log_initial("[uWSGI] getting Lua configuration from %s\n", filename);
|
||||
char *code = uwsgi_open_and_read(filename, &len, 1, magic_table);
|
||||
lua_State *L = luaL_newstate();
|
||||
if (!L) {
|
||||
uwsgi_log("unable to initialize Lua state for configuration\n");
|
||||
exit(1);
|
||||
}
|
||||
luaL_openlibs(L);
|
||||
if (luaL_dostring(L, code) != 0) {
|
||||
uwsgi_log("error running Lua configurator: %s\n", lua_tostring(L, -1));
|
||||
exit(1);
|
||||
}
|
||||
free(code);
|
||||
|
||||
if (!lua_istable(L, -1)) {
|
||||
uwsgi_log("Lua configurator has to return a table !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
lua_pushnil(L);
|
||||
// we always use uwsgi_str to avoid GC destroying our strings
|
||||
// and to be able to call lua_close at the end
|
||||
while (lua_next(L, -2) != 0) {
|
||||
// array ?
|
||||
if (lua_isnumber(L, -2)) {
|
||||
uwsgi_lua_configurator_array(L);
|
||||
break;
|
||||
}
|
||||
// dictionary
|
||||
else {
|
||||
char *key = uwsgi_str((char *)lua_tostring(L, -2));
|
||||
if (lua_istable(L, -1)) {
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, -2) != 0) {
|
||||
char *value = uwsgi_str((char *)lua_tostring(L, -1));
|
||||
add_exported_option(key, value, 0);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
char *value = uwsgi_str((char *)lua_tostring(L, -1));
|
||||
add_exported_option(key, value, 0);
|
||||
}
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
// this will destroy the whole Lua state
|
||||
lua_close(L);
|
||||
}
|
||||
|
||||
static void uwsgi_register_lua_features() {
|
||||
uwsgi_register_configurator(".lua", uwsgi_lua_configurator);
|
||||
}
|
||||
|
||||
static void uwsgi_lua_hijack(void) {
|
||||
if (ulua.shell && uwsgi.mywid == 1) {
|
||||
uwsgi.workers[uwsgi.mywid].hijacked = 1;
|
||||
uwsgi.workers[uwsgi.mywid].hijacked_count++;
|
||||
// re-map stdin to stdout and stderr if we are logging to a file
|
||||
if (uwsgi.logfile) {
|
||||
if (dup2(0, 1) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
}
|
||||
if (dup2(0, 2) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
}
|
||||
}
|
||||
int ret = -1;
|
||||
// run in the first state
|
||||
lua_State *L = ulua.L[0];
|
||||
lua_getglobal(L, "debug");
|
||||
lua_getfield(L, -1, "debug");
|
||||
ret = lua_pcall(L, 0, 0, 0);
|
||||
if (ret == 0) {
|
||||
exit(UWSGI_QUIET_CODE);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_plugin lua_plugin = {
|
||||
|
||||
@@ -685,8 +823,11 @@ struct uwsgi_plugin lua_plugin = {
|
||||
.magic = uwsgi_lua_magic,
|
||||
.signal_handler = uwsgi_lua_signal_handler,
|
||||
|
||||
.hijack_worker = uwsgi_lua_hijack,
|
||||
|
||||
.code_string = uwsgi_lua_code_string,
|
||||
.rpc = uwsgi_lua_rpc,
|
||||
|
||||
.on_load = uwsgi_register_lua_features,
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
a fake plugin used for preloading mongodb library when only available as static.
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_plugin mongodb_plugin = {
|
||||
.name = "mongodb",
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
NAME='mongodb'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = ['-Wl,-whole-archive', '-lmongoclient', '-Wl,-no-whole-archive', '-lboost_thread', '-lboost_system', '-lboost_filesystem']
|
||||
|
||||
GCC_LIST = ['plugin']
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
@@ -29,7 +29,7 @@ struct uwsgi_mongodb_state {
|
||||
struct iovec iovec[13];
|
||||
};
|
||||
|
||||
ssize_t uwsgi_mongodb_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
static ssize_t uwsgi_mongodb_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
|
||||
struct uwsgi_mongodb_state *ums = NULL;
|
||||
|
||||
@@ -151,7 +151,7 @@ done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void uwsgi_mongodblog_register() {
|
||||
static void uwsgi_mongodblog_register() {
|
||||
uwsgi_register_logger("mongodblog", uwsgi_mongodb_logger);
|
||||
}
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ static int sapi_uwsgi_send_headers(sapi_headers_struct *sapi_headers)
|
||||
}
|
||||
else {
|
||||
char *sl = SG(sapi_headers).http_status_line;
|
||||
uwsgi_response_prepare_headers(wsgi_req, sl, strlen(sl));
|
||||
uwsgi_response_prepare_headers(wsgi_req, sl + 8 , strlen(sl) - 8);
|
||||
}
|
||||
|
||||
h = zend_llist_get_first_ex(&sapi_headers->headers, &pos);
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int connect_prober_callback(int interesting_fd, struct uwsgi_signal_probe *up) {
|
||||
|
||||
// is this a timeout event ?
|
||||
if (interesting_fd == -1) {
|
||||
// am i wating for something ?
|
||||
if (up->fd != -1) {
|
||||
if (up->cycles > (uint64_t) up->timeout) {
|
||||
// reset the cycle
|
||||
up->cycles = 0;
|
||||
close(up->fd);
|
||||
up->fd = -1;
|
||||
// state = NOOP
|
||||
up->state = 0;
|
||||
// avoid duplicated events
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ok register a new event
|
||||
else {
|
||||
if ((up->cycles % up->freq) == 0) {
|
||||
up->fd = uwsgi_connect(up->args, -1, 1);
|
||||
if (up->fd != -1) {
|
||||
// status = CONNECTING
|
||||
up->state = 1;
|
||||
event_queue_add_fd_write(uwsgi.master_queue, up->fd);
|
||||
return 0;
|
||||
}
|
||||
// signal the bad event (if not already bad)
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (up->fd != -1) {
|
||||
// is this event for me ?
|
||||
if (interesting_fd == up->fd) {
|
||||
// uselsess here (we have only one state), only to show a good practice
|
||||
// check the state
|
||||
if (up->state == 1) {
|
||||
if (uwsgi_is_bad_connection(up->fd)) {
|
||||
// signal the bad connection (if needed)
|
||||
up->cycles = 0;
|
||||
close(up->fd);
|
||||
up->fd = -1;
|
||||
// state = NOOP
|
||||
up->state = 0;
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
// this is a good connection
|
||||
up->cycles = 0;
|
||||
close(up->fd);
|
||||
up->fd = -1;
|
||||
// state = NOOP
|
||||
up->state = 0;
|
||||
if (up->bad) {
|
||||
up->bad = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// default action
|
||||
return 0;
|
||||
}
|
||||
|
||||
int probeconnect_init() {
|
||||
|
||||
uwsgi_probe_register(&uwsgi.probes, "connect", connect_prober_callback);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin probeconnect_plugin = {
|
||||
|
||||
.init = probeconnect_init,
|
||||
};
|
||||
@@ -1,7 +0,0 @@
|
||||
|
||||
NAME='probeconnect'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
GCC_LIST = ['connectprobe']
|
||||
@@ -1,132 +0,0 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <libpq-fe.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
int pg_prober_callback(int, struct uwsgi_signal_probe *);
|
||||
int probepg_init(void);
|
||||
|
||||
int pg_prober_callback(int interesting_fd, struct uwsgi_signal_probe *up) {
|
||||
|
||||
// is this a timeout event ?
|
||||
if (interesting_fd == -1) {
|
||||
// am i wating for something ?
|
||||
if (up->fd != -1) {
|
||||
if (up->cycles > (uint64_t) up->timeout) {
|
||||
// reset the cycle
|
||||
up->cycles = 0;
|
||||
PQfinish((PGconn *) up->data);
|
||||
up->fd = -1;
|
||||
// state = NOOP
|
||||
up->state = 0;
|
||||
// avoid duplicated events
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ok register a new event
|
||||
else {
|
||||
if ((up->cycles % up->freq) == 0) {
|
||||
up->last_event = event_queue_write();
|
||||
up->data = (void *) PQconnectStart(up->args);
|
||||
if (up->data) {
|
||||
// status = CONNECTING
|
||||
up->state = PQstatus((PGconn *) up->data);
|
||||
if (up->state == CONNECTION_BAD)
|
||||
goto bad;
|
||||
up->fd = PQsocket((PGconn *) up->data);
|
||||
event_queue_add_fd_write(uwsgi.master_queue, up->fd);
|
||||
return 0;
|
||||
}
|
||||
bad:
|
||||
// signal the bad event (if not already bad)
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (up->fd != -1) {
|
||||
// is this event for me ?
|
||||
if (interesting_fd == up->fd) {
|
||||
// check the state
|
||||
up->state = PQstatus((PGconn *) up->data);
|
||||
if (up->state == CONNECTION_BAD) {
|
||||
// signal the bad connection (if needed)
|
||||
up->cycles = 0;
|
||||
PQfinish((PGconn *) up->data);
|
||||
up->fd = -1;
|
||||
up->state = 0;
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (up->state == CONNECTION_OK) {
|
||||
up->cycles = 0;
|
||||
PQfinish((PGconn *) up->data);
|
||||
up->fd = -1;
|
||||
// state = NOOP
|
||||
up->state = 0;
|
||||
if (up->bad) {
|
||||
up->bad = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// still wait...
|
||||
else {
|
||||
PostgresPollingStatusType wait_type = PQconnectPoll((PGconn *) up->data);
|
||||
// the connection is good
|
||||
if (wait_type == PGRES_POLLING_ACTIVE || wait_type == PGRES_POLLING_FAILED || wait_type == PGRES_POLLING_OK) {
|
||||
if (wait_type == PGRES_POLLING_ACTIVE)
|
||||
wait_type = PQconnectPoll((PGconn *) up->data);
|
||||
up->cycles = 0;
|
||||
up->fd = -1;
|
||||
// state = NOOP
|
||||
up->state = 0;
|
||||
PQfinish((PGconn *) up->data);
|
||||
if (wait_type == PGRES_POLLING_FAILED) {
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (up->bad) {
|
||||
up->bad = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (wait_type == PGRES_POLLING_READING) {
|
||||
event_queue_del_fd(uwsgi.master_queue, up->fd, up->last_event);
|
||||
event_queue_add_fd_read(uwsgi.master_queue, up->fd);
|
||||
up->last_event = event_queue_read();
|
||||
}
|
||||
else if (wait_type == PGRES_POLLING_WRITING) {
|
||||
event_queue_del_fd(uwsgi.master_queue, up->fd, up->last_event);
|
||||
event_queue_add_fd_write(uwsgi.master_queue, up->fd);
|
||||
up->last_event = event_queue_write();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// default action
|
||||
return 0;
|
||||
}
|
||||
|
||||
int probepg_init() {
|
||||
|
||||
uwsgi_probe_register(&uwsgi.probes, "pg", pg_prober_callback);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin probepg_plugin = {
|
||||
|
||||
.init = probepg_init,
|
||||
};
|
||||
@@ -1,9 +0,0 @@
|
||||
import os
|
||||
|
||||
NAME='probepg'
|
||||
CFLAGS = os.popen('pg_config --cflags').read().rstrip().split()
|
||||
CFLAGS.append('-I' + os.popen('pg_config --includedir').read().rstrip())
|
||||
LDFLAGS = os.popen('pg_config --ldflags').read().rstrip().split()
|
||||
LIBS = ['-L' + os.popen('pg_config --libdir').read().rstrip(), '-lpq']
|
||||
|
||||
GCC_LIST = ['pgprobe']
|
||||
@@ -9,8 +9,11 @@ extern struct uwsgi_plugin psgi_plugin;
|
||||
XS(XS_input_seek) {
|
||||
|
||||
dXSARGS;
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
psgi_check_args(1);
|
||||
uwsgi_request_body_seek(wsgi_req, SvIV(ST(0)));
|
||||
|
||||
XSRETURN(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -513,6 +513,10 @@ void uwsgi_perl_after_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
log_request(wsgi_req);
|
||||
|
||||
// We may be called after an early exit in XS_coroae_accept_request,
|
||||
// before the environ is set up.
|
||||
if (!wsgi_req->async_environ) return;
|
||||
|
||||
// dereference %env
|
||||
SV *env = SvRV((SV *) wsgi_req->async_environ);
|
||||
|
||||
@@ -664,7 +668,7 @@ void uwsgi_perl_run_hook(SV *hook) {
|
||||
}
|
||||
|
||||
static void uwsgi_perl_atexit() {
|
||||
if (uwsgi.mywid == -1) goto realstuff;
|
||||
if (uwsgi.mywid == 0) goto realstuff;
|
||||
|
||||
// if hijacked do not run atexit hooks
|
||||
if (uwsgi.workers[uwsgi.mywid].hijacked)
|
||||
|
||||
@@ -33,12 +33,12 @@ void set_dyn_pyhome(char *home, uint16_t pyhome_len) {
|
||||
}
|
||||
|
||||
// simulate a pythonhome directive
|
||||
if (uwsgi.wsgi_req->pyhome_len > 0) {
|
||||
if (uwsgi.wsgi_req->home_len > 0) {
|
||||
|
||||
PyObject *venv_path = UWSGI_PYFROMSTRINGSIZE(uwsgi.wsgi_req->pyhome, uwsgi.wsgi_req->pyhome_len);
|
||||
PyObject *venv_path = UWSGI_PYFROMSTRINGSIZE(uwsgi.wsgi_req->home, uwsgi.wsgi_req->home_len);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("setting dynamic virtualenv to %.*s\n", uwsgi.wsgi_req->pyhome_len, uwsgi.wsgi_req->pyhome);
|
||||
uwsgi_debug("setting dynamic virtualenv to %.*s\n", uwsgi.wsgi_req->home_len, uwsgi.wsgi_req->home);
|
||||
#endif
|
||||
|
||||
PyDict_SetItemString(pysys_dict, "prefix", venv_path);
|
||||
@@ -177,8 +177,8 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
wi->interpreter = up.main_thread;
|
||||
}
|
||||
|
||||
if (wsgi_req->pyhome_len) {
|
||||
set_dyn_pyhome(wsgi_req->pyhome, wsgi_req->pyhome_len);
|
||||
if (wsgi_req->home_len) {
|
||||
set_dyn_pyhome(wsgi_req->home, wsgi_req->home_len);
|
||||
}
|
||||
|
||||
if (wsgi_req->touch_reload_len > 0 && wsgi_req->touch_reload_len < 0xff) {
|
||||
@@ -196,8 +196,6 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
goto doh;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// the module contains multiple apps
|
||||
if (PyDict_Check((PyObject *)wi->callable)) {
|
||||
applications = wi->callable;
|
||||
|
||||
@@ -25,7 +25,12 @@ void uwsgi_opt_pythonpath(char *opt, char *value, void *foobar) {
|
||||
void uwsgi_opt_pyshell(char *opt, char *value, void *foobar) {
|
||||
|
||||
uwsgi.honour_stdin = 1;
|
||||
up.pyshell = 1;
|
||||
if (value) {
|
||||
up.pyshell = value;
|
||||
}
|
||||
else {
|
||||
up.pyshell = "";
|
||||
}
|
||||
|
||||
if (!strcmp("pyshell-oneshot", opt)) {
|
||||
up.pyshell_oneshot = 1;
|
||||
@@ -55,7 +60,6 @@ void uwsgi_opt_pyver(char *opt, char *foo, void *bar) {
|
||||
}
|
||||
|
||||
|
||||
#ifdef UWSGI_INI
|
||||
void uwsgi_opt_ini_paste(char *opt, char *value, void *foobar) {
|
||||
|
||||
uwsgi_opt_load_ini(opt, value, NULL);
|
||||
@@ -72,7 +76,6 @@ void uwsgi_opt_ini_paste(char *opt, char *value, void *foobar) {
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
struct uwsgi_option uwsgi_python_options[] = {
|
||||
{"wsgi-file", required_argument, 0, "load .wsgi file", uwsgi_opt_set_str, &up.file_config, 0},
|
||||
@@ -121,16 +124,16 @@ struct uwsgi_option uwsgi_python_options[] = {
|
||||
{"web3", required_argument, 0, "load a web3 app", uwsgi_opt_set_str, &up.web3, 0},
|
||||
{"pump", required_argument, 0, "load a pump app", uwsgi_opt_set_str, &up.pump, 0},
|
||||
{"wsgi-lite", required_argument, 0, "load a wsgi-lite app", uwsgi_opt_set_str, &up.wsgi_lite, 0},
|
||||
#ifdef UWSGI_INI
|
||||
{"ini-paste", required_argument, 0, "load a paste.deploy config file containing uwsgi section", uwsgi_opt_ini_paste, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"ini-paste-logged", required_argument, 0, "load a paste.deploy config file containing uwsgi section (load loggers too)", uwsgi_opt_ini_paste, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#endif
|
||||
{"reload-os-env", no_argument, 0, "force reload of os.environ at each request", uwsgi_opt_true, &up.reload_os_env, 0},
|
||||
#ifndef __CYGWIN__
|
||||
#ifndef UWSGI_PYPY
|
||||
{"no-site", no_argument, 0, "do not import site module", uwsgi_opt_true, &Py_NoSiteFlag, 0},
|
||||
#endif
|
||||
{"pyshell", no_argument, 0, "run an interactive python shell in the uWSGI environment", uwsgi_opt_pyshell, NULL, 0},
|
||||
{"pyshell-oneshot", no_argument, 0, "run an interactive python shell in the uWSGI environment (one-shot variant)", uwsgi_opt_pyshell, NULL, 0},
|
||||
#endif
|
||||
{"pyshell", optional_argument, 0, "run an interactive python shell in the uWSGI environment", uwsgi_opt_pyshell, NULL, 0},
|
||||
{"pyshell-oneshot", optional_argument, 0, "run an interactive python shell in the uWSGI environment (one-shot variant)", uwsgi_opt_pyshell, NULL, 0},
|
||||
|
||||
{"python", required_argument, 0, "run a python script in the uWSGI environment", uwsgi_opt_pyrun, NULL, 0},
|
||||
{"py", required_argument, 0, "run a python script in the uWSGI environment", uwsgi_opt_pyrun, NULL, 0},
|
||||
@@ -292,7 +295,7 @@ void uwsgi_python_reset_random_seed() {
|
||||
|
||||
void uwsgi_python_atexit() {
|
||||
|
||||
if (uwsgi.mywid == -1) goto realstuff;
|
||||
if (uwsgi.mywid == 0) goto realstuff;
|
||||
|
||||
// if hijacked do not run atexit hooks
|
||||
if (uwsgi.workers[uwsgi.mywid].hijacked)
|
||||
@@ -1065,9 +1068,7 @@ void uwsgi_python_init_apps() {
|
||||
#endif
|
||||
|
||||
// setup app loaders
|
||||
#ifdef UWSGI_MINTERPRETERS
|
||||
up.loaders[LOADER_DYN] = uwsgi_dyn_loader;
|
||||
#endif
|
||||
up.loaders[LOADER_UWSGI] = uwsgi_uwsgi_loader;
|
||||
up.loaders[LOADER_FILE] = uwsgi_file_loader;
|
||||
up.loaders[LOADER_PASTE] = uwsgi_paste_loader;
|
||||
@@ -1692,11 +1693,17 @@ void uwsgi_python_hijack(void) {
|
||||
}
|
||||
}
|
||||
UWSGI_GET_GIL;
|
||||
PyImport_ImportModule("readline");
|
||||
int ret = -1;
|
||||
if (up.pyshell[0] != 0) {
|
||||
ret = PyRun_SimpleString(up.pyshell);
|
||||
}
|
||||
else {
|
||||
PyImport_ImportModule("readline");
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
int ret = PyRun_InteractiveLoop(stdin, "uwsgi");
|
||||
|
||||
ret = PyRun_InteractiveLoop(stdin, "uwsgi");
|
||||
#endif
|
||||
}
|
||||
if (up.pyshell_oneshot) {
|
||||
exit(UWSGI_DE_HIJACKED_CODE);
|
||||
}
|
||||
@@ -1704,7 +1711,6 @@ void uwsgi_python_hijack(void) {
|
||||
if (ret == 0) {
|
||||
exit(UWSGI_QUIET_CODE);
|
||||
}
|
||||
#endif
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,26 +210,6 @@ PyObject *py_uwsgi_add_cron(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
|
||||
PyObject *py_uwsgi_add_probe(PyObject * self, PyObject * args) {
|
||||
|
||||
uint8_t uwsgi_signal;
|
||||
int timeout = 0;
|
||||
int freq = 0;
|
||||
char *probe, *probe_args;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "Bss|ii:add_probe", &uwsgi_signal, &probe, &probe_args, &timeout, &freq)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (uwsgi_add_probe(uwsgi_signal, probe, probe_args, timeout, freq))
|
||||
return PyErr_Format(PyExc_ValueError, "unable to add probe");
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PyObject *py_uwsgi_add_timer(PyObject * self, PyObject * args) {
|
||||
|
||||
uint8_t uwsgi_signal;
|
||||
@@ -474,6 +454,37 @@ PyObject *py_uwsgi_lord_scroll(PyObject * self, PyObject * args) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void scrolls_items(uint16_t pos, char *key, uint16_t keylen, void *data) {
|
||||
PyObject *list = (PyObject *) data;
|
||||
PyObject *zero = PyString_FromStringAndSize(key, keylen);
|
||||
PyList_Append(list, zero);
|
||||
Py_DECREF(zero);
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_scrolls(PyObject * self, PyObject * args) {
|
||||
char *legion_name = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s:scrolls", &legion_name)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint64_t rlen = 0;
|
||||
char *buf = uwsgi_legion_scrolls(legion_name, &rlen);
|
||||
if (!buf) goto end;
|
||||
PyObject *list = PyList_New(0);
|
||||
if (uwsgi_hooked_parse_array(buf, rlen, scrolls_items, list)) {
|
||||
goto error;
|
||||
}
|
||||
free(buf);
|
||||
return list;
|
||||
error:
|
||||
free(buf);
|
||||
end:
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
PyObject *py_uwsgi_register_signal(PyObject * self, PyObject * args) {
|
||||
@@ -2413,7 +2424,6 @@ static PyMethodDef uwsgi_advanced_methods[] = {
|
||||
{"signal_received", py_uwsgi_signal_received, METH_VARARGS, ""},
|
||||
{"add_file_monitor", py_uwsgi_add_file_monitor, METH_VARARGS, ""},
|
||||
{"add_timer", py_uwsgi_add_timer, METH_VARARGS, ""},
|
||||
{"add_probe", py_uwsgi_add_probe, METH_VARARGS, ""},
|
||||
{"add_rb_timer", py_uwsgi_add_rb_timer, METH_VARARGS, ""},
|
||||
{"add_cron", py_uwsgi_add_cron, METH_VARARGS, ""},
|
||||
|
||||
@@ -2434,6 +2444,7 @@ static PyMethodDef uwsgi_advanced_methods[] = {
|
||||
#ifdef UWSGI_SSL
|
||||
{"i_am_the_lord", py_uwsgi_i_am_the_lord, METH_VARARGS, ""},
|
||||
{"lord_scroll", py_uwsgi_lord_scroll, METH_VARARGS, ""},
|
||||
{"scrolls", py_uwsgi_scrolls, METH_VARARGS, ""},
|
||||
#endif
|
||||
{"async_sleep", py_uwsgi_async_sleep, METH_VARARGS, ""},
|
||||
{"async_connect", py_uwsgi_async_connect, METH_VARARGS, ""},
|
||||
|
||||
@@ -106,7 +106,7 @@ struct uwsgi_python {
|
||||
|
||||
char *test_module;
|
||||
|
||||
int pyshell;
|
||||
char *pyshell;
|
||||
int pyshell_oneshot;
|
||||
|
||||
|
||||
@@ -268,10 +268,6 @@ struct uwsgi_buffer *uwsgi_python_exception_repr(struct wsgi_request *);
|
||||
struct uwsgi_buffer *uwsgi_python_backtrace(struct wsgi_request *);
|
||||
void uwsgi_python_exception_log(struct wsgi_request *);
|
||||
|
||||
#ifdef UWSGI_PYPY
|
||||
#undef UWSGI_MINTERPRETERS
|
||||
#endif
|
||||
|
||||
#define py_current_wsgi_req() current_wsgi_req();\
|
||||
if (!wsgi_req) {\
|
||||
return PyErr_Format(PyExc_SystemError, "you can call uwsgi api function only from the main callable");\
|
||||
|
||||
@@ -42,6 +42,9 @@ if not 'UWSGI_PYTHON_NOLIB' in os.environ:
|
||||
if not os.path.exists(libpath):
|
||||
libpath = '%s/libpython%s.a' % (libdir, version)
|
||||
LIBS.append(libpath)
|
||||
# hack for messy linkers/compilers
|
||||
if '-lutil' in LIBS:
|
||||
LIBS.append('-lutil')
|
||||
else:
|
||||
try:
|
||||
LDFLAGS.append("-L%s" % sysconfig.get_config_var('LIBDIR'))
|
||||
|
||||
@@ -135,11 +135,34 @@ static PyObject *uwsgi_Input_close(uwsgi_Input *self, PyObject *args) {
|
||||
|
||||
static PyObject *uwsgi_Input_seek(uwsgi_Input *self, PyObject *args) {
|
||||
long pos = 0;
|
||||
int whence = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "l:seek", &pos)) {
|
||||
if (!uwsgi.post_buffering) {
|
||||
return PyErr_Format(PyExc_IOError, "seeking wsgi.input without post_buffering is IMPOSSIBLE !!!");
|
||||
}
|
||||
|
||||
if (!PyArg_ParseTuple(args, "l|i:seek", &pos, &whence)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
uwsgi_request_body_seek() uses SEEK_SET for positive value and SEEK_CUR for negative
|
||||
yous hould always try to transform the "pos" value to an absolute position.
|
||||
*/
|
||||
|
||||
// current
|
||||
if (whence == 1) {
|
||||
pos += self->wsgi_req->post_pos;
|
||||
}
|
||||
// end of stream
|
||||
if (whence == 2) {
|
||||
pos += self->wsgi_req->post_cl;
|
||||
}
|
||||
|
||||
if (pos < 0 || pos > (off_t)self->wsgi_req->post_cl) {
|
||||
return PyErr_Format(PyExc_IOError, "invalid seek position for wsgi.input");
|
||||
}
|
||||
|
||||
uwsgi_request_body_seek(self->wsgi_req, pos);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
@@ -151,6 +174,12 @@ static PyObject *uwsgi_Input_fileno(uwsgi_Input *self, PyObject *args) {
|
||||
return PyInt_FromLong(self->wsgi_req->fd);
|
||||
}
|
||||
|
||||
static PyObject *uwsgi_Input_tell(uwsgi_Input *self, PyObject *args) {
|
||||
|
||||
return PyLong_FromLong(self->wsgi_req->post_pos);
|
||||
}
|
||||
|
||||
|
||||
static PyMethodDef uwsgi_Input_methods[] = {
|
||||
{ "read", (PyCFunction)uwsgi_Input_read, METH_VARARGS, 0 },
|
||||
{ "readline", (PyCFunction)uwsgi_Input_readline, METH_VARARGS, 0 },
|
||||
@@ -158,6 +187,7 @@ static PyMethodDef uwsgi_Input_methods[] = {
|
||||
// add close to allow mod_wsgi compatibility
|
||||
{ "close", (PyCFunction)uwsgi_Input_close, METH_VARARGS, 0 },
|
||||
{ "seek", (PyCFunction)uwsgi_Input_seek, METH_VARARGS, 0 },
|
||||
{ "tell", (PyCFunction)uwsgi_Input_tell, METH_VARARGS, 0 },
|
||||
{ "fileno", (PyCFunction)uwsgi_Input_fileno, METH_VARARGS, 0 },
|
||||
{ NULL, NULL}
|
||||
};
|
||||
@@ -317,7 +347,6 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( (wsgi_req->app_id = uwsgi_get_app_id(wsgi_req->appid, wsgi_req->appid_len, 0)) == -1) {
|
||||
wsgi_req->app_id = uwsgi.default_app;
|
||||
if (uwsgi.no_default_app) {
|
||||
|
||||
@@ -58,11 +58,12 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
char *status_line = NULL;
|
||||
size_t status_line_len = 0;
|
||||
#ifdef PYTHREE
|
||||
PyObject *zero = NULL;
|
||||
PyObject *zero2 = NULL;
|
||||
if (self != Py_None) {
|
||||
PyObject *zero = PyUnicode_AsASCIIString(head);
|
||||
zero = PyUnicode_AsASCIIString(head);
|
||||
status_line = PyBytes_AsString(zero);
|
||||
status_line_len = PyBytes_Size(zero);
|
||||
Py_DECREF(zero);
|
||||
}
|
||||
else {
|
||||
status_line = PyBytes_AsString(head);
|
||||
@@ -73,9 +74,15 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
status_line_len = PyString_Size(head);
|
||||
#endif
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, status_line, status_line_len)) {
|
||||
#ifdef PYTHREE
|
||||
Py_DECREF(zero);
|
||||
#endif
|
||||
return PyErr_Format(PyExc_TypeError, "unable to set HTTP status line");
|
||||
}
|
||||
|
||||
#ifdef PYTHREE
|
||||
Py_DECREF(zero);
|
||||
#endif
|
||||
|
||||
headers = PyTuple_GetItem(args, 1);
|
||||
if (!headers) {
|
||||
@@ -125,10 +132,9 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
|
||||
#ifdef PYTHREE
|
||||
if (self != Py_None) {
|
||||
PyObject *zero = PyUnicode_AsASCIIString(h_key);
|
||||
zero = PyUnicode_AsASCIIString(h_key);
|
||||
k = PyBytes_AsString(zero);
|
||||
kl = PyBytes_Size(zero);
|
||||
Py_DECREF(zero);
|
||||
}
|
||||
else {
|
||||
k = PyBytes_AsString(h_key);
|
||||
@@ -141,10 +147,9 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
|
||||
#ifdef PYTHREE
|
||||
if (self != Py_None) {
|
||||
PyObject *zero = PyUnicode_AsASCIIString(h_value);
|
||||
v = PyBytes_AsString(zero);
|
||||
vl = PyBytes_Size(zero);
|
||||
Py_DECREF(zero);
|
||||
zero2 = PyUnicode_AsASCIIString(h_value);
|
||||
v = PyBytes_AsString(zero2);
|
||||
vl = PyBytes_Size(zero2);
|
||||
}
|
||||
else {
|
||||
v = PyBytes_AsString(h_value);
|
||||
@@ -156,9 +161,18 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
#endif
|
||||
|
||||
if (uwsgi_response_add_header(wsgi_req, k, kl, v, vl)) {
|
||||
#ifdef PYTHREE
|
||||
Py_DECREF(zero);
|
||||
Py_DECREF(zero2);
|
||||
#endif
|
||||
return PyErr_Format(PyExc_TypeError, "unable to add header to the response");
|
||||
}
|
||||
|
||||
#ifdef PYTHREE
|
||||
Py_DECREF(zero);
|
||||
Py_DECREF(zero2);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
if (up.start_response_nodelay) {
|
||||
|
||||
+77
-16
@@ -5,6 +5,22 @@ extern struct uwsgi_server uwsgi;
|
||||
struct uwsgi_rack ur;
|
||||
struct uwsgi_plugin rack_plugin;
|
||||
|
||||
static void uwsgi_opt_rbshell(char *opt, char *value, void *foobar) {
|
||||
|
||||
uwsgi.honour_stdin = 1;
|
||||
if (value) {
|
||||
ur.rbshell = value;
|
||||
}
|
||||
else {
|
||||
ur.rbshell = "";
|
||||
}
|
||||
|
||||
if (!strcmp("rbshell-oneshot", opt)) {
|
||||
ur.rb_shell_oneshot = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_option uwsgi_rack_options[] = {
|
||||
|
||||
{"rails", required_argument, 0, "load a rails <= 2.x app", uwsgi_opt_set_str, &ur.rails, UWSGI_OPT_POST_BUFFERING},
|
||||
@@ -29,7 +45,8 @@ struct uwsgi_option uwsgi_rack_options[] = {
|
||||
|
||||
{"rvm-path", required_argument, 0, "search for rvm in the specified directory", uwsgi_opt_add_string_list, &ur.rvm_path, 0},
|
||||
|
||||
{"rbshell", optional_argument, 0, "run a ruby/irb shell", uwsgi_opt_true, &ur.rb_shell, 0},
|
||||
{"rbshell", optional_argument, 0, "run a ruby/irb shell", uwsgi_opt_rbshell, NULL, 0},
|
||||
{"rbshell-oneshot", no_argument, 0, "set ruby/irb shell (one shot)", uwsgi_opt_rbshell, NULL, 0},
|
||||
|
||||
#ifdef RUBY19
|
||||
{"rb-threads", required_argument, 0, "set the number of ruby threads to run", uwsgi_opt_set_int, &ur.rb_threads, 0},
|
||||
@@ -320,7 +337,7 @@ uint16_t uwsgi_ruby_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[],
|
||||
ret = rb_protect(rack_call_rpc_handler, rb_args, &error);
|
||||
|
||||
if (error) {
|
||||
uwsgi_manage_exception(NULL, 0);
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -489,7 +506,7 @@ void uwsgi_rack_preinit_apps() {
|
||||
int error = 0;
|
||||
rb_protect( uwsgi_require_file, rb_str_new2(usl->value), &error ) ;
|
||||
if (error) {
|
||||
uwsgi_manage_exception(NULL, 0);
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
@@ -519,7 +536,7 @@ void uwsgi_rack_init_apps(void) {
|
||||
error = 0;
|
||||
rb_protect( uwsgi_require_file, rb_str_new2(usl->value), &error ) ;
|
||||
if (error) {
|
||||
uwsgi_manage_exception(NULL, 0);
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
@@ -527,7 +544,7 @@ void uwsgi_rack_init_apps(void) {
|
||||
if (ur.rack) {
|
||||
ur.dispatcher = rb_protect(init_rack_app, rb_str_new2(ur.rack), &error);
|
||||
if (error) {
|
||||
uwsgi_manage_exception(NULL, 0);
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
exit(1);
|
||||
}
|
||||
if (ur.dispatcher == Qnil) {
|
||||
@@ -551,7 +568,7 @@ void uwsgi_rack_init_apps(void) {
|
||||
uwsgi_log("loading rails app %s\n", ur.rails);
|
||||
rb_protect( require_rails, 0, &error ) ;
|
||||
if (error) {
|
||||
uwsgi_manage_exception(NULL, 0);
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("rails app %s ready\n", ur.rails);
|
||||
@@ -573,7 +590,7 @@ void uwsgi_rack_init_apps(void) {
|
||||
if (acim_call == Qtrue) {
|
||||
ur.dispatcher = rb_protect(uwsgi_rb_call_new, ac_dispatcher, &error);
|
||||
if (error) {
|
||||
uwsgi_manage_exception(NULL, 0);
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@@ -583,7 +600,7 @@ void uwsgi_rack_init_apps(void) {
|
||||
uwsgi_log("non-rack rails version detected...loading thin adapter...\n");
|
||||
rb_protect( require_thin, 0, &error ) ;
|
||||
if (error) {
|
||||
uwsgi_manage_exception(NULL, 0);
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
exit(1);
|
||||
}
|
||||
VALUE thin_rack = rb_const_get(rb_cObject, rb_intern("Rack"));
|
||||
@@ -591,7 +608,7 @@ void uwsgi_rack_init_apps(void) {
|
||||
VALUE thin_rack_adapter_rails = rb_const_get(thin_rack_adapter, rb_intern("Rails"));
|
||||
ur.dispatcher = rb_protect( uwsgi_rb_call_new, thin_rack_adapter_rails, &error);
|
||||
if (error) {
|
||||
uwsgi_manage_exception(NULL, 0);
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@@ -963,7 +980,7 @@ VALUE init_rack_app( VALUE script ) {
|
||||
#endif
|
||||
rb_protect( require_rack, 0, &error ) ;
|
||||
if (error) {
|
||||
uwsgi_manage_exception(NULL, 0);
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
@@ -1029,7 +1046,51 @@ int uwsgi_rack_mount_app(char *mountpoint, char *app) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
void uwsgi_rack_hijack(void) {
|
||||
VALUE run_irb(VALUE arg) {
|
||||
rb_funcall(rb_cObject, rb_intern("require"), 1, rb_str_new2("irb"));
|
||||
VALUE irb = rb_const_get(rb_cObject, rb_intern("IRB"));
|
||||
return rb_funcall(irb, rb_intern("start"), 0);
|
||||
}
|
||||
|
||||
static void uwsgi_rack_hijack(void) {
|
||||
if (ur.rb_shell_oneshot && uwsgi.workers[uwsgi.mywid].hijacked_count > 0) {
|
||||
uwsgi.workers[uwsgi.mywid].hijacked = 0;
|
||||
return;
|
||||
}
|
||||
if (ur.rbshell && uwsgi.mywid == 1) {
|
||||
uwsgi.workers[uwsgi.mywid].hijacked = 1;
|
||||
uwsgi.workers[uwsgi.mywid].hijacked_count++;
|
||||
// re-map stdin to stdout and stderr if we are logging to a file
|
||||
if (uwsgi.logfile) {
|
||||
if (dup2(0, 1) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
}
|
||||
if (dup2(0, 2) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
}
|
||||
}
|
||||
int ret = -1;
|
||||
int error = 0;
|
||||
if (ur.rbshell[0] != 0) {
|
||||
rb_eval_string(ur.rbshell);
|
||||
}
|
||||
else {
|
||||
rb_protect( run_irb, 0, &error ) ;
|
||||
if (error) {
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (ur.rb_shell_oneshot) {
|
||||
exit(UWSGI_DE_HIJACKED_CODE);
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
exit(UWSGI_QUIET_CODE);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_rack_mule(char *opt) {
|
||||
@@ -1038,7 +1099,7 @@ int uwsgi_rack_mule(char *opt) {
|
||||
if (uwsgi_endswith(opt, (char *)".rb")) {
|
||||
rb_protect( uwsgi_require_file, rb_str_new2(opt), &error ) ;
|
||||
if (error) {
|
||||
uwsgi_manage_exception(NULL, 0);
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -1063,7 +1124,7 @@ void uwsgi_rb_post_fork() {
|
||||
// call the post_fork_hook
|
||||
rb_protect(uwsgi_rb_pfh, 0, &error);
|
||||
if (error) {
|
||||
uwsgi_manage_exception(NULL, 0);
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1081,7 +1142,7 @@ int uwsgi_rack_mule_msg(char *message, size_t len) {
|
||||
VALUE arg = rb_str_new(message, len);
|
||||
rb_protect(uwsgi_rb_mmh, arg, &error);
|
||||
if (error) {
|
||||
uwsgi_manage_exception(NULL, 0);
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -1107,7 +1168,7 @@ int uwsgi_rack_signal_handler(uint8_t sig, void *handler) {
|
||||
rb_ary_store(args, 1, rbsig);
|
||||
rb_protect(rack_call_signal_handler, args, &error);
|
||||
if (error) {
|
||||
uwsgi_manage_exception(NULL, 0);
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
rb_gc();
|
||||
return -1;
|
||||
}
|
||||
@@ -1155,7 +1216,7 @@ int uwsgi_rack_spooler(char *filename, char *buf, uint16_t len, char *body, size
|
||||
|
||||
VALUE ret = rb_protect(uwsgi_rb_do_spooler, spool_dict, &error);
|
||||
if (error) {
|
||||
uwsgi_manage_exception(NULL, 0);
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
rb_gc();
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,8 @@ struct uwsgi_rack {
|
||||
|
||||
pthread_mutex_t gvl;
|
||||
|
||||
int rb_shell;
|
||||
char *rbshell;
|
||||
int rb_shell_oneshot;
|
||||
int app_id;
|
||||
|
||||
int unprotected;
|
||||
|
||||
@@ -244,7 +244,7 @@ static int uwsgi_ring_request(struct wsgi_request *wsgi_req) {
|
||||
// *** REQUEST GENERATION ***
|
||||
|
||||
if (uwsgi_ring_request_item_add_keyword(hm, "request-method", 14, wsgi_req->method, wsgi_req->method_len)) goto end;
|
||||
if (uwsgi_ring_request_item_add(hm, "uri", 3, wsgi_req->uri, wsgi_req->uri_len)) goto end;
|
||||
if (uwsgi_ring_request_item_add(hm, "uri", 3, wsgi_req->path_info, wsgi_req->path_info_len)) goto end;
|
||||
if (uwsgi_ring_request_item_add(hm, "server-name", 11, wsgi_req->host, wsgi_req->host_len)) goto end;
|
||||
|
||||
// server-port is required !!!
|
||||
@@ -450,10 +450,13 @@ static int uwsgi_ring_setup() {
|
||||
}
|
||||
|
||||
char *namespace = uwsgi_str(uring.app);
|
||||
char *colon = strchr(namespace, ':');
|
||||
char *colon = strchr(namespace, '/');
|
||||
if (!colon) {
|
||||
uwsgi_log("invalid ring application namespace/handler\n");
|
||||
exit(1);
|
||||
colon = strchr(namespace, ':');
|
||||
if (!colon) {
|
||||
uwsgi_log("invalid ring application namespace/handler\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
*colon = 0;
|
||||
uring.handler = uwsgi_jvm_call_object_static(clojure, clojure_var, uwsgi_jvm_str(namespace, 0), uwsgi_jvm_str(colon+1, 0));
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import os
|
||||
import shutil
|
||||
|
||||
jvm_path = 'plugins/jvm'
|
||||
|
||||
up = {}
|
||||
@@ -14,3 +17,13 @@ CFLAGS.append('-I%s' % jvm_path)
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
GCC_LIST = ['ring_plugin']
|
||||
|
||||
def post_build(config):
|
||||
env = os.environ.get('VIRTUAL_ENV')
|
||||
if env:
|
||||
plugin = "%s/ring_plugin.so" % os.getcwd()
|
||||
if os.path.exists(plugin):
|
||||
tgt = "%s/bin/ring_plugin.so" % env
|
||||
shutil.copyfile(plugin, tgt)
|
||||
print("*** ring_plugin.so had been copied to %s" % tgt)
|
||||
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
|
||||
#ifdef __linux__
|
||||
#include <crypt.h>
|
||||
#elif defined(__CYGWIN__)
|
||||
#include <crypt.h>
|
||||
pthread_mutex_t ur_basicauth_crypt_mutex;
|
||||
#else
|
||||
pthread_mutex_t ur_basicauth_crypt_mutex;
|
||||
#endif
|
||||
|
||||
@@ -10,83 +10,134 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
syntax:
|
||||
|
||||
route = /^foobar1(.*)/ cache:key=foo$1poo,type=body
|
||||
route = /^foobar1 cache:var=PATH_INFO,type=body
|
||||
route = /^foobar2 cache:var=REQUEST_URI,type=full
|
||||
route = /^foobar3 cache:var=REQUEST_URI,type=body,content_type=text/html
|
||||
route = /^foobar1(.*)/ cache:key=foo$1poo,content_type=text/html,name=foobar
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_router_cache_conf {
|
||||
|
||||
// the name of the cache
|
||||
char *name;
|
||||
size_t name_len;
|
||||
|
||||
char *key;
|
||||
size_t key_len;
|
||||
char *var;
|
||||
char *type;
|
||||
|
||||
long var_offset;
|
||||
long var_offset_len;
|
||||
|
||||
char *content_type;
|
||||
char *name;
|
||||
size_t content_type_len;
|
||||
|
||||
// 0 -> full, 1 -> body
|
||||
int type_num;
|
||||
struct uwsgi_cache *cache;
|
||||
|
||||
char *expires_str;
|
||||
uint64_t expires;
|
||||
|
||||
};
|
||||
|
||||
// be tolerant on errors
|
||||
static int uwsgi_routing_func_cache_store(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
|
||||
struct uwsgi_router_cache_conf *urcc = (struct uwsgi_router_cache_conf *) ur->data2;
|
||||
|
||||
// overwrite previous run
|
||||
if (wsgi_req->cache_it) {
|
||||
uwsgi_buffer_destroy(wsgi_req->cache_it);
|
||||
wsgi_req->cache_it = NULL;
|
||||
}
|
||||
|
||||
if (wsgi_req->cache_it_to) {
|
||||
uwsgi_buffer_destroy(wsgi_req->cache_it_to);
|
||||
wsgi_req->cache_it_to = NULL;
|
||||
}
|
||||
|
||||
// build key and name
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
wsgi_req->cache_it = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urcc->key, urcc->key_len);
|
||||
if (!wsgi_req->cache_it) return UWSGI_ROUTE_NEXT;
|
||||
|
||||
if (urcc->name) {
|
||||
wsgi_req->cache_it_to = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urcc->name, urcc->name_len);
|
||||
if (!wsgi_req->cache_it_to) {
|
||||
uwsgi_buffer_destroy(wsgi_req->cache_it);
|
||||
wsgi_req->cache_it = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
wsgi_req->cache_it_expires = urcc->expires;
|
||||
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
|
||||
}
|
||||
|
||||
static int uwsgi_routing_func_cache(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
|
||||
|
||||
struct uwsgi_router_cache_conf *urcc = (struct uwsgi_router_cache_conf *) ur->data2;
|
||||
|
||||
if (!uwsgi.cache_max_items) return UWSGI_ROUTE_NEXT;
|
||||
|
||||
char *c_k = NULL;
|
||||
uint16_t c_k_len = 0;
|
||||
int k_need_free = 0;
|
||||
|
||||
if (urcc->key) {
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
c_k = uwsgi_regexp_apply_ovec(*subject, *subject_len, urcc->key, urcc->key_len, ur->ovector, ur->ovn);
|
||||
c_k_len = strlen(c_k);
|
||||
k_need_free = 1;
|
||||
}
|
||||
else {
|
||||
char **key = (char **) (((char *) wsgi_req) + urcc->var_offset);
|
||||
uint16_t *keylen = (uint16_t *) (((char *) wsgi_req) + urcc->var_offset_len);
|
||||
c_k = *key;
|
||||
c_k_len = *keylen;
|
||||
}
|
||||
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, urcc->key, urcc->key_len);
|
||||
if (!ub) return UWSGI_ROUTE_BREAK;
|
||||
|
||||
uint64_t valsize = 0;
|
||||
char *value = uwsgi_cache_magic_get(c_k, c_k_len, &valsize, urcc->name);
|
||||
char *value = uwsgi_cache_magic_get(ub->buf, ub->pos, &valsize, urcc->name);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
if (value) {
|
||||
if (urcc->type_num == 1) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto error;
|
||||
if (uwsgi_response_add_content_type(wsgi_req, urcc->content_type, urcc->content_type_len)) goto error;
|
||||
if (uwsgi_response_add_content_length(wsgi_req, valsize)) goto error;
|
||||
}
|
||||
// body only
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto error;
|
||||
if (uwsgi_response_add_content_type(wsgi_req, urcc->content_type, urcc->content_type_len)) goto error;
|
||||
if (uwsgi_response_add_content_length(wsgi_req, valsize)) goto error;
|
||||
uwsgi_response_write_body_do(wsgi_req, value, valsize);
|
||||
free(value);
|
||||
if (k_need_free) free(c_k);
|
||||
if (ur->custom)
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
if (k_need_free) free(c_k);
|
||||
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
error:
|
||||
free(value);
|
||||
if (k_need_free) free(c_k);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
static int uwsgi_router_cache_store(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_cache_store;
|
||||
ur->data = args;
|
||||
ur->data_len = strlen(args);
|
||||
struct uwsgi_router_cache_conf *urcc = uwsgi_calloc(sizeof(struct uwsgi_router_cache_conf));
|
||||
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
|
||||
"key", &urcc->key,
|
||||
"name", &urcc->name,
|
||||
"expires", &urcc->expires_str, NULL)) {
|
||||
uwsgi_log("invalid cachestore route syntax: %s\n", args);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (urcc->key) {
|
||||
urcc->key_len = strlen(urcc->key);
|
||||
}
|
||||
|
||||
if (urcc->name) {
|
||||
urcc->name_len = strlen(urcc->name);
|
||||
}
|
||||
|
||||
if (!urcc->key) {
|
||||
uwsgi_log("invalid cachestore route syntax: you need to specify a cache key\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (urcc->expires_str) {
|
||||
urcc->expires = strtoul(urcc->expires_str, NULL, 10);
|
||||
}
|
||||
|
||||
ur->data2 = urcc;
|
||||
return 0;
|
||||
error:
|
||||
if (urcc->key) free(urcc->key);
|
||||
if (urcc->name) free(urcc->name);
|
||||
if (urcc->expires_str) free(urcc->expires_str);
|
||||
free(urcc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int uwsgi_router_cache(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_cache;
|
||||
ur->data = args;
|
||||
@@ -94,10 +145,9 @@ static int uwsgi_router_cache(struct uwsgi_route *ur, char *args) {
|
||||
struct uwsgi_router_cache_conf *urcc = uwsgi_calloc(sizeof(struct uwsgi_router_cache_conf));
|
||||
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
|
||||
"key", &urcc->key,
|
||||
"var", &urcc->var,
|
||||
"content_type", &urcc->content_type,
|
||||
"name", &urcc->name,
|
||||
"type", &urcc->type, NULL)) {
|
||||
NULL)) {
|
||||
uwsgi_log("invalid route syntax: %s\n", args);
|
||||
exit(1);
|
||||
}
|
||||
@@ -106,35 +156,15 @@ static int uwsgi_router_cache(struct uwsgi_route *ur, char *args) {
|
||||
urcc->key_len = strlen(urcc->key);
|
||||
}
|
||||
|
||||
if (!urcc->key && !urcc->var) {
|
||||
uwsgi_log("invalid route syntax: you need to specify a cache key or var\n");
|
||||
if (!urcc->key) {
|
||||
uwsgi_log("invalid route syntax: you need to specify a cache key\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!urcc->type) urcc->type = "full";
|
||||
if (!urcc->content_type) urcc->content_type = "text/html";
|
||||
|
||||
urcc->content_type_len = strlen(urcc->content_type);
|
||||
|
||||
if (urcc->var) {
|
||||
if (!strcmp(urcc->var, "REQUEST_URI")) {
|
||||
urcc->var_offset = offsetof(struct wsgi_request, uri);
|
||||
urcc->var_offset_len = offsetof(struct wsgi_request, uri_len);
|
||||
}
|
||||
else if (!strcmp(urcc->var, "PATH_INFO")) {
|
||||
urcc->var_offset = offsetof(struct wsgi_request, path_info);
|
||||
urcc->var_offset_len = offsetof(struct wsgi_request, path_info_len);
|
||||
}
|
||||
else {
|
||||
urcc->var_offset = offsetof(struct wsgi_request, uri);
|
||||
urcc->var_offset_len = offsetof(struct wsgi_request, uri_len);
|
||||
}
|
||||
}
|
||||
|
||||
if (!strcmp(urcc->type, "body")) {
|
||||
urcc->type_num = 1;
|
||||
}
|
||||
|
||||
ur->data2 = urcc;
|
||||
return 0;
|
||||
}
|
||||
@@ -148,6 +178,8 @@ static int uwsgi_router_cache_continue(struct uwsgi_route *ur, char *args) {
|
||||
static void router_cache_register() {
|
||||
uwsgi_register_router("cache", uwsgi_router_cache);
|
||||
uwsgi_register_router("cache-continue", uwsgi_router_cache_continue);
|
||||
uwsgi_register_router("cachestore", uwsgi_router_cache_store);
|
||||
uwsgi_register_router("cache-store", uwsgi_router_cache_store);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin router_cache_plugin = {
|
||||
|
||||
@@ -40,10 +40,342 @@ static int uwsgi_rpc_request(struct wsgi_request *wsgi_req) {
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
static int uwsgi_routing_func_rpc(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
int ret = -1;
|
||||
// this is the list of args
|
||||
char *argv[UMAX8];
|
||||
// this is the size of each argument
|
||||
uint16_t argvs[UMAX8];
|
||||
// this is a placeholder for tmp uwsgi_buffers
|
||||
struct uwsgi_buffer *ubs[UMAX8];
|
||||
|
||||
char **r_argv = (char **) ur->data2;
|
||||
uint16_t *r_argvs = (uint16_t *) ur->data3;
|
||||
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
uint64_t i;
|
||||
for(i=0;i<ur->custom;i++) {
|
||||
ubs[i] = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, r_argv[i], r_argvs[i]);
|
||||
if (!ubs[i]) goto end;
|
||||
argv[i] = ubs[i]->buf;
|
||||
argvs[i] = ubs[i]->pos;
|
||||
}
|
||||
|
||||
// ok we now need to check it it is a local call or a remote one
|
||||
char *func = uwsgi_str(ur->data);
|
||||
char *remote = NULL;
|
||||
char *at = strchr(func, '@');
|
||||
if (at) {
|
||||
*at = 0;
|
||||
remote = at+1;
|
||||
}
|
||||
uint16_t size;
|
||||
char *response = uwsgi_do_rpc(remote, func, ur->custom, argv, argvs, &size);
|
||||
free(func);
|
||||
if (!response) goto end;
|
||||
|
||||
ret = UWSGI_ROUTE_BREAK;
|
||||
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) {free(response) ; goto end;}
|
||||
if (uwsgi_response_add_content_length(wsgi_req, size)) {free(response) ; goto end;}
|
||||
uwsgi_response_write_body_do(wsgi_req, response, size);
|
||||
free(response);
|
||||
|
||||
end:
|
||||
for(i=0;i<ur->custom;i++) {
|
||||
if (ubs[i] != NULL) {
|
||||
uwsgi_buffer_destroy(ubs[i]);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_routing_func_rpc_blob(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
int ret = -1;
|
||||
// this is the list of args
|
||||
char *argv[UMAX8];
|
||||
// this is the size of each argument
|
||||
uint16_t argvs[UMAX8];
|
||||
// this is a placeholder for tmp uwsgi_buffers
|
||||
struct uwsgi_buffer *ubs[UMAX8];
|
||||
|
||||
char **r_argv = (char **) ur->data2;
|
||||
uint16_t *r_argvs = (uint16_t *) ur->data3;
|
||||
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
uint64_t i;
|
||||
for(i=0;i<ur->custom;i++) {
|
||||
ubs[i] = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, r_argv[i], r_argvs[i]);
|
||||
if (!ubs[i]) goto end;
|
||||
argv[i] = ubs[i]->buf;
|
||||
argvs[i] = ubs[i]->pos;
|
||||
}
|
||||
|
||||
// ok we now need to check it it is a local call or a remote one
|
||||
char *func = uwsgi_str(ur->data);
|
||||
char *remote = NULL;
|
||||
char *at = strchr(func, '@');
|
||||
if (at) {
|
||||
*at = 0;
|
||||
remote = at+1;
|
||||
}
|
||||
uint16_t size;
|
||||
char *response = uwsgi_do_rpc(remote, func, ur->custom, argv, argvs, &size);
|
||||
free(func);
|
||||
if (!response) goto end;
|
||||
|
||||
ret = UWSGI_ROUTE_NEXT;
|
||||
|
||||
// optimization
|
||||
if (!wsgi_req->headers_sent) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) {free(response) ; goto end;}
|
||||
if (uwsgi_response_add_connection_close(wsgi_req)) {free(response) ; goto end;}
|
||||
}
|
||||
uwsgi_response_write_body_do(wsgi_req, response, size);
|
||||
free(response);
|
||||
|
||||
end:
|
||||
for(i=0;i<ur->custom;i++) {
|
||||
if (ubs[i] != NULL) {
|
||||
uwsgi_buffer_destroy(ubs[i]);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_routing_func_rpc_raw(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
int ret = -1;
|
||||
// this is the list of args
|
||||
char *argv[UMAX8];
|
||||
// this is the size of each argument
|
||||
uint16_t argvs[UMAX8];
|
||||
// this is a placeholder for tmp uwsgi_buffers
|
||||
struct uwsgi_buffer *ubs[UMAX8];
|
||||
|
||||
char **r_argv = (char **) ur->data2;
|
||||
uint16_t *r_argvs = (uint16_t *) ur->data3;
|
||||
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
uint64_t i;
|
||||
for(i=0;i<ur->custom;i++) {
|
||||
ubs[i] = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, r_argv[i], r_argvs[i]);
|
||||
if (!ubs[i]) goto end;
|
||||
argv[i] = ubs[i]->buf;
|
||||
argvs[i] = ubs[i]->pos;
|
||||
}
|
||||
|
||||
// ok we now need to check it it is a local call or a remote one
|
||||
char *func = uwsgi_str(ur->data);
|
||||
char *remote = NULL;
|
||||
char *at = strchr(func, '@');
|
||||
if (at) {
|
||||
*at = 0;
|
||||
remote = at+1;
|
||||
}
|
||||
uint16_t size;
|
||||
char *response = uwsgi_do_rpc(remote, func, ur->custom, argv, argvs, &size);
|
||||
free(func);
|
||||
if (!response) goto end;
|
||||
|
||||
ret = UWSGI_ROUTE_NEXT;
|
||||
if (size == 0) goto end;
|
||||
|
||||
ret = uwsgi_blob_to_response(wsgi_req, response, size);
|
||||
free(response);
|
||||
if (ret == 0) {
|
||||
ret = UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
end:
|
||||
for(i=0;i<ur->custom;i++) {
|
||||
if (ubs[i] != NULL) {
|
||||
uwsgi_buffer_destroy(ubs[i]);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// "next" || "continue" || "break(.*)" || "goon" || "goto .+"
|
||||
static int uwsgi_routing_func_rpc_ret(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
int ret = -1;
|
||||
// this is the list of args
|
||||
char *argv[UMAX8];
|
||||
// this is the size of each argument
|
||||
uint16_t argvs[UMAX8];
|
||||
// this is a placeholder for tmp uwsgi_buffers
|
||||
struct uwsgi_buffer *ubs[UMAX8];
|
||||
|
||||
char **r_argv = (char **) ur->data2;
|
||||
uint16_t *r_argvs = (uint16_t *) ur->data3;
|
||||
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
uint64_t i;
|
||||
for(i=0;i<ur->custom;i++) {
|
||||
ubs[i] = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, r_argv[i], r_argvs[i]);
|
||||
if (!ubs[i]) goto end;
|
||||
argv[i] = ubs[i]->buf;
|
||||
argvs[i] = ubs[i]->pos;
|
||||
}
|
||||
|
||||
// ok we now need to check it it is a local call or a remote one
|
||||
char *func = uwsgi_str(ur->data);
|
||||
char *remote = NULL;
|
||||
char *at = strchr(func, '@');
|
||||
if (at) {
|
||||
*at = 0;
|
||||
remote = at+1;
|
||||
}
|
||||
uint16_t size;
|
||||
char *response = uwsgi_do_rpc(remote, func, ur->custom, argv, argvs, &size);
|
||||
free(func);
|
||||
if (!response) goto end;
|
||||
|
||||
ret = UWSGI_ROUTE_CONTINUE;
|
||||
if (!uwsgi_strncmp(response, size, "next", 4 )) {
|
||||
ret = UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
else if (!uwsgi_strncmp(response, size, "continue", 8 )) {
|
||||
ret = UWSGI_ROUTE_CONTINUE;
|
||||
}
|
||||
else if (!uwsgi_strncmp(response, size, "goon", 4 )) {
|
||||
ret = UWSGI_ROUTE_GOON;
|
||||
}
|
||||
else if (!uwsgi_starts_with(response, size, "break", 5 )) {
|
||||
ret = UWSGI_ROUTE_BREAK;
|
||||
if (size > 6) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, response+6, size-6)) goto end0;
|
||||
if (uwsgi_response_add_connection_close(wsgi_req)) goto end0;
|
||||
if (uwsgi_response_add_content_type(wsgi_req, "text/plain", 10)) goto end0;
|
||||
// no need to check for return value
|
||||
uwsgi_response_write_headers_do(wsgi_req);
|
||||
}
|
||||
}
|
||||
else if (!uwsgi_starts_with(response, size, "goto ", 5)) {
|
||||
ret = UWSGI_ROUTE_BREAK;
|
||||
if (size > 5) {
|
||||
// find the label
|
||||
struct uwsgi_route *routes = uwsgi.routes;
|
||||
while(routes) {
|
||||
if (!routes->label) goto next;
|
||||
if (!uwsgi_strncmp(routes->label, routes->label_len, response+5, size-5)) {
|
||||
ret = UWSGI_ROUTE_NEXT;
|
||||
wsgi_req->route_goto = routes->pos;
|
||||
goto found;
|
||||
}
|
||||
next:
|
||||
routes = routes->next;
|
||||
}
|
||||
goto end0;
|
||||
found:
|
||||
if (wsgi_req->route_goto <= wsgi_req->route_pc) {
|
||||
wsgi_req->route_goto = 0;
|
||||
uwsgi_log("[uwsgi-route] ERROR \"goto\" instruction can only jump forward (check your label !!!)\n");
|
||||
ret = UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end0:
|
||||
free(response);
|
||||
|
||||
end:
|
||||
for(i=0;i<ur->custom;i++) {
|
||||
if (ubs[i] != NULL) {
|
||||
uwsgi_buffer_destroy(ubs[i]);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
ur->data = the func name
|
||||
ur->custom = the number of arguments
|
||||
ur->data2 = the pointer to the args
|
||||
ur->data3 = the pointer to the args sizes
|
||||
*/
|
||||
static int uwsgi_router_rpc_base(struct uwsgi_route *ur, char *args) {
|
||||
ur->custom = 0;
|
||||
ur->data2 = uwsgi_calloc(sizeof(char *) * UMAX8);
|
||||
ur->data3 = uwsgi_calloc(sizeof(uint16_t) * UMAX8);
|
||||
char *p = strtok(args, " ");
|
||||
while(p) {
|
||||
if (!ur->data) {
|
||||
ur->data = p;
|
||||
}
|
||||
else {
|
||||
if (ur->custom >= UMAX8) {
|
||||
uwsgi_log("unable to register route: maximum number of rpc args reached\n");
|
||||
free(ur->data2);
|
||||
free(ur->data3);
|
||||
return -1;
|
||||
}
|
||||
char **argv = (char **) ur->data2;
|
||||
uint16_t *argvs = (uint16_t *) ur->data3;
|
||||
argv[ur->custom] = p;
|
||||
argvs[ur->custom] = strlen(p);
|
||||
ur->custom++;
|
||||
}
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
|
||||
if (!ur->data) {
|
||||
uwsgi_log("unable to register route: you need to specify an rpc function\n");
|
||||
free(ur->data2);
|
||||
free(ur->data3);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_router_rpc(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_rpc;
|
||||
return uwsgi_router_rpc_base(ur, args);
|
||||
}
|
||||
|
||||
static int uwsgi_router_rpc_ret(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_rpc_ret;
|
||||
return uwsgi_router_rpc_base(ur, args);
|
||||
}
|
||||
|
||||
static int uwsgi_router_rpc_blob(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_rpc_blob;
|
||||
return uwsgi_router_rpc_base(ur, args);
|
||||
}
|
||||
|
||||
static int uwsgi_router_rpc_raw(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_rpc_raw;
|
||||
return uwsgi_router_rpc_base(ur, args);
|
||||
}
|
||||
|
||||
|
||||
static void router_rpc_register() {
|
||||
uwsgi_register_router("call", uwsgi_router_rpc);
|
||||
uwsgi_register_router("rpc", uwsgi_router_rpc);
|
||||
uwsgi_register_router("rpcret", uwsgi_router_rpc_ret);
|
||||
uwsgi_register_router("rpcblob", uwsgi_router_rpc_blob);
|
||||
uwsgi_register_router("rpcnext", uwsgi_router_rpc_blob);
|
||||
uwsgi_register_router("rpcraw", uwsgi_router_rpc_raw);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct uwsgi_plugin rpc_plugin = {
|
||||
|
||||
.name = "rpc",
|
||||
.modifier1 = 173,
|
||||
|
||||
.request = uwsgi_rpc_request,
|
||||
#ifdef UWSGI_ROUTING
|
||||
.on_load = router_rpc_register,
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
#include <uwsgi.h>
|
||||
#include <sqlite3.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
static void uwsgi_sqlite3_config(char *, char *[]);
|
||||
static void uwsgi_opt_load_sqlite3(char *opt, char *filename, void *none) {
|
||||
config_magic_table_fill(filename, uwsgi.magic_table);
|
||||
uwsgi_sqlite3_config(filename, uwsgi.magic_table);
|
||||
}
|
||||
|
||||
static struct uwsgi_option uwsgi_sqlite3_options[] = {
|
||||
{"sqlite3", required_argument, 0, "load config from sqlite3 db", uwsgi_opt_load_sqlite3, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"sqlite", required_argument, 0, "load config from sqlite3 db", uwsgi_opt_load_sqlite3, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
static int uwsgi_sqlite3_config_callback(void *magic_table, int field_count, char **fields, char **col) {
|
||||
// make a copy of the string
|
||||
if (field_count >= 2) {
|
||||
size_t value_len = strlen(fields[1]) + 1;
|
||||
char *value = magic_sub(fields[1], value_len, &value_len, (char **) magic_table);
|
||||
add_exported_option(uwsgi_strncopy(fields[0], strlen(fields[0])), value, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uwsgi_sqlite3_config(char *file, char *magic_table[]) {
|
||||
|
||||
sqlite3 *db;
|
||||
char *err = NULL;
|
||||
char *query = "SELECT * FROM uwsgi";
|
||||
|
||||
char *colon = uwsgi_get_last_char(file, ':');
|
||||
|
||||
if (colon) {
|
||||
colon[0] = 0;
|
||||
if (colon[1] != 0) {
|
||||
query = colon + 1;
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("[uWSGI] getting sqlite3 configuration from %s\n", file);
|
||||
|
||||
#ifdef sqlite3_open_v2
|
||||
if (sqlite3_open_v2(file, &db, SQLITE_OPEN_READONLY, NULL)) {
|
||||
#else
|
||||
if (sqlite3_open(file, &db)) {
|
||||
#endif
|
||||
uwsgi_log("unable to open sqlite3 db: %s\n", sqlite3_errmsg(db));
|
||||
sqlite3_close(db);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (sqlite3_exec(db, query, uwsgi_sqlite3_config_callback, (void *) magic_table, &err)) {
|
||||
uwsgi_log("sqlite3 error: %s\n", err);
|
||||
sqlite3_close(db);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sqlite3_close(db);
|
||||
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_plugin sqlite3_plugin = {
|
||||
.name = "sqlite3",
|
||||
.options = uwsgi_sqlite3_options,
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
NAME='sqlite3'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lsqlite3']
|
||||
|
||||
GCC_LIST = ['plugin']
|
||||
@@ -0,0 +1,526 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#define UWSGI_SSI_MAX_ARGS 8
|
||||
|
||||
/*
|
||||
|
||||
uWSGI server side includes implementation
|
||||
|
||||
*/
|
||||
|
||||
|
||||
struct uwsgi_ssi_arg {
|
||||
char *key;
|
||||
size_t key_len;
|
||||
char *value;
|
||||
size_t val_len;
|
||||
};
|
||||
|
||||
struct uwsgi_ssi_cmd {
|
||||
char *name;
|
||||
size_t name_len;
|
||||
struct uwsgi_buffer *(*func)(struct wsgi_request *, struct uwsgi_ssi_arg *, int);
|
||||
struct uwsgi_ssi_cmd *next;
|
||||
};
|
||||
|
||||
struct uwsgi_ssi_cmd *uwsgi_ssi_commands = NULL;
|
||||
|
||||
static struct uwsgi_ssi_cmd* uwsgi_ssi_get_cmd(char *name, size_t name_len) {
|
||||
struct uwsgi_ssi_cmd *usc = uwsgi_ssi_commands;
|
||||
while(usc) {
|
||||
if (!uwsgi_strncmp(usc->name, usc->name_len, name, name_len)) {
|
||||
return usc;
|
||||
}
|
||||
usc = usc->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct uwsgi_ssi_cmd *uwsgi_register_ssi_command(char *name, struct uwsgi_buffer *(*func)(struct wsgi_request *, struct uwsgi_ssi_arg *, int)) {
|
||||
struct uwsgi_ssi_cmd *old_usc = NULL,*usc = uwsgi_ssi_commands;
|
||||
while(usc) {
|
||||
if (!strcmp(usc->name, name)) {
|
||||
return usc;
|
||||
}
|
||||
old_usc = usc;
|
||||
usc = usc->next;
|
||||
}
|
||||
|
||||
usc = uwsgi_calloc(sizeof(struct uwsgi_ssi_cmd));
|
||||
usc->name = name;
|
||||
usc->name_len = strlen(name);
|
||||
usc->func = func;
|
||||
|
||||
if (old_usc) {
|
||||
old_usc->next = usc;
|
||||
}
|
||||
else {
|
||||
uwsgi_ssi_commands = usc;
|
||||
}
|
||||
|
||||
return usc;
|
||||
}
|
||||
|
||||
static int uwsgi_ssi_parse_args(struct wsgi_request *wsgi_req, char *buf, size_t len, struct uwsgi_ssi_arg *argv, int *argc) {
|
||||
// status [0]null/= [1]" [2]" [3]\s
|
||||
size_t i;
|
||||
uint8_t status = 0;
|
||||
char *key = buf;
|
||||
size_t key_len = 0;
|
||||
char *value = NULL;
|
||||
size_t val_len = 0;
|
||||
for(i=0;i<len;i++) {
|
||||
switch(status) {
|
||||
case 0:
|
||||
if (buf[i] == '=') {
|
||||
status = 1;
|
||||
}
|
||||
else {
|
||||
key_len++;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (buf[i] == '"') {
|
||||
status = 2;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (buf[i] == '"') {
|
||||
status = 3;
|
||||
argv[*argc].key = key; argv[*argc].key_len = key_len;
|
||||
argv[*argc].value = value; argv[*argc].val_len = val_len;
|
||||
*argc = *argc+1;
|
||||
if (*argc >= UWSGI_SSI_MAX_ARGS) {
|
||||
return -1;
|
||||
}
|
||||
key = NULL;
|
||||
key_len = 0;
|
||||
value = NULL;
|
||||
val_len = 0;
|
||||
}
|
||||
else {
|
||||
if (!value) {
|
||||
value = buf + i;
|
||||
}
|
||||
val_len++;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (!isspace((int)buf[i])) {
|
||||
key = buf + i;
|
||||
key_len = 1;
|
||||
status = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct uwsgi_buffer *uwsgi_ssi_parse_command(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
|
||||
// storage for arguments
|
||||
struct uwsgi_ssi_arg argv[UWSGI_SSI_MAX_ARGS];
|
||||
int argc = 0;
|
||||
|
||||
// first remove white spaces from the begin and the end
|
||||
char *cmd = buf;
|
||||
size_t cmd_len = len;
|
||||
size_t i;
|
||||
for(i=0;i<len;i++) {
|
||||
if (isspace((int)buf[i])) {
|
||||
cmd++;
|
||||
cmd_len--;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// then rstrip (skipping the first char...)
|
||||
for(i=(len-1);i>0;i--) {
|
||||
if (isspace((int)buf[i])) {
|
||||
cmd_len--;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// now get the command
|
||||
char *ssi_cmd = cmd;
|
||||
size_t ssi_cmd_len = 0;
|
||||
int found = 0;
|
||||
|
||||
for(i=0;i<cmd_len;i++) {
|
||||
if (isspace(cmd[i])) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
ssi_cmd_len++;
|
||||
}
|
||||
|
||||
struct uwsgi_ssi_cmd *usc = uwsgi_ssi_get_cmd(ssi_cmd, ssi_cmd_len);
|
||||
if (!usc) return NULL ;
|
||||
|
||||
if (!found) goto run;
|
||||
|
||||
// now split the args
|
||||
char *cmd_args = cmd + ssi_cmd_len + 1;
|
||||
size_t cmd_args_len = cmd_len - (ssi_cmd_len + 1);
|
||||
|
||||
for(i=(ssi_cmd_len + 1);i<cmd_len;i++) {
|
||||
if (isspace((int)cmd[i])) {
|
||||
cmd_args++;
|
||||
cmd_args_len--;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi_ssi_parse_args(wsgi_req, cmd_args, cmd_args_len, argv, &argc)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
run:
|
||||
return usc->func(wsgi_req, argv, argc);
|
||||
}
|
||||
|
||||
static struct uwsgi_buffer *uwsgi_ssi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
size_t i;
|
||||
uint8_t status = 0;
|
||||
char *cmd = NULL;
|
||||
size_t cmd_len = 0;
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(len);
|
||||
// parsing status 0[null] 1[<] 2[!] 3[-] 4[-] 5[#/-] 6[-] 7[>]
|
||||
// on status 6-7-8 the reset action come back to 5 instead of 0
|
||||
for(i=0;i<len;i++) {
|
||||
switch(status) {
|
||||
case 0:
|
||||
if (buf[i] == '<') {
|
||||
status = 1;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_buffer_append(ub, &buf[i], 1)) goto error;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
status = 0;
|
||||
if (buf[i] == '!') {
|
||||
status = 2;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_buffer_append(ub, "<", 1)) goto error;
|
||||
if (uwsgi_buffer_append(ub, &buf[i], 1)) goto error;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
status = 0;
|
||||
if (buf[i] == '-') {
|
||||
status = 3;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_buffer_append(ub, "<!", 2)) goto error;
|
||||
if (uwsgi_buffer_append(ub, &buf[i], 1)) goto error;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
status = 0;
|
||||
if (buf[i] == '-') {
|
||||
status = 4;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_buffer_append(ub, "<!-", 3)) goto error;
|
||||
if (uwsgi_buffer_append(ub, &buf[i], 1)) goto error;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
status = 0;
|
||||
if (buf[i] == '#') {
|
||||
status = 5;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_buffer_append(ub, "<!--", 4)) goto error;
|
||||
if (uwsgi_buffer_append(ub, &buf[i], 1)) goto error;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if (buf[i] == '-') {
|
||||
status = 6;
|
||||
break;
|
||||
}
|
||||
if (!cmd) {
|
||||
cmd = buf+i;
|
||||
}
|
||||
cmd_len++;
|
||||
break;
|
||||
case 6:
|
||||
status = 5;
|
||||
if (buf[i] == '-') {
|
||||
status = 7;
|
||||
}
|
||||
else {
|
||||
cmd_len+=2;
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
status = 5;
|
||||
if (buf[i] == '>') {
|
||||
status = 0;
|
||||
struct uwsgi_buffer *ub_cmd = uwsgi_ssi_parse_command(wsgi_req, cmd, cmd_len);
|
||||
if (ub_cmd) {
|
||||
if (uwsgi_buffer_append(ub, ub_cmd->buf, ub_cmd->pos)) {
|
||||
uwsgi_buffer_destroy(ub_cmd);
|
||||
goto error;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub_cmd);
|
||||
}
|
||||
cmd = NULL;
|
||||
cmd_len = 0;
|
||||
}
|
||||
else {
|
||||
cmd_len+=3;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
return ub;
|
||||
|
||||
error:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int uwsgi_ssi_request(struct wsgi_request *wsgi_req) {
|
||||
struct uwsgi_buffer *ub = NULL;
|
||||
|
||||
if (uwsgi_parse_vars(wsgi_req)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!wsgi_req->document_root_len || !wsgi_req->path_info_len) {
|
||||
uwsgi_log("[uwsgi-ssi] DOCUMENT_ROOT and PATH_INFO must be defined !!!\n");
|
||||
uwsgi_500(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
char *filename = uwsgi_concat3n(wsgi_req->document_root, wsgi_req->document_root_len, "/", 1, wsgi_req->path_info, wsgi_req->path_info_len);
|
||||
size_t filename_len = wsgi_req->document_root_len + 1 + wsgi_req->path_info_len;
|
||||
|
||||
// we expand the path for future security implementations
|
||||
char *real_filename = uwsgi_expand_path(filename, filename_len, NULL);
|
||||
free(filename);
|
||||
if (!real_filename) {
|
||||
uwsgi_404(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub_ssi = uwsgi_buffer_from_file(real_filename);
|
||||
free(real_filename);
|
||||
if (!ub_ssi) {
|
||||
uwsgi_500(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
ub = uwsgi_ssi_parse(wsgi_req, ub_ssi->buf, ub_ssi->pos);
|
||||
uwsgi_buffer_destroy(ub_ssi);
|
||||
if (!ub) {
|
||||
uwsgi_500(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
// prepare headers
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) {
|
||||
uwsgi_500(wsgi_req);
|
||||
goto end;
|
||||
}
|
||||
// content_length
|
||||
if (uwsgi_response_add_content_length(wsgi_req, ub->pos)) {
|
||||
uwsgi_500(wsgi_req);
|
||||
goto end;
|
||||
}
|
||||
// content_type
|
||||
if (uwsgi_response_add_content_type(wsgi_req, "text/html", 9)) {
|
||||
uwsgi_500(wsgi_req);
|
||||
goto end;
|
||||
}
|
||||
|
||||
uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
|
||||
end:
|
||||
if (ub) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
}
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
static char *uwsgi_ssi_get_arg(struct uwsgi_ssi_arg *argv, int argc, char *key, size_t key_len, size_t *val_len) {
|
||||
int i;
|
||||
for(i=0;i<argc;i++) {
|
||||
struct uwsgi_ssi_arg *arg = &argv[i];
|
||||
if (!uwsgi_strncmp(arg->key, arg->key_len, key, key_len)) {
|
||||
*val_len = arg->val_len;
|
||||
return arg->value;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// echo command
|
||||
static struct uwsgi_buffer *ssi_cmd_echo(struct wsgi_request *wsgi_req, struct uwsgi_ssi_arg *argv, int argc) {
|
||||
size_t var_len = 0;
|
||||
char *var = uwsgi_ssi_get_arg(argv, argc, "var", 3, &var_len);
|
||||
|
||||
if (!var || var_len == 0) return NULL;
|
||||
|
||||
uint16_t rlen = 0;
|
||||
char *value = uwsgi_get_var(wsgi_req, var, var_len, &rlen);
|
||||
if (!value) return NULL;
|
||||
if (rlen == 0) return NULL;
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(rlen);
|
||||
if (uwsgi_buffer_append(ub, value, rlen)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ub;
|
||||
};
|
||||
|
||||
// printenv command
|
||||
static struct uwsgi_buffer *ssi_cmd_printenv(struct wsgi_request *wsgi_req, struct uwsgi_ssi_arg *argv, int argc) {
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
|
||||
int i;
|
||||
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
|
||||
if (uwsgi_buffer_append(ub, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len)) goto error;
|
||||
if (uwsgi_buffer_append(ub, "=", 1)) goto error;
|
||||
if (uwsgi_buffer_append(ub, wsgi_req->hvec[i+1].iov_base, wsgi_req->hvec[i+1].iov_len)) goto error;
|
||||
if (uwsgi_buffer_append(ub, "\n", 1)) goto error;
|
||||
}
|
||||
|
||||
return ub;
|
||||
error:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return NULL;
|
||||
};
|
||||
|
||||
// include command
|
||||
static struct uwsgi_buffer *ssi_cmd_include(struct wsgi_request *wsgi_req, struct uwsgi_ssi_arg *argv, int argc) {
|
||||
size_t var_len = 0;
|
||||
char *var = uwsgi_ssi_get_arg(argv, argc, "file", 4, &var_len);
|
||||
if (!var || var_len == 0) return NULL;
|
||||
|
||||
char *filename = uwsgi_concat2n(var, var_len, "", 0);
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_from_file(filename);
|
||||
|
||||
free(filename);
|
||||
|
||||
return ub;
|
||||
}
|
||||
|
||||
// cache command (uWSGI specific)
|
||||
static struct uwsgi_buffer *ssi_cmd_cache(struct wsgi_request *wsgi_req, struct uwsgi_ssi_arg *argv, int argc) {
|
||||
size_t var_len = 0;
|
||||
char *var = uwsgi_ssi_get_arg(argv, argc, "key", 3, &var_len);
|
||||
if (!var || var_len == 0) return NULL;
|
||||
|
||||
size_t cache_len = 0;
|
||||
char *cache = uwsgi_ssi_get_arg(argv, argc, "name", 4, &cache_len);
|
||||
char *cache_name = NULL;
|
||||
|
||||
if (cache && cache_len) {
|
||||
cache_name = uwsgi_concat2n(cache, cache_len, "", 0);
|
||||
}
|
||||
|
||||
uint64_t rlen = 0;
|
||||
char *value = uwsgi_cache_magic_get(var, var_len, &rlen, cache_name);
|
||||
if (cache_name) free(cache_name);
|
||||
struct uwsgi_buffer *ub = NULL;
|
||||
if (value) {
|
||||
ub = uwsgi_buffer_new(rlen);
|
||||
if (uwsgi_buffer_append(ub, value, rlen)) {
|
||||
free(value);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return NULL;
|
||||
}
|
||||
free(value);
|
||||
}
|
||||
|
||||
return ub;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_routing_func_ssi(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
|
||||
|
||||
struct uwsgi_buffer *ub = NULL;
|
||||
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
struct uwsgi_buffer *ub_filename = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
||||
if (!ub_filename) goto end;
|
||||
|
||||
struct uwsgi_buffer *ub_ssi = uwsgi_buffer_from_file(ub_filename->buf);
|
||||
uwsgi_buffer_destroy(ub_filename);
|
||||
if (!ub_ssi) goto end;
|
||||
|
||||
ub = uwsgi_ssi_parse(wsgi_req, ub_ssi->buf, ub_ssi->pos);
|
||||
uwsgi_buffer_destroy(ub_ssi);
|
||||
if (!ub) goto end;
|
||||
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto end;
|
||||
if (uwsgi_response_add_content_length(wsgi_req, ub->pos)) goto end;
|
||||
if (uwsgi_response_add_content_type(wsgi_req, "text/html", 9)) goto end;
|
||||
|
||||
uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
|
||||
|
||||
end:
|
||||
if (ub) uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_router_ssi(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_ssi;
|
||||
ur->data = args;
|
||||
ur->data_len = strlen(args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_ssi_init() {
|
||||
uwsgi_register_ssi_command("echo", ssi_cmd_echo);
|
||||
uwsgi_register_ssi_command("printenv", ssi_cmd_printenv);
|
||||
uwsgi_register_ssi_command("include", ssi_cmd_include);
|
||||
uwsgi_register_ssi_command("cache", ssi_cmd_cache);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void uwsgi_ssi_register_router() {
|
||||
uwsgi_register_router("ssi", uwsgi_router_ssi);
|
||||
}
|
||||
|
||||
static void uwsgi_ssi_log(struct wsgi_request *wsgi_req) {
|
||||
log_request(wsgi_req);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin ssi_plugin = {
|
||||
.name = "ssi",
|
||||
.modifier1 = 19,
|
||||
.init = uwsgi_ssi_init,
|
||||
.request = uwsgi_ssi_request,
|
||||
.after_request = uwsgi_ssi_log,
|
||||
.on_load = uwsgi_ssi_register_router,
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='ssi'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
GCC_LIST = ['ssi']
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
void stats_pusher_mongodb(struct uwsgi_stats_pusher_instance *, time_t, char *, size_t);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
#include "client/dbclient.h"
|
||||
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
import os
|
||||
|
||||
NAME='stats_pusher_mongodb'
|
||||
|
||||
CFLAGS = ['-I/usr/include/mongo','-I/usr/local/include/mongo']
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lmongoclient', '-lboost_thread','-lboost_filesystem']
|
||||
|
||||
LIBS = []
|
||||
if not 'UWSGI_MONGODB_NOLIB' in os.environ:
|
||||
LIBS.append('-lmongoclient')
|
||||
LIBS.append('-lboost_thread')
|
||||
LIBS.append('-lboost_filesystem')
|
||||
|
||||
GCC_LIST = ['plugin', 'stats_pusher_mongodb.cc']
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user