big update: hooks and plugins

This commit is contained in:
roberto@sirius
2010-02-07 23:06:24 +01:00
parent a6b42af85a
commit e0882ed8df
12 changed files with 3077 additions and 2230 deletions
+25 -3
View File
@@ -1,7 +1,20 @@
include config
UWSGI_CFLAGS = ""
UWSGI_LD_FLAGS = ""
ifneq ($(SCTP), 'no')
UWSGI_CFLAGS = -DSCTP
UWSGI_LD_FLAGS = -lsctp
endif
CFLAGS := $(CFLAGS) $(UWSGI_CFLAGS)
LD_FLAGS := $(LD_FLAGS) $(UWSGI_LD_FLAGS)
all: clean uwsgi
uwsgi: utils.o protocol.o socket.o pymodule.o spooler.o logging.o main.o
$(CC) $(LD_FLAGS) utils.o protocol.o socket.o spooler.o logging.o pymodule.o main.o -o $(PROGRAM)
uwsgi: utils.o protocol.o socket.o pymodule.o spooler.o logging.o snmp.o wsgihandlers.o basehandlers.o main.o
$(CC) $(LD_FLAGS) utils.o protocol.o socket.o spooler.o logging.o snmp.o pymodule.o wsgihandlers.o basehandlers.o main.o -o $(PROGRAM)
utils.o: utils.c
$(CC) -c $(CFLAGS) utils.c
@@ -18,11 +31,20 @@ spooler.o: spooler.c
logging.o: logging.c
$(CC) -c $(CFLAGS) logging.c
snmp.o: snmp.c
$(CC) -c $(CFLAGS) snmp.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 logging.o main.o
rm -f utils.o protocol.o socket.o pymodule.o spooler.o logging.o snmp.o wsgihandlers.o basehandlers.o main.o
+3
View File
@@ -0,0 +1,3 @@
XML=no
SNMP=no
SCTP=yes
+18
View File
@@ -0,0 +1,18 @@
#include "../../uwsgi.h"
void uwsgi_init(struct uwsgi_server *uwsgi){
fprintf(stderr,"i am the example plugin initialization function\n");
}
int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, char *buffer) {
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));
return 0;
}
int uwsgi_after_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, char *buffer) {
fprintf(stderr,"i am the example plugin after request function\n");
return 0;
}
+436
View File
@@ -0,0 +1,436 @@
#ifndef ROCK_SOLID
#ifndef UNBIT
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
#define SNMP_SEQUENCE 0x30
#define SNMP_INTEGER 0x02
#define SNMP_STRING 0x04
#define SNMP_GET 0xA0
#define SNMP_OID 0x06
/* 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_length(uint8_t *, uint16_t *);
static int get_snmp_integer(uint8_t *, uint64_t *);
static int get_snmp_string(uint8_t *, uint16_t *, char **);
static uint64_t get_uwsgi_snmp_value(uint64_t);
static uint64_t get_uwsgi_custom_snmp_value(uint64_t);
struct uwsgi_oid {
uint64_t oid1;
uint64_t oid2;
uint64_t value;
uint64_t valuesize;
uint16_t size;
uint8_t first_byte ;
};
static int build_snmp_response(struct uwsgi_oid*, int, uint8_t *, int, uint64_t, uint64_t, char *, uint16_t);
void manage_snmp(int fd, uint8_t *buffer, int size, struct sockaddr_in *client_addr) {
uint16_t asnlen;
uint16_t oidlen;
uint64_t oid_part[2];
uint8_t what_oid_part ;
uint16_t slen;
int ptrdelta ;
uint8_t *ptr = buffer ;
struct uwsgi_oid output_oid[10];
int how_many_output_oid = 0;
uint64_t snmp_int ;
uint64_t snmp_version ;
uint64_t request_id ;
char *snmp_str ;
// skip first byte (already parsed)
ptr++;
// check total sequence size
ptrdelta = get_snmp_length(ptr, &asnlen);
if (ptrdelta <= 0)
return;
if (asnlen != size-(ptrdelta+1))
return;
ptr += ptrdelta ;
// check snmp version
if (*ptr != SNMP_INTEGER)
return;
ptr++;
ptrdelta = get_snmp_integer(ptr, &snmp_version);
if (ptrdelta <= 0)
return;
if (snmp_version > 2)
return;
if (ptr+ptrdelta >= buffer+size)
return;
ptr += ptrdelta ;
// check for community string (this must be set from the python vm using uwsgi.community)
if (*ptr != SNMP_STRING)
return;
ptr++;
ptrdelta = get_snmp_string(ptr, &slen, &snmp_str);
if (ptrdelta <= 0)
return;
if (ptr+ptrdelta >= buffer+size)
return;
// TODO check for community string
ptr += ptrdelta ;
// check for get request
if (*ptr != SNMP_GET)
return;
ptr++;
ptrdelta = get_snmp_length(ptr, &asnlen);
if (ptrdelta <= 0)
return;
if (ptr+ptrdelta >= buffer+size)
return;
if (asnlen != ( (buffer+size) - (ptr+ptrdelta) ))
return;
ptr += ptrdelta ;
// get request_id
if (*ptr != SNMP_INTEGER)
return;
ptr++; ptrdelta = get_snmp_integer(ptr, &request_id);
if (ptrdelta <= 0)
return;
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++;
ptrdelta = get_snmp_length(ptr, &asnlen);
if (ptrdelta <= 0)
return;
if (ptr+ptrdelta >= buffer+size)
return;
if (asnlen != ( (buffer+size) - (ptr+ptrdelta) ))
return;
ptr += ptrdelta ;
// now the interesting stuff: OID management
while(ptr < buffer+size && how_many_output_oid < 10) {
if (*ptr != SNMP_SEQUENCE)
return;
ptr++;
ptrdelta = get_snmp_length(ptr, &asnlen);
if (ptrdelta <= 0)
return;
if (ptr+ptrdelta >= buffer+size)
return;
// check for normal OID uWSGI size: |1.3|.6|.1|.4|.1.|35156|.17|.1/2|.x| + OID_NULL
if (asnlen < 13)
return;
ptr += ptrdelta ;
// is it an OID ?
if (*ptr != SNMP_OID)
return;
ptr++;
ptrdelta = get_snmp_length(ptr, &oidlen);
if (ptrdelta <= 0)
return;
if (ptr+ptrdelta >= buffer+size)
return;
if (oidlen > (asnlen-ptrdelta-2))
return;
ptr += ptrdelta ;
// used by the output sender
output_oid[how_many_output_oid].size = oidlen ;
// and now parse the OID !!!
if (strncmp((char *) ptr, SNMP_UWSGI_BASE, 9))
return;
ptr+=9;
// get the next two oid number
oidlen = oidlen - 9 ;
what_oid_part = 0;
while(oidlen > 0 && what_oid_part < 2) {
oid_part[what_oid_part] = 0 ;
while( (*ptr & 0x80) && oidlen > 0) {
oid_part[what_oid_part] += (oid_part[what_oid_part] * 0x80) + (*ptr^0x80) ;
ptr++;
oidlen--;
}
oid_part[what_oid_part] = (oid_part[what_oid_part] * 0x80) + *ptr;
ptr++;
oidlen--;
what_oid_part++;
}
if (oid_part[1] > 100)
return;
// check for null
if (strncmp((char *)ptr, "\x05\x00", 2))
return;
ptr+=2;
if (oid_part[0] == 1) {
output_oid[how_many_output_oid].oid1 = oid_part[0] ;
output_oid[how_many_output_oid].oid2 = oid_part[1] ;
output_oid[how_many_output_oid].value = get_uwsgi_snmp_value(oid_part[1]);
}
else if (oid_part[0] == 2) {
output_oid[how_many_output_oid].oid1 = oid_part[0] ;
output_oid[how_many_output_oid].oid2 = oid_part[1] ;
output_oid[how_many_output_oid].value = get_uwsgi_custom_snmp_value(oid_part[1]);
}
else {
return;
}
how_many_output_oid++;
}
size = build_snmp_response(output_oid, how_many_output_oid, buffer, size, request_id, snmp_version, snmp_str, slen);
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) {
return val * 300 ;
}
static uint64_t get_uwsgi_custom_snmp_value(uint64_t val) {
return val * 260 ;
}
static int get_snmp_string(uint8_t *ptr, uint16_t *strlen, char **str) {
int delta;
delta = get_snmp_length(ptr, strlen) ;
if (*strlen > 0) {
*str = (char *) ptr+delta ;
return delta + *strlen ;
}
return -1 ;
}
static int get_snmp_integer(uint8_t *ptr, uint64_t *val) {
uint16_t tlen ;
int delta,i;
delta = get_snmp_length(ptr, &tlen) ;
if (tlen > 0) {
#ifdef __BIG_ENDIAN__
for(i=0;i<tlen;i++) {
#else
for(i=tlen-1;i>=0;i--) {
#endif
val[i] = ptr[1+i];
}
return tlen + delta ;
}
return -1 ;
}
static int get_snmp_length(uint8_t *ptr, uint16_t *len) {
char tlen ;
int i ;
char *blen = (char *) len ;
*len = *ptr ;
if (*len > 127) {
tlen = *len & 0x7f ;
if (tlen > 2) {
fprintf(stderr,"unsupported snmp length\n");
return -1 ;
}
#ifdef __BIG_ENDIAN__
for(i=0;i<tlen;i++) {
blen[i] = ptr[1+i];
#else
for(i=tlen-1;i>=0;i--) {
blen[i] = ptr[1+((tlen-1)-i)];
#endif
}
return tlen+1 ;
}
else {
return 1 ;
}
}
static int build_snmp_response(struct uwsgi_oid* output_oid, int num_output_oid, uint8_t *buffer, int size, uint64_t request_id, uint64_t version, char *community, uint16_t community_len) {
static char *snmp_buffer = NULL ;
int i ;
int tmpptr = 0 ;
// calc the new size without null values
uint64_t new_size = size - (2*num_output_oid) ;
uint16_t seq_size ;
if (snmp_buffer == NULL) {
snmp_buffer = malloc(uwsgi.buffer_size);
if (!snmp_buffer) {
perror("malloc()");
return -1 ;
}
}
for(i=0;i<num_output_oid;i++) {
new_size += output_oid[i].valuesize = 1 ;
if (output_oid[i].value > 127) {
output_oid[i].valuesize++;
output_oid[i].first_byte = 0x81 ;
if (output_oid[i].value > 0xFF) {
output_oid[i].valuesize++;
output_oid[i].first_byte = 0x82 ;
}
}
new_size += output_oid[i].valuesize ;
}
fprintf(stderr,"the SNMP output size is : %llu\n", new_size);
if (new_size > uwsgi.buffer_size || new_size > 0xFFFF)
return -1;
seq_size = (uint16_t) new_size ;
snmp_buffer[0] = buffer[0];
if (seq_size > 127) {
if (seq_size > 0xff) {
snmp_buffer[1] = 0x81 ;
snmp_buffer[2] = (uint8_t) seq_size ;
tmpptr = 3 ;
}
else {
snmp_buffer[1] = 0x82 ;
#ifdef __BIG_ENDIAN__
snmp_buffer[2] = ((uint8_t *) &seq_size)[0];
snmp_buffer[3] = ((uint8_t *) &seq_size)[1];
#else
snmp_buffer[2] = ((uint8_t *) &seq_size)[1];
snmp_buffer[3] = ((uint8_t *) &seq_size)[0];
#endif
tmpptr = 4 ;
}
}
else {
tmpptr = 2 ;
snmp_buffer[1] = (uint8_t) seq_size ;
}
/*
snmp_buffer[tmpptr] = // copy version
snmp_buffer[tmpptr] = // copy community
snmp_buffer[tmpptr] = // set response
snmp_buffer[tmpptr] = // sequence size (!!!)
snmp_buffer[tmpptr] = // request_id
snmp_buffer[tmpptr] = // error
snmp_buffer[tmpptr] = // index
snmp_buffer[tmpptr] = // main sequence
snmp_buffer[tmpptr] = // OID cycle -> sequence + oid + value
*/
return -1 ;
}
#endif
#endif
+94
View File
@@ -61,6 +61,100 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
return serverfd;
}
#ifdef 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
#ifndef ROCK_SOLID
#ifndef UNBIT
int bind_to_udp(char *socket_name) {
int serverfd ;
struct sockaddr_in uws_addr;
char *udp_port ;
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);
serverfd = socket(AF_INET,SOCK_DGRAM,0);
if (serverfd < 0) {
perror("socket()");
return -1 ;
}
if (bind(serverfd, (struct sockaddr *) &uws_addr, sizeof(uws_addr) ) != 0) {
perror("bind()");
close(serverfd);
return -1 ;
}
return serverfd;
}
#endif
#endif
int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
int serverfd;
+193 -147
View File
@@ -7,285 +7,331 @@
extern char *spool_dir;
struct uwsgi_packet_header {
uint8_t modifier1;
uint16_t datasize;
uint8_t modifier2;
uint8_t modifier1;
uint16_t datasize;
uint8_t modifier2;
};
int spool_request(char *filename, int rn, char *buffer, int size) {
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_packet_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 ;
perror ("open()");
return 0;
}
#ifdef __sun__
if (lockf(fd, F_LOCK, 0)) {
perror("lockf()");
if (lockf (fd, F_LOCK, 0)) {
perror ("lockf()");
#else
if (flock(fd, LOCK_EX)) {
perror("flock()");
if (flock (fd, LOCK_EX)) {
perror ("flock()");
#endif
close(fd);
close (fd);
return 0;
}
uh.modifier1 = 17 ;
uh.modifier2 = 0 ;
uh.datasize = (uint16_t) size ;
uh.modifier1 = 17;
uh.modifier2 = 0;
uh.datasize = (uint16_t) size;
#ifdef __BIG_ENDIAN__
uh.datasize= uwsgi_swap16(uh.datasize);
uh.datasize = uwsgi_swap16 (uh.datasize);
#endif
if (write(fd, &uh, 4) != 4) {
goto clear ;
if (write (fd, &uh, 4) != 4) {
goto clear;
}
if (write(fd, buffer, size) != size) {
goto clear ;
if (write (fd, buffer, size) != size) {
goto clear;
}
close(fd);
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:
perror("write()");
unlink(filename);
close(fd);
clear:
perror ("write()");
unlink (filename);
close (fd);
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_packet_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);
}
uwsgi_module_dict = PyModule_GetDict (uwsgi_module);
if (!uwsgi_module_dict) {
fprintf (stderr, "could not get uwsgi module __dict__\n");
exit (1);
}
spool_tuple = PyTuple_New(1);
spool_tuple = PyTuple_New (1);
if (!spool_tuple) {
fprintf(stderr,"could not create spooler tuple.\n");
exit(1);
fprintf (stderr, "could not create spooler tuple.\n");
exit (1);
}
spool_env = PyDict_New();
spool_env = PyDict_New ();
if (!spool_env) {
fprintf(stderr,"could not create spooler env.\n");
exit(1);
fprintf (stderr, "could not create spooler env.\n");
exit (1);
}
if (PyTuple_SetItem(spool_tuple, 0, spool_env)) {
PyErr_Print();
exit(1);
}
if (chdir(spool_dir)) {
perror("chdir()");
exit(1);
if (PyTuple_SetItem (spool_tuple, 0, spool_env)) {
PyErr_Print ();
exit (1);
}
for(;;) {
sdir = opendir(".");
if (chdir (spool_dir)) {
perror ("chdir()");
exit (1);
}
for (;;) {
sdir = opendir (".");
if (sdir) {
while((dp = readdir(sdir)) != NULL) {
while ((dp = readdir (sdir)) != NULL) {
#ifndef __sun__
if (!strncmp("uwsgi_spoolfile_on_", dp->d_name, 19) && dp->d_type == DT_REG) {
if (!strncmp ("uwsgi_spoolfile_on_", dp->d_name, 19) && dp->d_type == DT_REG) {
#else
if (!strncmp("uwsgi_spoolfile_on_", dp->d_name, 19)) {
if (!strncmp ("uwsgi_spoolfile_on_", dp->d_name, 19)) {
struct stat sf_lstat;
if (lstat(dp->d_name, &sf_lstat)) {
if (lstat (dp->d_name, &sf_lstat)) {
continue;
}
if (!S_ISREG(sf_lstat.st_mode)) {
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");
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()");
perror ("open()");
continue;
}
}
#ifdef __sun__
if (lockf(spool_fd, F_LOCK, 0)) {
perror("lockf()");
if (lockf (spool_fd, F_LOCK, 0)) {
perror ("lockf()");
#else
if (flock(spool_fd, LOCK_EX)) {
perror("flock()");
if (flock (spool_fd, LOCK_EX)) {
perror ("flock()");
#endif
close(spool_fd);
close (spool_fd);
continue;
}
if (read(spool_fd, &uh, 4) != 4) {
perror("read()");
close(spool_fd);
if (read (spool_fd, &uh, 4) != 4) {
perror ("read()");
close (spool_fd);
continue;
}
#ifdef __BIG_ENDIAN__
uh.datasize= uwsgi_swap16(uh.datasize);
#endif
datasize = 0 ;
#ifdef __BIG_ENDIAN__
uh.datasize = uwsgi_swap16 (uh.datasize);
#endif
while( datasize < uh.datasize) {
rlen = read(spool_fd, &uwstrlen, 2) ;
datasize = 0;
while (datasize < uh.datasize) {
rlen = read (spool_fd, &uwstrlen, 2);
if (rlen != 2) {
perror("read()");
goto next_spool ;
perror ("read()");
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()");
perror ("malloc()");
goto retry_later;
}
rlen = read(spool_fd, key, uwstrlen);
rlen = read (spool_fd, key, uwstrlen);
if (rlen != uwstrlen) {
perror("read()");
free(key);
perror ("read()");
free (key);
goto next_spool;
}
datasize += rlen ;
key[rlen] = 0 ;
datasize += rlen;
key[rlen] = 0;
rlen = read(spool_fd, &uwstrlen, 2);
rlen = read (spool_fd, &uwstrlen, 2);
if (rlen != 2) {
perror("read()");
free(key);
perror ("read()");
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()");
free (key);
perror ("malloc()");
goto retry_later;
}
rlen = read(spool_fd, val, uwstrlen);
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 */
}
if (PyDict_SetItemString(spool_env, key, PyString_FromStringAndSize(val, uwstrlen))) {
PyErr_Print();
free(key);
free(val);
goto retry_later ;
if (PyDict_SetItemString (spool_env, key, PyString_FromStringAndSize (val, uwstrlen))) {
PyErr_Print ();
free (key);
free (val);
goto retry_later;
}
free(key);
free(val);
free (key);
free (val);
}
else {
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");
PyErr_Print ();
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");
if (PyInt_Check (spool_result)) {
if (PyInt_AsLong (spool_result) == 17) {
Py_DECREF (spool_result);
fprintf (stderr, "retry this task later...\n");
goto retry_later;
}
}
Py_DECREF(spool_result);
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");
exit(1);
if (unlink (dp->d_name)) {
perror ("unlink");
fprintf (stderr, "something horrible happened to the spooler. Better to kill it.\n");
exit (1);
}
retry_later:
PyDict_Clear(spool_env);
close(spool_fd);
retry_later:
PyDict_Clear (spool_env);
close (spool_fd);
}
}
}
closedir(sdir);
closedir (sdir);
}
else {
perror("opendir()");
perror ("opendir()");
}
/* TODO spooler frequency user-configurable */
sleep(5);
sleep (5);
}
}
int uwsgi_request_spooler (struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, char *buffer) {
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, 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 ;
}
#endif
+4 -2
View File
@@ -10,6 +10,7 @@ os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'
#import django.core.handlers.wsgi
uwsgi.load_plugin(0, "plugins/rack/rack_plugin.so")
from threading import Thread
@@ -89,8 +90,8 @@ def reload(env, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
uwsgi.sorry_i_need_to_block()
time.sleep(1)
#uwsgi.sorry_i_need_to_block()
#time.sleep(1)
#uwsgi.reload()
@@ -154,6 +155,7 @@ def reload(env, start_response):
#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>'
+1430 -1885
View File
File diff suppressed because it is too large Load Diff
+226 -177
View File
@@ -1,6 +1,7 @@
/* uWSGI */
/* indent -i8 -br -brs -brf -l0 -npsl */
#include <stdio.h>
@@ -10,6 +11,11 @@
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#ifdef SCTP
#include <netinet/sctp.h>
#endif
#include <arpa/inet.h>
#include <sys/mman.h>
#include <sys/file.h>
@@ -18,6 +24,11 @@
#include <stdint.h>
#include <sys/wait.h>
#include <dlfcn.h>
#include <poll.h>
#include <sys/uio.h>
#include <sys/socket.h>
@@ -36,18 +47,17 @@
#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
@@ -56,18 +66,26 @@
#define MAX_PYARGV 10
#ifndef ROCK_SOLID
#ifdef __linux__
#include <sys/sendfile.h>
#endif
#endif
#undef _XOPEN_SOURCE
#include <Python.h>
#if PY_MINOR_VERSION == 4 && PY_MAJOR_VERSION == 2
#define Py_ssize_t int
#define Py_ssize_t int
#endif
#if PY_MAJOR_VERSION > 2
#define PYTHREE
#define PYTHREE
#endif
PyAPI_FUNC(PyObject *) PyMarshal_WriteObjectToString(PyObject *, int);
PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
PyAPI_FUNC (PyObject *) PyMarshal_WriteObjectToString (PyObject *, int);
PyAPI_FUNC (PyObject *) PyMarshal_ReadObjectFromString (char *, Py_ssize_t);
#define LONG_ARGS_PIDFILE 17001
@@ -79,6 +97,7 @@ PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
#define LONG_ARGS_CHECK_INTERVAL 17007
#define LONG_ARGS_PYARGV 17008
#define LONG_ARGS_LIMIT_AS 17009
#define LONG_ARGS_UDP 17010
#ifdef __linux__
@@ -104,7 +123,6 @@ PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
#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_ADMIN_REQUEST 10
@@ -119,16 +137,16 @@ PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
#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
@@ -140,122 +158,173 @@ PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
#define MAX_VARS 64
struct uwsgi_app {
struct uwsgi_app {
#ifndef ROCK_SOLID
PyThreadState *interpreter ;
PyObject *pymain_dict ;
PyThreadState *interpreter;
PyObject *pymain_dict;
#endif
#ifdef ROCK_SOLID
PyObject *wsgi_module;
PyObject *wsgi_dict;
PyObject *wsgi_module;
PyObject *wsgi_dict;
#endif
PyObject *wsgi_callable ;
PyObject *wsgi_environ ;
PyObject *wsgi_args;
PyObject *wsgi_harakiri;
PyObject *wsgi_callable;
PyObject *wsgi_environ;
PyObject *wsgi_args;
PyObject *wsgi_harakiri;
#ifndef ROCK_SOLID
PyObject *wsgi_sendfile;
PyObject *wsgi_cprofile_run;
int requests ;
PyObject *wsgi_sendfile;
PyObject *wsgi_cprofile_run;
int requests;
#endif
};
};
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;
};
struct uwsgi_server {
char *pyhome;
struct uwsgi_server {
char *pyhome;
#ifndef ROCK_SOLID
int has_threads;
int wsgi_cnt;
int default_app;
int enable_profiler;
int has_threads;
int wsgi_cnt;
int default_app;
int enable_profiler;
int i_have_gil ;
PyThreadState *_save;
#ifndef UNBIT
char *chroot;
gid_t gid;
uid_t uid;
char *chroot;
gid_t gid;
uid_t uid;
#endif
#endif
int to_heaven ;
int to_hell ;
int (*hooks[0xFF])(struct uwsgi_server *, struct wsgi_request*, char*) ;
int (*after_hooks[0xFF])(struct uwsgi_server *, struct wsgi_request*, char*) ;
int buffer_size;
// iovec
struct iovec *hvec;
int master_process;
int to_heaven;
int to_hell;
int no_defer_accept;
int buffer_size;
int page_size ;
int master_process;
char *sync_page ;
int synclog;
int no_defer_accept;
char *test_module;
int page_size;
char *pidfile;
char *sync_page;
int synclog;
int numproc;
int maxworkers;
char *test_module;
int max_vars ;
int vec_size ;
char *pidfile;
char *sharedarea ;
int numproc;
int maxworkers;
int max_vars;
int vec_size;
char *sharedarea;
#ifndef __OpenBSD__
void *sharedareamutex ;
void *sharedareamutex;
#endif
int sharedareasize ;
int sharedareasize;
/* the list of workers */
struct uwsgi_worker *workers ;
pid_t mypid;
int mywid;
/* the list of workers */
struct uwsgi_worker *workers;
pid_t mypid;
int mywid;
struct timeval start_tv;
struct timeval start_tv;
#ifndef UNBIT
int abstract_socket;
int chmod_socket;
int listen_queue;
int abstract_socket;
int chmod_socket;
int listen_queue;
#ifndef ROCK_SOLID
char *xml_config;
char *python_path[64];
int python_path_cnt;
char *pyargv ;
char *xml_config;
char *python_path[64];
int python_path_cnt;
char *pyargv;
#endif
#endif
#ifndef ROCK_SOLID
char *wsgi_config;
char *paste;
char *wsgi_config;
char *paste;
#endif
#ifndef ROCK_SOLID
int single_interpreter;
int py_optimize;
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 ;
PyThreadState *main_thread;
#endif
struct pollfd poll;
struct pollfd poll;
uint32_t *options;
uint32_t *options;
#ifndef ROCK_SOLID
struct uwsgi_app wsgi_apps[64];
PyObject *py_apps;
struct uwsgi_app wsgi_apps[64];
PyObject *py_apps;
#endif
};
};
struct __attribute__((packed)) uwsgi_worker {
int id ;
struct __attribute__ ((packed)) uwsgi_worker {
int id;
pid_t pid;
time_t last_spawn;
unsigned long long requests;
@@ -265,125 +334,105 @@ struct __attribute__((packed)) uwsgi_worker {
unsigned long long vsz_size;
unsigned long long rss_size;
double running_time ;
double running_time;
double load ;
double last_running_time ;
double last_running_time;
int in_request;
int manage_next_request;
int blocking ;
int current_workers ;
};
int blocking;
int current_workers;
};
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 ;
char *uwsgi_get_cwd (void);
void warn_pipe (void);
void goodbye_cruel_world (void);
void gracefully_kill (void);
void reap_them_all (void);
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_udp (char *);
#ifdef SCTP
int bind_to_sctp (char *, int, char *);
#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);
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 *);
#ifndef UNBIT
void daemonize(char *);
void daemonize (char *);
#endif
void log_request(struct wsgi_request*) ;
void log_request (struct wsgi_request *);
#ifndef ROCK_SOLID
void get_memusage(void) ;
void get_memusage (void);
#endif
void harakiri(void) ;
void harakiri (void);
#ifndef UNBIT
void stats(void) ;
void stats (void);
#endif
void init_uwsgi_vars(void);
void init_uwsgi_embedded_module(void);
void init_uwsgi_vars (void);
void init_uwsgi_embedded_module (void);
#ifndef UNBIT
void uwsgi_xml_config(void);
void uwsgi_xml_config (void);
#endif
#ifndef ROCK_SOLID
void uwsgi_wsgi_config(void);
void uwsgi_paste_config(void);
void uwsgi_wsgi_config (void);
void uwsgi_paste_config (void);
#endif
void init_uwsgi_module_sharedarea(PyObject *);
void init_uwsgi_module_advanced(PyObject *);
void init_uwsgi_module_spooler(PyObject *);
void internal_server_error(int, char *);
void init_uwsgi_module_sharedarea (PyObject *);
void init_uwsgi_module_advanced (PyObject *);
void init_uwsgi_module_spooler (PyObject *);
#ifndef ROCK_SOLID
int spool_request(char *, int, char *, int);
void spooler(PyObject *);
pid_t spooler_start(int, PyObject *);
#ifndef UNBIT
void manage_snmp (int, uint8_t *, int, struct sockaddr_in *);
#endif
#endif
void set_harakiri(int);
#ifndef ROCK_SOLID
int spool_request (char *, int, char *, int);
void spooler (PyObject *);
pid_t spooler_start (int, PyObject *);
#endif
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 *);
#endif
PyObject *uwsgi_send_message(const char *, int, uint8_t, uint8_t, char *, int, int);
PyObject *uwsgi_send_message (const 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_enqueue_message (char *, int, uint8_t, uint8_t, char *, int, int);
/* included HOOKS */
int uwsgi_request_wsgi(struct uwsgi_server*, struct wsgi_request*, char *);
int uwsgi_after_request_wsgi(struct uwsgi_server*, struct wsgi_request*, char *);
int uwsgi_request_admin(struct uwsgi_server*, struct wsgi_request*, char *);
int uwsgi_request_spooler(struct uwsgi_server*, struct wsgi_request*, char *);
int uwsgi_request_fastfunc(struct uwsgi_server*, struct wsgi_request*, char *);
int uwsgi_request_marshal(struct uwsgi_server*, struct wsgi_request*, char *);
int uwsgi_request_ping(struct uwsgi_server*, struct wsgi_request*, char *);
int uwsgi_enqueue_message(char *, int, uint8_t, uint8_t, char *, int, int);
+117
View File
@@ -0,0 +1,117 @@
#include "uwsgi.h"
/* uwsgi PING|100 */
int uwsgi_request_ping (struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, char *buffer) {
fprintf (stderr, "PING\n");
wsgi_req->modifier_arg = 1;
if (write (uwsgi->poll.fd, wsgi_req, 4) != 4) {
perror ("write()");
}
return 0;
}
/* uwsgi ADMIN|10 */
int uwsgi_request_admin (struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, char *buffer) {
uint32_t opt_value = 0;
int i;
if (wsgi_req->size >= 4) {
memcpy (&opt_value, buffer, 4);
// TODO: check endianess
}
fprintf (stderr, "setting internal option %d to %d\n", wsgi_req->modifier_arg, opt_value);
uwsgi->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, char *buffer) {
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, char *buffer) {
PyObject *func_result;
PyObject *umm = PyDict_GetItemString (uwsgi->embedded_dict,
"message_manager_marshal");
if (umm) {
PyObject *ummo = PyMarshal_ReadObjectFromString (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;
}
+48 -16
View File
@@ -546,6 +546,51 @@ PyObject *py_uwsgi_set_option(PyObject *self, PyObject *args) {
return PyInt_FromLong(value);
}
PyObject *py_uwsgi_load_plugin(PyObject *self, PyObject *args) {
uint8_t modifier ;
char *plugin_name = NULL ;
void *plugin_handle;
void (*plugin_init)(struct uwsgi_server *);
int (*plugin_request)(struct uwsgi_server *, struct wsgi_request*, char*) ;
int (*plugin_after_request)(struct uwsgi_server *, struct wsgi_request*, char*) ;
if (!PyArg_ParseTuple(args, "is:load_plugin", &modifier, &plugin_name)) {
return NULL ;
}
if (modifier <= 255) {
plugin_handle = dlopen(plugin_name, RTLD_LAZY);
if (!plugin_handle) {
fprintf (stderr, "%s\n", dlerror());
}
else {
plugin_init = dlsym(plugin_handle, "uwsgi_init");
if (plugin_init) {
(*plugin_init)(&uwsgi);
}
plugin_request = dlsym(plugin_handle, "uwsgi_request");
if (plugin_request) {
uwsgi.hooks[modifier] = plugin_request ;
plugin_after_request = dlsym(plugin_handle, "uwsgi_after_request");
if (plugin_after_request) {
uwsgi.after_hooks[modifier] = plugin_after_request ;
}
Py_INCREF(Py_True);
return Py_True;
}
else {
fprintf (stderr, "%s\n", dlerror());
}
}
}
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_uwsgi_send_message(PyObject *self, PyObject *args) {
PyObject *arg_message = NULL;
@@ -620,18 +665,9 @@ PyObject *py_uwsgi_total_requests(PyObject *self, PyObject *args) {
PyObject *py_uwsgi_workers(PyObject *self, PyObject *args) {
PyObject *worker_dict, *zero;
int i, w ;
int i ;
if (uwsgi.master_process) {
w = uwsgi.workers[0].current_workers ;
}
else {
w = uwsgi.numproc;
}
fprintf(stderr,"W = %d\n", w);
for(i=0;i<w;i++) {
for(i=0;i<uwsgi.numproc;i++) {
worker_dict = PyTuple_GetItem(uwsgi.workers_tuple, i) ;
if (!worker_dict) {
goto clear;
@@ -693,11 +729,6 @@ PyObject *py_uwsgi_workers(PyObject *self, PyObject *args) {
}
Py_DECREF(zero);
zero = PyFloat_FromDouble(uwsgi.workers[i+1].load);
if (PyDict_SetItemString(worker_dict, "load", zero)) {
goto clear;
}
Py_DECREF(zero);
}
@@ -781,6 +812,7 @@ static PyMethodDef uwsgi_advanced_methods[] = {
{"worker_id", py_uwsgi_worker_id, METH_VARARGS, ""},
{"log", py_uwsgi_log, METH_VARARGS, ""},
{"disconnect", py_uwsgi_disconnect, METH_VARARGS, ""},
{"load_plugin", py_uwsgi_load_plugin, METH_VARARGS, ""},
{NULL, NULL},
};
+483
View File
@@ -0,0 +1,483 @@
#include "uwsgi.h"
int uwsgi_request_wsgi (struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, char *buffer) {
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;
int rlen;
/* Standard WSGI request */
if (!wsgi_req->size) {
fprintf (stderr, "Invalid WSGI 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) {
#ifndef ROCK_SOLID
#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->i_have_gil) {
PyEval_RestoreThread (uwsgi->_save);
uwsgi->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->options[UWSGI_OPTION_THREADS] == 1) {
uwsgi->_save = PyEval_SaveThread ();
uwsgi->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)) {
#else
if (!strncmp ("SERVER_PROTOCOL", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
#endif
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;
}
#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 ROCK_SOLID
if (uwsgi->has_threads && !uwsgi->i_have_gil) {
PyEval_RestoreThread (uwsgi->_save);
uwsgi->i_have_gil = 1;
}
#endif
wsgi_file = fdopen (uwsgi->poll.fd, "r");
#ifndef ROCK_SOLID
#ifndef UNBIT
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);
}
#endif
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;
}
/* max 1 minute before harakiri */
if (uwsgi->options[UWSGI_OPTION_HARAKIRI] > 0) {
#ifdef UNBIT
if (wsgi_req->modifier != 0) {
switch (wsgi_req->modifier) {
case UWSGI_MODIFIER_HT_S:
set_harakiri (wsgi_req->modifier_arg);
case UWSGI_MODIFIER_HT_M:
set_harakiri (wsgi_req->modifier_arg * 60);
case UWSGI_MODIFIER_HT_H:
set_harakiri (wsgi_req->modifier_arg * 3600);
}
}
else {
#endif
set_harakiri (uwsgi->options[UWSGI_OPTION_HARAKIRI]);
#ifdef UNBIT
}
#endif
}
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);
#ifndef ROCK_SOLID
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);
}
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
#ifndef ROCK_SOLID
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 ();
}
#ifndef ROCK_SOLID
}
#endif
if (wsgi_result) {
#ifndef ROCK_SOLID
if (wsgi_req->sendfile_fd > -1) {
rlen = lseek (wsgi_req->sendfile_fd, 0, SEEK_END);
if (rlen > 0) {
lseek (wsgi_req->sendfile_fd, 0, SEEK_SET);
#ifndef __linux__
#if defined(__FreeBSD__) || defined(__DragonFly__)
wsgi_req->response_size = sendfile (wsgi_req->sendfile_fd, uwsgi->poll.fd, 0, 0, NULL, (off_t *) & rlen, 0);
#elif __OpenBSD__ || __sun__
char *no_sendfile_buf[4096];
int jlen = 0;
i = 0;
while (i < rlen) {
jlen = read (wsgi_req->sendfile_fd, no_sendfile_buf, 4096);
if (jlen <= 0) {
perror ("read()");
break;
}
i += jlen;
jlen = write (uwsgi->poll.fd, no_sendfile_buf, jlen);
if (jlen <= 0) {
perror ("write()");
break;
}
}
#else
wsgi_req->response_size = sendfile (wsgi_req->sendfile_fd, uwsgi->poll.fd, 0, (off_t *) & rlen, NULL, 0);
#endif
#else
wsgi_req->response_size = sendfile (uwsgi->poll.fd, wsgi_req->sendfile_fd, NULL, rlen);
#endif
}
Py_DECREF (uwsgi->py_sendfile);
}
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);
}
#ifndef ROCK_SOLID
}
if (uwsgi->enable_profiler == 0) {
#endif
Py_DECREF (wsgi_result);
#ifndef ROCK_SOLID
}
#endif
}
PyDict_Clear (wi->wsgi_environ);
#ifndef ROCK_SOLID
wi->requests++;
#endif
PyErr_Clear ();
if (uwsgi->options[UWSGI_OPTION_HARAKIRI] > 0) {
set_harakiri (0);
}
#ifndef ROCK_SOLID
if (uwsgi->single_interpreter == 0) {
// restoring main interpreter
PyThreadState_Swap (uwsgi->main_thread);
}
#endif
clean:
fclose (wsgi_file);
#ifndef ROCK_SOLID
if (uwsgi->has_threads && uwsgi->options[UWSGI_OPTION_THREADS] == 1) {
uwsgi->_save = PyEval_SaveThread ();
uwsgi->i_have_gil = 0;
}
#endif
uwsgi->workers[uwsgi->mywid].requests++;
return 0;
}
int uwsgi_after_request_wsgi (struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, char *buffer) {
if (uwsgi->options[UWSGI_OPTION_LOGGING])
log_request(wsgi_req) ;
return 0;
}