mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 07:58:33 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ef17013945 | ||
|
|
a225d53825 | ||
|
|
d4298469ba | ||
|
|
395de489b8 | ||
|
|
6e6efc5605 | ||
|
|
ce260ecbb6 | ||
|
|
e143e25b3c | ||
|
|
e9a58bac46 | ||
|
|
1448fbc5a3 | ||
|
|
b801f839fc | ||
|
|
bcb8321480 | ||
|
|
5cd9e64073 | ||
|
|
d878b65401 | ||
|
|
ded149fc80 | ||
|
|
f041d1095d | ||
|
|
886842de12 | ||
|
|
b4915f778e | ||
|
|
a25e02bbb3 | ||
|
|
16aec7c44b | ||
|
|
42dfa20f27 | ||
|
|
2092050f00 | ||
|
|
b5a0434710 | ||
|
|
2737cd5c35 | ||
|
|
7a29d9649c | ||
|
|
27cc164ebe | ||
|
|
40be8fc916 | ||
|
|
f219afc6e0 | ||
|
|
f20f72ceb1 | ||
|
|
6555c2804c | ||
|
|
c05082a8e4 | ||
|
|
62dab40a22 | ||
|
|
02e68ae578 | ||
|
|
ba1fb72427 | ||
|
|
df9a76a171 | ||
|
|
98e7e0845d | ||
|
|
6c9f73ae7f | ||
|
|
b12658102d | ||
|
|
c51b74a32b | ||
|
|
b0e6d19d5c | ||
|
|
7ff3584ad7 | ||
|
|
57b6d1f51b | ||
|
|
1646f9c199 | ||
|
|
260b49c3f6 | ||
|
|
58af067bef | ||
|
|
d1285c6dc4 | ||
|
|
d4e9f3a2d4 | ||
|
|
a15de85811 | ||
|
|
4b09ead07d | ||
|
|
338aca9da5 | ||
|
|
3f0b9390d9 | ||
|
|
e14b189c77 | ||
|
|
cabb179a84 | ||
|
|
ad9b48b69e | ||
|
|
08443d5463 | ||
|
|
5d11a5cd77 | ||
|
|
3aba97745c | ||
|
|
0b596bdf42 | ||
|
|
4c4b08c36f | ||
|
|
1f0827abc8 | ||
|
|
2ea67c67df | ||
|
|
8eebc9f400 | ||
|
|
2ad6a1c8e8 | ||
|
|
d39d0e8403 | ||
|
|
2838fffbde | ||
|
|
45bc51541a | ||
|
|
3427a17191 | ||
|
|
0cf61abf9d | ||
|
|
53fde5fcdd | ||
|
|
e81f068e4b | ||
|
|
aaee226183 | ||
|
|
d7bba38d7a | ||
|
|
18fa1172db | ||
|
|
9e95312169 | ||
|
|
216aff3820 | ||
|
|
eae335a43e | ||
|
|
e0cf245a0e | ||
|
|
d463f9e7d9 | ||
|
|
06c62033dd | ||
|
|
72ea5ab54a | ||
|
|
843a3b18ad | ||
|
|
37acca060b | ||
|
|
a0ff5b91b8 | ||
|
|
ea19e1e67b | ||
|
|
c20e3fb1a8 | ||
|
|
a57c2997f4 | ||
|
|
3d051e5d79 | ||
|
|
3b0d18c1ec | ||
|
|
89e04c5d17 | ||
|
|
84ea262203 | ||
|
|
15fa2be4ee | ||
|
|
f18ceea9bf | ||
|
|
e4a993ac31 | ||
|
|
cf2c20418c | ||
|
|
d155197d98 | ||
|
|
fbc1551112 | ||
|
|
b3bba48d1a | ||
|
|
18972d95a8 | ||
|
|
8aa8d6070b | ||
|
|
3f0e9f899a | ||
|
|
00bf0aa713 | ||
|
|
60675724d3 | ||
|
|
b45deb780d | ||
|
|
24e144268b | ||
|
|
b870b8c6d8 | ||
|
|
62be7482d4 | ||
|
|
0c8f473e6f | ||
|
|
8b19fd3f94 | ||
|
|
7553ce3a48 | ||
|
|
9ff67391c0 | ||
|
|
4f4f9b93aa | ||
|
|
51a8f31f17 | ||
|
|
32b7126836 | ||
|
|
4d43a66581 | ||
|
|
0f95ef6d5a | ||
|
|
c0c43a7d47 | ||
|
|
4361ef2dc6 | ||
|
|
b7298aba85 |
@@ -2,7 +2,7 @@
|
||||
|
||||
*** mod_proxy_uwsgi ***
|
||||
|
||||
Copyright 2009-2013 Unbit S.a.s. <info@unbit.it>
|
||||
Copyright 2009-2014 Unbit S.a.s. <info@unbit.it>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
*** uWSGI/mod_uwsgi ***
|
||||
|
||||
Copyright 2009-2013 Unbit S.a.s. <info@unbit.it>
|
||||
Copyright 2009-2014 Unbit S.a.s. <info@unbit.it>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = python,gevent
|
||||
inherit = base
|
||||
debug = false
|
||||
|
||||
@@ -81,6 +81,22 @@ int uwsgi_logic_opt_for_glob(char *key, char *value) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_for_readline(char *key, char *value) {
|
||||
|
||||
char line[1024];
|
||||
|
||||
FILE *fh = fopen(uwsgi.logic_opt_data, "r");
|
||||
if (fh) {
|
||||
while (fgets(line, 1024, fh)) {
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi_chomp(uwsgi_str(line))), 0);
|
||||
}
|
||||
fclose(fh);
|
||||
return 1;
|
||||
}
|
||||
uwsgi_error_open(uwsgi.logic_opt_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_for_times(char *key, char *value) {
|
||||
|
||||
int num = atoi(uwsgi.logic_opt_data);
|
||||
|
||||
+60
-15
@@ -55,7 +55,7 @@ void uwsgi_daemons_smart_check() {
|
||||
if (ud->pid > 0) {
|
||||
if (!kill(ud->pid, 0)) {
|
||||
uwsgi_log("[uwsgi_daemons] stopping legion \"%s\" daemon: %s (pid: %d)\n", ud->legion, ud->command, ud->pid);
|
||||
kill(-ud->pid, ud->stop_signal);
|
||||
kill(-(ud->pid), ud->stop_signal);
|
||||
}
|
||||
else {
|
||||
// pid already died
|
||||
@@ -237,12 +237,12 @@ void uwsgi_detach_daemons() {
|
||||
time_t timeout = uwsgi_now() + (uwsgi.reload_mercy ? uwsgi.reload_mercy : 3);
|
||||
int waitpid_status;
|
||||
while (!kill(ud->pid, 0)) {
|
||||
kill(-ud->pid, ud->stop_signal);
|
||||
kill(-(ud->pid), ud->stop_signal);
|
||||
sleep(1);
|
||||
waitpid(-ud->pid, &waitpid_status, WNOHANG);
|
||||
waitpid(ud->pid, &waitpid_status, WNOHANG);
|
||||
if (uwsgi_now() >= timeout) {
|
||||
uwsgi_log("[uwsgi-daemons] daemon did not die in time, killing (pid: %d): %s\n", (int) ud->pid, ud->command);
|
||||
kill(-ud->pid, SIGKILL);
|
||||
kill(-(ud->pid), SIGKILL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -253,18 +253,19 @@ void uwsgi_detach_daemons() {
|
||||
}
|
||||
}
|
||||
|
||||
static int daemon_spawn(void *);
|
||||
|
||||
void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
|
||||
// skip unregistered daemons
|
||||
if (!ud->registered) return;
|
||||
|
||||
int throttle = 0;
|
||||
ud->throttle = 0;
|
||||
|
||||
if (uwsgi.current_time - ud->last_spawn <= 3) {
|
||||
throttle = ud->respawns - (uwsgi.current_time - ud->last_spawn);
|
||||
ud->throttle = ud->respawns - (uwsgi.current_time - ud->last_spawn);
|
||||
// if ud->respawns == 0 then we can end up with throttle < 0
|
||||
if (throttle <= 0) throttle = 1;
|
||||
if (ud->throttle <= 0) ud->throttle = 1;
|
||||
}
|
||||
|
||||
pid_t pid = uwsgi_fork("uWSGI external daemon");
|
||||
@@ -291,6 +292,50 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
uwsgi_close_all_sockets();
|
||||
uwsgi_close_all_fds();
|
||||
|
||||
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL) && defined(CLONE_NEWPID)
|
||||
if (ud->ns_pid) {
|
||||
// we need to create a new session
|
||||
if (setsid() < 0) {
|
||||
uwsgi_error("setsid()");
|
||||
exit(1);
|
||||
}
|
||||
// avoid the need to set stop_signal in attach-daemon2
|
||||
signal(SIGTERM, end_me);
|
||||
|
||||
char stack[PTHREAD_STACK_MIN];
|
||||
pid_t pid = clone((int (*)(void *))daemon_spawn, stack + PTHREAD_STACK_MIN, SIGCHLD | CLONE_NEWPID, (void *) ud);
|
||||
if (pid > 0) {
|
||||
|
||||
#ifdef PR_SET_PDEATHSIG
|
||||
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
|
||||
uwsgi_error("uwsgi_spawn_daemon()/prctl()");
|
||||
}
|
||||
#endif
|
||||
// block all signals except SIGTERM
|
||||
sigset_t smask;
|
||||
sigfillset(&smask);
|
||||
sigdelset(&smask, SIGTERM);
|
||||
sigprocmask(SIG_BLOCK, &smask, NULL);
|
||||
int status;
|
||||
if (waitpid(pid, &status, 0) < 0) {
|
||||
uwsgi_error("uwsgi_spawn_daemon()/waitpid()");
|
||||
}
|
||||
_exit(0);
|
||||
}
|
||||
uwsgi_error("uwsgi_spawn_daemon()/clone()");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
daemon_spawn((void *) ud);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int daemon_spawn(void *arg) {
|
||||
|
||||
struct uwsgi_daemon *ud = (struct uwsgi_daemon *) arg;
|
||||
|
||||
if (ud->gid) {
|
||||
if (setgid(ud->gid)) {
|
||||
uwsgi_error("uwsgi_spawn_daemon()/setgid()");
|
||||
@@ -307,7 +352,7 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
|
||||
if (ud->daemonize) {
|
||||
/* refork... */
|
||||
pid = fork();
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
uwsgi_error("fork()");
|
||||
exit(1);
|
||||
@@ -329,7 +374,7 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
}
|
||||
|
||||
if (!ud->pidfile) {
|
||||
#ifdef __linux__
|
||||
#ifdef PR_SET_PDEATHSIG
|
||||
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
|
||||
uwsgi_error("prctl()");
|
||||
}
|
||||
@@ -337,9 +382,9 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
}
|
||||
|
||||
|
||||
if (throttle) {
|
||||
uwsgi_log("[uwsgi-daemons] throttling \"%s\" for %d seconds\n", ud->command, throttle);
|
||||
sleep((unsigned int) throttle);
|
||||
if (ud->throttle) {
|
||||
uwsgi_log("[uwsgi-daemons] throttling \"%s\" for %d seconds\n", ud->command, ud->throttle);
|
||||
sleep((unsigned int) ud->throttle);
|
||||
}
|
||||
|
||||
uwsgi_log("[uwsgi-daemons] %sspawning \"%s\" (uid: %d gid: %d)\n", ud->respawns > 0 ? "re" : "", ud->command, (int) getuid(), (int) getgid());
|
||||
@@ -348,9 +393,6 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
|
||||
// never here;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -454,6 +496,7 @@ void uwsgi_opt_add_daemon2(char *opt, char *value, void *none) {
|
||||
char *d_stdin = NULL;
|
||||
char *d_uid = NULL;
|
||||
char *d_gid = NULL;
|
||||
char *d_ns_pid = NULL;
|
||||
|
||||
char *arg = uwsgi_str(value);
|
||||
|
||||
@@ -474,6 +517,7 @@ void uwsgi_opt_add_daemon2(char *opt, char *value, void *none) {
|
||||
"stdin", &d_stdin,
|
||||
"uid", &d_uid,
|
||||
"gid", &d_gid,
|
||||
"ns_pid", &d_ns_pid,
|
||||
NULL)) {
|
||||
uwsgi_log("invalid --%s keyval syntax\n", opt);
|
||||
exit(1);
|
||||
@@ -519,6 +563,7 @@ void uwsgi_opt_add_daemon2(char *opt, char *value, void *none) {
|
||||
#ifdef UWSGI_SSL
|
||||
uwsgi_ud->legion = d_legion;
|
||||
#endif
|
||||
uwsgi_ud->ns_pid = d_ns_pid ? 1 : 0;
|
||||
|
||||
if (d_touch) {
|
||||
size_t i,rlen = 0;
|
||||
|
||||
+56
-3
@@ -18,6 +18,8 @@ int emperor_throttle_level;
|
||||
|
||||
struct uwsgi_instance *ui;
|
||||
|
||||
time_t on_royal_death = 0;
|
||||
|
||||
/*
|
||||
|
||||
blacklist subsystem
|
||||
@@ -482,6 +484,10 @@ void uwsgi_register_imperial_monitor(char *name, void (*init) (struct uwsgi_empe
|
||||
// the sad death of an Emperor
|
||||
static void royal_death(int signum) {
|
||||
|
||||
if (on_royal_death) {
|
||||
uwsgi_log("[emperor] *** RAGNAROK ALREADY EVOKED (mercyless in %d seconds)***\n", uwsgi.reload_mercy - (uwsgi_now() - on_royal_death));
|
||||
return;
|
||||
}
|
||||
|
||||
struct uwsgi_instance *c_ui = ui->ui_next;
|
||||
|
||||
@@ -502,8 +508,14 @@ static void royal_death(int signum) {
|
||||
}
|
||||
|
||||
uwsgi_log("[emperor] *** RAGNAROK EVOKED ***\n");
|
||||
uwsgi_notify("The Emperor is buried.");
|
||||
exit(0);
|
||||
|
||||
while (c_ui) {
|
||||
emperor_stop(c_ui);
|
||||
c_ui = c_ui->ui_next;
|
||||
}
|
||||
|
||||
if (!uwsgi.reload_mercy) uwsgi.reload_mercy = 30;
|
||||
on_royal_death = uwsgi_now();
|
||||
}
|
||||
|
||||
// massive reload of vassals
|
||||
@@ -1520,8 +1532,43 @@ void emperor_loop() {
|
||||
|
||||
int freq = 0;
|
||||
|
||||
uwsgi_hooks_run(uwsgi.hook_emperor_start, "emperor-start", 1);
|
||||
|
||||
// signal parent-Emperor about my loyalty
|
||||
if (uwsgi.has_emperor && !uwsgi.loyal) {
|
||||
uwsgi_log("announcing my loyalty to the Emperor...\n");
|
||||
char byte = 17;
|
||||
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
uwsgi.loyal = 1;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
|
||||
if (on_royal_death) {
|
||||
if (!ui->ui_next) break;
|
||||
if (uwsgi_now() - on_royal_death >= uwsgi.reload_mercy) {
|
||||
ui_current = ui->ui_next;
|
||||
while (ui_current) {
|
||||
uwsgi_log_verbose("[emperor] NO MERCY for vassal %s !!!\n", ui_current->name);
|
||||
kill(ui_current->pid, SIGKILL);
|
||||
ui_current = ui_current->ui_next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
ui_current = ui->ui_next;
|
||||
while (ui_current) {
|
||||
struct uwsgi_instance *dead_vassal = ui_current;
|
||||
ui_current = ui_current->ui_next;
|
||||
pid_t dead_pid = waitpid(dead_vassal->pid, &waitpid_status, WNOHANG);
|
||||
if (dead_pid > 0 || dead_pid < 0) {
|
||||
emperor_del(dead_vassal);
|
||||
}
|
||||
}
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!i_am_alone) {
|
||||
diedpid = waitpid(uwsgi.emperor_pid, &waitpid_status, WNOHANG);
|
||||
@@ -1612,6 +1659,9 @@ void emperor_loop() {
|
||||
ui_current = ui->ui_next;
|
||||
while (ui_current) {
|
||||
if (ui_current->last_heartbeat > 0) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%d %d %d %d\n", ui_current->last_heartbeat, uwsgi.emperor_heartbeat, ui_current->last_heartbeat + uwsgi.emperor_heartbeat, uwsgi_now());
|
||||
#endif
|
||||
if ((ui_current->last_heartbeat + uwsgi.emperor_heartbeat) < uwsgi_now()) {
|
||||
uwsgi_log("[emperor] vassal %s sent no heartbeat in last %d seconds, brutally respawning it...\n", ui_current->name, uwsgi.emperor_heartbeat);
|
||||
// set last_heartbeat to 0 avoiding races
|
||||
@@ -1705,6 +1755,10 @@ void emperor_loop() {
|
||||
|
||||
}
|
||||
|
||||
uwsgi_log_verbose("The Emperor is buried.\n");
|
||||
uwsgi_notify("The Emperor is buried.");
|
||||
exit(0);
|
||||
|
||||
}
|
||||
|
||||
void emperor_send_stats(int fd) {
|
||||
@@ -1995,7 +2049,6 @@ next:
|
||||
uwsgi.has_emperor = 1;
|
||||
uwsgi.emperor_fd = atoi(emperor_env);
|
||||
uwsgi.master_process = 1;
|
||||
uwsgi.no_orphans = 1;
|
||||
uwsgi_log("*** has_emperor mode detected (fd: %d) ***\n", uwsgi.emperor_fd);
|
||||
|
||||
if (getenv("UWSGI_EMPEROR_FD_CONFIG")) {
|
||||
|
||||
+137
-162
@@ -8,207 +8,182 @@ extern struct uwsgi_server uwsgi;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
void uwsgi_fsmon_setup() {
|
||||
struct uwsgi_string_list *usl = uwsgi.fs_reload;
|
||||
while(usl) {
|
||||
if (uwsgi_register_fsmon(usl)) {
|
||||
uwsgi_log("[uwsgi-fsmon] unable to register monitor for \"%s\"\n", usl->value);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[uwsgi-fsmon] registered monitor for \"%s\"\n", usl->value);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
usl = uwsgi.fs_brutal_reload;
|
||||
while(usl) {
|
||||
if (uwsgi_register_fsmon(usl)) {
|
||||
uwsgi_log("[uwsgi-fsmon] unable to register monitor for \"%s\"\n", usl->value);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[uwsgi-fsmon] registered monitor for \"%s\"\n", usl->value);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
usl = uwsgi.fs_signal;
|
||||
while(usl) {
|
||||
char *copy = uwsgi_str(usl->value);
|
||||
char *space = strchr(copy, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("[uwsgi-fsmon] invalid syntax: \"%s\"\n", usl->value);
|
||||
free(copy);
|
||||
goto next;
|
||||
}
|
||||
*space = 0;
|
||||
usl->value = copy;
|
||||
usl->len = strlen(copy);
|
||||
usl->custom_ptr = space+1;
|
||||
if (uwsgi_register_fsmon(usl)) {
|
||||
uwsgi_log("[uwsgi-fsmon] unable to register monitor for \"%s\"\n", usl->value);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[uwsgi-fsmon] registered monitor for \"%s\"\n", usl->value);
|
||||
}
|
||||
next:
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_register_fsmon(struct uwsgi_string_list *usl) {
|
||||
static int fsmon_add(struct uwsgi_fsmon *fs) {
|
||||
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
|
||||
#ifndef OBSOLETE_LINUX_KERNEL
|
||||
static int inotify_fd = -1;
|
||||
if (inotify_fd == -1) {
|
||||
inotify_fd = inotify_init();
|
||||
if (inotify_fd < 0) {
|
||||
uwsgi_error("uwsgi_register_fsmon()/inotify_init()");
|
||||
uwsgi_error("fsmon_add()/inotify_init()");
|
||||
return -1;
|
||||
}
|
||||
if (event_queue_add_fd_read(uwsgi.master_queue, inotify_fd)) {
|
||||
uwsgi_error("uwsgi_register_fsmon()/event_queue_add_fd_read()");
|
||||
uwsgi_error("fsmon_add()/event_queue_add_fd_read()");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
int wd = inotify_add_watch(inotify_fd, usl->value, IN_ATTRIB | IN_CREATE | IN_DELETE | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_MOVED_FROM | IN_MOVED_TO);
|
||||
int wd = inotify_add_watch(inotify_fd, fs->path, IN_ATTRIB | IN_CREATE | IN_DELETE | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_MOVED_FROM | IN_MOVED_TO);
|
||||
if (wd < 0) {
|
||||
uwsgi_error("uwsgi_register_fsmon()/inotify_add_watch()");
|
||||
uwsgi_error("fsmon_add()/inotify_add_watch()");
|
||||
return -1;
|
||||
}
|
||||
usl->custom = inotify_fd;
|
||||
usl->custom2 = wd;
|
||||
fs->fd = inotify_fd;
|
||||
fs->id = wd;
|
||||
return 0;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef UWSGI_EVENT_FILEMONITOR_USE_KQUEUE
|
||||
struct kevent kev;
|
||||
int fd = open(usl->value, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(usl->value);
|
||||
uwsgi_error("uwsgi_register_fsmon()/open()");
|
||||
return -1;
|
||||
}
|
||||
struct kevent kev;
|
||||
int fd = open(fs->path, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(fs->path);
|
||||
uwsgi_error("fsmon_add()/open()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
EV_SET(&kev, fd, EVFILT_VNODE, EV_ADD | EV_CLEAR, NOTE_WRITE | NOTE_DELETE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_RENAME | NOTE_REVOKE, 0, 0);
|
||||
if (kevent(uwsgi.master_queue, &kev, 1, NULL, 0, NULL) < 0) {
|
||||
uwsgi_error("uwsgi_register_fsmon()/kevent()");
|
||||
return -1;
|
||||
}
|
||||
usl->custom = fd;
|
||||
usl->custom2 = fd;
|
||||
EV_SET(&kev, fd, EVFILT_VNODE, EV_ADD | EV_CLEAR, NOTE_WRITE | NOTE_DELETE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_RENAME | NOTE_REVOKE, 0, 0);
|
||||
if (kevent(uwsgi.master_queue, &kev, 1, NULL, 0, NULL) < 0) {
|
||||
uwsgi_error("fsmon_add()/kevent()");
|
||||
return -1;
|
||||
}
|
||||
fs->fd = fd;
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
uwsgi_log("[uwsgi-fsmon] filesystem monitoring interface not available in this platform !!!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct uwsgi_string_list *uwsgi_fsmon_ack(int interesting_fd) {
|
||||
int found_fd = -1;
|
||||
struct uwsgi_string_list *usl = uwsgi.fs_reload;
|
||||
while(usl) {
|
||||
if ((int)usl->custom == interesting_fd) {
|
||||
found_fd = usl->custom;
|
||||
goto found;
|
||||
}
|
||||
usl = usl->next;
|
||||
static void fsmon_reload(struct uwsgi_fsmon *fs) {
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
grace_them_all(0);
|
||||
uwsgi_unblock_signal(SIGHUP);
|
||||
}
|
||||
|
||||
static void fsmon_brutal_reload(struct uwsgi_fsmon *fs) {
|
||||
if (uwsgi.die_on_term) {
|
||||
uwsgi_block_signal(SIGQUIT);
|
||||
reap_them_all(0);
|
||||
uwsgi_unblock_signal(SIGQUIT);
|
||||
}
|
||||
usl = uwsgi.fs_brutal_reload;
|
||||
while(usl) {
|
||||
if ((int)usl->custom == interesting_fd) {
|
||||
found_fd = usl->custom;
|
||||
goto found;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
usl = uwsgi.fs_signal;
|
||||
while(usl) {
|
||||
if ((int)usl->custom == interesting_fd) {
|
||||
found_fd = usl->custom;
|
||||
goto found;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
found:
|
||||
if (found_fd == -1) return NULL;
|
||||
else {
|
||||
uwsgi_block_signal(SIGTERM);
|
||||
reap_them_all(0);
|
||||
uwsgi_unblock_signal(SIGTERM);
|
||||
}
|
||||
}
|
||||
|
||||
static void fsmon_signal(struct uwsgi_fsmon *fs) {
|
||||
uwsgi_route_signal(atoi((char *) fs->data));
|
||||
}
|
||||
|
||||
void uwsgi_fsmon_setup() {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.fs_reload) {
|
||||
uwsgi_register_fsmon(usl->value, fsmon_reload, NULL);
|
||||
}
|
||||
uwsgi_foreach(usl, uwsgi.fs_brutal_reload) {
|
||||
uwsgi_register_fsmon(usl->value, fsmon_brutal_reload, NULL);
|
||||
}
|
||||
uwsgi_foreach(usl, uwsgi.fs_signal) {
|
||||
char *copy = uwsgi_str(usl->value);
|
||||
char *space = strchr(copy, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("[uwsgi-fsmon] invalid syntax: \"%s\"\n", usl->value);
|
||||
free(copy);
|
||||
continue;
|
||||
}
|
||||
*space = 0;
|
||||
uwsgi_register_fsmon(copy, fsmon_signal, space + 1);
|
||||
}
|
||||
|
||||
struct uwsgi_fsmon *fs = uwsgi.fsmon;
|
||||
while (fs) {
|
||||
if (fsmon_add(fs)) {
|
||||
uwsgi_log("[uwsgi-fsmon] unable to register monitor for \"%s\"\n", fs->path);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[uwsgi-fsmon] registered monitor for \"%s\"\n", fs->path);
|
||||
}
|
||||
fs = fs->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_fsmon *uwsgi_register_fsmon(char *path, void (*func) (struct uwsgi_fsmon *), void *data) {
|
||||
struct uwsgi_fsmon *old_fs = NULL, *fs = uwsgi.fsmon;
|
||||
while(fs) {
|
||||
old_fs = fs;
|
||||
fs = fs->next;
|
||||
}
|
||||
|
||||
fs = uwsgi_calloc(sizeof(struct uwsgi_fsmon));
|
||||
fs->path = path;
|
||||
fs->func = func;
|
||||
fs->data = data;
|
||||
|
||||
if (old_fs) {
|
||||
old_fs->next = fs;
|
||||
}
|
||||
else {
|
||||
uwsgi.fsmon = fs;
|
||||
}
|
||||
|
||||
return fs;
|
||||
}
|
||||
|
||||
static struct uwsgi_fsmon *uwsgi_fsmon_ack(int interesting_fd) {
|
||||
struct uwsgi_fsmon *found_fs = NULL;
|
||||
struct uwsgi_fsmon *fs = uwsgi.fsmon;
|
||||
while (fs) {
|
||||
if (fs->fd == interesting_fd) {
|
||||
found_fs = fs;
|
||||
break;
|
||||
}
|
||||
fs = fs->next;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
|
||||
#ifndef OBSOLETE_LINUX_KERNEL
|
||||
if (!found_fs)
|
||||
return NULL;
|
||||
found_fs = NULL;
|
||||
unsigned int isize = 0;
|
||||
if (ioctl(found_fd, FIONREAD, &isize) < 0) {
|
||||
uwsgi_error("uwsgi_fsmon_ack()/ioctl()");
|
||||
return 0;
|
||||
}
|
||||
if (isize == 0) return NULL;
|
||||
if (ioctl(interesting_fd, FIONREAD, &isize) < 0) {
|
||||
uwsgi_error("uwsgi_fsmon_ack()/ioctl()");
|
||||
return NULL;
|
||||
}
|
||||
if (isize == 0)
|
||||
return NULL;
|
||||
struct inotify_event *ie = uwsgi_malloc(isize);
|
||||
// read from the inotify descriptor
|
||||
ssize_t len = read(found_fd, ie, isize);
|
||||
if (len < 0) { free(ie); uwsgi_error("uwsgi_fsmon_ack()/read()"); return NULL;}
|
||||
found_fd = ie->wd;
|
||||
ssize_t len = read(interesting_fd, ie, isize);
|
||||
if (len < 0) {
|
||||
free(ie);
|
||||
uwsgi_error("uwsgi_fsmon_ack()/read()");
|
||||
return NULL;
|
||||
}
|
||||
fs = uwsgi.fsmon;
|
||||
while (fs) {
|
||||
if (fs->fd == interesting_fd && fs->id == ie->wd) {
|
||||
found_fs = fs;
|
||||
break;
|
||||
}
|
||||
fs = fs->next;
|
||||
}
|
||||
free(ie);
|
||||
#endif
|
||||
#endif
|
||||
// search for the item id and print it
|
||||
usl = uwsgi.fs_reload;
|
||||
while(usl) {
|
||||
if ((int)usl->custom2 == found_fd) {
|
||||
uwsgi_log("[uwsgi-fsmon] \"%s\" has been modified\n", usl->value);
|
||||
return uwsgi.fs_reload;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
usl = uwsgi.fs_brutal_reload;
|
||||
while(usl) {
|
||||
if ((int)usl->custom2 == found_fd) {
|
||||
uwsgi_log("[uwsgi-fsmon] \"%s\" has been modified\n", usl->value);
|
||||
return uwsgi.fs_brutal_reload;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
usl = uwsgi.fs_signal;
|
||||
while(usl) {
|
||||
if ((int)usl->custom2 == found_fd) {
|
||||
uwsgi_log("[uwsgi-fsmon] \"%s\" has been modified\n", usl->value);
|
||||
return usl;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return found_fs;
|
||||
}
|
||||
|
||||
int uwsgi_fsmon_event(int interesting_fd) {
|
||||
|
||||
struct uwsgi_string_list *usl = uwsgi_fsmon_ack(interesting_fd);
|
||||
struct uwsgi_fsmon *fs = uwsgi_fsmon_ack(interesting_fd);
|
||||
if (!fs)
|
||||
return 0;
|
||||
|
||||
if (!usl) return 0;
|
||||
|
||||
if (usl == uwsgi.fs_reload) {
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
grace_them_all(0);
|
||||
uwsgi_unblock_signal(SIGHUP);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (usl == uwsgi.fs_brutal_reload) {
|
||||
if (uwsgi.die_on_term) {
|
||||
uwsgi_block_signal(SIGQUIT);
|
||||
reap_them_all(0);
|
||||
uwsgi_unblock_signal(SIGQUIT);
|
||||
}
|
||||
else {
|
||||
uwsgi_block_signal(SIGTERM);
|
||||
reap_them_all(0);
|
||||
uwsgi_unblock_signal(SIGTERM);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// fallback to signal
|
||||
uwsgi_route_signal(atoi(usl->custom_ptr));
|
||||
uwsgi_log_verbose("[uwsgi-fsmon] detected event on \"%s\"\n", fs->path);
|
||||
fs->func(fs);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -92,6 +92,8 @@ void gateway_respawn(int id) {
|
||||
signal(SIGSTOP, SIG_IGN);
|
||||
signal(SIGTSTP, SIG_IGN);
|
||||
|
||||
uwsgi_hooks_run(uwsgi.hook_as_gateway, "as-gateway", 1);
|
||||
|
||||
if (ug->gid) {
|
||||
uwsgi_log("%s %d setgid() to %d\n", ug->name, ug->num, (int) ug->gid);
|
||||
if (setgid(ug->gid)) {
|
||||
|
||||
@@ -47,6 +47,18 @@ void uwsgi_register_hook(char *name, int (*func)(char *)) {
|
||||
}
|
||||
}
|
||||
|
||||
static int uwsgi_hook_alarm(char *arg) {
|
||||
char *space = strchr(arg,' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid alarm hook syntax, must be: <alarm> <msg>\n");
|
||||
return -1;
|
||||
}
|
||||
*space = 0;
|
||||
uwsgi_alarm_trigger(arg, space+1, strlen(space+1));
|
||||
*space = ' ';
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_chdir(char *arg) {
|
||||
int ret = chdir(arg);
|
||||
if (ret) {
|
||||
@@ -154,6 +166,17 @@ static int uwsgi_hook_write(char *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_creat(char *arg) {
|
||||
int fd = open(arg, O_WRONLY|O_CREAT|O_TRUNC, 0666);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(arg);
|
||||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_hook_append(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (!space) {
|
||||
@@ -262,6 +285,20 @@ static int uwsgi_hook_chmod(char *arg) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_sticky(char *arg) {
|
||||
struct stat st;
|
||||
if (stat(arg, &st)) {
|
||||
uwsgi_error("uwsgi_hook_sticky()/stat()");
|
||||
return -1;
|
||||
}
|
||||
if (chmod(arg, st.st_mode | S_ISVTX)) {
|
||||
uwsgi_error("uwsgi_hook_sticky()/chmod()");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_hook_chown(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (!space) {
|
||||
@@ -342,6 +379,9 @@ static int uwsgi_hook_chown2(char *arg) {
|
||||
}
|
||||
|
||||
|
||||
#ifdef __sun__
|
||||
extern int sethostname(char *, int);
|
||||
#endif
|
||||
static int uwsgi_hook_hostname(char *arg) {
|
||||
#ifdef __CYGWIN__
|
||||
return -1;
|
||||
@@ -456,8 +496,13 @@ void uwsgi_register_base_hooks() {
|
||||
uwsgi_register_hook("chown", uwsgi_hook_chown);
|
||||
uwsgi_register_hook("chown2", uwsgi_hook_chown2);
|
||||
|
||||
uwsgi_register_hook("sticky", uwsgi_hook_sticky);
|
||||
|
||||
uwsgi_register_hook("exec", uwsgi_hook_exec);
|
||||
|
||||
uwsgi_register_hook("create", uwsgi_hook_creat);
|
||||
uwsgi_register_hook("creat", uwsgi_hook_creat);
|
||||
|
||||
uwsgi_register_hook("write", uwsgi_hook_write);
|
||||
uwsgi_register_hook("writen", uwsgi_hook_writen);
|
||||
uwsgi_register_hook("append", uwsgi_hook_append);
|
||||
@@ -476,9 +521,12 @@ void uwsgi_register_base_hooks() {
|
||||
|
||||
uwsgi_register_hook("hostname", uwsgi_hook_hostname);
|
||||
|
||||
uwsgi_register_hook("alarm", uwsgi_hook_alarm);
|
||||
|
||||
// for testing
|
||||
uwsgi_register_hook("exit", uwsgi_hook_exit);
|
||||
uwsgi_register_hook("print", uwsgi_hook_print);
|
||||
uwsgi_register_hook("log", uwsgi_hook_print);
|
||||
}
|
||||
|
||||
void uwsgi_hooks_run(struct uwsgi_string_list *l, char *phase, int fatal) {
|
||||
|
||||
+3
-1
@@ -123,7 +123,7 @@ void uwsgi_init_default() {
|
||||
// a workers hould be running for at least 10 seconds
|
||||
uwsgi.min_worker_lifetime = 10;
|
||||
|
||||
uwsgi.shared->spooler_frequency = 30;
|
||||
uwsgi.spooler_frequency = 30;
|
||||
|
||||
uwsgi.shared->spooler_signal_pipe[0] = -1;
|
||||
uwsgi.shared->spooler_signal_pipe[1] = -1;
|
||||
@@ -183,6 +183,8 @@ void uwsgi_init_default() {
|
||||
|
||||
uwsgi.master_fifo_fd = -1;
|
||||
uwsgi_master_fifo_prepare();
|
||||
|
||||
uwsgi.notify_socket_fd = -1;
|
||||
}
|
||||
|
||||
void uwsgi_setup_reload() {
|
||||
|
||||
@@ -535,7 +535,46 @@ fallback:
|
||||
end:
|
||||
|
||||
if (magic_table) {
|
||||
|
||||
// here we inject blobs
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
if (uwsgi.inject_before || uwsgi.inject_after) {
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
|
||||
uwsgi_foreach(usl, uwsgi.inject_before) {
|
||||
size_t rlen = 0;
|
||||
char *before = uwsgi_open_and_read(usl->value, &rlen, 0, NULL);
|
||||
if (uwsgi_buffer_append(ub, before, rlen)) {
|
||||
uwsgi_log("unable to inject data in the config file\n");
|
||||
exit(1);
|
||||
}
|
||||
free(before);
|
||||
}
|
||||
if (uwsgi_buffer_append(ub, buffer, *size - add_zero)) {
|
||||
uwsgi_log("unable to inject data in the config file\n");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_foreach(usl, uwsgi.inject_after) {
|
||||
size_t rlen = 0;
|
||||
char *after = uwsgi_open_and_read(usl->value, &rlen, 0, NULL);
|
||||
if (uwsgi_buffer_append(ub, after, rlen)) {
|
||||
uwsgi_log("unable to inject data in the config file\n");
|
||||
exit(1);
|
||||
}
|
||||
free(after);
|
||||
}
|
||||
if (add_zero) {
|
||||
if (uwsgi_buffer_append(ub, "\0", 1)) {
|
||||
uwsgi_log("unable to inject data in the config file\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
*size = ub->pos;
|
||||
// free resources
|
||||
free(buffer);
|
||||
buffer = ub->buf;
|
||||
// aboid destroying buffer
|
||||
ub->buf = NULL;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
}
|
||||
magic_buf = magic_sub(buffer, *size, size, magic_table);
|
||||
free(buffer);
|
||||
return magic_buf;
|
||||
|
||||
+118
-1
@@ -4,7 +4,124 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#ifdef UWSGI_JSON_YAJL
|
||||
#if defined(UWSGI_JSON_YAJL_OLD)
|
||||
#include <yajl/yajl_parse.h>
|
||||
|
||||
struct uwsgi_yajl_old_state {
|
||||
char *object;
|
||||
char *key;
|
||||
int in_object;
|
||||
int is_array;
|
||||
};
|
||||
|
||||
static int uwsgi_yajl_cb_null(void *ctx) {
|
||||
struct uwsgi_yajl_old_state *uyos = (struct uwsgi_yajl_old_state *) ctx;
|
||||
if (!uyos->key) return 1;
|
||||
add_exported_option(uyos->key, strdup("0"), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int uwsgi_yajl_cb_boolean(void *ctx, int b) {
|
||||
struct uwsgi_yajl_old_state *uyos = (struct uwsgi_yajl_old_state *) ctx;
|
||||
if (!uyos->key) return 1;
|
||||
if (b) {
|
||||
add_exported_option(uyos->key, strdup("1"), 0);
|
||||
}
|
||||
else {
|
||||
add_exported_option(uyos->key, strdup("0"), 0);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int uwsgi_yajl_cb_integer(void *ctx, long n) {
|
||||
struct uwsgi_yajl_old_state *uyos = (struct uwsgi_yajl_old_state *) ctx;
|
||||
if (!uyos->key) return 1;
|
||||
add_exported_option(uyos->key, uwsgi_64bit2str((int64_t) n), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int uwsgi_yajl_cb_double(void *ctx, double n) {
|
||||
return uwsgi_yajl_cb_integer(ctx, (long) n);
|
||||
}
|
||||
|
||||
static int uwsgi_yajl_cb_string(void *ctx, const unsigned char *s, unsigned int s_len) {
|
||||
struct uwsgi_yajl_old_state *uyos = (struct uwsgi_yajl_old_state *) ctx;
|
||||
if (!uyos->key) return 1;
|
||||
add_exported_option(uyos->key, uwsgi_concat2n((char *)s, (size_t)s_len, "", 0), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int uwsgi_yajl_cb_number(void *ctx, const char *n, unsigned int n_len) {
|
||||
return uwsgi_yajl_cb_string(ctx, (const unsigned char *)n, n_len);
|
||||
}
|
||||
|
||||
static int uwsgi_yajl_cb_map_key(void *ctx, const unsigned char *s, unsigned int s_len) {
|
||||
struct uwsgi_yajl_old_state *uyos = (struct uwsgi_yajl_old_state *) ctx;
|
||||
if (!uyos->in_object) {
|
||||
if (!uwsgi_strncmp(uyos->object, strlen(uyos->object), (char *)s, (size_t)s_len)) {
|
||||
uyos->in_object = 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
uyos->key = uwsgi_concat2n((char *)s, (size_t)s_len, "", 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static yajl_callbacks callbacks = {
|
||||
.yajl_null = uwsgi_yajl_cb_null,
|
||||
.yajl_boolean = uwsgi_yajl_cb_boolean,
|
||||
.yajl_integer = uwsgi_yajl_cb_integer,
|
||||
.yajl_double = uwsgi_yajl_cb_double,
|
||||
.yajl_number = uwsgi_yajl_cb_number,
|
||||
.yajl_string = uwsgi_yajl_cb_string,
|
||||
.yajl_start_map = NULL,
|
||||
.yajl_map_key = uwsgi_yajl_cb_map_key,
|
||||
.yajl_end_map = NULL,
|
||||
.yajl_start_array = NULL,
|
||||
.yajl_end_array = NULL,
|
||||
};
|
||||
|
||||
void uwsgi_json_config(char *file, char *magic_table[]) {
|
||||
size_t len = 0;
|
||||
|
||||
char *object_asked = "uwsgi";
|
||||
char *colon;
|
||||
|
||||
if (uwsgi_check_scheme(file)) {
|
||||
colon = uwsgi_get_last_char(file, '/');
|
||||
colon = uwsgi_get_last_char(colon, ':');
|
||||
}
|
||||
else {
|
||||
colon = uwsgi_get_last_char(file, ':');
|
||||
}
|
||||
|
||||
if (colon) {
|
||||
colon[0] = 0;
|
||||
if (colon[1] != 0) {
|
||||
object_asked = colon + 1;
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_yajl_old_state uyos;
|
||||
memset(&uyos, 0, sizeof(struct uwsgi_yajl_old_state));
|
||||
uyos.object = object_asked;
|
||||
uwsgi_log_initial("[uWSGI] getting JSON configuration from %s\n", file);
|
||||
|
||||
char *json_data = uwsgi_open_and_read(file, &len, 1, magic_table);
|
||||
|
||||
yajl_handle hand = yajl_alloc(&callbacks, NULL, NULL, &uyos);
|
||||
|
||||
yajl_status s = yajl_parse(hand, (const unsigned char *)json_data, len);
|
||||
if (s != yajl_status_ok) {
|
||||
uwsgi_log("%s\n", yajl_get_error(hand, 1, (const unsigned char *)json_data, len));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#elif defined(UWSGI_JSON_YAJL)
|
||||
#include <yajl/yajl_tree.h>
|
||||
|
||||
void uwsgi_json_config(char *file, char *magic_table[]) {
|
||||
|
||||
+57
-10
@@ -279,9 +279,12 @@ static void legions_check_nodes_step2() {
|
||||
// go on if i am not an arbiter
|
||||
else if (ul->valor > 0) {
|
||||
// no potential Lord is available, i will propose myself
|
||||
best_valor = ul->valor;
|
||||
memcpy(best_uuid, ul->uuid, 36);
|
||||
i_am_the_best = 1;
|
||||
// but only if i am not suspended...
|
||||
if (uwsgi_now() > ul->suspended_til) {
|
||||
best_valor = ul->valor;
|
||||
memcpy(best_uuid, ul->uuid, 36);
|
||||
i_am_the_best = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// empty lord
|
||||
@@ -337,13 +340,20 @@ static void legions_check_nodes_step2() {
|
||||
}
|
||||
if (i_am_the_best) {
|
||||
if (!ul->i_am_the_lord) {
|
||||
uwsgi_log("[uwsgi-legion] i am now the Lord of the Legion %s\n", ul->legion);
|
||||
// triggering lord hooks
|
||||
uwsgi_log("[uwsgi-legion] attempting to become the Lord of the Legion %s\n", ul->legion);
|
||||
struct uwsgi_string_list *usl = ul->lord_hooks;
|
||||
while (usl) {
|
||||
int ret = uwsgi_legion_action_call("lord", ul, usl);
|
||||
if (ret) {
|
||||
uwsgi_log("[uwsgi-legion] ERROR, lord hook returned: %d\n", ret);
|
||||
if (uwsgi.legion_death_on_lord_error) {
|
||||
ul->dead = 1;
|
||||
uwsgi_legion_announce(ul);
|
||||
ul->suspended_til = uwsgi_now() + uwsgi.legion_death_on_lord_error;
|
||||
uwsgi_log("[uwsgi-legion] suspending myself from Legion \"%s\" for %d seconds\n", ul->legion, uwsgi.legion_death_on_lord_error);
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
@@ -356,6 +366,7 @@ static void legions_check_nodes_step2() {
|
||||
else {
|
||||
ul->lord_scroll_len = 0;
|
||||
}
|
||||
uwsgi_log("[uwsgi-legion] i am now the Lord of the Legion %s\n", ul->legion);
|
||||
ul->i_am_the_lord = uwsgi_now();
|
||||
// trick: reduce the time needed by the old lord to unlord itself
|
||||
uwsgi_legion_announce(ul);
|
||||
@@ -400,7 +411,7 @@ static void legions_check_nodes_step2() {
|
||||
}
|
||||
ul->last_warning = uwsgi_now();
|
||||
}
|
||||
|
||||
next:
|
||||
ul = ul->next;
|
||||
}
|
||||
}
|
||||
@@ -496,8 +507,15 @@ static void *legion_loop(void *foobar) {
|
||||
last_round = now;
|
||||
// wait for event
|
||||
int interesting_fd = -1;
|
||||
if (uwsgi_instance_is_reloading || uwsgi_instance_is_dying) return NULL;
|
||||
int rlen = event_queue_wait(uwsgi.legion_queue, timeout, &interesting_fd);
|
||||
|
||||
if (rlen < 0 && errno != EINTR) {
|
||||
if (uwsgi_instance_is_reloading || uwsgi_instance_is_dying) return NULL;
|
||||
uwsgi_nuclear_blast();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
now = uwsgi_now();
|
||||
if (timeout == 0 || rlen == 0 || (now - last_round) >= timeout) {
|
||||
struct uwsgi_legion *legions = uwsgi.legions;
|
||||
@@ -591,6 +609,8 @@ static void *legion_loop(void *foobar) {
|
||||
// check if the node is already accounted
|
||||
struct uwsgi_legion_node *node = uwsgi_legion_get_node(ul, legion_msg.valor, legion_msg.name, legion_msg.name_len, legion_msg.uuid);
|
||||
if (!node) {
|
||||
// if a lord hook election fails, a node can announce itself as dead for long time...
|
||||
if (legion_msg.dead) continue;
|
||||
// add the new node
|
||||
uwsgi_wlock(ul->lock);
|
||||
node = uwsgi_legion_add_node(ul, legion_msg.valor, legion_msg.name, legion_msg.name_len, legion_msg.uuid);
|
||||
@@ -648,7 +668,12 @@ int uwsgi_legion_action_call(char *phase, struct uwsgi_legion *ul, struct uwsgi_
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_log("[uwsgi-legion] (phase: %s legion: %s) calling %s\n", phase, ul->legion, usl->value);
|
||||
if (ula->log_msg) {
|
||||
uwsgi_log("[uwsgi-legion] (phase: %s legion: %s) %s\n", phase, ul->legion, ula->log_msg);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[uwsgi-legion] (phase: %s legion: %s) calling %s\n", phase, ul->legion, usl->value);
|
||||
}
|
||||
return ula->func(ul, usl->value + usl->custom);
|
||||
}
|
||||
|
||||
@@ -667,6 +692,18 @@ static int legion_action_log(struct uwsgi_legion *ul, char *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int legion_action_alarm(struct uwsgi_legion *ul, char *arg) {
|
||||
char *space = strchr(arg,' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid alarm action syntax, must be: <alarm> <msg>\n");
|
||||
return -1;
|
||||
}
|
||||
*space = 0;
|
||||
uwsgi_alarm_trigger(arg, space+1, strlen(space+1));
|
||||
*space = ' ';
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_start_legions() {
|
||||
pthread_t legion_loop_t;
|
||||
|
||||
@@ -675,8 +712,10 @@ void uwsgi_start_legions() {
|
||||
|
||||
// register embedded actions
|
||||
uwsgi_legion_action_register("cmd", legion_action_cmd);
|
||||
uwsgi_legion_action_register("exec", legion_action_cmd);
|
||||
uwsgi_legion_action_register("signal", legion_action_signal);
|
||||
uwsgi_legion_action_register("log", legion_action_log);
|
||||
uwsgi_legion_action_register("alarm", legion_action_alarm);
|
||||
|
||||
uwsgi.legion_queue = event_queue_init();
|
||||
struct uwsgi_legion *legion = uwsgi.legions;
|
||||
@@ -736,6 +775,11 @@ void uwsgi_legion_add(struct uwsgi_legion *ul) {
|
||||
}
|
||||
|
||||
int uwsgi_legion_announce(struct uwsgi_legion *ul) {
|
||||
time_t now = uwsgi_now();
|
||||
|
||||
if (now <= ul->suspended_til) return 0;
|
||||
ul->suspended_til = 0;
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(4096);
|
||||
unsigned char *encrypted = NULL;
|
||||
|
||||
@@ -743,7 +787,7 @@ int uwsgi_legion_announce(struct uwsgi_legion *ul) {
|
||||
goto err;
|
||||
if (uwsgi_buffer_append_keynum(ub, "valor", 5, ul->valor))
|
||||
goto err;
|
||||
if (uwsgi_buffer_append_keynum(ub, "unix", 4, uwsgi_now()))
|
||||
if (uwsgi_buffer_append_keynum(ub, "unix", 4, now))
|
||||
goto err;
|
||||
if (uwsgi_buffer_append_keynum(ub, "lord", 4, ul->i_am_the_lord ? ul->i_am_the_lord : 0))
|
||||
goto err;
|
||||
@@ -1115,10 +1159,11 @@ struct uwsgi_legion_action *uwsgi_legion_action_get(char *name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void uwsgi_legion_action_register(char *name, int (*func) (struct uwsgi_legion *, char *)) {
|
||||
if (uwsgi_legion_action_get(name)) {
|
||||
struct uwsgi_legion_action *uwsgi_legion_action_register(char *name, int (*func) (struct uwsgi_legion *, char *)) {
|
||||
struct uwsgi_legion_action *found_ula = uwsgi_legion_action_get(name);
|
||||
if (found_ula) {
|
||||
uwsgi_log("[uwsgi-legion] action \"%s\" is already registered !!!\n", name);
|
||||
return;
|
||||
return found_ula;
|
||||
}
|
||||
|
||||
struct uwsgi_legion_action *old_ula = NULL, *ula = uwsgi.legion_actions;
|
||||
@@ -1137,6 +1182,8 @@ void uwsgi_legion_action_register(char *name, int (*func) (struct uwsgi_legion *
|
||||
else {
|
||||
uwsgi.legion_actions = ula;
|
||||
}
|
||||
|
||||
return ula;
|
||||
}
|
||||
|
||||
void uwsgi_legion_announce_death(void) {
|
||||
|
||||
+35
-1
@@ -242,6 +242,17 @@ static void master_check_listen_queue() {
|
||||
if (uwsgi_sock->queue > 0 && uwsgi_sock->queue >= uwsgi_sock->max_queue) {
|
||||
uwsgi_log_verbose("*** uWSGI listen queue of socket \"%s\" (fd: %d) full !!! (%llu/%llu) ***\n", uwsgi_sock->name, uwsgi_sock->fd, (unsigned long long) uwsgi_sock->queue, (unsigned long long) uwsgi_sock->max_queue);
|
||||
}
|
||||
|
||||
if (uwsgi.alarm_backlog) {
|
||||
char buf[1024];
|
||||
int ret = snprintf(buf, 1024, "listen queue of socket \"%s\" (fd: %d) full !!! (%llu/%llu)", uwsgi_sock->name, uwsgi_sock->fd, (unsigned long long) uwsgi_sock->queue, (unsigned long long) uwsgi_sock->max_queue);
|
||||
if (ret > 0 && ret < 1024) {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.alarm_backlog) {
|
||||
uwsgi_alarm_trigger(usl->value, buf, ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
@@ -323,6 +334,12 @@ int master_loop(char **argv, char **environ) {
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.master_fifo_fd);
|
||||
}
|
||||
|
||||
if (uwsgi.notify_socket) {
|
||||
uwsgi.notify_socket_fd = bind_to_unix_dgram(uwsgi.notify_socket);
|
||||
uwsgi_log("notification socket enabled on %s (fd: %d)\n", uwsgi.notify_socket, uwsgi.notify_socket_fd);
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.notify_socket_fd);
|
||||
}
|
||||
|
||||
if (uwsgi.spoolers) {
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->spooler_signal_pipe[0]);
|
||||
}
|
||||
@@ -508,6 +525,16 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
ud = ud->next;
|
||||
}
|
||||
// hook touches
|
||||
uwsgi_foreach(usl, uwsgi.hook_touch) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
usl->len = strlen(usl->value);
|
||||
uwsgi_string_new_list((struct uwsgi_string_list **)&usl->custom_ptr, space+1);
|
||||
}
|
||||
}
|
||||
uwsgi_check_touches(uwsgi.hook_touch);
|
||||
|
||||
// fsmon
|
||||
uwsgi_fsmon_setup();
|
||||
@@ -555,6 +582,7 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
|
||||
// here really starts the master loop
|
||||
uwsgi_hooks_run(uwsgi.hook_master_start, "master-start", 1);
|
||||
|
||||
for (;;) {
|
||||
//uwsgi_log("uwsgi.ready_to_reload %d %d\n", uwsgi.ready_to_reload, uwsgi.numproc);
|
||||
@@ -807,7 +835,7 @@ int master_loop(char **argv, char **environ) {
|
||||
touched = uwsgi_check_touches(ud->touch);
|
||||
if (touched) {
|
||||
uwsgi_log_verbose("*** %s has been touched... reloading daemon \"%s\" (pid: %d) !!! ***\n", touched, ud->command, (int) ud->pid);
|
||||
if (kill(ud->pid, ud->stop_signal)) {
|
||||
if (kill(-ud->pid, ud->stop_signal)) {
|
||||
uwsgi_error("[uwsgi-daemon/touch] kill()");
|
||||
}
|
||||
}
|
||||
@@ -815,6 +843,12 @@ int master_loop(char **argv, char **environ) {
|
||||
ud = ud->next;
|
||||
}
|
||||
|
||||
// hook touches
|
||||
touched = uwsgi_check_touches(uwsgi.hook_touch);
|
||||
if (touched) {
|
||||
uwsgi_hooks_run((struct uwsgi_string_list *) touched, "touch", 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// allows the KILL signal to be delivered;
|
||||
|
||||
@@ -22,6 +22,10 @@ int uwsgi_master_manage_events(int interesting_fd) {
|
||||
return uwsgi_master_fifo_manage(uwsgi.master_fifo_fd);
|
||||
}
|
||||
|
||||
if (uwsgi.notify_socket_fd > -1 && interesting_fd == uwsgi.notify_socket_fd) {
|
||||
return uwsgi_notify_socket_manage(interesting_fd);
|
||||
}
|
||||
|
||||
// stats server ?
|
||||
if (uwsgi.stats && uwsgi.stats_fd > -1) {
|
||||
if (interesting_fd == uwsgi.stats_fd) {
|
||||
|
||||
@@ -407,6 +407,7 @@ void uwsgi_reload(char **argv) {
|
||||
/* check fd table (a module can obviosly open some fd on initialization...) */
|
||||
uwsgi_log("closing all non-uwsgi socket fds > 2 (max_fd = %d)...\n", (int) uwsgi.max_fd);
|
||||
for (i = 3; i < (int) uwsgi.max_fd; i++) {
|
||||
if (uwsgi.close_on_exec2) fcntl(i, F_SETFD, 0);
|
||||
|
||||
if (uwsgi_fd_is_safe(i)) continue;
|
||||
|
||||
@@ -587,6 +588,8 @@ void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
|
||||
|
||||
if (uwsgi.master_fifo_fd > -1) close(uwsgi.master_fifo_fd);
|
||||
|
||||
if (uwsgi.notify_socket_fd > -1) close(uwsgi.notify_socket_fd);
|
||||
|
||||
#ifdef __linux__
|
||||
for(i=0;i<uwsgi.setns_fds_count;i++) {
|
||||
close(uwsgi.setns_fds[i]);
|
||||
|
||||
@@ -75,3 +75,39 @@ void uwsgi_systemd_init(char *systemd_socket) {
|
||||
uwsgi.notify_ready = uwsgi_systemd_notify_ready;
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_notify_socket_manage(int fd) {
|
||||
char buf[8192];
|
||||
ssize_t rlen = read(fd, buf, 8192);
|
||||
if (rlen < 0) {
|
||||
if (uwsgi_is_again()) return 0;
|
||||
uwsgi_error("uwsgi_notify_socket_manage()/read()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (rlen > 0) {
|
||||
uwsgi_log_verbose("[notify-socket] %.*s\n", rlen, buf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_notify_msg(char *dst, char *msg, size_t len) {
|
||||
static int notify_fd = -1;
|
||||
if (notify_fd < 0) {
|
||||
notify_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||
if (notify_fd < 0) {
|
||||
uwsgi_error("uwsgi_notify_msg()/socket()");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
struct sockaddr_un un_addr;
|
||||
memset(&un_addr, 0, sizeof(struct sockaddr_un));
|
||||
un_addr.sun_family = AF_UNIX;
|
||||
// use 102 as the magic number
|
||||
strncat(un_addr.sun_path, dst, 102);
|
||||
if (sendto(notify_fd, msg, len, 0, (struct sockaddr *) &un_addr, sizeof(un_addr)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
+61
-90
@@ -76,18 +76,66 @@ char *uwsgi_getsockname(int fd) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int create_server_socket(int domain, int type) {
|
||||
int serverfd = socket(domain, type, 0);
|
||||
if (serverfd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uwsgi.close_on_exec2 && fcntl(serverfd, F_SETFD, FD_CLOEXEC) < 0)
|
||||
uwsgi_error("fcntl()");
|
||||
|
||||
if (domain != AF_UNIX) {
|
||||
int reuse = 1;
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) {
|
||||
uwsgi_error("SO_REUSEADDR setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == SOCK_STREAM) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
long somaxconn = uwsgi_num_from_file("/proc/sys/net/core/somaxconn", 1);
|
||||
if (somaxconn > 0 && uwsgi.listen_queue > somaxconn) {
|
||||
uwsgi_log("Listen queue size is greater than the system max net.core.somaxconn (%li).\n", somaxconn);
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return serverfd;
|
||||
}
|
||||
|
||||
int bind_to_unix_dgram(char *socket_name) {
|
||||
|
||||
int serverfd;
|
||||
struct sockaddr_un *uws_addr;
|
||||
socklen_t len;
|
||||
|
||||
serverfd = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||
if (serverfd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
serverfd = create_server_socket(AF_UNIX, SOCK_DGRAM);
|
||||
if (serverfd < 0) return -1;
|
||||
|
||||
if (unlink(socket_name) != 0 && errno != ENOENT) {
|
||||
uwsgi_error("error removing unix socket, unlink()");
|
||||
@@ -140,15 +188,11 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
}
|
||||
|
||||
memset(uws_addr, 0, sizeof(struct sockaddr_un));
|
||||
serverfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (serverfd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
serverfd = create_server_socket(AF_UNIX, SOCK_STREAM);
|
||||
if (serverfd < 0) return -1;
|
||||
if (abstract_socket == 0) {
|
||||
if (unlink(socket_name) != 0 && errno != ENOENT) {
|
||||
uwsgi_error("unlink()");
|
||||
uwsgi_error("error removing unix socket, unlink()");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,24 +200,6 @@ 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));
|
||||
@@ -203,15 +229,6 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
long somaxconn = uwsgi_num_from_file("/proc/sys/net/core/somaxconn", 1);
|
||||
if (somaxconn > 0 && uwsgi.listen_queue > somaxconn) {
|
||||
uwsgi_log("Listen queue size is greater than the system max net.core.somaxconn (%li).\n", somaxconn);
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (listen(serverfd, listen_queue) != 0) {
|
||||
uwsgi_error("listen()");
|
||||
uwsgi_nuclear_blast();
|
||||
@@ -243,7 +260,6 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
|
||||
struct sockaddr_in uws_addr;
|
||||
char *udp_port;
|
||||
int bcast = 1;
|
||||
int reuse = 1;
|
||||
|
||||
struct ip_mreq mc;
|
||||
|
||||
@@ -288,15 +304,8 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
|
||||
}
|
||||
|
||||
|
||||
serverfd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (serverfd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) {
|
||||
uwsgi_error("setsockopt()");
|
||||
}
|
||||
serverfd = create_server_socket(AF_INET, SOCK_DGRAM);
|
||||
if (serverfd < 0) return -1;
|
||||
|
||||
if (multicast) {
|
||||
// if multicast is enabled remember to bind to INADDR_ANY
|
||||
@@ -649,7 +658,6 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
#else
|
||||
struct sockaddr_in uws_addr;
|
||||
#endif
|
||||
int reuse = 1;
|
||||
int family = AF_INET;
|
||||
socklen_t addr_len = sizeof(struct sockaddr_in);
|
||||
|
||||
@@ -667,37 +675,9 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
#endif
|
||||
|
||||
|
||||
serverfd = socket(family, SOCK_STREAM, 0);
|
||||
if (serverfd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
serverfd = create_server_socket(family, SOCK_STREAM);
|
||||
if (serverfd < 0) 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()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
#ifndef IP_FREEBIND
|
||||
#define IP_FREEBIND 15
|
||||
@@ -781,15 +761,6 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
long somaxconn = uwsgi_num_from_file("/proc/sys/net/core/somaxconn", 1);
|
||||
if (somaxconn > 0 && uwsgi.listen_queue > somaxconn) {
|
||||
uwsgi_log("Listen queue size is greater than the system max net.core.somaxconn (%li).\n", somaxconn);
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (listen(serverfd, listen_queue) != 0) {
|
||||
uwsgi_error("listen()");
|
||||
uwsgi_nuclear_blast();
|
||||
|
||||
+108
-30
@@ -72,12 +72,12 @@ struct uwsgi_spooler *uwsgi_new_spooler(char *dir) {
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_spooler *uwsgi_get_spooler_by_name(char *name) {
|
||||
struct uwsgi_spooler *uwsgi_get_spooler_by_name(char *name, size_t name_len) {
|
||||
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
|
||||
while (uspool) {
|
||||
if (!strcmp(uspool->dir, name)) {
|
||||
if (!uwsgi_strncmp(uspool->dir, strlen(uspool->dir), name, name_len)) {
|
||||
return uspool;
|
||||
}
|
||||
uspool = uspool->next;
|
||||
@@ -167,47 +167,122 @@ void destroy_spool(char *dir, char *file) {
|
||||
|
||||
}
|
||||
|
||||
struct spooler_req {
|
||||
char *spooler;
|
||||
size_t spooler_len;
|
||||
char *priority;
|
||||
size_t priority_len;
|
||||
time_t at;
|
||||
};
|
||||
|
||||
int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core_id, char *buffer, int size, char *priority, time_t at, char *body, size_t body_len) {
|
||||
static void spooler_req_parser_hook(char *key, uint16_t key_len, char *value, uint16_t value_len, void *data) {
|
||||
struct spooler_req *sr = (struct spooler_req *) data;
|
||||
if (!uwsgi_strncmp(key, key_len, "spooler", 7)) {
|
||||
sr->spooler = value;
|
||||
sr->spooler_len = value_len;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!uwsgi_strncmp(key, key_len, "priority", 8)) {
|
||||
sr->priority = value;
|
||||
sr->priority_len = value_len;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!uwsgi_strncmp(key, key_len, "at", 2)) {
|
||||
sr->at = uwsgi_str_num(value, value_len);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
char *uwsgi_spool_request(struct wsgi_request *wsgi_req, char *buf, size_t len, char *body, size_t body_len) {
|
||||
|
||||
struct timeval tv;
|
||||
int fd;
|
||||
struct uwsgi_header uh;
|
||||
static uint64_t internal_counter = 0;
|
||||
int core_id = 0;
|
||||
int fd = -1;
|
||||
struct spooler_req sr;
|
||||
|
||||
if (len > 0xffff) {
|
||||
uwsgi_log("[uwsgi-spooler] args buffer is limited to 64k, use the 'body' for bigger values\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// parse the request buffer
|
||||
memset(&sr, 0, sizeof(struct spooler_req));
|
||||
uwsgi_hooked_parse(buf, len, spooler_req_parser_hook, &sr);
|
||||
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
if (!uspool) {
|
||||
uspool = uwsgi.spoolers;
|
||||
uwsgi_log("[uwsgi-spooler] no spooler available\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// if it is a number, get the spooler by id instead of by name
|
||||
if (sr.spooler && sr.spooler_len) {
|
||||
uspool = uwsgi_get_spooler_by_name(sr.spooler, sr.spooler_len);
|
||||
if (!uspool) {
|
||||
uwsgi_log("[uwsgi-spooler] unable to find spooler \"%.*s\"\n", sr.spooler_len, sr.spooler);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (wsgi_req) {
|
||||
core_id = wsgi_req->async_id;
|
||||
}
|
||||
|
||||
// this lock is for threads, the pid value in filename will avoid multiprocess races
|
||||
uwsgi_lock(uspool->lock);
|
||||
|
||||
// we increase it even if the request fails
|
||||
internal_counter++;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
if (priority) {
|
||||
if (snprintf(filename, 1024, "%s/%s", uspool->dir, priority) <= 0) {
|
||||
char *filename = NULL;
|
||||
size_t filename_len = 0;
|
||||
|
||||
if (sr.priority && sr.priority_len) {
|
||||
filename_len = strlen(uspool->dir) + sr.priority_len + strlen(uwsgi.hostname) + 256;
|
||||
filename = uwsgi_malloc(filename_len);
|
||||
int ret = snprintf(filename, filename_len, "%s/%.*s", uspool->dir, (int) sr.priority_len, sr.priority);
|
||||
if (ret <= 0 || ret >= (int) filename_len) {
|
||||
uwsgi_log("[uwsgi-spooler] error generating spooler filename\n");
|
||||
free(filename);
|
||||
uwsgi_unlock(uspool->lock);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
// no need to check for errors...
|
||||
(void) mkdir(filename, 0777);
|
||||
|
||||
if (snprintf(filename, 1024, "%s/%s/uwsgi_spoolfile_on_%s_%d_%d_%d_%llu_%llu", uspool->dir, priority, uwsgi.hostname, (int) getpid(), rn, core_id, (unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec) <= 0) {
|
||||
ret = snprintf(filename, filename_len, "%s/%.*s/uwsgi_spoolfile_on_%s_%d_%llu_%d_%llu_%llu", uspool->dir, (int)sr.priority_len, sr.priority, uwsgi.hostname, (int) getpid(), (unsigned long long) internal_counter, core_id,
|
||||
(unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec);
|
||||
if (ret <= 0 || ret >=(int) filename_len) {
|
||||
uwsgi_log("[uwsgi-spooler] error generating spooler filename\n");
|
||||
free(filename);
|
||||
uwsgi_unlock(uspool->lock);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (snprintf(filename, 1024, "%s/uwsgi_spoolfile_on_%s_%d_%d_%d_%llu_%llu", uspool->dir, uwsgi.hostname, (int) getpid(), rn, core_id, (unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec) <= 0) {
|
||||
filename_len = strlen(uspool->dir) + strlen(uwsgi.hostname) + 256;
|
||||
filename = uwsgi_malloc(filename_len);
|
||||
int ret = snprintf(filename, filename_len, "%s/uwsgi_spoolfile_on_%s_%d_%llu_%d_%llu_%llu", uspool->dir, uwsgi.hostname, (int) getpid(), (unsigned long long) internal_counter, core_id,
|
||||
(unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec);
|
||||
if (ret <= 0 || ret >= (int) filename_len) {
|
||||
uwsgi_log("[uwsgi-spooler] error generating spooler filename\n");
|
||||
free(filename);
|
||||
uwsgi_unlock(uspool->lock);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
fd = open(filename, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(filename);
|
||||
free(filename);
|
||||
uwsgi_unlock(uspool->lock);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// now lock the file, it will no be runnable, until the lock is not removed
|
||||
@@ -215,13 +290,15 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
|
||||
// in such case the spooler will detect a zeroed file and will retry later
|
||||
if (uwsgi_fcntl_lock(fd)) {
|
||||
close(fd);
|
||||
free(filename);
|
||||
uwsgi_unlock(uspool->lock);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_header uh;
|
||||
uh.modifier1 = 17;
|
||||
uh.modifier2 = 0;
|
||||
uh.pktsize = (uint16_t) size;
|
||||
uh.pktsize = (uint16_t) len;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
uh.pktsize = uwsgi_swap16(uh.pktsize);
|
||||
#endif
|
||||
@@ -231,7 +308,7 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
|
||||
goto clear;
|
||||
}
|
||||
|
||||
if (write(fd, buffer, size) != size) {
|
||||
if (write(fd, buf, len) != (ssize_t) len) {
|
||||
uwsgi_log("[spooler] unable to write args for %s\n", filename);
|
||||
goto clear;
|
||||
}
|
||||
@@ -243,28 +320,28 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
|
||||
}
|
||||
}
|
||||
|
||||
if (at > 0) {
|
||||
if (sr.at > 0) {
|
||||
#ifdef __UCLIBC__
|
||||
struct timespec ts[2];
|
||||
ts[0].tv_sec = at;
|
||||
ts[0].tv_sec = sr.at;
|
||||
ts[0].tv_nsec = 0;
|
||||
ts[1].tv_sec = at;
|
||||
ts[1].tv_sec = sr.at;
|
||||
ts[1].tv_nsec = 0;
|
||||
if (futimens(fd, ts)) {
|
||||
uwsgi_error("futimens()");
|
||||
uwsgi_error("uwsgi_spooler_request()/futimens()");
|
||||
}
|
||||
#else
|
||||
struct timeval tv[2];
|
||||
tv[0].tv_sec = at;
|
||||
tv[0].tv_sec = sr.at;
|
||||
tv[0].tv_usec = 0;
|
||||
tv[1].tv_sec = at;
|
||||
tv[1].tv_sec = sr.at;
|
||||
tv[1].tv_usec = 0;
|
||||
#ifdef __sun__
|
||||
if (futimesat(fd, NULL, tv)) {
|
||||
#else
|
||||
if (futimes(fd, tv)) {
|
||||
#endif
|
||||
uwsgi_error("futimes()");
|
||||
uwsgi_error("uwsgi_spooler_request()/futimes()");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -273,7 +350,7 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
|
||||
close(fd);
|
||||
|
||||
if (!uwsgi.spooler_quiet)
|
||||
uwsgi_log("[spooler] written %lu bytes to file %s\n", (unsigned long) size + body_len + 4, filename);
|
||||
uwsgi_log("[spooler] written %lu bytes to file %s\n", (unsigned long) len + body_len + 4, filename);
|
||||
|
||||
// and here waiting threads can continue
|
||||
uwsgi_unlock(uspool->lock);
|
||||
@@ -293,18 +370,19 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
|
||||
spoolers = spoolers->next;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return filename;
|
||||
|
||||
|
||||
clear:
|
||||
uwsgi_unlock(uspool->lock);
|
||||
uwsgi_error("write()");
|
||||
uwsgi_error("uwsgi_spool_request()/write()");
|
||||
if (unlink(filename)) {
|
||||
uwsgi_error("unlink()");
|
||||
uwsgi_error("uwsgi_spool_request()/unlink()");
|
||||
}
|
||||
free(filename);
|
||||
// unlock the file too
|
||||
close(fd);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -367,7 +445,7 @@ void spooler(struct uwsgi_spooler *uspool) {
|
||||
spooler_readdir(uspool, NULL);
|
||||
}
|
||||
|
||||
int timeout = uwsgi.shared->spooler_frequency;
|
||||
int timeout = uwsgi.shared->spooler_frequency ? uwsgi.shared->spooler_frequency : uwsgi.spooler_frequency;
|
||||
if (wakeup > 0) {
|
||||
timeout = 0;
|
||||
}
|
||||
|
||||
+109
-13
@@ -95,15 +95,38 @@ static int uwsgi_sni_cb(SSL *ssl, int *ad, void *arg) {
|
||||
const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
|
||||
if (!servername) return SSL_TLSEXT_ERR_NOACK;
|
||||
size_t servername_len = strlen(servername);
|
||||
// reduce DOS attempts
|
||||
int count = 5;
|
||||
|
||||
struct uwsgi_string_list *usl = uwsgi.sni;
|
||||
while(usl) {
|
||||
if (!uwsgi_strncmp(usl->value, usl->len, (char *)servername, servername_len)) {
|
||||
SSL_set_SSL_CTX(ssl, usl->custom_ptr);
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
while(count > 0) {
|
||||
struct uwsgi_string_list *usl = uwsgi.sni;
|
||||
while(usl) {
|
||||
if (!uwsgi_strncmp(usl->value, usl->len, (char *)servername, servername_len)) {
|
||||
SSL_set_SSL_CTX(ssl, (SSL_CTX *) usl->custom_ptr);
|
||||
// the following steps are taken from nginx
|
||||
SSL_set_verify(ssl, SSL_CTX_get_verify_mode((SSL_CTX *)usl->custom_ptr),
|
||||
SSL_CTX_get_verify_callback((SSL_CTX *)usl->custom_ptr));
|
||||
SSL_set_verify_depth(ssl, SSL_CTX_get_verify_depth((SSL_CTX *)usl->custom_ptr));
|
||||
#ifdef SSL_CTRL_CLEAR_OPTIONS
|
||||
SSL_clear_options(ssl, SSL_get_options(ssl) & ~SSL_CTX_get_options((SSL_CTX *)usl->custom_ptr));
|
||||
#endif
|
||||
SSL_set_options(ssl, SSL_CTX_get_options((SSL_CTX *)usl->custom_ptr));
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
if (!uwsgi.subscription_dotsplit) break;
|
||||
char *next = memchr(servername+1, '.', servername_len-1);
|
||||
if (next) {
|
||||
servername_len -= next - servername;
|
||||
servername = next;
|
||||
count--;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (uwsgi.subscription_dotsplit) goto end;
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
struct uwsgi_regexp_list *url = uwsgi.sni_regexp;
|
||||
@@ -126,7 +149,7 @@ static int uwsgi_sni_cb(SSL *ssl, int *ad, void *arg) {
|
||||
if (uwsgi_file_exists(sni_dir_client_ca)) {
|
||||
client_ca = sni_dir_client_ca;
|
||||
}
|
||||
usl = uwsgi_ssl_add_sni_item(uwsgi_str((char *)servername), sni_dir_cert, sni_dir_key, uwsgi.sni_dir_ciphers, client_ca);
|
||||
struct uwsgi_string_list *usl = uwsgi_ssl_add_sni_item(uwsgi_str((char *)servername), sni_dir_cert, sni_dir_key, uwsgi.sni_dir_ciphers, client_ca);
|
||||
if (!usl) goto done;
|
||||
free(sni_dir_cert);
|
||||
free(sni_dir_key);
|
||||
@@ -139,13 +162,39 @@ done:
|
||||
free(sni_dir_key);
|
||||
free(sni_dir_client_ca);
|
||||
}
|
||||
|
||||
end:
|
||||
return SSL_TLSEXT_ERR_NOACK;
|
||||
}
|
||||
#endif
|
||||
|
||||
char *uwsgi_write_pem_to_file(char *name, char *buf, size_t len, char *ext) {
|
||||
if (!uwsgi.ssl_tmp_dir) return NULL;
|
||||
char *filename = uwsgi_concat4(uwsgi.ssl_tmp_dir, "/", name, ext);
|
||||
int fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(filename);
|
||||
free(filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (write(fd, buf, len) != (ssize_t) len) {
|
||||
uwsgi_log("unable to write pem data in file %s\n", filename);
|
||||
uwsgi_error("uwsgi_write_pem_to_file()/write()");
|
||||
free(filename);
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return filename;
|
||||
}
|
||||
|
||||
SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ciphers, char *client_ca) {
|
||||
|
||||
int crt_need_free = 0;
|
||||
int key_need_free = 0;
|
||||
int client_ca_need_free = 0;
|
||||
|
||||
SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method());
|
||||
if (!ctx) {
|
||||
uwsgi_log("[uwsgi-ssl] unable to initialize context \"%s\"\n", name);
|
||||
@@ -165,11 +214,27 @@ SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ci
|
||||
#ifdef SSL_MODE_RELEASE_BUFFERS
|
||||
SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
|
||||
#endif
|
||||
|
||||
/*
|
||||
we need to support both file-based certs and stream based
|
||||
as dealing with openssl memory bio for keys is really overkill,
|
||||
we store them in a tmp directory
|
||||
*/
|
||||
|
||||
if (uwsgi.ssl_tmp_dir && !uwsgi_starts_with(crt, strlen(crt), "-----BEGIN ", 11)) {
|
||||
crt = uwsgi_write_pem_to_file(name, crt, strlen(crt), ".crt");
|
||||
if (!crt) {
|
||||
SSL_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
crt_need_free = 1;
|
||||
}
|
||||
|
||||
if (SSL_CTX_use_certificate_chain_file(ctx, crt) <= 0) {
|
||||
uwsgi_log("[uwsgi-ssl] unable to assign certificate %s for context \"%s\"\n", crt, name);
|
||||
SSL_CTX_free(ctx);
|
||||
return NULL;
|
||||
uwsgi_log("[uwsgi-ssl] unable to assign certificate %s for context \"%s\"\n", crt, name);
|
||||
SSL_CTX_free(ctx);
|
||||
if (crt_need_free) free(crt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// this part is based from stud
|
||||
@@ -192,12 +257,25 @@ SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ci
|
||||
}
|
||||
}
|
||||
|
||||
if (crt_need_free) free(crt);
|
||||
|
||||
if (uwsgi.ssl_tmp_dir && !uwsgi_starts_with(key, strlen(key), "-----BEGIN ", 11)) {
|
||||
key = uwsgi_write_pem_to_file(name, key, strlen(key), ".key");
|
||||
if (!key) {
|
||||
SSL_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
key_need_free = 1;
|
||||
}
|
||||
|
||||
if (SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM) <= 0) {
|
||||
uwsgi_log("[uwsgi-ssl] unable to assign key %s for context \"%s\"\n", key, name);
|
||||
SSL_CTX_free(ctx);
|
||||
if (key_need_free) free(key);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (key_need_free) free(key);
|
||||
|
||||
// if ciphers are specified, prefer server ciphers
|
||||
if (ciphers && strlen(ciphers) > 0) {
|
||||
@@ -225,19 +303,37 @@ SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ci
|
||||
}
|
||||
// in the future we should allow to set the verify depth
|
||||
SSL_CTX_set_verify_depth(ctx, 1);
|
||||
|
||||
if (uwsgi.ssl_tmp_dir && !uwsgi_starts_with(client_ca, strlen(client_ca), "-----BEGIN ", 11)) {
|
||||
if (!name) {
|
||||
SSL_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
client_ca = uwsgi_write_pem_to_file(name, client_ca, strlen(client_ca), ".ca");
|
||||
if (!client_ca) {
|
||||
SSL_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
client_ca_need_free = 1;
|
||||
}
|
||||
|
||||
if (SSL_CTX_load_verify_locations(ctx, client_ca, NULL) == 0) {
|
||||
uwsgi_log("[uwsgi-ssl] unable to set ssl verify locations (%s) for context \"%s\"\n", client_ca, name);
|
||||
SSL_CTX_free(ctx);
|
||||
if (client_ca_need_free) free(client_ca);
|
||||
return NULL;
|
||||
}
|
||||
STACK_OF(X509_NAME) * list = SSL_load_client_CA_file(client_ca);
|
||||
if (!list) {
|
||||
uwsgi_log("unable to load client CA certificate (%s) for context \"%s\"\n", client_ca, name);
|
||||
SSL_CTX_free(ctx);
|
||||
if (client_ca_need_free) free(client_ca);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SSL_CTX_set_client_CA_list(ctx, list);
|
||||
|
||||
if (client_ca_need_free) free(client_ca);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -578,7 +578,7 @@ static void stats_dump_var(char *k, uint16_t kl, char *v, uint16_t vl, void *dat
|
||||
|
||||
int uwsgi_stats_dump_vars(struct uwsgi_stats *us, struct uwsgi_core *uc) {
|
||||
if (!uc->in_request) return 0;
|
||||
struct uwsgi_header *uh = (struct uwsgi_header *) uwsgi.workers[0].cores[0].buffer;
|
||||
struct uwsgi_header *uh = (struct uwsgi_header *) uc->buffer;
|
||||
uint16_t pktsize = uh->pktsize;
|
||||
if (!pktsize) return 0;
|
||||
char *dst = uwsgi.workers[0].cores[0].buffer;
|
||||
|
||||
+435
-325
@@ -23,46 +23,52 @@ extern struct uwsgi_server uwsgi;
|
||||
#ifdef UWSGI_SSL
|
||||
static void uwsgi_subscription_sni_check(struct uwsgi_subscribe_slot *current_slot, struct uwsgi_subscribe_req *usr) {
|
||||
if (usr->sni_key_len > 0 && usr->sni_crt_len > 0) {
|
||||
if (!current_slot->sni_enabled) {
|
||||
char *sni_key = uwsgi_concat2n(usr->sni_key, usr->sni_key_len, "", 0);
|
||||
char *sni_crt = uwsgi_concat2n(usr->sni_crt, usr->sni_crt_len, "", 0);
|
||||
char *sni_ca = NULL;
|
||||
if (usr->sni_ca_len > 0) {
|
||||
sni_ca = uwsgi_concat2n(usr->sni_ca, usr->sni_ca_len, "", 0);
|
||||
}
|
||||
char *servername = NULL;
|
||||
char *colon = memchr(current_slot->key, ':', current_slot->keylen);
|
||||
if (colon) {
|
||||
servername = uwsgi_concat2n(current_slot->key, colon-current_slot->key, "", 0);
|
||||
}
|
||||
else {
|
||||
servername = uwsgi_concat2n(current_slot->key, current_slot->keylen, "", 0);
|
||||
}
|
||||
if (uwsgi_ssl_add_sni_item(servername, sni_crt, sni_key, uwsgi.sni_dir_ciphers , sni_ca)) {
|
||||
current_slot->sni_enabled = 1;
|
||||
}
|
||||
if (sni_key) free(sni_key);
|
||||
if (sni_crt) free(sni_crt);
|
||||
if (sni_ca) free(sni_ca);
|
||||
}
|
||||
}
|
||||
if (!current_slot->sni_enabled) {
|
||||
char *sni_key = uwsgi_concat2n(usr->sni_key, usr->sni_key_len, "", 0);
|
||||
char *sni_crt = uwsgi_concat2n(usr->sni_crt, usr->sni_crt_len, "", 0);
|
||||
char *sni_ca = NULL;
|
||||
if (usr->sni_ca_len > 0) {
|
||||
sni_ca = uwsgi_concat2n(usr->sni_ca, usr->sni_ca_len, "", 0);
|
||||
}
|
||||
char *servername = NULL;
|
||||
char *colon = memchr(current_slot->key, ':', current_slot->keylen);
|
||||
if (colon) {
|
||||
servername = uwsgi_concat2n(current_slot->key, colon - current_slot->key, "", 0);
|
||||
}
|
||||
else {
|
||||
servername = uwsgi_concat2n(current_slot->key, current_slot->keylen, "", 0);
|
||||
}
|
||||
if (uwsgi_ssl_add_sni_item(servername, sni_crt, sni_key, uwsgi.sni_dir_ciphers, sni_ca)) {
|
||||
current_slot->sni_enabled = 1;
|
||||
}
|
||||
if (sni_key)
|
||||
free(sni_key);
|
||||
if (sni_crt)
|
||||
free(sni_crt);
|
||||
if (sni_ca)
|
||||
free(sni_ca);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int uwsgi_subscription_credentials_check(struct uwsgi_subscribe_slot *slot, struct uwsgi_subscribe_req *usr) {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.subscriptions_credentials_check_dir) {
|
||||
char *filename = uwsgi_concat2n(usl->value, usl->len, slot->key, slot->keylen);
|
||||
struct stat st;
|
||||
int ret = stat(filename, &st);
|
||||
free(filename);
|
||||
if (ret != 0) continue;
|
||||
if (st.st_uid != usr->uid) continue;
|
||||
if (st.st_gid != usr->gid) continue;
|
||||
// accepted...
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.subscriptions_credentials_check_dir) {
|
||||
char *filename = uwsgi_concat2n(usl->value, usl->len, slot->key, slot->keylen);
|
||||
struct stat st;
|
||||
int ret = stat(filename, &st);
|
||||
free(filename);
|
||||
if (ret != 0)
|
||||
continue;
|
||||
if (st.st_uid != usr->uid)
|
||||
continue;
|
||||
if (st.st_gid != usr->gid)
|
||||
continue;
|
||||
// accepted...
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_subscribe_slot *uwsgi_get_subscribe_slot(struct uwsgi_subscribe_slot **slot, char *key, uint16_t keylen) {
|
||||
@@ -346,7 +352,7 @@ int uwsgi_remove_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsgi
|
||||
// first check if i am the only node
|
||||
if ((!prev_slot && !next_slot) || next_slot == node_slot) {
|
||||
#ifdef UWSGI_SSL
|
||||
if (uwsgi.subscriptions_sign_check_dir) {
|
||||
if (node_slot->sign_ctx) {
|
||||
EVP_PKEY_free(node_slot->sign_public_key);
|
||||
EVP_MD_CTX_destroy(node_slot->sign_ctx);
|
||||
}
|
||||
@@ -375,7 +381,7 @@ int uwsgi_remove_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsgi
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
if (uwsgi.subscriptions_sign_check_dir) {
|
||||
if (node_slot->sign_ctx) {
|
||||
EVP_PKEY_free(node_slot->sign_public_key);
|
||||
EVP_MD_CTX_destroy(node_slot->sign_ctx);
|
||||
}
|
||||
@@ -388,6 +394,11 @@ end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
static int subscription_new_sign_ctx(struct uwsgi_subscribe_slot *, struct uwsgi_subscribe_req *);
|
||||
static int subscription_is_safe(struct uwsgi_subscribe_req *);
|
||||
#endif
|
||||
|
||||
struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsgi_subscribe_req *usr) {
|
||||
|
||||
struct uwsgi_subscribe_slot *current_slot = uwsgi_get_subscribe_slot(slot, usr->key, usr->keylen), *old_slot = NULL, *a_slot;
|
||||
@@ -396,13 +407,6 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
if (usr->address_len > 0xff || usr->address_len == 0)
|
||||
return NULL;
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
if (uwsgi.subscriptions_sign_check_dir) {
|
||||
if (usr->sign_len == 0 || usr->base_len == 0)
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (current_slot) {
|
||||
#ifdef UWSGI_SSL
|
||||
if (uwsgi.subscriptions_sign_check_dir && !uwsgi_subscription_sign_check(current_slot, usr)) {
|
||||
@@ -419,7 +423,7 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
if (!uwsgi_strncmp(node->name, node->len, usr->address, usr->address_len)) {
|
||||
#ifdef UWSGI_SSL
|
||||
// this should avoid sending sniffed packets...
|
||||
if (uwsgi.subscriptions_sign_check_dir && usr->unix_check <= node->unix_check) {
|
||||
if (current_slot->sign_ctx && !subscription_is_safe(usr) && usr->unix_check <= node->unix_check) {
|
||||
uwsgi_log("[uwsgi-subscription for pid %d] invalid (sniffed ?) packet sent for slot: %.*s node: %.*s unix_check: %lu\n", (int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address, (unsigned long) usr->unix_check);
|
||||
return NULL;
|
||||
}
|
||||
@@ -440,12 +444,12 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
if (uwsgi.subscriptions_sign_check_dir && usr->unix_check < (uwsgi_now() - (time_t) uwsgi.subscriptions_sign_check_tolerance)) {
|
||||
if (current_slot->sign_ctx && !subscription_is_safe(usr) && usr->unix_check < (uwsgi_now() - (time_t) uwsgi.subscriptions_sign_check_tolerance)) {
|
||||
uwsgi_log("[uwsgi-subscription for pid %d] invalid (sniffed ?) packet sent for slot: %.*s node: %.*s unix_check: %lu\n", (int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address, (unsigned long) usr->unix_check);
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
// check here as we are sure the node will be added
|
||||
uwsgi_subscription_sni_check(current_slot, usr);
|
||||
uwsgi_subscription_sni_check(current_slot, usr);
|
||||
#endif
|
||||
|
||||
node = uwsgi_malloc(sizeof(struct uwsgi_subscribe_node));
|
||||
@@ -469,6 +473,11 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
node->pid = usr->pid;
|
||||
node->uid = usr->uid;
|
||||
node->gid = usr->gid;
|
||||
node->notify[0] = 0;
|
||||
if (usr->notify_len > 0 && usr->notify_len < 102) {
|
||||
memcpy(node->notify, usr->notify, usr->notify_len);
|
||||
node->notify[usr->notify_len] = 0;
|
||||
}
|
||||
node->last_check = uwsgi_now();
|
||||
node->slot = current_slot;
|
||||
memcpy(node->name, usr->address, usr->address_len);
|
||||
@@ -476,54 +485,28 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
old_node->next = node;
|
||||
}
|
||||
node->next = NULL;
|
||||
|
||||
uwsgi_log("[uwsgi-subscription for pid %d] %.*s => new node: %.*s\n", (int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address);
|
||||
if (node->notify[0]) {
|
||||
char buf[1024];
|
||||
int ret = snprintf(buf, 1024, "[subscription ack] %.*s => new node: %.*s", usr->keylen, usr->key, usr->address_len, usr->address);
|
||||
if (ret > 0 && ret < 1024)
|
||||
uwsgi_notify_msg(node->notify, buf, ret);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
else {
|
||||
current_slot = uwsgi_malloc(sizeof(struct uwsgi_subscribe_slot));
|
||||
#ifdef UWSGI_SSL
|
||||
FILE *kf = NULL;
|
||||
if (uwsgi.subscriptions_sign_check_dir) {
|
||||
if (usr->unix_check < (uwsgi_now() - (time_t) uwsgi.subscriptions_sign_check_tolerance)) {
|
||||
uwsgi_log("[uwsgi-subscription for pid %d] invalid (sniffed ?) packet sent for slot: %.*s node: %.*s unix_check: %lu\n", (int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address, (unsigned long) usr->unix_check);
|
||||
return NULL;
|
||||
}
|
||||
char *keyfile = uwsgi_sanitize_cert_filename(uwsgi.subscriptions_sign_check_dir, usr->key, usr->keylen);
|
||||
kf = fopen(keyfile, "r");
|
||||
free(keyfile);
|
||||
if (!kf)
|
||||
return NULL;
|
||||
|
||||
current_slot->sign_ctx = NULL;
|
||||
if (uwsgi.subscriptions_sign_check_dir && !subscription_new_sign_ctx(current_slot, usr)) {
|
||||
free(current_slot);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
current_slot = uwsgi_malloc(sizeof(struct uwsgi_subscribe_slot));
|
||||
uint32_t hash = djb33x_hash(usr->key, usr->keylen);
|
||||
int hash_key = hash % 0xffff;
|
||||
current_slot->hash = hash_key;
|
||||
#ifdef UWSGI_SSL
|
||||
if (uwsgi.subscriptions_sign_check_dir) {
|
||||
current_slot->sign_public_key = PEM_read_PUBKEY(kf, NULL, NULL, NULL);
|
||||
fclose(kf);
|
||||
if (!current_slot->sign_public_key) {
|
||||
uwsgi_log("unable to load public key for %.*s\n", usr->keylen, usr->key);
|
||||
free(current_slot);
|
||||
return NULL;
|
||||
}
|
||||
current_slot->sign_ctx = EVP_MD_CTX_create();
|
||||
if (!current_slot->sign_ctx) {
|
||||
uwsgi_log("unable to initialize EVP context for %.*s\n", usr->keylen, usr->key);
|
||||
EVP_PKEY_free(current_slot->sign_public_key);
|
||||
free(current_slot);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!uwsgi_subscription_sign_check(current_slot, usr)) {
|
||||
EVP_PKEY_free(current_slot->sign_public_key);
|
||||
EVP_MD_CTX_destroy(current_slot->sign_ctx);
|
||||
free(current_slot);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
current_slot->keylen = usr->keylen;
|
||||
memcpy(current_slot->key, usr->key, usr->keylen);
|
||||
if (uwsgi.subscriptions_credentials_check_dir) {
|
||||
@@ -561,6 +544,11 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
current_slot->nodes->pid = usr->pid;
|
||||
current_slot->nodes->uid = usr->uid;
|
||||
current_slot->nodes->gid = usr->gid;
|
||||
current_slot->nodes->notify[0] = 0;
|
||||
if (usr->notify_len > 0 && usr->notify_len < 102) {
|
||||
memcpy(current_slot->nodes->notify, usr->notify, usr->notify_len);
|
||||
current_slot->nodes->notify[usr->notify_len] = 0;
|
||||
}
|
||||
memcpy(current_slot->nodes->name, usr->address, usr->address_len);
|
||||
current_slot->nodes->last_check = uwsgi_now();
|
||||
|
||||
@@ -587,98 +575,153 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
|
||||
uwsgi_log("[uwsgi-subscription for pid %d] new pool: %.*s (hash key: %d)\n", (int) uwsgi.mypid, usr->keylen, usr->key, current_slot->hash);
|
||||
uwsgi_log("[uwsgi-subscription for pid %d] %.*s => new node: %.*s\n", (int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address);
|
||||
|
||||
if (current_slot->nodes->notify[0]) {
|
||||
char buf[1024];
|
||||
int ret = snprintf(buf, 1024, "[subscription ack] %.*s => new node: %.*s", usr->keylen, usr->key, usr->address_len, usr->address);
|
||||
if (ret > 0 && ret < 1024)
|
||||
uwsgi_notify_msg(current_slot->nodes->notify, buf, ret);
|
||||
}
|
||||
return current_slot->nodes;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void send_subscription(char *host, char *message, uint16_t message_size) {
|
||||
static void send_subscription(int sfd, char *host, char *message, uint16_t message_size) {
|
||||
|
||||
int fd;
|
||||
struct sockaddr_in udp_addr;
|
||||
struct sockaddr_un un_addr;
|
||||
ssize_t ret;
|
||||
int fd = sfd;
|
||||
struct sockaddr_in udp_addr;
|
||||
struct sockaddr_un un_addr;
|
||||
ssize_t ret;
|
||||
|
||||
char *udp_port = strchr(host, ':');
|
||||
if (udp_port) {
|
||||
udp_port[0] = 0;
|
||||
char *udp_port = strchr(host, ':');
|
||||
|
||||
fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (fd < 0) {
|
||||
uwsgi_error("send_subscription()/socket()");
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&udp_addr, 0, sizeof(struct sockaddr_in));
|
||||
udp_addr.sin_family = AF_INET;
|
||||
udp_addr.sin_port = htons(atoi(udp_port + 1));
|
||||
udp_addr.sin_addr.s_addr = inet_addr(host);
|
||||
}
|
||||
else {
|
||||
fd = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||
if (fd < 0) {
|
||||
uwsgi_error("send_subscription()/socket()");
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&un_addr, 0, sizeof(struct sockaddr_un));
|
||||
un_addr.sun_family = AF_UNIX;
|
||||
// use 102 as the magic number
|
||||
strncat(un_addr.sun_path, host, 102);
|
||||
|
||||
}
|
||||
|
||||
if (udp_port) {
|
||||
ret = sendto(fd, message, message_size, 0, (struct sockaddr *) &udp_addr, sizeof(udp_addr));
|
||||
udp_port[0] = ':';
|
||||
}
|
||||
else {
|
||||
if (uwsgi.subscriptions_use_credentials) {
|
||||
// could be useless as internally the socket could add them automagically
|
||||
ret = uwsgi_pass_cred2(fd, message, message_size, (struct sockaddr *) &un_addr, sizeof(un_addr));
|
||||
if (fd == -1) {
|
||||
if (udp_port) {
|
||||
fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
}
|
||||
else {
|
||||
ret = sendto(fd, message, message_size, 0, (struct sockaddr *) &un_addr, sizeof(un_addr));
|
||||
fd = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||
}
|
||||
if (fd < 0) {
|
||||
uwsgi_error("send_subscription()/socket()");
|
||||
return;
|
||||
}
|
||||
uwsgi_socket_nb(fd);
|
||||
}
|
||||
else if (fd == -2) {
|
||||
static int unix_fd = -1;
|
||||
static int inet_fd = -1;
|
||||
if (udp_port) {
|
||||
if (inet_fd == -1) {
|
||||
inet_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (inet_fd < 0) {
|
||||
uwsgi_error("send_subscription()/socket()");
|
||||
return;
|
||||
}
|
||||
uwsgi_socket_nb(inet_fd);
|
||||
}
|
||||
fd = inet_fd;
|
||||
}
|
||||
else {
|
||||
if (unix_fd == -1) {
|
||||
unix_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||
if (unix_fd < 0) {
|
||||
uwsgi_error("send_subscription()/socket()");
|
||||
return;
|
||||
}
|
||||
uwsgi_socket_nb(unix_fd);
|
||||
}
|
||||
fd = unix_fd;
|
||||
}
|
||||
}
|
||||
if (ret < 0) {
|
||||
uwsgi_error("send_subscription()/sendto()");
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, uint8_t modifier1, uint8_t modifier2, uint8_t cmd, char *socket_name, char *sign, char *sni_key, char *sni_crt, char *sni_ca) {
|
||||
|
||||
if (socket_name == NULL && !uwsgi.sockets)
|
||||
return;
|
||||
|
||||
if (!socket_name) {
|
||||
socket_name = uwsgi.sockets->name;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(4096);
|
||||
if (udp_port) {
|
||||
udp_port[0] = 0;
|
||||
memset(&udp_addr, 0, sizeof(struct sockaddr_in));
|
||||
udp_addr.sin_family = AF_INET;
|
||||
udp_addr.sin_port = htons(atoi(udp_port + 1));
|
||||
udp_addr.sin_addr.s_addr = inet_addr(host);
|
||||
ret = sendto(fd, message, message_size, 0, (struct sockaddr *) &udp_addr, sizeof(udp_addr));
|
||||
udp_port[0] = ':';
|
||||
}
|
||||
else {
|
||||
memset(&un_addr, 0, sizeof(struct sockaddr_un));
|
||||
un_addr.sun_family = AF_UNIX;
|
||||
// use 102 as the magic number
|
||||
strncat(un_addr.sun_path, host, 102);
|
||||
if (uwsgi.subscriptions_use_credentials) {
|
||||
// could be useless as internally the socket could add them automagically
|
||||
ret = uwsgi_pass_cred2(fd, message, message_size, (struct sockaddr *) &un_addr, sizeof(un_addr));
|
||||
}
|
||||
else {
|
||||
ret = sendto(fd, message, message_size, 0, (struct sockaddr *) &un_addr, sizeof(un_addr));
|
||||
}
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
uwsgi_error("send_subscription()/sendto()");
|
||||
}
|
||||
|
||||
if (sfd == -1)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static struct uwsgi_buffer *uwsgi_subscription_ub(char *key, size_t keysize, uint8_t modifier1, uint8_t modifier2, uint8_t cmd, char *socket_name, char *sign, char *sni_key, char *sni_crt, char *sni_ca) {
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(4096);
|
||||
|
||||
// make space for uwsgi header
|
||||
ub->pos = 4;
|
||||
|
||||
if (uwsgi_buffer_append_keyval(ub, "key", 3, key, keysize)) goto end;
|
||||
if (uwsgi_buffer_append_keyval(ub, "address", 7, socket_name, strlen(socket_name))) goto end;
|
||||
if (uwsgi_buffer_append_keynum(ub, "modifier1", 9, modifier1)) goto end;
|
||||
if (uwsgi_buffer_append_keynum(ub, "modifier2", 9, modifier2)) goto end;
|
||||
if (uwsgi_buffer_append_keynum(ub, "cores", 5, uwsgi.numproc * uwsgi.cores)) goto end;
|
||||
if (uwsgi_buffer_append_keynum(ub, "load", 4, uwsgi.shared->load)) goto end;
|
||||
if (uwsgi_buffer_append_keyval(ub, "key", 3, key, keysize))
|
||||
goto end;
|
||||
if (uwsgi_buffer_append_keyval(ub, "address", 7, socket_name, strlen(socket_name)))
|
||||
goto end;
|
||||
if (uwsgi_buffer_append_keynum(ub, "modifier1", 9, modifier1))
|
||||
goto end;
|
||||
if (uwsgi_buffer_append_keynum(ub, "modifier2", 9, modifier2))
|
||||
goto end;
|
||||
if (uwsgi_buffer_append_keynum(ub, "cores", 5, uwsgi.numproc * uwsgi.cores))
|
||||
goto end;
|
||||
if (uwsgi_buffer_append_keynum(ub, "load", 4, uwsgi.shared->load))
|
||||
goto end;
|
||||
if (uwsgi.auto_weight) {
|
||||
if (uwsgi_buffer_append_keynum(ub, "weight", 6, uwsgi.numproc * uwsgi.cores )) goto end;
|
||||
if (uwsgi_buffer_append_keynum(ub, "weight", 6, uwsgi.numproc * uwsgi.cores))
|
||||
goto end;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_buffer_append_keynum(ub, "weight", 6, uwsgi.weight )) goto end;
|
||||
if (uwsgi_buffer_append_keynum(ub, "weight", 6, uwsgi.weight))
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (sni_key) {
|
||||
if (uwsgi_buffer_append_keyval(ub, "sni_key", 7, sni_key, strlen(sni_key)))
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (sni_crt) {
|
||||
if (uwsgi_buffer_append_keyval(ub, "sni_crt", 7, sni_crt, strlen(sni_crt)))
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (sni_ca) {
|
||||
if (uwsgi_buffer_append_keyval(ub, "sni_ca", 6, sni_ca, strlen(sni_ca)))
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi.subscription_notify_socket) {
|
||||
if (uwsgi_buffer_append_keyval(ub, "notify", 6, uwsgi.subscription_notify_socket, strlen(uwsgi.subscription_notify_socket)))
|
||||
goto end;
|
||||
}
|
||||
else if (uwsgi.notify_socket_fd > -1 && uwsgi.notify_socket) {
|
||||
if (uwsgi_buffer_append_keyval(ub, "notify", 6, uwsgi.notify_socket, strlen(uwsgi.notify_socket)))
|
||||
goto end;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
if (sign) {
|
||||
if (uwsgi_buffer_append_keynum(ub, "unix", 4, (uwsgi_now() + (time_t) cmd) )) goto end;
|
||||
if (uwsgi_buffer_append_keynum(ub, "unix", 4, (uwsgi_now() + (time_t) cmd)))
|
||||
goto end;
|
||||
|
||||
unsigned int signature_len = 0;
|
||||
char *signature = uwsgi_rsa_sign(sign, ub->buf + 4, ub->pos - 4, &signature_len);
|
||||
@@ -692,29 +735,98 @@ void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, uint8
|
||||
}
|
||||
#endif
|
||||
|
||||
if (sni_key) {
|
||||
if (uwsgi_buffer_append_keyval(ub, "sni_key", 7, sni_key, strlen(sni_key))) goto end;
|
||||
}
|
||||
|
||||
if (sni_crt) {
|
||||
if (uwsgi_buffer_append_keyval(ub, "sni_crt", 7, sni_crt, strlen(sni_crt))) goto end;
|
||||
}
|
||||
|
||||
if (sni_ca) {
|
||||
if (uwsgi_buffer_append_keyval(ub, "sni_ca", 6, sni_ca, strlen(sni_ca))) goto end;
|
||||
}
|
||||
|
||||
// add uwsgi header
|
||||
if (uwsgi_buffer_set_uh(ub, 224, cmd)) goto end;
|
||||
if (uwsgi_buffer_set_uh(ub, 224, cmd))
|
||||
goto end;
|
||||
|
||||
return ub;
|
||||
|
||||
send_subscription(udp_address, ub->buf, ub->pos);
|
||||
end:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void uwsgi_send_subscription_from_fd(int fd, char *udp_address, char *key, size_t keysize, uint8_t modifier1, uint8_t modifier2, uint8_t cmd, char *socket_name, char *sign, char *sni_key, char *sni_crt, char *sni_ca) {
|
||||
|
||||
if (socket_name == NULL && !uwsgi.sockets)
|
||||
return;
|
||||
|
||||
if (!socket_name) {
|
||||
socket_name = uwsgi.sockets->name;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_subscription_ub(key, keysize, modifier1, modifier2, cmd, socket_name, sign, sni_key, sni_crt, sni_ca);
|
||||
|
||||
if (!ub)
|
||||
return;
|
||||
|
||||
send_subscription(fd, udp_address, ub->buf, ub->pos);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, uint8_t modifier1, uint8_t modifier2, uint8_t cmd, char *socket_name, char *sign, char *sni_key, char *sni_crt, char *sni_ca) {
|
||||
uwsgi_send_subscription_from_fd(-1, udp_address, key, keysize, modifier1, modifier2, cmd, socket_name, sign, sni_key, sni_crt, sni_ca);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
static int subscription_is_safe(struct uwsgi_subscribe_req *usr) {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.subscriptions_sign_skip_uid) {
|
||||
if (usl->custom == 0) {
|
||||
usl->custom = atoi(usl->value);
|
||||
}
|
||||
if (usr->uid > 0 && usr->uid == (uid_t) usl->custom) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int subscription_new_sign_ctx(struct uwsgi_subscribe_slot *slot, struct uwsgi_subscribe_req *usr) {
|
||||
if (subscription_is_safe(usr)) return 1;
|
||||
|
||||
if (usr->sign_len == 0 || usr->base_len == 0)
|
||||
return 0;
|
||||
|
||||
if (usr->unix_check < (uwsgi_now() - (time_t) uwsgi.subscriptions_sign_check_tolerance)) {
|
||||
uwsgi_log("[uwsgi-subscription for pid %d] invalid (sniffed ?) packet sent for slot: %.*s node: %.*s unix_check: %lu\n", (int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address, (unsigned long) usr->unix_check);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *keyfile = uwsgi_sanitize_cert_filename(uwsgi.subscriptions_sign_check_dir, usr->key, usr->keylen);
|
||||
FILE *kf = fopen(keyfile, "r");
|
||||
free(keyfile);
|
||||
if (!kf) return 0;
|
||||
slot->sign_public_key = PEM_read_PUBKEY(kf, NULL, NULL, NULL);
|
||||
fclose(kf);
|
||||
if (!slot->sign_public_key) {
|
||||
uwsgi_log("unable to load public key for %.*s\n", usr->keylen, usr->key);
|
||||
return 0;
|
||||
}
|
||||
slot->sign_ctx = EVP_MD_CTX_create();
|
||||
if (!slot->sign_ctx) {
|
||||
uwsgi_log("unable to initialize EVP context for %.*s\n", usr->keylen, usr->key);
|
||||
EVP_PKEY_free(slot->sign_public_key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!uwsgi_subscription_sign_check(slot, usr)) {
|
||||
EVP_PKEY_free(slot->sign_public_key);
|
||||
EVP_MD_CTX_destroy(slot->sign_ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
int uwsgi_subscription_sign_check(struct uwsgi_subscribe_slot *slot, struct uwsgi_subscribe_req *usr) {
|
||||
if (subscription_is_safe(usr)) return 1;
|
||||
|
||||
if (usr->sign_len == 0 || usr->base_len == 0)
|
||||
return 0;
|
||||
|
||||
if (!slot->sign_ctx) {
|
||||
if (!subscription_new_sign_ctx(slot, usr)) return 0;
|
||||
}
|
||||
|
||||
if (EVP_VerifyInit_ex(slot->sign_ctx, uwsgi.subscriptions_sign_check_md, NULL) == 0) {
|
||||
ERR_print_errors_fp(stderr);
|
||||
@@ -756,133 +868,133 @@ struct uwsgi_subscribe_slot **uwsgi_subscription_init_ht() {
|
||||
|
||||
void uwsgi_subscribe(char *subscription, uint8_t cmd) {
|
||||
|
||||
size_t subfile_size;
|
||||
size_t i;
|
||||
char *key = NULL;
|
||||
int keysize = 0;
|
||||
char *modifier1 = NULL;
|
||||
int modifier1_len = 0;
|
||||
char *socket_name = NULL;
|
||||
char *udp_address = subscription;
|
||||
char *udp_port = NULL;
|
||||
char *subscription_key = NULL;
|
||||
char *sign = NULL;
|
||||
size_t subfile_size;
|
||||
size_t i;
|
||||
char *key = NULL;
|
||||
int keysize = 0;
|
||||
char *modifier1 = NULL;
|
||||
int modifier1_len = 0;
|
||||
char *socket_name = NULL;
|
||||
char *udp_address = subscription;
|
||||
char *udp_port = NULL;
|
||||
char *subscription_key = NULL;
|
||||
char *sign = NULL;
|
||||
|
||||
// check for explicit socket_name
|
||||
char *equal = strchr(subscription, '=');
|
||||
if (equal) {
|
||||
socket_name = subscription;
|
||||
if (socket_name[0] == '=') {
|
||||
equal = strchr(socket_name + 1, '=');
|
||||
if (!equal)
|
||||
return;
|
||||
*equal = '\0';
|
||||
struct uwsgi_socket *us = uwsgi_get_shared_socket_by_num(atoi(socket_name + 1));
|
||||
if (!us)
|
||||
return;
|
||||
socket_name = us->name;
|
||||
}
|
||||
*equal = '\0';
|
||||
udp_address = equal + 1;
|
||||
}
|
||||
// check for explicit socket_name
|
||||
char *equal = strchr(subscription, '=');
|
||||
if (equal) {
|
||||
socket_name = subscription;
|
||||
if (socket_name[0] == '=') {
|
||||
equal = strchr(socket_name + 1, '=');
|
||||
if (!equal)
|
||||
return;
|
||||
*equal = '\0';
|
||||
struct uwsgi_socket *us = uwsgi_get_shared_socket_by_num(atoi(socket_name + 1));
|
||||
if (!us)
|
||||
return;
|
||||
socket_name = us->name;
|
||||
}
|
||||
*equal = '\0';
|
||||
udp_address = equal + 1;
|
||||
}
|
||||
|
||||
// check for unix socket
|
||||
if (udp_address[0] != '/') {
|
||||
udp_port = strchr(udp_address, ':');
|
||||
if (!udp_port) {
|
||||
if (equal)
|
||||
*equal = '=';
|
||||
return;
|
||||
}
|
||||
subscription_key = strchr(udp_port + 1, ':');
|
||||
}
|
||||
else {
|
||||
subscription_key = strchr(udp_address + 1, ':');
|
||||
}
|
||||
// check for unix socket
|
||||
if (udp_address[0] != '/') {
|
||||
udp_port = strchr(udp_address, ':');
|
||||
if (!udp_port) {
|
||||
if (equal)
|
||||
*equal = '=';
|
||||
return;
|
||||
}
|
||||
subscription_key = strchr(udp_port + 1, ':');
|
||||
}
|
||||
else {
|
||||
subscription_key = strchr(udp_address + 1, ':');
|
||||
}
|
||||
|
||||
if (!subscription_key) {
|
||||
if (equal)
|
||||
*equal = '=';
|
||||
return;
|
||||
}
|
||||
if (!subscription_key) {
|
||||
if (equal)
|
||||
*equal = '=';
|
||||
return;
|
||||
}
|
||||
|
||||
udp_address = uwsgi_concat2n(udp_address, subscription_key - udp_address, "", 0);
|
||||
udp_address = uwsgi_concat2n(udp_address, subscription_key - udp_address, "", 0);
|
||||
|
||||
if (subscription_key[1] == '@') {
|
||||
if (!uwsgi_file_exists(subscription_key + 2))
|
||||
goto clear;
|
||||
char *lines = uwsgi_open_and_read(subscription_key + 2, &subfile_size, 1, NULL);
|
||||
if (subfile_size > 0) {
|
||||
key = lines;
|
||||
for (i = 0; i < subfile_size; i++) {
|
||||
if (lines[i] == 0) {
|
||||
if (keysize > 0) {
|
||||
if (key[0] != '#' && key[0] != '\n') {
|
||||
modifier1 = strchr(key, ',');
|
||||
if (modifier1) {
|
||||
modifier1[0] = 0;
|
||||
modifier1++;
|
||||
modifier1_len = strlen(modifier1);
|
||||
keysize = strlen(key);
|
||||
}
|
||||
uwsgi_send_subscription(udp_address, key, keysize, uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign, NULL, NULL, NULL);
|
||||
modifier1 = NULL;
|
||||
modifier1_len = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (lines[i] == '\n') {
|
||||
if (keysize > 0) {
|
||||
if (key[0] != '#' && key[0] != '\n') {
|
||||
lines[i] = 0;
|
||||
modifier1 = strchr(key, ',');
|
||||
if (modifier1) {
|
||||
modifier1[0] = 0;
|
||||
modifier1++;
|
||||
modifier1_len = strlen(modifier1);
|
||||
keysize = strlen(key);
|
||||
}
|
||||
uwsgi_send_subscription(udp_address, key, keysize, uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign, NULL, NULL, NULL);
|
||||
modifier1 = NULL;
|
||||
modifier1_len = 0;
|
||||
lines[i] = '\n';
|
||||
}
|
||||
}
|
||||
key = lines + i + 1;
|
||||
keysize = 0;
|
||||
continue;
|
||||
}
|
||||
keysize++;
|
||||
}
|
||||
}
|
||||
free(lines);
|
||||
}
|
||||
else {
|
||||
modifier1 = strchr(subscription_key + 1, ',');
|
||||
if (modifier1) {
|
||||
modifier1[0] = 0;
|
||||
modifier1++;
|
||||
if (!uwsgi_file_exists(subscription_key + 2))
|
||||
goto clear;
|
||||
char *lines = uwsgi_open_and_read(subscription_key + 2, &subfile_size, 1, NULL);
|
||||
if (subfile_size > 0) {
|
||||
key = lines;
|
||||
for (i = 0; i < subfile_size; i++) {
|
||||
if (lines[i] == 0) {
|
||||
if (keysize > 0) {
|
||||
if (key[0] != '#' && key[0] != '\n') {
|
||||
modifier1 = strchr(key, ',');
|
||||
if (modifier1) {
|
||||
modifier1[0] = 0;
|
||||
modifier1++;
|
||||
modifier1_len = strlen(modifier1);
|
||||
keysize = strlen(key);
|
||||
}
|
||||
uwsgi_send_subscription(udp_address, key, keysize, uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign, NULL, NULL, NULL);
|
||||
modifier1 = NULL;
|
||||
modifier1_len = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (lines[i] == '\n') {
|
||||
if (keysize > 0) {
|
||||
if (key[0] != '#' && key[0] != '\n') {
|
||||
lines[i] = 0;
|
||||
modifier1 = strchr(key, ',');
|
||||
if (modifier1) {
|
||||
modifier1[0] = 0;
|
||||
modifier1++;
|
||||
modifier1_len = strlen(modifier1);
|
||||
keysize = strlen(key);
|
||||
}
|
||||
uwsgi_send_subscription(udp_address, key, keysize, uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign, NULL, NULL, NULL);
|
||||
modifier1 = NULL;
|
||||
modifier1_len = 0;
|
||||
lines[i] = '\n';
|
||||
}
|
||||
}
|
||||
key = lines + i + 1;
|
||||
keysize = 0;
|
||||
continue;
|
||||
}
|
||||
keysize++;
|
||||
}
|
||||
}
|
||||
free(lines);
|
||||
}
|
||||
else {
|
||||
modifier1 = strchr(subscription_key + 1, ',');
|
||||
if (modifier1) {
|
||||
modifier1[0] = 0;
|
||||
modifier1++;
|
||||
|
||||
sign = strchr(modifier1 + 1, ',');
|
||||
if (sign) {
|
||||
*sign = 0;
|
||||
sign++;
|
||||
}
|
||||
modifier1_len = strlen(modifier1);
|
||||
}
|
||||
sign = strchr(modifier1 + 1, ',');
|
||||
if (sign) {
|
||||
*sign = 0;
|
||||
sign++;
|
||||
}
|
||||
modifier1_len = strlen(modifier1);
|
||||
}
|
||||
|
||||
uwsgi_send_subscription(udp_address, subscription_key + 1, strlen(subscription_key + 1), uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign, NULL, NULL, NULL);
|
||||
if (modifier1)
|
||||
modifier1[-1] = ',';
|
||||
if (sign)
|
||||
sign[-1] = ',';
|
||||
}
|
||||
uwsgi_send_subscription(udp_address, subscription_key + 1, strlen(subscription_key + 1), uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign, NULL, NULL, NULL);
|
||||
if (modifier1)
|
||||
modifier1[-1] = ',';
|
||||
if (sign)
|
||||
sign[-1] = ',';
|
||||
}
|
||||
|
||||
clear:
|
||||
if (equal)
|
||||
*equal = '=';
|
||||
free(udp_address);
|
||||
if (equal)
|
||||
*equal = '=';
|
||||
free(udp_address);
|
||||
|
||||
}
|
||||
|
||||
@@ -901,27 +1013,16 @@ void uwsgi_subscribe2(char *arg, uint8_t cmd) {
|
||||
char *s2_sni_crt = NULL;
|
||||
char *s2_sni_ca = NULL;
|
||||
|
||||
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
|
||||
"server", &s2_server,
|
||||
"key", &s2_key,
|
||||
"socket", &s2_socket,
|
||||
"addr", &s2_addr,
|
||||
"weight", &s2_weight,
|
||||
"modifier1", &s2_modifier1,
|
||||
"modifier2", &s2_modifier2,
|
||||
"sign", &s2_sign,
|
||||
"check", &s2_check,
|
||||
"sni_key", &s2_sni_key,
|
||||
"sni_crt", &s2_sni_crt,
|
||||
"sni_ca", &s2_sni_ca,
|
||||
NULL)) {
|
||||
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=', "server", &s2_server, "key", &s2_key, "socket", &s2_socket, "addr", &s2_addr, "weight", &s2_weight, "modifier1", &s2_modifier1, "modifier2", &s2_modifier2, "sign", &s2_sign, "check", &s2_check, "sni_key", &s2_sni_key, "sni_crt", &s2_sni_crt, "sni_ca", &s2_sni_ca, NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!s2_server || !s2_key) goto end;
|
||||
if (!s2_server || !s2_key)
|
||||
goto end;
|
||||
|
||||
if (s2_check) {
|
||||
if (uwsgi_file_exists(s2_check)) goto end;
|
||||
if (uwsgi_file_exists(s2_check))
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (s2_weight) {
|
||||
@@ -951,39 +1052,48 @@ void uwsgi_subscribe2(char *arg, uint8_t cmd) {
|
||||
|
||||
uwsgi_send_subscription(s2_server, s2_key, strlen(s2_key), modifier1, modifier2, cmd, s2_addr, s2_sign, s2_sni_key, s2_sni_crt, s2_sni_ca);
|
||||
end:
|
||||
if (s2_server) free(s2_server);
|
||||
if (s2_key) free(s2_key);
|
||||
if (s2_socket) free(s2_socket);
|
||||
if (s2_addr) free(s2_addr);
|
||||
if (s2_weight) free(s2_weight);
|
||||
if (s2_modifier1) free(s2_modifier1);
|
||||
if (s2_modifier2) free(s2_modifier2);
|
||||
if (s2_sign) free(s2_sign);
|
||||
if (s2_check) free(s2_check);
|
||||
if (s2_server)
|
||||
free(s2_server);
|
||||
if (s2_key)
|
||||
free(s2_key);
|
||||
if (s2_socket)
|
||||
free(s2_socket);
|
||||
if (s2_addr)
|
||||
free(s2_addr);
|
||||
if (s2_weight)
|
||||
free(s2_weight);
|
||||
if (s2_modifier1)
|
||||
free(s2_modifier1);
|
||||
if (s2_modifier2)
|
||||
free(s2_modifier2);
|
||||
if (s2_sign)
|
||||
free(s2_sign);
|
||||
if (s2_check)
|
||||
free(s2_check);
|
||||
}
|
||||
|
||||
void uwsgi_subscribe_all(uint8_t cmd, int verbose) {
|
||||
|
||||
if (uwsgi.subscriptions_blocked) return;
|
||||
if (uwsgi.subscriptions_blocked)
|
||||
return;
|
||||
// -- subscribe
|
||||
struct uwsgi_string_list *subscriptions = uwsgi.subscriptions;
|
||||
while (subscriptions) {
|
||||
while (subscriptions) {
|
||||
if (verbose) {
|
||||
uwsgi_log("%s %s\n", cmd ? "unsubscribing from" : "subscribing to", subscriptions->value);
|
||||
uwsgi_log("%s %s\n", cmd ? "unsubscribing from" : "subscribing to", subscriptions->value);
|
||||
}
|
||||
uwsgi_subscribe(subscriptions->value, cmd);
|
||||
subscriptions = subscriptions->next;
|
||||
}
|
||||
uwsgi_subscribe(subscriptions->value, cmd);
|
||||
subscriptions = subscriptions->next;
|
||||
}
|
||||
|
||||
// --subscribe2
|
||||
subscriptions = uwsgi.subscriptions2;
|
||||
while (subscriptions) {
|
||||
if (verbose) {
|
||||
uwsgi_log("%s %s\n", cmd ? "unsubscribing from" : "subscribing to", subscriptions->value);
|
||||
}
|
||||
uwsgi_subscribe2(subscriptions->value, cmd);
|
||||
subscriptions = subscriptions->next;
|
||||
}
|
||||
while (subscriptions) {
|
||||
if (verbose) {
|
||||
uwsgi_log("%s %s\n", cmd ? "unsubscribing from" : "subscribing to", subscriptions->value);
|
||||
}
|
||||
uwsgi_subscribe2(subscriptions->value, cmd);
|
||||
subscriptions = subscriptions->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
+17
-4
@@ -754,7 +754,11 @@ void uwsgi_as_root() {
|
||||
}
|
||||
|
||||
if (uwsgi.logfile_chown) {
|
||||
if (fchown(2, uwsgi.uid, uwsgi.gid)) {
|
||||
int log_fd = 2;
|
||||
if (uwsgi.log_master && uwsgi.original_log_fd > -1) {
|
||||
log_fd = uwsgi.original_log_fd;
|
||||
}
|
||||
if (fchown(log_fd, uwsgi.uid, uwsgi.gid)) {
|
||||
uwsgi_error("fchown()");
|
||||
exit(1);
|
||||
}
|
||||
@@ -1432,7 +1436,7 @@ void uwsgi_heartbeat() {
|
||||
return;
|
||||
|
||||
time_t now = uwsgi_now();
|
||||
if (uwsgi.next_heartbeat < now) {
|
||||
if (uwsgi.next_heartbeat <= now) {
|
||||
char byte = 26;
|
||||
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
@@ -1456,7 +1460,15 @@ int wsgi_req_accept(int queue, struct wsgi_request *wsgi_req) {
|
||||
// heartbeat
|
||||
// in multithreaded mode we are now locked
|
||||
if (uwsgi.has_emperor && uwsgi.heartbeat) {
|
||||
time_t now = uwsgi_now();
|
||||
// overengineering ... (reduce skew problems)
|
||||
timeout = uwsgi.heartbeat;
|
||||
if (!uwsgi.next_heartbeat) {
|
||||
uwsgi.next_heartbeat = now;
|
||||
}
|
||||
if (uwsgi.next_heartbeat >= now) {
|
||||
timeout = uwsgi.next_heartbeat - now;
|
||||
}
|
||||
}
|
||||
|
||||
// need edge trigger ?
|
||||
@@ -1479,7 +1491,7 @@ int wsgi_req_accept(int queue, struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
// check for heartbeat
|
||||
if (timeout > 0) {
|
||||
if (uwsgi.has_emperor && uwsgi.heartbeat) {
|
||||
uwsgi_heartbeat();
|
||||
// no need to continue if timed-out
|
||||
if (ret == 0) {
|
||||
@@ -4182,7 +4194,8 @@ char *uwsgi_str_to_hex(char *src, size_t slen) {
|
||||
char *ptr = dst;
|
||||
size_t i;
|
||||
for (i = 0; i < slen; i++) {
|
||||
memcpy(ptr, uwsgi_hex_table[(int) src[i]], 2);
|
||||
uint8_t pos = (uint8_t) src[i];
|
||||
memcpy(ptr, uwsgi_hex_table[pos], 2);
|
||||
ptr += 2;
|
||||
}
|
||||
return dst;
|
||||
|
||||
+55
-2
@@ -2,7 +2,7 @@
|
||||
|
||||
*** uWSGI ***
|
||||
|
||||
Copyright (C) 2009-2013 Unbit S.a.s. <info@unbit.it>
|
||||
Copyright (C) 2009-2014 Unbit S.a.s. <info@unbit.it>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
@@ -104,6 +104,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},
|
||||
{"for-readline", required_argument, 0, "(opt logic) for cycle (expand the specified file to a list of lines)", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for_readline, 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},
|
||||
|
||||
@@ -150,6 +151,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
|
||||
{"inherit", required_argument, 0, "use the specified file as config template", uwsgi_opt_load, NULL, 0},
|
||||
{"include", required_argument, 0, "include the specified file as immediate configuration", uwsgi_opt_load, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"inject-before", required_argument, 0, "inject a text file before the config file (advanced templating)", uwsgi_opt_add_string_list, &uwsgi.inject_before, UWSGI_OPT_IMMEDIATE},
|
||||
{"inject-after", required_argument, 0, "inject a text file after the config file (advanced templating)", uwsgi_opt_add_string_list, &uwsgi.inject_after, UWSGI_OPT_IMMEDIATE},
|
||||
{"daemonize", required_argument, 'd', "daemonize uWSGI", uwsgi_opt_set_str, &uwsgi.daemonize, 0},
|
||||
{"daemonize2", required_argument, 0, "daemonize uWSGI after app loading", uwsgi_opt_set_str, &uwsgi.daemonize2, 0},
|
||||
{"stop", required_argument, 0, "stop an instance", uwsgi_opt_pidfile_signal, (void *) SIGINT, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -299,6 +302,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"spooler-quiet", no_argument, 0, "do not be verbose with spooler tasks", uwsgi_opt_true, &uwsgi.spooler_quiet, 0},
|
||||
{"spooler-max-tasks", required_argument, 0, "set the maximum number of tasks to run before recycling a spooler", uwsgi_opt_set_int, &uwsgi.spooler_max_tasks, 0},
|
||||
{"spooler-harakiri", required_argument, 0, "set harakiri timeout for spooler tasks", uwsgi_opt_set_int, &uwsgi.harakiri_options.spoolers, 0},
|
||||
{"spooler-frequency", required_argument, 0, "set spooler frequency", uwsgi_opt_set_int, &uwsgi.spooler_frequency, 0},
|
||||
{"spooler-freq", required_argument, 0, "set spooler frequency", uwsgi_opt_set_int, &uwsgi.spooler_frequency, 0},
|
||||
|
||||
{"mule", optional_argument, 0, "add a mule", uwsgi_opt_add_mule, NULL, UWSGI_OPT_MASTER},
|
||||
{"mules", required_argument, 0, "add the specified number of mules", uwsgi_opt_add_mules, NULL, UWSGI_OPT_MASTER},
|
||||
@@ -385,6 +390,11 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"hook-accepting-once", required_argument, 0, "run the specified hook after each worker enter the accepting phase (once per-instance)", uwsgi_opt_add_string_list, &uwsgi.hook_accepting_once, 0},
|
||||
{"hook-accepting1-once", required_argument, 0, "run the specified hook after the first worker enters the accepting phase (once per instance)", uwsgi_opt_add_string_list, &uwsgi.hook_accepting1_once, 0},
|
||||
|
||||
{"hook-master-start", required_argument, 0, "run the specified hook when the Master starts", uwsgi_opt_add_string_list, &uwsgi.hook_master_start, 0},
|
||||
|
||||
{"hook-touch", required_argument, 0, "run the specified hook when the specified file is touched (syntax: <file> <action>)", uwsgi_opt_add_string_list, &uwsgi.hook_touch, 0},
|
||||
|
||||
{"hook-emperor-start", required_argument, 0, "run the specified hook when the Emperor starts", uwsgi_opt_add_string_list, &uwsgi.hook_emperor_start, 0},
|
||||
{"hook-emperor-stop", required_argument, 0, "run the specified hook when the Emperor send a stop message", uwsgi_opt_add_string_list, &uwsgi.hook_emperor_stop, 0},
|
||||
{"hook-emperor-reload", required_argument, 0, "run the specified hook when the Emperor send a reload message", uwsgi_opt_add_string_list, &uwsgi.hook_emperor_reload, 0},
|
||||
{"hook-emperor-lost", required_argument, 0, "run the specified hook when the Emperor connection is lost", uwsgi_opt_add_string_list, &uwsgi.hook_emperor_lost, 0},
|
||||
@@ -394,6 +404,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
|
||||
{"hook-as-mule", required_argument, 0, "run the specified hook in each mule", uwsgi_opt_add_string_list, &uwsgi.hook_as_mule, 0},
|
||||
|
||||
{"hook-as-gateway", required_argument, 0, "run the specified hook in each gateway", uwsgi_opt_add_string_list, &uwsgi.hook_as_gateway, 0},
|
||||
|
||||
{"after-request-hook", required_argument, 0, "run the specified function/symbol after each request", uwsgi_opt_add_string_list, &uwsgi.after_request_hooks, 0},
|
||||
{"after-request-call", required_argument, 0, "run the specified function/symbol after each request", uwsgi_opt_add_string_list, &uwsgi.after_request_hooks, 0},
|
||||
|
||||
@@ -543,6 +555,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"metric", required_argument, 0, "add a custom metric", uwsgi_opt_add_string_list, &uwsgi.additional_metrics, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
{"metric-threshold", required_argument, 0, "add a metric threshold/alarm", uwsgi_opt_add_string_list, &uwsgi.metrics_threshold, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
{"metric-alarm", required_argument, 0, "add a metric threshold/alarm", uwsgi_opt_add_string_list, &uwsgi.metrics_threshold, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
{"alarm-metric", required_argument, 0, "add a metric threshold/alarm", uwsgi_opt_add_string_list, &uwsgi.metrics_threshold, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
{"metrics-dir", required_argument, 0, "export metrics as text files to the specified directory", uwsgi_opt_set_str, &uwsgi.metrics_dir, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
{"metrics-dir-restore", no_argument, 0, "restore last value taken from the metrics dir", uwsgi_opt_true, &uwsgi.metrics_dir_restore, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
{"metric-dir", required_argument, 0, "export metrics as text files to the specified directory", uwsgi_opt_set_str, &uwsgi.metrics_dir, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
@@ -563,12 +576,16 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
|
||||
{"master-fifo", required_argument, 0, "enable the master fifo", uwsgi_opt_add_string_list, &uwsgi.master_fifo, UWSGI_OPT_MASTER},
|
||||
|
||||
{"notify-socket", required_argument, 0, "enable the notification socket", uwsgi_opt_set_str, &uwsgi.notify_socket, UWSGI_OPT_MASTER},
|
||||
{"subscription-notify-socket", required_argument, 0, "set the notification socket for subscriptions", uwsgi_opt_set_str, &uwsgi.subscription_notify_socket, UWSGI_OPT_MASTER},
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
{"legion", required_argument, 0, "became a member of a legion", uwsgi_opt_legion, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-mcast", required_argument, 0, "became a member of a legion (shortcut for multicast)", uwsgi_opt_legion_mcast, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-node", required_argument, 0, "add a node to a legion", uwsgi_opt_legion_node, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-freq", required_argument, 0, "set the frequency of legion packets", uwsgi_opt_set_int, &uwsgi.legion_freq, UWSGI_OPT_MASTER},
|
||||
{"legion-tolerance", required_argument, 0, "set the tolerance of legion subsystem", uwsgi_opt_set_int, &uwsgi.legion_tolerance, UWSGI_OPT_MASTER},
|
||||
{"legion-death-on-lord-error", required_argument, 0, "declare itself as a dead node for the specified amount of seconds if one of the lord hooks fails", uwsgi_opt_set_int, &uwsgi.legion_death_on_lord_error, UWSGI_OPT_MASTER},
|
||||
{"legion-skew-tolerance", required_argument, 0, "set the clock skew tolerance of legion subsystem (default 30 seconds)", uwsgi_opt_set_int, &uwsgi.legion_skew_tolerance, UWSGI_OPT_MASTER},
|
||||
{"legion-lord", required_argument, 0, "action to call on Lord election", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-unlord", required_argument, 0, "action to call on Lord dismiss", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
|
||||
@@ -583,6 +600,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"legion-scroll-list-max-size", required_argument, 0, "set max size of legion scroll list buffer", uwsgi_opt_set_64bit, &uwsgi.legion_scroll_list_max_size, 0},
|
||||
{"subscriptions-sign-check", required_argument, 0, "set digest algorithm and certificate directory for secured subscription system", uwsgi_opt_scd, NULL, UWSGI_OPT_MASTER},
|
||||
{"subscriptions-sign-check-tolerance", required_argument, 0, "set the maximum tolerance (in seconds) of clock skew for secured subscription system", uwsgi_opt_set_int, &uwsgi.subscriptions_sign_check_tolerance, UWSGI_OPT_MASTER},
|
||||
{"subscriptions-sign-skip-uid", required_argument, 0, "skip signature check for the specified uid when using unix sockets credentials", uwsgi_opt_add_string_list, &uwsgi.subscriptions_sign_skip_uid, UWSGI_OPT_MASTER},
|
||||
#endif
|
||||
{"subscriptions-credentials-check", required_argument, 0, "add a directory to search for subscriptions key credentials", uwsgi_opt_add_string_list, &uwsgi.subscriptions_credentials_check_dir, UWSGI_OPT_MASTER},
|
||||
{"subscriptions-use-credentials", no_argument, 0, "enable management of SCM_CREDENTIALS in subscriptions UNIX sockets", uwsgi_opt_true, &uwsgi.subscriptions_use_credentials, 0},
|
||||
@@ -595,6 +613,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"subscribe-freq", required_argument, 0, "send subscription announce at the specified interval", uwsgi_opt_set_int, &uwsgi.subscribe_freq, 0},
|
||||
{"subscription-tolerance", required_argument, 0, "set tolerance for subscription servers", uwsgi_opt_set_int, &uwsgi.subscription_tolerance, 0},
|
||||
{"unsubscribe-on-graceful-reload", no_argument, 0, "force unsubscribe request even during graceful reload", uwsgi_opt_true, &uwsgi.unsubscribe_on_graceful_reload, 0},
|
||||
{"start-unsubscribed", no_argument, 0, "configure subscriptions but do not send them (useful with master fifo)", uwsgi_opt_true, &uwsgi.subscriptions_blocked, 0},
|
||||
{"snmp", optional_argument, 0, "enable the embedded snmp server", uwsgi_opt_snmp, NULL, 0},
|
||||
{"snmp-community", required_argument, 0, "set the snmp community string", uwsgi_opt_snmp_community, NULL, 0},
|
||||
#ifdef UWSGI_SSL
|
||||
@@ -610,6 +629,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
#ifdef UWSGI_PCRE
|
||||
{"sni-regexp", required_argument, 0, "add an SNI-governed SSL context (the key is a regexp)", uwsgi_opt_sni, NULL, 0},
|
||||
#endif
|
||||
{"ssl-tmp-dir", required_argument, 0, "store ssl-related temp files in the specified directory", uwsgi_opt_set_str, &uwsgi.ssl_tmp_dir, 0},
|
||||
#endif
|
||||
{"check-interval", required_argument, 0, "set the interval (in seconds) of master checks", uwsgi_opt_set_int, &uwsgi.master_interval, UWSGI_OPT_MASTER},
|
||||
{"forkbomb-delay", required_argument, 0, "sleep for the specified number of seconds when a forkbomb is detected", uwsgi_opt_set_int, &uwsgi.forkbomb_delay, UWSGI_OPT_MASTER},
|
||||
@@ -656,6 +676,12 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"alarm-fd", required_argument, 0, "raise the specified alarm when an fd is read for read (by default it reads 1 byte, set 8 for eventfd)", uwsgi_opt_add_string_list, &uwsgi.alarm_fd_list, UWSGI_OPT_MASTER},
|
||||
{"alarm-segfault", required_argument, 0, "raise the specified alarm when the segmentation fault handler is executed", uwsgi_opt_add_string_list, &uwsgi.alarm_segfault, UWSGI_OPT_MASTER},
|
||||
{"segfault-alarm", required_argument, 0, "raise the specified alarm when the segmentation fault handler is executed", uwsgi_opt_add_string_list, &uwsgi.alarm_segfault, UWSGI_OPT_MASTER},
|
||||
{"alarm-backlog", required_argument, 0, "raise the specified alarm when the socket backlog queue is full", uwsgi_opt_add_string_list, &uwsgi.alarm_backlog, UWSGI_OPT_MASTER},
|
||||
{"backlog-alarm", required_argument, 0, "raise the specified alarm when the socket backlog queue is full", uwsgi_opt_add_string_list, &uwsgi.alarm_backlog, UWSGI_OPT_MASTER},
|
||||
{"lq-alarm", required_argument, 0, "raise the specified alarm when the socket backlog queue is full", uwsgi_opt_add_string_list, &uwsgi.alarm_backlog, UWSGI_OPT_MASTER},
|
||||
{"alarm-lq", required_argument, 0, "raise the specified alarm when the socket backlog queue is full", uwsgi_opt_add_string_list, &uwsgi.alarm_backlog, UWSGI_OPT_MASTER},
|
||||
{"alarm-listen-queue", required_argument, 0, "raise the specified alarm when the socket backlog queue is full", uwsgi_opt_add_string_list, &uwsgi.alarm_backlog, UWSGI_OPT_MASTER},
|
||||
{"listen-queue-alarm", required_argument, 0, "raise the specified alarm when the socket backlog queue is full", uwsgi_opt_add_string_list, &uwsgi.alarm_backlog, UWSGI_OPT_MASTER},
|
||||
#ifdef UWSGI_PCRE
|
||||
{"log-alarm", required_argument, 0, "raise the specified alarm when a log line matches the specified regexp, syntax: <alarm>[,alarm...] <regexp>", uwsgi_opt_add_string_list, &uwsgi.alarm_logs_list, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
{"alarm-log", required_argument, 0, "raise the specified alarm when a log line matches the specified regexp, syntax: <alarm>[,alarm...] <regexp>", uwsgi_opt_add_string_list, &uwsgi.alarm_logs_list, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
@@ -861,7 +887,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"disable-sendfile", no_argument, 0, "disable sendfile() and rely on boring read()/write()", uwsgi_opt_true, &uwsgi.disable_sendfile, 0},
|
||||
|
||||
{"check-cache", optional_argument, 0, "check for response data in the specified cache (empty for default cache)", uwsgi_opt_set_str, &uwsgi.use_check_cache, 0},
|
||||
{"close-on-exec", no_argument, 0, "set close-on-exec on sockets (could be required for spawning processes in requests)", uwsgi_opt_true, &uwsgi.close_on_exec, 0},
|
||||
{"close-on-exec", no_argument, 0, "set close-on-exec on connection sockets (could be required for spawning processes in requests)", uwsgi_opt_true, &uwsgi.close_on_exec, 0},
|
||||
{"close-on-exec2", no_argument, 0, "set close-on-exec on server sockets (could be required for spawning processes in requests)", uwsgi_opt_true, &uwsgi.close_on_exec2, 0},
|
||||
{"mode", required_argument, 0, "set uWSGI custom mode", uwsgi_opt_set_str, &uwsgi.mode, 0},
|
||||
{"env", required_argument, 0, "set environment variable", uwsgi_opt_set_env, NULL, 0},
|
||||
{"envdir", required_argument, 0, "load a daemontools compatible envdir", uwsgi_opt_add_string_list, &uwsgi.envdirs, 0},
|
||||
@@ -999,6 +1026,17 @@ void config_magic_table_fill(char *filename, char **magic_table) {
|
||||
magic_table['b'] = uwsgi.binary_path;
|
||||
magic_table['p'] = fullname;
|
||||
|
||||
// compute filename hash
|
||||
uint32_t hash = djb33x_hash(magic_table['p'], strlen(magic_table['p']));
|
||||
char *hex = uwsgi_str_to_hex((char *)&hash, 4);
|
||||
magic_table['j'] = uwsgi_concat2n(hex, 8, "", 0);
|
||||
free(hex);
|
||||
|
||||
struct stat st;
|
||||
if (!lstat(fullname, &st)) {
|
||||
magic_table['i'] = uwsgi_num2str(st.st_ino);
|
||||
}
|
||||
|
||||
magic_table['s'] = uwsgi_get_last_char(fullname, '/') + 1;
|
||||
|
||||
magic_table['d'] = uwsgi_concat2n(magic_table['p'], magic_table['s'] - magic_table['p'], "", 0);
|
||||
@@ -1071,6 +1109,8 @@ reuse:
|
||||
magic_table['E'] = magic_table['e'];
|
||||
magic_table['N'] = magic_table['n'];
|
||||
magic_table['X'] = magic_table['x'];
|
||||
magic_table['I'] = magic_table['i'];
|
||||
magic_table['J'] = magic_table['j'];
|
||||
uwsgi.magic_table_first_round = 1;
|
||||
}
|
||||
|
||||
@@ -2733,6 +2773,9 @@ int uwsgi_start(void *v_argv) {
|
||||
!uwsgi.daemons_cnt &&
|
||||
!uwsgi.crons &&
|
||||
!uwsgi.emperor_proxy
|
||||
#ifdef __linux__
|
||||
&& !uwsgi.setns_socket
|
||||
#endif
|
||||
#ifdef UWSGI_SSL
|
||||
&& !uwsgi.legions
|
||||
#endif
|
||||
@@ -3109,6 +3152,16 @@ int uwsgi_run() {
|
||||
//from now on the process is a real worker
|
||||
}
|
||||
|
||||
#if defined(__linux__) && defined(PR_SET_PDEATHSIG)
|
||||
// avoid workers running without master at all costs !!! (dangerous)
|
||||
if (uwsgi.master_process && uwsgi.no_orphans) {
|
||||
if (prctl(PR_SET_PDEATHSIG, SIGKILL)) {
|
||||
uwsgi_error("uwsgi_run()/prctl()");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// eventually maps (or disable) sockets for the worker
|
||||
uwsgi_map_sockets();
|
||||
|
||||
|
||||
+68
-28
@@ -186,13 +186,18 @@ static int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len)
|
||||
size_t header_size = 0;
|
||||
int status_sent = 0;
|
||||
|
||||
// Search for Status/Location headers
|
||||
for(i=0;i<len;i++) {
|
||||
// end of a line
|
||||
if (buf[i] == '\n') {
|
||||
// end of headers
|
||||
if (key == NULL) {
|
||||
i++;
|
||||
goto send_body;
|
||||
// Default status
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("setting default Status header\n");
|
||||
#endif
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return -1;
|
||||
break;
|
||||
}
|
||||
// invalid header
|
||||
else if (value == NULL) {
|
||||
@@ -206,37 +211,72 @@ static int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len)
|
||||
}
|
||||
}
|
||||
|
||||
if (header_size >= 11) {
|
||||
// "Status: NNN"
|
||||
if (!strncasecmp("Status: ", key, 8)) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("found Status header: %.*s\n", header_size, key);
|
||||
#endif
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, key+8, header_size - 8)) return -1;
|
||||
break;
|
||||
}
|
||||
// Location: X
|
||||
if (!strncasecmp("Location: ", key, 10)) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("found Location header: %.*s\n", header_size, key);
|
||||
#endif
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "302 Found", 9)) return -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
key = NULL;
|
||||
value = NULL;
|
||||
}
|
||||
else if (buf[i] == ':') {
|
||||
value = buf+i;
|
||||
}
|
||||
else if (buf[i] != '\r') {
|
||||
if (key == NULL) {
|
||||
key = buf + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
key = buf;
|
||||
value = NULL;
|
||||
|
||||
for(i=0;i<len;i++) {
|
||||
// end of a line
|
||||
if (buf[i] == '\n') {
|
||||
// end of headers
|
||||
if (key == NULL) {
|
||||
i++;
|
||||
goto send_body;
|
||||
}
|
||||
// invalid header
|
||||
else if (value == NULL) {
|
||||
return -1;
|
||||
}
|
||||
header_size = (buf+i) - key;
|
||||
// security check
|
||||
if (buf+i > buf) {
|
||||
if ((buf[i-1]) == '\r') {
|
||||
header_size--;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("found CGI header: %.*s\n", header_size, key);
|
||||
#endif
|
||||
|
||||
if (status_sent == 0) {
|
||||
// "Status: NNN"
|
||||
if (header_size >= 11) {
|
||||
if (!strncasecmp("Status: ", key, 8)) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, key+8, header_size - 8)) return -1;
|
||||
status_sent = 1;
|
||||
key = NULL;
|
||||
value = NULL;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// default status
|
||||
if (status_sent == 0) {
|
||||
|
||||
// Location: X
|
||||
if (header_size >= 11) {
|
||||
if (!strncasecmp("Location: ", key, 10)) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "302 Found", 9)) return -1;
|
||||
status_sent = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (status_sent == 0) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return -1;
|
||||
// Ignore "Status: NNN" header
|
||||
if (status_sent == 0 && header_size >= 11) {
|
||||
if (!strncasecmp("Status: ", key, 8)) {
|
||||
status_sent = 1;
|
||||
key = NULL;
|
||||
value = NULL;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -201,9 +201,11 @@ int cheaper_busyness_algo(int can_spawn) {
|
||||
}
|
||||
|
||||
avg_busyness = (active_workers ? total_busyness / active_workers : 0);
|
||||
uwsgi_wlock(uwsgi.metrics_lock);
|
||||
uwsgi_cheaper_busyness_global.total_avg_busyness = avg_busyness;
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
if (uwsgi.has_metrics) {
|
||||
uwsgi_wlock(uwsgi.metrics_lock);
|
||||
uwsgi_cheaper_busyness_global.total_avg_busyness = avg_busyness;
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
}
|
||||
|
||||
if (uwsgi_cheaper_busyness_global.verbose)
|
||||
uwsgi_log("[busyness] %ds average busyness of %d worker(s) is at %d%%\n",
|
||||
|
||||
@@ -41,7 +41,9 @@ struct corerouter_peer *uwsgi_cr_peer_add(struct corerouter_session *cs) {
|
||||
peers->session = cs;
|
||||
peers->fd = -1;
|
||||
// create input buffer
|
||||
peers->in = uwsgi_buffer_new(uwsgi.page_size);
|
||||
size_t bufsize = cs->corerouter->buffer_size;
|
||||
if (!bufsize) bufsize = uwsgi.page_size;
|
||||
peers->in = uwsgi_buffer_new(bufsize);
|
||||
// add timeout
|
||||
peers->timeout = cr_add_timeout(cs->corerouter, peers);
|
||||
peers->prev = old_peers;
|
||||
@@ -284,6 +286,10 @@ void corerouter_manage_subscription(char *key, uint16_t keylen, char *val, uint1
|
||||
usr->sni_ca = val;
|
||||
usr->sni_ca_len = vallen;
|
||||
}
|
||||
else if (!uwsgi_strncmp("notify", 6, key, keylen)) {
|
||||
usr->notify = val;
|
||||
usr->notify_len = vallen;
|
||||
}
|
||||
}
|
||||
|
||||
void corerouter_close_peer(struct uwsgi_corerouter *ucr, struct corerouter_peer *peer) {
|
||||
@@ -562,7 +568,9 @@ struct corerouter_session *corerouter_alloc_session(struct uwsgi_corerouter *ucr
|
||||
|
||||
struct corerouter_peer *peer = uwsgi_calloc(sizeof(struct corerouter_peer));
|
||||
// main_peer has only input buffer as output buffer is taken from backend peers
|
||||
peer->in = uwsgi_buffer_new(uwsgi.page_size);
|
||||
size_t bufsize = ucr->buffer_size;
|
||||
if (!bufsize) bufsize = uwsgi.page_size;
|
||||
peer->in = uwsgi_buffer_new(bufsize);
|
||||
|
||||
ucr->cr_table[new_connection] = peer;
|
||||
cs->main_peer = peer;
|
||||
|
||||
@@ -265,6 +265,11 @@ struct uwsgi_corerouter {
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
|
||||
struct uwsgi_string_list *resubscribe;
|
||||
char *resubscribe_bind;
|
||||
|
||||
size_t buffer_size;
|
||||
|
||||
};
|
||||
|
||||
// a session is started when a client connect to the router
|
||||
|
||||
@@ -154,10 +154,6 @@ void uwsgi_corerouter_manage_subscription(struct uwsgi_corerouter *ucr, int id,
|
||||
if (node && node->len) {
|
||||
#ifdef UWSGI_SSL
|
||||
if (uwsgi.subscriptions_sign_check_dir) {
|
||||
if (usr.sign_len == 0 || usr.base_len == 0)
|
||||
return;
|
||||
if (usr.unix_check <= node->unix_check)
|
||||
return;
|
||||
if (!uwsgi_subscription_sign_check(node->slot, &usr)) {
|
||||
return;
|
||||
}
|
||||
@@ -187,6 +183,51 @@ void uwsgi_corerouter_manage_subscription(struct uwsgi_corerouter *ucr, int id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// resubscribe if needed ?
|
||||
if (ucr->resubscribe) {
|
||||
static char *address = NULL;
|
||||
if (!address) {
|
||||
struct uwsgi_gateway_socket *augs = uwsgi.gateway_sockets;
|
||||
while (augs) {
|
||||
if (!strcmp(ucr->name, augs->owner)) {
|
||||
if (!augs->subscription) {
|
||||
address = augs->name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
augs = augs->next;
|
||||
}
|
||||
}
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
char *sni_key = NULL;
|
||||
char *sni_cert = NULL;
|
||||
char *sni_ca = NULL;
|
||||
if (usr.sni_key_len) {
|
||||
sni_key = uwsgi_concat2n(usr.sni_key, usr.sni_key_len, "", 0);
|
||||
}
|
||||
if (usr.sni_crt_len) {
|
||||
sni_cert = uwsgi_concat2n(usr.sni_crt, usr.sni_crt_len, "", 0);
|
||||
}
|
||||
if (usr.sni_ca_len) {
|
||||
sni_ca = uwsgi_concat2n(usr.sni_ca, usr.sni_ca_len, "", 0);
|
||||
}
|
||||
uwsgi_foreach(usl, ucr->resubscribe) {
|
||||
if (ucr->resubscribe_bind) {
|
||||
static int rfd = -1;
|
||||
if (rfd == -1) {
|
||||
rfd = bind_to_udp(ucr->resubscribe_bind, 0, 0);
|
||||
}
|
||||
uwsgi_send_subscription_from_fd(rfd, usl->value, usr.key, usr.keylen, usr.modifier1, usr.modifier2, bbuf[3], address, NULL, sni_key, sni_cert, sni_ca);
|
||||
}
|
||||
else {
|
||||
uwsgi_send_subscription_from_fd(-2, usl->value, usr.key, usr.keylen, usr.modifier1, usr.modifier2, bbuf[3], address, NULL, sni_key, sni_cert, sni_ca);
|
||||
}
|
||||
}
|
||||
if (sni_key) free(sni_key);
|
||||
if (sni_cert) free(sni_cert);
|
||||
if (sni_ca) free(sni_ca);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -65,8 +65,11 @@ int uwsgi_cr_map_use_subscription_dotsplit(struct uwsgi_corerouter *ucr, struct
|
||||
|
||||
char *name = peer->key;
|
||||
uint16_t name_len = peer->key_len;
|
||||
// max 5 split, reduce DOS attempts
|
||||
int count = 5;
|
||||
|
||||
split:
|
||||
if (!count) return 0;
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("trying with %.*s\n", name_len, name);
|
||||
#endif
|
||||
@@ -76,6 +79,7 @@ split:
|
||||
if (next) {
|
||||
name_len -= next - name;
|
||||
name = next;
|
||||
count--;
|
||||
goto split;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-15
@@ -386,21 +386,9 @@ static void coroae_loop() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
perl_eval_pv("use Coro;", 0);
|
||||
if (SvTRUE(ERRSV)) {
|
||||
uwsgi_log("unable to load Coro module\n");
|
||||
exit(1);
|
||||
}
|
||||
perl_eval_pv("use AnyEvent;", 0);
|
||||
if (SvTRUE(ERRSV)) {
|
||||
uwsgi_log("unable to load AnyEvent module\n");
|
||||
exit(1);
|
||||
}
|
||||
perl_eval_pv("use Coro::AnyEvent;", 0);
|
||||
if (SvTRUE(ERRSV)) {
|
||||
uwsgi_log("unable to load Coro::AnyEvent module\n");
|
||||
exit(1);
|
||||
}
|
||||
perl_eval_pv("use Coro;", 1);
|
||||
perl_eval_pv("use AnyEvent;", 1);
|
||||
perl_eval_pv("use Coro::AnyEvent;", 1);
|
||||
|
||||
uwsgi.current_wsgi_req = coroae_current_wsgi_req;
|
||||
uwsgi.wait_write_hook = coroae_wait_fd_write;
|
||||
|
||||
@@ -37,7 +37,7 @@ static struct uwsgi_option fastrouter_options[] = {
|
||||
{"fastrouter-events", required_argument, 0, "set the maximum number of concurrent events", uwsgi_opt_set_int, &ufr.cr.nevents, 0},
|
||||
{"fastrouter-quiet", required_argument, 0, "do not report failed connections to instances", uwsgi_opt_true, &ufr.cr.quiet, 0},
|
||||
{"fastrouter-cheap", no_argument, 0, "run the fastrouter in cheap mode", uwsgi_opt_true, &ufr.cr.cheap, 0},
|
||||
{"fastrouter-subscription-server", required_argument, 0, "run the fastrouter subscription server on the spcified address", uwsgi_opt_corerouter_ss, &ufr, 0},
|
||||
{"fastrouter-subscription-server", required_argument, 0, "run the fastrouter subscription server on the specified address", uwsgi_opt_corerouter_ss, &ufr, 0},
|
||||
{"fastrouter-subscription-slot", required_argument, 0, "*** deprecated ***", uwsgi_opt_deprecated, (void *) "useless thanks to the new implementation", 0},
|
||||
|
||||
{"fastrouter-timeout", required_argument, 0, "set fastrouter timeout", uwsgi_opt_set_int, &ufr.cr.socket_timeout, 0},
|
||||
@@ -48,6 +48,13 @@ static struct uwsgi_option fastrouter_options[] = {
|
||||
{"fastrouter-stats-server", required_argument, 0, "run the fastrouter stats server", uwsgi_opt_set_str, &ufr.cr.stats_server, 0},
|
||||
{"fastrouter-ss", required_argument, 0, "run the fastrouter stats server", uwsgi_opt_set_str, &ufr.cr.stats_server, 0},
|
||||
{"fastrouter-harakiri", required_argument, 0, "enable fastrouter harakiri", uwsgi_opt_set_int, &ufr.cr.harakiri, 0},
|
||||
|
||||
{"fastrouter-uid", required_argument, 0, "drop fastrouter privileges to the specified uid", uwsgi_opt_uid, &ufr.cr.uid, 0 },
|
||||
{"fastrouter-gid", required_argument, 0, "drop fastrouter privileges to the specified gid", uwsgi_opt_gid, &ufr.cr.gid, 0 },
|
||||
{"fastrouter-resubscribe", required_argument, 0, "forward subscriptions to the specified subscription server", uwsgi_opt_add_string_list, &ufr.cr.resubscribe, 0},
|
||||
{"fastrouter-resubscribe-bind", required_argument, 0, "bind to the specified address when re-subscribing", uwsgi_opt_set_str, &ufr.cr.resubscribe_bind, 0},
|
||||
|
||||
{"fastrouter-buffer-size", required_argument, 0, "set internal buffer size (default: page size)", uwsgi_opt_set_64bit, &ufr.cr.buffer_size, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
|
||||
@@ -24,6 +24,9 @@ else:
|
||||
CFLAGS.append('-I' + archdir)
|
||||
CFLAGS.append('-I' + archdir + '/' + arch)
|
||||
CFLAGS.append('-I' + includedir + '/' + arch)
|
||||
archdir2 = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['rubyarchhdrdir']\"" % rbconfig).read().rstrip()
|
||||
if archdir2:
|
||||
CFLAGS.append('-I' + archdir2)
|
||||
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
@@ -132,6 +132,10 @@ static void greenlet_init_apps(void) {
|
||||
|
||||
|
||||
PyGreenlet_Import();
|
||||
if (PyErr_Occurred()){
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ugl.gl = uwsgi_malloc( sizeof(PyGreenlet *) * uwsgi.async );
|
||||
ugl.main = PyGreenlet_GetCurrent();
|
||||
|
||||
@@ -79,6 +79,11 @@ static void uwsgi_gridfs_do(struct wsgi_request *wsgi_req, struct uwsgi_gridfs_m
|
||||
}
|
||||
uwsgi_response_add_content_length(wsgi_req, gfile.getContentLength());
|
||||
|
||||
char http_last_modified[49];
|
||||
time_t t = gfile.getUploadDate().toTimeT();
|
||||
int size = uwsgi_http_date(t, http_last_modified);
|
||||
uwsgi_response_add_header(wsgi_req, (char *)"Last-Modified", 13, http_last_modified, size);
|
||||
|
||||
if (ugm->etag) {
|
||||
std::string g_md5 = gfile.getMD5();
|
||||
if (!g_md5.empty()) {
|
||||
|
||||
@@ -40,6 +40,8 @@ struct uwsgi_http {
|
||||
size_t spdy3_settings_size;
|
||||
#endif
|
||||
|
||||
int server_name_as_http_host;
|
||||
|
||||
};
|
||||
|
||||
struct http_session {
|
||||
|
||||
+8
-3
@@ -54,8 +54,12 @@ struct uwsgi_option http_options[] = {
|
||||
{"http-ss", required_argument, 0, "run the http router stats server", uwsgi_opt_set_str, &uhttp.cr.stats_server, 0},
|
||||
{"http-harakiri", required_argument, 0, "enable http router harakiri", uwsgi_opt_set_int, &uhttp.cr.harakiri, 0},
|
||||
{"http-stud-prefix", required_argument, 0, "expect a stud prefix (1byte family + 4/16 bytes address) on connections from the specified address", uwsgi_opt_add_addr_list, &uhttp.stud_prefix, 0},
|
||||
{"http-uid", required_argument, 0, "drop http routr privileges to the specified uid", uwsgi_opt_uid, &uhttp.cr.uid, 0 },
|
||||
{"http-gid", required_argument, 0, "drop http routr privileges to the specified gid", uwsgi_opt_gid, &uhttp.cr.gid, 0 },
|
||||
{"http-uid", required_argument, 0, "drop http router privileges to the specified uid", uwsgi_opt_uid, &uhttp.cr.uid, 0 },
|
||||
{"http-gid", required_argument, 0, "drop http router privileges to the specified gid", uwsgi_opt_gid, &uhttp.cr.gid, 0 },
|
||||
{"http-resubscribe", required_argument, 0, "forward subscriptions to the specified subscription server", uwsgi_opt_add_string_list, &uhttp.cr.resubscribe, 0},
|
||||
{"http-buffer-size", required_argument, 0, "set internal buffer size (default: page size)", uwsgi_opt_set_64bit, &uhttp.cr.buffer_size, 0},
|
||||
|
||||
{"http-server-name-as-http-host", required_argument, 0, "force SERVER_NAME to HTTP_HOST", uwsgi_opt_true, &uhttp.server_name_as_http_host, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
@@ -120,6 +124,7 @@ int http_add_uwsgi_header(struct corerouter_peer *peer, char *hh, uint16_t hhlen
|
||||
if (!uwsgi_strncmp("HOST", 4, hh, keylen)) {
|
||||
peer->key = val;
|
||||
peer->key_len = vallen;
|
||||
if (uhttp.server_name_as_http_host && uwsgi_buffer_append_keyval(out, "SERVER_NAME", 11, peer->key, peer->key_len)) return -1;
|
||||
}
|
||||
|
||||
else if (!uwsgi_strncmp("CONTENT_LENGTH", 14, hh, keylen)) {
|
||||
@@ -294,7 +299,7 @@ int http_headers_parse(struct corerouter_peer *peer) {
|
||||
if (uwsgi_buffer_append_keyval(out, "SCRIPT_NAME", 11, "", 0)) return -1;
|
||||
|
||||
// SERVER_NAME
|
||||
if (uwsgi_buffer_append_keyval(out, "SERVER_NAME", 11, uwsgi.hostname, uwsgi.hostname_len)) return -1;
|
||||
if (!uhttp.server_name_as_http_host && uwsgi_buffer_append_keyval(out, "SERVER_NAME", 11, uwsgi.hostname, uwsgi.hostname_len)) return -1;
|
||||
peer->key = uwsgi.hostname;
|
||||
peer->key_len = uwsgi.hostname_len;
|
||||
|
||||
|
||||
@@ -29,6 +29,10 @@ static ssize_t uwsgi_pipe_logger(struct uwsgi_logger *ul, char *message, size_t
|
||||
else {
|
||||
// child
|
||||
setsid();
|
||||
if (setsid() < 0) {
|
||||
uwsgi_error("setsid()");
|
||||
exit(1);
|
||||
}
|
||||
close(pipefd[1]);
|
||||
dup2(pipefd[0], STDIN_FILENO);
|
||||
close(pipefd[0]);
|
||||
|
||||
@@ -84,3 +84,4 @@ void uwsgi_perl_run_hook(SV *);
|
||||
void uwsgi_perl_exec(char *);
|
||||
|
||||
void uwsgi_perl_check_auto_reload(void);
|
||||
void uwsgi_psgi_preinit_apps(void);
|
||||
|
||||
+85
-36
@@ -107,11 +107,67 @@ XS(XS_input_read) {
|
||||
SV *read_buf = ST(1);
|
||||
unsigned long arg_len = SvIV(ST(2));
|
||||
|
||||
long offset = 0;
|
||||
if (items > 2) {
|
||||
offset = (long) SvIV(ST(3));
|
||||
}
|
||||
|
||||
ssize_t rlen = 0;
|
||||
|
||||
char *buf = uwsgi_request_body_read(wsgi_req, arg_len, &rlen);
|
||||
if (buf) {
|
||||
sv_setpvn(read_buf, buf, rlen);
|
||||
if (rlen > 0 && offset != 0) {
|
||||
STRLEN orig_len;
|
||||
// get data from original string
|
||||
char *orig = SvPV(read_buf, orig_len);
|
||||
size_t new_size = orig_len;
|
||||
// still valid ?
|
||||
if (offset > 0) {
|
||||
// if the new string is bigger than the old one, allocate a bigger chunk
|
||||
if ((size_t) rlen + offset > orig_len) {
|
||||
new_size = rlen + offset;
|
||||
}
|
||||
// if offset is bigger than orig_len, pad with "\0", so we use (slower) calloc
|
||||
char *new_buf = uwsgi_calloc(new_size);
|
||||
// put back older value
|
||||
memcpy(new_buf, orig, orig_len);
|
||||
// put the new value
|
||||
memcpy(new_buf + offset, buf, rlen);
|
||||
sv_setpvn(read_buf, new_buf, new_size);
|
||||
// free the new value
|
||||
free(new_buf);
|
||||
}
|
||||
// negative (a little bit more complex)
|
||||
else {
|
||||
long orig_offset = 0;
|
||||
// first of all get the new orig_len;
|
||||
offset = abs(offset);
|
||||
if (offset > (long) orig_len) {
|
||||
new_size = offset;
|
||||
orig_offset = offset - orig_len;
|
||||
offset = 0;
|
||||
}
|
||||
else {
|
||||
offset = orig_len - offset;
|
||||
}
|
||||
|
||||
if ((size_t) rlen + offset > new_size) {
|
||||
new_size = rlen + offset;
|
||||
}
|
||||
|
||||
char *new_buf = uwsgi_calloc(new_size);
|
||||
// put back older value
|
||||
memcpy(new_buf + orig_offset, orig, orig_len);
|
||||
// put the new value
|
||||
memcpy(new_buf + offset, buf, rlen);
|
||||
sv_setpvn(read_buf, new_buf, new_size);
|
||||
// free the new value
|
||||
free(new_buf);
|
||||
}
|
||||
}
|
||||
else {
|
||||
sv_setpvn(read_buf, buf, rlen);
|
||||
}
|
||||
goto ret;
|
||||
}
|
||||
|
||||
@@ -171,20 +227,6 @@ XS(XS_error_print) {
|
||||
XSRETURN(0);
|
||||
}
|
||||
|
||||
XS(XS_uwsgi_stacktrace) {
|
||||
|
||||
dXSARGS;
|
||||
|
||||
psgi_check_args(0);
|
||||
uwsgi_log("%s", SvPV_nolen(ERRSV));
|
||||
uwsgi_log("*** uWSGI perl stacktrace ***\n");
|
||||
SV *ret = perl_eval_pv("Devel::StackTrace->new->as_string;", 0);
|
||||
uwsgi_log("%s", SvPV_nolen(ret));
|
||||
uwsgi_log("*** end of perl stacktrace ***\n\n");
|
||||
XSRETURN(0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* automatically generated */
|
||||
|
||||
@@ -197,6 +239,7 @@ xs_init(pTHX)
|
||||
{
|
||||
char *file = __FILE__;
|
||||
dXSUB_SYS;
|
||||
HV *stash;
|
||||
|
||||
/* DynaLoader is a special case */
|
||||
newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
|
||||
@@ -218,13 +261,16 @@ xs_init(pTHX)
|
||||
newXS("uwsgi::streaming::write", XS_streaming_write, "uwsgi::streaming");
|
||||
newXS("uwsgi::streaming::close", XS_streaming_close, "uwsgi::streaming");
|
||||
|
||||
newXS("uwsgi::stacktrace", XS_uwsgi_stacktrace, "uwsgi");
|
||||
|
||||
|
||||
uperl.tmp_streaming_stash[uperl.tmp_current_i] = gv_stashpv("uwsgi::streaming", 0);
|
||||
|
||||
nonworker:
|
||||
|
||||
stash = gv_stashpv("uwsgi", 1);
|
||||
newCONSTSUB(stash, "VERSION", newSVpv(UWSGI_VERSION, 0));
|
||||
newCONSTSUB(stash, "SPOOL_OK", newSViv(-2));
|
||||
newCONSTSUB(stash, "SPOOL_RETRY", newSViv(-1));
|
||||
newCONSTSUB(stash, "SPOOL_IGNORE", newSViv(0));
|
||||
|
||||
init_perl_embedded_module();
|
||||
|
||||
}
|
||||
@@ -347,16 +393,12 @@ int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, Pe
|
||||
}
|
||||
}
|
||||
|
||||
perl_eval_pv("use IO::Handle;", 0);
|
||||
perl_eval_pv("use IO::File;", 0);
|
||||
perl_eval_pv("use IO::Socket;", 0);
|
||||
perl_eval_pv("use Scalar::Util;", 0);
|
||||
perl_eval_pv("use IO::Handle;", 1);
|
||||
perl_eval_pv("use IO::File;", 1);
|
||||
perl_eval_pv("use IO::Socket;", 1);
|
||||
perl_eval_pv("use Scalar::Util;", 1);
|
||||
if (!uperl.no_die_catch) {
|
||||
perl_eval_pv("use Devel::StackTrace;", 0);
|
||||
if (!SvTRUE(ERRSV)) {
|
||||
uperl.stacktrace_available = 1;
|
||||
perl_eval_pv("$SIG{__DIE__} = \\&uwsgi::stacktrace;", 0);
|
||||
}
|
||||
perl_eval_pv("use Devel::StackTrace; $SIG{__DIE__} = sub { print Devel::StackTrace->new()->as_string() };", 0);
|
||||
}
|
||||
|
||||
if (uperl.argv_items || uperl.argv_item) {
|
||||
@@ -394,7 +436,7 @@ int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, Pe
|
||||
free(buf);
|
||||
|
||||
if(SvTRUE(ERRSV)) {
|
||||
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
|
||||
uwsgi_log("%s", SvPV_nolen(ERRSV));
|
||||
free(callables);
|
||||
uwsgi_perl_free_stashes();
|
||||
goto clear;
|
||||
@@ -456,6 +498,17 @@ clear2:
|
||||
return -1;
|
||||
}
|
||||
|
||||
void uwsgi_psgi_preinit_apps() {
|
||||
if (uperl.exec) {
|
||||
PERL_SET_CONTEXT(uperl.main[0]);
|
||||
perl_parse(uperl.main[0], xs_init, 3, uperl.embedding, NULL);
|
||||
struct uwsgi_string_list *usl;
|
||||
uwsgi_foreach(usl, uperl.exec) {
|
||||
uwsgi_perl_exec(usl->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_psgi_app() {
|
||||
|
||||
if (uperl.psgi) {
|
||||
@@ -463,15 +516,11 @@ void uwsgi_psgi_app() {
|
||||
init_psgi_app(NULL, uperl.psgi, strlen(uperl.psgi), uperl.main);
|
||||
}
|
||||
// create a perl environment (if needed)
|
||||
else if (uperl.exec || uperl.shell) {
|
||||
else if (!uperl.exec && uperl.shell) {
|
||||
PERL_SET_CONTEXT(uperl.main[0]);
|
||||
perl_parse(uperl.main[0], xs_init, 2, uperl.embedding, NULL);
|
||||
perl_parse(uperl.main[0], xs_init, 3, uperl.embedding, NULL);
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *usl;
|
||||
uwsgi_foreach(usl, uperl.exec) {
|
||||
uwsgi_perl_exec(usl->value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -480,7 +529,7 @@ int uwsgi_perl_mule(char *opt) {
|
||||
if (uwsgi_endswith(opt, ".pl")) {
|
||||
PERL_SET_CONTEXT(uperl.main[0]);
|
||||
uperl.embedding[1] = opt;
|
||||
if (perl_parse(uperl.main[0], xs_init, 2, uperl.embedding, NULL)) {
|
||||
if (perl_parse(uperl.main[0], xs_init, 3, uperl.embedding, NULL)) {
|
||||
return 0;
|
||||
}
|
||||
perl_run(uperl.main[0]);
|
||||
@@ -495,6 +544,6 @@ int uwsgi_perl_mule(char *opt) {
|
||||
void uwsgi_perl_exec(char *filename) {
|
||||
size_t size = 0;
|
||||
char *buf = uwsgi_open_and_read(filename, &size, 1, NULL);
|
||||
perl_eval_pv(buf, 0);
|
||||
perl_eval_pv(buf, 1);
|
||||
free(buf);
|
||||
}
|
||||
|
||||
@@ -950,6 +950,7 @@ struct uwsgi_plugin psgi_plugin = {
|
||||
.init = uwsgi_perl_init,
|
||||
.options = uwsgi_perl_options,
|
||||
|
||||
.preinit_apps = uwsgi_psgi_preinit_apps,
|
||||
.init_apps = uwsgi_psgi_app,
|
||||
.mount_app = uwsgi_perl_mount_app,
|
||||
|
||||
|
||||
@@ -897,6 +897,64 @@ XS(XS_chunked_read_nb) {
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_spool) {
|
||||
|
||||
dXSARGS;
|
||||
psgi_check_args(1);
|
||||
|
||||
SV *arg = ST(0);
|
||||
HV *env = NULL;
|
||||
|
||||
char *body = NULL;
|
||||
STRLEN body_len = 0;
|
||||
|
||||
if (SvROK(arg)) {
|
||||
env = (HV *) SvRV(arg);
|
||||
}
|
||||
else {
|
||||
croak("spool argument must be a hashref");
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
|
||||
if (SvTYPE(env) != SVt_PVHV) {
|
||||
croak("spool argument must be a hashref");
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
|
||||
if (hv_exists(env, "body", 4)) {
|
||||
SV **body_sv = hv_fetch(env, "body", 4, 0);
|
||||
body = SvPV(*body_sv, body_len);
|
||||
(void)hv_delete(env, "body", 4, 0);
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
|
||||
|
||||
HE *he;
|
||||
hv_iterinit(env);
|
||||
while((he = hv_iternext(env))) {
|
||||
I32 klen;
|
||||
STRLEN vlen;
|
||||
char *key = hv_iterkey(he, &klen);
|
||||
char *value = SvPV(hv_iterval(env, he), vlen);
|
||||
if (uwsgi_buffer_append_keyval(ub, key, klen, value, vlen)) {
|
||||
croak("unable to serialize hash to spool file");
|
||||
uwsgi_buffer_destroy(ub);
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
}
|
||||
|
||||
char *filename = uwsgi_spool_request(current_wsgi_req(), ub->buf, ub->pos, body, body_len);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
if (filename) {
|
||||
ST(0) = newSVpv(filename, strlen(filename));
|
||||
free(filename);
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
croak("unable to spool request");
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
|
||||
void init_perl_embedded_module() {
|
||||
psgi_xs(reload);
|
||||
|
||||
@@ -957,4 +1015,6 @@ void init_perl_embedded_module() {
|
||||
psgi_xs(sharedarea_wait);
|
||||
|
||||
psgi_xs(spooler);
|
||||
psgi_xs(spool);
|
||||
|
||||
}
|
||||
|
||||
@@ -16,12 +16,15 @@ struct uwsgi_pypy {
|
||||
char *home;
|
||||
char *wsgi;
|
||||
char *wsgi_file;
|
||||
char *paste;
|
||||
struct uwsgi_string_list *eval;
|
||||
struct uwsgi_string_list *eval_post_fork;
|
||||
struct uwsgi_string_list *exec;
|
||||
struct uwsgi_string_list *exec_post_fork;
|
||||
|
||||
struct uwsgi_string_list *pp;
|
||||
|
||||
pthread_mutex_t attach_thread_lock;
|
||||
} upypy;
|
||||
|
||||
// the functions exposed by libpypy-c
|
||||
@@ -34,6 +37,7 @@ void (*u_pypy_init_threads)(void);
|
||||
// the hooks you can override with pypy
|
||||
void (*uwsgi_pypy_hook_loader)(char *);
|
||||
void (*uwsgi_pypy_hook_file_loader)(char *);
|
||||
void (*uwsgi_pypy_hook_paste_loader)(char *);
|
||||
void (*uwsgi_pypy_hook_pythonpath)(char *);
|
||||
void (*uwsgi_pypy_hook_request)(void *, int);
|
||||
void (*uwsgi_pypy_post_fork_hook)(void);
|
||||
@@ -231,6 +235,10 @@ static void uwsgi_pypy_init_apps() {
|
||||
if (uwsgi_pypy_hook_file_loader && upypy.wsgi_file) {
|
||||
uwsgi_pypy_hook_file_loader(upypy.wsgi_file);
|
||||
}
|
||||
|
||||
if (uwsgi_pypy_hook_paste_loader && upypy.paste) {
|
||||
uwsgi_pypy_hook_paste_loader(upypy.paste);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -240,12 +248,20 @@ static void uwsgi_pypy_atexit() {
|
||||
}
|
||||
*/
|
||||
|
||||
static void uwsgi_opt_pypy_ini_paste(char *opt, char *value, void *foobar) {
|
||||
uwsgi_opt_load_ini(opt, value, NULL);
|
||||
upypy.paste = value;
|
||||
}
|
||||
|
||||
|
||||
static struct uwsgi_option uwsgi_pypy_options[] = {
|
||||
{"pypy-lib", required_argument, 0, "set the path/name of the pypy library", uwsgi_opt_set_str, &upypy.lib, 0},
|
||||
{"pypy-setup", required_argument, 0, "set the path of the python setup script", uwsgi_opt_set_str, &upypy.setup, 0},
|
||||
{"pypy-home", required_argument, 0, "set the home of pypy library", uwsgi_opt_set_str, &upypy.home, 0},
|
||||
{"pypy-wsgi", required_argument, 0, "load a WSGI module", uwsgi_opt_set_str, &upypy.wsgi, 0},
|
||||
{"pypy-wsgi-file", required_argument, 0, "load a WSGI/mod_wsgi file", uwsgi_opt_set_str, &upypy.wsgi_file, 0},
|
||||
{"pypy-ini-paste", required_argument, 0, "load a paste.deploy config file containing uwsgi section", uwsgi_opt_pypy_ini_paste, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"pypy-paste", required_argument, 0, "load a paste.deploy config file", uwsgi_opt_set_str, &upypy.paste, 0},
|
||||
{"pypy-eval", required_argument, 0, "evaluate pypy code before fork()", uwsgi_opt_add_string_list, &upypy.eval, 0},
|
||||
{"pypy-eval-post-fork", required_argument, 0, "evaluate pypy code soon after fork()", uwsgi_opt_add_string_list, &upypy.eval_post_fork, 0},
|
||||
{"pypy-exec", required_argument, 0, "execute pypy code from file before fork()", uwsgi_opt_add_string_list, &upypy.exec, 0},
|
||||
@@ -264,7 +280,9 @@ static void uwsgi_pypy_enable_threads() {
|
||||
|
||||
static void uwsgi_pypy_init_thread() {
|
||||
if (u_pypy_thread_attach) {
|
||||
pthread_mutex_lock(&upypy.attach_thread_lock);
|
||||
u_pypy_thread_attach();
|
||||
pthread_mutex_unlock(&upypy.attach_thread_lock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,6 +304,7 @@ static uint64_t uwsgi_pypy_rpc(void *func, uint8_t argc, char **argv, uint16_t a
|
||||
}
|
||||
|
||||
static void uwsgi_pypy_post_fork() {
|
||||
pthread_mutex_init(&upypy.attach_thread_lock, NULL);
|
||||
struct uwsgi_string_list *usl = upypy.eval_post_fork;
|
||||
while(usl) {
|
||||
if (u_pypy_execute_source(usl->value)) {
|
||||
|
||||
@@ -26,6 +26,7 @@ int close(int);
|
||||
|
||||
void (*uwsgi_pypy_hook_loader)(char *);
|
||||
void (*uwsgi_pypy_hook_file_loader)(char *);
|
||||
void (*uwsgi_pypy_hook_paste_loader)(char *);
|
||||
void (*uwsgi_pypy_hook_pythonpath)(char *);
|
||||
void (*uwsgi_pypy_hook_request)(struct wsgi_request *);
|
||||
void (*uwsgi_pypy_post_fork_hook)(void);
|
||||
@@ -304,6 +305,25 @@ def uwsgi_pypy_file_loader(filename):
|
||||
mod = imp.load_source('uwsgi_file_wsgi', w)
|
||||
wsgi_application = getattr(mod, c)
|
||||
|
||||
"""
|
||||
load a .ini paste app
|
||||
"""
|
||||
@ffi.callback("void(char *)")
|
||||
def uwsgi_pypy_paste_loader(config):
|
||||
global wsgi_application
|
||||
c = ffi.string(config)
|
||||
if c.startswith('config:'):
|
||||
c = c[7:]
|
||||
if c[0] != '/':
|
||||
c = os.getcwd() + '/' + c
|
||||
try:
|
||||
from paste.script.util.logging_config import fileConfig
|
||||
fileConfig(c)
|
||||
except ImportError:
|
||||
print "PyPy WARNING: unable to load paste.script.util.logging_config"
|
||||
from paste.deploy import loadapp
|
||||
wsgi_application = loadapp('config:%s' % c)
|
||||
|
||||
"""
|
||||
.post_fork_hook
|
||||
"""
|
||||
@@ -462,6 +482,7 @@ def uwsgi_pypy_wsgi_handler(wsgi_req):
|
||||
|
||||
lib.uwsgi_pypy_hook_loader = uwsgi_pypy_loader
|
||||
lib.uwsgi_pypy_hook_file_loader = uwsgi_pypy_file_loader
|
||||
lib.uwsgi_pypy_hook_paste_loader = uwsgi_pypy_paste_loader
|
||||
lib.uwsgi_pypy_hook_pythonpath = uwsgi_pypy_pythonpath
|
||||
lib.uwsgi_pypy_hook_request = uwsgi_pypy_wsgi_handler
|
||||
lib.uwsgi_pypy_post_fork_hook = uwsgi_pypy_post_fork_hook
|
||||
|
||||
@@ -1616,25 +1616,25 @@ int uwsgi_python_spooler(char *filename, char *buf, uint16_t len, char *body, si
|
||||
return 0;
|
||||
}
|
||||
|
||||
int retval = -1;
|
||||
PyObject *spool_dict = PyDict_New();
|
||||
PyObject *pyargs, *ret;
|
||||
PyObject *pyargs = PyTuple_New(1);
|
||||
PyObject *ret = NULL;
|
||||
|
||||
PyObject *value = PyString_FromString(filename);
|
||||
PyDict_SetItemString(spool_dict, "spooler_task_name", value);
|
||||
Py_DECREF(value);
|
||||
|
||||
if (uwsgi_hooked_parse(buf, len, uwsgi_python_add_item, spool_dict)) {
|
||||
Py_DECREF(spool_dict);
|
||||
// malformed packet, destroy it
|
||||
UWSGI_RELEASE_GIL;
|
||||
return -2;
|
||||
retval = -2;
|
||||
goto clear;
|
||||
}
|
||||
|
||||
pyargs = PyTuple_New(1);
|
||||
|
||||
PyObject *zero = PyString_FromString(filename);
|
||||
PyDict_SetItemString(spool_dict, "spooler_task_name", zero);
|
||||
Py_DECREF(zero);
|
||||
|
||||
if (body && body_len > 0) {
|
||||
PyDict_SetItemString(spool_dict, "body", PyString_FromStringAndSize(body, body_len));
|
||||
PyObject *value = PyString_FromStringAndSize(body, body_len);
|
||||
PyDict_SetItemString(spool_dict, "body", value);
|
||||
Py_DECREF(value);
|
||||
}
|
||||
PyTuple_SetItem(pyargs, 0, spool_dict);
|
||||
|
||||
@@ -1642,32 +1642,25 @@ int uwsgi_python_spooler(char *filename, char *buf, uint16_t len, char *body, si
|
||||
|
||||
if (ret) {
|
||||
if (!PyInt_Check(ret)) {
|
||||
Py_DECREF(ret);
|
||||
Py_DECREF(spool_dict);
|
||||
Py_DECREF(pyargs);
|
||||
// error, retry
|
||||
UWSGI_RELEASE_GIL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int retval = (int) PyInt_AsLong(ret);
|
||||
Py_DECREF(ret);
|
||||
Py_DECREF(spool_dict);
|
||||
Py_DECREF(pyargs);
|
||||
UWSGI_RELEASE_GIL;
|
||||
return retval;
|
||||
|
||||
retval = -1; // error, retry
|
||||
} else {
|
||||
retval = (int) PyInt_AsLong(ret);
|
||||
}
|
||||
goto clear;
|
||||
}
|
||||
|
||||
|
||||
if (PyErr_Occurred())
|
||||
PyErr_Print();
|
||||
|
||||
Py_DECREF(spool_dict);
|
||||
Py_DECREF(pyargs);
|
||||
|
||||
// error, retry
|
||||
retval = -1;
|
||||
|
||||
clear:
|
||||
Py_XDECREF(ret);
|
||||
Py_XDECREF(pyargs);
|
||||
Py_XDECREF(spool_dict);
|
||||
UWSGI_RELEASE_GIL;
|
||||
return -1;
|
||||
return retval;
|
||||
}
|
||||
|
||||
void uwsgi_python_resume(struct wsgi_request *wsgi_req) {
|
||||
@@ -1802,15 +1795,13 @@ static void uwsgi_python_harakiri(int wid) {
|
||||
if (fd < 1)
|
||||
goto exit;
|
||||
|
||||
int ret = uwsgi_waitfd(fd, uwsgi.socket_timeout);
|
||||
if (ret <= 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
ssize_t len = read(fd, buf, 8192);
|
||||
if (len <= 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
uwsgi_log("%.*s", (int) len, buf);
|
||||
for(;;) {
|
||||
int ret = uwsgi_waitfd(fd, uwsgi.socket_timeout);
|
||||
if (ret <= 0) goto cleanup;
|
||||
ssize_t len = read(fd, buf, 8192);
|
||||
if (len <= 0) goto cleanup;
|
||||
uwsgi_log("%.*s", (int) len, buf);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
close(fd);
|
||||
|
||||
@@ -114,7 +114,6 @@ void *uwsgi_python_tracebacker_thread(void *foobar) {
|
||||
}
|
||||
PyObject *frame = PyIter_Next(frames_iter);
|
||||
while(frame) {
|
||||
|
||||
PyObject *thread_id = PyTuple_GetItem(frame, 0);
|
||||
if (!thread_id) goto next2;
|
||||
|
||||
|
||||
+49
-112
@@ -1289,7 +1289,7 @@ PyObject *py_uwsgi_mule_get_msg(PyObject * self, PyObject * args, PyObject *kwar
|
||||
int timeout = -1;
|
||||
int manage_signals = 1, manage_farms = 1;
|
||||
|
||||
static char *kwlist[] = {"signals", "buffer_size", "timeout", "farms", NULL};
|
||||
static char *kwlist[] = {"signals", "farms", "buffer_size", "timeout", NULL};
|
||||
|
||||
if (uwsgi.muleid == 0) {
|
||||
return PyErr_Format(PyExc_ValueError, "you can receive mule messages only in a mule !!!");
|
||||
@@ -1745,25 +1745,13 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
|
||||
PyObject *spool_dict, *spool_vars;
|
||||
PyObject *zero, *key, *val;
|
||||
uint16_t keysize, valsize;
|
||||
char *cur_buf;
|
||||
int i;
|
||||
char spool_filename[1024];
|
||||
struct wsgi_request *wsgi_req = py_current_wsgi_req();
|
||||
char *priority = NULL;
|
||||
long numprio = 0;
|
||||
time_t at = 0;
|
||||
char *body = NULL;
|
||||
size_t body_len= 0;
|
||||
|
||||
// this is a counter for non-request-related tasks (like threads or greenlet)
|
||||
static int internal_counter = 0xffff;
|
||||
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
|
||||
spool_dict = PyTuple_GetItem(args, 0);
|
||||
|
||||
if (spool_dict) {
|
||||
|
||||
if (!PyDict_Check(spool_dict)) {
|
||||
return PyErr_Format(PyExc_ValueError, "The argument of spooler callable must be a dictionary");
|
||||
}
|
||||
@@ -1774,46 +1762,10 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
|
||||
spool_dict = kw;
|
||||
}
|
||||
|
||||
|
||||
if (!spool_dict) {
|
||||
return PyErr_Format(PyExc_ValueError, "The argument of spooler callable must be a dictionary");
|
||||
}
|
||||
|
||||
// TODO if "spooler" is a num, get the spooler by id, otherwise get it by directory
|
||||
PyObject *py_spooler = uwsgi_py_dict_get(spool_dict, "spooler");
|
||||
if (py_spooler) {
|
||||
if (PyString_Check(py_spooler)) {
|
||||
uspool = uwsgi_get_spooler_by_name(PyString_AsString(py_spooler));
|
||||
if (!uspool) {
|
||||
return PyErr_Format(PyExc_ValueError, "Unknown spooler requested");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PyObject *pyprio = uwsgi_py_dict_get(spool_dict, "priority");
|
||||
if (pyprio) {
|
||||
if (PyInt_Check(pyprio)) {
|
||||
numprio = PyInt_AsLong(pyprio);
|
||||
uwsgi_py_dict_del(spool_dict, "priority");
|
||||
}
|
||||
}
|
||||
|
||||
PyObject *pyat = uwsgi_py_dict_get(spool_dict, "at");
|
||||
if (pyat) {
|
||||
if (PyInt_Check(pyat)) {
|
||||
at = (time_t) PyInt_AsLong(pyat);
|
||||
uwsgi_py_dict_del(spool_dict, "at");
|
||||
}
|
||||
else if (PyLong_Check(pyat)) {
|
||||
at = (time_t) PyLong_AsLong(pyat);
|
||||
uwsgi_py_dict_del(spool_dict, "at");
|
||||
}
|
||||
else if (PyFloat_Check(pyat)) {
|
||||
at = (time_t) PyFloat_AsDouble(pyat);
|
||||
uwsgi_py_dict_del(spool_dict, "at");
|
||||
}
|
||||
}
|
||||
|
||||
PyObject *pybody = uwsgi_py_dict_get(spool_dict, "body");
|
||||
if (pybody) {
|
||||
if (PyString_Check(pybody)) {
|
||||
@@ -1830,9 +1782,8 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
char *spool_buffer = uwsgi_malloc(UMAX16);
|
||||
|
||||
cur_buf = spool_buffer;
|
||||
int i;
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
|
||||
|
||||
for (i = 0; i < PyList_Size(spool_vars); i++) {
|
||||
zero = PyList_GetItem(spool_vars, i);
|
||||
@@ -1841,98 +1792,84 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
|
||||
key = PyTuple_GetItem(zero, 0);
|
||||
val = PyTuple_GetItem(zero, 1);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("ob_type %s %s\n", key->ob_type->tp_name, val->ob_type->tp_name);
|
||||
#endif
|
||||
|
||||
if (PyString_Check(key) && PyString_Check(val)) {
|
||||
|
||||
if (PyString_Check(key)) {
|
||||
|
||||
keysize = PyString_Size(key);
|
||||
valsize = PyString_Size(val);
|
||||
if (cur_buf + keysize + 2 + valsize + 2 <= spool_buffer + UMAX16) {
|
||||
|
||||
*cur_buf++ = (uint8_t) (keysize & 0xff);
|
||||
*cur_buf++ = (uint8_t) ((keysize >> 8) & 0xff);
|
||||
|
||||
memcpy(cur_buf, PyString_AsString(key), keysize);
|
||||
cur_buf += keysize;
|
||||
|
||||
*cur_buf++ = (uint8_t) (valsize & 0xff);
|
||||
*cur_buf++ = (uint8_t) ((valsize >> 8) & 0xff);
|
||||
|
||||
memcpy(cur_buf, PyString_AsString(val), valsize);
|
||||
cur_buf += valsize;
|
||||
|
||||
if (PyString_Check(val)) {
|
||||
valsize = PyString_Size(val);
|
||||
if (uwsgi_buffer_append_keyval(ub, PyString_AsString(key), keysize, PyString_AsString(val), valsize)) {
|
||||
Py_DECREF(zero);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Py_DECREF(zero);
|
||||
free(spool_buffer);
|
||||
return PyErr_Format(PyExc_ValueError, "spooler packet cannot be more than %d bytes", UMAX16);
|
||||
#ifdef PYTHREE
|
||||
PyObject *str = PyObject_Bytes(val);
|
||||
#else
|
||||
PyObject *str = PyObject_Str(val);
|
||||
#endif
|
||||
if (!str) {
|
||||
Py_DECREF(zero);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
goto error;
|
||||
}
|
||||
if (uwsgi_buffer_append_keyval(ub, PyString_AsString(key), keysize, PyString_AsString(str), PyString_Size(str))) {
|
||||
Py_DECREF(zero);
|
||||
Py_DECREF(str);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
goto error;
|
||||
}
|
||||
Py_DECREF(str);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Py_DECREF(zero);
|
||||
free(spool_buffer);
|
||||
return PyErr_Format(PyExc_ValueError, "spooler callable dictionary must contains only strings");
|
||||
uwsgi_buffer_destroy(ub);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else {
|
||||
free(spool_buffer);
|
||||
Py_DECREF(zero);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
goto error;
|
||||
}
|
||||
Py_DECREF(zero);
|
||||
}
|
||||
else {
|
||||
free(spool_buffer);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (numprio) {
|
||||
priority = uwsgi_num2str(numprio);
|
||||
}
|
||||
|
||||
int async_id;
|
||||
|
||||
if (wsgi_req) {
|
||||
async_id = wsgi_req->async_id;
|
||||
}
|
||||
else {
|
||||
// the GIL is protecting this counter...
|
||||
async_id = internal_counter;
|
||||
internal_counter++;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
i = spool_request(uspool, spool_filename, uwsgi.workers[0].requests + 1, async_id, spool_buffer, cur_buf - spool_buffer, priority, at, body, body_len);
|
||||
char *filename = uwsgi_spool_request(wsgi_req, ub->buf, ub->pos, body, body_len);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
|
||||
UWSGI_GET_GIL
|
||||
|
||||
|
||||
if (pybody) {
|
||||
Py_DECREF(pybody);
|
||||
}
|
||||
|
||||
if (priority) {
|
||||
free(priority);
|
||||
}
|
||||
|
||||
free(spool_buffer);
|
||||
|
||||
|
||||
Py_DECREF(spool_vars);
|
||||
|
||||
if (i > 0) {
|
||||
char *slash = uwsgi_get_last_char(spool_filename, '/');
|
||||
if (slash) {
|
||||
return PyString_FromString(slash+1);
|
||||
}
|
||||
return PyString_FromString(spool_filename);
|
||||
if (filename) {
|
||||
PyObject *ret = PyString_FromString(filename);
|
||||
free(filename);
|
||||
return ret;
|
||||
}
|
||||
return PyErr_Format(PyExc_ValueError, "unable to spool job");
|
||||
error:
|
||||
#ifdef PYTHREE
|
||||
return PyErr_Format(PyExc_ValueError, "spooler callable dictionary must contains only bytes");
|
||||
#else
|
||||
return PyErr_Format(PyExc_ValueError, "spooler callable dictionary must contains only strings");
|
||||
#endif
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_spooler_pid(PyObject * self, PyObject * args) {
|
||||
|
||||
+30
-68
@@ -932,35 +932,36 @@ static VALUE uwsgi_ruby_signal(int argc, VALUE *argv, VALUE *class) {
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
int rack_uwsgi_build_spool(VALUE rbkey, VALUE rbval, VALUE argv) {
|
||||
char **sa = (char **) argv;
|
||||
static int rack_uwsgi_build_spool(VALUE rbkey, VALUE rbval, VALUE argv) {
|
||||
struct uwsgi_buffer *ub = (struct uwsgi_buffer *) argv;
|
||||
|
||||
char *cur_buf = sa[0];
|
||||
char *watermark = sa[1];
|
||||
|
||||
if (TYPE(rbkey) != T_STRING || TYPE(rbval) != T_STRING) {
|
||||
if (TYPE(rbkey) != T_STRING) {
|
||||
rb_raise(rb_eRuntimeError, "spool hash must contains only strings");
|
||||
return ST_STOP;
|
||||
}
|
||||
|
||||
char *key = RSTRING_PTR(rbkey); uint16_t keylen = RSTRING_LEN(rbkey);
|
||||
char *val = RSTRING_PTR(rbval); uint16_t vallen = RSTRING_LEN(rbval);
|
||||
|
||||
if (cur_buf + (2+keylen+2+vallen) > watermark) {
|
||||
rb_raise(rb_eRuntimeError, "spool hash size can be no more than 64K");
|
||||
return ST_STOP;
|
||||
if (TYPE(rbval) == T_STRING) {
|
||||
char *val = RSTRING_PTR(rbval); uint16_t vallen = RSTRING_LEN(rbval);
|
||||
if (uwsgi_buffer_append_keyval(ub, key, keylen, val, vallen)) {
|
||||
rb_raise(rb_eRuntimeError, "error building the spool packet");
|
||||
return ST_STOP;
|
||||
}
|
||||
}
|
||||
else {
|
||||
//VALUE str = rb_any_to_s(rbval);
|
||||
VALUE str = rb_funcall( rbval, rb_intern("to_s"), 0);
|
||||
if (!str) {
|
||||
rb_raise(rb_eRuntimeError, "error building the spool packet");
|
||||
return ST_STOP;
|
||||
}
|
||||
char *val = RSTRING_PTR(str); uint16_t vallen = RSTRING_LEN(str);
|
||||
if (uwsgi_buffer_append_keyval(ub, key, keylen, val, vallen)) {
|
||||
rb_raise(rb_eRuntimeError, "error building the spool packet");
|
||||
return ST_STOP;
|
||||
}
|
||||
}
|
||||
|
||||
*cur_buf++ = (uint8_t) (keylen & 0xff);
|
||||
*cur_buf++ = (uint8_t) ((keylen >> 8) & 0xff);
|
||||
memcpy(cur_buf, key, keylen); cur_buf += keylen;
|
||||
|
||||
*cur_buf++ = (uint8_t) (vallen & 0xff);
|
||||
*cur_buf++ = (uint8_t) ((vallen >> 8) & 0xff);
|
||||
memcpy(cur_buf, val, vallen); cur_buf += vallen;
|
||||
|
||||
// fix the ptr
|
||||
sa[0] = cur_buf;
|
||||
|
||||
return ST_CONTINUE;
|
||||
}
|
||||
@@ -968,38 +969,12 @@ int rack_uwsgi_build_spool(VALUE rbkey, VALUE rbval, VALUE argv) {
|
||||
|
||||
static VALUE rack_uwsgi_send_spool(VALUE *class, VALUE args) {
|
||||
|
||||
char spool_filename[1024];
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
char *priority = NULL;
|
||||
long numprio = 0;
|
||||
time_t at = 0;
|
||||
char *body = NULL;
|
||||
size_t body_len= 0;
|
||||
|
||||
Check_Type(args, T_HASH);
|
||||
|
||||
// priority
|
||||
#ifdef RUBY19
|
||||
VALUE rbprio = rb_hash_lookup(args, rb_str_new2("priority"));
|
||||
#else
|
||||
VALUE rbprio = rb_hash_aref(args, rb_str_new2("priority"));
|
||||
#endif
|
||||
if (TYPE(rbprio) == T_FIXNUM) {
|
||||
numprio = NUM2INT(rbprio);
|
||||
rb_hash_delete(args, rb_str_new2("priority"));
|
||||
}
|
||||
|
||||
// at
|
||||
#ifdef RUBY19
|
||||
VALUE rbat = rb_hash_lookup(args, rb_str_new2("at"));
|
||||
#else
|
||||
VALUE rbat = rb_hash_aref(args, rb_str_new2("at"));
|
||||
#endif
|
||||
if (TYPE(rbat) == T_FIXNUM) {
|
||||
at = NUM2INT(rbat);
|
||||
rb_hash_delete(args, rb_str_new2("at"));
|
||||
}
|
||||
|
||||
// body
|
||||
#ifdef RUBY19
|
||||
VALUE rbbody = rb_hash_lookup(args, rb_str_new2("body"));
|
||||
@@ -1012,31 +987,18 @@ static VALUE rack_uwsgi_send_spool(VALUE *class, VALUE args) {
|
||||
rb_hash_delete(args, rb_str_new2("body"));
|
||||
}
|
||||
|
||||
char *spool_buffer = uwsgi_malloc(UMAX16);
|
||||
char *argv[2];
|
||||
argv[0] = spool_buffer;
|
||||
argv[1] = spool_buffer + UMAX16 ;
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
|
||||
|
||||
rb_hash_foreach(args, rack_uwsgi_build_spool, (VALUE) argv);
|
||||
rb_hash_foreach(args, rack_uwsgi_build_spool, (VALUE) ub);
|
||||
|
||||
if (numprio) {
|
||||
priority = uwsgi_num2str((int)numprio);
|
||||
}
|
||||
char *filename = uwsgi_spool_request(wsgi_req, ub->buf, ub->pos, body, body_len);
|
||||
|
||||
int ret = spool_request(uwsgi.spoolers, spool_filename, (int)(uwsgi.workers[0].requests + 1), wsgi_req->async_id, spool_buffer, (int)(argv[0] - spool_buffer), priority, at, body, body_len);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
|
||||
if (priority) {
|
||||
free(priority);
|
||||
}
|
||||
|
||||
free(spool_buffer);
|
||||
|
||||
if (ret > 0) {
|
||||
char *slash = uwsgi_get_last_char(spool_filename, '/');
|
||||
if (slash) {
|
||||
return rb_str_new2(slash+1);
|
||||
}
|
||||
return rb_str_new2(spool_filename);
|
||||
if (filename) {
|
||||
VALUE ret = rb_str_new2(filename);
|
||||
free(filename);
|
||||
return ret;
|
||||
}
|
||||
|
||||
rb_raise(rb_eRuntimeError, "unable to spool job");
|
||||
|
||||
@@ -459,6 +459,10 @@ static void rack_hack_dollar_zero(VALUE name, ID id) {
|
||||
rb_obj_taint(ur.dollar_zero);
|
||||
}
|
||||
|
||||
#ifndef RUBY19
|
||||
void Init_stack(VALUE*);
|
||||
#endif
|
||||
|
||||
int uwsgi_rack_init(){
|
||||
|
||||
#ifdef RUBY19
|
||||
@@ -483,14 +487,16 @@ int uwsgi_rack_init(){
|
||||
uwsgi_log("*** if you get errors about rubygems.rb, you can:\n");
|
||||
uwsgi_log("*** 1) add a directory to the libdir search path using --ruby-libdir ***\n");
|
||||
uwsgi_log("*** 2) force the RUBY_EXEC_PREFIX with --chdir ***\n");
|
||||
#ifdef UWSGI_RUBY_LIBDIR
|
||||
uwsgi_string_new_list(&ur.libdir, UWSGI_RUBY_LIBDIR);
|
||||
#endif
|
||||
#ifdef UWSGI_RUBY_ARCHDIR
|
||||
uwsgi_string_new_list(&ur.libdir, UWSGI_RUBY_ARCHDIR);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_RUBY_LIBDIR
|
||||
uwsgi_string_new_list(&ur.libdir, UWSGI_RUBY_LIBDIR);
|
||||
#endif
|
||||
#ifdef UWSGI_RUBY_ARCHDIR
|
||||
uwsgi_string_new_list(&ur.libdir, UWSGI_RUBY_ARCHDIR);
|
||||
#endif
|
||||
|
||||
ruby_init();
|
||||
struct uwsgi_string_list *usl = ur.libdir;
|
||||
while(usl) {
|
||||
@@ -501,6 +507,8 @@ int uwsgi_rack_init(){
|
||||
ruby_options(argc, argv);
|
||||
#else
|
||||
ruby_init();
|
||||
VALUE dummy;
|
||||
Init_stack(&dummy);
|
||||
ruby_init_loadpath();
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
#include <ruby.h>
|
||||
|
||||
|
||||
@@ -30,10 +30,12 @@ else:
|
||||
CFLAGS.append('-I' + includedir)
|
||||
archdir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['archdir']\"" % rbconfig).read().rstrip()
|
||||
arch = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['arch']\"" % rbconfig).read().rstrip()
|
||||
archdir2 = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['rubyarchhdrdir']\"" % rbconfig).read().rstrip()
|
||||
CFLAGS.append('-I' + archdir)
|
||||
CFLAGS.append('-I' + archdir + '/' + arch)
|
||||
CFLAGS.append('-I' + includedir + '/' + arch)
|
||||
|
||||
if archdir2:
|
||||
CFLAGS.append('-I' + archdir2)
|
||||
|
||||
LDFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['LDFLAGS']\"" % rbconfig).read().rstrip().split()
|
||||
libpath = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['libdir']\"" % rbconfig).read().rstrip()
|
||||
|
||||
@@ -56,6 +56,8 @@ static struct uwsgi_option rawrouter_options[] = {
|
||||
|
||||
{"rawrouter-xclient", no_argument, 0, "use the xclient protocol to pass the client addres", uwsgi_opt_true, &urr.xclient, 0},
|
||||
|
||||
{"rawrouter-buffer-size", required_argument, 0, "set internal buffer size (default: page size)", uwsgi_opt_set_64bit, &urr.cr.buffer_size, 0},
|
||||
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
|
||||
@@ -24,6 +24,9 @@ else:
|
||||
CFLAGS.append('-I' + archdir)
|
||||
CFLAGS.append('-I' + archdir + '/' + arch)
|
||||
CFLAGS.append('-I' + includedir + '/' + arch)
|
||||
archdir2 = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['rubyarchhdrdir']\"" % rbconfig).read().rstrip()
|
||||
if archdir2:
|
||||
CFLAGS.append('-I' + archdir2)
|
||||
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
@@ -10,15 +10,11 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
int uwsgi_request_spooler(struct wsgi_request *wsgi_req) {
|
||||
|
||||
int i;
|
||||
char spool_filename[1024];
|
||||
struct uwsgi_header uh;
|
||||
|
||||
// get the spooler from the modifier2
|
||||
// TODO get the spooler from the modifier2
|
||||
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
|
||||
if (uspool == NULL) {
|
||||
if (uwsgi.spoolers == NULL) {
|
||||
uwsgi_log("the spooler is inactive !!!...skip\n");
|
||||
uh.modifier1 = 255;
|
||||
uh.pktsize = 0;
|
||||
@@ -27,20 +23,21 @@ int uwsgi_request_spooler(struct wsgi_request *wsgi_req) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
i = spool_request(uspool, spool_filename, uwsgi.workers[0].requests + 1, wsgi_req->async_id, wsgi_req->buffer, wsgi_req->uh->pktsize, NULL, 0, NULL, 0);
|
||||
char *filename = uwsgi_spool_request(wsgi_req, wsgi_req->buffer, wsgi_req->uh->pktsize, NULL, 0);
|
||||
uh.modifier1 = 255;
|
||||
uh.pktsize = 0;
|
||||
if (i > 0) {
|
||||
if (filename) {
|
||||
uh.modifier2 = 1;
|
||||
if (uwsgi_response_write_body_do(wsgi_req, (char *) &uh, 4)) {
|
||||
uwsgi_log("disconnected client, remove spool file.\n");
|
||||
/* client disconnect, remove spool file */
|
||||
if (unlink(spool_filename)) {
|
||||
if (unlink(filename)) {
|
||||
uwsgi_error("uwsgi_request_spooler()/unlink()");
|
||||
uwsgi_log("something horrible happened !!! check your spooler ASAP !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
free(filename);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -155,6 +155,7 @@ static struct uwsgi_option sslrouter_options[] = {
|
||||
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
||||
{"sslrouter-sni", no_argument, 0, "use SNI to route requests", uwsgi_opt_true, &usr.sni, 0},
|
||||
#endif
|
||||
{"sslrouter-buffer-size", required_argument, 0, "set internal buffer size (default: page size)", uwsgi_opt_set_64bit, &usr.cr.buffer_size, 0},
|
||||
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
@@ -72,7 +72,6 @@ static void uwsgi_symcall_init(){
|
||||
exit(1);
|
||||
}
|
||||
*space = ' ';
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,13 +14,18 @@ int uwsgi_tuntap_peer_rules_check(struct uwsgi_tuntap_router *uttr, struct uwsgi
|
||||
uint32_t dst = ntohl(*dst_ip);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%X %X\n", src, dst);
|
||||
uwsgi_log("%d %X %X\n",direction, src, dst);
|
||||
#endif
|
||||
|
||||
int i;
|
||||
for(i=0;i<uttp->rules_cnt;i++) {
|
||||
struct uwsgi_tuntap_peer_rule *rule = &uttp->rules[i];
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("cnt = %i/%d direction = %d action = %d %X %X\n", i, uttp->rules_cnt, rule->direction, rule->action, rule->src_mask, rule->dst_mask);
|
||||
#endif
|
||||
|
||||
|
||||
if (rule->direction != direction) continue;
|
||||
|
||||
if (rule->src) {
|
||||
@@ -33,6 +38,7 @@ int uwsgi_tuntap_peer_rules_check(struct uwsgi_tuntap_router *uttr, struct uwsgi
|
||||
if (dst_masked != rule->dst) continue;
|
||||
}
|
||||
|
||||
|
||||
if (rule->action == 0) return 0;
|
||||
if (rule->action == 1) return 1;
|
||||
if (rule->action == 2) {
|
||||
@@ -295,7 +301,7 @@ void uwsgi_tuntap_peer_send_rules(int fd, struct uwsgi_tuntap_peer *peer) {
|
||||
|
||||
char *slash = strchr(argv[1],'/');
|
||||
if (slash) {
|
||||
utpr.src_mask = (0xffffffff << ((atoi(slash+1))-utpr.src_mask));
|
||||
utpr.src_mask = (0xffffffff << ((atoi(slash+1))-32));
|
||||
*slash = 0;
|
||||
}
|
||||
if (inet_pton(AF_INET, argv[1], &utpr.src) != 1) {
|
||||
@@ -307,7 +313,7 @@ void uwsgi_tuntap_peer_send_rules(int fd, struct uwsgi_tuntap_peer *peer) {
|
||||
|
||||
slash = strchr(argv[2],'/');
|
||||
if (slash) {
|
||||
utpr.dst_mask = (0xffffffff << ((atoi(slash+1))-utpr.dst_mask));
|
||||
utpr.dst_mask = (0xffffffff << ((atoi(slash+1))-32));
|
||||
*slash = 0;
|
||||
}
|
||||
if (inet_pton(AF_INET, argv[2], &utpr.dst) != 1) {
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
my $app = sub {
|
||||
my ($env) = @_;
|
||||
my $orig = $env->{QUERY_STRING};
|
||||
if ($env->{CONTENT_LENGTH} > 0) {
|
||||
$env->{'psgi.input'}->read($orig, $env->{CONTENT_LENGTH}, $env->{HTTP_UWSGI_OFFSET});
|
||||
}
|
||||
return [ 200, ['Content-Type' => 'text/plain'], [$orig."\n"]];
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
#uwsgi --http-socket :9090 --psgi apps/input_with_offset.pl
|
||||
|
||||
use IO::Socket::INET;
|
||||
|
||||
my @tests;
|
||||
|
||||
my $base = 'one_two_three_four';
|
||||
|
||||
push @tests, ['-1', 'HELLO', 'one_two_three_fouHELLO'];
|
||||
push @tests, ['-2', 'HELLO', 'one_two_three_foHELLO'];
|
||||
push @tests, ['-2', 'HELLOHELLOHELLOTEST2TEST3', 'one_two_three_foHELLOHELLOHELLOTEST2TEST3'];
|
||||
push @tests, ['-12', 'HELLOHELLOHELLOTEST2TEST3', 'one_twHELLOHELLOHELLOTEST2TEST3'];
|
||||
push @tests, ['-22', 'HELLOHELLOHELLOTEST2TEST3', "HELLOHELLOHELLOTEST2TEST3"];
|
||||
push @tests, ['-22', 'HELLO', "HELLOne_two_three_four"];
|
||||
push @tests, ['-23', 'HELLO', "HELLOone_two_three_four"];
|
||||
push @tests, ['-25', 'HELLO', "HELLO\0\0one_two_three_four"];
|
||||
push @tests, ['1', 'HELLO', "oHELLOo_three_four"];
|
||||
push @tests, ['3', 'HELLO', "oneHELLOthree_four"];
|
||||
push @tests, ['30', 'HELLO', "one_two_three_four\0\0\0\0\0\0\0\0\0\0\0\0HELLO"];
|
||||
|
||||
foreach(@tests) {
|
||||
print "testing: offset(".$_->[0].") body(".$_->[1].")\n";
|
||||
my $req = "POST /?".$base." HTTP/1.0\r\nContent-Length: ".length($_->[1])."\r\nuWSGI-Offset: ".$_->[0]."\r\n\r\n".$_->[1];
|
||||
|
||||
my $s = IO::Socket::INET->new(PeerAddr => $ARGV[0]);
|
||||
$s->send($req);
|
||||
|
||||
my $response = '';
|
||||
while(1) {
|
||||
$s->recv(my $buf, 4096);
|
||||
last unless length($buf);
|
||||
$response .= $buf;
|
||||
}
|
||||
$s->close;
|
||||
|
||||
my $expected = "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\n\r\n".$_->[2]."\n";
|
||||
if ($response ne $expected) {
|
||||
print "TEST FOR offset(".$_->[0].") body(".$_->[1].") FAILED:\nEXPECTED\n---\n".$expected."\n---\nGOT\n---\n".$response."\n---\n";
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
print "test result: SUCCESS\n";
|
||||
+1
-1
@@ -2,7 +2,7 @@ Gem::Specification.new do |s|
|
||||
s.name = 'uwsgi'
|
||||
s.license = 'GPL-2'
|
||||
s.version = `python -c "import uwsgiconfig as uc; print uc.uwsgi_version"`.sub(/-dev-.*/,'')
|
||||
s.date = '2013-12-30'
|
||||
s.date = '2014-02-09'
|
||||
s.summary = "uWSGI"
|
||||
s.description = "The uWSGI server for Ruby/Rack"
|
||||
s.authors = ["Unbit"]
|
||||
|
||||
@@ -602,6 +602,8 @@ struct uwsgi_daemon {
|
||||
char *legion;
|
||||
#endif
|
||||
|
||||
int ns_pid;
|
||||
int throttle;
|
||||
};
|
||||
|
||||
struct uwsgi_logger {
|
||||
@@ -696,12 +698,15 @@ struct uwsgi_legion {
|
||||
struct uwsgi_string_list *join_hooks;
|
||||
struct uwsgi_string_list *node_joined_hooks;
|
||||
struct uwsgi_string_list *node_left_hooks;
|
||||
|
||||
time_t suspended_til;
|
||||
struct uwsgi_legion *next;
|
||||
};
|
||||
|
||||
struct uwsgi_legion_action {
|
||||
char *name;
|
||||
int (*func) (struct uwsgi_legion *, char *);
|
||||
char *log_msg;
|
||||
struct uwsgi_legion_action *next;
|
||||
};
|
||||
#endif
|
||||
@@ -1656,6 +1661,15 @@ struct uwsgi_harakiri_options {
|
||||
int mules;
|
||||
};
|
||||
|
||||
struct uwsgi_fsmon {
|
||||
char *path;
|
||||
int fd;
|
||||
int id;
|
||||
void *data;
|
||||
void (*func)(struct uwsgi_fsmon *);
|
||||
struct uwsgi_fsmon *next;
|
||||
};
|
||||
|
||||
struct uwsgi_server {
|
||||
|
||||
// store the machine hostname
|
||||
@@ -2037,6 +2051,8 @@ struct uwsgi_server {
|
||||
|
||||
struct uwsgi_hook *hooks;
|
||||
|
||||
struct uwsgi_string_list *hook_touch;
|
||||
|
||||
struct uwsgi_string_list *hook_asap;
|
||||
struct uwsgi_string_list *hook_pre_jail;
|
||||
struct uwsgi_string_list *hook_post_jail;
|
||||
@@ -2051,6 +2067,9 @@ struct uwsgi_server {
|
||||
struct uwsgi_string_list *hook_accepting_once;
|
||||
struct uwsgi_string_list *hook_accepting1_once;
|
||||
|
||||
struct uwsgi_string_list *hook_emperor_start;
|
||||
struct uwsgi_string_list *hook_master_start;
|
||||
|
||||
struct uwsgi_string_list *hook_emperor_stop;
|
||||
struct uwsgi_string_list *hook_emperor_reload;
|
||||
struct uwsgi_string_list *hook_emperor_lost;
|
||||
@@ -2058,6 +2077,7 @@ struct uwsgi_server {
|
||||
struct uwsgi_string_list *hook_as_vassal;
|
||||
struct uwsgi_string_list *hook_as_emperor;
|
||||
struct uwsgi_string_list *hook_as_mule;
|
||||
struct uwsgi_string_list *hook_as_gateway;
|
||||
|
||||
|
||||
struct uwsgi_string_list *exec_asap;
|
||||
@@ -2147,6 +2167,7 @@ struct uwsgi_server {
|
||||
struct uwsgi_alarm_fd *alarm_fds;
|
||||
struct uwsgi_string_list *alarm_fd_list;
|
||||
struct uwsgi_string_list *alarm_segfault;
|
||||
struct uwsgi_string_list *alarm_backlog;
|
||||
struct uwsgi_alarm *alarms;
|
||||
struct uwsgi_alarm_instance *alarm_instances;
|
||||
struct uwsgi_alarm_log *alarm_logs;
|
||||
@@ -2166,6 +2187,7 @@ struct uwsgi_server {
|
||||
char *subscriptions_sign_check_dir;
|
||||
int subscriptions_sign_check_tolerance;
|
||||
const EVP_MD *subscriptions_sign_check_md;
|
||||
struct uwsgi_string_list *subscriptions_sign_skip_uid;
|
||||
#endif
|
||||
|
||||
struct uwsgi_string_list *subscriptions_credentials_check_dir;
|
||||
@@ -2279,6 +2301,8 @@ struct uwsgi_server {
|
||||
struct uwsgi_string_list *fs_brutal_reload;
|
||||
struct uwsgi_string_list *fs_signal;
|
||||
|
||||
struct uwsgi_fsmon *fsmon;
|
||||
|
||||
struct uwsgi_string_list *signal_timers;
|
||||
struct uwsgi_string_list *rb_signal_timers;
|
||||
|
||||
@@ -2308,6 +2332,7 @@ struct uwsgi_server {
|
||||
int spooler_max_tasks;
|
||||
int spooler_ordered;
|
||||
int spooler_quiet;
|
||||
int spooler_frequency;
|
||||
|
||||
int snmp;
|
||||
char *snmp_addr;
|
||||
@@ -2512,6 +2537,8 @@ struct uwsgi_server {
|
||||
void (*gbcw_hook) (void);
|
||||
|
||||
int close_on_exec;
|
||||
int close_on_exec2;
|
||||
|
||||
int tcp_nodelay;
|
||||
|
||||
char *loop;
|
||||
@@ -2603,6 +2630,7 @@ struct uwsgi_server {
|
||||
char *ssl_sessions_use_cache;
|
||||
int ssl_sessions_timeout;
|
||||
struct uwsgi_cache *ssl_sessions_cache;
|
||||
char *ssl_tmp_dir;
|
||||
#ifdef UWSGI_PCRE
|
||||
struct uwsgi_regexp_list *sni_regexp;
|
||||
#endif
|
||||
@@ -2620,6 +2648,7 @@ struct uwsgi_server {
|
||||
int legion_skew_tolerance;
|
||||
uint16_t legion_scroll_max_size;
|
||||
uint64_t legion_scroll_list_max_size;
|
||||
int legion_death_on_lord_error;
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
@@ -2658,6 +2687,14 @@ struct uwsgi_server {
|
||||
|
||||
struct uwsgi_string_list *schemes;
|
||||
|
||||
// inject text files (useful for advanced templating)
|
||||
struct uwsgi_string_list *inject_before;
|
||||
struct uwsgi_string_list *inject_after;
|
||||
|
||||
// this is a unix socket receiving external notifications (like subscription replies)
|
||||
char *notify_socket;
|
||||
int notify_socket_fd;
|
||||
char *subscription_notify_socket;
|
||||
};
|
||||
|
||||
struct uwsgi_rpc {
|
||||
@@ -2953,7 +2990,7 @@ void snmp_init(void);
|
||||
|
||||
void uwsgi_master_manage_snmp(int);
|
||||
|
||||
int spool_request(struct uwsgi_spooler *uspool, char *, int, int, char *, int, char *, time_t, char *, size_t);
|
||||
char *uwsgi_spool_request(struct wsgi_request *, char *, size_t, char *, size_t);
|
||||
void spooler(struct uwsgi_spooler *);
|
||||
pid_t spooler_start(struct uwsgi_spooler *);
|
||||
|
||||
@@ -3238,6 +3275,9 @@ struct uwsgi_subscribe_req {
|
||||
pid_t pid;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
|
||||
char *notify;
|
||||
uint16_t notify_len;
|
||||
};
|
||||
|
||||
void uwsgi_nuclear_blast();
|
||||
@@ -3501,6 +3541,8 @@ struct uwsgi_subscribe_node {
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
|
||||
char notify[102];
|
||||
|
||||
struct uwsgi_subscribe_slot *slot;
|
||||
|
||||
struct uwsgi_subscribe_node *next;
|
||||
@@ -3552,6 +3594,7 @@ int uwsgi_read_response(int, struct uwsgi_header *, int, char **);
|
||||
char *uwsgi_simple_file_read(char *);
|
||||
|
||||
void uwsgi_send_subscription(char *, char *, size_t, uint8_t, uint8_t, uint8_t, char *, char *, char *, char *, char *);
|
||||
void uwsgi_send_subscription_from_fd(int, char *, char *, size_t, uint8_t, uint8_t, uint8_t, char *, char *, char *, char *, char *);
|
||||
|
||||
void uwsgi_subscribe(char *, uint8_t);
|
||||
void uwsgi_subscribe2(char *, uint8_t);
|
||||
@@ -3591,7 +3634,7 @@ void *uwsgi_calloc_shared(size_t);
|
||||
|
||||
struct uwsgi_spooler *uwsgi_new_spooler(char *);
|
||||
|
||||
struct uwsgi_spooler *uwsgi_get_spooler_by_name(char *);
|
||||
struct uwsgi_spooler *uwsgi_get_spooler_by_name(char *, size_t);
|
||||
|
||||
int uwsgi_zerg_attach(char *);
|
||||
|
||||
@@ -3646,6 +3689,7 @@ void uwsgi_opt_add_unique_legion_cron(char *, char *, void *);
|
||||
void uwsgi_opt_sni(char *, char *, void *);
|
||||
struct uwsgi_string_list *uwsgi_ssl_add_sni_item(char *, char *, char *, char *, char *);
|
||||
void uwsgi_ssl_del_sni_item(char *, uint16_t);
|
||||
char *uwsgi_write_pem_to_file(char *, char *, size_t, char *);
|
||||
#endif
|
||||
void uwsgi_opt_flock(char *, char *, void *);
|
||||
void uwsgi_opt_flock_wait(char *, char *, void *);
|
||||
@@ -3699,6 +3743,7 @@ void uwsgi_opt_logic(char *, char *, void *);
|
||||
int uwsgi_logic_opt_for(char *, char *);
|
||||
int uwsgi_logic_opt_for_glob(char *, char *);
|
||||
int uwsgi_logic_opt_for_times(char *, char *);
|
||||
int uwsgi_logic_opt_for_readline(char *, char *);
|
||||
int uwsgi_logic_opt_if_env(char *, char *);
|
||||
int uwsgi_logic_opt_if_not_env(char *, char *);
|
||||
int uwsgi_logic_opt_if_opt(char *, char *);
|
||||
@@ -4219,7 +4264,7 @@ void uwsgi_start_legions(void);
|
||||
int uwsgi_legion_announce(struct uwsgi_legion *);
|
||||
struct uwsgi_legion *uwsgi_legion_get_by_name(char *);
|
||||
struct uwsgi_legion_action *uwsgi_legion_action_get(char *);
|
||||
void uwsgi_legion_action_register(char *, int (*)(struct uwsgi_legion *, char *));
|
||||
struct uwsgi_legion_action *uwsgi_legion_action_register(char *, int (*)(struct uwsgi_legion *, char *));
|
||||
int uwsgi_legion_action_call(char *, struct uwsgi_legion *, struct uwsgi_string_list *);
|
||||
void uwsgi_legion_atexit(void);
|
||||
#endif
|
||||
@@ -4467,7 +4512,7 @@ int uwsgi_init(int, char **, char **);
|
||||
#endif
|
||||
|
||||
int uwsgi_master_check_cron_death(int);
|
||||
int uwsgi_register_fsmon(struct uwsgi_string_list *);
|
||||
struct uwsgi_fsmon *uwsgi_register_fsmon(char *, void (*)(struct uwsgi_fsmon *), void *data);
|
||||
int uwsgi_fsmon_event(int);
|
||||
void uwsgi_fsmon_setup();
|
||||
|
||||
@@ -4694,6 +4739,9 @@ int uwsgi_socket_passcred(int);
|
||||
void uwsgi_dump_worker(int, char *);
|
||||
mode_t uwsgi_mode_t(char *, int *);
|
||||
|
||||
int uwsgi_notify_socket_manage(int);
|
||||
int uwsgi_notify_msg(char *, char *, size_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
+47
-16
@@ -1,6 +1,6 @@
|
||||
# uWSGI build system
|
||||
|
||||
uwsgi_version = '2.0'
|
||||
uwsgi_version = '2.0.1'
|
||||
|
||||
import os
|
||||
import re
|
||||
@@ -244,7 +244,10 @@ def build_uwsgi(uc, print_only=False, gcll=None):
|
||||
ep = uc.get('embedded_plugins').split(',')
|
||||
epc = "-DUWSGI_DECLARE_EMBEDDED_PLUGINS=\""
|
||||
eplc = "-DUWSGI_LOAD_EMBEDDED_PLUGINS=\""
|
||||
for p in ep:
|
||||
for item in ep:
|
||||
# allow name=path syntax
|
||||
kv = item.split('=')
|
||||
p = kv[0]
|
||||
if p is None or p == 'None':
|
||||
continue
|
||||
p = p.strip()
|
||||
@@ -358,15 +361,25 @@ def build_uwsgi(uc, print_only=False, gcll=None):
|
||||
|
||||
if len(ep) > 0:
|
||||
push_print("*** uWSGI compiling embedded plugins ***")
|
||||
for p in ep:
|
||||
for item in ep:
|
||||
# allows name=path syntax
|
||||
kv = item.split('=')
|
||||
if len(kv) > 1:
|
||||
p = kv[1]
|
||||
p = p.strip()
|
||||
path = os.path.abspath(p)
|
||||
else:
|
||||
p = kv[0]
|
||||
p = p.strip()
|
||||
path = 'plugins/%s' % p
|
||||
|
||||
if p is None or p == 'None':
|
||||
continue
|
||||
p = p.strip()
|
||||
|
||||
if p == 'ugreen':
|
||||
if uwsgi_os == 'OpenBSD' or uwsgi_cpu[0:3] == 'arm' or uwsgi_os == 'Haiku' or uwsgi_os.startswith('CYGWIN') or (uwsgi_os == 'Darwin' and uwsgi_os_k.startswith('8')):
|
||||
continue
|
||||
path = 'plugins/%s' % p
|
||||
|
||||
path = path.rstrip('/')
|
||||
|
||||
if not os.path.isdir(path):
|
||||
@@ -493,9 +506,9 @@ def build_uwsgi(uc, print_only=False, gcll=None):
|
||||
bin_name = os.environ.get('UWSGI_BIN_NAME', uc.get('bin_name'))
|
||||
|
||||
if uc.embed_config:
|
||||
gcc_list.append(uc.embed_config)
|
||||
gcc_list.append("%s.o" % binarize(uc.embed_config))
|
||||
for ef in binary_list:
|
||||
gcc_list.append("build/%s" % ef)
|
||||
gcc_list.append("%s.o" % ef)
|
||||
|
||||
additional_sources = os.environ.get('UWSGI_ADDITIONAL_SOURCES')
|
||||
if not additional_sources:
|
||||
@@ -734,7 +747,7 @@ class uConf(object):
|
||||
if 'UWSGI_PROFILE_OVERRIDE' in os.environ:
|
||||
for item in os.environ['UWSGI_PROFILE_OVERRIDE'].split(';'):
|
||||
k,v = item.split('=', 2)
|
||||
uc.set(k, v)
|
||||
self.set(k, v)
|
||||
|
||||
if 'UWSGI_AS_LIB' in os.environ:
|
||||
self.set('as_shared_library', 'true')
|
||||
@@ -1041,13 +1054,16 @@ class uConf(object):
|
||||
if not self.embed_config:
|
||||
self.embed_config = self.get('embed_config')
|
||||
if self.embed_config:
|
||||
binary_link_cmd = "ld -r -b binary -o %s.o %s" % (self.embed_config, self.embed_config)
|
||||
binary_link_cmd = "ld -r -b binary -o %s.o %s" % (binarize(self.embed_config), self.embed_config)
|
||||
print(binary_link_cmd)
|
||||
os.system(binary_link_cmd)
|
||||
self.cflags.append("-DUWSGI_EMBED_CONFIG=_binary_%s_start" % self.embed_config.replace('.','_'))
|
||||
self.cflags.append("-DUWSGI_EMBED_CONFIG_END=_binary_%s_end" % self.embed_config.replace('.','_'))
|
||||
if self.get('embed_files'):
|
||||
for ef in self.get('embed_files').split(','):
|
||||
self.cflags.append("-DUWSGI_EMBED_CONFIG=_binary_%s_start" % binarize(self.embed_config))
|
||||
self.cflags.append("-DUWSGI_EMBED_CONFIG_END=_binary_%s_end" % binarize(self.embed_config))
|
||||
embed_files = os.environ.get('UWSGI_EMBED_FILES')
|
||||
if not embed_files:
|
||||
embed_files = self.get('embed_files')
|
||||
if embed_files:
|
||||
for ef in embed_files.split(','):
|
||||
ef_parts = ef.split('=')
|
||||
symbase = None
|
||||
if len(ef_parts) > 1:
|
||||
@@ -1057,7 +1073,7 @@ class uConf(object):
|
||||
for directory, directories, files in os.walk(ef):
|
||||
for f in files:
|
||||
fname = "%s/%s" % (directory, f)
|
||||
binary_link_cmd = "ld -r -b binary -o build/%s.o %s" % (binarize(fname), fname)
|
||||
binary_link_cmd = "ld -r -b binary -o %s.o %s" % (binarize(fname), fname)
|
||||
print(binary_link_cmd)
|
||||
os.system(binary_link_cmd)
|
||||
if symbase:
|
||||
@@ -1067,7 +1083,7 @@ class uConf(object):
|
||||
os.system(objcopy_cmd)
|
||||
binary_list.append(binarize(fname))
|
||||
else:
|
||||
binary_link_cmd = "ld -r -b binary -o build/%s.o %s" % (binarize(ef), ef)
|
||||
binary_link_cmd = "ld -r -b binary -o %s.o %s" % (binarize(ef), ef)
|
||||
print(binary_link_cmd)
|
||||
os.system(binary_link_cmd)
|
||||
binary_list.append(binarize(ef))
|
||||
@@ -1117,7 +1133,7 @@ class uConf(object):
|
||||
report['yaml'] = 'libyaml'
|
||||
|
||||
if self.get('json'):
|
||||
if self.get('json') == 'auto':
|
||||
if self.get('json') in ('auto', 'true'):
|
||||
jsonconf = spcall("pkg-config --cflags jansson")
|
||||
if jsonconf:
|
||||
self.cflags.append(jsonconf)
|
||||
@@ -1139,6 +1155,9 @@ class uConf(object):
|
||||
self.libs.append(spcall("pkg-config --libs yajl"))
|
||||
self.cflags.append("-DUWSGI_JSON_YAJL")
|
||||
report['json'] = 'yajl'
|
||||
elif self.get('json') == 'true':
|
||||
print("*** jansson and yajl headers unavailable. uWSGI build is interrupted. You have to install jansson or yajl development headers or disable JSON")
|
||||
sys.exit(1)
|
||||
elif self.get('json') == 'jansson':
|
||||
jsonconf = spcall("pkg-config --cflags jansson")
|
||||
if jsonconf:
|
||||
@@ -1164,6 +1183,18 @@ class uConf(object):
|
||||
self.libs.append(spcall("pkg-config --libs yajl"))
|
||||
self.cflags.append("-DUWSGI_JSON_YAJL")
|
||||
report['json'] = 'yajl'
|
||||
elif self.has_include('yajl/yajl_tree.h'):
|
||||
self.cflags.append("-DUWSGI_JSON")
|
||||
self.gcc_list.append('core/json')
|
||||
self.libs.append('-lyajl')
|
||||
self.cflags.append("-DUWSGI_JSON_YAJL")
|
||||
report['json'] = 'yajl'
|
||||
elif self.has_include('yajl/yajl_parse.h'):
|
||||
self.cflags.append("-DUWSGI_JSON")
|
||||
self.gcc_list.append('core/json')
|
||||
self.libs.append('-lyajl')
|
||||
self.cflags.append("-DUWSGI_JSON_YAJL_OLD")
|
||||
report['json'] = 'yajl_old'
|
||||
else:
|
||||
print("*** yajl headers unavailable. uWSGI build is interrupted. You have to install yajl development package or use jansson or disable JSON")
|
||||
sys.exit(1)
|
||||
|
||||
Reference in New Issue
Block a user