mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d82ee16e0c | ||
|
|
e4d65c07ce | ||
|
|
86fcb78cc3 | ||
|
|
5beb422d75 | ||
|
|
53679879ca | ||
|
|
a8ad766182 | ||
|
|
cbb2d30f79 | ||
|
|
c5e00bcec6 | ||
|
|
51535d374d | ||
|
|
1e057e6c35 | ||
|
|
b23e8ab862 | ||
|
|
0f7f13dfb2 | ||
|
|
aa19ccda1d | ||
|
|
cd0129e780 | ||
|
|
506c9023e6 | ||
|
|
d47c25ea4c | ||
|
|
010651073c | ||
|
|
76364e3799 | ||
|
|
f9fd0a0203 | ||
|
|
8dfbde5d16 | ||
|
|
888991f8c1 | ||
|
|
ece03922d6 | ||
|
|
47bb827e6e | ||
|
|
a56003d847 | ||
|
|
61022c398c | ||
|
|
00bd8cc525 | ||
|
|
cf6a232aef | ||
|
|
59d1a45ef0 | ||
|
|
0b5f9fcb48 | ||
|
|
f713ffd6a1 | ||
|
|
22ba9d81d4 | ||
|
|
309bc98d7f | ||
|
|
9b8646a583 | ||
|
|
48d1b87ab8 | ||
|
|
c5f849d846 | ||
|
|
31fbb6e4f5 | ||
|
|
4d9a88e999 | ||
|
|
252e8484a8 | ||
|
|
1b89203932 | ||
|
|
673cb3ee21 |
@@ -2,10 +2,8 @@
|
||||
xml = auto
|
||||
yaml = true
|
||||
json = auto
|
||||
sqlite3 = auto
|
||||
zeromq = auto
|
||||
ssl = auto
|
||||
ldap = auto
|
||||
pcre = auto
|
||||
routing = auto
|
||||
debug = false
|
||||
|
||||
@@ -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,10 +2,8 @@
|
||||
xml = true
|
||||
yaml = true
|
||||
json = false
|
||||
sqlite3 = false
|
||||
zeromq = false
|
||||
ssl = true
|
||||
ldap = false
|
||||
pcre = true
|
||||
routing = true
|
||||
debug = false
|
||||
|
||||
+88
-77
@@ -288,21 +288,7 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
|
||||
(unsigned long long) ((sizeof(struct uwsgi_cache_item)+uc->keysize) * uc->max_items), (unsigned long long) (uc->blocksize * uc->max_items),
|
||||
(unsigned long long) uc->blocks_bitmap_size);
|
||||
|
||||
|
||||
struct uwsgi_string_list *usl = uc->nodes;
|
||||
while(usl) {
|
||||
char *port = strchr(usl->value, ':');
|
||||
if (!port) {
|
||||
uwsgi_log("[cache-udp-node] invalid udp address: %s\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
// no need to zero the memory, socket_to_in_addr will do that
|
||||
struct sockaddr_in *sin = uwsgi_malloc(sizeof(struct sockaddr_in));
|
||||
usl->custom = socket_to_in_addr(usl->value, port, 0, sin);
|
||||
usl->custom_ptr = sin;
|
||||
uwsgi_log("added udp node %s for cache \"%s\"\n", usl->value, uc->name);
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_cache_setup_nodes(uc);
|
||||
|
||||
uc->udp_node_socket = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (uc->udp_node_socket < 0) {
|
||||
@@ -311,70 +297,10 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
|
||||
}
|
||||
uwsgi_socket_nb(uc->udp_node_socket);
|
||||
|
||||
usl = uc->sync_nodes;
|
||||
while(usl) {
|
||||
uwsgi_log("[cache-sync] getting cache dump from %s ...\n", usl->value);
|
||||
int fd = uwsgi_connect(usl->value, 0, 0);
|
||||
if (fd < 0) {
|
||||
uwsgi_log("[cache-sync] unable to connect to the cache server\n");
|
||||
goto next;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size + uc->filesize);
|
||||
ub->pos = 4;
|
||||
if (uwsgi_buffer_append(ub, uc->name, uc->name_len)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (uwsgi_buffer_set_uh(ub, 111, 6)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (uwsgi_write_nb(fd, ub->buf, ub->pos, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_log("[cache-sync] unable to write to the cache server\n");
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
size_t rlen = ub->pos;
|
||||
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_log("[cache-sync] unable to read from the cache server\n");
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
uwsgi_hooked_parse(ub->buf, ub->pos, cache_sync_hook, uc);
|
||||
|
||||
if (uwsgi_read_nb(fd, (char *) uc->items, uc->filesize, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
uwsgi_log("[cache-sync] unable to read from the cache server\n");
|
||||
goto next;
|
||||
}
|
||||
|
||||
// reset the hashtable
|
||||
memset(uc->hashtable, 0, sizeof(uint64_t) * UMAX16);
|
||||
// re-fill the hashtable
|
||||
uwsgi_cache_fix(uc);
|
||||
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
break;
|
||||
next:
|
||||
if (!usl->next) {
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("[cache-sync] trying with the next sync node...\n");
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_cache_sync_from_nodes(uc);
|
||||
|
||||
uwsgi_cache_load_files(uc);
|
||||
|
||||
}
|
||||
|
||||
static uint64_t uwsgi_cache_get_index(struct uwsgi_cache *uc, char *key, uint16_t keylen) {
|
||||
@@ -1696,3 +1622,88 @@ int uwsgi_cache_magic_clear(char *cache) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_cache_sync_from_nodes(struct uwsgi_cache *uc) {
|
||||
struct uwsgi_string_list *usl = uc->sync_nodes;
|
||||
usl = uc->sync_nodes;
|
||||
while(usl) {
|
||||
uwsgi_log("[cache-sync] getting cache dump from %s ...\n", usl->value);
|
||||
int fd = uwsgi_connect(usl->value, 0, 0);
|
||||
if (fd < 0) {
|
||||
uwsgi_log("[cache-sync] unable to connect to the cache server\n");
|
||||
goto next;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size + uc->filesize);
|
||||
ub->pos = 4;
|
||||
if (uwsgi_buffer_append(ub, uc->name, uc->name_len)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (uwsgi_buffer_set_uh(ub, 111, 6)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (uwsgi_write_nb(fd, ub->buf, ub->pos, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_log("[cache-sync] unable to write to the cache server\n");
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
size_t rlen = ub->pos;
|
||||
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_log("[cache-sync] unable to read from the cache server\n");
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
uwsgi_hooked_parse(ub->buf, ub->pos, cache_sync_hook, uc);
|
||||
|
||||
if (uwsgi_read_nb(fd, (char *) uc->items, uc->filesize, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
uwsgi_log("[cache-sync] unable to read from the cache server\n");
|
||||
goto next;
|
||||
}
|
||||
|
||||
// reset the hashtable
|
||||
memset(uc->hashtable, 0, sizeof(uint64_t) * UMAX16);
|
||||
// re-fill the hashtable
|
||||
uwsgi_cache_fix(uc);
|
||||
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
break;
|
||||
next:
|
||||
if (!usl->next) {
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("[cache-sync] trying with the next sync node...\n");
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_cache_setup_nodes(struct uwsgi_cache *uc) {
|
||||
struct uwsgi_string_list *usl = uc->nodes;
|
||||
while(usl) {
|
||||
char *port = strchr(usl->value, ':');
|
||||
if (!port) {
|
||||
uwsgi_log("[cache-udp-node] invalid udp address: %s\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
// no need to zero the memory, socket_to_in_addr will do that
|
||||
struct sockaddr_in *sin = uwsgi_malloc(sizeof(struct sockaddr_in));
|
||||
usl->custom = socket_to_in_addr(usl->value, port, 0, sin);
|
||||
usl->custom_ptr = sin;
|
||||
uwsgi_log("added udp node %s for cache \"%s\"\n", usl->value, uc->name);
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -210,6 +210,15 @@ static void legions_check_nodes() {
|
||||
uwsgi_wlock(legion->lock);
|
||||
uwsgi_legion_remove_node(legion, tmp_node);
|
||||
uwsgi_rwunlock(legion->lock);
|
||||
// trigger node_left hooks
|
||||
struct uwsgi_string_list *usl = legion->node_left_hooks;
|
||||
while (usl) {
|
||||
int ret = uwsgi_legion_action_call("node_left", legion, usl);
|
||||
if (ret) {
|
||||
uwsgi_log("[uwsgi-legion] ERROR, node_left hook returned: %d\n", ret);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
node = node->next;
|
||||
@@ -570,6 +579,15 @@ static void *legion_loop(void *foobar) {
|
||||
legion_rebuild_scrolls(ul);
|
||||
uwsgi_rwunlock(ul->lock);
|
||||
uwsgi_log("[uwsgi-legion] node: %.*s valor: %llu uuid: %.*s joined Legion %s\n", node->name_len, node->name, node->valor, 36, node->uuid, ul->legion);
|
||||
// trigger node_joined hooks
|
||||
struct uwsgi_string_list *usl = ul->node_joined_hooks;
|
||||
while (usl) {
|
||||
int ret = uwsgi_legion_action_call("node_joined", ul, usl);
|
||||
if (ret) {
|
||||
uwsgi_log("[uwsgi-legion] ERROR, node_joined hook returned: %d\n", ret);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
node->last_seen = uwsgi_now();
|
||||
@@ -882,6 +900,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);
|
||||
|
||||
@@ -679,9 +679,6 @@ ready:
|
||||
// timer table lock
|
||||
uwsgi.timer_table_lock = uwsgi_lock_init("timer");
|
||||
|
||||
// probe table lock
|
||||
uwsgi.probe_table_lock = uwsgi_lock_init("probe");
|
||||
|
||||
// rb_timer table lock
|
||||
uwsgi.rb_timer_table_lock = uwsgi_lock_init("rbtimer");
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
|
||||
uWSGI metrics subsystem
|
||||
|
||||
a metric is a node in a tree reachable via a numeric id (OID, in SNMP way) or a simple string:
|
||||
|
||||
uwsgi.worker.1.requests
|
||||
uwsgi.custom.foo.bar
|
||||
|
||||
the oid representation:
|
||||
|
||||
1.3.6.1.4.1.35156.17 = iso.org.dod.internet.private.enterprise.unbit.uwsgi
|
||||
1.3.6.1.4.1.35156.17.3.1.1 = iso.org.dod.internet.private.enterprise.unbit.uwsgi.worker.1.requests
|
||||
1.3.6.1.4.1.35156.17.3.1.1 = iso.org.dod.internet.private.enterprise.unbit.uwsgi.worker.1.requests
|
||||
1.3.6.1.4.1.35156.17.3.1.2.1.1 = iso.org.dod.internet.private.enterprise.unbit.uwsgi.worker.1.core.1.requests
|
||||
1.3.6.1.4.1.35156.17.4.1 = iso.org.dod.internet.private.enterprise.unbit.uwsgi.system.load_avg
|
||||
...
|
||||
|
||||
each metric is a collected value with a specific frequency (a frequency of zero means the value is re-computed every time)
|
||||
metrics are meant for numeric values signed 64 bit, but they can be exposed as:
|
||||
|
||||
gauge
|
||||
counter
|
||||
absolute
|
||||
|
||||
both 32 and 64bit, both signed and unsigned
|
||||
|
||||
metrics are managed by a dedicated thread (in the master) holding a linked list of all the items. For few metrics it is a good (read: simple) approach,
|
||||
but you can cache lookups in a uWSGI cache for really big list.
|
||||
|
||||
struct uwsgi_metric *um = uwsgi_register_metric("worker.1.requests", "3.1.1", UWSGI_METRIC_COUNTER, UWSGI_METRIC_PTR, &uwsgi.workers[1].requests, 0, NULL);
|
||||
prototype: struct uwsgi_metric *uwsgi_register_metric(char *name, char *oid, uint8_t value_type, uint8_t collect_way, void *ptr, uint32_t freq, void *custom);
|
||||
|
||||
value_type = UWSGI_METRIC_COUNTER/UWSGI_METRIC_GAUGE/UWSGI_METRIC_ABSOLUTE
|
||||
collect_way = UWSGI_METRIC_PTR -> get from a pointer / UWSGI_METRIC_FUNC -> get from a func with the prototype int64_t func(struct uwsgi_metric *); / UWSGI_METRIC_FILE -> get the value from a file, ptr is the filename
|
||||
|
||||
when freq is zero the value is recomputed whenever requested, otherwise the metrics thread compute it every time the frequency is elapsed and caches it
|
||||
|
||||
For some metric (or all ?) you may want to hold a value even after a server reload. For such a reason you can specify a directory on wich the server (on startup/restart) will look for
|
||||
a file named like the metric and will read the initial value from it. It may look an old-fashioned and quite inefficient way, but it is the most versatile for a sysadmin (allowing him/her
|
||||
to even modify the values manually)
|
||||
|
||||
When registering a metric with the same name of an already registered one, the new one will overwrite the previous one. This allows plugins writer to override default behaviours
|
||||
|
||||
Applications are allowed to update metrics (but they cannot register new ones), with simple api funcs:
|
||||
|
||||
uwsgi.metric_set("worker.1.requests", N)
|
||||
uwsgi.metric_inc("worker.1.requests", N=1)
|
||||
uwsgi.metric_dec("worker.1.requests", N=1)
|
||||
uwsgi.metric_mul("worker.1.requests", N=1)
|
||||
uwsgi.metric_div("worker.1.requests", N=1)
|
||||
|
||||
and obviously they can get values:
|
||||
|
||||
uwsgi.metric_get("worker.1.requests", no_cache|force=False)
|
||||
if the second parameter is True, the value is recomputed (but if it is a metric with a cache, the cache value will not be updated accordingly, this is the job of the metric thread)
|
||||
|
||||
Updating metrics from your app MUST BE ATOMIC, for such a reason a uWSGI rwlock is initialized on startup and used for each operation (simple reading from a metric does not require locking)
|
||||
|
||||
Metrics can be updated from the internal routing subsystem too:
|
||||
|
||||
route-if = equal:${REQUEST_URI};/foobar metricinc:foobar.test 2
|
||||
|
||||
and can be accessed as ${metric[foobar.test]}
|
||||
|
||||
The stats server exports the metrics list in the "metrics" attribute (obviously some info could be redundant)
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_metric {
|
||||
char *name;
|
||||
char *oid;
|
||||
|
||||
// pre-computed snmp representation
|
||||
char *asn;
|
||||
size_t asn_size;
|
||||
|
||||
// ABSOLUTE/COUNTER/GAUGE
|
||||
uint8_t type;
|
||||
|
||||
// the value of the metric
|
||||
int64_t value;
|
||||
|
||||
// a custom blob you can attach to a metric
|
||||
void *custom;
|
||||
|
||||
// the collection frequency
|
||||
uint32_t freq;
|
||||
time_t last_update;
|
||||
|
||||
// run this function to collect the value
|
||||
int64_t (*collector)(struct uwsgi_metric *);
|
||||
// take the value from this pointer to a 64bit value
|
||||
int64_t *ptr;
|
||||
// get the initial value from this file, and store each update in it
|
||||
char *filename;
|
||||
|
||||
struct uwsgi_metric *next;
|
||||
};
|
||||
|
||||
struct uwsgi_metric *uwsgi_register_metric(char *name, char *oid, uint8_t value_type, uint8_t collect_way, void *ptr, uint32_t freq, void *custom) {
|
||||
struct uwsgi_metric *old_metric=NULL,*metric=uwsgi.metric;
|
||||
|
||||
while(metric) {
|
||||
metric = metric->next;
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_metric_loop() {
|
||||
// every second scan the whole metrics tree
|
||||
time_t now = uwsgi_now();
|
||||
}
|
||||
+97
-4
@@ -2,7 +2,7 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
// this is line uwsgi_str_num but with security checks
|
||||
// this is like uwsgi_str_num but with security checks
|
||||
static size_t get_content_length(char *buf, uint16_t size) {
|
||||
int i;
|
||||
size_t val = 0;
|
||||
@@ -80,7 +80,7 @@ ssize_t send_udp_message(uint8_t modifier1, uint8_t modifier2, char *host, char
|
||||
ret = sendto(fd, (char *) uh, message_size + 4, 0, (struct sockaddr *) &un_addr, sizeof(un_addr));
|
||||
}
|
||||
if (ret < 0) {
|
||||
uwsgi_error("sendto()");
|
||||
uwsgi_error("send_udp_message()/sendto()");
|
||||
}
|
||||
close(fd);
|
||||
|
||||
@@ -303,8 +303,41 @@ static int uwsgi_proto_check_9(struct wsgi_request *wsgi_req, char *key, char *b
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uwsgi_parse_http_range(char *buf, uint16_t len, size_t *from, size_t *to) {
|
||||
*from = 0;
|
||||
*to = 0;
|
||||
uint16_t rlen = 0;
|
||||
uint16_t i;
|
||||
for(i=0;i<len;i++) {
|
||||
if (buf[i] == ',') break;
|
||||
rlen++;
|
||||
}
|
||||
|
||||
// bytes=X-
|
||||
if (rlen < 8) return;
|
||||
char *equal = memchr(buf, '=', rlen);
|
||||
if (!equal) return;
|
||||
if (equal-buf != 5) return;
|
||||
if (memcmp(buf, "bytes", 5)) return;
|
||||
char *range = equal+1;
|
||||
rlen -= 6;
|
||||
char *dash = memchr(range, '-', rlen);
|
||||
if (!dash) return;
|
||||
*from = uwsgi_str_num(range, dash-range);
|
||||
*to = uwsgi_str_num(dash+1, rlen - ((dash+1)-range));
|
||||
if (*to > 0 && *from > *to) {
|
||||
*from = 0;
|
||||
*to = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int uwsgi_proto_check_10(struct wsgi_request *wsgi_req, char *key, char *buf, uint16_t len) {
|
||||
|
||||
if (uwsgi.honour_range && !uwsgi_proto_key("HTTP_RANGE", 10)) {
|
||||
uwsgi_parse_http_range(buf, len, &wsgi_req->range_from, &wsgi_req->range_to);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!uwsgi_proto_key("UWSGI_FILE", 10)) {
|
||||
wsgi_req->file = buf;
|
||||
wsgi_req->file_len = len;
|
||||
@@ -312,6 +345,12 @@ static int uwsgi_proto_check_10(struct wsgi_request *wsgi_req, char *key, char *
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!uwsgi_proto_key("UWSGI_HOME", 10)) {
|
||||
wsgi_req->home = buf;
|
||||
wsgi_req->home_len = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
+353
@@ -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;
|
||||
@@ -865,6 +1129,70 @@ static int uwsgi_route_condition_isexec(struct wsgi_request *wsgi_req, struct uw
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *uwsgi_route_var_uwsgi(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
char *ret = NULL;
|
||||
if (!uwsgi_strncmp(key, keylen, "wid", 3)) {
|
||||
ret = uwsgi_num2str(uwsgi.mywid);
|
||||
*vallen = strlen(ret);
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "pid", 3)) {
|
||||
ret = uwsgi_num2str(uwsgi.mypid);
|
||||
*vallen = strlen(ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *uwsgi_route_var_time(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
char *ret = NULL;
|
||||
if (!uwsgi_strncmp(key, keylen, "unix", 4)) {
|
||||
ret = uwsgi_num2str(uwsgi_now());
|
||||
*vallen = strlen(ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_MATHEVAL
|
||||
static char *uwsgi_route_var_math(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
char *ret = NULL;
|
||||
// avoid crash
|
||||
if (!wsgi_req->var_cnt) return NULL;
|
||||
// we make a bit of fun here, we do a copy of the vars buffer (+1 byte for final zero) and zeor-pad all of the strings
|
||||
char *vars_buf = uwsgi_malloc(wsgi_req->uh->pktsize + keylen + 1);
|
||||
char **names = uwsgi_malloc(sizeof(char *) * (wsgi_req->var_cnt/2));
|
||||
double *values = uwsgi_calloc(sizeof(double) * (wsgi_req->var_cnt/2));
|
||||
int i,j = 0;
|
||||
char *ptr = vars_buf;
|
||||
for (i = wsgi_req->var_cnt-1; i > 0; i -= 2) {
|
||||
memcpy(ptr, wsgi_req->hvec[i-1].iov_base, wsgi_req->hvec[i-1].iov_len);
|
||||
names[j] = ptr;
|
||||
ptr += wsgi_req->hvec[i-1].iov_len;
|
||||
*ptr++=0;
|
||||
char *num = ptr;
|
||||
memcpy(ptr, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
|
||||
ptr += wsgi_req->hvec[i].iov_len;
|
||||
*ptr++=0;
|
||||
values[j] = strtod(num, NULL);
|
||||
j++;
|
||||
}
|
||||
|
||||
char *expr = ptr;
|
||||
memcpy(ptr, key, keylen); ptr += keylen;
|
||||
*ptr++=0;
|
||||
|
||||
void *e = evaluator_create(expr);
|
||||
if (!e) goto end;
|
||||
double n = evaluator_evaluate(e, j, names, values);
|
||||
evaluator_destroy(e);
|
||||
ret = uwsgi_num2str((int)n);
|
||||
*vallen = strlen(ret);
|
||||
end:
|
||||
free(vars_buf);
|
||||
free(names);
|
||||
free(values);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
// register embedded routers
|
||||
void uwsgi_register_embedded_routers() {
|
||||
@@ -882,6 +1210,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 +1230,30 @@ 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);
|
||||
#ifdef UWSGI_SSL
|
||||
uwsgi_register_route_condition("lord", uwsgi_route_condition_lord);
|
||||
#endif
|
||||
|
||||
uwsgi_register_route_condition("empty", uwsgi_route_condition_empty);
|
||||
|
||||
uwsgi_register_route_var("cookie", uwsgi_get_cookie);
|
||||
uwsgi_register_route_var("qs", uwsgi_get_qs);
|
||||
struct uwsgi_route_var *urv = uwsgi_register_route_var("uwsgi", uwsgi_route_var_uwsgi);
|
||||
urv->need_free = 1;
|
||||
urv = uwsgi_register_route_var("time", uwsgi_route_var_time);
|
||||
urv->need_free = 1;
|
||||
#ifdef UWSGI_MATHEVAL
|
||||
urv = uwsgi_register_route_var("math", uwsgi_route_var_math);
|
||||
urv->need_free = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
struct uwsgi_router *uwsgi_register_router(char *name, int (*func) (struct uwsgi_route *, char *)) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()");
|
||||
|
||||
@@ -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
|
||||
+31
-4
@@ -451,8 +451,31 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
|
||||
uwsgi_log("[uwsgi-fileserve] file %s found\n", real_filename);
|
||||
#endif
|
||||
|
||||
size_t fsize = st->st_size;
|
||||
if (wsgi_req->range_to) {
|
||||
fsize = wsgi_req->range_to - wsgi_req->range_from;
|
||||
if (fsize > (size_t)st->st_size) {
|
||||
fsize = st->st_size;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// reset in case of inconsistent size
|
||||
if (wsgi_req->range_from > fsize) {
|
||||
wsgi_req->range_from = 0;
|
||||
fsize = 0 ;
|
||||
}
|
||||
else {
|
||||
fsize -= wsgi_req->range_from;
|
||||
}
|
||||
}
|
||||
|
||||
// HTTP status
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return -1;
|
||||
if (fsize > 0 && (wsgi_req->range_from || wsgi_req->range_to)) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "206 Partial Content", 19)) return -1;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return -1;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
uwsgi_add_expires(wsgi_req, real_filename, real_filename_len, st);
|
||||
@@ -490,8 +513,12 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
|
||||
if (uwsgi_static_want_gzip(wsgi_req, real_filename, real_filename_len, st)) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Content-Encoding", 16, "gzip", 4)) return -1;
|
||||
}
|
||||
// set Content-Length
|
||||
if (uwsgi_response_add_content_length(wsgi_req, st->st_size)) return -1;
|
||||
// set Content-Length (to fsize NOT st->st_size)
|
||||
if (uwsgi_response_add_content_length(wsgi_req, fsize)) return -1;
|
||||
if (fsize > 0 && (wsgi_req->range_from || wsgi_req->range_to)) {
|
||||
// here use teh original size !!!
|
||||
if (uwsgi_response_add_content_range(wsgi_req, wsgi_req->range_from, wsgi_req->range_to, st->st_size)) return -1;
|
||||
}
|
||||
int size = set_http_date(st->st_mtime, http_last_modified);
|
||||
if (uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, http_last_modified, size)) return -1;
|
||||
|
||||
@@ -506,7 +533,7 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
|
||||
int fd = open(real_filename, O_RDONLY);
|
||||
if (fd < 0) return -1;
|
||||
// fd will be closed in the following function
|
||||
uwsgi_response_sendfile_do(wsgi_req, fd, 0, st->st_size);
|
||||
uwsgi_response_sendfile_do(wsgi_req, fd, wsgi_req->range_from, fsize);
|
||||
}
|
||||
|
||||
wsgi_req->status = 200;
|
||||
|
||||
+26
-4
@@ -1525,6 +1525,25 @@ int uwsgi_logic_opt_for_glob(char *key, char *value) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_for_times(char *key, char *value) {
|
||||
|
||||
int num = atoi(uwsgi.logic_opt_data);
|
||||
int i;
|
||||
char str_num[11];
|
||||
|
||||
for (i = 1; i <= num; i++) {
|
||||
int ret = uwsgi_num2str2(i, str_num);
|
||||
// security check
|
||||
if (ret < 0 || ret > 11) {
|
||||
exit(1);
|
||||
}
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", str_num), 0);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void add_exported_option(char *key, char *value, int configured) {
|
||||
|
||||
@@ -3054,14 +3073,17 @@ void http_url_decode(char *buf, uint16_t * len, char *dst) {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
we scan the table in reverse, as updated values are at the end
|
||||
*/
|
||||
char *uwsgi_get_var(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t * len) {
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
|
||||
if (!uwsgi_strncmp(key, keylen, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len)) {
|
||||
*len = wsgi_req->hvec[i + 1].iov_len;
|
||||
return wsgi_req->hvec[i + 1].iov_base;
|
||||
for (i = wsgi_req->var_cnt-1; i > 0; i -= 2) {
|
||||
if (!uwsgi_strncmp(key, keylen, wsgi_req->hvec[i-1].iov_base, wsgi_req->hvec[i-1].iov_len)) {
|
||||
*len = wsgi_req->hvec[i].iov_len;
|
||||
return wsgi_req->hvec[i].iov_base;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+9
-23
@@ -80,6 +80,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},
|
||||
|
||||
@@ -294,20 +295,11 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"json", required_argument, 'j', "load config from json file", uwsgi_opt_load_json, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"js", required_argument, 'j', "load config from json file", uwsgi_opt_load_json, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#endif
|
||||
#ifdef UWSGI_SQLITE3
|
||||
{"sqlite3", required_argument, 0, "load config from sqlite3 db", uwsgi_opt_load_sqlite3, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"sqlite", required_argument, 0, "load config from sqlite3 db", uwsgi_opt_load_sqlite3, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#endif
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
{"zeromq", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "zmq", 0},
|
||||
{"zmq", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "zmq", 0},
|
||||
{"zeromq-socket", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "zmq", 0},
|
||||
{"zmq-socket", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "zmq", 0},
|
||||
#endif
|
||||
#ifdef UWSGI_LDAP
|
||||
{"ldap", required_argument, 0, "load configuration from ldap server", uwsgi_opt_load_ldap, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"ldap-schema", no_argument, 0, "dump uWSGI ldap schema", uwsgi_opt_ldap_dump, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"ldap-schema-ldif", no_argument, 0, "dump uWSGI ldap schema in ldif format", uwsgi_opt_ldap_dump_ldif, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#endif
|
||||
{"weight", required_argument, 0, "weight of the instance (used by clustering/lb/subscriptions)", uwsgi_opt_set_64bit, &uwsgi.weight, 0},
|
||||
{"auto-weight", required_argument, 0, "set weight of the instance (used by clustering/lb/subscriptions) automatically", uwsgi_opt_true, &uwsgi.auto_weight, 0},
|
||||
@@ -320,6 +312,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"socket-send-timeout", no_argument, 0, "set SO_SNDTIMEO", uwsgi_opt_set_int, &uwsgi.so_send_timeout, 0},
|
||||
{"so-write-timeout", no_argument, 0, "set SO_SNDTIMEO", uwsgi_opt_set_int, &uwsgi.so_send_timeout, 0},
|
||||
{"socket-write-timeout", no_argument, 0, "set SO_SNDTIMEO", uwsgi_opt_set_int, &uwsgi.so_send_timeout, 0},
|
||||
{"socket-sndbuf", required_argument, 0, "set SO_SNDBUF", uwsgi_opt_set_64bit, &uwsgi.so_sndbuf, 0},
|
||||
{"socket-rcvbuf", required_argument, 0, "set SO_RCVBUF", uwsgi_opt_set_64bit, &uwsgi.so_rcvbuf, 0},
|
||||
{"limit-as", required_argument, 0, "limit processes address space/vsz", uwsgi_opt_set_megabytes, &uwsgi.rl.rlim_max, 0},
|
||||
{"limit-nproc", required_argument, 0, "limit the number of spawnable processes", uwsgi_opt_set_int, &uwsgi.rl_nproc.rlim_max, 0},
|
||||
{"reload-on-as", required_argument, 0, "reload if address space is higher than specified megabytes", uwsgi_opt_set_megabytes, &uwsgi.reload_on_as, UWSGI_OPT_MEMORY},
|
||||
@@ -385,6 +379,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},
|
||||
@@ -576,6 +572,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"static-gzip-ext", required_argument, 0, "check for a gzip version of all requested static files with the specified ext/suffix", uwsgi_opt_add_string_list, &uwsgi.static_gzip_ext, UWSGI_OPT_MIME},
|
||||
{"static-gzip-suffix", required_argument, 0, "check for a gzip version of all requested static files with the specified ext/suffix", uwsgi_opt_add_string_list, &uwsgi.static_gzip_ext, UWSGI_OPT_MIME},
|
||||
|
||||
{"honour-range", no_argument, 0, "enable support for the HTTP Range header", uwsgi_opt_true, &uwsgi.honour_range, 0},
|
||||
|
||||
{"offload-threads", required_argument, 0, "set the number of offload threads to spawn (per-worker, default 0)", uwsgi_opt_set_int, &uwsgi.offload_threads, 0},
|
||||
{"offload-thread", required_argument, 0, "set the number of offload threads to spawn (per-worker, default 0)", uwsgi_opt_set_int, &uwsgi.offload_threads, 0},
|
||||
|
||||
@@ -1372,7 +1370,7 @@ void fixup_argv_and_environ(int argc, char **argv, char **environ) {
|
||||
env_count++;
|
||||
}
|
||||
|
||||
uwsgi.environ = uwsgi_malloc(sizeof(char *) * env_count);
|
||||
uwsgi.environ = uwsgi_malloc(sizeof(char *) * (env_count+1));
|
||||
for (i = 0; i < env_count; i++) {
|
||||
uwsgi.environ[i] = strdup(environ[i]);
|
||||
#ifdef UWSGI_DEBUG
|
||||
@@ -1380,6 +1378,7 @@ void fixup_argv_and_environ(int argc, char **argv, char **environ) {
|
||||
#endif
|
||||
environ[i] = uwsgi.environ[i];
|
||||
}
|
||||
uwsgi.environ[env_count] = NULL;
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("max space for custom process name = %d\n", uwsgi.max_procname);
|
||||
@@ -3883,13 +3882,6 @@ void uwsgi_opt_load_yml(char *opt, char *filename, void *none) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_SQLITE3
|
||||
void uwsgi_opt_load_sqlite3(char *opt, char *filename, void *none) {
|
||||
config_magic_table_fill(filename, uwsgi.magic_table);
|
||||
uwsgi_sqlite3_config(filename, uwsgi.magic_table);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_JSON
|
||||
void uwsgi_opt_load_json(char *opt, char *filename, void *none) {
|
||||
config_magic_table_fill(filename, uwsgi.magic_table);
|
||||
@@ -3897,12 +3889,6 @@ void uwsgi_opt_load_json(char *opt, char *filename, void *none) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_LDAP
|
||||
void uwsgi_opt_load_ldap(char *opt, char *url, void *none) {
|
||||
uwsgi_ldap_config(url);
|
||||
}
|
||||
#endif
|
||||
|
||||
void uwsgi_opt_add_custom_option(char *opt, char *value, void *none) {
|
||||
|
||||
struct uwsgi_custom_option *uco = uwsgi.custom_options, *old_uco;
|
||||
|
||||
@@ -12,6 +12,19 @@ int uwsgi_response_add_content_length(struct wsgi_request *wsgi_req, uint64_t cl
|
||||
return uwsgi_response_add_header(wsgi_req, "Content-Length", 14, buf, ret);
|
||||
}
|
||||
|
||||
int uwsgi_response_add_content_range(struct wsgi_request *wsgi_req, uint64_t start, uint64_t end, uint64_t cl) {
|
||||
char buf[6+(sizeof(UMAX64_STR)*3)+4];
|
||||
if (end == 0) {
|
||||
end = cl-1;
|
||||
}
|
||||
int ret = snprintf(buf, 6+(sizeof(UMAX64_STR)*3)+4, "bytes %llu-%llu/%llu", (unsigned long long) start, (unsigned long long) end, (unsigned long long) cl);
|
||||
if (ret <= 0 || ret > (int) (6+(sizeof(UMAX64_STR)*3)+4)) {
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
return uwsgi_response_add_header(wsgi_req, "Content-Range", 13, buf, ret);
|
||||
}
|
||||
|
||||
// status could be NNN or NNN message
|
||||
int uwsgi_response_prepare_headers(struct wsgi_request *wsgi_req, char *status, uint16_t status_len) {
|
||||
|
||||
@@ -225,6 +238,7 @@ sendfile:
|
||||
if (can_close) close(fd);
|
||||
return -1;
|
||||
}
|
||||
if (pos >= (size_t)st.st_size) return UWSGI_OK;
|
||||
len = st.st_size;
|
||||
}
|
||||
|
||||
|
||||
+52
-4
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
#ifdef UWSGI_LDAP
|
||||
|
||||
#include "uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
@@ -14,7 +12,22 @@ extern struct uwsgi_server uwsgi;
|
||||
#define ldap_unbind_ext_s ldap_unbind_ext
|
||||
#endif
|
||||
|
||||
void ldap2uwsgi(char *ldapname, char *uwsginame) {
|
||||
static void uwsgi_opt_ldap_dump(char *, char *, void *);
|
||||
static void uwsgi_opt_ldap_dump_ldif(char *, char *, void *);
|
||||
static void uwsgi_ldap_config(char *);
|
||||
|
||||
static void uwsgi_opt_load_ldap(char *opt, char *url, void *none) {
|
||||
uwsgi_ldap_config(url);
|
||||
}
|
||||
|
||||
static struct uwsgi_option uwsgi_ldap_options[] = {
|
||||
{"ldap", required_argument, 0, "load configuration from ldap server", uwsgi_opt_load_ldap, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"ldap-schema", no_argument, 0, "dump uWSGI ldap schema", uwsgi_opt_ldap_dump, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"ldap-schema-ldif", no_argument, 0, "dump uWSGI ldap schema in ldif format", uwsgi_opt_ldap_dump_ldif, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
static void ldap2uwsgi(char *ldapname, char *uwsginame) {
|
||||
char *ptr = uwsginame;
|
||||
|
||||
int i;
|
||||
@@ -32,7 +45,7 @@ void ldap2uwsgi(char *ldapname, char *uwsginame) {
|
||||
*ptr++ = 0;
|
||||
}
|
||||
|
||||
int calc_ldap_name(char *name) {
|
||||
static int calc_ldap_name(char *name) {
|
||||
int i;
|
||||
int counter = 0;
|
||||
|
||||
@@ -52,7 +65,7 @@ struct uwsgi_ldap_entry {
|
||||
};
|
||||
|
||||
|
||||
void uwsgi_name_to_ldap(char *src, char *dst) {
|
||||
static void uwsgi_name_to_ldap(char *src, char *dst) {
|
||||
|
||||
int i;
|
||||
char *ptr = dst;
|
||||
@@ -77,22 +90,7 @@ void uwsgi_name_to_ldap(char *src, char *dst) {
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_ldap_entry *get_ldap_by_num(struct uwsgi_ldap_entry *root, int num, int count) {
|
||||
|
||||
int i;
|
||||
struct uwsgi_ldap_entry *ule;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
ule = &root[i];
|
||||
if (ule->num == num) {
|
||||
return ule;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *name, int count) {
|
||||
static struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *name, int count) {
|
||||
int i;
|
||||
struct uwsgi_ldap_entry *ule;
|
||||
|
||||
@@ -106,7 +104,7 @@ struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_ldap_entry *get_ldap_names(int *count) {
|
||||
static struct uwsgi_ldap_entry *get_ldap_names(int *count) {
|
||||
|
||||
struct uwsgi_option *op = uwsgi.options;
|
||||
struct uwsgi_ldap_entry *ule, *entry;
|
||||
@@ -139,7 +137,7 @@ next:
|
||||
return ule;
|
||||
}
|
||||
|
||||
void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
|
||||
static void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
|
||||
|
||||
int i;
|
||||
int items;
|
||||
@@ -192,7 +190,7 @@ void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
|
||||
static void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
|
||||
|
||||
int i;
|
||||
int items;
|
||||
@@ -240,7 +238,7 @@ void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void uwsgi_ldap_config(char *url) {
|
||||
static void uwsgi_ldap_config(char *url) {
|
||||
|
||||
LDAP *ldp;
|
||||
LDAPMessage *results, *entry;
|
||||
@@ -367,4 +365,8 @@ void uwsgi_ldap_config(char *url) {
|
||||
ldap_unbind_ext_s(ldp, NULL, NULL);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
struct uwsgi_plugin ldap_plugin = {
|
||||
.name = "ldap",
|
||||
.options = uwsgi_ldap_options,
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
NAME='ldap'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lldap']
|
||||
|
||||
GCC_LIST = ['ldap']
|
||||
@@ -8,17 +8,31 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_lua {
|
||||
struct lua_State **L;
|
||||
|
||||
char *shell;
|
||||
char *filename;
|
||||
struct uwsgi_string_list *load;
|
||||
} ulua;
|
||||
|
||||
#define lca(L, n) ulua_check_args(L, __FUNCTION__, n)
|
||||
|
||||
static void uwsgi_opt_luashell(char *opt, char *value, void *foobar) {
|
||||
|
||||
uwsgi.honour_stdin = 1;
|
||||
if (value) {
|
||||
ulua.shell = value;
|
||||
}
|
||||
else {
|
||||
ulua.shell = "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct uwsgi_option uwsgi_lua_options[] = {
|
||||
|
||||
{"lua", required_argument, 0, "load lua wsapi app", uwsgi_opt_set_str, &ulua.filename, 0},
|
||||
{"lua-load", required_argument, 0, "load a lua file", uwsgi_opt_add_string_list, &ulua.load, 0},
|
||||
{"lua-shell", no_argument, 0, "run the lua interactive shell (debug.debug())", uwsgi_opt_luashell, NULL, 0},
|
||||
{"luashell", no_argument, 0, "run the lua interactive shell (debug.debug())", uwsgi_opt_luashell, NULL, 0},
|
||||
|
||||
{0, 0, 0, 0},
|
||||
|
||||
@@ -347,6 +361,7 @@ static const luaL_reg uwsgi_api[] = {
|
||||
|
||||
{"lock", uwsgi_api_lock},
|
||||
{"unlock", uwsgi_api_unlock},
|
||||
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -389,13 +404,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 +783,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 +823,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,
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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']
|
||||
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int connect_prober_callback(int interesting_fd, struct uwsgi_signal_probe *up) {
|
||||
|
||||
// is this a timeout event ?
|
||||
if (interesting_fd == -1) {
|
||||
// am i wating for something ?
|
||||
if (up->fd != -1) {
|
||||
if (up->cycles > (uint64_t) up->timeout) {
|
||||
// reset the cycle
|
||||
up->cycles = 0;
|
||||
close(up->fd);
|
||||
up->fd = -1;
|
||||
// state = NOOP
|
||||
up->state = 0;
|
||||
// avoid duplicated events
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ok register a new event
|
||||
else {
|
||||
if ((up->cycles % up->freq) == 0) {
|
||||
up->fd = uwsgi_connect(up->args, -1, 1);
|
||||
if (up->fd != -1) {
|
||||
// status = CONNECTING
|
||||
up->state = 1;
|
||||
event_queue_add_fd_write(uwsgi.master_queue, up->fd);
|
||||
return 0;
|
||||
}
|
||||
// signal the bad event (if not already bad)
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (up->fd != -1) {
|
||||
// is this event for me ?
|
||||
if (interesting_fd == up->fd) {
|
||||
// uselsess here (we have only one state), only to show a good practice
|
||||
// check the state
|
||||
if (up->state == 1) {
|
||||
if (uwsgi_is_bad_connection(up->fd)) {
|
||||
// signal the bad connection (if needed)
|
||||
up->cycles = 0;
|
||||
close(up->fd);
|
||||
up->fd = -1;
|
||||
// state = NOOP
|
||||
up->state = 0;
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
// this is a good connection
|
||||
up->cycles = 0;
|
||||
close(up->fd);
|
||||
up->fd = -1;
|
||||
// state = NOOP
|
||||
up->state = 0;
|
||||
if (up->bad) {
|
||||
up->bad = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// default action
|
||||
return 0;
|
||||
}
|
||||
|
||||
int probeconnect_init() {
|
||||
|
||||
uwsgi_probe_register(&uwsgi.probes, "connect", connect_prober_callback);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin probeconnect_plugin = {
|
||||
|
||||
.init = probeconnect_init,
|
||||
};
|
||||
@@ -1,7 +0,0 @@
|
||||
|
||||
NAME='probeconnect'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
GCC_LIST = ['connectprobe']
|
||||
@@ -1,132 +0,0 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <libpq-fe.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
int pg_prober_callback(int, struct uwsgi_signal_probe *);
|
||||
int probepg_init(void);
|
||||
|
||||
int pg_prober_callback(int interesting_fd, struct uwsgi_signal_probe *up) {
|
||||
|
||||
// is this a timeout event ?
|
||||
if (interesting_fd == -1) {
|
||||
// am i wating for something ?
|
||||
if (up->fd != -1) {
|
||||
if (up->cycles > (uint64_t) up->timeout) {
|
||||
// reset the cycle
|
||||
up->cycles = 0;
|
||||
PQfinish((PGconn *) up->data);
|
||||
up->fd = -1;
|
||||
// state = NOOP
|
||||
up->state = 0;
|
||||
// avoid duplicated events
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ok register a new event
|
||||
else {
|
||||
if ((up->cycles % up->freq) == 0) {
|
||||
up->last_event = event_queue_write();
|
||||
up->data = (void *) PQconnectStart(up->args);
|
||||
if (up->data) {
|
||||
// status = CONNECTING
|
||||
up->state = PQstatus((PGconn *) up->data);
|
||||
if (up->state == CONNECTION_BAD)
|
||||
goto bad;
|
||||
up->fd = PQsocket((PGconn *) up->data);
|
||||
event_queue_add_fd_write(uwsgi.master_queue, up->fd);
|
||||
return 0;
|
||||
}
|
||||
bad:
|
||||
// signal the bad event (if not already bad)
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (up->fd != -1) {
|
||||
// is this event for me ?
|
||||
if (interesting_fd == up->fd) {
|
||||
// check the state
|
||||
up->state = PQstatus((PGconn *) up->data);
|
||||
if (up->state == CONNECTION_BAD) {
|
||||
// signal the bad connection (if needed)
|
||||
up->cycles = 0;
|
||||
PQfinish((PGconn *) up->data);
|
||||
up->fd = -1;
|
||||
up->state = 0;
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (up->state == CONNECTION_OK) {
|
||||
up->cycles = 0;
|
||||
PQfinish((PGconn *) up->data);
|
||||
up->fd = -1;
|
||||
// state = NOOP
|
||||
up->state = 0;
|
||||
if (up->bad) {
|
||||
up->bad = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// still wait...
|
||||
else {
|
||||
PostgresPollingStatusType wait_type = PQconnectPoll((PGconn *) up->data);
|
||||
// the connection is good
|
||||
if (wait_type == PGRES_POLLING_ACTIVE || wait_type == PGRES_POLLING_FAILED || wait_type == PGRES_POLLING_OK) {
|
||||
if (wait_type == PGRES_POLLING_ACTIVE)
|
||||
wait_type = PQconnectPoll((PGconn *) up->data);
|
||||
up->cycles = 0;
|
||||
up->fd = -1;
|
||||
// state = NOOP
|
||||
up->state = 0;
|
||||
PQfinish((PGconn *) up->data);
|
||||
if (wait_type == PGRES_POLLING_FAILED) {
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (up->bad) {
|
||||
up->bad = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (wait_type == PGRES_POLLING_READING) {
|
||||
event_queue_del_fd(uwsgi.master_queue, up->fd, up->last_event);
|
||||
event_queue_add_fd_read(uwsgi.master_queue, up->fd);
|
||||
up->last_event = event_queue_read();
|
||||
}
|
||||
else if (wait_type == PGRES_POLLING_WRITING) {
|
||||
event_queue_del_fd(uwsgi.master_queue, up->fd, up->last_event);
|
||||
event_queue_add_fd_write(uwsgi.master_queue, up->fd);
|
||||
up->last_event = event_queue_write();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// default action
|
||||
return 0;
|
||||
}
|
||||
|
||||
int probepg_init() {
|
||||
|
||||
uwsgi_probe_register(&uwsgi.probes, "pg", pg_prober_callback);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin probepg_plugin = {
|
||||
|
||||
.init = probepg_init,
|
||||
};
|
||||
@@ -1,9 +0,0 @@
|
||||
import os
|
||||
|
||||
NAME='probepg'
|
||||
CFLAGS = os.popen('pg_config --cflags').read().rstrip().split()
|
||||
CFLAGS.append('-I' + os.popen('pg_config --includedir').read().rstrip())
|
||||
LDFLAGS = os.popen('pg_config --ldflags').read().rstrip().split()
|
||||
LIBS = ['-L' + os.popen('pg_config --libdir').read().rstrip(), '-lpq']
|
||||
|
||||
GCC_LIST = ['pgprobe']
|
||||
@@ -33,12 +33,12 @@ void set_dyn_pyhome(char *home, uint16_t pyhome_len) {
|
||||
}
|
||||
|
||||
// simulate a pythonhome directive
|
||||
if (uwsgi.wsgi_req->pyhome_len > 0) {
|
||||
if (uwsgi.wsgi_req->home_len > 0) {
|
||||
|
||||
PyObject *venv_path = UWSGI_PYFROMSTRINGSIZE(uwsgi.wsgi_req->pyhome, uwsgi.wsgi_req->pyhome_len);
|
||||
PyObject *venv_path = UWSGI_PYFROMSTRINGSIZE(uwsgi.wsgi_req->home, uwsgi.wsgi_req->home_len);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("setting dynamic virtualenv to %.*s\n", uwsgi.wsgi_req->pyhome_len, uwsgi.wsgi_req->pyhome);
|
||||
uwsgi_debug("setting dynamic virtualenv to %.*s\n", uwsgi.wsgi_req->home_len, uwsgi.wsgi_req->home);
|
||||
#endif
|
||||
|
||||
PyDict_SetItemString(pysys_dict, "prefix", venv_path);
|
||||
@@ -177,8 +177,8 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
wi->interpreter = up.main_thread;
|
||||
}
|
||||
|
||||
if (wsgi_req->pyhome_len) {
|
||||
set_dyn_pyhome(wsgi_req->pyhome, wsgi_req->pyhome_len);
|
||||
if (wsgi_req->home_len) {
|
||||
set_dyn_pyhome(wsgi_req->home, wsgi_req->home_len);
|
||||
}
|
||||
|
||||
if (wsgi_req->touch_reload_len > 0 && wsgi_req->touch_reload_len < 0xff) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,26 +210,6 @@ PyObject *py_uwsgi_add_cron(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
|
||||
PyObject *py_uwsgi_add_probe(PyObject * self, PyObject * args) {
|
||||
|
||||
uint8_t uwsgi_signal;
|
||||
int timeout = 0;
|
||||
int freq = 0;
|
||||
char *probe, *probe_args;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "Bss|ii:add_probe", &uwsgi_signal, &probe, &probe_args, &timeout, &freq)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (uwsgi_add_probe(uwsgi_signal, probe, probe_args, timeout, freq))
|
||||
return PyErr_Format(PyExc_ValueError, "unable to add probe");
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PyObject *py_uwsgi_add_timer(PyObject * self, PyObject * args) {
|
||||
|
||||
uint8_t uwsgi_signal;
|
||||
@@ -2444,7 +2424,6 @@ static PyMethodDef uwsgi_advanced_methods[] = {
|
||||
{"signal_received", py_uwsgi_signal_received, METH_VARARGS, ""},
|
||||
{"add_file_monitor", py_uwsgi_add_file_monitor, METH_VARARGS, ""},
|
||||
{"add_timer", py_uwsgi_add_timer, METH_VARARGS, ""},
|
||||
{"add_probe", py_uwsgi_add_probe, METH_VARARGS, ""},
|
||||
{"add_rb_timer", py_uwsgi_add_rb_timer, METH_VARARGS, ""},
|
||||
{"add_cron", py_uwsgi_add_cron, METH_VARARGS, ""},
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ struct uwsgi_python {
|
||||
|
||||
char *test_module;
|
||||
|
||||
int pyshell;
|
||||
char *pyshell;
|
||||
int pyshell_oneshot;
|
||||
|
||||
|
||||
|
||||
@@ -42,6 +42,9 @@ if not 'UWSGI_PYTHON_NOLIB' in os.environ:
|
||||
if not os.path.exists(libpath):
|
||||
libpath = '%s/libpython%s.a' % (libdir, version)
|
||||
LIBS.append(libpath)
|
||||
# hack for messy linkers/compilers
|
||||
if '-lutil' in LIBS:
|
||||
LIBS.append('-lutil')
|
||||
else:
|
||||
try:
|
||||
LDFLAGS.append("-L%s" % sysconfig.get_config_var('LIBDIR'))
|
||||
|
||||
@@ -135,11 +135,34 @@ static PyObject *uwsgi_Input_close(uwsgi_Input *self, PyObject *args) {
|
||||
|
||||
static PyObject *uwsgi_Input_seek(uwsgi_Input *self, PyObject *args) {
|
||||
long pos = 0;
|
||||
int whence = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "l:seek", &pos)) {
|
||||
if (!uwsgi.post_buffering) {
|
||||
return PyErr_Format(PyExc_IOError, "seeking wsgi.input without post_buffering is IMPOSSIBLE !!!");
|
||||
}
|
||||
|
||||
if (!PyArg_ParseTuple(args, "l|i:seek", &pos, &whence)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
uwsgi_request_body_seek() uses SEEK_SET for positive value and SEEK_CUR for negative
|
||||
yous hould always try to transform the "pos" value to an absolute position.
|
||||
*/
|
||||
|
||||
// current
|
||||
if (whence == 1) {
|
||||
pos += self->wsgi_req->post_pos;
|
||||
}
|
||||
// end of stream
|
||||
if (whence == 2) {
|
||||
pos += self->wsgi_req->post_cl;
|
||||
}
|
||||
|
||||
if (pos < 0 || pos > (off_t)self->wsgi_req->post_cl) {
|
||||
return PyErr_Format(PyExc_IOError, "invalid seek position for wsgi.input");
|
||||
}
|
||||
|
||||
uwsgi_request_body_seek(self->wsgi_req, pos);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
@@ -151,6 +174,12 @@ static PyObject *uwsgi_Input_fileno(uwsgi_Input *self, PyObject *args) {
|
||||
return PyInt_FromLong(self->wsgi_req->fd);
|
||||
}
|
||||
|
||||
static PyObject *uwsgi_Input_tell(uwsgi_Input *self, PyObject *args) {
|
||||
|
||||
return PyLong_FromLong(self->wsgi_req->post_pos);
|
||||
}
|
||||
|
||||
|
||||
static PyMethodDef uwsgi_Input_methods[] = {
|
||||
{ "read", (PyCFunction)uwsgi_Input_read, METH_VARARGS, 0 },
|
||||
{ "readline", (PyCFunction)uwsgi_Input_readline, METH_VARARGS, 0 },
|
||||
@@ -158,6 +187,7 @@ static PyMethodDef uwsgi_Input_methods[] = {
|
||||
// add close to allow mod_wsgi compatibility
|
||||
{ "close", (PyCFunction)uwsgi_Input_close, METH_VARARGS, 0 },
|
||||
{ "seek", (PyCFunction)uwsgi_Input_seek, METH_VARARGS, 0 },
|
||||
{ "tell", (PyCFunction)uwsgi_Input_tell, METH_VARARGS, 0 },
|
||||
{ "fileno", (PyCFunction)uwsgi_Input_fileno, METH_VARARGS, 0 },
|
||||
{ NULL, NULL}
|
||||
};
|
||||
@@ -317,7 +347,6 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( (wsgi_req->app_id = uwsgi_get_app_id(wsgi_req->appid, wsgi_req->appid_len, 0)) == -1) {
|
||||
wsgi_req->app_id = uwsgi.default_app;
|
||||
if (uwsgi.no_default_app) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
#include <uwsgi.h>
|
||||
#include <sqlite3.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
static void uwsgi_sqlite3_config(char *, char *[]);
|
||||
static void uwsgi_opt_load_sqlite3(char *opt, char *filename, void *none) {
|
||||
config_magic_table_fill(filename, uwsgi.magic_table);
|
||||
uwsgi_sqlite3_config(filename, uwsgi.magic_table);
|
||||
}
|
||||
|
||||
static struct uwsgi_option uwsgi_sqlite3_options[] = {
|
||||
{"sqlite3", required_argument, 0, "load config from sqlite3 db", uwsgi_opt_load_sqlite3, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"sqlite", required_argument, 0, "load config from sqlite3 db", uwsgi_opt_load_sqlite3, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
static int uwsgi_sqlite3_config_callback(void *magic_table, int field_count, char **fields, char **col) {
|
||||
// make a copy of the string
|
||||
if (field_count >= 2) {
|
||||
size_t value_len = strlen(fields[1]) + 1;
|
||||
char *value = magic_sub(fields[1], value_len, &value_len, (char **) magic_table);
|
||||
add_exported_option(uwsgi_strncopy(fields[0], strlen(fields[0])), value, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uwsgi_sqlite3_config(char *file, char *magic_table[]) {
|
||||
|
||||
sqlite3 *db;
|
||||
char *err = NULL;
|
||||
char *query = "SELECT * FROM uwsgi";
|
||||
|
||||
char *colon = uwsgi_get_last_char(file, ':');
|
||||
|
||||
if (colon) {
|
||||
colon[0] = 0;
|
||||
if (colon[1] != 0) {
|
||||
query = colon + 1;
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("[uWSGI] getting sqlite3 configuration from %s\n", file);
|
||||
|
||||
#ifdef sqlite3_open_v2
|
||||
if (sqlite3_open_v2(file, &db, SQLITE_OPEN_READONLY, NULL)) {
|
||||
#else
|
||||
if (sqlite3_open(file, &db)) {
|
||||
#endif
|
||||
uwsgi_log("unable to open sqlite3 db: %s\n", sqlite3_errmsg(db));
|
||||
sqlite3_close(db);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (sqlite3_exec(db, query, uwsgi_sqlite3_config_callback, (void *) magic_table, &err)) {
|
||||
uwsgi_log("sqlite3 error: %s\n", err);
|
||||
sqlite3_close(db);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sqlite3_close(db);
|
||||
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_plugin sqlite3_plugin = {
|
||||
.name = "sqlite3",
|
||||
.options = uwsgi_sqlite3_options,
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
NAME='sqlite3'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lsqlite3']
|
||||
|
||||
GCC_LIST = ['plugin']
|
||||
@@ -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
@@ -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();
|
||||
}
|
||||
#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;
|
||||
|
||||
TeaJS_uWSGI app;
|
||||
|
||||
v8::Persistent<v8::Context> uwsgi_v8_setup_context() {
|
||||
#ifdef UWSGI_V8_TEAJS
|
||||
v8::HandleScope handle_scope;
|
||||
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
|
||||
|
||||
+9
-11
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+3
-30
@@ -1,6 +1,6 @@
|
||||
# uWSGI build system
|
||||
|
||||
uwsgi_version = '1.9.5'
|
||||
uwsgi_version = '1.9.6'
|
||||
|
||||
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
|
||||
@@ -524,6 +522,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']
|
||||
@@ -971,19 +971,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 +1039,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')
|
||||
|
||||
Reference in New Issue
Block a user