Compare commits

..
125 Commits
Author SHA1 Message Date
roberto@sirius 63b41856e5 Changelog for 0.9.6 2010-08-28 19:58:55 +02:00
roberto@sirius ed1e668240 NetBSD latest fixes. Ready for 0.9.6 release 2010-08-28 19:36:55 +02:00
roberto@freebsd64 e3a7e70180 fix pidfile on HTTP mode 2010-08-28 13:51:38 +02:00
roberto@freebsd64 9f0b20c8d2 use getsockname() in vacuum() 2010-08-28 13:16:22 +02:00
roberto@freebsd64 68aff372ce HTTP final fixes, better reloading system, better cwd detection, powered up vacuum 2010-08-28 13:00:21 +02:00
roberto@sirius 38cfa72318 close ini file 2010-08-27 11:07:35 +02:00
roberto@sirius 31047e1e10 fixes for --file and shebang support 2010-08-27 07:32:44 +02:00
roberto@sirius bbb90296bb applied Leonid Borisenko patch to allow -O2 and -fno-strict-aliasing CFLAGS 2010-08-27 06:21:43 +02:00
roberto@sirius 00c6aa2f65 0.9.6-rc2 2010-08-26 17:08:15 +02:00
roberto@sirius 720da09631 xmlconf fixes 2010-08-26 15:33:25 +02:00
roberto@fiorenzo 47f7c09b97 add empty QUERY_STRING in http server 2010-08-26 14:55:39 +02:00
roberto@sirius cb5704da10 --callable 2010-08-26 14:09:15 +02:00
roberto@fiorenzo c64356b231 uwsgi packet watermark in HTTP server 2010-08-26 11:38:48 +02:00
roberto@sirius 2acd2f5224 another solaris hack 2010-08-26 11:01:57 +02:00
roberto@sirius ba251f8e3d another solaris fix 2010-08-26 10:09:40 +02:00
roberto@sirius 48019f9044 first round of http fixes 2010-08-26 10:06:17 +02:00
roberto@sunsparc d9a1f2448c solaris fixes 2010-08-26 09:33:23 +02:00
roberto@ubuntu64 553a947c2d fix routing 2010-08-26 08:43:28 +02:00
roberto@sirius 736aedfa89 add --ini-paste commodity and removal of strlc* functions 2010-08-26 08:36:44 +02:00
roberto@sirius 6184acc727 updated --help 2010-08-25 20:00:10 +02:00
roberto@sirius f0d96b03fa added --ping and --ping-timeout 2010-08-25 19:21:31 +02:00
roberto@sirius 14bf840eef fix urack.rb upload 2010-08-24 16:44:32 +02:00
roberto@sirius 7ea08093c7 uWSGI 0.9.6-rc1 2010-08-24 08:41:25 +02:00
roberto@sirius 8eb8d07151 ready for rc1 ? 2010-08-24 08:37:24 +02:00
roberto@sirius cdd95b434e http and sendfile fix 2010-08-24 08:33:03 +02:00
roberto@ubuntu64 82cbcea886 Linux has no strlcat 2010-08-23 18:51:02 +02:00
roberto@silente ea54a05fc3 OpenBSD fixes by Piotr Sikora 2010-06-08 07:43:48 +02:00
roberto@ubuntu64 eba39dcd67 LDAP support 2010-08-23 14:27:49 +02:00
roberto@ubuntu64 d71ea1404d allow non-numeric uid and gid 2010-08-22 18:31:18 +02:00
roberto@ubuntu64 0f0d5b2a5f safer automatic unix socket and --vacuum option 2010-08-22 18:02:09 +02:00
roberto@mrspurr 10a75ef848 support key-only value (without '=') in ini files 2010-08-22 08:10:23 +02:00
roberto@sirius 4bd9bf8917 remove REMOTE_USER in http server 2010-08-19 08:16:42 +02:00
roberto@mrspurr 323da1299e another fix for PEP 333 file_wrapper compatiblity 2010-08-18 19:42:21 +02:00
roberto@mrspurr 75d08898b4 http server fixes 2010-08-18 16:37:10 +02:00
roberto@sirius 5e47796a02 something to fix in utf8 handling [2] 2010-08-17 14:13:04 +02:00
roberto@sirius 0ade5aba0a something to fix in utf8 handling 2010-08-17 14:12:52 +02:00
roberto@sirius f7b1ad8cb0 add a little comment 2010-08-17 14:10:52 +02:00
roberto@sirius 3bd147e687 fixed random seeding (thanks to Jonas Borgström) 2010-08-17 14:04:44 +02:00
roberto@voldemort 66c99e257f fix pidfile (will be written at server startup and only if it is not a reload) 2010-08-15 18:55:48 +02:00
roberto@voldemort 8407a5921b warn user about harakiri without post buffering 2010-08-15 18:52:20 +02:00
roberto@voldemort 5f36987827 applied Jonas Borgström patch for lighttpd REMOTE_USER 2010-08-15 18:40:09 +02:00
roberto@voldemort ede1622368 fix a stupid bug in apache module 2010-08-14 15:59:36 +02:00
roberto@voldemort a28dfb790e does a fix for not reading post data really exists ? 2010-08-14 08:17:33 +02:00
roberto@voldemort 3711cbbd61 ini file improvement 2010-08-14 08:13:04 +02:00
roberto@voldermort c9ef6281ff added --catch-exceptions, it will print app exceptions to your browser 2010-08-13 17:37:34 +02:00
roberto@voldemort 604ea6fd57 INI files support 2010-08-13 15:46:37 +02:00
roberto@longshot 41dfcaa705 added --chdir2 2010-08-11 17:35:14 +02:00
roberto@sirius daa41d4a51 fixed --unbit PYLIB_PATH 2010-08-11 09:20:22 +02:00
roberto@sirius ded4450a70 http build option 2010-08-11 09:18:50 +02:00
roberto@sirius cd0be56bbe fixed --unbit 2010-08-11 08:59:12 +02:00
roberto@sirius 0bf7b64b46 mjpeg streaming example using uwsgi.sendfile() 2010-08-08 15:43:24 +02:00
roberto@sirius 215d2e7055 full PEP 333 compliant file_wrapper and advanced uwsgi.sendfile() 2010-08-08 15:41:34 +02:00
roberto@voldemort 2b5b0cf1bc fix spooler stdin 2010-08-05 12:21:34 +02:00
roberto@voldemort 67231da4a9 added uwsgi.env 2010-08-03 18:03:34 +02:00
roberto@sirius 8c25b38470 fix UNBIT compilation 2010-07-29 10:19:06 +02:00
roberto@sirius 08bbe0cd30 MINTERPRETERS build fixes 2010-07-28 14:37:47 +02:00
roberto@sirius 9f9f63fe2f UDP build fixes 2010-07-28 14:31:58 +02:00
roberto@sirius 997bd63cc3 add LD_RUN_PATH option 2010-07-27 11:43:22 +02:00
roberto@siris 6a566d9dca fix static compilation 2010-07-27 11:40:54 +02:00
roberto@sirius d2e743a800 rack/rails plugin base added. NOT USABLE 2010-07-27 08:47:27 +02:00
roberto@sirius 2fedb175b4 disable WSGI2 flag by default 2010-07-21 11:02:18 +02:00
roberto@sirius 6c5e25dbfe sendfile fix 2010-07-20 17:56:54 +02:00
roberto@fiorenzo 94fd3f0bfd mega.xml example 2010-07-20 15:45:19 +02:00
roberto@fiorenzo ca169b05fb xml id, working multi-thread http server, --env support 2010-07-20 15:43:09 +02:00
roberto@voldemort 10ea1fee6e a bunch of fixes 2010-07-19 12:22:16 +02:00
roberto@sirius d7b8704165 conditional paste inclusion and django_admin fix 2010-07-14 16:34:56 +02:00
roberto@voldemort 0f774b840c quick_callable, --chdir and (broken) multithread http.c 2010-07-14 00:19:00 +02:00
roberto@sirius 81521a314b embedded HTTP server for easy development 2010-07-12 18:34:16 +02:00
roberto@sirius 37ee7f8908 better management of SCRIPT_NAME 2010-07-07 11:47:39 +02:00
roberto@sirius 309648f68b more verbose spooler 2010-07-06 10:44:00 +02:00
roberto@sirius 5cfa65d04e Python 2.7 support 2010-07-06 09:20:41 +02:00
roberto@voldemort e73c8194a0 64 bit fixes [2] 2010-06-28 10:37:46 +02:00
roberto@voldemort 00a3f6ae7f 64 bit fixes 2010-06-28 10:36:02 +02:00
roberto@voldemort b7edaa68c8 various fixes from 0.9.5.2 2010-06-26 22:37:46 +02:00
roberto@sirius 2877ba54de better routing 2010-06-23 19:55:41 +02:00
roberto@mrspurr f74a19a71a preliminary routing support (PCRE needed) 2010-06-21 17:42:03 +02:00
roberto@sirius 3da5238ee5 PSGI embedded support 2010-06-14 16:59:50 +02:00
roberto@fedora-arm 567dd36592 remove UGREEN on arm 2010-06-11 02:48:53 -04:00
roberto@sirius b48062a026 add 0x to hex debug printing 2010-06-10 08:34:02 +02:00
roberto@sirius b039cb713f VirtualHosting mode and UWSGI_PYHOME uwsgi var 2010-06-10 08:05:11 +02:00
roberto@sirius 8e987ffa18 proposed WSGI2.0 response support 2010-06-08 17:44:43 +02:00
roberto@mrspurr 52502342e0 fix copyright year 2010-06-03 12:59:48 +02:00
roberto@mrspurr cb9e3c22f9 added apache2 mod_Ruwsgi 2010-06-03 12:53:27 +02:00
roberto@sirius 0c465775ad force next_upstream on http_502 and http_504 on nginx 2010-06-03 08:08:28 +02:00
roberto@sirius a5417f4963 Davies Liu fix for protocol parsing 2010-06-03 08:01:34 +02:00
roberto@mrspurr b48076f6e4 support for 'grunt' processes 2010-05-31 14:06:42 +02:00
roberto@voldemort c472eae332 upstart contrib example 2010-05-22 06:54:23 +02:00
roberto@voldemort 918fc654f4 --no-orphans option (uses prctl on Linux and getppid on others) 2010-05-22 06:39:09 +02:00
roberto@voldemort 9097cbe10d 0.9.5.1 tag 2010-05-19 16:09:08 +02:00
roberto@sirius e260873338 uWSGI 0.9.5.1 2010-05-19 16:08:29 +02:00
roberto@voldemort a7822742c0 lighttpd PATH_INFO fix 2010-05-18 08:01:32 +02:00
roberto@voldemort f1316ef4bb fix env configuration 2010-05-18 07:34:36 +02:00
roberto@sirius 4106931175 fix getrlimit() 2010-05-18 07:06:07 +02:00
roberto@sirius fb5ba40f0c support for unladen swallow 2010-05-16 12:34:19 +02:00
roberto@sirius 854e51f0ad fix for eval modifier 2010-05-13 13:47:15 +02:00
roberto@sirium 676b43f17d UWSGI_MODIFIER_EVAL and nginx module update 2010-05-13 13:04:37 +02:00
roberto@sirius 48b68e6a92 updated help and version 2010-05-12 16:40:47 +02:00
roberto@sirius 61f33721e1 add --limit-post 2010-05-12 13:13:01 +02:00
roberto@sirius 5c3c46598f --post-buffering, this will help harakiri mode with big uploads 2010-05-12 12:54:49 +02:00
roberto@sirius 4358036f9e add --prio option 2010-05-12 09:10:04 +02:00
roberto@sirius 54d75d92ef fix paste support 2010-05-10 18:04:01 +02:00
roberto@sirius b1ae57c932 applied gentoo fixes 2010-05-10 10:58:52 +02:00
roberto@sirius 2636baa33f added --logto 2010-05-02 12:38:39 +02:00
roberto@sirius 926c739517 0.9.5 2010-05-01 08:24:21 +02:00
roberto@sirius 79fa25c4e0 latest (i hope) pip hack 2010-05-01 08:10:36 +02:00
roberto@sirius 02050675a8 pip hack [5] 2010-05-01 08:06:44 +02:00
roberto@sirius 0d5857a1bc pip hack [4] 2010-05-01 08:04:05 +02:00
roberto@sirius e3a51be1f9 pip hack [3] 2010-05-01 07:58:53 +02:00
roberto@sirius 57cb098a6e move to setuptools 2010-05-01 07:39:56 +02:00
roberto@sirius 5f285eef56 pip hack [2] 2010-05-01 07:29:07 +02:00
roberto@sirius 7d5cf6f318 pip hack 2010-05-01 07:14:14 +02:00
roberto@silente 99d305c7a1 snmp big endian fixes 2010-04-30 16:41:57 +02:00
roberto@sirius b9cc3b6a7d snmp fix 2010-04-30 15:51:32 +02:00
roberto@sirius e1f8c69d3d minor fixes 2010-04-30 15:16:18 +02:00
roberto@sirius 67b6fbd15b admin modifier fix 2010-04-30 14:46:27 +02:00
roberto@sirius 50f407eb9e no_server fix 2010-04-30 14:41:30 +02:00
roberto@freebsd b127699c0a FreeBSD/Dragonfly little fix 2010-04-30 14:12:51 +02:00
roberto@netbsd 4d74fa6759 small netbsd include fix 2010-04-30 16:04:02 +02:00
roberto@sirius 2b9d6cb7c2 uwsgi_log everywhere 2010-04-30 12:28:01 +02:00
roberto@solaris e0b67bba58 uwsgi_log instead of fprintf [1] 2010-04-30 12:22:07 +02:00
roberto@silente 3cdf17df75 strlcopy insted of strcpy 2010-04-30 09:54:25 +02:00
roberto@silente 43c086494b be more verbose on extreme cases 2010-04-30 09:18:53 +02:00
roberto@silente ae26e90b3a OpenBSD ha no RLIMIT_AS and swapcontext(), added an harakiri message to avoid user confusion 2010-04-30 09:01:26 +02:00
roberto@sirius d35a7d8725 updated urack.rb for unbit 2010-04-27 12:47:29 +02:00
roberto@sirius 043e7ddde4 uWSGI 0.9.5-rc2 2010-04-20 10:51:54 +02:00
57 changed files with 5958 additions and 1326 deletions
+5
View File
@@ -1,3 +1,8 @@
d3850b52334a91d005b0fe45e1e38ba0997a1fb8 no_server mode
2d8a617299153ed2efa6ecee7920e9d36c29e0f5 0.9.5beta1
04722a2d0121080d14a64df097c278860db5ce8a 0.9.5rc1
820cc64ab296dc4589ef72a33a6b804c22a0430c 0.9.5rc2
b0db39cfad5ac6d4f00bbb3f9c57cf73206e2afb 0.9.5
9f8b98ad1dfa51b86b13fa624c65f73523075fc4 0.9.5.1
a83e7a482e65befcfbb0e24af8cd5d15190acdd7 0.9.6-rc1
b8f67c6cd0d62f864db9b2b265b4e260ad7d873c 0.9.6-rc2
+93
View File
@@ -1,3 +1,96 @@
*** august 2010 ***
* 0.9.6 [20100829]
- better handling of SCRIPT_NAME
- vacuum option for deleting unix sockets and pidfiles after usage
- advanced XML configuration
- new configuration systems: INI files and LDAP
- embedded HTTP server for development/testing
- better signal handling
- PSGI plugin improved
- usability fixes and new commodities options for root startup
- grunt processes (detached workers)
- preliminary integrated virtualhosting mode
- new option catch-exceptions can redirect python exceptions to your browser
- logging improvements (--logto and --logdate options)
- Full PEP 333 compliant usage of wsgi.file_wrapper
- re-initialize random seed after every fork() [security fix]
- fix Spooler's usage of stdin
- export WSGI environment in uwsgi.env (for doing evil things)
- logsize tracking (uwsgi.logsize) for future embedded log rotation
*** july 2010 ***
* 0.9.5.4 [20100706]
*** june 2010 ***
* 0.9.5.3 [20100628]
- fixed linux x86_64 compilation (sorry)
* 0.9.5.2 [20100626] *
- fixed a request parsing bug
- applied debian fixes
- fixed multiple interpreter sys.argv
- improved --chmod-socket
- fixed uid 0 SIGHUP
- updated nginx and apache modules
- updated PSGI, lua and example plugin
- fixed --pyargv with python 3.x
- improved plugin build system
*** may 2010 ***
* 0.9.5.1 [20100519] *
- fixed paste support
- added a new modifier (22)
- full support for configuration via environment variables
- nginx_string option in nginx module
- fix for harakiri without master
- backported unladen swallow support for 0.9.6-dev
- fixed address space limit detection via getrlimit()
- http body buffering implementation
- added --prio option (to set priority)
- added --post-limit to limit the size of uploads
- added --logto option to allow udp logging without daemonizing
- applied Gentoo's packagers fixes for build system
* 0.9.5 [20100501] *
- hook based request/modifier management
- plugin support via dlopen
- on-the-fly management flag
- integrated proxy
- logging via udp
- improved spooler for cron-like apps
- async support
- green thread platform (uGreen) on top of the async mode
- transparent Erlang integration
- embedded snmp agent
- nagios mode
- improved python 3.x support
- improved xml configuration
- new build system
- address space usage limiting
- lot of portability fixes
- lot of optimizations and code refactoring
*** april 2010 ***
* Fourth Maintenance release [20100427] *
- backported non-yielding app optimization from 0.9.5
- backported udp logging from 0.9.5
- backported uwsgi_error() from 0.9.5 (no more dumb perror())
- fix a rare (but possible) segmentation fault
- added --version
- updated apache2 module
*** march 2010 ***
* Third Maintenance release [20100310] *
+2
View File
@@ -0,0 +1,2 @@
all:
python2.7 uwsgiconfig.py --build
+923
View File
@@ -0,0 +1,923 @@
/*
*** uWSGI/mod_Ruwsgi ***
Copyright 2009-2010 Roger Florkowski <rflorkowski@mypublisher.com>
Copyright 2009-2010 Unbit S.a.s. <info@unbit.it>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
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.
*/
#define MOD_UWSGI_VERSION "1.0"
#include "ap_config.h"
#include "apr_version.h"
#include "apr_lib.h"
#include "apr_strings.h"
#include "httpd.h"
#include "http_core.h"
#include "http_request.h"
#include "http_config.h"
#include "http_log.h"
#include "http_protocol.h"
#include "util_script.h"
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/uio.h>
#include <time.h>
#include <poll.h>
#define DEFAULT_TIMEOUT 60 /* default socket timeout */
#define DEFAULT_CGIMODE 0 /* not enabled */
#define UNSET 0
#define ENABLED 1
#define DISABLED 2
#if APR_MAJOR_VERSION == 0
#define apr_socket_send apr_send
#define GET_PORT(port, addr) apr_sockaddr_port_get(&(port), addr)
#define CREATE_SOCKET(sock, family, pool) \
apr_socket_create(sock, family, SOCK_STREAM, pool)
#else
#define GET_PORT(port, addr) ((port) = (addr)->port)
#define CREATE_SOCKET(sock, family, pool) \
apr_socket_create(sock, family, SOCK_STREAM, APR_PROTO_TCP, pool)
#endif
typedef struct {
char *path;
char *addr;
apr_port_t port;
} mount_entry;
/*
* Configuration record. Used per-directory configuration data.
*/
typedef struct {
mount_entry mount;
int enabled; /* mod_uwsgi is enabled from this directory */
int timeout;
int cgi_mode;
uint8_t modifier1;
uint8_t modifier2;
} uwsgi_cfg;
/* Server level configuration */
typedef struct {
apr_array_header_t *mounts;
int timeout;
int cgi_mode;
} uwsgi_server_cfg;
module AP_MODULE_DECLARE_DATA uwsgi_module;
/*
* Locate our directory configuration record for the current request.
*/
static uwsgi_cfg *
our_dconfig(request_rec *r)
{
return (uwsgi_cfg *) ap_get_module_config(r->per_dir_config, &uwsgi_module);
}
static uwsgi_server_cfg *our_sconfig(server_rec *s)
{
return (uwsgi_server_cfg *) ap_get_module_config(s->module_config,
&uwsgi_module);
}
static int
mount_entry_matches(const char *url, const char *prefix,
const char **path_info)
{
int i;
for (i=0; prefix[i] != '\0'; i++) {
if (url[i] == '\0' || url[i] != prefix[i])
return 0;
}
if (url[i] == '\0' || url[i] == '/') {
*path_info = url + i;
return 1;
}
return 0;
}
static int uwsgi_translate(request_rec *r)
{
uwsgi_cfg *cfg = our_dconfig(r);
if (cfg->enabled == DISABLED) {
return DECLINED;
}
if (cfg->mount.addr != UNSET) {
ap_assert(cfg->mount.port != UNSET);
r->handler = "uwsgi-handler";
r->filename = r->uri;
return OK;
}
else {
int i;
uwsgi_server_cfg *scfg = our_sconfig(r->server);
mount_entry *entries = (mount_entry *) scfg->mounts->elts;
for (i = 0; i < scfg->mounts->nelts; ++i) {
const char *path_info;
mount_entry *mount = &entries[i];
if (mount_entry_matches(r->uri, mount->path, &path_info)) {
r->handler = "uwsgi-handler";
r->path_info = apr_pstrdup(r->pool, path_info);
r->filename = r->uri;
ap_set_module_config(r->request_config, &uwsgi_module, mount);
return OK;
}
}
}
return DECLINED;
}
static int uwsgi_map_location(request_rec *r)
{
if (r->handler && strcmp(r->handler, "uwsgi-handler") == 0) {
return OK; /* We don't want directory walk. */
}
return DECLINED;
}
static void log_err(const char *file, int line, request_rec *r,
apr_status_t status, const char *msg)
{
ap_log_rerror(file, line, APLOG_ERR, status, r, "uwsgi: %s", msg);
}
static void log_debug(const char *file, int line, request_rec *r, const
char *msg)
{
/*
ap_log_rerror(file, line, APLOG_DEBUG, APR_SUCCESS, r, msg);
ap_log_rerror(file, line, APLOG_WARNING, APR_SUCCESS, r, "uwsgi: %s", msg);
*/
ap_log_rerror(file, line, APLOG_DEBUG, APR_SUCCESS, r, "uwsgi: %s", msg);
}
/* buffered socket implementation (buckets are overkill) */
#define BUFFER_SIZE 8000
struct sockbuff {
apr_socket_t *sock;
char buf[BUFFER_SIZE];
int used;
};
static void binit(struct sockbuff *s, apr_socket_t *sock)
{
s->sock = sock;
s->used = 0;
}
static apr_status_t sendall(apr_socket_t *sock, char *buf, apr_size_t len)
{
apr_status_t rv;
apr_size_t n;
while (len > 0) {
n = len;
if ((rv = apr_socket_send(sock, buf, &n))) return rv;
buf += n;
len -= n;
}
return APR_SUCCESS;
}
static apr_status_t bflush(struct sockbuff *s)
{
apr_status_t rv;
ap_assert(s->used >= 0 && s->used <= BUFFER_SIZE);
if (s->used) {
if ((rv = sendall(s->sock, s->buf, s->used))) return rv;
s->used = 0;
}
return APR_SUCCESS;
}
static apr_status_t bwrite(struct sockbuff *s, char *buf, apr_size_t len)
{
apr_status_t rv;
if (len >= BUFFER_SIZE - s->used) {
if ((rv = bflush(s))) return rv;
while (len >= BUFFER_SIZE) {
if ((rv = sendall(s->sock, buf, BUFFER_SIZE))) return rv;
buf += BUFFER_SIZE;
len -= BUFFER_SIZE;
}
}
if (len > 0) {
ap_assert(len < BUFFER_SIZE - s->used);
memcpy(s->buf + s->used, buf, len);
s->used += len;
}
return APR_SUCCESS;
}
static apr_status_t bputs(struct sockbuff *s, char *buf)
{
return bwrite(s, buf, strlen(buf));
}
static apr_status_t bputc(struct sockbuff *s, char c)
{
char buf[1];
buf[0] = c;
return bwrite(s, buf, 1);
}
static apr_status_t bputh(struct sockbuff *s, unsigned short h)
{
return bwrite(s, (char *)&h, 2);
}
#define CONFIG_VALUE(value, fallback) ((value) != UNSET ? (value) : (fallback))
static apr_status_t
open_socket(apr_socket_t **sock, request_rec *r)
{
int timeout;
int retries = 4;
int sleeptime = 1;
apr_status_t rv;
apr_sockaddr_t *sockaddr;
uwsgi_server_cfg *scfg = our_sconfig(r->server);
uwsgi_cfg *cfg = our_dconfig(r);
mount_entry *m = (mount_entry *) ap_get_module_config(r->request_config,
&uwsgi_module);
if (!m) {
m = &cfg->mount;
}
timeout = CONFIG_VALUE(cfg->timeout, CONFIG_VALUE(scfg->timeout,
DEFAULT_TIMEOUT));
rv = apr_sockaddr_info_get(&sockaddr,
CONFIG_VALUE(m->addr, "localhost"),
APR_UNSPEC,
CONFIG_VALUE(m->port, 5000),
0,
r->pool);
if (rv) {
log_err(APLOG_MARK, r, rv, "apr_sockaddr_info_get() error");
return rv;
}
restart:
*sock = NULL;
rv = CREATE_SOCKET(sock, sockaddr->family, r->pool);
if (rv) {
log_err(APLOG_MARK, r, rv, "apr_socket_create() error");
return rv;
}
rv = apr_socket_timeout_set(*sock, apr_time_from_sec(timeout));
if (rv) {
log_err(APLOG_MARK, r, rv, "apr_socket_timeout_set() error");
return rv;
}
rv = apr_socket_connect(*sock, sockaddr);
if (rv) {
apr_socket_close(*sock);
if ((APR_STATUS_IS_ECONNREFUSED(rv) |
APR_STATUS_IS_EINPROGRESS(rv)) && retries > 0) {
/* server may be temporarily down, retry */
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, rv, r,
"uwsgi: connection failed, retrying");
apr_sleep(apr_time_from_sec(sleeptime));
--retries;
sleeptime *= 2;
goto restart;
}
log_err(APLOG_MARK, r, rv, "uwsgi: can't connect to server");
return rv;
}
#ifdef APR_TCP_NODELAY
/* disable Nagle, we don't send small packets */
apr_socket_opt_set(*sock, APR_TCP_NODELAY, 1);
#endif
return APR_SUCCESS;
}
/* This code is a duplicate of what's in util_script.c. We can't use
* r->unparsed_uri because it gets changed if there was a redirect. */
static char *original_uri(request_rec *r)
{
char *first, *last;
if (r->the_request == NULL) {
return (char *) apr_pcalloc(r->pool, 1);
}
first = r->the_request; /* use the request-line */
while (*first && !apr_isspace(*first)) {
++first; /* skip over the method */
}
while (apr_isspace(*first)) {
++first; /* and the space(s) */
}
last = first;
while (*last && !apr_isspace(*last)) {
++last; /* end at next whitespace */
}
return apr_pstrmemdup(r->pool, first, last - first);
}
static char *lookup_name(apr_table_t *t, const char *name)
{
const apr_array_header_t *hdrs_arr = apr_table_elts(t);
apr_table_entry_t *hdrs = (apr_table_entry_t *) hdrs_arr->elts;
int i;
for (i = 0; i < hdrs_arr->nelts; ++i) {
if (hdrs[i].key == NULL)
continue;
if (strcasecmp(hdrs[i].key, name) == 0)
return hdrs[i].val;
}
return NULL;
}
static char *lookup_header(request_rec *r, const char *name)
{
return lookup_name(r->headers_in, name);
}
static void add_header(apr_table_t *t, const char *name, const char *value)
{
if (name != NULL && value != NULL)
apr_table_addn(t, name, value);
}
static int find_path_info(const char *uri, const char *path_info)
{
int n;
n = strlen(uri) - strlen(path_info);
ap_assert(n >= 0);
return n;
}
static char *http2env(apr_pool_t *p, const char *name)
{
char *env_name = apr_pstrcat(p, "HTTP_", name, NULL);
char *cp;
for (cp = env_name + 5; *cp != 0; cp++) {
if (*cp == '-') {
*cp = '_';
}
else {
*cp = apr_toupper(*cp);
}
}
return env_name;
}
static apr_status_t
send_headers(request_rec *r, struct sockbuff *s)
{
int i;
const apr_array_header_t *hdrs_arr, *env_arr;
apr_table_entry_t *hdrs, *env;
char *buf;
unsigned short int n = 0;
apr_table_t *t;
apr_status_t rv = 0;
apr_port_t port = 0;
GET_PORT(port, r->connection->remote_addr);
uwsgi_cfg *cfg = our_dconfig(r);
log_debug(APLOG_MARK,r, "sending headers");
t = apr_table_make(r->pool, 40);
if (!t)
return APR_ENOMEM;
/* headers to send */
/* CONTENT_LENGTH must come first and always be present */
buf = lookup_header(r, "Content-Length");
if (buf == NULL)
buf = "0";
add_header(t, "CONTENT_LENGTH", buf);
add_header(t, "REQUEST_METHOD", (char *) r->method) ;
add_header(t, "QUERY_STRING", r->args ? r->args : "") ;
add_header(t, "SERVER_SOFTWARE", ap_get_server_version());
add_header(t, "SERVER_ADMIN", r->server->server_admin);
add_header(t, "SERVER_NAME", (char *) ap_get_server_name(r)) ;
add_header(t, "SERVER_PORT", apr_psprintf(r->pool, "%u",ap_get_server_port(r))) ;
add_header(t, "SERVER_ADDR", r->connection->local_ip);
add_header(t, "SERVER_PROTOCOL", r->protocol) ;
add_header(t, "REQUEST_URI", original_uri(r)) ;
add_header(t, "REMOTE_ADDR", r->connection->remote_ip) ;
add_header(t, "REMOTE_PORT", apr_psprintf(r->pool, "%d", port));
add_header(t, "REMOTE_USER", r->user) ;
add_header(t, "DOCUMENT_ROOT", (char *) ap_document_root(r)) ;
if (r->path_info) {
int path_info_start = find_path_info(r->uri, r->path_info);
add_header(t, "SCRIPT_NAME", apr_pstrndup(r->pool, r->uri,
path_info_start));
add_header(t, "PATH_INFO", r->path_info);
}
else {
/* skip PATH_INFO, don't know it */
add_header(t, "SCRIPT_NAME", r->uri) ;
}
add_header(t, "CONTENT_TYPE", lookup_header(r, "Content-type"));
/* HTTP headers */
hdrs_arr = apr_table_elts(r->headers_in);
hdrs = (apr_table_entry_t *) hdrs_arr->elts;
for (i = 0; i < hdrs_arr->nelts; ++i) {
if (hdrs[i].key) {
add_header(t, http2env(r->pool, hdrs[i].key), hdrs[i].val);
}
}
/* environment variables */
env_arr = apr_table_elts(r->subprocess_env);
env = (apr_table_entry_t*) env_arr->elts;
for (i = 0; i < env_arr->nelts; ++i) {
add_header(t, env[i].key, env[i].val);
}
hdrs_arr = apr_table_elts(t);
hdrs = (apr_table_entry_t*) hdrs_arr->elts;
/* calculate length of header data */
for (i = 0; i < hdrs_arr->nelts; ++i) {
n += strlen(hdrs[i].key);
n += strlen(hdrs[i].val);
n += 4 ; /* XXX */
}
log_debug(APLOG_MARK,r, apr_psprintf(r->pool, "pktheader size is %u", n)) ;
log_debug(APLOG_MARK,r, apr_psprintf(r->pool, "num headers %u", hdrs_arr->nelts)) ;
/* write pkt header */
rv = bputc(s, cfg->modifier1); /* marker */
if (rv) return rv;
rv = bputh(s, n); /* length of header data */
if (rv) return rv;
rv = bputc(s, cfg->modifier2); /* marker */
if (rv) return rv;
/* write out headers */
for (i = 0; i < hdrs_arr->nelts; ++i) {
rv = bputh(s, strlen(hdrs[i].key)); /* length */
if (rv) return rv;
rv = bputs(s, hdrs[i].key); /* key */
if (rv) return rv;
rv = bputh(s, strlen(hdrs[i].val)); /* length */
if (rv) return rv;
rv = bputs(s, hdrs[i].val); /* data */
if (rv) return rv;
}
return APR_SUCCESS;
}
static apr_status_t send_request_body(request_rec *r, struct sockbuff *s)
{
if (ap_should_client_block(r)) {
char buf[BUFFER_SIZE];
apr_status_t rv;
apr_off_t len;
while ((len = ap_get_client_block(r, buf, sizeof buf)) > 0) {
if ((rv = bwrite(s, buf, len))) return rv;
}
if (len == -1)
return HTTP_INTERNAL_SERVER_ERROR; /* what to return? */
}
return APR_SUCCESS;
}
static int uwsgi_handler(request_rec *r)
{
apr_status_t rv = 0;
int cgi_mode, http_status = 0;
struct sockbuff s;
apr_socket_t *sock;
apr_bucket_brigade *bb = NULL;
apr_bucket *b = NULL;
const char *location;
uwsgi_cfg *cfg = our_dconfig(r);
uwsgi_server_cfg *scfg = our_sconfig(r->server);
if (strcmp(r->handler, "uwsgi-handler"))
return DECLINED;
http_status = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR);
if (http_status != OK)
return http_status;
log_debug(APLOG_MARK, r, "connecting to server");
rv = open_socket(&sock, r);
if (rv) {
return HTTP_INTERNAL_SERVER_ERROR;
}
binit(&s, sock);
rv = send_headers(r, &s);
if (rv) {
log_err(APLOG_MARK, r, rv, "error sending request headers");
return HTTP_INTERNAL_SERVER_ERROR;
}
rv = send_request_body(r, &s);
if (rv) {
log_err(APLOG_MARK, r, rv, "error sending request body");
return HTTP_INTERNAL_SERVER_ERROR;
}
rv = bflush(&s);
if (rv) {
log_err(APLOG_MARK, r, rv, "error sending request");
return HTTP_INTERNAL_SERVER_ERROR;
}
log_debug(APLOG_MARK, r, "reading response headers");
bb = apr_brigade_create(r->connection->pool, r->connection->bucket_alloc);
cgi_mode = CONFIG_VALUE(cfg->cgi_mode, CONFIG_VALUE(scfg->cgi_mode, DEFAULT_CGIMODE));
if (!cgi_mode) {
/* receive implemented with http-0.9 based protocol */
apr_interval_time_t timeout;
char buf[4096] ;
apr_pollfd_t pollfd = {r->pool, APR_POLL_SOCKET, APR_POLLIN, 0, { NULL }, NULL };
pollfd.desc.s = sock;
timeout = CONFIG_VALUE(cfg->timeout, CONFIG_VALUE(scfg->timeout,
DEFAULT_TIMEOUT)) * 1000 * 1000;
r->assbackwards = 1 ; /* XXX */
for(;;) {
apr_int32_t nsds;
apr_size_t len;
if ((rv = apr_poll(&pollfd, 1, &nsds, timeout)) == APR_TIMEUP) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() timeout");
break;
}
if (rv != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: poll() %s", strerror(errno));
break;
}
len = 4096;
rv = apr_socket_recv(sock, buf, &len);
if (rv == APR_SUCCESS) {
apr_brigade_write(bb, NULL, NULL, buf, len);
}
else if (rv == APR_EOF) {
break;
}
else {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() %s", strerror(errno));
}
}
log_debug(APLOG_MARK,r, "recv finished") ;
b = apr_bucket_flush_create(r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);
b = apr_bucket_eos_create(r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);
} else {
/* receive implemented with http-1.x based protocol */
b = apr_bucket_socket_create(sock, r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);
b = apr_bucket_eos_create(r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);
rv = ap_scan_script_header_err_brigade(r, bb, NULL);
if (rv) {
if (rv == HTTP_INTERNAL_SERVER_ERROR) {
log_err(APLOG_MARK, r, rv, "error reading response headers");
}
else {
/* Work around an Apache bug whereby the returned status is
* ignored and status_line is used instead. This bug is
* present at least in 2.0.54.
*/
r->status_line = NULL;
}
apr_brigade_destroy(bb);
return rv;
}
location = apr_table_get(r->headers_out, "Location");
if (location && location[0] == '/' &&
((r->status == HTTP_OK) || ap_is_HTTP_REDIRECT(r->status))) {
apr_brigade_destroy(bb);
/* Internal redirect -- fake-up a pseudo-request */
r->status = HTTP_OK;
/* This redirect needs to be a GET no matter what the original
* method was.
*/
r->method = apr_pstrdup(r->pool, "GET");
r->method_number = M_GET;
ap_internal_redirect_handler(location, r);
return OK;
}
}
rv = ap_pass_brigade(r->output_filters, bb);
if (rv) {
log_err(APLOG_MARK, r, rv, "ap_pass_brigade()");
return HTTP_INTERNAL_SERVER_ERROR;
}
return OK;
}
static int uwsgi_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
server_rec *base_server)
{
ap_add_version_component(p, "mod_uwsgi/" MOD_UWSGI_VERSION);
return OK;
}
static void *
uwsgi_create_dir_config(apr_pool_t *p, char *dirspec)
{
uwsgi_cfg *cfg = apr_pcalloc(p, sizeof(uwsgi_cfg));
cfg->enabled = UNSET;
cfg->mount.addr = UNSET;
cfg->mount.port = UNSET;
cfg->timeout = UNSET;
cfg->cgi_mode = UNSET;
cfg->modifier1 = UNSET;
cfg->modifier2 = UNSET;
return cfg;
}
#define MERGE(b, n, a) (n->a == UNSET ? b->a : n->a)
static void *
uwsgi_merge_dir_config(apr_pool_t *p, void *basev, void *newv)
{
uwsgi_cfg* cfg = apr_pcalloc(p, sizeof(uwsgi_cfg));
uwsgi_cfg* base = basev;
uwsgi_cfg* new = newv;
cfg->enabled = MERGE(base, new, enabled);
cfg->mount.addr = MERGE(base, new, mount.addr);
cfg->mount.port = MERGE(base, new, mount.port);
cfg->timeout = MERGE(base, new, timeout);
cfg->cgi_mode = MERGE(base, new, cgi_mode);
cfg->modifier1 = MERGE(base, new, modifier1);
cfg->modifier2 = MERGE(base, new, modifier2);
return cfg;
}
static void *
uwsgi_create_server_config(apr_pool_t *p, server_rec *s)
{
uwsgi_server_cfg *c =
(uwsgi_server_cfg *) apr_pcalloc(p, sizeof(uwsgi_server_cfg));
c->mounts = apr_array_make(p, 20, sizeof(mount_entry));
c->timeout = UNSET;
c->cgi_mode = UNSET;
return c;
}
static void *
uwsgi_merge_server_config(apr_pool_t *p, void *basev, void *overridesv)
{
uwsgi_server_cfg *c = (uwsgi_server_cfg *)
apr_pcalloc(p, sizeof(uwsgi_server_cfg));
uwsgi_server_cfg *base = (uwsgi_server_cfg *) basev;
uwsgi_server_cfg *overrides = (uwsgi_server_cfg *) overridesv;
c->mounts = apr_array_append(p, overrides->mounts, base->mounts);
c->timeout = MERGE(base, overrides, timeout);
c->cgi_mode = MERGE(base, overrides, cgi_mode);
return c;
}
static const char *
cmd_uwsgi_mount(cmd_parms *cmd, void *dummy, const char *path, const char *addr)
{
int n;
apr_status_t rv;
char *scope_id = NULL; /* A ip6 parameter - not used here. */
uwsgi_server_cfg *scfg = our_sconfig(cmd->server);
mount_entry *new = apr_array_push(scfg->mounts);
n = strlen(path);
while (n > 0 && path[n-1] == '/') {
n--; /* strip trailing slashes */
}
new->path = apr_pstrndup(cmd->pool, path, n);
rv = apr_parse_addr_port(&new->addr, &scope_id, &new->port, addr,
cmd->pool);
if (rv)
return "error parsing address:port string";
return NULL;
}
static const char *
cmd_uwsgi_server(cmd_parms *cmd, void *pcfg, const char *addr_and_port)
{
apr_status_t rv;
uwsgi_cfg *cfg = pcfg;
char *scope_id = NULL; /* A ip6 parameter - not used here. */
if (cmd->path == NULL)
return "not a server command";
rv = apr_parse_addr_port(&cfg->mount.addr, &scope_id, &cfg->mount.port,
addr_and_port, cmd->pool);
if (rv)
return "error parsing address:port string";
return NULL;
}
static const char *
cmd_uwsgi_handler(cmd_parms* cmd, void* pcfg, int flag)
{
uwsgi_cfg *cfg = pcfg;
if (cmd->path == NULL) /* server command */
return "not a server command";
if (flag)
cfg->enabled = ENABLED;
else
cfg->enabled = DISABLED;
return NULL;
}
static const char *
cmd_uwsgi_timeout(cmd_parms *cmd, void* pcfg, const char *strtimeout)
{
uwsgi_cfg *dcfg = pcfg;
int timeout = atoi(strtimeout);
if (cmd->path == NULL) {
uwsgi_server_cfg *scfg = our_sconfig(cmd->server);
scfg->timeout = timeout;
}
else {
dcfg->timeout = timeout;
}
return NULL;
}
static const char *
cmd_uwsgi_force_cgi_mode(cmd_parms *cmd, void *pcfg, const char *value)
{
int cgi_mode;
if (!strcmp("yes", value) || !strcmp("on", value) || !strcmp("enable", value) || !strcmp("1", value)) {
cgi_mode = 1;
}
else {
cgi_mode = 0;
}
if (cmd->path == NULL) {
uwsgi_server_cfg *scfg = our_sconfig(cmd->server);
scfg->cgi_mode = cgi_mode;
}
else {
uwsgi_cfg *dcfg = pcfg;
dcfg->cgi_mode = cgi_mode;
}
return NULL ;
}
static const char *
cmd_uwsgi_modifier1(cmd_parms *cmd, void *pcfg, const char *value)
{
uwsgi_cfg *cfg = pcfg;
int val ;
if (cmd->path == NULL) /* server command */
return "not a server command";
val = atoi(value);
if (val < 0 || val > 255) {
return "ignored uWSGImodifier1. Value must be between 0 and 255" ;
}
else {
cfg->modifier1 = (uint8_t) val;
}
return NULL;
}
static const char *
cmd_uwsgi_modifier2(cmd_parms *cmd, void *pcfg, const char *value)
{
uwsgi_cfg *cfg = pcfg;
int val ;
if (cmd->path == NULL) /* server command */
return "not a server command";
val = atoi(value);
if (val < 0 || val > 255) {
return "ignored uWSGImodifier2. Value must be between 0 and 255" ;
}
else {
cfg->modifier2 = (uint8_t) val;
}
return NULL;
}
static const command_rec uwsgi_cmds[] = {
AP_INIT_TAKE2("uWSGImount", cmd_uwsgi_mount, NULL, RSRC_CONF,
"path prefix and address of UWSGI server"),
AP_INIT_TAKE1("uWSGIserver", cmd_uwsgi_server, NULL, ACCESS_CONF,
"Address and port of an UWSGI server (e.g. localhost:4000)"),
AP_INIT_FLAG( "uWSGIhandler", cmd_uwsgi_handler, NULL, ACCESS_CONF,
"On or Off to enable or disable the UWSGI handler"),
AP_INIT_TAKE1("uWSGIserverTimeout", cmd_uwsgi_timeout, NULL, ACCESS_CONF|RSRC_CONF,
"Timeout (in seconds) for communication with the UWSGI server."),
AP_INIT_TAKE1("uWSGIforceCGImode", cmd_uwsgi_force_cgi_mode, NULL, ACCESS_CONF|RSRC_CONF,
"Force uWSGI CGI mode for perfect integration with apache filter"),
AP_INIT_TAKE1("uWSGImodifier1", cmd_uwsgi_modifier1, NULL, ACCESS_CONF,
"Set uWSGI modifier1"),
AP_INIT_TAKE1("uWSGImodifier2", cmd_uwsgi_modifier2, NULL, ACCESS_CONF,
"Set uWSGI modifier2"),
/*
AP_INIT_TAKE12("uWSGIsocket", cmd_uwsgi_socket, NULL, RSRC_CONF|ACCESS_CONF,
"Absolute path and optional timeout in seconds of uwsgi server socket"),
AP_INIT_TAKE1("uWSGIsocket2", cmd_uwsgi_socket2, NULL, RSRC_CONF|ACCESS_CONF,
"Absolute path of failover uwsgi server socket"),
AP_INIT_TAKE1("uWSGIforceScriptName", cmd_uwsgi_force_script_name, NULL, ACCESS_CONF,
"Fix for PATH_INFO/SCRIPT_NAME when the location has filesystem correspondence"),
*/
{NULL}
};
static void uwsgi_register_hooks(apr_pool_t *p)
{
ap_hook_post_config(uwsgi_init, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_handler(uwsgi_handler, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_translate_name(uwsgi_translate, NULL, NULL, APR_HOOK_LAST);
ap_hook_map_to_storage(uwsgi_map_location, NULL, NULL, APR_HOOK_FIRST);
}
/* Dispatch list for API hooks */
module AP_MODULE_DECLARE_DATA uwsgi_module = {
STANDARD20_MODULE_STUFF,
uwsgi_create_dir_config, /* create per-dir config structs */
uwsgi_merge_dir_config, /* merge per-dir config structs */
uwsgi_create_server_config, /* create per-server config structs */
uwsgi_merge_server_config, /* merge per-server config structs */
uwsgi_cmds, /* table of config file commands */
uwsgi_register_hooks, /* register hooks */
};
+40 -22
View File
@@ -2,7 +2,7 @@
*** uWSGI/mod_uwsgi ***
Copyright 2009 Unbit S.a.s. <info@unbit.it>
Copyright 2009-2010 Unbit S.a.s. <info@unbit.it>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -456,33 +456,51 @@ static int uwsgi_handler(request_rec *r) {
return HTTP_INTERNAL_SERVER_ERROR;
}
else if (cnt > 0) {
cnt = recv(uwsgi_poll.fd, buf, 4096, 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;
if (uwsgi_poll.revents & POLLIN) {
cnt = recv(uwsgi_poll.fd, buf, 4096, 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);
r->status = atoi(uwsgi_http_status+8);
uwsgi_http_status_read+=cnt;
}
else {
memcpy(uwsgi_http_status+uwsgi_http_status_read, buf, cnt);
uwsgi_http_status_read+=cnt;
}
}
// check for client disconnect
if (r->connection->aborted) {
close(uwsgi_poll.fd);
apr_brigade_destroy(bb);
return HTTP_INTERNAL_SERVER_ERROR;
}
apr_brigade_write(bb, NULL, NULL, buf, cnt);
hret = ap_fflush(r->output_filters, bb) ;
if (hret != APR_SUCCESS) {
close(uwsgi_poll.fd);
apr_brigade_destroy(bb);
return hret;
}
}
else {
break;
}
}
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);
r->status = atoi(uwsgi_http_status+8);
uwsgi_http_status_read+=cnt;
}
else {
memcpy(uwsgi_http_status+uwsgi_http_status_read, buf, cnt);
uwsgi_http_status_read+=cnt;
}
}
apr_brigade_write(bb, NULL, NULL, buf, cnt);
}
else {
if (uwsgi_poll.revents & POLLHUP || uwsgi_poll.revents & POLLERR || uwsgi_poll.revents & POLLNVAL) {
break;
}
}
else {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: poll() %s", strerror(errno));
close(uwsgi_poll.fd);
apr_brigade_destroy(bb);
return HTTP_INTERNAL_SERVER_ERROR;
}
+2 -2
View File
@@ -42,7 +42,7 @@ int async_wait(int queuefd, void *events, int nevents, int block, int timeout) {
timeout = timeout*1000;
}
//fprintf(stderr,"waiting with timeout %d nevents %d\n", timeout, nevents);
//uwsgi_log("waiting with timeout %d nevents %d\n", timeout, nevents);
ret = epoll_wait(queuefd, (struct epoll_event *) events, nevents, timeout);
if (ret < 0) {
uwsgi_error("epoll_wait()");
@@ -139,7 +139,7 @@ int async_wait(int queuefd, void *events, int nevents, int block, int timeout) {
dv.dp_nfds = nevents;
dv.dp_timeout = timeout;
//fprintf(stderr,"waiting with timeout %d nevents %d\n", timeout, nevents);
//uwsgi_log("waiting with timeout %d nevents %d\n", timeout, nevents);
ret = ioctl(queuefd, DP_POLL, &dv);
if (ret < 0) {
uwsgi_error("ioctl()");
+15
View File
@@ -0,0 +1,15 @@
# uWSGI - manage uWSGI application server
#
description "uWSGI"
start on runlevel [2345]
stop on runlevel [!2345]
respawn
env LOGTO=/tmp/uwsgi.log
env BINPATH=/home/foo/uwsgi/uwsgi
# --no-orphans avoid workers without master
exec $BINPATH --no-orphans --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -m simple_app --logto $LOGTO -M -p 4
+282 -274
View File
@@ -1,303 +1,311 @@
# Copyright 2009 Unbit S.a.s. <info@unbit.it>
# see the COPYRIGHT file
require 'rubygems'
require 'socket'
require 'rack'
require 'rack/content_length'
require 'rack/rewindable_input'
require 'stringio'
$stdout.sync = true
options = {}
require 'optparse'
options = {
:processes => 1,
:master => false,
:logging => true,
:static => true,
:config => nil,
:cachehack => false
}
opts = OptionParser.new do |opts|
opts.on("-p", "--processes=nproc", Integer, '') { |p| options[:processes] = p }
opts.on("-M", "--master", '') { options[:master] = true }
opts.on("-L", "--no-logging", '') { options[:logging] = false }
opts.on("-S", "--no-static", '') { options[:static] = false }
opts.on("-C", "--cache-hack", '') { options[:cachehack] = true }
opts.parse! ARGV
end
if ARGV[0]
options[:config] = ARGV[0]
end
def human_round(float)
(float * (10 ** 2)).round / (10 ** 2).to_f
end
$domain = ARGV.last.gsub('[','').gsub(']','')
$unbit_log_base = "[uRack/Unbit on #{$domain}]"
$limit_as = human_round(Process.getrlimit(Process::RLIMIT_AS)[1].to_f/1024/1024)
puts "#{$unbit_log_base} process address space limit is #{$limit_as} MB"
$uidsec_size = syscall(357,0,0)
puts "#{$unbit_log_base} need #{$uidsec_size} bytes to store uidsec_struct..."
$uidsec = '1' * $uidsec_size
puts "#{$unbit_log_base} uidsec_struct allocated."
options[:processes] = 1
options[:serve_file] = nil
options[:max_input_size] = 8
options[:unbit_debug] = false
options[:master] = true
options[:gc_freq] = nil
puts "[#{Time.new}] uRack: loading app [#{RAILS_ROOT}]..."
starttime = Time.now
require "config/environment"
require 'socket'
require 'rubygems'
require 'rack'
require 'rack/utils'
require 'rack/content_length'
$requests = 0
$workers = Array.new
module Rack
module Handler
class Unbit
class Tempfile < ::Tempfile
def _close
@tmpfile.close if @tmpfile
@data[1] = nil if @data
@tmpfile = nil
end
end
def self.run(app, options={})
master_pid = Process.pid
options[:processes] ||= 1
class RailsCachingHack
def initialize app
@app = app
end
server = UNIXServer.for_fd(0)
def stripuri(uri)
uri = uri.split('/')
uri.slice!(1)
val = uri.join('/')
end
def call env
env['PATH_INFO'] = stripuri(env['PATH_INFO']) if env['PATH_INFO']
env['REQUEST_URI'] = stripuri(env['REQUEST_URI']) if env['REQUEST_URI']
env['REQUEST_URI'] = '/' if env['REQUEST_URI'] == ''
@app.call env
end
end
$workers = Array.new
module Handler
class Unbit
if options[:master]
$0 = "uRack #{ARGV.last}"
pid = Process.fork
if pid.to_i > 0
puts "[#{Time.new}] uRack: spawned rack worker 1 (pid: #{pid})"
$workers[1] = pid ;
end
end
def self.run(app, options={})
server = UNIXServer.for_fd(0)
# the check on master pid is necessary
# without it the first worker will execute this part
if options[:processes] > 1 and Process.pid == master_pid
for p in 2..options[:processes]
pid = Process.fork
break if pid.to_i == 0
puts "[#{Time.new}] uRack: spawned rack worker #{p} (pid: #{pid})"
$workers[p] = pid ;
end
end
can_spawn = true
if options[:master]
$0 = 'uRack master'
$workers[0] = Process.pid
ulog("master process enabled (pid: #{$workers[0]})")
$workers[1] = Process.fork
if $workers[1].to_i > 0
ulog("spawned worker 1 (pid: #{$workers[1]})")
elsif $workers[1].to_i == 0
$0 = "uRack worker 1"
can_spawn = false
end
else
$0 = 'uRack worker 1'
$workers[0] = nil
$workers[1] = Process.pid
ulog("spawned worker 1 (pid: #{$workers[1]})")
end
# am i the master ?
if options[:master] and Process.pid == master_pid
Signal.trap('TERM') do
puts "[#{Time.new}] uRack: gracefully killing uRack"
for wid in 1..options[:processes]
Process.kill('TERM', $workers[wid]);
end
exit 0;
end
Signal.trap('QUIT') do
puts "[#{Time.new}] uRack: brutally killing uRack"
for wid in 1..options[:processes]
Process.kill('INT', $workers[wid]);
end
exit 0;
end
puts "[#{Time.new}] uRack: the master process manager is alive."
while 1
pid = Process.waitpid
puts "[#{Time.new}] uRack: worker died ! (pid: #{pid})"
newpid = Process.fork
break if newpid.to_i == 0
puts "[#{Time.new}] uRack: respawned rack worker (pid: #{newpid})"
for wid in 1..options[:processes]
if $workers[wid] == pid
$workers[wid] = newpid
break
end
end
end
end
if Process.pid != master_pid
$0 = $0.gsub(/^uRack/,'urack')
Signal.trap("TERM") do
puts "[#{Time.new}] uRack: grecefully killing process #{Process.pid}..."
if $in_request == 0
puts "[#{Time.new}] uRack: goodbye to process #{Process.pid}"
exit 0
end
$manage_next_request = nil
end
Signal.trap('INT') do
puts "[#{Time.new}] uRack: brutally killing process #{Process.pid}..."
exit 0
end
Signal.trap('PIPE') do
puts "[#{Time.new}] uRack: the webserver (or the client) has closed the connection with process #{Process.pid} !!!"
end
end
max_input_size = options[:max_input_size].to_i * 1024
requests = 0
null_post = StringIO.new('')
options[:app_name] ||= Dir.getwd
app = Rack::ContentLength.new(app)
$manage_next_request = true
if options[:gc_freq].to_i > 1
GC.disable
end
while $manage_next_request
$in_request = 0
client = server.accept
$in_request = 1
timed_out = false
ver, size, arg1 = client.recvfrom(4)[0].unpack('CvC')
vars = client.recvfrom(size)[0]
env = Hash.new
i = 0
while i < size
kl = vars[i, 2].unpack('v')[0]
i = i + 2
key = vars[i, kl]
i = i + kl
vl = vars[i, 2].unpack('v')[0]
i = i + 2
value = vars[i, vl]
i = i + vl
env[key] = value
end
rack_input = null_post
env.delete 'CONTENT_LENGTH' if env['CONTENT_LENGTH'] == ''
if env['CONTENT_LENGTH'].to_i > 0
cl = env['CONTENT_LENGTH'].to_i
if cl <= max_input_size
poststr = ''
while poststr.size < cl
poststr = poststr + client.recvfrom(cl-poststr.size)[0] ;
end
rack_input = StringIO.new(poststr)
else
rack_input = Tempfile.new('UnbitRack')
rack_input.chmod(0000)
bytes_read = 0
while bytes_read < cl
buf = client.recvfrom(4096)[0]
rack_input.write(buf)
bytes_read += buf.size
end
rack_input.rewind
end
end
env["SCRIPT_NAME"] = ""
env.update({"rack.version" => [0,1],
"rack.input" => rack_input,
"rack.errors" => $stderr,
"rack.multithread" => false,
"rack.multiprocess" => true,
"rack.run_once" => false,
"rack.url_scheme" => "http"
})
env["QUERY_STRING"] ||= ""
env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
env["REQUEST_PATH"] ||= "/"
begin
#puts env.inspect
$start_of_request = Time.new
status, headers, body = app.call(env)
$speed = Time.new - $start_of_request
client.print "#{env["HTTP_VERSION"]} #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]}\r\n"
headers.each {|k,vs|
vs.split("\n").each { |v|
client.print "#{k}: #{v}\r\n"
}
}
client.print "\r\n"
client.flush
body.each {|part|
client.print part
client.flush
}
rescue Errno::EPIPE
puts "[#{Time.new}] uRack: the webserver (or the client) has closed the connection with process #{Process.pid} !!!"
timed_out = true
ensure
if rack_input.respond_to? :unlink
rack_input.unlink
end
unless rack_input.closed?
rack_input.close
end
client.close
requests = requests+1
# logging
$stderr.puts "[#{Time.new}] uRack: [#{options[:app_name]}] req: #{requests} ip: #{env['REMOTE_ADDR']} pid: #{Process.pid} as: #{human_round(syscall(356).to_f/1024/1024)} MB => #{env['REQUEST_METHOD']} #{env['REQUEST_URI']} in #{$speed} secs [#{status}]#{' TIMED OUT !!!' if timed_out}"
if syscall(357, $uidsec, 0) == $uidsec_size
if $uidsec[120..123].unpack('i')[0] > 0
$stderr.puts "[#{Time.new}] uRack: found a memory allocation error for request #{requests} (pid: #{Process.pid}). Better to kill myself..."
$manage_next_request = nil
end
end
$uidsec = '1' * $uidsec_size
if options[:unbit_debug]
current_as = human_round( (syscall(356).to_f/1024/1024) - $last_as )
$stderr.puts "#{$unbit_log_base} resource status after request #{requests}: AS for this request: #{current_as} MB | OBJ for this request: #{ObjectSpace.each_object {} - $last_obj} | OBJ total: #{ObjectSpace.each_object {}}"
$last_as = human_round(syscall(356).to_f/1024/1024) ;
$last_obj = ObjectSpace.each_object {}
end
if options[:gc_freq].to_i > 1
if requests % options[:gc_freq].to_i == 0
$stderr.puts "[#{Time.new}] uRack: [#{options[:app_name]}] calling GC for pid #{Process.pid} after #{requests} requests."
GC.enable ; GC.start ; GC.disable
end
end
end
end
puts "[#{Time.new}] uRack: goodbye to process #{Process.pid}"
if options[:processes] > 1 and can_spawn
for p in 2..options[:processes]
$workers[p] = Process.fork
if $workers[p].to_i == 0
$0 = "uRack worker #{p}"
break
elsif $workers[p].to_i > 0
ulog("spawned worker #{p} (pid: #{$workers[p]})")
end
end
end
# am i the master ?
if options[:master] and Process.pid == $workers[0]
while 1
i_am_a_child = false
pid = Process.waitpid
for wid in 1..options[:processes]
if $workers[wid] == pid
ulog("worker #{wid} died ! (pid: #{pid})")
$workers[wid] = Process.fork
if $workers[wid].to_i == 0
$0 = "uRack worker #{wid}"
i_am_a_child = true
break
elsif $workers[wid].to_i > 0
ulog("respawned worker #{wid} (pid: #{$workers[wid]})")
end
end
end
break if i_am_a_child
end
end
while client = server.accept
serve client, app, options
end
end
def self.serve(client, app, options)
speed = Time.now
head, sender = client.recvfrom(4)
unless head
client.close
return
end
mod1, size, mod2 = head.unpack('CvC')
if size == 0 or size.nil?
client.close
return
end
vars, sender = client.recvfrom(size)
if vars.length != size
client.close
return
end
env = Hash.new
i = 0
while i < size
kl = vars[i, 2].unpack('v')[0]
i = i + 2
key = vars[i, kl]
i = i + kl
vl = vars[i, 2].unpack('v')[0]
i = i + 2
value = vars[i, vl]
i = i + vl
env[key] = value
end
env.delete "HTTP_CONTENT_LENGTH"
env.delete "HTTP_CONTENT_TYPE"
env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/"
env["QUERY_STRING"] ||= ""
env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
env["REQUEST_PATH"] ||= "/"
env.delete "PATH_INFO" if env["PATH_INFO"] == ""
env.delete "CONTENT_TYPE" if env["CONTENT_TYPE"] == ""
env.delete "CONTENT_LENGTH" if env["CONTENT_LENGTH"] == ""
if env["CONTENT_LENGTH"].to_i > 4096
rack_input = Rack::RewindableInput::Tempfile.new('Rack_unbit_Input')
rack_input.chmod(0000)
rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding)
rack_input.binmode
rack_input.unlink
remains = env["CONTENT_LENGTH"].to_i
while remains > 0
if remains >= 4096
buf, sender = client.recvfrom(4096)
else
buf, sender = client.recvfrom(remains)
end
if buf.length == 0
break
end
rack_input.write( buf )
remains -= buf.length
end
elsif env["CONTENT_LENGTH"].to_i > 0
rack_input = StringIO.new(client.recvfrom(env["CONTENT_LENGTH"].to_i)[0])
else
rack_input = StringIO.new('')
end
rack_input.rewind
env.update({"rack.version" => [1,1],
"rack.input" => rack_input,
"rack.errors" => $stderr,
"rack.multithread" => false,
"rack.multiprocess" => true,
"rack.run_once" => false,
"rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http"
})
app = Rack::ContentLength.new(app)
disconnected = false
begin
status, headers, body = app.call(env)
begin
send_headers client, env["HTTP_VERSION"] ,status, headers
send_body client, body
ensure
body.close if body.respond_to? :close
end
rescue Errno::EPIPE, Errno::ECONNRESET
disconnected = true
ensure
rack_input.close
client.close
end
$requests = $requests+1
ulog("req: #{$requests} ip: #{env['REMOTE_ADDR']} pid: #{Process.pid} as: #{human_round(syscall(356).to_f/1024/1024)} MB => #{env['REQUEST_METHOD']} #{env['REQUEST_URI']} in #{Time.now-speed} secs [#{status}]#{' DISCONNECTED !!!' if disconnected}") if options[:logging]
end
def self.send_headers(client, protocol, status, headers)
client.print "#{protocol} #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]}\r\n"
headers.each { |k, vs|
vs.split("\n").each { |v|
client.print "#{k}: #{v}\r\n"
}
}
client.print "\r\n"
client.flush
end
def self.send_body(client, body)
body.each { |part|
client.print part
client.flush
}
end
end
end
end
def ulog(message)
$stderr.puts "[#{Time.new}] uRack: #{message}"
end
ulog("starting at #{Dir.getwd}")
limit_as = human_round(Process.getrlimit(Process::RLIMIT_AS)[1].to_f/1024/1024)
ulog("your process address space limit is #{limit_as} MB")
server = Rack::Handler.get('Unbit')
app = Rack::Builder.new {
if options[:serve_file]
puts "[#{Time.new}] uRack: file serving enabled."
use Rails::Rack::Static
starttime = Time.now
app = nil
if options[:config]
cfgfile = File.read(options[:config])
if cfgfile[/^#\\(.*)/]
opts.parse! $1.split(/\s+/)
end
if ActionController.const_defined?(:Dispatcher) && (ActionController::Dispatcher.instance_methods.include?(:call) || ActionController::Dispatcher.instance_methods.include?("call"))
run ActionController::Dispatcher.new
app = eval "Rack::Builder.new {( " + cfgfile + "\n )}.to_app", nil, options[:config]
else
# falling back to rails
if Dir.getwd =~ /\/public\/?$/
require '../config/environment'
else
require 'thin'
run Rack::Adapter::Rails.new(:environment => ENV['RAILS_ENV'])
require 'config/environment'
end
}.to_app
app = Rack::Builder.new {
if options[:cachehack]
use Rack::RailsCachingHack
end
if options[:static]
use Rails::Rack::Static
end
if ActionController.const_defined?(:Dispatcher) && (ActionController::Dispatcher.instance_methods.include?(:call) || ActionController::Dispatcher.instance_methods.include?("call"))
run ActionController::Dispatcher.new
else
require 'thin'
run Rack::Adapter::Rails.new(:environment => ENV['RAILS_ENV'])
end
}
end
$after_spawn_used_as = human_round(syscall(356).to_f/1024/1024)
$stderr.puts "#{$unbit_log_base} now you have #{$limit_as-$after_spawn_used_as} MB of address space available (used #{$after_spawn_used_as}MB after app startup)"
secs = Time.now-starttime
puts "[#{Time.new}] uRack: ready to serve requests after #{secs.to_i} secs (pid: #{Process.pid})"
ulog("your app is ready (in #{Time.now-starttime} seconds).")
$last_as = $after_spawn_used_as ;
$last_obj = ObjectSpace.each_object {}
server.run(app, options)
-6
View File
@@ -1,6 +0,0 @@
Package: uwsgi
Version: 0.9.2
Maintainer: Unbit
Description: Fast, developer-friendly wsgi server
Architecture: i386
Depends: python2.5, libxml2
+1
View File
@@ -59,6 +59,7 @@
{% if masterpid %}
<br/>
<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="reload/" method="post">
{% csrf_token %}
<input type="submit" value="gracefully reload uWSGI" name="_reload"/>
</form>
{% endif %}
+13 -13
View File
@@ -318,7 +318,7 @@ int init_erlang(char *nodename, char *cookie) {
ip = strchr(nodename, '@');
if (ip == NULL) {
fprintf(stderr, "*** invalid erlang node name ***\n");
uwsgi_log( "*** invalid erlang node name ***\n");
return -1;
}
@@ -326,7 +326,7 @@ int init_erlang(char *nodename, char *cookie) {
// get the cookie from the home
cookiehome = getenv("HOME");
if (!cookiehome) {
fprintf(stderr, "unable to get erlang cookie from your home.\n");
uwsgi_log( "unable to get erlang cookie from your home.\n");
return -1;
}
cookiefile = malloc(strlen(cookiehome) + 1 + strlen(".erlang.cookie") + 1);
@@ -346,7 +346,7 @@ int init_erlang(char *nodename, char *cookie) {
memset(cookievalue, 0, 128);
if (read(cookiefd, cookievalue, 127) < 1) {
fprintf(stderr, "invalid cookie found in %s\n", cookiefile);
uwsgi_log( "invalid cookie found in %s\n", cookiefile);
close(cookiefd);
free(cookiefile);
return -1;
@@ -367,7 +367,7 @@ int init_erlang(char *nodename, char *cookie) {
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");
uwsgi_log( "*** unable to initialize erlang c-node ***\n");
return -1;
}
@@ -409,12 +409,12 @@ int init_erlang(char *nodename, char *cookie) {
}
if (erl_publish(ntohs(e_addr.sin_port)) < 0) {
fprintf(stderr, "*** unable to subscribe with EPMD ***\n");
uwsgi_log( "*** 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);
uwsgi_log( "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);
@@ -512,7 +512,7 @@ ETERM *py_to_eterm(PyObject * pobj) {
free(eobj3);
}
else {
fprintf(stderr, "UNMANAGED PYTHON TYPE: %s\n", pobj->ob_type->tp_name);
uwsgi_log( "UNMANAGED PYTHON TYPE: %s\n", pobj->ob_type->tp_name);
}
clear:
@@ -560,7 +560,7 @@ PyObject *eterm_to_py(ETERM * obj) {
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));
uwsgi_log( "FOUND A BINARY %.*s\n", ERL_BIN_SIZE(obj), ERL_BIN_PTR(obj));
break;
case ERL_PID:
eobj = PyDict_New();
@@ -581,7 +581,7 @@ PyObject *eterm_to_py(ETERM * obj) {
break;
}
default:
fprintf(stderr, "UNMANAGED ETERM TYPE: %d\n", ERL_TYPE(obj));
uwsgi_log( "UNMANAGED ETERM TYPE: %d\n", ERL_TYPE(obj));
break;
}
@@ -603,13 +603,13 @@ void erlang_loop(struct wsgi_request *wsgi_req) {
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");
uwsgi_log( "- 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");
uwsgi_log( "- error preparing arg tuple for uwsgi.erlang_func callable, Erlang message manager will be disabled -\n");
}
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
@@ -632,7 +632,7 @@ void erlang_loop(struct wsgi_request *wsgi_req) {
}
if (!callable) {
fprintf(stderr, "- you still have not defined a uwsgi.erlang_func callable, Erlang message rejected -\n");
uwsgi_log( "- you still have not defined a uwsgi.erlang_func callable, Erlang message rejected -\n");
}
PyObject *zero = eterm_to_py(em.msg);
@@ -694,7 +694,7 @@ static void erlang_log() {
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);
uwsgi_log( "[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
+15
View File
@@ -0,0 +1,15 @@
#ifdef UWSGI_EVDIS
#include "uwsgi.h"
void evdis_loop(struct uwsgi_server *uwsgi) {
// populate event list
}
#else
#warning "*** Event Dispatcher support is disabled ***"
#endif
+34
View File
@@ -0,0 +1,34 @@
#ifdef __linux__
#include <sys/inotify.h>
int uwsgi_file_monitor_new() {
int inotify_fd ;
inotify_fd = inotify_init();
if (inotify_fd < 0) {
uwsgi_error("inotify_init()");
return -1;
}
return inotify_fd ;
}
int uwsgi_file_monitor_add(int fd, char *what) {
int inotify_watch_fd ;
inotify_watch_fd = inotify_add_watch(fd, what, IN_ALL_EVENTS);
if (inotify_watch_fd < 0) {
uwsgi_error("inotify_add_watch()");
return -1;
}
return inotify_watch_fd;
}
#endif
+384
View File
@@ -0,0 +1,384 @@
#include "uwsgi.h"
struct uwsgi_server uwsgi;
struct uwsgi_http_req {
pthread_t a_new_thread;
int fd;
struct sockaddr_in c_addr;
socklen_t c_len;
};
enum {
uwsgi_http_method,
uwsgi_http_uri,
uwsgi_http_protocol,
uwsgi_http_protocol_r,
uwsgi_http_header_key,
uwsgi_http_header_key_colon,
uwsgi_http_header_val,
uwsgi_http_header_val_r,
uwsgi_http_end
};
void http_end() {
uwsgi_log("closing uWSGI embedded HTTP server.\n");
exit(0);
}
void http_wait_end() {
pid_t wp_p;
int wp_c;
wp_p = waitpid(-1, &wp_c, 0);
uwsgi_log("closing uWSGI embedded HTTP server.\n");
exit(0);
}
static char *add_uwsgi_var(char *up, char *key, uint16_t keylen, char *val, uint16_t vallen, int header, char *watermark)
{
int i;
if (!header) {
if ( (up + 2 + keylen + 2 + vallen) > watermark ) return up ;
*up++ = (unsigned char) (keylen & 0xff);
*up++ = (unsigned char) ((keylen >> 8) & 0xff);
memcpy(up, key, keylen);
up += keylen;
} else {
for (i = 0; i < keylen; i++) {
if (key[i] == '-') {
key[i] = '_';
} else {
key[i] = toupper( (int) key[i]);
}
}
if (strncmp("CONTENT_TYPE", key, keylen) && strncmp("CONTENT_LENGTH", key, keylen)) {
if ( (up + 2 + keylen + 5 + 2 + vallen) > watermark ) return up ;
*up++ = (unsigned char) (((uint16_t) keylen + 5) & 0xff);
*up++ = (unsigned char) ((((uint16_t) keylen + 5) >> 8) & 0xff);
memcpy(up, "HTTP_", 5);
up += 5;
} else {
if ( (up + 2 + keylen + 2 + vallen) > watermark ) return up ;
*up++ = (unsigned char) (keylen & 0xff);
*up++ = (unsigned char) ((keylen >> 8) & 0xff);
}
memcpy(up, key, keylen);
up += keylen;
}
*up++ = (unsigned char) (vallen & 0xff);
*up++ = (unsigned char) ((vallen >> 8) & 0xff);
memcpy(up, val, vallen);
up += vallen;
return up;
}
static void *http_request(void *);
void http_loop(struct uwsgi_server * uwsgi)
{
struct uwsgi_http_req *ur;
int ret;
pthread_attr_t pa;
int stat_loc ;
ret = pthread_attr_init(&pa);
if (ret) {
uwsgi_log("pthread_attr_init() = %d\n", ret);
exit(1);
}
ret = pthread_attr_setdetachstate(&pa, PTHREAD_CREATE_DETACHED);
if (ret) {
uwsgi_log("pthread_attr_setdetachstate() = %d\n", ret);
exit(1);
}
// ignore broken pipes;
signal(SIGPIPE, SIG_IGN);
if (!uwsgi->http_only) {
signal(SIGCHLD, &http_end);
signal(SIGINT, &http_wait_end);
}
else {
signal(SIGINT, &http_end);
}
uwsgi->http_server_name = malloc(256);
if (!uwsgi->http_server_name) {
uwsgi_error("malloc()");
exit(1);
}
memset(uwsgi->http_server_name, 0, 256);
if (gethostname(uwsgi->http_server_name, 255)) {
uwsgi_error("gethostname()");
memcpy(uwsgi->http_server_name, "localhost", 9);
}
uwsgi_log("starting HTTP loop on %s (pid: %d)\n", uwsgi->http_server_name, (int) getpid());
for(;;) {
if (!uwsgi->http_only) {
if (waitpid(-1, &stat_loc, WNOHANG) != 0) {
http_end();
}
}
ur = malloc(sizeof(struct uwsgi_http_req));
if (!ur) {
uwsgi_error("malloc()");
sleep(1);
continue;
}
ur->c_len = sizeof(struct sockaddr_in) ;
ur->fd = accept(uwsgi->http_fd, (struct sockaddr *) &ur->c_addr, &ur->c_len);
if (ur->fd < 0) {
uwsgi_error("accept()");
free(ur);
continue;
}
ret = pthread_create(&ur->a_new_thread, &pa, http_request, (void *) ur);
if (ret) {
uwsgi_log("pthread_create() = %d\n", ret);
free(ur);
// sleep a bit to allow some resource gaining
sleep(1);
continue;
}
}
}
static void *http_request(void *u_h_r)
{
char buf[4096];
char tmp_buf[4096];
char *ptr;
char uwsgipkt[4096];
char *up;
struct uwsgi_http_req *ur = (struct uwsgi_http_req *) u_h_r ;
int clientfd = ur->fd;
int uwsgi_fd;
int need_to_read = 1;
int state = uwsgi_http_method;
int http_body_len = 0;
size_t len;
int i, j;
char HTTP_header_key[1024];
uint16_t ulen;
ptr = tmp_buf;
int qs = 0;
up = uwsgipkt;
char *watermark = up + 4096 ;
char *watermark2 = tmp_buf + 4096 ;
up[0] = 0;
up[3] = 0;
up += 4;
while (need_to_read) {
len = read(clientfd, buf, 4096);
if (len <= 0) {
uwsgi_error("read()");
break;
}
for (i = 0; i < len; i++) {
if (buf[i] == ' ') {
if (state == uwsgi_http_method) {
up = add_uwsgi_var(up, "REQUEST_METHOD", 14, tmp_buf, ptr - tmp_buf, 0, watermark);
ptr = tmp_buf;
state = uwsgi_http_uri;
} else if (state == uwsgi_http_uri) {
up = add_uwsgi_var(up, "REQUEST_URI", 11, tmp_buf, ptr - tmp_buf, 0, watermark);
int path_info_len = ptr - tmp_buf;
for (j = 0; j < ptr - tmp_buf; j++) {
if (tmp_buf[j] == '?') {
path_info_len = j;
if (j + 1 < (ptr - tmp_buf)) {
up = add_uwsgi_var(up, "QUERY_STRING", 12, tmp_buf + j + 1, (ptr - tmp_buf) - (j + 1), 0, watermark);
qs = 1 ;
}
break;
}
}
if (!qs) {
up = add_uwsgi_var(up, "QUERY_STRING", 12, NULL, 0, 0, watermark);
}
up = add_uwsgi_var(up, "PATH_INFO", 9, tmp_buf, path_info_len, 0, watermark);
ptr = tmp_buf;
state = uwsgi_http_protocol;
} else if (state == uwsgi_http_header_key_colon) {
if (ptr+1 > watermark2) { close(uwsgi_fd); goto clear;}
*ptr++ = 0;
memset(HTTP_header_key, 0, sizeof(HTTP_header_key));
memcpy(HTTP_header_key, tmp_buf, strlen(tmp_buf));
ptr = tmp_buf;
state = uwsgi_http_header_val;
} else {
//check for overflow
if (ptr+1 > watermark2) { close(uwsgi_fd); goto clear;}
*ptr++ = buf[i];
}
} else if (buf[i] == '\r') {
if (state == uwsgi_http_protocol) {
state = uwsgi_http_protocol_r;
}
if (state == uwsgi_http_header_val) {
state = uwsgi_http_header_val_r;
} else if (state == uwsgi_http_header_key) {
state = uwsgi_http_end;
}
} else if (buf[i] == '\n') {
if (state == uwsgi_http_header_val_r) {
up = add_uwsgi_var(up, HTTP_header_key, strlen(HTTP_header_key), tmp_buf, ptr - tmp_buf, 1, watermark);
if (!strcmp("CONTENT_LENGTH", HTTP_header_key)) {
if (ptr+1 > watermark2) { close(uwsgi_fd); goto clear;}
*ptr++ = 0;
http_body_len = atoi(tmp_buf);
}
ptr = tmp_buf;
state = uwsgi_http_header_key;
} else if (state == uwsgi_http_protocol_r) {
up = add_uwsgi_var(up, "SERVER_PROTOCOL", 15, tmp_buf, ptr - tmp_buf, 0, watermark);
ptr = tmp_buf;
state = uwsgi_http_header_key;
} else if (state == uwsgi_http_end) {
need_to_read = 0;
up = add_uwsgi_var(up, "SERVER_NAME", 11, uwsgi.http_server_name, strlen(uwsgi.http_server_name), 0, watermark);
up = add_uwsgi_var(up, "SERVER_PORT", 11, uwsgi.http_server_port, strlen(uwsgi.http_server_port), 0, watermark);
up = add_uwsgi_var(up, "SCRIPT_NAME", 11, "", 0, 0, watermark);
char *ip = inet_ntoa(ur->c_addr.sin_addr);
up = add_uwsgi_var(up, "REMOTE_ADDR", 11, ip, strlen(ip), 0, watermark);
//up = add_uwsgi_var(up, "REMOTE_ADDR", 11, "127.0.0.1", 9, 0, watermark);
//up = add_uwsgi_var(up, "REMOTE_USER", 11, "unknown", 7, 0);
for(j=0;j<uwsgi.http_vars_cnt;j++) {
char *separator;
separator = strchr(uwsgi.http_vars[j], '=');
if (separator) {
up = add_uwsgi_var(up, uwsgi.http_vars[j], separator - uwsgi.http_vars[j], separator + 1, strlen(separator + 1), 0, watermark);
}
else {
up = add_uwsgi_var(up, uwsgi.http_vars[j], strlen(uwsgi.http_vars[j]), NULL, 0, 0, watermark);
}
}
uwsgi_fd = uwsgi_connect(uwsgi.socket_name, 10);
if (uwsgi_fd >= 0) {
ulen = (up - uwsgipkt) - 4;
uwsgipkt[1] = (unsigned char) (ulen & 0xff);
uwsgipkt[2] = (unsigned char) ((ulen >> 8) & 0xff);
write(uwsgi_fd, uwsgipkt, ulen + 4);
if (http_body_len > 0) {
if (http_body_len >= len - (i + 1)) {
write(uwsgi_fd, buf + i + 1, len - (i + 1));
http_body_len -= len - (i + 1);
} else {
write(uwsgi_fd, buf + i, http_body_len);
http_body_len = 0;
}
while (http_body_len > 0) {
int to_read = 4096;
if (http_body_len < to_read) {
to_read = http_body_len;
}
len = read(clientfd, uwsgipkt, to_read);
write(uwsgi_fd, uwsgipkt, len);
http_body_len -= len;
}
}
while ((len = read(uwsgi_fd, uwsgipkt, 4096)) > 0) {
write(clientfd, uwsgipkt, len);
}
close(uwsgi_fd);
}
else {
close(uwsgi_fd);
goto clear;
}
}
} else if (buf[i] == ':') {
if (state == uwsgi_http_header_key) {
state = uwsgi_http_header_key_colon;
} else {
//check for overflow
if (ptr+1 > watermark2) { close(uwsgi_fd); goto clear;}
*ptr++ = buf[i];
}
} else {
//check for overflow
if (ptr+1 > watermark2) { close(uwsgi_fd); goto clear;}
*ptr++ = buf[i];
}
}
}
clear:
close(clientfd);
free(ur);
pthread_exit(NULL);
}
+185
View File
@@ -0,0 +1,185 @@
#ifdef UWSGI_INI
#include "uwsgi.h"
/*
ini file must be read ALL into memory.
This memory must not be freed for all the server lifecycle
*/
enum {
ini_key_start,
ini_val_start,
};
void ini_rstrip(char *line) {
off_t i ;
for(i = strlen(line)-1;i>=0; i--) {
if (line[i] == ' ' || line[i] == '\t') {
line[i] = 0;
continue;
}
break;
}
}
char *ini_lstrip(char *line) {
off_t i ;
char *ptr = line;
for(i=0;i<strlen(line);i++) {
if (line[i] == ' ' || line[i] == '\t') {
ptr++;
continue;
}
break;
}
return ptr;
}
char *ini_get_key(char *key) {
off_t i;
char *ptr = key ;
for(i=0;i<strlen(key);i++) {
ptr++ ;
if (key[i] == '=') {
key[i] = 0;
return ptr;
}
}
return ptr;
}
char *ini_get_line(char *ini, off_t size) {
off_t i ;
char *ptr = ini;
for(i=0;i<size;i++) {
ptr++;
if (ini[i] == '\n') {
ini[i] = 0;
return ptr;
}
}
return NULL;
}
void uwsgi_ini_config(char *file, struct option *long_options) {
int fd;
ssize_t len;
char *ini;
struct stat sb;
char *ini_line;
char *section = "";
char *key;
char *val;
int lines = 1 ;
struct option *lopt, *aopt;
char *section_asked = "uwsgi";
char *colon ;
colon = strchr(file, ':');
if (colon) {
colon[0] = 0;
if (colon[1] != 0) {
section_asked = colon+1 ;
}
}
fd = open(file, O_RDONLY);
if (fd < 0) {
uwsgi_error("open()");
exit(1);
}
if (fstat(fd, &sb)) {
uwsgi_error("fstat()");
exit(1);
}
ini = malloc(sb.st_size+1);
if (!ini) {
uwsgi_error("malloc()");
exit(1);
}
len = read(fd, ini, sb.st_size);
if (len != sb.st_size) {
uwsgi_error("read()");
exit(1);
}
ini[sb.st_size+1] = 0 ;
while(sb.st_size) {
ini_line = ini_get_line(ini, sb.st_size);
if (ini_line == NULL) {
break;
}
lines++;
// skip empty line
key = ini_lstrip(ini);
ini_rstrip(key);
if (key[0] != 0) {
if (key[0] == '[') {
section = key+1;
section[strlen(section)-1] = 0;
}
else if (key[0] == ';' || key[0] == '#') {
// this is a comment
}
else {
// val is always valid, but (obviously can be ignored)
val = ini_get_key(key);
if (!strcmp(section, section_asked)) {
ini_rstrip(key);
val = ini_lstrip(val);
ini_rstrip(val);
lopt = long_options;
while ((aopt = lopt)) {
if (!aopt->name)
break;
if (!strcmp(key, aopt->name)) {
if (aopt->flag) {
*aopt->flag = aopt->val;
}
else {
manage_opt(aopt->val, val);
}
}
lopt++;
}
}
}
}
ini += (ini_line - ini);
sb.st_size -= (ini_line - ini);
}
close(fd);
}
#endif
+352
View File
@@ -0,0 +1,352 @@
#ifdef UWSGI_LDAP
#include "uwsgi.h"
#include <ldap.h>
void ldap2uwsgi(char *ldapname, char *uwsginame) {
char *ptr = uwsginame ;
int i;
for(i=0;i<strlen(ldapname);i++) {
if (isupper( (int)ldapname[i])) {
*ptr++= '-';
*ptr++= tolower( (int) ldapname[i]);
}
else {
*ptr++= ldapname[i] ;
}
}
*ptr++= 0;
}
int calc_ldap_name(char *name) {
int i;
int counter = 0;
for(i=0;i<strlen(name);i++) {
if (isupper( (int) name[i])) {
counter++;
}
}
return strlen(name) + counter ;
}
void uwsgi_ldap_schema_dump_ldif(struct option *lo) {
struct option *aopt, *lopt ;
lopt = lo;
int i;
int counter = 30000;
int pythonpath_found = 0 ;
uwsgi_log("\n");
uwsgi_log("dn: cn=uwsgi,cn=schema,cn=config\n");
uwsgi_log("objectClass: olcSchemaConfig\n");
uwsgi_log("cn: uwsgi\n");
while( (aopt = lopt) ) {
if (!aopt->name)
break;
if (aopt->val == LONG_ARGS_PYTHONPATH) {
if (pythonpath_found) {
goto next;
}
pythonpath_found = 1;
}
if (aopt->flag) {
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.%d NAME 'uWSGI", counter) ;
counter++;
}
else {
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.%d NAME 'uWSGI", aopt->val) ;
}
for(i=0;i<strlen(aopt->name);i++) {
if (aopt->name[i] == '-') {
i++;
uwsgi_log("%c", toupper( (int) aopt->name[i]));
}
else {
uwsgi_log("%c", aopt->name[i]);
}
}
if (aopt->has_arg) {
uwsgi_log("' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
else {
uwsgi_log("' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
next:
lopt++;
}
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n") ;
lopt = lo;
uwsgi_log("olcObjectClasses: ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
pythonpath_found = 0;
while( (aopt = lopt) ) {
if (!aopt->name)
break;
if (aopt->val == LONG_ARGS_PYTHONPATH) {
if (pythonpath_found) {
goto next2;
}
pythonpath_found = 1;
}
uwsgi_log("uWSGI");
for(i=0;i<strlen(aopt->name);i++) {
if (aopt->name[i] == '-') {
i++;
uwsgi_log("%c", toupper( (int) aopt->name[i]));
}
else {
uwsgi_log("%c", aopt->name[i]);
}
}
uwsgi_log(" $ ");
next2:
lopt++;
}
uwsgi_log("uWSGInull ))\n");
uwsgi_log("\n");
exit(0);
}
void uwsgi_ldap_schema_dump(struct option *lo) {
struct option *aopt, *lopt ;
lopt = lo;
int i;
int counter = 30000;
int pythonpath_found = 0;
while( (aopt = lopt) ) {
if (!aopt->name)
break;
if (aopt->val == LONG_ARGS_PYTHONPATH) {
if (pythonpath_found) {
goto next;
}
pythonpath_found = 1;
}
if (aopt->flag) {
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.%d NAME 'uWSGI", counter) ;
counter++;
}
else {
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.%d NAME 'uWSGI", aopt->val) ;
}
for(i=0;i<strlen(aopt->name);i++) {
if (aopt->name[i] == '-') {
i++;
uwsgi_log("%c", toupper( (int) aopt->name[i]));
}
else {
uwsgi_log("%c", aopt->name[i]);
}
}
if (aopt->has_arg) {
uwsgi_log("' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
else {
uwsgi_log("' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
next:
lopt++;
}
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n") ;
lopt = lo;
uwsgi_log("objectclass ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
pythonpath_found = 0;
while( (aopt = lopt) ) {
if (!aopt->name)
break;
if (aopt->val == LONG_ARGS_PYTHONPATH) {
if (pythonpath_found) {
goto next2;
}
pythonpath_found = 1;
}
uwsgi_log("uWSGI");
for(i=0;i<strlen(aopt->name);i++) {
if (aopt->name[i] == '-') {
i++;
uwsgi_log("%c", toupper( (int) aopt->name[i]));
}
else {
uwsgi_log("%c", aopt->name[i]);
}
}
uwsgi_log(" $ ");
next2:
lopt++;
}
uwsgi_log("uWSGInull ))\n");
exit(0);
}
void uwsgi_ldap_config(struct uwsgi_server *uwsgi, struct option *long_options) {
LDAP *ldp;
LDAPMessage *results, *entry;
BerElement *ber;
struct berval **bervalues;
char *attr;
char *uwsgi_attr;
char *url = "ldap:///";
char *url_slash;
int desired_version = LDAP_VERSION3;
int ret;
struct option *aopt, *lopt;
LDAPURLDesc *ldap_url;
if (uwsgi->ldap) {
url = uwsgi->ldap;
}
if (!ldap_is_ldap_url(url)) {
uwsgi_log("invalid LDAP url.\n");
exit(1);
}
if (ldap_url_parse(url, &ldap_url) != LDAP_SUCCESS) {
uwsgi_log("unable to parse LDAP url.\n");
exit(1);
}
url_slash = strchr(url, '/');
url_slash = strchr(url_slash + 1, '/');
url_slash = strchr(url_slash + 1, '/');
if (url_slash) {
url_slash[0] = 0;
}
#ifdef UWSGI_DEBUG
uwsgi_debug("LDAP URL: %s\n", url);
uwsgi_debug("LDAP BASE DN: %s\n", ldap_url->lud_dn);
#endif
if ( (ret = ldap_initialize( &ldp, url)) != LDAP_SUCCESS) {
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
exit(1);
}
if ( (ret = ldap_set_option(ldp, LDAP_OPT_PROTOCOL_VERSION, &desired_version)) != LDAP_OPT_SUCCESS) {
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
exit(1);
}
if ( (ret = ldap_search_ext_s(ldp, ldap_url->lud_dn, ldap_url->lud_scope, ldap_url->lud_filter, NULL, 0, NULL, NULL, NULL, 1, &results)) != LDAP_SUCCESS) {
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
exit(1);
}
#ifdef UWSGI_DEBUG
uwsgi_debug("LDAP connection initialized %p\n", ldp);
#endif
free(ldap_url);
if (ldap_count_entries(ldp, results) < 1) {
uwsgi_log("no LDAP entry found\n");
exit(1);
}
entry = ldap_first_entry(ldp, results);
for( attr = ldap_first_attribute(ldp, entry, &ber); attr != NULL; attr = ldap_next_attribute(ldp, entry, ber)) {
if (!strncmp(attr,"uWSGI",5)) {
uwsgi_attr = malloc( calc_ldap_name(attr) + 1 );
if (!uwsgi_attr) {
uwsgi_error("malloc()");
exit(1);
}
ldap2uwsgi(attr+5, uwsgi_attr);
#ifdef UWSGI_DEBUG
uwsgi_debug("LDAP attribute: %s = --%s\n", attr, uwsgi_attr);
#endif
bervalues = ldap_get_values_len(ldp, entry, attr);
if (bervalues) {
// do not free uwsgi_val;
char *uwsgi_val = malloc( bervalues[0]->bv_len + 1 );
if (!uwsgi_val) {
uwsgi_error("malloc()");
exit(1);
}
memcpy(uwsgi_val, bervalues[0]->bv_val, bervalues[0]->bv_len);
uwsgi_val[bervalues[0]->bv_len] = 0;
lopt = long_options;
while ((aopt = lopt)) {
if (!aopt->name)
break;
if (!strcmp(uwsgi_attr, aopt->name)) {
if (aopt->flag) {
*aopt->flag = aopt->val;
}
else {
manage_opt(aopt->val, uwsgi_val);
}
}
lopt++;
}
}
free(bervalues);
free(uwsgi_attr);
}
free(attr);
}
free(ber);
free(results);
ldap_unbind_ext_s(ldp, NULL, NULL);
}
#endif
+9 -3
View File
@@ -38,7 +38,7 @@
#ifdef __linux__
#include <endian.h>
#elif __sun__
#elif __apple__
#elif __APPLE__
#include <libkern/OSByteOrder.h>
#else
#include <machine/endian.h>
@@ -483,6 +483,12 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
);
uwsgi_add_var(b, "REMOTE_PORT", 11, buf, strlen(buf));
if (!buffer_is_empty(con->authed_user)) {
uwsgi_add_var(b, "REMOTE_USER", 11,
CONST_BUF_LEN(con->authed_user));
}
s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
uwsgi_add_var(b, "REMOTE_ADDR", 11, (char *)s, strlen(s));
@@ -490,7 +496,7 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
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));
uwsgi_add_var(b, "PATH_INFO", 9, con->uri.path->ptr + hctx->path_info_offset, strlen(con->uri.path->ptr + hctx->path_info_offset));
}
else {
uwsgi_add_var(b, "PATH_INFO", 9, "/", 1);
@@ -498,7 +504,7 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
}
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) ;
uwsgi_add_var(b, "PATH_INFO", 9, con->uri.path->ptr, strlen(con->uri.path->ptr)) ;
}
+51 -21
View File
@@ -12,18 +12,28 @@
#define _FILE_OFFSET_BITS 64
#endif
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
#include <sys/sysctl.h>
#endif
extern struct uwsgi_server uwsgi;
void log_request(struct wsgi_request *wsgi_req) {
// optimize this (please)
char *time_request;
time_t microseconds, microseconds2;
static char *empty = "";
char *first_part = empty;
int rlen;
int app_req = -1;
char *msg2 = " ";
char *via = msg2;
char mempkt[4096];
char logpkt[4096];
struct iovec logvec[4] ;
int logvecpos = 0 ;
#ifdef UWSGI_SENDFILE
char *msg1 = " via sendfile() ";
@@ -35,9 +45,8 @@ void log_request(struct wsgi_request *wsgi_req) {
app_req = wi->requests;
}
}
via = msg2;
if (wsgi_req->sendfile_fd > -1) {
if (wsgi_req->sendfile_fd > -1 && wsgi_req->sendfile_obj == wsgi_req->async_result) { //wsgi_req->sendfile_fd_size > 0 ) {
via = msg1;
}
#endif
@@ -46,27 +55,39 @@ void log_request(struct wsgi_request *wsgi_req) {
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.vhost) {
logvec[logvecpos].iov_base = wsgi_req->host ;
logvec[logvecpos].iov_len = wsgi_req->host_len ;
logvecpos++;
logvec[logvecpos].iov_base = " " ;
logvec[logvecpos].iov_len = 1 ;
logvecpos++;
}
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);
}
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} {rss usage: %llu bytes/%lluMB} ",
(unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long ) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024,
(unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size, (unsigned long long ) uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
#else
fprintf(stderr, "{address space usage: %lld bytes/%lluMB} ", uwsgi.workers[uwsgi.mywid].vsz_size, uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024);
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} ",
(unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024);
#endif
logvec[logvecpos].iov_base = mempkt ;
logvec[logvecpos].iov_len = rlen ;
logvecpos++;
}
fprintf(stderr, "%s[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %llu bytes in %ld msecs%s(%.*s %d) %d headers in %d bytes (%d async switches on async core %d)\n",
first_part,
uwsgi.mypid,
rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %llu bytes in %ld msecs%s(%.*s %d) %d headers in %d bytes (%d async switches on async core %d)\n",
(int) uwsgi.mypid,
wsgi_req->app_id,
app_req,
uwsgi.workers[0].requests,
(unsigned long long ) 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,
@@ -74,7 +95,7 @@ void log_request(struct wsgi_request *wsgi_req) {
24, time_request,
wsgi_req->method_len, wsgi_req->method,
wsgi_req->uri_len, wsgi_req->uri,
(uint64_t) wsgi_req->response_size,
(unsigned long long) wsgi_req->response_size,
(long int) (microseconds - microseconds2) / 1000,
via,
wsgi_req->protocol_len, wsgi_req->protocol,
@@ -83,6 +104,11 @@ void log_request(struct wsgi_request *wsgi_req) {
wsgi_req->headers_size,
wsgi_req->async_switches, wsgi_req->async_id);
logvec[logvecpos].iov_base = logpkt ;
logvec[logvecpos].iov_len = rlen ;
// do not check for errors
rlen = writev(2, logvec, logvecpos+1);
}
@@ -95,9 +121,9 @@ void get_memusage() {
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);
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", (unsigned long long *) &uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long *) &uwsgi.workers[uwsgi.mywid].rss_size);
if (i != 2) {
fprintf(stderr, "warning: invalid record in /proc/self/stat\n");
uwsgi_log( "warning: invalid record in /proc/self/stat\n");
}
fclose(procfile);
}
@@ -138,12 +164,16 @@ void get_memusage() {
uwsgi.workers[uwsgi.mywid].vsz_size = kproc->ki_size;
uwsgi.workers[uwsgi.mywid].rss_size = kproc->ki_rssize * uwsgi.page_size;
}
#elif defined(__NetBSD__)
#elif defined(__NetBSD__) || defined(__OpenBSD__)
struct kinfo_proc2 *kproc2;
kproc2 = kvm_getproc2(kv, KERN_PROC_PID, uwsgi.mypid, sizeof(struct kinfo_proc2), &cnt);
if (kproc2 && cnt > 0) {
#ifdef __OpenBSD__
uwsgi.workers[uwsgi.mywid].vsz_size = (kproc2->p_vm_dsize + kproc2->p_vm_ssize + kproc2->p_vm_tsize) * uwsgi.page_size;
#else
uwsgi.workers[uwsgi.mywid].vsz_size = kproc2->p_vm_msize * uwsgi.page_size;
#endif
uwsgi.workers[uwsgi.mywid].rss_size = kproc2->p_vm_rssize * uwsgi.page_size;
}
#endif
+22
View File
@@ -0,0 +1,22 @@
<unbit>
<pippo/>
<pluto>
ciao
ciao
</pluto>
<uwsgi id="unbit.it">
<http>:3333</http>
<module>trac.web.main:dispatch_request</module>
<pluto>ciao</pluto>
<env>TRAC_ENV=/root/uwsgi/utrac</env>
</uwsgi>
<uwsgi id="projects.unbit.it">
<http>:4444</http>
<module>trac.web.main:dispatch_request</module>
</uwsgi>
</unbit>
+26
View File
@@ -0,0 +1,26 @@
import uwsgi
import os
def application(env, start_response):
boundary = 'uwsgi_mjpeg_frame'
start_response('200 Ok', [
('Cache-Control', 'no-cache'),
('Cache-Control', 'private'),
('Pragma', 'no-cache'),
('Content-Type', 'multipart/x-mixed-replace; boundary=' + boundary),
]
)
yield "--%s\n" % boundary
while 1:
yield "Content-Type: image/jpeg\r\n\r\n"
uwsgi.sendfile('screenshot.jpg')
yield "--%s\n" % boundary
#os.system('./isightcapture -w 640 -h 480 screenshot.jpg')
#os.system('screencapture -m -T 1 screenshot.jpg')
+23
View File
@@ -0,0 +1,23 @@
use Mojolicious::Lite;
# /
get '/' => 'index';
# /*
get '/:groovy' => sub {
my $self = shift;
$self->render_text($self->param('groovy'), layout => 'funky');
};
app->start('psgi');
__DATA__
@@ index.html.ep
% layout 'funky';
Yea baby!
@@ layouts/funky.html.ep
<!doctype html><html>
<head><title>Funky!</title></head>
<body><%= content %></body>
</html>
+28 -2
View File
@@ -35,7 +35,9 @@
#include <ngx_core.h>
#include <ngx_http.h>
#define NGX_HTTP_UWSGI_TEMP_PATH "uwsgi_temp"
#ifndef NGX_HTTP_UWSGI_TEMP_PATH
#define NGX_HTTP_UWSGI_TEMP_PATH "uwsgi_temp"
#endif
typedef struct {
ngx_http_upstream_conf_t upstream;
@@ -48,6 +50,8 @@ typedef struct {
ngx_array_t *uwsgi_lengths;
ngx_array_t *uwsgi_values;
ngx_str_t uwsgi_string ;
u_char modifier1;
u_char modifier2;
@@ -106,7 +110,9 @@ static ngx_conf_bitmask_t ngx_http_uwsgi_next_upstream_masks[] = {
{ngx_string ("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT},
{ngx_string ("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER},
{ngx_string ("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500},
{ngx_string ("http_502"), NGX_HTTP_UPSTREAM_FT_HTTP_502},
{ngx_string ("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503},
{ngx_string ("http_504"), NGX_HTTP_UPSTREAM_FT_HTTP_504},
{ngx_string ("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404},
{ngx_string ("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING},
{ngx_string ("off"), NGX_HTTP_UPSTREAM_FT_OFF},
@@ -271,6 +277,14 @@ static ngx_command_t ngx_http_uwsgi_commands[] = {
offsetof (ngx_http_uwsgi_loc_conf_t, params_source),
NULL},
{ ngx_string("uwsgi_string"),
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF |
NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_uwsgi_loc_conf_t, uwsgi_string),
NULL },
{ngx_string ("uwsgi_pass_header"),
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF |
NGX_CONF_FLAG,
@@ -538,13 +552,18 @@ ngx_http_uwsgi_create_request (ngx_http_request_t * r)
}
}
if (uwcf->uwsgi_string.data && uwcf->uwsgi_string.len) {
uwsgi_pkt_size += uwcf->uwsgi_string.len ;
}
// check here
/* allow custom uwsgi packet
if (uwsgi_pkt_size > 0 && uwsgi_pkt_size < 2) {
ngx_log_error (NGX_LOG_ALERT, r->connection->log, 0,
"uwsgi request is too little: %uz", uwsgi_pkt_size);
return NGX_ERROR;
}
*/
b = ngx_create_temp_buf (r->pool, uwsgi_pkt_size + 4);
if (b == NULL) {
@@ -676,6 +695,11 @@ ngx_http_uwsgi_create_request (ngx_http_request_t * r)
}
if (uwcf->uwsgi_string.data && uwcf->uwsgi_string.len) {
b->last = ngx_copy(b->last, uwcf->uwsgi_string.data, uwcf->uwsgi_string.len);
}
if (uwcf->upstream.pass_request_body) {
body = r->upstream->request_bufs;
r->upstream->request_bufs = cl;
@@ -1381,6 +1405,8 @@ ngx_http_uwsgi_merge_loc_conf (ngx_conf_t * cf, void *parent, void *child)
ngx_conf_merge_value (conf->upstream.intercept_errors,
prev->upstream.intercept_errors, 0);
ngx_conf_merge_str_value(conf->uwsgi_string, prev->uwsgi_string, "");
hash.max_size = 512;
hash.bucket_size = ngx_align (64, ngx_cacheline_size);
hash.name = "uwsgi_hide_headers_hash";
+81
View File
@@ -0,0 +1,81 @@
#include "uwsgi.h"
void embed_plugins(struct uwsgi_server *uwsgi) {
#ifdef UWSGI_EMBED_PLUGIN_PSGI
if (uwsgi->plugin_arg_psgi)
ret = uwsgi_load_plugin(uwsgi, 5, "psgi_plugin.so", uwsgi->plugin_arg_psgi, 0);
#endif
#ifdef UWSGI_EMBED_PLUGIN_LUA
if (uwsgi->plugin_arg_lua)
ret = uwsgi_load_plugin(uwsgi, 6, "lua_plugin.so", uwsgi->plugin_arg_lua, 0);
#endif
#ifdef UWSGI_EMBED_PLUGIN_RACK
if (uwsgi->plugin_arg_rack)
ret = uwsgi_load_plugin(uwsgi, 7, "rack_plugin.so", uwsgi->plugin_arg_rack, 0);
#endif
}
int uwsgi_load_plugin(struct uwsgi_server *uwsgi, int modifier, char *plugin, char *pargs, int absolute) {
char *plugin_name ;
void *plugin_handle;
int (*plugin_init) (struct uwsgi_server *, char *);
int (*plugin_request) (struct uwsgi_server *, struct wsgi_request *);
void (*plugin_after_request) (struct uwsgi_server *, struct wsgi_request *);
if (absolute) {
plugin_name = malloc(strlen(plugin) + 1);
memcpy(plugin_name, plugin, strlen(plugin) + 1);
}
else {
plugin_name = malloc(strlen(UWSGI_PLUGIN_DIR) + 1 + strlen(plugin) + 1);
if (!plugin_name) {
uwsgi_error("malloc()");
return -1 ;
}
memcpy(plugin_name, UWSGI_PLUGIN_DIR, strlen(UWSGI_PLUGIN_DIR));
memcpy(plugin_name + strlen(UWSGI_PLUGIN_DIR) , "/", 1);
memcpy(plugin_name + strlen(UWSGI_PLUGIN_DIR) + 1, plugin, strlen(plugin) + 1);
}
plugin_handle = dlopen(plugin_name, RTLD_NOW | RTLD_GLOBAL);
free(plugin_name);
if (!plugin_handle) {
uwsgi_log( "%s\n", dlerror());
}
else {
plugin_init = dlsym(plugin_handle, "uwsgi_init");
if (plugin_init) {
if ((*plugin_init) (uwsgi, pargs)) {
uwsgi_log( "plugin initialization returned error\n");
if (dlclose(plugin_handle)) {
uwsgi_log( "unable to unload plugin\n");
}
return -1;
}
}
plugin_request = dlsym(plugin_handle, "uwsgi_request");
if (plugin_request) {
uwsgi->shared->hooks[modifier] = plugin_request;
plugin_after_request = dlsym(plugin_handle, "uwsgi_after_request");
if (plugin_after_request) {
uwsgi->shared->after_hooks[modifier] = plugin_after_request;
}
return 0;
}
else {
uwsgi_log( "%s\n", dlerror());
}
}
return -1;
}
+2 -2
View File
@@ -1,7 +1,7 @@
#include "../../uwsgi.h"
int uwsgi_init(struct uwsgi_server *uwsgi, char *args){
fprintf(stderr,"i am the example plugin initialization function with arg: %s\n", args);
uwsgi_log("i am the example plugin initialization function with arg: %s\n", args);
return 0;
}
@@ -16,5 +16,5 @@ int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
void uwsgi_after_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
fprintf(stderr,"i am the example plugin after request function\n");
uwsgi_log("i am the example plugin after request function\n");
}
+1 -2
View File
@@ -104,8 +104,7 @@ int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
}
// put function in the stack
lua_pushvalue(ulua.L, -1);
lua_getfield(ulua.L, -1, "run");
lua_getfield(ulua.L, LUA_GLOBALSINDEX, "run");
// put cgi vars in the stack
lua_newtable(ulua.L);
+24 -20
View File
@@ -6,6 +6,8 @@
static PerlInterpreter *my_perl;
static SV *psgi_func ;
extern char **environ;
/* statistically ordered */
static struct http_status_codes hsc[] = {
@@ -76,7 +78,6 @@ xs_init(pTHX)
int uwsgi_init(struct uwsgi_server *uwsgi, char *args){
char *pargs[2] ;
char *psgibuffer ;
int fd ;
@@ -84,20 +85,20 @@ int uwsgi_init(struct uwsgi_server *uwsgi, char *args){
struct http_status_codes *http_sc ;
char *embedding[] = { "", "-e", "0" };
int argc = 4 ;
char *embedding[] = { "", args, "-e", "0" };
char **argv = embedding ;
uwsgi_log("initializing Perl environment: %s\n", args);
fprintf(stderr,"initializing Perl environment: %s\n", args);
PERL_SYS_INIT3(&argc, &argv, &environ);
my_perl = perl_alloc();
if (!my_perl) {
fprintf(stderr,"unable to allocate perl interpreter\n");
uwsgi_log("unable to allocate perl interpreter\n");
return -1;
}
pargs[0] = "" ;
pargs[1] = args ;
PL_perl_destruct_level = 1;
perl_construct(my_perl);
// filling http status codes
@@ -106,31 +107,32 @@ int uwsgi_init(struct uwsgi_server *uwsgi, char *args){
}
perl_parse(my_perl, xs_init, 3, embedding, NULL);
PL_origalen = 1;
perl_parse(my_perl, xs_init, 4, embedding, NULL);
perl_eval_pv("use IO::Handle;", 0);
fd = open(args, O_RDONLY);
if (fd < 0) {
perror("open()");
uwsgi_error("open()");
goto clear ;
}
if (fstat(fd, &stat_psgi)) {
perror("fstat()");
uwsgi_error("fstat()");
close(fd);
goto clear;
}
psgibuffer = malloc(stat_psgi.st_size);
if (!psgibuffer) {
perror("malloc()");
uwsgi_error("malloc()");
close(fd);
goto clear;
}
if (read(fd, psgibuffer, stat_psgi.st_size) != stat_psgi.st_size) {
perror("read()");
uwsgi_error("read()");
close(fd);
free(psgibuffer);
goto clear;
@@ -139,8 +141,9 @@ int uwsgi_init(struct uwsgi_server *uwsgi, char *args){
psgibuffer[stat_psgi.st_size] = 0 ;
psgi_func = perl_eval_pv(psgibuffer, 0);
if (!psgi_func) {
fprintf(stderr,"unable to find PSGI function entry point.\n");
uwsgi_log("unable to find PSGI function entry point.\n");
close(fd);
free(psgibuffer);
goto clear;
@@ -175,13 +178,13 @@ int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
/* Standard PSGI request */
if (!wsgi_req->uh.pktsize) {
fprintf (stderr, "Invalid PSGI request. skip.\n");
uwsgi_log("Invalid PSGI request. skip.\n");
return -1;
}
if (uwsgi_parse_vars(uwsgi, wsgi_req)) {
fprintf(stderr,"Invalid PSGI request. skip.\n");
uwsgi_log("Invalid PSGI request. skip.\n");
return -1;
}
@@ -259,7 +262,6 @@ int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
// dereference output
response = (AV *) SvRV( sv_2mortal(newSVsv(POPs)) ) ;
status_code = av_fetch(response, 0, 0);
wsgi_req->hvec[0].iov_base = "HTTP/1.1 ";
@@ -320,7 +322,7 @@ int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
if ( (wsgi_req->response_size = writev(wsgi_req->poll.fd, wsgi_req->hvec, vi+1)) < 0) {
perror("writev()");
uwsgi_error("writev()");
}
@@ -328,8 +330,7 @@ int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
io = *hitem;
if (SvTYPE(SvRV(io)) == SVt_PVGV) {
if (SvTYPE(SvRV(io)) == SVt_PVGV || SvTYPE(SvRV(io)) == SVt_PVHV) {
for(;;) {
@@ -360,6 +361,9 @@ int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
}
}
else {
uwsgi_log("unsupported response body type: %d\n", SvTYPE(SvRV(io)));
}
FREETMPS;
LEAVE;
+382
View File
@@ -0,0 +1,382 @@
#include <uwsgi.h>
#include <ruby.h>
extern char **environ;
/* statistically ordered */
static struct http_status_codes hsc[] = {
{"200", "OK"},
{"302", "Found"},
{"404", "Not Found"},
{"500", "Internal Server Error"},
{"301", "Moved Permanently"},
{"304", "Not Modified"},
{"303", "See Other"},
{"403", "Forbidden"},
{"307", "Temporary Redirect"},
{"401", "Unauthorized"},
{"400", "Bad Request"},
{"405", "Method Not Allowed"},
{"408", "Request Timeout"},
{"100", "Continue"},
{"101", "Switching Protocols"},
{"201", "Created"},
{"202", "Accepted"},
{"203", "Non-Authoritative Information"},
{"204", "No Content"},
{"205", "Reset Content"},
{"206", "Partial Content"},
{"300", "Multiple Choices"},
{"305", "Use Proxy"},
{"402", "Payment Required"},
{"406", "Not Acceptable"},
{"407", "Proxy Authentication Required"},
{"409", "Conflict"},
{"410", "Gone"},
{"411", "Length Required"},
{"412", "Precondition Failed"},
{"413", "Request Entity Too Large"},
{"414", "Request-URI Too Long"},
{"415", "Unsupported Media Type"},
{"416", "Requested Range Not Satisfiable"},
{"417", "Expectation Failed"},
{"501", "Not Implemented"},
{"502", "Bad Gateway"},
{"503", "Service Unavailable"},
{"504", "Gateway Timeout"},
{"505", "HTTP Version Not Supported"},
{ "", NULL },
};
VALUE dispatcher;
VALUE rb_uwsgi_io_class;
ID call;
VALUE rb_uwsgi_io_new(VALUE class, VALUE wr) {
struct wsgi_request *wsgi_req;
Data_Get_Struct(wr, struct wsgi_request, wsgi_req);
uwsgi_log("INITIALIZING UWSGI IO FOR FD: %d\n", wsgi_req->poll.fd);
VALUE self = Data_Wrap_Struct(class , 0, 0, wsgi_req);
rb_obj_call_init(self, 0, NULL);
return self;
}
VALUE rb_uwsgi_io_init(int argc, VALUE *argv, VALUE self) {
return self;
}
VALUE rb_uwsgi_io_gets(VALUE obj, VALUE args) {
struct wsgi_request *wsgi_req;
Data_Get_Struct(obj, struct wsgi_request, wsgi_req);
uwsgi_log("CALLING gets !!!\n");
return Qnil;
}
VALUE rb_uwsgi_io_each(VALUE obj, VALUE args) {
struct wsgi_request *wsgi_req;
Data_Get_Struct(obj, struct wsgi_request, wsgi_req);
uwsgi_log("CALLING each !!!\n");
return Qnil;
}
VALUE rb_uwsgi_io_read(VALUE obj, VALUE args) {
struct wsgi_request *wsgi_req;
Data_Get_Struct(obj, struct wsgi_request, wsgi_req);
size_t len;
uwsgi_log("CALLING read on %d !!!\n", wsgi_req->poll.fd);
if (RARRAY(args)->len == 0) {
uwsgi_log("READ ALL THE BODY (%d bytes)\n", wsgi_req->post_cl);
char *post_body = malloc(wsgi_req->post_cl);
if (post_body) {
len = read( wsgi_req->poll.fd, post_body, wsgi_req->post_cl);
VALUE chunk = rb_str_new(post_body, wsgi_req->post_cl);
free(post_body);
return chunk;
}
}
else if (RARRAY(args)->len > 0) {
uwsgi_log("CHUNK SIZE: %d\n", NUM2INT( RARRAY(args)->ptr[0] ) );
}
return Qnil;
}
VALUE rb_uwsgi_io_rewind(VALUE obj, VALUE args) {
struct wsgi_request *wsgi_req;
Data_Get_Struct(obj, struct wsgi_request, wsgi_req);
uwsgi_log("CALLING rewind !!!\n");
return Qnil;
}
int uwsgi_init(struct uwsgi_server *uwsgi, char *args){
struct http_status_codes *http_sc;
// filling http status codes
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
http_sc->message_size = strlen(http_sc->message);
}
ruby_init();
ruby_init_loadpath();
ruby_script("uwsgi");
if (chdir("mytipo")) {
uwsgi_error("chdir()");
}
rb_require("config/environment");
uwsgi_log("ruby ready\n");
VALUE ac = rb_const_get(rb_cObject, rb_intern("ActionController")) ;
dispatcher = rb_funcall( rb_const_get(ac, rb_intern("Dispatcher")), rb_intern("new"), 0);
if (dispatcher == Qnil) {
uwsgi_log("OOOPS\n");
exit(1);
}
else {
uwsgi_log("OK %p\n", dispatcher);
}
rb_gc_register_address(&dispatcher);
call = rb_intern("call");
rb_gc_register_address(&call);
rb_uwsgi_io_class = rb_define_class("Uwsgi_IO", rb_cObject);
rb_gc_register_address(&rb_uwsgi_io_class);
rb_define_singleton_method(rb_uwsgi_io_class, "new", rb_uwsgi_io_new, 1);
rb_define_method(rb_uwsgi_io_class, "initialize", rb_uwsgi_io_init, -1);
rb_define_method(rb_uwsgi_io_class, "gets", rb_uwsgi_io_gets, 0);
rb_define_method(rb_uwsgi_io_class, "each", rb_uwsgi_io_each, 0);
rb_define_method(rb_uwsgi_io_class, "read", rb_uwsgi_io_read, -2);
rb_define_method(rb_uwsgi_io_class, "rewind", rb_uwsgi_io_rewind, 0);
rb_gc_disable();
return 0;
}
VALUE call_dispatch(VALUE env) {
return rb_funcall(dispatcher, call, 1, env);
}
VALUE send_body(VALUE obj, VALUE fd) {
size_t len;
uwsgi_log("sending body\n");
if (TYPE(obj) == T_STRING) {
uwsgi_log("chunk is a string\n");
len = write( NUM2INT(fd), RSTRING(obj)->ptr, RSTRING(obj)->len);
}
return Qnil;
}
VALUE send_header(VALUE obj, VALUE fd) {
size_t len;
uwsgi_log("SENDING HEADER: %d\n", TYPE(obj));
if (TYPE(obj) == T_ARRAY) {
if (RARRAY(obj)->len == 2) {
VALUE hkey = rb_obj_as_string( RARRAY(obj)->ptr[0]);
VALUE hval = rb_obj_as_string( RARRAY(obj)->ptr[1]);
len = write( NUM2INT(fd), RSTRING(hkey)->ptr, RSTRING(hkey)->len);
len = write( NUM2INT(fd), ": ", 2);
len = write( NUM2INT(fd), RSTRING(hval)->ptr, RSTRING(hval)->len);
len = write( NUM2INT(fd), "\r\n", 2);
}
}
return Qnil;
}
static void uwsgi_ruby_exception(void) {
VALUE lasterr = rb_gv_get("$!");
VALUE message = rb_obj_as_string(lasterr);
uwsgi_log("%s\n", RSTRING(message)->ptr);
if(!NIL_P(ruby_errinfo)) {
VALUE ary = rb_funcall(ruby_errinfo, rb_intern("backtrace"), 0);
int i;
for (i=0; i<RARRAY(ary)->len; i++) {
uwsgi_log("%s\n", RSTRING(RARRAY(ary)->ptr[i])->ptr);
}
}
}
int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
int error;
int i;
struct http_status_codes *http_sc;
/* Standard RACK request */
if (!wsgi_req->uh.pktsize) {
uwsgi_log("Invalid RACK request. skip.\n");
return -1;
}
if (uwsgi_parse_vars(uwsgi, wsgi_req)) {
uwsgi_log("Invalid RACK request. skip.\n");
return -1;
}
VALUE env = rb_hash_new();
// fill ruby hash
for(i=0;i<wsgi_req->var_cnt;i++) {
rb_hash_aset(env, rb_str_new(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len),
rb_str_new(wsgi_req->hvec[i+1].iov_base, wsgi_req->hvec[i+1].iov_len));
i++;
}
VALUE rbv = rb_ary_new();
rb_ary_store(rbv, 0, INT2NUM(1));
rb_ary_store(rbv, 1, INT2NUM(1));
rb_hash_aset(env, rb_str_new2("rack.version"), rbv);
rb_hash_aset(env, rb_str_new2("rack.url_scheme"), rb_str_new2("http"));
rb_hash_aset(env, rb_str_new2("rack.multithread"), Qfalse);
rb_hash_aset(env, rb_str_new2("rack.multiprocess"), Qtrue);
rb_hash_aset(env, rb_str_new2("rack.run_once"), Qfalse);
VALUE dws_wr = Data_Wrap_Struct(rb_uwsgi_io_class, 0, 0, wsgi_req);
rb_hash_aset(env, rb_str_new2("rack.input"), rb_funcall(rb_uwsgi_io_class, rb_intern("new"), 1, dws_wr ));
VALUE ret = rb_protect( call_dispatch, env, &error);
if (error) {
uwsgi_ruby_exception();
return -1;
}
if (TYPE(ret) == T_ARRAY) {
if (RARRAY(ret)->len != 3) {
uwsgi_log("Invalid RACK response size: %d\n", RARRAY(ret)->len);
return -1;
}
// manage Status
VALUE status = rb_obj_as_string(RARRAY(ret)->ptr[0]);
uwsgi_log("Status: %.*s\n", RSTRING(status)->len, RSTRING(status)->ptr);
// get the status code
wsgi_req->hvec[0].iov_base = "HTTP/1.1 ";
wsgi_req->hvec[0].iov_len = 9 ;
wsgi_req->hvec[1].iov_base = RSTRING(status)->ptr;
wsgi_req->hvec[1].iov_len = 3 ;
wsgi_req->hvec[2].iov_base = " ";
wsgi_req->hvec[2].iov_len = 1 ;
wsgi_req->hvec[3].iov_len = 0 ;
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
if (!strncmp(http_sc->key, RSTRING(status)->ptr, 3)) {
wsgi_req->hvec[3].iov_base = http_sc->message ;
wsgi_req->hvec[3].iov_len = http_sc->message_size ;
break;
}
}
wsgi_req->hvec[4].iov_base = "\r\n";
wsgi_req->hvec[4].iov_len = 2 ;
if ( (wsgi_req->response_size = writev(wsgi_req->poll.fd, wsgi_req->hvec, 5)) < 0) {
uwsgi_error("writev()");
}
VALUE headers = RARRAY(ret)->ptr[1] ;
if (rb_respond_to( headers, rb_intern("each") )) {
uwsgi_log("headers respond_to each\n");
rb_iterate( rb_each, headers, send_header, INT2NUM(wsgi_req->poll.fd));
}
uwsgi_log("wsgi_req ptr: %p\n", wsgi_req);
write(wsgi_req->poll.fd, "\r\n", 2);
uwsgi_log("PTR: %p\n", RARRAY(ret)->ptr[2]);
VALUE body = RARRAY(ret)->ptr[2] ;
//rb_gc_register_address(&body);
if (rb_respond_to( body, rb_intern("to_path") )) {
uwsgi_log("BODY respond_to 'to_path'\n");
}
else if (rb_respond_to( body, rb_intern("each") )) {
rb_iterate( rb_each, body, send_body, INT2NUM(wsgi_req->poll.fd));
}
uwsgi_log("Fatto %p\n", body);
if (rb_respond_to( body, rb_intern("close") )) {
uwsgi_log("BODY respond_to 'close'\n");
}
uwsgi_log("Fatto 2 %p\n", wsgi_req);
}
rb_gc_disable();
return 0;
}
void uwsgi_after_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
if (uwsgi->shared->options[UWSGI_OPTION_LOGGING])
log_request(wsgi_req);
}
+5
View File
@@ -0,0 +1,5 @@
import os,sys
NAME='rack'
CFLAGS = '-I' + os.popen("ruby -e \"require 'mkmf';print Config::CONFIG['archdir']\"").read().rstrip()
LDFLAGS = '-l' + os.popen("ruby -e \"require 'mkmf';print CONFIG['RUBY_SO_NAME']\"").read().rstrip()
+56 -19
View File
@@ -2,6 +2,20 @@
extern struct uwsgi_server uwsgi;
static size_t get_content_length(char *buf, uint16_t size) {
int i;
size_t val = 0 ;
for(i=0;i<size;i++) {
if (buf[i] >= '0' && buf[i] <= '9') {
val = (val*10) + (buf[i] - '0') ;
continue;
}
break;
}
return val;
}
#ifdef UWSGI_UDP
ssize_t send_udp_message(uint8_t modifier1, char *host, char *message, uint16_t message_size) {
@@ -69,7 +83,7 @@ int uwsgi_enqueue_message(char *host, int port, uint8_t modifier1, uint8_t modif
timeout = 1;
if (size > 0xFFFF) {
fprintf(stderr, "invalid object (marshalled) size\n");
uwsgi_log( "invalid object (marshalled) size\n");
return -1;
}
@@ -127,7 +141,7 @@ PyObject *uwsgi_send_message(const char *host, int port, uint8_t modifier1, uint
timeout = 1;
if (size > 0xFFFF) {
fprintf(stderr, "invalid object (marshalled) size\n");
uwsgi_log( "invalid object (marshalled) size\n");
Py_INCREF(Py_None);
return Py_None;
}
@@ -212,7 +226,7 @@ int uwsgi_parse_response(struct pollfd *upoll, int timeout, struct uwsgi_header
exit(1);
}
else if (rlen == 0) {
fprintf(stderr, "timeout. skip request\n");
uwsgi_log( "timeout. skip request\n");
close(upoll->fd);
return 0;
}
@@ -226,13 +240,13 @@ int uwsgi_parse_response(struct pollfd *upoll, int timeout, struct uwsgi_header
exit(1);
}
else if (rlen == 0) {
fprintf(stderr, "timeout waiting for header. skip request.\n");
uwsgi_log( "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");
uwsgi_log( "broken header. skip request.\n");
close(upoll->fd);
break;
}
@@ -243,7 +257,7 @@ int uwsgi_parse_response(struct pollfd *upoll, int timeout, struct uwsgi_header
}
}
else if (rlen <= 0) {
fprintf(stderr, "invalid request header size: %d...skip\n", rlen);
uwsgi_log( "invalid request header size: %d...skip\n", rlen);
close(upoll->fd);
return 0;
}
@@ -252,14 +266,18 @@ int uwsgi_parse_response(struct pollfd *upoll, int timeout, struct uwsgi_header
uh->pktsize = uwsgi_swap16(uh->pktsize);
#endif
#ifdef UWSGI_DEBUG
uwsgi_debug("uwsgi payload size: %d (0x%X) modifier1: %d modifier2: %d\n", uh->pktsize, uh->pktsize, uh->modifier1, uh->modifier2);
#endif
/* check for max buffer size */
if (uh->pktsize > uwsgi.buffer_size) {
fprintf(stderr, "invalid request block size: %d...skip\n", uh->pktsize);
uwsgi_log( "invalid request block size: %d...skip\n", uh->pktsize);
close(upoll->fd);
return 0;
}
//fprintf(stderr,"ready for reading %d bytes\n", wsgi_req.size);
//uwsgi_log("ready for reading %d bytes\n", wsgi_req.size);
i = 0;
while (i < uh->pktsize) {
@@ -269,13 +287,13 @@ int uwsgi_parse_response(struct pollfd *upoll, int timeout, struct uwsgi_header
exit(1);
}
else if (rlen == 0) {
fprintf(stderr, "timeout. skip request. (expecting %d bytes, got %d)\n", uh->pktsize, i);
uwsgi_log( "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");
uwsgi_log( "broken vars. skip request.\n");
close(upoll->fd);
break;
}
@@ -312,7 +330,7 @@ int uwsgi_parse_vars(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req)
#endif
/* key cannot be null */
if (!strsize) {
fprintf(stderr, "uwsgi key cannot be null. skip this request.\n");
uwsgi_log( "uwsgi key cannot be null. skip this request.\n");
return -1;
}
@@ -322,16 +340,28 @@ int uwsgi_parse_vars(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req)
wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = strsize;
ptrbuf += strsize;
if (ptrbuf + 2 < bufferend) {
// value can be null (even at the end) so use <=
if (ptrbuf + 2 <= bufferend) {
memcpy(&strsize, ptrbuf, 2);
#ifdef __BIG_ENDIAN__
strsize = uwsgi_swap16(strsize);
#endif
ptrbuf += 2;
if (ptrbuf + strsize <= bufferend) {
//uwsgi_log("uwsgi %.*s = %.*s\n", wsgi_req->hvec[wsgi_req->var_cnt].iov_len, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, strsize, ptrbuf);
if (!strncmp("SCRIPT_NAME", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->script_name = ptrbuf;
wsgi_req->script_name_len = strsize;
#ifdef UWSGI_DEBUG
uwsgi_debug("SCRIPT_NAME=%.*s\n", wsgi_req->script_name_len, wsgi_req->script_name);
#endif
}
else if (!strncmp("PATH_INFO", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->path_info = ptrbuf;
wsgi_req->path_info_len = strsize;
#ifdef UWSGI_DEBUG
uwsgi_debug("PATH_INFO=%.*s\n", wsgi_req->path_info_len, wsgi_req->path_info);
#endif
}
else if (!strncmp("SERVER_PROTOCOL", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->protocol = ptrbuf;
@@ -373,31 +403,38 @@ int uwsgi_parse_vars(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req)
wsgi_req->wsgi_callable = ptrbuf;
wsgi_req->wsgi_callable_len = strsize;
}
else if (!strncmp("UWSGI_PYHOME", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->pyhome = ptrbuf;
wsgi_req->pyhome_len = strsize;
}
else if (!strncmp("SERVER_NAME", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->host = ptrbuf;
wsgi_req->host_len = strsize;
}
else if (!strncmp("HTTPS", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->https = ptrbuf;
wsgi_req->https_len = strsize;
}
#ifdef UNBIT
else if (!strncmp("UNBIT_FLAGS", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->unbit_flags = *(unsigned long long *) ptrbuf;
else if (!strncmp("CONTENT_LENGTH", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->post_cl = get_content_length(ptrbuf, strsize);
}
#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");
uwsgi_log( "max vec size reached. skip this header.\n");
return -1;
}
// var value
wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = strsize;
//fprintf(stderr,"%.*s = %.*s\n", wsgi_req->hvec[wsgi_req->var_cnt-1].iov_len, wsgi_req->hvec[wsgi_req->var_cnt-1].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len, wsgi_req->hvec[wsgi_req->var_cnt].iov_base);
//uwsgi_log("%.*s = %.*s\n", wsgi_req->hvec[wsgi_req->var_cnt-1].iov_len, wsgi_req->hvec[wsgi_req->var_cnt-1].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len, wsgi_req->hvec[wsgi_req->var_cnt].iov_base);
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");
uwsgi_log( "max vec size reached. skip this header.\n");
return -1;
}
ptrbuf += strsize;
+12 -12
View File
@@ -139,9 +139,9 @@ void uwsgi_proxy(int proxyfd) {
int next_node = -1;
fprintf(stderr, "spawned uWSGI proxy (pid: %d)\n", getpid());
uwsgi_log( "spawned uWSGI proxy (pid: %d)\n", getpid());
fprintf(stderr, "allocating space for %d concurrent proxy connections\n", max_connections);
uwsgi_log( "allocating space for %d concurrent proxy connections\n", max_connections);
// allocate memory for connections
upcs = malloc(sizeof(struct uwsgi_proxy_connection) * max_connections);
@@ -221,7 +221,7 @@ void uwsgi_proxy(int proxyfd) {
upcs[ev.ASYNC_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_log( "unable to find an available worker in the cluster !\n");
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
@@ -280,7 +280,7 @@ void uwsgi_proxy(int proxyfd) {
}
else {
fprintf(stderr, "!!! something horrible happened to the uWSGI proxy, reloading it !!!\n");
uwsgi_log( "!!! something horrible happened to the uWSGI proxy, reloading it !!!\n");
exit(1);
}
}
@@ -289,7 +289,7 @@ void uwsgi_proxy(int proxyfd) {
if (eevents[i].ASYNC_IS_IN) {
// is this a connected client/worker ?
//fprintf(stderr,"ready %d\n", upcs[eevents[i].data.fd].status);
//uwsgi_log("ready %d\n", upcs[eevents[i].data.fd].status);
if (!upcs[eevents[i].ASYNC_FD].status) {
if (upcs[eevents[i].ASYNC_FD].dest_fd >= 0) {
@@ -323,7 +323,7 @@ void uwsgi_proxy(int proxyfd) {
continue;
}
else {
fprintf(stderr, "UNKNOWN STATUS %d\n", upcs[eevents[i].ASYNC_FD].status);
uwsgi_log( "UNKNOWN STATUS %d\n", upcs[eevents[i].ASYNC_FD].status);
continue;
}
}
@@ -339,9 +339,9 @@ void uwsgi_proxy(int proxyfd) {
}
/* is something bad ? */
if (soopt) {
fprintf(stderr, "connect() %s\n", strerror(soopt));
uwsgi_log( "connect() %s\n", strerror(soopt));
// increase errors on node
fprintf(stderr, "*** marking cluster node %d/%s as failed ***\n", upcs[eevents[i].ASYNC_FD].node, uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].name);
uwsgi_log( "*** marking cluster node %d/%s as failed ***\n", upcs[eevents[i].ASYNC_FD].node, uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].name);
uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].errors++;
uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].status = UWSGI_NODE_FAILED;
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
@@ -372,7 +372,7 @@ void uwsgi_proxy(int proxyfd) {
}
}
else {
fprintf(stderr, "strange event for %d\n", (int) eevents[i].ASYNC_FD);
uwsgi_log( "strange event for %d\n", (int) eevents[i].ASYNC_FD);
}
}
else {
@@ -382,16 +382,16 @@ void uwsgi_proxy(int proxyfd) {
}
/* is something bad ? */
if (soopt) {
fprintf(stderr, "connect() %s\n", strerror(soopt));
uwsgi_log( "connect() %s\n", strerror(soopt));
}
// increase errors on node
fprintf(stderr, "*** marking cluster node %d/%s as failed ***\n", upcs[eevents[i].ASYNC_FD].node, uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].name);
uwsgi_log( "*** marking cluster node %d/%s as failed ***\n", upcs[eevents[i].ASYNC_FD].node, uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].name);
uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].errors++;
uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].status = UWSGI_NODE_FAILED;
}
else {
fprintf(stderr, "STRANGE EVENT !!! %d %d %d\n", (int) eevents[i].ASYNC_FD, (int) eevents[i].ASYNC_EV, upcs[eevents[i].ASYNC_FD].status);
uwsgi_log( "STRANGE EVENT !!! %d %d %d\n", (int) eevents[i].ASYNC_FD, (int) eevents[i].ASYNC_EV, upcs[eevents[i].ASYNC_FD].status);
}
uwsgi_proxy_close(upcs, eevents[i].ASYNC_FD);
continue;
+6 -1
View File
@@ -1,3 +1,8 @@
import uwsgi
import sys
uwsgi.load_plugin(0, "plugins/psgi/psgi_plugin.so", "test.psgi")
if uwsgi.load_plugin(0, "plugins/psgi/psgi_plugin.so", "mojoapp.pl"):
print "PSGI plugin loaded"
else:
print "unable to load PSGI plugin"
sys.exit(1)
+117 -7
View File
@@ -30,7 +30,7 @@ int manage_python_response(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi
#endif
#ifdef UWSGI_SENDFILE
if (wsgi_req->sendfile_fd != -1) {
if (wsgi_req->sendfile_obj == wsgi_req->async_result && wsgi_req->sendfile_fd != -1) {
sf_len = uwsgi_sendfile(uwsgi, wsgi_req);
if (sf_len < 1) goto clear;
wsgi_req->response_size += sf_len ;
@@ -45,6 +45,32 @@ int manage_python_response(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi
}
#endif
#ifdef UWSGI_WSGI2
// is it a tuple (WSGI2.0) ?
// move it to another hook !!!
if (PyTuple_Check((PyObject *)wsgi_req->async_result)) {
if (PyTuple_Size((PyObject *)wsgi_req->async_result) != 3) {
uwsgi_log("invalid WSGI2.0 response size: %d.\n", PyTuple_Size((PyObject *)wsgi_req->async_result));
goto clear;
}
#ifdef UWSGI_DEBUG
uwsgi_debug("wsgi_req->async_result = %d\n", ((PyObject *)wsgi_req->async_result)->ob_refcnt);
#endif
if (py_uwsgi_spit(NULL, (PyObject *)wsgi_req->async_result) == Py_None) {
goto clear;
}
#ifdef UWSGI_DEBUG
uwsgi_debug("wsgi_req->async_result = %d\n", ((PyObject *)wsgi_req->async_result)->ob_refcnt);
#endif
wsgi_req->async_orig_result = wsgi_req->async_result ;
wsgi_req->async_result = PyTuple_GetItem((PyObject *)wsgi_req->async_result, 2);
#ifdef UWSGI_DEBUG
uwsgi_debug("wsgi_req->async_orig_result = %d\n", ((PyObject *)wsgi_req->async_orig_result)->ob_refcnt);
uwsgi_debug("wsgi_req->async_result = %d\n", ((PyObject *)wsgi_req->async_result)->ob_refcnt);
#endif
return UWSGI_AGAIN;
}
#endif
// ok its a yield
if (!wsgi_req->async_placeholder) {
@@ -61,7 +87,6 @@ int manage_python_response(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi
pychunk = PyIter_Next(wsgi_req->async_placeholder) ;
if (!pychunk) {
@@ -81,7 +106,7 @@ int manage_python_response(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi
}
#ifdef PYTHREE
if (PyBytes_Check(pychunk)) {
else if (PyBytes_Check(pychunk)) {
if ((wsize = write(wsgi_req->poll.fd, PyBytes_AsString(pychunk), PyBytes_Size(pychunk))) < 0) {
uwsgi_error("write()");
Py_DECREF(pychunk);
@@ -90,6 +115,14 @@ int manage_python_response(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi
wsgi_req->response_size += wsize;
}
#endif
#ifdef UWSGI_SENDFILE
else if (wsgi_req->sendfile_obj == pychunk && wsgi_req->sendfile_fd != -1) {
sf_len = uwsgi_sendfile(uwsgi, wsgi_req);
if (sf_len < 1) goto clear;
wsgi_req->response_size += sf_len ;
}
#endif
Py_DECREF(pychunk);
return UWSGI_AGAIN ;
@@ -103,25 +136,57 @@ clear:
}
if (wsgi_req->async_post && !wsgi_req->fd_closed) {
fclose(wsgi_req->async_post);
wsgi_req->fd_closed = 1 ;
if (!uwsgi->post_buffering || wsgi_req->post_cl <= uwsgi->post_buffering) {
wsgi_req->fd_closed = 1 ;
}
}
Py_XDECREF((PyObject *)wsgi_req->async_placeholder);
#ifdef UWSGI_WSGI2
Py_XDECREF((PyObject *)wsgi_req->async_orig_result);
#endif
clear2:
Py_DECREF((PyObject *)wsgi_req->async_result);
PyErr_Clear();
#ifdef UWSGI_DEBUG
if (wsgi_req->async_placeholder) {
uwsgi_debug("wsgi_req->async_placeholder: %d\n", ((PyObject *)wsgi_req->async_placeholder)->ob_refcnt);
}
#ifdef UWSGI_WSGI2
if (wsgi_req->async_orig_result) {
uwsgi_debug("wsgi_req->async_orig_result: %d\n", ((PyObject *)wsgi_req->async_orig_result)->ob_refcnt);
}
#endif
if (wsgi_req->async_result) {
uwsgi_debug("wsgi_req->async_result: %d\n", ((PyObject *)wsgi_req->async_result)->ob_refcnt);
}
if (wsgi_req->async_app) {
uwsgi_debug("wsgi_req->async_app: %d\n", ((PyObject *)wsgi_req->async_app)->ob_refcnt);
}
#endif
return UWSGI_OK;
}
PyObject *python_call(PyObject *callable, PyObject *args) {
PyObject *python_call(PyObject *callable, PyObject *args, int catch) {
PyObject *pyret;
pyret = PyEval_CallObject(callable, args);
if (PyErr_Occurred()) {
PyErr_Print();
if (!catch) {
PyErr_Print();
}
}
#ifdef UWSGI_DEBUG
if (pyret) {
uwsgi_debug("called %p %p %d\n", callable, args, pyret->ob_refcnt);
}
#endif
return pyret;
}
@@ -129,7 +194,7 @@ PyObject *python_call(PyObject *callable, PyObject *args) {
int uwsgi_python_call(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, PyObject *callable, PyObject *args) {
wsgi_req->async_result = python_call(callable, args);
wsgi_req->async_result = python_call(callable, args, 0);
if (wsgi_req->async_result) {
while ( manage_python_response(uwsgi, wsgi_req) != UWSGI_OK) {
@@ -143,3 +208,48 @@ int uwsgi_python_call(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req,
return UWSGI_OK;
}
void init_pyargv(struct uwsgi_server *uwsgi) {
#ifdef PYTHREE
wchar_t pname[6];
mbstowcs(pname, "uwsgi", 6);
uwsgi->py_argv[0] = pname;
#else
uwsgi->py_argv[0] = "uwsgi";
#endif
if (uwsgi->pyargv != NULL && !uwsgi->pyargc) {
uwsgi->pyargc++;
#ifdef PYTHREE
wchar_t *wcargv = malloc( sizeof( wchar_t ) * (strlen(uwsgi->pyargv)+1));
if (!wcargv) {
uwsgi_error("malloc()");
exit(1);
}
memset(wcargv, 0, sizeof( wchar_t ) * (strlen(uwsgi->pyargv)+1));
#endif
char *ap;
#ifdef __sun__
// FIX THIS !!!
ap = strtok(uwsgi->pyargv, " ");
while ((ap = strtok(NULL, " ")) != NULL) {
#else
while ((ap = strsep(&uwsgi->pyargv, " \t")) != NULL) {
#endif
if (*ap != '\0') {
#ifdef PYTHREE
mbstowcs( wcargv + strlen(ap), ap, strlen(ap));
uwsgi->py_argv[uwsgi->pyargc] = wcargv + strlen(ap);
#else
uwsgi->py_argv[uwsgi->pyargc] = ap;
#endif
uwsgi->pyargc++;
}
if (uwsgi->pyargc + 1 > MAX_PYARGV)
break;
}
}
PySys_SetArgv(uwsgi->pyargc, uwsgi->py_argv);
}
+157
View File
@@ -0,0 +1,157 @@
#ifdef UWSGI_ROUTING
#include "uwsgi.h"
void routing_setup(struct uwsgi_server *uwsgi) {
int i;
struct uwsgi_route *ur;
int max_ovec = 0 ;
for(i=0;i<uwsgi->nroutes;i++) {
uwsgi_log("%d = %p\n", i, uwsgi->routes[i].pattern);
ur = &uwsgi->routes[i];
if (ur->args > max_ovec) {
max_ovec = ur->args;
}
}
uwsgi->async_ovector = malloc( sizeof(int *) * uwsgi->async);
if (!uwsgi->async_ovector) {
uwsgi_error("malloc()");
exit(1);
}
uwsgi_log("max_ovec = %d\n", max_ovec);
for(i=0;i<uwsgi->async;i++) {
uwsgi->async_ovector[i] = malloc(sizeof(int) * ((max_ovec+1)*3));
if (!uwsgi->async_ovector[i]) {
uwsgi_error("malloc()");
exit(1);
}
}
}
void check_route(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
int ret,i ;
struct uwsgi_route *ur;
for(i=0;i<uwsgi->nroutes;i++) {
//uwsgi_log("checking route %d\n", i);
ur = &uwsgi->routes[i];
ret = pcre_exec(ur->pattern, ur->pattern_extra, wsgi_req->path_info, wsgi_req->path_info_len, 0, 0, wsgi_req->ovector, (ur->args+1)*3 );
if (ret >= 0) {
uwsgi_log("found route %d for PATH_INFO=%.*s\n", i, wsgi_req->path_info_len, wsgi_req->path_info);
if (ur->action) {
ur->action(uwsgi, wsgi_req, ur);
}
else {
uwsgi_route_action_wsgi(uwsgi, wsgi_req, ur);
}
}
/* TODO check for errors if < 0 && != NO_MATCH */
}
return ;
}
void uwsgi_route_action_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
int i;
PyObject *route_py_callbase, *route_py_dict;
uwsgi_log("managing WSGI route...\n");
if (ur->callable == NULL) {
if (ur->callbase) {
route_py_callbase = PyImport_ImportModule(ur->callbase);
if (route_py_callbase == NULL) {
PyErr_Print();
}
else {
uwsgi_log("callbase dict ok for %s\n", ur->call);
route_py_dict = PyModule_GetDict(route_py_callbase);
}
}
ur->callable = PyDict_GetItemString(route_py_dict, ur->call);
if (ur->callable == NULL) {
uwsgi_log("route_py_dict: %p call: %s\n", route_py_dict, ur->call);
PyErr_Print();
}
}
// TODO put regex captured groups in WSGI env
PyObject *ra = PyTuple_New(ur->args);
for (i=1;i<=ur->args;i++) {
PyTuple_SetItem(ra, i-1, PyString_FromStringAndSize(
wsgi_req->path_info + wsgi_req->ovector[i*2],
wsgi_req->ovector[(i*2)+1] - wsgi_req->ovector[i*2]
));
}
PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.uwsgi.route_args", ra);
if (ur->callable) {
wsgi_req->async_app = ur->callable;
}
}
void uwsgi_route_action_uwsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
PyObject *route_py_callbase, *route_py_dict;
int i;
uwsgi_log("managing uwsgi route...\n");
if (ur->callable == NULL) {
if (ur->callbase) {
route_py_callbase = PyImport_ImportModule(ur->callbase);
if (route_py_callbase == NULL) {
PyErr_Print();
}
else {
uwsgi_log("callbase dict ok for %s\n", ur->call);
route_py_dict = PyModule_GetDict(route_py_callbase);
}
}
ur->callable = PyDict_GetItemString(route_py_dict, ur->call);
if (ur->callable == NULL) {
uwsgi_log("route_py_dict: %p call: %s\n", route_py_dict, ur->call);
PyErr_Print();
}
ur->callable_args = PyTuple_New(ur->args+1);
}
if (ur->callable) {
uwsgi_log("route callable dict ok: %d\n", ur->args);
wsgi_req->async_app = ur->callable;
wsgi_req->async_args = ur->callable_args;
for (i=1;i<=ur->args;i++) {
uwsgi_log("%d\n", i);
uwsgi_log("%d / %d\n", wsgi_req->ovector[i*2], wsgi_req->ovector[(i*2)+1]);
uwsgi_log("%d = %.*s\n", i,wsgi_req->ovector[(i*2)+1] - wsgi_req->ovector[i*2],
wsgi_req->path_info + wsgi_req->ovector[i*2]);
PyTuple_SetItem(wsgi_req->async_args, i, PyString_FromStringAndSize(
wsgi_req->path_info + wsgi_req->ovector[i*2],
wsgi_req->ovector[(i*2)+1] - wsgi_req->ovector[i*2]
));
}
uwsgi_log("route callable built\n");
}
}
#endif
+49 -32
View File
@@ -8,7 +8,7 @@ PyObject *py_uwsgi_sendfile(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
if (!PyArg_ParseTuple(args, "Oi:uwsgi_sendfile", &wsgi_req->async_sendfile, &wsgi_req->sendfile_fd_chunk)) {
if (!PyArg_ParseTuple(args, "O|i:uwsgi_sendfile", &wsgi_req->async_sendfile, &wsgi_req->sendfile_fd_chunk)) {
return NULL;
}
@@ -21,8 +21,12 @@ PyObject *py_uwsgi_sendfile(PyObject * self, PyObject * args) {
}
#endif
// PEP 333 hack
wsgi_req->sendfile_obj = wsgi_req->async_sendfile;
//wsgi_req->sendfile_obj = (void *) PyTuple_New(0);
return PyTuple_New(0);
Py_INCREF((PyObject *) wsgi_req->sendfile_obj);
return (PyObject *) wsgi_req->sendfile_obj;
}
ssize_t uwsgi_sendfile(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
@@ -30,7 +34,6 @@ ssize_t uwsgi_sendfile(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
int fd = wsgi_req->sendfile_fd ;
int sockfd = wsgi_req->poll.fd ;
struct stat stat_buf;
int sf_ret;
if (!wsgi_req->sendfile_fd_size) {
@@ -45,19 +48,32 @@ ssize_t uwsgi_sendfile(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
if (wsgi_req->sendfile_fd_size) {
if (!wsgi_req->sendfile_fd_chunk) wsgi_req->sendfile_fd_chunk = 4096 ;
if (!wsgi_req->sendfile_fd_chunk) wsgi_req->sendfile_fd_chunk = 4096 ;
return uwsgi_do_sendfile(sockfd, wsgi_req->sendfile_fd, wsgi_req->sendfile_fd_size, wsgi_req->sendfile_fd_chunk, &wsgi_req->sendfile_fd_pos, uwsgi->async);
}
return 0;
}
ssize_t uwsgi_do_sendfile(int sockfd, int filefd, size_t filesize, size_t chunk, off_t *pos, int async) {
#if defined(__FreeBSD__) || defined(__DragonFly__)
off_t sf_len = wsgi_req->sendfile_fd_size ;
int sf_ret;
if (uwsgi->async > 1) {
sf_len = wsgi_req->sendfile_fd_chunk;
sf_ret = sendfile(fd, sockfd, wsgi_req->sendfile_fd_pos, 0, NULL, &sf_len, 0);
wsgi_req->sendfile_fd_pos += sf_len ;
off_t sf_len = filesize ;
if (async > 1) {
sf_len = chunk;
sf_ret = sendfile(filefd, sockfd, *pos, 0, NULL, &sf_len, 0);
*pos += sf_len ;
}
else {
sf_ret = sendfile(fd, sockfd, 0, 0, NULL, &sf_len, 0);
sf_ret = sendfile(filefd, sockfd, 0, 0, NULL, &sf_len, 0);
}
if (sf_ret) {
@@ -66,16 +82,17 @@ ssize_t uwsgi_sendfile(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
}
return sf_len;
#elif __APPLE__
off_t sf_len = wsgi_req->sendfile_fd_size ;
#elif defined(__APPLE__)
int sf_ret;
off_t sf_len = filesize ;
if (uwsgi->async > 1) {
sf_len = wsgi_req->sendfile_fd_chunk;
sf_ret = sendfile(fd, sockfd, wsgi_req->sendfile_fd_pos, &sf_len, NULL, 0);
wsgi_req->sendfile_fd_pos += sf_len ;
if (async > 1) {
sf_len = chunk;
sf_ret = sendfile(filefd, sockfd, *pos, &sf_len, NULL, 0);
*pos += sf_len ;
}
else {
sf_ret = sendfile(fd, sockfd, 0, &sf_len, NULL, 0);
sf_ret = sendfile(filefd, sockfd, 0, &sf_len, NULL, 0);
}
if (sf_ret) {
@@ -86,11 +103,13 @@ ssize_t uwsgi_sendfile(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
return sf_len;
#elif defined(__linux__) || defined(__sun__)
if (uwsgi->async > 1) {
sf_ret = sendfile(sockfd, fd, &wsgi_req->sendfile_fd_pos, wsgi_req->sendfile_fd_chunk);
int sf_ret;
if (async > 1) {
sf_ret = sendfile(sockfd, filefd, pos, chunk);
}
else {
sf_ret = sendfile(sockfd, fd, &wsgi_req->sendfile_fd_pos, wsgi_req->sendfile_fd_size);
sf_ret = sendfile(sockfd, filefd, pos, filesize);
}
if (sf_ret < 0) {
@@ -100,7 +119,7 @@ ssize_t uwsgi_sendfile(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
return sf_ret ;
#else
static nosf_buf_size = 0 ;
static size_t nosf_buf_size = 0 ;
static char *nosf_buf ;
ssize_t jlen = 0;
@@ -108,16 +127,16 @@ ssize_t uwsgi_sendfile(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
ssize_t i = 0;
if (!nosf_buf) {
nosf_buf = malloc(wsgi_req->sendfile_fd_chunk);
nosf_buf = malloc(chunk);
}
else if (wsgi_req->sendfile_fd_chunk != nosf_buf_size) {
nosf_buf = realloc(nosf_buf, wsgi_req->sendfile_fd_chunk);
else if (chunk != nosf_buf_size) {
nosf_buf = realloc(nosf_buf, chunk);
}
nosf_buf_size = wsgi_req->sendfile_fd_chunk ;
nosf_buf_size = chunk ;
if (uwsgi->async > 1) {
jlen = read(fd, nosf_buf, wsgi_req->sendfile_fd_chunk);
if (async > 1) {
jlen = read(filefd, nosf_buf, chunk);
if (jlen <= 0) {
uwsgi_error("read()");
return 0;
@@ -130,8 +149,8 @@ ssize_t uwsgi_sendfile(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
return jlen ;
}
while (i < wsgi_req->sendfile_fd_size) {
jlen = read(fd, nosf_buf, wsgi_req->sendfile_fd_chunk);
while (i < filesize) {
jlen = read(filefd, nosf_buf, chunk);
if (jlen <= 0) {
uwsgi_error("read()");
break;
@@ -148,13 +167,11 @@ ssize_t uwsgi_sendfile(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
return rlen;
#endif
}
return 0;
}
#endif
+8 -4
View File
@@ -3,9 +3,10 @@ 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
from setuptools import setup
from setuptools.dist import Distribution
from setuptools.command.install import install
from setuptools.command.build_ext import build_ext
class uWSGIBuilder(build_ext):
@@ -17,6 +18,9 @@ class uWSGIBuilder(build_ext):
class uWSGIInstall(install):
def run(self):
# hack, hack and still hack. We need to find a solution for 0.9.6
if self.record:
record_file = open(self.record,'w')
uc.parse_vars()
uc.build_uwsgi(sys.prefix + '/bin/' + uc.UWSGI_BIN_NAME)
@@ -30,7 +34,7 @@ class uWSGIDistribution(Distribution):
setup(name='uWSGI',
version='0.9.5',
version='0.9.6',
description='The uWSGI server',
author='Unbit',
author_email='info@unbit.it',
+30 -1
View File
@@ -1,8 +1,37 @@
import uwsgi
print "uWSGI version:", uwsgi.version
def ciao():
print "modifica su /tmp"
def ciao2():
print "nuovo uwsgi_server"
counter = 0
#if uwsgi.load_plugin(0, 'plugins/example/example_plugin.so', 'ciao'):
# print "example plugin loaded"
#else:
# print "unable to load example plugin"
#uwsgi.event_add(uwsgi.EVENT_FILE, "/tmp", ciao)
#uwsgi.event_add(uwsgi.EVENT_DNSSD, "_uwsgi._tcp", ciao2)
#uwsgi.event_add(uwsgi.EVENT_TIMER, 1000, ciao2)
def application(env, start_response):
#print env
global counter
print env
start_response('200 Ok', [('Content-type', 'text/plain')])
yield "hello world"
yield "hello world2"
for i in xrange(1,1000):
yield str(i)
yield "\n"
yield str(counter)
counter += 1
+9
View File
@@ -0,0 +1,9 @@
def mygen(uri):
for i in xrange(1,100):
yield "ciao %s<br/>" % uri
def application(env, start_response = None):
return '200 OK', [('Content-Type', 'text/html')], "<h1>This is the fastest homepage of the world !!!</h1>"
#return '200 OK', [('Content-Type', 'text/html')], mygen(env['PATH_INFO'])
+12 -7
View File
@@ -43,17 +43,21 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
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;
@@ -66,6 +70,7 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
// 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;
@@ -266,7 +271,7 @@ static uint8_t snmp_int_to_snmp(uint64_t snmp_val, uint8_t oid_type, uint8_t * b
uint8_t tlen;
int i, j;
uint8_t *ptr = (uint8_t *) & snmp_val;
uint8_t *ptr = (uint8_t *) &snmp_val;
// check for counter, counter64 or gauge
@@ -334,7 +339,7 @@ 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)) {
if (!PyArg_ParseTuple(args, "bI:snmp_set_counter32", &oid_num, &oid_val)) {
return NULL;
}
@@ -358,7 +363,7 @@ 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)) {
if (!PyArg_ParseTuple(args, "bK:snmp_set_counter64", &oid_num, &oid_val)) {
return NULL;
}
@@ -382,7 +387,7 @@ 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)) {
if (!PyArg_ParseTuple(args, "bI:snmp_set_gauge", &oid_num, &oid_val)) {
return NULL;
}
@@ -410,11 +415,11 @@ PyObject *py_snmp_community(PyObject * self, PyObject * args) {
}
if (strlen(snmp_community) > 72) {
fprintf(stderr, "*** warning the supplied SNMP community string will be truncated to 72 chars ***\n");
uwsgi_log( "*** 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);
memcpy(uwsgi.shared->snmp_community, snmp_community, strlen(snmp_community) + 1);
}
Py_INCREF(Py_True);
@@ -440,7 +445,7 @@ void snmp_init() {
Py_DECREF(func);
}
fprintf(stderr, "SNMP python functions initialized.\n");
uwsgi_log( "SNMP python functions initialized.\n");
}
+68 -12
View File
@@ -7,11 +7,11 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
int serverfd;
struct sockaddr_un *uws_addr;
fprintf(stderr, "binding on UNIX socket: %s\n", socket_name);
uwsgi_log( "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");
uwsgi_log( "invalid socket name\n");
exit(1);
}
@@ -34,11 +34,11 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
}
if (abstract_socket == 1) {
fprintf(stderr, "setting abstract socket mode (warning: only Linux supports this)\n");
uwsgi_log( "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);
memcpy(uws_addr->sun_path + abstract_socket, socket_name, 102);
if (bind(serverfd, (struct sockaddr *) uws_addr, strlen(socket_name) + abstract_socket + ((void *) uws_addr->sun_path - (void *) uws_addr)) != 0) {
uwsgi_error("bind()");
@@ -52,12 +52,21 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
// 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) {
uwsgi_error("chmod()");
if (uwsgi.chmod_socket_value) {
if (chmod(socket_name, uwsgi.chmod_socket_value) != 0) {
uwsgi_error("chmod()");
}
}
else {
uwsgi_log( "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) {
uwsgi_error("chmod()");
}
}
}
free(uws_addr);
return serverfd;
}
@@ -95,7 +104,7 @@ int bind_to_sctp(char *socket_name, int listen_queue, char *sctp_port) {
exit(1);
}
fprintf(stderr, "binding on %d SCTP interfaces on port: %d\n", num_ip, ntohs(uws_addr[0].sin_port));
uwsgi_log( "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) {
@@ -168,7 +177,7 @@ int bind_to_udp(char *socket_name) {
}
#endif
fprintf(stderr, "binding on UDP port: %d\n", ntohs(uws_addr.sin_port));
uwsgi_log( "binding on UDP port: %d\n", ntohs(uws_addr.sin_port));
if (bind(serverfd, (struct sockaddr *) &uws_addr, sizeof(uws_addr)) != 0) {
uwsgi_error("bind()");
@@ -178,7 +187,7 @@ int bind_to_udp(char *socket_name) {
#ifdef UWSGI_MULTICAST
if (uwsgi.multicast_group) {
fprintf(stderr, "joining uWSGI multicast group: %s:%d\n", uwsgi.multicast_group, ntohs(uws_addr.sin_port));
uwsgi_log( "joining uWSGI multicast group: %s:%d\n", uwsgi.multicast_group, ntohs(uws_addr.sin_port));
if (setsockopt(serverfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mc, sizeof(mc))) {
uwsgi_error("setsockopt()");
}
@@ -190,6 +199,47 @@ int bind_to_udp(char *socket_name) {
}
#endif
int uwsgi_connect(char *socket_name, int timeout) {
char *tcp_port = strchr(socket_name, ':');
if (tcp_port) {
tcp_port[0] = 0;
tcp_port++;
return connect_to_tcp(socket_name, atoi(tcp_port), timeout);
}
return connect_to_unix(socket_name, timeout);
}
int connect_to_unix(char *socket_name, int timeout) {
struct pollfd uwsgi_poll;
struct sockaddr_un uws_addr;
memset(&uws_addr, 0, sizeof(struct sockaddr_un));
uws_addr.sun_family = AF_UNIX;
memcpy(uws_addr.sun_path, socket_name, 102);
uwsgi_poll.fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (uwsgi_poll.fd < 0) {
uwsgi_error("socket()");
return -1;
}
uwsgi_poll.events = POLLIN;
if (timed_connect(&uwsgi_poll, (const struct sockaddr *) &uws_addr, sizeof(struct sockaddr_un), timeout)) {
uwsgi_error("connect()");
close(uwsgi_poll.fd);
return -1;
}
return uwsgi_poll.fd;
}
int connect_to_tcp(char *socket_name, int port, int timeout) {
struct pollfd uwsgi_poll;
@@ -207,6 +257,8 @@ int connect_to_tcp(char *socket_name, int port, int timeout) {
uws_addr.sin_addr.s_addr = inet_addr(socket_name);
}
socket_name[strlen(socket_name)] = ':' ;
uwsgi_poll.fd = socket(AF_INET, SOCK_STREAM, 0);
if (uwsgi_poll.fd < 0) {
uwsgi_error("socket()");
@@ -262,7 +314,8 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
if (setsockopt(serverfd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], sizeof(int))) {
uwsgi_error("setsockopt()");
}
#elif defined(__apple__) || defined(__freebsd__)
// OSX has no SO_ACCEPTFILTER !!!
#elif defined(__freebsd__)
struct accept_filter_arg afa;
strcpy(afa.af_name, "dataready");
afa.af_arg[0] = 0;
@@ -274,9 +327,12 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
}
fprintf(stderr, "binding on TCP port: %d\n", ntohs(uws_addr.sin_port));
uwsgi_log( "binding on TCP port: %d\n", ntohs(uws_addr.sin_port));
if (bind(serverfd, (struct sockaddr *) &uws_addr, sizeof(uws_addr)) != 0) {
if (errno == EADDRINUSE) {
uwsgi_log("probably another instance of uWSGI is running on the same address.\n");
}
uwsgi_error("bind()");
exit(1);
}
+30 -19
View File
@@ -1,9 +1,6 @@
#ifdef UWSGI_SPOOLER
#include "uwsgi.h"
#include <dirent.h>
int spool_request(struct uwsgi_server *uwsgi, char *filename, int rn, char *buffer, int size) {
@@ -21,7 +18,7 @@ int spool_request(struct uwsgi_server *uwsgi, char *filename, int rn, char *buff
hostname[256] = 0;
if (snprintf(filename, 1024, "%s/uwsgi_spoolfile_on_%s_%d_%d_%llu_%llu", uwsgi->spool_dir, hostname, getpid(), rn, (unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec) <= 0) {
if (snprintf(filename, 1024, "%s/uwsgi_spoolfile_on_%s_%d_%d_%llu_%llu", uwsgi->spool_dir, hostname, (int) getpid(), rn, (unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec) <= 0) {
return 0;
}
@@ -59,7 +56,7 @@ int spool_request(struct uwsgi_server *uwsgi, char *filename, int rn, char *buff
close(fd);
fprintf(stderr, "written %d bytes to spool file %s.\n", size + 4, filename);
uwsgi_log( "written %d bytes to spool file %s.\n", size + 4, filename);
return 1;
@@ -81,6 +78,9 @@ void spooler(struct uwsgi_server *uwsgi, PyObject * uwsgi_module_dict) {
int rlen = 0;
int datasize;
// prevent process blindly reading stdin to make mess
int nullfd;
struct uwsgi_header uh;
char *key;
@@ -92,14 +92,14 @@ void spooler(struct uwsgi_server *uwsgi, PyObject * uwsgi_module_dict) {
spool_tuple = PyTuple_New(1);
if (!spool_tuple) {
fprintf(stderr, "could not create spooler tuple.\n");
uwsgi_log( "could not create spooler tuple.\n");
exit(1);
}
spool_env = PyDict_New();
if (!spool_env) {
fprintf(stderr, "could not create spooler env.\n");
uwsgi_log( "could not create spooler env.\n");
exit(1);
}
@@ -114,9 +114,20 @@ void spooler(struct uwsgi_server *uwsgi, PyObject * uwsgi_module_dict) {
}
// asked by Marco Beri
fprintf(stderr, "lowering spooler priority to %d\n", PRIO_MAX);
uwsgi_log( "lowering spooler priority to %d\n", PRIO_MAX);
setpriority(PRIO_PROCESS, getpid(), PRIO_MAX);
nullfd = open("/dev/null", O_RDONLY);
if (nullfd < 0) {
uwsgi_error("open()");
exit(1);
}
if (nullfd != 0) {
dup2(nullfd, 0);
close(nullfd);
}
for (;;) {
sleep(uwsgi->shared->spooler_frequency);
@@ -133,11 +144,11 @@ void spooler(struct uwsgi_server *uwsgi, PyObject * uwsgi_module_dict) {
continue;
}
if (!access(dp->d_name, R_OK | W_OK)) {
fprintf(stderr, "managing spool request %s...\n", dp->d_name);
uwsgi_log( "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");
uwsgi_log( "you have to define uwsgi.spooler to use the spooler !!!\n");
continue;
}
@@ -238,28 +249,28 @@ void spooler(struct uwsgi_server *uwsgi, PyObject * uwsgi_module_dict) {
}
spool_result = python_call(spooler_callable, spool_tuple);
spool_result = python_call(spooler_callable, spool_tuple, 0);
if (!spool_result) {
PyErr_Print();
fprintf(stderr, "error detected. spool request canceled.\n");
uwsgi_log( "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");
uwsgi_log( "retry this task later...\n");
goto retry_later;
}
}
Py_DECREF(spool_result);
fprintf(stderr, "done with task/spool %s\n", dp->d_name);
uwsgi_log( "done with task/spool %s\n", dp->d_name);
next_spool:
if (unlink(dp->d_name)) {
uwsgi_error("unlink");
fprintf(stderr, "something horrible happened to the spooler. Better to kill it.\n");
uwsgi_log( "something horrible happened to the spooler. Better to kill it.\n");
exit(1);
}
retry_later:
@@ -283,7 +294,7 @@ int uwsgi_request_spooler(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_
char spool_filename[1024];
if (uwsgi->spool_dir == NULL) {
fprintf(stderr, "the spooler is inactive !!!...skip\n");
uwsgi_log( "the spooler is inactive !!!...skip\n");
wsgi_req->uh.modifier1 = 255;
wsgi_req->uh.pktsize = 0;
wsgi_req->uh.modifier2 = 0;
@@ -294,18 +305,18 @@ int uwsgi_request_spooler(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_
return -1;
}
fprintf(stderr, "managing spool request...\n");
uwsgi_log( "managing spool request...\n");
i = spool_request(uwsgi, spool_filename, uwsgi->workers[0].requests + 1, wsgi_req->buffer, wsgi_req->uh.pktsize);
wsgi_req->uh.modifier1 = 255;
wsgi_req->uh.pktsize = 0;
if (i > 0) {
wsgi_req->uh.modifier2 = 1;
if (write(wsgi_req->poll.fd, wsgi_req, 4) != 4) {
fprintf(stderr, "disconnected client, remove spool file.\n");
uwsgi_log( "disconnected client, remove spool file.\n");
/* client disconnect, remove spool file */
if (unlink(spool_filename)) {
uwsgi_error("unlink()");
fprintf(stderr, "something horrible happened !!! check your spooler ASAP !!!\n");
uwsgi_log( "something horrible happened !!! check your spooler ASAP !!!\n");
goodbye_cruel_world();
}
}
+7 -7
View File
@@ -25,7 +25,7 @@ PyObject *py_uwsgi_stackless_worker(PyObject * self, PyObject * args) {
int async_id = wsgi_req->async_id;
//fprintf(stderr,"i am the tasklet worker\n");
//uwsgi_log("i am the tasklet worker\n");
for(;;) {
@@ -74,7 +74,7 @@ void stackless_init(struct uwsgi_server *uwsgi) {
memset(uwsgi->stackless_table[i], 0, sizeof(struct stackless_req));
}
fprintf(stderr,"initializing %d tasklet...", uwsgi->async);
uwsgi_log("initializing %d tasklet...", uwsgi->async);
// creating uwsgi->async tasklets
for(i=0;i<uwsgi->async;i++) {
@@ -90,7 +90,7 @@ void stackless_init(struct uwsgi_server *uwsgi) {
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
fprintf(stderr,"done\n");
uwsgi_log("done\n");
}
void stackless_loop(struct uwsgi_server *uwsgi) {
@@ -114,7 +114,7 @@ void stackless_loop(struct uwsgi_server *uwsgi) {
if (uwsgi->async_events[i].ASYNC_FD == uwsgi->serverfd) {
//pass the connection to the first available tasklet
fprintf(stderr,"sending new connection...\n");
uwsgi_log("sending new connection...\n");
PyChannel_Send(uwsgi->workers_channel, Py_True);
}
@@ -130,11 +130,11 @@ void stackless_loop(struct uwsgi_server *uwsgi) {
//int_tasklet = (PyTaskletObject *) PyStackless_RunWatchdog( 1000 );
/*
fprintf(stderr,"done watchdog %p\n", int_tasklet);
uwsgi_log("done watchdog %p\n", int_tasklet);
if (!PyTasklet_IsCurrent(int_tasklet)) {
fprintf(stderr,"re-insert: %d\n", 1);// PyTasklet_Insert(int_tasklet));
uwsgi_log("re-insert: %d\n", 1);// PyTasklet_Insert(int_tasklet));
}
fprintf(stderr,"recycle\n");
uwsgi_log("recycle\n");
*/
}
-1
View File
@@ -9,4 +9,3 @@ my $app = sub {
[ "Hello World\r\n", $env->{'REQUEST_URI'} ],
];
};
+1 -1
View File
@@ -2,5 +2,5 @@ import time
def application(env, start_response):
start_response( '200 OK', [ ('Content-Type','text/html') ])
for i in range(1,100000):
for i in range(1,1000):
yield "<h1>%s at %s</h1>" % (i, str(time.time()))
+22
View File
@@ -0,0 +1,22 @@
import uwsgi
import time
def application(env, start_response):
start_response('200 Ok', [ ('Content-Type','text/html') ] )
yield "I am the worker %d<br/>" % uwsgi.worker_id()
grunt = uwsgi.grunt()
if grunt is None:
print "worker %d detached" % uwsgi.worker_id()
else:
yield "And now i am the grunt with a fix worker id of %d<br/>" % uwsgi.worker_id()
time.sleep(2)
yield "Now, i will start a very slow task...<br/>"
for i in xrange(1,10):
yield "waiting for %d seconds<br/>" % i
time.sleep(i)
+1 -1
View File
@@ -296,7 +296,7 @@ void u_green_init(struct uwsgi_server *uwsgi) {
u_stack_size = uwsgi->ugreen_stackpages * uwsgi->page_size ;
}
fprintf(stderr,"initializing %d uGreen threads with stack size of %lu (%lu KB)\n", uwsgi->async, (unsigned long) u_stack_size, (unsigned long) u_stack_size/1024);
uwsgi_log("initializing %d uGreen threads with stack size of %lu (%lu KB)\n", uwsgi->async, (unsigned long) u_stack_size, (unsigned long) u_stack_size/1024);
uwsgi->ugreen_contexts = malloc( sizeof(ucontext_t*) * uwsgi->async);
+33
View File
@@ -0,0 +1,33 @@
import uwsgi
def ciao():
uwsgi.start_response('200 OK', [ ('Content-type', 'text/plain') ])
uwsgi.send(str(22+30))
def application(env, start_response):
start_response('200 Ok', [('Content-type', 'text/html')])
if env['REQUEST_METHOD'] == 'POST':
print "getting file..."
remains = int(env['CONTENT_LENGTH'])
print remains
buf = ''
while remains > 0:
if remains < 8192:
buf = env['wsgi.input'].read(remains)
else:
buf = env['wsgi.input'].read(8192)
#print len(buf)
remains = remains - len(buf)
#print "remains",remains
print "upload ready"
yield env['CONTENT_LENGTH']
else:
yield """
<form method="POST" enctype="multipart/form-data">
<input type="file" name="file" />
<input type="submit" value="invia" />
</form>
"""
+134 -45
View File
@@ -7,10 +7,37 @@ extern struct uwsgi_server uwsgi;
uint16_t uwsgi_swap16(uint16_t x) {
return (uint16_t) ((x & 0xff) << 8 | (x & 0xff00) >> 8);
}
uint32_t uwsgi_swap32(uint32_t x) {
x = ( (x<<8) & 0xFF00FF00 ) | ( (x>>8) & 0x00FF00FF );
return (x>>16) | (x<<16);
}
// thanks to ffmpeg project for this idea :P
uint64_t uwsgi_swap64(uint64_t x) {
union {
uint64_t ll;
uint32_t l[2];
} w, r;
w.ll = x;
r.l[0] = uwsgi_swap32(w.l[1]);
r.l[1] = uwsgi_swap32(w.l[0]);
return r.ll;
}
#endif
void inc_harakiri(int sec) {
if (uwsgi.master_process) {
uwsgi.workers[uwsgi.mywid].harakiri += sec;
}
else {
alarm(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] + sec);
}
}
void set_harakiri(int sec) {
if (uwsgi.workers) {
if (uwsgi.master_process) {
if (sec == 0) {
uwsgi.workers[uwsgi.mywid].harakiri = 0;
}
@@ -23,16 +50,10 @@ void set_harakiri(int sec) {
}
}
#ifndef UNBIT
void daemonize(char *logfile) {
pid_t pid;
int fd, fdin;
int fdin;
#ifdef UWSGI_UDP
char *udp_port;
struct sockaddr_in udp_addr;
#endif
@@ -76,13 +97,30 @@ void daemonize(char *logfile) {
exit(1);
}
/* stdin */
if (dup2(fdin, 0) < 0) {
uwsgi_error("dup2()");
exit(1);
}
logto(logfile);
}
void logto(char *logfile) {
int fd ;
#ifdef UWSGI_UDP
char *udp_port;
struct sockaddr_in udp_addr;
udp_port = strchr(logfile, ':');
if (udp_port) {
udp_port[0] = 0 ;
if ( !udp_port[1] || !logfile[0] ) {
fprintf(stderr,"invalid udp address\n");
uwsgi_log("invalid udp address\n");
exit(1);
}
@@ -111,15 +149,10 @@ void daemonize(char *logfile) {
exit(1);
}
#ifdef UWSGI_UDP
uwsgi.logfile = logfile;
}
#endif
/* stdin */
if (dup2(fdin, 0) < 0) {
uwsgi_error("dup2()");
exit(1);
}
/* stdout */
if (dup2(fd, 1) < 0) {
@@ -134,12 +167,9 @@ void daemonize(char *logfile) {
}
close(fd);
}
#endif
char *uwsgi_get_cwd() {
@@ -154,7 +184,7 @@ char *uwsgi_get_cwd() {
if (getcwd(cwd, newsize) == NULL) {
newsize = errno;
fprintf(stderr, "need a bigger buffer (%d bytes) for getcwd(). doing reallocation.\n", newsize);
uwsgi_log("need a bigger buffer (%d bytes) for getcwd(). doing reallocation.\n", newsize);
free(cwd);
cwd = malloc(newsize);
if (cwd == NULL) {
@@ -172,17 +202,14 @@ char *uwsgi_get_cwd() {
}
void internal_server_error(int fd, char *message) {
#ifndef UNBIT
if (uwsgi.shared->options[UWSGI_OPTION_CGI_MODE] == 0) {
#endif
uwsgi.wsgi_req->headers_size = write(fd, "HTTP/1.1 500 Internal Server Error\r\nContent-type: text/html\r\n\r\n", 63);
#ifndef UNBIT
}
else {
uwsgi.wsgi_req->headers_size = write(fd, "Status: 500 Internal Server Error\r\nContent-type: text/html\r\n\r\n", 62);
}
uwsgi.wsgi_req->header_cnt = 2;
#endif
uwsgi.wsgi_req->response_size = write(fd, "<h1>uWSGI Error</h1>", 20);
uwsgi.wsgi_req->response_size += write(fd, message, strlen(message));
}
@@ -190,28 +217,28 @@ void internal_server_error(int fd, char *message) {
void uwsgi_as_root() {
if (!getuid()) {
fprintf(stderr, "uWSGI running as root, you can use --uid/--gid/--chroot options\n");
uwsgi_log("uWSGI running as root, you can use --uid/--gid/--chroot options\n");
if (uwsgi.chroot) {
fprintf(stderr, "chroot() to %s\n", uwsgi.chroot);
uwsgi_log("chroot() to %s\n", uwsgi.chroot);
if (chroot(uwsgi.chroot)) {
uwsgi_error("chroot()");
exit(1);
}
#ifdef __linux__
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG]) {
fprintf(stderr, "*** Warning, on linux system you have to bind-mount the /proc fs in your chroot to get memory debug/report.\n");
uwsgi_log("*** Warning, on linux system you have to bind-mount the /proc fs in your chroot to get memory debug/report.\n");
}
#endif
}
if (uwsgi.gid) {
fprintf(stderr, "setgid() to %d\n", uwsgi.gid);
uwsgi_log("setgid() to %d\n", uwsgi.gid);
if (setgid(uwsgi.gid)) {
uwsgi_error("setgid()");
exit(1);
}
}
if (uwsgi.uid) {
fprintf(stderr, "setuid() to %d\n", uwsgi.uid);
uwsgi_log("setuid() to %d\n", uwsgi.uid);
if (setuid(uwsgi.uid)) {
uwsgi_error("setuid()");
exit(1);
@@ -219,20 +246,20 @@ void uwsgi_as_root() {
}
if (!getuid()) {
fprintf(stderr, " *** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** \n");
uwsgi_log(" *** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** \n");
}
}
else {
if (uwsgi.chroot) {
fprintf(stderr, "cannot chroot() as non-root user\n");
if (uwsgi.chroot && !uwsgi.is_a_reload) {
uwsgi_log("cannot chroot() as non-root user\n");
exit(1);
}
if (uwsgi.gid) {
fprintf(stderr, "cannot setgid() as non-root user\n");
if (uwsgi.gid && getgid() != uwsgi.gid) {
uwsgi_log("cannot setgid() as non-root user\n");
exit(1);
}
if (uwsgi.uid) {
fprintf(stderr, "cannot setuid() as non-root user\n");
if (uwsgi.uid && getuid() != uwsgi.uid) {
uwsgi_log("cannot setuid() as non-root user\n");
exit(1);
}
}
@@ -250,25 +277,27 @@ void uwsgi_close_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_r
if (uwsgi->shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1)
get_memusage();
// close the connection with the webserver
if (!wsgi_req->fd_closed) {
// TODO find a way to discard pending data
close(wsgi_req->poll.fd);
}
uwsgi->workers[0].requests++;
uwsgi->workers[uwsgi->mywid].requests++;
// after_request hook
(*uwsgi->shared->after_hooks[wsgi_req->uh.modifier1]) (uwsgi, wsgi_req);
// leave harakiri mode
if (uwsgi->workers[uwsgi->mywid].harakiri > 0) {
if (uwsgi->shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
set_harakiri(0);
}
// defunct process reaper
if (uwsgi->shared->options[UWSGI_OPTION_REAPER] == 1) {
waitpid(-1, &waitpid_status, WNOHANG);
if (uwsgi->shared->options[UWSGI_OPTION_REAPER] == 1 || uwsgi->grunt) {
while( waitpid(-1, &waitpid_status, WNOHANG) > 0) ;
}
// reset request
memset(wsgi_req, 0, sizeof(struct wsgi_request));
@@ -277,6 +306,7 @@ void uwsgi_close_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_r
goodbye_cruel_world();
}
}
void wsgi_req_setup(struct wsgi_request *wsgi_req, int async_id) {
@@ -294,6 +324,14 @@ void wsgi_req_setup(struct wsgi_request *wsgi_req, int async_id) {
wsgi_req->hvec = &uwsgi.async_hvec[wsgi_req->async_id];
wsgi_req->buffer = uwsgi.async_buf[wsgi_req->async_id];
#ifdef UWSGI_ROUTING
wsgi_req->ovector = uwsgi.async_ovector[wsgi_req->async_id];
#endif
if (uwsgi.post_buffering > 0) {
wsgi_req->post_buffering_buf = uwsgi.async_post_buf[wsgi_req->async_id];
}
}
int wsgi_req_recv(struct wsgi_request *wsgi_req) {
@@ -347,7 +385,7 @@ void sanitize_args(struct uwsgi_server *uwsgi) {
#ifdef UWSGI_PROFILER
if (uwsgi->enable_profiler) {
fprintf(stderr,"*** Profiler enabled, do not use it in production environment !!! ***\n");
uwsgi_log("*** Profiler enabled, do not use it in production environment !!! ***\n");
uwsgi->async = 1;
}
#endif
@@ -356,21 +394,46 @@ void sanitize_args(struct uwsgi_server *uwsgi) {
#ifdef UWSGI_THREADING
if (uwsgi->ugreen) {
if (uwsgi->has_threads) {
fprintf(stderr,"--- python threads will be disabled in uGreen mode ---\n");
uwsgi_log("--- python threads will be disabled in uGreen mode ---\n");
uwsgi->has_threads = 0;
}
}
#endif
#endif
if (uwsgi->wsgi_config) {
uwsgi->single_interpreter = 1 ;
}
if (uwsgi->shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
if (!uwsgi->post_buffering) {
uwsgi_log(" *** WARNING: you have enabled harakiri without post buffering. Slow upload could be rejected on post-unbuffered webservers *** \n");
}
}
#ifdef UWSGI_HTTP
if (uwsgi->http && !uwsgi->http_only) {
uwsgi->vacuum = 1;
}
#endif
}
void env_to_arg(char *src, char *dst) {
int i;
int val = 0 ;
for(i=0;i<strlen(src);i++) {
dst[i] = tolower(src[i]);
if (dst[i] == '_') {
dst[i] = '-';
if (src[i] == '=') {
val = 1 ;
}
if (val) {
dst[i] = src[i];
}
else {
dst[i] = tolower( (int) src[i]);
if (dst[i] == '_') {
dst[i] = '-';
}
}
}
@@ -424,3 +487,29 @@ void parse_sys_envs(char **envs, struct option *long_options) {
}
}
//use this instead of fprintf to avoid buffering mess with udp logging
void uwsgi_log(const char *fmt, ...) {
va_list ap;
char logpkt[4096];
int rlen = 0;
struct timeval tv;
if (uwsgi.logdate) {
gettimeofday(&tv, NULL);
memcpy( logpkt, ctime( (const time_t *) &tv.tv_sec), 24);
memcpy( logpkt + 24, " - ", 3);
rlen = 24 + 3 ;
}
va_start (ap, fmt);
rlen += vsnprintf(logpkt + rlen, 4096 - rlen, fmt, ap );
va_end(ap);
// do not check for errors
rlen = write(2, logpkt, rlen);
}
+1077 -601
View File
File diff suppressed because it is too large Load Diff
+306 -27
View File
@@ -1,18 +1,33 @@
/* uWSGI */
/* indent -i8 -br -brs -brf -l0 -npsl -nip -npcs */
/* indent -i8 -br -brs -brf -l0 -npsl -nip -npcs -npsl -di1 */
#define UWSGI_VERSION "0.9.5-dev"
#define UWSGI_VERSION "0.9.6"
#define uwsgi_error(x) fprintf(stderr, "%s: %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__);
#define uwsgi_error(x) uwsgi_log("%s: %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__);
#define uwsgi_debug(x, ...) uwsgi_log("[uWSGI DEBUG] " x, __VA_ARGS__);
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <stdarg.h>
#include <dirent.h>
#include <pwd.h>
#include <grp.h>
#include <sys/utsname.h>
#ifdef __linux
#include <sys/prctl.h>
#endif
#ifdef UWSGI_SCTP
#include <netinet/sctp.h>
@@ -22,6 +37,14 @@
#include <ucontext.h>
#endif
#ifndef UWSGI_PLUGIN_BASE
#define UWSGI_PLUGIN_BASE ""
#endif
#ifdef UWSGI_ROUTING
#include <pcre.h>
#endif
#include <arpa/inet.h>
#include <sys/mman.h>
#include <sys/file.h>
@@ -30,6 +53,10 @@
#include <sys/wait.h>
#ifdef __APPLE__
#define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_4
#endif
#include <dlfcn.h>
#include <poll.h>
@@ -42,9 +69,7 @@
#include <sys/resource.h>
#ifndef UNBIT
#include <getopt.h>
#endif
#ifdef __APPLE__
#include <libkern/OSAtomic.h>
@@ -73,6 +98,7 @@
#include <sys/sendfile.h>
#include <sys/epoll.h>
#elif defined(__sun__)
#include <sys/sendfile.h>
#include <sys/devpoll.h>
#else
#include <sys/event.h>
@@ -94,7 +120,7 @@
#endif
/* this value are taken from nginx */
#if defined(__apple__) || defined(__freebsd__)
#if defined(__APPLE__) || defined(__freebsd__)
#define UWSGI_LISTEN_QUEUE -1
#else
#define UWSGI_LISTEN_QUEUE 511
@@ -132,6 +158,27 @@ PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
#define LONG_ARGS_UGREEN_PAGES 17022
#define LONG_ARGS_FILE_CONFIG 17023
#define LONG_ARGS_MULTICAST 17024
#define LONG_ARGS_LOGTO 17025
#define LONG_ARGS_PRIO 17026
#define LONG_ARGS_POST_BUFFERING 17027
#define LONG_ARGS_POST_BUFFERING_SIZE 17028
#define LONG_ARGS_LIMIT_POST 17029
#define LONG_ARGS_HTTP 17030
#define LONG_ARGS_MODE 17031
#define LONG_ARGS_CHDIR 17032
#define LONG_ARGS_ENV 17033
#define LONG_ARGS_CHDIR2 17034
#define LONG_ARGS_INI 17035
#define LONG_ARGS_LDAP_SCHEMA 17036
#define LONG_ARGS_LDAP 17037
#define LONG_ARGS_LDAP_SCHEMA_LDIF 17038
#define LONG_ARGS_PING 17039
#define LONG_ARGS_PING_TIMEOUT 17040
#define LONG_ARGS_INI_PASTE 17041
#define LONG_ARGS_CALLABLE 17042
#define LONG_ARGS_HTTP_VAR 17043
#define UWSGI_OK 0
#define UWSGI_AGAIN 1
@@ -167,7 +214,7 @@ PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
#ifdef _BIG_ENDIAN
#define __BIG_ENDIAN__ 1
#endif
#elif __apple__
#elif __APPLE__
#include <libkern/OSByteOrder.h>
#else
#include <machine/endian.h>
@@ -183,14 +230,9 @@ PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
#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
#endif
#define UWSGI_MODIFIER_ADMIN_REQUEST 10
#define UWSGI_MODIFIER_SPOOL_REQUEST 17
#define UWSGI_MODIFIER_EVAL 22
#define UWSGI_MODIFIER_FASTFUNC 26
#define UWSGI_MODIFIER_MANAGE_PATH_INFO 30
#define UWSGI_MODIFIER_MESSAGE 31
@@ -211,6 +253,7 @@ PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
#define PyString_FromFormat PyUnicode_FromFormat
#define PyString_FromString PyUnicode_FromString
#define PyString_Size PyUnicode_GET_DATA_SIZE
#define PyString_Concat PyUnicode_Concat
#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
@@ -223,10 +266,14 @@ PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
#define MAX_VARS 64
struct wsgi_request;
struct uwsgi_server;
struct uwsgi_app {
PyThreadState *interpreter;
PyObject *pymain_dict;
PyObject *wsgi_dict;
PyObject *wsgi_callable;
@@ -251,6 +298,31 @@ struct uwsgi_app {
};
#ifdef UWSGI_ROUTING
struct uwsgi_route {
const char *mountpoint;
const char *callbase;
pcre *pattern;
pcre_extra *pattern_extra;
pcre *method;
pcre_extra *method_extra;
const char *call;
int modifier1;
int modifier2;
void *callable;
void *callable_args;
int args;
void (*action)(struct uwsgi_server *, struct wsgi_request *, struct uwsgi_route *);
};
#endif
struct __attribute__ ((packed)) uwsgi_header {
uint8_t modifier1;
uint16_t pktsize;
@@ -295,16 +367,20 @@ struct wsgi_request {
char *script_name;
uint16_t script_name_len;
char *host;
uint16_t host_len;
char *path_info;
uint16_t path_info_len;
char *wsgi_script;
uint16_t wsgi_script_len;
char *wsgi_module;
uint16_t wsgi_module_len;
char *wsgi_callable;
uint16_t wsgi_callable_len;
#ifdef UNBIT
unsigned long long unbit_flags;
#endif
char *pyhome;
uint16_t pyhome_len;
int fd_closed;
@@ -312,6 +388,7 @@ struct wsgi_request {
size_t sendfile_fd_chunk;
size_t sendfile_fd_size;
off_t sendfile_fd_pos;
void *sendfile_obj;
uint16_t var_cnt;
uint16_t header_cnt;
@@ -332,6 +409,9 @@ struct wsgi_request {
void *async_app;
void *async_result;
#ifdef UWSGI_WSGI2
void *async_orig_result;
#endif
void *async_placeholder;
void *async_args;
void *async_environ;
@@ -340,6 +420,11 @@ struct wsgi_request {
int async_plagued;
int *ovector;
size_t post_cl;
char *post_buffering_buf;
uint64_t post_buffering_read;
#ifdef UWSGI_STACKLESS
PyTaskletObject* tasklet;
#endif
@@ -361,12 +446,24 @@ struct uwsgi_server {
struct wsgi_request *wsgi_req ;
PyThreadState *_save;
#ifndef UNBIT
char *chroot;
gid_t gid;
uid_t uid;
char *mode;
#ifdef UWSGI_HTTP
char *http;
char *http_server_name;
char *http_server_port;
int http_only;
int http_fd;
char *http_vars[64];
int http_vars_cnt;
#endif
int ignore_script_name;
int logdate;
int serverfd;
#ifdef UWSGI_PROXY
@@ -374,10 +471,23 @@ struct uwsgi_server {
char *proxy_socket_name;
#endif
char *logfile;
int vhost;
struct iovec *async_hvec;
char **async_buf;
char **async_post_buf;
#ifdef UWSGI_ROUTING
int **async_ovector;
#endif
struct rlimit rl;
size_t limit_post;
int prio;
int grunt;
char *binary_path;
@@ -417,15 +527,16 @@ struct uwsgi_server {
int buffer_size;
int post_buffering;
int post_buffering_harakiri;
int post_buffering_bufsize;
int master_process;
int no_defer_accept;
int page_size;
char *sync_page;
int synclog;
char *test_module;
char *pidfile;
@@ -468,9 +579,9 @@ struct uwsgi_server {
struct timeval start_tv;
#ifndef UNBIT
int abstract_socket;
int chmod_socket;
mode_t chmod_socket_value;
int listen_queue;
#ifdef UWSGI_XML
@@ -482,10 +593,31 @@ struct uwsgi_server {
char *python_path[64];
int python_path_cnt;
char *pyargv;
int pyargc;
#ifdef PYTHREE
wchar_t *py_argv[MAX_PYARGV];
#else
char *py_argv[MAX_PYARGV];
#endif
#ifdef UWSGI_ROUTING
#ifndef MAX_UWSGI_ROUTES
#define MAX_UWSGI_ROUTES 64
#endif
int routing;
int nroutes;
struct uwsgi_route routes[MAX_UWSGI_ROUTES];
#endif
char *wsgi_config;
#ifdef UWSGI_INI
char *ini;
#endif
#ifdef UWSGI_PASTE
char *paste;
#endif
char *wsgi_file;
int single_interpreter;
@@ -517,6 +649,44 @@ struct uwsgi_server {
int erlang_nodes;
int erlangfd;
#endif
int no_orphans;
#ifdef UWSGI_EMBED_PLUGINS
#ifdef UWSGI_EMBED_PLUGIN_PSGI
char *plugin_arg_psgi;
#endif
#ifdef UWSGI_EMBED_PLUGIN_LUA
char *plugin_arg_lua;
#endif
#ifdef UWSGI_EMBED_PLUGIN_RACK
char *plugin_arg_rack;
char *plugin_arg_rails;
#endif
#endif
char *chdir2;
int catch_exceptions;
int vacuum;
int no_server;
#ifdef UWSGI_LDAP
char *ldap;
#endif
char *ping;
int ping_timeout;
char *callable;
int xml_round2;
char *cwd;
};
struct uwsgi_cluster_node {
@@ -555,6 +725,8 @@ struct uwsgi_shared {
struct uwsgi_cluster_node nodes[MAX_CLUSTER_NODES];
off_t logsize;
#ifdef UWSGI_SPOOLER
pid_t spooler_pid;
int spooler_frequency;
@@ -616,19 +788,22 @@ 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 uwsgi_connect(char *, int);
int connect_to_tcp(char *, int, int);
int connect_to_unix(char *, int);
#ifdef UWSGI_SCTP
int bind_to_sctp(char *, int, char *);
#endif
#ifndef UNBIT
void daemonize(char *);
#endif
void logto(char *);
void log_request(struct wsgi_request *);
void get_memusage(void);
void harakiri(void);
#ifndef UNBIT
void stats(void);
#endif
void init_uwsgi_vars(void);
void init_uwsgi_embedded_module(void);
@@ -660,9 +835,12 @@ pid_t spooler_start(int, PyObject *);
#endif
void set_harakiri(int);
void inc_harakiri(int);
#ifdef __BIG_ENDIAN__
uint16_t uwsgi_swap16(uint16_t);
uint32_t uwsgi_swap32(uint32_t);
uint64_t uwsgi_swap64(uint64_t);
#endif
int init_uwsgi_app(PyObject *, PyObject *);
@@ -686,6 +864,7 @@ 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_eval(struct uwsgi_server *, struct wsgi_request *);
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 *);
@@ -724,7 +903,12 @@ struct wsgi_request *find_first_available_wsgi_req(struct uwsgi_server *);
struct wsgi_request *find_wsgi_req_by_fd(struct uwsgi_server *, int, int);
struct wsgi_request *find_wsgi_req_by_id(struct uwsgi_server *, int);
#ifdef __clang__
struct wsgi_request *next_wsgi_req(struct uwsgi_server *, struct wsgi_request *);
#else
inline struct wsgi_request *next_wsgi_req(struct uwsgi_server *, struct wsgi_request *);
#endif
int async_add(int, int , int) ;
int async_mod(int, int , int) ;
@@ -773,11 +957,12 @@ PyObject *py_uwsgi_stackless(PyObject *, PyObject *) ;
int manage_python_response(struct uwsgi_server *, struct wsgi_request *);
int uwsgi_python_call(struct uwsgi_server *, struct wsgi_request *, PyObject *, PyObject *);
PyObject *python_call(PyObject *, PyObject *);
PyObject *python_call(PyObject *, PyObject *, int);
#ifdef UWSGI_SENDFILE
PyObject *py_uwsgi_sendfile(PyObject *, PyObject *) ;
ssize_t uwsgi_sendfile(struct uwsgi_server *, struct wsgi_request *);
ssize_t uwsgi_do_sendfile(int, int, size_t, size_t, off_t*, int);
#endif
PyObject *py_uwsgi_write(PyObject *, PyObject *) ;
@@ -813,9 +998,103 @@ void u_green_init(struct uwsgi_server *);
void u_green_loop(struct uwsgi_server *);
#endif
#ifdef __clang__
struct wsgi_request *current_wsgi_req(struct uwsgi_server *);
#else
inline struct wsgi_request *current_wsgi_req(struct uwsgi_server *);
#endif
void sanitize_args(struct uwsgi_server *);
void env_to_arg(char *, char *);
void parse_sys_envs(char **, struct option *);
void uwsgi_log(const char *, ...);
#ifdef UWSGI_EVDIS
#define EVDIS_TYPE_FILE
#define EVDIS_TYPE_DNSSD
#endif
int uwsgi_load_plugin(struct uwsgi_server *, int, char *, char *, int);
void embed_plugins(struct uwsgi_server *);
// PLUGINS
#define UWSGI_PLUGIN_LONGOPT_PSGI
#define UWSGI_PLUGIN_LONGOPT_LUA
#define UWSGI_PLUGIN_LONGOPT_RACK
#define LONG_ARGS_PLUGIN_EMBED_PSGI
#define LONG_ARGS_PLUGIN_EMBED_LUA
#define LONG_ARGS_PLUGIN_EMBED_RACK
#ifdef UWSGI_EMBED_PLUGINS
#ifdef UWSGI_EMBED_PLUGIN_PSGI
#undef UWSGI_PLUGIN_LONGOPT_PSGI
#define UWSGI_PLUGIN_LONGOPT_PSGI {"psgi", required_argument, 0, 30005},
#undef LONG_ARGS_PLUGIN_EMBED_PSGI
#define LONG_ARGS_PLUGIN_EMBED_PSGI case 30005:\
uwsgi.plugin_arg_psgi = optarg;\
break;
#endif
#ifdef UWSGI_EMBED_PLUGIN_LUA
#undef UWSGI_PLUGIN_LONGOPT_LUA
#define UWSGI_PLUGIN_LONGOPT_LUA {"lua", required_argument, 0, 30006},
#undef LONG_ARGS_PLUGIN_EMBED_LUA
#define LONG_ARGS_PLUGIN_EMBED_LUA case 30006:\
uwsgi.plugin_arg_lua = optarg;\
break;
#endif
#ifdef UWSGI_EMBED_PLUGIN_RACK
#undef UWSGI_PLUGIN_LONGOPT_RACK
#define UWSGI_PLUGIN_LONGOPT_RACK {"rack", required_argument, 0, 30007},\
{"rails", required_argument, 0, 30008},
#undef LONG_ARGS_PLUGIN_EMBED_RACK
#define LONG_ARGS_PLUGIN_EMBED_RACK case 30007:\
uwsgi.plugin_arg_rack = optarg;\
break;\
case 30008:\
uwsgi.plugin_arg_rails = optarg;\
break;
#endif
#endif
#ifdef UWSGI_ROUTING
void routing_setup(struct uwsgi_server *);
void check_route(struct uwsgi_server *, struct wsgi_request *);
void uwsgi_route_action_uwsgi(struct uwsgi_server *, struct wsgi_request *, struct uwsgi_route *);
void uwsgi_route_action_wsgi(struct uwsgi_server *, struct wsgi_request *, struct uwsgi_route *);
#endif
void init_pyargv(struct uwsgi_server *);
void http_loop(struct uwsgi_server *);
int unconfigured_hook(struct uwsgi_server *, struct wsgi_request *);
#ifdef UWSGI_INI
void uwsgi_ini_config(char *, struct option*);
#endif
#ifdef UWSGI_LDAP
void uwsgi_ldap_schema_dump(struct option*);
void uwsgi_ldap_schema_dump_ldif(struct option*);
void uwsgi_ldap_config(struct uwsgi_server *, struct option*);
#endif
+14 -3
View File
@@ -1,5 +1,16 @@
<uwsgi>
<app mountpoint="/test">
<script>myapp_wsgi</script>
</app>
<module>rtmpt</module>
<socket mode="dev">:3031</socket>
<socket mode="pippo">:3031</socket>
<routing base="rtmpt" modifier1="0" modifier2="0">
<route method="GET" pattern="^/pippo/(\d+)$" requires="REMOTE_USER">homepage</route>
<route method="GET|POST" pattern="^/ciccia/(\d+)/(\w+)$">view1</route>
<route action="wsgi" pattern="^/amf">amfapp</route>
<route pattern="^/open/">rtmpt_open</route>
<route pattern="^/idle/(\d+)/(\d+)$">rtmpt_idle</route>
<route pattern="^/send/(\d+)/(\d+)$">rtmpt_send</route>
<route pattern="^/$">index</route>
</routing>
</uwsgi>
+42 -8
View File
@@ -4,13 +4,13 @@
int uwsgi_request_ping(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
char len;
fprintf(stderr, "PING\n");
uwsgi_log( "PING\n");
wsgi_req->uh.modifier2 = 1;
wsgi_req->uh.pktsize = 0;
len = strlen(uwsgi->shared->warning_message);
if (len > 0) {
// endianess check is not needed as the warning message can be max 80 chars
// TODO: check endianess ?
wsgi_req->uh.pktsize = len;
}
if (write(wsgi_req->poll.fd, wsgi_req, 4) != 4) {
@@ -24,7 +24,7 @@ int uwsgi_request_ping(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
}
}
return 0;
return UWSGI_OK;
}
/* uwsgi ADMIN|10 */
@@ -33,19 +33,53 @@ int uwsgi_request_admin(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_re
int i;
if (wsgi_req->uh.pktsize >= 4) {
memcpy(&opt_value, &wsgi_req->buffer, 4);
// TODO: check endianess
memcpy(&opt_value, wsgi_req->buffer, 4);
// TODO: check endianess ?
}
fprintf(stderr, "setting internal option %d to %d\n", wsgi_req->uh.modifier2, opt_value);
uwsgi_log( "setting internal option %d to %d\n", wsgi_req->uh.modifier2, opt_value);
uwsgi->shared->options[wsgi_req->uh.modifier2] = opt_value;
// ACK
wsgi_req->uh.modifier1 = 255;
wsgi_req->uh.pktsize = 0;
wsgi_req->uh.modifier2 = 1;
i = write(wsgi_req->poll.fd, wsgi_req, 4);
if (i != 4) {
uwsgi_error("write()");
}
return UWSGI_OK;
}
int uwsgi_request_eval(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
PyObject *code, *py_dict;
PyObject *m = PyImport_AddModule("__main__");
if (m == NULL) {
PyErr_Print();
return -1;
}
py_dict = PyModule_GetDict(m);
// make it a valid c string
wsgi_req->buffer[wsgi_req->uh.pktsize] = 0 ;
// need to find a way to cache compilations...
code = Py_CompileString(wsgi_req->buffer, "uWSGI", Py_file_input);
if (code == NULL) {
PyErr_Print();
return -1;
}
PyEval_EvalCode((PyCodeObject *)code, py_dict, py_dict );
Py_DECREF(code);
if (PyErr_Occurred()) {
PyErr_Print();
return -1;
}
return UWSGI_OK;
}
@@ -62,7 +96,7 @@ int uwsgi_request_fastfunc(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi
ffunc = PyList_GetItem(uwsgi->fastfuncslist, wsgi_req->uh.modifier2);
if (ffunc) {
fprintf(stderr, "managing fastfunc %d\n", wsgi_req->uh.modifier2);
uwsgi_log( "managing fastfunc %d\n", wsgi_req->uh.modifier2);
return uwsgi_python_call(uwsgi, wsgi_req, ffunc, NULL);
}
@@ -104,7 +138,7 @@ int uwsgi_request_marshal(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_
}
}
else {
fprintf(stderr, "marshalled object is too big. skip\n");
uwsgi_log( "marshalled object is too big. skip\n");
}
Py_DECREF(marshalled);
}
+189 -48
View File
@@ -19,6 +19,92 @@ extern struct uwsgi_server uwsgi;
#define UWSGI_LOGBASE "[- uWSGI -"
PyObject *py_uwsgi_send(PyObject * self, PyObject * args) {
char *data;
if (!PyArg_ParseTuple(args, "s:send", &data)) {
return NULL;
}
if (write(uwsgi.wsgi_req->poll.fd, data, strlen(data)) < 0) {
uwsgi_error("write()");
Py_INCREF(Py_None);
return Py_None;
}
Py_INCREF(Py_True);
return Py_True;
}
#ifdef UWSGI_SENDFILE
PyObject *py_uwsgi_advanced_sendfile(PyObject * self, PyObject * args) {
PyObject *what;
char *filename;
size_t chunk;
off_t pos = 0;
size_t filesize = 0;
struct stat stat_buf;
int fd = -1;
if (!PyArg_ParseTuple(args, "O|iii:sendfile", &what, &chunk, &pos, &filesize)) {
return NULL;
}
if (PyString_Check(what)) {
filename = PyString_AsString(what);
fd = open(filename, O_RDONLY);
if (fd < 0) {
uwsgi_error("open");
goto clear;
}
}
else {
fd = PyObject_AsFileDescriptor(what);
if (fd < 0) goto clear;
// check for mixing file_wrapper and sendfile
if (fd == uwsgi.wsgi_req->sendfile_fd) {
Py_INCREF(what);
}
}
if (!filesize) {
if (fstat(fd, &stat_buf)) {
uwsgi_error("fstat()");
goto clear2;
}
else {
filesize = stat_buf.st_size;
}
}
if (!filesize) goto clear2;
if (!chunk) chunk = 4096;
uwsgi.wsgi_req->response_size += uwsgi_do_sendfile(uwsgi.wsgi_req->poll.fd, fd, filesize, chunk, &pos, 0);
close(fd);
Py_INCREF(Py_True);
return Py_True;
clear2:
close(fd);
clear:
Py_INCREF(Py_None);
return Py_None;
}
#endif
#ifdef UWSGI_ASYNC
@@ -51,7 +137,7 @@ PyObject *py_uwsgi_warning(PyObject * self, PyObject * args) {
len = strlen(message);
if (len > 80) {
fprintf(stderr, "- warning message must be max 80 chars, it will be truncated -");
uwsgi_log( "- warning message must be max 80 chars, it will be truncated -");
memcpy(uwsgi.shared->warning_message, message, 80);
uwsgi.shared->warning_message[80] = 0;
}
@@ -74,10 +160,10 @@ PyObject *py_uwsgi_log(PyObject * self, PyObject * args) {
tt = time(NULL);
if (logline[strlen(logline)] != '\n') {
fprintf(stderr, UWSGI_LOGBASE " %.*s] %s\n", 24, ctime(&tt), logline);
uwsgi_log( UWSGI_LOGBASE " %.*s] %s\n", 24, ctime(&tt), logline);
}
else {
fprintf(stderr, UWSGI_LOGBASE " %.*s] %s", 24, ctime(&tt), logline);
uwsgi_log( UWSGI_LOGBASE " %.*s] %s", 24, ctime(&tt), logline);
}
Py_INCREF(Py_True);
@@ -298,6 +384,7 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args) {
spool_dict = PyTuple_GetItem(args, 0);
if (!PyDict_Check(spool_dict)) {
uwsgi_log("The argument of spooler callable must be a dictionary.\n");
Py_INCREF(Py_None);
return Py_None;
}
@@ -352,6 +439,7 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args) {
}
}
else {
uwsgi_log("spooler callable dictionary must contains only strings.\n");
Py_DECREF(zero);
Py_INCREF(Py_None);
return Py_None;
@@ -497,7 +585,7 @@ PyObject *py_uwsgi_send_multi_message(PyObject * self, PyObject * args) {
goto megamulticlear;
}
else if (pret == 0) {
fprintf(stderr, "timeout on multiple send !\n");
uwsgi_log( "timeout on multiple send !\n");
goto megamulticlear;
}
else {
@@ -564,55 +652,21 @@ PyObject *py_uwsgi_set_option(PyObject * self, PyObject * args) {
}
PyObject *py_uwsgi_load_plugin(PyObject * self, PyObject * args) {
uint8_t modifier;
int modifier;
char *plugin_name = NULL;
char *pargs = NULL;
void *plugin_handle;
int (*plugin_init) (struct uwsgi_server *, char *);
int (*plugin_request) (struct uwsgi_server *, struct wsgi_request *);
void (*plugin_after_request) (struct uwsgi_server *, struct wsgi_request *);
if (!PyArg_ParseTuple(args, "is|s:load_plugin", &modifier, &plugin_name, &pargs)) {
return NULL;
}
plugin_handle = dlopen(plugin_name, RTLD_NOW | RTLD_GLOBAL);
if (!plugin_handle) {
fprintf(stderr, "%s\n", dlerror());
}
else {
plugin_init = dlsym(plugin_handle, "uwsgi_init");
if (plugin_init) {
if ((*plugin_init) (&uwsgi, pargs)) {
fprintf(stderr, "plugin initialization returned error\n");
if (dlclose(plugin_handle)) {
fprintf(stderr, "unable to unload plugin\n");
}
Py_INCREF(Py_None);
return Py_None;
}
}
plugin_request = dlsym(plugin_handle, "uwsgi_request");
if (plugin_request) {
uwsgi.shared->hooks[modifier] = plugin_request;
plugin_after_request = dlsym(plugin_handle, "uwsgi_after_request");
if (plugin_after_request) {
uwsgi.shared->after_hooks[modifier] = plugin_after_request;
}
Py_INCREF(Py_True);
return Py_True;
}
else {
fprintf(stderr, "%s\n", dlerror());
}
if (uwsgi_load_plugin(&uwsgi, modifier, plugin_name, pargs, 1)) {
Py_INCREF(Py_None);
return Py_None;
}
Py_INCREF(Py_None);
return Py_None;
Py_INCREF(Py_True);
return Py_True;
}
#ifdef UWSGI_MULTICAST
@@ -638,6 +692,22 @@ PyObject *py_uwsgi_multicast(PyObject * self, PyObject * args) {
}
#endif
PyObject *py_uwsgi_has_hook(PyObject * self, PyObject * args) {
int modifier1;
if (!PyArg_ParseTuple(args, "i:has_hook", &modifier1)) {
return NULL;
}
if (uwsgi.shared->hooks[modifier1] != unconfigured_hook) {
Py_INCREF(Py_True);
return Py_True;
}
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_uwsgi_send_message(PyObject * self, PyObject * args) {
PyObject *arg_message = NULL;
@@ -829,8 +899,25 @@ PyObject *py_uwsgi_worker_id(PyObject * self, PyObject * args) {
return PyInt_FromLong(uwsgi.mywid);
}
PyObject *py_uwsgi_logsize(PyObject * self, PyObject * args) {
return PyInt_FromLong(uwsgi.shared->logsize);
}
PyObject *py_uwsgi_mem(PyObject * self, PyObject * args) {
PyObject *ml = PyTuple_New(2);
get_memusage();
PyTuple_SetItem(ml, 0, PyLong_FromLong(uwsgi.workers[uwsgi.mywid].rss_size));
PyTuple_SetItem(ml, 1, PyLong_FromLong(uwsgi.workers[uwsgi.mywid].vsz_size));
return ml;
}
PyObject *py_uwsgi_disconnect(PyObject * self, PyObject * args) {
fprintf(stderr, "detaching uWSGI from current connection...\n");
uwsgi_log( "disconnecting worker %d (pid :%d) from session...\n", uwsgi.mywid, uwsgi.mypid);
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
@@ -841,6 +928,52 @@ PyObject *py_uwsgi_disconnect(PyObject * self, PyObject * args) {
return Py_True;
}
PyObject *py_uwsgi_grunt(PyObject * self, PyObject * args) {
pid_t grunt_pid ;
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
if (uwsgi.grunt) {
uwsgi_log( "spawning a grunt from worker %d (pid :%d)...\n", uwsgi.mywid, uwsgi.mypid);
}
else {
uwsgi_log( "grunt support is disabled !!!\n" );
goto clear;
}
grunt_pid = fork();
if (grunt_pid < 0) {
uwsgi_error("fork()");
goto clear;
}
else if (grunt_pid == 0) {
close(uwsgi.serverfd);
// create a new session
setsid();
// exit on SIGPIPE
signal(SIGPIPE, (void *) &end_me);
uwsgi.mywid = uwsgi.numproc + 1;
uwsgi.mypid = getpid();
memset(&uwsgi.workers[uwsgi.mywid], 0, sizeof(struct uwsgi_worker));
// this is pratically useless...
uwsgi.workers[uwsgi.mywid].id = uwsgi.mywid;
// this field will be overwrite after each call
uwsgi.workers[uwsgi.mywid].pid = uwsgi.mypid;
// take the gil to support threads in grunt (is this useful ?)
uwsgi.workers[uwsgi.mywid].i_have_gil = 1;
Py_INCREF(Py_True);
return Py_True;
}
// close connection on the worker
fclose(wsgi_req->async_post);
wsgi_req->fd_closed = 1 ;
clear:
Py_INCREF(Py_None);
return Py_None;
}
#ifdef UWSGI_SPOOLER
static PyMethodDef uwsgi_spooler_methods[] = {
{"send_to_spooler", py_uwsgi_send_spool, METH_VARARGS, ""},
@@ -865,10 +998,18 @@ 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, ""},
{"grunt", py_uwsgi_grunt, METH_VARARGS, ""},
{"load_plugin", py_uwsgi_load_plugin, METH_VARARGS, ""},
{"lock", py_uwsgi_lock, METH_VARARGS, ""},
{"unlock", py_uwsgi_unlock, METH_VARARGS, ""},
{"send", py_uwsgi_send, METH_VARARGS, ""},
#ifdef UWSGI_SENDFILE
{"sendfile", py_uwsgi_advanced_sendfile, METH_VARARGS, ""},
#endif
{"set_warning_message", py_uwsgi_warning, METH_VARARGS, ""},
{"mem", py_uwsgi_mem, METH_VARARGS, ""},
{"has_hook", py_uwsgi_has_hook, METH_VARARGS, ""},
{"logsize", py_uwsgi_logsize, METH_VARARGS, ""},
#ifdef UWSGI_MULTICAST
{"send_multicast_message", py_uwsgi_multicast, METH_VARARGS, ""},
#endif
@@ -900,7 +1041,7 @@ void init_uwsgi_module_spooler(PyObject * current_uwsgi_module) {
uwsgi_module_dict = PyModule_GetDict(current_uwsgi_module);
if (!uwsgi_module_dict) {
fprintf(stderr, "could not get uwsgi module __dict__\n");
uwsgi_log( "could not get uwsgi module __dict__\n");
exit(1);
}
@@ -925,7 +1066,7 @@ void init_uwsgi_module_advanced(PyObject * current_uwsgi_module) {
uwsgi_module_dict = PyModule_GetDict(current_uwsgi_module);
if (!uwsgi_module_dict) {
fprintf(stderr, "could not get uwsgi module __dict__\n");
uwsgi_log( "could not get uwsgi module __dict__\n");
exit(1);
}
@@ -942,7 +1083,7 @@ void init_uwsgi_module_sharedarea(PyObject * current_uwsgi_module) {
uwsgi_module_dict = PyModule_GetDict(current_uwsgi_module);
if (!uwsgi_module_dict) {
fprintf(stderr, "could not get uwsgi module __dict__\n");
uwsgi_log( "could not get uwsgi module __dict__\n");
exit(1);
}
+214 -40
View File
@@ -1,6 +1,7 @@
# uWSGI configuration
XML=True
INI=True
SNMP=True
SCTP=False
ERLANG=False
@@ -10,17 +11,28 @@ UDP=True
MULTICAST=True
THREADING=True
SENDFILE=True
PROFILER=True
PROFILER=False
NAGIOS=True
PROXY=True
PASTE=True
MINTERPRETERS=True
ASYNC=True
UGREEN=True
UGREEN=False
HTTP=True
EVDIS=False
LDAP=False
WSGI2=False
ROUTING=False
STACKLESS=False
#PLUGINS = ['psgi']
PLUGINS = []
USWALLOW=False
UNBIT=False
DEBUG=False
EMBED_PLUGINS=True
UWSGI_BIN_NAME = 'uwsgi'
GCC='gcc'
UWSGI_PLUGIN_DIR = '.'
# specific compilation flags
# libxml2 or expat
@@ -40,23 +52,37 @@ ERLANG_LDFLAGS = '-lerl_interface -lei'
import os
uwsgi_os = os.uname()[0]
uwsgi_cpu = os.uname()[4]
import sys
import subprocess
from distutils import sysconfig
gcc_list = ['utils', 'pyutils', 'protocol', 'socket', 'logging', 'wsgi_handlers', 'wsgi_headers', 'uwsgi_handlers', 'uwsgi']
GCC = os.environ.get('CC', sysconfig.get_config_var('CC'))
if not GCC:
GCC = 'gcc'
gcc_list = ['utils', 'pyutils', 'protocol', 'socket', 'logging', 'wsgi_handlers', 'wsgi_headers', 'uwsgi_handlers', 'plugins', 'uwsgi']
# large file support
try:
cflags = ['-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64'] + sysconfig.get_config_var('CFLAGS').split()
cflags = ['-Wall', '-Werror', '-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64'] + os.environ.get("CFLAGS", "").split()
except:
print("You need python headers to build uWSGI.")
sys.exit(1)
cflags = cflags + ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True) ]
ldflags = ['-lpthread', '-rdynamic'] + sysconfig.get_config_var('LIBS').split() + sysconfig.get_config_var('SYSLIBS').split()
ldflags = os.environ.get("LDFLAGS", "").split()
libs = ['-lpthread', '-rdynamic'] + sysconfig.get_config_var('LIBS').split() + sysconfig.get_config_var('SYSLIBS').split()
if not sysconfig.get_config_var('Py_ENABLE_SHARED'):
libs.append('-L' + sysconfig.get_config_var('LIBPL'))
if USWALLOW:
cflags = cflags + sysconfig.get_config_var('LLVM_CXXFLAGS').split()
ldflags = ldflags + sysconfig.get_config_var('LLVM_LDFLAGS').split() + sysconfig.get_config_var('LINKFORSHARED').split()
GCC = 'clang'
def depends_on(what, dep):
for d in dep:
@@ -68,9 +94,9 @@ def spcall(cmd):
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
if p.wait() == 0:
return p.stdout.read().rstrip().decode()
return p.stdout.read().rstrip().decode()
else:
return None
return None
def add_o(x):
if x == 'uwsgi':
@@ -92,12 +118,13 @@ def build_uwsgi(bin_name):
sys.exit(1)
if len(PLUGINS) > 0:
print("*** uWSGI embedding plugin ***")
print("*** uWSGI building plugins ***")
for plugin in PLUGINS:
print(plugin)
print("*** building plugin: %s ***" % plugin)
build_plugin("plugins/%s" % plugin)
print("*** uWSGI linking ***")
ldline = "%s -o %s %s %s" % (GCC, bin_name, ' '.join(map(add_o, gcc_list)), ' '.join(ldflags))
ldline = "%s -o %s %s %s %s" % (GCC, bin_name, ' '.join(ldflags), ' '.join(map(add_o, gcc_list)), ' '.join(libs))
print(ldline)
ret = os.system(ldline)
if ret != 0:
@@ -109,49 +136,128 @@ def build_uwsgi(bin_name):
print("*** uWSGI is ready, launch it with %s ***" % bin_name)
def unbit_setup():
global XML, SNMP, SCTP, ERLANG, SPOOLER
global EMBEDDED, UDP, MULTICAST, THREADING
global SENDFILE, PROFILER, NAGIOS, PROXY
global UWSGI_BIN_NAME
global XML
XML=True
XML=False
global INI
INI=False
global SNMP
SNMP=False
global SCTP
SCTP=False
global ERLANG
ERLANG=False
global SPOOLER
SPOOLER=True
global EMBEDDED
EMBEDDED=True
global UDP
UDP=False
global MULTICAST
MULTICAST=False
global THREADING
THREADING=False
global SENDFILE
SENDFILE=True
global PROFILER
PROFILER=False
global NAGIOS
NAGIOS=False
global PROXY
PROXY=False
EMBEDDED=True
SPOOLER=True
THREADING=True
SENDFILE=True
PROFILER=True
global PASTE
PASTE=False
global MINTERPRETERS
MINTERPRETERS=False
global ASYNC
ASYNC=False
global UGREEN
UGREEN=False
global HTTP
HTTP=False
global EVDIS
EVDIS=False
global WSGI2
WSGI2=False
global LDAP
LDAP=False
global ROUTING
ROUTING=False
global STACKLESS
STACKLESS=False
global PLUGINS
#PLUGINS = ['psgi']
PLUGINS = []
global USWALLOW
USWALLOW=False
global UNBIT
UNBIT=True
UWSGI_BIN_NAME='/usr/share/unbit/uwsgi26'
global DEBUG
DEBUG=False
global EMBED_PLUGINS
EMBED_PLUGINS=True
global UWSGI_BIN_NAME
UWSGI_BIN_NAME = '../bin/uwsgi'
global UWSGI_PLUGIN_DIR
UWSGI_PLUGIN_DIR = '../bin'
global PYLIB_PATH
PYLIB_PATH = '/proc/unbit/opt/python26/lib'
def parse_vars():
global UGREEN
version = sys.version_info
uver = "%d.%d" % (version[0], version[1])
ldflags.append('-lpython' + uver)
libs.append('-lpython' + uver)
if str(PYLIB_PATH) != '':
ldflags.insert(0,'-L' + PYLIB_PATH)
libs.insert(0,'-L' + PYLIB_PATH)
os.environ['LD_RUN_PATH'] = PYLIB_PATH
kvm_list = ['FreeBSD', 'OpenBSD', 'NetBSD', 'DragonFly']
if uwsgi_os == 'SunOS':
ldflags.append('-lsendfile')
ldflags.remove('-rdynamic')
libs.append('-lsendfile')
libs.remove('-rdynamic')
if uwsgi_os in kvm_list:
ldflags.append('-lkvm')
libs.append('-lkvm')
if uwsgi_os == 'OpenBSD' or uwsgi_cpu[0:3] == 'arm':
UGREEN = False
if EMBEDDED:
cflags.append('-DUWSGI_EMBEDDED')
@@ -182,11 +288,50 @@ def parse_vars():
cflags.append("-DUWSGI_NAGIOS")
gcc_list.append('nagios')
if INI:
cflags.append("-DUWSGI_INI")
gcc_list.append('ini')
if DEBUG:
cflags.append("-DUWSGI_DEBUG")
if PROXY:
depends_on("PROXY", ['ASYNC'])
cflags.append("-DUWSGI_PROXY")
gcc_list.append('proxy')
if LDAP:
cflags.append("-DUWSGI_LDAP")
gcc_list.append('ldap')
libs.append('-lldap')
if ROUTING:
depends_on("ROUTING", ['WSGI2', 'XML'])
cflags.append("-DUWSGI_ROUTING")
gcc_list.append('routing')
pcreconf = spcall("pcre-config --cflags")
if pcreconf is None:
print ("*** Unable to locate pcre-config. The uWSGI build has been interrupted. You have to install pcre.")
sys.exit(1)
else:
cflags.append(pcreconf)
pcreconf = spcall("pcre-config --libs")
if pcreconf is None:
print ("*** Unable to locate pcre-config. The uWSGI build has been interrupted. You have to install pcre.")
sys.exit(1)
else:
libs.append(pcreconf)
if HTTP:
cflags.append("-DUWSGI_HTTP")
gcc_list.append('http')
if EVDIS:
cflags.append("-DUWSGI_EVDIS")
gcc_list.append('evdis')
if UGREEN:
if uwsgi_os == 'Darwin':
cflags.append("-D_XOPEN_SOURCE")
@@ -205,6 +350,9 @@ def parse_vars():
if PROFILER:
cflags.append("-DUWSGI_PROFILER")
if PASTE:
cflags.append('-DUWSGI_PASTE')
if SENDFILE:
cflags.append("-DUWSGI_SENDFILE")
gcc_list.append('sendfile')
@@ -216,7 +364,7 @@ def parse_vars():
print("*** libxml2 headers unavailable. uWSGI build is interrupted. You have to install libxml2 development package or use libexpat or disable XML")
sys.exit(1)
else:
ldflags.append(xmlconf)
libs.append(xmlconf)
xmlconf = spcall("xml2-config --cflags")
if xmlconf is None:
print("*** libxml2 headers unavailable. uWSGI build is interrupted. You have to install libxml2 development package or use libexpat or disable XML")
@@ -227,29 +375,44 @@ def parse_vars():
gcc_list.append('xmlconf')
elif XML_IMPLEMENTATION == 'expat':
cflags.append("-DUWSGI_XML -DUWSGI_XML_EXPAT")
ldflags.append('-lexpat')
libs.append('-lexpat')
gcc_list.append('xmlconf')
if ERLANG:
depends_on("ERLANG", ['EMBEDDED'])
cflags.append("-DUWSGI_ERLANG")
ldflags.append(ERLANG_LDFLAGS)
libs.append(ERLANG_LDFLAGS)
if str(ERLANG_CFLAGS) != '':
cflags.append(ERLANG_CFLAGS)
gcc_list.append('erlang')
if UWSGI_PLUGIN_DIR is not None:
cflags.append("-DUWSGI_PLUGIN_DIR=\\\"%s\\\"" % UWSGI_PLUGIN_DIR)
if len(PLUGINS) > 0 and EMBED_PLUGINS:
cflags.append("-DUWSGI_EMBED_PLUGINS")
for plugin in PLUGINS:
cflags.append("-DUWSGI_EMBED_PLUGIN_%s" % plugin.upper())
if SCTP:
ldflags.append("-lsctp")
cflags.append("-DUWSGI_SCTP")
libs.append("-lsctp")
cflags.append("-DUWSGI_SCTP")
if SPOOLER:
depends_on("SPOOLER", ['EMBEDDED'])
cflags.append("-DUWSGI_SPOOLER")
gcc_list.append('spooler')
if WSGI2:
cflags.append("-DUWSGI_WSGI2")
if DEBUG:
cflags.append("-DUWSGI_DEBUG")
cflags.append("-g")
if UNBIT:
cflags.append("-DUWSGI_UNBIT")
cflags.append("-DUNBIT")
def build_plugin(path):
path = path.rstrip('/')
@@ -257,14 +420,23 @@ def build_plugin(path):
sys.path.insert(0, path)
import uwsgiplugin as up
cflags.append(up.CFLAGS)
ldflags.append(up.LDFLAGS)
p_cflags = cflags[:]
p_ldflags = ldflags[:]
cflags.insert(0, '-I.')
p_cflags.append(up.CFLAGS)
p_ldflags.append(up.LDFLAGS)
p_cflags.insert(0, '-I.')
plugin_base = path + '/' + up.NAME + '_plugin'
plugin_dest = UWSGI_PLUGIN_DIR + '/' + up.NAME + '_plugin'
gccline = "%s -fPIC -shared -o %s.so %s %s.c %s" % (GCC, plugin_base, ' '.join(cflags), plugin_base, ' '.join(ldflags))
shared_flag = '-shared'
if uwsgi_os == 'Darwin':
shared_flag = '-dynamiclib -undefined dynamic_lookup'
gccline = "%s -fPIC %s -o %s.so %s %s %s.c" % (GCC, shared_flag, plugin_dest, ' '.join(p_cflags), ' '.join(p_ldflags), plugin_base )
print(gccline)
ret = os.system(gccline)
@@ -272,7 +444,7 @@ def build_plugin(path):
print("*** unable to build %s plugin ***" % up.NAME)
sys.exit(1)
print("*** %s plugin built and available in %s ***" % (up.NAME, plugin_base + '.so'))
print("*** %s plugin built and available in %s ***" % (up.NAME, plugin_dest + '.so'))
@@ -289,9 +461,11 @@ if __name__ == "__main__":
sys.exit(1)
if cmd == '--cflags':
print(' '.join(cflags))
print(' '.join(cflags))
if cmd == '--ldflags':
print(' '.join(ldflags))
print(' '.join(ldflags))
if cmd == '--libs':
print(' '.join(libs))
elif cmd == '--build':
parse_vars()
build_uwsgi(UWSGI_BIN_NAME)
+79
View File
@@ -0,0 +1,79 @@
import uwsgi
import time
import sys
import os
def application(env, start_response):
print env
start_response('200 OK', [('Content-Type', 'text/html')])
yield '<h1>uWSGI %s status</h1>' % uwsgi.version
yield 'masterpid: <b>' + str(uwsgi.masterpid()) + '</b><br/>'
yield 'started on: <b>' + time.ctime(uwsgi.started_on) + '</b><br/>'
yield 'buffer size: <b>' + str(uwsgi.buffer_size) + '</b><br/>'
yield 'total_requests: <b>' + str(uwsgi.total_requests()) + '</b><br/>'
yield 'log size: <b>' + str(uwsgi.logsize()) + '</b><br/>'
yield 'workers: <b>' + str(uwsgi.numproc) + '</b><br/>'
yield "cwd: <b>%s</b><br/>" % os.getcwd()
try:
yield "mode: <b>%s</b><br/>" % uwsgi.mode
except:
pass
try:
yield "pidfile: <b>%s</b><br/>" % uwsgi.pidfile
except:
pass
yield "<h2>Hooks</h2>"
for h in range(0,255):
if uwsgi.has_hook(h):
yield "%d<br/>" % h
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();
yield '<h2>workers</h2>'
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['pid']) + '</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 "<h2>PYTHONPATH</h2>"
yield "<ul>"
for p in sys.path:
yield "<li>%s</li>" % p
yield "</ul>"
yield "<i>%s</i>" % str(os.uname())
+129 -18
View File
@@ -98,15 +98,22 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
/* Standard WSGI request */
if (!wsgi_req->uh.pktsize) {
fprintf(stderr, "Invalid WSGI request. skip.\n");
uwsgi_log( "Invalid WSGI request. skip.\n");
return -1;
}
if (uwsgi_parse_vars(uwsgi, wsgi_req)) {
fprintf(stderr,"Invalid WSGI request. skip.\n");
uwsgi_log("Invalid WSGI request. skip.\n");
return -1;
}
if (uwsgi->limit_post) {
if (wsgi_req->post_cl > uwsgi->limit_post) {
uwsgi_log("Invalid (too big) CONTENT_LENGTH. skip.\n");
return -1;
}
}
#ifdef UWSGI_THREADING
if (uwsgi->has_threads && !uwsgi->workers[uwsgi->mywid].i_have_gil) {
@@ -115,15 +122,32 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
}
#endif
if (!uwsgi->ignore_script_name) {
if (!wsgi_req->script_name)
wsgi_req->script_name = "";
if (uwsgi->vhost) {
zero = PyString_FromStringAndSize(wsgi_req->host, wsgi_req->host_len);
#ifdef PYTHREE
zero = PyString_Concat(zero, PyString_FromString("|"));
zero = PyString_Concat(zero, PyString_FromStringAndSize(wsgi_req->script_name, wsgi_req->script_name_len));
#else
PyString_Concat(&zero, PyString_FromString("|"));
PyString_Concat(&zero, PyString_FromStringAndSize(wsgi_req->script_name, wsgi_req->script_name_len));
#endif
}
else {
zero = PyString_FromStringAndSize(wsgi_req->script_name, wsgi_req->script_name_len);
}
if (wsgi_req->script_name_len > 0) {
zero = PyString_FromStringAndSize(wsgi_req->script_name, wsgi_req->script_name_len);
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;
wsgi_req->app_id = PyInt_AsLong(PyDict_GetItem(uwsgi->py_apps, zero));
}
else {
/* unavailable app for this SCRIPT_NAME */
wsgi_req->app_id = -1;
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(wsgi_req->poll.fd, "wsgi application not found");
@@ -131,9 +155,13 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
goto clear2;
}
}
}
Py_DECREF(zero);
}
}
Py_DECREF(zero);
}
else {
wsgi_req->app_id = 0;
}
if (wsgi_req->app_id == -1) {
@@ -158,13 +186,13 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
if (wsgi_req->protocol_len < 5) {
fprintf(stderr, "INVALID PROTOCOL: %.*s", wsgi_req->protocol_len, wsgi_req->protocol);
uwsgi_log( "INVALID PROTOCOL: %.*s\n", wsgi_req->protocol_len, wsgi_req->protocol);
internal_server_error(wsgi_req->poll.fd, "invalid HTTP protocol !!!");
goto clear;
}
if (strncmp(wsgi_req->protocol, "HTTP/", 5)) {
fprintf(stderr, "INVALID PROTOCOL: %.*s", wsgi_req->protocol_len, wsgi_req->protocol);
uwsgi_log( "INVALID PROTOCOL: %.*s\n", wsgi_req->protocol_len, wsgi_req->protocol);
internal_server_error(wsgi_req->poll.fd, "invalid HTTP protocol !!!");
goto clear;
}
@@ -183,7 +211,11 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
//fprintf(stderr,"%.*s: %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
/*
#ifdef UWSGI_DEBUG
uwsgi_debug("%.*s: %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
#endif
*/
pydictkey = PyString_FromStringAndSize(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
pydictvalue = PyString_FromStringAndSize(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len);
PyDict_SetItem(wsgi_req->async_environ, pydictkey, pydictvalue);
@@ -212,7 +244,41 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
// set wsgi vars
wsgi_req->async_post = fdopen(wsgi_req->poll.fd, "r");
if (uwsgi->post_buffering > 0 && wsgi_req->post_cl > uwsgi->post_buffering) {
wsgi_req->async_post = tmpfile();
if (!wsgi_req->async_post) {
uwsgi_error("tmpfile()");
goto clear;
}
size_t post_remains = wsgi_req->post_cl;
ssize_t post_chunk;
while(post_remains > 0) {
if (uwsgi->shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
inc_harakiri(uwsgi->shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
}
if (post_remains > uwsgi->post_buffering_bufsize) {
post_chunk = read(wsgi_req->poll.fd, wsgi_req->post_buffering_buf, uwsgi->post_buffering_bufsize);
}
else {
post_chunk = read(wsgi_req->poll.fd, wsgi_req->post_buffering_buf, post_remains);
}
if (post_chunk < 0) {
uwsgi_error("read()");
goto clear;
}
if (fwrite(wsgi_req->post_buffering_buf, post_chunk, 1, wsgi_req->async_post) <0) {
uwsgi_error("fwrite()");
goto clear;
}
post_remains -= post_chunk;
}
rewind(wsgi_req->async_post);
}
else {
wsgi_req->async_post = fdopen(wsgi_req->poll.fd, "r");
}
wsgi_socket = PyFile_FromFile(wsgi_req->async_post, "wsgi_input", "r", NULL);
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.input", wsgi_socket);
@@ -267,11 +333,26 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.url_scheme", zero);
Py_DECREF(zero);
wsgi_req->async_app = wi->wsgi_callable ;
PyDict_SetItemString(uwsgi->embedded_dict, "env", wsgi_req->async_environ);
#ifdef UWSGI_ROUTING
uwsgi_log("routing %d routes %d\n", uwsgi->routing, uwsgi->nroutes);
if (uwsgi->routing && uwsgi->nroutes > 0) {
check_route(uwsgi, wsgi_req);
}
#endif
// call
#ifdef UWSGI_PROFILER
if (uwsgi->enable_profiler == 1) {
PyDict_SetItem(wi->pymain_dict, PyString_FromFormat("uwsgi_environ__%d", wsgi_req->app_id), wsgi_req->async_environ);
wsgi_req->async_result = python_call(wi->wsgi_cprofile_run, wsgi_req->async_args);
wsgi_req->async_result = python_call(wi->wsgi_cprofile_run, wsgi_req->async_args, 0);
if (wsgi_req->async_result) {
wsgi_req->async_result = PyDict_GetItemString(wi->pymain_dict, "uwsgi_out");
Py_INCREF((PyObject*)wsgi_req->async_result);
@@ -283,7 +364,7 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
PyTuple_SetItem(wsgi_req->async_args, 0, wsgi_req->async_environ);
wsgi_req->async_result = python_call(wi->wsgi_callable, wsgi_req->async_args);
wsgi_req->async_result = python_call(wsgi_req->async_app, wsgi_req->async_args, uwsgi->catch_exceptions);
#ifdef UWSGI_PROFILER
}
@@ -303,6 +384,36 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
}
else if (uwsgi->catch_exceptions) {
wsgi_req->response_size += write(wsgi_req->poll.fd, wsgi_req->protocol, wsgi_req->protocol_len);
wsgi_req->response_size += write(wsgi_req->poll.fd, " 500 Internal Server Error\r\n", 28 );
wsgi_req->response_size += write(wsgi_req->poll.fd, "Content-type: text/plain\r\n\r\n", 28 );
wsgi_req->header_cnt = 1 ;
/*
sorry that is a hack to avoid the rewrite of PyErr_Print
temporarily map (using dup2) stderr to wsgi_req->poll.fd
*/
int tmp_stderr = dup(2);
if (tmp_stderr < 0) {
uwsgi_error("dup()");
goto clear;
}
// map 2 to wsgi_req
if (dup2(wsgi_req->poll.fd, 2) < 0) {
close(tmp_stderr);
uwsgi_error("dup2()");
goto clear;
}
// print the error
PyErr_Print();
// ...resume the original stderr, in case of error we are damaged forever !!!
if (dup2(tmp_stderr, 2) < 0) {
uwsgi_error("dup2()");
}
close(tmp_stderr);
}
clear:
+4 -22
View File
@@ -13,11 +13,7 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
#ifndef UNBIT
int base = 0;
#else
int base = 4;
#endif
// use writev()
@@ -27,16 +23,13 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
}
if (!PyString_Check(head)) {
fprintf(stderr, "http status must be a string !\n");
uwsgi_log( "http status must be a string !\n");
goto clear;
}
#ifndef UNBIT
if (uwsgi.shared->options[UWSGI_OPTION_CGI_MODE] == 0) {
base = 4;
#endif
if (wsgi_req->protocol_len == 0) {
wsgi_req->hvec[0].iov_base = (char *) http_protocol;
@@ -59,7 +52,6 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
wsgi_req->status = atoi(wsgi_req->hvec[2].iov_base);
wsgi_req->hvec[3].iov_base = nl;
wsgi_req->hvec[3].iov_len = NL_SIZE;
#ifndef UNBIT
}
else {
// drop http status on cgi mode
@@ -77,16 +69,6 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
wsgi_req->hvec[2].iov_base = nl;
wsgi_req->hvec[2].iov_len = NL_SIZE;
}
#endif
#ifdef UNBIT
if (wsgi_req->unbit_flags & (unsigned long long) 1) {
if (tmp_dir_fd >= 0 && tmp_filename[0] != 0 && wsgi_req->status == 200 && wsgi_req->method_len == 3 && wsgi_req->method[0] == 'G' && wsgi_req->method[1] == 'E' && wsgi_req->method[2] == 'T') {
save_to_disk = openat(tmp_dir_fd, tmp_filename, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP);
}
}
#endif
headers = PyTuple_GetItem(args, 1);
@@ -94,7 +76,7 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
goto clear;
}
if (!PyList_Check(headers)) {
fprintf(stderr, "http headers must be in a python list\n");
uwsgi_log( "http headers must be in a python list\n");
goto clear;
}
wsgi_req->header_cnt = PyList_Size(headers);
@@ -111,7 +93,7 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
goto clear;
}
if (!PyTuple_Check(head)) {
fprintf(stderr, "http header must be defined in a tuple !\n");
uwsgi_log( "http header must be defined in a tuple !\n");
goto clear;
}
h_key = PyTuple_GetItem(head, 0);
@@ -140,7 +122,7 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
#endif
wsgi_req->hvec[j + 3].iov_base = nl;
wsgi_req->hvec[j + 3].iov_len = NL_SIZE;
//fprintf(stderr, "%.*s: %.*s\n", wsgi_req->hvec[j].iov_len, (char *)wsgi_req->hvec[j].iov_base, wsgi_req->hvec[j+2].iov_len, (char *) wsgi_req->hvec[j+2].iov_base);
//uwsgi_log( "%.*s: %.*s\n", wsgi_req->hvec[j].iov_len, (char *)wsgi_req->hvec[j].iov_base, wsgi_req->hvec[j+2].iov_len, (char *) wsgi_req->hvec[j+2].iov_base);
}
+152 -23
View File
@@ -18,51 +18,115 @@ void uwsgi_xml_config(struct wsgi_request *wsgi_req, struct option *long_options
xmlChar *xml_uwsgi_mountpoint = NULL;
xmlChar *xml_uwsgi_script = NULL;
xmlChar *node_mode;
struct option *lopt, *aopt;
char *colon ;
char *xml_id ;
colon = strchr(uwsgi.xml_config, ':');
if (colon) {
colon[0] = 0 ;
colon++;
if (*colon == 0) {
uwsgi_log("invalid xml id\n");
exit(1);
}
uwsgi_log( "[uWSGI] using xml uwsgi id: %s\n", colon);
}
doc = xmlReadFile(uwsgi.xml_config, NULL, 0);
if (doc == NULL) {
fprintf(stderr, "[uWSGI] could not parse file %s.\n", uwsgi.xml_config);
uwsgi_log( "[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);
uwsgi_log( "[uWSGI] parsing config file %s\n", uwsgi.xml_config);
}
element = xmlDocGetRootElement(doc);
if (element == NULL) {
fprintf(stderr, "[uWSGI] invalid xml config file.\n");
uwsgi_log( "[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);
for (node = element->children; node; node = node->next) {
element = NULL ;
if (node->type == XML_ELEMENT_NODE) {
if (!strcmp((char *) node->name, "uwsgi")) {
xml_id = (char *) xmlGetProp(node, (const xmlChar *) "id");
if (colon && xml_id) {
if ( strcmp(colon, xml_id) ) {
continue;
}
}
element = node ;
break;
}
}
}
if (!element) {
uwsgi_log( "[uWSGI] invalid xml root element, <uwsgi> expected.\n");
exit(1);
}
}
if (long_options) {
// first check for pythonpath
// first check for options
for (node = element->children; node; node = node->next) {
if (node->type == XML_ELEMENT_NODE) {
if (!strcmp((char *) node->name, "app")) {
uwsgi.xml_round2 = 1 ;
continue;
}
#ifdef UWSGI_ROUTING
if (!strcmp((char *) node->name, "route")) {
uwsgi.xml_round2 = 1 ;
continue;
}
if (!strcmp((char *) node->name, "routing")) {
uwsgi.xml_round2 = 1 ;
continue;
}
#endif
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);
uwsgi_log( "[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);
uwsgi_log( "[uWSGI] %s option need a value. skip.\n", aopt->name);
exit(1);
}
}
node_mode = xmlGetProp(node, (const xmlChar *) "mode") ;
if (uwsgi.mode && node_mode) {
if (strcmp(uwsgi.mode, (char *) node_mode)) {
goto next;
}
}
xml_id = (char *) xmlGetProp(node, (const xmlChar *) "id") ;
if (colon && xml_id) {
if (strcmp(colon, xml_id)) {
goto next;
}
}
if (aopt->flag) {
*aopt->flag = aopt->val;
}
@@ -75,6 +139,7 @@ void uwsgi_xml_config(struct wsgi_request *wsgi_req, struct option *long_options
}
}
}
next:
lopt++;
}
}
@@ -82,14 +147,14 @@ void uwsgi_xml_config(struct wsgi_request *wsgi_req, struct option *long_options
}
else {
// ... then for wsgi apps
// ... then for apps and routing
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");
uwsgi_log( "no mountpoint defined for app. skip.\n");
continue;
}
wsgi_req->script_name = (char *) xml_uwsgi_mountpoint;
@@ -99,12 +164,12 @@ void uwsgi_xml_config(struct wsgi_request *wsgi_req, struct option *long_options
if (node2->type == XML_ELEMENT_NODE) {
if (!strcmp((char *) node2->name, "script")) {
if (!node2->children) {
fprintf(stderr, "no wsgi script defined. skip.\n");
uwsgi_log( "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");
uwsgi_log( "no wsgi script defined. skip.\n");
continue;
}
wsgi_req->wsgi_script = (char *) xml_uwsgi_script;
@@ -114,13 +179,81 @@ void uwsgi_xml_config(struct wsgi_request *wsgi_req, struct option *long_options
}
}
}
#ifdef UWSGI_ROUTING
else if (!strcmp((char *) node->name, "routing")) {
unsigned char *default_route_mountpoint = NULL;
unsigned char *default_route_callbase = NULL ;
xmlChar *tmp_val;
int default_route_modifier1 = 0;
int default_route_modifier2 = 0;
const char *errstr;
int erroff;
default_route_mountpoint = xmlGetProp(node, (const xmlChar *) "mountpoint");
default_route_callbase = xmlGetProp(node, (const xmlChar *) "base");
tmp_val = xmlGetProp(node, (const xmlChar *) "modifier1");
if (tmp_val) {
default_route_modifier1 = atoi( (char *)tmp_val);
}
tmp_val = xmlGetProp(node, (const xmlChar *) "modifier2");
if (tmp_val) {
default_route_modifier2 = atoi( (char *) tmp_val);
}
for (node2 = node->children; node2; node2 = node2->next) {
if (node2->type == XML_ELEMENT_NODE) {
if (!strcmp((char *) node2->name, "route") && uwsgi.nroutes < MAX_UWSGI_ROUTES) {
if (!node2->children) {
uwsgi_log( "no route callable defined. skip.\n");
continue;
}
uwsgi.routes[uwsgi.nroutes].mountpoint = (char *) default_route_mountpoint;
uwsgi.routes[uwsgi.nroutes].callbase = (char *) default_route_callbase;
uwsgi.routes[uwsgi.nroutes].modifier1 = default_route_modifier1;
uwsgi.routes[uwsgi.nroutes].modifier2 = default_route_modifier2;
// TODO check for action
uwsgi.routes[uwsgi.nroutes].action = NULL;
uwsgi.routes[uwsgi.nroutes].call = (char *) node2->children->content;
if (uwsgi.routes[uwsgi.nroutes].call == NULL) {
uwsgi_log( "no route callable defined. skip.\n");
continue;
}
tmp_val = xmlGetProp(node2, (const xmlChar *) "pattern");
if (!tmp_val) {
uwsgi_log( "no route pattern defined. skip.\n");
continue;
}
uwsgi.routes[uwsgi.nroutes].pattern = pcre_compile( (char *) tmp_val, 0, &errstr, &erroff, NULL);
uwsgi.routes[uwsgi.nroutes].pattern_extra = pcre_study(uwsgi.routes[uwsgi.nroutes].pattern, 0, &errstr);
pcre_fullinfo(uwsgi.routes[uwsgi.nroutes].pattern, uwsgi.routes[uwsgi.nroutes].pattern_extra, PCRE_INFO_CAPTURECOUNT, &uwsgi.routes[uwsgi.nroutes].args);
uwsgi_log("route call: %s %d\n", uwsgi.routes[uwsgi.nroutes].call, uwsgi.routes[uwsgi.nroutes].args);
uwsgi.nroutes++;
}
}
}
}
#endif
}
}
}
/* We cannot free xml resources on the first round as the string pointer must be valid for all the server lifecycle */
/* We cannot free xml resources on the first round (and with routing enabled) as the string pointer must be valid for all the server lifecycle */
#ifdef UWSGI_ROUTING
if (!long_options && !uwsgi.routing) {
#else
if (!long_options) {
#endif
xmlFreeDoc (doc);
xmlCleanupParser ();
}
@@ -145,7 +278,7 @@ void uwsgi_endElement(void *userData, const char *name) {
}
else if (current_xmlnode_has_arg) {
if (!current_xmlnode_text_len) {
fprintf(stderr,"option %s requires an argument\n", name);
uwsgi_log("option %s requires an argument\n", name);
exit(1);
}
// HACK: use the first char of closing tag for nulling string
@@ -188,9 +321,9 @@ void uwsgi_startApp(void *userData, const char *name, const char **attrs) {
if (!strcmp(name, "app")) {
current_xmlnode = 0 ;
fprintf(stderr,"%s = %s\n", attrs[0], attrs[1]);
uwsgi_log("%s = %s\n", attrs[0], attrs[1]);
if (strcmp(attrs[0], "mountpoint")) {
fprintf(stderr,"invalid attribute for app tag. must be 'mountpoint'\n");
uwsgi_log("invalid attribute for app tag. must be 'mountpoint'\n");
exit(1);
}
if (attrs[1]) {
@@ -198,15 +331,11 @@ void uwsgi_startApp(void *userData, const char *name, const char **attrs) {
wsgi_req->script_name_len = strlen(attrs[1]);
}
else {
wsgi_req->script_name = "/";
wsgi_req->script_name_len = 1;
wsgi_req->script_name = "";
wsgi_req->script_name_len = 0;
}
}
else if (!strcmp(name, "script")) {
if (!wsgi_req->script_name_len) {
fprintf(stderr,"you have not specified an app mountpoint.\n");
exit(1);
}
current_xmlnode = 1 ;
}
}
@@ -283,7 +412,7 @@ void uwsgi_xml_config(struct wsgi_request *wsgi_req, struct option *long_options
}
if (!XML_Parse(parser, xmlbuf, stat_buf.st_size, 1)) {
fprintf(stderr, "%s at line %d\n", XML_ErrorString(XML_GetErrorCode(parser)), (int) XML_GetCurrentLineNumber(parser));
uwsgi_log( "%s at line %d\n", XML_ErrorString(XML_GetErrorCode(parser)), (int) XML_GetCurrentLineNumber(parser));
exit(1);
}