Compare commits

...
123 Commits
Author SHA1 Message Date
Unbit 4a6ed633b9 added hex and base64 routing vars 2013-04-22 16:36:46 +02:00
Unbit 2ab1845547 prepare gemspec for 1.9.7 2013-04-22 15:36:13 +02:00
Unbit f4d2e1f20c added UWSGI_EMBED_PLUGINS 2013-04-22 12:37:31 +02:00
Unbit 81dca1f690 better lock-engine auto-detection 2013-04-22 12:23:59 +02:00
Unbit 2b331fd68f fixed ipcsem removal on reload 2013-04-22 12:16:39 +02:00
Unbit cc77e4dba7 ported gridfs to the new uwsgi_get_app_id function 2013-04-22 10:33:52 +02:00
Unbit 620a13a308 added toxslt transformation 2013-04-22 10:08:56 +02:00
Unbit 42d4ba09d7 refactored uwsgi_get_app_id 2013-04-22 09:43:20 +02:00
Unbit ca071fa52f removed cherokee nginx and lighttpd directories 2013-04-22 08:07:26 +02:00
Unbit d38e5dec7b added uwsgi::register_rpc to perl 2013-04-22 08:05:20 +02:00
Unbit e5db38f7c0 kqueue timer for OpenBSD, NetBSD and DragonFlyBSD 2013-04-22 09:07:19 +02:00
Unbit 68a29730c0 transformation_gzip and transformation_tofile are part of the default build profile 2013-04-22 06:57:29 +02:00
Unbit 5c33c4d341 fixed fd leak in sendfile on error 2013-04-22 06:25:50 +02:00
Unbit a1d6270089 another static gzip refactoring 2013-04-21 20:48:08 +02:00
unbit 1968175b00 Merge pull request #240 from toofishes/static-gz-length
Fix Content-Length header when serving gzipped content
2013-04-21 11:38:18 -07:00
Dan McGee cf1e2aeeba Fix Content-Length header when serving gzipped content
The refactor in a56003d8 to support the Range header broke compliance
with the HTTP spec. When we find a gzipped resource to serve up, ensure
we use the correct Content-Length of the compressed file, not the
original one.
2013-04-21 13:16:33 -05:00
Unbit 199b0b9f57 resources allocated by transformations are correctly freed 2013-04-21 10:22:33 +02:00
Unbit 87a0daa465 ported gzip and toupper to the new transformation api 2013-04-21 10:17:37 +02:00
Unbit c2af90b58f cachestore response is buffered 2013-04-21 10:09:02 +02:00
Unbit 62f01453af refactored cachestore to use transformation api 2013-04-21 10:07:48 +02:00
Unbit 375d6ee331 allows non-request plugin to register rpc functions 2013-04-21 09:43:45 +02:00
Unbit 222ca2915b symcall has been improved and added to the dfault build profile 2013-04-20 19:22:50 +02:00
Unbit 5ca848f9fe more robust subscription propagation using non blocking sockets 2013-04-20 15:17:43 +02:00
Unbit 68d878ff6b added arbiters to the Legion subsystem 2013-04-20 14:20:32 +02:00
Unbit 782a7b418a added mime route var 2013-04-20 13:56:10 +02:00
Unbit 724d7854ad allows transformation to rewrite headers 2013-04-20 13:51:48 +02:00
Unbit f8e64d17e8 added safe-fd concept and --alarm-fd 2013-04-20 13:24:36 +02:00
Unbit 3b40799000 more robust error checking for cgroups and support for writing proc files on the fly 2013-04-20 10:49:42 +02:00
Roberta Giordano 709964ca92 raise an exception with python3 if the headers are not encodable in latin1 2013-04-20 08:08:53 +02:00
Unbit d2cdedc610 maintain headers sent as the last resort even in buffered mode 2013-04-18 22:09:05 +02:00
Unbit b7d0730343 fixed another typo 2013-04-18 18:06:07 +02:00
Unbit 30b4ea7d49 added transformation_gzip 2013-04-18 18:05:01 +02:00
Unbit 546dadbd06 fixed some typo 2013-04-18 17:59:24 +02:00
Unbit 76edf902de added trasnformations 2013-04-18 17:56:13 +02:00
Unbit 068024134c added --load-file-in-cache-gzip 2013-04-17 16:08:27 +02:00
Unbit 538ab57b6e extend magic cache api to export the expires value (if available) 2013-04-16 18:56:25 +02:00
Unbit fd6d9148f3 filter more headers in proxy mode 2013-04-16 18:00:30 +02:00
Unbit f033f59755 fixed gzip caching 2013-04-16 17:51:50 +02:00
Unbit 7168c6dd69 improved caching 2013-04-16 17:46:36 +02:00
Unbit f121d41c2f added proxyhttp and proxyuwsgi 2013-04-16 17:11:32 +02:00
Unbit e56e774eac Merge branch 'master' of github.com:unbit/uwsgi 2013-04-16 10:17:29 +02:00
Unbit 6d9b0918a3 do not skip atexit hooks on end_me when run by the master 2013-04-16 10:17:11 +02:00
unbit d445418611 Merge pull request #229 from prymitive/cb_in_base
add cheaper_busyness plugin to default build profile
2013-04-16 01:12:52 -07:00
Unbit 6d15a51c9a added --skip-atexit 2013-04-16 10:12:22 +02:00
unbit 42a615efdd Merge pull request #231 from prymitive/legion_lock
add missing locks to legion_cache_fetch plugin
2013-04-15 10:32:01 -07:00
Łukasz Mierzwa 54cd1f79a6 add missing locks to legion_cache_fetch plugin 2013-04-15 19:15:54 +02:00
Unbit 8ed8f46374 fixed some minor-bug dected by cppcheck 2013-04-15 13:45:46 +02:00
Unbit dd3a2996a4 fixed leak in cache gzip 2013-04-15 13:22:26 +02:00
Unbit bf1f90a96a added the ability to store cache items in gzip 2013-04-15 12:36:27 +02:00
Unbit 2d6200231a added content_encoding to routing cache 2013-04-15 11:28:54 +02:00
Unbit 032cd23304 added --legion-mcast shortcut 2013-04-14 18:12:57 +02:00
Łukasz Mierzwa de4c0a9e1c add cheaper_busyness plugin to default build profile 2013-04-14 12:28:49 +02:00
Unbit e33f8e8920 compile the remote spooler plugin by default 2013-04-14 09:39:46 +02:00
Unbit 22615c7921 correctly support default cache in ssl session scaling 2013-04-14 08:23:48 +02:00
Unbit 9d8809c580 added the curl_cron plugin 2013-04-13 10:04:21 +02:00
Unbit 96b92c98ff refactored cron to allows better plugins integration 2013-04-13 09:22:22 +02:00
unbit 07939acecd Merge pull request #228 from prymitive/cache_last_modified
store cache last modification time if enabled, fixes #224
2013-04-13 00:08:10 -07:00
Łukasz Mierzwa 30abcb2563 store cache last modification time if enabled, fixes #224 2013-04-12 22:11:25 +02:00
Unbit 35ce8f2b8d do not spawn the excpetion thread handler if no exception handler has been loaded 2013-04-12 08:12:15 +02:00
Unbit d6453eab38 improved cache usage in corerouters 2013-04-11 20:25:18 +02:00
Unbit e0964d07ea ported router_http improvements to router_uwsgi 2013-04-11 17:59:49 +02:00
Unbit fc359f1956 better to set status to 202 for offloaded requests 2013-04-11 17:39:20 +02:00
Unbit 322261d65d Merge branch 'master' of github.com:unbit/uwsgi 2013-04-11 17:26:42 +02:00
Unbit bd1163c439 fixed websocket proxy 2013-04-11 17:24:44 +02:00
unbit e203a8c706 Merge pull request #226 from prymitive/legion_log_fixes
remove unnecessary new lines in legion logs
2013-04-11 05:54:16 -07:00
unbit 6a1ba2af74 Merge pull request #225 from prymitive/cron_interval_fix
execute cron tasks with 60 second resolution, instead of 61 seconds
2013-04-11 05:37:00 -07:00
Łukasz Mierzwa 22569e64df remove unnecessary new lines in legion logs 2013-04-11 14:33:38 +02:00
Łukasz Mierzwa dcafe41cde execute cron tasks with 60 second resolution, instead of 61 seconds 2013-04-11 14:09:49 +02:00
Unbit dd2adc08a3 fixed teajs support 2013-04-11 12:25:06 +02:00
Unbit d7534d2673 improve post_buffering management in http internal router 2013-04-11 12:20:32 +02:00
Unbit 0a59920025 honour http protocol in http internal router 2013-04-11 11:47:14 +02:00
Unbit 77602a8de4 improved websockets detection 2013-04-11 11:30:15 +02:00
Unbit 65b3fde97c added --legion-cron 2013-04-11 09:37:22 +02:00
unbit b690148452 Merge pull request #223 from prymitive/lcf_fixes
free values on old sync node list
2013-04-10 22:52:55 -07:00
Łukasz Mierzwa 4c7bc9ada6 free list value before we free list itself 2013-04-10 22:12:06 +02:00
Unbit 432651489f let's start with 1.9.7 2013-04-10 19:04:12 +02:00
unbit 82aa232a37 Merge pull request #221 from prymitive/legion_cache_plugin2
plugin for fetching cache dump from any node after joining legion
2013-04-10 09:32:41 -07:00
Unbit 19b13bf7a7 fixed offloading and more metric analysis 2013-04-10 18:21:28 +02:00
Łukasz Mierzwa f7e25d807d Merge remote branch 'upstream/master' into legion_cache_plugin2 2013-04-10 15:57:04 +02:00
unbit cf05316b95 Merge pull request #210 from prymitive/cron_refactoring
move crontab entry parsing to separate function
2013-04-10 06:40:30 -07:00
Łukasz Mierzwa 001c4386b5 move crontab entry parsing to separate function 2013-04-10 15:37:10 +02:00
Łukasz Mierzwa 572527f8cb plugin for fetching cache dump from any node after joining legion 2013-04-10 13:28:03 +02:00
Unbit b4252beda6 updated gemspec 2013-04-09 19:05:26 +02:00
Unbit d82ee16e0c completed first step of teajs integration, improved environ copy 2013-04-09 18:54:08 +02:00
unbit e4d65c07ce added support for gcc 4.8 2013-04-09 15:48:58 +02:00
Unbit 86fcb78cc3 fix for broken linkers 2013-04-09 14:51:47 +02:00
unbit 5beb422d75 Merge pull request #219 from prymitive/legion_cache_plugin
cache refactoring for better plugin friendliness
2013-04-09 05:48:49 -07:00
Łukasz Mierzwa 53679879ca cache refactoring for better plugin friendliness 2013-04-09 14:15:33 +02:00
Unbit a8ad766182 fixed matheval route var, added time route var 2013-04-09 11:09:15 +02:00
Unbit cbb2d30f79 more analysis for the metric subsystem 2013-04-09 06:38:34 +02:00
Unbit c5e00bcec6 preparing for uWSGI 1.9.6 2013-04-09 06:13:51 +02:00
Unbit 51535d374d reindented uwsgi.h 2013-04-09 06:13:28 +02:00
Unbit 1e057e6c35 the ldap support is now a plugin 2013-04-09 05:55:18 +02:00
Unbit b23e8ab862 added --socket-sndbuf and --socket-rcvbuf 2013-04-08 20:41:54 +02:00
Unbit 0f7f13dfb2 prepare for TeaJS integration 2013-04-08 19:50:01 +02:00
Unbit aa19ccda1d removed the probe subsystem 2013-04-08 17:05:12 +02:00
unbit cd0129e780 Merge pull request #218 from prymitive/legion_hooks
more legion hooks
2013-04-08 06:53:55 -07:00
Łukasz Mierzwa 506c9023e6 more legion hooks 2013-04-08 15:48:16 +02:00
Unbit d47c25ea4c added --lua-shell 2013-04-08 14:16:36 +02:00
Unbit 010651073c added rbshell 2013-04-08 13:49:23 +02:00
Unbit 76364e3799 added 'alarm' routing action 2013-04-08 11:10:18 +02:00
Unbit f9fd0a0203 added uwsgi route var 2013-04-08 10:34:45 +02:00
Unbit 8dfbde5d16 added --for-times 2013-04-08 10:20:22 +02:00
Unbit 888991f8c1 core/metrics.c 2013-04-08 09:39:57 +02:00
Unbit ece03922d6 added gridfs authentication 2013-04-06 15:09:01 +02:00
Unbit 47bb827e6e added 'lord' routing condition 2013-04-06 13:46:21 +02:00
Unbit a56003d847 added support for range header 2013-04-06 12:45:03 +02:00
Unbit 61022c398c added rpcraw 2013-04-06 08:42:55 +02:00
Unbit 00bd8cc525 improved pyshell 2013-04-06 07:44:12 +02:00
Unbit cf6a232aef added check for seek and tell in wsgi 2013-04-06 07:33:25 +02:00
Unbit 59d1a45ef0 added math route var 2013-04-05 19:26:33 +02:00
Unbit 0b5f9fcb48 added math[] route var 2013-04-05 18:39:01 +02:00
Unbit f713ffd6a1 improved mongodb dumb plugin 2013-04-05 18:17:28 +02:00
Unbit 22ba9d81d4 more generic mongodb plugin 2013-04-05 17:51:41 +02:00
Unbit 309bc98d7f added simple numeric checks for routing conditions 2013-04-05 17:48:20 +02:00
unbit 9b8646a583 Merge pull request #213 from prymitive/carbon_avg_policy
adds ability to control what values (if any) for avg_rt will be sent if ...
2013-04-05 02:18:19 -07:00
Unbit 48d1b87ab8 completed sqlite3 plugin 2013-04-05 10:37:18 +02:00
Unbit c5f849d846 added sqlite3 plugin 2013-04-05 10:35:30 +02:00
Unbit 31fbb6e4f5 prepare for moving sqlite to a dedicated plugin 2013-04-05 10:29:49 +02:00
Unbit 4d9a88e999 added setfile routing instruction and improved uwsgi_get_var 2013-04-05 07:47:32 +02:00
Unbit 252e8484a8 added chdir,setapp and sethome routing actions 2013-04-04 11:19:31 +02:00
Unbit 1b89203932 prepare for language independent home concept 2013-04-04 11:03:26 +02:00
Łukasz Mierzwa 673cb3ee21 adds ability to control what values (if any) for avg_rt will be sent if no requests were done, fixes #212 2013-04-04 00:55:02 +02:00
98 changed files with 3589 additions and 4561 deletions
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = python,gevent,psgi,lua,php,rack,jvm,jwsgi,ring,mono,transformation_toupper,coroae,v8,cgi
inherit = base
+1 -3
View File
@@ -2,10 +2,8 @@
xml = auto
yaml = true
json = auto
sqlite3 = auto
zeromq = auto
ssl = auto
ldap = auto
pcre = auto
routing = auto
debug = false
@@ -18,7 +16,7 @@ plugins =
bin_name = uwsgi
append_version =
plugin_dir = .
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http, logfile, router_cache, rawrouter, router_static, sslrouter
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http, logfile, router_cache, rawrouter, router_static, sslrouter, spooler, cheaper_busyness, symcall, transformation_tofile, transformation_gzip
as_shared_library = false
locking = auto
-2
View File
@@ -2,10 +2,8 @@
xml = true
yaml = true
json = true
sqlite3 = true
zeromq = true
ssl = true
ldap = true
pcre = true
routing = true
debug = false
-2
View File
@@ -2,10 +2,8 @@
xml = true
yaml = true
json = false
sqlite3 = false
zeromq = false
ssl = true
ldap = false
pcre = true
routing = true
debug = false
-1
View File
@@ -1 +0,0 @@
the uwsgi handler is included in the official Cherokee distribution
+139 -10
View File
@@ -11,6 +11,29 @@ void uwsgi_alarm_func_signal(struct uwsgi_alarm_instance *uai, char *msg, size_t
uwsgi_route_signal(uai->data8);
}
// simply log an alarm
void uwsgi_alarm_init_log(struct uwsgi_alarm_instance *uai) {
}
void uwsgi_alarm_func_log(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
if (msg[len-1] != '\n') {
if (uai->arg && strlen(uai->arg) > 0) {
uwsgi_log_alarm("] %s %.*s\n", uai->arg, len, msg);
}
else {
uwsgi_log_alarm("] %.*s\n", len, msg);
}
}
else {
if (uai->arg && strlen(uai->arg) > 0) {
uwsgi_log_alarm("] %s %.*s", uai->arg, len, msg);
}
else {
uwsgi_log_alarm("] %.*s", len, msg);
}
}
}
// run a command on alarm
void uwsgi_alarm_init_cmd(struct uwsgi_alarm_instance *uai) {
uai->data_ptr = uai->arg;
@@ -86,6 +109,7 @@ void uwsgi_register_embedded_alarms() {
uwsgi_register_alarm("signal", uwsgi_alarm_init_signal, uwsgi_alarm_func_signal);
uwsgi_register_alarm("cmd", uwsgi_alarm_init_cmd, uwsgi_alarm_func_cmd);
uwsgi_register_alarm("mule", uwsgi_alarm_init_mule, uwsgi_alarm_func_mule);
uwsgi_register_alarm("log", uwsgi_alarm_init_log, uwsgi_alarm_func_log);
}
static int uwsgi_alarm_add(char *name, char *plugin, char *arg) {
@@ -189,21 +213,54 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
#endif
static void uwsgi_alarm_thread_loop(struct uwsgi_thread *ut) {
// add uwsgi_alarm_fd;
struct uwsgi_alarm_fd *uafd = uwsgi.alarm_fds;
while(uafd) {
event_queue_add_fd_read(ut->queue, uafd->fd);
uafd = uafd->next;
}
char *buf = uwsgi_malloc(uwsgi.alarm_msg_size + sizeof(long));
for (;;) {
int interesting_fd = -1;
int ret = event_queue_wait(ut->queue, -1, &interesting_fd);
if (ret > 0) {
ssize_t len = read(ut->pipe[1], buf, uwsgi.alarm_msg_size + sizeof(long));
if (len > (ssize_t)(sizeof(long) + 1)) {
size_t msg_size = len - sizeof(long);
char *msg = buf + sizeof(long);
long ptr = 0;
memcpy(&ptr, buf, sizeof(long));
struct uwsgi_alarm_instance *uai = (struct uwsgi_alarm_instance *) ptr;
if (!uai)
break;
uwsgi_alarm_run(uai, msg, msg_size);
if (interesting_fd == ut->pipe[1]) {
ssize_t len = read(ut->pipe[1], buf, uwsgi.alarm_msg_size + sizeof(long));
if (len > (ssize_t)(sizeof(long) + 1)) {
size_t msg_size = len - sizeof(long);
char *msg = buf + sizeof(long);
long ptr = 0;
memcpy(&ptr, buf, sizeof(long));
struct uwsgi_alarm_instance *uai = (struct uwsgi_alarm_instance *) ptr;
if (!uai)
break;
uwsgi_alarm_run(uai, msg, msg_size);
}
}
// check for alarm_fd
else {
uafd = uwsgi.alarm_fds;
int fd_read = 0;
while(uafd) {
if (interesting_fd == uafd->fd) {
if (fd_read) goto raise;
size_t remains = uafd->buf_len;
while(remains) {
ssize_t len = read(uafd->fd, uafd->buf + (uafd->buf_len-remains), remains);
if (len <= 0) {
uwsgi_error("[uwsgi-alarm-fd]/read()");
uwsgi_log("[uwsgi-alarm-fd] i will stop monitoring fd %d\n", uafd->fd);
event_queue_del_fd(ut->queue, uafd->fd, event_queue_read());
break;
}
remains-=len;
}
fd_read = 1;
raise:
uwsgi_alarm_run(uafd->alarm, uafd->msg, uafd->msg_len);
}
uafd = uafd->next;
}
}
}
}
@@ -243,6 +300,37 @@ void uwsgi_alarms_init() {
if (!uwsgi.alarm_instances) return;
// map alarm file descriptors
usl = uwsgi.alarm_fd_list;
while(usl) {
char *space0 = strchr(usl->value, ' ');
if (!space0) {
uwsgi_log("invalid alarm-fd syntax: %s\n", usl->value);
exit(1);
}
*space0 = 0;
size_t buf_len = 1;
char *space1 = strchr(space0+1, ' ');
if (!space1) {
uwsgi_log("invalid alarm-fd syntax: %s\n", usl->value);
exit(1);
}
char *colon = strchr(space0+1, ':');
if (colon) {
buf_len = strtoul(colon+1, NULL, 10);
*colon = 0;
}
int fd = atoi(space0+1);
uwsgi_add_alarm_fd(fd, usl->value, buf_len, space1+1, strlen(space1+1));
*space0 = ' ';
*space1 = ' ';
if (colon) {
*colon = ':';
}
usl = usl->next;
}
#ifdef UWSGI_PCRE
// then map log-alarm
usl = uwsgi.alarm_logs_list;
@@ -340,3 +428,44 @@ void uwsgi_alarm_trigger(char *alarm_instance_name, char *msg, size_t len) {
uwsgi_error("[uwsgi-alarm-error] uwsgi_alarm_trigger()/writev()");
}
}
struct uwsgi_alarm_fd *uwsgi_add_alarm_fd(int fd, char *alarm, size_t buf_len, char *msg, size_t msg_len) {
struct uwsgi_alarm_fd *old_uafd = NULL, *uafd = uwsgi.alarm_fds;
struct uwsgi_alarm_instance *uai = uwsgi_alarm_get_instance(alarm);
if (!uai) {
uwsgi_log("unable to find alarm \"%s\"\n", alarm);
exit(1);
}
if (!buf_len) buf_len = 1;
while(uafd) {
// check if an equal alarm has been added
if (uafd->fd == fd && uafd->alarm == uai) {
return uafd;
}
old_uafd = uafd;
uafd = uafd->next;
}
uafd = uwsgi_calloc(sizeof(struct uwsgi_alarm_fd));
uafd->fd = fd;
uafd->buf = uwsgi_malloc(buf_len);
uafd->buf_len = buf_len;
uafd->msg = msg;
uafd->msg_len = msg_len;
uafd->alarm = uai;
if (!old_uafd) {
uwsgi.alarm_fds = uafd;
}
else {
old_uafd->next = uafd;
}
// avoid the fd to be closed
uwsgi_add_safe_fd(fd);
uwsgi_log("[uwsgi-alarm] added fd %d\n", fd);
return uafd;
}
+173 -88
View File
@@ -156,14 +156,14 @@ static void cache_send_udp_command(struct uwsgi_cache *, char *, uint16_t, char
static void cache_sync_hook(char *k, uint16_t kl, char *v, uint16_t vl, void *data) {
struct uwsgi_cache *uc = (struct uwsgi_cache *) data;
if (!uwsgi_strncmp(k, kl, "items", 5)) {
size_t num = uwsgi_str_num(v, vl);
size_t num = uwsgi_str_num(v, vl);
if (num != uc->max_items) {
uwsgi_log("[cache-sync] invalid cache size, expected %llu received %llu\n", (unsigned long long) uc->max_items, (unsigned long long) num);
exit(1);
}
}
if (!uwsgi_strncmp(k, kl, "blocksize", 9)) {
size_t num = uwsgi_str_num(v, vl);
size_t num = uwsgi_str_num(v, vl);
if (num != uc->blocksize) {
uwsgi_log("[cache-sync] invalid cache block size, expected %llu received %llu\n", (unsigned long long) uc->blocksize, (unsigned long long) num);
exit(1);
@@ -200,6 +200,40 @@ static void uwsgi_cache_load_files(struct uwsgi_cache *uc) {
next:
usl = usl->next;
}
#ifdef UWSGI_ZLIB
usl = uwsgi.load_file_in_cache_gzip;
while(usl) {
size_t len = 0;
char *value = NULL;
char *key = usl->value;
uint16_t key_len = usl->len;
char *space = strchr(usl->value, ' ');
if (space) {
// need to skip ?
if (uwsgi_strncmp(uc->name, uc->name_len, usl->value, space-usl->value)) {
goto next2;
}
key = space+1;
key_len = usl->len - ((space-usl->value)+1);
}
value = uwsgi_open_and_read(key, &len, 0, NULL);
if (value) {
struct uwsgi_buffer *gzipped = uwsgi_gzip(value, len);
if (gzipped) {
uwsgi_wlock(uc->lock);
if (!uwsgi_cache_set2(uc, key, key_len, gzipped->buf, gzipped->len, 0, 0)) {
uwsgi_log("[cache-gzip] stored \"%.*s\" in \"%s\"\n", key_len, key, uc->name);
}
uwsgi_rwunlock(uc->lock);
uwsgi_buffer_destroy(gzipped);
}
free(value);
}
next2:
usl = usl->next;
}
#endif
}
@@ -288,21 +322,7 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
(unsigned long long) ((sizeof(struct uwsgi_cache_item)+uc->keysize) * uc->max_items), (unsigned long long) (uc->blocksize * uc->max_items),
(unsigned long long) uc->blocks_bitmap_size);
struct uwsgi_string_list *usl = uc->nodes;
while(usl) {
char *port = strchr(usl->value, ':');
if (!port) {
uwsgi_log("[cache-udp-node] invalid udp address: %s\n", usl->value);
exit(1);
}
// no need to zero the memory, socket_to_in_addr will do that
struct sockaddr_in *sin = uwsgi_malloc(sizeof(struct sockaddr_in));
usl->custom = socket_to_in_addr(usl->value, port, 0, sin);
usl->custom_ptr = sin;
uwsgi_log("added udp node %s for cache \"%s\"\n", usl->value, uc->name);
usl = usl->next;
}
uwsgi_cache_setup_nodes(uc);
uc->udp_node_socket = socket(AF_INET, SOCK_DGRAM, 0);
if (uc->udp_node_socket < 0) {
@@ -311,70 +331,10 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
}
uwsgi_socket_nb(uc->udp_node_socket);
usl = uc->sync_nodes;
while(usl) {
uwsgi_log("[cache-sync] getting cache dump from %s ...\n", usl->value);
int fd = uwsgi_connect(usl->value, 0, 0);
if (fd < 0) {
uwsgi_log("[cache-sync] unable to connect to the cache server\n");
goto next;
}
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size + uc->filesize);
ub->pos = 4;
if (uwsgi_buffer_append(ub, uc->name, uc->name_len)) {
uwsgi_buffer_destroy(ub);
close(fd);
goto next;
}
if (uwsgi_buffer_set_uh(ub, 111, 6)) {
uwsgi_buffer_destroy(ub);
close(fd);
goto next;
}
if (uwsgi_write_nb(fd, ub->buf, ub->pos, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
uwsgi_buffer_destroy(ub);
uwsgi_log("[cache-sync] unable to write to the cache server\n");
close(fd);
goto next;
}
size_t rlen = ub->pos;
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
uwsgi_buffer_destroy(ub);
uwsgi_log("[cache-sync] unable to read from the cache server\n");
close(fd);
goto next;
}
uwsgi_hooked_parse(ub->buf, ub->pos, cache_sync_hook, uc);
if (uwsgi_read_nb(fd, (char *) uc->items, uc->filesize, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
uwsgi_buffer_destroy(ub);
close(fd);
uwsgi_log("[cache-sync] unable to read from the cache server\n");
goto next;
}
// reset the hashtable
memset(uc->hashtable, 0, sizeof(uint64_t) * UMAX16);
// re-fill the hashtable
uwsgi_cache_fix(uc);
uwsgi_buffer_destroy(ub);
close(fd);
break;
next:
if (!usl->next) {
exit(1);
}
uwsgi_log("[cache-sync] trying with the next sync node...\n");
usl = usl->next;
}
uwsgi_cache_sync_from_nodes(uc);
uwsgi_cache_load_files(uc);
}
static uint64_t uwsgi_cache_get_index(struct uwsgi_cache *uc, char *key, uint16_t keylen) {
@@ -456,6 +416,28 @@ char *uwsgi_cache_get2(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint6
return NULL;
}
char *uwsgi_cache_get3(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint64_t * valsize, uint64_t *expires) {
uint64_t index = uwsgi_cache_get_index(uc, key, keylen);
if (index) {
struct uwsgi_cache_item *uci = cache_item(index);
if (uci->flags & UWSGI_CACHE_FLAG_UNGETTABLE)
return NULL;
*valsize = uci->valsize;
if (expires)
*expires = uci->expires;
uci->hits++;
uc->hits++;
return uc->data + (uci->first_block * uc->blocksize);
}
uc->miss++;
return NULL;
}
int uwsgi_cache_del2(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint64_t index, uint16_t flags) {
struct uwsgi_cache_item *uci;
@@ -501,6 +483,10 @@ int uwsgi_cache_del2(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint64_
uci->expires = 0;
uc->n_items--;
if (uc->use_last_modified) {
uc->last_modified_at = uwsgi_now();
}
}
if (uc->nodes && ret == 0 && !(flags & UWSGI_CACHE_FLAG_LOCAL)) {
@@ -547,6 +533,7 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
uint8_t rollback_mode = 0;
int ret = -1;
time_t now = 0;
if (!keylen || !vallen)
return -1;
@@ -592,13 +579,13 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
uc->unused_blocks_stack_ptr++;
}
else if (rollback_mode == 2) {
uc->first_available_block--;
uc->first_available_block--;
}
goto end;
}
// mark used blocks;
uint64_t needed_blocks = cache_mark_blocks(uc, uci->first_block, vallen);
// optimize teh scan
uint64_t needed_blocks = cache_mark_blocks(uc, uci->first_block, vallen);
// optimize the scan
if (uc->blocks_bitmap_pos + (needed_blocks+1) > uc->blocks) {
uc->blocks_bitmap_pos = 0;
}
@@ -606,8 +593,10 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
uc->blocks_bitmap_pos = uci->first_block + needed_blocks + 1;
}
}
if (expires && !(flags & UWSGI_CACHE_FLAG_ABSEXPIRE))
expires += uwsgi_now();
if (expires && !(flags & UWSGI_CACHE_FLAG_ABSEXPIRE)) {
now = uwsgi_now();
expires += now;
}
uci->expires = expires;
uci->hash = uc->hash->func(key, keylen);
uci->hits = 0;
@@ -646,7 +635,8 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
else if (flags & UWSGI_CACHE_FLAG_UPDATE) {
uci = cache_item(index);
if (expires && !(flags & UWSGI_CACHE_FLAG_ABSEXPIRE)) {
expires += uwsgi_now();
now = uwsgi_now();
expires += now;
uci->expires = expires;
}
if (uc->blocks_bitmap) {
@@ -675,7 +665,11 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
uci->valsize = vallen;
ret = 0;
}
if (uc->use_last_modified) {
uc->last_modified_at = (now ? now : uwsgi_now());
}
if (uc->nodes && ret == 0 && !(flags & UWSGI_CACHE_FLAG_LOCAL)) {
cache_send_udp_command(uc, key, keylen, val, vallen, expires, 10);
}
@@ -953,6 +947,7 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
uc->nodes = uwsgi.cache_udp_node;
uc->udp_servers = uwsgi.cache_udp_server;
uc->store_sync = uwsgi.cache_store_sync;
uc->use_last_modified = (uint8_t) uwsgi.cache_use_last_modified;
if (uwsgi.cache_sync) {
uwsgi_string_new_list(&uc->sync_nodes, uwsgi.cache_sync);
@@ -972,6 +967,7 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
char *c_sync = NULL;
char *c_udp_servers = NULL;
char *c_bitmap = NULL;
char *c_use_last_modified = NULL;
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
"name", &c_name,
@@ -997,6 +993,7 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
"udpservers", &c_udp_servers,
"udpserver", &c_udp_servers,
"bitmap", &c_bitmap,
"lastmod", &c_use_last_modified,
NULL)) {
uwsgi_log("unable to parse cache definition\n");
exit(1);
@@ -1041,6 +1038,7 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
uc->use_blocks_bitmap = 1;
uc->max_item_size = uc->blocksize * uc->blocks;
}
if (c_use_last_modified) uc->use_last_modified = 1;
uc->store_sync = uwsgi.cache_store_sync;
if (c_store_sync) { uc->store_sync = uwsgi_n64(c_store_sync); }
@@ -1307,7 +1305,7 @@ static int cache_magic_send_and_manage(int fd, struct uwsgi_buffer *ub, char *st
return 0;
}
char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, char *cache) {
char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, uint64_t *expires, char *cache) {
struct uwsgi_cache_magic_context ucmc;
struct uwsgi_cache *uc = NULL;
char *cache_server = NULL;
@@ -1332,7 +1330,7 @@ char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, char *
// we have a local cache !!!
if (uc) {
uwsgi_rlock(uc->lock);
char *value = uwsgi_cache_get2(uc, key, keylen, vallen);
char *value = uwsgi_cache_get3(uc, key, keylen, vallen, expires);
if (!value) {
uwsgi_rwunlock(uc->lock);
return NULL;
@@ -1402,6 +1400,9 @@ char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, char *
ub->buf = NULL;
uwsgi_buffer_destroy(ub);
*vallen = ucmc.size;
if (expires) {
*expires = ucmc.expires;
}
return value;
}
@@ -1696,3 +1697,87 @@ int uwsgi_cache_magic_clear(char *cache) {
}
void uwsgi_cache_sync_from_nodes(struct uwsgi_cache *uc) {
struct uwsgi_string_list *usl = uc->sync_nodes;
while(usl) {
uwsgi_log("[cache-sync] getting cache dump from %s ...\n", usl->value);
int fd = uwsgi_connect(usl->value, 0, 0);
if (fd < 0) {
uwsgi_log("[cache-sync] unable to connect to the cache server\n");
goto next;
}
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size + uc->filesize);
ub->pos = 4;
if (uwsgi_buffer_append(ub, uc->name, uc->name_len)) {
uwsgi_buffer_destroy(ub);
close(fd);
goto next;
}
if (uwsgi_buffer_set_uh(ub, 111, 6)) {
uwsgi_buffer_destroy(ub);
close(fd);
goto next;
}
if (uwsgi_write_nb(fd, ub->buf, ub->pos, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
uwsgi_buffer_destroy(ub);
uwsgi_log("[cache-sync] unable to write to the cache server\n");
close(fd);
goto next;
}
size_t rlen = ub->pos;
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
uwsgi_buffer_destroy(ub);
uwsgi_log("[cache-sync] unable to read from the cache server\n");
close(fd);
goto next;
}
uwsgi_hooked_parse(ub->buf, ub->pos, cache_sync_hook, uc);
if (uwsgi_read_nb(fd, (char *) uc->items, uc->filesize, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
uwsgi_buffer_destroy(ub);
close(fd);
uwsgi_log("[cache-sync] unable to read from the cache server\n");
goto next;
}
// reset the hashtable
memset(uc->hashtable, 0, sizeof(uint64_t) * UMAX16);
// re-fill the hashtable
uwsgi_cache_fix(uc);
uwsgi_buffer_destroy(ub);
close(fd);
break;
next:
if (!usl->next) {
exit(1);
}
uwsgi_log("[cache-sync] trying with the next sync node...\n");
usl = usl->next;
}
}
void uwsgi_cache_setup_nodes(struct uwsgi_cache *uc) {
struct uwsgi_string_list *usl = uc->nodes;
while(usl) {
char *port = strchr(usl->value, ':');
if (!port) {
uwsgi_log("[cache-udp-node] invalid udp address: %s\n", usl->value);
exit(1);
}
// no need to zero the memory, socket_to_in_addr will do that
struct sockaddr_in *sin = uwsgi_malloc(sizeof(struct sockaddr_in));
usl->custom = socket_to_in_addr(usl->value, port, 0, sin);
usl->custom_ptr = sin;
uwsgi_log("added udp node %s for cache \"%s\"\n", usl->value, uc->name);
usl = usl->next;
}
}
+172
View File
@@ -0,0 +1,172 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
struct uwsgi_cron *uwsgi_cron_add(char *crontab) {
int i;
struct uwsgi_cron *old_uc, *uc = uwsgi.crons;
if (!uc) {
uc = uwsgi_malloc(sizeof(struct uwsgi_cron));
uwsgi.crons = uc;
}
else {
old_uc = uc;
while (uc->next) {
uc = uc->next;
old_uc = uc;
}
old_uc->next = uwsgi_malloc(sizeof(struct uwsgi_cron));
uc = old_uc->next;
}
memset(uc, 0, sizeof(struct uwsgi_cron));
if (sscanf(crontab, "%d %d %d %d %d %n", &uc->minute, &uc->hour, &uc->day, &uc->month, &uc->week, &i) != 5) {
uwsgi_log("invalid cron syntax\n");
exit(1);
}
uc->command = crontab + i;
return uc;
}
void uwsgi_opt_add_cron(char *opt, char *value, void *foobar) {
uwsgi_cron_add(value);
}
#ifdef UWSGI_SSL
void uwsgi_opt_add_legion_cron(char *opt, char *value, void *foobar) {
char *space = strchr(value, ' ');
if (!space) {
uwsgi_log("invalid %s syntax, must be prefixed with a legion name\n", opt);
exit(1);
}
char *legion = uwsgi_concat2n(value, space-value, "", 0);
struct uwsgi_cron *uc = uwsgi_cron_add(space+1);
uc->legion = legion;
}
#endif
int uwsgi_signal_add_cron(uint8_t sig, int minute, int hour, int day, int month, int week) {
if (!uwsgi.master_process)
return -1;
uwsgi_lock(uwsgi.cron_table_lock);
if (ushared->cron_cnt < MAX_CRONS) {
ushared->cron[ushared->cron_cnt].sig = sig;
ushared->cron[ushared->cron_cnt].minute = minute;
ushared->cron[ushared->cron_cnt].hour = hour;
ushared->cron[ushared->cron_cnt].day = day;
ushared->cron[ushared->cron_cnt].month = month;
ushared->cron[ushared->cron_cnt].week = week;
ushared->cron_cnt++;
}
else {
uwsgi_log("you can register max %d cron !!!\n", MAX_CRONS);
uwsgi_unlock(uwsgi.cron_table_lock);
return -1;
}
uwsgi_unlock(uwsgi.cron_table_lock);
return 0;
}
void uwsgi_manage_signal_cron(time_t now) {
struct tm *uwsgi_cron_delta;
int i;
uwsgi_cron_delta = localtime(&now);
if (uwsgi_cron_delta) {
// fix month
uwsgi_cron_delta->tm_mon++;
uwsgi_lock(uwsgi.cron_table_lock);
for (i = 0; i < ushared->cron_cnt; i++) {
struct uwsgi_cron *ucron = &ushared->cron[i];
int run_task = uwsgi_cron_task_needs_execution(uwsgi_cron_delta, ucron->minute, ucron->hour, ucron->day, ucron->month, ucron->week);
if (run_task == 1) {
// date match, signal it ?
if (now - ucron->last_job >= 60) {
uwsgi_route_signal(ucron->sig);
ucron->last_job = now;
}
}
}
uwsgi_unlock(uwsgi.cron_table_lock);
}
else {
uwsgi_error("localtime()");
}
}
void uwsgi_manage_command_cron(time_t now) {
struct tm *uwsgi_cron_delta;
struct uwsgi_cron *current_cron = uwsgi.crons;
uwsgi_cron_delta = localtime(&now);
if (!uwsgi_cron_delta) {
uwsgi_error("uwsgi_manage_command_cron()/localtime()");
return;
}
// fix month
uwsgi_cron_delta->tm_mon++;
while (current_cron) {
#ifdef UWSGI_SSL
// check for legion cron
if (current_cron->legion) {
if (!uwsgi_legion_i_am_the_lord(current_cron->legion)) {
current_cron = current_cron->next;
continue;
}
}
#endif
int run_task = uwsgi_cron_task_needs_execution(uwsgi_cron_delta, current_cron->minute, current_cron->hour, current_cron->day, current_cron->month, current_cron->week);
if (run_task == 1) {
// date match, run command ?
if (now - current_cron->last_job >= 60) {
//call command
if (current_cron->command) {
if (current_cron->func) {
current_cron->func(current_cron, now);
}
else {
if (uwsgi_run_command(current_cron->command, NULL, -1) >= 0) {
uwsgi_log_verbose("[uwsgi-cron] running %s\n", current_cron->command);
}
}
}
current_cron->last_job = now;
}
}
current_cron = current_cron->next;
}
}
+3 -3
View File
@@ -322,7 +322,7 @@ void uwsgi_manage_exception(struct wsgi_request *wsgi_req,int catch) {
if (do_exit) goto check_catch;
if (wsgi_req && uwsgi.exception_handlers_instance) {
if (uwsgi.exception_handlers_instance) {
struct uwsgi_buffer *ehi = uwsgi_exception_handler_object(wsgi_req);
if (ehi) {
uwsgi_exception_run_handlers(ehi);
@@ -442,7 +442,7 @@ static void uwsgi_exception_handler_thread_loop(struct uwsgi_thread *ut) {
int interesting_fd = -1;
int ret = event_queue_wait(ut->queue, -1, &interesting_fd);
if (ret > 0) {
ssize_t len = read(ut->pipe[1], buf, uwsgi.alarm_msg_size + sizeof(long));
ssize_t len = read(ut->pipe[1], buf, uwsgi.exception_handler_msg_size + sizeof(long));
if (len > (ssize_t)(sizeof(long) + 1)) {
size_t msg_size = len - sizeof(long);
char *msg = buf + sizeof(long);
@@ -488,7 +488,7 @@ void uwsgi_exception_setup_handlers() {
}
void uwsgi_exceptions_handler_thread_start() {
if (!uwsgi.exception_handlers_instance) return;
// start the exception_handler_thread
uwsgi.exception_handler_thread = uwsgi_thread_new(uwsgi_exception_handler_thread_loop);
if (!uwsgi.exception_handler_thread) {
+7
View File
@@ -28,10 +28,17 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop) (int, void *), v
ug->fullname = fullname;
ug->data = data;
#if defined(SOCK_SEQPACKET) && defined(__linux__)
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, ug->internal_subscription_pipe)) {
#else
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, ug->internal_subscription_pipe)) {
#endif
uwsgi_error("socketpair()");
}
uwsgi_socket_nb(ug->internal_subscription_pipe[0]);
uwsgi_socket_nb(ug->internal_subscription_pipe[1]);
if (!uwsgi.master_process)
gateway_respawn(ushared->gateways_cnt);
+75 -3
View File
@@ -955,6 +955,8 @@ readok2:
int uwsgi_proxy_nb(struct wsgi_request *wsgi_req, char *addr, struct uwsgi_buffer *ub, size_t remains, int timeout) {
struct uwsgi_buffer *headers = NULL;
int fd = uwsgi_connect(addr, 0, 1);
if (fd < 0) {
return -1;
@@ -988,21 +990,91 @@ int uwsgi_proxy_nb(struct wsgi_request *wsgi_req, char *addr, struct uwsgi_buffe
}
// read the response
headers = uwsgi_buffer_new(8192);
// max 64k headers
ub->limit = UMAX16;
for(;;) {
char buf[8192];
ssize_t rlen = uwsgi_read_true_nb(fd, buf, 8192, timeout);
if (rlen > 0) {
if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) {
break;
}
if (headers) {
if (uwsgi_buffer_append(headers, buf, rlen)) {
goto end;
}
// check if we have a full HTTP response
if (uwsgi_is_full_http(headers)) {
int ret = uwsgi_blob_to_response(wsgi_req, headers->buf, headers->pos);
if (ret) continue;
uwsgi_buffer_destroy(headers);
headers = NULL;
}
}
else {
if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) {
break;
}
}
continue;
}
break;
}
if (headers) uwsgi_buffer_destroy(headers);
close(fd);
return 0;
end:
if (headers) uwsgi_buffer_destroy(headers);
close(fd);
return -1;
}
void uwsgi_file_write_do(struct uwsgi_string_list *usl) {
struct uwsgi_string_list *fl = usl;
while(fl) {
char *equal = strchr(fl->value, '=');
if (equal) {
*equal = 0;
FILE *f = fopen(fl->value, "w");
if (!f) {
uwsgi_error_open("uwsgi_file_write_do()");
exit(1);
}
uwsgi_log("writing \"%s\" to \"%s\" ...\n", equal+1, fl->value);
if (fprintf(f, "%s\n", equal+1) <= 0 || ferror(f) || fclose(f)) {
uwsgi_error("uwsgi_file_write_do()");
exit(1);
}
}
else {
uwsgi_log("unable to write empty value for \"%s\"\n", fl->value);
exit(1);
}
*equal = '=';
fl = fl->next;
}
}
int uwsgi_fd_is_safe(int fd) {
int i;
for(i=0;i<uwsgi.safe_fds_cnt;i++) {
if (uwsgi.safe_fds[i] == fd) {
return 1;
}
}
return 0;
}
void uwsgi_add_safe_fd(int fd) {
// check if the fd is already safe
if (uwsgi_fd_is_safe(fd)) return;
size_t len = sizeof(int) * (uwsgi.safe_fds_cnt+1);
int *tmp = realloc(uwsgi.safe_fds, len);
if (!tmp) {
uwsgi_error("uwsgi_add_safe_fd()/realloc()");
exit(1);
}
uwsgi.safe_fds = tmp;
uwsgi.safe_fds[uwsgi.safe_fds_cnt] = fd;
uwsgi.safe_fds_cnt++;
}
+72 -10
View File
@@ -206,10 +206,19 @@ static void legions_check_nodes() {
if (now - node->last_seen > uwsgi.legion_tolerance) {
struct uwsgi_legion_node *tmp_node = node;
node = node->next;
uwsgi_log("[uwsgi-legion] node: %.*s valor: %llu uuid: %.*s left Legion %s\n", tmp_node->name_len, tmp_node->name, tmp_node->valor, 36, tmp_node->uuid, legion->legion);
uwsgi_log("[uwsgi-legion] %s: %.*s valor: %llu uuid: %.*s left Legion %s\n", tmp_node->valor > 0 ? "node" : "arbiter", tmp_node->name_len, tmp_node->name, tmp_node->valor, 36, tmp_node->uuid, legion->legion);
uwsgi_wlock(legion->lock);
uwsgi_legion_remove_node(legion, tmp_node);
uwsgi_rwunlock(legion->lock);
// trigger node_left hooks
struct uwsgi_string_list *usl = legion->node_left_hooks;
while (usl) {
int ret = uwsgi_legion_action_call("node_left", legion, usl);
if (ret) {
uwsgi_log("[uwsgi-legion] ERROR, node_left hook returned: %d\n", ret);
}
usl = usl->next;
}
continue;
}
node = node->next;
@@ -223,12 +232,12 @@ struct uwsgi_legion_node *uwsgi_legion_get_lord(struct uwsgi_legion *);
static void legions_report_quorum(struct uwsgi_legion *ul, uint64_t best_valor, char *best_uuid, int votes) {
struct uwsgi_legion_node *nodes = ul->nodes_head;
uwsgi_log("\n[uwsgi-legion] --- WE HAVE QUORUM FOR LEGION %s !!! (valor: %llu uuid: %.*s checksum: %llu votes: %d) ---\n", ul->legion, best_valor, 36, best_uuid, ul->checksum, votes);
uwsgi_log("[uwsgi-legion] --- WE HAVE QUORUM FOR LEGION %s !!! (valor: %llu uuid: %.*s checksum: %llu votes: %d) ---\n", ul->legion, best_valor, 36, best_uuid, ul->checksum, votes);
while (nodes) {
uwsgi_log("[uwsgi-legion-node] node: %.*s valor: %llu uuid: %.*s last_seen: %d vote_valor: %llu vote_uuid: %.*s\n", nodes->name_len, nodes->name, nodes->valor, 36, nodes->uuid, nodes->last_seen, nodes->lord_valor, 36, nodes->lord_uuid);
uwsgi_log("[uwsgi-legion-node] %s: %.*s valor: %llu uuid: %.*s last_seen: %d vote_valor: %llu vote_uuid: %.*s\n", nodes->valor > 0 ? "node" : "arbiter", nodes->name_len, nodes->name, nodes->valor, 36, nodes->uuid, nodes->last_seen, nodes->lord_valor, 36, nodes->lord_uuid);
nodes = nodes->next;
}
uwsgi_log("[uwsgi-legion] --- END OF QUORUM REPORT ---\n\n");
uwsgi_log("[uwsgi-legion] --- END OF QUORUM REPORT ---\n");
}
uint64_t uwsgi_legion_checksum(struct uwsgi_legion *ul) {
@@ -264,12 +273,17 @@ static void legions_check_nodes_step2() {
best_valor = node->valor;
memcpy(best_uuid, node->uuid, 36);
}
else {
// go on if i am not an arbiter
else if (ul->valor > 0) {
// no potential Lord is available, i will propose myself
best_valor = ul->valor;
memcpy(best_uuid, ul->uuid, 36);
i_am_the_best = 1;
}
else {
// empty lord
memset(best_uuid, 0, 36);
}
// calculate the checksum
uint64_t new_checksum = uwsgi_legion_checksum(ul);
@@ -348,9 +362,9 @@ static void legions_check_nodes_step2() {
if (ul->i_am_the_lord) {
uwsgi_log("[uwsgi-legion] a new Lord (valor: %llu uuid: %.*s) raised for Legion %s...\n", ul->lord_valor, 36, ul->lord_uuid, ul->legion);
if (ul->lord_scroll_len > 0) {
uwsgi_log("*********** The New Lord Scroll ***********\n\n");
uwsgi_log("*********** The New Lord Scroll ***********\n");
uwsgi_log("%.*s\n", ul->lord_scroll_len, ul->lord_scroll);
uwsgi_log("\n*********** End of the New Lord Scroll ***********\n\n");
uwsgi_log("*********** End of the New Lord Scroll ***********\n");
}
// no more lord, trigger unlord hooks
struct uwsgi_string_list *usl = ul->unlord_hooks;
@@ -367,6 +381,20 @@ static void legions_check_nodes_step2() {
}
else if (votes > 0 && votes < ul->quorum && (uwsgi_now() - ul->last_warning >= 60)) {
uwsgi_log("[uwsgi-legion] no quorum: only %d vote(s) for Legion %s, %d needed to elect a Lord\n", votes, ul->legion, ul->quorum);
// no more quorum, leave the Lord state
if (ul->i_am_the_lord) {
uwsgi_log("[uwsgi-legion] i cannot be The Lord of The Legion %s without a quorum ...\n", ul->legion);
// no more lord, trigger unlord hooks
struct uwsgi_string_list *usl = ul->unlord_hooks;
while (usl) {
int ret = uwsgi_legion_action_call("unlord", ul, usl);
if (ret) {
uwsgi_log("[uwsgi-legion] ERROR, unlord hook returned: %d\n", ret);
}
usl = usl->next;
}
ul->i_am_the_lord = 0;
}
ul->last_warning = uwsgi_now();
}
@@ -386,6 +414,8 @@ struct uwsgi_legion_node *uwsgi_legion_get_lord(struct uwsgi_legion *ul) {
struct uwsgi_legion_node *nodes = ul->nodes_head;
while (nodes) {
// skip arbiters
if (nodes->valor == 0) goto next;
if (nodes->valor > best_valor) {
best_node = nodes;
best_valor = nodes->valor;
@@ -398,11 +428,12 @@ struct uwsgi_legion_node *uwsgi_legion_get_lord(struct uwsgi_legion *ul) {
memcpy(best_uuid, nodes->uuid, 36);
}
}
next:
nodes = nodes->next;
}
// first round ?
if (ul->lord_valor == 0) {
// first round ? (skip first round if arbiter)
if (ul->valor > 0 && ul->lord_valor == 0) {
ul->changed = 1;
}
else if (best_valor != ul->lord_valor) {
@@ -569,7 +600,16 @@ static void *legion_loop(void *foobar) {
// we are still locked (and safe), let's rebuild the scrolls list
legion_rebuild_scrolls(ul);
uwsgi_rwunlock(ul->lock);
uwsgi_log("[uwsgi-legion] node: %.*s valor: %llu uuid: %.*s joined Legion %s\n", node->name_len, node->name, node->valor, 36, node->uuid, ul->legion);
uwsgi_log("[uwsgi-legion] %s: %.*s valor: %llu uuid: %.*s joined Legion %s\n", node->valor > 0 ? "node" : "arbiter", node->name_len, node->name, node->valor, 36, node->uuid, ul->legion);
// trigger node_joined hooks
struct uwsgi_string_list *usl = ul->node_joined_hooks;
while (usl) {
int ret = uwsgi_legion_action_call("node_joined", ul, usl);
if (ret) {
uwsgi_log("[uwsgi-legion] ERROR, node_joined hook returned: %d\n", ret);
}
usl = usl->next;
}
}
node->last_seen = uwsgi_now();
@@ -757,6 +797,21 @@ err:
return -1;
}
void uwsgi_opt_legion_mcast(char *opt, char *value, void *foobar) {
uwsgi_opt_legion(opt, value, foobar);
char *legion = uwsgi_str(value);
char *space = strchr(legion, ' ');
// over engineering
if (!space) exit(1);
*space = 0;
struct uwsgi_legion *ul = uwsgi_legion_get_by_name(legion);
if (!ul) {
uwsgi_log("unknown legion: %s\n", legion);
exit(1);
}
uwsgi_legion_register_node(ul, uwsgi_str(ul->addr));
}
void uwsgi_opt_legion_node(char *opt, char *value, void *foobar) {
char *legion = uwsgi_str(value);
@@ -882,6 +937,13 @@ void uwsgi_legion_register_hook(struct uwsgi_legion *ul, char *event, char *acti
else if (!strcmp(event, "join")) {
usl = uwsgi_string_new_list(&ul->join_hooks, action);
}
else if (!strcmp(event, "node-joined")) {
usl = uwsgi_string_new_list(&ul->node_joined_hooks, action);
}
else if (!strcmp(event, "node-left")) {
usl = uwsgi_string_new_list(&ul->node_left_hooks, action);
}
else {
uwsgi_log("[uwsgi-legion] invalid event: %s\n", event);
exit(1);
-5
View File
@@ -474,8 +474,6 @@ void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
#define UWSGI_LOCK_ENGINE_NAME "ipcsem"
#define UWSGI_IPCSEM_ATEXIT 1
#endif
struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
@@ -679,9 +677,6 @@ ready:
// timer table lock
uwsgi.timer_table_lock = uwsgi_lock_init("timer");
// probe table lock
uwsgi.probe_table_lock = uwsgi_lock_init("probe");
// rb_timer table lock
uwsgi.rb_timer_table_lock = uwsgi_lock_init("rbtimer");
-16
View File
@@ -638,22 +638,6 @@ int master_loop(char **argv, char **environ) {
uwsgi_manage_command_cron(uwsgi_now());
}
// check for probes
if (ushared->probes_cnt > 0) {
uwsgi_lock(uwsgi.probe_table_lock);
for (i = 0; i < ushared->probes_cnt; i++) {
if (interesting_fd == -1) {
// increment cycles
ushared->probes[i].cycles++;
}
if (ushared->probes[i].func(interesting_fd, &ushared->probes[i])) {
uwsgi_route_signal(ushared->probes[i].sig);
}
}
uwsgi_unlock(uwsgi.probe_table_lock);
}
// some event returned
if (rlen > 0) {
// if the following function returns -1, a new worker has just spawned
+69 -173
View File
@@ -351,6 +351,9 @@ void uwsgi_reload(char **argv) {
/* check fd table (a module can obviosly open some fd on initialization...) */
uwsgi_log("closing all non-uwsgi socket fds > 2 (max_fd = %d)...\n", (int) uwsgi.max_fd);
for (i = 3; i < (int) uwsgi.max_fd; i++) {
if (uwsgi_fd_is_safe(i)) continue;
int found = 0;
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
@@ -413,6 +416,13 @@ void uwsgi_reload(char **argv) {
#endif
}
#ifndef UWSGI_IPCSEM_ATEXIT
// free ipc semaphores if in use
if (!strcmp(uwsgi.lock_engine, "ipcsem")) {
uwsgi_ipcsem_clear();
}
#endif
uwsgi_log("running %s\n", uwsgi.binary_path);
uwsgi_flush_logs();
argv[0] = uwsgi.binary_path;
@@ -630,178 +640,6 @@ int uwsgi_respawn_worker(int wid) {
return 0;
}
void uwsgi_manage_signal_cron(time_t now) {
struct tm *uwsgi_cron_delta;
int i;
uwsgi_cron_delta = localtime(&now);
if (uwsgi_cron_delta) {
// fix month
uwsgi_cron_delta->tm_mon++;
uwsgi_lock(uwsgi.cron_table_lock);
for (i = 0; i < ushared->cron_cnt; i++) {
struct uwsgi_cron *ucron = &ushared->cron[i];
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
uc_minute = ucron->minute;
uc_hour = ucron->hour;
uc_day = ucron->day;
uc_month = ucron->month;
uc_week = ucron->week;
// negative values as interval -1 = * , -5 = */5
if (ucron->minute < 0) {
if ((uwsgi_cron_delta->tm_min % abs(ucron->minute)) == 0) {
uc_minute = uwsgi_cron_delta->tm_min;
}
}
if (ucron->hour < 0) {
if ((uwsgi_cron_delta->tm_hour % abs(ucron->hour)) == 0) {
uc_hour = uwsgi_cron_delta->tm_hour;
}
}
if (ucron->month < 0) {
if ((uwsgi_cron_delta->tm_mon % abs(ucron->month)) == 0) {
uc_month = uwsgi_cron_delta->tm_mon;
}
}
if (ucron->day < 0) {
if ((uwsgi_cron_delta->tm_mday % abs(ucron->day)) == 0) {
uc_day = uwsgi_cron_delta->tm_mday;
}
}
if (ucron->week < 0) {
if ((uwsgi_cron_delta->tm_wday % abs(ucron->week)) == 0) {
uc_week = uwsgi_cron_delta->tm_wday;
}
}
int run_task = 0;
// mday and wday are ORed
if (ucron->day >= 0 && ucron->week >= 0) {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
run_task = 1;
}
}
else {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
run_task = 1;
}
}
if (run_task == 1) {
// date match, signal it ?
if (now - ucron->last_job > 60) {
uwsgi_route_signal(ucron->sig);
ucron->last_job = now;
}
}
}
uwsgi_unlock(uwsgi.cron_table_lock);
}
else {
uwsgi_error("localtime()");
}
}
void uwsgi_manage_command_cron(time_t now) {
struct tm *uwsgi_cron_delta;
struct uwsgi_cron *current_cron = uwsgi.crons;
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
uwsgi_cron_delta = localtime(&now);
if (!uwsgi_cron_delta) {
uwsgi_error("localtime()");
return;
}
// fix month
uwsgi_cron_delta->tm_mon++;
while (current_cron) {
uc_minute = current_cron->minute;
uc_hour = current_cron->hour;
uc_day = current_cron->day;
uc_month = current_cron->month;
uc_week = current_cron->week;
// negative values as interval -1 = * , -5 = */5
if (current_cron->minute < 0) {
if ((uwsgi_cron_delta->tm_min % abs(current_cron->minute)) == 0) {
uc_minute = uwsgi_cron_delta->tm_min;
}
}
if (current_cron->hour < 0) {
if ((uwsgi_cron_delta->tm_hour % abs(current_cron->hour)) == 0) {
uc_hour = uwsgi_cron_delta->tm_hour;
}
}
if (current_cron->month < 0) {
if ((uwsgi_cron_delta->tm_mon % abs(current_cron->month)) == 0) {
uc_month = uwsgi_cron_delta->tm_mon;
}
}
if (current_cron->day < 0) {
if ((uwsgi_cron_delta->tm_mday % abs(current_cron->day)) == 0) {
uc_day = uwsgi_cron_delta->tm_mday;
}
}
if (current_cron->week < 0) {
if ((uwsgi_cron_delta->tm_wday % abs(current_cron->week)) == 0) {
uc_week = uwsgi_cron_delta->tm_wday;
}
}
int run_task = 0;
// mday and wday are ORed
if (current_cron->day >= 0 && current_cron->week >= 0) {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
run_task = 1;
}
}
else {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
run_task = 1;
}
}
if (run_task == 1) {
// date match, run command ?
if (now - current_cron->last_job > 60) {
//call command
if (current_cron->command) {
if (uwsgi_run_command(current_cron->command, NULL, -1) >= 0) {
uwsgi_log_verbose("[uWSGI-cron] running %s\n", current_cron->command);
}
}
current_cron->last_job = now;
}
}
current_cron = current_cron->next;
}
}
struct uwsgi_stats *uwsgi_master_generate_stats() {
int i;
@@ -940,7 +778,10 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
if (uwsgi_stats_keylong_comma(us, "miss", (unsigned long long) uc->miss))
goto end;
if (uwsgi_stats_keylong(us, "full", (unsigned long long) uc->full))
if (uwsgi_stats_keylong_comma(us, "full", (unsigned long long) uc->full))
goto end;
if (uwsgi_stats_keylong(us, "last_modified_at", (unsigned long long) uc->last_modified_at))
goto end;
if (uwsgi_stats_object_close(us))
@@ -1485,3 +1326,58 @@ void uwsgi_master_fix_request_counters() {
uwsgi.workers[0].requests = total_counter;
}
int uwsgi_cron_task_needs_execution(struct tm *uwsgi_cron_delta, int minute, int hour, int day, int month, int week) {
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
uc_minute = minute;
uc_hour = hour;
uc_day = day;
uc_month = month;
uc_week = week;
// negative values as interval -1 = * , -5 = */5
if (minute < 0) {
if ((uwsgi_cron_delta->tm_min % abs(minute)) == 0) {
uc_minute = uwsgi_cron_delta->tm_min;
}
}
if (hour < 0) {
if ((uwsgi_cron_delta->tm_hour % abs(hour)) == 0) {
uc_hour = uwsgi_cron_delta->tm_hour;
}
}
if (month < 0) {
if ((uwsgi_cron_delta->tm_mon % abs(month)) == 0) {
uc_month = uwsgi_cron_delta->tm_mon;
}
}
if (day < 0) {
if ((uwsgi_cron_delta->tm_mday % abs(day)) == 0) {
uc_day = uwsgi_cron_delta->tm_mday;
}
}
if (week < 0) {
if ((uwsgi_cron_delta->tm_wday % abs(week)) == 0) {
uc_week = uwsgi_cron_delta->tm_wday;
}
}
int run_task = 0;
// mday and wday are ORed
if (day >= 0 && week >= 0) {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
run_task = 1;
}
}
else {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
run_task = 1;
}
}
return run_task;
}
+138
View File
@@ -0,0 +1,138 @@
/*
uWSGI metrics subsystem
a metric is a node in a tree reachable via a numeric id (OID, in SNMP way) or a simple string:
uwsgi.worker.1.requests
uwsgi.custom.foo.bar
the oid representation:
1.3.6.1.4.1.35156.17 = iso.org.dod.internet.private.enterprise.unbit.uwsgi
1.3.6.1.4.1.35156.17.3.1.1 = iso.org.dod.internet.private.enterprise.unbit.uwsgi.worker.1.requests
1.3.6.1.4.1.35156.17.3.1.1 = iso.org.dod.internet.private.enterprise.unbit.uwsgi.worker.1.requests
1.3.6.1.4.1.35156.17.3.1.2.1.1 = iso.org.dod.internet.private.enterprise.unbit.uwsgi.worker.1.core.1.requests
1.3.6.1.4.1.35156.17.4.1 = iso.org.dod.internet.private.enterprise.unbit.uwsgi.system.load_avg
...
each metric is a collected value with a specific frequency (a frequency of zero means the value is re-computed every time)
metrics are meant for numeric values signed 64 bit, but they can be exposed as:
gauge
counter
absolute
both 32 and 64bit, both signed and unsigned
metrics are managed by a dedicated thread (in the master) holding a linked list of all the items. For few metrics it is a good (read: simple) approach,
but you can cache lookups in a uWSGI cache for really big list.
struct uwsgi_metric *um = uwsgi_register_metric("worker.1.requests", "3.1.1", UWSGI_METRIC_COUNTER, UWSGI_METRIC_PTR, &uwsgi.workers[1].requests, 0, NULL);
prototype: struct uwsgi_metric *uwsgi_register_metric(char *name, char *oid, uint8_t value_type, uint8_t collect_way, void *ptr, uint32_t freq, void *custom);
value_type = UWSGI_METRIC_COUNTER/UWSGI_METRIC_GAUGE/UWSGI_METRIC_ABSOLUTE
collect_way = UWSGI_METRIC_PTR -> get from a pointer / UWSGI_METRIC_FUNC -> get from a func with the prototype int64_t func(struct uwsgi_metric *); / UWSGI_METRIC_FILE -> get the value from a file, ptr is the filename
when freq is zero the value is recomputed whenever requested, otherwise the metrics thread compute it every time the frequency is elapsed and caches it
For some metric (or all ?) you may want to hold a value even after a server reload. For such a reason you can specify a directory on wich the server (on startup/restart) will look for
a file named like the metric and will read the initial value from it. It may look an old-fashioned and quite inefficient way, but it is the most versatile for a sysadmin (allowing him/her
to even modify the values manually)
When registering a metric with the same name of an already registered one, the new one will overwrite the previous one. This allows plugins writer to override default behaviours
Applications are allowed to update metrics (but they cannot register new ones), with simple api funcs:
uwsgi.metric_set("worker.1.requests", N)
uwsgi.metric_inc("worker.1.requests", N=1)
uwsgi.metric_dec("worker.1.requests", N=1)
uwsgi.metric_mul("worker.1.requests", N=1)
uwsgi.metric_div("worker.1.requests", N=1)
and obviously they can get values:
uwsgi.metric_get("worker.1.requests", no_cache|force=False)
if the second parameter is True, the value is recomputed (but if it is a metric with a cache, the cache value will not be updated accordingly, this is the job of the metric thread)
Updating metrics from your app MUST BE ATOMIC, for such a reason a uWSGI rwlock is initialized on startup and used for each operation (simple reading from a metric does not require locking)
Metrics can be updated from the internal routing subsystem too:
route-if = equal:${REQUEST_URI};/foobar metricinc:foobar.test 2
and can be accessed as ${metric[foobar.test]}
The stats server exports the metrics list in the "metrics" attribute (obviously some info could be redundant)
*/
struct uwsgi_metric {
char *name;
char *oid;
// pre-computed snmp representation
char *asn;
size_t asn_size;
// ABSOLUTE/COUNTER/GAUGE
uint8_t type;
// MANUAL/PTR/FUNC/FILE
uint8_t collect_way
// this could be taken from a file storage and must laways be added to value when reporting (default 0)
int64_t initial_value;
// the value of the metric (point to a shared memory area)
*int64_t value;
// a custom blob you can attach to a metric
void *custom;
// the collection frequency
uint32_t freq;
time_t last_update;
// run this function to collect the value
int64_t (*collector)(struct uwsgi_metric *);
// take the value from this pointer to a 64bit value
int64_t *ptr;
// get the initial value from this file, and store each update in it
char *filename;
struct uwsgi_metric *next;
};
struct uwsgi_metric *uwsgi_register_metric(char *name, char *oid, uint8_t value_type, uint8_t collect_way, void *ptr, uint32_t freq, void *custom) {
struct uwsgi_metric *old_metric=NULL,*metric=uwsgi.metric;
while(metric) {
metric = metric->next;
}
}
void uwsgi_metric_loop() {
// every second scan the whole metrics tree
time_t now = uwsgi_now();
}
int64_t uwsgi_metric_get(char *name, char *oid) {
struct uwsgi_metric *um = NULL;
if (name) {
um = uwsgi_metric_find_by_name(name);
}
else if (oid) {
um = uwsgi_metric_find_by_oid(oid);
}
if (!um) return 0;
//
switch(um->collect_way) {
case UWSGI_METRIC_MANUAL:
return um->initial_value+*um->value;
case UWSGI_METRIC_PTR:
return um->initial_value+*um->ptr;
case UWSGI_METRIC_FUNC:
case UWSGI_METRIC_FILE:
}
}
+1 -1
View File
@@ -72,7 +72,7 @@ int u_offload_transfer_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offlo
return -1;
}
uor->fd = uwsgi_connect(uor->ubuf->buf, 0, 1);
uor->fd = uwsgi_connect(uor->name, 0, 1);
if (uor->fd < 0) {
uwsgi_error("u_offload_transfer_prepare()/connect()");
return -1;
+99 -6
View File
@@ -2,7 +2,7 @@
extern struct uwsgi_server uwsgi;
// this is line uwsgi_str_num but with security checks
// this is like uwsgi_str_num but with security checks
static size_t get_content_length(char *buf, uint16_t size) {
int i;
size_t val = 0;
@@ -80,7 +80,7 @@ ssize_t send_udp_message(uint8_t modifier1, uint8_t modifier2, char *host, char
ret = sendto(fd, (char *) uh, message_size + 4, 0, (struct sockaddr *) &un_addr, sizeof(un_addr));
}
if (ret < 0) {
uwsgi_error("sendto()");
uwsgi_error("send_udp_message()/sendto()");
}
close(fd);
@@ -303,8 +303,41 @@ static int uwsgi_proto_check_9(struct wsgi_request *wsgi_req, char *key, char *b
return 0;
}
static void uwsgi_parse_http_range(char *buf, uint16_t len, size_t *from, size_t *to) {
*from = 0;
*to = 0;
uint16_t rlen = 0;
uint16_t i;
for(i=0;i<len;i++) {
if (buf[i] == ',') break;
rlen++;
}
// bytes=X-
if (rlen < 8) return;
char *equal = memchr(buf, '=', rlen);
if (!equal) return;
if (equal-buf != 5) return;
if (memcmp(buf, "bytes", 5)) return;
char *range = equal+1;
rlen -= 6;
char *dash = memchr(range, '-', rlen);
if (!dash) return;
*from = uwsgi_str_num(range, dash-range);
*to = uwsgi_str_num(dash+1, rlen - ((dash+1)-range));
if (*to > 0 && *from > *to) {
*from = 0;
*to = 0;
}
}
static int uwsgi_proto_check_10(struct wsgi_request *wsgi_req, char *key, char *buf, uint16_t len) {
if (uwsgi.honour_range && !uwsgi_proto_key("HTTP_RANGE", 10)) {
uwsgi_parse_http_range(buf, len, &wsgi_req->range_from, &wsgi_req->range_to);
return 0;
}
if (!uwsgi_proto_key("UWSGI_FILE", 10)) {
wsgi_req->file = buf;
wsgi_req->file_len = len;
@@ -312,6 +345,12 @@ static int uwsgi_proto_check_10(struct wsgi_request *wsgi_req, char *key, char *
return 0;
}
if (!uwsgi_proto_key("UWSGI_HOME", 10)) {
wsgi_req->home = buf;
wsgi_req->home_len = len;
return 0;
}
return 0;
}
@@ -416,8 +455,8 @@ static int uwsgi_proto_check_12(struct wsgi_request *wsgi_req, char *key, char *
}
if (!uwsgi_proto_key("UWSGI_PYHOME", 12)) {
wsgi_req->pyhome = buf;
wsgi_req->pyhome_len = len;
wsgi_req->home = buf;
wsgi_req->home_len = len;
return 0;
}
@@ -700,7 +739,7 @@ next:
// check if data are available in the local cache
if (wsgi_req->cache_get_len > 0) {
uint64_t cache_value_size;
char *cache_value = uwsgi_cache_magic_get(wsgi_req->cache_get, wsgi_req->cache_get_len, &cache_value_size, NULL);
char *cache_value = uwsgi_cache_magic_get(wsgi_req->cache_get, wsgi_req->cache_get_len, &cache_value_size, NULL, NULL);
if (cache_value && cache_value_size > 0) {
uwsgi_response_write_body_do(wsgi_req, cache_value, cache_value_size);
free(cache_value);
@@ -711,7 +750,7 @@ next:
if (uwsgi.check_cache && wsgi_req->uri_len && wsgi_req->method_len == 3 && wsgi_req->method[0] == 'G' && wsgi_req->method[1] == 'E' && wsgi_req->method[2] == 'T') {
uint64_t cache_value_size;
char *cache_value = uwsgi_cache_magic_get(wsgi_req->uri, wsgi_req->uri_len, &cache_value_size, NULL);
char *cache_value = uwsgi_cache_magic_get(wsgi_req->uri, wsgi_req->uri_len, &cache_value_size, NULL, NULL);
if (cache_value && cache_value_size > 0) {
uwsgi_response_write_body_do(wsgi_req, cache_value, cache_value_size);
free(cache_value);
@@ -968,6 +1007,60 @@ int uwsgi_hooked_parse_array(char *buffer, size_t len, void (*hook) (uint16_t, c
}
// this functions transform a raw HTTP response to a uWSGI-managed response
int uwsgi_blob_to_response(struct wsgi_request *wsgi_req, char *body, size_t len) {
char *line = body;
size_t line_len = 0;
size_t i;
int status_managed = 0;
for(i=0;i<len;i++) {
if (body[i] == '\n') {
// invalid line
if (line_len < 1) {
return -1;
}
if (line[line_len-1] != '\r') {
return -1;
}
// end of the headers
if (line_len == 1) {
break;
}
if (status_managed) {
char *colon = memchr(line, ':', line_len-1);
if (!colon) return -1;
if (colon[1] != ' ') return -1;
if (uwsgi_response_add_header(wsgi_req, line, colon-line, colon+2, (line_len-1) - ((colon+2)-line))) return -1;
}
else {
char *space = memchr(line, ' ', line_len-1);
if (!space) return -1;
if ((line_len-1) - ((space+1)-line) < 3) return -1;
if (uwsgi_response_prepare_headers(wsgi_req, space+1, (line_len-1) - ((space+1)-line))) return -1;
status_managed = 1;
}
line = NULL;
line_len = 0;
}
else {
if (!line) {
line = body + i;
}
line_len++;
}
}
if ((i+1) < len) {
if (uwsgi_response_write_body_do(wsgi_req, body + (i + 1), len-(i+1))) {
return -1;
}
}
return 0;
}
/*
the following functions need to take in account that POST data could be already available in wsgi_req->buffer (generally when uwsgi protocol is in use)
+1 -1
View File
@@ -47,7 +47,7 @@ void uwsgi_request_body_seek(struct wsgi_request *wsgi_req, off_t pos) {
if (uwsgi.post_buffering) {
if (pos < 0) {
if (pos > (off_t) wsgi_req->post_pos) {
if ((off_t) wsgi_req->post_pos - pos < 0) {
wsgi_req->post_pos = 0;
return;
}
+415
View File
@@ -220,6 +220,10 @@ run:
if (ret == UWSGI_ROUTE_GOON) {
goon_func = routes->func;
}
if (ret == -1) {
return UWSGI_ROUTE_BREAK;
}
}
next:
subject = orig_subject;
@@ -661,6 +665,153 @@ static int uwsgi_router_signal(struct uwsgi_route *ur, char *arg) {
return 0;
}
// chdir route
static int uwsgi_router_chdir_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
if (chdir(ub->buf)) {
uwsgi_error("uwsgi_router_chdir_func()/chdir()");
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_chdir(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_chdir_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// setapp route
static int uwsgi_router_setapp_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
char *ptr = uwsgi_req_append(wsgi_req, "UWSGI_APPID", 11, ub->buf, ub->pos);
if (!ptr) {
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
wsgi_req->appid = ptr;
wsgi_req->appid_len = ub->pos;
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_setapp(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_setapp_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// sethome route
static int uwsgi_router_sethome_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
char *ptr = uwsgi_req_append(wsgi_req, "UWSGI_HOME", 10, ub->buf, ub->pos);
if (!ptr) {
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
wsgi_req->home = ptr;
wsgi_req->home_len = ub->pos;
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_sethome(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_sethome_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// setfile route
static int uwsgi_router_setfile_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
char *ptr = uwsgi_req_append(wsgi_req, "UWSGI_HOME", 10, ub->buf, ub->pos);
if (!ptr) {
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
wsgi_req->file = ptr;
wsgi_req->file_len = ub->pos;
wsgi_req->dynamic = 1;
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_setfile(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_setfile_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// setprocname route
static int uwsgi_router_setprocname_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
uwsgi_set_processname(ub->buf);
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_setprocname(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_setprocname_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// alarm route
static int uwsgi_router_alarm_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub_alarm = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub_alarm) return UWSGI_ROUTE_BREAK;
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data2, ur->data2_len);
if (!ub) {
uwsgi_buffer_destroy(ub_alarm);
return UWSGI_ROUTE_BREAK;
}
uwsgi_alarm_trigger(ub_alarm->buf, ub->buf, ub->pos);
uwsgi_buffer_destroy(ub_alarm);
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_alarm(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_alarm_func;
char *space = strchr(arg, ' ');
if (!space) {
return -1;
}
*space = 0;
ur->data = arg;
ur->data_len = strlen(arg);
ur->data2 = space+1;
ur->data2_len = strlen(ur->data2);
return 0;
}
// send route
static int uwsgi_router_send_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
@@ -780,6 +931,119 @@ static int uwsgi_route_condition_equal(struct wsgi_request *wsgi_req, struct uws
return 0;
}
static int uwsgi_route_condition_higher(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
if (!semicolon) return 0;
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
if (!ub) return -1;
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
if (!ub2) {
uwsgi_buffer_destroy(ub);
return -1;
}
long num1 = strtol(ub->buf, NULL, 10);
long num2 = strtol(ub2->buf, NULL, 10);
if(num1 > num2) {
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 1;
}
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 0;
}
static int uwsgi_route_condition_higherequal(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
if (!semicolon) return 0;
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
if (!ub) return -1;
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
if (!ub2) {
uwsgi_buffer_destroy(ub);
return -1;
}
long num1 = strtol(ub->buf, NULL, 10);
long num2 = strtol(ub2->buf, NULL, 10);
if(num1 >= num2) {
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 1;
}
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 0;
}
static int uwsgi_route_condition_lower(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
if (!semicolon) return 0;
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
if (!ub) return -1;
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
if (!ub2) {
uwsgi_buffer_destroy(ub);
return -1;
}
long num1 = strtol(ub->buf, NULL, 10);
long num2 = strtol(ub2->buf, NULL, 10);
if(num1 < num2) {
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 1;
}
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 0;
}
static int uwsgi_route_condition_lowerequal(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
if (!semicolon) return 0;
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
if (!ub) return -1;
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
if (!ub2) {
uwsgi_buffer_destroy(ub);
return -1;
}
long num1 = strtol(ub->buf, NULL, 10);
long num2 = strtol(ub2->buf, NULL, 10);
if(num1 <= num2) {
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 1;
}
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 0;
}
#ifdef UWSGI_SSL
static int uwsgi_route_condition_lord(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, ur->subject_str_len);
if (!ub) return -1;
int ret = uwsgi_legion_i_am_the_lord(ub->buf);
uwsgi_buffer_destroy(ub);
return ret;
}
#endif
static int uwsgi_route_condition_startswith(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
if (!semicolon) return 0;
@@ -803,6 +1067,29 @@ static int uwsgi_route_condition_startswith(struct wsgi_request *wsgi_req, struc
return 0;
}
static int uwsgi_route_condition_contains(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
if (!semicolon) return 0;
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
if (!ub) return -1;
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
if (!ub2) {
uwsgi_buffer_destroy(ub);
return -1;
}
if(uwsgi_contains_n(ub->buf, ub->pos, ub2->buf, ub2->pos)) {
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 1;
}
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 0;
}
static int uwsgi_route_condition_endswith(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
if (!semicolon) return 0;
@@ -865,6 +1152,101 @@ static int uwsgi_route_condition_isexec(struct wsgi_request *wsgi_req, struct uw
return 0;
}
static char *uwsgi_route_var_uwsgi(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
char *ret = NULL;
if (!uwsgi_strncmp(key, keylen, "wid", 3)) {
ret = uwsgi_num2str(uwsgi.mywid);
*vallen = strlen(ret);
}
else if (!uwsgi_strncmp(key, keylen, "pid", 3)) {
ret = uwsgi_num2str(uwsgi.mypid);
*vallen = strlen(ret);
}
return ret;
}
static char *uwsgi_route_var_mime(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
size_t mime_type_len = 0;
char *ret = uwsgi_get_mime_type(key, keylen, &mime_type_len);
if (ret) *vallen = mime_type_len;
return ret;
}
static char *uwsgi_route_var_time(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
char *ret = NULL;
if (!uwsgi_strncmp(key, keylen, "unix", 4)) {
ret = uwsgi_num2str(uwsgi_now());
*vallen = strlen(ret);
}
return ret;
}
static char *uwsgi_route_var_base64(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
char *ret = NULL;
uint16_t var_vallen = 0;
char *var_value = uwsgi_get_var(wsgi_req, key, keylen, &var_vallen);
if (var_value) {
size_t b64_len = 0;
ret = uwsgi_base64_encode(var_value, var_vallen, &b64_len);
*vallen = b64_len;
}
return ret;
}
static char *uwsgi_route_var_hex(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
char *ret = NULL;
uint16_t var_vallen = 0;
char *var_value = uwsgi_get_var(wsgi_req, key, keylen, &var_vallen);
if (var_value) {
ret = uwsgi_str_to_hex(var_value, var_vallen);
*vallen = var_vallen*2;
}
return ret;
}
#ifdef UWSGI_MATHEVAL
static char *uwsgi_route_var_math(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
char *ret = NULL;
// avoid crash
if (!wsgi_req->var_cnt) return NULL;
// we make a bit of fun here, we do a copy of the vars buffer (+1 byte for final zero) and zeor-pad all of the strings
char *vars_buf = uwsgi_malloc(wsgi_req->uh->pktsize + keylen + 1);
char **names = uwsgi_malloc(sizeof(char *) * (wsgi_req->var_cnt/2));
double *values = uwsgi_calloc(sizeof(double) * (wsgi_req->var_cnt/2));
int i,j = 0;
char *ptr = vars_buf;
for (i = wsgi_req->var_cnt-1; i > 0; i -= 2) {
memcpy(ptr, wsgi_req->hvec[i-1].iov_base, wsgi_req->hvec[i-1].iov_len);
names[j] = ptr;
ptr += wsgi_req->hvec[i-1].iov_len;
*ptr++=0;
char *num = ptr;
memcpy(ptr, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
ptr += wsgi_req->hvec[i].iov_len;
*ptr++=0;
values[j] = strtod(num, NULL);
j++;
}
char *expr = ptr;
memcpy(ptr, key, keylen); ptr += keylen;
*ptr++=0;
void *e = evaluator_create(expr);
if (!e) goto end;
double n = evaluator_evaluate(e, j, names, values);
evaluator_destroy(e);
ret = uwsgi_num2str((int)n);
*vallen = strlen(ret);
end:
free(vars_buf);
free(names);
free(values);
return ret;
}
#endif
// register embedded routers
void uwsgi_register_embedded_routers() {
@@ -882,6 +1264,12 @@ void uwsgi_register_embedded_routers() {
uwsgi_register_router("signal", uwsgi_router_signal);
uwsgi_register_router("send", uwsgi_router_send);
uwsgi_register_router("send-crnl", uwsgi_router_send_crnl);
uwsgi_register_router("chdir", uwsgi_router_chdir);
uwsgi_register_router("setapp", uwsgi_router_setapp);
uwsgi_register_router("sethome", uwsgi_router_sethome);
uwsgi_register_router("setfile", uwsgi_router_setfile);
uwsgi_register_router("setprocname", uwsgi_router_setprocname);
uwsgi_register_router("alarm", uwsgi_router_alarm);
uwsgi_register_route_condition("exists", uwsgi_route_condition_exists);
uwsgi_register_route_condition("isfile", uwsgi_route_condition_isfile);
@@ -896,11 +1284,38 @@ void uwsgi_register_embedded_routers() {
uwsgi_register_route_condition("endswith", uwsgi_route_condition_endswith);
uwsgi_register_route_condition("regexp", uwsgi_route_condition_regexp);
uwsgi_register_route_condition("re", uwsgi_route_condition_regexp);
uwsgi_register_route_condition("ishigher", uwsgi_route_condition_higher);
uwsgi_register_route_condition(">", uwsgi_route_condition_higher);
uwsgi_register_route_condition("islower", uwsgi_route_condition_lower);
uwsgi_register_route_condition("<", uwsgi_route_condition_lower);
uwsgi_register_route_condition("ishigherequal", uwsgi_route_condition_higherequal);
uwsgi_register_route_condition(">=", uwsgi_route_condition_higherequal);
uwsgi_register_route_condition("islowerequal", uwsgi_route_condition_lowerequal);
uwsgi_register_route_condition("<=", uwsgi_route_condition_lowerequal);
uwsgi_register_route_condition("contains", uwsgi_route_condition_contains);
uwsgi_register_route_condition("contain", uwsgi_route_condition_contains);
#ifdef UWSGI_SSL
uwsgi_register_route_condition("lord", uwsgi_route_condition_lord);
#endif
uwsgi_register_route_condition("empty", uwsgi_route_condition_empty);
uwsgi_register_route_var("cookie", uwsgi_get_cookie);
uwsgi_register_route_var("qs", uwsgi_get_qs);
uwsgi_register_route_var("mime", uwsgi_route_var_mime);
struct uwsgi_route_var *urv = uwsgi_register_route_var("uwsgi", uwsgi_route_var_uwsgi);
urv->need_free = 1;
urv = uwsgi_register_route_var("time", uwsgi_route_var_time);
urv->need_free = 1;
#ifdef UWSGI_MATHEVAL
urv = uwsgi_register_route_var("math", uwsgi_route_var_math);
urv->need_free = 1;
#endif
urv = uwsgi_register_route_var("base64", uwsgi_route_var_base64);
urv->need_free = 1;
urv = uwsgi_register_route_var("hex", uwsgi_route_var_hex);
urv->need_free = 1;
}
struct uwsgi_router *uwsgi_register_router(char *name, int (*func) (struct uwsgi_route *, char *)) {
+5 -5
View File
@@ -1,8 +1,8 @@
#include "uwsgi.h"
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
int uwsgi_register_rpc(char *name, uint8_t modifier1, uint8_t args, void *func) {
int uwsgi_register_rpc(char *name, struct uwsgi_plugin *plugin, uint8_t args, void *func) {
struct uwsgi_rpc *urpc;
int ret = -1;
@@ -30,7 +30,7 @@ int uwsgi_register_rpc(char *name, uint8_t modifier1, uint8_t args, void *func)
uwsgi.shared->rpc_count[uwsgi.mywid]++;
already:
memcpy(urpc->name, name, strlen(name));
urpc->modifier1 = modifier1;
urpc->plugin = plugin;
urpc->args = args;
urpc->func = func;
urpc->shared = uwsgi.mywid == 0 ? 1 : 0;
@@ -77,8 +77,8 @@ uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], cha
}
if (urpc) {
if (uwsgi.p[urpc->modifier1]->rpc) {
ret = uwsgi.p[urpc->modifier1]->rpc(urpc->func, argc, argv, argvs, output);
if (urpc->plugin->rpc) {
ret = urpc->plugin->rpc(urpc->func, argc, argv, argvs, output);
}
}
+3
View File
@@ -106,6 +106,9 @@ void uwsgi_setup_inherited_sockets() {
//now close all the unbound fd
for (j = 3; j < (int) uwsgi.max_fd; j++) {
int useless = 1;
if (uwsgi_fd_is_safe(j)) continue;
if (uwsgi.has_emperor) {
if (j == uwsgi.emperor_fd)
continue;
-138
View File
@@ -177,87 +177,6 @@ int uwsgi_add_file_monitor(uint8_t sig, char *filename) {
}
struct uwsgi_probe *uwsgi_probe_register(struct uwsgi_probe **up, char *name, int (*func) (int, struct uwsgi_signal_probe *)) {
struct uwsgi_probe *uwsgi_up = *up, *old_up;
if (!uwsgi_up) {
*up = uwsgi_malloc(sizeof(struct uwsgi_probe));
uwsgi_up = *up;
}
else {
while (uwsgi_up) {
old_up = uwsgi_up;
uwsgi_up = uwsgi_up->next;
}
uwsgi_up = uwsgi_malloc(sizeof(struct uwsgi_probe));
old_up->next = uwsgi_up;
}
uwsgi_up->name = name;
uwsgi_up->func = func;
uwsgi_up->next = NULL;
uwsgi_log("registered new probe \"%s\" at %p\n", name, uwsgi_up);
return uwsgi_up;
}
int uwsgi_add_probe(uint8_t sig, char *kind, char *args, int timeout, int freq) {
uwsgi_lock(uwsgi.probe_table_lock);
if (ushared->probes_cnt < MAX_PROBES) {
struct uwsgi_probe *up = uwsgi.probes;
while (up) {
if (!strcmp(up->name, kind)) {
break;
}
up = up->next;
}
if (!up) {
uwsgi_log("unable to find probe \"%s\" !!!\n", kind);
uwsgi_unlock(uwsgi.probe_table_lock);
return -1;
}
// fill the probe table
ushared->probes[ushared->probes_cnt].func = up->func;
strncpy(ushared->probes[ushared->probes_cnt].args, args, 1024 - 1);
ushared->probes[ushared->probes_cnt].registered = 0;
ushared->probes[ushared->probes_cnt].sig = sig;
ushared->probes[ushared->probes_cnt].fd = -1;
ushared->probes[ushared->probes_cnt].state = 0;
ushared->probes[ushared->probes_cnt].last_event = 0;
ushared->probes[ushared->probes_cnt].data = NULL;
ushared->probes[ushared->probes_cnt].cycles = 0;
ushared->probes[ushared->probes_cnt].bad = 0;
if (!timeout) {
timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
}
ushared->probes[ushared->probes_cnt].timeout = timeout;
if (!freq) {
freq = 1;
}
ushared->probes[ushared->probes_cnt].freq = freq;
ushared->probes_cnt++;
}
else {
uwsgi_log("you can register max %d probes !!!\n", MAX_PROBES);
uwsgi_unlock(uwsgi.probe_table_lock);
return -1;
}
uwsgi_unlock(uwsgi.probe_table_lock);
return 0;
}
int uwsgi_add_timer(uint8_t sig, int secs) {
if (!uwsgi.master_process) return -1;
@@ -284,63 +203,6 @@ int uwsgi_add_timer(uint8_t sig, int secs) {
}
void uwsgi_opt_add_cron(char *opt, char *value, void *foobar) {
int i;
struct uwsgi_cron *old_uc, *uc = uwsgi.crons;
if (!uc) {
uc = uwsgi_malloc(sizeof(struct uwsgi_cron));
uwsgi.crons = uc;
}
else {
old_uc = uc;
while (uc->next) {
uc = uc->next;
old_uc = uc;
}
old_uc->next = uwsgi_malloc(sizeof(struct uwsgi_cron));
uc = old_uc->next;
}
memset(uc, 0, sizeof(struct uwsgi_cron));
if (sscanf(value, "%d %d %d %d %d %n", &uc->minute, &uc->hour, &uc->day, &uc->month, &uc->week, &i) != 5) {
uwsgi_log("invalid cron syntax\n");
exit(1);
}
uc->command = value + i;
}
int uwsgi_signal_add_cron(uint8_t sig, int minute, int hour, int day, int month, int week) {
if (!uwsgi.master_process)
return -1;
uwsgi_lock(uwsgi.cron_table_lock);
if (ushared->cron_cnt < MAX_CRONS) {
ushared->cron[ushared->cron_cnt].sig = sig;
ushared->cron[ushared->cron_cnt].minute = minute;
ushared->cron[ushared->cron_cnt].hour = hour;
ushared->cron[ushared->cron_cnt].day = day;
ushared->cron[ushared->cron_cnt].month = month;
ushared->cron[ushared->cron_cnt].week = week;
ushared->cron_cnt++;
}
else {
uwsgi_log("you can register max %d cron !!!\n", MAX_CRONS);
uwsgi_unlock(uwsgi.cron_table_lock);
return -1;
}
uwsgi_unlock(uwsgi.cron_table_lock);
return 0;
}
int uwsgi_signal_add_rb_timer(uint8_t sig, int secs, int iterations) {
if (!uwsgi.master_process)
+36
View File
@@ -136,6 +136,24 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
uwsgi_log("setting abstract socket mode (warning: only Linux supports this)\n");
}
if (uwsgi.so_sndbuf) {
socklen_t sndbuf = (socklen_t) uwsgi.so_sndbuf;
if (setsockopt(serverfd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(socklen_t)) < 0) {
uwsgi_error("SO_SNDBUF setsockopt()");
uwsgi_nuclear_blast();
return -1;
}
}
if (uwsgi.so_rcvbuf) {
socklen_t rcvbuf = (socklen_t) uwsgi.so_rcvbuf;
if (setsockopt(serverfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(socklen_t)) < 0) {
uwsgi_error("SO_RCVBUF setsockopt()");
uwsgi_nuclear_blast();
return -1;
}
}
uws_addr->sun_family = AF_UNIX;
if (socket_name[0] == '@') {
memcpy(uws_addr->sun_path + abstract_socket, socket_name + 1, UMIN(strlen(socket_name + 1), 101));
@@ -587,6 +605,24 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
uwsgi_nuclear_blast();
return -1;
}
if (uwsgi.so_sndbuf) {
socklen_t sndbuf = (socklen_t) uwsgi.so_sndbuf;
if (setsockopt(serverfd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(socklen_t)) < 0) {
uwsgi_error("SO_SNDBUF setsockopt()");
uwsgi_nuclear_blast();
return -1;
}
}
if (uwsgi.so_rcvbuf) {
socklen_t rcvbuf = (socklen_t) uwsgi.so_rcvbuf;
if (setsockopt(serverfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(socklen_t)) < 0) {
uwsgi_error("SO_RCVBUF setsockopt()");
uwsgi_nuclear_blast();
return -1;
}
}
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) {
uwsgi_error("SO_REUSEADDR setsockopt()");
-57
View File
@@ -1,57 +0,0 @@
#ifdef UWSGI_SQLITE3
#include "uwsgi.h"
#include <sqlite3.h>
extern struct uwsgi_server uwsgi;
static int uwsgi_sqlite3_config_callback(void *magic_table, int field_count, char **fields, char **col) {
// make a copy of the string
if (field_count >= 2) {
size_t value_len = strlen(fields[1]) + 1;
char *value = magic_sub(fields[1], value_len, &value_len, (char **) magic_table);
add_exported_option(uwsgi_strncopy(fields[0], strlen(fields[0])), value, 0);
}
return 0;
}
void uwsgi_sqlite3_config(char *file, char *magic_table[]) {
sqlite3 *db;
char *err = NULL;
char *query = "SELECT * FROM uwsgi";
char *colon = uwsgi_get_last_char(file, ':');
if (colon) {
colon[0] = 0;
if (colon[1] != 0) {
query = colon + 1;
}
}
uwsgi_log("[uWSGI] getting sqlite3 configuration from %s\n", file);
#ifdef sqlite3_open_v2
if (sqlite3_open_v2(file, &db, SQLITE_OPEN_READONLY, NULL)) {
#else
if (sqlite3_open(file, &db)) {
#endif
uwsgi_log("unable to open sqlite3 db: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
exit(1);
}
if (sqlite3_exec(db, query, uwsgi_sqlite3_config_callback, (void *) magic_table, &err)) {
uwsgi_log("sqlite3 error: %s\n", err);
sqlite3_close(db);
exit(1);
}
sqlite3_close(db);
}
#endif
+8 -2
View File
@@ -252,8 +252,14 @@ SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ci
uwsgi.ssl_sessions_cache = uwsgi_cache_by_name(uwsgi.ssl_sessions_use_cache);
if (!uwsgi.ssl_sessions_cache) {
uwsgi_log("unable to find cache \"%s\"\n", uwsgi.ssl_sessions_use_cache ? uwsgi.ssl_sessions_use_cache : "default");
exit(1);
// check for default cache
if (!strcmp(uwsgi.ssl_sessions_use_cache, "true") && uwsgi.caches) {
uwsgi.ssl_sessions_cache = uwsgi.caches;
}
else {
uwsgi_log("unable to find cache \"%s\"\n", uwsgi.ssl_sessions_use_cache ? uwsgi.ssl_sessions_use_cache : "default");
exit(1);
}
}
if (!uwsgi.ssl_sessions_cache->max_items) {
+59 -24
View File
@@ -55,7 +55,7 @@ gzip:
return 1;
}
static int set_http_date(time_t t, char *dst) {
int uwsgi_http_date(time_t t, char *dst) {
static char *week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
static char *months[] = {
@@ -179,7 +179,7 @@ int uwsgi_add_expires_type(struct wsgi_request *wsgi_req, char *mime_type, int m
while (udd) {
if (!uwsgi_strncmp(udd->key, udd->keylen, mime_type, mime_type_len)) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(now + delta, expires);
int size = uwsgi_http_date(now + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
@@ -192,7 +192,7 @@ int uwsgi_add_expires_type(struct wsgi_request *wsgi_req, char *mime_type, int m
while (udd) {
if (!uwsgi_strncmp(udd->key, udd->keylen, mime_type, mime_type_len)) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(st->st_mtime + delta, expires);
int size = uwsgi_http_date(st->st_mtime + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
@@ -215,7 +215,7 @@ int uwsgi_add_expires(struct wsgi_request *wsgi_req, char *filename, int filenam
while (udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, filename, filename_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(now + delta, expires);
int size = uwsgi_http_date(now + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
@@ -228,7 +228,7 @@ int uwsgi_add_expires(struct wsgi_request *wsgi_req, char *filename, int filenam
while (udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, filename, filename_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(st->st_mtime + delta, expires);
int size = uwsgi_http_date(st->st_mtime + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
@@ -250,7 +250,7 @@ int uwsgi_add_expires_path_info(struct wsgi_request *wsgi_req, struct stat *st)
while (udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->path_info, wsgi_req->path_info_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(now + delta, expires);
int size = uwsgi_http_date(now + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
@@ -263,7 +263,7 @@ int uwsgi_add_expires_path_info(struct wsgi_request *wsgi_req, struct stat *st)
while (udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->path_info, wsgi_req->path_info_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(st->st_mtime + delta, expires);
int size = uwsgi_http_date(st->st_mtime + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
@@ -285,7 +285,7 @@ int uwsgi_add_expires_uri(struct wsgi_request *wsgi_req, struct stat *st) {
while (udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->uri, wsgi_req->uri_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(now + delta, expires);
int size = uwsgi_http_date(now + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
@@ -298,7 +298,7 @@ int uwsgi_add_expires_uri(struct wsgi_request *wsgi_req, struct stat *st) {
while (udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->uri, wsgi_req->uri_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(st->st_mtime + delta, expires);
int size = uwsgi_http_date(st->st_mtime + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
@@ -333,6 +333,10 @@ char *uwsgi_get_mime_type(char *name, int namelen, size_t *size) {
if (!ext)
return NULL;
if (uwsgi.threads > 1)
pthread_mutex_lock(&uwsgi.lock_static);
struct uwsgi_dyn_dict *udd = uwsgi.mimetypes;
while (udd) {
if (!uwsgi_strncmp(ext, count, udd->key, udd->keylen)) {
@@ -361,11 +365,16 @@ char *uwsgi_get_mime_type(char *name, int namelen, size_t *size) {
}
}
*size = udd->vallen;
if (uwsgi.threads > 1)
pthread_mutex_unlock(&uwsgi.lock_static);
return udd->value;
}
udd = udd->next;
}
if (uwsgi.threads > 1)
pthread_mutex_unlock(&uwsgi.lock_static);
return NULL;
}
@@ -431,14 +440,12 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
size_t mime_type_size = 0;
char http_last_modified[49];
if (uwsgi.threads > 1)
pthread_mutex_lock(&uwsgi.lock_static);
int use_gzip = 0;
char *mime_type = uwsgi_get_mime_type(real_filename, real_filename_len, &mime_type_size);
if (uwsgi.threads > 1)
pthread_mutex_unlock(&uwsgi.lock_static);
// here we need to choose if we want the gzip variant;
if (uwsgi_static_want_gzip(wsgi_req, real_filename, real_filename_len, st)) use_gzip = 1;
if (wsgi_req->if_modified_since_len) {
time_t ims = parse_http_date(wsgi_req->if_modified_since, wsgi_req->if_modified_since_len);
@@ -451,8 +458,32 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
uwsgi_log("[uwsgi-fileserve] file %s found\n", real_filename);
#endif
size_t fsize = st->st_size;
if (wsgi_req->range_to) {
fsize = wsgi_req->range_to - wsgi_req->range_from;
if (fsize > (size_t)st->st_size) {
fsize = st->st_size;
}
}
else {
// reset in case of inconsistent size
if (wsgi_req->range_from > fsize) {
wsgi_req->range_from = 0;
fsize = 0;
}
else {
fsize -= wsgi_req->range_from;
}
}
// HTTP status
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return -1;
if (fsize > 0 && (wsgi_req->range_from || wsgi_req->range_to)) {
if (uwsgi_response_prepare_headers(wsgi_req, "206 Partial Content", 19)) return -1;
}
else {
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return -1;
}
#ifdef UWSGI_PCRE
uwsgi_add_expires(wsgi_req, real_filename, real_filename_len, st);
@@ -460,6 +491,10 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
uwsgi_add_expires_uri(wsgi_req, st);
#endif
if (use_gzip) {
if (uwsgi_response_add_header(wsgi_req, "Content-Encoding", 16, "gzip", 4)) return -1;
}
// Content-Type (if available)
if (mime_type_size > 0 && mime_type) {
if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_size)) return -1;
@@ -474,25 +509,25 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
if (uwsgi.file_serve_mode == 1) {
if (uwsgi_response_add_header(wsgi_req, "X-Accel-Redirect", 16, real_filename, real_filename_len)) return -1;
// this is the final header (\r\n added)
int size = set_http_date(st->st_mtime, http_last_modified);
int size = uwsgi_http_date(st->st_mtime, http_last_modified);
if (uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, http_last_modified, size)) return -1;
}
// apache
else if (uwsgi.file_serve_mode == 2) {
if (uwsgi_response_add_header(wsgi_req, "X-Sendfile", 10, real_filename, real_filename_len)) return -1;
// this is the final header (\r\n added)
int size = set_http_date(st->st_mtime, http_last_modified);
int size = uwsgi_http_date(st->st_mtime, http_last_modified);
if (uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, http_last_modified, size)) return -1;
}
// raw
else {
// here we need to choose if we want the gzip variant;
if (uwsgi_static_want_gzip(wsgi_req, real_filename, real_filename_len, st)) {
if (uwsgi_response_add_header(wsgi_req, "Content-Encoding", 16, "gzip", 4)) return -1;
// set Content-Length (to fsize NOT st->st_size)
if (uwsgi_response_add_content_length(wsgi_req, fsize)) return -1;
if (fsize > 0 && (wsgi_req->range_from || wsgi_req->range_to)) {
// here use the original size !!!
if (uwsgi_response_add_content_range(wsgi_req, wsgi_req->range_from, wsgi_req->range_to, st->st_size)) return -1;
}
// set Content-Length
if (uwsgi_response_add_content_length(wsgi_req, st->st_size)) return -1;
int size = set_http_date(st->st_mtime, http_last_modified);
int size = uwsgi_http_date(st->st_mtime, http_last_modified);
if (uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, http_last_modified, size)) return -1;
// if it is a HEAD request just skip transfer
@@ -506,7 +541,7 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
int fd = open(real_filename, O_RDONLY);
if (fd < 0) return -1;
// fd will be closed in the following function
uwsgi_response_sendfile_do(wsgi_req, fd, 0, st->st_size);
uwsgi_response_sendfile_do(wsgi_req, fd, wsgi_req->range_from, fsize);
}
wsgi_req->status = 200;
+69
View File
@@ -0,0 +1,69 @@
#include <uwsgi.h>
/*
uWSGI transformations
responses can be buffered in the wsgi_request structure (instead of being sent to the client)
Before closing the request, the transformations are applied in chain to the response buffer
Finally the resulting buffer is sent to the client
Transformations (if required) could completely swallow already set headers
*/
extern struct uwsgi_server uwsgi;
int uwsgi_apply_transformations(struct wsgi_request *wsgi_req) {
int ret = 0;
struct uwsgi_transformation *ut = wsgi_req->transformations;
while(ut) {
struct uwsgi_buffer *new_ub = NULL;
if (ut->func(wsgi_req, wsgi_req->response_buffer, &new_ub, ut->data)) {
ret = -1;
goto end;
}
if (new_ub) {
uwsgi_buffer_destroy(wsgi_req->response_buffer);
wsgi_req->response_buffer = new_ub;
}
ut = ut->next;
}
end:
ut = wsgi_req->transformations;
while(ut) {
struct uwsgi_transformation *current_ut = ut;
ut = ut->next;
free(current_ut);
}
return ret;
}
struct uwsgi_transformation *uwsgi_add_transformation(struct wsgi_request *wsgi_req, int (*func)(struct wsgi_request *, struct uwsgi_buffer *, struct uwsgi_buffer **, void *), void *data) {
struct uwsgi_transformation *old_ut = NULL, *ut = wsgi_req->transformations;
while(ut) {
old_ut = ut;
ut = ut->next;
}
ut = uwsgi_malloc(sizeof(struct uwsgi_transformation));
ut->func = func;
ut->next = NULL;
ut->data = data;
if (old_ut) {
old_ut->next = ut;
}
else {
wsgi_req->transformations = ut;
}
// start buffering
if (!wsgi_req->response_buffer) {
wsgi_req->response_buffer = uwsgi_buffer_new(uwsgi.page_size);
}
return ut;
}
+110 -34
View File
@@ -222,12 +222,11 @@ void uwsgi_set_cgroup() {
uwsgi_error_open(cgroup_taskfile);
exit(1);
}
if (fprintf(cgroup, "%d", (int) getpid()) <= 0) {
uwsgi_log("could not set cgroup\n");
if (fprintf(cgroup, "%d\n", (int) getpid()) <= 0 || ferror(cgroup) || fclose(cgroup)) {
uwsgi_error("could not set cgroup");
exit(1);
}
uwsgi_log("assigned process %d to cgroup %s\n", (int) getpid(), cgroup_taskfile);
fclose(cgroup);
free(cgroup_taskfile);
@@ -248,11 +247,10 @@ void uwsgi_set_cgroup() {
cgroup_taskfile = uwsgi_concat3(usl->value, "/", uslo->value);
cgroup = fopen(cgroup_taskfile, "w");
if (cgroup) {
if (fprintf(cgroup, "%s\n", cgroup_opt) < 0) {
if (fprintf(cgroup, "%s\n", cgroup_opt) <= 0 || ferror(cgroup) || fclose(cgroup)) {
uwsgi_log("could not set cgroup option %s to %s\n", uslo->value, cgroup_opt);
exit(1);
}
fclose(cgroup);
uwsgi_log("set %s to %s\n", cgroup_opt, cgroup_taskfile);
}
free(cgroup_taskfile);
@@ -576,6 +574,23 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
int tmp_id;
uint64_t tmp_rt, rss = 0, vsz = 0;
// flush the response buf (if any)
if (wsgi_req->response_buffer) {
// send the body only if transformations are successfull
struct uwsgi_buffer *ub = wsgi_req->response_buffer;
if (uwsgi_apply_transformations(wsgi_req) == 0) {
// the response_buffer could be changed by translations
ub = wsgi_req->response_buffer;
// force true write
wsgi_req->response_buffer = NULL;
uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
}
else {
wsgi_req->write_errors++;
}
uwsgi_buffer_destroy(ub);
}
// check if headers should be sent
if (wsgi_req->headers) {
if (!wsgi_req->headers_sent && !wsgi_req->headers_size && !wsgi_req->response_size) {
@@ -599,7 +614,6 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
uwsgi.workers[uwsgi.mywid].rss_size = rss;
}
// close the connection with the client
if (!wsgi_req->fd_closed) {
// NOTE, if we close the socket before receiving eventually sent data, socket layer will send a RST
@@ -622,25 +636,6 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
free(wsgi_req->proto_parser_buf);
}
// do we need to store the response in the cache
if (wsgi_req->cache_it) {
// only response with a body and a status code of 200 can be cached (TODO allows it to be configurable)
if (wsgi_req->cached_response && wsgi_req->status == 200 && wsgi_req->response_size > 0) {
uwsgi_cache_magic_set(wsgi_req->cache_it->buf, wsgi_req->cache_it->pos,
wsgi_req->cached_response->buf, wsgi_req->cached_response->pos, wsgi_req->cache_it_expires, UWSGI_CACHE_FLAG_UPDATE, wsgi_req->cache_it_to ? wsgi_req->cache_it_to->buf : NULL);
}
uwsgi_buffer_destroy(wsgi_req->cache_it);
}
if (wsgi_req->cache_it_to) {
uwsgi_buffer_destroy(wsgi_req->cache_it_to);
}
if (wsgi_req->cached_response) {
uwsgi_buffer_destroy(wsgi_req->cached_response);
}
if (!wsgi_req->do_not_account) {
uwsgi.workers[0].requests++;
uwsgi.workers[uwsgi.mywid].requests++;
@@ -1141,11 +1136,36 @@ void parse_sys_envs(char **envs) {
}
// get the application id
int uwsgi_get_app_id(char *app_name, int app_name_len, int modifier1) {
int uwsgi_get_app_id(struct wsgi_request *wsgi_req, char *key, uint16_t key_len, int modifier1) {
int i;
struct stat st;
int found;
int free_appname = 0;
char *app_name = key;
uint16_t app_name_len = key_len;
if (!app_name && wsgi_req) {
app_name = wsgi_req->appid;
app_name_len = wsgi_req->appid_len;
if (app_name_len == 0) {
if (!uwsgi.ignore_script_name) {
app_name = wsgi_req->script_name;
app_name_len = wsgi_req->script_name_len;
}
if (uwsgi.vhost) {
app_name = uwsgi_concat3n(wsgi_req->host, wsgi_req->host_len, "|",1, wsgi_req->script_name, wsgi_req->script_name_len);
app_name_len = wsgi_req->host_len + 1 + wsgi_req->script_name_len;
#ifdef UWSGI_DEBUG
uwsgi_debug("VirtualHost KEY=%.*s\n", wsgi_req->appid_len, wsgi_req->appid);
#endif
free_appname = 1;
}
}
}
for (i = 0; i < uwsgi_apps_cnt; i++) {
// reset check
@@ -1177,14 +1197,19 @@ int uwsgi_get_app_id(char *app_name, int app_name_len, int modifier1) {
}
}
}
if (modifier1 == -1)
if (modifier1 == -1) {
if (free_appname) free(app_name);
return i;
if (modifier1 == uwsgi_apps[i].modifier1)
}
if (modifier1 == uwsgi_apps[i].modifier1) {
if (free_appname) free(app_name);
return i;
}
}
}
if (!uwsgi.no_default_app) {
if (free_appname) free(app_name);
return uwsgi.default_app;
}
@@ -1525,6 +1550,25 @@ int uwsgi_logic_opt_for_glob(char *key, char *value) {
return 1;
}
int uwsgi_logic_opt_for_times(char *key, char *value) {
int num = atoi(uwsgi.logic_opt_data);
int i;
char str_num[11];
for (i = 1; i <= num; i++) {
int ret = uwsgi_num2str2(i, str_num);
// security check
if (ret < 0 || ret > 11) {
exit(1);
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", str_num), 0);
}
return 1;
}
void add_exported_option(char *key, char *value, int configured) {
@@ -3054,14 +3098,17 @@ void http_url_decode(char *buf, uint16_t * len, char *dst) {
}
/*
we scan the table in reverse, as updated values are at the end
*/
char *uwsgi_get_var(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t * len) {
int i;
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
if (!uwsgi_strncmp(key, keylen, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len)) {
*len = wsgi_req->hvec[i + 1].iov_len;
return wsgi_req->hvec[i + 1].iov_base;
for (i = wsgi_req->var_cnt-1; i > 0; i -= 2) {
if (!uwsgi_strncmp(key, keylen, wsgi_req->hvec[i-1].iov_base, wsgi_req->hvec[i-1].iov_len)) {
*len = wsgi_req->hvec[i].iov_len;
return wsgi_req->hvec[i].iov_base;
}
}
@@ -3214,10 +3261,9 @@ void uwsgi_write_pidfile(char *pidfile_name) {
uwsgi_error_open(pidfile_name);
exit(1);
}
if (fprintf(pidfile, "%d\n", (int) getpid()) < 0) {
if (fprintf(pidfile, "%d\n", (int) getpid()) <= 0 || ferror(pidfile) || fclose(pidfile)) {
uwsgi_log("could not write pidfile.\n");
}
fclose(pidfile);
}
char *uwsgi_expand_path(char *dir, int dir_len, char *ptr) {
@@ -3829,3 +3875,33 @@ char *uwsgi_get_header(struct wsgi_request *wsgi_req, char *hh, uint16_t len, ui
return value;
}
static char *uwsgi_hex_table[] = {
"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F",
"10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F",
"20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F",
"30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F",
"40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F",
"50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5A", "5B", "5C", "5D", "5E", "5F",
"60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6A", "6B", "6C", "6D", "6E", "6F",
"70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7A", "7B", "7C", "7D", "7E", "7F",
"80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B", "8C", "8D", "8E", "8F",
"90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F",
"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF",
"B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF",
"C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF",
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF",
"E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF",
"F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF",
};
char *uwsgi_str_to_hex(char *src, size_t slen) {
char *dst = uwsgi_malloc(slen*2);
char *ptr = dst;
size_t i;
for(i=0;i<slen;i++) {
memcpy(ptr, uwsgi_hex_table[ (int) src[i] ], 2);
ptr+=2;
}
return dst;
}
+49 -26
View File
@@ -24,6 +24,7 @@
#include <uwsgi.h>
struct uwsgi_server uwsgi;
pid_t masterpid;
#if defined(__APPLE__) && defined(UWSGI_AS_SHARED_LIBRARY)
#include <crt_externs.h>
@@ -73,6 +74,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"config", required_argument, 0, "load configuration using the pluggable system", uwsgi_opt_load_config, NULL, UWSGI_OPT_IMMEDIATE},
{"skip-zero", no_argument, 0, "skip check of file descriptor 0", uwsgi_opt_true, &uwsgi.skip_zero, 0},
{"skip-atexit", no_argument, 0, "skip atexit hooks (ignored by the master)", uwsgi_opt_true, &uwsgi.skip_atexit, 0},
{"set", required_argument, 'S', "set a custom placeholder", uwsgi_opt_set_placeholder, NULL, UWSGI_OPT_IMMEDIATE},
{"get", required_argument, 0, "print the specified option value and exit", uwsgi_opt_add_string_list, &uwsgi.get_list, UWSGI_OPT_NO_INITIAL},
@@ -80,6 +82,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"for", required_argument, 0, "(opt logic) for cycle", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for, UWSGI_OPT_IMMEDIATE},
{"for-glob", required_argument, 0, "(opt logic) for cycle (expand glob)", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for_glob, UWSGI_OPT_IMMEDIATE},
{"for-times", required_argument, 0, "(opt logic) for cycle (expand the specified num to a list starting from 1)", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for_times, UWSGI_OPT_IMMEDIATE},
{"endfor", optional_argument, 0, "(opt logic) end for cycle", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
{"end-for", optional_argument, 0, "(opt logic) end for cycle", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
@@ -215,6 +218,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"ftok", required_argument, 0, "set the ipcsem key via ftok() for avoiding duplicates", uwsgi_opt_set_str, &uwsgi.ftok, 0},
{"sharedarea", required_argument, 'A', "create a raw shared memory area of specified pages", uwsgi_opt_set_int, &uwsgi.sharedareasize, 0},
{"safe-fd", no_argument, 0, "do not close the specified file descriptor", uwsgi_opt_safe_fd, NULL, 0},
{"fd-safe", no_argument, 0, "do not close the specified file descriptor", uwsgi_opt_safe_fd, NULL, 0},
{"cache", required_argument, 0, "create a shared cache containing given elements", uwsgi_opt_set_64bit, &uwsgi.cache_max_items, 0},
{"cache-blocksize", required_argument, 0, "set cache blocksize", uwsgi_opt_set_64bit, &uwsgi.cache_blocksize, 0},
{"cache-store", required_argument, 0, "enable persistent cache to disk", uwsgi_opt_set_str, &uwsgi.cache_store, UWSGI_OPT_MASTER},
@@ -225,8 +231,12 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"cache-udp-server", required_argument, 0, "bind the cache udp server (used only for set/update/delete) to the specified socket", uwsgi_opt_add_string_list, &uwsgi.cache_udp_server, UWSGI_OPT_MASTER},
{"cache-udp-node", required_argument, 0, "send cache update/deletion to the specified cache udp server", uwsgi_opt_add_string_list, &uwsgi.cache_udp_node, UWSGI_OPT_MASTER},
{"cache-sync", required_argument, 0, "copy the whole content of another uWSGI cache server on server startup", uwsgi_opt_set_str, &uwsgi.cache_sync, 0},
{"cache-use-last-modified", no_argument, 0, "update last_modified_at timestamp on every cache item modification (default is disabled)", uwsgi_opt_true, &uwsgi.cache_use_last_modified, 0},
{"load-file-in-cache", required_argument, 0, "load a static file in the cache", uwsgi_opt_add_string_list, &uwsgi.load_file_in_cache, 0},
#ifdef UWSGI_ZLIB
{"load-file-in-cache-gzip", required_argument, 0, "load a static file in the cache with gzip compression", uwsgi_opt_add_string_list, &uwsgi.load_file_in_cache_gzip, 0},
#endif
{"cache2", required_argument, 0, "create a new generation shared cache (keyval syntax)", uwsgi_opt_add_string_list, &uwsgi.cache2, 0},
@@ -294,20 +304,11 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"json", required_argument, 'j', "load config from json file", uwsgi_opt_load_json, NULL, UWSGI_OPT_IMMEDIATE},
{"js", required_argument, 'j', "load config from json file", uwsgi_opt_load_json, NULL, UWSGI_OPT_IMMEDIATE},
#endif
#ifdef UWSGI_SQLITE3
{"sqlite3", required_argument, 0, "load config from sqlite3 db", uwsgi_opt_load_sqlite3, NULL, UWSGI_OPT_IMMEDIATE},
{"sqlite", required_argument, 0, "load config from sqlite3 db", uwsgi_opt_load_sqlite3, NULL, UWSGI_OPT_IMMEDIATE},
#endif
#ifdef UWSGI_ZEROMQ
{"zeromq", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "zmq", 0},
{"zmq", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "zmq", 0},
{"zeromq-socket", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "zmq", 0},
{"zmq-socket", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "zmq", 0},
#endif
#ifdef UWSGI_LDAP
{"ldap", required_argument, 0, "load configuration from ldap server", uwsgi_opt_load_ldap, NULL, UWSGI_OPT_IMMEDIATE},
{"ldap-schema", no_argument, 0, "dump uWSGI ldap schema", uwsgi_opt_ldap_dump, NULL, UWSGI_OPT_IMMEDIATE},
{"ldap-schema-ldif", no_argument, 0, "dump uWSGI ldap schema in ldif format", uwsgi_opt_ldap_dump_ldif, NULL, UWSGI_OPT_IMMEDIATE},
#endif
{"weight", required_argument, 0, "weight of the instance (used by clustering/lb/subscriptions)", uwsgi_opt_set_64bit, &uwsgi.weight, 0},
{"auto-weight", required_argument, 0, "set weight of the instance (used by clustering/lb/subscriptions) automatically", uwsgi_opt_true, &uwsgi.auto_weight, 0},
@@ -320,6 +321,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"socket-send-timeout", no_argument, 0, "set SO_SNDTIMEO", uwsgi_opt_set_int, &uwsgi.so_send_timeout, 0},
{"so-write-timeout", no_argument, 0, "set SO_SNDTIMEO", uwsgi_opt_set_int, &uwsgi.so_send_timeout, 0},
{"socket-write-timeout", no_argument, 0, "set SO_SNDTIMEO", uwsgi_opt_set_int, &uwsgi.so_send_timeout, 0},
{"socket-sndbuf", required_argument, 0, "set SO_SNDBUF", uwsgi_opt_set_64bit, &uwsgi.so_sndbuf, 0},
{"socket-rcvbuf", required_argument, 0, "set SO_RCVBUF", uwsgi_opt_set_64bit, &uwsgi.so_rcvbuf, 0},
{"limit-as", required_argument, 0, "limit processes address space/vsz", uwsgi_opt_set_megabytes, &uwsgi.rl.rlim_max, 0},
{"limit-nproc", required_argument, 0, "limit the number of spawnable processes", uwsgi_opt_set_int, &uwsgi.rl_nproc.rlim_max, 0},
{"reload-on-as", required_argument, 0, "reload if address space is higher than specified megabytes", uwsgi_opt_set_megabytes, &uwsgi.reload_on_as, UWSGI_OPT_MEMORY},
@@ -376,6 +379,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
#ifdef UWSGI_SSL
{"legion", required_argument, 0, "became a member of a legion", uwsgi_opt_legion, NULL, UWSGI_OPT_MASTER},
{"legion-mcast", required_argument, 0, "became a member of a legion (shortcut for multicast)", uwsgi_opt_legion_mcast, NULL, UWSGI_OPT_MASTER},
{"legion-node", required_argument, 0, "add a node to a legion", uwsgi_opt_legion_node, NULL, UWSGI_OPT_MASTER},
{"legion-freq", required_argument, 0, "set the frequency of legion packets", uwsgi_opt_set_int, &uwsgi.legion_freq, UWSGI_OPT_MASTER},
{"legion-tolerance", required_argument, 0, "set the tolerance of legion subsystem", uwsgi_opt_set_int, &uwsgi.legion_tolerance, UWSGI_OPT_MASTER},
@@ -385,6 +389,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"legion-setup", required_argument, 0, "action to call on legion setup", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
{"legion-death", required_argument, 0, "action to call on legion death (shutdown of the instance)", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
{"legion-join", required_argument, 0, "action to call on legion join (first time quorum is reached)", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
{"legion-node-joined", required_argument, 0, "action to call on new node joining legion", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
{"legion-node-left", required_argument, 0, "action to call node leaving legion", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
{"legion-quorum", required_argument, 0, "set the quorum of a legion", uwsgi_opt_legion_quorum, NULL, UWSGI_OPT_MASTER},
{"legion-scroll", required_argument, 0, "set the scroll of a legion", uwsgi_opt_legion_scroll, NULL, UWSGI_OPT_MASTER},
{"legion-scroll-max-size", required_argument, 0, "set max size of legion scroll buffer", uwsgi_opt_set_16bit, &uwsgi.legion_scroll_max_size, 0},
@@ -450,6 +456,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
#endif
{"alarm", required_argument, 0, "create a new alarm, syntax: <alarm> <plugin:args>", uwsgi_opt_add_string_list, &uwsgi.alarm_list, UWSGI_OPT_MASTER},
{"alarm-freq", required_argument, 0, "tune the anti-loop alam system (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.alarm_freq, 0},
{"alarm-fd", required_argument, 0, "raise the specified alarm when an fd is read for read (by default it reads 1 byte, set 8 for eventfd)", uwsgi_opt_add_string_list, &uwsgi.alarm_fd_list, UWSGI_OPT_MASTER},
#ifdef UWSGI_PCRE
{"log-alarm", required_argument, 0, "raise the specified alarm when a log line matches the specified regexp, syntax: <alarm>[,alarm...] <regexp>", uwsgi_opt_add_string_list, &uwsgi.alarm_logs_list, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
{"alarm-log", required_argument, 0, "raise the specified alarm when a log line matches the specified regexp, syntax: <alarm>[,alarm...] <regexp>", uwsgi_opt_add_string_list, &uwsgi.alarm_logs_list, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
@@ -576,6 +583,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"static-gzip-ext", required_argument, 0, "check for a gzip version of all requested static files with the specified ext/suffix", uwsgi_opt_add_string_list, &uwsgi.static_gzip_ext, UWSGI_OPT_MIME},
{"static-gzip-suffix", required_argument, 0, "check for a gzip version of all requested static files with the specified ext/suffix", uwsgi_opt_add_string_list, &uwsgi.static_gzip_ext, UWSGI_OPT_MIME},
{"honour-range", no_argument, 0, "enable support for the HTTP Range header", uwsgi_opt_true, &uwsgi.honour_range, 0},
{"offload-threads", required_argument, 0, "set the number of offload threads to spawn (per-worker, default 0)", uwsgi_opt_set_int, &uwsgi.offload_threads, 0},
{"offload-thread", required_argument, 0, "set the number of offload threads to spawn (per-worker, default 0)", uwsgi_opt_set_int, &uwsgi.offload_threads, 0},
@@ -588,6 +597,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"env", required_argument, 0, "set environment variable", uwsgi_opt_set_env, NULL, 0},
{"unenv", required_argument, 0, "unset environment variable", uwsgi_opt_unset_env, NULL, 0},
{"vacuum", no_argument, 0, "try to remove all of the generated file/sockets", uwsgi_opt_true, &uwsgi.vacuum, 0},
{"file-write", required_argument, 0, "write the specified content to the specified file (syntax: file=value) before privileges drop", uwsgi_opt_add_string_list, &uwsgi.file_write_list, 0},
#ifdef __linux__
{"cgroup", required_argument, 0, "put the processes in the specified cgroup", uwsgi_opt_add_string_list, &uwsgi.cgroup, 0},
{"cgroup-opt", required_argument, 0, "set value in specified cgroup option", uwsgi_opt_add_string_list, &uwsgi.cgroup_opt, 0},
@@ -607,6 +617,10 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"zerg-server", required_argument, 0, "enable the zerg server on the specified UNIX socket", uwsgi_opt_set_str, &uwsgi.zerg_server, UWSGI_OPT_MASTER},
{"cron", required_argument, 0, "add a cron task", uwsgi_opt_add_cron, NULL, UWSGI_OPT_MASTER},
#ifdef UWSGI_SSL
{"legion-cron", required_argument, 0, "add a cron task runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron, NULL, UWSGI_OPT_MASTER},
{"cron-legion", required_argument, 0, "add a cron task runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron, NULL, UWSGI_OPT_MASTER},
#endif
{"loop", required_argument, 0, "select the uWSGI loop engine", uwsgi_opt_set_str, &uwsgi.loop, 0},
{"loop-list", no_argument, 0, "list enabled loop engines", uwsgi_opt_true, &uwsgi.loop_list, 0},
{"loops-list", no_argument, 0, "list enabled loop engines", uwsgi_opt_true, &uwsgi.loop_list, 0},
@@ -946,6 +960,10 @@ void gracefully_kill(int signum) {
}
void end_me(int signum) {
if (getpid() != masterpid && uwsgi.skip_atexit) {
_exit(UWSGI_END_CODE);
// never here
}
exit(UWSGI_END_CODE);
}
@@ -1202,7 +1220,6 @@ void what_i_am_doing() {
}
pid_t masterpid;
int unconfigured_hook(struct wsgi_request *wsgi_req) {
uwsgi_log("-- unavailable modifier requested: %d --\n", wsgi_req->uh->modifier1);
@@ -1372,7 +1389,7 @@ void fixup_argv_and_environ(int argc, char **argv, char **environ) {
env_count++;
}
uwsgi.environ = uwsgi_malloc(sizeof(char *) * env_count);
uwsgi.environ = uwsgi_malloc(sizeof(char *) * (env_count+1));
for (i = 0; i < env_count; i++) {
uwsgi.environ[i] = strdup(environ[i]);
#ifdef UWSGI_DEBUG
@@ -1380,6 +1397,7 @@ void fixup_argv_and_environ(int argc, char **argv, char **environ) {
#endif
environ[i] = uwsgi.environ[i];
}
uwsgi.environ[env_count] = NULL;
#ifdef UWSGI_DEBUG
uwsgi_log("max space for custom process name = %d\n", uwsgi.max_procname);
@@ -2049,6 +2067,8 @@ int uwsgi_start(void *v_argv) {
}
#endif
uwsgi_file_write_do(uwsgi.file_write_list);
if (!uwsgi.master_as_root && !uwsgi.chown_socket) {
uwsgi_as_root();
}
@@ -2353,7 +2373,8 @@ int uwsgi_start(void *v_argv) {
!uwsgi.udp_socket &&
!uwsgi.emperor &&
!uwsgi.command_mode &&
!uwsgi.daemons_cnt
!uwsgi.daemons_cnt &&
!uwsgi.crons
#ifdef UWSGI_SSL
&& !uwsgi.legions
#endif
@@ -2416,7 +2437,14 @@ unsafe:
if (uwsgi.crons) {
struct uwsgi_cron *ucron = uwsgi.crons;
while (ucron) {
uwsgi_log("command \"%s\" registered as uWSGI-cron task\n", ucron->command);
#ifdef UWSGI_SSL
if (ucron->legion) {
uwsgi_log("[uwsgi-cron] command \"%s\" registered as cron task for legion \"%s\"\n", ucron->command, ucron->legion);
ucron = ucron->next;
continue;
}
#endif
uwsgi_log("[uwsgi-cron] command \"%s\" registered as cron task\n", ucron->command);
ucron = ucron->next;
}
}
@@ -3245,6 +3273,14 @@ void uwsgi_opt_set_immediate_uid(char *opt, char *value, void *none) {
uwsgi_log("immediate uid: %d\n", (int) uid);
}
void uwsgi_opt_safe_fd(char *opt, char *value, void *foobar) {
int fd = atoi(value);
if (fd < 0) {
uwsgi_log("invalid file descriptor: %d\n", fd);
exit(1);
}
uwsgi_add_safe_fd(fd);
}
void uwsgi_opt_set_int(char *opt, char *value, void *key) {
int *ptr = (int *) key;
@@ -3883,13 +3919,6 @@ void uwsgi_opt_load_yml(char *opt, char *filename, void *none) {
}
#endif
#ifdef UWSGI_SQLITE3
void uwsgi_opt_load_sqlite3(char *opt, char *filename, void *none) {
config_magic_table_fill(filename, uwsgi.magic_table);
uwsgi_sqlite3_config(filename, uwsgi.magic_table);
}
#endif
#ifdef UWSGI_JSON
void uwsgi_opt_load_json(char *opt, char *filename, void *none) {
config_magic_table_fill(filename, uwsgi.magic_table);
@@ -3897,12 +3926,6 @@ void uwsgi_opt_load_json(char *opt, char *filename, void *none) {
}
#endif
#ifdef UWSGI_LDAP
void uwsgi_opt_load_ldap(char *opt, char *url, void *none) {
uwsgi_ldap_config(url);
}
#endif
void uwsgi_opt_add_custom_option(char *opt, char *value, void *none) {
struct uwsgi_custom_option *uco = uwsgi.custom_options, *old_uco;
+49 -14
View File
@@ -12,6 +12,36 @@ int uwsgi_response_add_content_length(struct wsgi_request *wsgi_req, uint64_t cl
return uwsgi_response_add_header(wsgi_req, "Content-Length", 14, buf, ret);
}
int uwsgi_response_add_expires(struct wsgi_request *wsgi_req, uint64_t t) {
// 30+1
char expires[31];
int len = uwsgi_http_date((time_t) t, expires);
if (!len) {
wsgi_req->write_errors++;
return -1;
}
return uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, len);
}
int uwsgi_response_add_content_range(struct wsgi_request *wsgi_req, uint64_t start, uint64_t end, uint64_t cl) {
char buf[6+(sizeof(UMAX64_STR)*3)+4];
if (end == 0) {
end = cl-1;
}
int ret = snprintf(buf, 6+(sizeof(UMAX64_STR)*3)+4, "bytes %llu-%llu/%llu", (unsigned long long) start, (unsigned long long) end, (unsigned long long) cl);
if (ret <= 0 || ret > (int) (6+(sizeof(UMAX64_STR)*3)+4)) {
wsgi_req->write_errors++;
return -1;
}
return uwsgi_response_add_header(wsgi_req, "Content-Range", 13, buf, ret);
}
int uwsgi_response_prepare_headers_int(struct wsgi_request *wsgi_req, int status) {
char status_str[11];
uwsgi_num2str2(status, status_str);
return uwsgi_response_prepare_headers(wsgi_req, status_str, 3);
}
// status could be NNN or NNN message
int uwsgi_response_prepare_headers(struct wsgi_request *wsgi_req, char *status, uint16_t status_len) {
@@ -146,7 +176,8 @@ int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_
if (wsgi_req->write_errors) return -1;
if (!wsgi_req->headers_sent) {
// do not commit headers until a response_buffer is available
if (!wsgi_req->response_buffer && !wsgi_req->headers_sent) {
int ret = uwsgi_response_write_headers_do(wsgi_req);
if (ret == UWSGI_OK) goto sendbody;
if (ret == UWSGI_AGAIN) return UWSGI_AGAIN;
@@ -157,6 +188,14 @@ int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_
sendbody:
if (len == 0) return UWSGI_OK;
if (wsgi_req->response_buffer) {
if (uwsgi_buffer_append(wsgi_req->response_buffer, buf, len)) {
wsgi_req->write_errors++;
return -1;
}
return UWSGI_OK;
}
for(;;) {
int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
@@ -183,18 +222,6 @@ sendbody:
// reset for the next write
wsgi_req->write_pos = 0;
// now we need to check if the chunk must be stored
if (wsgi_req->cache_it) {
if (!wsgi_req->cached_response) {
wsgi_req->cached_response = uwsgi_buffer_new(len);
}
// if we are unable to append the buffer, we just stop caching it
if (uwsgi_buffer_append(wsgi_req->cached_response, buf, len)) {
uwsgi_buffer_destroy(wsgi_req->cache_it);
wsgi_req->cache_it = NULL;
}
}
return UWSGI_OK;
}
@@ -204,7 +231,10 @@ int uwsgi_response_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t pos
if (fd == wsgi_req->sendfile_fd) can_close = 0;
if (wsgi_req->write_errors) return -1;
if (wsgi_req->write_errors) {
if (can_close) close(fd);
return -1;
}
if (!wsgi_req->headers_sent) {
int ret = uwsgi_response_write_headers_do(wsgi_req);
@@ -225,6 +255,10 @@ sendfile:
if (can_close) close(fd);
return -1;
}
if (pos >= (size_t)st.st_size) {
if (can_close) close(fd);
return UWSGI_OK;
}
len = st.st_size;
}
@@ -276,6 +310,7 @@ sendfile:
if (ret == 0) {
uwsgi_log("uwsgi_response_sendfile_do() TIMEOUT !!!\n");
wsgi_req->write_errors++;
if (can_close) close(fd);
return -1;
}
}
+32
View File
@@ -1,5 +1,37 @@
#include <uwsgi.h>
static char gzheader[10] = { 0x1f, 0x8b, Z_DEFLATED, 0, 0, 0, 0, 0, 0, 3 };
struct uwsgi_buffer *uwsgi_gzip(char *buf, size_t len) {
z_stream z;
struct uwsgi_buffer *ub = NULL;
uint32_t gzip_crc32 = 0;
char *gzipped = NULL;
char *gzipped0 = NULL;
size_t dlen = 0;
size_t dlen0 = 0;
uwsgi_crc32(&gzip_crc32, NULL, 0);
if (uwsgi_deflate_init(&z, NULL, 0)) return NULL;
uwsgi_crc32(&gzip_crc32, buf, len);
gzipped = uwsgi_deflate(&z, buf, len, &dlen);
if (!gzipped) goto end;
gzipped0 = uwsgi_deflate(&z, NULL, 0, &dlen0);
if (!gzipped0) goto end;
ub = uwsgi_buffer_new(10 + dlen + dlen0 + 8);
if (uwsgi_buffer_append(ub, gzheader, 10)) goto end;
if (uwsgi_buffer_append(ub, gzipped, dlen)) goto end;
if (uwsgi_buffer_append(ub, gzipped0, dlen0)) goto end;
if (uwsgi_buffer_u32le(ub, gzip_crc32)) goto end;
if (uwsgi_buffer_u32le(ub, len)) goto end;
end:
if (gzipped) free(gzipped);
if (gzipped0) free(gzipped0);
deflateEnd(&z);
return ub;
}
int uwsgi_deflate_init(z_stream *z, char *dict, size_t dict_len) {
z->zalloc = Z_NULL;
-1356
View File
File diff suppressed because it is too large Load Diff
-3
View File
@@ -1,3 +0,0 @@
ngx_addon_name=ngx_http_uwsgi_module
HTTP_MODULES="$HTTP_MODULES ngx_http_uwsgi_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_uwsgi_module.c"
File diff suppressed because it is too large Load Diff
-16
View File
@@ -1,16 +0,0 @@
uwsgi_param QUERY_STRING $query_string;
uwsgi_param REQUEST_METHOD $request_method;
uwsgi_param CONTENT_TYPE $content_type;
uwsgi_param CONTENT_LENGTH $content_length;
uwsgi_param REQUEST_URI $request_uri;
uwsgi_param PATH_INFO $document_uri;
uwsgi_param DOCUMENT_ROOT $document_root;
uwsgi_param SERVER_PROTOCOL $server_protocol;
uwsgi_param REMOTE_ADDR $remote_addr;
uwsgi_param REMOTE_PORT $remote_port;
uwsgi_param SERVER_ADDR $server_addr;
uwsgi_param SERVER_PORT $server_port;
uwsgi_param SERVER_NAME $server_name;
+9 -5
View File
@@ -40,7 +40,7 @@ static void cache_simple_command(char *key, uint16_t keylen, char *val, uint16_t
if (vallen > 0) {
if (!uwsgi_strncmp(key, keylen, "key", 3)) {
uint64_t vallen = 0;
char *value = uwsgi_cache_magic_get(val, vallen, &vallen, NULL);
char *value = uwsgi_cache_magic_get(val, vallen, &vallen, NULL, NULL);
if (value) {
uwsgi_response_write_body_do(wsgi_req, value, vallen);
free(value);
@@ -49,7 +49,7 @@ static void cache_simple_command(char *key, uint16_t keylen, char *val, uint16_t
}
else if (!uwsgi_strncmp(key, keylen, "get", 3)) {
uint64_t vallen = 0;
char *value = uwsgi_cache_magic_get(val, vallen, &vallen, NULL);
char *value = uwsgi_cache_magic_get(val, vallen, &vallen, NULL, NULL);
if (value) {
uwsgi_response_write_body_do(wsgi_req, value, vallen);
free(value);
@@ -77,8 +77,9 @@ static void manage_magic_context(struct wsgi_request *wsgi_req, struct uwsgi_cac
// cache get
if (!uwsgi_strncmp(ucmc->cmd, ucmc->cmd_len, "get", 3)) {
uint64_t vallen = 0;
uint64_t expires = 0;
uwsgi_rlock(uc->lock);
char *value = uwsgi_cache_get2(uc, ucmc->key, ucmc->key_len, &vallen);
char *value = uwsgi_cache_get3(uc, ucmc->key, ucmc->key_len, &vallen, &expires);
if (!value) {
uwsgi_rwunlock(uc->lock);
return;
@@ -88,6 +89,9 @@ static void manage_magic_context(struct wsgi_request *wsgi_req, struct uwsgi_cac
ub->pos = 4;
if (uwsgi_buffer_append_keyval(ub, "status", 6, "ok", 2)) goto error;
if (uwsgi_buffer_append_keynum(ub, "size", 4, vallen)) goto error;
if (expires) {
if (uwsgi_buffer_append_keynum(ub, "expires", 7, expires)) goto error;
}
if (uwsgi_buffer_set_uh(ub, 111, 17)) goto error;
if (uwsgi_buffer_append(ub, value, vallen)) goto error;
// unlock !!!
@@ -205,7 +209,7 @@ static int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
case 0:
// get
if (wsgi_req->uh->pktsize > 0) {
value = uwsgi_cache_magic_get(wsgi_req->buffer, wsgi_req->uh->pktsize, &vallen, NULL);
value = uwsgi_cache_magic_get(wsgi_req->buffer, wsgi_req->uh->pktsize, &vallen, NULL, NULL);
if (value) {
wsgi_req->uh->pktsize = vallen;
if (uwsgi_response_write_body_do(wsgi_req, (char *)&wsgi_req->uh, 4)) { free(value) ; return -1;}
@@ -242,7 +246,7 @@ static int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
case 5:
// get (uwsgi + stream)
if (wsgi_req->uh->pktsize > 0) {
value = uwsgi_cache_magic_get(wsgi_req->buffer, wsgi_req->uh->pktsize, &vallen, NULL);
value = uwsgi_cache_magic_get(wsgi_req->buffer, wsgi_req->uh->pktsize, &vallen, NULL, NULL);
if (value) {
wsgi_req->uh->pktsize = 0;
wsgi_req->uh->modifier2 = 1;
+52 -4
View File
@@ -35,6 +35,10 @@ struct uwsgi_carbon {
char *hostname_dot_replacement;
char *hostname;
int resolve_hostname;
char *idle_avg;
int push_avg;
int zero_avg;
uint64_t last_requests;
struct uwsgi_stats_pusher *pusher;
} u_carbon;
@@ -50,6 +54,7 @@ static struct uwsgi_option carbon_options[] = {
{"carbon-hostname-dots", required_argument, 0, "set char to use as a replacement for dots in hostname (dots are not replaced by default)", uwsgi_opt_set_str, &u_carbon.hostname_dot_replacement, 0},
{"carbon-name-resolve", no_argument, 0, "allow using hostname as carbon server address (default disabled)", uwsgi_opt_true, &u_carbon.resolve_hostname, 0},
{"carbon-resolve-names", no_argument, 0, "allow using hostname as carbon server address (default disabled)", uwsgi_opt_true, &u_carbon.resolve_hostname, 0},
{"carbon-idle-avg", required_argument, 0, "average values source during idle period (no requests), can be \"last\", \"zero\", \"none\" (default is last)", uwsgi_opt_set_str, &u_carbon.idle_avg, 0},
{0, 0, 0, 0, 0, 0, 0},
};
@@ -121,6 +126,22 @@ static void carbon_post_init() {
}
}
u_carbon.push_avg = 1;
u_carbon.zero_avg = 0;
if (!u_carbon.idle_avg) {
u_carbon.idle_avg = "last";
}
else if (!strcmp(u_carbon.idle_avg, "zero")) {
u_carbon.zero_avg = 1;
}
else if (!strcmp(u_carbon.idle_avg, "none")) {
u_carbon.push_avg = 0;
}
else if (strcmp(u_carbon.idle_avg, "last")) {
uwsgi_log("[carbon] invalid value for carbon-idle-avg: \"%s\"\n", u_carbon.idle_avg);
exit(1);
}
if (!u_carbon.last_busyness_values) {
u_carbon.last_busyness_values = uwsgi_calloc(sizeof(unsigned long long) * uwsgi.numproc);
}
@@ -237,6 +258,8 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
unsigned long long worker_busyness = 0;
unsigned long long total_harakiri = 0;
int do_avg_push;
wok = carbon_write(fd, "%s%s.%s.requests %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) uwsgi.workers[0].requests, (unsigned long long) now);
if (!wok) goto clear;
@@ -287,8 +310,19 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
if (!wok) goto clear;
}
wok = carbon_write(fd, "%s%s.%s.worker%d.avg_rt %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) avg_rt, (unsigned long long) now);
if (!wok) goto clear;
do_avg_push = 1;
if (!u_carbon.last_requests || u_carbon.last_requests == uwsgi.workers[0].requests) {
if (!u_carbon.push_avg) {
do_avg_push = 0;
}
else if (u_carbon.zero_avg) {
avg_rt = 0;
}
}
if (do_avg_push) {
wok = carbon_write(fd, "%s%s.%s.worker%d.avg_rt %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) avg_rt, (unsigned long long) now);
if (!wok) goto clear;
}
wok = carbon_write(fd, "%s%s.%s.worker%d.tx %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].tx, (unsigned long long) now);
if (!wok) goto clear;
@@ -309,8 +343,20 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
if (!wok) goto clear;
}
wok = carbon_write(fd, "%s%s.%s.avg_rt %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) (active_workers ? total_avg_rt / active_workers : 0), (unsigned long long) now);
if (!wok) goto clear;
do_avg_push = 1;
uint64_t c_total_avg_rt = (active_workers ? total_avg_rt / active_workers : 0);
if (!u_carbon.last_requests || u_carbon.last_requests == uwsgi.workers[0].requests) {
if (!u_carbon.push_avg) {
do_avg_push = 0;
}
else if (u_carbon.zero_avg) {
c_total_avg_rt = 0;
}
}
if (do_avg_push) {
wok = carbon_write(fd, "%s%s.%s.avg_rt %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) c_total_avg_rt, (unsigned long long) now);
if (!wok) goto clear;
}
wok = carbon_write(fd, "%s%s.%s.tx %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) total_tx, (unsigned long long) now);
if (!wok) goto clear;
@@ -338,6 +384,8 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
usl->healthy = 1;
usl->errors = 0;
u_carbon.last_requests = uwsgi.workers[0].requests;
clear:
close(fd);
nxt:
+4 -3
View File
@@ -701,7 +701,8 @@ void uwsgi_corerouter_loop(int id, void *data) {
if (ucr->use_cache) {
ucr->cache = uwsgi_cache_by_name(ucr->use_cache);
if (!ucr->cache) {
uwsgi_log("unable to find cache \"%s\"\n", ucr->use_cache);
uwsgi_log("!!! unable to find cache \"%s\" !!!\n", ucr->use_cache);
exit(1);
}
ucr->mapper = uwsgi_cr_map_use_cache;
}
@@ -899,7 +900,7 @@ int uwsgi_corerouter_init(struct uwsgi_corerouter *ucr) {
if (ucr->has_sockets) {
if (ucr->use_cache && !uwsgi.cache_max_items) {
if (ucr->use_cache && !uwsgi.caches) {
uwsgi_log("you need to create a uwsgi cache to use the %s (add --cache <n>)\n", ucr->name);
exit(1);
}
@@ -945,7 +946,7 @@ void corerouter_send_stats(struct uwsgi_corerouter *ucr) {
int client_fd = accept(ucr->cr_stats_server, (struct sockaddr *) &client_src, &client_src_len);
if (client_fd < 0) {
uwsgi_error("accept()");
uwsgi_error("corerouter_send_stats()/accept()");
return;
}
+1 -1
View File
@@ -173,7 +173,7 @@ void uwsgi_corerouter_manage_subscription(struct uwsgi_corerouter *ucr, int id,
continue;
if (!strcmp(ushared->gateways[i].name, ucr->name)) {
if (send(ushared->gateways[i].internal_subscription_pipe[0], bbuf, len, 0) != len) {
uwsgi_error("send()");
uwsgi_error("uwsgi_corerouter_manage_subscription()/send()");
}
}
}
+1 -1
View File
@@ -171,7 +171,7 @@ end:
}
XS(XS_coroae_sighandler) {
int sigfd = (int) XSANY.any_ptr;
int sigfd = (long) XSANY.any_ptr;
uwsgi_receive_signal(sigfd, "worker", uwsgi.mywid);
}
+58
View File
@@ -0,0 +1,58 @@
#include <uwsgi.h>
#include <curl/curl.h>
extern struct uwsgi_server uwsgi;
static void curl_cron_func(struct uwsgi_cron *uc, time_t now) {
CURL *curl = curl_easy_init();
// ARGH !!!
if (!curl) return;
curl_easy_setopt(curl, CURLOPT_URL, uc->command);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
// use 1 minute as the cron resolution
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60);
uwsgi_log("[uwsgi-curl-cron] requesting %s\n", uc->command);
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK) {
uwsgi_log("[uwsgi-curl-cron] curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
}
curl_easy_cleanup(curl);
}
static void uwsgi_opt_add_cron_curl(char *opt, char *value, void *foobar) {
struct uwsgi_cron *uc = uwsgi_cron_add(value);
uc->func = curl_cron_func;
}
#ifdef UWSGI_SSL
static void uwsgi_opt_add_legion_cron_curl(char *opt, char *value, void *foobar) {
char *space = strchr(value, ' ');
if (!space) {
uwsgi_log("invalid %s syntax, must be prefixed with a legion name\n", opt);
exit(1);
}
char *legion = uwsgi_concat2n(value, space-value, "", 0);
struct uwsgi_cron *uc = uwsgi_cron_add(space+1);
uc->legion = legion;
uc->func = curl_cron_func;
}
#endif
static struct uwsgi_option curl_cron_options[] = {
{"curl-cron", required_argument, 0, "add a cron task invoking the specified url via CURL", uwsgi_opt_add_cron_curl, NULL, UWSGI_OPT_MASTER},
{"cron-curl", required_argument, 0, "add a cron task invoking the specified url via CURL", uwsgi_opt_add_cron_curl, NULL, UWSGI_OPT_MASTER},
#ifdef UWSGI_SSL
{"legion-curl-cron", required_argument, 0, "add a cron task invoking the specified url via CURL runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron_curl, NULL, UWSGI_OPT_MASTER},
{"legion-cron-curl", required_argument, 0, "add a cron task invoking the specified url via CURL runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron_curl, NULL, UWSGI_OPT_MASTER},
{"curl-cron-legion", required_argument, 0, "add a cron task invoking the specified url via CURL runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron_curl, NULL, UWSGI_OPT_MASTER},
{"cron-curl-legion", required_argument, 0, "add a cron task invoking the specified url via CURL runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron_curl, NULL, UWSGI_OPT_MASTER},
#endif
{ 0, 0, 0, 0, 0, 0, 0},
};
struct uwsgi_plugin curl_cron_plugin = {
.name = "curl_cron",
.options = curl_cron_options,
};
+6
View File
@@ -0,0 +1,6 @@
NAME='curl_cron'
CFLAGS = []
LDFLAGS = []
LIBS = ['-lcurl']
GCC_LIST = ['curl_cron']
+1 -1
View File
@@ -150,7 +150,7 @@ func CacheGet(key string, cache string) []byte {
var p []byte
c_value := C.uwsgi_cache_magic_get(k, C.uint16_t(kl), &vl, c)
c_value := C.uwsgi_cache_magic_get(k, C.uint16_t(kl), &vl, (*C.uint64_t)(nil), c)
if c_value != nil {
p = C.GoBytes((unsafe.Pointer)(c_value), C.int(vl))
+17 -8
View File
@@ -19,6 +19,8 @@ struct uwsgi_gridfs_mountpoint {
uint16_t itemname_len;
char *skip_slash;
uint16_t prefix_len;
char *username;
char *password;
};
struct uwsgi_gridfs {
@@ -40,6 +42,15 @@ static void uwsgi_gridfs_do(struct wsgi_request *wsgi_req, struct uwsgi_gridfs_m
try {
mongo::scoped_ptr<mongo::ScopedDbConnection> conn( mongo::ScopedDbConnection::getScopedDbConnection(ugm->server, ugm->timeout) );
try {
if (ugm->username && ugm->password) {
std::string errmsg;
if ((*conn).conn().auth(ugm->db, ugm->username, ugm->password, errmsg)) {
uwsgi_log("[uwsgi-gridfs]: %s\n", errmsg.c_str());
(*conn).done();
uwsgi_403(wsgi_req);
return;
}
}
mongo::GridFS gridfs((*conn).conn(), ugm->db);
mongo::GridFile gfile = gridfs.findFile(itemname);
if (need_free) {
@@ -131,6 +142,8 @@ static struct uwsgi_gridfs_mountpoint *uwsgi_gridfs_add_mountpoint(char *arg, si
"etag", &ugm->etag,
"itemname", &ugm->itemname,
"item", &ugm->itemname,
"username", &ugm->username,
"password", &ugm->password,
NULL)) {
uwsgi_log("invalid gridfs mountpoint syntax\n");
free(ugm);
@@ -184,14 +197,7 @@ extern "C" int uwsgi_gridfs_request(struct wsgi_request *wsgi_req) {
return -1;
}
if (wsgi_req->appid_len == 0) {
if (!uwsgi.ignore_script_name) {
wsgi_req->appid = wsgi_req->script_name;
wsgi_req->appid_len = wsgi_req->script_name_len;
}
}
wsgi_req->app_id = uwsgi_get_app_id(wsgi_req->appid, wsgi_req->appid_len, gridfs_plugin.modifier1);
wsgi_req->app_id = uwsgi_get_app_id(wsgi_req, wsgi_req->appid, wsgi_req->appid_len, gridfs_plugin.modifier1);
if (ugridfs.debug) {
uwsgi_log("[uwsgi-gridfs-debug] app_id = %d\n", wsgi_req->app_id);
}
@@ -225,6 +231,9 @@ extern "C" int uwsgi_gridfs_request(struct wsgi_request *wsgi_req) {
extern "C" void uwsgi_gridfs_mount() {
if (!uwsgi.skip_atexit) {
uwsgi_log("*** WARNING libmongoclient could have a bug with atexit() hooks, if you get segfault on end/reload, add --skip-atexit ***\n");
}
struct uwsgi_string_list *usl = ugridfs.mountpoints;
while(usl) {
if (uwsgi_apps_cnt >= uwsgi.max_apps) {
+13 -8
View File
@@ -90,31 +90,35 @@ int http_add_uwsgi_header(struct corerouter_peer *peer, char *hh, uint16_t hhlen
if (!keylen)
return -1;
if (!uwsgi_strncmp("HOST", 4, hh, keylen)) {
peer->key = val;
peer->key_len = vallen;
}
else if (hr->websockets) {
if (hr->websockets) {
if (!uwsgi_strncmp("UPGRADE", 7, hh, keylen)) {
if (!uwsgi_strnicmp(val, vallen, "websocket", 9)) {
hr->websockets++;
}
goto done;
}
else if (!uwsgi_strncmp("CONNECTION", 10, hh, keylen)) {
if (!uwsgi_strnicmp(val, vallen, "Upgrade", 7)) {
hr->websockets++;
}
goto done;
}
else if (!uwsgi_strncmp("SEC_WEBSOCKET_VERSION", 21, hh, keylen)) {
hr->websockets++;
hr->websockets++;
goto done;
}
else if (!uwsgi_strncmp("SEC_WEBSOCKET_KEY", 17, hh, keylen)) {
hr->websocket_key = val;
hr->websocket_key_len = vallen;
goto done;
}
}
if (!uwsgi_strncmp("HOST", 4, hh, keylen)) {
peer->key = val;
peer->key_len = vallen;
}
else if (!uwsgi_strncmp("CONTENT_LENGTH", 14, hh, keylen)) {
hr->content_length = uwsgi_str_num(val, vallen);
hr->session.can_keepalive = 0;
@@ -139,12 +143,13 @@ int http_add_uwsgi_header(struct corerouter_peer *peer, char *hh, uint16_t hhlen
}
#endif
done:
if (uwsgi_strncmp("CONTENT_TYPE", 12, hh, keylen) && uwsgi_strncmp("CONTENT_LENGTH", 14, hh, keylen)) {
keylen += 5;
prefix = 1;
}
if (uwsgi_buffer_u16le(out, keylen)) return -1;
if (prefix) {
+3 -3
View File
@@ -41,7 +41,7 @@ JNIEXPORT void JNICALL uwsgi_jvm_api_register_signal(JNIEnv *env, jclass c, jint
JNIEXPORT void JNICALL uwsgi_jvm_api_register_rpc(JNIEnv *env, jclass c, jstring name, jobject func) {
// no need to release it
char *n = uwsgi_jvm_str2c(name);
if (uwsgi_register_rpc(n, jvm_plugin.modifier1, 0, uwsgi_jvm_ref(func))) {
if (uwsgi_register_rpc(n, &jvm_plugin, 0, uwsgi_jvm_ref(func))) {
uwsgi_jvm_throw("unable to register rpc function");
}
}
@@ -79,7 +79,7 @@ JNIEXPORT jobject JNICALL uwsgi_jvm_api_cache_get(JNIEnv *env, jclass c, jstring
size_t keylen = uwsgi_jvm_strlen(jkey);
char *key = uwsgi_jvm_str2c(jkey);
uint64_t vallen = 0;
char *value = uwsgi_cache_magic_get(key, keylen, &vallen, NULL);
char *value = uwsgi_cache_magic_get(key, keylen, &vallen, NULL, NULL);
uwsgi_jvm_release_chars(jkey, key);
if (value) {
jobject o = uwsgi_jvm_bytearray(value, vallen);
@@ -99,7 +99,7 @@ JNIEXPORT jobject JNICALL uwsgi_jvm_api_cache_get_name(JNIEnv *env, jclass c, js
char *key = uwsgi_jvm_str2c(jkey);
char *cache = uwsgi_jvm_str2c(jcache);
uint64_t vallen = 0;
char *value = uwsgi_cache_magic_get(key, keylen, &vallen, cache);
char *value = uwsgi_cache_magic_get(key, keylen, &vallen, NULL, cache);
uwsgi_jvm_release_chars(jkey, key);
uwsgi_jvm_release_chars(jcache, cache);
if (value) {
+29 -27
View File
@@ -1,6 +1,4 @@
#ifdef UWSGI_LDAP
#include "uwsgi.h"
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
@@ -14,7 +12,22 @@ extern struct uwsgi_server uwsgi;
#define ldap_unbind_ext_s ldap_unbind_ext
#endif
void ldap2uwsgi(char *ldapname, char *uwsginame) {
static void uwsgi_opt_ldap_dump(char *, char *, void *);
static void uwsgi_opt_ldap_dump_ldif(char *, char *, void *);
static void uwsgi_ldap_config(char *);
static void uwsgi_opt_load_ldap(char *opt, char *url, void *none) {
uwsgi_ldap_config(url);
}
static struct uwsgi_option uwsgi_ldap_options[] = {
{"ldap", required_argument, 0, "load configuration from ldap server", uwsgi_opt_load_ldap, NULL, UWSGI_OPT_IMMEDIATE},
{"ldap-schema", no_argument, 0, "dump uWSGI ldap schema", uwsgi_opt_ldap_dump, NULL, UWSGI_OPT_IMMEDIATE},
{"ldap-schema-ldif", no_argument, 0, "dump uWSGI ldap schema in ldif format", uwsgi_opt_ldap_dump_ldif, NULL, UWSGI_OPT_IMMEDIATE},
{0, 0, 0, 0, 0, 0, 0},
};
static void ldap2uwsgi(char *ldapname, char *uwsginame) {
char *ptr = uwsginame;
int i;
@@ -32,7 +45,7 @@ void ldap2uwsgi(char *ldapname, char *uwsginame) {
*ptr++ = 0;
}
int calc_ldap_name(char *name) {
static int calc_ldap_name(char *name) {
int i;
int counter = 0;
@@ -52,7 +65,7 @@ struct uwsgi_ldap_entry {
};
void uwsgi_name_to_ldap(char *src, char *dst) {
static void uwsgi_name_to_ldap(char *src, char *dst) {
int i;
char *ptr = dst;
@@ -77,22 +90,7 @@ void uwsgi_name_to_ldap(char *src, char *dst) {
}
struct uwsgi_ldap_entry *get_ldap_by_num(struct uwsgi_ldap_entry *root, int num, int count) {
int i;
struct uwsgi_ldap_entry *ule;
for (i = 0; i < count; i++) {
ule = &root[i];
if (ule->num == num) {
return ule;
}
}
return NULL;
}
struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *name, int count) {
static struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *name, int count) {
int i;
struct uwsgi_ldap_entry *ule;
@@ -106,7 +104,7 @@ struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *
return NULL;
}
struct uwsgi_ldap_entry *get_ldap_names(int *count) {
static struct uwsgi_ldap_entry *get_ldap_names(int *count) {
struct uwsgi_option *op = uwsgi.options;
struct uwsgi_ldap_entry *ule, *entry;
@@ -139,7 +137,7 @@ next:
return ule;
}
void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
static void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
int i;
int items;
@@ -192,7 +190,7 @@ void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
exit(0);
}
void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
static void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
int i;
int items;
@@ -240,7 +238,7 @@ void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
exit(0);
}
void uwsgi_ldap_config(char *url) {
static void uwsgi_ldap_config(char *url) {
LDAP *ldp;
LDAPMessage *results, *entry;
@@ -367,4 +365,8 @@ void uwsgi_ldap_config(char *url) {
ldap_unbind_ext_s(ldp, NULL, NULL);
}
#endif
struct uwsgi_plugin ldap_plugin = {
.name = "ldap",
.options = uwsgi_ldap_options,
};
+7
View File
@@ -0,0 +1,7 @@
NAME='ldap'
CFLAGS = []
LDFLAGS = []
LIBS = ['-lldap']
GCC_LIST = ['ldap']
@@ -0,0 +1,71 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
static int legion_action_cache_fetch_from_legion(struct uwsgi_legion *ul, char *arg) {
uwsgi_log("[legion-cache-fetch] getting cache '%s' dump from legion '%s' nodes\n", arg, ul->legion);
struct uwsgi_cache *uc = uwsgi_cache_by_name(arg);
if (!uc) {
uwsgi_log("[legion-cache-fetch] cannot sync, cache '%s' not found\n", arg);
return 1;
}
struct uwsgi_string_list *dump_from_nodes = NULL;
uwsgi_rlock(ul->lock);
struct uwsgi_legion_node *legion_nodes = ul->nodes_head;
while (legion_nodes) {
char *dump_socket = NULL;
if (uwsgi_kvlist_parse(legion_nodes->scroll, legion_nodes->scroll_len, ',', '=',
"dump-socket", &dump_socket,
NULL)) {
uwsgi_log("[legion-cache-fetch] cannot sync from %.*s, cache socket address not found in legion scroll: %.*s\n",
legion_nodes->name_len, legion_nodes->name, legion_nodes->scroll_len, legion_nodes->scroll);
}
else {
if (dump_socket) {
uwsgi_string_new_list(&dump_from_nodes, dump_socket);
}
else {
uwsgi_log("[legion-cache-fetch] cannot sync from %.*s, cache socket address not found in legion scroll: %.*s\n",
legion_nodes->name_len, legion_nodes->name, legion_nodes->scroll_len, legion_nodes->scroll);
}
}
legion_nodes = legion_nodes->next;
}
// update uc->sync_nodes list
struct uwsgi_string_list *usl = uc->sync_nodes;
struct uwsgi_string_list *next;
while (usl) {
next = usl->next;
free(usl->value);
free(usl);
usl = next;
}
uwsgi_rwunlock(ul->lock);
uwsgi_rlock(uc->lock);
uc->sync_nodes = dump_from_nodes;
uwsgi_rwunlock(uc->lock);
// call sync
uwsgi_cache_sync_from_nodes(uc);
return 0;
}
static void legion_cache_register() {
uwsgi_legion_action_register("legion-cache-fetch", legion_action_cache_fetch_from_legion);
}
struct uwsgi_plugin legion_cache_fetch_plugin = {
.name = "legion_cache_fetch",
.on_load = legion_cache_register,
};
@@ -0,0 +1,8 @@
NAME = 'legion_cache_fetch'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['legion_cache_fetch']
+54 -5
View File
@@ -1,4 +1,4 @@
#include "../../uwsgi.h"
#include <uwsgi.h>
#include <lua.h>
#include <lualib.h>
@@ -8,17 +8,33 @@ extern struct uwsgi_server uwsgi;
struct uwsgi_lua {
struct lua_State **L;
char *shell;
char *filename;
struct uwsgi_string_list *load;
} ulua;
struct uwsgi_plugin lua_plugin;
#define lca(L, n) ulua_check_args(L, __FUNCTION__, n)
static void uwsgi_opt_luashell(char *opt, char *value, void *foobar) {
uwsgi.honour_stdin = 1;
if (value) {
ulua.shell = value;
}
else {
ulua.shell = "";
}
}
static struct uwsgi_option uwsgi_lua_options[] = {
{"lua", required_argument, 0, "load lua wsapi app", uwsgi_opt_set_str, &ulua.filename, 0},
{"lua-load", required_argument, 0, "load a lua file", uwsgi_opt_add_string_list, &ulua.load, 0},
{"lua-shell", no_argument, 0, "run the lua interactive shell (debug.debug())", uwsgi_opt_luashell, NULL, 0},
{"luashell", no_argument, 0, "run the lua interactive shell (debug.debug())", uwsgi_opt_luashell, NULL, 0},
{0, 0, 0, 0},
@@ -74,7 +90,7 @@ static int uwsgi_api_register_rpc(lua_State *L) {
uwsgi_log("registered function %d in Lua global table\n", func);
lfunc = func;
if (uwsgi_register_rpc((char *)name, 6, 0, (void *) lfunc)) {
if (uwsgi_register_rpc((char *)name, &lua_plugin, 0, (void *) lfunc)) {
lua_pushnil(L);
}
else {
@@ -262,7 +278,7 @@ static int uwsgi_api_cache_get(lua_State *L) {
if (argc > 1) {
cache = lua_tolstring(L, 2, NULL);
}
value = uwsgi_cache_magic_get((char *)key, keylen, &valsize, (char *)cache);
value = uwsgi_cache_magic_get((char *)key, keylen, &valsize, NULL, (char *)cache);
if (value) {
lua_pushlstring(L, value, valsize);
free(value);
@@ -347,6 +363,7 @@ static const luaL_reg uwsgi_api[] = {
{"lock", uwsgi_api_lock},
{"unlock", uwsgi_api_unlock},
{NULL, NULL}
};
@@ -389,13 +406,16 @@ static int uwsgi_lua_init(){
static void uwsgi_lua_app() {
int i;
if (!ulua.filename && !ulua.load) return;
if (!ulua.filename && !ulua.load && !ulua.shell) return;
for(i=0;i<uwsgi.cores;i++) {
ulua.L[i] = luaL_newstate();
luaL_openlibs(ulua.L[i]);
luaL_register(ulua.L[i], "uwsgi", uwsgi_api);
lua_pushstring(ulua.L[i], UWSGI_VERSION);
lua_setfield(ulua.L[i], -2, "version");
struct uwsgi_string_list *usl = ulua.load;
while(usl) {
if (luaL_dofile(ulua.L[i], usl->value)) {
@@ -765,6 +785,33 @@ static void uwsgi_register_lua_features() {
uwsgi_register_configurator(".lua", uwsgi_lua_configurator);
}
static void uwsgi_lua_hijack(void) {
if (ulua.shell && uwsgi.mywid == 1) {
uwsgi.workers[uwsgi.mywid].hijacked = 1;
uwsgi.workers[uwsgi.mywid].hijacked_count++;
// re-map stdin to stdout and stderr if we are logging to a file
if (uwsgi.logfile) {
if (dup2(0, 1) < 0) {
uwsgi_error("dup2()");
}
if (dup2(0, 2) < 0) {
uwsgi_error("dup2()");
}
}
int ret = -1;
// run in the first state
lua_State *L = ulua.L[0];
lua_getglobal(L, "debug");
lua_getfield(L, -1, "debug");
ret = lua_pcall(L, 0, 0, 0);
if (ret == 0) {
exit(UWSGI_QUIET_CODE);
}
exit(0);
}
}
struct uwsgi_plugin lua_plugin = {
@@ -778,6 +825,8 @@ struct uwsgi_plugin lua_plugin = {
.magic = uwsgi_lua_magic,
.signal_handler = uwsgi_lua_signal_handler,
.hijack_worker = uwsgi_lua_hijack,
.code_string = uwsgi_lua_code_string,
.rpc = uwsgi_lua_rpc,
-9
View File
@@ -1,9 +0,0 @@
#include <uwsgi.h>
#include "client/dbclient.h"
extern "C" int uwsgi_mongodb_version() {
// this is only a hack to force the linked to embed libmongoclient.a
mongo::DBClientConnection c;
return 0;
}
-3
View File
@@ -6,9 +6,6 @@ a fake plugin used for preloading mongodb library when only available as static.
*/
int uwsgi_mongodb_version(void);
struct uwsgi_plugin mongodb_plugin = {
.name = "mongodb",
.init = uwsgi_mongodb_version,
};
+3 -3
View File
@@ -1,8 +1,8 @@
NAME='mongodb'
CFLAGS = ['-I/usr/include/mongo','-I/usr/local/include/mongo']
CFLAGS = []
LDFLAGS = []
LIBS = ['-lmongoclient', '-lboost_thread','-lboost_filesystem']
LIBS = ['-Wl,-whole-archive', '-lmongoclient', '-Wl,-no-whole-archive', '-lboost_thread', '-lboost_system', '-lboost_filesystem']
GCC_LIST = ['plugin', 'foobar.cc']
GCC_LIST = ['plugin']
+3 -3
View File
@@ -267,7 +267,7 @@ static MonoArray *uwsgi_mono_method_api_CacheGet(MonoString *key, MonoString *ca
c_cache = mono_string_to_utf8(cache);
}
uint64_t vallen = 0 ;
char *value = uwsgi_cache_magic_get(c_key, c_keylen, &vallen, c_cache);
char *value = uwsgi_cache_magic_get(c_key, c_keylen, &vallen, NULL, c_cache);
if (value) {
MonoArray *ret = mono_array_new(mono_domain_get(), umono.byte_class, vallen);
char *buf = mono_array_addr(ret, char, 0);
@@ -540,7 +540,7 @@ static int uwsgi_mono_request(struct wsgi_request *wsgi_req) {
key_len = 0;
}
wsgi_req->app_id = uwsgi_get_app_id(key, key_len, mono_plugin.modifier1);
wsgi_req->app_id = uwsgi_get_app_id(NULL, key, key_len, mono_plugin.modifier1);
// if it is -1, try to load a dynamic app
if (wsgi_req->app_id == -1) {
if (uwsgi.threads > 1) {
@@ -548,7 +548,7 @@ static int uwsgi_mono_request(struct wsgi_request *wsgi_req) {
}
// check if the mean time, something changed
wsgi_req->app_id = uwsgi_get_app_id(key, key_len, mono_plugin.modifier1);
wsgi_req->app_id = uwsgi_get_app_id(NULL, key, key_len, mono_plugin.modifier1);
if (wsgi_req->app_id == -1) {
wsgi_req->app_id = uwsgi_mono_create_app(key, key_len, key, key_len, 0);
+1 -1
View File
@@ -309,7 +309,7 @@ PHP_FUNCTION(uwsgi_cache_get) {
RETURN_NULL();
}
char *value = uwsgi_cache_magic_get(key, keylen, &valsize, cache);
char *value = uwsgi_cache_magic_get(key, keylen, &valsize, NULL, cache);
if (value) {
char *ret = estrndup(value, valsize);
free(value);
+1 -1
View File
@@ -17,7 +17,7 @@ try:
except:
pass
CFLAGS = [os.popen(PHPPATH + ' --includes').read().rstrip(), '-Wno-error=sign-compare']
CFLAGS = [os.popen(PHPPATH + ' --includes').read().rstrip(), '-Wno-sign-compare']
LDFLAGS = os.popen(PHPPATH + ' --ldflags').read().rstrip().split()
if ld_run_path:
-90
View File
@@ -1,90 +0,0 @@
#include "../../uwsgi.h"
extern struct uwsgi_server uwsgi;
int connect_prober_callback(int interesting_fd, struct uwsgi_signal_probe *up) {
// is this a timeout event ?
if (interesting_fd == -1) {
// am i wating for something ?
if (up->fd != -1) {
if (up->cycles > (uint64_t) up->timeout) {
// reset the cycle
up->cycles = 0;
close(up->fd);
up->fd = -1;
// state = NOOP
up->state = 0;
// avoid duplicated events
if (!up->bad) {
up->bad = 1;
return 1;
}
}
}
// ok register a new event
else {
if ((up->cycles % up->freq) == 0) {
up->fd = uwsgi_connect(up->args, -1, 1);
if (up->fd != -1) {
// status = CONNECTING
up->state = 1;
event_queue_add_fd_write(uwsgi.master_queue, up->fd);
return 0;
}
// signal the bad event (if not already bad)
if (!up->bad) {
up->bad = 1;
return 1;
}
}
}
}
else if (up->fd != -1) {
// is this event for me ?
if (interesting_fd == up->fd) {
// uselsess here (we have only one state), only to show a good practice
// check the state
if (up->state == 1) {
if (uwsgi_is_bad_connection(up->fd)) {
// signal the bad connection (if needed)
up->cycles = 0;
close(up->fd);
up->fd = -1;
// state = NOOP
up->state = 0;
if (!up->bad) {
up->bad = 1;
return 1;
}
return 0;
}
// this is a good connection
up->cycles = 0;
close(up->fd);
up->fd = -1;
// state = NOOP
up->state = 0;
if (up->bad) {
up->bad = 0;
return 1;
}
}
}
}
// default action
return 0;
}
int probeconnect_init() {
uwsgi_probe_register(&uwsgi.probes, "connect", connect_prober_callback);
return 0;
}
struct uwsgi_plugin probeconnect_plugin = {
.init = probeconnect_init,
};
-7
View File
@@ -1,7 +0,0 @@
NAME='probeconnect'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['connectprobe']
-132
View File
@@ -1,132 +0,0 @@
#include "../../uwsgi.h"
#include <libpq-fe.h>
extern struct uwsgi_server uwsgi;
int pg_prober_callback(int, struct uwsgi_signal_probe *);
int probepg_init(void);
int pg_prober_callback(int interesting_fd, struct uwsgi_signal_probe *up) {
// is this a timeout event ?
if (interesting_fd == -1) {
// am i wating for something ?
if (up->fd != -1) {
if (up->cycles > (uint64_t) up->timeout) {
// reset the cycle
up->cycles = 0;
PQfinish((PGconn *) up->data);
up->fd = -1;
// state = NOOP
up->state = 0;
// avoid duplicated events
if (!up->bad) {
up->bad = 1;
return 1;
}
}
}
// ok register a new event
else {
if ((up->cycles % up->freq) == 0) {
up->last_event = event_queue_write();
up->data = (void *) PQconnectStart(up->args);
if (up->data) {
// status = CONNECTING
up->state = PQstatus((PGconn *) up->data);
if (up->state == CONNECTION_BAD)
goto bad;
up->fd = PQsocket((PGconn *) up->data);
event_queue_add_fd_write(uwsgi.master_queue, up->fd);
return 0;
}
bad:
// signal the bad event (if not already bad)
if (!up->bad) {
up->bad = 1;
return 1;
}
}
}
}
else if (up->fd != -1) {
// is this event for me ?
if (interesting_fd == up->fd) {
// check the state
up->state = PQstatus((PGconn *) up->data);
if (up->state == CONNECTION_BAD) {
// signal the bad connection (if needed)
up->cycles = 0;
PQfinish((PGconn *) up->data);
up->fd = -1;
up->state = 0;
if (!up->bad) {
up->bad = 1;
return 1;
}
return 0;
}
else if (up->state == CONNECTION_OK) {
up->cycles = 0;
PQfinish((PGconn *) up->data);
up->fd = -1;
// state = NOOP
up->state = 0;
if (up->bad) {
up->bad = 0;
return 1;
}
}
// still wait...
else {
PostgresPollingStatusType wait_type = PQconnectPoll((PGconn *) up->data);
// the connection is good
if (wait_type == PGRES_POLLING_ACTIVE || wait_type == PGRES_POLLING_FAILED || wait_type == PGRES_POLLING_OK) {
if (wait_type == PGRES_POLLING_ACTIVE)
wait_type = PQconnectPoll((PGconn *) up->data);
up->cycles = 0;
up->fd = -1;
// state = NOOP
up->state = 0;
PQfinish((PGconn *) up->data);
if (wait_type == PGRES_POLLING_FAILED) {
if (!up->bad) {
up->bad = 1;
return 1;
}
}
else {
if (up->bad) {
up->bad = 0;
return 1;
}
}
}
else if (wait_type == PGRES_POLLING_READING) {
event_queue_del_fd(uwsgi.master_queue, up->fd, up->last_event);
event_queue_add_fd_read(uwsgi.master_queue, up->fd);
up->last_event = event_queue_read();
}
else if (wait_type == PGRES_POLLING_WRITING) {
event_queue_del_fd(uwsgi.master_queue, up->fd, up->last_event);
event_queue_add_fd_write(uwsgi.master_queue, up->fd);
up->last_event = event_queue_write();
}
}
}
}
// default action
return 0;
}
int probepg_init() {
uwsgi_probe_register(&uwsgi.probes, "pg", pg_prober_callback);
return 0;
}
struct uwsgi_plugin probepg_plugin = {
.init = probepg_init,
};
-9
View File
@@ -1,9 +0,0 @@
import os
NAME='probepg'
CFLAGS = os.popen('pg_config --cflags').read().rstrip().split()
CFLAGS.append('-I' + os.popen('pg_config --includedir').read().rstrip())
LDFLAGS = os.popen('pg_config --ldflags').read().rstrip().split()
LIBS = ['-L' + os.popen('pg_config --libdir').read().rstrip(), '-lpq']
GCC_LIST = ['pgprobe']
+38 -2
View File
@@ -394,7 +394,7 @@ int uwsgi_perl_request(struct wsgi_request *wsgi_req) {
return -1;
}
wsgi_req->app_id = uwsgi_get_app_id(wsgi_req->appid, wsgi_req->appid_len, psgi_plugin.modifier1);
wsgi_req->app_id = uwsgi_get_app_id(wsgi_req, wsgi_req->appid, wsgi_req->appid_len, psgi_plugin.modifier1);
// if it is -1, try to load a dynamic app
if (wsgi_req->app_id == -1) {
if (wsgi_req->dynamic) {
@@ -621,7 +621,7 @@ void uwsgi_perl_enable_threads(void) {
#endif
}
int uwsgi_perl_signal_handler(uint8_t sig, void *handler) {
static int uwsgi_perl_signal_handler(uint8_t sig, void *handler) {
int ret = 0;
@@ -688,6 +688,41 @@ realstuff:
}
}
static uint16_t uwsgi_perl_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
int i;
uint16_t ret = 0;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
for(i=0;i<argc;i++) {
XPUSHs( sv_2mortal(newSVpv(argv[i], argvs[i])));
}
PUTBACK;
call_sv( SvRV((SV*)func), G_SCALAR | G_EVAL);
SPAGAIN;
if(SvTRUE(ERRSV)) {
uwsgi_log("[uwsgi-perl error] %s", SvPV_nolen(ERRSV));
}
else {
STRLEN rlen;
SV *response = POPs;
char *value = SvPV(response, rlen );
ret = UMIN(UMAX16, rlen);
memcpy(buffer, value, ret);
}
PUTBACK;
FREETMPS;
LEAVE;
return ret;
}
struct uwsgi_plugin psgi_plugin = {
.name = "psgi",
@@ -700,6 +735,7 @@ struct uwsgi_plugin psgi_plugin = {
.init_thread = uwsgi_perl_init_thread,
.signal_handler = uwsgi_perl_signal_handler,
.rpc = uwsgi_perl_rpc,
.mule = uwsgi_perl_mule,
+17 -1
View File
@@ -136,7 +136,7 @@ XS(XS_cache_get) {
cache = SvPV_nolen(ST(1));
}
char *value = uwsgi_cache_magic_get(key, (uint16_t) keylen, &vallen, cache);
char *value = uwsgi_cache_magic_get(key, (uint16_t) keylen, &vallen, NULL, cache);
if (value) {
ST(0) = newSVpv(value, vallen);
free(value);
@@ -233,6 +233,21 @@ XS(XS_register_signal) {
}
XS(XS_register_rpc) {
dXSARGS;
psgi_check_args(2);
char *name = SvPV_nolen(ST(0));
if (uwsgi_register_rpc(name, &psgi_plugin, 0, (void *) newRV_inc(ST(1)))) {
XSRETURN_NO;
}
XSRETURN_YES;
}
XS(XS_postfork) {
dXSARGS;
@@ -519,6 +534,7 @@ void init_perl_embedded_module() {
psgi_xs(suspend);
psgi_xs(signal);
psgi_xs(register_signal);
psgi_xs(register_rpc);
psgi_xs(signal_wait);
#ifdef UWSGI_SSL
psgi_xs(i_am_the_lord);
+6 -6
View File
@@ -33,12 +33,12 @@ void set_dyn_pyhome(char *home, uint16_t pyhome_len) {
}
// simulate a pythonhome directive
if (uwsgi.wsgi_req->pyhome_len > 0) {
if (uwsgi.wsgi_req->home_len > 0) {
PyObject *venv_path = UWSGI_PYFROMSTRINGSIZE(uwsgi.wsgi_req->pyhome, uwsgi.wsgi_req->pyhome_len);
PyObject *venv_path = UWSGI_PYFROMSTRINGSIZE(uwsgi.wsgi_req->home, uwsgi.wsgi_req->home_len);
#ifdef UWSGI_DEBUG
uwsgi_debug("setting dynamic virtualenv to %.*s\n", uwsgi.wsgi_req->pyhome_len, uwsgi.wsgi_req->pyhome);
uwsgi_debug("setting dynamic virtualenv to %.*s\n", uwsgi.wsgi_req->home_len, uwsgi.wsgi_req->home);
#endif
PyDict_SetItemString(pysys_dict, "prefix", venv_path);
@@ -86,7 +86,7 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
time_t now = uwsgi_now();
if (uwsgi_get_app_id(wsgi_req->appid, wsgi_req->appid_len, -1) != -1) {
if (uwsgi_get_app_id(NULL, wsgi_req->appid, wsgi_req->appid_len, -1) != -1) {
uwsgi_log( "mountpoint %.*s already configured. skip.\n", wsgi_req->appid_len, wsgi_req->appid);
return -1;
}
@@ -177,8 +177,8 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
wi->interpreter = up.main_thread;
}
if (wsgi_req->pyhome_len) {
set_dyn_pyhome(wsgi_req->pyhome, wsgi_req->pyhome_len);
if (wsgi_req->home_len) {
set_dyn_pyhome(wsgi_req->home, wsgi_req->home_len);
}
if (wsgi_req->touch_reload_len > 0 && wsgi_req->touch_reload_len < 0xff) {
+17 -7
View File
@@ -25,7 +25,12 @@ void uwsgi_opt_pythonpath(char *opt, char *value, void *foobar) {
void uwsgi_opt_pyshell(char *opt, char *value, void *foobar) {
uwsgi.honour_stdin = 1;
up.pyshell = 1;
if (value) {
up.pyshell = value;
}
else {
up.pyshell = "";
}
if (!strcmp("pyshell-oneshot", opt)) {
up.pyshell_oneshot = 1;
@@ -127,8 +132,8 @@ struct uwsgi_option uwsgi_python_options[] = {
{"no-site", no_argument, 0, "do not import site module", uwsgi_opt_true, &Py_NoSiteFlag, 0},
#endif
#endif
{"pyshell", no_argument, 0, "run an interactive python shell in the uWSGI environment", uwsgi_opt_pyshell, NULL, 0},
{"pyshell-oneshot", no_argument, 0, "run an interactive python shell in the uWSGI environment (one-shot variant)", uwsgi_opt_pyshell, NULL, 0},
{"pyshell", optional_argument, 0, "run an interactive python shell in the uWSGI environment", uwsgi_opt_pyshell, NULL, 0},
{"pyshell-oneshot", optional_argument, 0, "run an interactive python shell in the uWSGI environment (one-shot variant)", uwsgi_opt_pyshell, NULL, 0},
{"python", required_argument, 0, "run a python script in the uWSGI environment", uwsgi_opt_pyrun, NULL, 0},
{"py", required_argument, 0, "run a python script in the uWSGI environment", uwsgi_opt_pyrun, NULL, 0},
@@ -1688,11 +1693,17 @@ void uwsgi_python_hijack(void) {
}
}
UWSGI_GET_GIL;
PyImport_ImportModule("readline");
int ret = -1;
if (up.pyshell[0] != 0) {
ret = PyRun_SimpleString(up.pyshell);
}
else {
PyImport_ImportModule("readline");
#ifndef UWSGI_PYPY
int ret = PyRun_InteractiveLoop(stdin, "uwsgi");
ret = PyRun_InteractiveLoop(stdin, "uwsgi");
#endif
}
if (up.pyshell_oneshot) {
exit(UWSGI_DE_HIJACKED_CODE);
}
@@ -1700,7 +1711,6 @@ void uwsgi_python_hijack(void) {
if (ret == 0) {
exit(UWSGI_QUIET_CODE);
}
#endif
exit(0);
}
}
+3 -23
View File
@@ -2,6 +2,7 @@
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
extern struct uwsgi_plugin python_plugin;
PyObject *py_uwsgi_signal_wait(PyObject * self, PyObject * args) {
@@ -210,26 +211,6 @@ PyObject *py_uwsgi_add_cron(PyObject * self, PyObject * args) {
}
PyObject *py_uwsgi_add_probe(PyObject * self, PyObject * args) {
uint8_t uwsgi_signal;
int timeout = 0;
int freq = 0;
char *probe, *probe_args;
if (!PyArg_ParseTuple(args, "Bss|ii:add_probe", &uwsgi_signal, &probe, &probe_args, &timeout, &freq)) {
return NULL;
}
if (uwsgi_add_probe(uwsgi_signal, probe, probe_args, timeout, freq))
return PyErr_Format(PyExc_ValueError, "unable to add probe");
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_uwsgi_add_timer(PyObject * self, PyObject * args) {
uint8_t uwsgi_signal;
@@ -414,7 +395,7 @@ PyObject *py_uwsgi_register_rpc(PyObject * self, PyObject * args) {
}
if (uwsgi_register_rpc(name, 0, argc, func)) {
if (uwsgi_register_rpc(name, &python_plugin, argc, func)) {
return PyErr_Format(PyExc_ValueError, "unable to register rpc function");
}
@@ -2444,7 +2425,6 @@ static PyMethodDef uwsgi_advanced_methods[] = {
{"signal_received", py_uwsgi_signal_received, METH_VARARGS, ""},
{"add_file_monitor", py_uwsgi_add_file_monitor, METH_VARARGS, ""},
{"add_timer", py_uwsgi_add_timer, METH_VARARGS, ""},
{"add_probe", py_uwsgi_add_probe, METH_VARARGS, ""},
{"add_rb_timer", py_uwsgi_add_rb_timer, METH_VARARGS, ""},
{"add_cron", py_uwsgi_add_cron, METH_VARARGS, ""},
@@ -2946,7 +2926,7 @@ PyObject *py_uwsgi_cache_get(PyObject * self, PyObject * args) {
uint64_t vallen = 0;
UWSGI_RELEASE_GIL
char *value = uwsgi_cache_magic_get(key, keylen, &vallen, cache);
char *value = uwsgi_cache_magic_get(key, keylen, &vallen, NULL, cache);
UWSGI_GET_GIL
if (value) {
// in python 3.x we return bytes
+1 -1
View File
@@ -106,7 +106,7 @@ struct uwsgi_python {
char *test_module;
int pyshell;
char *pyshell;
int pyshell_oneshot;
+3
View File
@@ -42,6 +42,9 @@ if not 'UWSGI_PYTHON_NOLIB' in os.environ:
if not os.path.exists(libpath):
libpath = '%s/libpython%s.a' % (libdir, version)
LIBS.append(libpath)
# hack for messy linkers/compilers
if '-lutil' in LIBS:
LIBS.append('-lutil')
else:
try:
LDFLAGS.append("-L%s" % sysconfig.get_config_var('LIBDIR'))
+32 -30
View File
@@ -135,11 +135,34 @@ static PyObject *uwsgi_Input_close(uwsgi_Input *self, PyObject *args) {
static PyObject *uwsgi_Input_seek(uwsgi_Input *self, PyObject *args) {
long pos = 0;
int whence = 0;
if (!PyArg_ParseTuple(args, "l:seek", &pos)) {
if (!uwsgi.post_buffering) {
return PyErr_Format(PyExc_IOError, "seeking wsgi.input without post_buffering is IMPOSSIBLE !!!");
}
if (!PyArg_ParseTuple(args, "l|i:seek", &pos, &whence)) {
return NULL;
}
/*
uwsgi_request_body_seek() uses SEEK_SET for positive value and SEEK_CUR for negative
yous hould always try to transform the "pos" value to an absolute position.
*/
// current
if (whence == 1) {
pos += self->wsgi_req->post_pos;
}
// end of stream
if (whence == 2) {
pos += self->wsgi_req->post_cl;
}
if (pos < 0 || pos > (off_t)self->wsgi_req->post_cl) {
return PyErr_Format(PyExc_IOError, "invalid seek position for wsgi.input");
}
uwsgi_request_body_seek(self->wsgi_req, pos);
Py_INCREF(Py_None);
@@ -151,6 +174,12 @@ static PyObject *uwsgi_Input_fileno(uwsgi_Input *self, PyObject *args) {
return PyInt_FromLong(self->wsgi_req->fd);
}
static PyObject *uwsgi_Input_tell(uwsgi_Input *self, PyObject *args) {
return PyLong_FromLong(self->wsgi_req->post_pos);
}
static PyMethodDef uwsgi_Input_methods[] = {
{ "read", (PyCFunction)uwsgi_Input_read, METH_VARARGS, 0 },
{ "readline", (PyCFunction)uwsgi_Input_readline, METH_VARARGS, 0 },
@@ -158,6 +187,7 @@ static PyMethodDef uwsgi_Input_methods[] = {
// add close to allow mod_wsgi compatibility
{ "close", (PyCFunction)uwsgi_Input_close, METH_VARARGS, 0 },
{ "seek", (PyCFunction)uwsgi_Input_seek, METH_VARARGS, 0 },
{ "tell", (PyCFunction)uwsgi_Input_tell, METH_VARARGS, 0 },
{ "fileno", (PyCFunction)uwsgi_Input_fileno, METH_VARARGS, 0 },
{ NULL, NULL}
};
@@ -263,8 +293,6 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
struct uwsgi_app *wi;
int free_appid = 0;
if (wsgi_req->async_status == UWSGI_AGAIN) {
wi = &uwsgi_apps[wsgi_req->app_id];
UWSGI_GET_GIL
@@ -300,29 +328,7 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
return -1;
}
if (wsgi_req->appid_len == 0) {
if (!uwsgi.ignore_script_name) {
wsgi_req->appid = wsgi_req->script_name;
wsgi_req->appid_len = wsgi_req->script_name_len;
}
if (uwsgi.vhost) {
wsgi_req->appid = uwsgi_concat3n(wsgi_req->host, wsgi_req->host_len, "|",1, wsgi_req->script_name, wsgi_req->script_name_len);
wsgi_req->appid_len = wsgi_req->host_len + 1 + wsgi_req->script_name_len;
#ifdef UWSGI_DEBUG
uwsgi_debug("VirtualHost KEY=%.*s\n", wsgi_req->appid_len, wsgi_req->appid);
#endif
free_appid = 1;
}
}
if ( (wsgi_req->app_id = uwsgi_get_app_id(wsgi_req->appid, wsgi_req->appid_len, 0)) == -1) {
wsgi_req->app_id = uwsgi.default_app;
if (uwsgi.no_default_app) {
wsgi_req->app_id = -1;
}
if ( (wsgi_req->app_id = uwsgi_get_app_id(wsgi_req, wsgi_req->appid, wsgi_req->appid_len, 0)) == -1) {
if (wsgi_req->dynamic) {
// this part must be heavy locked in threaded modes
if (uwsgi.threads > 1) {
@@ -343,10 +349,6 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
}
}
if (free_appid) {
free(wsgi_req->appid);
}
if (wsgi_req->app_id == -1) {
uwsgi_500(wsgi_req);
uwsgi_log("--- no python application found, check your startup logs for errors ---\n");
+9
View File
@@ -62,6 +62,9 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
PyObject *zero2 = NULL;
if (self != Py_None) {
zero = PyUnicode_AsASCIIString(head);
if (!zero) {
return PyErr_Format(PyExc_TypeError, "http status string must be encodable in latin1");
}
status_line = PyBytes_AsString(zero);
status_line_len = PyBytes_Size(zero);
}
@@ -133,6 +136,9 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
#ifdef PYTHREE
if (self != Py_None) {
zero = PyUnicode_AsASCIIString(h_key);
if (!zero) {
return PyErr_Format(PyExc_TypeError, "http header must be encodable in latin1");
}
k = PyBytes_AsString(zero);
kl = PyBytes_Size(zero);
}
@@ -148,6 +154,9 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
#ifdef PYTHREE
if (self != Py_None) {
zero2 = PyUnicode_AsASCIIString(h_value);
if (!zero2) {
return PyErr_Format(PyExc_TypeError, "http header must be encodable in latin1");
}
v = PyBytes_AsString(zero2);
vl = PyBytes_Size(zero2);
}
+2 -2
View File
@@ -463,7 +463,7 @@ VALUE rack_uwsgi_cache_get(int argc, VALUE *argv, VALUE *class) {
}
uint64_t vallen = 0;;
char *value = uwsgi_cache_magic_get(key, keylen, &vallen, cache);
char *value = uwsgi_cache_magic_get(key, keylen, &vallen, NULL, cache);
if (value) {
VALUE res = rb_str_new(value, vallen);
free(value);
@@ -774,7 +774,7 @@ VALUE uwsgi_ruby_register_rpc(int argc, VALUE *argv, VALUE *class) {
void *func = (void *) argv[1];
if (uwsgi_register_rpc(name, rack_plugin.modifier1, rb_argc, func)) {
if (uwsgi_register_rpc(name, &rack_plugin, rb_argc, func)) {
clear:
rb_raise(rb_eRuntimeError, "unable to register rpc function");
return Qnil;
+63 -2
View File
@@ -5,6 +5,22 @@ extern struct uwsgi_server uwsgi;
struct uwsgi_rack ur;
struct uwsgi_plugin rack_plugin;
static void uwsgi_opt_rbshell(char *opt, char *value, void *foobar) {
uwsgi.honour_stdin = 1;
if (value) {
ur.rbshell = value;
}
else {
ur.rbshell = "";
}
if (!strcmp("rbshell-oneshot", opt)) {
ur.rb_shell_oneshot = 1;
}
}
struct uwsgi_option uwsgi_rack_options[] = {
{"rails", required_argument, 0, "load a rails <= 2.x app", uwsgi_opt_set_str, &ur.rails, UWSGI_OPT_POST_BUFFERING},
@@ -29,7 +45,8 @@ struct uwsgi_option uwsgi_rack_options[] = {
{"rvm-path", required_argument, 0, "search for rvm in the specified directory", uwsgi_opt_add_string_list, &ur.rvm_path, 0},
{"rbshell", optional_argument, 0, "run a ruby/irb shell", uwsgi_opt_true, &ur.rb_shell, 0},
{"rbshell", optional_argument, 0, "run a ruby/irb shell", uwsgi_opt_rbshell, NULL, 0},
{"rbshell-oneshot", no_argument, 0, "set ruby/irb shell (one shot)", uwsgi_opt_rbshell, NULL, 0},
#ifdef RUBY19
{"rb-threads", required_argument, 0, "set the number of ruby threads to run", uwsgi_opt_set_int, &ur.rb_threads, 0},
@@ -1029,7 +1046,51 @@ int uwsgi_rack_mount_app(char *mountpoint, char *app) {
return -1;
}
void uwsgi_rack_hijack(void) {
VALUE run_irb(VALUE arg) {
rb_funcall(rb_cObject, rb_intern("require"), 1, rb_str_new2("irb"));
VALUE irb = rb_const_get(rb_cObject, rb_intern("IRB"));
return rb_funcall(irb, rb_intern("start"), 0);
}
static void uwsgi_rack_hijack(void) {
if (ur.rb_shell_oneshot && uwsgi.workers[uwsgi.mywid].hijacked_count > 0) {
uwsgi.workers[uwsgi.mywid].hijacked = 0;
return;
}
if (ur.rbshell && uwsgi.mywid == 1) {
uwsgi.workers[uwsgi.mywid].hijacked = 1;
uwsgi.workers[uwsgi.mywid].hijacked_count++;
// re-map stdin to stdout and stderr if we are logging to a file
if (uwsgi.logfile) {
if (dup2(0, 1) < 0) {
uwsgi_error("dup2()");
}
if (dup2(0, 2) < 0) {
uwsgi_error("dup2()");
}
}
int ret = -1;
int error = 0;
if (ur.rbshell[0] != 0) {
rb_eval_string(ur.rbshell);
}
else {
rb_protect( run_irb, 0, &error ) ;
if (error) {
uwsgi_ruby_exception_log(NULL);
exit(1);
}
}
if (ur.rb_shell_oneshot) {
exit(UWSGI_DE_HIJACKED_CODE);
}
if (ret == 0) {
exit(UWSGI_QUIET_CODE);
}
exit(0);
}
}
int uwsgi_rack_mule(char *opt) {
+2 -1
View File
@@ -45,7 +45,8 @@ struct uwsgi_rack {
pthread_mutex_t gvl;
int rb_shell;
char *rbshell;
int rb_shell_oneshot;
int app_id;
int unprotected;
+112 -23
View File
@@ -1,4 +1,4 @@
#include "../../uwsgi.h"
#include <uwsgi.h>
#ifdef UWSGI_ROUTING
@@ -23,54 +23,113 @@ struct uwsgi_router_cache_conf {
char *key;
size_t key_len;
// use mime types ?
char *mime;
#ifdef UWSGI_ZLIB
char *gzip;
size_t gzip_len;
#endif
char *content_type;
size_t content_type_len;
char *content_encoding;
size_t content_encoding_len;
struct uwsgi_cache *cache;
char *expires_str;
uint64_t expires;
};
// this is allocated for each transformation
struct uwsgi_transformation_cache_conf {
struct uwsgi_buffer *cache_it;
#ifdef UWSGI_ZLIB
struct uwsgi_buffer *cache_it_gzip;
#endif
struct uwsgi_buffer *cache_it_to;
uint64_t cache_it_expires;
};
static int transform_cache(struct wsgi_request *wsgi_req, struct uwsgi_buffer *ub, struct uwsgi_buffer **new, void *data) {
struct uwsgi_transformation_cache_conf *utcc = (struct uwsgi_transformation_cache_conf *) data;
// store only successfull response
if (wsgi_req->write_errors == 0 && wsgi_req->status == 200 && ub->pos > 0) {
if (utcc->cache_it) {
uwsgi_cache_magic_set(utcc->cache_it->buf, utcc->cache_it->pos, ub->buf, ub->pos, utcc->cache_it_expires,
UWSGI_CACHE_FLAG_UPDATE, utcc->cache_it_to ? utcc->cache_it_to->buf : NULL);
#ifdef UWSGI_ZLIB
if (utcc->cache_it_gzip) {
struct uwsgi_buffer *gzipped = uwsgi_gzip(ub->buf, ub->pos);
if (gzipped) {
uwsgi_cache_magic_set(utcc->cache_it_gzip->buf, utcc->cache_it_gzip->pos, gzipped->buf, gzipped->pos, utcc->cache_it_expires,
UWSGI_CACHE_FLAG_UPDATE, utcc->cache_it_to ? utcc->cache_it_to->buf : NULL);
uwsgi_buffer_destroy(gzipped);
}
}
#endif
}
}
// free resources
if (utcc->cache_it) uwsgi_buffer_destroy(utcc->cache_it);
#ifdef UWSGI_ZLIB
if (utcc->cache_it_gzip) uwsgi_buffer_destroy(utcc->cache_it_gzip);
#endif
if (utcc->cache_it_to) uwsgi_buffer_destroy(utcc->cache_it_to);
free(utcc);
return 0;
}
// be tolerant on errors
static int uwsgi_routing_func_cache_store(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
struct uwsgi_router_cache_conf *urcc = (struct uwsgi_router_cache_conf *) ur->data2;
// overwrite previous run
if (wsgi_req->cache_it) {
uwsgi_buffer_destroy(wsgi_req->cache_it);
wsgi_req->cache_it = NULL;
}
if (wsgi_req->cache_it_to) {
uwsgi_buffer_destroy(wsgi_req->cache_it_to);
wsgi_req->cache_it_to = NULL;
}
struct uwsgi_transformation_cache_conf *utcc = uwsgi_calloc(sizeof(struct uwsgi_transformation_cache_conf));
// build key and name
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
wsgi_req->cache_it = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urcc->key, urcc->key_len);
if (!wsgi_req->cache_it) return UWSGI_ROUTE_NEXT;
utcc->cache_it = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urcc->key, urcc->key_len);
if (!utcc->cache_it) goto error;
if (urcc->name) {
wsgi_req->cache_it_to = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urcc->name, urcc->name_len);
if (!wsgi_req->cache_it_to) {
uwsgi_buffer_destroy(wsgi_req->cache_it);
wsgi_req->cache_it = NULL;
}
utcc->cache_it_to = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urcc->name, urcc->name_len);
if (!utcc->cache_it_to) goto error;
}
wsgi_req->cache_it_expires = urcc->expires;
#ifdef UWSGI_ZLIB
if (urcc->gzip) {
utcc->cache_it_gzip = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urcc->gzip, urcc->gzip_len);
if (!utcc->cache_it_gzip) goto error;
}
#endif
utcc->cache_it_expires = urcc->expires;
uwsgi_add_transformation(wsgi_req, transform_cache, utcc);
return UWSGI_ROUTE_NEXT;
error:
if (utcc->cache_it) uwsgi_buffer_destroy(utcc->cache_it);
#ifdef UWSGI_ZLIB
if (utcc->cache_it_gzip) uwsgi_buffer_destroy(utcc->cache_it_gzip);
#endif
if (utcc->cache_it_to) uwsgi_buffer_destroy(utcc->cache_it_to);
free(utcc);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_routing_func_cache(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
char *mime_type = NULL;
size_t mime_type_len = 0;
struct uwsgi_router_cache_conf *urcc = (struct uwsgi_router_cache_conf *) ur->data2;
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
@@ -79,11 +138,26 @@ static int uwsgi_routing_func_cache(struct wsgi_request *wsgi_req, struct uwsgi_
if (!ub) return UWSGI_ROUTE_BREAK;
uint64_t valsize = 0;
char *value = uwsgi_cache_magic_get(ub->buf, ub->pos, &valsize, urcc->name);
uint64_t expires = 0;
char *value = uwsgi_cache_magic_get(ub->buf, ub->pos, &valsize, &expires, urcc->name);
if (urcc->mime && value) {
mime_type = uwsgi_get_mime_type(ub->buf, ub->pos, &mime_type_len);
}
uwsgi_buffer_destroy(ub);
if (value) {
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto error;
if (uwsgi_response_add_content_type(wsgi_req, urcc->content_type, urcc->content_type_len)) goto error;
if (mime_type) {
uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_len);
}
else {
if (uwsgi_response_add_content_type(wsgi_req, urcc->content_type, urcc->content_type_len)) goto error;
}
if (urcc->content_encoding_len) {
if (uwsgi_response_add_header(wsgi_req, "Content-Encoding", 16, urcc->content_encoding, urcc->content_encoding_len)) goto error;
}
if (expires) {
if (uwsgi_response_add_expires(wsgi_req, expires)) goto error;
}
if (uwsgi_response_add_content_length(wsgi_req, valsize)) goto error;
uwsgi_response_write_body_do(wsgi_req, value, valsize);
free(value);
@@ -105,6 +179,9 @@ static int uwsgi_router_cache_store(struct uwsgi_route *ur, char *args) {
struct uwsgi_router_cache_conf *urcc = uwsgi_calloc(sizeof(struct uwsgi_router_cache_conf));
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
"key", &urcc->key,
#ifdef UWSGI_ZLIB
"gzip", &urcc->gzip,
#endif
"name", &urcc->name,
"expires", &urcc->expires_str, NULL)) {
uwsgi_log("invalid cachestore route syntax: %s\n", args);
@@ -115,6 +192,12 @@ static int uwsgi_router_cache_store(struct uwsgi_route *ur, char *args) {
urcc->key_len = strlen(urcc->key);
}
#ifdef UWSGI_ZLIB
if (urcc->gzip) {
urcc->gzip_len = strlen(urcc->gzip);
}
#endif
if (urcc->name) {
urcc->name_len = strlen(urcc->name);
}
@@ -146,6 +229,8 @@ static int uwsgi_router_cache(struct uwsgi_route *ur, char *args) {
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
"key", &urcc->key,
"content_type", &urcc->content_type,
"content_encoding", &urcc->content_encoding,
"mime", &urcc->mime,
"name", &urcc->name,
NULL)) {
uwsgi_log("invalid route syntax: %s\n", args);
@@ -165,6 +250,10 @@ static int uwsgi_router_cache(struct uwsgi_route *ur, char *args) {
urcc->content_type_len = strlen(urcc->content_type);
if (urcc->content_encoding) {
urcc->content_encoding_len = strlen(urcc->content_encoding);
}
ur->data2 = urcc;
return 0;
}
+17 -1
View File
@@ -36,6 +36,7 @@ static int uwsgi_routing_func_http(struct wsgi_request *wsgi_req, struct uwsgi_r
// append remaining body...
if (wsgi_req->proto_parser_remains > 0) {
if (uwsgi_buffer_append(ub, wsgi_req->proto_parser_remains_buf, wsgi_req->proto_parser_remains)) {
uwsgi_buffer_destroy(ub);
uwsgi_log("unable to generate http request for %s\n", addr);
return UWSGI_ROUTE_NEXT;
}
@@ -43,9 +44,18 @@ static int uwsgi_routing_func_http(struct wsgi_request *wsgi_req, struct uwsgi_r
}
// ok now if have offload threads, directly use them
if (wsgi_req->socket->can_offload) {
if (!wsgi_req->post_file && !ur->custom && wsgi_req->socket->can_offload) {
// append buffered body
if (uwsgi.post_buffering > 0 && wsgi_req->post_cl > 0) {
if (uwsgi_buffer_append(ub, wsgi_req->post_buffering_buf, wsgi_req->post_cl)) {
uwsgi_buffer_destroy(ub);
uwsgi_log("unable to generate http request for %s\n", addr);
return UWSGI_ROUTE_NEXT;
}
}
if (!uwsgi_offload_request_net_do(wsgi_req, addr, ub)) {
wsgi_req->via = UWSGI_VIA_OFFLOAD;
wsgi_req->status = 202;
return UWSGI_ROUTE_BREAK;
}
}
@@ -82,10 +92,16 @@ static int uwsgi_router_http(struct uwsgi_route *ur, char *args) {
return 0;
}
static int uwsgi_router_proxyhttp(struct uwsgi_route *ur, char *args) {
ur->custom = 1;
return uwsgi_router_http(ur, args);
}
static void router_http_register(void) {
uwsgi_register_router("http", uwsgi_router_http);
uwsgi_register_router("proxyhttp", uwsgi_router_proxyhttp);
}
struct uwsgi_plugin router_http_plugin = {
+13 -1
View File
@@ -58,9 +58,16 @@ static int uwsgi_routing_func_uwsgi_remote(struct wsgi_request *wsgi_req, struct
}
// ok now if have offload threads, directly use them
if (wsgi_req->socket->can_offload) {
if (!wsgi_req->post_file && !ur->custom && wsgi_req->socket->can_offload) {
// append buffered body
if (uwsgi.post_buffering > 0 && wsgi_req->post_cl > 0) {
if (uwsgi_buffer_append(ub, wsgi_req->post_buffering_buf, wsgi_req->post_cl)) {
goto end;
}
}
if (!uwsgi_offload_request_net_do(wsgi_req, addr, ub)) {
wsgi_req->via = UWSGI_VIA_OFFLOAD;
wsgi_req->status = 202;
return UWSGI_ROUTE_BREAK;
}
}
@@ -140,10 +147,15 @@ static int uwsgi_router_uwsgi(struct uwsgi_route *ur, char *args) {
return -1;
}
static int uwsgi_router_proxyuwsgi(struct uwsgi_route *ur, char *args) {
ur->custom = 1;
return uwsgi_router_uwsgi(ur, args);
}
static void router_uwsgi_register(void) {
uwsgi_register_router("uwsgi", uwsgi_router_uwsgi);
uwsgi_register_router("proxyuwsgi", uwsgi_router_proxyuwsgi);
}
struct uwsgi_plugin router_uwsgi_plugin = {
+60
View File
@@ -148,6 +148,60 @@ end:
return ret;
}
static int uwsgi_routing_func_rpc_raw(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
int ret = -1;
// this is the list of args
char *argv[UMAX8];
// this is the size of each argument
uint16_t argvs[UMAX8];
// this is a placeholder for tmp uwsgi_buffers
struct uwsgi_buffer *ubs[UMAX8];
char **r_argv = (char **) ur->data2;
uint16_t *r_argvs = (uint16_t *) ur->data3;
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
uint64_t i;
for(i=0;i<ur->custom;i++) {
ubs[i] = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, r_argv[i], r_argvs[i]);
if (!ubs[i]) goto end;
argv[i] = ubs[i]->buf;
argvs[i] = ubs[i]->pos;
}
// ok we now need to check it it is a local call or a remote one
char *func = uwsgi_str(ur->data);
char *remote = NULL;
char *at = strchr(func, '@');
if (at) {
*at = 0;
remote = at+1;
}
uint16_t size;
char *response = uwsgi_do_rpc(remote, func, ur->custom, argv, argvs, &size);
free(func);
if (!response) goto end;
ret = UWSGI_ROUTE_NEXT;
if (size == 0) goto end;
ret = uwsgi_blob_to_response(wsgi_req, response, size);
free(response);
if (ret == 0) {
ret = UWSGI_ROUTE_BREAK;
}
end:
for(i=0;i<ur->custom;i++) {
if (ubs[i] != NULL) {
uwsgi_buffer_destroy(ubs[i]);
}
}
return ret;
}
// "next" || "continue" || "break(.*)" || "goon" || "goto .+"
static int uwsgi_routing_func_rpc_ret(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
@@ -299,6 +353,11 @@ static int uwsgi_router_rpc_blob(struct uwsgi_route *ur, char *args) {
return uwsgi_router_rpc_base(ur, args);
}
static int uwsgi_router_rpc_raw(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_rpc_raw;
return uwsgi_router_rpc_base(ur, args);
}
static void router_rpc_register() {
uwsgi_register_router("call", uwsgi_router_rpc);
@@ -306,6 +365,7 @@ static void router_rpc_register() {
uwsgi_register_router("rpcret", uwsgi_router_rpc_ret);
uwsgi_register_router("rpcblob", uwsgi_router_rpc_blob);
uwsgi_register_router("rpcnext", uwsgi_router_rpc_blob);
uwsgi_register_router("rpcraw", uwsgi_router_rpc_raw);
}
#endif
+1 -1
View File
@@ -36,7 +36,7 @@ int uwsgi_request_spooler(struct wsgi_request *wsgi_req) {
uwsgi_log("disconnected client, remove spool file.\n");
/* client disconnect, remove spool file */
if (unlink(spool_filename)) {
uwsgi_error("unlink()");
uwsgi_error("uwsgi_request_spooler()/unlink()");
uwsgi_log("something horrible happened !!! check your spooler ASAP !!!\n");
exit(1);
}
+70
View File
@@ -0,0 +1,70 @@
#include <uwsgi.h>
#include <sqlite3.h>
extern struct uwsgi_server uwsgi;
static void uwsgi_sqlite3_config(char *, char *[]);
static void uwsgi_opt_load_sqlite3(char *opt, char *filename, void *none) {
config_magic_table_fill(filename, uwsgi.magic_table);
uwsgi_sqlite3_config(filename, uwsgi.magic_table);
}
static struct uwsgi_option uwsgi_sqlite3_options[] = {
{"sqlite3", required_argument, 0, "load config from sqlite3 db", uwsgi_opt_load_sqlite3, NULL, UWSGI_OPT_IMMEDIATE},
{"sqlite", required_argument, 0, "load config from sqlite3 db", uwsgi_opt_load_sqlite3, NULL, UWSGI_OPT_IMMEDIATE},
{0, 0, 0, 0, 0, 0, 0},
};
static int uwsgi_sqlite3_config_callback(void *magic_table, int field_count, char **fields, char **col) {
// make a copy of the string
if (field_count >= 2) {
size_t value_len = strlen(fields[1]) + 1;
char *value = magic_sub(fields[1], value_len, &value_len, (char **) magic_table);
add_exported_option(uwsgi_strncopy(fields[0], strlen(fields[0])), value, 0);
}
return 0;
}
static void uwsgi_sqlite3_config(char *file, char *magic_table[]) {
sqlite3 *db;
char *err = NULL;
char *query = "SELECT * FROM uwsgi";
char *colon = uwsgi_get_last_char(file, ':');
if (colon) {
colon[0] = 0;
if (colon[1] != 0) {
query = colon + 1;
}
}
uwsgi_log("[uWSGI] getting sqlite3 configuration from %s\n", file);
#ifdef sqlite3_open_v2
if (sqlite3_open_v2(file, &db, SQLITE_OPEN_READONLY, NULL)) {
#else
if (sqlite3_open(file, &db)) {
#endif
uwsgi_log("unable to open sqlite3 db: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
exit(1);
}
if (sqlite3_exec(db, query, uwsgi_sqlite3_config_callback, (void *) magic_table, &err)) {
uwsgi_log("sqlite3 error: %s\n", err);
sqlite3_close(db);
exit(1);
}
sqlite3_close(db);
}
struct uwsgi_plugin sqlite3_plugin = {
.name = "sqlite3",
.options = uwsgi_sqlite3_options,
};
+7
View File
@@ -0,0 +1,7 @@
NAME='sqlite3'
CFLAGS = []
LDFLAGS = []
LIBS = ['-lsqlite3']
GCC_LIST = ['plugin']
+1 -1
View File
@@ -444,7 +444,7 @@ static struct uwsgi_buffer *ssi_cmd_cache(struct wsgi_request *wsgi_req, struct
}
uint64_t rlen = 0;
char *value = uwsgi_cache_magic_get(var, var_len, &rlen, cache_name);
char *value = uwsgi_cache_magic_get(var, var_len, &rlen, NULL, cache_name);
if (cache_name) free(cache_name);
struct uwsgi_buffer *ub = NULL;
if (value) {
+60 -13
View File
@@ -1,33 +1,80 @@
#include "../../uwsgi.h"
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
int (*symcall_function)(struct wsgi_request *);
int uwsgi_symcall_init(){
symcall_function = dlsym(RTLD_DEFAULT, "pypy_uwsgi_request");
uwsgi_log("symcall function ptr: %p\n", symcall_function);
return 0;
struct uwsgi_symcall {
char *symcall_function_name;
int (*symcall_function)(struct wsgi_request *);
struct uwsgi_string_list *rpc;
} usym;
struct uwsgi_plugin symcall_plugin;
static struct uwsgi_option uwsgi_symcall_options[] = {
{"symcall", required_argument, 0, "load the specified C symbol as the symcall request handler", uwsgi_opt_set_str, &usym.symcall_function_name, 0},
{"symcall-register-rpc", required_argument, 0, "load the specified C symbol as an RPC function (syntax: name function)", uwsgi_opt_add_string_list, &usym.rpc, 0},
{0, 0, 0, 0},
};
static void uwsgi_symcall_init(){
if (usym.symcall_function_name) {
usym.symcall_function = dlsym(RTLD_DEFAULT, usym.symcall_function_name);
if (!usym.symcall_function) {
uwsgi_log("unable to find symbol \"%s\" in process address space\n", usym.symcall_function_name);
exit(1);
}
uwsgi_log("symcall function ptr: %p\n", usym.symcall_function);
}
struct uwsgi_string_list *usl = usym.rpc;
while(usl) {
char *space = strchr(usl->value, ' ');
if (!space) {
uwsgi_log("invalid symcall RPC syntax, must be: rpcname symbol\n");
exit(1);
}
*space = 0;
void *func = dlsym(RTLD_DEFAULT, space+1);
if (!func) {
uwsgi_log("unable to find symbol \"%s\" in process address space\n", space+1);
exit(1);
}
if (uwsgi_register_rpc(usl->value, &symcall_plugin, 0, func)) {
uwsgi_log("unable to register rpc function");
exit(1);
}
*space = ' ';
usl = usl->next;
}
}
int uwsgi_symcall_request(struct wsgi_request *wsgi_req) {
return symcall_function(wsgi_req);
static int uwsgi_symcall_request(struct wsgi_request *wsgi_req) {
if (usym.symcall_function) {
return usym.symcall_function(wsgi_req);
}
return UWSGI_OK;
}
void uwsgi_symcall_after_request(struct wsgi_request *wsgi_req) {
// TODO
static void uwsgi_symcall_after_request(struct wsgi_request *wsgi_req) {
log_request(wsgi_req);
}
static uint16_t uwsgi_symcall_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
uint16_t (*casted_func)(uint8_t, char **, uint16_t *, char *) = (uint16_t (*)(uint8_t, char **, uint16_t *, char *)) func;
return casted_func(argc, argv, argvs, buffer);
}
struct uwsgi_plugin symcall_plugin = {
.name = "symcall",
.modifier1 = 18,
.init = uwsgi_symcall_init,
.options = uwsgi_symcall_options,
.init_apps = uwsgi_symcall_init,
.request = uwsgi_symcall_request,
.after_request = uwsgi_symcall_after_request,
.rpc = uwsgi_symcall_rpc,
};
+48
View File
@@ -0,0 +1,48 @@
#include <uwsgi.h>
#if defined(UWSGI_ROUTING) && defined(UWSGI_ZLIB)
/*
gzip transformations reset your headers !!!
remember to re-add the content type via routing rules
*/
static int transform_gzip(struct wsgi_request *wsgi_req, struct uwsgi_buffer *ub, struct uwsgi_buffer **new, void *data) {
struct uwsgi_buffer *gzipped = uwsgi_gzip(ub->buf, ub->pos);
if (!gzipped) {
return -1;
}
// use this new buffer
*new = gzipped;
if (uwsgi_response_prepare_headers_int(wsgi_req, wsgi_req->status)) return -1;
if (uwsgi_response_add_header(wsgi_req, "Content-Encoding", 16, "gzip", 4)) return -1;
if (uwsgi_response_add_content_length(wsgi_req, gzipped->pos)) return -1;
return 0;
}
static int uwsgi_routing_func_gzip(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
uwsgi_add_transformation(wsgi_req, transform_gzip, NULL);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_gzip(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_gzip;
return 0;
}
static void router_gzip_register(void) {
uwsgi_register_router("gzip", uwsgi_router_gzip);
}
struct uwsgi_plugin transformation_gzip_plugin = {
.name = "transformation_gzip",
.on_load = router_gzip_register,
};
#else
struct uwsgi_plugin transformation_gzip_plugin = {
.name = "transformation_gzip",
};
#endif
@@ -0,0 +1,6 @@
NAME='transformation_gzip'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['gzip']
+125
View File
@@ -0,0 +1,125 @@
#include <uwsgi.h>
#ifdef UWSGI_ROUTING
extern struct uwsgi_server uwsgi;
struct uwsgi_router_tofile_conf {
// the name of the file
char *filename;
size_t filename_len;
// the mode of the file
char *mode;
size_t mode_len;
};
// this is allocated for each transformation
struct uwsgi_transformation_tofile_conf {
struct uwsgi_buffer *filename;
};
static int transform_tofile(struct wsgi_request *wsgi_req, struct uwsgi_buffer *ub, struct uwsgi_buffer **new, void *data) {
struct uwsgi_transformation_tofile_conf *uttc = (struct uwsgi_transformation_tofile_conf *) data;
// store only successfull response
if (wsgi_req->write_errors == 0 && wsgi_req->status == 200 && ub->pos > 0) {
if (uttc->filename) {
int fd = open(uttc->filename->buf, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
if (fd < 0) {
uwsgi_error_open(uttc->filename->buf);
goto end;
}
// lock the file
if (uwsgi_fcntl_lock(fd)) {
close(fd);
goto end;
}
// write to it
size_t remains = ub->pos;
while(remains) {
ssize_t rlen = write(fd, ub->buf + (ub->pos - remains), remains);
if (rlen <= 0) {
uwsgi_error("transform_tofile()/write()");
unlink(uttc->filename->buf);
break;
}
remains -= rlen;
}
// unlock/close
close(fd);
}
}
end:
// free resources
if (uttc->filename) uwsgi_buffer_destroy(uttc->filename);
free(uttc);
return 0;
}
// be tolerant on errors
static int uwsgi_routing_func_tofile(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
struct uwsgi_router_tofile_conf *urtc = (struct uwsgi_router_tofile_conf *) ur->data2;
struct uwsgi_transformation_tofile_conf *uttc = uwsgi_calloc(sizeof(struct uwsgi_transformation_tofile_conf));
// build key and name
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
uttc->filename = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urtc->filename, urtc->filename_len);
if (!uttc->filename) goto error;
uwsgi_add_transformation(wsgi_req, transform_tofile, uttc);
return UWSGI_ROUTE_NEXT;
error:
if (uttc->filename) uwsgi_buffer_destroy(uttc->filename);
free(uttc);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_tofile(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_tofile;
ur->data = args;
ur->data_len = strlen(args);
struct uwsgi_router_tofile_conf *urtc = uwsgi_calloc(sizeof(struct uwsgi_router_tofile_conf));
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
"filename", &urtc->filename,
"name", &urtc->filename,
"mode", &urtc->mode, NULL)) {
uwsgi_log("invalid tofile route syntax: %s\n", args);
goto error;
}
if (!urtc->filename) {
uwsgi_log("invalid tofile route syntax, you need to specify a filename\n");
goto error;
}
urtc->filename_len = strlen(urtc->filename);
ur->data2 = urtc;
return 0;
error:
if (urtc->filename) free(urtc->filename);
free(urtc);
return -1;
}
static void router_tofile_register() {
uwsgi_register_router("tofile", uwsgi_router_tofile);
uwsgi_register_router("to-file", uwsgi_router_tofile);
}
struct uwsgi_plugin transformation_tofile_plugin = {
.name = "transformation_tofile",
.on_load = router_tofile_register,
};
#else
struct uwsgi_plugin transformation_tofile_plugin = {
.name = "transformation_tofile",
};
#endif
@@ -0,0 +1,6 @@
NAME='transformation_tofile'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['tofile']
+28
View File
@@ -0,0 +1,28 @@
#include <uwsgi.h>
static int transform_toupper(struct wsgi_request *wsgi_req, struct uwsgi_buffer *ub, struct uwsgi_buffer **foobar, void *data) {
size_t i;
for(i=0;i<ub->pos;i++) {
ub->buf[i] = toupper((int) ub->buf[i]);
}
return 0;
}
static int uwsgi_routing_func_toupper(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
uwsgi_add_transformation(wsgi_req, transform_toupper, NULL);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_toupper(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_toupper;
return 0;
}
static void router_toupper_register(void) {
uwsgi_register_router("toupper", uwsgi_router_toupper);
}
struct uwsgi_plugin transformation_toupper_plugin = {
.name = "transformation_toupper",
.on_load = router_toupper_register,
};
@@ -0,0 +1,6 @@
NAME='transformation_toupper'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['toupper']
+5
View File
@@ -1,6 +1,11 @@
import os
NAME='v8'
CFLAGS = ['-Wno-deprecated-declarations']
LDFLAGS = []
LIBS = ['-lv8']
engine = os.environ.get('UWSGICONFIG_V8_ENGINE', '')
if engine == 'teajs':
CFLAGS.append('-DUWSGI_V8_TEAJS -fexceptions')
LIBS.append('-lteajs')
GCC_LIST = ['plugin', 'v8_uwsgi.cc', 'v8_commonjs.cc', 'v8_jsgi.cc']
+119 -32
View File
@@ -1,32 +1,122 @@
#include "v8_uwsgi.h"
extern struct uwsgi_v8 uv8;
extern struct uwsgi_server uwsgi;
static v8::Handle<v8::Value> uwsgi_v8_commonjs_require_do(char *filename) {
#ifdef UWSGI_V8_TEAJS
#include "app.h"
#include "macros.h"
class TeaJS_uWSGI : public TeaJS_App {
public:
void init() {
TeaJS_App::init();
v8::HandleScope handle_scope;
this->mainfile = "";
this->create_context();
this->mainModule = v8::Object::New();
this->prepare(uwsgi.environ);
}
v8::Persistent<v8::Context> getContext() {
return this->context;
}
private:
const char *instanceType() {
return "uWSGI";
}
const char *executableName() {
return uwsgi.binary_path;
}
};
static v8::Handle < v8::Value > uwsgi_v8_commonjs_require(const v8::Arguments & args) {
if (args.Length() > 0) {
try {
v8::String::Utf8Value module_name(args[0]->ToString());
return APP_PTR->require(std::string(*module_name), "");
}
catch (std::string e) {
uwsgi_log("%s\n", e.c_str());
}
}
return v8::Undefined();
}
TeaJS_uWSGI app;
#else
static v8::Handle < v8::Value > uwsgi_v8_commonjs_require(const v8::Arguments &);
static v8::Handle < v8::Value > uwsgi_v8_commonjs_require_do(char *);
#endif
extern struct uwsgi_v8 uv8;
extern struct uwsgi_server uwsgi;
v8::Persistent<v8::Context> uwsgi_v8_setup_context() {
v8::HandleScope handle_scope;
#ifdef UWSGI_V8_TEAJS
try {
app.init();
app.getContext()->Global()->Set(v8::String::New("require"), v8::FunctionTemplate::New(uwsgi_v8_commonjs_require)->GetFunction());
return app.getContext();
}
catch (std::string e) {
uwsgi_log("%s\n", e.c_str());
exit(1);
}
}
#else
// create a new context
v8::Persistent<v8::Context> context = v8::Context::New();
context->Enter();
v8::Handle<v8::Object> global = context->Global();
v8::Handle < v8::Object > system = v8::Object::New();
v8::Handle < v8::Array > args = v8::Array::New();
int i;
for (i = 0; i < uwsgi.argc; i++) {
args->Set(v8::Integer::New(i), v8::String::New(uwsgi.argv[i]));
}
system->Set(v8::String::New("args"), args);
v8::Handle < v8::Object > env = v8::Object::New();
system->Set(v8::String::New("env"), env);
global->Set(v8::String::New("require"), v8::FunctionTemplate::New(uwsgi_v8_commonjs_require)->GetFunction());
global->Set(v8::String::New("system"), system);
return context;
}
/*
uWSGI native "require" support
*/
static v8::Handle < v8::Value > uwsgi_v8_commonjs_require_do(char *filename) {
size_t len = 0;
char *code = uwsgi_open_and_read(filename, &len, 1, NULL);
char *code = uwsgi_open_and_read(filename, &len, 1, NULL);
// we re-create every time an "exports" object to emulate a local object
v8::Local<v8::Object> exports = v8::Object::New();
v8::Local < v8::Object > exports = v8::Object::New();
v8::Context::GetCurrent()->Global()->Set(v8::String::New("exports"), exports);
// we do not use TryCatch as we directly use stderr and simply exit with error code 1
v8::Handle<v8::Script> script = v8::Script::Compile( v8::String::New(code), v8::String::New(filename) );
free(code);
if (script.IsEmpty()) {
exit(1);
}
// we do not use TryCatch as we directly use stderr and simply exit with error code 1
v8::Handle < v8::Script > script = v8::Script::Compile(v8::String::New(code), v8::String::New(filename));
free(code);
if (script.IsEmpty()) {
exit(1);
}
v8::Handle<v8::Value> result = script->Run();
if (result.IsEmpty()) {
v8::Handle < v8::Value > result = script->Run();
if (result.IsEmpty()) {
return v8::Undefined();
}
}
return exports;
}
static v8::Handle<v8::Value> uwsgi_v8_commonjs_require(const v8::Arguments& args) {
static v8::Handle < v8::Value > uwsgi_v8_commonjs_require(const v8::Arguments & args) {
if (args.Length() > 0) {
v8::String::Utf8Value module_name(args[0]->ToString());
// ok lets start searching the module
@@ -35,33 +125,33 @@ static v8::Handle<v8::Value> uwsgi_v8_commonjs_require(const v8::Arguments& args
}
// try appending .js extension
if (!uwsgi_endswith(*module_name, (char *)".js")) {
char *tmp_filename = uwsgi_concat2(*module_name, (char *)".js");
if (!uwsgi_endswith(*module_name, (char *) ".js")) {
char *tmp_filename = uwsgi_concat2(*module_name, (char *) ".js");
if (uwsgi_is_file(tmp_filename)) {
v8::Handle<v8::Value> ret = uwsgi_v8_commonjs_require_do(tmp_filename);
v8::Handle < v8::Value > ret = uwsgi_v8_commonjs_require_do(tmp_filename);
free(tmp_filename);
return ret;
return ret;
}
free(tmp_filename);
}
// let's start searching in the modules search path
struct uwsgi_string_list *usl = uv8.module_paths;
while(usl) {
char *tmp_filename = uwsgi_concat3(usl->value, (char *)"/", *module_name);
while (usl) {
char *tmp_filename = uwsgi_concat3(usl->value, (char *) "/", *module_name);
if (uwsgi_is_file(tmp_filename)) {
v8::Handle<v8::Value> ret = uwsgi_v8_commonjs_require_do(tmp_filename);
v8::Handle < v8::Value > ret = uwsgi_v8_commonjs_require_do(tmp_filename);
free(tmp_filename);
return ret;
}
}
free(tmp_filename);
if (!uwsgi_endswith(*module_name, (char *)".js")) {
tmp_filename = uwsgi_concat4(usl->value, (char *)"/", *module_name, (char *)".js");
if (!uwsgi_endswith(*module_name, (char *) ".js")) {
tmp_filename = uwsgi_concat4(usl->value, (char *) "/", *module_name, (char *) ".js");
if (uwsgi_is_file(tmp_filename)) {
v8::Handle<v8::Value> ret = uwsgi_v8_commonjs_require_do(tmp_filename);
free(tmp_filename);
return ret;
}
v8::Handle < v8::Value > ret = uwsgi_v8_commonjs_require_do(tmp_filename);
free(tmp_filename);
return ret;
}
}
free(tmp_filename);
usl = usl->next;
@@ -69,7 +159,4 @@ static v8::Handle<v8::Value> uwsgi_v8_commonjs_require(const v8::Arguments& args
}
return v8::Undefined();
}
void uwsgi_v8_add_commonjs(v8::Handle<v8::ObjectTemplate> global) {
global->Set(v8::String::New("require"), v8::FunctionTemplate::New(uwsgi_v8_commonjs_require));
}
#endif
+11 -12
View File
@@ -85,7 +85,7 @@ static v8::Handle<v8::Value> uwsgi_v8_api_register_rpc(const v8::Arguments& args
uvrt->func[core_id] = func;
// we can safely call register_rpc here as it will check for already registered funcs
if (uwsgi_register_rpc(*name, v8_plugin.modifier1, j_argc, uvrt)) {
if (uwsgi_register_rpc(*name, &v8_plugin, j_argc, uvrt)) {
uwsgi_log("[uwsgi-v8] unable to register RPC function \"%s\"\n", *name);
return v8::Undefined();
}
@@ -134,7 +134,7 @@ static v8::Handle<v8::Value> uwsgi_v8_api_log(const v8::Arguments& args) {
return v8::Undefined();
}
void uwsgi_v8_add_commonjs(v8::Handle<v8::ObjectTemplate>);
v8::Persistent<v8::Context> uwsgi_v8_setup_context();
static v8::Persistent<v8::Context> uwsgi_v8_new_isolate(int core_id) {
// create a new isolate
@@ -144,21 +144,19 @@ static v8::Persistent<v8::Context> uwsgi_v8_new_isolate(int core_id) {
uv8.isolates[core_id] = v8::Isolate::GetCurrent();
v8::Persistent<v8::Context> context = uwsgi_v8_setup_context();
context->Enter();
v8::HandleScope handle_scope;
// uWSGI api
v8::Handle<v8::ObjectTemplate> uwsgi_api = v8::ObjectTemplate::New();
uwsgi_api->Set(v8::String::New("log"), v8::FunctionTemplate::New(uwsgi_v8_api_log));
uwsgi_api->Set(v8::String::New("register_rpc"), v8::FunctionTemplate::New(uwsgi_v8_api_register_rpc));
uwsgi_api->Set(v8::String::New("register_signal"), v8::FunctionTemplate::New(uwsgi_v8_api_register_signal));
v8::Handle<v8::Object> uwsgi_api = v8::Object::New();
uwsgi_api->Set(v8::String::New("log"), v8::FunctionTemplate::New(uwsgi_v8_api_log)->GetFunction());
uwsgi_api->Set(v8::String::New("register_rpc"), v8::FunctionTemplate::New(uwsgi_v8_api_register_rpc)->GetFunction());
uwsgi_api->Set(v8::String::New("register_signal"), v8::FunctionTemplate::New(uwsgi_v8_api_register_signal)->GetFunction());
v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
global->Set(v8::String::New("uwsgi"), uwsgi_api);
context->Global()->Set(v8::String::New("uwsgi"), uwsgi_api);
uwsgi_v8_add_commonjs(global);
// create a new context
v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);
return context;
}
@@ -181,6 +179,7 @@ extern "C" int uwsgi_v8_init(){
pthread_key_create(&uv8.current_core, NULL);
pthread_setspecific(uv8.current_core, (void *) 0);
uv8.contexts[0] = uwsgi_v8_new_isolate(0);
return 0;
+119 -16
View File
@@ -15,6 +15,10 @@
xslt:doc=<path1>,stylesheet=<path2>,params=<params>
As transformation
toxslt:stylesheet=<path2>,params=<params>
*/
struct uwsgi_xslt_config {
@@ -37,6 +41,12 @@ struct uwsgi_router_xslt_conf {
uint16_t content_type_len;
};
struct uwsgi_transformation_xslt_conf {
struct uwsgi_buffer *stylesheet;
struct uwsgi_buffer *params;
struct uwsgi_buffer *content_type;
};
struct uwsgi_option uwsgi_xslt_options[] = {
{"xslt-docroot", required_argument, 0, "add a document_root for xslt processing", uwsgi_opt_add_string_list, &uxslt.docroot, 0},
{"xslt-ext", required_argument, 0, "search for xslt stylesheets with the specified extension", uwsgi_opt_add_string_list, &uxslt.ext, 0},
@@ -46,7 +56,7 @@ struct uwsgi_option uwsgi_xslt_options[] = {
{NULL, 0, 0, NULL, NULL, NULL, 0},
};
static char *uwsgi_xslt_apply(char *xmlfile, char *xsltfile, char *params, int *rlen) {
static char *uwsgi_xslt_apply(xmlDoc *doc, char *xsltfile, char *params, int *rlen) {
char **vparams = NULL;
char *tmp_params = NULL;
@@ -79,19 +89,8 @@ static char *uwsgi_xslt_apply(char *xmlfile, char *xsltfile, char *params, int *
xmlSubstituteEntitiesDefault(1);
xmlLoadExtDtdDefaultValue = 1;
xmlDocPtr doc = xmlParseFile(xmlfile);
if (!doc) {
if (vparams) {
int i; for(i=1;i<(count*2);i+=2) free(vparams[i]);
free(tmp_params);
free(vparams);
}
return NULL;
}
xsltStylesheetPtr ss = xsltParseStylesheetFile((const xmlChar *) xsltfile);
if (!ss) {
xmlFreeDoc(doc);
if (vparams) {
int i; for(i=1;i<(count*2);i+=2) free(vparams[i]);
free(tmp_params);
@@ -103,7 +102,6 @@ static char *uwsgi_xslt_apply(char *xmlfile, char *xsltfile, char *params, int *
xmlDocPtr res = xsltApplyStylesheet(ss, doc, (const char **) vparams);
if (!res) {
xsltFreeStylesheet(ss);
xmlFreeDoc(doc);
if (vparams) {
int i; for(i=1;i<(count*2);i+=2) free(vparams[i]);
free(tmp_params);
@@ -116,7 +114,6 @@ static char *uwsgi_xslt_apply(char *xmlfile, char *xsltfile, char *params, int *
int ret = xsltSaveResultToString(&output, rlen, res, ss);
xsltFreeStylesheet(ss);
xmlFreeDoc(res);
xmlFreeDoc(doc);
if (vparams) {
int i; for(i=1;i<(count*2);i+=2) free(vparams[i]);
free(tmp_params);
@@ -279,7 +276,13 @@ apply:
params = uwsgi_concat2n(wsgi_req->query_string, wsgi_req->query_string_len, "", 0);
}
// we have both the file and the stylesheet, let's run the engine
output = uwsgi_xslt_apply(filename, stylesheet, params, &output_rlen);
xmlDoc *doc = xmlParseFile(xmlfile);
if (!doc) {
uwsgi_500(wsgi_req);
return UWSGI_OK;
}
output = uwsgi_xslt_apply(doc, stylesheet, params, &output_rlen);
xmlFree(doc);
if (params) free(params);
if (!output) {
uwsgi_500(wsgi_req);
@@ -313,6 +316,72 @@ static void uwsgi_xslt_log(struct wsgi_request *wsgi_req) {
log_request(wsgi_req);
}
static int transform_toxslt(struct wsgi_request *wsgi_req, struct uwsgi_buffer *ub, struct uwsgi_buffer **new, void *data) {
int ret = -1;
struct uwsgi_transformation_xslt_conf *utxc = (struct uwsgi_transformation_xslt_conf *) data;
xmlDoc *doc = xmlReadMemory(ub->buf, ub->pos, NULL, NULL, 0);
if (!doc) goto end;
int rlen;
char *output = uwsgi_xslt_apply( doc, utxc->stylesheet->buf, utxc->params ? utxc->params->buf : NULL, &rlen);
if (!output) goto end;
if (uwsgi_response_prepare_headers_int(wsgi_req, wsgi_req->status)) goto end;
if (uwsgi_response_add_content_length(wsgi_req, rlen)) goto end;
if (uwsgi_response_add_content_type(wsgi_req, utxc->content_type->buf, utxc->content_type->pos)) goto end;
*new = uwsgi_buffer_new(rlen);
if (uwsgi_buffer_append(*new, output, rlen)) {
xmlFree(output);
uwsgi_buffer_destroy(*new);
*new = NULL;
goto end;
}
xmlFree(output);
ret = 0;
end:
if (doc) xmlFreeDoc(doc);
if (utxc->stylesheet) uwsgi_buffer_destroy(utxc->stylesheet);
if (utxc->params) uwsgi_buffer_destroy(utxc->params);
if (utxc->content_type) uwsgi_buffer_destroy(utxc->content_type);
free(utxc);
return ret;
}
static int uwsgi_routing_func_toxslt(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
struct uwsgi_router_xslt_conf *urxc = (struct uwsgi_router_xslt_conf *) ur->data2;
struct uwsgi_transformation_xslt_conf *utxc = uwsgi_calloc(sizeof(struct uwsgi_transformation_xslt_conf));
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
utxc->stylesheet = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urxc->stylesheet, urxc->stylesheet_len);
if (!utxc->stylesheet) goto end;
if (urxc->params) {
utxc->params = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urxc->params, urxc->params_len);
if (!utxc->params) goto end;
}
if (urxc->content_type) {
utxc->content_type = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urxc->content_type, urxc->content_type_len);
if (!utxc->content_type) goto end;
}
uwsgi_add_transformation(wsgi_req, transform_toxslt, utxc);
return UWSGI_ROUTE_NEXT;
end:
if (utxc->stylesheet) uwsgi_buffer_destroy(utxc->stylesheet);
if (utxc->params) uwsgi_buffer_destroy(utxc->params);
if (utxc->content_type) uwsgi_buffer_destroy(utxc->content_type);
free(utxc);
return UWSGI_ROUTE_BREAK;
}
static int uwsgi_routing_func_xslt(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
struct uwsgi_router_xslt_conf *urxc = (struct uwsgi_router_xslt_conf *) ur->data2;
@@ -341,7 +410,10 @@ static int uwsgi_routing_func_xslt(struct wsgi_request *wsgi_req, struct uwsgi_r
}
int rlen;
char *output = uwsgi_xslt_apply( ub_doc->buf, ub_stylesheet->buf, ub_params ? ub_params->buf : NULL, &rlen);
xmlDoc *doc = xmlParseFile(ub_doc->buf) ;
if (!doc) goto end;
char *output = uwsgi_xslt_apply(doc, ub_stylesheet->buf, ub_params ? ub_params->buf : NULL, &rlen);
xmlFree(doc);
if (!output) goto end;
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto end;
@@ -390,9 +462,40 @@ static int uwsgi_router_xslt(struct uwsgi_route *ur, char *args) {
return 0;
}
static int uwsgi_router_toxslt(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_toxslt;
ur->data = args;
ur->data_len = strlen(args);
struct uwsgi_router_xslt_conf *urxc = uwsgi_calloc(sizeof(struct uwsgi_router_xslt_conf));
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
"stylesheet", &urxc->stylesheet,
"content_type", &urxc->content_type,
"params", &urxc->params,
NULL)) {
uwsgi_log("invalid route syntax: %s\n", args);
exit(1);
}
if (!urxc->stylesheet) {
uwsgi_log("invalid route/transformation syntax: you need to specify a stylesheet\n");
exit(1);
}
urxc->stylesheet_len = strlen(urxc->stylesheet);
if (urxc->params) urxc->params_len = strlen(urxc->params);
if (!urxc->content_type) urxc->content_type = "text/html";
urxc->content_type_len = strlen(urxc->content_type);
ur->data2 = urxc;
return 0;
}
static void router_xslt_register() {
uwsgi_register_router("xslt", uwsgi_router_xslt);
uwsgi_register_router("toxslt", uwsgi_router_toxslt);
}
+52 -1
View File
@@ -310,13 +310,14 @@ struct uwsgi_buffer *uwsgi_to_http(struct wsgi_request *wsgi_req, char *host, ui
if (uwsgi_buffer_append(ub, wsgi_req->uri, wsgi_req->uri_len)) goto clear;
}
// force HTTP/1.0
if (uwsgi_buffer_append(ub, " HTTP/1.0\r\n", 11)) goto clear;
int i;
char *x_forwarded_for = NULL;
size_t x_forwarded_for_len = 0;
// starting adding headers
// start adding headers
for(i=0;i<wsgi_req->var_cnt;i++) {
if (!uwsgi_starts_with(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len, "HTTP_", 5)) {
@@ -325,8 +326,17 @@ struct uwsgi_buffer *uwsgi_to_http(struct wsgi_request *wsgi_req, char *host, ui
if (host && !uwsgi_strncmp(header, header_len, "HOST", 4)) goto next;
// remove dangerous headers
if (!uwsgi_strncmp(header, header_len, "CONNECTION", 10)) goto next;
if (!uwsgi_strncmp(header, header_len, "KEEP_ALIVE", 10)) goto next;
if (!uwsgi_strncmp(header, header_len, "ACCEPT_ENCODING", 15)) goto next;
if (!uwsgi_strncmp(header, header_len, "TE", 2)) goto next;
if (!uwsgi_strncmp(header, header_len, "TRAILER", 7)) goto next;
if (!uwsgi_strncmp(header, header_len, "IF_MATCH", 8)) goto next;
if (!uwsgi_strncmp(header, header_len, "IF_MODIFIED_SINCE", 17)) goto next;
if (!uwsgi_strncmp(header, header_len, "IF_RANGE", 8)) goto next;
if (!uwsgi_strncmp(header, header_len, "IF_UNMODIFIED_SINCE", 19)) goto next;
if (!uwsgi_strncmp(header, header_len, "IF_NONE_MATCH", 13)) goto next;
if (!uwsgi_strncmp(header, header_len, "X_FORWARDED_FOR", 15)) {
x_forwarded_for = wsgi_req->hvec[i+1].iov_base;
x_forwarded_for_len = wsgi_req->hvec[i+1].iov_len;
@@ -386,3 +396,44 @@ clear:
return NULL;
}
int uwsgi_is_full_http(struct uwsgi_buffer *ub) {
size_t i;
int status = 0;
for(i=0;i<ub->pos;i++) {
switch(status) {
// \r
case 0:
if (ub->buf[i] == '\r') status = 1;
break;
// \r\n
case 1:
if (ub->buf[i] == '\n') {
status = 2;
break;
}
status = 0;
break;
// \r\n\r
case 2:
if (ub->buf[i] == '\r') {
status = 3;
break;
}
status = 0;
break;
// \r\n\r\n
case 3:
if (ub->buf[i] == '\n') {
return 1;
}
status = 0;
break;
default:
status = 0;
break;
}
}
return 0;
}
+8
View File
@@ -1,6 +1,14 @@
use strict;
use warnings;
uwsgi::register_rpc('hello', sub {
my ($one, $two, $three) = @_;
unless($one) {
return "passed no args to RPC func";
}
return $three.'-'.$two.'-'.$one;
});
my $rpc_value = uwsgi::call('hello', 'foo', 'bar', 'test');
if ($rpc_value) {
+1 -1
View File
@@ -2,7 +2,7 @@ Gem::Specification.new do |s|
s.name = 'uwsgi'
s.license = 'GPL-2'
s.version = `python -c "import uwsgiconfig as uc; print uc.uwsgi_version"`.sub(/-dev-.*/,'')
s.date = '2013-04-04'
s.date = '2013-04-22'
s.summary = "uWSGI"
s.description = "The uWSGI server for Ruby/Rack"
s.authors = ["Unbit"]
+380 -373
View File
File diff suppressed because it is too large Load Diff
+11 -33
View File
@@ -1,6 +1,6 @@
# uWSGI build system
uwsgi_version = '1.9.5'
uwsgi_version = '1.9.7'
import os
import re
@@ -66,11 +66,9 @@ report['routing'] = False
report['capabilities'] = False
report['yaml'] = False
report['json'] = False
report['ldap'] = False
report['ssl'] = False
report['zeromq'] = False
report['xml'] = False
report['sqlite3'] = False
report['debug'] = False
report['plugin_dir'] = False
report['zlib'] = False
@@ -218,6 +216,9 @@ def build_uwsgi(uc, print_only=False):
gcc_list, cflags, ldflags, libs = uc.get_gcll()
if 'UWSGI_EMBED_PLUGINS' in os.environ:
uc.set('embedded_plugins', uc.get('embedded_plugins') + ',' + os.environ['UWSGI_EMBED_PLUGINS'])
if uc.get('embedded_plugins'):
ep = uc.get('embedded_plugins').split(',')
epc = "-DUWSGI_DECLARE_EMBEDDED_PLUGINS=\""
@@ -458,10 +459,10 @@ class uConf(object):
self.gcc_list = ['core/utils', 'core/protocol', 'core/socket', 'core/logging', 'core/master', 'core/master_utils', 'core/emperor',
'core/notify', 'core/mule', 'core/subscription', 'core/stats', 'core/sendfile', 'core/async', 'core/master_checks',
'core/offload', 'core/io', 'core/static', 'core/websockets', 'core/spooler', 'core/snmp', 'core/exceptions', 'core/config',
'core/setup_utils', 'core/clock', 'core/init', 'core/buffer', 'core/reader', 'core/writer', 'core/alarm',
'core/setup_utils', 'core/clock', 'core/init', 'core/buffer', 'core/reader', 'core/writer', 'core/alarm', 'core/cron',
'core/plugins', 'core/lock', 'core/cache', 'core/daemons', 'core/errors', 'core/hash', 'core/master_events',
'core/queue', 'core/event', 'core/signal', 'core/strings', 'core/progress', 'core/timebomb', 'core/ini',
'core/rpc', 'core/gateway', 'core/loop', 'core/cookie', 'core/querystring', 'core/rb_timers', 'core/uwsgi']
'core/rpc', 'core/gateway', 'core/loop', 'core/cookie', 'core/querystring', 'core/rb_timers', 'core/transformations', 'core/uwsgi']
# add protocols
self.gcc_list.append('proto/base')
self.gcc_list.append('proto/uwsgi')
@@ -524,6 +525,8 @@ class uConf(object):
# add -fno-strict-aliasing only on python2 and gcc < 4.3
if gcc_major >= 4:
self.cflags = self.cflags + [ '-Wextra', '-Wno-unused-parameter', '-Wno-missing-field-initializers' ]
if (gcc_major == 4 and gcc_minor >= 8) or gcc_major > 4:
self.cflags.append('-Wno-format')
self.ldflags = os.environ.get("LDFLAGS", "").split()
self.libs = ['-lpthread', '-lm', '-rdynamic']
@@ -669,6 +672,8 @@ class uConf(object):
self.cflags.append('-DUWSGI_LOCK_USE_OSX_SPINLOCK')
elif locking_mode == 'windows_mutex':
self.cflags.append('-DUWSGI_LOCK_USE_WINDOWS_MUTEX')
else:
self.cflags.append('-DUWSGI_IPCSEM_ATEXIT')
if locking_mode == 'auto':
report['locking'] = 'sysv semaphores'
@@ -730,7 +735,7 @@ class uConf(object):
if int(sun_minor) >= 10:
timer_mode = 'port'
elif uwsgi_os in ('Darwin', 'FreeBSD'):
elif uwsgi_os in ('Darwin', 'FreeBSD', 'OpenBSD', 'NetBSD', 'DragonFly'):
timer_mode = 'kqueue'
if timer_mode == 'timerfd':
@@ -971,19 +976,6 @@ class uConf(object):
if has_json:
report['json'] = True
if self.get('ldap'):
if self.get('ldap') == 'auto':
if self.has_include('ldap.h'):
self.cflags.append("-DUWSGI_LDAP")
self.gcc_list.append('core/ldap')
self.libs.append('-lldap')
report['ldap'] = True
else:
self.cflags.append("-DUWSGI_LDAP")
self.gcc_list.append('core/ldap')
self.libs.append('-lldap')
report['ldap'] = True
if self.get('ssl'):
if self.get('ssl') == 'auto':
if self.has_include('openssl/ssl.h'):
@@ -1052,20 +1044,6 @@ class uConf(object):
self.gcc_list.append('core/xmlconf')
report['xml'] = 'expat'
if self.get('sqlite3'):
if self.get('sqlite3') == 'auto':
if self.has_include('sqlite3.h'):
self.cflags.append("-DUWSGI_SQLITE3")
self.libs.append('-lsqlite3')
self.gcc_list.append('core/sqlite3')
report['sqlite3'] = True
else:
self.cflags.append("-DUWSGI_SQLITE3")
self.libs.append('-lsqlite3')
self.gcc_list.append('core/sqlite3')
report['sqlite3'] = True
if self.get('plugin_dir'):
self.cflags.append('-DUWSGI_PLUGIN_DIR=\\"%s\\"' % self.get('plugin_dir'))
report['plugin_dir'] = self.get('plugin_dir')