mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
134
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
86d28b2654 | ||
|
|
09bc058e88 | ||
|
|
0bf55fc1f9 | ||
|
|
e05edd9f82 | ||
|
|
aa9c5331d4 | ||
|
|
665511e6fa | ||
|
|
41190a5336 | ||
|
|
f2b72814a6 | ||
|
|
67d49defb6 | ||
|
|
bf1f800cf4 | ||
|
|
55a95ac4b4 | ||
|
|
820caa5364 | ||
|
|
67ce14dfa8 | ||
|
|
dc16e8eb38 | ||
|
|
fc0de78d88 | ||
|
|
1ffecc7939 | ||
|
|
2b4759e5e1 | ||
|
|
779ab3702a | ||
|
|
25fe41dd50 | ||
|
|
1c03935b76 | ||
|
|
6b10370c0a | ||
|
|
e84c3808e9 | ||
|
|
b9ff3f87d0 | ||
|
|
7a6d40c258 | ||
|
|
5c211817b7 | ||
|
|
21b2769edd | ||
|
|
baff440f18 | ||
|
|
793dcd92d2 | ||
|
|
1d203021c7 | ||
|
|
d38cc66738 | ||
|
|
603351c736 | ||
|
|
ae5b69b19c | ||
|
|
0229a9727e | ||
|
|
da571c2515 | ||
|
|
d3160c3f60 | ||
|
|
175ef65d9f | ||
|
|
8a572a642e | ||
|
|
70a51c2909 | ||
|
|
8b32564b05 | ||
|
|
c0ada5e52a | ||
|
|
0ffcb9e05e | ||
|
|
5a279bb170 | ||
|
|
757049d9da | ||
|
|
8674787692 | ||
|
|
3654016c53 | ||
|
|
4dbc15a253 | ||
|
|
3d55ab8327 | ||
|
|
f4e336026b | ||
|
|
ed90e0cf4b | ||
|
|
bed7682a3b | ||
|
|
3874d3e610 | ||
|
|
d378d42c4c | ||
|
|
4faeb852c6 | ||
|
|
27177a4df9 | ||
|
|
4ee9b36579 | ||
|
|
c06a1626ed | ||
|
|
86787b796a | ||
|
|
3bae35805b | ||
|
|
f26e79fb09 | ||
|
|
b72fc0a178 | ||
|
|
f1853568f9 | ||
|
|
2785cd3065 | ||
|
|
a8a497e431 | ||
|
|
710588fcfd | ||
|
|
a66aad02d8 | ||
|
|
651dacad3a | ||
|
|
fdeb2e26cf | ||
|
|
d5d5b87627 | ||
|
|
67c1a547af | ||
|
|
ed9c99c417 | ||
|
|
2e29b6b234 | ||
|
|
e0882ed8df | ||
|
|
a6b42af85a | ||
|
|
595e99a0c6 | ||
|
|
54f666f214 | ||
|
|
f1fad65b43 | ||
|
|
40fb6ffa91 | ||
|
|
d83a685d01 | ||
|
|
e7b346d3d9 | ||
|
|
25ec7aadc0 | ||
|
|
f7ef3161e4 | ||
|
|
2cd731f36d | ||
|
|
15a0b7fbc9 | ||
|
|
f33d16edb7 | ||
|
|
6fdb5cac37 | ||
|
|
20f7e4f0bc | ||
|
|
0c1e9080af | ||
|
|
1ceb82af59 | ||
|
|
ace76d686d | ||
|
|
a7bb9bd2bb | ||
|
|
aa39cc0eca | ||
|
|
74c88f21a9 | ||
|
|
c03e94f97e | ||
|
|
be4da2e8d9 | ||
|
|
d781a02eed | ||
|
|
fd42997e8f | ||
|
|
6be13c2e04 | ||
|
|
63f63adda6 | ||
|
|
c0904e42fc | ||
|
|
8b8f1d60ed | ||
|
|
5a6850e64b | ||
|
|
cc6e9924b8 | ||
|
|
816998155e | ||
|
|
b2ffd406e3 | ||
|
|
713ffe38b4 | ||
|
|
1810af7b2d | ||
|
|
d0fb89c783 | ||
|
|
b0c23faeeb | ||
|
|
edc4aa42c8 | ||
|
|
dda8c2ffaa | ||
|
|
7059fd8d88 | ||
|
|
dad81ce7bd | ||
|
|
277afccf64 | ||
|
|
3854d14867 | ||
|
|
e3a67a9bcd | ||
|
|
a51b19669c | ||
|
|
2707860bc5 | ||
|
|
7c69aade57 | ||
|
|
38c5d3d4b5 | ||
|
|
065b992bf9 | ||
|
|
3b93696775 | ||
|
|
62534b2490 | ||
|
|
5018c152e9 | ||
|
|
57fc6bcef0 | ||
|
|
36f26dba85 | ||
|
|
6062bf8a72 | ||
|
|
0152fb077b | ||
|
|
440d42303d | ||
|
|
72e28580a6 | ||
|
|
acf7984eb3 | ||
|
|
bda58ad5cd | ||
|
|
89258474ad | ||
|
|
dc01fc4b42 | ||
|
|
0dd5add615 |
@@ -1,3 +1,40 @@
|
||||
*** march 2010 ***
|
||||
|
||||
* Third Maintenance release [20100310] *
|
||||
|
||||
- fix sendfile on 64bit
|
||||
- include setup.py
|
||||
|
||||
*** february 2010 ***
|
||||
* Maintenance release *
|
||||
|
||||
- better support for NetBSD
|
||||
- threading fix for FreeBSD
|
||||
- sendfile portability fixes
|
||||
- new makefiles
|
||||
- example app for testing static file serving
|
||||
- fixes for ROCK_SOLID mode
|
||||
|
||||
*** january 2010 ***
|
||||
|
||||
- Integrated Spooler
|
||||
- better error management
|
||||
- long options
|
||||
- clustering functions
|
||||
- experimental lighttpd module
|
||||
- official support for OpenBSD and OpenSolaris
|
||||
- FastFuncs
|
||||
- new functions for embedded module
|
||||
- reliable harakiri
|
||||
- better Makefiles
|
||||
- python threads support in master process
|
||||
- proper timeout handling in apache2 module
|
||||
- endianess fixes all over the place
|
||||
- paste support
|
||||
- Django app for managing and monitoring the uWSGI server
|
||||
- options for changin uid/gid and chrooting when run by root
|
||||
- lot of bugfixes and optimizations
|
||||
|
||||
*** 20091129 Version 0.9.3 ***
|
||||
|
||||
- Nginx 0.7.x module
|
||||
|
||||
@@ -1,13 +1,2 @@
|
||||
CC=gcc
|
||||
|
||||
PYTHON_CFLAGS=`python2.5-config --cflags`
|
||||
PYTHON_LIBS=`python2.5-config --libs`
|
||||
XML_CFLAGS=`xml2-config --cflags`
|
||||
XML_LIBS=`xml2-config --libs`
|
||||
|
||||
CFLAGS=$(PYTHON_CFLAGS) $(XML_CFLAGS)
|
||||
LD_FLAGS=$(PYTHON_LIBS) $(XML_LIBS)
|
||||
|
||||
PROGRAM=uwsgi
|
||||
|
||||
include base.mk
|
||||
all:
|
||||
python uwsgiconfig.py --build
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
CC=/usr/lib/llvm/llvm/gcc-4.2/bin/llvm-gcc
|
||||
|
||||
PYTHON_CFLAGS=`python2.5-config --cflags`
|
||||
PYTHON_LIBS=`python2.5-config --libs`
|
||||
XML_CFLAGS=`xml2-config --cflags`
|
||||
XML_LIBS=`xml2-config --libs`
|
||||
|
||||
CFLAGS=$(PYTHON_CFLAGS) $(XML_CFLAGS)
|
||||
LD_FLAGS=$(PYTHON_LIBS) $(XML_LIBS)
|
||||
|
||||
PROGRAM=uwsgi
|
||||
|
||||
all: uwsgi
|
||||
|
||||
uwsgi: utils.o socket.o pymodule.o main.o
|
||||
$(CC) $(LD_FLAGS) utils.o socket.o pymodule.o main.o -o $(PROGRAM)
|
||||
|
||||
utils.o: utils.c
|
||||
$(CC) -c $(CFLAGS) utils.c
|
||||
|
||||
socket.o: socket.c
|
||||
$(CC) -c $(CFLAGS) socket.c
|
||||
|
||||
pymodule.o: uwsgi_pymodule.c
|
||||
$(CC) -c $(CFLAGS) -o pymodule.o uwsgi_pymodule.c
|
||||
|
||||
main.o: uwsgi.c
|
||||
$(CC) -c $(CFLAGS) -o main.o uwsgi.c
|
||||
|
||||
clean:
|
||||
rm -f utils.o socket.o pymodule.o main.o
|
||||
@@ -1,31 +0,0 @@
|
||||
CC=/usr/lib/llvm/llvm/gcc-4.2/bin/llvm-gcc
|
||||
|
||||
PYTHON_CFLAGS=`python2.6-config --cflags`
|
||||
PYTHON_LIBS=`python2.6-config --libs`
|
||||
XML_CFLAGS=`xml2-config --cflags`
|
||||
XML_LIBS=`xml2-config --libs`
|
||||
|
||||
CFLAGS=$(PYTHON_CFLAGS) $(XML_CFLAGS)
|
||||
LD_FLAGS=$(PYTHON_LIBS) $(XML_LIBS)
|
||||
|
||||
PROGRAM=uwsgi26
|
||||
|
||||
all: uwsgi
|
||||
|
||||
uwsgi: utils.o socket.o pymodule.o main.o
|
||||
$(CC) $(LD_FLAGS) utils.o socket.o pymodule.o main.o -o $(PROGRAM)
|
||||
|
||||
utils.o: utils.c
|
||||
$(CC) -c $(CFLAGS) utils.c
|
||||
|
||||
socket.o: socket.c
|
||||
$(CC) -c $(CFLAGS) socket.c
|
||||
|
||||
pymodule.o: uwsgi_pymodule.c
|
||||
$(CC) -c $(CFLAGS) -o pymodule.o uwsgi_pymodule.c
|
||||
|
||||
main.o: uwsgi.c
|
||||
$(CC) -c $(CFLAGS) -o main.o uwsgi.c
|
||||
|
||||
clean:
|
||||
rm -f utils.o socket.o pymodule.o main.o
|
||||
@@ -0,0 +1,2 @@
|
||||
all:
|
||||
python2.4 uwsgiconfig.py --build
|
||||
@@ -0,0 +1,2 @@
|
||||
all:
|
||||
python2.5 uwsgiconfig.py --build
|
||||
+2
-13
@@ -1,13 +1,2 @@
|
||||
CC=gcc
|
||||
|
||||
PYTHON_CFLAGS=`python2.6-config --cflags`
|
||||
PYTHON_LIBS=`python2.6-config --libs`
|
||||
XML_CFLAGS=`xml2-config --cflags`
|
||||
XML_LIBS=`xml2-config --libs`
|
||||
|
||||
CFLAGS=$(PYTHON_CFLAGS) $(XML_CFLAGS)
|
||||
LD_FLAGS=$(PYTHON_LIBS) $(XML_LIBS)
|
||||
|
||||
PROGRAM=uwsgi26
|
||||
|
||||
include base.mk
|
||||
all:
|
||||
python2.6 uwsgiconfig.py --build
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
all:
|
||||
python3.0 uwsgiconfig.py --build
|
||||
@@ -0,0 +1,2 @@
|
||||
all:
|
||||
python3.1 uwsgiconfig.py --build
|
||||
@@ -1,29 +0,0 @@
|
||||
CC=gcc
|
||||
|
||||
PYTHON_CFLAGS=`python2.6-config --cflags`
|
||||
PYTHON_LIBS=`python2.6-config --libs`
|
||||
|
||||
CFLAGS=$(PYTHON_CFLAGS) -DROCK_SOLID
|
||||
LD_FLAGS=$(PYTHON_LIBS) -DROCK_SOLID
|
||||
|
||||
PROGRAM=uwsgi26_rs
|
||||
|
||||
all: uwsgi
|
||||
|
||||
uwsgi: utils.o socket.o pymodule.o main.o
|
||||
$(CC) $(LD_FLAGS) utils.o socket.o pymodule.o main.o -o $(PROGRAM)
|
||||
|
||||
utils.o: utils.c
|
||||
$(CC) -c $(CFLAGS) utils.c
|
||||
|
||||
socket.o: socket.c
|
||||
$(CC) -c $(CFLAGS) socket.c
|
||||
|
||||
pymodule.o: uwsgi_pymodule.c
|
||||
$(CC) -c $(CFLAGS) -o pymodule.o uwsgi_pymodule.c
|
||||
|
||||
main.o: uwsgi.c
|
||||
$(CC) -c $(CFLAGS) -o main.o uwsgi.c
|
||||
|
||||
clean:
|
||||
rm -f utils.o socket.o pymodule.o main.o
|
||||
+1
-16
@@ -8,19 +8,4 @@ LD_FLAGS=$(PYTHON_LIBS) -DUNBIT -D_GNU_SOURCE
|
||||
|
||||
PROGRAM=/usr/share/unbit/uwsgi24
|
||||
|
||||
all: clean uwsgi
|
||||
|
||||
uwsgi: utils.o pymodule.o main.o
|
||||
$(CC) $(LD_FLAGS) main.o utils.o pymodule.o -o $(PROGRAM)
|
||||
|
||||
utils.o: utils.c
|
||||
$(CC) -c $(CFLAGS) utils.c
|
||||
|
||||
pymodule.o: uwsgi_pymodule.c
|
||||
$(CC) -c $(CFLAGS) -o pymodule.o uwsgi_pymodule.c
|
||||
|
||||
main.o: uwsgi.c
|
||||
$(CC) -c $(CFLAGS) -o main.o uwsgi.c
|
||||
|
||||
clean:
|
||||
rm -f utils.o pymodule.o main.o
|
||||
include base.mk
|
||||
|
||||
+1
-16
@@ -8,19 +8,4 @@ LD_FLAGS=$(PYTHON_LIBS) -DUNBIT -D_GNU_SOURCE
|
||||
|
||||
PROGRAM=/usr/share/unbit/uwsgi
|
||||
|
||||
all: clean uwsgi
|
||||
|
||||
uwsgi: utils.o pymodule.o main.o
|
||||
$(CC) $(LD_FLAGS) main.o utils.o pymodule.o -o $(PROGRAM)
|
||||
|
||||
utils.o: utils.c
|
||||
$(CC) -c $(CFLAGS) utils.c
|
||||
|
||||
pymodule.o: uwsgi_pymodule.c
|
||||
$(CC) -c $(CFLAGS) -o pymodule.o uwsgi_pymodule.c
|
||||
|
||||
main.o: uwsgi.c
|
||||
$(CC) -c $(CFLAGS) -o main.o uwsgi.c
|
||||
|
||||
clean:
|
||||
rm -f utils.o pymodule.o main.o
|
||||
include base.mk
|
||||
|
||||
+6
-24
@@ -1,33 +1,15 @@
|
||||
CC=gcc
|
||||
|
||||
PYBASE=/opt/packages/python/26
|
||||
BASE=/opt/packages/python/26
|
||||
|
||||
PATH := ${PATH}:$(PYBASE)/bin
|
||||
export LD_LIBRARY_PATH=$(BASE)/lib
|
||||
|
||||
LD_LIBRARY_PATH= $(PYBASE)/lib
|
||||
export LD_LIBRARY_PATH
|
||||
|
||||
PYTHON_CFLAGS=`python2.6-config --cflags`
|
||||
PYTHON_LIBS=`python2.6-config --libs`
|
||||
PYTHON_CFLAGS=`$(BASE)/bin/python2.6-config --cflags`
|
||||
PYTHON_LIBS=`$(BASE)/bin/python2.6-config --libs`
|
||||
|
||||
CFLAGS=$(PYTHON_CFLAGS) -DUNBIT -D_GNU_SOURCE
|
||||
LD_FLAGS=$(PYTHON_LIBS) -DUNBIT -D_GNU_SOURCE -L $(LD_LIBRARY_PATH)
|
||||
LD_FLAGS=$(PYTHON_LIBS) -L$(BASE)/lib -DUNBIT -D_GNU_SOURCE
|
||||
|
||||
PROGRAM=/usr/share/unbit/uwsgi26
|
||||
|
||||
all: clean uwsgi
|
||||
|
||||
uwsgi: utils.o pymodule.o main.o
|
||||
$(CC) $(LD_FLAGS) main.o utils.o pymodule.o -o $(PROGRAM)
|
||||
|
||||
utils.o: utils.c
|
||||
$(CC) -c $(CFLAGS) utils.c
|
||||
|
||||
pymodule.o: uwsgi_pymodule.c
|
||||
$(CC) -c $(CFLAGS) -o pymodule.o uwsgi_pymodule.c
|
||||
|
||||
main.o: uwsgi.c
|
||||
$(CC) -c $(CFLAGS) -o main.o uwsgi.c
|
||||
|
||||
clean:
|
||||
rm -f utils.o pymodule.o main.o
|
||||
include base.mk
|
||||
|
||||
+3
-22
@@ -1,30 +1,11 @@
|
||||
CC=gcc
|
||||
|
||||
PYBASE=/opt/packages/python/30
|
||||
|
||||
PATH := ${PATH}:$(PYBASE)/bin
|
||||
|
||||
LD_LIBRARY_PATH= $(PYBASE)/lib
|
||||
export LD_LIBRARY_PATH
|
||||
|
||||
PYTHON_CFLAGS=`python3.0-config --cflags`
|
||||
PYTHON_LIBS=`python3.0-config --libs`
|
||||
|
||||
CFLAGS=$(PYTHON_CFLAGS) -DUNBIT -D_GNU_SOURCE -DPYTHREE
|
||||
LD_FLAGS=$(PYTHON_LIBS) -DUNBIT -D_GNU_SOURCE -DPYTHREE -L $(LD_LIBRARY_PATH)
|
||||
CFLAGS=$(PYTHON_CFLAGS) -DUNBIT -D_GNU_SOURCE
|
||||
LD_FLAGS=$(PYTHON_LIBS) -DUNBIT -D_GNU_SOURCE
|
||||
|
||||
PROGRAM=/usr/share/unbit/uwsgi30
|
||||
|
||||
all: clean uwsgi
|
||||
|
||||
uwsgi: utils.o main.o
|
||||
$(CC) $(LD_FLAGS) main.o utils.o -o $(PROGRAM)
|
||||
|
||||
utils.o: utils.c
|
||||
$(CC) -c $(CFLAGS) utils.c
|
||||
|
||||
main.o: uwsgi.c
|
||||
$(CC) -c $(CFLAGS) -o main.o uwsgi.c
|
||||
|
||||
clean:
|
||||
rm -f utils.o main.o
|
||||
include base.mk
|
||||
|
||||
+3
-22
@@ -1,30 +1,11 @@
|
||||
CC=gcc
|
||||
|
||||
PYBASE=/opt/packages/python/31
|
||||
|
||||
PATH := ${PATH}:$(PYBASE)/bin
|
||||
|
||||
LD_LIBRARY_PATH= $(PYBASE)/lib
|
||||
export LD_LIBRARY_PATH
|
||||
|
||||
PYTHON_CFLAGS=`python3.1-config --cflags`
|
||||
PYTHON_LIBS=`python3.1-config --libs`
|
||||
|
||||
CFLAGS=$(PYTHON_CFLAGS) -DUNBIT -D_GNU_SOURCE -DPYTHREE
|
||||
LD_FLAGS=$(PYTHON_LIBS) -DUNBIT -D_GNU_SOURCE -DPYTHREE -L $(LD_LIBRARY_PATH)
|
||||
CFLAGS=$(PYTHON_CFLAGS) -DUNBIT -D_GNU_SOURCE
|
||||
LD_FLAGS=$(PYTHON_LIBS) -DUNBIT -D_GNU_SOURCE
|
||||
|
||||
PROGRAM=/usr/share/unbit/uwsgi31
|
||||
|
||||
all: clean uwsgi
|
||||
|
||||
uwsgi: utils.o main.o
|
||||
$(CC) $(LD_FLAGS) main.o utils.o -o $(PROGRAM)
|
||||
|
||||
utils.o: utils.c
|
||||
$(CC) -c $(CFLAGS) utils.c
|
||||
|
||||
main.o: uwsgi.c
|
||||
$(CC) -c $(CFLAGS) -o main.o uwsgi.c
|
||||
|
||||
clean:
|
||||
rm -f utils.o main.o
|
||||
include base.mk
|
||||
|
||||
+117
-22
@@ -24,8 +24,8 @@ To compile:
|
||||
apxs2 -i -c mod_uwsgi.c
|
||||
(OSX)
|
||||
sudo apxs -i -a -c mod_uwsgi.c
|
||||
(OSX 64bit)
|
||||
sudo apxs -i -a -c -Wc,'-arch x86_64' -Wl,'-arch x86_64' mod_uwsgi.c
|
||||
(OSX Universal binary)
|
||||
sudo apxs -i -a -c -Wc,"-arch ppc -arch i386 -arch x86_64" -Wl,"-arch ppc -arch i386 -arch x86_64" mod_uwsgi.c
|
||||
|
||||
|
||||
Configure:
|
||||
@@ -71,25 +71,73 @@ typedef struct {
|
||||
uint8_t modifier1;
|
||||
uint8_t modifier2;
|
||||
char script_name[256];
|
||||
char scheme[9];
|
||||
int cgi_mode ;
|
||||
} uwsgi_cfg;
|
||||
|
||||
module AP_MODULE_DECLARE_DATA uwsgi_module;
|
||||
|
||||
#if APR_IS_BIGENDIAN
|
||||
static uint16_t uwsgi_swap16(uint16_t x) {
|
||||
return (uint16_t) ((x & 0xff) << 8 | (x & 0xff00) >> 8);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int uwsgi_add_var(struct iovec *vec, int i, char *key, char *value, uint16_t *pkt_size) {
|
||||
|
||||
vec[i].iov_base = &vec[i+1].iov_len ;
|
||||
vec[i].iov_len = 2 ;
|
||||
|
||||
#if APR_IS_BIGENDIAN
|
||||
char *ptr;
|
||||
vec[i+2].iov_base = key ;
|
||||
vec[i+2].iov_len = strlen(key) ;
|
||||
#else
|
||||
vec[i+1].iov_base = key ;
|
||||
vec[i+1].iov_len = strlen(key) ;
|
||||
vec[i+2].iov_base = &vec[i+3].iov_len ;
|
||||
vec[i+2].iov_len = 2 ;
|
||||
vec[i+3].iov_base = value ;
|
||||
vec[i+3].iov_len = strlen(value) ;
|
||||
#endif
|
||||
|
||||
#if APR_IS_BIGENDIAN
|
||||
ptr = (char *) &vec[i+2].iov_len;
|
||||
vec[i].iov_base = ptr+sizeof(long)-1 ;
|
||||
vec[i].iov_len = 1 ;
|
||||
vec[i+1].iov_base = ptr+sizeof(long)-2 ;
|
||||
vec[i+1].iov_len = 1 ;
|
||||
#else
|
||||
vec[i].iov_base = &vec[i+1].iov_len ;
|
||||
vec[i].iov_len = 2 ;
|
||||
#endif
|
||||
|
||||
|
||||
#if APR_IS_BIGENDIAN
|
||||
vec[i+5].iov_base = value ;
|
||||
vec[i+5].iov_len = strlen(value) ;
|
||||
#else
|
||||
vec[i+3].iov_base = value ;
|
||||
vec[i+3].iov_len = strlen(value) ;
|
||||
#endif
|
||||
|
||||
#if APR_IS_BIGENDIAN
|
||||
ptr = (char *) &vec[i+5].iov_len;
|
||||
vec[i+3].iov_base = ptr+sizeof(long)-1 ;
|
||||
vec[i+3].iov_len = 1 ;
|
||||
vec[i+4].iov_base = ptr+sizeof(long)-2 ;
|
||||
vec[i+4].iov_len = 1 ;
|
||||
#else
|
||||
vec[i+2].iov_base = &vec[i+3].iov_len ;
|
||||
vec[i+2].iov_len = 2 ;
|
||||
#endif
|
||||
|
||||
|
||||
#if APR_IS_BIGENDIAN
|
||||
*pkt_size+= vec[i+2].iov_len + vec[i+5].iov_len + 4 ;
|
||||
#else
|
||||
*pkt_size+= vec[i+1].iov_len + vec[i+3].iov_len + 4 ;
|
||||
#endif
|
||||
|
||||
#if APR_IS_BIGENDIAN
|
||||
return i+6;
|
||||
#else
|
||||
return i+4;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void *uwsgi_server_config(apr_pool_t *p, server_rec *s) {
|
||||
@@ -195,12 +243,17 @@ static int uwsgi_handler(request_rec *r) {
|
||||
|
||||
uwsgi_cfg *c = ap_get_module_config(r->per_dir_config, &uwsgi_module);
|
||||
|
||||
#if APR_IS_BIGENDIAN
|
||||
struct iovec uwsgi_vars[(MAX_VARS*6)+1] ;
|
||||
#else
|
||||
struct iovec uwsgi_vars[(MAX_VARS*4)+1] ;
|
||||
#endif
|
||||
int vecptr = 1 ;
|
||||
char pkt_header[4];
|
||||
uint16_t pkt_size = 0;
|
||||
char buf[4096] ;
|
||||
int cnt,i ;
|
||||
int i ;
|
||||
ssize_t cnt ;
|
||||
const apr_array_header_t *headers;
|
||||
apr_table_entry_t *h;
|
||||
char *penv, *cp;
|
||||
@@ -272,9 +325,16 @@ static int uwsgi_handler(request_rec *r) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SERVER_PROTOCOL", r->protocol, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REQUEST_URI", r->uri, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REMOTE_ADDR", r->connection->remote_ip, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REMOTE_USER", r->user ? r->args : "", &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REMOTE_USER", r->user ? r->user : "", &pkt_size) ;
|
||||
if (r->user) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "AUTH_TYPE", (char *) ap_auth_type(r), &pkt_size) ;
|
||||
}
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "DOCUMENT_ROOT", (char *) ap_document_root(r), &pkt_size) ;
|
||||
|
||||
if (c->scheme[0] != 0) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "UWSGI_SCHEME", c->scheme, &pkt_size) ;
|
||||
}
|
||||
|
||||
if (c->script_name[0] == '/') {
|
||||
if (c->script_name[1] == 0) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", "", &pkt_size) ;
|
||||
@@ -302,6 +362,7 @@ static int uwsgi_handler(request_rec *r) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
headers = apr_table_elts(r->headers_in);
|
||||
h = (apr_table_entry_t *) headers->elts;
|
||||
|
||||
@@ -339,7 +400,13 @@ static int uwsgi_handler(request_rec *r) {
|
||||
uwsgi_vars[0].iov_len = 4;
|
||||
|
||||
pkt_header[0] = c->modifier1 ;
|
||||
#if APR_IS_BIGENDIAN
|
||||
pkt_size = uwsgi_swap16(pkt_size);
|
||||
memcpy(pkt_header+1, &pkt_size, 2);
|
||||
pkt_size = uwsgi_swap16(pkt_size);
|
||||
#else
|
||||
memcpy(pkt_header+1, &pkt_size, 2);
|
||||
#endif
|
||||
pkt_header[3] = c->modifier2 ;
|
||||
|
||||
cnt = writev( uwsgi_poll.fd, uwsgi_vars, vecptr );
|
||||
@@ -354,6 +421,7 @@ static int uwsgi_handler(request_rec *r) {
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (ap_should_client_block(r)) {
|
||||
while ((cnt = ap_get_client_block(r, buf, 4096)) > 0) {
|
||||
@@ -366,25 +434,35 @@ static int uwsgi_handler(request_rec *r) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!c->cgi_mode) {
|
||||
r->assbackwards = 1 ;
|
||||
uwsgi_http_status[13] = 0 ;
|
||||
uwsgi_http_status[12] = 0 ;
|
||||
}
|
||||
|
||||
|
||||
bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
|
||||
|
||||
uwsgi_poll.events = POLLIN ;
|
||||
|
||||
|
||||
|
||||
for(;;) {
|
||||
/* put -1 to disable timeout on zero */
|
||||
cnt = poll(&uwsgi_poll, 1, (c->socket_timeout*1000)-1) ;
|
||||
if (cnt == 0) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() timeout");
|
||||
break;
|
||||
apr_brigade_destroy(bb);
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
else if (cnt > 0) {
|
||||
cnt = recv(uwsgi_poll.fd, buf, 4096, 0) ;
|
||||
if (cnt > 0) {
|
||||
if (cnt < 0) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() %s", strerror(errno));
|
||||
apr_brigade_destroy(bb);
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
else if (cnt > 0) {
|
||||
if (!c->cgi_mode && uwsgi_http_status_read < 12) {
|
||||
if (uwsgi_http_status_read + cnt >= 12) {
|
||||
memcpy(uwsgi_http_status+uwsgi_http_status_read, buf, 12-uwsgi_http_status_read);
|
||||
@@ -397,31 +475,32 @@ static int uwsgi_handler(request_rec *r) {
|
||||
}
|
||||
}
|
||||
apr_brigade_write(bb, NULL, NULL, buf, cnt);
|
||||
}
|
||||
else if (cnt == 0) {
|
||||
break;
|
||||
|
||||
}
|
||||
else {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() %s", strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: poll() %s", strerror(errno));
|
||||
break;
|
||||
apr_brigade_destroy(bb);
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
close(uwsgi_poll.fd);
|
||||
|
||||
|
||||
b = apr_bucket_eos_create(r->connection->bucket_alloc);
|
||||
APR_BRIGADE_INSERT_TAIL(bb, b);
|
||||
|
||||
if (!c->cgi_mode) {
|
||||
if (uwsgi_http_status_read == 0) {
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
b = apr_bucket_eos_create(r->connection->bucket_alloc);
|
||||
APR_BRIGADE_INSERT_TAIL(bb, b);
|
||||
|
||||
if (hret = ap_scan_script_header_err_brigade(r, bb, NULL)) {
|
||||
apr_brigade_destroy(bb);
|
||||
@@ -429,10 +508,11 @@ static int uwsgi_handler(request_rec *r) {
|
||||
}
|
||||
}
|
||||
|
||||
return ap_pass_brigade(r->output_filters, bb);
|
||||
|
||||
return ap_pass_brigade(r->output_filters, bb) ;
|
||||
}
|
||||
|
||||
static const char * cmd_uwsgi_force_script_name(cmd_parms *cmd, void *cfg, const char *location) {
|
||||
static const char * cmd_uwsgi_force_wsgi_scheme(cmd_parms *cmd, void *cfg, const char *location) {
|
||||
uwsgi_cfg *c = cfg;
|
||||
|
||||
if (strlen(location) <= 255 && location[0] == '/') {
|
||||
@@ -446,6 +526,20 @@ static const char * cmd_uwsgi_force_script_name(cmd_parms *cmd, void *cfg, const
|
||||
|
||||
}
|
||||
|
||||
static const char * cmd_uwsgi_force_script_name(cmd_parms *cmd, void *cfg, const char *scheme) {
|
||||
uwsgi_cfg *c = cfg;
|
||||
|
||||
if (strlen(scheme) < 9 & strlen(scheme) > 0) {
|
||||
strcpy(c->scheme, scheme);
|
||||
}
|
||||
else {
|
||||
return "ignored uWSGIforceWSGIscheme. Invalid size (max 8 chars)" ;
|
||||
}
|
||||
|
||||
return NULL ;
|
||||
|
||||
}
|
||||
|
||||
static const char * cmd_uwsgi_modifier1(cmd_parms *cmd, void *cfg, const char *value) {
|
||||
|
||||
uwsgi_cfg *c ;
|
||||
@@ -588,6 +682,7 @@ static const command_rec uwsgi_cmds[] = {
|
||||
AP_INIT_TAKE1("uWSGImodifier2", cmd_uwsgi_modifier2, NULL, RSRC_CONF|ACCESS_CONF, "Set uWSGI modifier2"),
|
||||
AP_INIT_TAKE1("uWSGIforceScriptName", cmd_uwsgi_force_script_name, NULL, ACCESS_CONF, "Fix for PATH_INFO/SCRIPT_NAME when the location has filesystem correspondence"),
|
||||
AP_INIT_TAKE1("uWSGIforceCGImode", cmd_uwsgi_force_cgi_mode, NULL, ACCESS_CONF, "Force uWSGI CGI mode for perfect integration with apache filter"),
|
||||
AP_INIT_TAKE1("uWSGIforceWSGIscheme", cmd_uwsgi_force_wsgi_scheme, NULL, ACCESS_CONF, "Force the WSGI scheme var (set by default to \"http\")"),
|
||||
{NULL}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
all: clean uwsgi
|
||||
|
||||
uwsgi: utils.o protocol.o socket.o pymodule.o spooler.o main.o
|
||||
$(CC) $(LD_FLAGS) utils.o protocol.o socket.o spooler.o pymodule.o main.o -o $(PROGRAM)
|
||||
uwsgi: utils.o protocol.o socket.o pymodule.o spooler.o logging.o xmlconf.o snmp.o proxy.o erlang.o wsgihandlers.o basehandlers.o main.o
|
||||
$(CC) -lpthread utils.o protocol.o socket.o spooler.o logging.o xmlconf.o snmp.o proxy.o erlang.o pymodule.o wsgihandlers.o basehandlers.o main.o -o $(PROGRAM) $(LD_FLAGS)
|
||||
|
||||
utils.o: utils.c
|
||||
$(CC) -c $(CFLAGS) utils.c
|
||||
@@ -15,11 +15,32 @@ socket.o: socket.c
|
||||
spooler.o: spooler.c
|
||||
$(CC) -c $(CFLAGS) spooler.c
|
||||
|
||||
logging.o: logging.c
|
||||
$(CC) -c $(CFLAGS) logging.c
|
||||
|
||||
xmlconf.o: xmlconf.c
|
||||
$(CC) -c $(CFLAGS) xmlconf.c
|
||||
|
||||
snmp.o: snmp.c
|
||||
$(CC) -c $(CFLAGS) snmp.c
|
||||
|
||||
proxy.o: proxy.c
|
||||
$(CC) -c $(CFLAGS) proxy.c
|
||||
|
||||
erlang.o: erlang.c
|
||||
$(CC) -c $(CFLAGS) erlang.c
|
||||
|
||||
pymodule.o: uwsgi_pymodule.c
|
||||
$(CC) -c $(CFLAGS) -o pymodule.o uwsgi_pymodule.c
|
||||
|
||||
basehandlers.o: uwsgi_handlers.c
|
||||
$(CC) -c $(CFLAGS) -o basehandlers.o uwsgi_handlers.c
|
||||
|
||||
wsgihandlers.o: wsgi_handlers.c
|
||||
$(CC) -c $(CFLAGS) -o wsgihandlers.o wsgi_handlers.c
|
||||
|
||||
main.o: uwsgi.c
|
||||
$(CC) -c $(CFLAGS) -o main.o uwsgi.c
|
||||
|
||||
clean:
|
||||
rm -f utils.o protocol.o socket.o pymodule.o spooler.o main.o
|
||||
rm -f utils.o protocol.o socket.o pymodule.o spooler.o logging.o xmlconf.o snmp.o proxy.o erlang.o wsgihandlers.o basehandlers.o main.o
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
the uwsgi handler is included in the official Cherokee distribution
|
||||
@@ -1,92 +0,0 @@
|
||||
from Form import *
|
||||
from Table import *
|
||||
from Module import *
|
||||
from validations import *
|
||||
from consts import *
|
||||
|
||||
# For gettext
|
||||
N_ = lambda x: x
|
||||
|
||||
from ModuleCgi import *
|
||||
from ModuleBalancer import NOTE_BALANCER
|
||||
|
||||
HELPS = [
|
||||
('modules_handlers_uwsgi', "UWSGI")
|
||||
]
|
||||
|
||||
class ModuleUwsgi (ModuleCgiBase):
|
||||
PROPERTIES = ModuleCgiBase.PROPERTIES + [
|
||||
'balancer',
|
||||
'modifier1',
|
||||
'modifier2',
|
||||
'pass_wsgi_vars',
|
||||
'pass_request_body'
|
||||
]
|
||||
|
||||
def __init__ (self, cfg, prefix, submit):
|
||||
ModuleCgiBase.__init__ (self, cfg, prefix, 'uwsgi', submit)
|
||||
|
||||
self.show_script_alias = False
|
||||
self.show_change_uid = False
|
||||
self.show_document_root = True
|
||||
|
||||
def _op_render (self):
|
||||
txt = ModuleCgiBase._op_render (self)
|
||||
|
||||
txt += '<h2>%s</h2>' % (_('UWSGI specific'))
|
||||
|
||||
table = TableProps()
|
||||
|
||||
|
||||
opt = "%s!modifier1" % (self._prefix)
|
||||
self.AddPropEntry(table, _('Modifier1'), opt, 'a number between 0 and 255', size=3);
|
||||
|
||||
opt = "%s!modifier2" % (self._prefix)
|
||||
self.AddPropEntry(table, _('Modifier2'), opt, 'a number between 0 and 255', size=3);
|
||||
|
||||
opt = "%s!pass_wsgi_vars" % (self._prefix)
|
||||
self.AddPropCheck (table, _("Pass WSGI vars"), opt, True, 'pass all the wsgi vars to the application')
|
||||
|
||||
opt = "%s!pass_request_body" % (self._prefix)
|
||||
self.AddPropCheck (table, _("Pass Request body"), opt, True, 'pass the request body to the application')
|
||||
|
||||
opt = "%s!balancer" % (self._prefix)
|
||||
e = self.AddPropOptions_Reload_Module (table, _("Balancer"), opt,
|
||||
modules_available(BALANCERS), _(NOTE_BALANCER))
|
||||
|
||||
txt += self.Indent(str(table) + e)
|
||||
|
||||
return txt
|
||||
|
||||
def _op_apply_changes (self, uri, post):
|
||||
|
||||
# Apply modifier1
|
||||
opt = "%s!modifier1" % (self._prefix)
|
||||
mod1 = post.pop(opt)
|
||||
if mod1:
|
||||
self._cfg[opt] = mod1
|
||||
|
||||
# Apply modifier2
|
||||
opt = "%s!modifier2" % (self._prefix)
|
||||
mod2 = post.pop(opt)
|
||||
if mod2:
|
||||
self._cfg[opt] = mod2
|
||||
|
||||
# Apply pass_request_body and pass_wsgi_vars
|
||||
self.ApplyChangesPrefix (self._prefix, ['pass_wsgi_vars','pass_request_body'], post)
|
||||
|
||||
# Apply balancer changes
|
||||
pre = "%s!balancer" % (self._prefix)
|
||||
|
||||
new_balancer = post.pop(pre)
|
||||
if new_balancer:
|
||||
self._cfg[pre] = new_balancer
|
||||
|
||||
cfg = self._cfg[pre]
|
||||
if cfg and cfg.value:
|
||||
name = cfg.value
|
||||
props = module_obj_factory (name, self._cfg, pre, self.submit_url)
|
||||
props._op_apply_changes (uri, post)
|
||||
|
||||
# And CGI changes
|
||||
return ModuleCgiBase._op_apply_changes (self, uri, post)
|
||||
@@ -1,452 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
|
||||
/* Cherokee
|
||||
*
|
||||
* Authors:
|
||||
* Alvaro Lopez Ortega <alvaro@alobbs.com>
|
||||
*
|
||||
* Copyright (C) 2001-2009 Alvaro Lopez Ortega
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2 of the GNU General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "common-internal.h"
|
||||
#include "handler_uwsgi.h"
|
||||
|
||||
#include "connection.h"
|
||||
#include "source_interpreter.h"
|
||||
#include "thread.h"
|
||||
#include "util.h"
|
||||
#include "connection-protected.h"
|
||||
#include "bogotime.h"
|
||||
|
||||
#define ENTRIES "handler,cgi"
|
||||
|
||||
/* Plug-in initialization
|
||||
*/
|
||||
CGI_LIB_INIT (uwsgi, http_all_methods);
|
||||
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
static uint16_t uwsgi_swap16(uint16_t x) {
|
||||
return (uint16_t) ((x & 0xff) << 8 | (x & 0xff00) >> 8);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Methods implementation
|
||||
*/
|
||||
static ret_t
|
||||
props_free (cherokee_handler_uwsgi_props_t *props)
|
||||
{
|
||||
if (props->balancer)
|
||||
cherokee_balancer_free (props->balancer);
|
||||
|
||||
return cherokee_handler_cgi_base_props_free (PROP_CGI_BASE(props));
|
||||
}
|
||||
|
||||
ret_t
|
||||
cherokee_handler_uwsgi_configure (cherokee_config_node_t *conf, cherokee_server_t *srv, cherokee_module_props_t **_props)
|
||||
{
|
||||
ret_t ret;
|
||||
cherokee_list_t *i;
|
||||
cherokee_handler_uwsgi_props_t *props;
|
||||
|
||||
/* Instance a new property object
|
||||
*/
|
||||
if (*_props == NULL) {
|
||||
CHEROKEE_NEW_STRUCT (n, handler_uwsgi_props);
|
||||
|
||||
cherokee_handler_cgi_base_props_init_base (PROP_CGI_BASE(n),
|
||||
MODULE_PROPS_FREE(props_free));
|
||||
|
||||
n->balancer = NULL;
|
||||
n->modifier1 = 0 ;
|
||||
n->modifier2 = 0 ;
|
||||
n->pass_wsgi_vars = true;
|
||||
n->pass_request_body = true;
|
||||
|
||||
*_props = MODULE_PROPS(n);
|
||||
}
|
||||
|
||||
props = PROP_UWSGI(*_props);
|
||||
|
||||
/* Parse the configuration tree
|
||||
*/
|
||||
cherokee_config_node_foreach (i, conf) {
|
||||
cherokee_config_node_t *subconf = CONFIG_NODE(i);
|
||||
|
||||
if (equal_buf_str (&subconf->key, "balancer")) {
|
||||
ret = cherokee_balancer_instance (&subconf->val, subconf, srv, &props->balancer);
|
||||
if (ret != ret_ok) return ret;
|
||||
}
|
||||
else if (equal_buf_str (&subconf->key, "modifier1")) {
|
||||
props->modifier1 = (uint8_t) atoi(subconf->val.buf);
|
||||
}
|
||||
else if (equal_buf_str (&subconf->key, "modifier2")) {
|
||||
props->modifier2 = (uint8_t) atoi(subconf->val.buf);
|
||||
}
|
||||
else if (equal_buf_str (&subconf->key, "pass_wsgi_vars")) {
|
||||
props->pass_wsgi_vars = !! atoi (subconf->val.buf);
|
||||
}
|
||||
else if (equal_buf_str (&subconf->key, "pass_request_body")) {
|
||||
props->pass_request_body = !! atoi (subconf->val.buf);
|
||||
}
|
||||
}
|
||||
|
||||
/* Init base class
|
||||
*/
|
||||
ret = cherokee_handler_cgi_base_configure (conf, srv, _props);
|
||||
if (ret != ret_ok) return ret;
|
||||
|
||||
/* Final checks
|
||||
*/
|
||||
if (props->balancer == NULL) {
|
||||
LOG_CRITICAL_S (CHEROKEE_ERROR_HANDLER_NO_BALANCER);
|
||||
return ret_error;
|
||||
}
|
||||
|
||||
return ret_ok;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
add_env_pair (cherokee_handler_cgi_base_t *cgi_base,
|
||||
const char *key, int key_len,
|
||||
const char *val, int val_len)
|
||||
{
|
||||
cherokee_handler_uwsgi_t *uwsgi = HDL_UWSGI(cgi_base);
|
||||
uint16_t u_key_len = (uint16_t) key_len ;
|
||||
uint16_t u_val_len = (uint16_t) val_len ;
|
||||
|
||||
|
||||
/* 2 bytes for every string (16 bit le) */
|
||||
cherokee_buffer_ensure_size (&uwsgi->header, uwsgi->header.len + key_len + val_len + 4);
|
||||
|
||||
/* force to le if cherokee is big-endian */
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
u_key_len = uwsgi_swap16(u_key_len);
|
||||
#endif
|
||||
cherokee_buffer_add (&uwsgi->header, (const char *) &u_key_len, 2);
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
u_key_len = uwsgi_swap16(u_key_len);
|
||||
#endif
|
||||
cherokee_buffer_add (&uwsgi->header, key, key_len);
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
u_val_len = uwsgi_swap16(u_val_len);
|
||||
#endif
|
||||
cherokee_buffer_add (&uwsgi->header, (const char *) &u_val_len, 2);
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
u_val_len = uwsgi_swap16(u_val_len);
|
||||
#endif
|
||||
cherokee_buffer_add (&uwsgi->header, val, val_len);
|
||||
}
|
||||
|
||||
|
||||
static ret_t
|
||||
read_from_uwsgi (cherokee_handler_cgi_base_t *cgi_base, cherokee_buffer_t *buffer)
|
||||
{
|
||||
ret_t ret;
|
||||
size_t read = 0;
|
||||
cherokee_handler_uwsgi_t *uwsgi = HDL_UWSGI(cgi_base);
|
||||
|
||||
ret = cherokee_socket_bufread (&uwsgi->socket, buffer, 4096, &read);
|
||||
|
||||
switch (ret) {
|
||||
case ret_eagain:
|
||||
cherokee_thread_deactive_to_polling (HANDLER_THREAD(cgi_base), HANDLER_CONN(cgi_base),
|
||||
uwsgi->socket.socket, 0, false);
|
||||
return ret_eagain;
|
||||
|
||||
case ret_ok:
|
||||
TRACE (ENTRIES, "%d bytes read\n", read);
|
||||
return ret_ok;
|
||||
|
||||
case ret_eof:
|
||||
case ret_error:
|
||||
cgi_base->got_eof = true;
|
||||
return ret;
|
||||
|
||||
default:
|
||||
RET_UNKNOWN(ret);
|
||||
}
|
||||
|
||||
SHOULDNT_HAPPEN;
|
||||
return ret_error;
|
||||
}
|
||||
|
||||
|
||||
ret_t
|
||||
cherokee_handler_uwsgi_new (cherokee_handler_t **hdl, void *cnt, cherokee_module_props_t *props)
|
||||
{
|
||||
CHEROKEE_NEW_STRUCT (n, handler_uwsgi);
|
||||
|
||||
/* Init the base class
|
||||
*/
|
||||
cherokee_handler_cgi_base_init (
|
||||
HDL_CGI_BASE(n), cnt,
|
||||
PLUGIN_INFO_HANDLER_PTR(uwsgi),
|
||||
HANDLER_PROPS(props),
|
||||
add_env_pair, read_from_uwsgi);
|
||||
|
||||
/* Virtual methods
|
||||
*/
|
||||
MODULE(n)->init = (handler_func_init_t) cherokee_handler_uwsgi_init;
|
||||
MODULE(n)->free = (module_func_free_t) cherokee_handler_uwsgi_free;
|
||||
|
||||
/* Virtual methods: implemented by handler_cgi_base
|
||||
*/
|
||||
HANDLER(n)->step = (handler_func_step_t) cherokee_handler_cgi_base_step;
|
||||
HANDLER(n)->add_headers = (handler_func_add_headers_t) cherokee_handler_cgi_base_add_headers;
|
||||
|
||||
/* Properties
|
||||
*/
|
||||
n->post_len = 0;
|
||||
n->src_ref = NULL;
|
||||
|
||||
cherokee_buffer_init (&n->header);
|
||||
cherokee_socket_init (&n->socket);
|
||||
|
||||
/* Return the object
|
||||
*/
|
||||
*hdl = HANDLER(n);
|
||||
return ret_ok;
|
||||
}
|
||||
|
||||
|
||||
ret_t
|
||||
cherokee_handler_uwsgi_free (cherokee_handler_uwsgi_t *hdl)
|
||||
{
|
||||
/* Free the rest of the handler CGI memory
|
||||
*/
|
||||
cherokee_handler_cgi_base_free (HDL_CGI_BASE(hdl));
|
||||
|
||||
/* UWSGI stuff
|
||||
*/
|
||||
cherokee_socket_close (&hdl->socket);
|
||||
cherokee_socket_mrproper (&hdl->socket);
|
||||
|
||||
cherokee_buffer_mrproper (&hdl->header);
|
||||
|
||||
return ret_ok;
|
||||
}
|
||||
|
||||
|
||||
static ret_t
|
||||
uwsgi_fix_packet (cherokee_buffer_t *buf, uint8_t modifier1, uint8_t modifier2)
|
||||
{
|
||||
|
||||
uwsgi_header uh;
|
||||
|
||||
uh.modifier1 = modifier1 ;
|
||||
uh.modifier2 = modifier2 ;
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
uh.env_size = uwsgi_swap16((uint16_t) buf->len) ;
|
||||
#else
|
||||
uh.env_size = (uint16_t) buf->len ;
|
||||
#endif
|
||||
|
||||
cherokee_buffer_ensure_size (buf, buf->len + 4);
|
||||
cherokee_buffer_prepend (buf, (const char * )&uh, 4);
|
||||
|
||||
return ret_ok;
|
||||
}
|
||||
|
||||
|
||||
static ret_t
|
||||
build_header (cherokee_handler_uwsgi_t *hdl)
|
||||
{
|
||||
|
||||
cherokee_handler_uwsgi_props_t *props = HANDLER_UWSGI_PROPS(hdl);
|
||||
|
||||
cuint_t len;
|
||||
char tmp[64];
|
||||
|
||||
if (props->pass_request_body == true && props->pass_wsgi_vars == true) {
|
||||
len = snprintf (tmp, sizeof(tmp), FMT_OFFSET, (CST_OFFSET)hdl->post_len);
|
||||
add_env_pair(HDL_CGI_BASE(hdl), "CONTENT_LENGTH", 14, tmp, len);
|
||||
}
|
||||
|
||||
if (props->pass_wsgi_vars == true) {
|
||||
cherokee_handler_cgi_base_build_envp (HDL_CGI_BASE(hdl), HANDLER_CONN(hdl));
|
||||
}
|
||||
|
||||
return uwsgi_fix_packet (&hdl->header, props->modifier1, props->modifier2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static ret_t
|
||||
connect_to_server (cherokee_handler_uwsgi_t *hdl)
|
||||
{
|
||||
ret_t ret;
|
||||
cherokee_connection_t *conn = HANDLER_CONN(hdl);
|
||||
cherokee_handler_uwsgi_props_t *props = HANDLER_UWSGI_PROPS(hdl);
|
||||
|
||||
/* Get a reference to the target host
|
||||
*/
|
||||
if (hdl->src_ref == NULL) {
|
||||
ret = cherokee_balancer_dispatch (props->balancer, conn, &hdl->src_ref);
|
||||
if (ret != ret_ok)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Try to connect
|
||||
*/
|
||||
if (hdl->src_ref->type == source_host) {
|
||||
ret = cherokee_source_connect_polling (hdl->src_ref, &hdl->socket, conn);
|
||||
if ((ret == ret_deny) || (ret == ret_error))
|
||||
{
|
||||
cherokee_balancer_report_fail (props->balancer, conn, hdl->src_ref);
|
||||
}
|
||||
} else {
|
||||
ret = cherokee_source_interpreter_connect_polling (SOURCE_INT(hdl->src_ref),
|
||||
&hdl->socket, conn);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static ret_t
|
||||
send_header (cherokee_handler_uwsgi_t *hdl)
|
||||
{
|
||||
ret_t ret;
|
||||
size_t written = 0;
|
||||
cherokee_connection_t *conn = HANDLER_CONN(hdl);
|
||||
|
||||
ret = cherokee_socket_bufwrite (&hdl->socket, &hdl->header, &written);
|
||||
if (ret != ret_ok) {
|
||||
conn->error_code = http_bad_gateway;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if 0
|
||||
cherokee_buffer_print_debug (&hdl->header, -1);
|
||||
#endif
|
||||
cherokee_buffer_move_to_begin (&hdl->header, written);
|
||||
|
||||
TRACE (ENTRIES, "sent remaining=%d\n", hdl->header.len);
|
||||
|
||||
if (! cherokee_buffer_is_empty (&hdl->header))
|
||||
return ret_eagain;
|
||||
|
||||
return ret_ok;
|
||||
}
|
||||
|
||||
|
||||
static ret_t
|
||||
send_post (cherokee_handler_uwsgi_t *hdl)
|
||||
{
|
||||
ret_t ret;
|
||||
int e_fd = -1;
|
||||
int mode = 0;
|
||||
cherokee_connection_t *conn = HANDLER_CONN(hdl);
|
||||
|
||||
ret = cherokee_post_walk_to_fd (&conn->post, hdl->socket.socket, &e_fd, &mode);
|
||||
|
||||
switch (ret) {
|
||||
case ret_ok:
|
||||
break;
|
||||
case ret_eagain:
|
||||
if (e_fd != -1)
|
||||
cherokee_thread_deactive_to_polling (HANDLER_THREAD(hdl), conn, e_fd, mode, false);
|
||||
return ret_eagain;
|
||||
default:
|
||||
conn->error_code = http_bad_gateway;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret_ok;
|
||||
}
|
||||
|
||||
|
||||
ret_t
|
||||
cherokee_handler_uwsgi_init (cherokee_handler_uwsgi_t *hdl)
|
||||
{
|
||||
ret_t ret;
|
||||
cherokee_connection_t *conn = HANDLER_CONN(hdl);
|
||||
cherokee_handler_uwsgi_props_t *props = HANDLER_UWSGI_PROPS(hdl);
|
||||
|
||||
switch (HDL_CGI_BASE(hdl)->init_phase) {
|
||||
case hcgi_phase_build_headers:
|
||||
TRACE (ENTRIES, "Init: %s\n", "begins");
|
||||
|
||||
/* Extracts PATH_INFO and filename from request uri
|
||||
*/
|
||||
ret = cherokee_handler_cgi_base_extract_path (HDL_CGI_BASE(hdl), false);
|
||||
if (unlikely (ret < ret_ok)) {
|
||||
conn->error_code = http_internal_error;
|
||||
return ret_error;
|
||||
}
|
||||
|
||||
/* Prepare Post
|
||||
*/
|
||||
if (! cherokee_post_is_empty (&conn->post)) {
|
||||
cherokee_post_walk_reset (&conn->post);
|
||||
cherokee_post_get_len (&conn->post, &hdl->post_len);
|
||||
}
|
||||
|
||||
/* Build the headers
|
||||
*/
|
||||
ret = build_header (hdl);
|
||||
if (unlikely (ret != ret_ok)) {
|
||||
conn->error_code = http_internal_error;
|
||||
return ret_error;
|
||||
}
|
||||
|
||||
HDL_CGI_BASE(hdl)->init_phase = hcgi_phase_connect;
|
||||
|
||||
case hcgi_phase_connect:
|
||||
TRACE (ENTRIES, "Init: %s\n", "connect");
|
||||
|
||||
/* Connect
|
||||
*/
|
||||
ret = connect_to_server (hdl);
|
||||
switch (ret) {
|
||||
case ret_ok:
|
||||
break;
|
||||
case ret_eagain:
|
||||
return ret_eagain;
|
||||
case ret_deny:
|
||||
conn->error_code = http_gateway_timeout;
|
||||
return ret_error;
|
||||
default:
|
||||
conn->error_code = http_service_unavailable;
|
||||
return ret_error;
|
||||
}
|
||||
|
||||
HDL_CGI_BASE(hdl)->init_phase = hcgi_phase_send_headers;
|
||||
|
||||
case hcgi_phase_send_headers:
|
||||
TRACE (ENTRIES, "Init: %s\n", "send_headers");
|
||||
|
||||
/* Send the header
|
||||
*/
|
||||
ret = send_header (hdl);
|
||||
if (ret != ret_ok)
|
||||
return ret;
|
||||
|
||||
HDL_CGI_BASE(hdl)->init_phase = hcgi_phase_send_post;
|
||||
|
||||
case hcgi_phase_send_post:
|
||||
/* Send the Post
|
||||
*/
|
||||
if (hdl->post_len > 0 && props->pass_request_body == true) {
|
||||
return send_post (hdl);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return ret_ok;
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
|
||||
/* Cherokee
|
||||
*
|
||||
* Authors:
|
||||
* Alvaro Lopez Ortega <alvaro@alobbs.com>
|
||||
*
|
||||
* Copyright (C) 2001-2009 Alvaro Lopez Ortega
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2 of the GNU General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef CHEROKEE_HANDLER_UWSGI_H
|
||||
#define CHEROKEE_HANDLER_UWSGI_H
|
||||
|
||||
#include "common-internal.h"
|
||||
|
||||
#include "handler.h"
|
||||
#include "buffer.h"
|
||||
#include "plugin_loader.h"
|
||||
#include "socket.h"
|
||||
#include "handler_cgi_base.h"
|
||||
#include "balancer.h"
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t modifier1;
|
||||
uint16_t env_size;
|
||||
uint8_t modifier2;
|
||||
} uwsgi_header ;
|
||||
|
||||
|
||||
typedef struct {
|
||||
cherokee_handler_cgi_base_t base;
|
||||
cherokee_balancer_t *balancer;
|
||||
uint8_t modifier1;
|
||||
uint8_t modifier2;
|
||||
cherokee_boolean_t pass_wsgi_vars;
|
||||
cherokee_boolean_t pass_request_body;
|
||||
} cherokee_handler_uwsgi_props_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
cherokee_handler_cgi_base_t base;
|
||||
cherokee_buffer_t header;
|
||||
cherokee_socket_t socket;
|
||||
cherokee_source_t *src_ref;
|
||||
time_t spawned;
|
||||
off_t post_len;
|
||||
} cherokee_handler_uwsgi_t;
|
||||
|
||||
#define HDL_UWSGI(x) ((cherokee_handler_uwsgi_t *)(x))
|
||||
#define PROP_UWSGI(x) ((cherokee_handler_uwsgi_props_t *)(x))
|
||||
#define HANDLER_UWSGI_PROPS(x) (PROP_UWSGI(MODULE(x)->props))
|
||||
|
||||
|
||||
/* Library init function
|
||||
*/
|
||||
void PLUGIN_INIT_NAME(uwsgi) (cherokee_plugin_loader_t *loader);
|
||||
|
||||
/* Methods
|
||||
*/
|
||||
ret_t cherokee_handler_uwsgi_new (cherokee_handler_t **hdl, void *cnt, cherokee_module_props_t *props);
|
||||
ret_t cherokee_handler_uwsgi_free (cherokee_handler_uwsgi_t *hdl);
|
||||
ret_t cherokee_handler_uwsgi_init (cherokee_handler_uwsgi_t *hdl);
|
||||
|
||||
#endif /* CHEROKEE_HANDLER_UWSGI_H */
|
||||
@@ -1 +0,0 @@
|
||||
file
|
||||
@@ -0,0 +1,69 @@
|
||||
{% extends "admin/base_site.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
|
||||
{% block breadcrumbs %}
|
||||
<div class="breadcrumbs">
|
||||
<a href="../">{% trans 'Home' %}</a> ›
|
||||
{% trans 'uWSGI' %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<div id="content-main">
|
||||
<h1>uWSGI status</h1>
|
||||
<b>masterpid:</b> {{masterpid}}<br/>
|
||||
<b>started_on:</b> {{started_on}}<br/>
|
||||
<b>buffer size:</b> {{buffer_size}}<br/>
|
||||
<b>workers:</b> {{numproc}}<br/>
|
||||
<b>total requests:</b> {{total_requests}}<br/>
|
||||
|
||||
<br/>
|
||||
|
||||
<div class="module" style="width:860px">
|
||||
<table>
|
||||
<caption style="width:860px">workers</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="row">id</th>
|
||||
<th scope="row">pid</th>
|
||||
<th scope="row">requests</th>
|
||||
<th scope="row">running time (milliseconds)</th>
|
||||
<th scope="row">load</th>
|
||||
<th scope="row">last spawn</th>
|
||||
<th scope="row">respawn count</th>
|
||||
<th scope="row">address space (vsz)</th>
|
||||
<th scope="row">resident memory (rss)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for w in workers %}
|
||||
<tr>
|
||||
<td align="center">{{w.id}}</td>
|
||||
<td align="center">{{w.pid}}</td>
|
||||
<td align="right">{{w.requests}}</td>
|
||||
<td align="right">{{w.running_time}}</td>
|
||||
<td align="right">{{w.load|floatformat:2}} %</td>
|
||||
<td align="right">{{w.last_spawn_str}}</td>
|
||||
<td align="right">{{w.respawn_count}}</td>
|
||||
<td align="right">{{w.vsz|filesizeformat}}</td>
|
||||
<td align="right">{{w.rss|filesizeformat}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{% if masterpid %}
|
||||
<br/>
|
||||
<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="reload/" method="post">
|
||||
<input type="submit" value="gracefully reload uWSGI" name="_reload"/>
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import sys, os
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from django.conf.urls.defaults import *
|
||||
|
||||
urlpatterns = patterns('uwsgi_admin.views',
|
||||
(r'^$', 'index'),
|
||||
(r'^reload/$', 'reload')
|
||||
)
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import uwsgi
|
||||
import time
|
||||
from django.shortcuts import render_to_response
|
||||
from django.template import RequestContext
|
||||
from django.contrib.admin.views.decorators import staff_member_required
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http import HttpResponseRedirect
|
||||
|
||||
|
||||
def index(request):
|
||||
workers = uwsgi.workers()
|
||||
total_load = time.time() - uwsgi.started_on
|
||||
for w in workers:
|
||||
w['load'] = (100 * (w['running_time']/1000))/total_load
|
||||
w['last_spawn_str'] = time.ctime(w['last_spawn'])
|
||||
|
||||
return render_to_response('uwsgi.html', {'masterpid': uwsgi.masterpid(),
|
||||
'started_on': time.ctime(uwsgi.started_on),
|
||||
'buffer_size': uwsgi.buffer_size,
|
||||
'total_requests': uwsgi.total_requests(),
|
||||
'numproc': uwsgi.numproc,
|
||||
'workers': workers,
|
||||
}, RequestContext(request, {}))
|
||||
index = staff_member_required(index)
|
||||
|
||||
def reload(request):
|
||||
if uwsgi.masterpid() > 0:
|
||||
uwsgi.reload()
|
||||
request.user.message_set.create(message="uWSGI reloaded")
|
||||
else:
|
||||
request.user.message_set.create(message="The uWSGI master process is not active")
|
||||
|
||||
return HttpResponseRedirect(reverse(index))
|
||||
|
||||
reload = staff_member_required(reload)
|
||||
@@ -0,0 +1,702 @@
|
||||
#ifdef UWSGI_ERLANG
|
||||
|
||||
#include "uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
static void erlang_log(void);
|
||||
|
||||
PyObject *py_erlang_connect(PyObject * self, PyObject * args) {
|
||||
|
||||
char *erlang_node;
|
||||
int fd;
|
||||
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s:erlang_connect", &erlang_node)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UWSGI_SET_BLOCKING;
|
||||
fd = erl_connect(erlang_node);
|
||||
UWSGI_UNSET_BLOCKING;
|
||||
return PyInt_FromLong(fd);
|
||||
}
|
||||
|
||||
PyObject *py_erlang_recv_message(PyObject * self, PyObject * args) {
|
||||
int erfd;
|
||||
struct pollfd erpoll;
|
||||
ErlMessage emsg;
|
||||
PyObject *pyer = NULL;
|
||||
unsigned char erlang_buffer[8192];
|
||||
int eret;
|
||||
int timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i|i:erlang_recv_message", &erfd, &timeout)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (erfd < 0) {
|
||||
goto clear;
|
||||
}
|
||||
|
||||
erpoll.fd = erfd;
|
||||
erpoll.events = POLLIN;
|
||||
cycle:
|
||||
memset(&emsg, 0, sizeof(ErlMessage));
|
||||
UWSGI_SET_BLOCKING;
|
||||
if (timeout > 0) {
|
||||
eret = poll(&erpoll, 1, timeout * 1000);
|
||||
if (eret < 0) {
|
||||
perror("poll()");
|
||||
goto clear;
|
||||
}
|
||||
else if (eret == 0) {
|
||||
goto clear;
|
||||
}
|
||||
}
|
||||
if (erl_receive_msg(erfd, erlang_buffer, 8192, &emsg) == ERL_MSG) {
|
||||
if (emsg.type == ERL_TICK) {
|
||||
goto cycle;
|
||||
}
|
||||
if (emsg.msg) {
|
||||
pyer = eterm_to_py(emsg.msg);
|
||||
}
|
||||
if (emsg.msg) {
|
||||
erl_free_compound(emsg.msg);
|
||||
}
|
||||
if (emsg.to) {
|
||||
erl_free_compound(emsg.to);
|
||||
}
|
||||
if (emsg.from) {
|
||||
erl_free_compound(emsg.from);
|
||||
}
|
||||
if (!pyer) {
|
||||
goto clear;
|
||||
}
|
||||
UWSGI_UNSET_BLOCKING;
|
||||
return pyer;
|
||||
}
|
||||
|
||||
clear:
|
||||
UWSGI_UNSET_BLOCKING;
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_erlang_send_message(PyObject * self, PyObject * args) {
|
||||
|
||||
ETERM *pymessage;
|
||||
ETERM *pid;
|
||||
int erfd;
|
||||
PyObject *ermessage, *erdest, *zero;
|
||||
|
||||
int er_number, er_serial, er_creation;
|
||||
char *er_node;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "iOO|i:erlang_send_message", &erfd, &erdest, &ermessage)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (erfd < 0) {
|
||||
goto clear;
|
||||
}
|
||||
|
||||
if (!PyString_Check(erdest) && !PyDict_Check(erdest)) {
|
||||
goto clear;
|
||||
}
|
||||
|
||||
pymessage = py_to_eterm(ermessage);
|
||||
if (!pymessage) {
|
||||
goto clear;
|
||||
}
|
||||
|
||||
|
||||
if (PyString_Check(erdest)) {
|
||||
if (!erl_reg_send(erfd, PyString_AsString(erdest), pymessage)) {
|
||||
erl_err_msg("erl_reg_send()");
|
||||
goto clear2;
|
||||
}
|
||||
}
|
||||
else if (PyDict_Check(erdest)) {
|
||||
zero = PyDict_GetItemString(erdest, "node");
|
||||
if (!zero) {
|
||||
goto clear2;
|
||||
}
|
||||
if (!PyString_Check(zero)) {
|
||||
goto clear2;
|
||||
}
|
||||
er_node = PyString_AsString(zero);
|
||||
|
||||
zero = PyDict_GetItemString(erdest, "number");
|
||||
if (!zero) {
|
||||
goto clear2;
|
||||
}
|
||||
if (!PyInt_Check(zero)) {
|
||||
goto clear2;
|
||||
}
|
||||
er_number = PyInt_AsLong(zero);
|
||||
|
||||
zero = PyDict_GetItemString(erdest, "serial");
|
||||
if (!zero) {
|
||||
goto clear2;
|
||||
}
|
||||
if (!PyInt_Check(zero)) {
|
||||
goto clear2;
|
||||
}
|
||||
er_serial = PyInt_AsLong(zero);
|
||||
|
||||
zero = PyDict_GetItemString(erdest, "creation");
|
||||
if (!zero) {
|
||||
goto clear2;
|
||||
}
|
||||
if (!PyInt_Check(zero)) {
|
||||
goto clear2;
|
||||
}
|
||||
er_creation = PyInt_AsLong(zero);
|
||||
|
||||
pid = erl_mk_pid((const char *) er_node, er_number, er_serial, er_creation);
|
||||
|
||||
if (!pid) {
|
||||
goto clear2;
|
||||
}
|
||||
|
||||
if (!erl_send(erfd, pid, pymessage)) {
|
||||
erl_err_msg("erl_send()");
|
||||
erl_free_term(pid);
|
||||
goto clear2;
|
||||
}
|
||||
|
||||
erl_free_term(pid);
|
||||
}
|
||||
else {
|
||||
goto clear;
|
||||
}
|
||||
|
||||
erl_free_compound(pymessage);
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
clear2:
|
||||
erl_free_compound(pymessage);
|
||||
clear:
|
||||
PyErr_Print();
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_erlang_rpc(PyObject * self, PyObject * args) {
|
||||
|
||||
int fd, timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
|
||||
char *emod, *efun;
|
||||
PyObject *eargs, *pyer = NULL;
|
||||
ETERM *pyargs, *rex;
|
||||
ErlMessage emsg;
|
||||
int eret;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "issO|i:erlang_rpc", &fd, &emod, &efun, &eargs, &timeout)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fd < 0) {
|
||||
goto clear;
|
||||
}
|
||||
|
||||
pyargs = py_to_eterm(eargs);
|
||||
if (!pyargs) {
|
||||
goto clear;
|
||||
}
|
||||
|
||||
|
||||
if (erl_rpc_to(fd, emod, efun, pyargs)) {
|
||||
erl_err_msg("erl_rpc_to()");
|
||||
goto clear2;
|
||||
}
|
||||
|
||||
|
||||
cycle:
|
||||
memset(&emsg, 0, sizeof(ErlMessage));
|
||||
UWSGI_SET_BLOCKING;
|
||||
eret = erl_rpc_from(fd, timeout * 1000, &emsg);
|
||||
if (eret == ERL_TICK) {
|
||||
goto cycle;
|
||||
}
|
||||
else if (eret == ERL_MSG) {
|
||||
if (emsg.msg) {
|
||||
if (ERL_IS_TUPLE(emsg.msg)) {
|
||||
rex = erl_element(1, emsg.msg);
|
||||
if (!rex) {
|
||||
goto clear2;
|
||||
}
|
||||
if (!strncmp("rex", ERL_ATOM_PTR(rex), ERL_ATOM_SIZE(rex))) {
|
||||
erl_free_term(rex);
|
||||
rex = erl_element(2, emsg.msg);
|
||||
if (!rex) {
|
||||
goto clear2;
|
||||
}
|
||||
pyer = eterm_to_py(rex);
|
||||
erl_free_term(rex);
|
||||
}
|
||||
else {
|
||||
erl_free_term(rex);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (emsg.msg) {
|
||||
erl_free_compound(emsg.msg);
|
||||
}
|
||||
if (emsg.to) {
|
||||
erl_free_compound(emsg.to);
|
||||
}
|
||||
if (emsg.from) {
|
||||
erl_free_compound(emsg.from);
|
||||
}
|
||||
if (!pyer) {
|
||||
goto clear2;
|
||||
}
|
||||
erl_free_compound(pyargs);
|
||||
UWSGI_UNSET_BLOCKING;
|
||||
return pyer;
|
||||
}
|
||||
else {
|
||||
erl_err_msg("erl_rpc_from()");
|
||||
}
|
||||
|
||||
clear2:
|
||||
UWSGI_UNSET_BLOCKING;
|
||||
erl_free_compound(pyargs);
|
||||
|
||||
clear:
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_erlang_close(PyObject * self, PyObject * args) {
|
||||
|
||||
int fd;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i:erlang_close", &fd)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
if (fd >= 0) {
|
||||
erl_close_connection(fd);
|
||||
}
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
}
|
||||
|
||||
static PyMethodDef uwsgi_erlang_methods[] = {
|
||||
{"erlang_connect", py_erlang_connect, METH_VARARGS, ""},
|
||||
{"erlang_send_message", py_erlang_send_message, METH_VARARGS, ""},
|
||||
{"erlang_recv_message", py_erlang_recv_message, METH_VARARGS, ""},
|
||||
{"erlang_rpc", py_erlang_rpc, METH_VARARGS, ""},
|
||||
{"erlang_close", py_erlang_close, METH_VARARGS, ""},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
|
||||
int init_erlang(char *nodename, char *cookie) {
|
||||
|
||||
struct sockaddr_in e_addr;
|
||||
|
||||
char *ip;
|
||||
char *node;
|
||||
int efd;
|
||||
int rlen;
|
||||
char *cookiefile;
|
||||
char *cookiehome;
|
||||
char cookievalue[128];
|
||||
int cookiefd;
|
||||
|
||||
PyMethodDef *uwsgi_function;
|
||||
|
||||
|
||||
ip = strchr(nodename, '@');
|
||||
|
||||
if (ip == NULL) {
|
||||
fprintf(stderr, "*** invalid erlang node name ***\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cookie == NULL) {
|
||||
// get the cookie from the home
|
||||
cookiehome = getenv("HOME");
|
||||
if (!cookiehome) {
|
||||
fprintf(stderr, "unable to get erlang cookie from your home.\n");
|
||||
return -1;
|
||||
}
|
||||
cookiefile = malloc(strlen(cookiehome) + 1 + strlen(".erlang.cookie") + 1);
|
||||
if (!cookiefile) {
|
||||
perror("malloc()");
|
||||
}
|
||||
cookiefile[0] = 0;
|
||||
strcat(cookiefile, cookiehome);
|
||||
strcat(cookiefile, "/.erlang.cookie");
|
||||
|
||||
cookiefd = open(cookiefile, O_RDONLY);
|
||||
if (cookiefd < 0) {
|
||||
perror("open()");
|
||||
free(cookiefile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(cookievalue, 0, 128);
|
||||
if (read(cookiefd, cookievalue, 127) < 1) {
|
||||
fprintf(stderr, "invalid cookie found in %s\n", cookiefile);
|
||||
close(cookiefd);
|
||||
free(cookiefile);
|
||||
return -1;
|
||||
}
|
||||
cookie = cookievalue;
|
||||
close(cookiefd);
|
||||
free(cookiefile);
|
||||
}
|
||||
|
||||
node = malloc((ip - nodename) + 1);
|
||||
if (node == NULL) {
|
||||
perror("malloc()");
|
||||
return -1;
|
||||
}
|
||||
memset(node, 0, (ip - nodename) + 1);
|
||||
memcpy(node, nodename, ip - nodename);
|
||||
|
||||
erl_init(NULL, 0);
|
||||
|
||||
if (erl_connect_xinit(ip + 1, node, nodename, NULL, cookie, 0) == -1) {
|
||||
fprintf(stderr, "*** unable to initialize erlang c-node ***\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
efd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (efd < 0) {
|
||||
perror("socket()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
memset(&e_addr, 0, sizeof(struct sockaddr_in));
|
||||
e_addr.sin_family = AF_INET;
|
||||
e_addr.sin_addr.s_addr = inet_addr(ip + 1);
|
||||
|
||||
rlen = 1;
|
||||
if (setsockopt(efd, SOL_SOCKET, SO_REUSEADDR, &rlen, sizeof(rlen))) {
|
||||
perror("setsockopt()");
|
||||
close(efd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (bind(efd, (struct sockaddr *) &e_addr, sizeof(struct sockaddr_in)) < 0) {
|
||||
perror("bind()");
|
||||
close(efd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rlen = sizeof(struct sockaddr_in);
|
||||
if (getsockname(efd, (struct sockaddr *) &e_addr, (socklen_t *) & rlen)) {
|
||||
perror("getsockname()");
|
||||
close(efd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (listen(efd, uwsgi.listen_queue)) {
|
||||
perror("listen()");
|
||||
close(efd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (erl_publish(ntohs(e_addr.sin_port)) < 0) {
|
||||
fprintf(stderr, "*** unable to subscribe with EPMD ***\n");
|
||||
close(efd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Erlang C-Node initialized on port %d you can access it with name %s\n", ntohs(e_addr.sin_port), nodename);
|
||||
|
||||
for (uwsgi_function = uwsgi_erlang_methods; uwsgi_function->ml_name != NULL; uwsgi_function++) {
|
||||
PyObject *func = PyCFunction_New(uwsgi_function, NULL);
|
||||
PyDict_SetItemString(uwsgi.embedded_dict, uwsgi_function->ml_name, func);
|
||||
Py_DECREF(func);
|
||||
}
|
||||
|
||||
return efd;
|
||||
|
||||
}
|
||||
|
||||
ETERM *py_to_eterm(PyObject * pobj) {
|
||||
int i;
|
||||
int count;
|
||||
PyObject *pobj2;
|
||||
ETERM *eobj = NULL;
|
||||
ETERM *eobj2 = NULL;
|
||||
ETERM **eobj3;
|
||||
|
||||
if (pobj == NULL) {
|
||||
return erl_mk_empty_list();
|
||||
}
|
||||
|
||||
if (PyString_Check(pobj)) {
|
||||
eobj = erl_mk_atom(PyString_AsString(pobj));
|
||||
}
|
||||
else if (PyInt_Check(pobj)) {
|
||||
eobj = erl_mk_int(PyInt_AsLong(pobj));
|
||||
}
|
||||
else if (PyList_Check(pobj)) {
|
||||
eobj = erl_mk_empty_list();
|
||||
for (i = PyList_Size(pobj) - 1; i >= 0; i--) {
|
||||
pobj2 = PyList_GetItem(pobj, i);
|
||||
eobj2 = py_to_eterm(pobj2);
|
||||
eobj = erl_cons(eobj2, eobj);
|
||||
}
|
||||
}
|
||||
else if (PyDict_Check(pobj)) {
|
||||
// a pid
|
||||
char *er_node;
|
||||
int er_number, er_serial, er_creation;
|
||||
pobj2 = PyDict_GetItemString(pobj, "node");
|
||||
if (!pobj2) {
|
||||
PyErr_Print();
|
||||
goto clear;
|
||||
}
|
||||
if (!PyString_Check(pobj2)) {
|
||||
goto clear;
|
||||
}
|
||||
er_node = PyString_AsString(pobj2);
|
||||
|
||||
pobj2 = PyDict_GetItemString(pobj, "number");
|
||||
if (!pobj2) {
|
||||
PyErr_Print();
|
||||
goto clear;
|
||||
}
|
||||
if (!PyInt_Check(pobj2)) {
|
||||
goto clear;
|
||||
}
|
||||
er_number = PyInt_AsLong(pobj2);
|
||||
|
||||
pobj2 = PyDict_GetItemString(pobj, "serial");
|
||||
if (!pobj2) {
|
||||
PyErr_Print();
|
||||
goto clear;
|
||||
}
|
||||
if (!PyInt_Check(pobj2)) {
|
||||
goto clear;
|
||||
}
|
||||
er_serial = PyInt_AsLong(pobj2);
|
||||
|
||||
pobj2 = PyDict_GetItemString(pobj, "creation");
|
||||
if (!pobj2) {
|
||||
PyErr_Print();
|
||||
goto clear;
|
||||
}
|
||||
if (!PyInt_Check(pobj2)) {
|
||||
goto clear;
|
||||
}
|
||||
er_creation = PyInt_AsLong(pobj2);
|
||||
|
||||
eobj = erl_mk_pid(er_node, er_number, er_serial, er_creation);
|
||||
}
|
||||
else if (PyTuple_Check(pobj)) {
|
||||
count = PyTuple_Size(pobj);
|
||||
eobj3 = malloc(sizeof(ETERM *) * count);
|
||||
for (i = 0; i < count; i++) {
|
||||
pobj2 = PyTuple_GetItem(pobj, i);
|
||||
if (!pobj2) {
|
||||
break;
|
||||
}
|
||||
eobj3[i] = py_to_eterm(pobj2);
|
||||
}
|
||||
eobj = erl_mk_tuple(eobj3, count);
|
||||
free(eobj3);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "UNMANAGED PYTHON TYPE: %s\n", pobj->ob_type->tp_name);
|
||||
}
|
||||
|
||||
clear:
|
||||
if (eobj == NULL) {
|
||||
return erl_mk_empty_list();
|
||||
}
|
||||
|
||||
return eobj;
|
||||
}
|
||||
|
||||
PyObject *eterm_to_py(ETERM * obj) {
|
||||
int i;
|
||||
int count;
|
||||
ETERM *obj2;
|
||||
PyObject *eobj = NULL;
|
||||
|
||||
if (obj == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
switch (ERL_TYPE(obj)) {
|
||||
|
||||
case ERL_CONS:
|
||||
case ERL_NIL:
|
||||
count = erl_length(obj);
|
||||
eobj = PyList_New(0);
|
||||
for (i = 0; i < count; i++) {
|
||||
obj2 = erl_hd(obj);
|
||||
PyList_Append(eobj, eterm_to_py(obj2));
|
||||
obj = erl_tl(obj);
|
||||
}
|
||||
break;
|
||||
case ERL_TUPLE:
|
||||
eobj = PyTuple_New(erl_size(obj));
|
||||
for (i = 1; i <= erl_size(obj); i++) {
|
||||
obj2 = erl_element(i, obj);
|
||||
PyTuple_SetItem(eobj, i - 1, eterm_to_py(obj2));
|
||||
}
|
||||
break;
|
||||
case ERL_ATOM:
|
||||
eobj = PyString_FromStringAndSize(ERL_ATOM_PTR(obj), ERL_ATOM_SIZE(obj));
|
||||
break;
|
||||
case ERL_INTEGER:
|
||||
eobj = PyInt_FromLong(ERL_INT_VALUE(obj));
|
||||
break;
|
||||
case ERL_BINARY:
|
||||
fprintf(stderr, "FOUND A BINARY %.*s\n", ERL_BIN_SIZE(obj), ERL_BIN_PTR(obj));
|
||||
break;
|
||||
case ERL_PID:
|
||||
eobj = PyDict_New();
|
||||
if (PyDict_SetItemString(eobj, "node", PyString_FromString(ERL_PID_NODE(obj)))) {
|
||||
PyErr_Print();
|
||||
break;
|
||||
}
|
||||
if (PyDict_SetItemString(eobj, "number", PyInt_FromLong(ERL_PID_NUMBER(obj)))) {
|
||||
PyErr_Print();
|
||||
break;
|
||||
}
|
||||
if (PyDict_SetItemString(eobj, "serial", PyInt_FromLong(ERL_PID_SERIAL(obj)))) {
|
||||
PyErr_Print();
|
||||
break;
|
||||
}
|
||||
if (PyDict_SetItemString(eobj, "creation", PyInt_FromLong(ERL_PID_CREATION(obj)))) {
|
||||
PyErr_Print();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
fprintf(stderr, "UNMANAGED ETERM TYPE: %d\n", ERL_TYPE(obj));
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (eobj == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
return eobj;
|
||||
}
|
||||
|
||||
void erlang_loop() {
|
||||
|
||||
ErlConnect econn;
|
||||
ErlMessage em;
|
||||
ETERM *eresponse;
|
||||
|
||||
PyObject *callable = PyDict_GetItemString(uwsgi.embedded_dict, "erlang_func");
|
||||
if (!callable) {
|
||||
PyErr_Print();
|
||||
fprintf(stderr, "- you have not defined a uwsgi.erlang_func callable, Erlang message manager will be disabled until you define it -\n");
|
||||
}
|
||||
|
||||
PyObject *pargs = PyTuple_New(1);
|
||||
if (!pargs) {
|
||||
PyErr_Print();
|
||||
fprintf(stderr, "- error preparing arg tuple for uwsgi.erlang_func callable, Erlang message manager will be disabled -\n");
|
||||
}
|
||||
|
||||
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
|
||||
|
||||
|
||||
UWSGI_CLEAR_STATUS;
|
||||
|
||||
uwsgi.poll.fd = erl_accept(uwsgi.erlangfd, &econn);
|
||||
|
||||
if (uwsgi.poll.fd >= 0) {
|
||||
|
||||
UWSGI_SET_ERLANGING;
|
||||
for (;;) {
|
||||
if (erl_receive_msg(uwsgi.poll.fd, (unsigned char *) uwsgi.buffer, uwsgi.buffer_size, &em) == ERL_MSG) {
|
||||
if (em.type == ERL_TICK)
|
||||
continue;
|
||||
|
||||
if (!callable) {
|
||||
callable = PyDict_GetItemString(uwsgi.embedded_dict, "erlang_func");
|
||||
}
|
||||
|
||||
if (!callable) {
|
||||
fprintf(stderr, "- you still have not defined a uwsgi.erlang_func callable, Erlang message rejected -\n");
|
||||
}
|
||||
|
||||
PyObject *zero = eterm_to_py(em.msg);
|
||||
if (em.msg) {
|
||||
erl_free_compound(em.msg);
|
||||
}
|
||||
if (em.to) {
|
||||
erl_free_compound(em.to);
|
||||
}
|
||||
|
||||
if (!zero) {
|
||||
PyErr_Print();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (PyTuple_SetItem(pargs, 0, zero)) {
|
||||
PyErr_Print();
|
||||
continue;
|
||||
}
|
||||
|
||||
PyObject *erlang_result = PyEval_CallObject(callable, pargs);
|
||||
|
||||
//Py_DECREF(zero);
|
||||
|
||||
if (erlang_result) {
|
||||
eresponse = py_to_eterm(erlang_result);
|
||||
if (eresponse) {
|
||||
erl_send(uwsgi.poll.fd, em.from, eresponse);
|
||||
erl_free_compound(eresponse);
|
||||
}
|
||||
Py_DECREF(erlang_result);
|
||||
}
|
||||
|
||||
if (em.from) {
|
||||
erl_free_compound(em.from);
|
||||
}
|
||||
|
||||
uwsgi.workers[0].requests++;
|
||||
uwsgi.workers[uwsgi.mywid].requests++;
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_LOGGING])
|
||||
erlang_log();
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
erl_close_connection(uwsgi.poll.fd);
|
||||
|
||||
UWSGI_UNSET_ERLANGING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void erlang_log() {
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG]) {
|
||||
get_memusage();
|
||||
}
|
||||
else {
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = 0;
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = 0;
|
||||
}
|
||||
fprintf(stderr, "[Erlang worker %d pid %d] request %llu done {rss: %llu vsz: %llu}\n", uwsgi.mywid, uwsgi.mypid, uwsgi.workers[uwsgi.mywid].requests, uwsgi.workers[uwsgi.mywid].rss_size, uwsgi.workers[uwsgi.mywid].vsz_size);
|
||||
}
|
||||
|
||||
#else
|
||||
#warning "*** Erlang support is disabled ***"
|
||||
#endif
|
||||
+104
-64
@@ -35,6 +35,23 @@
|
||||
#define data_uwsgi data_fastcgi
|
||||
#define data_uwsgi_init data_fastcgi_init
|
||||
|
||||
#ifdef __linux__
|
||||
#include <endian.h>
|
||||
#elif __sun__
|
||||
#elif __apple__
|
||||
#include <libkern/OSByteOrder.h>
|
||||
#else
|
||||
#include <machine/endian.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
static uint16_t uwsgi_swap16(uint16_t x) {
|
||||
return (uint16_t) ((x & 0xff) << 8 | (x & 0xff00) >> 8);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* the uwsgi module is based on the proxy module
|
||||
@@ -49,23 +66,15 @@ typedef struct __attribute__((packed)) {
|
||||
uint8_t modifier2;
|
||||
} uwsgi_header ;
|
||||
|
||||
typedef enum {
|
||||
UWSGI_BALANCE_UNSET,
|
||||
UWSGI_BALANCE_FAIR,
|
||||
} uwsgi_balance_t;
|
||||
|
||||
typedef struct {
|
||||
array *extensions;
|
||||
unsigned short debug;
|
||||
|
||||
uwsgi_balance_t balance;
|
||||
} plugin_config;
|
||||
|
||||
typedef struct {
|
||||
PLUGIN_DATA;
|
||||
|
||||
buffer *parse_response;
|
||||
buffer *balance_buf;
|
||||
|
||||
plugin_config **config_storage;
|
||||
|
||||
@@ -121,6 +130,7 @@ static handler_ctx * handler_ctx_init() {
|
||||
hctx->fd = -1;
|
||||
hctx->fde_ndx = -1;
|
||||
|
||||
|
||||
return hctx;
|
||||
}
|
||||
|
||||
@@ -138,7 +148,6 @@ INIT_FUNC(mod_uwsgi_init) {
|
||||
p = calloc(1, sizeof(*p));
|
||||
|
||||
p->parse_response = buffer_init();
|
||||
p->balance_buf = buffer_init();
|
||||
|
||||
return p;
|
||||
}
|
||||
@@ -150,7 +159,6 @@ FREE_FUNC(mod_uwsgi_free) {
|
||||
UNUSED(srv);
|
||||
|
||||
buffer_free(p->parse_response);
|
||||
buffer_free(p->balance_buf);
|
||||
|
||||
if (p->config_storage) {
|
||||
size_t i;
|
||||
@@ -180,7 +188,6 @@ SETDEFAULTS_FUNC(mod_uwsgi_set_defaults) {
|
||||
config_values_t cv[] = {
|
||||
{ "uwsgi.server", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
|
||||
{ "uwsgi.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
|
||||
{ "uwsgi.balance", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
|
||||
{ NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
|
||||
};
|
||||
|
||||
@@ -196,9 +203,7 @@ SETDEFAULTS_FUNC(mod_uwsgi_set_defaults) {
|
||||
|
||||
cv[0].destination = s->extensions;
|
||||
cv[1].destination = &(s->debug);
|
||||
cv[2].destination = p->balance_buf;
|
||||
|
||||
buffer_reset(p->balance_buf);
|
||||
|
||||
p->config_storage[i] = s;
|
||||
ca = ((data_config *)srv->config_context->data[i])->value;
|
||||
@@ -207,16 +212,6 @@ SETDEFAULTS_FUNC(mod_uwsgi_set_defaults) {
|
||||
return HANDLER_ERROR;
|
||||
}
|
||||
|
||||
if (buffer_is_empty(p->balance_buf)) {
|
||||
s->balance = UWSGI_BALANCE_FAIR;
|
||||
} else if (buffer_is_equal_string(p->balance_buf, CONST_STR_LEN("fair"))) {
|
||||
s->balance = UWSGI_BALANCE_FAIR;
|
||||
} else {
|
||||
log_error_write(srv, __FILE__, __LINE__, "s",
|
||||
"uwsgi.balance has to be fair");
|
||||
return HANDLER_ERROR;
|
||||
}
|
||||
|
||||
if (NULL != (du = array_get_element(ca, "uwsgi.server"))) {
|
||||
size_t j;
|
||||
data_array *da = (data_array *)du;
|
||||
@@ -276,7 +271,7 @@ SETDEFAULTS_FUNC(mod_uwsgi_set_defaults) {
|
||||
|
||||
df = data_uwsgi_init();
|
||||
|
||||
df->port = 80;
|
||||
df->port = 3031;
|
||||
|
||||
buffer_copy_string_buffer(df->key, da_host->key);
|
||||
|
||||
@@ -396,12 +391,28 @@ static int uwsgi_establish_connection(server *srv, handler_ctx *hctx) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uwsgi_add_var(buffer *b, char * key, uint16_t keylen, char *val, uint16_t vallen) {
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
uint16_t uwlen ;
|
||||
|
||||
uwlen = uwsgi_swap16(keylen);
|
||||
buffer_append_memory(b, (char *) &uwlen, 2); buffer_append_memory(b, key, keylen);
|
||||
uwlen = uwsgi_swap16(vallen);
|
||||
buffer_append_memory(b, (char *) &uwlen, 2); buffer_append_memory(b, val, vallen);
|
||||
#else
|
||||
buffer_append_memory(b, (char *) &keylen, 2); buffer_append_memory(b, key, keylen);
|
||||
buffer_append_memory(b, (char *) &vallen, 2); buffer_append_memory(b, val, vallen);
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
|
||||
size_t i;
|
||||
|
||||
char buf[32];
|
||||
uwsgi_header *uh ;
|
||||
uint16_t uwsgi_strsize;
|
||||
const char *s;
|
||||
#ifdef HAVE_IPV6
|
||||
char b2[INET6_ADDRSTRLEN + 1];
|
||||
@@ -416,36 +427,28 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
|
||||
|
||||
b = chunkqueue_get_append_buffer(hctx->wb);
|
||||
|
||||
log_error_write(srv, __FILE__, __LINE__, "s", "starting uwsgi request...");
|
||||
|
||||
/* make space for uwsgi header */
|
||||
buffer_append_memory(b, "\0\0\0\0", 4);
|
||||
|
||||
log_error_write(srv, __FILE__, __LINE__, "s", "space done...");
|
||||
|
||||
/* set WSGI vars */
|
||||
s = get_http_method_name(con->request.http_method);
|
||||
uwsgi_strsize = 14; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, "REQUEST_METHOD", uwsgi_strsize);
|
||||
uwsgi_strsize = strlen(s); buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, s, uwsgi_strsize);
|
||||
uwsgi_add_var(b, "REQUEST_METHOD", 14, (char *) s, strlen(s));
|
||||
|
||||
uwsgi_strsize = 12; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, "QUERY_STRING", uwsgi_strsize);
|
||||
if (!buffer_is_empty(con->uri.query)) {
|
||||
uwsgi_strsize = con->uri.query->used; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, con->uri.query->ptr, uwsgi_strsize);
|
||||
uwsgi_add_var(b, "QUERY_STRING", 12, con->uri.query->ptr, con->uri.query->used-1);
|
||||
} else {
|
||||
uwsgi_strsize = 0; buffer_append_memory(b, &uwsgi_strsize, 2);
|
||||
uwsgi_add_var(b, "QUERY_STRING", 12, "", 0);
|
||||
}
|
||||
|
||||
s = get_http_version_name(con->request.http_version);
|
||||
uwsgi_strsize = 15; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, "SERVER_PROTOCOL", uwsgi_strsize);
|
||||
uwsgi_strsize = strlen(s); buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, s, uwsgi_strsize);
|
||||
uwsgi_add_var(b, "SERVER_PROTOCOL", 15, (char *) s, strlen(s));
|
||||
|
||||
|
||||
uwsgi_strsize = 11; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, "SERVER_NAME", uwsgi_strsize);
|
||||
if (con->server_name->used) {
|
||||
size_t len = con->server_name->used - 1;
|
||||
char *colon = strchr(con->server_name->ptr, ':');
|
||||
if (colon) len = colon - con->server_name->ptr;
|
||||
uwsgi_strsize = len ;
|
||||
uwsgi_add_var(b, "SERVER_NAME", 11, con->server_name->ptr, len);
|
||||
|
||||
} else {
|
||||
#ifdef HAVE_IPV6
|
||||
@@ -457,11 +460,9 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
|
||||
#else
|
||||
s = inet_ntoa(srv_sock->addr.ipv4.sin_addr);
|
||||
#endif
|
||||
uwsgi_strsize = strlen(s);
|
||||
uwsgi_add_var(b, "SERVER_NAME", 11, (char *)s, strlen(s));
|
||||
}
|
||||
buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, s, uwsgi_strsize);
|
||||
|
||||
uwsgi_strsize = 11; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, "SERVER_PORT", uwsgi_strsize);
|
||||
LI_ltostr(buf,
|
||||
#ifdef HAVE_IPV6
|
||||
ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
|
||||
@@ -470,12 +471,9 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
|
||||
#endif
|
||||
);
|
||||
|
||||
uwsgi_strsize = strlen(s); buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, s, uwsgi_strsize);
|
||||
uwsgi_add_var(b, "SERVER_PORT", 11, buf, strlen(buf));
|
||||
uwsgi_add_var(b, "REQUEST_URI", 11, con->request.orig_uri->ptr, con->request.orig_uri->used-1);
|
||||
|
||||
uwsgi_strsize = 11; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, "REQUEST_URI", uwsgi_strsize);
|
||||
uwsgi_strsize = con->request.orig_uri->used; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, con->request.orig_uri->ptr, uwsgi_strsize);
|
||||
|
||||
uwsgi_strsize = 11; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, "REMOTE_PORT", uwsgi_strsize);
|
||||
LI_ltostr(buf,
|
||||
#ifdef HAVE_IPV6
|
||||
ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
|
||||
@@ -483,23 +481,75 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
|
||||
ntohs(con->dst_addr.ipv4.sin_port)
|
||||
#endif
|
||||
);
|
||||
uwsgi_add_var(b, "REMOTE_PORT", 11, buf, strlen(buf));
|
||||
|
||||
uwsgi_strsize = strlen(s); buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, s, uwsgi_strsize);
|
||||
|
||||
uwsgi_strsize = 11; buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, "REMOTE_ADDR", uwsgi_strsize);
|
||||
s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
|
||||
uwsgi_strsize = strlen(s); buffer_append_memory(b, &uwsgi_strsize, 2); buffer_append_memory(b, s, uwsgi_strsize);
|
||||
|
||||
uwsgi_add_var(b, "REMOTE_ADDR", 11, (char *)s, strlen(s));
|
||||
|
||||
if (hctx->path_info_offset > 1) {
|
||||
uwsgi_add_var(b, "SCRIPT_NAME", 11, con->uri.path->ptr, hctx->path_info_offset);
|
||||
if (strlen(con->uri.path->ptr + hctx->path_info_offset) > 0) {
|
||||
uwsgi_add_var(b, "PATH_INFO", 9, con->request.orig_uri->ptr + hctx->path_info_offset, strlen(con->request.orig_uri->ptr + hctx->path_info_offset));
|
||||
}
|
||||
else {
|
||||
uwsgi_add_var(b, "PATH_INFO", 9, "/", 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_add_var(b, "SCRIPT_NAME", 11, "", 0) ;
|
||||
uwsgi_add_var(b, "PATH_INFO", 9, con->request.orig_uri->ptr, con->request.orig_uri->used-1) ;
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < con->request.headers->used; i++) {
|
||||
data_string *ds;
|
||||
ds = (data_string *)con->request.headers->data[i];
|
||||
|
||||
if (ds->value->used && ds->key->used) {
|
||||
size_t j;
|
||||
buffer_reset(srv->tmp_buf);
|
||||
if (!strcasecmp(ds->key->ptr, "CONTENT-TYPE") || !strcasecmp(ds->key->ptr, "CONTENT-LENGTH")) {
|
||||
buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
|
||||
}
|
||||
else {
|
||||
buffer_prepare_append(srv->tmp_buf, ds->key->used + 7);
|
||||
buffer_append_memory(srv->tmp_buf, "HTTP_", 5);
|
||||
}
|
||||
for (j = 0; j < ds->key->used - 1; j++) {
|
||||
srv->tmp_buf->ptr[srv->tmp_buf->used++] = light_isalpha(ds->key->ptr[j]) ? ds->key->ptr[j] & ~32 : '_';
|
||||
}
|
||||
srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
|
||||
uwsgi_add_var(b, srv->tmp_buf->ptr, srv->tmp_buf->used-1, ds->value->ptr, ds->value->used-1);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < con->environment->used; i++) {
|
||||
data_string *ds;
|
||||
ds = (data_string *)con->environment->data[i];
|
||||
if (ds->value->used && ds->key->used) {
|
||||
size_t j;
|
||||
buffer_reset(srv->tmp_buf);
|
||||
buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
|
||||
for (j = 0; j < ds->key->used - 1; j++) {
|
||||
srv->tmp_buf->ptr[srv->tmp_buf->used++] = light_isalnum((unsigned char)ds->key->ptr[j]) ? toupper((unsigned char)ds->key->ptr[j]) : '_';
|
||||
}
|
||||
|
||||
srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
|
||||
uwsgi_add_var(b, srv->tmp_buf->ptr, srv->tmp_buf->used-1, ds->value->ptr, ds->value->used-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uh = (uwsgi_header *) b->ptr ;
|
||||
uh->modifier1 = 0 ;
|
||||
uh->modifier1 = (uint8_t) 0 ;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
uh->pktsize = uwsgi_swap16((uint16_t) b->used - 4) ;
|
||||
#else
|
||||
uh->pktsize = b->used - 4 ;
|
||||
uh->modifier2 = 0 ;
|
||||
#endif
|
||||
uh->modifier2 = (uint8_t) 0 ;
|
||||
|
||||
log_error_write(srv, __FILE__, __LINE__, "sd", "uwsgi_header ", b->used - 4);
|
||||
b->used++; /* fix size */
|
||||
|
||||
hctx->wb->bytes_in += b->used -1 ;
|
||||
@@ -908,7 +958,6 @@ static int mod_uwsgi_patch_connection(server *srv, connection *con, plugin_data
|
||||
|
||||
PATCH(extensions);
|
||||
PATCH(debug);
|
||||
PATCH(balance);
|
||||
|
||||
/* skip the first, the global context */
|
||||
for (i = 1; i < srv->config_context->used; i++) {
|
||||
@@ -926,8 +975,6 @@ static int mod_uwsgi_patch_connection(server *srv, connection *con, plugin_data
|
||||
PATCH(extensions);
|
||||
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("uwsgi.debug"))) {
|
||||
PATCH(debug);
|
||||
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("uwsgi.balance"))) {
|
||||
PATCH(balance);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1097,7 +1144,6 @@ static handler_t uwsgi_handle_fdevent(void *s, void *ctx, int revents) {
|
||||
static handler_t mod_uwsgi_check_extension(server *srv, connection *con, void *p_d) {
|
||||
plugin_data *p = p_d;
|
||||
size_t s_len;
|
||||
unsigned long last_max = ULONG_MAX;
|
||||
int max_usage = INT_MAX;
|
||||
int ndx = -1;
|
||||
size_t k;
|
||||
@@ -1143,13 +1189,7 @@ static handler_t mod_uwsgi_check_extension(server *srv, connection *con, void *p
|
||||
/* check extension in the form "/uwsgi_pattern" */
|
||||
if (*(ext->key->ptr) == '/') {
|
||||
if (strncmp(fn->ptr, ext->key->ptr, ct_len) == 0) {
|
||||
if (s_len > ct_len + 1) {
|
||||
char *pi_offset;
|
||||
|
||||
if (0 != (pi_offset = strchr(fn->ptr + ct_len + 1, '/'))) {
|
||||
path_info_offset = pi_offset - fn->ptr;
|
||||
}
|
||||
}
|
||||
path_info_offset = ct_len ;
|
||||
extension = ext;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
#include "uwsgi.h"
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__sun__) || defined(__OpenBSD__)
|
||||
#include <kvm.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/user.h>
|
||||
#endif
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
void log_request(struct wsgi_request *wsgi_req) {
|
||||
char *time_request;
|
||||
time_t microseconds, microseconds2;
|
||||
|
||||
|
||||
#ifdef UWSGI_SENDFILE
|
||||
char *msg1 = " via sendfile() ";
|
||||
char *msg2 = " ";
|
||||
char *via;
|
||||
static char *empty = "";
|
||||
|
||||
char *first_part = empty;
|
||||
struct uwsgi_app *wi;
|
||||
int app_req = -1;
|
||||
|
||||
if (wsgi_req->app_id >= 0) {
|
||||
wi = &uwsgi.wsgi_apps[wsgi_req->app_id];
|
||||
if (wi->requests > 0) {
|
||||
app_req = wi->requests;
|
||||
}
|
||||
}
|
||||
via = msg2;
|
||||
|
||||
if (wsgi_req->sendfile_fd > -1) {
|
||||
via = msg1;
|
||||
}
|
||||
#endif
|
||||
|
||||
time_request = ctime((const time_t *) &wsgi_req->start_of_request.tv_sec);
|
||||
microseconds = wsgi_req->end_of_request.tv_sec * 1000000 + wsgi_req->end_of_request.tv_usec;
|
||||
microseconds2 = wsgi_req->start_of_request.tv_sec * 1000000 + wsgi_req->start_of_request.tv_usec;
|
||||
|
||||
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1) {
|
||||
#ifndef UNBIT
|
||||
if (uwsgi.synclog) {
|
||||
snprintf(uwsgi.sync_page, uwsgi.page_size, "{address space usage: %lld bytes/%lluMB} {rss usage: %llu bytes/%lluMB} ", uwsgi.workers[uwsgi.mywid].vsz_size, uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024, uwsgi.workers[uwsgi.mywid].rss_size, uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
|
||||
first_part = uwsgi.sync_page;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "{address space usage: %lld bytes/%lluMB} {rss usage: %llu bytes/%lluMB} ", uwsgi.workers[uwsgi.mywid].vsz_size, uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024, uwsgi.workers[uwsgi.mywid].rss_size, uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
|
||||
}
|
||||
#else
|
||||
fprintf(stderr, "{address space usage: %lld bytes/%lluMB} ", uwsgi.workers[uwsgi.mywid].vsz_size, uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024);
|
||||
#endif
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %d bytes in %ld msecs%s(%.*s %d) %d headers in %d bytes\n", first_part, uwsgi.mypid, wsgi_req->app_id, app_req, uwsgi.workers[0].requests, wsgi_req->remote_addr_len, wsgi_req->remote_addr, wsgi_req->remote_user_len, wsgi_req->remote_user, wsgi_req->var_cnt, wsgi_req->size, 24, time_request, wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri, wsgi_req->response_size, (long int) (microseconds - microseconds2) / 1000, via, wsgi_req->protocol_len, wsgi_req->protocol, wsgi_req->status, wsgi_req->header_cnt, wsgi_req->headers_size);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void get_memusage() {
|
||||
|
||||
#ifdef UNBIT
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = syscall(356);
|
||||
#elif defined(__linux__)
|
||||
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 %*s %llu %lld", &uwsgi.workers[uwsgi.mywid].vsz_size, &uwsgi.workers[uwsgi.mywid].rss_size);
|
||||
if (i != 2) {
|
||||
fprintf(stderr, "warning: invalid record in /proc/self/stat\n");
|
||||
}
|
||||
fclose(procfile);
|
||||
}
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = uwsgi.workers[uwsgi.mywid].rss_size * uwsgi.page_size;
|
||||
#elif defined( __APPLE__)
|
||||
/* darwin documentation says that the value are in pages, but they are bytes !!! */
|
||||
struct task_basic_info t_info;
|
||||
mach_msg_type_number_t t_size = sizeof(struct task_basic_info);
|
||||
|
||||
if (task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t) & t_info, &t_size) == KERN_SUCCESS) {
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = t_info.resident_size;
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = t_info.virtual_size;
|
||||
}
|
||||
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__sun__) || defined(__OpenBSD__)
|
||||
kvm_t *kv;
|
||||
|
||||
kv = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);
|
||||
if (kv) {
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
struct kinfo_proc *kproc;
|
||||
int cnt;
|
||||
kproc = kvm_getprocs(kv, KERN_PROC_PID, uwsgi.mypid, &cnt);
|
||||
if (kproc && cnt > 0) {
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = kproc->ki_size;
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = kproc->ki_rssize * uwsgi.page_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
kvm_close(kv);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 5.8 KiB |
@@ -0,0 +1,7 @@
|
||||
import uwsgi
|
||||
import struct
|
||||
import sys
|
||||
|
||||
|
||||
print uwsgi.send_uwsgi_message(sys.argv[1], int(sys.argv[2]), 10, int(sys.argv[3]), struct.pack("i", int(sys.argv[4])))
|
||||
|
||||
+976
-921
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,22 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
/* gcc `python-config --cflags` `python ../../uwsgiconfig.py --cflags` -o example_plugin.so -fPIC -shared example_plugin.c */
|
||||
|
||||
int uwsgi_init(struct uwsgi_server *uwsgi, char *args){
|
||||
fprintf(stderr,"i am the example plugin initialization function with arg: %s\n", args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
|
||||
char *http = "HTTP/1.1 200 Ok\r\nContent-type: text/html\r\n\r\n<h1>Hello World</h1>" ;
|
||||
wsgi_req->response_size += write(uwsgi->poll.fd, http, strlen(http));
|
||||
|
||||
fprintf(stderr,"UWSGI POLL: %p\n", &uwsgi->poll);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_after_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
|
||||
fprintf(stderr,"i am the example plugin after request function\n");
|
||||
}
|
||||
@@ -0,0 +1,269 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/* gcc -fPIC -shared -o lua_plugin.so `python2.5-config --cflags` -I /usr/include/lua5.1 -llua5.1 lua_plugin.c */
|
||||
|
||||
#include <lua.h>
|
||||
#include <lualib.h>
|
||||
|
||||
|
||||
static struct uwsgi_lua {
|
||||
struct lua_State *L ;
|
||||
struct uwsgi_server *uwsgi;
|
||||
} ulua;
|
||||
|
||||
static void *uwsgi_lua_alloc(void *ud, void *ptr, size_t osize, size_t nsize) {
|
||||
if(nsize == 0) {
|
||||
free(ptr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return realloc(ptr, nsize);
|
||||
}
|
||||
|
||||
static const char *uwsgi_read_lua(lua_State *L, void *data, size_t *size) {
|
||||
|
||||
int fd = *(int *)data;
|
||||
static char buf[4096];
|
||||
|
||||
*size = read(fd, buf, 4096);
|
||||
|
||||
if (size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int uwsgi_lua_input(lua_State *L) {
|
||||
|
||||
int n = lua_gettop(L);
|
||||
|
||||
static char *buf = "" ;
|
||||
|
||||
fprintf(stderr,"richiesti %d bytes\n", n);
|
||||
|
||||
//sum = read(ulua.uwsgi->poll.fd,);
|
||||
|
||||
lua_pushlstring(L, buf, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int uwsgi_init(struct uwsgi_server *uwsgi, char *args){
|
||||
|
||||
int fd, i;
|
||||
|
||||
fprintf(stderr,"Initializing Lua environment...\n");
|
||||
|
||||
|
||||
|
||||
|
||||
ulua.L = lua_newstate(uwsgi_lua_alloc, NULL);
|
||||
|
||||
luaL_openlibs(ulua.L);
|
||||
|
||||
|
||||
fd = open(args, O_RDONLY) ;
|
||||
if (fd < 0) {
|
||||
perror("open()");
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
|
||||
i = lua_load(ulua.L, uwsgi_read_lua, &fd, "uwsgi");
|
||||
|
||||
fprintf(stderr,"lua_load: %d\n" ,i);
|
||||
|
||||
// use a pcall
|
||||
lua_call(ulua.L, 0, 1);
|
||||
|
||||
fprintf(stderr,"%s\n", lua_typename(ulua.L, lua_type(ulua.L, -1)));
|
||||
|
||||
// ok the lua engine is ready
|
||||
return 0 ;
|
||||
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
|
||||
|
||||
char *ptrbuf;
|
||||
char *buffer = uwsgi->buffer ;
|
||||
char *bufferend;
|
||||
uint16_t strsize = 0;
|
||||
int i;
|
||||
const char *http ;
|
||||
size_t slen ;
|
||||
|
||||
/* Standard WSAPI request */
|
||||
if (!wsgi_req->size) {
|
||||
fprintf (stderr, "Invalid WSAPI request. skip.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ptrbuf = buffer;
|
||||
bufferend = ptrbuf + wsgi_req->size;
|
||||
|
||||
/* set an HTTP 500 status as default */
|
||||
wsgi_req->status = 500;
|
||||
|
||||
while (ptrbuf < bufferend) {
|
||||
if (ptrbuf + 2 < bufferend) {
|
||||
memcpy (&strsize, ptrbuf, 2);
|
||||
#ifdef __BIG_ENDIAN__
|
||||
strsize = uwsgi_swap16 (strsize);
|
||||
#endif
|
||||
ptrbuf += 2;
|
||||
if (ptrbuf + strsize < bufferend) {
|
||||
// var key
|
||||
uwsgi->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
|
||||
uwsgi->hvec[wsgi_req->var_cnt].iov_len = strsize;
|
||||
ptrbuf += strsize;
|
||||
if (ptrbuf + 2 < bufferend) {
|
||||
memcpy (&strsize, ptrbuf, 2);
|
||||
#ifdef __BIG_ENDIAN__
|
||||
strsize = uwsgi_swap16 (strsize);
|
||||
#endif
|
||||
ptrbuf += 2;
|
||||
if (ptrbuf + strsize <= bufferend) {
|
||||
if (wsgi_req->var_cnt < uwsgi->vec_size - (4 + 1)) {
|
||||
wsgi_req->var_cnt++;
|
||||
}
|
||||
else {
|
||||
fprintf (stderr, "max vec size reached. skip this header.\n");
|
||||
break;
|
||||
}
|
||||
// var value
|
||||
uwsgi->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
|
||||
uwsgi->hvec[wsgi_req->var_cnt].iov_len = strsize;
|
||||
if (wsgi_req->var_cnt < uwsgi->vec_size - (4 + 1)) {
|
||||
wsgi_req->var_cnt++;
|
||||
}
|
||||
else {
|
||||
fprintf (stderr, "max vec size reached. skip this header.\n");
|
||||
break;
|
||||
}
|
||||
ptrbuf += strsize;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// put function in the stack
|
||||
lua_pushvalue(ulua.L, -1);
|
||||
lua_getfield(ulua.L, -1, "run");
|
||||
|
||||
// put cgi vars in the stack
|
||||
lua_newtable(ulua.L);
|
||||
lua_pushstring(ulua.L, "");
|
||||
lua_setfield(ulua.L, -2, "CONTENT_TYPE");
|
||||
for(i=0;i<wsgi_req->var_cnt;i++) {
|
||||
lua_pushlstring(ulua.L, (char *)uwsgi->hvec[i+1].iov_base, uwsgi->hvec[i+1].iov_len);
|
||||
// transform it in a valid c string TODO this is ugly
|
||||
ptrbuf = uwsgi->hvec[i].iov_base+uwsgi->hvec[i].iov_len ;
|
||||
*ptrbuf = 0 ;
|
||||
lua_setfield(ulua.L, -2, (char *)uwsgi->hvec[i].iov_base);
|
||||
//fprintf(stderr,"%.*s=%.*s\n", uwsgi->hvec[i].iov_len, uwsgi->hvec[i].iov_base, uwsgi->hvec[i+1].iov_len, uwsgi->hvec[i+1].iov_base);
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
// put "input" table
|
||||
lua_newtable(ulua.L);
|
||||
lua_pushcfunction(ulua.L, uwsgi_lua_input);
|
||||
lua_setfield(ulua.L, -2, "read");
|
||||
lua_setfield(ulua.L, -2, "input");
|
||||
|
||||
|
||||
// call function
|
||||
i = lua_pcall(ulua.L, 1, 3, 0);
|
||||
if (i != 0) {
|
||||
fprintf(stderr,"%s\n", lua_tostring(ulua.L, -1));
|
||||
lua_pop(ulua.L, 1);
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
fprintf(stderr,"%d %s %s %s\n",i,lua_typename(ulua.L, lua_type(ulua.L, -3)), lua_typename(ulua.L, lua_type(ulua.L, -2)) , lua_typename(ulua.L, lua_type(ulua.L, -1)));
|
||||
|
||||
// send status
|
||||
if (lua_type(ulua.L, -3) == LUA_TSTRING || lua_type(ulua.L, -3) == LUA_TNUMBER) {
|
||||
http = lua_tolstring(ulua.L, -3, &slen);
|
||||
if (write(uwsgi->poll.fd, "HTTP/1.1 ", 9) != 9) {
|
||||
perror("write()");
|
||||
return -1 ;
|
||||
}
|
||||
if (write(uwsgi->poll.fd, http, slen) != slen) {
|
||||
perror("write()");
|
||||
return -1 ;
|
||||
}
|
||||
if (write(uwsgi->poll.fd, "\r\n", 2) != 2) {
|
||||
perror("write()");
|
||||
return -1 ;
|
||||
}
|
||||
}
|
||||
|
||||
// send headers
|
||||
|
||||
lua_pushnil(ulua.L);
|
||||
while(lua_next(ulua.L, -3) != 0) {
|
||||
http = lua_tolstring(ulua.L, -2, &slen);
|
||||
if (write(uwsgi->poll.fd, http, slen) != slen) {
|
||||
perror("write()");
|
||||
return -1 ;
|
||||
}
|
||||
if (write(uwsgi->poll.fd, ": ", 2) != 2) {
|
||||
perror("write()");
|
||||
return -1 ;
|
||||
}
|
||||
http = lua_tolstring(ulua.L, -1, &slen);
|
||||
if (write(uwsgi->poll.fd, http, slen) != slen) {
|
||||
perror("write()");
|
||||
return -1 ;
|
||||
}
|
||||
if (write(uwsgi->poll.fd, "\r\n", 2) != 2) {
|
||||
perror("write()");
|
||||
return -1 ;
|
||||
}
|
||||
lua_pop(ulua.L, 1);
|
||||
}
|
||||
|
||||
if (write(uwsgi->poll.fd, "\r\n", 2) != 2) {
|
||||
perror("write()");
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
// send body with coroutine
|
||||
lua_pushvalue(ulua.L, -1);
|
||||
|
||||
while ( (i = lua_pcall(ulua.L, 0, 1, 0)) == 0) {
|
||||
if (lua_type(ulua.L, -1) == LUA_TSTRING) {
|
||||
http = lua_tolstring(ulua.L, -1, &slen);
|
||||
if (write(uwsgi->poll.fd, http, slen) != slen) {
|
||||
perror("write()");
|
||||
return -1 ;
|
||||
}
|
||||
//fprintf(stderr,"%.*s\n", slen, http);
|
||||
}
|
||||
lua_pop(ulua.L, 1);
|
||||
lua_pushvalue(ulua.L, -1);
|
||||
}
|
||||
|
||||
lua_pop(ulua.L, 4);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_after_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
|
||||
return;
|
||||
}
|
||||
+345
-146
@@ -2,208 +2,407 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int uwsgi_enqueue_message(char *host, int port, uint8_t modifier1, uint8_t modifier2, char *message, int size, int timeout) {
|
||||
#ifdef UWSGI_UDP
|
||||
ssize_t send_udp_message(uint8_t modifier1, char *host, char *message, uint16_t message_size) {
|
||||
|
||||
int uwsgi_fd;
|
||||
struct sockaddr_in uws_addr;
|
||||
int cnt ;
|
||||
struct uwsgi_header uh;
|
||||
int fd ;
|
||||
struct sockaddr_in udp_addr;
|
||||
char *udp_port ;
|
||||
ssize_t ret;
|
||||
char udpbuff[1024];
|
||||
|
||||
if (size > 0xFFFF) {
|
||||
fprintf(stderr,"invalid object (marshalled) size\n");
|
||||
if (message_size + 4 > 1024)
|
||||
return -1;
|
||||
|
||||
udp_port = strchr(host, ':');
|
||||
if (udp_port == NULL) {
|
||||
return -1 ;
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (uwsgi_fd < 0) {
|
||||
udp_port[0] = 0 ;
|
||||
|
||||
fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (fd < 0) {
|
||||
perror("socket()");
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
memset(&udp_addr, 0, sizeof(struct sockaddr_in));
|
||||
udp_addr.sin_family = AF_INET;
|
||||
udp_addr.sin_port = htons(atoi(udp_port));
|
||||
udp_addr.sin_addr.s_addr = inet_addr(host);
|
||||
|
||||
udpbuff[0] = modifier1 ;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
message_size = uwsgi_swap16(message_size);
|
||||
#endif
|
||||
|
||||
memcpy(udpbuff+1, &message_size, 2);
|
||||
|
||||
udpbuff[3] = 0 ;
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
message_size = uwsgi_swap16(message_size);
|
||||
#endif
|
||||
|
||||
memcpy(udpbuff+4, message, message_size);
|
||||
|
||||
ret = sendto(fd, udpbuff, message_size+4, 0, (struct sockaddr *) &udp_addr, sizeof(udp_addr));
|
||||
if (ret < 0) {
|
||||
perror("sendto()");
|
||||
}
|
||||
close(fd);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
int uwsgi_enqueue_message(char *host, int port, uint8_t modifier1, uint8_t modifier2, char *message, int size, int timeout) {
|
||||
|
||||
struct pollfd uwsgi_poll;
|
||||
struct sockaddr_in uws_addr;
|
||||
int cnt;
|
||||
struct uwsgi_header uh;
|
||||
|
||||
if (!timeout)
|
||||
timeout = 1;
|
||||
|
||||
if (size > 0xFFFF) {
|
||||
fprintf(stderr, "invalid object (marshalled) size\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_poll.fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (uwsgi_poll.fd < 0) {
|
||||
perror("socket()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&uws_addr, 0, sizeof(struct sockaddr_in));
|
||||
uws_addr.sin_family = AF_INET;
|
||||
uws_addr.sin_port = htons(port);
|
||||
uws_addr.sin_addr.s_addr = inet_addr(host);
|
||||
uws_addr.sin_family = AF_INET;
|
||||
uws_addr.sin_port = htons(port);
|
||||
uws_addr.sin_addr.s_addr = inet_addr(host);
|
||||
|
||||
uwsgi_poll.events = POLLIN;
|
||||
|
||||
if (connect(uwsgi_fd, (const struct sockaddr *) &uws_addr, sizeof(struct sockaddr_in))) {
|
||||
perror("connect()");
|
||||
close(uwsgi_fd);
|
||||
return -1 ;
|
||||
}
|
||||
if (timed_connect(&uwsgi_poll, (const struct sockaddr *) &uws_addr, sizeof(struct sockaddr_in), timeout)) {
|
||||
perror("connect()");
|
||||
close(uwsgi_poll.fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uh.modifier1 = modifier1;
|
||||
uh.pktsize = (uint16_t) size ;
|
||||
uh.modifier2 = modifier2;
|
||||
uh.modifier1 = modifier1;
|
||||
uh.pktsize = (uint16_t) size;
|
||||
uh.modifier2 = modifier2;
|
||||
|
||||
cnt = write(uwsgi_fd, &uh, 4) ;
|
||||
if (cnt != 4) {
|
||||
perror("write()");
|
||||
close(uwsgi_fd);
|
||||
return -1;
|
||||
}
|
||||
cnt = write(uwsgi_poll.fd, &uh, 4);
|
||||
if (cnt != 4) {
|
||||
perror("write()");
|
||||
close(uwsgi_poll.fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
cnt = write(uwsgi_fd, message, size) ;
|
||||
if (cnt != size) {
|
||||
perror("write()");
|
||||
close(uwsgi_fd);
|
||||
return -1;
|
||||
}
|
||||
cnt = write(uwsgi_poll.fd, message, size);
|
||||
if (cnt != size) {
|
||||
perror("write()");
|
||||
close(uwsgi_poll.fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return uwsgi_fd;
|
||||
return uwsgi_poll.fd;
|
||||
}
|
||||
|
||||
PyObject *uwsgi_send_message(char *host, int port, uint8_t modifier1, uint8_t modifier2, char *message, int size, int timeout) {
|
||||
PyObject *uwsgi_send_message(const char *host, int port, uint8_t modifier1, uint8_t modifier2, char *message, int size, int timeout) {
|
||||
|
||||
struct pollfd uwsgi_mpoll ;
|
||||
struct pollfd uwsgi_mpoll;
|
||||
struct sockaddr_in uws_addr;
|
||||
int cnt ;
|
||||
int cnt;
|
||||
struct uwsgi_header uh;
|
||||
char buffer[0xFFFF];
|
||||
|
||||
|
||||
|
||||
if (!timeout)
|
||||
timeout = 1;
|
||||
|
||||
if (size > 0xFFFF) {
|
||||
fprintf(stderr,"invalid object (marshalled) size\n");
|
||||
fprintf(stderr, "invalid object (marshalled) size\n");
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
uwsgi_mpoll.events = POLLIN ;
|
||||
uwsgi_mpoll.events = POLLIN;
|
||||
|
||||
uwsgi_mpoll.fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (uwsgi_mpoll.fd < 0) {
|
||||
perror("socket()");
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
memset(&uws_addr, 0, sizeof(struct sockaddr_in));
|
||||
uws_addr.sin_family = AF_INET;
|
||||
uws_addr.sin_port = htons(port);
|
||||
uws_addr.sin_port = htons(port);
|
||||
uws_addr.sin_addr.s_addr = inet_addr(host);
|
||||
|
||||
UWSGI_SET_BLOCKING;
|
||||
|
||||
if (connect(uwsgi_mpoll.fd, (const struct sockaddr *) &uws_addr, sizeof(struct sockaddr_in))) {
|
||||
if (timed_connect(&uwsgi_mpoll, (const struct sockaddr *) &uws_addr, sizeof(struct sockaddr_in), timeout)) {
|
||||
perror("connect()");
|
||||
close(uwsgi_mpoll.fd);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
uh.modifier1 = modifier1;
|
||||
uh.pktsize = (uint16_t) size ;
|
||||
uh.modifier2 = modifier2;
|
||||
|
||||
cnt = write(uwsgi_mpoll.fd, &uh, 4) ;
|
||||
if (cnt != 4) {
|
||||
perror("write()");
|
||||
close(uwsgi_mpoll.fd);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
cnt = write(uwsgi_mpoll.fd, message, size) ;
|
||||
if (cnt != size) {
|
||||
perror("write()");
|
||||
close(uwsgi_mpoll.fd);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
if (!uwsgi_parse_response(&uwsgi_mpoll, timeout, &uh, buffer)) {
|
||||
|
||||
uh.modifier1 = modifier1;
|
||||
uh.pktsize = (uint16_t) size;
|
||||
uh.modifier2 = modifier2;
|
||||
|
||||
cnt = write(uwsgi_mpoll.fd, &uh, 4);
|
||||
if (cnt != 4) {
|
||||
perror("write()");
|
||||
close(uwsgi_mpoll.fd);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
cnt = write(uwsgi_mpoll.fd, message, size);
|
||||
if (cnt != size) {
|
||||
perror("write()");
|
||||
close(uwsgi_mpoll.fd);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
if (!uwsgi_parse_response(&uwsgi_mpoll, timeout, &uh, buffer)) {
|
||||
UWSGI_UNSET_BLOCKING;
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
UWSGI_UNSET_BLOCKING;
|
||||
|
||||
close(uwsgi_mpoll.fd);
|
||||
|
||||
return PyMarshal_ReadObjectFromString(buffer, uh.pktsize);
|
||||
|
||||
if (uh.modifier1 == UWSGI_MODIFIER_RESPONSE) {
|
||||
if (!uh.modifier2) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
else {
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
}
|
||||
}
|
||||
|
||||
return PyMarshal_ReadObjectFromString(buffer, uh.pktsize);
|
||||
}
|
||||
|
||||
int uwsgi_parse_response(struct pollfd * upoll, int timeout, struct uwsgi_header *uh, char *buffer) {
|
||||
int uwsgi_parse_response(struct pollfd *upoll, int timeout, struct uwsgi_header *uh, char *buffer) {
|
||||
int rlen, i;
|
||||
|
||||
if (!timeout)
|
||||
timeout = 1;
|
||||
/* first 4 byte header */
|
||||
rlen = poll(upoll, 1, timeout*1000) ;
|
||||
if (rlen < 0) {
|
||||
perror("poll()");
|
||||
exit(1);
|
||||
}
|
||||
else if (rlen == 0) {
|
||||
fprintf(stderr, "timeout. skip request\n");
|
||||
close(upoll->fd);
|
||||
return 0 ;
|
||||
}
|
||||
rlen = read(upoll->fd, uh, 4) ;
|
||||
if (rlen > 0 && rlen < 4) {
|
||||
i = rlen ;
|
||||
while(i < 4) {
|
||||
rlen = poll(upoll, 1, timeout*1000) ;
|
||||
if (rlen < 0) {
|
||||
perror("poll()");
|
||||
exit(1);
|
||||
}
|
||||
else if (rlen == 0) {
|
||||
fprintf(stderr, "timeout waiting for header. skip request.\n");
|
||||
close(upoll->fd);
|
||||
break ;
|
||||
}
|
||||
rlen = read(upoll->fd, (char *)(uh)+i, 4-i);
|
||||
if (rlen <= 0) {
|
||||
fprintf(stderr, "broken header. skip request.\n");
|
||||
close(upoll->fd);
|
||||
break ;
|
||||
}
|
||||
i += rlen;
|
||||
}
|
||||
if (i < 4) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (rlen <= 0){
|
||||
fprintf(stderr,"invalid request header size: %d...skip\n", rlen);
|
||||
close(upoll->fd);
|
||||
return 0;
|
||||
}
|
||||
/* big endian ? */
|
||||
#ifdef __BIG_ENDIAN__
|
||||
uh->pktsize = uwsgi_swap16(uh->pktsize);
|
||||
#endif
|
||||
|
||||
/* check for max buffer size */
|
||||
if (uh->pktsize > uwsgi.buffer_size) {
|
||||
fprintf(stderr,"invalid request block size: %d...skip\n", uh->pktsize);
|
||||
close(upoll->fd);
|
||||
rlen = poll(upoll, 1, timeout * 1000);
|
||||
if (rlen < 0) {
|
||||
perror("poll()");
|
||||
exit(1);
|
||||
}
|
||||
else if (rlen == 0) {
|
||||
fprintf(stderr, "timeout. skip request\n");
|
||||
close(upoll->fd);
|
||||
return 0;
|
||||
}
|
||||
rlen = read(upoll->fd, uh, 4);
|
||||
if (rlen > 0 && rlen < 4) {
|
||||
i = rlen;
|
||||
while (i < 4) {
|
||||
rlen = poll(upoll, 1, timeout * 1000);
|
||||
if (rlen < 0) {
|
||||
perror("poll()");
|
||||
exit(1);
|
||||
}
|
||||
else if (rlen == 0) {
|
||||
fprintf(stderr, "timeout waiting for header. skip request.\n");
|
||||
close(upoll->fd);
|
||||
break;
|
||||
}
|
||||
rlen = read(upoll->fd, (char *) (uh) + i, 4 - i);
|
||||
if (rlen <= 0) {
|
||||
fprintf(stderr, "broken header. skip request.\n");
|
||||
close(upoll->fd);
|
||||
break;
|
||||
}
|
||||
i += rlen;
|
||||
}
|
||||
if (i < 4) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (rlen <= 0) {
|
||||
fprintf(stderr, "invalid request header size: %d...skip\n", rlen);
|
||||
close(upoll->fd);
|
||||
return 0;
|
||||
}
|
||||
/* big endian ? */
|
||||
#ifdef __BIG_ENDIAN__
|
||||
uh->pktsize = uwsgi_swap16(uh->pktsize);
|
||||
#endif
|
||||
|
||||
//fprintf(stderr,"ready for reading %d bytes\n", wsgi_req.size);
|
||||
/* check for max buffer size */
|
||||
if (uh->pktsize > uwsgi.buffer_size) {
|
||||
fprintf(stderr, "invalid request block size: %d...skip\n", uh->pktsize);
|
||||
close(upoll->fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
i = 0 ;
|
||||
while(i < uh->pktsize) {
|
||||
rlen = poll(upoll, 1, timeout*1000) ;
|
||||
if (rlen < 0) {
|
||||
perror("poll()");
|
||||
exit(1);
|
||||
}
|
||||
else if (rlen == 0) {
|
||||
fprintf(stderr, "timeout. skip request. (expecting %d bytes, got %d)\n", uh->pktsize, i);
|
||||
close(upoll->fd);
|
||||
break ;
|
||||
}
|
||||
rlen = read(upoll->fd, buffer+i, uh->pktsize-i);
|
||||
if (rlen <= 0) {
|
||||
fprintf(stderr, "broken vars. skip request.\n");
|
||||
close(upoll->fd);
|
||||
break ;
|
||||
}
|
||||
i += rlen ;
|
||||
}
|
||||
//fprintf(stderr,"ready for reading %d bytes\n", wsgi_req.size);
|
||||
|
||||
i = 0;
|
||||
while (i < uh->pktsize) {
|
||||
rlen = poll(upoll, 1, timeout * 1000);
|
||||
if (rlen < 0) {
|
||||
perror("poll()");
|
||||
exit(1);
|
||||
}
|
||||
else if (rlen == 0) {
|
||||
fprintf(stderr, "timeout. skip request. (expecting %d bytes, got %d)\n", uh->pktsize, i);
|
||||
close(upoll->fd);
|
||||
break;
|
||||
}
|
||||
rlen = read(upoll->fd, buffer + i, uh->pktsize - i);
|
||||
if (rlen <= 0) {
|
||||
fprintf(stderr, "broken vars. skip request.\n");
|
||||
close(upoll->fd);
|
||||
break;
|
||||
}
|
||||
i += rlen;
|
||||
}
|
||||
|
||||
|
||||
if (i < uh->pktsize) {
|
||||
return 0;
|
||||
}
|
||||
if (i < uh->pktsize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int uwsgi_parse_vars(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
|
||||
|
||||
char *buffer = uwsgi->buffer;
|
||||
|
||||
char *ptrbuf, *bufferend;
|
||||
|
||||
uint16_t strsize = 0;
|
||||
|
||||
ptrbuf = buffer;
|
||||
bufferend = ptrbuf + wsgi_req->size;
|
||||
|
||||
/* set an HTTP 500 status as default */
|
||||
wsgi_req->status = 500;
|
||||
|
||||
while (ptrbuf < bufferend) {
|
||||
if (ptrbuf + 2 < bufferend) {
|
||||
memcpy(&strsize, ptrbuf, 2);
|
||||
#ifdef __BIG_ENDIAN__
|
||||
strsize = uwsgi_swap16(strsize);
|
||||
#endif
|
||||
|
||||
/* key cannot be null */
|
||||
if (!strsize) {
|
||||
fprintf(stderr, "uwsgi key cannot be null. skip this request.\n");
|
||||
return -1;
|
||||
}
|
||||
ptrbuf += 2;
|
||||
if (ptrbuf + strsize < bufferend) {
|
||||
// var key
|
||||
uwsgi->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
|
||||
uwsgi->hvec[wsgi_req->var_cnt].iov_len = strsize;
|
||||
ptrbuf += strsize;
|
||||
if (ptrbuf + 2 < bufferend) {
|
||||
memcpy(&strsize, ptrbuf, 2);
|
||||
#ifdef __BIG_ENDIAN__
|
||||
strsize = uwsgi_swap16(strsize);
|
||||
#endif
|
||||
ptrbuf += 2;
|
||||
if (ptrbuf + strsize <= bufferend) {
|
||||
if (wsgi_req->var_cnt < uwsgi->vec_size - (4 + 1)) {
|
||||
wsgi_req->var_cnt++;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "max vec size reached. skip this header.\n");
|
||||
return -1;
|
||||
}
|
||||
// var value
|
||||
uwsgi->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
|
||||
uwsgi->hvec[wsgi_req->var_cnt].iov_len = strsize;
|
||||
if (wsgi_req->var_cnt < uwsgi->vec_size - (4 + 1)) {
|
||||
wsgi_req->var_cnt++;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "max vec size reached. skip this header.\n");
|
||||
return -1;
|
||||
}
|
||||
ptrbuf += strsize;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_ping_node(int node, struct wsgi_request *wsgi_req) {
|
||||
|
||||
|
||||
struct pollfd uwsgi_poll;
|
||||
|
||||
struct uwsgi_cluster_node *ucn = &uwsgi.shared->nodes[node];
|
||||
|
||||
if (ucn->name[0] == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ucn->status == UWSGI_NODE_OK) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uwsgi_poll.fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (uwsgi_poll.fd < 0) {
|
||||
perror("socket()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (timed_connect(&uwsgi_poll, (const struct sockaddr *) &ucn->ucn_addr, sizeof(struct sockaddr_in), uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
close(uwsgi_poll.fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wsgi_req->modifier = UWSGI_MODIFIER_PING;
|
||||
wsgi_req->size = 0;
|
||||
wsgi_req->modifier_arg = 0;
|
||||
if (write(uwsgi_poll.fd, wsgi_req, 4) != 4) {
|
||||
perror("write()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_poll.events = POLLIN;
|
||||
if (!uwsgi_parse_response(&uwsgi_poll, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], (struct uwsgi_header *) wsgi_req, uwsgi.buffer)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,490 @@
|
||||
#ifdef UWSGI_PROXY
|
||||
|
||||
/*
|
||||
|
||||
uWSGI proxy
|
||||
|
||||
it needs one of this tecnology to work:
|
||||
|
||||
- epoll (linux 2.6)
|
||||
- kqueue (various BSD and Darwin)
|
||||
- /dev/poll (Solaris)
|
||||
|
||||
*/
|
||||
|
||||
#include "uwsgi.h"
|
||||
|
||||
#ifdef __linux__
|
||||
#include <sys/epoll.h>
|
||||
#define UWSGI_PROXY_USE_EPOLL 1
|
||||
#define EV_FD eevents[i].data.fd
|
||||
#define EV_EV eevents[i].events
|
||||
#define EV_IN EPOLLIN
|
||||
#define EV_OUT EPOLLOUT
|
||||
#define NEV_FD ee.data.fd
|
||||
#define NEV_EV ee.events
|
||||
#define NEV_ADD epoll_ctl(epfd, EPOLL_CTL_ADD, NEV_FD, &ee)
|
||||
#define NEV_MOD epoll_ctl(epfd, EPOLL_CTL_MOD, NEV_FD, &ee)
|
||||
#define EV_NAME "epoll_ctl()"
|
||||
#define EV_IS_IN EV_EV & EV_IN
|
||||
#define EV_IS_OUT EV_EV & EV_OUT
|
||||
#elif defined(__sun__)
|
||||
|
||||
#else
|
||||
#include <sys/event.h>
|
||||
#define UWSGI_PROXY_USE_KQUEUE 1
|
||||
#define EV_FD krevents[i].ident
|
||||
#define EV_EV krevents[i].filter
|
||||
#define EV_IN EVFILT_READ
|
||||
#define EV_OUT EVFILT_WRITE
|
||||
#define NEV_FD kev.ident
|
||||
#define NEV_EV kev.filter
|
||||
#define NEV_ADD kevent(kq, &kev, 1, NULL, 0, NULL) < 0
|
||||
#define NEV_MOD kevent(kq, &kev, 1, NULL, 0, NULL) < 0
|
||||
#define EV_NAME "kevent()"
|
||||
#define EV_IS_IN EV_EV == EV_IN
|
||||
#define EV_IS_OUT EV_EV == EV_OUT
|
||||
#endif
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
|
||||
#define UWSGI_PROXY_CONNECTING 1
|
||||
#define UWSGI_PROXY_WAITING 2
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_proxy_connection {
|
||||
|
||||
int dest_fd;
|
||||
int status;
|
||||
int retry;
|
||||
int node;
|
||||
};
|
||||
|
||||
static void end_proxy(void) {
|
||||
exit(UWSGI_END_CODE);
|
||||
}
|
||||
|
||||
|
||||
static void reload_proxy(void) {
|
||||
exit(UWSGI_RELOAD_CODE);
|
||||
}
|
||||
|
||||
static void uwsgi_proxy_close(struct uwsgi_proxy_connection *upcs, int fd) {
|
||||
|
||||
|
||||
if (upcs[fd].dest_fd >= 0) {
|
||||
close(upcs[fd].dest_fd);
|
||||
upcs[upcs[fd].dest_fd].dest_fd = -1;
|
||||
upcs[upcs[fd].dest_fd].status = 0;
|
||||
upcs[upcs[fd].dest_fd].retry = 0;
|
||||
if (upcs[upcs[fd].dest_fd].node > -1) {
|
||||
if (uwsgi.shared->nodes[upcs[upcs[fd].dest_fd].node].connections > 0)
|
||||
uwsgi.shared->nodes[upcs[upcs[fd].dest_fd].node].connections--;
|
||||
}
|
||||
}
|
||||
|
||||
if (fd >= 0) {
|
||||
close(fd);
|
||||
upcs[fd].dest_fd = -1;
|
||||
upcs[fd].status = 0;
|
||||
upcs[fd].retry = 0;
|
||||
if (upcs[fd].node > -1) {
|
||||
if (uwsgi.shared->nodes[upcs[fd].node].connections > 0)
|
||||
uwsgi.shared->nodes[upcs[fd].node].connections--;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int uwsgi_proxy_find_next_node(int current_node) {
|
||||
|
||||
int i;
|
||||
|
||||
current_node++;
|
||||
if (current_node >= MAX_CLUSTER_NODES) {
|
||||
current_node = 0;
|
||||
}
|
||||
|
||||
// is it a good node ?
|
||||
if (uwsgi.shared->nodes[current_node].name[0] != 0 && uwsgi.shared->nodes[current_node].status == UWSGI_NODE_OK) {
|
||||
if (uwsgi.shared->nodes[current_node].connections < uwsgi.shared->nodes[current_node].workers)
|
||||
return current_node;
|
||||
}
|
||||
|
||||
// try to find a better one
|
||||
|
||||
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
|
||||
if (uwsgi.shared->nodes[i].name[0] != 0 && uwsgi.shared->nodes[i].status == UWSGI_NODE_OK) {
|
||||
if (uwsgi.shared->nodes[i].connections < uwsgi.shared->nodes[i].workers)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
// ok, it is a very loaded system, fallback to round robin
|
||||
if (uwsgi.shared->nodes[current_node].name[0] != 0 && uwsgi.shared->nodes[current_node].status == UWSGI_NODE_OK) {
|
||||
return current_node;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
|
||||
if (uwsgi.shared->nodes[i].name[0] != 0 && uwsgi.shared->nodes[i].status == UWSGI_NODE_OK) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_proxy(int proxyfd) {
|
||||
|
||||
#ifdef __linux__
|
||||
int epfd;
|
||||
struct epoll_event ee;
|
||||
struct epoll_event *eevents;
|
||||
#else
|
||||
int kq;
|
||||
struct kevent *krevents;
|
||||
struct kevent kev;
|
||||
#endif
|
||||
|
||||
int max_events = 64;
|
||||
int nevents, i;
|
||||
const int nonblocking = 1;
|
||||
const int blocking = 0;
|
||||
|
||||
char buffer[4096];
|
||||
ssize_t rlen;
|
||||
ssize_t wlen;
|
||||
int max_connections = sysconf(_SC_OPEN_MAX);
|
||||
|
||||
int soopt;
|
||||
socklen_t solen = sizeof(int);
|
||||
|
||||
int rc;
|
||||
|
||||
struct uwsgi_proxy_connection *upcs;
|
||||
|
||||
struct sockaddr_in upc_addr;
|
||||
socklen_t upc_len = sizeof(struct sockaddr_in);
|
||||
|
||||
int next_node = -1;
|
||||
|
||||
fprintf(stderr, "spawned uWSGI proxy (pid: %d)\n", getpid());
|
||||
|
||||
fprintf(stderr, "allocating space for %d concurrent proxy connections\n", max_connections);
|
||||
|
||||
// allocate memory for connections
|
||||
upcs = malloc(sizeof(struct uwsgi_proxy_connection) * max_connections);
|
||||
if (!upcs) {
|
||||
perror("malloc()");
|
||||
exit(1);
|
||||
}
|
||||
memset(upcs, 0, sizeof(struct uwsgi_proxy_connection) * max_connections);
|
||||
|
||||
#ifdef __linux__
|
||||
//init epoll
|
||||
epfd = epoll_create(256);
|
||||
|
||||
if (epfd < 0) {
|
||||
perror("epoll_create()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// allocate memory for events
|
||||
eevents = malloc(sizeof(struct epoll_event) * max_events);
|
||||
if (!eevents) {
|
||||
perror("malloc()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// now add the proxyfd to the epoll list
|
||||
|
||||
ee.events = EPOLLIN;
|
||||
ee.data.fd = proxyfd;
|
||||
|
||||
if (epoll_ctl(epfd, EPOLL_CTL_ADD, proxyfd, &ee)) {
|
||||
perror("epoll_ctl()");
|
||||
exit(1);
|
||||
}
|
||||
#else
|
||||
kq = kqueue();
|
||||
if (kq < 0) {
|
||||
perror("kqueue()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// allocate memory for events
|
||||
krevents = malloc(sizeof(struct kevent) * max_events);
|
||||
if (!krevents) {
|
||||
perror("malloc()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
EV_SET(&kev, proxyfd, EVFILT_READ, EV_ADD, 0, 0, NULL);
|
||||
if (kevent(kq, &kev, 1, NULL, 0, NULL) < 0) {
|
||||
perror("kevent()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
signal(SIGINT, (void *) &end_proxy);
|
||||
signal(SIGTERM, (void *) &reload_proxy);
|
||||
signal(SIGHUP, (void *) &reload_proxy);
|
||||
// and welcome to the loop...
|
||||
|
||||
for (;;) {
|
||||
|
||||
#ifdef __linux__
|
||||
nevents = epoll_wait(epfd, eevents, max_events, -1);
|
||||
if (nevents < 0) {
|
||||
perror("epoll_wait()");
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
nevents = kevent(kq, NULL, 0, krevents, max_events, NULL);
|
||||
if (nevents < 0) {
|
||||
perror("kevent()");
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
for (i = 0; i < nevents; i++) {
|
||||
|
||||
|
||||
if (EV_FD == proxyfd) {
|
||||
|
||||
if (EV_IS_IN) {
|
||||
// new connection, accept it
|
||||
NEV_FD = accept(proxyfd, (struct sockaddr *) &upc_addr, &upc_len);
|
||||
if (NEV_FD < 0) {
|
||||
perror("accept()");
|
||||
continue;
|
||||
}
|
||||
upcs[NEV_FD].node = -1;
|
||||
|
||||
// now connect to the first worker available
|
||||
|
||||
upcs[NEV_FD].dest_fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (upcs[NEV_FD].dest_fd < 0) {
|
||||
perror("socket()");
|
||||
uwsgi_proxy_close(upcs, NEV_FD);
|
||||
continue;
|
||||
}
|
||||
upcs[upcs[NEV_FD].dest_fd].node = -1;
|
||||
|
||||
// set nonblocking
|
||||
if (ioctl(upcs[NEV_FD].dest_fd, FIONBIO, &nonblocking)) {
|
||||
perror("ioctl()");
|
||||
uwsgi_proxy_close(upcs, NEV_FD);
|
||||
continue;
|
||||
}
|
||||
|
||||
upcs[NEV_FD].status = 0;
|
||||
upcs[NEV_FD].retry = 0;
|
||||
next_node = uwsgi_proxy_find_next_node(next_node);
|
||||
if (next_node == -1) {
|
||||
fprintf(stderr, "unable to find an available worker in the cluster !\n");
|
||||
uwsgi_proxy_close(upcs, NEV_FD);
|
||||
continue;
|
||||
}
|
||||
upcs[upcs[NEV_FD].dest_fd].node = next_node;
|
||||
rc = connect(upcs[NEV_FD].dest_fd, (struct sockaddr *) &uwsgi.shared->nodes[next_node].ucn_addr, sizeof(struct sockaddr_in));
|
||||
uwsgi.shared->nodes[next_node].connections++;
|
||||
|
||||
if (!rc) {
|
||||
// connected to worker, put it in the epoll_list
|
||||
|
||||
NEV_EV = EV_IN;
|
||||
if (NEV_ADD) {
|
||||
perror(EV_NAME);
|
||||
uwsgi_proxy_close(upcs, NEV_FD);
|
||||
continue;
|
||||
}
|
||||
|
||||
upcs[upcs[NEV_FD].dest_fd].dest_fd = NEV_FD;
|
||||
upcs[upcs[NEV_FD].dest_fd].status = 0;
|
||||
upcs[upcs[NEV_FD].dest_fd].retry = 0;
|
||||
|
||||
NEV_FD = upcs[NEV_FD].dest_fd;
|
||||
|
||||
NEV_EV = EV_IN;
|
||||
if (NEV_ADD) {
|
||||
perror(EV_NAME);
|
||||
uwsgi_proxy_close(upcs, NEV_FD);
|
||||
continue;
|
||||
}
|
||||
|
||||
// re-set blocking
|
||||
if (ioctl(upcs[upcs[NEV_FD].dest_fd].dest_fd, FIONBIO, &blocking)) {
|
||||
perror("ioctl()");
|
||||
uwsgi_proxy_close(upcs, NEV_FD);
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
else if (errno == EINPROGRESS) {
|
||||
// the socket is waiting, set status to CONNECTING
|
||||
upcs[NEV_FD].status = UWSGI_PROXY_WAITING;
|
||||
upcs[upcs[NEV_FD].dest_fd].dest_fd = NEV_FD;
|
||||
upcs[upcs[NEV_FD].dest_fd].status = UWSGI_PROXY_CONNECTING;
|
||||
upcs[upcs[NEV_FD].dest_fd].retry = 0;
|
||||
|
||||
NEV_FD = upcs[NEV_FD].dest_fd;
|
||||
NEV_EV = EV_OUT;
|
||||
if (NEV_ADD) {
|
||||
perror(EV_NAME);
|
||||
uwsgi_proxy_close(upcs, NEV_FD);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// connection failed, retry with the next node ?
|
||||
perror("connect()");
|
||||
// close only when all node are tried
|
||||
uwsgi_proxy_close(upcs, NEV_FD);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "!!! something horrible happened to the uWSGI proxy, reloading it !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// this is for clients/workers
|
||||
if (EV_IS_IN) {
|
||||
|
||||
// is this a connected client/worker ?
|
||||
//fprintf(stderr,"ready %d\n", upcs[eevents[i].data.fd].status);
|
||||
|
||||
if (!upcs[EV_FD].status) {
|
||||
if (upcs[EV_FD].dest_fd >= 0) {
|
||||
|
||||
rlen = read(EV_FD, buffer, 4096);
|
||||
if (rlen < 0) {
|
||||
perror("read()");
|
||||
uwsgi_proxy_close(upcs, EV_FD);
|
||||
continue;
|
||||
}
|
||||
else if (rlen == 0) {
|
||||
uwsgi_proxy_close(upcs, EV_FD);
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
wlen = write(upcs[EV_FD].dest_fd, buffer, rlen);
|
||||
if (wlen != rlen) {
|
||||
perror("write()");
|
||||
uwsgi_proxy_close(upcs, EV_FD);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_proxy_close(upcs, EV_FD);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (upcs[EV_FD].status == UWSGI_PROXY_WAITING) {
|
||||
// disconnected node
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "UNKNOWN STATUS %d\n", upcs[EV_FD].status);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (EV_IS_OUT) {
|
||||
if (upcs[EV_FD].status == UWSGI_PROXY_CONNECTING) {
|
||||
|
||||
|
||||
#ifdef UWSGI_PROXY_USE_KQUEUE
|
||||
if (getsockopt(EV_FD, SOL_SOCKET, SO_ERROR, (void *) (&soopt), &solen) < 0) {
|
||||
perror("getsockopt()");
|
||||
uwsgi_proxy_close(upcs, NEV_FD);
|
||||
continue;
|
||||
}
|
||||
/* is something bad ? */
|
||||
if (soopt) {
|
||||
fprintf(stderr, "connect() %s\n", strerror(soopt));
|
||||
// increase errors on node
|
||||
fprintf(stderr, "*** marking cluster node %d/%s as failed ***\n", upcs[EV_FD].node, uwsgi.shared->nodes[upcs[EV_FD].node].name);
|
||||
uwsgi.shared->nodes[upcs[EV_FD].node].errors++;
|
||||
uwsgi.shared->nodes[upcs[EV_FD].node].status = UWSGI_NODE_FAILED;
|
||||
uwsgi_proxy_close(upcs, NEV_FD);
|
||||
continue;
|
||||
}
|
||||
|
||||
// increase errors on node
|
||||
#endif
|
||||
NEV_FD = upcs[EV_FD].dest_fd;
|
||||
NEV_EV = EV_IN;
|
||||
upcs[NEV_FD].status = 0;
|
||||
if (NEV_ADD) {
|
||||
perror(EV_NAME);
|
||||
uwsgi_proxy_close(upcs, NEV_FD);
|
||||
continue;
|
||||
}
|
||||
|
||||
NEV_FD = upcs[NEV_FD].dest_fd;
|
||||
upcs[NEV_FD].status = 0;
|
||||
|
||||
#ifdef UWSGI_PROXY_USE_KQUEUE
|
||||
EV_SET(&kev, NEV_FD, EVFILT_WRITE, EV_ADD | EV_DISABLE, 0, 0, NULL);
|
||||
if (NEV_MOD) {
|
||||
perror(EV_NAME);
|
||||
uwsgi_proxy_close(upcs, NEV_FD);
|
||||
continue;
|
||||
}
|
||||
EV_SET(&kev, NEV_FD, EVFILT_READ, EV_ADD, 0, 0, NULL);
|
||||
#endif
|
||||
if (NEV_MOD) {
|
||||
perror(EV_NAME);
|
||||
uwsgi_proxy_close(upcs, NEV_FD);
|
||||
continue;
|
||||
}
|
||||
// re-set blocking
|
||||
if (ioctl(NEV_FD, FIONBIO, &blocking)) {
|
||||
perror("ioctl()");
|
||||
uwsgi_proxy_close(upcs, NEV_FD);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "strange event for %d\n", (int) EV_FD);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (upcs[EV_FD].status == UWSGI_PROXY_CONNECTING) {
|
||||
if (getsockopt(EV_FD, SOL_SOCKET, SO_ERROR, (void *) (&soopt), &solen) < 0) {
|
||||
perror("getsockopt()");
|
||||
}
|
||||
/* is something bad ? */
|
||||
if (soopt) {
|
||||
fprintf(stderr, "connect() %s\n", strerror(soopt));
|
||||
}
|
||||
|
||||
// increase errors on node
|
||||
fprintf(stderr, "*** marking cluster node %d/%s as failed ***\n", upcs[EV_FD].node, uwsgi.shared->nodes[upcs[EV_FD].node].name);
|
||||
uwsgi.shared->nodes[upcs[EV_FD].node].errors++;
|
||||
uwsgi.shared->nodes[upcs[EV_FD].node].status = UWSGI_NODE_FAILED;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "STRANGE EVENT !!! %d %d %d\n", (int) EV_FD, EV_EV, upcs[EV_FD].status);
|
||||
}
|
||||
uwsgi_proxy_close(upcs, EV_FD);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
#warning "*** PROXY support is disabled ***"
|
||||
#endif
|
||||
@@ -0,0 +1,43 @@
|
||||
import os
|
||||
import sys
|
||||
import uwsgiconfig as uc
|
||||
import shutil
|
||||
|
||||
from distutils.core import setup, Distribution
|
||||
from distutils.command.install import install
|
||||
from distutils.command.build_ext import build_ext
|
||||
|
||||
class uWSGIBuilder(build_ext):
|
||||
|
||||
def run(self):
|
||||
uc.parse_vars()
|
||||
uc.build_uwsgi(sys.prefix + '/bin/' + uc.UWSGI_BIN_NAME)
|
||||
|
||||
|
||||
class uWSGIInstall(install):
|
||||
|
||||
def run(self):
|
||||
uc.parse_vars()
|
||||
uc.build_uwsgi(sys.prefix + '/bin/' + uc.UWSGI_BIN_NAME)
|
||||
|
||||
class uWSGIDistribution(Distribution):
|
||||
|
||||
def __init__(self, *attrs):
|
||||
Distribution.__init__(self, *attrs)
|
||||
self.cmdclass['install'] = uWSGIInstall
|
||||
self.cmdclass['build_ext'] = uWSGIBuilder
|
||||
|
||||
|
||||
|
||||
setup(name='uWSGI',
|
||||
version='0.9.5',
|
||||
description='The uWSGI server',
|
||||
author='Unbit',
|
||||
author_email='info@unbit.it',
|
||||
url='http://projects.unbit.it/uwsgi/',
|
||||
license='GPL2',
|
||||
distclass = uWSGIDistribution,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
def application(env, start_response):
|
||||
start_response('200 Ok', [('Content-type', 'text/plain; charset=UTF-32')])
|
||||
return "hello world"
|
||||
@@ -0,0 +1,450 @@
|
||||
#ifdef UWSGI_SNMP
|
||||
|
||||
#include "uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#define SNMP_SEQUENCE 0x30
|
||||
#define SNMP_INTEGER 0x02
|
||||
#define SNMP_STRING 0x04
|
||||
#define SNMP_NULL 0x05
|
||||
#define SNMP_GET 0xA0
|
||||
#define SNMP_RES 0xA2
|
||||
#define SNMP_OID 0x06
|
||||
|
||||
#define SNMP_WATERMARK (127-8)
|
||||
|
||||
/* 1.3.6.1.4.1.35156.17.X.X */
|
||||
#define SNMP_UWSGI_BASE "\x2B\x06\x01\x04\x01\x82\x92\x54\x11"
|
||||
|
||||
static int get_snmp_integer(uint8_t *, uint64_t *);
|
||||
|
||||
static uint64_t get_uwsgi_snmp_value(uint64_t, uint8_t *);
|
||||
static uint64_t get_uwsgi_custom_snmp_value(uint64_t, uint8_t *);
|
||||
|
||||
static uint8_t snmp_int_to_snmp(uint64_t, uint8_t, uint8_t *);
|
||||
|
||||
static ssize_t build_snmp_response(uint8_t, uint8_t, uint8_t *, int, uint8_t *, uint8_t *, uint8_t *);
|
||||
|
||||
void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_addr) {
|
||||
|
||||
uint16_t asnlen;
|
||||
uint16_t oidlen;
|
||||
|
||||
uint8_t oid_part[2];
|
||||
|
||||
int ptrdelta;
|
||||
|
||||
uint8_t *ptr = buffer, *seq1, *seq2, *seq3;
|
||||
|
||||
uint8_t community_len;
|
||||
|
||||
uint64_t snmp_int;
|
||||
uint64_t request_id;
|
||||
uint64_t version;
|
||||
|
||||
// KISS for memory management
|
||||
if (size > SNMP_WATERMARK)
|
||||
return;
|
||||
ptr++;
|
||||
|
||||
// check total sequence size
|
||||
if (*ptr > SNMP_WATERMARK || *ptr < 13)
|
||||
return;
|
||||
ptr++;
|
||||
|
||||
|
||||
// check snmp version
|
||||
if (*ptr != SNMP_INTEGER)
|
||||
return;
|
||||
ptr++;
|
||||
|
||||
ptrdelta = get_snmp_integer(ptr, &version);
|
||||
if (version > 2)
|
||||
return;
|
||||
ptr += ptrdelta;
|
||||
|
||||
|
||||
|
||||
// check for community string (this must be set from the python vm using uwsgi.snmp_community or with --snmp-community arg)
|
||||
if (*ptr != SNMP_STRING)
|
||||
return;
|
||||
ptr++;
|
||||
|
||||
community_len = *ptr;
|
||||
|
||||
|
||||
|
||||
if (community_len > 72 || community_len < 1)
|
||||
return;
|
||||
ptr++;
|
||||
|
||||
// check for community string
|
||||
if (strlen(uwsgi.shared->snmp_community) != community_len)
|
||||
return;
|
||||
if (memcmp(ptr, uwsgi.shared->snmp_community, community_len))
|
||||
return;
|
||||
|
||||
ptr += community_len;
|
||||
|
||||
// check for get request
|
||||
if (*ptr != SNMP_GET)
|
||||
return;
|
||||
*ptr = SNMP_RES;
|
||||
ptr++;
|
||||
seq1 = ptr;
|
||||
|
||||
|
||||
if (*ptr != ((size - community_len) - 9))
|
||||
return;
|
||||
ptr++;
|
||||
|
||||
|
||||
|
||||
// get request_id
|
||||
if (*ptr != SNMP_INTEGER)
|
||||
return;
|
||||
ptr++;
|
||||
ptrdelta = get_snmp_integer(ptr, &request_id);
|
||||
|
||||
|
||||
if (ptrdelta <= 0)
|
||||
return;
|
||||
|
||||
// check here
|
||||
if (ptr + ptrdelta >= buffer + size)
|
||||
return;
|
||||
ptr += ptrdelta;
|
||||
|
||||
// get error
|
||||
if (*ptr != SNMP_INTEGER)
|
||||
return;
|
||||
ptr++;
|
||||
ptrdelta = get_snmp_integer(ptr, &snmp_int);
|
||||
if (ptrdelta <= 0)
|
||||
return;
|
||||
if (ptr + ptrdelta >= buffer + size)
|
||||
return;
|
||||
if (snmp_int != 0)
|
||||
return;
|
||||
ptr += ptrdelta;
|
||||
|
||||
// get index
|
||||
if (*ptr != SNMP_INTEGER)
|
||||
return;
|
||||
ptr++;
|
||||
ptrdelta = get_snmp_integer(ptr, &snmp_int);
|
||||
if (ptrdelta <= 0)
|
||||
return;
|
||||
if (ptr + ptrdelta >= buffer + size)
|
||||
return;
|
||||
|
||||
if (snmp_int != 0)
|
||||
return;
|
||||
ptr += ptrdelta;
|
||||
|
||||
// check for sequence
|
||||
if (*ptr != SNMP_SEQUENCE)
|
||||
return;
|
||||
ptr++;
|
||||
|
||||
|
||||
if (*ptr > SNMP_WATERMARK)
|
||||
return;
|
||||
seq2 = ptr;
|
||||
ptr++;
|
||||
|
||||
// now the interesting stuff: OID management
|
||||
if (*ptr != SNMP_SEQUENCE)
|
||||
return;
|
||||
ptr++;
|
||||
|
||||
|
||||
|
||||
// check for normal OID uWSGI size: |1.3|.6|.1|.4|.1.|35156|.17|.1/2|.x| + OID_NULL
|
||||
asnlen = *ptr;
|
||||
if (asnlen < 15)
|
||||
return;
|
||||
seq3 = ptr;
|
||||
ptr++;
|
||||
|
||||
// is it an OID ?
|
||||
if (*ptr != SNMP_OID)
|
||||
return;
|
||||
ptr++;
|
||||
|
||||
|
||||
oidlen = *ptr;
|
||||
if (oidlen != 11)
|
||||
return;
|
||||
ptr++;
|
||||
|
||||
// and now parse the OID !!!
|
||||
if (memcmp(ptr, SNMP_UWSGI_BASE, 9))
|
||||
return;
|
||||
|
||||
ptr += 9;
|
||||
|
||||
oid_part[0] = *ptr;
|
||||
|
||||
if (oid_part[0] != 1 && oid_part[0] != 2)
|
||||
return;
|
||||
ptr++;
|
||||
|
||||
oid_part[1] = *ptr;
|
||||
if (oid_part[1] < 1 || oid_part[1] > 100)
|
||||
return;
|
||||
ptr++;
|
||||
|
||||
// check for null
|
||||
if (memcmp((char *) ptr, "\x05\x00", 2))
|
||||
return;
|
||||
ptr += 2;
|
||||
|
||||
|
||||
size = build_snmp_response(oid_part[0], oid_part[1], buffer, size, seq1, seq2, seq3);
|
||||
|
||||
if (size > 0) {
|
||||
if (sendto(fd, buffer, size, 0, (struct sockaddr *) client_addr, sizeof(struct sockaddr_in)) < 0) {
|
||||
perror("sendto()");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static uint64_t get_uwsgi_snmp_value(uint64_t val, uint8_t * oid_t) {
|
||||
|
||||
val--;
|
||||
|
||||
if (uwsgi.shared->snmp_gvalue[val].type) {
|
||||
*oid_t = uwsgi.shared->snmp_gvalue[val].type;
|
||||
return *uwsgi.shared->snmp_gvalue[val].val;
|
||||
}
|
||||
|
||||
*oid_t = SNMP_NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t get_uwsgi_custom_snmp_value(uint64_t val, uint8_t * oid_t) {
|
||||
|
||||
val--;
|
||||
if (uwsgi.shared->snmp_value[val].type) {
|
||||
*oid_t = uwsgi.shared->snmp_value[val].type;
|
||||
return uwsgi.shared->snmp_value[val].val;
|
||||
}
|
||||
|
||||
*oid_t = SNMP_NULL;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int get_snmp_integer(uint8_t * ptr, uint64_t * val) {
|
||||
|
||||
uint16_t tlen;
|
||||
int i, j;
|
||||
|
||||
tlen = *ptr;
|
||||
|
||||
if (tlen > 4)
|
||||
return -1;
|
||||
|
||||
|
||||
j = 0;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
for (i = 0; i < tlen; i++) {
|
||||
#else
|
||||
for (i = tlen - 1; i >= 0; i--) {
|
||||
#endif
|
||||
val[j] = ptr[1 + i];
|
||||
j++;
|
||||
}
|
||||
|
||||
return tlen + 1;
|
||||
}
|
||||
|
||||
static uint8_t snmp_int_to_snmp(uint64_t snmp_val, uint8_t oid_type, uint8_t * buffer) {
|
||||
|
||||
uint8_t tlen;
|
||||
int i, j;
|
||||
uint8_t *ptr = (uint8_t *) & snmp_val;
|
||||
|
||||
|
||||
// check for counter, counter64 or gauge
|
||||
|
||||
if (oid_type == SNMP_COUNTER64) {
|
||||
tlen = 8;
|
||||
}
|
||||
else if (oid_type == SNMP_NULL || oid_type == 0) {
|
||||
tlen = 0;
|
||||
}
|
||||
else {
|
||||
tlen = 4;
|
||||
}
|
||||
|
||||
buffer[0] = tlen;
|
||||
|
||||
j = 1;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
for (i = 0; i < tlen; i++) {
|
||||
#else
|
||||
for (i = tlen - 1; i >= 0; i--) {
|
||||
#endif
|
||||
buffer[j] = ptr[i];
|
||||
j++;
|
||||
}
|
||||
|
||||
return tlen + 1;
|
||||
}
|
||||
|
||||
static ssize_t build_snmp_response(uint8_t oid1, uint8_t oid2, uint8_t * buffer, int size, uint8_t * seq1, uint8_t * seq2, uint8_t * seq3) {
|
||||
|
||||
uint64_t snmp_val;
|
||||
uint8_t oid_sz;
|
||||
uint8_t oid_type;
|
||||
|
||||
if (oid1 == 1) {
|
||||
snmp_val = get_uwsgi_snmp_value(oid2, &oid_type);
|
||||
}
|
||||
else if (oid1 == 2) {
|
||||
snmp_val = get_uwsgi_custom_snmp_value(oid2, &oid_type);
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer[size - 2] = oid_type;
|
||||
oid_sz = snmp_int_to_snmp(snmp_val, oid_type, buffer + (size - 1));
|
||||
|
||||
if (oid_sz < 0)
|
||||
return -1;
|
||||
|
||||
oid_sz--;
|
||||
|
||||
buffer[1] += oid_sz;
|
||||
*seq1 += oid_sz;
|
||||
*seq2 += oid_sz;
|
||||
*seq3 += oid_sz;
|
||||
|
||||
return size + oid_sz;
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_snmp_counter32(PyObject * self, PyObject * args) {
|
||||
|
||||
uint8_t oid_num;
|
||||
uint32_t oid_val = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "bi:snmp_set_counter32", &oid_num, &oid_val)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (oid_num > 100 || oid_num < 1)
|
||||
goto clear;
|
||||
|
||||
uwsgi.shared->snmp_value[oid_num - 1].type = SNMP_COUNTER32;
|
||||
uwsgi.shared->snmp_value[oid_num - 1].val = oid_val;
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
clear:
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_snmp_counter64(PyObject * self, PyObject * args) {
|
||||
|
||||
uint8_t oid_num;
|
||||
uint64_t oid_val = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "bl:snmp_set_counter64", &oid_num, &oid_val)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (oid_num > 100 || oid_num < 1)
|
||||
goto clear;
|
||||
|
||||
uwsgi.shared->snmp_value[oid_num - 1].type = SNMP_COUNTER64;
|
||||
uwsgi.shared->snmp_value[oid_num - 1].val = oid_val;
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
clear:
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_snmp_gauge(PyObject * self, PyObject * args) {
|
||||
|
||||
uint8_t oid_num;
|
||||
uint32_t oid_val = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "bi:snmp_set_gauge", &oid_num, &oid_val)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (oid_num > 100 || oid_num < 1)
|
||||
goto clear;
|
||||
|
||||
uwsgi.shared->snmp_value[oid_num - 1].type = SNMP_GAUGE;
|
||||
uwsgi.shared->snmp_value[oid_num - 1].val = oid_val;
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
clear:
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_snmp_community(PyObject * self, PyObject * args) {
|
||||
|
||||
char *snmp_community;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s:snmp_set_community", &snmp_community)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strlen(snmp_community) > 72) {
|
||||
fprintf(stderr, "*** warning the supplied SNMP community string will be truncated to 72 chars ***\n");
|
||||
memcpy(uwsgi.shared->snmp_community, snmp_community, 72);
|
||||
}
|
||||
else {
|
||||
strcpy(uwsgi.shared->snmp_community, snmp_community);
|
||||
}
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
}
|
||||
|
||||
static PyMethodDef uwsgi_snmp_methods[] = {
|
||||
{"snmp_set_counter32", py_snmp_counter32, METH_VARARGS, ""},
|
||||
{"snmp_set_counter64", py_snmp_counter64, METH_VARARGS, ""},
|
||||
{"snmp_set_gauge", py_snmp_gauge, METH_VARARGS, ""},
|
||||
{"snmp_set_community", py_snmp_community, METH_VARARGS, ""},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
void snmp_init() {
|
||||
|
||||
PyMethodDef *uwsgi_function;
|
||||
|
||||
for (uwsgi_function = uwsgi_snmp_methods; uwsgi_function->ml_name != NULL; uwsgi_function++) {
|
||||
PyObject *func = PyCFunction_New(uwsgi_function, NULL);
|
||||
PyDict_SetItemString(uwsgi.embedded_dict, uwsgi_function->ml_name, func);
|
||||
Py_DECREF(func);
|
||||
}
|
||||
|
||||
fprintf(stderr, "SNMP python functions initialized.\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
#else
|
||||
#warning "*** SNMP support is disabled ***"
|
||||
#endif
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abstract_socket) {
|
||||
|
||||
int serverfd;
|
||||
@@ -7,69 +9,215 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
|
||||
fprintf(stderr, "binding on UNIX socket: %s\n", socket_name);
|
||||
|
||||
// leave 1 byte for abstract namespace (108 linux -> 104 bsd/mac)
|
||||
if (strlen(socket_name) > 102) {
|
||||
fprintf(stderr, "invalid socket name\n");
|
||||
exit(1);
|
||||
}
|
||||
// leave 1 byte for abstract namespace (108 linux -> 104 bsd/mac)
|
||||
if (strlen(socket_name) > 102) {
|
||||
fprintf(stderr, "invalid socket name\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uws_addr = malloc(sizeof(struct sockaddr_un));
|
||||
if (uws_addr == NULL) {
|
||||
perror("malloc()");
|
||||
exit(1);
|
||||
}
|
||||
uws_addr = malloc(sizeof(struct sockaddr_un));
|
||||
if (uws_addr == NULL) {
|
||||
perror("malloc()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(uws_addr, 0, sizeof(struct sockaddr_un)) ;
|
||||
serverfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (serverfd < 0) {
|
||||
perror("socket()");
|
||||
exit(1);
|
||||
}
|
||||
if (abstract_socket == 0) {
|
||||
if (unlink(socket_name) != 0) {
|
||||
perror("unlink()");
|
||||
}
|
||||
}
|
||||
memset(uws_addr, 0, sizeof(struct sockaddr_un));
|
||||
serverfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (serverfd < 0) {
|
||||
perror("socket()");
|
||||
exit(1);
|
||||
}
|
||||
if (abstract_socket == 0) {
|
||||
if (unlink(socket_name) != 0 && errno != ENOENT) {
|
||||
perror("unlink()");
|
||||
}
|
||||
}
|
||||
|
||||
if (abstract_socket ==1) {
|
||||
fprintf(stderr, "setting abstract socket mode (warning: only Linux supports this)\n");
|
||||
}
|
||||
if (abstract_socket == 1) {
|
||||
fprintf(stderr, "setting abstract socket mode (warning: only Linux supports this)\n");
|
||||
}
|
||||
|
||||
uws_addr->sun_family = AF_UNIX;
|
||||
strcpy(uws_addr->sun_path+abstract_socket, socket_name);
|
||||
strcpy(uws_addr->sun_path + abstract_socket, socket_name);
|
||||
|
||||
if (bind(serverfd, (struct sockaddr *) uws_addr, strlen(socket_name)+ abstract_socket + ( (void *)uws_addr->sun_path - (void *)uws_addr) ) != 0) {
|
||||
if (bind(serverfd, (struct sockaddr *) uws_addr, strlen(socket_name) + abstract_socket + ((void *) uws_addr->sun_path - (void *) uws_addr)) != 0) {
|
||||
perror("bind()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (listen(serverfd, listen_queue) != 0) {
|
||||
perror("listen()");
|
||||
exit(1);
|
||||
perror("listen()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// chmod unix socket for lazy users
|
||||
if (chmod_socket == 1 && abstract_socket == 0) {
|
||||
fprintf(stderr, "chmod() socket to 666 for lazy and brave users\n");
|
||||
if (chmod(socket_name, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) != 0) {
|
||||
perror("chmod()");
|
||||
}
|
||||
fprintf(stderr, "chmod() socket to 666 for lazy and brave users\n");
|
||||
if (chmod(socket_name, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) != 0) {
|
||||
perror("chmod()");
|
||||
}
|
||||
}
|
||||
|
||||
return serverfd;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SCTP
|
||||
|
||||
#define MAX_SCTP_ADDRESS 4
|
||||
/* sctp address format sctp:127.0.0.1,192.168.0.17:3031 */
|
||||
int bind_to_sctp(char *socket_name, int listen_queue, char *sctp_port) {
|
||||
int serverfd;
|
||||
struct sockaddr_in uws_addr[MAX_SCTP_ADDRESS];
|
||||
int num_ip = 0;
|
||||
|
||||
struct sctp_initmsg sctp_im;
|
||||
|
||||
|
||||
sctp_port[0] = 0;
|
||||
memset(uws_addr, 0, sizeof(struct sockaddr_in) * MAX_SCTP_ADDRESS);
|
||||
memset(&sctp_im, 0, sizeof(struct sctp_initmsg));
|
||||
|
||||
while (socket_name != NULL && num_ip < MAX_SCTP_ADDRESS) {
|
||||
char *ap;
|
||||
while ((ap = strsep(&socket_name, ",")) != NULL) {
|
||||
if (*ap != '\0') {
|
||||
uws_addr[num_ip].sin_family = AF_INET;
|
||||
uws_addr[num_ip].sin_port = htons(atoi(sctp_port + 1));
|
||||
uws_addr[num_ip].sin_addr.s_addr = inet_addr(ap);
|
||||
num_ip++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
serverfd = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP);
|
||||
if (serverfd < 0) {
|
||||
perror("socket()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fprintf(stderr, "binding on %d SCTP interfaces on port: %d\n", num_ip, ntohs(uws_addr[0].sin_port));
|
||||
|
||||
|
||||
if (sctp_bindx(serverfd, (struct sockaddr *) uws_addr, num_ip, SCTP_BINDX_ADD_ADDR) != 0) {
|
||||
perror("sctp_bindx()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sctp_im.sinit_max_instreams = 0xFFFF;
|
||||
sctp_im.sinit_num_ostreams = 0xFFFF;
|
||||
|
||||
if (setsockopt(serverfd, IPPROTO_SCTP, SCTP_INITMSG, &sctp_im, sizeof(sctp_im))) {
|
||||
perror("setsockopt()");
|
||||
}
|
||||
|
||||
if (listen(serverfd, listen_queue) != 0) {
|
||||
perror("listen()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return serverfd;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_UDP
|
||||
int bind_to_udp(char *socket_name) {
|
||||
int serverfd;
|
||||
struct sockaddr_in uws_addr;
|
||||
char *udp_port;
|
||||
|
||||
struct ip_mreq mc;
|
||||
|
||||
udp_port = strchr(socket_name, ':');
|
||||
if (udp_port == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
udp_port[0] = 0;
|
||||
memset(&uws_addr, 0, sizeof(struct sockaddr_in));
|
||||
uws_addr.sin_family = AF_INET;
|
||||
uws_addr.sin_port = htons(atoi(udp_port + 1));
|
||||
//uws_addr.sin_addr.s_addr = inet_addr(socket_name);
|
||||
uws_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
serverfd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (serverfd < 0) {
|
||||
perror("socket()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// if multicast is enabled remember to bind to INADDR_ANY
|
||||
mc.imr_multiaddr.s_addr = inet_addr("225.0.0.1");
|
||||
if (socket_name[0] == 0) {
|
||||
mc.imr_interface.s_addr = INADDR_ANY;
|
||||
}
|
||||
else {
|
||||
mc.imr_interface.s_addr = inet_addr(socket_name);
|
||||
}
|
||||
|
||||
fprintf(stderr, "binding on UDP port: %d\n", ntohs(uws_addr.sin_port));
|
||||
|
||||
if (bind(serverfd, (struct sockaddr *) &uws_addr, sizeof(uws_addr)) != 0) {
|
||||
perror("bind()");
|
||||
close(serverfd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(stderr, "joining uWSGI multicast group: %s:%d\n", "225.0.0.1", ntohs(uws_addr.sin_port));
|
||||
if (setsockopt(serverfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mc, sizeof(mc))) {
|
||||
perror("setsockopt()");
|
||||
}
|
||||
|
||||
return serverfd;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
int connect_to_tcp(char *socket_name, int port, int timeout) {
|
||||
|
||||
struct pollfd uwsgi_poll;
|
||||
struct sockaddr_in uws_addr;
|
||||
|
||||
memset(&uws_addr, 0, sizeof(struct sockaddr_in));
|
||||
|
||||
uws_addr.sin_family = AF_INET;
|
||||
uws_addr.sin_port = htons(port);
|
||||
|
||||
if (socket_name[0] == 0) {
|
||||
uws_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
}
|
||||
else {
|
||||
uws_addr.sin_addr.s_addr = inet_addr(socket_name);
|
||||
}
|
||||
|
||||
uwsgi_poll.fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (uwsgi_poll.fd < 0) {
|
||||
perror("socket()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_poll.events = POLLIN;
|
||||
|
||||
if (timed_connect(&uwsgi_poll, (const struct sockaddr *) &uws_addr, sizeof(struct sockaddr_in), timeout)) {
|
||||
perror("connect()");
|
||||
close(uwsgi_poll.fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return uwsgi_poll.fd;
|
||||
|
||||
}
|
||||
|
||||
int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
|
||||
int serverfd;
|
||||
struct sockaddr_in uws_addr;
|
||||
int reuse = 1 ;
|
||||
|
||||
tcp_port[0] = 0 ;
|
||||
int reuse = 1;
|
||||
|
||||
tcp_port[0] = 0;
|
||||
memset(&uws_addr, 0, sizeof(struct sockaddr_in));
|
||||
|
||||
uws_addr.sin_family = AF_INET;
|
||||
uws_addr.sin_port = htons(atoi(tcp_port+1));
|
||||
uws_addr.sin_port = htons(atoi(tcp_port + 1));
|
||||
|
||||
|
||||
if (socket_name[0] == 0) {
|
||||
@@ -79,29 +227,109 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
uws_addr.sin_addr.s_addr = inet_addr(socket_name);
|
||||
}
|
||||
|
||||
serverfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (serverfd < 0) {
|
||||
perror("socket()");
|
||||
exit(1);
|
||||
}
|
||||
serverfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (serverfd < 0) {
|
||||
perror("socket()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&reuse , sizeof(int)) < 0) {
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) {
|
||||
perror("setsockopt()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!uwsgi.no_defer_accept) {
|
||||
|
||||
fprintf(stderr,"binding on TCP port: %d\n", ntohs(uws_addr.sin_port));
|
||||
#ifdef TCP_DEFER_ACCEPT
|
||||
if (setsockopt(serverfd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], sizeof(int))) {
|
||||
perror("setsockopt()");
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "TCP_DEFER_ACCEPT enabled.\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bind(serverfd, (struct sockaddr *) &uws_addr, sizeof(uws_addr) ) != 0) {
|
||||
}
|
||||
|
||||
|
||||
fprintf(stderr, "binding on TCP port: %d\n", ntohs(uws_addr.sin_port));
|
||||
|
||||
if (bind(serverfd, (struct sockaddr *) &uws_addr, sizeof(uws_addr)) != 0) {
|
||||
perror("bind()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (listen(serverfd, listen_queue) != 0) {
|
||||
perror("listen()");
|
||||
exit(1);
|
||||
perror("listen()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
return serverfd;
|
||||
}
|
||||
|
||||
int timed_connect(struct pollfd *fdpoll, const struct sockaddr *addr, int addr_size, int timeout) {
|
||||
|
||||
int arg, ret;
|
||||
int soopt;
|
||||
socklen_t solen = sizeof(int);
|
||||
int cnt;
|
||||
/* set non-blocking socket */
|
||||
|
||||
arg = fcntl(fdpoll->fd, F_GETFL, NULL);
|
||||
if (arg < 0) {
|
||||
perror("fcntl()");
|
||||
return -1;
|
||||
}
|
||||
arg |= O_NONBLOCK;
|
||||
if (fcntl(fdpoll->fd, F_SETFL, arg) < 0) {
|
||||
perror("fcntl()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = connect(fdpoll->fd, addr, addr_size);
|
||||
if (ret < 0) {
|
||||
/* check what happened */
|
||||
|
||||
// in progress ?
|
||||
if (errno == EINPROGRESS) {
|
||||
if (timeout < 1)
|
||||
timeout = 3;
|
||||
fdpoll->events = POLLOUT;
|
||||
cnt = poll(fdpoll, 1, timeout * 1000);
|
||||
/* check for errors */
|
||||
if (cnt < 0 && errno != EINTR) {
|
||||
perror("poll()");
|
||||
return -1;
|
||||
}
|
||||
/* something hapened on the socket ... */
|
||||
else if (cnt > 0) {
|
||||
if (getsockopt(fdpoll->fd, SOL_SOCKET, SO_ERROR, (void *) (&soopt), &solen) < 0) {
|
||||
perror("getsockopt()");
|
||||
return -1;
|
||||
}
|
||||
/* is something bad ? */
|
||||
if (soopt) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/* timeout */
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* re-set blocking socket */
|
||||
arg &= (~O_NONBLOCK);
|
||||
if (fcntl(fdpoll->fd, F_SETFL, arg) < 0) {
|
||||
perror("fcntl()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#ifdef UWSGI_SPOOLER
|
||||
#include "uwsgi.h"
|
||||
|
||||
#include <dirent.h>
|
||||
@@ -5,37 +6,31 @@
|
||||
|
||||
extern char *spool_dir;
|
||||
|
||||
struct uwsgi_packet_header {
|
||||
uint8_t modifier1;
|
||||
uint16_t datasize;
|
||||
uint8_t modifier2;
|
||||
};
|
||||
|
||||
|
||||
int spool_request(char *filename, int rn, char *buffer, int size) {
|
||||
|
||||
char hostname[256+1];
|
||||
struct timeval tv;
|
||||
char hostname[256 + 1];
|
||||
struct timeval tv;
|
||||
int fd;
|
||||
struct uwsgi_packet_header uh ;
|
||||
struct uwsgi_header uh;
|
||||
|
||||
if (gethostname(hostname,256)) {
|
||||
perror("gethostname()");
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
hostname[256] = 0 ;
|
||||
|
||||
if (snprintf(filename,1024,"%s/uwsgi_spoolfile_on_%s_%d_%d_%llu_%llu", spool_dir, hostname, getpid(), rn, (unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec ) <= 0) {
|
||||
if (gethostname(hostname, 256)) {
|
||||
perror("gethostname()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
fd = open(filename, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR);
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
hostname[256] = 0;
|
||||
|
||||
if (snprintf(filename, 1024, "%s/uwsgi_spoolfile_on_%s_%d_%d_%llu_%llu", spool_dir, hostname, getpid(), rn, (unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec) <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
fd = open(filename, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR);
|
||||
if (fd < 0) {
|
||||
perror("open()");
|
||||
return 0 ;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __sun__
|
||||
@@ -49,29 +44,29 @@ int spool_request(char *filename, int rn, char *buffer, int size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uh.modifier1 = 17 ;
|
||||
uh.modifier2 = 0 ;
|
||||
uh.datasize = (uint16_t) size ;
|
||||
uh.modifier1 = 17;
|
||||
uh.modifier2 = 0;
|
||||
uh.pktsize = (uint16_t) size;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
uh.datasize= uwsgi_swap16(uh.datasize);
|
||||
uh.pktsize = uwsgi_swap16(uh.pktsize);
|
||||
#endif
|
||||
|
||||
if (write(fd, &uh, 4) != 4) {
|
||||
goto clear ;
|
||||
goto clear;
|
||||
}
|
||||
|
||||
if (write(fd, buffer, size) != size) {
|
||||
goto clear ;
|
||||
goto clear;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
fprintf(stderr,"written %d bytes to spool file %s.\n",size + 4, filename);
|
||||
fprintf(stderr, "written %d bytes to spool file %s.\n", size + 4, filename);
|
||||
|
||||
return 1;
|
||||
|
||||
|
||||
clear:
|
||||
|
||||
clear:
|
||||
|
||||
perror("write()");
|
||||
unlink(filename);
|
||||
@@ -79,38 +74,38 @@ clear:
|
||||
return 0;
|
||||
}
|
||||
|
||||
void spooler(PyObject *uwsgi_module) {
|
||||
DIR *sdir ;
|
||||
void spooler(PyObject * uwsgi_module) {
|
||||
DIR *sdir;
|
||||
struct dirent *dp;
|
||||
PyObject *uwsgi_module_dict, *spooler_callable, *spool_result, *spool_tuple, *spool_env ;
|
||||
int spool_fd ;
|
||||
uint16_t uwstrlen ;
|
||||
PyObject *uwsgi_module_dict, *spooler_callable, *spool_result, *spool_tuple, *spool_env;
|
||||
int spool_fd;
|
||||
uint16_t uwstrlen;
|
||||
int rlen = 0;
|
||||
int datasize ;
|
||||
int datasize;
|
||||
|
||||
struct uwsgi_packet_header uh ;
|
||||
struct uwsgi_header uh;
|
||||
|
||||
char *key;
|
||||
char *val;
|
||||
|
||||
uwsgi_module_dict = PyModule_GetDict(uwsgi_module);
|
||||
if (!uwsgi_module_dict) {
|
||||
fprintf(stderr,"could not get uwsgi module __dict__\n");
|
||||
exit(1);
|
||||
}
|
||||
if (!uwsgi_module_dict) {
|
||||
fprintf(stderr, "could not get uwsgi module __dict__\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
spool_tuple = PyTuple_New(1);
|
||||
|
||||
if (!spool_tuple) {
|
||||
fprintf(stderr,"could not create spooler tuple.\n");
|
||||
fprintf(stderr, "could not create spooler tuple.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
spool_env = PyDict_New();
|
||||
if (!spool_env) {
|
||||
fprintf(stderr,"could not create spooler env.\n");
|
||||
fprintf(stderr, "could not create spooler env.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -118,19 +113,20 @@ void spooler(PyObject *uwsgi_module) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
if (chdir(spool_dir)) {
|
||||
perror("chdir()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
// asked by Marco Beri
|
||||
fprintf(stderr, "lowering spooler priority to %d\n", PRIO_MAX);
|
||||
setpriority(PRIO_PROCESS, getpid(), PRIO_MAX);
|
||||
|
||||
for (;;) {
|
||||
sdir = opendir(".");
|
||||
if (sdir) {
|
||||
while((dp = readdir(sdir)) != NULL) {
|
||||
#ifndef __sun__
|
||||
if (!strncmp("uwsgi_spoolfile_on_", dp->d_name, 19) && dp->d_type == DT_REG) {
|
||||
#else
|
||||
while ((dp = readdir(sdir)) != NULL) {
|
||||
if (!strncmp("uwsgi_spoolfile_on_", dp->d_name, 19)) {
|
||||
struct stat sf_lstat;
|
||||
if (lstat(dp->d_name, &sf_lstat)) {
|
||||
@@ -139,21 +135,20 @@ void spooler(PyObject *uwsgi_module) {
|
||||
if (!S_ISREG(sf_lstat.st_mode)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (!access(dp->d_name, R_OK|W_OK)) {
|
||||
fprintf(stderr,"managing spool request %s...\n", dp->d_name);
|
||||
if (!access(dp->d_name, R_OK | W_OK)) {
|
||||
fprintf(stderr, "managing spool request %s...\n", dp->d_name);
|
||||
|
||||
spooler_callable = PyDict_GetItemString(uwsgi_module_dict, "spooler");
|
||||
if (!spooler_callable) {
|
||||
fprintf(stderr,"you have to define uwsgi.spooler to use the spooler !!!\n");
|
||||
fprintf(stderr, "you have to define uwsgi.spooler to use the spooler !!!\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
spool_fd = open(dp->d_name, O_RDONLY) ;
|
||||
spool_fd = open(dp->d_name, O_RDONLY);
|
||||
if (spool_fd < 0) {
|
||||
perror("open()");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __sun__
|
||||
if (lockf(spool_fd, F_LOCK, 0)) {
|
||||
@@ -172,23 +167,23 @@ void spooler(PyObject *uwsgi_module) {
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
uh.datasize= uwsgi_swap16(uh.datasize);
|
||||
#endif
|
||||
|
||||
datasize = 0 ;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
uh.pktsize = uwsgi_swap16(uh.pktsize);
|
||||
#endif
|
||||
|
||||
while( datasize < uh.datasize) {
|
||||
rlen = read(spool_fd, &uwstrlen, 2) ;
|
||||
datasize = 0;
|
||||
|
||||
while (datasize < uh.pktsize) {
|
||||
rlen = read(spool_fd, &uwstrlen, 2);
|
||||
if (rlen != 2) {
|
||||
perror("read()");
|
||||
goto next_spool ;
|
||||
goto next_spool;
|
||||
}
|
||||
datasize += rlen ;
|
||||
datasize += rlen;
|
||||
key = NULL;
|
||||
val = NULL;
|
||||
if (uwstrlen > 0) {
|
||||
key = malloc(uwstrlen+1);
|
||||
key = malloc(uwstrlen + 1);
|
||||
if (!key) {
|
||||
perror("malloc()");
|
||||
goto retry_later;
|
||||
@@ -199,8 +194,8 @@ void spooler(PyObject *uwsgi_module) {
|
||||
free(key);
|
||||
goto next_spool;
|
||||
}
|
||||
datasize += rlen ;
|
||||
key[rlen] = 0 ;
|
||||
datasize += rlen;
|
||||
key[rlen] = 0;
|
||||
|
||||
|
||||
rlen = read(spool_fd, &uwstrlen, 2);
|
||||
@@ -209,10 +204,10 @@ void spooler(PyObject *uwsgi_module) {
|
||||
free(key);
|
||||
goto next_spool;
|
||||
}
|
||||
datasize += rlen ;
|
||||
datasize += rlen;
|
||||
|
||||
if (uwstrlen > 0) {
|
||||
val = malloc(uwstrlen+1);
|
||||
val = malloc(uwstrlen + 1);
|
||||
if (!val) {
|
||||
free(key);
|
||||
perror("malloc()");
|
||||
@@ -221,12 +216,12 @@ void spooler(PyObject *uwsgi_module) {
|
||||
|
||||
rlen = read(spool_fd, val, uwstrlen);
|
||||
if (rlen != uwstrlen) {
|
||||
perror("read()");
|
||||
free(key);
|
||||
goto next_spool;
|
||||
}
|
||||
datasize += rlen ;
|
||||
val[rlen] = 0 ;
|
||||
perror("read()");
|
||||
free(key);
|
||||
goto next_spool;
|
||||
}
|
||||
datasize += rlen;
|
||||
val[rlen] = 0;
|
||||
/* ready to add item to the dict */
|
||||
}
|
||||
|
||||
@@ -234,7 +229,7 @@ void spooler(PyObject *uwsgi_module) {
|
||||
PyErr_Print();
|
||||
free(key);
|
||||
free(val);
|
||||
goto retry_later ;
|
||||
goto retry_later;
|
||||
}
|
||||
|
||||
free(key);
|
||||
@@ -244,33 +239,33 @@ void spooler(PyObject *uwsgi_module) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
spool_result = PyEval_CallObject(spooler_callable, spool_tuple);
|
||||
|
||||
spool_result = PyEval_CallObject(spooler_callable, spool_tuple);
|
||||
if (!spool_result) {
|
||||
PyErr_Print();
|
||||
fprintf(stderr,"error detected. spool request canceled.\n");
|
||||
fprintf(stderr, "error detected. spool request canceled.\n");
|
||||
goto next_spool;
|
||||
}
|
||||
if (PyInt_Check(spool_result)) {
|
||||
if (PyInt_AsLong(spool_result) == 17) {
|
||||
Py_DECREF(spool_result);
|
||||
fprintf(stderr,"retry this task later...\n");
|
||||
fprintf(stderr, "retry this task later...\n");
|
||||
goto retry_later;
|
||||
}
|
||||
}
|
||||
|
||||
Py_DECREF(spool_result);
|
||||
|
||||
fprintf(stderr,"done with task/spool %s\n", dp->d_name);
|
||||
next_spool:
|
||||
fprintf(stderr, "done with task/spool %s\n", dp->d_name);
|
||||
next_spool:
|
||||
|
||||
if (unlink(dp->d_name)) {
|
||||
perror("unlink");
|
||||
fprintf(stderr,"something horrible happened to the spooler. Better to kill it.\n");
|
||||
fprintf(stderr, "something horrible happened to the spooler. Better to kill it.\n");
|
||||
exit(1);
|
||||
}
|
||||
retry_later:
|
||||
retry_later:
|
||||
PyDict_Clear(spool_env);
|
||||
close(spool_fd);
|
||||
}
|
||||
@@ -286,3 +281,53 @@ retry_later:
|
||||
sleep(5);
|
||||
}
|
||||
}
|
||||
|
||||
int uwsgi_request_spooler(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
|
||||
|
||||
int i;
|
||||
char spool_filename[1024];
|
||||
|
||||
if (spool_dir == NULL) {
|
||||
fprintf(stderr, "the spooler is inactive !!!...skip\n");
|
||||
wsgi_req->modifier = 255;
|
||||
wsgi_req->size = 0;
|
||||
wsgi_req->modifier_arg = 0;
|
||||
i = write(uwsgi->poll.fd, wsgi_req, 4);
|
||||
if (i != 4) {
|
||||
perror("write()");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(stderr, "managing spool request...\n");
|
||||
i = spool_request(spool_filename, uwsgi->workers[0].requests + 1, uwsgi->buffer, wsgi_req->size);
|
||||
wsgi_req->modifier = 255;
|
||||
wsgi_req->size = 0;
|
||||
if (i > 0) {
|
||||
wsgi_req->modifier_arg = 1;
|
||||
if (write(uwsgi->poll.fd, wsgi_req, 4) != 4) {
|
||||
fprintf(stderr, "disconnected client, remove spool file.\n");
|
||||
/* client disconnect, remove spool file */
|
||||
if (unlink(spool_filename)) {
|
||||
perror("unlink()");
|
||||
fprintf(stderr, "something horrible happened !!! check your spooler ASAP !!!\n");
|
||||
goodbye_cruel_world();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
/* announce a failed spool request */
|
||||
wsgi_req->modifier_arg = 0;
|
||||
i = write(uwsgi->poll.fd, wsgi_req, 4);
|
||||
if (i != 4) {
|
||||
perror("write()");
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#else
|
||||
#warning "*** Spooler support is disabled ***"
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
def application(environ, start_response):
|
||||
start_response('200 OK', [('Content-Type', 'image/png')])
|
||||
fd = open('logo_uWSGI.png','r')
|
||||
return environ['wsgi.file_wrapper'](fd, 4096)
|
||||
@@ -0,0 +1,13 @@
|
||||
import uwsgi
|
||||
|
||||
counter = 0
|
||||
uwsgi.snmp_set_counter64(1, counter)
|
||||
|
||||
def application(environ, start_response):
|
||||
global counter
|
||||
|
||||
start_response('200 OK', [('Content-Type', 'image/png')])
|
||||
fd = open('logo_uWSGI.png','r')
|
||||
counter = counter+1
|
||||
uwsgi.snmp_set_counter64(1, counter)
|
||||
return environ['wsgi.file_wrapper'](fd, 4096)
|
||||
+38
-17
@@ -10,6 +10,7 @@ os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'
|
||||
|
||||
#import django.core.handlers.wsgi
|
||||
|
||||
uwsgi.load_plugin(0, "plugins/example/example_plugin.so", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa")
|
||||
|
||||
from threading import Thread
|
||||
|
||||
@@ -88,6 +89,10 @@ def djangohomepage():
|
||||
def reload(env, start_response):
|
||||
|
||||
start_response('200 OK', [('Content-Type', 'text/html')])
|
||||
|
||||
#uwsgi.sorry_i_need_to_block()
|
||||
#time.sleep(1)
|
||||
|
||||
#uwsgi.reload()
|
||||
|
||||
# print str(uwsgi.masterpid()) + "\n"
|
||||
@@ -115,31 +120,47 @@ def reload(env, start_response):
|
||||
|
||||
# yield 4/0
|
||||
|
||||
out = '<h1>uWSGI status</h1>' ;
|
||||
out += 'masterpid: <b>' + str(uwsgi.masterpid()) + '</b><br/>'
|
||||
yield '<h1>uWSGI status ('+env['SCRIPT_NAME']+')</h1>' ;
|
||||
yield 'masterpid: <b>' + str(uwsgi.masterpid()) + '</b><br/>'
|
||||
|
||||
out += 'started on: <b>' + time.ctime(uwsgi.started_on) + '</b><br/>'
|
||||
yield 'started on: <b>' + time.ctime(uwsgi.started_on) + '</b><br/>'
|
||||
|
||||
out += 'buffer size: <b>' + str(uwsgi.buffer_size) + '</b><br/>'
|
||||
yield 'buffer size: <b>' + str(uwsgi.buffer_size) + '</b><br/>'
|
||||
|
||||
out += 'total_requests: <b>' + str(uwsgi.total_requests()) + '</b><br/>'
|
||||
yield 'total_requests: <b>' + str(uwsgi.total_requests()) + '</b><br/>'
|
||||
|
||||
out += 'workers: <b>' + str(uwsgi.numproc) + '</b><br/>'
|
||||
yield 'workers: <b>' + str(uwsgi.numproc) + '</b><br/>'
|
||||
|
||||
out += '<table border="1">'
|
||||
out += '<th>worker id</th><th>pid</th><th>requests</th><th>address space</th><th>rss</th>'
|
||||
yield '<h2>dynamic options</h2>'
|
||||
|
||||
yield '<b>logging</b>: ' + str(uwsgi.get_option(0)) + '<br/>'
|
||||
yield '<b>max_requests</b>: ' + str(uwsgi.getoption(1)) + '<br/>'
|
||||
yield '<b>socket_timeout</b>: ' + str(uwsgi.getoption(2)) + '<br/>'
|
||||
yield '<b>memory_debug</b>: ' + str(uwsgi.getoption(3)) + '<br/>'
|
||||
yield '<b>master_interval</b>: ' + str(uwsgi.getoption(4)) + '<br/>'
|
||||
yield '<b>harakiri</b>: ' + str(uwsgi.getoption(5)) + '<br/>'
|
||||
yield '<b>cgi_mode</b>: ' + str(uwsgi.get_option(6)) + '<br/>'
|
||||
yield '<b>threads</b>: ' + str(uwsgi.get_option(7)) + '<br/>'
|
||||
yield '<b>process_reaper</b>: ' + str(uwsgi.get_option(8)) + '<br/>'
|
||||
|
||||
yield '<table border="1">'
|
||||
yield '<th>worker id</th><th>pid</th><th>in request</th><th>requests</th><th>running time</th><th>address space</th><th>rss</th>'
|
||||
|
||||
workers = uwsgi.workers();
|
||||
|
||||
for w in workers:
|
||||
print w
|
||||
if w is not None:
|
||||
out += '<tr><td>'+ str(w['id']) +'</td><td>' + str(w['pid']) + '</td><td>' + str(w['requests']) + '</td><td>' + str(w['vsz']) + '</td><td>' + str(w['rss']) + '</td></tr>'
|
||||
|
||||
out += '</table>'
|
||||
yield '<h2>workers</h2>'
|
||||
|
||||
yield out
|
||||
print "FATTOfattoFATTO"
|
||||
for w in workers:
|
||||
#print w
|
||||
#print w['running_time']
|
||||
if w is not None:
|
||||
yield '<tr><td>'+ str(w['id']) +'</td><td>' + str(w['pid']) + '</td><td>' + str(w['in_request']) + '</td><td>' + str(w['requests']) + '</td><td>' + str(w['running_time']) + '</td><td>' + str(w['vsz']) + '</td><td>' + str(w['rss']) + '</td></tr>'
|
||||
print w
|
||||
|
||||
yield '</table>'
|
||||
|
||||
#yield out
|
||||
#print "FATTOfattoFATTO"
|
||||
|
||||
def remotemako(env, start_response):
|
||||
start_response('200 OK', [('Content-Type', 'text/html')])
|
||||
@@ -162,7 +183,7 @@ uwsgi.fastfuncs.insert(17, djangohomepage)
|
||||
#djangoapp = django.core.handlers.wsgi.WSGIHandler()
|
||||
|
||||
#applications = { '/':django.core.handlers.wsgi.WSGIHandler() }
|
||||
uwsgi.applications = { '/':reload }
|
||||
uwsgi.applications = { '/':reload, '/pippo':reload }
|
||||
|
||||
print uwsgi.applications
|
||||
print uwsgi.applist
|
||||
|
||||
@@ -1,50 +1,50 @@
|
||||
/* taken from http://wiki.unbit.it/UnbitKernel */
|
||||
struct uidsec_struct {
|
||||
/* network limits */
|
||||
unsigned short ipv4_tcp_port;
|
||||
unsigned short ipv4_udp_port;
|
||||
unsigned short ipv4_tcp_control_port;
|
||||
/* network limits */
|
||||
unsigned short ipv4_tcp_port;
|
||||
unsigned short ipv4_udp_port;
|
||||
unsigned short ipv4_tcp_control_port;
|
||||
|
||||
int ipv4_tcp_socket_protection;
|
||||
unsigned long long ipv4_firewall_mask;
|
||||
int ipv4_tcp_socket_protection;
|
||||
unsigned long long ipv4_firewall_mask;
|
||||
|
||||
/* limits */
|
||||
int fs_readonly;
|
||||
/* limits */
|
||||
int fs_readonly;
|
||||
|
||||
/* process markers */
|
||||
int domain_id;
|
||||
int fcgi_id;
|
||||
int scgi_id;
|
||||
int apps_id;
|
||||
int wapp_id;
|
||||
int ssh_id;
|
||||
int cron_id;
|
||||
/* process markers */
|
||||
int domain_id;
|
||||
int fcgi_id;
|
||||
int scgi_id;
|
||||
int apps_id;
|
||||
int wapp_id;
|
||||
int ssh_id;
|
||||
int cron_id;
|
||||
|
||||
/* thread ?*/
|
||||
int cloned_vm;
|
||||
/* thread ? */
|
||||
int cloned_vm;
|
||||
|
||||
/* process limit */
|
||||
int max_dom_proc;
|
||||
int max_apps_proc;
|
||||
int max_apps_thread;
|
||||
int max_ssh_proc;
|
||||
int max_cron_proc;
|
||||
/* process limit */
|
||||
int max_dom_proc;
|
||||
int max_apps_proc;
|
||||
int max_apps_thread;
|
||||
int max_ssh_proc;
|
||||
int max_cron_proc;
|
||||
|
||||
/* misc */
|
||||
int control_uid;
|
||||
int listen_backlog;
|
||||
int errors ;
|
||||
/* misc */
|
||||
int control_uid;
|
||||
int listen_backlog;
|
||||
int errors;
|
||||
|
||||
/* counters */
|
||||
int accept_cnt ;
|
||||
int accept_last;
|
||||
/* counters */
|
||||
int accept_cnt;
|
||||
int accept_last;
|
||||
|
||||
int fork_cnt ;
|
||||
int fork_last;
|
||||
int fork_cnt;
|
||||
int fork_last;
|
||||
|
||||
unsigned long long bio_read;
|
||||
unsigned long long bio_write;
|
||||
unsigned long long bio_read;
|
||||
unsigned long long bio_write;
|
||||
|
||||
int memory_errors;
|
||||
int memory_errors;
|
||||
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "uwsgi.h"
|
||||
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
@@ -11,10 +12,10 @@ uint16_t uwsgi_swap16(uint16_t x) {
|
||||
void set_harakiri(int sec) {
|
||||
if (uwsgi.workers) {
|
||||
if (sec == 0) {
|
||||
uwsgi.workers[uwsgi.mywid].harakiri = 0 ;
|
||||
uwsgi.workers[uwsgi.mywid].harakiri = 0;
|
||||
}
|
||||
else {
|
||||
uwsgi.workers[uwsgi.mywid].harakiri = time(NULL) + sec ;
|
||||
uwsgi.workers[uwsgi.mywid].harakiri = time(NULL) + sec;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -25,76 +26,76 @@ void set_harakiri(int sec) {
|
||||
#ifndef UNBIT
|
||||
|
||||
void daemonize(char *logfile) {
|
||||
pid_t pid;
|
||||
int fd, fdin;
|
||||
pid_t pid;
|
||||
int fd, fdin;
|
||||
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
perror("fork()");
|
||||
exit(1) ;
|
||||
}
|
||||
if (pid != 0) {
|
||||
exit(0);
|
||||
}
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
perror("fork()");
|
||||
exit(1);
|
||||
}
|
||||
if (pid != 0) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (setsid() < 0) {
|
||||
perror("setsid()");
|
||||
exit(1) ;
|
||||
}
|
||||
if (setsid() < 0) {
|
||||
perror("setsid()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/* refork... */
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
perror("fork()");
|
||||
exit(1) ;
|
||||
}
|
||||
if (pid != 0) {
|
||||
exit(0);
|
||||
}
|
||||
/* refork... */
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
perror("fork()");
|
||||
exit(1);
|
||||
}
|
||||
if (pid != 0) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
umask(0);
|
||||
umask(0);
|
||||
|
||||
|
||||
/*if (chdir("/") != 0) {
|
||||
perror("chdir()");
|
||||
exit(1);
|
||||
}*/
|
||||
/*if (chdir("/") != 0) {
|
||||
perror("chdir()");
|
||||
exit(1);
|
||||
} */
|
||||
|
||||
|
||||
fdin = open("/dev/null", O_RDWR);
|
||||
if (fdin < 0) {
|
||||
perror("open()");
|
||||
exit(1);
|
||||
}
|
||||
fdin = open("/dev/null", O_RDWR);
|
||||
if (fdin < 0) {
|
||||
perror("open()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fd = open(logfile, O_RDWR|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP );
|
||||
if (fd < 0) {
|
||||
perror("open()");
|
||||
exit(1);
|
||||
}
|
||||
fd = open(logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (fd < 0) {
|
||||
perror("open()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* stdin */
|
||||
if (dup2(fdin, 0) < 0) {
|
||||
perror("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* stdin */
|
||||
if (dup2(fdin,0) < 0) {
|
||||
perror("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/* stdout */
|
||||
if (dup2(fd,1) < 0) {
|
||||
perror("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
if (dup2(fd, 1) < 0) {
|
||||
perror("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* stderr */
|
||||
if (dup2(fd,2) < 0) {
|
||||
perror("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
/* stderr */
|
||||
if (dup2(fd, 2) < 0) {
|
||||
perror("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
close(fd);
|
||||
|
||||
|
||||
}
|
||||
@@ -102,26 +103,26 @@ void daemonize(char *logfile) {
|
||||
|
||||
#endif
|
||||
|
||||
char * uwsgi_get_cwd() {
|
||||
char *uwsgi_get_cwd() {
|
||||
|
||||
int newsize = 256 ;
|
||||
char *cwd ;
|
||||
int newsize = 256;
|
||||
char *cwd;
|
||||
|
||||
cwd = malloc(newsize);
|
||||
if (cwd == NULL) {
|
||||
perror("malloc()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (getcwd(cwd, newsize) == NULL) {
|
||||
newsize = errno;
|
||||
fprintf(stderr,"need a bigger buffer (%d bytes) for getcwd(). doing reallocation.\n", newsize);
|
||||
fprintf(stderr, "need a bigger buffer (%d bytes) for getcwd(). doing reallocation.\n", newsize);
|
||||
free(cwd);
|
||||
cwd = malloc(newsize);
|
||||
if (cwd == NULL) {
|
||||
perror("malloc()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (getcwd(cwd, newsize) == NULL) {
|
||||
perror("getcwd()");
|
||||
exit(1);
|
||||
@@ -129,5 +130,5 @@ char * uwsgi_get_cwd() {
|
||||
}
|
||||
|
||||
return cwd;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/* uWSGI */
|
||||
|
||||
/* indent -i8 -br -brs -brf -l0 -npsl -nip -npcs */
|
||||
|
||||
|
||||
#define UWSGI_VERSION "0.9.5-dev"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -9,13 +10,21 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#ifdef UWSGI_SCTP
|
||||
#include <netinet/sctp.h>
|
||||
#endif
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/file.h>
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include <poll.h>
|
||||
#include <sys/uio.h>
|
||||
@@ -28,36 +37,101 @@
|
||||
#include <sys/resource.h>
|
||||
|
||||
#ifndef UNBIT
|
||||
#ifndef ROCK_SOLID
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <libkern/OSAtomic.h>
|
||||
#include <mach/task.h>
|
||||
#include <mach/mach_init.h>
|
||||
#include <libkern/OSAtomic.h>
|
||||
#include <mach/task.h>
|
||||
#include <mach/mach_init.h>
|
||||
#endif
|
||||
|
||||
#ifdef UNBIT
|
||||
#undef _XOPEN_SOURCE
|
||||
#include "unbit.h"
|
||||
#endif
|
||||
|
||||
#ifdef _POSIX_C_SOURCE
|
||||
#undef _POSIX_C_SOURCE
|
||||
#undef _POSIX_C_SOURCE
|
||||
#endif
|
||||
#ifdef __sun__
|
||||
#undef _FILE_OFFSET_BITS
|
||||
#define WAIT_ANY (-1)
|
||||
#endif
|
||||
|
||||
#define MAX_PYARGV 10
|
||||
|
||||
#ifdef __linux__
|
||||
#include <sys/sendfile.h>
|
||||
#endif
|
||||
|
||||
#undef _XOPEN_SOURCE
|
||||
#include <Python.h>
|
||||
|
||||
#if PY_MINOR_VERSION == 4 && PY_MAJOR_VERSION == 2
|
||||
#define Py_ssize_t int
|
||||
#endif
|
||||
|
||||
#if PY_MAJOR_VERSION > 2
|
||||
#define PYTHREE
|
||||
#endif
|
||||
|
||||
/* this value are taken from nginx */
|
||||
#if defined(__apple__) || defined(__freebsd__)
|
||||
#define UWSGI_LISTEN_QUEUE -1
|
||||
#else
|
||||
#define UWSGI_LISTEN_QUEUE 511
|
||||
#endif
|
||||
|
||||
PyAPI_FUNC(PyObject *) PyMarshal_WriteObjectToString(PyObject *, int);
|
||||
PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
|
||||
|
||||
#define MAX_CLUSTER_NODES 100
|
||||
|
||||
#define UWSGI_NODE_OK 0
|
||||
#define UWSGI_NODE_FAILED 1
|
||||
|
||||
#define LONG_ARGS_PIDFILE 17001
|
||||
#define LONG_ARGS_CHROOT 17002
|
||||
#define LONG_ARGS_GID 17003
|
||||
#define LONG_ARGS_UID 17004
|
||||
#define LONG_ARGS_PYTHONPATH 17005
|
||||
#define LONG_ARGS_PASTE 17006
|
||||
#define LONG_ARGS_CHECK_INTERVAL 17007
|
||||
#define LONG_ARGS_PYARGV 17008
|
||||
#define LONG_ARGS_LIMIT_AS 17009
|
||||
#define LONG_ARGS_UDP 17010
|
||||
#define LONG_ARGS_WSGI_FILE 17011
|
||||
#define LONG_ARGS_ERLANG 17012
|
||||
#define LONG_ARGS_ERLANG_COOKIE 17013
|
||||
#define LONG_ARGS_BINARY_PATH 17014
|
||||
#define LONG_ARGS_PROXY 17015
|
||||
#define LONG_ARGS_PROXY_NODE 17016
|
||||
#define LONG_ARGS_PROXY_MAX_CONNECTIONS 17017
|
||||
#define LONG_ARGS_VERSION 17018
|
||||
#define LONG_ARGS_SNMP 17019
|
||||
#define LONG_ARGS_SNMP_COMMUNITY 17020
|
||||
|
||||
#define UWSGI_CLEAR_STATUS uwsgi.workers[uwsgi.mywid].status = 0
|
||||
|
||||
#define UWSGI_STATUS_IN_REQUEST 1 << 0
|
||||
#define UWSGI_IS_IN_REQUEST uwsgi.workers[uwsgi.mywid].status & UWSGI_STATUS_IN_REQUEST
|
||||
#define UWSGI_SET_IN_REQUEST uwsgi.workers[uwsgi.mywid].status |= UWSGI_STATUS_IN_REQUEST
|
||||
#define UWSGI_UNSET_IN_REQUEST uwsgi.workers[uwsgi.mywid].status ^= UWSGI_STATUS_IN_REQUEST
|
||||
|
||||
#define UWSGI_STATUS_BLOCKING 1 << 1
|
||||
#define UWSGI_IS_BLOCKING uwsgi.workers[uwsgi.mywid].status & UWSGI_STATUS_BLOCKING
|
||||
#define UWSGI_SET_BLOCKING uwsgi.workers[uwsgi.mywid].status |= UWSGI_STATUS_BLOCKING
|
||||
#define UWSGI_UNSET_BLOCKING uwsgi.workers[uwsgi.mywid].status ^= UWSGI_STATUS_BLOCKING
|
||||
|
||||
#define UWSGI_STATUS_LOCKING 1 << 2
|
||||
#define UWSGI_IS_LOCKING uwsgi.workers[uwsgi.mywid].status & UWSGI_STATUS_LOCKING
|
||||
#define UWSGI_SET_LOCKING uwsgi.workers[uwsgi.mywid].status |= UWSGI_STATUS_LOCKING
|
||||
#define UWSGI_UNSET_LOCKING uwsgi.workers[uwsgi.mywid].status ^= UWSGI_STATUS_LOCKING
|
||||
|
||||
#define UWSGI_STATUS_ERLANGING 1 << 3
|
||||
#define UWSGI_IS_ERLANGING uwsgi.workers[uwsgi.mywid].status & UWSGI_STATUS_ERLANGING
|
||||
#define UWSGI_SET_ERLANGING uwsgi.workers[uwsgi.mywid].status |= UWSGI_STATUS_ERLANGING
|
||||
#define UWSGI_UNSET_ERLANGING uwsgi.workers[uwsgi.mywid].status ^= UWSGI_STATUS_ERLANGING
|
||||
|
||||
#ifdef __linux__
|
||||
#include <endian.h>
|
||||
@@ -68,220 +142,336 @@ PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
|
||||
#include <machine/endian.h>
|
||||
#endif
|
||||
|
||||
#define UWSGI_OPTION_LOGGING 0
|
||||
#define UWSGI_OPTION_MAX_REQUESTS 1
|
||||
#define UWSGI_OPTION_SOCKET_TIMEOUT 2
|
||||
#define UWSGI_OPTION_MEMORY_DEBUG 3
|
||||
#define UWSGI_OPTION_MASTER_INTERVAL 4
|
||||
#define UWSGI_OPTION_HARAKIRI 5
|
||||
#define UWSGI_OPTION_CGI_MODE 6
|
||||
#define UWSGI_OPTION_THREADS 7
|
||||
#define UWSGI_OPTION_REAPER 8
|
||||
|
||||
#ifdef UNBIT
|
||||
#define UWSGI_MODIFIER_HT_S 1
|
||||
#define UWSGI_MODIFIER_HT_M 2
|
||||
#define UWSGI_MODIFIER_HT_H 3
|
||||
#undef _XOPEN_SOURCE
|
||||
#endif
|
||||
|
||||
#define UWSGI_MODIFIER_SPOOL_REQUEST 17
|
||||
#define UWSGI_MODIFIER_FASTFUNC 26
|
||||
#define UWSGI_MODIFIER_MANAGE_PATH_INFO 30
|
||||
#define UWSGI_MODIFIER_MESSAGE 31
|
||||
#define UWSGI_MODIFIER_MESSAGE_ARRAY 32
|
||||
#define UWSGI_MODIFIER_MESSAGE_MARSHAL 33
|
||||
#define UWSGI_MODIFIER_PING 100
|
||||
#define UWSGI_MODIFIER_ADMIN_REQUEST 10
|
||||
#define UWSGI_MODIFIER_SPOOL_REQUEST 17
|
||||
#define UWSGI_MODIFIER_FASTFUNC 26
|
||||
#define UWSGI_MODIFIER_MANAGE_PATH_INFO 30
|
||||
#define UWSGI_MODIFIER_MESSAGE 31
|
||||
#define UWSGI_MODIFIER_MESSAGE_ARRAY 32
|
||||
#define UWSGI_MODIFIER_MESSAGE_MARSHAL 33
|
||||
#define UWSGI_MODIFIER_MULTICAST_ANNOUNCE 73
|
||||
#define UWSGI_MODIFIER_MULTICAST 74
|
||||
#define UWSGI_MODIFIER_PING 100
|
||||
|
||||
#define UWSGI_MODIFIER_RESPONSE 255
|
||||
|
||||
#ifdef PYTHREE
|
||||
#define PyInt_FromLong PyLong_FromLong
|
||||
#define PyInt_AsLong PyLong_AsLong
|
||||
#define PyInt_Check PyLong_Check
|
||||
#define PyString_Check PyUnicode_Check
|
||||
#define PyString_FromStringAndSize PyUnicode_FromStringAndSize
|
||||
#define PyString_FromFormat PyUnicode_FromFormat
|
||||
#define PyString_FromString PyUnicode_FromString
|
||||
#define PyString_Size PyUnicode_GET_DATA_SIZE
|
||||
#define PyString_AsString (char *) PyUnicode_AS_UNICODE
|
||||
#define PyFile_FromFile(A,B,C,D) PyFile_FromFd(fileno((A)), (B), (C), -1, NULL, NULL, NULL, 0)
|
||||
#define PyInt_FromLong PyLong_FromLong
|
||||
#define PyInt_AsLong PyLong_AsLong
|
||||
#define PyInt_Check PyLong_Check
|
||||
#define PyString_Check PyUnicode_Check
|
||||
#define PyString_FromStringAndSize PyUnicode_FromStringAndSize
|
||||
#define PyString_FromFormat PyUnicode_FromFormat
|
||||
#define PyString_FromString PyUnicode_FromString
|
||||
#define PyString_Size PyUnicode_GET_DATA_SIZE
|
||||
#define PyString_AsString (char *) PyUnicode_AS_UNICODE
|
||||
#define PyFile_FromFile(A,B,C,D) PyFile_FromFd(fileno((A)), (B), (C), -1, NULL, NULL, NULL, 0)
|
||||
#endif
|
||||
|
||||
|
||||
#define NL_SIZE 2
|
||||
#define H_SEP_SIZE 2
|
||||
|
||||
#ifndef PAGE_SIZE
|
||||
#define PAGE_SIZE 4096
|
||||
#endif
|
||||
|
||||
#define UWSGI_RELOAD_CODE 17
|
||||
#define UWSGI_END_CODE 30
|
||||
|
||||
#define MAX_VARS 64
|
||||
|
||||
struct uwsgi_app {
|
||||
#ifndef ROCK_SOLID
|
||||
PyThreadState *interpreter ;
|
||||
PyObject *pymain_dict ;
|
||||
#endif
|
||||
|
||||
#ifdef ROCK_SOLID
|
||||
PyObject *wsgi_module;
|
||||
PyObject *wsgi_dict;
|
||||
#endif
|
||||
PyObject *wsgi_callable ;
|
||||
PyObject *wsgi_environ ;
|
||||
PyObject *wsgi_args;
|
||||
PyObject *wsgi_harakiri;
|
||||
#ifndef ROCK_SOLID
|
||||
PyObject *wsgi_sendfile;
|
||||
PyObject *wsgi_cprofile_run;
|
||||
int requests ;
|
||||
#endif
|
||||
PyThreadState *interpreter;
|
||||
PyObject *pymain_dict;
|
||||
|
||||
PyObject *wsgi_callable;
|
||||
PyObject *wsgi_environ;
|
||||
PyObject *wsgi_args;
|
||||
PyObject *wsgi_harakiri;
|
||||
|
||||
PyObject *wsgi_sendfile;
|
||||
PyObject *wsgi_cprofile_run;
|
||||
|
||||
int requests;
|
||||
|
||||
};
|
||||
|
||||
struct __attribute__ ((packed)) wsgi_request {
|
||||
uint8_t modifier;
|
||||
uint16_t size;
|
||||
uint8_t modifier_arg;
|
||||
// temporary attr
|
||||
|
||||
int app_id;
|
||||
|
||||
struct timeval start_of_request;
|
||||
struct timeval end_of_request;
|
||||
char *uri;
|
||||
unsigned short uri_len;
|
||||
char *remote_addr;
|
||||
unsigned short remote_addr_len;
|
||||
char *remote_user;
|
||||
unsigned short remote_user_len;
|
||||
char *query_string;
|
||||
unsigned short query_string_len;
|
||||
char *protocol;
|
||||
unsigned short protocol_len;
|
||||
char *method;
|
||||
unsigned short method_len;
|
||||
char *scheme;
|
||||
unsigned short scheme_len;
|
||||
char *https;
|
||||
unsigned short https_len;
|
||||
#ifdef UNBIT
|
||||
unsigned long long unbit_flags;
|
||||
#endif
|
||||
char *wsgi_script;
|
||||
unsigned short wsgi_script_len;
|
||||
char *wsgi_module;
|
||||
unsigned short wsgi_module_len;
|
||||
char *wsgi_callable;
|
||||
unsigned short wsgi_callable_len;
|
||||
char *script_name;
|
||||
unsigned short script_name_len;
|
||||
|
||||
int sendfile_fd;
|
||||
|
||||
unsigned short var_cnt;
|
||||
unsigned short header_cnt;
|
||||
|
||||
int status;
|
||||
int response_size;
|
||||
int headers_size;
|
||||
|
||||
int async_status;
|
||||
};
|
||||
|
||||
struct uwsgi_server {
|
||||
|
||||
char *pyhome;
|
||||
#ifndef ROCK_SOLID
|
||||
|
||||
int has_threads;
|
||||
int wsgi_cnt;
|
||||
int default_app;
|
||||
int enable_profiler;
|
||||
PyThreadState *_save;
|
||||
#ifndef UNBIT
|
||||
char *chroot;
|
||||
gid_t gid;
|
||||
uid_t uid;
|
||||
#endif
|
||||
int manage_next_request;
|
||||
int in_request;
|
||||
|
||||
char *buffer;
|
||||
|
||||
int serverfd;
|
||||
#ifdef UWSGI_PROXY
|
||||
int proxyfd;
|
||||
char *proxy_socket_name;
|
||||
#endif
|
||||
|
||||
struct rlimit rl;
|
||||
|
||||
char *binary_path;
|
||||
|
||||
int is_a_reload;
|
||||
|
||||
char *socket_name;
|
||||
char *udp_socket;
|
||||
#ifdef UWSGI_ERLANG
|
||||
char *erlang_node;
|
||||
char *erlang_cookie;
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_SNMP
|
||||
int snmp;
|
||||
char *snmp_community;
|
||||
#endif
|
||||
|
||||
// iovec
|
||||
struct iovec *hvec;
|
||||
|
||||
int to_heaven;
|
||||
int to_hell;
|
||||
|
||||
int buffer_size;
|
||||
|
||||
int master_process;
|
||||
|
||||
int no_defer_accept;
|
||||
|
||||
int page_size;
|
||||
|
||||
char *sync_page;
|
||||
int synclog;
|
||||
|
||||
char *test_module;
|
||||
|
||||
char *pidfile;
|
||||
|
||||
int numproc;
|
||||
|
||||
int max_vars ;
|
||||
int vec_size ;
|
||||
int max_vars;
|
||||
int vec_size;
|
||||
|
||||
int request_logging;
|
||||
|
||||
char *sharedarea ;
|
||||
#ifndef __OpenBSD__
|
||||
void *sharedareamutex ;
|
||||
#endif
|
||||
int sharedareasize ;
|
||||
char *sharedarea;
|
||||
void *sharedareamutex;
|
||||
int sharedareasize;
|
||||
|
||||
/* the list of workers */
|
||||
struct uwsgi_worker *workers ;
|
||||
struct uwsgi_worker *workers;
|
||||
|
||||
pid_t mypid;
|
||||
int mywid;
|
||||
|
||||
struct timeval start_tv;
|
||||
|
||||
#ifndef UNBIT
|
||||
#ifndef ROCK_SOLID
|
||||
int cgi_mode;
|
||||
#endif
|
||||
int abstract_socket;
|
||||
int chmod_socket;
|
||||
int listen_queue;
|
||||
#ifndef ROCK_SOLID
|
||||
|
||||
#ifdef UWSGI_XML
|
||||
char *xml_config;
|
||||
#endif
|
||||
|
||||
char *python_path[64];
|
||||
int python_path_cnt;
|
||||
#endif
|
||||
char *pyargv;
|
||||
#endif
|
||||
|
||||
#ifndef ROCK_SOLID
|
||||
char *wsgi_config;
|
||||
#endif
|
||||
char *paste;
|
||||
char *wsgi_file;
|
||||
|
||||
#ifndef ROCK_SOLID
|
||||
int single_interpreter;
|
||||
int py_optimize;
|
||||
|
||||
PyObject *py_sendfile ;
|
||||
PyObject *embedded_dict ;
|
||||
PyObject *embedded_args ;
|
||||
PyObject *fastfuncslist ;
|
||||
PyObject *py_sendfile;
|
||||
PyObject *embedded_dict;
|
||||
PyObject *embedded_args;
|
||||
PyObject *fastfuncslist;
|
||||
|
||||
PyObject *workers_tuple ;
|
||||
PyObject *workers_tuple;
|
||||
|
||||
PyThreadState *main_thread ;
|
||||
#endif
|
||||
PyThreadState *main_thread;
|
||||
|
||||
struct pollfd poll;
|
||||
|
||||
int harakiri_timeout;
|
||||
int socket_timeout;
|
||||
struct uwsgi_shared *shared;
|
||||
|
||||
#ifndef ROCK_SOLID
|
||||
int memory_debug;
|
||||
#endif
|
||||
|
||||
#ifndef ROCK_SOLID
|
||||
struct uwsgi_app wsgi_apps[64];
|
||||
PyObject *py_apps;
|
||||
|
||||
#ifdef UWSGI_ERLANG
|
||||
int erlang_nodes;
|
||||
int erlangfd;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct uwsgi_cluster_node {
|
||||
char name[101];
|
||||
|
||||
struct __attribute__((packed)) uwsgi_worker {
|
||||
int id ;
|
||||
struct sockaddr_in ucn_addr;
|
||||
|
||||
int workers;
|
||||
int connections;
|
||||
int status;
|
||||
|
||||
time_t last_seen;
|
||||
int errors;
|
||||
};
|
||||
|
||||
#ifdef UWSGI_SNMP
|
||||
struct uwsgi_snmp_custom_value {
|
||||
uint8_t type;
|
||||
uint64_t val;
|
||||
};
|
||||
|
||||
struct uwsgi_snmp_server_value {
|
||||
uint8_t type;
|
||||
uint64_t *val;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct uwsgi_shared {
|
||||
|
||||
// vga 80x25 specific !
|
||||
char warning_message[81];
|
||||
|
||||
int (*hooks[256]) (struct uwsgi_server *, struct wsgi_request *);
|
||||
void (*after_hooks[256]) (struct uwsgi_server *, struct wsgi_request *);
|
||||
uint32_t options[256];
|
||||
|
||||
struct uwsgi_cluster_node nodes[MAX_CLUSTER_NODES];
|
||||
|
||||
#ifdef UWSGI_SPOOLER
|
||||
pid_t spooler_pid;
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_PROXY
|
||||
pid_t proxy_pid;
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_SNMP
|
||||
char snmp_community[72 + 1];
|
||||
struct uwsgi_snmp_server_value snmp_gvalue[100];
|
||||
struct uwsgi_snmp_custom_value snmp_value[100];
|
||||
|
||||
#define SNMP_COUNTER32 0x41
|
||||
#define SNMP_GAUGE 0x42
|
||||
#define SNMP_COUNTER64 0x46
|
||||
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
struct uwsgi_worker {
|
||||
int id;
|
||||
pid_t pid;
|
||||
uint64_t status;
|
||||
|
||||
int i_have_gil;
|
||||
|
||||
time_t last_spawn;
|
||||
unsigned long long requests;
|
||||
unsigned long long failed_requests;
|
||||
uint64_t respawn_count;
|
||||
|
||||
uint64_t requests;
|
||||
uint64_t failed_requests;
|
||||
|
||||
time_t harakiri;
|
||||
unsigned long long respawn_count;
|
||||
|
||||
unsigned long long vsz_size;
|
||||
unsigned long long rss_size;
|
||||
uint64_t vsz_size;
|
||||
uint64_t rss_size;
|
||||
|
||||
double running_time;
|
||||
double last_running_time;
|
||||
|
||||
int manage_next_request;
|
||||
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) uwsgi_header {
|
||||
uint8_t modifier1;
|
||||
uint16_t pktsize ;
|
||||
uint8_t modifier2;
|
||||
struct __attribute__ ((packed)) uwsgi_header {
|
||||
uint8_t modifier1;
|
||||
uint16_t pktsize;
|
||||
uint8_t modifier2;
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) wsgi_request {
|
||||
uint8_t modifier;
|
||||
uint16_t size ;
|
||||
uint8_t modifier_arg;
|
||||
// temporary attr
|
||||
#ifndef ROCK_SOLID
|
||||
int app_id ;
|
||||
#endif
|
||||
struct timeval start_of_request ;
|
||||
char *uri;
|
||||
unsigned short uri_len;
|
||||
char *remote_addr;
|
||||
unsigned short remote_addr_len;
|
||||
char *remote_user;
|
||||
unsigned short remote_user_len;
|
||||
char *query_string;
|
||||
unsigned short query_string_len;
|
||||
char *protocol;
|
||||
unsigned short protocol_len;
|
||||
char *method;
|
||||
unsigned short method_len;
|
||||
#ifdef UNBIT
|
||||
unsigned long long unbit_flags;
|
||||
#endif
|
||||
#ifndef ROCK_SOLID
|
||||
char *wsgi_script;
|
||||
unsigned short wsgi_script_len;
|
||||
char *wsgi_module;
|
||||
unsigned short wsgi_module_len;
|
||||
char *wsgi_callable;
|
||||
unsigned short wsgi_callable_len;
|
||||
char *script_name;
|
||||
unsigned short script_name_len;
|
||||
int sendfile_fd;
|
||||
#endif
|
||||
unsigned short var_cnt;
|
||||
unsigned short header_cnt;
|
||||
int status;
|
||||
int response_size;
|
||||
int headers_size;
|
||||
};
|
||||
|
||||
|
||||
|
||||
char *uwsgi_get_cwd(void);
|
||||
|
||||
void warn_pipe(void);
|
||||
void goodbye_cruel_world(void);
|
||||
void gracefully_kill(void);
|
||||
void reap_them_all(void);
|
||||
@@ -289,35 +479,48 @@ void kill_them_all(void);
|
||||
void grace_them_all(void);
|
||||
void reload_me(void);
|
||||
void end_me(void);
|
||||
int bind_to_unix(char *, int, int , int );
|
||||
int bind_to_tcp(char *, int , char *);
|
||||
int bind_to_unix(char *, int, int, int);
|
||||
int bind_to_tcp(char *, int, char *);
|
||||
int bind_to_udp(char *);
|
||||
int timed_connect(struct pollfd *, const struct sockaddr *, int, int);
|
||||
int connect_to_tcp(char *, int, int);
|
||||
#ifdef UWSGI_SCTP
|
||||
int bind_to_sctp(char *, int, char *);
|
||||
#endif
|
||||
#ifndef UNBIT
|
||||
void daemonize(char *);
|
||||
#endif
|
||||
void log_request(void) ;
|
||||
#ifndef ROCK_SOLID
|
||||
void get_memusage(void) ;
|
||||
#endif
|
||||
void harakiri(void) ;
|
||||
void log_request(struct wsgi_request *);
|
||||
void get_memusage(void);
|
||||
void harakiri(void);
|
||||
#ifndef UNBIT
|
||||
void stats(void) ;
|
||||
void stats(void);
|
||||
#endif
|
||||
void init_uwsgi_vars(void);
|
||||
void init_uwsgi_embedded_module(void);
|
||||
|
||||
#ifndef UNBIT
|
||||
void uwsgi_xml_config(void);
|
||||
#ifdef UWSGI_XML
|
||||
void uwsgi_xml_config(struct wsgi_request *, struct option *);
|
||||
#endif
|
||||
|
||||
#ifndef ROCK_SOLID
|
||||
void uwsgi_wsgi_config(void);
|
||||
#endif
|
||||
void uwsgi_paste_config(void);
|
||||
void uwsgi_wsgi_file_config(void);
|
||||
|
||||
void internal_server_error(int, char *);
|
||||
|
||||
void init_uwsgi_module_sharedarea(PyObject *);
|
||||
void init_uwsgi_module_advanced(PyObject *);
|
||||
#ifdef UWSGI_SPOOLER
|
||||
void init_uwsgi_module_spooler(PyObject *);
|
||||
#endif
|
||||
|
||||
#ifndef ROCK_SOLID
|
||||
#ifdef UWSGI_SNMP
|
||||
void manage_snmp(int, uint8_t *, int, struct sockaddr_in *);
|
||||
void snmp_init(void);
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_SPOOLER
|
||||
int spool_request(char *, int, char *, int);
|
||||
void spooler(PyObject *);
|
||||
pid_t spooler_start(int, PyObject *);
|
||||
@@ -326,15 +529,58 @@ pid_t spooler_start(int, PyObject *);
|
||||
void set_harakiri(int);
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
uint16_t uwsgi_swap16( uint16_t );
|
||||
uint16_t uwsgi_swap16(uint16_t);
|
||||
#endif
|
||||
|
||||
#ifndef ROCK_SOLID
|
||||
int init_uwsgi_app(PyObject *, PyObject *) ;
|
||||
int init_uwsgi_app(PyObject *, PyObject *);
|
||||
|
||||
PyObject *uwsgi_send_message(const char *, int, uint8_t, uint8_t, char *, int, int);
|
||||
|
||||
#ifdef UWSGI_UDP
|
||||
ssize_t send_udp_message(uint8_t, char *, char *, uint16_t);
|
||||
#endif
|
||||
|
||||
PyObject *uwsgi_send_message(char *, int, uint8_t, uint8_t, char *, int, int);
|
||||
|
||||
int uwsgi_parse_response(struct pollfd*, int, struct uwsgi_header *, char *);
|
||||
int uwsgi_parse_response(struct pollfd *, int, struct uwsgi_header *, char *);
|
||||
int uwsgi_parse_vars(struct uwsgi_server *, struct wsgi_request *);
|
||||
|
||||
int uwsgi_enqueue_message(char *, int, uint8_t, uint8_t, char *, int, int);
|
||||
|
||||
/* included HOOKS */
|
||||
int uwsgi_request_wsgi(struct uwsgi_server *, struct wsgi_request *);
|
||||
void uwsgi_after_request_wsgi(struct uwsgi_server *, struct wsgi_request *);
|
||||
|
||||
int uwsgi_request_admin(struct uwsgi_server *, struct wsgi_request *);
|
||||
#ifdef UWSGI_SPOOLER
|
||||
int uwsgi_request_spooler(struct uwsgi_server *, struct wsgi_request *);
|
||||
#endif
|
||||
int uwsgi_request_fastfunc(struct uwsgi_server *, struct wsgi_request *);
|
||||
int uwsgi_request_marshal(struct uwsgi_server *, struct wsgi_request *);
|
||||
int uwsgi_request_ping(struct uwsgi_server *, struct wsgi_request *);
|
||||
|
||||
#ifdef UWSGI_ERLANG
|
||||
|
||||
#include <erl_interface.h>
|
||||
#include <ei.h>
|
||||
|
||||
int init_erlang(char *, char *);
|
||||
void erlang_loop(void);
|
||||
PyObject *eterm_to_py(ETERM *);
|
||||
ETERM *py_to_eterm(PyObject *);
|
||||
|
||||
#endif
|
||||
|
||||
void manage_opt(int, char *);
|
||||
|
||||
#ifdef UWSGI_PROXY
|
||||
void uwsgi_proxy(int);
|
||||
pid_t proxy_start(int);
|
||||
#endif
|
||||
|
||||
void uwsgi_cluster_add_node(char *, int);
|
||||
int uwsgi_ping_node(int, struct wsgi_request *);
|
||||
|
||||
struct http_status_codes {
|
||||
char key[3];
|
||||
char *message;
|
||||
int message_size;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
#include "uwsgi.h"
|
||||
|
||||
/* uwsgi PING|100 */
|
||||
int uwsgi_request_ping(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
|
||||
char len;
|
||||
|
||||
fprintf(stderr, "PING\n");
|
||||
wsgi_req->modifier_arg = 1;
|
||||
wsgi_req->size = 0;
|
||||
|
||||
len = strlen(uwsgi->shared->warning_message);
|
||||
if (len > 0) {
|
||||
// endianess check is not needed as the warning message can be max 80 chars
|
||||
wsgi_req->size = len;
|
||||
}
|
||||
if (write(uwsgi->poll.fd, wsgi_req, 4) != 4) {
|
||||
perror("write()");
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
if (write(uwsgi->poll.fd, uwsgi->shared->warning_message, len)
|
||||
!= len) {
|
||||
perror("write()");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* uwsgi ADMIN|10 */
|
||||
int uwsgi_request_admin(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
|
||||
uint32_t opt_value = 0;
|
||||
int i;
|
||||
|
||||
if (wsgi_req->size >= 4) {
|
||||
memcpy(&opt_value, uwsgi->buffer, 4);
|
||||
// TODO: check endianess
|
||||
}
|
||||
fprintf(stderr, "setting internal option %d to %d\n", wsgi_req->modifier_arg, opt_value);
|
||||
uwsgi->shared->options[wsgi_req->modifier_arg] = opt_value;
|
||||
wsgi_req->modifier = 255;
|
||||
wsgi_req->size = 0;
|
||||
wsgi_req->modifier_arg = 1;
|
||||
i = write(uwsgi->poll.fd, wsgi_req, 4);
|
||||
if (i != 4) {
|
||||
perror("write()");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* uwsgi FASTFUNC|26 */
|
||||
int uwsgi_request_fastfunc(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
|
||||
|
||||
PyObject *zero, *func_result, *fchunk, *func_chunks;
|
||||
|
||||
zero = PyList_GetItem(uwsgi->fastfuncslist, wsgi_req->modifier_arg);
|
||||
if (zero) {
|
||||
fprintf(stderr, "managing fastfunc %d\n", wsgi_req->modifier_arg);
|
||||
func_result = PyEval_CallObject(zero, NULL);
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Print();
|
||||
}
|
||||
if (func_result) {
|
||||
func_chunks = PyObject_GetIter(func_result);
|
||||
if (func_chunks) {
|
||||
while ((fchunk = PyIter_Next(func_chunks))) {
|
||||
if (PyString_Check(fchunk)) {
|
||||
wsgi_req->response_size += write(uwsgi->poll.fd, PyString_AsString(fchunk), PyString_Size(fchunk));
|
||||
}
|
||||
Py_DECREF(fchunk);
|
||||
}
|
||||
Py_DECREF(func_chunks);
|
||||
}
|
||||
Py_DECREF(func_result);
|
||||
}
|
||||
}
|
||||
PyErr_Clear();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* uwsgi MARSHAL|33 */
|
||||
int uwsgi_request_marshal(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
|
||||
PyObject *func_result;
|
||||
|
||||
PyObject *umm = PyDict_GetItemString(uwsgi->embedded_dict,
|
||||
"message_manager_marshal");
|
||||
if (umm) {
|
||||
PyObject *ummo = PyMarshal_ReadObjectFromString(uwsgi->buffer,
|
||||
wsgi_req->size);
|
||||
if (ummo) {
|
||||
if (!PyTuple_SetItem(uwsgi->embedded_args, 0, ummo)) {
|
||||
if (!PyTuple_SetItem(uwsgi->embedded_args, 1, PyInt_FromLong(wsgi_req->modifier_arg))) {
|
||||
func_result = PyEval_CallObject(umm, uwsgi->embedded_args);
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Print();
|
||||
}
|
||||
if (func_result) {
|
||||
PyObject *marshalled = PyMarshal_WriteObjectToString(func_result, 1);
|
||||
if (!marshalled) {
|
||||
PyErr_Print();
|
||||
}
|
||||
else {
|
||||
if (PyString_Size(marshalled) <= 0xFFFF) {
|
||||
wsgi_req->size = (uint16_t)
|
||||
PyString_Size(marshalled);
|
||||
if (write(uwsgi->poll.fd, wsgi_req, 4) == 4) {
|
||||
if (write(uwsgi->poll.fd, PyString_AsString(marshalled), wsgi_req->size) != wsgi_req->size) {
|
||||
perror("write()");
|
||||
}
|
||||
}
|
||||
else {
|
||||
perror("write()");
|
||||
}
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "marshalled object is too big. skip\n");
|
||||
}
|
||||
Py_DECREF(marshalled);
|
||||
}
|
||||
Py_DECREF(func_result);
|
||||
}
|
||||
}
|
||||
}
|
||||
//Py_DECREF(ummo);
|
||||
}
|
||||
}
|
||||
PyErr_Clear();
|
||||
|
||||
return 0;
|
||||
}
|
||||
+586
-426
File diff suppressed because it is too large
Load Diff
+218
@@ -0,0 +1,218 @@
|
||||
# uWSGI configuration
|
||||
|
||||
XML=True
|
||||
SNMP=True
|
||||
SCTP=False
|
||||
ERLANG=False
|
||||
SPOOLER=True
|
||||
EMBEDDED=True
|
||||
UDP=True
|
||||
MULTICAST=True
|
||||
THREADING=True
|
||||
SENDFILE=True
|
||||
PROFILER=True
|
||||
NAGIOS=True
|
||||
PROXY=True
|
||||
MINTERPRETERS=True
|
||||
PLUGINS = []
|
||||
UWSGI_BIN_NAME = 'uwsgi'
|
||||
GCC='gcc'
|
||||
|
||||
|
||||
|
||||
|
||||
# end of configuration
|
||||
|
||||
import os
|
||||
uwsgi_os = os.uname()[0]
|
||||
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
gcc_list = ['utils', 'protocol', 'socket', 'logging', 'wsgi_handlers', 'uwsgi_handlers', 'uwsgi']
|
||||
|
||||
# large file support
|
||||
cflags = ['-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64']
|
||||
ldflags = ['-lpthread', '-rdynamic']
|
||||
|
||||
def spcall(cmd):
|
||||
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
|
||||
|
||||
if p.wait() == 0:
|
||||
return p.stdout.read().rstrip().decode()
|
||||
else:
|
||||
return None
|
||||
|
||||
def add_o(x):
|
||||
if x == 'uwsgi':
|
||||
x = 'main'
|
||||
x = x + '.o'
|
||||
return x
|
||||
|
||||
|
||||
def build_uwsgi(bin_name):
|
||||
print("*** uWSGI compiling ***")
|
||||
for file in gcc_list:
|
||||
objfile = file
|
||||
if objfile == 'uwsgi':
|
||||
objfile = 'main'
|
||||
cmdline = "%s -c %s -o %s %s" % (GCC, ' '.join(cflags), objfile + '.o', file + '.c')
|
||||
print(cmdline)
|
||||
ret = os.system(cmdline)
|
||||
if ret != 0:
|
||||
sys.exit(1)
|
||||
|
||||
if len(PLUGINS) > 0:
|
||||
print("*** uWSGI embedding plugin ***")
|
||||
for plugin in PLUGINS:
|
||||
print(plugin)
|
||||
|
||||
print("*** uWSGI linking ***")
|
||||
ldline = "%s -o %s %s %s" % (GCC, bin_name, ' '.join(map(add_o, gcc_list)), ' '.join(ldflags))
|
||||
print(ldline)
|
||||
ret = os.system(ldline)
|
||||
if ret != 0:
|
||||
print("*** error linking uWSGI ***")
|
||||
sys.exit(1)
|
||||
|
||||
if bin_name.find("/") < 0:
|
||||
bin_name = './' + bin_name
|
||||
print("*** uWSGI is ready, launch it with %s ***" % bin_name)
|
||||
|
||||
|
||||
def parse_vars():
|
||||
|
||||
version = sys.version_info
|
||||
uver = "%d.%d" % (version[0], version[1])
|
||||
|
||||
pyconf = spcall("python%s-config --cflags" % uver)
|
||||
if pyconf is None:
|
||||
print("python development headers unavailable !!!!")
|
||||
sys.exit(1)
|
||||
cflags.insert(0,pyconf)
|
||||
|
||||
pyconf = spcall("python%s-config --libs" % uver)
|
||||
if pyconf is None:
|
||||
print("python development headers unavailable !!!!")
|
||||
sys.exit(1)
|
||||
ldflags.insert(0,pyconf)
|
||||
|
||||
kvm_list = ['SunOS', 'FreeBSD', 'OpenBSD', 'NetBSD', 'DragonFly']
|
||||
|
||||
if uwsgi_os == 'SunOS':
|
||||
ldflags.append('-lsendfile')
|
||||
|
||||
if uwsgi_os in kvm_list:
|
||||
ldflags.append('-lkvm')
|
||||
|
||||
if EMBEDDED:
|
||||
cflags.append('-DUWSGI_EMBEDDED')
|
||||
gcc_list.append('uwsgi_pymodule')
|
||||
|
||||
if UDP:
|
||||
cflags.append("-DUWSGI_UDP")
|
||||
|
||||
if MULTICAST:
|
||||
cflags.append("-DUWSGI_MULTICAST")
|
||||
|
||||
if MINTERPRETERS:
|
||||
cflags.append("-DUWSGI_MINTERPRETERS")
|
||||
|
||||
if NAGIOS:
|
||||
cflags.append("-DUWSGI_NAGIOS")
|
||||
|
||||
if PROXY:
|
||||
cflags.append("-DUWSGI_PROXY")
|
||||
gcc_list.append('proxy')
|
||||
|
||||
if SNMP:
|
||||
cflags.append("-DUWSGI_SNMP")
|
||||
gcc_list.append('snmp')
|
||||
|
||||
if THREADING:
|
||||
cflags.append("-DUWSGI_THREADING")
|
||||
|
||||
if PROFILER:
|
||||
cflags.append("-DUWSGI_PROFILER")
|
||||
|
||||
if SENDFILE:
|
||||
cflags.append("-DUWSGI_SENDFILE")
|
||||
|
||||
if XML:
|
||||
xmlconf = spcall('xml2-config --libs')
|
||||
if xmlconf is None:
|
||||
print("libxml2 headers unavailable. XML support will be disabled")
|
||||
else:
|
||||
ldflags.append(xmlconf)
|
||||
xmlconf = spcall("xml2-config --cflags")
|
||||
if xmlconf is None:
|
||||
print("libxml2 headers unavailable. XML support will be disabled")
|
||||
else:
|
||||
cflags.append(xmlconf)
|
||||
cflags.append("-DUWSGI_XML")
|
||||
gcc_list.append('xmlconf')
|
||||
|
||||
if ERLANG:
|
||||
cflags.append("-DUWSGI_ERLANG")
|
||||
ldflags.append("-lerl_interface -lei")
|
||||
gcc_list.append('erlang')
|
||||
|
||||
if SCTP:
|
||||
ldflags.append("-lsctp")
|
||||
cflags.append("-DUWSGI_SCTP")
|
||||
|
||||
if SPOOLER:
|
||||
cflags.append("-DUWSGI_SPOOLER")
|
||||
gcc_list.append('spooler')
|
||||
|
||||
def build_plugin(path):
|
||||
path = path.rstrip('/')
|
||||
|
||||
sys.path.insert(0, path)
|
||||
import uwsgiplugin as up
|
||||
|
||||
cflags.append(up.CFLAGS)
|
||||
ldflags.append(up.LDFLAGS)
|
||||
|
||||
cflags.insert(0, '-I.')
|
||||
|
||||
plugin_base = path + '/' + up.NAME + '_plugin'
|
||||
|
||||
gccline = "%s -fPIC -shared -o %s.so %s %s.c %s" % (GCC, plugin_base, ' '.join(cflags), plugin_base, ' '.join(ldflags))
|
||||
print(gccline)
|
||||
|
||||
ret = os.system(gccline)
|
||||
if ret != 0:
|
||||
print("*** unable to build %s plugin ***" % up.NAME)
|
||||
sys.exit(1)
|
||||
|
||||
print("*** %s plugin built and available in %s ***" % (up.NAME, plugin_base + '.so'))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
cmd = sys.argv[1]
|
||||
except:
|
||||
print("please specify an argument")
|
||||
sys.exit(1)
|
||||
|
||||
if cmd == '--cflags':
|
||||
print(' '.join(cflags))
|
||||
if cmd == '--ldflags':
|
||||
print(' '.join(ldflags))
|
||||
elif cmd == '--build':
|
||||
parse_vars()
|
||||
build_uwsgi(UWSGI_BIN_NAME)
|
||||
elif cmd == '--plugin':
|
||||
parse_vars()
|
||||
build_plugin(sys.argv[2])
|
||||
else:
|
||||
print("unknown uwsgiconfig command")
|
||||
sys.exit(1)
|
||||
|
||||
+497
@@ -0,0 +1,497 @@
|
||||
#include "uwsgi.h"
|
||||
|
||||
static int uwsgi_sendfile(struct uwsgi_server *, int, int);
|
||||
|
||||
int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
|
||||
|
||||
char *ptrbuf;
|
||||
char *bufferend;
|
||||
uint16_t strsize = 0;
|
||||
FILE *wsgi_file;
|
||||
int i;
|
||||
|
||||
struct uwsgi_app *wi;
|
||||
|
||||
PyObject *zero, *wsgi_socket;
|
||||
|
||||
PyObject *pydictkey, *pydictvalue;
|
||||
|
||||
char *path_info;
|
||||
|
||||
PyObject *wsgi_result, *wsgi_chunks, *wchunk;
|
||||
|
||||
/* Standard WSGI request */
|
||||
if (!wsgi_req->size) {
|
||||
fprintf(stderr, "Invalid WSGI request. skip.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ptrbuf = uwsgi->buffer;
|
||||
bufferend = ptrbuf + wsgi_req->size;
|
||||
|
||||
/* set an HTTP 500 status as default */
|
||||
wsgi_req->status = 500;
|
||||
|
||||
|
||||
|
||||
while (ptrbuf < bufferend) {
|
||||
if (ptrbuf + 2 < bufferend) {
|
||||
memcpy(&strsize, ptrbuf, 2);
|
||||
#ifdef __BIG_ENDIAN__
|
||||
strsize = uwsgi_swap16(strsize);
|
||||
#endif
|
||||
ptrbuf += 2;
|
||||
if (ptrbuf + strsize < bufferend) {
|
||||
// var key
|
||||
uwsgi->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
|
||||
uwsgi->hvec[wsgi_req->var_cnt].iov_len = strsize;
|
||||
ptrbuf += strsize;
|
||||
if (ptrbuf + 2 < bufferend) {
|
||||
memcpy(&strsize, ptrbuf, 2);
|
||||
#ifdef __BIG_ENDIAN__
|
||||
strsize = uwsgi_swap16(strsize);
|
||||
#endif
|
||||
ptrbuf += 2;
|
||||
if (ptrbuf + strsize <= bufferend) {
|
||||
#ifdef UNBIT
|
||||
if (single_app_mode == 0 && !strncmp("SCRIPT_NAME", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
#else
|
||||
if (!strncmp("SCRIPT_NAME", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
#endif
|
||||
// set the request app_id
|
||||
// LOCKED SECTION
|
||||
if (strsize > 0) {
|
||||
if (uwsgi->has_threads && !uwsgi->workers[uwsgi->mywid].i_have_gil) {
|
||||
PyEval_RestoreThread(uwsgi->_save);
|
||||
uwsgi->workers[uwsgi->mywid].i_have_gil = 1;
|
||||
}
|
||||
zero = PyString_FromStringAndSize(ptrbuf, strsize);
|
||||
if (PyDict_Contains(uwsgi->py_apps, zero)) {
|
||||
wsgi_req->app_id = PyInt_AsLong(PyDict_GetItem(uwsgi->py_apps, zero));
|
||||
}
|
||||
else {
|
||||
/* unavailable app for this SCRIPT_NAME */
|
||||
wsgi_req->app_id = -1;
|
||||
}
|
||||
Py_DECREF(zero);
|
||||
if (uwsgi->has_threads && uwsgi->shared->options[UWSGI_OPTION_THREADS] == 1) {
|
||||
uwsgi->_save = PyEval_SaveThread();
|
||||
uwsgi->workers[uwsgi->mywid].i_have_gil = 0;
|
||||
}
|
||||
}
|
||||
// UNLOCK
|
||||
}
|
||||
else if (!strncmp("SERVER_PROTOCOL", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->protocol = ptrbuf;
|
||||
wsgi_req->protocol_len = strsize;
|
||||
}
|
||||
else if (!strncmp("REQUEST_URI", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->uri = ptrbuf;
|
||||
wsgi_req->uri_len = strsize;
|
||||
}
|
||||
else if (!strncmp("QUERY_STRING", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->query_string = ptrbuf;
|
||||
wsgi_req->query_string_len = strsize;
|
||||
}
|
||||
else if (!strncmp("REQUEST_METHOD", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->method = ptrbuf;
|
||||
wsgi_req->method_len = strsize;
|
||||
}
|
||||
else if (!strncmp("REMOTE_ADDR", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->remote_addr = ptrbuf;
|
||||
wsgi_req->remote_addr_len = strsize;
|
||||
}
|
||||
else if (!strncmp("REMOTE_USER", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->remote_user = ptrbuf;
|
||||
wsgi_req->remote_user_len = strsize;
|
||||
}
|
||||
else if (!strncmp("UWSGI_SCHEME", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->scheme = ptrbuf;
|
||||
wsgi_req->scheme_len = strsize;
|
||||
}
|
||||
else if (!strncmp("HTTPS", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->https = ptrbuf;
|
||||
wsgi_req->https_len = strsize;
|
||||
}
|
||||
#ifdef UNBIT
|
||||
else if (!strncmp("UNBIT_FLAGS", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->unbit_flags = *(unsigned long long *) ptrbuf;
|
||||
}
|
||||
#endif
|
||||
if (wsgi_req->var_cnt < uwsgi->vec_size - (4 + 1)) {
|
||||
wsgi_req->var_cnt++;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "max vec size reached. skip this header.\n");
|
||||
break;
|
||||
}
|
||||
// var value
|
||||
uwsgi->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
|
||||
uwsgi->hvec[wsgi_req->var_cnt].iov_len = strsize;
|
||||
if (wsgi_req->var_cnt < uwsgi->vec_size - (4 + 1)) {
|
||||
wsgi_req->var_cnt++;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "max vec size reached. skip this header.\n");
|
||||
break;
|
||||
}
|
||||
ptrbuf += strsize;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef UWSGI_THREADING
|
||||
if (uwsgi->has_threads && !uwsgi->workers[uwsgi->mywid].i_have_gil) {
|
||||
PyEval_RestoreThread(uwsgi->_save);
|
||||
uwsgi->workers[uwsgi->mywid].i_have_gil = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
wsgi_file = fdopen(uwsgi->poll.fd, "r");
|
||||
|
||||
|
||||
#ifdef UWSGI_XML
|
||||
if (wsgi_req->app_id == -1 && uwsgi->xml_config == NULL) {
|
||||
#else
|
||||
if (wsgi_req->app_id == -1 && uwsgi->wsgi_config == NULL) {
|
||||
#endif
|
||||
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
|
||||
if (!strncmp("SCRIPT_NAME", uwsgi->hvec[i].iov_base, uwsgi->hvec[i].iov_len)) {
|
||||
wsgi_req->script_name = uwsgi->hvec[i + 1].iov_base;
|
||||
wsgi_req->script_name_len = uwsgi->hvec[i + 1].iov_len;
|
||||
}
|
||||
if (!strncmp("UWSGI_SCRIPT", uwsgi->hvec[i].iov_base, uwsgi->hvec[i].iov_len)) {
|
||||
wsgi_req->wsgi_script = uwsgi->hvec[i + 1].iov_base;
|
||||
wsgi_req->wsgi_script_len = uwsgi->hvec[i + 1].iov_len;
|
||||
}
|
||||
if (!strncmp("UWSGI_MODULE", uwsgi->hvec[i].iov_base, uwsgi->hvec[i].iov_len)) {
|
||||
wsgi_req->wsgi_module = uwsgi->hvec[i + 1].iov_base;
|
||||
wsgi_req->wsgi_module_len = uwsgi->hvec[i + 1].iov_len;
|
||||
}
|
||||
if (!strncmp("UWSGI_CALLABLE", uwsgi->hvec[i].iov_base, uwsgi->hvec[i].iov_len)) {
|
||||
wsgi_req->wsgi_callable = uwsgi->hvec[i + 1].iov_base;
|
||||
wsgi_req->wsgi_callable_len = uwsgi->hvec[i + 1].iov_len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (wsgi_req->wsgi_script_len > 0 || (wsgi_req->wsgi_callable_len > 0 && wsgi_req->wsgi_module_len > 0)) {
|
||||
if ((wsgi_req->app_id = init_uwsgi_app(NULL, NULL)) == -1) {
|
||||
internal_server_error(uwsgi->poll.fd, "wsgi application not found");
|
||||
goto clean;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (wsgi_req->app_id == -1) {
|
||||
internal_server_error(uwsgi->poll.fd, "wsgi application not found");
|
||||
goto clean;
|
||||
}
|
||||
|
||||
|
||||
wi = &uwsgi->wsgi_apps[wsgi_req->app_id];
|
||||
|
||||
if (uwsgi->single_interpreter == 0) {
|
||||
if (!wi->interpreter) {
|
||||
internal_server_error(uwsgi->poll.fd, "wsgi application's %d interpreter not found");
|
||||
goto clean;
|
||||
}
|
||||
|
||||
// set the interpreter
|
||||
PyThreadState_Swap(wi->interpreter);
|
||||
}
|
||||
|
||||
|
||||
if (wsgi_req->protocol_len < 5) {
|
||||
fprintf(stderr, "INVALID PROTOCOL: %.*s", wsgi_req->protocol_len, wsgi_req->protocol);
|
||||
internal_server_error(uwsgi->poll.fd, "invalid HTTP protocol !!!");
|
||||
goto clean;
|
||||
}
|
||||
if (strncmp(wsgi_req->protocol, "HTTP/", 5)) {
|
||||
fprintf(stderr, "INVALID PROTOCOL: %.*s", wsgi_req->protocol_len, wsgi_req->protocol);
|
||||
internal_server_error(uwsgi->poll.fd, "invalid HTTP protocol !!!");
|
||||
goto clean;
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
|
||||
/*fprintf(stderr,"%.*s: %.*s\n", uwsgi->hvec[i].iov_len, uwsgi->hvec[i].iov_base, uwsgi->hvec[i+1].iov_len, uwsgi->hvec[i+1].iov_base); */
|
||||
pydictkey = PyString_FromStringAndSize(uwsgi->hvec[i].iov_base, uwsgi->hvec[i].iov_len);
|
||||
pydictvalue = PyString_FromStringAndSize(uwsgi->hvec[i + 1].iov_base, uwsgi->hvec[i + 1].iov_len);
|
||||
PyDict_SetItem(wi->wsgi_environ, pydictkey, pydictvalue);
|
||||
Py_DECREF(pydictkey);
|
||||
Py_DECREF(pydictvalue);
|
||||
}
|
||||
|
||||
if (wsgi_req->modifier == UWSGI_MODIFIER_MANAGE_PATH_INFO) {
|
||||
pydictkey = PyDict_GetItemString(wi->wsgi_environ, "SCRIPT_NAME");
|
||||
if (pydictkey) {
|
||||
if (PyString_Check(pydictkey)) {
|
||||
pydictvalue = PyDict_GetItemString(wi->wsgi_environ, "PATH_INFO");
|
||||
if (pydictvalue) {
|
||||
if (PyString_Check(pydictvalue)) {
|
||||
path_info = PyString_AsString(pydictvalue);
|
||||
PyDict_SetItemString(wi->wsgi_environ, "PATH_INFO", PyString_FromString(path_info + PyString_Size(pydictkey)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// set wsgi vars
|
||||
|
||||
wsgi_socket = PyFile_FromFile(wsgi_file, "wsgi_input", "r", NULL);
|
||||
PyDict_SetItemString(wi->wsgi_environ, "wsgi.input", wsgi_socket);
|
||||
Py_DECREF(wsgi_socket);
|
||||
|
||||
#ifdef UWSGI_SENDFILE
|
||||
PyDict_SetItemString(wi->wsgi_environ, "wsgi.file_wrapper", wi->wsgi_sendfile);
|
||||
#endif
|
||||
|
||||
zero = PyTuple_New(2);
|
||||
PyTuple_SetItem(zero, 0, PyInt_FromLong(1));
|
||||
PyTuple_SetItem(zero, 1, PyInt_FromLong(0));
|
||||
PyDict_SetItemString(wi->wsgi_environ, "wsgi.version", zero);
|
||||
Py_DECREF(zero);
|
||||
|
||||
zero = PyFile_FromFile(stderr, "wsgi_input", "w", NULL);
|
||||
PyDict_SetItemString(wi->wsgi_environ, "wsgi.errors", zero);
|
||||
Py_DECREF(zero);
|
||||
|
||||
PyDict_SetItemString(wi->wsgi_environ, "wsgi.run_once", Py_False);
|
||||
|
||||
PyDict_SetItemString(wi->wsgi_environ, "wsgi.multithread", Py_False);
|
||||
if (uwsgi->numproc == 1) {
|
||||
PyDict_SetItemString(wi->wsgi_environ, "wsgi.multiprocess", Py_False);
|
||||
}
|
||||
else {
|
||||
PyDict_SetItemString(wi->wsgi_environ, "wsgi.multiprocess", Py_True);
|
||||
}
|
||||
|
||||
if (wsgi_req->scheme_len > 0) {
|
||||
zero = PyString_FromStringAndSize(wsgi_req->scheme, wsgi_req->scheme_len);
|
||||
}
|
||||
else if (wsgi_req->https_len > 0) {
|
||||
if (!strncasecmp(wsgi_req->https, "on", 2) || wsgi_req->https[0] == '1') {
|
||||
zero = PyString_FromString("https");
|
||||
}
|
||||
else {
|
||||
zero = PyString_FromString("http");
|
||||
}
|
||||
}
|
||||
else {
|
||||
zero = PyString_FromString("http");
|
||||
}
|
||||
PyDict_SetItemString(wi->wsgi_environ, "wsgi.url_scheme", zero);
|
||||
Py_DECREF(zero);
|
||||
|
||||
#ifdef UNBIT
|
||||
if (wsgi_req->unbit_flags & (unsigned long long) 1) {
|
||||
if (uri_to_hex() <= 0) {
|
||||
tmp_filename[0] = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// call
|
||||
#ifdef UWSGI_PROFILER
|
||||
if (uwsgi->enable_profiler == 1) {
|
||||
wsgi_result = PyEval_CallObject(wi->wsgi_cprofile_run, wi->wsgi_args);
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Print();
|
||||
}
|
||||
if (wsgi_result) {
|
||||
Py_DECREF(wsgi_result);
|
||||
wsgi_result = PyDict_GetItemString(wi->pymain_dict, "uwsgi_out");
|
||||
}
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
|
||||
wsgi_result = PyEval_CallObject(wi->wsgi_callable, wi->wsgi_args);
|
||||
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Print();
|
||||
}
|
||||
#ifdef UWSGI_PROFILER
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
if (wsgi_result) {
|
||||
|
||||
|
||||
#ifdef UWSGI_SENDFILE
|
||||
if (wsgi_req->sendfile_fd > -1) {
|
||||
wsgi_req->response_size = uwsgi_sendfile(uwsgi, wsgi_req->sendfile_fd, uwsgi->poll.fd);
|
||||
}
|
||||
else {
|
||||
|
||||
#endif
|
||||
|
||||
wsgi_chunks = PyObject_GetIter(wsgi_result);
|
||||
if (wsgi_chunks) {
|
||||
while ((wchunk = PyIter_Next(wsgi_chunks))) {
|
||||
if (PyString_Check(wchunk)) {
|
||||
if ((i = write(uwsgi->poll.fd, PyString_AsString(wchunk), PyString_Size(wchunk))) < 0) {
|
||||
perror("write()");
|
||||
}
|
||||
wsgi_req->response_size += i;
|
||||
#ifdef UNBIT
|
||||
if (save_to_disk >= 0) {
|
||||
if (write(save_to_disk, PyString_AsString(wchunk), PyString_Size(wchunk)) < 0) {
|
||||
perror("write()");
|
||||
close(save_to_disk);
|
||||
save_to_disk = -1;
|
||||
unlinkat(tmp_dir_fd, tmp_filename, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "invalid output returned by the wsgi callable !!!\n");
|
||||
}
|
||||
Py_DECREF(wchunk);
|
||||
}
|
||||
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Print();
|
||||
}
|
||||
|
||||
#ifdef UNBIT
|
||||
else if (save_to_disk >= 0) {
|
||||
close(save_to_disk);
|
||||
save_to_disk = -1;
|
||||
fprintf(stderr, "[uWSGI cacher] output of request %llu (%.*s) on pid %d written to cache file %s\n", uwsgi->workers[0].requests + 1, wsgi_req->uri_len, wsgi_req->uri, uwsgi->mypid, tmp_filename);
|
||||
}
|
||||
#endif
|
||||
Py_DECREF(wsgi_chunks);
|
||||
}
|
||||
#ifdef UWSGI_PROFILER
|
||||
}
|
||||
if (uwsgi->enable_profiler == 0) {
|
||||
#endif
|
||||
Py_DECREF(wsgi_result);
|
||||
#ifdef UWSGI_PROFILER
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
PyDict_Clear(wi->wsgi_environ);
|
||||
wi->requests++;
|
||||
|
||||
PyErr_Clear();
|
||||
if (uwsgi->shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
|
||||
set_harakiri(0);
|
||||
}
|
||||
|
||||
if (uwsgi->single_interpreter == 0) {
|
||||
// restoring main interpreter
|
||||
PyThreadState_Swap(uwsgi->main_thread);
|
||||
}
|
||||
|
||||
clean:
|
||||
fclose(wsgi_file);
|
||||
|
||||
#ifdef UWSGI_THREADING
|
||||
if (uwsgi->has_threads && uwsgi->shared->options[UWSGI_OPTION_THREADS] == 1) {
|
||||
uwsgi->_save = PyEval_SaveThread();
|
||||
uwsgi->workers[uwsgi->mywid].i_have_gil = 0;
|
||||
}
|
||||
#endif
|
||||
uwsgi->workers[uwsgi->mywid].requests++;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_after_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (uwsgi->shared->options[UWSGI_OPTION_LOGGING])
|
||||
log_request(wsgi_req);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SENDFILE
|
||||
static int uwsgi_sendfile(struct uwsgi_server *uwsgi, int fd, int sockfd) {
|
||||
|
||||
off_t rlen;
|
||||
|
||||
#ifdef __sun__
|
||||
struct stat stat_buf;
|
||||
if (fstat(fd, &stat_buf)) {
|
||||
perror("fstat()");
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
rlen = stat_buf.st_size;
|
||||
}
|
||||
#else
|
||||
rlen = lseek(fd, 0, SEEK_END);
|
||||
#endif
|
||||
|
||||
if (rlen > 0) {
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
#if !defined(__linux__) && !defined(__sun__)
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
|
||||
if (sendfile(fd, sockfd, 0, 0, NULL, &rlen, 0)) {
|
||||
perror("sendfile()");
|
||||
}
|
||||
#elif __APPLE__
|
||||
if (sendfile(fd, sockfd, 0, &rlen, NULL, 0)) {
|
||||
perror("sendfile()");
|
||||
}
|
||||
#else
|
||||
ssize_t i = 0;
|
||||
char *no_sendfile_buf[4096];
|
||||
ssize_t jlen = 0;
|
||||
rlen = 0;
|
||||
i = 0;
|
||||
while (i < rlen) {
|
||||
jlen = read(fd, no_sendfile_buf, 4096);
|
||||
if (jlen <= 0) {
|
||||
perror("read()");
|
||||
break;
|
||||
}
|
||||
i += jlen;
|
||||
jlen = write(sockfd, no_sendfile_buf, jlen);
|
||||
if (jlen <= 0) {
|
||||
perror("write()");
|
||||
break;
|
||||
}
|
||||
rlen += jlen;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
off_t sf_ot = 0;
|
||||
rlen = sendfile(sockfd, fd, &sf_ot, rlen);
|
||||
#endif
|
||||
|
||||
}
|
||||
Py_DECREF(uwsgi->py_sendfile);
|
||||
|
||||
return rlen;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,127 @@
|
||||
#ifdef UWSGI_XML
|
||||
|
||||
#include "uwsgi.h"
|
||||
|
||||
#include <libxml/parser.h>
|
||||
#include <libxml/tree.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
void uwsgi_xml_config(struct wsgi_request *wsgi_req, struct option *long_options) {
|
||||
xmlDoc *doc = NULL;
|
||||
xmlNode *element = NULL;
|
||||
xmlNode *node = NULL;
|
||||
xmlNode *node2 = NULL;
|
||||
|
||||
xmlChar *xml_uwsgi_mountpoint = NULL;
|
||||
xmlChar *xml_uwsgi_script = NULL;
|
||||
struct option *lopt, *aopt;
|
||||
|
||||
|
||||
doc = xmlReadFile(uwsgi.xml_config, NULL, 0);
|
||||
if (doc == NULL) {
|
||||
fprintf(stderr, "[uWSGI] could not parse file %s.\n", uwsgi.xml_config);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (long_options) {
|
||||
fprintf(stderr, "[uWSGI] parsing config file %s\n", uwsgi.xml_config);
|
||||
}
|
||||
|
||||
element = xmlDocGetRootElement(doc);
|
||||
if (element == NULL) {
|
||||
fprintf(stderr, "[uWSGI] invalid xml config file.\n");
|
||||
exit(1);
|
||||
}
|
||||
if (strcmp((char *) element->name, "uwsgi")) {
|
||||
fprintf(stderr, "[uWSGI] invalid xml root element, <uwsgi> expected.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
if (long_options) {
|
||||
// first check for pythonpath
|
||||
for (node = element->children; node; node = node->next) {
|
||||
if (node->type == XML_ELEMENT_NODE) {
|
||||
lopt = long_options;
|
||||
while ((aopt = lopt)) {
|
||||
if (!aopt->name)
|
||||
break;
|
||||
if (!strcmp((char *) node->name, aopt->name)) {
|
||||
if (!node->children && aopt->has_arg) {
|
||||
fprintf(stderr, "[uWSGI] %s option need a value. skip.\n", aopt->name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (node->children) {
|
||||
if (!node->children->content && aopt->has_arg) {
|
||||
fprintf(stderr, "[uWSGI] %s option need a value. skip.\n", aopt->name);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (aopt->flag) {
|
||||
*aopt->flag = aopt->val;
|
||||
}
|
||||
else {
|
||||
if (node->children) {
|
||||
manage_opt(aopt->val, (char *) node->children->content);
|
||||
}
|
||||
else {
|
||||
manage_opt(aopt->val, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
lopt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
// ... then for wsgi apps
|
||||
for (node = element->children; node; node = node->next) {
|
||||
if (node->type == XML_ELEMENT_NODE) {
|
||||
|
||||
if (!strcmp((char *) node->name, "app")) {
|
||||
xml_uwsgi_mountpoint = xmlGetProp(node, (const xmlChar *) "mountpoint");
|
||||
if (xml_uwsgi_mountpoint == NULL) {
|
||||
fprintf(stderr, "no mountpoint defined for app. skip.\n");
|
||||
continue;
|
||||
}
|
||||
wsgi_req->script_name = (char *) xml_uwsgi_mountpoint;
|
||||
wsgi_req->script_name_len = strlen(wsgi_req->script_name);
|
||||
|
||||
for (node2 = node->children; node2; node2 = node2->next) {
|
||||
if (node2->type == XML_ELEMENT_NODE) {
|
||||
if (!strcmp((char *) node2->name, "script")) {
|
||||
if (!node2->children) {
|
||||
fprintf(stderr, "no wsgi script defined. skip.\n");
|
||||
continue;
|
||||
}
|
||||
xml_uwsgi_script = node2->children->content;
|
||||
if (xml_uwsgi_script == NULL) {
|
||||
fprintf(stderr, "no wsgi script defined. skip.\n");
|
||||
continue;
|
||||
}
|
||||
wsgi_req->wsgi_script = (char *) xml_uwsgi_script;
|
||||
wsgi_req->wsgi_script_len = strlen(wsgi_req->wsgi_script);
|
||||
init_uwsgi_app(NULL, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* We cannot free xml resources as the string pointer must be valid for all the server lifecycle */
|
||||
//xmlFreeDoc (doc);
|
||||
//xmlCleanupParser ();
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
#warning "*** XML configuration support is disabled ***"
|
||||
#endif
|
||||
Reference in New Issue
Block a user